From e87feca855ee7e65010922a7b40d01abd4640def Mon Sep 17 00:00:00 2001 From: Max Hohlfeld Date: Thu, 29 Aug 2024 22:33:22 +0200 Subject: [PATCH] refactor: user management --- migrations/20230609121618_initial.sql | 10 ++ src/endpoints/user/delete.rs | 4 +- src/endpoints/user/get_edit.rs | 42 +++---- src/endpoints/user/get_new.rs | 30 ++--- src/endpoints/user/mod.rs | 43 ++++--- src/endpoints/user/patch.rs | 1 + src/endpoints/user/post_new.rs | 2 +- src/endpoints/user/post_reset.rs | 4 +- src/endpoints/user/post_toggle.rs | 73 +++++++++--- src/filters.rs | 24 +++- templates/user/edit.html | 127 -------------------- templates/user/new.html | 126 -------------------- templates/user/new_or_edit.html | 141 +++++++++++++++++++++++ templates/user/overview.html | 160 +++++++++++--------------- templates/user/profile.html | 6 +- 15 files changed, 367 insertions(+), 426 deletions(-) delete mode 100644 templates/user/edit.html delete mode 100644 templates/user/new.html create mode 100644 templates/user/new_or_edit.html diff --git a/migrations/20230609121618_initial.sql b/migrations/20230609121618_initial.sql index 62d4463e..74490f00 100644 --- a/migrations/20230609121618_initial.sql +++ b/migrations/20230609121618_initial.sql @@ -98,3 +98,13 @@ CREATE UNLOGGED TABLE passwordReset ); CREATE INDEX passwordReset_token_idx ON passwordReset (token); + +CREATE UNLOGGED TABLE registration +( + id SERIAL PRIMARY KEY, + token TEXT UNIQUE NOT NULL, + userId INTEGER NOT NULL REFERENCES user_ (id), + expires TIMESTAMP NOT NULL +); + +CREATE INDEX registration_token_idx ON registration (token); diff --git a/src/endpoints/user/delete.rs b/src/endpoints/user/delete.rs index 7ff86d95..36705260 100644 --- a/src/endpoints/user/delete.rs +++ b/src/endpoints/user/delete.rs @@ -4,7 +4,7 @@ use sqlx::PgPool; use crate::{endpoints::IdPath, models::{Role, User}}; -#[actix_web::delete("/users/delete/{id}")] +#[actix_web::delete("/users/{id}")] pub async fn delete(user: Identity, pool: web::Data, path: web::Path) -> impl Responder { let current_user = User::read_by_id(pool.get_ref(), user.id().unwrap().parse().unwrap()) .await @@ -21,7 +21,7 @@ pub async fn delete(user: Identity, pool: web::Data, path: web::Path>, - id: i32, - email: String, - name: String, - role: u8, - function: u8, - area_id: i32 -} +use crate::{ + endpoints::{user::NewOrEditUserTemplate, IdPath}, + models::{Area, Role, User}, +}; #[actix_web::get("/users/edit/{id}")] -pub async fn get_edit(user: Identity, pool: web::Data, path: web::Path) -> impl Responder { - let current_user = User::read_by_id(pool.get_ref(), user.id().unwrap().parse().unwrap()).await.unwrap(); +pub async fn get_edit( + user: web::ReqData, + pool: web::Data, + path: web::Path, +) -> impl Responder { let mut areas = None; - if current_user.role != Role::AreaManager && current_user.role != Role::Admin { + if user.role != Role::AreaManager && user.role != Role::Admin { return HttpResponse::Unauthorized().finish(); } - if current_user.role == Role::Admin { + if user.role == Role::Admin { areas = Some(Area::read_all(pool.get_ref()).await.unwrap()); } if let Ok(user_in_db) = User::read_by_id(pool.get_ref(), path.id).await { - let template = EditUserTemplate { user: current_user, id: user_in_db.id, areas, email: user_in_db.email, name: user_in_db.name, role: user_in_db.role as u8, function: user_in_db.function as u8, area_id: user_in_db.area_id }; + let template = NewOrEditUserTemplate { + user: user.into_inner(), + id: Some(user_in_db.id), + areas, + email: Some(user_in_db.email), + name: Some(user_in_db.name), + role: Some(user_in_db.role as u8), + function: Some(user_in_db.function as u8), + area_id: Some(user_in_db.area_id), + }; return template.to_response(); } diff --git a/src/endpoints/user/get_new.rs b/src/endpoints/user/get_new.rs index 86274839..45d296b9 100644 --- a/src/endpoints/user/get_new.rs +++ b/src/endpoints/user/get_new.rs @@ -1,28 +1,30 @@ -use actix_identity::Identity; use actix_web::{web, Responder}; -use askama::Template; use askama_actix::TemplateToResponse; use sqlx::PgPool; -use crate::models::{Area, Role, User}; - -#[derive(Template)] -#[template(path = "user/new.html")] -pub struct NewUserTemplate { - user: User, - areas: Option> -} +use crate::{ + endpoints::user::NewOrEditUserTemplate, + models::{Area, Role, User}, +}; #[actix_web::get("/users/new")] -pub async fn get_new(user: Identity, pool: web::Data) -> impl Responder { - let current_user = User::read_by_id(pool.get_ref(), user.id().unwrap().parse().unwrap()).await.unwrap(); +pub async fn get_new(user: web::ReqData, pool: web::Data) -> impl Responder { let mut areas: Option> = None; - if current_user.role == Role::Admin { + if user.role == Role::Admin { areas = Some(Area::read_all(pool.get_ref()).await.unwrap()) } - let template = NewUserTemplate { user: current_user, areas }; + let template = NewOrEditUserTemplate { + user: user.into_inner(), + areas, + id: None, + email: None, + name: None, + role: None, + function: None, + area_id: None, + }; template.to_response() } diff --git a/src/endpoints/user/mod.rs b/src/endpoints/user/mod.rs index 8303493a..0a6f68c5 100644 --- a/src/endpoints/user/mod.rs +++ b/src/endpoints/user/mod.rs @@ -1,16 +1,33 @@ -pub mod get_overview; -pub mod get_new; -pub mod post_new; -pub mod get_edit; -pub mod post_edit; -pub mod patch; +use crate::filters; +use crate::models::{Area, Role, User}; +use askama::Template; + pub mod delete; -pub mod get_logout; -pub mod get_login; -pub mod post_login; -pub mod get_reset; -pub mod post_reset; -pub mod get_profile; -pub mod post_toggle; pub mod get_changepassword; +pub mod get_edit; +pub mod get_login; +pub mod get_logout; +pub mod get_new; +pub mod get_overview; +pub mod get_profile; +pub mod get_reset; +pub mod patch; pub mod post_changepassword; +pub mod post_edit; +pub mod post_login; +pub mod post_new; +pub mod post_reset; +pub mod post_toggle; + +#[derive(Template)] +#[template(path = "user/new_or_edit.html")] +pub struct NewOrEditUserTemplate { + user: User, + areas: Option>, + id: Option, + email: Option, + name: Option, + role: Option, + function: Option, + area_id: Option, +} diff --git a/src/endpoints/user/patch.rs b/src/endpoints/user/patch.rs index 19d14525..fce3753d 100644 --- a/src/endpoints/user/patch.rs +++ b/src/endpoints/user/patch.rs @@ -15,6 +15,7 @@ pub struct JsonPatchDoc { value: Value, } +// TODO: deprecated route #[actix_web::patch("/users/edit/{id}")] pub async fn patch( user: web::ReqData, diff --git a/src/endpoints/user/post_new.rs b/src/endpoints/user/post_new.rs index 2e98c258..9a12816d 100644 --- a/src/endpoints/user/post_new.rs +++ b/src/endpoints/user/post_new.rs @@ -11,7 +11,7 @@ pub struct NewUserForm { name: String, password: String, role: u8, - function: u8, + function: u8, area: Option } diff --git a/src/endpoints/user/post_reset.rs b/src/endpoints/user/post_reset.rs index 308aea70..09950ef6 100644 --- a/src/endpoints/user/post_reset.rs +++ b/src/endpoints/user/post_reset.rs @@ -105,7 +105,7 @@ Viele Grüße"##, user.name, reset_url)) } } - let user = User::read_by_id(pool.get_ref(), token.as_ref().unwrap().id) + let user = User::read_by_id(pool.get_ref(), token.as_ref().unwrap().userid) .await .unwrap(); let mut split_names: Vec<&str> = user.name.as_str().split_whitespace().collect(); @@ -143,7 +143,7 @@ Viele Grüße"##, user.name, reset_url)) User::update( pool.get_ref(), - token.as_ref().unwrap().id, + token.as_ref().unwrap().userid, None, None, Some(&hash), diff --git a/src/endpoints/user/post_toggle.rs b/src/endpoints/user/post_toggle.rs index b91c0782..b2266cad 100644 --- a/src/endpoints/user/post_toggle.rs +++ b/src/endpoints/user/post_toggle.rs @@ -19,7 +19,7 @@ pub async fn post( path: web::Path, query: web::Query, ) -> impl Responder { - if user.id != path.id && (user.role != Role::Admin || user.role != Role::AreaManager) { + if user.id != path.id && user.role != Role::Admin && user.role != Role::AreaManager { return HttpResponse::Unauthorized().finish(); } @@ -30,21 +30,61 @@ pub async fn post( }; match query.field.as_str() { - "locked" => User::update( - pool.get_ref(), - user.id, - None, - None, - None, - None, - None, - None, - None, - None, - Some(!user.locked), - ) - .await - .unwrap(), + "locked" => { + User::update( + pool.get_ref(), + user.id, + None, + None, + None, + None, + None, + None, + None, + None, + Some(!user.locked), + ) + .await + .unwrap(); + + if !user.locked { + return HttpResponse::Ok().body(format!( + r##" + + + + + Entsperren +
ja
+ "##, + id = user.id)); + } else { + return HttpResponse::Ok().body(format!( + r##" + + + + + Sperren +
nein
+ "##, + id = user.id)); + } + } "receiveNotifications" => { User::update( pool.get_ref(), @@ -61,7 +101,6 @@ pub async fn post( ) .await .unwrap(); - //return HttpResponse::Ok().body(""); } _ => return HttpResponse::BadRequest().body("Other PATCH paths are not supported!"), }; diff --git a/src/filters.rs b/src/filters.rs index 0a30cd70..23fb457a 100644 --- a/src/filters.rs +++ b/src/filters.rs @@ -1,9 +1,5 @@ pub fn show_area_query(a: &Option, first: bool) -> ::askama::Result { - let char = if first { - '?' - } else { - '&' - }; + let char = if first { '?' } else { '&' }; if let Some(a) = a { return Ok(format!("{}area={}", char, a)); @@ -17,7 +13,25 @@ pub fn cond_show(show: &bool, text: &str) -> askama::Result { Ok(String::from(text)) } else { Ok(String::new()) + }; +} + +pub fn insert_value(option: &Option) -> askama::Result { + if let Some(val) = option { + println!("{val}"); + let s = format!(r#"value="{val}""#); + println!("{s}"); + return Ok(s); } + + Ok(String::new()) +} + +pub fn is_some_and_eq(option: &Option, other: &T) -> askama::Result +where + T: Eq +{ + Ok(option.as_ref().is_some_and(|x| x == other)) } pub fn invert(b: &bool) -> askama::Result { diff --git a/templates/user/edit.html b/templates/user/edit.html deleted file mode 100644 index c2ca83f5..00000000 --- a/templates/user/edit.html +++ /dev/null @@ -1,127 +0,0 @@ -{% extends "nav.html" %} - -{% block content %} -
-
-
-

Nutzer '{{ name }}' bearbeiten

- -
-
- -
-
-
-
- -
-
-
-
- -
-
- -
-
-
-
- -
-
-
-
- -
-
- -
-
-
-
- -
-
-
-
- -
-
- -
-
-
-
-
- -
-
-
-
-
- -
-
- -
-
-
-
-
- -
-
-
-
-
- - {% if user.role == Role::Admin %} -
-
- -
-
-
-
-
- -
-
-
-
-
- {% endif %} - -
-
-
-
-
- -
-
- Zurück -
-
-
-
- -
-
-
- - -{% endblock %} diff --git a/templates/user/new.html b/templates/user/new.html deleted file mode 100644 index 8177df66..00000000 --- a/templates/user/new.html +++ /dev/null @@ -1,126 +0,0 @@ -{% extends "nav.html" %} - -{% block content %} -
-
-
-

Neuen Nutzer anlegen

- -
-
- -
-
-
-
- -
-
-
-
- -
-
- -
-
-
-
- -
-
-
-
- -
-
- -
-
-
-
- -
-
-
-
- -
-
- -
-
-
-
-
- -
-
-
-
-
- -
-
- -
-
-
-
-
- -
-
-
-
-
- - {% if user.role == Role::Admin %} -
-
- -
-
-
-
-
- -
-
-
-
-
- {% endif %} - -
-
-
-
-
- -
-
- Zurück -
-
-
-
- -
-
-
- - -{% endblock %} diff --git a/templates/user/new_or_edit.html b/templates/user/new_or_edit.html new file mode 100644 index 00000000..34da3611 --- /dev/null +++ b/templates/user/new_or_edit.html @@ -0,0 +1,141 @@ +{% extends "nav.html" %} + +{% block content %} +
+
+ {% if id.is_some() %} +
+

Nutzer '{{ name.as_ref().unwrap() }}' bearbeiten

+ {% else %} + +

Neuen Nutzer anlegen

+ {% endif %} + +
+
+ +
+
+
+
+ +
+
+
+
+ +
+
+ +
+
+
+
+ +
+
+
+
+ +
+
+ +
+
+
+
+
+ +
+
+
+
+
+ +
+
+ +
+
+
+
+
+ +
+
+
+
+
+ + {% if user.role == Role::Admin %} +
+
+ +
+
+
+
+
+ +
+
+
+
+
+ {% endif %} + +
+
+
+
+
+ +
+ +
+
+
+ +
+
+
+ +{% endblock %} diff --git a/templates/user/overview.html b/templates/user/overview.html index b293f934..ef6e57c5 100644 --- a/templates/user/overview.html +++ b/templates/user/overview.html @@ -10,15 +10,17 @@ - {% if users.len() == 0 %} -
-
keine Nutzer vorhanden
-
- {% else %}
@@ -36,8 +38,8 @@ - {% for u in users %} - + {% for u in users %} + @@ -46,22 +48,22 @@ {% if user.role == Role::Admin %} @@ -70,90 +72,58 @@ {% endif %} - + - {% endfor %} + {% endfor %}
{{ u.email }} {% match u.role %} - {% when Role::Staff %} - Nutzer - {% when Role::AreaManager %} - Bereichsleiter - {% when Role::Admin %} - Admin - {% else %} + {% when Role::Staff %} + Personal + {% when Role::AreaManager %} + Bereichsleiter + {% when Role::Admin %} + Admin + {% else %} {% endmatch %} {% match u.function %} - {% when Function::Posten %} - Posten - {% when Function::Wachhabender %} - Wachhabender - {% else %} + {% when Function::Posten %} + Posten + {% when Function::Wachhabender %} + Wachhabender + {% else %} {% endmatch %} - {% if u.last_login.is_some() %} - {{ u.last_login.as_ref().unwrap() }} - {% else %} + {% if u.last_login.is_some() %} + {% let format = "%d.%m.%Y %H:%M:%S" %} + {{ u.last_login.as_ref().unwrap().format(format) }} + {% else %} nie - {% endif %} + {% endif %} - {% if u.locked %} - ja - {% else %} - nein - {% endif %} - -
- - Bearbeiten - +
+ {% if u.locked %} + ja + {% else %} + nein + {% endif %}
+ {% if user.id != u.id %} +
+ + + + + + + + Bearbeiten + + +
+ {% endif %} +
- {% endif %} - - - {% endblock %} diff --git a/templates/user/profile.html b/templates/user/profile.html index 12f05bc2..58d8a81e 100644 --- a/templates/user/profile.html +++ b/templates/user/profile.html @@ -43,7 +43,7 @@
{% match user.role %} {% when Role::Staff %} - Nutzer + Personal {% when Role::AreaManager %} Bereichsleiter {% when Role::Admin %} @@ -64,9 +64,9 @@
{% match user.function %} {% when Function::Posten %} - Posten + Posten {% when Function::Wachhabender %} - Wachhabender + Wachhabender {% else %} {% endmatch %}