1
0
Fork 0
mirror of https://gitlab.com/famedly/conduit.git synced 2025-08-11 17:50:59 +00:00

refactor: use RoomVersionRules instead of matching against RoomVersionId

This commit is contained in:
Matthias Ahouansou 2025-07-02 19:39:03 +01:00
parent b631621f8c
commit a8fa237fad
No known key found for this signature in database
7 changed files with 135 additions and 219 deletions

View file

@ -23,7 +23,7 @@ use ruma::{
},
int,
serde::JsonObject,
CanonicalJsonObject, OwnedRoomAliasId, RoomAliasId, RoomId, RoomVersionId,
CanonicalJsonObject, OwnedRoomAliasId, RoomAliasId, RoomId,
};
use serde_json::{json, value::to_raw_value};
use std::{cmp::max, collections::BTreeMap, sync::Arc};
@ -137,6 +137,10 @@ pub async fn create_room_route(
}
None => services().globals.default_room_version(),
};
let rules = room_version
.rules()
.expect("Supported room version must have rules.")
.authorization;
let content = match &body.creation_content {
Some(content) => {
@ -144,26 +148,13 @@ pub async fn create_room_route(
.deserialize_as::<CanonicalJsonObject>()
.expect("Invalid creation content");
match room_version {
RoomVersionId::V1
| RoomVersionId::V2
| RoomVersionId::V3
| RoomVersionId::V4
| RoomVersionId::V5
| RoomVersionId::V6
| RoomVersionId::V7
| RoomVersionId::V8
| RoomVersionId::V9
| RoomVersionId::V10 => {
content.insert(
"creator".into(),
json!(&sender_user).try_into().map_err(|_| {
Error::BadRequest(ErrorKind::BadJson, "Invalid creation content")
})?,
);
}
RoomVersionId::V11 => {} // V11 removed the "creator" key
_ => unreachable!("Validity of room version already checked"),
if !rules.use_room_create_sender {
content.insert(
"creator".into(),
json!(&sender_user).try_into().map_err(|_| {
Error::BadRequest(ErrorKind::BadJson, "Invalid creation content")
})?,
);
}
content.insert(
@ -175,19 +166,10 @@ pub async fn create_room_route(
content
}
None => {
let content = match room_version {
RoomVersionId::V1
| RoomVersionId::V2
| RoomVersionId::V3
| RoomVersionId::V4
| RoomVersionId::V5
| RoomVersionId::V6
| RoomVersionId::V7
| RoomVersionId::V8
| RoomVersionId::V9
| RoomVersionId::V10 => RoomCreateEventContent::new_v1(sender_user.clone()),
RoomVersionId::V11 => RoomCreateEventContent::new_v11(),
_ => unreachable!("Validity of room version already checked"),
let content = if rules.use_room_create_sender {
RoomCreateEventContent::new_v11()
} else {
RoomCreateEventContent::new_v1(sender_user.clone())
};
let mut content = serde_json::from_str::<CanonicalJsonObject>(
to_raw_value(&content)
@ -602,6 +584,11 @@ pub async fn upgrade_room_route(
));
}
let rules = body
.new_version
.rules()
.expect("Supported room version must have rules.");
// Create a replacement room
let replacement_room = RoomId::new(services().globals.server_name());
services()
@ -676,30 +663,17 @@ pub async fn upgrade_room_route(
));
// Send a m.room.create event containing a predecessor field and the applicable room_version
match body.new_version {
RoomVersionId::V1
| RoomVersionId::V2
| RoomVersionId::V3
| RoomVersionId::V4
| RoomVersionId::V5
| RoomVersionId::V6
| RoomVersionId::V7
| RoomVersionId::V8
| RoomVersionId::V9
| RoomVersionId::V10 => {
create_event_content.insert(
"creator".into(),
json!(&sender_user).try_into().map_err(|_| {
Error::BadRequest(ErrorKind::BadJson, "Error forming creation event")
})?,
);
}
RoomVersionId::V11 => {
// "creator" key no longer exists in V11 rooms
create_event_content.remove("creator");
}
_ => unreachable!("Validity of room version already checked"),
if rules.authorization.use_room_create_sender {
create_event_content.remove("creator");
} else {
create_event_content.insert(
"creator".into(),
json!(&sender_user).try_into().map_err(|_| {
Error::BadRequest(ErrorKind::BadJson, "Error forming creation event")
})?,
);
}
create_event_content.insert(
"room_version".into(),
json!(&body.new_version)

View file

@ -2021,16 +2021,11 @@ fn user_can_perform_restricted_join(
return Ok(false);
};
if matches!(
room_version_id,
RoomVersionId::V1
| RoomVersionId::V2
| RoomVersionId::V3
| RoomVersionId::V4
| RoomVersionId::V5
| RoomVersionId::V6
| RoomVersionId::V7
) {
let rules = room_version_id
.rules()
.expect("Supported room version must have rules.")
.authorization;
if !rules.restricted_join_rule {
return Ok(false);
}

View file

@ -1693,19 +1693,14 @@ impl Service {
services().users.create(conduit_user, None)?;
let room_version = services().globals.default_room_version();
let mut content = match room_version {
RoomVersionId::V1
| RoomVersionId::V2
| RoomVersionId::V3
| RoomVersionId::V4
| RoomVersionId::V5
| RoomVersionId::V6
| RoomVersionId::V7
| RoomVersionId::V8
| RoomVersionId::V9
| RoomVersionId::V10 => RoomCreateEventContent::new_v1(conduit_user.to_owned()),
RoomVersionId::V11 => RoomCreateEventContent::new_v11(),
_ => unreachable!("Validity of room version already checked"),
let rules = room_version
.rules()
.expect("Supported room version must have rules.")
.authorization;
let mut content = if rules.use_room_create_sender {
RoomCreateEventContent::new_v11()
} else {
RoomCreateEventContent::new_v1(conduit_user.to_owned())
};
content.federate = true;
content.predecessor = None;

View file

@ -1,8 +1,8 @@
mod data;
pub use data::{Data, SigningKeys};
use ruma::{
serde::Base64, MilliSecondsSinceUnixEpoch, OwnedDeviceId, OwnedEventId, OwnedRoomAliasId,
OwnedRoomId, OwnedServerName, OwnedUserId, RoomAliasId,
room_version_rules::RoomVersionRules, serde::Base64, MilliSecondsSinceUnixEpoch, OwnedDeviceId,
OwnedEventId, OwnedRoomAliasId, OwnedRoomId, OwnedServerName, OwnedUserId, RoomAliasId,
};
use crate::api::server_server::DestinationResponse;
@ -427,11 +427,11 @@ impl Service {
&self,
keys: BTreeMap<String, SigningKeys>,
timestamp: MilliSecondsSinceUnixEpoch,
room_version_id: &RoomVersionId,
rules: &RoomVersionRules,
) -> BTreeMap<String, BTreeMap<String, Base64>> {
keys.into_iter()
.filter_map(|(server, keys)| {
self.filter_keys_single_server(keys, timestamp, room_version_id)
self.filter_keys_single_server(keys, timestamp, rules)
.map(|keys| (server, keys))
})
.collect()
@ -443,15 +443,12 @@ impl Service {
&self,
keys: SigningKeys,
timestamp: MilliSecondsSinceUnixEpoch,
room_version_id: &RoomVersionId,
rules: &RoomVersionRules,
) -> Option<BTreeMap<String, Base64>> {
if keys.valid_until_ts > timestamp
// valid_until_ts MUST be ignored in room versions 1, 2, 3, and 4.
// https://spec.matrix.org/v1.10/server-server-api/#get_matrixkeyv2server
|| matches!(room_version_id, RoomVersionId::V1
| RoomVersionId::V2
| RoomVersionId::V4
| RoomVersionId::V3)
|| !rules.enforce_key_validity
{
// Given that either the room version allows stale keys, or the valid_until_ts is
// in the future, all verify_keys are valid

View file

@ -34,7 +34,7 @@ use ruma::{
room_version_rules::{AuthorizationRules, RoomVersionRules},
state_res::{self, StateMap},
uint, CanonicalJsonObject, CanonicalJsonValue, EventId, MilliSecondsSinceUnixEpoch,
OwnedServerName, OwnedServerSigningKeyId, RoomId, RoomVersionId, ServerName,
OwnedServerName, OwnedServerSigningKeyId, RoomId, ServerName,
};
use serde_json::value::RawValue as RawJsonValue;
use tokio::sync::{RwLock, RwLockWriteGuard, Semaphore};
@ -373,7 +373,7 @@ impl Service {
let filtered_keys = services().globals.filter_keys_server_map(
pkey_map,
origin_server_ts,
room_version_id,
&room_version_rules,
);
let mut val =
@ -846,48 +846,31 @@ impl Service {
)
.is_err()
|| incoming_pdu.kind == TimelineEventType::RoomRedaction
&& match room_version_id {
RoomVersionId::V1
| RoomVersionId::V2
| RoomVersionId::V3
| RoomVersionId::V4
| RoomVersionId::V5
| RoomVersionId::V6
| RoomVersionId::V7
| RoomVersionId::V8
| RoomVersionId::V9
| RoomVersionId::V10 => {
if let Some(redact_id) = &incoming_pdu.redacts {
!services().rooms.state_accessor.user_can_redact(
redact_id,
&incoming_pdu.sender,
&incoming_pdu.room_id,
true,
)?
} else {
false
}
}
RoomVersionId::V11 => {
let content = serde_json::from_str::<RoomRedactionEventContent>(
incoming_pdu.content.get(),
)
.map_err(|_| Error::bad_database("Invalid content in redaction pdu."))?;
&& if room_version_rules.redaction.content_field_redacts {
let content = serde_json::from_str::<RoomRedactionEventContent>(
incoming_pdu.content.get(),
)
.map_err(|_| Error::bad_database("Invalid content in redaction pdu."))?;
if let Some(redact_id) = &content.redacts {
!services().rooms.state_accessor.user_can_redact(
redact_id,
&incoming_pdu.sender,
&incoming_pdu.room_id,
true,
)?
} else {
false
}
}
_ => {
unreachable!("Validity of room version already checked")
if let Some(redact_id) = &content.redacts {
!services().rooms.state_accessor.user_can_redact(
redact_id,
&incoming_pdu.sender,
&incoming_pdu.room_id,
true,
)?
} else {
false
}
} else if let Some(redact_id) = &incoming_pdu.redacts {
!services().rooms.state_accessor.user_can_redact(
redact_id,
&incoming_pdu.sender,
&incoming_pdu.room_id,
true,
)?
} else {
false
};
// 14. Use state resolution to find new room state

View file

@ -722,10 +722,9 @@ async fn validate_and_add_event_id(
let unfiltered_keys = (*pub_key_map.read().await).clone();
let keys =
services()
.globals
.filter_keys_server_map(unfiltered_keys, origin_server_ts, room_version);
let keys = services()
.globals
.filter_keys_server_map(unfiltered_keys, origin_server_ts, rules);
if let Err(e) = ruma::signatures::verify_event(&keys, &value, rules) {
warn!("Event {} failed verification {:?} {}", event_id, pdu, e);

View file

@ -23,7 +23,7 @@ use ruma::{
push::{Action, Ruleset, Tweak},
state_res::{self, Event},
uint, user_id, CanonicalJsonObject, CanonicalJsonValue, EventId, MilliSecondsSinceUnixEpoch,
OwnedEventId, OwnedRoomId, OwnedServerName, RoomId, RoomVersionId, ServerName, UserId,
OwnedEventId, OwnedRoomId, OwnedServerName, RoomId, ServerName, UserId,
};
use serde::Deserialize;
use serde_json::value::{to_raw_value, RawValue as RawJsonValue};
@ -383,46 +383,36 @@ impl Service {
match pdu.kind {
TimelineEventType::RoomRedaction => {
let room_version_id = services().rooms.state.get_room_version(&pdu.room_id)?;
match room_version_id {
RoomVersionId::V1
| RoomVersionId::V2
| RoomVersionId::V3
| RoomVersionId::V4
| RoomVersionId::V5
| RoomVersionId::V6
| RoomVersionId::V7
| RoomVersionId::V8
| RoomVersionId::V9
| RoomVersionId::V10 => {
if let Some(redact_id) = &pdu.redacts {
if services().rooms.state_accessor.user_can_redact(
redact_id,
&pdu.sender,
&pdu.room_id,
false,
)? {
self.redact_pdu(redact_id, pdu, shortroomid)?;
}
let rules = room_version_id
.rules()
.expect("Supported room version must have rules.")
.redaction;
if rules.content_field_redacts {
let content =
serde_json::from_str::<RoomRedactionEventContent>(pdu.content.get())
.map_err(|_| {
Error::bad_database("Invalid content in redaction pdu.")
})?;
if let Some(redact_id) = &content.redacts {
if services().rooms.state_accessor.user_can_redact(
redact_id,
&pdu.sender,
&pdu.room_id,
false,
)? {
self.redact_pdu(redact_id, pdu, shortroomid)?;
}
}
RoomVersionId::V11 => {
let content =
serde_json::from_str::<RoomRedactionEventContent>(pdu.content.get())
.map_err(|_| {
Error::bad_database("Invalid content in redaction pdu.")
})?;
if let Some(redact_id) = &content.redacts {
if services().rooms.state_accessor.user_can_redact(
redact_id,
&pdu.sender,
&pdu.room_id,
false,
)? {
self.redact_pdu(redact_id, pdu, shortroomid)?;
}
}
} else if let Some(redact_id) = &pdu.redacts {
if services().rooms.state_accessor.user_can_redact(
redact_id,
&pdu.sender,
&pdu.room_id,
false,
)? {
self.redact_pdu(redact_id, pdu, shortroomid)?;
}
_ => unreachable!("Validity of room version already checked"),
};
}
TimelineEventType::SpaceChild => {
@ -958,56 +948,39 @@ impl Service {
// If redaction event is not authorized, do not append it to the timeline
if pdu.kind == TimelineEventType::RoomRedaction {
match services().rooms.state.get_room_version(&pdu.room_id)? {
RoomVersionId::V1
| RoomVersionId::V2
| RoomVersionId::V3
| RoomVersionId::V4
| RoomVersionId::V5
| RoomVersionId::V6
| RoomVersionId::V7
| RoomVersionId::V8
| RoomVersionId::V9
| RoomVersionId::V10 => {
if let Some(redact_id) = &pdu.redacts {
if !services().rooms.state_accessor.user_can_redact(
redact_id,
&pdu.sender,
&pdu.room_id,
false,
)? {
return Err(Error::BadRequest(
ErrorKind::forbidden(),
"User cannot redact this event.",
));
}
};
}
RoomVersionId::V11 => {
let content =
serde_json::from_str::<RoomRedactionEventContent>(pdu.content.get())
.map_err(|_| {
Error::bad_database("Invalid content in redaction pdu.")
})?;
let room_version_id = services().rooms.state.get_room_version(&pdu.room_id)?;
let rules = room_version_id
.rules()
.expect("Supported room version must have rules.")
.redaction;
if let Some(redact_id) = &content.redacts {
if !services().rooms.state_accessor.user_can_redact(
redact_id,
&pdu.sender,
&pdu.room_id,
false,
)? {
return Err(Error::BadRequest(
ErrorKind::forbidden(),
"User cannot redact this event.",
));
}
if rules.content_field_redacts {
let content = serde_json::from_str::<RoomRedactionEventContent>(pdu.content.get())
.map_err(|_| Error::bad_database("Invalid content in redaction pdu."))?;
if let Some(redact_id) = &content.redacts {
if !services().rooms.state_accessor.user_can_redact(
redact_id,
&pdu.sender,
&pdu.room_id,
false,
)? {
return Err(Error::BadRequest(
ErrorKind::forbidden(),
"User cannot redact this event.",
));
}
}
_ => {
} else if let Some(redact_id) = &pdu.redacts {
if !services().rooms.state_accessor.user_can_redact(
redact_id,
&pdu.sender,
&pdu.room_id,
false,
)? {
return Err(Error::BadRequest(
ErrorKind::UnsupportedRoomVersion,
"Unsupported room version",
ErrorKind::forbidden(),
"User cannot redact this event.",
));
}
}