Add / remove from group + clean up code.
This commit is contained in:
@@ -20,3 +20,7 @@ pub struct Message {
|
|||||||
|
|
||||||
pub previous_content: Option<Vec<PreviousEntry>>,
|
pub previous_content: Option<Vec<PreviousEntry>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ? TODO: write global send message
|
||||||
|
// ? pub fn send_message();
|
||||||
|
// ? handle websockets?
|
||||||
|
|||||||
@@ -160,20 +160,3 @@ impl<'r> FromParam<'r> for UserRef {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'r> FromParam<'r> for User {
|
|
||||||
type Error = &'r RawStr;
|
|
||||||
|
|
||||||
fn from_param(param: &'r RawStr) -> Result<Self, Self::Error> {
|
|
||||||
let col = database::get_collection("users");
|
|
||||||
let result = col
|
|
||||||
.find_one(doc! { "_id": param.to_string() }, None)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
if let Some(user) = result {
|
|
||||||
Ok(from_bson(bson::Bson::Document(user)).expect("Failed to unwrap user."))
|
|
||||||
} else {
|
|
||||||
Err(param)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -6,26 +6,8 @@ use serde::{Deserialize, Serialize};
|
|||||||
|
|
||||||
use crate::database;
|
use crate::database;
|
||||||
|
|
||||||
use database::channel::Channel;
|
|
||||||
use database::message::Message;
|
use database::message::Message;
|
||||||
|
|
||||||
impl<'r> FromParam<'r> for Channel {
|
|
||||||
type Error = &'r RawStr;
|
|
||||||
|
|
||||||
fn from_param(param: &'r RawStr) -> Result<Self, Self::Error> {
|
|
||||||
let col = database::get_collection("channels");
|
|
||||||
let result = col
|
|
||||||
.find_one(doc! { "_id": param.to_string() }, None)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
if let Some(channel) = result {
|
|
||||||
Ok(from_bson(bson::Bson::Document(channel)).expect("Failed to unwrap channel."))
|
|
||||||
} else {
|
|
||||||
Err(param)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub struct ChannelRef {
|
pub struct ChannelRef {
|
||||||
#[serde(rename = "_id")]
|
#[serde(rename = "_id")]
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ use rocket::request::FromParam;
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::database;
|
use crate::database;
|
||||||
use crate::database::guild::Guild;
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub struct GuildRef {
|
pub struct GuildRef {
|
||||||
@@ -74,20 +73,3 @@ impl<'r> FromParam<'r> for GuildRef {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'r> FromParam<'r> for Guild {
|
|
||||||
type Error = &'r RawStr;
|
|
||||||
|
|
||||||
fn from_param(param: &'r RawStr) -> Result<Self, Self::Error> {
|
|
||||||
let col = database::get_collection("guilds");
|
|
||||||
let result = col
|
|
||||||
.find_one(doc! { "_id": param.to_string() }, None)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
if let Some(guild) = result {
|
|
||||||
Ok(from_bson(bson::Bson::Document(guild)).expect("Failed to unwrap guild."))
|
|
||||||
} else {
|
|
||||||
Err(param)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use super::Response;
|
use super::Response;
|
||||||
use crate::database::{
|
use crate::database::{
|
||||||
self, get_relationship_internal, message::Message, Permission, PermissionCalculator,
|
self, get_relationship, get_relationship_internal, message::Message, Permission,
|
||||||
Relationship,
|
PermissionCalculator, Relationship,
|
||||||
};
|
};
|
||||||
use crate::guards::auth::UserRef;
|
use crate::guards::auth::UserRef;
|
||||||
use crate::guards::channel::ChannelRef;
|
use crate::guards::channel::ChannelRef;
|
||||||
@@ -9,7 +9,7 @@ use crate::util::vec_to_set;
|
|||||||
|
|
||||||
use bson::{doc, from_bson, Bson, Bson::UtcDatetime};
|
use bson::{doc, from_bson, Bson, Bson::UtcDatetime};
|
||||||
use chrono::prelude::*;
|
use chrono::prelude::*;
|
||||||
use hashbrown::HashSet;
|
use mongodb::options::FindOptions;
|
||||||
use num_enum::TryFromPrimitive;
|
use num_enum::TryFromPrimitive;
|
||||||
use rocket_contrib::json::Json;
|
use rocket_contrib::json::Json;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@@ -64,40 +64,61 @@ pub fn create_group(user: UserRef, info: Json<CreateGroup>) -> Response {
|
|||||||
return Response::BadRequest(json!({ "error": "Group already created!" }));
|
return Response::BadRequest(json!({ "error": "Group already created!" }));
|
||||||
}
|
}
|
||||||
|
|
||||||
let relationships = user.fetch_relationships();
|
let mut query = vec![];
|
||||||
|
for item in &set {
|
||||||
let mut users = vec![];
|
if item == &user.id {
|
||||||
for item in set {
|
continue;
|
||||||
if let Some(target) = UserRef::from(item) {
|
|
||||||
if get_relationship_internal(&user.id, &target.id, &relationships)
|
|
||||||
!= Relationship::Friend
|
|
||||||
{
|
|
||||||
return Response::BadRequest(json!({ "error": "Not friends with user(s)." }));
|
|
||||||
}
|
|
||||||
|
|
||||||
users.push(Bson::String(target.id));
|
|
||||||
} else {
|
|
||||||
return Response::BadRequest(json!({ "error": "Specified non-existant user(s)." }));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
query.push(Bson::String(item.clone()));
|
||||||
}
|
}
|
||||||
|
|
||||||
let id = Ulid::new().to_string();
|
if let Ok(result) = database::get_collection("users").find(
|
||||||
if col
|
doc! {
|
||||||
.insert_one(
|
"_id": {
|
||||||
doc! {
|
"$in": &query
|
||||||
"_id": id.clone(),
|
}
|
||||||
"nonce": nonce,
|
},
|
||||||
"type": ChannelType::GROUPDM as u32,
|
FindOptions::builder().limit(query.len() as i64).build(),
|
||||||
"recipients": users,
|
) {
|
||||||
"name": name,
|
if result.count() != query.len() {
|
||||||
},
|
return Response::BadRequest(json!({ "error": "Specified non-existant user(s)." }));
|
||||||
None,
|
}
|
||||||
)
|
|
||||||
.is_ok()
|
let relationships = user.fetch_relationships();
|
||||||
{
|
for item in set {
|
||||||
Response::Success(json!({ "id": id }))
|
if item == user.id {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if get_relationship_internal(&user.id, &item, &relationships) != Relationship::Friend {
|
||||||
|
return Response::BadRequest(json!({ "error": "Not friends with user(s)." }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
query.push(Bson::String(user.id.clone()));
|
||||||
|
|
||||||
|
let id = Ulid::new().to_string();
|
||||||
|
if col
|
||||||
|
.insert_one(
|
||||||
|
doc! {
|
||||||
|
"_id": id.clone(),
|
||||||
|
"nonce": nonce,
|
||||||
|
"type": ChannelType::GROUPDM as u32,
|
||||||
|
"recipients": &query,
|
||||||
|
"name": name,
|
||||||
|
"owner": &user.id,
|
||||||
|
},
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.is_ok()
|
||||||
|
{
|
||||||
|
Response::Success(json!({ "id": id }))
|
||||||
|
} else {
|
||||||
|
Response::InternalServerError(json!({ "error": "Failed to create guild channel." }))
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Response::InternalServerError(json!({ "error": "Failed to create guild channel." }))
|
Response::InternalServerError(json!({ "error": "Failed to validate users." }))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,6 +171,102 @@ pub fn channel(user: UserRef, target: ChannelRef) -> Option<Response> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// [groups] add user to channel
|
||||||
|
#[put("/<target>/recipients/<member>")]
|
||||||
|
pub fn add_member(user: UserRef, target: ChannelRef, member: UserRef) -> Option<Response> {
|
||||||
|
if target.channel_type != 1 {
|
||||||
|
return Some(Response::BadRequest(json!({ "error": "Not a group DM." })));
|
||||||
|
}
|
||||||
|
|
||||||
|
with_permissions!(user, target);
|
||||||
|
|
||||||
|
let recp = target.recipients.unwrap();
|
||||||
|
if recp.len() == 50 {
|
||||||
|
return Some(Response::BadRequest(
|
||||||
|
json!({ "error": "Maximum group size is 50." }),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
let set = vec_to_set(&recp);
|
||||||
|
if set.get(&member.id).is_some() {
|
||||||
|
return Some(Response::BadRequest(
|
||||||
|
json!({ "error": "User already in group!" }),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
match get_relationship(&user, &member) {
|
||||||
|
Relationship::Friend => {
|
||||||
|
if database::get_collection("channels")
|
||||||
|
.update_one(
|
||||||
|
doc! { "_id": &target.id },
|
||||||
|
doc! {
|
||||||
|
"$push": {
|
||||||
|
"recipients": &member.id
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.is_ok()
|
||||||
|
{
|
||||||
|
Some(Response::Result(super::Status::Ok))
|
||||||
|
} else {
|
||||||
|
Some(Response::InternalServerError(
|
||||||
|
json!({ "error": "Failed to add user to group." }),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => Some(Response::BadRequest(
|
||||||
|
json!({ "error": "Not friends with user." }),
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// [groups] remove user from channel
|
||||||
|
#[delete("/<target>/recipients/<member>")]
|
||||||
|
pub fn remove_member(user: UserRef, target: ChannelRef, member: UserRef) -> Option<Response> {
|
||||||
|
if target.channel_type != 1 {
|
||||||
|
return Some(Response::BadRequest(json!({ "error": "Not a group DM." })));
|
||||||
|
}
|
||||||
|
|
||||||
|
if &user.id == &member.id {
|
||||||
|
return Some(Response::BadRequest(
|
||||||
|
json!({ "error": "Cannot kick yourself, leave the channel instead." }),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
let permissions = with_permissions!(user, target);
|
||||||
|
|
||||||
|
if !permissions.get_kick_members() {
|
||||||
|
return Some(Response::LackingPermission(Permission::KickMembers));
|
||||||
|
}
|
||||||
|
|
||||||
|
let set = vec_to_set(&target.recipients.unwrap());
|
||||||
|
if set.get(&member.id).is_none() {
|
||||||
|
return Some(Response::BadRequest(
|
||||||
|
json!({ "error": "User not in group!" }),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
if database::get_collection("channels")
|
||||||
|
.update_one(
|
||||||
|
doc! { "_id": &target.id },
|
||||||
|
doc! {
|
||||||
|
"$pull": {
|
||||||
|
"recipients": &member.id
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.is_ok()
|
||||||
|
{
|
||||||
|
Some(Response::Result(super::Status::Ok))
|
||||||
|
} else {
|
||||||
|
Some(Response::InternalServerError(
|
||||||
|
json!({ "error": "Failed to add user to group." }),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// delete channel
|
/// delete channel
|
||||||
/// or leave group DM
|
/// or leave group DM
|
||||||
/// or close DM conversation
|
/// or close DM conversation
|
||||||
@@ -297,7 +414,11 @@ pub fn send_message(
|
|||||||
let nonce: String = message.nonce.chars().take(32).collect();
|
let nonce: String = message.nonce.chars().take(32).collect();
|
||||||
|
|
||||||
let col = database::get_collection("messages");
|
let col = database::get_collection("messages");
|
||||||
if let Some(_) = col.find_one(doc! { "nonce": nonce.clone() }, None).unwrap() {
|
if col
|
||||||
|
.find_one(doc! { "nonce": nonce.clone() }, None)
|
||||||
|
.unwrap()
|
||||||
|
.is_some()
|
||||||
|
{
|
||||||
return Some(Response::BadRequest(
|
return Some(Response::BadRequest(
|
||||||
json!({ "error": "Message already sent!" }),
|
json!({ "error": "Message already sent!" }),
|
||||||
));
|
));
|
||||||
@@ -309,10 +430,10 @@ pub fn send_message(
|
|||||||
.insert_one(
|
.insert_one(
|
||||||
doc! {
|
doc! {
|
||||||
"_id": id.clone(),
|
"_id": id.clone(),
|
||||||
"nonce": nonce.clone(),
|
"nonce": nonce,
|
||||||
"channel": target.id.clone(),
|
"channel": target.id.clone(),
|
||||||
"author": user.id.clone(),
|
"author": user.id,
|
||||||
"content": content.clone(),
|
"content": content,
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
@@ -321,7 +442,7 @@ pub fn send_message(
|
|||||||
if target.channel_type == ChannelType::DM as u8 {
|
if target.channel_type == ChannelType::DM as u8 {
|
||||||
let col = database::get_collection("channels");
|
let col = database::get_collection("channels");
|
||||||
col.update_one(
|
col.update_one(
|
||||||
doc! { "_id": target.id.clone() },
|
doc! { "_id": &target.id },
|
||||||
doc! { "$set": { "active": true } },
|
doc! { "$set": { "active": true } },
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
@@ -420,7 +541,7 @@ pub fn edit_message(
|
|||||||
doc! {
|
doc! {
|
||||||
"$set": {
|
"$set": {
|
||||||
"content": edit.content.clone(),
|
"content": edit.content.clone(),
|
||||||
"edited": UtcDatetime(edited.clone())
|
"edited": UtcDatetime(edited)
|
||||||
},
|
},
|
||||||
"$push": {
|
"$push": {
|
||||||
"previous_content": {
|
"previous_content": {
|
||||||
@@ -467,7 +588,7 @@ pub fn delete_message(user: UserRef, target: ChannelRef, message: Message) -> Op
|
|||||||
|
|
||||||
let col = database::get_collection("messages");
|
let col = database::get_collection("messages");
|
||||||
|
|
||||||
match col.delete_one(doc! { "_id": message.id.clone() }, None) {
|
match col.delete_one(doc! { "_id": &message.id }, None) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
/*websocket::queue_message(
|
/*websocket::queue_message(
|
||||||
get_recipients(&target),
|
get_recipients(&target),
|
||||||
|
|||||||
@@ -127,7 +127,11 @@ pub fn create_guild(user: UserRef, info: Json<CreateGuild>) -> Response {
|
|||||||
|
|
||||||
let channels = database::get_collection("channels");
|
let channels = database::get_collection("channels");
|
||||||
let col = database::get_collection("guilds");
|
let col = database::get_collection("guilds");
|
||||||
if let Some(_) = col.find_one(doc! { "nonce": nonce.clone() }, None).unwrap() {
|
if col
|
||||||
|
.find_one(doc! { "nonce": nonce.clone() }, None)
|
||||||
|
.unwrap()
|
||||||
|
.is_some()
|
||||||
|
{
|
||||||
return Response::BadRequest(json!({ "error": "Guild already created!" }));
|
return Response::BadRequest(json!({ "error": "Guild already created!" }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -89,6 +89,8 @@ pub fn mount(rocket: Rocket) -> Rocket {
|
|||||||
routes![
|
routes![
|
||||||
channel::create_group,
|
channel::create_group,
|
||||||
channel::channel,
|
channel::channel,
|
||||||
|
channel::add_member,
|
||||||
|
channel::remove_member,
|
||||||
channel::delete,
|
channel::delete,
|
||||||
channel::messages,
|
channel::messages,
|
||||||
channel::get_message,
|
channel::get_message,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use hashbrown::HashSet;
|
use hashbrown::HashSet;
|
||||||
use std::iter::FromIterator;
|
use std::iter::FromIterator;
|
||||||
|
|
||||||
pub fn vec_to_set<T: Clone + Eq + std::hash::Hash>(data: &Vec<T>) -> HashSet<T> {
|
pub fn vec_to_set<T: Clone + Eq + std::hash::Hash>(data: &[T]) -> HashSet<T> {
|
||||||
HashSet::from_iter(data.iter().cloned())
|
HashSet::from_iter(data.iter().cloned())
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user