Files
tiku-backend.net/Tiku.Api/Configuration/DependencyInjection.cs

100 lines
5.0 KiB
C#

using Serilog;
using Tiku.Application;
using Tiku.Infrastructure;
using Tiku.Infrastructure.Security;
using Tiku.Api.Caching;
using Tiku.Api.BackgroundProcessing;
using Microsoft.AspNetCore.ResponseCompression;
using System.IO.Compression;
using Tiku.Application.PlatformBilling;
using Tiku.Application.Security;
using Tiku.Application.Tenancy;
using Microsoft.Extensions.DependencyInjection.Extensions;
namespace Tiku.Api.Configuration;
public static class DependencyInjection
{
public static WebApplicationBuilder AddApiServices(this WebApplicationBuilder builder)
{
builder.Services.AddSerilog((services, configuration) => configuration
.ReadFrom.Configuration(builder.Configuration)
.ReadFrom.Services(services)
.Enrich.FromLogContext(),
preserveStaticLogger: true);
builder.Services.AddApiPresentation();
builder.Services.AddHealthChecks();
builder.Services.AddApiObservability(builder.Configuration, builder.Environment);
builder.Services.AddApplication();
builder.Services.AddNetworkConfiguration(builder.Configuration, builder.Environment);
builder.Services.AddApiRateLimiting(builder.Configuration);
var connectionString = Options.OptionsValidation.ResolveDatabaseConnectionString(
builder.Configuration,
builder.Environment.IsDevelopment());
builder.Services.AddInfrastructure(connectionString);
var redisConnectionString = builder.Configuration.GetConnectionString("Redis") ?? builder.Configuration["REDIS_URL"];
builder.Services.AddOptions<RedisSecurityConnectionOptions>()
.Configure(options => options.ConnectionString = redisConnectionString ?? string.Empty)
.Validate(
options => !builder.Environment.IsProduction() || !string.IsNullOrWhiteSpace(options.ConnectionString),
"Redis is required in Production.")
.ValidateOnStart();
if (!string.IsNullOrWhiteSpace(redisConnectionString))
{
builder.Services.AddRedisSecurity(redisConnectionString, builder.Environment.EnvironmentName);
}
else if (builder.Environment.IsProduction())
{
throw new InvalidOperationException(
"Redis is required in Production. Configure ConnectionStrings:Redis or REDIS_URL.");
}
builder.Services.AddOutputCache(options =>
{
options.AddPolicy("TenantPublic", new TenantPublicOutputCachePolicy());
options.DefaultExpirationTimeSpan = TimeSpan.FromSeconds(60);
});
builder.Services.RemoveAll<ITenantPublicCacheInvalidator>();
builder.Services.AddSingleton<ITenantPublicCacheInvalidator, TenantPublicCacheInvalidator>();
if (builder.Environment.IsProduction() && !string.IsNullOrWhiteSpace(redisConnectionString))
{
builder.Services.AddStackExchangeRedisOutputCache(options =>
{
options.Configuration = redisConnectionString;
options.InstanceName = $"tiku:{builder.Environment.EnvironmentName.ToLowerInvariant()}:output:";
});
}
builder.Services.AddResponseCompression(options =>
{
options.EnableForHttps = true;
options.Providers.Add<BrotliCompressionProvider>();
options.Providers.Add<GzipCompressionProvider>();
options.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(["application/json"]);
});
builder.Services.Configure<BrotliCompressionProviderOptions>(options => options.Level = CompressionLevel.Fastest);
builder.Services.Configure<GzipCompressionProviderOptions>(options => options.Level = CompressionLevel.Fastest);
builder.Services.AddOptions<BackgroundProcessingOptions>()
.Bind(builder.Configuration.GetSection(BackgroundProcessingOptions.SectionName))
.Validate(BackgroundProcessingOptions.BeValid, "Background processing settings are invalid.")
.ValidateOnStart();
builder.Services.AddOptions<DomainLifecycleOptions>()
.Bind(builder.Configuration.GetSection("TenantDomains"));
builder.Services.AddOptions<SaasSubscriptionLifecycleOptions>()
.Bind(builder.Configuration.GetSection("SaasSubscriptions"));
builder.Services.AddOptions<FeatureUsageReconciliationOptions>()
.Bind(builder.Configuration.GetSection("FeatureUsageReconciliation"));
builder.Services.AddHostedService<TenantDomainBackgroundService>();
builder.Services.AddHostedService<SaasSubscriptionBackgroundService>();
builder.Services.AddHostedService<FeatureUsageBackgroundService>();
builder.Services.AddHostedService<BackgroundJobsBackgroundService>();
builder.Services.AddApiDataProtection(builder.Configuration, builder.Environment);
builder.Services.AddExternalServiceOptions(builder.Configuration, builder.Environment);
builder.Services.AddApiAuthenticationAndAuthorization(builder.Configuration, builder.Environment);
return builder;
}
}