debt-pirate/api/src/requests/auth/login/handler.rs

114 lines
3.2 KiB
Rust

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<AppState>,
Json(body): Json<AuthLoginRequest>,
) -> Result<Response, AppError> {
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<V4>,
body: AuthLoginRequest,
) -> Result<Response, AppError> {
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<V4>,
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),
))
}