Skip to content

Latest commit

 

History

History
459 lines (346 loc) · 13.8 KB

File metadata and controls

459 lines (346 loc) · 13.8 KB

API & Swagger Testing Guide

This document covers only the REST API endpoints exposed by UBS — not the whole application internals.


Quick links

What URL
Swagger UI (try endpoints in the browser) http://localhost:8081/swagger-ui/index.html
OpenAPI JSON (import into Postman, etc.) http://localhost:8081/v3/api-docs
Health check (no auth) http://localhost:8081/actuator/health

Default port is 8081 (server.port in application.properties). Change examples if you use another port.


Before you start

  1. PostgreSQL must be running and match spring.datasource.* in application.properties (or application-local.properties).
  2. Start the app:
    mvn spring-boot:run
  3. Wait until you see something like Started JavaTApplication (main class name) in the console.
  4. Open Swagger UI in your browser.

Seeded admin account (for ADMIN endpoints)

Field Value
Name Emmanuel Uwimana
Email admin@ubs.rw
Password Admin@1234
Role ADMIN

Feature coverage

Area Status Notes
User registration Done BCrypt password; no JWT until verified
Login + JWT Done Access token (typ=access) + refresh token (typ=refresh)
RBAC Done USER, MODERATOR, MANAGER, ADMIN
Logout Done Blacklists refresh token jti in revoked_tokens
Refresh tokens Done POST /auth/refresh with refreshToken body
Email verification Done Link (GET /verify-email) + OTP (POST /otp/verify)
OTP Done 6-digit code, 10 min expiry, stored in otp_codes
Forgot / reset password Done Link + OTP; validate token via GET /reset-password
DTO validation Done @Valid on all request bodies
Global errors Done GlobalExceptionHandler → consistent ApiResponse + errors[]

Endpoint plan (recommended order)

Phase 1 — Public auth (no JWT)

# Method Path Purpose
1 POST /api/v1/auth/register Create user (PENDING until verified)
2 GET /api/v1/auth/verify-email?token= Verify via email link
3 POST /api/v1/auth/resend-verification Resend link + OTP
4 POST /api/v1/auth/otp/send Request OTP (EMAIL_VERIFICATION or PASSWORD_RESET)
5 POST /api/v1/auth/otp/verify Verify email with 6-digit OTP
6 POST /api/v1/auth/login Get accessToken + refreshToken
7 POST /api/v1/auth/refresh Exchange refresh token for new access token
8 POST /api/v1/auth/logout Blacklist refresh token (send access JWT in header)
9 POST /api/v1/auth/forgot-password Send reset link + OTP
10 GET /api/v1/auth/reset-password?token= Check if reset token is valid
11 POST /api/v1/auth/reset-password Reset with link token
12 POST /api/v1/auth/reset-password-otp Reset with OTP

Phase 2 — Protected user routes (JWT required)

Authorize in Swagger with the access token (not refresh).

# Method Path Who
13 GET /api/v1/users/me Any logged-in user
14 PATCH /api/v1/users/me Any logged-in user
15 PATCH /api/v1/users/me/password Any logged-in user
16 POST /api/v1/users ADMIN — create user
17 GET /api/v1/users ADMIN or MANAGER — list users
18 GET /api/v1/users/{id} ADMIN or MANAGER — read user
19 PATCH /api/v1/users/{id} ADMIN — update profile
20 PATCH /api/v1/users/{id}/role ADMIN — update role
21 DELETE /api/v1/users/{id} ADMIN — soft-delete
22 DELETE /api/v1/users/{id}/permanent ADMIN — hard delete
23 PATCH /api/v1/users/{id}/deactivate ADMIN
24 PATCH /api/v1/users/{id}/activate ADMIN

How to use Swagger UI

Step 1 — Login

  1. Expand AuthenticationPOST /api/v1/auth/login.
  2. Click Try it out.
  3. Request body:
    {
      "email": "admin@ubs.rw",
      "password": "Admin@1234"
    }
  4. Click Execute.
  5. In the response, find data.accessToken and copy the long string (starts with eyJ...).

Step 2 — Authorize

  1. Click the green Authorize button (top right).
  2. Under bearerAuth, paste only the accessToken value (do not type Bearer — Swagger adds it).
  3. Click Authorize, then Close.

Step 3 — Call protected endpoints

  1. Expand User Management → e.g. GET /api/v1/users/me.
  2. Try it outExecute.
  3. Expect 200 and your user in data.

Step 4 — Log out of Swagger (optional)

Click AuthorizeLogout to clear the token.


Standard response shape

Every API returns the same envelope:

{
  "success": true,
  "message": "Login successful",
  "data": { },
  "timestamp": "2026-06-04T12:00:00Z",
  "path": "/api/v1/auth/login"
}
  • successtrue or false
  • data — payload on success (tokens, user, page of users, etc.)
  • errors — list of field errors on validation failure (400)
  • On 401 / 403, success is false and message explains why

Examples — curl (PowerShell)

Set the base URL once:

$base = "http://localhost:8081"

1. Login (get token)

$loginBody = @{
  email    = "admin@ubs.rw"
  password = "Admin@1234"
} | ConvertTo-Json

$login = Invoke-RestMethod -Method POST -Uri "$base/api/v1/auth/login" `
  -ContentType "application/json" -Body $loginBody

$token = $login.data.accessToken
Write-Host "Token:" $token.Substring(0, 20) "..."

2. Get my profile (authenticated)

$headers = @{ Authorization = "Bearer $token" }

Invoke-RestMethod -Method GET -Uri "$base/api/v1/users/me" -Headers $headers

3. List all users — ADMIN (with pagination)

Invoke-RestMethod -Method GET -Uri "$base/api/v1/users?page=0&size=10&sortBy=createdAt&sortDir=desc" `
  -Headers $headers

4. Get user by ID

Invoke-RestMethod -Method GET -Uri "$base/api/v1/users/1" -Headers $headers

5. Register a new user

$registerBody = @{
  firstName = "Marie Claire"
  lastName  = "Ingabire"
  username  = "mclaire01"
  email     = "marie.ingabire@example.rw"
  password  = "Secret@123"
} | ConvertTo-Json

Invoke-RestMethod -Method POST -Uri "$base/api/v1/auth/register" `
  -ContentType "application/json" -Body $registerBody

New users are PENDING until email is verified. Login returns 403 until you call verify-email.

6. Verify email (query param)

# Replace YOUR_TOKEN with the token from the verification email or database
Invoke-RestMethod -Method GET -Uri "$base/api/v1/auth/verify-email?token=YOUR_TOKEN"

7. Resend verification

$body = @{ email = "marie.ingabire@example.rw" } | ConvertTo-Json
Invoke-RestMethod -Method POST -Uri "$base/api/v1/auth/resend-verification" `
  -ContentType "application/json" -Body $body

8. Forgot password

$body = @{ email = "admin@ubs.rw" } | ConvertTo-Json
Invoke-RestMethod -Method POST -Uri "$base/api/v1/auth/forgot-password" `
  -ContentType "application/json" -Body $body

9. Refresh access token

$body = @{ refreshToken = $login.data.refreshToken } | ConvertTo-Json
$refreshed = Invoke-RestMethod -Method POST -Uri "$base/api/v1/auth/refresh" `
  -ContentType "application/json" -Body $body
$token = $refreshed.data.accessToken

10. Logout (blacklist refresh token)

$body = @{ refreshToken = $login.data.refreshToken } | ConvertTo-Json
Invoke-RestMethod -Method POST -Uri "$base/api/v1/auth/logout" `
  -Headers @{ Authorization = "Bearer $token" } `
  -ContentType "application/json" -Body $body

11. Send / verify OTP

# Send OTP for email verification
$body = @{ email = "marie.ingabire@example.rw"; purpose = "EMAIL_VERIFICATION" } | ConvertTo-Json
Invoke-RestMethod -Method POST -Uri "$base/api/v1/auth/otp/send" `
  -ContentType "application/json" -Body $body

# Verify (code from email or otp_codes table in dev)
$body = @{
  email   = "marie.ingabire@example.rw"
  code    = "123456"
  purpose = "EMAIL_VERIFICATION"
} | ConvertTo-Json
Invoke-RestMethod -Method POST -Uri "$base/api/v1/auth/otp/verify" `
  -ContentType "application/json" -Body $body

12. Validate reset token (before showing reset form)

Invoke-RestMethod -Method GET -Uri "$base/api/v1/auth/reset-password?token=TOKEN_FROM_EMAIL"

13. Reset password (link or OTP)

# Via link token
$body = @{
  token       = "TOKEN_FROM_EMAIL"
  newPassword = "NewSecret@456"
} | ConvertTo-Json
Invoke-RestMethod -Method POST -Uri "$base/api/v1/auth/reset-password" `
  -ContentType "application/json" -Body $body

# Via OTP
$body = @{
  email       = "marie.ingabire@example.rw"
  code        = "123456"
  newPassword = "NewSecret@456"
} | ConvertTo-Json
Invoke-RestMethod -Method POST -Uri "$base/api/v1/auth/reset-password-otp" `
  -ContentType "application/json" -Body $body

14. Validation error example (expect 400)

$body = @{ firstName = "OnlyName" } | ConvertTo-Json
try {
  Invoke-RestMethod -Method POST -Uri "$base/api/v1/auth/register" `
    -ContentType "application/json" -Body $body
} catch {
  $_.ErrorDetails.Message  # JSON with success=false and errors[]
}

15. Update my profile

$body = @{ firstName = "Claudine" } | ConvertTo-Json
Invoke-RestMethod -Method PATCH -Uri "$base/api/v1/users/me" `
  -Headers $headers -ContentType "application/json" -Body $body

16. Change my password

$body = @{
  currentPassword = "Admin@1234"
  newPassword     = "Admin@1234"
} | ConvertTo-Json

Invoke-RestMethod -Method PATCH -Uri "$base/api/v1/users/me/password" `
  -Headers $headers -ContentType "application/json" -Body $body

17. Create user (ADMIN)

$body = @{
  firstName = "Jean Paul"
  lastName  = "Mizero"
  username  = "jmizero"
  email     = "jean.mizero@example.rw"
  password  = "Secret@123"
  role      = "USER"
} | ConvertTo-Json

Invoke-RestMethod -Method POST -Uri "$base/api/v1/users" `
  -Headers $headers -ContentType "application/json" -Body $body

18. Delete user (ADMIN)

Invoke-RestMethod -Method DELETE -Uri "$base/api/v1/users/2" -Headers $headers

19. Change another user's role (ADMIN)

$body = @{ role = "MODERATOR" } | ConvertTo-Json
Invoke-RestMethod -Method PATCH -Uri "$base/api/v1/users/2/role" `
  -Headers $headers -ContentType "application/json" -Body $body

20. Deactivate / activate user (ADMIN)

Invoke-RestMethod -Method PATCH -Uri "$base/api/v1/users/2/deactivate" -Headers $headers
Invoke-RestMethod -Method PATCH -Uri "$base/api/v1/users/2/activate" -Headers $headers

Examples — curl (bash / Git Bash)

BASE=http://localhost:8081

# Login
TOKEN=$(curl -s -X POST "$BASE/api/v1/auth/login" \
  -H "Content-Type: application/json" \
  -d '{"email":"admin@ubs.rw","password":"Admin@1234"}' \
  | jq -r '.data.accessToken')

# My profile
curl -s "$BASE/api/v1/users/me" -H "Authorization: Bearer $TOKEN" | jq

# List users (admin)
curl -s "$BASE/api/v1/users?page=0&size=5" -H "Authorization: Bearer $TOKEN" | jq

Expected status codes (cheat sheet)

Code Meaning Typical cause
200 OK Success
201 Created Register
400 Bad request Validation errors
401 Unauthorized Missing/invalid JWT or wrong login
403 Forbidden Wrong role or email not verified
404 Not found User id does not exist
409 Conflict Duplicate email/username on register

Automated test scripts

From the project root (app must already be running on port 8081):

# Quick smoke test (login + main routes)
.\scripts\test-api.ps1

# Full suite: register, verify, OTP, refresh, logout, reset, validation, CRUD (25 steps)
.\scripts\test-all-endpoints.ps1

The full script reads verification/OTP tokens from PostgreSQL when email is not configured — requires psql on your PATH and DB at 127.0.0.1:5435.


Verification checklist

Use this when you finish a testing session:

  • App starts without errors (Flyway migrations OK)
  • Swagger UI loads at /swagger-ui/index.html
  • POST /auth/register does not return JWT until verified
  • GET /auth/verify-email or POST /auth/otp/verify activates account
  • POST /auth/login returns accessToken and refreshToken
  • POST /auth/refresh returns new access token
  • POST /auth/logout invalidates refresh token
  • Invalid register body returns 400 with errors[]
  • After Authorize, GET /users/me returns 200
  • GET /users as admin returns paginated list
  • Without token, GET /users/me returns 401

Troubleshooting

Problem What to try
Connection refused Is the app running? Is the port 8081?
Flyway / DB errors Check PostgreSQL is up; URL/username/password in properties
401 on /users/me Login again; use access token in Authorize (not refresh)
403 on login Email not verified — verify first or use admin@ubs.rw
403 on /users Need ADMIN or MANAGER role for list/read
Refresh fails after logout Expected — refresh token was blacklisted
Swagger 404 Use /swagger-ui/index.html not only /swagger-ui.html

Related files in the repo

File Role
src/main/java/.../config/SwaggerConfig.java OpenAPI title, JWT scheme, testing hints
src/main/java/.../auth/AuthController.java Auth endpoints + Swagger descriptions
src/main/java/.../user/UserController.java User endpoints + Swagger descriptions
src/main/resources/application.properties Port, public paths, SpringDoc settings