Skip to content
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

Policy Extender and Tests #2461

Merged
merged 25 commits into from
Dec 9, 2020
Merged

Policy Extender and Tests #2461

merged 25 commits into from
Dec 9, 2020

Conversation

askvortsov1
Copy link
Sponsor Member

@askvortsov1 askvortsov1 commented Nov 22, 2020

Foundation for fixing #1832
Part of #1891

Please note that most of this diff is moving policy implementation content from the root folder of each service directory to an Access subfolder.

Changes proposed in this pull request:

  • Ask that policies return ->allow, ->deny, ->forceAllow, ->forceDeny instead of true/false to increase flexibility
  • Improve evaluation of whether a user has the ability to do something on an instance to avoid order-dependence.
  • Rename getPermission (->checkAbility)
  • Collect policies via a singleton in user extender
  • Move policy stuff into an Access sub-namespace
  • Add policy extender and integration tests
  • Deprecate old policy stuff

Reviewers should focus on:

Confirmed

  • Frontend changes: tested on a local Flarum installation.
  • Backend changes: tests are green (run composer test).

Required changes:

  • Related documentation PR: (Remove if irrelevant)
  • Related core extension PRs: (Remove if irrelevant)

Copy link
Member

@SychO9 SychO9 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just some minor comments

I think we should also mark the old AbstractPolicy class deprecated ? (nvm, we'd have to do that after deprecating ScopeModelVisibility event as well)

src/Extend/Policy.php Outdated Show resolved Hide resolved
src/User/Access/Gate.php Outdated Show resolved Hide resolved
src/User/Access/Gate.php Outdated Show resolved Hide resolved
src/User/UserServiceProvider.php Outdated Show resolved Hide resolved
src/User/UserServiceProvider.php Outdated Show resolved Hide resolved
src/Extend/Policy.php Outdated Show resolved Hide resolved
src/User/Access/AbstractPolicy.php Outdated Show resolved Hide resolved
Copy link
Member

@clarkwinkelmann clarkwinkelmann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good, I just can't figure out where the policy classes are resolved through the container.

Does it happen in User::setGate($this->app->makeWith(Access\Gate::class, ['policies' => $this->app->make('flarum.policies.compiled')])); ?

It would be ideal to only instantiate the class when interacting with that model.

@askvortsov1
Copy link
Sponsor Member Author

Looking good, I just can't figure out where the policy classes are resolved through the container.

Does it happen in User::setGate($this->app->makeWith(Access\Gate::class, ['policies' => $this->app->make('flarum.policies.compiled')])); ?

It would be ideal to only instantiate the class when interacting with that model.

It happens in $this->app->make('flarum.policies.compiled')

Copy link
Member

@SychO9 SychO9 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me!

Copy link
Member

@clarkwinkelmann clarkwinkelmann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still haven't been able to test locally, but the code looks good. A few things.

src/User/Access/Gate.php Show resolved Hide resolved
src/User/Access/Gate.php Show resolved Hide resolved
@askvortsov1
Copy link
Sponsor Member Author

askvortsov1 commented Dec 8, 2020

One other thought: do we want to support returning true instead of allow and false instead of deny? It would be a bit complex since we'd need to turn the former into the latter, but might make some cases easier. Alternatively, the allow and deny approach is more consistent with the other 2 options. We can't use true and false as the keys since PHP would convert those into integers, and then strict comparison fails

Copy link
Member

@clarkwinkelmann clarkwinkelmann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. Your changes solve the problem of delaying resolve, but not of selectively resolving.

Most of the time, one request will only interact with the polices for one model, so it would be best to not resolve all policies for all existing models in the application.

What about calling a new method around line 82 which takes the list of class names, and takes/stores instances from an array which is keyed by the class name and serves as a cache?

Could we maybe even use the container itself to store instances? We could check if Container::bound, then Container::make and Container::instance store the policy.

Or alternatively, in the extender, register every policy as a singleton, then just use make in the Gate.

Not sure which of the options is more performant if you end up with a large number of policies.

@clarkwinkelmann
Copy link
Member

Regarding the true and false returns, if it makes things more complicated for us, I don't think we need to support it.

I think allowing them might make things ambiguous, because what would they map to?

However it would probably be great to have an error message if you return anything that's not null or one of the allowed values from a policy method, otherwise things would just fail silently and it could be a debugging nightmare.

@askvortsov1
Copy link
Sponsor Member Author

Hmm, that makes sense. Making the policies singletons feels inefficient, but I see what you mean about resolving model by model. Will try that.

@luceos luceos added this to the 0.1.0-beta.15 milestone Dec 8, 2020
Copy link
Contributor

@tankerkiller125 tankerkiller125 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Testing locally via GUI attempting to break things everything went well. We'll for sure want QA to test the permission stuff more during that process. But overall I'm happy with the results.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants