diff --git a/src/routes/channel.rs b/src/routes/channel.rs deleted file mode 100644 index 592da2a9e4cd241e5ecc59c414868d5a514a8af4..0000000000000000000000000000000000000000 --- a/src/routes/channel.rs +++ /dev/null @@ -1,688 +0,0 @@ -use super::Response; -use crate::database::{ - self, channel::Channel, get_relationship, get_relationship_internal, message::Message, - user::User, Permission, PermissionCalculator, Relationship, -}; -use crate::util::vec_to_set; - -use chrono::prelude::*; -use mongodb::bson::{doc, from_bson, Bson, Document}; -use mongodb::options::FindOptions; -use num_enum::TryFromPrimitive; -use rocket::request::Form; -use rocket_contrib::json::Json; -use rocket::futures::StreamExt; -use serde::{Deserialize, Serialize}; -use ulid::Ulid; - -const MAXGROUPSIZE: usize = 50; - -#[derive(Debug, TryFromPrimitive)] -#[repr(usize)] -pub enum ChannelType { - DM = 0, - GROUPDM = 1, - GUILDCHANNEL = 2, -} - -macro_rules! with_permissions { - ($user: expr, $target: expr) => {{ - let permissions = PermissionCalculator::new($user.clone()) - .channel($target.clone()) - .fetch_data() - .await; - - let value = permissions.as_permission().await; - if !value.get_access() { - return None; - } - - value - }}; -} - -#[derive(Serialize, Deserialize)] -pub struct CreateGroup { - name: String, - nonce: String, - users: Vec<String>, -} - -/// create a new group -#[post("/create", data = "<info>")] -pub async fn create_group(user: User, info: Json<CreateGroup>) -> Response { - let name: String = info.name.chars().take(32).collect(); - let nonce: String = info.nonce.chars().take(32).collect(); - - let mut set = vec_to_set(&info.users); - set.insert(user.id.clone()); - - if set.len() > MAXGROUPSIZE { - return Response::BadRequest(json!({ "error": "Maximum group size is 50." })); - } - - let col = database::get_collection("channels"); - if let Some(_) = col.find_one(doc! { "nonce": nonce.clone() }, None).await.unwrap() { - return Response::BadRequest(json!({ "error": "Group already created!" })); - } - - let mut query = vec![]; - for item in &set { - if item == &user.id { - continue; - } - - query.push(Bson::String(item.clone())); - } - - if let Ok(result) = database::get_collection("users").find( - doc! { - "_id": { - "$in": &query - } - }, - FindOptions::builder().limit(query.len() as i64).build(), - ).await { - if result.collect::<Vec<Result<Document, _>>>().await.len() != query.len() { - return Response::BadRequest(json!({ "error": "Specified non-existant user(s)." })); - } - - for item in set { - if item == user.id { - continue; - } - - if get_relationship_internal(&user.id, &item, &user.relations) != Relationship::Friend { - return Response::BadRequest(json!({ "error": "Not friends with user(s)." })); - } - } - - query.push(Bson::String(user.id.clone())); - - let id = Ulid::new().to_string(); - if col - .insert_one( - doc! { - "_id": id.clone(), - "nonce": nonce, - "type": ChannelType::GROUPDM as u32, - "recipients": &query, - "name": name, - "owner": &user.id, - }, - None, - ) - .await - .is_ok() - { - Response::Success(json!({ "id": id })) - } else { - Response::InternalServerError(json!({ "error": "Failed to create guild channel." })) - } - } else { - Response::InternalServerError(json!({ "error": "Failed to validate users." })) - } -} - -/// fetch channel information -#[get("/<target>")] -pub async fn channel(user: User, target: Channel) -> Option<Response> { - with_permissions!(user, target); - Some(Response::Success(target.serialise())) -} - -/// [groups] add user to channel -#[put("/<target>/recipients/<member>")] -pub async fn add_member(user: User, target: Channel, member: User) -> Option<Response> { - if target.channel_type != 1 { - return Some(Response::BadRequest(json!({ "error": "Not a group DM." }))); - } - - with_permissions!(user, target); - - let recp = target.recipients.as_ref().unwrap(); - if recp.len() == 50 { - return Some(Response::BadRequest( - json!({ "error": "Maximum group size is 50." }), - )); - } - - let set = vec_to_set(&recp); - if set.get(&member.id).is_some() { - return Some(Response::BadRequest( - json!({ "error": "User already in group!" }), - )); - } - - match get_relationship(&user, &member) { - Relationship::Friend => { - if database::get_collection("channels") - .update_one( - doc! { "_id": target.id.clone() }, - doc! { - "$push": { - "recipients": &member.id - } - }, - None, - ) - .await - .is_ok() - { - if (Message { - id: Ulid::new().to_string(), - nonce: None, - channel: target.id.clone(), - author: "system".to_string(), - content: format!("<@{}> added <@{}> to the group.", &user.id, &member.id), - edited: None, - previous_content: vec![], - }) - .send(&target) - .await - { - /*notifications::send_message_given_channel( - Notification::group_user_join(UserJoin { - id: target.id.clone(), - user: member.id.clone(), - }), - &target, FIXME - );*/ - - Some(Response::Result(super::Status::Ok)) - } else { - Some(Response::PartialStatus( - json!({ "error": "Failed to send join message, but user has been added." }), - )) - } - } else { - Some(Response::InternalServerError( - json!({ "error": "Failed to add user to group." }), - )) - } - } - _ => Some(Response::BadRequest( - json!({ "error": "Not friends with user." }), - )), - } -} - -/// [groups] remove user from channel -#[delete("/<target>/recipients/<member>")] -pub async fn remove_member(user: User, target: Channel, member: User) -> Option<Response> { - if target.channel_type != 1 { - return Some(Response::BadRequest(json!({ "error": "Not a group DM." }))); - } - - if &user.id == &member.id { - return Some(Response::BadRequest( - json!({ "error": "Cannot kick yourself, leave the channel instead." }), - )); - } - - let permissions = with_permissions!(user, target); - - if !permissions.get_kick_members() { - return Some(Response::LackingPermission(Permission::KickMembers)); - } - - let set = vec_to_set(target.recipients.as_ref().unwrap()); - if set.get(&member.id).is_none() { - return Some(Response::BadRequest( - json!({ "error": "User not in group!" }), - )); - } - - if database::get_collection("channels") - .update_one( - doc! { "_id": &target.id }, - doc! { - "$pull": { - "recipients": &member.id - } - }, - None, - ) - .await - .is_ok() - { - if (Message { - id: Ulid::new().to_string(), - nonce: None, - channel: target.id.clone(), - author: "system".to_string(), - content: format!("<@{}> removed <@{}> from the group.", &user.id, &member.id), - edited: None, - previous_content: vec![], - }) - .send(&target) - .await - { - /*notifications::send_message_given_channel( - Notification::group_user_leave(UserLeave { - id: target.id.clone(), - user: member.id.clone(), - }), - &target, FIXME - );*/ - - Some(Response::Result(super::Status::Ok)) - } else { - Some(Response::PartialStatus( - json!({ "error": "Failed to send join message, but user has been removed." }), - )) - } - } else { - Some(Response::InternalServerError( - json!({ "error": "Failed to add user to group." }), - )) - } -} - -/// delete channel -/// or leave group DM -/// or close DM conversation -#[delete("/<target>")] -pub async fn delete(user: User, target: Channel) -> Option<Response> { - let permissions = with_permissions!(user, target); - - if !permissions.get_manage_channels() { - return Some(Response::LackingPermission(Permission::ManageChannels)); - } - - let col = database::get_collection("channels"); - let target_id = target.id.clone(); - - let try_delete = async || { - let messages = database::get_collection("messages"); - - if messages - .delete_many(doc! { "channel": &target_id }, None) - .await - .is_ok() - { - if col.delete_one(doc! { "_id": &target_id }, None).await.is_ok() { - Some(Response::Result(super::Status::Ok)) - } else { - Some(Response::InternalServerError( - json!({ "error": "Failed to delete channel." }), - )) - } - } else { - Some(Response::InternalServerError( - json!({ "error": "Failed to delete messages." }), - )) - } - }; - - match target.channel_type { - 0 => { - if col - .update_one( - doc! { "_id": &target_id }, - doc! { "$set": { "active": false } }, - None, - ) - .await - .is_ok() - { - Some(Response::Result(super::Status::Ok)) - } else { - Some(Response::InternalServerError( - json!({ "error": "Failed to close channel." }), - )) - } - } - 1 => { - let mut recipients = vec_to_set( - target - .recipients - .as_ref() - .expect("Missing recipients on Group DM."), - ); - let owner = target.owner.as_ref().expect("Missing owner on Group DM."); - - if recipients.len() == 1 { - try_delete().await - } else { - recipients.remove(&user.id); - let new_owner = if owner == &user.id { - recipients.iter().next().unwrap() - } else { - &owner - }; - - if col - .update_one( - doc! { "_id": target_id }, - doc! { - "$set": { - "owner": new_owner, - }, - "$pull": { - "recipients": &user.id, - } - }, - None, - ) - .await - .is_ok() - { - if (Message { - id: Ulid::new().to_string(), - nonce: None, - channel: target.id.clone(), - author: "system".to_string(), - content: format!("<@{}> left the group.", &user.id), - edited: None, - previous_content: vec![], - }) - .send(&target) - .await - { - /*notifications::send_message_given_channel( - Notification::group_user_leave(UserLeave { - id: target.id.clone(), - user: user.id.clone(), - }), - &target, FIXME - );*/ - - Some(Response::Result(super::Status::Ok)) - } else { - Some(Response::PartialStatus( - json!({ "error": "Failed to send leave message, but you have left the group." }), - )) - } - } else { - Some(Response::InternalServerError( - json!({ "error": "Failed to remove you from the group." }), - )) - } - } - } - 2 => { - let guild_id = target.guild.unwrap(); - if database::get_collection("guilds") - .update_one( - doc! { "_id": &guild_id }, - doc! { - "$pull": { - "invites": { - "channel": &target.id - }, - "channels": &target.id - } - }, - None, - ) - .await - .is_ok() - { - /*notifications::send_message_threaded( - None, - guild_id.clone(), - Notification::guild_channel_delete(ChannelDelete { - id: guild_id.clone(), - channel: target.id.clone(), - }), FIXME - );*/ - - try_delete().await - } else { - Some(Response::InternalServerError( - json!({ "error": "Failed to remove invites." }), - )) - } - } - _ => Some(Response::InternalServerError( - json!({ "error": "Unknown error has occurred." }), - )), - } -} - -#[derive(Serialize, Deserialize, FromForm)] -pub struct MessageFetchOptions { - limit: Option<i64>, - before: Option<String>, - after: Option<String>, -} - -/// fetch channel messages -#[get("/<target>/messages?<options..>")] -pub async fn messages( - user: User, - target: Channel, - options: Form<MessageFetchOptions>, -) -> Option<Response> { - let permissions = with_permissions!(user, target); - - if !permissions.get_read_messages() { - return Some(Response::LackingPermission(Permission::ReadMessages)); - } - - // ! FIXME: update wiki to reflect changes - let mut query = doc! { "channel": target.id }; - - if let Some(before) = &options.before { - query.insert("_id", doc! { "$lt": before }); - } - - if let Some(after) = &options.after { - query.insert("_id", doc! { "$gt": after }); - } - - let limit = if let Some(limit) = options.limit { - limit.min(100).max(0) - } else { - 50 - }; - - let col = database::get_collection("messages"); - let mut result = col - .find( - query, - FindOptions::builder() - .limit(limit) - .sort(doc! { - "_id": -1 - }) - .build(), - ) - .await - .unwrap(); - - let mut messages = Vec::new(); - while let Some(item) = result.next().await { - let message: Message = - from_bson(Bson::Document(item.unwrap())).expect("Failed to unwrap message."); - messages.push(json!({ - "id": message.id, - "author": message.author, - "content": message.content, - "edited": if let Some(t) = message.edited { Some(t.timestamp()) } else { None } - })); - } - - Some(Response::Success(json!(messages))) -} - -#[derive(Serialize, Deserialize)] -pub struct SendMessage { - content: String, - nonce: String, -} - -/// send a message to a channel -#[post("/<target>/messages", data = "<message>")] -pub async fn send_message(user: User, target: Channel, message: Json<SendMessage>) -> Option<Response> { - let permissions = with_permissions!(user, target); - - if !permissions.get_send_messages() { - if target.channel_type == 0 { - return Some(Response::LackingPermission(Permission::SendDirectMessages)); - } - - return Some(Response::LackingPermission(Permission::SendMessages)); - } - - let content: String = message.content.chars().take(2000).collect(); - let nonce: String = message.nonce.chars().take(32).collect(); - - if content.len() == 0 { - return Some(Response::NotAcceptable( - json!({ "error": "No message content!" }), - )); - } - - let col = database::get_collection("messages"); - if col - .find_one(doc! { "nonce": nonce.clone() }, None) - .await - .unwrap() - .is_some() - { - return Some(Response::BadRequest( - json!({ "error": "Message already sent!" }), - )); - } - - let id = Ulid::new().to_string(); - let message = Message { - id: id.clone(), - nonce: Some(nonce), - channel: target.id.clone(), - author: user.id, - content, - edited: None, - previous_content: vec![], - }; - - if message.send(&target).await { - Some(Response::Success(json!({ "id": id }))) - } else { - Some(Response::BadRequest( - json!({ "error": "Failed to send message." }), - )) - } -} - -/// get a message -#[get("/<target>/messages/<message>")] -pub async fn get_message(user: User, target: Channel, message: Message) -> Option<Response> { - let permissions = with_permissions!(user, target); - - if !permissions.get_read_messages() { - return Some(Response::LackingPermission(Permission::ReadMessages)); - } - - // ! CHECK IF USER HAS PERMISSION TO VIEW EDITS OF MESSAGES - let mut entries = vec![]; - for entry in message.previous_content { - entries.push(json!({ - "content": entry.content, - "time": entry.time.timestamp(), - })); - } - - 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": entries, - }))) -} - -#[derive(Serialize, Deserialize)] -pub struct EditMessage { - content: String, -} - -/// edit a message -#[patch("/<target>/messages/<message>", data = "<edit>")] -pub async fn edit_message( - user: User, - target: Channel, - message: Message, - edit: Json<EditMessage>, -) -> Option<Response> { - with_permissions!(user, target); - - if message.author != user.id { - return Some(Response::Unauthorized( - json!({ "error": "You did not send this message." }), - )); - } - - let col = database::get_collection("messages"); - let time = if let Some(edited) = message.edited { - edited.0 - } else { - Ulid::from_string(&message.id).unwrap().datetime() - }; - - let edited = Utc::now(); - match col.update_one( - doc! { "_id": message.id.clone() }, - doc! { - "$set": { - "content": &edit.content, - "edited": Bson::DateTime(edited) - }, - "$push": { - "previous_content": { - "content": &message.content, - "time": time, - } - }, - }, - None, - ) - .await { - Ok(_) => { - /*notifications::send_message_given_channel( - Notification::message_edit(Edit { - id: message.id.clone(), - channel: target.id.clone(), - author: message.author.clone(), - content: edit.content.clone(), - }), - &target, FIXME - );*/ - - Some(Response::Result(super::Status::Ok)) - } - Err(_) => Some(Response::InternalServerError( - json!({ "error": "Failed to update message." }), - )), - } -} - -/// delete a message -#[delete("/<target>/messages/<message>")] -pub async fn delete_message(user: User, target: Channel, message: Message) -> Option<Response> { - let permissions = with_permissions!(user, target); - - if !permissions.get_manage_messages() && message.author != user.id { - return Some(Response::LackingPermission(Permission::ManageMessages)); - } - - let col = database::get_collection("messages"); - - match col.delete_one(doc! { "_id": &message.id }, None).await { - Ok(_) => { - /*notifications::send_message_given_channel( - Notification::message_delete(Delete { - id: message.id.clone(), - }), - &target, FIXME - );*/ - - Some(Response::Result(super::Status::Ok)) - } - Err(_) => Some(Response::InternalServerError( - json!({ "error": "Failed to delete message." }), - )), - } -} diff --git a/src/routes/channels/mod.rs b/src/routes/channels/mod.rs new file mode 100644 index 0000000000000000000000000000000000000000..9a5378acc6a6de07d35b1c9796f88801f844f3d0 --- /dev/null +++ b/src/routes/channels/mod.rs @@ -0,0 +1,5 @@ +use rocket::Route; + +pub fn routes() -> Vec<Route> { + routes! [] +} diff --git a/src/routes/guild.rs b/src/routes/guild.rs deleted file mode 100644 index 4ab993a1ca8605c605fe131f82a67cf1da636911..0000000000000000000000000000000000000000 --- a/src/routes/guild.rs +++ /dev/null @@ -1,818 +0,0 @@ -use super::channel::ChannelType; -use super::Response; -use crate::database::guild::{fetch_member as get_member, get_invite, Guild, MemberKey}; -use crate::database::{ - self, channel::fetch_channel, channel::Channel, guild::serialise_guilds_with_channels, - user::User, Permission, PermissionCalculator, -}; -use crate::util::gen_token; - -use mongodb::bson::{doc, Bson}; -use mongodb::options::{FindOneOptions, FindOptions}; -use rocket::request::Form; -use rocket_contrib::json::Json; -use serde::{Deserialize, Serialize}; -use rocket::futures::StreamExt; -use ulid::Ulid; - -// ! FIXME: GET RID OF THIS -macro_rules! with_permissions { - ($user: expr, $target: expr) => {{ - let permissions = PermissionCalculator::new($user.clone()) - .guild($target.clone()) - .fetch_data() - .await; - - let value = permissions.as_permission().await; - if !value.get_access() { - return None; - } - - (value, permissions.member.unwrap()) - }}; -} - -/// fetch your guilds -#[get("/@me")] -pub async fn my_guilds(user: User) -> Response { - if let Ok(gids) = user.find_guilds().await { - if let Ok(data) = serialise_guilds_with_channels(&gids).await { - Response::Success(json!(data)) - } else { - Response::InternalServerError(json!({ "error": "Failed to fetch guilds." })) - } - } else { - Response::InternalServerError(json!({ "error": "Failed to fetch memberships." })) - } -} - -/// fetch a guild -#[get("/<target>")] -pub async fn guild(user: User, target: Guild) -> Option<Response> { - with_permissions!(user, target); - - if let Ok(result) = target.seralise_with_channels().await { - Some(Response::Success(result)) - } else { - Some(Response::InternalServerError( - json!({ "error": "Failed to fetch channels!" }), - )) - } -} - -/// delete or leave a guild -#[delete("/<target>")] -pub async fn remove_guild(user: User, target: Guild) -> Option<Response> { - with_permissions!(user, target); - - if user.id == target.owner { - let channels = database::get_collection("channels"); - if let Ok(mut result) = channels.find( - doc! { - "type": 2, - "guild": &target.id - }, - FindOptions::builder().projection(doc! { "_id": 1 }).build(), - ).await { - let mut values = vec![]; - while let Some(item) = result.next().await { - if let Ok(doc) = item { - values.push(Bson::String(doc.get_str("_id").unwrap().to_string())); - } - } - - if database::get_collection("messages") - .delete_many( - doc! { - "channel": { - "$in": values - } - }, - None, - ) - .await - .is_ok() - { - if channels - .delete_many( - doc! { - "type": 2, - "guild": &target.id, - }, - None, - ) - .await - .is_ok() - { - if database::get_collection("members") - .delete_many( - doc! { - "_id.guild": &target.id, - }, - None, - ) - .await - .is_ok() - { - if database::get_collection("guilds") - .delete_one( - doc! { - "_id": &target.id - }, - None, - ) - .await - .is_ok() - { - /*notifications::send_message_threaded( - None, - target.id.clone(), - Notification::guild_delete(Delete { - id: target.id.clone(), - }), FIXME - );*/ - - Some(Response::Result(super::Status::Ok)) - } else { - Some(Response::InternalServerError( - json!({ "error": "Failed to delete guild." }), - )) - } - } else { - Some(Response::InternalServerError( - json!({ "error": "Failed to delete guild members." }), - )) - } - } else { - Some(Response::InternalServerError( - json!({ "error": "Failed to delete guild channels." }), - )) - } - } else { - Some(Response::InternalServerError( - json!({ "error": "Failed to delete guild messages." }), - )) - } - } else { - Some(Response::InternalServerError( - json!({ "error": "Could not fetch channels." }), - )) - } - } else if database::get_collection("members") - .delete_one( - doc! { - "_id.guild": &target.id, - "_id.user": &user.id, - }, - None, - ) - .await - .is_ok() - { - /*notifications::send_message_threaded( - None, - target.id.clone(), - Notification::guild_user_leave(UserLeave { - id: target.id.clone(), - user: user.id.clone(), - banned: false, - }), FIXME - );*/ - - Some(Response::Result(super::Status::Ok)) - } else { - Some(Response::InternalServerError( - json!({ "error": "Failed to remove you from the guild." }), - )) - } -} - -#[derive(Serialize, Deserialize)] -pub struct CreateChannel { - nonce: String, - name: String, - description: Option<String>, -} - -/// create a new channel -#[post("/<target>/channels", data = "<info>")] -pub async fn create_channel(user: User, target: Guild, info: Json<CreateChannel>) -> Option<Response> { - let (permissions, _) = with_permissions!(user, target); - - if !permissions.get_manage_channels() { - return Some(Response::LackingPermission(Permission::ManageChannels)); - } - - let nonce: String = info.nonce.chars().take(32).collect(); - let name: String = info.name.chars().take(32).collect(); - let description: String = info - .description - .clone() - .unwrap_or(String::new()) - .chars() - .take(255) - .collect(); - - if let Ok(result) = - database::get_collection("channels").find_one(doc! { "nonce": &nonce }, None) - .await - { - if result.is_some() { - return Some(Response::BadRequest( - json!({ "error": "Channel already created." }), - )); - } - - let id = Ulid::new().to_string(); - if database::get_collection("channels") - .insert_one( - doc! { - "_id": &id, - "nonce": &nonce, - "type": 2, - "guild": &target.id, - "name": &name, - "description": &description, - }, - None, - ) - .await - .is_ok() - { - if database::get_collection("guilds") - .update_one( - doc! { - "_id": &target.id - }, - doc! { - "$addToSet": { - "channels": &id - } - }, - None, - ) - .await - .is_ok() - { - /*notifications::send_message_threaded( - None, - target.id.clone(), - Notification::guild_channel_create(ChannelCreate { - id: target.id.clone(), - channel: id.clone(), - name: name.clone(), - description: description.clone(), - }), FIXME - );*/ - - Some(Response::Success(json!({ "id": &id }))) - } else { - Some(Response::InternalServerError( - json!({ "error": "Couldn't save channel list." }), - )) - } - } else { - Some(Response::InternalServerError( - json!({ "error": "Couldn't create channel." }), - )) - } - } else { - Some(Response::BadRequest( - json!({ "error": "Failed to check if channel was made." }), - )) - } -} - -#[derive(Serialize, Deserialize)] -pub struct InviteOptions { - // ? TODO: add options -} - -/// create a new invite -#[post("/<target>/channels/<channel>/invite", data = "<_options>")] -pub async fn create_invite( - user: User, - target: Guild, - channel: Channel, - _options: Json<InviteOptions>, -) -> Option<Response> { - let (permissions, _) = with_permissions!(user, target); - - if !permissions.get_create_invite() { - return Some(Response::LackingPermission(Permission::CreateInvite)); - } - - let code = gen_token(7); - if database::get_collection("guilds") - .update_one( - doc! { "_id": target.id }, - doc! { - "$push": { - "invites": { - "code": &code, - "creator": user.id, - "channel": channel.id, - } - } - }, - None, - ) - .await - .is_ok() - { - Some(Response::Success(json!({ "code": code }))) - } else { - Some(Response::BadRequest( - json!({ "error": "Failed to create invite." }), - )) - } -} - -/// remove an invite -#[delete("/<target>/invites/<code>")] -pub async fn remove_invite(user: User, target: Guild, code: String) -> Option<Response> { - let (permissions, _) = with_permissions!(user, target); - - if let Some((guild_id, _, invite)) = get_invite(&code, None).await { - if invite.creator != user.id && !permissions.get_manage_server() { - return Some(Response::LackingPermission(Permission::ManageServer)); - } - - if database::get_collection("guilds") - .update_one( - doc! { - "_id": &guild_id, - }, - doc! { - "$pull": { - "invites": { - "code": &code - } - } - }, - None, - ) - .await - .is_ok() - { - Some(Response::Result(super::Status::Ok)) - } else { - Some(Response::BadRequest( - json!({ "error": "Failed to delete invite." }), - )) - } - } else { - Some(Response::NotFound( - json!({ "error": "Failed to fetch invite or code is invalid." }), - )) - } -} - -/// fetch all guild invites -#[get("/<target>/invites")] -pub async fn fetch_invites(user: User, target: Guild) -> Option<Response> { - let (permissions, _) = with_permissions!(user, target); - - if !permissions.get_manage_server() { - return Some(Response::LackingPermission(Permission::ManageServer)); - } - - Some(Response::Success(json!(target.invites))) -} - -/// view an invite before joining -#[get("/join/<code>", rank = 1)] -pub async fn fetch_invite(user: User, code: String) -> Response { - if let Some((guild_id, name, invite)) = get_invite(&code, user.id).await { - match fetch_channel(&invite.channel).await { - Ok(result) => { - if let Some(channel) = result { - Response::Success(json!({ - "guild": { - "id": guild_id, - "name": name, - }, - "channel": { - "id": channel.id, - "name": channel.name, - } - })) - } else { - Response::NotFound(json!({ "error": "Channel does not exist." })) - } - } - Err(err) => Response::InternalServerError(json!({ "error": err })), - } - } else { - Response::NotFound(json!({ "error": "Failed to fetch invite or code is invalid." })) - } -} - -/// join a guild using an invite -#[post("/join/<code>", rank = 1)] -pub async fn use_invite(user: User, code: String) -> Response { - if let Some((guild_id, _, invite)) = get_invite(&code, Some(user.id.clone())).await { - if let Ok(result) = database::get_collection("members").find_one( - doc! { - "_id.guild": &guild_id, - "_id.user": &user.id - }, - FindOneOptions::builder() - .projection(doc! { "_id": 1 }) - .build(), - ) - .await { - if result.is_none() { - if database::get_collection("members") - .insert_one( - doc! { - "_id": { - "guild": &guild_id, - "user": &user.id - } - }, - None, - ) - .await - .is_ok() - { - /*notifications::send_message_threaded( - None, - guild_id.clone(), - Notification::guild_user_join(UserJoin { - id: guild_id.clone(), - user: user.id.clone(), - }), FIXME - );*/ - - Response::Success(json!({ - "guild": &guild_id, - "channel": &invite.channel, - })) - } else { - Response::InternalServerError( - json!({ "error": "Failed to add you to the guild." }), - ) - } - } else { - Response::BadRequest(json!({ "error": "Already in the guild." })) - } - } else { - Response::InternalServerError( - json!({ "error": "Failed to check if you're in the guild." }), - ) - } - } else { - Response::NotFound(json!({ "error": "Failed to fetch invite or code is invalid." })) - } -} - -#[derive(Serialize, Deserialize)] -pub struct CreateGuild { - name: String, - description: Option<String>, - nonce: String, -} - -/// create a new guild -#[post("/create", data = "<info>")] -pub async fn create_guild(user: User, info: Json<CreateGuild>) -> Response { - if !user.email_verification.verified { - return Response::Unauthorized(json!({ "error": "Email not verified!" })); - } - - let name: String = info.name.chars().take(32).collect(); - let description: String = info - .description - .clone() - .unwrap_or("No description.".to_string()) - .chars() - .take(255) - .collect(); - let nonce: String = info.nonce.chars().take(32).collect(); - - let channels = database::get_collection("channels"); - let col = database::get_collection("guilds"); - if col - .find_one(doc! { "nonce": nonce.clone() }, None) - .await - .unwrap() - .is_some() - { - return Response::BadRequest(json!({ "error": "Guild already created!" })); - } - - let id = Ulid::new().to_string(); - let channel_id = Ulid::new().to_string(); - if channels - .insert_one( - doc! { - "_id": channel_id.clone(), - "type": ChannelType::GUILDCHANNEL as u32, - "name": "general", - "description": "", - "guild": id.clone(), - }, - None, - ) - .await - .is_err() - { - return Response::InternalServerError( - json!({ "error": "Failed to create guild channel." }), - ); - } - - if database::get_collection("members") - .insert_one( - doc! { - "_id": { - "guild": &id, - "user": &user.id - } - }, - None, - ) - .await - .is_err() - { - return Response::InternalServerError( - json!({ "error": "Failed to add you to members list." }), - ); - } - - if col - .insert_one( - doc! { - "_id": &id, - "nonce": nonce, - "name": name, - "description": description, - "owner": &user.id, - "channels": [ channel_id.clone() ], - "invites": [], - "bans": [], - "default_permissions": 51, - }, - None, - ) - .await - .is_ok() - { - Response::Success(json!({ "id": id })) - } else { - channels - .delete_one(doc! { "_id": channel_id }, None) - .await - .expect("Failed to delete the channel we just made."); - - Response::InternalServerError(json!({ "error": "Failed to create guild." })) - } -} - -/// fetch a guild's member -#[get("/<target>/members")] -pub async fn fetch_members(user: User, target: Guild) -> Option<Response> { - with_permissions!(user, target); - - if let Ok(mut result) = - database::get_collection("members").find(doc! { "_id.guild": target.id }, None) - .await - { - let mut users = vec![]; - - while let Some(item) = result.next().await { - if let Ok(doc) = item { - users.push(json!({ - "id": doc.get_document("_id").unwrap().get_str("user").unwrap(), - "nickname": doc.get_str("nickname").ok(), - })); - } - } - - Some(Response::Success(json!(users))) - } else { - Some(Response::InternalServerError( - json!({ "error": "Failed to fetch members." }), - )) - } -} - -/// fetch a guild member -#[get("/<target>/members/<other>")] -pub async fn fetch_member(user: User, target: Guild, other: String) -> Option<Response> { - with_permissions!(user, target); - - if let Ok(result) = get_member(MemberKey(target.id, other)).await { - if let Some(member) = result { - Some(Response::Success(json!({ - "id": member.id.user, - "nickname": member.nickname, - }))) - } else { - Some(Response::NotFound( - json!({ "error": "Member does not exist!" }), - )) - } - } else { - Some(Response::InternalServerError( - json!({ "error": "Failed to fetch member." }), - )) - } -} - -/// kick a guild member -#[delete("/<target>/members/<other>")] -pub async fn kick_member(user: User, target: Guild, other: String) -> Option<Response> { - let (permissions, _) = with_permissions!(user, target); - - if user.id == other { - return Some(Response::BadRequest( - json!({ "error": "Cannot kick yourself." }), - )); - } - - if !permissions.get_kick_members() { - return Some(Response::LackingPermission(Permission::KickMembers)); - } - - if let Ok(result) = get_member(MemberKey(target.id.clone(), other.clone())).await { - if result.is_none() { - return Some(Response::BadRequest( - json!({ "error": "User not part of guild." }), - )); - } - } else { - return Some(Response::InternalServerError( - json!({ "error": "Failed to fetch member." }), - )); - } - - if database::get_collection("members") - .delete_one( - doc! { - "_id.guild": &target.id, - "_id.user": &other, - }, - None, - ) - .await - .is_ok() - { - /*notifications::send_message_threaded( - None, - target.id.clone(), - Notification::guild_user_leave(UserLeave { - id: target.id.clone(), - user: other.clone(), - banned: false, - }), FIXME - );*/ - - Some(Response::Result(super::Status::Ok)) - } else { - Some(Response::InternalServerError( - json!({ "error": "Failed to kick member." }), - )) - } -} - -#[derive(Serialize, Deserialize, FromForm)] -pub struct BanOptions { - reason: Option<String>, -} - -/// ban a guild member -#[put("/<target>/members/<other>/ban?<options..>")] -pub async fn ban_member( - user: User, - target: Guild, - other: String, - options: Form<BanOptions>, -) -> Option<Response> { - let (permissions, _) = with_permissions!(user, target); - let reason: String = options - .reason - .clone() - .unwrap_or("No reason specified.".to_string()) - .chars() - .take(64) - .collect(); - - if user.id == other { - return Some(Response::BadRequest( - json!({ "error": "Cannot ban yourself." }), - )); - } - - if !permissions.get_ban_members() { - return Some(Response::LackingPermission(Permission::BanMembers)); - } - - if let Ok(result) = get_member(MemberKey(target.id.clone(), other.clone())).await { - if result.is_none() { - return Some(Response::BadRequest( - json!({ "error": "User not part of guild." }), - )); - } - } else { - return Some(Response::InternalServerError( - json!({ "error": "Failed to fetch member." }), - )); - } - - if database::get_collection("guilds") - .update_one( - doc! { "_id": &target.id }, - doc! { - "$push": { - "bans": { - "id": &other, - "reason": reason, - } - } - }, - None, - ) - .await - .is_err() - { - return Some(Response::BadRequest( - json!({ "error": "Failed to add ban to guild." }), - )); - } - - if database::get_collection("members") - .delete_one( - doc! { - "_id.guild": &target.id, - "_id.user": &other, - }, - None, - ) - .await - .is_ok() - { - /*notifications::send_message_threaded( - None, - target.id.clone(), - Notification::guild_user_leave(UserLeave { - id: target.id.clone(), - user: other.clone(), - banned: true, - }), FIXME - );*/ - - Some(Response::Result(super::Status::Ok)) - } else { - Some(Response::InternalServerError( - json!({ "error": "Failed to kick member after adding to ban list." }), - )) - } -} - -/// unban a guild member -#[delete("/<target>/members/<other>/ban")] -pub async fn unban_member(user: User, target: Guild, other: String) -> Option<Response> { - let (permissions, _) = with_permissions!(user, target); - - if user.id == other { - return Some(Response::BadRequest( - json!({ "error": "Cannot unban yourself (not checking if you're banned)." }), - )); - } - - if !permissions.get_ban_members() { - return Some(Response::LackingPermission(Permission::BanMembers)); - } - - if target.bans.iter().any(|v| v.id == other) { - return Some(Response::BadRequest(json!({ "error": "User not banned." }))); - } - - if database::get_collection("guilds") - .update_one( - doc! { - "_id": &target.id - }, - doc! { - "$pull": { - "bans": { - "$elemMatch": { - "id": &other - } - } - } - }, - None, - ) - .await - .is_ok() - { - Some(Response::Result(super::Status::Ok)) - } else { - Some(Response::BadRequest( - json!({ "error": "Failed to remove ban." }), - )) - } -} diff --git a/src/routes/guild/mod.rs b/src/routes/guild/mod.rs new file mode 100644 index 0000000000000000000000000000000000000000..9a5378acc6a6de07d35b1c9796f88801f844f3d0 --- /dev/null +++ b/src/routes/guild/mod.rs @@ -0,0 +1,5 @@ +use rocket::Route; + +pub fn routes() -> Vec<Route> { + routes! [] +} diff --git a/src/routes/mod.rs b/src/routes/mod.rs index 07c2b91bb8e1dc8c70daf7bdd80133a2eb748d95..c5bc6063f05a3634d168a85e7658515b9971372e 100644 --- a/src/routes/mod.rs +++ b/src/routes/mod.rs @@ -2,71 +2,20 @@ pub use rocket::http::Status; pub use rocket::response::Redirect; use rocket::Rocket; -// use crate::database::Permission; -// use rocket_contrib::json::JsonValue; - -/* pub mod channel; -pub mod guild; -pub mod user; */ -pub mod root; - -/* #[derive(Responder)] -pub enum Response { - #[response()] - Result(Status), - #[response()] - Success(JsonValue), - #[response()] - Redirect(Redirect), - #[response(status = 207)] - PartialStatus(JsonValue), - #[response(status = 400)] - BadRequest(JsonValue), - #[response(status = 401)] - Unauthorized(JsonValue), - #[response(status = 401)] - LackingPermission(Permission), - #[response(status = 404)] - NotFound(JsonValue), - #[response(status = 406)] - NotAcceptable(JsonValue), - #[response(status = 409)] - Conflict(JsonValue), - #[response(status = 410)] - Gone(JsonValue), - #[response(status = 418)] - Teapot(JsonValue), - #[response(status = 422)] - UnprocessableEntity(JsonValue), - #[response(status = 429)] - TooManyRequests(JsonValue), - #[response(status = 500)] - InternalServerError(JsonValue), -} - -use rocket::http::ContentType; -use rocket::request::Request; -use std::io::Cursor; - -use rocket::response::{Responder, Result}; - -impl<'a> Responder<'a, 'static> for Permission { - fn respond_to(self, _: &Request) -> Result<'static> { - let body = format!( - "{{\"error\":\"Lacking permission: {:?}.\",\"permission\":{}}}", - self, self as u32, - ); - - rocket::response::Response::build() - .header(ContentType::JSON) - .sized_body(body.len(), Cursor::new(body)) - .ok() - } -} */ +mod root; +mod users; +mod guild; +mod onboard; +mod channels; pub fn mount(rocket: Rocket) -> Rocket { rocket .mount("/", routes![root::root, root::teapot]) + .mount("/onboard", onboard::routes()) + .mount("/users", users::routes()) + .mount("/channels", channels::routes()) + .mount("/guild", guild::routes()) + /*.mount( "/users", routes![ diff --git a/src/routes/onboard/hello.rs b/src/routes/onboard/hello.rs new file mode 100644 index 0000000000000000000000000000000000000000..ecf5847782f14c40669f0d78bf0fcbae4b9e2da8 --- /dev/null +++ b/src/routes/onboard/hello.rs @@ -0,0 +1,7 @@ +use crate::util::result::Result; +use rauth::auth::Session; + +#[get("/hello")] +pub async fn req(session: Session) -> Result<String> { + Ok("try onboard user".to_string()) +} diff --git a/src/routes/onboard/mod.rs b/src/routes/onboard/mod.rs new file mode 100644 index 0000000000000000000000000000000000000000..74216aba9b2b3da618379599576133e637105be6 --- /dev/null +++ b/src/routes/onboard/mod.rs @@ -0,0 +1,9 @@ +use rocket::Route; + +mod hello; + +pub fn routes() -> Vec<Route> { + routes! [ + hello::req + ] +} diff --git a/src/routes/user.rs b/src/routes/user.rs deleted file mode 100644 index e464e82fb21659f99029f007167e0297e578bee0..0000000000000000000000000000000000000000 --- a/src/routes/user.rs +++ /dev/null @@ -1,752 +0,0 @@ -use super::Response; -use crate::database::{ - self, get_relationship, get_relationship_internal, user::User, Relationship, -}; -use crate::routes::channel; - -use mongodb::bson::doc; -use mongodb::options::{Collation, FindOneOptions, FindOptions}; -use rocket_contrib::json::Json; -use serde::{Deserialize, Serialize}; -use rocket::futures::StreamExt; -use ulid::Ulid; - -/// retrieve your user information -#[get("/@me")] -pub async fn me(user: User) -> Response { - Response::Success(user.serialise(Relationship::SELF as i32)) -} - -/// retrieve another user's information -#[get("/<target>")] -pub async fn user(user: User, target: User) -> Response { - let relationship = get_relationship(&user, &target) as i32; - Response::Success(user.serialise(relationship)) -} - -#[derive(Serialize, Deserialize)] -pub struct UserQuery { - username: String, -} - -/// find a user by their username -#[post("/query", data = "<query>")] -pub async fn query(user: User, query: Json<UserQuery>) -> Response { - let col = database::get_collection("users"); - - if let Ok(result) = col.find_one( - doc! { "username": query.username.clone() }, - FindOneOptions::builder() - .collation(Collation::builder().locale("en").strength(2).build()) - .build(), - ) - .await { - if let Some(doc) = result { - let id = doc.get_str("_id").unwrap(); - Response::Success(json!({ - "id": id, - "username": doc.get_str("username").unwrap(), - "display_name": doc.get_str("display_name").unwrap(), - "relationship": get_relationship_internal(&user.id, &id, &user.relations) as i32 - })) - } else { - Response::NotFound(json!({ - "error": "User not found!" - })) - } - } else { - Response::InternalServerError(json!({ "error": "Failed database query." })) - } -} - -/*#[derive(Serialize, Deserialize)] -pub struct LookupQuery { - username: String, -} - -/// lookup a user on Revolt -/// currently only supports exact username searches -#[post("/lookup", data = "<query>")] -pub fn lookup(user: User, query: Json<LookupQuery>) -> Response { - let relationships = user.fetch_relationships(); - let col = database::get_collection("users"); - - if let Ok(users) = col.find( - doc! { "username": query.username.clone() }, - FindOptions::builder() - .projection(doc! { "_id": 1, "username": 1 }) - .limit(10) - .build(), - ) { - let mut results = Vec::new(); - for item in users { - if let Ok(doc) = item { - let id = doc.get_str("id").unwrap(); - results.push(json!({ - "id": id, - "username": doc.get_str("username").unwrap(), - "relationship": get_relationship_internal(&user.id, &id, &relationships) as i32 - })); - } - } - - Response::Success(json!(results)) - } else { - Response::InternalServerError(json!({ "error": "Failed database query." })) - } -}*/ - -/// retrieve all of your DMs -#[get("/@me/dms")] -pub async fn dms(user: User) -> Response { - let col = database::get_collection("channels"); - - if let Ok(mut results) = col.find( - doc! { - "$or": [ - { - "type": channel::ChannelType::DM as i32, - "active": true - }, - { - "type": channel::ChannelType::GROUPDM as i32 - } - ], - "recipients": user.id - }, - FindOptions::builder().projection(doc! {}).build(), - ) - .await { - let mut channels = Vec::new(); - while let Some(item) = results.next().await { - if let Ok(doc) = item { - let id = doc.get_str("_id").unwrap(); - let last_message = doc.get_document("last_message").unwrap(); - let recipients = doc.get_array("recipients").unwrap(); - - match doc.get_i32("type").unwrap() { - 0 => { - channels.push(json!({ - "id": id, - "type": 0, - "last_message": last_message, - "recipients": recipients, - })); - } - 1 => { - channels.push(json!({ - "id": id, - "type": 1, - "recipients": recipients, - "name": doc.get_str("name").unwrap(), - "owner": doc.get_str("owner").unwrap(), - "description": doc.get_str("description").unwrap_or(""), - })); - } - _ => unreachable!(), - } - } - } - - Response::Success(json!(channels)) - } else { - Response::InternalServerError(json!({ "error": "Failed database query." })) - } -} - -/// open a DM with a user -#[get("/<target>/dm")] -pub async fn dm(user: User, target: User) -> Response { - let col = database::get_collection("channels"); - - if let Ok(result) = col.find_one( - doc! { "type": channel::ChannelType::DM as i32, "recipients": { "$all": [ user.id.clone(), target.id.clone() ] } }, - None - ) - .await { - if let Some(channel) = result { - Response::Success( json!({ "id": channel.get_str("_id").unwrap() })) - } else { - let id = Ulid::new(); - - if col.insert_one( - doc! { - "_id": id.to_string(), - "type": channel::ChannelType::DM as i32, - "recipients": [ user.id, target.id ], - "active": false - }, - None - ) - .await - .is_ok() { - Response::Success(json!({ "id": id.to_string() })) - } else { - Response::InternalServerError(json!({ "error": "Failed to create new channel." })) - } - } - } else { - Response::InternalServerError(json!({ "error": "Failed server query." })) - } -} - -/// retrieve all of your friends -#[get("/@me/friend")] -pub async fn get_friends(user: User) -> Response { - let mut results = Vec::new(); - if let Some(arr) = user.relations { - for item in arr { - results.push(json!({ - "id": item.id, - "status": item.status - })) - } - } - - Response::Success(json!(results)) -} - -/// retrieve friend status with user -#[get("/<target>/friend")] -pub async fn get_friend(user: User, target: User) -> Response { - Response::Success(json!({ "status": get_relationship(&user, &target) as i32 })) -} - -/// create or accept a friend request -#[put("/<target>/friend")] -pub async fn add_friend(user: User, target: User) -> Response { - let col = database::get_collection("users"); - - match get_relationship(&user, &target) { - Relationship::Friend => Response::BadRequest(json!({ "error": "Already friends." })), - Relationship::Outgoing => { - Response::BadRequest(json!({ "error": "Already sent a friend request." })) - } - Relationship::Incoming => { - if col - .update_one( - doc! { - "_id": user.id.clone(), - "relations.id": target.id.clone() - }, - doc! { - "$set": { - "relations.$.status": Relationship::Friend as i32 - } - }, - None, - ) - .await - .is_ok() - { - if col - .update_one( - doc! { - "_id": target.id.clone(), - "relations.id": user.id.clone() - }, - doc! { - "$set": { - "relations.$.status": Relationship::Friend as i32 - } - }, - None, - ) - .await - .is_ok() - { - /*notifications::send_message_threaded( - vec![target.id.clone()], - None, - Notification::user_friend_status(FriendStatus { - id: target.id.clone(), - user: user.id.clone(), - status: Relationship::Friend as i32, - }), - ); - - notifications::send_message_threaded( - vec![user.id.clone()], - None, - Notification::user_friend_status(FriendStatus { - id: user.id.clone(), - user: target.id.clone(), - status: Relationship::Friend as i32, - }), FIXME - );*/ - - Response::Success(json!({ "status": Relationship::Friend as i32 })) - } 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::NONE => { - if col - .update_one( - doc! { - "_id": user.id.clone() - }, - doc! { - "$push": { - "relations": { - "id": target.id.clone(), - "status": Relationship::Outgoing as i32 - } - } - }, - None, - ) - .await - .is_ok() - { - if col - .update_one( - doc! { - "_id": target.id.clone() - }, - doc! { - "$push": { - "relations": { - "id": user.id.clone(), - "status": Relationship::Incoming as i32 - } - } - }, - None, - ) - .await - .is_ok() - { - /*notifications::send_message_threaded( - vec![user.id.clone()], - None, - Notification::user_friend_status(FriendStatus { - id: user.id.clone(), - user: target.id.clone(), - status: Relationship::Outgoing as i32, - }), - ); - - notifications::send_message_threaded( - vec![target.id.clone()], - None, - Notification::user_friend_status(FriendStatus { - id: target.id.clone(), - user: user.id.clone(), - status: Relationship::Incoming as i32, - }), FIXME - );*/ - - Response::Success(json!({ "status": Relationship::Outgoing as i32 })) - } 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:" })) - } - } -} - -/// remove a friend or deny a request -#[delete("/<target>/friend")] -pub async fn remove_friend(user: User, target: User) -> Response { - let col = database::get_collection("users"); - - match get_relationship(&user, &target) { - Relationship::Friend | Relationship::Outgoing | Relationship::Incoming => { - if col - .update_one( - doc! { - "_id": user.id.clone() - }, - doc! { - "$pull": { - "relations": { - "id": target.id.clone() - } - } - }, - None, - ) - .await - .is_ok() - { - if col - .update_one( - doc! { - "_id": target.id.clone() - }, - doc! { - "$pull": { - "relations": { - "id": user.id.clone() - } - } - }, - None, - ) - .await - .is_ok() - { - /*notifications::send_message_threaded( - vec![user.id.clone()], - None, - Notification::user_friend_status(FriendStatus { - id: user.id.clone(), - user: target.id.clone(), - status: Relationship::NONE as i32, - }), - ); - - notifications::send_message_threaded( - vec![target.id.clone()], - None, - Notification::user_friend_status(FriendStatus { - id: target.id.clone(), - user: user.id.clone(), - status: Relationship::NONE as i32, - }), FIXME - );*/ - - Response::Success(json!({ "status": Relationship::NONE as i32 })) - } 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 => Response::BadRequest(json!({ "error": "This has no effect." })), - } -} - -/// block a user -#[put("/<target>/block")] -pub async fn block_user(user: User, target: User) -> Response { - let col = database::get_collection("users"); - - match get_relationship(&user, &target) { - Relationship::Friend | Relationship::Incoming | Relationship::Outgoing => { - if col - .update_one( - doc! { - "_id": user.id.clone(), - "relations.id": target.id.clone() - }, - doc! { - "$set": { - "relations.$.status": Relationship::Blocked as i32 - } - }, - None, - ) - .await - .is_ok() - { - if col - .update_one( - doc! { - "_id": target.id.clone(), - "relations.id": user.id.clone() - }, - doc! { - "$set": { - "relations.$.status": Relationship::BlockedOther as i32 - } - }, - None, - ) - .await - .is_ok() - { - /*notifications::send_message_threaded( - vec![user.id.clone()], - None, - Notification::user_friend_status(FriendStatus { - id: user.id.clone(), - user: target.id.clone(), - status: Relationship::Blocked as i32, - }), - ); - - notifications::send_message_threaded( - vec![target.id.clone()], - None, - Notification::user_friend_status(FriendStatus { - id: target.id.clone(), - user: user.id.clone(), - status: Relationship::BlockedOther as i32, - }), FIXME - );*/ - - Response::Success(json!({ "status": Relationship::Blocked as i32 })) - } else { - Response::InternalServerError( - json!({ "error": "Failed to commit! Try blocking the user again, remove it first." }), - ) - } - } else { - Response::InternalServerError( - json!({ "error": "Failed to commit to database, try again." }), - ) - } - } - - Relationship::NONE => { - if col - .update_one( - doc! { - "_id": user.id.clone(), - }, - doc! { - "$push": { - "relations": { - "id": target.id.clone(), - "status": Relationship::Blocked as i32, - } - } - }, - None, - ) - .await - .is_ok() - { - if col - .update_one( - doc! { - "_id": target.id.clone(), - }, - doc! { - "$push": { - "relations": { - "id": user.id.clone(), - "status": Relationship::BlockedOther as i32, - } - } - }, - None, - ) - .await - .is_ok() - { - /*notifications::send_message_threaded( - vec![user.id.clone()], - None, - Notification::user_friend_status(FriendStatus { - id: user.id.clone(), - user: target.id.clone(), - status: Relationship::Blocked as i32, - }), - ); - - notifications::send_message_threaded( - vec![target.id.clone()], - None, - Notification::user_friend_status(FriendStatus { - id: target.id.clone(), - user: user.id.clone(), - status: Relationship::BlockedOther as i32, - }), FIXME - );*/ - - Response::Success(json!({ "status": Relationship::Blocked as i32 })) - } else { - Response::InternalServerError( - json!({ "error": "Failed to commit! Try blocking the user again, remove it first." }), - ) - } - } else { - Response::InternalServerError( - json!({ "error": "Failed to commit to database, try again." }), - ) - } - } - Relationship::Blocked => { - Response::BadRequest(json!({ "error": "Already blocked this person." })) - } - Relationship::BlockedOther => { - if col - .update_one( - doc! { - "_id": user.id.clone(), - "relations.id": target.id.clone() - }, - doc! { - "$set": { - "relations.$.status": Relationship::Blocked as i32 - } - }, - None, - ) - .await - .is_ok() - { - /*notifications::send_message_threaded( - vec![user.id.clone()], - None, - Notification::user_friend_status(FriendStatus { - id: user.id.clone(), - user: target.id.clone(), - status: Relationship::Blocked as i32, - }), FIXME - );*/ - - Response::Success(json!({ "status": Relationship::Blocked as i32 })) - } else { - Response::InternalServerError( - json!({ "error": "Failed to commit to database, try again." }), - ) - } - } - Relationship::SELF => Response::BadRequest(json!({ "error": "This has no effect." })), - } -} - -/// unblock a user -#[delete("/<target>/block")] -pub async fn unblock_user(user: User, target: User) -> Response { - let col = database::get_collection("users"); - - match get_relationship(&user, &target) { - Relationship::Blocked => match get_relationship(&target, &user) { - Relationship::Blocked => { - if col - .update_one( - doc! { - "_id": user.id.clone(), - "relations.id": target.id.clone() - }, - doc! { - "$set": { - "relations.$.status": Relationship::BlockedOther as i32 - } - }, - None, - ) - .await - .is_ok() - { - /*notifications::send_message_threaded( - vec![user.id.clone()], - None, - Notification::user_friend_status(FriendStatus { - id: user.id.clone(), - user: target.id.clone(), - status: Relationship::BlockedOther as i32, - }), FIXME - );*/ - - Response::Success(json!({ "status": Relationship::BlockedOther as i32 })) - } else { - Response::InternalServerError( - json!({ "error": "Failed to commit to database, try again." }), - ) - } - } - Relationship::BlockedOther => { - if col - .update_one( - doc! { - "_id": user.id.clone() - }, - doc! { - "$pull": { - "relations": { - "id": target.id.clone() - } - } - }, - None, - ) - .await - .is_ok() - { - if col - .update_one( - doc! { - "_id": target.id.clone() - }, - doc! { - "$pull": { - "relations": { - "id": user.id.clone() - } - } - }, - None, - ) - .await - .is_ok() - { - /*notifications::send_message_threaded( - vec![user.id.clone()], - None, - Notification::user_friend_status(FriendStatus { - id: user.id.clone(), - user: target.id.clone(), - status: Relationship::NONE as i32, - }), - ); - - notifications::send_message_threaded( - vec![target.id.clone()], - None, - Notification::user_friend_status(FriendStatus { - id: target.id.clone(), - user: user.id.clone(), - status: Relationship::NONE as i32, - }), FIXME - );*/ - - Response::Success(json!({ "status": Relationship::NONE as i32 })) - } 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." }), - ) - } - } - _ => unreachable!(), - }, - Relationship::BlockedOther => { - Response::BadRequest(json!({ "error": "Cannot remove block by other user." })) - } - Relationship::Friend - | Relationship::Incoming - | Relationship::Outgoing - | Relationship::SELF - | Relationship::NONE => Response::BadRequest(json!({ "error": "This has no effect." })), - } -} diff --git a/src/routes/users/fetch_user.rs b/src/routes/users/fetch_user.rs new file mode 100644 index 0000000000000000000000000000000000000000..009bace7e02f79e9c862211717d46ddb97b6ff91 --- /dev/null +++ b/src/routes/users/fetch_user.rs @@ -0,0 +1,7 @@ +use crate::util::result::Result; + +#[get("/<id>")] +pub async fn req(id: String) -> Result<String> { + println!("{}", id); + Ok("LETS FUCKING GOOOO".to_string()) +} diff --git a/src/routes/users/mod.rs b/src/routes/users/mod.rs new file mode 100644 index 0000000000000000000000000000000000000000..4251314cc7e25e44688ba492475c1940dfadce99 --- /dev/null +++ b/src/routes/users/mod.rs @@ -0,0 +1,9 @@ +use rocket::Route; + +mod fetch_user; + +pub fn routes() -> Vec<Route> { + routes! [ + fetch_user::req + ] +}