base: Make BaseRoomInfo compatible with room version 11

By copying the sender field as the creator field of m.room.create's event content

Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
This commit is contained in:
Kévin Commaille
2023-09-16 09:36:24 +02:00
committed by Benjamin Bouvier
parent 79f408b511
commit acfb999e76
5 changed files with 143 additions and 23 deletions

View File

@@ -43,7 +43,8 @@ pub use http;
pub use matrix_sdk_crypto as crypto;
pub use once_cell;
pub use rooms::{
DisplayName, Room, RoomInfo, RoomMember, RoomMemberships, RoomState, RoomStateFilter,
DisplayName, Room, RoomCreateWithCreatorEventContent, RoomInfo, RoomMember, RoomMemberships,
RoomState, RoomStateFilter,
};
pub use store::{StateChanges, StateStore, StateStoreDataKey, StateStoreDataValue, StoreError};
pub use utils::{

View File

@@ -11,18 +11,24 @@ pub use normal::{Room, RoomInfo, RoomState, RoomStateFilter};
use ruma::{
assign,
events::{
macros::EventContent,
room::{
avatar::RoomAvatarEventContent, canonical_alias::RoomCanonicalAliasEventContent,
create::RoomCreateEventContent, encryption::RoomEncryptionEventContent,
avatar::RoomAvatarEventContent,
canonical_alias::RoomCanonicalAliasEventContent,
create::{PreviousRoom, RoomCreateEventContent},
encryption::RoomEncryptionEventContent,
guest_access::RoomGuestAccessEventContent,
history_visibility::RoomHistoryVisibilityEventContent,
join_rules::RoomJoinRulesEventContent, member::MembershipState,
name::RoomNameEventContent, tombstone::RoomTombstoneEventContent,
join_rules::RoomJoinRulesEventContent,
member::MembershipState,
name::RoomNameEventContent,
tombstone::RoomTombstoneEventContent,
topic::RoomTopicEventContent,
},
AnyStrippedStateEvent, AnySyncStateEvent, RedactContent, RedactedStateEventContent,
StaticStateEventContent, SyncStateEvent,
AnyStrippedStateEvent, AnySyncStateEvent, EmptyStateKey, RedactContent,
RedactedStateEventContent, StaticStateEventContent, SyncStateEvent,
},
room::RoomType,
EventId, OwnedUserId, RoomVersionId,
};
use serde::{Deserialize, Serialize};
@@ -69,7 +75,7 @@ pub struct BaseRoomInfo {
/// The canonical alias of this room.
canonical_alias: Option<MinimalStateEvent<RoomCanonicalAliasEventContent>>,
/// The `m.room.create` event content of this room.
create: Option<MinimalStateEvent<RoomCreateEventContent>>,
create: Option<MinimalStateEvent<RoomCreateWithCreatorEventContent>>,
/// A list of user ids this room is considered as direct message, if this
/// room is a DM.
pub(crate) dm_targets: HashSet<OwnedUserId>,
@@ -311,6 +317,99 @@ fn calculate_room_name(
}
}
/// The content of an `m.room.create` event, with a required `creator` field.
///
/// Starting with room version 11, the `creator` field should be removed and the
/// `sender` field of the event should be used instead. This is reflected on
/// [`RoomCreateEventContent`].
///
/// This type was created as an alternative for ease of use. When it is used in
/// the SDK, it is constructed by copying the `sender` of the original event as
/// the `creator`.
#[derive(Clone, Debug, Deserialize, Serialize, EventContent)]
#[ruma_event(type = "m.room.create", kind = State, state_key_type = EmptyStateKey, custom_redacted)]
pub struct RoomCreateWithCreatorEventContent {
/// The `user_id` of the room creator.
///
/// This is set by the homeserver.
///
/// While this should be optional since room version 11, we copy the sender
/// of the event so we can still access it.
pub creator: OwnedUserId,
/// Whether or not this room's data should be transferred to other
/// homeservers.
#[serde(
rename = "m.federate",
default = "ruma::serde::default_true",
skip_serializing_if = "ruma::serde::is_true"
)]
pub federate: bool,
/// The version of the room.
///
/// Defaults to `RoomVersionId::V1`.
#[serde(default = "default_create_room_version_id")]
pub room_version: RoomVersionId,
/// A reference to the room this room replaces, if the previous room was
/// upgraded.
#[serde(skip_serializing_if = "Option::is_none")]
pub predecessor: Option<PreviousRoom>,
/// The room type.
///
/// This is currently only used for spaces.
#[serde(skip_serializing_if = "Option::is_none", rename = "type")]
pub room_type: Option<RoomType>,
}
impl RoomCreateWithCreatorEventContent {
/// Constructs a `RoomCreateWithCreatorEventContent` with the given original
/// content and sender.
pub fn from_event_content(content: RoomCreateEventContent, sender: OwnedUserId) -> Self {
let RoomCreateEventContent { federate, room_version, predecessor, room_type, .. } = content;
Self { creator: sender, federate, room_version, predecessor, room_type }
}
fn into_event_content(self) -> (RoomCreateEventContent, OwnedUserId) {
let Self { creator, federate, room_version, predecessor, room_type } = self;
#[allow(deprecated)]
let content = assign!(RoomCreateEventContent::new_v11(), {
creator: Some(creator.clone()),
federate,
room_version,
predecessor,
room_type,
});
(content, creator)
}
}
/// Redacted form of [`RoomCreateWithCreatorEventContent`].
pub type RedactedRoomCreateWithCreatorEventContent = RoomCreateWithCreatorEventContent;
impl RedactedStateEventContent for RedactedRoomCreateWithCreatorEventContent {
type StateKey = EmptyStateKey;
}
impl RedactContent for RoomCreateWithCreatorEventContent {
type Redacted = RedactedRoomCreateWithCreatorEventContent;
fn redact(self, version: &RoomVersionId) -> Self::Redacted {
let (content, sender) = self.into_event_content();
// Use Ruma's redaction algorithm.
let content = content.redact(version);
Self::from_event_content(content, sender)
}
}
fn default_create_room_version_id() -> RoomVersionId {
RoomVersionId::V1
}
bitflags! {
/// Room membership filter as a bitset.
///

View File

@@ -35,7 +35,6 @@ use ruma::{
ignored_user_list::IgnoredUserListEventContent,
receipt::{Receipt, ReceiptThread, ReceiptType},
room::{
create::RoomCreateEventContent,
encryption::RoomEncryptionEventContent,
guest_access::GuestAccess,
history_visibility::HistoryVisibility,
@@ -59,7 +58,7 @@ use tracing::{debug, field::debug, info, instrument, trace, warn};
use super::{
members::{MemberInfo, MemberRoomInfo},
BaseRoomInfo, DisplayName, RoomMember,
BaseRoomInfo, DisplayName, RoomCreateWithCreatorEventContent, RoomMember,
};
use crate::{
deserialized_responses::MemberEvent,
@@ -257,10 +256,7 @@ impl Room {
/// This usually isn't optional but some servers might not send an
/// `m.room.create` event as the first event for a given room, thus this can
/// be optional.
///
/// It can also be redacted in current room versions, leaving only the
/// `creator` field.
pub fn create_content(&self) -> Option<RoomCreateEventContent> {
pub fn create_content(&self) -> Option<RoomCreateWithCreatorEventContent> {
self.inner
.read()
.base_info
@@ -995,10 +991,9 @@ impl RoomInfo {
}
fn creator(&self) -> Option<&UserId> {
#[allow(deprecated)]
match self.base_info.create.as_ref()? {
MinimalStateEvent::Original(ev) => ev.content.creator.as_deref(),
MinimalStateEvent::Redacted(ev) => ev.content.creator.as_deref(),
MinimalStateEvent::Original(ev) => Some(&ev.content.creator),
MinimalStateEvent::Redacted(ev) => Some(&ev.content.creator),
}
}

View File

@@ -4,7 +4,7 @@ use ruma::{
room::{
avatar::{RoomAvatarEventContent, StrippedRoomAvatarEvent},
canonical_alias::{RoomCanonicalAliasEventContent, StrippedRoomCanonicalAliasEvent},
create::{RoomCreateEventContent, StrippedRoomCreateEvent},
create::{StrippedRoomCreateEvent, SyncRoomCreateEvent},
guest_access::{
RedactedRoomGuestAccessEventContent, RoomGuestAccessEventContent,
StrippedRoomGuestAccessEvent,
@@ -28,6 +28,8 @@ use ruma::{
};
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use crate::rooms::RoomCreateWithCreatorEventContent;
// #[serde(bound)] instead of DeserializeOwned in type where clause does not
// work, it can only be a single bound that replaces the default and if a helper
// trait is used, the compiler still complains about Deserialize not being
@@ -181,6 +183,27 @@ where
}
}
impl From<&SyncRoomCreateEvent> for MinimalStateEvent<RoomCreateWithCreatorEventContent> {
fn from(ev: &SyncRoomCreateEvent) -> Self {
match ev {
SyncStateEvent::Original(ev) => Self::Original(OriginalMinimalStateEvent {
content: RoomCreateWithCreatorEventContent::from_event_content(
ev.content.clone(),
ev.sender.clone(),
),
event_id: Some(ev.event_id.clone()),
}),
SyncStateEvent::Redacted(ev) => Self::Redacted(RedactedMinimalStateEvent {
content: RoomCreateWithCreatorEventContent::from_event_content(
ev.content.clone(),
ev.sender.clone(),
),
event_id: Some(ev.event_id.clone()),
}),
}
}
}
impl From<&StrippedRoomAvatarEvent> for MinimalStateEvent<RoomAvatarEventContent> {
fn from(event: &StrippedRoomAvatarEvent) -> Self {
let content = assign!(RoomAvatarEventContent::new(), {
@@ -208,14 +231,15 @@ impl From<&StrippedRoomNameEvent> for MinimalStateEvent<RoomNameEventContent> {
}
}
impl From<&StrippedRoomCreateEvent> for MinimalStateEvent<RoomCreateEventContent> {
impl From<&StrippedRoomCreateEvent> for MinimalStateEvent<RoomCreateWithCreatorEventContent> {
fn from(event: &StrippedRoomCreateEvent) -> Self {
let content = assign!(RoomCreateEventContent::new_v1(event.sender.clone()), {
let content = RoomCreateWithCreatorEventContent {
creator: event.sender.clone(),
federate: event.content.federate,
room_version: event.content.room_version.clone(),
predecessor: event.content.predecessor.clone(),
room_type: event.content.room_type.clone(),
});
};
Self::Original(OriginalMinimalStateEvent { content, event_id: None })
}
}

View File

@@ -23,8 +23,9 @@ pub use matrix_sdk_base::crypto;
pub use matrix_sdk_base::{
deserialized_responses,
store::{DynStateStore, MemoryStore, StateStoreExt},
DisplayName, Room as BaseRoom, RoomInfo, RoomMember as BaseRoomMember, RoomMemberships,
RoomState, SessionMeta, StateChanges, StateStore, StoreError,
DisplayName, Room as BaseRoom, RoomCreateWithCreatorEventContent, RoomInfo,
RoomMember as BaseRoomMember, RoomMemberships, RoomState, SessionMeta, StateChanges,
StateStore, StoreError,
};
pub use matrix_sdk_common::*;
pub use reqwest;