<?php
namespace App\Security\Voter\User;
use App\Entity\Member;
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 MemberVoter extends Voter
{
public const EDIT = 'edit';
public const READ_COINS = 'read_coins';
public const PERMISSION_READ_SENSITIVE = 'read_sensitive';
public const PERMISSION_WRITE_SENSITIVE = 'write_sensitive';
/**
* ProfileVisits.
*/
public const PERMISSION_VISITS_READ = 'visits_read';
public const PERMISSION_VISITS_CREATE = 'visits_create';
public const PERMISSION_GUESTBOOK_MANAGE = 'guestbook_manage';
public const PERMISSION_READ_MESSAGES = 'messages_read';
public const PERMISSION_MESSENGER_CONVERSATION_START = 'messenger_conversation_start';
/**
* ChatTemplate general access. There is an extra voter for accessing a chattemplate entity.
*/
public const PERMISSION_MESSENGER_TEMPLATES_READ = 'messenger_templates_read';
public const PERMISSION_MESSENGER_TEMPLATES_CREATE = 'messenger_templates_create';
public const PERMISSION_MESSENGER_NOTICE_READ = 'messenger_notice_read';
public const PERMISSION_MESSENGER_NOTICE_WRITE = 'messenger_notice_write';
protected function supports(string $attribute, $subject): bool
{
if (!$subject instanceof Member) {
return false;
}
return in_array($attribute, [
self::EDIT,
self::READ_COINS,
self::PERMISSION_READ_SENSITIVE,
self::PERMISSION_WRITE_SENSITIVE,
self::PERMISSION_VISITS_READ,
self::PERMISSION_VISITS_CREATE,
self::PERMISSION_GUESTBOOK_MANAGE,
self::PERMISSION_READ_MESSAGES,
self::PERMISSION_MESSENGER_CONVERSATION_START,
self::PERMISSION_MESSENGER_TEMPLATES_READ,
self::PERMISSION_MESSENGER_TEMPLATES_CREATE,
self::PERMISSION_MESSENGER_NOTICE_READ,
self::PERMISSION_MESSENGER_NOTICE_WRITE,
], true);
}
protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token): bool
{
$user = $token->getUser();
if (!$user instanceof ApiUser) {
return false;
}
/*
* @var $subject Member
*/
switch ($attribute) {
case self::PERMISSION_MESSENGER_CONVERSATION_START:
return $this->canStartConversation($subject, $user);
case self::PERMISSION_VISITS_CREATE:
return $this->mayCreateProfileVisit($subject, $user);
case self::PERMISSION_MESSENGER_TEMPLATES_READ:
case self::PERMISSION_MESSENGER_NOTICE_READ:
case self::PERMISSION_MESSENGER_NOTICE_WRITE:
return $this->isSameOrOperatedBy($subject, $user);
case self::READ_COINS:
return $this->mayReadCoins($subject, $user);
default:
// admin should be able to do anything
if ($user->getIsAdmin()) {
return true;
}
return $user->getMember()->getId() === $subject->getId();
}
}
protected function mayReadCoins(Member $member, ApiUser $user): bool
{
if ($user->getMember()->getId() === $member->getId()) {
return true;
}
if ($user->getIsAdmin()) {
return true;
}
if ($user->getIsOperator() && !$member->getIsAmateur() && $member->getIsActive()) {
return true;
}
return false;
}
protected function isSameOrOperatedBy(Member $amateur, ApiUser $user): bool
{
if ($user->getMember()->getId() === $amateur->getId()) {
return true;
}
if ($user->getIsOperator()) {
return MemberOperatorService::isMemberOperatedByUser($amateur, $user);
}
return false;
}
protected function canStartConversation(Member $partner, ApiUser $user): bool
{
return $user->getMember()->getId() !== $partner->getId();
}
protected function mayCreateProfileVisit(Member $subject, ApiUser $user): bool
{
if ($user->getIsAdmin()) {
return true;
}
if ($user->getIsOperator()) {
if ($subject->getId() === $user->getMember()->getId()) {
return true;
}
return MemberOperatorService::isMemberOperatedByUser($subject, $user);
}
return $user->getMember()->getId() === $subject->getId();
}
}