From 7b70b79bf002e3f50a768e1f2a55f9559f76b9ce Mon Sep 17 00:00:00 2001 From: Lennart <18233294+lennart-k@users.noreply.github.com> Date: Sat, 12 Apr 2025 12:15:50 +0200 Subject: [PATCH] use askama_web to make template responses more ergonomic --- Cargo.lock | 23 +++++++++++++++++ Cargo.toml | 1 + crates/frontend/Cargo.toml | 1 + crates/frontend/src/lib.rs | 30 ++++++++++------------- crates/frontend/src/routes/addressbook.rs | 22 +++++++---------- crates/frontend/src/routes/calendar.rs | 22 +++++++---------- crates/frontend/src/routes/login.rs | 13 +++++----- 7 files changed, 62 insertions(+), 50 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fc63227..15c5c56 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -425,6 +425,28 @@ dependencies = [ "winnow", ] +[[package]] +name = "askama_web" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b939333ab32b63d49be3a84492eefacff005ed369ac331e1597d1839e3c62f11" +dependencies = [ + "actix-web", + "askama", + "askama_web_derive", +] + +[[package]] +name = "askama_web_derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34921de3d57974069bad483fdfe0ec65d88c4ff892edd1ab4d8b03be0dda1b9b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "async-trait" version = "0.1.88" @@ -2828,6 +2850,7 @@ dependencies = [ "actix-session", "actix-web", "askama", + "askama_web", "futures-core", "hex", "mime_guess", diff --git a/Cargo.toml b/Cargo.toml index 70e5e06..8f41a80 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -74,6 +74,7 @@ derive_more = { version = "2.0", features = [ "constructor", ] } askama = { version = "0.13", features = ["serde_json"] } +askama_web = { version = "0.13.0", features = ["actix-web-4"] } sqlx = { version = "0.8", default-features = false, features = [ "sqlx-sqlite", "uuid", diff --git a/crates/frontend/Cargo.toml b/crates/frontend/Cargo.toml index d9be442..616ca8c 100644 --- a/crates/frontend/Cargo.toml +++ b/crates/frontend/Cargo.toml @@ -8,6 +8,7 @@ publish = false [dependencies] askama.workspace = true +askama_web.workspace = true actix-session = { workspace = true } serde = { workspace = true } thiserror = { workspace = true } diff --git a/crates/frontend/src/lib.rs b/crates/frontend/src/lib.rs index 5a45bd2..5d74a13 100644 --- a/crates/frontend/src/lib.rs +++ b/crates/frontend/src/lib.rs @@ -1,15 +1,16 @@ use actix_session::{ - config::CookieContentSecurity, storage::CookieSessionStore, SessionMiddleware, + SessionMiddleware, config::CookieContentSecurity, storage::CookieSessionStore, }; use actix_web::{ + HttpRequest, HttpResponse, Responder, cookie::{Key, SameSite}, dev::ServiceResponse, http::{Method, StatusCode}, middleware::{ErrorHandlerResponse, ErrorHandlers}, - web::{self, Data, Html, Path}, - HttpRequest, HttpResponse, Responder, + web::{self, Data, Path}, }; use askama::Template; +use askama_web::WebTemplate; use assets::{Assets, EmbedService}; use routes::{ addressbook::{route_addressbook, route_addressbook_restore}, @@ -17,8 +18,8 @@ use routes::{ login::{route_get_login, route_post_login}, }; use rustical_store::{ - auth::{AuthenticationMiddleware, AuthenticationProvider, User}, Addressbook, AddressbookStore, Calendar, CalendarStore, + auth::{AuthenticationMiddleware, AuthenticationProvider, User}, }; use std::sync::Arc; @@ -28,7 +29,7 @@ mod routes; pub use config::FrontendConfig; -#[derive(Template)] +#[derive(Template, WebTemplate)] #[template(path = "pages/user.html")] struct UserPage { pub user_id: String, @@ -51,19 +52,14 @@ async fn route_user( return actix_web::HttpResponse::Unauthorized().body("Unauthorized"); } - Html::new( - UserPage { - calendars: cal_store.get_calendars(&user.id).await.unwrap(), - deleted_calendars: cal_store.get_deleted_calendars(&user.id).await.unwrap(), - addressbooks: addr_store.get_addressbooks(&user.id).await.unwrap(), - deleted_addressbooks: addr_store.get_deleted_addressbooks(&user.id).await.unwrap(), - user_id: user.id, - } - .render() - .unwrap(), - ) + UserPage { + calendars: cal_store.get_calendars(&user.id).await.unwrap(), + deleted_calendars: cal_store.get_deleted_calendars(&user.id).await.unwrap(), + addressbooks: addr_store.get_addressbooks(&user.id).await.unwrap(), + deleted_addressbooks: addr_store.get_deleted_addressbooks(&user.id).await.unwrap(), + user_id: user.id, + } .respond_to(&req) - .map_into_boxed_body() } async fn route_root(user: Option, req: HttpRequest) -> impl Responder { diff --git a/crates/frontend/src/routes/addressbook.rs b/crates/frontend/src/routes/addressbook.rs index 4c7e9fb..700087e 100644 --- a/crates/frontend/src/routes/addressbook.rs +++ b/crates/frontend/src/routes/addressbook.rs @@ -1,12 +1,13 @@ use actix_web::{ - http::{header, StatusCode}, - web::{self, Data, Html, Path}, HttpRequest, HttpResponse, Responder, + http::{StatusCode, header}, + web::{self, Data, Path}, }; use askama::Template; -use rustical_store::{auth::User, Addressbook, AddressbookStore}; +use askama_web::WebTemplate; +use rustical_store::{Addressbook, AddressbookStore, auth::User}; -#[derive(Template)] +#[derive(Template, WebTemplate)] #[template(path = "pages/addressbook.html")] struct AddressbookPage { addressbook: Addressbook, @@ -22,15 +23,10 @@ pub async fn route_addressbook( if !user.is_principal(&owner) { return Ok(HttpResponse::Unauthorized().body("Unauthorized")); } - Ok(Html::new( - AddressbookPage { - addressbook: store.get_addressbook(&owner, &addrbook_id).await?, - } - .render() - .unwrap(), - ) - .respond_to(&req) - .map_into_boxed_body()) + Ok(AddressbookPage { + addressbook: store.get_addressbook(&owner, &addrbook_id).await?, + } + .respond_to(&req)) } pub async fn route_addressbook_restore( diff --git a/crates/frontend/src/routes/calendar.rs b/crates/frontend/src/routes/calendar.rs index b70fad2..fd604f7 100644 --- a/crates/frontend/src/routes/calendar.rs +++ b/crates/frontend/src/routes/calendar.rs @@ -1,12 +1,13 @@ use actix_web::{ - http::{header, StatusCode}, - web::{self, Data, Html, Path}, HttpRequest, HttpResponse, Responder, + http::{StatusCode, header}, + web::{self, Data, Path}, }; use askama::Template; -use rustical_store::{auth::User, Calendar, CalendarStore}; +use askama_web::WebTemplate; +use rustical_store::{Calendar, CalendarStore, auth::User}; -#[derive(Template)] +#[derive(Template, WebTemplate)] #[template(path = "pages/calendar.html")] struct CalendarPage { calendar: Calendar, @@ -22,15 +23,10 @@ pub async fn route_calendar( if !user.is_principal(&owner) { return Ok(HttpResponse::Unauthorized().body("Unauthorized")); } - Ok(Html::new( - CalendarPage { - calendar: store.get_calendar(&owner, &cal_id).await?, - } - .render() - .unwrap(), - ) - .respond_to(&req) - .map_into_boxed_body()) + Ok(CalendarPage { + calendar: store.get_calendar(&owner, &cal_id).await?, + } + .respond_to(&req)) } pub async fn route_calendar_restore( diff --git a/crates/frontend/src/routes/login.rs b/crates/frontend/src/routes/login.rs index 44f1e58..58135a8 100644 --- a/crates/frontend/src/routes/login.rs +++ b/crates/frontend/src/routes/login.rs @@ -1,21 +1,20 @@ use actix_session::Session; use actix_web::{ - error::ErrorUnauthorized, - web::{Data, Form, Html, Redirect}, HttpRequest, HttpResponse, Responder, + error::ErrorUnauthorized, + web::{Data, Form, Redirect}, }; use askama::Template; +use askama_web::WebTemplate; use rustical_store::auth::AuthenticationProvider; use serde::Deserialize; -#[derive(Template)] +#[derive(Template, WebTemplate)] #[template(path = "pages/login.html")] struct LoginPage; -pub async fn route_get_login(req: HttpRequest) -> impl Responder { - Html::new(LoginPage.render().unwrap()) - .respond_to(&req) - .map_into_boxed_body() +pub async fn route_get_login() -> impl Responder { + LoginPage } #[derive(Deserialize)]