Implement channel permissions.

This commit is contained in:
Paul Makles
2020-04-09 11:38:32 +01:00
parent 7af9a77df4
commit 82f6e6215f
8 changed files with 360 additions and 240 deletions

View File

@@ -8,7 +8,7 @@ pub fn find_member_permissions<C: Into<Option<String>>>(
id: String,
guild: String,
channel: C,
) -> u8 {
) -> u32 {
let col = get_collection("guilds");
match col.find_one(
@@ -31,10 +31,10 @@ pub fn find_member_permissions<C: Into<Option<String>>>(
Ok(result) => {
if let Some(doc) = result {
if doc.get_str("owner").unwrap() == id {
return u8::MAX;
return u32::MAX;
}
doc.get_i32("default_permissions").unwrap() as u8
doc.get_i32("default_permissions").unwrap() as u32
} else {
0
}

View File

@@ -27,6 +27,7 @@ pub fn get_collection(collection: &str) -> Collection {
pub mod channel;
pub mod guild;
pub mod message;
pub mod mutual;
pub mod permissions;
pub mod user;

35
src/database/mutual.rs Normal file
View File

@@ -0,0 +1,35 @@
use super::get_collection;
use bson::{bson, doc};
use mongodb::options::FindOneOptions;
/*pub struct MutualGuild {
}
pub fn find_mutual_guilds(user_id: String, target_id: String) -> Vec<> {
}*/
pub fn has_mutual_connection(user_id: String, target_id: String) -> bool {
let col = get_collection("guilds");
if let Ok(result) = col.find_one(
doc! {
"$and": [
{ "members": { "$elemMatch": { "id": user_id } } },
{ "members": { "$elemMatch": { "id": target_id } } },
]
},
FindOneOptions::builder()
.projection(doc! { "_id": 1 })
.build(),
) {
if result.is_some() {
true
} else {
false
}
} else {
false
}
}

View File

@@ -1,31 +1,99 @@
bitfield! {
pub struct MemberPermissions(MSB0 [u8]);
u8;
pub get_access, set_access: 7;
pub get_create_invite, set_create_invite: 6;
pub get_kick_members, set_kick_members: 5;
pub get_ban_members, set_ban_members: 4;
pub get_read_messages, set_read_messages: 3;
pub get_send_messages, set_send_messages: 2;
}
use super::get_collection;
use super::mutual::has_mutual_connection;
use crate::database::user::UserRelationship;
use crate::guards::auth::UserRef;
use crate::guards::channel::ChannelRef;
use crate::guards::guild::GuildRef;
use bson::{bson, doc};
use mongodb::options::FindOneOptions;
use num_enum::TryFromPrimitive;
#[derive(Debug, PartialEq, Eq, TryFromPrimitive)]
#[repr(u8)]
pub enum Relationship {
FRIEND = 0,
OUTGOING = 1,
INCOMING = 2,
BLOCKED = 3,
BLOCKEDOTHER = 4,
NONE = 5,
SELF = 6,
}
#[derive(Debug, PartialEq, Eq, TryFromPrimitive)]
#[repr(u32)]
pub enum Permission {
ACCESS = 1,
CREATE_INVITE = 2,
KICK_MEMBERS = 4,
BAN_MEMBERS = 8,
READ_MESSAGES = 16,
SEND_MESSAGES = 32,
MANAGE_MESSAGES = 64,
MANAGE_CHANNELS = 128,
MANAGE_SERVER = 256,
MANAGE_ROLES = 512,
}
bitfield! {
pub struct MemberPermissions(MSB0 [u32]);
u8;
pub get_access, set_access: 31;
pub get_create_invite, set_create_invite: 30;
pub get_kick_members, set_kick_members: 29;
pub get_ban_members, set_ban_members: 28;
pub get_read_messages, set_read_messages: 27;
pub get_send_messages, set_send_messages: 26;
pub get_manage_messages, set_manage_messages: 25;
pub get_manage_channels, set_manage_channels: 24;
pub get_manage_server, set_manage_server: 23;
pub get_manage_roles, set_manage_roles: 22;
}
pub fn get_relationship_internal(
user_id: &str,
target_id: &str,
relationships: &Option<Vec<UserRelationship>>,
) -> Relationship {
if user_id == target_id {
return Relationship::SELF;
}
if let Some(arr) = &relationships {
for entry in arr {
if entry.id == target_id {
match entry.status {
0 => return Relationship::FRIEND,
1 => return Relationship::OUTGOING,
2 => return Relationship::INCOMING,
3 => return Relationship::BLOCKED,
4 => return Relationship::BLOCKEDOTHER,
_ => return Relationship::NONE,
}
}
}
}
Relationship::NONE
}
pub fn get_relationship(a: &UserRef, b: &UserRef) -> Relationship {
if a.id == b.id {
return Relationship::SELF;
}
get_relationship_internal(&a.id, &b.id, &a.fetch_relationships())
}
pub struct PermissionCalculator {
pub user_id: String,
pub user: UserRef,
pub channel: Option<ChannelRef>,
pub guild: Option<GuildRef>,
}
impl PermissionCalculator {
pub fn new(user_id: String) -> PermissionCalculator {
pub fn new(user: UserRef) -> PermissionCalculator {
PermissionCalculator {
user_id,
user,
channel: None,
guild: None,
}
@@ -45,7 +113,7 @@ impl PermissionCalculator {
}
}
pub fn calculate(self) -> u8 {
pub fn calculate(self) -> u32 {
let guild = if let Some(value) = self.guild {
Some(value)
} else if let Some(channel) = &self.channel {
@@ -70,14 +138,14 @@ impl PermissionCalculator {
doc! {
"members": {
"$elemMatch": {
"id": &self.user_id,
"id": &self.user.id,
}
}
},
doc! { }
doc! {},
) {
if guild.owner == self.user_id {
return u8::MAX;
if guild.owner == self.user.id {
return u32::MAX;
}
permissions = guild.default_permissions;
@@ -87,29 +155,42 @@ impl PermissionCalculator {
if let Some(channel) = &self.channel {
match channel.channel_type {
0 => {
// ? check user is part of the channel
if let Some(arr) = &channel.recipients {
let mut other_user = "";
for item in arr {
if item == &self.user_id {
if item == &self.user.id {
permissions = 49;
break;
} else {
other_user = item;
}
}
let relationships = self.user.fetch_relationships();
let relationship =
get_relationship_internal(&self.user.id, &other_user, &relationships);
if relationship == Relationship::BLOCKED
|| relationship == Relationship::BLOCKEDOTHER
{
permissions = 1;
} else if has_mutual_connection(self.user.id, other_user.to_string()) {
permissions = 49;
}
}
},
1 => {
unreachable!()
},
}
1 => unreachable!(),
2 => {
// nothing implemented yet
},
}
_ => {}
}
}
permissions as u8
permissions as u32
}
pub fn as_permission(self) -> MemberPermissions<[u8; 1]> {
MemberPermissions([ self.calculate() ])
pub fn as_permission(self) -> MemberPermissions<[u32; 1]> {
MemberPermissions([self.calculate()])
}
}