use crate::{ model::{ activity::Activity, family::Family, log::Log, logbook::Logbook, mail::valid_mails, role::Role, user::{ AdminUser, AllowedToEditPaymentStatusUser, ManageUserUser, User, UserWithDetails, UserWithMembershipPdf, UserWithRolesAndMembershipPdf, VorstandUser, clubmember::ClubMemberUser, foerdernd::FoerderndUser, member::Member, regular::RegularUser, scheckbuch::ScheckbuchUser, schnupperant::SchnupperantUser, schnupperinterest::SchnupperInterestUser, unterstuetzend::UnterstuetzendUser, }, }, tera::Config, }; use chrono::NaiveDate; use futures::future::join_all; use rocket::{ FromForm, Request, Route, State, form::Form, fs::TempFile, get, http::{ContentType, Status}, post, request::{FlashMessage, FromRequest, Outcome}, response::{Flash, Redirect}, routes, }; use rocket_dyn_templates::{Template, tera::Context}; use sqlx::SqlitePool; // Custom request guard to extract the Referer header struct Referer(String); #[rocket::async_trait] impl<'r> FromRequest<'r> for Referer { type Error = (); async fn from_request(request: &'r Request<'_>) -> Outcome { match request.headers().get_one("Referer") { Some(referer) => Outcome::Success(Referer(referer.to_string())), None => Outcome::Error((Status::BadRequest, ())), } } } #[get("/user?&")] async fn index( db: &State, user: VorstandUser, flash: Option>, sort: Option, asc: bool, ) -> Template { let sort_column = sort.unwrap_or_else(|| "last_access".to_string()); let user_futures: Vec<_> = User::all_with_order(db, &sort_column, asc) .await .into_iter() .map(|u| async move { UserWithRolesAndMembershipPdf::from_user(db, u).await }) .collect(); let user: User = user.into_inner(); let allowed_to_edit = ManageUserUser::new(db, &user).await.is_some(); let users: Vec = join_all(user_futures).await; let financial = Role::all_cluster(db, "financial").await; let roles = Role::all(db).await; let families = Family::all_with_members(db).await; let mut context = Context::new(); if let Some(msg) = flash { context.insert("flash", &msg.into_inner()); } context.insert("allowed_to_edit", &allowed_to_edit); context.insert("users", &users); context.insert("roles", &roles); context.insert("financial", &financial); context.insert("families", &families); context.insert("loggedin_user", &UserWithDetails::from_user(user, db).await); Template::render("admin/user/index", context.into_json()) } #[get("/user", rank = 2)] async fn index_admin( db: &State, user: AdminUser, flash: Option>, ) -> Template { let user_futures: Vec<_> = User::all(db) .await .into_iter() .map(|u| async move { UserWithRolesAndMembershipPdf::from_user(db, u).await }) .collect(); let users: Vec = join_all(user_futures).await; let user: User = user.user; let financial = Role::all_cluster(db, "financial").await; let allowed_to_edit = ManageUserUser::new(db, &user).await.is_some(); let roles = Role::all(db).await; let families = Family::all_with_members(db).await; let mut context = Context::new(); if let Some(msg) = flash { context.insert("flash", &msg.into_inner()); } context.insert("allowed_to_edit", &allowed_to_edit); context.insert("users", &users); context.insert("roles", &roles); context.insert("financial", &financial); context.insert("families", &families); context.insert("loggedin_user", &UserWithDetails::from_user(user, db).await); Template::render("admin/user/index", context.into_json()) } #[get("/user/")] async fn view( db: &State, admin: VorstandUser, flash: Option>, user: i32, ) -> Result> { let Some(user) = User::find_by_id(db, user).await else { return Err(Flash::error( Redirect::to("/admin/user"), format!("User mit ID {} gibts ned", user), )); }; let member = Member::from(db, user.clone()).await; let fee = user.fee(db).await; let activities = Activity::for_user(db, &user).await; let financial = Role::all_cluster(db, "financial").await; let user_financial = user.financial(db).await; let skill = Role::all_cluster(db, "skill").await; let user_skill = user.skill(db).await; let user = UserWithRolesAndMembershipPdf::from_user(db, user).await; let admin: User = admin.into_inner(); let allowed_to_edit = ManageUserUser::new(db, &admin).await.is_some(); let roles = Role::all(db).await; let families = Family::all_with_members(db).await; let mut context = Context::new(); if let Some(msg) = flash { context.insert("flash", &msg.into_inner()); } context.insert("allowed_to_edit", &allowed_to_edit); context.insert("user", &user); context.insert("is_clubmember", &member.is_club_member()); context.insert("supposed_to_pay", &member.supposed_to_pay()); context.insert("fee", &fee); context.insert("skill", &skill); context.insert("user_skill", &user_skill); context.insert("financial", &financial); context.insert("user_financial", &user_financial); context.insert("member", &member); context.insert("activities", &activities); context.insert("roles", &roles); context.insert("families", &families); context.insert( "loggedin_user", &UserWithDetails::from_user(admin, db).await, ); Ok(Template::render("admin/user/view", context.into_json())) } #[get("/user/fees")] async fn fees( db: &State, user: VorstandUser, flash: Option>, ) -> Template { let mut context = Context::new(); let users = User::all_payer_groups(db).await; let mut fees = Vec::new(); for user in users { if let Some(fee) = user.fee(db).await { fees.push(fee); } } context.insert("fees", &fees); if let Some(msg) = flash { context.insert("flash", &msg.into_inner()); } context.insert( "loggedin_user", &UserWithDetails::from_user(user.into_inner(), db).await, ); Template::render("admin/user/fees", context.into_json()) } #[get("/user/scheckbuch")] async fn scheckbuch( db: &State, user: VorstandUser, flash: Option>, ) -> Template { let mut context = Context::new(); let scheckbooks = Role::find_by_name(db, "scheckbuch").await.unwrap(); let scheckbooks = User::all_with_role(db, &scheckbooks).await; let mut scheckbooks_with_roles = Vec::new(); for s in scheckbooks { scheckbooks_with_roles.push(( Logbook::completed_with_user(db, &s).await, UserWithDetails::from_user(s, db).await, )) } context.insert("scheckbooks", &scheckbooks_with_roles); if let Some(msg) = flash { context.insert("flash", &msg.into_inner()); } context.insert( "loggedin_user", &UserWithDetails::from_user(user.into_inner(), db).await, ); Template::render("admin/user/scheckbuch", context.into_json()) } #[get("/user/fees/paid?")] async fn fees_paid( db: &State, calling_user: AllowedToEditPaymentStatusUser, user_ids: Vec, referer: Referer, ) -> Flash { let mut res = String::new(); for user_id in user_ids { let user = User::find_by_id(db, user_id).await.unwrap(); res.push_str(&format!("{} + ", user.name)); if user.has_role(db, "paid").await { user.has_not_paid(db, &calling_user).await; } else { user.has_paid(db, &calling_user).await; } } res.truncate(res.len() - 3); // remove ' + ' from the end Flash::success( Redirect::to(referer.0), format!("Zahlungsstatus von {} erfolgreich geändert", res), ) } #[get("/user//reset-pw")] async fn resetpw(db: &State, admin: ManageUserUser, user: i32) -> Flash { let user = User::find_by_id(db, user).await; match user { Some(user) => { Log::create( db, format!("{} has resetted the pw for {}", admin.user.name, user.name), ) .await; user.reset_pw(db).await; Flash::success( Redirect::to("/admin/user"), format!("Passwort von {} zurückgesetzt", user.name), ) } None => Flash::error(Redirect::to("/admin/user"), "User does not exist"), } } #[get("/user//delete")] async fn delete(db: &State, admin: ManageUserUser, user: i32) -> Flash { let user = User::find_by_id(db, user).await; Log::create(db, format!("{} deleted user: {user:?}", admin.user.name)).await; match user { Some(user) => { user.delete(db, &admin).await; Flash::success( Redirect::to("/admin/user"), format!("Benutzer {} gelöscht", user.name), ) } None => Flash::error(Redirect::to("/admin/user"), "User does not exist"), } } #[derive(FromForm, Debug)] pub struct MailUpdateForm { mail: String, } #[post("/user//change-mail", data = "")] async fn update_mail( db: &State, data: Form, admin: ManageUserUser, id: i32, ) -> Flash { let Some(user) = User::find_by_id(db, id).await else { return Flash::error( Redirect::to("/admin/user"), format!("User with ID {} does not exist!", id), ); }; match user.update_mail(db, &admin, &data.mail).await { Ok(_) => Flash::success( Redirect::to(format!("/admin/user/{}", user.id)), "Mailadresse erfolgreich geändert", ), Err(e) => Flash::error(Redirect::to(format!("/admin/user/{}", user.id)), e), } } #[derive(FromForm, Debug)] pub struct AddNoteForm { note: String, } #[post("/user//new-note", data = "")] async fn add_note( db: &State, data: Form, admin: ManageUserUser, id: i32, ) -> Flash { let Some(user) = User::find_by_id(db, id).await else { return Flash::error( Redirect::to("/admin/user"), format!("User with ID {} does not exist!", id), ); }; match user.add_note(db, &admin, &user, &data.note).await { Ok(_) => Flash::success( Redirect::to(format!("/admin/user/{}", user.id)), "Notiz hinzugefügt", ), Err(e) => Flash::error(Redirect::to(format!("/admin/user/{}", user.id)), e), } } #[derive(FromForm, Debug)] pub struct PhoneUpdateForm { phone: String, } #[post("/user//change-phone", data = "")] async fn update_phone( db: &State, data: Form, admin: ManageUserUser, id: i32, ) -> Flash { let Some(user) = User::find_by_id(db, id).await else { return Flash::error( Redirect::to("/admin/user"), format!("User with ID {} does not exist!", id), ); }; user.update_phone(db, &admin, &data.phone).await; Flash::success( Redirect::to(format!("/admin/user/{}", user.id)), "Telefonnummer erfolgreich geändert", ) } #[derive(FromForm, Debug)] pub struct AddressUpdateForm { address: String, } #[post("/user//change-address", data = "")] async fn update_address( db: &State, data: Form, admin: ManageUserUser, id: i32, ) -> Flash { let Some(user) = User::find_by_id(db, id).await else { return Flash::error( Redirect::to("/admin/user"), format!("User with ID {} does not exist!", id), ); }; user.update_address(db, &admin, &data.address).await; Flash::success( Redirect::to(format!("/admin/user/{}", user.id)), "Adresse erfolgreich geändert", ) } #[derive(FromForm, Debug)] pub struct FamilyUpdateForm { family_id: Option, } #[post("/user//change-family", data = "")] async fn update_family( db: &State, data: Form, admin: ManageUserUser, id: i32, ) -> Flash { let Some(user) = User::find_by_id(db, id).await else { return Flash::error( Redirect::to("/admin/user"), format!("User with ID {} does not exist!", id), ); }; let family = match data.family_id { Some(-1) => Some( Family::find_by_id(db, Family::insert(db).await) .await .unwrap(), ), Some(id) => match Family::find_by_id(db, id).await { Some(f) => Some(f), None => { return Flash::error( Redirect::to("/admin/user/{id}"), format!("Family with ID {} does not exist!", id), ); } }, None => None, }; user.update_family(db, &admin, family).await; Flash::success( Redirect::to(format!("/admin/user/{}", user.id)), "Familie erfolgreich geändert", ) } #[derive(FromForm, Debug)] pub struct ChangeSkillForm { skill_id: String, } #[post("/user//change-skill", data = "")] async fn change_skill( db: &State, data: Form, admin: ManageUserUser, id: i32, ) -> Flash { let Some(user) = User::find_by_id(db, id).await else { return Flash::error( Redirect::to("/admin/user"), format!("User with ID {} does not exist!", id), ); }; let skill = if data.skill_id.is_empty() { None } else { let Ok(skill_id) = data.skill_id.parse() else { return Flash::error( Redirect::to(format!("/admin/user/{id}")), "Skill_id is not a number", ); }; Role::find_by_id(db, skill_id).await }; match user.change_skill(db, &admin, skill).await { Ok(()) => Flash::success( Redirect::to(format!("/admin/user/{}", user.id)), "Skill erfolgreich geändert", ), Err(e) => Flash::error(Redirect::to(format!("/admin/user/{}", user.id)), e), } } #[derive(FromForm, Debug)] pub struct ChangeFinancialForm { financial_id: String, } #[post("/user//change-financial", data = "")] async fn change_financial( db: &State, data: Form, admin: ManageUserUser, id: i32, ) -> Flash { let Some(user) = User::find_by_id(db, id).await else { return Flash::error( Redirect::to("/admin/user"), format!("User with ID {} does not exist!", id), ); }; let financial = if data.financial_id.is_empty() { None } else { let Ok(financial_id) = data.financial_id.parse() else { return Flash::error( Redirect::to(format!("/admin/user/{id}")), "Finacial_id is not a number", ); }; Role::find_by_id(db, financial_id).await }; match user.change_financial(db, &admin, financial).await { Ok(()) => Flash::success( Redirect::to(format!("/admin/user/{}", user.id)), "Ermäßigung erfolgreich geändert", ), Err(e) => Flash::error(Redirect::to(format!("/admin/user/{}", user.id)), e), } } #[derive(FromForm, Debug)] pub struct AddMembershipPDFForm<'a> { membership_pdf: TempFile<'a>, } #[post("/user//add-membership-pdf", data = "")] async fn add_membership_pdf( db: &State, data: Form>, admin: ManageUserUser, id: i32, ) -> Flash { let Some(user) = User::find_by_id(db, id).await else { return Flash::error( Redirect::to("/admin/user"), format!("User with ID {} does not exist!", id), ); }; match user .add_membership_pdf(db, &admin, &data.membership_pdf) .await { Ok(_) => Flash::success( Redirect::to(format!("/admin/user/{}", user.id)), "Beitrittserklärung erfolgreich hinzugefügt", ), Err(e) => Flash::error(Redirect::to(format!("/admin/user/{}", user.id)), e), } } #[derive(FromForm, Debug)] pub struct NicknameUpdateForm { nickname: String, } #[post("/user//change-nickname", data = "")] async fn update_nickname( db: &State, data: Form, admin: ManageUserUser, id: i32, ) -> Flash { let Some(user) = User::find_by_id(db, id).await else { return Flash::error( Redirect::to("/admin/user"), format!("User with ID {} does not exist!", id), ); }; match user.update_nickname(db, &admin, &data.nickname).await { Ok(_) => Flash::success( Redirect::to(format!("/admin/user/{}", user.id)), "Spitzname erfolgreich geändert", ), Err(e) => Flash::error(Redirect::to(format!("/admin/user/{}", user.id)), e), } } #[derive(FromForm, Debug)] pub struct MemberSinceUpdateForm { member_since: String, } #[post("/user//change-member-since", data = "")] async fn update_member_since( db: &State, data: Form, admin: ManageUserUser, id: i32, ) -> Flash { let Some(user) = User::find_by_id(db, id).await else { return Flash::error( Redirect::to("/admin/user"), format!("User with ID {} does not exist!", id), ); }; let Ok(new_member_since_date) = NaiveDate::parse_from_str(&data.member_since, "%Y-%m-%d") else { return Flash::error( Redirect::to("/admin/user/{id}"), format!( "Beitrittsdatum {} ist nicht im YYYY-MM-DD Format", &data.member_since ), ); }; user.update_member_since(db, &admin, &new_member_since_date) .await; Flash::success( Redirect::to(format!("/admin/user/{}", user.id)), "Beitrittsdatum erfolgreich geändert", ) } #[derive(FromForm, Debug)] pub struct BirthdateUpdateForm { birthdate: String, } #[post("/user//change-birthdate", data = "")] async fn update_birthdate( db: &State, data: Form, admin: ManageUserUser, id: i32, ) -> Flash { let Some(user) = User::find_by_id(db, id).await else { return Flash::error( Redirect::to("/admin/user"), format!("User with ID {} does not exist!", id), ); }; let Ok(new_birthdate) = NaiveDate::parse_from_str(&data.birthdate, "%Y-%m-%d") else { return Flash::error( Redirect::to("/admin/user/{id}"), format!( "Geburtsdatum {} ist nicht im YYYY-MM-DD Format", &data.birthdate ), ); }; user.update_birthdate(db, &admin, &new_birthdate).await; Flash::success( Redirect::to(format!("/admin/user/{}", user.id)), "Geburtstag erfolgreich geändert", ) } #[derive(FromForm, Debug)] pub struct AddRoleForm { role_id: i32, } #[post("/user//add-role", data = "")] async fn add_role( db: &State, data: Form, admin: ManageUserUser, id: i32, ) -> Flash { let Some(user) = User::find_by_id(db, id).await else { return Flash::error( Redirect::to("/admin/user"), format!("User with ID {} does not exist!", id), ); }; let Some(role) = Role::find_by_id(db, data.role_id).await else { return Flash::error( Redirect::to("/admin/user/{user_id}"), format!("Role with ID {} does not exist!", data.role_id), ); }; match user.add_role(db, &admin, &role).await { Ok(_) => Flash::success( Redirect::to(format!("/admin/user/{}", user.id)), "Rolle erfolgreich hinzugefügt", ), Err(e) => Flash::error(Redirect::to(format!("/admin/user/{}", user.id)), e), } } #[get("/user//remove-role/")] async fn remove_role( db: &State, admin: ManageUserUser, user_id: i32, role_id: i32, ) -> Flash { let Some(user) = User::find_by_id(db, user_id).await else { return Flash::error( Redirect::to("/admin/user"), format!("User with ID {} does not exist!", user_id), ); }; let Some(role) = Role::find_by_id(db, role_id).await else { return Flash::error( Redirect::to("/admin/user/{user_id}"), format!("Role with ID {} does not exist!", role_id), ); }; match user.remove_role(db, &admin, &role).await { Ok(_) => Flash::success( Redirect::to(format!("/admin/user/{}", user.id)), "Rolle erfolgreich gelöscht", ), Err(e) => Flash::error(Redirect::to(format!("/admin/user/{}", user.id)), e), } } #[get("/user//membership")] async fn download_membership_pdf( db: &State, admin: ManageUserUser, user: i32, ) -> (ContentType, Vec) { let user = User::find_by_id(db, user).await.unwrap(); let user = UserWithMembershipPdf::from(db, user).await; Log::create( db, format!( "{} downloaded membership application for user: {}", admin.user.name, user.user.name ), ) .await; (ContentType::PDF, user.membership_pdf.unwrap()) } //#[derive(FromForm, Debug)] //struct UserAddScheckbuchForm<'r> { // name: &'r str, // mail: &'r str, //} //#[post("/user/new/scheckbuch", data = "")] //async fn create_scheckbuch( // db: &State, // data: Form>, // admin: VorstandUser, // config: &State, //) -> Flash { // // 1. Check mail adress // let mail = data.mail.trim(); // if mail.parse::
().is_err() { // return Flash::error( // Redirect::to("/admin/user/scheckbuch"), // "Keine gültige Mailadresse".to_string(), // ); // } // // // 2. Check name // let name = data.name.trim(); // if User::find_by_name(db, name).await.is_some() { // return Flash::error( // Redirect::to("/admin/user/scheckbuch"), // "Kann kein Scheckbuch erstellen, der Name wird bereits von einem User verwendet" // .to_string(), // ); // } // // // 3. Create user // User::create_with_mail(db, name, mail).await; // let user = User::find_by_name(db, name).await.unwrap(); // // // 4. Add 'scheckbuch' role // let scheckbuch = Role::find_by_name(db, "scheckbuch").await.unwrap(); // user.add_role(db, &scheckbuch) // .await // .expect("new user has no roles yet"); // // // 4. Send welcome mail (+ notification) // user.send_welcome_email(db, &config.smtp_pw).await.unwrap(); // // Log::create( // db, // format!("{} created new scheckbuch: {data:?}", admin.name), // ) // .await; // Flash::success(Redirect::to("/admin/user/scheckbuch"), format!("Scheckbuch erfolgreich erstellt. Eine E-Mail in der alles erklärt wird, wurde an {mail} verschickt.")) //} #[derive(FromForm, Debug)] pub struct SchnupperantToRegularForm<'a> { membertype: String, member_since: String, birthdate: String, phone: String, address: String, membership_pdf: TempFile<'a>, } #[post("/user//schnupperant-to-regular", data = "")] async fn schnupperant_to_regular( db: &State, data: Form>, admin: ManageUserUser, config: &State, id: i32, ) -> Flash { let Some(user) = User::find_by_id(db, id).await else { return Flash::error( Redirect::to("/admin/user"), format!("User with ID {} does not exist!", id), ); }; let Ok(birthdate) = NaiveDate::parse_from_str(&data.birthdate, "%Y-%m-%d") else { return Flash::error( Redirect::to(format!("/admin/user/{id}")), format!( "Geburtsdatum {} ist nicht im YYYY-MM-DD Format", &data.birthdate ), ); }; let Ok(member_since) = NaiveDate::parse_from_str(&data.member_since, "%Y-%m-%d") else { return Flash::error( Redirect::to(format!("/admin/user/{id}")), format!( "Beitrittsdatum {} ist nicht im YYYY-MM-DD Format", &data.birthdate ), ); }; let Some(user) = SchnupperantUser::new(db, &user).await else { return Flash::error( Redirect::to(format!("/admin/user/{id}")), "User ist kein Schnupperant", ); }; let Ok(phone) = data.phone.clone().try_into() else { return Flash::error( Redirect::to(format!("/admin/user/{id}")), "Vereinsmitglied braucht eine Telefonnummer", ); }; let Ok(address) = data.address.clone().try_into() else { return Flash::error( Redirect::to(format!("/admin/user/{id}")), "Vereinsmitglied braucht eine Adresse", ); }; let response = match &*data.membertype { "regular" => { user.convert_to_regular_user( db, &config.smtp_pw, &admin, &member_since, &birthdate, phone, address, &data.membership_pdf, ) .await } "unterstuetzend" => { user.convert_to_unterstuetzend_user( db, &config.smtp_pw, &admin, &member_since, &birthdate, phone, address, &data.membership_pdf, ) .await } "foerdernd" => { user.convert_to_foerdernd_user( db, &config.smtp_pw, &admin, &member_since, &birthdate, phone, address, &data.membership_pdf, ) .await } _ => { return Flash::error( Redirect::to(format!("/admin/user/{id}")), "Membertype gibts ned", ); } }; match response { Ok(_) => Flash::success( Redirect::to(format!("/admin/user/{}", id)), "Mitgliedstyp umgewandelt und Infos versendet", ), Err(e) => Flash::error(Redirect::to(format!("/admin/user/{}", id)), e), } } #[derive(FromForm, Debug)] pub struct ScheckToRegularForm<'a> { membertype: String, member_since: String, birthdate: String, phone: String, address: String, membership_pdf: TempFile<'a>, } #[post("/user//scheckbook-to-regular", data = "")] async fn scheckbook_to_regular( db: &State, data: Form>, admin: ManageUserUser, config: &State, id: i32, ) -> Flash { let Some(user) = User::find_by_id(db, id).await else { return Flash::error( Redirect::to("/admin/user"), format!("User with ID {} does not exist!", id), ); }; let Ok(birthdate) = NaiveDate::parse_from_str(&data.birthdate, "%Y-%m-%d") else { return Flash::error( Redirect::to(format!("/admin/user/{id}")), format!( "Geburtsdatum {} ist nicht im YYYY-MM-DD Format", &data.birthdate ), ); }; let Ok(member_since) = NaiveDate::parse_from_str(&data.member_since, "%Y-%m-%d") else { return Flash::error( Redirect::to(format!("/admin/user/{id}")), format!( "Beitrittsdatum {} ist nicht im YYYY-MM-DD Format", &data.birthdate ), ); }; let Some(user) = ScheckbuchUser::new(db, &user).await else { return Flash::error( Redirect::to(format!("/admin/user/{id}")), "User ist kein Scheckbuchuser", ); }; let Ok(phone) = data.phone.clone().try_into() else { return Flash::error( Redirect::to(format!("/admin/user/{id}")), "Vereinsmitglied braucht eine Telefonnummer", ); }; let Ok(address) = data.address.clone().try_into() else { return Flash::error( Redirect::to(format!("/admin/user/{id}")), "Vereinsmitglied braucht eine Adresse", ); }; let response = match &*data.membertype { "regular" => { user.convert_to_regular_user( db, &config.smtp_pw, &admin, &member_since, &birthdate, phone, address, &data.membership_pdf, ) .await } "unterstuetzend" => { user.convert_to_unterstuetzend_user( db, &config.smtp_pw, &admin, &member_since, &birthdate, phone, address, &data.membership_pdf, ) .await } "foerdernd" => { user.convert_to_foerdernd_user( db, &config.smtp_pw, &admin, &member_since, &birthdate, phone, address, &data.membership_pdf, ) .await } _ => { return Flash::error( Redirect::to(format!("/admin/user/{id}")), "Membertype gibts ned", ); } }; match response { Ok(_) => Flash::success( Redirect::to(format!("/admin/user/{}", id)), "Mitgliedstyp umgewandelt und Infos versendet", ), Err(e) => Flash::error(Redirect::to(format!("/admin/user/{}", id)), e), } } #[derive(FromForm, Debug)] pub struct ChangeMembertypeForm { membertype: String, } #[post("/user//change-membertype", data = "")] async fn change_membertype( db: &State, admin: ManageUserUser, data: Form, id: i32, ) -> Flash { let Some(user) = User::find_by_id(db, id).await else { return Flash::error( Redirect::to("/admin/user"), format!("User with ID {} does not exist!", id), ); }; let Some(user) = ClubMemberUser::new(db, &user).await else { return Flash::error( Redirect::to("/admin/user"), format!("User {user} ist kein Vereinsmitglied"), ); }; let response = match &*data.membertype { "regular" => user.move_to_regular(db, &admin).await, "unterstuetzend" => user.move_to_unterstuetzend(db, &admin).await, "foerdernd" => user.move_to_foerdernd(db, &admin).await, _ => { return Flash::error( Redirect::to(format!("/admin/user/{id}")), "Membertype gibt's ned", ); } }; match response { Ok(_) => Flash::success( Redirect::to(format!("/admin/user/{}", id)), "Mitgliedstyp umgewandelt und Infos versendet", ), Err(e) => Flash::error(Redirect::to(format!("/admin/user/{}", id)), e), } } #[get("/user//schnupperant-to-scheckbuch")] async fn schnupperant_to_scheckbook( db: &State, admin: ManageUserUser, config: &State, id: i32, ) -> Flash { let Some(user) = User::find_by_id(db, id).await else { return Flash::error( Redirect::to("/admin/user"), format!("User with ID {} does not exist!", id), ); }; let Some(user) = SchnupperantUser::new(db, &user).await else { return Flash::error( Redirect::to(format!("/admin/user/{id}")), format!("User {user} ist kein Schnupperant"), ); }; match user.move_to_scheckbook(db, &admin, &config.smtp_pw).await { Ok(_) => Flash::success( Redirect::to(format!("/admin/user/{}", id)), "Mitgliedstyp umgewandelt und Infos versendet", ), Err(e) => Flash::error(Redirect::to(format!("/admin/user/{}", id)), e), } } #[get("/user//schnupperinterest-to-schnupperant")] async fn schnupperinterest_to_schnupperant( db: &State, admin: ManageUserUser, config: &State, id: i32, ) -> Flash { let Some(user) = User::find_by_id(db, id).await else { return Flash::error( Redirect::to("/admin/user"), format!("User with ID {} does not exist!", id), ); }; let Some(user) = SchnupperInterestUser::new(db, &user).await else { return Flash::error( Redirect::to(format!("/admin/user/{id}")), format!("User {user} ist kein Schnupperinteressierter"), ); }; match user.move_to_schnupperant(db, &admin, &config.smtp_pw).await { Ok(_) => Flash::success( Redirect::to(format!("/admin/user/{}", id)), "Mitgliedstyp umgewandelt und Infos versendet", ), Err(e) => Flash::error(Redirect::to(format!("/admin/user/{}", id)), e), } } #[get("/user//schnupperant-to-schnupperinterest")] async fn schnupperant_to_schnupperinterest( db: &State, admin: ManageUserUser, id: i32, ) -> Flash { let Some(user) = User::find_by_id(db, id).await else { return Flash::error( Redirect::to("/admin/user"), format!("User with ID {} does not exist!", id), ); }; let Some(user) = SchnupperantUser::new(db, &user).await else { return Flash::error( Redirect::to(format!("/admin/user/{id}")), format!("User {user} ist kein Schnupperant"), ); }; match user.move_to_schnupperinterest(db, &admin).await { Ok(_) => Flash::success( Redirect::to(format!("/admin/user/{}", id)), "Mitgliedstyp umgewandelt.", ), Err(e) => Flash::error(Redirect::to(format!("/admin/user/{}", id)), e), } } #[get("/user//schnupperinterest-to-scheckbuch")] async fn schnupperinterest_to_scheckbuch( db: &State, admin: ManageUserUser, config: &State, id: i32, ) -> Flash { let Some(user) = User::find_by_id(db, id).await else { return Flash::error( Redirect::to("/admin/user"), format!("User with ID {} does not exist!", id), ); }; let Some(user) = SchnupperInterestUser::new(db, &user).await else { return Flash::error( Redirect::to(format!("/admin/user/{id}")), format!("User {user} ist kein Schnupperinteressierter"), ); }; match user.move_to_scheckbook(db, &admin, &config.smtp_pw).await { Ok(_) => Flash::success( Redirect::to(format!("/admin/user/{}", id)), "Mitgliedstyp umgewandelt und Infos versendet", ), Err(e) => Flash::error(Redirect::to(format!("/admin/user/{}", id)), e), } } #[derive(FromForm, Debug)] pub struct AddClubMemberForm<'a> { name: String, mail: String, financial_id: String, membertype: String, member_since: String, birthdate: String, phone: String, address: String, membership_pdf: TempFile<'a>, } #[post("/user/new/clubmember", data = "")] async fn add_club_member( db: &State, data: Form>, admin: ManageUserUser, config: &State, ) -> Flash { if !valid_mails(&data.mail) { return Flash::error( Redirect::to("/admin/user"), format!( "{} ist kein gültiges Format für eine Mailadresse", &data.mail ), ); } let financial = if data.financial_id.is_empty() { None } else { let Ok(financial_id) = data.financial_id.parse() else { return Flash::error(Redirect::to("/admin/user"), "Finacial_id is not a number"); }; Role::find_by_id(db, financial_id).await }; let Ok(birthdate) = NaiveDate::parse_from_str(&data.birthdate, "%Y-%m-%d") else { return Flash::error( Redirect::to("/admin/user/"), format!( "Geburtsdatum {} ist nicht im YYYY-MM-DD Format", &data.birthdate ), ); }; let Ok(member_since) = NaiveDate::parse_from_str(&data.member_since, "%Y-%m-%d") else { return Flash::error( Redirect::to("/admin/user"), format!( "Beitrittsdatum {} ist nicht im YYYY-MM-DD Format", &data.birthdate ), ); }; let Ok(phone) = data.phone.clone().try_into() else { return Flash::error( Redirect::to("/admin/user"), "Vereinsmitglied braucht eine Telefonnummer", ); }; let Ok(address) = data.address.clone().try_into() else { return Flash::error( Redirect::to("/admin/user"), "Vereinsmitglied braucht eine Adresse", ); }; let Ok(name) = data.name.clone().try_into() else { return Flash::error( Redirect::to("/admin/user"), "Vereinsmitglied braucht einen Namen", ); }; let response = match &*data.membertype { "regular" => { RegularUser::create( db, &admin, &config.smtp_pw, name, &data.mail, financial, &birthdate, &member_since, phone, address, &data.membership_pdf, ) .await } "unterstuetzend" => { UnterstuetzendUser::create( db, &admin, &config.smtp_pw, name, &data.mail, financial, &birthdate, &member_since, phone, address, &data.membership_pdf, ) .await } "foerdernd" => { FoerderndUser::create( db, &admin, &config.smtp_pw, name, &data.mail, financial, &birthdate, &member_since, phone, address, &data.membership_pdf, ) .await } _ => return Flash::error(Redirect::to("/admin/user"), "Membertype gibts ned"), }; match response { Ok(_) => Flash::success(Redirect::to("/admin/user"), "Mitglied erfolgreich erstellt"), Err(e) => Flash::error(Redirect::to("/admin/user"), e), } } #[derive(FromForm, Debug)] pub struct AddScheckbuchForm { name: String, mail: String, } #[post("/user/new/scheckbuch", data = "")] async fn add_scheckbuch( db: &State, data: Form, admin: ManageUserUser, config: &State, ) -> Flash { if !valid_mails(&data.mail) { return Flash::error( Redirect::to("/admin/user"), format!( "{} ist kein gültiges Format für eine Mailadresse", &data.mail ), ); } let Ok(name) = data.name.clone().try_into() else { return Flash::error( Redirect::to("/admin/user"), "Scheckbuch braucht einen Namen", ); }; match ScheckbuchUser::create(db, &admin, &config.smtp_pw, name, &data.mail).await { Ok(_) => Flash::success( Redirect::to("/admin/user"), "Scheckbuch erfolgreich erstellt", ), Err(e) => Flash::error(Redirect::to("/admin/user"), e), } } #[derive(FromForm, Debug)] pub struct AddSchnupperForm { name: String, mail: String, schnupper_type: String, } #[post("/user/new/schnupper", data = "")] async fn add_schnupper( db: &State, data: Form, admin: ManageUserUser, config: &State, ) -> Flash { if !valid_mails(&data.mail) { return Flash::error( Redirect::to("/admin/user"), format!( "{} ist kein gültiges Format für eine Mailadresse", &data.mail ), ); } let Ok(name) = data.name.clone().try_into() else { return Flash::error( Redirect::to("/admin/user"), "Schnupperer braucht einen Namen", ); }; let response = match &*data.schnupper_type { "schnupperInterested" => SchnupperInterestUser::create(db, &admin, name, &data.mail).await, "schnupperant" => { SchnupperantUser::create(db, &admin, &config.smtp_pw, name, &data.mail).await } _ => return Flash::error(Redirect::to("/admin/user"), "Schnuppertyp gibts ned"), }; match response { Ok(_) => Flash::success( Redirect::to("/admin/user"), "Schnupperer erfolgreich erstellt", ), Err(e) => Flash::error(Redirect::to("/admin/user"), e), } } pub fn routes() -> Vec { routes![ index, index_admin, view, resetpw, delete, fees, fees_paid, scheckbuch, download_membership_pdf, // Updates update_mail, update_phone, update_nickname, update_member_since, update_birthdate, update_address, update_family, change_skill, change_financial, add_membership_pdf, add_role, add_note, remove_role, // Moves scheckbook_to_regular, schnupperant_to_regular, schnupperant_to_scheckbook, schnupperinterest_to_schnupperant, schnupperant_to_schnupperinterest, schnupperinterest_to_scheckbuch, change_membertype, // Add add_club_member, add_scheckbuch, add_schnupper, ] }