feat: sync guard - Blockieren alter Clients beim sync
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
using System.Text.Json;
|
||||
using LehrerApp.Sync;
|
||||
|
||||
namespace LehrerApp.Api;
|
||||
|
||||
/// <summary>
|
||||
/// Stoppt veraltete Sync-Clients vor Authentifizierung und insbesondere vor jedem Store-Zugriff.
|
||||
/// Die Prüfung gilt auch für Anhänge, Plain-Sync und Device-Pairing-Snapshots.
|
||||
/// </summary>
|
||||
public sealed class SyncProtocolVersionMiddleware(RequestDelegate next)
|
||||
{
|
||||
public async Task InvokeAsync(HttpContext context)
|
||||
{
|
||||
if (!IsProtectedSyncPath(context.Request.Path))
|
||||
{
|
||||
await next(context);
|
||||
return;
|
||||
}
|
||||
|
||||
context.Response.Headers[SyncProtocol.VersionHeaderName] = SyncProtocol.CurrentVersion;
|
||||
var clientVersion = context.Request.Headers[SyncProtocol.VersionHeaderName].ToString();
|
||||
if (string.Equals(clientVersion, SyncProtocol.CurrentVersion, StringComparison.Ordinal))
|
||||
{
|
||||
await next(context);
|
||||
return;
|
||||
}
|
||||
|
||||
context.Response.StatusCode = StatusCodes.Status426UpgradeRequired;
|
||||
context.Response.ContentType = "application/problem+json";
|
||||
await JsonSerializer.SerializeAsync(context.Response.Body, new
|
||||
{
|
||||
type = "https://lehrerapp.local/problems/sync-version-mismatch",
|
||||
title = "Inkompatible Sync-Version",
|
||||
status = StatusCodes.Status426UpgradeRequired,
|
||||
detail = $"Der Server erwartet Sync-Version {SyncProtocol.CurrentVersion}.",
|
||||
expectedVersion = SyncProtocol.CurrentVersion,
|
||||
receivedVersion = string.IsNullOrEmpty(clientVersion) ? null : clientVersion,
|
||||
});
|
||||
}
|
||||
|
||||
private static bool IsProtectedSyncPath(PathString path) =>
|
||||
path.StartsWithSegments("/api/sync", StringComparison.OrdinalIgnoreCase) ||
|
||||
path.StartsWithSegments("/api/snapshot", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
Reference in New Issue
Block a user