forked from jmug/stoatchat
Servers: Route for kicking a member.
This commit is contained in:
@@ -258,4 +258,30 @@ impl Server {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn remove_member(&self, id: &str) -> Result<()> {
|
||||||
|
get_collection("server_members")
|
||||||
|
.delete_one(
|
||||||
|
doc! {
|
||||||
|
"_id": {
|
||||||
|
"server": &self.id,
|
||||||
|
"user": &id
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.map_err(|_| Error::DatabaseError {
|
||||||
|
operation: "delete_one",
|
||||||
|
with: "server_members",
|
||||||
|
})?;
|
||||||
|
|
||||||
|
ClientboundNotification::ServerMemberLeave {
|
||||||
|
id: self.id.clone(),
|
||||||
|
user: id.to_string()
|
||||||
|
}
|
||||||
|
.publish(self.id.clone());
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,14 +28,14 @@ pub enum RelationshipStatus {
|
|||||||
BlockedOther,
|
BlockedOther,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub struct Relationship {
|
pub struct Relationship {
|
||||||
#[serde(rename = "_id")]
|
#[serde(rename = "_id")]
|
||||||
pub id: String,
|
pub id: String,
|
||||||
pub status: RelationshipStatus,
|
pub status: RelationshipStatus,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub enum Presence {
|
pub enum Presence {
|
||||||
Online,
|
Online,
|
||||||
Idle,
|
Idle,
|
||||||
@@ -43,7 +43,7 @@ pub enum Presence {
|
|||||||
Invisible,
|
Invisible,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Validate, Serialize, Deserialize, Debug)]
|
#[derive(Validate, Serialize, Deserialize, Debug, Clone)]
|
||||||
pub struct UserStatus {
|
pub struct UserStatus {
|
||||||
#[validate(length(min = 1, max = 128))]
|
#[validate(length(min = 1, max = 128))]
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
@@ -52,7 +52,7 @@ pub struct UserStatus {
|
|||||||
pub presence: Option<Presence>,
|
pub presence: Option<Presence>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub struct UserProfile {
|
pub struct UserProfile {
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub content: Option<String>,
|
pub content: Option<String>,
|
||||||
@@ -72,7 +72,7 @@ pub enum Badges {
|
|||||||
impl_op_ex_commutative!(+ |a: &i32, b: &Badges| -> i32 { *a | *b as i32 });
|
impl_op_ex_commutative!(+ |a: &i32, b: &Badges| -> i32 { *a | *b as i32 });
|
||||||
|
|
||||||
// When changing this struct, update notifications/payload.rs#80
|
// When changing this struct, update notifications/payload.rs#80
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub struct User {
|
pub struct User {
|
||||||
#[serde(rename = "_id")]
|
#[serde(rename = "_id")]
|
||||||
pub id: String,
|
pub id: String,
|
||||||
|
|||||||
@@ -9,7 +9,8 @@ use std::ops;
|
|||||||
#[repr(u32)]
|
#[repr(u32)]
|
||||||
pub enum ServerPermission {
|
pub enum ServerPermission {
|
||||||
View = 0b00000000000000000000000000000001, // 1
|
View = 0b00000000000000000000000000000001, // 1
|
||||||
// 2 bits of space
|
ManageMembers = 0b00000000000000000000000000000010, // 2
|
||||||
|
ManageChannels = 0b00000000000000000000000000000100, // 4
|
||||||
ManageServer = 0b00000000000000000000000000001000, // 8
|
ManageServer = 0b00000000000000000000000000001000, // 8
|
||||||
// 8 bits of space
|
// 8 bits of space
|
||||||
ChangeNickname = 0b00000000000000000001000000000000, // 4096
|
ChangeNickname = 0b00000000000000000001000000000000, // 4096
|
||||||
@@ -26,6 +27,8 @@ bitfield! {
|
|||||||
pub struct ServerPermissions(MSB0 [u32]);
|
pub struct ServerPermissions(MSB0 [u32]);
|
||||||
u32;
|
u32;
|
||||||
pub get_view, _: 31;
|
pub get_view, _: 31;
|
||||||
|
pub get_manage_members, _: 30;
|
||||||
|
pub get_manage_channels, _: 29;
|
||||||
pub get_manage_server, _: 28;
|
pub get_manage_server, _: 28;
|
||||||
|
|
||||||
pub get_change_nickname, _: 19;
|
pub get_change_nickname, _: 19;
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ use crate::{
|
|||||||
util::result::{Error, Result},
|
util::result::{Error, Result},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
#[serde(tag = "error")]
|
#[serde(tag = "error")]
|
||||||
pub enum WebSocketError {
|
pub enum WebSocketError {
|
||||||
LabelMe,
|
LabelMe,
|
||||||
@@ -29,7 +29,7 @@ pub enum ServerboundNotification {
|
|||||||
EndTyping { channel: String },
|
EndTyping { channel: String },
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub enum RemoveUserField {
|
pub enum RemoveUserField {
|
||||||
ProfileContent,
|
ProfileContent,
|
||||||
ProfileBackground,
|
ProfileBackground,
|
||||||
@@ -37,26 +37,26 @@ pub enum RemoveUserField {
|
|||||||
Avatar,
|
Avatar,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub enum RemoveChannelField {
|
pub enum RemoveChannelField {
|
||||||
Icon,
|
Icon,
|
||||||
Description,
|
Description,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub enum RemoveServerField {
|
pub enum RemoveServerField {
|
||||||
Icon,
|
Icon,
|
||||||
Banner,
|
Banner,
|
||||||
Description,
|
Description,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub enum RemoveMemberField {
|
pub enum RemoveMemberField {
|
||||||
Nickname,
|
Nickname,
|
||||||
Avatar
|
Avatar
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
#[serde(tag = "type")]
|
#[serde(tag = "type")]
|
||||||
pub enum ClientboundNotification {
|
pub enum ClientboundNotification {
|
||||||
Error(WebSocketError),
|
Error(WebSocketError),
|
||||||
@@ -210,7 +210,7 @@ pub async fn prehandle_hook(notification: &ClientboundNotification) -> Result<()
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn posthandle_hook(notification: &ClientboundNotification) {
|
pub async fn posthandle_hook(notification: &ClientboundNotification) {
|
||||||
match ¬ification {
|
match ¬ification {
|
||||||
ClientboundNotification::ChannelDelete { id } => {
|
ClientboundNotification::ChannelDelete { id } => {
|
||||||
get_hive().hive.drop_topic(&id).ok();
|
get_hive().hive.drop_topic(&id).ok();
|
||||||
@@ -218,7 +218,7 @@ pub fn posthandle_hook(notification: &ClientboundNotification) {
|
|||||||
ClientboundNotification::ChannelGroupLeave { id, user } => {
|
ClientboundNotification::ChannelGroupLeave { id, user } => {
|
||||||
get_hive()
|
get_hive()
|
||||||
.hive
|
.hive
|
||||||
.unsubscribe(&user.to_string(), &id.to_string())
|
.unsubscribe(user, id)
|
||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
ClientboundNotification::ServerDelete { id } => {
|
ClientboundNotification::ServerDelete { id } => {
|
||||||
@@ -227,14 +227,23 @@ pub fn posthandle_hook(notification: &ClientboundNotification) {
|
|||||||
ClientboundNotification::ServerMemberLeave { id, user } => {
|
ClientboundNotification::ServerMemberLeave { id, user } => {
|
||||||
get_hive()
|
get_hive()
|
||||||
.hive
|
.hive
|
||||||
.unsubscribe(&user.to_string(), &id.to_string())
|
.unsubscribe(user, id)
|
||||||
.ok();
|
.ok();
|
||||||
|
|
||||||
|
if let Ok(server) = Ref::from_unchecked(id.clone()).fetch_server().await {
|
||||||
|
for channel in server.channels {
|
||||||
|
get_hive()
|
||||||
|
.hive
|
||||||
|
.unsubscribe(user, &channel)
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ClientboundNotification::UserRelationship { id, user, status } => {
|
ClientboundNotification::UserRelationship { id, user, status } => {
|
||||||
if status == &RelationshipStatus::None {
|
if status == &RelationshipStatus::None {
|
||||||
get_hive()
|
get_hive()
|
||||||
.hive
|
.hive
|
||||||
.unsubscribe(&id.to_string(), &user.id.to_string())
|
.unsubscribe(id, &user.id)
|
||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,8 +13,11 @@ static HIVE: OnceCell<Hive> = OnceCell::new();
|
|||||||
|
|
||||||
pub async fn init_hive() {
|
pub async fn init_hive() {
|
||||||
let hive = MongodbPubSub::new(
|
let hive = MongodbPubSub::new(
|
||||||
|ids, notification| {
|
|ids, notification: ClientboundNotification| {
|
||||||
super::events::posthandle_hook(¬ification);
|
let notif = notification.clone();
|
||||||
|
async_std::task::spawn(async move {
|
||||||
|
super::events::posthandle_hook(¬if).await;
|
||||||
|
});
|
||||||
|
|
||||||
if let Ok(data) = to_string(¬ification) {
|
if let Ok(data) = to_string(¬ification) {
|
||||||
debug!("Pushing out notification. {}", data);
|
debug!("Pushing out notification. {}", data);
|
||||||
|
|||||||
25
src/routes/servers/member_remove.rs
Normal file
25
src/routes/servers/member_remove.rs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
use crate::database::*;
|
||||||
|
use crate::util::result::{Error, Result};
|
||||||
|
|
||||||
|
use mongodb::bson::doc;
|
||||||
|
|
||||||
|
#[delete("/<target>/members/<member>")]
|
||||||
|
pub async fn req(user: User, target: Ref, member: String) -> Result<()> {
|
||||||
|
let target = target.fetch_server().await?;
|
||||||
|
|
||||||
|
let perm = permissions::PermissionCalculator::new(&user)
|
||||||
|
.with_server(&target)
|
||||||
|
.for_server()
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
if !perm.get_manage_members() {
|
||||||
|
return Err(Error::MissingPermission)
|
||||||
|
}
|
||||||
|
|
||||||
|
let member = Ref::from(member)?.fetch_member(&target.id).await?;
|
||||||
|
if member.id.user == user.id {
|
||||||
|
return Err(Error::InvalidOperation)
|
||||||
|
}
|
||||||
|
|
||||||
|
target.remove_member(&member.id.user).await
|
||||||
|
}
|
||||||
@@ -8,6 +8,7 @@ mod server_edit;
|
|||||||
mod channel_create;
|
mod channel_create;
|
||||||
|
|
||||||
mod member_fetch_all;
|
mod member_fetch_all;
|
||||||
|
mod member_remove;
|
||||||
mod member_fetch;
|
mod member_fetch;
|
||||||
mod member_edit;
|
mod member_edit;
|
||||||
|
|
||||||
@@ -21,6 +22,7 @@ pub fn routes() -> Vec<Route> {
|
|||||||
server_edit::req,
|
server_edit::req,
|
||||||
channel_create::req,
|
channel_create::req,
|
||||||
member_fetch_all::req,
|
member_fetch_all::req,
|
||||||
|
member_remove::req,
|
||||||
member_fetch::req,
|
member_fetch::req,
|
||||||
member_edit::req,
|
member_edit::req,
|
||||||
invites_fetch::req
|
invites_fetch::req
|
||||||
|
|||||||
Reference in New Issue
Block a user