-
Notifications
You must be signed in to change notification settings - Fork 23
Refactor of internal role hierarchy model + changes for 3.0.0 #34
Refactor of internal role hierarchy model + changes for 3.0.0 #34
Conversation
@ezimuel just a quick question - are we not going to bump PHP requirements to version 7.1 with 3.0.0 release?? |
@webimpress yes, I'm removing the support for PHP 5.6 and PHP 7.0, thanks for the reminder. |
@webimpress fixed now, requiring PHP 7.1+. |
Ping @Ocramius, @webimpress for review. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ezimuel I've tried not to duplicate my comments, but basically what I've pointed should be applied across the whole PR. Also as we are using PHP 7.1 we should add strict type declarations for all files (can be done later on with other PHP 7.1 improvements, to keep this PR clear).
In general it looks good, I need to have another detailed look on functionality changes.
composer.json
Outdated
@@ -3,7 +3,7 @@ | |||
"description": "provides a role-based access control management", | |||
"license": "BSD-3-Clause", | |||
"keywords": [ | |||
"zf2", | |||
"zf3", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We stop using version with zf components, so I'd suggest to use only zf
and add please zendframework
(please see maintainers repository and templates there)
composer.json
Outdated
@@ -29,7 +29,7 @@ | |||
} | |||
}, | |||
"require-dev": { | |||
"phpunit/phpunit": "^5.7.15|| ^6.2.1", | |||
"phpunit/phpunit": "^6.4.4", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can switch to PHPUnit 7.0.1 as it supports only PHP 7.1+ !
doc/book/examples.md
Outdated
@@ -98,7 +98,7 @@ class AssertUserIdMatches implements AssertionInterface | |||
$this->article = $article; | |||
} | |||
|
|||
public function assert(Rbac $rbac) | |||
public function assert(Rbac $rbac, $permission = null, $role = null) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add some typehints? If these types are mixed could we please add PHPDocs about allowed types?
src/Assertion/CallbackAssertion.php
Outdated
* | ||
* @param Rbac $rbac | ||
* @return bool | ||
* {@inheritDoc} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment doesn't have any value, I would remove it.
src/Assertion/CallbackAssertion.php
Outdated
*/ | ||
public function assert(Rbac $rbac) | ||
public function assert(Rbac $rbac, string $permission = null, RoleInterface $role = null) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add also return type in function declaration, please?
src/Exception/RuntimeException.php
Outdated
* Zend Framework (http://framework.zend.com/) | ||
* | ||
* @link http://github.com/zendframework/zf2 for the canonical source repository | ||
* @copyright Copyright (c) 2005-2018 Zend Technologies USA Inc. (http://www.zend.com) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For new files we should use only current year.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where is this requirement defined?
src/Exception/RuntimeException.php
Outdated
/** | ||
* Zend Framework (http://framework.zend.com/) | ||
* | ||
* @link http://github.com/zendframework/zf2 for the canonical source repository |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be nice to update all headers to point to the repository (as we have in many others repos already, for example see any expressive repo)
src/Exception/RuntimeException.php
Outdated
* | ||
* @link http://github.com/zendframework/zf2 for the canonical source repository | ||
* @copyright Copyright (c) 2005-2018 Zend Technologies USA Inc. (http://www.zend.com) | ||
* @license http://framework.zend.com/license/new-bsd New BSD License |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The same here, this link doesn't even work....
src/Rbac.php
Outdated
* @return \Zend\Permissions\Rbac\Rbac | ||
*/ | ||
public function setCreateMissingRoles($createMissingRoles) | ||
public function setCreateMissingRoles(bool $createMissingRoles): Rbac |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are using single space before colon in return type declaration.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also as a return type I would use self
(it's clearer when you read class in the middle then we know straight away that we return the same class).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or we should drop the fluent interface altogether, as we have in other components, and return void
. (This comment applies to all setter methods that currently implement a fluent interface.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed fluent interface in all the library.
src/Rbac.php
Outdated
@@ -22,20 +25,19 @@ class Rbac extends AbstractIterator | |||
protected $createMissingRoles = false; | |||
|
|||
/** | |||
* @param bool $createMissingRoles | |||
* @param bool $createMissingRoles | |||
* @return \Zend\Permissions\Rbac\Rbac |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Imho this should be updated to return $this
Hi all, Thanks for including me in this conversation! As you can imagine, a lot has happened since I posted the original issue. I ended up developing my own solution, which, to be honest, I'm really happy with and having successfully used it for several months in production environment there is no real need for me to switch back to Zend RBAC. My solution literally consists of two classes - container and role - and supports adding roles by names and works around circular references. I posted the related files in this Gist in case anyone's interested to have a look. There's a Speaking about the PR - looks good to me at a glance. I like that the Other than that, I can only go by what @weierophinney says as he's the expert when it comes to framework standards. Sorry, if I'm not really being helpful :/ |
Maybe (unit) tests? 😉 |
@froschdesign You mean unit testing my implementation or |
@codeaid |
@codeaid thanks for sharing your code with us. It's always interesting to compare different solutions to the same problem. If this works for you that's great! Of course, as @froschdesign suggested unit test will help. I suggest to add it in your implementation to find issues before they will happens in production. Thanks again for your feedbacks! |
@froschdesign @ezimuel - Of course I have unit tests! How could you even assume otherwise!? :D I added them to the gist (if it helps). I believe they yield a 100% coverage too so I'm covered (pun intended). |
… improved code coverage
@webimpress, @weierophinney I incorporated all the feedbacks, including: |
Now we have 100% code coverage! |
Since it exists...
If a param or return annotation does not provide information beyond the typing and name already present in the signature, they are redundant.
- Adds a `callable` typehint to the `$callback` argument of the constructor. - Decorates the callback in a closure to ensure type safety when invoked; no more casting!
- Remove redundant `@param` and `@return` annotations. - Add descriptions for `@throws` annotations. - Remove unnecessary whitespace. - Add necessary whitespace. - Throw exceptions only from conditions.
- Removes redundant `@param` and `@return` annotations. - Corrects `@throws` annotations. - Adds whitespace where necessary. - Removes whitespace where necessary.
src/AssertionInterface.php
Outdated
*/ | ||
public function assert(Rbac $rbac); | ||
public function assert(Rbac $rbac, RoleInterface $role = null, string $permission = null) : bool; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm still not entirely convinced these arguments should be optional.
While I understand the argument of keeping BC breaks to a minimum, I also think we could address this in a new v2.X minor release by doing the following:
- Updating the
Rbac
class to pass the role and permission when calling an assertion. - Documenting in migration notes to users that they should add these arguments to their assertions in order to prepare for the v3 release. Their assertions can ignore them for now — or even update their logic to make use of them!
Taking those steps allows the v3 release to make these required, as they are always passed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@weierophinney ok, this plan sounds good to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In talking with @ezimuel today, we realized that for anybody implementing the AssertionInterface
, they will need to make a signature change when upgrading to version 3 regardless of any changes we'd make in the v2 release branch. As such, we will not do another v2 release, and move ahead instead with the v3 release.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only blocker at this point is a migration guide, as we already discussed, @ezimuel!
@weierophinney I wrote the migration guide, removed the optionals in AssertionInterface and fixed an issue on CHANGELOG. |
Adds a complete section on `RoleInterface` changes, incorporating the sections on `setParent` and `addChild` changes, and adding information on type hint changes, renaming of getParent to getParents, and addition of getChildren.
@ezimuel I've edited and expanded the migration document; I think this is good to go at this point! |
doc/book/methods.md
Outdated
|
||
## `Zend\Permissions\Rbac\Rbac` | ||
|
||
`Rbac` is the object with which you will interact within your application in | ||
order to query for permissions. It extends `AbstractIterator`. | ||
order to query for permissions. | ||
|
||
Method signature | Description | ||
--------------------------------------------------------------------------- | ----------- | ||
`addRole(string|RoleInterface $child, array|RoleInterface $parents = null)` | Add a role to the RBAC. If `$parents` is non-null, the `$child` is also added to any parents provided. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Backslash is required for pipe:
addRole(string\|RoleInterface $child, array\|RoleInterface $parents = null)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Problem is the rendering inside tables.
doc/book/methods.md
Outdated
|
||
Method signature | Description | ||
--------------------------------------------------------------------------- | ----------- | ||
`addRole(string|RoleInterface $child, array|RoleInterface $parents = null)` | Add a role to the RBAC. If `$parents` is non-null, the `$child` is also added to any parents provided. | ||
`getRole(string|RoleInterface $role) : RoleInterface` | Recursively queries the RBAC for the given role, returning it if found, and raising an exception otherwise. | ||
`getRole(string $role) : RoleInterface` | Get the role specified by name, raising an exception if not found. | ||
`hasRole(string|RoleInterface $role) : bool` | Recursively queries the RBAC for the given role, returning `true` if found, `false` otherwise. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here:
hasRole(string\|RoleInterface $role) : bool
doc/book/methods.md
Outdated
|
||
Method signature | Description | ||
--------------------------------------------------------------------------- | ----------- | ||
`addRole(string|RoleInterface $child, array|RoleInterface $parents = null)` | Add a role to the RBAC. If `$parents` is non-null, the `$child` is also added to any parents provided. | ||
`getRole(string|RoleInterface $role) : RoleInterface` | Recursively queries the RBAC for the given role, returning it if found, and raising an exception otherwise. | ||
`getRole(string $role) : RoleInterface` | Get the role specified by name, raising an exception if not found. | ||
`hasRole(string|RoleInterface $role) : bool` | Recursively queries the RBAC for the given role, returning `true` if found, `false` otherwise. | ||
`getCreateMissingRoles() : bool` | Retrieve the flag that determines whether or not `$parent` roles are added automatically if not present when calling `addRole()`. | ||
`setCreateMissingRoles(bool $flag) : void` | Set the flag that determines whether or not `$parent` roles are added automatically if not present when calling `addRole()`. | ||
`isGranted(string|RoleInterface $role, string $permission, $assert = null)` | Determine if the role has the given permission. If `$assert` is provided and either an `AssertInterface` instance or callable, it will be queried before checking against the given role. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here:
isGranted(string\|RoleInterface $role, string $permission, $assert = null)
@froschdesign I added the backslash for pipe in docs, as you suggested. Thanks! |
Thanks, @ezimuel - great improvement! Merged to develop. |
This PR contains a big refactoring of the role hierarchy model with minor changes in the APIs. This PR contains a potential 3.0.0 release for
zend-permissions-rbac
, containing BC breaks.This PR includes the following changes:
Added
Role::addChild()
andRole::addParent()
functions.Changed
Role::addChild(RoleInterface $child)
, accepts onlyRoleInterface
parameter, no string anymore.Role::addParent(RoleInterface $parent)
, accepts onlyRoleInterface
parameter, no string anymore.Zend\Permissions\Rbac\AssertionInterface
, added the optional parameters$permission
and$role
in theassert()
function, as follows:assert(Rbac $rbac, string $permission = null, RoleInterface $role = null)
Deprecated
Removed
AbstractIterator, removed the class. The role hierarchy is not based anymore on
RecursiveIterator
.AbstractRole, removed the class. All the functions have been moved in
Zend\Permissions\Rbac\Role
.Role::setParent()
, useRole::addParent()
instead.Fixed
Role::hasAncestor($role)
used inRole::addChild()
andRole::hasDescendant($role)
inRole::addParent()
.