rowt/src/tera/admin/user.rs
Philipp Hofer e853381bd7
Some checks failed
CI/CD Pipeline / test (push) Failing after 11s
CI/CD Pipeline / deploy-staging (push) Has been skipped
CI/CD Pipeline / deploy-main (push) Has been skipped
Fill acitivites from various activities; Fixes #972
2025-05-04 18:38:14 +02:00

1235 lines
36 KiB
Rust

use crate::{
model::{
activity::Activity,
family::Family,
log::Log,
logbook::Logbook,
role::Role,
user::{
clubmember::ClubMemberUser, member::Member, scheckbuch::ScheckbuchUser,
schnupperant::SchnupperantUser, schnupperinterest::SchnupperInterestUser, AdminUser,
AllowedToEditPaymentStatusUser, ManageUserUser, User, UserWithDetails,
UserWithMembershipPdf, UserWithRolesAndMembershipPdf, VorstandUser,
},
},
tera::Config,
};
use chrono::NaiveDate;
use futures::future::join_all;
use rocket::{
form::Form,
fs::TempFile,
get,
http::{ContentType, Status},
post,
request::{FlashMessage, FromRequest, Outcome},
response::{Flash, Redirect},
routes, FromForm, Request, Route, State,
};
use rocket_dyn_templates::{tera::Context, Template};
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<Self, Self::Error> {
match request.headers().get_one("Referer") {
Some(referer) => Outcome::Success(Referer(referer.to_string())),
None => Outcome::Error((Status::BadRequest, ())),
}
}
}
#[get("/user?<sort>&<asc>")]
async fn index(
db: &State<SqlitePool>,
user: VorstandUser,
flash: Option<FlashMessage<'_>>,
sort: Option<String>,
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<UserWithRolesAndMembershipPdf> = join_all(user_futures).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("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<SqlitePool>,
user: AdminUser,
flash: Option<FlashMessage<'_>>,
) -> 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<UserWithRolesAndMembershipPdf> = join_all(user_futures).await;
let user: User = user.user;
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("families", &families);
context.insert("loggedin_user", &UserWithDetails::from_user(user, db).await);
Template::render("admin/user/index", context.into_json())
}
#[get("/user/<user>")]
async fn view(
db: &State<SqlitePool>,
admin: VorstandUser,
flash: Option<FlashMessage<'_>>,
user: i32,
) -> Result<Template, Flash<Redirect>> {
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<SqlitePool>,
user: VorstandUser,
flash: Option<FlashMessage<'_>>,
) -> 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<SqlitePool>,
user: VorstandUser,
flash: Option<FlashMessage<'_>>,
) -> 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?<user_ids>")]
async fn fees_paid(
db: &State<SqlitePool>,
calling_user: AllowedToEditPaymentStatusUser,
user_ids: Vec<i32>,
referer: Referer,
) -> Flash<Redirect> {
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/<user>/reset-pw")]
async fn resetpw(db: &State<SqlitePool>, admin: ManageUserUser, user: i32) -> Flash<Redirect> {
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/<user>/delete")]
async fn delete(db: &State<SqlitePool>, admin: ManageUserUser, user: i32) -> Flash<Redirect> {
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).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/<id>/change-mail", data = "<data>")]
async fn update_mail(
db: &State<SqlitePool>,
data: Form<MailUpdateForm>,
admin: ManageUserUser,
id: i32,
) -> Flash<Redirect> {
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/<id>/new-note", data = "<data>")]
async fn add_note(
db: &State<SqlitePool>,
data: Form<AddNoteForm>,
admin: ManageUserUser,
id: i32,
) -> Flash<Redirect> {
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/<id>/change-phone", data = "<data>")]
async fn update_phone(
db: &State<SqlitePool>,
data: Form<PhoneUpdateForm>,
admin: ManageUserUser,
id: i32,
) -> Flash<Redirect> {
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/<id>/change-address", data = "<data>")]
async fn update_address(
db: &State<SqlitePool>,
data: Form<AddressUpdateForm>,
admin: ManageUserUser,
id: i32,
) -> Flash<Redirect> {
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<i64>,
}
#[post("/user/<id>/change-family", data = "<data>")]
async fn update_family(
db: &State<SqlitePool>,
data: Form<FamilyUpdateForm>,
admin: ManageUserUser,
id: i32,
) -> Flash<Redirect> {
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/<id>/change-skill", data = "<data>")]
async fn change_skill(
db: &State<SqlitePool>,
data: Form<ChangeSkillForm>,
admin: ManageUserUser,
id: i32,
) -> Flash<Redirect> {
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 == "" {
None
} else {
let Ok(skill_id) = data.skill_id.parse() else {
return Flash::error(
Redirect::to(format!("/admin/user/{id}")),
format!("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/<id>/change-financial", data = "<data>")]
async fn change_financial(
db: &State<SqlitePool>,
data: Form<ChangeFinancialForm>,
admin: ManageUserUser,
id: i32,
) -> Flash<Redirect> {
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 == "" {
None
} else {
let Ok(financial_id) = data.financial_id.parse() else {
return Flash::error(
Redirect::to(format!("/admin/user/{id}")),
format!("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/<id>/add-membership-pdf", data = "<data>")]
async fn add_membership_pdf(
db: &State<SqlitePool>,
data: Form<AddMembershipPDFForm<'_>>,
admin: ManageUserUser,
id: i32,
) -> Flash<Redirect> {
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/<id>/change-nickname", data = "<data>")]
async fn update_nickname(
db: &State<SqlitePool>,
data: Form<NicknameUpdateForm>,
admin: ManageUserUser,
id: i32,
) -> Flash<Redirect> {
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/<id>/change-member-since", data = "<data>")]
async fn update_member_since(
db: &State<SqlitePool>,
data: Form<MemberSinceUpdateForm>,
admin: ManageUserUser,
id: i32,
) -> Flash<Redirect> {
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/<id>/change-birthdate", data = "<data>")]
async fn update_birthdate(
db: &State<SqlitePool>,
data: Form<BirthdateUpdateForm>,
admin: ManageUserUser,
id: i32,
) -> Flash<Redirect> {
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/<id>/add-role", data = "<data>")]
async fn add_role(
db: &State<SqlitePool>,
data: Form<AddRoleForm>,
admin: ManageUserUser,
id: i32,
) -> Flash<Redirect> {
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/<user_id>/remove-role/<role_id>")]
async fn remove_role(
db: &State<SqlitePool>,
admin: ManageUserUser,
user_id: i32,
role_id: i32,
) -> Flash<Redirect> {
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/<user>/membership")]
async fn download_membership_pdf(
db: &State<SqlitePool>,
admin: ManageUserUser,
user: i32,
) -> (ContentType, Vec<u8>) {
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 = "<data>")]
//async fn create_scheckbuch(
// db: &State<SqlitePool>,
// data: Form<UserAddScheckbuchForm<'_>>,
// admin: VorstandUser,
// config: &State<Config>,
//) -> Flash<Redirect> {
// // 1. Check mail adress
// let mail = data.mail.trim();
// if mail.parse::<Address>().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/<id>/schnupperant-to-regular", data = "<data>")]
async fn schnupperant_to_regular(
db: &State<SqlitePool>,
data: Form<SchnupperantToRegularForm<'_>>,
admin: ManageUserUser,
config: &State<Config>,
id: i32,
) -> Flash<Redirect> {
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/<id>/scheckbook-to-regular", data = "<data>")]
async fn scheckbook_to_regular(
db: &State<SqlitePool>,
data: Form<ScheckToRegularForm<'_>>,
admin: ManageUserUser,
config: &State<Config>,
id: i32,
) -> Flash<Redirect> {
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/<id>/change-membertype", data = "<data>")]
async fn change_membertype(
db: &State<SqlitePool>,
admin: ManageUserUser,
data: Form<ChangeMembertypeForm>,
id: i32,
) -> Flash<Redirect> {
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 }}")),
format!("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/<id>/schnupperant-to-scheckbuch")]
async fn schnupperant_to_scheckbook(
db: &State<SqlitePool>,
admin: ManageUserUser,
config: &State<Config>,
id: i32,
) -> Flash<Redirect> {
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/<id>/schnupperinterest-to-schnupperant")]
async fn schnupperinterest_to_schnupperant(
db: &State<SqlitePool>,
admin: ManageUserUser,
config: &State<Config>,
id: i32,
) -> Flash<Redirect> {
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/<id>/schnupperant-to-schnupperinterest")]
async fn schnupperant_to_schnupperinterest(
db: &State<SqlitePool>,
admin: ManageUserUser,
id: i32,
) -> Flash<Redirect> {
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/<id>/schnupperinterest-to-scheckbuch")]
async fn schnupperinterest_to_scheckbuch(
db: &State<SqlitePool>,
admin: ManageUserUser,
config: &State<Config>,
id: i32,
) -> Flash<Redirect> {
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),
}
}
pub fn routes() -> Vec<Route> {
routes![
index,
index_admin,
view,
resetpw,
//create_scheckbuch,
delete,
fees,
fees_paid,
scheckbuch,
download_membership_pdf,
//
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,
//
scheckbook_to_regular,
schnupperant_to_regular,
schnupperant_to_scheckbook,
schnupperinterest_to_schnupperant,
schnupperant_to_schnupperinterest,
schnupperinterest_to_scheckbuch,
change_membertype,
]
}