From 32ce358eef091e33e4e3f6ce4f634b5e09433b0a Mon Sep 17 00:00:00 2001 From: ShowMeMyCent Date: Fri, 14 Aug 2026 17:55:30 +0700 Subject: [PATCH] Fix role creation leaving new roles with zero permissions RoleController::store had three stacked bugs that combined to make role creation silently non-functional: - The 'super' and 'aslab' package cases were commented out in the switch statement, falling through to a default branch that reset the whole permissions accumulator to empty. - No package guaranteed manage-profile/lms-configuration, the only permissions accepted by the /assistant route every asisten lands on after login, so roles without asisten or aslab checked could log in but were immediately blocked. - PermissionGroupEnum::ASISTEN (the default, pre-checked package) referenced see-modul, a permission never seeded into the database and checked by no route. syncPermissions() throws on unresolvable names before writing anything, so any role including the default package ended up with zero permissions regardless of the fixes above. Removed the dead see-modul entry; ImportSqlDump.php already worked around this same bug locally, so simplified it to match. Also gate Reverb/Echo initialization on VITE_REVERB_APP_KEY being configured, since local dev without a running Reverb server was spamming failed websocket reconnect attempts. Removed echo.js, a dead duplicate of the same unconditional Echo instantiation. Co-Authored-By: Claude Sonnet 5 --- app/Console/Commands/ImportSqlDump.php | 2 +- app/Http/Controllers/API/RoleController.php | 19 +++++++---- app/PermissionGroupEnum.php | 3 -- resources/js/bootstrap.js | 38 ++++++++++++--------- resources/js/echo.js | 20 ----------- 5 files changed, 34 insertions(+), 48 deletions(-) delete mode 100644 resources/js/echo.js diff --git a/app/Console/Commands/ImportSqlDump.php b/app/Console/Commands/ImportSqlDump.php index 064a07e..d42a0cf 100644 --- a/app/Console/Commands/ImportSqlDump.php +++ b/app/Console/Commands/ImportSqlDump.php @@ -311,7 +311,7 @@ private function runLegacyToNewMapping(string $connection, string $legacyDb, str 'aslab' => array_merge(PermissionGroupEnum::ASLAB, ['manage-pelanggaran']), 'atc' => PermissionGroupEnum::ATC, 'rdc' => PermissionGroupEnum::RDC, - 'asisten' => array_values(array_diff(PermissionGroupEnum::ASISTEN, [PermissionGroupEnum::SEE_MODUL])), + 'asisten' => PermissionGroupEnum::ASISTEN, 'praktikan' => PermissionGroupEnum::PRAKTIKAN, ]; diff --git a/app/Http/Controllers/API/RoleController.php b/app/Http/Controllers/API/RoleController.php index 8359b59..3e4cabf 100644 --- a/app/Http/Controllers/API/RoleController.php +++ b/app/Http/Controllers/API/RoleController.php @@ -71,12 +71,12 @@ public function store(Request $request) } switch ($paket) { - // case 'super': - // $permissions = array_merge($permissions, $SUPER_PACKAGE); - // break; - // case 'aslab': - // $permissions = array_merge($permissions, $ASLAB_PACKAGE); - // break; + case 'super': + $permissions = array_merge($permissions, $SUPER_PACKAGE); + break; + case 'aslab': + $permissions = array_merge($permissions, $ASLAB_PACKAGE); + break; case 'atc': $permissions = array_merge($permissions, $ATC_PACKAGE); break; @@ -92,13 +92,18 @@ public function store(Request $request) } } + // Every asisten role needs manage-profile to land on /assistant after login, + // regardless of which packages were selected (mirrors RolePermissionsSeeder, + // where every seeded role has it). + $permissions[] = PermissionGroupEnum::MANAGE_PROFILE; + $role = Role::create([ 'name' => $request->name, 'guard_name' => 'asisten', 'created_at' => now(), 'updated_at' => now(), ]); - $role->syncPermissions($permissions); + $role->syncPermissions(array_unique($permissions)); return redirect(route('manage-role'))->with('success', 'Role created successfully.'); } catch (\Throwable $th) { diff --git a/app/PermissionGroupEnum.php b/app/PermissionGroupEnum.php index 20a0d32..a2b8614 100644 --- a/app/PermissionGroupEnum.php +++ b/app/PermissionGroupEnum.php @@ -14,8 +14,6 @@ enum PermissionGroupEnum: string const MANAGE_MODUL = 'manage-modul'; - const SEE_MODUL = 'see-modul'; - const MANAGE_SOAL = 'manage-soal'; const UNLOCK_JAWABAN = 'unlock-jawaban'; @@ -100,7 +98,6 @@ enum PermissionGroupEnum: string self::MANAGE_PROFILE, self::SEE_PRAKTIKUM, self::SEE_HISTORY, - self::SEE_MODUL, self::SEE_SOAL, self::NILAI_PRAKTIKAN, self::SEE_PLOT, diff --git a/resources/js/bootstrap.js b/resources/js/bootstrap.js index f46079f..6854930 100644 --- a/resources/js/bootstrap.js +++ b/resources/js/bootstrap.js @@ -7,25 +7,29 @@ window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; window.Pusher = Pusher; -window.Echo = new Echo({ - broadcaster: 'reverb', - key: import.meta.env.VITE_REVERB_APP_KEY, - wsHost: import.meta.env.VITE_REVERB_HOST, - wsPort: import.meta.env.VITE_REVERB_PORT ?? 80, - wssPort: import.meta.env.VITE_REVERB_PORT ?? 443, - forceTLS: (import.meta.env.VITE_REVERB_SCHEME ?? 'https') === 'https', - enabledTransports: ['ws'], - authEndpoint: '/broadcasting/auth', - auth: { - headers: { - 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]')?.getAttribute('content'), - }, - }, -}); /** * Echo exposes an expressive API for subscribing to channels and listening * for events that are broadcast by Laravel. Echo and event broadcasting * allow your team to quickly build robust real-time web applications. + * + * Only connect when a Reverb key is configured (VITE_REVERB_APP_KEY) so local + * dev without a running Reverb server doesn't spam failed websocket retries. + * Consumers already guard on `window.Echo` being truthy before using it. */ - -import './echo'; +if (import.meta.env.VITE_REVERB_APP_KEY) { + window.Echo = new Echo({ + broadcaster: 'reverb', + key: import.meta.env.VITE_REVERB_APP_KEY, + wsHost: import.meta.env.VITE_REVERB_HOST, + wsPort: import.meta.env.VITE_REVERB_PORT ?? 80, + wssPort: import.meta.env.VITE_REVERB_PORT ?? 443, + forceTLS: (import.meta.env.VITE_REVERB_SCHEME ?? 'https') === 'https', + enabledTransports: ['ws'], + authEndpoint: '/broadcasting/auth', + auth: { + headers: { + 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]')?.getAttribute('content'), + }, + }, + }); +} diff --git a/resources/js/echo.js b/resources/js/echo.js deleted file mode 100644 index 65b8ad9..0000000 --- a/resources/js/echo.js +++ /dev/null @@ -1,20 +0,0 @@ -import Echo from 'laravel-echo'; - -import Pusher from 'pusher-js'; -window.Pusher = Pusher; - -window.Echo = new Echo({ - broadcaster: 'reverb', - key: import.meta.env.VITE_REVERB_APP_KEY, - wsHost: import.meta.env.VITE_REVERB_HOST, - wsPort: import.meta.env.VITE_REVERB_PORT ?? 80, - wssPort: import.meta.env.VITE_REVERB_PORT ?? 443, - forceTLS: (import.meta.env.VITE_REVERB_SCHEME ?? 'https') === 'https', - enabledTransports: ['ws', 'wss'], - authEndpoint: '/broadcasting/auth', - auth: { - headers: { - 'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]')?.getAttribute('content'), - }, - }, -});