use std::time::Duration; use crate::{ db::{insert_new_user, NewUserEntity, UserEntity}, models::ApiResponse, requests::AppState, services::{auth_token::generate_token, hash_string, UserConfirmationMessage}, }; use axum::{ extract::State, response::{IntoResponse, Response}, Json, }; use http::StatusCode; use super::models::{UserRegistrationRequest, UserRegistrationResponse}; static FIFTEEN_MINUTES: u64 = 60 * 15; pub async fn user_registration_post_handler( State(app_state): State, Json(request): Json, ) -> Result { let UserRegistrationRequest { username, password, email, name, } = request; 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(app_state.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 signing_key = app_state.env().token_key(); let (auth_token, expiration) = generate_token( signing_key, user_id, Some(Duration::from_secs(FIFTEEN_MINUTES)), Some("user-verify.debtpirate.bikeshedengineering.internal"), ); let new_user_confirmation_message = UserConfirmationMessage::new(email.as_str(), name.as_str(), auth_token.as_str()); let _ = app_state .env() .email_sender() .send(new_user_confirmation_message) .inspect_err(|err| { eprintln!("Got the rollowing error while sending across the channel: {err}"); }); let response = ( StatusCode::CREATED, ApiResponse::new(UserRegistrationResponse { id: user_id, expiration, }) .into_json_response(), ); Ok(response.into_response()) }