Authentication and form for newsletter publishing

This commit is contained in:
Alphonse Paix
2025-09-01 15:47:27 +02:00
parent 6f6e6ab017
commit d47fba5cc9
16 changed files with 394 additions and 408 deletions

View File

@@ -1,9 +1,12 @@
use crate::telemetry::spawn_blocking_with_tracing;
use crate::{
routes::AdminError, session_state::TypedSession, telemetry::spawn_blocking_with_tracing,
};
use anyhow::Context;
use argon2::{
Algorithm, Argon2, Params, PasswordHash, PasswordHasher, PasswordVerifier, Version,
password_hash::{SaltString, rand_core::OsRng},
};
use axum::{extract::Request, middleware::Next, response::Response};
use secrecy::{ExposeSecret, SecretString};
use sqlx::PgPool;
use uuid::Uuid;
@@ -19,6 +22,8 @@ pub enum AuthError {
UnexpectedError(#[from] anyhow::Error),
#[error("Invalid credentials.")]
InvalidCredentials(#[source] anyhow::Error),
#[error("Not authenticated.")]
NotAuthenticated,
}
#[tracing::instrument(name = "Change password", skip(password, connection_pool))]
@@ -125,3 +130,34 @@ async fn get_stored_credentials(
.map(|row| (row.user_id, SecretString::from(row.password_hash)));
Ok(row)
}
pub async fn require_auth(
session: TypedSession,
mut request: Request,
next: Next,
) -> Result<Response, AdminError> {
let user_id = session
.get_user_id()
.await
.map_err(|e| AdminError::UnexpectedError(e.into()))?
.ok_or(AdminError::NotAuthenticated)?;
let username = session
.get_username()
.await
.map_err(|e| AdminError::UnexpectedError(e.into()))?
.ok_or(AdminError::UnexpectedError(anyhow::anyhow!(
"Could not find username in session."
)))?;
request
.extensions_mut()
.insert(AuthenticatedUser { user_id, username });
Ok(next.run(request).await)
}
#[derive(Clone)]
pub struct AuthenticatedUser {
pub user_id: Uuid,
pub username: String,
}