Reputation: 1637
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
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