<?php
namespace App\Security\Voter\Messenger;
use App\Entity\Conversation;
use App\Security\ApiUser;
use App\Service\User\MemberOperatorService;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
class ConversationVoter extends Voter
{
public const PERMISSION_READ = 'read';
public const PERMISSION_WRITE = 'write';
public const PERMISSION_DELETE = 'delete';
protected function supports(string $attribute, $subject): bool
{
if (!$subject instanceof Conversation) {
return false;
}
return in_array($attribute, [
self::PERMISSION_READ,
self::PERMISSION_WRITE,
self::PERMISSION_DELETE,
], true);
}
protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token): bool
{
$user = $token->getUser();
if (!$user instanceof ApiUser) {
return false;
}
/*
* @var $subject Conversation
*/
if (self::PERMISSION_DELETE == $attribute) {
return $this->canDelete($subject, $user);
}
if (self::PERMISSION_READ === $attribute) {
return $this->canRead($subject, $user);
}
if (self::PERMISSION_WRITE === $attribute) {
return $this->canWrite($subject, $user);
}
return false;
}
protected function canRead(Conversation $subject, ApiUser $user): bool
{
if ($user->getIsOperator()) {
foreach ($subject->getRoutes() as $route) {
if (MemberOperatorService::isMemberOperatedByUser($route->getFromMember(), $user)) {
return true;
}
}
}
if ($user->getIsAdmin()) {
return true;
}
return $this->isParticipant($subject, $user);
}
protected function canWrite(Conversation $subject, ApiUser $user): bool
{
if ($user->getIsOperator()) {
return true;
}
// admins may not write
return $this->isParticipant($subject, $user);
}
protected function canDelete(Conversation $subject, ApiUser $user): bool
{
if ($user->getIsAdmin()) {
return true;
}
return $this->isParticipant($subject, $user);
}
protected function isParticipant(Conversation $subject, ApiUser $user): bool
{
foreach ($subject->getRoutes() as $route) {
if ($route->getFromMember()->getId() == $user->getMember()->getId()) {
return true;
}
}
return false;
}
}