Admin dashboard and sessions

This commit is contained in:
Alphonse Paix
2025-09-01 03:08:43 +02:00
parent de1fc4a825
commit 6f6e6ab017
23 changed files with 809 additions and 56 deletions

View File

@@ -1,11 +1,13 @@
use crate::telemetry::spawn_blocking_with_tracing;
use anyhow::Context;
use argon2::{Argon2, PasswordHash, PasswordVerifier};
use argon2::{
Algorithm, Argon2, Params, PasswordHash, PasswordHasher, PasswordVerifier, Version,
password_hash::{SaltString, rand_core::OsRng},
};
use secrecy::{ExposeSecret, SecretString};
use sqlx::PgPool;
use uuid::Uuid;
use crate::telemetry::spawn_blocking_with_tracing;
pub struct Credentials {
pub username: String,
pub password: SecretString,
@@ -19,6 +21,38 @@ pub enum AuthError {
InvalidCredentials(#[source] anyhow::Error),
}
#[tracing::instrument(name = "Change password", skip(password, connection_pool))]
pub async fn change_password(
user_id: Uuid,
password: SecretString,
connection_pool: &PgPool,
) -> Result<(), anyhow::Error> {
let password_hash = spawn_blocking_with_tracing(move || compute_pasword_hash(password))
.await?
.context("Failed to hash password")?;
sqlx::query!(
"UPDATE users SET password_hash = $1 WHERE user_id = $2",
password_hash.expose_secret(),
user_id
)
.execute(connection_pool)
.await
.context("Failed to update user password in the database.")?;
Ok(())
}
fn compute_pasword_hash(password: SecretString) -> Result<SecretString, anyhow::Error> {
let salt = SaltString::generate(&mut OsRng);
let password_hash = Argon2::new(
Algorithm::Argon2id,
Version::V0x13,
Params::new(1500, 2, 1, None).unwrap(),
)
.hash_password(password.expose_secret().as_bytes(), &salt)?
.to_string();
Ok(SecretString::from(password_hash))
}
#[tracing::instrument(
name = "Validate credentials",
skip(username, password, connection_pool)