ModuleVoter.php 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. <?php
  2. declare(strict_types=1);
  3. namespace App\Security\Voter;
  4. use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface;
  5. use App\Entity\Access\Access;
  6. use App\Entity\Organization\Organization;
  7. use App\Service\Security\Module;
  8. use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
  9. use Symfony\Component\Security\Core\Authentication\Token\NullToken;
  10. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  11. use Symfony\Component\Security\Core\Authorization\Voter\Voter;
  12. /**
  13. * Class ModuleVoter : permet d'assurer que la resource appelée est comprise dans l'un des modules de la structure
  14. * @package App\Security
  15. */
  16. class ModuleVoter extends Voter
  17. {
  18. const HAVING_MODULE = 'IS_HAVING_MODULE';
  19. public function __construct(private Module $module, private ResourceMetadataFactoryInterface $resourceMetadataFactory)
  20. { }
  21. protected function supports(string $attribute, $subject): bool
  22. {
  23. if (!in_array($attribute, [self::HAVING_MODULE])) {
  24. return false;
  25. }
  26. return true;
  27. }
  28. /**
  29. * @param string $attribute
  30. * @param mixed $subject
  31. * @param TokenInterface $token
  32. * @return bool
  33. * @throws \ApiPlatform\Core\Exception\ResourceClassNotFoundException
  34. */
  35. protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token): bool
  36. {
  37. if (!$subject->attributes->get('_api_resource_class') || !$resourceMetadata = $this->resourceMetadataFactory->create($subject->attributes->get('_api_resource_class'))) {
  38. throw new AccessDeniedHttpException(sprintf('Missing resource class'));
  39. }
  40. if ($token instanceof NullToken) {
  41. return false;
  42. }
  43. $module = $this->module->getModuleByResourceName($resourceMetadata->getShortName());
  44. //Check if there is a module for this entity : eq configuration problem
  45. if (null === $module) {
  46. throw new AccessDeniedHttpException(sprintf('There are no module for the entity (%s) !', $resourceMetadata->getShortName()));
  47. }
  48. /** @var Access $currentAccess */
  49. $currentAccess = $token->getUser();
  50. /** @var Organization $organization */
  51. $organization = $currentAccess->getOrganization();
  52. if (!$this->isOrganizationHaveThisModule($organization, $module)) {
  53. throw new AccessDeniedHttpException(
  54. sprintf("The organization doesn't have the module '%s'", $module)
  55. );
  56. }
  57. return true;
  58. }
  59. /**
  60. * Test si l'organisation possède le module parmis les modules possédés via le produit souscrit, les options souscrites
  61. * ou les modules possédées via des conditions particulières (isCmf par exemple)
  62. *
  63. * @param Organization $organization
  64. * @param string $module
  65. * @return bool
  66. */
  67. private function isOrganizationHaveThisModule(Organization $organization, string $module): bool{
  68. $organizationModules = $this->module->getOrganizationModules($organization);
  69. return in_array($module, $organizationModules);
  70. }
  71. }