forked from jmug/stoatchat
Re-implement user relationships.
This commit is contained in:
124
Cargo.lock
generated
124
Cargo.lock
generated
@@ -15,12 +15,6 @@ version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e"
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
version = "0.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "739f4a8db6605981345c5654f3a85b056ce52f37a39d34da03f25bf2151ea16e"
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "0.7.15"
|
||||
@@ -245,18 +239,6 @@ version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
|
||||
|
||||
[[package]]
|
||||
name = "bcrypt"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2cab630912253fb9dc92c0e2fabd0a7b51f5a5a4007177cfa31e517015b7204"
|
||||
dependencies = [
|
||||
"base64 0.12.3",
|
||||
"blowfish",
|
||||
"byteorder",
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "binascii"
|
||||
version = "0.1.4"
|
||||
@@ -319,15 +301,6 @@ dependencies = [
|
||||
"generic-array 0.14.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-cipher"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f337a3e6da609650eb74e02bc9fac7b735049f7623ab12f2e4c719316fcc7e80"
|
||||
dependencies = [
|
||||
"generic-array 0.14.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-padding"
|
||||
version = "0.1.5"
|
||||
@@ -351,17 +324,6 @@ dependencies = [
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "blowfish"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0f06850ba969bc59388b2cc0a4f186fc6d9d37208863b15b84ae3866ac90ac06"
|
||||
dependencies = [
|
||||
"block-cipher",
|
||||
"byteorder",
|
||||
"opaque-debug 0.3.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bson"
|
||||
version = "1.1.0"
|
||||
@@ -396,16 +358,6 @@ version = "1.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "0.4.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"iovec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "0.5.6"
|
||||
@@ -985,7 +937,7 @@ version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e4728fd124914ad25e99e3d15a9361a879f6620f63cb56bbb08f95abb97a535"
|
||||
dependencies = [
|
||||
"bytes 0.5.6",
|
||||
"bytes",
|
||||
"fnv",
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
@@ -1004,9 +956,6 @@ name = "hashbrown"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
@@ -1073,7 +1022,7 @@ version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "84129d298a6d57d246960ff8eb831ca4af3f96d29e2e28848dae275408658e26"
|
||||
dependencies = [
|
||||
"bytes 0.5.6",
|
||||
"bytes",
|
||||
"fnv",
|
||||
"itoa",
|
||||
]
|
||||
@@ -1084,7 +1033,7 @@ version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b"
|
||||
dependencies = [
|
||||
"bytes 0.5.6",
|
||||
"bytes",
|
||||
"http",
|
||||
]
|
||||
|
||||
@@ -1115,7 +1064,7 @@ version = "0.13.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6ad767baac13b44d4529fcf58ba2cd0995e36e7b435bc5b039de6f47e880dbf"
|
||||
dependencies = [
|
||||
"bytes 0.5.6",
|
||||
"bytes",
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
@@ -1139,7 +1088,7 @@ version = "0.21.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37743cc83e8ee85eacfce90f2f4102030d9ff0a95244098d781e9bee4a90abb6"
|
||||
dependencies = [
|
||||
"bytes 0.5.6",
|
||||
"bytes",
|
||||
"futures-util",
|
||||
"hyper",
|
||||
"log",
|
||||
@@ -1155,7 +1104,7 @@ version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d979acc56dcb5b8dddba3917601745e877576475aa046df3226eabdecef78eed"
|
||||
dependencies = [
|
||||
"bytes 0.5.6",
|
||||
"bytes",
|
||||
"hyper",
|
||||
"native-tls",
|
||||
"tokio",
|
||||
@@ -1169,7 +1118,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2adce67e2c21cd95288ae3d9f2bbb2762cf17c03744628d49679f315ed1e2e58"
|
||||
dependencies = [
|
||||
"base64 0.13.0",
|
||||
"bytes 0.5.6",
|
||||
"bytes",
|
||||
"http",
|
||||
"httparse",
|
||||
"httpdate",
|
||||
@@ -1231,7 +1180,7 @@ version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19a8a95243d5a0398cae618ec29477c6e3cb631152be5c19481f80bc71559754"
|
||||
dependencies = [
|
||||
"bytes 0.5.6",
|
||||
"bytes",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1322,12 +1271,6 @@ version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "lazycell"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
||||
|
||||
[[package]]
|
||||
name = "lettre"
|
||||
version = "0.10.0-alpha.4"
|
||||
@@ -1390,15 +1333,6 @@ dependencies = [
|
||||
"cfg-if 0.1.10",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lru"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3aae342b73d57ad0b8b364bd12584819f2c1fe9114285dfcf8b0722607671635"
|
||||
dependencies = [
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lru-cache"
|
||||
version = "0.1.2"
|
||||
@@ -1488,18 +1422,6 @@ dependencies = [
|
||||
"winapi 0.2.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mio-extras"
|
||||
version = "2.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19"
|
||||
dependencies = [
|
||||
"lazycell",
|
||||
"log",
|
||||
"mio",
|
||||
"slab",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mio-uds"
|
||||
version = "0.6.8"
|
||||
@@ -2295,7 +2217,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0718f81a8e14c4dbb3b34cf23dc6aaf9ab8a0dfec160c534b3dbca1aaa21f47c"
|
||||
dependencies = [
|
||||
"base64 0.13.0",
|
||||
"bytes 0.5.6",
|
||||
"bytes",
|
||||
"encoding_rs",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
@@ -2344,7 +2266,6 @@ version = "0.3.0-alpha"
|
||||
dependencies = [
|
||||
"async-std",
|
||||
"async-tungstenite",
|
||||
"bcrypt",
|
||||
"bitfield",
|
||||
"chrono",
|
||||
"ctrlc",
|
||||
@@ -2356,13 +2277,13 @@ dependencies = [
|
||||
"lazy_static",
|
||||
"lettre",
|
||||
"log",
|
||||
"lru",
|
||||
"many-to-many",
|
||||
"mongodb",
|
||||
"num_enum",
|
||||
"once_cell",
|
||||
"rand 0.7.3",
|
||||
"rauth",
|
||||
"regex",
|
||||
"reqwest",
|
||||
"rocket",
|
||||
"rocket_contrib",
|
||||
@@ -2373,7 +2294,6 @@ dependencies = [
|
||||
"time 0.2.23",
|
||||
"ulid",
|
||||
"validator",
|
||||
"ws",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3060,7 +2980,7 @@ version = "0.2.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "099837d3464c16a808060bb3f02263b412f6fafcb5d01c533d309985fbeebe48"
|
||||
dependencies = [
|
||||
"bytes 0.5.6",
|
||||
"bytes",
|
||||
"fnv",
|
||||
"futures-core",
|
||||
"iovec",
|
||||
@@ -3128,7 +3048,7 @@ version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499"
|
||||
dependencies = [
|
||||
"bytes 0.5.6",
|
||||
"bytes",
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
"log",
|
||||
@@ -3236,7 +3156,7 @@ checksum = "f0308d80d86700c5878b9ef6321f020f29b1bb9d5ff3cab25e75e23f3a492a23"
|
||||
dependencies = [
|
||||
"base64 0.12.3",
|
||||
"byteorder",
|
||||
"bytes 0.5.6",
|
||||
"bytes",
|
||||
"http",
|
||||
"httparse",
|
||||
"input_buffer",
|
||||
@@ -3648,24 +3568,6 @@ dependencies = [
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ws"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c51a2c47b5798ccc774ffb93ff536aec7c4275d722fd9c740c83cdd1af1f2d94"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"bytes 0.4.12",
|
||||
"httparse",
|
||||
"log",
|
||||
"mio",
|
||||
"mio-extras",
|
||||
"rand 0.7.3",
|
||||
"sha-1 0.8.2",
|
||||
"slab",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ws2_32-sys"
|
||||
version = "0.2.1"
|
||||
|
||||
@@ -35,11 +35,9 @@ reqwest = { version = "0.10.8", features = ["json"] }
|
||||
lazy_static = "1.4.0"
|
||||
num_enum = "0.5.1"
|
||||
chrono = "0.4.15"
|
||||
bcrypt = "0.8.2"
|
||||
time = "0.2.16"
|
||||
rand = "0.7.3"
|
||||
lru = "0.6.0"
|
||||
ws = "0.9.1"
|
||||
regex = "1"
|
||||
|
||||
lettre = "0.10.0-alpha.1"
|
||||
env_logger = "0.7.1"
|
||||
|
||||
@@ -2,14 +2,26 @@ use mongodb::bson::{doc, from_bson, Bson};
|
||||
use rauth::auth::Session;
|
||||
use rocket::http::Status;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use crate::database::guards::reference::Ref;
|
||||
use crate::database::get_collection;
|
||||
use rocket::request::{self, FromRequest, Outcome, Request};
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub enum RelationshipStatus {
|
||||
None,
|
||||
User,
|
||||
Friend,
|
||||
Outgoing,
|
||||
Incoming,
|
||||
Blocked,
|
||||
BlockedOther
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct Relationship {
|
||||
#[serde(rename = "_id")]
|
||||
pub id: String,
|
||||
pub status: u8,
|
||||
pub status: RelationshipStatus,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
@@ -47,3 +59,9 @@ impl<'a, 'r> FromRequest<'a, 'r> for User {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl User {
|
||||
pub fn as_ref(&self) -> Ref {
|
||||
Ref { id: self.id.to_string() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,11 +18,11 @@ impl Ref {
|
||||
Ok(Ref { id })
|
||||
}
|
||||
|
||||
pub async fn fetch_user(self) -> Result<User> {
|
||||
pub async fn fetch_user(&self) -> Result<User> {
|
||||
let doc = get_collection("users")
|
||||
.find_one(
|
||||
doc! {
|
||||
"_id": self.id
|
||||
"_id": &self.id
|
||||
},
|
||||
None
|
||||
)
|
||||
|
||||
@@ -30,3 +30,22 @@ pub async fn temp_calc_perm(_user: &User, _target: &User) -> UserPermissions<[u3
|
||||
|
||||
UserPermissions([UserPermission::Access + UserPermission::SendMessage + UserPermission::Invite])
|
||||
}
|
||||
|
||||
use crate::database::entities::RelationshipStatus;
|
||||
use crate::database::guards::reference::Ref;
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
@@ -7,10 +7,15 @@ use rocket_contrib::json::Json;
|
||||
use rauth::auth::Session;
|
||||
use validator::Validate;
|
||||
use mongodb::bson::doc;
|
||||
use regex::Regex;
|
||||
|
||||
lazy_static! {
|
||||
static ref RE_USERNAME: Regex = Regex::new(r"^[a-zA-Z0-9-_]+$").unwrap();
|
||||
}
|
||||
|
||||
#[derive(Validate, Serialize, Deserialize)]
|
||||
pub struct Data {
|
||||
#[validate(length(min = 2, max = 32))]
|
||||
#[validate(length(min = 2, max = 32), regex = "RE_USERNAME")]
|
||||
username: String
|
||||
}
|
||||
|
||||
|
||||
84
src/routes/users/add_friend.rs
Normal file
84
src/routes/users/add_friend.rs
Normal file
@@ -0,0 +1,84 @@
|
||||
use crate::{database::{entities::{User, RelationshipStatus}, get_collection, guards::reference::Ref, permissions::get_relationship}, util::result::Error};
|
||||
use rocket_contrib::json::JsonValue;
|
||||
use crate::util::result::Result;
|
||||
use mongodb::bson::doc;
|
||||
use futures::try_join;
|
||||
|
||||
#[put("/<target>/friend")]
|
||||
pub async fn req(user: User, target: Ref) -> Result<JsonValue> {
|
||||
let col = get_collection("users");
|
||||
|
||||
match get_relationship(&user, &target) {
|
||||
RelationshipStatus::User => return Err(Error::NoEffect),
|
||||
RelationshipStatus::Friend => return Err(Error::AlreadyFriends),
|
||||
RelationshipStatus::Outgoing => return Err(Error::AlreadySentRequest),
|
||||
RelationshipStatus::Blocked => return Err(Error::Blocked),
|
||||
RelationshipStatus::BlockedOther => return Err(Error::BlockedByOther),
|
||||
RelationshipStatus::Incoming => {
|
||||
match try_join!(
|
||||
col.update_one(
|
||||
doc! {
|
||||
"_id": &user.id,
|
||||
"relations._id": &target.id
|
||||
},
|
||||
doc! {
|
||||
"$set": {
|
||||
"relations.$.status": "Friend"
|
||||
}
|
||||
},
|
||||
None
|
||||
),
|
||||
col.update_one(
|
||||
doc! {
|
||||
"_id": &target.id,
|
||||
"relations._id": &user.id
|
||||
},
|
||||
doc! {
|
||||
"$set": {
|
||||
"relations.$.status": "Friend"
|
||||
}
|
||||
},
|
||||
None
|
||||
)
|
||||
) {
|
||||
Ok(_) => Ok(json!({ "status": "Friend" })),
|
||||
Err(_) => Err(Error::DatabaseError { operation: "update_one", with: "user" })
|
||||
}
|
||||
}
|
||||
RelationshipStatus::None => {
|
||||
match try_join!(
|
||||
col.update_one(
|
||||
doc! {
|
||||
"_id": &user.id
|
||||
},
|
||||
doc! {
|
||||
"$push": {
|
||||
"relations": {
|
||||
"_id": &target.id,
|
||||
"status": "Outgoing"
|
||||
}
|
||||
}
|
||||
},
|
||||
None
|
||||
),
|
||||
col.update_one(
|
||||
doc! {
|
||||
"_id": &target.id
|
||||
},
|
||||
doc! {
|
||||
"$push": {
|
||||
"relations": {
|
||||
"_id": &user.id,
|
||||
"status": "Incoming"
|
||||
}
|
||||
}
|
||||
},
|
||||
None
|
||||
)
|
||||
) {
|
||||
Ok(_) => Ok(json!({ "status": "Outgoing" })),
|
||||
Err(_) => Err(Error::DatabaseError { operation: "update_one", with: "user" })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
101
src/routes/users/block_user.rs
Normal file
101
src/routes/users/block_user.rs
Normal file
@@ -0,0 +1,101 @@
|
||||
use crate::{database::entities::RelationshipStatus, database::guards::reference::Ref, database::entities::User, database::permissions::get_relationship, util::result::Error, database::get_collection};
|
||||
use rocket_contrib::json::JsonValue;
|
||||
use crate::util::result::Result;
|
||||
use mongodb::bson::doc;
|
||||
use futures::try_join;
|
||||
|
||||
#[put("/<target>/block")]
|
||||
pub async fn req(user: User, target: Ref) -> Result<JsonValue> {
|
||||
let col = get_collection("users");
|
||||
|
||||
match get_relationship(&user, &target) {
|
||||
RelationshipStatus::User |
|
||||
RelationshipStatus::Blocked => Err(Error::NoEffect),
|
||||
RelationshipStatus::BlockedOther => {
|
||||
col.update_one(
|
||||
doc! {
|
||||
"_id": &user.id,
|
||||
"relations._id": &target.id
|
||||
},
|
||||
doc! {
|
||||
"$set": {
|
||||
"relations.$.status": "Blocked"
|
||||
}
|
||||
},
|
||||
None
|
||||
)
|
||||
.await
|
||||
.map_err(|_| Error::DatabaseError { operation: "update_one", with: "user" })?;
|
||||
|
||||
Ok(json!({ "status": "Blocked" }))
|
||||
},
|
||||
RelationshipStatus::None => {
|
||||
match try_join!(
|
||||
col.update_one(
|
||||
doc! {
|
||||
"_id": &user.id
|
||||
},
|
||||
doc! {
|
||||
"$push": {
|
||||
"relations": {
|
||||
"_id": &target.id,
|
||||
"status": "Blocked"
|
||||
}
|
||||
}
|
||||
},
|
||||
None
|
||||
),
|
||||
col.update_one(
|
||||
doc! {
|
||||
"_id": &target.id
|
||||
},
|
||||
doc! {
|
||||
"$push": {
|
||||
"relations": {
|
||||
"_id": &user.id,
|
||||
"status": "BlockedOther"
|
||||
}
|
||||
}
|
||||
},
|
||||
None
|
||||
)
|
||||
) {
|
||||
Ok(_) => Ok(json!({ "status": "Blocked" })),
|
||||
Err(_) => Err(Error::DatabaseError { operation: "update_one", with: "user" })
|
||||
}
|
||||
},
|
||||
RelationshipStatus::Friend |
|
||||
RelationshipStatus::Incoming |
|
||||
RelationshipStatus::Outgoing => {
|
||||
match try_join!(
|
||||
col.update_one(
|
||||
doc! {
|
||||
"_id": &user.id,
|
||||
"relations._id": &target.id
|
||||
},
|
||||
doc! {
|
||||
"$set": {
|
||||
"relations.$.status": "Blocked"
|
||||
}
|
||||
},
|
||||
None
|
||||
),
|
||||
col.update_one(
|
||||
doc! {
|
||||
"_id": &target.id,
|
||||
"relations._id": &user.id
|
||||
},
|
||||
doc! {
|
||||
"$set": {
|
||||
"relations.$.status": "BlockedOther"
|
||||
}
|
||||
},
|
||||
None
|
||||
)
|
||||
) {
|
||||
Ok(_) => Ok(json!({ "status": "Blocked" })),
|
||||
Err(_) => Err(Error::DatabaseError { operation: "update_one", with: "user" })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
10
src/routes/users/fetch_relationship.rs
Normal file
10
src/routes/users/fetch_relationship.rs
Normal file
@@ -0,0 +1,10 @@
|
||||
use crate::database::{entities::User, guards::reference::Ref, permissions::get_relationship};
|
||||
use rocket_contrib::json::JsonValue;
|
||||
use crate::util::result::Result;
|
||||
|
||||
#[get("/<target>/relationship")]
|
||||
pub async fn req(user: User, target: Ref) -> Result<JsonValue> {
|
||||
Ok(json!({
|
||||
"status": get_relationship(&user, &target)
|
||||
}))
|
||||
}
|
||||
14
src/routes/users/fetch_relationships.rs
Normal file
14
src/routes/users/fetch_relationships.rs
Normal file
@@ -0,0 +1,14 @@
|
||||
use crate::database::entities::User;
|
||||
use rocket_contrib::json::JsonValue;
|
||||
use crate::util::result::Result;
|
||||
|
||||
#[get("/relationships")]
|
||||
pub async fn req(user: User) -> Result<JsonValue> {
|
||||
Ok(
|
||||
if let Some(vec) = user.relations {
|
||||
json!(vec)
|
||||
} else {
|
||||
json!([])
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -3,11 +3,28 @@ use rocket::Route;
|
||||
mod fetch_user;
|
||||
mod fetch_dms;
|
||||
mod open_dm;
|
||||
mod fetch_relationships;
|
||||
mod fetch_relationship;
|
||||
mod add_friend;
|
||||
mod remove_friend;
|
||||
mod block_user;
|
||||
mod unblock_user;
|
||||
|
||||
pub fn routes() -> Vec<Route> {
|
||||
routes! [
|
||||
// User Information
|
||||
fetch_user::req,
|
||||
|
||||
// Direct Messaging
|
||||
fetch_dms::req,
|
||||
open_dm::req,
|
||||
|
||||
// Relationships
|
||||
fetch_relationships::req,
|
||||
fetch_relationship::req,
|
||||
add_friend::req,
|
||||
remove_friend::req,
|
||||
block_user::req,
|
||||
unblock_user::req,
|
||||
]
|
||||
}
|
||||
|
||||
52
src/routes/users/remove_friend.rs
Normal file
52
src/routes/users/remove_friend.rs
Normal file
@@ -0,0 +1,52 @@
|
||||
use crate::{database::entities::RelationshipStatus, database::guards::reference::Ref, database::entities::User, database::permissions::get_relationship, util::result::Error, database::get_collection};
|
||||
use rocket_contrib::json::JsonValue;
|
||||
use crate::util::result::Result;
|
||||
use mongodb::bson::doc;
|
||||
use futures::try_join;
|
||||
|
||||
#[delete("/<target>/friend")]
|
||||
pub async fn req(user: User, target: Ref) -> Result<JsonValue> {
|
||||
let col = get_collection("users");
|
||||
|
||||
match get_relationship(&user, &target) {
|
||||
RelationshipStatus::Blocked |
|
||||
RelationshipStatus::BlockedOther |
|
||||
RelationshipStatus::User |
|
||||
RelationshipStatus::None => Err(Error::NoEffect),
|
||||
RelationshipStatus::Friend |
|
||||
RelationshipStatus::Outgoing |
|
||||
RelationshipStatus::Incoming => {
|
||||
match try_join!(
|
||||
col.update_one(
|
||||
doc! {
|
||||
"_id": &user.id
|
||||
},
|
||||
doc! {
|
||||
"$pull": {
|
||||
"relations": {
|
||||
"_id": &target.id
|
||||
}
|
||||
}
|
||||
},
|
||||
None
|
||||
),
|
||||
col.update_one(
|
||||
doc! {
|
||||
"_id": &target.id
|
||||
},
|
||||
doc! {
|
||||
"$pull": {
|
||||
"relations": {
|
||||
"_id": &user.id
|
||||
}
|
||||
}
|
||||
},
|
||||
None
|
||||
)
|
||||
) {
|
||||
Ok(_) => Ok(json!({ "status": "None" })),
|
||||
Err(_) => Err(Error::DatabaseError { operation: "update_one", with: "user" })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
75
src/routes/users/unblock_user.rs
Normal file
75
src/routes/users/unblock_user.rs
Normal file
@@ -0,0 +1,75 @@
|
||||
use crate::{database::entities::RelationshipStatus, database::guards::reference::Ref, database::entities::User, database::permissions::get_relationship, util::result::Error, database::get_collection};
|
||||
use rocket_contrib::json::JsonValue;
|
||||
use crate::util::result::Result;
|
||||
use mongodb::bson::doc;
|
||||
use futures::try_join;
|
||||
|
||||
#[delete("/<target>/block")]
|
||||
pub async fn req(user: User, target: Ref) -> Result<JsonValue> {
|
||||
let col = get_collection("users");
|
||||
|
||||
match get_relationship(&user, &target) {
|
||||
RelationshipStatus::None |
|
||||
RelationshipStatus::User |
|
||||
RelationshipStatus::BlockedOther |
|
||||
RelationshipStatus::Incoming |
|
||||
RelationshipStatus::Outgoing |
|
||||
RelationshipStatus::Friend => Err(Error::NoEffect),
|
||||
RelationshipStatus::Blocked => {
|
||||
match get_relationship(&target.fetch_user().await?, &user.as_ref()) {
|
||||
RelationshipStatus::Blocked => {
|
||||
col.update_one(
|
||||
doc! {
|
||||
"_id": &user.id,
|
||||
"relations._id": &target.id
|
||||
},
|
||||
doc! {
|
||||
"$set": {
|
||||
"relations.$.status": "BlockedOther"
|
||||
}
|
||||
},
|
||||
None
|
||||
)
|
||||
.await
|
||||
.map_err(|_| Error::DatabaseError { operation: "update_one", with: "user" })?;
|
||||
|
||||
Ok(json!({ "status": "BlockedOther" }))
|
||||
},
|
||||
RelationshipStatus::BlockedOther => {
|
||||
match try_join!(
|
||||
col.update_one(
|
||||
doc! {
|
||||
"_id": &user.id
|
||||
},
|
||||
doc! {
|
||||
"$pull": {
|
||||
"relations": {
|
||||
"_id": &target.id
|
||||
}
|
||||
}
|
||||
},
|
||||
None
|
||||
),
|
||||
col.update_one(
|
||||
doc! {
|
||||
"_id": &target.id
|
||||
},
|
||||
doc! {
|
||||
"$pull": {
|
||||
"relations": {
|
||||
"_id": &user.id
|
||||
}
|
||||
}
|
||||
},
|
||||
None
|
||||
)
|
||||
) {
|
||||
Ok(_) => Ok(json!({ "status": "None" })),
|
||||
Err(_) => Err(Error::DatabaseError { operation: "update_one", with: "user" })
|
||||
}
|
||||
},
|
||||
_ => Err(Error::InternalError)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,60 +11,35 @@ use json;
|
||||
#[serde(tag = "type")]
|
||||
pub enum Error {
|
||||
#[snafu(display("This error has not been labelled."))]
|
||||
#[serde(rename = "unlabelled_error")]
|
||||
LabelMe,
|
||||
|
||||
// ? Onboarding related errors.
|
||||
#[snafu(display("Already finished onboarding."))]
|
||||
#[serde(rename = "already_onboarded")]
|
||||
AlreadyOnboarded,
|
||||
|
||||
// ? User related errors.
|
||||
#[snafu(display("Username has already been taken."))]
|
||||
#[serde(rename = "username_taken")]
|
||||
UsernameTaken,
|
||||
#[snafu(display("This user does not exist!"))]
|
||||
#[serde(rename = "unknown_user")]
|
||||
UnknownUser,
|
||||
#[snafu(display("Already friends with this user."))]
|
||||
AlreadyFriends,
|
||||
#[snafu(display("Already sent a request to this user."))]
|
||||
AlreadySentRequest,
|
||||
#[snafu(display("You have blocked this user."))]
|
||||
Blocked,
|
||||
#[snafu(display("You have been blocked by this user."))]
|
||||
BlockedByOther,
|
||||
|
||||
// ? General errors.
|
||||
#[snafu(display("Failed to validate fields."))]
|
||||
#[serde(rename = "failed_validation")]
|
||||
FailedValidation { error: ValidationErrors },
|
||||
#[snafu(display("Encountered a database error."))]
|
||||
#[serde(rename = "database_error")]
|
||||
DatabaseError { operation: &'static str, with: &'static str },
|
||||
|
||||
/* #[snafu(display("Failed to validate fields."))]
|
||||
#[serde(rename = "failed_validation")]
|
||||
FailedValidation { error: ValidationErrors },
|
||||
#[snafu(display("Encountered a database error."))]
|
||||
#[serde(rename = "database_error")]
|
||||
DatabaseError,
|
||||
#[snafu(display("Encountered an internal error."))]
|
||||
#[serde(rename = "internal_error")]
|
||||
#[snafu(display("Internal server error."))]
|
||||
InternalError,
|
||||
#[snafu(display("Operation did not succeed."))]
|
||||
#[serde(rename = "operation_failed")]
|
||||
OperationFailed,
|
||||
#[snafu(display("Missing authentication headers."))]
|
||||
#[serde(rename = "missing_headers")]
|
||||
MissingHeaders,
|
||||
#[snafu(display("Invalid session information."))]
|
||||
#[serde(rename = "invalid_session")]
|
||||
InvalidSession,
|
||||
#[snafu(display("User account has not been verified."))]
|
||||
#[serde(rename = "unverified_account")]
|
||||
UnverifiedAccount,
|
||||
#[snafu(display("This user does not exist!"))]
|
||||
#[serde(rename = "unknown_user")]
|
||||
UnknownUser,
|
||||
#[snafu(display("Email is use."))]
|
||||
#[serde(rename = "email_in_use")]
|
||||
EmailInUse,
|
||||
#[snafu(display("Wrong password."))]
|
||||
#[serde(rename = "wrong_password")]
|
||||
WrongPassword, */
|
||||
#[snafu(display("This request had no effect."))]
|
||||
NoEffect,
|
||||
}
|
||||
|
||||
pub type Result<T, E = Error> = std::result::Result<T, E>;
|
||||
@@ -73,12 +48,21 @@ pub type Result<T, E = Error> = std::result::Result<T, E>;
|
||||
impl<'r> Responder<'r, 'static> for Error {
|
||||
fn respond_to(self, _: &'r Request<'_>) -> response::Result<'static> {
|
||||
let status = match self {
|
||||
Error::AlreadyOnboarded => Status::Forbidden,
|
||||
Error::DatabaseError { .. } => Status::InternalServerError,
|
||||
Error::FailedValidation { .. } => Status::UnprocessableEntity,
|
||||
Error::LabelMe => Status::InternalServerError,
|
||||
|
||||
Error::AlreadyOnboarded => Status::Forbidden,
|
||||
|
||||
Error::UnknownUser => Status::NotFound,
|
||||
Error::UsernameTaken => Status::Conflict,
|
||||
Error::AlreadyFriends => Status::Conflict,
|
||||
Error::AlreadySentRequest => Status::Conflict,
|
||||
Error::Blocked => Status::Conflict,
|
||||
Error::BlockedByOther => Status::Forbidden,
|
||||
|
||||
Error::FailedValidation { .. } => Status::UnprocessableEntity,
|
||||
Error::DatabaseError { .. } => Status::InternalServerError,
|
||||
Error::InternalError => Status::InternalServerError,
|
||||
Error::NoEffect => Status::Ok,
|
||||
};
|
||||
|
||||
// Serialize the error data structure into JSON.
|
||||
|
||||
Reference in New Issue
Block a user