use std::sync::Arc;
use async_trait::async_trait;
use email_address::EmailAddress;
use fistinc_errors::{CommonError, ServiceResult};
use crate::domain::entity::User;
use crate::domain::services::{UserAuthService, UserSecurityService};
use crate::domain::UserRepository;
pub struct UserAuthServiceImpl {
pub repository: Arc<dyn UserRepository>,
pub security: Arc<dyn UserSecurityService>,
}
impl UserAuthServiceImpl {
pub fn new(repository: Arc<dyn UserRepository>, security: Arc<dyn UserSecurityService>) -> Self {
UserAuthServiceImpl { repository, security }
}
}
#[async_trait]
impl UserAuthService for UserAuthServiceImpl {
async fn login(&self, email: &EmailAddress, password: &str) -> ServiceResult<(User, String)> {
let user = self
.repository
.find_by_email(email).await
.map_err(|e| -> CommonError { e.into() })?;
match user {
None => {
return Err(CommonError {
message: "UserNotFound".to_string(),
code: 404,
});
}
Some(user) => {
let is_valid = self
.security
.verify_hash(&user.password, password).await?;
if !is_valid {
Err(CommonError {
message: "InvalidPassword".to_string(),
code: 401,
})
} else {
let token = self
.security
.token_generator(&user).await?;
Ok((user, token))
}
}
}
}
}