From c2e384a13adff4c05ce516a9e1afca43475b7986 Mon Sep 17 00:00:00 2001 From: shockrah Date: Thu, 4 Feb 2021 01:58:57 -0800 Subject: [PATCH] */message/send Now polls content from the request body * flattened a bunch of checks with data fetches to the db Outright reduction of branches yey --- json-api/src/messages.rs | 84 +++++++++++++++++++++++----------------- 1 file changed, 48 insertions(+), 36 deletions(-) diff --git a/json-api/src/messages.rs b/json-api/src/messages.rs index 6c8d278..2f28ebb 100644 --- a/json-api/src/messages.rs +++ b/json-api/src/messages.rs @@ -1,9 +1,13 @@ use mysql_async::Pool; use hyper::{Response, Body, StatusCode}; +use hyper::body::to_bytes; use serde_json::Value; use serde_json::json; +use std::collections::HashMap; + use crate::http::{self, set_json_body}; +use crate::perms; use db::messages::Message; pub async fn get_by_time(pool: &Pool, response: &mut Response, params: Value) { @@ -64,47 +68,55 @@ pub async fn get_by_time(pool: &Pool, response: &mut Response, params: Val } } -pub async fn send_message(pool: &Pool, response: &mut Response, params: Value) { +pub async fn send_message(pool: &Pool, response: &mut Response, body: Body, params: HashMap<&str, &str>) { /* - * @content: expecting string type - * @channel: channel id that we're going to send a message to + * Message content is sent in the message body + * @channel_id: channel id that we're going to send a message to + * TODO: more features here because send_message is a large handler */ + use db::Response::*; + use db::member::Member; + use crate::db::common::FromDB; + // NOTE: auth module guarantees this will be there in the correct form - let author = http::extract_uid(¶ms); + let uid = http::extract_uid(¶ms); + let permissions = match Member::get(pool, uid).await { + Row(user) => user.permissions, + _ => 0 + }; + if perms::has_perm(permissions, perms::SEND_MESSAGES) == false { + *response.status_mut() = StatusCode::BAD_REQUEST; + return; + } - match (params.get("content") , params.get("channel")) { - (Some(content_v), Some(channel_id_v)) => { - let (content, channel) = (content_v.as_str(), channel_id_v.as_u64()); + let channel_id = match params.get("channel") { + Some(cval) => { + if let Ok(num) = (*cval).to_string().parse::() { + Some(num) + } else { + None + } + } + None => None + }; - if let (Some(message), Some(cid)) = (content, channel) { - // call returns empty on sucess so we don't need to do anything - // TODO: loggin - let db_result = db::messages::Message::send(pool, message, cid, author).await; - if let Err(issue) = db_result { - *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - eprintln!("\t{}", issue); - } - else { - match db_result.unwrap() { - db::Response::RestrictedInput(msg) => { - // user issue - *response.status_mut() = StatusCode::BAD_REQUEST; - set_json_body(response, json!({"msg": msg})) - }, - db::Response::Empty => {}, // nothing to do hyper defaults to 200 - db::Response::Other(msg) => { - eprintln!("{}", msg); - *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; - }, - _ => *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR - }; - } - } - else { - *response.status_mut() = StatusCode::BAD_REQUEST; - } - }, - _ => *response.status_mut() = StatusCode::BAD_REQUEST + // Black magic + let body_bytes: &[u8] = &to_bytes(body).await.unwrap(); // yolo + let content = String::from_utf8_lossy(body_bytes); + + // 400 on empty bodies or missing channel id's + if content.len() == 0 || channel_id.is_none() { + *response.status_mut() = StatusCode::BAD_REQUEST; + } else { + match db::messages::Message::send(pool, &content, channel_id.unwrap(), uid).await { + Ok(Empty) => {}, // nothing to do hyper defaults to 200 + Ok(RestrictedInput(msg)) => *response.status_mut() = StatusCode::BAD_REQUEST, + Ok(Other(msg)) => { + eprintln!("{}", msg); + *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; + }, + _ => *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR + } } }