use std::sync::Arc; use uuid::Uuid; use crate::entities::User; use crate::errors::{DomainError, DomainResult}; use crate::repositories::UserRepository; use crate::value_objects::Email; /// Service for managing users. pub struct UserService { user_repository: Arc, } impl UserService { pub fn new(user_repository: Arc) -> Self { Self { user_repository } } pub async fn find_or_create(&self, subject: &str, email: &str) -> DomainResult { if let Some(user) = self.user_repository.find_by_subject(subject).await? { return Ok(user); } if let Some(mut user) = self.user_repository.find_by_email(email).await? { if user.subject != subject { user.subject = subject.to_string(); self.user_repository.save(&user).await?; } return Ok(user); } let email = Email::try_from(email)?; let user = User::new(subject, email); self.user_repository.save(&user).await?; Ok(user) } pub async fn find_by_id(&self, id: Uuid) -> DomainResult { self.user_repository .find_by_id(id) .await? .ok_or(DomainError::UserNotFound(id)) } pub async fn find_by_email(&self, email: &str) -> DomainResult> { self.user_repository.find_by_email(email).await } pub async fn create_local( &self, email: &str, password_hash: &str, ) -> DomainResult { let email = Email::try_from(email)?; let user = User::new_local(email, password_hash); self.user_repository.save(&user).await?; Ok(user) } }