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

133 lines
3.3 KiB
Rust
Raw Normal View History

2024-10-05 08:09:46 -04:00
use std::{sync::mpsc::Sender, time::SystemTime};
use crate::{
db::{insert_new_user, DbPool, NewUserEntity, UserEntity},
2024-10-05 08:09:46 -04:00
models::{ApiResponse, AppError, Session},
requests::AppState,
2024-10-05 08:09:46 -04:00
services::{
self, auth_token::generate_new_user_token, hash_password, CachePool,
UserConfirmationMessage,
},
};
use axum::{
debug_handler,
extract::State,
response::{IntoResponse, Response},
Json,
};
use http::StatusCode;
use pasetors::{keys::SymmetricKey, version4::V4};
use tracing::debug;
use super::models::{UserRegistrationRequest, UserRegistrationResponse};
#[debug_handler]
pub async fn user_registration_post_handler(
State(state): State<AppState>,
Json(request): Json<UserRegistrationRequest>,
) -> Result<Response, AppError> {
let env = state.env();
register_new_user_request(
request,
2024-10-05 08:09:46 -04:00
state.db_pool(),
state.cache_pool(),
env.token_key(),
env.send_verification_email(),
env.email_sender(),
)
.await
}
async fn register_new_user_request(
body: UserRegistrationRequest,
2024-10-05 08:09:46 -04:00
db_pool: &DbPool,
cache_pool: &CachePool,
signing_key: &SymmetricKey<V4>,
send_verification_email: bool,
email_sender: &Sender<UserConfirmationMessage>,
) -> Result<Response, AppError> {
debug!(?body, send_verification_email);
let UserRegistrationRequest {
username,
password,
email,
name,
} = body;
2024-10-05 08:09:46 -04:00
let hashed_password = hash_password(password);
let new_user = NewUserEntity {
2024-10-05 08:09:46 -04:00
username: username.clone(),
password: hashed_password.to_string(),
email,
name,
};
let UserEntity {
id: user_id,
name,
email,
..
2024-10-05 08:09:46 -04:00
} = insert_new_user(db_pool, new_user).await.map_err(|err| {
if err.is_duplicate_record() {
AppError::duplicate_record(
"There is already an account associated with this username or email address.",
)
} else {
err
}
})?;
2024-10-05 08:09:46 -04:00
let (verification_token, token_id, expires_at) = generate_new_user_token(signing_key, user_id);
let new_user_session = Session {
user_id,
created_at: SystemTime::now(),
expires_at,
};
let expires_in = expires_at.duration_since(SystemTime::now()).unwrap();
services::user_session::store_user_session(
cache_pool,
token_id,
new_user_session,
Some(expires_in),
)
.await?;
let response_body = if send_verification_email {
let new_user_confirmation_message = UserConfirmationMessage {
email,
name,
2024-10-03 15:27:30 -04:00
verification_token: verification_token.clone(),
};
let _ = email_sender
.send(new_user_confirmation_message)
.inspect_err(|err| {
eprintln!("Got the rollowing error while sending across the channel: {err}");
});
UserRegistrationResponse {
user_id,
2024-10-05 08:09:46 -04:00
expires_at,
session_token: None,
}
} else {
UserRegistrationResponse {
user_id,
2024-10-05 08:09:46 -04:00
expires_at,
session_token: Some(verification_token),
}
};
let response = (
StatusCode::CREATED,
ApiResponse::new(response_body).into_json_response(),
);
Ok(response.into_response())
}