using System.Text;
using Microsoft.AspNetCore.Mvc;
using SQLInsight.Contracts;
using SQLInsight.Repository;
namespace SQLInsight.Web;
///
/// Support cases with SEOSoft (Professional/Enterprise). The form posts here; the request is stored in the repository
/// and the agent sends it to SQLInsight Hub, which gives it a case number. The web UI never talks to the hub itself.
///
public static class Support
{
public static void Map(IEndpointRouteBuilder app) => app.MapPost("/support", CreateAsync);
/// Title and description for a case about . Sensitive measurements are left out.
public static (string Title, string Description) Prefill(StoredFinding finding)
{
ArgumentNullException.ThrowIfNull(finding);
var text = new StringBuilder();
text.Append("Instans: ").Append(finding.InstanceName).Append('\n');
text.Append("Regel: ").Append(finding.RuleId).Append('\n');
text.Append("Alvor: ").Append(Display.SeverityName(finding.Severity)).Append('\n');
if (!string.IsNullOrEmpty(finding.Subject))
{
text.Append("Emne: ").Append(finding.Subject).Append('\n');
}
text.Append('\n').Append(finding.Explanation).Append('\n');
var evidence = finding.Evidence.Where(e => !e.Sensitive).Take(10).ToList();
if (evidence.Count > 0)
{
text.Append("\nMålinger:\n");
foreach (var e in evidence)
{
text.Append("- ").Append(e.Name).Append(": ").Append(e.Value.Length > 200 ? e.Value[..200] + "…" : e.Value).Append('\n');
}
}
text.Append("\nHvad har I prøvet, og hvad har ændret sig?\n");
var title = finding.Title.Length > SupportCaseRequest.MaxTitle ? finding.Title[..SupportCaseRequest.MaxTitle] : finding.Title;
var description = text.ToString();
return (title, description.Length > SupportCaseRequest.MaxDescription ? description[..SupportCaseRequest.MaxDescription] : description);
}
/// The user part of DOMAIN\user, as a starting point for the contact name.
public static string ContactNameFrom(string? windowsUser) =>
windowsUser is { Length: > 0 } user ? user[(user.LastIndexOf('\\') + 1)..] : string.Empty;
public static string StatusText(SupportCaseRow row)
{
ArgumentNullException.ThrowIfNull(row);
return row.Status switch
{
SupportCaseStatus.Pending => row.Attempts > 0 ? "Venter på hubben (prøver igen)" : "Sendes",
SupportCaseStatus.Open => "Åben",
SupportCaseStatus.Closed => "Lukket",
_ => "Afvist",
};
}
private static async Task CreateAsync(
HttpContext http, InsightRepository repository,
[FromForm] string? title, [FromForm] string? description, [FromForm] string? contactName, [FromForm] string? contactEmail,
[FromForm] string? contactPhone, [FromForm] long? findingId)
{
var back = findingId is { } id ? $"&fund={id}" : string.Empty;
if ((await repository.GetHubStatusAsync(http.RequestAborted))?.AllowsSupportCases != true)
{
return Results.Redirect("/support?fejl=" + Uri.EscapeDataString("Supportsager kræver Professional eller Enterprise og at deling med SQLInsight Hub er slået til."));
}
var finding = findingId is { } fid ? await repository.GetFindingAsync(fid, http.RequestAborted) : null;
var request = new SupportCaseRequest(Guid.NewGuid(), title?.Trim() ?? string.Empty, Blank(description), contactName?.Trim() ?? string.Empty,
contactEmail?.Trim() ?? string.Empty, Blank(contactPhone), http.User.Identity?.Name, finding?.InstanceName, finding?.RuleId, finding?.Subject);
if (request.Validate() is { } invalid)
{
return Results.Redirect("/support?fejl=" + Uri.EscapeDataString(invalid) + back);
}
await repository.AddSupportRequestAsync(new NewSupportRequest(request.ClientRequestId, request.Title, request.Description, request.ContactName,
request.ContactEmail, request.ContactPhone, request.RequestedBy, finding?.FindingId, finding?.InstanceName, finding?.RuleId, finding?.Subject),
DateTimeOffset.UtcNow, http.RequestAborted);
return Results.Redirect("/support?sendt=1");
}
private static string? Blank(string? value) => string.IsNullOrWhiteSpace(value) ? null : value.Trim();
}