|
15 | 15 |
|
16 | 16 | | Method | Path | Description | Notes | |
17 | 17 | | --- | --- | --- | --- | |
18 | | -| POST | /api/login | Username/password check against `users` table. | Uses BCrypt hashes; returns `{ token: "dev-token", username, image }`. No JWT enforcement yet (`SecurityConfig` permits all requests).| |
19 | | -| GET | /api/profile | Fetch minimal profile for a username. | Query param `username`; response `{ username, image }`.| |
20 | | -| POST | /api/profile/image | Update stored base64 avatar. | Body `{ username, image }`; blank image clears it.| |
21 | | -| POST | /api/profile/password | Change password after verifying `currentPassword`. | Requires `username`, `currentPassword`, `newPassword`.| |
| 18 | +| POST | /api/login | Username/password check against `users` table. | Uses BCrypt hashes; returns `{ token: "<jwt>", username, image }`. The token is a signed JWT; the frontend should store it (e.g. localStorage) and send it as `Authorization: Bearer <jwt>` on subsequent requests. The login endpoint remains public; other endpoints enforce JWT-based auth via `SecurityConfig`. | |
| 19 | +| GET | /api/profile | Fetch minimal profile for the authenticated user. | Auth required: `Authorization: Bearer <jwt>`. The server reads the username from the JWT subject and ignores any `username` query param. Response `{ username, image }`. | |
| 20 | +| POST | /api/profile/image | Update stored base64 avatar. | Auth required. Request body `{ image }` (username is inferred from JWT); blank image clears it. | |
| 21 | +| POST | /api/profile/password | Change password after verifying `currentPassword`. | Auth required. Server uses username from JWT; body must include `currentPassword` and `newPassword`. | |
22 | 22 |
|
23 | 23 | ### Transformers |
24 | 24 |
|
25 | 25 | | Method | Path | Description | Notes | |
26 | 26 | | --- | --- | --- | --- | |
27 | 27 | | GET | /api/transformers | List transformers. | Query `tf` (exact transformerNumber) and `fav=true` filter; summary proxy drops image blobs for faster list rendering| |
28 | 28 | | GET | /api/transformers/{id} | Fetch a single transformer. | Returns full entity including base64 baseline images.| |
29 | | -| POST | /api/transformers | Create transformer metadata and optional baselines. | Request body mirrors `Transformer` fields; frontend stamps uploader metadata when sending| |
30 | | -| PUT | /api/transformers/{id} | Update transformer. | Replaces entity by ID; caller should preserve existing IDs when overwriting.| |
31 | | -| DELETE | /api/transformers/{id} | Remove transformer and cascade inspections. | Responds `{ ok: true }` on success.| |
32 | | -| POST | /api/transformers/{id}/baseline | Upload baseline thermal image. | `multipart/form-data` with parts `file` (image) and `weather` (`sunny\|cloudy\|rainy`). Optional `x-username` header annotates uploader.| |
| 29 | +| POST | /api/transformers | Create transformer metadata and optional baselines. | Auth required for mutations: `Authorization: Bearer <jwt>`. Request body mirrors `Transformer` fields; the server records `createdBy` from the JWT subject. | |
| 30 | +| PUT | /api/transformers/{id} | Update transformer. | Auth required. Replaces entity by ID; caller should preserve existing IDs when overwriting; `modifiedBy` is set from JWT. | |
| 31 | +| DELETE | /api/transformers/{id} | Remove transformer and cascade inspections. | Auth required. Responds `{ ok: true }` on success; action is attributed to the JWT user. | |
| 32 | +| POST | /api/transformers/{id}/baseline | Upload baseline thermal image. | Auth required. `multipart/form-data` with parts `file` (image) and `weather` (`sunny\|cloudy\|rainy`). The uploader is taken from the JWT; the `x-username` header is deprecated and ignored by the server. | |
33 | 33 |
|
34 | 34 | ### Inspections & Analysis |
35 | 35 |
|
|
38 | 38 | | GET | /api/inspections | List inspections. | Optional `fav=true`; frontend uses `summary=1` query on proxy to strip heavy fields.| |
39 | 39 | | GET | /api/inspections/{id} | Fetch full inspection. | Includes transformer reference and latest analysis blobs.| |
40 | 40 | | GET | /api/inspections/{id}/export | Generate analysis export ZIP. | Packages `metadata.json`, `history.csv`, candidate/baseline images, and plotting script.| |
41 | | -| POST | /api/inspections | Create inspection linked to transformer. | Body must include `transformer` with `id` or `transformerNumber`.| |
42 | | -| PUT | /api/inspections/{id} | Update inspection metadata. | Validates transformer reference same as create.| |
43 | | -| DELETE | /api/inspections/{id} | Delete inspection. | Returns `{ ok: true }`.| |
44 | | -| POST | /api/inspections/{id}/upload | Store latest inspection image. | `multipart/form-data` (`file`, `weather`); optional `x-username` recorded.| |
45 | | -| POST | /api/inspections/{id}/analyze | Run AI comparison using uploaded candidate file. | `multipart/form-data` with `file` and `weather`; archives previous AI results before persisting new bounding boxes and per-box metadata.| |
46 | | -| POST | /api/inspections/{id}/clear-analysis | Remove stored analysis artifacts. | Clears image, boxes, fault metadata, history snapshots.| |
47 | | -| POST | /api/inspections/{id}/boxes | Append a user-drawn bounding box. | JSON body `{ x,y,w,h,faultType,comment }`; optional `x-username` marks author; response echoes arrays plus updated `recentStatus`.| |
48 | | -| DELETE | /api/inspections/{id}/boxes/{index} | Delete a box by array index. | Archives prior state, realigns aligned arrays, responds with updated payload.| |
49 | | -| DELETE | /api/inspections/{id}/boxes | Delete a box by coordinates. | Query params `x,y,w,h`; tolerant to ±0.5 pixel for float rounding.| |
50 | | -| PUT | /api/inspections/{id}/boxes/bulk | Replace boxes/faults/comments en masse. | Body arrays `boundingBoxes`, `faultTypes`, `annotatedBy`, `comments`, optional `tuneModel` (default `true`); archives previous snapshot and optionally triggers tuning.| |
51 | | -| POST | /api/inspections/model/reset | Reset AI tunable parameters. | Restores defaults via `AiParameterService` and returns `{ ok, parameters, resetBy }`.| |
| 41 | +| POST | /api/inspections | Create inspection linked to transformer. | Auth required. Body must include `transformer` with `id` or `transformerNumber`. The created record is attributed to the JWT user. | |
| 42 | +| PUT | /api/inspections/{id} | Update inspection metadata. | Auth required. Validates transformer reference same as create; action attributed to JWT user. | |
| 43 | +| DELETE | /api/inspections/{id} | Delete inspection. | Auth required. Returns `{ ok: true }` and records the deleter from JWT. | |
| 44 | +| POST | /api/inspections/{id}/upload | Store latest inspection image. | Auth required. `multipart/form-data` (`file`, `weather`); uploader is taken from JWT; `x-username` header is deprecated and ignored. | |
| 45 | +| POST | /api/inspections/{id}/analyze | Run AI comparison using uploaded candidate file. | Auth required. `multipart/form-data` with `file` and `weather`; archives previous AI results before persisting new bounding boxes and per-box metadata. Analysis runs use parameters cached/persisted server-side. | |
| 46 | +| POST | /api/inspections/{id}/clear-analysis | Remove stored analysis artifacts. | Auth required. Clears image, boxes, fault metadata, history snapshots. | |
| 47 | +| POST | /api/inspections/{id}/boxes | Append a user-drawn bounding box. | Auth required. JSON body `{ x,y,w,h,faultType,comment }`; author is taken from JWT (the `x-username` header is ignored). Response echoes arrays plus updated `recentStatus`. | |
| 48 | +| DELETE | /api/inspections/{id}/boxes/{index} | Delete a box by array index. | Auth required. Archives prior state, realigns aligned arrays, responds with updated payload. | |
| 49 | +| DELETE | /api/inspections/{id}/boxes | Delete a box by coordinates. | Auth required. Query params `x,y,w,h`; tolerant to ±0.5 pixel for float rounding. | |
| 50 | +| PUT | /api/inspections/{id}/boxes/bulk | Replace boxes/faults/comments en masse. | Auth required. Body arrays `boundingBoxes`, `faultTypes`, `annotatedBy`, `comments`, optional `tuneModel` (default `true`); archives previous snapshot and optionally triggers tuning. `annotatedBy` values will be validated/normalized against the JWT user when present. | |
| 51 | +| POST | /api/inspections/model/reset | Reset AI tunable parameters. | Auth required. Typically restricted to admin users (checked via roles/claims in the JWT). Restores defaults via `AiParameterService` and returns `{ ok, parameters, resetBy }`. | |
52 | 52 |
|
53 | 53 | ### Model Parameter Storage |
54 | 54 |
|
55 | 55 | | Method | Path | Description | Notes | |
56 | 56 | | --- | --- | --- | --- | |
57 | 57 | | GET | *(not exposed)* | Parameters are read server-side only. | `AiParameterService` caches values and supplies them to the analyzer/tuner.| |
58 | 58 |
|
| 59 | +## Spring Boot architecture (backend) |
| 60 | + |
| 61 | +- Layered structure: the backend follows a conventional Spring Boot layering pattern to keep concerns separated: |
| 62 | + - Controller: HTTP entrypoints that validate requests, map inputs to domain types, and return HTTP responses (`@RestController`). Controllers should remain thin — orchestrating service calls and shaping the ResponseEntity. Example: `InspectionController` handles upload, analyze, export and box mutation endpoints. |
| 63 | + - Service: Application/business logic and orchestration (`@Service`). Services perform image/file IO, call downstream tools (the Python analyzer), transform domain data, and coordinate transactions. Example: `PythonAnalyzerService` wraps the external Python process; `ParameterTuningService` and `AiParameterService` encapsulate tuning and parameter persistence logic. |
| 64 | + - Repository: Persistence layer (`@Repository` or Spring Data `JpaRepository` interfaces). These are simple, CRUD-focused interfaces. Example: `InspectionRepo`, `TransformerRepo` live under `...repo` and map entities to database rows. |
| 65 | + - Model/Entity: Domain objects (`@Entity`, DTOs) that represent the database schema and API payloads. Look in `backend/src/main/java/com/apexgrid/transformertracker/model/` for inspection/transformer classes and their JSON fields. |
| 66 | + - Configuration/Resources: `application.properties` / `application.yml` and resource files (export helpers under `src/main/resources/export`) centralize runtime settings and assets. |
| 67 | + |
| 68 | +- Wiring and DI: The app uses constructor injection (preferred) to provide dependencies. Beans are discovered via `@Service`, `@Repository`, `@Component`, and controllers via `@RestController`. This makes unit testing straightforward (mock services/repos and call controllers directly). |
| 69 | + |
| 70 | +- Property binding and environment wiring: |
| 71 | + - Simple properties are injected with `@Value("${...}")` (see `PythonAnalyzerService` where `app.ai.python` and `app.ai.script` are injected). These properties may be set in `application.yml`, `application.properties`, or via environment variables using Spring Boot relaxed binding (e.g. `APP_AI_PYTHON`, `APP_AI_SCRIPT`). The Dockerfile demonstrates producing environment variables mapped to Spring properties. |
| 72 | + |
| 73 | +- Error handling & responses: Controllers use `ResponseEntity` to control HTTP status and payloads. Services throw exceptions for unexpected states; controllers catch or translate them into friendly client responses (see `InspectionController.analyze` for strategic try/catch and mapping to 400/500 responses). |
| 74 | + |
| 75 | +- Where code lives in this repo (quick map): |
| 76 | + - Controllers: `backend/src/main/java/com/apexgrid/transformertracker/web/` (e.g. `InspectionController.java`). |
| 77 | + - Services: `backend/src/main/java/com/apexgrid/transformertracker/ai/` (e.g. `PythonAnalyzerService.java`, `ParameterTuningService.java`, `AiParameterService.java`). |
| 78 | + - Repositories: `backend/src/main/java/com/apexgrid/transformertracker/repo/` (`InspectionRepo`, `TransformerRepo`). |
| 79 | + - Models/Entities: `backend/src/main/java/com/apexgrid/transformertracker/model/`. |
| 80 | + - Resources: `backend/src/main/resources/` (properties, export helpers). |
| 81 | + |
| 82 | +- Best practices used / recommendations: |
| 83 | + - Keep controllers thin: validate inputs, call services, return DTOs or ResponseEntity. |
| 84 | + - Business rules belong in services so they are testable without HTTP plumbing. |
| 85 | + - Repositories expose only persistence operations; complex queries can be placed in repository implementations or service-level methods that combine repo calls. |
| 86 | + - External process calls (like the Python analyzer) are wrapped in a service (`PythonAnalyzerService`) so the rest of the app doesn't rely on ProcessBuilder details; this wrapper also centralizes retries, timeouts, and parameter handling if you add them later. |
| 87 | + |
59 | 88 | ## AI Analysis Pipeline (`backend/AI/analyze.py`) |
60 | 89 |
|
61 | 90 | - Inputs: baseline image (PNG) and candidate inspection image (PNG). Optional JSON config supplies parameter overrides; defaults pulled from `DEFAULT_PARAMS`. |
|
0 commit comments