fix: do up No audit of document access in vigilcare-records-gap-analysis.md
This commit is contained in:
@@ -1,6 +1,10 @@
|
||||
using System.Text;
|
||||
using System.Threading.RateLimiting;
|
||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
|
||||
using Microsoft.AspNetCore.RateLimiting;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Diagnostics.HealthChecks;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using Minio;
|
||||
using Prometheus;
|
||||
@@ -24,7 +28,12 @@ try
|
||||
|
||||
// Redis
|
||||
builder.Services.AddSingleton<IConnectionMultiplexer>(sp =>
|
||||
ConnectionMultiplexer.Connect(sp.GetRequiredService<IConfiguration>()["Redis:ConnectionString"]!));
|
||||
{
|
||||
var config = ConfigurationOptions.Parse(
|
||||
sp.GetRequiredService<IConfiguration>()["Redis:ConnectionString"]!);
|
||||
config.AbortOnConnectFail = false;
|
||||
return ConnectionMultiplexer.Connect(config);
|
||||
});
|
||||
|
||||
// MinIO
|
||||
var minioOptions = builder.Configuration.GetSection(MinioOptions.Section).Get<MinioOptions>()!;
|
||||
@@ -43,6 +52,13 @@ try
|
||||
|
||||
// JWT Authentication
|
||||
var jwtOptions = builder.Configuration.GetSection(JwtOptions.Section).Get<JwtOptions>()!;
|
||||
|
||||
if (string.IsNullOrEmpty(jwtOptions.Secret) ||
|
||||
Encoding.UTF8.GetByteCount(jwtOptions.Secret) < 32)
|
||||
throw new InvalidOperationException(
|
||||
"JWT Secret must be at least 256 bits (32 bytes). " +
|
||||
"Configure a strong secret via Jwt:Secret in appsettings or the Jwt__Secret environment variable.");
|
||||
|
||||
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
|
||||
.AddJwtBearer(options =>
|
||||
{
|
||||
@@ -59,6 +75,35 @@ try
|
||||
});
|
||||
builder.Services.AddAuthorization();
|
||||
|
||||
// CORS
|
||||
builder.Services.AddCors(options =>
|
||||
{
|
||||
options.AddPolicy("VigilCare", policy =>
|
||||
{
|
||||
policy.WithOrigins(builder.Configuration.GetSection("Cors:AllowedOrigins").Get<string[]>()!)
|
||||
.AllowAnyHeader()
|
||||
.AllowAnyMethod()
|
||||
.AllowCredentials();
|
||||
});
|
||||
});
|
||||
|
||||
// Rate limiting (disabled in Testing — integration tests issue many auth requests)
|
||||
var isTesting = builder.Environment.IsEnvironment("Testing");
|
||||
if (!isTesting)
|
||||
{
|
||||
builder.Services.AddRateLimiter(options =>
|
||||
{
|
||||
options.RejectionStatusCode = StatusCodes.Status429TooManyRequests;
|
||||
options.AddFixedWindowLimiter("auth", opt =>
|
||||
{
|
||||
opt.Window = TimeSpan.FromMinutes(5);
|
||||
opt.PermitLimit = 10;
|
||||
opt.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
|
||||
opt.QueueLimit = 0;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Services
|
||||
builder.Services.AddScoped<IAuthService, AuthService>();
|
||||
builder.Services.AddScoped<IBatchService, BatchService>();
|
||||
@@ -79,6 +124,20 @@ try
|
||||
builder.Services.AddHostedService<MetricsCollectorService>();
|
||||
builder.Services.AddHostedService<PromotionRetryService>();
|
||||
|
||||
// Health checks
|
||||
builder.Services.AddHealthChecks()
|
||||
.AddNpgSql(
|
||||
builder.Configuration.GetConnectionString("DefaultConnection")!,
|
||||
name: "postgresql",
|
||||
tags: new[] { "ready", "startup" })
|
||||
.AddRedis(
|
||||
builder.Configuration["Redis:ConnectionString"]!,
|
||||
name: "redis",
|
||||
tags: new[] { "ready" })
|
||||
.AddCheck<MinioHealthCheck>(
|
||||
"minio",
|
||||
tags: new[] { "ready" });
|
||||
|
||||
builder.Services.AddControllers();
|
||||
builder.Services.AddEndpointsApiExplorer();
|
||||
builder.Services.AddVigilCareRecordsSwagger();
|
||||
@@ -98,11 +157,47 @@ try
|
||||
});
|
||||
}
|
||||
|
||||
app.UseHttpMetrics();
|
||||
app.UseHttpMetrics();
|
||||
app.UseCors("VigilCare");
|
||||
if (!app.Environment.IsEnvironment("Testing"))
|
||||
app.UseRateLimiter();
|
||||
app.UseAuthentication();
|
||||
app.UseAuthorization();
|
||||
app.MapControllers();
|
||||
app.MapMetrics();
|
||||
app.MapMetrics();
|
||||
|
||||
app.MapHealthChecks("/health/live", new HealthCheckOptions
|
||||
{
|
||||
Predicate = _ => false,
|
||||
ResultStatusCodes =
|
||||
{
|
||||
[HealthStatus.Healthy] = StatusCodes.Status200OK,
|
||||
[HealthStatus.Degraded] = StatusCodes.Status200OK,
|
||||
[HealthStatus.Unhealthy] = StatusCodes.Status503ServiceUnavailable
|
||||
}
|
||||
});
|
||||
|
||||
app.MapHealthChecks("/health/ready", new HealthCheckOptions
|
||||
{
|
||||
Predicate = check => check.Tags.Contains("ready"),
|
||||
ResultStatusCodes =
|
||||
{
|
||||
[HealthStatus.Healthy] = StatusCodes.Status200OK,
|
||||
[HealthStatus.Degraded] = StatusCodes.Status200OK,
|
||||
[HealthStatus.Unhealthy] = StatusCodes.Status503ServiceUnavailable
|
||||
}
|
||||
});
|
||||
|
||||
app.MapHealthChecks("/health/startup", new HealthCheckOptions
|
||||
{
|
||||
Predicate = check => check.Tags.Contains("startup"),
|
||||
ResultStatusCodes =
|
||||
{
|
||||
[HealthStatus.Healthy] = StatusCodes.Status200OK,
|
||||
[HealthStatus.Degraded] = StatusCodes.Status200OK,
|
||||
[HealthStatus.Unhealthy] = StatusCodes.Status503ServiceUnavailable
|
||||
}
|
||||
});
|
||||
|
||||
if (!app.Environment.IsEnvironment("Testing"))
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user