src/Security/Voters/ClientVoter.php line 17

Open in your IDE?
  1. <?php
  2. namespace App\Security\Voters;
  3. use App\Domain\Exception\Restrict\RestrictException;
  4. use App\Services\Accounts\ChildAccountService;
  5. use App\Services\Clients\ClientSystemState\ClientSystemStateService;
  6. use App\Entity\Client;
  7. use App\Entity\CompanyPerson;
  8. use App\Entity\OA2User;
  9. use App\Repository\ClientAccountRepository;
  10. use App\Repository\ClientRepository;
  11. use App\Repository\CompanyPersonRepository;
  12. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  13. use Symfony\Component\Security\Core\Authorization\Voter\Voter;
  14. class ClientVoter extends Voter
  15. {
  16.     public const MODE_READ 'read';
  17.     public const MODE_UPDATE 'update';
  18.     public const MODE_DELETE 'delete';
  19.     public const CAN_OPEN_ACCOUNTS 'can_open_accounts';
  20.     public const CAN_GRANT_PERMISSIONS 'can_grant_permissions';
  21.     public const CAN_ADD_COMPANY_PERSONS 'can_add_company_persons';
  22.     public const CAN_CHANGE_COMPANY_ACCOUNT_LIMITS 'can_change_company_account_limits';
  23.     public const CAN_MAKE_CLUSTERS 'can_make_clusters';
  24.     public const IN_COMPANY 'in_company';
  25.     public const CAN_VIEW_SHAREHOLDERS 'can_view_shareholders';
  26.     public const CAN_ADD_SHAREHOLDERS 'can_add_shareholders';
  27.     public const CAN_UPDATE_COMPANY 'can_update_company';
  28.     public const CAN_CREATE_COMPANY 'can_create_company';
  29.     /**
  30.      * @var ClientRepository
  31.      */
  32.     private $clientRepository;
  33.     /**
  34.      * @var ClientAccountRepository
  35.      */
  36.     private $clientAccountRepository;
  37.     /**
  38.      * @var CompanyPersonRepository
  39.      */
  40.     private $companyPersonRepository;
  41.     /**
  42.      * @var ClientSystemStateService
  43.      */
  44.     private $systemStateService;
  45.     private $childAccountService;
  46.     public function __construct(
  47.         ClientRepository $clientRepository,
  48.         CompanyPersonRepository $companyPersonRepository,
  49.         ClientAccountRepository $clientAccountRepository,
  50.         ChildAccountService $childAccountService,
  51.         ClientSystemStateService $systemStateService
  52.     ) {
  53.         $this->clientRepository $clientRepository;
  54.         $this->companyPersonRepository $companyPersonRepository;
  55.         $this->clientAccountRepository $clientAccountRepository;
  56.         $this->childAccountService $childAccountService;
  57.         $this->systemStateService $systemStateService;
  58.     }
  59.     protected function supports($attribute$subject)
  60.     {
  61.         if (!in_array($attribute$this->getSupportedPermissions())) {
  62.             return false;
  63.         }
  64.         // only vote on Post objects inside this voter
  65.         return !(!$subject instanceof Client)
  66.          ;
  67.     }
  68.     protected function voteOnAttribute($attribute$subjectTokenInterface $token)
  69.     {
  70.         if (!in_array($attribute$this->getSupportedPermissions())) {
  71.             return false;
  72.         }
  73.         /** @var Client $ownerClient */
  74.         $ownerClient $subject;
  75.         /** @var Client $currentClient */
  76.         $currentClient $this->getCurrentClient($token);
  77.         if (!$currentClient) {
  78.             return false;
  79.         }
  80.         // Its a workaround for shareholders functionality
  81.         // Specially for that endpoints we need check company relation without checking company write permissions
  82.         if ($attribute == self::CAN_VIEW_SHAREHOLDERS) {
  83.             return $this->inCompany($currentClient$ownerClient);
  84.         }
  85.         if ($attribute == self::CAN_ADD_SHAREHOLDERS) {
  86.             if (!$this->allowUseSystem($currentClient)) {
  87.                 return false;
  88.             }
  89.             return $this->inCompany($currentClient$ownerClient);
  90.         }
  91.         if ($attribute === self::CAN_UPDATE_COMPANY) {
  92.             return $this->canGrantPermissions($currentClient$ownerClient);
  93.         }
  94.         if ($attribute !== self::MODE_READ) {
  95.             if (!$this->allowUseSystem($currentClient) || !$this->allowUseSystem($ownerClient)) {
  96.                 return false;
  97.             }
  98.         }
  99.         if ($ownerClient->getId() === $currentClient->getId()) {
  100.             return true;
  101.         }
  102.         if ($this->isChild($ownerClient$currentClient)) {
  103.             return true;
  104.         }
  105.         if ($attribute === self::IN_COMPANY) {
  106.             return $this->inCompany($currentClient$ownerClient);
  107.         }
  108.         if ($attribute === self::CAN_OPEN_ACCOUNTS) {
  109.             return $this->canOpenAccounts($currentClient$ownerClient);
  110.         }
  111.         if ($attribute === self::CAN_ADD_COMPANY_PERSONS) {
  112.             return $this->canAddCompanyPersons($currentClient$ownerClient);
  113.         }
  114.         if ($attribute === self::CAN_GRANT_PERMISSIONS) {
  115.             return $this->canGrantPermissions($currentClient$ownerClient);
  116.         }
  117.         if ($attribute === self::CAN_CHANGE_COMPANY_ACCOUNT_LIMITS) {
  118.             return $this->canChangeCompanyAccountLimits($currentClient$ownerClient);
  119.         }
  120.         if ($attribute === self::CAN_MAKE_CLUSTERS) {
  121.             return $this->canMakeClusters($currentClient$ownerClient);
  122.         }
  123.         // TODO: check owner rules!
  124.         $relationAccount $this->clientAccountRepository->findOneByOwnerClient($currentClient$ownerClient);
  125.         if ($relationAccount) {
  126.             return true;
  127.         }
  128.         $relationCompany $this->companyPersonRepository->findOneByOwnerClient($currentClient$ownerClient);
  129.         return (bool) ($relationCompany)
  130.          ;
  131.     }
  132.     private function isChild(Client $ownerClientClient $currentClient): bool
  133.     {
  134.         if (!$ownerClient->isPerson()) {
  135.             return false;
  136.         }
  137.         $parent $this->childAccountService->getValidParentClient($ownerClient->getPerson());
  138.         return (bool) ($parent && $parent->getId() === $currentClient->getId())
  139.          ;
  140.     }
  141.     private function canGrantPermissions(Client $currentClientClient $ownerClient): bool
  142.     {
  143.         /** @var CompanyPerson $relationCompany */
  144.         $relationCompany $this->companyPersonRepository->findOneByOwnerClient($currentClient$ownerClient);
  145.         return $relationCompany $relationCompany->getCanGrantPermissions() : false;
  146.     }
  147.     private function inCompany(Client $currentClientClient $companyClient)
  148.     {
  149.         /** @var CompanyPerson $relationCompany */
  150.         $relationCompany $this->companyPersonRepository->findOneByOwnerClient($currentClient$companyClient);
  151.         return (bool) $relationCompany;
  152.     }
  153.     private function canAddCompanyPersons(Client $currentClientClient $ownerClient): bool
  154.     {
  155.         /** @var CompanyPerson $relationCompany */
  156.         $relationCompany $this->companyPersonRepository->findOneByOwnerClient($currentClient$ownerClient);
  157.         return $relationCompany $relationCompany->getCanAddCompanyPersons() : false;
  158.     }
  159.     private function canOpenAccounts(Client $currentClientClient $ownerClient): bool
  160.     {
  161.         /** @var CompanyPerson $relationCompany */
  162.         $relationCompany $this->companyPersonRepository->findOneByOwnerClient($currentClient$ownerClient);
  163.         return $relationCompany $relationCompany->getCanOpenAccounts() : false;
  164.     }
  165.     private function canChangeCompanyAccountLimits(Client $currentClientClient $ownerClient): bool
  166.     {
  167.         /** @var CompanyPerson $relationCompany */
  168.         $relationCompany $this->companyPersonRepository->findOneByOwnerClient($currentClient$ownerClient);
  169.         return $relationCompany $relationCompany->getCanChangeCompanyAccountLimits() : false;
  170.     }
  171.     private function canMakeClusters(Client $currentClientClient $ownerClient): bool
  172.     {
  173.         /** @var CompanyPerson $relationCompany */
  174.         $relationCompany $this->companyPersonRepository->findOneByOwnerClient($currentClient$ownerClient);
  175.         return $relationCompany $relationCompany->getCanMakeClusters() : false;
  176.     }
  177.     private function allowUseSystem(Client $client)
  178.     {
  179.         try {
  180.             $this->systemStateService->allowUseSystem($client);
  181.             return true;
  182.         } catch (RestrictException $exception) {
  183.             return false;
  184.         }
  185.     }
  186.     private function getSupportedPermissions(): array
  187.     {
  188.         return [
  189.             self::MODE_READ,
  190.             self::MODE_UPDATE,
  191.             self::MODE_DELETE,
  192.             self::CAN_OPEN_ACCOUNTS,
  193.             self::CAN_GRANT_PERMISSIONS,
  194.             self::CAN_ADD_COMPANY_PERSONS,
  195.             self::CAN_CHANGE_COMPANY_ACCOUNT_LIMITS,
  196.             self::IN_COMPANY,
  197.             self::CAN_MAKE_CLUSTERS,
  198.             self::CAN_VIEW_SHAREHOLDERS,
  199.             self::CAN_ADD_SHAREHOLDERS,
  200.             self::CAN_UPDATE_COMPANY,
  201.             self::CAN_CREATE_COMPANY,
  202.         ];
  203.     }
  204.     private function getCurrentClient(TokenInterface $token): ?Client
  205.     {
  206.         /** @var OA2User $oa2User */
  207.         $oa2User $token->getUser();
  208.         if (!$oa2User instanceof OA2User || $oa2User->isBankUser()) {
  209.             return null// Client user only
  210.         }
  211.         return $this->clientRepository->findOneByOa2User($oa2User);
  212.     }
  213. }