Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion app/Http/Controllers/Gallery/PhotoController.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
use App\Jobs\ExtractZip;
use App\Jobs\ProcessImageJob;
use App\Jobs\WatermarkerJob;
use App\Models\Extensions\BaseAlbum;
use App\Models\Photo;
use App\Models\SizeVariant;
use App\Models\Tag;
Expand Down Expand Up @@ -325,7 +326,28 @@ public function albums(GetPhotoAlbumsRequest $request): Collection
$album_policy = resolve(AlbumPolicy::class);

return $photo->albums
->filter(fn ($album) => $album_policy->canAccess($user, $album))
->filter(function ($album) use ($album_policy, $user) {
if (!$album instanceof BaseAlbum) {
return $album_policy->canAccess($user, $album);
}

// Owner always sees their albums in the list
if ($album_policy->isOwner($user, $album)) {
return true;
}

// Explicitly shared albums are visible to the shared user
if ($album->current_user_permissions() !== null) {
return true;
}

// Public albums are only shown if not link-required (hidden from listings)
$public_perm = $album->public_permissions();

return $public_perm !== null &&
Comment thread
ildyria marked this conversation as resolved.
$public_perm->is_link_required === false &&
($public_perm->password === null || $album_policy->isUnlocked($album));
})
->values()
->map(fn ($album) => new PhotoAlbumResource($album));
}
Expand Down
23 changes: 23 additions & 0 deletions tests/Feature_v2/Photo/GetPhotoAlbumsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

namespace Tests\Feature_v2\Photo;

use App\Models\AccessPermission;
use App\Models\Album;
use App\Models\Photo;
use Tests\Feature_v2\Base\BaseApiWithDataTest;
Expand Down Expand Up @@ -104,4 +105,26 @@ public function testPhotoWithNoAlbumsReturnsEmptyArray(): void
$response->assertJsonCount(0);
$response->assertExactJson([]);
}

/**
* S-018-08: Hidden (link-required) albums are not shown to non-owners.
*
* Regression test for https://github.com/LycheeOrg/Lychee/discussions/4355
*/
public function testHiddenAlbumNotShownToNonOwner(): void
{
// photo4 is in album4 (public+visible). Also place it in a new hidden album.
$hiddenAlbum = Album::factory()->as_root()->owned_by($this->userLocked)->create();
// Public permission with is_link_required=true (hidden from listings)
AccessPermission::factory()->public()->for_album($hiddenAlbum)->create();
$this->photo4->albums()->syncWithoutDetaching([$hiddenAlbum->id]);

// A guest user should only see album4 (the visible one), NOT the hidden album
$response = $this->getJson('Photo/' . $this->photo4->id . '/albums');
$this->assertOk($response);

$response->assertJsonCount(1);
$response->assertJsonFragment(['id' => $this->album4->id]);
$response->assertJsonMissing(['id' => $hiddenAlbum->id]);
}
}
Loading