471 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			471 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| 
 | |
| namespace App\Traits;
 | |
| 
 | |
| use App\Models\Auth\Permission;
 | |
| use App\Models\Auth\Role;
 | |
| use App\Utilities\Reports;
 | |
| use App\Utilities\Widgets;
 | |
| use Illuminate\Routing\Route;
 | |
| use Illuminate\Support\Str;
 | |
| 
 | |
| trait Permissions
 | |
| {
 | |
|     public function getActionsMap()
 | |
|     {
 | |
|         return [
 | |
|             'c' => 'create',
 | |
|             'r' => 'read',
 | |
|             'u' => 'update',
 | |
|             'd' => 'delete',
 | |
|         ];
 | |
|     }
 | |
| 
 | |
|     public function attachPermissionsByRoleNames($roles)
 | |
|     {
 | |
|         foreach ($roles as $role_name => $permissions) {
 | |
|             $role = $this->createRole($role_name);
 | |
| 
 | |
|             foreach ($permissions as $id => $permission) {
 | |
|                 $this->attachPermissionsByAction($role, $id, $permission);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     public function attachPermissionsToAdminRoles($permissions)
 | |
|     {
 | |
|         $this->applyPermissionsToRoles($this->getDefaultAdminRoles(), 'attach', $permissions);
 | |
|     }
 | |
| 
 | |
|     public function attachPermissionsToPortalRoles($permissions)
 | |
|     {
 | |
|         $this->applyPermissionsToRoles($this->getDefaultPortalRoles(), 'attach', $permissions);
 | |
|     }
 | |
| 
 | |
|     public function attachPermissionsToAllRoles($permissions, $require = 'read-admin-panel')
 | |
|     {
 | |
|         $this->applyPermissionsToRoles($this->getRoles($require), 'attach', $permissions);
 | |
|     }
 | |
| 
 | |
|     public function detachPermissionsByRoleNames($roles)
 | |
|     {
 | |
|         foreach ($roles as $role_name => $permissions) {
 | |
|             foreach ($permissions as $permission_name) {
 | |
|                 $this->detachPermission($role_name, $permission_name);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     public function detachPermissionsFromAdminRoles($permissions)
 | |
|     {
 | |
|         $this->applyPermissionsToRoles($this->getDefaultAdminRoles(), 'detach', $permissions);
 | |
|     }
 | |
| 
 | |
|     public function detachPermissionsFromPortalRoles($permissions)
 | |
|     {
 | |
|         $this->applyPermissionsToRoles($this->getDefaultPortalRoles(), 'detach', $permissions);
 | |
|     }
 | |
| 
 | |
|     public function detachPermissionsFromAllRoles($permissions, $require = 'read-admin-panel')
 | |
|     {
 | |
|         $this->applyPermissionsToRoles($this->getRoles($require), 'detach', $permissions, $require);
 | |
|     }
 | |
| 
 | |
|     public function applyPermissionsToRoles($roles, $apply, $permissions)
 | |
|     {
 | |
|         $roles->each(function ($role) use ($apply, $permissions) {
 | |
|             $f1 = $apply . 'PermissionsByAction';
 | |
|             $f2 = $apply . 'Permission';
 | |
| 
 | |
|             foreach ($permissions as $id => $permission) {
 | |
|                 if ($this->isActionList($permission)) {
 | |
|                     $this->$f1($role, $id, $permission);
 | |
| 
 | |
|                     continue;
 | |
|                 }
 | |
| 
 | |
|                 $this->$f2($role, $permission);
 | |
|             }
 | |
|         });
 | |
|     }
 | |
| 
 | |
|     public function updatePermissionNames($permissions)
 | |
|     {
 | |
|         $actions = $this->getActionsMap();
 | |
| 
 | |
|         foreach ($permissions as $old => $new) {
 | |
|             foreach ($actions as $action) {
 | |
|                 $old_name = $action . '-' . $old;
 | |
| 
 | |
|                 $permission = Permission::where('name', $old_name)->first();
 | |
| 
 | |
|                 if (empty($permission)) {
 | |
|                     continue;
 | |
|                 }
 | |
| 
 | |
|                 $new_name = $action . '-' . $new;
 | |
|                 $new_display_name = $this->getPermissionDisplayName($new_name);
 | |
| 
 | |
|                 $permission->update([
 | |
|                     'name' => $new_name,
 | |
|                     'display_name' => $new_display_name,
 | |
|                 ]);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     public function attachDefaultModulePermissions($module, $require = null)
 | |
|     {
 | |
|         $this->attachModuleReportPermissions($module, $require);
 | |
| 
 | |
|         $this->attachModuleWidgetPermissions($module, $require);
 | |
| 
 | |
|         $this->attachModuleSettingPermissions($module, $require);
 | |
|     }
 | |
| 
 | |
|     public function attachModuleReportPermissions($module, $require = null)
 | |
|     {
 | |
|         if (is_string($module)) {
 | |
|             $module = module($module);
 | |
|         }
 | |
| 
 | |
|         if (empty($module->get('reports'))) {
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         $permissions = [];
 | |
| 
 | |
|         foreach ($module->get('reports') as $class) {
 | |
|             if (!class_exists($class)) {
 | |
|                 continue;
 | |
|             }
 | |
| 
 | |
|             $permissions[] = $this->createModuleReportPermission($module, $class);
 | |
|         }
 | |
| 
 | |
|         $require
 | |
|                 ? $this->attachPermissionsToAllRoles($permissions, $require)
 | |
|                 : $this->attachPermissionsToAdminRoles($permissions);
 | |
|     }
 | |
| 
 | |
|     public function attachModuleWidgetPermissions($module, $require = null)
 | |
|     {
 | |
|         if (is_string($module)) {
 | |
|             $module = module($module);
 | |
|         }
 | |
| 
 | |
|         if (empty($module->get('widgets'))) {
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         $permissions = [];
 | |
| 
 | |
|         foreach ($module->get('widgets') as $class) {
 | |
|             if (!class_exists($class)) {
 | |
|                 continue;
 | |
|             }
 | |
| 
 | |
|             $permissions[] = $this->createModuleWidgetPermission($module, $class);
 | |
|         }
 | |
| 
 | |
|         $require
 | |
|                 ? $this->attachPermissionsToAllRoles($permissions, $require)
 | |
|                 : $this->attachPermissionsToAdminRoles($permissions);
 | |
|     }
 | |
| 
 | |
|     public function attachModuleSettingPermissions($module, $require = null)
 | |
|     {
 | |
|         if (is_string($module)) {
 | |
|             $module = module($module);
 | |
|         }
 | |
| 
 | |
|         if (empty($module->get('settings'))) {
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         $permissions = [];
 | |
| 
 | |
|         $permissions[] = $this->createModuleSettingPermission($module, 'read');
 | |
|         $permissions[] = $this->createModuleSettingPermission($module, 'update');
 | |
| 
 | |
|         $require
 | |
|                 ? $this->attachPermissionsToAllRoles($permissions, $require)
 | |
|                 : $this->attachPermissionsToAdminRoles($permissions);
 | |
|     }
 | |
| 
 | |
|     public function createModuleReportPermission($module, $class)
 | |
|     {
 | |
|         if (is_string($module)) {
 | |
|             $module = module($module);
 | |
|         }
 | |
| 
 | |
|         if (!class_exists($class)) {
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         $name = Reports::getPermission($class);
 | |
|         $display_name = 'Read ' . $module->getName() . ' Reports ' . Reports::getDefaultName($class);
 | |
| 
 | |
|         return $this->createPermission($name, $display_name);
 | |
|     }
 | |
| 
 | |
|     public function createModuleWidgetPermission($module, $class)
 | |
|     {
 | |
|         if (is_string($module)) {
 | |
|             $module = module($module);
 | |
|         }
 | |
| 
 | |
|         if (!class_exists($class)) {
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         $name = Widgets::getPermission($class);
 | |
|         $display_name = 'Read ' . $module->getName() . ' Widgets ' . Widgets::getDefaultName($class);
 | |
| 
 | |
|         return $this->createPermission($name, $display_name);
 | |
|     }
 | |
| 
 | |
|     public function createModuleSettingPermission($module, $action)
 | |
|     {
 | |
|         return $this->createModuleControllerPermission($module, $action, 'settings');
 | |
|     }
 | |
| 
 | |
|     public function createModuleControllerPermission($module, $action, $controller)
 | |
|     {
 | |
|         if (is_string($module)) {
 | |
|             $module = module($module);
 | |
|         }
 | |
| 
 | |
|         $name = $action . '-' . $module->getAlias() . '-' . $controller;
 | |
|         $display_name = Str::title($action) . ' ' . $module->getName() . ' ' . Str::title($controller);
 | |
| 
 | |
|         return $this->createPermission($name, $display_name);
 | |
|     }
 | |
| 
 | |
|     public function createRole($name, $display_name = null, $description = null)
 | |
|     {
 | |
|         $display_name = $display_name ?? Str::title($name);
 | |
| 
 | |
|         return Role::firstOrCreate([
 | |
|             'name' => $name,
 | |
|         ], [
 | |
|             'display_name' => $display_name,
 | |
|             'description' => $description ?? $display_name,
 | |
|         ]);
 | |
|     }
 | |
| 
 | |
|     public function createPermission($name, $display_name = null, $description = null)
 | |
|     {
 | |
|         $display_name = $display_name ?? $this->getPermissionDisplayName($name);
 | |
| 
 | |
|         return Permission::firstOrCreate([
 | |
|             'name' => $name,
 | |
|         ], [
 | |
|             'display_name' => $display_name,
 | |
|             'description' => $description ?? $display_name,
 | |
|         ]);
 | |
|     }
 | |
| 
 | |
|     public function attachPermission($role, $permission)
 | |
|     {
 | |
|         if (is_string($permission)) {
 | |
|             $permission = $this->createPermission($permission);
 | |
|         }
 | |
| 
 | |
|         if ($role->hasPermission($permission->name)) {
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         $role->attachPermission($permission);
 | |
|     }
 | |
| 
 | |
|     public function detachPermission($role, $permission, $delete = true)
 | |
|     {
 | |
|         if (is_string($role)) {
 | |
|             $role = Role::where('name', $role)->first();
 | |
|         }
 | |
| 
 | |
|         if (empty($role)) {
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         if (is_string($permission)) {
 | |
|             $permission = Permission::where('name', $permission)->first();
 | |
|         }
 | |
| 
 | |
|         if (empty($permission)) {
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         if ($role->hasPermission($permission->name)) {
 | |
|             $role->detachPermission($permission);
 | |
|         }
 | |
| 
 | |
|         if ($delete === false) {
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         $permission->delete();
 | |
|     }
 | |
| 
 | |
|     public function isActionList($permission)
 | |
|     {
 | |
|         if (!is_string($permission)) {
 | |
|             return false;
 | |
|         }
 | |
| 
 | |
|         // c || c,r,u,d
 | |
|         return (Str::length($permission) == 1) || Str::contains($permission, ',');
 | |
|     }
 | |
| 
 | |
|     public function attachPermissionsByAction($role, $page, $action_list)
 | |
|     {
 | |
|         $this->applyPermissionsByAction('attach', $role, $page, $action_list);
 | |
|     }
 | |
| 
 | |
|     public function detachPermissionsByAction($role, $page, $action_list)
 | |
|     {
 | |
|         $this->applyPermissionsByAction('detach', $role, $page, $action_list);
 | |
|     }
 | |
| 
 | |
|     public function applyPermissionsByAction($apply, $role, $page, $action_list)
 | |
|     {
 | |
|         $function = $apply . 'Permission';
 | |
| 
 | |
|         $actions_map = collect($this->getActionsMap());
 | |
| 
 | |
|         $actions = explode(',', $action_list);
 | |
| 
 | |
|         foreach ($actions as $short_action) {
 | |
|             $action = $actions_map->get($short_action);
 | |
| 
 | |
|             $name = $action . '-' . $page;
 | |
| 
 | |
|             $this->$function($role, $name);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     public function getPermissionDisplayName($name)
 | |
|     {
 | |
|         if (!empty($this->alias)) {
 | |
|             $name = str_replace($this->alias, '{Module Placeholder}', $name);
 | |
|         }
 | |
| 
 | |
|         $name = Str::title(str_replace('-', ' ', $name));
 | |
| 
 | |
|         if (!empty($this->alias)) {
 | |
|             $name = str_replace('{Module Placeholder}', module($this->alias)->getName(), $name);
 | |
|         }
 | |
| 
 | |
|         return $name;
 | |
|     }
 | |
| 
 | |
|     public function getRoles($require = 'read-admin-panel')
 | |
|     {
 | |
|         return Role::all()->filter(function ($role) use ($require) {
 | |
|             return $require ? $role->hasPermission($require) : true;
 | |
|         });
 | |
|     }
 | |
| 
 | |
|     public function getDefaultAdminRoles($custom = null)
 | |
|     {
 | |
|         $roles = Role::whereIn('name', $custom ?? ['admin', 'manager'])->get();
 | |
| 
 | |
|         if ($roles->isNotEmpty()) {
 | |
|             return $roles;
 | |
|         }
 | |
| 
 | |
|         return $this->getRoles('read-admin-panel');
 | |
|     }
 | |
| 
 | |
|     public function getDefaultPortalRoles($custom = null)
 | |
|     {
 | |
|         $roles = Role::whereIn('name', $custom ?? ['customer'])->get();
 | |
| 
 | |
|         if ($roles->isNotEmpty()) {
 | |
|             return $roles;
 | |
|         }
 | |
| 
 | |
|         return $this->getRoles('read-client-portal');
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Assign permissions middleware to default controller methods.
 | |
|      *
 | |
|      * @return void
 | |
|      */
 | |
|     public function assignPermissionsToController()
 | |
|     {
 | |
|         // No need to check for permission in console
 | |
|         if (app()->runningInConsole()) {
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         $table = request()->is('api/*') ? request()->segment(2) : '';
 | |
| 
 | |
|         // Fire event to find the proper controller for common API endpoints
 | |
|         if (in_array($table, ['contacts', 'documents', 'transactions'])) {
 | |
|             $controller = '';
 | |
| 
 | |
|             $type = request()->get('type');
 | |
| 
 | |
|             $alias = config('type.' . $type . '.alias');
 | |
|             $group = config('type.' . $type . '.group');
 | |
|             $prefix = config('type.' . $type . '.permission.prefix');
 | |
| 
 | |
|             // if use module set module alias
 | |
|             if (!empty($alias)) {
 | |
|                 $controller .= $alias . '-';
 | |
|             }
 | |
| 
 | |
|             // if controller in folder it must
 | |
|             if (!empty($group)) {
 | |
|                 $controller .= $group . '-';
 | |
|             }
 | |
| 
 | |
|             $controller .= $prefix;
 | |
|         } else {
 | |
|             $route = app(Route::class);
 | |
| 
 | |
|             // Get the controller array
 | |
|             $arr = array_reverse(explode('\\', explode('@', $route->getAction()['uses'])[0]));
 | |
| 
 | |
|             $controller = '';
 | |
| 
 | |
|             // Add module
 | |
|             if (isset($arr[3]) && isset($arr[4])) {
 | |
|                 if (strtolower($arr[4]) == 'modules') {
 | |
|                     $controller .= Str::kebab($arr[3]) . '-';
 | |
|                 } elseif (isset($arr[5]) && (strtolower($arr[5]) == 'modules')) {
 | |
|                     $controller .= Str::kebab($arr[4]) . '-';
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             // Add folder
 | |
|             if (strtolower($arr[1]) != 'controllers') {
 | |
|                 $controller .= Str::kebab($arr[1]) . '-';
 | |
|             }
 | |
| 
 | |
|             // Add file
 | |
|             $controller .= Str::kebab($arr[0]);
 | |
| 
 | |
|             // Skip ACL
 | |
|             $skip = ['portal-dashboard'];
 | |
|             if (in_array($controller, $skip)) {
 | |
|                 return;
 | |
|             }
 | |
| 
 | |
|             // App\Http\Controllers\FooBar                  -->> foo-bar
 | |
|             // App\Http\Controllers\FooBar\Main             -->> foo-bar-main
 | |
|             // Modules\Blog\Http\Controllers\Posts          -->> blog-posts
 | |
|             // Modules\Blog\Http\Controllers\Portal\Posts   -->> blog-portal-posts
 | |
|         }
 | |
| 
 | |
|         // Add CRUD permission check
 | |
|         $this->middleware('permission:create-' . $controller)->only('create', 'store', 'duplicate', 'import');
 | |
|         $this->middleware('permission:read-' . $controller)->only('index', 'show', 'edit', 'export');
 | |
|         $this->middleware('permission:update-' . $controller)->only('update', 'enable', 'disable');
 | |
|         $this->middleware('permission:delete-' . $controller)->only('destroy');
 | |
|     }
 | |
| }
 |