Skip to content

feat: Service Klien API Satu Data & Menu DataSpasial Berbasis Peran (KAB-01) - #1307

Open
pandigresik wants to merge 2 commits into
rilis-devfrom
2503-dataspasial-integration
Open

pandigresik wants to merge 2 commits into
rilis-devfrom
2503-dataspasial-integration

Conversation

@pandigresik

@pandigresik pandigresik commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

Pull Request: feat: Service Klien API Satu Data & Menu DataSpasial Berbasis Peran (KAB-01)

Description

PR ini membangun fondasi integrasi DataSpasial untuk OpenKab: satu service klien terpusat untuk seluruh endpoint /api/v1/dataspasial/* milik API Satu Data (API-Database-Gabungan), lima menu DataSpasial yang hanya terbuka bagi peran berwenang, serta penanganan kegagalan yang menampilkan pesan "data sementara tidak tersedia" alih-alih halaman error. OpenKab tidak terhubung langsung ke database gabungan dan tidak membuat tabel ds_* — seluruh baca/tulis melewati API Satu Data. Satu-satunya perubahan data lokal adalah peran & izin (spatie), yang dipasok lewat data migration agar otomatis tersedia saat deploy.

Changes made:

  1. Service klien (baru): app/Services/DataSpasialApiService.php — pintu tunggal seluruh pemanggilan /api/v1/dataspasial/* (10 operasi baca + 3 operasi tulis), bearer token, timeout, header identitas pemanggil, klasifikasi hasil tiga-keadaan, dan cache baca TTL + invalidasi setelah tulis.
  2. Value object & enum (baru): app/Services/DataSpasialResult.php, app/Enums/DataSpasialStatus.php, app/Enums/DataSpasialReason.php, app/Exceptions/DataSpasialUnavailableException.php — status yang dapat dibedakan: data / empty / unavailable beserta reason untuk log.
  3. Konfigurasi (baru): config/dataspasial.php (timeout, cache_ttl, cache_store, cache_prefix, path_prefix, header identitas, pesan unavailable) dan penambahan API_DATASPASIAL_TIMEOUT + API_DATASPASIAL_CACHE_TTL ke .env.example. Base URL & token tidak dikonfigurasi di sini.
  4. Menu (modifikasi): entri grup "DataSpasial" (5 submenu) pada app/Enums/Modul.php sebagai satu-satunya sumber kebenaran menu admin.
  5. Kontrol akses (modifikasi): grup route dataspasial pada routes/web.php dijaga middleware permission:dataspasial-*-read (server-side, bukan sekadar menyembunyikan menu) + 5 controller kerangka di app/Http/Controllers/DataSpasial/.
  6. Tampilan (baru): partial resources/views/dataspasial/unavailable.blade.php dan empty.blade.php, komponen resources/views/components/dataspasial-status.blade.php, serta 5 halaman kerangka menu.
  7. Peran & izin (baru): data migration database/migrations/2026_10_14_000001_create_dataspasial_roles.php — menyediakan peran Admin Skema, Operator Impor, Analis OPD beserta matriks izinnya; role administrator diberi akses lewat admin:menu-update.
  8. Perbaikan (modifikasi): app/Services/BaseApiService.php — perbaiki presedensi operator pada header Authorization ('Bearer '.$x['k'] ?? '' → 'Bearer '.($x['k'] ?? '')).
  9. Pengujian (baru): tests/Feature/DataSpasial/* (service, menu access, result, role migration, unavailable) dan tests/Browser/SmokeDataSpasialMenuTest.php, seluruhnya terisolasi dengan DatabaseTransactions.

Reason for change:

  • Satu pintu akses: Menghindari pemanggilan API tersebar; seluruh modul DataSpasial memakai konfigurasi, timeout, cache, penanganan error, dan header audit yang sama (FR-002/SC-009).
  • Keamanan akses: Menegakkan otorisasi di sisi server lewat middleware permission, sehingga Analis OPD tidak dapat mengakses pengelolaan skema/impor walau mengetik URL langsung (FR-011/FR-013).
  • Ketahanan integrasi: API eksternal bisa mati/timeout; pengguna tetap melihat pesan generik di area konten dengan kerangka halaman utuh, bukan halaman error/stack trace (FR-014/FR-015).
  • Audit: Setiap request membawa identitas pemanggil X-OpenKab-User-Id/X-OpenKab-User-Name agar tercatat pada audit API-07 (OpenSID/API-Database-Gabungan#473).
  • Otomatisasi deploy: Peran & izin disediakan lewat data migration, sehingga php artisan migrate sudah cukup tanpa langkah db:seed manual.

Impact of change:

✅ Konsistensi: Semua modul DataSpasial memakai satu DataSpasialApiService; tidak ada pemanggilan Http:: langsung ke /dataspasial/*.
✅ Keamanan: Menu tersembunyi dan akses URL ditolak (403) bagi peran tanpa izin.
✅ Ketahanan: Degradasi anggun saat API bermasalah; tanpa halaman error.
✅ Observabilitas: Kegagalan API dicatat (Log::warning) dengan endpoint, status, dan reason, tanpa membocorkan detail teknis ke pengguna.
✅ Performa: Cache baca TTL (default 300 dtk) menekan permintaan berulang; invalidasi kasar per-namespace mencegah data basi setelah tulis/impor.

Related Issue

#1296

Steps to Reproduce

Kata kunci verifikasi (fitur baru):

  1. php artisan migrate pada basis data bersih (menjalankan data migration peran) lalu php artisan admin:menu-update.
  2. Login sebagai administrator → navigasi memuat grup DataSpasial berisi 5 submenu: Skema DataSpasial, Peta Gabungan, Dasbor DataSpasial, Impor Data, Monitoring.
  3. Pastikan Setting database_gabungan_api_key terisi dan API_DATABASE_GABUNGAN_HOST menunjuk API Satu Data.
  4. Matikan API (atau buat timeout) → muat ulang salah satu menu → ✅ tampil "Data sementara tidak tersedia. Silakan coba lagi nanti." pada area konten; sidebar & kerangka halaman tetap ada (bukan halaman error).
  5. Login sebagai user grup analis opd → ✅ hanya Peta Gabungan, Dasbor, Monitoring yang tampil; akses langsung ke /dataspasial/skema dan /dataspasial/impor → ❌ 403 Forbidden.

Testing on related features:

  • Navigator/sidebar adminlte ✅ tetap dirender normal.
  • Service database gabungan existing (BaseApiService) ✅ tidak terganggu (perbaikan presedensi hanya memperbaiki kasus token kosong).

Checklist

  • I have complied with script writing rules
  • I have followed pull request review process
  • I have created unit test/integration test to verify the fix
  • Manual testing has been done in development environment
  • No console errors or warnings
  • Code has been reviewed by at least 1 person

Technical Details

Technical Explanation

Alur service (DataSpasialApiService)

Controller → DataSpasialApiService::request()
              ├─ cache baca (GET) → DataSpasialResult::fromCachePayload()
              ├─ Http::withHeaders(Accept, Authorization: Bearer <token>,
              │     X-OpenKab-User-Id, X-OpenKab-User-Name [, X-Schema-Version])
              │     ->timeout(config('dataspasial.timeout'))
              └─ map respons → data | empty | unavailable(reason)
                    ├─ tulis sukses → invalidateCache() (bump generation)
                    └─ unavailable → TIDAK di-cache + Log::warning
  • Sumber kredensial: Base URL dari config('app.databaseGabunganUrl') (env API_DATABASE_GABUNGAN_HOST) dan token dari Setting key database_gabungan_api_key — mengikuti pengaturan database gabungan yang sudah ada (bukan config/env khusus DataSpasial).
  • Tiga keadaan: DataSpasialStatus (data/empty/unavailable) dengan DataSpasialResult immutable yang memvalidasi invariant di constructor.
  • Pemetaan error: 401/403 → unauthorized; 503 pada /dataspasial/* → module_not_installed (keadaan "modul belum terpasang / belum dikonfigurasi sepenuhnya" diperoleh dari respons API, sesuai API-02/Perbaikan data papan #467); 5xx lain → http_5xx; 400 SchemaVersionUnsupported → schema_version_unsupported; timeout/connection → timeout/connection_failed.
  • Cache: kunci dataspasial:get:{generation}:{path}:{md5(query)}; invalidasi O(1) dengan menaikkan nomor generasi setelah operasi tulis sukses.
  • Kontrol akses: routes/web.php memakai permission:dataspasial-{menu}-read; visibilitas menu mengikuti JSON team.menu.
  • Peran: Team (grup) + Role spatie dengan team_id sama. Matriks: Admin Skema → skema (read/write/edit/delete) + baca peta/dasbor/monitoring; Operator Impor → impor (read/write) + baca peta/dasbor/monitoring; Analis OPD → baca peta/dasbor/monitoring. Administrator → seluruh permission via admin:menu-update.

Configuration changes

.env (opsional, ada default):

API_DATASPASIAL_TIMEOUT=10      # detik
API_DATASPASIAL_CACHE_TTL=300   # detik (0 = nonaktif)

Base URL & token tidak memakai env khusus:

  • URL : API_DATABASE_GABUNGAN_HOST → config('app.databaseGabunganUrl')
  • Token: Setting key database_gabungan_api_key

Dependencies added

No new dependencies.

Testing

Manual Testing

  • Grup menu DataSpasial tampil untuk administrator dengan 5 submenu.
  • Analis OPD tidak melihat menu Skema/Impor dan ditolak (403) saat akses URL langsung.
  • API mati/timeout/503 → pesan "Data sementara tidak tersedia" dengan kerangka halaman utuh.
  • Respons sukses tanpa data → empty state, bukan error.
  • Header X-OpenKab-User-Id & X-OpenKab-User-Name terkirim pada request baca & tulis.
  • Regression Testing — fitur existing (menu lain, service database gabungan) tidak terganggu.

Automated Testing

  • vendor/bin/pest tests/Feature/DataSpasial/DataSpasialApiServiceTest.php — sukses, kosong, 503, timeout, konfigurasi tidak lengkap, header audit, cache & invalidasi.
  • vendor/bin/pest tests/Feature/DataSpasial/DataSpasialMenuAccessTest.php — visibilitas menu + penolakan URL langsung per peran.
  • vendor/bin/pest tests/Feature/DataSpasial/DataSpasialRoleMigrationTest.php — 3 peran + matriks izin + idempotensi + akses administrator.
  • vendor/bin/pest tests/Feature/DataSpasial/DataSpasialUnavailableTest.php — pesan generik, empty state, kerangka utuh, tanpa stack trace.
  • vendor/bin/pest tests/Browser/SmokeDataSpasialMenuTest.php — smoke menu per peran.

Catatan: seluruh feature test memakai trait DatabaseTransactions (rollback otomatis) sehingga tidak mengotori basis data.

Screenshots / Video

simplescreenrecorder-2026-10-14_15.15.40.mp4

Before:

Menu DataSpasial belum tersedia; tidak ada service klien API Satu Data.

After:

Grup menu DataSpasial tampil sesuai peran; seluruh pemanggilan API Satu Data melewati satu service; kegagalan API tampil sebagai pesan di area konten.

Breaking Changes

None. (app/Services/BaseApiService.php hanya memperbaiki presedensi operator agar token kosong tidak memicu peringatan akses array — perilaku untuk token valid tidak berubah.)

Migration Guide

Cukup jalankan:

php artisan migrate          # menjalankan data migration peran & izin DataSpasial
php artisan admin:menu-update  # rebuild permission & menu administrator dari App\Enums\Modul::Menu

Tidak ada perubahan tabel ds_* (tabel DataSpasial tetap berada di API Satu Data).

Catatan Penyimpangan dari Deskripsi Issue

Perubahan desain berikut disepakati selama klarifikasi spesifikasi:

  1. URL & token: Tidak memakai env khusus (issue menyebut "URL dan token di .env"). Keduanya otomatis mengikuti pengaturan database gabungan — config('app.databaseGabunganUrl') dan Setting database_gabungan_api_key — untuk menghindari dua sumber kebenaran.
  2. Peran & hak akses: Disediakan lewat data migration (issue menyebut "dengan seeder") agar otomatis berjalan saat php artisan migrate pada deploy.
  3. Isolasi uji: Seluruh uji memakai DatabaseTransactions agar tidak mengotori basis data.
  4. Kode "modul belum terpasang/terkonfigurasi": Keadaan/pesan diperoleh dari hasil respons API (API-02), bukan dideteksi lokal.

References


Additional notes: Fitur ini adalah fondasi; fungsi rinci tiap menu (editor sektor/isian/pemetaan, peta geospasial, dashboard agregat, log entri) menjadi lingkup fitur turunan KAB-02/KAB-04/KAB-06/KAB-08 dan dibangun di atas kontrak service ini tanpa mengubahnya.

@github-actions

Copy link
Copy Markdown
Contributor

🔄 AI PR Review sedang antri di server...

Proses review akan segera dimulai di background — hasil akan muncul sebagai komentar setelah selesai.
Powered by CrewAI · PR #1307

@pandigresik pandigresik changed the title Klien API Satu Data, menu & peran feat: Service Klien API Satu Data & Menu DataSpasial Berbasis Peran (KAB-01) Oct 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant