Skip to content

Show album cover art while password-protected - #4704

Open
matthewbolding wants to merge 1 commit into
LycheeOrg:masterfrom
matthewbolding:album-cover-while-locked
Open

Show album cover art while password-protected#4704
matthewbolding wants to merge 1 commit into
LycheeOrg:masterfrom
matthewbolding:album-cover-while-locked

Conversation

@matthewbolding

@matthewbolding matthewbolding commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Adds a "Show cover when locked" toggle to the Visibility tab (v7 and
v8) for password-protected albums. When enabled, the album's cover
thumbnail is shown to anonymous visitors on gallery listings even
before they enter the password — the photos themselves stay hidden
until unlock. This replaces the need for a custom-JS workaround some
users (myself included) had resorted to.

  • Off by default for every album, existing and new — no behavior
    change unless an admin explicitly opts an album in.
  • Scoped to gallery listings (root albums, search, tags) via
    ThumbAlbumResource. The embed endpoint is intentionally out of
    scope for this PR: EmbededRequest::authorize() already rejects any
    password-protected album outright before the resource layer is
    ever reached, and the embed DTO doesn't carry a cover/thumbnail
    concept in the first place. Wiring cover-while-locked into that
    flow is a separate design decision, not a small addition.
  • Not exposed in the bulk-edit admin action; per-album only for now.
  • Fixed a latent bug this change surfaced: AlbumThumb.vue and
    AlbumListItem.vue (v7 + v8) inferred "is this album locked" from
    thumb === null, which was only ever true by coincidence — the
    old ThumbAlbumResource had exactly one code path that nulled out
    thumb, and it was the same path that ran when the album was
    locked, so the two facts always lined up. This PR breaks that
    coincidence on purpose: a locked album with the new toggle on now
    has is_password_required = true and a non-null thumb at the
    same time. Run that state through the old badge logic and it shows
    the green "unlocked" badge on an album that still requires a
    password to view any photos — a real, user-visible bug that simply
    had no way to occur before now. Fixed by adding an explicit
    is_locked field on ThumbAlbumResource and pointing all four
    components at it instead of inferring from thumb.

Note for anyone driving the API directly: grants_cover_access is
now a required field on Album::updateProtectionPolicy, matching
the existing validation on grants_full_photo_access.

Tests added: AlbumsTest::testLockedAlbumHidesThumbByDefault and
::testLockedAlbumWithGrantsCoverAccessShowsThumb, plus updates to
existing protection-policy tests for the new required field.

Summary by CodeRabbit

  • New Features

    • Added a “Show cover when locked” option for password-protected albums.
    • Visitors can view an album’s cover photo before entering its password when enabled.
    • Album listings now accurately indicate locked and unlocked states.
  • Bug Fixes

    • Cover-access settings are preserved when editing album permissions.
    • Thumbnail visibility and lock indicators now reflect the configured protection state.
  • Documentation

    • Added translations for the new cover-access option across supported languages.

Adds a per-album 'grants_cover_access' toggle so a locked album can
still display its cover thumbnail to anonymous visitors, without
revealing photo contents. Defaults to off for every existing album.
@matthewbolding
matthewbolding requested a review from a team as a code owner September 1, 2026 16:43
@coderabbitai

coderabbitai Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The change adds grants_cover_access to album permissions, protection policies, API updates, resources, frontend forms, and translations. Locked album thumbnails can remain visible when permitted. Password badges now use explicit lock state.

Changes

Album cover-access permission

Layer / File(s) Summary
Permission and policy contract
database/migrations/..., app/Models/AccessPermission.php, app/Constants/AccessPermissionConstants.php, database/factories/AccessPermissionFactory.php, app/Http/Resources/Models/Utils/AlbumProtectionPolicy.php
Adds the database column, model support, factory state, permission constant, and policy field. Base and smart albums populate the flag from public permissions.
Backend policy update flow
app/Http/Requests/Album/SetAlbumProtectionPolicyRequest.php, app/Actions/Album/SetProtectionPolicy.php, app/Actions/Admin/BulkEditAlbumsAction.php, app/Http/Resources/Models/ThumbAlbumResource.php
Validates and persists cover access, preserves it during bulk edits, and exposes grants_cover_access with is_locked in album resources.
Frontend controls and types
resources/js/lychee.d.ts, resources/js/services/album-service.ts, resources/js/v7/components/forms/album/AlbumVisibility.vue, resources/js/v8/components/forms/album/AlbumVisibility.vue, lang/*/dialogs.php
Adds the typed field, visibility switches, update payloads, and localized labels and explanations.
Lock state presentation
resources/js/v7/components/gallery/albumModule/*, resources/js/v8/components/gallery/albumModule/*
Uses is_locked for locked and unlocked password badges instead of thumbnail presence.
Validation coverage
tests/Feature_v2/Album/*, tests/Feature_v2/SmartAlbums/OverridePermissionsTest.php, tests/Unit/Actions/Album/SetProtectionPolicyTest.php, tests/Unit/Http/Requests/Album/SetAlbumProtectionPolicyRequestTest.php, tests/Precomputing/CoverSelection/EventPropagationIntegrationTest.php
Updates protection-policy payloads and constructor calls. Adds coverage for hidden and visible thumbnails on locked albums.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Merge Risk: ⚪ Minimal · up to b49f8

The PR opt-in behavior shows album cover art while keeping protected photos hidden; no actionable merge-blocking risk remains after normal checks and review.

Poem

A rabbit flips the cover switch,
The locked album shines less cryptic.
Permissions hop through fields so neat,
Badges find the state they seek.
“Thump,” says the rabbit, “tests complete!”

🚥 Pre-merge checks | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 52.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 25 functions across 41 files. (6 skipped:… Write docstrings for the functions missing them to satisfy the coverage threshold.
Full details: Docstring Coverage

Explanation

Docstring coverage is 52.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 25 functions across 41 files. (6 skipped: 6 unsupported.)

  • Fix all pre-merge checks with AI

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
tests/Feature_v2/Album/AlbumsTest.php (1)

229-250: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use snake_case for the locked album variable.

Rename $lockedAlbum to $locked_album in both tests. Update all references in each test.

  • tests/Feature_v2/Album/AlbumsTest.php#L229-L250: Rename $lockedAlbum and its references to $locked_album.
  • tests/Feature_v2/Album/AlbumsTest.php#L254-L276: Rename $lockedAlbum and its references to $locked_album.

As per coding guidelines: “Variable names should be in snake_case.”

Source: Coding guidelines


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Team

Run ID: 8d7ad47d-68b4-448e-afe3-12c2b33ae587

📥 Commits

Reviewing files that changed from the base of the PR and between 2ffb790 and b49f8a3.

📒 Files selected for processing (47)
  • app/Actions/Admin/BulkEditAlbumsAction.php
  • app/Actions/Album/SetProtectionPolicy.php
  • app/Constants/AccessPermissionConstants.php
  • app/Contracts/Http/Requests/RequestAttribute.php
  • app/Http/Requests/Album/SetAlbumProtectionPolicyRequest.php
  • app/Http/Resources/Models/ThumbAlbumResource.php
  • app/Http/Resources/Models/Utils/AlbumProtectionPolicy.php
  • app/Models/AccessPermission.php
  • database/factories/AccessPermissionFactory.php
  • database/migrations/2026_08_31_000000_add_grants_cover_access_to_access_permissions_table.php
  • lang/ar/dialogs.php
  • lang/bg/dialogs.php
  • lang/cz/dialogs.php
  • lang/de/dialogs.php
  • lang/el/dialogs.php
  • lang/en/dialogs.php
  • lang/es/dialogs.php
  • lang/fa/dialogs.php
  • lang/fr/dialogs.php
  • lang/hu/dialogs.php
  • lang/it/dialogs.php
  • lang/ja/dialogs.php
  • lang/nl/dialogs.php
  • lang/no/dialogs.php
  • lang/pl/dialogs.php
  • lang/pt/dialogs.php
  • lang/ru/dialogs.php
  • lang/sk/dialogs.php
  • lang/sv/dialogs.php
  • lang/tr/dialogs.php
  • lang/vi/dialogs.php
  • lang/zh_CN/dialogs.php
  • lang/zh_TW/dialogs.php
  • resources/js/lychee.d.ts
  • resources/js/services/album-service.ts
  • resources/js/v7/components/forms/album/AlbumVisibility.vue
  • resources/js/v7/components/gallery/albumModule/AlbumListItem.vue
  • resources/js/v7/components/gallery/albumModule/thumbs/AlbumThumb.vue
  • resources/js/v8/components/forms/album/AlbumVisibility.vue
  • resources/js/v8/components/gallery/albumModule/AlbumListItem.vue
  • resources/js/v8/components/gallery/albumModule/thumbs/AlbumThumb.vue
  • tests/Feature_v2/Album/AlbumUpdateTest.php
  • tests/Feature_v2/Album/AlbumsTest.php
  • tests/Feature_v2/SmartAlbums/OverridePermissionsTest.php
  • tests/Precomputing/CoverSelection/EventPropagationIntegrationTest.php
  • tests/Unit/Actions/Album/SetProtectionPolicyTest.php
  • tests/Unit/Http/Requests/Album/SetAlbumProtectionPolicyRequestTest.php

Included review availability: Your plan provides up to 8 included reviews per hour; 7 remain after this review.

@ildyria

ildyria commented Sep 1, 2026

Copy link
Copy Markdown
Member

Hi @matthewbolding I am currently in the middle of a huge refactoring of the way albums are actually being displayed in the front-end.

Do you mind we wait for it to be merged as it will have a LOT of changes with regard to your proposition?

PS: I really like the idea BTW, it is just that it arrives at the worse moment and I don't want you to waste your time on something which is going to be removed soon.

See here for what is coming: #4705
If you join discord, feel free to ping me so we can see how to synchronize. :)

And yes, I am planning the same change for the photo display...

@codecov

codecov Bot commented Sep 1, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 91.45%. Comparing base (2ffb790) to head (b49f8a3).
⚠️ Report is 1 commits behind head on master.

🚀 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.

@matthewbolding

Copy link
Copy Markdown
Contributor Author

Hi @matthewbolding I am currently in the middle of a huge refactoring of the way albums are actually being displayed in the front-end.

Do you mind we wait for it to be merged as it will have a LOT of changes with regard to your proposition?

PS: I really like the idea BTW, it is just that it arrives at the worse moment and I don't want you to waste your time on something which is going to be removed soon.

See here for what is coming: #4705 If you join discord, feel free to ping me so we can see how to synchronize. :)

And yes, I am planning the same change for the photo display...

Hi @ildyria. Thanks for the reply. Yes, I have no issue waiting on other changes to the codebase to be applied before this feature gets incorporated. I'll likely reach out to you on Discord late on. Glad you like the idea!

Another idea I had was to permit fully custom album covers, i.e., the system shall accept a new image file to be used for the sole purpose of an album cover.

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.

2 participants