mirror of
https://github.com/CannedNet/CannedNet.git
synced 2026-10-25 15:09:23 -07:00
allow for ns change
This commit is contained in:
@@ -80,6 +80,7 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
edit.NsBaseUrl = edit.ServerBaseUrl;
|
||||||
AdminConfig.Save(edit);
|
AdminConfig.Save(edit);
|
||||||
saved = true;
|
saved = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
@rendermode InteractiveServer
|
@rendermode InteractiveServer
|
||||||
@inject AdminConfigService AdminConfig
|
@inject AdminConfigService AdminConfig
|
||||||
@inject NavigationManager Navigation
|
@inject NavigationManager Navigation
|
||||||
|
@using System.Net.Http.Json
|
||||||
|
|
||||||
<PageTitle>First-Time Setup</PageTitle>
|
<PageTitle>First-Time Setup</PageTitle>
|
||||||
|
|
||||||
@@ -60,6 +61,11 @@ else
|
|||||||
private bool error;
|
private bool error;
|
||||||
private string errorMessage = "";
|
private string errorMessage = "";
|
||||||
|
|
||||||
|
private class KeyResponse
|
||||||
|
{
|
||||||
|
public string? apiKey { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
private async Task Save()
|
private async Task Save()
|
||||||
{
|
{
|
||||||
saving = true;
|
saving = true;
|
||||||
@@ -83,7 +89,26 @@ else
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
edit.NsBaseUrl = edit.ServerBaseUrl;
|
||||||
AdminConfig.Save(edit);
|
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;
|
saved = true;
|
||||||
await Task.Delay(1000);
|
await Task.Delay(1000);
|
||||||
Navigation.NavigateTo("/login", forceLoad: true);
|
Navigation.NavigateTo("/login", forceLoad: true);
|
||||||
|
|||||||
@@ -42,5 +42,6 @@ public class AdminConfigService
|
|||||||
public class AdminConfigData
|
public class AdminConfigData
|
||||||
{
|
{
|
||||||
public string ServerBaseUrl { get; set; } = "";
|
public string ServerBaseUrl { get; set; } = "";
|
||||||
|
public string NsBaseUrl { get; set; } = "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,5 @@
|
|||||||
},
|
},
|
||||||
"AllowedHosts": "*",
|
"AllowedHosts": "*",
|
||||||
"ServerBaseUrl": "http://localhost:5000",
|
"ServerBaseUrl": "http://localhost:5000",
|
||||||
"ImagesBaseUrl": "https://cannednet.lapis.codes/img",
|
"ImagesBaseUrl": "https://cannednet.lapis.codes/img"
|
||||||
"Admin": {
|
|
||||||
"ApiKey": "changeme-replace-with-a-secure-key"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
|
using System.Security.Cryptography;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
using CannedNet.Data;
|
using CannedNet.Data;
|
||||||
using CannedNet.Hubs;
|
using CannedNet.Hubs;
|
||||||
@@ -42,6 +43,23 @@ public static class Program
|
|||||||
builder.Services.AddSingleton<ConfigService>();
|
builder.Services.AddSingleton<ConfigService>();
|
||||||
builder.Services.AddSignalR();
|
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 =>
|
builder.Services.AddAuthentication(options =>
|
||||||
{
|
{
|
||||||
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
|
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
|
||||||
|
|||||||
@@ -360,3 +360,42 @@ public class AdminController : ControllerBase
|
|||||||
return Results.Ok(new { success = true });
|
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 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user