Write proper user permission code.
This commit is contained in:
@@ -19,7 +19,6 @@ hive_pubsub = { version = "0.4.3", features = ["mongo"] }
|
|||||||
rocket_cors = { git = "https://github.com/lawliet89/rocket_cors", branch = "master" }
|
rocket_cors = { git = "https://github.com/lawliet89/rocket_cors", branch = "master" }
|
||||||
rocket_contrib = { git = "https://github.com/SergioBenitez/Rocket", branch = "master" }
|
rocket_contrib = { git = "https://github.com/SergioBenitez/Rocket", branch = "master" }
|
||||||
rocket = { git = "https://github.com/SergioBenitez/Rocket", branch = "master", default-features = false }
|
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 }
|
mongodb = { version = "1.1.1", features = ["tokio-runtime"], default-features = false }
|
||||||
|
|
||||||
once_cell = "1.4.1"
|
once_cell = "1.4.1"
|
||||||
|
|||||||
@@ -1,46 +1,3 @@
|
|||||||
use crate::database::*;
|
pub mod user;
|
||||||
use num_enum::TryFromPrimitive;
|
|
||||||
use std::ops;
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, TryFromPrimitive, Copy, Clone)]
|
pub use user::get_relationship;
|
||||||
#[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
|
|
||||||
}
|
|
||||||
|
|||||||
50
src/database/permissions/user.rs
Normal file
50
src/database/permissions/user.rs
Normal file
@@ -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
|
||||||
|
}
|
||||||
@@ -33,9 +33,7 @@ pub async fn req(user: User, username: String) -> Result<JsonValue> {
|
|||||||
|
|
||||||
match get_relationship(
|
match get_relationship(
|
||||||
&user,
|
&user,
|
||||||
&Ref {
|
&target_id,
|
||||||
id: target_id.to_string(),
|
|
||||||
},
|
|
||||||
) {
|
) {
|
||||||
RelationshipStatus::User => return Err(Error::NoEffect),
|
RelationshipStatus::User => return Err(Error::NoEffect),
|
||||||
RelationshipStatus::Friend => return Err(Error::AlreadyFriends),
|
RelationshipStatus::Friend => return Err(Error::AlreadyFriends),
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ use rocket_contrib::json::JsonValue;
|
|||||||
pub async fn req(user: User, target: Ref) -> Result<JsonValue> {
|
pub async fn req(user: User, target: Ref) -> Result<JsonValue> {
|
||||||
let col = get_collection("users");
|
let col = get_collection("users");
|
||||||
|
|
||||||
match get_relationship(&user, &target) {
|
match get_relationship(&user, &target.id) {
|
||||||
RelationshipStatus::User | RelationshipStatus::Blocked => Err(Error::NoEffect),
|
RelationshipStatus::User | RelationshipStatus::Blocked => Err(Error::NoEffect),
|
||||||
RelationshipStatus::BlockedOther => {
|
RelationshipStatus::BlockedOther => {
|
||||||
col.update_one(
|
col.update_one(
|
||||||
|
|||||||
@@ -5,5 +5,5 @@ use rocket_contrib::json::JsonValue;
|
|||||||
|
|
||||||
#[get("/<target>/relationship")]
|
#[get("/<target>/relationship")]
|
||||||
pub async fn req(user: User, target: Ref) -> Result<JsonValue> {
|
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) }))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ pub async fn req(user: User, target: Ref) -> Result<JsonValue> {
|
|||||||
|
|
||||||
if user.id != target.id {
|
if user.id != target.id {
|
||||||
// Check whether we are allowed to fetch this user.
|
// 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() {
|
if !perm.get_access() {
|
||||||
Err(Error::LabelMe)?
|
Err(Error::LabelMe)?
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ use rocket_contrib::json::JsonValue;
|
|||||||
pub async fn req(user: User, target: Ref) -> Result<JsonValue> {
|
pub async fn req(user: User, target: Ref) -> Result<JsonValue> {
|
||||||
let col = get_collection("users");
|
let col = get_collection("users");
|
||||||
|
|
||||||
match get_relationship(&user, &target) {
|
match get_relationship(&user, &target.id) {
|
||||||
RelationshipStatus::Friend
|
RelationshipStatus::Friend
|
||||||
| RelationshipStatus::Outgoing
|
| RelationshipStatus::Outgoing
|
||||||
| RelationshipStatus::Incoming => {
|
| RelationshipStatus::Incoming => {
|
||||||
|
|||||||
@@ -11,9 +11,9 @@ use rocket_contrib::json::JsonValue;
|
|||||||
pub async fn req(user: User, target: Ref) -> Result<JsonValue> {
|
pub async fn req(user: User, target: Ref) -> Result<JsonValue> {
|
||||||
let col = get_collection("users");
|
let col = get_collection("users");
|
||||||
|
|
||||||
match get_relationship(&user, &target) {
|
match get_relationship(&user, &target.id) {
|
||||||
RelationshipStatus::Blocked => {
|
RelationshipStatus::Blocked => {
|
||||||
match get_relationship(&target.fetch_user().await?, &user.as_ref()) {
|
match get_relationship(&target.fetch_user().await?, &user.id) {
|
||||||
RelationshipStatus::Blocked => {
|
RelationshipStatus::Blocked => {
|
||||||
col.update_one(
|
col.update_one(
|
||||||
doc! {
|
doc! {
|
||||||
|
|||||||
Reference in New Issue
Block a user