From 2ebbc88c0a78c0565bdf0c8f13ff8902deb8a684 Mon Sep 17 00:00:00 2001 From: jakubmanczak Date: Wed, 4 Mar 2026 22:46:46 +0100 Subject: [PATCH] user list, user create w/ endpoints, misc --- src/api/mod.rs | 6 ++++++ src/api/users.rs | 20 ++++++++++++++++++-- src/users/mod.rs | 20 ++++++++++++++++++++ src/users/permissions.rs | 1 + 4 files changed, 45 insertions(+), 2 deletions(-) diff --git a/src/api/mod.rs b/src/api/mod.rs index 8b4a76c..bb7b511 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -18,15 +18,21 @@ mod users; pub fn api_router() -> Router { Router::new() .route("/api/live", get(async || "Mnemosyne lives")) + // .route("/api/auth/login", post(auth::login)) .route("/api/auth/logout", post(auth::logout)) + // + .route("/api/users", get(users::get_all)) + .route("/api/users", post(users::create)) .route("/api/users/me", get(users::get_me)) .route("/api/users/{id}", get(users::get_by_id)) .route("/api/users/@{handle}", get(users::get_by_handle)) .route("/api/users/{id}/setpassw", post(users::change_password)) .route("/api/users/{id}/sethandle", post(users::change_handle)) + // .route("/api/sessions/{id}", get(sessions::get_by_id)) .route("/api/sessions/{id}/revoke", post(sessions::revoke_by_id)) + // .route("/api/tags/{id}", get(tags::get_by_id)) .route("/api/tags/#{name}", get(tags::get_by_name)) } diff --git a/src/api/users.rs b/src/api/users.rs index fdbb203..0ebddb7 100644 --- a/src/api/users.rs +++ b/src/api/users.rs @@ -19,6 +19,7 @@ use crate::{ const CANT_CHANGE_OTHERS_HANDLE: &str = "You don't have permission to change this user's handle."; const CANT_CHANGE_OTHERS_PASSW: &str = "You don't have permission to change this user's password."; +const CANT_MANUALLY_MAKE_USERS: &str = "You don't have permission to manually create new users."; const HANDLE_CHANGED_SUCCESS: &str = "Handle changed successfully."; const PASSW_CHANGED_SUCCESS: &str = "Password changed successfully."; @@ -42,14 +43,29 @@ pub async fn get_by_handle( Ok(Json(User::get_by_handle(handle)?).into_response()) } +pub async fn get_all(headers: HeaderMap) -> Result { + User::authenticate(&headers)?.required()?; + Ok(Json(User::get_all()?).into_response()) +} + #[derive(Deserialize)] -pub struct ChangeHandleForm { +pub struct HandleForm { handle: UserHandle, } +pub async fn create( + headers: HeaderMap, + Json(form): Json, +) -> Result { + let u = User::authenticate(&headers)?.required()?; + if !u.has_permission(Permission::ManuallyCreateUsers)? { + return Ok((StatusCode::FORBIDDEN, CANT_MANUALLY_MAKE_USERS).into_response()); + } + Ok(Json(User::create(form.handle)?).into_response()) +} pub async fn change_handle( Path(id): Path, headers: HeaderMap, - Json(form): Json, + Json(form): Json, ) -> Result { let u = User::authenticate(&headers)?.required()?; let mut target = if u.id == id { diff --git a/src/users/mod.rs b/src/users/mod.rs index 09d8629..ccbfd11 100644 --- a/src/users/mod.rs +++ b/src/users/mod.rs @@ -74,6 +74,26 @@ impl User { None => Err(UserError::NoUserWithHandle(handle)), } } + pub fn get_all() -> Result, UserError> { + Ok(database::conn()? + .prepare("SELECT id, handle FROM users")? + .query_map((), |r| { + Ok(User { + id: r.get(0)?, + handle: r.get(1)?, + }) + })? + .collect::, _>>()?) + } + + pub fn create(handle: UserHandle) -> Result { + let conn = database::conn()?; + let id = Uuid::now_v7(); + conn.prepare("INSERT INTO users(id, handle) VALUES (?1, ?2)")? + .execute((&id, &handle))?; + Ok(User { id, handle }) + } + pub fn set_handle(&mut self, new_handle: UserHandle) -> Result<(), UserError> { let conn = database::conn()?; conn.prepare("UPDATE users SET handle = ?1 WHERE id = ?2")? diff --git a/src/users/permissions.rs b/src/users/permissions.rs index 9e2e631..9a5c09b 100644 --- a/src/users/permissions.rs +++ b/src/users/permissions.rs @@ -10,6 +10,7 @@ pub enum Permission { ChangeOthersPasswords, // All Users have the right to change their own handle ChangeOthersHandles, + ManuallyCreateUsers, } impl User {