update hak akses role: view-point-audit terkunci 'Khusus Admin' (badge + kunci di UI, proteksi di backend update()) + test
This commit is contained in:
@@ -11,6 +11,13 @@ use Illuminate\View\View;
|
||||
|
||||
class PermissionController extends Controller
|
||||
{
|
||||
/**
|
||||
* Permission yang TIDAK bisa diubah via halaman ini — khusus admin.
|
||||
*/
|
||||
public const ADMIN_ONLY_PERMISSIONS = [
|
||||
'view-point-audit',
|
||||
];
|
||||
|
||||
public function index(): View
|
||||
{
|
||||
$permissions = DB::table('permissions')
|
||||
@@ -29,7 +36,9 @@ class PermissionController extends Controller
|
||||
->toArray();
|
||||
}
|
||||
|
||||
return view('settings.permissions', compact('permissions', 'roles', 'rolePermissions'));
|
||||
$adminOnlyKeys = self::ADMIN_ONLY_PERMISSIONS;
|
||||
|
||||
return view('settings.permissions', compact('permissions', 'roles', 'rolePermissions', 'adminOnlyKeys'));
|
||||
}
|
||||
|
||||
public function update(Request $request): RedirectResponse
|
||||
@@ -46,10 +55,27 @@ class PermissionController extends Controller
|
||||
|
||||
if (! empty($data['permissions'])) {
|
||||
foreach ($data['permissions'] as $role => $permissionIds) {
|
||||
// Permission khusus admin tidak boleh diberikan ke role lain
|
||||
if ($role !== 'admin') {
|
||||
$permissionIds = array_filter($permissionIds, function ($pid) {
|
||||
$pid = (int) $pid;
|
||||
if (! $pid) {
|
||||
return false;
|
||||
}
|
||||
$key = DB::table('permissions')->where('id', $pid)->value('key');
|
||||
|
||||
return ! in_array($key, self::ADMIN_ONLY_PERMISSIONS, true);
|
||||
});
|
||||
}
|
||||
|
||||
foreach ($permissionIds as $permissionId) {
|
||||
$permissionId = (int) $permissionId;
|
||||
if (! $permissionId) {
|
||||
continue;
|
||||
}
|
||||
DB::table('role_permissions')->insert([
|
||||
'role' => $role,
|
||||
'permission_id' => (int) $permissionId,
|
||||
'permission_id' => $permissionId,
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
]);
|
||||
|
||||
@@ -96,11 +96,18 @@
|
||||
<tr class="hover:bg-gradient-to-r hover:from-blue-50/30 hover:to-white transition-all duration-100 group">
|
||||
<td class="px-5 py-3.5">
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="w-8 h-8 rounded-lg bg-gray-100 flex items-center justify-center group-hover:bg-blue-100 transition-all duration-200">
|
||||
<i class="fa-solid fa-check text-xs text-gray-400 group-hover:text-blue-500 transition-colors"></i>
|
||||
<div class="w-8 h-8 rounded-lg {{ in_array($perm->key, $adminOnlyKeys) ? 'bg-amber-50' : 'bg-gray-100' }} flex items-center justify-center group-hover:bg-blue-100 transition-all duration-200">
|
||||
<i class="fa-solid {{ in_array($perm->key, $adminOnlyKeys) ? 'fa-crown text-amber-500' : 'fa-check text-xs text-gray-400 group-hover:text-blue-500' }} transition-colors"></i>
|
||||
</div>
|
||||
<div>
|
||||
<div class="text-sm font-semibold text-gray-800">{{ $perm->label }}</div>
|
||||
<div class="text-sm font-semibold text-gray-800 flex items-center gap-2">
|
||||
{{ $perm->label }}
|
||||
@if (in_array($perm->key, $adminOnlyKeys))
|
||||
<span class="inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-[10px] font-bold bg-amber-50 text-amber-700 border border-amber-200">
|
||||
<i class="fa-solid fa-lock text-[9px]"></i> Khusus Admin
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
<div class="text-[10px] text-gray-400 font-mono mt-0.5">{{ $perm->key }}</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -109,11 +116,12 @@
|
||||
@php
|
||||
$checked = in_array($perm->id, $rolePermissions[$role] ?? []);
|
||||
$disabled = ($role === 'admin');
|
||||
$adminOnly = in_array($perm->key, $adminOnlyKeys);
|
||||
@endphp
|
||||
<td class="text-center px-3 py-3.5">
|
||||
@if($disabled)
|
||||
<div class="inline-flex items-center justify-center w-9 h-9 rounded-lg bg-blue-50 border border-blue-200">
|
||||
<i class="fa-solid fa-lock text-xs text-blue-400"></i>
|
||||
@if($disabled || $adminOnly)
|
||||
<div class="inline-flex items-center justify-center w-9 h-9 rounded-lg {{ $adminOnly ? 'bg-amber-50 border border-amber-200' : 'bg-blue-50 border border-blue-200' }}">
|
||||
<i class="fa-solid {{ $adminOnly ? 'fa-crown' : 'fa-lock' }} text-xs {{ $adminOnly ? 'text-amber-500' : 'text-blue-400' }}"></i>
|
||||
</div>
|
||||
@else
|
||||
<input type="checkbox"
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Tests\TestCase;
|
||||
|
||||
class PermissionManagementTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
$this->admin = User::factory()->create(['roles' => ['admin']]);
|
||||
}
|
||||
|
||||
public function test_permission_khusus_admin_tidak_bisa_diberikan_ke_role_lain(): void
|
||||
{
|
||||
$auditId = DB::table('permissions')->where('key', 'view-point-audit')->value('id');
|
||||
$normalId = DB::table('permissions')->where('key', 'input-violations')->value('id');
|
||||
|
||||
$this->actingAs($this->admin)
|
||||
->post('/settings/permissions', [
|
||||
'permissions' => [
|
||||
'bk' => [$auditId, $normalId],
|
||||
'ketua_tim' => [$auditId],
|
||||
],
|
||||
])
|
||||
->assertRedirect()
|
||||
->assertSessionHas('success');
|
||||
|
||||
// view-point-audit TIDAK boleh jatuh ke role non-admin
|
||||
$this->assertDatabaseMissing('role_permissions', ['role' => 'bk', 'permission_id' => $auditId]);
|
||||
$this->assertDatabaseMissing('role_permissions', ['role' => 'ketua_tim', 'permission_id' => $auditId]);
|
||||
|
||||
// permission normal tetap tersimpan
|
||||
$this->assertDatabaseHas('role_permissions', ['role' => 'bk', 'permission_id' => $normalId]);
|
||||
|
||||
// admin selalu dapat semua
|
||||
$this->assertDatabaseHas('role_permissions', ['role' => 'admin', 'permission_id' => $auditId]);
|
||||
}
|
||||
|
||||
public function test_halaman_hak_akses_menampilkan_permission_khusus_admin(): void
|
||||
{
|
||||
$response = $this->actingAs($this->admin)
|
||||
->get('/settings/permissions')
|
||||
->assertOk()
|
||||
->assertSee('Hak Akses Role')
|
||||
->assertSee('view-point-audit')
|
||||
->assertSee('Khusus Admin');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user