From bb4dba7bc966a041eaa023cb3a6ba47649da3822 Mon Sep 17 00:00:00 2001 From: philipp Date: Sat, 29 Apr 2023 18:57:01 +0200 Subject: [PATCH] only allow guests to register for specific events; don't even show them the other trips --- migration.sql | 2 +- src/model/mod.rs | 17 +++++++++++++++++ src/model/planned_event.rs | 17 +++++++++-------- src/model/trip.rs | 7 ++++--- src/model/tripdetails.rs | 29 +++++++++++++++++++++++++---- src/model/user.rs | 2 +- src/model/usertrip.rs | 20 ++++++++++++++++++++ src/rest/admin/planned_event.rs | 10 ++-------- src/rest/cox.rs | 2 ++ src/rest/mod.rs | 12 +++++++++++- templates/forms/event.html.tera | 4 ++-- templates/forms/trip.html.tera | 3 ++- 12 files changed, 96 insertions(+), 29 deletions(-) diff --git a/migration.sql b/migration.sql index 6f74a40..aaa127a 100644 --- a/migration.sql +++ b/migration.sql @@ -21,6 +21,7 @@ CREATE TABLE IF NOT EXISTS "trip_details" ( "planned_starting_time" text NOT NULL, "max_people" INTEGER NOT NULL, "day" TEXT NOT NULL, + "allow_guests" boolean NOT NULL default false, "notes" TEXT, "trip_type_id" INTEGER, FOREIGN KEY(trip_type_id) REFERENCES trip_type(id) @@ -30,7 +31,6 @@ CREATE TABLE IF NOT EXISTS "planned_event" ( "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "name" text NOT NULL, "planned_amount_cox" INTEGER unsigned NOT NULL, - "allow_guests" boolean NOT NULL default false, "trip_details_id" INTEGER NOT NULL, "created_at" text NOT NULL DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY(trip_details_id) REFERENCES trip_details(id) ON DELETE CASCADE diff --git a/src/model/mod.rs b/src/model/mod.rs index 1029bf2..73be211 100644 --- a/src/model/mod.rs +++ b/src/model/mod.rs @@ -30,4 +30,21 @@ impl Day { trips: Trip::get_for_day(db, day).await, } } + pub async fn new_guest(db: &SqlitePool, day: NaiveDate) -> Self { + let mut day = Self::new(db, day).await; + + day.planned_events = day + .planned_events + .into_iter() + .filter(|e| e.planned_event.allow_guests) + .collect(); + + day.trips = day + .trips + .into_iter() + .filter(|t| t.trip.allow_guests) + .collect(); + + day + } } diff --git a/src/model/planned_event.rs b/src/model/planned_event.rs index 1012cc9..a776cd9 100644 --- a/src/model/planned_event.rs +++ b/src/model/planned_event.rs @@ -9,19 +9,19 @@ pub struct PlannedEvent { pub id: i64, name: String, planned_amount_cox: i64, - allow_guests: bool, trip_details_id: i64, planned_starting_time: String, max_people: i64, day: String, notes: Option, + pub allow_guests: bool, trip_type_id: Option, } #[derive(Serialize)] pub struct PlannedEventWithUserAndTriptype { #[serde(flatten)] - planned_event: PlannedEvent, + pub planned_event: PlannedEvent, trip_type: Option, cox_needed: bool, cox: Vec, @@ -42,7 +42,7 @@ impl PlannedEvent { Self, " SELECT - planned_event.id, planned_event.name, planned_amount_cox, allow_guests, trip_details_id, planned_starting_time, max_people, day, notes, trip_type_id + planned_event.id, planned_event.name, planned_amount_cox, trip_details_id, planned_starting_time, max_people, day, notes, allow_guests, trip_type_id FROM planned_event INNER JOIN trip_details ON planned_event.trip_details_id = trip_details.id WHERE planned_event.id like ? @@ -61,7 +61,7 @@ WHERE planned_event.id like ? let day = format!("{day}"); let events = sqlx::query_as!( PlannedEvent, - "SELECT planned_event.id, planned_event.name, planned_amount_cox, allow_guests, trip_details_id, planned_starting_time, max_people, day, notes, trip_type_id + "SELECT planned_event.id, planned_event.name, planned_amount_cox, trip_details_id, planned_starting_time, max_people, day, notes, allow_guests, trip_type_id FROM planned_event INNER JOIN trip_details ON planned_event.trip_details_id = trip_details.id WHERE day=?", @@ -127,12 +127,13 @@ FROM user_trip WHERE trip_details_id = (SELECT trip_details_id FROM planned_even db: &SqlitePool, name: String, planned_amount_cox: i32, - allow_guests: bool, trip_details: TripDetails, ) { sqlx::query!( - "INSERT INTO planned_event(name, planned_amount_cox, allow_guests, trip_details_id) VALUES(?, ?, ?, ?)", - name, planned_amount_cox, allow_guests, trip_details.id + "INSERT INTO planned_event(name, planned_amount_cox, trip_details_id) VALUES(?, ?, ?)", + name, + planned_amount_cox, + trip_details.id ) .execute(db) .await @@ -170,7 +171,7 @@ mod test { let trip_details = TripDetails::find_by_id(&pool, 1).await.unwrap(); - PlannedEvent::create(&pool, "new-event".into(), 2, false, trip_details).await; + PlannedEvent::create(&pool, "new-event".into(), 2, trip_details).await; let res = PlannedEvent::get_for_day(&pool, NaiveDate::from_ymd_opt(1970, 1, 1).unwrap()).await; diff --git a/src/model/trip.rs b/src/model/trip.rs index fb9d8b8..7d1f8fa 100644 --- a/src/model/trip.rs +++ b/src/model/trip.rs @@ -19,13 +19,14 @@ pub struct Trip { max_people: i64, day: String, notes: Option, + pub allow_guests: bool, trip_type_id: Option, } #[derive(Serialize)] pub struct TripWithUserAndType { #[serde(flatten)] - trip: Trip, + pub trip: Trip, rower: Vec, trip_type: Option, } @@ -47,7 +48,7 @@ impl Trip { sqlx::query_as!( Self, " -SELECT trip.id, cox_id, user.name as cox_name, trip_details_id, planned_starting_time, max_people, day, notes, trip_type_id +SELECT trip.id, cox_id, user.name as cox_name, trip_details_id, planned_starting_time, max_people, day, notes, allow_guests, trip_type_id FROM trip INNER JOIN trip_details ON trip.trip_details_id = trip_details.id INNER JOIN user ON trip.cox_id = user.id @@ -100,7 +101,7 @@ WHERE trip.id=? let trips = sqlx::query_as!( Trip, " -SELECT trip.id, cox_id, user.name as cox_name, trip_details_id, planned_starting_time, max_people, day, notes, trip_type_id +SELECT trip.id, cox_id, user.name as cox_name, trip_details_id, planned_starting_time, max_people, day, notes, allow_guests, trip_type_id FROM trip INNER JOIN trip_details ON trip.trip_details_id = trip_details.id INNER JOIN user ON trip.cox_id = user.id diff --git a/src/model/tripdetails.rs b/src/model/tripdetails.rs index fcdf28e..a834f90 100644 --- a/src/model/tripdetails.rs +++ b/src/model/tripdetails.rs @@ -8,6 +8,7 @@ pub struct TripDetails { max_people: i64, day: String, notes: Option, + pub allow_guests: bool, trip_type_id: Option, } @@ -16,7 +17,7 @@ impl TripDetails { sqlx::query_as!( TripDetails, " -SELECT id, planned_starting_time, max_people, day, notes, trip_type_id +SELECT id, planned_starting_time, max_people, day, notes, allow_guests, trip_type_id FROM trip_details WHERE id like ? ", @@ -34,14 +35,16 @@ WHERE id like ? max_people: i32, day: String, notes: Option, + allow_guests: bool, trip_type_id: Option, ) -> i64 { let query = sqlx::query!( - "INSERT INTO trip_details(planned_starting_time, max_people, day, notes, trip_type_id) VALUES(?, ?, ?, ?, ?)" , + "INSERT INTO trip_details(planned_starting_time, max_people, day, notes, allow_guests, trip_type_id) VALUES(?, ?, ?, ?, ?, ?)" , planned_starting_time, max_people, day, notes, + allow_guests, trip_type_id ) .execute(db) @@ -97,11 +100,29 @@ mod test { let pool = testdb!(); assert_eq!( - TripDetails::create(&pool, "10:00".into(), 2, "1970-01-01".into(), None, None).await, + TripDetails::create( + &pool, + "10:00".into(), + 2, + "1970-01-01".into(), + None, + false, + None + ) + .await, 3, ); assert_eq!( - TripDetails::create(&pool, "10:00".into(), 2, "1970-01-01".into(), None, None).await, + TripDetails::create( + &pool, + "10:00".into(), + 2, + "1970-01-01".into(), + None, + false, + None + ) + .await, 4, ); } diff --git a/src/model/user.rs b/src/model/user.rs index 767636b..c9d6a63 100644 --- a/src/model/user.rs +++ b/src/model/user.rs @@ -17,7 +17,7 @@ pub struct User { pw: Option, pub is_cox: bool, pub is_admin: bool, - is_guest: bool, + pub is_guest: bool, #[serde(default = "bool::default")] deleted: bool, } diff --git a/src/model/usertrip.rs b/src/model/usertrip.rs index 3a8e481..b8c4f47 100644 --- a/src/model/usertrip.rs +++ b/src/model/usertrip.rs @@ -14,6 +14,10 @@ impl UserTrip { return Err(UserTripError::EventAlreadyFull); } + if user.is_guest && !trip_details.allow_guests { + return Err(UserTripError::GuestNotAllowedForThisEvent); + } + //check if cox if own event let is_cox = sqlx::query!( "SELECT count(*) as amount @@ -80,6 +84,7 @@ pub enum UserTripError { AlreadyRegisteredAsCox, EventAlreadyFull, CantRegisterAtOwnEvent, + GuestNotAllowedForThisEvent, } #[cfg(test)] @@ -180,4 +185,19 @@ mod test { assert_eq!(result, UserTripError::AlreadyRegisteredAsCox); } + + #[sqlx::test] + fn test_fail_create_guest() { + let pool = testdb!(); + + let user = User::find_by_name(&pool, "guest".into()).await.unwrap(); + + let trip_details = TripDetails::find_by_id(&pool, 1).await.unwrap(); + + let result = UserTrip::create(&pool, &user, &trip_details) + .await + .expect_err("Not allowed for guests"); + + assert_eq!(result, UserTripError::GuestNotAllowedForThisEvent); + } } diff --git a/src/rest/admin/planned_event.rs b/src/rest/admin/planned_event.rs index ff0c30f..a5750df 100644 --- a/src/rest/admin/planned_event.rs +++ b/src/rest/admin/planned_event.rs @@ -34,6 +34,7 @@ async fn create( data.max_people, data.day.clone(), data.notes.clone(), + data.allow_guests, data.trip_type, ) .await; @@ -43,14 +44,7 @@ async fn create( //the object //TODO: fix clone() - PlannedEvent::create( - db, - data.name.clone(), - data.planned_amount_cox, - data.allow_guests, - trip_details, - ) - .await; + PlannedEvent::create(db, data.name.clone(), data.planned_amount_cox, trip_details).await; Flash::success(Redirect::to("/"), "Successfully planned the event") } diff --git a/src/rest/cox.rs b/src/rest/cox.rs index caeefda..ce49e5e 100644 --- a/src/rest/cox.rs +++ b/src/rest/cox.rs @@ -22,6 +22,7 @@ struct AddTripForm { max_people: i32, notes: Option, trip_type: Option, + allow_guests: bool, } #[post("/trip", data = "")] @@ -33,6 +34,7 @@ async fn create(db: &State, data: Form, cox: CoxUser) - data.max_people, data.day.clone(), data.notes.clone(), + data.allow_guests, data.trip_type, ) .await; diff --git a/src/rest/mod.rs b/src/rest/mod.rs index 327f848..d19eb3d 100644 --- a/src/rest/mod.rs +++ b/src/rest/mod.rs @@ -37,6 +37,7 @@ async fn index(db: &State, user: User, flash: Option, user: User, flash: Option, trip_details_id: i64, user: User) -> Flash Redirect::to("/"), "Du kannst bei einer selbst ausgeschriebenen Fahrt nicht mitrudern ;)", ), + Err(UserTripError::GuestNotAllowedForThisEvent) => Flash::error( + Redirect::to("/"), + "Bei dieser Ausfahrt können leider keine Gäste mitfahren.", + ), } } diff --git a/templates/forms/event.html.tera b/templates/forms/event.html.tera index 8c80a83..8905ad9 100644 --- a/templates/forms/event.html.tera +++ b/templates/forms/event.html.tera @@ -7,8 +7,8 @@ {{ macros::input(label='Startzeit', name='planned_starting_time', type='time', required=true) }} {{ macros::input(label='Anzahl Steuerleute', name='planned_amount_cox', type='number', required=true, min='0') }} {{ macros::input(label='Anzahl Ruderer (ohne Steuerperson)', name='max_people', type='number', required=true, min='0') }} - {{ macros::checkbox(label='Gäste erlauben', name='max_allow_guestspeople') }} + {{ macros::checkbox(label='Gäste erlauben', name='allow_guests') }} {{ macros::input(label='Anmerkungen', name='notes', type='input') }} - \ No newline at end of file + diff --git a/templates/forms/trip.html.tera b/templates/forms/trip.html.tera index ae6e1d2..7a65a22 100644 --- a/templates/forms/trip.html.tera +++ b/templates/forms/trip.html.tera @@ -5,7 +5,8 @@ {{ macros::input(label='Startzeit (zB "10:00")', name='planned_starting_time', type='time', required=true) }} {{ macros::input(label='Anzahl Ruderer (ohne Steuerperson)', name='max_people', type='number', required=true, min='0') }} + {{ macros::checkbox(label='Gäste erlauben', name='allow_guests') }} {{ macros::input(label='Anmerkungen', name='notes', type='input') }} - \ No newline at end of file +