forked from xiongyuxing/tiku-backend.net
feat(security): add distributed authorization foundation
This commit is contained in:
@@ -44,6 +44,9 @@ using Tiku.Infrastructure.StudyContent;
|
||||
using Tiku.Infrastructure.TenantAdmin;
|
||||
using Tiku.Infrastructure.Tenancy;
|
||||
using Tiku.Domain.Identity;
|
||||
using StackExchange.Redis;
|
||||
using MassTransit;
|
||||
using Tiku.Infrastructure.Messaging;
|
||||
|
||||
namespace Tiku.Infrastructure;
|
||||
|
||||
@@ -83,6 +86,8 @@ public static class DependencyInjection
|
||||
.AddPasswordValidator<LetterAndDigitPasswordValidator<User>>();
|
||||
services.Configure<PasswordHasherOptions>(options => options.IterationCount = 210_000);
|
||||
services.AddScoped<ITenantDirectory, TenantDirectory>();
|
||||
services.AddSingleton<IRedisSecurityStore, NullRedisSecurityStore>();
|
||||
services.AddScoped<ISecurityEventPublisher, NullSecurityEventPublisher>();
|
||||
services.AddMemoryCache();
|
||||
services.AddScoped<ITenantFrontendConfigService, TenantFrontendConfigService>();
|
||||
services.AddScoped<ITenantExternalProviderConfigService, TenantExternalProviderConfigService>();
|
||||
@@ -121,6 +126,7 @@ public static class DependencyInjection
|
||||
services.AddScoped<IBackofficeService, BackofficeService>();
|
||||
services.AddScoped<IPlatformAdminService, PlatformAdminService>();
|
||||
services.AddScoped<ICurrentAccessContext, CurrentAccessContext>();
|
||||
services.AddScoped<ICapabilityAccessEvaluator, CapabilityAccessEvaluator>();
|
||||
services.AddScoped<IOperationAuditService, OperationAuditService>();
|
||||
services.AddScoped<IBackgroundJobService, BackgroundJobService>();
|
||||
services.AddScoped<ICommerceService, CommerceService>();
|
||||
@@ -150,4 +156,78 @@ public static class DependencyInjection
|
||||
|
||||
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<Microsoft.Extensions.Logging.ILogger<RedisSecurityStore>>()));
|
||||
services.AddSingleton<IRedisSecurityStore>(provider => provider.GetRequiredService<RedisSecurityStore>());
|
||||
services.AddStackExchangeRedisCache(cache => cache.ConfigurationOptions = options);
|
||||
return services;
|
||||
}
|
||||
|
||||
public static IServiceCollection AddReliableMessaging(
|
||||
this IServiceCollection services,
|
||||
MessagingOptions options)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(options);
|
||||
if (!options.IsConfigured)
|
||||
{
|
||||
throw new ArgumentException("A valid RabbitMQ host URI is required.", nameof(options));
|
||||
}
|
||||
|
||||
services.AddMassTransit(registration =>
|
||||
{
|
||||
registration.SetKebabCaseEndpointNameFormatter();
|
||||
registration.ConfigureHealthCheckOptions(health =>
|
||||
{
|
||||
health.Name = "rabbitmq";
|
||||
health.Tags.Add("ready");
|
||||
});
|
||||
registration.AddEntityFrameworkOutbox<TikuDbContext>(outbox =>
|
||||
{
|
||||
outbox.UsePostgres();
|
||||
outbox.UseBusOutbox();
|
||||
outbox.QueryDelay = TimeSpan.FromSeconds(1);
|
||||
outbox.DuplicateDetectionWindow = TimeSpan.FromMinutes(30);
|
||||
});
|
||||
if (options.ConfigureConsumers)
|
||||
{
|
||||
registration.AddConsumer<SecurityStateChangedConsumer>(consumer =>
|
||||
{
|
||||
consumer.ConcurrentMessageLimit = 1;
|
||||
consumer.UseMessageRetry(retry => retry.Intervals(
|
||||
TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(15)));
|
||||
});
|
||||
registration.AddConfigureEndpointsCallback((context, _, endpoint) =>
|
||||
{
|
||||
endpoint.PrefetchCount = 1;
|
||||
endpoint.ConcurrentMessageLimit = 1;
|
||||
endpoint.UseEntityFrameworkOutbox<TikuDbContext>(context);
|
||||
});
|
||||
}
|
||||
|
||||
registration.UsingRabbitMq((context, configurator) =>
|
||||
{
|
||||
configurator.Host(new Uri(options.Host), options.VirtualHost, host =>
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(options.Username)) host.Username(options.Username);
|
||||
if (!string.IsNullOrWhiteSpace(options.Password)) host.Password(options.Password);
|
||||
});
|
||||
configurator.ConfigureEndpoints(context);
|
||||
});
|
||||
});
|
||||
services.AddScoped<ISecurityEventPublisher, MassTransitSecurityEventPublisher>();
|
||||
return services;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user