fistinc-auth 0.1.0

Paging types for Fist Inc bank
Documentation
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?;
                    //todo save login action
                    Ok((user, token))
                }
            }
        }
    }
}