From d5d14305d02e73a28888eb720a6d90b5bca02854 Mon Sep 17 00:00:00 2001 From: Paul Makles <paulmakles@gmail.com> Date: Sat, 8 Feb 2020 15:03:40 +0000 Subject: [PATCH] Finish implementing all routes. --- src/database/channel.rs | 3 + src/database/message.rs | 9 +- src/guards/channel.rs | 2 +- src/routes/channel.rs | 196 +++++++++++++++++++++++++++++++++++++++- src/routes/mod.rs | 2 +- 5 files changed, 205 insertions(+), 7 deletions(-) diff --git a/src/database/channel.rs b/src/database/channel.rs index be88081..e60856b 100644 --- a/src/database/channel.rs +++ b/src/database/channel.rs @@ -4,7 +4,10 @@ use serde::{ Deserialize, Serialize }; pub struct Channel { #[serde(rename = "_id")] pub id: String, + #[serde(rename = "type")] pub channel_type: u8, + + pub last_message: Option<String>, // for Direct Messages pub recipients: Option<Vec<String>>, diff --git a/src/database/message.rs b/src/database/message.rs index d65b211..9411b82 100644 --- a/src/database/message.rs +++ b/src/database/message.rs @@ -1,8 +1,13 @@ - use serde::{ Deserialize, Serialize }; +use bson::{ UtcDateTime }; #[derive(Serialize, Deserialize, Debug)] pub struct Message { #[serde(rename = "_id")] - pub id: String, + pub id: String, + pub channel: String, + pub author: String, + + pub content: String, + pub edited: Option<UtcDateTime>, } diff --git a/src/guards/channel.rs b/src/guards/channel.rs index daa277d..fde2b82 100644 --- a/src/guards/channel.rs +++ b/src/guards/channel.rs @@ -2,7 +2,7 @@ use rocket::http::{ RawStr }; use rocket::request::{ FromParam }; use bson::{ bson, doc, from_bson }; -use crate::database; +use crate::database::{ self, user::User }; use database::channel::Channel; use database::message::Message; diff --git a/src/routes/channel.rs b/src/routes/channel.rs index 81d3f07..66a90f6 100644 --- a/src/routes/channel.rs +++ b/src/routes/channel.rs @@ -1,8 +1,11 @@ -use crate::database::{ user::User, channel::Channel }; +use crate::database::{ self, user::User, channel::Channel, message::Message }; -use rocket_contrib::json::{ JsonValue }; +use bson::{ bson, doc, from_bson, Bson::UtcDatetime }; +use rocket_contrib::json::{ JsonValue, Json }; +use serde::{ Serialize, Deserialize }; use num_enum::TryFromPrimitive; -use bson::{ doc }; +use chrono::prelude::*; +use ulid::Ulid; #[derive(Debug, TryFromPrimitive)] #[repr(usize)] @@ -46,3 +49,190 @@ pub fn channel(user: User, target: Channel) -> Option<JsonValue> { } )) } + +/// delete channel +/// or leave group DM +/// or close DM conversation +#[delete("/<target>")] +pub fn delete(user: User, target: Channel) -> Option<JsonValue> { + if !has_permission(&user, &target) { + return None + } + + let col = database::get_collection("channels"); + Some(match target.channel_type { + 0 => { + col.update_one( + doc! { "_id": target.id }, + doc! { "$set": { "active": false } }, + None + ).expect("Failed to update channel."); + + json!({ + "success": true + }) + }, + 1 => { + // ? TODO: group dm + + json!({ + "success": true + }) + }, + 2 => { + // ? TODO: guild + + json!({ + "success": true + }) + }, + _ => + json!({ + "success": false + }) + }) +} + +/// fetch channel messages +#[get("/<target>/messages")] +pub fn messages(user: User, target: Channel) -> Option<JsonValue> { + if !has_permission(&user, &target) { + return None + } + + let col = database::get_collection("messages"); + let result = col.find( + doc! { "channel": target.id }, + None + ).unwrap(); + + let mut messages = Vec::new(); + for item in result { + let message: Message = from_bson(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(json!(messages)) +} + +#[derive(Serialize, Deserialize)] +pub struct SendMessage { + content: String, +} + +/// send a message to a channel +#[post("/<target>/messages", data = "<message>")] +pub fn send_message(user: User, target: Channel, message: Json<SendMessage>) -> Option<JsonValue> { + if !has_permission(&user, &target) { + return None + } + + let col = database::get_collection("messages"); + let id = Ulid::new().to_string(); + Some(match col.insert_one( + doc! { + "_id": id.clone(), + "channel": target.id, + "author": user.id, + "content": message.content.clone(), + }, + None + ) { + Ok(_) => + json!({ + "success": true, + "id": id + }), + Err(_) => + json!({ + "success": false, + "error": "Failed database query." + }) + }) +} + +#[derive(Serialize, Deserialize)] +pub struct EditMessage { + content: String, +} + +/// edit a message +#[patch("/<target>/messages/<message>", data = "<edit>")] +pub fn edit_message(user: User, target: Channel, message: Message, edit: Json<SendMessage>) -> Option<JsonValue> { + if !has_permission(&user, &target) { + return None + } + + Some( + if message.author != user.id { + json!({ + "success": false, + "error": "You did not send this message." + }) + } else { + let col = database::get_collection("messages"); + + match col.update_one( + doc! { "_id": message.id }, + doc! { + "$set": { + "content": edit.content.clone(), + "edited": UtcDatetime(Utc::now()) + } + }, + None + ) { + Ok(_) => + json!({ + "success": true + }), + 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> { + if !has_permission(&user, &target) { + return None + } + + Some( + if message.author != user.id { + json!({ + "success": false, + "error": "You did not send this message." + }) + } else { + let col = database::get_collection("messages"); + + match col.delete_one( + doc! { "_id": message.id }, + None + ) { + Ok(_) => + json!({ + "success": true + }), + Err(_) => + json!({ + "success": false, + "error": "Failed to delete message." + }) + } + } + ) +} diff --git a/src/routes/mod.rs b/src/routes/mod.rs index b189080..ef4de33 100644 --- a/src/routes/mod.rs +++ b/src/routes/mod.rs @@ -8,5 +8,5 @@ pub fn mount(rocket: Rocket) -> Rocket { rocket .mount("/api/account", routes![ account::create, account::verify_email, account::resend_email, account::login ]) .mount("/api/users", routes![ user::me, user::user, user::lookup, user::dms, user::dm, user::get_friends, user::get_friend, user::add_friend, user::remove_friend ]) - .mount("/api/channels", routes![ channel::channel ]) + .mount("/api/channels", routes![ channel::channel, channel::delete, channel::messages, channel::send_message, channel::edit_message, channel::delete_message ]) } -- GitLab