refactor: 收紧角色与商户跨租户能力
This commit is contained in:
@@ -27,7 +27,7 @@ public sealed class GetMerchantListQuery : IRequest<PagedResult<MerchantListItem
|
|||||||
public OperatingMode? OperatingMode { get; init; }
|
public OperatingMode? OperatingMode { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 租户过滤(管理员可用)。
|
/// 租户过滤(可选,默认当前租户;禁止跨租户)。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public long? TenantId { get; init; }
|
public long? TenantId { get; init; }
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
using MediatR;
|
using MediatR;
|
||||||
using TakeoutSaaS.Application.Identity.Commands;
|
using TakeoutSaaS.Application.Identity.Commands;
|
||||||
using TakeoutSaaS.Domain.Identity.Repositories;
|
using TakeoutSaaS.Domain.Identity.Repositories;
|
||||||
|
using TakeoutSaaS.Shared.Abstractions.Constants;
|
||||||
|
using TakeoutSaaS.Shared.Abstractions.Exceptions;
|
||||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||||
|
|
||||||
namespace TakeoutSaaS.Application.Identity.Handlers;
|
namespace TakeoutSaaS.Application.Identity.Handlers;
|
||||||
@@ -22,9 +24,21 @@ public sealed class BindRolePermissionsCommandHandler(
|
|||||||
public async Task<bool> Handle(BindRolePermissionsCommand request, CancellationToken cancellationToken)
|
public async Task<bool> Handle(BindRolePermissionsCommand request, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
// 1. 获取租户上下文
|
// 1. 获取租户上下文
|
||||||
var tenantId = request.TenantId ?? tenantProvider.GetCurrentTenantId();
|
var currentTenantId = tenantProvider.GetCurrentTenantId();
|
||||||
|
if (currentTenantId <= 0)
|
||||||
|
{
|
||||||
|
throw new BusinessException(ErrorCodes.BadRequest, "缺少租户标识");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. (空行后) 禁止跨租户操作
|
||||||
|
if (request.TenantId.HasValue && request.TenantId.Value != currentTenantId)
|
||||||
|
{
|
||||||
|
throw new BusinessException(ErrorCodes.Forbidden, "禁止跨租户操作角色权限");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. (空行后) 覆盖式绑定权限
|
||||||
|
var tenantId = currentTenantId;
|
||||||
|
|
||||||
// 2. 覆盖式绑定权限
|
|
||||||
var distinctPermissionIds = request.PermissionIds
|
var distinctPermissionIds = request.PermissionIds
|
||||||
.Where(id => id > 0)
|
.Where(id => id > 0)
|
||||||
.Distinct()
|
.Distinct()
|
||||||
@@ -33,7 +47,7 @@ public sealed class BindRolePermissionsCommandHandler(
|
|||||||
await rolePermissionRepository.ReplaceRolePermissionsAsync(tenantId, request.RoleId, distinctPermissionIds, cancellationToken);
|
await rolePermissionRepository.ReplaceRolePermissionsAsync(tenantId, request.RoleId, distinctPermissionIds, cancellationToken);
|
||||||
await rolePermissionRepository.SaveChangesAsync(cancellationToken);
|
await rolePermissionRepository.SaveChangesAsync(cancellationToken);
|
||||||
|
|
||||||
// 3. 返回执行结果
|
// 4. (空行后) 返回执行结果
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,10 +25,23 @@ public sealed class CreateRoleCommandHandler(
|
|||||||
/// <returns>创建后的角色 DTO。</returns>
|
/// <returns>创建后的角色 DTO。</returns>
|
||||||
public async Task<RoleDto> Handle(CreateRoleCommand request, CancellationToken cancellationToken)
|
public async Task<RoleDto> Handle(CreateRoleCommand request, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
// 1. 获取租户上下文
|
// 1. 获取租户上下文并校验跨租户
|
||||||
var tenantId = request.TenantId ?? tenantProvider.GetCurrentTenantId();
|
var currentTenantId = tenantProvider.GetCurrentTenantId();
|
||||||
|
if (currentTenantId <= 0)
|
||||||
|
{
|
||||||
|
throw new BusinessException(ErrorCodes.BadRequest, "缺少租户标识");
|
||||||
|
}
|
||||||
|
|
||||||
// 2. 归一化输入并校验唯一
|
// 2. (空行后) 禁止跨租户创建
|
||||||
|
if (request.TenantId.HasValue && request.TenantId.Value != currentTenantId)
|
||||||
|
{
|
||||||
|
throw new BusinessException(ErrorCodes.Forbidden, "禁止跨租户创建角色");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. (空行后) 使用当前租户创建角色
|
||||||
|
var tenantId = currentTenantId;
|
||||||
|
|
||||||
|
// 4. (空行后) 归一化输入并校验唯一
|
||||||
var name = request.Name?.Trim() ?? string.Empty;
|
var name = request.Name?.Trim() ?? string.Empty;
|
||||||
var code = request.Code?.Trim() ?? string.Empty;
|
var code = request.Code?.Trim() ?? string.Empty;
|
||||||
if (string.IsNullOrWhiteSpace(name) || string.IsNullOrWhiteSpace(code))
|
if (string.IsNullOrWhiteSpace(name) || string.IsNullOrWhiteSpace(code))
|
||||||
@@ -42,7 +55,7 @@ public sealed class CreateRoleCommandHandler(
|
|||||||
throw new BusinessException(ErrorCodes.Conflict, "角色编码已存在");
|
throw new BusinessException(ErrorCodes.Conflict, "角色编码已存在");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. 构建角色实体
|
// 5. (空行后) 构建角色实体
|
||||||
var role = new Role
|
var role = new Role
|
||||||
{
|
{
|
||||||
TenantId = tenantId,
|
TenantId = tenantId,
|
||||||
@@ -51,11 +64,11 @@ public sealed class CreateRoleCommandHandler(
|
|||||||
Description = request.Description
|
Description = request.Description
|
||||||
};
|
};
|
||||||
|
|
||||||
// 4. 持久化
|
// 6. (空行后) 持久化
|
||||||
await roleRepository.AddAsync(role, cancellationToken);
|
await roleRepository.AddAsync(role, cancellationToken);
|
||||||
await roleRepository.SaveChangesAsync(cancellationToken);
|
await roleRepository.SaveChangesAsync(cancellationToken);
|
||||||
|
|
||||||
// 5. 返回 DTO
|
// 7. (空行后) 返回 DTO
|
||||||
return new RoleDto
|
return new RoleDto
|
||||||
{
|
{
|
||||||
Id = role.Id,
|
Id = role.Id,
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
using MediatR;
|
using MediatR;
|
||||||
using TakeoutSaaS.Application.Identity.Commands;
|
using TakeoutSaaS.Application.Identity.Commands;
|
||||||
using TakeoutSaaS.Domain.Identity.Repositories;
|
using TakeoutSaaS.Domain.Identity.Repositories;
|
||||||
|
using TakeoutSaaS.Shared.Abstractions.Constants;
|
||||||
|
using TakeoutSaaS.Shared.Abstractions.Exceptions;
|
||||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||||
|
|
||||||
namespace TakeoutSaaS.Application.Identity.Handlers;
|
namespace TakeoutSaaS.Application.Identity.Handlers;
|
||||||
@@ -22,13 +24,25 @@ public sealed class DeleteRoleCommandHandler(
|
|||||||
public async Task<bool> Handle(DeleteRoleCommand request, CancellationToken cancellationToken)
|
public async Task<bool> Handle(DeleteRoleCommand request, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
// 1. 获取租户上下文
|
// 1. 获取租户上下文
|
||||||
var tenantId = request.TenantId ?? tenantProvider.GetCurrentTenantId();
|
var currentTenantId = tenantProvider.GetCurrentTenantId();
|
||||||
|
if (currentTenantId <= 0)
|
||||||
|
{
|
||||||
|
throw new BusinessException(ErrorCodes.BadRequest, "缺少租户标识");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. (空行后) 禁止跨租户操作
|
||||||
|
if (request.TenantId.HasValue && request.TenantId.Value != currentTenantId)
|
||||||
|
{
|
||||||
|
throw new BusinessException(ErrorCodes.Forbidden, "禁止跨租户操作角色");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. (空行后) 删除角色
|
||||||
|
var tenantId = currentTenantId;
|
||||||
|
|
||||||
// 2. 删除角色
|
|
||||||
await roleRepository.DeleteAsync(request.RoleId, tenantId, cancellationToken);
|
await roleRepository.DeleteAsync(request.RoleId, tenantId, cancellationToken);
|
||||||
await roleRepository.SaveChangesAsync(cancellationToken);
|
await roleRepository.SaveChangesAsync(cancellationToken);
|
||||||
|
|
||||||
// 3. 返回执行结果
|
// 4. (空行后) 返回执行结果
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ using MediatR;
|
|||||||
using TakeoutSaaS.Application.Identity.Contracts;
|
using TakeoutSaaS.Application.Identity.Contracts;
|
||||||
using TakeoutSaaS.Application.Identity.Queries;
|
using TakeoutSaaS.Application.Identity.Queries;
|
||||||
using TakeoutSaaS.Domain.Identity.Repositories;
|
using TakeoutSaaS.Domain.Identity.Repositories;
|
||||||
|
using TakeoutSaaS.Shared.Abstractions.Constants;
|
||||||
|
using TakeoutSaaS.Shared.Abstractions.Exceptions;
|
||||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||||
|
|
||||||
namespace TakeoutSaaS.Application.Identity.Handlers;
|
namespace TakeoutSaaS.Application.Identity.Handlers;
|
||||||
@@ -19,24 +21,37 @@ public sealed class RoleDetailQueryHandler(
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public async Task<RoleDetailDto?> Handle(RoleDetailQuery request, CancellationToken cancellationToken)
|
public async Task<RoleDetailDto?> Handle(RoleDetailQuery request, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
// 1. 获取租户上下文并查询角色
|
// 1. 获取租户上下文并校验跨租户
|
||||||
var tenantId = request.TenantId ?? tenantProvider.GetCurrentTenantId();
|
var currentTenantId = tenantProvider.GetCurrentTenantId();
|
||||||
|
if (currentTenantId <= 0)
|
||||||
|
{
|
||||||
|
throw new BusinessException(ErrorCodes.BadRequest, "缺少租户标识");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. (空行后) 禁止跨租户查询
|
||||||
|
if (request.TenantId.HasValue && request.TenantId.Value != currentTenantId)
|
||||||
|
{
|
||||||
|
throw new BusinessException(ErrorCodes.Forbidden, "禁止跨租户查询角色详情");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. (空行后) 查询角色
|
||||||
|
var tenantId = currentTenantId;
|
||||||
var role = await roleRepository.FindByIdAsync(request.RoleId, tenantId, cancellationToken);
|
var role = await roleRepository.FindByIdAsync(request.RoleId, tenantId, cancellationToken);
|
||||||
if (role is null)
|
if (role is null)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 查询角色权限关系
|
// 4. (空行后) 查询角色权限关系
|
||||||
var relations = await rolePermissionRepository.GetByRoleIdsAsync(tenantId, new[] { role.Id }, cancellationToken);
|
var relations = await rolePermissionRepository.GetByRoleIdsAsync(tenantId, new[] { role.Id }, cancellationToken);
|
||||||
var permissionIds = relations.Select(x => x.PermissionId).ToArray();
|
var permissionIds = relations.Select(x => x.PermissionId).ToArray();
|
||||||
|
|
||||||
// 3. 拉取权限实体
|
// 5. (空行后) 拉取权限实体
|
||||||
var permissions = permissionIds.Length == 0
|
var permissions = permissionIds.Length == 0
|
||||||
? Array.Empty<Domain.Identity.Entities.Permission>()
|
? Array.Empty<Domain.Identity.Entities.Permission>()
|
||||||
: await permissionRepository.GetByIdsAsync(tenantId, permissionIds, cancellationToken);
|
: await permissionRepository.GetByIdsAsync(tenantId, permissionIds, cancellationToken);
|
||||||
|
|
||||||
// 4. 映射 DTO
|
// 6. (空行后) 映射 DTO
|
||||||
var permissionDtos = permissions
|
var permissionDtos = permissions
|
||||||
.Select(x => new PermissionDto
|
.Select(x => new PermissionDto
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ using MediatR;
|
|||||||
using TakeoutSaaS.Application.Identity.Contracts;
|
using TakeoutSaaS.Application.Identity.Contracts;
|
||||||
using TakeoutSaaS.Application.Identity.Queries;
|
using TakeoutSaaS.Application.Identity.Queries;
|
||||||
using TakeoutSaaS.Domain.Identity.Repositories;
|
using TakeoutSaaS.Domain.Identity.Repositories;
|
||||||
|
using TakeoutSaaS.Shared.Abstractions.Constants;
|
||||||
|
using TakeoutSaaS.Shared.Abstractions.Exceptions;
|
||||||
using TakeoutSaaS.Shared.Abstractions.Results;
|
using TakeoutSaaS.Shared.Abstractions.Results;
|
||||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||||
|
|
||||||
@@ -23,11 +25,24 @@ public sealed class SearchRolesQueryHandler(
|
|||||||
/// <returns>分页结果。</returns>
|
/// <returns>分页结果。</returns>
|
||||||
public async Task<PagedResult<RoleDto>> Handle(SearchRolesQuery request, CancellationToken cancellationToken)
|
public async Task<PagedResult<RoleDto>> Handle(SearchRolesQuery request, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
// 1. 获取租户上下文并查询角色
|
// 1. 获取租户上下文并校验跨租户
|
||||||
var tenantId = request.TenantId ?? tenantProvider.GetCurrentTenantId();
|
var currentTenantId = tenantProvider.GetCurrentTenantId();
|
||||||
|
if (currentTenantId <= 0)
|
||||||
|
{
|
||||||
|
throw new BusinessException(ErrorCodes.BadRequest, "缺少租户标识");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. (空行后) 禁止跨租户查询
|
||||||
|
if (request.TenantId.HasValue && request.TenantId.Value != currentTenantId)
|
||||||
|
{
|
||||||
|
throw new BusinessException(ErrorCodes.Forbidden, "禁止跨租户查询角色");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. (空行后) 查询角色列表
|
||||||
|
var tenantId = currentTenantId;
|
||||||
var roles = await roleRepository.SearchAsync(tenantId, request.Keyword, cancellationToken);
|
var roles = await roleRepository.SearchAsync(tenantId, request.Keyword, cancellationToken);
|
||||||
|
|
||||||
// 2. 排序
|
// 4. (空行后) 排序
|
||||||
var sorted = request.SortBy?.ToLowerInvariant() switch
|
var sorted = request.SortBy?.ToLowerInvariant() switch
|
||||||
{
|
{
|
||||||
"name" => request.SortDescending
|
"name" => request.SortDescending
|
||||||
@@ -38,13 +53,13 @@ public sealed class SearchRolesQueryHandler(
|
|||||||
: roles.OrderBy(x => x.CreatedAt)
|
: roles.OrderBy(x => x.CreatedAt)
|
||||||
};
|
};
|
||||||
|
|
||||||
// 3. 分页
|
// 5. (空行后) 分页
|
||||||
var paged = sorted
|
var paged = sorted
|
||||||
.Skip((request.Page - 1) * request.PageSize)
|
.Skip((request.Page - 1) * request.PageSize)
|
||||||
.Take(request.PageSize)
|
.Take(request.PageSize)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
// 4. 映射 DTO
|
// 6. (空行后) 映射 DTO
|
||||||
var items = paged.Select(role => new RoleDto
|
var items = paged.Select(role => new RoleDto
|
||||||
{
|
{
|
||||||
Id = role.Id,
|
Id = role.Id,
|
||||||
@@ -54,7 +69,7 @@ public sealed class SearchRolesQueryHandler(
|
|||||||
Description = role.Description
|
Description = role.Description
|
||||||
}).ToList();
|
}).ToList();
|
||||||
|
|
||||||
// 5. 返回分页结果
|
// 7. (空行后) 返回分页结果
|
||||||
return new PagedResult<RoleDto>(items, request.Page, request.PageSize, roles.Count);
|
return new PagedResult<RoleDto>(items, request.Page, request.PageSize, roles.Count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ using MediatR;
|
|||||||
using TakeoutSaaS.Application.Identity.Commands;
|
using TakeoutSaaS.Application.Identity.Commands;
|
||||||
using TakeoutSaaS.Application.Identity.Contracts;
|
using TakeoutSaaS.Application.Identity.Contracts;
|
||||||
using TakeoutSaaS.Domain.Identity.Repositories;
|
using TakeoutSaaS.Domain.Identity.Repositories;
|
||||||
|
using TakeoutSaaS.Shared.Abstractions.Constants;
|
||||||
|
using TakeoutSaaS.Shared.Abstractions.Exceptions;
|
||||||
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
using TakeoutSaaS.Shared.Abstractions.Tenancy;
|
||||||
|
|
||||||
namespace TakeoutSaaS.Application.Identity.Handlers;
|
namespace TakeoutSaaS.Application.Identity.Handlers;
|
||||||
@@ -22,23 +24,36 @@ public sealed class UpdateRoleCommandHandler(
|
|||||||
/// <returns>更新后的角色 DTO 或 null。</returns>
|
/// <returns>更新后的角色 DTO 或 null。</returns>
|
||||||
public async Task<RoleDto?> Handle(UpdateRoleCommand request, CancellationToken cancellationToken)
|
public async Task<RoleDto?> Handle(UpdateRoleCommand request, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
// 1. 获取租户上下文并查询角色
|
// 1. 获取租户上下文并校验跨租户
|
||||||
var tenantId = request.TenantId ?? tenantProvider.GetCurrentTenantId();
|
var currentTenantId = tenantProvider.GetCurrentTenantId();
|
||||||
|
if (currentTenantId <= 0)
|
||||||
|
{
|
||||||
|
throw new BusinessException(ErrorCodes.BadRequest, "缺少租户标识");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. (空行后) 禁止跨租户更新
|
||||||
|
if (request.TenantId.HasValue && request.TenantId.Value != currentTenantId)
|
||||||
|
{
|
||||||
|
throw new BusinessException(ErrorCodes.Forbidden, "禁止跨租户更新角色");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. (空行后) 查询角色
|
||||||
|
var tenantId = currentTenantId;
|
||||||
var role = await roleRepository.FindByIdAsync(request.RoleId, tenantId, cancellationToken);
|
var role = await roleRepository.FindByIdAsync(request.RoleId, tenantId, cancellationToken);
|
||||||
if (role == null)
|
if (role == null)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 更新字段
|
// 4. (空行后) 更新字段
|
||||||
role.Name = request.Name;
|
role.Name = request.Name;
|
||||||
role.Description = request.Description;
|
role.Description = request.Description;
|
||||||
|
|
||||||
// 3. 持久化
|
// 5. (空行后) 持久化
|
||||||
await roleRepository.UpdateAsync(role, cancellationToken);
|
await roleRepository.UpdateAsync(role, cancellationToken);
|
||||||
await roleRepository.SaveChangesAsync(cancellationToken);
|
await roleRepository.SaveChangesAsync(cancellationToken);
|
||||||
|
|
||||||
// 4. 返回 DTO
|
// 6. (空行后) 返回 DTO
|
||||||
return new RoleDto
|
return new RoleDto
|
||||||
{
|
{
|
||||||
Id = role.Id,
|
Id = role.Id,
|
||||||
|
|||||||
@@ -18,22 +18,6 @@ public interface IMerchantRepository
|
|||||||
/// <returns>商户实体或 null。</returns>
|
/// <returns>商户实体或 null。</returns>
|
||||||
Task<Merchant?> FindByIdAsync(long merchantId, long tenantId, CancellationToken cancellationToken = default);
|
Task<Merchant?> FindByIdAsync(long merchantId, long tenantId, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 依据标识获取商户(忽略租户过滤)。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="merchantId">商户 ID。</param>
|
|
||||||
/// <param name="cancellationToken">取消标记。</param>
|
|
||||||
/// <returns>商户实体或 null。</returns>
|
|
||||||
Task<Merchant?> FindByIdAsync(long merchantId, CancellationToken cancellationToken = default);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 依据租户标识获取商户(忽略租户过滤)。
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="tenantId">租户 ID。</param>
|
|
||||||
/// <param name="cancellationToken">取消标记。</param>
|
|
||||||
/// <returns>商户实体或 null。</returns>
|
|
||||||
Task<Merchant?> FindByTenantIdAsync(long tenantId, CancellationToken cancellationToken = default);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 按状态筛选商户列表。
|
/// 按状态筛选商户列表。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -44,16 +28,16 @@ public interface IMerchantRepository
|
|||||||
Task<IReadOnlyList<Merchant>> SearchAsync(long tenantId, MerchantStatus? status, CancellationToken cancellationToken = default);
|
Task<IReadOnlyList<Merchant>> SearchAsync(long tenantId, MerchantStatus? status, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 按条件筛选商户列表(支持跨租户)。
|
/// 按条件筛选商户列表。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="tenantId">租户 ID,为 null 时查询全部租户。</param>
|
/// <param name="tenantId">租户 ID。</param>
|
||||||
/// <param name="status">状态过滤。</param>
|
/// <param name="status">状态过滤。</param>
|
||||||
/// <param name="operatingMode">经营模式过滤。</param>
|
/// <param name="operatingMode">经营模式过滤。</param>
|
||||||
/// <param name="keyword">关键词过滤。</param>
|
/// <param name="keyword">关键词过滤。</param>
|
||||||
/// <param name="cancellationToken">取消标记。</param>
|
/// <param name="cancellationToken">取消标记。</param>
|
||||||
/// <returns>商户集合。</returns>
|
/// <returns>商户集合。</returns>
|
||||||
Task<IReadOnlyList<Merchant>> SearchAsync(
|
Task<IReadOnlyList<Merchant>> SearchAsync(
|
||||||
long? tenantId,
|
long tenantId,
|
||||||
MerchantStatus? status,
|
MerchantStatus? status,
|
||||||
OperatingMode? operatingMode,
|
OperatingMode? operatingMode,
|
||||||
string? keyword,
|
string? keyword,
|
||||||
|
|||||||
@@ -25,26 +25,6 @@ public sealed class EfMerchantRepository(TakeoutAppDbContext context, TakeoutLog
|
|||||||
.FirstOrDefaultAsync(cancellationToken);
|
.FirstOrDefaultAsync(cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public Task<Merchant?> FindByIdAsync(long merchantId, CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
return context.Merchants
|
|
||||||
.IgnoreQueryFilters()
|
|
||||||
.AsNoTracking()
|
|
||||||
.Where(x => x.Id == merchantId)
|
|
||||||
.FirstOrDefaultAsync(cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public Task<Merchant?> FindByTenantIdAsync(long tenantId, CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
return context.Merchants
|
|
||||||
.IgnoreQueryFilters()
|
|
||||||
.AsNoTracking()
|
|
||||||
.Where(x => x.TenantId == tenantId)
|
|
||||||
.FirstOrDefaultAsync(cancellationToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public async Task<IReadOnlyList<Merchant>> SearchAsync(long tenantId, MerchantStatus? status, CancellationToken cancellationToken = default)
|
public async Task<IReadOnlyList<Merchant>> SearchAsync(long tenantId, MerchantStatus? status, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
@@ -238,22 +218,17 @@ public sealed class EfMerchantRepository(TakeoutAppDbContext context, TakeoutLog
|
|||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public async Task<IReadOnlyList<Merchant>> SearchAsync(
|
public async Task<IReadOnlyList<Merchant>> SearchAsync(
|
||||||
long? tenantId,
|
long tenantId,
|
||||||
MerchantStatus? status,
|
MerchantStatus? status,
|
||||||
OperatingMode? operatingMode,
|
OperatingMode? operatingMode,
|
||||||
string? keyword,
|
string? keyword,
|
||||||
CancellationToken cancellationToken = default)
|
CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
var query = context.Merchants
|
var query = context.Merchants
|
||||||
.IgnoreQueryFilters()
|
|
||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
|
.Where(x => x.TenantId == tenantId)
|
||||||
.AsQueryable();
|
.AsQueryable();
|
||||||
|
|
||||||
if (tenantId.HasValue && tenantId.Value > 0)
|
|
||||||
{
|
|
||||||
query = query.Where(x => x.TenantId == tenantId.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (status.HasValue)
|
if (status.HasValue)
|
||||||
{
|
{
|
||||||
query = query.Where(x => x.Status == status.Value);
|
query = query.Where(x => x.Status == status.Value);
|
||||||
|
|||||||
Reference in New Issue
Block a user