-
-
Notifications
You must be signed in to change notification settings - Fork 842
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactoring Policies #2092
Comments
Franz and I had a very productive conversation about this today, here are my takeaways: What I'm Proposing
Policies
Policy Implementation
Scope Model Visibility
Concerns
|
Will this refactoring also remove the semi hardcoded admin users? Eg "admin" currently isn't even a specified permission, whether a user is an admin is based on whether they are part of the group with ID 1. This also applies to the Moderator group, which (I'm not sure) should not even have any value across our codebase, see User: /**
* Check whether or not the user is an administrator.
*
* @return bool
*/
public function isAdmin()
{
return $this->groups->contains(Group::ADMINISTRATOR_ID);
} Group /**
* The ID of the administrator group.
*/
const ADMINISTRATOR_ID = 1;
/**
* The ID of the guest group.
*/
const GUEST_ID = 2;
/**
* The ID of the member group.
*/
const MEMBER_ID = 3;
/**
* The ID of the mod group.
*/
const MODERATOR_ID = 4; |
So right now, the permission system has, essentially 4 layers, checked in the following order.
My proposed changes to the actual process are:
So no, this wouldn't cause any issues in the area you addressed. |
I've also been thinking about how we could do proper namespacing, and I think I have an idea that could massively increase flexibility. @tankerkiller125 and I discussed policies and how they could be improved a few days ago, and I think this goes a bit closer to fulfilling some of his ideas. What if we stored the policies, after they are registered, in a prefix tree? This means that:
This would even further increase flexibility and allow for elegant organization (and lookup!) of really really complex permission systems. If that's fine with us, the only other major issue to consider is whether we'd want to go all out, and require a callable (class/function) for every individual permission (essentially splitting up the policy classes into many separate classes/functions). This could have merit, but also could be messy. Personally, I think that grouping them together but namespacing properly is the better option here, but I'm not set in that opinion. |
Another interesting question is how this should play into any possible future expansions we want to make to extension permissioning, and/or a group rewrite. Tags, for instance, introduces a new 'permission key' per-tag iirc. Is that something we'd like to fit into the standard namespacing system, or perhaps add another delimiter to the permission keys? |
Issue that was raised in developer call: Do we want to have policy/permissions inheritance? Perhaps higher namespaced policies could only be applied if no lower-namespaced policies exist? Should this be mirrored in permissions (if group has user.edit, group would have user.edit.username, user.edit.groups, etc)? |
On second thought, instead of automatic inheritance, I think we might want to allow wildcard suffixes (and probably suffixes only: no wildcards on empty strings, and no wildcards with stuff after them) instead. |
Fixed in #2461 |
Functionality Discussion
Is your feature request related to a problem? Please describe.
Policies are currently designed in a way that is confusing, and does not work well with our proposed extenders system, as ScopeModelVisibility depends on a non-domain event.
I've started on some of these in #2056.
Describe the solution you'd like
There's a lot of components to this, but I would propose the following:
Split off visibility scoping into a second abstract class from AbstractPolicy. The way I see it, AbstractPolicy applies to whether or not a user has a permission on a given instance/class of a model. ScopeModelVisibility restricts a query to records that a user can see, optionally based off of some action. It seems like these 2 were grouped together for sake of convenience, but similar methods (
->view()
vs->find()
), support for custom methods (based on the permission in question), and significant differences in functionality make this a suboptimal design IMO.in AbstractPolicy, rename
getPermission
tocanPerform
, or similar. Permissions are something concrete that are attached to groups and stored in the database. Policy checks allow logic to determine whether a user can perform a somewhat more abstract action, such asview
,edit
, or something custom likeoverrideAdminSettings
(made that one up but it's possible to implement).canPerform
would be more descriptive, or something likecanPerformActionOnInstance
(although that one is clunky).Rename pretty much everything on the new ScopeModelVisibility-related abstract class. I don't like
find
, because it's not a searching sysgtem, and it's not looking for individual instances. I'd prefer that devs, when extending the abstract model, define:find
, this scopes a query for viewingfindACTION_NAME
, where a different method is defined for each action. I think these should be consolidated into one method, where the action is provided with a string, then devs could conditionally apply filters depending on the action in question. Alternatively,$this->scopeQueryForACTION_NAME
could also work.Move AbstractPolicy away from events in implementation. One serious issue with the current implementation can be found here: Replacement options for dispatcher->until() #2091. A potential fix could be found here: WIP Policy Refactor, Extender #2056
Move AbstractQueryVisibilityScoper away from events in implementation. This removed yet another non-domain event, which is part of our path to stable. I propose the following:
The text was updated successfully, but these errors were encountered: