refactor: address code review findings across all projects
Apply comprehensive fixes from code reviews including: - Extract shared utilities (SqlFormatHelper, CellValueConverter, DbDestinationBase) - Add interface abstractions (IAuthenticationService, IDatabaseMigrator, IMisQueryBuilder) - Implement SecureStore for encrypted secrets storage - Fix error handling with proper HTTP status codes and logging - Optimize double enumeration in DevEtlRegistry - Add DataSync.Dev README for developer onboarding - Extract filter panel base classes to reduce duplication - Update code review docs to mark all issues as fixed
This commit is contained in:
@@ -3,6 +3,8 @@ using JdeScoping.DataAccess.Options;
|
||||
using JdeScoping.DataSync.Options;
|
||||
using JdeScoping.ExcelIO.Options;
|
||||
using JdeScoping.Database;
|
||||
using JdeScoping.Infrastructure.Security;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
@@ -11,14 +13,21 @@ var builder = WebApplication.CreateBuilder(args);
|
||||
builder.Host.UseWindowsService();
|
||||
|
||||
// Run database migrations (skip in Testing environment)
|
||||
// Note: IDatabaseMigrator interface enables mocking for integration tests
|
||||
if (!builder.Environment.IsEnvironment("Testing"))
|
||||
{
|
||||
var migrator = new DatabaseMigrator(builder.Configuration);
|
||||
// Create early logger for startup diagnostics
|
||||
using var loggerFactory = LoggerFactory.Create(b => b
|
||||
.AddConfiguration(builder.Configuration.GetSection("Logging"))
|
||||
.AddConsole());
|
||||
var startupLogger = loggerFactory.CreateLogger("JdeScoping.Host.Startup");
|
||||
|
||||
IDatabaseMigrator migrator = new DatabaseMigrator(builder.Configuration);
|
||||
var migrationResult = migrator.Migrate();
|
||||
|
||||
if (!migrationResult.Successful)
|
||||
{
|
||||
Console.WriteLine($"Database migration failed: {migrationResult.Error?.Message}");
|
||||
startupLogger.LogError(migrationResult.Error, "Database migration failed: {ErrorMessage}", migrationResult.Error?.Message);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -36,6 +45,13 @@ builder.Services
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
// Migrate existing secrets to SecureStore (skip in Testing environment)
|
||||
if (!app.Environment.IsEnvironment("Testing"))
|
||||
{
|
||||
var migrator = app.Services.GetRequiredService<SecretsMigrator>();
|
||||
migrator.MigrateIfNeeded();
|
||||
}
|
||||
|
||||
// Startup validation - verify critical services are registered
|
||||
ValidateServices(app.Services);
|
||||
|
||||
@@ -64,11 +80,15 @@ static void ValidateServices(IServiceProvider services)
|
||||
{
|
||||
using var scope = services.CreateScope();
|
||||
var provider = scope.ServiceProvider;
|
||||
var logger = provider.GetRequiredService<ILoggerFactory>().CreateLogger("JdeScoping.Host.Startup");
|
||||
|
||||
// Validate Options classes are bound
|
||||
_ = provider.GetRequiredService<IOptions<DataAccessOptions>>();
|
||||
_ = provider.GetRequiredService<IOptions<DataSyncOptions>>();
|
||||
_ = provider.GetRequiredService<IOptions<ExcelExportOptions>>();
|
||||
_ = provider.GetRequiredService<IOptions<SearchProcessingOptions>>();
|
||||
Console.WriteLine("Service validation completed successfully.");
|
||||
logger.LogInformation("Service validation completed successfully");
|
||||
}
|
||||
|
||||
// Enable WebApplicationFactory<Program> for integration testing
|
||||
public partial class Program { }
|
||||
|
||||
@@ -128,6 +128,13 @@
|
||||
"UseFileDataSource": false,
|
||||
"FileDirectory": "DevData"
|
||||
},
|
||||
"SecureStore": {
|
||||
"StorePath": "data/secrets.json",
|
||||
"KeyFilePath": "data/secrets.key",
|
||||
"MasterKeyEnvVar": "SCOPINGTOOL_MASTER_KEY",
|
||||
"AutoCreateStore": true,
|
||||
"MigrateExistingSecrets": true
|
||||
},
|
||||
"WorkProcessor": {
|
||||
"Enabled": true,
|
||||
"WorkInterval": "00:00:05",
|
||||
|
||||
Reference in New Issue
Block a user