use chrono::{Datelike, Duration, Local, NaiveDate}; use rocket::{ catch, catchers, fs::FileServer, get, request::FlashMessage, response::{Flash, Redirect}, routes, Build, Rocket, State, }; use rocket_dyn_templates::{tera::Context, Template}; use sqlx::SqlitePool; use crate::model::{ log::Log, tripdetails::TripDetails, triptype::TripType, user::User, usertrip::{UserTrip, UserTripError}, Day, }; mod admin; mod auth; mod cox; #[get("/")] async fn index(db: &State, user: User, flash: Option>) -> Template { let mut days = Vec::new(); let mut context = Context::new(); let mut show_next_n_days = 6; 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() + 1; } if user.is_cox || user.is_admin { let triptypes = TripType::all(db).await; context.insert("trip_types", &triptypes); } for i in 0..show_next_n_days { let date = (Local::now() + Duration::days(i)).date_naive(); days.push(Day::new(db, date).await); } if let Some(msg) = flash { context.insert("flash", &msg.into_inner()); } context.insert("loggedin_user", &user); context.insert("days", &days); Template::render("index", context.into_json()) } #[get("/join/")] async fn join(db: &State, trip_details_id: i64, user: User) -> Flash { let trip_details = match TripDetails::find_by_id(db, trip_details_id).await { Some(trip_details) => trip_details, None => return Flash::error(Redirect::to("/"), "Trip_details do not exist."), }; match UserTrip::create(db, &user, &trip_details).await { Ok(_) => { Log::create( db, format!( "User {} registered for trip_details.id={}", user.name, trip_details_id ), ) .await; Flash::success(Redirect::to("/"), "Erfolgreich angemeldet!") } Err(UserTripError::EventAlreadyFull) => { Flash::error(Redirect::to("/"), "Event bereits ausgebucht!") } Err(UserTripError::AlreadyRegistered) => { Flash::error(Redirect::to("/"), "Du nimmst bereits teil!") } Err(UserTripError::AlreadyRegisteredAsCox) => { Flash::error(Redirect::to("/"), "Du hilfst bereits als Steuerperson aus!") } Err(UserTripError::CantRegisterAtOwnEvent) => Flash::error( Redirect::to("/"), "Du kannst bei einer selbst ausgeschriebenen Fahrt nicht mitrudern ;)", ), } } #[get("/remove/")] async fn remove(db: &State, trip_details_id: i64, user: User) -> Flash { let trip_details = match TripDetails::find_by_id(db, trip_details_id).await { Some(trip_details) => trip_details, None => { return Flash::error(Redirect::to("/"), "TripDetailsId does not exist"); } }; UserTrip::delete(db, &user, &trip_details).await; Log::create( db, format!( "User {} unregistered for trip_details.id={}", user.name, trip_details_id ), ) .await; Flash::success(Redirect::to("/"), "Erfolgreich abgemeldet!") } #[catch(401)] //unauthorized fn unauthorized_error() -> Redirect { Redirect::to("/auth") } pub fn start(db: SqlitePool) -> Rocket { rocket::build() .manage(db) .mount("/", routes![index, join, remove]) .mount("/auth", auth::routes()) .mount("/cox", cox::routes()) .mount("/admin", admin::routes()) .mount("/public", FileServer::from("static/")) .register("/", catchers![unauthorized_error]) .attach(Template::fairing()) } //#[cfg(test)] //mod test { // use crate::testdb; // // use super::start; // use rocket::http::Status; // use rocket::local::asynchronous::Client; // use rocket::uri; // use sqlx::SqlitePool; // // #[sqlx::test] // fn test_not_logged_in() { // let pool = testdb!(); // // let client = Client::tracked(start(pool)) // .await // .expect("valid rocket instance"); // let response = client.get(uri!(super::index)).dispatch().await; // // assert_eq!(response.status(), Status::SeeOther); // let location = response.headers().get("Location").next().unwrap(); // assert_eq!(location, "/auth"); // } //}