mirror of
https://github.com/DorkSquadRR/DorkNet.git
synced 2026-10-25 23:18:44 -07:00
Migrate auth to Open.IdentityServer
This commit is contained in:
+4
-4
@@ -1,14 +1,14 @@
|
||||
# DorkNet.Server container image — Coolify deploy target.
|
||||
# ────────────────────────────────────────────────────────────────────
|
||||
# Multi-stage: SDK image builds + publishes, runtime image is the
|
||||
# slimmer aspnet:9.0 with only the published output.
|
||||
# slimmer aspnet:10.0 with only the published output.
|
||||
#
|
||||
# Build context: repo root (so Tools/ and DorkNet.Models/ are visible
|
||||
# to ProjectReference + dotnet restore). The .dockerignore at the
|
||||
# repo root keeps the bin/, obj/, and other dev junk out of the
|
||||
# context.
|
||||
|
||||
ARG DOTNET_VERSION=9.0
|
||||
ARG DOTNET_VERSION=10.0
|
||||
ARG NODE_VERSION=20
|
||||
|
||||
# ── admin SPA build stage ──────────────────────────────────────────
|
||||
@@ -76,13 +76,13 @@ WORKDIR /app
|
||||
|
||||
# curl + wget for healthcheck probes — Coolify v4 defaults to wget for
|
||||
# its own probe regardless of what the image's HEALTHCHECK uses, so
|
||||
# both have to be present. The aspnet:9.0 base image strips both by
|
||||
# both have to be present. The aspnet:10.0 base image strips both by
|
||||
# default to keep the surface area small.
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends curl wget \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Run as a non-root user — aspnet:9.0 ships with the `app` UID 1654.
|
||||
# Run as a non-root user — aspnet:10.0 ships with the `app` UID 1654.
|
||||
# Coolify mounts persistent volumes with write permission for this UID.
|
||||
USER app
|
||||
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
ARG DOTNET_VERSION=9.0
|
||||
ARG DOTNET_VERSION=10.0
|
||||
ARG NODE_VERSION=20
|
||||
|
||||
FROM node:${NODE_VERSION}-alpine AS admin-ui
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsPackable>false</IsPackable>
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="9.0.4" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="10.0.9" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
|
||||
<PackageReference Include="xunit" Version="2.9.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
using System.Text;
|
||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.HostFiltering;
|
||||
using Microsoft.AspNetCore.Mvc.Testing;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
|
||||
namespace DorkNet.Server.Tests;
|
||||
|
||||
@@ -38,8 +35,8 @@ public sealed class DorkNetServerFactory : WebApplicationFactory<Program>
|
||||
["S3:Endpoint"] = "",
|
||||
["S3:AccessKey"] = "",
|
||||
["S3:SecretKey"] = "",
|
||||
["DorkNet:DefaultClientVersion"] = "december_2020_12_18",
|
||||
["DorkNet:SupportedVersions:0"] = "december_2020_12_18",
|
||||
["DorkNet:DefaultClientVersion"] = "march_2023_03_21",
|
||||
["DorkNet:SupportedVersions:0"] = "march_2023_03_21",
|
||||
});
|
||||
});
|
||||
builder.ConfigureServices(services =>
|
||||
@@ -56,18 +53,6 @@ public sealed class DorkNetServerFactory : WebApplicationFactory<Program>
|
||||
options.AllowEmptyHosts = true;
|
||||
options.IncludeFailureMessage = true;
|
||||
});
|
||||
services.PostConfigure<JwtBearerOptions>(JwtBearerDefaults.AuthenticationScheme, options =>
|
||||
{
|
||||
options.TokenValidationParameters = new TokenValidationParameters
|
||||
{
|
||||
ValidateIssuerSigningKey = true,
|
||||
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(JwtSecret)),
|
||||
ValidateIssuer = true,
|
||||
ValidIssuer = "https://api.rec.net/",
|
||||
ValidateAudience = false,
|
||||
ClockSkew = TimeSpan.Zero,
|
||||
};
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -61,8 +61,8 @@ public sealed class GameClientEndpointContractTests :
|
||||
ToHttpMethod(route.Method),
|
||||
new Uri($"http://{host}{path}"));
|
||||
request.Headers.Accept.ParseAdd("application/json");
|
||||
request.Headers.UserAgent.ParseAdd("RecRoom/2020.12.18");
|
||||
request.Headers.TryAddWithoutValidation("X-DorkNet-Version", "december_2020_12_18");
|
||||
request.Headers.UserAgent.ParseAdd("RecRoom/2023.03.21");
|
||||
request.Headers.TryAddWithoutValidation("X-DorkNet-Version", "march_2023_03_21");
|
||||
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", session.AccessToken);
|
||||
|
||||
if (NeedsRequestBody(request.Method))
|
||||
|
||||
@@ -21,11 +21,13 @@ public static class GameClientSessionFactory
|
||||
HttpMethod.Post,
|
||||
new Uri($"http://auth.{apexDomain}/connect/token"));
|
||||
tokenRequest.Headers.Accept.ParseAdd("application/json");
|
||||
tokenRequest.Headers.UserAgent.ParseAdd("RecRoom/2020.12.18");
|
||||
tokenRequest.Headers.TryAddWithoutValidation("X-DorkNet-Version", "december_2020_12_18");
|
||||
tokenRequest.Headers.UserAgent.ParseAdd("RecRoom/2023.03.21");
|
||||
tokenRequest.Headers.TryAddWithoutValidation("X-DorkNet-Version", "march_2023_03_21");
|
||||
tokenRequest.Content = new FormUrlEncodedContent(new Dictionary<string, string>
|
||||
{
|
||||
["grant_type"] = "password",
|
||||
["client_id"] = "recroom",
|
||||
["client_secret"] = "VxZ53kgbbEaRoZAeMe00MagtgD12GLL2",
|
||||
["username"] = "EndpointContract",
|
||||
["device_id"] = deviceId,
|
||||
["platform"] = "0",
|
||||
@@ -49,8 +51,8 @@ public static class GameClientSessionFactory
|
||||
HttpMethod.Get,
|
||||
new Uri($"http://auth.{apexDomain}/connect/userinfo"));
|
||||
userInfoRequest.Headers.Accept.ParseAdd("application/json");
|
||||
userInfoRequest.Headers.UserAgent.ParseAdd("RecRoom/2020.12.18");
|
||||
userInfoRequest.Headers.TryAddWithoutValidation("X-DorkNet-Version", "december_2020_12_18");
|
||||
userInfoRequest.Headers.UserAgent.ParseAdd("RecRoom/2023.03.21");
|
||||
userInfoRequest.Headers.TryAddWithoutValidation("X-DorkNet-Version", "march_2023_03_21");
|
||||
userInfoRequest.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
|
||||
|
||||
using var userInfoResponse = await client.SendAsync(userInfoRequest);
|
||||
|
||||
@@ -11,11 +11,11 @@ namespace DorkNet.Server.Tests;
|
||||
public sealed class VersionCheckControllerTests
|
||||
{
|
||||
[Fact]
|
||||
public void December_2020_build_is_valid_with_minimal_service_config()
|
||||
public void March_2023_build_is_valid_with_minimal_service_config()
|
||||
{
|
||||
var controller = CreateController();
|
||||
|
||||
var result = Assert.IsType<OkObjectResult>(controller.Check("20201210", "0"));
|
||||
var result = Assert.IsType<OkObjectResult>(controller.Check("20230321", "0"));
|
||||
|
||||
Assert.Equal(0, ReadVersionStatus(result.Value));
|
||||
}
|
||||
@@ -37,9 +37,9 @@ public sealed class VersionCheckControllerTests
|
||||
[new Late2020VersionPlugin()],
|
||||
new HashSet<string>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
"december_2020_12_18",
|
||||
"march_2023_03_21",
|
||||
},
|
||||
"december_2020_12_18");
|
||||
"march_2023_03_21");
|
||||
|
||||
return new VersionCheckController(
|
||||
config,
|
||||
|
||||
@@ -3,10 +3,10 @@ using System.Security.Claims;
|
||||
using System.Security.Cryptography;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
using Duende.IdentityServer;
|
||||
using Duende.IdentityServer.Models;
|
||||
using Duende.IdentityServer.Services;
|
||||
using Duende.IdentityServer.Validation;
|
||||
using Open.IdentityServer;
|
||||
using Open.IdentityServer.Models;
|
||||
using Open.IdentityServer.Services;
|
||||
using Open.IdentityServer.Validation;
|
||||
using Microsoft.AspNetCore.Http.Features;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
@@ -206,12 +206,6 @@ public static class RecRoomIdentityServerRegistration
|
||||
.AddIdentityServer(options =>
|
||||
{
|
||||
options.IssuerUri = domain.AuthIssuer.TrimEnd('/');
|
||||
options.KeyManagement.Enabled = false;
|
||||
var licenseKey =
|
||||
Environment.GetEnvironmentVariable("DUENDE_IDENTITYSERVER_LICENSE_KEY")
|
||||
?? config["IdentityServer:LicenseKey"];
|
||||
if (!string.IsNullOrWhiteSpace(licenseKey))
|
||||
options.LicenseKey = licenseKey;
|
||||
})
|
||||
.AddInMemoryIdentityResources(RecRoomIdentityServerConfig.IdentityResources)
|
||||
.AddInMemoryApiScopes(RecRoomIdentityServerConfig.ApiScopes)
|
||||
@@ -256,7 +250,7 @@ internal static class RecRoomIdentityServerConfig
|
||||
ClientName = "Rec Room game client",
|
||||
RequireClientSecret = true,
|
||||
ClientSecrets = { new Secret(ClientSecret.Sha256()) },
|
||||
AllowedGrantTypes = { GrantType.ResourceOwnerPassword, GrantType.RefreshToken, CachedLoginGrantType },
|
||||
AllowedGrantTypes = { GrantType.ResourceOwnerPassword, "refresh_token", CachedLoginGrantType },
|
||||
AllowedScopes = RecRoomScopes(),
|
||||
AllowOfflineAccess = true,
|
||||
AccessTokenLifetime = 60 * 60 * 12,
|
||||
|
||||
@@ -40,7 +40,6 @@ public class AdminController(
|
||||
SignupCodeService signupCodes,
|
||||
IObjectStorage storage,
|
||||
DomainConfig domain,
|
||||
IConfiguration config,
|
||||
IdentityServerSigningKeyProvider signingKeys,
|
||||
ILogger<AdminController> adminLogger) : ControllerBase
|
||||
{
|
||||
@@ -1490,9 +1489,6 @@ public class AdminController(
|
||||
var certPath = signingKeys.CertificatePath;
|
||||
var fullCertPath = Path.GetFullPath(certPath);
|
||||
var certificateExists = signingKeys.LoadedFromBase64 || System.IO.File.Exists(fullCertPath);
|
||||
var licenseConfigured =
|
||||
!string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable("DUENDE_IDENTITYSERVER_LICENSE_KEY"))
|
||||
|| !string.IsNullOrWhiteSpace(config["IdentityServer:LicenseKey"]);
|
||||
|
||||
return Ok(new
|
||||
{
|
||||
@@ -1524,10 +1520,6 @@ public class AdminController(
|
||||
NotAfterUtc = signingKeys.Certificate.NotAfter.ToUniversalTime(),
|
||||
Algorithm = SecurityAlgorithms.RsaSha256,
|
||||
},
|
||||
License = new
|
||||
{
|
||||
Configured = licenseConfigured,
|
||||
},
|
||||
PersistedGrants = new
|
||||
{
|
||||
Store = "in-memory",
|
||||
|
||||
@@ -6,7 +6,7 @@ using DorkNet.Server.Services;
|
||||
namespace DorkNet.Server.Controllers.Auth;
|
||||
|
||||
/// <summary>
|
||||
/// auth.rec.net game-specific auth helpers. OAuth/OIDC endpoints are owned by Duende IdentityServer.
|
||||
/// auth.rec.net game-specific auth helpers. OAuth/OIDC endpoints are owned by IdentityServer.
|
||||
/// </summary>
|
||||
[ApiController]
|
||||
public class AuthController(
|
||||
|
||||
@@ -1,21 +1,22 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Duende.IdentityServer" Version="7.4.7" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.4" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.15" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.4">
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="10.0.9" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="10.0.9" />
|
||||
<PackageReference Include="Open.IdentityServer" Version="1.0.0" />
|
||||
<PackageReference Include="MessagePack" Version="3.1.7" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.9">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.4" />
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.4" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="10.0.9" />
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="10.0.2" />
|
||||
<!-- RenderedCompactJsonFormatter for stdout JSON logs in production
|
||||
(Coolify-friendly). The host pipeline reads stdout line-by-line,
|
||||
and structured JSON lets a future Loki/Datadog ingest parse fields
|
||||
@@ -26,8 +27,8 @@
|
||||
scale: SignalR group fanout, OrphanAccountTracker (sticky-session
|
||||
account-creation flow), and PlayerPresenceService heartbeats all
|
||||
need shared state across replicas. -->
|
||||
<PackageReference Include="StackExchange.Redis" Version="2.8.16" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.StackExchangeRedis" Version="9.0.4" />
|
||||
<PackageReference Include="StackExchange.Redis" Version="2.13.17" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SignalR.StackExchangeRedis" Version="10.0.9" />
|
||||
<!-- S3-compatible object storage. Production target: Garage in
|
||||
Coolify (one-click). Dev fallback: local MinIO for parity
|
||||
testing. The SDK speaks plain S3, so swapping endpoints
|
||||
@@ -39,7 +40,7 @@
|
||||
cost+salt in the output string so we only need one column. -->
|
||||
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
|
||||
<PackageReference Include="Serilog.AspNetCore" Version="9.0.0" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="7.3.1" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="10.2.3" />
|
||||
<!-- Server-side crop/resize for img.* CDN transforms (?cropSquare=1&width=N
|
||||
on profile thumbnails). The 2020 client treats this as part of the
|
||||
image CDN contract — it uploads a full-frame capture and expects the
|
||||
|
||||
@@ -29,9 +29,6 @@ interface IdentityServerSettings {
|
||||
notAfterUtc: string;
|
||||
algorithm: string;
|
||||
};
|
||||
license: {
|
||||
configured: boolean;
|
||||
};
|
||||
persistedGrants: {
|
||||
store: string;
|
||||
warning: string;
|
||||
@@ -86,7 +83,6 @@ export function IdentityServer() {
|
||||
</div>
|
||||
<div className="flex flex-wrap gap-2 text-xs">
|
||||
<StatusBadge ok={settings.signing.certificateExists} on="Signing key" off="Missing key" />
|
||||
<StatusBadge ok={settings.license.configured} on="License set" off="No license key" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -82,7 +82,7 @@ discovery and JWT validation agree on `https://auth.<domain>`.
|
||||
dotnet run --project DorkNet.Server
|
||||
```
|
||||
|
||||
First boot creates `bin/Debug/net9.0/data/dorknet.db`, runs every
|
||||
First boot creates `bin/Debug/net10.0/data/dorknet.db`, runs every
|
||||
`LegacyUpgrades` pass, seeds canonical rooms / store catalog / club
|
||||
categories / playlists, and starts listening. You should see
|
||||
`Application started.` in the log; `curl http://localhost:8080/healthz`
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -51,8 +51,8 @@ static Assembly LoadServerAssembly(string[] args)
|
||||
var repositoryRoot = FindRepositoryRoot();
|
||||
var candidates = new[]
|
||||
{
|
||||
Path.Combine(repositoryRoot, "DorkNet.Server", "bin", "Debug", "net9.0", "DorkNet.Server.dll"),
|
||||
Path.Combine(repositoryRoot, "DorkNet.Server", "bin", "Release", "net9.0", "DorkNet.Server.dll")
|
||||
Path.Combine(repositoryRoot, "DorkNet.Server", "bin", "Debug", "net10.0", "DorkNet.Server.dll"),
|
||||
Path.Combine(repositoryRoot, "DorkNet.Server", "bin", "Release", "net10.0", "DorkNet.Server.dll")
|
||||
};
|
||||
|
||||
var existingCandidates = candidates.Where(File.Exists).ToArray();
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -333,8 +333,8 @@ static Assembly LoadServerAssembly(string? configuredPath)
|
||||
var repositoryRoot = FindRepositoryRoot();
|
||||
var candidates = new[]
|
||||
{
|
||||
Path.Combine(repositoryRoot, "DorkNet.Server", "bin", "Debug", "net9.0", "DorkNet.Server.dll"),
|
||||
Path.Combine(repositoryRoot, "DorkNet.Server", "bin", "Release", "net9.0", "DorkNet.Server.dll")
|
||||
Path.Combine(repositoryRoot, "DorkNet.Server", "bin", "Debug", "net10.0", "DorkNet.Server.dll"),
|
||||
Path.Combine(repositoryRoot, "DorkNet.Server", "bin", "Release", "net10.0", "DorkNet.Server.dll")
|
||||
};
|
||||
var existingCandidates = candidates.Where(File.Exists).ToArray();
|
||||
if (existingCandidates.Length == 0)
|
||||
|
||||
Reference in New Issue
Block a user