diff --git a/MODULE_GUIDE.md b/MODULE_GUIDE.md new file mode 100644 index 0000000..8e60def --- /dev/null +++ b/MODULE_GUIDE.md @@ -0,0 +1,111 @@ +# Panduan Menambah Module Baru + +## 📦 Struktur Module + +Setiap module baru mengikuti pola yang sama: + +``` +src/Modules/ModuleBaru/ + ├── ModuleBaruRoutes.php # Register routes + ├── Controller.php # Request handler + └── Service.php # Business logic +``` + +## 🚀 Langkah Menambah Module + +### 1. Buat Struktur Folder + +```bash +mkdir -p src/Modules/ModuleBaru +``` + +### 2. Buat Routes File + +`src/Modules/ModuleBaru/ModuleBaruRoutes.php`: + +```php +group('/modulebaru', function ($group) { + $group->group('/v1', function ($v1Group) { + // Routes di sini + $v1Group->get('/endpoint', [Controller::class, 'method']); + }); + }); + } +} +``` + +### 3. Register di public/index.php + +Tambahkan di bagian "Register module routes": + +```php +use App\Modules\ModuleBaru\ModuleBaruRoutes; + +// ... + +// Register module routes +HealthRoutes::register($app); +AuthRoutes::register($app); +RetribusiRoutes::register($app); +ModuleBaruRoutes::register($app); // <-- Tambahkan di sini +``` + +### 4. Update OpenAPI Spec (Opsional) + +Edit `public/docs/openapi.json` dan tambahkan endpoint baru di `paths`. + +## ✅ Contoh: Module "Parkir" + +```php +// src/Modules/Parkir/ParkirRoutes.php +namespace App\Modules\Parkir; + +use App\Middleware\JwtMiddleware; +use Slim\App; + +class ParkirRoutes +{ + public static function register(App $app): void + { + $jwtMiddleware = new JwtMiddleware(); + + $app->group('/parkir', function ($group) use ($jwtMiddleware) { + $group->group('/v1', function ($v1Group) use ($jwtMiddleware) { + $v1Group->get('/zones', [ParkirController::class, 'getZones']) + ->add($jwtMiddleware); + }); + }); + } +} +``` + +## 🔄 Best Practices + +1. **Isolasi**: Setiap module independen +2. **Naming**: Gunakan namespace yang jelas +3. **Routes**: Group by module name +4. **Versioning**: Gunakan `/v1` untuk future compatibility +5. **Middleware**: Apply di level group atau route + +## 📝 Checklist Module Baru + +- [ ] Buat folder `src/Modules/ModuleName/` +- [ ] Buat `ModuleNameRoutes.php` dengan method `register()` +- [ ] Buat Controller & Service (jika perlu) +- [ ] Register di `public/index.php` +- [ ] Test routes +- [ ] Update OpenAPI spec (opsional) +- [ ] Commit & push + diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..4b347da --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,204 @@ +# Security Guidelines - API Documentation + +## 🔒 Keamanan API Documentation + +### Current Implementation + +Saat ini API documentation (Swagger UI) di `/docs` **PUBLIC** - bisa diakses tanpa authentication. + +### ⚠️ Security Considerations + +**Risiko jika docs public:** +1. **Information Disclosure**: Endpoint structure terlihat semua orang +2. **Attack Surface**: Attacker tahu semua endpoint yang ada +3. **API Key Exposure**: Jika ada contoh API key di docs (jangan!) +4. **Business Logic**: Flow bisnis bisa terlihat + +**Tapi juga ada benefit:** +1. **Developer Experience**: Developer mudah test API +2. **Onboarding**: New developer cepat paham +3. **Integration**: Partner bisa lihat spec dengan mudah + +## 🛡️ Opsi Security untuk Docs + +### Opsi 1: Public (Current - Recommended untuk Internal API) + +**Cocok untuk:** +- Internal API (tidak public internet) +- API dengan authentication kuat (JWT + Role) +- Development/Staging environment + +**Kelebihan:** +- Mudah digunakan +- Developer friendly +- Tidak perlu setup tambahan + +**Kekurangan:** +- Endpoint structure terlihat +- Perlu pastikan tidak ada sensitive info di docs + +### Opsi 2: JWT Protected (Recommended untuk Production) + +Protect `/docs` dengan JWT middleware. + +**Implementasi:** + +Update `public/index.php`: + +```php +use App\Middleware\JwtMiddleware; + +// ... + +// Docs route - dengan JWT protection +$jwtMiddleware = new JwtMiddleware(); + +$app->get('/docs', function ($request, $response) { + // ... existing code ... +})->add($jwtMiddleware); + +$app->get('/docs/openapi.json', function ($request, $response) { + // ... existing code ... +})->add($jwtMiddleware); +``` + +**Cocok untuk:** +- Production API yang sensitive +- Public API dengan authentication +- API yang perlu kontrol akses + +### Opsi 3: IP Whitelist (Paling Ketat) + +Hanya allow IP tertentu yang bisa akses docs. + +**Implementasi:** + +Buat middleware `src/Middleware/IpWhitelistMiddleware.php`: + +```php +allowedIps = $allowedIps; + } + + public function process( + ServerRequestInterface $request, + RequestHandlerInterface $handler + ): ResponseInterface { + $serverParams = $request->getServerParams(); + $clientIp = $serverParams['REMOTE_ADDR'] ?? '0.0.0.0'; + + // Check X-Forwarded-For (behind proxy) + if (isset($serverParams['HTTP_X_FORWARDED_FOR'])) { + $ips = explode(',', $serverParams['HTTP_X_FORWARDED_FOR']); + $clientIp = trim($ips[0]); + } + + if (!in_array($clientIp, $this->allowedIps, true)) { + $responseFactory = new ResponseFactory(); + $response = $responseFactory->createResponse(); + return ResponseHelper::json( + $response, + ['error' => 'forbidden', 'message' => 'Access denied'], + 403 + ); + } + + return $handler->handle($request); + } +} +``` + +Gunakan di `public/index.php`: + +```php +use App\Middleware\IpWhitelistMiddleware; +use App\Config\AppConfig; + +// Get allowed IPs from ENV +$allowedIps = explode(',', AppConfig::get('DOCS_ALLOWED_IPS', '')); +$ipWhitelist = new IpWhitelistMiddleware($allowedIps); + +$app->get('/docs', function ($request, $response) { + // ... existing code ... +})->add($ipWhitelist); +``` + +**Cocok untuk:** +- Very sensitive API +- Internal company network only +- High security requirement + +### Opsi 4: Basic Auth (Simple) + +Protect dengan HTTP Basic Authentication. + +**Implementasi:** + +Buat middleware atau gunakan nginx basic auth: + +```nginx +location /docs { + auth_basic "API Documentation"; + auth_basic_user_file /path/to/.htpasswd; + # ... rest of config +} +``` + +## 📋 Recommendations + +### Untuk API Internal (Current Setup) + +**Status**: ✅ **AMAN** jika: +- API hanya diakses dari internal network +- Semua endpoint sudah protected dengan JWT/API Key +- Tidak ada sensitive data di OpenAPI spec +- Server tidak exposed ke public internet + +**Action**: +- Pastikan tidak ada contoh API key/password di docs +- Review OpenAPI spec sebelum deploy +- Monitor access logs + +### Untuk Public API + +**Status**: ⚠️ **PERLU PROTECTION** jika: +- API exposed ke public internet +- Ada sensitive business logic +- Compliance requirement (GDPR, dll) + +**Action**: +- Implement JWT protection untuk `/docs` +- Atau IP whitelist untuk internal team +- Review dan sanitize OpenAPI spec + +## 🔐 Best Practices + +1. **Jangan hardcode credentials** di OpenAPI spec +2. **Gunakan environment variables** untuk examples +3. **Review secara berkala** endpoint yang di-expose +4. **Monitor access logs** untuk `/docs` +5. **Update docs** jika ada perubahan security + +## 🚨 Jika Perlu Protect Docs Sekarang + +Saya bisa implement JWT protection untuk `/docs` dengan cepat. Tinggal kasih tahu mau pakai opsi mana! + diff --git a/public/index.php b/public/index.php index 250e796..3d8ea9d 100644 --- a/public/index.php +++ b/public/index.php @@ -27,36 +27,38 @@ $app->get('/', function ($request, $response) { }); // Docs route - serve Swagger UI +// NOTE: Saat ini PUBLIC. Jika perlu protect, tambahkan JwtMiddleware atau IpWhitelistMiddleware $app->get('/docs', function ($request, $response) { $docsPath = __DIR__ . '/docs/index.html'; - + if (!file_exists($docsPath)) { $response->getBody()->write('