Хочу разобрать случай когда нужно выставлять права определенному пользователю. Например, Вы разрабатываете CRM-систему у владельца компании есть сотрудники которые имеют доступ к системе и Вам необходимо чтобы несколько сотрудников выполняли разные функции или запретить экспорт базы данных клиентов.
Подготовка базы данных.
Создание миграции.
php artisan make:migration create_permissions_table --create=permissions
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreatePermissionsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('permissions', function (Blueprint $table) {
            $table->increments('id'); // идентификатор
            $table->string('name')->unique(); // имя на анг.
            $table->integer('parent'); // родитель
            $table->string('display_name')->nullable(); // Отображаемое имя
            $table->string('description')->nullable(); // описание
            $table->index('parent'); // присваиваемым индекс полю родитель
            $table->timestamps();
        });
        Schema::create('permission_user', function (Blueprint $table) {
            $table->integer('permission_id')->unsigned(); // id права
            $table->integer('user_id')->unsigned(); // id пользователя
            $table->foreign('permission_id')->references('id')->on('permissions') // устанавливаем зависимости полей
                ->onUpdate('cascade')->onDelete('cascade');
            $table->foreign('user_id')->references('id')->on('users')
                ->onUpdate('cascade')->onDelete('cascade');
            $table->primary(['permission_id', 'user_id']); // ключи
        });
    }
    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('permissions');
        Schema::dropIfExists('permission_user');
    }
}
Содержимое миграции.
Таблица «permissions» будет содержать набор прав пользователей, «permissions_user» права пользователя.
Выполняем миграцию php artisan migrate
Создаем модель.
php artisan make:model /Models/Permission
Содержимое модели ниже. Связь с таблицей пользователи многое ко многим.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Cookie;
class Permission extends Model
{
    protected $table = 'permissions';
    protected $fillable = [
        'name', 'parent', 'display_name', 'description'
    ];
    
    /**
     * Пользователи, которые принадлежат права.
     */
    public function users()
    {
        return $this->belongsToMany('App\Models\User', 'permission_user', 'permission_id', 'user_id');
    }
}
Seed.
Сразу же для удобства создадим наполнения БД начальными данными(seeding). Эти классы хранятся в app/database/seeds
Создадим файл PermissionsTableSeeder.php и записываем необходимый набор прав.
У меня такой получился такой набор.
<?php
use Illuminate\Database\Seeder;
use App\Models\Permission;
class PermissionTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        $permission = [
            /* client */
            [
                'name' => 'client-list',
                'parent_id' => '0',
                'display_name' => 'Просмотр клиента',
                'description' => ''
            ],
            /* master */
            [
                'name' => 'master-list',
                'parent_id' => '0',
                'display_name' => 'Просмотр мастеров',
                'description' => ''
            ],
            /* personal */
            [
                'name' => 'personal-list',
                'parent_id' => '0',
                'display_name' => 'Просмотр персонала',
                'description' => ''
            ],
            /* record */
            [
                'name' => 'record-list',
                'parent_id' => '0',
                'display_name' => 'Работа с записями',
                'description' => ''
            ],
            /* company */
            [
                'name' => 'company-list',
                'parent_id' => '0',
                'display_name' => 'Просмотр списка компаний',
                'description' => ''
            ],
            /* products */
            [
                'name' => 'product-management',
                'parent_id' => '0',
                'display_name' => 'Управление складом',
                'description' => ''
            ],
            /* metric */
            [
                'name' => 'metric-list',
                'parent_id' => '0',
                'display_name' => 'Просмотр статистики',
                'description' => ''
            ],
            [
                'name' => 'client-create',
                'parent_id' => '1',
                'display_name' => 'Создание новых клиентов',
                'description' => ''
            ],
            [
                'name' => 'client-edit',
                'parent_id' => '1',
                'display_name' => 'Изменение данных клиента',
                'description' => ''
            ],
            [
                'name' => 'client-copy',
                'parent_id' => '1',
                'display_name' => 'Выгрузка клиентской БД',
                'description' => ''
            ],
            [
                'name' => 'client-delete',
                'parent_id' => '1',
                'display_name' => 'Удаление клиента',
                'description' => ''
            ],
            /* master */
            [
                'name' => 'master-create',
                'parent_id' => '2',
                'display_name' => 'Создание мастера',
                'description' => ''
            ],
            [
                'name' => 'master-edit',
                'parent_id' => '2',
                'display_name' => 'Изменение данных мастера',
                'description' => ''
            ],
            [
                'name' => 'master-delete',
                'parent_id' => '2',
                'display_name' => 'Удаление мастера',
                'description' => ''
            ],
            /* personal */
            [
                'name' => 'personal-confirm',
                'parent_id' => '3',
                'display_name' => 'Подтвержать регистрацию',
                'description' => ''
            ],
            [
                'name' => 'personal-edit',
                'parent_id' => '3',
                'display_name' => 'Изменение данных персонала',
                'description' => ''
            ],
            [
                'name' => 'personal-delete',
                'parent_id' => '3',
                'display_name' => 'Удаление персонала',
                'description' => ''
            ],
            /* record */
            [
                'name' => 'record-delete',
                'parent_id' => '4',
                'display_name' => 'Удаление записей',
                'description' => ' '
            ],
            /* company */
            [
                'name' => 'company-create',
                'parent_id' => '5',
                'display_name' => 'Создание компании',
                'description' => ''
            ],
            [
                'name' => 'company-edit',
                'parent_id' => '5',
                'display_name' => 'Правка информации о компании',
                'description' => ''
            ],
            [
                'name' => 'company-delete',
                'parent_id' => '5',
                'display_name' => 'Удаление информации о компании',
                'description' => ''
            ],
            /* products */
            [
                'name' => 'product-category',
                'parent_id' => '6',
                'display_name' => 'Работа с категориями',
                'description' => ''
            ],
            [
                'name' => 'product-provider',
                'parent_id' => '6',
                'display_name' => 'Работа с поставщиками',
                'description' => ''
            ],
            [
                'name' => 'product-sale',
                'parent_id' => '6',
                'display_name' => 'Продажа товара',
                'description' => ''
            ],
            [
                'name' => 'product-history-sale',
                'parent_id' => '6',
                'display_name' => 'Просмотр истории продаж',
                'description' => ''
            ],
            [
                'name' => 'product-history',
                'parent_id' => '6',
                'display_name' => 'Просмотр истории',
                'description' => ''
            ],
            [
                'name' => 'product-delete',
                'parent_id' => '6',
                'display_name' => 'Удаление товаров',
                'description' => ''
            ]
        ];
        foreach ($permission as $key => $value) {
            Permission::create($value);
        }
    }
}
Запускаем сид php artisan db:seed —class=PermissionsTableSeeder
Теперь нужно написать проверку на наличие прав получения, название права и связь с таблицей прав.
В модели User.php
    /**
     * Проверка имеет ли пользователь определенную роль
     * @param $check
     * @return boolean
     */
    public function hasPermission($check)
    {
        return in_array($check, array_pluck($this->permissions->toArray(), 'name'));
    }
    /**
     * Получает название права
     * @param $name
     * @return mixed
     */
    public function getPermissionDisplayName($name)
    {
        return DB::table('permissions')->where('name', $name)->first()->display_name;
    }
    /**
     * Функция для получение прав.
     * @return boolean
     **/
    public function permissions()
    {
        return $this->belongsToMany('App\Models\Permission', 'permission_user', 'user_id', 'permission_id');
    }
Создание посредника.
Проверка прав у пользователей будет через посредника(middleware).
php artisan make:middleware PermissionMiddleware
<?php
namespace App\Http\Middleware;
use Closure;
class PermissionMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request $request
     * @param  \Closure $next
     * @param  $permission
     * @return mixed
     */
    public function handle($request, Closure $next, $permission)
    {
        if (!$request->user()->hasPermission($permission)) {
            $name = $request->user()->getPermissionDisplayName($permission);
            return redirect('/')->with('error', 'Не достаточно прав! Для операции: "' . $name . '"');
        }
        return $next($request);
    }
}
После создание посредника нужно зарегистрировать его. Переходим в файл Kernel.php и дописываем строку в массив $routeMiddleware
protected $routeMiddleware = [
         ***
        'permission' => \App\Http\Middleware\PermissionMiddleware::class,
         ***
    ];
Использование.
Теперь в роуторе можно использовать права. Например, для работы с клиентам.
/* Работа с клиентами */
Route::get('clients', ['as' => 'clients.index', 'uses' => 'ClientsController@index', 'middleware' => ['permission:client-list']]);
Route::post('clients/create', ['as' => 'clients.store', 'uses' => 'ClientsController@store', 'middleware' => ['permission:client-create']]);
Route::post('clients/create/ajax', ['as' => 'clients.store.ajax', 'uses' => 'ClientsController@storeAjax', 'middleware' => ['permission:client-create']]);
Route::get('clients/{id}', ['as' => 'clients.show', 'uses' => 'ClientsController@show', 'middleware' => ['permission:client-list']]);
Route::patch('clients/{id}', ['as' => 'clients.update', 'uses' => 'ClientsController@update', 'middleware' => ['permission:client-edit']]);
Route::delete('clients/{id}', ['as' => 'clients.destroy', 'uses' => 'ClientsController@destroy', 'middleware' => ['permission:client-delete']]);
Со стороны UI не охота было бы видеть кнопку удалить по которой нельзя нажать. Выход из этого такой.
Переходим в файл шаблона и прописываем такую конструкцию на кнопку или на любой другой элемент и если у пользователя есть права, то он увидит содержимое.
@if (Auth::user()->hasPermission('client-delete'))
// other code
@endif
По присваиванию прав будет отдельная статья. В ней будет использоваться jQuery плагин jsTree.
Если есть вопросы задавайте в комментарии