# Spesifikasi BE: manajemen user oleh superadmin

Dokumen untuk **tim backend** (WorkPulse API / Gin). Di **FE** saat ini halaman **Settings** belum memiliki form tambah user; `POST /api/v1/auth/register` publik selalu membuat role **`user`**. Agar **superadmin** bisa menambah akun (termasuk role **superadmin** / **user**), BE perlu endpoint khusus dengan otorisasi berbasis JWT.

---

## Keadaan sekarang (repo)

| Area | Keterangan |
|------|------------|
| `POST /api/v1/auth/register` | Publik; `INSERT ...` tanpa field `role` → default DB / hardcode **`user`** (lihat `internal/api/auth.go` → `postRegister`). |
| `authMiddleware` | Memasang `userID` + `role` dari klaim JWT akses (`internal/api/server.go`). |
| `router.go` | Tidak ada grup **`/admin`** atau middleware **`RequireRole("superadmin")`**. |
| Tabel `users` | Sudah punya kolom **`role`** (dipakai login / `getMe`). |

---

## Yang diminta produk (ringkas)

1. **Superadmin** dapat **membuat** user baru: email, nama, password awal (atau undangan / reset link — opsional fase 2), **role** (`superadmin` \| `user` \| role lain jika ada di DB).
2. **Superadmin** dapat **melihat daftar** user (pagination + filter opsional).
3. **Superadmin** dapat **mengubah** user: `is_active`, `role`, `name` (email biasanya immutable atau per flow khusus).
4. **Tidak** boleh mengandalkan FE untuk keamanan: setiap endpoint memverifikasi **`role === "superadmin"`** dari JWT + konsistensi DB.

---

## Usulan rute API (JSON envelope sama seperti `httpapi.OK` / `Fail`)

Prefix: `/api/v1/admin` (semua di bawah **`authMiddleware`** + middleware baru **`requireSuperadmin`**).

| Method | Path | Fungsi |
|--------|------|--------|
| `GET` | `/admin/users` | Daftar user (`limit`, `offset`, opsional `q` search email/nama). |
| `POST` | `/admin/users` | Buat user: body `{ "email", "password", "name", "role" }` — hash password dengan bcrypt sama seperti register. |
| `GET` | `/admin/users/:id` | Detail satu user. |
| `PATCH` | `/admin/users/:id` | Ubah `name`, `role`, `is_active` (partial JSON). |
| `POST` | `/admin/users/:id/reset-password` | (Opsional) Set password baru atau kirim token — bisa fase 2. |

**Respons error contoh**

- `403` + `forbidden` jika bukan superadmin.
- `409` + `duplicate` jika email sudah ada.
- `400` + `validation` untuk body tidak valid / role tidak dikenal.

---

## Implementasi BE (checklist)

1. **`requireSuperadmin` middleware**  
   Baca `c.Get("role")` (string) yang sudah diset `authMiddleware`; jika bukan `superadmin` → `403` + `Abort`.

2. **Daftarkan rute** di `internal/api/router.go` di dalam grup `authz` (sudah pakai bearer), lalu subgroup `admin` + `Use(requireSuperadmin)`.

3. **Handler baru** (mis. `internal/api/admin_users.go`): query ke tabel `users`; untuk `POST` gunakan pola bcrypt + insert mirip `postRegister` tetapi **izinkan set `role`** dari body (whitelist nilai: `superadmin`, `user`, …).

4. **Aturan bisnis (disarankan)**  
   - Minimal satu user **superadmin** aktif — cegah patch yang menonaktifkan / menurunkan role jika itu user superadmin terakhir.  
   - Email **lowercase** konsisten dengan `postLogin` / `postRegister`.  
   - **Audit** (opsional): log siapa membuat/mengubah user.

5. **Timeout DB**  
   Pakai `ctx` / `authCtx` konsisten dengan endpoint auth lain agar tidak hang.

6. **CORS**  
   Tidak perlu perubahan jika FE tetap same-origin `/workpulse-api`; jika cross-origin, pastikan origin work sudah di `WORKPULSE_CORS_ORIGINS`.

---

## Referensi file BE (titik masuk)

- `internal/api/router.go` — registrasi rute.
- `internal/api/server.go` — `authMiddleware`, `c.Set("role", ...)`.
- `internal/api/auth.go` — pola bcrypt, insert user, envelope JSON.
- `internal/httpapi/envelope.go` — format `{ ok, data, error }`.

---

## FE (WorkPulse Nuxt — repo ini)

- **Settings → Workspace**: superadmin melihat form **tambah pengguna**, tabel daftar, **Ubah** (nama / role / aktif) memanggil `GET/POST/PATCH /api/v1/admin/users` lewat proxy `/workpulse-api`.
- Token akses disimpan di **`sessionStorage`** setelah login (bersama role) agar panggilan admin tetap jalan setelah `location.replace("/")`.
- Komponen: `components/settings/WorkspaceUsersPanel.vue`; composable: `composables/useWorkpulseAdminUsers.ts`.

**Path dokumen ini (repo FE):** `/var/www/html/wp-system/FE/docs/BE_SPEC_ADMIN_USER_MANAGEMENT.md`
