chore: 同步当前开发内容

This commit is contained in:
2025-11-23 01:25:20 +08:00
parent ddf584f212
commit 1169e1f220
58 changed files with 1886 additions and 82 deletions

View File

@@ -0,0 +1,99 @@
using System;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
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.Identity.Options;
using TakeoutSaaS.Infrastructure.Identity.Persistence;
using TakeoutSaaS.Infrastructure.Identity.Services;
using DomainIdentityUser = TakeoutSaaS.Domain.Identity.Entities.IdentityUser;
namespace TakeoutSaaS.Infrastructure.Identity.Extensions;
/// <summary>
/// 身份认证基础设施注入
/// </summary>
public static class ServiceCollectionExtensions
{
/// <summary>
/// 注册身份认证基础设施数据库、Redis、JWT、限流等
/// </summary>
/// <param name="services">服务集合</param>
/// <param name="configuration">配置源</param>
/// <param name="enableMiniFeatures">是否启用小程序相关依赖(如微信登录)</param>
/// <param name="enableAdminSeed">是否启用后台账号初始化</param>
public static IServiceCollection AddIdentityInfrastructure(
this IServiceCollection services,
IConfiguration configuration,
bool enableMiniFeatures = false,
bool enableAdminSeed = false)
{
var dbConnection = configuration.GetConnectionString("IdentityDatabase");
if (string.IsNullOrWhiteSpace(dbConnection))
{
throw new InvalidOperationException("缺少 IdentityDatabase 连接字符串配置");
}
services.AddDbContext<IdentityDbContext>(options => options.UseNpgsql(dbConnection));
var redisConnection = configuration.GetConnectionString("Redis");
if (string.IsNullOrWhiteSpace(redisConnection))
{
throw new InvalidOperationException("缺少 Redis 连接字符串配置");
}
services.AddStackExchangeRedisCache(options =>
{
options.Configuration = redisConnection;
});
services.AddScoped<IIdentityUserRepository, EfIdentityUserRepository>();
services.AddScoped<IMiniUserRepository, EfMiniUserRepository>();
services.AddScoped<IJwtTokenService, JwtTokenService>();
services.AddScoped<IRefreshTokenStore, RedisRefreshTokenStore>();
services.AddScoped<ILoginRateLimiter, RedisLoginRateLimiter>();
services.AddScoped<IPasswordHasher<DomainIdentityUser>, PasswordHasher<DomainIdentityUser>>();
services.AddOptions<JwtOptions>()
.Bind(configuration.GetSection("Identity:Jwt"))
.ValidateDataAnnotations()
.ValidateOnStart();
services.AddOptions<LoginRateLimitOptions>()
.Bind(configuration.GetSection("Identity:LoginRateLimit"))
.ValidateDataAnnotations()
.ValidateOnStart();
services.AddOptions<RefreshTokenStoreOptions>()
.Bind(configuration.GetSection("Identity:RefreshTokenStore"));
if (enableMiniFeatures)
{
services.AddOptions<WeChatMiniOptions>()
.Bind(configuration.GetSection("Identity:WeChatMini"))
.ValidateDataAnnotations()
.ValidateOnStart();
services.AddHttpClient<IWeChatAuthService, WeChatAuthService>(client =>
{
client.BaseAddress = new Uri("https://api.weixin.qq.com/");
client.Timeout = TimeSpan.FromSeconds(10);
});
}
if (enableAdminSeed)
{
services.AddOptions<AdminSeedOptions>()
.Bind(configuration.GetSection("Identity:AdminSeed"))
.ValidateDataAnnotations()
.ValidateOnStart();
services.AddHostedService<IdentityDataSeeder>();
}
return services;
}
}