feat: Plan 3 — Manajemen Pengguna (Admin User Management)
- Add AdminUserController: CRUD users, assign role, reset password,
self-delete guard (403 on own account)
- Add admin route group under role:administrator middleware
(GET/POST/PUT/DELETE /api/admin/users, PUT /api/admin/users/{id}/password)
- Add resources/views/admin/users.blade.php: DaisyUI table + 4 modals
(create, edit, reset password, delete confirm), stats grid, toast
- Add Admin nav link (administrator-only) to map and data navbars
- 9 new tests covering page access, API CRUD, self-delete guard, password reset
- Mark Plan 3 complete in missing_features.md; update README page list
- Save plan3 to docs/ for reference
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
class AdminUserTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
foreach (['administrator', 'pengurus_ibadah', 'petugas_pendataan', 'pemangku_kebijakan'] as $role) {
|
||||
\Spatie\Permission\Models\Role::create(['name' => $role, 'guard_name' => 'web']);
|
||||
}
|
||||
}
|
||||
|
||||
private function createUser(string $role): User
|
||||
{
|
||||
$user = User::factory()->create();
|
||||
$user->assignRole($role);
|
||||
return $user;
|
||||
}
|
||||
|
||||
public function test_admin_users_page_is_accessible(): void
|
||||
{
|
||||
$admin = $this->createUser('administrator');
|
||||
$this->actingAs($admin);
|
||||
|
||||
$this->get('/admin/users')->assertOk();
|
||||
}
|
||||
|
||||
public function test_non_admin_cannot_access_users_page(): void
|
||||
{
|
||||
$pengurus = $this->createUser('pengurus_ibadah');
|
||||
$this->actingAs($pengurus);
|
||||
|
||||
$this->get('/admin/users')->assertStatus(403);
|
||||
}
|
||||
|
||||
public function test_admin_can_list_users(): void
|
||||
{
|
||||
$admin = $this->createUser('administrator');
|
||||
$this->actingAs($admin);
|
||||
|
||||
$this->getJson('/api/admin/users')
|
||||
->assertOk()
|
||||
->assertJsonFragment(['email' => $admin->email]);
|
||||
}
|
||||
|
||||
public function test_non_admin_cannot_list_users(): void
|
||||
{
|
||||
$pengurus = $this->createUser('pengurus_ibadah');
|
||||
$this->actingAs($pengurus);
|
||||
|
||||
$this->getJson('/api/admin/users')->assertStatus(403);
|
||||
}
|
||||
|
||||
public function test_admin_can_create_user(): void
|
||||
{
|
||||
$admin = $this->createUser('administrator');
|
||||
$this->actingAs($admin);
|
||||
|
||||
$this->postJson('/api/admin/users', [
|
||||
'name' => 'User Baru',
|
||||
'email' => 'userbaru@webgis.local',
|
||||
'password' => 'password123',
|
||||
'role' => 'petugas_pendataan',
|
||||
])->assertOk()->assertJsonFragment(['email' => 'userbaru@webgis.local']);
|
||||
|
||||
$this->assertDatabaseHas('users', ['email' => 'userbaru@webgis.local']);
|
||||
}
|
||||
|
||||
public function test_admin_can_update_user(): void
|
||||
{
|
||||
$admin = $this->createUser('administrator');
|
||||
$target = $this->createUser('pengurus_ibadah');
|
||||
$this->actingAs($admin);
|
||||
|
||||
$this->putJson("/api/admin/users/{$target->id}", [
|
||||
'name' => 'Nama Diubah',
|
||||
'email' => $target->email,
|
||||
'role' => 'petugas_pendataan',
|
||||
])->assertOk()->assertJsonFragment(['name' => 'Nama Diubah']);
|
||||
|
||||
$this->assertTrue($target->fresh()->hasRole('petugas_pendataan'));
|
||||
}
|
||||
|
||||
public function test_admin_can_delete_other_user(): void
|
||||
{
|
||||
$admin = $this->createUser('administrator');
|
||||
$target = $this->createUser('pengurus_ibadah');
|
||||
$this->actingAs($admin);
|
||||
|
||||
$this->deleteJson("/api/admin/users/{$target->id}")->assertOk();
|
||||
$this->assertNull(User::find($target->id));
|
||||
}
|
||||
|
||||
public function test_admin_cannot_delete_self(): void
|
||||
{
|
||||
$admin = $this->createUser('administrator');
|
||||
$this->actingAs($admin);
|
||||
|
||||
$this->deleteJson("/api/admin/users/{$admin->id}")->assertStatus(403);
|
||||
$this->assertNotNull(User::find($admin->id));
|
||||
}
|
||||
|
||||
public function test_admin_can_reset_password(): void
|
||||
{
|
||||
$admin = $this->createUser('administrator');
|
||||
$target = $this->createUser('pengurus_ibadah');
|
||||
$this->actingAs($admin);
|
||||
|
||||
$this->putJson("/api/admin/users/{$target->id}/password", [
|
||||
'password' => 'newpassword123',
|
||||
'password_confirmation' => 'newpassword123',
|
||||
])->assertOk();
|
||||
|
||||
$this->assertTrue(
|
||||
\Illuminate\Support\Facades\Hash::check('newpassword123', $target->fresh()->password)
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user