<?php
/**
* This file is part of the educat package.
*
* (c) Solvee
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
declare(strict_types=1);
namespace App\Chat\Application\Security;
use App\Common\Model\Chat\MessageInterface;
use App\Common\Model\Core\UserInterface;
use App\Common\Security\AccountRole;
use LogicException;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
use Symfony\Component\Security\Core\Security;
/**
* Class MessageVoter
*
* @author Jarosław Dylewski <jaroslaw.dylewski@interia.pl>
*/
class MessageVoter extends Voter
{
public const CAN_SEND_MESSAGE = 'can_send_message';
public const CAN_GET_MESSAGE = 'can_get_message';
public const CAN_MARK_MESSAGE_AS_READ = 'can_mark_message_as_read';
/** @var Security */
private Security $security;
/**
* MessageVoter constructor.
*
* @param Security $security
*/
public function __construct(Security $security)
{
$this->security = $security;
}
/**
* @param string $attribute
* @param mixed $subject
*
* @return bool
*/
protected function supports($attribute, $subject)
{
if (!in_array(
$attribute,
[
self::CAN_SEND_MESSAGE,
self::CAN_GET_MESSAGE,
self::CAN_MARK_MESSAGE_AS_READ,
]
)) {
return false;
}
return $attribute && $subject instanceof MessageInterface;
}
/**
* @param string $attribute
* @param mixed $subject
* @param TokenInterface $token
*
* @return bool
*/
protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
{
$user = $token->getUser();
if (!$user instanceof UserInterface) {
return false;
}
switch ($attribute) {
case self::CAN_SEND_MESSAGE:
return $this->canSendMessage($subject, $user);
case self::CAN_GET_MESSAGE:
return $this->canGetMessage($subject, $user);
case self::CAN_MARK_MESSAGE_AS_READ:
return $this->canMarkMessageAsRead($subject, $user);
default:
throw new LogicException();
}
}
/**
* @param MessageInterface $message
* @param UserInterface $user
*
* @return bool
*/
private function canSendMessage(MessageInterface $message, UserInterface $user): bool
{
return $this->isAdminOrMessageSender($message, $user);
}
/**
* @param MessageInterface $message
* @param UserInterface $user
*
* @return bool
*/
private function canGetMessage(MessageInterface $message, UserInterface $user): bool
{
if ($this->security->isGranted(AccountRole::ADMIN)) {
return true;
}
return $message->getFrom() === $user || $message->getTo() === $user;
}
/**
* @param MessageInterface $message
* @param UserInterface $user
*
* @return bool
*/
private function canMarkMessageAsRead(MessageInterface $message, UserInterface $user): bool
{
if ($this->security->isGranted(AccountRole::ADMIN)) {
return true;
}
return $message->getTo() === $user;
}
/**
* @param MessageInterface $message
* @param UserInterface $user
*
* @return bool
*/
private function isAdminOrMessageSender(MessageInterface $message, UserInterface $user): bool
{
if ($this->security->isGranted(AccountRole::ADMIN)) {
return true;
}
return $message->getFrom() === $user;
}
}