using System; using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using TakeoutSaaS.Application.Identity.Abstractions; using TakeoutSaaS.Domain.Identity.Entities; using TakeoutSaaS.Domain.Identity.Repositories; using TakeoutSaaS.Infrastructure.Common.Extensions; using TakeoutSaaS.Infrastructure.Common.Options; using TakeoutSaaS.Infrastructure.Identity.Options; using TakeoutSaaS.Infrastructure.Identity.Persistence; using TakeoutSaaS.Infrastructure.Identity.Services; using TakeoutSaaS.Shared.Abstractions.Constants; using DomainIdentityUser = TakeoutSaaS.Domain.Identity.Entities.IdentityUser; namespace TakeoutSaaS.Infrastructure.Identity.Extensions; /// /// 身份认证基础设施注入。 /// public static class ServiceCollectionExtensions { /// /// 注册身份认证基础设施(数据库、Redis、JWT、限流等)。 /// /// 服务集合。 /// 配置源。 /// 是否启用小程序相关依赖(如微信登录)。 /// 是否启用后台账号初始化。 /// 服务集合。 /// 配置缺失时抛出。 public static IServiceCollection AddIdentityInfrastructure( this IServiceCollection services, IConfiguration configuration, bool enableMiniFeatures = false, bool enableAdminSeed = false) { services.AddDatabaseInfrastructure(configuration); services.AddPostgresDbContext(DatabaseConstants.IdentityDataSource); var redisConnection = configuration.GetConnectionString("Redis"); if (string.IsNullOrWhiteSpace(redisConnection)) { throw new InvalidOperationException("缺少 Redis 连接字符串配置。"); } services.AddStackExchangeRedisCache(options => { options.Configuration = redisConnection; }); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped, PasswordHasher>(); services.AddOptions() .Bind(configuration.GetSection("Identity:Jwt")) .ValidateDataAnnotations() .ValidateOnStart(); services.AddOptions() .Bind(configuration.GetSection("Identity:LoginRateLimit")) .ValidateDataAnnotations() .ValidateOnStart(); services.AddOptions() .Bind(configuration.GetSection("Identity:RefreshTokenStore")); if (enableMiniFeatures) { services.AddOptions() .Bind(configuration.GetSection("Identity:WeChatMini")) .ValidateDataAnnotations() .ValidateOnStart(); services.AddHttpClient(client => { client.BaseAddress = new Uri("https://api.weixin.qq.com/"); client.Timeout = TimeSpan.FromSeconds(10); }); } if (enableAdminSeed) { services.AddOptions() .Bind(configuration.GetSection("Identity:AdminSeed")) .ValidateDataAnnotations() .ValidateOnStart(); services.AddHostedService(); } return services; } /// /// 确保数据库连接已配置(Database 节或 ConnectionStrings)。 /// /// 配置源。 /// 数据源名称。 /// 未配置时抛出。 private static void EnsureDatabaseConnectionConfigured(IConfiguration configuration, string dataSourceName) { // 保留兼容接口,当前逻辑在 DatabaseConnectionFactory 中兜底并记录日志。 } }