consolidation of some of the modules, localization fixes, product advisories work, qa work
This commit is contained in:
@@ -1,11 +1,17 @@
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using StellaOps.Auth.ServerIntegration;
|
||||
using StellaOps.Auth.ServerIntegration.Tenancy;
|
||||
using StellaOps.Infrastructure.Postgres.Options;
|
||||
using StellaOps.Localization;
|
||||
using StellaOps.Remediation.Core.Abstractions;
|
||||
using StellaOps.Remediation.Core.Services;
|
||||
using StellaOps.Remediation.Persistence.Postgres;
|
||||
using StellaOps.Remediation.Persistence.Repositories;
|
||||
using StellaOps.Auth.ServerIntegration.Tenancy;
|
||||
using StellaOps.Remediation.WebService.Endpoints;
|
||||
using StellaOps.Router.AspNet;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
var storageDriver = ResolveStorageDriver(builder.Configuration, "Remediation");
|
||||
|
||||
builder.Services.AddProblemDetails();
|
||||
builder.Services.AddHealthChecks();
|
||||
@@ -18,6 +24,7 @@ builder.Services.AddAuthorization(options =>
|
||||
});
|
||||
builder.Services.AddAuthentication();
|
||||
builder.Services.AddStellaOpsTenantServices();
|
||||
builder.Services.AddStellaOpsCors(builder.Environment, builder.Configuration);
|
||||
builder.Services.AddStellaOpsLocalization(builder.Configuration);
|
||||
builder.Services.AddTranslationBundle(System.Reflection.Assembly.GetExecutingAssembly());
|
||||
|
||||
@@ -25,26 +32,28 @@ builder.Services.AddTranslationBundle(System.Reflection.Assembly.GetExecutingAss
|
||||
builder.Services.AddSingleton<IContributorTrustScorer, ContributorTrustScorer>();
|
||||
builder.Services.AddSingleton<IRemediationVerifier, RemediationVerifier>();
|
||||
|
||||
// Persistence (in-memory stubs for now; swap to Postgres in production)
|
||||
var templateRepo = new PostgresFixTemplateRepository();
|
||||
var submissionRepo = new PostgresPrSubmissionRepository();
|
||||
builder.Services.AddSingleton<IFixTemplateRepository>(templateRepo);
|
||||
builder.Services.AddSingleton<IPrSubmissionRepository>(submissionRepo);
|
||||
RegisterPersistence(builder.Services, builder.Configuration, builder.Environment, storageDriver);
|
||||
|
||||
// Registry: compose from repositories
|
||||
builder.Services.AddSingleton<IRemediationRegistry>(sp =>
|
||||
new InMemoryRemediationRegistry(templateRepo, submissionRepo));
|
||||
// Registry/matcher: compose from repositories.
|
||||
builder.Services.AddSingleton<IRemediationRegistry, RepositoryBackedRemediationRegistry>();
|
||||
builder.Services.AddSingleton<IRemediationMatcher, RepositoryBackedRemediationMatcher>();
|
||||
|
||||
// Matcher: compose from template repository
|
||||
builder.Services.AddSingleton<IRemediationMatcher>(sp =>
|
||||
new InMemoryRemediationMatcher(templateRepo));
|
||||
var routerEnabled = builder.Services.AddRouterMicroservice(
|
||||
builder.Configuration,
|
||||
serviceName: "remediation",
|
||||
version: System.Reflection.CustomAttributeExtensions.GetCustomAttribute<System.Reflection.AssemblyInformationalVersionAttribute>(System.Reflection.Assembly.GetExecutingAssembly())?.InformationalVersion ?? "1.0.0",
|
||||
routerOptionsSection: "Router");
|
||||
builder.TryAddStellaOpsLocalBinding("remediation");
|
||||
|
||||
var app = builder.Build();
|
||||
app.LogStellaOpsLocalHostname("remediation");
|
||||
|
||||
app.UseAuthentication();
|
||||
app.UseStellaOpsCors();
|
||||
app.UseStellaOpsLocalization();
|
||||
app.UseAuthorization();
|
||||
app.UseStellaOpsTenantMiddleware();
|
||||
app.TryUseStellaRouter(routerEnabled);
|
||||
|
||||
app.MapHealthChecks("/healthz").AllowAnonymous();
|
||||
|
||||
@@ -53,17 +62,112 @@ app.MapRemediationMatchEndpoints();
|
||||
app.MapRemediationSourceEndpoints();
|
||||
|
||||
await app.LoadTranslationsAsync();
|
||||
app.TryRefreshStellaRouterEndpoints(routerEnabled);
|
||||
app.Run();
|
||||
|
||||
static void RegisterPersistence(
|
||||
IServiceCollection services,
|
||||
IConfiguration configuration,
|
||||
IHostEnvironment environment,
|
||||
string storageDriver)
|
||||
{
|
||||
if (string.Equals(storageDriver, "postgres", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var connectionString = ResolvePostgresConnectionString(configuration, "Remediation");
|
||||
if (string.IsNullOrWhiteSpace(connectionString))
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Remediation requires PostgreSQL connection settings when Storage:Driver=postgres. " +
|
||||
"Set ConnectionStrings:Default or Remediation:Storage:Postgres:ConnectionString.");
|
||||
}
|
||||
|
||||
var schemaName = ResolveSchemaName(configuration, "Remediation") ?? RemediationDataSource.DefaultSchemaName;
|
||||
|
||||
services.Configure<PostgresOptions>(options =>
|
||||
{
|
||||
options.ConnectionString = connectionString;
|
||||
options.SchemaName = schemaName;
|
||||
});
|
||||
services.AddSingleton<RemediationDataSource>();
|
||||
services.AddSingleton<IFixTemplateRepository, PostgresFixTemplateRepository>();
|
||||
services.AddSingleton<IPrSubmissionRepository, PostgresPrSubmissionRepository>();
|
||||
services.AddSingleton<IMarketplaceSourceRepository, PostgresMarketplaceSourceRepository>();
|
||||
return;
|
||||
}
|
||||
|
||||
if (string.Equals(storageDriver, "inmemory", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (!IsTestEnvironment(environment))
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
"Remediation in-memory storage driver is restricted to Test/Testing environments.");
|
||||
}
|
||||
|
||||
services.AddSingleton<IFixTemplateRepository>(_ => new PostgresFixTemplateRepository());
|
||||
services.AddSingleton<IPrSubmissionRepository>(_ => new PostgresPrSubmissionRepository());
|
||||
services.AddSingleton<IMarketplaceSourceRepository>(_ => new PostgresMarketplaceSourceRepository());
|
||||
return;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException(
|
||||
$"Unsupported Remediation storage driver '{storageDriver}'. Allowed values: postgres, inmemory.");
|
||||
}
|
||||
|
||||
static bool IsTestEnvironment(IHostEnvironment environment)
|
||||
{
|
||||
return environment.IsEnvironment("Test") || environment.IsEnvironment("Testing");
|
||||
}
|
||||
|
||||
static string ResolveStorageDriver(IConfiguration configuration, string serviceName)
|
||||
{
|
||||
return FirstNonEmpty(
|
||||
configuration[$"{serviceName}:Storage:Driver"],
|
||||
configuration["Storage:Driver"])
|
||||
?? "postgres";
|
||||
}
|
||||
|
||||
static string? ResolveSchemaName(IConfiguration configuration, string serviceName)
|
||||
{
|
||||
return FirstNonEmpty(
|
||||
configuration[$"{serviceName}:Storage:Postgres:SchemaName"],
|
||||
configuration["Storage:Postgres:SchemaName"],
|
||||
configuration[$"Postgres:{serviceName}:SchemaName"]);
|
||||
}
|
||||
|
||||
static string? ResolvePostgresConnectionString(IConfiguration configuration, string serviceName)
|
||||
{
|
||||
return FirstNonEmpty(
|
||||
configuration[$"{serviceName}:Storage:Postgres:ConnectionString"],
|
||||
configuration["Storage:Postgres:ConnectionString"],
|
||||
configuration[$"Postgres:{serviceName}:ConnectionString"],
|
||||
configuration[$"ConnectionStrings:{serviceName}"],
|
||||
configuration["ConnectionStrings:Default"]);
|
||||
}
|
||||
|
||||
static string? FirstNonEmpty(params string?[] values)
|
||||
{
|
||||
foreach (var value in values)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public partial class Program { }
|
||||
|
||||
/// <summary>
|
||||
/// In-memory registry implementation composed from repositories.
|
||||
/// Repository-backed registry implementation composed from repositories.
|
||||
/// </summary>
|
||||
internal sealed class InMemoryRemediationRegistry : IRemediationRegistry
|
||||
internal sealed class RepositoryBackedRemediationRegistry : IRemediationRegistry
|
||||
{
|
||||
private readonly IFixTemplateRepository _templates;
|
||||
private readonly IPrSubmissionRepository _submissions;
|
||||
|
||||
public InMemoryRemediationRegistry(IFixTemplateRepository templates, IPrSubmissionRepository submissions)
|
||||
public RepositoryBackedRemediationRegistry(IFixTemplateRepository templates, IPrSubmissionRepository submissions)
|
||||
{
|
||||
_templates = templates;
|
||||
_submissions = submissions;
|
||||
@@ -92,13 +196,13 @@ internal sealed class InMemoryRemediationRegistry : IRemediationRegistry
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// In-memory matcher implementation that delegates to template repository.
|
||||
/// Repository-backed matcher implementation that delegates to template repository.
|
||||
/// </summary>
|
||||
internal sealed class InMemoryRemediationMatcher : IRemediationMatcher
|
||||
internal sealed class RepositoryBackedRemediationMatcher : IRemediationMatcher
|
||||
{
|
||||
private readonly IFixTemplateRepository _templates;
|
||||
|
||||
public InMemoryRemediationMatcher(IFixTemplateRepository templates)
|
||||
public RepositoryBackedRemediationMatcher(IFixTemplateRepository templates)
|
||||
{
|
||||
_templates = templates;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user