修改User模块

This commit is contained in:
chfei committed 2026-10-23 19:01:28 +08:00
1 parent d6471f97d3
commit bb7162aaf6
21 files changed
+278 -336

No files matched your search

@@ -1,3 +1,4 @@
using Store.Users.Contracts.Enums;
using MAX.Framework.Validation;
using FreeSql;
using MAX.Core.DependencyInjection;
@@ -30,7 +31,6 @@ public sealed partial class UserManagementService(IFreeSql orm, ICurrentUser cur
var actor = await Actor(orm, ct);
var name = string.IsNullOrWhiteSpace(userName) ? actor.UserName : userName.Trim();
RequestValidator.Validate(new UserNameRequest { UserName = name });
UserInputChecks.Length(name, 20, "用户名");
var target = await orm.Select<UserEntity>().Where(u => u.UserName == name).FirstAsync(ct)
?? throw new AppException("用户不存在");
if (!UserAccessPolicy.CanRead(actor, target))
@@ -38,27 +38,12 @@ public sealed partial class UserManagementService(IFreeSql orm, ICurrentUser cur
return await query.GetUser(target.UserName);
}
/// <summary>解析代操作目标,服务端校验管理员或主子账号归属,省略用户名时操作本人。</summary>
public async Task<string> GetManagedUserName(string? userName, CancellationToken ct)
{
var actor = await Actor(orm, ct);
var name = string.IsNullOrWhiteSpace(userName) ? actor.UserName : userName.Trim();
UserInputChecks.Length(name, 20, "用户名");
var target = await orm.Select<UserEntity>().Where(u => u.UserName == name).FirstAsync(ct)
?? throw new AppException("用户不存在");
if (!UserAccessPolicy.CanManage(actor, target) && actor.Id != target.Id)
throw new AppException("无权操作该账户", 403);
return target.UserName;
}
/// <summary>管理员查询全部账户;普通主账号的列表范围为本人和直属子账号。</summary>
public async Task<UserPage<UserInfo>> Search(UserSearchRequest request, bool subUsersOnly, CancellationToken ct)
{
RequestValidator.Validate(request);
UserInputChecks.Search(request);
var actor = await Actor(orm, ct);
if (!subUsersOnly && !IsAdmin(actor) && !actor.IsMainUser) throw new AppException("无权查询账户列表", 403);
if (subUsersOnly && !IsAdmin(actor) && !actor.IsMainUser) throw new AppException("子账号不能管理其他账户", 403);
if (!IsAdmin(actor) && !actor.IsMainUser) throw new AppException("子账号不能管理账户列表", 403);
var select = orm.Select<UserEntity>();
if (subUsersOnly)
{
@@ -75,11 +60,16 @@ public sealed partial class UserManagementService(IFreeSql orm, ICurrentUser cur
if (!string.IsNullOrWhiteSpace(parentUserName)
&& !string.Equals(parentUserName, actor.UserName, StringComparison.OrdinalIgnoreCase))
throw new AppException("只能查询自己的子账号", 403);
select = select.Where(u => u.ParentUserName == actor.UserName);
select = select.Where(u => u.ParentUserName == actor.UserName && (u.SaLevel == null || u.SaLevel != UserAdminLevel.SuperAdmin));
}
}
else if (!IsAdmin(actor))
select = select.Where(u => u.Id == actor.Id || u.ParentUserName == actor.UserName);
select = select.Where(u => u.Id == actor.Id || (u.ParentUserName == actor.UserName && (u.SaLevel == null || u.SaLevel != UserAdminLevel.SuperAdmin)));
if (!subUsersOnly && !string.IsNullOrWhiteSpace(request.ParentUserName))
{
var parentName = request.ParentUserName.Trim();
select = select.Where(u => u.ParentUserName == parentName);
}
if (request.GroupId.HasValue) select = select.Where(u => u.GroupId == request.GroupId.Value);
if (!string.IsNullOrWhiteSpace(request.Keyword))
{
@@ -96,10 +86,6 @@ public sealed partial class UserManagementService(IFreeSql orm, ICurrentUser cur
public async Task<UserInfo> Create(UserCreateRequest request, bool subUser, CancellationToken ct)
{
RequestValidator.Validate(request);
UserInputChecks.Length(request.UserName, 20, "用户名");
UserInputChecks.Length(request.Password, 128, "密码", 6);
UserInputChecks.Edit(request);
UserInputChecks.Length(request.ParentUserName, 20, "父账号");
using var work = orm.CreateUnitOfWork();
work.GetOrBeginTransaction();
@@ -124,9 +110,9 @@ public sealed partial class UserManagementService(IFreeSql orm, ICurrentUser cur
if (await db.Select<UserEntity>().Where(u => u.UserName == name).AnyAsync(ct)) throw new AppException("用户名已存在");
var user = new UserEntity
{
UserName = name, ParentUserName = parentName, GroupId = subUser ? (byte)4 : (byte)3,
UserName = name, ParentUserName = parentName, GroupId = subUser ? UserGroup.CustomerService : UserGroup.MainAccount,
NickName = name, Mobile = "", CompanyName = "", Notes = "", CardId = "", Authority = "",
ForbiddenPage = "", OemId = "", SaLevel = 0, ShopPointsPerMonth = 30,
ForbiddenPage = "", OemId = "", SaLevel = UserAdminLevel.Normal, ShopPointsPerMonth = 30,
PostagePerOrder = 2.2m, RefundPostagePerOrder = 2.5m, GiftOemAmountPerOrder = 0,
SyncLogisticsPerOrder = 0, Points = 0, Balance = 0, RechargePointsTotal = 0,
RechargeAmountTotal = 0, AddTime = DateTime.Now, MdyTime = DateTime.Now
@@ -141,11 +127,10 @@ public sealed partial class UserManagementService(IFreeSql orm, ICurrentUser cur
}
/// <summary>修改资料。登录名保持稳定,避免破坏主子账号、商铺和历史流水中的关联。</summary>
public async Task<UserInfo> Update(int id, UserEditRequest request, bool subUser, CancellationToken ct)
public async Task<UserInfo> Update(UserUpdateRequest request, bool subUser, CancellationToken ct)
{
UserInputChecks.PositiveId(id);
RequestValidator.Validate(request);
UserInputChecks.Edit(request);
var id = request.Id;
using var work = orm.CreateUnitOfWork();
work.GetOrBeginTransaction();
var db = work.Orm;
@@ -173,14 +158,13 @@ public sealed partial class UserManagementService(IFreeSql orm, ICurrentUser cur
/// <summary>只有无余额、无积分、无子账号且无商铺关联的账户才能删除,保留历史流水。</summary>
public async Task Delete(int id, CancellationToken ct)
{
UserInputChecks.PositiveId(id);
RequestValidator.Validate(new UserIdRequest { Id = id });
using var work = orm.CreateUnitOfWork();
work.GetOrBeginTransaction();
var db = work.Orm;
var actor = await Actor(db, ct);
var target = await db.Select<UserEntity>().Where(u => u.Id == id).ForUpdate().FirstAsync(ct)
?? throw new AppException("用户不存在");
if (actor.Id == target.Id) throw new AppException("不能删除当前登录账户");
if (!UserAccessPolicy.CanManage(actor, target)) throw new AppException("无权删除该账户", 403);
if ((target.Balance ?? 0) != 0 || target.Points != 0) throw new AppException("账户仍有余额或积分,不能删除");
if (await db.Select<UserEntity>().Where(u => u.ParentUserName == target.UserName).AnyAsync(ct))
@@ -194,18 +178,15 @@ public sealed partial class UserManagementService(IFreeSql orm, ICurrentUser cur
onlineUsers.SignOut(target.UserName);
}
/// <summary>本人改密校验原密码,管理者可重置授权账户密码;比较并更新后失效目标账户会话。</summary>
/// <summary>非管理员本人改密校验原密码,管理员可重置任意账户密码;比较并更新后失效目标账户会话。</summary>
public async Task ChangePassword(ChangePasswordRequest request, CancellationToken ct)
{
RequestValidator.Validate(request);
UserInputChecks.Length(request.OldPassword, 128, "原密码");
UserInputChecks.Length(request.NewPassword, 128, "新密码", 6);
var actor = await Actor(orm, ct);
var name = string.IsNullOrWhiteSpace(request.UserName) ? actor.UserName : request.UserName.Trim();
UserInputChecks.Length(name, 20, "用户名");
var target = await orm.Select<UserEntity>().Where(u => u.UserName == name).FirstAsync(ct)
?? throw new AppException("用户不存在");
if (target.Id == actor.Id)
if (target.Id == actor.Id && !IsAdmin(actor))
{
RequestValidator.Validate(new UserPasswordProofRequest { OldPassword = request.OldPassword! });
if (!UserPassword.Verify(target, request.OldPassword!)) throw new AppException("原密码错误");
@@ -223,7 +204,6 @@ public sealed partial class UserManagementService(IFreeSql orm, ICurrentUser cur
public async Task<UserPage<UserPointsRecordEntity>> Points(string? userName, UserRecordSearchRequest request, CancellationToken ct)
{
RequestValidator.Validate(request);
UserInputChecks.Records(request);
var user = await GetUser(userName, ct);
var select = orm.Select<UserPointsRecordEntity>().Where(r => r.UserName == user.UserName);
if (request.StartTime.HasValue) select = select.Where(r => r.AddTime >= request.StartTime.Value);
@@ -239,7 +219,6 @@ public sealed partial class UserManagementService(IFreeSql orm, ICurrentUser cur
public async Task<UserPage<UserPaymentRecordEntity>> Balance(string? userName, UserRecordSearchRequest request, CancellationToken ct)
{
RequestValidator.Validate(request);
UserInputChecks.Records(request);
var user = await GetUser(userName, ct);
var select = orm.Select<UserPaymentRecordEntity>().Where(r => r.UserName == user.UserName && r.IsDeleted == 0);
if (request.StartTime.HasValue) select = select.Where(r => r.CreateTime >= request.StartTime.Value);
@@ -259,9 +238,9 @@ public sealed partial class UserManagementService(IFreeSql orm, ICurrentUser cur
private static void Apply(UserEntity user, UserEditRequest request, UserEntity actor, bool subUser)
{
// 合法分组值已由服务参数检查保证,这里检查主/子账号身份是否匹配。
if (request.GroupId.HasValue && (subUser ? request.GroupId == 3 : request.GroupId != 3))
throw new AppException("主账号分组必须为3,子账号分组必须为4、5、8、9、10或11");
// 合法分组值已由 DTO 保证,这里检查主/子账号身份是否匹配。
if (request.GroupId.HasValue && (subUser ? request.GroupId == UserGroup.MainAccount : request.GroupId != UserGroup.MainAccount))
throw new AppException("主账号必须使用主号分组,子账号不能使用主号分组");
// 普通主账号只能授予自己已有的权限,不能通过创建子账号提升权限。
if (!IsAdmin(actor) && request.Authority != null)
{