<?php
namespace App\ApiPlatform\Voter;
use App\Entity\Discussion;
use App\Entity\User;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
use Symfony\Component\Security\Core\Security;
class DiscussionVoter extends Voter
{
public const CREATE = 'CREATE';
public const EDIT = 'EDIT';
public const DELETE = 'DELETE';
public function __construct(private readonly Security $security)
{
}
protected function supports(string $attribute, $subject): bool
{
if (!$subject instanceof Discussion) {
return false;
}
return in_array($attribute, [self::CREATE, self::EDIT, self::DELETE]);
}
protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token): bool
{
$user = $token->getUser();
if (!$user instanceof User) {
return false;
}
// If user is master admin, grant all permissions
if ($user->isMasterAdmin()) {
return true;
}
switch ($attribute) {
case self::CREATE:
return $this->canCreate($user, $subject);
case self::EDIT:
case self::DELETE:
return $this->canEditOrDelete($user, $subject);
}
return false;
}
private function canCreate(User $user, Discussion $discussion): bool
{
if (!$discussion->getSite()) {
return false;
}
// Check if user has access to the discussion's site
foreach ($user->getUserSites() as $userSite) {
if ($userSite->getSite()->getId() === $discussion->getSite()->getId()) {
return true;
}
}
return false;
}
private function canEditOrDelete(User $user, Discussion $discussion): bool
{
// Check if user is associated with the discussion's site
foreach ($user->getUserSites() as $userSite) {
if ($userSite->getSite()->getId() === $discussion->getSite()->getId()) {
return true;
}
}
// Creator of the discussion can always edit/delete their own discussions
if ($discussion->getUser() && $discussion->getUser()->getId() === $user->getId()) {
return true;
}
return false;
}
}