src/Security/Voter/Profile/ProfileVoter.php line 16

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace App\Security\Voter\Profile;
  4. use App\Model\User\Entity\User\Role\Permission;
  5. use App\Model\User\Entity\User\Role\RoleConstants;
  6. use App\ReadModel\Profile\DetailView;
  7. use App\Security\UserIdentity;
  8. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  9. use Symfony\Component\Security\Core\Authorization\Voter\Voter;
  10. use Symfony\Component\Security\Core\Exception\AccessDeniedException;
  11. use Symfony\Component\Security\Core\Security;
  12. class ProfileVoter extends Voter
  13. {
  14.     public const PROFILE_CREATE = 'profile_create';
  15.     public const PROFILE_EDIT = 'profile_edit';
  16.     public const PROFILE_INDEX = 'profile_index';
  17.     // Только просмотр карточки профиля (страница profile). PROFILE_INDEX дополнительно
  18.     // используется для доступа к изменению профиля, поэтому для просмотра отдельный атрибут.
  19.     public const PROFILE_SHOW = 'profile_show';
  20.     public const PROFILE_RECALL = 'profile_recall';
  21.     public const ORGANIZATION_USERS_LIST = 'organization_users_list';
  22.     public const ORGANIZATION_POSITION_LIST = 'organization_position_list';
  23.     public const ORGANIZATION_USERS_CREATE = 'organization_users_create';
  24.     public const ORGANIZATION_USERS_DELETE = 'organization_users_delete';
  25.     public const CONTRACTS_LIST = 'contracts_list';
  26.     public const PROCEDURE_MY_LIST = 'procedure_my_list';
  27.     private Security $security;
  28.     public function __construct(Security $security)
  29.     {
  30.         $this->security = $security;
  31.     }
  32.     protected function supports(string $attribute, $subject): bool
  33.     {
  34.         return in_array($attribute, [
  35.                 self::PROFILE_CREATE,
  36.                 self::PROFILE_EDIT,
  37.                 self::PROFILE_INDEX,
  38.                 self::PROFILE_SHOW,
  39.                 self::PROFILE_RECALL,
  40.                 self::ORGANIZATION_USERS_LIST,
  41.                 self::ORGANIZATION_POSITION_LIST,
  42.                 self::ORGANIZATION_USERS_CREATE,
  43.                 self::ORGANIZATION_USERS_DELETE,
  44.                 self::CONTRACTS_LIST,
  45.                 self::PROCEDURE_MY_LIST
  46.             ], true);
  47.     }
  48.     /**
  49.      * @param string $attribute
  50.      * @param $subject
  51.      * @param TokenInterface $token
  52.      * @return bool
  53.      */
  54.     protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token): bool
  55.     {
  56.         // Moderators have full access
  57.         if ($this->security->isGranted('ROLE_MODERATOR')) {
  58.             return true;
  59.         }
  60.         if ($attribute === self::PROFILE_SHOW) {
  61.             // Расширенный менеджер может только просматривать любой профиль
  62.             if ($this->security->isGranted('ROLE_MANAGER_EXTENDED')) {
  63.                 return true;
  64.             }
  65.             $attribute = self::PROFILE_INDEX;
  66.         }
  67.         $user = $token->getUser();
  68.         // Only authenticated UserIdentity can proceed
  69.         if (!$user instanceof UserIdentity) {
  70.             return false;
  71.         }
  72.         $role = (new RoleConstants($user->getRole()));
  73.         if ($role->isOrganizerUser()) {
  74.             if ($this->checkPermissionEmployee($user, $attribute, $subject) === false) {
  75.                 return $this->handleException();
  76.             }
  77.         }
  78.         // Check specific permissions
  79.         switch ($attribute) {
  80.             case self::PROFILE_INDEX:
  81.                 if (!$this->isOwnerProfile($subject, $user)) {
  82.                     return $this->handleException();
  83.                 }
  84.                 break;
  85.             case self::PROFILE_EDIT:
  86.                 // Only profile owner can proceed
  87.                 if (!$this->isOwnerProfile($subject, $user)) {
  88.                     return $this->handleException();
  89.                 }
  90.                 return $user->isPermission(Permission::PROFILE_EDIT);
  91.                 break;
  92.             case self::CONTRACTS_LIST:
  93.                 // Only profile owner can proceed
  94.                 if (!$this->isOwnerProfile($subject, $user)) {
  95.                     return $this->handleException();
  96.                 }
  97.                 return $user->isPermission(Permission::CONTRACTS_LIST);
  98.                 break;
  99.             case self::PROCEDURE_MY_LIST:
  100.                 if ($subject->id !== $user->getProfileId()) {
  101.                     return $this->handleException();
  102.                 }
  103.                 break;
  104.         }
  105.         return true;
  106.     }
  107.     private function handleException()
  108.     {
  109.         throw new AccessDeniedException('Доступ запрещен. У вас недостаточно прав для совершения этого действия.');
  110.     }
  111.     /**
  112.      * Проверка разрешений сотрудника
  113.      * @param UserIdentity $user
  114.      * @param string $attribute
  115.      * @param DetailView $subject
  116.      * @return bool
  117.      */
  118.     private function checkPermissionEmployee(UserIdentity $user, string $attribute, DetailView $subject): bool
  119.     {
  120.         switch ($attribute) {
  121.             case self::PROFILE_INDEX:
  122.                 if (!$this->isOwnerProfile($subject, $user)) {
  123.                     return false;
  124.                 }
  125.                 return true;
  126.                 break;
  127.             case self::PROFILE_EDIT:
  128.                 if (!$this->isOwnerProfile($subject, $user)) {
  129.                     return false;
  130.                 }
  131.                 return $user->isPermission(Permission::PROFILE_EDIT);
  132.                 break;
  133.             case self::ORGANIZATION_USERS_LIST:
  134.                 // Only profile owner can proceed
  135.                 if (!$this->isOwnerProfile($subject, $user)) {
  136.                     return false;
  137.                 }
  138.                 return $user->isPermission(Permission::ORGANIZATION_USERS_LIST);
  139.                 break;
  140.             case self::ORGANIZATION_POSITION_LIST:
  141.                 if (!$this->isOwnerProfile($subject, $user)) {
  142.                     return false;
  143.                 }
  144.                 return $user->isPermission(Permission::ORGANIZATION_POSITION_LIST);
  145.                 break;
  146.             case self::ORGANIZATION_USERS_CREATE:
  147.                 if (!$this->isOwnerProfile($subject, $user)) {
  148.                     return false;
  149.                 }
  150.                 return $user->isPermission(Permission::ORGANIZATION_USERS_CREATE);
  151.                 break;
  152.             case self::ORGANIZATION_USERS_DELETE:
  153.                 if (!$this->isOwnerProfile($subject, $user)) {
  154.                     return false;
  155.                 }
  156.                 return $user->isPermission(Permission::ORGANIZATION_USERS_DELETE);
  157.                 break;
  158.             case self::CONTRACTS_LIST:
  159.                 if (!$this->isOwnerProfile($subject, $user)) {
  160.                     return false;
  161.                 }
  162.                 return $user->isPermission(Permission::CONTRACTS_LIST);
  163.                 break;
  164.             case self::PROCEDURE_MY_LIST:
  165.                 if ($subject->id !== $user->getProfileId()) {
  166.                     return $this->handleException();
  167.                 }
  168.                 return true;
  169.                 break;
  170.             default:
  171.                 return false;
  172.         }
  173.     }
  174.     private function isOwnerProfile(DetailView $subject, UserIdentity $user): bool
  175.     {
  176.         // Only profile owner can proceed
  177.         if ($subject->id !== $user->getProfileId()) {
  178.             return false;
  179.         }
  180.         return true;
  181.     }
  182. }