Conditionally clear logging providers and set up NLog only when the application is not in the development environment. This change improves logging management based on the environment, enhancing production logging behavior.
232 lines
8.2 KiB
C#
232 lines
8.2 KiB
C#
using DigitalData.Core.API;
|
||
using DigitalData.Core.Application;
|
||
using EnvelopeGenerator.Infrastructure;
|
||
using Microsoft.AspNetCore.Authentication.Cookies;
|
||
using Microsoft.AspNetCore.Localization;
|
||
using Microsoft.EntityFrameworkCore;
|
||
using System.Globalization;
|
||
using Scalar.AspNetCore;
|
||
using Microsoft.OpenApi.Models;
|
||
using DigitalData.UserManager.DependencyInjection;
|
||
using EnvelopeGenerator.Application;
|
||
using DigitalData.Auth.Client;
|
||
using DigitalData.Core.Abstractions;
|
||
using EnvelopeGenerator.GeneratorAPI.Models;
|
||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||
using Microsoft.IdentityModel.Tokens;
|
||
using DigitalData.Core.Abstractions.Security.Extensions;
|
||
using EnvelopeGenerator.GeneratorAPI.Middleware;
|
||
using NLog.Web;
|
||
using NLog;
|
||
|
||
var logger = LogManager.Setup().LoadConfigurationFromAppSettings().GetCurrentClassLogger();
|
||
logger.Info("Logging initialized!");
|
||
|
||
try
|
||
{
|
||
var builder = WebApplication.CreateBuilder(args);
|
||
|
||
builder.Logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);
|
||
|
||
if (!builder.Environment.IsDevelopment())
|
||
{
|
||
builder.Logging.ClearProviders();
|
||
builder.Host.UseNLog();
|
||
}
|
||
|
||
var config = builder.Configuration;
|
||
|
||
var deferredProvider = new DeferredServiceProvider();
|
||
|
||
builder.Services.AddControllers();
|
||
|
||
//CORS Policy
|
||
var allowedOrigins = config.GetSection("AllowedOrigins").Get<string[]>() ??
|
||
throw new InvalidOperationException("AllowedOrigins section is missing in the configuration.");
|
||
builder.Services.AddCors(options =>
|
||
{
|
||
options.AddPolicy("AllowSpecificOriginsPolicy", builder =>
|
||
{
|
||
builder.WithOrigins(allowedOrigins)
|
||
.SetIsOriginAllowedToAllowWildcardSubdomains()
|
||
.AllowAnyMethod()
|
||
.AllowAnyHeader()
|
||
.AllowCredentials();
|
||
});
|
||
});
|
||
|
||
// Swagger
|
||
builder.Services.AddEndpointsApiExplorer();
|
||
builder.Services.AddSwaggerGen(options =>
|
||
{
|
||
options.SwaggerDoc("v1", new OpenApiInfo
|
||
{
|
||
Version = "v1",
|
||
Title = "signFLOW Absender-API",
|
||
Description = "Eine API zur Verwaltung der Erstellung, des Versands und der Nachverfolgung von Umschl<68>gen in der signFLOW-Anwendung.",
|
||
Contact = new OpenApiContact
|
||
{
|
||
Name = "Digital Data GmbH",
|
||
Url = new Uri("https://digitaldata.works/digitale-signatur#kontakt"),
|
||
Email = "info-flow@digitaldata.works"
|
||
},
|
||
});
|
||
|
||
options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
|
||
{
|
||
Name = "Authorization",
|
||
Type = SecuritySchemeType.Http,
|
||
Scheme = "bearer",
|
||
BearerFormat = "JWT",
|
||
In = ParameterLocation.Header,
|
||
Description = "JWT-Autorisierungs-Header unter Verwendung des Bearer-Schemas.",
|
||
});
|
||
|
||
options.AddSecurityRequirement(new OpenApiSecurityRequirement
|
||
{
|
||
{
|
||
new OpenApiSecurityScheme
|
||
{
|
||
Reference = new OpenApiReference
|
||
{
|
||
Type = ReferenceType.SecurityScheme,
|
||
Id = "Bearer"
|
||
}
|
||
},
|
||
new string[] {}
|
||
}
|
||
});
|
||
|
||
var xmlFiles = Directory.GetFiles(AppContext.BaseDirectory, "*.xml");
|
||
foreach (var xmlFile in xmlFiles)
|
||
{
|
||
options.IncludeXmlComments(xmlFile);
|
||
}
|
||
});
|
||
builder.Services.AddOpenApi();
|
||
// DbContext
|
||
var connStr = config.GetConnectionString("Default") ?? throw new InvalidOperationException("There is no default connection string in appsettings.json.");
|
||
|
||
builder.Services.Configure<ConnectionString>(cs => cs.Value = connStr);
|
||
|
||
builder.Services.AddDbContext<EGDbContext>(options => options.UseSqlServer(connStr));
|
||
|
||
builder.Services.AddAuthHubClient(config.GetSection("AuthClientParams"));
|
||
|
||
var authTokenKeys = config.GetOrDefault<AuthTokenKeys>();
|
||
|
||
builder.Services.AddAuthentication(options =>
|
||
{
|
||
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
|
||
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
|
||
})
|
||
.AddJwtBearer(opt =>
|
||
{
|
||
opt.TokenValidationParameters = new TokenValidationParameters
|
||
{
|
||
ValidateIssuerSigningKey = true,
|
||
IssuerSigningKeyResolver = (token, securityToken, identifier, parameters) =>
|
||
{
|
||
var clientParams = deferredProvider.GetOptions<ClientParams>();
|
||
var publicKey = clientParams!.PublicKeys.Get(authTokenKeys.Issuer, authTokenKeys.Audience);
|
||
return new List<SecurityKey>() { publicKey.SecurityKey };
|
||
},
|
||
ValidateIssuer = true,
|
||
ValidIssuer = authTokenKeys.Issuer,
|
||
ValidateAudience = true,
|
||
ValidAudience = authTokenKeys.Audience,
|
||
};
|
||
|
||
opt.Events = new JwtBearerEvents
|
||
{
|
||
OnMessageReceived = context =>
|
||
{
|
||
// if there is no token read related cookie or query string
|
||
if (context.Token is null) // if there is no token
|
||
{
|
||
if (context.Request.Cookies.TryGetValue(authTokenKeys.Cookie, out var cookieToken) && cookieToken is not null)
|
||
context.Token = cookieToken;
|
||
else if (context.Request.Query.TryGetValue(authTokenKeys.QueryString, out var queryStrToken))
|
||
context.Token = queryStrToken;
|
||
}
|
||
return Task.CompletedTask;
|
||
}
|
||
};
|
||
});
|
||
|
||
// Authentication
|
||
builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
|
||
.AddCookie(options =>
|
||
{
|
||
options.Cookie.HttpOnly = true; // Makes the cookie inaccessible to client-side scripts for security
|
||
options.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest; // Ensures cookies are sent over HTTPS only
|
||
options.Cookie.SameSite = SameSiteMode.Strict; // Protects against CSRF attacks by restricting how cookies are sent with requests from external sites
|
||
options.LoginPath = "/api/auth/login";
|
||
options.LogoutPath = "/api/auth/logout";
|
||
options.SlidingExpiration = true;
|
||
});
|
||
|
||
// User manager
|
||
builder.Services.AddUserManager<EGDbContext>();
|
||
|
||
// LDAP
|
||
builder.ConfigureBySection<DirectorySearchOptions>();
|
||
builder.Services.AddDirectorySearchService(config.GetSection("DirectorySearchOptions"));
|
||
|
||
// Localizer
|
||
builder.Services.AddCookieBasedLocalizer();
|
||
|
||
// Envelope generator serives
|
||
builder.Services
|
||
.AddEnvelopeGeneratorInfrastructureServices(sqlExecutorConfigureOptions: executor => executor.ConnectionString = connStr)
|
||
.AddEnvelopeGeneratorServices(config);
|
||
|
||
var app = builder.Build();
|
||
|
||
deferredProvider.Factory = () => app.Services;
|
||
|
||
app.UseMiddleware<ExceptionHandlingMiddleware>();
|
||
|
||
app.MapOpenApi();
|
||
|
||
// Configure the HTTP request pipeline.
|
||
if (app.Environment.IsDevelopment() || (app.IsDevOrDiP() && config.GetValue<bool>("UseSwagger")))
|
||
{
|
||
app.UseSwagger();
|
||
app.UseSwaggerUI();
|
||
app.MapScalarApiReference();
|
||
}
|
||
|
||
// Set CORS policy
|
||
app.UseCors("AllowSpecificOriginsPolicy");
|
||
|
||
// Localizer
|
||
string[] supportedCultureNames = { "de-DE", "en-US" };
|
||
IList<CultureInfo> list = supportedCultureNames.Select((string cn) => new CultureInfo(cn)).ToList();
|
||
CultureInfo cultureInfo = list.FirstOrDefault() ?? throw new ArgumentNullException("supportedCultureNames", "Supported cultures cannot be empty.");
|
||
RequestLocalizationOptions requestLocalizationOptions = new RequestLocalizationOptions
|
||
{
|
||
SupportedCultures = list,
|
||
SupportedUICultures = list
|
||
};
|
||
requestLocalizationOptions.RequestCultureProviders.Add(new QueryStringRequestCultureProvider());
|
||
app.UseRequestLocalization(requestLocalizationOptions);
|
||
|
||
|
||
app.UseHttpsRedirection();
|
||
|
||
app.UseDefaultFiles();
|
||
app.UseStaticFiles();
|
||
|
||
app.UseAuthentication();
|
||
app.UseAuthorization();
|
||
|
||
app.MapControllers();
|
||
|
||
app.Run();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
logger.Error(ex, "Stopped program because of exception");
|
||
throw;
|
||
} |