
В данной заметке о том, как организовать простую систему работы с ролями пользователей.
Для этого нам придется внести всего одно изменение в базу данных, а именно - создать поле для хранения ролей в таблице с пользователями.
В сущность User добавляем роли в виде констант:
const ROLE_USER = 1; const ROLE_ADMIN = 10;Для примера тут всего 2 роли.
А так же добавим метод проверки текущего пользователя - админ он или нет:
public function isAdmin(): bool { return $this->role === self::ROLE_ADMIN; }Для всех новых ролей нужно создавать аналогичные методы.
Создаем миграцию:
php artisan make:migration AddUserRole
Содержимое класса меняем таким образом:
class AddUserRole extends Migration { public function up() { Schema::table('users', function (Blueprint $table) { $table->unsignedSmallInteger('role')->after('status'); }); DB::table('users')->update([ 'role' => User::ROLE_USER, ]); } public function down() { Schema::table('users', function (Blueprint $table) { $table->dropColumn('role'); }); } }Всем существующим на данный момент пользователям автоматически присваиваем роль простого пользователя.
Применяем миграцию:
php artisan migrate
В файле Providers/AuthServiceProvider.php прописываем нужные правила для существующих ролей.
Например у нас есть админка и нужно разрешить к ней доступ для ролей имеющих право с названием (например) «admin-panel»
public function boot() { $this->registerPolicies(); Gate::define('admin-panel', function (User $user) { return $user->isAdmin(); }); }
Осталось только применить данное правило. Это можно сделать по-разному. Т.к. правило в данном случае глобальное - ограничивает доступ ко всей админке, можно его прописать для группы маршрутов которая обслуживает админку.
routes/web.php
Route::group( [ 'prefix' => 'admin', 'middleware' => ['auth', 'can:admin-panel'], ], function () { // } );«auth» - алиас для посредника \App\Http\Middleware\Authenticate (прописанный в Http/Kernel.php). Он нужен для того, чтобы неавторизованного пользователя перенаправляло на страницу входа.
«can» - алиас для посредника \Illuminate\Auth\Middleware\Authorize который будет проверять права пользователей.
Через двоеточие передается параметр для посредника.
Аналогично можно прописать в нужном контроллере:
public function __construct(){ $this->middleware('can:admin-panel'); }
Можно прописать несколько прав через запятую:
'can:admin-panel,other'
Есть возможность передавать нужные для проверки данные при создании правила, например проверить является ли текущий пользователь автором данного поста или объявления:
Правило:
Gate::define('show-advert', function (User $user, Advert $advert) { return $user->isAdmin() || $user->isModerator() || $advert->user_id === $user->id; });
Проверка с передачей данных:
if (!Gate::allows('show-advert', $advert)) { abort(403); }
Может показаться лишним создание правил типа:
Gate::define('admin-panel', function (User $user) { return $user->isAdmin(); });если можно просто вставить такую проверку в нужное место:
if(!\Auth::user()->isAdmin()){ abort(403); }
Но это у нас только одна роль. А если ролей 3 или более, то проверка уже будет выглядеть так:
if(!(\Auth::user()->isAdmin() || \Auth::user()->isManager() || \Auth::user()->isModerator())){ abort(403); }Удобнее прописывать все проверки в отдельном файле и обращаться к ним с помощью посредников.