<?php
namespace App\Security;
use App\Entity\Vehicles;
use App\Entity\Users;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
use Doctrine\ORM\EntityManagerInterface;
class VehicleVoter extends Voter
{
const ACCESS= [
'vehicle_view_exit_permission' => 'vehicle_view_exit_permission',
'vehicle_edit_tech_info' => 'vehicle_edit_tech_info',
'other_missing_parts' => 'other_missing_parts',
'vehicle_sale_tax_fields' => 'vehicle_sale_tax_fields'
];
/**
* @var AccessDecisionManager|null
*/
protected $decisionManager;
/**
* @var EntityManager|null
*/
protected $entityManager;
/**
* DelegateVoter constructor.
* @param AccessDecisionManager|null $decisionManager
* @param EntityManager|null $entityManager
*/
public function __construct(AccessDecisionManagerInterface $decisionManager, EntityManagerInterface $entityManager)
{
$this->decisionManager = $decisionManager;
$this->entityManager = $entityManager;
}
/**
* determines if your voter should vote on the attribute/subject combination. If you return true,
* voteOnAttribute() will be called. Otherwise, your voter is done: some other voter should process this
*/
protected function supports($attribute, $subject)
{
// if the attribute isn't one we support, return false
if (!in_array($attribute, self::ACCESS)) {
return false;
}
// only vote on Vehicles objects inside this voter
if ($subject && !$subject instanceof Vehicles) {
return false;
}
return true;
}
/**
* If you return true from supports(), then this method is called. Your job is simple: return true to allow access
* and false to deny access
*/
protected function voteOnAttribute($attribute, $vehicle, TokenInterface $token)
{
$loggedinUser = $token->getUser();
$em = $this->entityManager;
$vehiclesRepo = $em->getRepository(Vehicles::class);
if (!$loggedinUser instanceof Users) {
return false; // the user must be logged in; if not, deny access
}
// ROLE_SUPER_ADMIN can do anything! The power! Calling decide() on the AccessDecisionManager is essentially the same
// as calling isGranted() from a controller or other places (it's just a little lower-level, which is necessary for a voter).
if ($this->decisionManager->decide($token, ['ROLE_SUPER_ADMIN'])) {
return true;
}
switch ($attribute) {
case self::ACCESS['vehicle_view_exit_permission']:
return $this->decisionManager->decide($token, ['ROLE_ADMIN']) && $vehiclesRepo->isVehicleAllowedForDelivering($vehicle);
case self::ACCESS['vehicle_edit_tech_info']:
return $this->decisionManager->decide($token, ['ROLE_VEHICLES_TECHNICIAN']); //only vehicles' technician can edit
case self::ACCESS['other_missing_parts']:
return $this->decisionManager->decide($token, ['ROLE_VEHICLES_TECHNICIAN']); //only vehicles' technician can edit
case self::ACCESS['vehicle_sale_tax_fields']:
return $this->decisionManager->decide($token, ['ROLE_ACCOUNT_MANAGER']);
}
throw new \LogicException('This code should not be reached!');
}
}