diff --git a/src/routes/account.rs b/src/routes/account.rs index cea602fbcc10699bb15c555ff053a6a37a96cd0a..be323057ec47c7938d4772e6b90e19506237f8ac 100644 --- a/src/routes/account.rs +++ b/src/routes/account.rs @@ -205,7 +205,7 @@ pub fn resend_email(info: Json<Resend>) -> Response { ).expect("Failed to update user!"); match email::send_verification_email(info.email.to_string(), code) { - true => Response::Ok(None), + true => Response::Result(super::Status::Ok), false => Response::InternalServerError( json!({ "success": false, "error": "Failed to send email! Likely an issue with the backend API." }), ), @@ -279,16 +279,12 @@ pub fn token(info: Json<Token>) -> Response { .find_one(doc! { "access_token": info.token.clone() }, None) .expect("Failed user lookup") { - Response::Success( - json!({ - "id": u.get_str("_id").unwrap(), - }) - ) + Response::Success(json!({ + "id": u.get_str("_id").unwrap(), + })) } else { - Response::Unauthorized( - json!({ - "error": "Invalid token!", - }) - ) + Response::Unauthorized(json!({ + "error": "Invalid token!", + })) } } diff --git a/src/routes/channel.rs b/src/routes/channel.rs index eacd68c8720c971f29124c69e6b66f9338c0f45c..1ed1adbe5bb35d04d1e0d90f56ad2f789e95cd7d 100644 --- a/src/routes/channel.rs +++ b/src/routes/channel.rs @@ -1,3 +1,4 @@ +use super::Response; use crate::database::{self, channel::Channel, message::Message, user::User}; use crate::websocket; @@ -43,24 +44,23 @@ fn get_recipients(target: &Channel) -> Vec<String> { /// fetch channel information #[get("/<target>")] -pub fn channel(user: User, target: Channel) -> Option<JsonValue> { +pub fn channel(user: User, target: Channel) -> Option<Response> { if !has_permission(&user, &target) { return None; } - Some(json!({ - "id": target.id, - "type": target.channel_type, - "recipients": get_recipients(&target), - } - )) + Some(Response::Success(json!({ + "id": target.id, + "type": target.channel_type, + "recipients": get_recipients(&target), + }))) } /// delete channel /// or leave group DM /// or close DM conversation #[delete("/<target>")] -pub fn delete(user: User, target: Channel) -> Option<JsonValue> { +pub fn delete(user: User, target: Channel) -> Option<Response> { if !has_permission(&user, &target) { return None; } @@ -75,33 +75,25 @@ pub fn delete(user: User, target: Channel) -> Option<JsonValue> { ) .expect("Failed to update channel."); - json!({ - "success": true - }) + Response::Result(super::Status::Ok) } 1 => { // ? TODO: group dm - json!({ - "success": true - }) + Response::Result(super::Status::Ok) } 2 => { // ? TODO: guild - json!({ - "success": true - }) + Response::Result(super::Status::Ok) } - _ => json!({ - "success": false - }), + _ => Response::InternalServerError(json!({ "error": "Unknown error has occurred." })), }) } /// fetch channel messages #[get("/<target>/messages")] -pub fn messages(user: User, target: Channel) -> Option<JsonValue> { +pub fn messages(user: User, target: Channel) -> Option<Response> { if !has_permission(&user, &target) { return None; } @@ -121,7 +113,7 @@ pub fn messages(user: User, target: Channel) -> Option<JsonValue> { })); } - Some(json!(messages)) + Some(Response::Success(json!(messages))) } #[derive(Serialize, Deserialize)] @@ -132,7 +124,7 @@ pub struct SendMessage { /// send a message to a channel #[post("/<target>/messages", data = "<message>")] -pub fn send_message(user: User, target: Channel, message: Json<SendMessage>) -> Option<JsonValue> { +pub fn send_message(user: User, target: Channel, message: Json<SendMessage>) -> Option<Response> { if !has_permission(&user, &target) { return None; } @@ -142,10 +134,9 @@ pub fn send_message(user: User, target: Channel, message: Json<SendMessage>) -> let col = database::get_collection("messages"); if let Some(_) = col.find_one(doc! { "nonce": nonce.clone() }, None).unwrap() { - return Some(json!({ - "success": false, - "error": "Message already sent!" - })); + return Some(Response::BadRequest( + json!({ "error": "Message already sent!" }), + )); } let id = Ulid::new().to_string(); @@ -188,22 +179,18 @@ pub fn send_message(user: User, target: Channel, message: Json<SendMessage>) -> .to_string(), ); - json!({ - "success": true, - "id": id - }) + Response::Success(json!({ "id": id })) } else { - json!({ - "success": false, + Response::InternalServerError(json!({ "error": "Failed database query." - }) + })) }, ) } /// get a message #[get("/<target>/messages/<message>")] -pub fn get_message(user: User, target: Channel, message: Message) -> Option<JsonValue> { +pub fn get_message(user: User, target: Channel, message: Message) -> Option<Response> { if !has_permission(&user, &target) { return None; } @@ -224,13 +211,13 @@ pub fn get_message(user: User, target: Channel, message: Message) -> Option<Json None }; - Some(json!({ + Some(Response::Success(json!({ "id": message.id, "author": message.author, "content": message.content, "edited": if let Some(t) = message.edited { Some(t.timestamp()) } else { None }, "previous_content": prev, - })) + }))) } #[derive(Serialize, Deserialize)] @@ -245,16 +232,13 @@ pub fn edit_message( target: Channel, message: Message, edit: Json<EditMessage>, -) -> Option<JsonValue> { +) -> Option<Response> { if !has_permission(&user, &target) { return None; } Some(if message.author != user.id { - json!({ - "success": false, - "error": "You did not send this message." - }) + Response::Unauthorized(json!({ "error": "You did not send this message." })) } else { let col = database::get_collection("messages"); @@ -296,30 +280,24 @@ pub fn edit_message( .to_string(), ); - json!({ - "success": true - }) + Response::Result(super::Status::Ok) + } + Err(_) => { + Response::InternalServerError(json!({ "error": "Failed to update message." })) } - Err(_) => json!({ - "success": false, - "error": "Failed to update message." - }), } }) } /// delete a message #[delete("/<target>/messages/<message>")] -pub fn delete_message(user: User, target: Channel, message: Message) -> Option<JsonValue> { +pub fn delete_message(user: User, target: Channel, message: Message) -> Option<Response> { if !has_permission(&user, &target) { return None; } Some(if message.author != user.id { - json!({ - "success": false, - "error": "You did not send this message." - }) + Response::Unauthorized(json!({ "error": "You did not send this message." })) } else { let col = database::get_collection("messages"); @@ -337,14 +315,11 @@ pub fn delete_message(user: User, target: Channel, message: Message) -> Option<J .to_string(), ); - json!({ - "success": true - }) + Response::Result(super::Status::Ok) + } + Err(_) => { + Response::InternalServerError(json!({ "error": "Failed to delete message." })) } - Err(_) => json!({ - "success": false, - "error": "Failed to delete message." - }), } }) } diff --git a/src/routes/guild.rs b/src/routes/guild.rs index c7c902e7cb565f6f6fa88d48a66b1d294886bcf5..76b807c29ee4ec28314e95d43e40d6e1d04d2315 100644 --- a/src/routes/guild.rs +++ b/src/routes/guild.rs @@ -1,3 +1,4 @@ +use super::Response; use crate::database::{ self, channel::Channel, @@ -14,7 +15,7 @@ use super::channel::ChannelType; /// fetch your guilds #[get("/@me")] -pub fn my_guilds(user: User) -> JsonValue { +pub fn my_guilds(user: User) -> Response { let col = database::get_collection("guilds"); let guilds = col .find( @@ -40,12 +41,12 @@ pub fn my_guilds(user: User) -> JsonValue { })); } - json!(parsed) + Response::Success(json!(parsed)) } /// fetch a guild #[get("/<target>")] -pub fn guild(user: User, target: Guild) -> Option<JsonValue> { +pub fn guild(user: User, target: Guild) -> Option<Response> { if find_member_permissions(user.id.clone(), target.id.clone(), None) == 0 { return None; } @@ -78,18 +79,17 @@ pub fn guild(user: User, target: Guild) -> Option<JsonValue> { })); } - Some(json!({ + Some(Response::Success(json!({ "id": target.id, "name": target.name, "description": target.description, "owner": target.owner, "channels": channels, - })) + }))) } - Err(_) => Some(json!({ - "success": false, - "error": "Failed to fetch channels." - })), + Err(_) => Some(Response::InternalServerError( + json!({ "error": "Failed to fetch channels." }), + )), } } @@ -102,12 +102,9 @@ pub struct CreateGuild { /// create a new guild #[post("/create", data = "<info>")] -pub fn create_guild(user: User, info: Json<CreateGuild>) -> JsonValue { +pub fn create_guild(user: User, info: Json<CreateGuild>) -> Response { if !user.email_verification.verified { - return json!({ - "success": false, - "error": "Email not verified!", - }); + return Response::Unauthorized(json!({ "error": "Email not verified!" })); } let name: String = info.name.chars().take(32).collect(); @@ -123,10 +120,7 @@ pub fn create_guild(user: User, info: Json<CreateGuild>) -> JsonValue { let channels = database::get_collection("channels"); let col = database::get_collection("guilds"); if let Some(_) = col.find_one(doc! { "nonce": nonce.clone() }, None).unwrap() { - return json!({ - "success": false, - "error": "Guild already created!" - }); + return Response::BadRequest(json!({ "error": "Guild already created!" })); } let id = Ulid::new().to_string(); @@ -140,10 +134,9 @@ pub fn create_guild(user: User, info: Json<CreateGuild>) -> JsonValue { }, None, ) { - return json!({ - "success": false, - "error": "Failed to create guild channel." - }); + return Response::InternalServerError( + json!({ "error": "Failed to create guild channel." }), + ); } if col @@ -169,18 +162,12 @@ pub fn create_guild(user: User, info: Json<CreateGuild>) -> JsonValue { ) .is_ok() { - json!({ - "success": true, - "id": id, - }) + Response::Success(json!({ "id": id })) } else { channels .delete_one(doc! { "_id": channel_id }, None) .expect("Failed to delete the channel we just made."); - json!({ - "success": false, - "error": "Failed to create guild." - }) + Response::InternalServerError(json!({ "error": "Failed to create guild." })) } } diff --git a/src/routes/mod.rs b/src/routes/mod.rs index cb88d0ac11206e5a03d121a7eb5105a4f10f9531..ce019e404bf74154693aae56698300ed48f8acbf 100644 --- a/src/routes/mod.rs +++ b/src/routes/mod.rs @@ -1,4 +1,4 @@ -use rocket::http::Status; +pub use rocket::http::Status; pub use rocket::response::Redirect; use rocket::Rocket; use rocket_contrib::json::JsonValue; @@ -12,7 +12,7 @@ pub mod user; #[derive(Responder)] pub enum Response { #[response()] - Ok(Option<JsonValue>), + Result(Status), #[response()] Success(JsonValue), #[response()] @@ -35,8 +35,6 @@ pub enum Response { TooManyRequests(JsonValue), #[response(status = 500)] InternalServerError(JsonValue), - #[response()] - Error(Status), } pub fn mount(rocket: Rocket) -> Rocket { diff --git a/src/routes/root.rs b/src/routes/root.rs index 14aa560cce962242d18ae7109dfb33a66e3abbd7..798d2950e7b170a13827da7b53b76a72f7a99217 100644 --- a/src/routes/root.rs +++ b/src/routes/root.rs @@ -1,10 +1,11 @@ +use super::Response; + use bson::doc; -use rocket_contrib::json::JsonValue; /// root #[get("/")] -pub fn root() -> JsonValue { - json!({ +pub fn root() -> Response { + Response::Success(json!({ "revolt": "0.0.1" - }) + })) } diff --git a/src/routes/user.rs b/src/routes/user.rs index bf94bf30b1847516e7bfae7cbb1be41fd2151258..516745b7b9e31a5ecac2351c6e6f815f3b3c0777 100644 --- a/src/routes/user.rs +++ b/src/routes/user.rs @@ -1,3 +1,4 @@ +use super::Response; use crate::database::{self, channel::Channel, user::User}; use crate::routes::channel; @@ -20,12 +21,12 @@ pub fn me(user: User) -> JsonValue { /// retrieve another user's information #[get("/<target>")] -pub fn user(user: User, target: User) -> JsonValue { - json!({ +pub fn user(user: User, target: User) -> Response { + Response::Success(json!({ "id": target.id, "username": target.username, "relationship": get_relationship(&user, &target) as u8 - }) + })) } #[derive(Serialize, Deserialize)] @@ -36,7 +37,7 @@ pub struct Query { /// lookup a user on Revolt /// currently only supports exact username searches #[post("/lookup", data = "<query>")] -pub fn lookup(user: User, query: Json<Query>) -> JsonValue { +pub fn lookup(user: User, query: Json<Query>) -> Response { let col = database::get_collection("users"); let users = col @@ -57,12 +58,12 @@ pub fn lookup(user: User, query: Json<Query>) -> JsonValue { })); } - json!(results) + Response::Success(json!(results)) } /// retrieve all of your DMs #[get("/@me/dms")] -pub fn dms(user: User) -> JsonValue { +pub fn dms(user: User) -> Response { let col = database::get_collection("channels"); let results = col @@ -95,23 +96,20 @@ pub fn dms(user: User) -> JsonValue { })); } - json!(channels) + Response::Success(json!(channels)) } /// open a DM with a user #[get("/<target>/dm")] -pub fn dm(user: User, target: User) -> JsonValue { +pub fn dm(user: User, target: User) -> Response { let col = database::get_collection("channels"); match col.find_one( doc! { "type": channel::ChannelType::DM as i32, "recipients": { "$all": [ user.id.clone(), target.id.clone() ] } }, None ).expect("Failed channel lookup") { - Some(channel) => - json!({ - "success": true, - "id": channel.get_str("_id").unwrap() - }), + Some(channel) => + Response::Success( json!({ "id": channel.get_str("_id").unwrap() })), None => { let id = Ulid::new(); @@ -125,10 +123,7 @@ pub fn dm(user: User, target: User) -> JsonValue { None ).expect("Failed insert query."); - json!({ - "success": true, - "id": id.to_string() - }) + Response::Success(json!({ "id": id.to_string() })) } } } @@ -168,7 +163,7 @@ fn get_relationship(a: &User, b: &User) -> Relationship { /// retrieve all of your friends #[get("/@me/friend")] -pub fn get_friends(user: User) -> JsonValue { +pub fn get_friends(user: User) -> Response { let mut results = Vec::new(); if let Some(arr) = user.relations { for item in arr { @@ -179,170 +174,185 @@ pub fn get_friends(user: User) -> JsonValue { } } - json!(results) + Response::Success(json!(results)) } /// retrieve friend status with user #[get("/<target>/friend")] -pub fn get_friend(user: User, target: User) -> JsonValue { +pub fn get_friend(user: User, target: User) -> Response { let relationship = get_relationship(&user, &target); - json!({ - "id": target.id, - "status": relationship as u8 - }) + Response::Success(json!({ "status": relationship as u8 })) } /// create or accept a friend request #[put("/<target>/friend")] -pub fn add_friend(user: User, target: User) -> JsonValue { +pub fn add_friend(user: User, target: User) -> Response { let col = database::get_collection("users"); let relationship = get_relationship(&user, &target); match relationship { - Relationship::FRIEND => json!({ - "success": false, - "error": "Already friends." - }), - Relationship::OUTGOING => json!({ - "success": false, - "error": "Already sent a friend request." - }), + Relationship::FRIEND => Response::BadRequest(json!({ "error": "Already friends." })), + Relationship::OUTGOING => { + Response::BadRequest(json!({ "error": "Already sent a friend request." })) + } Relationship::INCOMING => { - col.update_one( - doc! { - "_id": user.id.clone(), - "relations.id": target.id.clone() - }, - doc! { - "$set": { - "relations.$.status": Relationship::FRIEND as i32 - } - }, - None, - ) - .expect("Failed update query."); - - col.update_one( - doc! { - "_id": target.id, - "relations.id": user.id - }, - doc! { - "$set": { - "relations.$.status": Relationship::FRIEND as i32 - } - }, - None, - ) - .expect("Failed update query."); - - json!({ - "success": true, - "status": Relationship::FRIEND as u8, - }) + if col + .update_one( + doc! { + "_id": user.id.clone(), + "relations.id": target.id.clone() + }, + doc! { + "$set": { + "relations.$.status": Relationship::FRIEND as i32 + } + }, + None, + ) + .is_ok() + { + if col + .update_one( + doc! { + "_id": target.id, + "relations.id": user.id + }, + doc! { + "$set": { + "relations.$.status": Relationship::FRIEND as i32 + } + }, + None, + ) + .is_ok() + { + Response::Success(json!({ "status": Relationship::FRIEND as u8 })) + } else { + Response::InternalServerError( + json!({ "error": "Failed to commit! Try re-adding them as a friend." }), + ) + } + } else { + Response::InternalServerError( + json!({ "error": "Failed to commit to database, try again." }), + ) + } + } + Relationship::BLOCKED => { + Response::BadRequest(json!({ "error": "You have blocked this person." })) + } + Relationship::BLOCKEDOTHER => { + Response::Conflict(json!({ "error": "You have been blocked by this person." })) } - Relationship::BLOCKED => json!({ - "success": false, - "error": "You have blocked this person." - }), - Relationship::BLOCKEDOTHER => json!({ - "success": false, - "error": "You have been blocked by this person." - }), Relationship::NONE => { - col.update_one( - doc! { - "_id": user.id.clone() - }, - doc! { - "$push": { - "relations": { - "id": target.id.clone(), - "status": Relationship::OUTGOING as i32 - } - } - }, - None, - ) - .expect("Failed update query."); - - col.update_one( - doc! { - "_id": target.id - }, - doc! { - "$push": { - "relations": { - "id": user.id, - "status": Relationship::INCOMING as i32 + if col + .update_one( + doc! { + "_id": user.id.clone() + }, + doc! { + "$push": { + "relations": { + "id": target.id.clone(), + "status": Relationship::OUTGOING as i32 + } } - } - }, - None, - ) - .expect("Failed update query."); - - json!({ - "success": true, - "status": Relationship::OUTGOING as u8, - }) + }, + None, + ) + .is_ok() + { + if col + .update_one( + doc! { + "_id": target.id + }, + doc! { + "$push": { + "relations": { + "id": user.id, + "status": Relationship::INCOMING as i32 + } + } + }, + None, + ) + .is_ok() + { + Response::Success(json!({ "status": Relationship::OUTGOING as u8 })) + } else { + Response::InternalServerError( + json!({ "error": "Failed to commit! Try re-adding them as a friend." }), + ) + } + } else { + Response::InternalServerError( + json!({ "error": "Failed to commit to database, try again." }), + ) + } + } + Relationship::SELF => { + Response::BadRequest(json!({ "error": "You're already friends with yourself, no? c:" })) } - Relationship::SELF => json!({ - "success": false, - "error": "Cannot add yourself as a friend." - }), } } /// remove a friend or deny a request #[delete("/<target>/friend")] -pub fn remove_friend(user: User, target: User) -> JsonValue { +pub fn remove_friend(user: User, target: User) -> Response { let col = database::get_collection("users"); let relationship = get_relationship(&user, &target); match relationship { Relationship::FRIEND | Relationship::OUTGOING | Relationship::INCOMING => { - col.update_one( - doc! { - "_id": user.id.clone() - }, - doc! { - "$pull": { - "relations": { - "id": target.id.clone() - } - } - }, - None, - ) - .expect("Failed update query."); - - col.update_one( - doc! { - "_id": target.id - }, - doc! { - "$pull": { - "relations": { - "id": user.id + if col + .update_one( + doc! { + "_id": user.id.clone() + }, + doc! { + "$pull": { + "relations": { + "id": target.id.clone() + } } - } - }, - None, - ) - .expect("Failed update query."); - - json!({ - "success": true - }) + }, + None, + ) + .is_ok() + { + if col + .update_one( + doc! { + "_id": target.id + }, + doc! { + "$pull": { + "relations": { + "id": user.id + } + } + }, + None, + ) + .is_ok() + { + Response::Result(super::Status::Ok) + } else { + Response::InternalServerError( + json!({ "error": "Failed to commit! Target remains in same state." }), + ) + } + } else { + Response::InternalServerError( + json!({ "error": "Failed to commit to database, try again." }), + ) + } } Relationship::BLOCKED | Relationship::BLOCKEDOTHER | Relationship::NONE - | Relationship::SELF => json!({ - "success": false, - "error": "This has no effect." - }), + | Relationship::SELF => Response::BadRequest(json!({ "error": "This has no effect." })), } }