sqlinsight-pro/src/SQLInsight.Web/Components/Pages/ServerFindingDetail.razor
Søren Eggert Lundsteen Olsen 18cd879dbb Review 1.5: server and check pages: one overview query, paused checks are not run, bad numbers refused, seconds kept
- /servere reads the overview in one query and says which paused servers and checks are left out of the active
  findings; admin notes use InstanceSetup.WhoMayChangeText as main.
- The check form refuses a port, interval, timeout or limit that is not a number (Danish message) and clamps
  minutes before multiplying; an interval set to part of a minute through the API is shown and kept in seconds.
- "Kør nu" is refused for a paused check (message, no button); ?koersel= shows that run.
- A finding of a removed server or check does not link to a missing page and says why it is not active.
- The forecast text uses the history the forecasts were computed from; the grant script text matches the new
  script (-WhatIf first, -WinRM, -EnableFirewall -AgentAddress, -Remove only what it added).
- HTTP addresses are at most 2000 characters.

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

123 lines
3.7 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>
}
else
{
<a href="@ServerSetup.ChecksPage">Syntetiske tjek</a> <text>/</text>
}
@if (_finding.ScopeRemoved)
{
<span>@_finding.ScopeName</span>
}
else
{
<a href="@(_finding.Scope == FindingScope.Server ? ServerSetup.ServerPage(_finding.ScopeId) : ServerSetup.CheckPage(_finding.ScopeId))">@_finding.ScopeName</a>
}
/ @_finding.RuleId
</p>
@if (_finding.ResolvedAt is null && _finding.ScopeRemoved)
{
<p class="notice" role="note">@(_finding.Scope == FindingScope.Server ? "Serveren" : "Tjekket") er fjernet og overvåges ikke længere. Fundet er historik og løses inden for en time.</p>
}
else if (_finding.ResolvedAt is null && _finding.ScopePaused)
{
<p class="notice" role="note">@(_finding.Scope == FindingScope.Server ? "Serveren" : "Tjekket") er sat på pause, så fundet er ikke med blandt de aktive fund og løses inden for en time.</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);
}
}