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
|
// this is the non redacted event content's impl
|
||||||
impl #ident {
|
impl #ident {
|
||||||
/// Transforms the full event content into a redacted content according to spec.
|
/// 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, )* }
|
#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 field_accessor_impl = accessor_methods(kind, var, &variants);
|
||||||
|
|
||||||
|
let redact_impl = generate_redact(&ident, kind, var, &variants);
|
||||||
|
|
||||||
Some(quote! {
|
Some(quote! {
|
||||||
#any_enum
|
#any_enum
|
||||||
|
|
||||||
#field_accessor_impl
|
#field_accessor_impl
|
||||||
|
|
||||||
|
#redact_impl
|
||||||
|
|
||||||
#event_deserialize_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,
|
/// Generates the 3 redacted state enums, 2 redacted message enums,
|
||||||
/// and `Deserialize` implementations.
|
/// and `Deserialize` implementations.
|
||||||
///
|
///
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
//! Types for custom events outside of the Matrix specification.
|
//! Types for custom events outside of the Matrix specification.
|
||||||
|
|
||||||
|
use ruma_identifiers::RoomVersionId;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use serde_json::{value::RawValue as RawJsonValue, Value as JsonValue};
|
use serde_json::{value::RawValue as RawJsonValue, Value as JsonValue};
|
||||||
|
|
||||||
@ -23,7 +24,7 @@ pub struct CustomEventContent {
|
|||||||
|
|
||||||
impl CustomEventContent {
|
impl CustomEventContent {
|
||||||
/// Transforms the full event content into a redacted content according to spec.
|
/// 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 }
|
RedactedCustomEventContent { event_type: self.event_type }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//! Types for the *m.room.aliases* event.
|
//! Types for the *m.room.aliases* event.
|
||||||
|
|
||||||
use ruma_events_macros::StateEventContent;
|
use ruma_events_macros::StateEventContent;
|
||||||
use ruma_identifiers::RoomAliasId;
|
use ruma_identifiers::{RoomAliasId, RoomVersionId};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json::value::RawValue as RawJsonValue;
|
use serde_json::value::RawValue as RawJsonValue;
|
||||||
|
|
||||||
@ -27,6 +27,22 @@ impl AliasesEventContent {
|
|||||||
pub fn new(aliases: Vec<RoomAliasId>) -> Self {
|
pub fn new(aliases: Vec<RoomAliasId>) -> Self {
|
||||||
Self { aliases }
|
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.
|
/// An aliases event that has been redacted.
|
||||||
|
@ -13,11 +13,12 @@ use ruma_events::{
|
|||||||
message::RedactedMessageEventContent,
|
message::RedactedMessageEventContent,
|
||||||
redaction::{RedactionEvent, RedactionEventContent, SyncRedactionEvent},
|
redaction::{RedactionEvent, RedactionEventContent, SyncRedactionEvent},
|
||||||
},
|
},
|
||||||
AnyRedactedMessageEvent, AnyRedactedSyncMessageEvent, AnyRedactedSyncStateEvent, AnyRoomEvent,
|
AnyMessageEvent, AnyRedactedMessageEvent, AnyRedactedSyncMessageEvent,
|
||||||
AnySyncRoomEvent, RedactedMessageEvent, RedactedSyncMessageEvent, RedactedSyncStateEvent,
|
AnyRedactedSyncStateEvent, AnyRoomEvent, AnySyncRoomEvent, RedactedMessageEvent,
|
||||||
RedactedSyncUnsigned, RedactedUnsigned, Unsigned,
|
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};
|
use serde_json::{from_value as from_json_value, json, to_value as to_json_value};
|
||||||
|
|
||||||
fn full_unsigned() -> RedactedSyncUnsigned {
|
fn full_unsigned() -> RedactedSyncUnsigned {
|
||||||
@ -263,10 +264,8 @@ fn redacted_custom_event_serialize() {
|
|||||||
&& event_type == "m.made.up"
|
&& event_type == "m.made.up"
|
||||||
);
|
);
|
||||||
|
|
||||||
let x = from_json_value::<Raw<crate::AnyRedactedSyncStateEvent>>(redacted)
|
let x =
|
||||||
.unwrap()
|
from_json_value::<Raw<AnyRedactedSyncStateEvent>>(redacted).unwrap().deserialize().unwrap();
|
||||||
.deserialize()
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(x.event_id(), &EventId::try_from("$h29iv0s8:example.com").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();
|
let actual = to_json_value(&redacted).unwrap();
|
||||||
assert_eq!(actual, expected);
|
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