use std::time::SystemTime; use axum::{ debug_handler, extract::State, response::{IntoResponse, Response}, Json, }; use http::StatusCode; use pasetors::{keys::SymmetricKey, version4::V4}; use tracing::debug; use crate::{ db::{get_username_and_password_by_username, DbPool, UserIdAndHashedPasswordEntity}, models::{ApiResponse, AppError, Session}, requests::{ auth::login::models::{AuthLoginResponse, AuthLoginTokenData}, AppState, }, services::{ auth_token::{generate_auth_token, generate_session_token, store_user_auth_token}, user_session, verify_password, CachePool, }, }; use super::models::AuthLoginRequest; #[debug_handler] pub async fn auth_login_post_handler( State(state): State, Json(body): Json, ) -> Result { let db_pool = state.db_pool(); let cache_pool = state.cache_pool(); let token_key = state.env().token_key(); auth_login_request(db_pool, cache_pool, token_key, body).await } async fn auth_login_request( db_pool: &DbPool, cache_pool: &CachePool, token_key: &SymmetricKey, body: AuthLoginRequest, ) -> Result { debug!(?body); let AuthLoginRequest { username, password } = body; let UserIdAndHashedPasswordEntity { id: user_id, password: hashed_password, } = get_username_and_password_by_username(db_pool, username).await?; verify_password(password, hashed_password)?; let ((session_token, session_token_expiration), (auth_token, auth_token_expiration)) = generate_login_auth_and_session_tokens(cache_pool, token_key, user_id).await?; let response = AuthLoginResponse { user_id, session: AuthLoginTokenData { token: session_token, expiration: session_token_expiration, }, auth: AuthLoginTokenData { token: auth_token, expiration: auth_token_expiration, }, }; Ok(( StatusCode::OK, ApiResponse::new(response).into_json_response(), ) .into_response()) } pub async fn generate_login_auth_and_session_tokens( cache_pool: &CachePool, token_key: &SymmetricKey, user_id: i32, ) -> Result<((String, SystemTime), (String, SystemTime)), AppError> { let (session_token, session_token_id, session_token_expiration) = generate_session_token(token_key, user_id); let (auth_token, _, auth_token_expiration) = generate_auth_token(token_key, user_id); store_user_auth_token( cache_pool, user_id, auth_token.as_str(), auth_token_expiration .duration_since(SystemTime::now()) .unwrap(), ) .await?; let session = Session { user_id, created_at: SystemTime::now(), expires_at: auth_token_expiration, }; let expiration = session_token_expiration .duration_since(SystemTime::now()) .unwrap(); user_session::store_user_session(cache_pool, session_token_id, session, Some(expiration)) .await?; Ok(( (session_token, session_token_expiration), (auth_token, auth_token_expiration), )) }