From 87e7df02f29052a1db13f8e6b129a55eae21f36b Mon Sep 17 00:00:00 2001 From: Paul Makles <paulmakles@gmail.com> Date: Sun, 12 Apr 2020 12:16:00 +0100 Subject: [PATCH] Add check that people can message others in guild. --- src/database/mutual.rs | 50 +++++++++++++++++++++++++++++-------- src/database/permissions.rs | 17 +++++++------ src/routes/channel.rs | 4 +++ src/routes/mod.rs | 5 ++-- src/routes/user.rs | 2 +- 5 files changed, 57 insertions(+), 21 deletions(-) diff --git a/src/database/mutual.rs b/src/database/mutual.rs index 5eb2341..162dcc8 100644 --- a/src/database/mutual.rs +++ b/src/database/mutual.rs @@ -1,7 +1,7 @@ -use super::get_collection; +use super::{get_collection, MemberPermissions}; use bson::doc; -use mongodb::options::{FindOneOptions, FindOptions}; +use mongodb::options::FindOptions; pub fn find_mutual_guilds(user_id: &str, target_id: &str) -> Vec<String> { let col = get_collection("members"); @@ -79,23 +79,51 @@ pub fn find_mutual_groups(user_id: &str, target_id: &str) -> Vec<String> { } } -pub fn has_mutual_connection(user_id: &str, target_id: &str) -> bool { - let col = get_collection("guilds"); - if let Ok(result) = col.find_one( +pub fn has_mutual_connection(user_id: &str, target_id: &str, with_permission: bool) -> bool { + let mut doc = doc! { "_id": 1 }; + + if with_permission { + doc.insert("default_permissions", 1); + } + + let opt = FindOptions::builder().projection(doc); + + if let Ok(result) = get_collection("guilds").find( doc! { "$and": [ { "members": { "$elemMatch": { "id": user_id } } }, { "members": { "$elemMatch": { "id": target_id } } }, ] }, - FindOneOptions::builder() - .projection(doc! { "_id": 1 }) // ? TODO: fetch permissions - .build(), - ) { - if result.is_some() { - true + if with_permission { + opt.build() } else { + opt.limit(1).build() + }, + ) { + if with_permission { + for item in result { + // ? logic should match permissions.rs#calculate + if let Ok(guild) = item { + if guild.get_str("owner").unwrap() == user_id { + return true; + } + + let permissions = guild.get_i32("default_permissions").unwrap() as u32; + + if MemberPermissions([ permissions ]).get_send_direct_messages() { + return true; + } + } + } + false + } else { + if result.count() > 0 { + true + } else { + false + } } } else { false diff --git a/src/database/permissions.rs b/src/database/permissions.rs index 29ebdbf..ef51cd1 100644 --- a/src/database/permissions.rs +++ b/src/database/permissions.rs @@ -19,7 +19,7 @@ pub enum Relationship { SELF = 6, } -#[derive(Debug, PartialEq, Eq, TryFromPrimitive)] +#[derive(Debug, PartialEq, Eq, TryFromPrimitive, Copy, Clone)] #[repr(u32)] pub enum Permission { Access = 1, @@ -37,7 +37,7 @@ pub enum Permission { bitfield! { pub struct MemberPermissions(MSB0 [u32]); - u8; + u32; pub get_access, set_access: 31; pub get_create_invite, set_create_invite: 30; pub get_kick_members, set_kick_members: 29; @@ -148,6 +148,7 @@ impl PermissionCalculator { let mut permissions: u32 = 0; if let Some(guild) = &self.guild { if let Some(_member) = &self.member { + // ? logic should match mutual.rs#has_mutual_connection if guild.owner == self.user.id { return u32::MAX; } @@ -162,9 +163,7 @@ impl PermissionCalculator { if let Some(arr) = &channel.recipients { let mut other_user = ""; for item in arr { - if item == &self.user.id { - permissions = 177; - } else { + if item != &self.user.id { other_user = item; } } @@ -173,12 +172,16 @@ impl PermissionCalculator { let relationship = get_relationship_internal(&self.user.id, &other_user, &relationships); - if relationship == Relationship::Blocked + if relationship == Relationship::Friend { + permissions = 177; + } else if relationship == Relationship::Blocked || relationship == Relationship::BlockedOther { permissions = 1; - } else if has_mutual_connection(&self.user.id, other_user) { + } else if has_mutual_connection(&self.user.id, other_user, true) { permissions = 177; + } else { + permissions = 1; } } } diff --git a/src/routes/channel.rs b/src/routes/channel.rs index c49574e..bbee4f5 100644 --- a/src/routes/channel.rs +++ b/src/routes/channel.rs @@ -431,6 +431,10 @@ pub fn send_message( let permissions = with_permissions!(user, target); if !permissions.get_send_messages() { + if target.channel_type == 0 { + return Some(Response::LackingPermission(Permission::SendDirectMessages)); + } + return Some(Response::LackingPermission(Permission::SendMessages)); } diff --git a/src/routes/mod.rs b/src/routes/mod.rs index 2493df4..aeeac18 100644 --- a/src/routes/mod.rs +++ b/src/routes/mod.rs @@ -50,8 +50,9 @@ impl<'a> rocket::response::Responder<'a> for Permission { rocket::response::Response::build() .header(ContentType::JSON) .sized_body(Cursor::new(format!( - "{{\"error\":\"Lacking {:?} permission.\"}}", - self + "{{\"error\":\"Lacking permission: {:?}.\",\"permission\":{}}}", + self, + self as u32, ))) .ok() } diff --git a/src/routes/user.rs b/src/routes/user.rs index f2dee0f..71ccc83 100644 --- a/src/routes/user.rs +++ b/src/routes/user.rs @@ -157,7 +157,7 @@ pub fn dm(user: UserRef, target: UserRef) -> Response { ).is_ok() { Response::Success(json!({ "id": id.to_string() })) } else { - Response::InternalServerError(json!({ "error": "Failed to create new chanel." })) + Response::InternalServerError(json!({ "error": "Failed to create new channel." })) } } } else { -- GitLab