Group member add and remove routes.

This commit is contained in:
Paul Makles
2021-01-19 09:02:18 +00:00
parent 901b29f49e
commit c21d7c4620
8 changed files with 185 additions and 59 deletions

View File

@@ -5,6 +5,7 @@ use crate::{
};
use mongodb::bson::{to_bson, DateTime};
use serde::{Deserialize, Serialize};
use ulid::Ulid;
/*#[derive(Serialize, Deserialize, Debug)]
pub struct PreviousEntry {
@@ -41,6 +42,18 @@ pub struct Message {
}
impl Message {
pub fn create(author: String, channel: String, content: String) -> Message {
Message {
id: Ulid::new().to_string(),
nonce: None,
channel,
author,
content,
edited: None,
}
}
pub async fn publish(self) -> Result<()> {
get_collection("messages")
.insert_one(to_bson(&self).unwrap().as_document().unwrap().clone(), None)

View File

@@ -49,6 +49,12 @@ pub async fn calculate(user: &User, target: &Channel) -> ChannelPermissions<[u32
ChannelPermissions([0])
}
_ => unreachable!(),
Channel::Group { recipients, .. } => {
if recipients.iter().find(|x| *x == &user.id).is_some() {
ChannelPermissions([ChannelPermission::View + ChannelPermission::SendMessage])
} else {
ChannelPermissions([0])
}
}
}
}

View File

@@ -43,68 +43,20 @@ pub enum ClientboundNotification {
},
ChannelCreate(Channel),
/*MessageCreate {
ChannelGroupJoin {
id: String,
nonce: Option<String>,
channel: String,
author: String,
content: String,
user: String,
},
MessageEdit {
id: String,
channel: String,
author: String,
content: String,
},
MessageDelete {
id: String,
},
GroupUserJoin {
ChannelGroupLeave {
id: String,
user: String,
},
GroupUserLeave {
id: String,
user: String,
},
GuildUserJoin {
id: String,
user: String,
},
GuildUserLeave {
id: String,
user: String,
banned: bool,
},
GuildChannelCreate {
id: String,
channel: String,
name: String,
description: String,
},
GuildChannelDelete {
id: String,
channel: String,
},
GuildDelete {
id: String,
},*/
UserRelationship {
id: String,
user: String,
status: RelationshipStatus,
},
UserPresence {
id: String,
online: bool,

View File

@@ -0,0 +1,70 @@
use crate::util::result::{Error, Result};
use crate::util::variables::MAX_GROUP_SIZE;
use crate::{database::*, notifications::events::ClientboundNotification};
use mongodb::bson::doc;
#[put("/<target>/recipients/<member>")]
pub async fn req(user: User, target: Ref, member: Ref) -> Result<()> {
if get_relationship(&user, &member.id) != RelationshipStatus::Friend {
Err(Error::NotFriends)?
}
let channel = target.fetch_channel().await?;
let perm = permissions::channel::calculate(&user, &channel).await;
if !perm.get_view() {
Err(Error::LabelMe)?
}
if let Channel::Group { id, recipients, .. } = channel {
if recipients.len() >= *MAX_GROUP_SIZE {
Err(Error::GroupTooLarge {
max: *MAX_GROUP_SIZE,
})?
}
if recipients.iter().find(|x| *x == &member.id).is_some() {
Err(Error::AlreadyInGroup)?
}
get_collection("channels")
.update_one(
doc! {
"_id": &id
},
doc! {
"$push": {
"recipients": &member.id
}
},
None,
)
.await
.map_err(|_| Error::DatabaseError {
operation: "update_one",
with: "channel",
})?;
ClientboundNotification::ChannelGroupJoin {
id: id.clone(),
user: member.id.clone(),
}
.publish(id.clone())
.await
.ok();
Message::create(
"00000000000000000000000000".to_string(),
id,
format!("<@{}> added <@{}> to the group.", user.id, member.id),
)
.publish()
.await
.ok();
Ok(())
} else {
Err(Error::InvalidOperation)
}
}

View File

@@ -36,6 +36,12 @@ pub async fn req(user: User, info: Json<Data>) -> Result<JsonValue> {
})?
}
for target in &set {
if get_relationship(&user, target) != RelationshipStatus::Friend {
Err(Error::NotFriends)?
}
}
if get_collection("channels")
.find_one(
doc! {
@@ -53,12 +59,6 @@ pub async fn req(user: User, info: Json<Data>) -> Result<JsonValue> {
Err(Error::DuplicateNonce)?
}
for target in &set {
if get_relationship(&user, target) != RelationshipStatus::Friend {
Err(Error::NotFriends)?
}
}
let id = Ulid::new().to_string();
let channel = Channel::Group {
id,

View File

@@ -0,0 +1,69 @@
use crate::util::result::{Error, Result};
use crate::{database::*, notifications::events::ClientboundNotification};
use mongodb::bson::doc;
#[delete("/<target>/recipients/<member>")]
pub async fn req(user: User, target: Ref, member: Ref) -> Result<()> {
if &user.id == &member.id {
Err(Error::CannotRemoveYourself)?
}
let channel = target.fetch_channel().await?;
if let Channel::Group {
id,
owner,
recipients,
..
} = channel
{
if &user.id != &owner {
// figure out if we want to use perm system here
Err(Error::LabelMe)?
}
if recipients.iter().find(|x| *x == &member.id).is_none() {
Err(Error::NotInGroup)?
}
get_collection("channels")
.update_one(
doc! {
"_id": &id
},
doc! {
"$pull": {
"recipients": &member.id
}
},
None,
)
.await
.map_err(|_| Error::DatabaseError {
operation: "update_one",
with: "channel",
})?;
ClientboundNotification::ChannelGroupLeave {
id: id.clone(),
user: member.id.clone(),
}
.publish(id.clone())
.await
.ok();
Message::create(
"00000000000000000000000000".to_string(),
id,
format!("<@{}> removed <@{}> from the group.", user.id, member.id),
)
.publish()
.await
.ok();
Ok(())
} else {
Err(Error::InvalidOperation)
}
}

View File

@@ -2,7 +2,9 @@ use rocket::Route;
mod delete_channel;
mod fetch_channel;
mod group_add_member;
mod group_create;
mod group_remove_member;
mod message_delete;
mod message_edit;
mod message_fetch;
@@ -18,6 +20,8 @@ pub fn routes() -> Vec<Route> {
message_fetch::req,
message_edit::req,
message_delete::req,
group_create::req
group_create::req,
group_add_member::req,
group_remove_member::req
]
}

View File

@@ -36,8 +36,14 @@ pub enum Error {
// ? Channel related errors.
#[snafu(display("Cannot edit someone else's message."))]
CannotEditMessage,
#[snafu(display("Cannot remove yourself from a group, use delete channel instead."))]
CannotRemoveYourself,
#[snafu(display("Group size is too large."))]
GroupTooLarge { max: usize },
#[snafu(display("User already part of group."))]
AlreadyInGroup,
#[snafu(display("User is not part of the group."))]
NotInGroup,
// ? General errors.
#[snafu(display("Failed to validate fields."))]
@@ -49,6 +55,8 @@ pub enum Error {
},
#[snafu(display("Internal server error."))]
InternalError,
#[snafu(display("Operation cannot be performed on this object."))]
InvalidOperation,
#[snafu(display("Already created an object with this nonce."))]
DuplicateNonce,
#[snafu(display("This request had no effect."))]
@@ -74,11 +82,15 @@ impl<'r> Responder<'r, 'static> for Error {
Error::NotFriends => Status::Forbidden,
Error::CannotEditMessage => Status::Forbidden,
Error::CannotRemoveYourself => Status::BadRequest,
Error::GroupTooLarge { .. } => Status::Forbidden,
Error::AlreadyInGroup => Status::Conflict,
Error::NotInGroup => Status::NotFound,
Error::FailedValidation { .. } => Status::UnprocessableEntity,
Error::DatabaseError { .. } => Status::InternalServerError,
Error::InternalError => Status::InternalServerError,
Error::InvalidOperation => Status::BadRequest,
Error::DuplicateNonce => Status::Conflict,
Error::NoEffect => Status::Ok,
};