Gislef
Gislef

Reputation: 1637

Dynamic Allow access to different permission rules - ACL LARAVEL

The admin user can view all posts on the homepage and access the update page for each post

 $gate->before(function(User $user, $ability)
    {
        if ($user->hasAnyRoles('adm') )
            return true;
    });

This is ok

But I do not know what I am doing wrong in the policies because other users can see all posts at home page but can not access the post update page that they have created, access is denied.

The permissions are dynamic, I have the tables in the DB:

Home Controller

<?php

namespace App\Http\Controllers;

use App\Http\Requests;
use Illuminate\Http\Request;
use App\Post;
use Gate;

class HomeController extends Controller
{
    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('auth');
    }

    /**
     * Show the application dashboard.
     *
     * @return \Illuminate\Http\Response
     */
    public function index(Post $post)
    {
       $posts = $post->all();
        return view('home', compact('posts'));
    }


    public function update($idPost)
    {
        $post = Post::find($idPost);


        if(Gate::denies('update-post', $post))
            abort(403);

        return view('update-post', compact('post'));
    }  

}

class AuthServiceProvider

<?php

namespace App\Providers;

use Illuminate\Contracts\Auth\Access\Gate as GateContract;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use App\Post;
use App\User;
use App\Permission;

class AuthServiceProvider extends ServiceProvider
{
    /**
     * The policy mappings for the application.
     *
     * @var array
     */
    protected $policies = [

    ];


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

        $permissions = Permission::with('roles')->get();
            foreach( $permissions as $permission)
            {
                $gate->define($permission->name, function(User $user) use ($permission){
                        return $user->hasPermission($permission);
                });
            }



        $gate->before(function(User $user, $ability)
        {
            if ($user->hasAnyRoles('adm') )
                return true;
        });

    }
}

model User

<?php

namespace App;

use Illuminate\Foundation\Auth\User as Authenticatable;
use App\Permission;

class User extends Authenticatable
{
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name', 'email', 'password',
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token',
    ];

    public function roles()
    {
        return $this->belongsToMany(\App\Role::class);
    }

    public function hasPermission(Permission $permission)
    {
        return $this->hasAnyRoles($permission->roles);
    }

    public function hasAnyRoles($roles)
    {
        if(is_array($roles) || is_object($roles)){
            foreach($roles as $role){
                return $roles->intersect($this->roles)->count();
            }
        }
        return $this->roles->contains('name', $roles);

    }
}

model Role

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Role extends Model
{
   public function permissions()
   {
       return $this->belongsToMany(\App\Permission::class);
   }
}

model Permission

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Permission extends Model
{
    public function roles()
    {
        return $this->belongsToMany(\App\Role::class);      
    }
}

view home.blade.php

@extends('layouts.app')

@section('content')
<div class="container">
    @forelse($posts as $post)
        @can('view_post', $post)
            <h2>{{$post->title}}</h2>
            <p>{{$post->description}}</p><br>
            <p>Autor: {{$post->user->name}}</p>
            <a href="{{url("/post/$post->id/update")}}">Editar</a>
        @endcan
        <hr>
    @empty
        <p>No posts registered</p>
    @endforelse
</div>
@endsection

view update-post.blade.php

@extends('layouts.app')

@section('content')
@can('edit_post', $post)
<div class="container">
        <h2>{{$post->title}}</h2>
        <p>{{$post->description}}</p><br>
        <p>Autor: {{$post->user->name}}</p>
@endcan
@endsection

Upvotes: 0

Views: 4347

Answers (1)

sandeep goel
sandeep goel

Reputation: 104

create a policy class:

php artisan make:policy PostPolicy --model=Post

than in your AuthServiceProvider register the policy:

 protected $policies = [
    Post::class => PostPolicy::class,
];

than in PostPolicy update method do this:

public function update(User $user, Post $post)
{
    return $user->id === $post->user_id;
}

you made a mistake in your home controller.

    if(Gate::denies('update-post', $post))
    {
        abort(403);
    }

or you can do the same in a single line:

$this->authorize('update-post', $post);

or using can middleware:

if ($user->can('update-post', $post)) {
return view('update-post', compact('post'));
}

Upvotes: 0

Related Questions