Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
17 / 17
100.00% covered (success)
100.00%
4 / 4
CRAP
100.00% covered (success)
100.00%
1 / 1
MaxfieldVoter
100.00% covered (success)
100.00%
17 / 17
100.00% covered (success)
100.00%
4 / 4
9
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 supports
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 voteOnAttribute
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
1 / 1
5
 canModify
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3declare(strict_types=1);
4
5namespace App\Security;
6
7use App\Entity\Maxfield;
8use App\Entity\User;
9use App\Enum\UserRole;
10use LogicException;
11use Symfony\Bundle\SecurityBundle\Security;
12use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
13use Symfony\Component\Security\Core\Authorization\Voter\Vote;
14use Symfony\Component\Security\Core\Authorization\Voter\Voter;
15
16/** @extends Voter<string, mixed> */
17class MaxfieldVoter extends Voter
18{
19    final public const string MODIFY = 'modify';
20
21    public function __construct(private readonly Security $security) {}
22
23    protected function supports(string $attribute, mixed $subject): bool
24    {
25        if ($attribute !== self::MODIFY) {
26            return false;
27        }
28
29        return $subject instanceof Maxfield;
30    }
31
32    protected function voteOnAttribute(
33        string $attribute,
34        mixed $subject,
35        TokenInterface $token,
36        ?Vote $vote = null
37    ): bool
38    {
39        $user = $token->getUser();
40
41        if (!$user instanceof User) {
42            // the user must be logged in; if not, deny access
43            return false;
44        }
45
46        if ($this->security->isGranted(UserRole::ADMIN)) {
47            return true;
48        }
49
50        /** @var Maxfield $maxfield */
51        $maxfield = $subject;
52
53        return match ($attribute) {
54            self::MODIFY => $this->canModify($maxfield, $user),
55            default => throw new LogicException(
56                'This code should not be reached!'
57            )
58        };
59    }
60
61    private function canModify(Maxfield $maxfield, User $user): bool
62    {
63        return $user === $maxfield->getOwner();
64    }
65}