forked from Ruderverein-Donau-Linz/rowt
		
	final touches
This commit is contained in:
		
							
								
								
									
										21
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										21
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							@@ -1185,6 +1185,15 @@ dependencies = [
 | 
			
		||||
 "wasm-bindgen",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "keccak"
 | 
			
		||||
version = "0.1.3"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "3afef3b6eff9ce9d8ff9b3601125eec7f0c8cbac7abd14f355d053fa56c98768"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "cpufeatures",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "kernel32-sys"
 | 
			
		||||
version = "0.2.2"
 | 
			
		||||
@@ -2071,11 +2080,13 @@ name = "rot"
 | 
			
		||||
version = "0.1.0"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "chrono",
 | 
			
		||||
 "hex",
 | 
			
		||||
 "rocket",
 | 
			
		||||
 "rocket_dyn_templates",
 | 
			
		||||
 "sea-orm",
 | 
			
		||||
 "sea-orm-migration",
 | 
			
		||||
 "serde",
 | 
			
		||||
 "sha3",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
@@ -2377,6 +2388,16 @@ dependencies = [
 | 
			
		||||
 "digest",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "sha3"
 | 
			
		||||
version = "0.10.6"
 | 
			
		||||
source = "registry+https://github.com/rust-lang/crates.io-index"
 | 
			
		||||
checksum = "bdf0c33fae925bdc080598b84bc15c55e7b9a4a43b3c704da051f977469691c9"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "digest",
 | 
			
		||||
 "keccak",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "sharded-slab"
 | 
			
		||||
version = "0.1.4"
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,8 @@ edition = "2021"
 | 
			
		||||
sea-orm = { version = "^0", features = [ "sqlx-sqlite", "runtime-tokio-rustls", "macros" ] }
 | 
			
		||||
sea-orm-migration = { version = "0.11", features = [ "runtime-tokio-rustls", "sqlx-sqlite" ] }
 | 
			
		||||
serde = { version = "1.0", features = [ "derive" ]}
 | 
			
		||||
rocket = "0.5.0-rc.2"
 | 
			
		||||
rocket = { version = "0.5.0-rc.2", features = ["secrets"]}
 | 
			
		||||
rocket_dyn_templates = { version = "0.1.0-rc.2", features= ["tera"] }
 | 
			
		||||
chrono =  { version = "0.4", features = ["serde"]}
 | 
			
		||||
 | 
			
		||||
sha3 = "0.10"
 | 
			
		||||
hex = "0.4"
 | 
			
		||||
 
 | 
			
		||||
@@ -19,6 +19,7 @@ impl MigrationTrait for Migration {
 | 
			
		||||
                            .primary_key(),
 | 
			
		||||
                    )
 | 
			
		||||
                    .col(ColumnDef::new(User::Name).string().not_null().unique_key())
 | 
			
		||||
                    .col(ColumnDef::new(User::Pw).string())
 | 
			
		||||
                    .col(
 | 
			
		||||
                        ColumnDef::new(User::IsCox)
 | 
			
		||||
                            .boolean()
 | 
			
		||||
@@ -49,6 +50,7 @@ pub enum User {
 | 
			
		||||
    Table,
 | 
			
		||||
    Id,
 | 
			
		||||
    Name,
 | 
			
		||||
    Pw,
 | 
			
		||||
    IsCox,
 | 
			
		||||
    IsAdmin,
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
use sea_orm::{DatabaseConnection, ModelTrait};
 | 
			
		||||
use sea_orm::{ColumnTrait, DatabaseConnection, EntityTrait, QueryFilter};
 | 
			
		||||
use serde::Serialize;
 | 
			
		||||
 | 
			
		||||
use super::{day, trip, user};
 | 
			
		||||
@@ -10,16 +10,8 @@ pub struct TripWithUser {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl TripWithUser {
 | 
			
		||||
    async fn new(trip: trip::Model, db: &DatabaseConnection) -> Self {
 | 
			
		||||
        Self {
 | 
			
		||||
            trip: trip.clone(),
 | 
			
		||||
            user: trip
 | 
			
		||||
                .find_related(user::Entity)
 | 
			
		||||
                .one(db)
 | 
			
		||||
                .await
 | 
			
		||||
                .unwrap()
 | 
			
		||||
                .unwrap(),
 | 
			
		||||
        }
 | 
			
		||||
    fn new(trip: trip::Model, user: user::Model) -> Self {
 | 
			
		||||
        Self { trip, user }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -32,8 +24,17 @@ pub struct DayWithTrips {
 | 
			
		||||
impl DayWithTrips {
 | 
			
		||||
    pub async fn new(day: day::Model, db: &DatabaseConnection) -> Self {
 | 
			
		||||
        let mut trips = Vec::new();
 | 
			
		||||
        for trip in day.find_related(trip::Entity).all(db).await.unwrap() {
 | 
			
		||||
            trips.push(TripWithUser::new(trip, db).await);
 | 
			
		||||
 | 
			
		||||
        let trips_with_users: Vec<(trip::Model, Option<user::Model>)> = trip::Entity::find()
 | 
			
		||||
            .filter(trip::Column::Day.eq(day.day))
 | 
			
		||||
            .find_also_related(user::Entity)
 | 
			
		||||
            .all(db)
 | 
			
		||||
            .await
 | 
			
		||||
            .unwrap();
 | 
			
		||||
        println!("{:#?}", trips_with_users);
 | 
			
		||||
 | 
			
		||||
        for (trip, users) in trips_with_users {
 | 
			
		||||
            trips.push(TripWithUser::new(trip, users.unwrap()));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Self { day, trips }
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,7 @@ pub struct Model {
 | 
			
		||||
    #[sea_orm(primary_key)]
 | 
			
		||||
    pub id: i32,
 | 
			
		||||
    pub name: String,
 | 
			
		||||
    pub pw: Option<String>,
 | 
			
		||||
    pub is_cox: bool,
 | 
			
		||||
    pub is_admin: bool,
 | 
			
		||||
}
 | 
			
		||||
@@ -53,7 +54,7 @@ impl<'r> FromRequest<'r> for Model {
 | 
			
		||||
    type Error = UserError;
 | 
			
		||||
 | 
			
		||||
    async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, Self::Error> {
 | 
			
		||||
        match req.cookies().get("name") {
 | 
			
		||||
        match req.cookies().get_private("name") {
 | 
			
		||||
            Some(name) => {
 | 
			
		||||
                let db = req.guard::<&'r State<DatabaseConnection>>();
 | 
			
		||||
                let name = name.value();
 | 
			
		||||
@@ -70,7 +71,7 @@ impl<'r> FromRequest<'r> for AdminUser {
 | 
			
		||||
    type Error = UserError;
 | 
			
		||||
 | 
			
		||||
    async fn from_request(req: &'r Request<'_>) -> request::Outcome<Self, Self::Error> {
 | 
			
		||||
        match req.cookies().get("name") {
 | 
			
		||||
        match req.cookies().get_private("name") {
 | 
			
		||||
            Some(name) => {
 | 
			
		||||
                let db = req.guard::<&'r State<DatabaseConnection>>();
 | 
			
		||||
                let name = name.value();
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,7 @@ use rocket::{
 | 
			
		||||
};
 | 
			
		||||
use rocket_dyn_templates::{context, Template};
 | 
			
		||||
use sea_orm::{Database, DatabaseConnection};
 | 
			
		||||
use sha3::{Digest, Sha3_256};
 | 
			
		||||
 | 
			
		||||
use super::models::{all::DayWithTrips, day, user};
 | 
			
		||||
 | 
			
		||||
@@ -35,17 +36,18 @@ impl Deref for NaiveDateForm {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[get("/")]
 | 
			
		||||
async fn index(db: &State<DatabaseConnection>, user: user::Model) -> Template {
 | 
			
		||||
#[get("/?<all>")]
 | 
			
		||||
async fn index(db: &State<DatabaseConnection>, user: user::Model, all: Option<String>) -> Template {
 | 
			
		||||
    let mut data = Vec::new();
 | 
			
		||||
 | 
			
		||||
    let mut show_next_n_days = 6;
 | 
			
		||||
    if user.is_cox {
 | 
			
		||||
        let end_of_year = NaiveDate::from_ymd_opt(Local::now().year(), 5, 31).unwrap();
 | 
			
		||||
        show_next_n_days = end_of_year
 | 
			
		||||
            .signed_duration_since(Local::now().date_naive())
 | 
			
		||||
            .num_days()
 | 
			
		||||
            + 1;
 | 
			
		||||
    if let Some(_) = all {
 | 
			
		||||
        if user.is_cox {
 | 
			
		||||
            let end_of_year = NaiveDate::from_ymd_opt(Local::now().year(), 12, 31).unwrap();
 | 
			
		||||
            show_next_n_days = end_of_year
 | 
			
		||||
                .signed_duration_since(Local::now().date_naive())
 | 
			
		||||
                .num_days();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for i in 0..show_next_n_days {
 | 
			
		||||
@@ -65,17 +67,45 @@ fn name() -> Template {
 | 
			
		||||
#[derive(FromForm)]
 | 
			
		||||
struct NameForm {
 | 
			
		||||
    name: String,
 | 
			
		||||
    pw: Option<String>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[put("/name", data = "<name>")]
 | 
			
		||||
fn savename(name: Form<NameForm>, cookies: &CookieJar) -> Redirect {
 | 
			
		||||
    cookies.add(Cookie::new("name", name.name.clone()));
 | 
			
		||||
async fn savename(
 | 
			
		||||
    name: Form<NameForm>,
 | 
			
		||||
    cookies: &CookieJar<'_>,
 | 
			
		||||
    db: &State<DatabaseConnection>,
 | 
			
		||||
) -> Redirect {
 | 
			
		||||
    let user = user::Model::find_or_create_user(&name.name, db.inner()).await;
 | 
			
		||||
    match user.pw {
 | 
			
		||||
        Some(pw) => {
 | 
			
		||||
            match &name.pw {
 | 
			
		||||
                Some(entered_pw) => {
 | 
			
		||||
                    let mut hasher = Sha3_256::new();
 | 
			
		||||
                    hasher.update(entered_pw);
 | 
			
		||||
                    let entered_pw = hasher.finalize();
 | 
			
		||||
 | 
			
		||||
                    if hex::encode(entered_pw) == pw {
 | 
			
		||||
                        cookies.add_private(Cookie::new("name", name.name.clone()));
 | 
			
		||||
                    } else {
 | 
			
		||||
                        Redirect::to("/"); // Wrong PW
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                None => {
 | 
			
		||||
                    Redirect::to("/"); // No PW supplied
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        None => {
 | 
			
		||||
            cookies.add_private(Cookie::new("name", name.name.clone()));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    Redirect::to("/")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[get("/logout")]
 | 
			
		||||
fn logout(cookies: &CookieJar) -> Redirect {
 | 
			
		||||
    cookies.remove(Cookie::new("name", ""));
 | 
			
		||||
    cookies.remove_private(Cookie::new("name", ""));
 | 
			
		||||
    Redirect::to("/")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,9 @@
 | 
			
		||||
use rocket::{form::Form, response::Redirect, Route, State};
 | 
			
		||||
use rocket_dyn_templates::{context, Template};
 | 
			
		||||
use sea_orm::{ActiveModelTrait, DatabaseConnection, EntityTrait, Set};
 | 
			
		||||
use sha3::{Digest, Sha3_256};
 | 
			
		||||
 | 
			
		||||
use crate::models::{day, user};
 | 
			
		||||
 | 
			
		||||
use super::NaiveDateForm;
 | 
			
		||||
use crate::models::user;
 | 
			
		||||
 | 
			
		||||
#[get("/")]
 | 
			
		||||
async fn index(db: &State<DatabaseConnection>, user: user::AdminUser) -> Template {
 | 
			
		||||
@@ -15,6 +14,7 @@ async fn index(db: &State<DatabaseConnection>, user: user::AdminUser) -> Templat
 | 
			
		||||
 | 
			
		||||
#[derive(FromForm)]
 | 
			
		||||
struct UserEditForm {
 | 
			
		||||
    pw: Option<String>,
 | 
			
		||||
    is_cox: bool,
 | 
			
		||||
    is_admin: bool,
 | 
			
		||||
}
 | 
			
		||||
@@ -26,12 +26,22 @@ async fn update(
 | 
			
		||||
    data: Form<UserEditForm>,
 | 
			
		||||
    _user: user::AdminUser,
 | 
			
		||||
) -> Redirect {
 | 
			
		||||
    let new_user = user::ActiveModel {
 | 
			
		||||
    let mut new_user = user::ActiveModel {
 | 
			
		||||
        id: Set(id),
 | 
			
		||||
        is_cox: Set(data.is_cox),
 | 
			
		||||
        is_admin: Set(data.is_admin),
 | 
			
		||||
        ..Default::default()
 | 
			
		||||
    };
 | 
			
		||||
    if let Some(pw) = &data.pw {
 | 
			
		||||
        if pw != "" {
 | 
			
		||||
            let mut hasher = Sha3_256::new();
 | 
			
		||||
            hasher.update(pw);
 | 
			
		||||
            let entered_pw = hasher.finalize();
 | 
			
		||||
 | 
			
		||||
            let pw = hex::encode(entered_pw);
 | 
			
		||||
            new_user.pw = Set(Some(pw));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    new_user.update(db.inner()).await.unwrap();
 | 
			
		||||
 | 
			
		||||
    Redirect::to("/user")
 | 
			
		||||
 
 | 
			
		||||
@@ -83,5 +83,9 @@
 | 
			
		||||
{% endfor %}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
{% if user.is_cox %}
 | 
			
		||||
	<a class="button" href="/?all">Alle heurigen Ausfahrten anzeigen</a>
 | 
			
		||||
{% endif %}
 | 
			
		||||
 | 
			
		||||
{% endblock content %}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -3,8 +3,13 @@
 | 
			
		||||
 | 
			
		||||
<form action="/name" method="post">
 | 
			
		||||
	<input type="hidden" name="_method" value="put" />
 | 
			
		||||
 | 
			
		||||
	<label for="name">Bitte deinen Namen eingeben</label>
 | 
			
		||||
	<input type="text" id="name" name="name"/>
 | 
			
		||||
 | 
			
		||||
	<label for="pw">(Optional) Passwort eingeben</label>
 | 
			
		||||
	<input type="password" id="pw" name="pw"/>
 | 
			
		||||
 | 
			
		||||
	<input type="submit" value="Weiter"/>
 | 
			
		||||
</form>
 | 
			
		||||
{% endblock content %}
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,7 @@
 | 
			
		||||
  <thead>
 | 
			
		||||
    <tr>
 | 
			
		||||
      <th>Name</th>
 | 
			
		||||
      <th>Pw</th>
 | 
			
		||||
      <th>Cox</th>
 | 
			
		||||
      <th>Admin</th>
 | 
			
		||||
      <th>Action</th>
 | 
			
		||||
@@ -16,6 +17,12 @@
 | 
			
		||||
		<form action="/user/{{ user.id }}" method="post">
 | 
			
		||||
			<input type="hidden" name="_method" value="put" />
 | 
			
		||||
			<td>{{user.name}}</td>
 | 
			
		||||
			<td>
 | 
			
		||||
				{% if user.pw %}
 | 
			
		||||
				<input type="checkbox" checked disabled>
 | 
			
		||||
				{% endif %}
 | 
			
		||||
				<input type="password" name="pw" />
 | 
			
		||||
			</td>
 | 
			
		||||
			<td>
 | 
			
		||||
				<input type="checkbox" name="is_cox" {% if user.is_cox %} checked="true"{% endif %}
 | 
			
		||||
			</td>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user