76 lines
2.3 KiB
Rust
76 lines
2.3 KiB
Rust
use std::time::Duration;
|
|
|
|
use axum::{
|
|
extract::State,
|
|
response::{IntoResponse, Response},
|
|
routing::post,
|
|
Json, Router,
|
|
};
|
|
use http::StatusCode;
|
|
|
|
use crate::{
|
|
db::{insert_new_user, NewUserEntity, UserEntity},
|
|
models::ApiResponse,
|
|
requests::AppState,
|
|
services::{auth_token::generate_token, hash_string, UserConfirmationMessage},
|
|
};
|
|
|
|
use super::models::{UserPostRequest, UserPostResponse};
|
|
|
|
static FIFTEEN_MINUTES: u64 = 60 * 15;
|
|
|
|
pub fn request(app_state: AppState) -> Router {
|
|
Router::new()
|
|
.route("/", post(user_post_handler))
|
|
.with_state(app_state)
|
|
}
|
|
|
|
async fn user_post_handler(
|
|
State(app_state): State<AppState>,
|
|
Json(request): Json<UserPostRequest>,
|
|
) -> Result<Response, Response> {
|
|
let UserPostRequest {
|
|
username,
|
|
password,
|
|
email,
|
|
name,
|
|
} = request;
|
|
|
|
let hashed_password = hash_string(password.as_str());
|
|
let new_user = NewUserEntity::new(username, email.clone(), hashed_password, name.clone());
|
|
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 (auth_token, expiration) = generate_token(
|
|
app_state.env().token_key(),
|
|
user_id,
|
|
Some(Duration::from_secs(FIFTEEN_MINUTES)),
|
|
Some(format!("/user/{user_id}/verify").as_str()),
|
|
);
|
|
|
|
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,
|
|
Json(ApiResponse::<UserPostResponse>::new(UserPostResponse::new(
|
|
user_id, auth_token, expiration,
|
|
))),
|
|
);
|
|
|
|
Ok(response.into_response())
|
|
}
|