mirror of
https://github.com/okieselbach/AutopilotMonitor.git
synced 2026-10-24 12:42:38 +00:00
14a3ce5b9c
- Fix 500 error on download URL: replace GenerateSasUri() with
blobClient.Uri (SAS already embedded in service-level connection string)
- Add AdminNote field to SessionReportMetadata shared model
- Read AdminNote from Table Storage in GetAllReportsAsync
- Add UpdateAdminNoteAsync to SessionReportService
- New PATCH /api/galactic/session-reports/{reportId}/note endpoint
- Frontend: editable Admin Note textarea in report detail modal with
inline save feedback; Admin Note column in reports table with icon
- Add copy-to-clipboard buttons for Session ID, Tenant ID,
Submitted By, and Email fields in report detail modal
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
100 lines
4.3 KiB
C#
100 lines
4.3 KiB
C#
using System.Net;
|
|
using AutopilotMonitor.Functions.Helpers;
|
|
using AutopilotMonitor.Functions.Services;
|
|
using Microsoft.Azure.Functions.Worker;
|
|
using Microsoft.Azure.Functions.Worker.Http;
|
|
using Microsoft.Extensions.Logging;
|
|
using Newtonsoft.Json;
|
|
using Newtonsoft.Json.Linq;
|
|
|
|
namespace AutopilotMonitor.Functions.Functions
|
|
{
|
|
/// <summary>
|
|
/// Allows Galactic Admins to add or update an admin note on a submitted session report.
|
|
/// </summary>
|
|
public class UpdateSessionReportNoteFunction
|
|
{
|
|
private readonly ILogger<UpdateSessionReportNoteFunction> _logger;
|
|
private readonly SessionReportService _sessionReportService;
|
|
private readonly GalacticAdminService _galacticAdminService;
|
|
|
|
public UpdateSessionReportNoteFunction(
|
|
ILogger<UpdateSessionReportNoteFunction> logger,
|
|
SessionReportService sessionReportService,
|
|
GalacticAdminService galacticAdminService)
|
|
{
|
|
_logger = logger;
|
|
_sessionReportService = sessionReportService;
|
|
_galacticAdminService = galacticAdminService;
|
|
}
|
|
|
|
[Function("UpdateSessionReportNote")]
|
|
public async Task<HttpResponseData> Run(
|
|
[HttpTrigger(AuthorizationLevel.Anonymous, "patch", Route = "galactic/session-reports/{reportId}/note")] HttpRequestData req,
|
|
string reportId)
|
|
{
|
|
try
|
|
{
|
|
if (!TenantHelper.IsAuthenticated(req))
|
|
{
|
|
var unauthorizedResponse = req.CreateResponse(HttpStatusCode.Unauthorized);
|
|
await unauthorizedResponse.WriteAsJsonAsync(new { success = false, message = "Authentication required." });
|
|
return unauthorizedResponse;
|
|
}
|
|
|
|
var userIdentifier = TenantHelper.GetUserIdentifier(req);
|
|
var isGalacticAdmin = await _galacticAdminService.IsGalacticAdminAsync(userIdentifier);
|
|
if (!isGalacticAdmin)
|
|
{
|
|
var forbiddenResponse = req.CreateResponse(HttpStatusCode.Forbidden);
|
|
await forbiddenResponse.WriteAsJsonAsync(new { success = false, message = "Access denied. Galactic Admin role required." });
|
|
return forbiddenResponse;
|
|
}
|
|
|
|
if (string.IsNullOrEmpty(reportId))
|
|
{
|
|
var badRequest = req.CreateResponse(HttpStatusCode.BadRequest);
|
|
await badRequest.WriteAsJsonAsync(new { success = false, message = "reportId is required." });
|
|
return badRequest;
|
|
}
|
|
|
|
string body = await req.ReadAsStringAsync() ?? string.Empty;
|
|
JObject json;
|
|
try
|
|
{
|
|
json = JObject.Parse(body);
|
|
}
|
|
catch (JsonException)
|
|
{
|
|
var badRequest = req.CreateResponse(HttpStatusCode.BadRequest);
|
|
await badRequest.WriteAsJsonAsync(new { success = false, message = "Invalid JSON body." });
|
|
return badRequest;
|
|
}
|
|
|
|
var adminNote = json["adminNote"]?.ToString() ?? string.Empty;
|
|
|
|
var updated = await _sessionReportService.UpdateAdminNoteAsync(reportId, adminNote);
|
|
if (!updated)
|
|
{
|
|
var notFoundResponse = req.CreateResponse(HttpStatusCode.NotFound);
|
|
await notFoundResponse.WriteAsJsonAsync(new { success = false, message = "Report not found." });
|
|
return notFoundResponse;
|
|
}
|
|
|
|
_logger.LogInformation("Admin note updated for report {ReportId} by {User}", reportId, userIdentifier);
|
|
|
|
var response = req.CreateResponse(HttpStatusCode.OK);
|
|
await response.WriteAsJsonAsync(new { success = true });
|
|
return response;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError(ex, "Error updating admin note for report {ReportId}", reportId);
|
|
var errorResponse = req.CreateResponse(HttpStatusCode.InternalServerError);
|
|
await errorResponse.WriteAsJsonAsync(new { success = false, message = "Internal server error." });
|
|
return errorResponse;
|
|
}
|
|
}
|
|
}
|
|
}
|