debt-pirate/api/src/requests/user/verify/handler.rs

109 lines
3.1 KiB
Rust
Raw Normal View History

use std::str::FromStr;
use axum::{
2024-10-03 15:27:30 -04:00
debug_handler,
extract::{Path, Query, State},
response::{IntoResponse, Response},
2024-10-03 15:27:30 -04:00
Json,
};
use http::StatusCode;
2024-10-03 15:27:30 -04:00
use pasetors::{claims::ClaimsValidationRules, keys::SymmetricKey, version4::V4};
use tracing::{debug, error};
use uuid::Uuid;
use crate::{
db::{verify_user, DbPool},
models::{ApiResponse, AppError},
requests::{
auth::generate_login_auth_and_session_tokens,
user::verify::UserVerifyGetResponseTokenAndExpiration, AppState,
},
services::{auth_token::verify_token, user_session, CachePool},
};
2024-10-03 15:27:30 -04:00
use super::{UserVerifyGetParams, UserVerifyGetResponse};
2024-10-03 15:27:30 -04:00
#[debug_handler]
pub async fn user_verification_get_handler(
State(state): State<AppState>,
Path(user_id): Path<i32>,
Query(query): Query<UserVerifyGetParams>,
) -> Result<Response, AppError> {
let db_pool = state.db_pool();
let cache_pool = state.cache_pool();
2024-10-03 15:27:30 -04:00
let env = state.env();
let UserVerifyGetParams { verification_token } = query;
let token_key = env.token_key();
verify_new_user_request(db_pool, cache_pool, user_id, verification_token, token_key).await
}
2024-10-03 15:27:30 -04:00
async fn verify_new_user_request(
db_pool: &DbPool,
cache_pool: &CachePool,
2024-10-03 15:27:30 -04:00
user_id: i32,
verification_token: String,
token_key: &SymmetricKey<V4>,
) -> Result<Response, AppError> {
2024-10-03 15:27:30 -04:00
debug!(user_id);
let validation_rules = {
let mut rules = ClaimsValidationRules::new();
rules.validate_audience_with(format!("/user/{user_id}/verify").as_str());
rules
};
let verified_token = verify_token(
token_key,
verification_token.as_str(),
Some(validation_rules.clone()),
)
.inspect_err(|err| error!(?err))?;
let verification_token_id = verified_token
.payload_claims()
.map(|claims| claims.get_claim("jti"))
.flatten()
.map(|jti| Uuid::from_str(jti.as_str().unwrap()).unwrap())
.unwrap();
user_session::exists(cache_pool, verification_token_id)
.await
.and_then(|exists| {
if exists {
Ok(user_session::get_user_session(
cache_pool,
verification_token_id,
))
} else {
Err(AppError::no_session_found())
}
})?
.await?;
verify_user(db_pool, user_id)
.await
.inspect_err(|err| error!(?err))?;
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 = UserVerifyGetResponse {
user_id,
session: UserVerifyGetResponseTokenAndExpiration {
token: session_token,
expires_at: session_token_expiration,
},
auth: UserVerifyGetResponseTokenAndExpiration {
token: auth_token,
expires_at: auth_token_expiration,
},
};
Ok((
StatusCode::OK,
Json(ApiResponse::<UserVerifyGetResponse>::new(response)),
)
.into_response())
}