Gate DM Delete on the effective room role, not the org role (LC-599) #563
Loading…
Reference in a new issue
No description provided.
Delete branch "fix/lc599-dm-delete-uses-effective-role"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes LC-599. Found while auditing the message menu for LC-598, not introduced by it.
The divergence
dm.rscomputed the view flag from the global org role:m.user_id == user.id || user.role == "admin" || user.role == "moderator". The delete endpoint atroom.rs(which serves DM messages too) instead callsdb::room_rbac::is_room_moderator, which resolveseffective_role=max_role(org_role, per_room_override). A user whose moderator status comes from an override passed the endpoint check and failed the template check.The template was more restrictive than the endpoint, so this is a missing affordance, not a privilege escalation. Worth stating plainly, since a
can_deletemismatch would otherwise read as a security issue.The fix
dm.rsnow resolves the effective role once before the render loop, exactly asget_roomalready does, and both timelines read the same predicate. The change is strictly widening:is_room_moderatortakes the max of the org role and the override, so every user who saw Delete before still sees it. The same flag also gates Require acknowledgement, whose endpoint enforcesrequire_author_or_mod, so that affordance realigns with its endpoint as a consequence.Reachability, which the ticket left open
Confirmed reachable.
post_grantguards withrequire_can_manage, a role whitelist, and an enclave-membership check on the target. DM rooms carry no enclave, so the membership check is skipped andrequire_can_managefalls through toroom_can_manage_overrides(None, site_role), which a site admin satisfies. There is no DM exclusion anywhere on that path, so an admin can grant a moderator override on a DM room today.Verification
Two integration tests in
routes_room_rbac.rs, alongside the existing LC-84 override coverage.dm_offers_delete_to_a_moderator_by_room_overridegrants the override through the real HTTP endpoint, asserts the Delete control renders, and then asserts the endpoint actually accepts the delete, pinning the two together rather than testing the template in isolation. It fails against the old predicate (verified by reverting the line in place).dm_hides_delete_from_a_plain_memberproves the affordance is still withheld without an override, so the positive test is not vacuous, and it asserts the message body renders so a blank or errored page cannot pass it.just checkand the fulljust testsuite are green.Noted, not done
MessageViewhas nois_owner,can_pin, oris_modfield, socan_deletedoubles as the moderator proxy in the template. That is what let this predicate drift in two places. A named field would prevent a third, but it touches every message-rendering path and belongs in its own change rather than riding along with a one-line correctness fix.🤖 Generated with Claude Code
https://claude.ai/code/session_01BE9k4nWNUhPrjte9BcvASg