Files
missions/_docs/02_document/diagrams/flows/flow_vehicle_crud.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

3.8 KiB

Flow F1 — Vehicle CRUD

Post-rename / post-B7. Today: [Route("aircrafts")], Aircraft* files. See 02_mission_planning is unaffected by route prefix.

Description

Operator manages the inventory of Vehicle rows. Six endpoints: POST, PUT, DELETE, GET-list (unpaginated by spec), GET-by-id, PATCH /default. Every endpoint is gated by [Authorize(Policy = "FL")]. The "exactly one default vehicle" exclusivity rule is stricter than spec — the code clears IsDefault on every other row before setting it on the target. See 01_vehicle_catalog Caveats #1, tracked under Jira AZ-551 (B12).

Preconditions

  • Service is running and schema is in place (Flow F6 has completed).
  • Caller holds a JWT with permissions=FL (Flow F5 succeeds).

Sequence Diagram (POST /vehicles with IsDefault: true)

sequenceDiagram
    autonumber
    participant UI as Operator UI
    participant Pipeline as ASP.NET Pipeline
    participant Identity as 05_identity
    participant Errs as 06_http_conventions
    participant Ctrl as VehiclesController
    participant Svc as VehicleService
    participant DB as 04_persistence (postgres-local)

    UI->>Pipeline: POST /vehicles + Bearer JWT + body
    Pipeline->>Errs: enter middleware (catches exceptions)
    Errs->>Identity: validate JWT + policy "FL"
    alt JWT or policy fails
        Identity-->>UI: 401 / 403
    else authorized
        Identity-->>Ctrl: ClaimsPrincipal attached
        Ctrl->>Svc: CreateVehicle(req)
        opt req.IsDefault == true
            Svc->>DB: UPDATE vehicles SET is_default=FALSE WHERE is_default=TRUE
            note right of Svc: Stricter than spec. Race-prone (no transaction). B12.
        end
        Svc->>DB: INSERT INTO vehicles VALUES (...)
        DB-->>Svc: row id
        Svc-->>Ctrl: Vehicle entity
        Ctrl-->>Errs: 201 Created + Vehicle (PascalCase JSON)
        Errs-->>UI: 201 Created
    end

Flowchart (DELETE /vehicles/{id})

flowchart TD
    Start([DELETE /vehicles/id]) --> Auth{JWT + FL valid?}
    Auth -->|no| Reject([401 / 403])
    Auth -->|yes| Lookup[SELECT 1 FROM vehicles WHERE id=?]
    Lookup --> Exists{Found?}
    Exists -->|no| NotFound([KeyNotFoundException → 404])
    Exists -->|yes| Refs[SELECT 1 FROM missions WHERE vehicle_id=?]
    Refs --> InUse{Any mission references it?}
    InUse -->|yes| Conflict([InvalidOperationException → 409])
    InUse -->|no| Del[DELETE FROM vehicles WHERE id=?]
    Del --> Done([204 No Content])

Data Flow

Step From To Data Format
1 UI VehiclesController CreateVehicleRequest / UpdateVehicleRequest / SetDefaultRequest / query string JSON (PascalCase)
2 VehicleService vehicles table INSERT / UPDATE / DELETE SQL
3 vehicles table VehicleService row(s) LinqToDB entity mapping
4 VehicleService UI Vehicle entity JSON (PascalCase) — entity returned directly, no DTO mapping

Error Scenarios

Error Where Detection Recovery
Missing / invalid JWT Pipeline JwtBearerHandler 401; client refreshes token
Missing "FL" claim Policy evaluator Claim lookup 403
Vehicle not found Service entity lookup null result KeyNotFoundException404
Delete-with-references VehicleService.DeleteVehicle IsAny<Mission> true InvalidOperationException409
Concurrent default-set VehicleService.{Create,Update}Vehicle / SetDefault none (no transaction) Race window: 2+ defaults OR zero defaults. B12

Performance Expectations

Metric Target Notes
End-to-end latency (CRUD) <10ms typical Single round-trip against local PostgreSQL
Throughput Operator-paced Not load-tested; catalog is small in practice (tens to low hundreds of rows)