Merge remote-tracking branch 'origin/main' into ben-remove-store-key

This commit is contained in:
Benjamin Kampmann
2022-04-19 10:41:40 +02:00
45 changed files with 451 additions and 315 deletions

View File

@@ -12,7 +12,7 @@ criterion = { version = "0.3.4", features = ["async", "async_tokio", "html_repor
matrix-sdk-crypto = { path = "../crates/matrix-sdk-crypto" }
matrix-sdk-sled = { path = "../crates/matrix-sdk-sled", default-features = false, features = ["crypto-store"] }
matrix-sdk-test = { path = "../crates/matrix-sdk-test" }
ruma = { git = "https://github.com/ruma/ruma", rev = "deea762b8" }
ruma = { git = "https://github.com/ruma/ruma", rev = "548232ef5" }
serde_json = "1.0.79"
tempfile = "3.2.0"
tokio = { version = "1.7.1", default-features = false, features = ["rt-multi-thread"] }

View File

@@ -47,7 +47,7 @@ features = ["rt-multi-thread"]
[dependencies.ruma]
git = "https://github.com/ruma/ruma"
rev = "deea762b8"
rev = "548232ef5"
features = ["client-api-c"]
[build-dependencies]

View File

@@ -31,7 +31,7 @@ use ruma::{
IncomingResponse,
},
events::{
key::verification::VerificationMethod, room::encrypted::SyncRoomEncryptedEvent,
key::verification::VerificationMethod, room::encrypted::OriginalSyncRoomEncryptedEvent,
AnyMessageLikeEventContent, EventContent,
},
DeviceKeyAlgorithm, EventId, RoomId, TransactionId, UserId,
@@ -535,7 +535,7 @@ impl OlmMachine {
content: &'a RawValue,
}
let event: SyncRoomEncryptedEvent = serde_json::from_str(event)?;
let event: OriginalSyncRoomEncryptedEvent = serde_json::from_str(event)?;
let room_id = RoomId::parse(room_id)?;
let decrypted = self.runtime.block_on(self.inner.decrypt_room_event(&event, &room_id))?;
@@ -573,7 +573,7 @@ impl OlmMachine {
event: &str,
room_id: &str,
) -> Result<KeyRequestPair, DecryptionError> {
let event: SyncRoomEncryptedEvent = serde_json::from_str(event)?;
let event: OriginalSyncRoomEncryptedEvent = serde_json::from_str(event)?;
let room_id = RoomId::parse(room_id)?;
let (cancel, request) =

View File

@@ -24,10 +24,10 @@ base64 = "0.13.0"
byteorder = "1.4.3"
image = { version = "0.23.14", optional = true }
qrcode = { version = "0.12.0", default-features = false }
ruma-common = { git = "https://github.com/ruma/ruma", rev = "deea762b8" }
ruma-common = { git = "https://github.com/ruma/ruma", rev = "548232ef5" }
rqrr = { version = "0.4.0", optional = true }
thiserror = "1.0.25"
[dependencies.vodozemac]
git = "https://github.com/matrix-org/vodozemac"
rev = "443b6530510004a60a9e5937ff4021f7b06f63c8"
rev = "e09c93f2c8df9770793abeec57ed984d5e1f3834"

View File

@@ -29,7 +29,7 @@ http = "0.2"
matrix-sdk = { version = "0.4", path = "../matrix-sdk", default-features = false, features = ["appservice"] }
percent-encoding = "2.1.0"
regex = "1"
ruma = { git = "https://github.com/ruma/ruma", rev = "deea762b8", features = ["client-api-c", "appservice-api-s"] }
ruma = { git = "https://github.com/ruma/ruma", rev = "548232ef5", features = ["client-api-c", "appservice-api-s"] }
serde = "1"
serde_json = "1"
serde_yaml = "0.8"

View File

@@ -5,7 +5,7 @@ use matrix_sdk_appservice::{
event_handler::Ctx,
room::Room,
ruma::{
events::room::member::{MembershipState, SyncRoomMemberEvent},
events::room::member::{MembershipState, OriginalSyncRoomMemberEvent},
UserId,
},
},
@@ -16,7 +16,7 @@ use tracing::trace;
pub async fn handle_room_member(
appservice: AppService,
room: Room,
event: SyncRoomMemberEvent,
event: OriginalSyncRoomMemberEvent,
) -> Result<()> {
if !appservice.user_id_is_in_namespace(&event.state_key)? {
trace!("not an appservice user: {}", event.state_key);
@@ -44,7 +44,9 @@ pub async fn main() -> Result<(), Box<dyn std::error::Error>> {
appservice
.register_event_handler_context(appservice.clone())?
.register_event_handler(
move |event: SyncRoomMemberEvent, room: Room, Ctx(appservice): Ctx<AppService>| {
move |event: OriginalSyncRoomMemberEvent,
room: Room,
Ctx(appservice): Ctx<AppService>| {
handle_room_member(appservice, room, event)
},
)

View File

@@ -5,7 +5,7 @@ use std::{
use matrix_sdk::{
config::RequestConfig,
ruma::{api::appservice::Registration, events::room::member::SyncRoomMemberEvent},
ruma::{api::appservice::Registration, events::room::member::OriginalSyncRoomMemberEvent},
Client,
};
use matrix_sdk_appservice::*;
@@ -204,7 +204,7 @@ async fn test_event_handler() -> Result<()> {
appservice
.register_event_handler({
let on_state_member = on_state_member.clone();
move |_ev: SyncRoomMemberEvent| {
move |_ev: OriginalSyncRoomMemberEvent| {
*on_state_member.lock().unwrap() = true;
future::ready(())
}

View File

@@ -36,7 +36,7 @@ matrix-sdk-common = { version = "0.4.0", path = "../matrix-sdk-common" }
matrix-sdk-crypto = { version = "0.4.0", path = "../matrix-sdk-crypto", optional = true }
pbkdf2 = { version = "0.10.0", default-features = false, optional = true }
rand = { version = "0.8.4", optional = true }
ruma = { git = "https://github.com/ruma/ruma", rev = "deea762b8", features = ["client-api-c", "signatures"] }
ruma = { git = "https://github.com/ruma/ruma", rev = "548232ef5", features = ["client-api-c", "signatures"] }
serde = { version = "1.0.126", features = ["rc"] }
serde_json = "1.0.64"
sha2 = { version = "0.10.1", optional = true }

View File

@@ -45,7 +45,7 @@ use ruma::{
api::client::keys::claim_keys::v3::Request as KeysClaimRequest,
events::{
room::{encrypted::RoomEncryptedEventContent, history_visibility::HistoryVisibility},
AnySyncMessageLikeEvent, EventContent, MessageLikeEventType,
AnySyncMessageLikeEvent, MessageLikeEventContent, SyncMessageLikeEvent,
},
DeviceId, TransactionId,
};
@@ -55,6 +55,7 @@ use ruma::{
push_rules::PushRulesEvent, room::member::MembershipState, AnyGlobalAccountDataEvent,
AnyRoomAccountDataEvent, AnyStrippedStateEvent, AnySyncEphemeralRoomEvent,
AnySyncRoomEvent, AnySyncStateEvent, GlobalAccountDataEventType, StateEventType,
SyncStateEvent,
},
push::{Action, PushConditionRoomCtx, Ruleset},
serde::Raw,
@@ -260,7 +261,7 @@ impl BaseClient {
#[allow(clippy::single_match)]
match &e {
AnySyncRoomEvent::State(s) => match s {
AnySyncStateEvent::RoomMember(member) => {
AnySyncStateEvent::RoomMember(SyncStateEvent::Original(member)) => {
if let Ok(member) = MemberEvent::try_from(member.clone()) {
ambiguity_cache.handle_event(changes, room_id, &member).await?;
@@ -293,7 +294,7 @@ impl BaseClient {
}
}
_ => {
room_info.handle_state_event(&s.content());
room_info.handle_state_event(s);
let raw_event: Raw<AnySyncStateEvent> = event.event.clone().cast();
changes.add_state_event(room_id, s.clone(), raw_event);
}
@@ -301,7 +302,7 @@ impl BaseClient {
#[cfg(feature = "encryption")]
AnySyncRoomEvent::MessageLike(AnySyncMessageLikeEvent::RoomEncrypted(
encrypted,
SyncMessageLikeEvent::Original(encrypted),
)) => {
if let Some(olm) = self.olm_machine().await {
if let Ok(decrypted) =
@@ -385,7 +386,7 @@ impl BaseClient {
}
}
Ok(e) => {
room_info.handle_state_event(&e.content());
room_info.handle_stripped_state_event(&e);
state_events
.entry(e.event_type())
.or_insert_with(BTreeMap::new)
@@ -429,9 +430,9 @@ impl BaseClient {
}
};
room_info.handle_state_event(&event.content());
room_info.handle_state_event(&event);
if let AnySyncStateEvent::RoomMember(member) = event {
if let AnySyncStateEvent::RoomMember(SyncStateEvent::Original(member)) = event {
match MemberEvent::try_from(member) {
Ok(m) => {
ambiguity_cache.handle_event(changes, &room_id, &m).await?;
@@ -1020,7 +1021,7 @@ impl BaseClient {
pub async fn encrypt(
&self,
room_id: &RoomId,
content: impl EventContent<EventType = MessageLikeEventType>,
content: impl MessageLikeEventContent,
) -> Result<RoomEncryptedEventContent> {
match self.olm_machine().await {
Some(o) => Ok(o.encrypt(room_id, content).await?),
@@ -1210,14 +1211,14 @@ impl BaseClient {
.and_then(|events| events.get(""))
.and_then(|e| e.deserialize().ok())
{
event.content
event.power_levels()
} else if let Some(AnySyncStateEvent::RoomPowerLevels(event)) = self
.store
.get_state_event(room_id, StateEventType::RoomPowerLevels, "")
.await?
.and_then(|e| e.deserialize().ok())
{
event.content
event.power_levels()
} else {
return Ok(None);
};
@@ -1260,7 +1261,7 @@ impl BaseClient {
.and_then(|events| events.get(""))
.and_then(|e| e.deserialize().ok())
{
let room_power_levels = event.content;
let room_power_levels = event.power_levels();
push_rules.users_power_levels = room_power_levels.users;
push_rules.default_power_level = room_power_levels.users_default;

View File

@@ -92,11 +92,11 @@ impl RoomMember {
(*self.power_levels)
.as_ref()
.map(|e| {
e.content
.users
let pls = e.power_levels();
pls.users
.get(self.user_id())
.map(|p| (*p).into())
.unwrap_or_else(|| e.content.users_default.into())
.unwrap_or_else(|| pls.users_default.into())
})
.unwrap_or_else(|| if self.is_room_creator { 100 } else { 0 })
}

View File

@@ -12,7 +12,7 @@ use ruma::{
guest_access::GuestAccess, history_visibility::HistoryVisibility, join_rules::JoinRule,
tombstone::RoomTombstoneEventContent,
},
AnyStateEventContent,
AnyStrippedStateEvent, AnySyncStateEvent, SyncStateEvent,
},
MxcUri, RoomAliasId, UserId,
};
@@ -72,42 +72,103 @@ impl BaseRoomInfo {
/// Handle a state event for this room and update our info accordingly.
///
/// Returns true if the event modified the info, false otherwise.
pub fn handle_state_event(&mut self, content: &AnyStateEventContent) -> bool {
match content {
AnyStateEventContent::RoomEncryption(encryption) => {
self.encryption = Some(encryption.clone());
pub fn handle_state_event(&mut self, ev: &AnySyncStateEvent) -> bool {
match ev {
// No redacted branch - enabling encryption cannot be undone.
AnySyncStateEvent::RoomEncryption(SyncStateEvent::Original(encryption)) => {
self.encryption = Some(encryption.content.clone());
}
AnyStateEventContent::RoomAvatar(a) => {
self.avatar_url = a.url.clone();
AnySyncStateEvent::RoomAvatar(a) => {
self.avatar_url = a.as_original().and_then(|a| a.content.url.clone());
}
AnyStateEventContent::RoomName(n) => {
self.name = n.name.as_ref().map(|n| n.to_string());
AnySyncStateEvent::RoomName(n) => {
self.name =
n.as_original().and_then(|n| n.content.name.as_ref().map(|n| n.to_string()));
}
AnyStateEventContent::RoomCreate(c) if self.create.is_none() => {
self.create = Some(c.clone());
AnySyncStateEvent::RoomCreate(SyncStateEvent::Original(c)) if self.create.is_none() => {
self.create = Some(c.content.clone());
}
AnyStateEventContent::RoomHistoryVisibility(h) => {
self.history_visibility = h.history_visibility.clone();
AnySyncStateEvent::RoomHistoryVisibility(h) => {
self.history_visibility = match h {
SyncStateEvent::Original(h) => h.content.history_visibility.clone(),
SyncStateEvent::Redacted(h) => h.content.history_visibility.clone(),
};
}
AnyStateEventContent::RoomGuestAccess(g) => {
self.guest_access = g.guest_access.clone();
AnySyncStateEvent::RoomGuestAccess(g) => {
self.guest_access = g
.as_original()
.map_or(GuestAccess::Forbidden, |g| g.content.guest_access.clone());
}
AnyStateEventContent::RoomJoinRules(c) => {
self.join_rule = c.join_rule.clone();
AnySyncStateEvent::RoomJoinRules(c) => {
self.join_rule = match c {
SyncStateEvent::Original(c) => c.content.join_rule.clone(),
SyncStateEvent::Redacted(c) => c.content.join_rule.clone(),
};
}
AnyStateEventContent::RoomCanonicalAlias(a) => {
self.canonical_alias = a.alias.clone();
AnySyncStateEvent::RoomCanonicalAlias(a) => {
self.canonical_alias = a.as_original().and_then(|a| a.content.alias.clone());
}
AnyStateEventContent::RoomTopic(t) => {
self.topic = Some(t.topic.clone());
AnySyncStateEvent::RoomTopic(t) => {
self.topic = t.as_original().map(|t| t.content.topic.clone());
}
AnyStateEventContent::RoomTombstone(t) => {
self.tombstone = Some(t.clone());
AnySyncStateEvent::RoomTombstone(t) => {
self.tombstone = t.as_original().map(|t| t.content.clone());
}
AnyStateEventContent::RoomPowerLevels(p) => {
let max_power_level =
p.users.values().fold(self.max_power_level, |acc, &p| max(acc, p.into()));
self.max_power_level = max_power_level;
AnySyncStateEvent::RoomPowerLevels(p) => {
self.max_power_level = p
.power_levels()
.users
.values()
.fold(self.max_power_level, |acc, &p| max(acc, p.into()));
}
_ => return false,
}
true
}
/// Handle a stripped state event for this room and update our info
/// accordingly.
///
/// Returns true if the event modified the info, false otherwise.
pub fn handle_stripped_state_event(&mut self, ev: &AnyStrippedStateEvent) -> bool {
match ev {
AnyStrippedStateEvent::RoomEncryption(encryption) => {
self.encryption = Some(encryption.content.clone());
}
AnyStrippedStateEvent::RoomAvatar(a) => {
self.avatar_url = a.content.url.clone();
}
AnyStrippedStateEvent::RoomName(n) => {
self.name = n.content.name.as_ref().map(|n| n.to_string());
}
AnyStrippedStateEvent::RoomCreate(c) if self.create.is_none() => {
self.create = Some(c.content.clone());
}
AnyStrippedStateEvent::RoomHistoryVisibility(h) => {
self.history_visibility = h.content.history_visibility.clone();
}
AnyStrippedStateEvent::RoomGuestAccess(g) => {
self.guest_access = g.content.guest_access.clone();
}
AnyStrippedStateEvent::RoomJoinRules(c) => {
self.join_rule = c.content.join_rule.clone();
}
AnyStrippedStateEvent::RoomCanonicalAlias(a) => {
self.canonical_alias = a.content.alias.clone();
}
AnyStrippedStateEvent::RoomTopic(t) => {
self.topic = Some(t.content.topic.clone());
}
AnyStrippedStateEvent::RoomTombstone(t) => {
self.tombstone = Some(t.content.clone());
}
AnyStrippedStateEvent::RoomPowerLevels(p) => {
self.max_power_level = p
.content
.users
.values()
.fold(self.max_power_level, |acc, &p| max(acc, p.into()));
}
_ => return false,
}
@@ -124,7 +185,7 @@ impl Default for BaseRoomInfo {
create: None,
dm_target: None,
encryption: None,
guest_access: GuestAccess::CanJoin,
guest_access: GuestAccess::Forbidden,
history_visibility: HistoryVisibility::WorldReadable,
join_rule: JoinRule::Public,
max_power_level: 100,

View File

@@ -29,8 +29,8 @@ use ruma::{
tombstone::RoomTombstoneEventContent,
},
tag::Tags,
AnyRoomAccountDataEvent, AnyStateEventContent, AnySyncStateEvent, RoomAccountDataEventType,
StateEventType,
AnyRoomAccountDataEvent, AnyStrippedStateEvent, AnySyncStateEvent,
RoomAccountDataEventType, StateEventType,
},
receipt::ReceiptType,
room::RoomType as CreateRoomType,
@@ -654,13 +654,20 @@ impl RoomInfo {
self.base_info.encryption.is_some()
}
/// handle the given State event.
/// Handle the given state event.
///
/// Returns true if the event modified the info, false otherwise.
pub fn handle_state_event(&mut self, event: &AnyStateEventContent) -> bool {
pub fn handle_state_event(&mut self, event: &AnySyncStateEvent) -> bool {
self.base_info.handle_state_event(event)
}
/// Handle the given stripped tate event.
///
/// Returns true if the event modified the info, false otherwise.
pub fn handle_stripped_state_event(&mut self, event: &AnyStrippedStateEvent) -> bool {
self.base_info.handle_stripped_state_event(event)
}
/// Update the notifications count
pub fn update_notification_count(&mut self, notification_counts: UnreadNotificationsCount) {
self.notification_counts = notification_counts;

View File

@@ -147,14 +147,14 @@ macro_rules! statestore_integration_tests {
let name_json: &JsonValue = &test_json::NAME;
let name_raw = serde_json::from_value::<Raw<AnySyncStateEvent>>(name_json.clone()).unwrap();
let name_event = name_raw.deserialize().unwrap();
room.handle_state_event(&name_event.content());
room.handle_state_event(&name_event);
changes.add_state_event(room_id, name_event, name_raw);
let topic_json: &JsonValue = &test_json::TOPIC;
let topic_raw =
serde_json::from_value::<Raw<AnySyncStateEvent>>(topic_json.clone()).unwrap();
let topic_event = topic_raw.deserialize().unwrap();
room.handle_state_event(&topic_event.content());
room.handle_state_event(&topic_event);
changes.add_state_event(room_id, topic_event, topic_raw);
let mut room_ambiguity_map = BTreeMap::new();
@@ -213,7 +213,7 @@ macro_rules! statestore_integration_tests {
serde_json::from_value::<Raw<AnyStrippedStateEvent>>(stripped_name_json.clone())
.unwrap();
let stripped_name_event = stripped_name_raw.deserialize().unwrap();
stripped_room.handle_state_event(&stripped_name_event.content());
stripped_room.handle_stripped_state_event(&stripped_name_event);
changes.stripped_state.insert(
stripped_room_id.to_owned(),
BTreeMap::from([(

View File

@@ -26,7 +26,10 @@ use ruma::{
events::{
presence::PresenceEvent,
receipt::Receipt,
room::member::{MembershipState, RoomMemberEventContent},
room::{
member::{MembershipState, RoomMemberEventContent},
redaction::SyncRoomRedactionEvent,
},
AnyGlobalAccountDataEvent, AnyRoomAccountDataEvent, AnyStrippedStateEvent,
AnySyncMessageLikeEvent, AnySyncRoomEvent, AnySyncStateEvent, GlobalAccountDataEventType,
RoomAccountDataEventType, StateEventType,
@@ -361,7 +364,9 @@ impl MemoryStore {
for event in &timeline.events {
// Redact events already in store only on sync response
if let Ok(AnySyncRoomEvent::MessageLike(
AnySyncMessageLikeEvent::RoomRedaction(redaction),
AnySyncMessageLikeEvent::RoomRedaction(SyncRoomRedactionEvent::Original(
redaction,
)),
)) = event.event.deserialize()
{
let pos = data.event_id_to_position.get(&redaction.redacts).copied();

View File

@@ -17,7 +17,7 @@ targets = ["x86_64-unknown-linux-gnu", "wasm32-unknown-unknown"]
[dependencies]
async-trait = "0.1.50"
ruma = { git = "https://github.com/ruma/ruma", rev = "deea762b8", features = ["client-api-c"] }
ruma = { git = "https://github.com/ruma/ruma", rev = "548232ef5", features = ["client-api-c"] }
serde = "1.0.126"
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]

View File

@@ -10,7 +10,8 @@ use ruma::{
},
events::{
room::member::{
RoomMemberEvent, RoomMemberEventContent, StrippedRoomMemberEvent, SyncRoomMemberEvent,
OriginalRoomMemberEvent, OriginalSyncRoomMemberEvent, RoomMemberEventContent,
StrippedRoomMemberEvent,
},
AnyRoomEvent, AnySyncRoomEvent, StateUnsigned,
},
@@ -296,7 +297,7 @@ impl TimelineSlice {
}
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(try_from = "SyncRoomMemberEvent", into = "SyncRoomMemberEvent")]
#[serde(try_from = "OriginalSyncRoomMemberEvent", into = "OriginalSyncRoomMemberEvent")]
pub struct MemberEvent {
pub content: RoomMemberEventContent,
pub event_id: Box<EventId>,
@@ -306,10 +307,10 @@ pub struct MemberEvent {
pub unsigned: StateUnsigned<RoomMemberEventContent>,
}
impl TryFrom<SyncRoomMemberEvent> for MemberEvent {
impl TryFrom<OriginalSyncRoomMemberEvent> for MemberEvent {
type Error = ruma::IdParseError;
fn try_from(event: SyncRoomMemberEvent) -> Result<Self, Self::Error> {
fn try_from(event: OriginalSyncRoomMemberEvent) -> Result<Self, Self::Error> {
Ok(MemberEvent {
content: event.content,
event_id: event.event_id,
@@ -321,10 +322,10 @@ impl TryFrom<SyncRoomMemberEvent> for MemberEvent {
}
}
impl TryFrom<RoomMemberEvent> for MemberEvent {
impl TryFrom<OriginalRoomMemberEvent> for MemberEvent {
type Error = ruma::IdParseError;
fn try_from(event: RoomMemberEvent) -> Result<Self, Self::Error> {
fn try_from(event: OriginalRoomMemberEvent) -> Result<Self, Self::Error> {
Ok(MemberEvent {
content: event.content,
event_id: event.event_id,
@@ -336,7 +337,7 @@ impl TryFrom<RoomMemberEvent> for MemberEvent {
}
}
impl From<MemberEvent> for SyncRoomMemberEvent {
impl From<MemberEvent> for OriginalSyncRoomMemberEvent {
fn from(other: MemberEvent) -> Self {
Self {
content: other.content,
@@ -395,8 +396,8 @@ mod tests {
use ruma::{
event_id,
events::{
room::message::RoomMessageEventContent, AnyMessageLikeEvent, AnySyncMessageLikeEvent,
AnySyncRoomEvent, MessageLikeEvent, MessageLikeUnsigned,
room::message::RoomMessageEventContent, AnySyncMessageLikeEvent, AnySyncRoomEvent,
MessageLikeUnsigned, OriginalMessageLikeEvent, SyncMessageLikeEvent,
},
room_id,
serde::Raw,
@@ -409,7 +410,7 @@ mod tests {
fn room_event_to_sync_room_event() {
let content = RoomMessageEventContent::text_plain("foobar");
let event = MessageLikeEvent {
let event = OriginalMessageLikeEvent {
content,
event_id: event_id!("$xxxxx:example.org").to_owned(),
room_id: room_id!("!someroom:example.com").to_owned(),
@@ -425,9 +426,9 @@ mod tests {
let converted_event: AnySyncRoomEvent = converted_room_event.event.deserialize().unwrap();
let event: AnyMessageLikeEvent = event.into();
let sync_event: AnySyncMessageLikeEvent = event.into();
let sync_event: AnySyncRoomEvent = sync_event.into();
let sync_event = AnySyncRoomEvent::MessageLike(AnySyncMessageLikeEvent::RoomMessage(
SyncMessageLikeEvent::Original(event.into()),
));
// There is no PartialEq implementation for AnySyncRoomEvent, so we
// just compare a couple of fields here. The important thing is that

View File

@@ -52,16 +52,16 @@ http = { version = "0.2.4", optional = true }
[target.'cfg(not(target_arch = "wasm32"))'.dependencies.vodozemac]
git = "https://github.com/matrix-org/vodozemac"
rev = "443b6530510004a60a9e5937ff4021f7b06f63c8"
rev = "e09c93f2c8df9770793abeec57ed984d5e1f3834"
[target.'cfg(target_arch = "wasm32")'.dependencies.vodozemac]
git = "https://github.com/matrix-org/vodozemac"
rev = "443b6530510004a60a9e5937ff4021f7b06f63c8"
rev = "e09c93f2c8df9770793abeec57ed984d5e1f3834"
features = ["js"]
[dependencies.ruma]
git = "https://github.com/ruma/ruma"
rev = "deea762b8"
rev = "548232ef5"
features = ["client-api-c", "rand", "unstable-msc2676", "unstable-msc2677"]
[dev-dependencies]

View File

@@ -39,7 +39,7 @@ pub enum OlmError {
/// The received room key couldn't be converted into a valid Megolm session.
#[error(transparent)]
SessionCreation(#[from] vodozemac::megolm::SessionCreationError),
SessionCreation(#[from] vodozemac::megolm::SessionKeyDecodeError),
/// The storage layer returned an error.
#[error("failed to read or write to the crypto store {0}")]

View File

@@ -336,7 +336,7 @@ mod tests {
let decrypted = decrypt_key_export(Cursor::new(encrypted), "1234").unwrap();
for (exported, decrypted) in export.iter().zip(decrypted.iter()) {
assert_eq!(exported.session_key.as_str(), decrypted.session_key.as_str());
assert_eq!(exported.session_key.to_base64(), decrypted.session_key.to_base64());
}
assert_eq!(

View File

@@ -14,7 +14,6 @@
use std::{
collections::{BTreeMap, BTreeSet, HashSet},
mem,
sync::Arc,
};
@@ -36,18 +35,19 @@ use ruma::{
assign,
events::{
room::encrypted::{
EncryptedEventScheme, MegolmV1AesSha2Content, RoomEncryptedEventContent,
SyncRoomEncryptedEvent, ToDeviceRoomEncryptedEvent,
EncryptedEventScheme, MegolmV1AesSha2Content, OriginalSyncRoomEncryptedEvent,
RoomEncryptedEventContent, ToDeviceRoomEncryptedEvent,
},
room_key::ToDeviceRoomKeyEvent,
secret::request::SecretName,
AnyRoomEvent, AnyToDeviceEvent, EventContent, MessageLikeEventType,
AnyRoomEvent, AnyToDeviceEvent, MessageLikeEventContent,
},
DeviceId, DeviceKeyAlgorithm, DeviceKeyId, EventEncryptionAlgorithm, RoomId, TransactionId,
UInt, UserId,
};
use serde_json::Value;
use tracing::{debug, error, info, trace, warn};
use zeroize::Zeroize;
#[cfg(feature = "backups_v1")]
use crate::backups::BackupMachine;
@@ -556,16 +556,17 @@ impl OlmMachine {
) -> OlmResult<(Option<AnyToDeviceEvent>, Option<InboundGroupSession>)> {
match event.content.algorithm {
EventEncryptionAlgorithm::MegolmV1AesSha2 => {
let session_key = SessionKey(mem::take(&mut event.content.session_key));
match SessionKey::from_base64(&event.content.session_key) {
Ok(session_key) => {
event.content.session_key.zeroize();
let session = InboundGroupSession::new(
sender_key,
signing_key,
&event.content.room_id,
session_key,
None,
);
match InboundGroupSession::new(
sender_key,
signing_key,
&event.content.room_id,
session_key,
None,
) {
Ok(session) => {
info!(
sender = event.sender.as_str(),
sender_key = sender_key,
@@ -658,7 +659,7 @@ impl OlmMachine {
pub async fn encrypt(
&self,
room_id: &RoomId,
content: impl EventContent<EventType = MessageLikeEventType>,
content: impl MessageLikeEventContent,
) -> MegolmResult<RoomEncryptedEventContent> {
let event_type = content.event_type().to_string();
let content = serde_json::to_value(&content)?;
@@ -985,7 +986,7 @@ impl OlmMachine {
/// * `session_id` - The id that uniquely identifies the session.
pub async fn request_room_key(
&self,
event: &SyncRoomEncryptedEvent,
event: &OriginalSyncRoomEncryptedEvent,
room_id: &RoomId,
) -> MegolmResult<(Option<OutgoingRequest>, OutgoingRequest)> {
let content = match &event.content.scheme {
@@ -1038,7 +1039,7 @@ impl OlmMachine {
async fn decrypt_megolm_v1_event(
&self,
room_id: &RoomId,
event: &SyncRoomEncryptedEvent,
event: &OriginalSyncRoomEncryptedEvent,
content: &MegolmV1AesSha2Content,
) -> MegolmResult<RoomEvent> {
if let Some(session) = self
@@ -1099,7 +1100,7 @@ impl OlmMachine {
/// * `room_id` - The ID of the room where the event was sent to.
pub async fn decrypt_room_event(
&self,
event: &SyncRoomEncryptedEvent,
event: &OriginalSyncRoomEncryptedEvent,
room_id: &RoomId,
) -> MegolmResult<RoomEvent> {
match &event.content.scheme {
@@ -1312,7 +1313,7 @@ impl OlmMachine {
let mut keys = BTreeMap::new();
for (i, key) in exported_keys.into_iter().enumerate() {
let session = InboundGroupSession::from_export(key)?;
let session = InboundGroupSession::from_export(key);
// Only import the session if we didn't have this session or if it's
// a better version of the same session, that is the first known
@@ -1535,8 +1536,8 @@ pub(crate) mod tests {
message::{MessageType, RoomMessageEventContent},
},
AnyMessageLikeEvent, AnyMessageLikeEventContent, AnyRoomEvent, AnyToDeviceEvent,
AnyToDeviceEventContent, MessageLikeEvent, MessageLikeUnsigned, SyncMessageLikeEvent,
ToDeviceEvent,
AnyToDeviceEventContent, MessageLikeEvent, MessageLikeUnsigned,
OriginalMessageLikeEvent, OriginalSyncMessageLikeEvent, ToDeviceEvent,
},
room_id,
serde::Raw,
@@ -1956,7 +1957,7 @@ pub(crate) mod tests {
.await
.unwrap();
let event = SyncMessageLikeEvent {
let event = OriginalSyncMessageLikeEvent {
event_id: event_id!("$xxxxx:example.org").to_owned(),
origin_server_ts: milli_seconds_since_unix_epoch(),
sender: alice.user_id().to_owned(),
@@ -1967,11 +1968,9 @@ pub(crate) mod tests {
let decrypted_event =
bob.decrypt_room_event(&event, room_id).await.unwrap().event.deserialize().unwrap();
if let AnyRoomEvent::MessageLike(AnyMessageLikeEvent::RoomMessage(MessageLikeEvent {
sender,
content,
..
})) = decrypted_event
if let AnyRoomEvent::MessageLike(AnyMessageLikeEvent::RoomMessage(
MessageLikeEvent::Original(OriginalMessageLikeEvent { sender, content, .. }),
)) = decrypted_event
{
assert_eq!(&sender, alice.user_id());
if let MessageType::Text(c) = &content.msgtype {

View File

@@ -1077,8 +1077,7 @@ impl ReadOnlyAccount {
room_id,
outbound.session_key().await,
Some(visibility),
)
.expect("Can't create inbound group session from a newly created outbound group session");
);
Ok((outbound, inbound))
}

View File

@@ -16,8 +16,7 @@
use std::{
collections::BTreeMap,
convert::TryFrom,
fmt, mem,
fmt,
sync::{
atomic::{AtomicBool, Ordering::SeqCst},
Arc,
@@ -29,7 +28,7 @@ use ruma::{
events::{
forwarded_room_key::ToDeviceForwardedRoomKeyEventContent,
room::{
encrypted::{EncryptedEventScheme, SyncRoomEncryptedEvent},
encrypted::{EncryptedEventScheme, OriginalSyncRoomEncryptedEvent},
history_visibility::HistoryVisibility,
},
AnyRoomEvent,
@@ -42,10 +41,11 @@ use serde_json::Value;
use vodozemac::{
megolm::{
DecryptedMessage, DecryptionError, ExportedSessionKey, InboundGroupSession as InnerSession,
InboundGroupSessionPickle, MegolmMessage, SessionCreationError,
InboundGroupSessionPickle, MegolmMessage, SessionKeyDecodeError,
},
PickleError,
};
use zeroize::Zeroize;
use super::{BackedUpRoomKey, ExportedRoomKey, SessionKey};
use crate::error::{EventError, MegolmResult};
@@ -99,15 +99,15 @@ impl InboundGroupSession {
room_id: &RoomId,
session_key: SessionKey,
history_visibility: Option<HistoryVisibility>,
) -> Result<Self, SessionCreationError> {
let session = InnerSession::new(&session_key)?;
) -> Self {
let session = InnerSession::new(&session_key);
let session_id = session.session_id();
let first_known_index = session.first_known_index();
let mut keys: BTreeMap<DeviceKeyAlgorithm, String> = BTreeMap::new();
keys.insert(DeviceKeyAlgorithm::Ed25519, signing_key.to_owned());
Ok(InboundGroupSession {
InboundGroupSession {
inner: Arc::new(Mutex::new(session)),
session_id: session_id.into(),
history_visibility: history_visibility.into(),
@@ -118,7 +118,7 @@ impl InboundGroupSession {
forwarding_chains: Vec::new().into(),
imported: false,
backed_up: AtomicBool::new(false).into(),
})
}
}
/// Create a InboundGroupSession from an exported version of the group
@@ -127,20 +127,14 @@ impl InboundGroupSession {
/// Most notably this can be called with an `ExportedRoomKey` from a
/// previous [`export()`] call.
///
///
/// [`export()`]: #method.export
pub fn from_export(
exported_session: impl Into<ExportedRoomKey>,
) -> Result<Self, SessionCreationError> {
Self::try_from(exported_session.into())
pub fn from_export(exported_session: ExportedRoomKey) -> Self {
Self::from(exported_session)
}
#[allow(dead_code)]
fn from_backup(
room_id: &RoomId,
backup: BackedUpRoomKey,
) -> Result<Self, SessionCreationError> {
let session = InnerSession::import(&backup.session_key)?;
fn from_backup(room_id: &RoomId, backup: BackedUpRoomKey) -> Self {
let session = InnerSession::import(&backup.session_key);
let session_id = session.session_id();
Self::from_export(ExportedRoomKey {
@@ -166,10 +160,11 @@ impl InboundGroupSession {
pub fn from_forwarded_key(
sender_key: &str,
content: &mut ToDeviceForwardedRoomKeyEventContent,
) -> Result<Self, SessionCreationError> {
let key = ExportedSessionKey(mem::take(&mut content.session_key));
) -> Result<Self, SessionKeyDecodeError> {
let key = ExportedSessionKey::from_base64(&content.session_key)?;
content.session_key.zeroize();
let session = InnerSession::import(&key)?;
let session = InnerSession::import(&key);
let first_known_index = session.first_known_index();
let mut forwarding_chains = content.forwarding_curve25519_key_chain.clone();
forwarding_chains.push(sender_key.to_owned());
@@ -348,7 +343,7 @@ impl InboundGroupSession {
/// * `event` - The event that should be decrypted.
pub async fn decrypt(
&self,
event: &SyncRoomEncryptedEvent,
event: &OriginalSyncRoomEncryptedEvent,
) -> MegolmResult<(Raw<AnyRoomEvent>, u32)> {
let content = match &event.content.scheme {
EncryptedEventScheme::MegolmV1AesSha2(c) => c,
@@ -440,14 +435,12 @@ pub struct PickledInboundGroupSession {
pub history_visibility: Option<HistoryVisibility>,
}
impl TryFrom<ExportedRoomKey> for InboundGroupSession {
type Error = SessionCreationError;
fn try_from(key: ExportedRoomKey) -> Result<Self, Self::Error> {
let session = InnerSession::import(&key.session_key)?;
impl From<ExportedRoomKey> for InboundGroupSession {
fn from(key: ExportedRoomKey) -> Self {
let session = InnerSession::import(&key.session_key);
let first_known_index = session.first_known_index();
Ok(InboundGroupSession {
InboundGroupSession {
inner: Mutex::new(session).into(),
session_id: key.session_id.into(),
sender_key: key.sender_key.into(),
@@ -458,6 +451,6 @@ impl TryFrom<ExportedRoomKey> for InboundGroupSession {
forwarding_chains: key.forwarding_curve25519_key_chain.into(),
imported: true,
backed_up: AtomicBool::from(false).into(),
})
}
}
}

View File

@@ -30,7 +30,9 @@ pub(crate) use outbound::ShareState;
pub use outbound::{
EncryptionSettings, GroupSession, OutboundGroupSession, PickledOutboundGroupSession, ShareInfo,
};
use vodozemac::megolm::SessionKeyDecodeError;
pub use vodozemac::megolm::{ExportedSessionKey, SessionKey};
use zeroize::Zeroize;
/// An exported version of an `InboundGroupSession`
///
@@ -110,7 +112,7 @@ impl TryInto<ToDeviceForwardedRoomKeyEventContent> for ExportedRoomKey {
room_id: self.room_id,
sender_key: self.sender_key,
session_id: self.session_id,
session_key: self.session_key.0.clone(),
session_key: self.session_key.to_base64(),
sender_claimed_ed25519_key: claimed_key.to_owned(),
forwarding_curve25519_key_chain: self.forwarding_curve25519_key_chain,
}
@@ -131,22 +133,29 @@ impl From<ExportedRoomKey> for BackedUpRoomKey {
}
}
impl From<ToDeviceForwardedRoomKeyEventContent> for ExportedRoomKey {
impl TryFrom<ToDeviceForwardedRoomKeyEventContent> for ExportedRoomKey {
type Error = SessionKeyDecodeError;
/// Convert the content of a forwarded room key into a exported room key.
fn from(forwarded_key: ToDeviceForwardedRoomKeyEventContent) -> Self {
fn try_from(
mut forwarded_key: ToDeviceForwardedRoomKeyEventContent,
) -> Result<Self, Self::Error> {
let mut sender_claimed_keys: BTreeMap<DeviceKeyAlgorithm, String> = BTreeMap::new();
sender_claimed_keys
.insert(DeviceKeyAlgorithm::Ed25519, forwarded_key.sender_claimed_ed25519_key);
Self {
let session_key = ExportedSessionKey::from_base64(&forwarded_key.session_key)?;
forwarded_key.session_key.zeroize();
Ok(Self {
algorithm: forwarded_key.algorithm,
room_id: forwarded_key.room_id,
session_id: forwarded_key.session_id,
forwarding_curve25519_key_chain: forwarded_key.forwarding_curve25519_key_chain,
sender_claimed_keys,
sender_key: forwarded_key.sender_key,
session_key: ExportedSessionKey(forwarded_key.session_key),
}
session_key,
})
}
}

View File

@@ -372,7 +372,7 @@ impl OutboundGroupSession {
EventEncryptionAlgorithm::MegolmV1AesSha2,
self.room_id().to_owned(),
self.session_id().to_owned(),
session_key.0.clone(),
session_key.to_base64(),
))
}

View File

@@ -67,13 +67,14 @@ pub(crate) mod tests {
forwarded_room_key::ToDeviceForwardedRoomKeyEventContent,
room::message::{Relation, Replacement, RoomMessageEventContent},
AnyMessageLikeEvent, AnyRoomEvent, AnySyncMessageLikeEvent, AnySyncRoomEvent,
MessageLikeEvent, SyncMessageLikeEvent,
},
room_id, user_id, DeviceId, UserId,
};
use serde_json::json;
use vodozemac::olm::OlmMessage;
use crate::olm::{InboundGroupSession, ReadOnlyAccount, Session};
use crate::olm::{ExportedRoomKey, InboundGroupSession, ReadOnlyAccount, Session};
fn alice_id() -> &'static UserId {
user_id!("@alice:example.org")
@@ -185,8 +186,7 @@ pub(crate) mod tests {
room_id,
outbound.session_key().await,
None,
)
.unwrap();
);
assert_eq!(0, inbound.first_known_index());
@@ -223,8 +223,7 @@ pub(crate) mod tests {
room_id,
outbound.session_key().await,
None,
)
.unwrap();
);
assert_eq!(0, inbound.first_known_index());
@@ -245,19 +244,20 @@ pub(crate) mod tests {
let event: AnySyncRoomEvent = serde_json::from_str(&event).unwrap();
let event =
if let AnySyncRoomEvent::MessageLike(AnySyncMessageLikeEvent::RoomEncrypted(event)) =
event
{
event
} else {
panic!("Invalid event type")
};
let event = if let AnySyncRoomEvent::MessageLike(AnySyncMessageLikeEvent::RoomEncrypted(
SyncMessageLikeEvent::Original(event),
)) = event
{
event
} else {
panic!("Invalid event type")
};
let decrypted = inbound.decrypt(&event).await.unwrap().0;
if let AnyRoomEvent::MessageLike(AnyMessageLikeEvent::RoomMessage(e)) =
decrypted.deserialize().unwrap()
if let AnyRoomEvent::MessageLike(AnyMessageLikeEvent::RoomMessage(
MessageLikeEvent::Original(e),
)) = decrypted.deserialize().unwrap()
{
assert_matches!(e.content.relates_to, Some(Relation::Replacement(_)));
} else {
@@ -274,8 +274,9 @@ pub(crate) mod tests {
let export = inbound.export().await;
let export: ToDeviceForwardedRoomKeyEventContent = export.try_into().unwrap();
let export = ExportedRoomKey::try_from(export).unwrap();
let imported = InboundGroupSession::from_export(export).unwrap();
let imported = InboundGroupSession::from_export(export);
assert_eq!(inbound.session_id(), imported.session_id());
}

View File

@@ -246,8 +246,7 @@ mod tests {
room_id,
outbound.session_key().await,
None,
)
.unwrap();
);
let store = GroupSessionStore::new();
store.add(inbound.clone());

View File

@@ -275,7 +275,7 @@ macro_rules! cryptostore_integration_tests {
export.forwarding_curve25519_key_chain = vec!["some_chain".to_owned()];
let session = InboundGroupSession::from_export(export).unwrap();
let session = InboundGroupSession::from_export(export);
let changes =
Changes { inbound_group_sessions: vec![session.clone()], ..Default::default() };

View File

@@ -347,8 +347,7 @@ mod tests {
room_id,
outbound.session_key().await,
None,
)
.unwrap();
);
let store = MemoryStore::new();
let _ = store.save_inbound_group_sessions(vec![inbound.clone()]).await;

View File

@@ -590,7 +590,7 @@ pub enum CryptoStoreError {
/// The received room key couldn't be converted into a valid Megolm session.
#[error(transparent)]
SessionCreation(#[from] vodozemac::megolm::SessionCreationError),
SessionCreation(#[from] vodozemac::megolm::SessionKeyDecodeError),
/// A Matrix identifier failed to be validated.
#[error(transparent)]

View File

@@ -41,6 +41,7 @@ use ruma::{
},
room::message::{KeyVerificationRequestEventContent, MessageType},
AnyMessageLikeEvent, AnyMessageLikeEventContent, AnyToDeviceEvent, AnyToDeviceEventContent,
MessageLikeEvent,
},
serde::{Base64, CanonicalJsonValue},
DeviceId, MilliSecondsSinceUnixEpoch, RoomId, UserId,
@@ -79,51 +80,37 @@ impl AnyEvent<'_> {
pub fn verification_content(&self) -> Option<AnyVerificationContent<'_>> {
match self {
AnyEvent::Room(e) => match e {
AnyMessageLikeEvent::CallAnswer(_)
| AnyMessageLikeEvent::CallInvite(_)
| AnyMessageLikeEvent::CallHangup(_)
| AnyMessageLikeEvent::CallCandidates(_)
| AnyMessageLikeEvent::Reaction(_)
| AnyMessageLikeEvent::RoomEncrypted(_)
| AnyMessageLikeEvent::RoomMessageFeedback(_)
| AnyMessageLikeEvent::RoomRedaction(_)
| AnyMessageLikeEvent::Sticker(_) => None,
AnyMessageLikeEvent::RoomMessage(m) => {
AnyMessageLikeEvent::RoomMessage(MessageLikeEvent::Original(m)) => {
if let MessageType::VerificationRequest(v) = &m.content.msgtype {
Some(RequestContent::from(v).into())
} else {
None
}
}
AnyMessageLikeEvent::KeyVerificationReady(e) => {
AnyMessageLikeEvent::KeyVerificationReady(MessageLikeEvent::Original(e)) => {
Some(ReadyContent::from(&e.content).into())
}
AnyMessageLikeEvent::KeyVerificationStart(e) => {
AnyMessageLikeEvent::KeyVerificationStart(MessageLikeEvent::Original(e)) => {
Some(StartContent::from(&e.content).into())
}
AnyMessageLikeEvent::KeyVerificationCancel(e) => {
AnyMessageLikeEvent::KeyVerificationCancel(MessageLikeEvent::Original(e)) => {
Some(CancelContent::from(&e.content).into())
}
AnyMessageLikeEvent::KeyVerificationAccept(e) => {
AnyMessageLikeEvent::KeyVerificationAccept(MessageLikeEvent::Original(e)) => {
Some(AcceptContent::from(&e.content).into())
}
AnyMessageLikeEvent::KeyVerificationKey(e) => {
AnyMessageLikeEvent::KeyVerificationKey(MessageLikeEvent::Original(e)) => {
Some(KeyContent::from(&e.content).into())
}
AnyMessageLikeEvent::KeyVerificationMac(e) => {
AnyMessageLikeEvent::KeyVerificationMac(MessageLikeEvent::Original(e)) => {
Some(MacContent::from(&e.content).into())
}
AnyMessageLikeEvent::KeyVerificationDone(e) => {
AnyMessageLikeEvent::KeyVerificationDone(MessageLikeEvent::Original(e)) => {
Some(DoneContent::from(&e.content).into())
}
_ => None,
},
AnyEvent::ToDevice(e) => match e {
AnyToDeviceEvent::Dummy(_)
| AnyToDeviceEvent::RoomKey(_)
| AnyToDeviceEvent::RoomKeyRequest(_)
| AnyToDeviceEvent::ForwardedRoomKey(_)
| AnyToDeviceEvent::RoomEncrypted(_) => None,
AnyToDeviceEvent::KeyVerificationRequest(e) => {
Some(RequestContent::from(&e.content).into())
}
@@ -182,35 +169,28 @@ impl TryFrom<&AnyMessageLikeEvent> for FlowId {
fn try_from(value: &AnyMessageLikeEvent) -> Result<Self, Self::Error> {
match value {
AnyMessageLikeEvent::CallAnswer(_)
| AnyMessageLikeEvent::CallInvite(_)
| AnyMessageLikeEvent::CallHangup(_)
| AnyMessageLikeEvent::CallCandidates(_)
| AnyMessageLikeEvent::Reaction(_)
| AnyMessageLikeEvent::RoomEncrypted(_)
| AnyMessageLikeEvent::RoomMessageFeedback(_)
| AnyMessageLikeEvent::RoomRedaction(_)
| AnyMessageLikeEvent::Sticker(_) => Err(()),
AnyMessageLikeEvent::KeyVerificationReady(e) => {
AnyMessageLikeEvent::KeyVerificationReady(MessageLikeEvent::Original(e)) => {
Ok(FlowId::from((&*e.room_id, &*e.content.relates_to.event_id)))
}
AnyMessageLikeEvent::RoomMessage(e) => Ok(FlowId::from((&*e.room_id, &*e.event_id))),
AnyMessageLikeEvent::KeyVerificationStart(e) => {
AnyMessageLikeEvent::RoomMessage(MessageLikeEvent::Original(e)) => {
Ok(FlowId::from((&*e.room_id, &*e.event_id)))
}
AnyMessageLikeEvent::KeyVerificationStart(MessageLikeEvent::Original(e)) => {
Ok(FlowId::from((&*e.room_id, &*e.content.relates_to.event_id)))
}
AnyMessageLikeEvent::KeyVerificationCancel(e) => {
AnyMessageLikeEvent::KeyVerificationCancel(MessageLikeEvent::Original(e)) => {
Ok(FlowId::from((&*e.room_id, &*e.content.relates_to.event_id)))
}
AnyMessageLikeEvent::KeyVerificationAccept(e) => {
AnyMessageLikeEvent::KeyVerificationAccept(MessageLikeEvent::Original(e)) => {
Ok(FlowId::from((&*e.room_id, &*e.content.relates_to.event_id)))
}
AnyMessageLikeEvent::KeyVerificationKey(e) => {
AnyMessageLikeEvent::KeyVerificationKey(MessageLikeEvent::Original(e)) => {
Ok(FlowId::from((&*e.room_id, &*e.content.relates_to.event_id)))
}
AnyMessageLikeEvent::KeyVerificationMac(e) => {
AnyMessageLikeEvent::KeyVerificationMac(MessageLikeEvent::Original(e)) => {
Ok(FlowId::from((&*e.room_id, &*e.content.relates_to.event_id)))
}
AnyMessageLikeEvent::KeyVerificationDone(e) => {
AnyMessageLikeEvent::KeyVerificationDone(MessageLikeEvent::Original(e)) => {
Ok(FlowId::from((&*e.room_id, &*e.content.relates_to.event_id)))
}
_ => Err(()),
@@ -223,11 +203,6 @@ impl TryFrom<&AnyToDeviceEvent> for FlowId {
fn try_from(value: &AnyToDeviceEvent) -> Result<Self, Self::Error> {
match value {
AnyToDeviceEvent::Dummy(_)
| AnyToDeviceEvent::RoomKey(_)
| AnyToDeviceEvent::RoomKeyRequest(_)
| AnyToDeviceEvent::ForwardedRoomKey(_)
| AnyToDeviceEvent::RoomEncrypted(_) => Err(()),
AnyToDeviceEvent::KeyVerificationRequest(e) => {
Ok(FlowId::from(e.content.transaction_id.to_owned()))
}

View File

@@ -29,7 +29,10 @@ use matrix_sdk_common::{
events::{
presence::PresenceEvent,
receipt::Receipt,
room::member::{MembershipState, RoomMemberEventContent},
room::{
member::{MembershipState, RoomMemberEventContent},
redaction::SyncRoomRedactionEvent,
},
AnyGlobalAccountDataEvent, AnyRoomAccountDataEvent, AnySyncMessageLikeEvent,
AnySyncRoomEvent, AnySyncStateEvent, GlobalAccountDataEventType,
RoomAccountDataEventType, StateEventType,
@@ -706,7 +709,9 @@ impl IndexeddbStore {
for event in &timeline.events {
// Redact events already in store only on sync response
if let Ok(AnySyncRoomEvent::MessageLike(
AnySyncMessageLikeEvent::RoomRedaction(redaction),
AnySyncMessageLikeEvent::RoomRedaction(
SyncRoomRedactionEvent::Original(redaction),
),
)) = event.event.deserialize()
{
let redacts_key = self.encode_key(

View File

@@ -26,7 +26,10 @@ use futures_util::stream::{self, StreamExt, TryStreamExt};
use matrix_sdk_base::{
deserialized_responses::{MemberEvent, SyncRoomEvent},
media::{MediaRequest, UniqueKey},
store::{BoxStream, Result as StoreResult, StateChanges, StateStore, StoreError},
ruma::events::room::redaction::SyncRoomRedactionEvent,
store::{
BoxStream, Result as StoreResult, StateChanges, StateStore, StoreError,
},
RoomInfo,
};
use matrix_sdk_common::{
@@ -713,9 +716,7 @@ impl SledStore {
pub async fn get_room_infos(&self) -> Result<impl Stream<Item = Result<RoomInfo>>> {
let db = self.clone();
spawn_blocking(move || {
stream::iter(
db.room_info.iter().map(move |r| db.deserialize_event(&r?.1)),
)
stream::iter(db.room_info.iter().map(move |r| db.deserialize_event(&r?.1)))
})
.await
.map_err(Into::into)
@@ -724,11 +725,7 @@ impl SledStore {
pub async fn get_stripped_room_infos(&self) -> Result<impl Stream<Item = Result<RoomInfo>>> {
let db = self.clone();
spawn_blocking(move || {
stream::iter(
db.stripped_room_infos
.iter()
.map(move |r| db.deserialize_event(&r?.1)),
)
stream::iter(db.stripped_room_infos.iter().map(move |r| db.deserialize_event(&r?.1)))
})
.await
.map_err(Into::into)
@@ -1158,7 +1155,9 @@ impl SledStore {
for event in &timeline.events {
// Redact events already in store only on sync response
if let Ok(AnySyncRoomEvent::MessageLike(
AnySyncMessageLikeEvent::RoomRedaction(redaction),
AnySyncMessageLikeEvent::RoomRedaction(SyncRoomRedactionEvent::Original(
redaction,
)),
)) = event.event.deserialize()
{
let redacts_key =

View File

@@ -18,6 +18,6 @@ appservice = []
http = "0.2.4"
lazy_static = "1.4.0"
matrix-sdk-test-macros = { version = "0.1.0", path = "../matrix-sdk-test-macros" }
ruma = { git = "https://github.com/ruma/ruma", rev = "deea762b8", features = ["client-api-c"] }
ruma = { git = "https://github.com/ruma/ruma", rev = "548232ef5", features = ["client-api-c"] }
serde = "1.0.126"
serde_json = "1.0.64"

View File

@@ -103,7 +103,7 @@ default_features = false
[dependencies.ruma]
git = "https://github.com/ruma/ruma"
rev = "deea762b8"
rev = "548232ef5"
features = ["client-api-c", "compat", "rand", "unstable-msc2448"]
[dependencies.tokio-stream]

View File

@@ -4,12 +4,12 @@ use matrix_sdk::{
config::SyncSettings,
room::Room,
ruma::events::room::message::{
MessageType, RoomMessageEventContent, SyncRoomMessageEvent, TextMessageEventContent,
MessageType, OriginalSyncRoomMessageEvent, RoomMessageEventContent, TextMessageEventContent,
},
Client,
};
async fn on_room_message(event: SyncRoomMessageEvent, room: Room) {
async fn on_room_message(event: OriginalSyncRoomMessageEvent, room: Room) {
if let Room::Joined(room) = room {
let msg_body = match event.content.msgtype {
MessageType::Text(TextMessageEventContent { body, .. }) => body,

View File

@@ -19,6 +19,7 @@ use matrix_sdk::{
},
Client, LoopCtrl,
};
use ruma::events::SyncMessageLikeEvent;
use url::Url;
async fn wait_for_confirmation(client: Client, sas: SasVerification) {
@@ -135,7 +136,9 @@ async fn login(
{
if let AnySyncRoomEvent::MessageLike(event) = event {
match event {
AnySyncMessageLikeEvent::RoomMessage(m) => {
AnySyncMessageLikeEvent::RoomMessage(
SyncMessageLikeEvent::Original(m),
) => {
if let MessageType::VerificationRequest(_) = &m.content.msgtype
{
let request = client
@@ -150,7 +153,9 @@ async fn login(
.expect("Can't accept verification request");
}
}
AnySyncMessageLikeEvent::KeyVerificationKey(e) => {
AnySyncMessageLikeEvent::KeyVerificationKey(
SyncMessageLikeEvent::Original(e),
) => {
if let Some(Verification::SasV1(sas)) = client
.encryption()
.get_verification(
@@ -162,7 +167,9 @@ async fn login(
tokio::spawn(wait_for_confirmation((*client).clone(), sas));
}
}
AnySyncMessageLikeEvent::KeyVerificationMac(e) => {
AnySyncMessageLikeEvent::KeyVerificationMac(
SyncMessageLikeEvent::Original(e),
) => {
if let Some(Verification::SasV1(sas)) = client
.encryption()
.get_verification(

View File

@@ -13,16 +13,16 @@ use matrix_sdk::{
config::SyncSettings,
room::Room,
ruma::events::room::message::{
MessageType, RoomMessageEventContent, SyncRoomMessageEvent, TextMessageEventContent,
MessageType, OriginalSyncRoomMessageEvent, RoomMessageEventContent, TextMessageEventContent,
},
Client,
};
use tokio::sync::Mutex;
use url::Url;
async fn on_room_message(event: SyncRoomMessageEvent, room: Room, image: Arc<Mutex<File>>) {
async fn on_room_message(event: OriginalSyncRoomMessageEvent, room: Room, image: Arc<Mutex<File>>) {
if let Room::Joined(room) = room {
let msg_body = if let SyncRoomMessageEvent {
let msg_body = if let OriginalSyncRoomMessageEvent {
content:
RoomMessageEventContent {
msgtype: MessageType::Text(TextMessageEventContent { body: msg_body, .. }),

View File

@@ -5,15 +5,15 @@ use matrix_sdk::{
config::SyncSettings,
room::Room,
ruma::events::room::message::{
MessageType, RoomMessageEventContent, SyncRoomMessageEvent, TextMessageEventContent,
MessageType, OriginalSyncRoomMessageEvent, RoomMessageEventContent, TextMessageEventContent,
},
Client,
};
use url::Url;
async fn on_room_message(event: SyncRoomMessageEvent, room: Room) {
async fn on_room_message(event: OriginalSyncRoomMessageEvent, room: Room) {
if let Room::Joined(room) = room {
if let SyncRoomMessageEvent {
if let OriginalSyncRoomMessageEvent {
content:
RoomMessageEventContent {
msgtype: MessageType::Text(TextMessageEventContent { body: msg_body, .. }),

View File

@@ -8,7 +8,7 @@ use matrix_sdk::{
ruma::{
api::client::filter::{FilterDefinition, LazyLoadOptions, RoomEventFilter, RoomFilter},
assign,
events::{AnyMessageLikeEventContent, AnySyncRoomEvent},
events::{AnySyncMessageLikeEvent, AnySyncRoomEvent, SyncMessageLikeEvent},
},
store::make_store_config,
Client, LoopCtrl,
@@ -32,12 +32,14 @@ async fn login(homeserver_url: String, username: &str, password: &str) -> Client
}
fn event_content(event: AnySyncRoomEvent) -> Option<String> {
if let AnySyncRoomEvent::MessageLike(event) = event {
if let AnyMessageLikeEventContent::RoomMessage(content) = event.content() {
return Some(content.msgtype.body().to_owned());
}
if let AnySyncRoomEvent::MessageLike(AnySyncMessageLikeEvent::RoomMessage(
SyncMessageLikeEvent::Original(event),
)) = event
{
Some(event.content.msgtype.body().to_owned())
} else {
None
}
None
}
async fn print_timeline(room: Room) {
let backward_stream = room.timeline_backward().await.unwrap();

View File

@@ -4,9 +4,11 @@ use matrix_sdk::{
ruma::{
events::{
room::message::{
MessageType, RoomMessageEventContent, SyncRoomMessageEvent, TextMessageEventContent,
MessageType, OriginalSyncRoomMessageEvent, RoomMessageEventContent,
TextMessageEventContent,
},
AnyMessageLikeEventContent, AnySyncMessageLikeEvent, AnySyncRoomEvent,
SyncMessageLikeEvent,
},
RoomId,
},
@@ -19,8 +21,8 @@ use web_sys::console;
struct WasmBot(Client);
impl WasmBot {
async fn on_room_message(&self, room_id: &RoomId, event: &SyncRoomMessageEvent) {
let msg_body = if let SyncRoomMessageEvent {
async fn on_room_message(&self, room_id: &RoomId, event: &OriginalSyncRoomMessageEvent) {
let msg_body = if let OriginalSyncRoomMessageEvent {
content:
RoomMessageEventContent {
msgtype: MessageType::Text(TextMessageEventContent { body: msg_body, .. }),
@@ -59,8 +61,9 @@ impl WasmBot {
for (room_id, room) in response.rooms.join {
for event in room.timeline.events {
if let Ok(AnySyncRoomEvent::MessageLike(AnySyncMessageLikeEvent::RoomMessage(ev))) =
event.event.deserialize()
if let Ok(AnySyncRoomEvent::MessageLike(AnySyncMessageLikeEvent::RoomMessage(
SyncMessageLikeEvent::Original(ev),
))) = event.event.deserialize()
{
self.on_room_message(&room_id, &ev).await
}

View File

@@ -1660,7 +1660,7 @@ impl Client {
/// # let password = "";
/// use matrix_sdk::{
/// Client, config::SyncSettings,
/// ruma::events::room::message::SyncRoomMessageEvent,
/// ruma::events::room::message::OriginalSyncRoomMessageEvent,
/// };
///
/// let client = Client::new(homeserver).await?;
@@ -1671,7 +1671,7 @@ impl Client {
///
/// // Register our handler so we start responding once we receive a new
/// // event.
/// client.register_event_handler(|ev: SyncRoomMessageEvent| async move {
/// client.register_event_handler(|ev: OriginalSyncRoomMessageEvent| async move {
/// println!("Received event {}: {:?}", ev.sender, ev.content);
/// }).await;
///
@@ -1765,7 +1765,7 @@ impl Client {
/// # let password = "";
/// use matrix_sdk::{
/// Client, config::SyncSettings,
/// ruma::events::room::message::SyncRoomMessageEvent,
/// ruma::events::room::message::OriginalSyncRoomMessageEvent,
/// };
///
/// let client = Client::new(homeserver).await?;
@@ -1773,7 +1773,7 @@ impl Client {
///
/// // Register our handler so we start responding once we receive a new
/// // event.
/// client.register_event_handler(|ev: SyncRoomMessageEvent| async move {
/// client.register_event_handler(|ev: OriginalSyncRoomMessageEvent| async move {
/// println!("Received event {}: {:?}", ev.sender, ev.content);
/// }).await;
///

View File

@@ -56,7 +56,10 @@ use ruma::{
};
use tracing::{debug, instrument, trace, warn};
#[cfg(feature = "encryption")]
use {ruma::api::client::config::set_global_account_data, ruma::events::EventContent};
use {
ruma::api::client::config::set_global_account_data,
ruma::events::{GlobalAccountDataEventContent, SyncMessageLikeEvent},
};
use crate::{
attachment::{AttachmentInfo, Thumbnail},
@@ -80,7 +83,10 @@ impl Client {
// Turn the AnyMessageLikeEvent into a AnySyncMessageLikeEvent
let event = event.clone().into();
if let AnySyncMessageLikeEvent::RoomEncrypted(e) = event {
if let AnySyncMessageLikeEvent::RoomEncrypted(SyncMessageLikeEvent::Original(
e,
)) = event
{
if let Ok(decrypted) = machine.decrypt_room_event(&e, room_id).await {
return decrypted;
}
@@ -90,6 +96,7 @@ impl Client {
}
// Fallback to still-encrypted room event
RoomEvent { event, encryption_info: None }
}
@@ -237,7 +244,7 @@ impl Client {
content: T,
) -> Result<set_global_account_data::v3::Response>
where
T: EventContent<EventType = GlobalAccountDataEventType>,
T: GlobalAccountDataEventContent,
{
let own_user =
self.user_id().await.ok_or_else(|| Error::from(HttpError::AuthenticationRequired))?;

View File

@@ -47,14 +47,36 @@ pub enum EventKind {
GlobalAccountData,
RoomAccountData,
EphemeralRoomData,
Message { redacted: bool },
State { redacted: bool },
MessageLike,
OriginalMessageLike,
RedactedMessageLike,
State,
OriginalState,
RedactedState,
StrippedState,
InitialState,
ToDevice,
Presence,
}
impl EventKind {
fn message_like_redacted(redacted: bool) -> Self {
if redacted {
Self::RedactedMessageLike
} else {
Self::OriginalMessageLike
}
}
fn state_redacted(redacted: bool) -> Self {
if redacted {
Self::RedactedState
} else {
Self::OriginalState
}
}
}
/// A statically-known event kind/type that can be retrieved from an event sync.
pub trait SyncEvent {
#[doc(hidden)]
@@ -269,6 +291,10 @@ impl Client {
unsigned: Option<UnsignedDetails>,
}
// Event handlers for possibly-redacted state events
self.handle_sync_events(EventKind::State, room, state_events).await?;
// Event handlers specifically for redacted OR unredacted state events
self.handle_sync_events_wrapped_with(
room,
state_events,
@@ -276,10 +302,12 @@ impl Client {
|raw| {
let StateEventDetails { event_type, unsigned } = raw.deserialize_as()?;
let redacted = unsigned.and_then(|u| u.redacted_because).is_some();
Ok((EventKind::State { redacted }, event_type))
Ok((EventKind::state_redacted(redacted), event_type))
},
)
.await
.await?;
Ok(())
}
pub(crate) async fn handle_sync_timeline_events(
@@ -295,6 +323,25 @@ impl Client {
unsigned: Option<UnsignedDetails>,
}
// Event handlers for possibly-redacted timeline events
self.handle_sync_events_wrapped_with(
room,
timeline_events,
|e| (&e.event, e.encryption_info.as_ref()),
|raw| {
let TimelineEventDetails { event_type, state_key, .. } = raw.deserialize_as()?;
let kind = match state_key {
Some(_) => EventKind::State,
None => EventKind::MessageLike,
};
Ok((kind, event_type))
},
)
.await?;
// Event handlers specifically for redacted OR unredacted timeline events
self.handle_sync_events_wrapped_with(
room,
timeline_events,
@@ -305,14 +352,16 @@ impl Client {
let redacted = unsigned.and_then(|u| u.redacted_because).is_some();
let kind = match state_key {
Some(_) => EventKind::State { redacted },
None => EventKind::Message { redacted },
Some(_) => EventKind::state_redacted(redacted),
None => EventKind::message_like_redacted(redacted),
};
Ok((kind, event_type))
},
)
.await
.await?;
Ok(())
}
async fn handle_sync_events_wrapped_with<'a, T: 'a, U: 'a>(
@@ -390,72 +439,107 @@ mod static_events {
use ruma::events::{
self,
presence::{PresenceEvent, PresenceEventContent},
EphemeralRoomEventType, EventContent, GlobalAccountDataEventType, MessageLikeEventType,
RedactedEventContent, RoomAccountDataEventType, StateEventType, StaticEventContent,
ToDeviceEventType,
EphemeralRoomEventContent, GlobalAccountDataEventContent, MessageLikeEventContent,
RedactContent, RedactedEventContent, RoomAccountDataEventContent, StateEventContent,
StaticEventContent, ToDeviceEventContent,
};
use super::{EventKind, SyncEvent};
impl<C> SyncEvent for events::GlobalAccountDataEvent<C>
where
C: StaticEventContent + EventContent<EventType = GlobalAccountDataEventType>,
C: StaticEventContent + GlobalAccountDataEventContent,
{
const ID: (EventKind, &'static str) = (EventKind::GlobalAccountData, C::TYPE);
}
impl<C> SyncEvent for events::RoomAccountDataEvent<C>
where
C: StaticEventContent + EventContent<EventType = RoomAccountDataEventType>,
C: StaticEventContent + RoomAccountDataEventContent,
{
const ID: (EventKind, &'static str) = (EventKind::RoomAccountData, C::TYPE);
}
impl<C> SyncEvent for events::SyncEphemeralRoomEvent<C>
where
C: StaticEventContent + EventContent<EventType = EphemeralRoomEventType>,
C: StaticEventContent + EphemeralRoomEventContent,
{
const ID: (EventKind, &'static str) = (EventKind::EphemeralRoomData, C::TYPE);
}
impl<C> SyncEvent for events::SyncMessageLikeEvent<C>
where
C: StaticEventContent + EventContent<EventType = MessageLikeEventType>,
C: StaticEventContent + MessageLikeEventContent + RedactContent,
C::Redacted: MessageLikeEventContent + RedactedEventContent,
{
const ID: (EventKind, &'static str) = (EventKind::Message { redacted: false }, C::TYPE);
const ID: (EventKind, &'static str) = (EventKind::MessageLike, C::TYPE);
}
impl<C> SyncEvent for events::OriginalSyncMessageLikeEvent<C>
where
C: StaticEventContent + MessageLikeEventContent,
{
const ID: (EventKind, &'static str) = (EventKind::OriginalMessageLike, C::TYPE);
}
impl<C> SyncEvent for events::RedactedSyncMessageLikeEvent<C>
where
C: StaticEventContent + MessageLikeEventContent + RedactedEventContent,
{
const ID: (EventKind, &'static str) = (EventKind::RedactedMessageLike, C::TYPE);
}
impl SyncEvent for events::room::redaction::SyncRoomRedactionEvent {
const ID: (EventKind, &'static str) =
(EventKind::MessageLike, events::room::redaction::RoomRedactionEventContent::TYPE);
}
impl SyncEvent for events::room::redaction::RedactedSyncRoomRedactionEvent {
const ID: (EventKind, &'static str) = (
EventKind::Message { redacted: false },
EventKind::OriginalMessageLike,
events::room::redaction::RoomRedactionEventContent::TYPE,
);
}
impl<C> SyncEvent for events::SyncStateEvent<C>
where
C: StaticEventContent + EventContent<EventType = StateEventType>,
C: StaticEventContent + StateEventContent + RedactContent,
C::Redacted: StateEventContent + RedactedEventContent,
{
const ID: (EventKind, &'static str) = (EventKind::State { redacted: false }, C::TYPE);
const ID: (EventKind, &'static str) = (EventKind::State, C::TYPE);
}
impl<C> SyncEvent for events::OriginalSyncStateEvent<C>
where
C: StaticEventContent + StateEventContent,
{
const ID: (EventKind, &'static str) = (EventKind::OriginalState, C::TYPE);
}
impl<C> SyncEvent for events::RedactedSyncStateEvent<C>
where
C: StaticEventContent + StateEventContent + RedactedEventContent,
{
const ID: (EventKind, &'static str) = (EventKind::RedactedState, C::TYPE);
}
impl<C> SyncEvent for events::StrippedStateEvent<C>
where
C: StaticEventContent + EventContent<EventType = StateEventType>,
C: StaticEventContent + StateEventContent,
{
const ID: (EventKind, &'static str) = (EventKind::StrippedState, C::TYPE);
}
impl<C> SyncEvent for events::InitialStateEvent<C>
where
C: StaticEventContent + EventContent<EventType = StateEventType>,
C: StaticEventContent + StateEventContent,
{
const ID: (EventKind, &'static str) = (EventKind::InitialState, C::TYPE);
}
impl<C> SyncEvent for events::ToDeviceEvent<C>
where
C: StaticEventContent + EventContent<EventType = ToDeviceEventType>,
C: StaticEventContent + ToDeviceEventContent,
{
const ID: (EventKind, &'static str) = (EventKind::ToDevice, C::TYPE);
}
@@ -463,29 +547,6 @@ mod static_events {
impl SyncEvent for PresenceEvent {
const ID: (EventKind, &'static str) = (EventKind::Presence, PresenceEventContent::TYPE);
}
impl<C> SyncEvent for events::RedactedSyncMessageLikeEvent<C>
where
C: StaticEventContent
+ EventContent<EventType = MessageLikeEventType>
+ RedactedEventContent,
{
const ID: (EventKind, &'static str) = (EventKind::Message { redacted: true }, C::TYPE);
}
impl SyncEvent for events::room::redaction::RedactedSyncRoomRedactionEvent {
const ID: (EventKind, &'static str) = (
EventKind::Message { redacted: true },
events::room::redaction::RoomRedactionEventContent::TYPE,
);
}
impl<C> SyncEvent for events::RedactedSyncStateEvent<C>
where
C: StaticEventContent + EventContent<EventType = StateEventType> + RedactedEventContent,
{
const ID: (EventKind, &'static str) = (EventKind::State { redacted: true }, C::TYPE);
}
}
#[cfg(all(test, not(target_arch = "wasm32")))]
@@ -497,7 +558,7 @@ mod tests {
use matrix_sdk_test::{EventBuilder, EventsJson};
use ruma::{
events::room::member::{StrippedRoomMemberEvent, SyncRoomMemberEvent},
events::room::member::{OriginalSyncRoomMemberEvent, StrippedRoomMemberEvent},
room_id,
};
use serde_json::json;
@@ -518,7 +579,7 @@ mod tests {
client
.register_event_handler({
let member_count = member_count.clone();
move |_ev: SyncRoomMemberEvent, _room: room::Room| {
move |_ev: OriginalSyncRoomMemberEvent, _room: room::Room| {
member_count.fetch_add(1, SeqCst);
future::ready(())
}
@@ -526,7 +587,7 @@ mod tests {
.await
.register_event_handler({
let typing_count = typing_count.clone();
move |_ev: SyncRoomMemberEvent| {
move |_ev: OriginalSyncRoomMemberEvent| {
typing_count.fetch_add(1, SeqCst);
future::ready(())
}
@@ -534,7 +595,7 @@ mod tests {
.await
.register_event_handler({
let power_levels_count = power_levels_count.clone();
move |_ev: SyncRoomMemberEvent, _client: Client, _room: room::Room| {
move |_ev: OriginalSyncRoomMemberEvent, _client: Client, _room: room::Room| {
power_levels_count.fetch_add(1, SeqCst);
future::ready(())
}

View File

@@ -18,8 +18,9 @@ use ruma::{
events::{
room::{history_visibility::HistoryVisibility, MediaSource},
tag::{TagInfo, TagName},
AnyRoomAccountDataEvent, AnyStateEvent, AnySyncStateEvent, EventContent,
RoomAccountDataEvent, RoomAccountDataEventType, StateEventType, StaticEventContent,
AnyRoomAccountDataEvent, AnyStateEvent, AnySyncStateEvent, RedactContent,
RedactedEventContent, RoomAccountDataEvent, RoomAccountDataEventContent,
RoomAccountDataEventType, StateEventContent, StateEventType, StaticEventContent,
SyncStateEvent,
},
serde::Raw,
@@ -662,7 +663,8 @@ impl Common {
/// ```
pub async fn get_state_events_static<C>(&self) -> Result<Vec<Raw<SyncStateEvent<C>>>>
where
C: StaticEventContent + EventContent<EventType = StateEventType>,
C: StaticEventContent + StateEventContent + RedactContent,
C::Redacted: StateEventContent + RedactedEventContent,
{
// FIXME: Could be more efficient, if we had streaming store accessor functions
Ok(self.get_state_events(C::TYPE.into()).await?.into_iter().map(Raw::cast).collect())
@@ -702,7 +704,8 @@ impl Common {
state_key: &str,
) -> Result<Option<Raw<SyncStateEvent<C>>>>
where
C: StaticEventContent + EventContent<EventType = StateEventType>,
C: StaticEventContent + StateEventContent + RedactContent,
C::Redacted: StateEventContent + RedactedEventContent,
{
Ok(self.get_state_event(C::TYPE.into(), state_key).await?.map(Raw::cast))
}
@@ -737,7 +740,7 @@ impl Common {
/// ```
pub async fn account_data_static<C>(&self) -> Result<Option<Raw<RoomAccountDataEvent<C>>>>
where
C: StaticEventContent + EventContent<EventType = RoomAccountDataEventType>,
C: StaticEventContent + RoomAccountDataEventContent,
{
Ok(self.account_data(C::TYPE.into()).await?.map(Raw::cast))
}

View File

@@ -26,9 +26,7 @@ use ruma::{
typing::create_typing_event::v3::{Request as TypingRequest, Typing},
},
assign,
events::{
room::message::RoomMessageEventContent, EventContent, MessageLikeEventType, StateEventType,
},
events::{room::message::RoomMessageEventContent, MessageLikeEventContent, StateEventContent},
receipt::ReceiptType,
serde::Raw,
EventId, TransactionId, UserId,
@@ -468,7 +466,7 @@ impl Joined {
/// [`transaction_id`]: ruma::events::MessageLikeUnsigned#structfield.transaction_id
pub async fn send(
&self,
content: impl EventContent<EventType = MessageLikeEventType>,
content: impl MessageLikeEventContent,
txn_id: Option<&TransactionId>,
) -> Result<send_message_event::v3::Response> {
let event_type = content.event_type().to_string();
@@ -808,7 +806,7 @@ impl Joined {
/// ```
pub async fn send_state_event(
&self,
content: impl EventContent<EventType = StateEventType>,
content: impl StateEventContent,
state_key: &str,
) -> Result<send_state_event::v3::Response> {
let request =