feat(spaces): reject power level changes that conflict with space roles
Checks proposed m.room.power_levels events against Space-granted power levels. Rejects if any user's proposed PL is below their Space role PL. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
9eb2d2542a
commit
f7cfc9d35d
2 changed files with 28 additions and 4 deletions
|
|
@ -127,7 +127,7 @@ where
|
|||
// Make unsigned fields correct. This is not properly documented in the spec,
|
||||
// but state events need to have previous content in the unsigned field, so
|
||||
// clients can easily interpret things like membership changes
|
||||
if let Some(_state_key) = pdu.state_key() {
|
||||
if let Some(state_key) = pdu.state_key() {
|
||||
if let CanonicalJsonValue::Object(unsigned) = pdu_json
|
||||
.entry("unsigned".to_owned())
|
||||
.or_insert_with(|| CanonicalJsonValue::Object(BTreeMap::default()))
|
||||
|
|
@ -226,7 +226,7 @@ where
|
|||
let mut highlights = Vec::with_capacity(push_target.len().saturating_add(1));
|
||||
|
||||
if *pdu.kind() == TimelineEventType::RoomMember {
|
||||
if let Some(_state_key) = pdu.state_key() {
|
||||
if let Some(state_key) = pdu.state_key() {
|
||||
let target_user_id = UserId::parse(state_key)?;
|
||||
|
||||
if self.services.users.is_active_local(target_user_id).await {
|
||||
|
|
@ -327,7 +327,7 @@ where
|
|||
}
|
||||
},
|
||||
| TimelineEventType::SpaceChild =>
|
||||
if let Some(_state_key) = pdu.state_key() {
|
||||
if let Some(state_key) = pdu.state_key() {
|
||||
self.services
|
||||
.spaces
|
||||
.roomid_spacehierarchy_cache
|
||||
|
|
@ -336,7 +336,7 @@ where
|
|||
.remove(room_id);
|
||||
},
|
||||
| TimelineEventType::RoomMember => {
|
||||
if let Some(_state_key) = pdu.state_key() {
|
||||
if let Some(state_key) = pdu.state_key() {
|
||||
// if the state_key fails
|
||||
let target_user_id =
|
||||
UserId::parse(state_key).expect("This state_key was previously validated");
|
||||
|
|
|
|||
|
|
@ -97,6 +97,30 @@ pub async fn build_and_append_pdu(
|
|||
)));
|
||||
}
|
||||
}
|
||||
// Space permission cascading: reject power level changes that conflict
|
||||
// with Space-granted levels
|
||||
if self.services.roles.is_enabled()
|
||||
&& *pdu.kind() == TimelineEventType::RoomPowerLevels
|
||||
{
|
||||
if let Some(parent_space) = self.services.roles.get_parent_space(&room_id).await {
|
||||
use ruma::events::room::power_levels::RoomPowerLevelsEventContent;
|
||||
|
||||
if let Ok(proposed) = pdu.get_content::<RoomPowerLevelsEventContent>() {
|
||||
for (user_id, proposed_pl) in &proposed.users {
|
||||
if let Some(space_pl) =
|
||||
self.services.roles.get_user_power_level(&parent_space, user_id).await
|
||||
{
|
||||
if i64::from(*proposed_pl) < space_pl {
|
||||
return Err!(Request(Forbidden(
|
||||
"Cannot set power level below Space-granted level"
|
||||
)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if *pdu.kind() == TimelineEventType::RoomCreate {
|
||||
trace!("Creating shortroomid for {room_id}");
|
||||
self.services
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue