Files
komp_ac/server/src/auth/handlers/register.rs
2025-07-26 20:34:02 +02:00

73 lines
2.4 KiB
Rust

// src/auth/handlers/register.rs
use bcrypt::{hash, DEFAULT_COST};
use tonic::{Response, Status};
use common::proto::komp_ac::auth::{RegisterRequest, AuthResponse};
use crate::db::PgPool;
use crate::auth::models::AuthError;
const DEFAULT_ROLE: &str = "accountant";
pub async fn register(
pool: &PgPool,
payload: RegisterRequest,
) -> Result<Response<AuthResponse>, Status> {
// Validate required fields
if payload.email.trim().is_empty() {
return Err(Status::invalid_argument("Email is required"));
}
// Validate passwords match
if payload.password != payload.password_confirmation {
return Err(Status::invalid_argument(AuthError::PasswordMismatch.to_string()));
}
// Hash password
let password_hash = hash(payload.password, DEFAULT_COST)
.map_err(|e| Status::internal(AuthError::HashingError(e.to_string()).to_string()))?;
let role_to_insert = if payload.role.is_empty() { DEFAULT_ROLE } else { &payload.role };
// Insert user
let user = sqlx::query!(
r#"
INSERT INTO users (username, email, password_hash, role)
VALUES ($1, $2, $3, $4)
RETURNING id, username, email, role
"#,
payload.username,
payload.email,
password_hash,
role_to_insert
)
.fetch_one(pool)
.await
.map_err(|e| {
if let Some(db_err) = e.as_database_error() {
if db_err.constraint() == Some("valid_roles") {
return Status::invalid_argument(format!("Invalid role specified: '{}'", role_to_insert));
}
// Check for specific constraint violations
if let Some(constraint) = db_err.constraint() {
if constraint.contains("users_username_key") {
return Status::already_exists("Username already exists".to_string());
}
if constraint.contains("users_email_key") {
return Status::already_exists("Email already exists".to_string());
}
}
}
if e.to_string().contains("duplicate key") {
Status::already_exists(AuthError::UserExists.to_string())
} else {
Status::internal(AuthError::DatabaseError(e.to_string()).to_string())
}
})?;
Ok(Response::new(AuthResponse {
id: user.id.to_string(),
username: user.username,
email: user.email.unwrap_or_default(),
role: user.role,
}))
}