<?php
namespace App\Security\Voter;
use App\Entity\CdpEntityInterface;
use App\Exception\Security\CurrentAccountWasNotSetException;
use App\Metadata\SchemaFactory;
use App\Metadata\Schema\Schema;
use App\Security\Voter\CdpVoterHelperTrait;
use App\Service\CdpService;
use Cdp\Transverse\Enumerations\Entity\Fond\AbstractEnumerations as FondAbstractEnumerations;
use Cdp\Transverse\Enumerations\Security\Voter\FondEnumerationCRUDVoter;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
/**
* Le seul voter Symfony
* C'est lui qui va décider de router la decision sur le SchemaPermissionVoter ou sur un CdpEntityVoterInterface dédié
*/
class MasterVoter extends Voter
{
use CdpVoterHelperTrait;
/**
* @var CdpService
*/
protected $cdp;
/**
* @var CdpEntityVoter[]
*/
protected $cdpEntityVoters = [];
/**
* @var FondEnumerationCRUDVoter
*/
protected $fondEnumerationCRUDVoter;
/**
* @var SchemaPermissionVoter
*/
protected $schemaPermissionVoter;
public function __construct(CdpService $cdp, SchemaFactory $schemaFactory, iterable $cdpEntityVoters, FondEnumerationCRUDVoter $fondEnumerationCRUDVoter, SchemaPermissionVoter $schemaPermissionVoter)
{
$this->cdp = $cdp;
$this->schemaFactory = $schemaFactory;
foreach ($cdpEntityVoters as $cdpEntityVoter) {
$this->cdpEntityVoters[$cdpEntityVoter->getEntityClass()] = $cdpEntityVoter;
}
$this->fondEnumerationCRUDVoter = $fondEnumerationCRUDVoter;
$this->schemaPermissionVoter = $schemaPermissionVoter;
}
protected function getCurrentAccount()
{
return $this->cdp->getCurrentAccount();
}
protected function supports($attribute, $subject)
{
// Extract classname
try {
$class = $this->extractSubjectClass($subject);
} catch (\InvalidArgumentException $e) {
return false;
}
// Only CdpEntities
if (!is_subclass_of($class, CdpEntityInterface::class)) {
return false;
}
// Extract action and context
try {
list($action, $context) = $this->extractRoleAndContext($attribute);
} catch (\InvalidArgumentException $e) {
return false;
}
try {
$currentAccount = $this->getCurrentAccount();
} catch (CurrentAccountWasNotSetException $e) {
$currentAccount = null;
}
// Check si il n'existe pas un cdpvoter dédié
if (array_key_exists($class, $this->cdpEntityVoters)) {
return $this->cdpEntityVoters[$class]->supportsAction($action, $context, $subject, $currentAccount);
}
// Ne peut pas être un cdpEntityVoters car il gère une abstract
if (is_subclass_of($class, FondAbstractEnumerations::class)) {
return $this->fondEnumerationCRUDVoter->supportsAction($action, $context, $subject, $currentAccount);
}
// Sinon on retourne les permissions de schema + account rights
return $this->schemaPermissionVoter->supportsAction($action, $context, $subject, $currentAccount);
}
protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
{
$class = $this->extractSubjectClass($subject);
list($action, $context) = $this->extractRoleAndContext($attribute);
try {
$currentAccount = $this->getCurrentAccount();
} catch (CurrentAccountWasNotSetException $e) {
$currentAccount = null;
}
// Check si il n'existe pas un cdpvoter dédié
if (array_key_exists($class, $this->cdpEntityVoters)) {
return $this->cdpEntityVoters[$class]->voteAction($action, $context, $subject, $currentAccount);
}
if (is_subclass_of($class, FondAbstractEnumerations::class)) {
return $this->fondEnumerationCRUDVoter->voteAction($action, $context, $subject, $currentAccount);
}
// Sinon on retourne les permissions de schema + account rights
return $this->schemaPermissionVoter->voteAction($action, $context, $subject, $currentAccount);
}
}