# Plan: Thymeleaf UI for Dynamic API Server ## Context The app is currently REST-only. The user wants a browser-accessible UI covering: - Generate API key - List/view all keys - Revoke a key - Test dynamic endpoints Since the app is stateless (no sessions), the UI controller will call the service layer directly (bypassing REST auth), with UI paths made public in SecurityConfiguration. --- ## Files to Create/Modify ### 1. `pom.xml` — Add dependencies - `spring-boot-starter-thymeleaf` - `bootstrap` (WebJar, 5.3.x) - `webjars-locator-lite` (auto-resolves WebJar versions in templates) ### 2. `SecurityConfiguration.java` — Add public UI paths Add `/ui/**` to the permit-all list so browser requests don't need an `X-API-Key` header. ### 3. `ApiKeyService.java` — Add `listAllKeys()` method Returns `List` via `apiKeyRepository.findAll()` (already available from JpaRepository). ### 4. `UiController.java` (new) — `com/dynamicapi/controller/UiController.java` Mapped to `/ui/**`. Injects `ApiKeyService` and `DynamicApiConfigLoader` directly. Endpoints: - `GET /ui/` → `index.html` (generate key form) - `POST /ui/generate` → calls `apiKeyService.generateApiKey()`, redirects to index with result - `GET /ui/keys` → `keys.html` (list all keys) - `POST /ui/revoke/{key}` → calls `apiKeyService.revokeApiKey()`, redirects to keys page - `GET /ui/test` → `test.html` (test endpoint form, loads endpoint list) - `POST /ui/test` → makes RestTemplate call to selected endpoint, returns result to test.html ### 5. Templates (new) — `src/main/resources/templates/` **`fragments/layout.html`** — Bootstrap 5 base layout with navbar (links: Home, API Keys, Test Endpoints) **`index.html`** — API Key generation - Form: clientName (required), description (optional) → POST `/ui/generate` - On success: shows generated key in a highlighted alert box with copy button (JS) - On error: shows validation/duplicate error message **`keys.html`** — Key management table - Table columns: Client Name, Key (masked, last 8 chars shown), Created At, Last Used, Status (Active/Revoked), Actions - Revoke button → POST `/ui/revoke/{key}` (only shown for active keys) - Flash message on successful revoke **`test.html`** — Endpoint tester - Dropdown: select from registered dynamic endpoints (path + method) - Input: API Key (required to call protected endpoints) - Submit → POST `/ui/test` → displays JSON response in `
` block

---

## Implementation Notes

- Use Bootstrap 5 via WebJar (no CDN required)
- Thymeleaf fragment includes for navbar (`th:replace`)
- Flash attributes (`RedirectAttributes`) for post-redirect-get pattern on generate/revoke
- RestTemplate in UiController for the endpoint tester (reuse existing pattern from DynamicApiController)
- The endpoint tester calls `http://localhost:8080/api/dynamic/{path}` with the user-supplied API key

---

## Verification
1. `mvn spring-boot:run` compiles and starts cleanly
2. `GET http://localhost:8080/api/ui/` — renders generate key form
3. Submit form → key displayed on page
4. `GET http://localhost:8080/api/ui/keys` — lists all keys
5. Revoke a key → table reflects revoked status
6. `GET http://localhost:8080/api/ui/test` — dropdown shows all dynamic endpoints, submit returns JSON response