mirror of
https://github.com/nsnail/NetAdmin.git
synced 2025-06-21 03:08:16 +08:00
feat: ✨ 基础模块
注册登录 用户管理 角色管理 部门管理 消息管理 接口管理 菜单管理 字典管理 缓存管理 请求日志 系统设置 版本信息 代码生成
This commit is contained in:
@ -14,10 +14,12 @@ using NetAdmin.SysComponent.Application.Services.Sys.Dependency;
|
||||
namespace NetAdmin.SysComponent.Application.Services.Sys;
|
||||
|
||||
/// <inheritdoc cref="IUserService" />
|
||||
public sealed class UserService : RepositoryService<Sys_User, IUserService>, IUserService
|
||||
public sealed class UserService(DefaultRepository<Sys_User> rpo //
|
||||
, IUserProfileService userProfileService //
|
||||
, IVerifyCodeService verifyCodeService //
|
||||
, IEventPublisher eventPublisher) //
|
||||
: RepositoryService<Sys_User, IUserService>(rpo), IUserService
|
||||
{
|
||||
private readonly IEventPublisher _eventPublisher;
|
||||
|
||||
private readonly Expression<Func<Sys_User, Sys_User>> _selectUserFields = a => new Sys_User {
|
||||
Id = a.Id
|
||||
, Avatar = a.Avatar
|
||||
@ -32,25 +34,7 @@ public sealed class UserService : RepositoryService<Sys_User, IUserService>, IUs
|
||||
, Roles = a.Roles
|
||||
};
|
||||
|
||||
private readonly IUserProfileService _userProfileService;
|
||||
|
||||
private readonly IVerifyCodeService _verifyCodeService;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UserService" /> class.
|
||||
/// </summary>
|
||||
public UserService(Repository<Sys_User> rpo, IUserProfileService userProfileService
|
||||
, IVerifyCodeService verifyCodeService, IEventPublisher eventPublisher) //
|
||||
: base(rpo)
|
||||
{
|
||||
_userProfileService = userProfileService;
|
||||
_verifyCodeService = verifyCodeService;
|
||||
_eventPublisher = eventPublisher;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 批量删除用户
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
public async Task<int> BulkDeleteAsync(BulkReq<DelReq> req)
|
||||
{
|
||||
var sum = 0;
|
||||
@ -61,25 +45,19 @@ public sealed class UserService : RepositoryService<Sys_User, IUserService>, IUs
|
||||
return sum;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查手机号是否可用
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
public async Task<bool> CheckMobileAvailableAsync(CheckMobileAvailableReq req)
|
||||
{
|
||||
return !await Rpo.Select.Where(a => a.Mobile == req.Mobile && a.Id != req.Id).AnyAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查用户名是否可用
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
public async Task<bool> CheckUserNameAvailableAsync(CheckUserNameAvailableReq req)
|
||||
{
|
||||
return !await Rpo.Select.Where(a => a.UserName == req.UserName && a.Id != req.Id).AnyAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建用户
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryUserRsp> CreateAsync(CreateUserReq req)
|
||||
{
|
||||
await CreateUpdateCheckAsync(req);
|
||||
@ -92,14 +70,12 @@ public sealed class UserService : RepositoryService<Sys_User, IUserService>, IUs
|
||||
await Rpo.SaveManyAsync(entity, nameof(entity.Roles));
|
||||
|
||||
// 档案表
|
||||
_ = await _userProfileService.CreateAsync(req.Profile with { Id = dbUser.Id });
|
||||
_ = await userProfileService.CreateAsync(req.Profile with { Id = dbUser.Id });
|
||||
var ret = await QueryAsync(new QueryReq<QueryUserReq> { Filter = new QueryUserReq { Id = dbUser.Id } });
|
||||
return ret.First();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除用户
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
public async Task<int> DeleteAsync(DelReq req)
|
||||
{
|
||||
var effect = 0;
|
||||
@ -111,31 +87,25 @@ public sealed class UserService : RepositoryService<Sys_User, IUserService>, IUs
|
||||
effect += await Rpo.Orm.Delete<Sys_UserRole>(new { UserId = req.Id }).ExecuteAffrowsAsync();
|
||||
|
||||
// 删除档案表
|
||||
effect += await _userProfileService.DeleteAsync(req);
|
||||
effect += await userProfileService.DeleteAsync(req);
|
||||
|
||||
return effect;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 判断用户是否存在
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
public async Task<bool> ExistAsync(QueryReq<QueryUserReq> req)
|
||||
{
|
||||
return await (await QueryInternalAsync(req)).AnyAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取单个用户
|
||||
/// </summary>
|
||||
/// <exception cref="NotImplementedException">NotImplementedException</exception>
|
||||
public Task<QueryUserRsp> GetAsync(QueryUserReq req)
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryUserRsp> GetAsync(QueryUserReq req)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
var ret = await (await QueryInternalAsync(new QueryReq<QueryUserReq> { Filter = req })).ToOneAsync();
|
||||
return ret.Adapt<QueryUserRsp>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取单个用户(带更新锁)
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryUserRsp> GetForUpdateAsync(QueryUserReq req)
|
||||
{
|
||||
// ReSharper disable once MethodHasAsyncOverload
|
||||
@ -143,9 +113,7 @@ public sealed class UserService : RepositoryService<Sys_User, IUserService>, IUs
|
||||
.Adapt<QueryUserRsp>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 密码登录
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
/// <exception cref="NetAdminInvalidOperationException">用户名或密码错误</exception>
|
||||
public async Task<LoginRsp> LoginByPwdAsync(LoginByPwdReq req)
|
||||
{
|
||||
@ -155,35 +123,31 @@ public sealed class UserService : RepositoryService<Sys_User, IUserService>, IUs
|
||||
#pragma warning disable IDE0045
|
||||
if (new MobileAttribute().IsValid(req.Account)) {
|
||||
#pragma warning restore IDE0045
|
||||
dbUser = await Rpo.GetAsync(a => a.Mobile == req.Account && a.Password == pwd);
|
||||
dbUser = await Rpo.Where(a => a.Mobile == req.Account && a.Password == pwd).ToOneAsync();
|
||||
}
|
||||
else {
|
||||
dbUser = new EmailAddressAttribute().IsValid(req.Account)
|
||||
? await Rpo.GetAsync(a => a.Email == req.Account && a.Password == pwd)
|
||||
: await Rpo.GetAsync(a => a.UserName == req.Account && a.Password == pwd);
|
||||
? await Rpo.Where(a => a.Email == req.Account && a.Password == pwd).ToOneAsync()
|
||||
: await Rpo.Where(a => a.UserName == req.Account && a.Password == pwd).ToOneAsync();
|
||||
}
|
||||
|
||||
return dbUser == null ? throw new NetAdminInvalidOperationException(Ln.用户名或密码错误) : LoginInternal(dbUser);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 短信登录
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
/// <exception cref="NetAdminInvalidOperationException">验证码不正确</exception>
|
||||
/// <exception cref="NetAdminInvalidOperationException">用户不存在</exception>
|
||||
public async Task<LoginRsp> LoginBySmsAsync(LoginBySmsReq req)
|
||||
{
|
||||
if (!await _verifyCodeService.VerifyAsync(req.Adapt<VerifySmsCodeReq>())) {
|
||||
if (!await verifyCodeService.VerifyAsync(req.Adapt<VerifySmsCodeReq>())) {
|
||||
throw new NetAdminInvalidOperationException(Ln.验证码不正确);
|
||||
}
|
||||
|
||||
var dbUser = await Rpo.GetAsync(a => a.Mobile == req.DestDevice);
|
||||
var dbUser = await Rpo.Where(a => a.Mobile == req.DestDevice).ToOneAsync();
|
||||
return dbUser == null ? throw new NetAdminInvalidOperationException(Ln.用户不存在) : LoginInternal(dbUser);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 分页查询用户
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
public async Task<PagedQueryRsp<QueryUserRsp>> PagedQueryAsync(PagedQueryReq<QueryUserReq> req)
|
||||
{
|
||||
var list = await (await QueryInternalAsync(req)).Page(req.Page, req.PageSize)
|
||||
@ -192,30 +156,24 @@ public sealed class UserService : RepositoryService<Sys_User, IUserService>, IUs
|
||||
return new PagedQueryRsp<QueryUserRsp>(req.Page, req.PageSize, total, list.Adapt<IEnumerable<QueryUserRsp>>());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询用户
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
public async Task<IEnumerable<QueryUserRsp>> QueryAsync(QueryReq<QueryUserReq> req)
|
||||
{
|
||||
var list = await (await QueryInternalAsync(req)).Take(req.Count).ToListAsync(_selectUserFields);
|
||||
return list.Adapt<IEnumerable<QueryUserRsp>>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询用户档案
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
public Task<IEnumerable<QueryUserProfileRsp>> QueryProfileAsync(QueryReq<QueryUserProfileReq> req)
|
||||
{
|
||||
return _userProfileService.QueryAsync(req);
|
||||
return userProfileService.QueryAsync(req);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 注册用户
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
/// <exception cref="NetAdminInvalidOperationException">验证码不正确</exception>
|
||||
public async Task<UserInfoRsp> RegisterAsync(RegisterUserReq req)
|
||||
{
|
||||
if (!await _verifyCodeService.VerifyAsync(req.VerifySmsCodeReq)) {
|
||||
if (!await verifyCodeService.VerifyAsync(req.VerifySmsCodeReq)) {
|
||||
throw new NetAdminInvalidOperationException(Ln.验证码不正确);
|
||||
}
|
||||
|
||||
@ -223,14 +181,12 @@ public sealed class UserService : RepositoryService<Sys_User, IUserService>, IUs
|
||||
return (await CreateAsync(createReq)).Adapt<UserInfoRsp>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重设密码
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
/// <exception cref="NetAdminInvalidOperationException">验证码不正确</exception>
|
||||
/// <exception cref="NetAdminInvalidOperationException">用户不存在</exception>
|
||||
public async Task<uint> ResetPasswordAsync(ResetPasswordReq req)
|
||||
{
|
||||
return !await _verifyCodeService.VerifyAsync(req.VerifySmsCodeReq)
|
||||
return !await verifyCodeService.VerifyAsync(req.VerifySmsCodeReq)
|
||||
? throw new NetAdminInvalidOperationException(Ln.验证码不正确)
|
||||
: (uint)await Rpo.UpdateDiy
|
||||
.SetSource((await Rpo.Where(a => a.Mobile == req.VerifySmsCodeReq.DestDevice)
|
||||
@ -259,7 +215,7 @@ public sealed class UserService : RepositoryService<Sys_User, IUserService>, IUs
|
||||
.Adapt<UserInfoRsp>();
|
||||
|
||||
// 发布用户更新事件
|
||||
await _eventPublisher.PublishAsync(new UserUpdatedEvent(ret));
|
||||
await eventPublisher.PublishAsync(new UserUpdatedEvent(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -270,12 +226,12 @@ public sealed class UserService : RepositoryService<Sys_User, IUserService>, IUs
|
||||
|
||||
// 如果已绑定手机号、需要手机安全验证
|
||||
if (!user.Mobile.NullOrEmpty()) {
|
||||
if (!await _verifyCodeService.VerifyAsync(req.VerifySmsCodeReq)) {
|
||||
if (!await verifyCodeService.VerifyAsync(req.VerifySmsCodeReq)) {
|
||||
throw new NetAdminInvalidOperationException(Ln.验证码不正确);
|
||||
}
|
||||
|
||||
if (user.Mobile != req.VerifySmsCodeReq.DestDevice) {
|
||||
throw new NetAdminInvalidOperationException($"{Ln.手机号码} {Ln.不正确}");
|
||||
throw new NetAdminInvalidOperationException($"{Ln.手机号码不正确}");
|
||||
}
|
||||
}
|
||||
|
||||
@ -291,7 +247,7 @@ public sealed class UserService : RepositoryService<Sys_User, IUserService>, IUs
|
||||
.Adapt<UserInfoRsp>();
|
||||
|
||||
// 发布用户更新事件
|
||||
await _eventPublisher.PublishAsync(new UserUpdatedEvent(ret));
|
||||
await eventPublisher.PublishAsync(new UserUpdatedEvent(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -302,18 +258,18 @@ public sealed class UserService : RepositoryService<Sys_User, IUserService>, IUs
|
||||
|
||||
if (!user.Mobile.NullOrEmpty()) {
|
||||
// 已有手机号,需验证旧手机
|
||||
if (!await _verifyCodeService.VerifyAsync(req.OriginVerifySmsCodeReq)) {
|
||||
throw new NetAdminInvalidOperationException($"{Ln.旧手机号码} {Ln.验证码不正确}");
|
||||
if (!await verifyCodeService.VerifyAsync(req.OriginVerifySmsCodeReq)) {
|
||||
throw new NetAdminInvalidOperationException($"{Ln.旧手机号码验证码不正确}");
|
||||
}
|
||||
|
||||
if (user.Mobile != req.OriginVerifySmsCodeReq.DestDevice) {
|
||||
throw new NetAdminInvalidOperationException($"{Ln.旧手机号码} {Ln.不正确}");
|
||||
throw new NetAdminInvalidOperationException($"{Ln.旧手机号码不正确}");
|
||||
}
|
||||
}
|
||||
|
||||
// 验证新手机号
|
||||
if (!await _verifyCodeService.VerifyAsync(req.NewVerifySmsCodeReq)) {
|
||||
throw new NetAdminInvalidOperationException($"{Ln.新手机号码} {Ln.验证码不正确}");
|
||||
if (!await verifyCodeService.VerifyAsync(req.NewVerifySmsCodeReq)) {
|
||||
throw new NetAdminInvalidOperationException($"{Ln.新手机号码验证码不正确}");
|
||||
}
|
||||
|
||||
if (await Rpo.UpdateDiy
|
||||
@ -332,7 +288,7 @@ public sealed class UserService : RepositoryService<Sys_User, IUserService>, IUs
|
||||
.Adapt<UserInfoRsp>();
|
||||
|
||||
// 发布用户更新事件
|
||||
await _eventPublisher.PublishAsync(new UserUpdatedEvent(ret));
|
||||
await eventPublisher.PublishAsync(new UserUpdatedEvent(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -341,24 +297,22 @@ public sealed class UserService : RepositoryService<Sys_User, IUserService>, IUs
|
||||
{
|
||||
var version = await Rpo.Where(a => a.Id == UserToken.Id && a.Password == req.OldPassword.Pwd().Guid())
|
||||
.ToOneAsync(a => new long?(a.Version));
|
||||
if (version == null) {
|
||||
throw new NetAdminInvalidInputException($"{Ln.旧密码} {Ln.不正确}");
|
||||
if (version != null) {
|
||||
var ret = await Rpo.UpdateDiy
|
||||
.SetSource(new Sys_User {
|
||||
Id = UserToken.Id
|
||||
, Password = req.NewPassword.Pwd().Guid()
|
||||
, Version = version.Value
|
||||
})
|
||||
.UpdateColumns(a => a.Password)
|
||||
.ExecuteAffrowsAsync();
|
||||
return ret <= 0 ? throw new NetAdminUnexpectedException() : (uint)ret;
|
||||
}
|
||||
|
||||
var ret = await Rpo.UpdateDiy
|
||||
.SetSource(new Sys_User {
|
||||
Id = UserToken.Id
|
||||
, Password = req.NewPassword.Pwd().Guid()
|
||||
, Version = version.Value
|
||||
})
|
||||
.UpdateColumns(a => a.Password)
|
||||
.ExecuteAffrowsAsync();
|
||||
return ret <= 0 ? throw new NetAdminUnexpectedException() : (uint)ret;
|
||||
throw new NetAdminInvalidOperationException($"{Ln.旧密码不正确}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新用户
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
public async Task<QueryUserRsp> UpdateAsync(UpdateUserReq req)
|
||||
{
|
||||
await CreateUpdateCheckAsync(req);
|
||||
@ -373,7 +327,7 @@ public sealed class UserService : RepositoryService<Sys_User, IUserService>, IUs
|
||||
_ = await Rpo.UpdateDiy.SetSource(entity).IgnoreColumns(ignoreCols.ToArray()).ExecuteAffrowsAsync();
|
||||
|
||||
// 档案表
|
||||
_ = await _userProfileService.UpdateAsync(req.Profile);
|
||||
_ = await userProfileService.UpdateAsync(req.Profile);
|
||||
|
||||
// 分表
|
||||
await Rpo.SaveManyAsync(entity, nameof(entity.Roles));
|
||||
@ -381,21 +335,17 @@ public sealed class UserService : RepositoryService<Sys_User, IUserService>, IUs
|
||||
var ret = (await QueryAsync(new QueryReq<QueryUserReq> { Filter = new QueryUserReq { Id = req.Id } })).First();
|
||||
|
||||
// 发布用户更新事件
|
||||
await _eventPublisher.PublishAsync(new UserUpdatedEvent(ret.Adapt<UserInfoRsp>()));
|
||||
await eventPublisher.PublishAsync(new UserUpdatedEvent(ret.Adapt<UserInfoRsp>()));
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 单体更新
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
public Task UpdateSingleAsync(UpdateUserReq req)
|
||||
{
|
||||
return Rpo.UpdateAsync(req);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当前用户信息
|
||||
/// </summary>
|
||||
/// <inheritdoc />
|
||||
public async Task<UserInfoRsp> UserInfoAsync()
|
||||
{
|
||||
var dbUser = await Rpo.Where(a => a.Token == UserToken.Token && a.Enabled)
|
||||
@ -410,6 +360,12 @@ public sealed class UserService : RepositoryService<Sys_User, IUserService>, IUs
|
||||
return dbUser.Adapt<UserInfoRsp>();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Task<Sys_User> UpdateForSqliteAsync(Sys_User req)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private static LoginRsp LoginInternal(IFieldEnabled dbUser)
|
||||
{
|
||||
if (!dbUser.Enabled) {
|
||||
@ -447,10 +403,14 @@ public sealed class UserService : RepositoryService<Sys_User, IUserService>, IUs
|
||||
|
||||
private ISelect<Sys_User> QueryInternal(QueryReq<QueryUserReq> req)
|
||||
{
|
||||
return Rpo.Select.WhereDynamicFilter(req.DynamicFilter)
|
||||
.WhereDynamic(req.Filter)
|
||||
.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending)
|
||||
.OrderByDescending(a => a.Id);
|
||||
var ret = Rpo.Select.WhereDynamicFilter(req.DynamicFilter)
|
||||
.WhereDynamic(req.Filter)
|
||||
.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
||||
if (!req.Prop?.Equals(nameof(req.Filter.Id), StringComparison.OrdinalIgnoreCase) ?? true) {
|
||||
ret = ret.OrderByDescending(a => a.Id);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private async Task<ISelect<Sys_User>> QueryInternalAsync(QueryReq<QueryUserReq> req)
|
||||
@ -473,8 +433,8 @@ public sealed class UserService : RepositoryService<Sys_User, IUserService>, IUs
|
||||
req.Filter?.RoleId > 0, a => a.Roles.Any(b => b.Id == req.Filter.RoleId))
|
||||
.WhereIf( //
|
||||
req.Keywords?.Length > 0
|
||||
, a => a.UserName.Contains(req.Keywords) || a.Id == req.Keywords.Int64Try(0) ||
|
||||
a.Mobile.Contains(req.Keywords) || a.Email.Contains(req.Keywords) ||
|
||||
, a => a.Id == req.Keywords.Int64Try(0) || a.UserName.Contains(req.Keywords) ||
|
||||
a.Mobile.Contains(req.Keywords) || a.Email.Contains(req.Keywords) ||
|
||||
a.Summary.Contains(req.Keywords))
|
||||
.OrderByPropertyNameIf(req.Prop?.Length > 0, req.Prop, req.Order == Orders.Ascending);
|
||||
|
||||
|
Reference in New Issue
Block a user