diff --git a/json-api/client-tests/client.py b/json-api/client-tests/client.py index 5e8fb17..47c8f6f 100644 --- a/json-api/client-tests/client.py +++ b/json-api/client-tests/client.py @@ -171,10 +171,10 @@ def run(worker: Worker): message_tests = [ # bs message spam - {'init': ['post', '/message/send', {'channel_id': chan_d['id'], 'content': 'bs content'}], 'auth': jwt, 'hope': 200, 'body': True}, - {'init': ['post', '/message/send', {'channel_id': chan_d['id'], 'content': 'bs content'}], 'auth': jwt, 'hope': 200}, - {'init': ['post', '/message/send', {'channel_id': chan_d['id'], 'content': 'bs content'}], 'auth': jwt, 'hope': 200}, - {'init': ['post', '/message/send', {'channel_id': chan_d['id'], 'content': 'bs content'}], 'auth': jwt, 'hope': 200}, + {'init': ['post', '/message/send', {'type': 'text', 'channel_id': chan_d['id'], 'content': 'bs content'}], 'auth': jwt, 'hope': 200, 'body': True}, + {'init': ['post', '/message/send', {'type': 'text', 'channel_id': chan_d['id'], 'content': 'bs content'}], 'auth': jwt, 'hope': 200}, + {'init': ['post', '/message/send', {'type': 'text', 'channel_id': chan_d['id'], 'content': 'bs content'}], 'auth': jwt, 'hope': 200}, + {'init': ['post', '/message/send', {'type': 'text', 'channel_id': chan_d['id'], 'content': 'bs content'}], 'auth': jwt, 'hope': 200}, # can we get them back tho? { @@ -214,19 +214,14 @@ def run(worker: Worker): ], 'auth': jwt, 'hope': 200, 'body': True }, - # tests that don't follow the api's rules { - # channel doesn't exist so a 404 seems to be inorder - 'init': [ - 'get', '/message/from_id', {'start': 1, 'channel_id':9} - ], + # Channel doesn't exist so empty vector is result + 'init': [ 'get', '/message/from_id', {'start': 1, 'channel_id':9} ], 'auth': jwt, 'hope': 404 }, { - 'init': [ - # good channel but id is tooo high - 'get', '/message/from_id', {'start': 5, 'channel_id':3} - ], + # Channel id doesn't refer to a real channel + 'init': [ 'get', '/message/from_id', {'start': 5, 'channel_id':3} ], 'auth': jwt, 'hope': 404 }, ] diff --git a/json-api/db/src/messages.rs b/json-api/db/src/messages.rs index 5b16917..50177f4 100644 --- a/json-api/db/src/messages.rs +++ b/json-api/db/src/messages.rs @@ -11,20 +11,21 @@ const MAX_MESSAGES: u64 = 1000; impl crate::Message { - pub async fn send(p: &Pool, content: &str, cid: UBigInt, uid: UBigInt) -> Result, SqlError> { + pub async fn send(p: &Pool, content: &str, content_type: &str, cid: UBigInt, uid: UBigInt) -> Result, SqlError> { //! @returns on_sucess -> empty //! @returns on_failure Err(SqlErr) use chrono::Utc; let conn = p.get_conn().await?; let q = "INSERT INTO messages - (time, content, author_id, channel_id) - VALUES (:time, :content, :author, :channel)"; + (time, content, content_type, author_id, channel_id) + VALUES (:time, :content, :ctype, :author, :channel)"; let now = Utc::now().timestamp(); let res = conn.prep_exec(q, params!{ "time" => now, "content" => content, + "ctype" => content_type, "author" => uid, "channel" => cid }).await; @@ -102,6 +103,7 @@ impl crate::Message { pub async fn get_from_id(p: &Pool, channel_id: UBigInt, start: UBigInt, limit: Option) -> Result, SqlError> { //! @returns on success : Set(Vec) + //! @returns on user failure : RestrictedInput(String) //! @returns on failure : Err(SqlError) let conn = p.get_conn().await?; let limit = if let Some(limit) = limit{ diff --git a/json-api/migrations/2020-07-06-022319_messages/up.sql b/json-api/migrations/2020-07-06-022319_messages/up.sql index d5fa48f..9017353 100644 --- a/json-api/migrations/2020-07-06-022319_messages/up.sql +++ b/json-api/migrations/2020-07-06-022319_messages/up.sql @@ -3,7 +3,7 @@ CREATE TABLE IF NOT EXISTS `messages`( `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, `time` BIGINT NOT NULL, `content` VARCHAR(4096) NOT NULL, - `content_type` VARCHAR NOT NULL, + `content_type` VARCHAR(10) NOT NULL, `author_id` BIGINT UNSIGNED NOT NULL, `channel_id` BIGINT UNSIGNED NOT NULL, PRIMARY KEY (`id`), diff --git a/json-api/src/messages.rs b/json-api/src/messages.rs index 3452bfd..3e9a439 100644 --- a/json-api/src/messages.rs +++ b/json-api/src/messages.rs @@ -66,6 +66,8 @@ pub async fn send_message(pool: &Pool, response: &mut Response, body: Body // NOTE: auth module guarantees this will be there in the correct form let uid = qs_param!(params, "id", u64).unwrap(); + let ctype = params.get("type"); + let permissions = match Member::get(pool, uid).await { Row(user) => user.permissions, _ => 0 @@ -82,17 +84,24 @@ pub async fn send_message(pool: &Pool, response: &mut Response, body: Body 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() { + if content.len() == 0 || channel_id.is_none() || ctype.is_none() { *response.status_mut() = StatusCode::BAD_REQUEST; } else { - match db::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 + // block away wrong content types + const CONTENT_TYPES: [&'static str;7] = ["text", "png", "jpeg", "jpg", "webm", "mp3", "mp4"]; + if CONTENT_TYPES.contains(&ctype.unwrap().as_str()) == false { + *response.status_mut() = StatusCode::BAD_REQUEST; + } + else { + match db::Message::send(pool, &content, ctype.unwrap(), channel_id.unwrap(), uid).await { + Ok(Empty) => {/* TODO: put something here to notify the rtc server if its there*/}, + 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 + } } } } @@ -117,14 +126,11 @@ pub async fn from_id(pool: &Pool, response: &mut Response, params: HashMap Ok(db_response) => { match db_response { db::Response::Set(messages) => { - // NOTE this check is here because the db's check doesn't - // correctly with async and caching and magic idfk its here - // it works its correct and the cost is the same as putting - // it in the db layer so whatever + // *any* kind of empty response, even those from weird + // parameters get 404's if messages.len() == 0 { *response.status_mut() = StatusCode::NOT_FOUND; - } - else { + } else { set_json_body(response, json!({"messages": messages})); } },