Jack Barham
Jack Barham

Reputation: 3219

Unable to get Policies working in Laravel 5.3

I've been following the Laravel Authorization docs trying to build "is the user allowed to do this" functionality by using Policies, but I can't get it to work. I keep getting This action is unauthorized and I've tried with route middleware too.

PagePolicy.php:

namespace App\Policies;

use App\Models\User;
use App\Models\Page;

use Illuminate\Auth\Access\HandlesAuthorization;

class PagePolicy
{
    use HandlesAuthorization;

    /**
     * Determine whether the user can view the page.
     *
     * @param  App\Models\User  $user
     * @param  App\Models\Page  $page
     * @return mixed
     */
    public function view(User $user, Page $page)
    {
        return $user->id === $page->user_id;
    }

    /**
     * Determine whether the user can create pages.
     *
     * @param  App\Models\User  $user
     * @return mixed
     */
    public function create(User $user)
    {

    }

    /**
     * Determine whether the user can update the page.
     *
     * @param  App\Models\User  $user
     * @param  App\Models\Page  $page
     * @return mixed
     */
    public function update(User $user, Page $page)
    {
        //
    }

    /**
     * Determine whether the user can delete the page.
     *
     * @param  App\Models\User  $user
     * @param  App\Models\Page  $page
     * @return mixed
     */
    public function delete(User $user, Page $page)
    {
        //
    }
}

PageController.php:

namespace App\Http\Controllers;

use Auth;
use Carbon\Carbon;

use App\Models\Page;

use App\Http\Requests\PageRequest;

class PageController extends ApiController
{
    public function createNewPage(PageRequest $request)
    {
        $this->authorize('create', Page::class);

        $request->merge([
            'user_id' => Auth::id(),
            'published_at' => Carbon::now(),
        ]);

        if (Page::create($request->all())) {
            return response()->json('success', 201);
        }

        return response()->json('error', 500);
    }

}

AuthServiceProvidor.php:

namespace App\Providers;

use App\Models\Page;
use App\Policies\PagePolicy;

use Illuminate\Support\Facades\Gate;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;

class AuthServiceProvider extends ServiceProvider
{
    /**
     * The policy mappings for the application.
     *
     * @var array
     */
    protected $policies = [
        Page::class => PagePolicy::class,
    ];

    /**
     * Register any authentication / authorization services.
     *
     * @return void
     */
    public function boot()
    {
        $this->registerPolicies();

        //
    }
}

Upvotes: 3

Views: 5809

Answers (4)

Darren Murphy
Darren Murphy

Reputation: 1164

Current code:

protected $policies = [
    Task::class => TaskPolicy::class,
];

Solution code:

protected $policies = [
    'App\Task' => 'App\Policies\TaskPolicy',
];

I experienced the same problem, while following the Intermediate Task List Tutorial on the Laravel website.

The solution is actually present in the Github code for this tutorial.

Upvotes: -2

Jack Barham
Jack Barham

Reputation: 3219

I managed to figure it out. I wasn't using Route Model Binding. So I added authorize() after the page call and used the $page variable instead of Page::class.

public function update(PageUpdateRequest $request, $pageSlug)
{
    $page = Page::where(['user_id' => Auth::id(), 'slug' => $pageSlug])->first();
    $this->authorize('update', $page);
    $page->update($request->all());
    return fractal()->item($page, new PageTransformer())->toArray();
}

Upvotes: 3

bytesandcaffeine
bytesandcaffeine

Reputation: 195

I think the problem is not in your policies, rather in your PageRequest class. Make sure the authorize() method in your App\Http\Requests\PageRequest class returns true .

class PageRequest extends FormRequest
{
    /**
    * Determine if the user is authorized to make this request.
    *
    * @return bool
    */
    public function authorize()
    {
        return true; // you can also check the authorization using PagePolicy here
    }
}

Upvotes: 0

alaric
alaric

Reputation: 987

It's not totally clear to me which action you're attempting to authorize since you've provided the call to create in the controller but only provided a policy check in place for viewing a page. Having said that, I would be sure to var_dump/dd the values you're attempting to do a type comparison of to verify they're of the same type. If anything's been explicitly cast, it may cause issues with certain database drivers that return integers as strings.

Upvotes: 1

Related Questions