<?php
namespace App\Security\Voter;
use App\Entity\Address;
use App\Entity\User;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
// https://symfony.com/doc/current/security/voters.html
class AddressVoter extends Voter
{
const CAN_EDIT_ADDRESS = 'edit_address';
const CAN_DELETE_ADDRESS = 'delete_address';
public function __construct()
{
}
protected function supports($attribute, $subject): bool
{
// if the attribute isn't one we support, return false
if (!in_array($attribute, [self::CAN_EDIT_ADDRESS, self::CAN_DELETE_ADDRESS])) {
return false;
}
// only vote on `Address` objects
if (!$subject instanceof Address) {
return false;
}
return true;
}
protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool
{
/** @var User */
$loggedUser = $token->getUser();
// you know $subject is a Address object, thanks to `supports()`
/** @var Address $address */
$address = $subject;
return match ($attribute) {
self::CAN_EDIT_ADDRESS => $this->canEdit($address, $loggedUser),
self::CAN_DELETE_ADDRESS => $this->canDelete($address, $loggedUser),
default => throw new \LogicException('This code should not be reached!')
};
}
private function canEdit(Address $address, ?User $loggedUser): bool
{
if (!$loggedUser) {
// the user must be logged in; if not, deny access
return false;
}
if ($address->getUser() != $loggedUser) {
// the address must be owned by the user
return false;
}
return true;
}
private function canDelete(Address $address, ?User $loggedUser): bool
{
if (!$loggedUser) {
// the user must be logged in; if not, deny access
return false;
}
if ($address->getUser() != $loggedUser) {
// the address must be owned by the user
return false;
}
return true;
}
}