register users
This commit is contained in:
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user