ModuleVoter.php 3.0 KB

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