From ad24215fef631b1dc1a81e8fc9e3277f6903cf3a Mon Sep 17 00:00:00 2001 From: BAaboe Date: Wed, 23 Jul 2025 00:50:50 +0200 Subject: [PATCH] feat: added endpoint for banning --- src/api/v1/members/mod.rs | 3 ++- src/api/v1/members/uuid/ban.rs | 47 ++++++++++++++++++++++++++++++++++ src/objects/member.rs | 37 ++++++++++++++++++++++++++ 3 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 src/api/v1/members/uuid/ban.rs diff --git a/src/api/v1/members/mod.rs b/src/api/v1/members/mod.rs index 34b6938..59ceac2 100644 --- a/src/api/v1/members/mod.rs +++ b/src/api/v1/members/mod.rs @@ -2,7 +2,7 @@ use std::sync::Arc; use axum::{ Router, - routing::{delete, get}, + routing::{delete, get, post}, }; use crate::AppState; @@ -13,4 +13,5 @@ pub fn router() -> Router> { Router::new() .route("/{uuid}", get(uuid::get)) .route("/{uuid}", delete(uuid::delete)) + .route("/{uuid}/ban", post(uuid::ban::post)) } diff --git a/src/api/v1/members/uuid/ban.rs b/src/api/v1/members/uuid/ban.rs new file mode 100644 index 0000000..3fb1b58 --- /dev/null +++ b/src/api/v1/members/uuid/ban.rs @@ -0,0 +1,47 @@ +use std::sync::Arc; + +use axum::{ + Extension, + extract::{Path, State, Json}, + http::StatusCode, + response::IntoResponse, +}; +use diesel::{insert_into, RunQueryDsl}; +use serde::Deserialize; + +use crate::{ + api::v1::auth::CurrentUser, error::Error, objects::{Me, Member, Permissions}, schema::guild_bans::{self, dsl}, utils::global_checks, AppState +}; + +use uuid::Uuid; + +#[derive(Deserialize)] +pub struct RequstBody { + reason: String +} + + +pub async fn post( + State(app_state): State>, + Path(member_uuid): Path, + Extension(CurrentUser(uuid)): Extension>, + Json(payload): Json, +) -> Result{ + global_checks(&app_state, uuid).await?; + + let mut conn = app_state.pool.get().await?; + + let member = Member::fetch_one_with_member(&app_state, None, member_uuid).await?; + + if member.is_owner { + return Err(Error::Forbidden("Not allowed".to_string())); + } + + let baner = Member::check_membership(&mut conn, uuid, member.guild_uuid).await?; + baner.check_permission(&app_state, Permissions::ManageMember).await?; + + member.ban(&mut conn, &payload.reason).await?; + + + Ok(StatusCode::OK) +} diff --git a/src/objects/member.rs b/src/objects/member.rs index 337c2e9..40bcaee 100644 --- a/src/objects/member.rs +++ b/src/objects/member.rs @@ -1,3 +1,4 @@ +use axum::http::StatusCode; use diesel::{ ExpressionMethods, Insertable, QueryDsl, Queryable, Selectable, SelectableHelper, delete, insert_into, @@ -11,6 +12,7 @@ use crate::{ error::Error, objects::{Me, Permissions, Role}, schema::guild_members, + schema::guild_bans, }; use super::{User, load_or_empty}; @@ -73,6 +75,13 @@ pub struct Member { user: User, } +#[derive(Serialize, Deserialize)] +pub struct GuildBan { + pub guild_uuid: Uuid, + pub user_uuid: Uuid, + pub reason: String, +} + impl Member { pub async fn count(conn: &mut Conn, guild_uuid: Uuid) -> Result { use guild_members::dsl; @@ -169,6 +178,18 @@ impl Member { ) -> Result { let mut conn = app_state.pool.get().await?; + use guild_bans::dsl; + let banned = dsl::guild_bans + .filter(guild_bans::guild_uuid.eq(guild_uuid)) + .filter(guild_bans::user_uuid.eq(user_uuid)) + .execute(&mut conn) + .await; + match banned { + Ok(_) => Err(Error::Forbidden("User banned".to_string())), + Err(diesel::result::Error::NotFound) => Ok(()), + Err(e) => Err(e.into()), + }?; + let member_uuid = Uuid::now_v7(); let member = MemberBuilder { @@ -195,4 +216,20 @@ impl Member { Ok(()) } + + pub async fn ban(self, conn: &mut Conn, reason: &String) -> Result<(), Error> { + use guild_bans::dsl; + insert_into(guild_bans::table) + .values(( + dsl::guild_uuid.eq(self.guild_uuid), + dsl::user_uuid.eq(self.user_uuid), + dsl::reason.eq(reason), + )) + .execute(conn) + .await?; + + self.delete(conn).await?; + + Ok(()) + } }