92 lines
4.2 KiB
C#
92 lines
4.2 KiB
C#
using Microsoft.AspNetCore.Identity;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Microsoft.Extensions.Logging;
|
|
using Microsoft.Extensions.Options;
|
|
using Npgsql;
|
|
using StackExchange.Redis;
|
|
using Tiku.Application.Security;
|
|
using Tiku.Domain.Identity;
|
|
using Tiku.Infrastructure.Auth;
|
|
using Tiku.Infrastructure.Observability;
|
|
using Tiku.Infrastructure.Persistence;
|
|
using Tiku.Infrastructure.Security;
|
|
|
|
namespace Tiku.Infrastructure;
|
|
|
|
public static class DependencyInjection
|
|
{
|
|
public static IServiceCollection AddInfrastructure(
|
|
this IServiceCollection services,
|
|
string connectionString,
|
|
Action<DbContextOptionsBuilder>? configureDatabase = null)
|
|
{
|
|
ArgumentException.ThrowIfNullOrWhiteSpace(connectionString);
|
|
|
|
services.AddSingleton(_ => NpgsqlDataSource.Create(connectionString));
|
|
services.AddScoped<TenantIsolationSaveChangesInterceptor>();
|
|
services.AddSingleton<DatabasePerformanceInterceptor>();
|
|
services.AddDbContext<TikuDbContext>((serviceProvider, options) =>
|
|
{
|
|
var dataSource = serviceProvider.GetRequiredService<NpgsqlDataSource>();
|
|
options.UseNpgsql(dataSource, npgsql =>
|
|
npgsql.MigrationsAssembly(typeof(TikuDbContext).Assembly.FullName));
|
|
configureDatabase?.Invoke(options);
|
|
options.AddInterceptors(
|
|
serviceProvider.GetRequiredService<TenantIsolationSaveChangesInterceptor>(),
|
|
serviceProvider.GetRequiredService<DatabasePerformanceInterceptor>());
|
|
});
|
|
services.AddIdentityCore<User>(options =>
|
|
{
|
|
options.Password.RequiredLength = 8;
|
|
options.Password.RequireDigit = false;
|
|
options.Password.RequireLowercase = false;
|
|
options.Password.RequireUppercase = false;
|
|
options.Password.RequireNonAlphanumeric = false;
|
|
options.Lockout.MaxFailedAccessAttempts = 5;
|
|
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(15);
|
|
options.User.RequireUniqueEmail = false;
|
|
})
|
|
.AddEntityFrameworkStores<TikuDbContext>()
|
|
.AddSignInManager()
|
|
.AddDefaultTokenProviders()
|
|
.AddPasswordValidator<LetterAndDigitPasswordValidator<User>>();
|
|
services.Configure<PasswordHasherOptions>(options => options.IterationCount = 210_000);
|
|
services.AddPlatformCoreModule();
|
|
services.AddAuthModule();
|
|
services.AddContentModule();
|
|
services.AddLearningModule();
|
|
services.AddTenantAdminModule();
|
|
services.AddCommerceModule();
|
|
services.AddJobsModule();
|
|
services.AddPlatformModule();
|
|
|
|
return services;
|
|
}
|
|
|
|
public static IServiceCollection AddRedisSecurity(
|
|
this IServiceCollection services,
|
|
string connectionString,
|
|
string environmentName)
|
|
{
|
|
ArgumentException.ThrowIfNullOrWhiteSpace(connectionString);
|
|
var options = ConfigurationOptions.Parse(connectionString);
|
|
options.AbortOnConnectFail = false;
|
|
options.ClientName = $"tiku-{environmentName.ToLowerInvariant()}";
|
|
services.AddSingleton<IConnectionMultiplexer>(_ => ConnectionMultiplexer.Connect(options));
|
|
services.AddSingleton(provider => new RedisSecurityStore(
|
|
provider.GetRequiredService<IConnectionMultiplexer>(),
|
|
environmentName,
|
|
provider.GetRequiredService<ILogger<RedisSecurityStore>>()));
|
|
services.AddSingleton<IRedisSecurityStore>(provider => provider.GetRequiredService<RedisSecurityStore>());
|
|
services.AddSingleton(provider => new RedisAuthorizationCache(
|
|
provider.GetRequiredService<IConnectionMultiplexer>(),
|
|
provider.GetRequiredService<IOptions<AuthorizationCacheOptions>>(),
|
|
environmentName));
|
|
services.AddSingleton<IAccessSecurityCache>(provider => provider.GetRequiredService<RedisAuthorizationCache>());
|
|
services.AddSingleton<IAuthorizationSnapshotCache>(provider =>
|
|
provider.GetRequiredService<RedisAuthorizationCache>());
|
|
services.AddStackExchangeRedisCache(cache => cache.ConfigurationOptions = options);
|
|
return services;
|
|
}
|
|
} |