From 181f1bce02c63d60f748f4850f5d6d7cfb847db9 Mon Sep 17 00:00:00 2001 From: Demian Katz <demian.katz@villanova.edu> Date: Fri, 6 Feb 2015 14:05:35 -0500 Subject: [PATCH] Added ZFC RBAC in anticipation of authorization logic. --- composer.json | 3 +- composer.lock | 128 ++- vendor/autoload.php | 2 +- vendor/composer/autoload_namespaces.php | 2 + vendor/composer/autoload_real.php | 8 +- vendor/composer/installed.json | 130 +++ vendor/zf-commons/zfc-rbac/.gitignore | 4 + vendor/zf-commons/zfc-rbac/.travis.yml | 27 + vendor/zf-commons/zfc-rbac/CHANGELOG.md | 3 + vendor/zf-commons/zfc-rbac/LICENSE | 27 + vendor/zf-commons/zfc-rbac/Module.php | 7 + vendor/zf-commons/zfc-rbac/README.md | 50 ++ vendor/zf-commons/zfc-rbac/UPGRADE.md | 43 + vendor/zf-commons/zfc-rbac/composer.json | 60 ++ .../zfc-rbac/config/module.config.php | 93 +++ .../zfc-rbac/config/zfc_rbac.global.php.dist | 132 +++ .../zfc-rbac/data/FlatRole.php.dist | 114 +++ .../zfc-rbac/data/HierarchicalRole.php.dist | 146 ++++ .../zfc-rbac/data/Permission.php.dist | 69 ++ vendor/zf-commons/zfc-rbac/data/README.md | 14 + .../zfc-rbac/docs/01. Introduction.md | 59 ++ .../zfc-rbac/docs/02. Quick Start.md | 136 +++ .../zfc-rbac/docs/03. Role providers.md | 200 +++++ vendor/zf-commons/zfc-rbac/docs/04. Guards.md | 479 +++++++++++ .../zfc-rbac/docs/05. Strategies.md | 152 ++++ .../06. Using the Authorization Service.md | 276 +++++++ .../zf-commons/zfc-rbac/docs/07. Cookbook.md | 780 ++++++++++++++++++ vendor/zf-commons/zfc-rbac/docs/README.md | 52 ++ .../docs/images/workflow-with-guards.png | Bin 0 -> 32236 bytes .../docs/images/workflow-without-guards.png | Bin 0 -> 8905 bytes vendor/zf-commons/zfc-rbac/phpunit.xml.dist | 22 + .../ZfcRbac/Assertion/AssertionInterface.php | 43 + .../Assertion/AssertionPluginManager.php | 56 ++ .../src/ZfcRbac/Collector/RbacCollector.php | 230 ++++++ .../ZfcRbac/Exception/ExceptionInterface.php | 29 + .../Exception/InvalidArgumentException.php | 31 + .../Exception/RoleNotFoundException.php | 35 + .../ZfcRbac/Exception/RuntimeException.php | 31 + .../Exception/UnauthorizedException.php | 35 + .../UnauthorizedExceptionInterface.php | 29 + .../Factory/AssertionPluginManagerFactory.php | 47 ++ .../AuthenticationIdentityProviderFactory.php | 44 + .../AuthorizationServiceDelegatorFactory.php | 52 ++ .../Factory/AuthorizationServiceFactory.php | 56 ++ .../Factory/ControllerGuardFactory.php | 66 ++ .../ControllerPermissionsGuardFactory.php | 67 ++ .../Factory/GuardPluginManagerFactory.php | 47 ++ .../src/ZfcRbac/Factory/GuardsFactory.php | 56 ++ .../Factory/HasRoleViewHelperFactory.php | 45 + .../Factory/IsGrantedPluginFactory.php | 44 + .../Factory/IsGrantedViewHelperFactory.php | 44 + .../ZfcRbac/Factory/ModuleOptionsFactory.php | 41 + .../ObjectRepositoryRoleProviderFactory.php | 81 ++ .../src/ZfcRbac/Factory/RbacFactory.php | 46 ++ .../Factory/RedirectStrategyFactory.php | 45 + .../RoleProviderPluginManagerFactory.php | 47 ++ .../ZfcRbac/Factory/RoleServiceFactory.php | 66 ++ .../src/ZfcRbac/Factory/RouteGuardFactory.php | 66 ++ .../Factory/RoutePermissionsGuardFactory.php | 68 ++ .../Factory/UnauthorizedStrategyFactory.php | 43 + .../src/ZfcRbac/Guard/AbstractGuard.php | 78 ++ .../src/ZfcRbac/Guard/ControllerGuard.php | 129 +++ .../Guard/ControllerPermissionsGuard.php | 141 ++++ .../src/ZfcRbac/Guard/GuardInterface.php | 55 ++ .../src/ZfcRbac/Guard/GuardPluginManager.php | 67 ++ .../ZfcRbac/Guard/ProtectionPolicyTrait.php | 54 ++ .../zfc-rbac/src/ZfcRbac/Guard/RouteGuard.php | 110 +++ .../ZfcRbac/Guard/RoutePermissionsGuard.php | 112 +++ .../AuthenticationIdentityProvider.php | 54 ++ .../ZfcRbac/Identity/IdentityInterface.php | 35 + .../Identity/IdentityProviderInterface.php | 35 + .../AuthorizationServiceInitializer.php | 48 ++ .../zfc-rbac/src/ZfcRbac/Module.php | 59 ++ .../Mvc/Controller/Plugin/IsGranted.php | 58 ++ .../src/ZfcRbac/Options/ModuleOptions.php | 287 +++++++ .../Options/RedirectStrategyOptions.php | 148 ++++ .../Options/UnauthorizedStrategyOptions.php | 53 ++ .../Permission/PermissionInterface.php | 34 + .../src/ZfcRbac/Role/InMemoryRoleProvider.php | 95 +++ .../Role/ObjectRepositoryRoleProvider.php | 100 +++ .../ZfcRbac/Role/RoleProviderInterface.php | 39 + .../Role/RoleProviderPluginManager.php | 70 ++ .../ZfcRbac/Service/AuthorizationService.php | 164 ++++ .../AuthorizationServiceAwareInterface.php | 35 + .../AuthorizationServiceAwareTrait.php | 58 ++ .../Service/AuthorizationServiceInterface.php | 39 + .../src/ZfcRbac/Service/RoleService.php | 211 +++++ .../src/ZfcRbac/View/Helper/HasRole.php | 55 ++ .../src/ZfcRbac/View/Helper/IsGranted.php | 58 ++ .../View/Strategy/AbstractStrategy.php | 47 ++ .../View/Strategy/RedirectStrategy.php | 107 +++ .../View/Strategy/UnauthorizedStrategy.php | 83 ++ .../zf-commons/zfc-rbac/tests/Bootstrap.php | 56 ++ .../zfc-rbac/tests/TestConfiguration.php.dist | 32 + .../tests/ZfcRbacTest/Asset/FlatRole.php | 89 ++ .../ZfcRbacTest/Asset/HierarchicalRole.php | 96 +++ .../tests/ZfcRbacTest/Asset/Permission.php | 83 ++ .../ZfcRbacTest/Asset/SimpleAssertion.php | 48 ++ .../Collector/RbacCollectorTest.php | 179 ++++ .../AssertionPluginManagerFactoryTest.php | 44 + ...henticationIdentityProviderFactoryTest.php | 42 + .../AuthorizationServiceDelegatorTest.php | 128 +++ .../AuthorizationServiceFactoryTest.php | 54 ++ .../Factory/ControllerGuardFactoryTest.php | 62 ++ .../ControllerPermissionsGuardFactoryTest.php | 62 ++ .../Factory/GuardPluginManagerFactoryTest.php | 44 + .../ZfcRbacTest/Factory/GuardsFactoryTest.php | 101 +++ .../Factory/HasRoleViewHelperFactoryTest.php | 47 ++ .../Factory/IsGrantedPluginFactoryTest.php | 47 ++ .../IsGrantedViewHelperFactoryTest.php | 47 ++ .../Factory/ModuleOptionsFactoryTest.php | 42 + ...bjectRepositoryRoleProviderFactoryTest.php | 126 +++ .../ZfcRbacTest/Factory/RbacFactoryTest.php | 39 + .../Factory/RedirectStrategyFactoryTest.php | 55 ++ .../RoleProviderPluginManagerFactoryTest.php | 44 + .../Factory/RoleServiceFactoryTest.php | 86 ++ .../Factory/RouteGuardFactoryTest.php | 62 ++ .../RoutePermissionsGuardFactoryTest.php | 62 ++ .../UnauthorizedStrategyFactoryTest.php | 49 ++ .../ZfcRbacTest/Guard/ControllerGuardTest.php | 524 ++++++++++++ .../Guard/ControllerPermissionsGuardTest.php | 513 ++++++++++++ .../Guard/GuardPluginManagerTest.php | 99 +++ .../Guard/ProtectionPolicyTraitTest.php | 34 + .../ZfcRbacTest/Guard/RouteGuardTest.php | 467 +++++++++++ .../Guard/RoutePermissionsGuardTest.php | 424 ++++++++++ .../AuthenticationIdentityProviderTest.php | 54 ++ .../Initializer/AuthorizationAwareFake.php | 32 + .../AuthorizationServiceInitializerTest.php | 46 ++ .../zfc-rbac/tests/ZfcRbacTest/ModuleTest.php | 57 ++ .../Mvc/Controller/Plugin/IsGrantedTest.php | 41 + .../ZfcRbacTest/Options/ModuleOptionsTest.php | 89 ++ .../Options/RedirectStrategyOptionsTest.php | 55 ++ .../UnauthorizedStrategyOptionsTest.php | 43 + .../Role/InMemoryRoleProviderTest.php | 67 ++ .../Role/ObjectRepositoryRoleProviderTest.php | 170 ++++ .../Role/RoleProviderPluginManagerTest.php | 44 + .../AuthorizationServiceAwareTraitTest.php | 36 + .../Service/AuthorizationServiceTest.php | 254 ++++++ .../ZfcRbacTest/Service/RoleServiceTest.php | 241 ++++++ .../Util/ServiceManagerFactory.php | 76 ++ .../ZfcRbacTest/View/Helper/HasRoleTest.php | 59 ++ .../ZfcRbacTest/View/Helper/IsGrantedTest.php | 55 ++ .../View/Strategy/RedirectStrategyTest.php | 197 +++++ .../Strategy/UnauthorizedStrategyTest.php | 64 ++ .../zfc-rbac/tests/testing.config.php | 52 ++ .../zf-commons/zfc-rbac/view/error/403.phtml | 15 + .../toolbar/zfc-rbac.phtml | 102 +++ vendor/zfr/rbac/.gitignore | 7 + vendor/zfr/rbac/.travis.yml | 16 + vendor/zfr/rbac/CHANGELOG.md | 19 + vendor/zfr/rbac/README.md | 24 + vendor/zfr/rbac/composer.json | 34 + vendor/zfr/rbac/phpunit.xml.dist | 22 + .../Rbac/Permission/PermissionInterface.php | 28 + vendor/zfr/rbac/src/Rbac/Rbac.php | 68 ++ .../rbac/src/Rbac/Role/HierarchicalRole.php | 47 ++ .../Rbac/Role/HierarchicalRoleInterface.php | 34 + vendor/zfr/rbac/src/Rbac/Role/Role.php | 66 ++ .../zfr/rbac/src/Rbac/Role/RoleInterface.php | 33 + .../Rbac/Traversal/RecursiveRoleIterator.php | 63 ++ .../Traversal/Strategy/GeneratorStrategy.php | 43 + .../RecursiveRoleIteratorStrategy.php | 32 + .../Strategy/TraversalStrategyInterface.php | 25 + vendor/zfr/rbac/tests/Bootstrap.php | 46 ++ vendor/zfr/rbac/tests/RbacTest/RbacTest.php | 120 +++ .../RbacTest/Role/HierarchicalRoleTest.php | 65 ++ .../zfr/rbac/tests/RbacTest/Role/RoleTest.php | 43 + .../Traversal/RecursiveRoleIteratorTest.php | 108 +++ .../Strategy/GeneratorStrategyTest.php | 71 ++ .../RecursiveRoleIteratorStrategyTest.php | 36 + 170 files changed, 14305 insertions(+), 7 deletions(-) create mode 100644 vendor/zf-commons/zfc-rbac/.gitignore create mode 100644 vendor/zf-commons/zfc-rbac/.travis.yml create mode 100644 vendor/zf-commons/zfc-rbac/CHANGELOG.md create mode 100644 vendor/zf-commons/zfc-rbac/LICENSE create mode 100644 vendor/zf-commons/zfc-rbac/Module.php create mode 100644 vendor/zf-commons/zfc-rbac/README.md create mode 100644 vendor/zf-commons/zfc-rbac/UPGRADE.md create mode 100644 vendor/zf-commons/zfc-rbac/composer.json create mode 100644 vendor/zf-commons/zfc-rbac/config/module.config.php create mode 100644 vendor/zf-commons/zfc-rbac/config/zfc_rbac.global.php.dist create mode 100644 vendor/zf-commons/zfc-rbac/data/FlatRole.php.dist create mode 100644 vendor/zf-commons/zfc-rbac/data/HierarchicalRole.php.dist create mode 100644 vendor/zf-commons/zfc-rbac/data/Permission.php.dist create mode 100644 vendor/zf-commons/zfc-rbac/data/README.md create mode 100644 vendor/zf-commons/zfc-rbac/docs/01. Introduction.md create mode 100644 vendor/zf-commons/zfc-rbac/docs/02. Quick Start.md create mode 100644 vendor/zf-commons/zfc-rbac/docs/03. Role providers.md create mode 100644 vendor/zf-commons/zfc-rbac/docs/04. Guards.md create mode 100644 vendor/zf-commons/zfc-rbac/docs/05. Strategies.md create mode 100644 vendor/zf-commons/zfc-rbac/docs/06. Using the Authorization Service.md create mode 100644 vendor/zf-commons/zfc-rbac/docs/07. Cookbook.md create mode 100644 vendor/zf-commons/zfc-rbac/docs/README.md create mode 100644 vendor/zf-commons/zfc-rbac/docs/images/workflow-with-guards.png create mode 100644 vendor/zf-commons/zfc-rbac/docs/images/workflow-without-guards.png create mode 100644 vendor/zf-commons/zfc-rbac/phpunit.xml.dist create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Assertion/AssertionInterface.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Assertion/AssertionPluginManager.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Collector/RbacCollector.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Exception/ExceptionInterface.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Exception/InvalidArgumentException.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Exception/RoleNotFoundException.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Exception/RuntimeException.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Exception/UnauthorizedException.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Exception/UnauthorizedExceptionInterface.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/AssertionPluginManagerFactory.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/AuthenticationIdentityProviderFactory.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/AuthorizationServiceDelegatorFactory.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/AuthorizationServiceFactory.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/ControllerGuardFactory.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/ControllerPermissionsGuardFactory.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/GuardPluginManagerFactory.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/GuardsFactory.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/HasRoleViewHelperFactory.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/IsGrantedPluginFactory.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/IsGrantedViewHelperFactory.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/ModuleOptionsFactory.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/ObjectRepositoryRoleProviderFactory.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/RbacFactory.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/RedirectStrategyFactory.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/RoleProviderPluginManagerFactory.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/RoleServiceFactory.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/RouteGuardFactory.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/RoutePermissionsGuardFactory.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/UnauthorizedStrategyFactory.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Guard/AbstractGuard.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Guard/ControllerGuard.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Guard/ControllerPermissionsGuard.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Guard/GuardInterface.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Guard/GuardPluginManager.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Guard/ProtectionPolicyTrait.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Guard/RouteGuard.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Guard/RoutePermissionsGuard.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Identity/AuthenticationIdentityProvider.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Identity/IdentityInterface.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Identity/IdentityProviderInterface.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Initializer/AuthorizationServiceInitializer.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Module.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Mvc/Controller/Plugin/IsGranted.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Options/ModuleOptions.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Options/RedirectStrategyOptions.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Options/UnauthorizedStrategyOptions.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Permission/PermissionInterface.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Role/InMemoryRoleProvider.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Role/ObjectRepositoryRoleProvider.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Role/RoleProviderInterface.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Role/RoleProviderPluginManager.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Service/AuthorizationService.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Service/AuthorizationServiceAwareInterface.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Service/AuthorizationServiceAwareTrait.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Service/AuthorizationServiceInterface.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/Service/RoleService.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/View/Helper/HasRole.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/View/Helper/IsGranted.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/View/Strategy/AbstractStrategy.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/View/Strategy/RedirectStrategy.php create mode 100644 vendor/zf-commons/zfc-rbac/src/ZfcRbac/View/Strategy/UnauthorizedStrategy.php create mode 100644 vendor/zf-commons/zfc-rbac/tests/Bootstrap.php create mode 100644 vendor/zf-commons/zfc-rbac/tests/TestConfiguration.php.dist create mode 100644 vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Asset/FlatRole.php create mode 100644 vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Asset/HierarchicalRole.php create mode 100644 vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Asset/Permission.php create mode 100644 vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Asset/SimpleAssertion.php create mode 100644 vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Collector/RbacCollectorTest.php create mode 100644 vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/AssertionPluginManagerFactoryTest.php create mode 100644 vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/AuthenticationIdentityProviderFactoryTest.php create mode 100644 vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/AuthorizationServiceDelegatorTest.php create mode 100644 vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/AuthorizationServiceFactoryTest.php create mode 100644 vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/ControllerGuardFactoryTest.php create mode 100644 vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/ControllerPermissionsGuardFactoryTest.php create mode 100644 vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/GuardPluginManagerFactoryTest.php create mode 100644 vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/GuardsFactoryTest.php create mode 100644 vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/HasRoleViewHelperFactoryTest.php create mode 100644 vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/IsGrantedPluginFactoryTest.php create mode 100644 vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/IsGrantedViewHelperFactoryTest.php create mode 100644 vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/ModuleOptionsFactoryTest.php create mode 100644 vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/ObjectRepositoryRoleProviderFactoryTest.php create mode 100644 vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/RbacFactoryTest.php create mode 100644 vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/RedirectStrategyFactoryTest.php create mode 100644 vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/RoleProviderPluginManagerFactoryTest.php create mode 100644 vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/RoleServiceFactoryTest.php create mode 100644 vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/RouteGuardFactoryTest.php create mode 100644 vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/RoutePermissionsGuardFactoryTest.php create mode 100644 vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/UnauthorizedStrategyFactoryTest.php create mode 100644 vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Guard/ControllerGuardTest.php create mode 100644 vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Guard/ControllerPermissionsGuardTest.php create mode 100644 vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Guard/GuardPluginManagerTest.php create mode 100644 vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Guard/ProtectionPolicyTraitTest.php create mode 100644 vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Guard/RouteGuardTest.php create mode 100644 vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Guard/RoutePermissionsGuardTest.php create mode 100644 vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Identity/AuthenticationIdentityProviderTest.php create mode 100644 vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Initializer/AuthorizationAwareFake.php create mode 100644 vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Initializer/AuthorizationServiceInitializerTest.php create mode 100644 vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/ModuleTest.php create mode 100644 vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Mvc/Controller/Plugin/IsGrantedTest.php create mode 100644 vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Options/ModuleOptionsTest.php create mode 100644 vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Options/RedirectStrategyOptionsTest.php create mode 100644 vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Options/UnauthorizedStrategyOptionsTest.php create mode 100644 vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Role/InMemoryRoleProviderTest.php create mode 100644 vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Role/ObjectRepositoryRoleProviderTest.php create mode 100644 vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Role/RoleProviderPluginManagerTest.php create mode 100644 vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Service/AuthorizationServiceAwareTraitTest.php create mode 100644 vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Service/AuthorizationServiceTest.php create mode 100644 vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Service/RoleServiceTest.php create mode 100644 vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Util/ServiceManagerFactory.php create mode 100644 vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/View/Helper/HasRoleTest.php create mode 100644 vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/View/Helper/IsGrantedTest.php create mode 100644 vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/View/Strategy/RedirectStrategyTest.php create mode 100644 vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/View/Strategy/UnauthorizedStrategyTest.php create mode 100644 vendor/zf-commons/zfc-rbac/tests/testing.config.php create mode 100644 vendor/zf-commons/zfc-rbac/view/error/403.phtml create mode 100644 vendor/zf-commons/zfc-rbac/view/zend-developer-tools/toolbar/zfc-rbac.phtml create mode 100644 vendor/zfr/rbac/.gitignore create mode 100644 vendor/zfr/rbac/.travis.yml create mode 100644 vendor/zfr/rbac/CHANGELOG.md create mode 100644 vendor/zfr/rbac/README.md create mode 100644 vendor/zfr/rbac/composer.json create mode 100644 vendor/zfr/rbac/phpunit.xml.dist create mode 100644 vendor/zfr/rbac/src/Rbac/Permission/PermissionInterface.php create mode 100644 vendor/zfr/rbac/src/Rbac/Rbac.php create mode 100644 vendor/zfr/rbac/src/Rbac/Role/HierarchicalRole.php create mode 100644 vendor/zfr/rbac/src/Rbac/Role/HierarchicalRoleInterface.php create mode 100644 vendor/zfr/rbac/src/Rbac/Role/Role.php create mode 100644 vendor/zfr/rbac/src/Rbac/Role/RoleInterface.php create mode 100644 vendor/zfr/rbac/src/Rbac/Traversal/RecursiveRoleIterator.php create mode 100644 vendor/zfr/rbac/src/Rbac/Traversal/Strategy/GeneratorStrategy.php create mode 100644 vendor/zfr/rbac/src/Rbac/Traversal/Strategy/RecursiveRoleIteratorStrategy.php create mode 100644 vendor/zfr/rbac/src/Rbac/Traversal/Strategy/TraversalStrategyInterface.php create mode 100644 vendor/zfr/rbac/tests/Bootstrap.php create mode 100644 vendor/zfr/rbac/tests/RbacTest/RbacTest.php create mode 100644 vendor/zfr/rbac/tests/RbacTest/Role/HierarchicalRoleTest.php create mode 100644 vendor/zfr/rbac/tests/RbacTest/Role/RoleTest.php create mode 100644 vendor/zfr/rbac/tests/RbacTest/Traversal/RecursiveRoleIteratorTest.php create mode 100644 vendor/zfr/rbac/tests/RbacTest/Traversal/Strategy/GeneratorStrategyTest.php create mode 100644 vendor/zfr/rbac/tests/RbacTest/Traversal/Strategy/RecursiveRoleIteratorStrategyTest.php diff --git a/composer.json b/composer.json index 4c274aab89b..ee2f3cda47a 100644 --- a/composer.json +++ b/composer.json @@ -63,7 +63,8 @@ "zendframework/zendframework": "2.3.4", "zendframework/zendrest": "2.*", "zendframework/zendservice-amazon": "2.*", - "zendframework/zendservice-recaptcha": "2.*" + "zendframework/zendservice-recaptcha": "2.*", + "zf-commons/zfc-rbac": "~2.4" }, "require-dev": { "behat/mink": "1.6.*", diff --git a/composer.lock b/composer.lock index 650e5e406ea..c0405cb14ce 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "fcc3247c05b04451214d193fe0c08e4f", + "hash": "81dc30f74255130821d7ca7044d73d08", "packages": [ { "name": "aferrandini/phpqrcode", @@ -952,6 +952,132 @@ "issues": "https://github.com/zendframework/ZendXml/issues" }, "time": "2014-03-05 22:25:44" + }, + { + "name": "zf-commons/zfc-rbac", + "version": "2.4.2", + "source": { + "type": "git", + "url": "https://github.com/ZF-Commons/zfc-rbac.git", + "reference": "42f466656ad9730025a6bbbfd4144ac2f3abb64c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ZF-Commons/zfc-rbac/zipball/42f466656ad9730025a6bbbfd4144ac2f3abb64c", + "reference": "42f466656ad9730025a6bbbfd4144ac2f3abb64c", + "shasum": "" + }, + "require": { + "php": ">=5.4", + "zendframework/zend-mvc": "~2.2", + "zendframework/zend-servicemanager": "~2.2", + "zfr/rbac": "~1.2" + }, + "require-dev": { + "doctrine/common": "~2.4", + "doctrine/doctrine-module": "~0.8", + "doctrine/doctrine-orm-module": "~0.8", + "phpunit/phpunit": "~3.7", + "satooshi/php-coveralls": "~0.6", + "squizlabs/php_codesniffer": "1.4.*", + "zendframework/zend-developer-tools": "dev-master", + "zendframework/zendframework": "~2.2" + }, + "suggest": { + "doctrine/doctrine-module": "if you want to use Doctrine role provider", + "zendframework/zend-developer-tools": "if you want to show information about the roles" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.4-dev", + "dev-develop": "3.0-dev" + } + }, + "autoload": { + "psr-0": { + "ZfcRbac\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kyle Spraggs", + "email": "theman@spiffyjr.me", + "homepage": "http://www.spiffyjr.me/" + }, + { + "name": "Jean-Marie Leroux", + "email": "jmleroux.pro@gmail.com" + }, + { + "name": "Michaël Gallego", + "email": "mic.gallego@gmail.com", + "homepage": "http://www.michaelgallego.fr" + } + ], + "description": "Zend Framework 2 Module that provides a layer of features of Zend\\Permissions\\Rbac", + "homepage": "http://www.github.com/ZF-Commons/zfc-rbac", + "keywords": [ + "module", + "permissions", + "rbac", + "zf2" + ], + "time": "2015-01-26 11:29:23" + }, + { + "name": "zfr/rbac", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/zf-fr/rbac.git", + "reference": "493711bfc2a637fd7c6f23b71b7b55a621c35d9d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zf-fr/rbac/zipball/493711bfc2a637fd7c6f23b71b7b55a621c35d9d", + "reference": "493711bfc2a637fd7c6f23b71b7b55a621c35d9d", + "shasum": "" + }, + "require": { + "php": ">=5.4" + }, + "require-dev": { + "phpunit/phpunit": "~3.7", + "satooshi/php-coveralls": "~0.6", + "squizlabs/php_codesniffer": "1.4.*", + "zendframework/zend-servicemanager": "~2.2" + }, + "type": "library", + "autoload": { + "psr-0": { + "Rbac\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michaël Gallego", + "email": "mic.gallego@gmail.com", + "homepage": "http://michaelgallego.fr" + } + ], + "description": "Zend Framework 3 prototype for Zend\\Permissions\\Rbac.", + "homepage": "https://github.com/zf-fr/rbac", + "keywords": [ + "rbac", + "security", + "zf2", + "zf3" + ], + "time": "2014-02-06 14:18:34" } ], "packages-dev": [ diff --git a/vendor/autoload.php b/vendor/autoload.php index aa11b61d89d..6a133ef32ad 100644 --- a/vendor/autoload.php +++ b/vendor/autoload.php @@ -4,4 +4,4 @@ require_once __DIR__ . '/composer' . '/autoload_real.php'; -return ComposerAutoloaderInitb177c89eef09b489e2d5c8b83acacb55::getLoader(); +return ComposerAutoloaderInit2185453e64f723932ef1189948c3ad03::getLoader(); diff --git a/vendor/composer/autoload_namespaces.php b/vendor/composer/autoload_namespaces.php index e1c8580f77b..b7ba447e90c 100644 --- a/vendor/composer/autoload_namespaces.php +++ b/vendor/composer/autoload_namespaces.php @@ -6,6 +6,7 @@ $vendorDir = dirname(dirname(__FILE__)); $baseDir = dirname($vendorDir); return array( + 'ZfcRbac\\' => array($vendorDir . '/zf-commons/zfc-rbac/src'), 'Zend\\' => array($vendorDir . '/zendframework/zendframework/library'), 'ZendXml' => array($vendorDir . '/zendframework/zendxml/library'), 'ZendService\\Amazon\\' => array($vendorDir . '/zendframework/zendservice-amazon/library'), @@ -17,6 +18,7 @@ return array( 'Symfony\\Component\\Process\\' => array($vendorDir . '/symfony/process'), 'Symfony\\Component\\CssSelector\\' => array($vendorDir . '/symfony/css-selector'), 'SerialsSolutions' => array($vendorDir . '/serialssolutions/summon'), + 'Rbac\\' => array($vendorDir . '/zfr/rbac/src'), 'ProxyManager\\' => array($vendorDir . '/ocramius/proxy-manager/src'), 'PHPQRCode' => array($vendorDir . '/aferrandini/phpqrcode/lib'), 'Less' => array($vendorDir . '/oyejorge/less.php/lib'), diff --git a/vendor/composer/autoload_real.php b/vendor/composer/autoload_real.php index 2bed176b669..ffd5409f5ea 100644 --- a/vendor/composer/autoload_real.php +++ b/vendor/composer/autoload_real.php @@ -2,7 +2,7 @@ // autoload_real.php @generated by Composer -class ComposerAutoloaderInitb177c89eef09b489e2d5c8b83acacb55 +class ComposerAutoloaderInit2185453e64f723932ef1189948c3ad03 { private static $loader; @@ -19,9 +19,9 @@ class ComposerAutoloaderInitb177c89eef09b489e2d5c8b83acacb55 return self::$loader; } - spl_autoload_register(array('ComposerAutoloaderInitb177c89eef09b489e2d5c8b83acacb55', 'loadClassLoader'), true, true); + spl_autoload_register(array('ComposerAutoloaderInit2185453e64f723932ef1189948c3ad03', 'loadClassLoader'), true, true); self::$loader = $loader = new \Composer\Autoload\ClassLoader(); - spl_autoload_unregister(array('ComposerAutoloaderInitb177c89eef09b489e2d5c8b83acacb55', 'loadClassLoader')); + spl_autoload_unregister(array('ComposerAutoloaderInit2185453e64f723932ef1189948c3ad03', 'loadClassLoader')); $includePaths = require __DIR__ . '/include_paths.php'; array_push($includePaths, get_include_path()); @@ -48,7 +48,7 @@ class ComposerAutoloaderInitb177c89eef09b489e2d5c8b83acacb55 } } -function composerRequireb177c89eef09b489e2d5c8b83acacb55($file) +function composerRequire2185453e64f723932ef1189948c3ad03($file) { require $file; } diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index fa081367fea..f088b05b895 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -1210,5 +1210,135 @@ ], "description": "VuFind 2.x HTTP service library", "homepage": "http://vufind.org/" + }, + { + "name": "zfr/rbac", + "version": "1.2.0", + "version_normalized": "1.2.0.0", + "source": { + "type": "git", + "url": "https://github.com/zf-fr/rbac.git", + "reference": "493711bfc2a637fd7c6f23b71b7b55a621c35d9d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zf-fr/rbac/zipball/493711bfc2a637fd7c6f23b71b7b55a621c35d9d", + "reference": "493711bfc2a637fd7c6f23b71b7b55a621c35d9d", + "shasum": "" + }, + "require": { + "php": ">=5.4" + }, + "require-dev": { + "phpunit/phpunit": "~3.7", + "satooshi/php-coveralls": "~0.6", + "squizlabs/php_codesniffer": "1.4.*", + "zendframework/zend-servicemanager": "~2.2" + }, + "time": "2014-02-06 14:18:34", + "type": "library", + "installation-source": "dist", + "autoload": { + "psr-0": { + "Rbac\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michaël Gallego", + "email": "mic.gallego@gmail.com", + "homepage": "http://michaelgallego.fr" + } + ], + "description": "Zend Framework 3 prototype for Zend\\Permissions\\Rbac.", + "homepage": "https://github.com/zf-fr/rbac", + "keywords": [ + "rbac", + "security", + "zf2", + "zf3" + ] + }, + { + "name": "zf-commons/zfc-rbac", + "version": "2.4.2", + "version_normalized": "2.4.2.0", + "source": { + "type": "git", + "url": "https://github.com/ZF-Commons/zfc-rbac.git", + "reference": "42f466656ad9730025a6bbbfd4144ac2f3abb64c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ZF-Commons/zfc-rbac/zipball/42f466656ad9730025a6bbbfd4144ac2f3abb64c", + "reference": "42f466656ad9730025a6bbbfd4144ac2f3abb64c", + "shasum": "" + }, + "require": { + "php": ">=5.4", + "zendframework/zend-mvc": "~2.2", + "zendframework/zend-servicemanager": "~2.2", + "zfr/rbac": "~1.2" + }, + "require-dev": { + "doctrine/common": "~2.4", + "doctrine/doctrine-module": "~0.8", + "doctrine/doctrine-orm-module": "~0.8", + "phpunit/phpunit": "~3.7", + "satooshi/php-coveralls": "~0.6", + "squizlabs/php_codesniffer": "1.4.*", + "zendframework/zend-developer-tools": "dev-master", + "zendframework/zendframework": "~2.2" + }, + "suggest": { + "doctrine/doctrine-module": "if you want to use Doctrine role provider", + "zendframework/zend-developer-tools": "if you want to show information about the roles" + }, + "time": "2015-01-26 11:29:23", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.4-dev", + "dev-develop": "3.0-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-0": { + "ZfcRbac\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kyle Spraggs", + "email": "theman@spiffyjr.me", + "homepage": "http://www.spiffyjr.me/" + }, + { + "name": "Jean-Marie Leroux", + "email": "jmleroux.pro@gmail.com" + }, + { + "name": "Michaël Gallego", + "email": "mic.gallego@gmail.com", + "homepage": "http://www.michaelgallego.fr" + } + ], + "description": "Zend Framework 2 Module that provides a layer of features of Zend\\Permissions\\Rbac", + "homepage": "http://www.github.com/ZF-Commons/zfc-rbac", + "keywords": [ + "module", + "permissions", + "rbac", + "zf2" + ] } ] diff --git a/vendor/zf-commons/zfc-rbac/.gitignore b/vendor/zf-commons/zfc-rbac/.gitignore new file mode 100644 index 00000000000..ac78e19ff91 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/.gitignore @@ -0,0 +1,4 @@ +vendor +composer.lock +.idea +composer.phar diff --git a/vendor/zf-commons/zfc-rbac/.travis.yml b/vendor/zf-commons/zfc-rbac/.travis.yml new file mode 100644 index 00000000000..796ebed7e33 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/.travis.yml @@ -0,0 +1,27 @@ +language: php + +php: + - 5.4 + - 5.5 + - 5.6 + - hhvm + +before_script: + - composer self-update + - composer update --prefer-source + +script: + - ./vendor/bin/phpunit --coverage-clover ./build/logs/clover.xml --exclude-group Functional + - ./vendor/bin/phpunit --group=Functional + - ./vendor/bin/phpcs --standard=PSR2 ./src/ + +after_script: + - php vendor/bin/coveralls -v + +notifications: + irc: "irc.freenode.org#zftalk.modules" + email: true + +matrix: + allow_failures: + - php: hhvm diff --git a/vendor/zf-commons/zfc-rbac/CHANGELOG.md b/vendor/zf-commons/zfc-rbac/CHANGELOG.md new file mode 100644 index 00000000000..e8a8f776573 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/CHANGELOG.md @@ -0,0 +1,3 @@ +# CHANGELOG + +For changelog, please refer to the [releases](https://github.com/ZF-Commons/ZfcRbac/releases) page. diff --git a/vendor/zf-commons/zfc-rbac/LICENSE b/vendor/zf-commons/zfc-rbac/LICENSE new file mode 100644 index 00000000000..7519bc3cbbf --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2013, ZF-Commons Contributors +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or + other materials provided with the distribution. + + Neither the name of the ZF-Commons nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/zf-commons/zfc-rbac/Module.php b/vendor/zf-commons/zfc-rbac/Module.php new file mode 100644 index 00000000000..f9b62d5fe15 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/Module.php @@ -0,0 +1,7 @@ +<?php +/** + * This file is placed here for compatibility with Zendframework 2's ModuleManager. + * It allows usage of this module even without composer. + * The original Module.php is in 'src/ZfcRbac' in order to respect PSR-0 + */ +require_once __DIR__ . '/src/ZfcRbac/Module.php'; diff --git a/vendor/zf-commons/zfc-rbac/README.md b/vendor/zf-commons/zfc-rbac/README.md new file mode 100644 index 00000000000..a2f5ecf9c94 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/README.md @@ -0,0 +1,50 @@ +# ZfcRbac + +[](http://travis-ci.org/ZF-Commons/zfc-rbac) +[](https://coveralls.io/r/ZF-Commons/zfc-rbac) +[](https://packagist.org/packages/zf-commons/zfc-rbac) +[](https://packagist.org/packages/zf-commons/zfc-rbac) +[](https://scrutinizer-ci.com/g/ZF-Commons/zfc-rbac/) +[](https://packagist.org/packages/zf-commons/zfc-rbac) + +ZfcRbac is an access control module for Zend Framework 2, based on the RBAC permission model. + +## Requirements + +- PHP 5.4 or higher +- [Rbac component](https://github.com/zf-fr/rbac): this is actually a prototype for the ZF3 Rbac component. +- [Zend Framework 2.2 or higher](http://www.github.com/zendframework/zf2) + +> If you are looking for older version of ZfcRbac, please refer to the 0.2.x branch. +> If you are using ZfcRbac 1.0, please upgrade to 2.0. + +## Optional + +- [DoctrineModule](https://github.com/doctrine/DoctrineModule): if you want to use some built-in role and permission providers. +- [ZendDeveloperTools](https://github.com/zendframework/ZendDeveloperTools): if you want to have useful stats added to +the Zend Developer toolbar. + +## Upgrade + +You can find an [upgrade guide](UPGRADE.md) to quickly upgrade your application from major versions of ZfcRbac. + +## Installation + +ZfcRbac only officially supports installation through Composer. For Composer documentation, please refer to +[getcomposer.org](http://getcomposer.org/). + +Install the module: + +```sh +$ php composer.phar require zf-commons/zfc-rbac:~2.4 +``` + +Enable the module by adding `ZfcRbac` key to your `application.config.php` file. Customize the module by copy-pasting +the `zfc_rbac.global.php.dist` file to your `config/autoload` folder. + +## Documentation + +The official documentation is available in the [/docs](/docs) folder. + +You can also find some Doctrine entities in the [/data](/data) folder that will help you to more quickly take advantage +of ZfcRbac. diff --git a/vendor/zf-commons/zfc-rbac/UPGRADE.md b/vendor/zf-commons/zfc-rbac/UPGRADE.md new file mode 100644 index 00000000000..a0e5bb25f57 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/UPGRADE.md @@ -0,0 +1,43 @@ +# Upgrade guide + +## From v2.2 to v2.3 + +- No BC + +## From v2.1 to v2.2 + +- [Potential BC] To simplify unit tests, we have introduced a new `AuthorizationServiceInterface` that the +`AuthorizationService` now implements. We didn't touch any interface (such as `AssertionInterface`) that rely explicitly +on typehinting the `AuthorizationService` to avoid big BC. However, we have updated the view helper and controller +plugins to use the interface instead. This can lead to a BC if you created subclasses of those plugins (which is +not a typical use case). If this is the case, just change `AuthorizationService` to `AuthorizationServiceInterface`. + +## From v2.0 to v2.1 + +- [Potential BC] A potential BC have been introduced in v2.1 to respect interfaces of RBAC component more strictly. +However there is great chance that you have nothing to do. Now, ZfcRbac no longer cast permissions to string before +passing it to your "hasPermission" method in the Role entity. If you used to call `isGranted` using a string permission, +like this: `isGranted('myPermission')`, then you have nothing to do. However, if you are passing a `PermissionInterface` +object, you will now receive this object instead of a string. It's up to you to getting the name from your permission. + +## From v1 to v2 + +Here are the major breaking changes from ZfcRbac 1 to ZfcRbac 2: + +- [BC] Dependency to the ZF2 RBAC component has been replaced in favour of a ZF3 prototype which fixes a lot +of design issues. +- [BC] ZfcRbac no longer accepts multiple role providers. Therefore, the option `role_providers` has been renamed +to `role_provider` +- [BC] Permission providers are gone (hence, the options `permission_providers` as well as `permission_manager` should +be removed). Instead, roles now embed all the necessary information +- [BC] The `redirect_to_route` option for the `RedirectStrategy` is gone. Instead, we now have two options: +`redirect_to_route_connected` and `redirect_to_route_disconnected`. This solves an issue when people used to have +a guard on `login` for non-authenticated users only, which leaded to circular redirections. +- [BC] The default protection policy is now `POLICY_ALLOW`. `POLICY_DENY` was way too restrictive and annoying to +work with by default. +- [BC] `isGranted` method of the AuthorizationService no longer accepts an assertion as a second parameter. Instead, +the AuthorizationService now has an assertion map, that allows to map an assertion to a permission. This allows to +inject dependencies into assertions, as well as making the use of assertions much more transparent. +- [BC] Each assertions now receive the whole `AuthorizationService` instead of the current identity. This allows to +support use cases where an assertion needs to check another permission. +- [BC] Entity schema for hierarchical role have changed and no longer require to implement `RecursiveIterator`. Please have a look at the new schema in the `data` folder. diff --git a/vendor/zf-commons/zfc-rbac/composer.json b/vendor/zf-commons/zfc-rbac/composer.json new file mode 100644 index 00000000000..b5bf4814ac6 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/composer.json @@ -0,0 +1,60 @@ +{ + "name": "zf-commons/zfc-rbac", + "description": "Zend Framework 2 Module that provides a layer of features of Zend\\Permissions\\Rbac", + "type": "library", + "license": "MIT", + "keywords": [ + "module", + "zf2", + "rbac", + "permissions" + ], + "homepage": "http://www.github.com/ZF-Commons/zfc-rbac", + "authors": [ + { + "name": "Kyle Spraggs", + "email": "theman@spiffyjr.me", + "homepage": "http://www.spiffyjr.me/" + }, + { + "name": "Michaël Gallego", + "email": "mic.gallego@gmail.com", + "homepage": "http://www.michaelgallego.fr" + }, + { + "name": "Jean-Marie Leroux", + "email": "jmleroux.pro@gmail.com" + } + ], + "require": { + "php": ">=5.4", + "zendframework/zend-mvc": "~2.2", + "zendframework/zend-servicemanager": "~2.2", + "zfr/rbac": "~1.2" + }, + "require-dev": { + "zendframework/zendframework": "~2.2", + "zendframework/zend-developer-tools": "dev-master", + "phpunit/phpunit": "~3.7", + "squizlabs/php_codesniffer": "1.4.*", + "satooshi/php-coveralls": "~0.6", + "doctrine/common": "~2.4", + "doctrine/doctrine-module": "~0.8", + "doctrine/doctrine-orm-module": "~0.8" + }, + "suggest": { + "zendframework/zend-developer-tools": "if you want to show information about the roles", + "doctrine/doctrine-module": "if you want to use Doctrine role provider" + }, + "autoload": { + "psr-0": { + "ZfcRbac\\": "src/" + } + }, + "extra": { + "branch-alias": { + "dev-master": "2.4-dev", + "dev-develop": "3.0-dev" + } + } +} diff --git a/vendor/zf-commons/zfc-rbac/config/module.config.php b/vendor/zf-commons/zfc-rbac/config/module.config.php new file mode 100644 index 00000000000..17783041e05 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/config/module.config.php @@ -0,0 +1,93 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +return [ + 'service_manager' => [ + 'invokables' => [ + 'ZfcRbac\Collector\RbacCollector' => 'ZfcRbac\Collector\RbacCollector', + ], + + 'factories' => [ + /* Factories that do not map to a class */ + 'ZfcRbac\Guards' => 'ZfcRbac\Factory\GuardsFactory', + + /* Factories that map to a class */ + 'Rbac\Rbac' => 'ZfcRbac\Factory\RbacFactory', + 'ZfcRbac\Assertion\AssertionPluginManager' => 'ZfcRbac\Factory\AssertionPluginManagerFactory', + 'ZfcRbac\Guard\GuardPluginManager' => 'ZfcRbac\Factory\GuardPluginManagerFactory', + 'ZfcRbac\Identity\AuthenticationIdentityProvider' => 'ZfcRbac\Factory\AuthenticationIdentityProviderFactory', + 'ZfcRbac\Options\ModuleOptions' => 'ZfcRbac\Factory\ModuleOptionsFactory', + 'ZfcRbac\Role\RoleProviderPluginManager' => 'ZfcRbac\Factory\RoleProviderPluginManagerFactory', + 'ZfcRbac\Service\AuthorizationService' => 'ZfcRbac\Factory\AuthorizationServiceFactory', + 'ZfcRbac\Service\RoleService' => 'ZfcRbac\Factory\RoleServiceFactory', + 'ZfcRbac\View\Strategy\RedirectStrategy' => 'ZfcRbac\Factory\RedirectStrategyFactory', + 'ZfcRbac\View\Strategy\UnauthorizedStrategy' => 'ZfcRbac\Factory\UnauthorizedStrategyFactory', + ], + ], + + 'view_helpers' => [ + 'factories' => [ + 'ZfcRbac\View\Helper\IsGranted' => 'ZfcRbac\Factory\IsGrantedViewHelperFactory', + 'ZfcRbac\View\Helper\HasRole' => 'ZfcRbac\Factory\HasRoleViewHelperFactory' + ], + 'aliases' => [ + 'isGranted' => 'ZfcRbac\View\Helper\IsGranted', + 'hasRole' => 'ZfcRbac\View\Helper\HasRole' + ] + ], + + 'controller_plugins' => [ + 'factories' => [ + 'ZfcRbac\Mvc\Controller\Plugin\IsGranted' => 'ZfcRbac\Factory\IsGrantedPluginFactory' + ], + 'aliases' => [ + 'isGranted' => 'ZfcRbac\Mvc\Controller\Plugin\IsGranted' + ] + ], + + 'view_manager' => [ + 'template_map' => [ + 'error/403' => __DIR__ . '/../view/error/403.phtml', + 'zend-developer-tools/toolbar/zfc-rbac' => __DIR__ . '/../view/zend-developer-tools/toolbar/zfc-rbac.phtml' + ] + ], + + 'zenddevelopertools' => [ + 'profiler' => [ + 'collectors' => [ + 'zfc_rbac' => 'ZfcRbac\Collector\RbacCollector', + ], + ], + 'toolbar' => [ + 'entries' => [ + 'zfc_rbac' => 'zend-developer-tools/toolbar/zfc-rbac', + ], + ], + ], + + 'zfc_rbac' => [ + // Guard plugin manager + 'guard_manager' => [], + + // Role provider plugin manager + 'role_provider_manager' => [], + + // Assertion plugin manager + 'assertion_manager' => [] + ] +]; diff --git a/vendor/zf-commons/zfc-rbac/config/zfc_rbac.global.php.dist b/vendor/zf-commons/zfc-rbac/config/zfc_rbac.global.php.dist new file mode 100644 index 00000000000..d8b57be55e3 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/config/zfc_rbac.global.php.dist @@ -0,0 +1,132 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +/** + * Copy-paste this file to your config/autoload folder (don't forget to remove the .dist extension!) + */ + +return [ + 'zfc_rbac' => [ + /** + * Key that is used to fetch the identity provider + * + * Please note that when an identity is found, it MUST implements the ZfcRbac\Identity\IdentityProviderInterface + * interface, otherwise it will throw an exception. + */ + // 'identity_provider' => 'ZfcRbac\Identity\AuthenticationIdentityProvider', + + /** + * Set the guest role + * + * This role is used by the authorization service when the authentication service returns no identity + */ + // 'guest_role' => 'guest', + + /** + * Set the guards + * + * You must comply with the various options of guards. The format must be of the following format: + * + * 'guards' => [ + * 'ZfcRbac\Guard\RouteGuard' => [ + * // options + * ] + * ] + */ + // 'guards' => [], + + /** + * As soon as one rule for either route or controller is specified, a guard will be automatically + * created and will start to hook into the MVC loop. + * + * If the protection policy is set to DENY, then any route/controller will be denied by + * default UNLESS it is explicitly added as a rule. On the other hand, if it is set to ALLOW, then + * not specified route/controller will be implicitly approved. + * + * DENY is the most secure way, but it is more work for the developer + */ + // 'protection_policy' => \ZfcRbac\Guard\GuardInterface::POLICY_ALLOW, + + /** + * Configuration for role provider + * + * It must be an array that contains configuration for the role provider. The provider config + * must follow the following format: + * + * 'ZfcRbac\Role\InMemoryRoleProvider' => [ + * 'role1' => [ + * 'children' => ['children1', 'children2'], // OPTIONAL + * 'permissions' => ['edit', 'read'] // OPTIONAL + * ] + * ] + * + * Supported options depend of the role provider, so please refer to the official documentation + */ + 'role_provider' => [], + + /** + * Configure the unauthorized strategy. It is used to render a template whenever a user is unauthorized + */ + 'unauthorized_strategy' => [ + /** + * Set the template name to render + */ + // 'template' => 'error/403' + ], + + /** + * Configure the redirect strategy. It is used to redirect the user to another route when a user is + * unauthorized + */ + 'redirect_strategy' => [ + /** + * Enable redirection when the user is connected + */ + // 'redirect_when_connected' => true, + + /** + * Set the route to redirect when user is connected (of course, it must exist!) + */ + // 'redirect_to_route_connected' => 'home', + + /** + * Set the route to redirect when user is disconnected (of course, it must exist!) + */ + // 'redirect_to_route_disconnected' => 'login', + + /** + * If a user is unauthorized and redirected to another route (login, for instance), should we + * append the previous URI (the one that was unauthorized) in the query params? + */ + // 'append_previous_uri' => true, + + /** + * If append_previous_uri option is set to true, this option set the query key to use when + * the previous uri is appended + */ + // 'previous_uri_query_key' => 'redirectTo' + ], + + /** + * Various plugin managers for guards and role providers. Each of them must follow a common + * plugin manager config format, and can be used to create your custom objects + */ + // 'guard_manager' => [], + // 'role_provider_manager' => [] + ] +]; diff --git a/vendor/zf-commons/zfc-rbac/data/FlatRole.php.dist b/vendor/zf-commons/zfc-rbac/data/FlatRole.php.dist new file mode 100644 index 00000000000..b3e6ac59bb8 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/data/FlatRole.php.dist @@ -0,0 +1,114 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\ORM\Mapping as ORM; +use Rbac\Role\RoleInterface; +use ZfcRbac\Permission\PermissionInterface; + +/** + * @ORM\Entity + * @ORM\Table(name="roles") + */ +class FlatRole implements RoleInterface +{ + /** + * @var int|null + * + * @ORM\Id + * @ORM\Column(type="integer") + * @ORM\GeneratedValue(strategy="AUTO") + */ + protected $id; + + /** + * @var string|null + * + * @ORM\Column(type="string", length=48, unique=true) + */ + protected $name; + + /** + * @var PermissionInterface[]|\Doctrine\Common\Collections\Collection + * + * @ORM\ManyToMany(targetEntity="Permission", indexBy="name", fetch="EAGER", cascade={"persist"}) + */ + protected $permissions; + + /** + * Init the Doctrine collection + */ + public function __construct() + { + $this->permissions = new ArrayCollection(); + } + + /** + * Get the role identifier + * + * @return int + */ + public function getId() + { + return $this->id; + } + + /** + * Set the role name + * + * @param string $name + * @return void + */ + public function setName($name) + { + $this->name = (string) $name; + } + + /** + * Get the role name + * + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * {@inheritDoc} + */ + public function addPermission($permission) + { + if (is_string($permission)) { + $permission = new Permission($permission); + } + + $this->permissions[(string) $permission] = $permission; + } + + /** + * {@inheritDoc} + */ + public function hasPermission($permission) + { + // This can be a performance problem if your role has a lot of permissions. Please refer + // to the cookbook to an elegant way to solve this issue + + return isset($this->permissions[(string) $permission]); + } +} diff --git a/vendor/zf-commons/zfc-rbac/data/HierarchicalRole.php.dist b/vendor/zf-commons/zfc-rbac/data/HierarchicalRole.php.dist new file mode 100644 index 00000000000..3a90ec39b05 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/data/HierarchicalRole.php.dist @@ -0,0 +1,146 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\ORM\Mapping as ORM; +use Rbac\Role\HierarchicalRoleInterface; +use ZfcRbac\Permission\PermissionInterface; + +/** + * @ORM\Entity + * @ORM\Table(name="roles") + */ +class HierarchicalRole implements HierarchicalRoleInterface +{ + /** + * @var int|null + * + * @ORM\Id + * @ORM\Column(type="integer") + * @ORM\GeneratedValue(strategy="AUTO") + */ + protected $id; + + /** + * @var string|null + * + * @ORM\Column(type="string", length=48, unique=true) + */ + protected $name; + + /** + * @var HierarchicalRoleInterface[]|\Doctrine\Common\Collections\Collection + * + * @ORM\ManyToMany(targetEntity="HierarchicalRole") + */ + protected $children = []; + + /** + * @var PermissionInterface[]|\Doctrine\Common\Collections\Collection + * + * @ORM\ManyToMany(targetEntity="Permission", indexBy="name", fetch="EAGER") + */ + protected $permissions; + + /** + * Init the Doctrine collection + */ + public function __construct() + { + $this->children = new ArrayCollection(); + $this->permissions = new ArrayCollection(); + } + + /** + * Get the role identifier + * + * @return int + */ + public function getId() + { + return $this->id; + } + + /** + * Set the role name + * + * @param string $name + * @return void + */ + public function setName($name) + { + $this->name = (string) $name; + } + + /** + * Get the role name + * + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * {@inheritDoc} + */ + public function addChild(HierarchicalRoleInterface $child) + { + $this->children[] = $child; + } + + /** + * {@inheritDoc} + */ + public function addPermission($permission) + { + if (is_string($permission)) { + $permission = new Permission($permission); + } + + $this->permissions[(string) $permission] = $permission; + } + + /** + * {@inheritDoc} + */ + public function hasPermission($permission) + { + // This can be a performance problem if your role has a lot of permissions. Please refer + // to the cookbook to an elegant way to solve this issue + + return isset($this->permissions[(string) $permission]); + } + + /** + * {@inheritDoc} + */ + public function getChildren() + { + return $this->children; + } + + /** + * {@inheritDoc} + */ + public function hasChildren() + { + return !$this->children->isEmpty(); + } +} diff --git a/vendor/zf-commons/zfc-rbac/data/Permission.php.dist b/vendor/zf-commons/zfc-rbac/data/Permission.php.dist new file mode 100644 index 00000000000..c327dcfff19 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/data/Permission.php.dist @@ -0,0 +1,69 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +use Doctrine\ORM\Mapping as ORM; +use ZfcRbac\Permission\PermissionInterface; + +/** + * @ORM\Entity + * @ORM\Table(name="permissions") + */ +class Permission implements PermissionInterface +{ + /** + * @var int|null + * + * @ORM\Id + * @ORM\Column(type="integer") + * @ORM\GeneratedValue(strategy="AUTO") + */ + protected $id; + + /** + * @var string|null + * + * @ORM\Column(type="string", length=128, unique=true) + */ + protected $name; + + /** + * Constructor + */ + public function __construct($name) + { + $this->name = (string) $name; + } + + /** + * Get the permission identifier + * + * @return int + */ + public function getId() + { + return $this->id; + } + + /** + * {@inheritDoc} + */ + public function __toString() + { + return $this->name; + } +} diff --git a/vendor/zf-commons/zfc-rbac/data/README.md b/vendor/zf-commons/zfc-rbac/data/README.md new file mode 100644 index 00000000000..25b66765109 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/data/README.md @@ -0,0 +1,14 @@ +These files are only provided as-in, and are not part of ZfcRbac. They provide you some basic Doctrine ORM +entities that you can use as a starting point. + +## Flat role or hierarchical role? + +As you can see, there are a FlatRole and HierarchicalRole entity classes. You must only use one of them, not both. + +The flat role is easier to follow, because each role contains all its permissions, and the database schema is easier +as you do not need a join table for the role hierarchy. + +On the other hand, the hierarchical role is much more flexible, and prevent you from duplicating the same permissions +into all roles. + +It really depends on your application. diff --git a/vendor/zf-commons/zfc-rbac/docs/01. Introduction.md b/vendor/zf-commons/zfc-rbac/docs/01. Introduction.md new file mode 100644 index 00000000000..8a41f46fe86 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/docs/01. Introduction.md @@ -0,0 +1,59 @@ +# Introduction + +Welcome to the official documentation of ZfcRbac! + +In this part, the following questions will be answered: + +* Why should I use an authorization module? +* What is the Rbac model? +* How can I integrate ZfcRbac into my application? + +## Why should I use an authorization module? + +The authorization part of an application is an essential aspect to secure your application. While the authentication +part tells you who is using your website, the authorization answers if the given identity has the permission to +perform specific actions. + +## What is the Rbac model? + +Rbac stands for **role-based access control**. We use a very simple (albeit powerful) implementation of this model +through the use of [this PHP library](https://github.com/zf-fr/rbac). + +> We are not using the official ZF2 Rbac component since ZfcRbac 2.0 as it has some design flaws. The library we are +using here is actually a prototype for ZF3 Rbac component I've made specifically for ZfcRbac. + +The basic idea of Rbac is to use roles and permissions: + +* **Users** can have one or many **Roles** +* **Roles** request access to **Permissions** +* **Permissions** are granted to **Roles** + +By default, ZfcRbac can be used for two kinds of Rbac model: + +* Flat RBAC model: in this model, roles cannot have children. This is ideal for smaller application, as it is easier +to understand, and the database design is simpler (no need for a join table). +* Hierarchical RBAC model: in this model, roles can have children roles. When evaluating if a given role has a +permission, this model also checks recursively if any of its child roles also have the permission. + + +## How can I integrate ZfcRbac into my application? + +ZfcRbac offers multiple ways to protect your application: + +* Using **Guards**: those classes act as "firewalls" that block access to routes and/or controllers. Guards are usually + configured using PHP arrays, and are executed early in the MVC dispatch process. Typically this happens right after + the route has been matched. +* Using **AuthorizationService**: a complementary method is to use the `AuthorizationService` and inject them into your + service classes to protect them from unwanted access. + +While it is advised to use both methods to make your application even more secure, this is completely optional and you +can choose either of them independently. + +To find out about how you can easily make your existing application more secure, please refer to the following section: + +* [Cookbook: A real world example](/docs/07. Cookbook.md#a-real-world-application) + +### Navigation + +* Continue to [the **Quick Start**](/docs/02. Quick Start.md) +* Back to [the Index](/docs/README.md) diff --git a/vendor/zf-commons/zfc-rbac/docs/02. Quick Start.md b/vendor/zf-commons/zfc-rbac/docs/02. Quick Start.md new file mode 100644 index 00000000000..102d2671a15 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/docs/02. Quick Start.md @@ -0,0 +1,136 @@ +# Quick Start + +In this section, you will learn: + +* How to setup the module +* How to specify an identity provider +* How to add simple role provider + +Before starting the quick start, make sure you have properly installed the module by following the instructions in +the README file. + +## Specifying an identity provider + +By default, ZfcRbac internally uses the `Zend\Authentication\AuthenticationService` to retrieve the user (logged or +not). Therefore, you must register this service in your application by adding those lines in your `module.config.php` file: + +```php +return [ + 'service_manager' => [ + 'factories' => [ + 'Zend\Authentication\AuthenticationService' => function($sm) { + // Create your authentication service! + } + ] + ] +]; +``` +The identity given by `Zend\Authentication\AuthenticationService` must implement `ZfcRbac\Identity\IdentityInterface` like the one provided by Doctrine Module Authentication. Note that the default identity provided with ZF2 does not implement this interface. + +ZfcRbac is flexible enough to use something else than the built-in `AuthenticationService`, by specifying custom +identity providers. For more information, refer [to this section](/docs/03. Role providers.md#identity-providers). + +## Adding a guard + +A guard allows to block access to routes and/or controllers using a simple syntax. For instance, this configuration +grants access to any route that begins with `admin` (or is exactly `admin`) to the `admin` role only: + +```php +return [ + 'zfc_rbac' => [ + 'guards' => [ + 'ZfcRbac\Guard\RouteGuard' => [ + 'admin*' => ['admin'] + ] + ] + ] +]; +``` + +ZfcRbac have several built-in guards, and you can also register your own guards. For more information, refer +[to this section](/docs/04. Guards.md#built-in-guards). + +## Adding a role provider + +RBAC model is based on roles. Therefore, for ZfcRbac to work properly, it must be aware of all the roles that are +used inside your application. + +This configuration creates an *admin* role that has a children role called *member*. The *admin* role automatically +inherits the *member* permissions. + +```php +return [ + 'zfc_rbac' => [ + 'role_provider' => [ + 'ZfcRbac\Role\InMemoryRoleProvider' => [ + 'admin' => [ + 'children' => ['member'], + 'permissions' => ['delete'] + ], + 'member' => [ + 'permissions' => ['edit'] + ] + ] + ] + ] +]; +``` + +In this example, the *admin* role have two permissions: `delete` and `edit` (because it inherits the permissions from +its child), while the *member* role only has the permission `edit`. + +ZfcRbac have several built-in role providers, and you can also register your own role providers. For more information, +refer [to this section](/docs/03. Role providers.md#built-in-role-providers). + +## Registering a strategy + +When a guard blocks access to a route/controller, or if you throw the `ZfcRbac\Exception\UnauthorizedException` +exception in your service, ZfcRbac automatically performs some logic for you depending on the view strategy used. + +For instance, if you want ZfcRbac to automatically redirect all unauthorized requests to the "login" route, add +the following code in the `onBootstrap` method of your `Module.php` class: + +```php +public function onBootstrap(EventInterface $e) +{ + $t = $e->getTarget(); + + $t->getEventManager()->attach( + $t->getServiceManager()->get('ZfcRbac\View\Strategy\RedirectStrategy') + ); +} +``` + +By default, `RedirectStrategy` redirects all unauthorized requests to a route named "login" when user is not connected +and to a route named "home" when user is connected. This is, of course, entirely configurable. + +> For flexibility purpose, ZfcRbac **does not** register any strategy for you by default! + +For more information about built-in strategies, refer [to this section](/docs/05. Strategies.md#built-in-strategies). + +## Using the authorization service + +Now that ZfcRbac is properly configured, you can inject the authorization service in any class and use it to check +if the current identity is granted to do something. + +The authorization service is registered inside the service manager using the following key: `ZfcRbac\Service\AuthorizationService`. +Once injected, you can use it as follow: + +```php +use ZfcRbac\Exception\UnauthorizedException; + +public function delete() +{ + if (!$this->authorizationService->isGranted('delete')) { + throw new UnauthorizedException(); + } + + // Delete the post +} +``` + +### Navigation + +* Continue to [the **Role providers**](/docs/03. Role providers.md) +* Back to [the Introduction](/docs/01. Introduction.md) +* Back to [the Index](/docs/README.md) diff --git a/vendor/zf-commons/zfc-rbac/docs/03. Role providers.md b/vendor/zf-commons/zfc-rbac/docs/03. Role providers.md new file mode 100644 index 00000000000..175fc6bb978 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/docs/03. Role providers.md @@ -0,0 +1,200 @@ +# Role providers + +In this section, you will learn: + +* What are role providers +* What are identity providers +* How to use and configure built-in providers +* How to create custom role providers + +## What are role providers? + +A role provider is an object that returns a list of roles. Each role provider must implement the +`ZfcRbac\Role\RoleProviderInterface` interface. The only required method is `getRoles`, and must return an array +of `Rbac\Role\RoleInterface` objects. + +Roles can come from any sources: in memory, from a file, from a database... However, please note that since ZfcRbac +2.0, you can specify only one role provider per application. The reason is that having multiple role providers make +the workflow harder and can lead to security problems that are very hard to spot. + +## Identity providers? + +Identity providers return the current identity. Most of the time, this means the logged user. ZfcRbac comes with a +default identity provider (`ZfcRbac\Identity\AuthenticationIdentityProvider`) that uses the +`Zend\Authentication\AuthenticationService` service. + +### Create your own identity provider + +If you want to implement your own identity provider, create a new class that implements +`ZfcRbac\Identity\IdentityProviderInterface` class. Then, change the `identity_provider` option in ZfcRbac config, +as shown below: + +```php +return [ + 'zfc_rbac' => [ + 'identity_provider' => 'MyCustomIdentityProvider' + ] +]; +``` + +The identity provider is automatically pulled from the service manager. + +## Built-in role providers + +ZfcRbac comes with two built-in role providers: `InMemoryRoleProvider` and `ObjectRepositoryRoleProvider`. A role +provider must be added to the `role_provider` subkey: + +```php +return [ + 'zfc_rbac' => [ + 'role_provider' => [ + // Role provider config here! + ] + ] +]; +``` + +### InMemoryRoleProvider + +This provider is ideal for small/medium sites with few roles/permissions. All the data is specified in a simple +PHP file, so you never hit a database. + +Here is an example of the format you need to use: + +```php +return [ + 'zfc_rbac' => [ + 'role_provider' => [ + 'ZfcRbac\Role\InMemoryRoleProvider' => [ + 'admin' => [ + 'children' => ['member'], + 'permissions' => ['article.delete'] + ], + 'member' => [ + 'children' => ['guest'], + 'permissions' => ['article.edit', 'article.archive'] + ], + 'guest' => [ + 'permissions' => ['article.read'] + ] + ] + ] + ] +]; +``` + +The `children` and `permissions` subkeys are entirely optionals. Internally, the `InMemoryRoleProvider` creates +either a `Rbac\Role\Role` object if the role does not have any children, or a `Rbac\Role\HierarchicalRole` if +the role has at least one child. + +If you are more confident with flat RBAC, the previous config can be re-written to remove any inheritence between roles: + +```php +return [ + 'zfc_rbac' => [ + 'role_provider' => [ + 'ZfcRbac\Role\InMemoryRoleProvider' => [ + 'admin' => [ + 'permissions' => [ + 'article.delete', + 'article.edit', + 'article.archive', + 'article.read' + ] + ], + 'member' => [ + 'permissions' => [ + 'article.edit', + 'article.archive', + 'article.read' + ] + ], + 'guest' => [ + 'permissions' => ['article.read'] + ] + ] + ] + ] +]; +``` + +### ObjectRepositoryRoleProvider + +This provider fetches roles from the database using `Doctrine\Common\Persistence\ObjectRepository` interface. + +You can configure this provider by giving an object repository service name that is fetched from the service manager +using the `object_repository` key: + +```php +return [ + 'zfc_rbac' => [ + 'role_provider' => [ + 'ZfcRbac\Role\ObjectRepositoryRoleProvider' => [ + 'object_repository' => 'App\Repository\RoleRepository', + 'role_name_property' => 'name' + ] + ] + ] +]; +``` + +Or you can specify the `object_manager` and `class_name` options: + +```php +return [ + 'zfc_rbac' => [ + 'role_provider' => [ + 'ZfcRbac\Role\ObjectRepositoryRoleProvider' => [ + 'object_manager' => 'doctrine.entitymanager.orm_default', + 'class_name' => 'App\Entity\Role', + 'role_name_property' => 'name' + ] + ] + ] +]; +``` + +In both cases, you need to specify the `role_name_property` value, which is the name of the entity's property +that holds the actual role name. This is used internally to only load the identity roles, instead of loading +the whole table every time. + +Please note that your entity fetched from the table MUST implement the `Rbac\Role\RoleInterface` interface. + +## Creating custom role providers + +To create a custom role providers, you first need to create a class that implements the `ZfcRbac\Role\RoleProviderInterface` +interface. + +Then, you need to add it to the role provider manager: + +```php +return [ + 'zfc_rbac' => [ + 'role_provider_manager' => [ + 'factories' => [ + 'Application\Role\CustomRoleProvider' => 'Application\Factory\CustomRoleProviderFactory' + ] + ] + ] +]; +``` + +You can now use it like any other role provider: + +```php +return [ + 'zfc_rbac' => [ + 'role_provider' => [ + 'Application\Role\CustomRoleProvider' => [ + // Options + ] + ] + ] +]; +``` + +### Navigation + +* Continue to [the **Guards**](/docs/04. Guards.md) +* Back to [the Quick Start](/docs/02. Quick Start.md) +* Back to [the Index](/docs/README.md) diff --git a/vendor/zf-commons/zfc-rbac/docs/04. Guards.md b/vendor/zf-commons/zfc-rbac/docs/04. Guards.md new file mode 100644 index 00000000000..85a4d3a2085 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/docs/04. Guards.md @@ -0,0 +1,479 @@ +# Guards + +In this section, you will learn: + +* What are guards +* How to use and configure built-in guards +* How to create custom guards + +## What are guards and when to use them? + +Guards (called firewalls in older versions of ZfcRbac) are listeners that are registered on a specific event of +the MVC workflow. They allow to quickly unauthorized requests. + +Here is a simple workflow without guards: + + + +And here is a simple workflow with a route guard: + + + +RouteGuard and ControllerGuard are not aware of permissions but rather only think about "roles". For +instance, you may want to refuse access to each routes that begin by "admin/*" to all users that do not have the +"admin" role. + +If you want to protect a route for a set of permissions, you must use RoutePermissionsGuard. For instance, +you may want to grant access to a route "post/delete" only to roles having the "delete" permission. +Note that in a RBAC system, a permission is linked to a role, not to a user. + +Albeit simple to use, guards should not be the only protection in your application, and you should always also +protect your service. The reason is that your business logic should be handled by your service. Protecting a given +route or controller does not mean that the service cannot be access from elsewhere (another action for instance). + +### Protection policy + +By default, when a guard is added, it will perform check only on the specified guard rules. Any route or controller +that are not specified in the rules will be "granted" by default. Therefore, the default is a "blacklist" +mechanism. + +However, you may want a more restrictive approach (also called "whitelist"). In this mode, once a guard is added, +anything that is not explicitely added will be refused by default. + +For instance, let's say you have two routes: "index" and "login". If you specify a route guard rule to allow "index" +route to "member" role, your "login" route will become defacto unauthorized to anyone, unless you add a new rule for +allowing the route "login" to "member" role. + +You can change it in ZfcRbac config, as follows: + +```php +use ZfcRbac\Guard\GuardInterface; + +return [ + 'zfc_rbac' => [ + 'protection_policy' => GuardInterface::POLICY_DENY + ] +]; +``` + +> NOTE: this policy will block ANY route/controller (so it will also block any console routes or controllers). The +deny policy is much more secure, but it needs much more configuration to work with. + +## Built-in guards + +ZfcRbac comes with four guards, in order of priority : + +* RouteGuard : protect a set of routes based on the identity roles +* RoutePermissionsGuard : protect a set of routes based on roles permissions +* ControllerGuard : protect a controllers and/or actions based on the identity roles +* ControllerPermissionsGuard : protect a controllers and/or actions based on roles permissions + +All guards must be added in the `guards` subkey: + +```php +return [ + 'zfc_rbac' => [ + 'guards' => [ + // Guards config here! + ] + ] +]; +``` + +Because of the way Zend Framework 2 handles config, you can without problem define some rules in one module, and +more rules in another module. All the rules will be automatically merged. + +> For your mental health, I recommend you to use either the route guard OR the controller guard, but not both. If +you decide to use both conjointly, I recommend you to set the protection policy to "allow" (otherwise, you will +need to define rules for every routes AND every controller, which can become quite frustrating!). + +Please note that if your application use both route and controller guards, route guards are always executed +**before** controller guards (they have a higher priority). + +### RouteGuard + +> The RouteGuard listens to the `MvcEvent::EVENT_ROUTE` event with a priority of -5. + +The RouteGuard allows to protect a route or a hierarchy of route. You must provide an array of "key" => "value", +where the key is a route pattern, and value an array of role names: + +```php +return [ + 'zfc_rbac' => [ + 'guards' => [ + 'ZfcRbac\Guard\RouteGuard' => [ + 'admin*' => ['admin'], + 'login' => ['guest'] + ] + ] + ] +]; +``` + +> Only one role in a rule need to be matched (it is an OR condition). + +Those rules grant access to all admin routes to users that have the "admin" role, and grant access to the "login" +route to users that have the "guest" role (eg.: most likely unauthenticated users). + +> The route pattern is not a regex. It only supports the wildcard (*) character, that replaces any segment. + +You can also use the wildcard character * for roles: + +```php +return [ + 'zfc_rbac' => [ + 'guards' => [ + 'ZfcRbac\Guard\RouteGuard' => [ + 'home' => ['*'] + ] + ] + ] +]; +``` + +This rule grants access to the "home" route to anyone. + +Finally, you can also omit the roles array to completly block a route, for maintenance purpose for example : + +```php +return [ + 'zfc_rbac' => [ + 'guards' => [ + 'ZfcRbac\Guard\RouteGuard' => [ + 'route_under_construction' + ] + ] + ] +]; +``` + +This rule will be inaccessible. + +Note : this last example could be (and should be) written in a more explicit way : + +```php +return [ + 'zfc_rbac' => [ + 'guards' => [ + 'ZfcRbac\Guard\RouteGuard' => [ + 'route_under_construction' => [] + ] + ] + ] +]; +``` + + +### RoutePermissionsGuard + +> The RoutePermissionsGuard listens to the `MvcEvent::EVENT_ROUTE` event with a priority of -8. + +The RoutePermissionsGuard allows to protect a route or a hierarchy of route. You must provide an array of "key" => "value", +where the key is a route pattern, and value an array of permissions names: + +```php +return [ + 'zfc_rbac' => [ + 'guards' => [ + 'ZfcRbac\Guard\RoutePermissionsGuard' => [ + 'admin*' => ['admin'], + 'post/manage' => ['post.update', 'post.delete'] + ] + ] + ] +]; +``` + +> All permissions in a rule must be matched (it is an AND condition). + +In the previous example, one must have ```post.update``` **AND** ```post.delete``` permissions +to access the ```post/manage``` route. + +> Permissions are linked to roles, not to users + +Those rules grant access to all admin routes to roles that have the "admin" permission, and grant access to the +"post/delete" route to roles that have the "post.delete" or "admin" permissions. + +> The route pattern is not a regex. It only supports the wildcard (*) character, that replaces any segment. + +You can also use the wildcard character * for permissions: + +```php +return [ + 'zfc_rbac' => [ + 'guards' => [ + 'ZfcRbac\Guard\RoutePermissionsGuard' => [ + 'home' => ['*'] + ] + ] + ] +]; +``` + +This rule grants access to the "home" route to anyone. + +Finally, you can also use an empty array to completly block a route, for maintenance purpose for example : + +```php +return [ + 'zfc_rbac' => [ + 'guards' => [ + 'ZfcRbac\Guard\RoutePermissionsGuard' => [ + 'route_under_construction' => [] + ] + ] + ] +]; +``` + +This rule will be inaccessible. + + +### ControllerGuard + +> The ControllerGuard listens to the `MvcEvent::EVENT_ROUTE` event with a priority of -10. + +The ControllerGuard allows to protect a controller. You must provide an array of array: + +```php +return [ + 'zfc_rbac' => [ + 'guards' => [ + 'ZfcRbac\Guard\ControllerGuard' => [ + [ + 'controller' => 'MyController', + 'roles' => ['guest', 'member'] + ] + ] + ] + ] +]; +``` + +> Only one role in a rule need to be matched (it is an OR condition). + +Those rules grant access to each actions of the MyController controller to users that have either the "guest" or +"member" roles. + +As for RouteGuard, you can use a wildcard (*) character for roles. + +You can also specify optional actions, so that the rule only apply to one or several actions: + +```php +return [ + 'zfc_rbac' => [ + 'guards' => [ + 'ZfcRbac\Guard\ControllerGuard' => [ + [ + 'controller' => 'MyController', + 'actions' => ['read', 'edit'], + 'roles' => ['guest', 'member'] + ] + ] + ] + ] +]; +``` + +You can combine a generic rule and a specific action rule for the same controller, as follow: + +```php +return [ + 'zfc_rbac' => [ + 'guards' => [ + 'ZfcRbac\Guard\ControllerGuard' => [ + [ + 'controller' => 'PostController', + 'roles' => ['member'] + ], + [ + 'controller' => 'PostController', + 'actions' => ['delete'], + 'roles' => ['admin'] + ] + ] + ] + ] +]; +``` + +Those rules grant access to each actions of the controller to users that have the "member" role, but restrict the +"delete" action to "admin" only. + +### ControllerPermissionsGuard + +> The ControllerPermissionsGuard listens to the `MvcEvent::EVENT_ROUTE` event with a priority of -13. + +The ControllerPermissionsGuard allows to protect a controller using permissions. You must provide an array of array: + +```php +return [ + 'zfc_rbac' => [ + 'guards' => [ + 'ZfcRbac\Guard\ControllerPermissionsGuard' => [ + [ + 'controller' => 'MyController', + 'permissions' => ['post.update', 'post.delete'] + ] + ] + ] + ] +]; +``` + +> All permissions in a rule must be matched (it is an AND condition). + +In the previous example, the user must have ```post.update``` **AND** ```post.delete``` permissions +to access each actions of the MyController controller. + +As for all other guards, you can use a wildcard (*) character for permissions. + +The configuration rules are the same as for ControllerGuard. + +### Security notice + +RouteGuard and ControllerGuard listen to the `MvcEvent::EVENT_ROUTE` event. Therefore, if you use the +`forward` method into your controller, those guards will not intercept and check requests (because internally +ZF2 does not trigger again a new MVC loop). + +Most of the time, this is not an issue, but you must be aware of it, and this is an additional reason why you +should always protect your services too. + +## Creating custom guards + +ZfcRbac is flexible enough to allow you to create custom guard. Let's say we want to create a guard that will +refuse access based on an IP addresses blacklist. + +First create the guard: + +```php +namespace Application\Guard; + +use Zend\Http\Request as HttpRequest; +use Zend\Mvc\MvcEvent; +use ZfcRbac\Guard\AbstractGuard; + +class IpGuard extends AbstractGuard +{ + const EVENT_PRIORITY = 100; + + /** + * List of IPs to blacklist + */ + protected $ipAddresses = []; + + /** + * @param array $ipAddresses + */ + public function __construct(array $ipAddresses) + { + $this->ipAddresses = $ipAddresses; + } + + /** + * @param MvcEvent $event + * @return bool + */ + public function isGranted(MvcEvent $event) + { + $request = $event->getRequest(); + + if (!$request instanceof HttpRequest) { + return true; + } + + if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { + $clientIp = $_SERVER['HTTP_X_FORWARDED_FOR']; + } else { + $clientIp = $_SERVER['REMOTE_ADDR']; + } + + return !in_array($clientIp, $this->ipAddresses); + } +} +``` + +> Guards must implement `ZfcRbac\Guard\GuardInterface`. + +By default, guards are listening to the event `MvcEvent::EVENT_ROUTE` with a priority of -5 (you can change the default +event to listen by overriding the `EVENT_NAME` constant in your guard subclass). However, in this case, we don't +even need to wait for the route to be matched, so we overload the `EVENT_PRIORITY` constant to be executed earlier. + +The `isGranted` method simply retrieves the client IP address, and check it against the blacklist. + +However, for this to work, we must register the newly created guard to the guard plugin manager. To do so, add the +following code in your config: + +```php +return [ + 'zfc_rbac' => [ + 'guard_manager' => [ + 'factories' => [ + 'Application\Guard\IpGuard' => 'Application\Factory\IpGuardFactory' + ] + ] + ] +]; +``` + +The `guard_manager` config follows a conventional service manager config format. + +Now, let's create the factory: + +```php +namespace Application\Factory; + +use Application\Guard\IpGuard; +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\MutableCreationOptionsInterface; +use Zend\ServiceManager\ServiceLocatorInterface; + +class IpGuardFactory implements FactoryInterface, MutableCreationOptionsInterface +{ + /** + * @var array + */ + protected $options; + + /** + * {@inheritDoc} + */ + public function setCreationOptions(array $options) + { + $this->options = $options; + } + + /** + * {@inheritDoc} + */ + public function createService(ServiceLocatorInterface $serviceLocator) + { + return new IpGuard($this->options); + } +} +``` + +The `MutableCreationOptionsInterface` was introduced in Zend Framework 2.2, and allows your factories to accept +options. In fact, in a real use case, you would likely fetched the blacklist from database. + +Now, we just need to add the guard to the `guards` option, so that ZfcRbac execute the logic behind this guard. In +your config, add the following code: + +```php +return [ + 'zfc_rbac' => [ + 'guards' => [ + 'Application\Guard\IpGuard' => [ + '87.45.66.46', + '65.87.35.43' + ] + ] + ] +]; +``` + +### Navigation + +* Continue to [the **Strategies**](/docs/05. Strategies.md) +* Back to [the Role providers](/docs/03. Role providers.md) +* Back to [the Index](/docs/README.md) diff --git a/vendor/zf-commons/zfc-rbac/docs/05. Strategies.md b/vendor/zf-commons/zfc-rbac/docs/05. Strategies.md new file mode 100644 index 00000000000..444da88a1f5 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/docs/05. Strategies.md @@ -0,0 +1,152 @@ +# Strategies + +In this section, you will learn: + +* What are strategies +* How to use built-in strategies +* Creating custom strategies + +## What are strategies? + +A strategy is an object that listens to the `MvcEvent::EVENT_DISPATCH_ERROR` event. It is used to describe what +happens when an access to a resource is unauthorized by ZfcRbac. + +ZfcRbac strategies all check if an `ZfcRbac\Exception\UnauthorizedExceptionInterface` has been thrown. + +By default, ZfcRbac does not register any strategy for you. The best place to register it is in your `onBootstrap` +method of the `Module.php` class: + +```php +public function onBootstrap(EventInterface $e) +{ + $t = $e->getTarget(); + + $t->getEventManager()->attach( + $t->getServiceManager()->get('ZfcRbac\View\Strategy\UnauthorizedStrategy') + ); +} +``` + +## Built-in strategies + +ZfcRbac comes with two built-in strategies: `RedirectStrategy` and `UnauthorizedStrategy`. + +### RedirectStrategy + +This strategy allows to redirect any unauthorized request to another route, by optionally appending the previous +URL as a query param. + +To register it, copy-paste this code in your Module.php class: + +```php +public function onBootstrap(EventInterface $e) +{ + $t = $e->getTarget(); + + $t->getEventManager()->attach( + $t->getServiceManager()->get('ZfcRbac\View\Strategy\RedirectStrategy') + ); +} +``` + +You can configure the strategy using the `redirect_strategy` subkey: + +```php +return [ + 'zfc_rbac' => [ + 'redirect_strategy' => [ + 'redirect_when_connected' => true, + 'redirect_to_route_connected' => 'home', + 'redirect_to_route_disconnected' => 'login', + 'append_previous_uri' => true, + 'previous_uri_query_key' => 'redirectTo' + ], + ] +]; +``` + +If a user tries to access to an unauthorized resource (eg.: http://www.example.com/delete), he/she will be +redirect to the "login" route if is not connected and to the "home" route otherwise (it must exists in your route config, +of course) with the previous URL appended : http://www.example.com/login?redirectTo=http://www.example.com/delete + +You can prevent redirection when a user is connected (i.e. so that the user gets a 403 page) by setting `redirect_when_connected` to `false`. + +### UnauthorizedStrategy + +This strategy allows to render a template on any unauthorized request. + +To register it, copy-paste this code in your Module.php class: + +```php +public function onBootstrap(EventInterface $e) +{ + $t = $e->getTarget(); + + $t->getEventManager()->attach( + $t->getServiceManager()->get('ZfcRbac\View\Strategy\UnauthorizedStrategy') + ); +} +``` + +You can configure the strategy using the `unauthorized_strategy` subkey: + +```php +return [ + 'zfc_rbac' => [ + 'unauthorized_strategy' => [ + 'template' => 'error/custom-403' + ], + ] +]; +``` + +> By default, ZfcRbac uses a template called `error/403`. + +## Creating custom strategies + +Creating a custom strategy is rather easy. Let's say we want to create a strategy that integrates with +the [ApiProblem](https://github.com/zfcampus/zf-api-problem) Zend Framework 2 module: + +```php +namespace Application\View\Strategy; + +use Zend\Http\Response as HttpResponse; +use Zend\Mvc\MvcEvent; +use ZF\ApiProblem\ApiProblem; +use ZF\ApiProblem\ApiProblemResponse; +use ZfcRbac\View\Strategy\AbstractStrategy; +use ZfcRbac\Exception\UnauthorizedExceptionInterface; + +class ApiProblemStrategy extends AbstractStrategy +{ + public function onError(MvcEvent $event) + { + // Do nothing if no error or if response is not HTTP response + if (!($exception = $event->getParam('exception') instanceof UnauthorizedExceptionInterface) + || ($result = $event->getResult() instanceof HttpResponse) + || !($response = $event->getResponse() instanceof HttpResponse) + ) { + return; + } + + return new ApiProblemResponse(new ApiProblem($exception->getMessage())); + } +} +``` + +Register your strategy: + +```php +public function onBootstrap(EventInterface $e) +{ + $e->getTarget() + ->getEventManager() + ->attach(new ApiProblemStrategy()); +} +``` + +### Navigation + +* Continue to [the **Authorization Service**](/docs/06. Using the Authorization Service.md) +* Back to [the Guards](/docs/04. Guards.md) +* Back to [the Index](/docs/README.md) diff --git a/vendor/zf-commons/zfc-rbac/docs/06. Using the Authorization Service.md b/vendor/zf-commons/zfc-rbac/docs/06. Using the Authorization Service.md new file mode 100644 index 00000000000..53c031e0604 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/docs/06. Using the Authorization Service.md @@ -0,0 +1,276 @@ +# Using the Authorization Service + +This section will teach you how to use the AuthorizationService to its full extend. + +## Injecting the Authorization Service + +### Using initializers + +To automatically inject the authorization service into your classes, you can implement the +`AuthorizationServiceAwareInterface` and use the trait, as shown below: + +```php +namespace YourModule; + +use ZfcRbac\Service\AuthorizationServiceAwareInterface; +use ZfcRbac\Service\AuthorizationServiceAwareTrait; + +class MyClass implements AuthorizationServiceAwareInterface +{ + use AuthorizationServiceAwareTrait; + + public function doSomethingThatRequiresAuth() + { + if (! $this->getAuthorizationService()->isGranted('deletePost')) { + throw new UnauthorizedException('You are not allowed !'); + } + + return true; + } +} +``` + +Then, registers the initializer in your config (it is not by default): + +```php +class Module +{ + // ... + + public function getServiceConfig() + { + return [ + 'initializers' => [ + 'ZfcRbac\Initializer\AuthorizationServiceInitializer' + ] + ]; + } +} +``` + +> While initializers allow rapid prototyping, it can leads to more fragile code. We'd suggest using factories. + +### Using delegator factory + +ZfcRbac is shipped with a `ZfcRbac\Factory\AuthorizationServiceDelegatorFactory` [delegator factory] +(http://framework.zend.com/manual/2.3/en/modules/zend.service-manager.delegator-factories.html) +to automatically inject the authorization service into your classes. + +As for the initializer, the class must implement the `AuthorizationServiceAwareInterface`. + +You just have to add your classes to the right delegator : + +```php +class Module +{ + // ... + + public function getServiceConfig() + { + return [ + 'invokables' => [ + 'Application\Service\MyClass' => 'Application\Service\MyClassService', + ], + 'delegators' => [ + 'Application\Service\MyClass' => [ + 'ZfcRbac\Factory\AuthorizationServiceDelegatorFactory', + // eventually add more delegators here + ], + ], + ]; + } +} +``` + +> While they need a little more configuration, delegators factories have better performances than initializers. + +### Using Factories + +You can inject the AuthorizationService in your factories by using Zend's ServiceManager. The AuthorizationService +is known to the ServiceManager as `'ZfcRbac\Service\AuthorizationService'`. Here is a classic example for injecting +the AuthorizationService: + +*YourModule/Module.php* + +```php +class Module +{ + // getAutoloaderConfig(), etc... + + public function getServiceConfig() + { + return [ + 'factories' => [ + 'MyService' => function($sm) { + $authService = $sm->get('ZfcRbac\Service\AuthorizationService'); + return new MyService($authService); + } + ] + ]; + } +} +``` + +### Using Zend\DI + +DI is a great way for prototyping, getting results *fast* and maintaining a flexible structure. However it adds overhead and can get very slow. Unless you are using a compiler it is **not** recommended for production. +Here's how you enable Zend\DI to inject the AuthorizationService in MyClass: + +*YourModule/Module.php* + +```php +namespace YourModule; + +class Module +{ + // getAutoloaderConfig(), etc... + + public function getConfig() + { + return [ + 'di' => [ + 'definition' => [ + 'class' => [ + __NAMESPACE__ . '\MyClass' => [ + 'setAuthorizationService' => [ + 'required' => true + ] + ] + ] + ] + ] + ]; + } +} +``` + +## Permissions and Assertions + +Since you now know how to inject the AuthorizationService, let's use it! + +One of the great things the AuthorizationService brings are **assertions**. Assertions get executed *if the identity +in fact holds the permission you are requesting*. A common example is a blog post, which only the author can edit. In +this case, you have a `post.edit` permission and run an assertion checking the author afterwards. + +### Defining assertions + +The AssertionPluginManager is a great way for you to use assertions and IOC. You can add new assertions quite easily +by adding this to your `module.config.php` file: + +```php +return [ + 'zfc_rbac' => [ + 'assertion_manager' => [ + 'factories' => [ + 'MyAssertion' => 'MyAssertionFactory' + ] + ] + ] +]; +``` + +### Defining the assertion map + +The assertion map can automatically map permissions to assertions. This means that every times you check for a +permission with an assertion map, you'll include the assertion in your check. You can define the assertion map by +adding this to your `module.config.php` file: + +```php +return [ + 'zfc_rbac' => [ + 'assertion_map' => [ + 'myPermission' => 'myAssertion' + ] + ] +]; +``` + +Now, everytime you check for `myPermission`, `myAssertion` will be checked as well. + +### Checking permissions in a service + +So let's check for a permission, shall we? + +```php +$authorizationService->isGranted('myPermission'); +``` + +That was easy, wasn't it? + +`isGranted` checks if the current identity is granted the permission and additionally runs the assertion that is +provided by the assertion map. + +### Checking permissions in a controller or in a view + +ZfcRbac comes with both a controller plugin and a view helper to check permissions. + +In a controller : + +```php + public function doSomethingAction() + { + if (!$this->isGranted('myPermission')) { + // redirect if not granted for example + } + } +``` + +In a view : + +```php + <?php if (!$this->isGranted('myPermission')): ?> + <div> + <p>Display only if granted</p> + </div> + <?php endif ?> +``` + +### Defining additional permissions + +But what if you don't want to use the assertion map? That's quite easy as well! + +Here are four use cases on how you can work without the assertion map: + +Disable the assertion: + +```php +$authorizationService->setAssertion('myPermission', null); +$authorizationService->isGranted('myPermission'); +``` + +Callback assertion: +```php +$something = true; + +$authorizationService->setAssertion( + 'myPermission', + function(AuthorizationService $authorization, $context = true) use ($something) { + return $something === $context + } +); + +$authorizationService->isGranted('myPermission'); // returns true, when the identity holds the permission `myPermission` +``` + +Object implementing `AssertionInterface`: +```php +$context = true; + +$authorizationService->setAssertion('myPermission', new MyAssertion($foo, $bar)); +$authorizationService->isGranted('myPermission', $context); +``` + +Using the AssertionPluginManager: +```php +$context = true; +$authorizationService->setAssertion('myPermission', 'MyAssertion'); +$authorizationService->isGranted('myPermission', $context); +``` + +*Please note: The context parameter is optional!* + +### Navigation + +* Continue to [the **Cookbook**](/docs/07. Cookbook.md) +* Back to [the Strategies](/docs/05. Strategies.md) +* Back to [the Index](/docs/README.md) diff --git a/vendor/zf-commons/zfc-rbac/docs/07. Cookbook.md b/vendor/zf-commons/zfc-rbac/docs/07. Cookbook.md new file mode 100644 index 00000000000..14dee276a7e --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/docs/07. Cookbook.md @@ -0,0 +1,780 @@ +# Cookbook + +This section will help you to further understand how ZfcRbac works by providing more concrete examples. If you have +any other recipe you'd like to add, please open an issue! + +- [A Real World Application](/docs/07.%20Cookbook.md#a-real-world-application) + - [Best Practices](https://github.com/manuakasam/zfc-rbac/blob/master/docs/07.%20Cookbook.md#best-practices) + - [When to use Guards](/docs/07.%20Cookbook.md#when-using-guards-then) +- [A Real World Application Part 2 - Only delete your own Posts](/docs/07.%20Cookbook.md#a-real-world-application-part-2---only-delete-your-own-posts) +- [A Real World Application Part 3 - But Admins can delete everything](/docs/07.%20Cookbook.md#a-real-world-application-part-3---admins-can-delete-everything) +- [A Real World Application Part 4 - Only admins have the menu item for managing the posts] + (/docs/07.%20Cookbook.md#a-real-world-application-part-4---checking-permissions-in-the-view) +- [Using ZfcRbac with Doctrine ORM](/docs/07.%20Cookbook.md#using-zfcrbac-with-doctrine-orm) + - [How to deal with roles with lot of permissions?](/docs/07.%20Cookbook.md#how-to-deal-with-roles-with-lot-of-permissions) +- [Using ZfcRbac and ZF2 Assetic](/docs/07.%20Cookbook.md#using-zfcrbac-and-zf2-assetic) +- [Using ZfcRbac and ZfcUser](/docs/07.%20Cookbook.md#using-zfcrbac-and-zfcuser) + +## A Real World Application + +In this example we are going to create a very little real world application. We will create a controller +`PostController` that interacts with a service called `PostService`. For the sake of simplicity we will only +cover the `delete`-methods of both parts. + +Let's start by creating a controller that has the `PostService` as dependency: + +```php +class PostController +{ + protected $postService; + + public function __construct(PostService $postService) + { + $this->postService = $postService; + } + + // addAction(), editAction(), etc... + + public function deleteAction() + { + $id = $this->params()->fromQuery('id'); + + $this->postService->deletePost($id); + + return $this->redirect()->toRoute('posts'); + } +} +``` + +Since we have a dependency, let's inject it using the `ControllerManager`, we will do this inside our `Module`-Class + +```php +class Module +{ + // getAutoloaderConfig(), getConfig(), etc... + + public function getControllerConfig() + { + return [ + 'factories' => [ + 'PostController' => function($cpm) { + // We assume a Service key 'PostService' here that returns the PostService Class + return new PostController( + $cpm->getServiceLocator()->get('PostService') + ); + } + ] + ]; + } +} +``` + +Now that we got this in place let us quickly define our `PostService`. We will be using a Service that makes use +of Doctrine, so we require a `Doctrine\Common\Persistence\ObjectManager` as dependency. + +```php +use Doctrine\Common\Persistence\ObjectManager; + +class PostService +{ + protected $objectManager; + + public function __construct(ObjectManager $objectManager) + { + $this->objectManager = $objectManager; + } + + public function deletePost($id) + { + $post = $this->objectManager->find('Post', $id); + $this->objectManager->remove($post); + $this->objectManager->flush(); + } +} +``` + +And for this one, too, let's quickly create the factory, again within our `Module` class. + +```php +class Module +{ + // getAutoloaderConfig(), getConfig(), etc... + + public function getServiceConfig() + { + return [ + 'factories' => [ + 'PostService' => function($sm) { + return new PostService( + $sm->get('doctrine.entitymanager.orm_default') + ); + } + ] + ]; + } +} +``` + +With this set up we can now cover some best practices. + +## Best practices + +Ideally, you should not protect your applications using only guards (Route or Controller guards). +This leaves your application open for some undesired side-effects. +As a best practice you should protect all your services or controllers by injecting the authorization service. +But let's go step by step: + +Assuming the application example above we can easily use ZfcRbac to protect our route using the following guard: + +```php +return [ + 'zfc_rbac' => [ + 'guards' => [ + 'ZfcRbac\Guard\RouteGuard' => [ + 'post/delete' => ['admin'] + ] + ] + ] +]; +``` + +Now, any users that do not have the "admin" role will receive a 403 error (unauthorized) when trying to access +the "post/delete" route. However, this does not prevent the service (which should contain the actual logic in a properly +design application) to be injected and used elsewhere in your code. For instance: + +```php +class PostController +{ + protected $postService; + + public function createAction() + { + // this action may have been reached through the "forward" method, hence bypassing guards + $this->postService->deletePost('2'); + } +} +``` + +You see the issue! + +The solution is to inject the `AuthorizationService` into your services, and checking for the +permissions before doing anything wrong. So let's modify our previously created `PostService`-class + +```php +use Doctrine\Common\Persistence\ObjectManager; + +class PostService +{ + protected $objectManager; + + protected $authorizationService; + + public function __construct( + ObjectManager $objectManager, + AuthorizationService $autorizationService + ) { + $this->objectManager = $objectManager; + $this->authorizationService = $autorizationService; + } + + public function deletePost($id) + { + // First check permission + if (!$this->authorizationService->isGranted('deletePost')) { + throw new UnauthorizedException('You are not allowed !'); + } + + $post = $this->objectManager->find('Post', $id); + $this->objectManager->remove($post); + $this->objectManager->flush(); + } +} +``` + +Since we now have an additional dependency we should inject it through our factory, again within our `Module` class. + +```php +class Module +{ + // getAutoloaderConfig(), getConfig(), etc... + + public function getServiceConfig() + { + return [ + 'factories' => [ + 'PostService' => function($sm) { + return new PostService( + $sm->get('doctrine.entitymanager.orm_default'), + $sm->get('ZfcRbac\Service\AuthorizationService') // This is new! + ); + } + ] + ]; + } +} +``` + +Alternatively, you can also protect your controllers using the `isGranted` helper (you do not need to inject +the AuthorizationService then): + +```php +class PostController +{ + protected $postService; + + public function createAction() + { + if (!$this->isGranted('deletePost')) { + throw new UnauthorizedException('You are not allowed !'); + } + + $this->postService->deletePost('2'); + } +} +``` + +While protecting services is the more defensive way (because services are usually the last part of the logic flow), +it is often complicated to deal with. +If your application is architectured correctly, it is often simpler to protect your controllers. + +### When using guards then? + +In fact, you should see guards as a very efficient way to quickly reject access to a hierarchy of routes or a +whole controller. For instance, assuming you have the following route config: + +```php +return [ + 'router' => [ + 'routes' => [ + 'admin' => [ + 'type' => 'Literal', + 'options' => [ + 'route' => '/admin' + ], + 'may_terminate' => true, + 'child_routes' => [ + 'users' => [ + 'type' => 'Literal', + 'options' => [ + 'route' => '/users' + ] + ], + 'invoices' => [ + 'type' => 'Literal', + 'options' => [ + 'route' => '/invoices' + ] + ] + ] + ] + ] + ] +}; +``` + +You can quickly unauthorized access to all admin routes using the following guard: + +```php +return [ + 'zfc_rbac' => [ + 'guards' => [ + 'ZfcRbac\Guard\RouteGuard' => [ + 'admin*' => ['admin'] + ] + ] + ] +]; +``` + +## A Real World Application Part 2 - Only delete your own Posts + +If you jumped straight to this section please notice, that we assume you have the knowledge that we presented in the +previous example. In here we will cover a very common use-case. Users of our Application should only have delete +permissions to their own content. So let's quickly refresh our `PostService` class: + +```php +use Doctrine\Common\Persistence\ObjectManager; + +class PostService +{ + protected $objectManager; + + protected $authorizationService; + + public function __construct( + ObjectManager $objectManager, + AuthorizationService $autorizationService + ) { + $this->objectManager = $objectManager; + $this->authorizationService = $autorizationService; + } + + public function deletePost($id) + { + // First check permission + if (!$this->authorizationService->isGranted('deletePost')) { + throw new UnauthorizedException('You are not allowed !'); + } + + $post = $this->objectManager->find('Post', $id); + $this->objectManager->remove($post); + $this->objectManager->flush(); + } +} +``` + +As we can see, we check within our Service if the User of our Application is allowed to delete the post with a check +against the `deletePost` permission. Now how can we achieve that only a user who is the owner of the Post to be able to +delete his own post, but other users can't? We do not want to change our Service with more complex logic because this +is not the task of such service. The Permission-System should handle this. And we can, for this we have the + [`AssertionPluginManager`](/src/ZfcRbac/Assertion/AssertionPluginManager.php) and here is how to do it: + +First of all things we need to write an Assertion. The Assertion will return a boolean statement about the current +identity being the owner of the post. + +```php +namespace Your\Namespace; + +use ZfcRbac\Assertion\AssertionInterface; +use ZfcRbac\Service\AuthorizationService; + +class MustBeAuthorAssertion implements AssertionInterface +{ + /** + * Check if this assertion is true + * + * @param AuthorizationService $authorization + * @param mixed $post + * + * @return bool + */ + public function assert(AuthorizationService $authorization, $post = null) + { + return $authorization->getIdentity() === $post->getAuthor(); + } +} +``` + +This simple `MustBeAuthorAssertion` will check against the current `$authorization` if it equals the identity of the +current context Author. The second parameter is called the "context". A context can be anything (an object, a scalar, +an array...) and makes only sense in the context of the assertion. + +Imagine a user calls `http://my.dom/post/delete/42`, so obviously he wants to delete the Post-Entity with ID#42. In +this case Entity#42 is our Context! If you're wondering of how the context get there, bare with me, we will get to +this later. + +Now that we have written the Assertion, we want to make sure that this assertion will always be called, whenever we +check for the `deletePost` permission. We don't want others to delete our previous content! For this we have the so- +called `assertion_map`. In this map we glue `assertions` and `permissions` together. + +```php +// module.config.php or wherever you configure your RBAC stuff +return [ + 'zfc_rbac' => [ + 'assertion_map' => [ + 'deletePost' => 'Your\Namespace\MustBeAuthorAssertion' + ] + ] +]; +``` + +Now, whenever some test the `deletePost` permission, it will automatically call the `MustBeAuthorAssertion` from +the `AssertionPluginManager`. This plugin manager is configured to automatically add unknown classes to an invokable. +However, some assertions may need dependencies. You can manually configure the assertion plugin manager as +shown below: + +```php +// module.config.php or wherever you configure your RBAC stuff +return [ + 'zfc_rbac' => [ + // ... other rbac stuff + 'assertion_manager' => [ + 'factories' => [ + 'AssertionWithDependency' => 'Your\Namespace\AssertionWithDependencyFactory' + ] + ] + ] +]; +``` + +Now we need to remember about the **context**. Somehow we need to let the `AssertionPluginManager` know about our +context. This is done as simple as to passing it to the `isGranted()` method. For this we need to modify our Service +one last time. + +```php +use Doctrine\Common\Persistence\ObjectManager; + +class PostService +{ + protected $objectManager; + + protected $authorizationService; + + public function __construct( + ObjectManager $objectManager, + AuthorizationService $autorizationService + ) { + $this->objectManager = $objectManager; + $this->authorizationService = $autorizationService; + } + + public function deletePost($id) + { + // Note, we now need to query for the post of interest first! + $post = $this->objectManager->find('Post', $id); + + // Check the permission now with a given context + if (!$this->authorizationService->isGranted('deletePost', $post)) { + throw new UnauthorizedException('You are not allowed !'); + } + + $this->objectManager->remove($post); + $this->objectManager->flush(); + } +} +``` + +And there you have it. The context is injected into the `isGranted()` method and now the `AssertionPluginManager` knows +about it and can do its thing. Note that in reality, after you have queried for the `$post` you would check if `$post` +is actually a real post. Because if it is an empty return value then you should throw an exception earlier without +needing to check against the permission. + +## A Real World Application Part 3 - Admins can delete everything + +Often, you want users with a specific role to be able to have full access to everything. For instance, admins could +delete all the posts, even if they don't own it. + +However, with the previous assertion, even if the admin has the permission `deletePost`, it won't work because +the assertion will evaluate to false. + +Actually, the answer is quite simple: deleting my own posts and deleting others' posts should be treated like +two different permissions (it makes sense if you think about it). Therefore, admins will have the permission +`deleteOthersPost` (as well as the permission `deletePost`, because admin could write posts, too). + +The assertion must therefore be modified like this: + +```php +namespace Your\Namespace; + +use ZfcRbac\Assertion\AssertionInterface; +use ZfcRbac\Service\AuthorizationService; + +class MustBeAuthorAssertion implements AssertionInterface +{ + /** + * Check if this assertion is true + * + * @param AuthorizationService $authorization + * @param mixed $context + * + * @return bool + */ + public function assert(AuthorizationService $authorization, $context = null) + { + if ($authorization->getIdentity() === $context->getAuthor()) { + return true; + } + + return $authorization->isGranted('deleteOthersPost'); + } +} +``` + +## A Real World Application Part 4 - Checking permissions in the view + +If some part of the view needs to be protected, you can use the shipped ```isGranted``` view helper. + +For example, lets's say that only users with the permissions ```post.manage``` will have a menu item to acces +the adminsitration panel : + +In your template post-index.phtml + +```php +<ul class="nav"> + <li><a href="/">Home</a></li> + <li><a href="/posts/list">View posts</a></li> + <?php if ($this->isGranted('post.manage'): ?> + <li><a href="/posts/admin">Manage posts</a></li> + <?php endif ?> +</ul> +``` + +You can even protect your menu item regarding a role, by using the ```hasRole``` view helper : + +```php +<ul class="nav"> + <li><a href="/">Home</a></li> + <li><a href="/posts/list">View posts</a></li> + <?php if ($this->hasRole('admin'): ?> + <li><a href="/posts/admin">Manage posts</a></li> + <?php endif ?> +</ul> +``` + +In this last example, the menu item will be hidden for users who don't have the ```admin``` role. + +## Using ZfcRbac with Doctrine ORM + +First your User entity class must implement `ZfcRbac\Identity\IdentityInterface` : + +```php +use ZfcUser\Entity\User as ZfcUserEntity; +use ZfcRbac\Identity\IdentityInterface; +use Doctrine\ORM\Mapping as ORM; +use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\Common\Collections\Collection; + +/** + * @ORM\Entity + * @ORM\Table(name="user") + */ +class User extends ZfcUserEntity implements IdentityInterface +{ + /** + * @var Collection + * @ORM\ManyToMany(targetEntity="HierarchicalRole") + */ + private $roles; + + public function __construct() + { + $this->roles = new ArrayCollection(); + } + + /** + * {@inheritDoc} + */ + public function getRoles() + { + return $this->roles->toArray(); + } + + /** + * Set the list of roles + * @param Collection $roles + */ + public function setRoles(Collection $roles) + { + $this->roles->clear(); + foreach ($roles as $role) { + $this->roles[] = $role; + } + } + + /** + * Add one role to roles list + * @param \Rbac\Role\RoleInterface $role + */ + public function addRole(RoleInterface $role) + { + $this->roles[] = $role; + } +} +``` +For this example we will use the more complex situation by using `Rbac\Role\HierarchicalRoleInterface` so the second step is to create HierarchicalRole entity class + +```php +class HierarchicalRole implements HierarchicalRoleInterface +{ + /** + * @var HierarchicalRoleInterface[]|\Doctrine\Common\Collections\Collection + * + * @ORM\ManyToMany(targetEntity="HierarchicalRole") + */ + protected $children; + + /** + * @var PermissionInterface[]|\Doctrine\Common\Collections\Collection + * + * @ORM\ManyToMany(targetEntity="Permission", indexBy="name", fetch="EAGER", cascade={"persist"}) + */ + protected $permissions; + + /** + * Init the Doctrine collection + */ + public function __construct() + { + $this->children = new ArrayCollection(); + $this->permissions = new ArrayCollection(); + } + + /** + * {@inheritDoc} + */ + public function addChild(HierarchicalRoleInterface $child) + { + $this->children[] = $child; + } + + /* + * Set the list of permission + * @param Collection $permissions + */ + public function setPermissions(Collection $permissions) + { + $this->permissions->clear(); + foreach ($permissions as $permission) { + $this->permissions[] = $permission; + } + } + + /** + * {@inheritDoc} + */ + public function addPermission($permission) + { + if (is_string($permission)) { + $permission = new Permission($permission); + } + + $this->permissions[(string) $permission] = $permission; + } + + /** + * {@inheritDoc} + */ + public function hasPermission($permission) + { + // This can be a performance problem if your role has a lot of permissions. Please refer + // to the cookbook to an elegant way to solve this issue + + return isset($this->permissions[(string) $permission]); + } + + /** + * {@inheritDoc} + */ + public function getChildren() + { + return $this->children->toArray(); + } + + /** + * {@inheritDoc} + */ + public function hasChildren() + { + return !$this->children->isEmpty(); + } +} +``` + +And the last step is to create Permission entity class which is a very simple entity class, you don't have to do specific things ! + +You can find all entity example in this folder : [Example](/data) + +You need one more configuration step. Indeed, how can the RoleProvider retrieve your role and permissions ? For this you need to configure `ZfcRbac\Role\ObjectRepositoryRoleProvider` in your `zfc_rbac.global.php` file : +```php + /** + * Configuration for role provider + */ + 'role_provider' => [ + 'ZfcRbac\Role\ObjectRepositoryRoleProvider' => [ + 'object_manager' => 'doctrine.entitymanager.orm_default', // alias for doctrine ObjectManager + 'class_name' => 'User\Entity\HierarchicalRole', // FQCN for your role entity class + 'role_name_property' => 'name', // Name to show + ], + ], +``` + +Using DoctrineORM with ZfcRbac is very simple. You need to be aware from performances where there is a lot of permissions for roles. + +## How to deal with roles with lot of permissions? + +In very complex applications, your roles may have dozens of permissions. In the [/data/FlatRole.php.dist] entity +we provide, we configure the permissions association so that whenever a role is loaded, all its permissions are also +loaded in one query (notice the `fetch="EAGER"`): + +```php +/** + * @ORM\ManyToMany(targetEntity="Permission", indexBy="name", fetch="EAGER") + */ +protected $permissions; +``` + +The `hasPermission` method is therefore really simple: + +```php +public function hasPermission($permission) +{ + return isset($this->permissions[(string) $permission]); +} +``` + +However, with a lot of permissions, this method will quickly kill your database. What you can do is modfiy the Doctrine +mapping so that the collection is not actually loaded: + +```php +/** + * @ORM\ManyToMany(targetEntity="Permission", indexBy="name", fetch="LAZY") + */ +protected $permissions; +``` + +Then, modify the `hasPermission` method to use the Criteria API. The Criteria API is a Doctrine 2.2+ API that allows +to efficiently filter a collection without loading the whole collection: + +```php +use Doctrine\Common\Collections\Criteria; + +public function hasPermission($permission) +{ + $criteria = Criteria::create()->where(Criteria::expr()->eq('name', (string) $permission)); + $result = $this->permissions->matching($criteria); + + return count($result) > 0; +} +``` + +> NOTE: This is only supported starting from Doctrine ORM 2.5! + +## Using ZfcRbac and ZF2 Assetic + +To use [Assetic](https://github.com/widmogrod/zf2-assetic-module) with ZfcRbac guards, you should modify your +`module.config.php` using the following configuration: + +```php +return [ + 'assetic_configuration' => [ + 'acceptableErrors' => [ + \ZfcRbac\Guard\GuardInterface::GUARD_UNAUTHORIZED + ] + ] +]; +``` + +## Using ZfcRbac and ZfcUser + +To use the authentication service from ZfcUser, just add the following alias in your application.config.php: + +```php +return [ + 'service_manager' => [ + 'aliases' => [ + 'Zend\Authentication\AuthenticationService' => 'zfcuser_auth_service' + ] + ] +]; +``` + +Finally add the ZfcUser routes to your `guards`: + +```php +return [ + 'zfc_rbac' => [ + 'guards' => [ + 'ZfcRbac\Guard\RouteGuard' => [ + 'zfcuser/login' => ['guest'], + 'zfcuser/register' => ['guest'], // required if registration is enabled + 'zfcuser*' => ['user'] // includes logout, changepassword and changeemail + ] + ] + ] +]; +``` + +### Navigation + +* Back to [the Using the Authorization Service](/docs/06. Using the Authorization Service.md) +* Back to [the Index](/docs/README.md) diff --git a/vendor/zf-commons/zfc-rbac/docs/README.md b/vendor/zf-commons/zfc-rbac/docs/README.md new file mode 100644 index 00000000000..72039c69434 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/docs/README.md @@ -0,0 +1,52 @@ +_Up-to-date with version 2.3.* of ZfcRbac_ + +Welcome to the official ZfcRbac documentation. This documentation will help you to quickly understand how to use +and extend ZfcRbac. + +If you are looking for some information that is not listed in the documentation, please open an issue! + +1. [Introduction](/docs/01. Introduction.md) + 1. [Why should I use an authorization module?](/docs/01. Introduction.md#why-should-i-use-an-authorization-module) + 2. [What is the Rbac model?](/docs/01. Introduction.md#what-is-the-rbac-model) + 3. [How can I integrate ZfcRbac into my application?](/docs/01. Introduction.md#how-can-i-integrate-zfcrbac-into-my-application) + +2. [Quick Start](/docs/02. Quick Start.md) + 1. [Specifying an identity provider](/docs/02. Quick Start.md#specifying-an-identity-provider) + 2. [Adding a guard](/docs/02. Quick Start.md#adding-a-guard) + 3. [Adding a role provider](/docs/02. Quick Start.md#adding-a-role-provider) + 5. [Registering a strategy](/docs/02. Quick Start.md#registering-a-strategy) + 6. [Using the authorization service](/docs/02. Quick Start.md#using-the-authorization-service) + +3. [Role providers](/docs/03. Role providers.md) + 1. [What are role providers?](/docs/03. Role providers.md#what-are-role-providers) + 2. [Identity providers](/docs/03. Role providers.md#identity-providers) + 3. [Built-in role providers](/docs/03. Role providers.md#built-in-role-providers) + 4. [Creating custom role providers](/docs/03. Role providers.md#creating-custom-role-providers) + +4. [Guards](/docs/04. Guards.md) + 1. [What are guards and when to use them?](/docs/04. Guards.md#what-are-guards-and-when-to-use-them) + 2. [Built-in guards](/docs/04. Guards.md#built-in-guards) + 3. [Creating custom guards](/docs/04. Guards.md#creating-custom-guards) + +5. [Strategies](/docs/05. Strategies.md) + 1. [What are strategies?](/docs/05. Strategies.md#what-are-strategies) + 2. [Built-in strategies](/docs/05. Strategies.md#built-in-strategies) + 3. [Creating custom strategies](/docs/05. Strategies.md#creating-custom-strategies) + +6. [Using the Authorization Service](/docs/06. Using the Authorization Service.md) + 1. [Injecting the AuthorizationService](/docs/06. Using the Authorization Service.md#injecting-the-authorization-service) + 2. [Checking permissions](/docs/06. Using the Authorization Service.md#checking-permissions-in-a-service) + 1. [In a service](/docs/06. Using the Authorization Service.md#checking-permissions-in-a-service) + 2. [In a controller's action using the isGranted controller pluign] + (/docs/06. Using the Authorization Service.md#checking-permissions-in-a-controller-or-in-a-view) + 3. [In a view using the isGranted view helper] + (/docs/06. Using the Authorization Service.md#checking-permissions-in-a-a-controller-or-in-a-view) + 3. [Permissions and Assertions](/docs/06. Using the Authorization Service.md#permissions-and-assertions) + +7. [Cookbook](/docs/07. Cookbook.md) + 1. [A real world example](/docs/07. Cookbook.md#a-real-world-application) + 2. [Best practices](/docs/07. Cookbook.md#best-practices) + 3. [Using ZfcRbac with Doctrine ORM](/docs/07. Cookbook.md#using-zfcrbac-with-doctrine-orm) + 4. [How to deal with roles with lot of permissions?](/docs/07. Cookbook.md#how-to-deal-with-roles-with-lot-of-permissions) + 5. [Using ZfcRbac and ZF2 Assetic](/docs/07. Cookbook.md#using-zfcrbac-and-zf2-assetic) + 6. [Using ZfcRbac and ZfcUser](/docs/07. Cookbook.md#using-zfcrbac-and-zfcuser) diff --git a/vendor/zf-commons/zfc-rbac/docs/images/workflow-with-guards.png b/vendor/zf-commons/zfc-rbac/docs/images/workflow-with-guards.png new file mode 100644 index 0000000000000000000000000000000000000000..3c3d21799b3b02eececb149bcecf20bcc1f41966 GIT binary patch literal 32236 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 literal 0 HcmV?d00001 diff --git a/vendor/zf-commons/zfc-rbac/docs/images/workflow-without-guards.png b/vendor/zf-commons/zfc-rbac/docs/images/workflow-without-guards.png new file mode 100644 index 0000000000000000000000000000000000000000..fd49abadd8e3f151c4b9c330eaa9099175e0bcea GIT binary patch literal 8905 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 literal 0 HcmV?d00001 diff --git a/vendor/zf-commons/zfc-rbac/phpunit.xml.dist b/vendor/zf-commons/zfc-rbac/phpunit.xml.dist new file mode 100644 index 00000000000..5a5fa78f15e --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/phpunit.xml.dist @@ -0,0 +1,22 @@ +<?xml version="1.0"?> +<phpunit + bootstrap="./tests/Bootstrap.php" + colors="true" + convertErrorsToExceptions="true" + convertNoticesToExceptions="true" + convertWarningsToExceptions="true" + verbose="true" + stopOnFailure="false" + processIsolation="false" + backupGlobals="false" + syntaxCheck="true" + > + <testsuite name="ZfcRbac tests"> + <directory>./tests</directory> + </testsuite> + <filter> + <whitelist addUncoveredFilesFromWhitelist="true"> + <directory suffix=".php">./src</directory> + </whitelist> + </filter> +</phpunit> \ No newline at end of file diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Assertion/AssertionInterface.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Assertion/AssertionInterface.php new file mode 100644 index 00000000000..88095c6548f --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Assertion/AssertionInterface.php @@ -0,0 +1,43 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Assertion; + +use ZfcRbac\Service\AuthorizationService; + +/** + * Interface that you can implement for dynamic assertions + * + * @author Michaël Gallego <mic.gallego@gmail.com> + * @author Aeneas Rekkas + * @author Daniel Gimenes <daniel@danielgimenes.com.br> + * @licence MIT + */ +interface AssertionInterface +{ + /** + * Check if this assertion is true + * + * @TODO: for v3, update the interface to typehint to AuthorizationServiceInterface instead + * + * @param AuthorizationService $authorizationService + * @param mixed $context + * @return bool + */ + public function assert(AuthorizationService $authorizationService); +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Assertion/AssertionPluginManager.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Assertion/AssertionPluginManager.php new file mode 100644 index 00000000000..0813db3bbbb --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Assertion/AssertionPluginManager.php @@ -0,0 +1,56 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Assertion; + +use Zend\ServiceManager\AbstractPluginManager; +use ZfcRbac\Exception; + +/** + * Plugin manager to create assertions + * + * @author Aeneas Rekkas + * @licence MIT + * + * @method AssertionInterface get($name) + */ +class AssertionPluginManager extends AbstractPluginManager +{ + /** + * {@inheritDoc} + */ + public function validatePlugin($plugin) + { + if ($plugin instanceof AssertionInterface) { + return; // we're okay + } + + throw new Exception\RuntimeException(sprintf( + 'Assertions must implement "ZfcRbac\Assertion\AssertionInterface", but "%s" was given', + is_object($plugin) ? get_class($plugin) : gettype($plugin) + )); + } + + /** + * {@inheritDoc} + */ + protected function canonicalizeName($name) + { + return $name; + } +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Collector/RbacCollector.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Collector/RbacCollector.php new file mode 100644 index 00000000000..532a867c953 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Collector/RbacCollector.php @@ -0,0 +1,230 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Collector; + +use Rbac\Role\HierarchicalRoleInterface; +use Rbac\Role\RoleInterface; +use Rbac\Traversal\RecursiveRoleIterator; +use RecursiveIteratorIterator; +use ReflectionProperty; +use Serializable; +use Traversable; +use Zend\Mvc\MvcEvent; +use ZendDeveloperTools\Collector\CollectorInterface; +use ZfcRbac\Options\ModuleOptions; +use ZfcRbac\Service\RoleService; + +/** + * RbacCollector + * + * @author Michaël Gallego <mic.gallego@gmail.com> + * @licence MIT + */ +class RbacCollector implements CollectorInterface, Serializable +{ + /** + * Collector priority + */ + const PRIORITY = -100; + + /** + * @var array + */ + protected $collection = []; + + /** + * @var array + */ + protected $collectedGuards = []; + + /** + * @var array + */ + protected $collectedRoles = []; + + /** + * @var array + */ + protected $collectedPermissions = []; + + /** + * @var array + */ + protected $collectedOptions = []; + + /** + * Collector Name. + * + * @return string + */ + public function getName() + { + return 'zfc_rbac'; + } + + /** + * Collector Priority. + * + * @return integer + */ + public function getPriority() + { + return self::PRIORITY; + } + + /** + * Collects data. + * + * @param MvcEvent $mvcEvent + */ + public function collect(MvcEvent $mvcEvent) + { + if (!$application = $mvcEvent->getApplication()) { + return; + } + + $serviceManager = $application->getServiceManager(); + + /* @var \ZfcRbac\Service\RoleService $roleService */ + $roleService = $serviceManager->get('ZfcRbac\Service\RoleService'); + + /* @var \ZfcRbac\Options\ModuleOptions $options */ + $options = $serviceManager->get('ZfcRbac\Options\ModuleOptions'); + + // Start collect all the data we need! + $this->collectOptions($options); + $this->collectGuards($options->getGuards()); + $this->collectIdentityRolesAndPermissions($roleService); + } + + /** + * Collect options + * + * @param ModuleOptions $moduleOptions + * @return void + */ + private function collectOptions(ModuleOptions $moduleOptions) + { + $this->collectedOptions = [ + 'guest_role' => $moduleOptions->getGuestRole(), + 'protection_policy' => $moduleOptions->getProtectionPolicy() + ]; + } + + /** + * Collect guards + * + * @param array $guards + * @return void + */ + private function collectGuards($guards) + { + $this->collectedGuards = []; + + foreach ($guards as $type => $rules) { + $this->collectedGuards[$type] = $rules; + } + } + + /** + * Collect roles and permissions + * + * @param RoleService $roleService + * @return void + */ + private function collectIdentityRolesAndPermissions(RoleService $roleService) + { + $identityRoles = $roleService->getIdentityRoles(); + + foreach ($identityRoles as $role) { + $roleName = $role->getName(); + + if (!$role instanceof HierarchicalRoleInterface) { + $this->collectedRoles[] = $roleName; + } else { + $iteratorIterator = new RecursiveIteratorIterator( + new RecursiveRoleIterator($role->getChildren()), + RecursiveIteratorIterator::SELF_FIRST + ); + + foreach ($iteratorIterator as $childRole) { + $this->collectedRoles[$roleName][] = $childRole->getName(); + $this->collectPermissions($childRole); + } + } + + $this->collectPermissions($role); + } + } + + /** + * Collect permissions for the given role + * + * @param RoleInterface $role + * @return void + */ + private function collectPermissions(RoleInterface $role) + { + // Gather the permissions for the given role. We have to use reflection as + // the RoleInterface does not have "getPermissions" method + $reflectionProperty = new ReflectionProperty($role, 'permissions'); + $reflectionProperty->setAccessible(true); + + $permissions = $reflectionProperty->getValue($role); + + if ($permissions instanceof Traversable) { + $permissions = iterator_to_array($permissions); + } + + array_walk($permissions, function (&$permission) { + $permission = (string) $permission; + }); + + $this->collectedPermissions[$role->getName()] = array_values($permissions); + } + + /** + * @return array|string[] + */ + public function getCollection() + { + return $this->collection; + } + + /** + * {@inheritDoc} + */ + public function serialize() + { + return serialize([ + 'guards' => $this->collectedGuards, + 'roles' => $this->collectedRoles, + 'permissions' => $this->collectedPermissions, + 'options' => $this->collectedOptions + ]); + } + + /** + * {@inheritDoc} + */ + public function unserialize($serialized) + { + $this->collection = unserialize($serialized); + } +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Exception/ExceptionInterface.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Exception/ExceptionInterface.php new file mode 100644 index 00000000000..a2c5474167a --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Exception/ExceptionInterface.php @@ -0,0 +1,29 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Exception; + +/** + * Base exception interface for ZfcRbac + * + * @author Michaël Gallego <mic.gallego@gmail.com> + * @licence MIT + */ +interface ExceptionInterface +{ +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Exception/InvalidArgumentException.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Exception/InvalidArgumentException.php new file mode 100644 index 00000000000..e58af1a3c03 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Exception/InvalidArgumentException.php @@ -0,0 +1,31 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Exception; + +use InvalidArgumentException as BaseInvalidArgumentException; + +/** + * InvalidArgumentException + * + * @author Michaël Gallego <mic.gallego@gmail.com> + * @licence MIT + */ +class InvalidArgumentException extends BaseInvalidArgumentException implements ExceptionInterface +{ +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Exception/RoleNotFoundException.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Exception/RoleNotFoundException.php new file mode 100644 index 00000000000..1bfbdacb6b9 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Exception/RoleNotFoundException.php @@ -0,0 +1,35 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Exception; + +use RuntimeException as BaseRuntimeException; + +/** + * Exception that is thrown when a role cannot be found (for instance from a provider) + * + * @author Michaël Gallego <mic.gallego@gmail.com> + * @licence MIT + */ +class RoleNotFoundException extends BaseRuntimeException implements ExceptionInterface +{ + /** + * @var string + */ + protected $message = 'No role could be found'; +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Exception/RuntimeException.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Exception/RuntimeException.php new file mode 100644 index 00000000000..9125ab5684d --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Exception/RuntimeException.php @@ -0,0 +1,31 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Exception; + +use RuntimeException as BaseRuntimeException; + +/** + * RuntimeException + * + * @author Michaël Gallego <mic.gallego@gmail.com> + * @licence MIT + */ +class RuntimeException extends BaseRuntimeException implements ExceptionInterface +{ +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Exception/UnauthorizedException.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Exception/UnauthorizedException.php new file mode 100644 index 00000000000..eeb2490aa3f --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Exception/UnauthorizedException.php @@ -0,0 +1,35 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Exception; + +use RuntimeException as BaseRuntimeException; + +/** + * Unauthorized exception + * + * @author Michaël Gallego <mic.gallego@gmail.com> + * @licence MIT + */ +class UnauthorizedException extends BaseRuntimeException implements UnauthorizedExceptionInterface +{ + /** + * @var string + */ + protected $message = 'You are not authorized to access this resource'; +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Exception/UnauthorizedExceptionInterface.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Exception/UnauthorizedExceptionInterface.php new file mode 100644 index 00000000000..ad7d32b5bde --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Exception/UnauthorizedExceptionInterface.php @@ -0,0 +1,29 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Exception; + +/** + * Interface for an unauthorized exception + * + * @author Michaël Gallego <mic.gallego@gmail.com> + * @licence MIT + */ +interface UnauthorizedExceptionInterface extends ExceptionInterface +{ +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/AssertionPluginManagerFactory.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/AssertionPluginManagerFactory.php new file mode 100644 index 00000000000..6ff9e63da8e --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/AssertionPluginManagerFactory.php @@ -0,0 +1,47 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Factory; + +use Zend\ServiceManager\Config; +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; +use ZfcRbac\Assertion\AssertionPluginManager; + +/** + * Factory to create a assertion plugin manager + * + * @author Aeneas Rekkas + * @licence MIT + */ +class AssertionPluginManagerFactory implements FactoryInterface +{ + /** + * {@inheritDoc} + * @return AssertionPluginManager + */ + public function createService(ServiceLocatorInterface $serviceLocator) + { + $config = $serviceLocator->get('Config')['zfc_rbac']['assertion_manager']; + + $pluginManager = new AssertionPluginManager(new Config($config)); + $pluginManager->setServiceLocator($serviceLocator); + + return $pluginManager; + } +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/AuthenticationIdentityProviderFactory.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/AuthenticationIdentityProviderFactory.php new file mode 100644 index 00000000000..e0ec541ebc0 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/AuthenticationIdentityProviderFactory.php @@ -0,0 +1,44 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Factory; + +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; +use ZfcRbac\Identity\AuthenticationIdentityProvider; + +/** + * Factory to create the authentication identity provider + * + * @author Michaël Gallego <mic.gallego@gmail.com> + * @licence MIT + */ +class AuthenticationIdentityProviderFactory implements FactoryInterface +{ + /** + * {@inheritDoc} + * @return AuthenticationIdentityProvider + */ + public function createService(ServiceLocatorInterface $serviceLocator) + { + /* @var \Zend\Authentication\AuthenticationService $authenticationProvider */ + $authenticationProvider = $serviceLocator->get('Zend\Authentication\AuthenticationService'); + + return new AuthenticationIdentityProvider($authenticationProvider); + } +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/AuthorizationServiceDelegatorFactory.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/AuthorizationServiceDelegatorFactory.php new file mode 100644 index 00000000000..feed79700c2 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/AuthorizationServiceDelegatorFactory.php @@ -0,0 +1,52 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Factory; + +use Zend\ServiceManager\AbstractPluginManager; +use Zend\ServiceManager\DelegatorFactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; +use ZfcRbac\Exception\RuntimeException; +use ZfcRbac\Service\AuthorizationServiceAwareInterface; + +/** + * Delegator factory for classes implementing AuthorizationServiceAwareInterface + * + * @author Jean-Marie Leroux <jmleroux.pro@gmail.com> + * @license MIT License + */ +class AuthorizationServiceDelegatorFactory implements DelegatorFactoryInterface +{ + public function createDelegatorWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName, $callback) + { + $instanceToDecorate = call_user_func($callback); + + if (!$instanceToDecorate instanceof AuthorizationServiceAwareInterface) { + throw new RuntimeException("The service $requestedName must implement AuthorizationServiceAwareInterface."); + } + + if ($serviceLocator instanceof AbstractPluginManager) { + $serviceLocator = $serviceLocator->getServiceLocator(); + } + + $authorizationService = $serviceLocator->get('ZfcRbac\Service\AuthorizationService'); + $instanceToDecorate->setAuthorizationService($authorizationService); + + return $instanceToDecorate; + } +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/AuthorizationServiceFactory.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/AuthorizationServiceFactory.php new file mode 100644 index 00000000000..49cd88d5daa --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/AuthorizationServiceFactory.php @@ -0,0 +1,56 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Factory; + +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; +use ZfcRbac\Service\AuthorizationService; + +/** + * Factory to create the authorization service + * + * @author Michaël Gallego <mic.gallego@gmail.com> + * @licence MIT + */ +class AuthorizationServiceFactory implements FactoryInterface +{ + /** + * {@inheritDoc} + * @return AuthorizationService + */ + public function createService(ServiceLocatorInterface $serviceLocator) + { + /* @var \Rbac\Rbac $rbac */ + $rbac = $serviceLocator->get('Rbac\Rbac'); + + /* @var \ZfcRbac\Service\RoleService $roleService */ + $roleService = $serviceLocator->get('ZfcRbac\Service\RoleService'); + + /* @var \ZfcRbac\Assertion\AssertionPluginManager $assertionPluginManager */ + $assertionPluginManager = $serviceLocator->get('ZfcRbac\Assertion\AssertionPluginManager'); + + /* @var \ZfcRbac\Options\ModuleOptions $moduleOptions */ + $moduleOptions = $serviceLocator->get('ZfcRbac\Options\ModuleOptions'); + + $authorizationService = new AuthorizationService($rbac, $roleService, $assertionPluginManager); + $authorizationService->setAssertions($moduleOptions->getAssertionMap()); + + return $authorizationService; + } +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/ControllerGuardFactory.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/ControllerGuardFactory.php new file mode 100644 index 00000000000..1bb88428448 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/ControllerGuardFactory.php @@ -0,0 +1,66 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Factory; + +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\MutableCreationOptionsInterface; +use Zend\ServiceManager\ServiceLocatorInterface; +use ZfcRbac\Guard\ControllerGuard; + +/** + * Create a controller guard + * + * @author Michaël Gallego <mic.gallego@gmail.com> + * @licence MIT + */ +class ControllerGuardFactory implements FactoryInterface, MutableCreationOptionsInterface +{ + /** + * @var array + */ + protected $options = []; + + /** + * {@inheritDoc} + */ + public function setCreationOptions(array $options) + { + $this->options = $options; + } + + /** + * {@inheritDoc} + * @return ControllerGuard + */ + public function createService(ServiceLocatorInterface $serviceLocator) + { + $parentLocator = $serviceLocator->getServiceLocator(); + + /* @var \ZfcRbac\Options\ModuleOptions $moduleOptions */ + $moduleOptions = $parentLocator->get('ZfcRbac\Options\ModuleOptions'); + + /* @var \ZfcRbac\Service\RoleService $roleService */ + $roleService = $parentLocator->get('ZfcRbac\Service\RoleService'); + + $controllerGuard = new ControllerGuard($roleService, $this->options); + $controllerGuard->setProtectionPolicy($moduleOptions->getProtectionPolicy()); + + return $controllerGuard; + } +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/ControllerPermissionsGuardFactory.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/ControllerPermissionsGuardFactory.php new file mode 100644 index 00000000000..0ca7acfe659 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/ControllerPermissionsGuardFactory.php @@ -0,0 +1,67 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Factory; + +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\MutableCreationOptionsInterface; +use Zend\ServiceManager\ServiceLocatorInterface; +use ZfcRbac\Guard\ControllerPermissionsGuard; +use ZfcRbac\Guard\RouteGuard; + +/** + * Create a controller guard for checking permissions + * + * @author JM Lerouxw <jmleroux.pro@gmail.com> + * @licence MIT + */ +class ControllerPermissionsGuardFactory implements FactoryInterface, MutableCreationOptionsInterface +{ + /** + * @var array + */ + protected $options = []; + + /** + * {@inheritDoc} + */ + public function setCreationOptions(array $options) + { + $this->options = $options; + } + + /** + * @param \Zend\ServiceManager\AbstractPluginManager|ServiceLocatorInterface $serviceLocator + * @return RouteGuard + */ + public function createService(ServiceLocatorInterface $serviceLocator) + { + $parentLocator = $serviceLocator->getServiceLocator(); + + /* @var \ZfcRbac\Options\ModuleOptions $moduleOptions */ + $moduleOptions = $parentLocator->get('ZfcRbac\Options\ModuleOptions'); + + /* @var \ZfcRbac\Service\AuthorizationService $authorizationService */ + $authorizationService = $parentLocator->get('ZfcRbac\Service\AuthorizationService'); + + $guard = new ControllerPermissionsGuard($authorizationService, $this->options); + $guard->setProtectionPolicy($moduleOptions->getProtectionPolicy()); + + return $guard; + } +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/GuardPluginManagerFactory.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/GuardPluginManagerFactory.php new file mode 100644 index 00000000000..4eab407330b --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/GuardPluginManagerFactory.php @@ -0,0 +1,47 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Factory; + +use Zend\ServiceManager\Config; +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; +use ZfcRbac\Guard\GuardPluginManager; + +/** + * Factory to create a guard plugin manager + * + * @author Michaël Gallego <mic.gallego@gmail.com> + * @licence MIT + */ +class GuardPluginManagerFactory implements FactoryInterface +{ + /** + * {@inheritDoc} + * @return GuardPluginManager + */ + public function createService(ServiceLocatorInterface $serviceLocator) + { + $config = $serviceLocator->get('Config')['zfc_rbac']['guard_manager']; + + $pluginManager = new GuardPluginManager(new Config($config)); + $pluginManager->setServiceLocator($serviceLocator); + + return $pluginManager; + } +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/GuardsFactory.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/GuardsFactory.php new file mode 100644 index 00000000000..4ff51200c8b --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/GuardsFactory.php @@ -0,0 +1,56 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Factory; + +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; + +/** + * Create a list of guards + * + * @author Michaël Gallego <mic.gallego@gmail.com> + * @licence MIT + */ +class GuardsFactory implements FactoryInterface +{ + /** + * {@inheritDoc} + * @return \ZfcRbac\Guard\GuardInterface[]|array + */ + public function createService(ServiceLocatorInterface $serviceLocator) + { + /* @var \ZfcRbac\Options\ModuleOptions $options */ + $options = $serviceLocator->get('ZfcRbac\Options\ModuleOptions'); + $guardsOptions = $options->getGuards(); + + if (empty($guardsOptions)) { + return []; + } + + /* @var \ZfcRbac\Guard\GuardPluginManager $pluginManager */ + $pluginManager = $serviceLocator->get('ZfcRbac\Guard\GuardPluginManager'); + $guards = []; + + foreach ($guardsOptions as $type => $options) { + $guards[] = $pluginManager->get($type, $options); + } + + return $guards; + } +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/HasRoleViewHelperFactory.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/HasRoleViewHelperFactory.php new file mode 100644 index 00000000000..bf27bd1323b --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/HasRoleViewHelperFactory.php @@ -0,0 +1,45 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Factory; + +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; +use ZfcRbac\Service\RoleService; +use ZfcRbac\View\Helper\HasRole; + +/** + * Create the HasRole view helper + * + * @author JM Leroux <jmleroux.pro@gmail.com> + * @licence MIT + */ +class HasRoleViewHelperFactory implements FactoryInterface +{ + /** + * {@inheritDoc} + * @return HasRole + */ + public function createService(ServiceLocatorInterface $serviceLocator) + { + /* @var RoleService $roleService */ + $roleService = $serviceLocator->getServiceLocator()->get('ZfcRbac\Service\RoleService'); + + return new HasRole($roleService); + } +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/IsGrantedPluginFactory.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/IsGrantedPluginFactory.php new file mode 100644 index 00000000000..2de14e3f684 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/IsGrantedPluginFactory.php @@ -0,0 +1,44 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Factory; + +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; +use ZfcRbac\Mvc\Controller\Plugin\IsGranted; + +/** + * Create the IsGranted controller plugin + * + * @author Michaël Gallego <mic.gallego@gmail.com> + * @licence MIT + */ +class IsGrantedPluginFactory implements FactoryInterface +{ + /** + * {@inheritDoc} + * @return IsGranted + */ + public function createService(ServiceLocatorInterface $serviceLocator) + { + /* @var \ZfcRbac\Service\AuthorizationService $authorizationService */ + $authorizationService = $serviceLocator->getServiceLocator()->get('ZfcRbac\Service\AuthorizationService'); + + return new IsGranted($authorizationService); + } +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/IsGrantedViewHelperFactory.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/IsGrantedViewHelperFactory.php new file mode 100644 index 00000000000..aef60e25238 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/IsGrantedViewHelperFactory.php @@ -0,0 +1,44 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Factory; + +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; +use ZfcRbac\View\Helper\IsGranted; + +/** + * Create the IsGranted view helper + * + * @author Michaël Gallego <mic.gallego@gmail.com> + * @licence MIT + */ +class IsGrantedViewHelperFactory implements FactoryInterface +{ + /** + * {@inheritDoc} + * @return IsGranted + */ + public function createService(ServiceLocatorInterface $serviceLocator) + { + /* @var \ZfcRbac\Service\AuthorizationService $authorizationService */ + $authorizationService = $serviceLocator->getServiceLocator()->get('ZfcRbac\Service\AuthorizationService'); + + return new IsGranted($authorizationService); + } +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/ModuleOptionsFactory.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/ModuleOptionsFactory.php new file mode 100644 index 00000000000..20f543cfafa --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/ModuleOptionsFactory.php @@ -0,0 +1,41 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Factory; + +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; +use ZfcRbac\Options\ModuleOptions; + +/** + * Factory for the module options + * + * @author Michaël Gallego <mic.gallego@gmail.com> + * @licence MIT + */ +class ModuleOptionsFactory implements FactoryInterface +{ + /** + * {@inheritDoc} + * @return ModuleOptions + */ + public function createService(ServiceLocatorInterface $serviceLocator) + { + return new ModuleOptions($serviceLocator->get('Config')['zfc_rbac']); + } +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/ObjectRepositoryRoleProviderFactory.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/ObjectRepositoryRoleProviderFactory.php new file mode 100644 index 00000000000..0a18bdfb29d --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/ObjectRepositoryRoleProviderFactory.php @@ -0,0 +1,81 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Factory; + +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\MutableCreationOptionsInterface; +use Zend\ServiceManager\ServiceLocatorInterface; +use ZfcRbac\Exception; +use ZfcRbac\Role\ObjectRepositoryRoleProvider; + +/** + * Factory used to create an object repository role provider + * + * @author Michaël Gallego <mic.gallego@gmail.com> + * @licence MIT + */ +class ObjectRepositoryRoleProviderFactory implements FactoryInterface, MutableCreationOptionsInterface +{ + /** + * @var array + */ + protected $options = []; + + /** + * {@inheritDoc} + */ + public function setCreationOptions(array $options) + { + $this->options = $options; + } + + /** + * {@inheritDoc} + * @return ObjectRepositoryRoleProvider + */ + public function createService(ServiceLocatorInterface $serviceLocator) + { + $parentLocator = $serviceLocator->getServiceLocator(); + $objectRepository = null; + + if (!isset($this->options['role_name_property'])) { + throw new Exception\RuntimeException('The "role_name_property" option is missing'); + } + + if (isset($this->options['object_repository'])) { + /* @var \Doctrine\Common\Persistence\ObjectRepository $objectRepository */ + $objectRepository = $parentLocator->get($this->options['object_repository']); + + return new ObjectRepositoryRoleProvider($objectRepository, $this->options['role_name_property']); + } + + if (isset($this->options['object_manager']) && isset($this->options['class_name'])) { + /* @var \Doctrine\Common\Persistence\ObjectManager $objectManager */ + $objectManager = $parentLocator->get($this->options['object_manager']); + $objectRepository = $objectManager->getRepository($this->options['class_name']); + + return new ObjectRepositoryRoleProvider($objectRepository, $this->options['role_name_property']); + } + + throw new Exception\RuntimeException( + 'No object repository was found while creating the ZfcRbac object repository role provider. Are + you sure you specified either the "object_repository" option or "object_manager"/"class_name" options?' + ); + } +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/RbacFactory.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/RbacFactory.php new file mode 100644 index 00000000000..6cd333e9b81 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/RbacFactory.php @@ -0,0 +1,46 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Factory; + +use Rbac\Rbac; +use Rbac\Traversal\Strategy\GeneratorStrategy; +use Rbac\Traversal\Strategy\RecursiveRoleIteratorStrategy; +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; + +/** + * @author Michaël Gallego <mic.gallego@gmail.com> + * @licence MIT + */ +class RbacFactory implements FactoryInterface +{ + /** + * {@inheritDoc} + */ + public function createService(ServiceLocatorInterface $serviceLocator) + { + if (version_compare(PHP_VERSION, '5.5.0', '>=')) { + $traversalStrategy = new GeneratorStrategy(); + } else { + $traversalStrategy = new RecursiveRoleIteratorStrategy(); + } + + return new Rbac($traversalStrategy); + } +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/RedirectStrategyFactory.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/RedirectStrategyFactory.php new file mode 100644 index 00000000000..d186df7b25b --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/RedirectStrategyFactory.php @@ -0,0 +1,45 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Factory; + +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; +use ZfcRbac\View\Strategy\RedirectStrategy; + +/** + * Factory to create a redirect strategy + * + * @author Michaël Gallego <mic.gallego@gmail.com> + * @licence MIT + */ +class RedirectStrategyFactory implements FactoryInterface +{ + /** + * {@inheritDoc} + */ + public function createService(ServiceLocatorInterface $serviceLocator) + { + /* @var \ZfcRbac\Options\ModuleOptions $moduleOptions */ + $moduleOptions = $serviceLocator->get('ZfcRbac\Options\ModuleOptions'); + /** @var \Zend\Authentication\AuthenticationService $authenticationService */ + $authenticationService = $serviceLocator->get('Zend\Authentication\AuthenticationService'); + + return new RedirectStrategy($moduleOptions->getRedirectStrategy(), $authenticationService); + } +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/RoleProviderPluginManagerFactory.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/RoleProviderPluginManagerFactory.php new file mode 100644 index 00000000000..084c9923f7d --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/RoleProviderPluginManagerFactory.php @@ -0,0 +1,47 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Factory; + +use Zend\ServiceManager\Config; +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; +use ZfcRbac\Role\RoleProviderPluginManager; + +/** + * Factory to create a role provider plugin manager + * + * @author Michaël Gallego <mic.gallego@gmail.com> + * @licence MIT + */ +class RoleProviderPluginManagerFactory implements FactoryInterface +{ + /** + * {@inheritDoc} + * @return RoleProviderPluginManager + */ + public function createService(ServiceLocatorInterface $serviceLocator) + { + $config = $serviceLocator->get('Config')['zfc_rbac']['role_provider_manager']; + + $pluginManager = new RoleProviderPluginManager(new Config($config)); + $pluginManager->setServiceLocator($serviceLocator); + + return $pluginManager; + } +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/RoleServiceFactory.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/RoleServiceFactory.php new file mode 100644 index 00000000000..e7041fd3b90 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/RoleServiceFactory.php @@ -0,0 +1,66 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Factory; + +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; +use ZfcRbac\Exception\RuntimeException; +use ZfcRbac\Service\RoleService; + +/** + * Factory to create the role service + * + * @author Michaël Gallego <mic.gallego@gmail.com> + * @licence MIT + */ +class RoleServiceFactory implements FactoryInterface +{ + /** + * {@inheritDoc} + * @return RoleService + */ + public function createService(ServiceLocatorInterface $serviceLocator) + { + /* @var \ZfcRbac\Options\ModuleOptions $moduleOptions */ + $moduleOptions = $serviceLocator->get('ZfcRbac\Options\ModuleOptions'); + + /* @var \ZfcRbac\Identity\IdentityProviderInterface $identityProvider */ + $identityProvider = $serviceLocator->get($moduleOptions->getIdentityProvider()); + + $roleProviderConfig = $moduleOptions->getRoleProvider(); + + if (empty($roleProviderConfig)) { + throw new RuntimeException('No role provider has been set for ZfcRbac'); + } + + /* @var \ZfcRbac\Role\RoleProviderPluginManager $pluginManager */ + $pluginManager = $serviceLocator->get('ZfcRbac\Role\RoleProviderPluginManager'); + + /* @var \ZfcRbac\Role\RoleProviderInterface $roleProvider */ + $roleProvider = $pluginManager->get(key($roleProviderConfig), current($roleProviderConfig)); + + /* @var \Rbac\Traversal\Strategy\TraversalStrategyInterface $traversalStrategy */ + $traversalStrategy = $serviceLocator->get('Rbac\Rbac')->getTraversalStrategy(); + + $roleService = new RoleService($identityProvider, $roleProvider, $traversalStrategy); + $roleService->setGuestRole($moduleOptions->getGuestRole()); + + return $roleService; + } +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/RouteGuardFactory.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/RouteGuardFactory.php new file mode 100644 index 00000000000..7bf4f67b892 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/RouteGuardFactory.php @@ -0,0 +1,66 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Factory; + +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\MutableCreationOptionsInterface; +use Zend\ServiceManager\ServiceLocatorInterface; +use ZfcRbac\Guard\RouteGuard; + +/** + * Create a route guard + * + * @author Michaël Gallego <mic.gallego@gmail.com> + * @licence MIT + */ +class RouteGuardFactory implements FactoryInterface, MutableCreationOptionsInterface +{ + /** + * @var array + */ + protected $options = []; + + /** + * {@inheritDoc} + */ + public function setCreationOptions(array $options) + { + $this->options = $options; + } + + /** + * {@inheritDoc} + * @return RouteGuard + */ + public function createService(ServiceLocatorInterface $serviceLocator) + { + $parentLocator = $serviceLocator->getServiceLocator(); + + /* @var \ZfcRbac\Options\ModuleOptions $moduleOptions */ + $moduleOptions = $parentLocator->get('ZfcRbac\Options\ModuleOptions'); + + /* @var \ZfcRbac\Service\RoleService $roleService */ + $roleService = $parentLocator->get('ZfcRbac\Service\RoleService'); + + $routeGuard = new RouteGuard($roleService, $this->options); + $routeGuard->setProtectionPolicy($moduleOptions->getProtectionPolicy()); + + return $routeGuard; + } +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/RoutePermissionsGuardFactory.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/RoutePermissionsGuardFactory.php new file mode 100644 index 00000000000..f5b99f7029d --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/RoutePermissionsGuardFactory.php @@ -0,0 +1,68 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Factory; + +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\MutableCreationOptionsInterface; +use Zend\ServiceManager\ServiceLocatorInterface; +use ZfcRbac\Guard\RouteGuard; +use ZfcRbac\Guard\RoutePermissionsGuard; + +/** + * Create a route guard for checking permissions + * + * @author Michaël Gallego <mic.gallego@gmail.com> + * @author JM Lerouxw <jmleroux.pro@gmail.com> + * @licence MIT + */ +class RoutePermissionsGuardFactory implements FactoryInterface, MutableCreationOptionsInterface +{ + /** + * @var array + */ + protected $options = []; + + /** + * {@inheritDoc} + */ + public function setCreationOptions(array $options) + { + $this->options = $options; + } + + /** + * @param \Zend\ServiceManager\AbstractPluginManager|ServiceLocatorInterface $serviceLocator + * @return RouteGuard + */ + public function createService(ServiceLocatorInterface $serviceLocator) + { + $parentLocator = $serviceLocator->getServiceLocator(); + + /* @var \ZfcRbac\Options\ModuleOptions $moduleOptions */ + $moduleOptions = $parentLocator->get('ZfcRbac\Options\ModuleOptions'); + + /* @var \ZfcRbac\Service\AuthorizationService $authorizationService */ + $authorizationService = $parentLocator->get('ZfcRbac\Service\AuthorizationService'); + + $routeGuard = new RoutePermissionsGuard($authorizationService, $this->options); + $routeGuard->setProtectionPolicy($moduleOptions->getProtectionPolicy()); + + return $routeGuard; + } +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/UnauthorizedStrategyFactory.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/UnauthorizedStrategyFactory.php new file mode 100644 index 00000000000..112da138af2 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Factory/UnauthorizedStrategyFactory.php @@ -0,0 +1,43 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Factory; + +use Zend\ServiceManager\FactoryInterface; +use Zend\ServiceManager\ServiceLocatorInterface; +use ZfcRbac\View\Strategy\UnauthorizedStrategy; + +/** + * Factory to create an unauthorized strategy + * + * @author Michaël Gallego <mic.gallego@gmail.com> + * @licence MIT + */ +class UnauthorizedStrategyFactory implements FactoryInterface +{ + /** + * {@inheritDoc} + */ + public function createService(ServiceLocatorInterface $serviceLocator) + { + /* @var \ZfcRbac\Options\ModuleOptions $moduleOptions */ + $moduleOptions = $serviceLocator->get('ZfcRbac\Options\ModuleOptions'); + + return new UnauthorizedStrategy($moduleOptions->getUnauthorizedStrategy()); + } +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Guard/AbstractGuard.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Guard/AbstractGuard.php new file mode 100644 index 00000000000..93e2678cac6 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Guard/AbstractGuard.php @@ -0,0 +1,78 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Guard; + +use Zend\EventManager\EventManagerInterface; +use Zend\EventManager\ListenerAggregateTrait; +use Zend\Mvc\MvcEvent; +use ZfcRbac\Exception; + +/** + * Abstract guard that hook on the MVC workflow + * + * @author Michaël Gallego <mic.gallego@gmail.com> + * @licence MIT + */ +abstract class AbstractGuard implements GuardInterface +{ + use ListenerAggregateTrait; + + /** + * Event priority + */ + const EVENT_PRIORITY = -5; + + /** + * MVC event to listen + */ + const EVENT_NAME = MvcEvent::EVENT_ROUTE; + + /** + * {@inheritDoc} + */ + public function attach(EventManagerInterface $events) + { + $this->listeners[] = $events->attach(static::EVENT_NAME, [$this, 'onResult'], static::EVENT_PRIORITY); + } + + /** + * @private + * @param MvcEvent $event + * @return void + */ + public function onResult(MvcEvent $event) + { + if ($this->isGranted($event)) { + return; + } + + $event->setError(self::GUARD_UNAUTHORIZED); + $event->setParam('exception', new Exception\UnauthorizedException( + 'You are not authorized to access this resource', + 403 + )); + + $event->stopPropagation(true); + + $application = $event->getApplication(); + $eventManager = $application->getEventManager(); + + $eventManager->trigger(MvcEvent::EVENT_DISPATCH_ERROR, $event); + } +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Guard/ControllerGuard.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Guard/ControllerGuard.php new file mode 100644 index 00000000000..1f5fdcc4db5 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Guard/ControllerGuard.php @@ -0,0 +1,129 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Guard; + +use Zend\Mvc\MvcEvent; +use ZfcRbac\Service\RoleService; + +/** + * A controller guard can protect a controller and a set of actions + * + * @author Michaël Gallego <mic.gallego@gmail.com> + * @licence MIT + */ +class ControllerGuard extends AbstractGuard +{ + use ProtectionPolicyTrait; + + /** + * Event priority + */ + const EVENT_PRIORITY = -10; + + /** + * @var RoleService + */ + protected $roleService; + + /** + * Controller guard rules + * + * @var array + */ + protected $rules = []; + + /** + * Constructor + * + * @param RoleService $roleService + * @param array $rules + */ + public function __construct(RoleService $roleService, array $rules = []) + { + $this->roleService = $roleService; + $this->setRules($rules); + } + + /** + * Set the rules + * + * A controller rule is made the following way: + * + * [ + * 'controller' => 'ControllerName', + * 'actions' => []/string + * 'roles' => []/string + * ] + * + * @param array $rules + * @return void + */ + public function setRules(array $rules) + { + $this->rules = []; + + foreach ($rules as $rule) { + $controller = strtolower($rule['controller']); + $actions = isset($rule['actions']) ? (array) $rule['actions'] : []; + $roles = (array) $rule['roles']; + + if (empty($actions)) { + $this->rules[$controller][0] = $roles; + continue; + } + + foreach ($actions as $action) { + $this->rules[$controller][strtolower($action)] = $roles; + } + } + } + + /** + * {@inheritDoc} + */ + public function isGranted(MvcEvent $event) + { + $routeMatch = $event->getRouteMatch(); + $controller = strtolower($routeMatch->getParam('controller')); + $action = strtolower($routeMatch->getParam('action')); + + // If no rules apply, it is considered as granted or not based on the protection policy + if (!isset($this->rules[$controller])) { + return $this->protectionPolicy === self::POLICY_ALLOW; + } + + // Algorithm is as follow: we first check if there is an exact match (controller + action), if not + // we check if there are rules set globally for the whole controllers (see the index "0"), and finally + // if nothing is matched, we fallback to the protection policy logic + + if (isset($this->rules[$controller][$action])) { + $allowedRoles = $this->rules[$controller][$action]; + } elseif (isset($this->rules[$controller][0])) { + $allowedRoles = $this->rules[$controller][0]; + } else { + return $this->protectionPolicy === self::POLICY_ALLOW; + } + + if (in_array('*', $allowedRoles)) { + return true; + } + + return $this->roleService->matchIdentityRoles($allowedRoles); + } +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Guard/ControllerPermissionsGuard.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Guard/ControllerPermissionsGuard.php new file mode 100644 index 00000000000..22391295400 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Guard/ControllerPermissionsGuard.php @@ -0,0 +1,141 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Guard; + +use Zend\Mvc\MvcEvent; +use ZfcRbac\Service\AuthorizationServiceInterface; + +/** + * A controller guard can protect a controller and a set of actions + * + * @author Michaël Gallego <mic.gallego@gmail.com> + * @author JM Leroux <jmleroux.pro@gmail.com> + * @licence MIT + */ +class ControllerPermissionsGuard extends AbstractGuard +{ + use ProtectionPolicyTrait; + + /** + * Event priority + */ + const EVENT_PRIORITY = -15; + + /** + * @var AuthorizationServiceInterface + */ + protected $authorizationService; + + /** + * Controller guard rules + * + * @var array + */ + protected $rules = []; + + /** + * Constructor + * + * @param AuthorizationServiceInterface $authorizationService + * @param array $rules + */ + public function __construct(AuthorizationServiceInterface $authorizationService, array $rules = []) + { + $this->authorizationService = $authorizationService; + $this->setRules($rules); + } + + /** + * Set the rules + * + * A controller rule is made the following way: + * + * [ + * 'controller' => 'ControllerName', + * 'actions' => []/string + * 'roles' => []/string + * ] + * + * @param array $rules + * @return void + */ + public function setRules(array $rules) + { + $this->rules = []; + + foreach ($rules as $rule) { + $controller = strtolower($rule['controller']); + $actions = isset($rule['actions']) ? (array)$rule['actions'] : []; + $permissions = (array)$rule['permissions']; + + if (empty($actions)) { + $this->rules[$controller][0] = $permissions; + continue; + } + + foreach ($actions as $action) { + $this->rules[$controller][strtolower($action)] = $permissions; + } + } + } + + /** + * {@inheritDoc} + */ + public function isGranted(MvcEvent $event) + { + $routeMatch = $event->getRouteMatch(); + $controller = strtolower($routeMatch->getParam('controller')); + $action = strtolower($routeMatch->getParam('action')); + + // If no rules apply, it is considered as granted or not based on the protection policy + if (!isset($this->rules[$controller])) { + return $this->protectionPolicy === self::POLICY_ALLOW; + } + + // Algorithm is as follow: we first check if there is an exact match (controller + action), if not + // we check if there are rules set globally for the whole controllers (see the index "0"), and finally + // if nothing is matched, we fallback to the protection policy logic + + if (isset($this->rules[$controller][$action])) { + $allowedPermissions = $this->rules[$controller][$action]; + } elseif (isset($this->rules[$controller][0])) { + $allowedPermissions = $this->rules[$controller][0]; + } else { + return $this->protectionPolicy === self::POLICY_ALLOW; + } + + // If no rules apply, it is considered as granted or not based on the protection policy + if (empty($allowedPermissions)) { + return $this->protectionPolicy === self::POLICY_ALLOW; + } + + if (in_array('*', $allowedPermissions)) { + return true; + } + + foreach ($allowedPermissions as $permission) { + if (!$this->authorizationService->isGranted($permission)) { + return false; + } + } + + return true; + } +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Guard/GuardInterface.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Guard/GuardInterface.php new file mode 100644 index 00000000000..05f19537ae2 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Guard/GuardInterface.php @@ -0,0 +1,55 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Guard; + +use Zend\EventManager\ListenerAggregateInterface; +use Zend\Mvc\MvcEvent; + +/** + * Interface that each guard must implement + * + * A guard is a lightweight security layer that occurs typically after the route has been matched. ZfcRbac + * provides built-in implementations that can guard your routes and/or controllers. + * + * A guard can be used to block, for instance, a whole route hierarchy (all admin routes). However, only + * using guards is not sufficient and rather limited, and you should protected your services using the + * proper authorization service (see the doc for more details) + * + * @author Michaël Gallego <mic.gallego@gmail.com> + * @licence MIT + */ +interface GuardInterface extends ListenerAggregateInterface +{ + /** + * Constant for guard that can be added to the MVC event result + */ + const GUARD_UNAUTHORIZED = 'guard-unauthorized'; + + /** + * Protection policy constants + */ + const POLICY_DENY = 'deny'; + const POLICY_ALLOW = 'allow'; + + /** + * @param MvcEvent $event + * @return bool + */ + public function isGranted(MvcEvent $event); +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Guard/GuardPluginManager.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Guard/GuardPluginManager.php new file mode 100644 index 00000000000..dbb8573f9d4 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Guard/GuardPluginManager.php @@ -0,0 +1,67 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Guard; + +use Zend\ServiceManager\AbstractPluginManager; +use ZfcRbac\Exception; + +/** + * Plugin manager to create guards + * + * @method GuardInterface get($name) + * + * @author Michaël Gallego <mic.gallego@gmail.com> + * @author JM Leroux <jmleroux.pro@gmail.com> + * @licence MIT + */ +class GuardPluginManager extends AbstractPluginManager +{ + /** + * @var array + */ + protected $factories = [ + 'ZfcRbac\Guard\ControllerGuard' => 'ZfcRbac\Factory\ControllerGuardFactory', + 'ZfcRbac\Guard\ControllerPermissionsGuard' => 'ZfcRbac\Factory\ControllerPermissionsGuardFactory', + 'ZfcRbac\Guard\RouteGuard' => 'ZfcRbac\Factory\RouteGuardFactory', + 'ZfcRbac\Guard\RoutePermissionsGuard' => 'ZfcRbac\Factory\RoutePermissionsGuardFactory', + ]; + + /** + * {@inheritDoc} + */ + public function validatePlugin($plugin) + { + if ($plugin instanceof GuardInterface) { + return; // we're okay + } + + throw new Exception\RuntimeException(sprintf( + 'Guards must implement "ZfcRbac\Guard\GuardInterface", but "%s" was given', + is_object($plugin) ? get_class($plugin) : gettype($plugin) + )); + } + + /** + * {@inheritDoc} + */ + protected function canonicalizeName($name) + { + return $name; + } +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Guard/ProtectionPolicyTrait.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Guard/ProtectionPolicyTrait.php new file mode 100644 index 00000000000..1f337666981 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Guard/ProtectionPolicyTrait.php @@ -0,0 +1,54 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Guard; + +/** + * Trait that is can be used for any guard that uses the protection policy pattern + * + * @author Michaël Gallego <mic.gallego@gmail.com> + * @licence MIT + */ +trait ProtectionPolicyTrait +{ + /** + * @var string + */ + protected $protectionPolicy = GuardInterface::POLICY_DENY; + + /** + * Set the protection policy + * + * @param string $protectionPolicy + * @return void + */ + public function setProtectionPolicy($protectionPolicy) + { + $this->protectionPolicy = (string) $protectionPolicy; + } + + /** + * Get the protection policy + * + * @return string + */ + public function getProtectionPolicy() + { + return $this->protectionPolicy; + } +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Guard/RouteGuard.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Guard/RouteGuard.php new file mode 100644 index 00000000000..70aca06ef91 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Guard/RouteGuard.php @@ -0,0 +1,110 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Guard; + +use Zend\Mvc\MvcEvent; +use ZfcRbac\Exception; +use ZfcRbac\Service\RoleService; + +/** + * A route guard can protect a route or a hierarchy of routes (using simple wildcard pattern) + * + * @author Michaël Gallego <mic.gallego@gmail.com> + * @licence MIT + */ +class RouteGuard extends AbstractGuard +{ + use ProtectionPolicyTrait; + + /** + * @var RoleService + */ + protected $roleService; + + /** + * Route guard rules + * + * Those rules are an associative array that map a rule with one or multiple roles + * + * @var array + */ + protected $rules = []; + + /** + * Constructor + * + * @param RoleService $roleService + * @param array $rules + */ + public function __construct(RoleService $roleService, array $rules = []) + { + $this->roleService = $roleService; + $this->setRules($rules); + } + + /** + * Set the rules (it overrides any existing rules) + * + * @param array $rules + * @return void + */ + public function setRules(array $rules) + { + $this->rules = []; + + foreach ($rules as $key => $value) { + if (is_int($key)) { + $routeRegex = $value; + $roles = []; + } else { + $routeRegex = $key; + $roles = (array) $value; + } + + $this->rules[$routeRegex] = $roles; + } + } + + /** + * {@inheritDoc} + */ + public function isGranted(MvcEvent $event) + { + $matchedRouteName = $event->getRouteMatch()->getMatchedRouteName(); + $allowedRoles = null; + + foreach (array_keys($this->rules) as $routeRule) { + if (fnmatch($routeRule, $matchedRouteName, FNM_CASEFOLD)) { + $allowedRoles = $this->rules[$routeRule]; + break; + } + } + + // If no rules apply, it is considered as granted or not based on the protection policy + if (null === $allowedRoles) { + return $this->protectionPolicy === self::POLICY_ALLOW; + } + + if (in_array('*', $allowedRoles)) { + return true; + } + + return $this->roleService->matchIdentityRoles($allowedRoles); + } +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Guard/RoutePermissionsGuard.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Guard/RoutePermissionsGuard.php new file mode 100644 index 00000000000..577a9c8251b --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Guard/RoutePermissionsGuard.php @@ -0,0 +1,112 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ +namespace ZfcRbac\Guard; + +use Zend\Mvc\MvcEvent; +use ZfcRbac\Exception; +use ZfcRbac\Service\AuthorizationServiceInterface; + +/** + * A route guard can protect a route or a hierarchy of routes (using simple wildcard pattern) + * + * @author Michaël Gallego <mic.gallego@gmail.com> + * @author JM Leroux <jmleroux.pro@gmail.com> + * @licence MIT + */ +class RoutePermissionsGuard extends AbstractGuard +{ + use ProtectionPolicyTrait; + + const EVENT_PRIORITY = -8; + + /** + * @var AuthorizationServiceInterface + */ + protected $authorizationService; + + /** + * Route guard rules + * Those rules are an associative array that map a rule with one or multiple permissions + * @var array + */ + protected $rules = []; + + /** + * @param AuthorizationServiceInterface $authorizationService + * @param array $rules + */ + public function __construct(AuthorizationServiceInterface $authorizationService, array $rules = []) + { + $this->authorizationService = $authorizationService; + $this->setRules($rules); + } + + /** + * Set the rules (it overrides any existing rules) + * + * @param array $rules + * @return void + */ + public function setRules(array $rules) + { + $this->rules = []; + foreach ($rules as $key => $value) { + if (is_int($key)) { + $routeRegex = $value; + $permissions = []; + } else { + $routeRegex = $key; + $permissions = (array) $value; + } + $this->rules[$routeRegex] = $permissions; + } + } + + /** + * {@inheritDoc} + */ + public function isGranted(MvcEvent $event) + { + $matchedRouteName = $event->getRouteMatch()->getMatchedRouteName(); + $allowedPermissions = null; + + foreach (array_keys($this->rules) as $routeRule) { + if (fnmatch($routeRule, $matchedRouteName, FNM_CASEFOLD)) { + $allowedPermissions = $this->rules[$routeRule]; + break; + } + } + + // If no rules apply, it is considered as granted or not based on the protection policy + if (null === $allowedPermissions) { + return $this->protectionPolicy === self::POLICY_ALLOW; + } + + if (in_array('*', $allowedPermissions)) { + return true; + } + + foreach ($allowedPermissions as $permission) { + if (!$this->authorizationService->isGranted($permission)) { + return false; + } + } + + return true; + } +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Identity/AuthenticationIdentityProvider.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Identity/AuthenticationIdentityProvider.php new file mode 100644 index 00000000000..316f77ace32 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Identity/AuthenticationIdentityProvider.php @@ -0,0 +1,54 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Identity; + +use Zend\Authentication\AuthenticationServiceInterface; +use ZfcRbac\Exception; + +/** + * This provider uses the Zend authentication service to fetch the identity + * + * @author Michaël Gallego <mic.gallego@gmail.com> + * @licence MIT + */ +class AuthenticationIdentityProvider implements IdentityProviderInterface +{ + /** + * @var AuthenticationService + */ + protected $authenticationService; + + /** + * Constructor + * + * @param AuthenticationServiceInterface $authenticationService + */ + public function __construct(AuthenticationServiceInterface $authenticationService) + { + $this->authenticationService = $authenticationService; + } + + /** + * {@inheritDoc} + */ + public function getIdentity() + { + return $this->authenticationService->getIdentity(); + } +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Identity/IdentityInterface.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Identity/IdentityInterface.php new file mode 100644 index 00000000000..624a5f59016 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Identity/IdentityInterface.php @@ -0,0 +1,35 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Identity; + +/** + * Interface for an identity + * + * @author Michaël Gallego <mic.gallego@gmail.com> + * @licence MIT + */ +interface IdentityInterface +{ + /** + * Get the list of roles of this identity + * + * @return string[]|\Rbac\Role\RoleInterface[] + */ + public function getRoles(); +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Identity/IdentityProviderInterface.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Identity/IdentityProviderInterface.php new file mode 100644 index 00000000000..1f01b6211cc --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Identity/IdentityProviderInterface.php @@ -0,0 +1,35 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Identity; + +/** + * An identity provider is an object that returns an object that implement ZfcRbac\Identity\IdentityInterface + * + * @author Michaël Gallego <mic.gallego@gmail.com> + * @licence MIT + */ +interface IdentityProviderInterface +{ + /** + * Get the identity + * + * @return IdentityInterface|null + */ + public function getIdentity(); +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Initializer/AuthorizationServiceInitializer.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Initializer/AuthorizationServiceInitializer.php new file mode 100644 index 00000000000..dcaa358a4c7 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Initializer/AuthorizationServiceInitializer.php @@ -0,0 +1,48 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Initializer; + +use Zend\ServiceManager\AbstractPluginManager; +use Zend\ServiceManager\InitializerInterface; +use Zend\ServiceManager\ServiceLocatorInterface; +use ZfcRbac\Service\AuthorizationServiceAwareInterface; + +/** + * Initializer for classes implementing AuthorizationServiceAwareInterface + * + * @author Aeneas Rekkas + * @license MIT License + */ +class AuthorizationServiceInitializer implements InitializerInterface +{ + /** + * @see \Zend\ServiceManager\InitializerInterface::initialize() + */ + public function initialize($instance, ServiceLocatorInterface $serviceLocator) + { + if ($instance instanceof AuthorizationServiceAwareInterface) { + if ($serviceLocator instanceof AbstractPluginManager) { + $serviceLocator = $serviceLocator->getServiceLocator(); + } + + $authorizationService = $serviceLocator->get('ZfcRbac\Service\AuthorizationService'); + $instance->setAuthorizationService($authorizationService); + } + } +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Module.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Module.php new file mode 100644 index 00000000000..077773816a5 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Module.php @@ -0,0 +1,59 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac; + +use Zend\EventManager\EventInterface; +use Zend\ModuleManager\Feature\BootstrapListenerInterface; +use Zend\ModuleManager\Feature\ConfigProviderInterface; + +/** + * Module class for ZfcRbac + * + * @author Michaël Gallego <mic.gallego@gmail.com> + * @licence MIT + */ +class Module implements BootstrapListenerInterface, ConfigProviderInterface +{ + /** + * {@inheritDoc} + */ + public function onBootstrap(EventInterface $event) + { + /* @var \Zend\Mvc\Application $application */ + $application = $event->getTarget(); + $serviceManager = $application->getServiceManager(); + $eventManager = $application->getEventManager(); + + /* @var \ZfcRbac\Guard\GuardInterface[]|array $guards */ + $guards = $serviceManager->get('ZfcRbac\Guards'); + + // Register listeners, if any + foreach ($guards as $guard) { + $eventManager->attachAggregate($guard); + } + } + + /** + * {@inheritDoc} + */ + public function getConfig() + { + return include __DIR__ . '/../../config/module.config.php'; + } +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Mvc/Controller/Plugin/IsGranted.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Mvc/Controller/Plugin/IsGranted.php new file mode 100644 index 00000000000..fe852623c83 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Mvc/Controller/Plugin/IsGranted.php @@ -0,0 +1,58 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Mvc\Controller\Plugin; + +use Zend\Mvc\Controller\Plugin\AbstractPlugin; +use ZfcRbac\Service\AuthorizationServiceInterface; + +/** + * Controller plugin that allows to test a permission in a controller + * + * @author Michaël Gallego <mic.gallego@gmail.com> + * @licence MIT + */ +class IsGranted extends AbstractPlugin +{ + /** + * @var AuthorizationServiceInterface + */ + private $authorizationService; + + /** + * Constructor + * + * @param AuthorizationServiceInterface $authorizationService + */ + public function __construct(AuthorizationServiceInterface $authorizationService) + { + $this->authorizationService = $authorizationService; + } + + /** + * Check against the given permission + * + * @param string $permission + * @param mixed $context + * @return bool + */ + public function __invoke($permission, $context = null) + { + return $this->authorizationService->isGranted($permission, $context); + } +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Options/ModuleOptions.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Options/ModuleOptions.php new file mode 100644 index 00000000000..c49a8d506ad --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Options/ModuleOptions.php @@ -0,0 +1,287 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Options; + +use Zend\Stdlib\AbstractOptions; +use ZfcRbac\Exception; +use ZfcRbac\Guard\GuardInterface; + +/** + * Options for ZfcRbac module + * + * @author Michaël Gallego <mic.gallego@gmail.com> + * @licence MIT + */ +class ModuleOptions extends AbstractOptions +{ + /** + * Key of the identity provider used to retrieve the identity + * + * @var string + */ + protected $identityProvider = 'ZfcRbac\Identity\AuthenticationIdentityProvider'; + + /** + * Guest role (used when no identity is found) + * + * @var string + */ + protected $guestRole = 'guest'; + + /** + * Guards + * + * @var array + */ + protected $guards = []; + + /** + * Assertion map + * + * @var array + */ + protected $assertionMap = []; + + /** + * Protection policy for guards (can be "deny" or "allow") + * + * @var string + */ + protected $protectionPolicy = GuardInterface::POLICY_ALLOW; + + /** + * A configuration for role provider + * + * @var array + */ + protected $roleProvider = []; + + /** + * Options for the unauthorized strategy + * + * @var UnauthorizedStrategyOptions|null + */ + protected $unauthorizedStrategy; + + /** + * Options for the redirect strategy + * + * @var RedirectStrategyOptions|null + */ + protected $redirectStrategy; + + /** + * Constructor + * + * {@inheritDoc} + */ + public function __construct($options = null) + { + $this->__strictMode__ = false; + parent::__construct($options); + } + + /** + * Set the key of the identity provider used to retrieve the identity + * + * @param string $identityProvider + * @return void + */ + public function setIdentityProvider($identityProvider) + { + $this->identityProvider = (string) $identityProvider; + } + + /** + * Get the key of the identity provider used to retrieve the identity + * + * @return string + */ + public function getIdentityProvider() + { + return $this->identityProvider; + } + + /** + * Set the assertions options + * + * @param array $assertionMap + * @return void + */ + public function setAssertionMap(array $assertionMap) + { + $this->assertionMap = $assertionMap; + } + + /** + * Get the assertions options + * + * @return array + */ + public function getAssertionMap() + { + return $this->assertionMap; + } + + /** + * Set the guest role (used when no identity is found) + * + * @param string $guestRole + * @return void + */ + public function setGuestRole($guestRole) + { + $this->guestRole = (string) $guestRole; + } + + /** + * Get the guest role (used when no identity is found) + * + * @return string + */ + public function getGuestRole() + { + return $this->guestRole; + } + + /** + * Set the guards options + * + * @param array $guards + * @return void + */ + public function setGuards(array $guards) + { + $this->guards = $guards; + } + + /** + * Get the guards options + * + * @return array + */ + public function getGuards() + { + return $this->guards; + } + + /** + * Set the protection policy for guards + * + * @param string $protectionPolicy + * @throws Exception\RuntimeException + * @return void + */ + public function setProtectionPolicy($protectionPolicy) + { + if ($protectionPolicy !== GuardInterface::POLICY_ALLOW && $protectionPolicy !== GuardInterface::POLICY_DENY) { + throw new Exception\RuntimeException(sprintf( + 'An invalid protection policy was set. Can only be "deny" or "allow", "%s" given', + $protectionPolicy + )); + } + + $this->protectionPolicy = (string) $protectionPolicy; + } + + /** + * Get the protection policy for guards + * + * @return string + */ + public function getProtectionPolicy() + { + return $this->protectionPolicy; + } + + /** + * Set the configuration for the role provider + * + * @param array $roleProvider + * @throws Exception\RuntimeException + */ + public function setRoleProvider(array $roleProvider) + { + if (count($roleProvider) > 1) { + throw new Exception\RuntimeException( + 'You can only have one role provider' + ); + } + + $this->roleProvider = $roleProvider; + } + + /** + * Get the configuration for the role provider + * + * @return array + */ + public function getRoleProvider() + { + return $this->roleProvider; + } + + /** + * Set the unauthorized strategy options + * + * @param array $unauthorizedStrategy + */ + public function setUnauthorizedStrategy(array $unauthorizedStrategy) + { + $this->unauthorizedStrategy = new UnauthorizedStrategyOptions($unauthorizedStrategy); + } + + /** + * Get the unauthorized strategy options + * + * @return UnauthorizedStrategyOptions + */ + public function getUnauthorizedStrategy() + { + if (null === $this->unauthorizedStrategy) { + $this->unauthorizedStrategy = new UnauthorizedStrategyOptions(); + } + + return $this->unauthorizedStrategy; + } + + /** + * Set the redirect strategy options + * + * @param array $redirectStrategy + */ + public function setRedirectStrategy(array $redirectStrategy) + { + $this->redirectStrategy = new RedirectStrategyOptions($redirectStrategy); + } + + /** + * Get the redirect strategy options + * + * @return RedirectStrategyOptions + */ + public function getRedirectStrategy() + { + if (null === $this->redirectStrategy) { + $this->redirectStrategy = new RedirectStrategyOptions(); + } + + return $this->redirectStrategy; + } +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Options/RedirectStrategyOptions.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Options/RedirectStrategyOptions.php new file mode 100644 index 00000000000..83a7361492c --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Options/RedirectStrategyOptions.php @@ -0,0 +1,148 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Options; + +use Zend\Stdlib\AbstractOptions; + +/** + * Redirect strategy options + * + * @author Michaël Gallego <mic.gallego@gmail.com> + * @licence MIT + */ +class RedirectStrategyOptions extends AbstractOptions +{ + /** + * Should the user be redirected when connected and not authorized + * + * @var bool + */ + protected $redirectWhenConnected = true; + + /** + * The name of the route to redirect when a user is connected and not authorized + * + * @var string + */ + protected $redirectToRouteConnected = 'home'; + + /** + * The name of the route to redirect when a user is disconnected and not authorized + * + * @var string + */ + protected $redirectToRouteDisconnected = 'login'; + + /** + * Should the previous URI should be appended as a query param? + * + * @var bool + */ + protected $appendPreviousUri = true; + + /** + * If appendPreviousUri is enabled, key to use in query params that hold the previous URI + * + * @var string + */ + protected $previousUriQueryKey = 'redirectTo'; + + /** + * @param bool $redirectWhenConnected + * @return void + */ + public function setRedirectWhenConnected($redirectWhenConnected) + { + $this->redirectWhenConnected = (bool) $redirectWhenConnected; + } + + /** + * @return bool + */ + public function getRedirectWhenConnected() + { + return $this->redirectWhenConnected; + } + + /** + * @param string $redirectToRouteConnected + * @return void + */ + public function setRedirectToRouteConnected($redirectToRouteConnected) + { + $this->redirectToRouteConnected = (string) $redirectToRouteConnected; + } + + /** + * @return string + */ + public function getRedirectToRouteConnected() + { + return $this->redirectToRouteConnected; + } + + /** + * @param string $redirectToRouteDisconnected + * @return void + */ + public function setRedirectToRouteDisconnected($redirectToRouteDisconnected) + { + $this->redirectToRouteDisconnected = (string) $redirectToRouteDisconnected; + } + + /** + * @return string + */ + public function getRedirectToRouteDisconnected() + { + return $this->redirectToRouteDisconnected; + } + + /** + * @param boolean $appendPreviousUri + */ + public function setAppendPreviousUri($appendPreviousUri) + { + $this->appendPreviousUri = (bool) $appendPreviousUri; + } + + /** + * @return boolean + */ + public function getAppendPreviousUri() + { + return $this->appendPreviousUri; + } + + /** + * @param string $previousUriQueryKey + */ + public function setPreviousUriQueryKey($previousUriQueryKey) + { + $this->previousUriQueryKey = (string) $previousUriQueryKey; + } + + /** + * @return string + */ + public function getPreviousUriQueryKey() + { + return $this->previousUriQueryKey; + } +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Options/UnauthorizedStrategyOptions.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Options/UnauthorizedStrategyOptions.php new file mode 100644 index 00000000000..bf22f69ea43 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Options/UnauthorizedStrategyOptions.php @@ -0,0 +1,53 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Options; + +use Zend\Stdlib\AbstractOptions; + +/** + * Unauthorized strategy options + * + * @author Michaël Gallego <mic.gallego@gmail.com> + * @licence MIT + */ +class UnauthorizedStrategyOptions extends AbstractOptions +{ + /** + * Template to use + * + * @var string + */ + protected $template = 'error/403'; + + /** + * @param string $template + */ + public function setTemplate($template) + { + $this->template = (string) $template; + } + + /** + * @return string + */ + public function getTemplate() + { + return $this->template; + } +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Permission/PermissionInterface.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Permission/PermissionInterface.php new file mode 100644 index 00000000000..388c736bd8e --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Permission/PermissionInterface.php @@ -0,0 +1,34 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Permission; + +use Rbac\Permission\PermissionInterface as BasePermissionInterface; + +/** + * Interface that permissions must implement to be used with the AuthorizationService + * + * Please note that currently the interface extends the one from RBAC, but starting in ZF3, the + * permission will be removed from RBAC component and moved here completely + * + * @author Michaël Gallego <mic.gallego@gmail.com> + * @licence MIT + */ +interface PermissionInterface extends BasePermissionInterface +{ +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Role/InMemoryRoleProvider.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Role/InMemoryRoleProvider.php new file mode 100644 index 00000000000..dc559ea2fd8 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Role/InMemoryRoleProvider.php @@ -0,0 +1,95 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Role; + +use Rbac\Role\HierarchicalRole; +use Rbac\Role\Role; + +/** + * Simple role providers that store them in memory (ideal for small websites) + * + * This provider expects role to be specified using string only. The format is as follow: + * + * [ + * 'myRole' => [ + * 'children' => ['subRole1', 'subRole2'], // OPTIONAL + * 'permissions' => ['permission1'] // OPTIONAL + * ] + * ] + * + * For maximum performance, this provider DOES NOT do a lot of type check, so you must closely + * follow the format :) + * + * @author Michaël Gallego <mic.gallego@gmail.com> + * @licence MIT + */ +class InMemoryRoleProvider implements RoleProviderInterface +{ + /** + * @var array + */ + private $rolesConfig = []; + + /** + * @param array + */ + public function __construct(array $rolesConfig) + { + $this->rolesConfig = $rolesConfig; + } + + /** + * {@inheritDoc} + */ + public function getRoles(array $roleNames) + { + $roles = []; + + foreach ($roleNames as $roleName) { + // If no config, we create a simple role with no permission + if (!isset($this->rolesConfig[$roleName])) { + $roles[] = new Role($roleName); + continue; + } + + $roleConfig = $this->rolesConfig[$roleName]; + + if (isset($roleConfig['children'])) { + $role = new HierarchicalRole($roleName); + $childRoles = (array) $roleConfig['children']; + + foreach ($this->getRoles($childRoles) as $childRole) { + $role->addChild($childRole); + } + } else { + $role = new Role($roleName); + } + + $permissions = isset($roleConfig['permissions']) ? $roleConfig['permissions'] : []; + + foreach ($permissions as $permission) { + $role->addPermission($permission); + } + + $roles[] = $role; + } + + return $roles; + } +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Role/ObjectRepositoryRoleProvider.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Role/ObjectRepositoryRoleProvider.php new file mode 100644 index 00000000000..f6f445a88bf --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Role/ObjectRepositoryRoleProvider.php @@ -0,0 +1,100 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Role; + +use Doctrine\Common\Persistence\ObjectRepository; +use ZfcRbac\Exception\RoleNotFoundException; + +/** + * Role provider that uses Doctrine object repository to fetch roles + * + * @author Michaël Gallego <mic.gallego@gmail.com> + * @licence MIT + */ +class ObjectRepositoryRoleProvider implements RoleProviderInterface +{ + /** + * @var ObjectRepository + */ + private $objectRepository; + + /** + * @var string + */ + private $roleNameProperty; + + /** + * @var array + */ + private $roleCache = []; + + /** + * Constructor + * + * @param ObjectRepository $objectRepository + * @param string $roleNameProperty + */ + public function __construct(ObjectRepository $objectRepository, $roleNameProperty) + { + $this->objectRepository = $objectRepository; + $this->roleNameProperty = $roleNameProperty; + } + + /** + * Clears the role cache + * + * @return void + */ + public function clearRoleCache() + { + $this->roleCache = []; + } + + /** + * {@inheritDoc} + */ + public function getRoles(array $roleNames) + { + $key = implode($roleNames); + + if (isset($this->roleCache[$key])) { + return $this->roleCache[$key]; + } + + $roles = $this->objectRepository->findBy([$this->roleNameProperty => $roleNames]); + + // We allow more roles to be loaded than asked (although this should not happen because + // role name should have a UNIQUE constraint in database... but just in case ;)) + if (count($roles) >= count($roleNames)) { + $this->roleCache[$key] = $roles; + + return $roles; + } + + // We have roles that were asked but couldn't be found in database... problem! + foreach ($roles as &$role) { + $role = $role->getName(); + } + + throw new RoleNotFoundException(sprintf( + 'Some roles were asked but could not be loaded from database: %s', + implode(', ', array_diff($roleNames, $roles)) + )); + } +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Role/RoleProviderInterface.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Role/RoleProviderInterface.php new file mode 100644 index 00000000000..d0dd07afc10 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Role/RoleProviderInterface.php @@ -0,0 +1,39 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Role; + +/** + * A role provider is an object that collect roles from string and convert them to RoleInterface instances + * + * Data can come from anywhere. ZfcRbac is bundled with two providers that allow to load roles from database + * or from memory + * + * @author Michaël Gallego <mic.gallego@gmail.com> + * @licence MIT + */ +interface RoleProviderInterface +{ + /** + * Get the roles from the provider + * + * @param string[] $roleNames + * @return \Rbac\Role\RoleInterface[] + */ + public function getRoles(array $roleNames); +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Role/RoleProviderPluginManager.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Role/RoleProviderPluginManager.php new file mode 100644 index 00000000000..0d4d649d469 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Role/RoleProviderPluginManager.php @@ -0,0 +1,70 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Role; + +use Zend\ServiceManager\AbstractPluginManager; +use ZfcRbac\Exception; + +/** + * Plugin manager to create role providers + * + * @method RoleProviderInterface get($name) + * + * @author Michaël Gallego <mic.gallego@gmail.com> + * @licence MIT + */ +class RoleProviderPluginManager extends AbstractPluginManager +{ + /** + * @var array + */ + protected $invokableClasses = [ + 'ZfcRbac\Role\InMemoryRoleProvider' => 'ZfcRbac\Role\InMemoryRoleProvider' + ]; + + /** + * @var array + */ + protected $factories = [ + 'ZfcRbac\Role\ObjectRepositoryRoleProvider' => 'ZfcRbac\Factory\ObjectRepositoryRoleProviderFactory' + ]; + + /** + * {@inheritDoc} + */ + public function validatePlugin($plugin) + { + if ($plugin instanceof RoleProviderInterface) { + return; // we're okay + } + + throw new Exception\RuntimeException(sprintf( + 'Role provider must implement "ZfcRbac\Role\RoleProviderInterface", but "%s" was given', + is_object($plugin) ? get_class($plugin) : gettype($plugin) + )); + } + + /** + * {@inheritDoc} + */ + protected function canonicalizeName($name) + { + return $name; + } +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Service/AuthorizationService.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Service/AuthorizationService.php new file mode 100644 index 00000000000..0b86b18ebf0 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Service/AuthorizationService.php @@ -0,0 +1,164 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Service; + +use Rbac\Rbac; +use Rbac\Permission\PermissionInterface; +use ZfcRbac\Assertion\AssertionPluginManager; +use ZfcRbac\Assertion\AssertionInterface; +use ZfcRbac\Exception; +use ZfcRbac\Identity\IdentityInterface; + +/** + * Authorization service is a simple service that internally uses Rbac to check if identity is + * granted a permission + * + * @author Michaël Gallego <mic.gallego@gmail.com> + * @licence MIT + */ +class AuthorizationService implements AuthorizationServiceInterface +{ + /** + * @var Rbac + */ + protected $rbac; + + /** + * @var RoleService + */ + protected $roleService; + + /** + * @var AssertionPluginManager + */ + protected $assertionPluginManager; + + /** + * @var array + */ + protected $assertions = []; + + /** + * Constructor + * + * @param Rbac $rbac + * @param RoleService $roleService + * @param AssertionPluginManager $assertionPluginManager + */ + public function __construct(Rbac $rbac, RoleService $roleService, AssertionPluginManager $assertionPluginManager) + { + $this->rbac = $rbac; + $this->roleService = $roleService; + $this->assertionPluginManager = $assertionPluginManager; + } + + /** + * Set an assertion + * + * @param string|PermissionInterface $permission + * @param string|callable|AssertionInterface $assertion + * @return void + */ + public function setAssertion($permission, $assertion) + { + $this->assertions[(string) $permission] = $assertion; + } + + /** + * Set assertions + * + * @param array $assertions + * @return void + */ + public function setAssertions(array $assertions) + { + $this->assertions = $assertions; + } + + /** + * Checks if a assertion exists + * + * @param string|PermissionInterface $permission + * @return bool + */ + public function hasAssertion($permission) + { + return isset($this->assertions[(string) $permission]); + } + + /** + * Get the current identity from the role service + * + * @return IdentityInterface|null + */ + public function getIdentity() + { + return $this->roleService->getIdentity(); + } + + /** + * Check if the permission is granted to the current identity + * + * @param string|PermissionInterface $permission + * @param mixed $context + * @return bool + */ + public function isGranted($permission, $context = null) + { + $roles = $this->roleService->getIdentityRoles(); + + if (empty($roles)) { + return false; + } + + if (!$this->rbac->isGranted($roles, $permission)) { + return false; + } + + if ($this->hasAssertion($permission)) { + return $this->assert($this->assertions[(string) $permission], $context); + } + + return true; + } + + /** + * @param string|callable|AssertionInterface $assertion + * @param mixed $context + * @return bool + * @throws Exception\InvalidArgumentException If an invalid assertion is passed + */ + protected function assert($assertion, $context = null) + { + if (is_callable($assertion)) { + return $assertion($this, $context); + } elseif ($assertion instanceof AssertionInterface) { + return $assertion->assert($this, $context); + } elseif (is_string($assertion)) { + $assertion = $this->assertionPluginManager->get($assertion); + + return $assertion->assert($this, $context); + } + + throw new Exception\InvalidArgumentException(sprintf( + 'Assertion must be callable, string or implement ZfcRbac\Assertion\AssertionInterface, "%s" given', + is_object($assertion) ? get_class($assertion) : gettype($assertion) + )); + } +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Service/AuthorizationServiceAwareInterface.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Service/AuthorizationServiceAwareInterface.php new file mode 100644 index 00000000000..175afbf02c3 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Service/AuthorizationServiceAwareInterface.php @@ -0,0 +1,35 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ +namespace ZfcRbac\Service; + +/** + * @author Aeneas Rekkas + * @license http://www.opensource.org/licenses/mit-license.html MIT License + */ +interface AuthorizationServiceAwareInterface +{ + /** + * Set the AuthorizationService + * + * @TODO: for v3, update the interface to typehint to AuthorizationServiceInterface instead + * + * @param AuthorizationService $authorizationService + * @return void + */ + public function setAuthorizationService(AuthorizationService $authorizationService); +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Service/AuthorizationServiceAwareTrait.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Service/AuthorizationServiceAwareTrait.php new file mode 100644 index 00000000000..78119a0cffb --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Service/AuthorizationServiceAwareTrait.php @@ -0,0 +1,58 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Service; + +/** + * Makes a class AuthorizationService aware + * + * @author Aeneas Rekkas + * @license MIT License + */ +trait AuthorizationServiceAwareTrait +{ + /** + * The AuthorizationService + * + * @var AuthorizationService + */ + protected $authorizationService; + + /** + * Set the AuthorizationService + * + * @TODO: for v3, update the interface to typehint to AuthorizationServiceInterface instead + * + * @param AuthorizationService $authorizationService + * @return void + */ + public function setAuthorizationService(AuthorizationService $authorizationService) + { + $this->authorizationService = $authorizationService; + } + + /** + * Return the AuthorizationService + * + * @return AuthorizationService + */ + public function getAuthorizationService() + { + return $this->authorizationService; + } +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Service/AuthorizationServiceInterface.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Service/AuthorizationServiceInterface.php new file mode 100644 index 00000000000..a22c6d059a0 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Service/AuthorizationServiceInterface.php @@ -0,0 +1,39 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Service; + +use Rbac\Permission\PermissionInterface; + +/** + * Minimal interface for an authorization service + * + * @author Michaël Gallego <mic.gallego@gmail.com> + * @licence MIT + */ +interface AuthorizationServiceInterface +{ + /** + * Check if the permission is granted to the current identity + * + * @param string|PermissionInterface $permission + * @param mixed $context + * @return bool + */ + public function isGranted($permission, $context = null); +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Service/RoleService.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Service/RoleService.php new file mode 100644 index 00000000000..3fb131b3327 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/Service/RoleService.php @@ -0,0 +1,211 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\Service; + +use Rbac\Role\HierarchicalRoleInterface; +use Rbac\Role\RoleInterface; +use RecursiveIteratorIterator; +use Traversable; +use ZfcRbac\Exception; +use ZfcRbac\Identity\IdentityInterface; +use ZfcRbac\Identity\IdentityProviderInterface; +use ZfcRbac\Role\RoleProviderInterface; +use Rbac\Traversal\Strategy\TraversalStrategyInterface; + +/** + * Role service + * + * @author Michaël Gallego <mic.gallego@gmail.com> + * @licence MIT + */ +class RoleService +{ + /** + * @var IdentityProviderInterface + */ + protected $identityProvider; + + /** + * @var RoleProviderInterface + */ + protected $roleProvider; + + /** + * @var TraversalStrategyInterface + */ + protected $traversalStrategy; + + /** + * @var string + */ + protected $guestRole = ''; + + /** + * Constructor + * + * @param IdentityProviderInterface $identityProvider + * @param RoleProviderInterface $roleProvider + * @param TraversalStrategyInterface $traversalStrategy + */ + public function __construct( + IdentityProviderInterface $identityProvider, + RoleProviderInterface $roleProvider, + TraversalStrategyInterface $traversalStrategy + ) { + $this->identityProvider = $identityProvider; + $this->roleProvider = $roleProvider; + $this->traversalStrategy = $traversalStrategy; + } + + /** + * Set the guest role + * + * @param string $guestRole + * @return void + */ + public function setGuestRole($guestRole) + { + $this->guestRole = (string) $guestRole; + } + + /** + * Get the guest role + * + * @return string + */ + public function getGuestRole() + { + return $this->guestRole; + } + + /** + * Get the current identity from the identity provider + * + * @return IdentityInterface|null + */ + public function getIdentity() + { + return $this->identityProvider->getIdentity(); + } + + /** + * Get the identity roles from the current identity, applying some more logic + * + * @return RoleInterface[] + * @throws Exception\RuntimeException + */ + public function getIdentityRoles() + { + if (!$identity = $this->getIdentity()) { + return $this->convertRoles([$this->guestRole]); + } + + if (!$identity instanceof IdentityInterface) { + throw new Exception\RuntimeException(sprintf( + 'ZfcRbac expects your identity to implement ZfcRbac\Identity\IdentityInterface, "%s" given', + is_object($identity) ? get_class($identity) : gettype($identity) + )); + } + + return $this->convertRoles($identity->getRoles()); + } + + /** + * Check if the given roles match one of the identity roles + * + * This method is smart enough to automatically recursively extracts roles for hierarchical roles + * + * @param string[]|RoleInterface[] $roles + * @return bool + */ + public function matchIdentityRoles(array $roles) + { + $identityRoles = $this->getIdentityRoles(); + + // Too easy... + if (empty($identityRoles)) { + return false; + } + + $roleNames = []; + + foreach ($roles as $role) { + $roleNames[] = $role instanceof RoleInterface ? $role->getName() : (string) $role; + } + + $identityRoles = $this->flattenRoles($identityRoles); + + return count(array_intersect($roleNames, $identityRoles)) > 0; + } + + /** + * Convert the roles (potentially strings) to concrete RoleInterface objects using role provider + * + * @param array|Traversable $roles + * @return RoleInterface[] + */ + protected function convertRoles($roles) + { + if ($roles instanceof Traversable) { + $roles = iterator_to_array($roles); + } + + $collectedRoles = []; + $toCollect = []; + + foreach ((array) $roles as $role) { + // If it's already a RoleInterface, nothing to do as a RoleInterface contains everything already + if ($role instanceof RoleInterface) { + $collectedRoles[] = $role; + continue; + } + + // Otherwise, it's a string and hence we need to collect it + $toCollect[] = (string) $role; + } + + // Nothing to collect, we don't even need to hit the (potentially) costly role provider + if (empty($toCollect)) { + return $collectedRoles; + } + + return array_merge($collectedRoles, $this->roleProvider->getRoles($toCollect)); + } + + /** + * Flatten an array of role with role names + * + * This method iterates through the list of roles, and convert any RoleInterface to a string. For any + * role, it also extracts all the children + * + * @param array|RoleInterface[] $roles + * @return string[] + */ + protected function flattenRoles(array $roles) + { + $roleNames = []; + $iterator = $this->traversalStrategy->getRolesIterator($roles); + + foreach ($iterator as $role) { + $roleNames[] = $role->getName(); + } + + return array_unique($roleNames); + } +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/View/Helper/HasRole.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/View/Helper/HasRole.php new file mode 100644 index 00000000000..77cccbde6b4 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/View/Helper/HasRole.php @@ -0,0 +1,55 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\View\Helper; + +use Zend\View\Helper\AbstractHelper; +use ZfcRbac\Service\RoleService; + +/** + * View helper that allows to test a role in a view + * + * @author JM Leroux <jmleroux.pro@gmail.com> + * @licence MIT + */ +class HasRole extends AbstractHelper +{ + /** + * @var RoleService + */ + private $roleService; + + /** + * Constructor + * + * @param RoleService $roleService + */ + public function __construct(RoleService $roleService) + { + $this->roleService = $roleService; + } + + /** + * @param string|string[] $roleOrRoles + * @return bool + */ + public function __invoke($roleOrRoles) + { + return $this->roleService->matchIdentityRoles((array)$roleOrRoles); + } +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/View/Helper/IsGranted.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/View/Helper/IsGranted.php new file mode 100644 index 00000000000..f2dab6c7eda --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/View/Helper/IsGranted.php @@ -0,0 +1,58 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\View\Helper; + +use Zend\View\Helper\AbstractHelper; +use ZfcRbac\Service\AuthorizationServiceInterface; + +/** + * View helper that allows to test a permission in a view + * + * @author Michaël Gallego <mic.gallego@gmail.com> + * @licence MIT + */ +class IsGranted extends AbstractHelper +{ + /** + * @var AuthorizationServiceInterface + */ + private $authorizationService; + + /** + * Constructor + * + * @param AuthorizationServiceInterface $authorizationService + */ + public function __construct(AuthorizationServiceInterface $authorizationService) + { + $this->authorizationService = $authorizationService; + } + + /** + * Check against the given permission + * + * @param string $permission + * @param mixed $context + * @return bool + */ + public function __invoke($permission, $context = null) + { + return $this->authorizationService->isGranted($permission, $context); + } +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/View/Strategy/AbstractStrategy.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/View/Strategy/AbstractStrategy.php new file mode 100644 index 00000000000..609162d91f5 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/View/Strategy/AbstractStrategy.php @@ -0,0 +1,47 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\View\Strategy; + +use Zend\EventManager\AbstractListenerAggregate; +use Zend\EventManager\EventManagerInterface; +use Zend\Mvc\MvcEvent; + +/** + * Abstract strategy for any unauthorized access + * + * @author Michaël Gallego <mic.gallego@gmail.com> + * @licence MIT + */ +abstract class AbstractStrategy extends AbstractListenerAggregate +{ + /** + * {@inheritDoc} + */ + public function attach(EventManagerInterface $events) + { + $this->listeners[] = $events->attach(MvcEvent::EVENT_DISPATCH_ERROR, [$this, 'onError']); + } + + /** + * @private + * @param MvcEvent $event + * @return void + */ + abstract public function onError(MvcEvent $event); +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/View/Strategy/RedirectStrategy.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/View/Strategy/RedirectStrategy.php new file mode 100644 index 00000000000..fad3fcc8ca7 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/View/Strategy/RedirectStrategy.php @@ -0,0 +1,107 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\View\Strategy; + +use Zend\Authentication\AuthenticationServiceInterface; +use Zend\Http\Response as HttpResponse; +use Zend\Mvc\MvcEvent; +use ZfcRbac\Exception\UnauthorizedExceptionInterface; +use ZfcRbac\Options\RedirectStrategyOptions; + +/** + * This strategy redirects to another route when a user is unauthorized + * + * @author Michaël Gallego <mic.gallego@gmail.com> + * @licence MIT + */ +class RedirectStrategy extends AbstractStrategy +{ + /** + * @var RedirectStrategyOptions + */ + protected $options; + + /** + * @var AuthenticationServiceInterface + */ + protected $authenticationService; + + /** + * Constructor + * + * @param RedirectStrategyOptions $options + * @param AuthenticationServiceInterface $authenticationService + */ + public function __construct(RedirectStrategyOptions $options, AuthenticationServiceInterface $authenticationService) + { + $this->options = $options; + $this->authenticationService = $authenticationService; + } + + /** + * @private + * @param MvcEvent $event + * @return void + */ + public function onError(MvcEvent $event) + { + // Do nothing if no error or if response is not HTTP response + if (!($event->getParam('exception') instanceof UnauthorizedExceptionInterface) + || ($event->getResult() instanceof HttpResponse) + || !($event->getResponse() instanceof HttpResponse) + ) { + return; + } + + $router = $event->getRouter(); + + if ($this->authenticationService->hasIdentity()) { + if (!$this->options->getRedirectWhenConnected()) { + return; + } + + $redirectRoute = $this->options->getRedirectToRouteConnected(); + } else { + $redirectRoute = $this->options->getRedirectToRouteDisconnected(); + } + + $uri = $router->assemble([], ['name' => $redirectRoute]); + + if ($this->options->getAppendPreviousUri()) { + $redirectKey = $this->options->getPreviousUriQueryKey(); + $previousUri = $event->getRequest()->getUriString(); + + $uri = $router->assemble( + [], + [ + 'name' => $redirectRoute, + 'query' => [$redirectKey => $previousUri] + ] + ); + } + + $response = $event->getResponse() ?: new HttpResponse(); + + $response->getHeaders()->addHeaderLine('Location', $uri); + $response->setStatusCode(302); + + $event->setResponse($response); + $event->setResult($response); + } +} diff --git a/vendor/zf-commons/zfc-rbac/src/ZfcRbac/View/Strategy/UnauthorizedStrategy.php b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/View/Strategy/UnauthorizedStrategy.php new file mode 100644 index 00000000000..6a0f791bdb7 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/src/ZfcRbac/View/Strategy/UnauthorizedStrategy.php @@ -0,0 +1,83 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbac\View\Strategy; + +use Zend\Http\Response as HttpResponse; +use Zend\Mvc\MvcEvent; +use Zend\View\Model\ViewModel; +use ZfcRbac\Exception\UnauthorizedExceptionInterface; +use ZfcRbac\Guard\GuardInterface; +use ZfcRbac\Options\UnauthorizedStrategyOptions; + +/** + * This strategy renders a specific template when a user is unauthorized + * + * @author Michaël Gallego <mic.gallego@gmail.com> + * @licence MIT + */ +class UnauthorizedStrategy extends AbstractStrategy +{ + /** + * @var UnauthorizedStrategyOptions + */ + protected $options; + + /** + * Constructor + * + * @param UnauthorizedStrategyOptions $options + */ + public function __construct(UnauthorizedStrategyOptions $options) + { + $this->options = $options; + } + + /** + * @private + * @param MvcEvent $event + * @return void + */ + public function onError(MvcEvent $event) + { + // Do nothing if no error or if response is not HTTP response + if (!($event->getParam('exception') instanceof UnauthorizedExceptionInterface) + || ($event->getResult() instanceof HttpResponse) + || !($event->getResponse() instanceof HttpResponse) + ) { + return; + } + + $model = new ViewModel(); + $model->setTemplate($this->options->getTemplate()); + + switch ($event->getError()) { + case GuardInterface::GUARD_UNAUTHORIZED: + $model->setVariable('error', GuardInterface::GUARD_UNAUTHORIZED); + break; + + default: + } + + $response = $event->getResponse() ?: new HttpResponse(); + $response->setStatusCode(403); + + $event->setResponse($response); + $event->setResult($model); + } +} diff --git a/vendor/zf-commons/zfc-rbac/tests/Bootstrap.php b/vendor/zf-commons/zfc-rbac/tests/Bootstrap.php new file mode 100644 index 00000000000..f2f9e8a80d4 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/Bootstrap.php @@ -0,0 +1,56 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +use ZfcRbacTest\Util\ServiceManagerFactory; + +ini_set('error_reporting', E_ALL); + +$files = [ + __DIR__ . '/../vendor/autoload.php', + __DIR__ . '/../../../autoload.php' +]; + +foreach ($files as $file) { + if (file_exists($file)) { + $loader = require $file; + + break; + } +} + +if (! isset($loader)) { + throw new RuntimeException('vendor/autoload.php could not be found. Did you install via composer?'); +} + +$loader->add('ZfcRbacTest\\', __DIR__); + +$configFiles = [ + __DIR__ . '/TestConfiguration.php', + __DIR__ . '/TestConfiguration.php.dist' +]; + +foreach ($configFiles as $configFile) { + if (file_exists($configFile)) { + $config = require $configFile; + + break; + } +} + +ServiceManagerFactory::setApplicationConfig($config); +unset($files, $file, $loader, $configFiles, $configFile, $config); diff --git a/vendor/zf-commons/zfc-rbac/tests/TestConfiguration.php.dist b/vendor/zf-commons/zfc-rbac/tests/TestConfiguration.php.dist new file mode 100644 index 00000000000..a01abb2326e --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/TestConfiguration.php.dist @@ -0,0 +1,32 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +return [ + 'modules' => [ + 'ZfcRbac', + 'DoctrineModule', + 'DoctrineORMModule', + ], + 'module_listener_options' => [ + 'config_glob_paths' => [ + __DIR__ . '/testing.config.php', + ], + 'module_paths' => [ + ], + ], +]; diff --git a/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Asset/FlatRole.php b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Asset/FlatRole.php new file mode 100644 index 00000000000..cc0f5a5a33a --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Asset/FlatRole.php @@ -0,0 +1,89 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbacTest\Asset; + +use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\ORM\Mapping as ORM; +use Rbac\Permission\PermissionInterface; +use Rbac\Role\Role; + +/** + * @ORM\Entity + * @ORM\Table(name="roles") + */ +class FlatRole extends Role +{ + /** + * @var int|null + * + * @ORM\Id + * @ORM\Column(type="integer") + * @ORM\GeneratedValue(strategy="AUTO") + */ + protected $id; + + /** + * @var string|null + * + * @ORM\Column(type="string", length=32, unique=true) + */ + protected $name; + + /** + * @var PermissionInterface[]|\Doctrine\Common\Collections\Collection + * + * @ORM\ManyToMany(targetEntity="Permission", indexBy="name") + */ + protected $permissions; + + /** + * Init the Doctrine collection + */ + public function __construct($name) + { + $this->name = (string) $name; + $this->permissions = new ArrayCollection(); + } + + /** + * Get the role identifier + * + * @return int + */ + public function getId() + { + return $this->id; + } + + /** + * Add a permission + * + * @param PermissionInterface|string $permission + * @return void + */ + public function addPermission($permission) + { + if (is_string($permission)) { + $name = $permission; + $permission = new Permission($name); + } + + $this->permissions[$permission->getName()] = $permission; + } +} diff --git a/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Asset/HierarchicalRole.php b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Asset/HierarchicalRole.php new file mode 100644 index 00000000000..1a6dbe89cee --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Asset/HierarchicalRole.php @@ -0,0 +1,96 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbacTest\Asset; + +use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\ORM\Mapping as ORM; +use Rbac\Permission\PermissionInterface; +use Rbac\Role\HierarchicalRole as BaseHierarchicalRole; + +/** + * @ORM\Entity + * @ORM\Table(name="hierarchical_roles") + */ +class HierarchicalRole extends BaseHierarchicalRole +{ + /** + * @var int|null + * + * @ORM\Id + * @ORM\Column(type="integer") + * @ORM\GeneratedValue(strategy="AUTO") + */ + protected $id; + + /** + * @var string|null + * + * @ORM\Column(type="string", length=32, unique=true) + */ + protected $name; + + /** + * @var \Rbac\Role\RoleInterface[]|\Doctrine\Common\Collections\Collection + * + * @ORM\ManyToMany(targetEntity="HierarchicalRole") + */ + protected $children; + + /** + * @var PermissionInterface[]|\Doctrine\Common\Collections\Collection + * + * @ORM\ManyToMany(targetEntity="Permission", indexBy="name", fetch="EAGER") + */ + protected $permissions; + + /** + * Init the Doctrine collection + */ + public function __construct($name) + { + $this->name = (string) $name; + $this->permissions = new ArrayCollection(); + } + + /** + * Get the role identifier + * + * @return int + */ + public function getId() + { + return $this->id; + } + + /** + * Add a permission + * + * @param PermissionInterface|string $permission + * @return void + */ + public function addPermission($permission) + { + if (is_string($permission)) { + $name = $permission; + $permission = new Permission($name); + } + + $this->permissions[$permission->getName()] = $permission; + } +} diff --git a/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Asset/Permission.php b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Asset/Permission.php new file mode 100644 index 00000000000..30a354d238e --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Asset/Permission.php @@ -0,0 +1,83 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbacTest\Asset; + +use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\ORM\Mapping as ORM; +use Rbac\Permission\PermissionInterface; + +/** + * @ORM\Entity + * @ORM\Table(name="permissions") + */ +class Permission implements PermissionInterface +{ + /** + * @var int|null + * + * @ORM\Id + * @ORM\Column(type="integer") + * @ORM\GeneratedValue(strategy="AUTO") + */ + protected $id; + + /** + * @var string|null + * + * @ORM\Column(type="string", length=32, unique=true) + */ + protected $name; + + /** + * Constructor + */ + public function __construct($name) + { + $this->name = (string) $name; + $this->roles = new ArrayCollection(); + } + + /** + * Get the permission identifier + * + * @return int + */ + public function getId() + { + return $this->id; + } + + /** + * Get the permission name + * + * @return string + */ + public function getName() + { + return $this->name; + } + + /** + * {@inheritDoc} + */ + public function __toString() + { + return $this->getName(); + } +} diff --git a/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Asset/SimpleAssertion.php b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Asset/SimpleAssertion.php new file mode 100644 index 00000000000..de156f9adde --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Asset/SimpleAssertion.php @@ -0,0 +1,48 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbacTest\Asset; + +use ZfcRbac\Assertion\AssertionInterface; +use ZfcRbac\Service\AuthorizationService; + +class SimpleAssertion implements AssertionInterface +{ + /** + * @var bool + */ + protected $called = false; + + /** + * {@inheritDoc} + */ + public function assert(AuthorizationService $authorization, $context = false) + { + $this->called = true; + + return $context; + } + + /** + * @return bool + */ + public function getCalled() + { + return $this->called; + } +} diff --git a/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Collector/RbacCollectorTest.php b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Collector/RbacCollectorTest.php new file mode 100644 index 00000000000..c89ca248806 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Collector/RbacCollectorTest.php @@ -0,0 +1,179 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbacTest\Collector; + +use Zend\Mvc\MvcEvent; +use Zend\Permissions\Rbac\Rbac; +use Zend\Permissions\Rbac\Role; +use ZfcRbac\Collector\RbacCollector; +use ZfcRbac\Guard\GuardInterface; +use ZfcRbac\Options\ModuleOptions; +use ZfcRbac\Role\InMemoryRoleProvider; +use ZfcRbac\Service\RoleService; +use Rbac\Traversal\Strategy\RecursiveRoleIteratorStrategy; + +/** + * @covers \ZfcRbac\Collector\RbacCollector + */ +class RbacCollectorTest extends \PHPUnit_Framework_TestCase +{ + public function testDefaultGetterReturnValues() + { + $collector = new RbacCollector(); + + $this->assertSame(-100, $collector->getPriority()); + $this->assertSame('zfc_rbac', $collector->getName()); + } + + public function testSerialize() + { + $collector = new RbacCollector(); + $serialized = $collector->serialize(); + + $this->assertInternalType('string', $serialized); + + $unserialized = unserialize($serialized); + + $this->assertSame([], $unserialized['guards']); + $this->assertSame([], $unserialized['roles']); + $this->assertSame([], $unserialized['options']); + } + + public function testUnserialize() + { + $collector = new RbacCollector(); + $unserialized = [ + 'guards' => ['foo' => 'bar'], + 'roles' => ['foo' => 'bar'], + 'options' => ['foo' => 'bar'] + ]; + $serialized = serialize($unserialized); + + $collector->unserialize($serialized); + + $collection = $collector->getCollection(); + + $this->assertInternalType('array', $collection); + $this->assertSame(['foo' => 'bar'], $collection['guards']); + $this->assertSame(['foo' => 'bar'], $collection['roles']); + $this->assertSame(['foo' => 'bar'], $collection['options']); + } + + public function testCollectNothingIfNoApplicationIsSet() + { + $mvcEvent = new MvcEvent(); + $collector = new RbacCollector(); + + $this->assertNull($collector->collect($mvcEvent)); + } + + public function testCanCollect() + { + $dataToCollect = [ + 'module_options' => [ + 'guest_role' => 'guest', + 'protection_policy' => GuardInterface::POLICY_ALLOW, + 'guards' => [ + 'ZfcRbac\Guard\RouteGuard' => [ + 'admin*' => ['*'] + ], + 'ZfcRbac\Guard\ControllerGuard' => [ + [ + 'controller' => 'Foo', + 'roles' => ['*'] + ] + ] + ] + ], + 'role_config' => [ + 'member' => [ + 'children' => ['guest'], + 'permissions' => ['write', 'delete'] + ], + 'guest' => [ + 'permissions' => ['read'] + ] + ], + 'identity_role' => 'member' + ]; + + $serviceManager = $this->getMock('Zend\ServiceManager\ServiceLocatorInterface'); + + $application = $this->getMock('Zend\Mvc\Application', [], [], '', false); + $application->expects($this->once())->method('getServiceManager')->will($this->returnValue($serviceManager)); + + $mvcEvent = new MvcEvent(); + $mvcEvent->setApplication($application); + + $identity = $this->getMock('ZfcRbac\Identity\IdentityInterface'); + $identity->expects($this->once()) + ->method('getRoles') + ->will($this->returnValue($dataToCollect['identity_role'])); + + $identityProvider = $this->getMock('ZfcRbac\Identity\IdentityProviderInterface'); + $identityProvider->expects($this->once()) + ->method('getIdentity') + ->will($this->returnValue($identity)); + + $roleService = new RoleService($identityProvider, new InMemoryRoleProvider($dataToCollect['role_config']), new RecursiveRoleIteratorStrategy()); + + $serviceManager->expects($this->at(0)) + ->method('get') + ->with('ZfcRbac\Service\RoleService') + ->will($this->returnValue($roleService)); + + $serviceManager->expects($this->at(1)) + ->method('get') + ->with('ZfcRbac\Options\ModuleOptions') + ->will($this->returnValue(new ModuleOptions($dataToCollect['module_options']))); + + $collector = new RbacCollector(); + $collector->collect($mvcEvent); + + $collector->unserialize($collector->serialize()); + $collection = $collector->getCollection(); + + $expectedCollection = [ + 'options' => [ + 'guest_role' => 'guest', + 'protection_policy' => 'allow' + ], + 'guards' => [ + 'ZfcRbac\Guard\RouteGuard' => [ + 'admin*' => ['*'] + ], + 'ZfcRbac\Guard\ControllerGuard' => [ + [ + 'controller' => 'Foo', + 'roles' => ['*'] + ] + ] + ], + 'roles' => [ + 'member' => ['guest'] + ], + 'permissions' => [ + 'member' => ['write', 'delete'], + 'guest' => ['read'] + ] + ]; + + $this->assertEquals($expectedCollection, $collection); + } +} diff --git a/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/AssertionPluginManagerFactoryTest.php b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/AssertionPluginManagerFactoryTest.php new file mode 100644 index 00000000000..4d83c21a01b --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/AssertionPluginManagerFactoryTest.php @@ -0,0 +1,44 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbacTest\Factory; + +use Zend\ServiceManager\ServiceManager; +use ZfcRbac\Factory\AssertionPluginManagerFactory; + +/** + * @covers \ZfcRbac\Factory\AssertionPluginManagerFactory + */ +class AssertionPluginManagerFactoryTest extends \PHPUnit_Framework_TestCase +{ + public function testFactory() + { + $serviceManager = new ServiceManager(); + $serviceManager->setService('Config', [ + 'zfc_rbac' => [ + 'assertion_manager' => [] + ] + ]); + + $factory = new AssertionPluginManagerFactory(); + $pluginManager = $factory->createService($serviceManager); + + $this->assertInstanceOf('ZfcRbac\Assertion\AssertionPluginManager', $pluginManager); + $this->assertSame($serviceManager, $pluginManager->getServiceLocator()); + } +} diff --git a/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/AuthenticationIdentityProviderFactoryTest.php b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/AuthenticationIdentityProviderFactoryTest.php new file mode 100644 index 00000000000..0908f36d42a --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/AuthenticationIdentityProviderFactoryTest.php @@ -0,0 +1,42 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbacTest\Factory; + +use Zend\ServiceManager\ServiceManager; +use ZfcRbac\Factory\AuthenticationIdentityProviderFactory; + +/** + * @covers \ZfcRbac\Factory\AuthenticationIdentityProviderFactory + */ +class AuthenticationIdentityProviderFactoryTest extends \PHPUnit_Framework_TestCase +{ + public function testFactory() + { + $serviceManager = new ServiceManager(); + $serviceManager->setService( + 'Zend\Authentication\AuthenticationService', + $this->getMock('Zend\Authentication\AuthenticationService') + ); + + $factory = new AuthenticationIdentityProviderFactory(); + $authenticationProvider = $factory->createService($serviceManager); + + $this->assertInstanceOf('ZfcRbac\Identity\AuthenticationIdentityProvider', $authenticationProvider); + } +} diff --git a/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/AuthorizationServiceDelegatorTest.php b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/AuthorizationServiceDelegatorTest.php new file mode 100644 index 00000000000..ca6661ddf8f --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/AuthorizationServiceDelegatorTest.php @@ -0,0 +1,128 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ +namespace ZfcRbacTest\Factory; + +use ZfcRbac\Factory\AuthorizationServiceDelegatorFactory; +use ZfcRbacTest\Initializer\AuthorizationAwareFake; +use ZfcRbacTest\Util\ServiceManagerFactory; + +/** + * @covers \ZfcRbac\Factory\AuthorizationServiceDelegatorFactory + * @author Jean-Marie Leroux <jmleroux.pro@gmail.com> + * @license MIT License + */ +class AuthorizationServiceDelegatorTest extends \PHPUnit_Framework_TestCase +{ + public function testDelegatorFactory() + { + $authServiceClassName = 'ZfcRbac\Service\AuthorizationService'; + $delegator = new AuthorizationServiceDelegatorFactory(); + $serviceLocator = $this->getMock('Zend\ServiceManager\ServiceLocatorInterface'); + $authorizationService = $this->getMock('ZfcRbac\Service\AuthorizationService', [], [], '', false); + + $callback = function () { + return new AuthorizationAwareFake(); + }; + + $serviceLocator->expects($this->once()) + ->method('get') + ->with($authServiceClassName) + ->will($this->returnValue($authorizationService)); + + $decoratedInstance = $delegator->createDelegatorWithName($serviceLocator, 'name', 'requestedName', $callback); + + $this->assertEquals($authorizationService, $decoratedInstance->getAuthorizationService()); + } + + public function testAuthorizationServiceIsNotInjectedWithoutDelegator() + { + $serviceManager = ServiceManagerFactory::getServiceManager(); + + $serviceManager->setAllowOverride(true); + $authorizationService = $this->getMock('ZfcRbac\Service\AuthorizationService', [], [], '', false); + $serviceManager->setService( + 'ZfcRbac\Service\AuthorizationService', + $authorizationService + ); + $serviceManager->setAllowOverride(false); + + $serviceManager->setInvokableClass( + 'ZfcRbacTest\AuthorizationAware', + 'ZfcRbacTest\Initializer\AuthorizationAwareFake' + ); + $decoratedInstance = $serviceManager->get('ZfcRbacTest\AuthorizationAware'); + $this->assertNull($decoratedInstance->getAuthorizationService()); + } + + public function testAuthorizationServiceIsInjectedWithDelegator() + { + $serviceManager = ServiceManagerFactory::getServiceManager(); + + $serviceManager->setAllowOverride(true); + $authorizationService = $this->getMock('ZfcRbac\Service\AuthorizationService', [], [], '', false); + $serviceManager->setService( + 'ZfcRbac\Service\AuthorizationService', + $authorizationService + ); + $serviceManager->setAllowOverride(false); + + $serviceManager->setInvokableClass( + 'ZfcRbacTest\AuthorizationAware', + 'ZfcRbacTest\Initializer\AuthorizationAwareFake' + ); + + $serviceManager->addDelegator( + 'ZfcRbacTest\AuthorizationAware', + 'ZfcRbac\Factory\AuthorizationServiceDelegatorFactory' + ); + + $decoratedInstance = $serviceManager->get('ZfcRbacTest\AuthorizationAware'); + $this->assertEquals($authorizationService, $decoratedInstance->getAuthorizationService()); + } + + public function testDelegatorThrowExceptionWhenBadInterface() + { + $serviceManager = ServiceManagerFactory::getServiceManager(); + + $serviceManager->setAllowOverride(true); + $authorizationService = $this->getMock('ZfcRbac\Service\AuthorizationService', [], [], '', false); + $serviceManager->setService( + 'ZfcRbac\Service\AuthorizationService', + $authorizationService + ); + $serviceManager->setAllowOverride(false); + + $serviceManager->setFactory( + 'ZfcRbacTest\AuthorizationAware', + function () { + return new \StdClass(); + } + ); + + $serviceManager->addDelegator( + 'ZfcRbacTest\AuthorizationAware', + 'ZfcRbac\Factory\AuthorizationServiceDelegatorFactory' + ); + + $this->setExpectedException( + 'ZfcRbac\Exception\RuntimeException', + 'The service ZfcRbacTest\AuthorizationAware must implement AuthorizationServiceAwareInterface.' + ); + $serviceManager->get('ZfcRbacTest\AuthorizationAware'); + } +} diff --git a/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/AuthorizationServiceFactoryTest.php b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/AuthorizationServiceFactoryTest.php new file mode 100644 index 00000000000..1827445424b --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/AuthorizationServiceFactoryTest.php @@ -0,0 +1,54 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbacTest\Factory; + +use Zend\ServiceManager\ServiceManager; +use ZfcRbac\Factory\AuthorizationServiceFactory; +use ZfcRbac\Options\ModuleOptions; + +/** + * @covers \ZfcRbac\Factory\AuthorizationServiceFactory + */ +class AuthorizationServiceFactoryTest extends \PHPUnit_Framework_TestCase +{ + public function testFactory() + { + $serviceManager = new ServiceManager(); + + $serviceManager->setService('Rbac\Rbac', $this->getMock('Rbac\Rbac', [], [], '', false)); + + $serviceManager->setService( + 'ZfcRbac\Service\RoleService', + $this->getMock('ZfcRbac\Service\RoleService', [], [], '', false) + ); + $serviceManager->setService( + 'ZfcRbac\Assertion\AssertionPluginManager', + $this->getMock('ZfcRbac\Assertion\AssertionPluginManager', [], [], '', false) + ); + $serviceManager->setService( + 'ZfcRbac\Options\ModuleOptions', + new ModuleOptions([]) + ); + + $factory = new AuthorizationServiceFactory(); + $authorizationService = $factory->createService($serviceManager); + + $this->assertInstanceOf('ZfcRbac\Service\AuthorizationService', $authorizationService); + } +} diff --git a/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/ControllerGuardFactoryTest.php b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/ControllerGuardFactoryTest.php new file mode 100644 index 00000000000..850c0001dd1 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/ControllerGuardFactoryTest.php @@ -0,0 +1,62 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbacTest\Factory; + +use Zend\ServiceManager\ServiceManager; +use ZfcRbac\Factory\ControllerGuardFactory; +use ZfcRbac\Guard\GuardInterface; +use ZfcRbac\Guard\GuardPluginManager; +use ZfcRbac\Options\ModuleOptions; + +/** + * @covers \ZfcRbac\Factory\ControllerGuardFactory + */ +class ControllerGuardFactoryTest extends \PHPUnit_Framework_TestCase +{ + public function testFactory() + { + $options = new ModuleOptions([ + 'identity_provider' => 'ZfcRbac\Identity\AuthenticationProvider', + 'guards' => [ + 'ZfcRbac\Guard\ControllerGuard' => [ + 'controller' => 'MyController', + 'actions' => 'edit', + 'roles' => 'member' + ] + ], + 'protection_policy' => GuardInterface::POLICY_ALLOW + ]); + + $serviceManager = new ServiceManager(); + $serviceManager->setService('ZfcRbac\Options\ModuleOptions', $options); + $serviceManager->setService( + 'ZfcRbac\Service\RoleService', + $this->getMock('ZfcRbac\Service\RoleService', [], [], '', false) + ); + + $pluginManager = new GuardPluginManager(); + $pluginManager->setServiceLocator($serviceManager); + + $factory = new ControllerGuardFactory(); + $controllerGuard = $factory->createService($pluginManager); + + $this->assertInstanceOf('ZfcRbac\Guard\ControllerGuard', $controllerGuard); + $this->assertEquals(GuardInterface::POLICY_ALLOW, $controllerGuard->getProtectionPolicy()); + } +} diff --git a/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/ControllerPermissionsGuardFactoryTest.php b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/ControllerPermissionsGuardFactoryTest.php new file mode 100644 index 00000000000..046741053b3 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/ControllerPermissionsGuardFactoryTest.php @@ -0,0 +1,62 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbacTest\Factory; + +use Zend\ServiceManager\ServiceManager; +use ZfcRbac\Factory\ControllerPermissionsGuardFactory; +use ZfcRbac\Guard\GuardInterface; +use ZfcRbac\Guard\GuardPluginManager; +use ZfcRbac\Options\ModuleOptions; + +/** + * @covers \ZfcRbac\Factory\ControllerPermissionsGuardFactory + */ +class ControllerPermissionsGuardFactoryTest extends \PHPUnit_Framework_TestCase +{ + public function testFactory() + { + $creationOptions = [ + 'route' => 'permission' + ]; + + $options = new ModuleOptions([ + 'identity_provider' => 'ZfcRbac\Identity\AuthenticationProvider', + 'guards' => [ + 'ZfcRbac\Guard\ControllerPermissionsGuard' => $creationOptions + ], + 'protection_policy' => GuardInterface::POLICY_ALLOW, + ]); + + $serviceManager = new ServiceManager(); + $serviceManager->setService('ZfcRbac\Options\ModuleOptions', $options); + $serviceManager->setService( + 'ZfcRbac\Service\AuthorizationService', + $this->getMock('ZfcRbac\Service\AuthorizationService', [], [], '', false) + ); + + $pluginManager = new GuardPluginManager(); + $pluginManager->setServiceLocator($serviceManager); + + $factory = new ControllerPermissionsGuardFactory(); + $guard = $factory->createService($pluginManager); + + $this->assertInstanceOf('ZfcRbac\Guard\ControllerPermissionsGuard', $guard); + $this->assertEquals(GuardInterface::POLICY_ALLOW, $guard->getProtectionPolicy()); + } +} diff --git a/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/GuardPluginManagerFactoryTest.php b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/GuardPluginManagerFactoryTest.php new file mode 100644 index 00000000000..1f7b2c28f2f --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/GuardPluginManagerFactoryTest.php @@ -0,0 +1,44 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbacTest\Factory; + +use Zend\ServiceManager\ServiceManager; +use ZfcRbac\Factory\GuardPluginManagerFactory; + +/** + * @covers \ZfcRbac\Factory\GuardPluginManagerFactory + */ +class GuardPluginManagerFactoryTest extends \PHPUnit_Framework_TestCase +{ + public function testFactory() + { + $serviceManager = new ServiceManager(); + $serviceManager->setService('Config', [ + 'zfc_rbac' => [ + 'guard_manager' => [] + ] + ]); + + $factory = new GuardPluginManagerFactory(); + $pluginManager = $factory->createService($serviceManager); + + $this->assertInstanceOf('ZfcRbac\Guard\GuardPluginManager', $pluginManager); + $this->assertSame($serviceManager, $pluginManager->getServiceLocator()); + } +} diff --git a/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/GuardsFactoryTest.php b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/GuardsFactoryTest.php new file mode 100644 index 00000000000..f1c494b7023 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/GuardsFactoryTest.php @@ -0,0 +1,101 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbacTest\Factory; + +use Zend\ServiceManager\ServiceManager; +use ZfcRbac\Factory\GuardsFactory; +use ZfcRbac\Guard\GuardPluginManager; +use ZfcRbac\Options\ModuleOptions; + +/** + * @covers \ZfcRbac\Factory\GuardsFactory + */ +class GuardsFactoryTest extends \PHPUnit_Framework_TestCase +{ + public function testFactory() + { + $moduleOptions = new ModuleOptions([ + 'guards' => [ + 'ZfcRbac\Guard\RouteGuard' => [ + 'admin/*' => 'role1' + ], + 'ZfcRbac\Guard\RoutePermissionsGuard' => [ + 'admin/post' => 'post.manage' + ], + 'ZfcRbac\Guard\ControllerGuard' => [[ + 'controller' => 'MyController', + 'actions' => ['index', 'edit'], + 'roles' => ['role'] + ]], + 'ZfcRbac\Guard\ControllerPermissionsGuard' => [[ + 'controller' => 'PostController', + 'actions' => ['index', 'edit'], + 'permissions' => ['post.read'] + ]] + ] + ]); + + $pluginManager = new GuardPluginManager(); + + $serviceManager = new ServiceManager(); + $serviceManager->setService('ZfcRbac\Options\ModuleOptions', $moduleOptions); + $serviceManager->setService('ZfcRbac\Guard\GuardPluginManager', $pluginManager); + $serviceManager->setService( + 'ZfcRbac\Service\RoleService', + $this->getMock('ZfcRbac\Service\RoleService', [], [], '', false) + ); + $serviceManager->setService( + 'ZfcRbac\Service\AuthorizationService', + $this->getMock('ZfcRbac\Service\AuthorizationServiceInterface', [], [], '', false) + ); + + $pluginManager->setServiceLocator($serviceManager); + + $factory = new GuardsFactory(); + $guards = $factory->createService($serviceManager); + + $this->assertInternalType('array', $guards); + + $this->assertCount(4, $guards); + $this->assertInstanceOf('ZfcRbac\Guard\RouteGuard', $guards[0]); + $this->assertInstanceOf('ZfcRbac\Guard\RoutePermissionsGuard', $guards[1]); + $this->assertInstanceOf('ZfcRbac\Guard\ControllerGuard', $guards[2]); + $this->assertInstanceOf('ZfcRbac\Guard\ControllerPermissionsGuard', $guards[3]); + } + + public function testReturnArrayIfNoConfig() + { + $moduleOptions = new ModuleOptions([ + 'guards' => [] + ]); + + $pluginManager = new GuardPluginManager(); + + $serviceManager = new ServiceManager(); + $serviceManager->setService('ZfcRbac\Options\ModuleOptions', $moduleOptions); + $pluginManager->setServiceLocator($serviceManager); + + $factory = new GuardsFactory(); + $guards = $factory->createService($serviceManager); + + $this->assertInternalType('array', $guards); + + $this->assertEmpty($guards); + } +} diff --git a/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/HasRoleViewHelperFactoryTest.php b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/HasRoleViewHelperFactoryTest.php new file mode 100644 index 00000000000..c2a052eef48 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/HasRoleViewHelperFactoryTest.php @@ -0,0 +1,47 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbacTest\Factory; + +use Zend\ServiceManager\ServiceManager; +use Zend\View\HelperPluginManager; +use ZfcRbac\Factory\HasRoleViewHelperFactory; + +/** + * @covers \ZfcRbac\Factory\HasRoleViewHelperFactory + */ +class HasRoleViewHelperFactoryTest extends \PHPUnit_Framework_TestCase +{ + public function testFactory() + { + $serviceManager = new ServiceManager(); + + $pluginManager = new HelperPluginManager(); + $pluginManager->setServiceLocator($serviceManager); + + $serviceManager->setService( + 'ZfcRbac\Service\RoleService', + $this->getMock('ZfcRbac\Service\RoleService', [], [], '', false) + ); + + $factory = new HasRoleViewHelperFactory(); + $viewHelper = $factory->createService($pluginManager); + + $this->assertInstanceOf('ZfcRbac\View\Helper\HasRole', $viewHelper); + } +} diff --git a/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/IsGrantedPluginFactoryTest.php b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/IsGrantedPluginFactoryTest.php new file mode 100644 index 00000000000..9095c91b581 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/IsGrantedPluginFactoryTest.php @@ -0,0 +1,47 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbacTest\Factory; + +use Zend\Mvc\Controller\PluginManager; +use Zend\ServiceManager\ServiceManager; +use ZfcRbac\Factory\IsGrantedPluginFactory; + +/** + * @covers \ZfcRbac\Factory\IsGrantedPluginFactory + */ +class IsGrantedPluginFactoryTest extends \PHPUnit_Framework_TestCase +{ + public function testFactory() + { + $serviceManager = new ServiceManager(); + + $pluginManager = new PluginManager(); + $pluginManager->setServiceLocator($serviceManager); + + $serviceManager->setService( + 'ZfcRbac\Service\AuthorizationService', + $this->getMock('ZfcRbac\Service\AuthorizationServiceInterface') + ); + + $factory = new IsGrantedPluginFactory(); + $isGranted = $factory->createService($pluginManager); + + $this->assertInstanceOf('ZfcRbac\Mvc\Controller\Plugin\IsGranted', $isGranted); + } +} diff --git a/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/IsGrantedViewHelperFactoryTest.php b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/IsGrantedViewHelperFactoryTest.php new file mode 100644 index 00000000000..aa638d39f19 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/IsGrantedViewHelperFactoryTest.php @@ -0,0 +1,47 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbacTest\Factory; + +use Zend\ServiceManager\ServiceManager; +use Zend\View\HelperPluginManager; +use ZfcRbac\Factory\IsGrantedViewHelperFactory; + +/** + * @covers \ZfcRbac\Factory\IsGrantedViewHelperFactory + */ +class IsGrantedViewHelperFactoryTest extends \PHPUnit_Framework_TestCase +{ + public function testFactory() + { + $serviceManager = new ServiceManager(); + + $pluginManager = new HelperPluginManager(); + $pluginManager->setServiceLocator($serviceManager); + + $serviceManager->setService( + 'ZfcRbac\Service\AuthorizationService', + $this->getMock('ZfcRbac\Service\AuthorizationServiceInterface') + ); + + $factory = new IsGrantedViewHelperFactory(); + $isGranted = $factory->createService($pluginManager); + + $this->assertInstanceOf('ZfcRbac\View\Helper\IsGranted', $isGranted); + } +} diff --git a/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/ModuleOptionsFactoryTest.php b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/ModuleOptionsFactoryTest.php new file mode 100644 index 00000000000..4e2e5bf358e --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/ModuleOptionsFactoryTest.php @@ -0,0 +1,42 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbacTest\Factory; + +use Zend\ServiceManager\ServiceManager; +use ZfcRbac\Factory\ModuleOptionsFactory; + +/** + * @covers \ZfcRbac\Factory\ModuleOptionsFactory + */ +class ModuleOptionsFactoryTest extends \PHPUnit_Framework_TestCase +{ + public function testFactory() + { + $config = ['zfc_rbac' => []]; + + $serviceManager = new ServiceManager(); + $serviceManager->setService('Config', $config); + + $factory = new ModuleOptionsFactory(); + $options = $factory->createService($serviceManager); + + $this->assertInstanceOf('ZfcRbac\Options\ModuleOptions', $options); + } +} + \ No newline at end of file diff --git a/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/ObjectRepositoryRoleProviderFactoryTest.php b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/ObjectRepositoryRoleProviderFactoryTest.php new file mode 100644 index 00000000000..bd328e02a08 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/ObjectRepositoryRoleProviderFactoryTest.php @@ -0,0 +1,126 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbacTest\Factory; + +use Zend\ServiceManager\Exception\ServiceNotCreatedException; +use Zend\ServiceManager\ServiceManager; +use ZfcRbac\Exception\RuntimeException; +use ZfcRbac\Role\RoleProviderPluginManager; + +/** + * @covers \ZfcRbac\Factory\ObjectRepositoryRoleProviderFactory + */ +class ObjectRepositoryRoleProviderFactoryTest extends \PHPUnit_Framework_TestCase +{ + public function testFactoryUsingObjectRepository() + { + $pluginManager = new RoleProviderPluginManager(); + $serviceManager = new ServiceManager(); + + $pluginManager->setServiceLocator($serviceManager); + + $options = [ + 'role_name_property' => 'name', + 'object_repository' => 'RoleObjectRepository' + ]; + + $serviceManager->setService('RoleObjectRepository', $this->getMock('Doctrine\Common\Persistence\ObjectRepository')); + + $roleProvider = $pluginManager->get('ZfcRbac\Role\ObjectRepositoryRoleProvider', $options); + $this->assertInstanceOf('ZfcRbac\Role\ObjectRepositoryRoleProvider', $roleProvider); + } + + public function testFactoryUsingObjectManager() + { + $pluginManager = new RoleProviderPluginManager(); + $serviceManager = new ServiceManager(); + + $pluginManager->setServiceLocator($serviceManager); + + $options = [ + 'role_name_property' => 'name', + 'object_manager' => 'ObjectManager', + 'class_name' => 'Role' + ]; + + $objectManager = $this->getMock('Doctrine\Common\Persistence\ObjectManager'); + $objectManager->expects($this->once()) + ->method('getRepository') + ->with($options['class_name']) + ->will($this->returnValue($this->getMock('Doctrine\Common\Persistence\ObjectRepository'))); + + $serviceManager->setService('ObjectManager', $objectManager); + + $roleProvider = $pluginManager->get('ZfcRbac\Role\ObjectRepositoryRoleProvider', $options); + $this->assertInstanceOf('ZfcRbac\Role\ObjectRepositoryRoleProvider', $roleProvider); + } + + /** + * This is required due to the fact that the ServiceManager catches ALL exceptions and throws it's own... + */ + public function testThrowExceptionIfNoRoleNamePropertyIsSet() + { + try { + $pluginManager = new RoleProviderPluginManager(); + $serviceManager = new ServiceManager(); + + $pluginManager->setServiceLocator($serviceManager); + $pluginManager->get('ZfcRbac\Role\ObjectRepositoryRoleProvider', []); + } catch (ServiceNotCreatedException $smException) { + while ($e = $smException->getPrevious()) { + if ($e instanceof RuntimeException) { + return true; + } + } + } + + $this->fail( + 'ZfcRbac\Factory\ObjectRepositoryRoleProviderFactory::createService() :: ' + .'ZfcRbac\Exception\RuntimeException was not found in the previous Exceptions' + ); + } + + /** + * This is required due to the fact that the ServiceManager catches ALL exceptions and throws it's own... + */ + public function testThrowExceptionIfNoObjectManagerNorObjectRepositoryIsSet() + { + try { + $pluginManager = new RoleProviderPluginManager(); + $serviceManager = new ServiceManager(); + + $pluginManager->setServiceLocator($serviceManager); + $pluginManager->get('ZfcRbac\Role\ObjectRepositoryRoleProvider', [ + 'role_name_property' => 'name' + ]); + } catch (ServiceNotCreatedException $smException) { + + while ($e = $smException->getPrevious()) { + if ($e instanceof RuntimeException) { + return true; + } + } + } + + $this->fail( + 'ZfcRbac\Factory\ObjectRepositoryRoleProviderFactory::createService() :: ' + .'ZfcRbac\Exception\RuntimeException was not found in the previous Exceptions' + ); + } +} diff --git a/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/RbacFactoryTest.php b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/RbacFactoryTest.php new file mode 100644 index 00000000000..2b793d1c639 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/RbacFactoryTest.php @@ -0,0 +1,39 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbacTest\Factory; + +use Zend\ServiceManager\ServiceManager; +use ZfcRbac\Factory\RbacFactory; + +/** + * @covers ZfcRbac\Factory\RbacFactory + */ +class RbacFactoryTest extends \PHPUnit_Framework_TestCase +{ + public function testCanCreateFromFactory() + { + $serviceManager = new ServiceManager(); + $factory = new RbacFactory(); + + $rbac = $factory->createService($serviceManager); + + $this->assertInstanceOf('Rbac\Rbac', $rbac); + $this->assertInstanceOf('Rbac\Traversal\Strategy\TraversalStrategyInterface', $rbac->getTraversalStrategy()); + } +} diff --git a/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/RedirectStrategyFactoryTest.php b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/RedirectStrategyFactoryTest.php new file mode 100644 index 00000000000..d531b9c917f --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/RedirectStrategyFactoryTest.php @@ -0,0 +1,55 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbacTest\Factory; + +use ZfcRbac\Factory\RedirectStrategyFactory; + +/** + * @covers \ZfcRbac\Factory\RedirectStrategyFactory + */ +class RedirectStrategyFactoryTest extends \PHPUnit_Framework_TestCase +{ + public function testFactory() + { + $redirectStrategyOptions = $this->getMock('ZfcRbac\Options\RedirectStrategyOptions'); + + $moduleOptionsMock = $this->getMock('ZfcRbac\Options\ModuleOptions'); + $moduleOptionsMock->expects($this->once()) + ->method('getRedirectStrategy') + ->will($this->returnValue($redirectStrategyOptions)); + + $authenticationServiceMock = $this->getMock('Zend\Authentication\AuthenticationService'); + + $serviceLocatorMock = $this->getMock('Zend\ServiceManager\ServiceLocatorInterface'); + $serviceLocatorMock->expects($this->at(0)) + ->method('get') + ->with('ZfcRbac\Options\ModuleOptions') + ->will($this->returnValue($moduleOptionsMock)); + $serviceLocatorMock->expects($this->at(1)) + ->method('get') + ->with('Zend\Authentication\AuthenticationService') + ->will($this->returnValue($authenticationServiceMock)); + + $factory = new RedirectStrategyFactory(); + $redirectStrategy = $factory->createService($serviceLocatorMock); + + $this->assertInstanceOf('ZfcRbac\View\Strategy\RedirectStrategy', $redirectStrategy); + } +} + \ No newline at end of file diff --git a/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/RoleProviderPluginManagerFactoryTest.php b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/RoleProviderPluginManagerFactoryTest.php new file mode 100644 index 00000000000..13c490e5f0b --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/RoleProviderPluginManagerFactoryTest.php @@ -0,0 +1,44 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbacTest\Factory; + +use Zend\ServiceManager\ServiceManager; +use ZfcRbac\Factory\RoleProviderPluginManagerFactory; + +/** + * @covers \ZfcRbac\Factory\RoleProviderPluginManagerFactory + */ +class RoleProviderPluginManagerFactoryTest extends \PHPUnit_Framework_TestCase +{ + public function testFactory() + { + $serviceManager = new ServiceManager(); + $serviceManager->setService('Config', [ + 'zfc_rbac' => [ + 'role_provider_manager' => [] + ] + ]); + + $factory = new RoleProviderPluginManagerFactory(); + $pluginManager = $factory->createService($serviceManager); + + $this->assertInstanceOf('ZfcRbac\Role\RoleProviderPluginManager', $pluginManager); + $this->assertSame($serviceManager, $pluginManager->getServiceLocator()); + } +} diff --git a/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/RoleServiceFactoryTest.php b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/RoleServiceFactoryTest.php new file mode 100644 index 00000000000..63eafca89ad --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/RoleServiceFactoryTest.php @@ -0,0 +1,86 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbacTest\Factory; + +use Zend\ServiceManager\ServiceManager; +use ZfcRbac\Factory\RoleServiceFactory; +use ZfcRbac\Options\ModuleOptions; +use ZfcRbac\Role\RoleProviderPluginManager; + +/** + * @covers \ZfcRbac\Factory\RoleServiceFactory + */ +class RoleServiceFactoryTest extends \PHPUnit_Framework_TestCase +{ + public function testFactory() + { + $options = new ModuleOptions([ + 'identity_provider' => 'ZfcRbac\Identity\AuthenticationProvider', + 'guest_role' => 'guest', + 'role_provider' => [ + 'ZfcRbac\Role\InMemoryRoleProvider' => [ + 'foo' + ] + ] + ]); + + $serviceManager = new ServiceManager(); + $serviceManager->setService('ZfcRbac\Options\ModuleOptions', $options); + $serviceManager->setService('ZfcRbac\Role\RoleProviderPluginManager', new RoleProviderPluginManager()); + $serviceManager->setService( + 'ZfcRbac\Identity\AuthenticationProvider', + $this->getMock('ZfcRbac\Identity\IdentityProviderInterface') + ); + + $traversalStrategy = $this->getMock('Rbac\Traversal\Strategy\TraversalStrategyInterface'); + $rbac = $this->getMock('Rbac\Rbac', [], [], '', false); + + $rbac->expects($this->once())->method('getTraversalStrategy')->will($this->returnValue($traversalStrategy)); + + $serviceManager->setService('Rbac\Rbac', $rbac); + + $factory = new RoleServiceFactory(); + $roleService = $factory->createService($serviceManager); + + $this->assertInstanceOf('ZfcRbac\Service\RoleService', $roleService); + $this->assertEquals('guest', $roleService->getGuestRole()); + $this->assertAttributeSame($traversalStrategy, 'traversalStrategy', $roleService); + } + + public function testThrowExceptionIfNoRoleProvider() + { + $this->setExpectedException('ZfcRbac\Exception\RuntimeException'); + + $options = new ModuleOptions([ + 'identity_provider' => 'ZfcRbac\Identity\AuthenticationProvider', + 'guest_role' => 'guest', + 'role_provider' => [] + ]); + + $serviceManager = new ServiceManager(); + $serviceManager->setService('ZfcRbac\Options\ModuleOptions', $options); + $serviceManager->setService( + 'ZfcRbac\Identity\AuthenticationProvider', + $this->getMock('ZfcRbac\Identity\IdentityProviderInterface') + ); + + $factory = new RoleServiceFactory(); + $roleService = $factory->createService($serviceManager); + } +} diff --git a/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/RouteGuardFactoryTest.php b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/RouteGuardFactoryTest.php new file mode 100644 index 00000000000..8063ab4965e --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/RouteGuardFactoryTest.php @@ -0,0 +1,62 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbacTest\Factory; + +use Zend\ServiceManager\ServiceManager; +use ZfcRbac\Factory\RouteGuardFactory; +use ZfcRbac\Guard\GuardInterface; +use ZfcRbac\Guard\GuardPluginManager; +use ZfcRbac\Options\ModuleOptions; + +/** + * @covers \ZfcRbac\Factory\RouteGuardFactory + */ +class RouteGuardFactoryTest extends \PHPUnit_Framework_TestCase +{ + public function testFactory() + { + $creationOptions = [ + 'route' => 'role' + ]; + + $options = new ModuleOptions([ + 'identity_provider' => 'ZfcRbac\Identity\AuthenticationProvider', + 'guards' => [ + 'ZfcRbac\Guard\RouteGuard' => $creationOptions + ], + 'protection_policy' => GuardInterface::POLICY_ALLOW, + ]); + + $serviceManager = new ServiceManager(); + $serviceManager->setService('ZfcRbac\Options\ModuleOptions', $options); + $serviceManager->setService( + 'ZfcRbac\Service\RoleService', + $this->getMock('ZfcRbac\Service\RoleService', [], [], '', false) + ); + + $pluginManager = new GuardPluginManager(); + $pluginManager->setServiceLocator($serviceManager); + + $factory = new RouteGuardFactory(); + $routeGuard = $factory->createService($pluginManager); + + $this->assertInstanceOf('ZfcRbac\Guard\RouteGuard', $routeGuard); + $this->assertEquals(GuardInterface::POLICY_ALLOW, $routeGuard->getProtectionPolicy()); + } +} diff --git a/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/RoutePermissionsGuardFactoryTest.php b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/RoutePermissionsGuardFactoryTest.php new file mode 100644 index 00000000000..6aee9e566a9 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/RoutePermissionsGuardFactoryTest.php @@ -0,0 +1,62 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbacTest\Factory; + +use Zend\ServiceManager\ServiceManager; +use ZfcRbac\Factory\RoutePermissionsGuardFactory; +use ZfcRbac\Guard\GuardInterface; +use ZfcRbac\Guard\GuardPluginManager; +use ZfcRbac\Options\ModuleOptions; + +/** + * @covers \ZfcRbac\Factory\RoutePermissionsGuardFactory + */ +class RoutePermissionsGuardFactoryTest extends \PHPUnit_Framework_TestCase +{ + public function testFactory() + { + $creationOptions = [ + 'route' => 'role' + ]; + + $options = new ModuleOptions([ + 'identity_provider' => 'ZfcRbac\Identity\AuthenticationProvider', + 'guards' => [ + 'ZfcRbac\Guard\RoutePermissionsGuard' => $creationOptions + ], + 'protection_policy' => GuardInterface::POLICY_ALLOW, + ]); + + $serviceManager = new ServiceManager(); + $serviceManager->setService('ZfcRbac\Options\ModuleOptions', $options); + $serviceManager->setService( + 'ZfcRbac\Service\AuthorizationService', + $this->getMock('ZfcRbac\Service\AuthorizationService', [], [], '', false) + ); + + $pluginManager = new GuardPluginManager(); + $pluginManager->setServiceLocator($serviceManager); + + $factory = new RoutePermissionsGuardFactory(); + $routeGuard = $factory->createService($pluginManager); + + $this->assertInstanceOf('ZfcRbac\Guard\RoutePermissionsGuard', $routeGuard); + $this->assertEquals(GuardInterface::POLICY_ALLOW, $routeGuard->getProtectionPolicy()); + } +} diff --git a/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/UnauthorizedStrategyFactoryTest.php b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/UnauthorizedStrategyFactoryTest.php new file mode 100644 index 00000000000..1efb9b6be44 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Factory/UnauthorizedStrategyFactoryTest.php @@ -0,0 +1,49 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbacTest\Factory; + +use ZfcRbac\Factory\UnauthorizedStrategyFactory; + +/** + * @covers \ZfcRbac\Factory\UnauthorizedStrategyFactory + */ +class UnauthorizedStrategyFactoryTest extends \PHPUnit_Framework_TestCase +{ + public function testFactory() + { + $unauthorizedStrategyOptions = $this->getMock('ZfcRbac\Options\UnauthorizedStrategyOptions'); + + $moduleOptionsMock = $this->getMock('ZfcRbac\Options\ModuleOptions'); + $moduleOptionsMock->expects($this->once()) + ->method('getUnauthorizedStrategy') + ->will($this->returnValue($unauthorizedStrategyOptions)); + + $serviceLocatorMock = $this->getMock('Zend\ServiceManager\ServiceLocatorInterface'); + $serviceLocatorMock->expects($this->once()) + ->method('get') + ->with('ZfcRbac\Options\ModuleOptions') + ->will($this->returnValue($moduleOptionsMock)); + + $factory = new UnauthorizedStrategyFactory(); + $unauthorizedStrategy = $factory->createService($serviceLocatorMock); + + $this->assertInstanceOf('ZfcRbac\View\Strategy\UnauthorizedStrategy', $unauthorizedStrategy); + } +} + \ No newline at end of file diff --git a/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Guard/ControllerGuardTest.php b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Guard/ControllerGuardTest.php new file mode 100644 index 00000000000..3d3fa5ae44b --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Guard/ControllerGuardTest.php @@ -0,0 +1,524 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbacTest\Guard; + +use Zend\Mvc\MvcEvent; +use Zend\Mvc\Router\RouteMatch; +use ZfcRbac\Guard\ControllerGuard; +use ZfcRbac\Guard\GuardInterface; +use ZfcRbac\Role\InMemoryRoleProvider; +use ZfcRbac\Service\RoleService; +use Rbac\Traversal\Strategy\RecursiveRoleIteratorStrategy; + +/** + * @covers \ZfcRbac\Guard\AbstractGuard + * @covers \ZfcRbac\Guard\ControllerGuard + */ +class ControllerGuardTest extends \PHPUnit_Framework_TestCase +{ + public function testAttachToRightEvent() + { + $guard = new ControllerGuard($this->getMock('ZfcRbac\Service\RoleService', [], [], '', false)); + + $eventManager = $this->getMock('Zend\EventManager\EventManagerInterface'); + $eventManager->expects($this->once()) + ->method('attach') + ->with(ControllerGuard::EVENT_NAME); + + $guard->attach($eventManager); + } + + public function rulesConversionProvider() + { + return [ + // Without actions + [ + 'rules' => [ + [ + 'controller' => 'MyController', + 'roles' => 'role1' + ], + [ + 'controller' => 'MyController2', + 'roles' => ['role2', 'role3'] + ], + new \ArrayIterator([ + 'controller' => 'MyController3', + 'roles' => new \ArrayIterator(['role4']) + ]) + ], + 'expected' => [ + 'mycontroller' => [0 => ['role1']], + 'mycontroller2' => [0 => ['role2', 'role3']], + 'mycontroller3' => [0 => ['role4']] + ] + ], + + // With one action + [ + 'rules' => [ + [ + 'controller' => 'MyController', + 'actions' => 'DELETE', + 'roles' => 'role1' + ], + [ + 'controller' => 'MyController2', + 'actions' => ['delete'], + 'roles' => 'role2' + ], + new \ArrayIterator([ + 'controller' => 'MyController3', + 'actions' => new \ArrayIterator(['DELETE']), + 'roles' => new \ArrayIterator(['role3']) + ]) + ], + 'expected' => [ + 'mycontroller' => [ + 'delete' => ['role1'] + ], + 'mycontroller2' => [ + 'delete' => ['role2'] + ], + 'mycontroller3' => [ + 'delete' => ['role3'] + ], + ] + ], + + // With multiple actions + [ + 'rules' => [ + [ + 'controller' => 'MyController', + 'actions' => ['EDIT', 'delete'], + 'roles' => 'role1' + ], + new \ArrayIterator([ + 'controller' => 'MyController2', + 'actions' => new \ArrayIterator(['edit', 'DELETE']), + 'roles' => new \ArrayIterator(['role2']) + ]) + ], + 'expected' => [ + 'mycontroller' => [ + 'edit' => ['role1'], + 'delete' => ['role1'] + ], + 'mycontroller2' => [ + 'edit' => ['role2'], + 'delete' => ['role2'] + ] + ] + ], + + // Test that that if a rule is set globally to the controller, it does not override any + // action specific rule that may have been specified before + [ + 'rules' => [ + [ + 'controller' => 'MyController', + 'actions' => ['edit'], + 'roles' => 'role1' + ], + [ + 'controller' => 'MyController', + 'roles' => 'role2' + ] + ], + 'expected' => [ + 'mycontroller' => [ + 'edit' => ['role1'], + 0 => ['role2'] + ] + ] + ] + ]; + } + + /** + * @dataProvider rulesConversionProvider + */ + public function testRulesConversions(array $rules, array $expected) + { + $roleService = $this->getMock('ZfcRbac\Service\RoleService', [], [], '', false); + $controllerGuard = new ControllerGuard($roleService, $rules); + + $reflProperty = new \ReflectionProperty($controllerGuard, 'rules'); + $reflProperty->setAccessible(true); + + $this->assertEquals($expected, $reflProperty->getValue($controllerGuard)); + } + + public function controllerDataProvider() + { + return [ + // Test simple guard with both policies + [ + 'rules' => [ + [ + 'controller' => 'BlogController', + 'roles' => 'admin' + ] + ], + 'controller' => 'BlogController', + 'action' => 'edit', + 'rolesConfig' => [ + 'admin' + ], + 'identityRole' => 'admin', + 'isGranted' => true, + 'policy' => GuardInterface::POLICY_ALLOW + ], + [ + 'rules' => [ + [ + 'controller' => 'BlogController', + 'roles' => 'admin' + ] + ], + 'controller' => 'BlogController', + 'action' => 'edit', + 'rolesConfig' => [ + 'admin' + ], + 'identityRole' => 'admin', + 'isGranted' => true, + 'policy' => GuardInterface::POLICY_DENY + ], + + // Test with multiple rules + [ + 'rules' => [ + [ + 'controller' => 'BlogController', + 'actions' => 'read', + 'roles' => 'admin' + ], + [ + 'controller' => 'BlogController', + 'actions' => 'edit', + 'roles' => 'admin' + ] + ], + 'controller' => 'BlogController', + 'action' => 'edit', + 'rolesConfig' => [ + 'admin' + ], + 'identityRole' => 'admin', + 'isGranted' => true, + 'policy' => GuardInterface::POLICY_ALLOW + ], + [ + 'rules' => [ + [ + 'controller' => 'BlogController', + 'actions' => 'read', + 'roles' => 'admin' + ], + [ + 'controller' => 'BlogController', + 'actions' => 'edit', + 'roles' => 'admin' + ] + ], + 'controller' => 'BlogController', + 'action' => 'edit', + 'rolesConfig' => [ + 'admin' + ], + 'identityRole' => 'admin', + 'isGranted' => true, + 'policy' => GuardInterface::POLICY_DENY + ], + + // Assert that policy can deny unspecified rules + [ + 'rules' => [ + [ + 'controller' => 'BlogController', + 'roles' => 'member' + ], + ], + 'controller' => 'CommentController', + 'action' => 'edit', + 'rolesConfig' => [ + 'member' + ], + 'identityRole' => 'member', + 'isGranted' => true, + 'policy' => GuardInterface::POLICY_ALLOW + ], + [ + 'rules' => [ + [ + 'controller' => 'BlogController', + 'roles' => 'member' + ], + ], + 'controller' => 'CommentController', + 'action' => 'edit', + 'rolesConfig' => [ + 'member' + ], + 'identityRole' => 'member', + 'isGranted' => false, + 'policy' => GuardInterface::POLICY_DENY + ], + + // Test assert policy can deny other actions from controller when only one is specified + [ + 'rules' => [ + [ + 'controller' => 'BlogController', + 'actions' => 'edit', + 'roles' => 'member' + ], + ], + 'controller' => 'BlogController', + 'action' => 'read', + 'rolesConfig' => [ + 'member' + ], + 'identityRole' => 'member', + 'isGranted' => true, + 'policy' => GuardInterface::POLICY_ALLOW + ], + [ + 'rules' => [ + [ + 'controller' => 'BlogController', + 'actions' => 'edit', + 'roles' => 'member' + ], + ], + 'controller' => 'BlogController', + 'action' => 'read', + 'rolesConfig' => [ + 'member' + ], + 'identityRole' => 'member', + 'isGranted' => false, + 'policy' => GuardInterface::POLICY_DENY + ], + + // Assert it can uses parent-children relationship + [ + 'rules' => [ + [ + 'controller' => 'IndexController', + 'actions' => 'index', + 'roles' => 'guest' + ] + ], + 'controller' => 'IndexController', + 'action' => 'index', + 'rolesConfig' => [ + 'admin' => [ + 'children' => ['guest'] + ], + 'guest' + ], + 'identityRole' => 'admin', + 'isGranted' => true, + 'policy' => GuardInterface::POLICY_ALLOW + ], + [ + 'rules' => [ + [ + 'controller' => 'IndexController', + 'actions' => 'index', + 'roles' => 'guest' + ] + ], + 'controller' => 'IndexController', + 'action' => 'index', + 'rolesConfig' => [ + 'admin' => [ + 'children' => ['guest'] + ], + 'guest' + ], + 'identityRole' => 'admin', + 'isGranted' => true, + 'policy' => GuardInterface::POLICY_DENY + ], + + // Assert wildcard in roles + [ + 'rules' => [ + [ + 'controller' => 'IndexController', + 'roles' => '*' + ] + ], + 'controller' => 'IndexController', + 'action' => 'index', + 'rolesConfig' => [ + 'admin' + ], + 'identityRole' => 'admin', + 'isGranted' => true, + 'policy' => GuardInterface::POLICY_ALLOW + ], + [ + 'rules' => [ + [ + 'controller' => 'IndexController', + 'roles' => '*' + ] + ], + 'controller' => 'IndexController', + 'action' => 'index', + 'rolesConfig' => [ + 'admin' + ], + 'identityRole' => 'admin', + 'isGranted' => true, + 'policy' => GuardInterface::POLICY_DENY + ], + ]; + } + + /** + * @dataProvider controllerDataProvider + */ + public function testControllerGranted( + array $rules, + $controller, + $action, + array $rolesConfig, + $identityRole, + $isGranted, + $protectionPolicy + ) { + $event = new MvcEvent(); + $routeMatch = new RouteMatch([]); + $routeMatch->setParam('controller', $controller); + $routeMatch->setParam('action', $action); + + $event->setRouteMatch($routeMatch); + + $identity = $this->getMock('ZfcRbac\Identity\IdentityInterface'); + $identity->expects($this->any())->method('getRoles')->will($this->returnValue($identityRole)); + + $identityProvider = $this->getMock('ZfcRbac\Identity\IdentityProviderInterface'); + $identityProvider->expects($this->any()) + ->method('getIdentity') + ->will($this->returnValue($identity)); + + $roleProvider = new InMemoryRoleProvider($rolesConfig); + $roleService = new RoleService($identityProvider, $roleProvider, new RecursiveRoleIteratorStrategy()); + + $controllerGuard = new ControllerGuard($roleService, $rules); + $controllerGuard->setProtectionPolicy($protectionPolicy); + + $this->assertEquals($isGranted, $controllerGuard->isGranted($event)); + } + + public function testProperlyFillEventOnAuthorization() + { + $event = new MvcEvent(); + $routeMatch = new RouteMatch([]); + + $application = $this->getMock('Zend\Mvc\Application', [], [], '', false); + $eventManager = $this->getMock('Zend\EventManager\EventManagerInterface'); + + $application->expects($this->never()) + ->method('getEventManager') + ->will($this->returnValue($eventManager)); + + $routeMatch->setParam('controller', 'MyController'); + $routeMatch->setParam('action', 'edit'); + $event->setRouteMatch($routeMatch); + $event->setApplication($application); + + $identity = $this->getMock('ZfcRbac\Identity\IdentityInterface'); + $identity->expects($this->any())->method('getRoles')->will($this->returnValue(['member'])); + + $identityProvider = $this->getMock('ZfcRbac\Identity\IdentityProviderInterface'); + $identityProvider->expects($this->any()) + ->method('getIdentity') + ->will($this->returnValue($identity)); + + $roleProvider = new InMemoryRoleProvider([ + 'member' + ]); + + $roleService = new RoleService($identityProvider, $roleProvider, new RecursiveRoleIteratorStrategy()); + + $routeGuard = new ControllerGuard($roleService, [[ + 'controller' => 'MyController', + 'actions' => 'edit', + 'roles' => 'member' + ]]); + + $routeGuard->onResult($event); + + $this->assertEmpty($event->getError()); + $this->assertNull($event->getParam('exception')); + } + + public function testProperlySetUnauthorizedAndTriggerEventOnUnauthorization() + { + $event = new MvcEvent(); + $routeMatch = new RouteMatch([]); + + $application = $this->getMock('Zend\Mvc\Application', [], [], '', false); + $eventManager = $this->getMock('Zend\EventManager\EventManagerInterface'); + + $application->expects($this->once()) + ->method('getEventManager') + ->will($this->returnValue($eventManager)); + + $eventManager->expects($this->once()) + ->method('trigger') + ->with(MvcEvent::EVENT_DISPATCH_ERROR); + + $routeMatch->setParam('controller', 'MyController'); + $routeMatch->setParam('action', 'delete'); + + $event->setRouteMatch($routeMatch); + $event->setApplication($application); + + $identityProvider = $this->getMock('ZfcRbac\Identity\IdentityProviderInterface'); + $identityProvider->expects($this->any()) + ->method('getIdentityRoles') + ->will($this->returnValue('member')); + + $roleProvider = new InMemoryRoleProvider([ + 'member' + ]); + + $roleService = new RoleService($identityProvider, $roleProvider, new RecursiveRoleIteratorStrategy()); + + $routeGuard = new ControllerGuard($roleService, [[ + 'controller' => 'MyController', + 'actions' => 'edit', + 'roles' => 'member' + ]]); + + $routeGuard->onResult($event); + + $this->assertTrue($event->propagationIsStopped()); + $this->assertEquals(ControllerGuard::GUARD_UNAUTHORIZED, $event->getError()); + $this->assertInstanceOf('ZfcRbac\Exception\UnauthorizedException', $event->getParam('exception')); + } +} diff --git a/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Guard/ControllerPermissionsGuardTest.php b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Guard/ControllerPermissionsGuardTest.php new file mode 100644 index 00000000000..8b7f9cb5acd --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Guard/ControllerPermissionsGuardTest.php @@ -0,0 +1,513 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbacTest\Guard; + +use Zend\Mvc\MvcEvent; +use Zend\Mvc\Router\RouteMatch; +use ZfcRbac\Guard\ControllerGuard; +use ZfcRbac\Guard\ControllerPermissionsGuard; +use ZfcRbac\Guard\GuardInterface; +use ZfcRbac\Role\InMemoryRoleProvider; +use ZfcRbac\Service\RoleService; +use Rbac\Traversal\Strategy\RecursiveRoleIteratorStrategy; + +/** + * @covers \ZfcRbac\Guard\AbstractGuard + * @covers \ZfcRbac\Guard\ControllerPermissionsGuard + */ +class ControllerPermissionsGuardTest extends \PHPUnit_Framework_TestCase +{ + private function getMockAuthorizationService() + { + $authorizationService = $this->getMock('ZfcRbac\Service\AuthorizationService', [], [], '', false); + + return $authorizationService; + } + + public function testAttachToRightEvent() + { + $guard = new ControllerPermissionsGuard($this->getMockAuthorizationService()); + + $eventManager = $this->getMock('Zend\EventManager\EventManagerInterface'); + $eventManager->expects($this->once()) + ->method('attach') + ->with(ControllerGuard::EVENT_NAME); + + $guard->attach($eventManager); + } + + public function rulesConversionProvider() + { + return [ + // Without actions + [ + 'rules' => [ + [ + 'controller' => 'MyController', + 'permissions' => 'post.manage' + ], + [ + 'controller' => 'MyController2', + 'permissions' => ['post.update', 'post.delete'] + ], + new \ArrayIterator([ + 'controller' => 'MyController3', + 'permissions' => new \ArrayIterator(['post.manage']) + ]) + ], + 'expected' => [ + 'mycontroller' => [0 => ['post.manage']], + 'mycontroller2' => [0 => ['post.update', 'post.delete']], + 'mycontroller3' => [0 => ['post.manage']] + ] + ], + // With one action + [ + 'rules' => [ + [ + 'controller' => 'MyController', + 'actions' => 'DELETE', + 'permissions' => 'permission1' + ], + [ + 'controller' => 'MyController2', + 'actions' => ['delete'], + 'permissions' => 'permission2' + ], + new \ArrayIterator([ + 'controller' => 'MyController3', + 'actions' => new \ArrayIterator(['DELETE']), + 'permissions' => new \ArrayIterator(['permission3']) + ]) + ], + 'expected' => [ + 'mycontroller' => [ + 'delete' => ['permission1'] + ], + 'mycontroller2' => [ + 'delete' => ['permission2'] + ], + 'mycontroller3' => [ + 'delete' => ['permission3'] + ], + ] + ], + // With multiple actions + [ + 'rules' => [ + [ + 'controller' => 'MyController', + 'actions' => ['EDIT', 'delete'], + 'permissions' => 'permission1' + ], + new \ArrayIterator([ + 'controller' => 'MyController2', + 'actions' => new \ArrayIterator(['edit', 'DELETE']), + 'permissions' => new \ArrayIterator(['permission2']) + ]) + ], + 'expected' => [ + 'mycontroller' => [ + 'edit' => ['permission1'], + 'delete' => ['permission1'] + ], + 'mycontroller2' => [ + 'edit' => ['permission2'], + 'delete' => ['permission2'] + ] + ] + ], + // Test that that if a rule is set globally to the controller, it does not override any + // action specific rule that may have been specified before + [ + 'rules' => [ + [ + 'controller' => 'MyController', + 'actions' => ['edit'], + 'permissions' => 'permission1' + ], + [ + 'controller' => 'MyController', + 'permissions' => 'permission2' + ] + ], + 'expected' => [ + 'mycontroller' => [ + 'edit' => ['permission1'], + 0 => ['permission2'] + ] + ] + ] + ]; + } + + /** + * @dataProvider rulesConversionProvider + */ + public function testRulesConversions(array $rules, array $expected) + { + $controllerGuard = new ControllerPermissionsGuard($this->getMockAuthorizationService(), $rules); + + $reflProperty = new \ReflectionProperty($controllerGuard, 'rules'); + $reflProperty->setAccessible(true); + + $this->assertEquals($expected, $reflProperty->getValue($controllerGuard)); + } + + public function controllerDataProvider() + { + return [ + // Test simple guard with both policies + [ + 'rules' => [ + [ + 'controller' => 'BlogController', + 'permissions' => 'post.edit' + ] + ], + 'controller' => 'BlogController', + 'action' => 'edit', + 'identityPermissions' => [['post.edit', null, true]], + 'isGranted' => true, + 'policy' => GuardInterface::POLICY_ALLOW + ], + [ + 'rules' => [ + [ + 'controller' => 'BlogController', + 'permissions' => 'post.edit' + ] + ], + 'controller' => 'BlogController', + 'action' => 'edit', + 'identityPermissions' => [['post.edit', null, true]], + 'isGranted' => true, + 'policy' => GuardInterface::POLICY_DENY + ], + // Test with multiple rules + [ + 'rules' => [ + [ + 'controller' => 'BlogController', + 'actions' => 'read', + 'permissions' => 'post.read' + ], + [ + 'controller' => 'BlogController', + 'actions' => 'edit', + 'permissions' => 'post.edit' + ] + ], + 'controller' => 'BlogController', + 'action' => 'edit', + 'identityPermissions' => [ + ['post.edit', null, true] + ], + 'isGranted' => true, + 'policy' => GuardInterface::POLICY_ALLOW + ], + [ + 'rules' => [ + [ + 'controller' => 'BlogController', + 'actions' => 'read', + 'permissions' => 'post.read' + ], + [ + 'controller' => 'BlogController', + 'actions' => 'edit', + 'permissions' => 'post.edit' + ] + ], + 'controller' => 'BlogController', + 'action' => 'edit', + 'identityPermissions' => [ + ['post.edit', null, true] + ], + 'isGranted' => true, + 'policy' => GuardInterface::POLICY_DENY + ], + // Test with multiple permissions. All must be authorized. + [ + 'rules' => [ + [ + 'controller' => 'BlogController', + 'actions' => 'admin', + 'permissions' => ['post.update', 'post.delete'], + ], + ], + 'controller' => 'BlogController', + 'action' => 'admin', + 'identityPermissions' => [ + ['post.update', null, true], + ['post.delete', null, true], + ], + 'isGranted' => true, + 'policy' => GuardInterface::POLICY_DENY + ], + [ + 'rules' => [ + [ + 'controller' => 'BlogController', + 'actions' => 'admin', + 'permissions' => ['post.update', 'post.delete'], + ], + ], + 'controller' => 'BlogController', + 'action' => 'admin', + 'identityPermissions' => [ + ['post.update', null, false], + ['post.delete', null, true], + ], + 'isGranted' => false, + 'policy' => GuardInterface::POLICY_DENY + ], + [ + 'rules' => [ + [ + 'controller' => 'BlogController', + 'actions' => 'admin', + 'permissions' => ['post.update', 'post.delete'], + ], + ], + 'controller' => 'BlogController', + 'action' => 'admin', + 'identityPermissions' => [ + ['post.update', null, true], + ['post.delete', null, false], + ], + 'isGranted' => false, + 'policy' => GuardInterface::POLICY_DENY + ], + // Assert that policy can deny unspecified rules + [ + 'rules' => [ + [ + 'controller' => 'BlogController', + 'permissions' => 'post.edit' + ], + ], + 'controller' => 'CommentController', + 'action' => 'edit', + 'identityPermissions' => [ + ['post.edit', null, true] + ], + 'isGranted' => true, + 'policy' => GuardInterface::POLICY_ALLOW + ], + [ + 'rules' => [ + [ + 'controller' => 'BlogController', + 'permissions' => 'post.edit' + ], + ], + 'controller' => 'CommentController', + 'action' => 'edit', + 'identityPermissions' => [ + ['post.edit', null, true] + ], + 'isGranted' => false, + 'policy' => GuardInterface::POLICY_DENY + ], + // Test assert policy can deny other actions from controller when only one is specified + [ + 'rules' => [ + [ + 'controller' => 'BlogController', + 'actions' => 'edit', + 'permissions' => 'post.edit' + ], + ], + 'controller' => 'BlogController', + 'action' => 'read', + 'identityPermissions' => [ + ['post.edit', null, true] + ], + 'isGranted' => true, + 'policy' => GuardInterface::POLICY_ALLOW + ], + [ + 'rules' => [ + [ + 'controller' => 'BlogController', + 'actions' => 'edit', + 'permissions' => 'post.edit' + ], + ], + 'controller' => 'BlogController', + 'action' => 'read', + 'identityPermissions' => [ + ['post.edit', null, true] + ], + 'isGranted' => false, + 'policy' => GuardInterface::POLICY_DENY + ], + // Assert wildcard in permissions + [ + 'rules' => [ + [ + 'controller' => 'IndexController', + 'permissions' => '*' + ] + ], + 'controller' => 'IndexController', + 'action' => 'index', + 'identityPermissions' => [['post.edit', null, false]], + 'isGranted' => true, + 'policy' => GuardInterface::POLICY_ALLOW + ], + [ + 'rules' => [ + [ + 'controller' => 'IndexController', + 'permissions' => '*' + ] + ], + 'controller' => 'IndexController', + 'action' => 'index', + 'identityPermissions' => [['post.edit', null, false]], + 'isGranted' => true, + 'policy' => GuardInterface::POLICY_DENY + ], + ]; + } + + /** + * @dataProvider controllerDataProvider + */ + public function testControllerGranted( + array $rules, + $controller, + $action, + $identityPermissions, + $isGranted, + $protectionPolicy + ) { + $routeMatch = new RouteMatch([]); + $routeMatch->setParam('controller', $controller); + $routeMatch->setParam('action', $action); + + $authorizationService = $this->getMockAuthorizationService(); + $authorizationService->expects($this->any()) + ->method('isGranted') + ->will($this->returnValueMap($identityPermissions)); + + $controllerGuard = new ControllerPermissionsGuard($authorizationService, $rules); + $controllerGuard->setProtectionPolicy($protectionPolicy); + + $event = new MvcEvent(); + $event->setRouteMatch($routeMatch); + + $this->assertEquals($isGranted, $controllerGuard->isGranted($event)); + } + + public function testProperlyFillEventOnAuthorization() + { + $event = new MvcEvent(); + $routeMatch = new RouteMatch([]); + + $application = $this->getMock('Zend\Mvc\Application', [], [], '', false); + $eventManager = $this->getMock('Zend\EventManager\EventManagerInterface'); + + $application->expects($this->never()) + ->method('getEventManager') + ->will($this->returnValue($eventManager)); + + $routeMatch->setParam('controller', 'MyController'); + $routeMatch->setParam('action', 'edit'); + $event->setRouteMatch($routeMatch); + $event->setApplication($application); + + $identity = $this->getMock('ZfcRbac\Identity\IdentityInterface'); + $identity->expects($this->any())->method('getRoles')->will($this->returnValue(['member'])); + + $identityProvider = $this->getMock('ZfcRbac\Identity\IdentityProviderInterface'); + $identityProvider->expects($this->any()) + ->method('getIdentity') + ->will($this->returnValue($identity)); + + $roleProvider = new InMemoryRoleProvider([ + 'member' + ]); + + $roleService = new RoleService($identityProvider, $roleProvider, new RecursiveRoleIteratorStrategy()); + + $routeGuard = new ControllerGuard($roleService, [ + [ + 'controller' => 'MyController', + 'actions' => 'edit', + 'roles' => 'member' + ] + ]); + + $routeGuard->onResult($event); + + $this->assertEmpty($event->getError()); + $this->assertNull($event->getParam('exception')); + } + + public function testProperlySetUnauthorizedAndTriggerEventOnUnauthorization() + { + $event = new MvcEvent(); + $routeMatch = new RouteMatch([]); + + $application = $this->getMock('Zend\Mvc\Application', [], [], '', false); + $eventManager = $this->getMock('Zend\EventManager\EventManagerInterface'); + + $application->expects($this->once()) + ->method('getEventManager') + ->will($this->returnValue($eventManager)); + + $eventManager->expects($this->once()) + ->method('trigger') + ->with(MvcEvent::EVENT_DISPATCH_ERROR); + + $routeMatch->setParam('controller', 'MyController'); + $routeMatch->setParam('action', 'delete'); + + $event->setRouteMatch($routeMatch); + $event->setApplication($application); + + $identityProvider = $this->getMock('ZfcRbac\Identity\IdentityProviderInterface'); + $identityProvider->expects($this->any()) + ->method('getIdentityRoles') + ->will($this->returnValue('member')); + + $roleProvider = new InMemoryRoleProvider([ + 'member' + ]); + + $roleService = new RoleService($identityProvider, $roleProvider, new RecursiveRoleIteratorStrategy()); + + $routeGuard = new ControllerGuard($roleService, [ + [ + 'controller' => 'MyController', + 'actions' => 'edit', + 'roles' => 'member' + ] + ]); + + $routeGuard->onResult($event); + + $this->assertTrue($event->propagationIsStopped()); + $this->assertEquals(ControllerGuard::GUARD_UNAUTHORIZED, $event->getError()); + $this->assertInstanceOf('ZfcRbac\Exception\UnauthorizedException', $event->getParam('exception')); + } +} diff --git a/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Guard/GuardPluginManagerTest.php b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Guard/GuardPluginManagerTest.php new file mode 100644 index 00000000000..ff43d263c7f --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Guard/GuardPluginManagerTest.php @@ -0,0 +1,99 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbacTest\Guard; + +use Zend\ServiceManager\ServiceManager; +use ZfcRbac\Guard\GuardPluginManager; +use ZfcRbac\Options\ModuleOptions; + +/** + * @covers \ZfcRbac\Guard\GuardPluginManager + */ +class GuardPluginManagerTest extends \PHPUnit_Framework_TestCase +{ + public function guardProvider() + { + return [ + [ + 'ZfcRbac\Guard\RouteGuard', + [ + 'admin/*' => 'foo' + ] + ], + [ + 'ZfcRbac\Guard\RoutePermissionsGuard', + [ + 'post/delete' => 'post.delete' + ] + ], + [ + 'ZfcRbac\Guard\ControllerGuard', + [ + [ + 'controller' => 'Foo', + 'actions' => 'bar', + 'roles' => 'baz' + ] + ] + ], + [ + 'ZfcRbac\Guard\ControllerPermissionsGuard', + [ + [ + 'controller' => 'Foo', + 'actions' => 'bar', + 'permissions' => 'baz' + ] + ] + ], + ]; + } + + /** + * @dataProvider guardProvider + */ + public function testCanCreateDefaultGuards($type, $options) + { + $serviceManager = new ServiceManager(); + $serviceManager->setService('ZfcRbac\Options\ModuleOptions', new ModuleOptions()); + $serviceManager->setService( + 'ZfcRbac\Service\RoleService', + $this->getMock('ZfcRbac\Service\RoleService', [], [], '', false) + ); + $serviceManager->setService( + 'ZfcRbac\Service\AuthorizationService', + $this->getMock('ZfcRbac\Service\AuthorizationService', [], [], '', false) + ); + + $pluginManager = new GuardPluginManager(); + $pluginManager->setServiceLocator($serviceManager); + + $guard = $pluginManager->get($type, $options); + + $this->assertInstanceOf($type, $guard); + } + + public function testThrowExceptionForInvalidPlugin() + { + $this->setExpectedException('ZfcRbac\Exception\RuntimeException'); + + $pluginManager = new GuardPluginManager(); + $pluginManager->get('stdClass'); + } +} diff --git a/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Guard/ProtectionPolicyTraitTest.php b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Guard/ProtectionPolicyTraitTest.php new file mode 100644 index 00000000000..800f917ea50 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Guard/ProtectionPolicyTraitTest.php @@ -0,0 +1,34 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbacTest\Guard; +use ZfcRbac\Guard\GuardInterface; + +/** + * @covers \ZfcRbac\Guard\ProtectionPolicyTrait + */ +class ProtectionPolicyTraitTest extends \PHPUnit_Framework_TestCase +{ + public function testTrait() + { + $trait = $this->getObjectForTrait('ZfcRbac\Guard\ProtectionPolicyTrait'); + $trait->setProtectionPolicy(GuardInterface::POLICY_DENY); + + $this->assertEquals(GuardInterface::POLICY_DENY, $trait->getProtectionPolicy()); + } +} diff --git a/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Guard/RouteGuardTest.php b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Guard/RouteGuardTest.php new file mode 100644 index 00000000000..2844250946d --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Guard/RouteGuardTest.php @@ -0,0 +1,467 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbacTest\Guard; + +use Zend\Mvc\MvcEvent; +use Zend\Mvc\Router\RouteMatch; +use ZfcRbac\Guard\ControllerGuard; +use ZfcRbac\Guard\GuardInterface; +use ZfcRbac\Guard\RouteGuard; +use ZfcRbac\Guard\RoutePermissionsGuard; +use ZfcRbac\Role\InMemoryRoleProvider; +use ZfcRbac\Service\RoleService; +use Rbac\Traversal\Strategy\RecursiveRoleIteratorStrategy; + +/** + * @covers \ZfcRbac\Guard\AbstractGuard + * @covers \ZfcRbac\Guard\RouteGuard + */ +class RouteGuardTest extends \PHPUnit_Framework_TestCase +{ + public function testAttachToRightEvent() + { + $guard = new RouteGuard($this->getMock('ZfcRbac\Service\RoleService', [], [], '', false)); + + $eventManager = $this->getMock('Zend\EventManager\EventManagerInterface'); + $eventManager->expects($this->once()) + ->method('attach') + ->with(RouteGuard::EVENT_NAME); + + $guard->attach($eventManager); + } + + /** + * We want to ensure an order for guards + */ + public function testAssertRouteGuardPriority() + { + $this->assertGreaterThan(RoutePermissionsGuard::EVENT_PRIORITY, RouteGuard::EVENT_PRIORITY); + $this->assertGreaterThan(ControllerGuard::EVENT_PRIORITY, RouteGuard::EVENT_PRIORITY); + } + + public function rulesConversionProvider() + { + return [ + // Simple string to array conversion + [ + 'rules' => [ + 'route' => 'role1' + ], + 'expected' => [ + 'route' => ['role1'] + ] + ], + + // Array to array + [ + 'rules' => [ + 'route' => ['role1', 'role2'] + ], + 'expected' => [ + 'route' => ['role1', 'role2'] + ] + ], + + // Traversable to array + [ + 'rules' => [ + 'route' => new \ArrayIterator(['role1', 'role2']) + ], + 'expected' => [ + 'route' => ['role1', 'role2'] + ] + ], + + // Block a route for everyone + [ + 'rules' => [ + 'route' + ], + 'expected' => [ + 'route' => [] + ] + ], + ]; + } + + /** + * @dataProvider rulesConversionProvider + */ + public function testRulesConversions(array $rules, array $expected) + { + $roleService = $this->getMock('ZfcRbac\Service\RoleService', [], [], '', false); + $routeGuard = new RouteGuard($roleService, $rules); + + $reflProperty = new \ReflectionProperty($routeGuard, 'rules'); + $reflProperty->setAccessible(true); + + $this->assertEquals($expected, $reflProperty->getValue($routeGuard)); + } + + public function routeDataProvider() + { + return [ + // Assert basic one-to-one mapping with both policies + [ + 'rules' => ['adminRoute' => 'admin'], + 'matchedRouteName' => 'adminRoute', + 'rolesConfig' => ['admin'], + 'identityRole' => 'admin', + 'isGranted' => true, + 'policy' => GuardInterface::POLICY_ALLOW + ], + [ + 'rules' => ['adminRoute' => 'admin'], + 'matchedRouteName' => 'adminRoute', + 'rolesConfig' => ['admin'], + 'identityRole' => 'admin', + 'isGranted' => true, + 'policy' => GuardInterface::POLICY_DENY + ], + + // Assert that policy changes result for non-specified route guards + [ + 'rules' => ['route' => 'member'], + 'matchedRouteName' => 'anotherRoute', + 'rolesConfig' => ['member'], + 'identityRole' => 'member', + 'isGranted' => true, + 'policy' => GuardInterface::POLICY_ALLOW + ], + [ + 'rules' => ['route' => 'member'], + 'matchedRouteName' => 'anotherRoute', + 'rolesConfig' => ['member'], + 'identityRole' => 'member', + 'isGranted' => false, + 'policy' => GuardInterface::POLICY_DENY + ], + + // Assert that composed route work for both policies + [ + 'rules' => ['admin/dashboard' => 'admin'], + 'matchedRouteName' => 'admin/dashboard', + 'rolesConfig' => ['admin'], + 'identityRole' => 'admin', + 'isGranted' => true, + 'policy' => GuardInterface::POLICY_ALLOW + ], + [ + 'rules' => ['admin/dashboard' => 'admin'], + 'matchedRouteName' => 'admin/dashboard', + 'rolesConfig' => ['admin'], + 'identityRole' => 'admin', + 'isGranted' => true, + 'policy' => GuardInterface::POLICY_DENY + ], + + // Assert that wildcard route work for both policies + [ + 'rules' => ['admin/*' => 'admin'], + 'matchedRouteName' => 'admin/dashboard', + 'rolesConfig' => ['admin'], + 'identityRole' => 'admin', + 'isGranted' => true, + 'policy' => GuardInterface::POLICY_ALLOW + ], + [ + 'rules' => ['admin/*' => 'admin'], + 'matchedRouteName' => 'admin/dashboard', + 'rolesConfig' => ['admin'], + 'identityRole' => 'admin', + 'isGranted' => true, + 'policy' => GuardInterface::POLICY_DENY + ], + + // Assert that wildcard route does match (or not depending on the policy) if rules is after matched route name + [ + 'rules' => ['fooBar/*' => 'admin'], + 'matchedRouteName' => 'admin/fooBar/baz', + 'rolesConfig' => ['admin'], + 'identityRole' => 'admin', + 'isGranted' => true, + 'policy' => GuardInterface::POLICY_ALLOW + ], + [ + 'rules' => ['fooBar/*' => 'admin'], + 'matchedRouteName' => 'admin/fooBar/baz', + 'rolesConfig' => ['admin'], + 'identityRole' => 'admin', + 'isGranted' => false, + 'policy' => GuardInterface::POLICY_DENY + ], + + // Assert that it can grant access with multiple rules + [ + 'rules' => [ + 'route1' => 'admin', + 'route2' => 'admin' + ], + 'matchedRouteName' => 'route1', + 'rolesConfig' => ['admin'], + 'identityRole' => 'admin', + 'isGranted' => true, + 'policy' => GuardInterface::POLICY_ALLOW + ], + [ + 'rules' => [ + 'route1' => 'admin', + 'route2' => 'admin' + ], + 'matchedRouteName' => 'route1', + 'rolesConfig' => ['admin'], + 'identityRole' => 'admin', + 'isGranted' => true, + 'policy' => GuardInterface::POLICY_DENY + ], + + // Assert that it can grant/deny access with multiple rules based on the policy + [ + 'rules' => [ + 'route1' => 'admin', + 'route2' => 'admin' + ], + 'matchedRouteName' => 'route3', + 'rolesConfig' => ['admin'], + 'identityRole' => 'admin', + 'isGranted' => true, + 'policy' => GuardInterface::POLICY_ALLOW + ], + [ + 'rules' => [ + 'route1' => 'admin', + 'route2' => 'admin' + ], + 'matchedRouteName' => 'route3', + 'rolesConfig' => ['admin'], + 'identityRole' => 'admin', + 'isGranted' => false, + 'policy' => GuardInterface::POLICY_DENY + ], + + // Assert it can deny access if a role does not have access + [ + 'rules' => ['route' => 'admin'], + 'matchedRouteName' => 'route', + 'rolesConfig' => ['admin', 'guest'], + 'identityRole' => 'guest', + 'isGranted' => false, + 'policy' => GuardInterface::POLICY_ALLOW + ], + [ + 'rules' => ['route' => 'admin'], + 'matchedRouteName' => 'route', + 'rolesConfig' => ['admin', 'guest'], + 'identityRole' => 'guest', + 'isGranted' => false, + 'policy' => GuardInterface::POLICY_DENY + ], + + // Assert it can grant access using child-parent relationship between roles + [ + 'rules' => ['home' => 'guest'], + 'matchedRouteName' => 'home', + 'rolesConfig' => [ + 'admin' => [ + 'children' => ['member'] + ], + 'member' => [ + 'children' => ['guest'] + ], + 'guest' + ], + 'identityRole' => 'admin', + 'isGranted' => true, + 'policy' => GuardInterface::POLICY_ALLOW + ], + [ + 'rules' => ['home' => 'guest'], + 'matchedRouteName' => 'home', + 'rolesConfig' => [ + 'admin' => [ + 'children' => ['member'] + ], + 'member' => [ + 'children' => ['guest'] + ], + 'guest' + ], + 'identityRole' => 'admin', + 'isGranted' => true, + 'policy' => GuardInterface::POLICY_DENY + ], + + // Assert it can deny access using child-parent relationship between roles (just to be sure) + [ + 'rules' => ['route' => 'admin'], + 'matchedRouteName' => 'route', + 'rolesToCreate' => [ + 'admin' => [ + 'children' => 'member' + ], + 'member' + ], + 'identityRole' => 'member', + 'isGranted' => false, + 'policy' => GuardInterface::POLICY_ALLOW + ], + [ + 'rules' => ['route' => 'admin'], + 'matchedRouteName' => 'route', + 'rolesToCreate' => [ + 'admin' => [ + 'children' => 'member' + ], + 'member' + ], + 'identityRole' => 'member', + 'isGranted' => false, + 'policy' => GuardInterface::POLICY_DENY + ], + + // Assert wildcard in role + [ + 'rules' => ['home' => '*'], + 'matchedRouteName' => 'home', + 'rolesConfig' => ['admin'], + 'identityRole' => 'admin', + 'isGranted' => true, + 'policy' => GuardInterface::POLICY_ALLOW + ], + [ + 'rules' => ['home' => '*'], + 'matchedRouteName' => 'home', + 'rolesConfig' => ['admin'], + 'identityRole' => 'admin', + 'isGranted' => true, + 'policy' => GuardInterface::POLICY_DENY + ], + ]; + } + + /** + * @dataProvider routeDataProvider + */ + public function testRouteGranted( + array $rules, + $matchedRouteName, + array $rolesConfig, + $identityRole, + $isGranted, + $protectionPolicy + ) { + $event = new MvcEvent(); + $routeMatch = new RouteMatch([]); + $routeMatch->setMatchedRouteName($matchedRouteName); + + $event->setRouteMatch($routeMatch); + + $identity = $this->getMock('ZfcRbac\Identity\IdentityInterface'); + $identity->expects($this->any())->method('getRoles')->will($this->returnValue($identityRole)); + + $identityProvider = $this->getMock('ZfcRbac\Identity\IdentityProviderInterface'); + $identityProvider->expects($this->any()) + ->method('getIdentity') + ->will($this->returnValue($identity)); + + $roleProvider = new InMemoryRoleProvider($rolesConfig); + $roleService = new RoleService($identityProvider, $roleProvider, new RecursiveRoleIteratorStrategy()); + + $routeGuard = new RouteGuard($roleService, $rules); + $routeGuard->setProtectionPolicy($protectionPolicy); + + $this->assertEquals($isGranted, $routeGuard->isGranted($event)); + } + + public function testProperlyFillEventOnAuthorization() + { + $event = new MvcEvent(); + $routeMatch = new RouteMatch([]); + + $application = $this->getMock('Zend\Mvc\Application', [], [], '', false); + $eventManager = $this->getMock('Zend\EventManager\EventManagerInterface'); + + $application->expects($this->never()) + ->method('getEventManager') + ->will($this->returnValue($eventManager)); + + $routeMatch->setMatchedRouteName('adminRoute'); + $event->setRouteMatch($routeMatch); + $event->setApplication($application); + + $identity = $this->getMock('ZfcRbac\Identity\IdentityInterface'); + $identity->expects($this->any())->method('getRoles')->will($this->returnValue(['member'])); + + $identityProvider = $this->getMock('ZfcRbac\Identity\IdentityProviderInterface'); + $identityProvider->expects($this->any()) + ->method('getIdentity') + ->will($this->returnValue($identity)); + + $roleProvider = new InMemoryRoleProvider(['member']); + $roleService = new RoleService($identityProvider, $roleProvider, new RecursiveRoleIteratorStrategy()); + + $routeGuard = new RouteGuard($roleService, [ + 'adminRoute' => 'member' + ]); + + $routeGuard->onResult($event); + + $this->assertEmpty($event->getError()); + $this->assertNull($event->getParam('exception')); + } + + public function testProperlySetUnauthorizedAndTriggerEventOnUnauthorization() + { + $event = new MvcEvent(); + $routeMatch = new RouteMatch([]); + + $application = $this->getMock('Zend\Mvc\Application', [], [], '', false); + $eventManager = $this->getMock('Zend\EventManager\EventManagerInterface'); + + $application->expects($this->once()) + ->method('getEventManager') + ->will($this->returnValue($eventManager)); + + $eventManager->expects($this->once()) + ->method('trigger') + ->with(MvcEvent::EVENT_DISPATCH_ERROR); + + $routeMatch->setMatchedRouteName('adminRoute'); + $event->setRouteMatch($routeMatch); + $event->setApplication($application); + + $identityProvider = $this->getMock('ZfcRbac\Identity\IdentityProviderInterface'); + $identityProvider->expects($this->any()) + ->method('getIdentityRoles') + ->will($this->returnValue('member')); + + $roleProvider = new InMemoryRoleProvider(['member', 'guest']); + $roleService = new RoleService($identityProvider, $roleProvider, new RecursiveRoleIteratorStrategy()); + + $routeGuard = new RouteGuard($roleService, [ + 'adminRoute' => 'guest' + ]); + + $routeGuard->onResult($event); + + $this->assertTrue($event->propagationIsStopped()); + $this->assertEquals(RouteGuard::GUARD_UNAUTHORIZED, $event->getError()); + $this->assertInstanceOf('ZfcRbac\Exception\UnauthorizedException', $event->getParam('exception')); + } +} diff --git a/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Guard/RoutePermissionsGuardTest.php b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Guard/RoutePermissionsGuardTest.php new file mode 100644 index 00000000000..0de7740d04d --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Guard/RoutePermissionsGuardTest.php @@ -0,0 +1,424 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ +namespace ZfcRbacTest\Guard; + +use Zend\Mvc\MvcEvent; +use Zend\Mvc\Router\RouteMatch; +use ZfcRbac\Guard\ControllerGuard; +use ZfcRbac\Guard\GuardInterface; +use ZfcRbac\Guard\RouteGuard; +use ZfcRbac\Guard\RoutePermissionsGuard; + +/** + * @covers \ZfcRbac\Guard\AbstractGuard + * @covers \ZfcRbac\Guard\RoutePermissionsGuard + */ +class RoutePermissionsGuardTest extends \PHPUnit_Framework_TestCase +{ + public function testAttachToRightEvent() + { + $eventManager = $this->getMock('Zend\EventManager\EventManagerInterface'); + $eventManager->expects($this->once()) + ->method('attach') + ->with(RouteGuard::EVENT_NAME); + + $guard = new RoutePermissionsGuard($this->getMock('ZfcRbac\Service\AuthorizationService', [], [], '', false)); + $guard->attach($eventManager); + } + + /** + * We want to ensure an order for guards + */ + public function testAssertRoutePermissionsGuardPriority() + { + $this->assertLessThan(RouteGuard::EVENT_PRIORITY, RoutePermissionsGuard::EVENT_PRIORITY); + $this->assertGreaterThan(ControllerGuard::EVENT_PRIORITY, RoutePermissionsGuard::EVENT_PRIORITY); + } + + public function rulesConversionProvider() + { + return [ + // Simple string to array conversion + [ + 'rules' => [ + 'route' => 'permission1' + ], + 'expected' => [ + 'route' => ['permission1'] + ] + ], + // Array to array + [ + 'rules' => [ + 'route' => ['permission1', 'permission2'] + ], + 'expected' => [ + 'route' => ['permission1', 'permission2'] + ] + ], + // Traversable to array + [ + 'rules' => [ + 'route' => new \ArrayIterator(['permission1', 'permission2']) + ], + 'expected' => [ + 'route' => ['permission1', 'permission2'] + ] + ], + // Block a route for everyone + [ + 'rules' => [ + 'route' + ], + 'expected' => [ + 'route' => [] + ] + ], + ]; + } + + /** + * @dataProvider rulesConversionProvider + */ + public function testRulesConversions(array $rules, array $expected) + { + $roleService = $this->getMock('ZfcRbac\Service\AuthorizationService', [], [], '', false); + $routeGuard = new RoutePermissionsGuard($roleService, $rules); + $reflProperty = new \ReflectionProperty($routeGuard, 'rules'); + $reflProperty->setAccessible(true); + $this->assertEquals($expected, $reflProperty->getValue($routeGuard)); + } + + public function routeDataProvider() + { + return [ + // Assert basic one-to-one mapping with both policies + [ + 'rules' => ['adminRoute' => 'post.edit'], + 'matchedRouteName' => 'adminRoute', + 'identityPermissions' => [['post.edit', null, true]], + 'isGranted' => true, + 'policy' => GuardInterface::POLICY_ALLOW + ], + [ + 'rules' => ['adminRoute' => 'post.edit'], + 'matchedRouteName' => 'adminRoute', + 'identityPermissions' => [['post.edit', null, true]], + 'isGranted' => true, + 'policy' => GuardInterface::POLICY_DENY + ], + // Assert that policy changes result for non-specified route guards + [ + 'rules' => ['route' => 'post.edit'], + 'matchedRouteName' => 'anotherRoute', + 'identityPermissions' => [['post.edit', null, true]], + 'isGranted' => true, + 'policy' => GuardInterface::POLICY_ALLOW + ], + [ + 'rules' => ['route' => 'post.edit'], + 'matchedRouteName' => 'anotherRoute', + 'identityPermissions' => [['post.edit', null, true]], + 'isGranted' => false, + 'policy' => GuardInterface::POLICY_DENY + ], + // Assert that composed route work for both policies + [ + 'rules' => ['admin/dashboard' => 'post.edit'], + 'matchedRouteName' => 'admin/dashboard', + 'identityPermissions' => [['post.edit', null, true]], + 'isGranted' => true, + 'policy' => GuardInterface::POLICY_ALLOW + ], + [ + 'rules' => ['admin/dashboard' => 'post.edit'], + 'matchedRouteName' => 'admin/dashboard', + 'identityPermissions' => [['post.edit', null, true]], + 'isGranted' => true, + 'policy' => GuardInterface::POLICY_DENY + ], + // Assert that wildcard route work for both policies + [ + 'rules' => ['admin/*' => 'post.edit'], + 'matchedRouteName' => 'admin/dashboard', + 'identityPermissions' => [['post.edit', null, true]], + 'isGranted' => true, + 'policy' => GuardInterface::POLICY_ALLOW + ], + [ + 'rules' => ['admin/*' => 'post.edit'], + 'matchedRouteName' => 'admin/dashboard', + 'identityPermissions' => [['post.edit', null, true]], + 'isGranted' => true, + 'policy' => GuardInterface::POLICY_DENY + ], + // Assert that wildcard route does match (or not depending on the policy) if rules is after matched route name + [ + 'rules' => ['fooBar/*' => 'post.edit'], + 'matchedRouteName' => 'admin/fooBar/baz', + 'identityPermissions' => [['post.edit', null, true]], + 'isGranted' => true, + 'policy' => GuardInterface::POLICY_ALLOW + ], + [ + 'rules' => ['fooBar/*' => 'post.edit'], + 'matchedRouteName' => 'admin/fooBar/baz', + 'identityPermissions' => [['post.edit', null, true]], + 'isGranted' => false, + 'policy' => GuardInterface::POLICY_DENY + ], + // Assert that it can grant access with multiple rules + [ + 'rules' => [ + 'route1' => 'post.edit', + 'route2' => 'post.edit' + ], + 'matchedRouteName' => 'route1', + 'identityPermissions' => [['post.edit', null, true]], + 'isGranted' => true, + 'policy' => GuardInterface::POLICY_ALLOW + ], + [ + 'rules' => [ + 'route1' => 'post.edit', + 'route2' => 'post.edit' + ], + 'matchedRouteName' => 'route2', + 'identityPermissions' => [['post.edit', null, true]], + 'isGranted' => true, + 'policy' => GuardInterface::POLICY_ALLOW + ], + [ + 'rules' => [ + 'route1' => 'post.edit', + 'route2' => 'post.edit' + ], + 'matchedRouteName' => 'route1', + 'identityPermissions' => [['post.edit', null, true]], + 'isGranted' => true, + 'policy' => GuardInterface::POLICY_DENY + ], + [ + 'rules' => [ + 'route1' => 'post.edit', + 'route2' => 'post.edit' + ], + 'matchedRouteName' => 'route2', + 'identityPermissions' => [['post.edit', null, true]], + 'isGranted' => true, + 'policy' => GuardInterface::POLICY_DENY + ], + // Assert that it can grant/deny access with multiple rules based on the policy + [ + 'rules' => [ + 'route1' => 'post.edit', + 'route2' => 'post.edit' + ], + 'matchedRouteName' => 'route3', + 'identityPermissions' => [['post.edit', null, true]], + 'isGranted' => true, + 'policy' => GuardInterface::POLICY_ALLOW + ], + [ + 'rules' => [ + 'route1' => 'post.edit', + 'route2' => 'post.edit' + ], + 'matchedRouteName' => 'route3', + 'identityPermissions' => [['post.edit', null, true]], + 'isGranted' => false, + 'policy' => GuardInterface::POLICY_DENY + ], + // Assert it can deny access if the only permission does not have access + [ + 'rules' => ['route' => 'post.edit'], + 'matchedRouteName' => 'route', + 'identityPermissions' => [ + ['post.edit', null, false], + ['post.read', null, true] + ], + 'isGranted' => false, + 'policy' => GuardInterface::POLICY_ALLOW + ], + [ + 'rules' => ['route' => 'post.edit'], + 'matchedRouteName' => 'route', + 'identityPermissions' => [ + ['post.edit', null, false], + ['post.read', null, true] + ], + 'isGranted' => false, + 'policy' => GuardInterface::POLICY_DENY + ], + // Assert it can deny access if one of the permission does not have access + [ + 'rules' => ['route' => ['post.edit', 'post.read']], + 'matchedRouteName' => 'route', + 'identityPermissions' => [ + ['post.edit', null, true], + ['post.read', null, true] + ], + 'isGranted' => true, + 'policy' => GuardInterface::POLICY_ALLOW + ], + [ + 'rules' => ['route' => ['post.edit', 'post.read']], + 'matchedRouteName' => 'route', + 'identityPermissions' => [ + ['post.edit', null, true], + ['post.read', null, false] + ], + 'isGranted' => false, + 'policy' => GuardInterface::POLICY_ALLOW + ], + [ + 'rules' => ['route' => ['post.edit', 'post.read']], + 'matchedRouteName' => 'route', + 'identityPermissions' => [ + ['post.edit', null, false], + ['post.read', null, true] + ], + 'isGranted' => false, + 'policy' => GuardInterface::POLICY_ALLOW + ], + // Assert wildcard in permission + [ + 'rules' => ['home' => '*'], + 'matchedRouteName' => 'home', + 'identityPermissions' => [['post.edit', null, true]], + 'isGranted' => true, + 'policy' => GuardInterface::POLICY_ALLOW + ], + [ + 'rules' => ['home' => '*'], + 'matchedRouteName' => 'home', + 'identityPermissions' => [['post.edit', null, true]], + 'isGranted' => true, + 'policy' => GuardInterface::POLICY_DENY + ], + // Assert wildcard wins all + [ + 'rules' => ['home' => ['*', 'post.edit']], + 'matchedRouteName' => 'home', + 'identityPermissions' => [['post.edit', null, false]], + 'isGranted' => true, + 'policy' => GuardInterface::POLICY_ALLOW + ], + [ + 'rules' => ['home' => ['*', 'post.edit']], + 'matchedRouteName' => 'home', + 'identityPermissions' => [['post.edit', null, false]], + 'isGranted' => true, + 'policy' => GuardInterface::POLICY_DENY + ], + ]; + } + + /** + * @dataProvider routeDataProvider + */ + public function testRoutePermissionGranted( + array $rules, + $matchedRouteName, + array $identityPermissions, + $isGranted, + $protectionPolicy + ) { + $routeMatch = new RouteMatch([]); + $routeMatch->setMatchedRouteName($matchedRouteName); + + $event = new MvcEvent(); + $event->setRouteMatch($routeMatch); + + $authorizationService = $this->getMock('ZfcRbac\Service\AuthorizationServiceInterface', [], [], '', false); + $authorizationService->expects($this->any()) + ->method('isGranted') + ->will($this->returnValueMap($identityPermissions)); + + $routeGuard = new RoutePermissionsGuard($authorizationService, $rules); + $routeGuard->setProtectionPolicy($protectionPolicy); + + $this->assertEquals($isGranted, $routeGuard->isGranted($event)); + } + + public function testProperlyFillEventOnAuthorization() + { + $eventManager = $this->getMock('Zend\EventManager\EventManagerInterface'); + + $application = $this->getMock('Zend\Mvc\Application', [], [], '', false); + $application->expects($this->never()) + ->method('getEventManager') + ->will($this->returnValue($eventManager)); + + $routeMatch = new RouteMatch([]); + $routeMatch->setMatchedRouteName('adminRoute'); + + $event = new MvcEvent(); + $event->setRouteMatch($routeMatch); + $event->setApplication($application); + + $authorizationService = $this->getMock('ZfcRbac\Service\AuthorizationServiceInterface', [], [], '', false); + $authorizationService->expects($this->once()) + ->method('isGranted') + ->with('post.edit') + ->will($this->returnValue(true)); + + $routeGuard = new RoutePermissionsGuard($authorizationService, [ + 'adminRoute' => 'post.edit' + ]); + $routeGuard->onResult($event); + + $this->assertEmpty($event->getError()); + $this->assertNull($event->getParam('exception')); + } + + public function testProperlySetUnauthorizedAndTriggerEventOnUnauthorization() + { + $eventManager = $this->getMock('Zend\EventManager\EventManagerInterface'); + $eventManager->expects($this->once()) + ->method('trigger') + ->with(MvcEvent::EVENT_DISPATCH_ERROR); + + $application = $this->getMock('Zend\Mvc\Application', [], [], '', false); + $application->expects($this->once()) + ->method('getEventManager') + ->will($this->returnValue($eventManager)); + + $routeMatch = new RouteMatch([]); + $routeMatch->setMatchedRouteName('adminRoute'); + + $event = new MvcEvent(); + $event->setRouteMatch($routeMatch); + $event->setApplication($application); + + $authorizationService = $this->getMock('ZfcRbac\Service\AuthorizationServiceInterface', [], [], '', false); + $authorizationService->expects($this->once()) + ->method('isGranted') + ->with('post.edit') + ->will($this->returnValue(false)); + + $routeGuard = new RoutePermissionsGuard($authorizationService, [ + 'adminRoute' => 'post.edit' + ]); + $routeGuard->onResult($event); + + $this->assertTrue($event->propagationIsStopped()); + $this->assertEquals(RouteGuard::GUARD_UNAUTHORIZED, $event->getError()); + $this->assertInstanceOf('ZfcRbac\Exception\UnauthorizedException', $event->getParam('exception')); + } +} diff --git a/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Identity/AuthenticationIdentityProviderTest.php b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Identity/AuthenticationIdentityProviderTest.php new file mode 100644 index 00000000000..fcca90c7ba4 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Identity/AuthenticationIdentityProviderTest.php @@ -0,0 +1,54 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbacTest\Identity; + +use ZfcRbac\Identity\AuthenticationIdentityProvider; + +/** + * @covers \ZfcRbac\Identity\AuthenticationIdentityProvider + */ +class AuthenticationIdentityProviderTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var AuthenticationIdentityProvider + */ + protected $identityProvider; + + /** + * @var \Zend\Authentication\AuthenticationService|\PHPUnit_Framework_MockObject_MockObject + */ + protected $authenticationService; + + public function setUp() + { + $this->authenticationService = $this->getMock('Zend\Authentication\AuthenticationService'); + $this->identityProvider = new AuthenticationIdentityProvider($this->authenticationService); + } + + public function testCanReturnIdentity() + { + $identity = $this->getMock('ZfcRbac\Identity\IdentityInterface'); + + $this->authenticationService->expects($this->once()) + ->method('getIdentity') + ->will($this->returnValue($identity)); + + $this->assertSame($identity, $this->identityProvider->getIdentity()); + } +} diff --git a/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Initializer/AuthorizationAwareFake.php b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Initializer/AuthorizationAwareFake.php new file mode 100644 index 00000000000..59757a47e1e --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Initializer/AuthorizationAwareFake.php @@ -0,0 +1,32 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ +namespace ZfcRbacTest\Initializer; + +use ZfcRbac\Service\AuthorizationServiceAwareInterface; + +/** + * A fake implementation for AuthorizationServiceAwareInterface + * + * @author Aeneas Rekkas + * @license MIT License + */ +class AuthorizationAwareFake implements AuthorizationServiceAwareInterface +{ + + use \ZfcRbac\Service\AuthorizationServiceAwareTrait; +} diff --git a/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Initializer/AuthorizationServiceInitializerTest.php b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Initializer/AuthorizationServiceInitializerTest.php new file mode 100644 index 00000000000..0cb1b3bc006 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Initializer/AuthorizationServiceInitializerTest.php @@ -0,0 +1,46 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ +namespace ZfcRbacTest\Initializer; + +use ZfcRbac\Initializer\AuthorizationServiceInitializer; + +/** + * @covers \ZfcRbac\Initializer\AuthorizationServiceInitializer + * @author Aeneas Rekkas + * @license MIT License + */ +class AuthorizationServiceInitializerTest extends \PHPUnit_Framework_TestCase +{ + public function testInitializer() + { + $authServiceClassName = 'ZfcRbac\Service\AuthorizationService'; + $initializer = new AuthorizationServiceInitializer(); + $instance = new AuthorizationAwareFake(); + $serviceLocator = $this->getMock('Zend\ServiceManager\ServiceLocatorInterface'); + $authorizationService = $this->getMock('ZfcRbac\Service\AuthorizationService', [], [], '', false); + + $serviceLocator->expects($this->once()) + ->method('get') + ->with($authServiceClassName) + ->will($this->returnValue($authorizationService)); + + $initializer->initialize($instance, $serviceLocator); + + $this->assertEquals($authorizationService, $instance->getAuthorizationService()); + } +} diff --git a/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/ModuleTest.php b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/ModuleTest.php new file mode 100644 index 00000000000..92b0d2aab91 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/ModuleTest.php @@ -0,0 +1,57 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbacTest; + +use ZfcRbac\Module; + +/** + * @covers \ZfcRbac\Module + */ +class ModuleTest extends \PHPUnit_Framework_TestCase +{ + public function testConfigIsArray() + { + $module = new Module(); + $this->assertInternalType('array', $module->getConfig()); + } + + public function testCanRegisterGuards() + { + $module = new Module(); + $mvcEvent = $this->getMock('Zend\Mvc\MvcEvent'); + $application = $this->getMock('Zend\Mvc\Application', [], [], '', false); + $eventManager = $this->getMock('Zend\EventManager\EventManagerInterface'); + $serviceManager = $this->getMock('Zend\ServiceManager\ServiceManager'); + + $mvcEvent->expects($this->once())->method('getTarget')->will($this->returnValue($application)); + $application->expects($this->once())->method('getEventManager')->will($this->returnValue($eventManager)); + $application->expects($this->once())->method('getServiceManager')->will($this->returnValue($serviceManager)); + + $guards = [ + $this->getMock('ZfcRbac\Guard\GuardInterface') + ]; + + $serviceManager->expects($this->once()) + ->method('get') + ->with('ZfcRbac\Guards') + ->will($this->returnValue($guards)); + + $module->onBootstrap($mvcEvent); + } +} diff --git a/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Mvc/Controller/Plugin/IsGrantedTest.php b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Mvc/Controller/Plugin/IsGrantedTest.php new file mode 100644 index 00000000000..6ccc8db0a25 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Mvc/Controller/Plugin/IsGrantedTest.php @@ -0,0 +1,41 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbacTest\Mvc\Controller\Plugin; + +use ZfcRbac\Mvc\Controller\Plugin\IsGranted; + +/** + * @covers \ZfcRbac\Mvc\Controller\Plugin\IsGranted + */ +class IsGrantedTest extends \PHPUnit_Framework_TestCase +{ + public function testCallAuthorizationService() + { + $authorizationService = $this->getMock('ZfcRbac\Service\AuthorizationServiceInterface'); + + $authorizationService->expects($this->once()) + ->method('isGranted') + ->with('edit') + ->will($this->returnValue(true)); + + $helper = new IsGranted($authorizationService); + + $this->assertTrue($helper('edit')); + } +} diff --git a/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Options/ModuleOptionsTest.php b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Options/ModuleOptionsTest.php new file mode 100644 index 00000000000..85d39d7ffc7 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Options/ModuleOptionsTest.php @@ -0,0 +1,89 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbacTest; + +use ZfcRbac\Options\ModuleOptions; +use ZfcRbacTest\Util\ServiceManagerFactory; + +/** + * @covers \ZfcRbac\Options\ModuleOptions + */ +class ModuleOptionsTest extends \PHPUnit_Framework_TestCase +{ + public function testAssertModuleDefaultOptions() + { + /** @var \ZfcRbac\Options\ModuleOptions $moduleOptions */ + $moduleOptions = ServiceManagerFactory::getServiceManager()->get('ZfcRbac\Options\ModuleOptions'); + + $this->assertEquals('ZfcRbac\Identity\AuthenticationIdentityProvider', $moduleOptions->getIdentityProvider()); + $this->assertEquals('guest', $moduleOptions->getGuestRole()); + $this->assertEquals('allow', $moduleOptions->getProtectionPolicy()); + $this->assertInternalType('array', $moduleOptions->getGuards()); + $this->assertInternalType('array', $moduleOptions->getRoleProvider()); + $this->assertInternalType('array', $moduleOptions->getAssertionMap()); + $this->assertInstanceOf('ZfcRbac\Options\UnauthorizedStrategyOptions', $moduleOptions->getUnauthorizedStrategy()); + $this->assertInstanceOf('ZfcRbac\Options\RedirectStrategyOptions', $moduleOptions->getRedirectStrategy()); + } + + public function testSettersAndGetters() + { + $moduleOptions = new ModuleOptions([ + 'identity_provider' => 'IdentityProvider', + 'guest_role' => 'unknown', + 'guards' => [], + 'protection_policy' => 'deny', + 'role_provider' => [], + 'assertion_map' => [ + 'foo' => 'bar' + ], + 'unauthorized_strategy' => [ + 'template' => 'error/unauthorized' + ], + 'redirect_strategy' => [ + 'redirect_to_route_connected' => 'home', + 'redirect_to_route_disconnected' => 'login' + ] + ]); + + $this->assertEquals('IdentityProvider', $moduleOptions->getIdentityProvider()); + $this->assertEquals('unknown', $moduleOptions->getGuestRole()); + $this->assertEquals([], $moduleOptions->getGuards()); + $this->assertEquals('deny', $moduleOptions->getProtectionPolicy()); + $this->assertEquals([], $moduleOptions->getRoleProvider()); + $this->assertEquals(['foo' => 'bar'], $moduleOptions->getAssertionMap()); + $this->assertInstanceOf('ZfcRbac\Options\UnauthorizedStrategyOptions', $moduleOptions->getUnauthorizedStrategy()); + $this->assertInstanceOf('ZfcRbac\Options\RedirectStrategyOptions', $moduleOptions->getRedirectStrategy()); + } + + public function testThrowExceptionForInvalidProtectionPolicy() + { + $this->setExpectedException('ZfcRbac\Exception\RuntimeException'); + + $moduleOptions = new ModuleOptions(); + $moduleOptions->setProtectionPolicy('invalid'); + } + + public function testThrowExceptionIfMoreThanOneRoleProviderIsSet() + { + $this->setExpectedException('ZfcRbac\Exception\RuntimeException'); + + $moduleOptions = new ModuleOptions(); + $moduleOptions->setRoleProvider(['foo', 'bar']); + } +} diff --git a/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Options/RedirectStrategyOptionsTest.php b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Options/RedirectStrategyOptionsTest.php new file mode 100644 index 00000000000..f9f40b6a58d --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Options/RedirectStrategyOptionsTest.php @@ -0,0 +1,55 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbacTest; + +use ZfcRbac\Options\RedirectStrategyOptions; + +/** + * @covers \ZfcRbac\Options\RedirectStrategyOptions + */ +class RedirectStrategyOptionsTest extends \PHPUnit_Framework_TestCase +{ + public function testAssertDefaultValues() + { + $redirectStrategyOptions = new RedirectStrategyOptions(); + + $this->assertTrue($redirectStrategyOptions->getRedirectWhenConnected()); + $this->assertEquals('login', $redirectStrategyOptions->getRedirectToRouteDisconnected()); + $this->assertEquals('home', $redirectStrategyOptions->getRedirectToRouteConnected()); + $this->assertTrue($redirectStrategyOptions->getAppendPreviousUri()); + $this->assertEquals('redirectTo', $redirectStrategyOptions->getPreviousUriQueryKey()); + } + + public function testSettersAndGetters() + { + $redirectStrategyOptions = new RedirectStrategyOptions([ + 'redirect_when_connected' => false, + 'redirect_to_route_connected' => 'foo', + 'redirect_to_route_disconnected' => 'bar', + 'append_previous_uri' => false, + 'previous_uri_query_key' => 'redirect-to' + ]); + + $this->assertFalse($redirectStrategyOptions->getRedirectWhenConnected()); + $this->assertEquals('foo', $redirectStrategyOptions->getRedirectToRouteConnected()); + $this->assertEquals('bar', $redirectStrategyOptions->getRedirectToRouteDisconnected()); + $this->assertFalse($redirectStrategyOptions->getAppendPreviousUri()); + $this->assertEquals('redirect-to', $redirectStrategyOptions->getPreviousUriQueryKey()); + } +} diff --git a/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Options/UnauthorizedStrategyOptionsTest.php b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Options/UnauthorizedStrategyOptionsTest.php new file mode 100644 index 00000000000..6437b71e4c5 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Options/UnauthorizedStrategyOptionsTest.php @@ -0,0 +1,43 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbacTest; + +use ZfcRbac\Options\UnauthorizedStrategyOptions; + +/** + * @covers \ZfcRbac\Options\UnauthorizedStrategyOptions + */ +class UnauthorizedStrategyOptionsTest extends \PHPUnit_Framework_TestCase +{ + public function testAssertDefaultValues() + { + $unauthorizedStrategyOptions = new UnauthorizedStrategyOptions(); + + $this->assertEquals('error/403', $unauthorizedStrategyOptions->getTemplate()); + } + + public function testSettersAndGetters() + { + $unauthorizedStrategyOptions = new UnauthorizedStrategyOptions([ + 'template' => 'error/unauthorized' + ]); + + $this->assertEquals('error/unauthorized', $unauthorizedStrategyOptions->getTemplate()); + } +} diff --git a/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Role/InMemoryRoleProviderTest.php b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Role/InMemoryRoleProviderTest.php new file mode 100644 index 00000000000..d626448f826 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Role/InMemoryRoleProviderTest.php @@ -0,0 +1,67 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbacTest\Role; + +use ZfcRbac\Role\InMemoryRoleProvider; + +/** + * @covers \ZfcRbac\Role\InMemoryRoleProvider + */ +class InMemoryRoleProviderTest extends \PHPUnit_Framework_TestCase +{ + public function testInMemoryProvider() + { + $inMemoryProvider = new InMemoryRoleProvider([ + 'admin' => [ + 'children' => ['member'], + 'permissions' => ['delete'] + ], + 'member' => [ + 'children' => ['guest'], + 'permissions' => ['write'] + ], + 'guest' + ]); + + $roles = $inMemoryProvider->getRoles(['admin', 'member', 'guest']); + + $this->assertCount(3, $roles); + + // Test admin role + $adminRole = $roles[0]; + $this->assertInstanceOf('Rbac\Role\HierarchicalRoleInterface', $adminRole); + $this->assertEquals('admin', $adminRole->getName()); + $this->assertTrue($adminRole->hasPermission('delete')); + + // Test member role + $memberRole = $roles[1]; + $this->assertInstanceOf('Rbac\Role\HierarchicalRoleInterface', $memberRole); + $this->assertEquals('member', $memberRole->getName()); + $this->assertTrue($memberRole->hasPermission('write')); + $this->assertFalse($memberRole->hasPermission('delete')); + + // Test guest role + $guestRole = $roles[2]; + $this->assertInstanceOf('Rbac\Role\RoleInterface', $guestRole); + $this->assertNotInstanceOf('Rbac\Role\HierarchicalRoleInterface', $guestRole); + $this->assertEquals('guest', $guestRole->getName()); + $this->assertFalse($guestRole->hasPermission('write')); + $this->assertFalse($guestRole->hasPermission('delete')); + } +} diff --git a/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Role/ObjectRepositoryRoleProviderTest.php b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Role/ObjectRepositoryRoleProviderTest.php new file mode 100644 index 00000000000..92bf5a6954e --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Role/ObjectRepositoryRoleProviderTest.php @@ -0,0 +1,170 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbacTest\Role; + +use Doctrine\ORM\Tools\SchemaTool; +use Rbac\Traversal\RecursiveRoleIterator; +use Zend\ServiceManager\ServiceManager; +use ZfcRbac\Role\ObjectRepositoryRoleProvider; +use ZfcRbacTest\Asset\FlatRole; +use ZfcRbacTest\Asset\HierarchicalRole; +use ZfcRbacTest\Util\ServiceManagerFactory; + +/** + * @covers \ZfcRbac\Role\ObjectRepositoryRoleProvider + */ +class ObjectRepositoryRoleProviderTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var ServiceManager + */ + protected $serviceManager; + + public function testObjectRepositoryProviderForFlatRole() + { + $this->serviceManager = ServiceManagerFactory::getServiceManager(); + $objectManager = $this->getObjectManager(); + + // Let's add some roles + $adminRole = new FlatRole('admin'); + $objectManager->persist($adminRole); + + $memberRole = new FlatRole('member'); + $objectManager->persist($memberRole); + + $objectManager->flush(); + + $objectRepository = $objectManager->getRepository('ZfcRbacTest\Asset\FlatRole'); + + $objectRepositoryRoleProvider = new ObjectRepositoryRoleProvider($objectRepository, 'name'); + + // Get only the admin role + $roles = $objectRepositoryRoleProvider->getRoles(['admin']); + + $this->assertCount(1, $roles); + $this->assertInternalType('array', $roles); + + $this->assertInstanceOf('Rbac\Role\RoleInterface', $roles[0]); + $this->assertEquals('admin', $roles[0]->getName()); + } + + public function testObjectRepositoryProviderForHierarchicalRole() + { + $this->serviceManager = ServiceManagerFactory::getServiceManager(); + $objectManager = $this->getObjectManager(); + + // Let's add some roles + $guestRole = new HierarchicalRole('guest'); + $objectManager->persist($guestRole); + + $memberRole = new HierarchicalRole('member'); + $memberRole->addChild($guestRole); + $objectManager->persist($memberRole); + + $adminRole = new HierarchicalRole('admin'); + $adminRole->addChild($memberRole); + $objectManager->persist($adminRole); + + $objectManager->flush(); + + $objectRepository = $objectManager->getRepository('ZfcRbacTest\Asset\HierarchicalRole'); + + $objectRepositoryRoleProvider = new ObjectRepositoryRoleProvider($objectRepository, 'name'); + + // Get only the admin role + $roles = $objectRepositoryRoleProvider->getRoles(['admin']); + + $this->assertCount(1, $roles); + $this->assertInternalType('array', $roles); + + $this->assertInstanceOf('Rbac\Role\HierarchicalRoleInterface', $roles[0]); + $this->assertEquals('admin', $roles[0]->getName()); + + $iteratorIterator = new \RecursiveIteratorIterator( + new RecursiveRoleIterator($roles[0]->getChildren()), + \RecursiveIteratorIterator::SELF_FIRST + ); + + $childRolesString = ''; + + foreach ($iteratorIterator as $childRole) { + $this->assertInstanceOf('Rbac\Role\HierarchicalRoleInterface', $childRole); + $childRolesString .= $childRole->getName(); + } + + $this->assertEquals('memberguest', $childRolesString); + } + + public function testRoleCacheOnConsecutiveCalls() + { + $objectRepository = $this->getMock('Doctrine\ORM\EntityRepository', ['findBy'], [], '', false); + $memberRole = new FlatRole('member'); + $provider = new ObjectRepositoryRoleProvider($objectRepository, 'name'); + $result = [$memberRole]; + + $objectRepository->expects($this->once())->method('findBy')->will($this->returnValue($result)); + + $this->assertEquals($result, $provider->getRoles(['member'])); + $this->assertEquals($result, $provider->getRoles(['member'])); + } + + public function testClearRoleCache() + { + $objectRepository = $this->getMock('Doctrine\ORM\EntityRepository', ['findBy'], [], '', false); + $memberRole = new FlatRole('member'); + $provider = new ObjectRepositoryRoleProvider($objectRepository, 'name'); + $result = [$memberRole]; + + $objectRepository->expects($this->exactly(2))->method('findBy')->will($this->returnValue($result)); + + $this->assertEquals($result, $provider->getRoles(['member'])); + $provider->clearRoleCache(); + $this->assertEquals($result, $provider->getRoles(['member'])); + } + + public function testThrowExceptionIfAskedRoleIsNotFound() + { + $this->serviceManager = ServiceManagerFactory::getServiceManager(); + + $objectManager = $this->getObjectManager(); + $objectRepository = $objectManager->getRepository('ZfcRbacTest\Asset\FlatRole'); + $objectRepositoryRoleProvider = new ObjectRepositoryRoleProvider($objectRepository, 'name'); + + $this->setExpectedException( + 'ZfcRbac\Exception\RoleNotFoundException', + 'Some roles were asked but could not be loaded from database: guest, admin' + ); + + $objectRepositoryRoleProvider->getRoles(['guest', 'admin']); + } + + /** + * @return \Doctrine\Common\Persistence\ObjectManager + */ + private function getObjectManager() + { + /* @var $entityManager \Doctrine\ORM\EntityManager */ + $entityManager = $this->serviceManager->get('Doctrine\\ORM\\EntityManager'); + $schemaTool = new SchemaTool($entityManager); + $schemaTool->dropDatabase(); + $schemaTool->createSchema($entityManager->getMetadataFactory()->getAllMetadata()); + + return $entityManager; + } +} diff --git a/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Role/RoleProviderPluginManagerTest.php b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Role/RoleProviderPluginManagerTest.php new file mode 100644 index 00000000000..8667acb01bb --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Role/RoleProviderPluginManagerTest.php @@ -0,0 +1,44 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbacTest\Role; + +use ZfcRbac\Role\RoleProviderPluginManager; + +/** + * @covers \ZfcRbac\Role\RoleProviderPluginManager + */ +class RoleProviderPluginManagerTest extends \PHPUnit_Framework_TestCase +{ + public function testValidationOfPluginSucceedsIfRoleProviderInterfaceIsImplemented() + { + $pluginMock = $this->getMock('ZfcRbac\Role\RoleProviderInterface'); + $pluginManager = new RoleProviderPluginManager(); + + $this->assertNull($pluginManager->validatePlugin($pluginMock)); + } + + public function testValidationOfPluginFailsIfRoleProviderInterfaceIsNotImplemented() + { + $this->setExpectedException('ZfcRbac\Exception\RuntimeException'); + + $pluginManager = new RoleProviderPluginManager(); + $pluginManager->get('stdClass', []); + } +} + \ No newline at end of file diff --git a/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Service/AuthorizationServiceAwareTraitTest.php b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Service/AuthorizationServiceAwareTraitTest.php new file mode 100644 index 00000000000..a4a15ad731c --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Service/AuthorizationServiceAwareTraitTest.php @@ -0,0 +1,36 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ +namespace ZfcRbacTest\Service; + +/** + * @covers \ZfcRbac\Service\AuthorizationServiceAwareTrait + * @author Aeneas Rekkas + * @license MIT License + */ +class AuthorizationServiceAwareTraitTest extends \PHPUnit_Framework_TestCase +{ + public function testTrait() + { + $trait = $this->getObjectForTrait('ZfcRbac\Service\AuthorizationServiceAwareTrait'); + $authorizationService = $this->getMock('ZfcRbac\Service\AuthorizationService', [], [], '', false); + + $trait->setAuthorizationService($authorizationService); + + $this->assertEquals($authorizationService, $trait->getAuthorizationService()); + } +} diff --git a/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Service/AuthorizationServiceTest.php b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Service/AuthorizationServiceTest.php new file mode 100644 index 00000000000..1685dc01a19 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Service/AuthorizationServiceTest.php @@ -0,0 +1,254 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbacTest\Service; + +use Rbac\Rbac; +use Rbac\Traversal\Strategy\RecursiveRoleIteratorStrategy; +use ZfcRbac\Role\InMemoryRoleProvider; +use ZfcRbac\Service\AuthorizationService; +use ZfcRbac\Service\RoleService; +use ZfcRbacTest\Asset\SimpleAssertion; +use ZfcRbac\Assertion\AssertionPluginManager; +use Zend\ServiceManager\Config; + +/** + * @covers \ZfcRbac\Service\AuthorizationService + */ +class AuthorizationServiceTest extends \PHPUnit_Framework_TestCase +{ + public function grantedProvider() + { + return [ + // Simple is granted + [ + 'guest', + 'read', + null, + true + ], + + // Simple is allowed from parent + [ + 'member', + 'read', + null, + true + ], + + // Simple is refused + [ + 'guest', + 'write', + null, + false + ], + + // Simple is refused from parent + [ + 'guest', + 'delete', + null, + false + ], + + // Simple is refused from assertion map + [ + 'admin', + 'delete', + false, + false, + [ + 'delete' => 'ZfcRbacTest\Asset\SimpleAssertion' + ] + ], + + // Simple is accepted from assertion map + [ + 'admin', + 'delete', + true, + true, + [ + 'delete' => 'ZfcRbacTest\Asset\SimpleAssertion' + ] + ], + + // Simple is refused from no role + [ + [], + 'read', + null, + false + ], + ]; + } + + /** + * @dataProvider grantedProvider + */ + public function testGranted($role, $permission, $context, $isGranted, $assertions = array()) + { + $roleConfig = [ + 'admin' => [ + 'children' => ['member'], + 'permissions' => ['delete'] + ], + 'member' => [ + 'children' => ['guest'], + 'permissions' => ['write'] + ], + 'guest' => [ + 'permissions' => ['read'] + ] + ]; + + $assertionPluginConfig = [ + 'invokables' => [ + 'ZfcRbacTest\Asset\SimpleAssertion' => 'ZfcRbacTest\Asset\SimpleAssertion' + ] + ]; + + $identity = $this->getMock('ZfcRbac\Identity\IdentityInterface'); + $identity->expects($this->once())->method('getRoles')->will($this->returnValue((array) $role)); + + $identityProvider = $this->getMock('ZfcRbac\Identity\IdentityProviderInterface'); + $identityProvider->expects($this->any()) + ->method('getIdentity') + ->will($this->returnValue($identity)); + + $rbac = new Rbac(new RecursiveRoleIteratorStrategy()); + $roleService = new RoleService( + $identityProvider, + new InMemoryRoleProvider($roleConfig), + $rbac->getTraversalStrategy() + ); + $assertionPluginManager = new AssertionPluginManager(new Config($assertionPluginConfig)); + $authorizationService = new AuthorizationService($rbac, $roleService, $assertionPluginManager); + + $authorizationService->setAssertions($assertions); + + $this->assertEquals($isGranted, $authorizationService->isGranted($permission, $context)); + } + + public function testDoNotCallAssertionIfThePermissionIsNotGranted() + { + $role = $this->getMock('Rbac\Role\RoleInterface'); + $rbac = $this->getMock('Rbac\Rbac', [], [], '', false); + + $roleService = $this->getMock('ZfcRbac\Service\RoleService', [], [], '', false); + $roleService->expects($this->once())->method('getIdentityRoles')->will($this->returnValue([$role])); + + $assertionPluginManager = $this->getMock('ZfcRbac\Assertion\AssertionPluginManager', [], [], '', false); + $assertionPluginManager->expects($this->never())->method('get'); + + $authorizationService = new AuthorizationService($rbac, $roleService, $assertionPluginManager); + + $this->assertFalse($authorizationService->isGranted('foo')); + } + + public function testThrowExceptionForInvalidAssertion() + { + $role = $this->getMock('Rbac\Role\RoleInterface'); + $rbac = $this->getMock('Rbac\Rbac', [], [], '', false); + + $rbac->expects($this->once())->method('isGranted')->will($this->returnValue(true)); + + $roleService = $this->getMock('ZfcRbac\Service\RoleService', [], [], '', false); + $roleService->expects($this->once())->method('getIdentityRoles')->will($this->returnValue([$role])); + + $assertionPluginManager = $this->getMock('ZfcRbac\Assertion\AssertionPluginManager', [], [], '', false); + $authorizationService = new AuthorizationService($rbac, $roleService, $assertionPluginManager); + + $this->setExpectedException('ZfcRbac\Exception\InvalidArgumentException'); + + $authorizationService->setAssertion('foo', new \stdClass()); + $authorizationService->isGranted('foo'); + } + + public function testDynamicAssertions() + { + $role = $this->getMock('Rbac\Role\RoleInterface'); + $rbac = $this->getMock('Rbac\Rbac', [], [], '', false); + + $rbac->expects($this->exactly(2))->method('isGranted')->will($this->returnValue(true)); + + $roleService = $this->getMock('ZfcRbac\Service\RoleService', [], [], '', false); + $roleService->expects($this->exactly(2))->method('getIdentityRoles')->will($this->returnValue([$role])); + + $assertionPluginManager = $this->getMock('ZfcRbac\Assertion\AssertionPluginManager', [], [], '', false); + $authorizationService = new AuthorizationService($rbac, $roleService, $assertionPluginManager); + + // Using a callable + $called = false; + + $authorizationService->setAssertion( + 'foo', + function (AuthorizationService $injectedService) use ($authorizationService, &$called) { + $this->assertSame($injectedService, $authorizationService); + + $called = true; + + return false; + } + ); + + $this->assertFalse($authorizationService->isGranted('foo')); + $this->assertTrue($called); + + // Using an assertion object + $assertion = new SimpleAssertion(); + $authorizationService->setAssertion('foo', $assertion); + + $this->assertFalse($authorizationService->isGranted('foo', false)); + $this->assertTrue($assertion->getCalled()); + } + + public function testAssertionMap() + { + $rbac = $this->getMock('Rbac\Rbac', [], [], '', false); + $roleService = $this->getMock('ZfcRbac\Service\RoleService', [], [], '', false); + $assertionPluginManager = $this->getMock('ZfcRbac\Assertion\AssertionPluginManager', [], [], '', false); + $authorizationService = new AuthorizationService($rbac, $roleService, $assertionPluginManager); + + $authorizationService->setAssertions(['foo' => 'bar', 'bar' => 'foo']); + + $this->assertTrue($authorizationService->hasAssertion('foo')); + $this->assertTrue($authorizationService->hasAssertion('bar')); + + $authorizationService->setAssertion('bar', null); + + $this->assertFalse($authorizationService->hasAssertion('bar')); + } + + /** + * @covers ZfcRbac\Service\AuthorizationService::getIdentity + */ + public function testGetIdentity() + { + $rbac = $this->getMock('Rbac\Rbac', [], [], '', false); + $identity = $this->getMock('ZfcRbac\Identity\IdentityInterface'); + $roleService = $this->getMock('ZfcRbac\Service\RoleService', [], [], '', false); + $assertionManager = $this->getMock('ZfcRbac\Assertion\AssertionPluginManager', [], [], '', false); + $authorization = new AuthorizationService($rbac, $roleService, $assertionManager); + + $roleService->expects($this->once())->method('getIdentity')->will($this->returnValue($identity)); + + $this->assertSame($authorization->getIdentity(), $identity); + } +} diff --git a/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Service/RoleServiceTest.php b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Service/RoleServiceTest.php new file mode 100644 index 00000000000..e9b35a38933 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Service/RoleServiceTest.php @@ -0,0 +1,241 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbacTest\Service; + +use ZfcRbac\Role\InMemoryRoleProvider; +use ZfcRbac\Service\RoleService; +use Rbac\Traversal\Strategy\RecursiveRoleIteratorStrategy; + +/** + * @covers \ZfcRbac\Service\RoleService + */ +class RoleServiceTest extends \PHPUnit_Framework_TestCase +{ + public function roleProvider() + { + return [ + // No identity role + [ + 'rolesConfig' => [], + 'identityRoles' => [], + 'rolesToCheck' => [ + 'member' + ], + 'doesMatch' => false + ], + + // Simple + [ + 'rolesConfig' => [ + 'member' => [ + 'children' => ['guest'] + ], + 'guest' + ], + 'identityRoles' => [ + 'guest' + ], + 'rolesToCheck' => [ + 'member' + ], + 'doesMatch' => false + ], + [ + 'rolesConfig' => [ + 'member' => [ + 'children' => ['guest'] + ], + 'guest' + ], + 'identityRoles' => [ + 'member' + ], + 'rolesToCheck' => [ + 'member' + ], + 'doesMatch' => true + ], + + // Complex role inheritance + [ + 'rolesConfig' => [ + 'admin' => [ + 'children' => ['moderator'] + ], + 'moderator' => [ + 'children' => ['member'] + ], + 'member' => [ + 'children' => ['guest'] + ], + 'guest' + ], + 'identityRoles' => [ + 'member', + 'moderator' + ], + 'rolesToCheck' => [ + 'admin' + ], + 'doesMatch' => false + ], + [ + 'rolesConfig' => [ + 'admin' => [ + 'children' => ['moderator'] + ], + 'moderator' => [ + 'children' => ['member'] + ], + 'member' => [ + 'children' => ['guest'] + ], + 'guest' + ], + 'identityRoles' => [ + 'member', + 'admin' + ], + 'rolesToCheck' => [ + 'moderator' + ], + 'doesMatch' => true + ], + + // Complex role inheritance and multiple check + [ + 'rolesConfig' => [ + 'sysadmin' => [ + 'children' => ['siteadmin', 'admin'] + ], + 'siteadmin', + 'admin' => [ + 'children' => ['moderator'] + ], + 'moderator' => [ + 'children' => ['member'] + ], + 'member' => [ + 'children' => ['guest'] + ], + 'guest' + ], + 'identityRoles' => [ + 'member', + 'moderator' + ], + 'rolesToCheck' => [ + 'admin', + 'sysadmin' + ], + 'doesMatch' => false + ], + [ + 'rolesConfig' => [ + 'sysadmin' => [ + 'children' => ['siteadmin', 'admin'] + ], + 'siteadmin', + 'admin' => [ + 'children' => ['moderator'] + ], + 'moderator' => [ + 'children' => ['member'] + ], + 'member' => [ + 'children' => ['guest'] + ], + 'guest' + ], + 'identityRoles' => [ + 'moderator', + 'admin' + ], + 'rolesToCheck' => [ + 'sysadmin', + 'siteadmin', + 'member' + ], + 'doesMatch' => true + ] + ]; + } + + /** + * @dataProvider roleProvider + */ + public function testMatchIdentityRoles(array $rolesConfig, array $identityRoles, array $rolesToCheck, $doesMatch) + { + $identity = $this->getMock('ZfcRbac\Identity\IdentityInterface'); + $identity->expects($this->once())->method('getRoles')->will($this->returnValue($identityRoles)); + + $identityProvider = $this->getMock('ZfcRbac\Identity\IdentityProviderInterface'); + $identityProvider->expects($this->any()) + ->method('getIdentity') + ->will($this->returnValue($identity)); + + $roleService = new RoleService($identityProvider, new InMemoryRoleProvider($rolesConfig), new RecursiveRoleIteratorStrategy()); + + $this->assertEquals($doesMatch, $roleService->matchIdentityRoles($rolesToCheck)); + } + + public function testReturnGuestRoleIfNoIdentityIsFound() + { + $identityProvider = $this->getMock('ZfcRbac\Identity\IdentityProviderInterface'); + $identityProvider->expects($this->any()) + ->method('getIdentity') + ->will($this->returnValue(null)); + + $roleService = new RoleService( + $identityProvider, + new InMemoryRoleProvider([]), + $this->getMock('Rbac\Traversal\Strategy\TraversalStrategyInterface') + ); + + $roleService->setGuestRole('guest'); + + $result = $roleService->getIdentityRoles(); + + $this->assertEquals('guest', $roleService->getGuestRole()); + $this->assertCount(1, $result); + $this->assertInstanceOf('Rbac\Role\RoleInterface', $result[0]); + $this->assertEquals('guest', $result[0]->getName()); + } + + public function testThrowExceptionIfIdentityIsWrongType() + { + $this->setExpectedException( + 'ZfcRbac\Exception\RuntimeException', + 'ZfcRbac expects your identity to implement ZfcRbac\Identity\IdentityInterface, "stdClass" given' + ); + + $identityProvider = $this->getMock('ZfcRbac\Identity\IdentityProviderInterface'); + $identityProvider->expects($this->any()) + ->method('getIdentity') + ->will($this->returnValue(new \stdClass())); + + $roleService = new RoleService( + $identityProvider, + $this->getMock('ZfcRbac\Role\RoleProviderInterface'), + $this->getMock('Rbac\Traversal\Strategy\TraversalStrategyInterface') + ); + + $roleService->getIdentityRoles(); + } +} diff --git a/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Util/ServiceManagerFactory.php b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Util/ServiceManagerFactory.php new file mode 100644 index 00000000000..964f19abaa1 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/Util/ServiceManagerFactory.php @@ -0,0 +1,76 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbacTest\Util; + +use Zend\Mvc\Service\ServiceManagerConfig; +use Zend\ServiceManager\ServiceManager; + +/** + * Base test case to be used when a new service manager instance is required + * + * @license MIT + * @author Marco Pivetta <ocramius@gmail.com> + */ +abstract class ServiceManagerFactory +{ + /** + * @var array + */ + private static $config = []; + + /** + * @static + * @param array $config + */ + public static function setApplicationConfig(array $config) + { + static::$config = $config; + } + + /** + * @static + * @return array + */ + public static function getApplicationConfig() + { + return static::$config; + } + + /** + * @param array|null $config + * @return ServiceManager + */ + public static function getServiceManager(array $config = null) + { + $config = $config ?: static::getApplicationConfig(); + $serviceManager = new ServiceManager( + new ServiceManagerConfig( + isset($config['service_manager']) ? $config['service_manager'] : [] + ) + ); + $serviceManager->setService('ApplicationConfig', $config); + + /* @var $moduleManager \Zend\ModuleManager\ModuleManagerInterface */ + $moduleManager = $serviceManager->get('ModuleManager'); + + $moduleManager->loadModules(); + + return $serviceManager; + } +} diff --git a/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/View/Helper/HasRoleTest.php b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/View/Helper/HasRoleTest.php new file mode 100644 index 00000000000..01dd63e5827 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/View/Helper/HasRoleTest.php @@ -0,0 +1,59 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbacTest\View\Helper; + +use ZfcRbac\View\Helper\HasRole; +use ZfcRbacTest\Util\ServiceManagerFactory; + +/** + * @covers \ZfcRbac\View\Helper\HasRole + */ +class HasRoleTest extends \PHPUnit_Framework_TestCase +{ + public function testHelperIsRegistered() + { + $serviceManager = ServiceManagerFactory::getServiceManager(); + $config = $serviceManager->get('Config'); + $this->assertArrayHasKey('view_helpers', $config); + $viewHelpersConfig = $config['view_helpers']; + $this->assertEquals('ZfcRbac\View\Helper\HasRole', $viewHelpersConfig['aliases']['hasRole']); + $this->assertEquals( + 'ZfcRbac\Factory\HasRoleViewHelperFactory', + $viewHelpersConfig['factories']['ZfcRbac\View\Helper\HasRole'] + ); + } + + public function testCallAuthorizationService() + { + $rolesConfig = [ + ['member', true], + [['member'], true], + ]; + + $authorizationService = $this->getMock('ZfcRbac\Service\RoleService', [], [], '', false); + $authorizationService->expects($this->any()) + ->method('matchIdentityRoles') + ->will($this->returnValueMap($rolesConfig)); + + $helper = new HasRole($authorizationService); + + $this->assertTrue($helper('member')); + $this->assertTrue($helper(['member'])); + } +} diff --git a/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/View/Helper/IsGrantedTest.php b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/View/Helper/IsGrantedTest.php new file mode 100644 index 00000000000..7f777eefc56 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/View/Helper/IsGrantedTest.php @@ -0,0 +1,55 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbacTest\View\Helper; + +use ZfcRbac\View\Helper\IsGranted; +use ZfcRbacTest\Util\ServiceManagerFactory; + +/** + * @covers \ZfcRbac\View\Helper\IsGranted + */ +class IsGrantedTest extends \PHPUnit_Framework_TestCase +{ + public function testHelperIsRegistered() + { + $serviceManager = ServiceManagerFactory::getServiceManager(); + $config = $serviceManager->get('Config'); + $this->assertArrayHasKey('view_helpers', $config); + $viewHelpersConfig = $config['view_helpers']; + $this->assertEquals('ZfcRbac\View\Helper\IsGranted', $viewHelpersConfig['aliases']['isGranted']); + $this->assertEquals( + 'ZfcRbac\Factory\IsGrantedViewHelperFactory', + $viewHelpersConfig['factories']['ZfcRbac\View\Helper\IsGranted'] + ); + } + + public function testCallAuthorizationService() + { + $authorizationService = $this->getMock('ZfcRbac\Service\AuthorizationServiceInterface'); + + $authorizationService->expects($this->once()) + ->method('isGranted') + ->with('edit') + ->will($this->returnValue(true)); + + $helper = new IsGranted($authorizationService); + + $this->assertTrue($helper('edit')); + } +} diff --git a/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/View/Strategy/RedirectStrategyTest.php b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/View/Strategy/RedirectStrategyTest.php new file mode 100644 index 00000000000..b80ec508e5c --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/View/Strategy/RedirectStrategyTest.php @@ -0,0 +1,197 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbacTest\View\Strategy; + +use Zend\Authentication\AuthenticationService; +use Zend\Http\Request as HttpRequest; +use Zend\Http\Response as HttpResponse; +use Zend\Mvc\MvcEvent; +use Zend\Mvc\Router\Http\TreeRouteStack; +use ZfcRbac\Exception\UnauthorizedException; +use ZfcRbac\Options\RedirectStrategyOptions; +use ZfcRbac\View\Strategy\RedirectStrategy; + +/** + * @covers \ZfcRbac\View\Strategy\RedirectStrategy + * @covers \ZfcRbac\View\Strategy\AbstractStrategy + */ +class RedirectStrategyTest extends \PHPUnit_Framework_TestCase +{ + public function testAttachToRightEvent() + { + $strategyListener = new RedirectStrategy(new RedirectStrategyOptions(), new AuthenticationService()); + + $eventManager = $this->getMock('Zend\EventManager\EventManagerInterface'); + $eventManager->expects($this->once()) + ->method('attach') + ->with(MvcEvent::EVENT_DISPATCH_ERROR); + + $strategyListener->attach($eventManager); + } + + public function testReturnNullIfNotRightException() + { + $redirectStrategy = new RedirectStrategy(new RedirectStrategyOptions(), new AuthenticationService()); + $event = new MvcEvent(); + $event->setParam('exception', new \RuntimeException()); + + $this->assertNull($redirectStrategy->onError($event)); + } + + public function testCanRedirectWhenDisconnected() + { + $response = new HttpResponse(); + + $router = new TreeRouteStack(); + $router->addRoute('login', [ + 'type' => 'Zend\Mvc\Router\Http\Literal', + 'options' => [ + 'route' => '/login' + ] + ]); + + $mvcEvent = new MvcEvent(); + $mvcEvent->setParam('exception', new UnauthorizedException()); + $mvcEvent->setResponse($response); + $mvcEvent->setRouter($router); + + $options = new RedirectStrategyOptions([ + 'redirect_to_route_disconnected' => 'login', + 'append_previous_uri' => false + ]); + + $authenticationService = $this->getMock('Zend\Authentication\AuthenticationService'); + $authenticationService->expects($this->once())->method('hasIdentity')->will($this->returnValue(false)); + + $redirectStrategy = new RedirectStrategy($options, $authenticationService); + + $redirectStrategy->onError($mvcEvent); + + $this->assertInstanceOf('Zend\Stdlib\ResponseInterface', $mvcEvent->getResult()); + $this->assertEquals(302, $mvcEvent->getResponse()->getStatusCode()); + $this->assertEquals('/login', $mvcEvent->getResponse()->getHeaders()->get('Location')->getFieldValue()); + } + + public function testCanRedirectWhenConnected() + { + $response = new HttpResponse(); + + $router = new TreeRouteStack(); + $router->addRoute('home', [ + 'type' => 'Zend\Mvc\Router\Http\Literal', + 'options' => [ + 'route' => '/home' + ] + ]); + + $mvcEvent = new MvcEvent(); + $mvcEvent->setParam('exception', new UnauthorizedException()); + $mvcEvent->setResponse($response); + $mvcEvent->setRouter($router); + + $options = new RedirectStrategyOptions([ + 'redirect_to_route_connected' => 'home', + 'append_previous_uri' => false + ]); + + $authenticationService = $this->getMock('Zend\Authentication\AuthenticationService'); + $authenticationService->expects($this->once())->method('hasIdentity')->will($this->returnValue(true)); + + $redirectStrategy = new RedirectStrategy($options, $authenticationService); + + $redirectStrategy->onError($mvcEvent); + + $this->assertInstanceOf('Zend\Stdlib\ResponseInterface', $mvcEvent->getResult()); + $this->assertEquals(302, $mvcEvent->getResponse()->getStatusCode()); + $this->assertEquals('/home', $mvcEvent->getResponse()->getHeaders()->get('Location')->getFieldValue()); + } + + public function testWontRedirectWhenConnectedAndOptionDisabled() + { + $response = new HttpResponse(); + + $router = new TreeRouteStack(); + $router->addRoute('home', [ + 'type' => 'Zend\Mvc\Router\Http\Literal', + 'options' => [ + 'route' => '/home' + ] + ]); + + $mvcEvent = new MvcEvent(); + $mvcEvent->setParam('exception', new UnauthorizedException()); + $mvcEvent->setResponse($response); + $mvcEvent->setRouter($router); + + $options = new RedirectStrategyOptions([ + 'redirect_when_connected' => false + ]); + + $authenticationService = $this->getMock('Zend\Authentication\AuthenticationService'); + $authenticationService->expects($this->once())->method('hasIdentity')->will($this->returnValue(true)); + + $redirectStrategy = new RedirectStrategy($options, $authenticationService); + + $redirectStrategy->onError($mvcEvent); + + $this->assertNotEquals(302, $mvcEvent->getResponse()->getStatusCode()); + } + + public function testCanAppendPreviousUri() + { + $response = new HttpResponse(); + + $request = new HttpRequest(); + $request->setUri('http://example.com'); + + $router = new TreeRouteStack(); + $router->addRoute('login', [ + 'type' => 'Zend\Mvc\Router\Http\Literal', + 'options' => [ + 'route' => '/login' + ] + ]); + + $mvcEvent = new MvcEvent(); + $mvcEvent->setParam('exception', new UnauthorizedException()); + $mvcEvent->setResponse($response); + $mvcEvent->setRequest($request); + $mvcEvent->setRouter($router); + + $options = new RedirectStrategyOptions([ + 'redirect_to_route_disconnected' => 'login', + 'append_previous_uri' => true, + 'previous_uri_query_key' => 'redirect-uri' + ]); + + $authenticationService = $this->getMock('Zend\Authentication\AuthenticationService'); + $authenticationService->expects($this->once())->method('hasIdentity')->will($this->returnValue(false)); + + $redirectStrategy = new RedirectStrategy($options, $authenticationService); + + $redirectStrategy->onError($mvcEvent); + + $this->assertInstanceOf('Zend\Stdlib\ResponseInterface', $mvcEvent->getResult()); + $this->assertEquals(302, $mvcEvent->getResponse()->getStatusCode()); + $this->assertEquals( + '/login?redirect-uri=http://example.com/', + $mvcEvent->getResponse()->getHeaders()->get('Location')->getFieldValue() + ); + } +} diff --git a/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/View/Strategy/UnauthorizedStrategyTest.php b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/View/Strategy/UnauthorizedStrategyTest.php new file mode 100644 index 00000000000..01a7b7c07ee --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/ZfcRbacTest/View/Strategy/UnauthorizedStrategyTest.php @@ -0,0 +1,64 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +namespace ZfcRbacTest\View\Strategy; + +use Zend\Http\Response as HttpResponse; +use Zend\Mvc\MvcEvent; +use ZfcRbac\Exception\UnauthorizedException; +use ZfcRbac\Options\UnauthorizedStrategyOptions; +use ZfcRbac\View\Strategy\UnauthorizedStrategy; + +/** + * @covers \ZfcRbac\View\Strategy\UnauthorizedStrategy + * @covers \ZfcRbac\View\Strategy\AbstractStrategy + */ +class UnauthorizedStrategyTest extends \PHPUnit_Framework_TestCase +{ + public function testAttachToRightEvent() + { + $strategyListener = new UnauthorizedStrategy(new UnauthorizedStrategyOptions()); + + $eventManager = $this->getMock('Zend\EventManager\EventManagerInterface'); + $eventManager->expects($this->once()) + ->method('attach') + ->with(MvcEvent::EVENT_DISPATCH_ERROR); + + $strategyListener->attach($eventManager); + } + + public function testFillEvent() + { + $response = new HttpResponse(); + + $mvcEvent = new MvcEvent(); + $mvcEvent->setParam('exception', new UnauthorizedException()); + $mvcEvent->setResponse($response); + + $options = new UnauthorizedStrategyOptions([ + 'template' => 'error/403' + ]); + + $unauthorizedStrategy = new UnauthorizedStrategy($options); + + $unauthorizedStrategy->onError($mvcEvent); + + $this->assertEquals(403, $mvcEvent->getResponse()->getStatusCode()); + $this->assertInstanceOf('Zend\View\Model\ModelInterface', $mvcEvent->getResult()); + } +} diff --git a/vendor/zf-commons/zfc-rbac/tests/testing.config.php b/vendor/zf-commons/zfc-rbac/tests/testing.config.php new file mode 100644 index 00000000000..16046f0168c --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/tests/testing.config.php @@ -0,0 +1,52 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +return [ + 'zfc_rbac' => [], + + 'doctrine' => [ + 'driver' => [ + 'application_driver' => [ + 'class' => 'Doctrine\ORM\Mapping\Driver\AnnotationDriver', + 'cache' => 'array', + 'paths' => [__DIR__ . '/ZfcRbacTest/Asset'] + ], + 'orm_default' => [ + 'drivers' => [ + 'ZfcRbacTest\Asset' => 'application_driver' + ] + ] + ], + + 'connection' => [ + 'orm_default' => [ + 'driverClass' => 'Doctrine\DBAL\Driver\PDOSqlite\Driver', + 'params' => [ + 'host' => null, + 'port' => null, + 'user' => null, + 'password' => null, + 'dbname' => 'test', + 'driver' => 'pdo_sqlite', + 'path' => null, + 'memory' => true, + ], + ], + ], + ], +]; diff --git a/vendor/zf-commons/zfc-rbac/view/error/403.phtml b/vendor/zf-commons/zfc-rbac/view/error/403.phtml new file mode 100644 index 00000000000..956111b1ad0 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/view/error/403.phtml @@ -0,0 +1,15 @@ +<h1>A 403 error occurred</h1> + +<p>You are not allowed to access this resource</p> + +<h2>Details</h2> + +<?php + use ZfcRbac\Guard\GuardInterface; + + switch ($this->error) { + case GuardInterface::GUARD_UNAUTHORIZED: + echo '<p>Request was blocked by a ZfcRbac guard</p>'; + break; + } +?> diff --git a/vendor/zf-commons/zfc-rbac/view/zend-developer-tools/toolbar/zfc-rbac.phtml b/vendor/zf-commons/zfc-rbac/view/zend-developer-tools/toolbar/zfc-rbac.phtml new file mode 100644 index 00000000000..b865461b642 --- /dev/null +++ b/vendor/zf-commons/zfc-rbac/view/zend-developer-tools/toolbar/zfc-rbac.phtml @@ -0,0 +1,102 @@ +<?php +/* @var $collection \ZfcRbac\Collector\RbacCollector */ +$collection = $this->collector->getCollection(); +?> + +<div class="zdt-toolbar-entry"> + <div class="zdt-toolbar-preview"> + <!-- Image Provided by https://github.com/Nitecon with New BSD License to ZfcRbac --> + <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAAewQAAHsEBw2lUUwAAAAl2cEFnAAAAFAAAABQAozsq0QAAAylJREFUOMudVM1rXFUU/51775s3X+9NZpKmE0MC2lBGS6QahRIMuOnC6l7Upbsqhf4FhS66qRstIoV2UwhaLdUu6qISKBRhIqb5KJMJSSbTyUeTaGo68+Z9zPu410UjLaZpmBw4m8v93fM7v9+5h/CSGD1bgAYIszf5yVhxK7h4Y/mGkeCh5UZ7YviLDkeGcqg9uoKZhcmetwazZ5knz1VX7FP9h+LJvi59obzqWF2GBseXu7B0+9K7J5cWrMRirTmlmZrXczihFQpmX29vasRMiY+bS9bx7TWH+75E04uiuhPOgtFYoPB7xDCXSAk72x3vbthh4er12iMq3Xr/prdqn4oirHXk4y7pIqYRDiknzLTqPoVu+F9tEAFSKkgAiiiIJfk2cfJSmVjm4aZnnvlq9nvBGTr6crou3eg1ckLAiSAjCSggzgkwtL3k0gjoVgBYI0DMCtAKZI8QSUGGVFBKAUQ7dxnaCUaAmeDgjJSQwDNllWrroWdOPCXCGTxhb7ibPiew6HmG7YVSCg0nhB+qNdF44s+1crpigSLQwRgKRlhcd2Xtb29JVKr2VLol7ZSg9MH6BRgj3K/attOS02J8ZnsyK6iaS4vBA8kHwPElJpasKoAH4vKd9ZU3+pJ3okgf1LX2NWREKK3YKK86vwFYFV9+8AruV6zrJNVn/V2xfLu+BBK4N1tf/6se/MCIwBkDbk9sb/Z3xbo703zYjHMQFBiwbwoiFBcs/PLHP9+6vhxVgBLFeQsn38xE45XmN0aCDx/JJ4fNBIfcZyYFI0zXbPxYfHz3cTO8RIBU2Nk2TU/hvYLZKK+5c5yzkbcHjM6enA4zqSGT2p1ZQ8NGPcTXv66X/qw0TwtO83KnPgcAuxVh+qGNa2cKKxduLj/YssKhfFY/nEkJhAqIFBDtfCkJ4F65gfM/LU/dLdVPZ5Ji3H1uje2y4MRRE5PV5rETR43zHw51fjR0xIg9dZ9guSHGZp74P49v3apsuOcYoSz/p8wLPSUACsjkO2KfvjNgfHH81fTrni9RnG+UJirWd64vRwE09sLuN7cD2bT4PIwULDe6AmDxZYB/AbS8alQXJDY6AAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDEzLTEwLTA1VDAwOjAzOjEyLTA0OjAwtQbKIQAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxMy0xMC0wNVQwMDowMzoxMi0wNDowMMRbcp0AAAAASUVORK5CYII=" alt="ZfcRbac"> + <span class="zdt-toolbar-info">Settings</span> + </div> + + <div class="zdt-toolbar-detail"> + <span class="zdt-toolbar-info-heading">Settings Details</span> + + <span class="zdt-toolbar-info"> + <span class="zdt-detail-label">Guest role</span> + <span class="zdt-detail-value"> </span> + <span class="zdt-detail-value-right"><?= $collection['options']['guest_role']; ?></span> + </span> + <span class="zdt-toolbar-info"> + <span class="zdt-detail-label">Guard protection policy</span> + <span class="zdt-detail-value"> </span> + <span class="zdt-detail-value-right"><?= $collection['options']['protection_policy']; ?></span> + </span> + </div> +</div> + +<div class="zdt-toolbar-entry"> + <div class="zdt-toolbar-preview"> + <!-- Image Provided by https://github.com/Nitecon with New BSD License to ZfcRbac --> + <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAAewQAAHsEBw2lUUwAAAAl2cEFnAAAAFAAAABQAozsq0QAAAylJREFUOMudVM1rXFUU/51775s3X+9NZpKmE0MC2lBGS6QahRIMuOnC6l7Upbsqhf4FhS66qRstIoV2UwhaLdUu6qISKBRhIqb5KJMJSSbTyUeTaGo68+Z9zPu410UjLaZpmBw4m8v93fM7v9+5h/CSGD1bgAYIszf5yVhxK7h4Y/mGkeCh5UZ7YviLDkeGcqg9uoKZhcmetwazZ5knz1VX7FP9h+LJvi59obzqWF2GBseXu7B0+9K7J5cWrMRirTmlmZrXczihFQpmX29vasRMiY+bS9bx7TWH+75E04uiuhPOgtFYoPB7xDCXSAk72x3vbthh4er12iMq3Xr/prdqn4oirHXk4y7pIqYRDiknzLTqPoVu+F9tEAFSKkgAiiiIJfk2cfJSmVjm4aZnnvlq9nvBGTr6crou3eg1ckLAiSAjCSggzgkwtL3k0gjoVgBYI0DMCtAKZI8QSUGGVFBKAUQ7dxnaCUaAmeDgjJSQwDNllWrroWdOPCXCGTxhb7ibPiew6HmG7YVSCg0nhB+qNdF44s+1crpigSLQwRgKRlhcd2Xtb29JVKr2VLol7ZSg9MH6BRgj3K/attOS02J8ZnsyK6iaS4vBA8kHwPElJpasKoAH4vKd9ZU3+pJ3okgf1LX2NWREKK3YKK86vwFYFV9+8AruV6zrJNVn/V2xfLu+BBK4N1tf/6se/MCIwBkDbk9sb/Z3xbo703zYjHMQFBiwbwoiFBcs/PLHP9+6vhxVgBLFeQsn38xE45XmN0aCDx/JJ4fNBIfcZyYFI0zXbPxYfHz3cTO8RIBU2Nk2TU/hvYLZKK+5c5yzkbcHjM6enA4zqSGT2p1ZQ8NGPcTXv66X/qw0TwtO83KnPgcAuxVh+qGNa2cKKxduLj/YssKhfFY/nEkJhAqIFBDtfCkJ4F65gfM/LU/dLdVPZ5Ji3H1uje2y4MRRE5PV5rETR43zHw51fjR0xIg9dZ9guSHGZp74P49v3apsuOcYoSz/p8wLPSUACsjkO2KfvjNgfHH81fTrni9RnG+UJirWd64vRwE09sLuN7cD2bT4PIwULDe6AmDxZYB/AbS8alQXJDY6AAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDEzLTEwLTA1VDAwOjAzOjEyLTA0OjAwtQbKIQAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxMy0xMC0wNVQwMDowMzoxMi0wNDowMMRbcp0AAAAASUVORK5CYII=" alt="ZfcRbac"> + <span class="zdt-toolbar-info">Guards</span> + </div> + <div class="zdt-toolbar-detail"> + <span class="zdt-toolbar-info-heading">Guards details</span> + + <?php if (count($collection['guards']) > 0): ?> + <?php foreach ($collection['guards'] as $type => $rules): ?> + <span class="zdt-toolbar-info"> + <span class="zdt-detail-label">Type</span> + <span class="zdt-detail-value"> </span> + <span class="zdt-detail-value-right"><?= $type; ?></span> + </span> + + <span class="zdt-toolbar-info"> + <span class="zdt-detail-label">Rules</span> + <span class="zdt-detail-value"> </span> + <span class="zdt-detail-value-right"> + <?php + $d = new \Zend\Debug\Debug(); + $d->dump($rules); + ?> + </span> + </span> + <?php endforeach; ?> + <?php else: ?> + <span class="zdt-toolbar-info"> + <span class="zdt-detail-value">No guards</span> + </span> + <?php endif; ?> + </div> +</div> + +<div class="zdt-toolbar-entry"> + <div class="zdt-toolbar-preview"> + <!-- Image Provided by https://github.com/Nitecon with New BSD License to ZfcRbac --> + <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABGdBTUEAALGPC/xhBQAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAAewQAAHsEBw2lUUwAAAAl2cEFnAAAAFAAAABQAozsq0QAAAylJREFUOMudVM1rXFUU/51775s3X+9NZpKmE0MC2lBGS6QahRIMuOnC6l7Upbsqhf4FhS66qRstIoV2UwhaLdUu6qISKBRhIqb5KJMJSSbTyUeTaGo68+Z9zPu410UjLaZpmBw4m8v93fM7v9+5h/CSGD1bgAYIszf5yVhxK7h4Y/mGkeCh5UZ7YviLDkeGcqg9uoKZhcmetwazZ5knz1VX7FP9h+LJvi59obzqWF2GBseXu7B0+9K7J5cWrMRirTmlmZrXczihFQpmX29vasRMiY+bS9bx7TWH+75E04uiuhPOgtFYoPB7xDCXSAk72x3vbthh4er12iMq3Xr/prdqn4oirHXk4y7pIqYRDiknzLTqPoVu+F9tEAFSKkgAiiiIJfk2cfJSmVjm4aZnnvlq9nvBGTr6crou3eg1ckLAiSAjCSggzgkwtL3k0gjoVgBYI0DMCtAKZI8QSUGGVFBKAUQ7dxnaCUaAmeDgjJSQwDNllWrroWdOPCXCGTxhb7ibPiew6HmG7YVSCg0nhB+qNdF44s+1crpigSLQwRgKRlhcd2Xtb29JVKr2VLol7ZSg9MH6BRgj3K/attOS02J8ZnsyK6iaS4vBA8kHwPElJpasKoAH4vKd9ZU3+pJ3okgf1LX2NWREKK3YKK86vwFYFV9+8AruV6zrJNVn/V2xfLu+BBK4N1tf/6se/MCIwBkDbk9sb/Z3xbo703zYjHMQFBiwbwoiFBcs/PLHP9+6vhxVgBLFeQsn38xE45XmN0aCDx/JJ4fNBIfcZyYFI0zXbPxYfHz3cTO8RIBU2Nk2TU/hvYLZKK+5c5yzkbcHjM6enA4zqSGT2p1ZQ8NGPcTXv66X/qw0TwtO83KnPgcAuxVh+qGNa2cKKxduLj/YssKhfFY/nEkJhAqIFBDtfCkJ4F65gfM/LU/dLdVPZ5Ji3H1uje2y4MRRE5PV5rETR43zHw51fjR0xIg9dZ9guSHGZp74P49v3apsuOcYoSz/p8wLPSUACsjkO2KfvjNgfHH81fTrni9RnG+UJirWd64vRwE09sLuN7cD2bT4PIwULDe6AmDxZYB/AbS8alQXJDY6AAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDEzLTEwLTA1VDAwOjAzOjEyLTA0OjAwtQbKIQAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxMy0xMC0wNVQwMDowMzoxMi0wNDowMMRbcp0AAAAASUVORK5CYII=" alt="ZfcRbac"> + <span class="zdt-toolbar-info">Roles</span> + </div> + <div class="zdt-toolbar-detail"> + <span class="zdt-toolbar-info zdt-toolbar-info-heading">Loaded identity roles</span> + + <?php if (count($collection['roles']) > 0): ?> + <?php foreach ($collection['roles'] as $key => $value): ?> + <span class="zdt-toolbar-info"> + <?php if (is_string($key)): ?> + <span class="zdt-detail-label" style="text-transform: none"><?= $key; ?></span> + <span class="zdt-detail-value"> </span> + <span class="zdt-detail-value-right"><?= implode(', ', $value); ?></span> + <?php else: ?> + <span class="zdt-detail-value"><?= $value; ?></span> + <?php endif; ?> + </span> + <?php endforeach; ?> + <?php else: ?> + <span class="zdt-toolbar-info"> + <span class="zdt-detail-value">No identity roles</span> + </span> + <?php endif; ?> + + <span class="zdt-toolbar-info zdt-toolbar-info-heading">Permissions for loaded identity roles</span> + + <?php foreach ($collection['permissions'] as $roleName => $permissions): ?> + <span class="zdt-toolbar-info"> + <span class="zdt-detail-label" style="text-transform: none"><?= $roleName; ?></span> + <span class="zdt-detail-value"> </span> + <span class="zdt-detail-value-right"><?= implode(', ', $permissions); ?></span> + </span> + <?php endforeach; ?> + </div> +</div> diff --git a/vendor/zfr/rbac/.gitignore b/vendor/zfr/rbac/.gitignore new file mode 100644 index 00000000000..dd82d95171a --- /dev/null +++ b/vendor/zfr/rbac/.gitignore @@ -0,0 +1,7 @@ +._* +.~lock.* +data/ +vendor/ +composer.lock +composer.phar +.idea diff --git a/vendor/zfr/rbac/.travis.yml b/vendor/zfr/rbac/.travis.yml new file mode 100644 index 00000000000..5301a67cebb --- /dev/null +++ b/vendor/zfr/rbac/.travis.yml @@ -0,0 +1,16 @@ +language: php + +php: + - 5.4 + - 5.5 + +before_script: + - composer self-update + - composer update --prefer-source --dev + +script: + - ./vendor/bin/phpunit --coverage-clover ./build/logs/clover.xml --group=Coverage + - ./vendor/bin/phpcs --standard=PSR2 ./src/ + +after_script: + - php vendor/bin/coveralls -v diff --git a/vendor/zfr/rbac/CHANGELOG.md b/vendor/zfr/rbac/CHANGELOG.md new file mode 100644 index 00000000000..1381ce19a05 --- /dev/null +++ b/vendor/zfr/rbac/CHANGELOG.md @@ -0,0 +1,19 @@ +# CHANGELOG + +## 1.2.0 + +* `isGranted` no longer cast permissions to string. Instead, the permission is now given to your role entity as it. This +may be a potential BC if you only expected string in your `hasPermission` method. +* `PermissionInterface` is deprecated and will be removed in final implementation (likely for ZF3). RBAC should not +enforce any interface for a permission as its representation is dependant of your application. However, modules +like ZfcRbac may enforce an interface for permissions. +* Various PHPDoc fixes + +## 1.1.0 + +* [BC] Remove factory. It was not intend to be here but rather on ZfcRbac. This way this component is completely +framework agnostic + +## 1.0.0 + +* Initial release diff --git a/vendor/zfr/rbac/README.md b/vendor/zfr/rbac/README.md new file mode 100644 index 00000000000..f88eb93f0f2 --- /dev/null +++ b/vendor/zfr/rbac/README.md @@ -0,0 +1,24 @@ +Rbac +==== + +[](https://travis-ci.org/zf-fr/rbac) +[](https://packagist.org/packages/zfr/rbac) +[](https://packagist.org/packages/zfr/rbac) + +Rbac (not to be confused with ZfcRbac) is a pure PHP implementation of the RBAC (*Role based access control*) +concept. Actually, it is a Zend Framework 3 prototype of the ZF2 Zend\Permissions\Rbac component. + +It aims to fix some design mistakes that were made to make it more usable and more efficient. + +It differs on those points: + +* A `PermissionInterface` has been introduced. +* `RoleInterface` no longer have `setParent` and `getParent` methods, and cannot have children anymore (this is +used to implement a simpler "flat RBAC"). +* A new `HierarchicalRoleInterface` has been introduced to allow roles to have children. +* Method `hasPermission` on a role no longer recursively iterate the children role, but only check its own permissions. +To properly check if a role is granted, you should use the `isGranted` method of the `Rbac` class. +* `Rbac` class is no longer a container. Instead, it just has a `isGranted` method. The container was complex to +properly handle because of role duplication, which could lead to security problems if not used correctly. + +This library is used in ZfcRbac 2.0 diff --git a/vendor/zfr/rbac/composer.json b/vendor/zfr/rbac/composer.json new file mode 100644 index 00000000000..f2e0460191e --- /dev/null +++ b/vendor/zfr/rbac/composer.json @@ -0,0 +1,34 @@ +{ + "name": "zfr/rbac", + "description": "Zend Framework 3 prototype for Zend\\Permissions\\Rbac.", + "type": "library", + "license": "MIT", + "keywords": [ + "zf2", + "zf3", + "rbac", + "security" + ], + "homepage": "https://github.com/zf-fr/rbac", + "authors": [ + { + "name": "Michaël Gallego", + "email": "mic.gallego@gmail.com", + "homepage": "http://www.michaelgallego.fr/" + } + ], + "require": { + "php": ">=5.4" + }, + "require-dev": { + "zendframework/zend-servicemanager": "~2.2", + "phpunit/phpunit": "~3.7", + "squizlabs/php_codesniffer": "1.4.*", + "satooshi/php-coveralls": "~0.6" + }, + "autoload": { + "psr-0": { + "Rbac\\": "src/" + } + } +} diff --git a/vendor/zfr/rbac/phpunit.xml.dist b/vendor/zfr/rbac/phpunit.xml.dist new file mode 100644 index 00000000000..6ac57bae18c --- /dev/null +++ b/vendor/zfr/rbac/phpunit.xml.dist @@ -0,0 +1,22 @@ +<?xml version="1.0"?> +<phpunit + bootstrap="./tests/Bootstrap.php" + colors="true" + convertErrorsToExceptions="true" + convertNoticesToExceptions="true" + convertWarningsToExceptions="true" + verbose="true" + stopOnFailure="false" + processIsolation="false" + backupGlobals="false" + syntaxCheck="true" +> + <testsuite name="ZfrRbac tests"> + <directory>./tests</directory> + </testsuite> + <filter> + <whitelist addUncoveredFilesFromWhitelist="true"> + <directory suffix=".php">./src</directory> + </whitelist> + </filter> +</phpunit> diff --git a/vendor/zfr/rbac/src/Rbac/Permission/PermissionInterface.php b/vendor/zfr/rbac/src/Rbac/Permission/PermissionInterface.php new file mode 100644 index 00000000000..e5e27a95f83 --- /dev/null +++ b/vendor/zfr/rbac/src/Rbac/Permission/PermissionInterface.php @@ -0,0 +1,28 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Rbac\Permission; + +/** + * Interface for permission + * + * @deprecated It will be removed from final implementation (likely for Zend Framework 3) + */ +interface PermissionInterface +{ + /** + * Get the permission name + * + * You really must return the name of the permission as internally, the casting to string is used + * as an optimization to avoid type checkings + * + * @return string + */ + public function __toString(); +} diff --git a/vendor/zfr/rbac/src/Rbac/Rbac.php b/vendor/zfr/rbac/src/Rbac/Rbac.php new file mode 100644 index 00000000000..a7a7630c79c --- /dev/null +++ b/vendor/zfr/rbac/src/Rbac/Rbac.php @@ -0,0 +1,68 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Rbac; + +use Rbac\Role\RoleInterface; +use Rbac\Traversal\Strategy\TraversalStrategyInterface; +use Traversable; + +/** + * Rbac object. It is used to check a permission against roles + */ +class Rbac +{ + /** + * @var TraversalStrategyInterface + */ + protected $traversalStrategy; + + /** + * @param TraversalStrategyInterface $strategy + */ + public function __construct(TraversalStrategyInterface $strategy) + { + $this->traversalStrategy = $strategy; + } + + /** + * Determines if access is granted by checking the roles for permission. + * + * @param RoleInterface|RoleInterface[]|Traversable $roles + * @param mixed $permission + * @return bool + */ + public function isGranted($roles, $permission) + { + if ($roles instanceof RoleInterface) { + $roles = [$roles]; + } + + $iterator = $this->traversalStrategy->getRolesIterator($roles); + + foreach ($iterator as $role) { + /* @var RoleInterface $role */ + if ($role->hasPermission($permission)) { + return true; + } + } + + return false; + } + + /** + * Get the strategy. + * + * @return TraversalStrategyInterface + */ + public function getTraversalStrategy() + { + return $this->traversalStrategy; + } +} diff --git a/vendor/zfr/rbac/src/Rbac/Role/HierarchicalRole.php b/vendor/zfr/rbac/src/Rbac/Role/HierarchicalRole.php new file mode 100644 index 00000000000..5ab2432bd65 --- /dev/null +++ b/vendor/zfr/rbac/src/Rbac/Role/HierarchicalRole.php @@ -0,0 +1,47 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Rbac\Role; + +/** + * Simple implementation for a hierarchical role + */ +class HierarchicalRole extends Role implements HierarchicalRoleInterface +{ + /** + * @var array|RoleInterface[] + */ + protected $children = []; + + /** + * {@inheritDoc} + */ + public function hasChildren() + { + return !empty($this->children); + } + + /** + * {@inheritDoc} + */ + public function getChildren() + { + return $this->children; + } + + /** + * Add a child role + * + * @param RoleInterface $child + */ + public function addChild(RoleInterface $child) + { + $this->children[$child->getName()] = $child; + } +} diff --git a/vendor/zfr/rbac/src/Rbac/Role/HierarchicalRoleInterface.php b/vendor/zfr/rbac/src/Rbac/Role/HierarchicalRoleInterface.php new file mode 100644 index 00000000000..9dbb5ead1e1 --- /dev/null +++ b/vendor/zfr/rbac/src/Rbac/Role/HierarchicalRoleInterface.php @@ -0,0 +1,34 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Rbac\Role; + +use Traversable; + +/** + * Interface for a hierarchical role + * + * A hierarchical role is a role that can have children. + */ +interface HierarchicalRoleInterface extends RoleInterface +{ + /** + * Check if the role has children + * + * @return bool + */ + public function hasChildren(); + + /** + * Get child roles + * + * @return array|RoleInterface[]|Traversable + */ + public function getChildren(); +} diff --git a/vendor/zfr/rbac/src/Rbac/Role/Role.php b/vendor/zfr/rbac/src/Rbac/Role/Role.php new file mode 100644 index 00000000000..f2b5a3f3879 --- /dev/null +++ b/vendor/zfr/rbac/src/Rbac/Role/Role.php @@ -0,0 +1,66 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Rbac\Role; + +/** + * Simple implementation for a role without hierarchy + * and using strings as permissions + */ +class Role implements RoleInterface +{ + /** + * @var string + */ + protected $name; + + /** + * @var string[] + */ + protected $permissions = []; + + /** + * Constructor + * + * @param string $name + */ + public function __construct($name) + { + $this->name = (string) $name; + } + + /** + * {@inheritDoc} + */ + public function getName() + { + return $this->name; + } + + /** + * Add a permission + * + * @param string $permission + */ + public function addPermission($permission) + { + $this->permissions[(string) $permission] = $permission; + } + + /** + * Checks if a permission exists for this role + * + * @param string $permission + * @return bool + */ + public function hasPermission($permission) + { + return isset($this->permissions[(string) $permission]); + } +} diff --git a/vendor/zfr/rbac/src/Rbac/Role/RoleInterface.php b/vendor/zfr/rbac/src/Rbac/Role/RoleInterface.php new file mode 100644 index 00000000000..04f23fd2221 --- /dev/null +++ b/vendor/zfr/rbac/src/Rbac/Role/RoleInterface.php @@ -0,0 +1,33 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Rbac\Role; + +/** + * Interface for a flat role + * + * The role embeds all the information needed to evaluate if a given role has a given permission + */ +interface RoleInterface +{ + /** + * Get the name of the role. + * + * @return string + */ + public function getName(); + + /** + * Checks if a permission exists for this role (it does not check child roles) + * + * @param mixed $permission + * @return bool + */ + public function hasPermission($permission); +} diff --git a/vendor/zfr/rbac/src/Rbac/Traversal/RecursiveRoleIterator.php b/vendor/zfr/rbac/src/Rbac/Traversal/RecursiveRoleIterator.php new file mode 100644 index 00000000000..6722e14e06c --- /dev/null +++ b/vendor/zfr/rbac/src/Rbac/Traversal/RecursiveRoleIterator.php @@ -0,0 +1,63 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Rbac\Traversal; + +use ArrayIterator; +use Rbac\Role\HierarchicalRoleInterface; +use Rbac\Role\RoleInterface; +use RecursiveIterator; +use Traversable; + +class RecursiveRoleIterator extends ArrayIterator implements RecursiveIterator +{ + /** + * Override constructor to accept {@link Traversable} as well + * + * @param RoleInterface[]|Traversable $roles + */ + public function __construct($roles) + { + if ($roles instanceof Traversable) { + $roles = iterator_to_array($roles); + } + + parent::__construct($roles); + } + + /** + * @return bool + */ + public function valid() + { + return $this->current() instanceof RoleInterface; + } + + /** + * @return bool + */ + public function hasChildren() + { + $current = $this->current(); + + if (!$current instanceof HierarchicalRoleInterface) { + return false; + } + + return $current->hasChildren(); + } + + /** + * @return RecursiveRoleIterator + */ + public function getChildren() + { + return new RecursiveRoleIterator($this->current()->getChildren()); + } +} diff --git a/vendor/zfr/rbac/src/Rbac/Traversal/Strategy/GeneratorStrategy.php b/vendor/zfr/rbac/src/Rbac/Traversal/Strategy/GeneratorStrategy.php new file mode 100644 index 00000000000..63574f0db01 --- /dev/null +++ b/vendor/zfr/rbac/src/Rbac/Traversal/Strategy/GeneratorStrategy.php @@ -0,0 +1,43 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Rbac\Traversal\Strategy; + +use Generator; +use Rbac\Role\HierarchicalRoleInterface; +use Rbac\Role\RoleInterface; +use Traversable; + +/** + * Recursively traverse roles using generator + * Requires PHP >= 5.5 + */ +class GeneratorStrategy implements TraversalStrategyInterface +{ + /** + * @param RoleInterface[]|Traversable $roles + * @return Generator + */ + public function getRolesIterator($roles) + { + foreach ($roles as $role) { + yield $role; + + if (!$role instanceof HierarchicalRoleInterface) { + continue; + } + + $children = $this->getRolesIterator($role->getChildren()); + + foreach ($children as $child) { + yield $child; + } + } + } +} diff --git a/vendor/zfr/rbac/src/Rbac/Traversal/Strategy/RecursiveRoleIteratorStrategy.php b/vendor/zfr/rbac/src/Rbac/Traversal/Strategy/RecursiveRoleIteratorStrategy.php new file mode 100644 index 00000000000..93b3a52e085 --- /dev/null +++ b/vendor/zfr/rbac/src/Rbac/Traversal/Strategy/RecursiveRoleIteratorStrategy.php @@ -0,0 +1,32 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Rbac\Traversal\Strategy; + +use Rbac\Role\RoleInterface; +use Rbac\Traversal\RecursiveRoleIterator; +use RecursiveIteratorIterator; + +/** + * Create a {@link RecursiveRoleIterator} and wrap it into a {@link RecursiveIteratorIterator} + */ +class RecursiveRoleIteratorStrategy implements TraversalStrategyInterface +{ + /** + * @param RoleInterface[] $roles + * @return RecursiveIteratorIterator + */ + public function getRolesIterator($roles) + { + return new RecursiveIteratorIterator( + new RecursiveRoleIterator($roles), + RecursiveIteratorIterator::SELF_FIRST + ); + } +} diff --git a/vendor/zfr/rbac/src/Rbac/Traversal/Strategy/TraversalStrategyInterface.php b/vendor/zfr/rbac/src/Rbac/Traversal/Strategy/TraversalStrategyInterface.php new file mode 100644 index 00000000000..dfe50461d60 --- /dev/null +++ b/vendor/zfr/rbac/src/Rbac/Traversal/Strategy/TraversalStrategyInterface.php @@ -0,0 +1,25 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace Rbac\Traversal\Strategy; + +use Rbac\Role\RoleInterface; +use Traversable; + +/** + * Interface for a traversal strategy + */ +interface TraversalStrategyInterface +{ + /** + * @param RoleInterface[]|Traversable + * @return Traversable + */ + public function getRolesIterator($roles); +} diff --git a/vendor/zfr/rbac/tests/Bootstrap.php b/vendor/zfr/rbac/tests/Bootstrap.php new file mode 100644 index 00000000000..69f3560d120 --- /dev/null +++ b/vendor/zfr/rbac/tests/Bootstrap.php @@ -0,0 +1,46 @@ +<?php +/* + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This software consists of voluntary contributions made by many individuals + * and is licensed under the MIT license. + */ + +ini_set('error_reporting', E_ALL); + +$files = [__DIR__ . '/../vendor/autoload.php', __DIR__ . '/../../../autoload.php']; + +foreach ($files as $file) { + if (file_exists($file)) { + $loader = require $file; + + break; + } +} + +if (! isset($loader)) { + throw new RuntimeException('vendor/autoload.php could not be found. Did you install via composer?'); +} + +$loader->add('RbacTest\\', __DIR__); + +$configFiles = [__DIR__ . '/TestConfiguration.php', __DIR__ . '/TestConfiguration.php.dist']; + +foreach ($configFiles as $configFile) { + if (file_exists($configFile)) { + $config = require $configFile; + + break; + } +} + diff --git a/vendor/zfr/rbac/tests/RbacTest/RbacTest.php b/vendor/zfr/rbac/tests/RbacTest/RbacTest.php new file mode 100644 index 00000000000..faa571ba0fc --- /dev/null +++ b/vendor/zfr/rbac/tests/RbacTest/RbacTest.php @@ -0,0 +1,120 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace RbacTest; + +use ArrayIterator; +use PHPUnit_Framework_TestCase as TestCase; +use Rbac\Rbac; +use Rbac\Role\Role; +use Rbac\Traversal\Strategy\RecursiveRoleIteratorStrategy; + +/** + * @covers Rbac\Rbac + * @group Coverage + */ +class RbacTest extends TestCase +{ + /** + * @covers Rbac\Rbac::__construct + */ + public function testConstructorAcceptCustomTraversalStrategy() + { + $customStrategy = $this->getMock('Rbac\Traversal\Strategy\TraversalStrategyInterface'); + $rbac = new Rbac($customStrategy); + + $this->assertAttributeSame($customStrategy, 'traversalStrategy', $rbac); + } + + /** + * @covers Rbac\Rbac::isGranted + */ + public function testInjectSingleRoleToArray() + { + $role = new Role('Foo'); + + $traversalStrategy = $this->getMock('Rbac\Traversal\Strategy\TraversalStrategyInterface'); + $traversalStrategy->expects($this->once()) + ->method('getRolesIterator') + ->with($this->equalTo([$role])) + ->will($this->returnValue(new ArrayIterator([]))); + + $rbac = new Rbac($traversalStrategy); + + $rbac->isGranted($role, 'permission'); + } + + /** + * @covers Rbac\Rbac::isGranted + */ + public function testFetchIteratorFromTraversalStrategy() + { + $traversalStrategy = $this->getMock('Rbac\Traversal\Strategy\TraversalStrategyInterface'); + $traversalStrategy->expects($this->once()) + ->method('getRolesIterator') + ->will($this->returnValue(new ArrayIterator([]))); + + $rbac = new Rbac($traversalStrategy); + + $rbac->isGranted([], 'permission'); + } + + /** + * @covers Rbac\Rbac::isGranted + */ + public function testTraverseRoles() + { + $role = $this->getMock('Rbac\Role\RoleInterface'); + $role->expects($this->exactly(3)) + ->method('hasPermission') + ->with($this->equalTo('permission')) + ->will($this->returnValue(false)); + + $roles = [$role, $role, $role]; + $rbac = new Rbac(new RecursiveRoleIteratorStrategy()); + + $rbac->isGranted($roles, 'permission'); + } + + /** + * @covers Rbac\Rbac::isGranted + */ + public function testReturnTrueWhenRoleHasPermission() + { + $grantedRole = $this->getMock('Rbac\Role\RoleInterface'); + $grantedRole->expects($this->once()) + ->method('hasPermission') + ->with('permission') + ->will($this->returnValue(true)); + + $nextRole = $this->getMock('Rbac\Role\RoleInterface'); + $nextRole->expects($this->never())->method('hasPermission'); + + $roles = [$grantedRole, $nextRole]; + $rbac = new Rbac(new RecursiveRoleIteratorStrategy()); + + $this->assertTrue($rbac->isGranted($roles, 'permission')); + } + + public function testReturnFalseIfNoRoleHasPermission() + { + $roles = [new Role('Foo'), new Role('Bar')]; + $rbac = new Rbac(new RecursiveRoleIteratorStrategy()); + + $this->assertFalse($rbac->isGranted($roles, 'permission')); + } + + public function testGetTraversalStrategy() + { + $customStrategy = $this->getMock('Rbac\Traversal\Strategy\TraversalStrategyInterface'); + $rbac = new Rbac($customStrategy); + + $this->assertSame($customStrategy, $rbac->getTraversalStrategy()); + } +} diff --git a/vendor/zfr/rbac/tests/RbacTest/Role/HierarchicalRoleTest.php b/vendor/zfr/rbac/tests/RbacTest/Role/HierarchicalRoleTest.php new file mode 100644 index 00000000000..f4b6ff9c8a2 --- /dev/null +++ b/vendor/zfr/rbac/tests/RbacTest/Role/HierarchicalRoleTest.php @@ -0,0 +1,65 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace RbacTest; + +use PHPUnit_Framework_TestCase as TestCase; +use Rbac\Role\HierarchicalRole; + +/** + * @covers Rbac\Role\HierarchicalRole + * @group Coverage + */ +class HierarchicalRoleTest extends TestCase +{ + /** + * @covers Rbac\Role\HierarchicalRole::addChild + */ + public function testCanAddChild() + { + $role = new HierarchicalRole('role'); + $child = new HierarchicalRole('child'); + + $role->addChild($child); + + $this->assertCount(1, $role->getChildren()); + } + + /** + * @covers Rbac\Role\HierarchicalRole::hasChildren + */ + public function testHasChildren() + { + $role = new HierarchicalRole('role'); + + $this->assertFalse($role->hasChildren()); + + $role->addChild(new HierarchicalRole('child')); + + $this->assertTrue($role->hasChildren()); + } + + /** + * @covers Rbac\Role\HierarchicalRole::getChildren + */ + public function testCanGetChildren() + { + $role = new HierarchicalRole('role'); + $child1 = new HierarchicalRole('child 1'); + $child2 = new HierarchicalRole('child 2'); + + $role->addChild($child1); + $role->addChild($child2); + + $children = $role->getChildren(); + + $this->assertCount(2, $children); + $this->assertContainsOnlyInstancesOf('Rbac\Role\HierarchicalRole', $children); + } +} diff --git a/vendor/zfr/rbac/tests/RbacTest/Role/RoleTest.php b/vendor/zfr/rbac/tests/RbacTest/Role/RoleTest.php new file mode 100644 index 00000000000..28d821bcc3a --- /dev/null +++ b/vendor/zfr/rbac/tests/RbacTest/Role/RoleTest.php @@ -0,0 +1,43 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + * @package Zend_Permissions + */ + +namespace RbacTest; + +use Rbac\Role\Role; + +/** + * @covers \Rbac\Role\Role + * @group Coverage + */ +class RoleTest extends \PHPUnit_Framework_TestCase +{ + public function testSetNameByConstructor() + { + $role = new Role('phpIsHell'); + $this->assertEquals('phpIsHell', $role->getName()); + } + + /** + * @covers Rbac\Role\Role::addPermission + */ + public function testRoleCanAddPermission() + { + $role = new Role('php'); + + $role->addPermission('debug'); + $this->assertTrue($role->hasPermission('debug')); + + $permission = $this->getMock('Rbac\Permission\PermissionInterface'); + $permission->expects($this->once())->method('__toString')->will($this->returnValue('interface')); + $role->addPermission($permission); + + $this->assertTrue($role->hasPermission('interface')); + } +} diff --git a/vendor/zfr/rbac/tests/RbacTest/Traversal/RecursiveRoleIteratorTest.php b/vendor/zfr/rbac/tests/RbacTest/Traversal/RecursiveRoleIteratorTest.php new file mode 100644 index 00000000000..cd168e8e661 --- /dev/null +++ b/vendor/zfr/rbac/tests/RbacTest/Traversal/RecursiveRoleIteratorTest.php @@ -0,0 +1,108 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace RbacTest\Traversal; + +use ArrayIterator; +use PHPUnit_Framework_TestCase as TestCase; +use Rbac\Role\HierarchicalRole; +use Rbac\Role\Role; +use Rbac\Traversal\RecursiveRoleIterator; +use stdClass; + +/** + * @covers Rbac\Traversal\RecursiveRoleIterator + * @group Coverage + */ +class RecursiveRoleIteratorTest extends TestCase +{ + /** + * @covers Rbac\Traversal\RecursiveRoleIterator::__construct + */ + public function testAcceptTraversable() + { + $roles = new ArrayIterator([new Role('foo'), new Role('bar')]); + $iterator = new RecursiveRoleIterator($roles); + + $this->assertEquals($iterator->getArrayCopy(), $roles->getArrayCopy()); + } + + /** + * @covers Rbac\Traversal\RecursiveRoleIterator::valid + */ + public function testValidateRoleInterface() + { + $foo = new Role('Foo'); + $roles = [$foo, new stdClass]; + $iterator = new RecursiveRoleIterator($roles); + + $this->assertSame($iterator->current(), $foo); + $this->assertTrue($iterator->valid()); + + $iterator->next(); + + $this->assertFalse($iterator->valid()); + } + + /** + * @covers Rbac\Traversal\RecursiveRoleIterator::hasChildren + */ + public function testHasChildrenReturnsFalseIfCurrentRoleIsNotHierarchical() + { + $foo = new Role('Foo'); + $roles = [$foo]; + $iterator = new RecursiveRoleIterator($roles); + + $this->assertFalse($iterator->hasChildren()); + } + + /** + * @covers Rbac\Traversal\RecursiveRoleIterator::hasChildren + */ + public function testHasChildrenReturnsFalseIfCurrentRoleHasNotChildren() + { + $role = $this->getMock('Rbac\Role\HierarchicalRoleInterface'); + $iterator = new RecursiveRoleIterator([$role]); + + $role->expects($this->once())->method('hasChildren')->will($this->returnValue(false)); + + $this->assertFalse($iterator->hasChildren()); + } + + /** + * @covers Rbac\Traversal\RecursiveRoleIterator::hasChildren + */ + public function testHasChildrenReturnsTrueIfCurrentRoleHasChildren() + { + $role = $this->getMock('Rbac\Role\HierarchicalRoleInterface'); + $iterator = new RecursiveRoleIterator([$role]); + + $role->expects($this->once())->method('hasChildren')->will($this->returnValue(true)); + + $this->assertTrue($iterator->hasChildren()); + } + + /** + * @covers Rbac\Traversal\RecursiveRoleIterator::getChildren + */ + public function testGetChildrenReturnsAnRecursiveRoleIteratorOfRoleChildren() + { + $baz = new HierarchicalRole('Baz'); + $baz->addChild(new Role('Foo')); + $baz->addChild(new Role('Bar')); + + $roles = [$baz]; + $iterator = new RecursiveRoleIterator($roles); + + $this->assertEquals( + $iterator->getChildren(), + new RecursiveRoleIterator($baz->getChildren()) + ); + } +} diff --git a/vendor/zfr/rbac/tests/RbacTest/Traversal/Strategy/GeneratorStrategyTest.php b/vendor/zfr/rbac/tests/RbacTest/Traversal/Strategy/GeneratorStrategyTest.php new file mode 100644 index 00000000000..5a260033aa6 --- /dev/null +++ b/vendor/zfr/rbac/tests/RbacTest/Traversal/Strategy/GeneratorStrategyTest.php @@ -0,0 +1,71 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace RbacTest\Traversal\Strategy; + +use PHPUnit_Framework_TestCase as TestCase; +use Rbac\Role\HierarchicalRole; +use Rbac\Role\Role; +use Rbac\Traversal\Strategy\GeneratorStrategy; + +/** + * @requires PHP 5.5.0 + * @covers Rbac\Traversal\Strategy\GeneratorStrategy + * @group Coverage + */ +class GeneratorStrategyTest extends TestCase +{ + /** + * @covers Rbac\Traversal\Strategy\GeneratorStrategy::getRolesIterator + */ + public function testTraverseFlatRoles() + { + $strategy = new GeneratorStrategy; + $roles = [new Role('Foo'), new Role('Bar')]; + + $this->assertEquals( + $roles, + iterator_to_array($strategy->getRolesIterator($roles)) + ); + } + + /** + * @covers Rbac\Traversal\Strategy\GeneratorStrategy::getRolesIterator + */ + public function testTraverseHierarchicalRoles() + { + $strategy = new GeneratorStrategy; + + $child1 = new Role('child 1'); + $child2 = new Role('child 2'); + $child3 = new Role('child 3'); + + $parent1 = new HierarchicalRole('parent 1'); + $parent1->addChild($child1); + + $parent2 = new HierarchicalRole('parent 2'); + $parent2->addChild($child2); + + $parent3 = new HierarchicalRole('parent 3'); + $parent3->addChild($child3); + + $roles = [$parent1, $parent2, $parent3]; + + $expectedResult = [ + $parent1, $child1, + $parent2, $child2, + $parent3, $child3, + ]; + + $this->assertEquals( + $expectedResult, + iterator_to_array($strategy->getRolesIterator($roles)) + ); + } +} diff --git a/vendor/zfr/rbac/tests/RbacTest/Traversal/Strategy/RecursiveRoleIteratorStrategyTest.php b/vendor/zfr/rbac/tests/RbacTest/Traversal/Strategy/RecursiveRoleIteratorStrategyTest.php new file mode 100644 index 00000000000..2933b11fe87 --- /dev/null +++ b/vendor/zfr/rbac/tests/RbacTest/Traversal/Strategy/RecursiveRoleIteratorStrategyTest.php @@ -0,0 +1,36 @@ +<?php +/** + * Zend Framework (http://framework.zend.com/) + * + * @link http://github.com/zendframework/zf2 for the canonical source repository + * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com) + * @license http://framework.zend.com/license/new-bsd New BSD License + */ + +namespace RbacTest\Traversal\Strategy; + +use PHPUnit_Framework_TestCase as TestCase; +use Rbac\Role\Role; +use Rbac\Traversal\Strategy\RecursiveRoleIteratorStrategy; + +/** + * @covers Rbac\Traversal\Strategy\RecursiveRoleIteratorStrategy + * @group Coverage + */ +class RecursiveRoleIteratorStrategyTest extends TestCase +{ + /** + * @covers Rbac\Traversal\Strategy\RecursiveRoleIteratorStrategy::getRolesIterator + */ + public function testGetIterator() + { + $strategy = new RecursiveRoleIteratorStrategy; + $roles = [new Role('Foo'), new Role('Bar')]; + $iterator = $strategy->getRolesIterator($roles); + $innerIterator = $iterator->getInnerIterator(); + + $this->assertInstanceOf('RecursiveIteratorIterator', $iterator); + $this->assertInstanceOf('Rbac\Traversal\RecursiveRoleIterator', $innerIterator); + $this->assertEquals($roles, $innerIterator->getArrayCopy()); + } +} -- GitLab