diff --git a/app/Enums/Permission.php b/app/Enums/Permission.php index 5df3566..769a215 100644 --- a/app/Enums/Permission.php +++ b/app/Enums/Permission.php @@ -103,6 +103,11 @@ enum Permission: string case ACTIVITY_LOGS_VIEW = 'activity-logs.view'; + case ROLES_VIEW = 'roles.view'; + case ROLES_CREATE = 'roles.create'; + case ROLES_UPDATE = 'roles.update'; + case ROLES_DELETE = 'roles.delete'; + public function label(): string { return match ($this) { @@ -200,6 +205,11 @@ public function label(): string self::SETTINGS_UPDATE => 'Ubah Pengaturan Aplikasi', self::ACTIVITY_LOGS_VIEW => 'Lihat Log Aktivitas', + + self::ROLES_VIEW => 'Lihat Role', + self::ROLES_CREATE => 'Tambah Role', + self::ROLES_UPDATE => 'Ubah Role', + self::ROLES_DELETE => 'Hapus Role', }; } @@ -241,6 +251,8 @@ public function group(): string self::PAYROLL_CLOSE => 'Gaji', self::SETTINGS_VIEW, self::SETTINGS_UPDATE => 'Pengaturan Aplikasi', self::ACTIVITY_LOGS_VIEW => 'Log Aktivitas', + self::ROLES_VIEW, self::ROLES_CREATE, self::ROLES_UPDATE, + self::ROLES_DELETE => 'Role & Permission', }; } diff --git a/app/Enums/Role.php b/app/Enums/Role.php index ecb0d8f..de1fe15 100644 --- a/app/Enums/Role.php +++ b/app/Enums/Role.php @@ -36,113 +36,84 @@ public function permissions(): array { return match ($this) { self::DEVELOPER, self::OWNER => Permission::cases(), + self::DIREKTUR => [ Permission::DASHBOARD_VIEW, + Permission::EMPLOYEES_VIEW, - Permission::EMPLOYEES_CREATE, - Permission::EMPLOYEES_UPDATE, - Permission::EMPLOYEES_DELETE, - Permission::EMPLOYEES_RESET_PASSWORD, - Permission::EMPLOYEES_TOGGLE_STATUS, + Permission::ATTENDANCES_VIEW, Permission::ATTENDANCES_CREATE, Permission::ATTENDANCES_DELETE, Permission::ATTENDANCES_MANAGE, + Permission::LEAVE_REQUESTS_VIEW, Permission::LEAVE_REQUESTS_CREATE, Permission::LEAVE_REQUESTS_UPDATE, Permission::LEAVE_REQUESTS_DELETE, + Permission::CATEGORIES_VIEW, - Permission::CATEGORIES_CREATE, - Permission::CATEGORIES_UPDATE, - Permission::CATEGORIES_DELETE, + Permission::SUPPLIERS_VIEW, - Permission::SUPPLIERS_CREATE, - Permission::SUPPLIERS_UPDATE, - Permission::SUPPLIERS_DELETE, + Permission::CUSTOMERS_VIEW, - Permission::CUSTOMERS_CREATE, - Permission::CUSTOMERS_UPDATE, - Permission::CUSTOMERS_DELETE, + Permission::PRODUCTS_VIEW, - Permission::PRODUCTS_CREATE, - Permission::PRODUCTS_UPDATE, - Permission::PRODUCTS_DELETE, - Permission::PRODUCTS_TOGGLE_STATUS, + Permission::RAW_MATERIALS_VIEW, - Permission::RAW_MATERIALS_CREATE, - Permission::RAW_MATERIALS_UPDATE, - Permission::RAW_MATERIALS_DELETE, - Permission::RAW_MATERIALS_TOGGLE_STATUS, + Permission::PURCHASES_VIEW, - Permission::PURCHASES_CREATE, - Permission::PURCHASES_UPDATE, - Permission::PURCHASES_DELETE, + Permission::ORDERS_VIEW, - Permission::ORDERS_CREATE, - Permission::ORDERS_UPDATE, - Permission::ORDERS_DELETE, - Permission::ORDERS_SEND, - Permission::ORDERS_COMPLETE, - Permission::ORDERS_CANCEL, + Permission::CUTTINGS_VIEW, - Permission::CUTTINGS_CREATE, - Permission::CUTTINGS_UPDATE, - Permission::CUTTINGS_DELETE, - Permission::CUTTINGS_COMPLETE, - Permission::CUTTINGS_VERIFY, - Permission::CUTTINGS_REJECT, + Permission::CASH_VIEW, - Permission::CASH_DEPOSIT, - Permission::CASH_UPDATE, - Permission::CASH_DELETE, + Permission::EXPENSES_VIEW, - Permission::EXPENSES_CREATE, - Permission::EXPENSES_UPDATE, - Permission::EXPENSES_DELETE, + Permission::EMPLOYEE_ADVANCES_VIEW, Permission::EMPLOYEE_ADVANCES_CREATE, Permission::EMPLOYEE_ADVANCES_UPDATE, Permission::EMPLOYEE_ADVANCES_DELETE, Permission::EMPLOYEE_ADVANCES_PAY, + Permission::PAYROLL_VIEW, - Permission::PAYROLL_PAY, - Permission::PAYROLL_ADJUST, - Permission::PAYROLL_CLOSE, - Permission::ACTIVITY_LOGS_VIEW, ], + self::ADMIN_TOKO => [ Permission::DASHBOARD_VIEW, - Permission::EMPLOYEES_VIEW, - Permission::EMPLOYEES_CREATE, - Permission::EMPLOYEES_UPDATE, - Permission::EMPLOYEES_RESET_PASSWORD, - Permission::EMPLOYEES_TOGGLE_STATUS, + Permission::ATTENDANCES_VIEW, Permission::ATTENDANCES_CREATE, Permission::ATTENDANCES_DELETE, - Permission::ATTENDANCES_MANAGE, + Permission::LEAVE_REQUESTS_VIEW, Permission::LEAVE_REQUESTS_CREATE, Permission::LEAVE_REQUESTS_UPDATE, Permission::LEAVE_REQUESTS_DELETE, + Permission::CATEGORIES_VIEW, Permission::CATEGORIES_CREATE, Permission::CATEGORIES_UPDATE, Permission::CATEGORIES_DELETE, + Permission::SUPPLIERS_VIEW, Permission::SUPPLIERS_CREATE, Permission::SUPPLIERS_UPDATE, Permission::SUPPLIERS_DELETE, + Permission::CUSTOMERS_VIEW, Permission::CUSTOMERS_CREATE, Permission::CUSTOMERS_UPDATE, Permission::CUSTOMERS_DELETE, + Permission::PRODUCTS_VIEW, Permission::PRODUCTS_CREATE, Permission::PRODUCTS_UPDATE, Permission::PRODUCTS_DELETE, Permission::PRODUCTS_TOGGLE_STATUS, + Permission::ORDERS_VIEW, Permission::ORDERS_CREATE, Permission::ORDERS_UPDATE, @@ -150,84 +121,128 @@ public function permissions(): array Permission::ORDERS_SEND, Permission::ORDERS_COMPLETE, Permission::ORDERS_CANCEL, + Permission::CUTTINGS_VIEW, Permission::CUTTINGS_VERIFY, - Permission::CUTTINGS_REJECT, + Permission::CASH_VIEW, Permission::CASH_DEPOSIT, Permission::CASH_UPDATE, Permission::CASH_DELETE, + Permission::EXPENSES_VIEW, Permission::EXPENSES_CREATE, Permission::EXPENSES_UPDATE, Permission::EXPENSES_DELETE, + Permission::EMPLOYEE_ADVANCES_VIEW, Permission::EMPLOYEE_ADVANCES_CREATE, Permission::EMPLOYEE_ADVANCES_UPDATE, Permission::EMPLOYEE_ADVANCES_DELETE, Permission::EMPLOYEE_ADVANCES_PAY, + Permission::PAYROLL_VIEW, Permission::PAYROLL_PAY, Permission::PAYROLL_ADJUST, Permission::PAYROLL_CLOSE, - Permission::SETTINGS_VIEW, - Permission::SETTINGS_UPDATE, - Permission::ACTIVITY_LOGS_VIEW, ], + self::ADMIN_BAHAN_BAKU => [ Permission::DASHBOARD_VIEW, - Permission::EMPLOYEES_VIEW, - Permission::ATTENDANCES_VIEW, - Permission::ATTENDANCES_CREATE, - Permission::LEAVE_REQUESTS_VIEW, - Permission::LEAVE_REQUESTS_CREATE, - Permission::LEAVE_REQUESTS_UPDATE, - Permission::LEAVE_REQUESTS_DELETE, - Permission::CATEGORIES_VIEW, - Permission::CATEGORIES_CREATE, - Permission::CATEGORIES_UPDATE, - Permission::CATEGORIES_DELETE, - Permission::SUPPLIERS_VIEW, - Permission::SUPPLIERS_CREATE, - Permission::SUPPLIERS_UPDATE, - Permission::SUPPLIERS_DELETE, - Permission::RAW_MATERIALS_VIEW, - Permission::RAW_MATERIALS_CREATE, - Permission::RAW_MATERIALS_UPDATE, - Permission::RAW_MATERIALS_DELETE, - Permission::RAW_MATERIALS_TOGGLE_STATUS, - Permission::PURCHASES_VIEW, - Permission::PURCHASES_CREATE, - Permission::PURCHASES_UPDATE, - Permission::PURCHASES_DELETE, - Permission::CUTTINGS_VIEW, - Permission::CUTTINGS_CREATE, - Permission::CUTTINGS_UPDATE, - Permission::CUTTINGS_DELETE, - Permission::CUTTINGS_COMPLETE, - ], - self::MARKETING => [ - Permission::DASHBOARD_VIEW, - Permission::EMPLOYEES_VIEW, + Permission::ATTENDANCES_VIEW, Permission::ATTENDANCES_CREATE, + Permission::ATTENDANCES_DELETE, + Permission::LEAVE_REQUESTS_VIEW, Permission::LEAVE_REQUESTS_CREATE, Permission::LEAVE_REQUESTS_UPDATE, Permission::LEAVE_REQUESTS_DELETE, + Permission::CATEGORIES_VIEW, Permission::CATEGORIES_CREATE, Permission::CATEGORIES_UPDATE, Permission::CATEGORIES_DELETE, + Permission::SUPPLIERS_VIEW, Permission::SUPPLIERS_CREATE, Permission::SUPPLIERS_UPDATE, Permission::SUPPLIERS_DELETE, + Permission::CUSTOMERS_VIEW, Permission::CUSTOMERS_CREATE, Permission::CUSTOMERS_UPDATE, Permission::CUSTOMERS_DELETE, + Permission::PRODUCTS_VIEW, + Permission::PRODUCTS_CREATE, + Permission::PRODUCTS_UPDATE, + Permission::PRODUCTS_DELETE, + Permission::PRODUCTS_TOGGLE_STATUS, + + Permission::ORDERS_VIEW, + Permission::ORDERS_CREATE, + Permission::ORDERS_UPDATE, + Permission::ORDERS_DELETE, + Permission::ORDERS_SEND, + Permission::ORDERS_COMPLETE, + Permission::ORDERS_CANCEL, + + Permission::CUTTINGS_VIEW, + Permission::CUTTINGS_VERIFY, + + Permission::CASH_VIEW, + Permission::CASH_DEPOSIT, + Permission::CASH_UPDATE, + Permission::CASH_DELETE, + + Permission::EXPENSES_VIEW, + Permission::EXPENSES_CREATE, + Permission::EXPENSES_UPDATE, + Permission::EXPENSES_DELETE, + + Permission::EMPLOYEE_ADVANCES_VIEW, + Permission::EMPLOYEE_ADVANCES_CREATE, + Permission::EMPLOYEE_ADVANCES_UPDATE, + Permission::EMPLOYEE_ADVANCES_DELETE, + Permission::EMPLOYEE_ADVANCES_PAY, + + Permission::PAYROLL_VIEW, + Permission::PAYROLL_PAY, + Permission::PAYROLL_ADJUST, + Permission::PAYROLL_CLOSE, + ], + + self::MARKETING => [ + Permission::DASHBOARD_VIEW, + + Permission::EMPLOYEES_VIEW, + + Permission::ATTENDANCES_VIEW, + Permission::ATTENDANCES_CREATE, + + Permission::LEAVE_REQUESTS_VIEW, + Permission::LEAVE_REQUESTS_CREATE, + Permission::LEAVE_REQUESTS_UPDATE, + Permission::LEAVE_REQUESTS_DELETE, + + Permission::CATEGORIES_VIEW, + Permission::CATEGORIES_CREATE, + Permission::CATEGORIES_UPDATE, + Permission::CATEGORIES_DELETE, + + Permission::SUPPLIERS_VIEW, + Permission::SUPPLIERS_CREATE, + Permission::SUPPLIERS_UPDATE, + Permission::SUPPLIERS_DELETE, + + Permission::CUSTOMERS_VIEW, + Permission::CUSTOMERS_CREATE, + Permission::CUSTOMERS_UPDATE, + Permission::CUSTOMERS_DELETE, + + Permission::PRODUCTS_VIEW, + Permission::ORDERS_VIEW, Permission::ORDERS_CREATE, Permission::ORDERS_UPDATE, @@ -235,6 +250,7 @@ public function permissions(): array Permission::ORDERS_COMPLETE, Permission::ORDERS_CANCEL, ], + self::NON_OPERATOR => [ Permission::DASHBOARD_VIEW, ], diff --git a/app/Http/Controllers/Admin/System/RoleController.php b/app/Http/Controllers/Admin/System/RoleController.php new file mode 100644 index 0000000..a9ec1ce --- /dev/null +++ b/app/Http/Controllers/Admin/System/RoleController.php @@ -0,0 +1,109 @@ +parseDataTableQuery($request); + + return Inertia::render('admin/system/roles/Index', [ + 'roles' => $this->roleService->paginateForIndex($tableQuery), + 'filters' => $this->dataTableFilters($tableQuery), + ]); + } + + public function create(): Response + { + $permissions = collect(PermissionEnum::cases()) + ->map(fn (PermissionEnum $permission) => [ + 'value' => $permission->value, + 'label' => $permission->label(), + 'group' => $permission->group(), + ]) + ->values() + ->all(); + + return Inertia::render('admin/system/roles/Create', [ + 'permissions' => $permissions, + ]); + } + + public function store(RoleRequest $request): RedirectResponse + { + $this->roleService->create($request->validated()); + + $this->flashCreated('Role'); + + return redirect()->route('admin.system.roles.index'); + } + + public function edit(Role $role): Response + { + $role->load('permissions'); + + $permissions = collect(PermissionEnum::cases()) + ->map(fn (PermissionEnum $permission) => [ + 'value' => $permission->value, + 'label' => $permission->label(), + 'group' => $permission->group(), + ]) + ->values() + ->all(); + + // Check if role is developer or owner to protect it + $isProtected = in_array($role->name, [EnumsRole::DEVELOPER->value, EnumsRole::OWNER->value], true); + + return Inertia::render('admin/system/roles/Edit', [ + 'role' => [ + 'id' => $role->id, + 'name' => $role->name, + 'permission_names' => $role->permissions->pluck('name')->all(), + ], + 'permissions' => $permissions, + 'isProtected' => $isProtected, + ]); + } + + public function update(RoleRequest $request, Role $role): RedirectResponse + { + $this->roleService->update($role, $request->validated()); + + $this->flashUpdated('Role'); + + return redirect()->route('admin.system.roles.index'); + } + + public function destroy(Role $role): RedirectResponse + { + try { + $this->roleService->delete($role); + $this->flashDeleted('Role'); + } catch (\InvalidArgumentException $e) { + $this->flashError($e->getMessage()); + } + + return redirect()->route('admin.system.roles.index'); + } +} diff --git a/app/Http/Requests/Admin/System/RoleRequest.php b/app/Http/Requests/Admin/System/RoleRequest.php new file mode 100644 index 0000000..5543e70 --- /dev/null +++ b/app/Http/Requests/Admin/System/RoleRequest.php @@ -0,0 +1,60 @@ +isMethod('POST') + ? Permission::ROLES_CREATE + : Permission::ROLES_UPDATE; + + return $this->user()?->can($permission->value) ?? false; + } + + protected function prepareForValidation(): void + { + if ($this->has('name')) { + $this->merge([ + 'name' => Str::slug($this->input('name')), + ]); + } + } + + /** + * @return array + */ + public function rules(): array + { + $roleId = $this->route('role')?->id; + + return [ + 'name' => [ + 'required', + 'string', + 'max:50', + 'regex:/^[a-z0-9\-]+$/', + Rule::unique('roles', 'name')->ignore($roleId), + ], + 'permissions' => ['nullable', 'array'], + 'permissions.*' => ['string', Rule::exists('permissions', 'name')], + ]; + } + + /** + * @return array + */ + public function attributes(): array + { + return [ + 'name' => 'nama', + 'permissions' => 'hak akses', + ]; + } +} diff --git a/app/Models/User.php b/app/Models/User.php index 3bf6b3a..ee89bcf 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -93,7 +93,13 @@ public function roleLabel(): Attribute get: function () { $role = $this->roles->first(); - return $role ? Role::from($role->name)->label() : null; + if (! $role) { + return null; + } + + $enum = Role::tryFrom($role->name); + + return $enum ? $enum->label() : ucwords(str_replace('-', ' ', $role->name)); }, ); } diff --git a/app/Services/System/RoleService.php b/app/Services/System/RoleService.php new file mode 100644 index 0000000..2f9a89d --- /dev/null +++ b/app/Services/System/RoleService.php @@ -0,0 +1,87 @@ +withCount('permissions') + ->when($tableQuery['search'] !== '', function (Builder $query) use ($tableQuery): void { + $search = $tableQuery['search']; + $query->where(function (Builder $query) use ($search): void { + $query->where('name', 'like', "%{$search}%"); + }); + }); + + $this->applySorting($query, $tableQuery['sort'], $tableQuery['direction']); + + return $query + ->paginate(10) + ->withQueryString(); + } + + /** + * @param array $validated + */ + public function create(array $validated): void + { + DB::transaction(function () use ($validated): void { + $role = Role::create([ + 'name' => Str::slug($validated['name']), + 'guard_name' => 'web', + ]); + + if (! empty($validated['permissions'])) { + $role->syncPermissions($validated['permissions']); + } + }); + } + + /** + * @param array $validated + */ + public function update(Role $role, array $validated): void + { + DB::transaction(function () use ($role, $validated): void { + // Protect developer and owner names from changing + if (! in_array($role->name, [EnumsRole::DEVELOPER->value, EnumsRole::OWNER->value], true)) { + $role->name = Str::slug($validated['name']); + } + $role->save(); + + $role->syncPermissions($validated['permissions'] ?? []); + }); + } + + public function delete(Role $role): void + { + if (in_array($role->name, [EnumsRole::DEVELOPER->value, EnumsRole::OWNER->value], true)) { + throw new \InvalidArgumentException('Role developer atau owner tidak dapat dihapus.'); + } + + $role->delete(); + } + + private function applySorting(Builder $query, string $sort, string $direction): void + { + if (in_array($sort, ['name'], true)) { + $query->orderBy($sort, $direction); + + return; + } + + $query->latest(); + } +} diff --git a/database/seeders/RolePermissionSeeder.php b/database/seeders/RolePermissionSeeder.php index 55ddd23..438437f 100644 --- a/database/seeders/RolePermissionSeeder.php +++ b/database/seeders/RolePermissionSeeder.php @@ -33,30 +33,6 @@ public function run(): void ); } - $legacyRoleMap = [ - 'super-admin' => RoleEnum::DEVELOPER->value, - 'admin' => RoleEnum::DIREKTUR->value, - 'hr' => RoleEnum::ADMIN_TOKO->value, - 'user' => RoleEnum::NON_OPERATOR->value, - ]; - - foreach ($legacyRoleMap as $oldRole => $newRole) { - $oldRoleModel = Role::query()->where('name', $oldRole)->where('guard_name', 'web')->first(); - - if (! $oldRoleModel) { - continue; - } - - $newRoleModel = Role::findByName($newRole, 'web'); - - foreach ($oldRoleModel->users as $user) { - $user->removeRole($oldRole); - $user->assignRole($newRoleModel); - } - - $oldRoleModel->delete(); - } - Role::query() ->where('guard_name', 'web') ->whereNotIn('name', RoleEnum::values()) diff --git a/resources/js/components/AppSidebar.vue b/resources/js/components/AppSidebar.vue index ddca68b..97af191 100644 --- a/resources/js/components/AppSidebar.vue +++ b/resources/js/components/AppSidebar.vue @@ -1,6 +1,6 @@ + + diff --git a/resources/js/components/admin/system/roles/columns.ts b/resources/js/components/admin/system/roles/columns.ts new file mode 100644 index 0000000..77f28ec --- /dev/null +++ b/resources/js/components/admin/system/roles/columns.ts @@ -0,0 +1,62 @@ +import DataTableActions from '@/components/admin/system/roles/data-table-actions.vue'; +import { DataTableColumnHeader } from '@/components/data-table'; +import type { ColumnDef } from '@tanstack/vue-table'; +import { h } from 'vue'; + +export interface RoleListItem { + id: number; + name: string; + permissions_count: number; +} + +export function createColumns(): ColumnDef[] { + return [ + { + accessorKey: 'name', + enableSorting: true, + header: () => + h(DataTableColumnHeader, { title: 'Nama', column: 'name' }), + cell: ({ row }) => { + const name = row.original.name; + const formattedName = name + .split('-') + .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) + .join(' '); + + return h('div', { class: 'flex flex-col' }, [ + h( + 'span', + { class: 'font-medium text-foreground' }, + formattedName, + ), + h( + 'span', + { class: 'text-xs text-muted-foreground font-mono' }, + name, + ), + ]); + }, + }, + { + accessorKey: 'permissions_count', + enableSorting: false, + header: 'Jumlah Hak Akses', + cell: ({ row }) => { + return h( + 'span', + { class: 'text-sm' }, + `${row.original.permissions_count} hak akses`, + ); + }, + }, + { + id: 'actions', + enableSorting: false, + enableHiding: false, + cell: ({ row }) => + h(DataTableActions, { + role: row.original, + }), + }, + ]; +} diff --git a/resources/js/components/admin/system/roles/data-table-actions.vue b/resources/js/components/admin/system/roles/data-table-actions.vue new file mode 100644 index 0000000..cca4403 --- /dev/null +++ b/resources/js/components/admin/system/roles/data-table-actions.vue @@ -0,0 +1,84 @@ + + + diff --git a/resources/js/pages/admin/system/roles/Create.vue b/resources/js/pages/admin/system/roles/Create.vue new file mode 100644 index 0000000..58c880c --- /dev/null +++ b/resources/js/pages/admin/system/roles/Create.vue @@ -0,0 +1,40 @@ + + + diff --git a/resources/js/pages/admin/system/roles/Edit.vue b/resources/js/pages/admin/system/roles/Edit.vue new file mode 100644 index 0000000..f94b60f --- /dev/null +++ b/resources/js/pages/admin/system/roles/Edit.vue @@ -0,0 +1,49 @@ + + + diff --git a/resources/js/pages/admin/system/roles/Index.vue b/resources/js/pages/admin/system/roles/Index.vue new file mode 100644 index 0000000..218495f --- /dev/null +++ b/resources/js/pages/admin/system/roles/Index.vue @@ -0,0 +1,102 @@ + + + diff --git a/routes/web.php b/routes/web.php index 93a65f2..a38e914 100644 --- a/routes/web.php +++ b/routes/web.php @@ -24,6 +24,7 @@ use App\Http\Controllers\Admin\Master\RawMaterialController; use App\Http\Controllers\Admin\Master\SupplierController; use App\Http\Controllers\Admin\System\ActivityLogController; +use App\Http\Controllers\Admin\System\RoleController; use App\Http\Controllers\Admin\System\SettingController; use App\Http\Controllers\Auth\LoginController; use App\Http\Controllers\Auth\LogoutController; @@ -273,6 +274,27 @@ }); Route::prefix('system')->name('system.')->group(function () { + Route::prefix('roles')->name('roles.') + ->middleware('permission:'.Permission::ROLES_VIEW->value) + ->group(function () { + Route::get('/', [RoleController::class, 'index'])->name('index'); + Route::get('create', [RoleController::class, 'create']) + ->middleware('permission:'.Permission::ROLES_CREATE->value) + ->name('create'); + Route::post('/', [RoleController::class, 'store']) + ->middleware('permission:'.Permission::ROLES_CREATE->value) + ->name('store'); + Route::get('{role}/edit', [RoleController::class, 'edit']) + ->middleware('permission:'.Permission::ROLES_UPDATE->value) + ->name('edit'); + Route::put('{role}', [RoleController::class, 'update']) + ->middleware('permission:'.Permission::ROLES_UPDATE->value) + ->name('update'); + Route::delete('{role}', [RoleController::class, 'destroy']) + ->middleware('permission:'.Permission::ROLES_DELETE->value) + ->name('destroy'); + }); + Route::prefix('activity-logs')->name('activity-logs.') ->middleware('permission:'.Permission::ACTIVITY_LOGS_VIEW->value) ->group(function () {