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:
parent
b631621f8c
commit
a8fa237fad
7 changed files with 135 additions and 219 deletions
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.",
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue