Umsetzung von #565. GET /api/updates liefert die laufende Fassung (BuildInfo), die verfuegbare, den Hinweis auf ein Sicherheitsupdate und den Changelog. Geprueft wird mit demselben Aufruf wie beim Start des Desktops (UpdateClient gegen das Deploymentcenter). Den Lizenzschluessel fuer den Paketabruf liest der Server, er verlaesst ihn nicht. Zwischenspeicher: UpdateStatusService haelt das Ergebnis 30 Minuten vor. "Jetzt pruefen" umgeht das, aber fruehestens nach 60 Sekunden; bis dahin kommt der vorige Stand mit der Wartezeit zurueck. Gleichzeitige Aufrufe loesen eine einzige Pruefung aus. Ohne das fragte jeder Seitenaufruf, jedes offene Browserfenster, das Deploymentcenter. Die Pruefung liegt hinter IUpdateChecker und ist damit ohne Netz testbar. Kein Installieren ueber das WebUI, und ein Test haelt fest, dass es keine solche Route gibt: Die Installation startet den Update-Agent und beendet danach die Anwendung und mit ihr den Webserver. Richards Vorgabe beschraenkt das Beenden ueber das WebUI auf das Trading (#563). Oberflaeche: - Karte "Version & Updates" in den Einstellungen, mit "Jetzt pruefen". - Im Dashboard ein Banner wie im Desktop-Launcher, sobald ein Update vorliegt. Er verweist zur Installation auf den Desktop. Nicht durch Unit-Tests abgedeckt: DeploymentcenterUpdateChecker selbst, weil er ueber das Netz geht. Er wird auf der VM gegen das echte Deploymentcenter geprueft. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
53 lines
2.2 KiB
C#
53 lines
2.2 KiB
C#
using System;
|
||
using System.Threading;
|
||
using Microsoft.AspNetCore.Builder;
|
||
using Microsoft.AspNetCore.Http;
|
||
using Microsoft.AspNetCore.Routing;
|
||
using Microsoft.Extensions.DependencyInjection;
|
||
using PolyTrader.Core;
|
||
using PolyTrader.Web.Updates;
|
||
|
||
namespace PolyTrader.Web.Endpoints
|
||
{
|
||
/// <summary>
|
||
/// Update-Status im WebUI (#565): laufende und verfügbare Fassung, Hinweis auf ein Sicherheitsupdate.
|
||
///
|
||
/// <para><b>Kein Installieren über das WebUI.</b> Die Installation startet den Update-Agent und beendet
|
||
/// danach die Anwendung – und mit ihr den Webserver. Richards Vorgabe beschränkt das Beenden über das
|
||
/// WebUI auf das Trading (#563). Installiert wird im Desktop.</para>
|
||
/// </summary>
|
||
public static class UpdatesEndpoints
|
||
{
|
||
public static IEndpointRouteBuilder MapUpdatesEndpoints(this IEndpointRouteBuilder routes)
|
||
{
|
||
routes.MapGet("/api/updates", async (IServiceProvider sp, bool? refresh, CancellationToken ct) =>
|
||
{
|
||
var service = sp.GetService<UpdateStatusService>();
|
||
if (service == null)
|
||
return Results.Problem("Die Update-Prüfung ist nicht verfügbar.", statusCode: StatusCodes.Status503ServiceUnavailable);
|
||
|
||
var (snapshot, fromCache, retryAfter) = await service.GetAsync(refresh == true, ct);
|
||
|
||
return Results.Ok(new
|
||
{
|
||
currentVersion = BuildInfo.Version,
|
||
currentBuild = BuildInfo.Summary,
|
||
enabled = snapshot.Enabled,
|
||
updateAvailable = snapshot.UpdateAvailable,
|
||
latestVersion = snapshot.LatestVersion,
|
||
changelog = snapshot.Changelog,
|
||
isCritical = snapshot.IsCritical,
|
||
unauthorized = snapshot.Unauthorized,
|
||
error = snapshot.Error,
|
||
checkedAt = snapshot.CheckedAtUtc.ToString("o"),
|
||
fromCache,
|
||
retryAfterSeconds = retryAfter.HasValue ? (int?)Math.Ceiling(retryAfter.Value.TotalSeconds) : null,
|
||
installVia = "desktop"
|
||
});
|
||
});
|
||
|
||
return routes;
|
||
}
|
||
}
|
||
}
|