mirror of
https://github.com/azaion/missions.git
synced 2026-06-21 10:31:07 +00:00
7025f4d075
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.
4.3 KiB
4.3 KiB
Module: Azaion.Missions.Services.WaypointService
File: Services/WaypointService.cs
NOTE (forward-looking): post-rename + post-GPS-Denied-removal. Today's source still uses
Flight/flightIdand the cascade reaches intogps_corrections. Renames tracked under Jira AZ-EPIC child B6; cascade shrink under B7.
Purpose
CRUD over waypoints (sub-aggregate of Mission) plus a manual cascade-delete chain that walks waypoint -> media -> annotations -> detection. All operations are scoped by missionId -- no cross-mission waypoint addressing.
Public Interface
public class WaypointService(AppDataConnection db) {
Task<Waypoint> CreateWaypoint(Guid missionId, CreateWaypointRequest request);
Task<Waypoint> UpdateWaypoint(Guid missionId, Guid waypointId, UpdateWaypointRequest request);
Task<List<Waypoint>> GetWaypoints(Guid missionId);
Task DeleteWaypoint(Guid missionId, Guid waypointId);
}
Internal Logic
CreateWaypoint
- Existence check:
db.Missions.AnyAsync(m => m.Id == missionId)->KeyNotFoundException("Mission not found") on miss -> 404. - Build a fresh
Waypoint:Id = Guid.NewGuid(),MissionId = missionId.Lat,Lon,Mgrsfromrequest.GeoPoint?(all three null-passthrough; ifGeoPointis null, all three are null).WaypointSource,WaypointObjectivecopied as-is.OrderNum,Heightcopied as-is.
db.InsertAsync(waypoint).
UpdateWaypoint
- Load by composite predicate
w.MissionId == missionId && w.Id == waypointId-> 404 on miss (so updates with the wrongmissionIdget 404, not 403). - Full overwrite -- every field is set unconditionally from the request, including
null-passthrough onLat/Lon/Mgrs. There is no partial-update semantic here, unlikeUpdateVehicleRequest. db.UpdateAsync(waypoint).
GetWaypoints
db.Waypoints.Where(w.MissionId == missionId).OrderBy(w.OrderNum).ToListAsync()-- no pagination.
DeleteWaypoint -- manual cascade
- Load by composite (404 on miss).
mediaIds = SELECT id FROM media WHERE waypoint_id = waypointId.- If any media exist:
annotationIds = SELECT id FROM annotations WHERE media_id IN (mediaIds).- If any annotations exist:
DELETE FROM detection WHERE annotation_id IN (annotationIds). DELETE FROM annotations WHERE media_id IN (mediaIds).
DELETE FROM media WHERE waypoint_id = waypointId.DELETE FROM waypoints WHERE id = waypointId.
Removed from cascade in B7: gps_corrections WHERE waypoint_id = waypointId. Schema gone after B9.
No transaction wraps the cascade either.
Dependencies
AppDataConnection, entitiesWaypoint,Mission(existence check), and 3 dependent entities used in the cascade.DTOs.GeoPoint,DTOs.CreateWaypointRequest,DTOs.UpdateWaypointRequest.Azaion.Missions.Enums(WaypointSource,WaypointObjective-- typed properties).
Consumers
Controllers.MissionsController-- exposed undermissions/{id}/waypoints/*routes.
Data Models
Reads missions (existence). Writes waypoints. Cascade also writes media, annotations, detection.
Configuration / External Integrations
None.
Security
- Behind
[Authorize(Policy = "FL")]via the controller. - Composite-key load (
MissionId AND Id) means a user cannot operate on a waypoint by guessing only its id -- they must also know the mission id (defense in depth, though both are GUIDs).
Tests
None present.
Notes / Smells
UpdateWaypointdoes a full overwrite even thoughUpdateWaypointRequestis "partial-shaped". Any client sending{}would silently zero outLat/Lon/Mgrs/OrderNum/Heightand reset enums to0. Client contract is fragile.waypoint_idnot found vs.mission_id/waypoint_idmismatch both return 404 with the same message -- slight UX issue (you can't tell which id is wrong).- No reorder endpoint --
OrderNumis set in the request but there's no atomic "reorder this list" operation. Reordering N waypoints requires N PUTs and is racy. - Same transaction gap as
MissionService.DeleteMission-- noBeginTransactionAsyncaround the cascade. GeoPoint?swallowing -- sending a request withGeoPoint = nullclears the location entirely. Likely intentional but combined with "no validation" means an empty waypoint can be created.