Skip to content

fix(portal): collection share thumbnails, idempotent revoke, confirm UI#486

Merged
cjimti merged 1 commit into
mainfrom
fix/share-revoke-and-thumbnails
May 27, 2026
Merged

fix(portal): collection share thumbnails, idempotent revoke, confirm UI#486
cjimti merged 1 commit into
mainfrom
fix/share-revoke-and-thumbnails

Conversation

@cjimti
Copy link
Copy Markdown
Member

@cjimti cjimti commented May 27, 2026

Summary

  • Asset thumbnails inside shared collections returned 403 for recipients because canViewAsset only checked asset-level shares, not collection membership.
  • Share revoke returned 500 on repeat clicks because Revoke errored on already-revoked shares and useRevokeShare did not invalidate collection share queries.
  • The trash icon on shares fired the revoke mutation immediately with no confirmation step.

What changed

pkg/portal/store.go

GetUserAssetPermissionViaCollection joins portal_shares through portal_collection_sections and portal_collection_items to find whether a user has access to an asset via a shared collection. Returns the highest permission found.

Revoke is now idempotent: UPDATE ... SET revoked = TRUE WHERE id = $1 without the AND revoked = FALSE guard, so revoking an already-revoked share succeeds silently.

pkg/portal/handler.go

canViewAsset and canEditAsset fall back to GetUserAssetPermissionViaCollection when no direct asset share exists.

ui/src/api/portal/hooks.ts

useRevokeShare.onSuccess now also invalidates ["collection-shares"] queries so the share list refreshes after revoking a collection share.

ui/src/components/ShareDialog.tsx

The trash icon now shows inline "Remove" / "Cancel" buttons instead of firing the mutation on click.

Verified

  • Ran GetUserAssetPermissionViaCollection SQL against production DB with a real shared user's email and an asset inside the shared collection. Returned editor.
  • TestGetThumbnailViaCollectionShare/granted_via_collection_share: non-owner with no direct asset share but a collection-level share gets 200 and the thumbnail.
  • TestGetThumbnailViaCollectionShare/denied_without_any_share: same user without any share gets 403.
  • TestGetThumbnailNotOwnerNotShared: existing test unchanged, still 403.
  • TestRevokeCollectionShare and TestPostgresShareStoreRevokeIdempotent pass.
  • Full go test -race ./pkg/portal/... passes. npx tsc --noEmit clean.

Test plan

  • TestGetThumbnailViaCollectionShare/granted_via_collection_share - 200
  • TestGetThumbnailViaCollectionShare/denied_without_any_share - 403
  • TestGetThumbnailNotOwnerNotShared - 403 (no regression)
  • TestRevokeCollectionShare/owner_can_revoke - 200
  • TestPostgresShareStoreRevokeIdempotent - no error on already-revoked
  • go test -race ./pkg/portal/... - all pass
  • npx tsc --noEmit - clean
  • Deploy, open a shared collection as a recipient, verify asset thumbnails load
  • Open share dialog, click trash, verify Remove/Cancel buttons appear before mutation fires

…nt revoke, confirm before remove

Asset thumbnails in shared collections returned 403 because canViewAsset
only checked asset-level shares, not collection membership. Added
GetUserAssetPermissionViaCollection which joins through collection
sections and items to find collection-level share grants.

Revoke is now idempotent (no error on already-revoked shares) to prevent
500 on repeat clicks. useRevokeShare invalidates collection-shares
queries so the UI refreshes after revoking a collection share.

The trash icon on shares now requires a confirmation click before
revoking. Clicking the trash shows inline Remove/Cancel buttons instead
of firing the mutation immediately. Confirmation state resets when the
dialog closes.
@cjimti cjimti force-pushed the fix/share-revoke-and-thumbnails branch from cd269ed to ed52114 Compare May 27, 2026 02:56
@cjimti cjimti merged commit d0d14a1 into main May 27, 2026
7 checks passed
@cjimti cjimti deleted the fix/share-revoke-and-thumbnails branch May 27, 2026 02:59
@codecov
Copy link
Copy Markdown

codecov Bot commented May 27, 2026

Codecov Report

❌ Patch coverage is 94.59459% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 86.21%. Comparing base (f719699) to head (ed52114).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
pkg/portal/store.go 91.30% 2 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main     #486   +/-   ##
=======================================
  Coverage   86.20%   86.21%           
=======================================
  Files         237      237           
  Lines       33025    33046   +21     
=======================================
+ Hits        28468    28489   +21     
- Misses       3298     3299    +1     
+ Partials     1259     1258    -1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant