SHA256
- Added tasks for publishing as container image. - Improvements for deployment: Db migrations on startup, reverse-proxy forward headers, and DataProtect management. - Added deploy example using docker-compose.
169 lines
6.4 KiB
C#
169 lines
6.4 KiB
C#
using FluentStorage;
|
|
using FluentValidation;
|
|
using Microsoft.AspNetCore.DataProtection;
|
|
using Microsoft.AspNetCore.HttpOverrides;
|
|
using Microsoft.AspNetCore.Localization;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.EntityFrameworkCore.Diagnostics;
|
|
using MudBlazor.Services;
|
|
using Serilog;
|
|
using Serilog.Extensions.Logging;
|
|
using Somnia.GuestLog;
|
|
using Somnia.GuestLog.Components;
|
|
using Somnia.GuestLog.Infrastructure;
|
|
using Somnia.GuestLog.Models.Configuration;
|
|
using Somnia.GuestLog.Models.DTOs;
|
|
using Somnia.GuestLog.Services;
|
|
using Somnia.GuestLog.Services.AddressQuery;
|
|
using Somnia.GuestLog.Services.Entity;
|
|
using Somnia.GuestLog.Services.SpainCodigoMunicipio;
|
|
using Somnia.GuestLog.Services.StayExport;
|
|
using Somnia.GuestLog.Utils;
|
|
using Somnia.GuestLog.Validators;
|
|
|
|
var builder = WebApplication.CreateBuilder(args);
|
|
|
|
//Load config files.
|
|
builder.Configuration.AddJsonFile("Config/log_Config.json", optional: false, reloadOnChange: false);
|
|
builder.Configuration.AddEnvironmentVariables("SOMNIA_");
|
|
|
|
//Create and configure Logger (Serilog)
|
|
var serilog = new LoggerConfiguration()
|
|
.ReadFrom.Configuration(builder.Configuration)
|
|
.CreateLogger();
|
|
builder.Services.AddSerilog(serilog);
|
|
|
|
var logger = new SerilogLoggerFactory(serilog).CreateLogger<Program>();
|
|
|
|
logger.LogInformation("\n\n\n -------------- Starting {appName} {appVersion} --------------", AppSettings.AppName, AppSettings.AppVersion);
|
|
|
|
if (!builder.Environment.IsDevelopment())
|
|
{
|
|
string dataProtectionPath = builder.Configuration.GetValue<string>("DataProtectionDir", defaultValue: "/SomniaGuestLog/dataprotection");
|
|
builder.Services.AddDataProtection()
|
|
.PersistKeysToFileSystem(new DirectoryInfo(dataProtectionPath))
|
|
.SetApplicationName("SomniaGuestLog");
|
|
}
|
|
|
|
builder.Services.Configure<ForwardedHeadersOptions>(options =>
|
|
{
|
|
options.ForwardedHeaders =
|
|
ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto | ForwardedHeaders.XForwardedHost;
|
|
});
|
|
|
|
var connectionStringGuestLog = builder.Configuration.GetConnectionString("DbSomniaGuestLog")
|
|
?? throw new InvalidOperationException("Connection string 'DbSomniaGuestLog' not found.");
|
|
builder.Services.AddDbContextFactory<GuestLogContext>(options =>
|
|
{
|
|
options.UseNpgsql(connectionStringGuestLog)
|
|
.UseLazyLoadingProxies()
|
|
.ConfigureWarnings(w => w.Log((CoreEventId.NavigationLazyLoading, LogLevel.Warning)));
|
|
|
|
// The following options help with debugging, but should
|
|
// be changed or removed for production.
|
|
if (builder.Environment.IsDevelopment())
|
|
{
|
|
options.EnableSensitiveDataLogging()
|
|
.EnableDetailedErrors();
|
|
}
|
|
});
|
|
|
|
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
|
|
|
|
// Add MudBlazor services
|
|
builder.Services.AddMudServices(c =>
|
|
{
|
|
c.SnackbarConfiguration.PositionClass = MudBlazor.Defaults.Classes.Position.TopCenter;
|
|
c.SnackbarConfiguration.ShowTransitionDuration = 300;
|
|
c.SnackbarConfiguration.HideTransitionDuration = 500;
|
|
c.SnackbarConfiguration.VisibleStateDuration = 10000;
|
|
});
|
|
|
|
// Add components services to the container.
|
|
builder.Services.AddRazorComponents()
|
|
.AddInteractiveServerComponents();
|
|
|
|
builder.Services.AddLocalization();
|
|
builder.Services.AddHttpClient();
|
|
|
|
// Add Validation Services
|
|
builder.Services.AddSingleton<IValidator<GuestDocumentDTO>, GuestDocumentDTOValidator>();
|
|
builder.Services.AddSingleton<IValidator<GuestDocIdDTO>, GuestDocIdDTOValidator>();
|
|
builder.Services.AddSingleton<IValidator<StayEntryDTO>, StayEntryDTOValidator>();
|
|
builder.Services.AddSingleton<IValidator<StayExportParamsDTO>, StayExportParamsDTOValidator>();
|
|
|
|
// Add Entity Services
|
|
builder.Services.AddSingleton<IGuestDocumentEntityService, GuestDocumentEntityService>();
|
|
builder.Services.AddSingleton<IStayEntryEntityService, StayEntryEntityService>();
|
|
builder.Services.AddSingleton<IStayExportFileEntityService, StayExportFileEntityService>();
|
|
|
|
// Add Services
|
|
builder.Services.AddSingleton<IDataListService, StaticDataListService>();
|
|
builder.Services.AddScoped<IUserMessageService, UserMessageService>();
|
|
builder.Services.AddSingleton<ILocalizerService, LocalizerService>();
|
|
builder.Services.AddSingleton<IStayExportService, StayExportService>();
|
|
builder.Services.AddSingleton<ISpainCodigoMunicipioService, SpainCodigoMunicipioCatastroService>();
|
|
|
|
// Add Factories (and it's services)
|
|
builder.Services.AddFactoryDI<IAddressQueryFactory, ConfigFileAddressQueryFactory>();
|
|
builder.Services.AddFactoryDI<IStayExportFormatProviderFactory, StayExportFormatProviderFactory>();
|
|
|
|
// Add Options config
|
|
builder.Services.AddOptions<AddressQueryConfig>()
|
|
.Bind(builder.Configuration.GetSection(AddressQueryConfig.SectionName));
|
|
builder.Services.AddOptions<StayExportConfig>()
|
|
.Bind(builder.Configuration.GetSection(StayExportConfig.SectionName));
|
|
builder.Services.AddOptions<StayExportSpainParteViajerosConfig>()
|
|
.Bind(builder.Configuration.GetSection(StayExportSpainParteViajerosConfig.SectionName));
|
|
|
|
var app = builder.Build();
|
|
|
|
app.UseForwardedHeaders();
|
|
|
|
// Configure the HTTP request pipeline.
|
|
if (app.Environment.IsDevelopment())
|
|
{
|
|
app.UseMigrationsEndPoint();
|
|
}
|
|
else
|
|
{
|
|
app.UseExceptionHandler("/Error", createScopeForErrors: true);
|
|
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
|
|
app.UseHsts();
|
|
}
|
|
app.UseStatusCodePagesWithReExecute("/not-found", createScopeForStatusCodePages: true);
|
|
app.UseHttpsRedirection();
|
|
|
|
app.UseAntiforgery();
|
|
|
|
string[] supportedCultures = ["en-US", "es-ES"];
|
|
var localizationOptions = new RequestLocalizationOptions()
|
|
.SetDefaultCulture(supportedCultures[0])
|
|
.AddSupportedCultures(supportedCultures)
|
|
.AddSupportedUICultures(supportedCultures);
|
|
localizationOptions.RequestCultureProviders = [
|
|
new QueryStringRequestCultureProvider(),
|
|
new CookieRequestCultureProvider()
|
|
];
|
|
|
|
app.UseRequestLocalization(localizationOptions);
|
|
app.MapStaticAssets();
|
|
app.MapRazorComponents<App>()
|
|
.AddInteractiveServerRenderMode();
|
|
|
|
//Activate S3 storage.
|
|
AwsS3Storage.Use();
|
|
|
|
//Run database migrations
|
|
bool runMigrationsOnStartup = builder.Configuration.GetValue<bool>("RunDatabaseMigrationOnStartup", defaultValue: true);
|
|
if (runMigrationsOnStartup)
|
|
{
|
|
logger.LogInformation("Running database migrations...");
|
|
using var scope = app.Services.CreateScope();
|
|
var db = scope.ServiceProvider.GetRequiredService<GuestLogContext>();
|
|
await db.Database.MigrateAsync();
|
|
logger.LogInformation("Database migrations OK");
|
|
}
|
|
|
|
app.Run();
|