From 1aafa51033f8c67abeaf3747f50cf87d3732ec36 Mon Sep 17 00:00:00 2001 From: Paul Makles Date: Fri, 4 Feb 2022 13:38:24 +0000 Subject: [PATCH] feat(users): implement relationships, DMs, proper perms --- Cargo.lock | 67 ++++++++++++++++--------------- src/routes/users/add_friend.rs | 14 ++++--- src/routes/users/block_user.rs | 15 ++++--- src/routes/users/edit_user.rs | 4 +- src/routes/users/fetch_dms.rs | 12 ++++-- src/routes/users/fetch_profile.rs | 20 ++++++--- src/routes/users/fetch_self.rs | 2 +- src/routes/users/fetch_user.rs | 7 ++-- src/routes/users/find_mutual.rs | 23 ++++++++--- src/routes/users/remove_friend.rs | 15 ++++--- src/routes/users/unblock_user.rs | 15 ++++--- 11 files changed, 117 insertions(+), 77 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6e0f7882..40bc6452 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1001,9 +1001,9 @@ checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7" [[package]] name = "futures" -version = "0.3.17" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a12aa0eb539080d55c3f2d45a67c3b58b6b0773c1a3ca2dfec66d58c97fd66ca" +checksum = "28560757fe2bb34e79f907794bb6b22ae8b0e5c669b638a1132f2592b19035b4" dependencies = [ "futures-channel", "futures-core", @@ -1016,9 +1016,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.17" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5da6ba8c3bb3c165d3c7319fc1cc8304facf1fb8db99c5de877183c08a273888" +checksum = "ba3dda0b6588335f360afc675d0564c17a77a2bda81ca178a4b6081bd86c7f0b" dependencies = [ "futures-core", "futures-sink", @@ -1026,15 +1026,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.17" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d1c26957f23603395cd326b0ffe64124b818f4449552f960d815cfba83a53d" +checksum = "d0c8ff0461b82559810cdccfde3215c3f373807f5e5232b71479bff7bb2583d7" [[package]] name = "futures-executor" -version = "0.3.17" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45025be030969d763025784f7f355043dc6bc74093e4ecc5000ca4dc50d8745c" +checksum = "29d6d2ff5bb10fb95c85b8ce46538a2e5f5e7fdc755623a7d4529ab8a4ed9d2a" dependencies = [ "futures-core", "futures-task", @@ -1043,9 +1043,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.17" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "522de2a0fe3e380f1bc577ba0474108faf3f6b18321dbf60b3b9c39a75073377" +checksum = "b1f9d34af5a1aac6fb380f735fe510746c38067c5bf16c7fd250280503c971b2" [[package]] name = "futures-lite" @@ -1064,12 +1064,10 @@ dependencies = [ [[package]] name = "futures-macro" -version = "0.3.17" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18e4a4b95cea4b4ccbcf1c5675ca7c4ee4e9e75eb79944d07defde18068f79bb" +checksum = "6dbd947adfffb0efc70599b3ddcf7b5597bb5fa9e245eb99f62b3a5f7bb8bd3c" dependencies = [ - "autocfg 1.0.1", - "proc-macro-hack", "proc-macro2", "quote 1.0.9", "syn 1.0.76", @@ -1077,15 +1075,15 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.17" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36ea153c13024fe480590b3e3d4cad89a0cfacecc24577b68f86c6ced9c2bc11" +checksum = "e3055baccb68d74ff6480350f8d6eb8fcfa3aa11bdc1a1ae3afdd0514617d508" [[package]] name = "futures-task" -version = "0.3.17" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d3d00f4eddb73e498a54394f228cd55853bdf059259e8e7bc6e69d408892e99" +checksum = "6ee7c6485c30167ce4dfb83ac568a849fe53274c831081476ee13e0dce1aad72" [[package]] name = "futures-timer" @@ -1095,11 +1093,10 @@ checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" [[package]] name = "futures-util" -version = "0.3.17" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36568465210a3a6ee45e1f165136d68671471a501e632e9a98d96872222b5481" +checksum = "d9b5cf40b47a271f77a8b1bec03ca09044d99d2372c0de244e66430761127164" dependencies = [ - "autocfg 1.0.1", "futures-channel", "futures-core", "futures-io", @@ -1109,8 +1106,6 @@ dependencies = [ "memchr", "pin-project-lite 0.2.7", "pin-utils", - "proc-macro-hack", - "proc-macro-nested", "slab", ] @@ -1291,7 +1286,7 @@ dependencies = [ "redis 0.21.2", "serde", "serde_json", - "ulid", + "ulid 0.4.1", ] [[package]] @@ -2417,12 +2412,6 @@ version = "0.5.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" -[[package]] -name = "proc-macro-nested" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086" - [[package]] name = "proc-macro2" version = "1.0.29" @@ -2746,7 +2735,7 @@ dependencies = [ "serde", "serde_json", "totp-lite", - "ulid", + "ulid 0.4.1", "validator", "wither", ] @@ -2941,7 +2930,7 @@ dependencies = [ "rocket_cors", "serde", "serde_json", - "ulid", + "ulid 0.4.1", "url", "validator", "web-push", @@ -2954,6 +2943,7 @@ dependencies = [ "async-std", "async-trait", "bitfield", + "futures", "impl_ops", "lazy_static", "log", @@ -2964,6 +2954,7 @@ dependencies = [ "rauth", "rocket", "serde", + "ulid 0.5.0", "validator", ] @@ -4088,6 +4079,16 @@ dependencies = [ "rand 0.6.5", ] +[[package]] +name = "ulid" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "220b18413e1fe5e85a5580b22f44241f82404a66c792c9f3c9eda74c52d9a22e" +dependencies = [ + "chrono", + "rand 0.8.4", +] + [[package]] name = "uncased" version = "0.9.6" @@ -4499,7 +4500,7 @@ dependencies = [ "mongodb 1.2.3", "serde", "thiserror", - "ulid", + "ulid 0.4.1", "wither_derive", ] diff --git a/src/routes/users/add_friend.rs b/src/routes/users/add_friend.rs index b0d4a057..02d4a77a 100644 --- a/src/routes/users/add_friend.rs +++ b/src/routes/users/add_friend.rs @@ -1,11 +1,13 @@ -use revolt_quark::{Error, Result}; +use revolt_quark::models::User; +use revolt_quark::{Result, Database}; -use futures::try_join; use mongodb::bson::doc; -use mongodb::options::{Collation, FindOneOptions}; -use rocket::serde::json::Value; +use rocket::State; +use rocket::serde::json::Json; #[put("//friend")] -pub async fn req(/*user: UserRef,*/ username: String) -> Result { - todo!() +pub async fn req(db: &State, user: User, username: String) -> Result> { + let mut target = db.fetch_user_by_username(&username).await?; + user.add_friend(db, &mut target).await?; + Ok(Json(target.with_auto_perspective(db, &user).await)) } diff --git a/src/routes/users/block_user.rs b/src/routes/users/block_user.rs index f3b8f3a7..cf624cd5 100644 --- a/src/routes/users/block_user.rs +++ b/src/routes/users/block_user.rs @@ -1,10 +1,13 @@ -use revolt_quark::{Error, Result}; +use revolt_quark::models::User; +use revolt_quark::{Result, Database}; -use futures::try_join; use mongodb::bson::doc; -use rocket::serde::json::Value; +use rocket::State; +use rocket::serde::json::Json; -#[put("//block")] -pub async fn req(/*user: UserRef, target: Ref*/ target: String) -> Result { - todo!() +#[put("//block")] +pub async fn req(db: &State, user: User, username: String) -> Result> { + let mut target = db.fetch_user_by_username(&username).await?; + user.block_user(db, &mut target).await?; + Ok(Json(target.with_auto_perspective(db, &user).await)) } diff --git a/src/routes/users/edit_user.rs b/src/routes/users/edit_user.rs index 7d0f82f0..492681b5 100644 --- a/src/routes/users/edit_user.rs +++ b/src/routes/users/edit_user.rs @@ -1,3 +1,5 @@ +//! Edit currently authenticated user. + use revolt_quark::models::File; use revolt_quark::{Error, Result, Database}; use revolt_quark::models::user::{FieldsUser, User, PartialUser}; @@ -96,5 +98,5 @@ pub async fn req(db: &State, mut user: User, data: Json) -> Resu } db.update_user(&user.id, &partial, data.remove.unwrap_or_default()).await?; - Ok(Json(user)) + Ok(Json(user.foreign())) } diff --git a/src/routes/users/fetch_dms.rs b/src/routes/users/fetch_dms.rs index c9f202c4..dce5f83a 100644 --- a/src/routes/users/fetch_dms.rs +++ b/src/routes/users/fetch_dms.rs @@ -1,9 +1,13 @@ -use revolt_quark::{Error, Result}; +//! Fetch direct messages that the current user is involved in +//! +//! This includes group DMs and "active" 1:1 DMs. + +use revolt_quark::{Result, models::{Channel, User}, Database}; use mongodb::bson::doc; -use rocket::serde::json::Value; +use rocket::{serde::json::Json, State}; #[get("/dms")] -pub async fn req(/*user: UserRef*/) -> Result { - todo!() +pub async fn req(db: &State, user: User) -> Result>> { + db.find_direct_messages(&user.id).await.map(Json) } diff --git a/src/routes/users/fetch_profile.rs b/src/routes/users/fetch_profile.rs index be7aab19..aa25d293 100644 --- a/src/routes/users/fetch_profile.rs +++ b/src/routes/users/fetch_profile.rs @@ -1,9 +1,19 @@ -use revolt_quark::{Error, Result}; +//! Fetch another user's profile +//! +//! Will fail if the authenticated user does not +//! have permission to access the other user's profile. -use mongodb::bson::doc; -use rocket::serde::json::Value; +use revolt_quark::{Ref, Result, Error, models::{User, user::UserProfile}, perms, Database}; + +use rocket::{serde::json::Json, State}; #[get("//profile")] -pub async fn req(/*user: UserRef, target: Ref*/ target: String) -> Result { - todo!() +pub async fn req(db: &State, user: User, target: Ref) -> Result> { + let target = target.as_user(db).await?; + + if perms(&user).user(&target).calc_user(db).await.get_view_profile() { + Ok(Json(target.profile.unwrap_or_default())) + } else { + Err(Error::NotFound) + } } diff --git a/src/routes/users/fetch_self.rs b/src/routes/users/fetch_self.rs index 89831878..c683ffaa 100755 --- a/src/routes/users/fetch_self.rs +++ b/src/routes/users/fetch_self.rs @@ -7,5 +7,5 @@ use rocket::serde::json::Json; #[get("/@me")] pub async fn req(user: User) -> Result> { - Ok(Json(user)) + Ok(Json(user.foreign())) } diff --git a/src/routes/users/fetch_user.rs b/src/routes/users/fetch_user.rs index d3684235..2422dd01 100644 --- a/src/routes/users/fetch_user.rs +++ b/src/routes/users/fetch_user.rs @@ -10,9 +10,10 @@ use rocket::{serde::json::Json, State}; #[get("/")] pub async fn req(db: &State, user: User, target: Ref) -> Result> { let target = target.as_user(db).await?; - - if perms(&user).user(&target).calc_user(db).await.get_access() { - Ok(Json(target)) + + let permissions = perms(&user).user(&target).calc_user(db).await; + if permissions.get_access() { + Ok(Json(target.with_perspective(&user, &permissions))) } else { Err(Error::NotFound) } diff --git a/src/routes/users/find_mutual.rs b/src/routes/users/find_mutual.rs index 0a89d197..654b0345 100644 --- a/src/routes/users/find_mutual.rs +++ b/src/routes/users/find_mutual.rs @@ -1,11 +1,22 @@ -use revolt_quark::{Error, Result}; +//! Fetch IDs of servers and friends that are mutually shared between the +//! authenticated user and the target user -use futures::StreamExt; -use mongodb::bson::{doc, Document}; -use mongodb::options::FindOptions; +use revolt_quark::models::User; +use revolt_quark::{Error, Result, perms, Database, Ref}; + +use rocket::State; use rocket::serde::json::Value; #[get("//mutual")] -pub async fn req(/*user: UserRef, target: Ref*/ target: String) -> Result { - todo!() +pub async fn req(db: &State, user: User, target: Ref) -> Result { + let target = target.as_user(db).await?; + + if perms(&user).user(&target).calc_user(db).await.get_view_profile() { + Ok(json!({ + "users": db.fetch_mutual_user_ids(&user.id, &target.id).await?, + "servers": db.fetch_mutual_server_ids(&user.id, &target.id).await? + })) + } else { + Err(Error::NotFound) + } } diff --git a/src/routes/users/remove_friend.rs b/src/routes/users/remove_friend.rs index 7fbcf2c8..f7650511 100644 --- a/src/routes/users/remove_friend.rs +++ b/src/routes/users/remove_friend.rs @@ -1,10 +1,13 @@ -use revolt_quark::{Error, Result}; +use revolt_quark::models::User; +use revolt_quark::{Result, Database}; -use futures::try_join; use mongodb::bson::doc; -use rocket::serde::json::Value; +use rocket::State; +use rocket::serde::json::Json; -#[delete("//friend")] -pub async fn req(/*user: UserRef, target: Ref*/ target: String) -> Result { - todo!() +#[delete("//friend")] +pub async fn req(db: &State, user: User, username: String) -> Result> { + let mut target = db.fetch_user_by_username(&username).await?; + user.remove_friend(db, &mut target).await?; + Ok(Json(target.with_auto_perspective(db, &user).await)) } diff --git a/src/routes/users/unblock_user.rs b/src/routes/users/unblock_user.rs index fc04c01d..704ccf1f 100644 --- a/src/routes/users/unblock_user.rs +++ b/src/routes/users/unblock_user.rs @@ -1,10 +1,13 @@ -use revolt_quark::{Error, Result}; +use revolt_quark::models::User; +use revolt_quark::{Result, Database}; -use futures::try_join; use mongodb::bson::doc; -use rocket::serde::json::Value; +use rocket::State; +use rocket::serde::json::Json; -#[delete("//block")] -pub async fn req(/*user: UserRef, target: Ref*/ target: String) -> Result { - todo!() +#[delete("//block")] +pub async fn req(db: &State, user: User, username: String) -> Result> { + let mut target = db.fetch_user_by_username(&username).await?; + user.unblock_user(db, &mut target).await?; + Ok(Json(target.with_auto_perspective(db, &user).await)) }