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