diff --git a/Cargo.lock b/Cargo.lock index 74e717033bf9feabad07745c1cf7069b27ce0bd3..15abde0bc4c0670495f2f1b8a3c536a3b96be734 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -95,6 +95,11 @@ dependencies = [ "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "bitfield" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "bitflags" version = "1.2.1" @@ -1553,6 +1558,7 @@ name = "revolt" version = "0.1.0" dependencies = [ "bcrypt 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bitfield 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)", "bson 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "dotenv 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2677,6 +2683,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" "checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" "checksum bcrypt 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "28dff1c1a22f9401213d983f6c309e807e72c33d5dc5514fe5005b0205c46e8f" +"checksum bitfield 0.13.2 (registry+https://github.com/rust-lang/crates.io-index)" = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719" "checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" "checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" "checksum block-cipher-trait 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1c924d49bd09e7c06003acda26cd9742e796e34282ec6c1189404dee0c1f4774" diff --git a/Cargo.toml b/Cargo.toml index f9c50dd2b2e07907170fe72af942f9565196f1d3..46faf38f660b61ede0fe7b4fba00c37f1e67d936 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,3 +26,4 @@ ws = "0.9.1" hashbrown = "0.7.0" serde_json = "1.0.47" rocket_cors = "0.5.1" +bitfield = "0.13.2" diff --git a/src/database/channel.rs b/src/database/channel.rs index ac35285b3ee33ae65e629540f207cbc5c759c8ec..1aba7e2a4dafd418938fbdb422880350afefb0b7 100644 --- a/src/database/channel.rs +++ b/src/database/channel.rs @@ -6,7 +6,7 @@ pub struct Channel { pub id: String, #[serde(rename = "type")] pub channel_type: u8, - + pub last_message: Option<String>, // for Direct Messages @@ -15,6 +15,7 @@ pub struct Channel { // for Guilds pub name: Option<String>, + pub guild: Option<String>, // for Guilds and Group DMs pub description: Option<String>, diff --git a/src/database/guild.rs b/src/database/guild.rs index c9254d2393af8dba9d9b4fda192ef06daddc2076..51a74aa5b9e02fbd6e78b14aaf315fb9aaf9e041 100644 --- a/src/database/guild.rs +++ b/src/database/guild.rs @@ -1,4 +1,56 @@ use serde::{Deserialize, Serialize}; +use bson::{bson, doc}; + +use super::get_collection; +use mongodb::options::FindOneOptions; + +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; +} + +pub fn find_member_permissions<C: Into<Option<String>>>(id: String, guild: String, channel: C) -> u8 { + let col = get_collection("guilds"); + + match col.find_one( + doc! { + "_id": &guild, + "members": { + "$elemMatch": { + "id": &id, + } + } + }, + FindOneOptions::builder() + .projection( + doc! { + "members.$": 1, + "owner": 1, + "default_permissions": 1, + } + ) + .build() + ) { + Ok(result) => { + if let Some(doc) = result { + if doc.get_str("owner").unwrap() == id { + return u8::MAX; + } + + doc.get_i32("default_permissions").unwrap() as u8 + } else { + 0 + } + }, + Err(_) => 0 + } +} #[derive(Serialize, Deserialize, Debug)] pub struct Member { @@ -24,4 +76,6 @@ pub struct Guild { pub channels: Vec<String>, pub members: Vec<Member>, pub invites: Vec<Invite>, + + pub default_permissions: u32, } diff --git a/src/main.rs b/src/main.rs index 13ade671775a1f5cd645fc2fb053c6769e6ad989..a3de253a052a1bd60e53474e4710b387768c898e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,8 @@ extern crate rocket; #[macro_use] extern crate rocket_contrib; +#[macro_use] +extern crate bitfield; pub mod database; pub mod email; diff --git a/src/routes/guild.rs b/src/routes/guild.rs index 684b8b49564fef2552cfdc6b86dec8a4dad6361b..37538c219fea31b002f4806c87993b68f46a98cc 100644 --- a/src/routes/guild.rs +++ b/src/routes/guild.rs @@ -1,4 +1,4 @@ -use crate::database::{self, channel::Channel, guild::Guild, user::User}; +use crate::database::{self, channel::Channel, guild::{ Guild, find_member_permissions }, user::User}; use bson::{bson, doc, from_bson, Bson}; use rocket_contrib::json::{Json, JsonValue}; @@ -40,7 +40,11 @@ pub fn my_guilds(user: User) -> JsonValue { /// fetch a guild #[get("/<target>")] -pub fn guild(user: User, target: Guild) -> JsonValue { +pub fn guild(user: User, target: Guild) -> Option<JsonValue> { + if find_member_permissions(user.id.clone(), target.id.clone(), None) == 0 { + return None; + } + let mut targets = vec![]; for channel in target.channels { targets.push(Bson::String(channel)); @@ -69,18 +73,18 @@ pub fn guild(user: User, target: Guild) -> JsonValue { })); } - json!({ + Some(json!({ "id": target.id, "name": target.name, "description": target.description, "owner": target.owner, "channels": channels, - }) + })) } - Err(_) => json!({ + Err(_) => Some(json!({ "success": false, "error": "Failed to fetch channels." - }), + })), } } @@ -91,7 +95,7 @@ pub struct CreateGuild { nonce: String, } -/// send a message to a channel +/// create a new guild #[post("/create", data = "<info>")] pub fn create_guild(user: User, info: Json<CreateGuild>) -> JsonValue { if !user.email_verification.verified { @@ -120,12 +124,14 @@ pub fn create_guild(user: User, info: Json<CreateGuild>) -> JsonValue { }); } + let id = Ulid::new().to_string(); let channel_id = Ulid::new().to_string(); if let Err(_) = channels.insert_one( doc! { "_id": channel_id.clone(), "type": ChannelType::GUILDCHANNEL as u32, "name": "general", + "guild": id.clone(), }, None, ) { @@ -135,7 +141,6 @@ pub fn create_guild(user: User, info: Json<CreateGuild>) -> JsonValue { }); } - let id = Ulid::new().to_string(); if col .insert_one( doc! { @@ -153,6 +158,7 @@ pub fn create_guild(user: User, info: Json<CreateGuild>) -> JsonValue { } ], "invites": [], + "default_permissions": 51, }, None, )