package cn.exrick.xboot.base.controller.manage; import cn.exrick.xboot.base.async.AddMessage; import cn.exrick.xboot.core.common.annotation.SystemLog; import cn.exrick.xboot.core.common.constant.CommonConstant; import cn.exrick.xboot.core.common.enums.LogType; import cn.exrick.xboot.core.common.exception.XbootException; import cn.exrick.xboot.core.common.redis.RedisTemplateHelper; import cn.exrick.xboot.core.common.utils.PageUtil; import cn.exrick.xboot.core.common.utils.ResultUtil; import cn.exrick.xboot.core.common.utils.SecurityUtil; import cn.exrick.xboot.core.common.utils.StopWordsUtil; import cn.exrick.xboot.core.common.vo.PageVo; import cn.exrick.xboot.core.common.vo.Result; import cn.exrick.xboot.core.common.vo.SearchVo; import cn.exrick.xboot.core.config.security.SecurityUserDetails; import cn.exrick.xboot.core.dao.mapper.DeleteMapper; import cn.exrick.xboot.core.entity.Department; import cn.exrick.xboot.core.entity.Role; import cn.exrick.xboot.core.entity.User; import cn.exrick.xboot.core.entity.UserRole; import cn.exrick.xboot.core.service.*; import cn.exrick.xboot.core.service.mybatis.IUserRoleService; import cn.exrick.xboot.core.vo.RoleDTO; import cn.hutool.core.util.StrUtil; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.CacheConfig; import org.springframework.cache.annotation.CacheEvict; import org.springframework.data.domain.Page; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.validation.Valid; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; /** * @author Exrickx */ @Slf4j @RestController @Api(tags = "用户接口") @RequestMapping("/xboot/user") @CacheConfig(cacheNames = "user") @Transactional public class UserController { public static final String USER = "user::"; @Autowired private UserService userService; @Autowired private RoleService roleService; @Autowired private DepartmentService departmentService; @Autowired private DepartmentHeaderService departmentHeaderService; @Autowired private IUserRoleService iUserRoleService; @Autowired private UserRoleService userRoleService; @Autowired private AddMessage addMessage; @Autowired private DeleteMapper deleteMapper; @Autowired private RedisTemplateHelper redisTemplate; @Autowired private SecurityUtil securityUtil; @PersistenceContext private EntityManager entityManager; @RequestMapping(value = "/smsLogin", method = RequestMethod.POST) @SystemLog(description = "短信登录", type = LogType.LOGIN) @ApiOperation(value = "短信登录接口") public Result smsLogin(@RequestParam String mobile, @RequestParam(required = false) Boolean saveLogin) { User u = userService.findByMobile(mobile); if (u == null) { throw new XbootException("手机号不存在"); } String accessToken = securityUtil.getToken(u.getUsername(), saveLogin); // 记录日志使用 UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(new SecurityUserDetails(u), null, null); SecurityContextHolder.getContext().setAuthentication(authentication); return ResultUtil.data(accessToken); } @RequestMapping(value = "/resetByMobile", method = RequestMethod.POST) @ApiOperation(value = "通过短信重置密码") public Result resetByMobile(@RequestParam String mobile, @RequestParam String password, @RequestParam String passStrength) { User u = userService.findByMobile(mobile); String encryptPass = new BCryptPasswordEncoder().encode(password); u.setPassword(encryptPass).setPassStrength(passStrength); userService.update(u); // 删除缓存 redisTemplate.delete(USER + u.getUsername()); return ResultUtil.success("重置密码成功"); } @RequestMapping(value = "/regist", method = RequestMethod.POST) @ApiOperation(value = "注册用户") public Result regist(@Valid User u) { // 校验是否已存在 checkUserInfo(u.getUsername(), u.getMobile(), u.getEmail()); String encryptPass = new BCryptPasswordEncoder().encode(u.getPassword()); u.setPassword(encryptPass).setType(CommonConstant.USER_TYPE_NORMAL); User user = userService.save(u); // 默认角色 List roleList = roleService.findByDefaultRole(true); if (roleList != null && roleList.size() > 0) { for (Role role : roleList) { UserRole ur = new UserRole().setUserId(user.getId()).setRoleId(role.getId()); userRoleService.save(ur); } } // 异步发送创建账号消息 addMessage.addSendMessage(user.getId()); return ResultUtil.data(user); } @RequestMapping(value = "/info", method = RequestMethod.GET) @ApiOperation(value = "获取当前登录用户接口") public Result getUserInfo() { User u = securityUtil.getCurrUser(); // 清除持久上下文环境 避免后面语句导致持久化 entityManager.clear(); u.setPassword(null); return new ResultUtil().setData(u); } @RequestMapping(value = "/changeMobile", method = RequestMethod.POST) @ApiOperation(value = "修改绑定手机") public Result changeMobile(@RequestParam String mobile) { User u = securityUtil.getCurrUser(); u.setMobile(mobile); userService.update(u); // 删除缓存 redisTemplate.delete(USER + u.getUsername()); return ResultUtil.success("修改手机号成功"); } @RequestMapping(value = "/unlock", method = RequestMethod.POST) @ApiOperation(value = "解锁验证密码") public Result unLock(@RequestParam String password) { User u = securityUtil.getCurrUser(); if (!new BCryptPasswordEncoder().matches(password, u.getPassword())) { return ResultUtil.error("密码不正确"); } return ResultUtil.data(null); } @RequestMapping(value = "/resetPass", method = RequestMethod.POST) @ApiOperation(value = "重置密码") public Result resetPass(@RequestParam String[] ids) { for (String id : ids) { User u = userService.get(id); // 在线DEMO所需 if ("test".equals(u.getUsername()) || "test2".equals(u.getUsername()) || "admin".equals(u.getUsername())) { throw new XbootException("测试账号及管理员账号不得重置"); } u.setPassword(new BCryptPasswordEncoder().encode("123456")); userService.update(u); redisTemplate.delete(USER + u.getUsername()); } return ResultUtil.success("操作成功"); } @RequestMapping(value = "/edit", method = RequestMethod.POST) @ApiOperation(value = "修改用户自己资料", notes = "用户名密码等不会修改 需要username更新缓存") @CacheEvict(key = "#u.username") public Result editOwn(User u) { User old = securityUtil.getCurrUser(); // 不能修改的字段 u.setUsername(old.getUsername()).setPassword(old.getPassword()).setType(old.getType()).setStatus(old.getStatus()); if (StrUtil.isBlank(u.getDepartmentId())) { u.setDepartmentId(null); } userService.update(u); return ResultUtil.success("修改成功"); } /** * 线上demo不允许测试账号改密码 * @param password * @param newPass * @return */ @RequestMapping(value = "/modifyPass", method = RequestMethod.POST) @ApiOperation(value = "修改密码") public Result modifyPass(@ApiParam("旧密码") @RequestParam String password, @ApiParam("新密码") @RequestParam String newPass, @ApiParam("密码强度") @RequestParam String passStrength) { User user = securityUtil.getCurrUser(); // 在线DEMO所需 if ("test".equals(user.getUsername()) || "test2".equals(user.getUsername())) { return ResultUtil.error("演示账号不支持修改密码"); } if (!new BCryptPasswordEncoder().matches(password, user.getPassword())) { return ResultUtil.error("旧密码不正确"); } String newEncryptPass = new BCryptPasswordEncoder().encode(newPass); user.setPassword(newEncryptPass); user.setPassStrength(passStrength); userService.update(user); // 手动更新缓存 redisTemplate.delete(USER + user.getUsername()); return ResultUtil.success("修改密码成功"); } @RequestMapping(value = "/getByCondition", method = RequestMethod.GET) @ApiOperation(value = "多条件分页获取用户列表") public Result> getByCondition(User user, SearchVo searchVo, PageVo pageVo) { Page page = userService.findByCondition(user, searchVo, PageUtil.initPage(pageVo)); for (User u : page.getContent()) { // 关联角色 List list = iUserRoleService.findByUserId(u.getId()); List roleDTOList = list.stream().map(e -> { return new RoleDTO().setId(e.getId()).setName(e.getName()).setDescription(e.getDescription()); }).collect(Collectors.toList()); u.setRoles(roleDTOList); // 游离态 避免后面语句导致持久化 entityManager.detach(u); u.setPassword(null); } return new ResultUtil>().setData(page); } @RequestMapping(value = "/getByDepartmentId/{departmentId}", method = RequestMethod.GET) @ApiOperation(value = "多条件分页获取用户列表") public Result> getByCondition(@PathVariable String departmentId) { List list = userService.findByDepartmentId(departmentId); entityManager.clear(); list.forEach(u -> { u.setPassword(null); }); return new ResultUtil>().setData(list); } @RequestMapping(value = "/searchByName/{username}", method = RequestMethod.GET) @ApiOperation(value = "通过用户名搜索用户") public Result> searchByName(@PathVariable String username) throws UnsupportedEncodingException { List list = userService.findByUsernameLikeAndStatus(URLDecoder.decode(username, "utf-8"), CommonConstant.STATUS_NORMAL); entityManager.clear(); list.forEach(u -> { u.setPassword(null); }); return new ResultUtil>().setData(list); } @RequestMapping(value = "/getAll", method = RequestMethod.GET) @ApiOperation(value = "获取全部用户数据") public Result> getAll() { List list = userService.getAll(); // 清除持久上下文环境 避免后面语句导致持久化 entityManager.clear(); for (User u : list) { u.setPassword(null); } return new ResultUtil>().setData(list); } @RequestMapping(value = "/admin/add", method = RequestMethod.POST) @ApiOperation(value = "添加用户") public Result add(@Valid User u, @RequestParam(required = false) String[] roleIds) { // 校验是否已存在 checkUserInfo(u.getUsername(), u.getMobile(), u.getEmail()); u.setDescription(u.getPassword()); String encryptPass = new BCryptPasswordEncoder().encode(u.getPassword()); u.setPassword(encryptPass); if (StrUtil.isNotBlank(u.getDepartmentId())) { Department d = departmentService.get(u.getDepartmentId()); if (d != null) { u.setDepartmentTitle(d.getTitle()); } } else { u.setDepartmentId(null); u.setDepartmentTitle(""); } User user = userService.save(u); if (roleIds != null) { // 添加角色 List userRoles = Arrays.asList(roleIds).stream().map(e -> { return new UserRole().setUserId(u.getId()).setRoleId(e); }).collect(Collectors.toList()); userRoleService.saveOrUpdateAll(userRoles); } // 发送创建账号消息 addMessage.addSendMessage(user.getId()); return ResultUtil.success("添加成功"); } @RequestMapping(value = "/admin/edit", method = RequestMethod.POST) @ApiOperation(value = "管理员修改资料", notes = "需要通过id获取原用户信息 需要username更新缓存") @CacheEvict(key = "#u.username") public Result edit(User u, @RequestParam(required = false) String[] roleIds) { User old = userService.get(u.getId()); u.setUsername(old.getUsername()); // 若修改了手机和邮箱判断是否唯一 if (!old.getMobile().equals(u.getMobile()) && userService.findByMobile(u.getMobile()) != null) { return ResultUtil.error("该手机号已绑定其他账户"); } if (!old.getEmail().equals(u.getEmail()) && userService.findByEmail(u.getEmail()) != null) { return ResultUtil.error("该邮箱已绑定其他账户"); } if (StrUtil.isNotBlank(u.getDepartmentId())) { Department d = departmentService.get(u.getDepartmentId()); if (d != null) { u.setDepartmentTitle(d.getTitle()); } } else { u.setDepartmentId(null); u.setDepartmentTitle(""); } u.setPassword(old.getPassword()); userService.update(u); // 删除该用户角色 userRoleService.deleteByUserId(u.getId()); if (roleIds != null) { // 新角色 List userRoles = Arrays.asList(roleIds).stream().map(e -> { return new UserRole().setRoleId(e).setUserId(u.getId()); }).collect(Collectors.toList()); userRoleService.saveOrUpdateAll(userRoles); } // 手动删除缓存 redisTemplate.delete("userRole::" + u.getId()); redisTemplate.delete("userRole::depIds:" + u.getId()); redisTemplate.delete("permission::userMenuList:" + u.getId()); return ResultUtil.success("修改成功"); } @RequestMapping(value = "/admin/disable/{userId}", method = RequestMethod.POST) @ApiOperation(value = "后台禁用用户") public Result disable(@ApiParam("用户唯一id标识") @PathVariable String userId) { User user = userService.get(userId); user.setStatus(CommonConstant.USER_STATUS_LOCK); userService.update(user); // 手动更新缓存 redisTemplate.delete(USER + user.getUsername()); return ResultUtil.success("操作成功"); } @RequestMapping(value = "/admin/enable/{userId}", method = RequestMethod.POST) @ApiOperation(value = "后台启用用户") public Result enable(@ApiParam("用户唯一id标识") @PathVariable String userId) { User user = userService.get(userId); user.setStatus(CommonConstant.USER_STATUS_NORMAL); userService.update(user); // 手动更新缓存 redisTemplate.delete(USER + user.getUsername()); return ResultUtil.success("操作成功"); } @RequestMapping(value = "/delByIds", method = RequestMethod.POST) @ApiOperation(value = "批量通过ids删除") public Result delAllByIds(@RequestParam String[] ids) { for (String id : ids) { User u = userService.get(id); // 删除相关缓存 redisTemplate.delete(USER + u.getUsername()); redisTemplate.delete("userRole::" + u.getId()); redisTemplate.delete("userRole::depIds:" + u.getId()); redisTemplate.delete("permission::userMenuList:" + u.getId()); redisTemplate.deleteByPattern("department::*"); userService.delete(id); // 删除关联角色 userRoleService.deleteByUserId(id); // 删除关联部门负责人 departmentHeaderService.deleteByUserId(id); // 删除关联流程、社交账号数据 try { deleteMapper.deleteActNode(u.getId()); deleteMapper.deleteActStarter(u.getId()); deleteMapper.deleteSocial(u.getUsername()); } catch (Exception e) { log.warn(e.toString()); } } return ResultUtil.success("批量通过id删除数据成功"); } @RequestMapping(value = "/importData", method = RequestMethod.POST) @ApiOperation(value = "导入用户数据") public Result importData(@RequestBody List users) { List errors = new ArrayList<>(); List reasons = new ArrayList<>(); int count = 0; for (User u : users) { count++; // 验证用户名、密码、手机、邮箱不为空 if (StrUtil.isBlank(u.getUsername()) || StrUtil.isBlank(u.getPassword()) || StrUtil.isBlank(u.getMobile()) || StrUtil.isBlank(u.getEmail())) { errors.add(count); reasons.add("用户名、密码、手机、邮箱不能为空"); continue; } // 验证用户名、手机、邮箱唯一 if (userService.findByUsername(u.getUsername()) != null || userService.findByMobile(u.getMobile()) != null || userService.findByEmail(u.getEmail()) != null) { errors.add(count); reasons.add("用户名、手机、邮箱已存在"); continue; } // 加密密码 u.setPassword(new BCryptPasswordEncoder().encode(u.getPassword())); // 验证部门id正确性 if (StrUtil.isNotBlank(u.getDepartmentId())) { Department department = departmentService.get(u.getDepartmentId()); if (department == null) { errors.add(count); reasons.add("部门id不存在"); continue; } u.setDepartmentTitle(department.getTitle()); } if (u.getStatus() == null) { u.setStatus(CommonConstant.USER_STATUS_NORMAL); } userService.save(u); // 分配默认角色 if (u.getDefaultRole() != null && u.getDefaultRole() == 1) { List roleList = roleService.findByDefaultRole(true); if (roleList != null && roleList.size() > 0) { for (Role role : roleList) { UserRole ur = new UserRole().setUserId(u.getId()).setRoleId(role.getId()); userRoleService.save(ur); } } } } // 批量保存数据 int successCount = users.size() - errors.size(); String successMessage = "全部导入成功,共计 " + successCount + " 条数据"; String failMessage = "导入成功 " + successCount + " 条,失败 " + errors.size() + " 条数据。
" + "第 " + errors.toString() + " 行数据导入出错,错误原因分别为:
" + reasons.toString(); String message = ""; if (errors.isEmpty()) { message = successMessage; } else { message = failMessage; } return ResultUtil.success(message); } /** * 校验 * @param username 用户名 不校验传空字符或null 下同 * @param mobile 手机号 * @param email 邮箱 */ public void checkUserInfo(String username, String mobile, String email) { // 禁用词 StopWordsUtil.matchWord(username); if (StrUtil.isNotBlank(username) && userService.findByUsername(username) != null) { throw new XbootException("该登录账号已被注册"); } if (StrUtil.isNotBlank(email) && userService.findByEmail(email) != null) { throw new XbootException("该邮箱已被注册"); } if (StrUtil.isNotBlank(mobile) && userService.findByMobile(mobile) != null) { throw new XbootException("该手机号已被注册"); } } @RequestMapping(value = "/findByType2", method = RequestMethod.GET) @ApiOperation(value = "获取全部用户数据") public Result> findByType2(int type) { List list = userService.findByType2(type); // 清除持久上下文环境 避免后面语句导致持久化 entityManager.clear(); for (User u : list) { u.setPassword(null); } return new ResultUtil>().setData(list); } }