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 中兜底并记录日志。
}
}