Upgrade Ruma

Co-authored-by: Timo Kösters <timo@koesters.xyz>
This commit is contained in:
Jonas Platte 2021-10-13 10:16:45 +02:00
parent 47f3263396
commit 09895a20c8
No known key found for this signature in database
GPG key ID: 7D261D771D915378
21 changed files with 628 additions and 623 deletions

View file

@ -15,19 +15,28 @@ use ruma::{
ThirdPartyIdRemovalStatus,
},
contact::get_contacts,
uiaa::{AuthFlow, UiaaInfo},
uiaa::{AuthFlow, AuthType, UiaaInfo},
},
},
events::{
room::{
canonical_alias, guest_access, history_visibility, join_rules, member, message, name,
topic,
canonical_alias::RoomCanonicalAliasEventContent,
create::RoomCreateEventContent,
guest_access::{GuestAccess, RoomGuestAccessEventContent},
history_visibility::{HistoryVisibility, RoomHistoryVisibilityEventContent},
join_rules::{JoinRule, RoomJoinRulesEventContent},
member::{MembershipState, RoomMemberEventContent},
message::RoomMessageEventContent,
name::RoomNameEventContent,
power_levels::RoomPowerLevelsEventContent,
topic::RoomTopicEventContent,
},
EventType,
},
identifiers::RoomName,
push, RoomAliasId, RoomId, RoomVersionId, UserId,
};
use serde_json::value::to_raw_value;
use tracing::info;
use register::RegistrationKind;
@ -147,7 +156,7 @@ pub async fn register_route(
// UIAA
let mut uiaainfo = UiaaInfo {
flows: vec![AuthFlow {
stages: vec!["m.login.dummy".to_owned()],
stages: vec![AuthType::Dummy],
}],
completed: Vec::new(),
params: Default::default(),
@ -270,7 +279,7 @@ pub async fn register_route(
);
let state_lock = mutex_state.lock().await;
let mut content = ruma::events::room::create::CreateEventContent::new(conduit_user.clone());
let mut content = RoomCreateEventContent::new(conduit_user.clone());
content.federate = true;
content.predecessor = None;
content.room_version = RoomVersionId::Version6;
@ -279,7 +288,7 @@ pub async fn register_route(
db.rooms.build_and_append_pdu(
PduBuilder {
event_type: EventType::RoomCreate,
content: serde_json::to_value(content).expect("event is valid, we just created it"),
content: to_raw_value(&content).expect("event is valid, we just created it"),
unsigned: None,
state_key: Some("".to_owned()),
redacts: None,
@ -294,8 +303,8 @@ pub async fn register_route(
db.rooms.build_and_append_pdu(
PduBuilder {
event_type: EventType::RoomMember,
content: serde_json::to_value(member::MemberEventContent {
membership: member::MembershipState::Join,
content: to_raw_value(&RoomMemberEventContent {
membership: MembershipState::Join,
displayname: None,
avatar_url: None,
is_direct: None,
@ -322,12 +331,10 @@ pub async fn register_route(
db.rooms.build_and_append_pdu(
PduBuilder {
event_type: EventType::RoomPowerLevels,
content: serde_json::to_value(
ruma::events::room::power_levels::PowerLevelsEventContent {
users,
..Default::default()
},
)
content: to_raw_value(&RoomPowerLevelsEventContent {
users,
..Default::default()
})
.expect("event is valid, we just created it"),
unsigned: None,
state_key: Some("".to_owned()),
@ -343,10 +350,8 @@ pub async fn register_route(
db.rooms.build_and_append_pdu(
PduBuilder {
event_type: EventType::RoomJoinRules,
content: serde_json::to_value(join_rules::JoinRulesEventContent::new(
join_rules::JoinRule::Invite,
))
.expect("event is valid, we just created it"),
content: to_raw_value(&RoomJoinRulesEventContent::new(JoinRule::Invite))
.expect("event is valid, we just created it"),
unsigned: None,
state_key: Some("".to_owned()),
redacts: None,
@ -361,11 +366,9 @@ pub async fn register_route(
db.rooms.build_and_append_pdu(
PduBuilder {
event_type: EventType::RoomHistoryVisibility,
content: serde_json::to_value(
history_visibility::HistoryVisibilityEventContent::new(
history_visibility::HistoryVisibility::Shared,
),
)
content: to_raw_value(&RoomHistoryVisibilityEventContent::new(
HistoryVisibility::Shared,
))
.expect("event is valid, we just created it"),
unsigned: None,
state_key: Some("".to_owned()),
@ -381,10 +384,8 @@ pub async fn register_route(
db.rooms.build_and_append_pdu(
PduBuilder {
event_type: EventType::RoomGuestAccess,
content: serde_json::to_value(guest_access::GuestAccessEventContent::new(
guest_access::GuestAccess::Forbidden,
))
.expect("event is valid, we just created it"),
content: to_raw_value(&RoomGuestAccessEventContent::new(GuestAccess::Forbidden))
.expect("event is valid, we just created it"),
unsigned: None,
state_key: Some("".to_owned()),
redacts: None,
@ -402,7 +403,7 @@ pub async fn register_route(
db.rooms.build_and_append_pdu(
PduBuilder {
event_type: EventType::RoomName,
content: serde_json::to_value(name::NameEventContent::new(Some(room_name)))
content: to_raw_value(&RoomNameEventContent::new(Some(room_name)))
.expect("event is valid, we just created it"),
unsigned: None,
state_key: Some("".to_owned()),
@ -417,7 +418,7 @@ pub async fn register_route(
db.rooms.build_and_append_pdu(
PduBuilder {
event_type: EventType::RoomTopic,
content: serde_json::to_value(topic::TopicEventContent {
content: to_raw_value(&RoomTopicEventContent {
topic: format!("Manage {}", db.globals.server_name()),
})
.expect("event is valid, we just created it"),
@ -439,7 +440,7 @@ pub async fn register_route(
db.rooms.build_and_append_pdu(
PduBuilder {
event_type: EventType::RoomCanonicalAlias,
content: serde_json::to_value(canonical_alias::CanonicalAliasEventContent {
content: to_raw_value(&RoomCanonicalAliasEventContent {
alias: Some(alias.clone()),
alt_aliases: Vec::new(),
})
@ -460,8 +461,8 @@ pub async fn register_route(
db.rooms.build_and_append_pdu(
PduBuilder {
event_type: EventType::RoomMember,
content: serde_json::to_value(member::MemberEventContent {
membership: member::MembershipState::Invite,
content: to_raw_value(&RoomMemberEventContent {
membership: MembershipState::Invite,
displayname: None,
avatar_url: None,
is_direct: None,
@ -482,8 +483,8 @@ pub async fn register_route(
db.rooms.build_and_append_pdu(
PduBuilder {
event_type: EventType::RoomMember,
content: serde_json::to_value(member::MemberEventContent {
membership: member::MembershipState::Join,
content: to_raw_value(&RoomMemberEventContent {
membership: MembershipState::Join,
displayname: Some(displayname),
avatar_url: None,
is_direct: None,
@ -506,7 +507,7 @@ pub async fn register_route(
db.rooms.build_and_append_pdu(
PduBuilder {
event_type: EventType::RoomMessage,
content: serde_json::to_value(message::MessageEventContent::text_html(
content: to_raw_value(&RoomMessageEventContent::text_html(
"## Thank you for trying out Conduit!\n\nConduit is currently in Beta. This means you can join and participate in most Matrix rooms, but not all features are supported and you might run into bugs from time to time.\n\nHelpful links:\n> Website: https://conduit.rs\n> Git and Documentation: https://gitlab.com/famedly/conduit\n> Report issues: https://gitlab.com/famedly/conduit/-/issues\n\nHere are some rooms you can join (by typing the command):\n\nConduit room (Ask questions and get notified on updates):\n`/join #conduit:fachschaften.org`\n\nConduit lounge (Off-topic, only Conduit users are allowed to join)\n`/join #conduit-lounge:conduit.rs`".to_owned(),
"<h2>Thank you for trying out Conduit!</h2>\n<p>Conduit is currently in Beta. This means you can join and participate in most Matrix rooms, but not all features are supported and you might run into bugs from time to time.</p>\n<p>Helpful links:</p>\n<blockquote>\n<p>Website: https://conduit.rs<br>Git and Documentation: https://gitlab.com/famedly/conduit<br>Report issues: https://gitlab.com/famedly/conduit/-/issues</p>\n</blockquote>\n<p>Here are some rooms you can join (by typing the command):</p>\n<p>Conduit room (Ask questions and get notified on updates):<br><code>/join #conduit:fachschaften.org</code></p>\n<p>Conduit lounge (Off-topic, only Conduit users are allowed to join)<br><code>/join #conduit-lounge:conduit.rs</code></p>\n".to_owned(),
))
@ -562,7 +563,7 @@ pub async fn change_password_route(
let mut uiaainfo = UiaaInfo {
flows: vec![AuthFlow {
stages: vec!["m.login.password".to_owned()],
stages: vec![AuthType::Password],
}],
completed: Vec::new(),
params: Default::default(),
@ -654,7 +655,7 @@ pub async fn deactivate_route(
let mut uiaainfo = UiaaInfo {
flows: vec![AuthFlow {
stages: vec!["m.login.password".to_owned()],
stages: vec![AuthType::Password],
}],
completed: Vec::new(),
params: Default::default(),
@ -698,8 +699,8 @@ pub async fn deactivate_route(
for room_id in all_rooms {
let room_id = room_id?;
let event = member::MemberEventContent {
membership: member::MembershipState::Leave,
let event = RoomMemberEventContent {
membership: MembershipState::Leave,
displayname: None,
avatar_url: None,
is_direct: None,
@ -721,7 +722,7 @@ pub async fn deactivate_route(
db.rooms.build_and_append_pdu(
PduBuilder {
event_type: EventType::RoomMember,
content: serde_json::to_value(event).expect("event is valid, we just created it"),
content: to_raw_value(&event).expect("event is valid, we just created it"),
unsigned: None,
state_key: Some(sender_user.to_string()),
redacts: None,

View file

@ -3,7 +3,7 @@ use ruma::api::client::{
error::ErrorKind,
r0::{
device::{self, delete_device, delete_devices, get_device, get_devices, update_device},
uiaa::{AuthFlow, UiaaInfo},
uiaa::{AuthFlow, AuthType, UiaaInfo},
},
};
@ -109,7 +109,7 @@ pub async fn delete_device_route(
// UIAA
let mut uiaainfo = UiaaInfo {
flows: vec![AuthFlow {
stages: vec!["m.login.password".to_owned()],
stages: vec![AuthType::Password],
}],
completed: Vec::new(),
params: Default::default(),
@ -172,7 +172,7 @@ pub async fn delete_devices_route(
// UIAA
let mut uiaainfo = UiaaInfo {
flows: vec![AuthFlow {
stages: vec!["m.login.password".to_owned()],
stages: vec![AuthType::Password],
}],
completed: Vec::new(),
params: Default::default(),

View file

@ -17,10 +17,16 @@ use ruma::{
},
directory::{Filter, IncomingFilter, IncomingRoomNetwork, PublicRoomsChunk, RoomNetwork},
events::{
room::{avatar, canonical_alias, guest_access, history_visibility, name, topic},
room::{
avatar::RoomAvatarEventContent,
canonical_alias::RoomCanonicalAliasEventContent,
guest_access::{GuestAccess, RoomGuestAccessEventContent},
history_visibility::{HistoryVisibility, RoomHistoryVisibilityEventContent},
name::RoomNameEventContent,
topic::RoomTopicEventContent,
},
EventType,
},
serde::Raw,
ServerName, UInt,
};
use tracing::{info, warn};
@ -217,157 +223,143 @@ pub(crate) async fn get_public_rooms_filtered_helper(
}
}
let mut all_rooms =
db.rooms
.public_rooms()
.map(|room_id| {
let room_id = room_id?;
let mut all_rooms = db
.rooms
.public_rooms()
.map(|room_id| {
let room_id = room_id?;
let chunk = PublicRoomsChunk {
aliases: Vec::new(),
canonical_alias: db
.rooms
.room_state_get(&room_id, &EventType::RoomCanonicalAlias, "")?
.map_or(Ok::<_, Error>(None), |s| {
Ok(serde_json::from_value::<
Raw<canonical_alias::CanonicalAliasEventContent>,
>(s.content.clone())
.expect("from_value::<Raw<..>> can never fail")
.deserialize()
.map_err(|_| {
Error::bad_database("Invalid canonical alias event in database.")
})?
.alias)
})?,
name: db
.rooms
.room_state_get(&room_id, &EventType::RoomName, "")?
.map_or(Ok::<_, Error>(None), |s| {
Ok(serde_json::from_value::<Raw<name::NameEventContent>>(
s.content.clone(),
)
.expect("from_value::<Raw<..>> can never fail")
.deserialize()
.map_err(|_| {
Error::bad_database("Invalid room name event in database.")
})?
.name)
})?,
num_joined_members: db
.rooms
.room_joined_count(&room_id)?
.unwrap_or_else(|| {
warn!("Room {} has no member count", room_id);
0
})
.try_into()
.expect("user count should not be that big"),
topic: db
.rooms
.room_state_get(&room_id, &EventType::RoomTopic, "")?
.map_or(Ok::<_, Error>(None), |s| {
Ok(Some(
serde_json::from_value::<Raw<topic::TopicEventContent>>(
s.content.clone(),
)
.expect("from_value::<Raw<..>> can never fail")
.deserialize()
let chunk = PublicRoomsChunk {
aliases: Vec::new(),
canonical_alias: db
.rooms
.room_state_get(&room_id, &EventType::RoomCanonicalAlias, "")?
.map_or(Ok::<_, Error>(None), |s| {
Ok(
serde_json::from_str::<RoomCanonicalAliasEventContent>(s.content.get())
.map_err(|_| {
Error::bad_database(
"Invalid canonical alias event in database.",
)
})?
.alias,
)
})?,
name: db
.rooms
.room_state_get(&room_id, &EventType::RoomName, "")?
.map_or(Ok::<_, Error>(None), |s| {
Ok(
serde_json::from_str::<RoomNameEventContent>(s.content.get())
.map_err(|_| {
Error::bad_database("Invalid room name event in database.")
})?
.name,
)
})?,
num_joined_members: db
.rooms
.room_joined_count(&room_id)?
.unwrap_or_else(|| {
warn!("Room {} has no member count", room_id);
0
})
.try_into()
.expect("user count should not be that big"),
topic: db
.rooms
.room_state_get(&room_id, &EventType::RoomTopic, "")?
.map_or(Ok::<_, Error>(None), |s| {
Ok(Some(
serde_json::from_str::<RoomTopicEventContent>(s.content.get())
.map_err(|_| {
Error::bad_database("Invalid room topic event in database.")
})?
.topic,
))
})?,
world_readable: db
.rooms
.room_state_get(&room_id, &EventType::RoomHistoryVisibility, "")?
.map_or(Ok::<_, Error>(false), |s| {
Ok(serde_json::from_value::<
Raw<history_visibility::HistoryVisibilityEventContent>,
>(s.content.clone())
.expect("from_value::<Raw<..>> can never fail")
.deserialize()
.map_err(|_| {
Error::bad_database(
"Invalid room history visibility event in database.",
)
})?
.history_visibility
== history_visibility::HistoryVisibility::WorldReadable)
})?,
guest_can_join: db
.rooms
.room_state_get(&room_id, &EventType::RoomGuestAccess, "")?
.map_or(Ok::<_, Error>(false), |s| {
Ok(
serde_json::from_value::<Raw<guest_access::GuestAccessEventContent>>(
s.content.clone(),
)
.expect("from_value::<Raw<..>> can never fail")
.deserialize()
.map_err(|_| {
Error::bad_database("Invalid room guest access event in database.")
})?
.guest_access
== guest_access::GuestAccess::CanJoin,
))
})?,
world_readable: db
.rooms
.room_state_get(&room_id, &EventType::RoomHistoryVisibility, "")?
.map_or(Ok::<_, Error>(false), |s| {
Ok(serde_json::from_str::<RoomHistoryVisibilityEventContent>(
s.content.get(),
)
})?,
avatar_url: db
.rooms
.room_state_get(&room_id, &EventType::RoomAvatar, "")?
.map(|s| {
Ok::<_, Error>(
serde_json::from_value::<Raw<avatar::AvatarEventContent>>(
s.content.clone(),
)
.expect("from_value::<Raw<..>> can never fail")
.deserialize()
.map_err(|_| {
Error::bad_database(
"Invalid room history visibility event in database.",
)
})?
.history_visibility
== HistoryVisibility::WorldReadable)
})?,
guest_can_join: db
.rooms
.room_state_get(&room_id, &EventType::RoomGuestAccess, "")?
.map_or(Ok::<_, Error>(false), |s| {
Ok(
serde_json::from_str::<RoomGuestAccessEventContent>(s.content.get())
.map_err(|_| {
Error::bad_database(
"Invalid room guest access event in database.",
)
})?
.guest_access
== GuestAccess::CanJoin,
)
})?,
avatar_url: db
.rooms
.room_state_get(&room_id, &EventType::RoomAvatar, "")?
.map(|s| {
Ok::<_, Error>(
serde_json::from_str::<RoomAvatarEventContent>(s.content.get())
.map_err(|_| {
Error::bad_database("Invalid room avatar event in database.")
})?
.url,
)
})
.transpose()?
// url is now an Option<String> so we must flatten
.flatten(),
room_id,
};
Ok(chunk)
})
.filter_map(|r: Result<_>| r.ok()) // Filter out buggy rooms
.filter(|chunk| {
if let Some(query) = filter
.generic_search_term
.as_ref()
.map(|q| q.to_lowercase())
{
if let Some(name) = &chunk.name {
if name.as_str().to_lowercase().contains(&query) {
return true;
}
)
})
.transpose()?
// url is now an Option<String> so we must flatten
.flatten(),
room_id,
};
Ok(chunk)
})
.filter_map(|r: Result<_>| r.ok()) // Filter out buggy rooms
.filter(|chunk| {
if let Some(query) = filter
.generic_search_term
.as_ref()
.map(|q| q.to_lowercase())
{
if let Some(name) = &chunk.name {
if name.as_str().to_lowercase().contains(&query) {
return true;
}
if let Some(topic) = &chunk.topic {
if topic.to_lowercase().contains(&query) {
return true;
}
}
if let Some(canonical_alias) = &chunk.canonical_alias {
if canonical_alias.as_str().to_lowercase().contains(&query) {
return true;
}
}
false
} else {
// No search term
true
}
})
// We need to collect all, so we can sort by member count
.collect::<Vec<_>>();
if let Some(topic) = &chunk.topic {
if topic.to_lowercase().contains(&query) {
return true;
}
}
if let Some(canonical_alias) = &chunk.canonical_alias {
if canonical_alias.as_str().to_lowercase().contains(&query) {
return true;
}
}
false
} else {
// No search term
true
}
})
// We need to collect all, so we can sort by member count
.collect::<Vec<_>>();
all_rooms.sort_by(|l, r| r.num_joined_members.cmp(&l.num_joined_members));

View file

@ -10,7 +10,7 @@ use ruma::{
claim_keys, get_key_changes, get_keys, upload_keys, upload_signatures,
upload_signing_keys,
},
uiaa::{AuthFlow, UiaaInfo},
uiaa::{AuthFlow, AuthType, UiaaInfo},
},
},
federation,
@ -148,7 +148,7 @@ pub async fn upload_signing_keys_route(
// UIAA
let mut uiaainfo = UiaaInfo {
flows: vec![AuthFlow {
stages: vec!["m.login.password".to_owned()],
stages: vec![AuthType::Password],
}],
completed: Vec::new(),
params: Default::default(),

View file

@ -1,10 +1,9 @@
use crate::{
client_server,
database::DatabaseGuard,
pdu::{PduBuilder, PduEvent},
pdu::{EventHash, PduBuilder, PduEvent},
server_server, utils, ConduitResult, Database, Error, Result, Ruma,
};
use member::{MemberEventContent, MembershipState};
use ruma::{
api::{
client::{
@ -18,14 +17,17 @@ use ruma::{
federation::{self, membership::create_invite},
},
events::{
pdu::Pdu,
room::{create::CreateEventContent, member},
room::{
create::RoomCreateEventContent,
member::{MembershipState, RoomMemberEventContent},
},
EventType,
},
serde::{to_canonical_value, CanonicalJsonObject, CanonicalJsonValue, Raw},
serde::{to_canonical_value, CanonicalJsonObject, CanonicalJsonValue},
state_res::{self, RoomVersion},
uint, EventId, RoomId, RoomVersionId, ServerName, UserId,
};
use serde_json::value::{to_raw_value, RawValue as RawJsonValue};
use std::{
collections::{hash_map::Entry, BTreeMap, HashMap, HashSet},
convert::{TryFrom, TryInto},
@ -204,7 +206,7 @@ pub async fn kick_user_route(
) -> ConduitResult<kick_user::Response> {
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
let mut event = serde_json::from_value::<Raw<ruma::events::room::member::MemberEventContent>>(
let mut event: RoomMemberEventContent = serde_json::from_str(
db.rooms
.room_state_get(
&body.room_id,
@ -216,13 +218,11 @@ pub async fn kick_user_route(
"Cannot kick member that's not in the room.",
))?
.content
.clone(),
.get(),
)
.expect("Raw::from_value always works")
.deserialize()
.map_err(|_| Error::bad_database("Invalid member event in database."))?;
event.membership = ruma::events::room::member::MembershipState::Leave;
event.membership = MembershipState::Leave;
// TODO: reason
let mutex_state = Arc::clone(
@ -238,7 +238,7 @@ pub async fn kick_user_route(
db.rooms.build_and_append_pdu(
PduBuilder {
event_type: EventType::RoomMember,
content: serde_json::to_value(event).expect("event is valid, we just created it"),
content: to_raw_value(&event).expect("event is valid, we just created it"),
unsigned: None,
state_key: Some(body.user_id.to_string()),
redacts: None,
@ -280,8 +280,8 @@ pub async fn ban_user_route(
&body.user_id.to_string(),
)?
.map_or(
Ok::<_, Error>(member::MemberEventContent {
membership: member::MembershipState::Ban,
Ok::<_, Error>(RoomMemberEventContent {
membership: MembershipState::Ban,
displayname: db.users.displayname(&body.user_id)?,
avatar_url: db.users.avatar_url(&body.user_id)?,
is_direct: None,
@ -290,13 +290,9 @@ pub async fn ban_user_route(
reason: None,
}),
|event| {
let mut event = serde_json::from_value::<Raw<member::MemberEventContent>>(
event.content.clone(),
)
.expect("Raw::from_value always works")
.deserialize()
.map_err(|_| Error::bad_database("Invalid member event in database."))?;
event.membership = ruma::events::room::member::MembershipState::Ban;
let mut event = serde_json::from_str::<RoomMemberEventContent>(event.content.get())
.map_err(|_| Error::bad_database("Invalid member event in database."))?;
event.membership = MembershipState::Ban;
Ok(event)
},
)?;
@ -314,7 +310,7 @@ pub async fn ban_user_route(
db.rooms.build_and_append_pdu(
PduBuilder {
event_type: EventType::RoomMember,
content: serde_json::to_value(event).expect("event is valid, we just created it"),
content: to_raw_value(&event).expect("event is valid, we just created it"),
unsigned: None,
state_key: Some(body.user_id.to_string()),
redacts: None,
@ -346,7 +342,7 @@ pub async fn unban_user_route(
) -> ConduitResult<unban_user::Response> {
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
let mut event = serde_json::from_value::<Raw<ruma::events::room::member::MemberEventContent>>(
let mut event = serde_json::from_str::<RoomMemberEventContent>(
db.rooms
.room_state_get(
&body.room_id,
@ -358,13 +354,11 @@ pub async fn unban_user_route(
"Cannot unban a user who is not banned.",
))?
.content
.clone(),
.get(),
)
.expect("from_value::<Raw<..>> can never fail")
.deserialize()
.map_err(|_| Error::bad_database("Invalid member event in database."))?;
event.membership = ruma::events::room::member::MembershipState::Leave;
event.membership = MembershipState::Leave;
let mutex_state = Arc::clone(
db.globals
@ -379,7 +373,7 @@ pub async fn unban_user_route(
db.rooms.build_and_append_pdu(
PduBuilder {
event_type: EventType::RoomMember,
content: serde_json::to_value(event).expect("event is valid, we just created it"),
content: to_raw_value(&event).expect("event is valid, we just created it"),
unsigned: None,
state_key: Some(body.user_id.to_string()),
redacts: None,
@ -584,10 +578,9 @@ async fn join_room_by_id_helper(
};
let mut join_event_stub =
serde_json::from_str::<CanonicalJsonObject>(make_join_response.event.json().get())
.map_err(|_| {
Error::BadServerResponse("Invalid make_join event json received from server.")
})?;
serde_json::from_str::<CanonicalJsonObject>(make_join_response.event.get()).map_err(
|_| Error::BadServerResponse("Invalid make_join event json received from server."),
)?;
// TODO: Is origin needed?
join_event_stub.insert(
@ -604,8 +597,8 @@ async fn join_room_by_id_helper(
);
join_event_stub.insert(
"content".to_owned(),
to_canonical_value(member::MemberEventContent {
membership: member::MembershipState::Join,
to_canonical_value(RoomMemberEventContent {
membership: MembershipState::Join,
displayname: db.users.displayname(sender_user)?,
avatar_url: db.users.avatar_url(sender_user)?,
is_direct: None,
@ -653,7 +646,7 @@ async fn join_room_by_id_helper(
federation::membership::create_join_event::v2::Request {
room_id,
event_id: &event_id,
pdu: PduEvent::convert_to_outgoing_federation_event(join_event.clone()),
pdu: &PduEvent::convert_to_outgoing_federation_event(join_event.clone()),
},
)
.await?;
@ -756,8 +749,8 @@ async fn join_room_by_id_helper(
// where events in the current room state do not exist
db.rooms.set_room_state(room_id, statehashid)?;
} else {
let event = member::MemberEventContent {
membership: member::MembershipState::Join,
let event = RoomMemberEventContent {
membership: MembershipState::Join,
displayname: db.users.displayname(sender_user)?,
avatar_url: db.users.avatar_url(sender_user)?,
is_direct: None,
@ -769,7 +762,7 @@ async fn join_room_by_id_helper(
db.rooms.build_and_append_pdu(
PduBuilder {
event_type: EventType::RoomMember,
content: serde_json::to_value(event).expect("event is valid, we just created it"),
content: to_raw_value(&event).expect("event is valid, we just created it"),
unsigned: None,
state_key: Some(sender_user.to_string()),
redacts: None,
@ -789,12 +782,12 @@ async fn join_room_by_id_helper(
}
fn validate_and_add_event_id(
pdu: &Raw<Pdu>,
pdu: &RawJsonValue,
room_version: &RoomVersionId,
pub_key_map: &RwLock<BTreeMap<String, BTreeMap<String, String>>>,
db: &Database,
) -> Result<(EventId, CanonicalJsonObject)> {
let mut value = serde_json::from_str::<CanonicalJsonObject>(pdu.json().get()).map_err(|e| {
let mut value = serde_json::from_str::<CanonicalJsonObject>(pdu.get()).map_err(|e| {
error!("Invalid PDU in server response: {:?}: {:?}", pdu, e);
Error::BadServerResponse("Invalid PDU in server response")
})?;
@ -884,9 +877,7 @@ pub(crate) async fn invite_helper<'a>(
let create_event_content = create_event
.as_ref()
.map(|create_event| {
serde_json::from_value::<Raw<CreateEventContent>>(create_event.content.clone())
.expect("Raw::from_value always works.")
.deserialize()
serde_json::from_str::<RoomCreateEventContent>(create_event.content.get())
.map_err(|e| {
warn!("Invalid create event: {}", e);
Error::bad_database("Invalid create event in db.")
@ -910,7 +901,7 @@ pub(crate) async fn invite_helper<'a>(
let room_version =
RoomVersion::new(&room_version_id).expect("room version is supported");
let content = serde_json::to_value(MemberEventContent {
let content = to_raw_value(&RoomMemberEventContent {
avatar_url: None,
displayname: None,
is_direct: Some(is_direct),
@ -946,7 +937,7 @@ pub(crate) async fn invite_helper<'a>(
unsigned.insert("prev_content".to_owned(), prev_pdu.content.clone());
unsigned.insert(
"prev_sender".to_owned(),
serde_json::to_value(&prev_pdu.sender).expect("UserId::to_value always works"),
serde_json::from_str(prev_pdu.sender.as_str()).expect("UserId is valid string"),
);
}
@ -967,11 +958,15 @@ pub(crate) async fn invite_helper<'a>(
.map(|(_, pdu)| pdu.event_id.clone())
.collect(),
redacts: None,
unsigned,
hashes: ruma::events::pdu::EventHash {
unsigned: if unsigned.is_empty() {
None
} else {
Some(to_raw_value(&unsigned).expect("to_raw_value always works"))
},
hashes: EventHash {
sha256: "aaa".to_owned(),
},
signatures: BTreeMap::new(),
signatures: None,
};
let auth_check = state_res::auth_check(
@ -1035,11 +1030,11 @@ pub(crate) async fn invite_helper<'a>(
&db.globals,
user_id.server_name(),
create_invite::v2::Request {
room_id: room_id.clone(),
event_id: expected_event_id.clone(),
room_version: room_version_id,
event: PduEvent::convert_to_outgoing_federation_event(pdu_json.clone()),
invite_room_state,
room_id,
event_id: &expected_event_id,
room_version: &room_version_id,
event: &PduEvent::convert_to_outgoing_federation_event(pdu_json.clone()),
invite_room_state: &invite_room_state,
},
)
.await?;
@ -1116,8 +1111,8 @@ pub(crate) async fn invite_helper<'a>(
db.rooms.build_and_append_pdu(
PduBuilder {
event_type: EventType::RoomMember,
content: serde_json::to_value(member::MemberEventContent {
membership: member::MembershipState::Invite,
content: to_raw_value(&RoomMemberEventContent {
membership: MembershipState::Invite,
displayname: db.users.displayname(user_id)?,
avatar_url: db.users.avatar_url(user_id)?,
is_direct: Some(is_direct),

View file

@ -9,9 +9,9 @@ use ruma::{
},
federation::{self, query::get_profile_information::v1::ProfileField},
},
events::EventType,
serde::Raw,
events::{room::member::RoomMemberEventContent, EventType},
};
use serde_json::value::to_raw_value;
use std::{convert::TryInto, sync::Arc};
#[cfg(feature = "conduit_bin")]
@ -45,9 +45,9 @@ pub async fn set_displayname_route(
Ok::<_, Error>((
PduBuilder {
event_type: EventType::RoomMember,
content: serde_json::to_value(ruma::events::room::member::MemberEventContent {
content: to_raw_value(&RoomMemberEventContent {
displayname: body.displayname.clone(),
..serde_json::from_value::<Raw<_>>(
..serde_json::from_str(
db.rooms
.room_state_get(
&room_id,
@ -61,10 +61,8 @@ pub async fn set_displayname_route(
)
})?
.content
.clone(),
.get(),
)
.expect("from_value::<Raw<..>> can never fail")
.deserialize()
.map_err(|_| Error::bad_database("Database contains invalid PDU."))?
})
.expect("event is valid, we just created it"),
@ -190,9 +188,9 @@ pub async fn set_avatar_url_route(
Ok::<_, Error>((
PduBuilder {
event_type: EventType::RoomMember,
content: serde_json::to_value(ruma::events::room::member::MemberEventContent {
content: to_raw_value(&RoomMemberEventContent {
avatar_url: body.avatar_url.clone(),
..serde_json::from_value::<Raw<_>>(
..serde_json::from_str(
db.rooms
.room_state_get(
&room_id,
@ -206,10 +204,8 @@ pub async fn set_avatar_url_route(
)
})?
.content
.clone(),
.get(),
)
.expect("from_value::<Raw<..>> can never fail")
.deserialize()
.map_err(|_| Error::bad_database("Database contains invalid PDU."))?
})
.expect("event is valid, we just created it"),

View file

@ -3,11 +3,12 @@ use std::sync::Arc;
use crate::{database::DatabaseGuard, pdu::PduBuilder, ConduitResult, Ruma};
use ruma::{
api::client::r0::redact::redact_event,
events::{room::redaction, EventType},
events::{room::redaction::RoomRedactionEventContent, EventType},
};
#[cfg(feature = "conduit_bin")]
use rocket::put;
use serde_json::value::to_raw_value;
/// # `PUT /_matrix/client/r0/rooms/{roomId}/redact/{eventId}/{txnId}`
///
@ -38,7 +39,7 @@ pub async fn redact_event_route(
let event_id = db.rooms.build_and_append_pdu(
PduBuilder {
event_type: EventType::RoomRedaction,
content: serde_json::to_value(redaction::RedactionEventContent {
content: to_raw_value(&RoomRedactionEventContent {
reason: body.reason.clone(),
})
.expect("event is valid, we just created it"),

View file

@ -8,12 +8,23 @@ use ruma::{
r0::room::{self, aliases, create_room, get_room_event, upgrade_room},
},
events::{
room::{guest_access, history_visibility, join_rules, member, name, topic},
room::{
canonical_alias::RoomCanonicalAliasEventContent,
create::RoomCreateEventContent,
guest_access::{GuestAccess, RoomGuestAccessEventContent},
history_visibility::{HistoryVisibility, RoomHistoryVisibilityEventContent},
join_rules::{JoinRule, RoomJoinRulesEventContent},
member::{MembershipState, RoomMemberEventContent},
name::RoomNameEventContent,
power_levels::RoomPowerLevelsEventContent,
tombstone::RoomTombstoneEventContent,
topic::RoomTopicEventContent,
},
EventType,
},
serde::Raw,
RoomAliasId, RoomId, RoomVersionId,
};
use serde_json::value::to_raw_value;
use std::{cmp::max, collections::BTreeMap, convert::TryFrom, sync::Arc};
use tracing::{info, warn};
@ -80,7 +91,7 @@ pub async fn create_room_route(
}
})?;
let mut content = ruma::events::room::create::CreateEventContent::new(sender_user.clone());
let mut content = RoomCreateEventContent::new(sender_user.clone());
content.federate = body.creation_content.federate;
content.predecessor = body.creation_content.predecessor.clone();
content.room_version = match body.room_version.clone() {
@ -101,7 +112,7 @@ pub async fn create_room_route(
db.rooms.build_and_append_pdu(
PduBuilder {
event_type: EventType::RoomCreate,
content: serde_json::to_value(content).expect("event is valid, we just created it"),
content: to_raw_value(&content).expect("event is valid, we just created it"),
unsigned: None,
state_key: Some("".to_owned()),
redacts: None,
@ -116,8 +127,8 @@ pub async fn create_room_route(
db.rooms.build_and_append_pdu(
PduBuilder {
event_type: EventType::RoomMember,
content: serde_json::to_value(member::MemberEventContent {
membership: member::MembershipState::Join,
content: to_raw_value(&RoomMemberEventContent {
membership: MembershipState::Join,
displayname: db.users.displayname(sender_user)?,
avatar_url: db.users.avatar_url(sender_user)?,
is_direct: Some(body.is_direct),
@ -157,12 +168,11 @@ pub async fn create_room_route(
}
}
let mut power_levels_content =
serde_json::to_value(ruma::events::room::power_levels::PowerLevelsEventContent {
users,
..Default::default()
})
.expect("event is valid, we just created it");
let mut power_levels_content = serde_json::to_value(RoomPowerLevelsEventContent {
users,
..Default::default()
})
.expect("event is valid, we just created it");
if let Some(power_level_content_override) = &body.power_level_content_override {
let json = serde_json::from_str::<serde_json::Map<String, serde_json::Value>>(
@ -180,7 +190,8 @@ pub async fn create_room_route(
db.rooms.build_and_append_pdu(
PduBuilder {
event_type: EventType::RoomPowerLevels,
content: power_levels_content,
content: to_raw_value(&power_levels_content)
.expect("to_raw_value always works on serde_json::Value"),
unsigned: None,
state_key: Some("".to_owned()),
redacts: None,
@ -196,12 +207,10 @@ pub async fn create_room_route(
db.rooms.build_and_append_pdu(
PduBuilder {
event_type: EventType::RoomCanonicalAlias,
content: serde_json::to_value(
ruma::events::room::canonical_alias::CanonicalAliasEventContent {
alias: Some(room_alias_id.clone()),
alt_aliases: vec![],
},
)
content: to_raw_value(&RoomCanonicalAliasEventContent {
alias: Some(room_alias_id.clone()),
alt_aliases: vec![],
})
.expect("We checked that alias earlier, it must be fine"),
unsigned: None,
state_key: Some("".to_owned()),
@ -220,17 +229,12 @@ pub async fn create_room_route(
db.rooms.build_and_append_pdu(
PduBuilder {
event_type: EventType::RoomJoinRules,
content: match preset {
create_room::RoomPreset::PublicChat => serde_json::to_value(
join_rules::JoinRulesEventContent::new(join_rules::JoinRule::Public),
)
.expect("event is valid, we just created it"),
content: to_raw_value(&RoomJoinRulesEventContent::new(match preset {
create_room::RoomPreset::PublicChat => JoinRule::Public,
// according to spec "invite" is the default
_ => serde_json::to_value(join_rules::JoinRulesEventContent::new(
join_rules::JoinRule::Invite,
))
.expect("event is valid, we just created it"),
},
_ => JoinRule::Invite,
}))
.expect("event is valid, we just created it"),
unsigned: None,
state_key: Some("".to_owned()),
redacts: None,
@ -245,8 +249,8 @@ pub async fn create_room_route(
db.rooms.build_and_append_pdu(
PduBuilder {
event_type: EventType::RoomHistoryVisibility,
content: serde_json::to_value(history_visibility::HistoryVisibilityEventContent::new(
history_visibility::HistoryVisibility::Shared,
content: to_raw_value(&RoomHistoryVisibilityEventContent::new(
HistoryVisibility::Shared,
))
.expect("event is valid, we just created it"),
unsigned: None,
@ -263,18 +267,11 @@ pub async fn create_room_route(
db.rooms.build_and_append_pdu(
PduBuilder {
event_type: EventType::RoomGuestAccess,
content: match preset {
create_room::RoomPreset::PublicChat => {
serde_json::to_value(guest_access::GuestAccessEventContent::new(
guest_access::GuestAccess::Forbidden,
))
.expect("event is valid, we just created it")
}
_ => serde_json::to_value(guest_access::GuestAccessEventContent::new(
guest_access::GuestAccess::CanJoin,
))
.expect("event is valid, we just created it"),
},
content: to_raw_value(&RoomGuestAccessEventContent::new(match preset {
create_room::RoomPreset::PublicChat => GuestAccess::Forbidden,
_ => GuestAccess::CanJoin,
}))
.expect("event is valid, we just created it"),
unsigned: None,
state_key: Some("".to_owned()),
redacts: None,
@ -306,7 +303,7 @@ pub async fn create_room_route(
db.rooms.build_and_append_pdu(
PduBuilder {
event_type: EventType::RoomName,
content: serde_json::to_value(name::NameEventContent::new(Some(name.clone())))
content: to_raw_value(&RoomNameEventContent::new(Some(name.clone())))
.expect("event is valid, we just created it"),
unsigned: None,
state_key: Some("".to_owned()),
@ -323,7 +320,7 @@ pub async fn create_room_route(
db.rooms.build_and_append_pdu(
PduBuilder {
event_type: EventType::RoomTopic,
content: serde_json::to_value(topic::TopicEventContent {
content: to_raw_value(&RoomTopicEventContent {
topic: topic.clone(),
})
.expect("event is valid, we just created it"),
@ -477,7 +474,7 @@ pub async fn upgrade_room_route(
let tombstone_event_id = db.rooms.build_and_append_pdu(
PduBuilder {
event_type: EventType::RoomTombstone,
content: serde_json::to_value(ruma::events::room::tombstone::TombstoneEventContent {
content: to_raw_value(&RoomTombstoneEventContent {
body: "This room has been replaced".to_string(),
replacement_room: replacement_room.clone(),
})
@ -505,15 +502,13 @@ pub async fn upgrade_room_route(
let state_lock = mutex_state.lock().await;
// Get the old room federations status
let federate = serde_json::from_value::<Raw<ruma::events::room::create::CreateEventContent>>(
let federate = serde_json::from_str::<RoomCreateEventContent>(
db.rooms
.room_state_get(&body.room_id, &EventType::RoomCreate, "")?
.ok_or_else(|| Error::bad_database("Found room without m.room.create event."))?
.content
.clone(),
.get(),
)
.expect("Raw::from_value always works")
.deserialize()
.map_err(|_| Error::bad_database("Invalid room event in database."))?
.federate;
@ -524,8 +519,7 @@ pub async fn upgrade_room_route(
));
// Send a m.room.create event containing a predecessor field and the applicable room_version
let mut create_event_content =
ruma::events::room::create::CreateEventContent::new(sender_user.clone());
let mut create_event_content = RoomCreateEventContent::new(sender_user.clone());
create_event_content.federate = federate;
create_event_content.room_version = body.new_version.clone();
create_event_content.predecessor = predecessor;
@ -533,7 +527,7 @@ pub async fn upgrade_room_route(
db.rooms.build_and_append_pdu(
PduBuilder {
event_type: EventType::RoomCreate,
content: serde_json::to_value(create_event_content)
content: to_raw_value(&create_event_content)
.expect("event is valid, we just created it"),
unsigned: None,
state_key: Some("".to_owned()),
@ -549,8 +543,8 @@ pub async fn upgrade_room_route(
db.rooms.build_and_append_pdu(
PduBuilder {
event_type: EventType::RoomMember,
content: serde_json::to_value(member::MemberEventContent {
membership: member::MembershipState::Join,
content: to_raw_value(&RoomMemberEventContent {
membership: MembershipState::Join,
displayname: db.users.displayname(sender_user)?,
avatar_url: db.users.avatar_url(sender_user)?,
is_direct: None,
@ -611,17 +605,14 @@ pub async fn upgrade_room_route(
}
// Get the old room power levels
let mut power_levels_event_content =
serde_json::from_value::<Raw<ruma::events::room::power_levels::PowerLevelsEventContent>>(
db.rooms
.room_state_get(&body.room_id, &EventType::RoomPowerLevels, "")?
.ok_or_else(|| Error::bad_database("Found room without m.room.create event."))?
.content
.clone(),
)
.expect("database contains invalid PDU")
.deserialize()
.map_err(|_| Error::bad_database("Invalid room event in database."))?;
let mut power_levels_event_content = serde_json::from_str::<RoomPowerLevelsEventContent>(
db.rooms
.room_state_get(&body.room_id, &EventType::RoomPowerLevels, "")?
.ok_or_else(|| Error::bad_database("Found room without m.room.create event."))?
.content
.get(),
)
.map_err(|_| Error::bad_database("Invalid room event in database."))?;
// Setting events_default and invite to the greater of 50 and users_default + 1
let new_level = max(
@ -635,7 +626,7 @@ pub async fn upgrade_room_route(
let _ = db.rooms.build_and_append_pdu(
PduBuilder {
event_type: EventType::RoomPowerLevels,
content: serde_json::to_value(power_levels_event_content)
content: to_raw_value(&power_levels_event_content)
.expect("event is valid, we just created it"),
unsigned: None,
state_key: Some("".to_owned()),

View file

@ -60,10 +60,10 @@ pub async fn login_route(
// Validate login method
// TODO: Other login methods
let user_id = match &body.login_info {
login::IncomingLoginInfo::Password {
login::IncomingLoginInfo::Password(login::IncomingPassword {
identifier,
password,
} => {
}) => {
let username = if let IncomingUserIdentifier::MatrixId(matrix_id) = identifier {
matrix_id
} else {
@ -97,7 +97,7 @@ pub async fn login_route(
user_id
}
login::IncomingLoginInfo::Token { token } => {
login::IncomingLoginInfo::Token(login::IncomingToken { token }) => {
if let Some(jwt_decoding_key) = db.globals.jwt_decoding_key() {
let token = jsonwebtoken::decode::<Claims>(
token,
@ -116,6 +116,12 @@ pub async fn login_route(
));
}
}
_ => {
return Err(Error::BadRequest(
ErrorKind::Unknown,
"Unsupported login type.",
));
}
};
// Generate new device id if the user didn't specify one

View file

@ -10,8 +10,8 @@ use ruma::{
},
events::{
room::{
canonical_alias::CanonicalAliasEventContent,
history_visibility::{HistoryVisibility, HistoryVisibilityEventContent},
canonical_alias::RoomCanonicalAliasEventContent,
history_visibility::{HistoryVisibility, RoomHistoryVisibilityEventContent},
},
AnyStateEventContent, EventType,
},
@ -112,7 +112,7 @@ pub async fn get_state_events_route(
db.rooms
.room_state_get(&body.room_id, &EventType::RoomHistoryVisibility, "")?
.map(|event| {
serde_json::from_value::<HistoryVisibilityEventContent>(event.content.clone())
serde_json::from_str::<RoomHistoryVisibilityEventContent>(event.content.get())
.map_err(|_| {
Error::bad_database(
"Invalid room history visibility event in database.",
@ -164,7 +164,7 @@ pub async fn get_state_events_for_key_route(
db.rooms
.room_state_get(&body.room_id, &EventType::RoomHistoryVisibility, "")?
.map(|event| {
serde_json::from_value::<HistoryVisibilityEventContent>(event.content.clone())
serde_json::from_str::<RoomHistoryVisibilityEventContent>(event.content.get())
.map_err(|_| {
Error::bad_database(
"Invalid room history visibility event in database.",
@ -190,7 +190,7 @@ pub async fn get_state_events_for_key_route(
))?;
Ok(get_state_events_for_key::Response {
content: serde_json::from_value(event.content.clone())
content: serde_json::from_str(event.content.get())
.map_err(|_| Error::bad_database("Invalid event content in database"))?,
}
.into())
@ -220,7 +220,7 @@ pub async fn get_state_events_for_empty_key_route(
db.rooms
.room_state_get(&body.room_id, &EventType::RoomHistoryVisibility, "")?
.map(|event| {
serde_json::from_value::<HistoryVisibilityEventContent>(event.content.clone())
serde_json::from_str::<RoomHistoryVisibilityEventContent>(event.content.get())
.map_err(|_| {
Error::bad_database(
"Invalid room history visibility event in database.",
@ -246,7 +246,7 @@ pub async fn get_state_events_for_empty_key_route(
))?;
Ok(get_state_events_for_key::Response {
content: serde_json::from_value(event.content.clone())
content: serde_json::from_str(event.content.get())
.map_err(|_| Error::bad_database("Invalid event content in database"))?,
}
.into())
@ -265,7 +265,7 @@ async fn send_state_event_for_key_helper(
// TODO: Review this check, error if event is unparsable, use event type, allow alias if it
// previously existed
if let Ok(canonical_alias) =
serde_json::from_str::<CanonicalAliasEventContent>(json.json().get())
serde_json::from_str::<RoomCanonicalAliasEventContent>(json.json().get())
{
let mut aliases = canonical_alias.alt_aliases.clone();

View file

@ -1,7 +1,10 @@
use crate::{database::DatabaseGuard, ConduitResult, Database, Error, Result, Ruma, RumaResponse};
use ruma::{
api::client::r0::{sync::sync_events, uiaa::UiaaResponse},
events::{room::member::MembershipState, AnySyncEphemeralRoomEvent, EventType},
events::{
room::member::{MembershipState, RoomMemberEventContent},
AnySyncEphemeralRoomEvent, EventType,
},
serde::Raw,
DeviceId, RoomId, UserId,
};
@ -287,10 +290,11 @@ async fn sync_helper(
.filter_map(|pdu| pdu.ok()) // Ignore all broken pdus
.filter(|(_, pdu)| pdu.kind == EventType::RoomMember)
.map(|(_, pdu)| {
let content = serde_json::from_value::<
ruma::events::room::member::MemberEventContent,
>(pdu.content.clone())
.map_err(|_| Error::bad_database("Invalid member event in database."))?;
let content =
serde_json::from_str::<RoomMemberEventContent>(pdu.content.get())
.map_err(|_| {
Error::bad_database("Invalid member event in database.")
})?;
if let Some(state_key) = &pdu.state_key {
let user_id = UserId::try_from(state_key.clone()).map_err(|_| {
@ -371,13 +375,9 @@ async fn sync_helper(
sender_user.as_str(),
)?
.and_then(|pdu| {
serde_json::from_value::<Raw<ruma::events::room::member::MemberEventContent>>(
pdu.content.clone(),
)
.expect("Raw::from_value always works")
.deserialize()
.map_err(|_| Error::bad_database("Invalid PDU in database."))
.ok()
serde_json::from_str::<RoomMemberEventContent>(pdu.content.get())
.map_err(|_| Error::bad_database("Invalid PDU in database."))
.ok()
});
let joined_since_last_sync = since_sender_member
@ -432,11 +432,9 @@ async fn sync_helper(
continue;
}
let new_membership = serde_json::from_value::<
Raw<ruma::events::room::member::MemberEventContent>,
>(state_event.content.clone())
.expect("Raw::from_value always works")
.deserialize()
let new_membership = serde_json::from_str::<RoomMemberEventContent>(
state_event.content.get(),
)
.map_err(|_| Error::bad_database("Invalid PDU in database."))?
.membership;
@ -739,7 +737,7 @@ async fn sync_helper(
presence: sync_events::Presence {
events: presence_updates
.into_iter()
.map(|(_, v)| Raw::from(v))
.map(|(_, v)| Raw::new(&v).expect("PresenceEvent always serializes successfully"))
.collect(),
},
account_data: sync_events::GlobalAccountData {