refactor: use rinja instead of askama
This commit is contained in:
parent
187f13a938
commit
4d04069f48
112
Cargo.lock
generated
112
Cargo.lock
generated
@ -379,60 +379,6 @@ dependencies = [
|
||||
"password-hash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "askama"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b79091df18a97caea757e28cd2d5fda49c6cd4bd01ddffd7ff01ace0c0ad2c28"
|
||||
dependencies = [
|
||||
"askama_derive",
|
||||
"askama_escape",
|
||||
"humansize",
|
||||
"num-traits",
|
||||
"percent-encoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "askama_actix"
|
||||
version = "0.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e4b0dd17cfe203b00ba3853a89fba459ecf24c759b738b244133330607c78e55"
|
||||
dependencies = [
|
||||
"actix-web",
|
||||
"askama",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "askama_derive"
|
||||
version = "0.12.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19fe8d6cb13c4714962c072ea496f3392015f0989b1a2847bb4b2d9effd71d83"
|
||||
dependencies = [
|
||||
"askama_parser",
|
||||
"basic-toml",
|
||||
"mime",
|
||||
"mime_guess",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"serde",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "askama_escape"
|
||||
version = "0.10.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "619743e34b5ba4e9703bba34deac3427c72507c7159f5fd030aea8cac0cfe341"
|
||||
|
||||
[[package]]
|
||||
name = "askama_parser"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "acb1161c6b64d1c3d83108213c2a2533a342ac225aabd0bda218278c2ddb00c0"
|
||||
dependencies = [
|
||||
"nom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-channel"
|
||||
version = "1.9.0"
|
||||
@ -738,8 +684,6 @@ dependencies = [
|
||||
"actix-web-static-files",
|
||||
"anyhow",
|
||||
"argon2",
|
||||
"askama",
|
||||
"askama_actix",
|
||||
"async-trait",
|
||||
"brass-config",
|
||||
"brass-macros",
|
||||
@ -754,6 +698,7 @@ dependencies = [
|
||||
"quick-xml",
|
||||
"rand",
|
||||
"regex",
|
||||
"rinja",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sqlx",
|
||||
@ -818,9 +763,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.3"
|
||||
version = "1.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "27f657647bcff5394bf56c7317665bbf790a137a50eaaa5c6bfbb9e27a518f2d"
|
||||
checksum = "9157bbaa6b165880c27a4293a474c91cdcf265cc68cc829bf10be0964a391caf"
|
||||
dependencies = [
|
||||
"jobserver",
|
||||
"libc",
|
||||
@ -2568,6 +2513,47 @@ dependencies = [
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rinja"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3dc4940d00595430b3d7d5a01f6222b5e5b51395d1120bdb28d854bb8abb17a5"
|
||||
dependencies = [
|
||||
"humansize",
|
||||
"itoa",
|
||||
"percent-encoding",
|
||||
"rinja_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rinja_derive"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08d9ed0146aef6e2825f1b1515f074510549efba38d71f4554eec32eb36ba18b"
|
||||
dependencies = [
|
||||
"basic-toml",
|
||||
"memchr",
|
||||
"mime",
|
||||
"mime_guess",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rinja_parser",
|
||||
"rustc-hash",
|
||||
"serde",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rinja_parser"
|
||||
version = "0.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93f9a866e2e00a7a1fb27e46e9e324a6f7c0e7edc4543cae1d38f4e4a100c610"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"nom",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rsa"
|
||||
version = "0.9.7"
|
||||
@ -2594,6 +2580,12 @@ version = "0.1.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c7fb8039b3032c191086b10f11f319a6e99e1e82889c5cc6046f515c9db1d497"
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.4.1"
|
||||
@ -2716,9 +2708,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.23"
|
||||
version = "1.0.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b"
|
||||
checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
|
@ -10,7 +10,8 @@ publish = false
|
||||
[dependencies]
|
||||
sqlx = { version = "^0.8", features = ["runtime-async-std-rustls", "postgres", "chrono"] }
|
||||
actix-web = { version = "4" }
|
||||
askama = { version = "0.12.0", features = ["with-actix-web"] }
|
||||
# askama = { version = "0.13.0", git = "https://github.com/rinja-rs/askama", branch = "main", features = ["with-actix-web"] }
|
||||
# askama_actix = { git = "https://github.com/rinja-rs/askama", branch = "main" }
|
||||
serde = { version = "1.0.164", features = ["derive"] }
|
||||
argon2 = { version = "0.5.0", features = [ "std"]}
|
||||
anyhow = "1.0.71"
|
||||
@ -19,7 +20,6 @@ actix-session = { version = "0.10.1", features = ["cookie-session"] }
|
||||
actix-identity = "0.8.0"
|
||||
chrono = { version = "0.4.33", features = ["serde", "now"] }
|
||||
actix-files = "0.6.5"
|
||||
askama_actix = "0.14.0"
|
||||
futures-util = "0.3.30"
|
||||
serde_json = "1.0.114"
|
||||
pico-args = "0.5.0"
|
||||
@ -36,6 +36,7 @@ regex = "1.11.1"
|
||||
brass-macros = { path = "../macros" }
|
||||
brass-config = { path = "../config" }
|
||||
actix-http = "3.9.0"
|
||||
rinja = "0.3.5"
|
||||
|
||||
[build-dependencies]
|
||||
built = "0.7.4"
|
||||
@ -44,8 +45,5 @@ static-files = "0.2.1"
|
||||
[dev-dependencies]
|
||||
insta = "1.41.1"
|
||||
|
||||
# [dev-dependencies]
|
||||
# brass-web = { path = "." }
|
||||
|
||||
# [profile.dev.package.askama_derive]
|
||||
# opt-level = 3
|
||||
|
@ -0,0 +1,56 @@
|
||||
---
|
||||
source: web/src/endpoints/area/get_new.rs
|
||||
expression: body
|
||||
snapshot_kind: text
|
||||
---
|
||||
<section class="section">
|
||||
<div class="container">
|
||||
|
||||
<form method="post" action="/area/new">
|
||||
<h1 class="title">Neuen Bereich anlegen</h1>
|
||||
|
||||
|
||||
<div class="field is-horizontal">
|
||||
<div class="field-label">
|
||||
<label class="label">Name</label>
|
||||
</div>
|
||||
<div class="field-body">
|
||||
<div class="field">
|
||||
<div class="control">
|
||||
<input class="input" type="text" name="name" required placeholder="Leipzig Ost" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="field is-horizontal">
|
||||
<div class="field-label"></div>
|
||||
<div class="field-body">
|
||||
<div class="field is-grouped">
|
||||
<div class="control">
|
||||
<button class="button is-success">
|
||||
<svg class="icon">
|
||||
<use href="/static/feather-sprite.svg#check-circle" />
|
||||
</svg>
|
||||
<span>
|
||||
|
||||
Erstellen
|
||||
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="control">
|
||||
<a class="button is-link is-light" hx-boost="true" href="/locations">
|
||||
<svg class="icon">
|
||||
<use href="/static/feather-sprite.svg#arrow-left" />
|
||||
</svg>
|
||||
<span>Zurück</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
@ -1,5 +1,5 @@
|
||||
use actix_web::{web, HttpResponse, Responder};
|
||||
use askama_actix::TemplateToResponse;
|
||||
use rinja::Template;
|
||||
use sqlx::PgPool;
|
||||
|
||||
use crate::{
|
||||
@ -24,7 +24,7 @@ async fn get(
|
||||
area: Some(area_in_db),
|
||||
};
|
||||
|
||||
return Ok(template.to_response());
|
||||
return Ok(HttpResponse::Ok().body(template.render()?))
|
||||
} else {
|
||||
return Ok(HttpResponse::NotFound().finish());
|
||||
}
|
||||
|
@ -1,23 +1,23 @@
|
||||
use actix_web::{body::MessageBody, test::read_body, web, HttpResponse, Responder};
|
||||
use askama_actix::TemplateToResponse;
|
||||
use brass_macros::db_test;
|
||||
use insta::assert_snapshot;
|
||||
|
||||
use crate::{
|
||||
endpoints::area::NewOrEditAreaTemplate,
|
||||
models::{Role, User},
|
||||
utils::test_helper::DbTestContext,
|
||||
utils::ApplicationError,
|
||||
};
|
||||
use actix_web::{web, HttpResponse, Responder};
|
||||
use brass_macros::db_test;
|
||||
use rinja::Template;
|
||||
|
||||
#[cfg(test)]
|
||||
use crate::utils::test_helper::{test_get, RequestConfig};
|
||||
use crate::utils::test_helper::{
|
||||
assert_snapshot, read_body, test_get, DbTestContext, RequestConfig,
|
||||
};
|
||||
#[cfg(test)]
|
||||
use actix_http::StatusCode;
|
||||
|
||||
#[actix_web::get("/area/new")]
|
||||
async fn get(user: web::ReqData<User>) -> impl Responder {
|
||||
async fn get(user: web::ReqData<User>) -> Result<impl Responder, ApplicationError> {
|
||||
if user.role != Role::Admin {
|
||||
return HttpResponse::Unauthorized().finish();
|
||||
return Err(ApplicationError::Unauthorized);
|
||||
}
|
||||
|
||||
let template = NewOrEditAreaTemplate {
|
||||
@ -25,7 +25,7 @@ async fn get(user: web::ReqData<User>) -> impl Responder {
|
||||
area: None,
|
||||
};
|
||||
|
||||
template.to_response()
|
||||
Ok(HttpResponse::Ok().body(template.render()?))
|
||||
}
|
||||
|
||||
#[db_test]
|
||||
@ -41,6 +41,6 @@ async fn produces_template(context: &DbTestContext) {
|
||||
|
||||
assert_eq!(StatusCode::OK, response.status());
|
||||
|
||||
let body = String::from_utf8(read_body(response).await.to_vec()).unwrap();
|
||||
let body = read_body(response).await;
|
||||
assert_snapshot!(body);
|
||||
}
|
||||
|
@ -4,13 +4,14 @@ pub mod get_edit;
|
||||
pub mod post_edit;
|
||||
pub mod delete;
|
||||
|
||||
use askama::Template;
|
||||
use rinja::Template;
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::models::{Area, Role, User};
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(path = "area/new_or_edit.html")]
|
||||
#[cfg_attr(not(test), template(path = "area/new_or_edit.html"))]
|
||||
#[cfg_attr(test, template(path = "area/new_or_edit.html", block = "content"))]
|
||||
struct NewOrEditAreaTemplate {
|
||||
user: User,
|
||||
area: Option<Area>,
|
||||
|
@ -1,5 +1,5 @@
|
||||
use actix_web::{web, HttpResponse, Responder};
|
||||
use askama_actix::TemplateToResponse;
|
||||
use rinja::Template;
|
||||
use serde::Deserialize;
|
||||
use sqlx::PgPool;
|
||||
|
||||
@ -61,5 +61,5 @@ pub async fn delete(
|
||||
further_wachhabender_required,
|
||||
};
|
||||
|
||||
Ok(template.to_response())
|
||||
Ok(HttpResponse::Ok().body(template.render()?))
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use askama::Template;
|
||||
use rinja::Template;
|
||||
|
||||
use crate::{
|
||||
filters,
|
||||
|
@ -1,7 +1,5 @@
|
||||
use std::ops::AddAssign;
|
||||
|
||||
use actix_web::{web, HttpResponse, Responder};
|
||||
use askama_actix::TemplateToResponse;
|
||||
use rinja::Template;
|
||||
use serde::Deserialize;
|
||||
use sqlx::PgPool;
|
||||
|
||||
@ -108,5 +106,5 @@ pub async fn post(
|
||||
further_wachhabender_required,
|
||||
};
|
||||
|
||||
Ok(template.to_response())
|
||||
Ok(HttpResponse::Ok().body(template.render()?))
|
||||
}
|
||||
|
@ -1,10 +1,11 @@
|
||||
use actix_web::{web, Responder};
|
||||
use askama_actix::TemplateToResponse;
|
||||
use actix_web::{web, HttpResponse, Responder};
|
||||
use chrono::NaiveDate;
|
||||
use rinja::Template;
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::endpoints::availability::NewOrEditAvailabilityTemplate;
|
||||
use crate::models::User;
|
||||
use crate::utils::ApplicationError;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct AvailabilityNewQuery {
|
||||
@ -17,7 +18,7 @@ struct AvailabilityNewQuery {
|
||||
pub async fn get(
|
||||
user: web::ReqData<User>,
|
||||
query: web::Query<AvailabilityNewQuery>,
|
||||
) -> impl Responder {
|
||||
) -> Result<impl Responder, ApplicationError> {
|
||||
let template = NewOrEditAvailabilityTemplate {
|
||||
user: user.into_inner(),
|
||||
date: query.date,
|
||||
@ -28,5 +29,5 @@ pub async fn get(
|
||||
comment: None,
|
||||
};
|
||||
|
||||
template.to_response()
|
||||
Ok(HttpResponse::Ok().body(template.render()?))
|
||||
}
|
||||
|
@ -1,8 +1,7 @@
|
||||
use crate::filters;
|
||||
use crate::{filters, utils::ApplicationError};
|
||||
use actix_web::{web, HttpResponse, Responder};
|
||||
use askama::Template;
|
||||
use askama_actix::TemplateToResponse;
|
||||
use chrono::{NaiveDate, Utc};
|
||||
use rinja::Template;
|
||||
use serde::Deserialize;
|
||||
use sqlx::PgPool;
|
||||
|
||||
@ -30,18 +29,18 @@ async fn get(
|
||||
user: web::ReqData<User>,
|
||||
pool: web::Data<PgPool>,
|
||||
query: web::Query<CalendarQuery>,
|
||||
) -> impl Responder {
|
||||
) -> Result<impl Responder, ApplicationError> {
|
||||
let date = match query.date {
|
||||
Some(given_date) => given_date,
|
||||
None => Utc::now().date_naive(),
|
||||
};
|
||||
|
||||
let areas = Area::read_all(pool.get_ref()).await.unwrap();
|
||||
let areas = Area::read_all(pool.get_ref()).await?;
|
||||
|
||||
let selected_area = match query.area {
|
||||
Some(id) => {
|
||||
if !areas.iter().any(|a| a.id == id) {
|
||||
return HttpResponse::BadRequest().finish();
|
||||
return Ok(HttpResponse::BadRequest().finish());
|
||||
}
|
||||
|
||||
Some(id)
|
||||
@ -54,16 +53,14 @@ async fn get(
|
||||
date,
|
||||
query.area.unwrap_or(user.area_id),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
.await?;
|
||||
|
||||
let availabillities = Availabillity::read_by_date_and_area_including_user(
|
||||
pool.get_ref(),
|
||||
date,
|
||||
query.area.unwrap_or(user.area_id),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
.await?;
|
||||
|
||||
let template = CalendarTemplate {
|
||||
user: user.into_inner(),
|
||||
@ -74,5 +71,5 @@ async fn get(
|
||||
availabillities,
|
||||
};
|
||||
|
||||
template.to_response()
|
||||
Ok(HttpResponse::Ok().body(template.render()?))
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
use actix_web::{web, HttpResponse, Responder};
|
||||
use askama_actix::TemplateToResponse;
|
||||
use rinja::Template;
|
||||
use serde::Deserialize;
|
||||
use sqlx::PgPool;
|
||||
|
||||
@ -50,5 +50,5 @@ pub async fn get(
|
||||
comment: availabillity.comment.as_deref(),
|
||||
};
|
||||
|
||||
Ok(template.to_response())
|
||||
Ok(HttpResponse::Ok().body(template.render()?))
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use askama::Template;
|
||||
use rinja::Template;
|
||||
use chrono::NaiveDate;
|
||||
|
||||
use crate::filters;
|
||||
|
@ -1,7 +1,6 @@
|
||||
use actix_web::{web, Responder};
|
||||
use askama::Template;
|
||||
use askama_actix::TemplateToResponse;
|
||||
use actix_web::{web, HttpResponse, Responder};
|
||||
use chrono::NaiveDate;
|
||||
use rinja::Template;
|
||||
use sqlx::PgPool;
|
||||
|
||||
use crate::{
|
||||
@ -40,5 +39,5 @@ pub async fn get(
|
||||
locations,
|
||||
};
|
||||
|
||||
Ok(template.to_response())
|
||||
Ok(HttpResponse::Ok().body(template.render()?))
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
use actix_web::{web, HttpResponse, Responder};
|
||||
use askama::Template;
|
||||
use askama_actix::TemplateToResponse;
|
||||
use rinja::Template;
|
||||
use sqlx::PgPool;
|
||||
|
||||
use crate::{
|
||||
@ -61,5 +60,5 @@ pub async fn get(
|
||||
further_wachhabender_required,
|
||||
};
|
||||
|
||||
Ok(template.to_response())
|
||||
Ok(HttpResponse::Ok().body(template.render()?))
|
||||
}
|
||||
|
@ -1,9 +1,8 @@
|
||||
use actix_web::{web, HttpResponse, Responder};
|
||||
use askama::Template;
|
||||
use askama_actix::TemplateToResponse;
|
||||
use rinja::Template;
|
||||
use sqlx::PgPool;
|
||||
|
||||
use crate::models::{Area, User, Role};
|
||||
use crate::{models::{Area, Role, User}, utils::ApplicationError};
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(path = "export/availability.html")]
|
||||
@ -16,13 +15,13 @@ struct AvailabilityExportTemplate {
|
||||
pub async fn get(
|
||||
user: web::ReqData<User>,
|
||||
pool: web::Data<PgPool>
|
||||
) -> impl Responder {
|
||||
) -> Result<impl Responder, ApplicationError> {
|
||||
if user.role != Role::Admin && user.role != Role::AreaManager {
|
||||
return HttpResponse::Unauthorized().finish();
|
||||
return Err(ApplicationError::Unauthorized);
|
||||
}
|
||||
|
||||
let areas = if user.role == Role::Admin {
|
||||
Some(Area::read_all(pool.get_ref()).await.unwrap())
|
||||
Some(Area::read_all(pool.get_ref()).await?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
@ -32,5 +31,5 @@ pub async fn get(
|
||||
areas
|
||||
};
|
||||
|
||||
return template.to_response();
|
||||
Ok(HttpResponse::Ok().body(template.render()?))
|
||||
}
|
||||
|
@ -40,9 +40,10 @@ pub async fn get(
|
||||
user: Identity,
|
||||
query: web::Query<ExportQuery>,
|
||||
) -> impl Responder {
|
||||
// TODO: rerwrite
|
||||
let current_user = User::read_by_id(pool.get_ref(), user.id().unwrap().parse().unwrap())
|
||||
.await
|
||||
.unwrap();
|
||||
.unwrap().unwrap();
|
||||
|
||||
if current_user.role != Role::Admin && current_user.role != Role::AreaManager {
|
||||
return HttpResponse::Unauthorized().finish();
|
||||
|
@ -1,14 +1,15 @@
|
||||
use actix_web::Responder;
|
||||
use askama::Template;
|
||||
use askama_actix::TemplateToResponse;
|
||||
use actix_web::{HttpResponse, Responder};
|
||||
use rinja::Template;
|
||||
|
||||
use crate::utils::ApplicationError;
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(path = "imprint.html")]
|
||||
struct ImprintTemplate {}
|
||||
|
||||
#[actix_web::get("/imprint")]
|
||||
pub async fn get_imprint() -> impl Responder {
|
||||
pub async fn get_imprint() -> Result<impl Responder, ApplicationError> {
|
||||
let template = ImprintTemplate {};
|
||||
|
||||
template.to_response()
|
||||
Ok(HttpResponse::Ok().body(template.render()?))
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
use actix_web::{web, HttpResponse, Responder};
|
||||
use askama_actix::TemplateToResponse;
|
||||
use rinja::Template;
|
||||
use sqlx::PgPool;
|
||||
|
||||
use crate::{
|
||||
@ -38,5 +38,5 @@ pub async fn get(
|
||||
location: Some(location),
|
||||
};
|
||||
|
||||
Ok(template.to_response())
|
||||
Ok(HttpResponse::Ok().body(template.render()?))
|
||||
}
|
||||
|
@ -1,26 +1,33 @@
|
||||
use actix_web::{web, HttpResponse, Responder};
|
||||
use askama_actix::TemplateToResponse;
|
||||
use rinja::Template;
|
||||
use sqlx::PgPool;
|
||||
|
||||
use crate::{endpoints::location::LocationTemplate, models::{Area, Role, User}};
|
||||
use crate::{
|
||||
endpoints::location::LocationTemplate,
|
||||
models::{Area, Role, User},
|
||||
utils::ApplicationError,
|
||||
};
|
||||
|
||||
#[actix_web::get("/locations/new")]
|
||||
pub async fn get(user: web::ReqData<User>, pool: web::Data<PgPool>) -> impl Responder {
|
||||
if user.role == Role::AreaManager || user.role == Role::Admin {
|
||||
let mut areas = None;
|
||||
|
||||
if user.role == Role::Admin {
|
||||
areas = Some(Area::read_all(pool.get_ref()).await.unwrap());
|
||||
}
|
||||
|
||||
let template = LocationTemplate {
|
||||
user: user.into_inner(),
|
||||
areas,
|
||||
location: None
|
||||
};
|
||||
|
||||
return template.to_response();
|
||||
pub async fn get(
|
||||
user: web::ReqData<User>,
|
||||
pool: web::Data<PgPool>,
|
||||
) -> Result<impl Responder, ApplicationError> {
|
||||
if user.role != Role::AreaManager && user.role != Role::Admin {
|
||||
return Err(ApplicationError::Unauthorized);
|
||||
}
|
||||
|
||||
return HttpResponse::Unauthorized().finish();
|
||||
let mut areas = None;
|
||||
|
||||
if user.role == Role::Admin {
|
||||
areas = Some(Area::read_all(pool.get_ref()).await?);
|
||||
}
|
||||
|
||||
let template = LocationTemplate {
|
||||
user: user.into_inner(),
|
||||
areas,
|
||||
location: None,
|
||||
};
|
||||
|
||||
Ok(HttpResponse::Ok().body(template.render()?))
|
||||
}
|
||||
|
@ -1,9 +1,11 @@
|
||||
use actix_web::{web, HttpResponse, Responder};
|
||||
use askama::Template;
|
||||
use askama_actix::TemplateToResponse;
|
||||
use rinja::Template;
|
||||
use sqlx::PgPool;
|
||||
|
||||
use crate::models::{Area, Location, Role, User};
|
||||
use crate::{
|
||||
models::{Area, Location, Role, User},
|
||||
utils::ApplicationError,
|
||||
};
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(path = "location/overview.html")]
|
||||
@ -13,45 +15,45 @@ pub struct LocationsTemplate {
|
||||
}
|
||||
|
||||
#[actix_web::get("/locations")]
|
||||
pub async fn get(user: web::ReqData<User>, pool: web::Data<PgPool>) -> impl Responder {
|
||||
if user.role == Role::AreaManager || user.role == Role::Admin {
|
||||
let mut locations;
|
||||
let mut grouped_locations: Vec<(Area, Vec<Location>)>;
|
||||
|
||||
if user.role == Role::Admin {
|
||||
locations = Location::read_all(pool.get_ref()).await.unwrap();
|
||||
grouped_locations = Area::read_all(pool.get_ref())
|
||||
.await
|
||||
.unwrap()
|
||||
.into_iter()
|
||||
.map(|a| (a, Vec::new()))
|
||||
.collect();
|
||||
} else {
|
||||
locations = Location::read_by_area(pool.get_ref(), user.area_id)
|
||||
.await
|
||||
.unwrap();
|
||||
let area = Area::read_by_id(pool.get_ref(), user.area_id)
|
||||
.await
|
||||
.unwrap().unwrap();
|
||||
|
||||
grouped_locations = vec![(area, Vec::new())];
|
||||
}
|
||||
|
||||
for entry in grouped_locations.iter_mut() {
|
||||
let (mut locations_in_this_area, rest): (Vec<_>, Vec<_>) =
|
||||
locations.into_iter().partition(|l| l.area_id == entry.0.id);
|
||||
locations = rest;
|
||||
|
||||
entry.1.append(&mut locations_in_this_area);
|
||||
}
|
||||
|
||||
let template = LocationsTemplate {
|
||||
user: user.into_inner(),
|
||||
grouped_locations,
|
||||
};
|
||||
|
||||
return template.to_response();
|
||||
pub async fn get(
|
||||
user: web::ReqData<User>,
|
||||
pool: web::Data<PgPool>,
|
||||
) -> Result<impl Responder, ApplicationError> {
|
||||
if user.role != Role::AreaManager && user.role != Role::Admin {
|
||||
return Err(ApplicationError::Unauthorized);
|
||||
}
|
||||
|
||||
return HttpResponse::Unauthorized().finish();
|
||||
let mut locations;
|
||||
let mut grouped_locations: Vec<(Area, Vec<Location>)>;
|
||||
|
||||
if user.role == Role::Admin {
|
||||
locations = Location::read_all(pool.get_ref()).await.unwrap();
|
||||
grouped_locations = Area::read_all(pool.get_ref())
|
||||
.await?
|
||||
.into_iter()
|
||||
.map(|a| (a, Vec::new()))
|
||||
.collect();
|
||||
} else {
|
||||
locations = Location::read_by_area(pool.get_ref(), user.area_id).await?;
|
||||
let area = Area::read_by_id(pool.get_ref(), user.area_id)
|
||||
.await?
|
||||
.unwrap();
|
||||
|
||||
grouped_locations = vec![(area, Vec::new())];
|
||||
}
|
||||
|
||||
for entry in grouped_locations.iter_mut() {
|
||||
let (mut locations_in_this_area, rest): (Vec<_>, Vec<_>) =
|
||||
locations.into_iter().partition(|l| l.area_id == entry.0.id);
|
||||
locations = rest;
|
||||
|
||||
entry.1.append(&mut locations_in_this_area);
|
||||
}
|
||||
|
||||
let template = LocationsTemplate {
|
||||
user: user.into_inner(),
|
||||
grouped_locations,
|
||||
};
|
||||
|
||||
Ok(HttpResponse::Ok().body(template.render()?))
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use askama::Template;
|
||||
use rinja::Template;
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::models::{Area, Location, Role, User};
|
||||
|
@ -16,7 +16,9 @@ pub async fn delete(
|
||||
return Err(ApplicationError::Unauthorized);
|
||||
}
|
||||
|
||||
let user_in_db = User::read_by_id(pool.get_ref(), path.id).await?;
|
||||
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);
|
||||
|
@ -1,16 +1,15 @@
|
||||
use actix_web::{web, Responder};
|
||||
use askama::Template;
|
||||
use askama_actix::TemplateToResponse;
|
||||
use actix_web::{web, HttpResponse, Responder};
|
||||
use rinja::Template;
|
||||
|
||||
use crate::models::User;
|
||||
use crate::{models::User, utils::ApplicationError};
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(path = "user/profile_change_password.html")]
|
||||
struct ProfileChangePasswordTemplate {}
|
||||
|
||||
#[actix_web::get("/users/changepassword")]
|
||||
pub async fn get(_user: web::ReqData<User>) -> impl Responder {
|
||||
pub async fn get(_user: web::ReqData<User>) -> Result<impl Responder, ApplicationError> {
|
||||
let template = ProfileChangePasswordTemplate {};
|
||||
|
||||
template.to_response()
|
||||
Ok(HttpResponse::Ok().body(template.render()?))
|
||||
}
|
||||
|
@ -1,10 +1,11 @@
|
||||
use actix_web::{web, HttpResponse, Responder};
|
||||
use askama_actix::TemplateToResponse;
|
||||
use rinja::Template;
|
||||
use sqlx::PgPool;
|
||||
|
||||
use crate::{
|
||||
endpoints::{user::NewOrEditUserTemplate, IdPath},
|
||||
models::{Area, Role, User},
|
||||
utils::ApplicationError,
|
||||
};
|
||||
|
||||
#[actix_web::get("/users/edit/{id}")]
|
||||
@ -12,19 +13,22 @@ pub async fn get_edit(
|
||||
user: web::ReqData<User>,
|
||||
pool: web::Data<PgPool>,
|
||||
path: web::Path<IdPath>,
|
||||
) -> impl Responder {
|
||||
) -> Result<impl Responder, ApplicationError> {
|
||||
let mut areas = None;
|
||||
|
||||
if user.role != Role::AreaManager && user.role != Role::Admin {
|
||||
return HttpResponse::Unauthorized().finish();
|
||||
return Err(ApplicationError::Unauthorized);
|
||||
}
|
||||
|
||||
if user.role == Role::Admin {
|
||||
areas = Some(Area::read_all(pool.get_ref()).await.unwrap());
|
||||
areas = Some(Area::read_all(pool.get_ref()).await?);
|
||||
}
|
||||
|
||||
if let Ok(user_in_db) = User::read_by_id(pool.get_ref(), path.id).await {
|
||||
let template = NewOrEditUserTemplate {
|
||||
let Some(user_in_db) = User::read_by_id(pool.get_ref(), path.id).await? else {
|
||||
return Ok(HttpResponse::NotFound().finish());
|
||||
};
|
||||
|
||||
let template = NewOrEditUserTemplate {
|
||||
user: user.into_inner(),
|
||||
id: Some(user_in_db.id),
|
||||
areas,
|
||||
@ -35,8 +39,5 @@ pub async fn get_edit(
|
||||
area_id: Some(user_in_db.area_id),
|
||||
};
|
||||
|
||||
return template.to_response();
|
||||
}
|
||||
|
||||
HttpResponse::BadRequest().body("Fehler beim Bearbeiten des Nutzers")
|
||||
Ok(HttpResponse::Ok().body(template.render()?))
|
||||
}
|
||||
|
@ -1,21 +1,22 @@
|
||||
use actix_identity::Identity;
|
||||
use actix_web::{http::header::LOCATION, HttpResponse, Responder};
|
||||
use askama::Template;
|
||||
use askama_actix::TemplateToResponse;
|
||||
use rinja::Template;
|
||||
|
||||
use crate::utils::ApplicationError;
|
||||
|
||||
#[derive(Template)]
|
||||
#[template(path = "user/login.html")]
|
||||
struct LoginTemplate {}
|
||||
|
||||
#[actix_web::get("/login")]
|
||||
async fn get(user: Option<Identity>) -> impl Responder {
|
||||
async fn get(user: Option<Identity>) -> Result<impl Responder, ApplicationError> {
|
||||
if let Some(_) = user {
|
||||
return HttpResponse::Found()
|
||||
Ok(HttpResponse::Found()
|
||||
.insert_header((LOCATION, "/"))
|
||||
.finish();
|
||||
.finish())
|
||||
} else {
|
||||
let template = LoginTemplate {};
|
||||
|
||||
return template.to_response();
|
||||
Ok(HttpResponse::Ok().body(template.render()?))
|
||||
}
|
||||
}
|
||||
|
@ -1,18 +1,22 @@
|
||||
use actix_web::{web, Responder};
|
||||
use askama_actix::TemplateToResponse;
|
||||
use actix_web::{web, HttpResponse, Responder};
|
||||
use rinja::Template;
|
||||
use sqlx::PgPool;
|
||||
|
||||
use crate::{
|
||||
endpoints::user::NewOrEditUserTemplate,
|
||||
models::{Area, Role, User},
|
||||
utils::ApplicationError,
|
||||
};
|
||||
|
||||
#[actix_web::get("/users/new")]
|
||||
pub async fn get_new(user: web::ReqData<User>, pool: web::Data<PgPool>) -> impl Responder {
|
||||
pub async fn get_new(
|
||||
user: web::ReqData<User>,
|
||||
pool: web::Data<PgPool>,
|
||||
) -> Result<impl Responder, ApplicationError> {
|
||||
let mut areas: Option<Vec<Area>> = None;
|
||||
|
||||
if user.role == Role::Admin {
|
||||
areas = Some(Area::read_all(pool.get_ref()).await.unwrap())
|
||||
areas = Some(Area::read_all(pool.get_ref()).await?)
|
||||
}
|
||||
|
||||
let template = NewOrEditUserTemplate {
|
||||
@ -26,5 +30,5 @@ pub async fn get_new(user: web::ReqData<User>, pool: web::Data<PgPool>) -> impl
|
||||
area_id: None,
|
||||
};
|
||||
|
||||
template.to_response()
|
||||
Ok(HttpResponse::Ok().body(template.render()?))
|
||||
}
|
||||
|
@ -1,8 +1,10 @@
|
||||
use crate::models::{Area, Role, User, Function};
|
||||
use actix_identity::Identity;
|
||||
use crate::{
|
||||
models::{Area, Function, Role, User},
|
||||
utils::ApplicationError,
|
||||
};
|
||||
|
||||
use actix_web::{web, HttpResponse, Responder};
|
||||
use askama::Template;
|
||||
use askama_actix::TemplateToResponse;
|
||||
use rinja::Template;
|
||||
use sqlx::PgPool;
|
||||
|
||||
#[derive(Template)]
|
||||
@ -14,36 +16,33 @@ pub struct UsersTemplate {
|
||||
}
|
||||
|
||||
#[actix_web::get("/users")]
|
||||
pub async fn get_overview(user: Identity, pool: web::Data<PgPool>) -> impl Responder {
|
||||
let current_user = User::read_by_id(pool.get_ref(), user.id().unwrap().parse().unwrap())
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
if current_user.role == Role::AreaManager || current_user.role == Role::Admin {
|
||||
let mut area = None;
|
||||
let users;
|
||||
|
||||
if current_user.role == Role::AreaManager {
|
||||
area = Some(
|
||||
Area::read_by_id(pool.get_ref(), current_user.area_id)
|
||||
.await
|
||||
.unwrap().unwrap(),
|
||||
);
|
||||
users = User::read_all_by_area(pool.get_ref(), current_user.area_id)
|
||||
.await
|
||||
.unwrap();
|
||||
} else {
|
||||
users = User::read_all_including_area(pool.get_ref()).await.unwrap();
|
||||
}
|
||||
|
||||
let template = UsersTemplate {
|
||||
user: current_user,
|
||||
area,
|
||||
users,
|
||||
};
|
||||
|
||||
return template.to_response();
|
||||
pub async fn get_overview(
|
||||
user: web::ReqData<User>,
|
||||
pool: web::Data<PgPool>,
|
||||
) -> Result<impl Responder, ApplicationError> {
|
||||
if user.role != Role::AreaManager && user.role != Role::Admin {
|
||||
return Err(ApplicationError::Unauthorized);
|
||||
}
|
||||
|
||||
return HttpResponse::BadRequest().body("Fehler beim Zugriff auf die Nutzerverwaltung!");
|
||||
let mut area = None;
|
||||
let users;
|
||||
|
||||
if user.role == Role::AreaManager {
|
||||
area = Some(
|
||||
Area::read_by_id(pool.get_ref(), user.area_id)
|
||||
.await?
|
||||
.unwrap(),
|
||||
);
|
||||
users = User::read_all_by_area(pool.get_ref(), user.area_id).await?;
|
||||
} else {
|
||||
users = User::read_all_including_area(pool.get_ref()).await?;
|
||||
}
|
||||
|
||||
let template = UsersTemplate {
|
||||
user: user.into_inner(),
|
||||
area,
|
||||
users,
|
||||
};
|
||||
|
||||
Ok(HttpResponse::Ok().body(template.render()?))
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
use actix_web::{web, Responder};
|
||||
use askama::Template;
|
||||
use askama_actix::TemplateToResponse;
|
||||
use actix_web::{web, HttpResponse, Responder};
|
||||
use rinja::Template;
|
||||
use sqlx::PgPool;
|
||||
|
||||
use crate::{
|
||||
filters,
|
||||
models::{Area, Role, User},
|
||||
utils::ApplicationError,
|
||||
};
|
||||
|
||||
#[derive(Template)]
|
||||
@ -15,15 +15,16 @@ struct ProfileTemplate {
|
||||
}
|
||||
|
||||
#[actix_web::get("/profile")]
|
||||
pub async fn get(user: web::ReqData<User>, pool: web::Data<PgPool>) -> impl Responder {
|
||||
let area = Area::read_by_id(pool.get_ref(), user.area_id)
|
||||
.await
|
||||
.unwrap();
|
||||
pub async fn get(
|
||||
user: web::ReqData<User>,
|
||||
pool: web::Data<PgPool>,
|
||||
) -> Result<impl Responder, ApplicationError> {
|
||||
let area = Area::read_by_id(pool.get_ref(), user.area_id).await?;
|
||||
|
||||
let mut user = user.into_inner();
|
||||
user.area = area;
|
||||
|
||||
let template = ProfileTemplate { user };
|
||||
|
||||
return template.to_response();
|
||||
Ok(HttpResponse::Ok().body(template.render()?))
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use actix_identity::Identity;
|
||||
use actix_web::{get, http::header::LOCATION, web, HttpResponse, Responder};
|
||||
use askama_actix::TemplateToResponse;
|
||||
use rinja::Template;
|
||||
use serde::Deserialize;
|
||||
use sqlx::PgPool;
|
||||
|
||||
@ -25,18 +25,18 @@ pub async fn get(
|
||||
.finish());
|
||||
}
|
||||
|
||||
if let Some(_) = Registration::does_token_exist(pool.get_ref(), &query.token).await? {
|
||||
let template = ResetPasswordTemplate {
|
||||
token: &query.token,
|
||||
title: "Brass - Registrierung",
|
||||
endpoint: "/register",
|
||||
new_password_label: "Passwort:",
|
||||
retype_label: "Passwort wiederholen:",
|
||||
submit_button_label: "Registrieren",
|
||||
};
|
||||
let Some(_) = Registration::does_token_exist(pool.get_ref(), &query.token).await? else {
|
||||
return Ok(HttpResponse::NotFound().finish());
|
||||
};
|
||||
|
||||
return Ok(template.to_response());
|
||||
}
|
||||
let template = ResetPasswordTemplate {
|
||||
token: &query.token,
|
||||
title: "Brass - Registrierung",
|
||||
endpoint: "/register",
|
||||
new_password_label: "Passwort:",
|
||||
retype_label: "Passwort wiederholen:",
|
||||
submit_button_label: "Registrieren",
|
||||
};
|
||||
|
||||
Ok(HttpResponse::NotFound().finish())
|
||||
Ok(HttpResponse::Ok().body(template.render()?))
|
||||
}
|
||||
|
@ -1,11 +1,10 @@
|
||||
use actix_identity::Identity;
|
||||
use actix_web::{get, http::header::LOCATION, web, HttpResponse, Responder};
|
||||
use askama::Template;
|
||||
use askama_actix::TemplateToResponse;
|
||||
use rinja::Template;
|
||||
use serde::Deserialize;
|
||||
use sqlx::PgPool;
|
||||
|
||||
use crate::models::PasswordReset;
|
||||
use crate::{models::PasswordReset, utils::ApplicationError};
|
||||
|
||||
use super::ResetPasswordTemplate;
|
||||
|
||||
@ -23,13 +22,13 @@ pub async fn get(
|
||||
user: Option<Identity>,
|
||||
pool: web::Data<PgPool>,
|
||||
query: web::Query<TokenQuery>,
|
||||
) -> impl Responder {
|
||||
) -> Result<impl Responder, ApplicationError> {
|
||||
if let Some(_) = user {
|
||||
return HttpResponse::Found()
|
||||
return Ok(HttpResponse::Found()
|
||||
.insert_header((LOCATION, "/"))
|
||||
.finish();
|
||||
.finish());
|
||||
} else if let Some(token) = &query.token {
|
||||
if let Ok(_) = PasswordReset::does_token_exist(pool.get_ref(), token).await {
|
||||
if let Some(_) = PasswordReset::does_token_exist(pool.get_ref(), token).await? {
|
||||
let template = ResetPasswordTemplate {
|
||||
token,
|
||||
title: "Brass - Passwort zurücksetzen",
|
||||
@ -39,11 +38,10 @@ pub async fn get(
|
||||
submit_button_label: "Passwort zurücksetzen",
|
||||
};
|
||||
|
||||
return template.to_response();
|
||||
return Ok(HttpResponse::Ok().body(template.render()?))
|
||||
}
|
||||
}
|
||||
|
||||
let template = ForgotPasswordTemplate {};
|
||||
|
||||
return template.to_response();
|
||||
Ok(HttpResponse::Ok().body(template.render()?))
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ use crate::models::{Area, Role, Token, User};
|
||||
use crate::utils::{password_help, ApplicationError};
|
||||
use crate::{auth, filters};
|
||||
use actix_web::HttpResponse;
|
||||
use askama::Template;
|
||||
use rinja::Template;
|
||||
use sqlx::PgPool;
|
||||
use zxcvbn::{zxcvbn, Score};
|
||||
|
||||
@ -73,7 +73,8 @@ async fn handle_password_change_request(
|
||||
return Ok(no_message);
|
||||
}
|
||||
|
||||
let user = User::read_by_id(pool, user_id).await?;
|
||||
// TODO: make sure this unwrap is safe
|
||||
let user = User::read_by_id(pool, user_id).await?.unwrap();
|
||||
let mut split_names: Vec<&str> = user.name.as_str().split_whitespace().collect();
|
||||
let mut user_inputs = vec![user.email.as_str()];
|
||||
user_inputs.append(&mut split_names);
|
||||
|
@ -24,15 +24,16 @@ pub async fn post_edit(
|
||||
path: web::Path<IdPath>,
|
||||
form: web::Form<EditUserForm>,
|
||||
) -> impl Responder {
|
||||
// TODO: rewrite
|
||||
let current_user = User::read_by_id(pool.get_ref(), user.id().unwrap().parse().unwrap())
|
||||
.await
|
||||
.unwrap();
|
||||
.unwrap().unwrap();
|
||||
|
||||
if current_user.role != Role::AreaManager && current_user.role != Role::Admin {
|
||||
return HttpResponse::Unauthorized().finish();
|
||||
}
|
||||
|
||||
if let Ok(user_in_db) = User::read_by_id(pool.get_ref(), path.id).await {
|
||||
if let Some(user_in_db) = User::read_by_id(pool.get_ref(), path.id).await.unwrap() {
|
||||
if current_user.role == Role::AreaManager && current_user.area_id != user_in_db.area_id {
|
||||
return HttpResponse::Unauthorized().finish();
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ pub async fn post_new(
|
||||
.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?;
|
||||
let new_user = User::read_by_id(pool.get_ref(), id).await?.unwrap();
|
||||
let message = email::build_registration_message(&new_user, ®istration.token)?;
|
||||
|
||||
mailer.send(&message)?;
|
||||
|
@ -19,12 +19,13 @@ pub async fn post(
|
||||
path: web::Path<IdPath>,
|
||||
query: web::Query<ToggleQuery>,
|
||||
) -> impl Responder {
|
||||
// Todo: rewrite
|
||||
if user.id != path.id && user.role != Role::Admin && user.role != Role::AreaManager {
|
||||
return HttpResponse::Unauthorized().finish();
|
||||
}
|
||||
|
||||
let user = if user.id != path.id {
|
||||
User::read_by_id(pool.get_ref(), path.id).await.unwrap()
|
||||
User::read_by_id(pool.get_ref(), path.id).await.unwrap().unwrap()
|
||||
} else {
|
||||
user.into_inner()
|
||||
};
|
||||
|
@ -1,5 +1,5 @@
|
||||
use actix_web::{web, HttpResponse, Responder};
|
||||
use askama_actix::TemplateToResponse;
|
||||
use rinja::Template;
|
||||
use sqlx::PgPool;
|
||||
|
||||
use crate::{
|
||||
@ -27,5 +27,5 @@ pub async fn get(
|
||||
vehicle: Some(vehicle),
|
||||
};
|
||||
|
||||
Ok(template.to_response())
|
||||
Ok(HttpResponse::Ok().body(template.render()?))
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
use actix_web::{web, Responder};
|
||||
use askama_actix::TemplateToResponse;
|
||||
use actix_web::{web, HttpResponse, Responder};
|
||||
use rinja::Template;
|
||||
|
||||
use crate::{
|
||||
endpoints::vehicle::VehicleNewOrEditTemplate,
|
||||
@ -18,5 +18,5 @@ pub async fn get(user: web::ReqData<User>) -> Result<impl Responder, Application
|
||||
vehicle: None,
|
||||
};
|
||||
|
||||
Ok(template.to_response())
|
||||
Ok(HttpResponse::Ok().body(template.render()?))
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
use actix_web::{web, Responder};
|
||||
use askama::Template;
|
||||
use askama_actix::TemplateToResponse;
|
||||
use actix_web::{web, HttpResponse, Responder};
|
||||
use rinja::Template;
|
||||
use sqlx::PgPool;
|
||||
|
||||
use crate::{models::{User, Vehicle, Role}, utils::ApplicationError};
|
||||
@ -25,5 +24,5 @@ pub async fn get(user: web::ReqData<User>, pool: web::Data<PgPool>) -> Result<im
|
||||
vehicles
|
||||
};
|
||||
|
||||
Ok(template.to_response())
|
||||
Ok(HttpResponse::Ok().body(template.render()?))
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use askama::Template;
|
||||
use rinja::Template;
|
||||
use serde::Deserialize;
|
||||
|
||||
use crate::models::{Role, User, Vehicle};
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::models::Function;
|
||||
|
||||
pub fn show_area_query(a: &Option<i32>, first: bool) -> ::askama::Result<String> {
|
||||
pub fn show_area_query(a: &Option<i32>, first: bool) -> rinja::Result<String> {
|
||||
let char = if first { '?' } else { '&' };
|
||||
|
||||
if let Some(a) = a {
|
||||
@ -10,7 +10,7 @@ pub fn show_area_query(a: &Option<i32>, first: bool) -> ::askama::Result<String>
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cond_show(show: &bool, text: &str) -> askama::Result<String> {
|
||||
pub fn cond_show(show: &bool, text: &str) -> rinja::Result<String> {
|
||||
return if *show {
|
||||
Ok(String::from(text))
|
||||
} else {
|
||||
@ -18,7 +18,7 @@ pub fn cond_show(show: &bool, text: &str) -> askama::Result<String> {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn insert_value(option: &Option<String>) -> askama::Result<String> {
|
||||
pub fn insert_value(option: &Option<String>) -> rinja::Result<String> {
|
||||
if let Some(val) = option {
|
||||
let s = format!(r#"value="{val}""#);
|
||||
return Ok(s);
|
||||
@ -27,18 +27,18 @@ pub fn insert_value(option: &Option<String>) -> askama::Result<String> {
|
||||
Ok(String::new())
|
||||
}
|
||||
|
||||
pub fn is_some_and_eq<T>(option: &Option<T>, other: &T) -> askama::Result<bool>
|
||||
pub fn is_some_and_eq<T>(option: &Option<T>, other: &T) -> rinja::Result<bool>
|
||||
where
|
||||
T: Eq,
|
||||
{
|
||||
Ok(option.as_ref().is_some_and(|x| x == other))
|
||||
}
|
||||
|
||||
pub fn invert(b: &bool) -> askama::Result<bool> {
|
||||
pub fn invert(b: &bool) -> rinja::Result<bool> {
|
||||
return Ok(!b);
|
||||
}
|
||||
|
||||
pub fn show_tree(f: &Function) -> askama::Result<String> {
|
||||
pub fn show_tree(f: &Function) -> rinja::Result<String> {
|
||||
let mut tags = String::from(r#"<span class="tag is-info is-light">Posten</span>"#);
|
||||
|
||||
if f == &Function::Fuehrungsassistent || f == &Function::Wachhabender {
|
||||
|
@ -56,6 +56,7 @@ where
|
||||
|
||||
let user = User::read_by_id(pool.get_ref(), id.parse().unwrap())
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
||||
req.extensions_mut().insert::<User>(user);
|
||||
|
@ -76,7 +76,7 @@ impl User {
|
||||
b
|
||||
}
|
||||
|
||||
pub async fn read_by_id(pool: &PgPool, id: i32) -> Result<User> {
|
||||
pub async fn read_by_id(pool: &PgPool, id: i32) -> Result<Option<User>> {
|
||||
let record = sqlx::query!(
|
||||
r#"
|
||||
SELECT id,
|
||||
@ -95,23 +95,23 @@ impl User {
|
||||
"#,
|
||||
id,
|
||||
)
|
||||
.fetch_one(pool)
|
||||
.fetch_optional(pool)
|
||||
.await?;
|
||||
|
||||
let user = User {
|
||||
id: record.id,
|
||||
name: record.name,
|
||||
email: record.email,
|
||||
password: record.password,
|
||||
salt: record.salt,
|
||||
role: record.role,
|
||||
function: record.function,
|
||||
area_id: record.areaid,
|
||||
let user = record.and_then(|u| Some(User {
|
||||
id: u.id,
|
||||
name: u.name,
|
||||
email: u.email,
|
||||
password: u.password,
|
||||
salt: u.salt,
|
||||
role: u.role,
|
||||
function: u.function,
|
||||
area_id: u.areaid,
|
||||
area: None,
|
||||
locked: record.locked,
|
||||
last_login: record.lastlogin,
|
||||
receive_notifications: record.receivenotifications,
|
||||
};
|
||||
locked: u.locked,
|
||||
last_login: u.lastlogin,
|
||||
receive_notifications: u.receivenotifications,
|
||||
}));
|
||||
|
||||
Ok(user)
|
||||
}
|
||||
@ -197,7 +197,7 @@ impl User {
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
pub async fn read_all_including_area(pool: &PgPool) -> anyhow::Result<Vec<User>> {
|
||||
pub async fn read_all_including_area(pool: &PgPool) -> Result<Vec<User>> {
|
||||
let records = sqlx::query!(
|
||||
r#"
|
||||
SELECT
|
||||
@ -245,7 +245,7 @@ impl User {
|
||||
Ok(results)
|
||||
}
|
||||
|
||||
pub async fn read_all_by_area(pool: &PgPool, area_id: i32) -> anyhow::Result<Vec<User>> {
|
||||
pub async fn read_all_by_area(pool: &PgPool, area_id: i32) -> Result<Vec<User>> {
|
||||
let records = sqlx::query!(
|
||||
r#"
|
||||
SELECT id,
|
||||
|
@ -18,7 +18,9 @@ pub enum ApplicationError {
|
||||
#[error("email transport not working")]
|
||||
EmailTransport(#[from] lettre::transport::smtp::Error),
|
||||
#[error("hashfunction failed")]
|
||||
Hash(#[from] argon2::password_hash::Error)
|
||||
Hash(#[from] argon2::password_hash::Error),
|
||||
#[error("templating failed")]
|
||||
Template(#[from] rinja::Error),
|
||||
}
|
||||
|
||||
impl actix_web::error::ResponseError for ApplicationError {
|
||||
@ -32,6 +34,7 @@ impl actix_web::error::ResponseError for ApplicationError {
|
||||
ApplicationError::Email(_) => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
ApplicationError::EmailTransport(_) => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
ApplicationError::Hash(_) => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
ApplicationError::Template(_) => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,6 +46,7 @@ impl actix_web::error::ResponseError for ApplicationError {
|
||||
ApplicationError::EmailAdress(e) => response.body(format!("{self} - {e}")),
|
||||
ApplicationError::Email(e) => response.body(format!("{self} - {e}")),
|
||||
ApplicationError::EmailTransport(e) => response.body(format!("{self} - {e}")),
|
||||
ApplicationError::Template(e) => response.body(format!("{self} - {e}")),
|
||||
_ => response.body(self.to_string()),
|
||||
}
|
||||
}
|
||||
|
@ -45,9 +45,9 @@
|
||||
</div>
|
||||
<div class="control">
|
||||
<a class="button is-link is-light" hx-boost="true" href="/locations">
|
||||
<svg class="icon">
|
||||
<use href="/static/feather-sprite.svg#arrow-left" />
|
||||
</svg>
|
||||
<svg class="icon">
|
||||
<use href="/static/feather-sprite.svg#arrow-left" />
|
||||
</svg>
|
||||
<span>Zurück</span>
|
||||
</a>
|
||||
</div>
|
||||
@ -58,7 +58,4 @@
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<script>
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
@ -32,10 +32,10 @@
|
||||
<label class="radio">
|
||||
{% if id.is_some() %}
|
||||
<input type="radio" name="hasTime" hx-get="/availabillity/edit/{{ id.unwrap() }}?wholeday=false"
|
||||
hx-target="closest body" {{ whole_day|invert|cond_show("checked") }} />
|
||||
hx-target="closest body" {{ whole_day|invert|ref|cond_show("checked") }} />
|
||||
{% else %}
|
||||
<input type="radio" name="hasTime" hx-get="/availabillity/new?date={{ date }}&wholeday=false"
|
||||
hx-target="closest body" {{ whole_day|invert|cond_show("checked") }} />
|
||||
hx-target="closest body" {{ whole_day|invert|ref|cond_show("checked") }} />
|
||||
{% endif %}
|
||||
zeitweise
|
||||
</label>
|
||||
@ -51,11 +51,11 @@
|
||||
<div class="field-body">
|
||||
<div class="field">
|
||||
<input class="input" type="time" id="from" name="from" value='{{ start_time.unwrap_or("00:00") }}' {{
|
||||
whole_day|cond_show("disabled") }} {{ whole_day|invert|cond_show("required") }}>
|
||||
whole_day|cond_show("disabled") }} {{ whole_day|invert|ref|cond_show("required") }}>
|
||||
</div>
|
||||
<div class="field">
|
||||
<input class="input" type="time" id="till" name="till" value='{{ end_time.unwrap_or("23:59") }}' {{
|
||||
whole_day|cond_show("disabled") }} {{ whole_day|invert|cond_show("required") }}>
|
||||
whole_day|cond_show("disabled") }} {{ whole_day|invert|ref|cond_show("required") }}>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -43,7 +43,7 @@
|
||||
</div>
|
||||
|
||||
<div class="cell is-col-span-2">
|
||||
<p><b>Anmerkungen:</b> {{ event.note.as_ref().unwrap_or(String::new()|as_ref) }}</p>
|
||||
<p><b>Anmerkungen:</b> {{ event.note.as_ref().unwrap_or(String::new()|ref) }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -45,23 +45,23 @@
|
||||
<div class="buttons has-addons">
|
||||
<button hx-post="/assignments/new?event={{ event.id }}&availabillity={{ availabillity.id }}&function=1"
|
||||
hx-target="closest table" hx-swap="outerHTML" class="button is-small" {% if !further_posten_required ||
|
||||
status !=AvailabillityAssignmentState::Unassigned|as_ref %}disabled{% endif %}>Posten</button>
|
||||
status !=AvailabillityAssignmentState::Unassigned|ref %}disabled{% endif %}>Posten</button>
|
||||
{% if u.function == Function::Wachhabender || u.function == Function::Fuehrungsassistent %}
|
||||
<button hx-post="/assignments/new?event={{ event.id }}&availabillity={{ availabillity.id }}&function=5"
|
||||
hx-target="closest table" hx-swap="outerHTML" class="button is-small" {% if
|
||||
!further_fuehrungsassistent_required || status !=AvailabillityAssignmentState::Unassigned|as_ref
|
||||
!further_fuehrungsassistent_required || status !=AvailabillityAssignmentState::Unassigned|ref
|
||||
%}disabled{% endif %}>Führungsassistent</button>
|
||||
{% endif %}
|
||||
{% if u.function == Function::Wachhabender %}
|
||||
<button hx-post="/assignments/new?event={{ event.id }}&availabillity={{ availabillity.id }}&function=10"
|
||||
hx-target="closest table" hx-swap="outerHTML" class="button is-small" {% if !further_wachhabender_required
|
||||
|| status !=AvailabillityAssignmentState::Unassigned|as_ref %}disabled{% endif %}>Wachhabender</button>
|
||||
|| status !=AvailabillityAssignmentState::Unassigned|ref %}disabled{% endif %}>Wachhabender</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
{% if status != AvailabillityAssignmentState::Unassigned|as_ref && status !=
|
||||
AvailabillityAssignmentState::Conflicting|as_ref %}
|
||||
{% if status != AvailabillityAssignmentState::Unassigned|ref && status !=
|
||||
AvailabillityAssignmentState::Conflicting|ref %}
|
||||
<button hx-delete="/assignments/delete?event={{ event.id }}&availabillity={{ availabillity.id }}"
|
||||
hx-target="closest table" hx-swap="outerHTML" class="button is-small">Entplanen</button>
|
||||
{% endif %}
|
||||
|
@ -40,7 +40,7 @@
|
||||
{% let areaid = loc.area_id %}
|
||||
{% endif -%}
|
||||
{% for area in areas.as_ref().unwrap() %}
|
||||
<option {{ areaid|is_some_and_eq(area.id)|cond_show("selected") }} value="{{ area.id }}">{{
|
||||
<option {{ areaid|is_some_and_eq(area.id)|ref|cond_show("selected") }} value="{{ area.id }}">{{
|
||||
area.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
|
@ -48,10 +48,10 @@
|
||||
<div class="control">
|
||||
<div class="select is-fullwidth">
|
||||
<select name="role">
|
||||
<option value="1" {{ role|is_some_and_eq(1|as_ref)|cond_show("selected") }}>Personal</option>
|
||||
<option value="10" {{ role|is_some_and_eq(10|as_ref)|cond_show("selected") }}>Bereichsleiter
|
||||
<option value="1" {{ role|is_some_and_eq(1|ref)|ref|cond_show("selected") }}>Personal</option>
|
||||
<option value="10" {{ role|is_some_and_eq(10|ref)|ref|cond_show("selected") }}>Bereichsleiter
|
||||
</option>
|
||||
<option value="100" {{ role|is_some_and_eq(100|as_ref)|cond_show("selected") }}>Admin</option>
|
||||
<option value="100" {{ role|is_some_and_eq(100|ref)|ref|cond_show("selected") }}>Admin</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
@ -68,10 +68,10 @@
|
||||
<div class="control">
|
||||
<div class="select is-fullwidth">
|
||||
<select name="function">
|
||||
<option value="1" {{ function|is_some_and_eq(1|as_ref)|cond_show("selected") }}>Posten</option>
|
||||
<option value="1" {{ function|is_some_and_eq(5|as_ref)|cond_show("selected") }}>Führungsassistent
|
||||
<option value="1" {{ function|is_some_and_eq(1|ref)|ref|cond_show("selected") }}>Posten</option>
|
||||
<option value="1" {{ function|is_some_and_eq(5|ref)|ref|cond_show("selected") }}>Führungsassistent
|
||||
</option>
|
||||
<option value="10" {{ function|is_some_and_eq(10|as_ref)|cond_show("selected") }}>Wachhabender
|
||||
<option value="10" {{ function|is_some_and_eq(10|ref)|ref|cond_show("selected") }}>Wachhabender
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
@ -91,7 +91,7 @@
|
||||
<div class="select is-fullwidth">
|
||||
<select name="area">
|
||||
{% for area in areas.as_ref().unwrap() %}
|
||||
<option value="{{ area.id }}" {{ area_id|is_some_and_eq(area.id)|cond_show("selected") }}>{{
|
||||
<option value="{{ area.id }}" {{ area_id|is_some_and_eq(area.id)|ref|cond_show("selected") }}>{{
|
||||
area.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
|
Loading…
x
Reference in New Issue
Block a user