refactor: rewrite todos and test
This commit is contained in:
parent
31b09a1c76
commit
0844cc5a17
17
Cargo.lock
generated
17
Cargo.lock
generated
@ -691,6 +691,7 @@ dependencies = [
|
|||||||
"change-detection",
|
"change-detection",
|
||||||
"chrono",
|
"chrono",
|
||||||
"dotenv",
|
"dotenv",
|
||||||
|
"fake",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"idna 1.0.2",
|
"idna 1.0.2",
|
||||||
"insta",
|
"insta",
|
||||||
@ -1079,6 +1080,12 @@ dependencies = [
|
|||||||
"unicode-xid",
|
"unicode-xid",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "deunicode"
|
||||||
|
version = "1.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "339544cc9e2c4dc3fc7149fd630c5f22263a4fdf18a98afd0075784968b5cf00"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "digest"
|
name = "digest"
|
||||||
version = "0.10.7"
|
version = "0.10.7"
|
||||||
@ -1208,6 +1215,16 @@ dependencies = [
|
|||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fake"
|
||||||
|
version = "3.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "661cb0601b5f4050d1e65452c5b0ea555c0b3e88fb5ed7855906adc6c42523ef"
|
||||||
|
dependencies = [
|
||||||
|
"deunicode",
|
||||||
|
"rand",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fancy-regex"
|
name = "fancy-regex"
|
||||||
version = "0.13.0"
|
version = "0.13.0"
|
||||||
|
@ -43,3 +43,4 @@ change-detection = "1.2.0"
|
|||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
insta = "1.41.1"
|
insta = "1.41.1"
|
||||||
|
fake = "3.0.1"
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use rinja::Template;
|
use rinja::Template;
|
||||||
use serde::Deserialize;
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::models::{Area, Location, Role, User};
|
use crate::models::{Area, Location, Role, User};
|
||||||
use crate::filters;
|
use crate::filters;
|
||||||
@ -19,7 +19,7 @@ pub struct LocationTemplate {
|
|||||||
location: Option<Location>,
|
location: Option<Location>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize, Serialize)]
|
||||||
pub struct LocationForm {
|
pub struct LocationForm {
|
||||||
name: String,
|
name: String,
|
||||||
area: Option<i32>,
|
area: Option<i32>,
|
||||||
|
@ -1,11 +1,16 @@
|
|||||||
use actix_web::{http::header::LOCATION, web, HttpResponse, Responder};
|
use actix_web::{http::header::LOCATION, web, HttpResponse, Responder};
|
||||||
|
use brass_macros::db_test;
|
||||||
use sqlx::PgPool;
|
use sqlx::PgPool;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
endpoints::location::LocationForm,
|
endpoints::location::LocationForm,
|
||||||
models::{Location, Role, User}, utils::ApplicationError,
|
models::{Location, Role, User},
|
||||||
|
utils::ApplicationError,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
use crate::utils::test_helper::{test_post, DbTestContext, RequestConfig, StatusCode};
|
||||||
|
|
||||||
#[actix_web::post("/locations/new")]
|
#[actix_web::post("/locations/new")]
|
||||||
pub async fn post(
|
pub async fn post(
|
||||||
user: web::ReqData<User>,
|
user: web::ReqData<User>,
|
||||||
@ -22,17 +27,66 @@ pub async fn post(
|
|||||||
area_id = form.area.unwrap();
|
area_id = form.area.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: rework
|
Location::create(pool.get_ref(), &form.name, area_id).await?;
|
||||||
match Location::create(pool.get_ref(), &form.name, area_id).await {
|
|
||||||
Ok(_) => {
|
return Ok(HttpResponse::Found()
|
||||||
return Ok(HttpResponse::Found()
|
.insert_header((LOCATION, "/locations"))
|
||||||
.insert_header((LOCATION, "/locations"))
|
.insert_header(("HX-LOCATION", "/locations"))
|
||||||
.insert_header(("HX-LOCATION", "/locations"))
|
.finish());
|
||||||
.finish())
|
}
|
||||||
}
|
|
||||||
Err(err) => {
|
#[db_test]
|
||||||
println!("{}", err);
|
async fn works_when_user_is_admin(context: &DbTestContext) {
|
||||||
return Ok(HttpResponse::InternalServerError().finish());
|
let app = context.app().await;
|
||||||
}
|
let config = RequestConfig {
|
||||||
}
|
uri: "/locations/new".to_string(),
|
||||||
|
role: Role::Admin,
|
||||||
|
function: crate::models::Function::Posten,
|
||||||
|
user_area: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
let form = LocationForm {
|
||||||
|
name: "Hauptbahnhof".to_string(),
|
||||||
|
area: Some(1),
|
||||||
|
};
|
||||||
|
|
||||||
|
let response = test_post(&context.db_pool, app, &config, form).await;
|
||||||
|
assert_eq!(StatusCode::FOUND, response.status());
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
"Hauptbahnhof".to_string(),
|
||||||
|
Location::read_by_id(&context.db_pool, 1)
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.unwrap()
|
||||||
|
.name
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[db_test]
|
||||||
|
async fn uses_area_id_of_area_manager(context: &DbTestContext) {
|
||||||
|
let app = context.app().await;
|
||||||
|
let config = RequestConfig {
|
||||||
|
uri: "/locations/new".to_string(),
|
||||||
|
role: Role::AreaManager,
|
||||||
|
function: crate::models::Function::Posten,
|
||||||
|
user_area: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
let form = LocationForm {
|
||||||
|
name: "Hauptbahnhof".to_string(),
|
||||||
|
area: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
let response = test_post(&context.db_pool, app, &config, form).await;
|
||||||
|
assert_eq!(StatusCode::FOUND, response.status());
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
"Hauptbahnhof".to_string(),
|
||||||
|
Location::read_by_id(&context.db_pool, 1)
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.unwrap()
|
||||||
|
.name
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,24 @@
|
|||||||
use actix_identity::Identity;
|
|
||||||
use actix_web::{http::header::LOCATION, web, HttpResponse, Responder};
|
use actix_web::{http::header::LOCATION, web, HttpResponse, Responder};
|
||||||
use serde::Deserialize;
|
use brass_macros::db_test;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
use sqlx::PgPool;
|
use sqlx::PgPool;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
endpoints::IdPath,
|
endpoints::IdPath,
|
||||||
models::{Function, Role, User},
|
models::{Function, Role, User},
|
||||||
|
utils::ApplicationError,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[cfg(test)]
|
||||||
|
use crate::utils::test_helper::{test_post, DbTestContext, RequestConfig, StatusCode};
|
||||||
|
#[cfg(test)]
|
||||||
|
use fake::{
|
||||||
|
faker::{internet::raw::SafeEmail, name::raw::Name},
|
||||||
|
locales::EN,
|
||||||
|
Fake,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize)]
|
||||||
pub struct EditUserForm {
|
pub struct EditUserForm {
|
||||||
email: String,
|
email: String,
|
||||||
name: String,
|
name: String,
|
||||||
@ -19,77 +29,167 @@ pub struct EditUserForm {
|
|||||||
|
|
||||||
#[actix_web::post("/users/edit/{id}")]
|
#[actix_web::post("/users/edit/{id}")]
|
||||||
pub async fn post_edit(
|
pub async fn post_edit(
|
||||||
user: Identity,
|
user: web::ReqData<User>,
|
||||||
pool: web::Data<PgPool>,
|
pool: web::Data<PgPool>,
|
||||||
path: web::Path<IdPath>,
|
path: web::Path<IdPath>,
|
||||||
form: web::Form<EditUserForm>,
|
form: web::Form<EditUserForm>,
|
||||||
) -> impl Responder {
|
) -> Result<impl Responder, ApplicationError> {
|
||||||
// TODO: rewrite
|
if user.role != Role::AreaManager && user.role != Role::Admin {
|
||||||
let current_user = User::read_by_id(pool.get_ref(), user.id().unwrap().parse().unwrap())
|
return Err(ApplicationError::Unauthorized);
|
||||||
.await
|
|
||||||
.unwrap().unwrap();
|
|
||||||
|
|
||||||
if current_user.role != Role::AreaManager && current_user.role != Role::Admin {
|
|
||||||
return HttpResponse::Unauthorized().finish();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(user_in_db) = User::read_by_id(pool.get_ref(), path.id).await.unwrap() {
|
if user.id == path.id {
|
||||||
if current_user.role == Role::AreaManager && current_user.area_id != user_in_db.area_id {
|
return Ok(HttpResponse::BadRequest().finish());
|
||||||
return HttpResponse::Unauthorized().finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut changed = false;
|
|
||||||
|
|
||||||
let email = if user_in_db.email != form.email {
|
|
||||||
changed = true;
|
|
||||||
Some(form.email.as_str())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
let name = if user_in_db.name != form.name {
|
|
||||||
changed = true;
|
|
||||||
Some(form.name.as_str())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
let role = if user_in_db.role as u8 != form.role {
|
|
||||||
if let Ok(r) = Role::try_from(form.role) {
|
|
||||||
changed = true;
|
|
||||||
Some(r)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
let function = if user_in_db.function as u8 != form.function {
|
|
||||||
if let Ok(f) = Function::try_from(form.function) {
|
|
||||||
changed = true;
|
|
||||||
Some(f)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
let area = if current_user.role == Role::Admin && form.area.is_some() && user_in_db.area_id != form.area.unwrap() {
|
|
||||||
changed = true;
|
|
||||||
Some(form.area.unwrap())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
if changed {
|
|
||||||
match User::update(pool.get_ref(), path.id, email, name, None, None, role, function, area, None, None).await {
|
|
||||||
Ok(_) => return HttpResponse::Found().insert_header((LOCATION, "/users")).finish(),
|
|
||||||
Err(err) => println!("{}", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return HttpResponse::BadRequest().body("Fehler beim Bearbeiten des Nutzers");
|
let Some(user_in_db) = User::read_by_id(pool.get_ref(), path.id).await? else {
|
||||||
|
return Ok(HttpResponse::NotFound().finish());
|
||||||
|
};
|
||||||
|
|
||||||
|
if user.role == Role::AreaManager && user.area_id != user_in_db.area_id {
|
||||||
|
return Err(ApplicationError::Unauthorized);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut changed = false;
|
||||||
|
|
||||||
|
let email = if user_in_db.email != form.email {
|
||||||
|
changed = true;
|
||||||
|
Some(form.email.as_str())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let name = if user_in_db.name != form.name {
|
||||||
|
changed = true;
|
||||||
|
Some(form.name.as_str())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let role = if user_in_db.role as u8 != form.role {
|
||||||
|
if let Ok(r) = Role::try_from(form.role) {
|
||||||
|
changed = true;
|
||||||
|
Some(r)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let function = if user_in_db.function as u8 != form.function {
|
||||||
|
if let Ok(f) = Function::try_from(form.function) {
|
||||||
|
changed = true;
|
||||||
|
Some(f)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let area = if user.role == Role::Admin
|
||||||
|
&& form.area.is_some()
|
||||||
|
&& user_in_db.area_id != form.area.unwrap()
|
||||||
|
{
|
||||||
|
changed = true;
|
||||||
|
Some(form.area.unwrap())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
if changed {
|
||||||
|
User::update(
|
||||||
|
pool.get_ref(),
|
||||||
|
path.id,
|
||||||
|
email,
|
||||||
|
name,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
role,
|
||||||
|
function,
|
||||||
|
area,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(HttpResponse::Found()
|
||||||
|
.insert_header((LOCATION, "/users"))
|
||||||
|
.insert_header(("HX-LOCATION", "/users"))
|
||||||
|
.finish())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[db_test]
|
||||||
|
async fn works_when_user_is_admin(context: &DbTestContext) {
|
||||||
|
User::create(
|
||||||
|
&context.db_pool,
|
||||||
|
&Name(EN).fake::<String>(),
|
||||||
|
&SafeEmail(EN).fake::<String>(),
|
||||||
|
Role::Staff,
|
||||||
|
Function::Posten,
|
||||||
|
1,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
crate::models::Area::create(&context.db_pool, "Süd")
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let app = context.app().await;
|
||||||
|
let config = RequestConfig {
|
||||||
|
uri: "/users/edit/1".to_string(),
|
||||||
|
role: Role::Admin,
|
||||||
|
function: crate::models::Function::Posten,
|
||||||
|
user_area: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
let new_name: String = Name(EN).fake();
|
||||||
|
let new_mail: String = SafeEmail(EN).fake();
|
||||||
|
|
||||||
|
let form = EditUserForm {
|
||||||
|
name: new_name.clone(),
|
||||||
|
email: new_mail.clone(),
|
||||||
|
role: Role::AreaManager as u8,
|
||||||
|
function: Function::Fuehrungsassistent as u8,
|
||||||
|
area: Some(2),
|
||||||
|
};
|
||||||
|
|
||||||
|
let response = test_post(&context.db_pool, app, &config, form).await;
|
||||||
|
assert_eq!(StatusCode::FOUND, response.status());
|
||||||
|
|
||||||
|
let updated_user = User::read_by_id(&context.db_pool, 1)
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
assert_eq!(new_name, updated_user.name);
|
||||||
|
assert_eq!(new_mail, updated_user.email);
|
||||||
|
assert_eq!(Role::AreaManager, updated_user.role);
|
||||||
|
assert_eq!(Function::Fuehrungsassistent, updated_user.function);
|
||||||
|
assert_eq!(2, updated_user.area_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[db_test]
|
||||||
|
async fn cant_edit_oneself(context: &DbTestContext) {
|
||||||
|
let app = context.app().await;
|
||||||
|
let config = RequestConfig {
|
||||||
|
uri: "/users/edit/1".to_string(),
|
||||||
|
role: Role::Admin,
|
||||||
|
function: crate::models::Function::Posten,
|
||||||
|
user_area: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
let form = EditUserForm {
|
||||||
|
name: "".to_string(),
|
||||||
|
email: "".to_string(),
|
||||||
|
role: Role::AreaManager as u8,
|
||||||
|
function: Function::Fuehrungsassistent as u8,
|
||||||
|
area: Some(1),
|
||||||
|
};
|
||||||
|
|
||||||
|
let response = test_post(&context.db_pool, app, &config, form).await;
|
||||||
|
assert_eq!(StatusCode::BAD_REQUEST, response.status());
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,7 @@ impl TryFrom<u8> for Function {
|
|||||||
fn try_from(value: u8) -> Result<Self, Self::Error> {
|
fn try_from(value: u8) -> Result<Self, Self::Error> {
|
||||||
match value {
|
match value {
|
||||||
1 => Ok(Function::Posten),
|
1 => Ok(Function::Posten),
|
||||||
|
5 => Ok(Function::Fuehrungsassistent),
|
||||||
10 => Ok(Function::Wachhabender),
|
10 => Ok(Function::Wachhabender),
|
||||||
_ => Err(ApplicationError::UnsupportedEnumValue {
|
_ => Err(ApplicationError::UnsupportedEnumValue {
|
||||||
value: value.to_string(),
|
value: value.to_string(),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user