add MSC4151 room reporting support

Signed-off-by: strawberry <strawberry@puppygock.gay>
This commit is contained in:
strawberry 2024-10-02 01:47:53 -04:00
parent 54a107c3c4
commit ab9a65db5d
4 changed files with 90 additions and 48 deletions

28
Cargo.lock generated
View file

@ -2975,7 +2975,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma" name = "ruma"
version = "0.10.1" version = "0.10.1"
source = "git+https://github.com/girlbossceo/ruwuma?rev=ade2f1daf0b1d9e8f7de81a24dca8925406e4d8e#ade2f1daf0b1d9e8f7de81a24dca8925406e4d8e" source = "git+https://github.com/girlbossceo/ruwuma?rev=e81ed2741b4ebe98fe41cabdfee2ac28a52a8e37#e81ed2741b4ebe98fe41cabdfee2ac28a52a8e37"
dependencies = [ dependencies = [
"assign", "assign",
"js_int", "js_int",
@ -2997,7 +2997,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma-appservice-api" name = "ruma-appservice-api"
version = "0.10.0" version = "0.10.0"
source = "git+https://github.com/girlbossceo/ruwuma?rev=ade2f1daf0b1d9e8f7de81a24dca8925406e4d8e#ade2f1daf0b1d9e8f7de81a24dca8925406e4d8e" source = "git+https://github.com/girlbossceo/ruwuma?rev=e81ed2741b4ebe98fe41cabdfee2ac28a52a8e37#e81ed2741b4ebe98fe41cabdfee2ac28a52a8e37"
dependencies = [ dependencies = [
"js_int", "js_int",
"ruma-common", "ruma-common",
@ -3009,7 +3009,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma-client-api" name = "ruma-client-api"
version = "0.18.0" version = "0.18.0"
source = "git+https://github.com/girlbossceo/ruwuma?rev=ade2f1daf0b1d9e8f7de81a24dca8925406e4d8e#ade2f1daf0b1d9e8f7de81a24dca8925406e4d8e" source = "git+https://github.com/girlbossceo/ruwuma?rev=e81ed2741b4ebe98fe41cabdfee2ac28a52a8e37#e81ed2741b4ebe98fe41cabdfee2ac28a52a8e37"
dependencies = [ dependencies = [
"as_variant", "as_variant",
"assign", "assign",
@ -3032,7 +3032,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma-common" name = "ruma-common"
version = "0.13.0" version = "0.13.0"
source = "git+https://github.com/girlbossceo/ruwuma?rev=ade2f1daf0b1d9e8f7de81a24dca8925406e4d8e#ade2f1daf0b1d9e8f7de81a24dca8925406e4d8e" source = "git+https://github.com/girlbossceo/ruwuma?rev=e81ed2741b4ebe98fe41cabdfee2ac28a52a8e37#e81ed2741b4ebe98fe41cabdfee2ac28a52a8e37"
dependencies = [ dependencies = [
"as_variant", "as_variant",
"base64 0.22.1", "base64 0.22.1",
@ -3062,7 +3062,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma-events" name = "ruma-events"
version = "0.28.1" version = "0.28.1"
source = "git+https://github.com/girlbossceo/ruwuma?rev=ade2f1daf0b1d9e8f7de81a24dca8925406e4d8e#ade2f1daf0b1d9e8f7de81a24dca8925406e4d8e" source = "git+https://github.com/girlbossceo/ruwuma?rev=e81ed2741b4ebe98fe41cabdfee2ac28a52a8e37#e81ed2741b4ebe98fe41cabdfee2ac28a52a8e37"
dependencies = [ dependencies = [
"as_variant", "as_variant",
"indexmap 2.6.0", "indexmap 2.6.0",
@ -3086,7 +3086,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma-federation-api" name = "ruma-federation-api"
version = "0.9.0" version = "0.9.0"
source = "git+https://github.com/girlbossceo/ruwuma?rev=ade2f1daf0b1d9e8f7de81a24dca8925406e4d8e#ade2f1daf0b1d9e8f7de81a24dca8925406e4d8e" source = "git+https://github.com/girlbossceo/ruwuma?rev=e81ed2741b4ebe98fe41cabdfee2ac28a52a8e37#e81ed2741b4ebe98fe41cabdfee2ac28a52a8e37"
dependencies = [ dependencies = [
"bytes", "bytes",
"http", "http",
@ -3104,7 +3104,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma-identifiers-validation" name = "ruma-identifiers-validation"
version = "0.9.5" version = "0.9.5"
source = "git+https://github.com/girlbossceo/ruwuma?rev=ade2f1daf0b1d9e8f7de81a24dca8925406e4d8e#ade2f1daf0b1d9e8f7de81a24dca8925406e4d8e" source = "git+https://github.com/girlbossceo/ruwuma?rev=e81ed2741b4ebe98fe41cabdfee2ac28a52a8e37#e81ed2741b4ebe98fe41cabdfee2ac28a52a8e37"
dependencies = [ dependencies = [
"js_int", "js_int",
"thiserror", "thiserror",
@ -3113,7 +3113,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma-identity-service-api" name = "ruma-identity-service-api"
version = "0.9.0" version = "0.9.0"
source = "git+https://github.com/girlbossceo/ruwuma?rev=ade2f1daf0b1d9e8f7de81a24dca8925406e4d8e#ade2f1daf0b1d9e8f7de81a24dca8925406e4d8e" source = "git+https://github.com/girlbossceo/ruwuma?rev=e81ed2741b4ebe98fe41cabdfee2ac28a52a8e37#e81ed2741b4ebe98fe41cabdfee2ac28a52a8e37"
dependencies = [ dependencies = [
"js_int", "js_int",
"ruma-common", "ruma-common",
@ -3123,7 +3123,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma-macros" name = "ruma-macros"
version = "0.13.0" version = "0.13.0"
source = "git+https://github.com/girlbossceo/ruwuma?rev=ade2f1daf0b1d9e8f7de81a24dca8925406e4d8e#ade2f1daf0b1d9e8f7de81a24dca8925406e4d8e" source = "git+https://github.com/girlbossceo/ruwuma?rev=e81ed2741b4ebe98fe41cabdfee2ac28a52a8e37#e81ed2741b4ebe98fe41cabdfee2ac28a52a8e37"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"once_cell", "once_cell",
@ -3139,7 +3139,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma-push-gateway-api" name = "ruma-push-gateway-api"
version = "0.9.0" version = "0.9.0"
source = "git+https://github.com/girlbossceo/ruwuma?rev=ade2f1daf0b1d9e8f7de81a24dca8925406e4d8e#ade2f1daf0b1d9e8f7de81a24dca8925406e4d8e" source = "git+https://github.com/girlbossceo/ruwuma?rev=e81ed2741b4ebe98fe41cabdfee2ac28a52a8e37#e81ed2741b4ebe98fe41cabdfee2ac28a52a8e37"
dependencies = [ dependencies = [
"js_int", "js_int",
"ruma-common", "ruma-common",
@ -3151,7 +3151,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma-server-util" name = "ruma-server-util"
version = "0.3.0" version = "0.3.0"
source = "git+https://github.com/girlbossceo/ruwuma?rev=ade2f1daf0b1d9e8f7de81a24dca8925406e4d8e#ade2f1daf0b1d9e8f7de81a24dca8925406e4d8e" source = "git+https://github.com/girlbossceo/ruwuma?rev=e81ed2741b4ebe98fe41cabdfee2ac28a52a8e37#e81ed2741b4ebe98fe41cabdfee2ac28a52a8e37"
dependencies = [ dependencies = [
"headers", "headers",
"http", "http",
@ -3164,7 +3164,7 @@ dependencies = [
[[package]] [[package]]
name = "ruma-signatures" name = "ruma-signatures"
version = "0.15.0" version = "0.15.0"
source = "git+https://github.com/girlbossceo/ruwuma?rev=ade2f1daf0b1d9e8f7de81a24dca8925406e4d8e#ade2f1daf0b1d9e8f7de81a24dca8925406e4d8e" source = "git+https://github.com/girlbossceo/ruwuma?rev=e81ed2741b4ebe98fe41cabdfee2ac28a52a8e37#e81ed2741b4ebe98fe41cabdfee2ac28a52a8e37"
dependencies = [ dependencies = [
"base64 0.22.1", "base64 0.22.1",
"ed25519-dalek", "ed25519-dalek",
@ -3180,10 +3180,10 @@ dependencies = [
[[package]] [[package]]
name = "ruma-state-res" name = "ruma-state-res"
version = "0.11.0" version = "0.11.0"
source = "git+https://github.com/girlbossceo/ruwuma?rev=ade2f1daf0b1d9e8f7de81a24dca8925406e4d8e#ade2f1daf0b1d9e8f7de81a24dca8925406e4d8e" source = "git+https://github.com/girlbossceo/ruwuma?rev=e81ed2741b4ebe98fe41cabdfee2ac28a52a8e37#e81ed2741b4ebe98fe41cabdfee2ac28a52a8e37"
dependencies = [ dependencies = [
"futures-util", "futures-util",
"itertools 0.12.1", "itertools 0.13.0",
"js_int", "js_int",
"ruma-common", "ruma-common",
"ruma-events", "ruma-events",

View file

@ -315,7 +315,7 @@ version = "0.1.2"
[workspace.dependencies.ruma] [workspace.dependencies.ruma]
git = "https://github.com/girlbossceo/ruwuma" git = "https://github.com/girlbossceo/ruwuma"
#branch = "conduwuit-changes" #branch = "conduwuit-changes"
rev = "ade2f1daf0b1d9e8f7de81a24dca8925406e4d8e" rev = "e81ed2741b4ebe98fe41cabdfee2ac28a52a8e37"
features = [ features = [
"compat", "compat",
"rand", "rand",

View file

@ -1,10 +1,14 @@
use std::time::Duration; use std::time::Duration;
use axum::extract::State; use axum::extract::State;
use axum_client_ip::InsecureClientIp;
use conduit::{utils::ReadyExt, Err}; use conduit::{utils::ReadyExt, Err};
use rand::Rng; use rand::Rng;
use ruma::{ use ruma::{
api::client::{error::ErrorKind, room::report_content}, api::client::{
error::ErrorKind,
room::{report_content, report_room},
},
events::room::message, events::room::message,
int, EventId, RoomId, UserId, int, EventId, RoomId, UserId,
}; };
@ -14,22 +18,75 @@ use tracing::info;
use crate::{ use crate::{
debug_info, debug_info,
service::{pdu::PduEvent, Services}, service::{pdu::PduEvent, Services},
utils::HtmlEscape,
Error, Result, Ruma, Error, Result, Ruma,
}; };
/// # `POST /_matrix/client/v3/rooms/{roomId}/report`
///
/// Reports an abusive room to homeserver admins
#[tracing::instrument(skip_all, fields(%client), name = "report_room")]
pub(crate) async fn report_room_route(
State(services): State<crate::State>, InsecureClientIp(client): InsecureClientIp,
body: Ruma<report_room::v3::Request>,
) -> Result<report_room::v3::Response> {
// user authentication
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
info!(
"Received room report by user {sender_user} for room {} with reason: {:?}",
body.room_id, body.reason
);
delay_response().await;
if !services
.rooms
.state_cache
.server_in_room(&services.globals.config.server_name, &body.room_id)
.await
{
return Err!(Request(NotFound(
"Room does not exist to us, no local users have joined at all"
)));
}
if body.reason.as_ref().is_some_and(|s| s.len() > 750) {
return Err(Error::BadRequest(
ErrorKind::InvalidParam,
"Reason too long, should be 750 characters or fewer",
));
};
// send admin room message that we received the report with an @room ping for
// urgency
services
.admin
.send_message(message::RoomMessageEventContent::text_markdown(format!(
"@room Room report received from {} -\n\nRoom ID: {}\n\nReport Reason: {}",
sender_user.to_owned(),
body.room_id,
body.reason.as_deref().unwrap_or("")
)))
.await
.ok();
Ok(report_room::v3::Response {})
}
/// # `POST /_matrix/client/v3/rooms/{roomId}/report/{eventId}` /// # `POST /_matrix/client/v3/rooms/{roomId}/report/{eventId}`
/// ///
/// Reports an inappropriate event to homeserver admins /// Reports an inappropriate event to homeserver admins
#[tracing::instrument(skip_all, fields(%client), name = "report_event")]
pub(crate) async fn report_event_route( pub(crate) async fn report_event_route(
State(services): State<crate::State>, body: Ruma<report_content::v3::Request>, State(services): State<crate::State>, InsecureClientIp(client): InsecureClientIp,
body: Ruma<report_content::v3::Request>,
) -> Result<report_content::v3::Response> { ) -> Result<report_content::v3::Response> {
// user authentication // user authentication
let sender_user = body.sender_user.as_ref().expect("user is authenticated"); let sender_user = body.sender_user.as_ref().expect("user is authenticated");
info!( info!(
"Received /report request by user {sender_user} for room {} and event ID {}", "Received event report by user {sender_user} for room {} and event ID {}, with reason: {:?}",
body.room_id, body.event_id body.room_id, body.event_id, body.reason
); );
delay_response().await; delay_response().await;
@ -39,7 +96,7 @@ pub(crate) async fn report_event_route(
return Err!(Request(NotFound("Event ID is not known to us or Event ID is invalid"))); return Err!(Request(NotFound("Event ID is not known to us or Event ID is invalid")));
}; };
is_report_valid( is_event_report_valid(
&services, &services,
&pdu.event_id, &pdu.event_id,
&body.room_id, &body.room_id,
@ -54,32 +111,16 @@ pub(crate) async fn report_event_route(
// urgency // urgency
services services
.admin .admin
.send_message(message::RoomMessageEventContent::text_html( .send_message(message::RoomMessageEventContent::text_markdown(format!(
format!( "@room Event report received from {} -\n\nEvent ID: {}\nRoom ID: {}\nSent By: {}\n\nReport Score: \
"@room Report received from: {}\n\nEvent ID: {}\nRoom ID: {}\nSent By: {}\n\nReport Score: {}\nReport \ {}\nReport Reason: {}",
Reason: {}", sender_user.to_owned(),
sender_user.to_owned(), pdu.event_id,
pdu.event_id, pdu.room_id,
pdu.room_id, pdu.sender,
pdu.sender.clone(), body.score.unwrap_or_else(|| ruma::Int::from(0)),
body.score.unwrap_or_else(|| ruma::Int::from(0)), body.reason.as_deref().unwrap_or("")
body.reason.as_deref().unwrap_or("") )))
),
format!(
"<details><summary>@room Report received from: <a href=\"https://matrix.to/#/{0}\">{0}\
</a></summary><ul><li>Event Info<ul><li>Event ID: <code>{1}</code>\
<a href=\"https://matrix.to/#/{2}/{1}\">🔗</a></li><li>Room ID: <code>{2}</code>\
</li><li>Sent By: <a href=\"https://matrix.to/#/{3}\">{3}</a></li></ul></li><li>\
Report Info<ul><li>Report Score: {4}</li><li>Report Reason: {5}</li></ul></li>\
</ul></details>",
sender_user.to_owned(),
pdu.event_id.clone(),
pdu.room_id.clone(),
pdu.sender.clone(),
body.score.unwrap_or_else(|| ruma::Int::from(0)),
HtmlEscape(body.reason.as_deref().unwrap_or(""))
),
))
.await .await
.ok(); .ok();
@ -92,7 +133,7 @@ pub(crate) async fn report_event_route(
/// check if score is in valid range /// check if score is in valid range
/// check if report reasoning is less than or equal to 750 characters /// check if report reasoning is less than or equal to 750 characters
/// check if reporting user is in the reporting room /// check if reporting user is in the reporting room
async fn is_report_valid( async fn is_event_report_valid(
services: &Services, event_id: &EventId, room_id: &RoomId, sender_user: &UserId, reason: &Option<String>, services: &Services, event_id: &EventId, room_id: &RoomId, sender_user: &UserId, reason: &Option<String>,
score: Option<ruma::Int>, pdu: &std::sync::Arc<PduEvent>, score: Option<ruma::Int>, pdu: &std::sync::Arc<PduEvent>,
) -> Result<()> { ) -> Result<()> {

View file

@ -91,6 +91,7 @@ pub fn build(router: Router<State>, server: &Server) -> Router<State> {
.ruma_route(&client::create_room_route) .ruma_route(&client::create_room_route)
.ruma_route(&client::redact_event_route) .ruma_route(&client::redact_event_route)
.ruma_route(&client::report_event_route) .ruma_route(&client::report_event_route)
.ruma_route(&client::report_room_route)
.ruma_route(&client::create_alias_route) .ruma_route(&client::create_alias_route)
.ruma_route(&client::delete_alias_route) .ruma_route(&client::delete_alias_route)
.ruma_route(&client::get_alias_route) .ruma_route(&client::get_alias_route)