I am trying to authorize Users and Roles in such a way that each user cannot have access to another's id when it comes to Editing.
For example, if I enter the editing page for My Termins(Meetings)(in this case) http://localhost:8000/admin/termins/2/edit
do not be able to access any meeting ID of another user in which I did not create that termin.
So, when I manually type http://localhost:8000/admin/termins/1/edit
, I can't access it, showing a 403 error.
My current Controller:
public function edit($id)
{
$termin = Termin::findOrFail($id);
$this->authorize('edit', $termin);
Rest of code...
My policy:
<?php
// app/Policies/TerminPolicy.php
namespace App\Policies;
use App\User;
use App\Termin;
use Illuminate\Auth\Access\HandlesAuthorization;
class TerminPolicy
{
use HandlesAuthorization;
public function edit(User $user, Termin $termin)
{
\Log::info("User ID: {$user->id}, Created By ID: {$termin->created_by_id}");
return $user->id === $termin->created_by_id;
}
public function view(User $user, Termin $termin)
{
return $user->id === $termin->created_by_id;
}
}
AuthServiceProvider:
<?php
namespace App\Providers;
use App\Policies\TerminPolicy;
use App\Role;
use App\User;
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 = [
Termin::class => TerminPolicy::class,
];
/**
* Register any authentication / authorization services.
*
* @return void
*/
public function boot()
{
$this->registerPolicies();
$user = \Auth::user();
if (! app()->runningInConsole()) {
$roles = Role::with('permission')->get();
$permissionArray = [];
foreach ($roles as $role) {
foreach ($role->permission as $permission) {
$permissionArray[$permission->title][] = $role->id;
}
}
foreach ($permissionArray as $title => $roles) {
Gate::define($title, function (User $user) use ($roles) {
return count(array_intersect($user->role->pluck('id')->toArray(), $roles));
});
}
}
}
}
User Model:
public function role()
{
return $this->belongsToMany(Role::class, 'role_user');
}
Rest of code...
With this code, I always get error 403 This action is unauthorized
when entering the edit page from any user.
But, as I said, each user have to edit and see only their own Termin.
Thank you.
The easiest solution would be to create a relationship between users and termin and access termin via auth()->user(). That way if Termin doesn't belong to the user they won't be able to access it.
public function edit($id)
{
$termin = auth()->user()->termins()->findOrFail($id);
$this->authorize('edit', $termin);
//..Rest of the code
}
You already have created_by_id which stores user id so you could just define relationship like this
public function termins()
{
return $this->hasMany(Termin::class, 'created_by_id');
}
Since you already defined relationship between users and termins you can also replace your policy
class TerminPolicy
{
use HandlesAuthorization;
public function edit(User $user, Termin $termin)
{
return $user->termins->contains($termin);
}
public function view(User $user, Termin $termin)
{
return $user->termins->contains($termin);
}
}