116 lines
No EOL
3.8 KiB
C#
116 lines
No EOL
3.8 KiB
C#
using System.Text.Json.Serialization;
|
|
using AspNetCore.Authentication.ApiKey;
|
|
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
|
using Microsoft.OpenApi.Models;
|
|
using Npgsql;
|
|
using StalwartSimpleLoginMiddleware.Contexts;
|
|
using StalwartSimpleLoginMiddleware.Models;
|
|
using StalwartSimpleLoginMiddleware.Repositories;
|
|
using StalwartSimpleLoginMiddleware.Services;
|
|
|
|
var logger = LoggerFactory.Create(logging => logging.AddConsole()).CreateLogger("Startup");
|
|
var builder = WebApplication.CreateBuilder(args);
|
|
|
|
// Add services to the container.
|
|
|
|
builder.Services.AddDbContextPool<ApiKeyContext>((_, options) => ApiKeyContext.ConfigureOptions(options));
|
|
|
|
builder.Services.AddHealthChecks()
|
|
.AddCheck("WebService", () => HealthCheckResult.Healthy("The web service is running."))
|
|
.AddDbContextCheck<ApiKeyContext>();
|
|
|
|
builder.Services.AddScoped<IApiKeyAccessor, ApiKeyAccessor>()
|
|
.AddScoped<IApiKeyRepository, ApiKeyContextRepository>();
|
|
|
|
builder.Services.AddAuthentication(ApiKeyDefaults.AuthenticationScheme)
|
|
.AddApiKeyInHeader(options =>
|
|
{
|
|
options.Realm = "StalwartSimpleLoginMiddleware";
|
|
options.KeyName = "Authentication";
|
|
options.Events = new ApiKeyProvider();
|
|
});
|
|
|
|
builder.Services.AddAuthorization(options =>
|
|
{
|
|
options.FallbackPolicy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build();
|
|
});
|
|
|
|
builder.Services.AddControllers()
|
|
.AddJsonOptions(options => { options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles; });
|
|
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
|
builder.Services.AddEndpointsApiExplorer();
|
|
builder.Services.AddSwaggerGen(c =>
|
|
{
|
|
// Add the API Key Security Definition
|
|
c.AddSecurityDefinition("ApiKey", new OpenApiSecurityScheme
|
|
{
|
|
Description =
|
|
"API Key needed to access endpoints. Add it to the request headers as 'Authentication: <API_KEY>'",
|
|
Type = SecuritySchemeType.ApiKey,
|
|
Name = "Authentication", // Header name for the API Key
|
|
In = ParameterLocation.Header
|
|
});
|
|
|
|
// Add security requirements to ensure the header is required
|
|
c.AddSecurityRequirement(new OpenApiSecurityRequirement
|
|
{
|
|
{
|
|
new OpenApiSecurityScheme
|
|
{
|
|
Reference = new OpenApiReference
|
|
{
|
|
Type = ReferenceType.SecurityScheme,
|
|
Id = "ApiKey"
|
|
}
|
|
},
|
|
new string[] { } // No specific scopes
|
|
}
|
|
});
|
|
});
|
|
|
|
builder.Services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>()
|
|
.AddSingleton<StalwartClient>();
|
|
|
|
var app = builder.Build();
|
|
|
|
// Ensure the database is migrated at startup.
|
|
using (var scope = app.Services.CreateScope())
|
|
{
|
|
try
|
|
{
|
|
var services = scope.ServiceProvider;
|
|
var context = services.GetRequiredService<ApiKeyContext>();
|
|
await context.EnsureDatabaseMigrated(logger);
|
|
}
|
|
catch (NpgsqlException ex)
|
|
{
|
|
if (ex.SqlState is PostgresErrorCodes.ConnectionFailure or PostgresErrorCodes.ConnectionException ||
|
|
ex.Message.StartsWith("Failed to connect"))
|
|
logger.LogCritical($"Database connection failed: {ex.Message}");
|
|
else if (ex.SqlState is PostgresErrorCodes.InvalidPassword
|
|
or PostgresErrorCodes.InvalidAuthorizationSpecification)
|
|
logger.LogCritical("Failed to connect. Invalid password.");
|
|
else
|
|
logger.LogCritical($"An unknown error occurred:{Environment.NewLine}{ex.StackTrace}");
|
|
}
|
|
}
|
|
|
|
// Configure the HTTP request pipeline.
|
|
if (app.Environment.IsDevelopment())
|
|
{
|
|
app.UseSwagger();
|
|
app.UseSwaggerUI();
|
|
}
|
|
|
|
app.UseHttpsRedirection();
|
|
|
|
app.UseRouting();
|
|
|
|
app.UseAuthentication();
|
|
app.UseAuthorization();
|
|
|
|
app.MapControllers();
|
|
|
|
app.MapHealthChecks("/health");
|
|
app.Run(); |