simplify client event endpoint
Signed-off-by: Jason Volk <jason@zemos.net>
This commit is contained in:
parent
565837ad75
commit
31ab84e928
3 changed files with 71 additions and 53 deletions
|
@ -1,6 +1,6 @@
|
||||||
use axum::extract::State;
|
use axum::extract::State;
|
||||||
use conduwuit::{
|
use conduwuit::{
|
||||||
at, is_equal_to,
|
at,
|
||||||
utils::{
|
utils::{
|
||||||
result::{FlatOk, LogErr},
|
result::{FlatOk, LogErr},
|
||||||
stream::{BroadbandExt, TryIgnore, WidebandExt},
|
stream::{BroadbandExt, TryIgnore, WidebandExt},
|
||||||
|
@ -30,7 +30,7 @@ use service::{
|
||||||
use crate::Ruma;
|
use crate::Ruma;
|
||||||
|
|
||||||
/// list of safe and common non-state events to ignore if the user is ignored
|
/// list of safe and common non-state events to ignore if the user is ignored
|
||||||
const IGNORED_MESSAGE_TYPES: &[TimelineEventType; 17] = &[
|
const IGNORED_MESSAGE_TYPES: &[TimelineEventType] = &[
|
||||||
Audio,
|
Audio,
|
||||||
CallInvite,
|
CallInvite,
|
||||||
Emote,
|
Emote,
|
||||||
|
@ -225,34 +225,50 @@ async fn get_member_event(
|
||||||
.ok()
|
.ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub(crate) async fn ignored_filter(
|
pub(crate) async fn ignored_filter(
|
||||||
services: &Services,
|
services: &Services,
|
||||||
item: PdusIterItem,
|
item: PdusIterItem,
|
||||||
user_id: &UserId,
|
user_id: &UserId,
|
||||||
) -> Option<PdusIterItem> {
|
) -> Option<PdusIterItem> {
|
||||||
let (_, pdu) = &item;
|
let (_, ref pdu) = item;
|
||||||
|
|
||||||
|
is_ignored_pdu(services, pdu, user_id)
|
||||||
|
.await
|
||||||
|
.eq(&false)
|
||||||
|
.then_some(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate) async fn is_ignored_pdu(
|
||||||
|
services: &Services,
|
||||||
|
pdu: &PduEvent,
|
||||||
|
user_id: &UserId,
|
||||||
|
) -> bool {
|
||||||
// exclude Synapse's dummy events from bloating up response bodies. clients
|
// exclude Synapse's dummy events from bloating up response bodies. clients
|
||||||
// don't need to see this.
|
// don't need to see this.
|
||||||
if pdu.kind.to_cow_str() == "org.matrix.dummy_event" {
|
if pdu.kind.to_cow_str() == "org.matrix.dummy_event" {
|
||||||
return None;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if IGNORED_MESSAGE_TYPES.binary_search(&pdu.kind).is_ok()
|
let ignored_type = IGNORED_MESSAGE_TYPES.binary_search(&pdu.kind).is_ok();
|
||||||
&& (services.users.user_is_ignored(&pdu.sender, user_id).await
|
|
||||||
|| services
|
let ignored_server = services
|
||||||
.server
|
.server
|
||||||
.config
|
.config
|
||||||
.forbidden_remote_server_names
|
.forbidden_remote_server_names
|
||||||
.iter()
|
.contains(pdu.sender().server_name());
|
||||||
.any(is_equal_to!(pdu.sender().server_name())))
|
|
||||||
|
if ignored_type
|
||||||
|
&& (ignored_server || services.users.user_is_ignored(&pdu.sender, user_id).await)
|
||||||
{
|
{
|
||||||
return None;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(item)
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub(crate) async fn visibility_filter(
|
pub(crate) async fn visibility_filter(
|
||||||
services: &Services,
|
services: &Services,
|
||||||
item: PdusIterItem,
|
item: PdusIterItem,
|
||||||
|
@ -268,7 +284,16 @@ pub(crate) async fn visibility_filter(
|
||||||
.then_some(item)
|
.then_some(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
pub(crate) fn event_filter(item: PdusIterItem, filter: &RoomEventFilter) -> Option<PdusIterItem> {
|
pub(crate) fn event_filter(item: PdusIterItem, filter: &RoomEventFilter) -> Option<PdusIterItem> {
|
||||||
let (_, pdu) = &item;
|
let (_, pdu) = &item;
|
||||||
pdu.matches(filter).then_some(item)
|
pdu.matches(filter).then_some(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(debug_assertions, conduwuit::ctor)]
|
||||||
|
fn _is_sorted() {
|
||||||
|
debug_assert!(
|
||||||
|
IGNORED_MESSAGE_TYPES.is_sorted(),
|
||||||
|
"IGNORED_MESSAGE_TYPES must be sorted by the developer"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -1,52 +1,44 @@
|
||||||
use axum::extract::State;
|
use axum::extract::State;
|
||||||
use conduwuit::{err, Err, Event, Result};
|
use conduwuit::{err, Err, Event, Result};
|
||||||
use futures::{try_join, FutureExt, TryFutureExt};
|
use futures::{future::try_join, FutureExt, TryFutureExt};
|
||||||
use ruma::api::client::room::get_room_event;
|
use ruma::api::client::room::get_room_event;
|
||||||
|
|
||||||
use crate::{client::ignored_filter, Ruma};
|
use crate::{client::is_ignored_pdu, Ruma};
|
||||||
|
|
||||||
/// # `GET /_matrix/client/r0/rooms/{roomId}/event/{eventId}`
|
/// # `GET /_matrix/client/r0/rooms/{roomId}/event/{eventId}`
|
||||||
///
|
///
|
||||||
/// Gets a single event.
|
/// Gets a single event.
|
||||||
pub(crate) async fn get_room_event_route(
|
pub(crate) async fn get_room_event_route(
|
||||||
State(services): State<crate::State>,
|
State(ref services): State<crate::State>,
|
||||||
ref body: Ruma<get_room_event::v3::Request>,
|
ref body: Ruma<get_room_event::v3::Request>,
|
||||||
) -> Result<get_room_event::v3::Response> {
|
) -> Result<get_room_event::v3::Response> {
|
||||||
|
let event_id = &body.event_id;
|
||||||
|
let room_id = &body.room_id;
|
||||||
|
|
||||||
let event = services
|
let event = services
|
||||||
.rooms
|
.rooms
|
||||||
.timeline
|
.timeline
|
||||||
.get_pdu(&body.event_id)
|
.get_pdu(event_id)
|
||||||
.map_err(|_| err!(Request(NotFound("Event {} not found.", &body.event_id))));
|
.map_err(|_| err!(Request(NotFound("Event {} not found.", event_id))));
|
||||||
|
|
||||||
let token = services
|
|
||||||
.rooms
|
|
||||||
.timeline
|
|
||||||
.get_pdu_count(&body.event_id)
|
|
||||||
.map_err(|_| err!(Request(NotFound("Event not found."))));
|
|
||||||
|
|
||||||
let visible = services
|
let visible = services
|
||||||
.rooms
|
.rooms
|
||||||
.state_accessor
|
.state_accessor
|
||||||
.user_can_see_event(body.sender_user(), &body.room_id, &body.event_id)
|
.user_can_see_event(body.sender_user(), room_id, event_id)
|
||||||
.map(Ok);
|
.map(Ok);
|
||||||
|
|
||||||
let (token, mut event, visible) = try_join!(token, event, visible)?;
|
let (mut event, visible) = try_join(event, visible).await?;
|
||||||
|
|
||||||
if !visible
|
if !visible || is_ignored_pdu(services, &event, body.sender_user()).await {
|
||||||
|| ignored_filter(&services, (token, event.clone()), body.sender_user())
|
|
||||||
.await
|
|
||||||
.is_none()
|
|
||||||
{
|
|
||||||
return Err!(Request(Forbidden("You don't have permission to view this event.")));
|
return Err!(Request(Forbidden("You don't have permission to view this event.")));
|
||||||
}
|
}
|
||||||
|
|
||||||
if event.event_id() != &body.event_id || event.room_id() != body.room_id {
|
debug_assert!(
|
||||||
return Err!(Request(NotFound("Event not found")));
|
event.event_id() == event_id && event.room_id() == room_id,
|
||||||
}
|
"Fetched PDU must match requested"
|
||||||
|
);
|
||||||
|
|
||||||
event.add_age().ok();
|
event.add_age().ok();
|
||||||
|
|
||||||
let event = event.to_room_event();
|
Ok(get_room_event::v3::Response { event: event.to_room_event() })
|
||||||
|
|
||||||
Ok(get_room_event::v3::Response { event })
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,11 +9,13 @@ use crate::{err, implement, is_true, Result};
|
||||||
|
|
||||||
#[implement(Pdu)]
|
#[implement(Pdu)]
|
||||||
pub fn remove_transaction_id(&mut self) -> Result {
|
pub fn remove_transaction_id(&mut self) -> Result {
|
||||||
|
use BTreeMap as Map;
|
||||||
|
|
||||||
let Some(unsigned) = &self.unsigned else {
|
let Some(unsigned) = &self.unsigned else {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut unsigned: BTreeMap<String, Box<RawJsonValue>> = serde_json::from_str(unsigned.get())
|
let mut unsigned: Map<&str, Box<RawJsonValue>> = serde_json::from_str(unsigned.get())
|
||||||
.map_err(|e| err!(Database("Invalid unsigned in pdu event: {e}")))?;
|
.map_err(|e| err!(Database("Invalid unsigned in pdu event: {e}")))?;
|
||||||
|
|
||||||
unsigned.remove("transaction_id");
|
unsigned.remove("transaction_id");
|
||||||
|
@ -26,10 +28,13 @@ pub fn remove_transaction_id(&mut self) -> Result {
|
||||||
|
|
||||||
#[implement(Pdu)]
|
#[implement(Pdu)]
|
||||||
pub fn add_age(&mut self) -> Result {
|
pub fn add_age(&mut self) -> Result {
|
||||||
let mut unsigned: BTreeMap<String, Box<RawJsonValue>> = self
|
use BTreeMap as Map;
|
||||||
|
|
||||||
|
let mut unsigned: Map<&str, Box<RawJsonValue>> = self
|
||||||
.unsigned
|
.unsigned
|
||||||
.as_ref()
|
.as_deref()
|
||||||
.map_or_else(|| Ok(BTreeMap::new()), |u| serde_json::from_str(u.get()))
|
.map(RawJsonValue::get)
|
||||||
|
.map_or_else(|| Ok(Map::new()), serde_json::from_str)
|
||||||
.map_err(|e| err!(Database("Invalid unsigned in pdu event: {e}")))?;
|
.map_err(|e| err!(Database("Invalid unsigned in pdu event: {e}")))?;
|
||||||
|
|
||||||
// deliberately allowing for the possibility of negative age
|
// deliberately allowing for the possibility of negative age
|
||||||
|
@ -37,10 +42,8 @@ pub fn add_age(&mut self) -> Result {
|
||||||
let then: i128 = self.origin_server_ts.into();
|
let then: i128 = self.origin_server_ts.into();
|
||||||
let this_age = now.saturating_sub(then);
|
let this_age = now.saturating_sub(then);
|
||||||
|
|
||||||
unsigned.insert("age".to_owned(), to_raw_value(&this_age).expect("age is valid"));
|
unsigned.insert("age", to_raw_value(&this_age)?);
|
||||||
self.unsigned = to_raw_value(&unsigned)
|
self.unsigned = Some(to_raw_value(&unsigned)?);
|
||||||
.map(Some)
|
|
||||||
.expect("unsigned is valid");
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -51,8 +54,9 @@ pub fn add_relation(&mut self, name: &str, pdu: Option<&Pdu>) -> Result {
|
||||||
|
|
||||||
let mut unsigned: Map<String, JsonValue> = self
|
let mut unsigned: Map<String, JsonValue> = self
|
||||||
.unsigned
|
.unsigned
|
||||||
.as_ref()
|
.as_deref()
|
||||||
.map_or_else(|| Ok(Map::new()), |u| serde_json::from_str(u.get()))
|
.map(RawJsonValue::get)
|
||||||
|
.map_or_else(|| Ok(Map::new()), serde_json::from_str)
|
||||||
.map_err(|e| err!(Database("Invalid unsigned in pdu event: {e}")))?;
|
.map_err(|e| err!(Database("Invalid unsigned in pdu event: {e}")))?;
|
||||||
|
|
||||||
let pdu = pdu
|
let pdu = pdu
|
||||||
|
@ -64,12 +68,9 @@ pub fn add_relation(&mut self, name: &str, pdu: Option<&Pdu>) -> Result {
|
||||||
.entry("m.relations")
|
.entry("m.relations")
|
||||||
.or_insert(JsonValue::Object(Map::new()))
|
.or_insert(JsonValue::Object(Map::new()))
|
||||||
.as_object_mut()
|
.as_object_mut()
|
||||||
.unwrap()
|
.map(|object| object.insert(name.to_owned(), pdu));
|
||||||
.insert(name.to_owned(), pdu);
|
|
||||||
|
|
||||||
self.unsigned = to_raw_value(&unsigned)
|
self.unsigned = Some(to_raw_value(&unsigned)?);
|
||||||
.map(Some)
|
|
||||||
.expect("unsigned is valid");
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue