<?php
namespace AppBundle\Security;
use AppBundle\Entity\ContactPortalUser;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
/**
* This class handle security access of portal API.
*/
class PortalVoter extends Voter
{
/**
* Most API need an access to a LawFirm, so use the PORTAL_ACCESS_LAW_FIRM attribute
*
* In API we must provide the query law_firm_id
* With annotation @Security('PORTAL_ACCESS_LAW_FIRM')
* In other cases (command, consumer, ...) we must provide the subject
* With Security or AuthorizationChecker service ->isGranted('PORTAL_ACCESS_LAW_FIRM', $lawFirmId)
*/
const PORTAL_ACCESS_LAW_FIRM = 'PORTAL_ACCESS_LAW_FIRM';
/**
* @var RequestStack
*/
private $requestStack;
/**
* PortalVoter constructor.
* @param RequestStack $requestStack
*/
public function __construct(RequestStack $requestStack)
{
$this->requestStack = $requestStack;
}
/**
* {@inheritdoc}
*/
protected function supports($attribute, $subject)
{
if (self::PORTAL_ACCESS_LAW_FIRM === $attribute) {
return true;
}
return false;
}
/**
* {@inheritdoc}
*/
protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
{
$user = $token->getUser();
if (!$user instanceof ContactPortalUser) {
return false;
}
switch ($attribute) {
case self::PORTAL_ACCESS_LAW_FIRM:
$request = $this->requestStack->getCurrentRequest();
if (null === $request && null === $subject) {
throw new \LogicException('No request found, the subject must be a law firm id');
}
// We can check this attribute with the law_firm_id as subject,
// otherwise we take the law_firm_id in request
$lawFirmId = $subject ?? $request->query->getInt('law_firm_id');
if (null === $lawFirmId || !is_int($lawFirmId)) {
return false;
}
return $user->hasAccessToLawFirm($lawFirmId);
default:
throw new \LogicException('This code should not be reached');
}
}
}