feat(spaces): wire up enforcement hooks in join, append, and build paths
Some checks failed
Documentation / Build and Deploy Documentation (pull_request) Has been skipped
Checks / Prek / Pre-commit & Formatting (pull_request) Failing after 5s
Checks / Prek / Clippy and Cargo Tests (pull_request) Failing after 6s
Update flake hashes / update-flake-hashes (pull_request) Failing after 6s

Add minimal integration points in existing files:
- append.rs: call on_pdu_appended for event-driven enforcement
- build.rs: call validate_pl_change to protect space-managed PLs
- join.rs: call check_join_allowed to gate joins on role requirements
- timeline/mod.rs: add roles service dependency
This commit is contained in:
ember33 2026-03-20 08:52:23 +01:00
parent 5f901a560b
commit 1f91a74b27
5 changed files with 23 additions and 1 deletions

View file

@ -0,0 +1 @@
Add Space permission cascading: power levels cascade from Spaces to child rooms, role-based room access with custom roles, continuous enforcement (auto-join/kick), and admin commands for role management. Server-wide default controlled by `space_permission_cascading` config flag (off by default), with per-Space overrides via `!admin space roles enable/disable <space>`.

View file

@ -347,6 +347,12 @@ pub async fn join_room_by_id_helper(
} }
} }
services
.rooms
.roles
.check_join_allowed(room_id, sender_user)
.await?;
if server_in_room { if server_in_room {
join_room_by_id_helper_local(services, sender_user, room_id, reason, servers, state_lock) join_room_by_id_helper_local(services, sender_user, room_id, reason, servers, state_lock)
.boxed() .boxed()

View file

@ -327,7 +327,7 @@ where
} }
}, },
| TimelineEventType::SpaceChild => | TimelineEventType::SpaceChild =>
if let Some(_state_key) = pdu.state_key() { if pdu.state_key().is_some() {
self.services self.services
.spaces .spaces
.roomid_spacehierarchy_cache .roomid_spacehierarchy_cache
@ -359,6 +359,8 @@ where
| _ => {}, | _ => {},
} }
self.services.roles.on_pdu_appended(room_id, &pdu);
// CONCERN: If we receive events with a relation out-of-order, we never write // CONCERN: If we receive events with a relation out-of-order, we never write
// their relation / thread. We need some kind of way to trigger when we receive // their relation / thread. We need some kind of way to trigger when we receive
// this event, and potentially a way to rebuild the table entirely. // this event, and potentially a way to rebuild the table entirely.

View file

@ -97,6 +97,17 @@ pub async fn build_and_append_pdu(
))); )));
} }
} }
if *pdu.kind() == TimelineEventType::RoomPowerLevels {
if let Ok(proposed) =
pdu.get_content::<ruma::events::room::power_levels::RoomPowerLevelsEventContent>()
{
self.services
.roles
.validate_pl_change(&room_id, pdu.sender(), &proposed)
.await?;
}
}
if *pdu.kind() == TimelineEventType::RoomCreate { if *pdu.kind() == TimelineEventType::RoomCreate {
trace!("Creating shortroomid for {room_id}"); trace!("Creating shortroomid for {room_id}");
self.services self.services

View file

@ -80,6 +80,7 @@ struct Services {
threads: Dep<rooms::threads::Service>, threads: Dep<rooms::threads::Service>,
search: Dep<rooms::search::Service>, search: Dep<rooms::search::Service>,
spaces: Dep<rooms::spaces::Service>, spaces: Dep<rooms::spaces::Service>,
roles: Dep<rooms::roles::Service>,
event_handler: Dep<rooms::event_handler::Service>, event_handler: Dep<rooms::event_handler::Service>,
} }
@ -112,6 +113,7 @@ impl crate::Service for Service {
threads: args.depend::<rooms::threads::Service>("rooms::threads"), threads: args.depend::<rooms::threads::Service>("rooms::threads"),
search: args.depend::<rooms::search::Service>("rooms::search"), search: args.depend::<rooms::search::Service>("rooms::search"),
spaces: args.depend::<rooms::spaces::Service>("rooms::spaces"), spaces: args.depend::<rooms::spaces::Service>("rooms::spaces"),
roles: args.depend::<rooms::roles::Service>("rooms::roles"),
event_handler: args event_handler: args
.depend::<rooms::event_handler::Service>("rooms::event_handler"), .depend::<rooms::event_handler::Service>("rooms::event_handler"),
}, },