• Час читання ~5 хв
  • 29.03.2023

При використанні Laravel Jetstream Teams типові ролі Jetstream можуть бути негнучкими для деякі потреби. Коли вам потрібні додаткові функції щодо управління ролями вашої команди, ви можете поєднати Laravel Jetstream з популярний пакет дозволів Spatie.

Приступаючи до роботи

, я припускаю, що у вас є свіжа установка Laravel Jetstream з увімкненою функцією teams, якщо ви не знаєте, як це зробити що, будь ласка, дотримуйтесь документації Laravel Jetstream.

У цьому прикладі я використовую стек Livewire, але оскільки я зосереджуюся на бекенд-речах, цей підручник повинен однаково працювати зі стеком «Інерція».

Встановлення пакета

дозволів Spatie Ми починаємо встановлювати пакет через композитора.

composer require spatie/laravel-permission

Тепер ми публікуємо файл міграції та дозволу.php конфігурації за допомогою:

php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider"

Тепер додайте рису дозволу Spatie HasRoles до своєї моделі користувача.

use Spatie\Permission\Traits\HasRoles;

class User extends Authenticatable
{
    use HasApiTokens;
    use HasFactory;
    use HasProfilePhoto;
    use HasTeams;
    use Notifiable;
    use TwoFactorAuthenticatable;
    use HasRoles;
}

Тепер нам потрібно ввімкнути функцію дозволів команди. В основному ми стежимо за Документація Spatie з деякими Налаштування jetstream.

Увімкніть конфігурацію дозволів команд:

// config/permission.php
'teams' => true,

Тепер нам потрібно додати проміжне програмне забезпечення, яке застосовує поточну область команди користувачів до пакету дозволів Spatie.

php artisan make:middleware TeamsPermission

У проміжному програмному забезпеченні TeamsPermission ми повинні витягти поточний ідентифікатор команди користувачів і застосувати його до дозволів Spatie Сфера застосування команди.

use Closure;
use Illuminate\Http\Request;
use Spatie\Permission\PermissionRegistrar;

class TeamsPermission
{
    public function handle(Request $request, Closure $next)
    {
        if (!empty($user = auth()->user()) && !empty($user->current_team_id)) {
            app(PermissionRegistrar::class)->setPermissionsTeamId($user->current_team_id);
        }

        return $next($request);
    }
}

Це проміжне програмне забезпечення має застосовуватися до кожного запиту HTTP, що надходить до нашого додатку. Для цього ми повинні розширити Ядро.php файл.

        //app/Http/Kernel.php
        'web' => [
            ...
            \App\Http\Middleware\TeamsPermission::class
        ],

У моєму випадку я не хочу, щоб це проміжне програмне забезпечення застосовувалося до запитів api, тому я додав його лише до "веб-" групи проміжного програмного забезпечення. Якщо ви хочете, щоб він застосовувався до всіх запитів, ви можете додати його до глобального стека проміжного програмного забезпечення.

Тепер загальне налаштування завершено, ми можемо почати грати з нашими новими командними ролями та дозволами.

Налаштування сідерів для демо-даних

Щоб погратися з нашою новою кодовою базою, нам потрібні деякі демо-дані. Давайте налаштуємо кілька швидких і брудних сівалок.

php artisan make:seeder PermissionSeeder

Початкові ролі та дозволи

//Database\Seeders\PermissionSeeder.php

namespace Database\Seeders;

use Illuminate\Database\Seeder;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\Models\Role;

class PermissionSeeder extends Seeder
{
    public function run(): void
    {
        //Some initially role configuration
        $roles = [
            'Admin' => [
                'view posts',
                'create posts',
                'update posts',
                'delete posts',
            ],
            'Editor' => [
                'view posts',
                'create posts',
                'update posts'
            ],
            'Member' => [
                'view posts'
            ]
        ];

        collect($roles)->each(function ($permissions, $role) {
            $role = Role::findOrCreate($role);
            collect($permissions)->each(function ($permission) use ($role) {
                $role->permissions()->save(Permission::findOrCreate($permission));
            });
        });
    }
}

Сідають демо-користувача з особистим та 3 іншими пов'язаними членством

//Database\Seeders\DatabaseSeeder.php
namespace Database\Seeders;

use App\Models\Team;
use App\Models\User;
use Illuminate\Database\Seeder;

class DatabaseSeeder extends Seeder
{
    public function run(): void
    {
        $this->call([PermissionSeeder::class]);

        User::factory(['email' => '[email protected]'])
            ->withPersonalTeam()
            ->hasAttached(Team::factory()->count(3))
            ->create();

    }
}

у команді Керуючі ролі у фронтенді

Я припускаю, що ви хочете показати користувачам поточні ролі у фронтенді, і ви хочете мати свого роду користувачів-адміністраторів, які можуть керувати ролями членів команди. Оскільки кодова база Jetstream зміниться в майбутньому, ми не будемо продовжувати дію за замовчуванням Для цього Jetstream керує ролями / діями членства в команді.

Тому я наведу кілька прикладів коду, як використовувати кілька ролей у командах Jetstream.

Оскільки кожен фронтенд-запит, що надходить до нашого додатку, обслуговується через наш \ App\Http\Middleware\TeamsPermission:: проміжне програмне забезпечення класу Пакет дозволів Spatie завжди в курсі поточної команди користувачів. Отже, кожна роль або Запит на дозвіл, який було викликано у фронтенді, обмежується поточним ідентифікатором команди користувачів.

Таким чином, ми можемо використовувати пакет дозволів Spatie, як зазвичай. Все просто працює, як і годиться!

//Get the user roles
auth()->user->roles()->get();
//Get the user permissions
auth()->user->permissions()->get();
//Give permission to a user
$role->givePermissionTo($permission);
//assign Roles
$permission->assignRole($role);

Керування ролями для API / Backend

Припустимо, що ми хочемо керувати командами ваших додатків на API. Як правило, ви хочете зробити це, коли інший зовнішній система або мікросервіс хоче оновити членів команди.

Для цього нам потрібен інвокований контролер API, який може оновлювати команди.

php artisan make:controller Api/UpdateTeamController -i

Для простоти ми не будемо створювати класи запитів і ресурсів для цього прикладу.

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\Team;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\Rule;
use Spatie\Permission\PermissionRegistrar;

class UpdateTeamController extends Controller
{
    public function __invoke(Request $request, Team $team): Team
    {
        $data = $request->validate([
            'name' => ['string', 'required', 'max:255'],
            'memberships' => ['array', 'sometimes'],
            'memberships.*.user_id' => ['required', 'integer', 'exists:users,id'],
            'memberships.*.roles' => ['present', 'array'],
            'memberships.*.roles.*' => ['string', Rule::exists('roles', 'name')->where('guard_name', 'web')]
        ]);

        DB::transaction(function () use (&$team, $data, $request) {
            //Update team fields
            $team->forceFill($request->except(['memberships']));
            $team->saveOrFail();

            if ($request->has('memberships')) {
                $memberships = collect($data['memberships']);
                //sync team memberships
                $team->users()->sync($memberships->map(function ($membership) {
                    return $membership['user_id'];
                })->toArray());
                //set Spatie permissions team foreign id scope
                app(PermissionRegistrar::class)->setPermissionsTeamId($team->id);
                //sync roles
                $memberships->each(function ($membership) {
                    $user = User::findOrFail($membership['user_id']);
                    $user->syncRoles($membership['roles']);
                });
            }

        });
        return $team;
    }
}

За допомогою цього коду контролер може оновлювати назви команд, членство в команді та ролі користувачів команди. Давайте розберемо це код на прості кроки:

Ми припускаємо, що отримуємо список користувачів з відповідною роллю для цієї конкретної команди. Ця інформація зберігається в масиві членства. Після перевірки введення запиту ми можемо почати оновлювати стан нашої бази даних.

При DB::transaction() цьому кожен запит бази даних, виконаний в рамках закриття, упаковується в базу даних. Якщо в закриття буде кинуто виняток, Laravel Framework відкочує всі наші зміни. Коли все працює нормально, Автоматично вносить зміни до бази даних.

В рамках транзакції ми починаємо оновлювати поля команди. Нічого особливого в цьому немає. Після цього обробляємо поля з масиву членства. Спочатку ми починаємо синхронізувати всі надані ідентифікатори користувачів з Команда Jetstream, що використовує метод sync() у відношенні

членства belongToMany(). Тепер ми переходимо до конкретних речей Spatie Laravel Permit:

Спочатку ми повинні повідомити пакет дозволів, в якому обсязі команди ми знаходимося app(PermissionRegistrar::class)->setPermissionsTeamId($team->id);. Таким чином, усі дозволи або ролі, які оновлюються або вибираються після цього рядка коду, завжди припадають на поточну команду Jetstream. У цьому випадку ми хочемо, щоб це була конкретна команда, надана за моделлю маршруту, прив'язка до нашого контролера. Але іноді ви хочете оновити дозволи для різних команд у циклі, тоді вам доведеться щоразу встановлювати цю область коли ви змінюєте відповідну область роботи групи.

Після зміни масштабу команди ми можемо оновити ролі, як зазвичай.

Наприкінці дії контролера ми повертаємо оновлений об'єкт Команди.

Заключні слова

Ми навчилися поєднувати команди Laravel Jetstream з чудовим пакетом дозволів Spatie. Завдяки чудовій документації з цих пакетів ми в основному стежимо за офіційними документами. Але я думаю, що ця стаття буде корисною, коли ви Почніть возитися з цими пакетами.

Весь вихідний код з цієї статті доступний на GitHub.

Comments

No comments yet
Yurij Finiv

Yurij Finiv

Full stack

Про мене

Professional Fullstack Developer with extensive experience in website and desktop application development. Proficient in a wide range of tools and technologies, including Bootstrap, Tailwind, HTML5, CSS3, PUG, JavaScript, Alpine.js, jQuery, PHP, MODX, and Node.js. Skilled in website development using Symfony, MODX, and Laravel. Experience: Contributed to the development and translation of MODX3 i...

Про автора CrazyBoy49z
WORK EXPERIENCE
Контакти
Ukraine, Lutsk
+380979856297