144 lines
4.4 KiB
C#
144 lines
4.4 KiB
C#
using System.Text.Json;
|
|
using System.Text.Json.Serialization;
|
|
using System.Threading.Channels;
|
|
using Femto.Api;
|
|
using Femto.Api.Auth;
|
|
using Femto.Api.Infrastructure;
|
|
using Femto.Common;
|
|
using Femto.Common.Domain;
|
|
using Femto.Common.Integration;
|
|
using Femto.Modules.Auth.Application;
|
|
using Femto.Modules.Blog.Application;
|
|
using Femto.Modules.Media.Application;
|
|
using Microsoft.AspNetCore.Authentication;
|
|
using Microsoft.AspNetCore.Diagnostics;
|
|
using Microsoft.AspNetCore.Mvc.Infrastructure;
|
|
using Microsoft.AspNetCore.WebUtilities;
|
|
|
|
const string CorsPolicyName = "DefaultCorsPolicy";
|
|
|
|
var builder = WebApplication.CreateBuilder(args);
|
|
|
|
builder.Services.AddOpenApi();
|
|
|
|
var loggerFactory = LoggerFactory.Create(b =>
|
|
{
|
|
b.SetMinimumLevel(LogLevel.Information)
|
|
.AddConfiguration(builder.Configuration.GetSection("Logging"))
|
|
.AddConsole()
|
|
.AddDebug();
|
|
});
|
|
|
|
builder.Services.AddSingleton(loggerFactory);
|
|
builder.Services.AddSingleton(typeof(ILogger<>), typeof(Logger<>));
|
|
|
|
var connectionString = builder.Configuration.GetConnectionString("Database");
|
|
if (connectionString is null)
|
|
throw new Exception("no database connection string found");
|
|
|
|
var blobStorageRoot = builder.Configuration.GetValue<string>("BlobStorageRoot");
|
|
if (blobStorageRoot is null)
|
|
throw new Exception("no blob storage root found");
|
|
|
|
|
|
var eventBus = new EventBus(Channel.CreateUnbounded<IEvent>());
|
|
builder.Services.AddHostedService(_ => eventBus);
|
|
|
|
builder.Services.InitializeBlogModule(connectionString, eventBus, loggerFactory);
|
|
builder.Services.InitializeMediaModule(connectionString, blobStorageRoot);
|
|
builder.Services.InitializeAuthenticationModule(connectionString, eventBus, loggerFactory, TimeProvider.System);
|
|
|
|
builder.Services.AddScoped<CurrentUserContext, CurrentUserContext>();
|
|
builder.Services.AddScoped<ICurrentUserContext>(s => s.GetRequiredService<CurrentUserContext>());
|
|
|
|
|
|
builder.Services.AddCors(options =>
|
|
{
|
|
options.AddPolicy(
|
|
CorsPolicyName,
|
|
b =>
|
|
{
|
|
b.AllowAnyHeader()
|
|
.AllowAnyMethod()
|
|
.WithOrigins(builder.Configuration.GetValue<string>("CorsOrigins")?.Split(';') ?? [])
|
|
.AllowCredentials();
|
|
}
|
|
);
|
|
});
|
|
|
|
builder
|
|
.Services.AddControllers()
|
|
.AddJsonOptions(options =>
|
|
{
|
|
options.JsonSerializerOptions.PropertyNameCaseInsensitive = true;
|
|
options.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
|
|
options.JsonSerializerOptions.DictionaryKeyPolicy = JsonNamingPolicy.CamelCase;
|
|
options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
|
|
options.JsonSerializerOptions.NumberHandling = JsonNumberHandling.AllowReadingFromString;
|
|
});
|
|
|
|
builder.Services.Configure<CookieSettings>(
|
|
builder.Configuration.GetSection("Cookies"));
|
|
|
|
builder
|
|
.Services.AddAuthentication("SessionAuth")
|
|
.AddScheme<AuthenticationSchemeOptions, SessionAuthenticationHandler>(
|
|
"SessionAuth",
|
|
options => { }
|
|
);
|
|
|
|
builder.Services.AddAuthorization();
|
|
|
|
var app = builder.Build();
|
|
|
|
app.UseCors(CorsPolicyName);
|
|
app.UseAuthentication();
|
|
app.UseAuthorization();
|
|
app.UseExceptionHandler(errorApp =>
|
|
{
|
|
errorApp.Run(async context =>
|
|
{
|
|
var exceptionHandlerFeature = context.Features.Get<IExceptionHandlerFeature>();
|
|
var exception = exceptionHandlerFeature?.Error;
|
|
var problemDetailsFactory =
|
|
errorApp.ApplicationServices.GetRequiredService<ProblemDetailsFactory>();
|
|
|
|
var statusCode = exception switch
|
|
{
|
|
DomainError => 400,
|
|
_ => 500,
|
|
};
|
|
|
|
var message = exception switch
|
|
{
|
|
DomainError domainError => domainError.Message,
|
|
{ } e => e.Message,
|
|
_ => ReasonPhrases.GetReasonPhrase(statusCode),
|
|
};
|
|
|
|
var problemDetails = problemDetailsFactory.CreateProblemDetails(
|
|
httpContext: context,
|
|
title: "An error occurred",
|
|
detail: message,
|
|
statusCode: statusCode
|
|
);
|
|
|
|
// problemDetails.Extensions["traceId"] = context.TraceIdentifier;
|
|
context.Response.StatusCode = statusCode;
|
|
context.Response.ContentType = "application/problem+json";
|
|
|
|
await context.Response.WriteAsJsonAsync(problemDetails);
|
|
});
|
|
});
|
|
|
|
// app.UseMiddleware<ExceptionMapperMiddleware>();
|
|
if (app.Environment.IsDevelopment())
|
|
{
|
|
app.MapOpenApi();
|
|
}
|
|
|
|
app.MapControllers();
|
|
|
|
app.UseHttpsRedirection();
|
|
|
|
app.Run();
|