👨‍👩‍👧‍👦

Laravel Permission でサイト単位でロールを割り当てたい

2022/10/14に公開

結論:Teamという概念を持っているので、それを使う

です。ドキュメントに書いていました。拡張性も考えているんですねぇ。

Teams permissions | laravel-permission | Spatie

あとはこれが必要になる経緯を書いていくだけです。はい。

Laravel Permission とは

Introduction | laravel-permission | Spatie

このパッケージを使用すると、ユーザーを権限と役割に関連付けることができます。すべての役割は、複数の権限に関連付けられています。RolePermissionは通常の Eloquent モデルが必要で、次のnameように作成できます。

うーん、この。

Laravel の Auth Middleware にバインドされた状態で、当該ユーザーの役割や権限を取得したり、条件判定をしたりできるパッケージです。 $user->can('edit') みたいな感じで、当該ユーザーに権限があるかチェックできる、というやつです。

ユーザーにグループの概念を持たせたケースでの役割権限管理をしたい

Laravel Permission の基本的な使い方は User <--> Permission もしくは User <--> Role <--> Permission の関係性を作って、当該ユーザーでは「何ができるのか」を導きます。

なので、基点は「ユーザー」にあるのですが、サービスによってはグループみたいな概念を持っていて「いちユーザーにつき複数グループに所属できる」仕様で構築するケースもあると思います。
このとき、あるグループでだけ代表者であり、他グループではメンバー、というケースだって考えられるわけですが、前述の原則では対応しきれません。

そこで、ユーザーとロールやパーミッションの間に「チーム」というレイヤーを Laravel Permission ではサポートしていて、それを利用すれば、グループごとのロールを再現することができます。

グループを識別できるタイミングでUserモデルインスタンスにチームIDをセット

namespace App\Http\Middleware;

class TeamsPermission
{
    public function handle($request, \Closure $next)
    {
        // ユーザー情報があれば
        if (!empty(auth()->user())) {
            // 指定のチームIDに関連したロールやパーミッションを
            // Usersモデルインスタンスにバインド
            setPermissionsTeamId($request->get('team_id'));
        }

        return $next($request);
    }
}

公式ドキュメントのまんまの引用ですが、上記のようなミドルウェアを定義しておいて、routesやKernelあたりでロードしてUsersモデルインスタンスからチェーンして、指定のチームID配下の役割権限情報が取得できます。

ひと手間が必要ですが、多岐にわたる役割権限管理にも対応するみたいでした。

自前で作っても良いけど・・

Web系、とくにPHPerであれば、よく検討されるポイントだと思いますが、自前で構築しないことによるコスト削減や、脆弱性や抜け漏れへのリスクヘッジ、おおやけのものであるゆえにブラックボックス化しにくいロジックや、誰かが作ったという安心感などを考えると、できるだけ「自前」は避けたいですよね。

自前じゃなくても良いんだ!という点からも Laravel Permission はしっかり考えられているんだなと感じました。

Discussion