panoscape / privileges
Permission control system for Laravel
Requires
- php: >=5.6.4
- illuminate/support: ^5.3
This package is not auto-updated.
Last update: 2024-11-09 20:50:50 UTC
README
Privilege and Group control for Laravel
Installation
You can install this package via composer using this command:
composer require panoscape/privileges
Register service provider:
config/app.php
'providers' => [ ... Panoscape\Privileges\PrivilegesServiceProvider::class, ];
If you need blade directives, also add this:
config/app.php
'providers' => [ ... Panoscape\Privileges\PrivilegesBladeServiceProvider::class, ];
A middleware can also be registered:
app/Http/Kernel.php
protected $routeMiddleware = [ ... 'privileges' => \Panoscape\Privileges\Middleware\PrivilegesMiddleware::class, ];
Publish profile config:
php artisan vendor:publish --provider="Panoscape\Privileges\PrivilegesServiceProvider" --tag="profile"
Modify the published profile template to suit your application.
config/privileges_profile.php
<?php return [ /* |-------------------------------------------------------------- | User entity |-------------------------------------------------------------- | */ 'user' => [ /* |-------------------------------------------------------------- | Model class |-------------------------------------------------------------- | */ 'model' => '\App\User', /* |-------------------------------------------------------------- | Table name |-------------------------------------------------------------- | */ 'table' => 'users', /* |-------------------------------------------------------------- | Primary key name in table |-------------------------------------------------------------- | */ 'id' => 'id', ], /* |-------------------------------------------------------------- | Group entity |-------------------------------------------------------------- | */ 'group' => [ /* |-------------------------------------------------------------- | Model class |-------------------------------------------------------------- | */ 'model' => '\App\Group', /* |-------------------------------------------------------------- | Table name |-------------------------------------------------------------- | */ 'table' => 'groups', /* |-------------------------------------------------------------- | Primary key name in table |-------------------------------------------------------------- | */ 'id' => 'id', ], /* |-------------------------------------------------------------- | Privilege entity |-------------------------------------------------------------- | */ 'privilege' => [ /* |-------------------------------------------------------------- | Model class |-------------------------------------------------------------- | */ 'model' => '\App\Privilege', /* |-------------------------------------------------------------- | Table name |-------------------------------------------------------------- | */ 'table' => 'privileges', /* |-------------------------------------------------------------- | Primary key name in table |-------------------------------------------------------------- | */ 'id' => 'id', ], /* |-------------------------------------------------------------- | User-Group pivot table |-------------------------------------------------------------- | */ 'user_group' => [ /* |-------------------------------------------------------------- | Table name |-------------------------------------------------------------- | */ 'table' => 'group_user', /* |-------------------------------------------------------------- | User foreign key in table |-------------------------------------------------------------- | */ 'user_id' => 'user_id', /* |-------------------------------------------------------------- | Group foreign key in table |-------------------------------------------------------------- | */ 'group_id' => 'group_id', ], /* |-------------------------------------------------------------- | Group-Privilege pivot table |-------------------------------------------------------------- | */ 'group_privilege' => [ /* |-------------------------------------------------------------- | Table name |-------------------------------------------------------------- | */ 'table' => 'privilege_group', /* |-------------------------------------------------------------- | Group foreign key in table |-------------------------------------------------------------- | */ 'group_id' => 'group_id', /* |-------------------------------------------------------------- | Privilege foreign key in table |-------------------------------------------------------------- | */ 'privilege_id' => 'privilege_id', ] ];
Add Panoscape\Privileges\Privilege\UserEntity
trait to your user model, Panoscape\Privileges\Privilege\GroupEntity
trait to your group model, and Panoscape\Privileges\Privilege\PrivilegeEntity
trait to your privilege model.
If you have multiple privileges control flow or you prefer a different profile name, you may copy and modify the default profile template and rename it to something else, admin_profile
for example. Then defile a method named profile
in your related models and set them to the config name of your choice.
Here is an example of Admin
, Role
, Permission
(instead of User
,Group
,Privilege
):
config/admin_profile.php
<?php return [ 'user' => [ 'model' => '\App\Admin', 'table' => 'admins', 'id' => 'id', ], 'group' => [ 'model' => '\App\Role', 'table' => 'roles', 'id' => 'id', ], 'privilege' => [ 'model' => '\App\Permission', 'table' => 'permissions', 'id' => 'id', ], 'user_group' => [ 'table' => 'admin_role', 'user_id' => 'admin_id', 'group_id' => 'role_id', ], 'group_privilege' => [ 'table' => 'permission_role', 'group_id' => 'role_id', 'privilege_id' => 'permission_id', ] ];
app/Admin.php
class Admin extends Authenticatable { ... use \Panoscape\Privileges\UserEntity; public function profile() { return 'admin_profile'; } }
app\Role.php
class Role extends Model { ... use \Panoscape\Privileges\GroupEntity; public function profile() { return 'admin_profile'; } }
app\Permission.php
class Permission extends Model { ... use \Panoscape\Privileges\PrivilegeEntity; public function profile() { return 'admin_profile'; } }
Migration
This package does not provide any migrations or commands. You should create three required models/migrations and two pivot tables by yourself. The minimal requirements of table structures are listed in the profile template.
Basic Usage
Access groups/privileges relationship of a user:
$user->groups()->get(); $user->privileges()->get();
or via dynamic properties:
$user->groups->get(); $user->privileges->get();
If you have different entity names other than the default User
, Group
, Privilege
, You should access the relationships by the table
values defined in your profile.
Example of Admin
, Role
, Permission
:
$admin->roles()->get(); $admin->roles->get(); $admin->permissions()->get(); $role->admins->get(); $role->permissions->get(); $permission->roles->get();
Group and Privilege validation
has:
//returns true if target group is found on this user $user->groups()->has('root');
all:
//returns false unless all groups are found on this user $user->groups()->all(['editor', 'author', 'subscriber']);
any:
//returns true as long as any of these groups are found on this user $user->groups()->any(['editor', 'author', 'subscriber']);
Instead of the default name
column checking, you may specify which column to check:
//check name column by default $user->groups()->has('root'); //check fullname column instead $user->groups()->has('Root Administrator', 'fullname'); //check id column instead $user->groups()->any([1, 3, 5], 'id');
validate:
With this method you can do complex checking
all:
$user->groups()->validate('root|author|subscriber')
equivalent to
$user->groups()->all(['editor', 'author', 'subscriber'])
any:
$user->groups()->validate('(root|author|subscriber)')
equivalent to
$user->groups()->any(['editor', 'author', 'subscriber'])
all + any:
$user->privileges()->validate('query|(delete|insert)|update')
equivalent to
$user->privileges()->all(['query', 'update']) && $user->privileges()->any(['delete', 'insert'])
group:
$user->validate('g=root|(author|subscriber)')
equivalent to
$user->groups()->all(['root']) && $user->groups()->any(['author', 'subscriber'])
privilege:
$user->validate('p=query|(delete|insert)|update')
equivalent to
$user->privileges()->all(['query', 'update']) && $user->privileges()->any(['delete', 'insert'])
group + privilege:
$user->validate('g=root|(author|subscriber);p=query|(delete|insert)|update')
equivalent to
$user->groups()->all(['root']) && $user->groups()->any(['author', 'subscriber']) && $user->privileges()->all(['query', 'update']) && $user->privileges()->any(['delete', 'insert'])
Column specification is also available:
$user->validate('g=1|(3|5);p=1|(2|10)|3', 'id')
Middleware
If you have registered the middleware, you can add it to any routes you'd like to guard with it.
Route::get('/pages', 'PageController@index')->middleware('privileges:g=editor|(author|subscriber);p=query|(delete|insert)|update');
Balde
If you have registered the blade service provider, you may guard your blade codes with @validate
, @group
and @privilege
.
Also your user entity need to implement Panoscape\Privileges\Privileged
interface in order to use these blade directives.
class Admin extends Authenticatable implements \Panoscape\Privileges\Privileged { ... use \Panoscape\Privileges\UserEntity; }
Blade directives:
@group('root') <button> ... </button> @endgroup @privilege('edit_users') <button> ... </button> @endprivilege @validate('g=(root|editor);p=edit_users') <button> ... </button> @endvalidate
Performance
$user->privileges()->validate('editor_users|edit_admins')
joined 5 tables(2 of them are pivot tables) within one query:
select count(*) as aggregate from "permissions" inner join "permission_role" on "permissions"."id" = "permission_role"."permission_id" inner join "roles" on "roles"."id" = "permission_role"."role_id" inner join "admin_role" on "roles"."id" = "admin_role"."role_id" inner join "admins" on "admins"."id" = "admin_role"."admin_id" where "admins"."id" = '1' and "permissions"."name" in ('edit_users', 'edit_admins')
$user->privileges()->validate('edit_users|(create_admins|edit_admins)')
joined 5 tables(2 of them are pivot tables) within two query:
select count(*) as aggregate from "permissions" inner join "permission_role" on "permissions"."id" = "permission_role"."permission_id" inner join "roles" on "roles"."id" = "permission_role"."role_id" inner join "admin_role" on "roles"."id" = "admin_role"."role_id" inner join "admins" on "admins"."id" = "admin_role"."admin_id" where "admins"."id" = '1' and "permissions"."name" in ('create_admins', 'edit_admins')
select count(*) as aggregate from "permissions" inner join "permission_role" on "permissions"."id" = "permission_role"."permission_id" inner join "roles" on "roles"."id" = "permission_role"."role_id" inner join "admin_role" on "roles"."id" = "admin_role"."role_id" inner join "admins" on "admins"."id" = "admin_role"."admin_id" where "admins"."id" = '1' and "permissions"."name" in ('edit_users')
$user->privileges()->validate('(edit_users|delete_users)|(create_admins|edit_admins)')
joined 5 tables(2 of them are pivot tables) within two query:
select count(*) as aggregate from "permissions" inner join "permission_role" on "permissions"."id" = "permission_role"."permission_id" inner join "roles" on "roles"."id" = "permission_role"."role_id" inner join "admin_role" on "roles"."id" = "admin_role"."role_id" inner join "admins" on "admins"."id" = "admin_role"."admin_id" where "admins"."id" = '1' and "permissions"."name" in ('edit_users', 'delete_users')
select count(*) as aggregate from "permissions" inner join "permission_role" on "permissions"."id" = "permission_role"."permission_id" inner join "roles" on "roles"."id" = "permission_role"."role_id" inner join "admin_role" on "roles"."id" = "admin_role"."role_id" inner join "admins" on "admins"."id" = "admin_role"."admin_id" where "admins"."id" = '1' and "permissions"."name" in ('create_admins', 'edit_admins')
Conclusion
Each any group costs one query;
All all group costs one query.