Skip to content

Develop - #301

Merged
ucswift merged 2 commits into
masterfrom
develop
Mar 17, 2026
Merged

Develop#301
ucswift merged 2 commits into
masterfrom
develop

Conversation

@ucswift

Copy link
Copy Markdown
Member

No description provided.

[HttpPost("CreateRoutePlan")]
[Authorize(Policy = ResgridResources.Route_Create)]
[ProducesResponseType(StatusCodes.Status201Created)]
public async Task<ActionResult<SaveRoutePlanResult>> CreateRoutePlan([FromBody] NewRoutePlanInput input)

Check failure

Code scanning / CodeQL

Missing cross-site request forgery token validation High

Method 'CreateRoutePlan' handles a POST request without performing CSRF token validation.

Copilot Autofix

AI 6 months ago

In general, to fix missing CSRF validation in ASP.NET Core MVC/Web API controllers that are using cookie-based authentication, you should decorate state‑changing actions (especially POST/PUT/DELETE) with antiforgery validation attributes or enable a global antiforgery filter. This ensures that any request must include a valid antiforgery token (typically sent in a header or form field) that the server verifies before processing the action.

For this specific method, the minimal, targeted fix without changing existing behavior is to add the built‑in [ValidateAntiForgeryToken] attribute directly above CreateRoutePlan. This action already has [HttpPost("CreateRoutePlan")] and [Authorize(...)] attributes; we simply extend that attribute list to include [ValidateAntiForgeryToken]. ASP.NET Core MVC defines ValidateAntiForgeryTokenAttribute in Microsoft.AspNetCore.Mvc, which is already imported at the top of the file (using Microsoft.AspNetCore.Mvc; on line 3), so no new using directives are required. No changes are needed to the method body, routes, or return types.

Concretely: edit Web/Resgrid.Web.Services/Controllers/v4/RoutesController.cs, locate the CreateRoutePlan action (around lines 170–176), and insert [ValidateAntiForgeryToken] between the existing attributes or after them. This will cause ASP.NET Core to enforce antiforgery token validation for this POST endpoint, addressing the CodeQL warning.

Suggested changeset 1
Web/Resgrid.Web.Services/Controllers/v4/RoutesController.cs

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/Web/Resgrid.Web.Services/Controllers/v4/RoutesController.cs b/Web/Resgrid.Web.Services/Controllers/v4/RoutesController.cs
--- a/Web/Resgrid.Web.Services/Controllers/v4/RoutesController.cs
+++ b/Web/Resgrid.Web.Services/Controllers/v4/RoutesController.cs
@@ -172,6 +172,7 @@
/// </summary>
[HttpPost("CreateRoutePlan")]
[Authorize(Policy = ResgridResources.Route_Create)]
+ [ValidateAntiForgeryToken]
[ProducesResponseType(StatusCodes.Status201Created)]
public async Task<ActionResult<SaveRoutePlanResult>> CreateRoutePlan([FromBody] NewRoutePlanInput input)
{
EOF
@@ -172,6 +172,7 @@
/// </summary>
[HttpPost("CreateRoutePlan")]
[Authorize(Policy=ResgridResources.Route_Create)]
[ValidateAntiForgeryToken]
[ProducesResponseType(StatusCodes.Status201Created)]
publicasyncTask<ActionResult<SaveRoutePlanResult>>CreateRoutePlan([FromBody]NewRoutePlanInputinput)
{
Copilot is powered by AI and may make mistakes. Always verify output.
Unable to commit as this autofix suggestion is now outdated
[HttpPost("StartRoute")]
[Authorize(Policy = ResgridResources.Route_Update)]
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task<ActionResult<GetRouteInstanceResult>> StartRoute([FromBody] StartRouteInput input)

Check failure

Code scanning / CodeQL

Missing cross-site request forgery token validation High

Method 'StartRoute' handles a POST request without performing CSRF token validation.

Copilot Autofix

AI 6 months ago

In general, to fix missing CSRF validation on ASP.NET Core MVC/Web API controllers that use cookie-based authentication, you should ensure that all state-changing POST, PUT, PATCH, and DELETE actions either (a) validate an anti-forgery token via [ValidateAntiForgeryToken] or [AutoValidateAntiforgeryToken], or (b) are explicitly and consciously exempted with a clear justification (e.g., pure token-based API with no cookies). The corresponding clients must include the token (e.g., via a hidden form field or header) when calling the endpoint.

For this specific method, the minimal and safest fix without changing existing behavior is to decorate StartRoute with the ASP.NET Core antiforgery attribute so that, whenever cookies are used for authentication, the POST request must also present a valid anti-forgery token. In ASP.NET Core MVC, this is done with [ValidateAntiForgeryToken] on the action method. No additional code within the method body is required, and no changes to the service call are needed. We will add the attribute directly above StartRoute, keeping all other attributes ([HttpPost("StartRoute")], [Authorize(...)], [ProducesResponseType(...)]) intact. The required namespace Microsoft.AspNetCore.Mvc is already imported at the top of the file, so no new imports are needed.

Concretely:

  • File: Web/Resgrid.Web.Services/Controllers/v4/RoutesController.cs
  • Region: method StartRoute at/around line 316.
  • Change: add [ValidateAntiForgeryToken] on its own line between the existing attributes and the method signature.
Suggested changeset 1
Web/Resgrid.Web.Services/Controllers/v4/RoutesController.cs

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/Web/Resgrid.Web.Services/Controllers/v4/RoutesController.cs b/Web/Resgrid.Web.Services/Controllers/v4/RoutesController.cs
--- a/Web/Resgrid.Web.Services/Controllers/v4/RoutesController.cs
+++ b/Web/Resgrid.Web.Services/Controllers/v4/RoutesController.cs
@@ -313,6 +313,7 @@
[HttpPost("StartRoute")]
[Authorize(Policy = ResgridResources.Route_Update)]
[ProducesResponseType(StatusCodes.Status200OK)]
+ [ValidateAntiForgeryToken]
public async Task<ActionResult<GetRouteInstanceResult>> StartRoute([FromBody] StartRouteInput input)
{
var instance = await _routeService.StartRouteAsync(input.RoutePlanId, input.UnitId, UserId);
EOF
@@ -313,6 +313,7 @@
[HttpPost("StartRoute")]
[Authorize(Policy=ResgridResources.Route_Update)]
[ProducesResponseType(StatusCodes.Status200OK)]
[ValidateAntiForgeryToken]
publicasyncTask<ActionResult<GetRouteInstanceResult>>StartRoute([FromBody]StartRouteInputinput)
{
varinstance=await_routeService.StartRouteAsync(input.RoutePlanId,input.UnitId,UserId);
Copilot is powered by AI and may make mistakes. Always verify output.
Unable to commit as this autofix suggestion is now outdated
[HttpPost("EndRoute")]
[Authorize(Policy = ResgridResources.Route_Update)]
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task<ActionResult<GetRouteInstanceResult>> EndRoute([FromBody] EndRouteInput input)

Check failure

Code scanning / CodeQL

Missing cross-site request forgery token validation High

Method 'EndRoute' handles a POST request without performing CSRF token validation.

Copilot Autofix

AI 6 months ago

In general, the fix is to ensure that all state-changing POST actions that are reachable from a browser and use cookie-based authentication validate an anti-forgery token. In ASP.NET Core MVC this is typically done with the [ValidateAntiForgeryToken] attribute on each such action, or by applying a global filter that enforces it for all unsafe HTTP methods.

For this specific case, the least invasive and most consistent fix is to decorate the EndRoute action with [ValidateAntiForgeryToken], just as recommended, and ensure the attribute is available via an appropriate using (in ASP.NET Core it lives in Microsoft.AspNetCore.Mvc). Since StartRoute is a similar POST action that also mutates state and is implemented alongside EndRoute, it should be protected in the same way to avoid inconsistent CSRF handling. The file already imports Microsoft.AspNetCore.Mvc, so no new import is needed; we only need to add [ValidateAntiForgeryToken] directly above both StartRoute and EndRoute methods (around lines 313–331). This change preserves existing behavior except for adding CSRF validation, which is the desired security fix.

Suggested changeset 1
Web/Resgrid.Web.Services/Controllers/v4/RoutesController.cs

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/Web/Resgrid.Web.Services/Controllers/v4/RoutesController.cs b/Web/Resgrid.Web.Services/Controllers/v4/RoutesController.cs
--- a/Web/Resgrid.Web.Services/Controllers/v4/RoutesController.cs
+++ b/Web/Resgrid.Web.Services/Controllers/v4/RoutesController.cs
@@ -312,6 +312,7 @@
/// </summary>
[HttpPost("StartRoute")]
[Authorize(Policy = ResgridResources.Route_Update)]
+ [ValidateAntiForgeryToken]
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task<ActionResult<GetRouteInstanceResult>> StartRoute([FromBody] StartRouteInput input)
{
@@ -327,6 +328,7 @@
/// </summary>
[HttpPost("EndRoute")]
[Authorize(Policy = ResgridResources.Route_Update)]
+ [ValidateAntiForgeryToken]
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task<ActionResult<GetRouteInstanceResult>> EndRoute([FromBody] EndRouteInput input)
{
EOF
@@ -312,6 +312,7 @@
/// </summary>
[HttpPost("StartRoute")]
[Authorize(Policy=ResgridResources.Route_Update)]
[ValidateAntiForgeryToken]
[ProducesResponseType(StatusCodes.Status200OK)]
publicasyncTask<ActionResult<GetRouteInstanceResult>>StartRoute([FromBody]StartRouteInputinput)
{
@@ -327,6 +328,7 @@
/// </summary>
[HttpPost("EndRoute")]
[Authorize(Policy=ResgridResources.Route_Update)]
[ValidateAntiForgeryToken]
[ProducesResponseType(StatusCodes.Status200OK)]
publicasyncTask<ActionResult<GetRouteInstanceResult>>EndRoute([FromBody]EndRouteInputinput)
{
Copilot is powered by AI and may make mistakes. Always verify output.
Unable to commit as this autofix suggestion is now outdated
[HttpPost("PauseRoute")]
[Authorize(Policy = ResgridResources.Route_Update)]
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task<ActionResult<GetRouteInstanceResult>> PauseRoute([FromBody] PauseRouteInput input)

Check failure

Code scanning / CodeQL

Missing cross-site request forgery token validation High

Method 'PauseRoute' handles a POST request without performing CSRF token validation.

Copilot Autofix

AI 6 months ago

In general, to fix missing CSRF protection on ASP.NET Core POST actions that are intended to be called from browser-based clients using cookie authentication, you add anti-forgery token validation to the action (or globally to all unsafe HTTP methods) and ensure clients send the token with each request. In ASP.NET Core MVC, this is usually done with [ValidateAntiForgeryToken] or [AutoValidateAntiforgeryToken].

For this specific issue, the minimal and best change—without altering existing logic—is to add the [ValidateAntiForgeryToken] attribute to the PauseRoute action, just as you would for any other state-changing POST endpoint that should be protected against CSRF. Since this is in an ASP.NET Core controller namespace already importing Microsoft.AspNetCore.Mvc, no new imports are required: [ValidateAntiForgeryToken] is defined in that assembly. We should place the attribute alongside the existing ones on the PauseRoute method (e.g., between [HttpPost("PauseRoute")] and [Authorize(...)] or directly above the method signature), so the runtime enforces anti-forgery token validation whenever this POST endpoint is invoked.

Only the code region around PauseRoute (lines 341–347) in Web/Resgrid.Web.Services/Controllers/v4/RoutesController.cs needs to be modified. The implementation of the method body does not change, just the list of attributes decorating the action.

Suggested changeset 1
Web/Resgrid.Web.Services/Controllers/v4/RoutesController.cs

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/Web/Resgrid.Web.Services/Controllers/v4/RoutesController.cs b/Web/Resgrid.Web.Services/Controllers/v4/RoutesController.cs
--- a/Web/Resgrid.Web.Services/Controllers/v4/RoutesController.cs
+++ b/Web/Resgrid.Web.Services/Controllers/v4/RoutesController.cs
@@ -342,6 +342,7 @@
/// </summary>
[HttpPost("PauseRoute")]
[Authorize(Policy = ResgridResources.Route_Update)]
+ [ValidateAntiForgeryToken]
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task<ActionResult<GetRouteInstanceResult>> PauseRoute([FromBody] PauseRouteInput input)
{
EOF
@@ -342,6 +342,7 @@
/// </summary>
[HttpPost("PauseRoute")]
[Authorize(Policy=ResgridResources.Route_Update)]
[ValidateAntiForgeryToken]
[ProducesResponseType(StatusCodes.Status200OK)]
publicasyncTask<ActionResult<GetRouteInstanceResult>>PauseRoute([FromBody]PauseRouteInputinput)
{
Copilot is powered by AI and may make mistakes. Always verify output.
Unable to commit as this autofix suggestion is now outdated
[HttpPost("ResumeRoute")]
[Authorize(Policy = ResgridResources.Route_Update)]
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task<ActionResult<GetRouteInstanceResult>> ResumeRoute([FromBody] ResumeRouteInput input)

Check failure

Code scanning / CodeQL

Missing cross-site request forgery token validation High

Method 'ResumeRoute' handles a POST request without performing CSRF token validation.

Copilot Autofix

AI 6 months ago

In general, state-changing HTTP POST actions that rely on cookie-based authentication must validate an antiforgery token (or use another robust CSRF mitigation). In ASP.NET Core MVC, this is typically done with the [ValidateAntiForgeryToken] attribute (or [AutoValidateAntiforgeryToken] globally). For JSON APIs that are still using cookies, the client must send the antiforgery token with the request (for example via header or form field), and the server must validate it.

For this specific fix, the minimal and safest change—without altering existing business logic—is to decorate the ResumeRoute method with [ValidateAntiForgeryToken] so that any POST to ResumeRoute must include a valid token. Because PauseRoute is a nearly identical state-changing POST, we should align it with the same protection to avoid leaving similar functionality exposed. ASP.NET Core places ValidateAntiForgeryTokenAttribute in the Microsoft.AspNetCore.Mvc namespace, which is already imported at the top of the file, so no new using directives are required. Concretely, in Web/Resgrid.Web.Services/Controllers/v4/RoutesController.cs, directly above the ResumeRoute method declaration (line 361 in the snippet), add [ValidateAntiForgeryToken]. Also add the same attribute above PauseRoute (line 346 in the snippet). No changes to method signatures, return types, or service calls are necessary.


Suggested changeset 1
Web/Resgrid.Web.Services/Controllers/v4/RoutesController.cs

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/Web/Resgrid.Web.Services/Controllers/v4/RoutesController.cs b/Web/Resgrid.Web.Services/Controllers/v4/RoutesController.cs
--- a/Web/Resgrid.Web.Services/Controllers/v4/RoutesController.cs
+++ b/Web/Resgrid.Web.Services/Controllers/v4/RoutesController.cs
@@ -343,6 +343,7 @@
[HttpPost("PauseRoute")]
[Authorize(Policy = ResgridResources.Route_Update)]
[ProducesResponseType(StatusCodes.Status200OK)]
+ [ValidateAntiForgeryToken]
public async Task<ActionResult<GetRouteInstanceResult>> PauseRoute([FromBody] PauseRouteInput input)
{
var instance = await _routeService.PauseRouteAsync(input.RouteInstanceId, UserId);
@@ -358,6 +359,7 @@
[HttpPost("ResumeRoute")]
[Authorize(Policy = ResgridResources.Route_Update)]
[ProducesResponseType(StatusCodes.Status200OK)]
+ [ValidateAntiForgeryToken]
public async Task<ActionResult<GetRouteInstanceResult>> ResumeRoute([FromBody] ResumeRouteInput input)
{
var instance = await _routeService.ResumeRouteAsync(input.RouteInstanceId, UserId);
EOF
@@ -343,6 +343,7 @@
[HttpPost("PauseRoute")]
[Authorize(Policy=ResgridResources.Route_Update)]
[ProducesResponseType(StatusCodes.Status200OK)]
[ValidateAntiForgeryToken]
publicasyncTask<ActionResult<GetRouteInstanceResult>>PauseRoute([FromBody]PauseRouteInputinput)
{
varinstance=await_routeService.PauseRouteAsync(input.RouteInstanceId,UserId);
@@ -358,6 +359,7 @@
[HttpPost("ResumeRoute")]
[Authorize(Policy=ResgridResources.Route_Update)]
[ProducesResponseType(StatusCodes.Status200OK)]
[ValidateAntiForgeryToken]
publicasyncTask<ActionResult<GetRouteInstanceResult>>ResumeRoute([FromBody]ResumeRouteInputinput)
{
varinstance=await_routeService.ResumeRouteAsync(input.RouteInstanceId,UserId);
Copilot is powered by AI and may make mistakes. Always verify output.
Unable to commit as this autofix suggestion is now outdated
[HttpPost("SkipStop")]
[Authorize(Policy = ResgridResources.Route_Update)]
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task<ActionResult> SkipStop([FromBody] SkipStopInput input)

Check failure

Code scanning / CodeQL

Missing cross-site request forgery token validation High

Method 'SkipStop' handles a POST request without performing CSRF token validation.

Copilot Autofix

AI 6 months ago

In general, to fix missing CSRF validation in ASP.NET Core MVC, you either (a) apply the standard anti-forgery validation attribute (e.g., [ValidateAntiForgeryToken] or, if you’re using auto-validation, ensure [AutoValidateAntiforgeryToken] or a global filter is configured), or (b) decorate the action with a custom attribute that enforces an equivalent CSRF token check. The client must then include the anti-forgery token with its POST requests (typically via a request header or form field).

For this specific code, the minimal, non‑breaking fix is to add an appropriate anti-forgery validation attribute to the SkipStop action (and, ideally, keep behavior consistent with other similar endpoints). Since this project is using ASP.NET Core, the standard attribute is ValidateAntiForgeryTokenAttribute in Microsoft.AspNetCore.Mvc. We can reference it via [ValidateAntiForgeryToken] without new using directives because we already have using Microsoft.AspNetCore.Mvc; at the top. We only change the attributes decorating SkipStop, leaving its logic and signature untouched.

Concretely:

  • In Web/Resgrid.Web.Services/Controllers/v4/RoutesController.cs, locate the SkipStop action.
  • Add [ValidateAntiForgeryToken] above the public async Task<ActionResult> SkipStop(...) declaration (or alongside the other attributes) so that ASP.NET Core’s anti-forgery system validates the token for this POST.
  • No extra imports or method definitions are needed; the attribute type is already available from existing using statements.
Suggested changeset 1
Web/Resgrid.Web.Services/Controllers/v4/RoutesController.cs

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/Web/Resgrid.Web.Services/Controllers/v4/RoutesController.cs b/Web/Resgrid.Web.Services/Controllers/v4/RoutesController.cs
--- a/Web/Resgrid.Web.Services/Controllers/v4/RoutesController.cs
+++ b/Web/Resgrid.Web.Services/Controllers/v4/RoutesController.cs
@@ -492,6 +492,7 @@
[HttpPost("SkipStop")]
[Authorize(Policy = ResgridResources.Route_Update)]
[ProducesResponseType(StatusCodes.Status200OK)]
+ [ValidateAntiForgeryToken]
public async Task<ActionResult> SkipStop([FromBody] SkipStopInput input)
{
await _routeService.SkipStopAsync(input.RouteInstanceStopId, input.Reason);
EOF
@@ -492,6 +492,7 @@
[HttpPost("SkipStop")]
[Authorize(Policy=ResgridResources.Route_Update)]
[ProducesResponseType(StatusCodes.Status200OK)]
[ValidateAntiForgeryToken]
publicasyncTask<ActionResult>SkipStop([FromBody]SkipStopInputinput)
{
await_routeService.SkipStopAsync(input.RouteInstanceStopId,input.Reason);
Copilot is powered by AI and may make mistakes. Always verify output.
Unable to commit as this autofix suggestion is now outdated
[HttpPost("GeofenceCheckIn")]
[Authorize(Policy = ResgridResources.Route_Update)]
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task<ActionResult> GeofenceCheckIn([FromBody] GeofenceCheckInInput input)

Check failure

Code scanning / CodeQL

Missing cross-site request forgery token validation High

Method 'GeofenceCheckIn' handles a POST request without performing CSRF token validation.

Copilot Autofix

AI 6 months ago

In general, to fix missing CSRF validation in ASP.NET Core MVC/API controllers that use cookie-based authentication, you decorate state-changing POST (and other unsafe) actions with [ValidateAntiForgeryToken] (or enable a global AutoValidateAntiforgeryToken filter). This ensures that requests must include a valid anti-forgery token, preventing cross-site attacks from a third-party origin that relies on the victim’s browser automatically attaching cookies.

For this specific case, the minimal, non‑breaking fix is to apply [ValidateAntiForgeryToken] to the GeofenceCheckIn action in Web/Resgrid.Web.Services/Controllers/v4/RoutesController.cs. Since this file already imports Microsoft.AspNetCore.Mvc, which defines ValidateAntiForgeryTokenAttribute, no new using directives are required. We will insert [ValidateAntiForgeryToken] directly above the existing [HttpPost("GeofenceCheckIn")] (order relative to [Authorize] doesn’t matter functionally, but we will keep the current style of attribute grouping consistent with the nearby SkipStop method). No changes to the method body are needed; the runtime will enforce antiforgery token validation automatically for POST requests to this action.

Concretely:

  • In RoutesController.cs, locate the GeofenceCheckIn method (lines 502–507 in the snippet).
  • Add [ValidateAntiForgeryToken] as an attribute on the method, directly above [HttpPost("GeofenceCheckIn")].
  • No extra imports or helper methods are needed, because ValidateAntiForgeryToken comes from Microsoft.AspNetCore.Mvc, which is already imported.
Suggested changeset 1
Web/Resgrid.Web.Services/Controllers/v4/RoutesController.cs

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/Web/Resgrid.Web.Services/Controllers/v4/RoutesController.cs b/Web/Resgrid.Web.Services/Controllers/v4/RoutesController.cs
--- a/Web/Resgrid.Web.Services/Controllers/v4/RoutesController.cs
+++ b/Web/Resgrid.Web.Services/Controllers/v4/RoutesController.cs
@@ -501,6 +501,7 @@
/// <summary>
/// Auto check-in from geofence proximity
/// </summary>
+ [ValidateAntiForgeryToken]
[HttpPost("GeofenceCheckIn")]
[Authorize(Policy = ResgridResources.Route_Update)]
[ProducesResponseType(StatusCodes.Status200OK)]
EOF
@@ -501,6 +501,7 @@
/// <summary>
/// Auto check-in from geofence proximity
/// </summary>
[ValidateAntiForgeryToken]
[HttpPost("GeofenceCheckIn")]
[Authorize(Policy=ResgridResources.Route_Update)]
[ProducesResponseType(StatusCodes.Status200OK)]
Copilot is powered by AI and may make mistakes. Always verify output.
Unable to commit as this autofix suggestion is now outdated
[HttpPost("AcknowledgeDeviation/{id}")]
[Authorize(Policy = ResgridResources.Route_Update)]
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task<ActionResult> AcknowledgeDeviation(string id)

Check failure

Code scanning / CodeQL

Missing cross-site request forgery token validation High

Method 'AcknowledgeDeviation' handles a POST request without performing CSRF token validation.

Copilot Autofix

AI 6 months ago

In general, to fix missing CSRF token validation in ASP.NET Core MVC/Web API controllers that use cookie-based authentication, you decorate state-changing actions (or the controller as a whole) with an anti-forgery validation attribute such as [ValidateAntiForgeryToken] or [AutoValidateAntiforgeryToken], and ensure the client sends the corresponding token with the request.

For this specific method, the minimal, non-breaking fix is to add [ValidateAntiForgeryToken] to AcknowledgeDeviation, since it is a POST endpoint that mutates state. ASP.NET Core’s anti-forgery attributes live in Microsoft.AspNetCore.Mvc, which is already imported at the top of the file, so no new using directives are needed. We will leave the existing route, authorization, and response types unchanged, and simply add the attribute above the method. The change occurs in Web/Resgrid.Web.Services/Controllers/v4/RoutesController.cs around lines 547–552 where the method is defined.

Suggested changeset 1
Web/Resgrid.Web.Services/Controllers/v4/RoutesController.cs

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/Web/Resgrid.Web.Services/Controllers/v4/RoutesController.cs b/Web/Resgrid.Web.Services/Controllers/v4/RoutesController.cs
--- a/Web/Resgrid.Web.Services/Controllers/v4/RoutesController.cs
+++ b/Web/Resgrid.Web.Services/Controllers/v4/RoutesController.cs
@@ -549,6 +549,7 @@
[HttpPost("AcknowledgeDeviation/{id}")]
[Authorize(Policy = ResgridResources.Route_Update)]
[ProducesResponseType(StatusCodes.Status200OK)]
+ [ValidateAntiForgeryToken]
public async Task<ActionResult> AcknowledgeDeviation(string id)
{
await _routeService.AcknowledgeDeviationAsync(id, UserId);
EOF
@@ -549,6 +549,7 @@
[HttpPost("AcknowledgeDeviation/{id}")]
[Authorize(Policy=ResgridResources.Route_Update)]
[ProducesResponseType(StatusCodes.Status200OK)]
[ValidateAntiForgeryToken]
publicasyncTask<ActionResult>AcknowledgeDeviation(stringid)
{
await_routeService.AcknowledgeDeviationAsync(id,UserId);
Copilot is powered by AI and may make mistakes. Always verify output.
Unable to commit as this autofix suggestion is now outdated
}

[HttpPost]
public async Task<IActionResult> SaveRegion([FromBody] IndoorMapZone region, CancellationToken cancellationToken)

Check failure

Code scanning / CodeQL

Missing cross-site request forgery token validation High

Method 'SaveRegion' handles a POST request without performing CSRF token validation.

Copilot Autofix

AI 6 months ago

In general, to fix missing CSRF validation on an ASP.NET Core MVC POST action, you add the [ValidateAntiForgeryToken] attribute (or a custom equivalent) to the action (or controller), and ensure that clients sending POST requests include a valid anti-forgery token. For JSON/AJAX requests, this commonly involves sending the token in a header or JSON field and using the built-in anti-forgery configuration.

For this specific case, the safest minimal fix that doesn’t change existing functionality is to decorate the SaveRegion action with [ValidateAntiForgeryToken]. This leverages ASP.NET Core’s built-in anti-forgery system and requires no changes to service logic. The attribute is available from the existing Microsoft.AspNetCore.Mvc import, so we don’t need new usings. The change is confined to Web/Resgrid.Web/Areas/User/Controllers/CustomMapsController.cs, at the definition of SaveRegion (around line 211). We simply insert the attribute above the method declaration, keeping the existing [HttpPost] attribute.

If the front-end already posts anti-forgery tokens for other actions, this will align SaveRegion with the same pattern. If not, the front-end will need to be updated separately to include a valid anti-forgery token in the AJAX call when saving regions.

Suggested changeset 1
Web/Resgrid.Web/Areas/User/Controllers/CustomMapsController.cs

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/Web/Resgrid.Web/Areas/User/Controllers/CustomMapsController.cs b/Web/Resgrid.Web/Areas/User/Controllers/CustomMapsController.cs
--- a/Web/Resgrid.Web/Areas/User/Controllers/CustomMapsController.cs
+++ b/Web/Resgrid.Web/Areas/User/Controllers/CustomMapsController.cs
@@ -209,6 +209,7 @@
}
[HttpPost]
+ [ValidateAntiForgeryToken]
public async Task<IActionResult> SaveRegion([FromBody] IndoorMapZone region, CancellationToken cancellationToken)
{
var layer = await _customMapService.GetLayerByIdAsync(region.IndoorMapFloorId);
EOF
@@ -209,6 +209,7 @@
}

[HttpPost]
[ValidateAntiForgeryToken]
publicasyncTask<IActionResult>SaveRegion([FromBody]IndoorMapZoneregion,CancellationTokencancellationToken)
{
varlayer=await_customMapService.GetLayerByIdAsync(region.IndoorMapFloorId);
Copilot is powered by AI and may make mistakes. Always verify output.
Unable to commit as this autofix suggestion is now outdated
}

[HttpPost]
public async Task<IActionResult> DeleteRegion([FromBody] DeleteRegionRequest request, CancellationToken cancellationToken)

Check failure

Code scanning / CodeQL

Missing cross-site request forgery token validation High

Method 'DeleteRegion' handles a POST request without performing CSRF token validation.

Copilot Autofix

AI 6 months ago

In general, to fix missing CSRF validation in ASP.NET Core MVC actions, you either (1) apply [ValidateAntiForgeryToken] (or [AutoValidateAntiforgeryToken] globally) to state-changing actions and ensure the client sends the token with each POST, or (2) use an alternative, well-defined CSRF mitigation strategy (such as double-submit cookies or same-site cookies with no ambient auth). In this codebase, the simplest, least disruptive fix that matches the recommendation is to add the standard ASP.NET Core anti-forgery validation attribute to the affected action.

For this specific issue, we should add [ValidateAntiForgeryToken] to the DeleteRegion POST action. Since this is an ASP.NET Core MVC controller (using Microsoft.AspNetCore.Mvc), the attribute class is available from existing imports; no new using directives are needed. The attribute should be applied directly above the DeleteRegion method, alongside [HttpPost], so that ASP.NET Core validates the anti-forgery token on each request to this endpoint. We will not alter the method’s logic or signature, just add the attribute. If the front-end is not yet sending anti-forgery tokens for this AJAX call, that would need to be handled separately in the client code, but that is outside the scope of the provided snippet.

Concretely, in Web/Resgrid.Web/Areas/User/Controllers/CustomMapsController.cs, locate the DeleteRegion method (line 234) and add [ValidateAntiForgeryToken] between [HttpPost] and the method declaration. No other code changes are required in this file.

Suggested changeset 1
Web/Resgrid.Web/Areas/User/Controllers/CustomMapsController.cs

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/Web/Resgrid.Web/Areas/User/Controllers/CustomMapsController.cs b/Web/Resgrid.Web/Areas/User/Controllers/CustomMapsController.cs
--- a/Web/Resgrid.Web/Areas/User/Controllers/CustomMapsController.cs
+++ b/Web/Resgrid.Web/Areas/User/Controllers/CustomMapsController.cs
@@ -231,6 +231,7 @@
}
[HttpPost]
+ [ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteRegion([FromBody] DeleteRegionRequest request, CancellationToken cancellationToken)
{
var region = await _customMapService.GetRegionByIdAsync(request.RegionId);
EOF
@@ -231,6 +231,7 @@
}

[HttpPost]
[ValidateAntiForgeryToken]
publicasyncTask<IActionResult>DeleteRegion([FromBody]DeleteRegionRequestrequest,CancellationTokencancellationToken)
{
varregion=await_customMapService.GetRegionByIdAsync(request.RegionId);
Copilot is powered by AI and may make mistakes. Always verify output.
Unable to commit as this autofix suggestion is now outdated
@request-info

Copy link
Copy Markdown

Thanks for opening this, but we'd appreciate a little more information. Could you update it with more details?

@coderabbitai

coderabbitaiBot commented Mar 17, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Too many files!

This PR contains 175 files, which is 25 over the limit of 150.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: fb17845b-8a3c-4413-a266-4a308e02a3f9

📥 Commits

Reviewing files that changed from the base of the PR and between 9151444 and b5846a2.

📒 Files selected for processing (175)
  • .gitignore
  • Core/Resgrid.Model/AuditLogTypes.cs
  • Core/Resgrid.Model/Call.cs
  • Core/Resgrid.Model/CustomMapImport.cs
  • Core/Resgrid.Model/CustomMapImportFileType.cs
  • Core/Resgrid.Model/CustomMapImportStatus.cs
  • Core/Resgrid.Model/CustomMapLayerType.cs
  • Core/Resgrid.Model/CustomMapTile.cs
  • Core/Resgrid.Model/CustomMapType.cs
  • Core/Resgrid.Model/DepartmentNotification.cs
  • Core/Resgrid.Model/IndoorMap.cs
  • Core/Resgrid.Model/IndoorMapFloor.cs
  • Core/Resgrid.Model/IndoorMapZone.cs
  • Core/Resgrid.Model/IndoorMapZoneType.cs
  • Core/Resgrid.Model/PermissionTypes.cs
  • Core/Resgrid.Model/Repositories/ICustomMapImportsRepository.cs
  • Core/Resgrid.Model/Repositories/ICustomMapTilesRepository.cs
  • Core/Resgrid.Model/Repositories/IIndoorMapFloorsRepository.cs
  • Core/Resgrid.Model/Repositories/IIndoorMapZonesRepository.cs
  • Core/Resgrid.Model/Repositories/IIndoorMapsRepository.cs
  • Core/Resgrid.Model/Repositories/IRouteDeviationsRepository.cs
  • Core/Resgrid.Model/Repositories/IRouteInstanceStopsRepository.cs
  • Core/Resgrid.Model/Repositories/IRouteInstancesRepository.cs
  • Core/Resgrid.Model/Repositories/IRoutePlansRepository.cs
  • Core/Resgrid.Model/Repositories/IRouteSchedulesRepository.cs
  • Core/Resgrid.Model/Repositories/IRouteStopsRepository.cs
  • Core/Resgrid.Model/RouteDeviation.cs
  • Core/Resgrid.Model/RouteInstance.cs
  • Core/Resgrid.Model/RouteInstanceStatus.cs
  • Core/Resgrid.Model/RouteInstanceStop.cs
  • Core/Resgrid.Model/RoutePlan.cs
  • Core/Resgrid.Model/RouteRecurrenceType.cs
  • Core/Resgrid.Model/RouteSchedule.cs
  • Core/Resgrid.Model/RouteStatus.cs
  • Core/Resgrid.Model/RouteStop.cs
  • Core/Resgrid.Model/RouteStopCheckInType.cs
  • Core/Resgrid.Model/RouteStopPriority.cs
  • Core/Resgrid.Model/RouteStopType.cs
  • Core/Resgrid.Model/Services/ICustomMapService.cs
  • Core/Resgrid.Model/Services/IIndoorMapService.cs
  • Core/Resgrid.Model/Services/IRouteService.cs
  • Core/Resgrid.Services/CallsService.cs
  • Core/Resgrid.Services/CustomMapService.cs
  • Core/Resgrid.Services/IndoorMapService.cs
  • Core/Resgrid.Services/Resgrid.Services.csproj
  • Core/Resgrid.Services/RouteService.cs
  • Core/Resgrid.Services/ServicesModule.cs
  • Providers/Resgrid.Providers.Claims/ClaimsLogic.cs
  • Providers/Resgrid.Providers.Claims/ClaimsPrincipalFactory.cs
  • Providers/Resgrid.Providers.Claims/JwtTokenProvider.cs
  • Providers/Resgrid.Providers.Claims/ResgridClaimTypes.cs
  • Providers/Resgrid.Providers.Claims/ResgridIdentity.cs
  • Providers/Resgrid.Providers.Claims/ResgridResources.cs
  • Providers/Resgrid.Providers.Migrations/Migrations/M0051_AddingIndoorMaps.cs
  • Providers/Resgrid.Providers.Migrations/Migrations/M0052_AddingCustomMapSupport.cs
  • Providers/Resgrid.Providers.Migrations/Migrations/M0053_AddingRoutePlanning.cs
  • Providers/Resgrid.Providers.MigrationsPg/Migrations/M0051_AddingIndoorMapsPg.cs
  • Providers/Resgrid.Providers.MigrationsPg/Migrations/M0052_AddingCustomMapSupportPg.cs
  • Providers/Resgrid.Providers.MigrationsPg/Migrations/M0053_AddingRoutePlanningPg.cs
  • Repositories/Resgrid.Repositories.DataRepository/Configs/SqlConfiguration.cs
  • Repositories/Resgrid.Repositories.DataRepository/CustomMapImportsRepository.cs
  • Repositories/Resgrid.Repositories.DataRepository/CustomMapTilesRepository.cs
  • Repositories/Resgrid.Repositories.DataRepository/IndoorMapFloorsRepository.cs
  • Repositories/Resgrid.Repositories.DataRepository/IndoorMapZonesRepository.cs
  • Repositories/Resgrid.Repositories.DataRepository/IndoorMapsRepository.cs
  • Repositories/Resgrid.Repositories.DataRepository/Modules/ApiDataModule.cs
  • Repositories/Resgrid.Repositories.DataRepository/Modules/DataModule.cs
  • Repositories/Resgrid.Repositories.DataRepository/Modules/NonWebDataModule.cs
  • Repositories/Resgrid.Repositories.DataRepository/Modules/TestingDataModule.cs
  • Repositories/Resgrid.Repositories.DataRepository/Queries/CustomMaps/DeleteCustomMapTilesForLayerQuery.cs
  • Repositories/Resgrid.Repositories.DataRepository/Queries/CustomMaps/SelectCustomMapImportsForMapQuery.cs
  • Repositories/Resgrid.Repositories.DataRepository/Queries/CustomMaps/SelectCustomMapTileQuery.cs
  • Repositories/Resgrid.Repositories.DataRepository/Queries/CustomMaps/SelectCustomMapTilesForLayerQuery.cs
  • Repositories/Resgrid.Repositories.DataRepository/Queries/CustomMaps/SelectPendingCustomMapImportsQuery.cs
  • Repositories/Resgrid.Repositories.DataRepository/Queries/IndoorMaps/SearchIndoorMapZonesQuery.cs
  • Repositories/Resgrid.Repositories.DataRepository/Queries/IndoorMaps/SelectIndoorMapFloorsByMapIdQuery.cs
  • Repositories/Resgrid.Repositories.DataRepository/Queries/IndoorMaps/SelectIndoorMapZonesByFloorIdQuery.cs
  • Repositories/Resgrid.Repositories.DataRepository/Queries/IndoorMaps/SelectIndoorMapsByDepartmentIdQuery.cs
  • Repositories/Resgrid.Repositories.DataRepository/Queries/Routes/SelectActiveRouteInstancesByUnitIdQuery.cs
  • Repositories/Resgrid.Repositories.DataRepository/Queries/Routes/SelectActiveRoutePlansByDepartmentIdQuery.cs
  • Repositories/Resgrid.Repositories.DataRepository/Queries/Routes/SelectActiveSchedulesDueQuery.cs
  • Repositories/Resgrid.Repositories.DataRepository/Queries/Routes/SelectRouteDeviationsByRouteInstanceIdQuery.cs
  • Repositories/Resgrid.Repositories.DataRepository/Queries/Routes/SelectRouteInstanceStopsByRouteInstanceIdQuery.cs
  • Repositories/Resgrid.Repositories.DataRepository/Queries/Routes/SelectRouteInstancesByDateRangeQuery.cs
  • Repositories/Resgrid.Repositories.DataRepository/Queries/Routes/SelectRouteInstancesByDepartmentIdQuery.cs
  • Repositories/Resgrid.Repositories.DataRepository/Queries/Routes/SelectRouteInstancesByRoutePlanIdQuery.cs
  • Repositories/Resgrid.Repositories.DataRepository/Queries/Routes/SelectRoutePlansByDepartmentIdQuery.cs
  • Repositories/Resgrid.Repositories.DataRepository/Queries/Routes/SelectRoutePlansByUnitIdQuery.cs
  • Repositories/Resgrid.Repositories.DataRepository/Queries/Routes/SelectRouteSchedulesByRoutePlanIdQuery.cs
  • Repositories/Resgrid.Repositories.DataRepository/Queries/Routes/SelectRouteStopsByCallIdQuery.cs
  • Repositories/Resgrid.Repositories.DataRepository/Queries/Routes/SelectRouteStopsByRoutePlanIdQuery.cs
  • Repositories/Resgrid.Repositories.DataRepository/Queries/Routes/SelectUnacknowledgedRouteDeviationsByDepartmentQuery.cs
  • Repositories/Resgrid.Repositories.DataRepository/RepositoryBase.cs
  • Repositories/Resgrid.Repositories.DataRepository/RouteDeviationsRepository.cs
  • Repositories/Resgrid.Repositories.DataRepository/RouteInstanceStopsRepository.cs
  • Repositories/Resgrid.Repositories.DataRepository/RouteInstancesRepository.cs
  • Repositories/Resgrid.Repositories.DataRepository/RoutePlansRepository.cs
  • Repositories/Resgrid.Repositories.DataRepository/RouteSchedulesRepository.cs
  • Repositories/Resgrid.Repositories.DataRepository/RouteStopsRepository.cs
  • Repositories/Resgrid.Repositories.DataRepository/Servers/PostgreSql/PostgreSqlConfiguration.cs
  • Repositories/Resgrid.Repositories.DataRepository/Servers/SqlServer/SqlServerConfiguration.cs
  • Tests/Resgrid.Tests/Services/CustomMapServiceTests.cs
  • Tests/Resgrid.Tests/Services/GeoImportServiceTests.cs
  • Tests/Resgrid.Tests/Services/RouteServiceTests.cs
  • Tests/Resgrid.Tests/Services/TileProcessingTests.cs
  • Web/Resgrid.Web.Services/Controllers/v4/CallsController.cs
  • Web/Resgrid.Web.Services/Controllers/v4/MappingController.cs
  • Web/Resgrid.Web.Services/Controllers/v4/RoutesController.cs
  • Web/Resgrid.Web.Services/Models/v4/Calls/NewCallInput.cs
  • Web/Resgrid.Web.Services/Models/v4/Mapping/CustomMapLayerResultData.cs
  • Web/Resgrid.Web.Services/Models/v4/Mapping/CustomMapRegionResultData.cs
  • Web/Resgrid.Web.Services/Models/v4/Mapping/CustomMapResultData.cs
  • Web/Resgrid.Web.Services/Models/v4/Mapping/GetCustomMapsResult.cs
  • Web/Resgrid.Web.Services/Models/v4/Mapping/GetIndoorMapsResult.cs
  • Web/Resgrid.Web.Services/Models/v4/Mapping/IndoorMapFloorResultData.cs
  • Web/Resgrid.Web.Services/Models/v4/Mapping/IndoorMapResultData.cs
  • Web/Resgrid.Web.Services/Models/v4/Mapping/IndoorMapZoneResultData.cs
  • Web/Resgrid.Web.Services/Models/v4/Routes/RouteInputModels.cs
  • Web/Resgrid.Web.Services/Models/v4/Routes/RouteResultModels.cs
  • Web/Resgrid.Web.Services/Resgrid.Web.Services.xml
  • Web/Resgrid.Web.Services/Startup.cs
  • Web/Resgrid.Web/Areas/User/Controllers/ContactsController.cs
  • Web/Resgrid.Web/Areas/User/Controllers/CustomMapsController.cs
  • Web/Resgrid.Web/Areas/User/Controllers/DispatchController.cs
  • Web/Resgrid.Web/Areas/User/Controllers/IndoorMapsController.cs
  • Web/Resgrid.Web/Areas/User/Controllers/RoutesController.cs
  • Web/Resgrid.Web/Areas/User/Models/CustomMaps/CustomMapImportView.cs
  • Web/Resgrid.Web/Areas/User/Models/CustomMaps/CustomMapIndexView.cs
  • Web/Resgrid.Web/Areas/User/Models/CustomMaps/CustomMapLayersView.cs
  • Web/Resgrid.Web/Areas/User/Models/CustomMaps/CustomMapNewView.cs
  • Web/Resgrid.Web/Areas/User/Models/CustomMaps/CustomMapRegionEditorView.cs
  • Web/Resgrid.Web/Areas/User/Models/IndoorMaps/IndoorMapFloorsView.cs
  • Web/Resgrid.Web/Areas/User/Models/IndoorMaps/IndoorMapIndexView.cs
  • Web/Resgrid.Web/Areas/User/Models/IndoorMaps/IndoorMapNewView.cs
  • Web/Resgrid.Web/Areas/User/Models/IndoorMaps/IndoorMapZoneEditorView.cs
  • Web/Resgrid.Web/Areas/User/Models/Routes/RouteViewModels.cs
  • Web/Resgrid.Web/Areas/User/Views/CustomMaps/Edit.cshtml
  • Web/Resgrid.Web/Areas/User/Views/CustomMaps/Import.cshtml
  • Web/Resgrid.Web/Areas/User/Views/CustomMaps/Index.cshtml
  • Web/Resgrid.Web/Areas/User/Views/CustomMaps/Layers.cshtml
  • Web/Resgrid.Web/Areas/User/Views/CustomMaps/New.cshtml
  • Web/Resgrid.Web/Areas/User/Views/CustomMaps/RegionEditor.cshtml
  • Web/Resgrid.Web/Areas/User/Views/Dispatch/Dashboard.cshtml
  • Web/Resgrid.Web/Areas/User/Views/Dispatch/NewCall.cshtml
  • Web/Resgrid.Web/Areas/User/Views/Dispatch/UpdateCall.cshtml
  • Web/Resgrid.Web/Areas/User/Views/IndoorMaps/Edit.cshtml
  • Web/Resgrid.Web/Areas/User/Views/IndoorMaps/Floors.cshtml
  • Web/Resgrid.Web/Areas/User/Views/IndoorMaps/Index.cshtml
  • Web/Resgrid.Web/Areas/User/Views/IndoorMaps/New.cshtml
  • Web/Resgrid.Web/Areas/User/Views/IndoorMaps/ZoneEditor.cshtml
  • Web/Resgrid.Web/Areas/User/Views/Mapping/Index.cshtml
  • Web/Resgrid.Web/Areas/User/Views/Routes/ActiveRoutes.cshtml
  • Web/Resgrid.Web/Areas/User/Views/Routes/Edit.cshtml
  • Web/Resgrid.Web/Areas/User/Views/Routes/Index.cshtml
  • Web/Resgrid.Web/Areas/User/Views/Routes/InstanceDetail.cshtml
  • Web/Resgrid.Web/Areas/User/Views/Routes/Instances.cshtml
  • Web/Resgrid.Web/Areas/User/Views/Routes/New.cshtml
  • Web/Resgrid.Web/Areas/User/Views/Routes/View.cshtml
  • Web/Resgrid.Web/Areas/User/Views/Shared/_UserLayout.cshtml
  • Web/Resgrid.Web/Helpers/ClaimsAuthorizationHelper.cs
  • Web/Resgrid.Web/Startup.cs
  • Web/Resgrid.Web/wwwroot/js/app/common/analytics/resgrid.common.analytics.js
  • Web/Resgrid.Web/wwwroot/js/app/internal/custommaps/resgrid.custommaps.editor.js
  • Web/Resgrid.Web/wwwroot/js/app/internal/custommaps/resgrid.custommaps.import.js
  • Web/Resgrid.Web/wwwroot/js/app/internal/custommaps/resgrid.custommaps.index.js
  • Web/Resgrid.Web/wwwroot/js/app/internal/custommaps/resgrid.custommaps.regioneditor.js
  • Web/Resgrid.Web/wwwroot/js/app/internal/indoormaps/resgrid.indoormaps.editor.js
  • Web/Resgrid.Web/wwwroot/js/app/internal/indoormaps/resgrid.indoormaps.index.js
  • Web/Resgrid.Web/wwwroot/js/app/internal/indoormaps/resgrid.indoormaps.zoneeditor.js
  • Web/Resgrid.Web/wwwroot/js/app/internal/routes/resgrid.routes.activeroutes.js
  • Web/Resgrid.Web/wwwroot/js/app/internal/routes/resgrid.routes.edit.js
  • Web/Resgrid.Web/wwwroot/js/app/internal/routes/resgrid.routes.index.js
  • Web/Resgrid.Web/wwwroot/js/app/internal/routes/resgrid.routes.instancedetail.js
  • Web/Resgrid.Web/wwwroot/js/app/internal/routes/resgrid.routes.new.js
  • Web/Resgrid.Web/wwwroot/js/app/internal/routes/resgrid.routes.view.js

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • ✅ Review completed - (🔄 Check again to review again)
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch develop
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

You can customize the high-level summary generated by CodeRabbit.

Configure the reviews.high_level_summary_instructions setting to provide custom instructions for generating the high-level summary.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces route planning and indoor/custom map capabilities across the web UI, API, claims/permissions, data repositories, and database migrations, plus a few telemetry and UI updates.

Changes:

  • Adds Route Plans/Stops/Schedules/Instances/Deviations domain + repositories + UI pages.
  • Adds Indoor Maps + Custom Maps (layers/tiles/imports) models, repositories, migrations, and dispatch “indoor location” selection.
  • Updates telemetry integrations (Sentry/Countly) and small UI/navigation adjustments.

Reviewed changes

Copilot reviewed 174 out of 175 changed files in this pull request and generated 12 comments.

Show a summary per file
FileDescription
Web/Resgrid.Web/wwwroot/js/app/internal/routes/resgrid.routes.view.jsRoute detail map rendering (geometry + stops).
Web/Resgrid.Web/wwwroot/js/app/internal/routes/resgrid.routes.new.jsNew route map initialization.
Web/Resgrid.Web/wwwroot/js/app/internal/routes/resgrid.routes.instancedetail.jsRoute instance detail map markers.
Web/Resgrid.Web/wwwroot/js/app/internal/routes/resgrid.routes.index.jsRoutes table DataTables setup.
Web/Resgrid.Web/wwwroot/js/app/internal/routes/resgrid.routes.edit.jsRoute edit map stop markers.
Web/Resgrid.Web/wwwroot/js/app/internal/routes/resgrid.routes.activeroutes.jsActive routes page auto-refresh.
Web/Resgrid.Web/wwwroot/js/app/internal/indoormaps/resgrid.indoormaps.index.jsIndoor maps table DataTables setup.
Web/Resgrid.Web/wwwroot/js/app/internal/indoormaps/resgrid.indoormaps.editor.jsIndoor map bounds editor (Leaflet rectangle).
Web/Resgrid.Web/wwwroot/js/app/internal/custommaps/resgrid.custommaps.index.jsCustom maps table DataTables setup.
Web/Resgrid.Web/wwwroot/js/app/internal/custommaps/resgrid.custommaps.import.jsClient-side import file extension validation.
Web/Resgrid.Web/wwwroot/js/app/internal/custommaps/resgrid.custommaps.editor.jsCustom map bounds editor using Leaflet.draw.
Web/Resgrid.Web/wwwroot/js/app/common/analytics/resgrid.common.analytics.jsUpdates Countly integration calls.
Web/Resgrid.Web/Startup.csAdds route authorization policies.
Web/Resgrid.Web/Helpers/ClaimsAuthorizationHelper.csAdds helper methods for route permission checks.
Web/Resgrid.Web/Areas/User/Views/Shared/_UserLayout.cshtmlUpdates Sentry/Countly init blocks; removes PostHog block.
Web/Resgrid.Web/Areas/User/Views/Routes/View.cshtmlNew route detail view + map script variables.
Web/Resgrid.Web/Areas/User/Views/Routes/New.cshtmlNew route creation view.
Web/Resgrid.Web/Areas/User/Views/Routes/Instances.cshtmlRoute history (instances) view.
Web/Resgrid.Web/Areas/User/Views/Routes/InstanceDetail.cshtmlRoute instance detail view + timeline + map variables.
Web/Resgrid.Web/Areas/User/Views/Routes/Index.cshtmlRoutes index list view.
Web/Resgrid.Web/Areas/User/Views/Routes/ActiveRoutes.cshtmlActive routes dashboard/cards.
Web/Resgrid.Web/Areas/User/Views/Mapping/Index.cshtmlAdds navigation entry to Custom Maps.
Web/Resgrid.Web/Areas/User/Views/IndoorMaps/New.cshtmlAdds indoor map create view (bounds map).
Web/Resgrid.Web/Areas/User/Views/IndoorMaps/Index.cshtmlAdds indoor maps index view.
Web/Resgrid.Web/Areas/User/Views/IndoorMaps/Floors.cshtmlAdds indoor map floors management view.
Web/Resgrid.Web/Areas/User/Views/IndoorMaps/Edit.cshtmlAdds indoor map edit view (bounds map).
Web/Resgrid.Web/Areas/User/Views/Dispatch/UpdateCall.cshtmlAdds Select2 indoor location search + hidden fields.
Web/Resgrid.Web/Areas/User/Views/Dispatch/NewCall.cshtmlAdds Select2 indoor location search + hidden fields.
Web/Resgrid.Web/Areas/User/Views/Dispatch/Dashboard.cshtmlAdds Routes button (conditional) and renames New Call button id.
Web/Resgrid.Web/Areas/User/Views/CustomMaps/New.cshtmlAdds custom map creation view + Leaflet/Draw assets.
Web/Resgrid.Web/Areas/User/Views/CustomMaps/Layers.cshtmlAdds custom map layer management view.
Web/Resgrid.Web/Areas/User/Views/CustomMaps/Index.cshtmlAdds custom maps index + filter tabs.
Web/Resgrid.Web/Areas/User/Views/CustomMaps/Import.cshtmlAdds custom map import upload + import history view.
Web/Resgrid.Web/Areas/User/Views/CustomMaps/Edit.cshtmlAdds custom map edit view + Leaflet/Draw assets.
Web/Resgrid.Web/Areas/User/Models/Routes/RouteViewModels.csAdds route UI view models.
Web/Resgrid.Web/Areas/User/Models/IndoorMaps/IndoorMapZoneEditorView.csAdds indoor zone editor view model.
Web/Resgrid.Web/Areas/User/Models/IndoorMaps/IndoorMapNewView.csAdds indoor map create/edit view model.
Web/Resgrid.Web/Areas/User/Models/IndoorMaps/IndoorMapIndexView.csAdds indoor map index view model.
Web/Resgrid.Web/Areas/User/Models/IndoorMaps/IndoorMapFloorsView.csAdds indoor map floors view model.
Web/Resgrid.Web/Areas/User/Models/CustomMaps/CustomMapRegionEditorView.csAdds custom map region editor view model.
Web/Resgrid.Web/Areas/User/Models/CustomMaps/CustomMapNewView.csAdds custom map create/edit view model.
Web/Resgrid.Web/Areas/User/Models/CustomMaps/CustomMapLayersView.csAdds custom map layers view model.
Web/Resgrid.Web/Areas/User/Models/CustomMaps/CustomMapIndexView.csAdds custom map index/filter view model.
Web/Resgrid.Web/Areas/User/Models/CustomMaps/CustomMapImportView.csAdds custom map import view model.
Web/Resgrid.Web/Areas/User/Controllers/IndoorMapsController.csRedirects indoor map routes to CustomMaps equivalents.
Web/Resgrid.Web/Areas/User/Controllers/DispatchController.csPersists indoor location fields on call create/update.
Web/Resgrid.Web/Areas/User/Controllers/ContactsController.csAdds guard when parsing entrance GPS coordinates.
Web/Resgrid.Web.Services/Startup.csAdds route authorization policies for services host.
Web/Resgrid.Web.Services/Models/v4/Routes/RouteInputModels.csAdds v4 route API input models.
Web/Resgrid.Web.Services/Models/v4/Mapping/IndoorMapZoneResultData.csAdds v4 indoor zone response DTO.
Web/Resgrid.Web.Services/Models/v4/Mapping/IndoorMapResultData.csAdds v4 indoor map response DTO.
Web/Resgrid.Web.Services/Models/v4/Mapping/IndoorMapFloorResultData.csAdds v4 indoor floor response DTO.
Web/Resgrid.Web.Services/Models/v4/Mapping/GetIndoorMapsResult.csAdds v4 indoor maps result wrappers.
Web/Resgrid.Web.Services/Models/v4/Mapping/GetCustomMapsResult.csAdds v4 custom maps result wrappers.
Web/Resgrid.Web.Services/Models/v4/Mapping/CustomMapResultData.csAdds v4 custom map response DTO.
Web/Resgrid.Web.Services/Models/v4/Mapping/CustomMapRegionResultData.csAdds v4 custom map region response DTO.
Web/Resgrid.Web.Services/Models/v4/Mapping/CustomMapLayerResultData.csAdds v4 custom map layer response DTO.
Web/Resgrid.Web.Services/Models/v4/Calls/NewCallInput.csExtends v4 call create input with indoor IDs.
Web/Resgrid.Web.Services/Controllers/v4/CallsController.csWrites indoor IDs into Call entity during SaveCall.
Repositories/Resgrid.Repositories.DataRepository/RouteStopsRepository.csAdds Dapper queries for route stops.
Repositories/Resgrid.Repositories.DataRepository/RouteSchedulesRepository.csAdds Dapper queries for route schedules.
Repositories/Resgrid.Repositories.DataRepository/RoutePlansRepository.csAdds Dapper queries for route plans.
Repositories/Resgrid.Repositories.DataRepository/RouteInstancesRepository.csAdds Dapper queries for route instances.
Repositories/Resgrid.Repositories.DataRepository/RouteInstanceStopsRepository.csAdds Dapper queries for instance stops.
Repositories/Resgrid.Repositories.DataRepository/RouteDeviationsRepository.csAdds Dapper queries for deviations.
Repositories/Resgrid.Repositories.DataRepository/RepositoryBase.csAdjusts “new entity” detection for string IDs.
Repositories/Resgrid.Repositories.DataRepository/Queries/Routes/SelectUnacknowledgedRouteDeviationsByDepartmentQuery.csAdds SQL query wrapper for unacknowledged deviations.
Repositories/Resgrid.Repositories.DataRepository/Queries/Routes/SelectRouteStopsByRoutePlanIdQuery.csAdds SQL query wrapper for route stops by plan.
Repositories/Resgrid.Repositories.DataRepository/Queries/Routes/SelectRouteStopsByCallIdQuery.csAdds SQL query wrapper for route stops by call.
Repositories/Resgrid.Repositories.DataRepository/Queries/Routes/SelectRouteSchedulesByRoutePlanIdQuery.csAdds SQL query wrapper for schedules by plan.
Repositories/Resgrid.Repositories.DataRepository/Queries/Routes/SelectRoutePlansByUnitIdQuery.csAdds SQL query wrapper for plans by unit.
Repositories/Resgrid.Repositories.DataRepository/Queries/Routes/SelectRoutePlansByDepartmentIdQuery.csAdds SQL query wrapper for plans by department.
Repositories/Resgrid.Repositories.DataRepository/Queries/Routes/SelectRouteInstancesByRoutePlanIdQuery.csAdds SQL query wrapper for instances by plan.
Repositories/Resgrid.Repositories.DataRepository/Queries/Routes/SelectRouteInstancesByDepartmentIdQuery.csAdds SQL query wrapper for instances by department.
Repositories/Resgrid.Repositories.DataRepository/Queries/Routes/SelectRouteInstancesByDateRangeQuery.csAdds SQL query wrapper for instances by date range.
Repositories/Resgrid.Repositories.DataRepository/Queries/Routes/SelectRouteInstanceStopsByRouteInstanceIdQuery.csAdds SQL query wrapper for instance stops by instance.
Repositories/Resgrid.Repositories.DataRepository/Queries/Routes/SelectRouteDeviationsByRouteInstanceIdQuery.csAdds SQL query wrapper for deviations by instance.
Repositories/Resgrid.Repositories.DataRepository/Queries/Routes/SelectActiveSchedulesDueQuery.csAdds SQL query wrapper for due schedules.
Repositories/Resgrid.Repositories.DataRepository/Queries/Routes/SelectActiveRoutePlansByDepartmentIdQuery.csAdds SQL query wrapper for active plans.
Repositories/Resgrid.Repositories.DataRepository/Queries/Routes/SelectActiveRouteInstancesByUnitIdQuery.csAdds SQL query wrapper for active instances by unit.
Repositories/Resgrid.Repositories.DataRepository/Queries/IndoorMaps/SelectIndoorMapsByDepartmentIdQuery.csAdds SQL query wrapper for indoor maps by department.
Repositories/Resgrid.Repositories.DataRepository/Queries/IndoorMaps/SelectIndoorMapZonesByFloorIdQuery.csAdds SQL query wrapper for zones by floor.
Repositories/Resgrid.Repositories.DataRepository/Queries/IndoorMaps/SelectIndoorMapFloorsByMapIdQuery.csAdds SQL query wrapper for floors by map.
Repositories/Resgrid.Repositories.DataRepository/Queries/IndoorMaps/SearchIndoorMapZonesQuery.csAdds SQL query wrapper for zone search.
Repositories/Resgrid.Repositories.DataRepository/Queries/CustomMaps/SelectPendingCustomMapImportsQuery.csAdds SQL query wrapper for pending imports.
Repositories/Resgrid.Repositories.DataRepository/Queries/CustomMaps/SelectCustomMapTilesForLayerQuery.csAdds SQL query wrapper for tiles by layer.
Repositories/Resgrid.Repositories.DataRepository/Queries/CustomMaps/SelectCustomMapTileQuery.csAdds SQL query wrapper for a specific tile.
Repositories/Resgrid.Repositories.DataRepository/Queries/CustomMaps/SelectCustomMapImportsForMapQuery.csAdds SQL query wrapper for imports by map.
Repositories/Resgrid.Repositories.DataRepository/Queries/CustomMaps/DeleteCustomMapTilesForLayerQuery.csAdds SQL query wrapper to delete tiles by layer.
Repositories/Resgrid.Repositories.DataRepository/Modules/TestingDataModule.csRegisters indoor/custom map + route repositories for tests.
Repositories/Resgrid.Repositories.DataRepository/Modules/NonWebDataModule.csRegisters indoor/custom map + route repositories (non-web).
Repositories/Resgrid.Repositories.DataRepository/Modules/DataModule.csRegisters indoor/custom map + route repositories (web).
Repositories/Resgrid.Repositories.DataRepository/Modules/ApiDataModule.csRegisters indoor/custom map + route repositories (API).
Repositories/Resgrid.Repositories.DataRepository/IndoorMapsRepository.csAdds repository for indoor maps (department scoped).
Repositories/Resgrid.Repositories.DataRepository/IndoorMapZonesRepository.csAdds repository for zones + search.
Repositories/Resgrid.Repositories.DataRepository/IndoorMapFloorsRepository.csAdds repository for floors by map.
Repositories/Resgrid.Repositories.DataRepository/CustomMapTilesRepository.csAdds repository for tile fetch/list/delete.
Repositories/Resgrid.Repositories.DataRepository/CustomMapImportsRepository.csAdds repository for imports by map + pending imports.
Repositories/Resgrid.Repositories.DataRepository/Configs/SqlConfiguration.csAdds SQL config properties for indoor/custom maps + routes.
Providers/Resgrid.Providers.MigrationsPg/Migrations/M0052_AddingCustomMapSupportPg.csPostgres migration for custom map support.
Providers/Resgrid.Providers.Migrations/Migrations/M0052_AddingCustomMapSupport.csSQL Server migration for custom map support.
Providers/Resgrid.Providers.Migrations/Migrations/M0051_AddingIndoorMaps.csSQL Server migration for indoor maps + call columns.
Providers/Resgrid.Providers.Claims/ResgridResources.csAdds Route_* authorization policy names.
Providers/Resgrid.Providers.Claims/ResgridIdentity.csAdds route-claims helper method.
Providers/Resgrid.Providers.Claims/ResgridClaimTypes.csAdds Route resource claim type.
Providers/Resgrid.Providers.Claims/JwtTokenProvider.csIncludes route claims in JWT generation.
Providers/Resgrid.Providers.Claims/ClaimsPrincipalFactory.csIncludes route claims in cookie principal generation.
Providers/Resgrid.Providers.Claims/ClaimsLogic.csImplements AddRouteClaims logic.
Core/Resgrid.Services/ServicesModule.csRegisters IndoorMap/CustomMap/Route services in DI.
Core/Resgrid.Services/Resgrid.Services.csprojAdds ImageSharp dependency (tile processing).
Core/Resgrid.Services/IndoorMapService.csAdds indoor map CRUD + search service implementation.
Core/Resgrid.Services/CallsService.csEnriches calls using indoor zone info (address + geo).
Core/Resgrid.Model/Services/IRouteService.csAdds route service contract.
Core/Resgrid.Model/Services/IIndoorMapService.csAdds indoor map service contract.
Core/Resgrid.Model/Services/ICustomMapService.csAdds custom map service contract (tiles/imports).
Core/Resgrid.Model/RouteStopType.csAdds route stop type enum.
Core/Resgrid.Model/RouteStopPriority.csAdds route stop priority enum.
Core/Resgrid.Model/RouteStopCheckInType.csAdds route check-in type enum.
Core/Resgrid.Model/RouteStop.csAdds route stop entity.
Core/Resgrid.Model/RouteStatus.csAdds route plan status enum.
Core/Resgrid.Model/RouteSchedule.csAdds route schedule entity.
Core/Resgrid.Model/RouteRecurrenceType.csAdds schedule recurrence enum.
Core/Resgrid.Model/RoutePlan.csAdds route plan entity.
Core/Resgrid.Model/RouteInstanceStop.csAdds route instance stop entity.
Core/Resgrid.Model/RouteInstanceStatus.csAdds route instance status enum.
Core/Resgrid.Model/RouteInstance.csAdds route instance entity.
Core/Resgrid.Model/RouteDeviation.csAdds route deviation entity.
Core/Resgrid.Model/Repositories/IRouteStopsRepository.csAdds route stops repository contract.
Core/Resgrid.Model/Repositories/IRouteSchedulesRepository.csAdds route schedules repository contract.
Core/Resgrid.Model/Repositories/IRoutePlansRepository.csAdds route plans repository contract.
Core/Resgrid.Model/Repositories/IRouteInstancesRepository.csAdds route instances repository contract.
Core/Resgrid.Model/Repositories/IRouteInstanceStopsRepository.csAdds route instance stops repository contract.
Core/Resgrid.Model/Repositories/IRouteDeviationsRepository.csAdds route deviations repository contract.
Core/Resgrid.Model/Repositories/IIndoorMapsRepository.csAdds indoor maps repository contract.
Core/Resgrid.Model/Repositories/IIndoorMapZonesRepository.csAdds indoor map zones repository contract + search.
Core/Resgrid.Model/Repositories/IIndoorMapFloorsRepository.csAdds indoor map floors repository contract.
Core/Resgrid.Model/Repositories/ICustomMapTilesRepository.csAdds custom map tiles repository contract.
Core/Resgrid.Model/Repositories/ICustomMapImportsRepository.csAdds custom map imports repository contract.
Core/Resgrid.Model/PermissionTypes.csAdds CreateRoute/ManageRoutes permission types.
Core/Resgrid.Model/IndoorMapZoneType.csAdds indoor map zone type enum.
Core/Resgrid.Model/IndoorMapZone.csAdds indoor map zone entity (incl. dispatchable flag).
Core/Resgrid.Model/IndoorMapFloor.csAdds indoor map floor entity (incl. tiling fields).
Core/Resgrid.Model/IndoorMap.csAdds indoor map entity (incl. custom map fields).
Core/Resgrid.Model/DepartmentNotification.csAdjusts notification display strings (“None” → “Any”).
Core/Resgrid.Model/CustomMapType.csAdds custom map type enum.
Core/Resgrid.Model/CustomMapTile.csAdds custom map tile entity.
Core/Resgrid.Model/CustomMapLayerType.csAdds custom map layer type enum.
Core/Resgrid.Model/CustomMapImportStatus.csAdds import status enum.
Core/Resgrid.Model/CustomMapImportFileType.csAdds import file type enum.
Core/Resgrid.Model/CustomMapImport.csAdds import tracking entity.
Core/Resgrid.Model/Call.csAdds IndoorMapZoneId/IndoorMapFloorId fields to calls.
Core/Resgrid.Model/AuditLogTypes.csAdds audit log types for route planning lifecycle.
.gitignoreIgnores .dual-graph/.

Comment on lines +66 to +73
@section Scripts {
<script>
$(document).ready(function () {
$('#indoorMapsTable').DataTable({
pageLength: 25
});
});
</script>
Comment on lines +94 to +96
var initialLat = @(Model.Map.CenterLatitude != 0 ? Model.Map.CenterLatitude.ToString() : "39.7392");
var initialLon = @(Model.Map.CenterLongitude != 0 ? Model.Map.CenterLongitude.ToString() : "-104.9903");
</script>
Comment on lines +94 to +96
<script>
var initialLat = @Model.Map.CenterLatitude;
var initialLon = @Model.Map.CenterLongitude;
Comment on lines +21 to +23
var marker = L.marker([stop.lat, stop.lng]).addTo(map);
marker.bindPopup('<strong>' + (index + 1) + '. ' + stop.Name + '</strong>');
group.push(marker);
Comment on lines +33 to +38
routeStops.forEach(function (stop, index) {
if (stop.lat && stop.lng) {
var marker = L.marker([stop.lat, stop.lng]).addTo(map);
marker.bindPopup('<strong>' + (index + 1) + '. ' + stop.Name + '</strong>');
group.push(marker);
}
Comment on lines +1557 to +1561
if (permissions != null && permissions.Any(x => x.PermissionType == (int)PermissionTypes.ManageRoutes))
{
var permission = permissions.First(x => x.PermissionType == (int)PermissionTypes.ManageRoutes);

if (permission.Action == (int)PermissionActions.DepartmentAdminsOnly)
Comment on lines +35 to +37
var marker = L.marker([stop.lat, stop.lng]).addTo(map);
marker.bindPopup('<strong>' + (index + 1) + '. ' + stop.Name + '</strong>');
group.push(marker);
Comment on lines +19 to +25
instanceStops.forEach(function (stop, index) {
if (stop.lat && stop.lng) {
var statusText = ['Pending', 'Checked In', 'Completed', 'Skipped'][stop.Status] || 'Unknown';
var marker = L.marker([stop.lat, stop.lng]).addTo(map);
marker.bindPopup('<strong>Stop ' + (stop.StopOrder + 1) + '</strong><br/>' + statusText);
group.push(marker);
}
Comment on lines +79 to +81
var routeStops = @Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(Model.Stops.OrderBy(s => s.StopOrder).Select(s => new { s.Name, lat = s.Latitude, lng = s.Longitude })));
var routeGeometry = '@Html.Raw(Model.Plan.MapboxRouteGeometry ?? "")';
var routeColor = '@Html.Raw(Model.Plan.RouteColor ?? "#3388ff")';
Comment on lines +620 to +627
// Indoor map zone
var indoorMapZoneId = collection["IndoorMapZoneId"].FirstOrDefault();
var indoorMapFloorId = collection["IndoorMapFloorId"].FirstOrDefault();
if (!String.IsNullOrWhiteSpace(indoorMapZoneId))
{
call.IndoorMapZoneId = indoorMapZoneId;
call.IndoorMapFloorId = indoorMapFloorId;
}
@ucswift

Copy link
Copy Markdown
MemberAuthor

Approve

@github-actionsgithub-actionsBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR is approved.

@ucswift
ucswift merged commit 1e4c5be into masterMar 17, 2026
20 of 23 checks passed
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@ucswift@github-advanced-security