From 51b450c05c5501adba499627ee263e8b312e56d7 Mon Sep 17 00:00:00 2001 From: Ginger Date: Wed, 18 Mar 2026 10:26:43 -0400 Subject: [PATCH] feat: Use a context struct to store global template context --- src/web/mod.rs | 13 ++++--- src/web/pages/index.rs | 32 +++++++---------- src/web/pages/mod.rs | 48 +++++++++++++++++++++++++ src/web/pages/password_reset.rs | 32 ++++++----------- src/web/pages/templates/_layout.html.j2 | 2 +- 5 files changed, 82 insertions(+), 45 deletions(-) diff --git a/src/web/mod.rs b/src/web/mod.rs index 886317bc..876c667d 100644 --- a/src/web/mod.rs +++ b/src/web/mod.rs @@ -9,6 +9,8 @@ use conduwuit_service::state; use tower_http::set_header::SetResponseHeaderLayer; use tower_sec_fetch::SecFetchLayer; +use crate::pages::TemplateContext; + mod pages; type State = state::State; @@ -40,8 +42,9 @@ impl IntoResponse for WebError { struct Error { error: WebError, status: StatusCode, - allow_indexing: bool, + context: TemplateContext, } + let status = match &self { | Self::ValidationError(_) | Self::BadRequest(_) @@ -54,9 +57,11 @@ impl IntoResponse for WebError { let template = Error { error: self, status, - // Statically set false to prevent error pages from being indexed and to prevent - // further errors if services.config is having issues. - allow_indexing: false, + context: TemplateContext { + // Statically set false to prevent error pages from being indexed and to prevent + // further errors if services.config is having issues. + allow_indexing: false, + }, }; if let Ok(body) = template.render() { diff --git a/src/web/pages/index.rs b/src/web/pages/index.rs index ba7fc4df..76cad1c4 100644 --- a/src/web/pages/index.rs +++ b/src/web/pages/index.rs @@ -1,30 +1,24 @@ use askama::Template; -use axum::{ - Router, - extract::State, - response::{Html, IntoResponse}, - routing::get, -}; +use axum::{Router, extract::State, response::IntoResponse, routing::get}; -use crate::WebError; +use crate::{WebError, template}; pub(crate) fn build() -> Router { Router::new().route("/", get(index_handler)) } async fn index_handler( State(services): State, ) -> Result { - #[derive(Debug, Template)] - #[template(path = "index.html.j2")] - struct Index<'a> { - server_name: &'a str, - first_run: bool, - allow_indexing: bool, + template! { + struct Index<'a> use "index.html.j2" { + server_name: &'a str, + first_run: bool + } } - let template = Index { - server_name: services.globals.server_name().as_str(), - first_run: services.firstrun.is_first_run(), - allow_indexing: services.config.index_page_allow_indexing, - }; - Ok(Html(template.render()?)) + Ok(Index::new( + &services, + services.globals.server_name().as_str(), + services.firstrun.is_first_run(), + ) + .into_response()) } diff --git a/src/web/pages/mod.rs b/src/web/pages/mod.rs index ae653a43..52ed5552 100644 --- a/src/web/pages/mod.rs +++ b/src/web/pages/mod.rs @@ -2,3 +2,51 @@ mod components; pub(super) mod index; pub(super) mod password_reset; pub(super) mod resources; + +#[derive(Debug)] +pub(crate) struct TemplateContext { + pub allow_indexing: bool, +} + +impl From<&crate::State> for TemplateContext { + fn from(state: &crate::State) -> Self { + Self { + allow_indexing: state.config.index_page_allow_indexing, + } + } +} + +#[macro_export] +macro_rules! template { + ( + struct $name:ident $(<$lifetime:lifetime>)? use $path:literal { + $($field_name:ident: $field_type:ty),* + } + ) => { + #[derive(Debug, askama::Template)] + #[template(path = $path)] + struct $name$(<$lifetime>)? { + context: $crate::pages::TemplateContext, + $($field_name: $field_type,)* + } + + impl$(<$lifetime>)? $name$(<$lifetime>)? { + fn new(state: &$crate::State, $($field_name: $field_type,)*) -> Self { + Self { + context: state.into(), + $($field_name,)* + } + } + } + + #[allow(single_use_lifetimes)] + impl$(<$lifetime>)? axum::response::IntoResponse for $name$(<$lifetime>)? { + fn into_response(self) -> axum::response::Response { + match self.render() { + Ok(rendered) => axum::response::Html(rendered).into_response(), + Err(err) => $crate::WebError::from(err).into_response() + } + } + } + }; +} diff --git a/src/web/pages/password_reset.rs b/src/web/pages/password_reset.rs index 3d95232e..f5d9b8d0 100644 --- a/src/web/pages/password_reset.rs +++ b/src/web/pages/password_reset.rs @@ -6,7 +6,7 @@ use axum::{ rejection::{FormRejection, QueryRejection}, }, http::StatusCode, - response::{Html, IntoResponse, Response}, + response::{IntoResponse, Response}, routing::get, }; use serde::Deserialize; @@ -15,6 +15,7 @@ use validator::Validate; use crate::{ WebError, form, pages::components::{UserCard, form::Form}, + template, }; #[derive(Deserialize)] @@ -22,12 +23,11 @@ struct PasswordResetQuery { token: String, } -#[derive(Debug, Template)] -#[template(path = "password_reset.html.j2")] -struct PasswordReset<'a> { - user_card: UserCard<'a>, - body: PasswordResetBody, - allow_indexing: bool, +template! { + struct PasswordReset<'a> use "password_reset.html.j2" { + user_card: UserCard<'a>, + body: PasswordResetBody + } } #[derive(Debug)] @@ -72,13 +72,8 @@ async fn password_reset_form( let user_card = UserCard::for_local_user(&services, &token.info.user).await; - let template = PasswordReset { - user_card, - body: PasswordResetBody::Form(reset_form), - allow_indexing: services.config.index_page_allow_indexing, - }; - - Ok(Html(template.render()?)) + Ok(PasswordReset::new(&services, user_card, PasswordResetBody::Form(reset_form)) + .into_response()) } async fn get_password_reset( @@ -111,13 +106,8 @@ async fn post_password_reset( .await?; let user_card = UserCard::for_local_user(&services, &user_id).await; - let template = PasswordReset { - user_card, - body: PasswordResetBody::Success, - allow_indexing: services.config.index_page_allow_indexing, - }; - - Ok(Html(template.render()?).into_response()) + Ok(PasswordReset::new(&services, user_card, PasswordResetBody::Success) + .into_response()) }, | Err(err) => Ok(( StatusCode::BAD_REQUEST, diff --git a/src/web/pages/templates/_layout.html.j2 b/src/web/pages/templates/_layout.html.j2 index 25eac50c..c79f8247 100644 --- a/src/web/pages/templates/_layout.html.j2 +++ b/src/web/pages/templates/_layout.html.j2 @@ -5,7 +5,7 @@ {% block title %}Continuwuity{% endblock %} - {%- if !allow_indexing %} + {%- if !context.allow_indexing %} {%- endif %}