Files
setrip/ADMIN_USER_MGMT_ROADMAP.md
T
arifal c4efe4453b -
- 
- 
- 
2026-05-18 18:31:16 +07:00

5.3 KiB

Setrip — Admin User Management Roadmap

Admin perlu bisa cari user dan suspend akun yang melakukan abuse (scam, harassment, fake review).

Skenario nyata: organizer scam berkali-kali bikin trip palsu pakai alias berbeda. Peserta lapor harassment dari user lain di grup WA trip. Saat ini admin cuma bisa refund korban — pelaku tetap bisa lanjut bikin trip baru / join trip lain.


Baseline

  • userRepo.findByEmail() dan userRepo.findById() ada di server/repositories/user.repo.ts.
  • User model lengkap dengan relasi ke trips, participations, bookings, tripReviews, organizerVerification, payouts.
  • Tidak ada page /admin/users.
  • Tidak ada field suspended di User.
  • Tidak ada guard di auth/server actions yang reject suspended user.
  • Tidak ada stats user (total signups, organizer aktif, peserta aktif).

Phase 1 — User List & Detail View

Baseline visibility. Sama pola dengan trip ops — list + search + detail.

Keputusan asumsi:

  • Search by email exact match dulu (paling sering dipakai admin saat ada laporan); kalau perlu, tambah name LIKE search nanti.
  • Detail page tampilkan: profile, verification status, booking history (sebagai peserta), trip history (sebagai organizer), payout history (sebagai organizer), review yang dibuat & diterima.
  • Sensitive info (password hash, OAuth tokens) tidak ditampilkan.
# Item Status File
1.1 userRepo.searchForAdmin({ q?, role?, suspended? }) — q match email atau name (case insensitive) server/repositories/user.repo.ts
1.2 Page /admin/users — list + search bar + filter (organizer/participant/suspended) app/admin/users/page.tsx
1.3 Page /admin/users/[id] — profil + tabs (Bookings, Trips Dibuat, Reviews, Verification) app/admin/users/[id]/page.tsx
1.4 Stats card di top: total bookings, total spent, total revenue (kalau organizer), verification status app/admin/users/[id]/page.tsx
1.5 Link "Users" di admin navbar app/admin/layout.tsx

Tindakan manual: tidak ada.


Phase 2 — User Suspension

Toggle suspend yang mencegah suspended user login + melakukan aksi mutatif.

Keputusan asumsi:

  • Tambah 4 kolom di User: suspended Boolean @default(false), suspendedAt DateTime?, suspendedReason String?, suspendedBy String? (FK User admin).
  • Block sign-in di NextAuth callbacks (signIn callback return false kalau user.suspended). Untuk JWT session sudah aktif, cek suspended di session callback lalu invalidate.
  • Block mutating actions via helper requireActiveUser(session) yang dipanggil di awal setiap server action mutating (joinTrip, createTrip, addReview, dst).
  • Suspended user tetap bisa lihat data sendiri (refund history, dll) — tidak hard-delete supaya audit trail terjaga.
  • Suspended organizer otomatis sembunyikan trip OPEN/FULL miliknya dari public list — tambah filter di tripRepo.findOpen (organizer: { suspended: false }).
  • Unsuspend = toggle false + clear field — tetap simpan history via ADMIN_AUDIT_ROADMAP.md Phase 4.
# Item Status File
2.1 Migration: tambah suspended, suspendedAt, suspendedReason, suspendedBy di User prisma/migrations/
2.2 userService.suspendUser(userId, adminId, reason) + unsuspendUser(userId, adminId) server/services/user.service.ts
2.3 Block sign-in di NextAuth signIn callback lib/auth.ts
2.4 Helper requireActiveUser(session) throw kalau suspended lib/auth-guards.ts
2.5 Wire requireActiveUser di semua mutating server action (joinTripAction, createTripAction, createReviewAction, dst) features/*/actions.ts
2.6 Filter trip public list: organizer tidak suspended server/repositories/trip.repo.ts
2.7 UI: tombol "Suspend" / "Unsuspend" di /admin/users/[id] + modal reason wajib app/admin/users/[id]/page.tsx
2.8 Badge "SUSPENDED" di user list + detail header (visual jelas) app/admin/users/[id]/page.tsx
2.9 Server action suspendUserAction + unsuspendUserAction (guard isAdmin) features/admin/actions.ts (baru) atau features/user/actions.ts

Tindakan manual:

  1. Brief admin: kriteria suspend (3 kategori: scam, harassment, repeated TOS violation). Hindari subjective suspend.
  2. Tulis halaman info "Akun ditangguhkan" yang ditampilkan saat suspended user coba login (jelaskan kenapa & cara appeal via email).
  3. Pertimbangkan suspended user di Midtrans webhook — saat ada payment masuk untuk suspended user's booking, tetap di-PAID (uang tetap diterima, refund proses normal).

Phase 3 — User Analytics (low priority, skip MVP)

Dashboard stats untuk growth tracking. Skip sampai ada kebutuhan konkret.

# Item Status File
3.1 Stats endpoint: total user, signup per minggu (4 minggu terakhir), organizer aktif (yang punya OPEN/FULL trip), peserta aktif (booking PAID) app/admin/users/stats/page.tsx
3.2 Chart sederhana (HTML/SVG inline, no chart library) app/admin/users/stats/page.tsx

Tindakan manual: tidak ada (skip phase ini).