summaryrefslogtreecommitdiff
path: root/src/routes
diff options
context:
space:
mode:
Diffstat (limited to 'src/routes')
-rw-r--r--src/routes/errors.rs26
-rw-r--r--src/routes/problem.rs (renamed from src/routes/problems.rs)0
-rw-r--r--src/routes/user.rs49
3 files changed, 75 insertions, 0 deletions
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<Body> {
+ 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/problems.rs b/src/routes/problem.rs
index caeb808..caeb808 100644
--- a/src/routes/problems.rs
+++ b/src/routes/problem.rs
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<AppState>,
+ Json(request): Json<CreateUserRequest>
+) -> Result<impl IntoResponse, RouteError> {
+
+ 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(),
+ }))));
+}
+