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<Object> 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<Object> 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<Object> 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<Role> 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<User> getUserInfo() {
|
|
User u = securityUtil.getCurrUser();
|
// 清除持久上下文环境 避免后面语句导致持久化
|
entityManager.clear();
|
u.setPassword(null);
|
return new ResultUtil<User>().setData(u);
|
}
|
|
@RequestMapping(value = "/changeMobile", method = RequestMethod.POST)
|
@ApiOperation(value = "修改绑定手机")
|
public Result<Object> 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<Object> 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<Object> 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<Object> 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<Object> modifyPass(@ApiParam("旧密码") @RequestParam String password,
|
@ApiParam("新密码") @RequestParam String newPass,
|
@ApiParam("密码强度") @RequestParam String passStrength) {
|
|
User user = securityUtil.getCurrUser();
|
// 在线DEMO所需
|
if (user.getType()==0) {
|
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<Page<User>> getByCondition(User user,
|
SearchVo searchVo,
|
PageVo pageVo) {
|
|
Page<User> page = userService.findByCondition(user, searchVo, PageUtil.initPage(pageVo));
|
for (User u : page.getContent()) {
|
// 关联角色
|
List<Role> list = iUserRoleService.findByUserId(u.getId());
|
List<RoleDTO> 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<Page<User>>().setData(page);
|
}
|
|
@RequestMapping(value = "/getByDepartmentId/{departmentId}", method = RequestMethod.GET)
|
@ApiOperation(value = "多条件分页获取用户列表")
|
public Result<List<User>> getByCondition(@PathVariable String departmentId) {
|
|
List<User> list = userService.findByDepartmentId(departmentId);
|
entityManager.clear();
|
list.forEach(u -> {
|
u.setPassword(null);
|
});
|
return new ResultUtil<List<User>>().setData(list);
|
}
|
|
@RequestMapping(value = "/searchByName/{username}", method = RequestMethod.GET)
|
@ApiOperation(value = "通过用户名搜索用户")
|
public Result<List<User>> searchByName(@PathVariable String username) throws UnsupportedEncodingException {
|
|
List<User> list = userService.findByUsernameLikeAndStatus(URLDecoder.decode(username, "utf-8"), CommonConstant.STATUS_NORMAL);
|
entityManager.clear();
|
list.forEach(u -> {
|
u.setPassword(null);
|
});
|
return new ResultUtil<List<User>>().setData(list);
|
}
|
|
@RequestMapping(value = "/getAll", method = RequestMethod.GET)
|
@ApiOperation(value = "获取全部用户数据")
|
public Result<List<User>> getAll() {
|
|
List<User> list = userService.getAll();
|
// 清除持久上下文环境 避免后面语句导致持久化
|
entityManager.clear();
|
for (User u : list) {
|
u.setPassword(null);
|
}
|
return new ResultUtil<List<User>>().setData(list);
|
}
|
|
@RequestMapping(value = "/admin/add", method = RequestMethod.POST)
|
@ApiOperation(value = "添加用户")
|
public Result<Object> 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<UserRole> 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<Object> 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<UserRole> 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<Object> 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<Object> 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<Object> 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<Object> importData(@RequestBody List<User> users) {
|
|
List<Integer> errors = new ArrayList<>();
|
List<String> 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<Role> 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() + " 条数据。<br>" +
|
"第 " + errors.toString() + " 行数据导入出错,错误原因分别为:<br>" + 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<List<User>> findByType2(int type) {
|
|
List<User> list = userService.findByType2(type);
|
// 清除持久上下文环境 避免后面语句导致持久化
|
List<User> list1 = new ArrayList<User>();
|
entityManager.clear();
|
for (User u : list) {
|
u.setPassword(null);
|
if (u.getType()==0){
|
list1.add(u);
|
}
|
}
|
return new ResultUtil<List<User>>().setData(list1);
|
}
|
}
|