Laravel-permission: Recommended pattern for seeding/updating

Created on 21 Dec 2017  路  4Comments  路  Source: spatie/laravel-permission

Hi,

Here is the recurring issue:

Each time you deploy a new feature, you need to make sure existing roles and permissions in production DB get updated. E.g.

  • We add a feature to our backend to manage users.
  • That feature uses permissions such as 'user-destroy', 'user-create' and 'user-update'
  • Those permissions should by default be granted to roles 'administrator', 'user-administrator'

I am wondering which pattern you recommend to solve this issue:

Manually

Requires an admin interface to create/edit roles/permissions. However this is error prone and time consumming.

Seeding

I am not really keen on running seeding commands on a production environment

Custom artisan command + configuration file

You store a role/permission tree in a config file
Then an artisan command will parse that array and update the database

Anything else more obvious and easier to implement?


Would you accept a PR which would help making this process easier and standardized in your package?

Most helpful comment

Looks like a pretty good way to do it. Even though I find it a little too verbose.

Maybe having a PermissionMigration class with some helper methods would make that nicer to use.

Something like

$this->appendRolePermissions([
    'role1' => ['p1', 'p2', ], // Update role 1 and add those permissions
    'role2' => ['p1', 'p4', ], // Update role 2 and add those permissions
    'role3' => ['p7', 'p3', ], // Create role 3 and add those permissions
]);

Thanks for the starting point. That will cover the most usual use-case which is to append new permissions to existing roles.

All 4 comments

Simplest way is to use migrations.

For example:

<?php

use Illuminate\Database\Migrations\Migration;
use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;

class AddMorePermissions extends Migration
{
    public function up()
    {
        Permission::create(['name' => 'test_permission']);

        $role = Role::create(['name' => 'TESTROLE']);
        $role->givePermissionTo('test_permission');
    }

    public function down()
    {
        $role = Role::findByName('TESTROLE');
        $role->revokePermissionTo('test_permission');
        $role->delete();

        $permission = Permission::findByName('test_permission');
        $permission->delete();
    }
}

Looks like a pretty good way to do it. Even though I find it a little too verbose.

Maybe having a PermissionMigration class with some helper methods would make that nicer to use.

Something like

$this->appendRolePermissions([
    'role1' => ['p1', 'p2', ], // Update role 1 and add those permissions
    'role2' => ['p1', 'p4', ], // Update role 2 and add those permissions
    'role3' => ['p7', 'p3', ], // Create role 3 and add those permissions
]);

Thanks for the starting point. That will cover the most usual use-case which is to append new permissions to existing roles.

`

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;

class RolesAndPermissionsMigrate extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
app()[\Spatie\Permission\PermissionRegistrar::class]->forgetCachedPermissions();

  foreach ($this->permissions as $permission) {
     Permission::create(['name' => $permission]);
  }

  foreach ($this->roles as $role_up) {
     $role = Role::create(['name' => $role_up]);

     foreach ($this->rolePermissions($role_up) as $role_permissions) {
       $role->givePermissionTo($role_permissions);
     }
  }
}

/**
 * Reverse the migrations.
 *
 * @return void
 */
public function down()
{
  foreach ($this->roles as $role_down) {
    $role = Role::findByName($role_down);

    foreach ($this->rolePermissions($role_down) as $role_permissions) {
      $role->revokePermissionTo($role_permissions);
    }

    $role->delete();
  }

  foreach ($this->permissions as $permission_down) {
    $permission = Permission::findByName($permission_down);
    $permission->delete();
  }

  app()[\Spatie\Permission\PermissionRegistrar::class]->forgetCachedPermissions();

}

private $permissions = [
                        'blog edit',
                       ];

private $roles       = [
                        'super-admin',
                        'admin',
                       ];

private function rolePermissions($role){

  $role_permissions = [
    'super-admin' => ['blog edit'],
    'admin' => ['blog edit'],
  ];

  return (isset($role_permissions[$role]))? $role_permissions[$role] : [];
}

}
?>
`

Installing permissions and roles via migrations is a very bad idea. In large applications, this greatly increases the number and volume of migrations.

This can slow down the unit testing process very much if the tests require a refresh database.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ergonomicus picture ergonomicus  路  3Comments

MichalKrakow picture MichalKrakow  路  4Comments

bbdangar picture bbdangar  路  4Comments

holymp2006 picture holymp2006  路  4Comments

dylangeorgeharbour picture dylangeorgeharbour  路  3Comments