Replace several expects with error coercions.

Signed-off-by: Jason Volk <jason@zemos.net>
This commit is contained in:
Jason Volk
2025-07-08 12:36:03 +00:00
parent 23d188f612
commit cca0f20148
5 changed files with 53 additions and 74 deletions

View File

@@ -487,43 +487,32 @@ fn default_power_levels_content(
visibility: &room::Visibility,
users: BTreeMap<OwnedUserId, Int>,
) -> Result<serde_json::Value> {
use serde_json::to_value;
let mut power_levels_content =
serde_json::to_value(RoomPowerLevelsEventContent { users, ..Default::default() })
.expect("event is valid, we just created it");
to_value(RoomPowerLevelsEventContent { users, ..Default::default() })?;
// secure proper defaults of sensitive/dangerous permissions that moderators
// (power level 50) should not have easy access to
power_levels_content["events"]["m.room.power_levels"] =
serde_json::to_value(100).expect("100 is valid Value");
power_levels_content["events"]["m.room.server_acl"] =
serde_json::to_value(100).expect("100 is valid Value");
power_levels_content["events"]["m.room.tombstone"] =
serde_json::to_value(100).expect("100 is valid Value");
power_levels_content["events"]["m.room.encryption"] =
serde_json::to_value(100).expect("100 is valid Value");
power_levels_content["events"]["m.room.history_visibility"] =
serde_json::to_value(100).expect("100 is valid Value");
power_levels_content["events"]["m.room.power_levels"] = to_value(100)?;
power_levels_content["events"]["m.room.server_acl"] = to_value(100)?;
power_levels_content["events"]["m.room.tombstone"] = to_value(100)?;
power_levels_content["events"]["m.room.encryption"] = to_value(100)?;
power_levels_content["events"]["m.room.history_visibility"] = to_value(100)?;
// always allow users to respond (not post new) to polls. this is primarily
// useful in read-only announcement rooms that post a public poll.
power_levels_content["events"]["org.matrix.msc3381.poll.response"] =
serde_json::to_value(0).expect("0 is valid Value");
power_levels_content["events"]["m.poll.response"] =
serde_json::to_value(0).expect("0 is valid Value");
power_levels_content["events"]["org.matrix.msc3381.poll.response"] = to_value(0)?;
power_levels_content["events"]["m.poll.response"] = to_value(0)?;
// synapse does this too. clients do not expose these permissions. it prevents
// default users from calling public rooms, for obvious reasons.
if *visibility == room::Visibility::Public {
power_levels_content["events"]["m.call.invite"] =
serde_json::to_value(50).expect("50 is valid Value");
power_levels_content["events"]["m.call"] =
serde_json::to_value(50).expect("50 is valid Value");
power_levels_content["events"]["m.call.member"] =
serde_json::to_value(50).expect("50 is valid Value");
power_levels_content["events"]["org.matrix.msc3401.call"] =
serde_json::to_value(50).expect("50 is valid Value");
power_levels_content["events"]["org.matrix.msc3401.call.member"] =
serde_json::to_value(50).expect("50 is valid Value");
power_levels_content["events"]["m.call.invite"] = to_value(50)?;
power_levels_content["events"]["m.call"] = to_value(50)?;
power_levels_content["events"]["m.call.member"] = to_value(50)?;
power_levels_content["events"]["org.matrix.msc3401.call"] = to_value(50)?;
power_levels_content["events"]["org.matrix.msc3401.call.member"] = to_value(50)?;
}
if let Some(power_level_content_override) = power_level_content_override {

View File

@@ -17,7 +17,7 @@ use ruma::{
};
use serde_json::{json, value::to_raw_value};
use tuwunel_core::{
Error, Result, err, info,
Err, Error, Result, err,
matrix::{Event, StateKey, pdu::PduBuilder},
};
@@ -54,10 +54,8 @@ pub(crate) async fn upgrade_room_route(
TRANSFERABLE_STATE_EVENTS.is_sorted(),
"TRANSFERABLE_STATE_EVENTS is not sorted"
);
let sender_user = body
.sender_user
.as_ref()
.expect("user is authenticated");
let sender_user = body.sender_user();
if !services
.server
@@ -134,8 +132,7 @@ pub(crate) async fn upgrade_room_route(
create_event_content.insert(
"creator".into(),
json!(&sender_user).try_into().map_err(|e| {
info!("Error forming creation event: {e}");
Error::BadRequest(ErrorKind::BadJson, "Error forming creation event")
err!(Request(BadJson(error!("Error forming creation event: {e}"))))
})?,
);
},
@@ -150,24 +147,20 @@ pub(crate) async fn upgrade_room_route(
"room_version".into(),
json!(&body.new_version)
.try_into()
.map_err(|_| Error::BadRequest(ErrorKind::BadJson, "Error forming creation event"))?,
.map_err(|_| err!(Request(BadJson("Error forming creation event"))))?,
);
create_event_content.insert(
"predecessor".into(),
json!(predecessor)
.try_into()
.map_err(|_| Error::BadRequest(ErrorKind::BadJson, "Error forming creation event"))?,
.map_err(|_| err!(Request(BadJson("Error forming creation event"))))?,
);
// Validate creation event content
if serde_json::from_str::<CanonicalJsonObject>(
to_raw_value(&create_event_content)
.expect("Error forming creation event")
.get(),
)
.is_err()
if serde_json::from_str::<CanonicalJsonObject>(to_raw_value(&create_event_content)?.get())
.is_err()
{
return Err(Error::BadRequest(ErrorKind::BadJson, "Error forming creation event"));
return Err!(Request(BadJson("Error forming creation event")));
}
services
@@ -176,8 +169,7 @@ pub(crate) async fn upgrade_room_route(
.build_and_append_pdu(
PduBuilder {
event_type: TimelineEventType::RoomCreate,
content: to_raw_value(&create_event_content)
.expect("event is valid, we just created it"),
content: to_raw_value(&create_event_content)?,
unsigned: None,
state_key: Some(StateKey::new()),
redacts: None,
@@ -205,8 +197,7 @@ pub(crate) async fn upgrade_room_route(
blurhash: services.users.blurhash(sender_user).await.ok(),
reason: None,
join_authorized_via_users_server: None,
})
.expect("event is valid, we just created it"),
})?,
unsigned: None,
state_key: Some(sender_user.as_str().into()),
redacts: None,

View File

@@ -447,12 +447,9 @@ async fn handle_left_room(
event_id: EventId::new(services.globals.server_name()),
sender: sender_user.to_owned(),
origin: None,
origin_server_ts: utils::millis_since_unix_epoch()
.try_into()
.expect("Timestamp is valid js_int value"),
origin_server_ts: utils::millis_since_unix_epoch().try_into()?,
kind: RoomMember,
content: serde_json::from_str(r#"{"membership":"leave"}"#)
.expect("this is valid JSON"),
content: serde_json::from_str(r#"{"membership":"leave"}"#)?,
state_key: Some(sender_user.as_str().into()),
unsigned: None,
// The following keys are dropped on conversion

View File

@@ -69,10 +69,8 @@ where
incoming_pdu
.insert("event_id".to_owned(), CanonicalJsonValue::String(event_id.as_str().to_owned()));
let pdu_event = serde_json::from_value::<PduEvent>(
serde_json::to_value(&incoming_pdu).expect("CanonicalJsonObj is a valid JsonValue"),
)
.map_err(|e| err!(Request(BadJson(debug_warn!("Event is not a valid PDU: {e}")))))?;
let pdu_event = serde_json::from_value::<PduEvent>(serde_json::to_value(&incoming_pdu)?)
.map_err(|e| err!(Request(BadJson(debug_warn!("Event is not a valid PDU: {e}")))))?;
check_room_id(room_id, &pdu_event)?;

View File

@@ -26,8 +26,8 @@ pub async fn create_hash_and_sign_event(
pdu_builder: PduBuilder,
sender: &UserId,
room_id: &RoomId,
_mutex_lock: &RoomMutexGuard, /* Take mutex guard to make sure users get the room
* state mutex */
// Take mutex guard to make sure users get the room state mutex
_mutex_lock: &RoomMutexGuard,
) -> Result<(PduEvent, CanonicalJsonObject)> {
let PduBuilder {
event_type,
@@ -100,36 +100,40 @@ pub async fn create_hash_and_sign_event(
}
}
let unsigned = if unsigned.is_empty() {
None
} else {
Some(to_raw_value(&unsigned)?)
};
let origin_server_ts = timestamp.map_or_else(
|| {
utils::millis_since_unix_epoch()
.try_into()
.expect("timestamp to UInt")
},
|ts| ts.get(),
);
let mut pdu = PduEvent {
event_id: ruma::event_id!("$thiswillbefilledinlater").into(),
room_id: room_id.to_owned(),
sender: sender.to_owned(),
origin: None,
origin_server_ts: timestamp.map_or_else(
|| {
utils::millis_since_unix_epoch()
.try_into()
.expect("u64 fits into UInt")
},
|ts| ts.get(),
),
origin_server_ts,
kind: event_type,
content,
state_key,
prev_events,
depth,
redacts,
unsigned,
hashes: EventHash { sha256: "aaa".to_owned() },
signatures: None,
prev_events,
auth_events: auth_events
.values()
.map(|pdu| pdu.event_id.clone())
.collect(),
redacts,
unsigned: if unsigned.is_empty() {
None
} else {
Some(to_raw_value(&unsigned)?)
},
hashes: EventHash { sha256: "aaa".to_owned() },
signatures: None,
};
let auth_fetch = |k: &StateEventType, s: &str| {