diff --git a/blahd/src/database.rs b/blahd/src/database.rs index 061cde4..5765b76 100644 --- a/blahd/src/database.rs +++ b/blahd/src/database.rs @@ -581,7 +581,26 @@ pub trait TransactionOps { } fn mark_room_msg_seen(&self, rid: Id, uid: i64, cid: Id) -> Result<()> { - // TODO: Validate `cid`? + let max_cid_in_room = prepare_cached_and_bind!( + self.conn(), + r" + SELECT MAX(`cid`) + FROM `msg` INDEXED BY `room_latest_msg` + WHERE `rid` = :rid + " + ) + .raw_query() + .next()? + .map(|row| row.get(0)) + .transpose()? + .unwrap_or(Id(0)); + if max_cid_in_room < cid { + return Err(error_response!( + StatusCode::BAD_REQUEST, + "invalid_request", + "invalid cid", + )); + } let updated = prepare_cached_and_bind!( self.conn(), r" diff --git a/blahd/tests/webapi.rs b/blahd/tests/webapi.rs index a780db8..cb34ddc 100644 --- a/blahd/tests/webapi.rs +++ b/blahd/tests/webapi.rs @@ -738,6 +738,11 @@ async fn last_seen(server: Server) { .await .unwrap(); assert_eq!(rooms, RoomList::default()); + + // Cannot see a future msg. + seen(&ALICE, Id::MAX) + .await + .expect_api_err(StatusCode::BAD_REQUEST, "invalid_request"); } #[rstest]