diff --git a/web/src/endpoints/user/mod.rs b/web/src/endpoints/user/mod.rs index feab61d6..55734fd9 100644 --- a/web/src/endpoints/user/mod.rs +++ b/web/src/endpoints/user/mod.rs @@ -8,6 +8,7 @@ use crate::{ }; use actix_web::HttpResponse; use rinja::Template; +use serde::Deserialize; use sqlx::PgPool; use zxcvbn::{zxcvbn, Score}; @@ -26,9 +27,9 @@ pub mod post_edit; pub mod post_login; pub mod post_new; pub mod post_register; +pub mod post_resend_registration; pub mod post_reset; pub mod post_toggle; -pub mod post_resend_registration; #[derive(Template)] #[template(path = "user/new_or_edit.html")] @@ -45,6 +46,21 @@ pub struct NewOrEditUserTemplate { area_id: Option, } +#[derive(Deserialize)] +#[cfg_attr(test, derive(serde::Serialize))] +struct NewOrEditUserForm { + email: String, + name: String, + role: u8, + #[serde(rename(deserialize = "is-posten"))] + is_posten: Option, + #[serde(rename(deserialize = "is-wachhabender"))] + is_wachhabender: Option, + #[serde(rename(deserialize = "is-fuehrungsassistent"))] + is_fuehrungsassistent: Option, + area: Option, +} + #[derive(Template)] #[template(path = "user/change_password.html")] struct ResetPasswordTemplate<'a> { diff --git a/web/src/endpoints/user/post_edit.rs b/web/src/endpoints/user/post_edit.rs index 961ceaad..95b0c22e 100644 --- a/web/src/endpoints/user/post_edit.rs +++ b/web/src/endpoints/user/post_edit.rs @@ -1,30 +1,19 @@ use actix_web::{http::header::LOCATION, web, HttpResponse, Responder}; use garde::Validate; -use serde::Deserialize; use sqlx::PgPool; use crate::{ - endpoints::IdPath, - models::{Area, Role, User, UserChangeset}, + endpoints::{user::NewOrEditUserForm, IdPath}, + models::{Area, Function, Role, User, UserChangeset}, utils::ApplicationError, }; -#[derive(Deserialize)] -#[cfg_attr(test, derive(serde::Serialize))] -pub struct EditUserForm { - email: String, - name: String, - role: u8, - function: u8, - area: Option, -} - #[actix_web::post("/users/edit/{id}")] pub async fn post_edit( user: web::ReqData, pool: web::Data, path: web::Path, - form: web::Form, + form: web::Form, ) -> Result { if user.role != Role::AreaManager && user.role != Role::Admin { return Err(ApplicationError::Unauthorized); @@ -47,11 +36,25 @@ pub async fn post_edit( return Err(ApplicationError::Unauthorized); } + let mut functions = Vec::with_capacity(3); + + if form.is_posten.unwrap_or(false) { + functions.push(Function::Posten); + } + + if form.is_wachhabender.unwrap_or(false) { + functions.push(Function::Wachhabender); + } + + if form.is_fuehrungsassistent.unwrap_or(false) { + functions.push(Function::Fuehrungsassistent); + } + let changeset = UserChangeset { name: form.name.clone(), email: form.email.clone(), role: form.role.try_into()?, - function: form.function.try_into()?, + functions, area_id, }; @@ -69,8 +72,7 @@ pub async fn post_edit( #[cfg(test)] mod tests { - use super::*; - use crate::{models::*, utils::test_helper::*}; + use crate::{endpoints::user::NewOrEditUserForm, models::*, utils::test_helper::*}; use brass_macros::db_test; use fake::{ faker::{internet::en::SafeEmail, name::en::Name}, @@ -94,11 +96,13 @@ mod tests { let new_name: String = Name().fake(); let new_mail: String = SafeEmail().fake(); - let form = EditUserForm { + let form = NewOrEditUserForm { name: new_name.clone(), email: new_mail.clone(), role: Role::AreaManager as u8, - function: Function::Fuehrungsassistent as u8, + is_posten: None, + is_wachhabender: None, + is_fuehrungsassistent: Some(true), area: Some(2), }; @@ -127,11 +131,13 @@ mod tests { user_area: 1, }; - let form = EditUserForm { + let form = NewOrEditUserForm { name: "".to_string(), email: "".to_string(), role: Role::AreaManager as u8, - function: Function::Fuehrungsassistent as u8, + is_posten: None, + is_wachhabender: None, + is_fuehrungsassistent: Some(true), area: Some(1), }; diff --git a/web/src/endpoints/user/post_new.rs b/web/src/endpoints/user/post_new.rs index bfae1226..e5e6c8cb 100644 --- a/web/src/endpoints/user/post_new.rs +++ b/web/src/endpoints/user/post_new.rs @@ -1,28 +1,19 @@ use actix_web::{http::header::LOCATION, web, HttpResponse, Responder}; use garde::Validate; -use serde::Deserialize; use sqlx::PgPool; use crate::{ + endpoints::user::NewOrEditUserForm, mail::Mailer, models::{Function, Registration, Role, User, UserChangeset}, utils::ApplicationError, }; -#[derive(Deserialize)] -pub struct NewUserForm { - email: String, - name: String, - role: u8, - function: u8, - area: Option, -} - #[actix_web::post("/users/new")] pub async fn post_new( user: web::ReqData, pool: web::Data, - form: web::Form, + form: web::Form, mailer: web::Data, ) -> Result { if user.role != Role::AreaManager && user.role != Role::Admin { @@ -36,29 +27,39 @@ pub async fn post_new( } let role = Role::try_from(form.role)?; - let function = Function::try_from(form.function)?; + let mut functions = Vec::with_capacity(3); + + if form.is_posten.unwrap_or(false) { + functions.push(Function::Posten); + } + + if form.is_wachhabender.unwrap_or(false) { + functions.push(Function::Wachhabender); + } + + if form.is_fuehrungsassistent.unwrap_or(false) { + functions.push(Function::Fuehrungsassistent); + } let changeset = UserChangeset { name: form.name.clone(), email: form.email.clone(), role, - function, - area_id + functions, + area_id, }; if let Err(e) = changeset.validate() { return Ok(HttpResponse::BadRequest().body(e.to_string())); }; - let id = User::create( - pool.get_ref(), - changeset - ) - .await?; + let id = User::create(pool.get_ref(), changeset).await?; let registration = Registration::insert_new_for_user(pool.get_ref(), id).await?; let new_user = User::read_by_id(pool.get_ref(), id).await?.unwrap(); - mailer.send_registration_mail(&new_user, ®istration.token).await?; + mailer + .send_registration_mail(&new_user, ®istration.token) + .await?; Ok(HttpResponse::Found() .insert_header((LOCATION, "/users")) diff --git a/web/src/models/user.rs b/web/src/models/user.rs index 43732e9b..483f26ed 100644 --- a/web/src/models/user.rs +++ b/web/src/models/user.rs @@ -30,7 +30,7 @@ impl User { changeset.name, changeset.email, changeset.role as Role, - changeset.function as Function, + changeset.functions.as_slice() as &[Function], changeset.area_id ) .fetch_one(pool) @@ -285,7 +285,7 @@ impl User { changeset.name, changeset.email, changeset.role as Role, - changeset.function as Function, + changeset.functions.as_slice() as &[Function], changeset.area_id, id ) diff --git a/web/src/models/user_changeset.rs b/web/src/models/user_changeset.rs index fe45261e..413858e4 100644 --- a/web/src/models/user_changeset.rs +++ b/web/src/models/user_changeset.rs @@ -5,7 +5,7 @@ use garde::Validate; use super::{Function, Role}; -#[derive(Validate)] +#[derive(Debug, Validate)] #[cfg_attr(test, derive(Dummy))] #[garde(allow_unvalidated)] pub struct UserChangeset { @@ -16,8 +16,8 @@ pub struct UserChangeset { pub email: String, #[cfg_attr(test, dummy(expr = "Role::Staff"))] pub role: Role, - #[cfg_attr(test, dummy(expr = "Function::Posten"))] - pub function: Function, + #[cfg_attr(test, dummy(expr = "vec![Function::Posten]"))] + pub functions: Vec, /// check before: must exist and user can create other user for this area #[cfg_attr(test, dummy(expr = "1"))] pub area_id: i32, diff --git a/web/templates/user/new_or_edit.html b/web/templates/user/new_or_edit.html index 0e5d4ff0..f55a6d0b 100644 --- a/web/templates/user/new_or_edit.html +++ b/web/templates/user/new_or_edit.html @@ -64,12 +64,28 @@
-
+
-
- -
+ +
+
+ +
+
+
@@ -87,8 +103,8 @@