use std::sync::mpsc::Sender; use crate::{ db::{insert_new_user, DbPool, NewUserEntity, UserEntity}, models::ApiResponse, requests::AppState, services::{auth_token::generate_new_user_token, hash_string, 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, Json(request): Json, ) -> Result { let env = state.env(); register_new_user_request( request, state.pool(), env.token_key(), env.send_verification_email(), env.email_sender(), ) .await } async fn register_new_user_request( body: UserRegistrationRequest, pool: &DbPool, signing_key: &SymmetricKey, send_verification_email: bool, email_sender: &Sender, ) -> Result { debug!(?body, send_verification_email); let UserRegistrationRequest { username, password, email, name, } = body; let hashed_password = hash_string(password); let new_user = NewUserEntity { username, password: hashed_password.to_string(), email, name, }; let UserEntity { id: user_id, name, email , ..} = insert_new_user(pool, new_user).await .map_err(|err| { if err.is_duplicate_record() { (StatusCode::CONFLICT, ApiResponse::error("There is already an account associated with this username or email address.").into_json_response()).into_response() } else { (StatusCode::INTERNAL_SERVER_ERROR, ApiResponse::error("An error occurred while creating your new user account. Please try again later.").into_json_response()).into_response() } })?; let (auth_token, expiration) = generate_new_user_token(signing_key, user_id); let response_body = if send_verification_email { let new_user_confirmation_message = UserConfirmationMessage { email, name, auth_token: auth_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 { id: user_id, expiration, auth_token: None, } } else { UserRegistrationResponse { id: user_id, expiration, auth_token: Some(auth_token), } }; let response = ( StatusCode::CREATED, ApiResponse::new(response_body).into_json_response(), ); Ok(response.into_response()) }