use rocket::{ form::Form, response::{Flash, Redirect}, Route, State, }; use sea_orm::{ActiveModelTrait, ColumnTrait, DatabaseConnection, EntityTrait, QueryFilter, Set}; use crate::models::{day, trip, user}; use super::NaiveDateForm; #[derive(FromForm)] struct RegisterForm { day: NaiveDateForm, #[field(validate = len(3..))] name: String, time: Option, cox_id: Option, } #[put("/", data = "")] async fn register( db: &State, register: Form, user: user::Model, ) -> Flash { let day = day::Entity::find_by_id(*register.day) .one(db.inner()) .await .unwrap() .expect("There's no trip on this date (yet)"); if register.cox_id.is_none() && !day.open_registration { log::error!("{} tried to register, even though the user it should not be possible to do so via UI -> manually crafted request?", user.name); return Flash::error( Redirect::to("/"), "Don't (try to ;)) abuse this system! Incident has been reported...", ); } if let Some(cox_id) = register.cox_id { let trip = trip::Entity::find_by_id(cox_id) .one(db.inner()) .await .unwrap() .unwrap(); if trip.user_id == user.id { log::warn!( "{} tried to register for his own trip ({})", user.name, trip.id ); return Flash::error( Redirect::to("/"), "Du kannst an deinen eigenen Ausfahrten nicht teilnehmen...", ); } } let user = user::Model::find_or_create_user(®ister.name, db.inner()).await; let day = format!("{}", day.day.format("%Y-%m-%d")); let trip = trip::ActiveModel { day: Set(day.clone()), user_id: Set(user.id), begin: Set(register.time.clone()), cox_id: Set(register.cox_id.clone()), ..Default::default() }; match trip.insert(db.inner()).await { Ok(_) => { log::info!("{} registered for {:?}", user.name, day); Flash::success(Redirect::to("/"), "Erfolgreich angemeldet!") } Err(_) => { log::warn!( "{} tried to register for {:?}, but is already registered", user.name, day ); Flash::error(Redirect::to("/"), "Du bist bereits angemeldet") } } } #[derive(FromForm)] struct DeleteForm { id: i32, } #[delete("/", data = "")] async fn delete( db: &State, delete: Form, user: user::Model, ) -> Flash { let trip = trip::Entity::find_by_id(delete.id) .one(db.inner()) .await .unwrap(); match trip { None => { log::error!("Tried to delete registration of non-existing trip (prob. hand crafted request (user.name = {})", user.name); return Flash::error(Redirect::to("/"), "Du bist gar nicht angemeldet!"); } Some(trip) => { if trip.user_id != user.id { log::error!( "{} tried to delete a registration from user_id {} (probably hand-crafted request)", user.name, delete.id ); return Flash::error( Redirect::to("/"), "Du kannst nur deine eigenen Anmeldungen löschen!", ); } log::info!("User {} deleted the registration for {:?}", user.name, trip); trip::Entity::delete(trip::ActiveModel { id: Set(trip.id), ..Default::default() }) .exec(db.inner()) .await .unwrap(); } } Flash::success(Redirect::to("/"), "Abmeldung erfolgreich") } pub fn routes() -> Vec { routes![register, delete] }