From 82f4388dab3182de9d97d4babdafcffd0db099f8 Mon Sep 17 00:00:00 2001 From: BAaboe Date: Tue, 22 Jul 2025 17:29:55 +0200 Subject: [PATCH 1/9] New endpoint 'members' with get and delete --- src/api/v1/members/mod.rs | 22 +++++++++++++ src/api/v1/members/uuid/mod.rs | 56 ++++++++++++++++++++++++++++++++++ src/api/v1/mod.rs | 4 ++- src/objects/member.rs | 28 ++++++++++++++++- 4 files changed, 108 insertions(+), 2 deletions(-) create mode 100644 src/api/v1/members/mod.rs create mode 100644 src/api/v1/members/uuid/mod.rs diff --git a/src/api/v1/members/mod.rs b/src/api/v1/members/mod.rs new file mode 100644 index 0000000..165e533 --- /dev/null +++ b/src/api/v1/members/mod.rs @@ -0,0 +1,22 @@ +use std::sync::Arc; + +use axum::{ + Router, + middleware::from_fn_with_state, + routing::{any, delete, get, patch}, +}; +//use socketioxide::SocketIo; + +use crate::{AppState, api::v1::auth::CurrentUser}; + +mod uuid; + +pub fn router(app_state: Arc) -> Router> { + let router_with_auth = Router::new() + .route("/{uuid}", get(uuid::get)) + .route("/{uuid}", delete(uuid::delete)) + .layer(from_fn_with_state(app_state, CurrentUser::check_auth_layer)); + + Router::new() + .merge(router_with_auth) +} diff --git a/src/api/v1/members/uuid/mod.rs b/src/api/v1/members/uuid/mod.rs new file mode 100644 index 0000000..9000e5a --- /dev/null +++ b/src/api/v1/members/uuid/mod.rs @@ -0,0 +1,56 @@ +//! `/api/v1/channels/{uuid}` Channel specific endpoints + +use std::sync::Arc; + +use crate::{ + AppState, + api::v1::auth::CurrentUser, + error::Error, + objects::{Channel, Member, Permissions, Me}, + utils::global_checks, +}; +use axum::{ + Extension, Json, + extract::{Path, State}, + http::StatusCode, + response::IntoResponse, +}; + +use serde::Deserialize; +use uuid::Uuid; + +pub async fn get( + State(app_state): State>, + Path(member_uuid): Path, + Extension(CurrentUser(uuid)): Extension>, +) -> Result { + global_checks(&app_state, uuid).await?; + + let me = Me::get(&mut app_state.pool.get().await?, uuid).await?; + + let member = Member::fetch_one_with_member(&app_state, &me, member_uuid).await?; + + + Ok((StatusCode::OK, Json(member))) +} + +pub async fn delete( + State(app_state): State>, + Path(member_uuid): Path, + Extension(CurrentUser(uuid)): Extension>, +) -> Result { + global_checks(&app_state, uuid).await?; + + let me = Me::get(&mut app_state.pool.get().await?, uuid).await?; + + let member = Member::fetch_one_with_member(&app_state, &me, member_uuid).await?; + + let deleter = Member::check_membership(&mut app_state.pool.get().await?, uuid, member.guild_uuid).await?; + + deleter.check_permission(&app_state, Permissions::ManageMember).await?; + + member.delete(&mut app_state.pool.get().await?).await?; + + Ok(StatusCode::OK) +} + diff --git a/src/api/v1/mod.rs b/src/api/v1/mod.rs index 860944c..ee9fbc8 100644 --- a/src/api/v1/mod.rs +++ b/src/api/v1/mod.rs @@ -13,6 +13,7 @@ mod invites; mod me; mod stats; mod users; +mod members; pub fn router(app_state: Arc) -> Router> { let router_with_auth = Router::new() @@ -28,6 +29,7 @@ pub fn router(app_state: Arc) -> Router> { Router::new() .route("/stats", get(stats::res)) .nest("/auth", auth::router(app_state.clone())) - .nest("/channels", channels::router(app_state)) + .nest("/channels", channels::router(app_state.clone())) + .nest("/members", members::router(app_state)) .merge(router_with_auth) } diff --git a/src/objects/member.rs b/src/objects/member.rs index 50b76b0..84ee095 100644 --- a/src/objects/member.rs +++ b/src/objects/member.rs @@ -1,5 +1,5 @@ use diesel::{ - ExpressionMethods, Insertable, QueryDsl, Queryable, Selectable, SelectableHelper, insert_into, + delete, insert_into, ExpressionMethods, Insertable, QueryDsl, Queryable, Selectable, SelectableHelper }; use diesel_async::RunQueryDsl; use serde::{Deserialize, Serialize}; @@ -119,6 +119,23 @@ impl Member { member.build(app_state, Some(me)).await } + pub async fn fetch_one_with_member ( + app_state: &AppState, + me: &Me, + uuid: Uuid + ) -> Result { + let mut conn = app_state.pool.get().await?; + + use guild_members::dsl; + let member: MemberBuilder = dsl::guild_members + .filter(dsl::uuid.eq(uuid)) + .select(MemberBuilder::as_select()) + .get_result(&mut conn) + .await?; + + member.build(app_state, Some(me)).await + } + pub async fn fetch_all( app_state: &AppState, me: &Me, @@ -168,4 +185,13 @@ impl Member { member.build(app_state, None).await } + + pub async fn delete(self, conn: &mut Conn) -> Result<(), Error> { + delete(guild_members::table) + .filter(guild_members::uuid.eq(self.uuid)) + .execute(conn) + .await?; + + Ok(()) + } } From 4ec36c1cda7e4fdfb7724d5d3439e631b648160b Mon Sep 17 00:00:00 2001 From: BAaboe Date: Tue, 22 Jul 2025 17:35:02 +0200 Subject: [PATCH 2/9] path name fix --- src/api/v1/{members => member}/mod.rs | 1 - src/api/v1/{members => member}/uuid/mod.rs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) rename src/api/v1/{members => member}/mod.rs (94%) rename src/api/v1/{members => member}/uuid/mod.rs (96%) diff --git a/src/api/v1/members/mod.rs b/src/api/v1/member/mod.rs similarity index 94% rename from src/api/v1/members/mod.rs rename to src/api/v1/member/mod.rs index 165e533..3ee9718 100644 --- a/src/api/v1/members/mod.rs +++ b/src/api/v1/member/mod.rs @@ -5,7 +5,6 @@ use axum::{ middleware::from_fn_with_state, routing::{any, delete, get, patch}, }; -//use socketioxide::SocketIo; use crate::{AppState, api::v1::auth::CurrentUser}; diff --git a/src/api/v1/members/uuid/mod.rs b/src/api/v1/member/uuid/mod.rs similarity index 96% rename from src/api/v1/members/uuid/mod.rs rename to src/api/v1/member/uuid/mod.rs index 9000e5a..f0425dd 100644 --- a/src/api/v1/members/uuid/mod.rs +++ b/src/api/v1/member/uuid/mod.rs @@ -1,4 +1,4 @@ -//! `/api/v1/channels/{uuid}` Channel specific endpoints +//! `/api/v1/member/{uuid}` Member specific endpoints use std::sync::Arc; From 228bc68327c1e494fd0fee174891bc2cad4b0b17 Mon Sep 17 00:00:00 2001 From: BAaboe Date: Tue, 22 Jul 2025 17:38:04 +0200 Subject: [PATCH 3/9] more path name fix --- src/api/v1/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/api/v1/mod.rs b/src/api/v1/mod.rs index ee9fbc8..b05774e 100644 --- a/src/api/v1/mod.rs +++ b/src/api/v1/mod.rs @@ -13,7 +13,7 @@ mod invites; mod me; mod stats; mod users; -mod members; +mod member; pub fn router(app_state: Arc) -> Router> { let router_with_auth = Router::new() @@ -30,6 +30,6 @@ pub fn router(app_state: Arc) -> Router> { .route("/stats", get(stats::res)) .nest("/auth", auth::router(app_state.clone())) .nest("/channels", channels::router(app_state.clone())) - .nest("/members", members::router(app_state)) + .nest("/member", member::router(app_state)) .merge(router_with_auth) } From 0468d1adca6d2011fb538219263b8b22b2deaeaa Mon Sep 17 00:00:00 2001 From: BAaboe Date: Tue, 22 Jul 2025 18:05:19 +0200 Subject: [PATCH 4/9] fix: Unecessary merge of routers --- src/api/v1/member/mod.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/api/v1/member/mod.rs b/src/api/v1/member/mod.rs index 3ee9718..61dc085 100644 --- a/src/api/v1/member/mod.rs +++ b/src/api/v1/member/mod.rs @@ -11,11 +11,8 @@ use crate::{AppState, api::v1::auth::CurrentUser}; mod uuid; pub fn router(app_state: Arc) -> Router> { - let router_with_auth = Router::new() + Router::new() .route("/{uuid}", get(uuid::get)) .route("/{uuid}", delete(uuid::delete)) - .layer(from_fn_with_state(app_state, CurrentUser::check_auth_layer)); - - Router::new() - .merge(router_with_auth) + .layer(from_fn_with_state(app_state, CurrentUser::check_auth_layer)) } From ea33230e58157fd7cb575a330b7218b84fda1752 Mon Sep 17 00:00:00 2001 From: BAaboe Date: Tue, 22 Jul 2025 18:10:37 +0200 Subject: [PATCH 5/9] fix: reduced numder of function calls to get conn --- src/api/v1/member/uuid/mod.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/api/v1/member/uuid/mod.rs b/src/api/v1/member/uuid/mod.rs index f0425dd..16cc7a9 100644 --- a/src/api/v1/member/uuid/mod.rs +++ b/src/api/v1/member/uuid/mod.rs @@ -1,4 +1,4 @@ -//! `/api/v1/member/{uuid}` Member specific endpoints +//! `/api/v1/members/{uuid}` Member specific endpoints use std::sync::Arc; @@ -41,15 +41,17 @@ pub async fn delete( ) -> Result { global_checks(&app_state, uuid).await?; - let me = Me::get(&mut app_state.pool.get().await?, uuid).await?; + let mut conn = app_state.pool.get().await?; + + let me = Me::get(&mut conn, uuid).await?; let member = Member::fetch_one_with_member(&app_state, &me, member_uuid).await?; - let deleter = Member::check_membership(&mut app_state.pool.get().await?, uuid, member.guild_uuid).await?; + let deleter = Member::check_membership(&mut conn, uuid, member.guild_uuid).await?; deleter.check_permission(&app_state, Permissions::ManageMember).await?; - member.delete(&mut app_state.pool.get().await?).await?; + member.delete(&mut conn).await?; Ok(StatusCode::OK) } From 31596c6bfe49532620688b63c8fc1628548d7cee Mon Sep 17 00:00:00 2001 From: BAaboe Date: Tue, 22 Jul 2025 18:26:04 +0200 Subject: [PATCH 6/9] fix: memebrs not member as endpoint --- src/api/v1/{member => members}/mod.rs | 3 +-- src/api/v1/{member => members}/uuid/mod.rs | 0 src/api/v1/mod.rs | 6 +++--- 3 files changed, 4 insertions(+), 5 deletions(-) rename src/api/v1/{member => members}/mod.rs (67%) rename src/api/v1/{member => members}/uuid/mod.rs (100%) diff --git a/src/api/v1/member/mod.rs b/src/api/v1/members/mod.rs similarity index 67% rename from src/api/v1/member/mod.rs rename to src/api/v1/members/mod.rs index 61dc085..9e1ea52 100644 --- a/src/api/v1/member/mod.rs +++ b/src/api/v1/members/mod.rs @@ -10,9 +10,8 @@ use crate::{AppState, api::v1::auth::CurrentUser}; mod uuid; -pub fn router(app_state: Arc) -> Router> { +pub fn router() -> Router> { Router::new() .route("/{uuid}", get(uuid::get)) .route("/{uuid}", delete(uuid::delete)) - .layer(from_fn_with_state(app_state, CurrentUser::check_auth_layer)) } diff --git a/src/api/v1/member/uuid/mod.rs b/src/api/v1/members/uuid/mod.rs similarity index 100% rename from src/api/v1/member/uuid/mod.rs rename to src/api/v1/members/uuid/mod.rs diff --git a/src/api/v1/mod.rs b/src/api/v1/mod.rs index b05774e..b2c9c99 100644 --- a/src/api/v1/mod.rs +++ b/src/api/v1/mod.rs @@ -13,7 +13,7 @@ mod invites; mod me; mod stats; mod users; -mod member; +mod members; pub fn router(app_state: Arc) -> Router> { let router_with_auth = Router::new() @@ -29,7 +29,7 @@ pub fn router(app_state: Arc) -> Router> { Router::new() .route("/stats", get(stats::res)) .nest("/auth", auth::router(app_state.clone())) - .nest("/channels", channels::router(app_state.clone())) - .nest("/member", member::router(app_state)) + .nest("/channels", channels::router(app_state)) + .nest("/members", members::router()) .merge(router_with_auth) } From 6dd8ddb0df8c3c5ff67af1d584734a71f64c75a6 Mon Sep 17 00:00:00 2001 From: BAaboe Date: Tue, 22 Jul 2025 18:27:36 +0200 Subject: [PATCH 7/9] fix: members in router_with_auth --- src/api/v1/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/v1/mod.rs b/src/api/v1/mod.rs index b2c9c99..3aee3a0 100644 --- a/src/api/v1/mod.rs +++ b/src/api/v1/mod.rs @@ -20,6 +20,7 @@ pub fn router(app_state: Arc) -> Router> { .nest("/users", users::router()) .nest("/guilds", guilds::router()) .nest("/invites", invites::router()) + .nest("/members", members::router()) .nest("/me", me::router()) .layer(from_fn_with_state( app_state.clone(), @@ -30,6 +31,5 @@ pub fn router(app_state: Arc) -> Router> { .route("/stats", get(stats::res)) .nest("/auth", auth::router(app_state.clone())) .nest("/channels", channels::router(app_state)) - .nest("/members", members::router()) .merge(router_with_auth) } From a3c460a611f43bf3bf4d5a2ad7ebfb78f6d40d44 Mon Sep 17 00:00:00 2001 From: BAaboe Date: Tue, 22 Jul 2025 18:33:41 +0200 Subject: [PATCH 8/9] fix: Only people in a server should see its members list --- src/api/v1/members/uuid/mod.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/api/v1/members/uuid/mod.rs b/src/api/v1/members/uuid/mod.rs index 16cc7a9..48f22e5 100644 --- a/src/api/v1/members/uuid/mod.rs +++ b/src/api/v1/members/uuid/mod.rs @@ -26,9 +26,12 @@ pub async fn get( ) -> Result { global_checks(&app_state, uuid).await?; - let me = Me::get(&mut app_state.pool.get().await?, uuid).await?; + let mut conn = app_state.pool.get().await?; + + let me = Me::get(&mut conn, uuid).await?; let member = Member::fetch_one_with_member(&app_state, &me, member_uuid).await?; + Member::check_membership(&mut conn, uuid, member.guild_uuid).await?; Ok((StatusCode::OK, Json(member))) From c26ec49e057e472e209747a63d4c2b653d41db5b Mon Sep 17 00:00:00 2001 From: BAaboe Date: Tue, 22 Jul 2025 18:50:17 +0200 Subject: [PATCH 9/9] fix: cargo clippy --fix && cargo fmt --- src/api/v1/members/mod.rs | 5 ++--- src/api/v1/members/uuid/mod.rs | 11 +++++------ src/api/v1/mod.rs | 2 +- src/objects/member.rs | 9 +++++---- 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/api/v1/members/mod.rs b/src/api/v1/members/mod.rs index 9e1ea52..34b6938 100644 --- a/src/api/v1/members/mod.rs +++ b/src/api/v1/members/mod.rs @@ -2,11 +2,10 @@ use std::sync::Arc; use axum::{ Router, - middleware::from_fn_with_state, - routing::{any, delete, get, patch}, + routing::{delete, get}, }; -use crate::{AppState, api::v1::auth::CurrentUser}; +use crate::AppState; mod uuid; diff --git a/src/api/v1/members/uuid/mod.rs b/src/api/v1/members/uuid/mod.rs index 48f22e5..244f5f8 100644 --- a/src/api/v1/members/uuid/mod.rs +++ b/src/api/v1/members/uuid/mod.rs @@ -6,7 +6,7 @@ use crate::{ AppState, api::v1::auth::CurrentUser, error::Error, - objects::{Channel, Member, Permissions, Me}, + objects::{Me, Member, Permissions}, utils::global_checks, }; use axum::{ @@ -16,7 +16,6 @@ use axum::{ response::IntoResponse, }; -use serde::Deserialize; use uuid::Uuid; pub async fn get( @@ -32,7 +31,6 @@ pub async fn get( let member = Member::fetch_one_with_member(&app_state, &me, member_uuid).await?; Member::check_membership(&mut conn, uuid, member.guild_uuid).await?; - Ok((StatusCode::OK, Json(member))) } @@ -51,11 +49,12 @@ pub async fn delete( let member = Member::fetch_one_with_member(&app_state, &me, member_uuid).await?; let deleter = Member::check_membership(&mut conn, uuid, member.guild_uuid).await?; - - deleter.check_permission(&app_state, Permissions::ManageMember).await?; + + deleter + .check_permission(&app_state, Permissions::ManageMember) + .await?; member.delete(&mut conn).await?; Ok(StatusCode::OK) } - diff --git a/src/api/v1/mod.rs b/src/api/v1/mod.rs index 3aee3a0..70271ef 100644 --- a/src/api/v1/mod.rs +++ b/src/api/v1/mod.rs @@ -11,9 +11,9 @@ mod channels; mod guilds; mod invites; mod me; +mod members; mod stats; mod users; -mod members; pub fn router(app_state: Arc) -> Router> { let router_with_auth = Router::new() diff --git a/src/objects/member.rs b/src/objects/member.rs index 84ee095..8678f4a 100644 --- a/src/objects/member.rs +++ b/src/objects/member.rs @@ -1,5 +1,6 @@ use diesel::{ - delete, insert_into, ExpressionMethods, Insertable, QueryDsl, Queryable, Selectable, SelectableHelper + ExpressionMethods, Insertable, QueryDsl, Queryable, Selectable, SelectableHelper, delete, + insert_into, }; use diesel_async::RunQueryDsl; use serde::{Deserialize, Serialize}; @@ -119,10 +120,10 @@ impl Member { member.build(app_state, Some(me)).await } - pub async fn fetch_one_with_member ( + pub async fn fetch_one_with_member( app_state: &AppState, me: &Me, - uuid: Uuid + uuid: Uuid, ) -> Result { let mut conn = app_state.pool.get().await?; @@ -191,7 +192,7 @@ impl Member { .filter(guild_members::uuid.eq(self.uuid)) .execute(conn) .await?; - + Ok(()) } }