forked from jmug/stoatchat
Add message sending.
This commit is contained in:
57
src/routes/channels/message_send.rs
Normal file
57
src/routes/channels/message_send.rs
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
use crate::database::*;
|
||||||
|
use crate::util::result::{Error, Result};
|
||||||
|
|
||||||
|
use serde::{Serialize, Deserialize};
|
||||||
|
use rocket_contrib::json::Json;
|
||||||
|
use validator::Validate;
|
||||||
|
use mongodb::bson::doc;
|
||||||
|
use ulid::Ulid;
|
||||||
|
|
||||||
|
#[derive(Validate, Serialize, Deserialize)]
|
||||||
|
pub struct Data {
|
||||||
|
#[validate(length(min = 1, max = 2000))]
|
||||||
|
content: String,
|
||||||
|
// Maximum length of 36 allows both ULIDs and UUIDs.
|
||||||
|
#[validate(length(min = 1, max = 36))]
|
||||||
|
nonce: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[post("/<target>/messages", data = "<message>")]
|
||||||
|
pub async fn req(user: User, target: Ref, message: Json<Data>) -> Result<()> {
|
||||||
|
message.validate()
|
||||||
|
.map_err(|error| Error::FailedValidation { error })?;
|
||||||
|
|
||||||
|
let target = target.fetch_channel().await?;
|
||||||
|
|
||||||
|
let perm = permissions::channel::calculate(&user, &target).await;
|
||||||
|
if !perm.get_send_message() {
|
||||||
|
Err(Error::LabelMe)?
|
||||||
|
}
|
||||||
|
|
||||||
|
if get_collection("messages")
|
||||||
|
.find_one(
|
||||||
|
doc! {
|
||||||
|
"nonce": &message.nonce
|
||||||
|
},
|
||||||
|
None
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.map_err(|_| Error::DatabaseError { operation: "find_one", with: "message" })?
|
||||||
|
.is_some() {
|
||||||
|
Err(Error::AlreadySentMessage)?
|
||||||
|
}
|
||||||
|
|
||||||
|
Message {
|
||||||
|
id: Ulid::new().to_string(),
|
||||||
|
channel: target.id().to_string(),
|
||||||
|
author: user.id,
|
||||||
|
|
||||||
|
content: message.content.clone(),
|
||||||
|
nonce: Some(message.nonce.clone()),
|
||||||
|
edited: None,
|
||||||
|
}
|
||||||
|
.send()
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
@@ -2,10 +2,12 @@ use rocket::Route;
|
|||||||
|
|
||||||
mod fetch_channel;
|
mod fetch_channel;
|
||||||
mod delete_channel;
|
mod delete_channel;
|
||||||
|
mod message_send;
|
||||||
|
|
||||||
pub fn routes() -> Vec<Route> {
|
pub fn routes() -> Vec<Route> {
|
||||||
routes![
|
routes![
|
||||||
fetch_channel::req,
|
fetch_channel::req,
|
||||||
delete_channel::req
|
delete_channel::req,
|
||||||
|
message_send::req
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,10 @@ pub enum Error {
|
|||||||
#[snafu(display("You have been blocked by this user."))]
|
#[snafu(display("You have been blocked by this user."))]
|
||||||
BlockedByOther,
|
BlockedByOther,
|
||||||
|
|
||||||
|
// ? Channel related errors.
|
||||||
|
#[snafu(display("Already sent a message with this nonce."))]
|
||||||
|
AlreadySentMessage,
|
||||||
|
|
||||||
// ? General errors.
|
// ? General errors.
|
||||||
#[snafu(display("Failed to validate fields."))]
|
#[snafu(display("Failed to validate fields."))]
|
||||||
FailedValidation { error: ValidationErrors },
|
FailedValidation { error: ValidationErrors },
|
||||||
@@ -62,6 +66,8 @@ impl<'r> Responder<'r, 'static> for Error {
|
|||||||
Error::Blocked => Status::Conflict,
|
Error::Blocked => Status::Conflict,
|
||||||
Error::BlockedByOther => Status::Forbidden,
|
Error::BlockedByOther => Status::Forbidden,
|
||||||
|
|
||||||
|
Error::AlreadySentMessage => Status::Conflict,
|
||||||
|
|
||||||
Error::FailedValidation { .. } => Status::UnprocessableEntity,
|
Error::FailedValidation { .. } => Status::UnprocessableEntity,
|
||||||
Error::DatabaseError { .. } => Status::InternalServerError,
|
Error::DatabaseError { .. } => Status::InternalServerError,
|
||||||
Error::InternalError => Status::InternalServerError,
|
Error::InternalError => Status::InternalServerError,
|
||||||
|
|||||||
Reference in New Issue
Block a user