Add redact method to all event_enum! generated enums
… and to AliasesEventContent
This commit is contained in:
parent
b260a13d4b
commit
1db0082281
@ -153,7 +153,7 @@ pub fn expand_event_content(input: &DeriveInput, emit_redacted: bool) -> syn::Re
|
||||
// this is the non redacted event content's impl
|
||||
impl #ident {
|
||||
/// Transforms the full event content into a redacted content according to spec.
|
||||
pub fn redact(self) -> #redacted_ident {
|
||||
pub fn redact(self, version: ::ruma_identifiers::RoomVersionId) -> #redacted_ident {
|
||||
#redacted_ident { #( #redaction_struct_fields: self.#redaction_struct_fields, )* }
|
||||
}
|
||||
}
|
||||
|
@ -131,15 +131,122 @@ fn expand_any_with_deser(
|
||||
|
||||
let field_accessor_impl = accessor_methods(kind, var, &variants);
|
||||
|
||||
let redact_impl = generate_redact(&ident, kind, var, &variants);
|
||||
|
||||
Some(quote! {
|
||||
#any_enum
|
||||
|
||||
#field_accessor_impl
|
||||
|
||||
#redact_impl
|
||||
|
||||
#event_deserialize_impl
|
||||
})
|
||||
}
|
||||
|
||||
fn generate_redact(
|
||||
ident: &Ident,
|
||||
kind: &EventKind,
|
||||
var: &EventKindVariation,
|
||||
variants: &[Ident],
|
||||
) -> Option<TokenStream> {
|
||||
if let EventKindVariation::Full | EventKindVariation::Sync | EventKindVariation::Stripped = var
|
||||
{
|
||||
let (param, redaction_type, redaction_enum) = match var {
|
||||
EventKindVariation::Full => {
|
||||
let struct_id = kind.to_event_ident(&EventKindVariation::Redacted)?;
|
||||
(
|
||||
quote! { ::ruma_events::room::redaction::RedactionEvent },
|
||||
quote! { ::ruma_events::#struct_id },
|
||||
kind.to_event_enum_ident(&EventKindVariation::Redacted)?,
|
||||
)
|
||||
}
|
||||
EventKindVariation::Sync => {
|
||||
let struct_id = kind.to_event_ident(&EventKindVariation::RedactedSync)?;
|
||||
(
|
||||
quote! { ::ruma_events::room::redaction::SyncRedactionEvent },
|
||||
quote! { ::ruma_events::#struct_id },
|
||||
kind.to_event_enum_ident(&EventKindVariation::RedactedSync)?,
|
||||
)
|
||||
}
|
||||
EventKindVariation::Stripped => {
|
||||
let struct_id = kind.to_event_ident(&EventKindVariation::RedactedStripped)?;
|
||||
(
|
||||
quote! { ::ruma_events::room::redaction::SyncRedactionEvent },
|
||||
quote! { ::ruma_events::#struct_id },
|
||||
kind.to_event_enum_ident(&EventKindVariation::RedactedStripped)?,
|
||||
)
|
||||
}
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
let fields = EVENT_FIELDS
|
||||
.iter()
|
||||
.map(|(name, has_field)| generate_redacted_fields(name, kind, var, *has_field));
|
||||
|
||||
let fields = quote! { #( #fields )* };
|
||||
|
||||
Some(quote! {
|
||||
impl #ident {
|
||||
/// Redacts `Self` given a valid `Redaction[Sync]Event`.
|
||||
pub fn redact(self, redaction: #param, version: ::ruma_identifiers::RoomVersionId) -> #redaction_enum {
|
||||
match self {
|
||||
#(
|
||||
Self::#variants(event) => {
|
||||
let content = event.content.redact(version);
|
||||
#redaction_enum::#variants(#redaction_type {
|
||||
content,
|
||||
#fields
|
||||
})
|
||||
}
|
||||
)*
|
||||
Self::Custom(event) => {
|
||||
let content = event.content.redact(version);
|
||||
#redaction_enum::Custom(#redaction_type {
|
||||
content,
|
||||
#fields
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn generate_redacted_fields(
|
||||
name: &str,
|
||||
kind: &EventKind,
|
||||
var: &EventKindVariation,
|
||||
is_event_kind: EventKindFn,
|
||||
) -> TokenStream {
|
||||
if is_event_kind(kind, var) {
|
||||
let name = Ident::new(name, Span::call_site());
|
||||
|
||||
if name == "unsigned" {
|
||||
let redaction_type = if let EventKindVariation::Sync = var {
|
||||
quote! { RedactedSyncUnsigned }
|
||||
} else {
|
||||
quote! { RedactedUnsigned }
|
||||
};
|
||||
|
||||
quote! {
|
||||
unsigned: ::ruma_events::#redaction_type {
|
||||
redacted_because: Some(::ruma_events::EventJson::from(redaction)),
|
||||
},
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
#name: event.#name,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
TokenStream::new()
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates the 3 redacted state enums, 2 redacted message enums,
|
||||
/// and `Deserialize` implementations.
|
||||
///
|
||||
|
@ -1,5 +1,6 @@
|
||||
//! Types for custom events outside of the Matrix specification.
|
||||
|
||||
use ruma_identifiers::RoomVersionId;
|
||||
use serde::Serialize;
|
||||
use serde_json::{value::RawValue as RawJsonValue, Value as JsonValue};
|
||||
|
||||
@ -23,7 +24,7 @@ pub struct CustomEventContent {
|
||||
|
||||
impl CustomEventContent {
|
||||
/// Transforms the full event content into a redacted content according to spec.
|
||||
pub fn redact(self) -> RedactedCustomEventContent {
|
||||
pub fn redact(self, _: RoomVersionId) -> RedactedCustomEventContent {
|
||||
RedactedCustomEventContent { event_type: self.event_type }
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
//! Types for the *m.room.aliases* event.
|
||||
|
||||
use ruma_events_macros::StateEventContent;
|
||||
use ruma_identifiers::RoomAliasId;
|
||||
use ruma_identifiers::{RoomAliasId, RoomVersionId};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::value::RawValue as RawJsonValue;
|
||||
|
||||
@ -27,6 +27,22 @@ impl AliasesEventContent {
|
||||
pub fn new(aliases: Vec<RoomAliasId>) -> Self {
|
||||
Self { aliases }
|
||||
}
|
||||
|
||||
/// Redact an `AliasesEventContent` according to current Matrix spec.
|
||||
pub fn redact(self, version: RoomVersionId) -> RedactedAliasesEventContent {
|
||||
// We compare the long way to avoid pre version 6 behavior if/when
|
||||
// a new room version is introduced.
|
||||
if version.is_version_1()
|
||||
|| version.is_version_2()
|
||||
|| version.is_version_3()
|
||||
|| version.is_version_4()
|
||||
|| version.is_version_5()
|
||||
{
|
||||
RedactedAliasesEventContent { aliases: Some(self.aliases) }
|
||||
} else {
|
||||
RedactedAliasesEventContent { aliases: None }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An aliases event that has been redacted.
|
||||
|
@ -13,11 +13,12 @@ use ruma_events::{
|
||||
message::RedactedMessageEventContent,
|
||||
redaction::{RedactionEvent, RedactionEventContent, SyncRedactionEvent},
|
||||
},
|
||||
AnyRedactedMessageEvent, AnyRedactedSyncMessageEvent, AnyRedactedSyncStateEvent, AnyRoomEvent,
|
||||
AnySyncRoomEvent, RedactedMessageEvent, RedactedSyncMessageEvent, RedactedSyncStateEvent,
|
||||
RedactedSyncUnsigned, RedactedUnsigned, Unsigned,
|
||||
AnyMessageEvent, AnyRedactedMessageEvent, AnyRedactedSyncMessageEvent,
|
||||
AnyRedactedSyncStateEvent, AnyRoomEvent, AnySyncRoomEvent, RedactedMessageEvent,
|
||||
RedactedSyncMessageEvent, RedactedSyncStateEvent, RedactedSyncUnsigned, RedactedUnsigned,
|
||||
Unsigned,
|
||||
};
|
||||
use ruma_identifiers::{EventId, RoomId, UserId};
|
||||
use ruma_identifiers::{EventId, RoomId, RoomVersionId, UserId};
|
||||
use serde_json::{from_value as from_json_value, json, to_value as to_json_value};
|
||||
|
||||
fn full_unsigned() -> RedactedSyncUnsigned {
|
||||
@ -263,10 +264,8 @@ fn redacted_custom_event_serialize() {
|
||||
&& event_type == "m.made.up"
|
||||
);
|
||||
|
||||
let x = from_json_value::<Raw<crate::AnyRedactedSyncStateEvent>>(redacted)
|
||||
.unwrap()
|
||||
.deserialize()
|
||||
.unwrap();
|
||||
let x =
|
||||
from_json_value::<Raw<AnyRedactedSyncStateEvent>>(redacted).unwrap().deserialize().unwrap();
|
||||
assert_eq!(x.event_id(), &EventId::try_from("$h29iv0s8:example.com").unwrap())
|
||||
}
|
||||
|
||||
@ -295,3 +294,47 @@ fn redacted_custom_event_deserialize() {
|
||||
let actual = to_json_value(&redacted).unwrap();
|
||||
assert_eq!(actual, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn redact_method_properly_redacts() {
|
||||
let ev = json!({
|
||||
"type": "m.room.message",
|
||||
"event_id": "$143273582443PhrSn:example.com",
|
||||
"origin_server_ts": 1,
|
||||
"room_id": "!roomid:room.com",
|
||||
"sender": "@user:example.com",
|
||||
"content": {
|
||||
"body": "test",
|
||||
"msgtype": "m.audio",
|
||||
"url": "http://example.com/audio.mp3",
|
||||
}
|
||||
});
|
||||
|
||||
let redaction = RedactionEvent {
|
||||
content: RedactionEventContent { reason: Some("redacted because".into()) },
|
||||
redacts: EventId::try_from("$143273582443PhrSn:example.com").unwrap(),
|
||||
event_id: EventId::try_from("$h29iv0s8:example.com").unwrap(),
|
||||
origin_server_ts: UNIX_EPOCH + Duration::from_millis(1),
|
||||
room_id: RoomId::try_from("!roomid:room.com").unwrap(),
|
||||
sender: UserId::try_from("@carl:example.com").unwrap(),
|
||||
unsigned: Unsigned::default(),
|
||||
};
|
||||
|
||||
let event = from_json_value::<Raw<AnyMessageEvent>>(ev).unwrap().deserialize().unwrap();
|
||||
|
||||
assert_matches!(
|
||||
event.redact(redaction, RoomVersionId::version_6()),
|
||||
AnyRedactedMessageEvent::RoomMessage(RedactedMessageEvent {
|
||||
content: RedactedMessageEventContent,
|
||||
event_id,
|
||||
room_id,
|
||||
sender,
|
||||
origin_server_ts,
|
||||
unsigned,
|
||||
}) if event_id == EventId::try_from("$143273582443PhrSn:example.com").unwrap()
|
||||
&& unsigned.redacted_because.is_some()
|
||||
&& room_id == RoomId::try_from("!roomid:room.com").unwrap()
|
||||
&& sender == UserId::try_from("@user:example.com").unwrap()
|
||||
&& origin_server_ts == UNIX_EPOCH + Duration::from_millis(1)
|
||||
);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user