Register form and confirmation messages

This commit is contained in:
Alphonse Paix
2025-09-04 23:39:53 +02:00
parent 3057fdc927
commit 767fc571b6
13 changed files with 160 additions and 45 deletions

View File

@@ -8,8 +8,9 @@ use axum::{
Form, Json,
extract::State,
http::StatusCode,
response::{IntoResponse, Response},
response::{IntoResponse, Redirect, Response},
};
use axum_messages::Messages;
use chrono::Utc;
use rand::{Rng, distr::Alphanumeric};
use serde::Deserialize;
@@ -63,12 +64,16 @@ impl IntoResponse for SubscribeError {
tracing::error!("{:?}", self);
let status = match self {
SubscribeError::UnexpectedError(_) => StatusCode::INTERNAL_SERVER_ERROR,
SubscribeError::ValidationError(_) => StatusCode::BAD_REQUEST,
};
let message = "An internal server error occured.";
(status, Json(ErrorResponse { message })).into_response()
match self {
SubscribeError::UnexpectedError(_) => (
StatusCode::INTERNAL_SERVER_ERROR,
Json(ErrorResponse {
message: "An internal server error occured.",
}),
)
.into_response(),
SubscribeError::ValidationError(_) => Redirect::to("/register").into_response(),
}
}
}
@@ -81,6 +86,7 @@ impl IntoResponse for SubscribeError {
)
)]
pub async fn subscribe(
messages: Messages,
State(AppState {
connection_pool,
email_client,
@@ -89,11 +95,17 @@ pub async fn subscribe(
}): State<AppState>,
Form(form): Form<SubscriptionFormData>,
) -> Result<Response, SubscribeError> {
let new_subscriber = match form.try_into() {
Ok(new_sub) => new_sub,
Err(e) => {
messages.error(&e);
return Err(SubscribeError::ValidationError(e));
}
};
let mut transaction = connection_pool
.begin()
.await
.context("Failed to acquire a Postgres connection from the pool.")?;
let new_subscriber = form.try_into().map_err(SubscribeError::ValidationError)?;
let subscriber_id = insert_subscriber(&mut transaction, &new_subscriber)
.await
.context("Failed to insert new subscriber in the database.")?;
@@ -113,7 +125,8 @@ pub async fn subscribe(
.commit()
.await
.context("Failed to commit the database transaction to store a new subscriber.")?;
Ok(StatusCode::OK.into_response())
messages.success("A confirmation email has been sent.");
Ok(Redirect::to("/register").into_response())
}
#[tracing::instrument(
@@ -198,6 +211,7 @@ Click <a href=\"{}\">here</a> to confirm your subscription.",
pub struct SubscriptionFormData {
name: String,
email: String,
email_check: String,
}
impl TryFrom<SubscriptionFormData> for NewSubscriber {
@@ -205,6 +219,9 @@ impl TryFrom<SubscriptionFormData> for NewSubscriber {
fn try_from(value: SubscriptionFormData) -> Result<Self, Self::Error> {
let name = SubscriberName::parse(value.name)?;
if value.email != value.email_check {
return Err("Email addresses don't match.".into());
}
let email = SubscriberEmail::parse(value.email)?;
Ok(Self { name, email })
}