114 lines
3.2 KiB
Rust
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),
|
|
))
|
|
}
|