allow for ns change

This commit is contained in:
Lapis
2026-06-19 18:14:00 -04:00
parent dd113b644e
commit c2ed2aa0e8
6 changed files with 85 additions and 4 deletions
@@ -80,6 +80,7 @@
return;
}
edit.NsBaseUrl = edit.ServerBaseUrl;
AdminConfig.Save(edit);
saved = true;
}
@@ -2,6 +2,7 @@
@rendermode InteractiveServer
@inject AdminConfigService AdminConfig
@inject NavigationManager Navigation
@using System.Net.Http.Json
<PageTitle>First-Time Setup</PageTitle>
@@ -60,6 +61,11 @@ else
private bool error;
private string errorMessage = "";
private class KeyResponse
{
public string? apiKey { get; set; }
}
private async Task Save()
{
saving = true;
@@ -83,7 +89,26 @@ else
return;
}
edit.NsBaseUrl = edit.ServerBaseUrl;
AdminConfig.Save(edit);
try
{
using var client = new HttpClient();
client.BaseAddress = new Uri(edit.ServerBaseUrl.TrimEnd('/'));
var keyResp = await client.GetFromJsonAsync<KeyResponse>("/admin/api/setup/key");
if (keyResp?.apiKey != null)
{
client.DefaultRequestHeaders.Add("X-Admin-Api-Key", keyResp.apiKey);
await client.PostAsJsonAsync("/admin/api/setup/baseurl", new { baseUrl = edit.ServerBaseUrl });
}
}
catch
{
// server config update is best-effort during setup
}
saved = true;
await Task.Delay(1000);
Navigation.NavigateTo("/login", forceLoad: true);
@@ -42,5 +42,6 @@ public class AdminConfigService
public class AdminConfigData
{
public string ServerBaseUrl { get; set; } = "";
public string NsBaseUrl { get; set; } = "";
}
}
+1 -4
View File
@@ -7,8 +7,5 @@
},
"AllowedHosts": "*",
"ServerBaseUrl": "http://localhost:5000",
"ImagesBaseUrl": "https://cannednet.lapis.codes/img",
"Admin": {
"ApiKey": "changeme-replace-with-a-secure-key"
}
"ImagesBaseUrl": "https://cannednet.lapis.codes/img"
}
+18
View File
@@ -1,4 +1,5 @@
using System.Security.Claims;
using System.Security.Cryptography;
using System.Text.Json.Serialization;
using CannedNet.Data;
using CannedNet.Hubs;
@@ -42,6 +43,23 @@ public static class Program
builder.Services.AddSingleton<ConfigService>();
builder.Services.AddSignalR();
var adminApiKey = builder.Configuration["Admin:ApiKey"];
if (string.IsNullOrEmpty(adminApiKey))
{
var keyFile = Path.Combine("Data", ".admin_key");
if (File.Exists(keyFile))
{
adminApiKey = File.ReadAllText(keyFile).Trim();
}
else
{
adminApiKey = Convert.ToHexString(RandomNumberGenerator.GetBytes(32));
Directory.CreateDirectory("Data");
File.WriteAllText(keyFile, adminApiKey);
}
builder.Configuration["Admin:ApiKey"] = adminApiKey;
}
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
@@ -360,3 +360,42 @@ public class AdminController : ControllerBase
return Results.Ok(new { success = true });
}
}
[ApiController, Route("admin/api/setup")]
public class SetupController : ControllerBase
{
private static readonly string SetupCompleteFile = Path.Combine("Data", ".setup_complete");
[HttpGet("key")]
public IResult GetKey([FromServices] IConfiguration config)
{
if (System.IO.File.Exists(SetupCompleteFile))
return Results.NotFound();
var key = config["Admin:ApiKey"] ?? "";
return Results.Ok(new { apiKey = key });
}
[HttpPost("baseurl")]
[Authorize(AuthenticationSchemes = "AdminApiKey")]
public async Task<IResult> SetBaseUrl([FromServices] ConfigService configService)
{
using var reader = new StreamReader(Request.Body);
var body = await reader.ReadToEndAsync();
var data = JsonSerializer.Deserialize<JsonElement>(body);
if (!data.TryGetProperty("baseUrl", out var baseUrlEl) || baseUrlEl.ValueKind != JsonValueKind.String)
return Results.BadRequest(new { error = "baseUrl is required" });
var baseUrl = baseUrlEl.GetString() ?? "";
if (string.IsNullOrWhiteSpace(baseUrl))
return Results.BadRequest(new { error = "baseUrl cannot be empty" });
var current = configService.Config;
current.BaseUrl = baseUrl.TrimEnd('/');
configService.SaveConfig(current);
System.IO.File.WriteAllText(SetupCompleteFile, "done");
return Results.Ok(new { success = true });
}
}