You do not need a complex RBAC to restrict access for particular application area. For the most cases a simple role and permissions system is enough.
Open App\Enums\AdminPermissionEnum - see a list of segregated admin permissions Open App\Enums\AdminRoleEnum - see the list of possible admin roles. Note that each role defines a list of permissions available for it.
Open App\Gates\AdminPermission - see permissions check implementation. Open App\Providers\AuthServiceProvider - see a new gate defined per each admin permission.
Open App\Http\Controllers\Admin\AdminController - see permission check at constructor.
We could rewrite our gate definition in the way it accepts permission as argument. For example
<?php
use App\Gates\AdminPermission;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Gate;
class AuthServiceProvider extends ServiceProvider
{
public function boot()
{
$this->registerPolicies();
Gate::define('admin-permission', function (object $admin, $permission) {
return AdminPermission::check($admin, $permission);
});
}
}
In this case our controller will look like following:
<?php
use App\Enums\AdminPermissionEnum;
use App\Http\Controllers\Controller;
class AdminController extends Controller
{
public function __construct()
{
$this->authorize('admin-permission', [AdminPermissionEnum::ADMINS]);
}
// ...
}
In the first example a multiple gates were defined to simplify the code. Also, it allows permission checks via middleware. For example:
<?php
use App\Enums\AdminPermissionEnum;
Route::middleware('can:' . AdminPermissionEnum::ADMINS()->ability())->get('admins', AdminController::class . '@index');
The most common case for extra context in gate check is passing an Eloquent model instance. For example:
<?php
use App\Models\Article;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Gate;
class AuthServiceProvider extends ServiceProvider
{
public function boot()
{
$this->registerPolicies();
Gate::define('article-edit', function (object $user, Article $article) {
if ($article->author_id === $user->id) {
return true;
}
return false;
});
}
}
For the permission checks over entire CRUD policies are used.