LoginSignup
9
9

More than 5 years have passed since last update.

Laravel 5.7 でフル機能マルチテナント・SaaS型アプリ基盤をゼロから3時間で構築する Part2

Last updated at Posted at 2018-12-15

前回の続きです。
なお、参考記事はこちら。

認証と認可できるところまで作る

 各テナント内で、認証と認可ができるようにします。

 ここで使うパッケージは、Spatieによるlaravel-permissionです。ユーザーに直接Permissionを与えたり、RoleにPermissionを与えてUserにRoleを割り当てたりできます。

laravel-permissionをインストール

 先にドキュメントを読んで、何となく使い方を把握しておくと楽です。英語が読めなくても使い方の箇所を何となく見てるだけでも分かりそうです。

 パッケージを入れます。

composer require spatie/laravel-permission

 さて、このパッケージにマルチテナントアプリだということを教えなくてはいけません。修正対象はPermissionとRoleのModelなのですが、ただ、もちろんあとでアップデートすることも考えて、直接Modelのコードを修正するのはやめておきます。具体的には、PermissionとRoleのModelを自作して、パッケージにこれらを使うように教えることにします。これはパッケージのvendor configファイルでの設定で実現可能です。まずpublishしましょう。

php artisan vendor:publish

 今回は、以下を選びます。

Provider: Spatie\Permission\PermissionServiceProvider

 これにより、config/permission.phpxxxx_xx_xx_xxxxxx_create_permission_tables.phpの2つが生成されます。

 Migrationであるxxxx_xx_xx_xxxxxx_create_permission_tables.phpは、テナント用のテーブルとしなくてはいけないので、database/migrationsフォルダからdatabase/migrations/tenantフォルダに移動します。

 次に、config/permission.phpを編集します。modelsセクションに以下のように追記です。(元の'permission''role'はコメントアウト)

config/permission.php
...
    'models' => [
        // For Tenancy, the custom permission/role models are used.
        'permission' => App\Permission::class,
        'role' => App\Role::class,
...
        //'permission' => Spatie\Permission\Models\Permission::class,
...
        //'role' => Spatie\Permission\Models\Role::class,
...

 実際にModelを作ります。

php artisan make:model Permission
php artisan make:model Role

 空っぽのModelが2つできるので、ここにマルチテナントアプリであることを教えて(テナント用のデータベース接続を使わせる)、なおかつlaravel-permissionパッケージの継承を行います。

app/Permission.php
<?php
namespace App;
use Hyn\Tenancy\Traits\UsesTenantConnection;
use Spatie\Permission\Models\Permission as BasePermission;
class Permission extends BasePermission
{
    use UsesTenantConnection;
}
app/Role.php
<?php
namespace App;
use Hyn\Tenancy\Traits\UsesTenantConnection;
use Spatie\Permission\Models\Role as BaseRole;
class Role extends BaseRole
{
    use UsesTenantConnection;
}

RoleとPermissionの初期設定をSeedする

 テナントが作られたとき、テナントデータベースに、RoleとPermissionの初期設定をSeedしたいので、それを設定してきます。これに必要なのは、どのSeederを使うべきかを教えるだけです。config/tenancy.php'tenant-seed-class'設定部分を見つけ、以下のように編集します。

config/tenancy.php
...
'tenant-seed-class' => TenantDatabaseSeeder::class,
...

 これにより、テナントデータベースが作られた後に'database/seeds/TenantDatabaseSeeder.php'クラスが実行されます。

 Seederを作りましょう。

php artisan make:seeder TenantDatabaseSeeder

 中を編集します。

database/seeds/TenantDatabaseSeeder.php
<?php
use App\Permission;
use Illuminate\Database\Seeder;
use Spatie\Permission\Models\Role;
class TenantDatabaseSeeder extends Seeder
{
    public function run()
    {
        $this->addRolesAndPermissions();
    }
    private function addRolesAndPermissions()
    {
        // create permissions for an admin
        $adminPermissions = collect(['create user', 'edit user', 'delete user'])->map(function ($name) {
            return Permission::create(['name' => $name]);
        });
        // add admin role
        $adminRole = Role::create(['name' => 'admin']);
        $adminRole->givePermissionTo($adminPermissions);
        // add a default user role
        Role::create(['name' => 'user']);
    }
}

 ポイントとしては、['create user', 'edit user', 'delete user']という3つのPermissionを作って、それをadminというRoleに割り当てて、さらに別途userというRoleを作っています。user Roleには何もPermissionが与えられていないですね。これらのPermissionは例なので深く考えないことにして、こんな感じで初期権限割り当てができるということだけ理解すれば十分です。

管理ユーザーにadmin権限を与える

 Part1では管理ユーザーを作っただけで権限を与えていませんでしたが、ここで権限を与える処理を加えます。

 ただ、その前にUserモデルがそもそもPermissionとRoleに対応しなければいけないのと、そもそもまだマルチテナント接続しなければいけないことに気づいてないので、以下のように追記編集します。

app/User.php
use Hyn\Tenancy\Traits\UsesTenantConnection;
use Spatie\Permission\Traits\HasRoles;

class User extends Authenticatable
{
    use UsesTenantConnection;
    use HasRoles;

    // ...
}

今後作るほかのModelにも、use UsesTenantConnection;を忘れないようにしてください。忘れるとハマります。

 では、app/Console/Commands/CreateTenant.phpに権限設定コードを入れましょう。

app/Console/Commands/CreateTenant.php
...
    private function addAdmin($name, $email, $password)
    {
        $admin = User::create(['name' => $name, 'email' => $email, 'password' => Hash::make($password)]);
        $admin->guard_name = 'web';
        $admin->assignRole('admin');
        return $admin;
    }
...

 2行追加しました。ガードでwebを指定し、管理ユーザーに権限を付与しています。UIでこの操作を行う場合ガードは気にしなくていいで鵜が、今回はコマンドラインで実行しているので、webに対しての権限付与であることを明示します。

 もう一度テナントを作ってみましょう。

php artisan tenant:create john john@example.com cafejohn

 成功したらテナントのデータベースを見てみましょう。model_has_permissions, model_has_roles, role_has_permissions, そして rolesのテーブルができているはずです。

 今後UIを作ることになったとしても、このコマンドをまねして作れば簡単です。

→ Part3へ

9
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
9