SysUserServiceImpl.java 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  1. package com.backendsys.modules.system.service.impl;
  2. import cn.hutool.core.convert.Convert;
  3. import com.backendsys.exception.CustException;
  4. import com.backendsys.modules.common.config.redis.utils.RedisUtil;
  5. import com.backendsys.modules.common.config.security.utils.TokenUtil;
  6. import com.backendsys.modules.common.utils.MybatisUtil;
  7. import com.backendsys.modules.system.dao.*;
  8. import com.backendsys.modules.system.entity.*;
  9. import com.backendsys.modules.system.service.SysUserIntegralService;
  10. import com.backendsys.modules.system.service.SysUserRoleMenuService;
  11. import com.backendsys.modules.system.service.SysUserService;
  12. import com.backendsys.utils.MD5Util;
  13. import com.backendsys.utils.response.PageEntity;
  14. import com.backendsys.utils.response.PageInfoResult;
  15. import com.backendsys.utils.v2.PageUtils;
  16. import com.baomidou.mybatisplus.core.conditions.Wrapper;
  17. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  18. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  19. import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
  20. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  21. import org.redisson.api.RLock;
  22. import org.redisson.api.RedissonClient;
  23. import org.springframework.beans.BeanUtils;
  24. import org.springframework.beans.factory.annotation.Autowired;
  25. import org.springframework.beans.factory.annotation.Value;
  26. import org.springframework.context.annotation.Lazy;
  27. import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
  28. import org.springframework.stereotype.Service;
  29. import org.springframework.transaction.annotation.Transactional;
  30. import java.security.NoSuchAlgorithmException;
  31. import java.util.*;
  32. import java.util.concurrent.TimeUnit;
  33. import java.util.stream.Collectors;
  34. @Service
  35. public class SysUserServiceImpl extends ServiceImpl<SysUserDao, SysUser> implements SysUserService {
  36. @Value("${REDIS_LOGIN_TOKEN_PREFIX}")
  37. private String REDIS_LOGIN_TOKEN_PREFIX;
  38. @Lazy
  39. @Autowired
  40. RedissonClient redissonClient;
  41. @Autowired
  42. private RedisUtil redisUtil;
  43. @Autowired
  44. private TokenUtil tokenUtil;
  45. @Autowired
  46. private SysUserDao sysUserDao;
  47. @Autowired
  48. private SysUserInfoDao sysUserInfoDao;
  49. @Autowired
  50. private SysUserRoleDao sysUserRoleDao;
  51. @Autowired
  52. private SysUserRoleMenuService sysUserRoleMenuService;
  53. @Autowired
  54. private SysUserRoleRelationDao sysUserRoleRelationDao;
  55. @Autowired
  56. private SysUserRolePermissionRelationDao sysUserRolePermissionRelationDao;
  57. @Autowired
  58. private SysUserIntegralService sysUserIntegralService;
  59. /**
  60. * 获取系统用户列表
  61. */
  62. @Override
  63. public PageEntity selectUserList(SysUserDTO sysUserDTO) {
  64. PageUtils.startPage(); // 分页
  65. List<SysUserInfo> list = sysUserInfoDao.selectUserList(sysUserDTO);
  66. return new PageInfoResult(list).toEntity();
  67. }
  68. /**
  69. * 获取系统用户列表 (在线的)
  70. */
  71. @Override
  72. public PageEntity selectUserOnlineList(SysUserDTO sysUserDTO) {
  73. PageUtils.startPage(); // 分页
  74. // 获得 用户最后登录的 tokenUUID
  75. Collection<String> redisKeys = redisUtil.keys(REDIS_LOGIN_TOKEN_PREFIX + "*");
  76. List<String> last_login_uuids = redisKeys.stream().map(e -> String.valueOf(e).replace(REDIS_LOGIN_TOKEN_PREFIX, "")).collect(Collectors.toList());
  77. List<SysUserInfo> list = sysUserInfoDao.selectUserByLastLoginUuids(last_login_uuids);
  78. return new PageInfoResult(list).toEntity();
  79. }
  80. /**
  81. * 获取系统用户详情
  82. */
  83. @Override
  84. public SysUserInfo selectUserInfo(Long user_id) {
  85. // 获得 用户账号信息
  86. SysUser sysUser = sysUserDao.selectOne(new QueryWrapper<SysUser>().eq("id", user_id));
  87. if (sysUser == null) throw new CustException("用户不存在");
  88. // 获得 用户基本信息
  89. SysUserInfo sysUserInfo = sysUserInfoDao.selectOne(new QueryWrapper<SysUserInfo>().eq("user_id", user_id));
  90. if (sysUserInfo == null) throw new CustException("用户不存在");
  91. // 用户账号信息 赋值到 用户基本信息
  92. BeanUtils.copyProperties(sysUser, sysUserInfo);
  93. // 获得 用户角色
  94. List<Map<String, Object>> roles = sysUserRoleDao.selectRoleByUserId(user_id);
  95. sysUserInfo.setRoles(roles);
  96. // 获得 用户角色Id
  97. List<Long> role_ids = roles.stream().map(m -> Convert.toLong(m.get("role_id"))).collect(Collectors.toList());
  98. sysUserInfo.setRole_id(role_ids);
  99. // 获得 用户角色权限Id (根据角色)
  100. List<String> permission_ids = sysUserRolePermissionRelationDao.selectUserRolePermissionIdsByRoleIds(role_ids);
  101. sysUserInfo.setPermission_ids(permission_ids);
  102. // 获得用户角色菜单 (根据权限)
  103. List<Map<String, Object>> sysUserRoleMenuList = sysUserRoleMenuService.selectUserRoleMenuList(permission_ids, 1);
  104. sysUserInfo.setMenus(sysUserRoleMenuList);
  105. // 获得用户积分
  106. Integer integral = sysUserIntegralService.selectIntegralByUserId(user_id);
  107. sysUserInfo.setIntegral(integral);
  108. return sysUserInfo;
  109. }
  110. /**
  111. * 获取系统用户详情(简约)
  112. */
  113. @Override
  114. public SysUserInfoSimple selectUserInfoSimple(Long user_id) {
  115. // 获得 用户账号信息
  116. SysUser sysUser = sysUserDao.selectOne(new QueryWrapper<SysUser>().eq("id", user_id));
  117. if (sysUser == null) throw new CustException("用户不存在");
  118. // 获得 用户基本信息
  119. SysUserInfo sysUserInfo = sysUserInfoDao.selectOne(new QueryWrapper<SysUserInfo>().eq("user_id", user_id));
  120. if (sysUserInfo == null) throw new CustException("用户不存在");
  121. // 获得用户积分
  122. Integer integral = sysUserIntegralService.selectIntegralByUserId(user_id);
  123. sysUserInfo.setIntegral(integral);
  124. // 获得 用户角色
  125. List<Map<String, Object>> roles = sysUserRoleDao.selectRoleByUserId(user_id);
  126. sysUserInfo.setRoles(roles);
  127. // 获得 用户角色Id
  128. List<Long> role_ids = roles.stream().map(m -> Convert.toLong(m.get("role_id"))).collect(Collectors.toList());
  129. sysUserInfo.setRole_id(role_ids);
  130. // 用户账号信息 赋值到 用户基本信息
  131. BeanUtils.copyProperties(sysUser, sysUserInfo);
  132. // 用户基本信息 赋值到 用户基本信息(简约)
  133. SysUserInfoSimple sysUserInfoSimple = new SysUserInfoSimple();
  134. BeanUtils.copyProperties(sysUserInfo, sysUserInfoSimple);
  135. return sysUserInfoSimple;
  136. }
  137. /**
  138. * 获取系统用户权限
  139. */
  140. @Override
  141. public Map<String, Object> selectUserPermission(Long user_id) {
  142. // 获得当前角色关系(集合)
  143. List<Long> userRoleIds = sysUserRoleRelationDao.selectUserRoleIds(user_id);
  144. // 获得当前角色关系(集合) 所对应的权限(集合)
  145. List<String> rolePermissionIds = new ArrayList<>();
  146. if (userRoleIds.size() > 0) {
  147. rolePermissionIds = sysUserRolePermissionRelationDao.selectUserRolePermissionIdsByRoleIds(userRoleIds);
  148. rolePermissionIds = rolePermissionIds.stream().distinct().collect(Collectors.toList());
  149. }
  150. Map<String, Object> resp = new LinkedHashMap<>();
  151. resp.put("user_id", user_id);
  152. resp.put("permission_ids", rolePermissionIds);
  153. return resp;
  154. }
  155. /**
  156. * 获取系统用户菜单
  157. */
  158. @Override
  159. public Map<String, Object> selectUserMenu(Long user_id) {
  160. // 获取系统用户权限
  161. Map<String, Object> permissionResp = selectUserPermission(user_id);
  162. List<String> permission_ids = (List<String>) permissionResp.get("permission_ids");
  163. // 获取系统用户菜单 (根据权限)
  164. List<Map<String, Object>> menuList = sysUserRoleMenuService.selectUserRoleMenuList(permission_ids, 1);
  165. Map<String, Object> resp = new LinkedHashMap<>();
  166. resp.put("user_id", user_id);
  167. resp.put("menus", menuList);
  168. return resp;
  169. }
  170. /**
  171. * 创建系统用户
  172. */
  173. @Override
  174. @Transactional
  175. public Map<String, Object> insertUser(SysUserDTO sysUserDTO) {
  176. RLock lock = redissonClient.getLock("insertUser");
  177. try { lock.tryLock(3, TimeUnit.SECONDS);
  178. String phone = sysUserDTO.getPhone();
  179. Integer phoneAreaCode = sysUserDTO.getPhone_area_code();
  180. String username = sysUserDTO.getUsername();
  181. // [查询] 判断用户名是否存在
  182. if (username != null) {
  183. SysUser sysUser1 = sysUserDao.selectOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUsername, username));
  184. if (sysUser1 != null) throw new CustException("用户名 (" + username + ") 已存在");
  185. }
  186. // [查询] 判断手机号是否存在
  187. if (phone != null) {
  188. LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
  189. queryWrapper.eq(SysUser::getPhone, phone);
  190. queryWrapper.eq(SysUser::getPhone_area_code, phoneAreaCode);
  191. SysUser sysUser2 = sysUserDao.selectOne(queryWrapper);
  192. if (sysUser2 != null) throw new CustException("手机号码 (+" + phoneAreaCode + " " + phone + ") 已存在");
  193. }
  194. // 密码二次加密
  195. String password = sysUserDTO.getPassword();
  196. BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
  197. String encodedPassword = encoder.encode(password);
  198. sysUserDTO.setPassword(encodedPassword);
  199. // 创建用户
  200. sysUserDao.insertUser(sysUserDTO);
  201. return Map.of("user_id", sysUserDTO.getId());
  202. } catch (InterruptedException e) { throw new RuntimeException(e);
  203. } finally { lock.unlock(); }
  204. }
  205. /**
  206. * 编辑系统用户信息
  207. */
  208. @Override
  209. @Transactional
  210. public Map<String, Object> updateUserInfo(SysUserDTO sysUserDTO) {
  211. RLock lock = redissonClient.getLock("updateUserInfo");
  212. try { lock.tryLock(3, TimeUnit.SECONDS);
  213. // 判断记录是否存在
  214. MybatisUtil.checkExists(sysUserDao, "id", sysUserDTO.getUser_id(), "用户不存在");
  215. // 判断手机号码是否存在
  216. if (sysUserDTO.getPhone() != null) {
  217. SysUser sysUser = sysUserDao.selectOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getPhone, sysUserDTO.getPhone()));
  218. if (sysUser != null) throw new CustException("手机号码已存在");
  219. }
  220. // 当 status 状态为 -1(禁用) 时,同时清除登录状态
  221. Integer status = sysUserDTO.getStatus();
  222. if (status != null && status == -1) {
  223. // 删除旧的登录缓存
  224. tokenUtil.deleteRedisLoginToken(sysUserDTO.getLast_login_uuid());
  225. sysUserDTO.setLast_login_uuid("");
  226. }
  227. sysUserDao.updateUserInfo(sysUserDTO);
  228. return Map.of("user_id", sysUserDTO.getUser_id());
  229. } catch (InterruptedException e) { throw new RuntimeException(e);
  230. } finally { lock.unlock(); }
  231. }
  232. /**
  233. * 编辑系统用户密码
  234. */
  235. @Override
  236. @Transactional
  237. public Map<String, Object> updateUserPassword(SysUserDTO sysUserDTO) {
  238. RLock lock = redissonClient.getLock("updateUserPassword");
  239. try { lock.tryLock(3, TimeUnit.SECONDS);
  240. // 查询用户
  241. SysUser sysUser = sysUserDao.selectOne(new QueryWrapper<SysUser>().eq("id", sysUserDTO.getUser_id()));
  242. if (sysUser == null) throw new CustException("原密码不正确");
  243. BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
  244. // [判断] 原密码是否正确
  245. String old_password_request = sysUserDTO.getOld_password();
  246. String old_password = sysUser.getPassword();
  247. if (!encoder.matches(old_password_request, old_password)) {
  248. throw new CustException("原密码不正确");
  249. }
  250. SysUser entity = new SysUser();
  251. entity.setId(sysUserDTO.getUser_id());
  252. // MD5加密
  253. String md5Password = MD5Util.encrypt(sysUserDTO.getPassword());
  254. // 加盐加密
  255. String encodedPassword = encoder.encode(md5Password);
  256. entity.setPassword(encodedPassword);
  257. //
  258. System.out.println(entity);
  259. sysUserDao.updateById(entity);
  260. return Map.of("user_id", sysUserDTO.getUser_id());
  261. } catch (InterruptedException e) {
  262. throw new RuntimeException(e);
  263. } catch (NoSuchAlgorithmException e) {
  264. throw new RuntimeException(e);
  265. } finally { lock.unlock(); }
  266. }
  267. /**
  268. * 重置系统用户密码
  269. */
  270. @Override
  271. @Transactional
  272. public Map<String, Object> resetUserPassword(SysUserDTO sysUserDTO) {
  273. RLock lock = redissonClient.getLock("resetUserPassword");
  274. try { lock.tryLock(3, TimeUnit.SECONDS);
  275. // 生成一个六位的随机数密码
  276. String uuid = UUID.randomUUID().toString().replace("-", "");
  277. String password = uuid.substring(0, 6);
  278. // MD5加密
  279. String md5Password = MD5Util.encrypt(password);
  280. // 加盐加密
  281. BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
  282. String encodedPassword = encoder.encode(md5Password);
  283. sysUserDTO.setPassword(encodedPassword);
  284. //
  285. SysUser entity = new SysUser();
  286. entity.setId(sysUserDTO.getUser_id());
  287. entity.setPassword(encodedPassword);
  288. System.out.println(entity);
  289. sysUserDao.updateById(entity);
  290. Map<String, Object> response = new LinkedHashMap<>();
  291. response.put("user_id", sysUserDTO.getUser_id());
  292. response.put("plain_password", password);
  293. return response;
  294. } catch (InterruptedException e) {
  295. throw new RuntimeException(e);
  296. } catch (NoSuchAlgorithmException e) {
  297. throw new RuntimeException(e);
  298. } finally { lock.unlock(); }
  299. }
  300. /**
  301. * 删除系统用户 (以及部分关联表)
  302. */
  303. @Override
  304. @Transactional
  305. public Map<String, Object> deleteUser(SysUserDTO sysUserDTO) {
  306. RLock lock = redissonClient.getLock("deleteUser");
  307. try { lock.tryLock(3, TimeUnit.SECONDS);
  308. // 单个删除
  309. Long user_id = sysUserDTO.getUser_id();
  310. if (user_id != null) {
  311. sysUserDao.deleteById(user_id);
  312. sysUserInfoDao.delete(new QueryWrapper<SysUserInfo>().eq("user_id", user_id));
  313. sysUserRoleRelationDao.delete(new QueryWrapper<SysUserRoleRelation>().eq("user_id", user_id));
  314. return Map.of("user_id", user_id);
  315. }
  316. // 批量删除
  317. List<Long> user_ids = sysUserDTO.getUser_ids();
  318. if (user_ids != null && user_ids.size() > 0) {
  319. sysUserDao.delete(new QueryWrapper<SysUser>().in("id", user_ids));
  320. sysUserInfoDao.delete(new QueryWrapper<SysUserInfo>().in("user_id", user_ids));
  321. sysUserRoleRelationDao.delete(new QueryWrapper<SysUserRoleRelation>().in("user_id", user_ids));
  322. return Map.of("user_ids", user_ids);
  323. }
  324. return null;
  325. } catch (InterruptedException e) { throw new RuntimeException(e);
  326. } finally { lock.unlock(); }
  327. }
  328. /**
  329. * 踢出系统用户
  330. */
  331. @Override
  332. public Map<String, Object> kickUser(Long user_id) {
  333. RLock lock = redissonClient.getLock("kickUser");
  334. try { lock.tryLock(3, TimeUnit.SECONDS);
  335. // 查询用户信息
  336. Wrapper queryWrapper = new QueryWrapper<SysUserInfo>().lambda().eq(SysUserInfo::getUser_id, user_id);
  337. SysUserInfo sysUserInfo = sysUserInfoDao.selectOne(queryWrapper);
  338. if (sysUserInfo != null) {
  339. // 删除旧的登录缓存
  340. tokenUtil.deleteRedisLoginToken(sysUserInfo.getLast_login_uuid());
  341. // 更新用户信息 (查询最后登录uuid,并清除)
  342. Wrapper updateWrapper = new UpdateWrapper<SysUserInfo>().lambda().set(SysUserInfo::getLast_login_uuid, "").eq(SysUserInfo::getUser_id, user_id);
  343. sysUserInfoDao.update(null, updateWrapper);
  344. }
  345. return Map.of("user_id", user_id);
  346. } catch (InterruptedException e) { throw new RuntimeException(e);
  347. } finally { lock.unlock(); }
  348. }
  349. }