From 5e70ceea0170b21875c50574906c76f9b641a23f Mon Sep 17 00:00:00 2001 From: Paul Makles <paulmakles@gmail.com> Date: Sat, 9 Jan 2021 16:50:11 +0000 Subject: [PATCH] Write proper user permission code. --- Cargo.toml | 1 - src/database/permissions/mod.rs | 47 ++---------------------- src/database/permissions/user.rs | 50 ++++++++++++++++++++++++++ src/routes/users/add_friend.rs | 4 +-- src/routes/users/block_user.rs | 2 +- src/routes/users/fetch_relationship.rs | 2 +- src/routes/users/fetch_user.rs | 2 +- src/routes/users/remove_friend.rs | 2 +- src/routes/users/unblock_user.rs | 4 +-- 9 files changed, 59 insertions(+), 55 deletions(-) create mode 100644 src/database/permissions/user.rs diff --git a/Cargo.toml b/Cargo.toml index 2ede2e1..d5813bd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,7 +19,6 @@ hive_pubsub = { version = "0.4.3", features = ["mongo"] } rocket_cors = { git = "https://github.com/lawliet89/rocket_cors", branch = "master" } rocket_contrib = { git = "https://github.com/SergioBenitez/Rocket", branch = "master" } rocket = { git = "https://github.com/SergioBenitez/Rocket", branch = "master", default-features = false } -# ! FIXME: Switch to async-std runtime. mongodb = { version = "1.1.1", features = ["tokio-runtime"], default-features = false } once_cell = "1.4.1" diff --git a/src/database/permissions/mod.rs b/src/database/permissions/mod.rs index 2de8a8e..4565ef9 100644 --- a/src/database/permissions/mod.rs +++ b/src/database/permissions/mod.rs @@ -1,46 +1,3 @@ -use crate::database::*; -use num_enum::TryFromPrimitive; -use std::ops; +pub mod user; -#[derive(Debug, PartialEq, Eq, TryFromPrimitive, Copy, Clone)] -#[repr(u32)] -pub enum UserPermission { - Access = 1, - SendMessage = 2, - Invite = 4, -} - -bitfield! { - pub struct UserPermissions(MSB0 [u32]); - u32; - pub get_access, _: 31; - pub get_send_message, _: 30; - pub get_invite, _: 29; -} - -impl_op_ex!(+ |a: &UserPermission, b: &UserPermission| -> u32 { *a as u32 | *b as u32 }); -impl_op_ex_commutative!(+ |a: &u32, b: &UserPermission| -> u32 { *a | *b as u32 }); - -pub async fn temp_calc_perm(_user: &User, _target: &User) -> UserPermissions<[u32; 1]> { - // if friends; Access + Message + Invite - // if mutually know each other: - // and has DMs from users enabled -> Access + Message - // otherwise -> Access - // otherwise; None - - UserPermissions([UserPermission::Access + UserPermission::SendMessage + UserPermission::Invite]) -} - -pub fn get_relationship(a: &User, b: &Ref) -> RelationshipStatus { - if a.id == b.id { - return RelationshipStatus::Friend; - } - - if let Some(relations) = &a.relations { - if let Some(relationship) = relations.iter().find(|x| x.id == b.id) { - return relationship.status.clone(); - } - } - - RelationshipStatus::None -} +pub use user::get_relationship; diff --git a/src/database/permissions/user.rs b/src/database/permissions/user.rs new file mode 100644 index 0000000..f08790a --- /dev/null +++ b/src/database/permissions/user.rs @@ -0,0 +1,50 @@ +use crate::database::*; +use num_enum::TryFromPrimitive; +use std::ops; + +#[derive(Debug, PartialEq, Eq, TryFromPrimitive, Copy, Clone)] +#[repr(u32)] +pub enum UserPermission { + Access = 1, + SendMessage = 2, + Invite = 4, +} + +bitfield! { + pub struct UserPermissions(MSB0 [u32]); + u32; + pub get_access, _: 31; + pub get_send_message, _: 30; + pub get_invite, _: 29; +} + +impl_op_ex!(+ |a: &UserPermission, b: &UserPermission| -> u32 { *a as u32 | *b as u32 }); +impl_op_ex_commutative!(+ |a: &u32, b: &UserPermission| -> u32 { *a | *b as u32 }); + +pub async fn calculate(user: &User, target: &str) -> UserPermissions<[u32; 1]> { + // if friends; Access + Message + Invite + // if mutually know each other: + // and has DMs from users enabled -> Access + Message + // otherwise -> Access + // otherwise; None + + if let RelationshipStatus::Friend = get_relationship(&user, &target) { + UserPermissions([UserPermission::Access + UserPermission::SendMessage + UserPermission::Invite]) + } else { + UserPermissions([ 0 ]) + } +} + +pub fn get_relationship(a: &User, b: &str) -> RelationshipStatus { + if a.id == b { + return RelationshipStatus::Friend; + } + + if let Some(relations) = &a.relations { + if let Some(relationship) = relations.iter().find(|x| x.id == b) { + return relationship.status.clone(); + } + } + + RelationshipStatus::None +} diff --git a/src/routes/users/add_friend.rs b/src/routes/users/add_friend.rs index 09b4d98..1af0a85 100644 --- a/src/routes/users/add_friend.rs +++ b/src/routes/users/add_friend.rs @@ -33,9 +33,7 @@ pub async fn req(user: User, username: String) -> Result<JsonValue> { match get_relationship( &user, - &Ref { - id: target_id.to_string(), - }, + &target_id, ) { RelationshipStatus::User => return Err(Error::NoEffect), RelationshipStatus::Friend => return Err(Error::AlreadyFriends), diff --git a/src/routes/users/block_user.rs b/src/routes/users/block_user.rs index b12fe04..cae153f 100644 --- a/src/routes/users/block_user.rs +++ b/src/routes/users/block_user.rs @@ -10,7 +10,7 @@ use rocket_contrib::json::JsonValue; pub async fn req(user: User, target: Ref) -> Result<JsonValue> { let col = get_collection("users"); - match get_relationship(&user, &target) { + match get_relationship(&user, &target.id) { RelationshipStatus::User | RelationshipStatus::Blocked => Err(Error::NoEffect), RelationshipStatus::BlockedOther => { col.update_one( diff --git a/src/routes/users/fetch_relationship.rs b/src/routes/users/fetch_relationship.rs index b4ebd16..2f2b171 100644 --- a/src/routes/users/fetch_relationship.rs +++ b/src/routes/users/fetch_relationship.rs @@ -5,5 +5,5 @@ use rocket_contrib::json::JsonValue; #[get("/<target>/relationship")] pub async fn req(user: User, target: Ref) -> Result<JsonValue> { - Ok(json!({ "status": get_relationship(&user, &target) })) + Ok(json!({ "status": get_relationship(&user, &target.id) })) } diff --git a/src/routes/users/fetch_user.rs b/src/routes/users/fetch_user.rs index 9f26713..21f4ceb 100644 --- a/src/routes/users/fetch_user.rs +++ b/src/routes/users/fetch_user.rs @@ -9,7 +9,7 @@ pub async fn req(user: User, target: Ref) -> Result<JsonValue> { if user.id != target.id { // Check whether we are allowed to fetch this user. - let perm = crate::database::permissions::temp_calc_perm(&user, &target).await; + let perm = permissions::user::calculate(&user, &target.id).await; if !perm.get_access() { Err(Error::LabelMe)? } diff --git a/src/routes/users/remove_friend.rs b/src/routes/users/remove_friend.rs index 8c14968..9054c97 100644 --- a/src/routes/users/remove_friend.rs +++ b/src/routes/users/remove_friend.rs @@ -11,7 +11,7 @@ use rocket_contrib::json::JsonValue; pub async fn req(user: User, target: Ref) -> Result<JsonValue> { let col = get_collection("users"); - match get_relationship(&user, &target) { + match get_relationship(&user, &target.id) { RelationshipStatus::Friend | RelationshipStatus::Outgoing | RelationshipStatus::Incoming => { diff --git a/src/routes/users/unblock_user.rs b/src/routes/users/unblock_user.rs index 583ee2c..1c4aaba 100644 --- a/src/routes/users/unblock_user.rs +++ b/src/routes/users/unblock_user.rs @@ -11,9 +11,9 @@ use rocket_contrib::json::JsonValue; pub async fn req(user: User, target: Ref) -> Result<JsonValue> { let col = get_collection("users"); - match get_relationship(&user, &target) { + match get_relationship(&user, &target.id) { RelationshipStatus::Blocked => { - match get_relationship(&target.fetch_user().await?, &user.as_ref()) { + match get_relationship(&target.fetch_user().await?, &user.id) { RelationshipStatus::Blocked => { col.update_one( doc! { -- GitLab