feat: folder-scoped sharing - #154
Conversation
Share a single VMS Folder without exposing the rest of the project. Each folder gets its own share_token, independent of the project share and of other folders. The public link is /vms/shared/folder/<id> with no project segment, so moving the folder never breaks it. Trashing the folder clears the token; scope is the folder's own assets only (nested subfolders excluded). Backend (vms/api.py, VMS Folder): - share_token field + revoke_share_on_trash controller hook - enable/disable_folder_sharing, get_shared_folder, get_shared_folder_assets - get_shared_asset_view_url / _download_url take an optional folder arg, validated against the folder token (project path unchanged); folder validation also rejects an unshared folder for authenticated non-VMS users Frontend: - ShareFolderPanel, Share entry in folder card / row / actions menus - /vms/shared/folder/:folderId route reuses SharedProjectPage in folder mode - in-folder header menu now shows the folder's actions Tests deferred (see plans/folder-scoped-sharing.md). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UDbtFtgkUmtPEU8PhbcoC5
Greptile SummaryAdds independently revocable, folder-scoped public sharing while preserving existing project sharing.
Confidence Score: 5/5The PR appears safe to merge, although automated coverage of the new sharing boundary remains a worthwhile non-blocking follow-up. The two prior authorization defects are fully fixed: every caller must now provide the folder token, and media URL endpoints reject trashed or still-uploading assets consistently with shared listings. The remaining previous feedback concerns deferred automated coverage and does not identify a current functional failure.
|
| Filename | Overview |
|---|---|
| vms/api.py | Adds folder-scoped sharing APIs and aligns folder-token, asset-scope, and lifecycle validation across listing and media URL endpoints. |
| vms/video_management_solution/doctype/vms_folder/vms_folder.py | Revokes an active folder share token whenever the folder enters the trash lifecycle. |
| vms/video_management_solution/doctype/vms_folder/vms_folder.json | Adds a hidden, read-only, unique share token to the folder data model. |
| frontend/src/pages/SharedProjectPage.vue | Generalizes the guest sharing page to support either project or direct-folder scope. |
| frontend/src/components/folders/ShareFolderPanel.vue | Adds the folder public-link toggle, link display, and clipboard interaction. |
| frontend/src/router.ts | Registers the guest folder-sharing route outside the authenticated shell. |
| plans/folder-scoped-sharing.md | Documents the folder-sharing boundary and explicitly defers automated regression coverage. |
Reviews (3): Last reviewed commit: "fix: harden shared-folder access checks ..." | Re-trigger Greptile
| ## Testing | ||
|
|
||
| Deferred — full e2e/unit suite is a follow-up. One security assertion was | ||
| verified during implementation: folder A (file a1) with subfolder B (b1) and | ||
| sibling C (c1); sharing A, a guest gets a1 only, b1/c1 are rejected; trashing A | ||
| clears the token and kills the link. |
There was a problem hiding this comment.
The new token-protected sharing boundary, including sibling and child isolation and trash revocation, has no automated regression coverage; this plan explicitly defers testing. Add an end-to-end case covering invalid or missing tokens, non-VMS authenticated sessions, out-of-scope assets, and folder and asset trash so future authorization changes cannot silently broaden public access.
Knowledge Base Used: Project workspaces and sharing
Prompt To Fix With AI
This is a comment left during a code review.
Path: plans/folder-scoped-sharing.md
Line: 82-87
Comment:
**Sharing boundary lacks tests**
The new token-protected sharing boundary, including sibling and child isolation and trash revocation, has no automated regression coverage; this plan explicitly defers testing. Add an end-to-end case covering invalid or missing tokens, non-VMS authenticated sessions, out-of-scope assets, and folder and asset trash so future authorization changes cannot silently broaden public access.
**Knowledge Base Used:** [Project workspaces and sharing](https://app.greptile.com/bwh-tech/-/custom-context/knowledge-base/bwhtech/vms/-/docs/project-workspaces-and-sharing.md)
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
- nosemgrep markers on the guest-whitelisted folder-share endpoints - type hints on get_shared_folder_assets page params Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UDbtFtgkUmtPEU8PhbcoC5
- _validate_folder_token requires a valid token for every caller; the authenticated-session branch that skipped the token comparison is gone, so a logged-in non-VMS account can no longer read a shared folder by id - get_shared_asset_view_url / _download_url reject a trashed or still-uploading asset instead of only checking scope, for both the folder and project paths Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UDbtFtgkUmtPEU8PhbcoC5
What
Share a single VMS Folder without exposing the rest of the project. Today
VMS Projectcarries oneshare_tokenandget_shared_project_assetsreturns every asset in the project as a flat list — there was no way to share one folder.How it works
VMS Foldergets its ownshare_token, independent of the project share and of other folders. Project + any number of folders can be shared at once; revoking one touches nothing else./vms/shared/folder/<folder-id>?token=…— no project segment, so moving the folder between projects doesn't break it.share_token(link dies); restoring does not re-enable it.Changes
Backend (
vms/api.py,VMS Folder)share_tokenfield (hidden, unique) +revoke_share_on_trashcontroller hookenable_folder_sharing/disable_folder_sharing/get_shared_folder/get_shared_folder_assetsget_shared_asset_view_url/get_shared_asset_download_urlgain an optionalfolderarg validated against the folder token — project path unchangedFrontend
ShareFolderPanel.vue; "Share" entry in folder card / row / in-folder actions menus/vms/shared/folder/:folderIdroute reusesSharedProjectPagein folder mode (title = folder name, flat grid, preview, Download all)⋯now shows the folder's actions (was project actions)Spec:
plans/folder-scoped-sharing.mdVerification
ruff check+format,yarn typecheck/lint/build— cleanFollow-ups (not in this PR)
sharing.spec.tsbefore mergeget_shared_asset_*_urlendpoints don't re-check "is it shared" — the folder path added here is hardened against this; worth a separate ticket🤖 Generated with Claude Code