org.openea.eap.module.system.service.user.AdminUserServiceImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of eap-module-system-biz Show documentation
Show all versions of eap-module-system-biz Show documentation
system 模块下,我们放通用业务,支撑上层的核心业务。
例如说:用户、部门、权限、数据字典等等
The newest version!
package org.openea.eap.module.system.service.user;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import org.openea.eap.framework.common.enums.CommonStatusEnum;
import org.openea.eap.framework.common.exception.ServiceException;
import org.openea.eap.framework.common.pojo.PageResult;
import org.openea.eap.framework.common.util.collection.CollectionUtils;
import org.openea.eap.framework.common.util.object.BeanUtils;
import org.openea.eap.framework.common.util.validation.ValidationUtils;
import org.openea.eap.framework.datapermission.core.util.DataPermissionUtils;
import org.openea.eap.module.infra.api.config.ConfigApi;
import org.openea.eap.module.infra.api.file.FileApi;
import org.openea.eap.module.system.controller.admin.user.vo.profile.UserProfileUpdatePasswordReqVO;
import org.openea.eap.module.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO;
import org.openea.eap.module.system.controller.admin.user.vo.user.UserImportExcelVO;
import org.openea.eap.module.system.controller.admin.user.vo.user.UserImportRespVO;
import org.openea.eap.module.system.controller.admin.user.vo.user.UserPageReqVO;
import org.openea.eap.module.system.controller.admin.user.vo.user.UserSaveReqVO;
import org.openea.eap.module.system.dal.dataobject.dept.DeptDO;
import org.openea.eap.module.system.dal.dataobject.dept.UserPostDO;
import org.openea.eap.module.system.dal.dataobject.user.AdminUserDO;
import org.openea.eap.module.system.dal.mysql.dept.UserPostMapper;
import org.openea.eap.module.system.dal.mysql.user.AdminUserMapper;
import org.openea.eap.module.system.service.dept.DeptService;
import org.openea.eap.module.system.service.dept.PostService;
import org.openea.eap.module.system.service.permission.PermissionService;
import org.openea.eap.module.system.service.tenant.TenantService;
import com.google.common.annotations.VisibleForTesting;
import com.mzt.logapi.context.LogRecordContext;
import com.mzt.logapi.service.impl.DiffParseFunction;
import com.mzt.logapi.starter.annotation.LogRecord;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import javax.validation.ConstraintViolationException;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.util.*;
import static org.openea.eap.framework.common.exception.util.ServiceExceptionUtil.exception;
import static org.openea.eap.framework.common.util.collection.CollectionUtils.convertList;
import static org.openea.eap.framework.common.util.collection.CollectionUtils.convertSet;
import static org.openea.eap.module.system.enums.ErrorCodeConstants.*;
import static org.openea.eap.module.system.enums.LogRecordConstants.*;
/**
* 后台用户 Service 实现类
*
*/
@Service("adminUserService")
@Slf4j
public class AdminUserServiceImpl implements AdminUserService {
static final String USER_INIT_PASSWORD_KEY = "system.user.init-password";
@Resource
protected AdminUserMapper userMapper;
@Resource
private DeptService deptService;
@Resource
private PostService postService;
@Resource
private PermissionService permissionService;
@Resource
private PasswordEncoder passwordEncoder;
@Resource
@Lazy // 延迟,避免循环依赖报错
private TenantService tenantService;
@Resource
private UserPostMapper userPostMapper;
@Resource
private FileApi fileApi;
@Resource
private ConfigApi configApi;
@Override
@Transactional(rollbackFor = Exception.class)
@LogRecord(type = SYSTEM_USER_TYPE, subType = SYSTEM_USER_CREATE_SUB_TYPE, bizNo = "{{#user.id}}",
success = SYSTEM_USER_CREATE_SUCCESS)
public Long createUser(UserSaveReqVO createReqVO) {
// 1.1 校验账户配合
tenantService.handleTenantInfo(tenant -> {
long count = userMapper.selectCount();
if (count >= tenant.getAccountCount()) {
throw exception(USER_COUNT_MAX, tenant.getAccountCount());
}
});
// 1.2 校验正确性
validateUserForCreateOrUpdate(null, createReqVO.getUsername(),
createReqVO.getMobile(), createReqVO.getEmail(), createReqVO.getDeptId(), createReqVO.getPostIds());
// 2.1 插入用户
AdminUserDO user = BeanUtils.toBean(createReqVO, AdminUserDO.class);
user.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 默认开启
user.setPassword(encodePassword(createReqVO.getPassword())); // 加密密码
userMapper.insert(user);
// 2.2 插入关联岗位
if (CollectionUtil.isNotEmpty(user.getPostIds())) {
userPostMapper.insertBatch(convertList(user.getPostIds(),
postId -> new UserPostDO().setUserId(user.getId()).setPostId(postId)));
}
// 3. 记录操作日志上下文
LogRecordContext.putVariable("user", user);
return user.getId();
}
@Override
@Transactional(rollbackFor = Exception.class)
@LogRecord(type = SYSTEM_USER_TYPE, subType = SYSTEM_USER_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}",
success = SYSTEM_USER_UPDATE_SUCCESS)
public void updateUser(UserSaveReqVO updateReqVO) {
updateReqVO.setPassword(null); // 特殊:此处不更新密码
// 1. 校验正确性
AdminUserDO oldUser = validateUserForCreateOrUpdate(updateReqVO.getId(), updateReqVO.getUsername(),
updateReqVO.getMobile(), updateReqVO.getEmail(), updateReqVO.getDeptId(), updateReqVO.getPostIds());
// 2.1 更新用户
AdminUserDO updateObj = BeanUtils.toBean(updateReqVO, AdminUserDO.class);
userMapper.updateById(updateObj);
// 2.2 更新岗位
updateUserPost(updateReqVO, updateObj);
// 3. 记录操作日志上下文
LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldUser, UserSaveReqVO.class));
LogRecordContext.putVariable("user", oldUser);
}
private void updateUserPost(UserSaveReqVO reqVO, AdminUserDO updateObj) {
Long userId = reqVO.getId();
Set dbPostIds = convertSet(userPostMapper.selectListByUserId(userId), UserPostDO::getPostId);
// 计算新增和删除的岗位编号
Set postIds = CollUtil.emptyIfNull(updateObj.getPostIds());
Collection createPostIds = CollUtil.subtract(postIds, dbPostIds);
Collection deletePostIds = CollUtil.subtract(dbPostIds, postIds);
// 执行新增和删除。对于已经授权的岗位,不用做任何处理
if (!CollectionUtil.isEmpty(createPostIds)) {
userPostMapper.insertBatch(convertList(createPostIds,
postId -> new UserPostDO().setUserId(userId).setPostId(postId)));
}
if (!CollectionUtil.isEmpty(deletePostIds)) {
userPostMapper.deleteByUserIdAndPostId(userId, deletePostIds);
}
}
@Override
public void updateUserLogin(Long id, String loginIp) {
userMapper.updateById(new AdminUserDO().setId(id).setLoginIp(loginIp).setLoginDate(LocalDateTime.now()));
}
@Override
public void updateUserProfile(Long id, UserProfileUpdateReqVO reqVO) {
// 校验正确性
validateUserExists(id);
validateEmailUnique(id, reqVO.getEmail());
validateMobileUnique(id, reqVO.getMobile());
// 执行更新
userMapper.updateById(BeanUtils.toBean(reqVO, AdminUserDO.class).setId(id));
}
@Override
public void updateUserPassword(Long id, UserProfileUpdatePasswordReqVO reqVO) {
// 校验旧密码密码
validateOldPassword(id, reqVO.getOldPassword());
// 执行更新
AdminUserDO updateObj = new AdminUserDO().setId(id);
updateObj.setPassword(encodePassword(reqVO.getNewPassword())); // 加密密码
userMapper.updateById(updateObj);
}
@Override
public String updateUserAvatar(Long id, InputStream avatarFile) {
validateUserExists(id);
// 存储文件
String avatar = fileApi.createFile(IoUtil.readBytes(avatarFile));
// 更新路径
AdminUserDO sysUserDO = new AdminUserDO();
sysUserDO.setId(id);
sysUserDO.setAvatar(avatar);
userMapper.updateById(sysUserDO);
return avatar;
}
@Override
@LogRecord(type = SYSTEM_USER_TYPE, subType = SYSTEM_USER_UPDATE_PASSWORD_SUB_TYPE, bizNo = "{{#id}}",
success = SYSTEM_USER_UPDATE_PASSWORD_SUCCESS)
public void updateUserPassword(Long id, String password) {
// 1. 校验用户存在
AdminUserDO user = validateUserExists(id);
// 2. 更新密码
AdminUserDO updateObj = new AdminUserDO();
updateObj.setId(id);
updateObj.setPassword(encodePassword(password)); // 加密密码
userMapper.updateById(updateObj);
// 3. 记录操作日志上下文
LogRecordContext.putVariable("user", user);
LogRecordContext.putVariable("newPassword", updateObj.getPassword());
}
@Override
public void updateUserStatus(Long id, Integer status) {
// 校验用户存在
validateUserExists(id);
// 更新状态
AdminUserDO updateObj = new AdminUserDO();
updateObj.setId(id);
updateObj.setStatus(status);
userMapper.updateById(updateObj);
}
@Override
@Transactional(rollbackFor = Exception.class)
@LogRecord(type = SYSTEM_USER_TYPE, subType = SYSTEM_USER_DELETE_SUB_TYPE, bizNo = "{{#id}}",
success = SYSTEM_USER_DELETE_SUCCESS)
public void deleteUser(Long id) {
// 1. 校验用户存在
AdminUserDO user = validateUserExists(id);
// 2.1 删除用户
userMapper.deleteById(id);
// 2.2 删除用户关联数据
permissionService.processUserDeleted(id);
// 2.2 删除用户岗位
userPostMapper.deleteByUserId(id);
// 3. 记录操作日志上下文
LogRecordContext.putVariable("user", user);
}
@Override
public AdminUserDO getUserByUsername(String username) {
return userMapper.selectByUsername(username);
}
@Override
public AdminUserDO getUserByMobile(String mobile) {
return userMapper.selectByMobile(mobile);
}
@Override
public PageResult getUserPage(UserPageReqVO reqVO) {
return userMapper.selectPage(reqVO, getDeptCondition(reqVO.getDeptId()));
}
@Override
public AdminUserDO getUser(Long id) {
return userMapper.selectById(id);
}
@Override
public List getUserListByDeptIds(Collection deptIds) {
if (CollUtil.isEmpty(deptIds)) {
return Collections.emptyList();
}
return userMapper.selectListByDeptIds(deptIds);
}
@Override
public List getUserListByPostIds(Collection postIds) {
if (CollUtil.isEmpty(postIds)) {
return Collections.emptyList();
}
Set userIds = convertSet(userPostMapper.selectListByPostIds(postIds), UserPostDO::getUserId);
if (CollUtil.isEmpty(userIds)) {
return Collections.emptyList();
}
return userMapper.selectBatchIds(userIds);
}
@Override
public List getUserList(Collection ids) {
if (CollUtil.isEmpty(ids)) {
return Collections.emptyList();
}
return userMapper.selectBatchIds(ids);
}
@Override
public void validateUserList(Collection ids) {
if (CollUtil.isEmpty(ids)) {
return;
}
// 获得岗位信息
List users = userMapper.selectBatchIds(ids);
Map userMap = CollectionUtils.convertMap(users, AdminUserDO::getId);
// 校验
ids.forEach(id -> {
AdminUserDO user = userMap.get(id);
if (user == null) {
throw exception(USER_NOT_EXISTS);
}
if (!CommonStatusEnum.ENABLE.getStatus().equals(user.getStatus())) {
throw exception(USER_IS_DISABLE, user.getNickname());
}
});
}
@Override
public List getUserListByNickname(String nickname) {
return userMapper.selectListByNickname(nickname);
}
/**
* 获得部门条件:查询指定部门的子部门编号们,包括自身
* @param deptId 部门编号
* @return 部门编号集合
*/
private Set getDeptCondition(Long deptId) {
if (deptId == null) {
return Collections.emptySet();
}
Set deptIds = convertSet(deptService.getChildDeptList(deptId), DeptDO::getId);
deptIds.add(deptId); // 包括自身
return deptIds;
}
private AdminUserDO validateUserForCreateOrUpdate(Long id, String username, String mobile, String email,
Long deptId, Set postIds) {
// 关闭数据权限,避免因为没有数据权限,查询不到数据,进而导致唯一校验不正确
return DataPermissionUtils.executeIgnore(() -> {
// 校验用户存在
AdminUserDO user = validateUserExists(id);
// 校验用户名唯一
validateUsernameUnique(id, username);
// 校验手机号唯一
validateMobileUnique(id, mobile);
// 校验邮箱唯一
validateEmailUnique(id, email);
// 校验部门处于开启状态
deptService.validateDeptList(CollectionUtils.singleton(deptId));
// 校验岗位处于开启状态
postService.validatePostList(postIds);
return user;
});
}
@VisibleForTesting
AdminUserDO validateUserExists(Long id) {
if (id == null) {
return null;
}
AdminUserDO user = userMapper.selectById(id);
if (user == null) {
throw exception(USER_NOT_EXISTS);
}
return user;
}
@VisibleForTesting
void validateUsernameUnique(Long id, String username) {
if (StrUtil.isBlank(username)) {
return;
}
AdminUserDO user = userMapper.selectByUsername(username);
if (user == null) {
return;
}
// 如果 id 为空,说明不用比较是否为相同 id 的用户
if (id == null) {
throw exception(USER_USERNAME_EXISTS);
}
if (!user.getId().equals(id)) {
throw exception(USER_USERNAME_EXISTS);
}
}
@VisibleForTesting
void validateEmailUnique(Long id, String email) {
if (StrUtil.isBlank(email)) {
return;
}
AdminUserDO user = userMapper.selectByEmail(email);
if (user == null) {
return;
}
// 如果 id 为空,说明不用比较是否为相同 id 的用户
if (id == null) {
throw exception(USER_EMAIL_EXISTS);
}
if (!user.getId().equals(id)) {
throw exception(USER_EMAIL_EXISTS);
}
}
@VisibleForTesting
void validateMobileUnique(Long id, String mobile) {
if (StrUtil.isBlank(mobile)) {
return;
}
AdminUserDO user = userMapper.selectByMobile(mobile);
if (user == null) {
return;
}
// 如果 id 为空,说明不用比较是否为相同 id 的用户
if (id == null) {
throw exception(USER_MOBILE_EXISTS);
}
if (!user.getId().equals(id)) {
throw exception(USER_MOBILE_EXISTS);
}
}
/**
* 校验旧密码
* @param id 用户 id
* @param oldPassword 旧密码
*/
@VisibleForTesting
void validateOldPassword(Long id, String oldPassword) {
AdminUserDO user = userMapper.selectById(id);
if (user == null) {
throw exception(USER_NOT_EXISTS);
}
if (!isPasswordMatch(oldPassword, user.getPassword())) {
throw exception(USER_PASSWORD_FAILED);
}
}
@Override
@Transactional(rollbackFor = Exception.class) // 添加事务,异常则回滚所有导入
public UserImportRespVO importUserList(List importUsers, boolean isUpdateSupport) {
// 1.1 参数校验
if (CollUtil.isEmpty(importUsers)) {
throw exception(USER_IMPORT_LIST_IS_EMPTY);
}
// 1.2 初始化密码不能为空
String initPassword = configApi.getConfigValueByKey(USER_INIT_PASSWORD_KEY).getCheckedData();
if (StrUtil.isEmpty(initPassword)) {
throw exception(USER_IMPORT_INIT_PASSWORD);
}
// 2. 遍历,逐个创建 or 更新
UserImportRespVO respVO = UserImportRespVO.builder().createUsernames(new ArrayList<>())
.updateUsernames(new ArrayList<>()).failureUsernames(new LinkedHashMap<>()).build();
importUsers.forEach(importUser -> {
// 2.1.1 校验字段是否符合要求
try {
ValidationUtils.validate(BeanUtils.toBean(importUser, UserSaveReqVO.class).setPassword(initPassword));
} catch (ConstraintViolationException ex){
respVO.getFailureUsernames().put(importUser.getUsername(), ex.getMessage());
return;
}
// 2.1.2 校验,判断是否有不符合的原因
try {
validateUserForCreateOrUpdate(null, null, importUser.getMobile(), importUser.getEmail(),
importUser.getDeptId(), null);
} catch (ServiceException ex) {
respVO.getFailureUsernames().put(importUser.getUsername(), ex.getMessage());
return;
}
// 2.2.1 判断如果不存在,在进行插入
AdminUserDO existUser = userMapper.selectByUsername(importUser.getUsername());
if (existUser == null) {
userMapper.insert(BeanUtils.toBean(importUser, AdminUserDO.class)
.setPassword(encodePassword(initPassword)).setPostIds(new HashSet<>())); // 设置默认密码及空岗位编号数组
respVO.getCreateUsernames().add(importUser.getUsername());
return;
}
// 2.2.2 如果存在,判断是否允许更新
if (!isUpdateSupport) {
respVO.getFailureUsernames().put(importUser.getUsername(), USER_USERNAME_EXISTS.getMsg());
return;
}
AdminUserDO updateUser = BeanUtils.toBean(importUser, AdminUserDO.class);
updateUser.setId(existUser.getId());
userMapper.updateById(updateUser);
respVO.getUpdateUsernames().add(importUser.getUsername());
});
return respVO;
}
@Override
public List getUserListByStatus(Integer status) {
return userMapper.selectListByStatus(status);
}
@Override
public boolean isPasswordMatch(String rawPassword, String encodedPassword) {
return passwordEncoder.matches(rawPassword, encodedPassword);
}
/**
* 对密码进行加密
*
* @param password 密码
* @return 加密后的密码
*/
private String encodePassword(String password) {
return passwordEncoder.encode(password);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy