| | |
| | | import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; |
| | | import cn.iocoder.yudao.module.system.dal.mysql.dept.UserPostMapper; |
| | | import cn.iocoder.yudao.module.system.dal.mysql.user.AdminUserMapper; |
| | | import cn.iocoder.yudao.module.system.mq.producer.user.AdminUserProducer; |
| | | import cn.iocoder.yudao.module.system.service.dept.DeptService; |
| | | import cn.iocoder.yudao.module.system.service.dept.PostService; |
| | | import cn.iocoder.yudao.module.system.service.oauth2.OAuth2TokenService; |
| | |
| | | /** |
| | | * 后台用户 Service 实现类 |
| | | * |
| | | * @author 芋道源码 |
| | | * @author 超级管理员 |
| | | */ |
| | | @Service("adminUserService") |
| | | @Slf4j |
| | |
| | | @Resource |
| | | private ConfigApi configApi; |
| | | |
| | | @Resource |
| | | private AdminUserProducer adminUserProducer; |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | @LogRecord(type = SYSTEM_USER_TYPE, subType = SYSTEM_USER_CREATE_SUB_TYPE, bizNo = "{{#user.id}}", |
| | |
| | | if (CollectionUtil.isNotEmpty(user.getPostIds())) { |
| | | userPostMapper.insertBatch(convertList(user.getPostIds(), |
| | | postId -> new UserPostDO().setUserId(user.getId()).setPostId(postId))); |
| | | } |
| | | // 2.3 分配用户角色 |
| | | if (CollUtil.isNotEmpty(createReqVO.getRoleIds())) { |
| | | permissionService.assignUserRole(user.getId(), createReqVO.getRoleIds()); |
| | | } |
| | | |
| | | // 3. 记录操作日志上下文 |
| | |
| | | userMapper.updateById(updateObj); |
| | | // 2.2 更新岗位 |
| | | updateUserPost(updateReqVO, updateObj); |
| | | // 2.3 昵称 / 头像变化时,发送消息供下游订阅(如 IM 模块推 FRIEND_INFO_UPDATED) |
| | | publishUserProfileUpdatedIfChanged(oldUser, updateReqVO.getNickname(), updateReqVO.getAvatar()); |
| | | |
| | | // 3. 记录操作日志上下文 |
| | | LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldUser, UserSaveReqVO.class)); |
| | |
| | | |
| | | @Override |
| | | public void updateUserProfile(Long id, UserProfileUpdateReqVO reqVO) { |
| | | // 校验正确性 |
| | | validateUserExists(id); |
| | | // 1. 校验正确性 |
| | | AdminUserDO oldUser = validateUserExists(id); |
| | | validateEmailUnique(id, reqVO.getEmail()); |
| | | validateMobileUnique(id, reqVO.getMobile()); |
| | | // 执行更新 |
| | | |
| | | // 2. 执行更新 |
| | | userMapper.updateById(BeanUtils.toBean(reqVO, AdminUserDO.class).setId(id)); |
| | | |
| | | // 3. 昵称 / 头像变化时,发送消息供下游订阅(如 IM 模块推 FRIEND_INFO_UPDATED) |
| | | publishUserProfileUpdatedIfChanged(oldUser, reqVO.getNickname(), reqVO.getAvatar()); |
| | | } |
| | | |
| | | /** |
| | | * 仅当 nickname 或 avatar 跟旧值不一致时,发送 AdminUserProfileUpdateMessage |
| | | */ |
| | | private void publishUserProfileUpdatedIfChanged(AdminUserDO oldUser, String newNickname, String newAvatar) { |
| | | boolean nicknameChanged = newNickname != null && !ObjUtil.equal(oldUser.getNickname(), newNickname); |
| | | boolean avatarChanged = newAvatar != null && !ObjUtil.equal(oldUser.getAvatar(), newAvatar); |
| | | if (!nicknameChanged && !avatarChanged) { |
| | | return; |
| | | } |
| | | adminUserProducer.sendUserProfileUpdateMessage(oldUser.getId(), |
| | | nicknameChanged ? newNickname : null, |
| | | avatarChanged ? newAvatar : null); |
| | | } |
| | | |
| | | @Override |
| | |
| | | } |
| | | return userMapper.selectByIds(ids); |
| | | } |
| | | |
| | | public List<AdminUserDO> getUserListAll() { |
| | | return userMapper.selectList(); |
| | | } |
| | | |
| | | |
| | | @Override |
| | | public void validateUserList(Collection<Long> ids) { |
| | |
| | | if (CollUtil.isEmpty(importUsers)) { |
| | | throw exception(USER_IMPORT_LIST_IS_EMPTY); |
| | | } |
| | | // 1.2 初始化密码不能为空 |
| | | // 1.2 系统参数中的初始密码,作为 Excel 未填写密码时的兜底 |
| | | String initPassword = configApi.getConfigValueByKey(USER_INIT_PASSWORD_KEY); |
| | | if (StrUtil.isEmpty(initPassword)) { |
| | | throw exception(USER_IMPORT_INIT_PASSWORD); |
| | | } |
| | | |
| | | // 2. 遍历,逐个创建 or 更新 |
| | | UserImportRespVO respVO = UserImportRespVO.builder().createUsernames(new ArrayList<>()) |
| | |
| | | AtomicInteger index = new AtomicInteger(1); |
| | | importUsers.forEach(importUser -> { |
| | | int currentIndex = index.getAndIncrement(); |
| | | String key = StrUtil.blankToDefault(importUser.getUsername(), "第 " + currentIndex + " 行"); |
| | | // 2.1.0 解析该行初始密码:Excel 填写了就用填写的,否则读取系统参数 |
| | | String effectivePassword = StrUtil.isNotBlank(importUser.getPassword()) |
| | | ? importUser.getPassword() : initPassword; |
| | | if (StrUtil.isBlank(effectivePassword)) { |
| | | respVO.getFailureUsernames().put(key, |
| | | "未填写初始密码,且系统参数 system.user.init-password 未配置。" |
| | | + "请在 Excel 中填写该行初始密码,或先在参数设置中配置 system.user.init-password"); |
| | | return; |
| | | } |
| | | // 2.1.1 校验字段是否符合要求 |
| | | try { |
| | | ValidationUtils.validate(BeanUtils.toBean(importUser, UserSaveReqVO.class).setPassword(initPassword)); |
| | | ValidationUtils.validate(BeanUtils.toBean(importUser, UserSaveReqVO.class).setPassword(effectivePassword)); |
| | | } catch (ConstraintViolationException ex) { |
| | | String key = StrUtil.blankToDefault(importUser.getUsername(), "第 " + currentIndex + " 行"); |
| | | respVO.getFailureUsernames().put(key, ex.getMessage()); |
| | | return; |
| | | } |
| | |
| | | AdminUserDO existUser = userMapper.selectByUsername(importUser.getUsername()); |
| | | if (existUser == null) { |
| | | userMapper.insert(BeanUtils.toBean(importUser, AdminUserDO.class) |
| | | .setPassword(encodePassword(initPassword)).setPostIds(new HashSet<>())); // 设置默认密码及空岗位编号数组 |
| | | .setPassword(encodePassword(effectivePassword)).setPostIds(new HashSet<>())); // 设置初始密码及空岗位编号数组 |
| | | respVO.getCreateUsernames().add(importUser.getUsername()); |
| | | return; |
| | | } |
| | |
| | | } |
| | | AdminUserDO updateUser = BeanUtils.toBean(importUser, AdminUserDO.class); |
| | | updateUser.setId(existUser.getId()); |
| | | // 密码单独处理:Excel 填写了才更新;未填写则置空,保持原密码不变(避免把明文写进库) |
| | | updateUser.setPassword(StrUtil.isNotBlank(importUser.getPassword()) |
| | | ? encodePassword(importUser.getPassword()) : null); |
| | | userMapper.updateById(updateUser); |
| | | respVO.getUpdateUsernames().add(importUser.getUsername()); |
| | | }); |
| | |
| | | } |
| | | |
| | | @Override |
| | | public List<AdminUserDO> getDeptUsers(Collection<Long> deptIds) { |
| | | return userMapper.selectListByDeptIds(deptIds); |
| | | } |
| | | |
| | | @Override |
| | | public boolean isPasswordMatch(String rawPassword, String encodedPassword) { |
| | | return passwordEncoder.matches(rawPassword, encodedPassword); |
| | | } |