use event content in account_data service api instead of full events

This eliminates the possibility of passing an event that has a
mismatching type, reducing the space of possible invalid states.
This commit is contained in:
Olivia Lee 2025-03-23 14:45:33 -07:00
parent 66210bc32d
commit b82458a460
No known key found for this signature in database
GPG key ID: 54D568A15B9CD1F9
15 changed files with 277 additions and 240 deletions

View file

@ -5,9 +5,10 @@ use std::{
use ruma::{
events::{
ignored_user_list::IgnoredUserListEvent, room::member::MembershipState,
AnyGlobalAccountDataEvent, AnyStrippedStateEvent, AnySyncStateEvent,
GlobalAccountDataEventType, RoomAccountDataEventType,
ignored_user_list::IgnoredUserListEventContent,
room::member::MembershipState, AnyGlobalAccountDataEventContent,
AnyStrippedStateEvent, AnySyncStateEvent, GlobalAccountDataEventType,
RoomAccountDataEventType,
},
serde::Raw,
OwnedRoomId, OwnedServerName, OwnedUserId, RoomId, ServerName, UserId,
@ -102,7 +103,7 @@ impl Service {
&GlobalAccountDataEventType::IgnoredUserList,
)?
.map(|event| {
event.deserialize_as::<IgnoredUserListEvent>()
event.deserialize_as::<IgnoredUserListEventContent>()
.map_err(|error| {
warn!(
%error,
@ -114,7 +115,6 @@ impl Service {
.transpose()?
.is_some_and(|ignored| {
ignored
.content
.ignored_users
.iter()
.any(|(user, _details)| user == sender)
@ -221,14 +221,14 @@ impl Service {
from_room_id: &RoomId,
to_room_id: &RoomId,
) -> Result<()> {
let Some(event) = services()
let Some(event_content) = services()
.account_data
.get_global(user_id, &GlobalAccountDataEventType::Direct)?
else {
return Ok(());
};
let mut event = event
let mut event_content = event_content
.deserialize_as::<serde_json::Value>()
.expect("RawValue -> Value should always succeed");
@ -240,14 +240,11 @@ impl Service {
//
// [1]: https://github.com/element-hq/element-web/issues/27630
//
// A valid m.direct event looks like this:
// Valid m.direct event content looks like this:
//
// {
// "type": "m.account_data",
// "content": {
// "@userid1": [ "!roomid1", "!roomid2" ],
// "@userid2": [ "!roomid3" ],
// }
// "@userid1": [ "!roomid1", "!roomid2" ],
// "@userid2": [ "!roomid3" ],
// }
//
// We want to find userid keys where the value contains from_room_id,
@ -257,10 +254,7 @@ impl Service {
// parts.
let mut event_updated = false;
let Some(direct_user_ids) = event.get_mut("content") else {
return Ok(());
};
let Some(direct_user_ids) = direct_user_ids.as_object_mut() else {
let Some(direct_user_ids) = event_content.as_object_mut() else {
return Ok(());
};
for room_ids in direct_user_ids.values_mut() {
@ -277,9 +271,9 @@ impl Service {
if let Err(error) = services().account_data.update_global(
user_id,
&GlobalAccountDataEventType::Direct,
&Raw::new(&event)
&Raw::new(&event_content)
.expect("json serialization should always succeed")
.cast::<AnyGlobalAccountDataEvent>(),
.cast::<AnyGlobalAccountDataEventContent>(),
) {
warn!(%error, "error writing m.direct account data event after upgrading room");
}

View file

@ -9,7 +9,7 @@ use ruma::{
api::{client::error::ErrorKind, federation},
canonical_json::to_canonical_value,
events::{
push_rules::PushRulesEvent,
push_rules::PushRulesEventContent,
room::{
create::RoomCreateEventContent, encrypted::Relation,
member::MembershipState, message::RoomMessageEventContent,
@ -419,15 +419,16 @@ impl Service {
.account_data
.get_global(user, &GlobalAccountDataEventType::PushRules)?
.map(|event| {
event.deserialize_as::<PushRulesEvent>().map_err(|_| {
Error::bad_database("Invalid push rules event in db.")
})
event.deserialize_as::<PushRulesEventContent>().map_err(
|_| {
Error::bad_database(
"Invalid push rules event in db.",
)
},
)
})
.transpose()?
.map_or_else(
|| Ruleset::server_default(user),
|ev: PushRulesEvent| ev.content.global,
);
.map_or_else(|| Ruleset::server_default(user), |ev| ev.global);
let mut highlight = false;
let mut notify = false;