Files
UTMS-NG-BE/docs/frontend-api-surface.md
2026-04-21 06:25:33 +07:00

7.8 KiB

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:

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:

{ username: string; password: string }

Success (200):

{
  "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:

{ refreshToken: string }

Success:

{
  "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:

{ "success": true, "message": "Logout successful", "data": null }

4) Profile API

GET /api/users/me

Success:

{
  "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

{ tenantId: "acme" }

6) User Management APIs (Workflow-first)

POST /api/users/management/requests/create

Local mode (default)

{
  username: string,
  password: string, // required local mode
  enabled?: boolean,
  roleCodes: string[]
}

LDAP mode

{
  username: string,
  ldapDn?: string, // optional metadata
  enabled?: boolean,
  roleCodes: string[]
}

Success always returns workflow request:

{
  "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

{ username: string; roleCodes: string[] }

Returns same response shape as approval response.

7) Role Management APIs (Workflow-first)

POST /api/roles/management/requests/create

{ code: string; name: string; permissionCodes: string[] }

POST /api/roles/management/requests/update-permissions

{ code: string; permissionCodes: string[] }

Both return ApprovalResponse with request status PENDING.

8) Workflow APIs

POST /api/workflow/request

Generic endpoint for custom workflow request:

{
  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:

{
  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

{ 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

{ notes?: string; checkerRole?: string }

Same behavior and guards as approve.

9) Module APIs (Admin only)

GET /api/modules

Returns:

{ code: string; name: string; enabled: boolean }[]

POST /api/modules/{code}/toggle

{ 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