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

[5.5] prevent policies from being too greedy #19120

Merged
merged 1 commit into from
May 10, 2017
Merged

[5.5] prevent policies from being too greedy #19120

merged 1 commit into from
May 10, 2017

Conversation

browner12
Copy link
Contributor

this was originally sent to 5.4 (#19106) and Taylor asked me to switch to 5.5

Description:

Policies are too greedy, and will not defer to the gates if they do not have a method that matches the requested ability.

Steps To Reproduce:

Let's assume a App\Blog, and App\Policies\Blog.

namespace App\Policies;

class BlogPolicy
{
    /**
     * @return bool
     */
    public function update
    {
        return false;
    }
}

and the following AuthServiceProvider:

namespace App\Providers;

use Illuminate\Contracts\Auth\Access\Gate;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;

class AuthServiceProvider extends ServiceProvider
{
    /**
     * The policy mappings for the application.
     *
     * @var array
     */
    protected $policies = [
        \App\Blog::class => \App\Policies\BlogPolicy::class,
    ];

    /**
     * Register any authentication / authorization services.
     *
     * @param \Illuminate\Contracts\Auth\Access\Gate $gate
     */
    public function boot(Gate $gate)
    {
        //register policies
        $this->registerPolicies();

        //define additional ability
        $gate->define('update-blog', function ($user, $blog) {
            return true;
        });
    }
}

Currently if you tried to use this ability, you would get an AuthorizationException, because the method didn't exist and the Gate would return false.

namespace App\Http\Controllers;

use App\Blog;

class BlogController extends Controller
{
    /**
     * @return
     */
    public function update(Blog $blog)
    {
        $this->authorize('update-blog', $blog);
    }

This is because the Gate would see an App\Blog passed as the first argument, and try to resolve the callback from App\Policies\BlogPolicy.

Solution

This PR makes sure the ability/method is callable on the policy, otherwise falls through to let the gate check for a matching ability, and then finally defaults to return false.

All tests are passing, including an additional one for this situation.

- return `false` on `resolvePolicyCallback` if the ability/method is
not callable
- if no policy callback is found, allow the gate to try and resolve the
ability before defaulting to `false`.
- add test to make sure policies defer to the gate if method does not
exist on policy
- minor rename to other test to explicitly state the policy defaults to
false if the method does not exists **AND** the gate does not exist.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants