diff --git a/src/Application/TakeoutSaaS.Application/Identity/Contracts/PermissionDto.cs b/src/Application/TakeoutSaaS.Application/Identity/Contracts/PermissionDto.cs
index f25dc09..115f95e 100644
--- a/src/Application/TakeoutSaaS.Application/Identity/Contracts/PermissionDto.cs
+++ b/src/Application/TakeoutSaaS.Application/Identity/Contracts/PermissionDto.cs
@@ -14,12 +14,6 @@ public sealed class PermissionDto
[JsonConverter(typeof(SnowflakeIdJsonConverter))]
public long Id { get; init; }
- ///
- /// 租户 ID(固定权限时为基准租户)。
- ///
- [JsonConverter(typeof(SnowflakeIdJsonConverter))]
- public long TenantId { get; init; }
-
///
/// 父级权限 ID。
///
diff --git a/src/Application/TakeoutSaaS.Application/Identity/Contracts/PermissionTreeDto.cs b/src/Application/TakeoutSaaS.Application/Identity/Contracts/PermissionTreeDto.cs
index a4dac6c..2a5bf73 100644
--- a/src/Application/TakeoutSaaS.Application/Identity/Contracts/PermissionTreeDto.cs
+++ b/src/Application/TakeoutSaaS.Application/Identity/Contracts/PermissionTreeDto.cs
@@ -14,12 +14,6 @@ public sealed record PermissionTreeDto
[JsonConverter(typeof(SnowflakeIdJsonConverter))]
public long Id { get; init; }
- ///
- /// 租户 ID(雪花,序列化为字符串)。
- ///
- [JsonConverter(typeof(SnowflakeIdJsonConverter))]
- public long TenantId { get; init; }
-
///
/// 父级权限 ID。
///
@@ -42,7 +36,7 @@ public sealed record PermissionTreeDto
public string Name { get; init; } = string.Empty;
///
- /// 权限编码(租户内唯一)。
+ /// 权限编码(全局唯一)。
///
public string Code { get; init; } = string.Empty;
diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/CopyRoleTemplateCommandHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/CopyRoleTemplateCommandHandler.cs
index 807371a..cc840af 100644
--- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/CopyRoleTemplateCommandHandler.cs
+++ b/src/Application/TakeoutSaaS.Application/Identity/Handlers/CopyRoleTemplateCommandHandler.cs
@@ -81,7 +81,6 @@ public sealed class CopyRoleTemplateCommandHandler(
var permission = new Permission
{
- TenantId = tenantId,
Name = code,
Code = code,
Description = code
diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/CreateMenuCommandHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/CreateMenuCommandHandler.cs
index eeda175..9ae4bc3 100644
--- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/CreateMenuCommandHandler.cs
+++ b/src/Application/TakeoutSaaS.Application/Identity/Handlers/CreateMenuCommandHandler.cs
@@ -3,19 +3,17 @@ using TakeoutSaaS.Application.Identity.Commands;
using TakeoutSaaS.Application.Identity.Contracts;
using TakeoutSaaS.Application.Identity;
using TakeoutSaaS.Domain.Identity.Entities;
+using TakeoutSaaS.Domain.Identity.Enums;
using TakeoutSaaS.Domain.Identity.Repositories;
using TakeoutSaaS.Shared.Abstractions.Constants;
using TakeoutSaaS.Shared.Abstractions.Exceptions;
-using TakeoutSaaS.Shared.Abstractions.Tenancy;
namespace TakeoutSaaS.Application.Identity.Handlers;
///
/// 创建菜单处理器。
///
-public sealed class CreateMenuCommandHandler(
- IMenuRepository menuRepository,
- ITenantProvider tenantProvider)
+public sealed class CreateMenuCommandHandler(IMenuRepository menuRepository)
: IRequestHandler
{
///
@@ -28,10 +26,9 @@ public sealed class CreateMenuCommandHandler(
}
// 2. 构造实体
- var tenantId = tenantProvider.GetCurrentTenantId();
var entity = new MenuDefinition
{
- TenantId = tenantId,
+ Portal = PortalType.Tenant,
ParentId = request.ParentId,
Name = request.Name.Trim(),
Path = request.Path.Trim(),
diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/CreatePermissionCommandHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/CreatePermissionCommandHandler.cs
index 8cf4ec2..cc7cfee 100644
--- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/CreatePermissionCommandHandler.cs
+++ b/src/Application/TakeoutSaaS.Application/Identity/Handlers/CreatePermissionCommandHandler.cs
@@ -43,7 +43,6 @@ public sealed class CreatePermissionCommandHandler(
var sortOrder = request.SortOrder < 0 ? 0 : request.SortOrder;
var permission = new Permission
{
- TenantId = tenantId,
ParentId = parentId,
SortOrder = sortOrder,
Type = normalizedType,
@@ -60,7 +59,6 @@ public sealed class CreatePermissionCommandHandler(
return new PermissionDto
{
Id = permission.Id,
- TenantId = permission.TenantId,
ParentId = permission.ParentId,
SortOrder = permission.SortOrder,
Type = permission.Type,
diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/DeleteMenuCommandHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/DeleteMenuCommandHandler.cs
index 6e8da19..545729f 100644
--- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/DeleteMenuCommandHandler.cs
+++ b/src/Application/TakeoutSaaS.Application/Identity/Handlers/DeleteMenuCommandHandler.cs
@@ -4,16 +4,13 @@ using TakeoutSaaS.Application.Identity.Commands;
using TakeoutSaaS.Domain.Identity.Repositories;
using TakeoutSaaS.Shared.Abstractions.Constants;
using TakeoutSaaS.Shared.Abstractions.Exceptions;
-using TakeoutSaaS.Shared.Abstractions.Tenancy;
namespace TakeoutSaaS.Application.Identity.Handlers;
///
/// 删除菜单处理器。
///
-public sealed class DeleteMenuCommandHandler(
- IMenuRepository menuRepository,
- ITenantProvider tenantProvider)
+public sealed class DeleteMenuCommandHandler(IMenuRepository menuRepository)
: IRequestHandler
{
///
@@ -25,9 +22,8 @@ public sealed class DeleteMenuCommandHandler(
throw new BusinessException(ErrorCodes.Forbidden, "菜单已固定,禁止删除");
}
- // 2. 删除目标及可能的孤儿由外层保证
- var tenantId = tenantProvider.GetCurrentTenantId();
- await menuRepository.DeleteAsync(request.Id, tenantId, cancellationToken);
+ // 2. 删除目标
+ await menuRepository.DeleteAsync(request.Id, cancellationToken);
// 3. 持久化
await menuRepository.SaveChangesAsync(cancellationToken);
diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/ListMenusQueryHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/ListMenusQueryHandler.cs
index 08b14b6..c224928 100644
--- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/ListMenusQueryHandler.cs
+++ b/src/Application/TakeoutSaaS.Application/Identity/Handlers/ListMenusQueryHandler.cs
@@ -1,32 +1,27 @@
using MediatR;
using TakeoutSaaS.Application.Identity.Contracts;
using TakeoutSaaS.Application.Identity.Queries;
+using TakeoutSaaS.Domain.Identity.Enums;
using TakeoutSaaS.Domain.Identity.Repositories;
-using TakeoutSaaS.Shared.Abstractions.Tenancy;
namespace TakeoutSaaS.Application.Identity.Handlers;
///
/// 菜单列表查询处理器。
///
-public sealed class ListMenusQueryHandler(
- IMenuRepository menuRepository,
- ITenantProvider tenantProvider)
+public sealed class ListMenusQueryHandler(IMenuRepository menuRepository)
: IRequestHandler>
{
///
public async Task> Handle(ListMenusQuery request, CancellationToken cancellationToken)
{
- // 1. 获取租户
- var tenantId = tenantProvider.GetCurrentTenantId();
+ // 1. 查询租户端菜单
+ var entities = await menuRepository.GetByPortalAsync(PortalType.Tenant, cancellationToken);
- // 2. 查询列表
- var entities = await menuRepository.GetByTenantAsync(tenantId, cancellationToken);
-
- // 3. 映射 DTO
+ // 2. 映射 DTO
var items = entities.Select(MenuMapper.ToDto).ToList();
- // 4. 返回结果
+ // 3. 返回结果
return items;
}
}
diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/MenuDetailQueryHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/MenuDetailQueryHandler.cs
index e681bc3..5e89430 100644
--- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/MenuDetailQueryHandler.cs
+++ b/src/Application/TakeoutSaaS.Application/Identity/Handlers/MenuDetailQueryHandler.cs
@@ -2,32 +2,26 @@ using MediatR;
using TakeoutSaaS.Application.Identity.Contracts;
using TakeoutSaaS.Application.Identity.Queries;
using TakeoutSaaS.Domain.Identity.Repositories;
-using TakeoutSaaS.Shared.Abstractions.Tenancy;
namespace TakeoutSaaS.Application.Identity.Handlers;
///
/// 菜单详情查询处理器。
///
-public sealed class MenuDetailQueryHandler(
- IMenuRepository menuRepository,
- ITenantProvider tenantProvider)
+public sealed class MenuDetailQueryHandler(IMenuRepository menuRepository)
: IRequestHandler
{
///
public async Task Handle(MenuDetailQuery request, CancellationToken cancellationToken)
{
- // 1. 获取租户
- var tenantId = tenantProvider.GetCurrentTenantId();
-
- // 2. 查询实体
- var entity = await menuRepository.FindByIdAsync(request.Id, tenantId, cancellationToken);
+ // 1. 查询实体
+ var entity = await menuRepository.FindByIdAsync(request.Id, cancellationToken);
if (entity is null)
{
return null;
}
- // 3. 映射并返回
+ // 2. 映射并返回
return MenuMapper.ToDto(entity);
}
}
diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/MenuMapper.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/MenuMapper.cs
index 9d68488..22c39f3 100644
--- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/MenuMapper.cs
+++ b/src/Application/TakeoutSaaS.Application/Identity/Handlers/MenuMapper.cs
@@ -1,6 +1,7 @@
using System.Text.Json;
using TakeoutSaaS.Application.Identity.Contracts;
using TakeoutSaaS.Domain.Identity.Entities;
+using TakeoutSaaS.Domain.Identity.Enums;
namespace TakeoutSaaS.Application.Identity.Handlers;
@@ -79,23 +80,22 @@ internal static class MenuMapper
/// 构建或更新菜单实体并返回 DTO。
///
/// 已存在的菜单实体。
- /// 租户 ID。
- /// 菜单名称。
+ /// 门户类型。
/// 菜单 DTO 载荷。
/// 菜单定义 DTO。
- public static MenuDefinitionDto FromCommand(MenuDefinition? existing, long tenantId, string name, MenuDefinitionDto payload)
+ public static MenuDefinitionDto FromCommand(MenuDefinition? existing, PortalType portal, MenuDefinitionDto payload)
{
// 1. 构造实体
var entity = existing ?? new MenuDefinition
{
- TenantId = tenantId,
+ Portal = portal,
CreatedAt = DateTime.UtcNow
};
- // // 填充字段
+ // 2. 填充字段
FillEntity(entity, payload);
- // 2. 返回 DTO 映射
+ // 3. 返回 DTO 映射
return ToDto(entity);
}
diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/PermissionTreeQueryHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/PermissionTreeQueryHandler.cs
index e134b54..64ef3e3 100644
--- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/PermissionTreeQueryHandler.cs
+++ b/src/Application/TakeoutSaaS.Application/Identity/Handlers/PermissionTreeQueryHandler.cs
@@ -32,7 +32,6 @@ public sealed class PermissionTreeQueryHandler(
x => new PermissionTreeDto
{
Id = x.Id,
- TenantId = x.TenantId,
ParentId = x.ParentId,
SortOrder = x.SortOrder,
Type = x.Type,
diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/RoleDetailQueryHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/RoleDetailQueryHandler.cs
index e958f7e..daf567b 100644
--- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/RoleDetailQueryHandler.cs
+++ b/src/Application/TakeoutSaaS.Application/Identity/Handlers/RoleDetailQueryHandler.cs
@@ -56,7 +56,6 @@ public sealed class RoleDetailQueryHandler(
.Select(x => new PermissionDto
{
Id = x.Id,
- TenantId = x.TenantId,
ParentId = x.ParentId,
SortOrder = x.SortOrder,
Type = x.Type,
diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/SearchPermissionsQueryHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/SearchPermissionsQueryHandler.cs
index e5e061c..d31a9ea 100644
--- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/SearchPermissionsQueryHandler.cs
+++ b/src/Application/TakeoutSaaS.Application/Identity/Handlers/SearchPermissionsQueryHandler.cs
@@ -60,7 +60,6 @@ public sealed class SearchPermissionsQueryHandler(
var items = paged.Select(permission => new PermissionDto
{
Id = permission.Id,
- TenantId = permission.TenantId,
ParentId = permission.ParentId,
SortOrder = permission.SortOrder,
Type = permission.Type,
diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/UpdateMenuCommandHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/UpdateMenuCommandHandler.cs
index ad18b6d..37019b9 100644
--- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/UpdateMenuCommandHandler.cs
+++ b/src/Application/TakeoutSaaS.Application/Identity/Handlers/UpdateMenuCommandHandler.cs
@@ -5,16 +5,13 @@ using TakeoutSaaS.Application.Identity.Contracts;
using TakeoutSaaS.Domain.Identity.Repositories;
using TakeoutSaaS.Shared.Abstractions.Constants;
using TakeoutSaaS.Shared.Abstractions.Exceptions;
-using TakeoutSaaS.Shared.Abstractions.Tenancy;
namespace TakeoutSaaS.Application.Identity.Handlers;
///
/// 更新菜单处理器。
///
-public sealed class UpdateMenuCommandHandler(
- IMenuRepository menuRepository,
- ITenantProvider tenantProvider)
+public sealed class UpdateMenuCommandHandler(IMenuRepository menuRepository)
: IRequestHandler
{
///
@@ -27,8 +24,7 @@ public sealed class UpdateMenuCommandHandler(
}
// 2. 校验存在
- var tenantId = tenantProvider.GetCurrentTenantId();
- var entity = await menuRepository.FindByIdAsync(request.Id, tenantId, cancellationToken)
+ var entity = await menuRepository.FindByIdAsync(request.Id, cancellationToken)
?? throw new BusinessException(ErrorCodes.NotFound, "菜单不存在");
// 3. 更新字段
diff --git a/src/Application/TakeoutSaaS.Application/Identity/Handlers/UpdatePermissionCommandHandler.cs b/src/Application/TakeoutSaaS.Application/Identity/Handlers/UpdatePermissionCommandHandler.cs
index 294045d..d108dde 100644
--- a/src/Application/TakeoutSaaS.Application/Identity/Handlers/UpdatePermissionCommandHandler.cs
+++ b/src/Application/TakeoutSaaS.Application/Identity/Handlers/UpdatePermissionCommandHandler.cs
@@ -61,7 +61,6 @@ public sealed class UpdatePermissionCommandHandler(
return new PermissionDto
{
Id = permission.Id,
- TenantId = permission.TenantId,
ParentId = permission.ParentId,
SortOrder = permission.SortOrder,
Type = permission.Type,
diff --git a/src/Application/TakeoutSaaS.Application/Identity/Services/AdminAuthService.cs b/src/Application/TakeoutSaaS.Application/Identity/Services/AdminAuthService.cs
index 93a53bc..b803c4f 100644
--- a/src/Application/TakeoutSaaS.Application/Identity/Services/AdminAuthService.cs
+++ b/src/Application/TakeoutSaaS.Application/Identity/Services/AdminAuthService.cs
@@ -142,9 +142,9 @@ public sealed class AdminAuthService(
{
// 1. 读取档案以获取权限
var profile = await GetProfileAsync(userId, cancellationToken);
- // 2. 读取菜单定义
- var tenantId = tenantProvider.GetCurrentTenantId();
- var definitions = await menuRepository.GetByTenantAsync(tenantId, cancellationToken);
+
+ // 2. 读取租户端菜单定义
+ var definitions = await menuRepository.GetByPortalAsync(PortalType.Tenant, cancellationToken);
// 3. 生成菜单树
var menu = BuildMenuTree(definitions, profile.Permissions);
diff --git a/src/Domain/TakeoutSaaS.Domain/Identity/Entities/MenuDefinition.cs b/src/Domain/TakeoutSaaS.Domain/Identity/Entities/MenuDefinition.cs
index 065b659..fb4fd08 100644
--- a/src/Domain/TakeoutSaaS.Domain/Identity/Entities/MenuDefinition.cs
+++ b/src/Domain/TakeoutSaaS.Domain/Identity/Entities/MenuDefinition.cs
@@ -1,12 +1,17 @@
+using TakeoutSaaS.Domain.Identity.Enums;
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Identity.Entities;
///
-/// 管理端菜单定义。
+/// 管理端菜单定义(系统级数据,不按租户隔离)。
///
-public sealed class MenuDefinition : MultiTenantEntityBase
+public sealed class MenuDefinition : AuditableEntityBase
{
+ ///
+ /// 门户类型(Admin=平台端,Tenant=租户端)。
+ ///
+ public PortalType Portal { get; set; }
///
/// 父级菜单 ID,根节点为 0。
///
diff --git a/src/Domain/TakeoutSaaS.Domain/Identity/Entities/Permission.cs b/src/Domain/TakeoutSaaS.Domain/Identity/Entities/Permission.cs
index d638ffd..21e0b45 100644
--- a/src/Domain/TakeoutSaaS.Domain/Identity/Entities/Permission.cs
+++ b/src/Domain/TakeoutSaaS.Domain/Identity/Entities/Permission.cs
@@ -1,11 +1,12 @@
+using TakeoutSaaS.Domain.Identity.Enums;
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Identity.Entities;
///
-/// 权限定义。
+/// 权限定义(系统级数据,不按租户隔离)。
///
-public sealed class Permission : MultiTenantEntityBase
+public sealed class Permission : AuditableEntityBase
{
///
/// 父级权限 ID,根节点为 0。
@@ -36,4 +37,9 @@ public sealed class Permission : MultiTenantEntityBase
/// 描述。
///
public string? Description { get; set; }
+
+ ///
+ /// 门户类型(Admin=平台端,Tenant=租户端)。
+ ///
+ public PortalType Portal { get; set; }
}
diff --git a/src/Domain/TakeoutSaaS.Domain/Identity/Enums/PortalType.cs b/src/Domain/TakeoutSaaS.Domain/Identity/Enums/PortalType.cs
new file mode 100644
index 0000000..f4ce806
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Identity/Enums/PortalType.cs
@@ -0,0 +1,17 @@
+namespace TakeoutSaaS.Domain.Identity.Enums;
+
+///
+/// 后台端类型(用于区分平台管理端与租户管理端)。
+///
+public enum PortalType
+{
+ ///
+ /// 平台管理端(Admin)。
+ ///
+ Admin = 0,
+
+ ///
+ /// 租户管理端(Tenant)。
+ ///
+ Tenant = 1
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Identity/Repositories/IMenuRepository.cs b/src/Domain/TakeoutSaaS.Domain/Identity/Repositories/IMenuRepository.cs
index 093c0ce..6b27aa4 100644
--- a/src/Domain/TakeoutSaaS.Domain/Identity/Repositories/IMenuRepository.cs
+++ b/src/Domain/TakeoutSaaS.Domain/Identity/Repositories/IMenuRepository.cs
@@ -1,4 +1,5 @@
using TakeoutSaaS.Domain.Identity.Entities;
+using TakeoutSaaS.Domain.Identity.Enums;
namespace TakeoutSaaS.Domain.Identity.Repositories;
@@ -8,14 +9,14 @@ namespace TakeoutSaaS.Domain.Identity.Repositories;
public interface IMenuRepository
{
///
- /// 按租户获取菜单列表。
+ /// 按门户类型获取菜单列表。
///
- Task> GetByTenantAsync(long tenantId, CancellationToken cancellationToken = default);
+ Task> GetByPortalAsync(PortalType portal, CancellationToken cancellationToken = default);
///
/// 根据 ID 查询菜单。
///
- Task FindByIdAsync(long id, long tenantId, CancellationToken cancellationToken = default);
+ Task FindByIdAsync(long id, CancellationToken cancellationToken = default);
///
/// 新增菜单。
@@ -30,7 +31,7 @@ public interface IMenuRepository
///
/// 删除菜单。
///
- Task DeleteAsync(long id, long tenantId, CancellationToken cancellationToken = default);
+ Task DeleteAsync(long id, CancellationToken cancellationToken = default);
///
/// 持久化变更。
diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/EfPermissionRepository.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/EfPermissionRepository.cs
index e150c3b..0d07f47 100644
--- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/EfPermissionRepository.cs
+++ b/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/EfPermissionRepository.cs
@@ -7,36 +7,41 @@ namespace TakeoutSaaS.Infrastructure.Identity.Persistence;
///
/// EF 权限仓储。
///
+///
+/// 权限是系统级数据,使用 IgnoreQueryFilters 忽略多租户过滤。
+///
public sealed class EfPermissionRepository(IdentityDbContext dbContext) : IPermissionRepository
{
///
/// 根据权限 ID 获取权限。
///
/// 权限 ID。
- /// 租户 ID。
+ /// 租户 ID(保留参数,实际不使用)。
/// 取消标记。
/// 权限实体或 null。
public Task FindByIdAsync(long permissionId, long tenantId, CancellationToken cancellationToken = default)
=> dbContext.Permissions
+ .IgnoreQueryFilters()
.AsNoTracking()
- .FirstOrDefaultAsync(x => x.Id == permissionId && x.TenantId == tenantId && x.DeletedAt == null, cancellationToken);
+ .FirstOrDefaultAsync(x => x.Id == permissionId && x.DeletedAt == null, cancellationToken);
///
/// 根据权限编码获取权限。
///
/// 权限编码。
- /// 租户 ID。
+ /// 租户 ID(保留参数,实际不使用)。
/// 取消标记。
/// 权限实体或 null。
public Task FindByCodeAsync(string code, long tenantId, CancellationToken cancellationToken = default)
=> dbContext.Permissions
+ .IgnoreQueryFilters()
.AsNoTracking()
- .FirstOrDefaultAsync(x => x.Code == code && x.TenantId == tenantId && x.DeletedAt == null, cancellationToken);
+ .FirstOrDefaultAsync(x => x.Code == code && x.DeletedAt == null, cancellationToken);
///
/// 根据权限编码集合批量获取权限。
///
- /// 租户 ID。
+ /// 租户 ID(保留参数,实际不使用)。
/// 权限编码集合。
/// 取消标记。
/// 权限列表。
@@ -49,10 +54,11 @@ public sealed class EfPermissionRepository(IdentityDbContext dbContext) : IPermi
.Distinct()
.ToArray();
- // 2. 读取租户权限
+ // 2. 读取权限(忽略租户过滤)
return dbContext.Permissions
+ .IgnoreQueryFilters()
.AsNoTracking()
- .Where(x => x.TenantId == tenantId && x.DeletedAt == null && normalizedCodes.Contains(x.Code))
+ .Where(x => x.DeletedAt == null && normalizedCodes.Contains(x.Code))
.ToListAsync(cancellationToken)
.ContinueWith(t => (IReadOnlyList)t.Result, cancellationToken);
}
@@ -60,30 +66,32 @@ public sealed class EfPermissionRepository(IdentityDbContext dbContext) : IPermi
///
/// 根据权限 ID 集合批量获取权限。
///
- /// 租户 ID。
+ /// 租户 ID(保留参数,实际不使用)。
/// 权限 ID 集合。
/// 取消标记。
/// 权限列表。
public Task> GetByIdsAsync(long tenantId, IEnumerable permissionIds, CancellationToken cancellationToken = default)
=> dbContext.Permissions
+ .IgnoreQueryFilters()
.AsNoTracking()
- .Where(x => x.TenantId == tenantId && x.DeletedAt == null && permissionIds.Contains(x.Id))
+ .Where(x => x.DeletedAt == null && permissionIds.Contains(x.Id))
.ToListAsync(cancellationToken)
.ContinueWith(t => (IReadOnlyList)t.Result, cancellationToken);
///
/// 按关键字搜索权限。
///
- /// 租户 ID。
+ /// 租户 ID(保留参数,实际不使用)。
/// 搜索关键字。
/// 取消标记。
/// 权限列表。
public Task> SearchAsync(long tenantId, string? keyword, CancellationToken cancellationToken = default)
{
- // 1. 构建基础查询
+ // 1. 构建基础查询(忽略租户过滤)
var query = dbContext.Permissions
+ .IgnoreQueryFilters()
.AsNoTracking()
- .Where(x => x.TenantId == tenantId && x.DeletedAt == null);
+ .Where(x => x.DeletedAt == null);
if (!string.IsNullOrWhiteSpace(keyword))
{
// 2. 追加关键字过滤
@@ -128,13 +136,15 @@ public sealed class EfPermissionRepository(IdentityDbContext dbContext) : IPermi
/// 删除指定权限。
///
/// 权限 ID。
- /// 租户 ID。
+ /// 租户 ID(保留参数,实际不使用)。
/// 取消标记。
/// 异步任务。
public async Task DeleteAsync(long permissionId, long tenantId, CancellationToken cancellationToken = default)
{
// 1. 查询目标权限
- var entity = await dbContext.Permissions.FirstOrDefaultAsync(x => x.Id == permissionId && x.TenantId == tenantId, cancellationToken);
+ var entity = await dbContext.Permissions
+ .IgnoreQueryFilters()
+ .FirstOrDefaultAsync(x => x.Id == permissionId, cancellationToken);
if (entity != null)
{
// 2. 删除实体
diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/IdentityDbContext.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/IdentityDbContext.cs
index 3800b5b..4efefe2 100644
--- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/IdentityDbContext.cs
+++ b/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Persistence/IdentityDbContext.cs
@@ -160,7 +160,6 @@ public sealed class IdentityDbContext(
{
builder.ToTable("permissions");
builder.HasKey(x => x.Id);
- builder.Property(x => x.TenantId).IsRequired();
builder.Property(x => x.ParentId).IsRequired();
builder.Property(x => x.SortOrder).IsRequired();
builder.Property(x => x.Type).HasMaxLength(16).IsRequired();
@@ -169,9 +168,8 @@ public sealed class IdentityDbContext(
builder.Property(x => x.Description).HasMaxLength(256);
ConfigureAuditableEntity(builder);
ConfigureSoftDeleteEntity(builder);
- builder.HasIndex(x => x.TenantId);
- builder.HasIndex(x => new { x.TenantId, x.ParentId, x.SortOrder });
- builder.HasIndex(x => new { x.TenantId, x.Code }).IsUnique();
+ builder.HasIndex(x => x.Code).IsUnique();
+ builder.HasIndex(x => new { x.Portal, x.ParentId, x.SortOrder });
}
private static void ConfigureRoleTemplate(EntityTypeBuilder builder)
@@ -226,7 +224,7 @@ public sealed class IdentityDbContext(
{
builder.ToTable("menu_definitions");
builder.HasKey(x => x.Id);
- builder.Property(x => x.TenantId).IsRequired();
+ builder.Property(x => x.Portal).HasConversion().IsRequired();
builder.Property(x => x.ParentId).IsRequired();
builder.Property(x => x.Name).HasMaxLength(64).IsRequired();
builder.Property(x => x.Path).HasMaxLength(256).IsRequired();
@@ -241,6 +239,6 @@ public sealed class IdentityDbContext(
builder.Property(x => x.AuthListJson).HasColumnType("text");
ConfigureAuditableEntity(builder);
ConfigureSoftDeleteEntity(builder);
- builder.HasIndex(x => new { x.TenantId, x.ParentId, x.SortOrder });
+ builder.HasIndex(x => new { x.Portal, x.ParentId, x.SortOrder });
}
}
diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Repositories/EfMenuRepository.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Repositories/EfMenuRepository.cs
index ed63222..5173e3c 100644
--- a/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Repositories/EfMenuRepository.cs
+++ b/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Repositories/EfMenuRepository.cs
@@ -1,5 +1,6 @@
using Microsoft.EntityFrameworkCore;
using TakeoutSaaS.Domain.Identity.Entities;
+using TakeoutSaaS.Domain.Identity.Enums;
using TakeoutSaaS.Domain.Identity.Repositories;
using TakeoutSaaS.Infrastructure.Identity.Persistence;
@@ -11,28 +12,28 @@ namespace TakeoutSaaS.Infrastructure.Identity.Repositories;
public sealed class EfMenuRepository(IdentityDbContext dbContext) : IMenuRepository
{
///
- public async Task> GetByTenantAsync(long tenantId, CancellationToken cancellationToken = default)
+ public async Task> GetByPortalAsync(PortalType portal, CancellationToken cancellationToken = default)
{
- // 1. 仅返回该租户的菜单,无回退逻辑
- var tenantMenus = await dbContext.MenuDefinitions
+ // 1. 按门户类型查询菜单(忽略租户过滤器)
+ var menus = await dbContext.MenuDefinitions
+ .IgnoreQueryFilters()
.AsNoTracking()
- .Where(x => x.TenantId == tenantId && x.DeletedAt == null)
+ .Where(x => x.Portal == portal && x.DeletedAt == null)
.OrderBy(x => x.ParentId)
.ThenBy(x => x.SortOrder)
.ToListAsync(cancellationToken);
- return tenantMenus;
+ return menus;
}
///
- public async Task FindByIdAsync(long id, long tenantId, CancellationToken cancellationToken = default)
+ public async Task FindByIdAsync(long id, CancellationToken cancellationToken = default)
{
- // 1. 仅查询该租户的菜单,无回退逻辑
+ // 1. 按 ID 查询菜单(忽略租户过滤器)
return await dbContext.MenuDefinitions
+ .IgnoreQueryFilters()
.AsNoTracking()
- .FirstOrDefaultAsync(
- x => x.Id == id && x.TenantId == tenantId && x.DeletedAt == null,
- cancellationToken);
+ .FirstOrDefaultAsync(x => x.Id == id && x.DeletedAt == null, cancellationToken);
}
///
@@ -49,11 +50,12 @@ public sealed class EfMenuRepository(IdentityDbContext dbContext) : IMenuReposit
}
///
- public async Task DeleteAsync(long id, long tenantId, CancellationToken cancellationToken = default)
+ public async Task DeleteAsync(long id, CancellationToken cancellationToken = default)
{
- // 1. 查询目标
+ // 1. 查询目标(忽略租户过滤器)
var entity = await dbContext.MenuDefinitions
- .FirstOrDefaultAsync(x => x.Id == id && x.TenantId == tenantId, cancellationToken);
+ .IgnoreQueryFilters()
+ .FirstOrDefaultAsync(x => x.Id == id, cancellationToken);
// 2. 存在则删除
if (entity is not null)