From 08d3982aa59d9ffc25828789c640ba3f4c3304c0 Mon Sep 17 00:00:00 2001 From: Yoga Pangestu Date: Tue, 14 Jul 2026 21:30:15 +0700 Subject: [PATCH] feat: enhance employee pagination by incorporating user role checks for improved access control --- .../Admin/Hr/EmployeeController.php | 1 + app/Services/Hr/EmployeeService.php | 11 +++ tests/Feature/Admin/Hr/EmployeeTest.php | 76 +++++++++++++++++++ 3 files changed, 88 insertions(+) diff --git a/app/Http/Controllers/Admin/Hr/EmployeeController.php b/app/Http/Controllers/Admin/Hr/EmployeeController.php index e3575b4..a1986a3 100644 --- a/app/Http/Controllers/Admin/Hr/EmployeeController.php +++ b/app/Http/Controllers/Admin/Hr/EmployeeController.php @@ -36,6 +36,7 @@ public function index(Request $request): Response return Inertia::render('admin/hr/employees/Index', [ 'employees' => $this->employeeService->paginateForIndex( $tableQuery, + $request->user(), $role, $gender, $employmentStatus, diff --git a/app/Services/Hr/EmployeeService.php b/app/Services/Hr/EmployeeService.php index bb14dba..316c4c2 100644 --- a/app/Services/Hr/EmployeeService.php +++ b/app/Services/Hr/EmployeeService.php @@ -28,6 +28,7 @@ public function __construct( public function paginateForIndex( array $tableQuery, + User $authUser, string $role = '', string $gender = '', string $employmentStatus = '', @@ -36,6 +37,16 @@ public function paginateForIndex( $query = User::query() ->with(['profile', 'employee', 'roles']) ->whereDoesntHave('roles', fn ($query) => $query->where('name', Role::DEVELOPER->value)) + ->when( + $authUser->hasRole(Role::ADMIN_BAHAN_BAKU->value), + fn ($query) => $query->whereHas('roles', fn ($query) => $query->where('name', Role::ADMIN_BAHAN_BAKU->value)) + ) + ->when( + $authUser->hasAnyRole([Role::DIREKTUR->value, Role::ADMIN_TOKO->value]), + fn ($query) => $query + ->whereDoesntHave('roles', fn ($query) => $query->where('name', Role::OWNER->value)) + ->whereDoesntHave('roles', fn ($query) => $query->where('name', Role::ADMIN_BAHAN_BAKU->value)) + ) ->when($tableQuery['search'] !== '', function ($query) use ($tableQuery): void { $search = $tableQuery['search']; $query->where(function ($query) use ($search): void { diff --git a/tests/Feature/Admin/Hr/EmployeeTest.php b/tests/Feature/Admin/Hr/EmployeeTest.php index 039ef9c..3217570 100644 --- a/tests/Feature/Admin/Hr/EmployeeTest.php +++ b/tests/Feature/Admin/Hr/EmployeeTest.php @@ -160,6 +160,82 @@ function validEmployeePayload(): array ->assertDontSee($developer->email) ->assertSee($employee->email); }); + + test('admin bahan baku hanya melihat pegawai dengan role yang sama', function () { + $user = createEmployeeUserWithPermission(PermissionEnum::EMPLOYEES_VIEW); + $user->assignRole('admin-bahan-baku'); + $user->forgetCachedPermissions(); + + $pegawaiBahanBaku = User::factory()->create(); + UserProfile::factory()->create(['user_id' => $pegawaiBahanBaku->id, 'full_name' => fake()->name()]); + Employee::factory()->create(['user_id' => $pegawaiBahanBaku->id]); + $pegawaiBahanBaku->assignRole('admin-bahan-baku'); + + $pegawaiLain = User::factory()->create(); + UserProfile::factory()->create(['user_id' => $pegawaiLain->id, 'full_name' => fake()->name()]); + Employee::factory()->create(['user_id' => $pegawaiLain->id]); + $pegawaiLain->assignRole('marketing-offline'); + + $this->actingAs($user) + ->get(route('admin.hr.employees.index')) + ->assertOk() + ->assertSee($pegawaiBahanBaku->email) + ->assertDontSee($pegawaiLain->email); + }); + + test('direktur tidak melihat owner dan admin bahan baku', function () { + $user = createEmployeeUserWithPermission(PermissionEnum::EMPLOYEES_VIEW); + $user->assignRole('direktur'); + $user->forgetCachedPermissions(); + + $owner = User::factory()->create(); + UserProfile::factory()->create(['user_id' => $owner->id, 'full_name' => fake()->name()]); + $owner->assignRole('owner'); + + $adminBahanBaku = User::factory()->create(); + UserProfile::factory()->create(['user_id' => $adminBahanBaku->id, 'full_name' => fake()->name()]); + Employee::factory()->create(['user_id' => $adminBahanBaku->id]); + $adminBahanBaku->assignRole('admin-bahan-baku'); + + $marketing = User::factory()->create(); + UserProfile::factory()->create(['user_id' => $marketing->id, 'full_name' => fake()->name()]); + Employee::factory()->create(['user_id' => $marketing->id]); + $marketing->assignRole('marketing-offline'); + + $this->actingAs($user) + ->get(route('admin.hr.employees.index')) + ->assertOk() + ->assertDontSee($owner->email) + ->assertDontSee($adminBahanBaku->email) + ->assertSee($marketing->email); + }); + + test('admin toko tidak melihat owner dan admin bahan baku', function () { + $user = createEmployeeUserWithPermission(PermissionEnum::EMPLOYEES_VIEW); + $user->assignRole('admin-toko'); + $user->forgetCachedPermissions(); + + $owner = User::factory()->create(); + UserProfile::factory()->create(['user_id' => $owner->id, 'full_name' => fake()->name()]); + $owner->assignRole('owner'); + + $adminBahanBaku = User::factory()->create(); + UserProfile::factory()->create(['user_id' => $adminBahanBaku->id, 'full_name' => fake()->name()]); + Employee::factory()->create(['user_id' => $adminBahanBaku->id]); + $adminBahanBaku->assignRole('admin-bahan-baku'); + + $cashier = User::factory()->create(); + UserProfile::factory()->create(['user_id' => $cashier->id, 'full_name' => fake()->name()]); + Employee::factory()->create(['user_id' => $cashier->id]); + $cashier->assignRole('cashier'); + + $this->actingAs($user) + ->get(route('admin.hr.employees.index')) + ->assertOk() + ->assertDontSee($owner->email) + ->assertDontSee($adminBahanBaku->email) + ->assertSee($cashier->email); + }); }); // ─── Create ───────────────────────────────────────────────