using System; using System.Collections.Generic; using System.Collections.Immutable; using System.ComponentModel.DataAnnotations; using System.Linq; namespace StellaOps.Scheduler.WebService.EventWebhooks; public sealed record ConselierExportEventRequest( string ExportId, IReadOnlyList ChangedProductKeys, IReadOnlyList? Kev, WebhookEventWindow? Window) { public string ExportId { get; } = ExportId?.Trim() ?? throw new ArgumentNullException(nameof(ExportId)); public IReadOnlyList ChangedProductKeys { get; } = NormalizeList(ChangedProductKeys, nameof(ChangedProductKeys)); public IReadOnlyList Kev { get; } = NormalizeList(Kev, nameof(Kev), allowEmpty: true); public WebhookEventWindow? Window { get; } = Window; private static IReadOnlyList NormalizeList(IReadOnlyList? source, string propertyName, bool allowEmpty = false) { if (source is null) { if (allowEmpty) { return ImmutableArray.Empty; } throw new ValidationException($"{propertyName} must be specified."); } var cleaned = source .Where(item => !string.IsNullOrWhiteSpace(item)) .Select(item => item.Trim()) .Distinct(StringComparer.OrdinalIgnoreCase) .ToArray(); if (!allowEmpty && cleaned.Length == 0) { throw new ValidationException($"{propertyName} must contain at least one value."); } return cleaned; } } public sealed record ExcitorExportEventRequest( string ExportId, IReadOnlyList ChangedClaims, WebhookEventWindow? Window) { public string ExportId { get; } = ExportId?.Trim() ?? throw new ArgumentNullException(nameof(ExportId)); public IReadOnlyList ChangedClaims { get; } = NormalizeClaims(ChangedClaims); public WebhookEventWindow? Window { get; } = Window; private static IReadOnlyList NormalizeClaims(IReadOnlyList? claims) { if (claims is null || claims.Count == 0) { throw new ValidationException("changedClaims must contain at least one entry."); } foreach (var claim in claims) { claim.Validate(); } return claims; } } public sealed record ExcitorClaimChange( string ProductKey, string VulnerabilityId, string Status) { public string ProductKey { get; } = Normalize(ProductKey, nameof(ProductKey)); public string VulnerabilityId { get; } = Normalize(VulnerabilityId, nameof(VulnerabilityId)); public string Status { get; } = Normalize(Status, nameof(Status)); internal void Validate() { _ = ProductKey; _ = VulnerabilityId; _ = Status; } private static string Normalize(string value, string propertyName) { if (string.IsNullOrWhiteSpace(value)) { throw new ValidationException($"{propertyName} must be provided."); } return value.Trim(); } } public sealed record WebhookEventWindow(DateTimeOffset? From, DateTimeOffset? To);