register users

This commit is contained in:
2025-07-16 18:37:26 +02:00
parent 990f196984
commit be362326aa
48 changed files with 1002 additions and 64 deletions

View File

@@ -1,4 +1,4 @@
use crate::domain::warren::ports::{FileSystemMetrics, WarrenMetrics};
use crate::domain::warren::ports::{AuthMetrics, FileSystemMetrics, WarrenMetrics};
#[derive(Debug, Clone, Copy)]
pub struct MetricsDebugLogger;
@@ -122,3 +122,12 @@ impl FileSystemMetrics for MetricsDebugLogger {
tracing::debug!("[Metrics] Entry rename failed");
}
}
impl AuthMetrics for MetricsDebugLogger {
async fn record_user_registration_success(&self) {
tracing::debug!("[Metrics] User registration succeeded");
}
async fn record_user_registration_failure(&self) {
tracing::debug!("[Metrics] User registration failed");
}
}

View File

@@ -1,9 +1,10 @@
use crate::domain::warren::{
models::{
file::{File, FilePath},
user::User,
warren::Warren,
},
ports::{FileSystemNotifier, WarrenNotifier},
ports::{AuthNotifier, FileSystemNotifier, WarrenNotifier},
};
#[derive(Debug, Clone, Copy)]
@@ -112,3 +113,9 @@ impl FileSystemNotifier for NotifierDebugLogger {
tracing::debug!("[Notifier] Renamed file {} to {}", old_path, new_path);
}
}
impl AuthNotifier for NotifierDebugLogger {
async fn user_registered(&self, user: &User) {
tracing::debug!("[Notifier] Registered user {}", user.name());
}
}

View File

@@ -1,6 +1,10 @@
use std::str::FromStr;
use anyhow::{Context, anyhow};
use argon2::{
Argon2,
password_hash::{PasswordHasher, SaltString, rand_core::OsRng},
};
use sqlx::{
ConnectOptions as _, Connection as _, PgConnection, PgPool,
postgres::{PgConnectOptions, PgPoolOptions},
@@ -8,10 +12,13 @@ use sqlx::{
use uuid::Uuid;
use crate::domain::warren::{
models::warren::{
FetchWarrenError, FetchWarrenRequest, ListWarrensError, ListWarrensRequest, Warren,
models::{
user::{RegisterUserError, RegisterUserRequest, User, UserEmail, UserName, UserPassword},
warren::{
FetchWarrenError, FetchWarrenRequest, ListWarrensError, ListWarrensRequest, Warren,
},
},
ports::WarrenRepository,
ports::{AuthRepository, WarrenRepository},
};
#[derive(Debug, Clone)]
@@ -98,6 +105,52 @@ impl Postgres {
Ok(warrens)
}
async fn create_user(
&self,
connection: &mut PgConnection,
name: &UserName,
email: &UserEmail,
password: &UserPassword,
is_admin: bool,
) -> anyhow::Result<User> {
let salt = SaltString::generate(&mut OsRng);
let argon2 = Argon2::default();
let password_hash = argon2
.hash_password(password.as_str().as_bytes(), &salt)
.map_err(|_| anyhow!("Failed to hash password"))?
.to_string();
let mut tx = connection.begin().await?;
let user: User = sqlx::query_as(
"INSERT INTO users (
name,
email,
hash,
admin
)
VALUES (
$1,
$2,
$3,
$4
)
RETURNING
*
",
)
.bind(name)
.bind(email)
.bind(password_hash)
.bind(is_admin)
.fetch_one(&mut *tx)
.await?;
tx.commit().await?;
Ok(user)
}
}
impl WarrenRepository for Postgres {
@@ -143,6 +196,29 @@ impl WarrenRepository for Postgres {
}
}
impl AuthRepository for Postgres {
async fn register_user(&self, request: RegisterUserRequest) -> Result<User, RegisterUserError> {
let mut connection = self
.pool
.acquire()
.await
.context("Failed to get a PostgreSQL connection")?;
let user = self
.create_user(
&mut connection,
request.name(),
request.email(),
request.password(),
false,
)
.await
.context(format!("Failed to create user"))?;
Ok(user)
}
}
fn is_not_found_error(err: &sqlx::Error) -> bool {
matches!(err, sqlx::Error::RowNotFound)
}