directlx-claude-config/plans/squishy-sauteeing-donut.md

76 lines
3.2 KiB
Markdown

# 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<ApiKey>` 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 `<pre>` 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