336 lines
7.8 KiB
Markdown
336 lines
7.8 KiB
Markdown
# Frontend API Surface (Backend: Current Spring Boot)
|
|
|
|
Use this as the exact frontend integration reference for the existing backend.
|
|
|
|
## 1) API Envelope
|
|
|
|
Most responses use:
|
|
|
|
```ts
|
|
type ApiResponse<T> = {
|
|
success: boolean
|
|
message: string
|
|
data: T
|
|
timestamp: string
|
|
}
|
|
```
|
|
|
|
### Error policy (actual backend behavior)
|
|
- Business errors and validation in request payloads return HTTP `400` with:
|
|
- `{ success: false, message: "...", data: null, timestamp: "..." }`
|
|
- Authorization failures return HTTP `403`:
|
|
- `{ success: false, message: "Access denied", data: null, timestamp: "..." }`
|
|
- Unhandled internal exceptions return HTTP `500` with:
|
|
- `{ success: false, message: "Internal server error", data: null, timestamp: "..." }`
|
|
- Authentication failures from Spring Security typically return `401` and are handled by frontend interceptor.
|
|
- JWT/session validation/blacklist failures can return `401` or be handled by security filters before controller.
|
|
|
|
## 2) Global request headers
|
|
|
|
For **every protected request** after login:
|
|
- `Authorization: Bearer <accessToken>`
|
|
- `X-Tenant-Id: <tenantId>`
|
|
- Optional: `Accept-Language: en-US` or `id-ID`
|
|
|
|
`POST /api/auth/login` also requires:
|
|
- `X-Tenant-Id`
|
|
|
|
## 3) Auth APIs
|
|
|
|
### POST `/api/auth/login`
|
|
|
|
Request:
|
|
|
|
```ts
|
|
{ username: string; password: string }
|
|
```
|
|
|
|
Success (`200`):
|
|
|
|
```ts
|
|
{
|
|
"success": true,
|
|
"message": "Login successful",
|
|
"data": {
|
|
"tokenType": "Bearer",
|
|
"accessToken": "eyJhbGciOiJIUzI1NiJ9...",
|
|
"refreshToken": "...",
|
|
"expiresInSeconds": 900
|
|
}
|
|
}
|
|
```
|
|
|
|
Common login failures:
|
|
- `401`: invalid credentials from security layer
|
|
- `400`: `{ message: "Invalid username or password" }`
|
|
- `400`: `{ message: "Account locked. Please try again in {0} seconds" }`
|
|
- LDAP mode + not provisioned local tenant user: `{ message: "LDAP user authenticated but not provisioned in this tenant" }`
|
|
|
|
### POST `/api/auth/refresh`
|
|
|
|
Request:
|
|
|
|
```ts
|
|
{ refreshToken: string }
|
|
```
|
|
|
|
Success:
|
|
|
|
```ts
|
|
{
|
|
"success": true,
|
|
"message": "Token refreshed successfully",
|
|
"data": {
|
|
"tokenType": "Bearer",
|
|
"accessToken": "...",
|
|
"refreshToken": "...",
|
|
"expiresInSeconds": 900
|
|
}
|
|
}
|
|
```
|
|
|
|
Failure:
|
|
- `400` with message `Refresh token not found` / `Token expired or revoked`
|
|
|
|
### POST `/api/auth/logout`
|
|
|
|
Request headers:
|
|
- `Authorization` and `X-Tenant-Id`
|
|
- optional body
|
|
|
|
Success:
|
|
|
|
```ts
|
|
{ "success": true, "message": "Logout successful", "data": null }
|
|
```
|
|
|
|
## 4) Profile API
|
|
|
|
### GET `/api/users/me`
|
|
|
|
Success:
|
|
|
|
```ts
|
|
{
|
|
"success": true,
|
|
"message": "Current user fetched successfully",
|
|
"data": {
|
|
"tenantId": "acme",
|
|
"username": "alice",
|
|
"roles": ["ADMIN", "USER_ROLE_ADMIN"],
|
|
"permissions": ["USER_MANAGE", "WORKFLOW_APPROVE", "ROLE_MANAGE"]
|
|
}
|
|
}
|
|
```
|
|
|
|
Use `roles` and `permissions` for:
|
|
- menu visibility
|
|
- action visibility
|
|
- route guards
|
|
|
|
## 5) Tenant APIs
|
|
|
|
### GET `/api/tenant/context`
|
|
|
|
```ts
|
|
{ tenantId: "acme" }
|
|
```
|
|
|
|
## 6) User Management APIs (Workflow-first)
|
|
|
|
### POST `/api/users/management/requests/create`
|
|
|
|
#### Local mode (default)
|
|
```ts
|
|
{
|
|
username: string,
|
|
password: string, // required local mode
|
|
enabled?: boolean,
|
|
roleCodes: string[]
|
|
}
|
|
```
|
|
|
|
#### LDAP mode
|
|
```ts
|
|
{
|
|
username: string,
|
|
ldapDn?: string, // optional metadata
|
|
enabled?: boolean,
|
|
roleCodes: string[]
|
|
}
|
|
```
|
|
|
|
Success always returns workflow request:
|
|
|
|
```ts
|
|
{
|
|
"success": true,
|
|
"message": "User management request created",
|
|
"data": {
|
|
"id": "uuid",
|
|
"resourceType": "USER_MANAGEMENT",
|
|
"resourceId": "jane",
|
|
"status": "PENDING",
|
|
"requiredSteps": 1,
|
|
"currentStep": 0
|
|
}
|
|
}
|
|
```
|
|
|
|
### POST `/api/users/management/requests/update-roles`
|
|
|
|
```ts
|
|
{ username: string; roleCodes: string[] }
|
|
```
|
|
|
|
Returns same response shape as approval response.
|
|
|
|
## 7) Role Management APIs (Workflow-first)
|
|
|
|
### POST `/api/roles/management/requests/create`
|
|
|
|
```ts
|
|
{ code: string; name: string; permissionCodes: string[] }
|
|
```
|
|
|
|
### POST `/api/roles/management/requests/update-permissions`
|
|
|
|
```ts
|
|
{ code: string; permissionCodes: string[] }
|
|
```
|
|
|
|
Both return `ApprovalResponse` with request status PENDING.
|
|
|
|
## 8) Workflow APIs
|
|
|
|
### POST `/api/workflow/request`
|
|
|
|
Generic endpoint for custom workflow request:
|
|
|
|
```ts
|
|
{
|
|
resourceType: string,
|
|
resourceId: string,
|
|
payload: string,
|
|
requiredSteps: number
|
|
}
|
|
```
|
|
|
|
### GET `/api/workflow/requests`
|
|
|
|
Query params:
|
|
- `status` = `DRAFT|PENDING|APPROVED|REJECTED` (optional)
|
|
- `resourceType` (optional)
|
|
- `makerUsername` (optional)
|
|
- `limit` default `50`, max internally clamped to `200`
|
|
|
|
Response list item:
|
|
|
|
```ts
|
|
{
|
|
id: "uuid",
|
|
tenantId: "acme",
|
|
resourceType: "USER_MANAGEMENT",
|
|
resourceId: "jane",
|
|
makerUsername: "alice",
|
|
payload: "{\"operation\":\"CREATE_USER\",...}",
|
|
status: "PENDING",
|
|
requiredSteps: 1,
|
|
currentStep: 0,
|
|
createdAt: "2026-04-20T08:00:00Z",
|
|
updatedAt: "2026-04-20T08:00:00Z"
|
|
}
|
|
```
|
|
|
|
### POST `/api/workflow/{id}/approve`
|
|
|
|
```ts
|
|
{ notes?: string; checkerRole?: string }
|
|
```
|
|
|
|
- If `checkerRole` omitted, backend uses step role default (`CHECKER` unless overridden by system default).
|
|
- Maker cannot approve own request.
|
|
- Success returns updated `ApprovalResponse`.
|
|
|
|
### POST `/api/workflow/{id}/reject`
|
|
|
|
```ts
|
|
{ notes?: string; checkerRole?: string }
|
|
```
|
|
|
|
Same behavior and guards as approve.
|
|
|
|
## 9) Module APIs (Admin only)
|
|
|
|
### GET `/api/modules`
|
|
|
|
Returns:
|
|
|
|
```ts
|
|
{ code: string; name: string; enabled: boolean }[]
|
|
```
|
|
|
|
### POST `/api/modules/{code}/toggle`
|
|
|
|
```ts
|
|
{ enabled: boolean }
|
|
```
|
|
|
|
Requires admin role.
|
|
|
|
## 10) Audit APIs (Admin only)
|
|
|
|
### GET `/api/audit?limit=50`
|
|
|
|
Response items include at least:
|
|
- `id`, `tenantId`, `actor`, `correlationId`, `action`, `domain`, `resourceType`, `resourceId`, `outcome`, `httpMethod`, `requestPath`, `beforeState`, `afterState`, `details`, `createdAt`.
|
|
|
|
Used for security/auditor trail and troubleshooting.
|
|
|
|
## 11) Statuses and RBAC to gate UI
|
|
|
|
- Approval status from backend: `DRAFT`, `PENDING`, `APPROVED`, `REJECTED`.
|
|
- User create / update role actions: `USER_MANAGE` OR `USER_ROLE_ADMIN`
|
|
- Role create / update permissions: `ROLE_MANAGE` OR `USER_ROLE_ADMIN`
|
|
- Workflow approve/reject: `WORKFLOW_APPROVE` OR `CHECKER`
|
|
- Workflow list: `WORKFLOW_APPROVE` OR `CHECKER` OR `ADMIN`
|
|
- Audit & modules listing/toggle: `ADMIN`
|
|
- Profile (`/api/users/me`): `USER_READ` OR `ADMIN`
|
|
|
|
## 12) Frontend negative-path checklist (QA-ready)
|
|
|
|
1. Login without tenant header should fail on protected flows.
|
|
2. Login with valid credentials but wrong tenant should fail on tenant-dependent services.
|
|
3. Repeated wrong password:
|
|
- eventually returns lockout message after configured threshold.
|
|
4. Create user (local mode) without password -> shows localized required validation error.
|
|
5. Create user (LDAP mode) with password payload should still be accepted by UI only if intentionally sent; backend ignores and should not rely on it.
|
|
6. Create user request duplicate username returns `400 User already exists`.
|
|
7. Workflow approve/reject where maker == checker returns error message `Maker cannot approve own request`.
|
|
8. Approving/rejecting without proper role returns `403`.
|
|
9. Audit API called by non-admin should return `403`.
|
|
10. Refresh with invalid token returns `400` and clear token state.
|
|
|
|
## 13) Suggested QA smoke script
|
|
|
|
- Validate auth:
|
|
- login, refresh, me, logout
|
|
- Validate tenant:
|
|
- switch tenant header and ensure data partitions by tenant
|
|
- Validate management flow:
|
|
- create user (local/LDAP variant) -> should appear in workflow as `PENDING`
|
|
- role create -> approval created
|
|
- approve/reject -> state transition to `APPROVED/REJECTED`
|
|
- Validate guard:
|
|
- hide actions by permissions and re-check with token from restricted user
|
|
|
|
## 14) Setup checklist
|
|
|
|
- Create `.env.local`:
|
|
- `NEXT_PUBLIC_API_BASE_URL=http://localhost:9191`
|
|
- `NEXT_PUBLIC_DEFAULT_TENANT=acme`
|
|
- `NEXT_PUBLIC_LOCALE=en`
|
|
- npm install / pnpm install
|
|
- Add Axios interceptor for auth and tenant headers
|
|
- Add 401/403 interceptor handling for logout and route redirect
|