VPR-59 [4/4] CMS: delegated block editing via per-block edit permissions#255
VPR-59 [4/4] CMS: delegated block editing via per-block edit permissions#255rlorenzo wants to merge 22 commits into
Conversation
Admins attach RAPS permissions to a content block as its EDIT permissions; holders of any of them can edit that block without SVMSecure.CMS.ManageContentBlocks. - New ContentBlockToEditPermission entity/table (schema applied manually per environment; DDL in the PR description). An empty edit list means manager-only: delegation is explicit, deliberately not the view list "empty means all SVMSecure" rule - CanEditAsync (manager OR edit-permission intersection, fail-closed, single-resolve HashSet) gates block load, history, diff, and the content-only PATCH, which now also carries attachment deltas; the delegated DTO has no settings fields, so field whitelisting is server-side by construction - Content-scoped file endpoints (attachable search capped at 25 with a minimal DTO, per-block check-name/upload, rollback-only delete constrained to uploader+folder+not-attached-elsewhere) give the editor one code path for managers and delegates alike - Editor renders a capability mode: read-only settings summary for delegates, full editor plus a new "Edit access" selector for managers; the hub gains a "Blocks you can edit" card; the editor route relies on server enforcement - Delegates can view and load version history (restoring is a content save); soft-deleted blocks are not delegate-editable; the anonymous fn endpoint discloses nothing new - 48 new tests (authorization matrix, field scoping, attachment deltas, rollback constraints, capability-mode rendering, hub card)
There was a problem hiding this comment.
Pull request overview
Adds “delegated block editing” to the CMS migration stack by introducing per-block edit-permission lists (separate from view permissions) and a content-scoped editing/file workflow that allows non-managers to edit only content + attachments for blocks they’re delegated.
Changes:
- Introduces
ContentBlockToEditPermission(entity + EF mapping) and edit-authorization inCmsContentBlockService(CanEditAsync, editable-block listing, attachable-file search, rollback-delete eligibility). - Expands the CMS content API with content-scoped endpoints for delegated editors (editable blocks list, attachable-files search, block-scoped file check-name/upload/rollback-delete) and adds attachment deltas to the content-only PATCH.
- Updates the Vue CMS editor and hub to support “capability mode” (manager vs delegated UI) and adds/updates frontend + backend tests for delegated scenarios.
Reviewed changes
Copilot reviewed 20 out of 20 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| web/Models/VIPER/ContentBlockToEditPermission.cs | New EF entity representing a block → edit-permission row. |
| web/Models/VIPER/ContentBlock.cs | Adds navigation collection for edit-permission rows. |
| web/Classes/SQLContext/VIPERContext.cs | Registers DbSet + model configuration for the new table. |
| web/Areas/CMS/Services/CmsContentBlockService.cs | Core authorization + delegated editing behaviors (content-only update with attachment deltas, editable listing, attachable-file search, rollback-delete checks). |
| web/Areas/CMS/Models/DTOs/ContentBlockDto.cs | Adds EditPermissions to block DTO; adds minimal CmsAttachableFileDto. |
| web/Areas/CMS/Models/CmsContentBlockMapper.cs | Maps edit-permission list into DTO. |
| web/Areas/CMS/Models/CMSBlockAddEdit.cs | Adds EditPermissions to create/update request model. |
| web/Areas/CMS/Controllers/CMSContentController.cs | Widens selected endpoints to SVMSecure + CanEditAsync gate; adds content-scoped endpoints for delegated file attach/upload/rollback-delete. |
| VueApp/src/CMS/types/index.ts | Adds editPermissions, plus types for editable blocks and attachable file search results. |
| VueApp/src/CMS/router/routes.ts | Broadens content-block edit route permission to SVMSecure (server is source of truth). |
| VueApp/src/CMS/pages/ContentBlockEdit.vue | Implements manager vs delegated capability UI; uses PATCH for delegated saves; switches attach/search and rollback paths to content-scoped APIs. |
| VueApp/src/CMS/pages/CmsHome.vue | Adds “Blocks you can edit” hub card (delegated editors). |
| VueApp/src/CMS/components/PermissionSelector.vue | Makes hint configurable to reuse for edit-permissions selector. |
| VueApp/src/CMS/components/InlineFileUpload.vue | Adds block-scoped upload mode (check-name/upload/rollback-delete) for delegated editors. |
| VueApp/src/CMS/tests/inline-file-upload.test.ts | Tests block-scoped uploader behavior (no folder/permission fields; no use-existing; POST overwrite). |
| VueApp/src/CMS/tests/content-block-edit-save.test.ts | Updates save payload expectations; tests edit-access selector; updates rollback URL expectations; updates attachable-files behavior. |
| VueApp/src/CMS/tests/content-block-edit-delegated.test.ts | New delegated-mode editor tests (read-only settings, PATCH save, conflict handling). |
| VueApp/src/CMS/tests/cms-home.test.ts | New tests for delegated editable-blocks hub card behavior. |
| test/CMS/CMSContentControllerTests.cs | Extends controller tests for CanEditAsync gating + content-scoped file ops. |
| test/CMS/CmsContentBlockServiceTests.cs | Adds service-level tests for delegated authorization, attachment deltas, editable listing, attachable search, and rollback-delete eligibility. |
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
# Conflicts: # VueApp/src/CMS/components/InlineFileUpload.vue
- refuse block file uploads when the block has no section path instead of falling back to the storage root (mirrors CheckBlockFileName) - treat CreateContentBlock holders as delegated editors on existing blocks; the update endpoint is manager-only, so the manager UI ended in a 403 on save - surface the API error on a failed block load so a 403 no longer reads as "not found"
- the attach-by-search picker returned any active file by name, so delegated editors could see names/guids of files they cannot download; results now pass the same rules as downloads (public, unrestricted, permission match, person grant) - CheckBlockFileName reads just the section path instead of loading and sanitizing the whole block, and returns 400 (not 404) for a block with no section path, matching UploadBlockFile
…PATCH The delegated-editor PATCH validated only that file GUIDs exist, so a guessed GUID could attach a restricted file and leak its name through the attachment list. Newly-added files now pass the same rules as downloads; files already on the block are exempt so a delegate can resend a manager-attached set.
The endpoint and the hub card both document delegated-matches-only with managers getting an empty list, but a manager whose permissions intersected an edit list still got results.
The route required a plain SVMSecure meta permission, but the CMS store only loads SVMSecure.CMS-prefixed permissions, so the guard redirected every user - managers included - away from the editor. The route now relies on requireLogin plus server-side 403s, per its documented design.
…attachments - bound the name-match candidate pool (200) before materializing so a broad two-character term cannot pull the whole file store into memory - the attach guard now requires active files, matching the search; a known GUID could otherwise resurrect a soft-deleted file into an active block
Slice 4 of the CMS migration stack (stacks on #253; the diff shows only this feature). Adds delegated block editing: admins attach RAPS permissions to a block as its edit permissions, and holders of any of them can edit that block's content and attached files — without
SVMSecure.CMS.ManageContentBlocksand without access to anything else.Apply to dev → TEST → PROD ahead of the corresponding deploy (same manual-DDL process as VPR-143). Additive only; invisible to legacy ColdFusion (which reads only the view-permission table), so coexistence is unaffected.
Semantics
ManageContentBlocksor any of B's edit permissions (ANY-OF).Implementation
ContentBlockToEditPermissionentity/table +CanEditAsyncauthorization (single-resolve permission HashSet, fail-closed).GET /editable,GET /attachable-files, per-blockfiles/check-name,POST {id}/files, rollback-onlyDELETE {id}/files/{guid}(owner + folder + not-attached-elsewhere constrained).fnendpoint DTO unchanged (no edit-permission disclosure).