|
-
- //
-
-
-
-
-
-
-
-
- using SafeCampus.Core.Extension;
-
- namespace SafeCampus.System;
-
- /// <summary>
- /// <inheritdoc cref="ISysUserService"/>
- /// </summary>
- public class SysUserService : DbRepository<SysUser>, ISysUserService
- {
- private readonly ILogger<ILogger> _logger;
- private readonly ISimpleCacheService _simpleCacheService;
- private readonly IRelationService _relationService;
- private readonly IResourceService _resourceService;
- private readonly ISysOrgService _sysOrgService;
- private readonly ISysRoleService _sysRoleService;
- private readonly IImportExportService _importExportService;
- private readonly ISysPositionService _sysPositionService;
- private readonly IDictService _dictService;
- private readonly IConfigService _configService;
- private readonly IBatchEditService _batchEditService;
-
- public SysUserService(ILogger<ILogger> logger, ISimpleCacheService simpleCacheService, IRelationService relationService,
- IResourceService resourceService, ISysOrgService orgService, ISysRoleService sysRoleService,
- IImportExportService importExportService, ISysPositionService sysPositionService, IDictService dictService,
- IConfigService configService, IBatchEditService updateBatchService)
- {
- _logger = logger;
- _simpleCacheService = simpleCacheService;
- _relationService = relationService;
- _resourceService = resourceService;
- _sysOrgService = orgService;
- _sysRoleService = sysRoleService;
- _importExportService = importExportService;
- _sysPositionService = sysPositionService;
- _dictService = dictService;
- _configService = configService;
- _batchEditService = updateBatchService;
- }
-
- #region 查询
-
- /// <inheritdoc/>
- public async Task<string> GetUserAvatar(long userId)
- {
- //先从缓存拿
- var avatar = _simpleCacheService.HashGetOne<string>(SystemConst.CACHE_SYS_USER_AVATAR, userId.ToString());
- if (string.IsNullOrEmpty(avatar))
- {
- //单查获取用户头像
- avatar = await GetFirstAsync(it => it.Id == userId, it => it.Avatar);
- if (!string.IsNullOrEmpty(avatar))
- {
- //插入缓存
- _simpleCacheService.HashAdd(SystemConst.CACHE_SYS_USER_AVATAR, userId.ToString(), avatar);
- }
- }
- return avatar;
- }
-
- /// <inheritdoc/>
- public async Task<SysUser> GetUserByAccount(string account, long? tenantId = null)
- {
- var userId = await GetIdByAccount(account, tenantId);//获取用户ID
- if (userId != SafeCampusConst.ZERO)
- {
- var sysUser = await GetUserById(userId);//获取用户信息
- if (sysUser.Account == account)//这里做了比较用来限制大小写
- return sysUser;
- return null;
- }
- return null;
- }
-
- /// <inheritdoc/>
- public async Task<SysUser> GetUserByPhone(string phone, long? tenantId = null)
- {
- var userId = await GetIdByPhone(phone, tenantId);//获取用户ID
- if (userId > 0)
- {
- return await GetUserById(userId);//获取用户信息
- }
- return null;
- }
-
- /// <inheritdoc/>
- public async Task<long> GetIdByPhone(string phone, long? tenantId = null)
- {
- var orgIds = new List<long>();
- var key = SystemConst.CACHE_SYS_USER_PHONE;
- if (tenantId != null)
- {
- key += $":{tenantId}";
- orgIds = await _sysOrgService.GetOrgChildIds(tenantId.Value);//获取下级机构
- }
- //先从缓存拿
- var userId = _simpleCacheService.HashGetOne<long>(key, phone);
- if (userId == 0)
- {
- var sm4Phone = CryptogramUtil.Sm4Encrypt(phone);//SM4加密一下
- //单查获取用户手机号对应的账号
- userId = await Context.Queryable<SysUser>()
- .Where(it => it.Phone == sm4Phone)
- .WhereIF(orgIds.Count > 0, it => orgIds.Contains(it.OrgId))
- .Select(it => it.Id)
- .FirstAsync();
- if (userId > 0)
- {
- //插入缓存
- _simpleCacheService.HashAdd(key, phone, userId);
- }
- }
- return userId;
- }
-
- /// <inheritdoc/>
- public async Task<SysUser> GetUserById(long userId)
- {
- //先从缓存拿
- var sysUser = _simpleCacheService.HashGetOne<SysUser>(SystemConst.CACHE_SYS_USER, userId.ToString());
- if (sysUser == null)
- {
- sysUser = await GetUserFromDb(userId);//从数据库拿用户信息
- }
- return sysUser;
- }
-
- /// <inheritdoc/>
- public async Task<T> GetUserById<T>(long userId)
- {
- var user = await GetUserById(userId);
- return user.Adapt<T>();
- }
-
- /// <inheritdoc/>
- public async Task<long> GetIdByAccount(string account, long? tenantId = null)
- {
- var orgIds = new List<long>();
- var key = SystemConst.CACHE_SYS_USER_ACCOUNT;
- if (tenantId != null)
- {
- key += $":{tenantId}";
- orgIds = await _sysOrgService.GetOrgChildIds(tenantId.Value);//获取下级机构
- }
- //先从缓存拿
- var userId = _simpleCacheService.HashGetOne<long>(key, account);
- if (userId == 0)
- {
- //单查获取用户账号对应ID
- userId = await Context.Queryable<SysUser>()
- .Where(it => it.Account == account)
- .WhereIF(orgIds.Count > 0, it => orgIds.Contains(it.OrgId))
- .Select(it => it.Id)
- .FirstAsync();
- if (userId != 0)
- {
- //插入缓存
- _simpleCacheService.HashAdd(key, account, userId);
- }
- }
- return userId;
- }
-
- /// <inheritdoc/>
- public async Task<List<string>> GetButtonCodeList(long userId)
- {
- var buttonCodeList = new List<string>();//按钮ID集合
- //获取用户资源集合
- var resourceList = await _relationService.GetRelationListByObjectIdAndCategory(userId, CateGoryConst.RELATION_SYS_USER_HAS_RESOURCE);
- var buttonIdList = new List<long>();//按钮ID集合
- if (resourceList.Count == 0)//如果有表示用户单独授权了不走用户角色
- {
- //获取用户角色关系集合
- var roleList = await _relationService.GetRelationListByObjectIdAndCategory(userId, CateGoryConst.RELATION_SYS_USER_HAS_ROLE);
- var roleIdList = roleList.Select(x => x.TargetId.ToLong()).ToList();//角色ID列表
- if (roleIdList.Count > 0)//如果该用户有角色
- {
- resourceList = await _relationService.GetRelationListByObjectIdListAndCategory(roleIdList,
- CateGoryConst.RELATION_SYS_ROLE_HAS_RESOURCE);//获取资源集合
- }
- }
- resourceList.ForEach(it =>
- {
- if (!string.IsNullOrEmpty(it.ExtJson))
- buttonIdList.AddRange(it.ExtJson.ToJsonEntity<RelationRoleResource>().ButtonInfo);//如果有按钮权限,将按钮ID放到buttonIdList
- });
- if (buttonIdList.Count > 0)
- {
- buttonCodeList = await _resourceService.GetCodeByIds(buttonIdList, CateGoryConst.RESOURCE_BUTTON);
- }
- return buttonCodeList;
- }
-
- /// <inheritdoc/>
- public async Task<List<DataScope>> GetPermissionListByUserId(long userId, long orgId)
- {
- var permissions = new List<DataScope>();//权限集合
- var sysRelations =
- await _relationService.GetRelationListByObjectIdAndCategory(userId, CateGoryConst.RELATION_SYS_USER_HAS_PERMISSION);//根据用户ID获取用户权限
- if (sysRelations.Count == 0)//如果有表示用户单独授权了不走用户角色
- {
- var roleIdList =
- await _relationService.GetRelationListByObjectIdAndCategory(userId, CateGoryConst.RELATION_SYS_USER_HAS_ROLE);//根据用户ID获取角色ID
- if (roleIdList.Count > 0)//如果角色ID不为空
- {
- //获取角色权限信息
- sysRelations = await _relationService.GetRelationListByObjectIdListAndCategory(roleIdList.Select(it => it.TargetId.ToLong()).ToList(),
- CateGoryConst.RELATION_SYS_ROLE_HAS_PERMISSION);
- }
- }
- var relationGroup = sysRelations.GroupBy(it => it.TargetId).ToList();//根据目标ID,也就是接口名分组,因为存在一个用户多个角色
- //遍历分组
- foreach (var it in relationGroup)
- {
- var scopeSet = new HashSet<long>();//定义不可重复列表
- var relationList = it.ToList();//关系列表
- var scopeCategory = CateGoryConst.SCOPE_SELF;//数据权限分类,默认为仅自己
- //获取角色权限信息列表
- var rolePermissions = relationList.Select(it => it.ExtJson.ToJsonEntity<RelationRolePermission>()).ToList();
- if (rolePermissions.Any(role => role.ScopeCategory == CateGoryConst.SCOPE_ALL))//如果有全部
- scopeCategory = CateGoryConst.SCOPE_ALL;//标记为全部
- else if (rolePermissions.Any(role => role.ScopeCategory == CateGoryConst.SCOPE_ORG_CHILD))//如果有机构及以下机构
- scopeCategory = CateGoryConst.SCOPE_ORG_CHILD;//标记为机构及以下机构
- else if (rolePermissions.Any(role => role.ScopeCategory == CateGoryConst.SCOPE_ORG))//如果有仅自己机构
- scopeCategory = CateGoryConst.SCOPE_ORG;//标记为仅自己机构
- else if (rolePermissions.Any(role => role.ScopeCategory == CateGoryConst.SCOPE_ORG_DEFINE))//如果有自定义机构
- {
- scopeCategory = CateGoryConst.SCOPE_ORG_DEFINE;//标记为仅自己
- rolePermissions.ForEach(s =>
- {
- scopeSet.AddRange(s.ScopeDefineOrgIdList);//添加自定义范围的机构ID
- });
- }
- var dataScopes = scopeSet.ToList();//获取范围列表转列表
- permissions.Add(new DataScope
- {
- ApiUrl = it.Key,
- ScopeCategory = scopeCategory,
- DataScopes = dataScopes
- });//将改URL的权限集合加入权限集合列表
- }
- return permissions;
- }
-
-
- /// <inheritdoc/>
- public async Task<SqlSugarPagedList<UserSelectorOutPut>> Selector(UserSelectorInput input)
- {
- var orgIds = await _sysOrgService.GetOrgChildIds(input.OrgId);//获取下级机构
- var result = await Context.Queryable<SysUser>()
- .WhereIF(input.OrgId > 0, u => orgIds.Contains(u.OrgId))//指定机构
- .WhereIF(input.OrgIds != null, u => input.OrgIds.Contains(u.OrgId))//在指定机构列表查询
- .WhereIF(input.PositionId > 0, u => u.PositionId == input.PositionId)//指定职位
- .WhereIF(input.RoleId > 0,
- u => SqlFunc.Subqueryable<SysRelation>()
- .Where(r => r.TargetId == input.RoleId.ToString() && r.ObjectId == u.Id && r.Category == CateGoryConst.RELATION_SYS_USER_HAS_ROLE)
- .Any())//指定角色
- .WhereIF(!string.IsNullOrEmpty(input.Account), u => u.Account.Contains(input.Account))//根据关键字查询
- .Select<UserSelectorOutPut>().ToPagedListAsync(input.PageNum, input.PageSize);
- return result;
- }
-
- /// <inheritdoc/>
- public async Task<SqlSugarPagedList<SysUser>> Page(UserPageInput input)
- {
- var query = await GetQuery(input);//获取查询条件
- var pageInfo = await query.ToPagedListAsync(input.PageNum, input.PageSize);//分页
- return pageInfo;
- }
-
- /// <inheritdoc/>
- public async Task<List<SysUser>> List(UserPageInput input)
- {
- var query = await GetQuery(input);//获取查询条件
- var list = await query.ToListAsync();
- return list;
- }
-
- /// <inheritdoc/>
- public async Task<List<RoleSelectorOutPut>> OwnRole(BaseIdInput input)
- {
- var relations = await _relationService.GetRelationListByObjectIdAndCategory(input.Id, CateGoryConst.RELATION_SYS_USER_HAS_ROLE);
- var roleIds = relations.Select(it => it.TargetId.ToLong()).ToList();
- var roleList = await Context.Queryable<SysRole>().Where(it => roleIds.Contains(it.Id)).Select<RoleSelectorOutPut>().ToListAsync();
- return roleList;
- }
-
- /// <inheritdoc />
- public async Task<RoleOwnResourceOutput> OwnResource(BaseIdInput input)
- {
- return await _sysRoleService.OwnResource(input, CateGoryConst.RELATION_SYS_USER_HAS_RESOURCE);
- }
-
- /// <inheritdoc />
- public async Task<RoleOwnPermissionOutput> OwnPermission(BaseIdInput input)
- {
- var roleOwnPermission = new RoleOwnPermissionOutput
- {
- Id = input.Id
- };//定义结果集
- var grantInfoList = new List<RelationRolePermission>();//已授权信息集合
- //获取关系列表
- var relations = await _relationService.GetRelationListByObjectIdAndCategory(input.Id, CateGoryConst.RELATION_SYS_USER_HAS_PERMISSION);
- //遍历关系表
- relations.ForEach(it =>
- {
- //将扩展信息转为实体
- var relationPermission = it.ExtJson.ToJsonEntity<RelationRolePermission>();
- grantInfoList.Add(relationPermission);//添加到已授权信息
- });
- roleOwnPermission.GrantInfoList = grantInfoList;//赋值已授权信息
- return roleOwnPermission;
- }
-
- /// <inheritdoc />
- public async Task<List<string>> UserPermissionTreeSelector(BaseIdInput input)
- {
- var permissionTreeSelectors = new List<string>();//授权树结果集
- //获取用户资源关系
- var relationsRes = await _relationService.GetRelationByCategory(CateGoryConst.RELATION_SYS_USER_HAS_RESOURCE);
- var menuIds = relationsRes.Where(it => it.ObjectId == input.Id).Select(it => it.TargetId.ToLong()).ToList();
- if (menuIds.Any())
- {
- //获取菜单信息
- var menus = await _resourceService.GetResourcesByIds(menuIds, CateGoryConst.RESOURCE_MENU);
- //获取权限授权树
- var permissions = _resourceService.PermissionTreeSelector(menus.Select(it => it.Path).ToList());
- if (permissions.Count > 0)
- {
- permissionTreeSelectors = permissions.Select(it => it.PermissionName).ToList();//返回授权树权限名称列表
- }
- }
- return permissionTreeSelectors;
- }
-
- /// <inheritdoc />
- public async Task<List<UserSelectorOutPut>> GetUserListByIdList(IdListInput input)
- {
- var userList = await Context.Queryable<SysUser>().Where(it => input.IdList.Contains(it.Id)).Select<UserSelectorOutPut>().ToListAsync();
- return userList;
- }
-
- /// <inheritdoc />
- public async Task<SysUser> Detail(BaseIdInput input)
- {
- var user = await GetUserById(input.Id);
- if (user != null)
- {
- user.Password = null;//清空密码
- }
- return user;
- }
-
- #endregion 查询
-
- #region 数据范围相关
-
- /// <inheritdoc/>
- public async Task<List<long>?> GetLoginUserApiDataScope()
- {
- var userInfo = await GetUserById(UserManager.UserId);//获取用户信息
- // 路由名称
- var routeName = App.HttpContext.Request.Path.Value;
- //获取当前url的数据范围
- var dataScope = userInfo.DataScopeList.Where(it => it.ApiUrl == routeName).FirstOrDefault();
- if (dataScope != null)
- {
- //根据数据范围分类获取数据范围
- //null:代表拥有全部数据权限
- //[xx,xx]:代表拥有部分机构的权限
- //[]:代表仅自己权限
- switch (dataScope.ScopeCategory)
- {
- case CateGoryConst.SCOPE_ALL:
- return null;
-
- case CateGoryConst.SCOPE_ORG_CHILD:
- return userInfo.ScopeOrgChildList;
-
- case CateGoryConst.SCOPE_ORG:
- return new List<long> { userInfo.OrgId };
-
- case CateGoryConst.SCOPE_ORG_DEFINE:
- return dataScope.DataScopes;
-
- case CateGoryConst.SCOPE_SELF:
- return new List<long>();
- }
- }
- return new List<long>();
- }
-
- /// <inheritdoc/>
- public async Task<bool> CheckApiDataScope(long? orgId, long? createUerId, string errMsg = "")
- {
- var hasPermission = true;
- //判断数据范围
- var dataScope = await GetLoginUserApiDataScope();
- if (dataScope is { Count: > 0 })//如果有机构
- {
- if (orgId == null || !dataScope.Contains(orgId.Value))//判断机构id是否在数据范围
- hasPermission = false;
- }
- else if (dataScope is { Count: 0 })// 表示仅自己
- {
- if (createUerId != UserManager.UserId)
- hasPermission = false;//机构的创建人不是自己则报错
- }
- //如果传了错误信息,直接抛出异常
- if (!hasPermission && !string.IsNullOrEmpty(errMsg))
- throw Oops.Bah(errMsg);
- return hasPermission;
- }
-
- public async Task<bool> CheckApiDataScope(List<long> orgIds, List<long> createUerIds, string errMsg = "")
- {
- var hasPermission = true;
- //判断数据范围
- var dataScope = await GetLoginUserApiDataScope();
- if (dataScope is { Count: > 0 })//如果有机构
- {
- if (orgIds == null || !dataScope.ContainsAll(orgIds))//判断机构id列表是否全在数据范围
- hasPermission = false;
- }
- else if (dataScope is { Count: 0 })// 表示仅自己
- {
- if (createUerIds.Any(it => it != UserManager.UserId))//如果创建者id里有任何不是自己创建的机构
- hasPermission = false;
- }
- //如果传了错误信息,直接抛出异常
- if (!hasPermission && !string.IsNullOrEmpty(errMsg))
- throw Oops.Bah(errMsg);
- return hasPermission;
- }
-
- #endregion
-
- #region 新增
-
- /// <inheritdoc/>
- public async Task Add(UserAddInput input)
- {
- await CheckInput(input);//检查参数
- var sysUser = input.Adapt<SysUser>();//实体转换
- //默认头像
- sysUser.Avatar = AvatarUtil.GetNameImageBase64(sysUser.Name);
- //获取默认密码
- sysUser.Password = await GetDefaultPassWord(true);//设置密码
- sysUser.Status = CommonStatusConst.ENABLE;//默认状态
- await InsertAsync(sysUser);//添加数据
- }
-
- #endregion 新增
-
- #region 编辑
-
- /// <inheritdoc/>
- public async Task Edit(UserEditInput input)
- {
- await CheckInput(input);//检查参数
- var exist = await GetUserById(input.Id);//获取用户信息
- if (exist != null)
- {
- var isSuperAdmin = exist.Account == SysRoleConst.SUPER_ADMIN;//判断是否有超管
- if (isSuperAdmin && !UserManager.SuperAdmin)
- throw Oops.Bah("不可修改系统内置超管用户账号");
- var name = exist.Name;//姓名
- var sysUser = input.Adapt<SysUser>();//实体转换
- if (name != input.Name)
- sysUser.Avatar = AvatarUtil.GetNameImageBase64(input.Name);//如果姓名改变了,重新生成头像
- if (await Context.Updateable(sysUser).IgnoreColumns(it => new
- {
- //忽略更新字段
- it.Password,
- it.LastLoginAddress,
- it.LastLoginDevice,
- it.LastLoginIp,
- it.LastLoginTime,
- it.LatestLoginAddress,
- it.LatestLoginDevice,
- it.LatestLoginIp,
- it.LatestLoginTime
- }).IgnoreColumnsIF(name == input.Name, it => it.Avatar).ExecuteCommandAsync() > 0
- )//修改数据
- {
- DeleteUserFromRedis(sysUser.Id);//删除用户缓存
- //删除用户token缓存
- _simpleCacheService.HashDel<List<TokenInfo>>(CacheConst.CACHE_USER_TOKEN, sysUser.Id.ToString());
- }
- }
- }
-
- /// <inheritdoc/>
- public async Task Edits(BatchEditInput input)
- {
- //获取参数字典
- var data = await _batchEditService.GetUpdateBatchConfigDict(input.Code, input.Columns);
- if (data.Count > 0)
- {
- await Context.Updateable<SysUser>(data).Where(it => input.Ids.Contains(it.Id)).ExecuteCommandAsync();
- }
- }
-
- /// <inheritdoc/>
- public async Task DisableUser(BaseIdInput input)
- {
- var sysUser = await GetUserById(input.Id);//获取用户信息
- if (sysUser != null)
- {
- var isSuperAdmin = sysUser.Account == SysRoleConst.SUPER_ADMIN;//判断是否有超管
- if (isSuperAdmin)
- throw Oops.Bah("不可禁用系统内置超管用户账号");
- CheckSelf(input.Id, SystemConst.DISABLE);//判断是不是自己
- //设置状态为禁用
- if (await UpdateSetColumnsTrueAsync(it => new SysUser
- {
- Status = CommonStatusConst.DISABLED
- }, it => it.Id == input.Id))
- DeleteUserFromRedis(input.Id);//从缓存删除用户信息
- }
- }
-
- /// <inheritdoc/>
- public async Task EnableUser(BaseIdInput input)
- {
- CheckSelf(input.Id, SystemConst.ENABLE);//判断是不是自己
- //设置状态为启用
- if (await UpdateSetColumnsTrueAsync(it => new SysUser
- {
- Status = CommonStatusConst.ENABLE
- }, it => it.Id == input.Id))
- DeleteUserFromRedis(input.Id);//从缓存删除用户信息
- }
-
- /// <inheritdoc/>
- public async Task ResetPassword(BaseIdInput input)
- {
- var password = await GetDefaultPassWord(true);//获取默认密码,这里不走Aop所以需要加密一下
- //重置密码
- if (await UpdateSetColumnsTrueAsync(it => new SysUser
- {
- Password = password
- }, it => it.Id == input.Id))
- DeleteUserFromRedis(input.Id);//从缓存删除用户信息
- }
-
- /// <inheritdoc />
- public async Task GrantRole(UserGrantRoleInput input)
- {
- var sysUser = await GetUserById(input.Id);//获取用户信息
- if (sysUser != null)
- {
- var isSuperAdmin = sysUser.Account == SysRoleConst.SUPER_ADMIN;//判断是否有超管
- if (isSuperAdmin)
- throw Oops.Bah("不能给超管分配角色");
- CheckSelf(input.Id, SystemConst.GRANT_ROLE);//判断是不是自己
- //给用户赋角色
- await _relationService.SaveRelationBatch(CateGoryConst.RELATION_SYS_USER_HAS_ROLE, input.Id,
- input.RoleIdList.Select(it => it.ToString()).ToList(), null, true);
- DeleteUserFromRedis(input.Id);//从缓存删除用户信息
- }
- }
-
- /// <inheritdoc />
- public async Task GrantResource(UserGrantResourceInput input)
- {
- var menuIds = input.GrantInfoList.Select(it => it.MenuId).ToList();//菜单ID
- var extJsons = input.GrantInfoList.Select(it => it.ToJson()).ToList();//拓展信息
- var relationRoles = new List<SysRelation>();//要添加的用户资源和授权关系表
- var sysUser = await GetUserById(input.Id);//获取用户
- if (sysUser != null)
- {
- #region 用户资源处理
-
- //遍历角色列表
- for (var i = 0; i < menuIds.Count; i++)
- {
- //将用户资源添加到列表
- relationRoles.Add(new SysRelation
- {
- ObjectId = sysUser.Id,
- TargetId = menuIds[i].ToString(),
- Category = CateGoryConst.RELATION_SYS_USER_HAS_RESOURCE,
- ExtJson = extJsons == null ? null : extJsons[i]
- });
- }
-
- #endregion 用户资源处理
-
- #region 用户权限处理.
-
- var relationRolePer = new List<SysRelation>();//要添加的用户有哪些权限列表
- var defaultDataScope = input.DefaultDataScope;//获取默认数据范围
-
- //获取菜单信息
- var menus = await _resourceService.GetResourcesByIds(menuIds, CateGoryConst.RESOURCE_MENU);
- if (menus.Count > 0)
- {
- #region 用户模块关系
-
- //获取我的模块信息Id列表
- var moduleIds = menus.Select(it => it.Module.Value).Distinct().ToList();
- moduleIds.ForEach(it =>
- {
- //将角色资源添加到列表
- relationRoles.Add(new SysRelation
- {
- ObjectId = sysUser.Id,
- TargetId = it.ToString(),
- Category = CateGoryConst.RELATION_SYS_USER_HAS_MODULE
- });
- });
-
- #endregion
-
- //获取权限授权树
- var permissions = _resourceService.PermissionTreeSelector(menus.Select(it => it.Path).ToList());
- permissions.ForEach(it =>
- {
- //新建角色权限关系
- relationRolePer.Add(new SysRelation
- {
- ObjectId = sysUser.Id,
- TargetId = it.ApiRoute,
- Category = CateGoryConst.RELATION_SYS_USER_HAS_PERMISSION,
- ExtJson = new RelationRolePermission
- {
- ApiUrl = it.ApiRoute,
- ScopeCategory = defaultDataScope.ScopeCategory,
- ScopeDefineOrgIdList = defaultDataScope.ScopeDefineOrgIdList
- }.ToJson()
- });
- });
- }
- relationRoles.AddRange(relationRolePer);//合并列表
-
- #endregion 用户权限处理.
-
- #region 保存数据库
-
- //事务
- var result = await Tenant.UseTranAsync(async () =>
- {
- var relationRep = ChangeRepository<DbRepository<SysRelation>>();//切换仓储
- await relationRep.DeleteAsync(it => it.ObjectId == sysUser.Id && (it.Category == CateGoryConst.RELATION_SYS_USER_HAS_PERMISSION
- || it.Category == CateGoryConst.RELATION_SYS_USER_HAS_RESOURCE) || it.Category == CateGoryConst.RELATION_SYS_USER_HAS_MODULE);
- await relationRep.InsertRangeAsync(relationRoles);//添加新的
- });
- if (result.IsSuccess)//如果成功了
- {
- await _relationService.RefreshCache(CateGoryConst.RELATION_SYS_USER_HAS_PERMISSION);//刷新关系缓存
- await _relationService.RefreshCache(CateGoryConst.RELATION_SYS_USER_HAS_RESOURCE);//刷新关系缓存
- await _relationService.RefreshCache(CateGoryConst.RELATION_SYS_USER_HAS_MODULE);//刷新关系缓存
- DeleteUserFromRedis(input.Id);//删除该用户缓存
- }
- else
- {
- //写日志
- _logger.LogError(result.ErrorMessage, result.ErrorException);
- throw Oops.Oh(ErrorCodeEnum.A0003);
- }
-
- #endregion 保存数据库
- }
- }
-
- /// <inheritdoc />
- public async Task GrantPermission(GrantPermissionInput input)
- {
- var sysUser = await GetUserById(input.Id);//获取用户
- if (sysUser != null)
- {
- var apiUrls = input.GrantInfoList.Select(it => it.ApiUrl).ToList();//apiurl列表
- var extJsons = input.GrantInfoList.Select(it => it.ToJson()).ToList();//拓展信息
- await _relationService.SaveRelationBatch(CateGoryConst.RELATION_SYS_USER_HAS_PERMISSION, input.Id, apiUrls, extJsons,
- true);//添加到数据库
- DeleteUserFromRedis(input.Id);
- }
- }
-
- #endregion 编辑
-
- #region 删除
-
- /// <inheritdoc/>
- public async Task Delete(BaseIdListInput input)
- {
- //获取所有ID
- var ids = input.Ids;
- if (ids.Count > 0)
- {
- var containsSuperAdmin = await IsAnyAsync(it => it.Account == SysRoleConst.SUPER_ADMIN && ids.Contains(it.Id));//判断是否有超管
- if (containsSuperAdmin)
- throw Oops.Bah("不可删除系统内置超管用户");
- if (ids.Contains(UserManager.UserId))
- throw Oops.Bah("不可删除自己");
-
- //定义删除的关系
- var delRelations = new List<string>
- {
- CateGoryConst.RELATION_SYS_USER_HAS_RESOURCE,
- CateGoryConst.RELATION_SYS_USER_HAS_PERMISSION,
- CateGoryConst.RELATION_SYS_USER_HAS_ROLE,
- CateGoryConst.RELATION_SYS_USER_HAS_MODULE,
- CateGoryConst.RELATION_SYS_USER_SCHEDULE_DATA,
- CateGoryConst.RELATION_SYS_USER_WORKBENCH_DATA
- };
- //事务
- var result = await Tenant.UseTranAsync(async () =>
- {
- //清除该用户作为主管信息
- await UpdateAsync(it => new SysUser
- {
- DirectorId = null
- }, it => ids.Contains(it.DirectorId.Value));
-
- //删除用户
- await DeleteByIdsAsync(ids.Cast<object>().ToArray());
- var relationRep = ChangeRepository<DbRepository<SysRelation>>();//切换仓储
- //删除关系表用户与资源关系,用户与权限关系,用户与角色关系
- await relationRep.DeleteAsync(it => ids.Contains(it.ObjectId) && delRelations.Contains(it.Category));
- var orgRep = ChangeRepository<DbRepository<SysOrg>>();//切换仓储
- //删除组织表主管信息
- await orgRep.DeleteAsync(it => ids.Contains(it.DirectorId.Value));
- });
- if (result.IsSuccess)//如果成功了
- {
- DeleteUserFromRedis(ids);//缓存删除用户
- await _relationService.RefreshCache(CateGoryConst.RELATION_SYS_USER_HAS_ROLE);//关系表刷新SYS_USER_HAS_ROLE缓存
- await _relationService.RefreshCache(CateGoryConst.RELATION_SYS_USER_HAS_RESOURCE);//关系表刷新SYS_USER_HAS_ROLE缓存
- await _relationService.RefreshCache(CateGoryConst.RELATION_SYS_USER_HAS_PERMISSION);//关系表刷新SYS_USER_HAS_ROLE缓存
- await _relationService.RefreshCache(CateGoryConst.RELATION_SYS_USER_HAS_MODULE);//关系表刷新RELATION_SYS_USER_HAS_MODULE缓存
- await _relationService.RefreshCache(CateGoryConst.RELATION_SYS_USER_SCHEDULE_DATA);//关系表刷新RELATION_SYS_USER_SCHEDULE_DATA缓存
- await _relationService.RefreshCache(CateGoryConst.RELATION_SYS_USER_WORKBENCH_DATA);//关系表刷新RELATION_SYS_USER_WORKBENCH_DATA缓存
- // TODO 此处需要将这些用户踢下线,并永久注销这些用户
- var idArray = ids.Select(it => it.ToString()).ToArray();
- //从列表中删除
- _simpleCacheService.HashDel<List<TokenInfo>>(CacheConst.CACHE_USER_TOKEN, idArray);
- }
- else
- {
- //写日志
- _logger.LogError(result.ErrorMessage, result.ErrorException);
- throw Oops.Oh(ErrorCodeEnum.A0002);
- }
- }
- }
-
- /// <inheritdoc />
- public void DeleteUserFromRedis(long userId)
- {
- DeleteUserFromRedis(new List<long>
- {
- userId
- });
- }
-
- /// <inheritdoc />
- public void DeleteUserFromRedis(List<long> ids)
- {
- var userIds = ids.Select(it => it.ToString()).ToArray();//id转string列表
- var sysUsers = _simpleCacheService.HashGet<SysUser>(SystemConst.CACHE_SYS_USER, userIds);//获取用户列表
- sysUsers = sysUsers.Where(it => it != null).ToList();//过滤掉不存在的
- if (sysUsers.Count > 0)
- {
- var accounts = sysUsers.Select(it => it.Account).ToArray();//账号集合
- var phones = sysUsers.Select(it => it.Phone).ToArray();//手机号集合
- //删除用户信息
- _simpleCacheService.HashDel<SysUser>(SystemConst.CACHE_SYS_USER, userIds);
- //删除用户头像信息
- _simpleCacheService.HashDel<string>(SystemConst.CACHE_SYS_USER_AVATAR, userIds);
- var userAccountKey = SystemConst.CACHE_SYS_USER_ACCOUNT;
- var userPhoneKey = SystemConst.CACHE_SYS_USER_PHONE;
- if (sysUsers.Any(it => it.TenantId != null))//如果有租户id不是空的表示是多租户模式
- {
- var tenantIds = sysUsers.Where(it => it.TenantId != null).Select(it => it.TenantId.Value).Distinct().ToArray();//租户id列表
- foreach (var tenantId in tenantIds)
- {
- userAccountKey = $"{userAccountKey}:{tenantId}";
- userPhoneKey = $"{userPhoneKey}:{tenantId}";
- //删除账号
- _simpleCacheService.HashDel<long>(userAccountKey, accounts);
- //删除手机
- if (phones != null)
- _simpleCacheService.HashDel<long>(userPhoneKey, phones);
- }
- }
- else
- {
- //删除账号
- _simpleCacheService.HashDel<long>(userAccountKey, accounts);
- //删除手机
- if (phones != null)
- _simpleCacheService.HashDel<long>(userPhoneKey, phones);
- }
- }
- }
-
- #endregion 删除
-
- #region 导入导出
-
- /// <inheritdoc/>
- public async Task<FileStreamResult> Template()
- {
- var templateName = "用户信息";
- //var result = _importExportService.GenerateLocalTemplate(templateName);
- var result = await _importExportService.GenerateTemplate<SysUserImportInput>(templateName);
- return result;
- }
-
- /// <inheritdoc/>
- public async Task<ImportPreviewOutput<SysUserImportInput>> Preview(ImportPreviewInput input)
- {
- var importPreview = await _importExportService.GetImportPreview<SysUserImportInput>(input.File);
- importPreview.Data = await CheckImport(importPreview.Data);//检查导入数据
- return importPreview;
- }
-
- /// <inheritdoc/>
- public async Task<ImportResultOutPut<SysUserImportInput>> Import(ImportResultInput<SysUserImportInput> input)
- {
- var data = await CheckImport(input.Data, true);//检查数据格式
- var result = _importExportService.GetImportResultPreview(data, out var importData);
- var sysUsers = importData.Adapt<List<SysUser>>();//转实体
- await SetUserDefault(sysUsers);//设置默认值
- await InsertOrBulkCopy(sysUsers);// 数据导入
- return result;
- }
-
- /// <inheritdoc/>
- public async Task<FileStreamResult> Export(UserPageInput input)
- {
- var genTests = await List(input);
- var data = genTests.Adapt<List<SysUserExportOutput>>();//转为Dto
- var result = await _importExportService.Export(data, "用户信息");
- return result;
- }
-
- /// <inheritdoc/>
- public async Task<List<T>> CheckImport<T>(List<T> data, bool clearError = false) where T : SysUserImportInput
- {
- #region 校验要用到的数据
-
- var accounts = data.Select(it => it.Account).ToList();//当前导入数据账号列表
- var phones = data.Where(it => !string.IsNullOrEmpty(it.Phone)).Select(it => it.Phone).ToList();//当前导入数据手机号列表
- var emails = data.Where(it => !string.IsNullOrEmpty(it.Email)).Select(it => it.Email).ToList();//当前导入数据邮箱列表
- var sysUsers = await GetListAsync(it => true, it => new SysUser
- {
- Account = it.Account,
- Phone = it.Phone,
- Email = it.Email
- });//获取数据用户信息
- var dbAccounts = sysUsers.Select(it => it.Account).ToList();//数据库账号列表
- var dbPhones = sysUsers.Where(it => !string.IsNullOrEmpty(it.Phone)).Select(it => it.Phone).ToList();//数据库手机号列表
- var dbEmails = sysUsers.Where(it => !string.IsNullOrEmpty(it.Email)).Select(it => it.Email).ToList();//邮箱账号列表
- var sysOrgList = await _sysOrgService.GetListAsync();
- var sysPositions = await _sysPositionService.GetListAsync();
- var dictList = await _dictService.GetListAsync();
-
- #endregion 校验要用到的数据
-
- foreach (var item in data)
- {
- if (clearError)//如果需要清除错误
- {
- item.ErrorInfo = new Dictionary<string, string>();
- item.HasError = false;
- }
-
- #region 校验账号
-
- if (dbAccounts.Contains(item.Account))
- item.ErrorInfo.Add(nameof(item.Account), $"系统已存在账号{item.Account}");
- if (accounts.Where(u => u == item.Account).Count() > 1)
- item.ErrorInfo.Add(nameof(item.Account), "账号重复");
-
- #endregion 校验账号
-
- #region 校验手机号
-
- if (!string.IsNullOrEmpty(item.Phone))
- {
- if (dbPhones.Contains(item.Phone))
- item.ErrorInfo.Add(nameof(item.Phone), $"系统已存在手机号{item.Phone}的用户");
- if (phones.Where(u => u == item.Phone).Count() > 1)
- item.ErrorInfo.Add(nameof(item.Phone), "手机号重复");
- }
-
- #endregion 校验手机号
-
- #region 校验邮箱
-
- if (!string.IsNullOrEmpty(item.Email))
- {
- if (dbEmails.Contains(item.Email))
- item.ErrorInfo.Add(nameof(item.Email), $"系统已存在邮箱{item.Email}");
- if (emails.Where(u => u == item.Email).Count() > 1)
- item.ErrorInfo.Add(nameof(item.Email), "邮箱重复");
- }
-
- #endregion 校验邮箱
-
- #region 校验部门和职位
-
- if (!string.IsNullOrEmpty(item.OrgName))
- {
- var org = sysOrgList.Where(u => u.Names == item.OrgName).FirstOrDefault();
- if (org != null) item.OrgId = org.Id;//赋值组织Id
- else item.ErrorInfo.Add(nameof(item.OrgName), $"部门{org}不存在");
- }
- //校验职位
- if (!string.IsNullOrEmpty(item.PositionName))
- {
- if (string.IsNullOrEmpty(item.OrgName))
- item.ErrorInfo.Add(nameof(item.PositionName), "请填写部门");
- else
- {
- //根据部门ID和职位名判断是否有职位
- var position = sysPositions.FirstOrDefault(u => u.OrgId == item.OrgId && u.Name == item.PositionName);
- if (position != null) item.PositionId = position.Id;
- else item.ErrorInfo.Add(nameof(item.PositionName), $"职位{item.PositionName}不存在");
- }
- }
-
- #endregion 校验部门和职位
-
- #region 校验性别等字典
-
- var genders = await _dictService.GetValuesByDictValue(SysDictConst.GENDER, dictList);
- if (!genders.Contains(item.Gender))
- item.ErrorInfo.Add(nameof(item.Gender), "性别只能是男和女");
- if (!string.IsNullOrEmpty(item.Nation))
- {
- var nations = await _dictService.GetValuesByDictValue(SysDictConst.NATION, dictList);
- if (!nations.Contains(item.Nation))
- item.ErrorInfo.Add(nameof(item.Nation), "不存在的民族");
- }
- if (!string.IsNullOrEmpty(item.IdCardType))
- {
- var idCarTypes = await _dictService.GetValuesByDictValue(SysDictConst.ID_CARD_TYPE, dictList);
- if (!idCarTypes.Contains(item.IdCardType))
- item.ErrorInfo.Add(nameof(item.IdCardType), "证件类型错误");
- }
- if (!string.IsNullOrEmpty(item.CultureLevel))
- {
- var cultureLevels = await _dictService.GetValuesByDictValue(SysDictConst.CULTURE_LEVEL, dictList);
- if (!cultureLevels.Contains(item.CultureLevel))
- item.ErrorInfo.Add(nameof(item.CultureLevel), "文化程度有误");
- }
-
- #endregion 校验性别等字典
-
- if (item.ErrorInfo.Count > 0) item.HasError = true;//如果错误信息数量大于0则表示有错误
- }
- data = data.OrderByDescending(it => it.HasError).ToList();//排序
- return data;
- }
-
- /// <inheritdoc/>
- public async Task SetUserDefault(List<SysUser> sysUsers)
- {
- var defaultPassword = await GetDefaultPassWord(true);//默认密码
-
- //默认值赋值
- sysUsers.ForEach(user =>
- {
- user.Status = CommonStatusConst.ENABLE;//状态
- user.Phone = CryptogramUtil.Sm4Encrypt(user.Phone);//手机号
- user.Password = defaultPassword;//默认密码
- user.Avatar = AvatarUtil.GetNameImageBase64(user.Name);//默认头像
- });
- }
-
- #endregion 导入导出
-
- #region 方法
-
- /// <summary>
- /// 获取默认密码
- /// </summary>
- /// <returns></returns>
- private async Task<string> GetDefaultPassWord(bool isSm4 = false)
- {
- //获取默认密码
- var defaultPassword = (await _configService.GetByConfigKey(CateGoryConst.CONFIG_PWD_POLICY, SysConfigConst.PWD_DEFAULT_PASSWORD)).ConfigValue;
- return isSm4 ? CryptogramUtil.Sm4Encrypt(defaultPassword) : defaultPassword;//判断是否需要加密
- }
-
- /// <summary>
- /// 检查输入参数
- /// </summary>
- /// <param name="sysUser"></param>
- private async Task CheckInput(SysUser sysUser)
- {
- var sysOrgList = await _sysOrgService.GetListAsync();//获取组织列表
- var userOrg = sysOrgList.FirstOrDefault(it => it.Id == sysUser.OrgId);
- if (userOrg == null)
- throw Oops.Bah($"组织机构不存在");
- //获取多租户配置
- var isTenant = await _configService.IsTenant();
- long? tenantId = null;
- if (isTenant)
- tenantId = await _sysOrgService.GetTenantIdByOrgId(sysUser.OrgId, sysOrgList);
- //判断账号重复,直接从缓存拿
- var accountId = await GetIdByAccount(sysUser.Account, tenantId);
- if (accountId > 0 && accountId != sysUser.Id)
- throw Oops.Bah($"存在重复的账号:{sysUser.Account}");
- //如果手机号不是空
- if (!string.IsNullOrEmpty(sysUser.Phone))
- {
- if (!sysUser.Phone.MatchPhoneNumber())//验证手机格式
- throw Oops.Bah($"手机号码:{sysUser.Phone} 格式错误");
- var phoneId = await GetIdByPhone(sysUser.Phone, tenantId);
- if (phoneId > 0 && sysUser.Id != phoneId)//判断重复
- throw Oops.Bah($"存在重复的手机号:{sysUser.Phone}");
- sysUser.Phone = CryptogramUtil.Sm4Encrypt(sysUser.Phone);
- }
- //如果邮箱不是空
- if (!string.IsNullOrEmpty(sysUser.Email))
- {
- var (isMatch, match) = sysUser.Email.MatchEmail();//验证邮箱格式
- if (!isMatch)
- throw Oops.Bah($"邮箱:{sysUser.Email} 格式错误");
- if (await IsAnyAsync(it => it.Email == sysUser.Email && it.Id != sysUser.Id))
- throw Oops.Bah($"存在重复的邮箱:{sysUser.Email}");
- }
- if (sysUser.DirectorId != null)
- {
- if (sysUser.DirectorId.Value == UserManager.UserId) throw Oops.Bah($"不能设置自己为主管");
- }
- }
-
- /// <summary>
- /// 检查是否为自己
- /// </summary>
- /// <param name="id"></param>
- /// <param name="operate">操作名称</param>
- private void CheckSelf(long id, string operate)
- {
- if (id == UserManager.UserId)//如果是自己
- {
- throw Oops.Bah($"禁止{operate}自己");
- }
- }
-
- /// <summary>
- /// 根据日期计算年龄
- /// </summary>
- /// <param name="birthdate"></param>
- /// <returns></returns>
- public int GetAgeByBirthdate(DateTime birthdate)
- {
- var now = DateTime.Now;
- var age = now.Year - birthdate.Year;
- if (now.Month < birthdate.Month || now.Month == birthdate.Month && now.Day < birthdate.Day)
- {
- age--;
- }
- return age < 0 ? 0 : age;
- }
-
- /// <summary>
- /// 获取SqlSugar的ISugarQueryable
- /// </summary>
- /// <param name="input"></param>
- /// <returns></returns>
- private async Task<ISugarQueryable<SysUser>> GetQuery(UserPageInput input)
- {
- var orgIds = await _sysOrgService.GetOrgChildIds(input.OrgId);//获取下级机构
- var query = Context.Queryable<SysUser>().LeftJoin<SysOrg>((u, o) => u.OrgId == o.Id).LeftJoin<SysPosition>((u, o, p) => u.PositionId == p.Id)
- .WhereIF(input.OrgId > 0, u => orgIds.Contains(u.OrgId))//根据组织
- .WhereIF(input.Expression != null, input.Expression?.ToExpression())//动态查询
- .WhereIF(!string.IsNullOrEmpty(input.Status), u => u.Status == input.Status)//根据状态查询
- .WhereIF(!string.IsNullOrEmpty(input.SearchKey), u => u.Name.Contains(input.SearchKey) || u.Account.Contains(input.SearchKey))//根据关键字查询
- .OrderByIF(!string.IsNullOrEmpty(input.SortField), $"u.{input.SortField} {input.SortOrder}").OrderBy(u => u.Id)//排序
- .OrderBy((u, o) => u.CreateTime)//排序
- .Select((u, o, p) => new SysUser
- {
- Id = u.Id.SelectAll(),
- OrgName = o.Name,
- PositionName = p.Name,
- OrgNames = o.Names
- }).Mapper(u =>
- {
- u.Password = null;//密码清空
- u.Phone = CryptogramUtil.Sm4Decrypt(u.Phone);//手机号解密
- });
- return query;
- }
-
- /// <summary>
- /// 数据库获取用户信息
- /// </summary>
- /// <param name="userId">用户ID</param>
- /// <returns></returns>
- private async Task<SysUser> GetUserFromDb(long userId)
- {
- var sysUser = await Context.Queryable<SysUser>().LeftJoin<SysOrg>((u, o) => u.OrgId == o.Id)//连表
- .LeftJoin<SysPosition>((u, o, p) => u.PositionId == p.Id)//连表
- .Where(u => u.Id == userId)
- .Select((u, o, p) => new SysUser
- {
- Id = u.Id.SelectAll(),
- OrgName = o.Name,
- OrgNames = o.Names,
- PositionName = p.Name,
- OrgAndPosIdList = o.ParentIdList
- }).FirstAsync();
- if (sysUser != null)
- {
- sysUser.Password = CryptogramUtil.Sm4Decrypt(sysUser.Password);//解密密码
- sysUser.Phone = CryptogramUtil.Sm4Decrypt(sysUser.Phone);//解密手机号
- sysUser.OrgAndPosIdList.AddRange(sysUser.OrgId, sysUser.PositionId);//添加组织和职位Id
- if (sysUser.DirectorId != null)
- {
- sysUser.DirectorInfo = await GetUserById<UserSelectorOutPut>(sysUser.DirectorId.Value);//获取主管信息
- }
- //获取按钮码
- var buttonCodeList = await GetButtonCodeList(sysUser.Id);
- //获取数据权限
- var dataScopeList = await GetPermissionListByUserId(sysUser.Id, sysUser.OrgId);
- //获取权限码
- var permissionCodeList = dataScopeList.Select(it => it.ApiUrl).ToList();
- //获取角色码
- var roleCodeList = await _sysRoleService.GetRoleListByUserId(sysUser.Id);
- //权限码赋值
- sysUser.ButtonCodeList = buttonCodeList;
- sysUser.RoleCodeList = roleCodeList.Select(it => it.Code).ToList();
- sysUser.RoleIdList = roleCodeList.Select(it => it.Id).ToList();
- sysUser.PermissionCodeList = permissionCodeList;
- sysUser.DataScopeList = dataScopeList;
- var sysOrgList = await _sysOrgService.GetListAsync();
- var scopeOrgChildList =
- (await _sysOrgService.GetChildListById(sysUser.OrgId, true, sysOrgList)).Select(it => it.Id).ToList();//获取所属机构的下级机构Id列表
- sysUser.ScopeOrgChildList = scopeOrgChildList;
- if (await _configService.IsTenant())//如果是多租户就获取用户的租户Id
- {
- var tenantId = await _sysOrgService.GetTenantIdByOrgId(sysUser.OrgId, sysOrgList);
- sysUser.TenantId = tenantId;
- }
- var moduleIds = await _relationService.GetUserModuleId(sysUser.RoleIdList, sysUser.Id);//获取模块ID列表
- var modules = await _resourceService.GetResourcesByIds(moduleIds, CateGoryConst.RESOURCE_MODULE);//获取模块列表
- sysUser.ModuleList = modules;//模块列表赋值给用户
- //插入缓存
- _simpleCacheService.HashAdd(SystemConst.CACHE_SYS_USER_AVATAR, sysUser.Id.ToString(), sysUser.Avatar);
- sysUser.Avatar = null;//头像清空,减少CACHE_SYS_USER的大小
- _simpleCacheService.HashAdd(SystemConst.CACHE_SYS_USER, sysUser.Id.ToString(), sysUser);
- return sysUser;
- }
- return null;
- }
-
- #endregion 方法
- }
|