feat(audit): multi-value filters across ManagementService, CLI and Central UI
This commit is contained in:
@@ -9,15 +9,18 @@ namespace ScadaLink.CLI.Commands;
|
||||
/// Filter arguments for an <c>audit query</c> invocation. Mirrors the Bundle B
|
||||
/// <c>GET /api/audit/query</c> filter parameters; <see cref="Since"/>/<see cref="Until"/>
|
||||
/// are time-specs (relative like <c>1h</c>/<c>7d</c>, or absolute ISO-8601).
|
||||
/// <see cref="Channel"/>/<see cref="Kind"/>/<see cref="Status"/>/<see cref="Site"/>
|
||||
/// are multi-valued — each supplied value becomes a repeated query-string param so
|
||||
/// the server's multi-value <c>IN (…)</c> filter sees the full set.
|
||||
/// </summary>
|
||||
public sealed class AuditQueryArgs
|
||||
{
|
||||
public string? Since { get; set; }
|
||||
public string? Until { get; set; }
|
||||
public string? Channel { get; set; }
|
||||
public string? Kind { get; set; }
|
||||
public string? Status { get; set; }
|
||||
public string? Site { get; set; }
|
||||
public string[] Channel { get; set; } = Array.Empty<string>();
|
||||
public string[] Kind { get; set; } = Array.Empty<string>();
|
||||
public string[] Status { get; set; } = Array.Empty<string>();
|
||||
public string[] Site { get; set; } = Array.Empty<string>();
|
||||
public string? Target { get; set; }
|
||||
public string? Actor { get; set; }
|
||||
public string? CorrelationId { get; set; }
|
||||
@@ -73,8 +76,11 @@ public static class AuditQueryHelpers
|
||||
|
||||
/// <summary>
|
||||
/// Builds the <c>?...</c> query string for <c>GET /api/audit/query</c> from the filter
|
||||
/// args plus an optional keyset cursor. Unset filters are omitted. <c>--errors-only</c>
|
||||
/// maps to <c>status=Failed</c> (the server takes a single status value).
|
||||
/// args plus an optional keyset cursor. Unset filters are omitted. The multi-valued
|
||||
/// <c>--channel</c>/<c>--kind</c>/<c>--status</c>/<c>--site</c> filters each emit ONE
|
||||
/// repeated query-string key per value (e.g. <c>channel=A&channel=B</c>) so the
|
||||
/// server's multi-value <c>IN (…)</c> filter receives the full set. <c>--errors-only</c>
|
||||
/// maps to a single <c>status=Failed</c> and overrides any explicit <c>--status</c>.
|
||||
/// </summary>
|
||||
public static string BuildQueryString(
|
||||
AuditQueryArgs args, DateTimeOffset now, DateTimeOffset? afterOccurredAtUtc, string? afterEventId)
|
||||
@@ -87,20 +93,35 @@ public static class AuditQueryHelpers
|
||||
parts.Add($"{key}={Uri.EscapeDataString(value)}");
|
||||
}
|
||||
|
||||
void AddEach(string key, IReadOnlyList<string> values)
|
||||
{
|
||||
foreach (var value in values)
|
||||
{
|
||||
Add(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(args.Since))
|
||||
Add("fromUtc", ResolveTimeSpec(args.Since!, now).ToString("o", CultureInfo.InvariantCulture));
|
||||
if (!string.IsNullOrWhiteSpace(args.Until))
|
||||
Add("toUtc", ResolveTimeSpec(args.Until!, now).ToString("o", CultureInfo.InvariantCulture));
|
||||
|
||||
Add("channel", args.Channel);
|
||||
Add("kind", args.Kind);
|
||||
AddEach("channel", args.Channel);
|
||||
AddEach("kind", args.Kind);
|
||||
|
||||
// --errors-only is a convenience shorthand for the single-value Failed status
|
||||
// filter. The server's status filter accepts one value, so --errors-only and an
|
||||
// explicit --status are mutually exclusive in effect; --errors-only wins.
|
||||
Add("status", args.ErrorsOnly ? "Failed" : args.Status);
|
||||
// --errors-only is a convenience shorthand for the Failed status filter. The
|
||||
// server's status filter is multi-value, but --errors-only stays a single-status
|
||||
// override: it pins status=Failed and supersedes any explicit --status values.
|
||||
if (args.ErrorsOnly)
|
||||
{
|
||||
Add("status", "Failed");
|
||||
}
|
||||
else
|
||||
{
|
||||
AddEach("status", args.Status);
|
||||
}
|
||||
|
||||
Add("sourceSiteId", args.Site);
|
||||
AddEach("sourceSiteId", args.Site);
|
||||
Add("target", args.Target);
|
||||
Add("actor", args.Actor);
|
||||
Add("correlationId", args.CorrelationId);
|
||||
|
||||
Reference in New Issue
Block a user