<?php
namespace App\Security;
use App\Entity\Users;
use App\Entity\VehicleClients;
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;
use App\Service\UserHelper;
class ClientVoter extends Voter
{
const ACCESS= [
'client_vehicles_list' => 'client_vehicles_list',
'client_view_delegations' => 'client_view_delegations',
'client_add_delegations' => 'client_add_delegations',
'client_bidding' => 'client_bidding',
'client_current_auction_deposit' => 'client_current_auction_deposit',
'client_transactions' => 'client_transactions',
'client_bonds' => 'client_bonds',
'client_financial' => 'client_financial'];
/**
* @var AccessDecisionManager|null
*/
protected $decisionManager;
/**
* @var EntityManager|null
*/
protected $entityManager;
/**
* @var EntityManager|null
*/
protected $userHelper;
/**
* DelegateVoter constructor.
* @param AccessDecisionManager|null $decisionManager
* @param EntityManager|null $entityManager
*/
public function __construct(AccessDecisionManagerInterface $decisionManager, EntityManagerInterface $entityManager, UserHelper $userHelper)
{
$this->decisionManager = $decisionManager;
$this->entityManager = $entityManager;
$this->userHelper = $userHelper;
}
/**
* 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;
}
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, $subject, TokenInterface $token)
{
$user = $token->getUser();
if (!$user 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;
}
// you know $subject is a VehicleClient object, thanks to supports
/** @var VehicleClients $vehicleClient */
$vehicleClient = $subject;
switch ($attribute) {
case self::ACCESS['client_vehicles_list']:
return $vehicleClient->getUser() == $user || $this->isDelegated($vehicleClient, $user) || $this->decisionManager->decide($token, ['ROLE_ADMIN']);
case self::ACCESS['client_view_delegations']:
return $this->decisionManager->decide($token, ['ROLE_ADMIN']);
case self::ACCESS['client_add_delegations']:
return $this->decisionManager->decide($token, ['ROLE_ADMIN']);
case self::ACCESS['client_transactions']:
case self::ACCESS['client_bonds']:
return $this->decisionManager->decide($token, ['ROLE_ADMIN']);
case self::ACCESS['client_bidding']:
return $vehicleClient->getUser() == $user || $this->isDelegated($vehicleClient, $user);
case self::ACCESS['client_current_auction_deposit']:
return $this->decisionManager->decide($token, ['ROLE_ADMIN']);
case self::ACCESS['client_financial']:
return $this->decisionManager->decide($token, ['ROLE_ACCOUNTANT']);
}
throw new \LogicException('This code should not be reached!');
}
/**
*/
private function isDelegated(VehicleClients $delegator, Users $user)
{
// $em = $this->entityManager;
// $delegations = $em->getRepository(ClientsDelegation::class)->findByDelegated($user->getUserId());
$delegations= $this->userHelper->getUserDelegators($user);
foreach($delegations as $delegation){
if($delegation->getDelegator() &&
($delegation->getDelegator()->getCompany()->getCompanyId() == $delegator->getClientId()
|| $delegation->getDelegator()->getUser() == $delegator->getClientId() )
){
return true;
}
}
return false;
}
/**
*/
private function canView(Post $post, User $user)
{
// if they can edit, they can view
if ($this->canEdit($post, $user)) {
return true;
}
// the Post object could have, for example, a method isPrivate()
// that checks a boolean $private property
return !$post->isPrivate();
}
}