2024-01-10 14:08:15 +01:00
use rocket ::{
get ,
request ::FlashMessage ,
response ::{ Flash , Redirect } ,
routes , Route , State ,
} ;
use rocket_dyn_templates ::Template ;
use sqlx ::SqlitePool ;
use tera ::Context ;
use crate ::model ::{
log ::Log ,
tripdetails ::TripDetails ,
triptype ::TripType ,
user ::{ AllowedForPlannedTripsUser , User , UserWithRoles } ,
usertrip ::{ UserTrip , UserTripDeleteError , UserTripError } ,
} ;
#[ get( " / " ) ]
async fn index (
db : & State < SqlitePool > ,
user : AllowedForPlannedTripsUser ,
flash : Option < FlashMessage < '_ > > ,
) -> Template {
let user : User = user . into ( ) ;
let mut context = Context ::new ( ) ;
if user . has_role ( db , " cox " ) . await | | user . has_role ( db , " admin " ) . await {
let triptypes = TripType ::all ( db ) . await ;
context . insert ( " trip_types " , & triptypes ) ;
}
let days = user . get_days ( db ) . await ;
if let Some ( msg ) = flash {
context . insert ( " flash " , & msg . into_inner ( ) ) ;
}
2024-01-10 14:24:58 +01:00
context . insert ( " loggedin_user " , & UserWithRoles ::from_user ( user , db ) . await ) ;
2024-01-10 14:08:15 +01:00
context . insert ( " days " , & days ) ;
Template ::render ( " planned " , context . into_json ( ) )
}
#[ get( " /join/<trip_details_id>?<user_note> " ) ]
async fn join (
db : & State < SqlitePool > ,
trip_details_id : i64 ,
user : AllowedForPlannedTripsUser ,
user_note : Option < String > ,
) -> Flash < Redirect > {
let user : User = user . into ( ) ;
let Some ( trip_details ) = TripDetails ::find_by_id ( db , trip_details_id ) . await else {
return Flash ::error ( Redirect ::to ( " / " ) , " Trip_details do not exist. " ) ;
} ;
match UserTrip ::create ( db , & user , & trip_details , user_note ) . await {
Ok ( _ ) = > {
Log ::create (
db ,
format! (
" User {} registered for trip_details.id={} " ,
user . name , trip_details_id
) ,
)
. await ;
2024-01-10 15:10:05 +01:00
Flash ::success ( Redirect ::to ( " /planned " ) , " Erfolgreich angemeldet! " )
2024-01-10 14:08:15 +01:00
}
Err ( UserTripError ::EventAlreadyFull ) = > {
2024-01-10 15:10:05 +01:00
Flash ::error ( Redirect ::to ( " /planned " ) , " Event bereits ausgebucht! " )
2024-01-10 14:08:15 +01:00
}
Err ( UserTripError ::AlreadyRegistered ) = > {
2024-01-10 15:10:05 +01:00
Flash ::error ( Redirect ::to ( " /planned " ) , " Du nimmst bereits teil! " )
2024-01-10 14:08:15 +01:00
}
Err ( UserTripError ::AlreadyRegisteredAsCox ) = > {
2024-01-10 15:10:05 +01:00
Flash ::error ( Redirect ::to ( " /planned " ) , " Du hilfst bereits als Steuerperson aus! " )
2024-01-10 14:08:15 +01:00
}
Err ( UserTripError ::CantRegisterAtOwnEvent ) = > Flash ::error (
2024-01-10 15:10:05 +01:00
Redirect ::to ( " /planned " ) ,
2024-01-10 14:08:15 +01:00
" Du kannst bei einer selbst ausgeschriebenen Fahrt nicht mitrudern ;) " ,
) ,
Err ( UserTripError ::GuestNotAllowedForThisEvent ) = > Flash ::error (
2024-01-10 15:10:05 +01:00
Redirect ::to ( " /planned " ) ,
2024-01-10 14:08:15 +01:00
" Bei dieser Ausfahrt können leider keine Gäste mitfahren. " ,
) ,
Err ( UserTripError ::NotAllowedToAddGuest ) = > Flash ::error (
2024-01-10 15:10:05 +01:00
Redirect ::to ( " /planned " ) ,
2024-01-10 14:08:15 +01:00
" Du darfst keine Gäste hinzufügen. " ,
) ,
Err ( UserTripError ::DetailsLocked ) = > Flash ::error (
2024-01-10 15:10:05 +01:00
Redirect ::to ( " /planned " ) ,
2024-01-10 14:08:15 +01:00
" Das Boot ist bereits eingeteilt. Bitte kontaktiere den Schiffsführer (Nummern siehe Signalgruppe) falls du dich doch abmelden willst. " ,
) ,
}
}
#[ get( " /remove/<trip_details_id>/<name> " ) ]
async fn remove_guest (
db : & State < SqlitePool > ,
trip_details_id : i64 ,
user : AllowedForPlannedTripsUser ,
name : String ,
) -> Flash < Redirect > {
let user : User = user . into ( ) ;
let Some ( trip_details ) = TripDetails ::find_by_id ( db , trip_details_id ) . await else {
2024-01-10 15:10:05 +01:00
return Flash ::error ( Redirect ::to ( " /planned " ) , " TripDetailsId does not exist " ) ;
2024-01-10 14:08:15 +01:00
} ;
match UserTrip ::delete ( db , & user , & trip_details , Some ( name ) ) . await {
Ok ( _ ) = > {
Log ::create (
db ,
format! (
" User {} unregistered for trip_details.id={} " ,
user . name , trip_details_id
) ,
)
. await ;
2024-01-10 15:10:05 +01:00
Flash ::success ( Redirect ::to ( " /planned " ) , " Erfolgreich abgemeldet! " )
2024-01-10 14:08:15 +01:00
}
Err ( UserTripDeleteError ::DetailsLocked ) = > {
Log ::create (
db ,
format! (
" User {} tried to unregister for locked trip_details.id={} " ,
user . name , trip_details_id
) ,
)
. await ;
2024-01-10 15:10:05 +01:00
Flash ::error ( Redirect ::to ( " /planned " ) , " Das Boot ist bereits eingeteilt. Bitte kontaktiere den Schiffsführer (Nummern siehe Signalgruppe) falls du dich doch abmelden willst. " )
2024-01-10 14:08:15 +01:00
}
Err ( UserTripDeleteError ::GuestNotParticipating ) = > {
2024-01-10 15:10:05 +01:00
Flash ::error ( Redirect ::to ( " /planned " ) , " Gast nicht angemeldet. " )
2024-01-10 14:08:15 +01:00
}
Err ( UserTripDeleteError ::NotAllowedToDeleteGuest ) = > Flash ::error (
2024-01-10 15:10:05 +01:00
Redirect ::to ( " /planned " ) ,
2024-01-10 14:08:15 +01:00
" Keine Berechtigung um den Gast zu entfernen. " ,
) ,
}
}
#[ get( " /remove/<trip_details_id> " ) ]
async fn remove (
db : & State < SqlitePool > ,
trip_details_id : i64 ,
user : AllowedForPlannedTripsUser ,
) -> Flash < Redirect > {
let user : User = user . into ( ) ;
let Some ( trip_details ) = TripDetails ::find_by_id ( db , trip_details_id ) . await else {
2024-01-10 15:10:05 +01:00
return Flash ::error ( Redirect ::to ( " /planned " ) , " TripDetailsId does not exist " ) ;
2024-01-10 14:08:15 +01:00
} ;
match UserTrip ::delete ( db , & user , & trip_details , None ) . await {
Ok ( _ ) = > {
Log ::create (
db ,
format! (
" User {} unregistered for trip_details.id={} " ,
user . name , trip_details_id
) ,
)
. await ;
2024-01-10 15:10:05 +01:00
Flash ::success ( Redirect ::to ( " /planned " ) , " Erfolgreich abgemeldet! " )
2024-01-10 14:08:15 +01:00
}
Err ( UserTripDeleteError ::DetailsLocked ) = > {
Log ::create (
db ,
format! (
" User {} tried to unregister for locked trip_details.id={} " ,
user . name , trip_details_id
) ,
)
. await ;
2024-01-10 15:10:05 +01:00
Flash ::error ( Redirect ::to ( " /planned " ) , " Das Boot ist bereits eingeteilt. Bitte kontaktiere den Schiffsführer (Nummern siehe Signalgruppe) falls du dich doch abmelden willst. " )
2024-01-10 14:08:15 +01:00
}
Err ( _ ) = > {
panic! ( " Not possible to be here " ) ;
}
}
}
pub fn routes ( ) -> Vec < Route > {
routes! [ index , join , remove , remove_guest ]
}
#[ cfg(test) ]
mod test {
use rocket ::{
http ::{ ContentType , Status } ,
local ::asynchronous ::Client ,
} ;
use sqlx ::SqlitePool ;
use crate ::testdb ;
#[ sqlx::test ]
fn test_join_and_remove ( ) {
let db = testdb! ( ) ;
let rocket = rocket ::build ( ) . manage ( db . clone ( ) ) ;
let rocket = crate ::tera ::config ( rocket ) ;
let client = Client ::tracked ( rocket ) . await . unwrap ( ) ;
let login = client
. post ( " /auth " )
. header ( ContentType ::Form ) // Set the content type to form
. body ( " name=rower&password=rower " ) ; // Add the form data to the request body;
login . dispatch ( ) . await ;
let req = client . get ( " /planned/join/1 " ) ;
let response = req . dispatch ( ) . await ;
assert_eq! ( response . status ( ) , Status ::SeeOther ) ;
2024-01-10 15:11:35 +01:00
assert_eq! ( response . headers ( ) . get ( " Location " ) . next ( ) , Some ( " /planned " ) ) ;
2024-01-10 14:08:15 +01:00
let flash_cookie = response
. cookies ( )
. get ( " _flash " )
. expect ( " Expected flash cookie " ) ;
assert_eq! ( flash_cookie . value ( ) , " 7:successErfolgreich angemeldet! " ) ;
let req = client . get ( " /planned/remove/1 " ) ;
let response = req . dispatch ( ) . await ;
assert_eq! ( response . status ( ) , Status ::SeeOther ) ;
2024-01-10 15:49:57 +01:00
assert_eq! ( response . headers ( ) . get ( " Location " ) . next ( ) , Some ( " /planned " ) ) ;
2024-01-10 14:08:15 +01:00
let flash_cookie = response
. cookies ( )
. get ( " _flash " )
. expect ( " Expected flash cookie " ) ;
assert_eq! ( flash_cookie . value ( ) , " 7:successErfolgreich abgemeldet! " ) ;
}
#[ sqlx::test ]
fn test_join_invalid_event ( ) {
let db = testdb! ( ) ;
let rocket = rocket ::build ( ) . manage ( db . clone ( ) ) ;
let rocket = crate ::tera ::config ( rocket ) ;
let client = Client ::tracked ( rocket ) . await . unwrap ( ) ;
let login = client
. post ( " /auth " )
. header ( ContentType ::Form ) // Set the content type to form
. body ( " name=rower&password=rower " ) ; // Add the form data to the request body;
login . dispatch ( ) . await ;
let req = client . get ( " /planned/join/9999 " ) ;
let response = req . dispatch ( ) . await ;
assert_eq! ( response . status ( ) , Status ::SeeOther ) ;
assert_eq! ( response . headers ( ) . get ( " Location " ) . next ( ) , Some ( " / " ) ) ;
let flash_cookie = response
. cookies ( )
. get ( " _flash " )
. expect ( " Expected flash cookie " ) ;
assert_eq! ( flash_cookie . value ( ) , " 5:errorTrip_details do not exist. " ) ;
}
}