feat: Use a context struct to store global template context
This commit is contained in:
parent
f9d1f71343
commit
51b450c05c
5 changed files with 82 additions and 45 deletions
|
|
@ -9,6 +9,8 @@ use conduwuit_service::state;
|
||||||
use tower_http::set_header::SetResponseHeaderLayer;
|
use tower_http::set_header::SetResponseHeaderLayer;
|
||||||
use tower_sec_fetch::SecFetchLayer;
|
use tower_sec_fetch::SecFetchLayer;
|
||||||
|
|
||||||
|
use crate::pages::TemplateContext;
|
||||||
|
|
||||||
mod pages;
|
mod pages;
|
||||||
|
|
||||||
type State = state::State;
|
type State = state::State;
|
||||||
|
|
@ -40,8 +42,9 @@ impl IntoResponse for WebError {
|
||||||
struct Error {
|
struct Error {
|
||||||
error: WebError,
|
error: WebError,
|
||||||
status: StatusCode,
|
status: StatusCode,
|
||||||
allow_indexing: bool,
|
context: TemplateContext,
|
||||||
}
|
}
|
||||||
|
|
||||||
let status = match &self {
|
let status = match &self {
|
||||||
| Self::ValidationError(_)
|
| Self::ValidationError(_)
|
||||||
| Self::BadRequest(_)
|
| Self::BadRequest(_)
|
||||||
|
|
@ -54,9 +57,11 @@ impl IntoResponse for WebError {
|
||||||
let template = Error {
|
let template = Error {
|
||||||
error: self,
|
error: self,
|
||||||
status,
|
status,
|
||||||
// Statically set false to prevent error pages from being indexed and to prevent
|
context: TemplateContext {
|
||||||
// further errors if services.config is having issues.
|
// Statically set false to prevent error pages from being indexed and to prevent
|
||||||
allow_indexing: false,
|
// further errors if services.config is having issues.
|
||||||
|
allow_indexing: false,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Ok(body) = template.render() {
|
if let Ok(body) = template.render() {
|
||||||
|
|
|
||||||
|
|
@ -1,30 +1,24 @@
|
||||||
use askama::Template;
|
use askama::Template;
|
||||||
use axum::{
|
use axum::{Router, extract::State, response::IntoResponse, routing::get};
|
||||||
Router,
|
|
||||||
extract::State,
|
|
||||||
response::{Html, IntoResponse},
|
|
||||||
routing::get,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::WebError;
|
use crate::{WebError, template};
|
||||||
|
|
||||||
pub(crate) fn build() -> Router<crate::State> { Router::new().route("/", get(index_handler)) }
|
pub(crate) fn build() -> Router<crate::State> { Router::new().route("/", get(index_handler)) }
|
||||||
|
|
||||||
async fn index_handler(
|
async fn index_handler(
|
||||||
State(services): State<crate::State>,
|
State(services): State<crate::State>,
|
||||||
) -> Result<impl IntoResponse, WebError> {
|
) -> Result<impl IntoResponse, WebError> {
|
||||||
#[derive(Debug, Template)]
|
template! {
|
||||||
#[template(path = "index.html.j2")]
|
struct Index<'a> use "index.html.j2" {
|
||||||
struct Index<'a> {
|
server_name: &'a str,
|
||||||
server_name: &'a str,
|
first_run: bool
|
||||||
first_run: bool,
|
}
|
||||||
allow_indexing: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let template = Index {
|
Ok(Index::new(
|
||||||
server_name: services.globals.server_name().as_str(),
|
&services,
|
||||||
first_run: services.firstrun.is_first_run(),
|
services.globals.server_name().as_str(),
|
||||||
allow_indexing: services.config.index_page_allow_indexing,
|
services.firstrun.is_first_run(),
|
||||||
};
|
)
|
||||||
Ok(Html(template.render()?))
|
.into_response())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,3 +2,51 @@ mod components;
|
||||||
pub(super) mod index;
|
pub(super) mod index;
|
||||||
pub(super) mod password_reset;
|
pub(super) mod password_reset;
|
||||||
pub(super) mod resources;
|
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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ use axum::{
|
||||||
rejection::{FormRejection, QueryRejection},
|
rejection::{FormRejection, QueryRejection},
|
||||||
},
|
},
|
||||||
http::StatusCode,
|
http::StatusCode,
|
||||||
response::{Html, IntoResponse, Response},
|
response::{IntoResponse, Response},
|
||||||
routing::get,
|
routing::get,
|
||||||
};
|
};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
@ -15,6 +15,7 @@ use validator::Validate;
|
||||||
use crate::{
|
use crate::{
|
||||||
WebError, form,
|
WebError, form,
|
||||||
pages::components::{UserCard, form::Form},
|
pages::components::{UserCard, form::Form},
|
||||||
|
template,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
|
|
@ -22,12 +23,11 @@ struct PasswordResetQuery {
|
||||||
token: String,
|
token: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Template)]
|
template! {
|
||||||
#[template(path = "password_reset.html.j2")]
|
struct PasswordReset<'a> use "password_reset.html.j2" {
|
||||||
struct PasswordReset<'a> {
|
user_card: UserCard<'a>,
|
||||||
user_card: UserCard<'a>,
|
body: PasswordResetBody
|
||||||
body: PasswordResetBody,
|
}
|
||||||
allow_indexing: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
@ -72,13 +72,8 @@ async fn password_reset_form(
|
||||||
|
|
||||||
let user_card = UserCard::for_local_user(&services, &token.info.user).await;
|
let user_card = UserCard::for_local_user(&services, &token.info.user).await;
|
||||||
|
|
||||||
let template = PasswordReset {
|
Ok(PasswordReset::new(&services, user_card, PasswordResetBody::Form(reset_form))
|
||||||
user_card,
|
.into_response())
|
||||||
body: PasswordResetBody::Form(reset_form),
|
|
||||||
allow_indexing: services.config.index_page_allow_indexing,
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(Html(template.render()?))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_password_reset(
|
async fn get_password_reset(
|
||||||
|
|
@ -111,13 +106,8 @@ async fn post_password_reset(
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let user_card = UserCard::for_local_user(&services, &user_id).await;
|
let user_card = UserCard::for_local_user(&services, &user_id).await;
|
||||||
let template = PasswordReset {
|
Ok(PasswordReset::new(&services, user_card, PasswordResetBody::Success)
|
||||||
user_card,
|
.into_response())
|
||||||
body: PasswordResetBody::Success,
|
|
||||||
allow_indexing: services.config.index_page_allow_indexing,
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(Html(template.render()?).into_response())
|
|
||||||
},
|
},
|
||||||
| Err(err) => Ok((
|
| Err(err) => Ok((
|
||||||
StatusCode::BAD_REQUEST,
|
StatusCode::BAD_REQUEST,
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<title>{% block title %}Continuwuity{% endblock %}</title>
|
<title>{% block title %}Continuwuity{% endblock %}</title>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
{%- if !allow_indexing %}
|
{%- if !context.allow_indexing %}
|
||||||
<meta name="robots" content="noindex" />
|
<meta name="robots" content="noindex" />
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue