refactor: update configuration handling to use environment variables and improve code organization
100 lines
2.9 KiB
Rust
100 lines
2.9 KiB
Rust
use std::sync::Arc;
|
|
|
|
use async_trait::async_trait;
|
|
use libertas_core::{
|
|
config::AppConfig,
|
|
error::{CoreError, CoreResult},
|
|
models::{Role, User},
|
|
repositories::UserRepository,
|
|
schema::{CreateUserData, LoginUserData},
|
|
services::UserService,
|
|
};
|
|
use uuid::Uuid;
|
|
|
|
use crate::security::{PasswordHasher, TokenGenerator};
|
|
|
|
pub struct UserServiceImpl {
|
|
repo: Arc<dyn UserRepository>,
|
|
hasher: Arc<dyn PasswordHasher>,
|
|
tokenizer: Arc<dyn TokenGenerator>,
|
|
config: Arc<AppConfig>,
|
|
}
|
|
|
|
impl UserServiceImpl {
|
|
pub fn new(
|
|
repo: Arc<dyn UserRepository>,
|
|
hasher: Arc<dyn PasswordHasher>,
|
|
tokenizer: Arc<dyn TokenGenerator>,
|
|
config: Arc<AppConfig>,
|
|
) -> Self {
|
|
Self {
|
|
repo,
|
|
hasher,
|
|
tokenizer,
|
|
config,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[async_trait]
|
|
impl UserService for UserServiceImpl {
|
|
async fn register(&self, data: CreateUserData<'_>) -> CoreResult<User> {
|
|
if data.username.is_empty() || data.email.is_empty() || data.password.is_empty() {
|
|
return Err(CoreError::Validation(
|
|
"Username, email, and password cannot be empty".to_string(),
|
|
));
|
|
}
|
|
|
|
if self.repo.find_by_email(data.email).await?.is_some() {
|
|
return Err(CoreError::Duplicate("Email already exists".to_string()));
|
|
}
|
|
if self.repo.find_by_username(data.username).await?.is_some() {
|
|
return Err(CoreError::Duplicate("Username already exists".to_string()));
|
|
}
|
|
|
|
let hashed_password = self.hasher.hash_password(data.password).await?;
|
|
|
|
let quota_gb = self.config.default_storage_quota_gb.unwrap_or(10);
|
|
let storage_quota = (quota_gb * 1024 * 1024 * 1024) as i64;
|
|
|
|
let user = User {
|
|
id: Uuid::new_v4(),
|
|
username: data.username.to_string(),
|
|
email: data.email.to_string(),
|
|
hashed_password,
|
|
created_at: chrono::Utc::now(),
|
|
updated_at: chrono::Utc::now(),
|
|
role: Role::User,
|
|
storage_quota,
|
|
storage_used: 0,
|
|
};
|
|
|
|
self.repo.create(user.clone()).await?;
|
|
|
|
Ok(user)
|
|
}
|
|
|
|
async fn login(&self, data: LoginUserData<'_>) -> CoreResult<String> {
|
|
let user = self
|
|
.repo
|
|
.find_by_email(data.username_or_email) // Allow login with email
|
|
.await?
|
|
.or(self.repo.find_by_username(data.username_or_email).await?) // Or username
|
|
.ok_or(CoreError::Auth("Invalid credentials".to_string()))?;
|
|
|
|
self.hasher
|
|
.verify_password(data.password, &user.hashed_password)
|
|
.await?;
|
|
|
|
// 3. Generate JWT token
|
|
self.tokenizer.generate_token(user.id)
|
|
}
|
|
|
|
async fn get_user_details(&self, user_id: Uuid) -> CoreResult<User> {
|
|
self.repo
|
|
.find_by_id(user_id)
|
|
.await?
|
|
.ok_or(CoreError::NotFound("User".to_string(), user_id))
|
|
}
|
|
}
|