<?php
namespace App\Security\Voter;
use App\Entity\Team;
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;
use Symfony\Component\Security\Core\User\UserInterface;
class TeamVoter extends Voter
{
public const VIEW = 'VIEW';
public const EDIT = 'EDIT';
public const DELETE = 'DELETE';
public const MANAGE_MEMBERS = 'MANAGE_MEMBERS';
public const MANAGE_SETTINGS = 'MANAGE_SETTINGS';
private $security;
public function __construct(Security $security)
{
$this->security = $security;
}
protected function supports(string $attribute, mixed $subject): bool
{
// if the attribute isn't one we support, return false
if (!in_array($attribute, [
self::VIEW,
self::EDIT,
self::DELETE,
self::MANAGE_MEMBERS,
self::MANAGE_SETTINGS
])) {
return false;
}
// only vote on `Team` objects
if (!$subject instanceof Team) {
return false;
}
return true;
}
protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool
{
$user = $token->getUser();
// if the user is anonymous, do not grant access
if (!$user instanceof UserInterface) {
return false;
}
// Admins and company managers can do anything
if ($this->security->isGranted('ROLE_ADMIN') || $this->security->isGranted('ROLE_COMPANY_MANAGER')) {
return true;
}
/** @var Team $team */
$team = $subject;
/** @var User $user */
$user = $token->getUser();
// Find the user's relationship with this team
$userTeam = null;
foreach ($team->getUserTeams() as $ut) {
if ($ut->getUser() === $user) {
$userTeam = $ut;
break;
}
}
// If user is not a member of the team, they can only view
if ($userTeam === null) {
return $attribute === self::VIEW;
}
// Check permissions based on role and requested action
switch ($attribute) {
case self::VIEW:
// All team members can view
return true;
case self::EDIT:
// Team captains, coaches, and managers can edit
return $userTeam->isTeamLeader();
case self::MANAGE_MEMBERS:
// Only coaches and managers can manage members
return $userTeam->canManageMembers();
case self::MANAGE_SETTINGS:
// Only managers can manage team settings
return $userTeam->canManageTeam();
case self::DELETE:
// Only managers can delete teams
return $userTeam->canManageTeam();
}
return false;
}
}