sdk: Allow to get stripped state events from the store

Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
This commit is contained in:
Kévin Commaille
2023-05-31 13:37:59 +02:00
committed by Jonas Platte
parent 645af31c59
commit 83e7afab5d
13 changed files with 279 additions and 173 deletions
@@ -19,7 +19,10 @@ use std::{collections::BTreeMap, fmt};
pub use matrix_sdk_common::deserialized_responses::*;
use ruma::{
events::{
room::member::{MembershipState, RoomMemberEvent, RoomMemberEventContent},
room::{
member::{MembershipState, RoomMemberEvent, RoomMemberEventContent},
power_levels::{RoomPowerLevels, RoomPowerLevelsEventContent},
},
AnyStrippedStateEvent, AnySyncStateEvent, EventContentFromType,
PossiblyRedactedStateEventContent, RedactContent, RedactedStateEventContent,
StateEventContent, StaticStateEventContent, StrippedStateEvent, SyncStateEvent,
@@ -265,3 +268,13 @@ impl MemberEvent {
self.state_key()
}
}
impl SyncOrStrippedState<RoomPowerLevelsEventContent> {
/// The power levels of the event.
pub fn power_levels(&self) -> RoomPowerLevels {
match self {
Self::Sync(e) => e.power_levels(),
Self::Stripped(e) => e.power_levels(),
}
}
}
+6 -3
View File
@@ -19,14 +19,17 @@ use ruma::{
presence::PresenceEvent,
room::{
member::MembershipState,
power_levels::{PowerLevelAction, RoomPowerLevels, SyncRoomPowerLevelsEvent},
power_levels::{PowerLevelAction, RoomPowerLevels, RoomPowerLevelsEventContent},
},
MessageLikeEventType, StateEventType,
},
MxcUri, UserId,
};
use crate::{deserialized_responses::MemberEvent, MinimalRoomMemberEvent};
use crate::{
deserialized_responses::{MemberEvent, SyncOrStrippedState},
MinimalRoomMemberEvent,
};
/// A member of a room.
#[derive(Clone, Debug)]
@@ -38,7 +41,7 @@ pub struct RoomMember {
pub(crate) profile: Arc<Option<MinimalRoomMemberEvent>>,
#[allow(dead_code)]
pub(crate) presence: Arc<Option<PresenceEvent>>,
pub(crate) power_levels: Arc<Option<SyncRoomPowerLevelsEvent>>,
pub(crate) power_levels: Arc<Option<SyncOrStrippedState<RoomPowerLevelsEventContent>>>,
pub(crate) max_power_level: i64,
pub(crate) is_room_creator: bool,
pub(crate) display_name_ambiguous: bool,
@@ -17,12 +17,12 @@ use ruma::{
SyncRoomMemberEvent,
},
power_levels::RoomPowerLevelsEventContent,
topic::{OriginalRoomTopicEvent, RedactedRoomTopicEvent, RoomTopicEventContent},
topic::RoomTopicEventContent,
MediaSource,
},
AnyEphemeralRoomEventContent, AnyGlobalAccountDataEvent, AnyRoomAccountDataEvent,
AnyStrippedStateEvent, AnySyncEphemeralRoomEvent, AnySyncStateEvent,
GlobalAccountDataEventType, RoomAccountDataEventType, StateEventType,
GlobalAccountDataEventType, RoomAccountDataEventType, StateEventType, SyncStateEvent,
},
mxc_uri, room_id,
serde::Raw,
@@ -266,8 +266,12 @@ impl StateStoreIntegrationTests for DynStateStore {
self.get_state_event_static::<RoomTopicEventContent>(room_id)
.await?
.expect("room topic found before redaction")
.deserialize_as::<OriginalRoomTopicEvent>()
.deserialize()
.expect("can deserialize room topic before redaction")
.as_sync()
.expect("room topic is a sync state event")
.as_original()
.expect("room topic is not redacted yet")
.content
.topic,
"😀"
@@ -283,23 +287,15 @@ impl StateStoreIntegrationTests for DynStateStore {
changes.add_redaction(room_id, &redacted_event_id, redaction_evt);
self.save_changes(&changes).await?;
match self
.get_state_event_static::<RoomTopicEventContent>(room_id)
.await?
.expect("room topic found before redaction")
.deserialize_as::<OriginalRoomTopicEvent>()
{
Err(_) => {} // as expected
Ok(_) => panic!("Topic has not been redacted"),
}
let _ = self
let redacted_event = self
.get_state_event_static::<RoomTopicEventContent>(room_id)
.await?
.expect("room topic found after redaction")
.deserialize_as::<RedactedRoomTopicEvent>()
.deserialize()
.expect("can deserialize room topic after redaction");
assert_matches!(redacted_event.as_sync(), Some(SyncStateEvent::Redacted(_)));
Ok(())
}
@@ -37,8 +37,9 @@ use tracing::{debug, warn};
use super::{Result, RoomInfo, StateChanges, StateStore, StoreError};
use crate::{
deserialized_responses::RawMemberEvent, media::MediaRequest, MinimalRoomMemberEvent,
RoomMemberships, StateStoreDataKey, StateStoreDataValue,
deserialized_responses::{RawAnySyncOrStrippedState, RawMemberEvent},
media::MediaRequest,
MinimalRoomMemberEvent, RoomMemberships, StateStoreDataKey, StateStoreDataValue,
};
/// In-Memory, non-persistent implementation of the `StateStore`
@@ -376,25 +377,48 @@ impl MemoryStore {
room_id: &RoomId,
event_type: StateEventType,
state_key: &str,
) -> Result<Option<Raw<AnySyncStateEvent>>> {
Ok(self
) -> Result<Option<RawAnySyncOrStrippedState>> {
if let Some(e) = self
.stripped_room_state
.get(room_id)
.as_ref()
.and_then(|events| events.get(&event_type))
.and_then(|m| m.get(state_key).map(|m| m.clone()))
{
Ok(Some(RawAnySyncOrStrippedState::Stripped(e)))
} else if let Some(e) = self
.room_state
.get(room_id)
.and_then(|e| e.get(&event_type).and_then(|s| s.get(state_key).map(|e| e.clone()))))
.as_ref()
.and_then(|events| events.get(&event_type))
.and_then(|m| m.get(state_key).map(|m| m.clone()))
{
Ok(Some(RawAnySyncOrStrippedState::Sync(e)))
} else {
Ok(None)
}
}
async fn get_state_events(
&self,
room_id: &RoomId,
event_type: StateEventType,
) -> Result<Vec<Raw<AnySyncStateEvent>>> {
Ok(self
.room_state
.get(room_id)
.and_then(|e| {
e.get(&event_type).map(|s| s.iter().map(|e| e.clone()).collect::<Vec<_>>())
) -> Result<Vec<RawAnySyncOrStrippedState>> {
if let Some(v) = self.stripped_room_state.get(room_id).as_ref().and_then(|events| {
events.get(&event_type).map(|s| {
s.iter().map(|e| RawAnySyncOrStrippedState::Stripped(e.clone())).collect::<Vec<_>>()
})
.unwrap_or_default())
}) {
Ok(v)
} else if let Some(v) = self.room_state.get(room_id).as_ref().and_then(|events| {
events.get(&event_type).map(|s| {
s.iter().map(|e| RawAnySyncOrStrippedState::Sync(e.clone())).collect::<Vec<_>>()
})
}) {
Ok(v)
} else {
Ok(Vec::new())
}
}
async fn get_profile(
@@ -410,25 +434,9 @@ impl MemoryStore {
room_id: &RoomId,
state_key: &UserId,
) -> Result<Option<RawMemberEvent>> {
if let Some(e) = self
.stripped_room_state
.get(room_id)
.as_ref()
.and_then(|events| events.get(&StateEventType::RoomMember))
.and_then(|m| m.get(state_key.as_str()).map(|m| m.clone().cast()))
{
Ok(Some(RawMemberEvent::Stripped(e)))
} else if let Some(e) = self
.room_state
.get(room_id)
.as_ref()
.and_then(|events| events.get(&StateEventType::RoomMember))
.and_then(|m| m.get(state_key.as_str()).map(|m| m.clone().cast()))
{
Ok(Some(RawMemberEvent::Sync(e)))
} else {
Ok(None)
}
self.get_state_event(room_id, StateEventType::RoomMember, state_key.as_str())
.await
.map(|opt| opt.map(|raw| raw.cast()))
}
/// Get the user IDs for the given room with the given memberships and
@@ -588,7 +596,7 @@ impl StateStore for MemoryStore {
room_id: &RoomId,
event_type: StateEventType,
state_key: &str,
) -> Result<Option<Raw<AnySyncStateEvent>>> {
) -> Result<Option<RawAnySyncOrStrippedState>> {
self.get_state_event(room_id, event_type, state_key).await
}
@@ -596,7 +604,7 @@ impl StateStore for MemoryStore {
&self,
room_id: &RoomId,
event_type: StateEventType,
) -> Result<Vec<Raw<AnySyncStateEvent>>> {
) -> Result<Vec<RawAnySyncOrStrippedState>> {
self.get_state_events(room_id, event_type).await
}
+20 -17
View File
@@ -20,11 +20,10 @@ use ruma::{
events::{
presence::PresenceEvent,
receipt::{Receipt, ReceiptThread, ReceiptType},
AnyGlobalAccountDataEvent, AnyRoomAccountDataEvent, AnySyncStateEvent, EmptyStateKey,
GlobalAccountDataEvent, GlobalAccountDataEventContent, GlobalAccountDataEventType,
RedactContent, RedactedStateEventContent, RoomAccountDataEvent,
RoomAccountDataEventContent, RoomAccountDataEventType, StateEventType, StaticEventContent,
StaticStateEventContent, SyncStateEvent,
AnyGlobalAccountDataEvent, AnyRoomAccountDataEvent, EmptyStateKey, GlobalAccountDataEvent,
GlobalAccountDataEventContent, GlobalAccountDataEventType, RedactContent,
RedactedStateEventContent, RoomAccountDataEvent, RoomAccountDataEventContent,
RoomAccountDataEventType, StateEventType, StaticEventContent, StaticStateEventContent,
},
serde::Raw,
EventId, MxcUri, OwnedEventId, OwnedUserId, RoomId, UserId,
@@ -32,8 +31,9 @@ use ruma::{
use super::{StateChanges, StoreError};
use crate::{
deserialized_responses::RawMemberEvent, media::MediaRequest, MinimalRoomMemberEvent, RoomInfo,
RoomMemberships,
deserialized_responses::{RawAnySyncOrStrippedState, RawMemberEvent, RawSyncOrStrippedState},
media::MediaRequest,
MinimalRoomMemberEvent, RoomInfo, RoomMemberships,
};
/// An abstract state store trait that can be used to implement different stores
@@ -102,7 +102,7 @@ pub trait StateStore: AsyncTraitDeps {
room_id: &RoomId,
event_type: StateEventType,
state_key: &str,
) -> Result<Option<Raw<AnySyncStateEvent>>, Self::Error>;
) -> Result<Option<RawAnySyncOrStrippedState>, Self::Error>;
/// Get a list of state events for a given room and `StateEventType`.
///
@@ -115,7 +115,7 @@ pub trait StateStore: AsyncTraitDeps {
&self,
room_id: &RoomId,
event_type: StateEventType,
) -> Result<Vec<Raw<AnySyncStateEvent>>, Self::Error>;
) -> Result<Vec<RawAnySyncOrStrippedState>, Self::Error>;
/// Get the current profile for the given user in the given room.
///
@@ -370,7 +370,7 @@ impl<T: StateStore> StateStore for EraseStateStoreError<T> {
room_id: &RoomId,
event_type: StateEventType,
state_key: &str,
) -> Result<Option<Raw<AnySyncStateEvent>>, Self::Error> {
) -> Result<Option<RawAnySyncOrStrippedState>, Self::Error> {
self.0.get_state_event(room_id, event_type, state_key).await.map_err(Into::into)
}
@@ -378,7 +378,7 @@ impl<T: StateStore> StateStore for EraseStateStoreError<T> {
&self,
room_id: &RoomId,
event_type: StateEventType,
) -> Result<Vec<Raw<AnySyncStateEvent>>, Self::Error> {
) -> Result<Vec<RawAnySyncOrStrippedState>, Self::Error> {
self.0.get_state_events(room_id, event_type).await.map_err(Into::into)
}
@@ -530,12 +530,12 @@ pub trait StateStoreExt: StateStore {
async fn get_state_event_static<C>(
&self,
room_id: &RoomId,
) -> Result<Option<Raw<SyncStateEvent<C>>>, Self::Error>
) -> Result<Option<RawSyncOrStrippedState<C>>, Self::Error>
where
C: StaticEventContent + StaticStateEventContent<StateKey = EmptyStateKey> + RedactContent,
C::Redacted: RedactedStateEventContent,
{
Ok(self.get_state_event(room_id, C::TYPE.into(), "").await?.map(Raw::cast))
Ok(self.get_state_event(room_id, C::TYPE.into(), "").await?.map(|raw| raw.cast()))
}
/// Get a specific state event of statically-known type.
@@ -547,14 +547,17 @@ pub trait StateStoreExt: StateStore {
&self,
room_id: &RoomId,
state_key: &K,
) -> Result<Option<Raw<SyncStateEvent<C>>>, Self::Error>
) -> Result<Option<RawSyncOrStrippedState<C>>, Self::Error>
where
C: StaticEventContent + StaticStateEventContent + RedactContent,
C::StateKey: Borrow<K>,
C::Redacted: RedactedStateEventContent,
K: AsRef<str> + ?Sized + Sync,
{
Ok(self.get_state_event(room_id, C::TYPE.into(), state_key.as_ref()).await?.map(Raw::cast))
Ok(self
.get_state_event(room_id, C::TYPE.into(), state_key.as_ref())
.await?
.map(|raw| raw.cast()))
}
/// Get a list of state events of a statically-known type for a given room.
@@ -565,7 +568,7 @@ pub trait StateStoreExt: StateStore {
async fn get_state_events_static<C>(
&self,
room_id: &RoomId,
) -> Result<Vec<Raw<SyncStateEvent<C>>>, Self::Error>
) -> Result<Vec<RawSyncOrStrippedState<C>>, Self::Error>
where
C: StaticEventContent + StaticStateEventContent + RedactContent,
C::Redacted: RedactedStateEventContent,
@@ -575,7 +578,7 @@ pub trait StateStoreExt: StateStore {
.get_state_events(room_id, C::TYPE.into())
.await?
.into_iter()
.map(Raw::cast)
.map(|raw| raw.cast())
.collect())
}
@@ -22,7 +22,7 @@ use async_trait::async_trait;
use gloo_utils::format::JsValueSerdeExt;
use indexed_db_futures::prelude::*;
use matrix_sdk_base::{
deserialized_responses::RawMemberEvent,
deserialized_responses::{RawAnySyncOrStrippedState, RawMemberEvent},
media::{MediaRequest, UniqueKey},
store::{StateChanges, StateStore, StoreError},
MinimalStateEvent, RoomInfo, RoomMemberships, StateStoreDataKey, StateStoreDataValue,
@@ -820,21 +820,52 @@ impl_state_store! {
room_id: &RoomId,
event_type: StateEventType,
state_key: &str,
) -> Result<Option<Raw<AnySyncStateEvent>>> {
self.inner
) -> Result<Option<RawAnySyncOrStrippedState>> {
if let Some(e) = self
.inner
.transaction_on_one_with_mode(keys::STRIPPED_ROOM_STATE, IdbTransactionMode::Readonly)?
.object_store(keys::STRIPPED_ROOM_STATE)?
.get(&self.encode_key(keys::STRIPPED_ROOM_STATE, (room_id, &event_type, state_key)))?
.await?
.map(|f| self.deserialize_event(&f))
.transpose()?
{
Ok(Some(RawAnySyncOrStrippedState::Stripped(e)))
} else if let Some(e) = self
.inner
.transaction_on_one_with_mode(keys::ROOM_STATE, IdbTransactionMode::Readonly)?
.object_store(keys::ROOM_STATE)?
.get(&self.encode_key(keys::ROOM_STATE, (room_id, event_type, state_key)))?
.await?
.map(|f| self.deserialize_event(&f))
.transpose()
.transpose()?
{
Ok(Some(RawAnySyncOrStrippedState::Sync(e)))
} else {
Ok(None)
}
}
async fn get_state_events(
&self,
room_id: &RoomId,
event_type: StateEventType,
) -> Result<Vec<Raw<AnySyncStateEvent>>> {
) -> Result<Vec<RawAnySyncOrStrippedState>> {
let stripped_range = self.encode_to_range(keys::STRIPPED_ROOM_STATE, (room_id, &event_type))?;
let stripped_events = self
.inner
.transaction_on_one_with_mode(keys::STRIPPED_ROOM_STATE, IdbTransactionMode::Readonly)?
.object_store(keys::STRIPPED_ROOM_STATE)?
.get_all_with_key(&stripped_range)?
.await?
.iter()
.filter_map(|f| self.deserialize_event(&f).ok().map(RawAnySyncOrStrippedState::Stripped))
.collect::<Vec<_>>();
if !stripped_events.is_empty() {
return Ok(stripped_events)
}
let range = self.encode_to_range(keys::ROOM_STATE, (room_id, event_type))?;
Ok(self
.inner
@@ -843,7 +874,7 @@ impl_state_store! {
.get_all_with_key(&range)?
.await?
.iter()
.filter_map(|f| self.deserialize_event(&f).ok())
.filter_map(|f| self.deserialize_event(&f).ok().map(RawAnySyncOrStrippedState::Sync))
.collect::<Vec<_>>())
}
@@ -402,7 +402,10 @@ mod test {
use matrix_sdk_test::{async_test, test_json};
use ruma::{
events::{
room::member::{StrippedRoomMemberEvent, SyncRoomMemberEvent},
room::{
member::{StrippedRoomMemberEvent, SyncRoomMemberEvent},
topic::RoomTopicEventContent,
},
AnySyncStateEvent, StateEventType,
},
room_id,
@@ -553,7 +556,7 @@ mod test {
.unwrap();
let event =
store.get_state_event(room_id, StateEventType::RoomTopic, "").await.unwrap().unwrap();
event.deserialize().unwrap();
event.cast::<RoomTopicEventContent>().deserialize().unwrap();
}
#[async_test]
+43 -31
View File
@@ -23,7 +23,7 @@ use async_trait::async_trait;
use futures_core::stream::Stream;
use futures_util::stream::{self, TryStreamExt};
use matrix_sdk_base::{
deserialized_responses::RawMemberEvent,
deserialized_responses::{RawAnySyncOrStrippedState, RawMemberEvent},
media::{MediaRequest, UniqueKey},
store::{Result as StoreResult, StateChanges, StateStore, StoreError},
MinimalStateEvent, RoomInfo, RoomMemberships, StateStoreDataKey, StateStoreDataValue,
@@ -787,11 +787,26 @@ impl SledStateStore {
room_id: &RoomId,
event_type: StateEventType,
state_key: &str,
) -> Result<Option<Raw<AnySyncStateEvent>>> {
) -> Result<Option<RawAnySyncOrStrippedState>> {
let db = self.clone();
let key = self.encode_key(keys::ROOM_STATE, (room_id, event_type.to_string(), state_key));
let stripped_key = self
.encode_key(keys::STRIPPED_ROOM_STATE, (room_id, event_type.to_string(), state_key));
spawn_blocking(move || {
db.room_state.get(key)?.map(|e| db.deserialize_value(&e)).transpose()
if let Some(e) = db
.stripped_room_state
.get(stripped_key)?
.map(|v| db.deserialize_value(&v))
.transpose()?
{
Ok(Some(RawAnySyncOrStrippedState::Stripped(e)))
} else if let Some(e) =
db.room_state.get(key)?.map(|v| db.deserialize_value(&v)).transpose()?
{
Ok(Some(RawAnySyncOrStrippedState::Sync(e)))
} else {
Ok(None)
}
})
.await?
}
@@ -800,13 +815,31 @@ impl SledStateStore {
&self,
room_id: &RoomId,
event_type: StateEventType,
) -> Result<Vec<Raw<AnySyncStateEvent>>> {
) -> Result<Vec<RawAnySyncOrStrippedState>> {
let db = self.clone();
let key = self.encode_key(keys::ROOM_STATE, (room_id, event_type.to_string()));
let stripped_key =
self.encode_key(keys::STRIPPED_ROOM_STATE, (room_id, event_type.to_string()));
spawn_blocking(move || {
let stripped_events = db
.stripped_room_state
.scan_prefix(stripped_key)
.flat_map(|e| {
e.map(|(_, e)| {
db.deserialize_value(&e).map(RawAnySyncOrStrippedState::Stripped)
})
})
.collect::<Result<Vec<_>, _>>()?;
if !stripped_events.is_empty() {
return Ok(stripped_events);
}
db.room_state
.scan_prefix(key)
.flat_map(|e| e.map(|(_, e)| db.deserialize_value(&e)))
.flat_map(|e| {
e.map(|(_, e)| db.deserialize_value(&e).map(RawAnySyncOrStrippedState::Sync))
})
.collect::<Result<_, _>>()
})
.await?
@@ -828,30 +861,9 @@ impl SledStateStore {
room_id: &RoomId,
state_key: &UserId,
) -> Result<Option<RawMemberEvent>> {
let db = self.clone();
let key =
self.encode_key(keys::ROOM_STATE, (room_id, StateEventType::RoomMember, state_key));
let stripped_key = self.encode_key(
keys::STRIPPED_ROOM_STATE,
(room_id, StateEventType::RoomMember, state_key),
);
spawn_blocking(move || {
if let Some(e) = db
.stripped_room_state
.get(stripped_key)?
.map(|v| db.deserialize_value(&v))
.transpose()?
{
Ok(Some(RawMemberEvent::Stripped(e)))
} else if let Some(e) =
db.room_state.get(key)?.map(|v| db.deserialize_value(&v)).transpose()?
{
Ok(Some(RawMemberEvent::Sync(e)))
} else {
Ok(None)
}
})
.await?
self.get_state_event(room_id, StateEventType::RoomMember, state_key.as_str())
.await
.map(|opt| opt.map(|raw| raw.cast()))
}
/// Get the user IDs for the given room with the given memberships and
@@ -1230,7 +1242,7 @@ impl StateStore for SledStateStore {
room_id: &RoomId,
event_type: StateEventType,
state_key: &str,
) -> StoreResult<Option<Raw<AnySyncStateEvent>>> {
) -> StoreResult<Option<RawAnySyncOrStrippedState>> {
self.get_state_event(room_id, event_type, state_key).await.map_err(Into::into)
}
@@ -1238,7 +1250,7 @@ impl StateStore for SledStateStore {
&self,
room_id: &RoomId,
event_type: StateEventType,
) -> StoreResult<Vec<Raw<AnySyncStateEvent>>> {
) -> StoreResult<Vec<RawAnySyncOrStrippedState>> {
self.get_state_events(room_id, event_type).await.map_err(Into::into)
}
+36 -30
View File
@@ -9,7 +9,7 @@ use std::{
use async_trait::async_trait;
use deadpool_sqlite::{Object as SqliteConn, Pool as SqlitePool, Runtime};
use matrix_sdk_base::{
deserialized_responses::RawMemberEvent,
deserialized_responses::{RawAnySyncOrStrippedState, RawMemberEvent},
media::{MediaRequest, UniqueKey},
RoomInfo, RoomMemberships, RoomState, StateChanges, StateStore, StateStoreDataKey,
StateStoreDataValue,
@@ -547,24 +547,6 @@ trait SqliteObjectStateStoreExt: SqliteObjectExt {
.await?)
}
async fn get_state_event(
&self,
room_id: Key,
event_type: Key,
state_key: Key,
stripped: bool,
) -> Result<Option<Vec<u8>>> {
Ok(self
.query_row(
"SELECT data FROM state_event
WHERE room_id = ? AND event_type = ? AND state_key = ? AND stripped = ?",
(room_id, event_type, state_key, stripped),
|row| row.get(0),
)
.await
.optional()?)
}
async fn get_maybe_stripped_state_event(
&self,
room_id: Key,
@@ -582,12 +564,20 @@ trait SqliteObjectStateStoreExt: SqliteObjectExt {
.optional()?)
}
async fn get_state_events(&self, room_id: Key, event_type: Key) -> Result<Vec<Vec<u8>>> {
async fn get_maybe_stripped_state_events(
&self,
room_id: Key,
event_type: Key,
) -> Result<Vec<(bool, Vec<u8>)>> {
Ok(self
.prepare(
"SELECT data FROM state_event
WHERE room_id = ? AND event_type = ? AND stripped = FALSE",
|mut stmt| stmt.query((room_id, event_type))?.mapped(|row| row.get(0)).collect(),
"SELECT stripped, data FROM state_event
WHERE room_id = ? AND event_type = ?",
|mut stmt| {
stmt.query((room_id, event_type))?
.mapped(|row| Ok((row.get(0)?, row.get(1)?)))
.collect()
},
)
.await?)
}
@@ -1080,15 +1070,23 @@ impl StateStore for SqliteStateStore {
room_id: &RoomId,
event_type: StateEventType,
state_key: &str,
) -> Result<Option<Raw<AnySyncStateEvent>>> {
) -> Result<Option<RawAnySyncOrStrippedState>> {
let room_id = self.encode_key(keys::STATE_EVENT, room_id);
let event_type = self.encode_key(keys::STATE_EVENT, event_type.to_string());
let state_key = self.encode_key(keys::STATE_EVENT, state_key);
self.acquire()
.await?
.get_state_event(room_id, event_type, state_key, false)
.get_maybe_stripped_state_event(room_id, event_type, state_key)
.await?
.map(|data| self.deserialize_json(&data))
.map(|(stripped, data)| {
let ev = if stripped {
RawAnySyncOrStrippedState::Stripped(self.deserialize_json(&data)?)
} else {
RawAnySyncOrStrippedState::Sync(self.deserialize_json(&data)?)
};
Ok(ev)
})
.transpose()
}
@@ -1096,15 +1094,23 @@ impl StateStore for SqliteStateStore {
&self,
room_id: &RoomId,
event_type: StateEventType,
) -> Result<Vec<Raw<AnySyncStateEvent>>> {
) -> Result<Vec<RawAnySyncOrStrippedState>> {
let room_id = self.encode_key(keys::STATE_EVENT, room_id);
let event_type = self.encode_key(keys::STATE_EVENT, event_type.to_string());
self.acquire()
.await?
.get_state_events(room_id, event_type)
.get_maybe_stripped_state_events(room_id, event_type)
.await?
.iter()
.map(|data| self.deserialize_json(data))
.into_iter()
.map(|(stripped, data)| {
let ev = if stripped {
RawAnySyncOrStrippedState::Stripped(self.deserialize_json(&data)?)
} else {
RawAnySyncOrStrippedState::Sync(self.deserialize_json(&data)?)
};
Ok(ev)
})
.collect()
}
+2
View File
@@ -10,6 +10,8 @@
- `Common::active_members(_no_sync)` and `Common::joined_members(_no_sync)` are deprecated.
- `matrix-sdk-sqlite` is the new default store implementation outside of WASM, behind the `sqlite` feature.
- The `sled` feature was removed. It is still possible to use `matrix-sdk-sled` as a custom store.
- The `Common` methods to retrieve state events can now return a sync or stripped event, so it can be used
for invited rooms too.
# 0.6.2
+25 -18
View File
@@ -1,7 +1,10 @@
use std::{borrow::Borrow, collections::BTreeMap, fmt, ops::Deref, sync::Arc};
use matrix_sdk_base::{
deserialized_responses::{MembersResponse, TimelineEvent},
deserialized_responses::{
MembersResponse, RawAnySyncOrStrippedState, RawSyncOrStrippedState, SyncOrStrippedState,
TimelineEvent,
},
store::StateStoreExt,
RoomMemberships, StateChanges,
};
@@ -35,10 +38,9 @@ use ruma::{
MediaSource,
},
tag::{TagInfo, TagName},
AnyRoomAccountDataEvent, AnyStateEvent, AnySyncStateEvent, EmptyStateKey, RedactContent,
AnyRoomAccountDataEvent, AnyStateEvent, EmptyStateKey, RedactContent,
RedactedStateEventContent, RoomAccountDataEvent, RoomAccountDataEventContent,
RoomAccountDataEventType, StateEventType, StaticEventContent, StaticStateEventContent,
SyncStateEvent,
},
push::{Action, PushConditionRoomCtx},
serde::Raw,
@@ -539,7 +541,7 @@ impl Common {
pub async fn get_state_events(
&self,
event_type: StateEventType,
) -> Result<Vec<Raw<AnySyncStateEvent>>> {
) -> Result<Vec<RawAnySyncOrStrippedState>> {
self.client.store().get_state_events(self.room_id(), event_type).await.map_err(Into::into)
}
@@ -551,15 +553,15 @@ impl Common {
/// # async {
/// # let room: matrix_sdk::room::Common = todo!();
/// use matrix_sdk::ruma::{
/// events::room::member::SyncRoomMemberEvent, serde::Raw,
/// events::room::member::RoomMemberEventContent, serde::Raw,
/// };
///
/// let room_members: Vec<Raw<SyncRoomMemberEvent>> =
/// room.get_state_events_static().await?;
/// let room_members =
/// room.get_state_events_static::<RoomMemberEventContent>().await?;
/// # anyhow::Ok(())
/// # };
/// ```
pub async fn get_state_events_static<C>(&self) -> Result<Vec<Raw<SyncStateEvent<C>>>>
pub async fn get_state_events_static<C>(&self) -> Result<Vec<RawSyncOrStrippedState<C>>>
where
C: StaticEventContent + StaticStateEventContent + RedactContent,
C::Redacted: RedactedStateEventContent,
@@ -572,7 +574,7 @@ impl Common {
&self,
event_type: StateEventType,
state_key: &str,
) -> Result<Option<Raw<AnySyncStateEvent>>> {
) -> Result<Option<RawAnySyncOrStrippedState>> {
self.client
.store()
.get_state_event(self.room_id(), event_type, state_key)
@@ -588,17 +590,17 @@ impl Common {
/// ```no_run
/// # async {
/// # let room: matrix_sdk::room::Common = todo!();
/// use matrix_sdk::ruma::events::room::power_levels::SyncRoomPowerLevelsEvent;
/// use matrix_sdk::ruma::events::room::power_levels::RoomPowerLevelsEventContent;
///
/// let power_levels: SyncRoomPowerLevelsEvent = room
/// .get_state_event_static()
/// let power_levels = room
/// .get_state_event_static::<RoomPowerLevelsEventContent>()
/// .await?
/// .expect("every room has a power_levels event")
/// .deserialize()?;
/// # anyhow::Ok(())
/// # };
/// ```
pub async fn get_state_event_static<C>(&self) -> Result<Option<Raw<SyncStateEvent<C>>>>
pub async fn get_state_event_static<C>(&self) -> Result<Option<RawSyncOrStrippedState<C>>>
where
C: StaticEventContent + StaticStateEventContent<StateKey = EmptyStateKey> + RedactContent,
C::Redacted: RedactedStateEventContent,
@@ -614,11 +616,13 @@ impl Common {
/// # async {
/// # let room: matrix_sdk::room::Common = todo!();
/// use matrix_sdk::ruma::{
/// events::room::member::SyncRoomMemberEvent, serde::Raw, user_id,
/// events::room::member::RoomMemberEventContent, serde::Raw, user_id,
/// };
///
/// let member_event: Option<Raw<SyncRoomMemberEvent>> = room
/// .get_state_event_static_for_key(user_id!("@alice:example.org"))
/// let member_event = room
/// .get_state_event_static_for_key::<RoomMemberEventContent, _>(user_id!(
/// "@alice:example.org"
/// ))
/// .await?;
/// # anyhow::Ok(())
/// # };
@@ -626,7 +630,7 @@ impl Common {
pub async fn get_state_event_static_for_key<C, K>(
&self,
state_key: &K,
) -> Result<Option<Raw<SyncStateEvent<C>>>>
) -> Result<Option<RawSyncOrStrippedState<C>>>
where
C: StaticEventContent + StaticStateEventContent + RedactContent,
C::StateKey: Borrow<K>,
@@ -839,7 +843,10 @@ impl Common {
.get_state_event_static::<RoomServerAclEventContent>()
.await?
.and_then(|ev| ev.deserialize().ok());
let acl = acl_ev.as_ref().and_then(|ev| ev.as_original()).map(|ev| &ev.content);
let acl = acl_ev.as_ref().and_then(|ev| match ev {
SyncOrStrippedState::Sync(ev) => ev.as_original().map(|ev| &ev.content),
SyncOrStrippedState::Stripped(ev) => Some(&ev.content),
});
// Filter out server names that:
// - Are blocked due to server ACLs
@@ -171,7 +171,10 @@ async fn test_state_event_getting() {
.deserialize()
.unwrap();
assert_matches::assert_matches!(encryption_event, AnySyncStateEvent::RoomEncryption(_));
assert_matches::assert_matches!(
encryption_event.as_sync(),
Some(AnySyncStateEvent::RoomEncryption(_))
);
}
#[async_test]
@@ -4,10 +4,7 @@ use matrix_sdk::{
config::SyncSettings,
ruma::{
api::client::room::create_room::v3::Request as CreateRoomRequest,
events::{
room::name::{RoomNameEventContent, SyncRoomNameEvent},
StateEventType,
},
events::{room::name::RoomNameEventContent, StateEventType},
},
Client,
};
@@ -64,13 +61,14 @@ async fn test_redacting_name() -> Result<()> {
let raw_event =
room.get_state_event(StateEventType::RoomName, "").await?.expect("Room Name not found");
let room_name_event: SyncRoomNameEvent = raw_event.deserialize_as()?;
let room_name_event = raw_event.cast::<RoomNameEventContent>().deserialize()?;
let sync_room_name_event = room_name_event.as_sync().expect("event is sync event");
assert!(
room_name_event.as_original().expect("event exists").content.name.is_some(),
sync_room_name_event.as_original().expect("event exists").content.name.is_some(),
"Event not found"
);
room.redact(room_name_event.event_id(), None, None).await?;
room.redact(sync_room_name_event.event_id(), None, None).await?;
// sync up.
for _ in 0..=10 {
// we call sync up to ten times to give the server time to flush other
@@ -84,10 +82,17 @@ async fn test_redacting_name() -> Result<()> {
let raw_event =
room.get_state_event(StateEventType::RoomName, "").await?.expect("Room Name not found");
let room_name_event: SyncRoomNameEvent = raw_event.deserialize_as()?;
let room_name_event = raw_event.cast::<RoomNameEventContent>().deserialize()?;
// Name content has been redacted
assert!(
room_name_event.as_original().expect("event exists").content.name.is_none(),
room_name_event
.as_sync()
.expect("event is sync event")
.as_original()
.expect("event exists")
.content
.name
.is_none(),
"Event hasn't been redacted"
);
@@ -132,14 +137,18 @@ async fn test_redacting_name_static() -> Result<()> {
// check state event.
let room_name_event: SyncRoomNameEvent =
room.get_state_event_static().await?.expect("Room Name not found").deserialize()?;
let room_name_event = room
.get_state_event_static::<RoomNameEventContent>()
.await?
.expect("Room Name not found")
.deserialize()?;
let sync_room_name_event = room_name_event.as_sync().expect("event is sync event");
assert!(
room_name_event.as_original().expect("event exists").content.name.is_some(),
sync_room_name_event.as_original().expect("event exists").content.name.is_some(),
"Event not found"
);
room.redact(room_name_event.event_id(), None, None).await?;
room.redact(sync_room_name_event.event_id(), None, None).await?;
// we sync up.
for _ in 0..=10 {
// we call sync up to ten times to give the server time to flush other
@@ -151,11 +160,21 @@ async fn test_redacting_name_static() -> Result<()> {
}
}
let room_name_event: SyncRoomNameEvent =
room.get_state_event_static().await?.expect("Room Name not found").deserialize()?;
let room_name_event = room
.get_state_event_static::<RoomNameEventContent>()
.await?
.expect("Room Name not found")
.deserialize()?;
// Name content has been redacted
assert!(
room_name_event.as_original().expect("event exists").content.name.is_none(),
room_name_event
.as_sync()
.expect("event is sync event")
.as_original()
.expect("event exists")
.content
.name
.is_none(),
"Event hasn't been redacted"
);