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