174 lines
6.3 KiB
C#
174 lines
6.3 KiB
C#
using PostFundManagement.Application.Extensions;
|
|
using PostFundManagement.Application.Filters;
|
|
using PostFundManagement.Domain.Extensions;
|
|
using PostFundManagement.Domain.Health;
|
|
using PostFundManagement.Domain.Mediator;
|
|
using static PostFundManagement.Domain.Extensions.Constants;
|
|
|
|
var builder = WebApplication.CreateBuilder(args);
|
|
|
|
builder.Services.AddEndpointsApiExplorer()
|
|
.AddApiVersioning(options => options.ApiVersionReader = new HeaderApiVersionReader());
|
|
|
|
builder.Services.AddApiVersioning().AddApiExplorer();
|
|
builder.Services.AddScoped<ActiveUserFilter>();
|
|
|
|
builder.Services.AddEndpoints(Assembly.GetExecutingAssembly());
|
|
builder.Services.AddApiServices(builder.Configuration);
|
|
builder.Services.AddSharedServices();
|
|
builder.Services.AddRegisterServicesWithCaching(builder.Configuration);
|
|
builder.Services.AddEndpointAndServiceCaching(builder.Configuration);
|
|
|
|
builder.Services.AddMediator();
|
|
builder.Services.AddSecurityApiSdk(builder.Configuration);
|
|
builder.Services.AddApiSecurity(builder.Configuration);
|
|
|
|
builder.Services.AddScoped(typeof(IPipelineBehavior<,>), typeof(TelemetryPipelineBehavior<,>));
|
|
builder.Services.AddScoped(typeof(IPipelineBehavior<,>), typeof(LoggingPipelineBehavior<,>));
|
|
|
|
builder.Services.AddQuartzScheduler(DefaultSchedulerName, builder.Configuration);
|
|
builder.Services.AddEmailServices(builder.Configuration);
|
|
builder.Services.AddHashServices(builder.Configuration);
|
|
builder.Services.AddGarageS3(builder.Configuration);
|
|
|
|
builder.Services.AddHttpClient();
|
|
builder.Services.AddDataProtectionDatabase(builder.Configuration);
|
|
builder.Services.AddApplicationDbContext(builder.Configuration);
|
|
|
|
builder.Services.AddHealthChecks()
|
|
.AddCheck<QuartzHealthCheck>("QuartzScheduler")
|
|
.AddCheck<PostgresHealthCheck>("PostgresDatabase")
|
|
.AddCheck("Self", () => HealthCheckResult.Healthy());
|
|
|
|
IEnumerable<string> identityScopes = ["openid", "profile", "roles", "email", "address"];
|
|
|
|
builder.Services.AddValidation()
|
|
.AddEndpointValidation();
|
|
|
|
builder.Services.AddOpenApi(options =>
|
|
{
|
|
options.AddDocumentTransformer((document, context, cancellationToken) =>
|
|
{
|
|
document.Components ??= new OpenApiComponents();
|
|
document.Components?.SecuritySchemes!["OAuth2"] = new OpenApiSecurityScheme
|
|
{
|
|
Type = SecuritySchemeType.OAuth2,
|
|
Description = "Interactive OAuth2 flow for authentication and authorization",
|
|
Flows = new OpenApiOAuthFlows
|
|
{
|
|
AuthorizationCode = new OpenApiOAuthFlow
|
|
{
|
|
AuthorizationUrl = new Uri($"{builder.Configuration["SecuritySettings:Authority"]}/connect/authorize"),
|
|
TokenUrl = new Uri($"{builder.Configuration["SecuritySettings:Authority"]}/connect/token"),
|
|
Scopes = new Dictionary<string, string>
|
|
{
|
|
{ "openid", "OpenID Connect" },
|
|
{ "profile", "User Profile" },
|
|
{ "roles", "User Roles" },
|
|
{ "email", "User Email" },
|
|
{ "address", "User Address" },
|
|
{ builder.Configuration["SecuritySettings:Audience"]!, "PFM API Scope" }
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
return Task.CompletedTask;
|
|
});
|
|
|
|
options.AddOperationTransformer((operation, context, cancellationToken) =>
|
|
{
|
|
operation.Security ??= [];
|
|
|
|
var schemeReference = new OpenApiSecuritySchemeReference("OAuth2");
|
|
|
|
operation.Security.Add(new OpenApiSecurityRequirement
|
|
{
|
|
[schemeReference] = [.. identityScopes, builder.Configuration["SecuritySettings:Audience"]!]
|
|
});
|
|
|
|
return Task.CompletedTask;
|
|
});
|
|
});
|
|
|
|
builder.Services.AddCors(options => options.AddPolicy("AllowFrontend", policy =>
|
|
policy.WithOrigins("https://localhost:3000").AllowAnyHeader().AllowAnyMethod().AllowCredentials()));
|
|
|
|
var app = builder.Build();
|
|
|
|
var schedulerFactory = app.Services.GetRequiredService<ISchedulerFactory>();
|
|
var scheduler = await schedulerFactory.GetScheduler(DefaultSchedulerName);
|
|
|
|
if (!scheduler!.IsStarted)
|
|
await scheduler.Start();
|
|
|
|
app.UseHsts();
|
|
app.UseHttpsRedirection();
|
|
|
|
app.UseRouting();
|
|
app.UseCors("AllowFrontend");
|
|
app.UseOutputCache();
|
|
app.UseAuthentication();
|
|
app.UseAuthorization();
|
|
|
|
ApiVersionSet versionSet = app.NewApiVersionSet("v1")
|
|
.HasApiVersion(new ApiVersion(1))
|
|
.ReportApiVersions()
|
|
.Build();
|
|
|
|
var versionGroups = new Dictionary<int, RouteGroupBuilder>
|
|
{
|
|
{
|
|
1, app.MapGroup("v{version:apiVersion}").WithApiVersionSet(versionSet)
|
|
.RequireAuthorization("ApiScope").AddEndpointFilter<ActiveUserFilter>()
|
|
}
|
|
};
|
|
|
|
app.MapEndpoints(versionGroups);
|
|
|
|
app.UseHealthChecks("/health", new HealthCheckOptions
|
|
{
|
|
Predicate = _ => true,
|
|
AllowCachingResponses = true,
|
|
ResponseWriter = HealthChecks.UI.Client.UIResponseWriter.WriteHealthCheckUIResponse
|
|
});
|
|
|
|
app.MapHealthChecksUI(options => { options.UIPath = "/healthui"; });
|
|
app.UseHealthChecks("/ready");
|
|
|
|
app.MapOpenApi();
|
|
|
|
var apiVersions = app.DescribeApiVersions()
|
|
.OrderByDescending(o => o.ApiVersion.MajorVersion)
|
|
.ToList();
|
|
|
|
foreach (var description in app.DescribeApiVersions().OrderByDescending(o => o.ApiVersion.MajorVersion))
|
|
{
|
|
app.MapScalarApiReference($"/openapi/{description.GroupName}", (options, context) =>
|
|
{
|
|
options.AddServer(new ScalarServer($"https://{context.Request.Host}"));
|
|
options.WithOpenApiRoutePattern($"/openapi/{description.GroupName}.json");
|
|
options.WithTheme(ScalarTheme.DeepSpace);
|
|
options.Agent = new ScalarAgentOptions { Disabled = true };
|
|
options.AddPreferredSecuritySchemes("OAuth2")
|
|
.AddOAuth2Flows("OAuth2", flow =>
|
|
{
|
|
flow.AuthorizationCode = new AuthorizationCodeFlow
|
|
{
|
|
ClientId = builder.Configuration["SecuritySettings:ClientId"]!,
|
|
Pkce = Pkce.Sha256,
|
|
SelectedScopes = [.. identityScopes, builder.Configuration["SecuritySettings:Audience"]!]
|
|
};
|
|
});
|
|
});
|
|
}
|
|
|
|
var latestVersionGroup = apiVersions.FirstOrDefault()?.GroupName ?? "v1";
|
|
|
|
app.MapGet("/", () => Results.Redirect($"/openapi/{latestVersionGroup}"))
|
|
.ExcludeFromDescription();
|
|
|
|
if (!app.Environment.IsDevelopment())
|
|
app.UseExceptionHandler("/Error", createScopeForErrors: true);
|
|
|
|
app.Run(); |