From 36fad793c3be58b220ae319a45c8cd8afbae09fa Mon Sep 17 00:00:00 2001 From: Daniel Hader Date: Mon, 11 May 2026 19:28:00 -0500 Subject: user route and database pooling using r2d2 --- src/routes/errors.rs | 26 ++++++++++++++++++++++++++ src/routes/problem.rs | 17 +++++++++++++++++ src/routes/problems.rs | 17 ----------------- src/routes/user.rs | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 92 insertions(+), 17 deletions(-) create mode 100644 src/routes/errors.rs create mode 100644 src/routes/problem.rs delete mode 100644 src/routes/problems.rs create mode 100644 src/routes/user.rs (limited to 'src/routes') diff --git a/src/routes/errors.rs b/src/routes/errors.rs new file mode 100644 index 0000000..6261d75 --- /dev/null +++ b/src/routes/errors.rs @@ -0,0 +1,26 @@ +use axum::{Json, body::Body, http::{Response, StatusCode}, response::IntoResponse}; +use serde_json::{json}; + +pub enum RouteError { + Internal(String), + UserCreateEmailExists(String), + UserCreateUsernameExists(String), +} + +impl IntoResponse for RouteError { + fn into_response(self) -> Response { + let (status, message) = match self { + Self::Internal(message) => { + (StatusCode::INTERNAL_SERVER_ERROR, message) + }, + RouteError::UserCreateEmailExists(email) => { + (StatusCode::BAD_REQUEST, format!("user with email \"{}\" already exists", email)) + }, + RouteError::UserCreateUsernameExists(username) => { + (StatusCode::BAD_REQUEST, format!("user with username \"{}\" already exists", username)) + } + }; + + (status, Json(json!({"error": message}))).into_response() + } +} diff --git a/src/routes/problem.rs b/src/routes/problem.rs new file mode 100644 index 0000000..caeb808 --- /dev/null +++ b/src/routes/problem.rs @@ -0,0 +1,17 @@ +use axum::response::Json; +use serde::Serialize; + +#[derive(Serialize)] +pub struct Problem { + title: String, + description: String, +} + +pub async fn get_problems() -> Json> { + let problem = Problem { + title: "test problem".into(), + description: "the description of a test problem".into(), + }; + Json(vec![problem]) +} + diff --git a/src/routes/problems.rs b/src/routes/problems.rs deleted file mode 100644 index caeb808..0000000 --- a/src/routes/problems.rs +++ /dev/null @@ -1,17 +0,0 @@ -use axum::response::Json; -use serde::Serialize; - -#[derive(Serialize)] -pub struct Problem { - title: String, - description: String, -} - -pub async fn get_problems() -> Json> { - let problem = Problem { - title: "test problem".into(), - description: "the description of a test problem".into(), - }; - Json(vec![problem]) -} - diff --git a/src/routes/user.rs b/src/routes/user.rs new file mode 100644 index 0000000..42db46f --- /dev/null +++ b/src/routes/user.rs @@ -0,0 +1,49 @@ +use axum::extract::{Json, State}; +use axum::http::StatusCode; +use axum::response::IntoResponse; +use serde::Deserialize; +use serde_json::json; + +use crate::AppState; +use crate::auth::hash_password; +use super::errors::RouteError; + +#[derive(Deserialize)] +pub struct CreateUserRequest { + email: String, + username: String, + password: String, +} + +pub async fn create_user( + State(state): State, + Json(request): Json +) -> Result { + + match state.database.fetch_user_by_email(&request.email) { + Err(_) => return Err(RouteError::Internal("database action failed".into())), + Ok(Some(_)) => return Err(RouteError::UserCreateEmailExists(request.email)), + Ok(None) => {}, + }; + + match state.database.fetch_user_by_username(&request.username) { + Err(_) => return Err(RouteError::Internal("database action failed B".into())), + Ok(Some(_)) => return Err(RouteError::UserCreateUsernameExists(request.username)), + Ok(None) => {}, + }; + + let Ok(password_hash) = hash_password(&request.password) else { + return Err(RouteError::Internal("failed to hash password".into())) + }; + + let Ok(user) = state.database.insert_user(&request.email, &request.username, &password_hash) else { + return Err(RouteError::Internal("failed to create user".into())); + }; + + return Ok((StatusCode::CREATED, Json(json!({ + "id": user.id(), + "email": user.email(), + "username": user.username(), + })))); +} + -- cgit v1.2.3