2024-10-03 10:05:30 -04:00
use std ::sync ::mpsc ::Sender ;
2024-09-29 09:57:02 -04:00
use crate ::{
2024-10-03 10:05:30 -04:00
db ::{ insert_new_user , DbPool , NewUserEntity , UserEntity } ,
2024-09-29 09:57:02 -04:00
models ::ApiResponse ,
requests ::AppState ,
2024-09-30 00:15:19 -04:00
services ::{ auth_token ::generate_new_user_token , hash_string , UserConfirmationMessage } ,
2024-09-29 09:57:02 -04:00
} ;
use axum ::{
2024-10-03 10:05:30 -04:00
debug_handler ,
2024-09-29 09:57:02 -04:00
extract ::State ,
response ::{ IntoResponse , Response } ,
Json ,
} ;
use http ::StatusCode ;
2024-10-03 10:05:30 -04:00
use pasetors ::{ keys ::SymmetricKey , version4 ::V4 } ;
use tracing ::debug ;
2024-09-29 09:57:02 -04:00
use super ::models ::{ UserRegistrationRequest , UserRegistrationResponse } ;
2024-10-03 10:05:30 -04:00
#[ debug_handler ]
2024-09-29 09:57:02 -04:00
pub async fn user_registration_post_handler (
2024-10-03 10:05:30 -04:00
State ( state ) : State < AppState > ,
2024-09-29 09:57:02 -04:00
Json ( request ) : Json < UserRegistrationRequest > ,
) -> Result < Response , Response > {
2024-10-03 10:05:30 -04:00
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 < V4 > ,
send_verification_email : bool ,
email_sender : & Sender < UserConfirmationMessage > ,
) -> Result < Response , Response > {
debug! ( ? body , send_verification_email ) ;
2024-09-29 09:57:02 -04:00
let UserRegistrationRequest {
username ,
password ,
email ,
name ,
2024-10-03 10:05:30 -04:00
} = body ;
2024-09-29 09:57:02 -04:00
let hashed_password = hash_string ( password ) ;
let new_user = NewUserEntity {
username ,
password : hashed_password . to_string ( ) ,
email ,
name ,
} ;
2024-10-03 10:05:30 -04:00
let UserEntity { id : user_id , name , email , .. } = insert_new_user ( pool , new_user ) . await
2024-09-29 09:57:02 -04:00
. 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 ( )
}
} ) ? ;
2024-09-30 00:15:19 -04:00
let ( auth_token , expiration ) = generate_new_user_token ( signing_key , user_id ) ;
2024-09-29 09:57:02 -04:00
2024-10-03 10:05:30 -04:00
let response_body = if send_verification_email {
let new_user_confirmation_message = UserConfirmationMessage {
email ,
name ,
auth_token : auth_token . clone ( ) ,
} ;
2024-09-29 09:57:02 -04:00
2024-10-03 10:05:30 -04:00
let _ = email_sender
2024-10-02 12:41:25 -04:00
. send ( new_user_confirmation_message )
. inspect_err ( | err | {
eprintln! ( " Got the rollowing error while sending across the channel: {err} " ) ;
} ) ;
2024-09-29 09:57:02 -04:00
2024-10-03 10:05:30 -04:00
UserRegistrationResponse {
id : user_id ,
expiration ,
auth_token : None ,
}
} else {
UserRegistrationResponse {
2024-09-29 09:57:02 -04:00
id : user_id ,
expiration ,
2024-10-03 10:05:30 -04:00
auth_token : Some ( auth_token ) ,
}
} ;
let response = (
StatusCode ::CREATED ,
ApiResponse ::new ( response_body ) . into_json_response ( ) ,
2024-09-29 09:57:02 -04:00
) ;
Ok ( response . into_response ( ) )
}