src/Security/UserVoter.php line 18

Open in your IDE?
  1. <?php
  2. namespace App\Security;
  3. use App\Entity\Company;
  4. use App\Entity\Location;
  5. use App\Entity\Role;
  6. use App\Entity\User;
  7. use App\Entity\UserLocation;
  8. use App\Enum\User\UserRestrictionsEnum;
  9. use Symfony\Component\HttpFoundation\RequestStack;
  10. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  11. use Symfony\Component\Security\Core\Authorization\Voter\Voter;
  12. use Symfony\Component\Security\Core\Security;
  13. class UserVoter extends Voter
  14. {
  15. /** @var Security */
  16. private $security;
  17. /** @var RequestStack */
  18. private $requestStack;
  19. public function __construct(Security $security, RequestStack $requestStack)
  20. {
  21. $this->security = $security;
  22. $this->requestStack = $requestStack;
  23. }
  24. public const CAN_ACCESS_BILLING_DATA = 'CAN_ACCESS_BILLING_DATA';
  25. public const CAN_ACCESS_COMPANIES_LOCATIONS = 'CAN_ACCESS_COMPANIES_LOCATIONS';
  26. public const CAN_ACCESS_USERS = 'CAN_ACCESS_USERS';
  27. public const CAN_GRANT_HATCH_ADMIN = 'CAN_GRANT_HATCH_ADMIN';
  28. public const CAN_SWITCH_USER = 'CAN_SWITCH_USER';
  29. public const HAS_ADMIN_ACCESS_NO_RESTRICTIONS = 'HAS_ADMIN_ACCESS_NO_RESTRICTIONS';
  30. public const USER_HAS_ROLE_HUMAN_RESOURCES = 'user_has_role_human_resources';
  31. public const VIEW_USERS_TRAININGS_AND_QUIZZES = 'VIEW_USERS_TRAININGS_AND_QUIZZES';
  32. protected function supports($attribute, $subject): bool
  33. {
  34. return in_array($attribute, [
  35. self::CAN_ACCESS_BILLING_DATA,
  36. self::CAN_ACCESS_COMPANIES_LOCATIONS,
  37. self::CAN_ACCESS_USERS,
  38. self::CAN_GRANT_HATCH_ADMIN,
  39. self::CAN_SWITCH_USER,
  40. self::HAS_ADMIN_ACCESS_NO_RESTRICTIONS,
  41. self::USER_HAS_ROLE_HUMAN_RESOURCES,
  42. self::VIEW_USERS_TRAININGS_AND_QUIZZES,
  43. ], true);
  44. }
  45. /**
  46. * @param $attribute
  47. * @param $subject
  48. * @param TokenInterface $token
  49. * @return bool
  50. */
  51. protected function voteOnAttribute($attribute, $subject, TokenInterface $token): bool
  52. {
  53. $user = $token->getUser();
  54. if (!$user instanceof User) {
  55. return false;
  56. }
  57. if ($attribute === self::CAN_GRANT_HATCH_ADMIN) {
  58. return in_array(strtolower($user->getUsername()) , ['megenos', 'crivera305']);
  59. }
  60. if ($attribute === self::USER_HAS_ROLE_HUMAN_RESOURCES && $subject instanceof Location) {
  61. return $user->hasRoleByCompany(Role::ROLE_NAME_HUMAN_RESOURCES, $subject->getCompany());
  62. }
  63. if ($attribute === self::CAN_SWITCH_USER) {
  64. return $this->handleImpersonation($user, $subject);
  65. }
  66. // at this point $attribute is VIEW_USERS_TRAININGS_AND_QUIZZES
  67. if ($attribute === self::VIEW_USERS_TRAININGS_AND_QUIZZES) {
  68. return $this->handleViewUsersTrainingsAndQuizzes($user, $subject);
  69. }
  70. if ($attribute === self::HAS_ADMIN_ACCESS_NO_RESTRICTIONS) {
  71. return $user->isHatchAdministrator() && !$user->hasRestrictions();
  72. }
  73. if ($attribute === self::CAN_ACCESS_COMPANIES_LOCATIONS) {
  74. return $user->isHatchAdministrator()
  75. && $user->hasRestriction(UserRestrictionsEnum::USER_RESTRICTION_COMPANIES_LOCATIONS);
  76. }
  77. if ($attribute === self::CAN_ACCESS_BILLING_DATA) {
  78. return $user->isHatchAdministrator()
  79. && $user->hasRestriction(UserRestrictionsEnum::USER_RESTRICTION_BILLING_DATA);
  80. }
  81. if ($attribute === self::CAN_ACCESS_USERS) {
  82. return $user->isHatchAdministrator()
  83. && $user->hasRestriction(UserRestrictionsEnum::USER_RESTRICTION_USERS);
  84. }
  85. return false;
  86. }
  87. /**
  88. * @param User $user
  89. * @param $subject
  90. * @return bool
  91. */
  92. protected function handleImpersonation(User $user, $subject): bool
  93. {
  94. if ($this->security->isGranted('ROLE_ADMIN')) {
  95. return true;
  96. } else {
  97. $request = $this->requestStack->getCurrentRequest();
  98. $routeParameters = $request->attributes->get('_route_params');
  99. if (isset($routeParameters['company'])) {
  100. $companies = $user->getCompanies();
  101. foreach ($companies as $company) {
  102. if ($routeParameters['company'] == $company->getId()){
  103. return $user->hasRoleByCompany(Role::ROLE_NAME_HUMAN_RESOURCES, $company);
  104. }
  105. }
  106. }
  107. if ($subject instanceof Company) {
  108. return $user->hasRoleByCompany(Role::ROLE_NAME_HUMAN_RESOURCES, $subject);
  109. }
  110. if (!$subject instanceof Location) {
  111. $userLocations = $user->getUserLocations();
  112. /** @var UserLocation $userLocation */
  113. foreach ($userLocations as $userLocation) {
  114. $location = $userLocation->getLocation();
  115. if (!isset($_REQUEST['locationId'])) {
  116. if ($location->isActive()) {
  117. $subject = $location;
  118. break;
  119. }
  120. } else if ($location->getId() == (int)$_REQUEST['locationId']) {
  121. $subject = $location;
  122. break;
  123. }
  124. }
  125. }
  126. if ($subject instanceof Location) {
  127. return $user->hasRoleByCompany(Role::ROLE_NAME_HUMAN_RESOURCES, $subject->getCompany());
  128. }
  129. return false;
  130. }
  131. }
  132. /**
  133. * @param User $user
  134. * @param $subject
  135. * @return bool
  136. */
  137. private function handleViewUsersTrainingsAndQuizzes(User $user, $subject): bool
  138. {
  139. if (!$subject instanceof Location) {
  140. return false;
  141. }
  142. //ANY ATTRIBUTE that makes it to here will return false if the condition below is met
  143. if (
  144. !$user->isAdminByCompany($subject->getCompany()) &&
  145. !$user->isSupervisorByCompany($subject->getCompany()) &&
  146. !$user->hasRoleByCompany(Role::ROLE_NAME_TJC_SURVEYOR, $subject->getCompany()) &&
  147. !$user->hasRoleByCompany(Role::ROLE_NAME_STATE_INSPECTOR, $subject->getCompany()) &&
  148. !$user->hasRoleByCompany(Role::ROLE_NAME_HUMAN_RESOURCES, $subject->getCompany())
  149. ) {
  150. return false;
  151. }
  152. return true;
  153. }
  154. }