Templates and TLS requests
All checks were successful
Rust / Test (push) Successful in 5m34s
Rust / Rustfmt (push) Successful in 22s
Rust / Clippy (push) Successful in 1m13s
Rust / Code coverage (push) Successful in 3m33s

Refactored HTML templates and added TLS back to issue HTTP requests
This commit is contained in:
Alphonse Paix
2025-09-29 02:39:53 +02:00
parent 3b727269c5
commit de44564ba0
29 changed files with 513 additions and 401 deletions

View File

@@ -27,7 +27,7 @@ pub use unsubscribe::*;
use crate::{
authentication::AuthError,
templates::{HtmlTemplate, InternalErrorTemplate, MessageTemplate, NotFoundTemplate},
templates::{ErrorTemplate, HtmlTemplate, MessageTemplate},
};
pub fn generate_token() -> String {
@@ -108,19 +108,16 @@ impl IntoResponse for AppError {
full_page,
} => {
let html = if *full_page {
Html(InternalErrorTemplate.render().unwrap())
Html(ErrorTemplate::InternalServer.render().unwrap())
} else {
let template = MessageTemplate::Error {
message: "An internal server error occured.".into(),
};
let template =
MessageTemplate::error("An internal server error occured.".into());
Html(template.render().unwrap())
};
html.into_response()
}
AppError::FormError(error) => {
let template = MessageTemplate::Error {
message: error.to_string(),
};
let template = MessageTemplate::error(error.to_string());
Html(template.render().unwrap()).into_response()
}
AppError::NotAuthenticated => {
@@ -164,7 +161,7 @@ pub async fn not_found() -> Response {
}
pub fn not_found_html() -> Response {
let template = HtmlTemplate(NotFoundTemplate);
let template = HtmlTemplate(ErrorTemplate::NotFound);
(StatusCode::NOT_FOUND, template).into_response()
}

View File

@@ -49,9 +49,7 @@ pub async fn change_password(
authentication::change_password(user_id, form.new_password, &connection_pool)
.await
.map_err(AdminError::ChangePassword)?;
let template = MessageTemplate::Success {
message: "Your password has been changed.".to_string(),
};
let template = MessageTemplate::success("Your password has been changed.".to_string());
Ok(Html(template.render().unwrap()).into_response())
}
}

View File

@@ -127,7 +127,7 @@ pub async fn publish_newsletter(
.context("Failed to enqueue delivery tasks.")?;
let message = String::from("Your email has been queued for delivery.");
let template = MessageTemplate::Success { message };
let template = MessageTemplate::success(message);
let response = Html(template.render().unwrap()).into_response();
let response = save_response(transaction, &idempotency_key, user_id, response)
.await

View File

@@ -73,9 +73,7 @@ pub async fn create_post(
.await
.context("Failed to enqueue delivery tasks.")?;
let template = MessageTemplate::Success {
message: "Your new post has been published!".into(),
};
let template = MessageTemplate::success("Your new post has been published!".into());
let response = Html(template.render().unwrap()).into_response();
let response = save_response(transaction, &idempotency_key, user_id, response)
.await
@@ -138,9 +136,7 @@ pub async fn delete_post(
"We could not find the post in the database."
)))
} else {
let template = MessageTemplate::Success {
message: "The subscriber has been deleted.".into(),
};
let template = MessageTemplate::success("The subscriber has been deleted.".into());
Ok(template.render().unwrap().into_response())
}
}

View File

@@ -63,12 +63,10 @@ pub async fn delete_subscriber(
.map_err(AppError::unexpected_message)?;
if let Some(record) = res {
tracing::Span::current().record("email", tracing::field::display(&record.email));
let template = MessageTemplate::Success {
message: format!(
"The subscriber with email '{}' has been deleted.",
record.email
),
};
let template = MessageTemplate::success(format!(
"The subscriber with email '{}' has been deleted.",
record.email
));
Ok(template.render().unwrap().into_response())
} else {
Err(AppError::unexpected_message(anyhow::anyhow!(

View File

@@ -66,9 +66,8 @@ pub async fn subscribe(
.context("Failed to commit the database transaction to store a new subscriber.")?;
}
let template = MessageTemplate::Success {
message: "You'll receive a confirmation email shortly.".to_string(),
};
let template =
MessageTemplate::success("You'll receive a confirmation email shortly.".to_string());
Ok(Html(template.render().unwrap()).into_response())
}

View File

@@ -1,11 +1,9 @@
use crate::{
domain::SubscriberEmail,
email_client::EmailClient,
routes::AppError,
routes::{AppError, not_found_html},
startup::AppState,
templates::{
MessageTemplate, NotFoundTemplate, UnsubscribeConfirmTemplate, UnsubscribeTemplate,
},
templates::{MessageTemplate, UnsubscribeConfirmTemplate, UnsubscribeTemplate},
};
use anyhow::Context;
use askama::Template;
@@ -14,7 +12,6 @@ use axum::{
extract::{Query, State},
response::{Html, IntoResponse, Response},
};
use reqwest::StatusCode;
use sqlx::{Executor, PgPool};
#[derive(serde::Deserialize)]
@@ -52,9 +49,9 @@ pub async fn post_unsubscribe(
.await
.context("Failed to send a confirmation email.")?;
}
let template = MessageTemplate::Success {
message: "If you are a subscriber, you'll receive a confirmation link shortly.".into(),
};
let template = MessageTemplate::success(
"If you are a subscriber, you'll receive a confirmation link shortly.".into(),
);
Ok(Html(template.render().unwrap()).into_response())
}
@@ -124,11 +121,7 @@ pub async fn unsubscribe_confirm(
if result.rows_affected() == 0 {
tracing::info!("Unsubscribe token is not tied to any confirmed user");
Ok((
StatusCode::NOT_FOUND,
Html(NotFoundTemplate.render().unwrap()),
)
.into_response())
Ok(not_found_html())
} else {
tracing::info!("User successfully removed");
Ok(Html(UnsubscribeConfirmTemplate.render().unwrap()).into_response())

View File

@@ -21,23 +21,33 @@ where
}
#[derive(Template)]
pub enum MessageTemplate {
#[template(path = "../templates/success.html")]
Success { message: String },
#[template(path = "../templates/error.html")]
Error { message: String },
#[template(path = "message.html")]
pub struct MessageTemplate {
pub message: String,
pub error: bool,
}
#[derive(Template)]
#[template(path = "../templates/500.html")]
pub struct InternalErrorTemplate;
impl MessageTemplate {
pub fn success(message: String) -> Self {
Self {
message,
error: false,
}
}
pub fn error(message: String) -> Self {
Self {
message,
error: true,
}
}
}
#[derive(Template)]
#[template(path = "../templates/login.html")]
pub struct LoginTemplate;
#[derive(Template)]
#[template(path = "../templates/dashboard.html")]
#[template(path = "dashboard/dashboard.html")]
pub struct DashboardTemplate {
pub username: String,
pub idempotency_key_1: String,
@@ -53,27 +63,27 @@ pub struct DashboardTemplate {
pub struct HomeTemplate;
#[derive(Template)]
#[template(path = "posts.html")]
#[template(path = "posts/list.html")]
pub struct PostsTemplate {
pub posts: Vec<PostEntry>,
pub next_page: Option<i64>,
}
#[derive(Template)]
#[template(path = "posts.html", block = "posts")]
#[template(path = "posts/list.html", block = "posts")]
pub struct PostListTemplate {
pub posts: Vec<PostEntry>,
pub next_page: Option<i64>,
}
#[derive(Template)]
#[template(path = "post.html")]
#[template(path = "posts/page.html")]
pub struct PostTemplate {
pub post: PostEntry,
}
#[derive(Template)]
#[template(path = "dashboard.html", block = "subs")]
#[template(path = "dashboard/subscribers/list.html", block = "subs")]
pub struct SubListTemplate {
pub subscribers: Vec<SubscriberEntry>,
pub current_page: i64,
@@ -81,19 +91,23 @@ pub struct SubListTemplate {
}
#[derive(Template)]
#[template(path = "confirm.html")]
#[template(path = "subscribe/confirm.html")]
pub struct ConfirmTemplate;
#[derive(Template)]
#[template(path = "404.html")]
pub struct NotFoundTemplate;
pub enum ErrorTemplate {
#[template(path = "error/404.html")]
NotFound,
#[template(path = "error/500.html")]
InternalServer,
}
#[derive(Template)]
#[template(path = "unsubscribe_confirm.html")]
#[template(path = "unsubscribe/confirm.html")]
pub struct UnsubscribeConfirmTemplate;
#[derive(Template)]
#[template(path = "unsubscribe.html")]
#[template(path = "unsubscribe/form.html")]
pub struct UnsubscribeTemplate;
#[derive(Template)]