Files
missions/_docs/02_document/modules/controller_missions.md
T
Oleksandr Bezdieniezhnykh 7025f4d075 refactor: enhance JWT authentication and CORS configuration
Updated JWT authentication to use configuration values instead of hardcoded secrets, improving security and flexibility. Enhanced CORS policy to conditionally allow origins based on configuration settings, with logging for permissive defaults. Updated README to reflect project renaming and clarify service context.
2026-05-14 19:48:25 +03:00

72 lines
4.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Module: `Azaion.Missions.Controllers.MissionsController`
**File**: `Controllers/MissionsController.cs`
> **NOTE (forward-looking)**: post-rename + post-route-change. Today's source is `Controllers/FlightsController.cs` mounted at `[Route("flights")]` with nested waypoint routes under `/flights/{id}/waypoints/...`. Renames + route changes tracked under Jira AZ-EPIC children B6 + B8.
## Purpose
REST surface for the `missions` resource AND its nested `waypoints` sub-resource. Wraps `MissionService` for the parent and `WaypointService` for the nested routes.
## Public Interface
### Missions
| HTTP | Route | Action | Body / Query | Returns |
|------|-------|--------|--------------|---------|
| `POST` | `/missions` | `Create` | `CreateMissionRequest` | `201` + `Location: /missions/{id}`, body: `Mission` |
| `PUT` | `/missions/{id:guid}` | `Update` | `UpdateMissionRequest` | `200`, body: `Mission` |
| `GET` | `/missions/{id:guid}` | `Get` | -- | `200`, body: `Mission` |
| `GET` | `/missions` | `GetAll` | `GetMissionsQuery` (`Name?`, `FromDate?`, `ToDate?`, `Page=1`, `PageSize=20`) | `200`, body: `PaginatedResponse<Mission>` |
| `DELETE` | `/missions/{id:guid}` | `Delete` | -- | `204` |
### Waypoints (nested under a mission)
| HTTP | Route | Action | Body | Returns |
|------|-------|--------|------|---------|
| `POST` | `/missions/{id:guid}/waypoints` | `CreateWaypoint` | `CreateWaypointRequest` | `201` + `Location: /missions/{id}/waypoints/{wpId}`, body: `Waypoint` |
| `PUT` | `/missions/{id:guid}/waypoints/{waypointId:guid}` | `UpdateWaypoint` | `UpdateWaypointRequest` | `200`, body: `Waypoint` |
| `DELETE` | `/missions/{id:guid}/waypoints/{waypointId:guid}` | `DeleteWaypoint` | -- | `204` |
| `GET` | `/missions/{id:guid}/waypoints` | `GetWaypoints` | -- | `200`, body: `List<Waypoint>` (no pagination) |
Class-level decorators: `[ApiController]`, `[Route("missions")]`, `[Authorize(Policy = "FL")]`.
## Internal Logic
Same pattern as `VehiclesController`: each action awaits the appropriate service method and wraps in `Created` / `Ok` / `NoContent`.
## Dependencies
- `MissionService`, `WaypointService` (constructor-injected; primary constructor)
- `Azaion.Missions.DTOs`
## Consumers
- HTTP clients.
- Cross-service callers in the suite: `autopilot` reads `GET /missions/{id}` + `GET /missions/{id}/waypoints` to drive UAV behavior; `ui` paginates `/missions`. Both will need to be updated to the new prefix as part of B11 (consumer updates).
## Data Models
Returns `Mission` (which has `Vehicle?` + `List<Waypoint>` association properties) and `Waypoint` (with `Mission?` association property) directly. Whether associations are populated on the wire depends on LinqToDB query behavior -- by default, `FirstOrDefaultAsync(predicate)` does NOT eager-load associations, so `mission.Vehicle` and `mission.Waypoints` will serialize as `null`/empty in JSON. Verify in Step 4 against actual API responses if available.
## Configuration / External Integrations
None directly.
## Security
- All routes behind `[Authorize(Policy = "FL")]`.
- Composite-key handling in waypoint operations means a stolen waypoint id alone is not enough -- the attacker must also know the parent mission id.
## Tests
None present.
## Notes / Smells
1. **Inconsistent listing pagination** -- `GET /missions` paginates, `GET /missions/{id}/waypoints` and `GET /vehicles` do not. Verification flag.
2. **Nested resource modeling** -- waypoints are exposed only as a sub-resource of a mission, never as `/waypoints/{id}`. Consistent with the data model (`mission_id` is `NOT NULL`).
3. **`Update` of a mission allows changing `vehicle_id`** but the controller doesn't reflect any business constraint (e.g., immutable after start). All such constraints would need to live in the service.
4. **No bulk endpoints** -- no batch create / batch delete for waypoints despite the natural use case ("upload a route plan").
5. **Entity body PascalCase wire shape** -- the whole API has no `JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase`, so `Mission`, `Waypoint`, and `PaginatedResponse<Mission>` responses serialize PascalCase property names. Spec says camelCase (per `../../suite/_docs/00_top_level_architecture.md`). Note: the global error envelope produced by `ErrorHandlingMiddleware` is already camelCase (anonymous object literal) -- this divergence applies only to entity / DTO bodies (see `middleware.md` Notes #1#2 for the distinction). Carry to verification log.