init
This commit is contained in:
89
libertas_api/src/services/user_service.rs
Normal file
89
libertas_api/src/services/user_service.rs
Normal file
@@ -0,0 +1,89 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use libertas_core::{
|
||||
error::{CoreError, CoreResult},
|
||||
models::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>,
|
||||
}
|
||||
|
||||
impl UserServiceImpl {
|
||||
pub fn new(
|
||||
repo: Arc<dyn UserRepository>,
|
||||
hasher: Arc<dyn PasswordHasher>,
|
||||
tokenizer: Arc<dyn TokenGenerator>,
|
||||
) -> Self {
|
||||
Self {
|
||||
repo,
|
||||
hasher,
|
||||
tokenizer,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[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 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(),
|
||||
};
|
||||
|
||||
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))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user