allow to create users
Some checks failed
CI/CD Pipeline / test (push) Has been cancelled
CI/CD Pipeline / deploy-staging (push) Has been cancelled
CI/CD Pipeline / deploy-main (push) Has been cancelled

This commit is contained in:
2025-05-05 11:35:38 +02:00
parent ebbb4fe3da
commit d9e86bf43b
44 changed files with 964 additions and 241 deletions

View File

@ -5,13 +5,14 @@ use crate::model::{
user::{User, UserWithDetails, VorstandUser},
};
use rocket::{
Route, State,
form::Form,
get, post,
request::FlashMessage,
response::{Flash, Redirect},
routes, Route, State,
routes,
};
use rocket_dyn_templates::{tera::Context, Template};
use rocket_dyn_templates::{Template, tera::Context};
use sqlx::SqlitePool;
#[get("/boat")]
@ -245,9 +246,11 @@ mod test {
let rocket = rocket::build().manage(db.clone());
let rocket = crate::tera::config(rocket);
assert!(Boat::find_by_name(&db, "completely-new-boat".into())
.await
.is_none());
assert!(
Boat::find_by_name(&db, "completely-new-boat".into())
.await
.is_none()
);
let client = Client::tracked(rocket).await.unwrap();
let login = client

View File

@ -1,8 +1,9 @@
use rocket::{
FromForm, Route, State,
form::Form,
get, post, put,
response::{Flash, Redirect},
routes, FromForm, Route, State,
routes,
};
use serde::Serialize;
use sqlx::SqlitePool;
@ -32,8 +33,8 @@ async fn create(
let trip_details_id = TripDetails::create(db, data.tripdetails).await;
let trip_details = TripDetails::find_by_id(db, trip_details_id).await.unwrap(); //Okay, bc. we
//just created
//the object
//just created
//the object
Event::create(
db,

View File

@ -1,9 +1,9 @@
use rocket::form::Form;
use rocket::fs::TempFile;
use rocket::response::{Flash, Redirect};
use rocket::{get, request::FlashMessage, routes, Route, State};
use rocket::{post, FromForm};
use rocket_dyn_templates::{tera::Context, Template};
use rocket::{FromForm, post};
use rocket::{Route, State, get, request::FlashMessage, routes};
use rocket_dyn_templates::{Template, tera::Context};
use sqlx::SqlitePool;
use crate::model::log::Log;

View File

@ -1,6 +1,6 @@
use csv::ReaderBuilder;
use rocket::{form::Form, get, post, routes, FromForm, Route, State};
use rocket_dyn_templates::{context, Template};
use rocket::{FromForm, Route, State, form::Form, get, post, routes};
use rocket_dyn_templates::{Template, context};
use sqlx::SqlitePool;
use crate::{

View File

@ -6,13 +6,14 @@ use crate::model::{
};
use itertools::Itertools;
use rocket::{
FromForm, Route, State,
form::Form,
get, post,
request::FlashMessage,
response::{Flash, Redirect},
routes, FromForm, Route, State,
routes,
};
use rocket_dyn_templates::{tera::Context, Template};
use rocket_dyn_templates::{Template, tera::Context};
use sqlx::SqlitePool;
#[get("/notification")]

View File

@ -3,8 +3,8 @@ use crate::model::{
user::{SchnupperBetreuerUser, User, UserWithDetails},
};
use futures::future::join_all;
use rocket::{get, request::FlashMessage, routes, Route, State};
use rocket_dyn_templates::{tera::Context, Template};
use rocket::{Route, State, get, request::FlashMessage, routes};
use rocket_dyn_templates::{Template, tera::Context};
use sqlx::SqlitePool;
#[get("/schnupper")]

View File

@ -4,11 +4,13 @@ use crate::{
family::Family,
log::Log,
logbook::Logbook,
mail::valid_mails,
role::Role,
user::{
clubmember::ClubMemberUser, member::Member, scheckbuch::ScheckbuchUser,
schnupperant::SchnupperantUser, schnupperinterest::SchnupperInterestUser, AdminUser,
AllowedToEditPaymentStatusUser, ManageUserUser, User, UserWithDetails,
clubmember::ClubMemberUser, foerdernd::FoerderndUser, member::Member,
regular::RegularUser, scheckbuch::ScheckbuchUser, schnupperant::SchnupperantUser,
schnupperinterest::SchnupperInterestUser, unterstuetzend::UnterstuetzendUser,
AdminUser, AllowedToEditPaymentStatusUser, ManageUserUser, User, UserWithDetails,
UserWithMembershipPdf, UserWithRolesAndMembershipPdf, VorstandUser,
},
},
@ -64,6 +66,7 @@ async fn index(
let allowed_to_edit = ManageUserUser::new(db, &user).await.is_some();
let users: Vec<UserWithRolesAndMembershipPdf> = 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;
@ -75,6 +78,7 @@ async fn index(
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);
@ -95,6 +99,7 @@ async fn index_admin(
let users: Vec<UserWithRolesAndMembershipPdf> = 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;
@ -107,6 +112,7 @@ async fn index_admin(
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);
@ -463,13 +469,13 @@ async fn change_skill(
);
};
let skill = if &data.skill_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}")),
format!("Skill_id is not a number"),
"Skill_id is not a number",
);
};
Role::find_by_id(db, skill_id).await
@ -503,13 +509,13 @@ async fn change_financial(
);
};
let financial = if &data.financial_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}")),
format!("Finacial_id is not a number"),
"Finacial_id is not a number",
);
};
Role::find_by_id(db, financial_id).await
@ -899,7 +905,7 @@ async fn schnupperant_to_regular(
return Flash::error(
Redirect::to(format!("/admin/user/{id}")),
"Membertype gibts ned",
)
);
}
};
@ -1018,7 +1024,7 @@ async fn scheckbook_to_regular(
return Flash::error(
Redirect::to(format!("/admin/user/{id}")),
"Membertype gibts ned",
)
);
}
};
@ -1050,7 +1056,7 @@ async fn change_membertype(
);
};
let Some(user) = ClubMemberUser::new(&db, &user).await else {
let Some(user) = ClubMemberUser::new(db, &user).await else {
return Flash::error(
Redirect::to("/admin/user"),
format!("User {user} ist kein Vereinsmitglied"),
@ -1063,9 +1069,9 @@ async fn change_membertype(
"foerdernd" => user.move_to_foerdernd(db, &admin).await,
_ => {
return Flash::error(
Redirect::to(format!("/admin/user/{{ id }}")),
format!("Membertype gibt's ned"),
)
Redirect::to(format!("/admin/user/{id}")),
"Membertype gibt's ned",
);
}
};
@ -1092,7 +1098,7 @@ async fn schnupperant_to_scheckbook(
);
};
let Some(user) = SchnupperantUser::new(&db, &user).await else {
let Some(user) = SchnupperantUser::new(db, &user).await else {
return Flash::error(
Redirect::to(format!("/admin/user/{id}")),
format!("User {user} ist kein Schnupperant"),
@ -1122,7 +1128,7 @@ async fn schnupperinterest_to_schnupperant(
);
};
let Some(user) = SchnupperInterestUser::new(&db, &user).await else {
let Some(user) = SchnupperInterestUser::new(db, &user).await else {
return Flash::error(
Redirect::to(format!("/admin/user/{id}")),
format!("User {user} ist kein Schnupperinteressierter"),
@ -1151,7 +1157,7 @@ async fn schnupperant_to_schnupperinterest(
);
};
let Some(user) = SchnupperantUser::new(&db, &user).await else {
let Some(user) = SchnupperantUser::new(db, &user).await else {
return Flash::error(
Redirect::to(format!("/admin/user/{id}")),
format!("User {user} ist kein Schnupperant"),
@ -1180,7 +1186,7 @@ async fn schnupperinterest_to_scheckbuch(
);
};
let Some(user) = SchnupperInterestUser::new(&db, &user).await else {
let Some(user) = SchnupperInterestUser::new(db, &user).await else {
return Flash::error(
Redirect::to(format!("/admin/user/{id}")),
format!("User {user} ist kein Schnupperinteressierter"),
@ -1196,19 +1202,236 @@ async fn schnupperinterest_to_scheckbuch(
}
}
#[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 = "<data>")]
async fn add_club_member(
db: &State<SqlitePool>,
data: Form<AddClubMemberForm<'_>>,
admin: ManageUserUser,
config: &State<Config>,
) -> Flash<Redirect> {
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 = "<data>")]
async fn add_scheckbuch(
db: &State<SqlitePool>,
data: Form<AddScheckbuchForm>,
admin: ManageUserUser,
config: &State<Config>,
) -> Flash<Redirect> {
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 = "<data>")]
async fn add_schnupper(
db: &State<SqlitePool>,
data: Form<AddSchnupperForm>,
admin: ManageUserUser,
config: &State<Config>,
) -> Flash<Redirect> {
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<Route> {
routes![
index,
index_admin,
view,
resetpw,
//create_scheckbuch,
delete,
fees,
fees_paid,
scheckbuch,
download_membership_pdf,
//
// Updates
update_mail,
update_phone,
update_nickname,
@ -1222,7 +1445,7 @@ pub fn routes() -> Vec<Route> {
add_role,
add_note,
remove_role,
//
// Moves
scheckbook_to_regular,
schnupperant_to_regular,
schnupperant_to_scheckbook,
@ -1230,5 +1453,9 @@ pub fn routes() -> Vec<Route> {
schnupperant_to_schnupperinterest,
schnupperinterest_to_scheckbuch,
change_membertype,
// Add
add_club_member,
add_scheckbuch,
add_schnupper,
]
}

View File

@ -1,4 +1,5 @@
use rocket::{
FromForm, Request, Route, State,
form::Form,
get,
http::{Cookie, CookieJar},
@ -8,9 +9,8 @@ use rocket::{
response::{Flash, Redirect},
routes,
time::{Duration, OffsetDateTime},
FromForm, Request, Route, State,
};
use rocket_dyn_templates::{context, tera, Template};
use rocket_dyn_templates::{Template, context, tera};
use sqlx::SqlitePool;
use crate::model::{
@ -73,7 +73,10 @@ async fn login(
);
}
Err(_) => {
return Flash::error(Redirect::to("/auth"), "Falscher Benutzername/Passwort. Du bist Vereinsmitglied und der Login klappt nicht? Kontaktiere unseren Schriftführer oder schreibe eine Mail an info@rudernlinz.at!");
return Flash::error(
Redirect::to("/auth"),
"Falscher Benutzername/Passwort. Du bist Vereinsmitglied und der Login klappt nicht? Kontaktiere unseren Schriftführer oder schreibe eine Mail an info@rudernlinz.at!",
);
}
};

View File

@ -3,8 +3,8 @@ use crate::model::{
role::Role,
user::{User, UserWithDetails, VorstandUser},
};
use rocket::{get, request::FlashMessage, routes, Route, State};
use rocket_dyn_templates::{tera::Context, Template};
use rocket::{Route, State, get, request::FlashMessage, routes};
use rocket_dyn_templates::{Template, tera::Context};
use sqlx::SqlitePool;
#[get("/achievement")]

View File

@ -4,13 +4,14 @@ use crate::model::{
user::{AdminUser, UserWithDetails, VorstandUser},
};
use rocket::{
FromForm, Route, State,
form::Form,
get, post,
request::FlashMessage,
response::{Flash, Redirect},
routes, FromForm, Route, State,
routes,
};
use rocket_dyn_templates::{tera::Context, Template};
use rocket_dyn_templates::{Template, tera::Context};
use sqlx::SqlitePool;
#[get("/boathouse")]

View File

@ -1,9 +1,10 @@
use rocket::{
FromForm, Route, State,
form::Form,
get, post,
request::FlashMessage,
response::{Flash, Redirect},
routes, FromForm, Route, State,
routes,
};
use rocket_dyn_templates::Template;
use sqlx::SqlitePool;

View File

@ -1,10 +1,11 @@
use chrono::NaiveDate;
use rocket::{
FromForm, Route, State,
form::Form,
get, post,
request::FlashMessage,
response::{Flash, Redirect},
routes, FromForm, Route, State,
routes,
};
use rocket_dyn_templates::Template;
use sqlx::SqlitePool;

View File

@ -1,8 +1,9 @@
use rocket::{
FromForm, Route, State,
form::Form,
get, post,
response::{Flash, Redirect},
routes, FromForm, Route, State,
routes,
};
use sqlx::SqlitePool;
@ -22,7 +23,7 @@ async fn create_ergo(
) -> Flash<Redirect> {
let trip_details_id = TripDetails::create(db, data.into_inner()).await;
let trip_details = TripDetails::find_by_id(db, trip_details_id).await.unwrap(); //Okay, bc just
//created
//created
Trip::new_own_ergo(db, &cox, trip_details).await; //TODO: fix
//Log::create(
@ -45,7 +46,7 @@ async fn create(
) -> Flash<Redirect> {
let trip_details_id = TripDetails::create(db, data.into_inner()).await;
let trip_details = TripDetails::find_by_id(db, trip_details_id).await.unwrap(); //Okay, bc just
//created
//created
Trip::new_own(db, &cox, trip_details).await; //TODO: fix
//Log::create(
@ -137,9 +138,10 @@ async fn join(db: &State<SqlitePool>, planned_event_id: i64, cox: SteeringUser)
.await;
Flash::success(Redirect::to("/planned"), "Danke für's helfen!")
}
Err(CoxHelpError::CanceledEvent) => {
Flash::error(Redirect::to("/planned"), "Die Ausfahrt wurde leider abgesagt...")
}
Err(CoxHelpError::CanceledEvent) => Flash::error(
Redirect::to("/planned"),
"Die Ausfahrt wurde leider abgesagt...",
),
Err(CoxHelpError::AlreadyRegisteredAsCox) => {
Flash::error(Redirect::to("/planned"), "Du hilfst bereits aus!")
}
@ -147,9 +149,10 @@ async fn join(db: &State<SqlitePool>, planned_event_id: i64, cox: SteeringUser)
Redirect::to("/planned"),
"Du hast dich bereits als Ruderer angemeldet!",
),
Err(CoxHelpError::DetailsLocked) => {
Flash::error(Redirect::to("/planned"), "Die Bootseinteilung wurde bereits gemacht. Wenn du noch steuern möchtest, frag bitte bei einer bereits angemeldeten Steuerperson nach, ob das noch möglich ist.")
}
Err(CoxHelpError::DetailsLocked) => Flash::error(
Redirect::to("/planned"),
"Die Bootseinteilung wurde bereits gemacht. Wenn du noch steuern möchtest, frag bitte bei einer bereits angemeldeten Steuerperson nach, ob das noch möglich ist.",
),
}
} else {
Flash::error(Redirect::to("/planned"), "Event gibt's nicht")
@ -197,9 +200,10 @@ async fn remove(
Flash::success(Redirect::to("/planned"), "Erfolgreich abgemeldet!")
}
Err(TripHelpDeleteError::DetailsLocked) => {
Flash::error(Redirect::to("/planned"), "Die Bootseinteilung wurde bereits gemacht. Wenn du doch nicht steuern kannst, melde dich bitte unbedingt schnellstmöglich bei einer anderen Steuerperson!")
}
Err(TripHelpDeleteError::DetailsLocked) => Flash::error(
Redirect::to("/planned"),
"Die Bootseinteilung wurde bereits gemacht. Wenn du doch nicht steuern kannst, melde dich bitte unbedingt schnellstmöglich bei einer anderen Steuerperson!",
),
Err(TripHelpDeleteError::CoxNotHelping) => {
Flash::error(Redirect::to("/planned"), "Steuermann hilft nicht aus...")
}

View File

@ -2,6 +2,7 @@ use std::env;
use chrono::Utc;
use rocket::{
FromForm, Route, State,
form::Form,
fs::TempFile,
get,
@ -9,9 +10,9 @@ use rocket::{
post,
request::FlashMessage,
response::{Flash, Redirect},
routes, FromForm, Route, State,
routes,
};
use rocket_dyn_templates::{context, Template};
use rocket_dyn_templates::{Template, context};
use serde::Serialize;
use sqlx::SqlitePool;
use tera::Context;

View File

@ -1,6 +1,7 @@
use std::net::IpAddr;
use rocket::{
Request, Route, State,
form::Form,
get,
http::{Cookie, CookieJar},
@ -9,9 +10,8 @@ use rocket::{
response::{Flash, Redirect},
routes,
time::{Duration, OffsetDateTime},
Request, Route, State,
};
use rocket_dyn_templates::{context, Template};
use rocket_dyn_templates::{Template, context};
use sqlx::SqlitePool;
use tera::Context;
@ -215,31 +215,77 @@ async fn create_logbook(
user: &DonauLinzUser,
smtp_pw: &str,
) -> Flash<Redirect> {
match Logbook::create(
db,
data.into_inner(),
user, smtp_pw
)
.await
{
Ok(msg) => Flash::success(Redirect::to("/log"), format!("Ausfahrt erfolgreich hinzugefügt{msg}")),
Err(LogbookCreateError::BoatAlreadyOnWater) => Flash::error(Redirect::to("/log"), "Boot schon am Wasser"),
Err(LogbookCreateError::RowerAlreadyOnWater(rower)) => Flash::error(Redirect::to("/log"), format!("Ruderer {} schon am Wasser", rower.name)),
Err(LogbookCreateError::BoatLocked) => Flash::error(Redirect::to("/log"),"Boot gesperrt"),
Err(LogbookCreateError::BoatNotFound) => Flash::error(Redirect::to("/log"), "Boot gibt's ned"),
Err(LogbookCreateError::TooManyRowers(expected, actual)) => Flash::error(Redirect::to("/log"), format!("Zu viele Ruderer (Boot fasst maximal {expected}, es wurden jedoch {actual} Ruderer ausgewählt)")),
Err(LogbookCreateError::RowerCreateError(rower, e)) => Flash::error(Redirect::to("/log"), format!("Fehler bei Ruderer {rower}: {e}")),
Err(LogbookCreateError::ArrivalNotAfterDeparture) => Flash::error(Redirect::to("/log"), "Ankunftszeit kann nicht vor der Abfahrtszeit sein"),
Err(LogbookCreateError::UserNotAllowedToUseBoat) => Flash::error(Redirect::to("/log"), "Schiffsführer darf dieses Boot nicht verwenden"),
Err(LogbookCreateError::SteeringPersonNotInRowers) => Flash::error(Redirect::to("/log"), "Steuerperson nicht in Liste der Ruderer!"),
Err(LogbookCreateError::ShipmasterNotInRowers) => Flash::error(Redirect::to("/log"), "Schiffsführer nicht in Liste der Ruderer!"),
Err(LogbookCreateError::NotYourEntry) => Flash::error(Redirect::to("/log"), "Nicht deine Ausfahrt!"),
Err(LogbookCreateError::ArrivalSetButNotRemainingTwo) => Flash::error(Redirect::to("/log"), "Ankunftszeit gesetzt aber nicht Distanz + Strecke"),
Err(LogbookCreateError::OnlyAllowedToEndTripsEndingToday) => Flash::error(Redirect::to("/log"), "Nur Ausfahrten, die in der letzten Woche enden dürfen eingetragen werden. Für einen Nachtrag schreibe alle Daten an den Vorstand (info@rudernlinz.at)."),
Err(LogbookCreateError::CantChangeHandoperatableStatusForThisBoat) => Flash::error(Redirect::to("/log"), "Handsteuer-Status dieses Boots kann nicht verändert werden."),
Err(LogbookCreateError::TooFast(km, min)) => Flash::error(Redirect::to("/log"), format!("KM zu groß für die eingegebene Dauer ({km} km in {min} Minuten). Bitte überprüfe deine Start- und Endzeit und versuche es erneut.")),
Err(LogbookCreateError::AlreadyFinalized) => Flash::error(Redirect::to("/log"), "Logbucheintrag wurde bereits abgeschlossen."),
Err(LogbookCreateError::ExternalSteeringPersonMustSteerOrShipmaster) => Flash::error(Redirect::to("/log"), "Wenn du eine 'Externe Steuerperson' hinzufügst, muss diese steuern oder Schiffsführer sein!"),
match Logbook::create(db, data.into_inner(), user, smtp_pw).await {
Ok(msg) => Flash::success(
Redirect::to("/log"),
format!("Ausfahrt erfolgreich hinzugefügt{msg}"),
),
Err(LogbookCreateError::BoatAlreadyOnWater) => {
Flash::error(Redirect::to("/log"), "Boot schon am Wasser")
}
Err(LogbookCreateError::RowerAlreadyOnWater(rower)) => Flash::error(
Redirect::to("/log"),
format!("Ruderer {} schon am Wasser", rower.name),
),
Err(LogbookCreateError::BoatLocked) => Flash::error(Redirect::to("/log"), "Boot gesperrt"),
Err(LogbookCreateError::BoatNotFound) => {
Flash::error(Redirect::to("/log"), "Boot gibt's ned")
}
Err(LogbookCreateError::TooManyRowers(expected, actual)) => Flash::error(
Redirect::to("/log"),
format!(
"Zu viele Ruderer (Boot fasst maximal {expected}, es wurden jedoch {actual} Ruderer ausgewählt)"
),
),
Err(LogbookCreateError::RowerCreateError(rower, e)) => Flash::error(
Redirect::to("/log"),
format!("Fehler bei Ruderer {rower}: {e}"),
),
Err(LogbookCreateError::ArrivalNotAfterDeparture) => Flash::error(
Redirect::to("/log"),
"Ankunftszeit kann nicht vor der Abfahrtszeit sein",
),
Err(LogbookCreateError::UserNotAllowedToUseBoat) => Flash::error(
Redirect::to("/log"),
"Schiffsführer darf dieses Boot nicht verwenden",
),
Err(LogbookCreateError::SteeringPersonNotInRowers) => Flash::error(
Redirect::to("/log"),
"Steuerperson nicht in Liste der Ruderer!",
),
Err(LogbookCreateError::ShipmasterNotInRowers) => Flash::error(
Redirect::to("/log"),
"Schiffsführer nicht in Liste der Ruderer!",
),
Err(LogbookCreateError::NotYourEntry) => {
Flash::error(Redirect::to("/log"), "Nicht deine Ausfahrt!")
}
Err(LogbookCreateError::ArrivalSetButNotRemainingTwo) => Flash::error(
Redirect::to("/log"),
"Ankunftszeit gesetzt aber nicht Distanz + Strecke",
),
Err(LogbookCreateError::OnlyAllowedToEndTripsEndingToday) => Flash::error(
Redirect::to("/log"),
"Nur Ausfahrten, die in der letzten Woche enden dürfen eingetragen werden. Für einen Nachtrag schreibe alle Daten an den Vorstand (info@rudernlinz.at).",
),
Err(LogbookCreateError::CantChangeHandoperatableStatusForThisBoat) => Flash::error(
Redirect::to("/log"),
"Handsteuer-Status dieses Boots kann nicht verändert werden.",
),
Err(LogbookCreateError::TooFast(km, min)) => Flash::error(
Redirect::to("/log"),
format!(
"KM zu groß für die eingegebene Dauer ({km} km in {min} Minuten). Bitte überprüfe deine Start- und Endzeit und versuche es erneut."
),
),
Err(LogbookCreateError::AlreadyFinalized) => Flash::error(
Redirect::to("/log"),
"Logbucheintrag wurde bereits abgeschlossen.",
),
Err(LogbookCreateError::ExternalSteeringPersonMustSteerOrShipmaster) => Flash::error(
Redirect::to("/log"),
"Wenn du eine 'Externe Steuerperson' hinzufügst, muss diese steuern oder Schiffsführer sein!",
),
}
}
@ -312,7 +358,13 @@ async fn update(
let data = data.into_inner();
let Some(logbook) = Logbook::find_by_id(db, data.id).await else {
return Flash::error(Redirect::to("/log"), format!("Logbucheintrag kann nicht bearbeitet werden, da es einen Logbuch-Eintrag mit ID={} nicht gibt", data.id));
return Flash::error(
Redirect::to("/log"),
format!(
"Logbucheintrag kann nicht bearbeitet werden, da es einen Logbuch-Eintrag mit ID={} nicht gibt",
data.id
),
);
};
match logbook.update(db, data.clone(), &user.user).await {
@ -353,14 +405,36 @@ async fn home_logbook(
);
};
match logbook.home(db,user, data.into_inner(), smtp_pw).await {
match logbook.home(db, user, data.into_inner(), smtp_pw).await {
Ok(_) => Flash::success(Redirect::to("/log"), "Ausfahrt korrekt eingetragen"),
Err(LogbookUpdateError::TooManyRowers(expected, actual)) => Flash::error(Redirect::to("/log"), format!("Zu viele Ruderer (Boot fasst maximal {expected}, es wurden jedoch {actual} Ruderer ausgewählt)")),
Err(LogbookUpdateError::OnlyAllowedToEndTripsEndingToday) => Flash::error(Redirect::to("/log"), "Nur Ausfahrten, die heute enden dürfen eingetragen werden. Für einen Nachtrag schreibe alle Daten dem Vorstand an info@rudernlinz.at."),
Err(LogbookUpdateError::TooFast(km, min)) => Flash::error(Redirect::to("/log"), format!("KM zu groß für die eingegebene Dauer ({km} km in {min} Minuten). Bitte überprüfe deine Start- und Endzeit und versuche es erneut.")),
Err(LogbookUpdateError::AlreadyFinalized) => Flash::error(Redirect::to("/log"), "Logbucheintrag wurde bereits abgeschlossen."),
Err(LogbookUpdateError::ExternalSteeringPersonMustSteerOrShipmaster) => Flash::error(Redirect::to("/log"), "Wenn du eine 'Externe Steuerperson' hinzufügst, muss diese steuern oder Schiffsführer sein!"),
Err(LogbookUpdateError::BoatAlreadyOnWater) => Flash::error(Redirect::to("/log"), "Das Boot war in diesem Zeitraum schon am Wasser. Bitte überprüfe das Datum und die Zeit."),
Err(LogbookUpdateError::TooManyRowers(expected, actual)) => Flash::error(
Redirect::to("/log"),
format!(
"Zu viele Ruderer (Boot fasst maximal {expected}, es wurden jedoch {actual} Ruderer ausgewählt)"
),
),
Err(LogbookUpdateError::OnlyAllowedToEndTripsEndingToday) => Flash::error(
Redirect::to("/log"),
"Nur Ausfahrten, die heute enden dürfen eingetragen werden. Für einen Nachtrag schreibe alle Daten dem Vorstand an info@rudernlinz.at.",
),
Err(LogbookUpdateError::TooFast(km, min)) => Flash::error(
Redirect::to("/log"),
format!(
"KM zu groß für die eingegebene Dauer ({km} km in {min} Minuten). Bitte überprüfe deine Start- und Endzeit und versuche es erneut."
),
),
Err(LogbookUpdateError::AlreadyFinalized) => Flash::error(
Redirect::to("/log"),
"Logbucheintrag wurde bereits abgeschlossen.",
),
Err(LogbookUpdateError::ExternalSteeringPersonMustSteerOrShipmaster) => Flash::error(
Redirect::to("/log"),
"Wenn du eine 'Externe Steuerperson' hinzufügst, muss diese steuern oder Schiffsführer sein!",
),
Err(LogbookUpdateError::BoatAlreadyOnWater) => Flash::error(
Redirect::to("/log"),
"Das Boot war in diesem Zeitraum schon am Wasser. Bitte überprüfe das Datum und die Zeit.",
),
Err(e) => Flash::error(
Redirect::to("/log"),
format!("Eintrag {logbook_id} konnte nicht abgesendet werden (Fehler: {e:?})!"),
@ -508,7 +582,7 @@ mod test {
use sqlx::SqlitePool;
use crate::model::logbook::Logbook;
use crate::tera::{log::Boat, User};
use crate::tera::{User, log::Boat};
use crate::testdb;
#[sqlx::test]

View File

@ -1,4 +1,4 @@
use rocket::{get, http::ContentType, routes, Route, State};
use rocket::{Route, State, get, http::ContentType, routes};
use sqlx::SqlitePool;
use crate::model::{event::Event, personal::cal::get_personal_cal, user::User};

View File

@ -2,7 +2,7 @@ use std::{fs::OpenOptions, io::Write};
use chrono::{Datelike, Local};
use rocket::{
catch, catchers,
Build, Data, FromForm, Request, Rocket, State, catch, catchers,
fairing::{AdHoc, Fairing, Info, Kind},
form::Form,
fs::FileServer,
@ -13,7 +13,6 @@ use rocket::{
response::{Flash, Redirect},
routes,
time::{Duration, OffsetDateTime},
Build, Data, FromForm, Request, Rocket, State,
};
use rocket_dyn_templates::Template;
use serde::Deserialize;
@ -21,6 +20,7 @@ use sqlx::SqlitePool;
use tera::Context;
use crate::{
SCHECKBUCH,
model::{
logbook::Logbook,
notification::Notification,
@ -28,7 +28,6 @@ use crate::{
role::Role,
user::{User, UserWithDetails},
},
SCHECKBUCH,
};
pub(crate) mod admin;
@ -202,7 +201,10 @@ async fn blogpost_unpublished(
#[catch(403)] //forbidden
fn forbidden_error() -> Flash<Redirect> {
Flash::error(Redirect::to("/"), "Keine Berechtigung für diese Aktion. Wenn du der Meinung bist, dass du das machen darfst, melde dich bitte bei it@rudernlinz.at.")
Flash::error(
Redirect::to("/"),
"Keine Berechtigung für diese Aktion. Wenn du der Meinung bist, dass du das machen darfst, melde dich bitte bei it@rudernlinz.at.",
)
}
struct Usage {}
@ -328,11 +330,13 @@ mod test {
assert_eq!(response.status(), Status::Ok);
assert!(response
.into_string()
.await
.unwrap()
.contains("Ruderassistent"));
assert!(
response
.into_string()
.await
.unwrap()
.contains("Ruderassistent")
);
}
#[sqlx::test]

View File

@ -1,7 +1,7 @@
use rocket::{
get,
Route, State, get,
response::{Flash, Redirect},
routes, Route, State,
routes,
};
use sqlx::SqlitePool;

View File

@ -1,14 +1,15 @@
use rocket::{
get,
Route, State, get,
request::FlashMessage,
response::{Flash, Redirect},
routes, Route, State,
routes,
};
use rocket_dyn_templates::Template;
use sqlx::SqlitePool;
use tera::Context;
use crate::{
AMOUNT_DAYS_TO_SHOW_TRIPS_AHEAD,
model::{
log::Log,
tripdetails::TripDetails,
@ -16,7 +17,6 @@ use crate::{
user::{AllowedForPlannedTripsUser, User, UserWithDetails},
usertrip::{UserTrip, UserTripDeleteError, UserTripError},
},
AMOUNT_DAYS_TO_SHOW_TRIPS_AHEAD,
};
#[get("/")]
@ -81,14 +81,15 @@ async fn join(
),
)
.await;
}else{
} else {
Log::create(
db,
format!(
"User {} registered the guest '{}' for trip_details.id={}",
user.name, registered_user, trip_details_id
),
).await;
)
.await;
}
Flash::success(Redirect::to("/planned"), "Erfolgreich angemeldet!")
}
@ -98,9 +99,10 @@ async fn join(
Err(UserTripError::AlreadyRegistered) => {
Flash::error(Redirect::to("/planned"), "Du nimmst bereits teil!")
}
Err(UserTripError::AlreadyRegisteredAsCox) => {
Flash::error(Redirect::to("/planned"), "Du hilfst bereits als Steuerperson aus!")
}
Err(UserTripError::AlreadyRegisteredAsCox) => Flash::error(
Redirect::to("/planned"),
"Du hilfst bereits als Steuerperson aus!",
),
Err(UserTripError::CantRegisterAtOwnEvent) => Flash::error(
Redirect::to("/planned"),
"Du kannst bei einer selbst ausgeschriebenen Fahrt nicht mitrudern ;)",
@ -160,7 +162,10 @@ async fn remove_guest(
)
.await;
Flash::error(Redirect::to("/planned"), "Die Bootseinteilung wurde bereits gemacht. Wenn du doch nicht mitrudern kannst, melde dich bitte unbedingt schnellstmöglich bei einer angemeldeten Steuerperson!")
Flash::error(
Redirect::to("/planned"),
"Die Bootseinteilung wurde bereits gemacht. Wenn du doch nicht mitrudern kannst, melde dich bitte unbedingt schnellstmöglich bei einer angemeldeten Steuerperson!",
)
}
Err(UserTripDeleteError::GuestNotParticipating) => {
Flash::error(Redirect::to("/planned"), "Gast nicht angemeldet.")
@ -211,7 +216,10 @@ async fn remove(
)
.await;
Flash::error(Redirect::to("/planned"), "Das Boot ist bereits eingeteilt. Bitte kontaktiere den Schiffsführer (Nummern siehe Signalgruppe) falls du dich doch abmelden willst.")
Flash::error(
Redirect::to("/planned"),
"Das Boot ist bereits eingeteilt. Bitte kontaktiere den Schiffsführer (Nummern siehe Signalgruppe) falls du dich doch abmelden willst.",
)
}
Err(UserTripDeleteError::NotVisibleToUser) => {
Log::create(
@ -223,7 +231,10 @@ async fn remove(
)
.await;
Flash::error(Redirect::to("/planned"), "Abmeldung nicht möglich, da du dieses Event eigentlich gar nicht sehen solltest...")
Flash::error(
Redirect::to("/planned"),
"Abmeldung nicht möglich, da du dieses Event eigentlich gar nicht sehen solltest...",
)
}
Err(_) => {
panic!("Not possible to be here");

View File

@ -1,5 +1,5 @@
use rocket::{get, routes, Route, State};
use rocket_dyn_templates::{context, Template};
use rocket::{Route, State, get, routes};
use rocket_dyn_templates::{Template, context};
use sqlx::SqlitePool;
use crate::model::{

View File

@ -1,10 +1,11 @@
use chrono::NaiveDate;
use rocket::{
FromForm, Route, State,
form::Form,
get, post,
request::FlashMessage,
response::{Flash, Redirect},
routes, FromForm, Route, State,
routes,
};
use rocket_dyn_templates::Template;
use sqlx::SqlitePool;