Implement version check enhancements and add tests for December 2020 build

This commit is contained in:
Alexa
2026-06-15 22:45:40 +03:00
parent babfd2833f
commit 1b0a9a62b4
6 changed files with 117 additions and 3 deletions
@@ -0,0 +1,56 @@
using System.Text.Json;
using DorkNet.Server.Compat;
using DorkNet.Server.Controllers.Auth;
using DorkNet.Server.Versions.Late2020;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging.Abstractions;
namespace DorkNet.Server.Tests;
public sealed class VersionCheckControllerTests
{
[Fact]
public void December_2020_build_is_valid_with_minimal_service_config()
{
var controller = CreateController();
var result = Assert.IsType<OkObjectResult>(controller.Check("20201210", "0"));
Assert.Equal(0, ReadVersionStatus(result.Value));
}
[Fact]
public void Unknown_build_still_requires_update()
{
var controller = CreateController();
var result = Assert.IsType<OkObjectResult>(controller.Check("unknown", "0"));
Assert.Equal(2, ReadVersionStatus(result.Value));
}
private static VersionCheckController CreateController()
{
var config = new ConfigurationBuilder().Build();
var registry = new VersionRegistry(
[new Late2020VersionPlugin()],
new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{
"december_2020_12_18",
},
"december_2020_12_18");
return new VersionCheckController(
config,
registry,
NullLogger<VersionCheckController>.Instance);
}
private static int ReadVersionStatus(object? value)
{
var json = JsonSerializer.Serialize(value);
using var document = JsonDocument.Parse(json);
return document.RootElement.GetProperty("VersionStatus").GetInt32();
}
}
@@ -46,6 +46,12 @@ public class VersionCheckController(
private const int VersionStatus_ValidForMenu = 1; private const int VersionStatus_ValidForMenu = 1;
private const int VersionStatus_UpdateRequired = 2; private const int VersionStatus_UpdateRequired = 2;
private static readonly IReadOnlyDictionary<string, string> BuiltInBuildIdToVersionKey =
new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
["20201210"] = "december_2020_12_18",
};
[HttpGet("/api/versioncheck/v4")] [HttpGet("/api/versioncheck/v4")]
[HttpGet("/api/versioncheck/v3")] [HttpGet("/api/versioncheck/v3")]
[HttpGet("/api/versioncheck/v2")] [HttpGet("/api/versioncheck/v2")]
@@ -66,9 +72,17 @@ public class VersionCheckController(
// } // }
// Mapping ABSENT → unknown build → UpdateRequired. // Mapping ABSENT → unknown build → UpdateRequired.
var mapSection = config.GetSection("DorkNet:BuildIdToVersionKey"); var mapSection = config.GetSection("DorkNet:BuildIdToVersionKey");
string? versionKey = !string.IsNullOrWhiteSpace(buildId) string? versionKey = null;
? mapSection[buildId] if (!string.IsNullOrWhiteSpace(buildId))
: null; {
var normalizedBuildId = buildId.Trim();
versionKey = mapSection[normalizedBuildId];
if (string.IsNullOrWhiteSpace(versionKey)
&& BuiltInBuildIdToVersionKey.TryGetValue(normalizedBuildId, out var builtInVersionKey))
{
versionKey = builtInVersionKey;
}
}
bool allowed = versionKey is not null && registry.IsSupported(versionKey); bool allowed = versionKey is not null && registry.IsSupported(versionKey);
var status = allowed ? VersionStatus_ValidForPlay : VersionStatus_UpdateRequired; var status = allowed ? VersionStatus_ValidForPlay : VersionStatus_UpdateRequired;
@@ -12,4 +12,12 @@
<ProjectReference Include="..\DorkNet.Server\DorkNet.Server.csproj" /> <ProjectReference Include="..\DorkNet.Server\DorkNet.Server.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Content Include="..\DorkNet.Server\wwwroot\**\*">
<Link>wwwroot\%(RecursiveDir)%(Filename)%(Extension)</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
</ItemGroup>
</Project> </Project>
+6
View File
@@ -8,6 +8,12 @@ x-dorknet-service-env: &dorknet-service-env
S3__AccessKey: ${DORKNET_S3_ACCESS_KEY:?Set DORKNET_S3_ACCESS_KEY in Dokploy} S3__AccessKey: ${DORKNET_S3_ACCESS_KEY:?Set DORKNET_S3_ACCESS_KEY in Dokploy}
S3__SecretKey: ${DORKNET_S3_SECRET_KEY:?Set DORKNET_S3_SECRET_KEY in Dokploy} S3__SecretKey: ${DORKNET_S3_SECRET_KEY:?Set DORKNET_S3_SECRET_KEY in Dokploy}
S3__Region: ${DORKNET_S3_REGION:-garage} S3__Region: ${DORKNET_S3_REGION:-garage}
Photon__AppId: ${Photon__AppId:?Set Photon__AppId in Dokploy}
Photon__VoiceAppId: ${Photon__VoiceAppId:-}
Photon__CloudRegion: ${Photon__CloudRegion:-eu}
DorkNet__DefaultClientVersion: ${DORKNET_DEFAULT_CLIENT_VERSION:-december_2020_12_18}
DorkNet__SupportedVersions__0: ${DORKNET_SUPPORTED_VERSION:-december_2020_12_18}
DorkNet__BuildIdToVersionKey__20201210: ${DORKNET_DECEMBER_BUILD_VERSION_KEY:-december_2020_12_18}
x-dorknet-app-networks: &dorknet-app-networks x-dorknet-app-networks: &dorknet-app-networks
networks: networks:
+6
View File
@@ -8,6 +8,12 @@ x-dorknet-service-env: &dorknet-service-env
S3__AccessKey: ${DORKNET_S3_ACCESS_KEY:-} S3__AccessKey: ${DORKNET_S3_ACCESS_KEY:-}
S3__SecretKey: ${DORKNET_S3_SECRET_KEY:-} S3__SecretKey: ${DORKNET_S3_SECRET_KEY:-}
S3__Region: ${DORKNET_S3_REGION:-garage} S3__Region: ${DORKNET_S3_REGION:-garage}
Photon__AppId: ${Photon__AppId:-}
Photon__VoiceAppId: ${Photon__VoiceAppId:-}
Photon__CloudRegion: ${Photon__CloudRegion:-eu}
DorkNet__DefaultClientVersion: ${DORKNET_DEFAULT_CLIENT_VERSION:-december_2020_12_18}
DorkNet__SupportedVersions__0: ${DORKNET_SUPPORTED_VERSION:-december_2020_12_18}
DorkNet__BuildIdToVersionKey__20201210: ${DORKNET_DECEMBER_BUILD_VERSION_KEY:-december_2020_12_18}
services: services:
gateway: gateway:
+24
View File
@@ -53,6 +53,9 @@ S3__Region=garage
Photon__AppId=your-photon-realtime-app-id Photon__AppId=your-photon-realtime-app-id
Photon__VoiceAppId=your-photon-voice-app-id Photon__VoiceAppId=your-photon-voice-app-id
Photon__CloudRegion=eu Photon__CloudRegion=eu
DORKNET_DEFAULT_CLIENT_VERSION=december_2020_12_18
DORKNET_SUPPORTED_VERSION=december_2020_12_18
DORKNET_DECEMBER_BUILD_VERSION_KEY=december_2020_12_18
``` ```
If Postgres and Redis are Dokploy-managed services in the same project, If Postgres and Redis are Dokploy-managed services in the same project,
@@ -163,6 +166,9 @@ DORKNET_DOMAIN=yourdomain.com
DORKNET_JWT_SECRET=replace-with-at-least-64-random-characters DORKNET_JWT_SECRET=replace-with-at-least-64-random-characters
POSTGRES_PASSWORD=replace-with-a-random-db-password POSTGRES_PASSWORD=replace-with-a-random-db-password
CLOUDFLARE_TUNNEL_TOKEN=<token from Cloudflare Zero Trust tunnel> CLOUDFLARE_TUNNEL_TOKEN=<token from Cloudflare Zero Trust tunnel>
Photon__AppId=your-photon-realtime-app-id
Photon__VoiceAppId=your-photon-voice-app-id
Photon__CloudRegion=eu
``` ```
By default the service containers connect to the bundled compose By default the service containers connect to the bundled compose
@@ -281,6 +287,24 @@ S3__TimeoutSeconds=300
For the microservices compose file, use the `DORKNET_S3_*` equivalents; For the microservices compose file, use the `DORKNET_S3_*` equivalents;
Compose maps them into `S3__*` for the service containers. Compose maps them into `S3__*` for the service containers.
The microservices compose files also map `Photon__AppId`,
`Photon__VoiceAppId`, and `Photon__CloudRegion` into every backend
service. Missing or wrong Photon values show up in the 2020 client as
NameServer/region connection failures after the boot version check.
They also map the December 2020 build ID into the version gate. A quick
check for the 2020 client should return `{"VersionStatus":0}`:
```bash
curl https://api.yourdomain.com/api/versioncheck/v4?v=20201210
```
If `admin.<domain>` or `feed.<domain>` returns the NameServer JSON
instead of the static site, verify the `web` container contains
`/app/wwwroot/admin/index.html` and `/app/wwwroot/feed/index.html`.
Those hosts should resolve through the gateway to the `web` service, not
the `ns` service or monolith fallback.
--- ---
## First-time cutover from SQLite ## First-time cutover from SQLite