diff --git a/src/database/channel.rs b/src/database/channel.rs new file mode 100644 index 0000000000000000000000000000000000000000..be88081674f577f6dae95b7607a1f56777bf9bcd --- /dev/null +++ b/src/database/channel.rs @@ -0,0 +1,12 @@ +use serde::{ Deserialize, Serialize }; + +#[derive(Serialize, Deserialize, Debug)] +pub struct Channel { + #[serde(rename = "_id")] + pub id: String, + pub channel_type: u8, + + // for Direct Messages + pub recipients: Option<Vec<String>>, + pub active: Option<bool>, +} diff --git a/src/database/message.rs b/src/database/message.rs new file mode 100644 index 0000000000000000000000000000000000000000..d65b2118e29611af733a3c2e02db9bf9ceabbd6f --- /dev/null +++ b/src/database/message.rs @@ -0,0 +1,8 @@ + +use serde::{ Deserialize, Serialize }; + +#[derive(Serialize, Deserialize, Debug)] +pub struct Message { + #[serde(rename = "_id")] + pub id: String, +} diff --git a/src/database/mod.rs b/src/database/mod.rs index a2b0e33ece1f4f8d96ad13b8fa9d937f250c004f..fb1d14cfcc07c750fcb06521a88eb8b60be46f01 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -24,4 +24,6 @@ pub fn get_collection(collection: &str) -> Collection { get_db().collection(collection) } -pub mod user; \ No newline at end of file +pub mod user; +pub mod channel; +pub mod message; diff --git a/src/guards/auth.rs b/src/guards/auth.rs index 3f718da94a3878c88bf252e7e3dac3b679fbf0ac..7c3b2bc128c978ca55024efe32915193336c3139 100644 --- a/src/guards/auth.rs +++ b/src/guards/auth.rs @@ -3,15 +3,9 @@ use rocket::http::{ Status, RawStr }; use rocket::request::{ self, Request, FromRequest, FromParam }; use bson::{ bson, doc, from_bson }; -use ulid::Ulid; use crate::database; - -pub struct User( - pub Ulid, - pub String, - pub database::user::User, -); +use database::user::User; #[derive(Debug)] pub enum AuthError { @@ -33,11 +27,7 @@ impl<'a, 'r> FromRequest<'a, 'r> for User { let result = col.find_one(doc! { "access_token": key }, None).unwrap(); if let Some(user) = result { - Outcome::Success(User ( - Ulid::from_string(user.get_str("_id").unwrap()).unwrap(), - user.get_str("username").unwrap().to_string(), - from_bson(bson::Bson::Document(user)).expect("Failed to unwrap user.") - )) + Outcome::Success(from_bson(bson::Bson::Document(user)).expect("Failed to unwrap user.")) } else { Outcome::Failure((Status::Forbidden, AuthError::Invalid)) } @@ -55,11 +45,7 @@ impl<'r> FromParam<'r> for User { let result = col.find_one(doc! { "_id": param.to_string() }, None).unwrap(); if let Some(user) = result { - Ok(User ( - Ulid::from_string(user.get_str("_id").unwrap()).unwrap(), - user.get_str("username").unwrap().to_string(), - from_bson(bson::Bson::Document(user)).expect("Failed to unwrap user.") - )) + Ok(from_bson(bson::Bson::Document(user)).expect("Failed to unwrap user.")) } else { Err(param) } diff --git a/src/guards/channel.rs b/src/guards/channel.rs index 9142c178e2570e8ad0bb0802c4487386c0f453e4..daa277d5ced8aefd760ab31e77571414f47e1c99 100644 --- a/src/guards/channel.rs +++ b/src/guards/channel.rs @@ -1,24 +1,11 @@ -use rocket::Outcome; -use rocket::http::{ Status, RawStr }; -use rocket::request::{ self, Request, FromRequest, FromParam }; - -use bson::{ bson, doc, ordered::OrderedDocument }; -use std::convert::TryFrom; -use ulid::Ulid; +use rocket::http::{ RawStr }; +use rocket::request::{ FromParam }; +use bson::{ bson, doc, from_bson }; use crate::database; -use crate::routes::channel::ChannelType; - -pub struct Channel ( - pub Ulid, - pub ChannelType, - pub OrderedDocument, -); -pub struct Message ( - pub Ulid, - pub OrderedDocument, -); +use database::channel::Channel; +use database::message::Message; impl<'r> FromParam<'r> for Channel { type Error = &'r RawStr; @@ -28,11 +15,7 @@ impl<'r> FromParam<'r> for Channel { let result = col.find_one(doc! { "_id": param.to_string() }, None).unwrap(); if let Some(channel) = result { - Ok(Channel ( - Ulid::from_string(channel.get_str("_id").unwrap()).unwrap(), - ChannelType::try_from(channel.get_i32("type").unwrap() as usize).unwrap(), - channel - )) + Ok(from_bson(bson::Bson::Document(channel)).expect("Failed to unwrap channel.")) } else { Err(param) } @@ -47,10 +30,7 @@ impl<'r> FromParam<'r> for Message { let result = col.find_one(doc! { "_id": param.to_string() }, None).unwrap(); if let Some(message) = result { - Ok(Message ( - Ulid::from_string(message.get_str("_id").unwrap()).unwrap(), - message - )) + Ok(from_bson(bson::Bson::Document(message)).expect("Failed to unwrap message.")) } else { Err(param) } diff --git a/src/routes/channel.rs b/src/routes/channel.rs index ed36ee80ce7f9b07fb40aa0a2fd68d514a5df47e..81d3f07437e4255573b61ebe7193a1c9914c0739 100644 --- a/src/routes/channel.rs +++ b/src/routes/channel.rs @@ -1,12 +1,8 @@ -use crate::guards::{ auth::User, channel::Channel }; -use crate::database; +use crate::database::{ user::User, channel::Channel }; -use rocket_contrib::json::{ Json, JsonValue }; -use serde::{ Serialize, Deserialize }; -use mongodb::options::FindOptions; +use rocket_contrib::json::{ JsonValue }; use num_enum::TryFromPrimitive; -use bson::{ bson, doc }; -use ulid::Ulid; +use bson::{ doc }; #[derive(Debug, TryFromPrimitive)] #[repr(usize)] @@ -17,19 +13,21 @@ pub enum ChannelType { } fn has_permission(user: &User, target: &Channel) -> bool { - let id = user.0.to_string(); - match target.1 { - ChannelType::DM | - ChannelType::GROUP_DM => { - for user in target.2.get_array("recipients").expect("DB[recipients]") { - if user.as_str().expect("Expected string id.") == id { - return true; + match target.channel_type { + 0..=1 => { + if let Some(arr) = &target.recipients { + for item in arr { + if item == &user.id { + return true; + } } } false }, - ChannelType::GUILD_CHANNEL => + 2 => + false, + _ => false } } @@ -41,12 +39,10 @@ pub fn channel(user: User, target: Channel) -> Option<JsonValue> { return None } - let Channel ( id, channel_type, doc ) = target; - Some( json!({ - "id": id.to_string(), - "type": channel_type as u8 + "id": target.id, + "type": target.channel_type } )) } diff --git a/src/routes/user.rs b/src/routes/user.rs index 01907890cc2c52e75afa2afa270ec214a2c6ff9b..1fde7d9e3ad5369471d92c8656217eac99b19225 100644 --- a/src/routes/user.rs +++ b/src/routes/user.rs @@ -1,5 +1,4 @@ -use crate::guards::auth::User; -use crate::database; +use crate::database::{ self, user::User, channel::Channel }; use crate::routes::channel; use rocket_contrib::json::{ Json, JsonValue }; @@ -11,14 +10,12 @@ use ulid::Ulid; /// retrieve your user information #[get("/@me")] pub fn me(user: User) -> JsonValue { - let User ( id, username, doc ) = user; - json!({ - "id": id.to_string(), - "username": username, - "email": doc.email, - "verified": doc.email_verification.verified, - "created_timestamp": id.datetime().timestamp(), + "id": user.id, + "username": user.username, + "email": user.email, + "verified": user.email_verification.verified, + "created_timestamp": Ulid::from_string(&user.id).unwrap().datetime().timestamp(), }) } @@ -46,7 +43,7 @@ pub fn lookup(_user: User, query: Json<Query>) -> JsonValue { let mut results = Vec::new(); for user in users { - let u: database::user::User = from_bson(bson::Bson::Document(user.unwrap())).expect("Failed to unwrap user."); + let u: User = from_bson(bson::Bson::Document(user.unwrap())).expect("Failed to unwrap user."); results.push( json!({ "id": u.id, @@ -73,35 +70,21 @@ pub fn dms(user: User) -> JsonValue { "type": channel::ChannelType::GROUP_DM as i32 } ], - "recipients": user.0.to_string() + "recipients": user.id }, None ).expect("Failed channel lookup"); let mut channels = Vec::new(); - for res in results { - let doc = res.expect("Failed to unwrap document"); - - let mut recipients = Vec::new(); - for user in doc.get_array("recipients").expect("DB[recipients]") { - recipients.push( - user.as_str() - .expect("Should be a string.") - ); - } - - let active = - match doc.get_bool("active") { - Ok(x) => x, - Err(_) => true - }; + for item in results { + let channel: Channel = from_bson(bson::Bson::Document(item.unwrap())).expect("Failed to unwrap channel."); channels.push( json!({ - "id": doc.get_str("_id").expect("DB[id]"), - "type": doc.get_i32("type").expect("DB[type]"), - "recipients": recipients, - "active": active + "id": channel.id, + "type": channel.channel_type, + "recipients": channel.recipients, + "active": channel.active.unwrap() }) ); } @@ -115,12 +98,12 @@ pub fn dm(user: User, target: User) -> JsonValue { let col = database::get_collection("channels"); match col.find_one( - doc! { "type": channel::ChannelType::DM as i32, "recipients": [ user.0.to_string(), target.0.to_string() ] }, + doc! { "type": channel::ChannelType::DM as i32, "recipients": [ user.id.clone(), target.id.clone() ] }, None ).expect("Failed channel lookup") { Some(channel) => json!({ - "id": channel.get_str("_id").expect("DB[id]") + "id": channel.get_str("_id").unwrap() }), None => { let id = Ulid::new(); @@ -129,7 +112,7 @@ pub fn dm(user: User, target: User) -> JsonValue { doc! { "_id": id.to_string(), "type": channel::ChannelType::DM as i32, - "recipients": [ user.0.to_string(), target.0.to_string() ], + "recipients": [ user.id, target.id ], "active": false }, None @@ -153,15 +136,13 @@ enum Relationship { } fn get_relationship(a: &User, b: &User) -> Relationship { - if a.0.to_string() == b.0.to_string() { + if a.id == b.id { return Relationship::SELF } - if let Some(arr) = &b.2.relations { - let id = a.0.to_string(); - + if let Some(arr) = &b.relations { for entry in arr { - if entry.id == id { + if entry.id == a.id { match entry.status { 0 => { return Relationship::FRIEND @@ -190,7 +171,7 @@ fn get_relationship(a: &User, b: &User) -> Relationship { #[get("/@me/friend")] pub fn get_friends(user: User) -> JsonValue { let mut results = Vec::new(); - if let Some(arr) = user.2.relations { + if let Some(arr) = user.relations { for item in arr { results.push( json!({ @@ -210,7 +191,7 @@ pub fn get_friend(user: User, target: User) -> JsonValue { let relationship = get_relationship(&user, &target); json!({ - "id": target.0.to_string(), + "id": target.id, "status": relationship as u8 }) } @@ -219,10 +200,7 @@ pub fn get_friend(user: User, target: User) -> JsonValue { #[put("/<target>/friend")] pub fn add_friend(user: User, target: User) -> JsonValue { let col = database::get_collection("users"); - let relationship = get_relationship(&user, &target); - let User ( id, _, _ ) = user; - let User ( tid, _, _ ) = target; match relationship { Relationship::FRIEND => @@ -238,8 +216,8 @@ pub fn add_friend(user: User, target: User) -> JsonValue { Relationship::INCOMING => { col.update_one( doc! { - "_id": id.to_string(), - "relations.id": tid.to_string() + "_id": user.id.clone(), + "relations.id": target.id.clone() }, doc! { "$set": { @@ -251,8 +229,8 @@ pub fn add_friend(user: User, target: User) -> JsonValue { col.update_one( doc! { - "_id": tid.to_string(), - "relations.id": id.to_string() + "_id": target.id, + "relations.id": user.id }, doc! { "$set": { @@ -279,12 +257,12 @@ pub fn add_friend(user: User, target: User) -> JsonValue { Relationship::NONE => { col.update_one( doc! { - "_id": id.to_string() + "_id": user.id.clone() }, doc! { "$push": { "relations": { - "id": tid.to_string(), + "id": target.id.clone(), "status": Relationship::OUTGOING as i32 } } @@ -294,12 +272,12 @@ pub fn add_friend(user: User, target: User) -> JsonValue { col.update_one( doc! { - "_id": tid.to_string() + "_id": target.id }, doc! { "$push": { "relations": { - "id": id.to_string(), + "id": user.id, "status": Relationship::INCOMING as i32 } } @@ -323,10 +301,7 @@ pub fn add_friend(user: User, target: User) -> JsonValue { #[delete("/<target>/friend")] pub fn remove_friend(user: User, target: User) -> JsonValue { let col = database::get_collection("users"); - let relationship = get_relationship(&user, &target); - let User ( id, _, _ ) = user; - let User ( tid, _, _ ) = target; match relationship { Relationship::FRIEND | @@ -334,12 +309,12 @@ pub fn remove_friend(user: User, target: User) -> JsonValue { Relationship::INCOMING => { col.update_one( doc! { - "_id": id.to_string() + "_id": user.id.clone() }, doc! { "$pull": { "relations": { - "id": tid.to_string() + "id": target.id.clone() } } }, @@ -348,12 +323,12 @@ pub fn remove_friend(user: User, target: User) -> JsonValue { col.update_one( doc! { - "_id": tid.to_string() + "_id": target.id }, doc! { "$pull": { "relations": { - "id": id.to_string() + "id": user.id } } },