diff --git a/src/api/client_server/context.rs b/src/api/client_server/context.rs index 260698ccdad22673c64376463d86e470e36b0b9b..2291e5864092b6ca6baece95a5efa85f45efb08f 100644 --- a/src/api/client_server/context.rs +++ b/src/api/client_server/context.rs @@ -188,14 +188,12 @@ pub(crate) async fn get_context_route(body: Ruma<get_context::v3::Request>) -> R } } - let resp = get_context::v3::Response { + Ok(get_context::v3::Response { start: Some(start_token), end: Some(end_token), events_before, event: Some(base_event), events_after, state, - }; - - Ok(resp) + }) } diff --git a/src/api/client_server/report.rs b/src/api/client_server/report.rs index 4cefcd089a43a88c4953e50a349f4d142a12d257..185d7edbb91f543f0d2a3e551e1c428812df0a8c 100644 --- a/src/api/client_server/report.rs +++ b/src/api/client_server/report.rs @@ -4,12 +4,12 @@ use ruma::{ api::client::{error::ErrorKind, room::report_content}, events::room::message, - int, + int, EventId, RoomId, UserId, }; use tokio::time::sleep; -use tracing::{debug, info}; +use tracing::info; -use crate::{services, utils::HtmlEscape, Error, Result, Ruma}; +use crate::{debug_info, service::pdu::PduEvent, services, utils::HtmlEscape, Error, Result, Ruma}; /// # `POST /_matrix/client/v3/rooms/{roomId}/report/{eventId}` /// @@ -20,7 +20,10 @@ pub(crate) async fn report_event_route( // user authentication let sender_user = body.sender_user.as_ref().expect("user is authenticated"); - info!("Received /report request by user {}", sender_user); + info!( + "Received /report request by user {sender_user} for room {} and event ID {}", + body.room_id, body.event_id + ); // check if we know about the reported event ID or if it's invalid let Some(pdu) = services().rooms.timeline.get_pdu(&body.event_id)? else { @@ -30,43 +33,7 @@ pub(crate) async fn report_event_route( )); }; - // check if the room ID from the URI matches the PDU's room ID - if body.room_id != pdu.room_id { - return Err(Error::BadRequest( - ErrorKind::NotFound, - "Event ID does not belong to the reported room", - )); - } - - // check if reporting user is in the reporting room - if !services() - .rooms - .state_cache - .room_members(&pdu.room_id) - .filter_map(Result::ok) - .any(|user_id| user_id == *sender_user) - { - return Err(Error::BadRequest( - ErrorKind::NotFound, - "You are not in the room you are reporting.", - )); - } - - // check if score is in valid range - if let Some(true) = body.score.map(|s| s > int!(0) || s < int!(-100)) { - return Err(Error::BadRequest( - ErrorKind::InvalidParam, - "Invalid score, must be within 0 to -100", - )); - }; - - // check if report reasoning is less than or equal to 750 characters - if let Some(true) = body.reason.clone().map(|s| s.chars().count() >= 750) { - return Err(Error::BadRequest( - ErrorKind::InvalidParam, - "Reason too long, should be 750 characters or fewer", - )); - }; + is_report_valid(&pdu.event_id, &body.room_id, sender_user, &body.reason, body.score, &pdu)?; // send admin room message that we received the report with an @room ping for // urgency @@ -100,15 +67,67 @@ pub(crate) async fn report_event_route( )) .await; - // even though this is kinda security by obscurity, let's still make a small - // random delay sending a successful response per spec suggestion regarding - // enumerating for potential events existing in our server. + delay_response().await?; + + Ok(report_content::v3::Response {}) +} + +/// in the following order: +/// +/// check if the room ID from the URI matches the PDU's room ID +/// check if reporting user is in the reporting room +/// check if score is in valid range +/// check if report reasoning is less than or equal to 750 characters +fn is_report_valid( + event_id: &EventId, room_id: &RoomId, sender_user: &UserId, reason: &Option<String>, score: Option<ruma::Int>, + pdu: &std::sync::Arc<PduEvent>, +) -> Result<bool> { + debug_info!("Checking if report from user {sender_user} for event {event_id} in room {room_id} is valid"); + + if room_id != pdu.room_id { + return Err(Error::BadRequest( + ErrorKind::NotFound, + "Event ID does not belong to the reported room", + )); + } + + if services() + .rooms + .state_cache + .room_members(&pdu.room_id) + .filter_map(Result::ok) + .any(|user_id| user_id != *sender_user) + { + return Err(Error::BadRequest( + ErrorKind::NotFound, + "You are not in the room you are reporting.", + )); + } + + if let Some(true) = score.map(|s| s > int!(0) || s < int!(-100)) { + return Err(Error::BadRequest( + ErrorKind::InvalidParam, + "Invalid score, must be within 0 to -100", + )); + }; + + if let Some(true) = reason.clone().map(|s| s.len() >= 750) { + return Err(Error::BadRequest( + ErrorKind::InvalidParam, + "Reason too long, should be 750 characters or fewer", + )); + }; + + Ok(true) +} + +/// even though this is kinda security by obscurity, let's still make a small +/// random delay sending a successful response per spec suggestion regarding +/// enumerating for potential events existing in our server. +async fn delay_response() -> Result<()> { let time_to_wait = rand::thread_rng().gen_range(8..21); - debug!( - "Got successful /report request, waiting {} seconds before sending successful response.", - time_to_wait - ); + debug_info!("Got successful /report request, waiting {time_to_wait} seconds before sending successful response."); sleep(Duration::from_secs(time_to_wait)).await; - Ok(report_content::v3::Response {}) + Ok(()) }