laravel-acl
laravel-acl copied to clipboard
Assign Permission to role with slug
@kodeine Actually I am integrating your package. It's good to use. Now I am having a problem with assigning Permission to roles. What I want: - ActuallyI have an admin panel in which I listed out all the permission with checkbox and user enter the role-name and checked permissions. actually, you provided the slug concept so I assuming them as child permissions So my listing view is like this.
So in laravel side i am trying to assign permission to role like that :-
$roleAdmin = Role::first(); // administrator
$roleAdmin->assignPermission('servicelocation, currency ,privacyandpolicy.create');
It gives error that
InvalidArgumentException in HasPermission.php line 183: Specified permission name does not exist.
@kushal555
$roleAdmin->assignPermission(->'servicelocation, currency ,privacyandpolicy.create' <--);
maybe you forgot to adjust the quotes?
@kodeine Sorry, I didn't get you. can you please explain a little bit more.
@kushal555
- Show your permissions. How are you creating permissions?
- As far as I understand, assignPermission works with permission
name
, not permissionslug
s. Do you have permissions namedservicelocation
,currency
,privacyandpolicy.create
created prior to this assignment? - Have a look for commas, It could be the parser issue. See example:
'servicelocation, currency ,privacyandpolicy.create'
vs
'servicelocation,currency,privacyandpolicy.create'
Make sure you understand how assignPermission()
works.
Is there any way, So we can assign Permission name and slug both in array or passing comma separate
Actually i have privacyandpolicy
is name of permission and create
is the slug.
Is there any track log maintained in which we can know who is created the roles and permissions ?.
@kushal555 Let me show you an example
One single permission
(name='blog'
) consists of many slug items (permission
items), such as:
- create (create blog posts)
- delete
- update
- view
- upload-images
In the code, all these slug items actually become JSON-encoded string like slug=["create":true,"update":false,"upload-images":true, etc...]
.
Our permission
object would look like this:
id: 3
name: 'blog'
slug: ["create":true,"update":false,"upload-images":true, etc...],
...
When you assign permission
to the role
or user
you are referring permission
id
value to role
or user
id
. For these purposes, there are permission_role
and permission_user
tables.
So there is simply no infrastructure for doing slug-based permission assignments at the moment.
Thanks @konovalov-nk for your replying.
Actually what I am trying to get, Just explain me the little bit:-
First, i am using the AngularJS client side.
I list down all permission with possibilities slug for my project and save all them with false
status.
eg.
#About Us
$permAboutUS = $permission->create([
'name' => 'aboutus',
'slug' => [ // pass an array of permissions.
'create' => false,
'view' => false,
'update' => false,
'delete' => false
],
'description' => 'manage About Us Page permissions',
'is_main'=>'1'
]);
Now, I have an admin panel in which I give the menu add the role, in which Super admin can add the role and I also listed out the permissions there with the checkbox in hierarchy structure( I provided screenshot above).
So Super Admin can check them according to the role.
Suppose if super admin checks only aboutus.view=true
. So, I just create the new role with a name of role.aboutuse
and insert slug ("create": true)
.
Now, it's making many entries if super admin creates every time new roles and in server side, i need to parse the every permission and check is it is name or slug.
@kushal555 So, basically, you need to implement an interface to create new roles with selected permission parameters, right?
Well, you probably need permission inheritance. As for the problem assigning permission name and slugs, it's really easy to solve.
You have multiple permissions listed with slugs as a set of checkboxes. When you check permission name
that would mean you want to inherit rules from this permission for your new role. Here is how permission inheritance works:
$permAboutUS = Permission::create([
'name' => 'aboutus',
'slug' => [ // An array of permissions.
'create' => false,
'view' => false,
'update' => false,
'delete' => false,
],
'description' => 'manage About Us Page permissions'
]);
$permAboutUSNewRoleName = Permission::create([
'name' => 'aboutus.new_role_slug',
'slug' => [ // An array of permissions only for new role you've created
'create' => true,
],
// We are using permission inheriting here.
'inherit_id' => $permAboutUS ->getKey(),
'description' => 'About Us Page permissions for new_role_slug'
]);
That would create a permission aboutus.new_role_slug
with this slug:
'slug' => [ // An array of permissions.
'create' => true, // See $permAboutUSNewRoleName 'slug' value.
'view' => false,
'update' => false,
'delete' => false,
],
but it wouldn't store the whole slug in the DB because it uses inherit_id
to fetch them from parent permission
object. So, it would store only slug="{'create':true}"
for this case.
Now, back to your interface. What you want to do is when you check permission
name checkbox, it would use that permission
id to inherit rules. Aside from that, you don't want simply inherit it, but also change some rules (slugs). I don't think checkboxes is a good way to describe slug values because it could confuse the user. Is checked rule means that this rule needs to be overridden or taken from the parent permission? Consider using radio buttons instead: Default [value=-1], Forbid [value=0], Permit [value=1]. That is standard UX practice for defining permissions for the role. To make the interface less cluttered you can use bootstrap tooltips and title values.
When you finally got your input from the submitted form you can compose your slug items:
// Get form data.
$data = request()->all();
// We have this input data structure:
// 'role_name' => 'New Role'
// 'role_slug' => 'new_role'
// 'role_description' => 'Some description'
// 'aboutus' => true
// 'aboutus.create' => 1
// 'aboutus.view' => -1
// 'aboutus.update' => -1
// 'aboutus.delete' => -1
// All new permissions we'll create that would be assigned to the new role.
$new_permissions = [];
// First check if we have checked 'aboutUS' permission.
if (isset($data["aboutus"])) {
// Get our parent permission.
$permAboutUS = Permission::whereName('aboutus')->first();
// Get our slug items from this permission.
$slug = $permAboutUS->slug;
$new_slug = [];
foreach ($slug as $slug_name => $value) {
// Create new slug item for new permission we want to create.
if ($data["aboutus.{$slug_name}"] >= 0) {
$new_slug[$slug_name] = (bool) $value;
} else {
// It would be inherited.
}
}
// Now create new permission:
$permAboutUSNewRoleName = Permission::create([
'name' => "aboutus.{$data['role_slug']}",
'slug' => $new_slug,
// We are using permission inheriting here.
'inherit_id' => $permAboutUS ->getKey(),
'description' => "About Us Page permissions for $data['role_name']"
]);
// Add permission name we've created, so we can assign it to the role later.
$new_permissions []= "aboutus.{$data['role_slug']}";
}
$roleNew = new Role();
$roleNew->name = $data['role_name'];
$roleNew->slug = $data['role_slug'];
$roleNew->description = $data['role_description'];
$roleNew->save();
// Assign all new permissions we've created to the role.
$roleNew->assignPermission(implode(',', $new_permissions));
I haven't tested the code, but you should get the idea.
Thank you so much @konovalov-nk for your support and consideration.
Actually, i also need to add who add this role, Because I have many types of Admin users So need to maintain roles according to them. If user A
create a role test.a
then he also able to assign role test.a
only not any other users.
So for that, i need to change in your table,
May I change it or find any other solution?
Once again I want to say thank you @konovalov-nk . :+1:
@kushal555
If you already have production data, then you must use migrations to add a column named user_id
to roles
table.
If that's not the case, then you can just update this migration file and run
php artisan migrate:rollback --step=7
php artisan migrate
When the user creates a new role, you can assign current user id to that role object.
Then you can add your business logic to forbid/allow access to roles based on user_id
value.
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddRoleTypeToRolesTable extends Migration {
/**
* Run the migrations.
*
* @return void
*/
public function up() {
//
Schema::table('roles', function($table) {
$table->tinyInteger('role_type')->after('description')->default(1)->comment('1 = User Role, 2 = Subscription, 3 = Super Admin');
$table->integer('user_id')->after('role_type')->nullable()->unsigned()->comment("who created this role");
$table->tinyInteger('is_editable')->after('user_id')->default(1)->comment('1 = Role is Editable, 0 = System Defautl Role which is not editable');
$table->foreign('user_id')->references('id')->on('users');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down() {
//
Schema::table('roles', function (Blueprint $table) {
$table->dropForeign(['user_id']);
$table->dropColumn('role_type');
$table->dropColumn('user_id');
$table->dropColumn('is_editable');
});
}
}
@kodeine I just create the new migration for existing role and also override the model fillable
array according to my requirement.
Is there way to get the new create permission with parent options Like as above we discussed new role is
$newRole = 'aboutus.admin';
// So if i get the new role permission
$permission=$newRole->getPermissions();
so it only return the allowed permissions. Actually i need the whole slugs which is belongs to user event they are associated or not. @konovalov-nk can you please look into that ?