Add per-object authorization for pages (security audit M2)
#52 in Riparion/riparion-cms — merged 2026-06-03
What
Closes the M2 finding from the full-app security audit: page mutations gated only on the global pages:write capability, with no per-object ownership check. Any pages:write holder could edit any page, and pages got no resource-membership row on create — unlike posts, which enforce Editor-on-the-resource and bootstrap the creator as Owner.
This is latent today: seeded authors get only [posts:write, media:upload], and the only holder of pages:write is the admin role, which also holds pages:write_any. The gap bites the moment a pages:write-only role is delegated. This change closes it proactively by mirroring the posts pattern.
Changes
can_edit_pagehelper (src/server/admin/mod.rs) — Editor+ on the("page", id)resource OR the globalpages:write_anyadmin override; the page twin ofcan_edit_post.create_pagebootstraps the author as the page resource Owner (arium_resource_members,kind='page'). No DB migration —kindis a free string on the existing table.update_pageandget_page_edittake theauthorityextractor and gate oncan_edit_pageinstead ofrequire_perm(PAGES_WRITE).delete_pagestays admin-only (pages:write_any) — unchanged.
Deliberately out of scope
- The admin page list stays unfiltered (full hierarchy tree visible to any
pages:writeholder) — pages are shared, hierarchical content and the tree needs ancestor context. Edit denial surfaces on the edit-form/update call. - The unpublished-page preview path (
src/server/pages.rs) — anypages:writeholder may preview drafts; minor read-only concern, left for parity-simplicity.
Verification
cargo fmt --check✅- clippy
-D warnings(CI flags) on server,sqlite + server,postgres + wasm ✅ cargo test --features server,sqlite— 42 passed ✅- Manual end-to-end steps recorded in
TODO_VERIFICATION.md(admin CRUD, owner-row check, the delegatedpages:write-only denial that proves the gap is closed, and the pre-existing-page regression note).
🤖 Generated with Claude Code
Last updated 2026-06-04
Links to this note
Merged pull requests, newest first.