refactor: 移除身份跨租户忽略租户过滤

This commit is contained in:
root
2026-01-29 13:48:31 +00:00
parent 8276174526
commit b3d611304b
9 changed files with 36 additions and 129 deletions

View File

@@ -9,15 +9,6 @@ namespace TakeoutSaaS.Infrastructure.Identity.Persistence;
/// </summary>
public sealed class EfIdentityUserRepository(IdentityDbContext dbContext) : IIdentityUserRepository
{
/// <summary>
/// 根据账号获取后台用户。
/// </summary>
/// <param name="account">账号。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>后台用户或 null。</returns>
public Task<IdentityUser?> FindByAccountAsync(string account, CancellationToken cancellationToken = default)
=> dbContext.IdentityUsers.AsNoTracking().FirstOrDefaultAsync(x => x.Account == account, cancellationToken);
/// <summary>
/// 根据租户与账号获取后台用户。
/// </summary>
@@ -143,19 +134,6 @@ public sealed class EfIdentityUserRepository(IdentityDbContext dbContext) : IIde
public Task<IdentityUser?> FindByIdAsync(long userId, CancellationToken cancellationToken = default)
=> dbContext.IdentityUsers.AsNoTracking().FirstOrDefaultAsync(x => x.Id == userId, cancellationToken);
/// <summary>
/// 根据 ID 获取后台用户(忽略租户过滤器,仅用于只读查询)。
/// </summary>
/// <param name="userId">用户 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>后台用户或 null。</returns>
public Task<IdentityUser?> FindByIdIgnoringTenantAsync(long userId, CancellationToken cancellationToken = default)
=> dbContext.IdentityUsers
.IgnoreQueryFilters()
.AsNoTracking()
.Where(x => x.DeletedAt == null)
.FirstOrDefaultAsync(x => x.Id == userId, cancellationToken);
/// <summary>
/// 根据 ID 获取后台用户(用于更新,返回可跟踪实体)。
/// </summary>
@@ -165,42 +143,23 @@ public sealed class EfIdentityUserRepository(IdentityDbContext dbContext) : IIde
public Task<IdentityUser?> GetForUpdateAsync(long userId, CancellationToken cancellationToken = default)
=> dbContext.IdentityUsers.FirstOrDefaultAsync(x => x.Id == userId, cancellationToken);
/// <summary>
/// 根据 ID 获取后台用户(用于更新,忽略租户过滤器)。
/// </summary>
/// <remarks>用于跨租户场景(如平台生成的重置密码链接)。</remarks>
/// <param name="userId">用户 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>后台用户或 null。</returns>
public Task<IdentityUser?> GetForUpdateIgnoringTenantAsync(long userId, CancellationToken cancellationToken = default)
=> dbContext.IdentityUsers
.IgnoreQueryFilters()
.Where(x => x.DeletedAt == null)
.FirstOrDefaultAsync(x => x.Id == userId, cancellationToken);
/// <summary>
/// 根据 ID 获取后台用户(用于更新,包含已删除数据)。
/// </summary>
/// <param name="tenantId">租户 ID。</param>
/// <param name="userId">用户 ID。</param>
/// <param name="ignoreTenantFilter">是否忽略租户过滤。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>后台用户或 null。</returns>
public Task<IdentityUser?> GetForUpdateIncludingDeletedAsync(
long tenantId,
long userId,
bool ignoreTenantFilter = false,
CancellationToken cancellationToken = default)
{
// 1. 构建查询(包含已删除数据)
var query = dbContext.IdentityUsers.IgnoreQueryFilters();
if (!ignoreTenantFilter)
{
query = query.Where(x => x.TenantId == tenantId);
}
// 2. 返回实体
return query.FirstOrDefaultAsync(x => x.Id == userId, cancellationToken);
// 1. 构建查询(包含已删除数据,但强制租户隔离
return dbContext.IdentityUsers
.IgnoreQueryFilters()
.Where(x => x.TenantId == tenantId)
.FirstOrDefaultAsync(x => x.Id == userId, cancellationToken);
}
/// <summary>
@@ -232,33 +191,28 @@ public sealed class EfIdentityUserRepository(IdentityDbContext dbContext) : IIde
/// 分页查询后台用户列表。
/// </summary>
/// <param name="filter">查询过滤条件。</param>
/// <param name="ignoreTenantFilter">是否忽略租户过滤器。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>分页结果。</returns>
public async Task<(IReadOnlyList<IdentityUser> Items, int Total)> SearchPagedAsync(
IdentityUserSearchFilter filter,
bool ignoreTenantFilter = false,
CancellationToken cancellationToken = default)
{
if (!filter.TenantId.HasValue || filter.TenantId.Value <= 0)
{
throw new InvalidOperationException("TenantId 不能为空且必须大于 0");
}
var tenantId = filter.TenantId.Value;
// 1. 构建基础查询
var query = dbContext.IdentityUsers.AsNoTracking();
if (ignoreTenantFilter || filter.IncludeDeleted)
if (filter.IncludeDeleted)
{
query = query.IgnoreQueryFilters();
}
// 2. 租户过滤
if (!ignoreTenantFilter)
{
if (filter.TenantId.HasValue && filter.TenantId.Value != 0)
{
query = query.Where(x => x.TenantId == filter.TenantId.Value);
}
}
else if (filter.TenantId.HasValue && filter.TenantId.Value != 0)
{
query = query.Where(x => x.TenantId == filter.TenantId.Value);
}
// 2. 租户过滤(强制)
query = query.Where(x => x.TenantId == tenantId);
if (!filter.IncludeDeleted)
{
@@ -288,22 +242,12 @@ public sealed class EfIdentityUserRepository(IdentityDbContext dbContext) : IIde
{
var roleId = filter.RoleId.Value;
var userRoles = dbContext.UserRoles.AsNoTracking();
if (ignoreTenantFilter || filter.IncludeDeleted)
if (filter.IncludeDeleted)
{
userRoles = userRoles.IgnoreQueryFilters();
}
if (!ignoreTenantFilter)
{
if (filter.TenantId.HasValue && filter.TenantId.Value != 0)
{
userRoles = userRoles.Where(x => x.TenantId == filter.TenantId.Value);
}
}
else if (filter.TenantId.HasValue && filter.TenantId.Value != 0)
{
userRoles = userRoles.Where(x => x.TenantId == filter.TenantId.Value);
}
userRoles = userRoles.Where(x => x.TenantId == tenantId);
if (!filter.IncludeDeleted)
{
@@ -373,11 +317,12 @@ public sealed class EfIdentityUserRepository(IdentityDbContext dbContext) : IIde
/// <param name="userIds">用户 ID 集合。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>后台用户列表。</returns>
public Task<IReadOnlyList<IdentityUser>> GetByIdsAsync(long tenantId, IEnumerable<long> userIds, CancellationToken cancellationToken = default)
=> dbContext.IdentityUsers.AsNoTracking()
public async Task<IReadOnlyList<IdentityUser>> GetByIdsAsync(long tenantId, IEnumerable<long> userIds, CancellationToken cancellationToken = default)
{
return await dbContext.IdentityUsers.AsNoTracking()
.Where(x => x.TenantId == tenantId && userIds.Contains(x.Id))
.ToListAsync(cancellationToken)
.ContinueWith(t => (IReadOnlyList<IdentityUser>)t.Result, cancellationToken);
.ToListAsync(cancellationToken);
}
/// <summary>
/// 批量获取后台用户(可用于更新,支持包含已删除数据)。
@@ -385,33 +330,28 @@ public sealed class EfIdentityUserRepository(IdentityDbContext dbContext) : IIde
/// <param name="tenantId">租户 ID。</param>
/// <param name="userIds">用户 ID 集合。</param>
/// <param name="includeDeleted">是否包含已删除数据。</param>
/// <param name="ignoreTenantFilter">是否忽略租户过滤器。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>后台用户列表。</returns>
public Task<IReadOnlyList<IdentityUser>> GetForUpdateByIdsAsync(
public async Task<IReadOnlyList<IdentityUser>> GetForUpdateByIdsAsync(
long tenantId,
IEnumerable<long> userIds,
bool includeDeleted,
bool ignoreTenantFilter = false,
CancellationToken cancellationToken = default)
{
// 1. 构建基础查询
var ids = userIds.Distinct().ToArray();
if (ids.Length == 0)
{
return Task.FromResult<IReadOnlyList<IdentityUser>>(Array.Empty<IdentityUser>());
return Array.Empty<IdentityUser>();
}
var query = dbContext.IdentityUsers.Where(x => ids.Contains(x.Id));
if (ignoreTenantFilter || includeDeleted)
if (includeDeleted)
{
query = query.IgnoreQueryFilters();
}
if (!ignoreTenantFilter)
{
query = query.Where(x => x.TenantId == tenantId);
}
query = query.Where(x => x.TenantId == tenantId);
if (!includeDeleted)
{
@@ -419,8 +359,7 @@ public sealed class EfIdentityUserRepository(IdentityDbContext dbContext) : IIde
}
// 2. 返回列表
return query.ToListAsync(cancellationToken)
.ContinueWith(t => (IReadOnlyList<IdentityUser>)t.Result, cancellationToken);
return await query.ToListAsync(cancellationToken);
}
/// <summary>