fix: 自助注册回填主管理员
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
using MediatR;
|
||||
using TakeoutSaaS.Application.App.Tenants.Commands;
|
||||
using TakeoutSaaS.Application.Identity.Abstractions;
|
||||
using TakeoutSaaS.Domain.Identity.Repositories;
|
||||
using TakeoutSaaS.Domain.Tenants.Entities;
|
||||
using TakeoutSaaS.Domain.Tenants.Enums;
|
||||
using TakeoutSaaS.Domain.Tenants.Repositories;
|
||||
@@ -17,6 +18,8 @@ namespace TakeoutSaaS.Application.App.Tenants.Handlers;
|
||||
public sealed class CreateTenantAdminResetLinkTokenCommandHandler(
|
||||
ITenantRepository tenantRepository,
|
||||
ITenantProvider tenantProvider,
|
||||
ITenantContextAccessor tenantContextAccessor,
|
||||
IIdentityUserRepository identityUserRepository,
|
||||
ICurrentUserAccessor currentUserAccessor,
|
||||
IAdminAuthService adminAuthService,
|
||||
IAdminPasswordResetTokenStore tokenStore)
|
||||
@@ -38,9 +41,28 @@ public sealed class CreateTenantAdminResetLinkTokenCommandHandler(
|
||||
var tenant = await tenantRepository.FindByIdAsync(request.TenantId, cancellationToken)
|
||||
?? throw new BusinessException(ErrorCodes.NotFound, "租户不存在");
|
||||
|
||||
// 2.1 (空行后) 若缺少主管理员则自动回填(兼容历史数据)
|
||||
if (!tenant.PrimaryOwnerUserId.HasValue || tenant.PrimaryOwnerUserId.Value == 0)
|
||||
{
|
||||
throw new BusinessException(ErrorCodes.BadRequest, "该租户未配置主管理员账号,无法生成重置链接");
|
||||
var originalContextForFix = tenantContextAccessor.Current;
|
||||
tenantContextAccessor.Current = new TenantContext(tenant.Id, tenant.Code, "admin:reset-link:fix-owner");
|
||||
try
|
||||
{
|
||||
var users = await identityUserRepository.SearchAsync(tenant.Id, keyword: null, cancellationToken);
|
||||
var ownerCandidate = users.OrderBy(x => x.CreatedAt).FirstOrDefault();
|
||||
if (ownerCandidate == null)
|
||||
{
|
||||
throw new BusinessException(ErrorCodes.BadRequest, "该租户未配置主管理员账号,且未找到可用管理员账号");
|
||||
}
|
||||
|
||||
tenant.PrimaryOwnerUserId = ownerCandidate.Id;
|
||||
await tenantRepository.UpdateTenantAsync(tenant, cancellationToken);
|
||||
await tenantRepository.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
finally
|
||||
{
|
||||
tenantContextAccessor.Current = originalContextForFix;
|
||||
}
|
||||
}
|
||||
|
||||
// 3. (空行后) 签发一次性重置令牌(默认 24 小时有效)
|
||||
@@ -70,4 +92,3 @@ public sealed class CreateTenantAdminResetLinkTokenCommandHandler(
|
||||
return token;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ using MediatR;
|
||||
using TakeoutSaaS.Application.App.Tenants.Commands;
|
||||
using TakeoutSaaS.Application.Identity.Abstractions;
|
||||
using TakeoutSaaS.Application.Identity.Contracts;
|
||||
using TakeoutSaaS.Domain.Identity.Repositories;
|
||||
using TakeoutSaaS.Domain.Tenants.Entities;
|
||||
using TakeoutSaaS.Domain.Tenants.Enums;
|
||||
using TakeoutSaaS.Domain.Tenants.Repositories;
|
||||
@@ -19,6 +20,7 @@ public sealed class ImpersonateTenantCommandHandler(
|
||||
ITenantRepository tenantRepository,
|
||||
ITenantProvider tenantProvider,
|
||||
ITenantContextAccessor tenantContextAccessor,
|
||||
IIdentityUserRepository identityUserRepository,
|
||||
ICurrentUserAccessor currentUserAccessor,
|
||||
IAdminAuthService adminAuthService,
|
||||
IJwtTokenService jwtTokenService)
|
||||
@@ -46,9 +48,28 @@ public sealed class ImpersonateTenantCommandHandler(
|
||||
var tenant = await tenantRepository.FindByIdAsync(request.TenantId, cancellationToken)
|
||||
?? throw new BusinessException(ErrorCodes.NotFound, "租户不存在");
|
||||
|
||||
// 2.1 (空行后) 若缺少主管理员则自动回填(兼容历史数据)
|
||||
if (!tenant.PrimaryOwnerUserId.HasValue || tenant.PrimaryOwnerUserId.Value == 0)
|
||||
{
|
||||
throw new BusinessException(ErrorCodes.BadRequest, "该租户未配置主管理员账号,无法伪装登录");
|
||||
var originalContextForFix = tenantContextAccessor.Current;
|
||||
tenantContextAccessor.Current = new TenantContext(tenant.Id, tenant.Code, "admin:impersonate:fix-owner");
|
||||
try
|
||||
{
|
||||
var users = await identityUserRepository.SearchAsync(tenant.Id, keyword: null, cancellationToken);
|
||||
var ownerCandidate = users.OrderBy(x => x.CreatedAt).FirstOrDefault();
|
||||
if (ownerCandidate == null)
|
||||
{
|
||||
throw new BusinessException(ErrorCodes.BadRequest, "该租户未配置主管理员账号,且未找到可用管理员账号");
|
||||
}
|
||||
|
||||
tenant.PrimaryOwnerUserId = ownerCandidate.Id;
|
||||
await tenantRepository.UpdateTenantAsync(tenant, cancellationToken);
|
||||
await tenantRepository.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
finally
|
||||
{
|
||||
tenantContextAccessor.Current = originalContextForFix;
|
||||
}
|
||||
}
|
||||
|
||||
// 3. (空行后) 进入目标租户上下文以读取租户内用户(避免多租户查询过滤导致找不到用户)
|
||||
|
||||
@@ -95,6 +95,11 @@ public sealed class SelfRegisterTenantCommandHandler(
|
||||
await identityUserRepository.AddAsync(adminUser, cancellationToken);
|
||||
await identityUserRepository.SaveChangesAsync(cancellationToken);
|
||||
|
||||
// 7.1 (空行后) 回填主管理员标识,确保后续伪装登录/重置管理员等能力可用
|
||||
tenant.PrimaryOwnerUserId = adminUser.Id;
|
||||
await tenantRepository.UpdateTenantAsync(tenant, cancellationToken);
|
||||
await tenantRepository.SaveChangesAsync(cancellationToken);
|
||||
|
||||
// 8. 初始化租户管理员角色模板
|
||||
await mediator.Send(new InitializeRoleTemplatesCommand
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user