diff --git a/.coveralls.yml b/.coveralls.yml new file mode 100644 index 0000000..2052335 --- /dev/null +++ b/.coveralls.yml @@ -0,0 +1 @@ +src_dir: library \ No newline at end of file diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..44042d3 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,30 @@ +language: php + +php: + - 5.4 + - 5.5 + - 5.6 + - hhvm + +branches: + only: + - master + - develop + +install: + - composer self-update + - composer install --dev --prefer-source + +before_script: + - mkdir -p build/coverage + +script: + - vendor/bin/phpunit + +after_script: + - php vendor/bin/coveralls + +matrix: + fast_finish: true + allow_failures: + - php: hhvm \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..12571ee --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,79 @@ +# Contributing + +Contributions to AclMan library are always welcomed and encouraged. + +You make our lives easier by sending us your contributions through github pull requests. + +* Coding standard for the project is [PSR-2](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md) + +* Any contribution must provide tests for additional introduced conditions + +## Team members + +The core team members are: + +| Name | Nickname | +|:---------------:|:------------------------------------:| +| Antonio Visalli | [visa4](http://github.com/visa4) | +| Leo Di Donato | [leodido](http://github.com/leodido) | +| Leonardo Grasso | [leogr](http://github.com/leogr) | + +## Got a question or problem? + +If you have questions about how to use AclMan library please write at . + +Other communication channels will be activated soon. In the mean time you can also contact us writing a [new issue](https://github.com/ripaclub/aclman/issues/new). + +Due to time constraints, we are not always able to respond as quickly as we would like. Please do not take delays personal and feel free to remind us. + +## New features + +You can request a new feature by submitting an issue to our github repository. If you would like to implement a new feature then consider what kind of change it is: + +* **Major changes** + + This kind of contribution should be discussed first with us in issues. This way we can better coordinate our efforts, prevent duplication of work, and help you to craft the change so that it is successfully accepted into the project. + +* **Small changes** + + Can be crafted and submitted to the github repository as a pull request. + +## Bug triage + +Bug triaging is managed via github [issues](https://github.com/ripaclub/aclman/issues). + +You can help report bugs by filing them [here](https://github.com/ripaclub/aclman/issues). + +Before submitting new bugs please verify that similar ones do not exists yet. This will help us to reduce the duplicates and the references between issues. + +Is desiderable that you provide reproducible behaviours attaching (failing) tests. + +## Testing + +The PHPUnit version to be used is the one installed as a dev-dependency via [composer](https://getcomposer.org/): + +```bash +$ ./vendor/bin/phpunit +``` + +## Contributing process + +What branch to issue the pull request against? + +For **new features**, or fixes that introduce **new elements to the public API** (such as new public methods or properties), issue the pull request against the `develop` branch. + +For **hotfixes** against the stable release, issue the pull request against the `master` branch. + +1. **Fork** the sphinxsearch [repository](https://github.com/ripaclub/aclman/fork) + +2. **Checkout** the forked repository + +3. Retrieve **dependencies** using [composer](https://getcomposer.org/) + +4. Create your **local branch**, **commit** your code and **push** your local branch to your github fork + +5. Send us a **pull request** as descripted for your changes to be included + +Please remember that **any contribution must provide tests** for additional introduced conditions. Accepted coverage for new contributions is 75%. Any contribution not satisfying this requirement won't be merged. + +Don't get discouraged! \ No newline at end of file diff --git a/README.md b/README.md index e69de29..0adbd30 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,203 @@ +ACL manager +=========== + +AclMan is a PHP library designed to manage access control list (ACL). + +| Branch | Build Status | Coverage | Dependencies | +|:-------------:|:-------------:|:-------------:|:-------------:| +|master|[![Build Status](https://travis-ci.org/ripaclub/aclman.svg?branch=master)](https://travis-ci.org/ripaclub/aclman) |[![Coverage Status](https://coveralls.io/repos/ripaclub/aclman/badge.png?branch=master)](https://coveralls.io/r/ripaclub/aclman)|[![Dependency Status](https://www.versioneye.com/user/projects/544efbb39fc4d5226e0000ec/badge.svg)](https://www.versioneye.com/user/projects/544efbb39fc4d5226e0000ec)| +|develop|[![Build Status](https://travis-ci.org/ripaclub/aclman.svg?branch=develop)](https://travis-ci.org/ripaclub/aclman)|[![Coverage Status](https://coveralls.io/repos/ripaclub/aclman/badge.png?branch=develop)](https://coveralls.io/r/ripaclub/aclman?branch=develop)|[![Dependency Status](https://www.versioneye.com/user/projects/544efb509fc4d5e91300017c/badge.svg)](https://www.versioneye.com/user/projects/544efb509fc4d5e91300017c)| + +Features +-------- + +AclMan has various features: + +* Assertions + + It provides an `AssertionPluginManager` whose goal is to deliver the assertions (i.e., `AssertionInterface` objects) + +* Permissions + + Contains a class, `GenericPermission`, that is a container of permission options (e.g., a role, a resource, a privilege, an assertion) + +* Resources and roles + + It provides a set of traits aimed to check the validity of resources and roles and instantiate their relative classes + +* Storages + + AclMan allows you to save the ACL configuration in several layers persistence, via `StorageInterface` objects and adapters (e.g., `ArrayAdapter`) + +* Services + + A set of classes aimed at the instantiation of ACL objects + +Installation +------------ + +Add `ripaclub/aclman` to your `composer.json`. + +``` +{ + "require": { + "ripaclub/aclman": "v0.1.0" + } +} +``` + +Configuration +------------- + +AclMan library has only two configuration nodes: + +1. `aclman_storage` to configure the persistence layer in which to save your ACL rules + +2. `aclman_services` to configure your services (e.g., a storage and optionally a plugin manager) + +Usage (1) +--------- + +So, here is an example of use. You first need to configure the factories. + +Put this PHP array into your configuration file. + +```php +'abstract_factories' => [ + 'AclMan\Service\ServiceFactory', + 'AclMan\Storage\StorageFactory' +], +'factories' => [ + 'AclMan\Assertion\AssertionManager' => 'AclMan\Assertion\AssertionManagerFactory' +] +``` + +Then we configure our service. + +```php +'aclman_services' => [ + 'AclService\Ex1' => [ + 'storage' => 'AclStorage\Ex1', + 'plugin_manager' => 'AclMan\Assertion\AssertionManager', + ], +] +``` + +Finally, our storage configuration. + +```php +'aclman_storage' => [ + 'AclStorage\Ex1' => [ + 'roles' => [ + 'Role1' => [ + 'resources' => [ + 'Resource1' => [ + [ + 'assert' => null, + 'allow' => true, + 'privilege' => 'add' + ] + ], + 'Resource2' => [ + [ + 'assert' => null, + 'allow' => true, + 'privilege' => 'view' + ] + ] + ], + ], + ], + ], +] +``` + +Our first ACL configuration is now complete. Use it: + +```php +$aclService1 = $serviceLocator->get('AclService\Ex1'); +$aclService1->isAllowed('Role1', 'Resource1', 'view'); // FALSE +$aclService1->isAllowed('Role1', 'Resource1', 'add'); // TRUE +// ... +``` + +Usage (2) +--------- + +Now we see how to modify the previous example in order to use the `AssertionManager`. + +We can do it in two ways: (1) create an assertion plugin manager or (2) fetch the provided `AssertionPluginManager` and add our assertions. + +We suggest you to create your own assertion plugin manager (1). For example: + +```php +namespace Ex1; +class OurAssertionPluginManager extends AbstractPluginManager +{ + protected $invokableClasses = [ + 'assertFalse' => 'Ex1\Assertion\Assertion1', + 'assertTrue' => 'Ex1\Assertion\Assertion2', + ]; + + public function validatePlugin($plugin) + { + if ($plugin instanceof AssertionInterface) { + return; + } + throw new \Exception(sprintf( + 'Plugin of type "%s" is invalid; must implement Zend\Permissions\Acl\Assertion\AssertionInterface', + (is_object($plugin) ? get_class($plugin) : gettype($plugin)) + )); + } +} +``` + +Now we need to register it in the service manager to load our assertion plugin manager. + +```php +'invokables' => [ + 'AclMan\Plugin\Manager' => 'Ex1\OurAssertionPluginManager' +] +``` + +Finally we can use our new assertions (see `(*)` in the comments) to configure roles: + +```php +'aclman_storage' => [ + 'AclStorage\Ex1' => [ + 'roles' => [ + 'Role1' => [ + 'resources' => [ + 'Resource1' => [ + [ + 'assert' => 'assertTrue', // (*) + 'allow' => true, + 'privilege' => 'add' + ] + ], + 'Resource2' => [ + [ + 'assert' => 'assertFalse', // (*) + 'allow' => true, + 'privilege' => 'view' + ] + ] + ], + ], + ], + ], +] +``` + +Notice the behaviour ... + +```php +$aclService1 = $serviceLocator->get('AclService\Ex1'); +$aclService1->isAllowed('Role1', 'Resource1', 'add'); // TRUE +$aclService1->isAllowed('Role1', 'Resource2', 'view'); // FALSE +// ... +``` + +--- + +[![Analytics](https://ga-beacon.appspot.com/UA-49655829-1/ripaclub/aclman)](https://github.com/igrigorik/ga-beacon) diff --git a/composer.json b/composer.json index 2c65036..bf46f40 100644 --- a/composer.json +++ b/composer.json @@ -10,7 +10,8 @@ }, "require-dev": { "phpunit/phpunit": "~4.2", - "zendframework/zend-mvc": "~2.3" + "zendframework/zend-mvc": "~2.3", + "satooshi/php-coveralls": "dev-master" }, "authors": [ { diff --git a/library/Resource/ResourceCheckTrait.php b/library/Resource/ResourceCheckTrait.php index 00a1709..2c09411 100644 --- a/library/Resource/ResourceCheckTrait.php +++ b/library/Resource/ResourceCheckTrait.php @@ -18,7 +18,7 @@ trait ResourceCheckTrait { /** - * @param $resource + * @param string|ResourceInterface $resource * @return GenericResource * @throws InvalidParameterException */ diff --git a/library/Role/RoleCheckTrait.php b/library/Role/RoleCheckTrait.php index 79fdb6a..ada5998 100644 --- a/library/Role/RoleCheckTrait.php +++ b/library/Role/RoleCheckTrait.php @@ -18,7 +18,7 @@ trait RoleCheckTrait { /** - * @param $role + * @param string|RoleInterface $role * @return GenericRole * @throws InvalidParameterException */ diff --git a/library/Service/ServiceFactory.php b/library/Service/ServiceFactory.php index a368e60..be26ace 100644 --- a/library/Service/ServiceFactory.php +++ b/library/Service/ServiceFactory.php @@ -23,7 +23,7 @@ class ServiceFactory implements AbstractFactoryInterface * Config Key * @var string */ - protected $configKey = 'alcManServices'; + protected $configKey = 'aclman_services'; /** * Default service class name @@ -61,9 +61,9 @@ public function canCreateServiceWithName(ServiceLocatorInterface $serviceLocator is_string($config[$requestedName]['storage']) && $serviceLocator->has($config[$requestedName]['storage']) && // Check Storage - isset($config[$requestedName]['pluginManager']) && - is_string($config[$requestedName]['pluginManager']) && - $serviceLocator->has($config[$requestedName]['pluginManager']) + isset($config[$requestedName]['plugin_manager']) && + is_string($config[$requestedName]['plugin_manager']) && + $serviceLocator->has($config[$requestedName]['plugin_manager']) ); } @@ -92,7 +92,7 @@ public function createServiceWithName(ServiceLocatorInterface $serviceLocator, $ )); } // PluginManager - $pluginManager = $serviceLocator->get($config['pluginManager']); + $pluginManager = $serviceLocator->get($config['plugin_manager']); // Config Service $acl = new Acl(); @@ -101,8 +101,8 @@ public function createServiceWithName(ServiceLocatorInterface $serviceLocator, $ $service->setAcl($acl); $service->setPluginManager($pluginManager); - if (isset($config['allowNotFoundResource'])) { - $service->setAllowNotFoundResource($config['allowNotFoundResource']); + if (isset($config['allow_not_found_resource'])) { + $service->setAllowNotFoundResource($config['allow_not_found_resource']); } return $service; diff --git a/tests/Integration/Service/ServiceAbstractTest.php b/tests/Integration/Service/ServiceAbstractTest.php index 8447aad..1b5e598 100644 --- a/tests/Integration/Service/ServiceAbstractTest.php +++ b/tests/Integration/Service/ServiceAbstractTest.php @@ -84,10 +84,10 @@ public function setUp() ] ] ], - 'alcManServices' => [ + 'aclman_services' => [ 'AclService' => [ 'storage' => 'AclStorage', - 'pluginManager' => 'assertManager', + 'plugin_manager' => 'assertManager', ], ] ]; diff --git a/tests/Service/ServiceFactoryTest.php b/tests/Service/ServiceFactoryTest.php index 01b91b3..5d9c45b 100644 --- a/tests/Service/ServiceFactoryTest.php +++ b/tests/Service/ServiceFactoryTest.php @@ -26,11 +26,11 @@ class ServiceFactoryTest extends AclManTestCase public function setUp() { $config = [ - 'alcManServices' => [ + 'aclman_services' => [ 'AclService' => [ 'storage' => 'ArrayStorage1', - 'pluginManager' => 'PluginManager', - 'allowNotFoundResource' => true + 'plugin_manager' => 'PluginManager', + 'allow_not_found_resource' => true ], 'AclService1' => [], ], @@ -66,11 +66,11 @@ public function testCreateServiceShouldThrowServiceNotCreatedExceptionWhenStorag $sm->setService( 'Config', [ - 'alcManServices' => [ + 'aclman_services' => [ 'AclService' => [ 'storage' => 'InvalidStorage', - 'pluginManager' => 'PluginManager', - 'allowNotFoundResource' => true + 'plugin_manager' => 'PluginManager', + 'allow_not_found_resource' => true ], 'AclService1' => [], ]