Files
tnsu-approval-route/backend/Tnsu.ApprovalRoute.Api/Program.cs
T
gorbenko.pavel 2a7130c37f
Tests / frontend-test (pull_request) Successful in 47s
Tests / backend-test (pull_request) Successful in 2m7s
джоба есть
2026-08-17 14:14:45 +05:00

117 lines
4.2 KiB
C#

using System.Text.Json.Serialization;
using Extensions.Hosting.AsyncInitialization;
using Hangfire;
using Hangfire.PostgreSql;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.OpenApi;
using Scalar.AspNetCore;
using Tnsu.ApprovalRoute.Api.Auth;
using Tnsu.ApprovalRoute.Api.Filters;
using Tnsu.ApprovalRoute.Application;
using Tnsu.ApprovalRoute.Application.Reminders;
using Tnsu.ApprovalRoute.Application.RequestTypeLists;
using Tnsu.ApprovalRoute.Application.Common.Interfaces;
using Tnsu.ApprovalRoute.Infrastructure;
const string CorsPolicyName = "Frontend";
var builder = WebApplication.CreateBuilder(args);
builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders =
ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
options.KnownNetworks.Clear();
options.KnownProxies.Clear();
});
var corsAllowedOrigins = builder.Configuration.GetSection("Cors:AllowedOrigins").Get<string[]>() ?? [];
builder.Services.AddCors(options =>
{
options.AddPolicy(CorsPolicyName, policy => policy
.WithOrigins(corsAllowedOrigins)
.AllowAnyHeader()
.AllowAnyMethod());
});
builder.Services.AddApprovalRouteInfrastructure(builder.Configuration);
builder.Services.AddApprovalRouteApplication();
builder.Services.Configure<RemindersOptions>(builder.Configuration.GetSection("Reminders"));
builder.Services.Configure<ListProvisioningOptions>(builder.Configuration.GetSection("ListProvisioning"));
// Hangfire на том же Postgres, что и остальные данные. Свои таблицы он создаёт сам
// (схема hangfire) при старте — отдельной EF-миграции для них не нужно.
builder.Services.AddHangfire(configuration => configuration
.SetDataCompatibilityLevel(CompatibilityLevel.Version_180)
.UseSimpleAssemblyNameTypeSerializer()
.UseRecommendedSerializerSettings()
.UsePostgreSqlStorage(postgres =>
postgres.UseNpgsqlConnection(builder.Configuration.GetConnectionString("Postgres"))));
// Воркер живёт в процессе API: задач мало (создание списка — редкое событие), и
// отдельный хост под них был бы лишней инфраструктурой.
builder.Services.AddHangfireServer();
builder.Services.AddApprovalRouteAuth(builder.Configuration);
builder.Services.AddScoped<ICurrentUser, CurrentUserAccessor>();
builder.Services.AddOpenApi(options =>
{
options.AddDocumentTransformer((document, _, _) =>
{
document.Components ??= new OpenApiComponents();
document.Components.SecuritySchemes ??= new Dictionary<string, IOpenApiSecurityScheme>();
document.Components.SecuritySchemes["Bearer"] = new OpenApiSecurityScheme
{
Type = SecuritySchemeType.Http,
Scheme = "bearer",
BearerFormat = "JWT",
Description = "Введите JWT токен"
};
return Task.CompletedTask;
});
options.AddOperationTransformer((operation, context, _) =>
{
operation.Security =
[
new OpenApiSecurityRequirement
{
[new OpenApiSecuritySchemeReference("Bearer", context.Document)] = []
}
];
return Task.CompletedTask;
});
});
builder.Services.AddHealthChecks();
builder.Services.AddControllers(options => options.Filters.Add<ValidationActionFilter>())
.AddJsonOptions(o => o.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()));
builder.Services.ConfigureHttpJsonOptions(o => o.SerializerOptions.Converters.Add(new JsonStringEnumConverter()));
var app = builder.Build();
app.UseForwardedHeaders();
app.MapOpenApi();
app.MapScalarApiReference(options =>
{
options
.WithTitle("Tnsu Approval Route")
.AddPreferredSecuritySchemes("Bearer")
.AddHttpAuthentication("Bearer", _ => { });
});
app.MapHealthChecks("/health");
app.UseCors(CorsPolicyName);
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
await app.InitAndRunAsync();
public partial class Program;