|
4 | 4 |
|
5 | 5 | namespace PhpList\Core\Domain\Identity\Service; |
6 | 6 |
|
7 | | -use PhpList\Core\Domain\Common\Model\Ability; |
| 7 | +use PhpList\Core\Domain\Common\Model\Interfaces\DomainModel; |
8 | 8 | use PhpList\Core\Domain\Common\Model\Interfaces\OwnableInterface; |
9 | 9 | use PhpList\Core\Domain\Identity\Model\Administrator; |
| 10 | +use PhpList\Core\Domain\Identity\Model\PrivilegeFlag; |
| 11 | +use PhpList\Core\Domain\Messaging\Model\Message; |
| 12 | +use PhpList\Core\Domain\Subscription\Model\Subscriber; |
| 13 | +use PhpList\Core\Domain\Subscription\Model\SubscriberList; |
10 | 14 |
|
11 | 15 | class PermissionChecker |
12 | 16 | { |
13 | | - public function isGranted( |
14 | | - Ability $ability, |
15 | | - Administrator $actor, |
16 | | - ?OwnableInterface $resource = null, |
17 | | - ): bool { |
18 | | - if ($this->isSuperAdmin($actor)) { |
19 | | - return true; |
20 | | - } |
| 17 | + private const REQUIRED_PRIVILEGE_MAP = [ |
| 18 | + Subscriber::class => PrivilegeFlag::Subscribers, |
| 19 | + SubscriberList::class => PrivilegeFlag::Subscribers, |
| 20 | + Message::class => PrivilegeFlag::Campaigns, |
| 21 | + ]; |
21 | 22 |
|
22 | | - return match ($ability) { |
23 | | - Ability::VIEW => $resource && $this->isOwner($actor, $resource), |
24 | | - Ability::EDIT => $resource && $this->isOwner($actor, $resource), |
25 | | - Ability::CREATE => $this->canCreate($actor), |
26 | | - }; |
27 | | - } |
| 23 | + private const OWNERSHIP_MAP = [ |
| 24 | + Subscriber::class => SubscriberList::class, |
| 25 | + Message::class => SubscriberList::class |
| 26 | + ]; |
28 | 27 |
|
29 | | - public function canView(Administrator $actor, OwnableInterface $resource): bool |
| 28 | + public function canManage(Administrator $actor, DomainModel $resource): bool |
30 | 29 | { |
31 | | - if ($this->isSuperAdmin($actor)) { |
| 30 | + if ($actor->isSuperUser()) { |
32 | 31 | return true; |
33 | 32 | } |
34 | 33 |
|
35 | | - return $this->isOwner($actor, $resource); |
36 | | - } |
| 34 | + $required = $this->resolveRequiredPrivilege($resource); |
| 35 | + if ($required !== null && !$actor->getPrivileges()->has($required)) { |
| 36 | + return false; |
| 37 | + } |
37 | 38 |
|
38 | | - public function canEdit(Administrator $actor, OwnableInterface $resource): bool |
39 | | - { |
40 | | - if ($this->isSuperAdmin($actor)) { |
41 | | - return true; |
| 39 | + if ($resource instanceof OwnableInterface) { |
| 40 | + return $actor->owns($resource); |
| 41 | + } |
| 42 | + |
| 43 | + $notRestricted = true; |
| 44 | + foreach (self::OWNERSHIP_MAP as $resourceClass => $relatedClass) { |
| 45 | + if ($resource instanceof $resourceClass) { |
| 46 | + $related = $this->resolveRelatedEntity($resource, $relatedClass); |
| 47 | + $notRestricted = $this->checkRelatedResources($related, $actor); |
| 48 | + } |
42 | 49 | } |
43 | 50 |
|
44 | | - return $this->isOwner($actor, $resource); |
| 51 | + return $notRestricted; |
45 | 52 | } |
46 | 53 |
|
47 | | - public function canCreate(Administrator $actor): bool |
| 54 | + private function resolveRequiredPrivilege(DomainModel $resource): ?PrivilegeFlag |
48 | 55 | { |
49 | | - if ($this->isSuperAdmin($actor)) { |
50 | | - return true; |
| 56 | + foreach (self::REQUIRED_PRIVILEGE_MAP as $class => $flag) { |
| 57 | + if ($resource instanceof $class) { |
| 58 | + return $flag; |
| 59 | + } |
51 | 60 | } |
52 | 61 |
|
53 | | - return $actor->getId() !== null; |
| 62 | + return null; |
54 | 63 | } |
55 | 64 |
|
56 | | - private function isSuperAdmin(Administrator $actor): bool |
| 65 | + /** @return OwnableInterface[] */ |
| 66 | + private function resolveRelatedEntity(DomainModel $resource, string $relatedClass): array |
57 | 67 | { |
58 | | - if ($actor->isSuperUser()) { |
59 | | - return true; |
| 68 | + if ($resource instanceof Subscriber && $relatedClass === SubscriberList::class) { |
| 69 | + return $resource->getSubscribedLists()->toArray(); |
60 | 70 | } |
61 | 71 |
|
62 | | - return false; |
| 72 | + if ($resource instanceof Message && $relatedClass === SubscriberList::class) { |
| 73 | + return $resource->getListMessages()->map(fn($lm) => $lm->getSubscriberList())->toArray(); |
| 74 | + } |
| 75 | + |
| 76 | + return []; |
63 | 77 | } |
64 | 78 |
|
65 | | - private function isOwner(Administrator $actor, OwnableInterface $resource): bool |
| 79 | + private function checkRelatedResources(array $related, Administrator $actor): bool |
66 | 80 | { |
67 | | - $owner = $resource->getOwner(); |
68 | | - $myId = $actor->getId(); |
| 81 | + foreach ($related as $relatedResource) { |
| 82 | + if ($actor->owns($relatedResource)) { |
| 83 | + return true; |
| 84 | + } |
| 85 | + } |
69 | 86 |
|
70 | | - return $owner !== null |
71 | | - && $myId !== null |
72 | | - && $owner->getId() === $myId; |
| 87 | + return false; |
73 | 88 | } |
74 | 89 | } |
0 commit comments