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.
I am wondering which pattern you recommend to solve this issue:
Requires an admin interface to create/edit roles/permissions. However this is error prone and time consumming.
I am not really keen on running seeding commands on a production environment
You store a role/permission tree in a config file
Then an artisan command will parse that array and update the database
Would you accept a PR which would help making this process easier and standardized in your package?
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.
Most helpful comment
Looks like a pretty good way to do it. Even though I find it a little too verbose.
Maybe having a
PermissionMigrationclass with some helper methods would make that nicer to use.Something like
Thanks for the starting point. That will cover the most usual use-case which is to append new permissions to existing roles.