├── .gitignore ├── laravel_rbac_roles_en.JPG ├── laravel_rbac_users_en.JPG ├── laravel_rbac_structure_en.jpg ├── laravel_rbac_permissions_en.JPG ├── resources ├── lang │ ├── en │ │ ├── roles.php │ │ ├── users.php │ │ ├── permissions.php │ │ ├── main.php │ │ └── validation.php │ └── ru │ │ ├── roles.php │ │ ├── permissions.php │ │ ├── users.php │ │ ├── main.php │ │ └── validation.php └── views │ ├── roles │ ├── create.blade.php │ ├── edit.blade.php │ ├── _fields.blade.php │ ├── show.blade.php │ └── index.blade.php │ ├── permissions │ ├── create.blade.php │ ├── edit.blade.php │ ├── _fields.blade.php │ ├── show.blade.php │ └── index.blade.php │ └── users │ ├── edit.blade.php │ ├── _fields.blade.php │ ├── show.blade.php │ └── index.blade.php ├── .scrutinizer.yml ├── src ├── Http │ ├── Controllers │ │ ├── Controller.php │ │ ├── PermissionController.php │ │ ├── RoleController.php │ │ └── UserController.php │ └── Requests │ │ ├── Delete.php │ │ ├── UpdateUser.php │ │ ├── StorePermission.php │ │ ├── StoreRole.php │ │ ├── UpdatePermission.php │ │ └── UpdateRole.php ├── Interfaces │ ├── RbacModelInterface.php │ └── RbacUserInterface.php ├── Classes │ └── MemberToRole.php ├── RbacRouteServiceProvider.php ├── Models │ ├── Permission.php │ └── Role.php ├── Commands │ ├── AdminCommand.php │ ├── DatabaseCommand.php │ └── PublishCommand.php ├── routes.php ├── RbacAuthServiceProvider.php ├── Helpers │ └── Helper.php ├── Traits │ └── Administrable.php └── RbacServiceProvider.php ├── database ├── seeders │ ├── LaRbacDatabaseSeeder.php │ ├── PermissionSeeder.php │ └── RoleSeeder.php └── migrations │ ├── 2020_07_11_151756_create_roles_table.php │ ├── 2020_07_11_151894_create_permissions_table.php │ ├── 2020_07_11_151925_create_role_permission_table.php │ └── 2020_07_11_151834_create_user_role_table.php ├── config └── rbac.php ├── LICENSE ├── composer.json ├── changelog.md └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | vendor 3 | composer.lock -------------------------------------------------------------------------------- /laravel_rbac_roles_en.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itstructure/laravel-rbac/HEAD/laravel_rbac_roles_en.JPG -------------------------------------------------------------------------------- /laravel_rbac_users_en.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itstructure/laravel-rbac/HEAD/laravel_rbac_users_en.JPG -------------------------------------------------------------------------------- /laravel_rbac_structure_en.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itstructure/laravel-rbac/HEAD/laravel_rbac_structure_en.jpg -------------------------------------------------------------------------------- /laravel_rbac_permissions_en.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itstructure/laravel-rbac/HEAD/laravel_rbac_permissions_en.JPG -------------------------------------------------------------------------------- /resources/lang/en/roles.php: -------------------------------------------------------------------------------- 1 | 'Roles', 5 | 'create_role' => 'Create role', 6 | 'edit_role' => 'Edit role', 7 | 'delete_role' => 'Delete role', 8 | 'role_details' => 'Role details', 9 | ]; 10 | -------------------------------------------------------------------------------- /resources/lang/ru/roles.php: -------------------------------------------------------------------------------- 1 | 'Роли', 5 | 'create_role' => 'Создать роль', 6 | 'edit_role' => 'Редактировать роль', 7 | 'delete_role' => 'Удалить роль', 8 | 'role_details' => 'Детали роли', 9 | ]; 10 | -------------------------------------------------------------------------------- /resources/lang/en/users.php: -------------------------------------------------------------------------------- 1 | 'Users', 5 | 'user_details' => 'User details', 6 | 'assign_roles' => 'Assign roles', 7 | 'assign_roles_for_user' => 'Assign roles for user', 8 | 'delete_user' => 'Delete user', 9 | 'name' => 'Name', 10 | ]; 11 | -------------------------------------------------------------------------------- /resources/lang/en/permissions.php: -------------------------------------------------------------------------------- 1 | 'Permissions', 5 | 'create_permission' => 'Create permission', 6 | 'edit_permission' => 'Edit permission', 7 | 'delete_permission' => 'Delete permission', 8 | 'permission_details' => 'Permission details', 9 | ]; 10 | -------------------------------------------------------------------------------- /resources/lang/ru/permissions.php: -------------------------------------------------------------------------------- 1 | 'Полномочия', 5 | 'create_permission' => 'Создать полномочие', 6 | 'edit_permission' => 'Редактировать полномочие', 7 | 'delete_permission' => 'Удалить полномочие', 8 | 'permission_details' => 'Детали полномочия', 9 | ]; 10 | -------------------------------------------------------------------------------- /resources/lang/ru/users.php: -------------------------------------------------------------------------------- 1 | 'Пользователи', 5 | 'user_details' => 'Детали пользователя', 6 | 'assign_roles' => 'Назначить роли', 7 | 'assign_roles_for_user' => 'Назначить роли пользователю', 8 | 'delete_user' => 'Удалить пользователя', 9 | 'name' => 'Имя', 10 | ]; 11 | -------------------------------------------------------------------------------- /.scrutinizer.yml: -------------------------------------------------------------------------------- 1 | build: 2 | nodes: 3 | analysis: 4 | tests: 5 | override: 6 | - "php-scrutinizer-run" 7 | 8 | checks: 9 | php: 10 | code_rating: true 11 | duplication: true 12 | 13 | filter: 14 | excluded_paths: 15 | - vendor/* 16 | 17 | before_commands: 18 | - "composer install --prefer-source" -------------------------------------------------------------------------------- /src/Http/Controllers/Controller.php: -------------------------------------------------------------------------------- 1 | 'Name', 5 | 'description' => 'Description', 6 | 'slug' => 'Slug', 7 | 'attribute' => 'Attribute', 8 | 'value' => 'Value', 9 | 'created' => 'Created', 10 | 'create' => 'Create', 11 | 'edit' => 'Edit', 12 | 'delete' => 'Delete', 13 | 'delete_confirm' => 'Are you sure you want to delete?', 14 | 'generated_automatically' => 'Generated automatically', 15 | ]; 16 | -------------------------------------------------------------------------------- /src/Interfaces/RbacModelInterface.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | interface RbacModelInterface 13 | { 14 | /** 15 | * Get Author id which related with user model record. 16 | * @return int 17 | */ 18 | public function getAuthorIdAttribute(): int; 19 | } 20 | -------------------------------------------------------------------------------- /resources/lang/ru/main.php: -------------------------------------------------------------------------------- 1 | 'Название', 5 | 'description' => 'Описание', 6 | 'slug' => 'Слаг', 7 | 'attribute' => 'Атрибут', 8 | 'value' => 'Значение', 9 | 'created' => 'Создано', 10 | 'create' => 'Создать', 11 | 'edit' => 'Редактировать', 12 | 'delete' => 'Удалить', 13 | 'delete_confirm' => 'Вы уверены что хотите это удалить?', 14 | 'generated_automatically' => 'Сгенерирован автоматически', 15 | ]; 16 | -------------------------------------------------------------------------------- /database/seeders/LaRbacDatabaseSeeder.php: -------------------------------------------------------------------------------- 1 | 10 | */ 11 | class LaRbacDatabaseSeeder extends Seeder 12 | { 13 | /** 14 | * Seed the application's database with RBAC data. 15 | * @return void 16 | */ 17 | public function run() 18 | { 19 | $this->call(PermissionSeeder::class); 20 | $this->call(RoleSeeder::class); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /resources/lang/en/validation.php: -------------------------------------------------------------------------------- 1 | 'The ":attribute" field is required.', 5 | 'string' => 'The ":attribute" field must be a string.', 6 | 'regex' => 'The ":attribute" field must contain latin characters.', 7 | 'min' => 'The ":attribute" field must contain at least :min characters.', 8 | 'max' => 'The ":attribute" field may contain no more :max characters.', 9 | 'unique' => 'The ":attribute" already exists with this value ":input" in database.', 10 | 'required_to_delete' => 'Select items to delete.', 11 | ]; 12 | -------------------------------------------------------------------------------- /resources/lang/ru/validation.php: -------------------------------------------------------------------------------- 1 | 'Атрибут ":attribute" обязательный.', 5 | 'string' => 'Атрибут ":attribute" должен быть строкой.', 6 | 'regex' => 'Атрибут ":attribute" должен содержать латинские символы.', 7 | 'min' => 'Атрибут ":attribute" должен содержать минимум :min символов.', 8 | 'max' => 'Атрибут ":attribute" может содержать не более :max символов.', 9 | 'unique' => 'Атрибут ":attribute" уже есть с таким значением ":input" в базе данных.', 10 | 'required_to_delete' => 'Выберите позиции для удаления.', 11 | ]; 12 | -------------------------------------------------------------------------------- /config/rbac.php: -------------------------------------------------------------------------------- 1 | '', // You must set it. Example: 'layout' => 'adminlte::page' 5 | 'userModelClass' => App\Models\User::class, // You can change it 6 | 'adminUserId' => null, // You must set it. This is the initial user id, which must be an administrator, at least at the first stage. 7 | 'routesMainPermission' => Itstructure\LaRbac\Models\Permission::ADMINISTRATE_PERMISSION, // You can change it 8 | 'routesAuthMiddlewares' => ['auth'], // You can change it 9 | 'memberNameAttributeKey' => function ($row) { // You can change it. And can simply set 'memberNameAttributeKey' => 'name' 10 | return $row->name; 11 | }, 12 | 'rowsPerPage' => 10, 13 | ]; 14 | -------------------------------------------------------------------------------- /resources/views/roles/create.blade.php: -------------------------------------------------------------------------------- 1 | @extends($rbacLayout) 2 | @section('title', __('rbac::roles.create_role')) 3 | @section('content') 4 | 5 |
6 |
7 |
8 | 9 |

{!! __('rbac::roles.create_role') !!}

10 | 11 |
12 | 13 | @include('rbac::roles._fields', ['edit' => false]) 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 |
22 |
23 |
24 | 25 | @stop 26 | -------------------------------------------------------------------------------- /resources/views/permissions/create.blade.php: -------------------------------------------------------------------------------- 1 | @extends($rbacLayout) 2 | @section('title', __('rbac::permissions.create_permission')) 3 | @section('content') 4 | 5 |
6 |
7 |
8 | 9 |

{!! __('rbac::permissions.create_permission') !!}

10 | 11 |
12 | 13 | @include('rbac::permissions._fields', ['edit' => false]) 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 |
22 |
23 |
24 | 25 | @stop 26 | -------------------------------------------------------------------------------- /resources/views/roles/edit.blade.php: -------------------------------------------------------------------------------- 1 | @extends($rbacLayout) 2 | @section('title', __('rbac::roles.edit_role')) 3 | @section('content') 4 | 5 |
6 |
7 |
8 | 9 |

{!! __('rbac::roles.edit_role') !!}: {{ $role->name }}

10 | 11 |
12 | 13 | @include('rbac::roles._fields', ['edit' => true]) 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 |
22 |
23 |
24 | 25 | @stop 26 | -------------------------------------------------------------------------------- /resources/views/users/edit.blade.php: -------------------------------------------------------------------------------- 1 | @extends($rbacLayout) 2 | @section('title', __('rbac::users.assign_roles')) 3 | @section('content') 4 | 5 |
6 |
7 |
8 | 9 |

{!! __('rbac::users.assign_roles_for_user') !!}: {{ $user->memberName }}

10 | 11 |
12 | 13 | @include('rbac::users._fields') 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 |
22 |
23 |
24 | 25 | @stop 26 | -------------------------------------------------------------------------------- /resources/views/permissions/edit.blade.php: -------------------------------------------------------------------------------- 1 | @extends($rbacLayout) 2 | @section('title', __('rbac::permissions.edit_permission')) 3 | @section('content') 4 | 5 |
6 |
7 |
8 | 9 |

{!! __('rbac::permissions.edit_permission') !!}: {{ $permission->name }}

10 | 11 |
12 | 13 | @include('rbac::permissions._fields', ['edit' => true]) 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 |
22 |
23 |
24 | 25 | @stop 26 | -------------------------------------------------------------------------------- /database/migrations/2020_07_11_151756_create_roles_table.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | class CreateRolesTable extends Migration 13 | { 14 | /** 15 | * Run the migrations. 16 | * @return void 17 | */ 18 | public function up() 19 | { 20 | Schema::create('roles', function (Blueprint $table) { 21 | $table->increments('id'); 22 | $table->string('name', 191); 23 | $table->string('slug', 191)->unique(); 24 | $table->string('description', 191); 25 | $table->timestamps(); 26 | }); 27 | } 28 | 29 | /** 30 | * Reverse the migrations. 31 | * @return void 32 | */ 33 | public function down() 34 | { 35 | Schema::dropIfExists('roles'); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /database/migrations/2020_07_11_151894_create_permissions_table.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | class CreatePermissionsTable extends Migration 13 | { 14 | /** 15 | * Run the migrations. 16 | * @return void 17 | */ 18 | public function up() 19 | { 20 | Schema::create('permissions', function (Blueprint $table) { 21 | $table->increments('id'); 22 | $table->string('name', 191); 23 | $table->string('slug', 191)->unique(); 24 | $table->string('description', 191); 25 | $table->timestamps(); 26 | }); 27 | } 28 | 29 | /** 30 | * Reverse the migrations. 31 | * @return void 32 | */ 33 | public function down() 34 | { 35 | Schema::dropIfExists('permissions'); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018 Andrey Girnik 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /src/Http/Requests/Delete.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | class Delete extends FormRequest 15 | { 16 | /** 17 | * Determine if the user is authorized to make this request. 18 | * 19 | * @return bool 20 | */ 21 | public function authorize() 22 | { 23 | return !empty(config('rbac.routesMainPermission')) ? $this->user()->can(config('rbac.routesMainPermission')) : true; 24 | } 25 | 26 | /** 27 | * Get the validation rules that apply to the request. 28 | * 29 | * @return array 30 | */ 31 | public function rules() 32 | { 33 | return [ 34 | 'items' => 'required|array', 35 | ]; 36 | } 37 | 38 | /** 39 | * @return array 40 | */ 41 | public function messages() 42 | { 43 | return [ 44 | 'items.required' => __('rbac::validation.required_to_delete'), 45 | ]; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Classes/MemberToRole.php: -------------------------------------------------------------------------------- 1 | member = $member; 34 | $obj->role = $role; 35 | 36 | return $obj; 37 | } 38 | 39 | /** 40 | * @return RbacUserInterface 41 | */ 42 | public function getMember(): RbacUserInterface 43 | { 44 | return $this->member; 45 | } 46 | 47 | /** 48 | * @return Role 49 | */ 50 | public function getRole(): Role 51 | { 52 | return $this->role; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /database/migrations/2020_07_11_151925_create_role_permission_table.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | class CreateRolePermissionTable extends Migration 13 | { 14 | /** 15 | * Run the migrations. 16 | * @return void 17 | */ 18 | public function up() 19 | { 20 | Schema::create('role_permission', function (Blueprint $table) { 21 | $table->unsignedInteger('role_id'); 22 | $table->unsignedInteger('permission_id'); 23 | $table->timestamps(); 24 | $table->unique(['permission_id','role_id']); 25 | $table->foreign('role_id')->references('id')->on('roles')->onDelete('cascade'); 26 | $table->foreign('permission_id')->references('id')->on('permissions')->onDelete('cascade'); 27 | }); 28 | } 29 | 30 | /** 31 | * Reverse the migrations. 32 | * @return void 33 | */ 34 | public function down() 35 | { 36 | Schema::dropIfExists('role_permission'); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "itstructure/laravel-rbac", 3 | "description": "Laravel package for RBAC manage", 4 | "type": "library", 5 | "keywords": ["laravel", "rbac", "role", "permission", "profile"], 6 | "license": "MIT", 7 | "authors": [ 8 | { 9 | "name": "Andrey Girnik", 10 | "email": "girnikandrey@gmail.com", 11 | "homepage": "https://github.com/itstructure", 12 | "role": "Developer" 13 | } 14 | ], 15 | "minimum-stability": "dev", 16 | "prefer-stable": true, 17 | "require": { 18 | "laravel/framework": "^8.0|^9.0|^10.0|^11.0|^12.0", 19 | "php": ">=7.3.0", 20 | "itstructure/laravel-grid-view": "^1.1" 21 | }, 22 | "classmap": [ 23 | "database/migrations", 24 | "database/seeders", 25 | "src/Models", 26 | "src/Http/Requests", 27 | "src/Http/Controllers" 28 | ], 29 | "autoload": { 30 | "psr-4": { 31 | "Itstructure\\LaRbac\\": "src" 32 | } 33 | }, 34 | "extra": { 35 | "laravel": { 36 | "providers": [ 37 | "Itstructure\\LaRbac\\RbacServiceProvider" 38 | ] 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/Http/Requests/UpdateUser.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | class UpdateUser extends FormRequest 15 | { 16 | /** 17 | * Determine if the user is authorized to make this request. 18 | * 19 | * @return bool 20 | */ 21 | public function authorize() 22 | { 23 | return !empty(config('rbac.routesMainPermission')) ? $this->user()->can(config('rbac.routesMainPermission')) : true; 24 | } 25 | 26 | /** 27 | * Get the validation rules that apply to the request. 28 | * 29 | * @return array 30 | */ 31 | public function rules() 32 | { 33 | return [ 34 | 'roles' => 'required|array', 35 | ]; 36 | } 37 | 38 | /** 39 | * Get the error messages for the defined validation rules. 40 | * 41 | * @return array 42 | */ 43 | public function messages() 44 | { 45 | return [ 46 | 'required' => __('rbac::validation.required'), 47 | ]; 48 | } 49 | 50 | /** 51 | * Get custom attributes for validator errors. 52 | * 53 | * @return array 54 | */ 55 | public function attributes() 56 | { 57 | return [ 58 | 'roles' => __('rbac::roles.roles') 59 | ]; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/Interfaces/RbacUserInterface.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | interface RbacUserInterface 15 | { 16 | /** 17 | * User identifier. 18 | * @return mixed 19 | */ 20 | public function getMemberKeyAttribute(); 21 | 22 | /** 23 | * User name. 24 | * @return string 25 | */ 26 | public function getMemberNameAttribute(): string; 27 | 28 | /** 29 | * Set new filled roles. 30 | * @param $value 31 | * @return void 32 | */ 33 | public function setRolesAttribute($value): void; 34 | 35 | /** 36 | * Get user roles by relation. 37 | * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany 38 | */ 39 | public function roles(); 40 | 41 | /** 42 | * Checks if User has access to $permissions. 43 | * @param array $permissions 44 | * @return bool 45 | */ 46 | public function hasAccess(array $permissions) : bool; 47 | 48 | /** 49 | * Checks if the user belongs to role. 50 | * @param string $roleSlug 51 | * @return bool 52 | */ 53 | public function inRole(string $roleSlug): bool; 54 | 55 | /** 56 | * @param RbacUserInterface $member 57 | * @param Role $role 58 | * @return bool 59 | */ 60 | public function canAssignRole(RbacUserInterface $member, Role $role): bool; 61 | } 62 | -------------------------------------------------------------------------------- /src/RbacRouteServiceProvider.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | class RbacRouteServiceProvider extends RouteServiceProvider 16 | { 17 | /** 18 | * This namespace is applied to your controller routes. 19 | * In addition, it is set as the URL generator's root namespace. 20 | * @var string 21 | */ 22 | protected $namespace = 'Itstructure\LaRbac\Http\Controllers'; 23 | 24 | /** 25 | * Define your route model bindings, pattern filters, etc. 26 | * @return void 27 | */ 28 | public function boot() 29 | { 30 | parent::boot(); 31 | } 32 | 33 | /** 34 | * Define the routes for the application. 35 | * @return void 36 | */ 37 | public function map() 38 | { 39 | $this->mapWebRoutes(); 40 | } 41 | 42 | /** 43 | * Define the "web" routes for the application. 44 | * These routes all receive session state, CSRF protection, etc. 45 | * @return void 46 | */ 47 | protected function mapWebRoutes() 48 | { 49 | Route::middleware('web') 50 | ->namespace($this->namespace) 51 | ->group($this->getRoutesFile()); 52 | } 53 | 54 | /** 55 | * Get routes file. 56 | * @return mixed 57 | */ 58 | private function getRoutesFile() 59 | { 60 | return __DIR__ . DIRECTORY_SEPARATOR . 'routes.php'; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/Models/Permission.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | class Permission extends Model 16 | { 17 | /** 18 | * Permissions 19 | */ 20 | const ADMINISTRATE_PERMISSION = 'administrate'; 21 | const VIEW_RECORD_PERMISSION = 'view-record'; 22 | const CREATE_RECORD_PERMISSION = 'create-record'; 23 | const UPDATE_RECORD_PERMISSION = 'update-record'; 24 | const DELETE_RECORD_PERMISSION = 'delete-record'; 25 | const PUBLISH_RECORD_PERMISSION = 'publish-record'; 26 | 27 | /** 28 | * Action flags 29 | */ 30 | const ASSIGN_ROLE_FLAG = 'assign-role'; 31 | const DELETE_MEMBER_FLAG = 'delete-member'; 32 | 33 | /** 34 | * @var array 35 | */ 36 | protected $fillable = [ 37 | 'name', 'slug', 'description', 38 | ]; 39 | 40 | /** 41 | * Get roles by relation. 42 | * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany 43 | */ 44 | public function roles() 45 | { 46 | return $this->belongsToMany(Role::class, 'role_permission', 'permission_id', 'role_id')->withTimestamps(); 47 | } 48 | 49 | /** 50 | * Set name. 51 | * Set slug by name. 52 | * @param $value 53 | * @return void 54 | */ 55 | public function setNameAttribute($value) 56 | { 57 | $this->attributes['name'] = strtolower($value); 58 | $this->attributes['slug'] = Str::slug($value, '-'); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /resources/views/users/_fields.blade.php: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 |
5 | @foreach($allRoles as $key => $role) 6 |
7 | id, $currentRoles)) checked @endif > 10 | 13 |
14 | 15 | @if(isset($currentRoles) && in_array($role->id, $currentRoles)) 16 | @cannot(Itstructure\LaRbac\Models\Permission::ASSIGN_ROLE_FLAG, Itstructure\LaRbac\Classes\MemberToRole::make($user, $role)) 17 | 18 | @endcannot 19 | @endif 20 | @endforeach 21 |
22 |
23 |
24 | 25 | @if ($errors->has('roles')) 26 |
27 |
28 | 31 |
32 |
33 | @endif -------------------------------------------------------------------------------- /database/seeders/PermissionSeeder.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | class PermissionSeeder extends Seeder 13 | { 14 | /** 15 | * Run the database seeds. 16 | * @return void 17 | */ 18 | public function run() 19 | { 20 | $this->createRecord( 21 | Permission::ADMINISTRATE_PERMISSION, 22 | 'Total administrate of users and content' 23 | ); 24 | 25 | $this->createRecord( 26 | Permission::VIEW_RECORD_PERMISSION, 27 | 'Permission to view record' 28 | ); 29 | 30 | $this->createRecord( 31 | Permission::CREATE_RECORD_PERMISSION, 32 | 'Permission to create record' 33 | ); 34 | 35 | $this->createRecord( 36 | Permission::UPDATE_RECORD_PERMISSION, 37 | 'Permission to update record' 38 | ); 39 | 40 | $this->createRecord( 41 | Permission::DELETE_RECORD_PERMISSION, 42 | 'Permission to delete record' 43 | ); 44 | 45 | $this->createRecord( 46 | Permission::PUBLISH_RECORD_PERMISSION, 47 | 'Permission to publish record' 48 | ); 49 | } 50 | 51 | /** 52 | * Create permission record in database. 53 | * @param string $slug 54 | * @param string $description 55 | * @return void 56 | */ 57 | private function createRecord(string $slug, string $description): void 58 | { 59 | Permission::create([ 60 | 'name' => str_replace('-', ' ', ucfirst($slug)), 61 | 'slug' => $slug, 62 | 'description' => $description, 63 | ]); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/Http/Requests/StorePermission.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | class StorePermission extends FormRequest 15 | { 16 | /** 17 | * Determine if the user is authorized to make this request. 18 | * 19 | * @return bool 20 | */ 21 | public function authorize() 22 | { 23 | return !empty(config('rbac.routesMainPermission')) ? $this->user()->can(config('rbac.routesMainPermission')) : true; 24 | } 25 | 26 | /** 27 | * Get the validation rules that apply to the request. 28 | * 29 | * @return array 30 | */ 31 | public function rules() 32 | { 33 | return [ 34 | 'name' => 'required|string|regex:/^[\w\s\-]+$/|min:3|max:191|unique:permissions', 35 | 'description' => 'required|string|min:3|max:191|unique:permissions', 36 | ]; 37 | } 38 | 39 | /** 40 | * Get the error messages for the defined validation rules. 41 | * 42 | * @return array 43 | */ 44 | public function messages() 45 | { 46 | return [ 47 | 'required' => __('rbac::validation.required'), 48 | 'string' => __('rbac::validation.string'), 49 | 'regex' => __('rbac::validation.regex'), 50 | 'min' => __('rbac::validation.min'), 51 | 'max' => __('rbac::validation.max'), 52 | 'unique' => __('rbac::validation.unique'), 53 | ]; 54 | } 55 | 56 | /** 57 | * Get custom attributes for validator errors. 58 | * 59 | * @return array 60 | */ 61 | public function attributes() 62 | { 63 | return [ 64 | 'name' => __('rbac::main.name'), 65 | 'description' => __('rbac::main.description'), 66 | ]; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /resources/views/permissions/_fields.blade.php: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | 5 | 7 | @if ($errors->has('name')) 8 |
9 | {{ $errors->first('name') }} 10 |
11 | @endif 12 |
13 |
14 |
15 | 16 |
17 |
18 |
19 | 20 | 22 | @if ($errors->has('description')) 23 |
24 | {{ $errors->first('description') }} 25 |
26 | @endif 27 |
28 |
29 |
30 | 31 | @if($edit) 32 |
33 |
34 |
35 | 36 | 37 |
38 |
39 |
40 | @endif -------------------------------------------------------------------------------- /src/Http/Requests/StoreRole.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | class StoreRole extends FormRequest 15 | { 16 | /** 17 | * Determine if the user is authorized to make this request. 18 | * 19 | * @return bool 20 | */ 21 | public function authorize() 22 | { 23 | return !empty(config('rbac.routesMainPermission')) ? $this->user()->can(config('rbac.routesMainPermission')) : true; 24 | } 25 | 26 | /** 27 | * Get the validation rules that apply to the request. 28 | * 29 | * @return array 30 | */ 31 | public function rules() 32 | { 33 | return [ 34 | 'name' => 'required|string|regex:/^[\w\s\-]+$/|min:3|max:191|unique:roles', 35 | 'description' => 'required|string|min:3|max:191|unique:roles', 36 | 'permissions' => 'required|array', 37 | ]; 38 | } 39 | 40 | /** 41 | * Get the error messages for the defined validation rules. 42 | * 43 | * @return array 44 | */ 45 | public function messages() 46 | { 47 | return [ 48 | 'required' => __('rbac::validation.required'), 49 | 'string' => __('rbac::validation.string'), 50 | 'regex' => __('rbac::validation.regex'), 51 | 'min' => __('rbac::validation.min'), 52 | 'max' => __('rbac::validation.max'), 53 | 'unique' => __('rbac::validation.unique'), 54 | ]; 55 | } 56 | 57 | /** 58 | * Get custom attributes for validator errors. 59 | * 60 | * @return array 61 | */ 62 | public function attributes() 63 | { 64 | return [ 65 | 'name' => __('rbac::main.name'), 66 | 'description' => __('rbac::main.description'), 67 | 'permissions' => __('rbac::permissions.permissions'), 68 | ]; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /changelog.md: -------------------------------------------------------------------------------- 1 | ### CHANGE LOG: 2 | 3 | **3.0.18 February 28, 2025:** 4 | - Describe `User` model tuning. 5 | 6 | **3.0.17 February 28, 2025:** 7 | - Fix grid view composer dependency. Fix README. 8 | 9 | **3.0.16 February 26, 2025:** 10 | - Add Laravel 12 support. 11 | 12 | **3.0.15 July 15, 2024:** 13 | - Fix README and dependency on grid view package to `^1.1.4`. 14 | 15 | **3.0.14 July 14, 2024:** 16 | - Small text fix. 17 | 18 | **3.0.13 July 14, 2024:** 19 | - Small fix for describing text in Commands classes. 20 | 21 | **3.0.12 March 20, 2024:** 22 | - Add support for Laravel 11. 23 | 24 | **3.0.11 February 04, 2024:** 25 | - Change dependence on Laravel Grid View. 26 | 27 | **3.0.10 February 04, 2024:** 28 | - Update copyright year and Readme. 29 | - Require Laravel Grid View ~1.1.0. 30 | 31 | **3.0.9 March 24, 2023:** 32 | - Improve code. Add base Controller. 33 | 34 | **3.0.8 February 18, 2023:** 35 | - Add support for Laravel 10. 36 | 37 | **3.0.7 January 24, 2023:** 38 | - Update copyright year and Readme. 39 | 40 | **3.0.6 March 22, 2022:** 41 | - Recommendation about AdminLTE layout installation. 42 | 43 | **3.0.5 March 6, 2022:** 44 | - Add support for Laravel 9. 45 | - Add view examples. 46 | 47 | **3.0.4 January 10, 2022:** 48 | - Readme fixes. Copyright year. 49 | 50 | **3.0.3 April 22, 2021:** 51 | - Update requirement of **grid view** package to ~1.0.7. 52 | 53 | **3.0.2 April 22, 2021:** 54 | - Update requirement of **grid view** package to ~1.0.6. 55 | - Add scrutinizer build option. 56 | 57 | **3.0.1 February 23, 2021:** 58 | - Upgrade copyright year. 59 | 60 | **3.0.0 September 10, 2020:** 61 | - Set compatibility for Laravel 8. 62 | 63 | **2.0.1 September 9, 2020:** 64 | - Add comments for 2.x version, which is for Laravel 6 or 7. 65 | 66 | **2.0.0 July 12, 2020:** 67 | - Total package reconstruction. 68 | 69 | **1.1.1 August 11, 2018:** 70 | - Code fixes according with the PSR standards. 71 | 72 | **1.1.0 July 23, 2018:** 73 | - Modify delete items 74 | - Protect self user delete 75 | - Protect role assign 76 | 77 | **1.0.0 July 22, 2018:** 78 | - Create package, which provides management with the next data: 79 | - Roles 80 | - Permissions 81 | - Assign roles for users 82 | - Created documentation. 83 | -------------------------------------------------------------------------------- /src/Commands/AdminCommand.php: -------------------------------------------------------------------------------- 1 | 17 | */ 18 | class AdminCommand extends Command 19 | { 20 | /** 21 | * The name and signature of the console command. 22 | * @var string 23 | */ 24 | protected $signature = 'rbac:admin'; 25 | 26 | /** 27 | * The console command description. 28 | * @var string 29 | */ 30 | protected $description = 'Assign Admin role for existing special user.'; 31 | 32 | /** 33 | * @var RbacUserInterface|ParentUser 34 | */ 35 | protected $userModelClass; 36 | 37 | /** 38 | * @var int 39 | */ 40 | protected $adminUserId; 41 | 42 | /** 43 | * AdminCommand constructor. 44 | */ 45 | public function __construct() 46 | { 47 | parent::__construct(); 48 | 49 | $this->userModelClass = config('rbac.userModelClass'); 50 | $this->adminUserId = config('rbac.adminUserId'); 51 | } 52 | 53 | /** 54 | * Execute the console command. 55 | */ 56 | public function handle() 57 | { 58 | try { 59 | $this->info('Start assign admin role for existing special user.'); 60 | 61 | Helper::checkUserModel($this->userModelClass); 62 | 63 | Helper::checkAdminUserId($this->adminUserId); 64 | 65 | $adminUser = Helper::retrieveUserModel($this->userModelClass, $this->adminUserId); 66 | 67 | $adminRoleId = Role::where('slug', Role::ADMIN_ROLE)->firstOrFail()->id; 68 | 69 | /** @var RbacUserInterface $adminUser */ 70 | $adminUser->roles()->attach([ 71 | $adminRoleId 72 | ]); 73 | 74 | $this->info('Admin role is assigned successfully.'); 75 | 76 | } catch (\Exception $e) { 77 | $this->error('Failed!'); 78 | $this->error($e->getMessage()); 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /resources/views/permissions/show.blade.php: -------------------------------------------------------------------------------- 1 | @extends($rbacLayout) 2 | @section('title', __('rbac::permissions.permission_details')) 3 | @section('content') 4 | 5 |
6 |

{!! __('rbac::permissions.permission_details') !!}: {{ $permission->name }}

7 | 8 |
9 |
10 |
11 | {!! __('rbac::permissions.edit_permission') !!} 12 | 13 | 14 | 15 |
16 |
17 |
18 | 19 |
20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 |
{!! __('rbac::main.attribute') !!}{!! __('rbac::main.value') !!}
{!! __('rbac::main.name') !!}{{ $permission->name }}
{!! __('rbac::main.slug') !!}{{ $permission->slug }}
{!! __('rbac::main.description') !!}{{ $permission->description }}
43 |
44 |
45 |
46 | 47 | @endsection 48 | -------------------------------------------------------------------------------- /src/Http/Requests/UpdatePermission.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | class UpdatePermission extends FormRequest 16 | { 17 | /** 18 | * Determine if the user is authorized to make this request. 19 | * 20 | * @return bool 21 | */ 22 | public function authorize() 23 | { 24 | return !empty(config('rbac.routesMainPermission')) ? $this->user()->can(config('rbac.routesMainPermission')) : true; 25 | } 26 | 27 | /** 28 | * Get the validation rules that apply to the request. 29 | * 30 | * @return array 31 | */ 32 | public function rules() 33 | { 34 | $id = $this->route('permission')->id; 35 | return [ 36 | 'name' => [ 37 | 'required', 38 | 'string', 39 | 'regex:/^[\w\s\-]+$/', 40 | 'min:3', 41 | 'max:191', 42 | Rule::unique('permissions')->where('id', '<>', $id), 43 | ], 44 | 'description' => [ 45 | 'required', 46 | 'string', 47 | 'min:3', 48 | 'max:191', 49 | Rule::unique('permissions')->where('id', '<>', $id), 50 | ], 51 | ]; 52 | } 53 | 54 | /** 55 | * Get the error messages for the defined validation rules. 56 | * 57 | * @return array 58 | */ 59 | public function messages() 60 | { 61 | return [ 62 | 'required' => __('rbac::validation.required'), 63 | 'string' => __('rbac::validation.string'), 64 | 'regex' => __('rbac::validation.regex'), 65 | 'min' => __('rbac::validation.min'), 66 | 'max' => __('rbac::validation.max'), 67 | 'unique' => __('rbac::validation.unique'), 68 | ]; 69 | } 70 | 71 | /** 72 | * Get custom attributes for validator errors. 73 | * 74 | * @return array 75 | */ 76 | public function attributes() 77 | { 78 | return [ 79 | 'name' => __('rbac::main.name'), 80 | 'description' => __('rbac::main.description'), 81 | ]; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/Http/Requests/UpdateRole.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | class UpdateRole extends FormRequest 16 | { 17 | /** 18 | * Determine if the user is authorized to make this request. 19 | * 20 | * @return bool 21 | */ 22 | public function authorize() 23 | { 24 | return !empty(config('rbac.routesMainPermission')) ? $this->user()->can(config('rbac.routesMainPermission')) : true; 25 | } 26 | 27 | /** 28 | * Get the validation rules that apply to the request. 29 | * 30 | * @return array 31 | */ 32 | public function rules() 33 | { 34 | $id = $this->route('role')->id; 35 | return [ 36 | 'name' => [ 37 | 'required', 38 | 'string', 39 | 'regex:/^[\w\s\-]+$/', 40 | 'min:3', 41 | 'max:191', 42 | Rule::unique('roles')->where('id', '<>', $id), 43 | ], 44 | 'description' => [ 45 | 'required', 46 | 'string', 47 | 'min:3', 48 | 'max:191', 49 | Rule::unique('roles')->where('id', '<>', $id), 50 | ], 51 | 'permissions' => 'required|array', 52 | ]; 53 | } 54 | 55 | /** 56 | * Get the error messages for the defined validation rules. 57 | * 58 | * @return array 59 | */ 60 | public function messages() 61 | { 62 | return [ 63 | 'required' => __('rbac::validation.required'), 64 | 'string' => __('rbac::validation.string'), 65 | 'regex' => __('rbac::validation.regex'), 66 | 'min' => __('rbac::validation.min'), 67 | 'max' => __('rbac::validation.max'), 68 | 'unique' => __('rbac::validation.unique'), 69 | ]; 70 | } 71 | 72 | /** 73 | * Get custom attributes for validator errors. 74 | * 75 | * @return array 76 | */ 77 | public function attributes() 78 | { 79 | return [ 80 | 'name' => __('rbac::main.name'), 81 | 'description' => __('rbac::main.description'), 82 | 'permissions' => __('rbac::permissions.permissions'), 83 | ]; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /database/migrations/2020_07_11_151834_create_user_role_table.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | class CreateUserRoleTable extends Migration 14 | { 15 | /** 16 | * @var string 17 | */ 18 | protected $userModelClass; 19 | 20 | /** 21 | * UserController constructor. 22 | */ 23 | public function __construct() 24 | { 25 | $this->userModelClass = config('rbac.userModelClass'); 26 | } 27 | 28 | /** 29 | * Run the migrations. 30 | * @throws Exception 31 | * @throws \Exception 32 | */ 33 | public function up() 34 | { 35 | Helper::checkUserModel($this->userModelClass); 36 | 37 | /* @var Illuminate\Foundation\Auth\User $userNewModel */ 38 | $userNewModel = new $this->userModelClass(); 39 | 40 | Helper::checkUserModelKeyType($userNewModel); 41 | 42 | $userModelTable = $userNewModel->getTable(); 43 | 44 | $userModelKeyName = $userNewModel->getAuthIdentifierName(); 45 | 46 | $userTablePrimaryType = Schema::getConnection()->getSchemaBuilder()->getColumnType($userModelTable, $userModelKeyName); 47 | 48 | Helper::checkUserTablePrimaryType($userTablePrimaryType, $userModelKeyName, $userModelTable); 49 | 50 | Schema::create('user_role', function (Blueprint $table) use ($userModelKeyName, $userModelTable, $userTablePrimaryType) { 51 | switch ($userTablePrimaryType) { 52 | case 'bigint': 53 | $table->unsignedBigInteger('user_id'); 54 | break; 55 | case 'integer': 56 | $table->unsignedInteger('user_id'); 57 | break; 58 | } 59 | $table->unsignedInteger('role_id'); 60 | $table->timestamps(); 61 | $table->unique(['user_id','role_id']); 62 | $table->foreign('user_id')->references($userModelKeyName)->on($userModelTable)->onDelete('cascade'); 63 | $table->foreign('role_id')->references('id')->on('roles')->onDelete('cascade'); 64 | }); 65 | } 66 | 67 | /** 68 | * Reverse the migrations. 69 | * @return void 70 | */ 71 | public function down() 72 | { 73 | Schema::dropIfExists('user_role'); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/Commands/DatabaseCommand.php: -------------------------------------------------------------------------------- 1 | 13 | */ 14 | class DatabaseCommand extends Command 15 | { 16 | /** 17 | * The name and signature of the console command. 18 | * @var string 19 | */ 20 | protected $signature = 'rbac:database '. 21 | '{--force : Overwrite existing files by default.}'. 22 | '{--only= : Run only specific process. Available values: migrate, seed.}'; 23 | 24 | /** 25 | * The console command description. 26 | * @var string 27 | */ 28 | protected $description = 'Fill database - migrate and seed.'; 29 | 30 | /** 31 | * Execute the console command. 32 | * @return void 33 | */ 34 | public function handle() 35 | { 36 | try { 37 | $this->info('Start fill database...'); 38 | 39 | $callArguments = []; 40 | 41 | if ($this->option('force')) { 42 | $this->warn('Force process.'); 43 | $callArguments['--force'] = true; 44 | } 45 | 46 | if ($this->option('only')) { 47 | switch ($this->option('only')) { 48 | case 'migrate': 49 | $this->info('Migration process...'); 50 | $this->call('migrate', $callArguments); 51 | break; 52 | 53 | case 'seed': 54 | $this->info('Seeding process...'); 55 | $this->call('db:seed', array_merge([ 56 | '--class' => 'LaRbacDatabaseSeeder', 57 | ], $callArguments) 58 | ); 59 | break; 60 | 61 | default: 62 | $this->error('Invalid "only" argument value!'); 63 | return; 64 | break; 65 | } 66 | 67 | } else { 68 | $this->info('Run all processes: migration and seeding.'); 69 | $this->call('migrate', $callArguments); 70 | $this->call('db:seed', array_merge([ 71 | '--class' => 'LaRbacDatabaseSeeder', 72 | ], $callArguments) 73 | ); 74 | } 75 | 76 | $this->info('Filling database is completed successfully.'); 77 | 78 | } catch (\Exception $e) { 79 | $this->error('Failed!'); 80 | $this->error($e->getMessage()); 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /resources/views/users/show.blade.php: -------------------------------------------------------------------------------- 1 | @extends($rbacLayout) 2 | @section('title', __('rbac::users.user_details')) 3 | @section('content') 4 | 5 |
6 |

{!! __('rbac::users.user_details') !!}: {{ $user->memberName }}

7 | 8 |
9 |
10 |
11 | {!! __('rbac::users.assign_roles') !!} 12 | @can(Itstructure\LaRbac\Models\Permission::DELETE_MEMBER_FLAG, $user->memberKey) 13 | 14 | 15 | 16 | @endcan 17 |
18 |
19 |
20 | 21 |
22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 46 | 47 | 48 |
{!! __('rbac::main.attribute') !!}{!! __('rbac::main.value') !!}
{!! __('rbac::users.name') !!}{{ $user->memberName }}
{!! __('rbac::roles.roles') !!} 38 |
    39 | @foreach($user->roles as $role) 40 |
  • 41 | {{ $role->name }} 42 |
  • 43 | @endforeach 44 |
45 |
49 |
50 |
51 |
52 | 53 | @endsection 54 | -------------------------------------------------------------------------------- /database/seeders/RoleSeeder.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | class RoleSeeder extends Seeder 13 | { 14 | /** 15 | * Run the database seeds. 16 | * @return void 17 | */ 18 | public function run() 19 | { 20 | $totalPermissionId = Permission::where('slug', Permission::ADMINISTRATE_PERMISSION)->firstOrFail()->id; 21 | $viewPermissionId = Permission::where('slug', Permission::VIEW_RECORD_PERMISSION)->firstOrFail()->id; 22 | $createPermissionId = Permission::where('slug', Permission::CREATE_RECORD_PERMISSION)->firstOrFail()->id; 23 | $updatePermissionId = Permission::where('slug', Permission::UPDATE_RECORD_PERMISSION)->firstOrFail()->id; 24 | $deletePermissionId = Permission::where('slug', Permission::DELETE_RECORD_PERMISSION)->firstOrFail()->id; 25 | $publishPermissionId = Permission::where('slug', Permission::PUBLISH_RECORD_PERMISSION)->firstOrFail()->id; 26 | 27 | $this->createRecord( 28 | Role::ADMIN_ROLE, 29 | 'Administrator', 30 | [ 31 | $totalPermissionId, 32 | $viewPermissionId, 33 | $createPermissionId, 34 | $updatePermissionId, 35 | $deletePermissionId, 36 | $publishPermissionId 37 | ] 38 | ); 39 | 40 | $this->createRecord( 41 | Role::MANAGER_ROLE, 42 | 'Content manager', 43 | [ 44 | $viewPermissionId, 45 | $createPermissionId, 46 | $updatePermissionId, 47 | $deletePermissionId, 48 | $publishPermissionId 49 | ] 50 | ); 51 | 52 | $this->createRecord( 53 | Role::EDITOR_ROLE, 54 | 'Record editor', 55 | [ 56 | $viewPermissionId, 57 | $createPermissionId, 58 | $updatePermissionId, 59 | $deletePermissionId, 60 | $publishPermissionId 61 | ] 62 | ); 63 | 64 | $this->createRecord( 65 | Role::USER_ROLE, 66 | 'Simple user', 67 | [ 68 | $viewPermissionId 69 | ] 70 | ); 71 | } 72 | 73 | /** 74 | * Create role record in database. 75 | * @param string $slug 76 | * @param string $description 77 | * @param array $permissions 78 | * @return void 79 | */ 80 | private function createRecord(string $slug, string $description, array $permissions): void 81 | { 82 | Role::create([ 83 | 'name' => ucfirst($slug), 84 | 'slug' => $slug, 85 | 'description' => $description, 86 | ])->permissions() 87 | ->attach($permissions); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /resources/views/roles/_fields.blade.php: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | 5 | 7 | @if ($errors->has('name')) 8 |
9 | {{ $errors->first('name') }} 10 |
11 | @endif 12 |
13 |
14 |
15 | 16 |
17 |
18 |
19 | 20 | 22 | @if ($errors->has('description')) 23 |
24 | {{ $errors->first('description') }} 25 |
26 | @endif 27 |
28 |
29 |
30 | 31 | @if($edit) 32 |
33 |
34 |
35 | 36 | 37 |
38 |
39 |
40 | @endif 41 | 42 |
43 |
44 | 45 | 46 |
47 | @foreach($allPermissions as $id => $name) 48 |
49 | 51 | 54 |
55 | @endforeach 56 |
57 | 58 | @if ($errors->has('permissions')) 59 | 62 | @endif 63 |
64 |
65 | -------------------------------------------------------------------------------- /resources/views/roles/show.blade.php: -------------------------------------------------------------------------------- 1 | @extends($rbacLayout) 2 | @section('title', __('rbac::roles.role_details')) 3 | @section('content') 4 | 5 |
6 |

{!! __('rbac::roles.role_details') !!}: {{ $role->name }}

7 | 8 |
9 |
10 |
11 | {!! __('rbac::roles.edit_role') !!} 12 | 13 | 14 | 15 |
16 |
17 |
18 | 19 |
20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 54 | 55 | 56 |
{!! __('rbac::main.attribute') !!}{!! __('rbac::main.value') !!}
{!! __('rbac::main.name') !!}{{ $role->name }}
{!! __('rbac::main.slug') !!}{{ $role->slug }}
{!! __('rbac::main.description') !!}{{ $role->description }}
{!! __('rbac::permissions.permissions') !!} 44 | 53 |
57 |
58 |
59 |
60 | 61 | @endsection 62 | -------------------------------------------------------------------------------- /src/routes.php: -------------------------------------------------------------------------------- 1 | 'rbac', 11 | 'middleware' => array_merge( 12 | is_array(config('rbac.routesAuthMiddlewares')) ? config('rbac.routesAuthMiddlewares') : ['auth'], 13 | !empty(config('rbac.routesMainPermission')) ? ['can:'.config('rbac.routesMainPermission')] : [] 14 | ) 15 | ], function () { 16 | 17 | // Users (members) 18 | Route::group(['prefix' => 'users'], function () { 19 | 20 | Route::get('/', [UserController::class, 'index']) 21 | ->name('list_users'); 22 | 23 | Route::get('show/{id}', [UserController::class, 'show']) 24 | ->name('show_user'); 25 | 26 | Route::get('edit/{id}', [UserController::class, 'edit']) 27 | ->name('edit_user'); 28 | 29 | Route::post('update/{id}', [UserController::class, 'update']) 30 | ->name('update_user'); 31 | 32 | Route::post('delete', [UserController::class, 'delete']) 33 | ->name('delete_user'); 34 | }); 35 | 36 | // Roles 37 | Route::group(['prefix' => 'roles'], function () { 38 | 39 | Route::get('/', [RoleController::class, 'index']) 40 | ->name('list_roles'); 41 | 42 | Route::get('show/{id}', [RoleController::class, 'show']) 43 | ->name('show_role'); 44 | 45 | Route::get('create', [RoleController::class, 'create']) 46 | ->name('create_role'); 47 | 48 | Route::get('edit/{role}', [RoleController::class, 'edit']) 49 | ->name('edit_role'); 50 | 51 | Route::post('store', [RoleController::class, 'store']) 52 | ->name('store_role'); 53 | 54 | Route::post('update/{role}', [RoleController::class, 'update']) 55 | ->name('update_role'); 56 | 57 | Route::post('/delete', [RoleController::class, 'delete']) 58 | ->name('delete_role'); 59 | }); 60 | 61 | // Permissions 62 | Route::group(['prefix' => 'permissions'], function () { 63 | 64 | Route::get('/', [PermissionController::class, 'index']) 65 | ->name('list_permissions'); 66 | 67 | Route::get('show/{id}', [PermissionController::class, 'show']) 68 | ->name('show_permission'); 69 | 70 | Route::get('create', [PermissionController::class, 'create']) 71 | ->name('create_permission'); 72 | 73 | Route::get('edit/{permission}', [PermissionController::class, 'edit']) 74 | ->name('edit_permission'); 75 | 76 | Route::post('store', [PermissionController::class, 'store']) 77 | ->name('store_permission'); 78 | 79 | Route::post('update/{permission}', [PermissionController::class, 'update']) 80 | ->name('update_permission'); 81 | 82 | Route::post('delete', [PermissionController::class, 'delete']) 83 | ->name('delete_permission'); 84 | }); 85 | }); 86 | -------------------------------------------------------------------------------- /src/Http/Controllers/PermissionController.php: -------------------------------------------------------------------------------- 1 | 19 | */ 20 | class PermissionController extends Controller 21 | { 22 | /** 23 | * Get list of all permissions. 24 | * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View 25 | */ 26 | public function index() 27 | { 28 | $dataProvider = new EloquentDataProvider(Permission::query()); 29 | 30 | return view('rbac::permissions.index', compact('dataProvider')); 31 | } 32 | 33 | /** 34 | * Render page to create new permission. 35 | * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View 36 | */ 37 | public function create() 38 | { 39 | return view('rbac::permissions.create'); 40 | } 41 | 42 | /** 43 | * Store new permission data. 44 | * @param StorePermissionRequest $request 45 | * @return \Illuminate\Http\RedirectResponse 46 | */ 47 | public function store(StorePermissionRequest $request) 48 | { 49 | Permission::create($request->all()); 50 | 51 | return redirect()->route('list_permissions'); 52 | } 53 | 54 | /** 55 | * Render page to edit current permission. 56 | * @param Permission $permission 57 | * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View 58 | */ 59 | public function edit(Permission $permission) 60 | { 61 | return view('rbac::permissions.edit', compact('permission')); 62 | } 63 | 64 | /** 65 | * Update current permission data. 66 | * @param Permission $permission 67 | * @param UpdatePermissionRequest $request 68 | * @return \Illuminate\Http\RedirectResponse 69 | */ 70 | public function update(Permission $permission, UpdatePermissionRequest $request) 71 | { 72 | $permission->fill($request->all())->save(); 73 | 74 | return redirect()->route('show_permission', [ 75 | 'id' => $permission->id 76 | ]); 77 | } 78 | 79 | /** 80 | * Render page to show current permission. 81 | * @param int $id 82 | * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View 83 | */ 84 | public function show(int $id) 85 | { 86 | $permission = Permission::findOrFail($id); 87 | 88 | return view('rbac::permissions.show', compact('permission')); 89 | } 90 | 91 | /** 92 | * Delete current permission data. 93 | * @param DeletePermissionRequest $request 94 | * @return \Illuminate\Http\RedirectResponse 95 | */ 96 | public function delete(DeletePermissionRequest $request) 97 | { 98 | foreach ($request->items as $item) { 99 | 100 | if (!is_numeric($item)) { 101 | continue; 102 | } 103 | 104 | Permission::destroy($item); 105 | } 106 | 107 | return redirect()->route('list_permissions'); 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /src/Http/Controllers/RoleController.php: -------------------------------------------------------------------------------- 1 | 19 | */ 20 | class RoleController extends Controller 21 | { 22 | /** 23 | * Get list of all roles. 24 | * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View 25 | */ 26 | public function index() 27 | { 28 | $dataProvider = new EloquentDataProvider(Role::query()->with('permissions')); 29 | 30 | return view('rbac::roles.index', compact('dataProvider')); 31 | } 32 | 33 | /** 34 | * Render page to create new role. 35 | * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View 36 | */ 37 | public function create() 38 | { 39 | $allPermissions = Permission::orderBy('id', 'desc')->pluck('name', 'id'); 40 | 41 | return view('rbac::roles.create', compact('allPermissions')); 42 | } 43 | 44 | /** 45 | * Store new role data. 46 | * @param StoreRoleRequest $request 47 | * @return \Illuminate\Http\RedirectResponse 48 | */ 49 | public function store(StoreRoleRequest $request) 50 | { 51 | Role::create($request->all()); 52 | 53 | return redirect()->route('list_roles'); 54 | } 55 | 56 | /** 57 | * Render page to edit current role. 58 | * @param Role $role 59 | * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View 60 | */ 61 | public function edit(Role $role) 62 | { 63 | $allPermissions = Permission::orderBy('id', 'desc')->pluck('name', 'id'); 64 | $currentPermissions = old('permissions') ?? $role->permissions()->pluck('id')->toArray(); 65 | 66 | return view('rbac::roles.edit', compact('role', 'allPermissions', 'currentPermissions')); 67 | } 68 | 69 | /** 70 | * Update current role data. 71 | * @param Role $role 72 | * @param UpdateRoleRequest $request 73 | * @return \Illuminate\Http\RedirectResponse 74 | */ 75 | public function update(Role $role, UpdateRoleRequest $request) 76 | { 77 | $role->fill($request->all())->save(); 78 | 79 | return redirect()->route('show_role', [ 80 | 'id' => $role->id 81 | ]); 82 | } 83 | 84 | /** 85 | * Render page to show current role. 86 | * @param int $id 87 | * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View 88 | */ 89 | public function show(int $id) 90 | { 91 | $role = Role::findOrFail($id); 92 | 93 | return view('rbac::roles.show', compact('role')); 94 | } 95 | 96 | /** 97 | * Delete current role data. 98 | * @param DeleteRoleRequest $request 99 | * @return \Illuminate\Http\RedirectResponse 100 | */ 101 | public function delete(DeleteRoleRequest $request) 102 | { 103 | foreach ($request->items as $item) { 104 | 105 | if (!is_numeric($item)) { 106 | continue; 107 | } 108 | 109 | Role::destroy($item); 110 | } 111 | 112 | return redirect()->route('list_roles'); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/Models/Role.php: -------------------------------------------------------------------------------- 1 | 14 | */ 15 | class Role extends Model 16 | { 17 | const ADMIN_ROLE = 'admin'; 18 | const MANAGER_ROLE = 'manager'; 19 | const EDITOR_ROLE = 'editor'; 20 | const USER_ROLE = 'user'; 21 | 22 | /** 23 | * @var array 24 | */ 25 | protected $fillable = [ 26 | 'name', 'slug', 'description', 'permissions' 27 | ]; 28 | 29 | /** 30 | * @var string 31 | */ 32 | private $_userModelClass; 33 | 34 | /** 35 | * @var array 36 | */ 37 | private $_permissions; 38 | 39 | /** 40 | * Role constructor. 41 | * @param array $attributes 42 | */ 43 | public function __construct(array $attributes = []) 44 | { 45 | $this->_userModelClass = config('rbac.userModelClass'); 46 | 47 | parent::__construct($attributes); 48 | } 49 | 50 | /** 51 | * Synchronize role permissions after save model. 52 | * @param array $options 53 | * @return bool 54 | */ 55 | public function save(array $options = []) 56 | { 57 | if (!parent::save($options)) { 58 | return false; 59 | } 60 | 61 | if (null !== $this->_permissions) { 62 | $this->permissions()->sync($this->_permissions); 63 | } 64 | 65 | return true; 66 | } 67 | 68 | /** 69 | * Get users by relation. 70 | * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany 71 | */ 72 | public function users() 73 | { 74 | return $this->belongsToMany($this->_userModelClass, 'user_role', 'role_id', 'user_id')->withTimestamps(); 75 | } 76 | 77 | /** 78 | * Set name. 79 | * Set slug by name. 80 | * @param $value 81 | * @return void 82 | */ 83 | public function setNameAttribute($value) 84 | { 85 | $this->attributes['name'] = $value; 86 | $this->attributes['slug'] = Str::slug($value, '-'); 87 | } 88 | 89 | /** 90 | * Set permissions. 91 | * @param $value 92 | * @return void 93 | */ 94 | public function setPermissionsAttribute($value) 95 | { 96 | $this->_permissions = $value; 97 | } 98 | 99 | /** 100 | * Get permissions by relation. 101 | * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany 102 | */ 103 | public function permissions() 104 | { 105 | return $this->belongsToMany(Permission::class, 'role_permission', 'role_id', 'permission_id')->withTimestamps(); 106 | } 107 | 108 | /** 109 | * Check if role has permissions, transferred to the function. 110 | * @param array $permissions 111 | * @return bool 112 | */ 113 | public function hasAccess(array $permissions) : bool 114 | { 115 | foreach ($permissions as $permission) { 116 | 117 | if ($this->hasPermission($permission)) { 118 | return true; 119 | } 120 | } 121 | 122 | return false; 123 | } 124 | 125 | /** 126 | * Check if role has single permission, transferred to the function. 127 | * @param string $permission 128 | * @return bool 129 | */ 130 | private function hasPermission(string $permission) : bool 131 | { 132 | return in_array($permission, $this->permissions()->pluck('slug')->toArray()); 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /src/RbacAuthServiceProvider.php: -------------------------------------------------------------------------------- 1 | 17 | */ 18 | class RbacAuthServiceProvider extends AuthServiceProvider 19 | { 20 | /** 21 | * Register any authentication / authorization services. 22 | * @return void 23 | */ 24 | public function boot() 25 | { 26 | $this->registerPolicies(); 27 | $this->registerRbacPolicies(); 28 | } 29 | 30 | /** 31 | * Register Rbac policies. 32 | */ 33 | public function registerRbacPolicies() 34 | { 35 | /* 36 | |-------------------------------------------------------------------------- 37 | | ADMIN member section. 38 | |-------------------------------------------------------------------------- 39 | */ 40 | Gate::define(Permission::ADMINISTRATE_PERMISSION, function (RbacUserInterface $user) { 41 | return $user->hasAccess([ 42 | Permission::ADMINISTRATE_PERMISSION 43 | ]); 44 | }); 45 | 46 | Gate::define(Permission::ASSIGN_ROLE_FLAG, function (RbacUserInterface $user, MemberToRole $memberToRole) { 47 | return $user->canAssignRole($memberToRole->getMember(), $memberToRole->getRole()); 48 | }); 49 | 50 | Gate::define(Permission::DELETE_MEMBER_FLAG, function (RbacUserInterface $user, $memberKey) { 51 | return $user->getMemberKeyAttribute() != $memberKey; 52 | }); 53 | 54 | 55 | /* 56 | |-------------------------------------------------------------------------- 57 | | Record section for application. 58 | |-------------------------------------------------------------------------- 59 | */ 60 | Gate::define(Permission::VIEW_RECORD_PERMISSION, function (RbacUserInterface $user, RbacModelInterface $model = null) { 61 | return $user->hasAccess([ 62 | Permission::VIEW_RECORD_PERMISSION 63 | ]) || !empty($model) ? $user->getMemberKeyAttribute() == $model->getAuthorIdAttribute() : false; 64 | }); 65 | 66 | Gate::define(Permission::CREATE_RECORD_PERMISSION, function (RbacUserInterface $user) { 67 | return $user->hasAccess([ 68 | Permission::CREATE_RECORD_PERMISSION 69 | ]); 70 | }); 71 | 72 | Gate::define(Permission::UPDATE_RECORD_PERMISSION, function (RbacUserInterface $user, RbacModelInterface $model = null) { 73 | return $user->hasAccess([ 74 | Permission::UPDATE_RECORD_PERMISSION 75 | ]) || !empty($model) ? $user->getMemberKeyAttribute() == $model->getAuthorIdAttribute() : false; 76 | }); 77 | 78 | Gate::define(Permission::DELETE_RECORD_PERMISSION, function (RbacUserInterface $user, RbacModelInterface $model = null) { 79 | return $user->hasAccess([ 80 | Permission::DELETE_RECORD_PERMISSION 81 | ]) || !empty($model) ? $user->getMemberKeyAttribute() == $model->getAuthorIdAttribute() : false; 82 | }); 83 | 84 | Gate::define(Permission::PUBLISH_RECORD_PERMISSION, function (RbacUserInterface $user) { 85 | return $user->hasAccess([ 86 | Permission::PUBLISH_RECORD_PERMISSION 87 | ]); 88 | }); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/Http/Controllers/UserController.php: -------------------------------------------------------------------------------- 1 | 20 | */ 21 | class UserController extends Controller 22 | { 23 | /** 24 | * @var string 25 | */ 26 | private $_userModelClass; 27 | 28 | /** 29 | * UserController constructor. 30 | */ 31 | public function __construct() 32 | { 33 | $this->_userModelClass = config('rbac.userModelClass'); 34 | } 35 | 36 | /** 37 | * Get list of all users. 38 | * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View 39 | */ 40 | public function index() 41 | { 42 | /** @var Authenticatable $userModelObj */ 43 | $userModelObj = new $this->_userModelClass(); 44 | 45 | $dataProvider = new EloquentDataProvider($userModelObj->newQuery()->with('roles')); 46 | 47 | $authIdentifierName = $userModelObj->getAuthIdentifierName(); 48 | 49 | return view('rbac::users.index', compact('dataProvider', 'authIdentifierName')); 50 | } 51 | 52 | /** 53 | * Render page to edit current user. 54 | * @param int $id 55 | * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View 56 | */ 57 | public function edit(int $id) 58 | { 59 | $user = $this->findOrFail($id); 60 | 61 | $allRoles = Role::orderBy('id', 'desc')->get(); 62 | $currentRoles = old('roles') ?? $user->roles->pluck('id')->toArray(); 63 | 64 | return view('rbac::users.edit', compact('user', 'allRoles', 'currentRoles')); 65 | } 66 | 67 | /** 68 | * Update current user data. 69 | * @param int $id 70 | * @param UpdateUserRequest $request 71 | * @return \Illuminate\Http\RedirectResponse 72 | */ 73 | public function update(int $id, UpdateUserRequest $request) 74 | { 75 | $this->findOrFail($id) 76 | ->fill($request->all()) 77 | ->save(); 78 | 79 | return redirect()->route('show_user', compact('id')); 80 | } 81 | 82 | /** 83 | * Render page to show current user. 84 | * @param int $id 85 | * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View 86 | */ 87 | public function show(int $id) 88 | { 89 | $user = $this->findOrFail($id); 90 | 91 | return view('rbac::users.show', compact('user')); 92 | } 93 | 94 | /** 95 | * Delete current user data. 96 | * @param DeleteUserRequest $request 97 | * @return \Illuminate\Http\RedirectResponse 98 | */ 99 | public function delete(DeleteUserRequest $request) 100 | { 101 | foreach ($request->items as $item) { 102 | 103 | if (!is_numeric($item) || $request->user()->getAuthIdentifier() == $item) { 104 | continue; 105 | } 106 | 107 | call_user_func([ 108 | $this->_userModelClass, 109 | 'destroy', 110 | ], $item); 111 | } 112 | 113 | return redirect()->route('list_users'); 114 | } 115 | 116 | /** 117 | * Find or fail user data. 118 | * @param int $id 119 | * @return mixed 120 | */ 121 | private function findOrFail(int $id) 122 | { 123 | return Helper::retrieveUserModel($this->_userModelClass, $id); 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /src/Commands/PublishCommand.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | class PublishCommand extends Command 17 | { 18 | /** 19 | * The name and signature of the console command. 20 | * @var string 21 | */ 22 | protected $signature = 'rbac:publish '. 23 | '{--force : Overwrite existing files by default.}'. 24 | '{--only= : Publish only specific part. Available parts: config, views, lang, migrations, seeders.}'; 25 | 26 | /** 27 | * The console command description. 28 | * @var string 29 | */ 30 | protected $description = 'Publish the RBAC package parts.'; 31 | 32 | /** 33 | * Execute the console command. 34 | * @return void 35 | */ 36 | public function handle() 37 | { 38 | $this->info('Starting publication process of RBAC package parts...'); 39 | 40 | $callArguments = ['--provider' => RbacServiceProvider::class]; 41 | 42 | $dumpAutoload = false; 43 | 44 | if ($this->option('only')) { 45 | switch ($this->option('only')) { 46 | case 'config': 47 | $this->info('Publish just a part: config.'); 48 | $callArguments['--tag'] = 'config'; 49 | break; 50 | 51 | case 'views': 52 | $this->info('Publish just a part: views.'); 53 | $callArguments['--tag'] = 'views'; 54 | break; 55 | 56 | case 'lang': 57 | $this->info('Publish just a part: lang.'); 58 | $callArguments['--tag'] = 'lang'; 59 | break; 60 | 61 | case 'migrations': 62 | $this->info('Publish just a part: migrations.'); 63 | $callArguments['--tag'] = 'migrations'; 64 | $dumpAutoload = true; 65 | break; 66 | 67 | case 'seeders': 68 | $this->info('Publish just a part: seeders.'); 69 | $callArguments['--tag'] = 'seeders'; 70 | $dumpAutoload = true; 71 | break; 72 | 73 | default: 74 | $this->error('Invalid "only" argument value!'); 75 | return; 76 | break; 77 | } 78 | 79 | } else { 80 | $this->info('Publish all parts: config, views, lang, migrations, seeders.'); 81 | $dumpAutoload = true; 82 | } 83 | 84 | if ($this->option('force')) { 85 | $this->warn('Force publishing.'); 86 | $callArguments['--force'] = true; 87 | } 88 | 89 | $this->call('vendor:publish', $callArguments); 90 | 91 | if ($dumpAutoload) { 92 | $this->info('Dumping the autoloaded files and reloading all new files.'); 93 | $composer = $this->findComposer(); 94 | $process = Process::fromShellCommandline($composer.' dump-autoload -o'); 95 | $process->setTimeout(null); 96 | $process->setWorkingDirectory(base_path())->run(); 97 | } 98 | } 99 | 100 | /** 101 | * Get the composer command for the environment. 102 | * @return string 103 | */ 104 | private function findComposer() 105 | { 106 | if (file_exists(getcwd().'/composer.phar')) { 107 | return '"'.PHP_BINARY.'" '.getcwd().'/composer.phar'; 108 | } 109 | 110 | return 'composer'; 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /resources/views/permissions/index.blade.php: -------------------------------------------------------------------------------- 1 | @extends($rbacLayout) 2 | @section('title', __('rbac::permissions.permissions')) 3 | @section('content') 4 | 5 |
6 | 7 |

{!! __('rbac::permissions.create_permission') !!}

8 | 9 | @if ($errors->has('items')) 10 |
11 |
12 | 15 |
16 |
17 | @endif 18 | 19 | @php 20 | $gridData = [ 21 | 'dataProvider' => $dataProvider, 22 | 'paginatorOptions' => [ 23 | 'pageName' => 'p', 24 | ], 25 | 'rowsPerPage' => $rbacRowsPerPage, 26 | 'title' => __('rbac::permissions.permissions'), 27 | 'rowsFormAction' => route('delete_permission'), 28 | 'columnFields' => [ 29 | [ 30 | 'label' => 'ID', 31 | 'attribute' => 'id', 32 | 'htmlAttributes' => [ 33 | 'width' => '5%', 34 | ], 35 | 'filter' => false 36 | ], 37 | [ 38 | 'label' => __('rbac::main.name'), 39 | 'value' => function ($permission) { 40 | return '' . $permission->name .''; 41 | }, 42 | 'filter' => [ 43 | 'class' => Itstructure\GridView\Filters\TextFilter::class, 44 | 'name' => 'name' 45 | ], 46 | 'sort' => 'name', 47 | 'format' => 'html', 48 | ], 49 | [ 50 | 'label' => __('rbac::main.slug'), 51 | 'attribute' => 'slug', 52 | ], 53 | [ 54 | 'label' => __('rbac::main.description'), 55 | 'attribute' => 'description', 56 | 'filter' => false, 57 | 'sort' => false 58 | ], 59 | [ 60 | 'label' => __('rbac::main.created'), 61 | 'attribute' => 'created_at', 62 | 'filter' => false, 63 | ], 64 | [ 65 | 'class' => Itstructure\GridView\Columns\ActionColumn::class, 66 | 'actionTypes' => [ 67 | 'view' => function ($permission) { 68 | return route('show_permission', ['id' => $permission->id]); 69 | }, 70 | 'edit' => function ($permission) { 71 | return route('edit_permission', ['permission' => $permission->id]); 72 | } 73 | ], 74 | 'htmlAttributes' => [ 75 | 'width' => '130', 76 | ], 77 | ], 78 | [ 79 | 'class' => Itstructure\GridView\Columns\CheckboxColumn::class, 80 | 'field' => 'items', 81 | 'attribute' => 'id' 82 | ], 83 | ], 84 | ]; 85 | @endphp 86 | 87 | @gridView($gridData) 88 | 89 |
90 | 91 | @endsection 92 | -------------------------------------------------------------------------------- /src/Helpers/Helper.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | class Helper 17 | { 18 | /** 19 | * Check user model for be implemented by RbacUserInterface and extended of parent Auth User model. 20 | * @param string|null $userModelClass 21 | * @throws Exception 22 | */ 23 | public static function checkUserModel(string $userModelClass = null) 24 | { 25 | if (empty($userModelClass)) { 26 | throw new Exception('User Model class is not defined in "rbac" config file.'); 27 | } 28 | 29 | static::checkUserModelInterface($userModelClass, RbacUserInterface::class); 30 | 31 | static::checkUserModelParent($userModelClass, ParentUser::class); 32 | } 33 | 34 | /** 35 | * Check user model for be implemented by RbacUserInterface. 36 | * @param string $userModelClass 37 | * @param string $interfaceClass 38 | * @throws Exception 39 | */ 40 | public static function checkUserModelInterface(string $userModelClass, string $interfaceClass): void 41 | { 42 | $userModelInterfaces = class_implements($userModelClass); 43 | 44 | if (!isset($userModelInterfaces[$interfaceClass])) { 45 | throw new Exception('User Model class must be implemented from "'.$interfaceClass.'".'); 46 | } 47 | } 48 | 49 | /** 50 | * Check user model for instance of parent Auth User model. 51 | * @param string $userModelClass 52 | * @param string $parentClass 53 | * @throws Exception 54 | */ 55 | public static function checkUserModelParent(string $userModelClass, string $parentClass): void 56 | { 57 | $userModelParents = class_parents($userModelClass); 58 | 59 | if (!isset($userModelParents[$parentClass])) { 60 | throw new Exception('User Model class should be extended from "'.$parentClass.'".'); 61 | } 62 | } 63 | 64 | /** 65 | * Check a primary key type of a User model. 66 | * @param ParentUser $userModelObject 67 | * @throws Exception 68 | */ 69 | public static function checkUserModelKeyType(ParentUser $userModelObject): void 70 | { 71 | if (!in_array($userModelObject->getKeyType(), ['int', 'integer'])) { 72 | throw new Exception('User Model keyType must be type of "int".'); 73 | } 74 | } 75 | 76 | /** 77 | * Check a primary key type of a users table. 78 | * @param string $userTablePrimaryType 79 | * @param string $userModelKeyName 80 | * @param string $userModelTable 81 | * @throws Exception 82 | */ 83 | public static function checkUserTablePrimaryType(string $userTablePrimaryType, string $userModelKeyName, string $userModelTable): void 84 | { 85 | if (!in_array($userTablePrimaryType, ['bigint', 'integer'])) { 86 | throw new Exception('Primary key "'.$userModelKeyName.'" in "'.$userModelTable.'" table must be type of "bigint" or "integer"'); 87 | } 88 | } 89 | 90 | /** 91 | * Check for correct defining of an Admin user ID value at the beginning package installation. 92 | * @param int|null $adminUserId 93 | * @throws Exception 94 | */ 95 | public static function checkAdminUserId(int $adminUserId = null): void 96 | { 97 | if (empty($adminUserId) || !is_int($adminUserId)) { 98 | throw new Exception('Identifier of a desired Admin user is not defined in "rbac" config file.'); 99 | } 100 | } 101 | 102 | /** 103 | * Retrieve user model entity. 104 | * @param string $userModelClass 105 | * @param int $adminUserId 106 | * @return mixed 107 | * @throws Exception 108 | */ 109 | public static function retrieveUserModel(string $userModelClass, int $adminUserId) 110 | { 111 | return call_user_func([ 112 | $userModelClass, 113 | 'findOrFail', 114 | ], $adminUserId); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /resources/views/users/index.blade.php: -------------------------------------------------------------------------------- 1 | @extends($rbacLayout) 2 | @section('title', __('rbac::users.users')) 3 | @section('content') 4 | 5 |
6 | 7 | @if ($errors->has('items')) 8 |
9 |
10 | 13 |
14 |
15 | @endif 16 | 17 | @php 18 | $gridData = [ 19 | 'dataProvider' => $dataProvider, 20 | 'paginatorOptions' => [ 21 | 'pageName' => 'p', 22 | ], 23 | 'rowsPerPage' => $rbacRowsPerPage, 24 | 'title' => __('rbac::users.users'), 25 | 'rowsFormAction' => route('delete_user'), 26 | 'columnFields' => [ 27 | [ 28 | 'label' => 'ID', 29 | 'attribute' => 'memberKey', 30 | 'htmlAttributes' => [ 31 | 'width' => '5%', 32 | ], 33 | 'filter' => false, 34 | 'sort' => $authIdentifierName 35 | ], 36 | [ 37 | 'label' => __('rbac::users.name'), 38 | 'value' => function ($user) { 39 | return '' . $user->memberName .''; 40 | }, 41 | 'filter' => [ 42 | 'class' => Itstructure\GridView\Filters\TextFilter::class, 43 | 'name' => 'name' 44 | ], 45 | 'sort' => 'name', 46 | 'format' => 'html', 47 | ], 48 | [ 49 | 'label' => __('rbac::roles.roles'), 50 | 'value' => function ($user) { 51 | $output = ''; 56 | }, 57 | 'filter' => false, 58 | 'sort' => false, 59 | 'format' => 'html', 60 | ], 61 | [ 62 | 'label' => __('rbac::main.created'), 63 | 'attribute' => 'created_at', 64 | 'filter' => false, 65 | ], 66 | [ 67 | 'class' => Itstructure\GridView\Columns\ActionColumn::class, 68 | 'actionTypes' => [ 69 | 'view' => function ($user) { 70 | return route('show_user', ['id' => $user->memberKey]); 71 | }, 72 | 'edit' => function ($user) { 73 | return route('edit_user', ['id' => $user->memberKey]); 74 | } 75 | ], 76 | 'htmlAttributes' => [ 77 | 'width' => '130', 78 | ], 79 | ], 80 | [ 81 | 'class' => Itstructure\GridView\Columns\CheckboxColumn::class, 82 | 'field' => 'items', 83 | 'attribute' => 'memberKey', 84 | 'display' => function ($user) { 85 | return Gate::allows(Itstructure\LaRbac\Models\Permission::DELETE_MEMBER_FLAG, $user->memberKey); 86 | } 87 | ], 88 | ], 89 | ]; 90 | @endphp 91 | 92 | @gridView($gridData) 93 | 94 |
95 | 96 | @endsection 97 | -------------------------------------------------------------------------------- /resources/views/roles/index.blade.php: -------------------------------------------------------------------------------- 1 | @extends($rbacLayout) 2 | @section('title', __('rbac::roles.roles')) 3 | @section('content') 4 | 5 |
6 | 7 |

{!! __('rbac::roles.create_role') !!}

8 | 9 | @if ($errors->has('items')) 10 |
11 |
12 | 15 |
16 |
17 | @endif 18 | 19 | @php 20 | $gridData = [ 21 | 'dataProvider' => $dataProvider, 22 | 'paginatorOptions' => [ 23 | 'pageName' => 'p', 24 | ], 25 | 'rowsPerPage' => $rbacRowsPerPage, 26 | 'title' => __('rbac::roles.roles'), 27 | 'rowsFormAction' => route('delete_role'), 28 | 'columnFields' => [ 29 | [ 30 | 'label' => 'ID', 31 | 'attribute' => 'id', 32 | 'htmlAttributes' => [ 33 | 'width' => '5%', 34 | ], 35 | 'filter' => false 36 | ], 37 | [ 38 | 'label' => __('rbac::main.name'), 39 | 'value' => function ($role) { 40 | return '' . $role->name .''; 41 | }, 42 | 'filter' => [ 43 | 'class' => Itstructure\GridView\Filters\TextFilter::class, 44 | 'name' => 'name' 45 | ], 46 | 'sort' => 'name', 47 | 'format' => 'html', 48 | ], 49 | [ 50 | 'label' => __('rbac::main.slug'), 51 | 'attribute' => 'slug', 52 | ], 53 | [ 54 | 'label' => __('rbac::main.description'), 55 | 'attribute' => 'description', 56 | 'filter' => false, 57 | 'sort' => false 58 | ], 59 | [ 60 | 'label' => __('rbac::permissions.permissions'), 61 | 'value' => function ($role) { 62 | $output = ''; 67 | }, 68 | 'filter' => false, 69 | 'sort' => false, 70 | 'format' => 'html', 71 | ], 72 | [ 73 | 'label' => __('rbac::main.created'), 74 | 'attribute' => 'created_at', 75 | 'filter' => false, 76 | ], 77 | [ 78 | 'class' => Itstructure\GridView\Columns\ActionColumn::class, 79 | 'actionTypes' => [ 80 | 'view' => function ($role) { 81 | return route('show_role', ['id' => $role->id]); 82 | }, 83 | 'edit' => function ($role) { 84 | return route('edit_role', ['role' => $role->id]); 85 | } 86 | ], 87 | 'htmlAttributes' => [ 88 | 'width' => '130', 89 | ], 90 | ], 91 | [ 92 | 'class' => Itstructure\GridView\Columns\CheckboxColumn::class, 93 | 'field' => 'items', 94 | 'attribute' => 'id' 95 | ], 96 | ], 97 | ]; 98 | @endphp 99 | 100 | @gridView($gridData) 101 | 102 |
103 | 104 | @endsection 105 | -------------------------------------------------------------------------------- /src/Traits/Administrable.php: -------------------------------------------------------------------------------- 1 | attributes[$this->getAuthIdentifierName()]; 34 | } 35 | 36 | /** 37 | * @return string 38 | */ 39 | public function getMemberNameAttribute(): string 40 | { 41 | $userNameAttributeKey = config('rbac.memberNameAttributeKey'); 42 | 43 | if (empty($userNameAttributeKey)) { 44 | return ''; 45 | } 46 | 47 | if (is_string($userNameAttributeKey)) { 48 | return $this->attributes[$userNameAttributeKey]; 49 | } 50 | 51 | if (is_callable($userNameAttributeKey)) { 52 | return $userNameAttributeKey($this); 53 | } 54 | 55 | return ''; 56 | } 57 | 58 | /** 59 | * Set new filled roles. 60 | * @param $value 61 | * @return void 62 | */ 63 | public function setRolesAttribute($value): void 64 | { 65 | $this->_roles = $value; 66 | } 67 | 68 | /** 69 | * Get user roles by relation. 70 | * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany 71 | */ 72 | public function roles() 73 | { 74 | return $this->belongsToMany(Role::class, 'user_role', 'user_id', 'role_id')->withTimestamps(); 75 | } 76 | 77 | /** 78 | * Checks if User has access to $permissions. 79 | * @param array $permissions 80 | * @return bool 81 | */ 82 | public function hasAccess(array $permissions) : bool 83 | { 84 | // check if the permission is available in any role 85 | /* @var Role $role */ 86 | foreach ($this->roles()->get() as $role) { 87 | 88 | if($role->hasAccess($permissions)) { 89 | return true; 90 | } 91 | } 92 | return false; 93 | } 94 | 95 | /** 96 | * Checks if the user belongs to role. 97 | * @param string $roleSlug 98 | * @return bool 99 | */ 100 | public function inRole(string $roleSlug): bool 101 | { 102 | return $this->roles()->where('slug', $roleSlug)->count() == 1; 103 | } 104 | 105 | /** 106 | * Can assign role checking. 107 | * @param RbacUserInterface $member 108 | * @param Role $role 109 | * @return bool 110 | */ 111 | public function canAssignRole(RbacUserInterface $member, Role $role): bool 112 | { 113 | if ($this->countAdministrativeRoles() == 0) { 114 | return false; 115 | } 116 | 117 | if ($this->getMemberKeyAttribute() != $member->getMemberKeyAttribute()) { 118 | return true; 119 | } 120 | 121 | if ($this->countAdministrativeRoles() > 1) { 122 | return true; 123 | } 124 | 125 | if (!$role->hasAccess([Permission::ADMINISTRATE_PERMISSION])) { 126 | return true; 127 | } 128 | 129 | if ($this->inRole($role->slug)) { 130 | return false; 131 | } 132 | 133 | return true; 134 | } 135 | 136 | /** 137 | * Synchronize user roles after save model. 138 | * @param array $options 139 | * @return bool 140 | */ 141 | public function save(array $options = []) 142 | { 143 | if (!parent::save($options)) { 144 | return false; 145 | } 146 | 147 | if (null !== $this->_roles) { 148 | $this->roles()->sync($this->_roles); 149 | } 150 | 151 | return true; 152 | } 153 | 154 | /** 155 | * @return int 156 | */ 157 | private function countAdministrativeRoles(): int 158 | { 159 | if (null !== $this->_countAdministrativeRoles) { 160 | return $this->_countAdministrativeRoles; 161 | } 162 | 163 | $this->_countAdministrativeRoles = 0; 164 | 165 | /* @var Role $role */ 166 | foreach ($this->roles()->get() as $role) { 167 | 168 | if($role->hasAccess([Permission::ADMINISTRATE_PERMISSION])) { 169 | $this->_countAdministrativeRoles += 1; 170 | } 171 | } 172 | 173 | return $this->_countAdministrativeRoles; 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /src/RbacServiceProvider.php: -------------------------------------------------------------------------------- 1 | 17 | */ 18 | class RbacServiceProvider extends ServiceProvider 19 | { 20 | public function register() 21 | { 22 | $this->app->register(RbacRouteServiceProvider::class); 23 | $this->app->register(RbacAuthServiceProvider::class); 24 | $this->app->register(GridViewServiceProvider::class); 25 | 26 | $this->registerCommands(); 27 | } 28 | 29 | public function boot() 30 | { 31 | // Loading settings 32 | $this->loadViews(); 33 | $this->loadTranslations(); 34 | $this->loadMigrations(); 35 | 36 | 37 | // Publish settings 38 | $this->publishConfig(); 39 | $this->publishViews(); 40 | $this->publishTranslations(); 41 | $this->publishMigrations(); 42 | $this->publishSeeders(); 43 | 44 | 45 | // Global view's params 46 | View::share('rbacLayout', config('rbac.layout')); 47 | View::share('rbacRowsPerPage', config('rbac.rowsPerPage', Grid::INIT_ROWS_PER_PAGE)); 48 | } 49 | 50 | 51 | /* 52 | |-------------------------------------------------------------------------- 53 | | COMMAND SETTINGS 54 | |-------------------------------------------------------------------------- 55 | */ 56 | 57 | /** 58 | * Register commands. 59 | * @return void 60 | */ 61 | private function registerCommands(): void 62 | { 63 | $this->commands(PublishCommand::class); 64 | $this->commands(DatabaseCommand::class); 65 | $this->commands(AdminCommand::class); 66 | } 67 | 68 | 69 | /* 70 | |-------------------------------------------------------------------------- 71 | | LOADING SETTINGS 72 | |-------------------------------------------------------------------------- 73 | */ 74 | 75 | /** 76 | * Set directory to load views. 77 | * @return void 78 | */ 79 | private function loadViews(): void 80 | { 81 | $this->loadViewsFrom($this->packagePath('resources/views'), 'rbac'); 82 | } 83 | 84 | /** 85 | * Set directory to load translations. 86 | * @return void 87 | */ 88 | private function loadTranslations(): void 89 | { 90 | $this->loadTranslationsFrom($this->packagePath('resources/lang'), 'rbac'); 91 | } 92 | 93 | /** 94 | * Set directory to load migrations. 95 | * @return void 96 | */ 97 | private function loadMigrations(): void 98 | { 99 | $this->loadMigrationsFrom($this->packagePath('database/migrations')); 100 | } 101 | 102 | 103 | /* 104 | |-------------------------------------------------------------------------- 105 | | PUBLISH SETTINGS 106 | |-------------------------------------------------------------------------- 107 | */ 108 | 109 | /** 110 | * Publish config. 111 | * @return void 112 | */ 113 | private function publishConfig(): void 114 | { 115 | $configPath = $this->packagePath('config/rbac.php'); 116 | 117 | $this->publishes([ 118 | $configPath => config_path('rbac.php'), 119 | ], 'config'); 120 | 121 | $this->mergeConfigFrom($configPath, 'rbac'); 122 | } 123 | 124 | /** 125 | * Publish views. 126 | * @return void 127 | */ 128 | private function publishViews(): void 129 | { 130 | $this->publishes([ 131 | $this->packagePath('resources/views') => resource_path('views/vendor/rbac'), 132 | ], 'views'); 133 | } 134 | 135 | /** 136 | * Publish translations. 137 | * @return void 138 | */ 139 | private function publishTranslations(): void 140 | { 141 | $this->publishes([ 142 | $this->packagePath('resources/lang') => resource_path('lang/vendor/rbac'), 143 | ], 'lang'); 144 | } 145 | 146 | /** 147 | * Publish migrations. 148 | * @return void 149 | */ 150 | private function publishMigrations(): void 151 | { 152 | $this->publishes([ 153 | $this->packagePath('database/migrations') => database_path('migrations'), 154 | ], 'migrations'); 155 | } 156 | 157 | /** 158 | * Publish seeders. 159 | * @return void 160 | */ 161 | private function publishSeeders(): void 162 | { 163 | $this->publishes([ 164 | $this->packagePath('database/seeders') => database_path('seeders'), 165 | ], 'seeders'); 166 | } 167 | 168 | 169 | /* 170 | |-------------------------------------------------------------------------- 171 | | OTHER SETTINGS 172 | |-------------------------------------------------------------------------- 173 | */ 174 | 175 | /** 176 | * Get package path. 177 | * @param $path 178 | * @return string 179 | */ 180 | private function packagePath($path): string 181 | { 182 | return __DIR__ . "/../" . $path; 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Laravel RBAC package 2 | 3 | [![Latest Stable Version](https://poser.pugx.org/itstructure/laravel-rbac/v/stable)](https://packagist.org/packages/itstructure/laravel-rbac) 4 | [![Latest Unstable Version](https://poser.pugx.org/itstructure/laravel-rbac/v/unstable)](https://packagist.org/packages/itstructure/laravel-rbac) 5 | [![License](https://poser.pugx.org/itstructure/laravel-rbac/license)](https://packagist.org/packages/itstructure/laravel-rbac) 6 | [![Total Downloads](https://poser.pugx.org/itstructure/laravel-rbac/downloads)](https://packagist.org/packages/itstructure/laravel-rbac) 7 | [![Build Status](https://scrutinizer-ci.com/g/itstructure/laravel-rbac/badges/build.png?b=master)](https://scrutinizer-ci.com/g/itstructure/laravel-rbac/build-status/master) 8 | [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/itstructure/laravel-rbac/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/itstructure/laravel-rbac/?branch=master) 9 | 10 | ## 1 Introduction 11 | 12 | **LaRbac** - Package for the Laravel framework which provides management with the next data: 13 | - Roles 14 | - Permissions 15 | - Assign roles for users 16 | 17 | ![RBAC package structure](https://github.com/itstructure/laravel-rbac/blob/master/laravel_rbac_structure_en.jpg) 18 | 19 | ## 2 Dependencies 20 | 21 | - laravel 8+ | 9+ | 10+ | 11+ | 12+ 22 | - Bootstrap 4 for styling 23 | - JQuery 24 | - php >= 7.3.0 25 | - composer 26 | 27 | ## 3 Installation 28 | 29 | **Note!** 30 | 31 | Version **3.x** is for laravel **8+**, **9+**, **10+**, **11+**, **12+**. 32 | 33 | Version **2.x** is for laravel **6** or **7**. You can use branch `laravel67-rbac` with **2.x** versions. 34 | 35 | ### 3.1 General installation from remote repository 36 | 37 | Run the composer command: 38 | 39 | `composer require itstructure/laravel-rbac "^3.0.18"` 40 | 41 | ### 3.2 Next internal installation steps 42 | 43 | **Notes:** 44 | 45 | - Make sure that a table for the users is already existing in your project. 46 | 47 | - Make sure that a model for the users table is already existing in your project. 48 | 49 | **Recommendation:** 50 | 51 | If you don't have any layout yet, it is useful to install for example [AdminLTE](https://github.com/jeroennoten/Laravel-AdminLTE) 52 | or you can make your special any layout template. 53 | Cause in this package there is no a layout specially. But in config it is necessary to set it (see the next point 2 about a configure). 54 | 55 | Let's go: 56 | 57 | 1. Publish files. 58 | 59 | **Note:** `rbac.php` config file and seeders `LaRbacDatabaseSeeder`, `PermissionSeeder`, `RoleSeeder` must be published surely! 60 | 61 | - To publish config run command: 62 | 63 | `php artisan rbac:publish --only=config` 64 | 65 | It stores config file to `config` folder. 66 | 67 | - To publish seeders run command: 68 | 69 | `php artisan rbac:publish --only=seeders` 70 | 71 | It stores seeder files to `database/seeders` folder. 72 | 73 | - To publish migrations run command: 74 | 75 | `php artisan rbac:publish --only=migrations` 76 | 77 | It stores migration files to `database/migrations` folder. 78 | 79 | - To publish views run command: 80 | 81 | `php artisan rbac:publish --only=views` 82 | 83 | It stores view files to `resources/views/vendor/rbac` folder. 84 | 85 | - To publish translations run command: 86 | 87 | `php artisan rbac:publish --only=lang` 88 | 89 | It stores translation files to `resources/lang/vendor/rbac` folder. 90 | 91 | - To publish all parts run command without `only` argument: 92 | 93 | `php artisan rbac:publish` 94 | 95 | Else you can use `--force` argument to rewrite already published files. 96 | 97 | 2. Configure published `config/rbac.php` file: 98 | 99 | - set `layout`. Example: `'layout' => 'adminlte::page'` 100 | 101 | - change `userModelClass` if it is needed to change 102 | 103 | - set `adminUserId` which you wanted to be with the role of administrator. **At least at the beginning stage**. 104 | 105 | It is necessary for the next time system to let you go into the Rbac control panel, after you assigned an administrator role for you (Later see point **4**). 106 | 107 | - Most likely you have to change `memberNameAttributeKey`. 108 | 109 | It is to display the user name in control panel by `getMemberNameAttribute()` method of `Administrable` trait. It can be **string** or a **callback**: 110 | 111 | ```php 112 | 'memberNameAttributeKey' => function ($row) { 113 | return $row->first_name . ' ' . $row->last_name; 114 | } 115 | ``` 116 | 117 | 3. Tuning your `User` model (as shown in **4.1** point): 118 | 119 | - Implement `User` model from `RbacUserInterface`. 120 | 121 | - Add **roles** attribute to `$fillable`. 122 | 123 | - Apply `Administrable` trait. 124 | 125 | 4. Run command to run migrations and seeders: 126 | 127 | `php artisan rbac:database` 128 | 129 | Or optional: 130 | 131 | To run just migrations `php artisan rbac:database --only=migrate` 132 | 133 | To run just seeds `php artisan rbac:database --only=seed` 134 | 135 | - Alternative variant for seeders. 136 | 137 | You can set published rbac `LaRbacDatabaseSeeder` seeder class in to a special `DatabaseSeeder`: 138 | 139 | ```php 140 | use Illuminate\Database\Seeder; 141 | ``` 142 | 143 | ```php 144 | class DatabaseSeeder extends Seeder 145 | { 146 | public function run() 147 | { 148 | $this->call(LaRbacDatabaseSeeder::class); 149 | } 150 | } 151 | ``` 152 | 153 | and run command: `php artisan db:seed`. 154 | 155 | 5. Run command to set Admin role for user with identifier `adminUserId`, defined in **2** point: 156 | 157 | `php artisan rbac:admin` 158 | 159 | ## 4 Usage 160 | 161 | **Notes**: 162 | 163 | - Make sure you use a **Bootstrap 4** for styling and **JQuery** in your application. 164 | 165 | - Make sure that a laravel initial factory authorization is already working in your application. 166 | 167 | ### 4.1 Model part 168 | 169 | According with the `Itstructure\LaRbac\Interfaces\RbacUserInterface` use functions from `Itstructure\LaRbac\Traits\Administrable` trait as in example: 170 | 171 | ```php 172 | namespace App; 173 | 174 | use Illuminate\Notifications\Notifiable; 175 | use Illuminate\Foundation\Auth\User as Authenticatable; 176 | use Itstructure\LaRbac\Interfaces\RbacUserInterface; 177 | use Itstructure\LaRbac\Traits\Administrable; 178 | ``` 179 | 180 | ```php 181 | class User extends Authenticatable implements RbacUserInterface 182 | { 183 | use Notifiable, Administrable; 184 | 185 | protected $fillable = [ 186 | 'name', 'email', 'password', 'roles' 187 | ]; 188 | 189 | protected $hidden = [ 190 | 'password', 'remember_token', 191 | ]; 192 | } 193 | ``` 194 | 195 | ### 4.2 Routes part 196 | 197 | There are already integrated base RBAC routes to manage **users**, **roles** and **permissions**. See in `routes.php` package file. 198 | 199 | They are guarded by the next: 200 | 201 | - middleware `auth` (editable by config). 202 | - permission `can:administrate` (editable by config). 203 | 204 | This routes allow you to go to the next routes: 205 | 206 | - **Users section** 207 | 208 | For get request method 209 | 210 | - `http://example-domain.com/rbac/users` 211 | - `http://example-domain.com/rbac/users/show/{id}` 212 | - `http://example-domain.com/rbac/users/edit/{id}` 213 | 214 | For post request method 215 | 216 | - `http://example-domain.com/rbac/users/update/{id}` 217 | - `http://example-domain.com/rbac/users/delete` 218 | 219 | - **Roles section** 220 | 221 | For get request method 222 | 223 | - `http://example-domain.com/rbac/roles` 224 | - `http://example-domain.com/rbac/roles/show/{id}` 225 | - `http://example-domain.com/rbac/roles/create` 226 | - `http://example-domain.com/rbac/roles/edit/{role}` 227 | 228 | For post request method 229 | 230 | - `http://example-domain.com/rbac/roles/store` 231 | - `http://example-domain.com/rbac/roles/update/{role}` 232 | - `http://example-domain.com/rbac/roles/delete` 233 | 234 | - **Permissions section** 235 | 236 | For get request method 237 | 238 | - `http://example-domain.com/rbac/permissions` 239 | - `http://example-domain.com/rbac/permissions/show/{id}` 240 | - `http://example-domain.com/rbac/permissions/create` 241 | - `http://example-domain.com/rbac/permissions/edit/{permission}` 242 | 243 | For post request method 244 | 245 | - `http://example-domain.com/rbac/permissions/store` 246 | - `http://example-domain.com/rbac/permissions/update/{permission}` 247 | - `http://example-domain.com/rbac/permissions/delete` 248 | 249 | ### 4.3 Gates part 250 | 251 | There are already integrated base RBAC gates to access control in your application to some of the resources. See provider file `RbacAuthServiceProvider.php`. 252 | 253 | It provides the next gate definitions: 254 | 255 | - `administrate` 256 | - `assign-role` 257 | - `delete-member` 258 | - `view-record` 259 | - `create-record` 260 | - `update-record` 261 | - `delete-record` 262 | - `publish-record` 263 | 264 | Read more in [Laravel gates](https://laravel.com/docs/9.x/authorization#gates) 265 | 266 | ## 5 View examples 267 | 268 | **Users** 269 | 270 | ![RBAC package structure](https://github.com/itstructure/laravel-rbac/blob/master/laravel_rbac_users_en.JPG) 271 | 272 | **Roles** 273 | 274 | ![RBAC package structure](https://github.com/itstructure/laravel-rbac/blob/master/laravel_rbac_roles_en.JPG) 275 | 276 | **Permissions** 277 | 278 | ![RBAC package structure](https://github.com/itstructure/laravel-rbac/blob/master/laravel_rbac_permissions_en.JPG) 279 | 280 | ## License 281 | 282 | Copyright © 2018-2025 Andrey Girnik girnikandrey@gmail.com. 283 | 284 | Licensed under the [MIT license](http://opensource.org/licenses/MIT). See LICENSE.txt for details. 285 | --------------------------------------------------------------------------------