From 5db1a4d94b7f7a35f89bae78852ac31ab4bc29bf Mon Sep 17 00:00:00 2001 From: Rory& Date: Mon, 17 Nov 2025 12:10:28 +0100 Subject: Event content redaction (v12) --- CONTRIBUTING.MD | 2 +- LibMatrix.EventTypes/EventContent.cs | 4 +++- .../Spec/State/RoomInfo/RoomCreateEventContent.cs | 2 ++ .../Spec/State/RoomInfo/RoomMemberEventContent.cs | 26 +++++++++++++++++++++- LibMatrix/StateEvent.cs | 21 +++++++++++++++++ 5 files changed, 52 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.MD b/CONTRIBUTING.MD index 8c305b7..50c5a4d 100644 --- a/CONTRIBUTING.MD +++ b/CONTRIBUTING.MD @@ -1,6 +1,6 @@ # Contributing -Any contribution is welcome, even if it's just documentation or recommended git practices! We're not too strict on code style, but we do have a few guidelines: +Any contribution is welcome, even if it's just documentation or recommended git practices! We're not too strict on code style, but we do have a few recommendations: - Use spaces, not tabs - Use 4 spaces for indentation - Use the C# naming convention for variables, methods, etc. diff --git a/LibMatrix.EventTypes/EventContent.cs b/LibMatrix.EventTypes/EventContent.cs index d612e44..7a9f0aa 100644 --- a/LibMatrix.EventTypes/EventContent.cs +++ b/LibMatrix.EventTypes/EventContent.cs @@ -1,4 +1,5 @@ using System.Diagnostics.CodeAnalysis; +using System.Net.Http.Json; using System.Reflection; using System.Text.Json; using System.Text.Json.Nodes; @@ -17,6 +18,7 @@ public abstract class EventContent { foreach (var attr in type.GetCustomAttributes(true)) { eventTypes.Add(attr.EventName); } + return eventTypes; } } @@ -55,7 +57,7 @@ public abstract class TimelineEventContent : EventContent { // used for reactions [JsonPropertyName("key")] public string? Key { get; set; } - + [JsonExtensionData] public Dictionary? AdditionalData { get; set; } = []; diff --git a/LibMatrix.EventTypes/Spec/State/RoomInfo/RoomCreateEventContent.cs b/LibMatrix.EventTypes/Spec/State/RoomInfo/RoomCreateEventContent.cs index 8519889..3dd033b 100644 --- a/LibMatrix.EventTypes/Spec/State/RoomInfo/RoomCreateEventContent.cs +++ b/LibMatrix.EventTypes/Spec/State/RoomInfo/RoomCreateEventContent.cs @@ -1,5 +1,7 @@ using System.Diagnostics.CodeAnalysis; +using System.Text.Json.Nodes; using System.Text.Json.Serialization; +using ArcaneLibs.Extensions; namespace LibMatrix.EventTypes.Spec.State.RoomInfo; diff --git a/LibMatrix.EventTypes/Spec/State/RoomInfo/RoomMemberEventContent.cs b/LibMatrix.EventTypes/Spec/State/RoomInfo/RoomMemberEventContent.cs index b034425..287754a 100644 --- a/LibMatrix.EventTypes/Spec/State/RoomInfo/RoomMemberEventContent.cs +++ b/LibMatrix.EventTypes/Spec/State/RoomInfo/RoomMemberEventContent.cs @@ -1,3 +1,5 @@ +using System.Text.Json; +using System.Text.Json.Nodes; using System.Text.Json.Serialization; namespace LibMatrix.EventTypes.Spec.State.RoomInfo; @@ -26,7 +28,29 @@ public class RoomMemberEventContent : EventContent { [JsonPropertyName("join_authorised_via_users_server")] public string? JoinAuthorisedViaUsersServer { get; set; } - + + [JsonPropertyName("third_party_invite")] + public ThirdPartyMemberInvite? ThirdPartyInvite { get; set; } + + public class ThirdPartyMemberInvite { + [JsonPropertyName("display_name")] + public required string DisplayName { get; set; } + + [JsonPropertyName("signed")] + public required SignedThirdPartyInvite Signed { get; set; } + + public class SignedThirdPartyInvite { + [JsonPropertyName("mxid")] + public required string Mxid { get; set; } + + [JsonPropertyName("signatures")] + public required Dictionary> Signatures { get; set; } + + [JsonPropertyName("token")] + public required string Token { get; set; } + } + } + public static class MembershipTypes { public const string Invite = "invite"; public const string Join = "join"; diff --git a/LibMatrix/StateEvent.cs b/LibMatrix/StateEvent.cs index 861b584..dfe393a 100644 --- a/LibMatrix/StateEvent.cs +++ b/LibMatrix/StateEvent.cs @@ -132,6 +132,27 @@ public class MatrixEvent { /// /// public static bool DeepEquals(MatrixEventResponse x, MatrixEventResponse y) => x.Type == y.Type && x.StateKey == y.StateKey && JsonNode.DeepEquals(x.RawContent, y.RawContent); + + public JsonObject GetRedactedContent(string roomVersion) { + JsonObject GetTopLevelKeys(string[] keys) { + var obj = new JsonObject(); + foreach (var key in keys) { + if (RawContent.ContainsKey(key)) + obj[key] = RawContent[key]!; + } + + return obj; + } + + return Type switch { + "m.room.create" => RawContent, // as of v11... TODO: implement older versions + "m.room.member" => GetTopLevelKeys(["membership", "join_authorised_via_users_server"]), // TODO: missing third_party_invite.signed + "m.room.join_rules" => GetTopLevelKeys(["join_rule", "allow"]), + "m.room.power_levels" => GetTopLevelKeys(["ban", "events", "events_default", "kick", "redact", "state_default", "users", "users_default"]), + "m.room.history_visibility" => GetTopLevelKeys(["history_visibility"]), + _ => new JsonObject() + }; + } } public class MatrixEventResponse : MatrixEvent { -- cgit 1.5.1