Laravel-permissionを使ってみよう

目次

メソッド一覧

Laravel-permission パッケージは、ロールとパーミッションの管理に関連する多くの便利なメソッドを提供します。以下に、よく使われる主要なメソッドをいくつか紹介します。

STEP

ロール関連のメソッド

ロールの作成

use Spatie\Permission\Models\Role;

$role = Role::create(['name' => 'role_name']);

ロールの割り当て

$user->assignRole('role_name');

ロールの削除

$user->removeRole('role_name');

ユーザーが特定のロールを持っているか確認

$user->hasRole('role_name');

すべてのロールの取得

$roles = Role::all();
STEP

パーミッション関連のメソッド

パーミッションの作成

use Spatie\Permission\Models\Permission;

$permission = Permission::create(['name' => 'permission_name']);

パーミッションの割り当て

$user->givePermissionTo('permission_name');
$role->givePermissionTo('permission_name');

パーミッションの削除

$user->revokePermissionTo('permission_name');
$role->revokePermissionTo('permission_name');

ユーザーが特定のパーミッションを持っているか確認

$user->hasPermissionTo('permission_name');

すべてのパーミッションの取得

$permissions = Permission::all();
STEP

ロールとパーミッションの同期

ロールの同期

$user->syncRoles(['role1', 'role2']);

ロールの同期

$user->syncPermissions(['permission1', 'permission2']);
$role->syncPermissions(['permission1', 'permission2']);

ロールとパーミッションの種類

これらは一般的なウェブアプリケーションやシステムにおける典型的なロールと権限の構造を考えてみましょう。

STEP

ロールと権限

  1. Super Admin
    • 権限: システム全体の管理と設定、すべてのユーザーとロールの管理。
    • アクション: ユーザーの追加・削除、ロールの作成・変更、システム設定の変更。
  2. Admin
    • 権限: ユーザーの管理、一部のシステム設定の変更。
    • アクション: ユーザーの追加・削除、ロールの割り当て。
  3. Director
    • 権限: チームの管理、ユーザーの管理。
    • アクション: チームの作成、削除、ユーザーの追加、削除。
  4. Moderator
    • 権限: コメントやフォーラムの管理。
    • アクション: コメントの承認・削除、ユーザー投稿のモデレーション。
  5. Manager
    • 権限: 特定部門またはチームの管理。
    • アクション: 部門内のユーザー管理、レポートの閲覧。
  6. Editor
    • 権限: コンテンツの作成、編集、公開。
    • アクション: 記事やブログの作成・編集、公開。
  7. Author
    • 権限: 自身のコンテンツの作成と編集。
    • アクション: 自分の記事の作成・編集。
  8. User
    • 権限: システムの基本的な使用。
    • アクション: プロフィールの編集、コメントの投稿。
  9. Guest
    • 権限: 閲覧のみ。
    • アクション: コンテンツの閲覧。
  10. Banned
    • 権限: アクセス制限されたユーザー。
    • アクション: 限定的な閲覧のみ、ログイン不可。
STEP

パーミッションの種類

パーミッションは、アプリケーション内で行える特定のアクションや操作に対するアクセス権を定義します。以下は一般的なパーミッションの種類の例です。

  1. CRUD操作:
    • create、read、update、delete(例: create posts、edit users)
  2. 管理機能:
    • manage users、mange roles、manage settings
  3. 特定の機能の使用:
    • access dashboard、publish articles、moderate comments
  4. リソース特有の操作:
    • edit own profile、delete own comments

AdminControllerでロールとパーミッションの作成

それでは、実際にAdminControllerを作成して、ロールとパーミッションを作成してみましょう。

STEP

AdminControllerの作成

php artisan make:controller AdminController
STEP

ルートグループの作成

ルートをグループ化して、共通の属性やミドルウェアをグループ全体に適用できるようにします。

use App\Http\Controllers\AdminController;
use Illuminate\Support\Facades\Route;

// Admin関連のルートをグループ化
Route::prefix('admin')->name('admin.')->middleware(['auth', 'role:admin'])->group(function () {
    Route::get('/dashboard', [AdminController::class, 'dashboard'])->name('dashboard');
    // その他のAdminControllerのアクションへのルートをここに追加
});
  • prefix(‘admin’): このグループ内のすべてのルートに /adminプレフィックスを追加します。例えば、/admin/dashboardのようになります。
  • name(‘admin.’): このグループ内のすべてのルートに admin. という名前のプレフィックスを付けます。これにより、ルート名が admin.dashboardのようになります。
  • middleware([‘auth’, ‘role:admin’]): このグループ内のすべてのルートに authと role:admin ミドルウェアを適用します。これにより、認証された adminロールのユーザーのみがアクセスできるようになります。
  • group(function() {…}): グループ内に AdminControllerの各アクションに対応するルートを定義します。例えば、ダッシュボードへのアクセス、ユーザー管理、ロール管理などです。

他の管理機能に対するルートも同様に、このグループ内に追加できます。例えば、ユーザーの一覧や編集フォームへのルートなどです。

この方法により、AdminControllerのルートを効率的に管理し、適切な権限チェックを行うことができます。また、将来的に新しい管理機能を追加する際も、このグループに新しいルートを追加するだけで済みます。

STEP

初期設定

まず最初に、シーダーを使ってadminロールと初期ユーザーを作成します。

シーダーファイルの作成

まず、シーダーファイルを作成します。これはArtisanコマンドを使用して行います。

php artisan make:seeder AdminUserSeeder

シーダーファイルの編集

次に、AdminUserSeeder.phpを編集して、adminロールと初期ユーザーを作成するロジックを追加します。

database/seeders/AdminUserSeeder.php
<?php

namespace Database\Seeders;

use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\Hash;
use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;
use App\Models\User;
use App\Models\Team; // 必要ならインポート

class AdminUserSeeder extends Seeder
{
    public function run()
    {
        // Super Admin ロールの作成
        $superAdminRole = Role::create(['name' => 'super-admin']);
        // Admin ロールの作成
        $adminRole = Role::create(['name' => 'admin']);

        // パーミッションの作成
        $manageEverythingPermission = Permission::create(['name' => 'manage everything']);
        $superAdminRole->givePermissionTo($manageEverythingPermission);
        // 必要に応じて Admin ロールに別のパーミッションを割り当てる

        // 初期ユーザーの作成
        $user = User::create([
            'name' => 'SuperAdmin User',
            'email' => 'admin@example.com',
            'password' => Hash::make('password')
            'email_verified_at' => now(), // 現在の時刻を設定
        ]);

        // ユーザーに両方のロールを割り当てる
        $user->assignRole($superAdminRole, $adminRole);
        
        // パーソナルチームの作成
        $team = Team::create([
            'user_id' => $user->id,
            'name' => $user->name . "'s Team",
            'personal_team' => true,
        ]);

        // ユーザーにチームを割り当てる
        $user->current_team_id = $team->id;
        $user->save();
    }
}
  • 16〜19行目:初期ユーザーには、SurperAdminロールとAdminロールの両方を付与しておきます。
  • 基本的に、Adminユーザーで管理は行いますが、ロールの作成や管理やSuperAdminに任せます。
  • 31行目:初期ユーザーにはEmail認証は不要なので、設定
  • 37行目〜46行目は、JetStreamのTeam機能を使用している場合は必要ですが、Team機能を使用していない場合は不要です。

データベースシーダーの実行

php artisan db:seed --class=AdminUserSeeder

このコマンドは、AdminUserSeederで定義したロールとユーザーをデータベースに挿入します。

STEP

メソッドの作成

AdminControllerにいくつかのメソッドを作成してみたいと思います。

コンストラクタの作成

public function __construct()
{
    // ロールやパーミッションの作成は、SuperAdminのみ
    $this->middleware('role:super-admin')->only('create');
}

indexメソッドの作成

public function index()
{
    $roles = Role::all();
    $permissions = Permission::all();

    // ビューに変数を渡す
    return view('admin.index', ['roles' => $roles, 'permissions' => $permissions]);
}

createメソッドの作成

下記で、ロールを作成するcreateメソッドを作成します。このロールはSuperAdminのみが実行できます。

app/Http/Controllers/AdminController.php
// ロールまたはパーミッションの作成
public function create(Request $request)
{
    $name = $request->input('name');
    $type = $request->input('type'); // 'role' または 'permission'

    if ($type == 'role') {
        $role = Role::create(['name' => $name]);
    } elseif ($type == 'permission') {
        $permission = Permission::create(['name' => $name]);
    }

    // 成功メッセージ
    return redirect()->back()->with('success', ucfirst($type) . ' を作成しました。');
}

AdminControllerに一覧表示のためのindexメソッドを作成しておきます(今回はここからロールやパーミッションを作成します)。

STEP

ビューの作成

index.balde.phpビューを下記のように作成します。

resources/views/admin/index.blade.php
@extends('layouts.admin')

@section('title', '管理者ページ')

@section('content')
    <div class="flex justify-between items-center">
        <h1 class="text-3xl font-bold">管理者ページ</h1>
        <a href="{{ route('logout') }}" class="text-sm text-gray-500 hover:text-gray-700 underline">ログアウト</a>
    </div>

    <div class="mt-8">
        @role('super-admin')
        <h2 class="text-xl font-bold">ロールまたはパーミッションの作成</h2>
        <form action="{{ route('admin.create') }}" method="POST" class="mt-4">
            @csrf
            <div class="flex flex-col">
                <label for="name" class="text-sm text-gray-500">名前</label>
                <input type="text" name="name" id="name" class="mt-2 px-4 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent">

                <div class="mt-4">
                    <label>
                        <input type="radio" name="type" value="role">
                        ロール
                    </label>
                    <label class="ml-4">
                        <input type="radio" name="type" value="permission">
                        パーミッション
                    </label>
                </div>
            </div>
            <div class="mt-4">
                <button type="submit" class="px-4 py-2 bg-blue-500 text-white rounded-md hover:bg-blue-600 focus:outline-none">作成</button>
            </div>
        </form>
        @endrole
    </div>

    <div class="flex flex-wrap mt-8">
        <!-- 既存のロールの表示 -->
        <div class="w-1/2 pr-4">
            <h2 class="text-xl font-bold">ロール一覧</h2>
            <ul>
                @foreach ($roles as $role)
                    <li>{{ $role->name }}</li>
                @endforeach
            </ul>
        </div>

        <!-- 既存のパーミッションの表示 -->
        <div class="w-1/2 pl-4">
            <h2 class="text-xl font-bold">パーミッション一覧</h2>
            <ul>
                @foreach ($permissions as $permission)
                    <li>{{ $permission->name }}</li>
                @endforeach
            </ul>
        </div>
    </div>
@endsection
STEP

エラー処理

Target class [role] does not exist.

下記のようなエラーが表示されました。

Spatie Laravel-permission パッケージのミドルウェア登録

Kernel.phpを確認したら、MiddleWearに登録されていない模様です。下記のように追加します。

app/Http/Kernel.php
protected $middlewareAliases = [
    // 他のエイリアス
    'role' => \Spatie\Permission\Middleware\RoleMiddleware::class,
        'permission' => \Spatie\Permission\Middleware\PermissionMiddleware::class,
        'role_or_permission' => \Spatie\Permission\Middleware\RoleOrPermissionMiddleware::class,
];
STEP

ルーターの修正

web.phpを下記のように修正します。

routes/web.php
Route::prefix('admin')->name('admin.')->middleware(['auth', 'role:admin'])->group(function () {
    Route::get('/', [AdminController::class, 'index'])->name('index');
    Route::post('/create', [AdminController::class, 'create'])->name('create');
    Route::get('/create-user', [AdminController::class, 'createUser'])->name('createUser');
    Route::post('/store-user', [AdminController::class, 'storeUser'])->name('storeUser');
});
STEP

AdminControllerの全コード

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;
use App\Models\User;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Mail;
use App\Mail\TestMail;

class AdminController extends Controller
{
    public function __construct()
    {
        // ロールとパーミッションの作成は、super-admin ロールを持つユーザーのみが実行できる
        $this->middleware('role:super-admin')->only('create');
    }

    public function index()
    {
        $roles = Role::all();
        $permissions = Permission::all();

        // ビューに変数を渡す
        return view('admin.index', ['roles' => $roles, 'permissions' => $permissions]);
    }

    // ロールまたはパーミッションの作成
    public function create(Request $request)
    {
        $name = $request->input('name');
        $type = $request->input('type'); // 'role' または 'permission'

        if ($type == 'role') {
            $role = Role::create(['name' => $name]);
        } elseif ($type == 'permission') {
            $permission = Permission::create(['name' => $name]);
        }

        // 成功メッセージ
        return redirect()->back()->with('success', ucfirst($type) . ' を作成しました。');
    }

    // ユーザー作成ページの表示
    public function createUser()
    {
        $currentUserRole = auth()->user()->roles->pluck('id')->min(); // 現在のユーザーの最小ロールIDを取得
    
        $roles = Role::where('id', '>', $currentUserRole)->get(); // 現在のユーザーのロールIDより大きいロールを取得
    
        $teams = \App\Models\Team::all();
    
        return view('admin.create-user', ['roles' => $roles, 'teams' => $teams]);
    }
    

    // ユーザーの作成
    public function storeUser(Request $request)
    {
        $name = $request->input('name');
        $email = $request->input('email');
        $password = $request->input('password'); // パスワードもリクエストから取得
        $role = $request->input('role');
        $teamId = $request->input('team_id'); // チームIDをリクエストから取得

        // ユーザーの作成
        $user = User::create([
            'name' => $name,
            'email' => $email,
            'password' => Hash::make($password),
            'email_verified_at' => now(), // ここで時刻設定
            'current_team_id' => $teamId ?? '',
        ]);

        // ロールの付与
        $user->assignRole($role);

        // チームにユーザーを追加
        if ($teamId) {
            $team = \App\Models\Team::find($teamId);
            $team->users()->attach($user->id);
        }

        // 登録完了のメール送信
        Mail::to($email)->send(new TestMail($user));
        // 成功メッセージ
        return redirect()->route('admin.index')->with('success', 'ユーザーを作成しました。');
    }
}
  1. コンストラクタ ( __construct ): super-admin ロールを持つユーザーだけがロールやパーミッションを作成できるようにミドルウェアを設定しています。
  2. インデックスメソッド ( index ): すべてのロールとパーミッションを取得し、ビューに渡す機能を持ちます。
  3. ロール/パーミッション作成メソッド ( create ): リクエストから受け取った名前とタイプ(ロールまたはパーミッション)を基に新しいロールやパーミッションを作成します。
  4. ユーザー作成ページ表示メソッド ( crateUser ): 現在のユーザーのロールIDより大きいロールを取得し、全てのチームと共にビューに渡します。
  5. ユーザー作成メソッド ( storeUser ): ユーザー情報をフォームから受け取り、新しいユーザーを作成します。ロールの割り当て、チームへの追加、確認メールの送信も行います。

ロールやパーミッションの利用法

STEP

アクセス制御

ユーザーに応じて異なるアクセスレベルを設定することで、システムのセキュリティを高めることができます。たとえば、super-admin ロールのユーザーはシステムの全機能にアクセスできますが、一般ユーザーやuser ロールのユーザーは限られた機能しか使えないようにします。

STEP

機能別のパーミッション割り当て

特定の機能へのアクセスを制御するために、細かくパーミッションを設定します。例えば、「ユーザーの作成」、「ユーザーの編集」、「ユーザーの削除」などの機能ごとにパーミッションを作成し、それぞれの機能にアクセスできるロールを定義します。

STEP

ミドルウェアの利用

Laravel のミドルウェアを活用して、ルートやコントローラーのアクションにアクセス制限をかけます。例えば、特定のルートに role:admin または permission:edit-user ミドルウェアを適用し、該当する権限を持つユーザーのみがアクセスできるようにします。

STEP

ユーザー管理

管理画面でロールやパーミッションを使ってユーザーを管理します。新しいユーザーを作成する際に適切なロールやパーミッションを割り当て、ユーザーの権限を適切に管理します。

STEP

監査とログ

ユーザーのアクションを追跡し、誰がいつ何をしたかを記録します。これにより、システムの安全性と透明性が向上します。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

目次