+155
-150
@@ -1,146 +1,174 @@
|
|||||||
API Spec - Contoh REST API (Bahasa Indonesia)
|
API Spec - Identity & Authorization API (Bahasa Indonesia)
|
||||||
|
|
||||||
Ringkasan
|
Ringkasan
|
||||||
--------
|
--------
|
||||||
API ini adalah contoh RESTful API yang bisa dipakai untuk manajemen pengguna, item, dan pesanan. Menggunakan JSON untuk request/response. Autentikasi memakai Bearer Token (JWT).
|
Spesifikasi berikut disesuaikan dengan controller aktual pada aplikasi: modul Auth (OIDC + internal JWT), modul Identity (Users, Roles, Permissions) dan mekanisme otorisasi berbasis permission.
|
||||||
|
|
||||||
Base URL
|
Base URL
|
||||||
--------
|
--------
|
||||||
- https://api.example.com/v1
|
- https://api.example.com
|
||||||
|
|
||||||
Header Umum
|
Header Umum & Auth
|
||||||
-----------
|
------------------
|
||||||
- Authorization: Bearer <token> (kecuali endpoint login/register)
|
|
||||||
- Content-Type: application/json
|
- Content-Type: application/json
|
||||||
- Accept: application/json
|
- Accept: application/json
|
||||||
|
- Otentikasi dapat diberikan dalam dua cara:
|
||||||
|
1) Cookie internal (default flow):
|
||||||
|
- raylab_jwt (internal JWT, httpOnly cookie)
|
||||||
|
- raylab_refresh (internal refresh token, httpOnly cookie)
|
||||||
|
2) Authorization header: Bearer <internal_jwt>
|
||||||
|
- Banyak endpoint melindungi akses dengan JWT dan permission checks. Respons sukses dari controller umumnya dibungkus sebagai:
|
||||||
|
{ "success": true, "data": ..., "meta": { ... } }
|
||||||
|
|
||||||
Autentikasi
|
Auth (modul /auth)
|
||||||
-----------
|
-------------------
|
||||||
- POST /auth/login
|
1) GET /auth/login
|
||||||
- Body (application/json):
|
- Deskripsi: Mulai flow Authorization Code + PKCE. Redirect (302) ke Identity Provider.
|
||||||
{
|
- Query params:
|
||||||
"email": "user@example.com",
|
- returnTo (optional) - URL tujuan setelah login
|
||||||
"password": "string"
|
- Response: 302 Redirect
|
||||||
}
|
|
||||||
- Response 200:
|
|
||||||
{
|
|
||||||
"access_token": "<jwt_token>",
|
|
||||||
"token_type": "Bearer",
|
|
||||||
"expires_in": 3600
|
|
||||||
}
|
|
||||||
- Kesalahan: 400 (invalid input), 401 (invalid credentials)
|
|
||||||
|
|
||||||
- POST /auth/register
|
2) GET /auth/callback
|
||||||
- Body:
|
- Deskripsi: Endpoint callback OIDC. Menukarkan code/state, membuat internal JWT & refresh token, dan menyetel cookie httpOnly.
|
||||||
{
|
- Response: 302 Redirect ke returnTo atau '/'
|
||||||
"name": "Nama User",
|
- Cookie yang disetel:
|
||||||
"email": "user@example.com",
|
- raylab_jwt (internal JWT, maxAge sesuai expiresIn)
|
||||||
"password": "password123"
|
- raylab_refresh (refresh token)
|
||||||
}
|
|
||||||
- Response 201: user created (id, name, email)
|
3) POST /auth/logout
|
||||||
|
- Deskripsi: Invalidate internal refresh token (opsional) dan redirect ke logout identity provider.
|
||||||
|
- Body (optional): { "refreshToken": "..." }
|
||||||
|
- Response: 302 Redirect
|
||||||
|
|
||||||
|
4) POST /auth/refresh
|
||||||
|
- Deskripsi: Tukar refresh token menjadi internal JWT baru.
|
||||||
|
- Input: refresh token di cookie raylab_refresh atau di body { "refreshToken": "..." }
|
||||||
|
- Response 200: { "success": true, "data": { "accessToken": "...", "expiresIn": 3600, ... } }
|
||||||
|
|
||||||
|
5) GET /auth/me
|
||||||
|
- Deskripsi: Ambil data user saat ini dari internal JWT (cookie atau Authorization header).
|
||||||
|
- Response 200: { "success": true, "data": { /* user object */ } }
|
||||||
|
|
||||||
|
Catatan: tidak ada endpoint "/auth/register" atau POST /auth/login berbasis email/password pada controller saat ini — login terjadi via OIDC dan internal session cookies.
|
||||||
|
|
||||||
|
Users (modul /users)
|
||||||
|
--------------------
|
||||||
|
Semua endpoint Users dijalankan di bawah guards: JwtAuthGuard, CurrentUserGuard dan PermissionGuard. Respons mengikuti format { success, data, meta }.
|
||||||
|
|
||||||
Endpoint Pengguna (Users)
|
|
||||||
-------------------------
|
|
||||||
1) GET /users
|
1) GET /users
|
||||||
- Deskripsi: Mendapatkan daftar pengguna (admin)
|
- Permission: PermissionType.USER_READ
|
||||||
- Query params:
|
- Deskripsi: List pengguna (paged)
|
||||||
- page (int, optional, default=1)
|
- Query params umum: page, per_page, sort, q
|
||||||
- per_page (int, optional, default=20, max=100)
|
|
||||||
- sort (string, optional, contoh: "created_at:desc")
|
|
||||||
- q (string, optional) - pencarian nama/email
|
|
||||||
- Response 200:
|
- Response 200:
|
||||||
{
|
{ "success": true, "data": [ /* user list (toResponse) */ ], "meta": { "total": 123 } }
|
||||||
"data": [ {"id":1, "name":"...", "email":"..."} , ...],
|
|
||||||
"meta": {"page":1, "per_page":20, "total":123}
|
|
||||||
}
|
|
||||||
|
|
||||||
2) GET /users/{id}
|
2) GET /users/me
|
||||||
- Path params:
|
- Deskripsi: Ambil profil user saat ini (token harus ada di cookie atau header)
|
||||||
- id (integer, required)
|
- Response 200: { "success": true, "data": { /* current user */ }, "meta": {} }
|
||||||
- Response 200: user object
|
|
||||||
- Errors: 404 jika tidak ditemukan
|
|
||||||
|
|
||||||
3) PUT /users/{id}
|
3) GET /users/:id
|
||||||
- Path params: id
|
- Permission: PermissionType.USER_READ
|
||||||
- Body (application/json):
|
- Deskripsi: Ambil user berdasarkan id
|
||||||
{
|
- Response 200: { "success": true, "data": { /* user */ }, "meta": {} }
|
||||||
"name": "Nama Baru",
|
|
||||||
"email": "email@baru.com"
|
|
||||||
}
|
|
||||||
- Validasi: email harus format valid; name min 2 karakter
|
|
||||||
- Response 200: updated user
|
|
||||||
|
|
||||||
4) DELETE /users/{id}
|
|
||||||
- Path params: id
|
|
||||||
- Response 204: no content
|
|
||||||
- Permissions: hanya admin
|
|
||||||
|
|
||||||
Endpoint Item (Items)
|
|
||||||
---------------------
|
|
||||||
1) GET /items
|
|
||||||
- Query params:
|
|
||||||
- page, per_page, sort (lihat Users)
|
|
||||||
- category (string, optional)
|
|
||||||
- min_price, max_price (decimal, optional)
|
|
||||||
- Response: list items dengan fields id, name, description, price, stock
|
|
||||||
|
|
||||||
2) POST /items
|
|
||||||
- Body:
|
|
||||||
{
|
|
||||||
"name": "Nama Item",
|
|
||||||
"description": "Deskripsi...",
|
|
||||||
"price": 125000.50,
|
|
||||||
"stock": 10,
|
|
||||||
"category": "Elektronik"
|
|
||||||
}
|
|
||||||
- Validasi:
|
|
||||||
- name (required, max 255)
|
|
||||||
- price (required, >=0)
|
|
||||||
- stock (integer, >=0)
|
|
||||||
- Response 201: created item
|
|
||||||
- Permissions: admin atau vendor
|
|
||||||
|
|
||||||
3) GET /items/{id}
|
|
||||||
- Response 200: item object
|
|
||||||
- 404 jika tidak ditemukan
|
- 404 jika tidak ditemukan
|
||||||
|
|
||||||
4) PUT /items/{id}
|
4) PATCH /users/:id/enable
|
||||||
- Body: fields yang boleh diupdate (name, description, price, stock, category)
|
- Permission: PermissionType.USER_UPDATE
|
||||||
|
- Deskripsi: Enable user
|
||||||
|
- Response 200: { "success": true, "data": { /* updated user */ }, "meta": {} }
|
||||||
|
|
||||||
|
5) PATCH /users/:id/disable
|
||||||
|
- Permission: PermissionType.USER_UPDATE
|
||||||
|
- Deskripsi: Disable user
|
||||||
- Response 200
|
- Response 200
|
||||||
|
|
||||||
5) DELETE /items/{id}
|
6) PATCH /users/:id
|
||||||
- Response 204
|
- Permission: PermissionType.USER_UPDATE
|
||||||
|
- Deskripsi: Update profil user (body berisi fields yang diperbolehkan)
|
||||||
|
- Body contoh: { "name": "Nama Baru", "email": "baru@example.com" }
|
||||||
|
- Response 200: { "success": true, "data": { /* updated user */ }, "meta": {} }
|
||||||
|
|
||||||
Endpoint Pesanan (Orders)
|
7) DELETE /users/:id
|
||||||
-------------------------
|
- Permission: PermissionType.USER_DELETE
|
||||||
1) POST /orders
|
- Deskripsi: Soft delete user
|
||||||
- Body:
|
- Response 200: { "success": true, "data": null, "meta": {} }
|
||||||
{
|
|
||||||
"user_id": 12, // optional jika token sudah mewakili user
|
|
||||||
"items": [
|
|
||||||
{"item_id": 5, "quantity": 2},
|
|
||||||
{"item_id": 7, "quantity": 1}
|
|
||||||
],
|
|
||||||
"shipping_address": "Alamat lengkap",
|
|
||||||
"note": "Catatan opsional"
|
|
||||||
}
|
|
||||||
- Validasi: setiap item quantity >= 1 dan tersedia di stock
|
|
||||||
- Response 201:
|
|
||||||
{
|
|
||||||
"order_id": 987,
|
|
||||||
"status": "pending",
|
|
||||||
"total": 375000.00
|
|
||||||
}
|
|
||||||
|
|
||||||
2) GET /orders/{id}
|
8) POST /users/:id/restore
|
||||||
- Path param: id
|
- Permission: PermissionType.USER_UPDATE
|
||||||
- Response 200: full order detail (items, prices, shipping, status)
|
- Deskripsi: Restore user yang di-soft-delete
|
||||||
- Permissions: hanya pemilik order atau admin
|
- Response 200: { "success": true, "data": { /* restored user */ }, "meta": {} }
|
||||||
|
|
||||||
3) PATCH /orders/{id}/status
|
Roles (modul /roles)
|
||||||
- Body: {"status": "shipped"}
|
--------------------
|
||||||
- Allowed status: pending, confirmed, shipped, delivered, cancelled
|
Semua route dilindungi oleh JwtAuthGuard, CurrentUserGuard dan PermissionGuard.
|
||||||
- Permissions: hanya admin atau staff
|
|
||||||
|
1) GET /roles
|
||||||
|
- Permission: PermissionType.ROLE_READ
|
||||||
|
- Deskripsi: List roles
|
||||||
|
- Query params: page, per_page, q
|
||||||
|
- Response 200: { "success": true, "data": [ /* roles */ ], "meta": { "total": 10 } }
|
||||||
|
|
||||||
|
2) GET /roles/:id
|
||||||
|
- Permission: PermissionType.ROLE_READ
|
||||||
|
- Deskripsi: Ambil role
|
||||||
|
- Response 200
|
||||||
|
|
||||||
|
3) POST /roles
|
||||||
|
- Permission: PermissionType.ROLE_CREATE
|
||||||
|
- Deskripsi: Buat role baru
|
||||||
|
- Body contoh: { "name": "editor", "description": "..." }
|
||||||
|
- Response 200: { "success": true, "data": { /* created role */ }, "meta": {} }
|
||||||
|
|
||||||
|
4) PATCH /roles/:id
|
||||||
|
- Permission: PermissionType.ROLE_UPDATE
|
||||||
|
- Deskripsi: Update role
|
||||||
|
- Response 200
|
||||||
|
|
||||||
|
5) DELETE /roles/:id
|
||||||
|
- Permission: PermissionType.ROLE_DELETE
|
||||||
|
- Deskripsi: Hapus role
|
||||||
|
- Response 200: { "success": true, "data": null, "meta": {} }
|
||||||
|
|
||||||
|
6) POST /roles/:id/permissions
|
||||||
|
- Permission: PermissionType.ROLE_UPDATE
|
||||||
|
- Deskripsi: Assign permission ke role
|
||||||
|
- Body: { "permissionId": "..." }
|
||||||
|
- Response 200: { "success": true, "data": { /* updated role */ }, "meta": {} }
|
||||||
|
|
||||||
|
7) DELETE /roles/:id/permissions/:permissionId
|
||||||
|
- Permission: PermissionType.ROLE_UPDATE
|
||||||
|
- Deskripsi: Remove permission dari role
|
||||||
|
- Response 200
|
||||||
|
|
||||||
|
Permissions (modul /permissions)
|
||||||
|
-------------------------------
|
||||||
|
Semua route dilindungi oleh JwtAuthGuard, CurrentUserGuard dan PermissionGuard.
|
||||||
|
|
||||||
|
1) GET /permissions
|
||||||
|
- Permission: PermissionType.PERMISSION_READ
|
||||||
|
- Deskripsi: List permissions
|
||||||
|
- Response 200: { "success": true, "data": [ /* permissions */ ], "meta": { "total": 20 } }
|
||||||
|
|
||||||
|
2) GET /permissions/:id
|
||||||
|
- Permission: PermissionType.PERMISSION_READ
|
||||||
|
- Deskripsi: Ambil permission
|
||||||
|
- Response 200
|
||||||
|
|
||||||
|
3) POST /permissions
|
||||||
|
- Permission: PermissionType.PERMISSION_CREATE
|
||||||
|
- Deskripsi: Buat permission baru
|
||||||
|
- Body contoh: { "name": "user:create", "description": "..." }
|
||||||
|
- Response 200: { "success": true, "data": { /* created */ }, "meta": {} }
|
||||||
|
|
||||||
|
4) PATCH /permissions/:id
|
||||||
|
- Permission: PermissionType.PERMISSION_UPDATE
|
||||||
|
- Deskripsi: Update permission
|
||||||
|
- Response 200
|
||||||
|
|
||||||
|
5) DELETE /permissions/:id
|
||||||
|
- Permission: PermissionType.PERMISSION_DELETE
|
||||||
|
- Deskripsi: Delete permission
|
||||||
|
- Response 200: { "success": true, "data": null, "meta": {} }
|
||||||
|
|
||||||
Format Tanggal dan Numerik
|
Format Tanggal dan Numerik
|
||||||
--------------------------
|
--------------------------
|
||||||
@@ -150,12 +178,13 @@ Format Tanggal dan Numerik
|
|||||||
Pagination
|
Pagination
|
||||||
----------
|
----------
|
||||||
- Gunakan page & per_page
|
- Gunakan page & per_page
|
||||||
- Meta object harus mengandung total, page, per_page, total_pages
|
- Meta object pada controller ini biasanya minimal: { total }
|
||||||
|
|
||||||
Response Error Umum
|
Response Error Umum
|
||||||
-------------------
|
-------------------
|
||||||
- 400 Bad Request - payload tidak valid
|
- 400 Bad Request - payload tidak valid
|
||||||
{
|
{
|
||||||
|
"success": false,
|
||||||
"error": "invalid_request",
|
"error": "invalid_request",
|
||||||
"message": "Deskripsi kesalahan",
|
"message": "Deskripsi kesalahan",
|
||||||
"details": { "field": ["pesan validasi"] }
|
"details": { "field": ["pesan validasi"] }
|
||||||
@@ -166,38 +195,14 @@ Response Error Umum
|
|||||||
- 429 Too Many Requests - rate limit
|
- 429 Too Many Requests - rate limit
|
||||||
- 500 Internal Server Error
|
- 500 Internal Server Error
|
||||||
|
|
||||||
Rate Limiting
|
|
||||||
-------------
|
|
||||||
- Contoh: 1000 requests per 1 jam per API key
|
|
||||||
- Header terkait:
|
|
||||||
- X-RateLimit-Limit: 1000
|
|
||||||
- X-RateLimit-Remaining: 750
|
|
||||||
- X-RateLimit-Reset: 1650000000 (epoch seconds)
|
|
||||||
|
|
||||||
Keamanan dan Persyaratan
|
Keamanan dan Persyaratan
|
||||||
------------------------
|
------------------------
|
||||||
- Semua permintaan harus lewat HTTPS (TLS 1.2+)
|
- Semua permintaan harus lewat HTTPS (TLS 1.2+)
|
||||||
- Gunakan header Authorization: Bearer <token>
|
- Gunakan cookie httpOnly (raylab_jwt / raylab_refresh) untuk flow internal atau header Authorization: Bearer <token>
|
||||||
- CORS: domain yang diijinkan harus didaftarkan
|
|
||||||
- Validasi input di server (length, tipe, range)
|
- Validasi input di server (length, tipe, range)
|
||||||
- Sanitasi data untuk mencegah injection
|
- Sanitasi data untuk mencegah injection
|
||||||
|
|
||||||
Versioning
|
Catatan Akhir
|
||||||
----------
|
------------
|
||||||
- Versi di URL: /v1/
|
- Spesifikasi ini disesuaikan dengan controller yang ada: /auth, /users, /roles, /permissions dan mekanisme otorisasi berbasis PermissionType.
|
||||||
- Buat v2 jika ada breaking change
|
- Perhatikan bahwa detail field respons (mis. bentuk toResponse pada entitas) dapat berbeda antar resource. Untuk integrasi, gunakan endpoint /auth/me dan /users/me untuk memvalidasi data user yang tersedia.
|
||||||
|
|
||||||
Contoh Request/Response (cURL)
|
|
||||||
-----------------------------
|
|
||||||
Login:
|
|
||||||
curl -X POST "https://api.example.com/v1/auth/login" \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d '{"email":"user@example.com","password":"password123"}'
|
|
||||||
|
|
||||||
Ambil daftar item:
|
|
||||||
curl "https://api.example.com/v1/items?page=1&per_page=20" \
|
|
||||||
-H "Authorization: Bearer <token>"
|
|
||||||
|
|
||||||
Footer
|
|
||||||
------
|
|
||||||
Spesifikasi ini adalah contoh umum. Sesuaikan endpoint, nama field, aturan autentikasi, dan kebijakan rate limit sesuai kebutuhan aplikasi Anda.
|
|
||||||
Reference in New Issue
Block a user