sqlinsight-pro/src/SQLInsight.Web/Components/Pages/ServerFindingDetail.razor
Søren Eggert Lundsteen Olsen 1c18bcfab8 Web: Windows-servere and Syntetiske tjek pages, and the same in API v1 (scope config:write)
- Menu group "Servere" with Windows-servere (/servere) and Syntetiske tjek
  (/syntetiske-tjek).
- /servere: every server with status (overvåges, delvist målbar, kan ikke læses),
  CPU, free memory, the fullest disk and the nearest "fuld om ca. N dage", findings;
  add application/AOS/file servers. /servere/{id}: findings and what is not
  measurable and why, CPU/memory for the last day, disks with forecasts, watched
  and stopped services, grouped event log errors, scheduled tasks, rights per area
  with the latest test, the least-privilege PowerShell script (copy or download,
  UTF-8 with BOM), role and service lists, pause and remove. /servere/fund/{id}.
- /syntetiske-tjek: checks with status and response time; one form for every kind
  (TCP, HTTP(S), SQL login + query, DNS, AX logon) with an optional server and
  service; a SQL login password is sealed for the agent at once and never shown.
  /syntetiske-tjek/{id}: latest result (incl. "kun porten er testet"), findings,
  response times, history, edit, run now, pause, remove.
- API v1: /windows-servers (+ test, grant-script, performance, disks, services,
  events, tasks, rule-states), /server-findings, /synthetic-checks (+ run, results,
  rule-states); all in OpenAPI. Passwords are write-only; event samples, failure
  messages and sensitive evidence are "[udeladt]" unless
  SQLInsight:Web:ApiIncludesSensitiveEvidence is on. /api/v1/rules lists the new rules.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-02 14:58:52 +02:00

107 lines
3 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

@page "/servere/fund/{Id:long}"
@inject InsightRepository Repository
@inject Display Display
@if (_finding is null)
{
<PageTitle>Ukendt fund · SQLInsight Pro</PageTitle>
<h1>Ukendt fund</h1>
return;
}
<PageTitle>@_finding.Title · SQLInsight Pro</PageTitle>
<p class="crumbs">
@if (_finding.Scope == FindingScope.Server)
{
<a href="@ServerSetup.ServersPage">Windows-servere</a> <text>/</text> <a href="@ServerSetup.ServerPage(_finding.ScopeId)">@_finding.ScopeName</a>
}
else
{
<a href="@ServerSetup.ChecksPage">Syntetiske tjek</a> <text>/</text> <a href="@ServerSetup.CheckPage(_finding.ScopeId)">@_finding.ScopeName</a>
}
/ @_finding.RuleId
</p>
<h1 data-finding-id="@_finding.FindingId"><SeverityBadge Severity="_finding.Severity" /> @_finding.Title</h1>
<p class="lead">
@if (_finding.ResolvedAt is { } resolved)
{
<span>Løst @Display.Time(resolved) · </span>
}
Set første gang @Display.Time(_finding.FirstSeenAt) · senest @Display.Time(_finding.LastSeenAt)
@if (!string.IsNullOrEmpty(_finding.Subject)) { <span> · @_finding.Subject</span> }
</p>
<section class="panel">
<h2>Hvorfor er det et problem?</h2>
<p>@_finding.Explanation</p>
</section>
@if (_finding.Evidence.Count > 0)
{
<section class="panel">
<h2>Målinger</h2>
<table class="evidence">
@foreach (var e in _finding.Evidence)
{
<tr><th>@e.Name</th><td>@e.Value</td></tr>
}
</table>
</section>
}
<section class="panel recommendation">
<h2>Hvad skal jeg gøre?</h2>
<p>@_finding.Recommendation</p>
<p class="muted">SQLInsight ændrer aldrig noget på serveren: den starter ikke tjenester og rydder ikke op.</p>
</section>
@if (_history.Count > 0)
{
<section class="panel">
<h2>Tidligere</h2>
<ul>
@foreach (var h in _history)
{
<li><a href="@ServerSetup.FindingPage(h.FindingId)">@Display.Time(h.FirstSeenAt) – @(h.ResolvedAt is { } r ? Display.Time(r) : "nu")</a>: @h.Title</li>
}
</ul>
</section>
}
@if (_finding.References.Count > 0)
{
<section class="panel">
<h2>Læs mere</h2>
<ul>
@foreach (var r in _finding.References)
{
<li><a href="@r.Url" rel="noopener noreferrer" target="_blank">@r.Title</a></li>
}
</ul>
</section>
}
@code {
[Parameter] public long Id { get; set; }
[CascadingParameter] private HttpContext? Http { get; set; }
private StoredServerFinding? _finding;
private IReadOnlyList<StoredServerFinding> _history = [];
protected override async Task OnInitializedAsync()
{
_finding = await Repository.GetServerFindingAsync(Id);
if (_finding is null)
{
if (Http is not null)
{
Http.Response.StatusCode = StatusCodes.Status404NotFound;
}
return;
}
_history = await Repository.GetServerFindingHistoryAsync(_finding);
}
}