Loading config/merged/perimetre.config.php +13 −0 Original line number Diff line number Diff line <?php use UnicaenPrivilege\Guard\PrivilegeController; use UnicaenPrivilege\Provider\Perimetre\Rules\StructureRuleProvider; use UnicaenPrivilege\Provider\Perimetre\Rules\StructureRuleProviderFactory; use UnicaenPrivilege\Service\Perimetre\PerimetreCategorieService; use UnicaenPrivilege\Service\Perimetre\PerimetreCategorieServiceFactory; use UnicaenPrivilege\Service\Perimetre\PerimetreService; use UnicaenPrivilege\Service\Perimetre\PerimetreServiceFactory; return [ 'unicaen-perimetre' => [ /** * Liste des périmètres (catégories) utilisés et du service associé fournissant la règle de gestion du périmètre. * NB: le service fournisseur doit implémenter l'interface @see PerimetreRuleInterface sinon il ne sera pas associé. */ 'rule_providers' => [ 'structure' => StructureRuleProvider::class, ], ], 'bjyauthorize' => [ 'guards' => [ PrivilegeController::class => [ Loading Loading @@ -66,6 +78,7 @@ return [ 'factories' => [ PerimetreService::class => PerimetreServiceFactory::class, PerimetreCategorieService::class => PerimetreCategorieServiceFactory::class, StructureRuleProvider::class => StructureRuleProviderFactory::class ], ], Loading config/unicaen-perimetre.global.php.dist 0 → 100644 +60 −0 Original line number Diff line number Diff line <?php use UnicaenPrivilege\Entity\Db\Perimetre; use UnicaenPrivilege\Entity\Db\Privilege; use UnicaenPrivilege\Provider\Privilege\PrivilegePrivileges; use UnicaenPrivilege\Provider\Rule\PrivilegeRuleProvider; use UnicaenPrivilege\Service\Privilege\PrivilegeService; $settings = [ /** * L'entité associée aux périmètres peut être spécifiée via la clef de configuration ['unicaen_auth']['perimetre_entity_class'] * Si elle est manquante alors la classe @see \UnicaenPrivilege\Entity\Db\Perimetre est utilisée * NB: la classe spécifiée doit hériter de @see \UnicaenPrivilege\Entity\Db\AbstractPerimetre */ 'perimetre_entity_class' => Perimetre::class, 'enable_perimetres' => true, ]; $config = [ 'unicaen-auth' => $settings, ]; if ($settings['enable_perimetres']) { $perimetres = [ 'unicaen-perimetre' => [ /** * Liste des périmètres (catégories) utilisés et du service associé fournissant la règle de gestion du périmètre. * NB: le service fournisseur doit implémenter l'interface @see PerimetreRuleInterface sinon il ne sera pas associé. */ 'rule_providers' => [ ], ], 'navigation' => [ 'default' => [ 'home' => [ 'pages' => [ 'droits' => [ 'pages' => [ [ 'label' => "Gérer les périmètres", 'title' => "Gérer les périmetres", 'route' => 'unicaen-perimetre', 'resource' => PrivilegePrivileges::getResourceId(PrivilegePrivileges::PRIVILEGE_VOIR), ], ], ], ], ], ], ], ]; } else { $perimetres = []; } return array_merge_recursive($config, $perimetres); No newline at end of file config/unicaen-privilege.global.php.dist +11 −14 Original line number Diff line number Diff line Loading @@ -8,14 +8,6 @@ use UnicaenPrivilege\Service\Privilege\PrivilegeService; $settings = [ 'unicaen-auth' => [ 'enable_privileges' => true, ], ]; if ($settings['unicaen-auth']['enable_privileges']) { $privileges = [ 'unicaen-auth' => [ /** * L'entité associée aux privilèges peut être spécifiée via la clef de configuration ['unicaen_auth']['privilege_entity_class'] * Si elle est manquante alors la classe @see \UnicaenPrivilege\Entity\Db\Privilege est utilisée Loading @@ -24,12 +16,17 @@ if ($settings['unicaen-auth']['enable_privileges']) { 'privilege_entity_class' => Privilege::class, /** * L'entité associée aux périmètres peut être spécifiée via la clef de configuration ['unicaen_auth']['perimetre_entity_class'] * Si elle est manquante alors la classe @see \UnicaenPrivilege\Entity\Db\Perimetre est utilisée * NB: la classe spécifiée doit hériter de @see \UnicaenPrivilege\Entity\Db\AbstractPerimetre * Activation des privilèges */ 'perimetre_entity_class' => Perimetre::class ], 'enable_privileges' => true, ]; $config = [ 'unicaen-auth' => $settings, ]; if ($settings['enable_privileges']) { $privileges = [ 'bjyauthorize' => [ Loading Loading @@ -69,4 +66,4 @@ if ($settings['unicaen-auth']['enable_privileges']) { $privileges = []; } return array_merge_recursive($settings, $privileges); No newline at end of file return array_merge_recursive($config, $privileges); No newline at end of file src/UnicaenPrivilege/Guard/PrivilegeController.php +92 −4 Original line number Diff line number Diff line Loading @@ -2,9 +2,16 @@ namespace UnicaenPrivilege\Guard; use Application\Entity\Db\UtilisateurRoleLinker; use BjyAuthorize\Guard\Controller; use UnicaenAuthentification\Service\Traits\UserContextServiceAwareTrait; use UnicaenPrivilege\Exception\RuntimeException; use UnicaenPrivilege\Provider\Perimetre\PerimetreProviderAwareTrait; use UnicaenPrivilege\Provider\Perimetre\Rules\PerimetreRuleInterface; use UnicaenPrivilege\Provider\Privilege\PrivilegeProviderAwareTrait; use UnicaenApp\Traits\SessionContainerTrait; use UnicaenUtilisateur\Entity\Db\UserInterface; use UnicaenUtilisateur\Entity\Db\UserRoleInterface; use UnicaenUtilisateur\Service\RechercheIndividu\RechercheIndividuServiceInterface; /** * Description of PrivilegeController Loading @@ -14,14 +21,35 @@ use UnicaenApp\Traits\SessionContainerTrait; class PrivilegeController extends Controller { use PrivilegeProviderAwareTrait; use SessionContainerTrait; use PerimetreProviderAwareTrait; use UserContextServiceAwareTrait; /** * @var PerimetreRuleInterface[] */ public $perimetresRules; /** * @param PerimetreRuleInterface[] $perimetresRules * @return self */ public function setPerimetresRules($perimetresRules) { $this->perimetresRules = $perimetresRules; return $this; } /** * {@inheritdoc} */ public function processConfig() { // filtrage des rôles en fonction des privilèges $this->config = $this->privilegesToRoles($this->config); // filtrage des rôles en fonction des périmètres $this->config = $this->perimetresToRoles($this->config); parent::processConfig(); } Loading @@ -36,12 +64,10 @@ class PrivilegeController extends Controller foreach ($rules as $index => $rule) { if (isset($rule['privileges'])) { $rolesCount = 0; $privileges = (array)$rule['privileges']; $rule['roles'] = isset($rule['roles']) ? (array)$rule['roles'] : []; foreach ($pr as $privilege => $roles) { if (in_array($privilege, $privileges)) { $rolesCount += count($roles); $rule['roles'] = array_unique(array_merge($rule['roles'], $roles)); } } Loading @@ -57,6 +83,68 @@ class PrivilegeController extends Controller return $rules; } protected function perimetresToRoles(array $rules): array { /** @var UserInterface $user */ $user = $this->serviceUserContext->getDbUser(); // liste des périmètres et des rôles associés $perimetresRoles = $this->getPerimetreProvider()->getPerimetresRoles(); // parcours de la liste des règles "bjyauthorize/guards" foreach ($rules as $index => $rule) { if(isset($rule['perimetres']) && $user) { $rulePerimetres = (array)$rule['perimetres']; // parcours de toutes les périmètres (catégories) foreach ($perimetresRoles as $perimetreCateg => $pr) { // vérification que le périmètre est appelé dans la règle if(in_array($perimetreCateg, $rulePerimetres)) { // parcours des rôles autorisés pour la règle foreach($rule['roles'] as $role) { // vérification que le rôle fait partie des rôles associés au périmètre if(in_array($role, $pr)) { // récupération des droits de l'utilisateur pour le rôle et le périmètre $userExactRole = $user->getFullRoles()->filter(function ($r) use ($role, $perimetreCateg) { /** @var UserRoleInterface $r */ $pc = $r->getPerimetreCategorie(); return $r->getRole()->getRoleId() === $role && ($pc ? $pc->getCode() : null) === $perimetreCateg; }); // si une règle existe if($userExactRole->count() === 1) { $ur = $userExactRole->current(); /** vérification que le périmètre a un service implémentant @see PerimetreRuleInterface associé dans la config */ if(array_key_exists($perimetreCateg, $this->perimetresRules)) { /** @var PerimetreRuleInterface $service */ $service = $this->perimetresRules[$perimetreCateg]; // vérification de la règle if($service->checkRule($ur->getPerimetre())) { continue; } } else { throw new RuntimeException(sprintf('Le périmètre "%s" n\'a aucun service associé défini dans la configuration : "unicaen-perimetre" > "rule_providers"', $perimetreCateg)); } } // suppression du rôle des rôles autorisés pour cette règle $key = array_search($role, $rule['roles']); unset($rule['roles'][$key]); } } } } unset($rule['perimetres']); if (0 < count($rule['roles'])) { $rules[$index] = $rule; } else { unset($rules[$index]); } } } return $rules; } public static function getResourceId($controller, $action = null) : string { if (isset($action)) { Loading src/UnicaenPrivilege/Guard/PrivilegeControllerFactory.php +26 −1 Original line number Diff line number Diff line Loading @@ -3,20 +3,45 @@ namespace UnicaenPrivilege\Guard; use Interop\Container\ContainerInterface; use UnicaenAuthentification\Service\UserContext; use UnicaenPrivilege\Provider\Perimetre\PerimetreProviderInterface; use UnicaenPrivilege\Provider\Perimetre\Rules\PerimetreRuleInterface; use UnicaenPrivilege\Provider\Privilege\PrivilegeProviderInterface; use UnicaenPrivilege\Service\Perimetre\PerimetreCategorieService; use UnicaenPrivilege\Service\Privilege\PrivilegeService; class PrivilegeControllerFactory { public function __invoke(ContainerInterface $container) : PrivilegeController { /** @var PrivilegeProviderInterface $privilegeService */ /** * @var PrivilegeProviderInterface $privilegeProvider * @var PerimetreProviderInterface $perimetreProvider * @var UserContext $userContextService */ $config = $container->get('Config'); $perimetreConfig = $config['unicaen-perimetre']; $privilegeProvider = $container->get(PrivilegeService::class); $perimetreProvider = $container->get(PerimetreCategorieService::class); $userContextService = $container->get(UserContext::class); $rules = []; // NB: l'injection des vraies rules est faite par \BjyAuthorize\Service\BaseProvidersServiceFactory $perimetresRules = []; if(array_key_exists('rule_providers', $perimetreConfig)) { foreach($perimetreConfig['rule_providers'] as $key => $provider) { $service = $container->get($provider); if($service instanceof PerimetreRuleInterface) { $perimetresRules[$key] = $service; } } } $instance = new PrivilegeController($rules, $container); $instance->setPrivilegeProvider($privilegeProvider); $instance->setPerimetreProvider($perimetreProvider); $instance->setPerimetresRules($perimetresRules); $instance->setServiceUserContext($userContextService); return $instance; } Loading Loading
config/merged/perimetre.config.php +13 −0 Original line number Diff line number Diff line <?php use UnicaenPrivilege\Guard\PrivilegeController; use UnicaenPrivilege\Provider\Perimetre\Rules\StructureRuleProvider; use UnicaenPrivilege\Provider\Perimetre\Rules\StructureRuleProviderFactory; use UnicaenPrivilege\Service\Perimetre\PerimetreCategorieService; use UnicaenPrivilege\Service\Perimetre\PerimetreCategorieServiceFactory; use UnicaenPrivilege\Service\Perimetre\PerimetreService; use UnicaenPrivilege\Service\Perimetre\PerimetreServiceFactory; return [ 'unicaen-perimetre' => [ /** * Liste des périmètres (catégories) utilisés et du service associé fournissant la règle de gestion du périmètre. * NB: le service fournisseur doit implémenter l'interface @see PerimetreRuleInterface sinon il ne sera pas associé. */ 'rule_providers' => [ 'structure' => StructureRuleProvider::class, ], ], 'bjyauthorize' => [ 'guards' => [ PrivilegeController::class => [ Loading Loading @@ -66,6 +78,7 @@ return [ 'factories' => [ PerimetreService::class => PerimetreServiceFactory::class, PerimetreCategorieService::class => PerimetreCategorieServiceFactory::class, StructureRuleProvider::class => StructureRuleProviderFactory::class ], ], Loading
config/unicaen-perimetre.global.php.dist 0 → 100644 +60 −0 Original line number Diff line number Diff line <?php use UnicaenPrivilege\Entity\Db\Perimetre; use UnicaenPrivilege\Entity\Db\Privilege; use UnicaenPrivilege\Provider\Privilege\PrivilegePrivileges; use UnicaenPrivilege\Provider\Rule\PrivilegeRuleProvider; use UnicaenPrivilege\Service\Privilege\PrivilegeService; $settings = [ /** * L'entité associée aux périmètres peut être spécifiée via la clef de configuration ['unicaen_auth']['perimetre_entity_class'] * Si elle est manquante alors la classe @see \UnicaenPrivilege\Entity\Db\Perimetre est utilisée * NB: la classe spécifiée doit hériter de @see \UnicaenPrivilege\Entity\Db\AbstractPerimetre */ 'perimetre_entity_class' => Perimetre::class, 'enable_perimetres' => true, ]; $config = [ 'unicaen-auth' => $settings, ]; if ($settings['enable_perimetres']) { $perimetres = [ 'unicaen-perimetre' => [ /** * Liste des périmètres (catégories) utilisés et du service associé fournissant la règle de gestion du périmètre. * NB: le service fournisseur doit implémenter l'interface @see PerimetreRuleInterface sinon il ne sera pas associé. */ 'rule_providers' => [ ], ], 'navigation' => [ 'default' => [ 'home' => [ 'pages' => [ 'droits' => [ 'pages' => [ [ 'label' => "Gérer les périmètres", 'title' => "Gérer les périmetres", 'route' => 'unicaen-perimetre', 'resource' => PrivilegePrivileges::getResourceId(PrivilegePrivileges::PRIVILEGE_VOIR), ], ], ], ], ], ], ], ]; } else { $perimetres = []; } return array_merge_recursive($config, $perimetres); No newline at end of file
config/unicaen-privilege.global.php.dist +11 −14 Original line number Diff line number Diff line Loading @@ -8,14 +8,6 @@ use UnicaenPrivilege\Service\Privilege\PrivilegeService; $settings = [ 'unicaen-auth' => [ 'enable_privileges' => true, ], ]; if ($settings['unicaen-auth']['enable_privileges']) { $privileges = [ 'unicaen-auth' => [ /** * L'entité associée aux privilèges peut être spécifiée via la clef de configuration ['unicaen_auth']['privilege_entity_class'] * Si elle est manquante alors la classe @see \UnicaenPrivilege\Entity\Db\Privilege est utilisée Loading @@ -24,12 +16,17 @@ if ($settings['unicaen-auth']['enable_privileges']) { 'privilege_entity_class' => Privilege::class, /** * L'entité associée aux périmètres peut être spécifiée via la clef de configuration ['unicaen_auth']['perimetre_entity_class'] * Si elle est manquante alors la classe @see \UnicaenPrivilege\Entity\Db\Perimetre est utilisée * NB: la classe spécifiée doit hériter de @see \UnicaenPrivilege\Entity\Db\AbstractPerimetre * Activation des privilèges */ 'perimetre_entity_class' => Perimetre::class ], 'enable_privileges' => true, ]; $config = [ 'unicaen-auth' => $settings, ]; if ($settings['enable_privileges']) { $privileges = [ 'bjyauthorize' => [ Loading Loading @@ -69,4 +66,4 @@ if ($settings['unicaen-auth']['enable_privileges']) { $privileges = []; } return array_merge_recursive($settings, $privileges); No newline at end of file return array_merge_recursive($config, $privileges); No newline at end of file
src/UnicaenPrivilege/Guard/PrivilegeController.php +92 −4 Original line number Diff line number Diff line Loading @@ -2,9 +2,16 @@ namespace UnicaenPrivilege\Guard; use Application\Entity\Db\UtilisateurRoleLinker; use BjyAuthorize\Guard\Controller; use UnicaenAuthentification\Service\Traits\UserContextServiceAwareTrait; use UnicaenPrivilege\Exception\RuntimeException; use UnicaenPrivilege\Provider\Perimetre\PerimetreProviderAwareTrait; use UnicaenPrivilege\Provider\Perimetre\Rules\PerimetreRuleInterface; use UnicaenPrivilege\Provider\Privilege\PrivilegeProviderAwareTrait; use UnicaenApp\Traits\SessionContainerTrait; use UnicaenUtilisateur\Entity\Db\UserInterface; use UnicaenUtilisateur\Entity\Db\UserRoleInterface; use UnicaenUtilisateur\Service\RechercheIndividu\RechercheIndividuServiceInterface; /** * Description of PrivilegeController Loading @@ -14,14 +21,35 @@ use UnicaenApp\Traits\SessionContainerTrait; class PrivilegeController extends Controller { use PrivilegeProviderAwareTrait; use SessionContainerTrait; use PerimetreProviderAwareTrait; use UserContextServiceAwareTrait; /** * @var PerimetreRuleInterface[] */ public $perimetresRules; /** * @param PerimetreRuleInterface[] $perimetresRules * @return self */ public function setPerimetresRules($perimetresRules) { $this->perimetresRules = $perimetresRules; return $this; } /** * {@inheritdoc} */ public function processConfig() { // filtrage des rôles en fonction des privilèges $this->config = $this->privilegesToRoles($this->config); // filtrage des rôles en fonction des périmètres $this->config = $this->perimetresToRoles($this->config); parent::processConfig(); } Loading @@ -36,12 +64,10 @@ class PrivilegeController extends Controller foreach ($rules as $index => $rule) { if (isset($rule['privileges'])) { $rolesCount = 0; $privileges = (array)$rule['privileges']; $rule['roles'] = isset($rule['roles']) ? (array)$rule['roles'] : []; foreach ($pr as $privilege => $roles) { if (in_array($privilege, $privileges)) { $rolesCount += count($roles); $rule['roles'] = array_unique(array_merge($rule['roles'], $roles)); } } Loading @@ -57,6 +83,68 @@ class PrivilegeController extends Controller return $rules; } protected function perimetresToRoles(array $rules): array { /** @var UserInterface $user */ $user = $this->serviceUserContext->getDbUser(); // liste des périmètres et des rôles associés $perimetresRoles = $this->getPerimetreProvider()->getPerimetresRoles(); // parcours de la liste des règles "bjyauthorize/guards" foreach ($rules as $index => $rule) { if(isset($rule['perimetres']) && $user) { $rulePerimetres = (array)$rule['perimetres']; // parcours de toutes les périmètres (catégories) foreach ($perimetresRoles as $perimetreCateg => $pr) { // vérification que le périmètre est appelé dans la règle if(in_array($perimetreCateg, $rulePerimetres)) { // parcours des rôles autorisés pour la règle foreach($rule['roles'] as $role) { // vérification que le rôle fait partie des rôles associés au périmètre if(in_array($role, $pr)) { // récupération des droits de l'utilisateur pour le rôle et le périmètre $userExactRole = $user->getFullRoles()->filter(function ($r) use ($role, $perimetreCateg) { /** @var UserRoleInterface $r */ $pc = $r->getPerimetreCategorie(); return $r->getRole()->getRoleId() === $role && ($pc ? $pc->getCode() : null) === $perimetreCateg; }); // si une règle existe if($userExactRole->count() === 1) { $ur = $userExactRole->current(); /** vérification que le périmètre a un service implémentant @see PerimetreRuleInterface associé dans la config */ if(array_key_exists($perimetreCateg, $this->perimetresRules)) { /** @var PerimetreRuleInterface $service */ $service = $this->perimetresRules[$perimetreCateg]; // vérification de la règle if($service->checkRule($ur->getPerimetre())) { continue; } } else { throw new RuntimeException(sprintf('Le périmètre "%s" n\'a aucun service associé défini dans la configuration : "unicaen-perimetre" > "rule_providers"', $perimetreCateg)); } } // suppression du rôle des rôles autorisés pour cette règle $key = array_search($role, $rule['roles']); unset($rule['roles'][$key]); } } } } unset($rule['perimetres']); if (0 < count($rule['roles'])) { $rules[$index] = $rule; } else { unset($rules[$index]); } } } return $rules; } public static function getResourceId($controller, $action = null) : string { if (isset($action)) { Loading
src/UnicaenPrivilege/Guard/PrivilegeControllerFactory.php +26 −1 Original line number Diff line number Diff line Loading @@ -3,20 +3,45 @@ namespace UnicaenPrivilege\Guard; use Interop\Container\ContainerInterface; use UnicaenAuthentification\Service\UserContext; use UnicaenPrivilege\Provider\Perimetre\PerimetreProviderInterface; use UnicaenPrivilege\Provider\Perimetre\Rules\PerimetreRuleInterface; use UnicaenPrivilege\Provider\Privilege\PrivilegeProviderInterface; use UnicaenPrivilege\Service\Perimetre\PerimetreCategorieService; use UnicaenPrivilege\Service\Privilege\PrivilegeService; class PrivilegeControllerFactory { public function __invoke(ContainerInterface $container) : PrivilegeController { /** @var PrivilegeProviderInterface $privilegeService */ /** * @var PrivilegeProviderInterface $privilegeProvider * @var PerimetreProviderInterface $perimetreProvider * @var UserContext $userContextService */ $config = $container->get('Config'); $perimetreConfig = $config['unicaen-perimetre']; $privilegeProvider = $container->get(PrivilegeService::class); $perimetreProvider = $container->get(PerimetreCategorieService::class); $userContextService = $container->get(UserContext::class); $rules = []; // NB: l'injection des vraies rules est faite par \BjyAuthorize\Service\BaseProvidersServiceFactory $perimetresRules = []; if(array_key_exists('rule_providers', $perimetreConfig)) { foreach($perimetreConfig['rule_providers'] as $key => $provider) { $service = $container->get($provider); if($service instanceof PerimetreRuleInterface) { $perimetresRules[$key] = $service; } } } $instance = new PrivilegeController($rules, $container); $instance->setPrivilegeProvider($privilegeProvider); $instance->setPerimetreProvider($perimetreProvider); $instance->setPerimetresRules($perimetresRules); $instance->setServiceUserContext($userContextService); return $instance; } Loading