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(()) + } }