using System.Text.Json; using Backend.Contracts; using Backend.Domain; namespace Backend.Endpoints; public static class AdminRiskFlagMappings { public static AdminRiskFlagDto ToDto(RiskFlag item) => new( item.Id, item.Source, item.Type, item.Severity, item.Status, item.Summary, item.TwitchUserId, item.CreatedFromIp, item.CreatedAt, item.MetadataJson, item.ReviewNote, item.ReviewedByTwitchId, item.ReviewedAt, BuildEntityLinks(item)); public static AdminRiskEntityLinkDto[] BuildEntityLinks(RiskFlag item) { var links = ReadExplicitLinks(item.MetadataJson).ToList(); if (links.Count > 0) { return links.ToArray(); } var query = Uri.EscapeDataString(item.TwitchUserId ?? item.Summary); return item.Source.ToLowerInvariant() switch { "clip" => [new AdminRiskEntityLinkDto("Clips öffnen", "clip", item.TwitchUserId ?? item.Id.ToString(), $"/admin/clips?query={query}")], "nomination" => [new AdminRiskEntityLinkDto("Reviews öffnen", "nomination", item.TwitchUserId ?? item.Id.ToString(), $"/admin/reviews?query={query}")], "vote" => [new AdminRiskEntityLinkDto("Voting-Analytics öffnen", "vote", item.TwitchUserId ?? item.Id.ToString(), $"/admin/analytics?query={query}")], "login" => [new AdminRiskEntityLinkDto("Audit-Log öffnen", "session", item.TwitchUserId ?? item.Id.ToString(), $"/admin/users-logs?query={query}")], _ => [], }; } private static IEnumerable ReadExplicitLinks(string metadataJson) { if (string.IsNullOrWhiteSpace(metadataJson)) { yield break; } JsonDocument document; try { document = JsonDocument.Parse(metadataJson); } catch (JsonException) { yield break; } using (document) { if (TryReadEntityLinks(document.RootElement, out var entityLinks)) { foreach (var link in entityLinks) { yield return link; } } } } private static bool TryReadEntityLinks(JsonElement root, out AdminRiskEntityLinkDto[] links) { links = []; if (root.ValueKind != JsonValueKind.Object || !TryGetProperty(root, "entityLinks", out var entityLinks) || entityLinks.ValueKind != JsonValueKind.Array) { return false; } links = entityLinks.EnumerateArray() .Where(item => item.ValueKind == JsonValueKind.Object) .Select(item => new AdminRiskEntityLinkDto( ReadString(item, "label"), ReadString(item, "entityType"), ReadString(item, "entityId"), ReadString(item, "to"))) .Where(item => !string.IsNullOrWhiteSpace(item.Label) && !string.IsNullOrWhiteSpace(item.To)) .ToArray(); return links.Length > 0; } private static bool TryGetProperty(JsonElement root, string propertyName, out JsonElement value) { foreach (var property in root.EnumerateObject()) { if (string.Equals(property.Name, propertyName, StringComparison.OrdinalIgnoreCase)) { value = property.Value; return true; } } value = default; return false; } private static string ReadString(JsonElement root, string propertyName) { if (!TryGetProperty(root, propertyName, out var value)) { return string.Empty; } return value.ValueKind switch { JsonValueKind.String => value.GetString() ?? string.Empty, JsonValueKind.Number => value.GetRawText(), _ => string.Empty, }; } }