17d12fef6a
Watch for KeySet, initial install will not have a valid value TitleDatabase will use data folder Reviewed-on: #2 Co-authored-by: Huy Nguyen <ecenshu@gmail.com> Co-committed-by: Huy Nguyen <ecenshu@gmail.com>
100 lines
4.7 KiB
C#
100 lines
4.7 KiB
C#
using System.Text.Json;
|
||
using Microsoft.Extensions.Caching.Memory;
|
||
using Microsoft.Extensions.Options;
|
||
using TinfoilVibeServer.Authentication;
|
||
using TinfoilVibeServer.Middleware;
|
||
using TinfoilVibeServer.Services;
|
||
using TinfoilVibeServer.Models;
|
||
|
||
var builder = WebApplication.CreateBuilder(args);
|
||
builder.Logging.ClearProviders();
|
||
builder.Logging.AddConsole();
|
||
builder.Logging.AddDebug();
|
||
|
||
builder.Services.AddMemoryCache();
|
||
var dataRoot = builder.Configuration["CONFIG_ROOT"] ?? "/app/config/";
|
||
// 1️⃣ Load the embedded default
|
||
var defaultResource = typeof(Program).Assembly
|
||
.GetManifestResourceStream("TinfoilVibeServer.appsettings.default.json")!; // adjust namespace
|
||
var defaultConfig = JsonDocument.Parse(defaultResource).RootElement;
|
||
|
||
// 2️⃣ Try to write the file if it doesn't exist
|
||
var configPath = Path.Combine(dataRoot, "appsettings.json");
|
||
if (!File.Exists(configPath))
|
||
{
|
||
// write the embedded JSON straight to disk
|
||
try
|
||
{
|
||
File.WriteAllText(configPath, defaultConfig.GetRawText());
|
||
}
|
||
catch (Exception e)
|
||
{
|
||
var tempFactory = LoggerFactory.Create(loggingBuilder =>
|
||
{
|
||
loggingBuilder.AddConsole();
|
||
loggingBuilder.AddDebug();
|
||
});
|
||
var logger = tempFactory.CreateLogger<Program>();
|
||
logger.LogError(e, "Failed to write default config file");
|
||
}
|
||
}
|
||
|
||
var config = new ConfigurationBuilder()
|
||
.AddJsonFile(Path.Combine(dataRoot,"appsettings.json"), optional: false, reloadOnChange: true)
|
||
.AddJsonFile(Path.Combine(dataRoot,$"appsettings.{builder.Environment.EnvironmentName}.json"), optional: true, reloadOnChange: true)
|
||
.AddJsonFile(Path.Combine(dataRoot,"appsettings.local.json"), optional: true, reloadOnChange: true)
|
||
.AddEnvironmentVariables()
|
||
.AddCommandLine(args).Build();
|
||
builder.Configuration.AddConfiguration(config);
|
||
builder.Services.AddOptions();
|
||
builder.Services.Configure<TitleDbOptions>(builder.Configuration.GetSection("TitleDb"));
|
||
builder.Services.Configure<NSPExtractorOptions>(builder.Configuration.GetSection("NSPExtractor"));
|
||
builder.Services.Configure<AuthSettings>(builder.Configuration.GetSection("AuthSettings"));
|
||
builder.Services.Configure<IndexBuilderSettings>(builder.Configuration.GetSection("IndexBuilder"));
|
||
builder.Services.AddOptions<SnapshotOptions>().Bind(builder.Configuration.GetSection("Snapshot")).ValidateOnStart();
|
||
builder.Services.AddSingleton<ConfigManager>();
|
||
builder.Services.AddSingleton<INSPExtractor, NSPExtractor>();
|
||
builder.Services.AddSingleton<SnapshotService>();
|
||
builder.Services.AddSingleton<ISnapshotService, SnapshotService>(sp => sp.GetRequiredService<SnapshotService>());
|
||
builder.Services.AddSingleton<IAuthStore, AuthStore>();
|
||
builder.Services.AddSingleton<TitleDatabaseService>();
|
||
builder.Services.AddSingleton<IArchiveHandler, ArchiveHandler>();
|
||
builder.Services.AddSingleton<IndexBuilderService>();
|
||
builder.Services.AddHostedService<IndexBuilderService>(provider => provider.GetRequiredService<IndexBuilderService>());
|
||
builder.Services.AddHostedService<SnapshotService>(provider => provider.GetRequiredService<SnapshotService>());
|
||
builder.Services.AddHostedService<TitleDatabaseService>(provider => provider.GetRequiredService<TitleDatabaseService>()).AddHttpClient();
|
||
builder.Services.AddControllers(); // add MVC
|
||
// -------------------------------------------------------------------
|
||
// 2) Middleware – Basic‑Auth (verifies username, password, UID, blacklist)
|
||
// -------------------------------------------------------------------
|
||
|
||
var app = builder.Build();
|
||
|
||
app.UseMiddleware<BasicAuthMiddleware>();
|
||
app.MapControllers(); // routes the /index.json & /download endpoints
|
||
|
||
// -------------------------------------------------------------------
|
||
// 3) End‑points
|
||
// -------------------------------------------------------------------
|
||
|
||
|
||
app.MapGet("/debug", () => new SnapshotService(
|
||
app.Services.GetRequiredService<IMemoryCache>(),
|
||
app.Services.GetRequiredService<IOptionsMonitor<SnapshotOptions>>(),
|
||
app.Services.GetRequiredService<INSPExtractor>(),
|
||
app.Services.GetRequiredService<IArchiveHandler>(),
|
||
app.Services.GetRequiredService<ILogger<SnapshotService>>(), app.Services.GetRequiredService<IHostEnvironment>())
|
||
.GetSnapshot());
|
||
app.Lifetime.ApplicationStarted.Register(() =>
|
||
app.Services.GetRequiredService<ILogger<Program>>().LogInformation("Application started. Listening on {Urls}", string.Join(", ", app.Urls)));
|
||
app.Use(async (ctx, next) =>
|
||
{
|
||
var logger = app.Services.GetRequiredService<ILogger<Program>>();
|
||
var correlationId = ctx.Request.Headers["X-Correlation-ID"].FirstOrDefault()
|
||
?? Guid.NewGuid().ToString();
|
||
using (logger.BeginScope("CorrelationId:{CorrelationId}", correlationId))
|
||
{
|
||
await next();
|
||
}
|
||
});
|
||
app.Run(); |