Skip to content

Commit 806b188

Browse files
authored
Fixes access rights with multiple groups (#4482)
* Fixes access rights with multiple groups * ADR
1 parent 9b11bc3 commit 806b188

16 files changed

Lines changed: 1070 additions & 29 deletions

File tree

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php
2+
3+
/**
4+
* SPDX-License-Identifier: MIT
5+
* Copyright (c) 2017-2018 Tobias Reich
6+
* Copyright (c) 2018-2026 LycheeOrg.
7+
*/
8+
9+
namespace App\DTO;
10+
11+
use App\Models\AccessPermission;
12+
use Illuminate\Support\Collection;
13+
14+
/**
15+
* Read-only, non-persistable capability snapshot for the current user on an
16+
* album: the union (logical OR) of every applicable AccessPermission row's
17+
* grant flags, independent of row order or source (direct-user vs. group).
18+
*/
19+
final readonly class EffectiveAccessPermission
20+
{
21+
public function __construct(
22+
public bool $grants_full_photo_access = false,
23+
public bool $grants_download = false,
24+
public bool $grants_upload = false,
25+
public bool $grants_edit = false,
26+
public bool $grants_delete = false,
27+
) {
28+
}
29+
30+
/**
31+
* Merge every given AccessPermission row into a single snapshot: each
32+
* grant flag is true if it is true on at least one row.
33+
*
34+
* @param Collection<int,AccessPermission> $permissions
35+
*/
36+
public static function merge(Collection $permissions): self
37+
{
38+
return new self(
39+
grants_full_photo_access: $permissions->contains(fn (AccessPermission $p) => $p->grants_full_photo_access),
40+
grants_download: $permissions->contains(fn (AccessPermission $p) => $p->grants_download),
41+
grants_upload: $permissions->contains(fn (AccessPermission $p) => $p->grants_upload),
42+
grants_edit: $permissions->contains(fn (AccessPermission $p) => $p->grants_edit),
43+
grants_delete: $permissions->contains(fn (AccessPermission $p) => $p->grants_delete),
44+
);
45+
}
46+
}

app/Models/Album.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
use App\Actions\Album\Delete;
1212
use App\DTO\AlbumSortingCriterion;
13+
use App\DTO\EffectiveAccessPermission;
1314
use App\Enum\AlbumTitleColor;
1415
use App\Enum\AlbumTitlePosition;
1516
use App\Enum\AspectRatioType;
@@ -84,7 +85,7 @@
8485
*
8586
* @property Collection<int,AccessPermission> $access_permissions
8687
* @property int|null $access_permissions_count
87-
* @property AccessPermission|null $current_user_permissions
88+
* @property EffectiveAccessPermission|null $current_user_permissions
8889
* @property AccessPermission|null $public_permissions
8990
* @property Collection<int,User> $shared_with
9091
* @property int|null $shared_with_count

app/Models/BaseAlbumImpl.php

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use App\Constants\AccessPermissionConstants as APC;
1212
use App\Constants\RandomID;
1313
use App\Contracts\Models\HasRandomID;
14+
use App\DTO\EffectiveAccessPermission;
1415
use App\DTO\PhotoSortingCriterion;
1516
use App\Enum\ColumnSortingType;
1617
use App\Enum\OrderSortingType;
@@ -256,18 +257,27 @@ public function access_permissions(): HasMany
256257
}
257258

258259
/**
259-
* Returns the relationship between an album and its associated current user permissions.
260+
* Returns the merged, effective permissions of the current user on this album.
261+
*
262+
* Combines the direct-user AccessPermission row (if any) with every row for
263+
* a group the user belongs to: each grant flag is the logical OR across all
264+
* matching rows, independent of row order (there is no precedence between
265+
* a direct-user row and a group row — the most permissive grant wins).
260266
*/
261-
public function current_user_permissions(): AccessPermission|null
267+
public function current_user_permissions(): EffectiveAccessPermission|null
262268
{
263269
if (Auth::guest()) {
264270
return null; // No permissions for guests
265271
}
266272

267273
$user = Auth::user();
274+
$group_ids = $user->user_groups->map(fn ($g) => $g->id)->all();
275+
276+
$matching = $this->access_permissions->filter(
277+
fn (AccessPermission $p) => $p->user_id === $user->id || in_array($p->user_group_id, $group_ids, true)
278+
);
268279

269-
return $this->access_permissions->first(fn (AccessPermission $p) => $p->user_id === $user->id)
270-
?? $this->access_permissions->first(fn (AccessPermission $p) => in_array($p->user_group_id, $user->user_groups->map(fn ($g) => $g->id)->all(), true));
280+
return $matching->isEmpty() ? null : EffectiveAccessPermission::merge($matching);
271281
}
272282

273283
/**

app/Models/Extensions/BaseAlbum.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use App\Constants\RandomID;
1212
use App\Contracts\Models\AbstractAlbum;
1313
use App\Contracts\Models\HasRandomID;
14+
use App\DTO\EffectiveAccessPermission;
1415
use App\DTO\PhotoSortingCriterion;
1516
use App\Enum\PhotoLayoutType;
1617
use App\Enum\TimelinePhotoGranularity;
@@ -115,7 +116,7 @@ public function access_permissions(): HasMany
115116
/**
116117
* Returns the relationship between an album and its associated current user permissions.
117118
*/
118-
public function current_user_permissions(): AccessPermission|null
119+
public function current_user_permissions(): EffectiveAccessPermission|null
119120
{
120121
return $this->base_class->current_user_permissions();
121122
}

app/Models/PersonAlbum.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
namespace App\Models;
1010

1111
use App\Constants\PersonAlbumPersons;
12+
use App\DTO\EffectiveAccessPermission;
1213
use App\Exceptions\InvalidPropertyException;
1314
use App\ModelFunctions\HasAbstractAlbumProperties;
1415
use App\Models\Builders\PersonAlbumBuilder;
@@ -38,7 +39,7 @@
3839
* @property int|null $shared_with_count
3940
* @property Collection<int, AccessPermission> $access_permissions
4041
* @property int|null $access_permissions_count
41-
* @property AccessPermission|null $current_user_permissions
42+
* @property EffectiveAccessPermission|null $current_user_permissions
4243
* @property AccessPermission|null $public_permissions
4344
*
4445
* @method static PersonAlbumBuilder|PersonAlbum addSelect($column)

app/Models/TagAlbum.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
namespace App\Models;
1010

11+
use App\DTO\EffectiveAccessPermission;
1112
use App\Exceptions\InvalidPropertyException;
1213
use App\ModelFunctions\HasAbstractAlbumProperties;
1314
use App\Models\Builders\TagAlbumBuilder;
@@ -39,7 +40,7 @@
3940
* @property int|null $shared_with_count
4041
* @property Collection<int, AccessPermission> $access_permissions
4142
* @property int|null $access_permissions_count
42-
* @property AccessPermission|null $current_user_permissions
43+
* @property EffectiveAccessPermission|null $current_user_permissions
4344
* @property AccessPermission|null $public_permissions
4445
* @property Collection<int, User> $shared_with
4546
*

0 commit comments

Comments
 (0)