2024-04-29 14:22:45 +08:00
|
|
|
|
using System.Text.RegularExpressions;
|
|
|
|
|
|
using Mapster;
|
2024-04-08 18:57:59 +08:00
|
|
|
|
using Microsoft.Extensions.Caching.Distributed;
|
|
|
|
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
|
|
|
|
using Microsoft.Extensions.Options;
|
|
|
|
|
|
using Volo.Abp.Authorization;
|
|
|
|
|
|
using Volo.Abp.Caching;
|
|
|
|
|
|
using Volo.Abp.Domain.Services;
|
2024-04-29 14:22:45 +08:00
|
|
|
|
using Volo.Abp.EventBus.Local;
|
2023-12-11 09:55:12 +08:00
|
|
|
|
using Volo.Abp.Guids;
|
|
|
|
|
|
using Yi.Framework.Rbac.Domain.Entities;
|
2024-04-08 18:57:59 +08:00
|
|
|
|
using Yi.Framework.Rbac.Domain.Repositories;
|
|
|
|
|
|
using Yi.Framework.Rbac.Domain.Shared.Caches;
|
2024-04-09 17:45:12 +08:00
|
|
|
|
using Yi.Framework.Rbac.Domain.Shared.Consts;
|
2024-04-08 18:57:59 +08:00
|
|
|
|
using Yi.Framework.Rbac.Domain.Shared.Dtos;
|
2024-04-29 14:22:45 +08:00
|
|
|
|
using Yi.Framework.Rbac.Domain.Shared.Etos;
|
2024-04-08 18:57:59 +08:00
|
|
|
|
using Yi.Framework.Rbac.Domain.Shared.Options;
|
2023-12-11 09:55:12 +08:00
|
|
|
|
using Yi.Framework.SqlSugarCore.Abstractions;
|
2023-04-13 21:12:06 +08:00
|
|
|
|
|
2023-12-11 09:55:12 +08:00
|
|
|
|
namespace Yi.Framework.Rbac.Domain.Managers
|
2023-04-13 21:12:06 +08:00
|
|
|
|
{
|
2023-12-11 09:55:12 +08:00
|
|
|
|
public class UserManager : DomainService
|
2023-04-13 21:12:06 +08:00
|
|
|
|
{
|
2024-05-22 14:35:08 +08:00
|
|
|
|
public readonly ISqlSugarRepository<UserAggregateRoot> _repository;
|
2024-01-07 13:34:50 +08:00
|
|
|
|
public readonly ISqlSugarRepository<UserRoleEntity> _repositoryUserRole;
|
|
|
|
|
|
public readonly ISqlSugarRepository<UserPostEntity> _repositoryUserPost;
|
2024-05-22 14:35:08 +08:00
|
|
|
|
private readonly ISqlSugarRepository<RoleAggregateRoot> _roleRepository;
|
2024-04-08 18:57:59 +08:00
|
|
|
|
private IDistributedCache<UserInfoCacheItem, UserInfoCacheKey> _userCache;
|
2023-12-11 09:55:12 +08:00
|
|
|
|
private readonly IGuidGenerator _guidGenerator;
|
2024-04-08 18:57:59 +08:00
|
|
|
|
private IUserRepository _userRepository;
|
2024-04-29 14:22:45 +08:00
|
|
|
|
private ILocalEventBus _localEventBus;
|
2024-05-22 14:35:08 +08:00
|
|
|
|
public UserManager(ISqlSugarRepository<UserAggregateRoot> repository, ISqlSugarRepository<UserRoleEntity> repositoryUserRole, ISqlSugarRepository<UserPostEntity> repositoryUserPost, IGuidGenerator guidGenerator, IDistributedCache<UserInfoCacheItem, UserInfoCacheKey> userCache, IUserRepository userRepository, ILocalEventBus localEventBus, ISqlSugarRepository<RoleAggregateRoot> roleRepository) =>
|
2024-04-29 14:22:45 +08:00
|
|
|
|
(_repository, _repositoryUserRole, _repositoryUserPost, _guidGenerator, _userCache, _userRepository, _localEventBus, _roleRepository) =
|
|
|
|
|
|
(repository, repositoryUserRole, repositoryUserPost, guidGenerator, userCache, userRepository, localEventBus, roleRepository);
|
2023-04-13 21:12:06 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 给用户设置角色
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="userIds"></param>
|
|
|
|
|
|
/// <param name="roleIds"></param>
|
|
|
|
|
|
/// <returns></returns>
|
2023-12-11 09:55:12 +08:00
|
|
|
|
public async Task GiveUserSetRoleAsync(List<Guid> userIds, List<Guid> roleIds)
|
2023-04-13 21:12:06 +08:00
|
|
|
|
{
|
|
|
|
|
|
//删除用户之前所有的用户角色关系(物理删除,没有恢复的必要)
|
|
|
|
|
|
await _repositoryUserRole.DeleteAsync(u => userIds.Contains(u.UserId));
|
|
|
|
|
|
|
|
|
|
|
|
if (roleIds is not null)
|
|
|
|
|
|
{
|
|
|
|
|
|
//遍历用户
|
|
|
|
|
|
foreach (var userId in userIds)
|
|
|
|
|
|
{
|
|
|
|
|
|
//添加新的关系
|
|
|
|
|
|
List<UserRoleEntity> userRoleEntities = new();
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var roleId in roleIds)
|
|
|
|
|
|
{
|
2023-12-11 09:55:12 +08:00
|
|
|
|
userRoleEntities.Add(new UserRoleEntity() { UserId = userId, RoleId = roleId });
|
2023-04-13 21:12:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
//一次性批量添加
|
|
|
|
|
|
await _repositoryUserRole.InsertRangeAsync(userRoleEntities);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 给用户设置岗位
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="userIds"></param>
|
|
|
|
|
|
/// <param name="postIds"></param>
|
|
|
|
|
|
/// <returns></returns>
|
2023-12-11 09:55:12 +08:00
|
|
|
|
public async Task GiveUserSetPostAsync(List<Guid> userIds, List<Guid> postIds)
|
2023-04-13 21:12:06 +08:00
|
|
|
|
{
|
|
|
|
|
|
//删除用户之前所有的用户角色关系(物理删除,没有恢复的必要)
|
|
|
|
|
|
await _repositoryUserPost.DeleteAsync(u => userIds.Contains(u.UserId));
|
|
|
|
|
|
if (postIds is not null)
|
|
|
|
|
|
{
|
|
|
|
|
|
//遍历用户
|
|
|
|
|
|
foreach (var userId in userIds)
|
|
|
|
|
|
{
|
|
|
|
|
|
//添加新的关系
|
|
|
|
|
|
List<UserPostEntity> userPostEntities = new();
|
|
|
|
|
|
foreach (var post in postIds)
|
|
|
|
|
|
{
|
2023-12-11 09:55:12 +08:00
|
|
|
|
userPostEntities.Add(new UserPostEntity() { UserId = userId, PostId = post });
|
2023-04-13 21:12:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//一次性批量添加
|
|
|
|
|
|
await _repositoryUserPost.InsertRangeAsync(userPostEntities);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-04-29 14:22:45 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 创建用户
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns></returns>
|
2024-05-22 14:35:08 +08:00
|
|
|
|
public async Task CreateAsync(UserAggregateRoot userEntity)
|
2024-04-29 14:22:45 +08:00
|
|
|
|
{
|
|
|
|
|
|
//校验用户名
|
|
|
|
|
|
ValidateUserName(userEntity);
|
|
|
|
|
|
|
|
|
|
|
|
if (userEntity.EncryPassword?.Password.Length < 6)
|
|
|
|
|
|
{
|
2024-04-29 17:50:51 +08:00
|
|
|
|
throw new UserFriendlyException(UserConst.Create_Passworld_Error);
|
2024-04-29 14:22:45 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-04-29 14:42:13 +08:00
|
|
|
|
if (userEntity.Phone is not null)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (await _repository.IsAnyAsync(x => x.Phone == userEntity.Phone))
|
|
|
|
|
|
{
|
2024-04-29 17:50:51 +08:00
|
|
|
|
throw new UserFriendlyException(UserConst.Phone_Repeat);
|
2024-04-29 14:42:13 +08:00
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var isExist = await _repository.IsAnyAsync(x => x.UserName == userEntity.UserName);
|
2024-04-29 14:22:45 +08:00
|
|
|
|
if (isExist)
|
|
|
|
|
|
{
|
2024-09-24 11:16:19 +08:00
|
|
|
|
throw new UserFriendlyException(UserConst.Exist);
|
2024-04-29 14:22:45 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var entity = await _repository.InsertReturnEntityAsync(userEntity);
|
|
|
|
|
|
|
|
|
|
|
|
userEntity = entity;
|
|
|
|
|
|
await _localEventBus.PublishAsync(new UserCreateEventArgs(entity.Id));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public async Task SetDefautRoleAsync(Guid userId)
|
|
|
|
|
|
{
|
|
|
|
|
|
var role = await _roleRepository.GetFirstAsync(x => x.RoleCode == UserConst.DefaultRoleCode);
|
|
|
|
|
|
if (role is not null)
|
|
|
|
|
|
{
|
|
|
|
|
|
await GiveUserSetRoleAsync(new List<Guid> { userId }, new List<Guid> { role.Id });
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-05-22 14:35:08 +08:00
|
|
|
|
private void ValidateUserName(UserAggregateRoot input)
|
2024-04-29 14:22:45 +08:00
|
|
|
|
{
|
|
|
|
|
|
if (input.UserName == UserConst.Admin || input.UserName == UserConst.TenantAdmin)
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new UserFriendlyException("用户名无效注册!");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (input.UserName.Length < 2)
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new UserFriendlyException("账号名需大于等于2位!");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 正则表达式,匹配只包含数字和字母的字符串
|
2024-10-25 17:36:23 +08:00
|
|
|
|
string pattern = @"^[a-zA-Z0-9_]+$";
|
2024-04-29 14:22:45 +08:00
|
|
|
|
|
|
|
|
|
|
bool isMatch = Regex.IsMatch(input.UserName, pattern);
|
|
|
|
|
|
if (!isMatch)
|
|
|
|
|
|
{
|
2024-10-25 17:36:23 +08:00
|
|
|
|
throw new UserFriendlyException("用户名不能包含除【字母】与【数字】与【_】的其他字符");
|
2024-04-29 14:22:45 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2024-04-08 18:57:59 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
2024-09-05 23:10:40 +08:00
|
|
|
|
/// 查询用户信息,取消缓存
|
2024-04-08 18:57:59 +08:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <returns></returns>
|
2024-04-09 17:45:12 +08:00
|
|
|
|
public async Task<UserRoleMenuDto> GetInfoAsync(Guid userId)
|
|
|
|
|
|
{
|
2024-09-05 23:10:40 +08:00
|
|
|
|
var user = await _userRepository.GetUserAllInfoAsync(userId);
|
|
|
|
|
|
var data = EntityMapToDto(user);
|
|
|
|
|
|
//系统用户数据被重置,老前端访问重新授权
|
|
|
|
|
|
if (data is null)
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new AbpAuthorizationException();
|
|
|
|
|
|
}
|
|
|
|
|
|
//data.Menus.Clear();
|
|
|
|
|
|
// output = data;
|
|
|
|
|
|
return data;
|
|
|
|
|
|
// var output = await GetInfoByCacheAsync(userId);
|
|
|
|
|
|
// return output;
|
2024-04-09 17:45:12 +08:00
|
|
|
|
}
|
2024-04-26 19:08:18 +08:00
|
|
|
|
private async Task<UserRoleMenuDto> GetInfoByCacheAsync(Guid userId)
|
2024-04-08 18:57:59 +08:00
|
|
|
|
{
|
|
|
|
|
|
//此处优先从缓存中获取
|
|
|
|
|
|
UserRoleMenuDto output = null;
|
2024-04-09 17:45:12 +08:00
|
|
|
|
var tokenExpiresMinuteTime = LazyServiceProvider.GetRequiredService<IOptions<JwtOptions>>().Value.ExpiresMinuteTime;
|
2024-04-26 19:08:18 +08:00
|
|
|
|
var cacheData = await _userCache.GetOrAddAsync(new UserInfoCacheKey(userId),
|
2024-04-09 17:45:12 +08:00
|
|
|
|
async () =>
|
|
|
|
|
|
{
|
2024-04-26 19:08:18 +08:00
|
|
|
|
var user = await _userRepository.GetUserAllInfoAsync(userId);
|
2024-04-09 17:45:12 +08:00
|
|
|
|
var data = EntityMapToDto(user);
|
|
|
|
|
|
//系统用户数据被重置,老前端访问重新授权
|
|
|
|
|
|
if (data is null)
|
|
|
|
|
|
{
|
|
|
|
|
|
throw new AbpAuthorizationException();
|
|
|
|
|
|
}
|
2024-04-26 19:08:18 +08:00
|
|
|
|
//data.Menus.Clear();
|
2024-04-09 17:45:12 +08:00
|
|
|
|
output = data;
|
|
|
|
|
|
return new UserInfoCacheItem(data);
|
|
|
|
|
|
},
|
|
|
|
|
|
() => new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(tokenExpiresMinuteTime) });
|
2024-04-08 18:57:59 +08:00
|
|
|
|
|
|
|
|
|
|
if (cacheData is not null)
|
|
|
|
|
|
{
|
|
|
|
|
|
output = cacheData.Info;
|
|
|
|
|
|
}
|
2024-04-09 17:45:12 +08:00
|
|
|
|
return output!;
|
|
|
|
|
|
}
|
2024-04-08 18:57:59 +08:00
|
|
|
|
|
2024-04-26 19:08:18 +08:00
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 批量查询用户信息
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
/// <param name="userIds"></param>
|
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
|
public async Task<List<UserRoleMenuDto>> GetInfoListAsync(List<Guid> userIds)
|
|
|
|
|
|
{
|
|
|
|
|
|
List<UserRoleMenuDto> output = new List<UserRoleMenuDto>();
|
|
|
|
|
|
foreach (var userId in userIds)
|
|
|
|
|
|
{
|
|
|
|
|
|
output.Add(await GetInfoByCacheAsync(userId));
|
|
|
|
|
|
}
|
|
|
|
|
|
return output;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2024-05-22 14:35:08 +08:00
|
|
|
|
private UserRoleMenuDto EntityMapToDto(UserAggregateRoot user)
|
2024-04-09 17:45:12 +08:00
|
|
|
|
{
|
2024-04-08 18:57:59 +08:00
|
|
|
|
|
2024-04-09 17:45:12 +08:00
|
|
|
|
var userRoleMenu = new UserRoleMenuDto();
|
|
|
|
|
|
//首先获取到该用户全部信息,导航到角色、菜单,(菜单需要去重,完全交给Set来处理即可)
|
2024-09-07 13:43:28 +08:00
|
|
|
|
if (user is null)
|
|
|
|
|
|
{
|
|
|
|
|
|
//为了解决token前端缓存,后端数据库重新dbseed
|
|
|
|
|
|
throw new UserFriendlyException($"数据错误,查询用户不存在,请重新登录");
|
|
|
|
|
|
}
|
2024-04-22 18:06:09 +08:00
|
|
|
|
user.EncryPassword.Password = string.Empty;
|
|
|
|
|
|
user.EncryPassword.Salt = string.Empty;
|
2024-04-09 17:45:12 +08:00
|
|
|
|
|
|
|
|
|
|
//超级管理员特殊处理
|
|
|
|
|
|
if (UserConst.Admin.Equals(user.UserName))
|
|
|
|
|
|
{
|
|
|
|
|
|
userRoleMenu.User = user.Adapt<UserDto>();
|
|
|
|
|
|
userRoleMenu.RoleCodes.Add(UserConst.AdminRolesCode);
|
|
|
|
|
|
userRoleMenu.PermissionCodes.Add(UserConst.AdminPermissionCode);
|
|
|
|
|
|
return userRoleMenu;
|
2024-04-08 18:57:59 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-04-09 17:45:12 +08:00
|
|
|
|
//得到角色集合
|
|
|
|
|
|
var roleList = user.Roles;
|
2024-04-08 18:57:59 +08:00
|
|
|
|
|
2024-04-09 17:45:12 +08:00
|
|
|
|
//得到菜单集合
|
|
|
|
|
|
foreach (var role in roleList)
|
|
|
|
|
|
{
|
|
|
|
|
|
userRoleMenu.RoleCodes.Add(role.RoleCode);
|
2024-04-08 18:57:59 +08:00
|
|
|
|
|
2024-04-09 17:45:12 +08:00
|
|
|
|
if (role.Menus is not null)
|
|
|
|
|
|
{
|
|
|
|
|
|
foreach (var menu in role.Menus)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!string.IsNullOrEmpty(menu.PermissionCode))
|
|
|
|
|
|
{
|
|
|
|
|
|
userRoleMenu.PermissionCodes.Add(menu.PermissionCode);
|
|
|
|
|
|
}
|
|
|
|
|
|
userRoleMenu.Menus.Add(menu.Adapt<MenuDto>());
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//刚好可以去除一下多余的导航属性
|
2024-05-22 14:35:08 +08:00
|
|
|
|
role.Menus = new List<MenuAggregateRoot>();
|
2024-04-09 17:45:12 +08:00
|
|
|
|
userRoleMenu.Roles.Add(role.Adapt<RoleDto>());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-05-22 14:35:08 +08:00
|
|
|
|
user.Roles = new List<RoleAggregateRoot>();
|
2024-04-09 17:45:12 +08:00
|
|
|
|
userRoleMenu.User = user.Adapt<UserDto>();
|
|
|
|
|
|
userRoleMenu.Menus = userRoleMenu.Menus.OrderByDescending(x => x.OrderNum).ToHashSet();
|
|
|
|
|
|
return userRoleMenu;
|
|
|
|
|
|
}
|
2023-04-13 21:12:06 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|