1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
use crate::config::AuthConfig;
use crate::model::token::{TokenData, TokenModel, TokenType};
use crate::repository::{AuthRepositoryManager, TokenRepository};
use c3p0::*;
use lightspeed_core::error::LightSpeedError;
use lightspeed_core::service::validator::Validator;
use lightspeed_core::utils::*;
use log::*;

#[derive(Clone)]
pub struct TokenService<RepoManager: AuthRepositoryManager> {
    auth_config: AuthConfig,
    token_repo: RepoManager::TokenRepo,
}

impl<RepoManager: AuthRepositoryManager> TokenService<RepoManager> {
    pub fn new(auth_config: AuthConfig, token_repo: RepoManager::TokenRepo) -> Self {
        TokenService {
            auth_config,
            token_repo,
        }
    }

    pub async fn generate_and_save_token_with_conn<S: Into<String>>(
        &self,
        conn: &mut RepoManager::Conn,
        username: S,
        token_type: TokenType,
    ) -> Result<TokenModel, LightSpeedError> {
        let username = username.into();
        info!(
            "Generate and save token of type [{:?}] for username [{}]",
            token_type, username
        );

        let issued_at = current_epoch_seconds();
        let expire_at_epoch = issued_at + (self.auth_config.activation_token_validity_minutes * 60);
        let token = NewModel::new(TokenData {
            token: new_hyphenated_uuid(),
            token_type,
            username,
            expire_at_epoch_seconds: expire_at_epoch,
        });
        self.token_repo.save(conn, token).await
    }

    pub async fn fetch_by_token_with_conn(
        &self,
        conn: &mut RepoManager::Conn,
        token: &str,
        validate: bool,
    ) -> Result<TokenModel, LightSpeedError> {
        debug!("Fetch by token [{}]", token);
        let token_model = self.token_repo.fetch_by_token(conn, token).await?;

        if validate {
            Validator::validate(&token_model.data)?;
        };

        Ok(token_model)
    }

    pub async fn fetch_all_by_username_with_conn(
        &self,
        conn: &mut RepoManager::Conn,
        username: &str,
    ) -> Result<Vec<TokenModel>, LightSpeedError> {
        debug!("Fetch by username [{}]", username);
        self.token_repo.fetch_by_username(conn, username).await
    }

    pub async fn delete_with_conn(
        &self,
        conn: &mut RepoManager::Conn,
        token_model: TokenModel,
    ) -> Result<TokenModel, LightSpeedError> {
        debug!(
            "Delete token_model with id [{}] and token [{}]",
            token_model.id, token_model.data.token
        );
        self.token_repo.delete(conn, token_model).await
    }
}