<?php
/*
* Author: Dominik Piekarski <code@dompie.de>
* Created at: 2021/08/26 15:50
*/
declare(strict_types=1);
namespace App\Voter;
use App\Security\ApiUser;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
use Symfony\Component\Security\Core\Security;
class GuestbookVoter extends Voter
{
public const PERMISSION_MANAGE_ENTRY = 'guestbookManageEntry';
public const PERMISSION_VIEW_PUBLIC = 'guestbookViewEntry';
public const PERMISSION_COMMENT = 'guestbookCommentEntry';
protected Security $security;
/**
* @var RequestStack
*/
protected RequestStack $requestStack;
/**
* @param Security $security
* @param RequestStack $requestStack
*/
public function __construct(Security $security, RequestStack $requestStack)
{
$this->security = $security;
$this->requestStack = $requestStack;
}
protected function supports(string $attribute, $subject)
{
$supportedAction = in_array($attribute, [
self::PERMISSION_MANAGE_ENTRY,
self::PERMISSION_VIEW_PUBLIC,
self::PERMISSION_COMMENT
], true);
$supportedSubject = is_array($subject) && isset($subject['id']) && isset($subject['recipient'])
&& isset($subject['is_spam']) && isset($subject['is_hidden']);
return $supportedSubject && $supportedAction;
}
protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token)
{
/** @var ApiUser $user */
$user = $this->security->getUser();
// admins may do anything, but may NOT comment
if ($attribute !== self::PERMISSION_COMMENT && $this->security->isGranted('ROLE_ADMIN', $user)) {
return true;
}
$isKnownUser = $user instanceof ApiUser && $user->getMemberId() > 0;
if ($isKnownUser && $subject['recipient']['username'] === $user->getUsername()) {
// owner may do anything
return true;
}
switch ($attribute) {
case self::PERMISSION_COMMENT:
case self::PERMISSION_MANAGE_ENTRY:
// operators may comment and delete, but only via the operator app / section
return $this->security->isGranted('ROLE_OPERATOR', $user) &&
$this->requestStack->getMainRequest()->get('_route') === 'app_messenger_operator_guestbook';
case self::PERMISSION_VIEW_PUBLIC:
return $subject['is_hidden'] === false && $subject['is_spam'] === false;
}
return false;
}
}