From f39bc07bb952adba2407587106892bc4ff7584eb Mon Sep 17 00:00:00 2001 From: Paul Makles <paulmakles@gmail.com> Date: Wed, 30 Dec 2020 11:36:32 +0000 Subject: [PATCH] Start work on notifications from client, cargo fmt --- src/database/entities/channel.rs | 26 ++++++--- src/database/entities/mod.rs | 4 +- src/database/entities/user.rs | 27 +++++---- src/database/guards/mod.rs | 2 +- src/database/guards/reference.rs | 25 +++++---- src/database/guards/user.rs | 1 + src/database/migrations/init.rs | 54 +++++++++--------- src/database/migrations/scripts.rs | 49 +++++++++-------- src/database/mod.rs | 4 +- src/database/permissions/mod.rs | 6 +- src/main.rs | 13 +++-- src/notifications/events.rs | 7 +-- src/notifications/hive.rs | 6 +- src/notifications/mod.rs | 2 +- src/notifications/websocket.rs | 73 ++++++++++++++++--------- src/routes/channels/mod.rs | 2 +- src/routes/guild/mod.rs | 2 +- src/routes/mod.rs | 6 +- src/routes/onboard/complete.rs | 50 ++++++++++------- src/routes/onboard/hello.rs | 2 +- src/routes/onboard/mod.rs | 7 +-- src/routes/root.rs | 2 +- src/routes/users/add_friend.rs | 24 ++++++-- src/routes/users/block_user.rs | 39 ++++++++----- src/routes/users/fetch_dms.rs | 19 ++++--- src/routes/users/fetch_relationship.rs | 6 +- src/routes/users/fetch_relationships.rs | 14 ++--- src/routes/users/fetch_user.rs | 4 +- src/routes/users/mod.rs | 14 ++--- src/routes/users/open_dm.rs | 19 +++---- src/routes/users/remove_friend.rs | 28 ++++++---- src/routes/users/unblock_user.rs | 41 ++++++++------ src/util/mod.rs | 2 +- src/util/result.rs | 15 +++-- 34 files changed, 336 insertions(+), 259 deletions(-) diff --git a/src/database/entities/channel.rs b/src/database/entities/channel.rs index 37736dc..ad10efc 100644 --- a/src/database/entities/channel.rs +++ b/src/database/entities/channel.rs @@ -1,6 +1,9 @@ -use serde::{Deserialize, Serialize}; -use crate::{database::get_collection, util::result::{Error, Result}}; +use crate::{ + database::get_collection, + util::result::{Error, Result}, +}; use mongodb::bson::to_document; +use serde::{Deserialize, Serialize}; /*#[derive(Serialize, Deserialize, Debug, Clone)] pub struct LastMessage { @@ -38,7 +41,7 @@ pub enum Channel { SavedMessages { #[serde(rename = "_id")] id: String, - user: String + user: String, }, DirectMessage { #[serde(rename = "_id")] @@ -53,20 +56,25 @@ pub enum Channel { owner: String, description: String, recipients: Vec<String>, - } + }, } impl Channel { pub async fn save(&self) -> Result<()> { get_collection("channels") .insert_one( - to_document(&self) - .map_err(|_| Error::DatabaseError { operation: "to_bson", with: "channel" })?, - None + to_document(&self).map_err(|_| Error::DatabaseError { + operation: "to_bson", + with: "channel", + })?, + None, ) .await - .map_err(|_| Error::DatabaseError { operation: "insert_one", with: "channel" })?; - + .map_err(|_| Error::DatabaseError { + operation: "insert_one", + with: "channel", + })?; + Ok(()) } } diff --git a/src/database/entities/mod.rs b/src/database/entities/mod.rs index 02c0f5e..d64512a 100644 --- a/src/database/entities/mod.rs +++ b/src/database/entities/mod.rs @@ -1,9 +1,9 @@ mod channel; -mod message; mod guild; +mod message; mod user; pub use channel::*; -pub use message::*; pub use guild::*; +pub use message::*; pub use user::*; diff --git a/src/database/entities/user.rs b/src/database/entities/user.rs index c6aca1f..1d97b7f 100644 --- a/src/database/entities/user.rs +++ b/src/database/entities/user.rs @@ -1,10 +1,10 @@ +use crate::database::get_collection; +use crate::database::guards::reference::Ref; 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}; +use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug, Clone)] pub enum RelationshipStatus { @@ -14,7 +14,7 @@ pub enum RelationshipStatus { Outgoing, Incoming, Blocked, - BlockedOther + BlockedOther, } #[derive(Serialize, Deserialize, Debug)] @@ -44,24 +44,29 @@ impl<'a, 'r> FromRequest<'a, 'r> for User { .find_one( doc! { "_id": &session.user_id - }, None + }, + None, ) - .await { + .await + { if let Some(doc) = result { - Outcome::Success( - from_bson(Bson::Document(doc)).unwrap() - ) + Outcome::Success(from_bson(Bson::Document(doc)).unwrap()) } else { Outcome::Failure((Status::Forbidden, rauth::util::Error::InvalidSession)) } } else { - Outcome::Failure((Status::InternalServerError, rauth::util::Error::DatabaseError)) + Outcome::Failure(( + Status::InternalServerError, + rauth::util::Error::DatabaseError, + )) } } } impl User { pub fn as_ref(&self) -> Ref { - Ref { id: self.id.to_string() } + Ref { + id: self.id.to_string(), + } } } diff --git a/src/database/guards/mod.rs b/src/database/guards/mod.rs index 728ede5..339d4c8 100644 --- a/src/database/guards/mod.rs +++ b/src/database/guards/mod.rs @@ -1,5 +1,5 @@ -pub mod user; pub mod reference; +pub mod user; /* // ! FIXME diff --git a/src/database/guards/reference.rs b/src/database/guards/reference.rs index 851bb2f..6504638 100644 --- a/src/database/guards/reference.rs +++ b/src/database/guards/reference.rs @@ -1,10 +1,10 @@ -use mongodb::bson::{doc, from_bson, Bson}; -use crate::util::result::{Error, Result}; -use serde::{Deserialize, Serialize}; -use crate::database::get_collection; use crate::database::entities::*; -use rocket::request::FromParam; +use crate::database::get_collection; +use crate::util::result::{Error, Result}; +use mongodb::bson::{doc, from_bson, Bson}; use rocket::http::RawStr; +use rocket::request::FromParam; +use serde::{Deserialize, Serialize}; use validator::Validate; #[derive(Validate, Serialize, Deserialize)] @@ -24,15 +24,20 @@ impl Ref { doc! { "_id": &self.id }, - None + None, ) .await - .map_err(|_| Error::DatabaseError { operation: "find_one", with: "user" })? + .map_err(|_| Error::DatabaseError { + operation: "find_one", + with: "user", + })? .ok_or_else(|| Error::UnknownUser)?; - + Ok( - from_bson(Bson::Document(doc)) - .map_err(|_| Error::DatabaseError { operation: "from_bson", with: "user" })? + from_bson(Bson::Document(doc)).map_err(|_| Error::DatabaseError { + operation: "from_bson", + with: "user", + })?, ) } } diff --git a/src/database/guards/user.rs b/src/database/guards/user.rs index e69de29..8b13789 100644 --- a/src/database/guards/user.rs +++ b/src/database/guards/user.rs @@ -0,0 +1 @@ + diff --git a/src/database/migrations/init.rs b/src/database/migrations/init.rs index 4edb04f..e8b2b89 100644 --- a/src/database/migrations/init.rs +++ b/src/database/migrations/init.rs @@ -10,28 +10,28 @@ pub async fn create_database() { let db = get_db(); db.create_collection("users", None) - .await - .expect("Failed to create users collection."); - + .await + .expect("Failed to create users collection."); + db.create_collection("channels", None) - .await - .expect("Failed to create channels collection."); - + .await + .expect("Failed to create channels collection."); + db.create_collection("guilds", None) - .await - .expect("Failed to create guilds collection."); - + .await + .expect("Failed to create guilds collection."); + db.create_collection("members", None) - .await - .expect("Failed to create members collection."); - + .await + .expect("Failed to create members collection."); + db.create_collection("messages", None) - .await - .expect("Failed to create messages collection."); - + .await + .expect("Failed to create messages collection."); + db.create_collection("migrations", None) - .await - .expect("Failed to create migrations collection."); + .await + .expect("Failed to create migrations collection."); db.create_collection( "pubsub", @@ -60,21 +60,21 @@ pub async fn create_database() { } ] }, - None + None, ) .await .expect("Failed to create username index."); db.collection("migrations") - .insert_one( - doc! { - "_id": 0, - "revision": LATEST_REVISION - }, - None, - ) - .await - .expect("Failed to save migration info."); + .insert_one( + doc! { + "_id": 0, + "revision": LATEST_REVISION + }, + None, + ) + .await + .expect("Failed to save migration info."); info!("Created database."); } diff --git a/src/database/migrations/scripts.rs b/src/database/migrations/scripts.rs index 5d469ff..5172416 100644 --- a/src/database/migrations/scripts.rs +++ b/src/database/migrations/scripts.rs @@ -1,10 +1,10 @@ -use super::super::{get_db, get_collection}; +use super::super::{get_collection, get_db}; +use crate::rocket::futures::StreamExt; use log::info; +use mongodb::bson::{doc, from_bson, Bson}; use mongodb::options::FindOptions; use serde::{Deserialize, Serialize}; -use crate::rocket::futures::StreamExt; -use mongodb::bson::{doc, from_bson, Bson}; #[derive(Serialize, Deserialize)] struct MigrationInfo { @@ -86,7 +86,7 @@ pub async fn run_migrations(revision: i32) -> i32 { .get_str("_id") .expect("Failed to get channel id.") .to_string(); - + let gid = channel .get_str("guild") .expect("Failed to get guild id.") @@ -124,27 +124,28 @@ pub async fn run_migrations(revision: i32) -> i32 { if revision <= 2 { info!("Running migration [revision 2]: Add username index to users."); - get_db().run_command( - doc! { - "createIndexes": "users", - "indexes": [ - { - "key": { - "username": 1 - }, - "name": "username", - "unique": true, - "collation": { - "locale": "en", - "strength": 2 + get_db() + .run_command( + doc! { + "createIndexes": "users", + "indexes": [ + { + "key": { + "username": 1 + }, + "name": "username", + "unique": true, + "collation": { + "locale": "en", + "strength": 2 + } } - } - ] - }, - None - ) - .await - .expect("Failed to create username index."); + ] + }, + None, + ) + .await + .expect("Failed to create username index."); } // Reminder to update LATEST_REVISION when adding new migrations. diff --git a/src/database/mod.rs b/src/database/mod.rs index 48d81d9..9feb7c8 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -26,7 +26,7 @@ pub fn get_collection(collection: &str) -> Collection { get_db().collection(collection) } -pub mod permissions; -pub mod migrations; pub mod entities; pub mod guards; +pub mod migrations; +pub mod permissions; diff --git a/src/database/permissions/mod.rs b/src/database/permissions/mod.rs index f2346a5..01e8386 100644 --- a/src/database/permissions/mod.rs +++ b/src/database/permissions/mod.rs @@ -7,7 +7,7 @@ use std::ops; pub enum UserPermission { Access = 1, SendMessage = 2, - Invite = 4 + Invite = 4, } bitfield! { @@ -40,9 +40,7 @@ pub fn get_relationship(a: &User, b: &Ref) -> RelationshipStatus { } if let Some(relations) = &a.relations { - if let Some(relationship) = relations - .iter() - .find(|x| x.id == b.id) { + if let Some(relationship) = relations.iter().find(|x| x.id == b.id) { return relationship.status.clone(); } } diff --git a/src/main.rs b/src/main.rs index f20e9f4..8c55f5b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,15 +13,15 @@ extern crate impl_ops; extern crate bitfield; extern crate ctrlc; -pub mod notifications; pub mod database; +pub mod notifications; pub mod routes; pub mod util; -use rauth; -use log::info; -use futures::join; use async_std::task; +use futures::join; +use log::info; +use rauth; use rocket_cors::AllowedOrigins; fn main() { @@ -41,7 +41,8 @@ async fn entry() { ctrlc::set_handler(move || { // Force ungraceful exit to avoid hang. std::process::exit(0); - }).expect("Error setting Ctrl-C handler"); + }) + .expect("Error setting Ctrl-C handler"); join!( launch_web(), @@ -57,7 +58,7 @@ async fn launch_web() { } .to_cors() .expect("Failed to create CORS."); - + let auth = rauth::auth::Auth::new(database::get_collection("accounts")); routes::mount(rauth::routes::mount(rocket::ignite(), "/auth", auth)) diff --git a/src/notifications/events.rs b/src/notifications/events.rs index 8814ada..b046737 100644 --- a/src/notifications/events.rs +++ b/src/notifications/events.rs @@ -1,5 +1,5 @@ -use serde::{Deserialize, Serialize}; use rauth::auth::Session; +use serde::{Deserialize, Serialize}; use snafu::Snafu; #[derive(Serialize, Deserialize, Debug, Snafu)] @@ -15,7 +15,7 @@ pub enum WebSocketError { #[derive(Deserialize, Debug)] #[serde(tag = "type")] pub enum ServerboundNotification { - Authenticate(Session) + Authenticate(Session), } #[derive(Serialize, Deserialize, Debug)] @@ -78,10 +78,9 @@ pub enum ClientboundNotification { GuildDelete { id: String, },*/ - UserRelationship { id: String, user: String, status: i32, - } + }, } diff --git a/src/notifications/hive.rs b/src/notifications/hive.rs index ec23101..98c8e4b 100644 --- a/src/notifications/hive.rs +++ b/src/notifications/hive.rs @@ -1,12 +1,12 @@ use super::events::ClientboundNotification; use crate::database::get_collection; +use futures::FutureExt; use hive_pubsub::backend::mongo::MongodbPubSub; use hive_pubsub::PubSub; +use log::{debug, error}; use once_cell::sync::OnceCell; use serde_json::to_string; -use futures::FutureExt; -use log::{error, debug}; static HIVE: OnceCell<MongodbPubSub<String, String, ClientboundNotification>> = OnceCell::new(); @@ -35,7 +35,7 @@ pub async fn listen() { .fuse() .await .expect("Hive hit an error"); - + dbg!("a"); } diff --git a/src/notifications/mod.rs b/src/notifications/mod.rs index 0312f43..23abbfd 100644 --- a/src/notifications/mod.rs +++ b/src/notifications/mod.rs @@ -1,3 +1,3 @@ -pub mod websocket; pub mod events; pub mod hive; +pub mod websocket; diff --git a/src/notifications/websocket.rs b/src/notifications/websocket.rs index 1b1593a..9d884fb 100644 --- a/src/notifications/websocket.rs +++ b/src/notifications/websocket.rs @@ -1,21 +1,26 @@ -use crate::util::variables::WS_HOST; +use crate::{database::entities::User, util::variables::WS_HOST}; -use log::info; -use ulid::Ulid; +use async_std::net::{TcpListener, TcpStream}; use async_std::task; -use futures::prelude::*; -use std::str::from_utf8; -use std::sync::{Arc, RwLock}; +use async_tungstenite::tungstenite::Message; +use futures::channel::mpsc::{unbounded, UnboundedSender}; +use futures::{pin_mut, prelude::*}; +use log::info; use many_to_many::ManyToMany; +use rauth::auth::Session; use std::collections::HashMap; -use futures::stream::SplitSink; -use async_tungstenite::WebSocketStream; -use async_tungstenite::tungstenite::Message; -use async_std::net::{TcpListener, TcpStream}; +use std::net::SocketAddr; +use std::str::from_utf8; +use std::sync::{Arc, Mutex, RwLock}; +use ulid::Ulid; + +use super::events::ServerboundNotification; + +type Tx = UnboundedSender<Message>; +type PeerMap = Arc<Mutex<HashMap<SocketAddr, Tx>>>; lazy_static! { - static ref CONNECTIONS: Arc<RwLock<HashMap<String, SplitSink<WebSocketStream<TcpStream>, Message>>>> = - Arc::new(RwLock::new(HashMap::new())); + static ref CONNECTIONS: PeerMap = Arc::new(Mutex::new(HashMap::new())); static ref USERS: Arc<RwLock<ManyToMany<String, String>>> = Arc::new(RwLock::new(ManyToMany::new())); } @@ -31,27 +36,41 @@ pub async fn launch_server() { } async fn accept(stream: TcpStream) { - let addr = stream.peer_addr().expect("Connected streams should have a peer address."); + let addr = stream + .peer_addr() + .expect("Connected streams should have a peer address."); let ws_stream = async_tungstenite::accept_async(stream) .await .expect("Error during websocket handshake."); - info!("User established WebSocket connection from {}.", addr); + info!("User established WebSocket connection from {}.", &addr); let id = Ulid::new().to_string(); let (write, read) = ws_stream.split(); - CONNECTIONS - .write() - .unwrap() - .insert(id, write); - - read - .for_each(|message| async { - let data = message.unwrap().into_data(); - // if you mess with the data, you get the bazooki - let string = from_utf8(&data).unwrap(); - println!("{}", string); - }) - .await; + let (tx, rx) = unbounded(); + CONNECTIONS.lock().unwrap().insert(addr, tx); + + let session: Option<Session> = None; + let user: Option<User> = None; + + let fwd = rx.map(Ok).forward(write); + let reading = read.for_each(|message| async { + let data = message.unwrap().into_data(); + // if you mess with the data, you get the bazooki + let string = from_utf8(&data).unwrap(); + + if let Ok(notification) = serde_json::from_str::<ServerboundNotification>(string) { + match notification { + ServerboundNotification::Authenticate(a) => { + dbg!(a); + } + } + } + }); + + pin_mut!(fwd, reading); + future::select(fwd, reading).await; + + println!("User {} disconnected.", &addr); } diff --git a/src/routes/channels/mod.rs b/src/routes/channels/mod.rs index 9a5378a..018a956 100644 --- a/src/routes/channels/mod.rs +++ b/src/routes/channels/mod.rs @@ -1,5 +1,5 @@ use rocket::Route; pub fn routes() -> Vec<Route> { - routes! [] + routes![] } diff --git a/src/routes/guild/mod.rs b/src/routes/guild/mod.rs index 9a5378a..018a956 100644 --- a/src/routes/guild/mod.rs +++ b/src/routes/guild/mod.rs @@ -1,5 +1,5 @@ use rocket::Route; pub fn routes() -> Vec<Route> { - routes! [] + routes![] } diff --git a/src/routes/mod.rs b/src/routes/mod.rs index 2789410..77ea709 100644 --- a/src/routes/mod.rs +++ b/src/routes/mod.rs @@ -2,11 +2,11 @@ pub use rocket::http::Status; pub use rocket::response::Redirect; use rocket::Rocket; -mod root; -mod users; +mod channels; mod guild; mod onboard; -mod channels; +mod root; +mod users; pub fn mount(rocket: Rocket) -> Rocket { rocket diff --git a/src/routes/onboard/complete.rs b/src/routes/onboard/complete.rs index 1ff0de0..857d7c6 100644 --- a/src/routes/onboard/complete.rs +++ b/src/routes/onboard/complete.rs @@ -1,13 +1,13 @@ -use mongodb::options::{Collation, FindOneOptions}; -use crate::util::result::{Error, Result}; -use serde::{Deserialize, Serialize}; use crate::database::entities::User; use crate::database::get_collection; -use rocket_contrib::json::Json; -use rauth::auth::Session; -use validator::Validate; +use crate::util::result::{Error, Result}; use mongodb::bson::doc; +use mongodb::options::{Collation, FindOneOptions}; +use rauth::auth::Session; use regex::Regex; +use rocket_contrib::json::Json; +use serde::{Deserialize, Serialize}; +use validator::Validate; lazy_static! { static ref RE_USERNAME: Regex = Regex::new(r"^[a-zA-Z0-9-_]+$").unwrap(); @@ -16,7 +16,7 @@ lazy_static! { #[derive(Validate, Serialize, Deserialize)] pub struct Data { #[validate(length(min = 2, max = 32), regex = "RE_USERNAME")] - username: String + username: String, } #[post("/complete", data = "<data>")] @@ -24,22 +24,27 @@ pub async fn req(session: Session, user: Option<User>, data: Json<Data>) -> Resu if user.is_some() { Err(Error::AlreadyOnboarded)? } - + data.validate() .map_err(|error| Error::FailedValidation { error })?; let col = get_collection("users"); - if col.find_one( - doc! { - "username": &data.username - }, - FindOneOptions::builder() - .collation(Collation::builder().locale("en").strength(2).build()) - .build() - ) - .await - .map_err(|_| Error::DatabaseError { operation: "find_one", with: "user" })? - .is_some() { + if col + .find_one( + doc! { + "username": &data.username + }, + FindOneOptions::builder() + .collation(Collation::builder().locale("en").strength(2).build()) + .build(), + ) + .await + .map_err(|_| Error::DatabaseError { + operation: "find_one", + with: "user", + })? + .is_some() + { Err(Error::UsernameTaken)? } @@ -48,10 +53,13 @@ pub async fn req(session: Session, user: Option<User>, data: Json<Data>) -> Resu "_id": session.user_id, "username": &data.username }, - None + None, ) .await - .map_err(|_| Error::DatabaseError { operation: "insert_one", with: "user" })?; + .map_err(|_| Error::DatabaseError { + operation: "insert_one", + with: "user", + })?; Ok(()) } diff --git a/src/routes/onboard/hello.rs b/src/routes/onboard/hello.rs index 8f8f77d..39f112a 100644 --- a/src/routes/onboard/hello.rs +++ b/src/routes/onboard/hello.rs @@ -1,6 +1,6 @@ -use rocket_contrib::json::JsonValue; use crate::database::entities::User; use rauth::auth::Session; +use rocket_contrib::json::JsonValue; #[get("/hello")] pub async fn req(_session: Session, user: Option<User>) -> JsonValue { diff --git a/src/routes/onboard/mod.rs b/src/routes/onboard/mod.rs index c7e9971..727886d 100644 --- a/src/routes/onboard/mod.rs +++ b/src/routes/onboard/mod.rs @@ -1,11 +1,8 @@ use rocket::Route; -mod hello; mod complete; +mod hello; pub fn routes() -> Vec<Route> { - routes! [ - hello::req, - complete::req - ] + routes![hello::req, complete::req] } diff --git a/src/routes/root.rs b/src/routes/root.rs index e3f9fc7..52a99d8 100644 --- a/src/routes/root.rs +++ b/src/routes/root.rs @@ -1,7 +1,7 @@ use crate::util::variables::{DISABLE_REGISTRATION, HCAPTCHA_SITEKEY, USE_EMAIL, USE_HCAPTCHA}; -use rocket_contrib::json::JsonValue; use mongodb::bson::doc; +use rocket_contrib::json::JsonValue; #[get("/")] pub async fn root() -> JsonValue { diff --git a/src/routes/users/add_friend.rs b/src/routes/users/add_friend.rs index d0e1a6a..a0762f2 100644 --- a/src/routes/users/add_friend.rs +++ b/src/routes/users/add_friend.rs @@ -1,8 +1,16 @@ -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 crate::{ + database::{ + entities::{RelationshipStatus, User}, + get_collection, + guards::reference::Ref, + permissions::get_relationship, + }, + util::result::Error, +}; use futures::try_join; +use mongodb::bson::doc; +use rocket_contrib::json::JsonValue; #[put("/<target>/friend")] pub async fn req(user: User, target: Ref) -> Result<JsonValue> { @@ -42,7 +50,10 @@ pub async fn req(user: User, target: Ref) -> Result<JsonValue> { ) ) { Ok(_) => Ok(json!({ "status": "Friend" })), - Err(_) => Err(Error::DatabaseError { operation: "update_one", with: "user" }) + Err(_) => Err(Error::DatabaseError { + operation: "update_one", + with: "user", + }), } } RelationshipStatus::None => { @@ -77,7 +88,10 @@ pub async fn req(user: User, target: Ref) -> Result<JsonValue> { ) ) { Ok(_) => Ok(json!({ "status": "Outgoing" })), - Err(_) => Err(Error::DatabaseError { operation: "update_one", with: "user" }) + Err(_) => Err(Error::DatabaseError { + operation: "update_one", + with: "user", + }), } } } diff --git a/src/routes/users/block_user.rs b/src/routes/users/block_user.rs index 59ccd4e..e7f1266 100644 --- a/src/routes/users/block_user.rs +++ b/src/routes/users/block_user.rs @@ -1,16 +1,18 @@ -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 crate::{ + database::entities::RelationshipStatus, database::entities::User, database::get_collection, + database::guards::reference::Ref, database::permissions::get_relationship, util::result::Error, +}; use futures::try_join; +use mongodb::bson::doc; +use rocket_contrib::json::JsonValue; #[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::User | RelationshipStatus::Blocked => Err(Error::NoEffect), RelationshipStatus::BlockedOther => { col.update_one( doc! { @@ -22,13 +24,16 @@ pub async fn req(user: User, target: Ref) -> Result<JsonValue> { "relations.$.status": "Blocked" } }, - None + None, ) .await - .map_err(|_| Error::DatabaseError { operation: "update_one", with: "user" })?; + .map_err(|_| Error::DatabaseError { + operation: "update_one", + with: "user", + })?; Ok(json!({ "status": "Blocked" })) - }, + } RelationshipStatus::None => { match try_join!( col.update_one( @@ -61,12 +66,15 @@ pub async fn req(user: User, target: Ref) -> Result<JsonValue> { ) ) { Ok(_) => Ok(json!({ "status": "Blocked" })), - Err(_) => Err(Error::DatabaseError { operation: "update_one", with: "user" }) + Err(_) => Err(Error::DatabaseError { + operation: "update_one", + with: "user", + }), } - }, - RelationshipStatus::Friend | - RelationshipStatus::Incoming | - RelationshipStatus::Outgoing => { + } + RelationshipStatus::Friend + | RelationshipStatus::Incoming + | RelationshipStatus::Outgoing => { match try_join!( col.update_one( doc! { @@ -94,7 +102,10 @@ pub async fn req(user: User, target: Ref) -> Result<JsonValue> { ) ) { Ok(_) => Ok(json!({ "status": "Blocked" })), - Err(_) => Err(Error::DatabaseError { operation: "update_one", with: "user" }) + Err(_) => Err(Error::DatabaseError { + operation: "update_one", + with: "user", + }), } } } diff --git a/src/routes/users/fetch_dms.rs b/src/routes/users/fetch_dms.rs index 2eda25e..218efae 100644 --- a/src/routes/users/fetch_dms.rs +++ b/src/routes/users/fetch_dms.rs @@ -1,9 +1,9 @@ use crate::database::entities::{Channel, User}; -use mongodb::bson::{Bson, doc, from_bson}; -use crate::util::result::{Error, Result}; use crate::database::get_collection; -use rocket_contrib::json::JsonValue; +use crate::util::result::{Error, Result}; use futures::StreamExt; +use mongodb::bson::{doc, from_bson, Bson}; +use rocket_contrib::json::JsonValue; #[get("/dms")] pub async fn req(user: User) -> Result<JsonValue> { @@ -21,11 +21,14 @@ pub async fn req(user: User) -> Result<JsonValue> { ], "recipients": user.id }, - None + None, ) .await - .map_err(|_| Error::DatabaseError { operation: "find", with: "channels" })?; - + .map_err(|_| Error::DatabaseError { + operation: "find", + with: "channels", + })?; + let mut channels = vec![]; while let Some(result) = cursor.next().await { if let Ok(doc) = result { @@ -33,7 +36,5 @@ pub async fn req(user: User) -> Result<JsonValue> { } } - Ok(json!( - channels - )) + Ok(json!(channels)) } diff --git a/src/routes/users/fetch_relationship.rs b/src/routes/users/fetch_relationship.rs index 3c2c686..bd3c0cb 100644 --- a/src/routes/users/fetch_relationship.rs +++ b/src/routes/users/fetch_relationship.rs @@ -1,10 +1,8 @@ use crate::database::{entities::User, guards::reference::Ref, permissions::get_relationship}; -use rocket_contrib::json::JsonValue; use crate::util::result::Result; +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) })) } diff --git a/src/routes/users/fetch_relationships.rs b/src/routes/users/fetch_relationships.rs index c974244..7df7e7c 100644 --- a/src/routes/users/fetch_relationships.rs +++ b/src/routes/users/fetch_relationships.rs @@ -1,14 +1,12 @@ use crate::database::entities::User; -use rocket_contrib::json::JsonValue; use crate::util::result::Result; +use rocket_contrib::json::JsonValue; #[get("/relationships")] pub async fn req(user: User) -> Result<JsonValue> { - Ok( - if let Some(vec) = user.relations { - json!(vec) - } else { - json!([]) - } - ) + Ok(if let Some(vec) = user.relations { + json!(vec) + } else { + json!([]) + }) } diff --git a/src/routes/users/fetch_user.rs b/src/routes/users/fetch_user.rs index ec7a23f..acbbfde 100644 --- a/src/routes/users/fetch_user.rs +++ b/src/routes/users/fetch_user.rs @@ -1,6 +1,6 @@ +use crate::database::entities::User; use crate::database::guards::reference::Ref; use crate::util::result::{Error, Result}; -use crate::database::entities::User; use rocket_contrib::json::JsonValue; #[get("/<target>")] @@ -13,7 +13,7 @@ pub async fn req(user: User, target: Ref) -> Result<JsonValue> { if !perm.get_access() { Err(Error::LabelMe)? } - + // Only return user relationships if the target is the caller. target.relations = None; } diff --git a/src/routes/users/mod.rs b/src/routes/users/mod.rs index 4a3e004..8f7b4ec 100644 --- a/src/routes/users/mod.rs +++ b/src/routes/users/mod.rs @@ -1,24 +1,22 @@ use rocket::Route; -mod fetch_user; +mod add_friend; +mod block_user; mod fetch_dms; -mod open_dm; -mod fetch_relationships; mod fetch_relationship; -mod add_friend; +mod fetch_relationships; +mod fetch_user; +mod open_dm; mod remove_friend; -mod block_user; mod unblock_user; pub fn routes() -> Vec<Route> { - routes! [ + routes![ // User Information fetch_user::req, - // Direct Messaging fetch_dms::req, open_dm::req, - // Relationships fetch_relationships::req, fetch_relationship::req, diff --git a/src/routes/users/open_dm.rs b/src/routes/users/open_dm.rs index 32f7496..1136e44 100644 --- a/src/routes/users/open_dm.rs +++ b/src/routes/users/open_dm.rs @@ -1,9 +1,9 @@ use crate::database::entities::{Channel, User}; +use crate::database::get_collection; use crate::database::guards::reference::Ref; use crate::util::result::{Error, Result}; -use crate::database::get_collection; -use rocket_contrib::json::JsonValue; use mongodb::bson::doc; +use rocket_contrib::json::JsonValue; use ulid::Ulid; #[get("/<target>/dm")] @@ -25,25 +25,22 @@ pub async fn req(user: User, target: Ref) -> Result<JsonValue> { let existing_channel = get_collection("channels") .find_one(query, None) .await - .map_err(|_| Error::DatabaseError { operation: "find_one", with: "channel" })?; + .map_err(|_| Error::DatabaseError { + operation: "find_one", + with: "channel", + })?; if let Some(doc) = existing_channel { Ok(json!(doc)) } else { let id = Ulid::new().to_string(); let channel = if user.id == target.id { - Channel::SavedMessages { - id, - user: user.id - } + Channel::SavedMessages { id, user: user.id } } else { Channel::DirectMessage { id, active: false, - recipients: vec! [ - user.id, - target.id - ] + recipients: vec![user.id, target.id], } }; diff --git a/src/routes/users/remove_friend.rs b/src/routes/users/remove_friend.rs index 97290ce..468a6be 100644 --- a/src/routes/users/remove_friend.rs +++ b/src/routes/users/remove_friend.rs @@ -1,21 +1,24 @@ -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 crate::{ + database::entities::RelationshipStatus, database::entities::User, database::get_collection, + database::guards::reference::Ref, database::permissions::get_relationship, util::result::Error, +}; use futures::try_join; +use mongodb::bson::doc; +use rocket_contrib::json::JsonValue; #[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 => { + RelationshipStatus::Blocked + | RelationshipStatus::BlockedOther + | RelationshipStatus::User + | RelationshipStatus::None => Err(Error::NoEffect), + RelationshipStatus::Friend + | RelationshipStatus::Outgoing + | RelationshipStatus::Incoming => { match try_join!( col.update_one( doc! { @@ -45,7 +48,10 @@ pub async fn req(user: User, target: Ref) -> Result<JsonValue> { ) ) { Ok(_) => Ok(json!({ "status": "None" })), - Err(_) => Err(Error::DatabaseError { operation: "update_one", with: "user" }) + Err(_) => Err(Error::DatabaseError { + operation: "update_one", + with: "user", + }), } } } diff --git a/src/routes/users/unblock_user.rs b/src/routes/users/unblock_user.rs index 10e13b6..585170f 100644 --- a/src/routes/users/unblock_user.rs +++ b/src/routes/users/unblock_user.rs @@ -1,20 +1,23 @@ -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 crate::{ + database::entities::RelationshipStatus, database::entities::User, database::get_collection, + database::guards::reference::Ref, database::permissions::get_relationship, util::result::Error, +}; use futures::try_join; +use mongodb::bson::doc; +use rocket_contrib::json::JsonValue; #[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::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 => { @@ -28,13 +31,16 @@ pub async fn req(user: User, target: Ref) -> Result<JsonValue> { "relations.$.status": "BlockedOther" } }, - None + None, ) .await - .map_err(|_| Error::DatabaseError { operation: "update_one", with: "user" })?; - + .map_err(|_| Error::DatabaseError { + operation: "update_one", + with: "user", + })?; + Ok(json!({ "status": "BlockedOther" })) - }, + } RelationshipStatus::BlockedOther => { match try_join!( col.update_one( @@ -65,10 +71,13 @@ pub async fn req(user: User, target: Ref) -> Result<JsonValue> { ) ) { Ok(_) => Ok(json!({ "status": "None" })), - Err(_) => Err(Error::DatabaseError { operation: "update_one", with: "user" }) + Err(_) => Err(Error::DatabaseError { + operation: "update_one", + with: "user", + }), } - }, - _ => Err(Error::InternalError) + } + _ => Err(Error::InternalError), } } } diff --git a/src/util/mod.rs b/src/util/mod.rs index 2a4d04f..28c9041 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -2,9 +2,9 @@ use rand::{distributions::Alphanumeric, Rng}; use std::collections::HashSet; use std::iter::FromIterator; +pub mod captcha; pub mod email; pub mod result; -pub mod captcha; pub mod variables; pub fn vec_to_set<T: Clone + Eq + std::hash::Hash>(data: &[T]) -> HashSet<T> { diff --git a/src/util/result.rs b/src/util/result.rs index 7f98081..e707f60 100644 --- a/src/util/result.rs +++ b/src/util/result.rs @@ -1,11 +1,11 @@ -use rocket::response::{self, Responder, Response}; +use json; use rocket::http::{ContentType, Status}; -use validator::ValidationErrors; use rocket::request::Request; +use rocket::response::{self, Responder, Response}; use serde::Serialize; -use std::io::Cursor; use snafu::Snafu; -use json; +use std::io::Cursor; +use validator::ValidationErrors; #[derive(Serialize, Debug, Snafu)] #[serde(tag = "type")] @@ -16,7 +16,7 @@ pub enum Error { // ? Onboarding related errors. #[snafu(display("Already finished onboarding."))] AlreadyOnboarded, - + // ? User related errors. #[snafu(display("Username has already been taken."))] UsernameTaken, @@ -35,7 +35,10 @@ pub enum Error { #[snafu(display("Failed to validate fields."))] FailedValidation { error: ValidationErrors }, #[snafu(display("Encountered a database error."))] - DatabaseError { operation: &'static str, with: &'static str }, + DatabaseError { + operation: &'static str, + with: &'static str, + }, #[snafu(display("Internal server error."))] InternalError, #[snafu(display("This request had no effect."))] -- GitLab