|
- using System.Security.Claims;
- using Campaign_Tracker.Server.Audit;
- using Campaign_Tracker.Server.Authorization;
- using Campaign_Tracker.Server.LegacyData.Schema;
- using Microsoft.AspNetCore.Authorization;
- using Microsoft.AspNetCore.Mvc;
-
- namespace Campaign_Tracker.Server.Controllers;
-
- /// <summary>
- /// Admin-only API for the legacy schema compatibility check (Story 1.7 AC #5).
- /// Exposes a manual trigger and a recent-history view.
- /// </summary>
- [ApiController]
- [Authorize(Policy = ApplicationPolicy.AdminAccess)]
- [Route("api/admin/legacy-schema")]
- public sealed class LegacySchemaController : ControllerBase
- {
- private readonly ILegacySchemaCompatibilityCheck _check;
- private readonly ILegacySchemaCheckHistory _history;
- private readonly IAuditService _audit;
- private readonly TimeProvider _timeProvider;
-
- public LegacySchemaController(
- ILegacySchemaCompatibilityCheck check,
- ILegacySchemaCheckHistory history,
- IAuditService audit,
- TimeProvider timeProvider)
- {
- _check = check;
- _history = history;
- _audit = audit;
- _timeProvider = timeProvider;
- }
-
- [HttpPost("check")]
- public async Task<ActionResult<LegacySchemaCheckResponse>> RunCheck(CancellationToken cancellationToken)
- {
- var result = await _check.RunAsync(cancellationToken);
- _history.Record(result);
-
- var actor = User.Identity?.Name
- ?? User.FindFirstValue(ClaimTypes.NameIdentifier)
- ?? "unknown";
- _audit.Record(new AuditEvent(
- EventType: result.Passed
- ? "LEGACY_SCHEMA_CHECK_PASSED"
- : "LEGACY_SCHEMA_CHECK_FAILED",
- ActorIdentity: actor,
- Resource: "legacy-schema/compatibility-check",
- Outcome: result.Passed ? "pass" : "fail",
- TraceIdentifier: HttpContext.TraceIdentifier,
- RecordedAt: _timeProvider.GetUtcNow()));
-
- return Ok(LegacySchemaCheckResponse.From(result));
- }
-
- [HttpGet("history")]
- public ActionResult<IReadOnlyList<LegacySchemaCheckResponse>> GetHistory([FromQuery] int max = 50)
- {
- var items = _history.GetRecent(max);
- return Ok(items.Select(LegacySchemaCheckResponse.From).ToArray());
- }
- }
-
- public sealed record LegacySchemaCheckResponse(
- bool Passed,
- int TablesVerified,
- int DriftCount,
- DateTimeOffset CheckedAt,
- string BaselineSource,
- IReadOnlyList<LegacySchemaDriftResponse> Drifts)
- {
- public static LegacySchemaCheckResponse From(LegacySchemaCheckResult result) =>
- new(result.Passed,
- result.TablesVerified,
- result.DriftCount,
- result.CheckedAt,
- result.BaselineSource,
- result.Drifts
- .Select(d => new LegacySchemaDriftResponse(
- d.TableName, d.ColumnName, d.ChangeType.ToString(), d.Detail))
- .ToArray());
- }
-
- public sealed record LegacySchemaDriftResponse(
- string TableName,
- string? ColumnName,
- string ChangeType,
- string Detail);
|