123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508 |
- package com.backendsys.modules.system.service.impl;
- import cn.hutool.core.convert.Convert;
- import com.backendsys.exception.CustException;
- import com.backendsys.modules.common.config.redis.utils.RedisUtil;
- import com.backendsys.modules.common.config.security.utils.SecurityUtil;
- import com.backendsys.modules.common.config.security.utils.TokenUtil;
- import com.backendsys.modules.common.utils.MybatisUtil;
- import com.backendsys.modules.sse.entity.SseResponse;
- import com.backendsys.modules.sse.entity.SseResponseEnum;
- import com.backendsys.modules.sse.utils.SseUtil;
- import com.backendsys.modules.system.dao.*;
- import com.backendsys.modules.system.entity.*;
- import com.backendsys.modules.system.service.SysUserIntegralService;
- import com.backendsys.modules.system.service.SysUserRoleMenuService;
- import com.backendsys.modules.system.service.SysUserService;
- import com.backendsys.utils.MD5Util;
- import com.backendsys.utils.response.PageEntity;
- import com.backendsys.utils.response.PageInfoResult;
- import com.backendsys.utils.v2.PageUtils;
- import com.baomidou.mybatisplus.core.conditions.Wrapper;
- import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
- import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
- import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
- import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
- import org.redisson.api.RLock;
- import org.redisson.api.RedissonClient;
- import org.springframework.beans.BeanUtils;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.beans.factory.annotation.Value;
- import org.springframework.context.annotation.Lazy;
- import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
- import org.springframework.stereotype.Service;
- import org.springframework.transaction.annotation.Transactional;
- import java.security.NoSuchAlgorithmException;
- import java.util.*;
- import java.util.concurrent.TimeUnit;
- import java.util.stream.Collectors;
- @Service
- public class SysUserServiceImpl extends ServiceImpl<SysUserDao, SysUser> implements SysUserService {
- @Value("${REDIS_LOGIN_TOKEN_PREFIX}")
- private String REDIS_LOGIN_TOKEN_PREFIX;
- @Value("${spring.application.name}")
- private String APPLICATION_NAME;
- @Autowired
- private SseUtil sseUtil;
- @Lazy
- @Autowired
- RedissonClient redissonClient;
- @Autowired
- private RedisUtil redisUtil;
- @Autowired
- private TokenUtil tokenUtil;
- @Autowired
- private SecurityUtil securityUtil;
- @Autowired
- private SysUserDao sysUserDao;
- @Autowired
- private SysUserInfoDao sysUserInfoDao;
- @Autowired
- private SysUserRoleDao sysUserRoleDao;
- @Autowired
- private SysUserRoleMenuService sysUserRoleMenuService;
- @Autowired
- private SysUserRoleRelationDao sysUserRoleRelationDao;
- @Autowired
- private SysUserRolePermissionRelationDao sysUserRolePermissionRelationDao;
- @Autowired
- private SysUserIntegralService sysUserIntegralService;
- /**
- * 获取系统用户列表
- */
- @Override
- public PageEntity selectUserList(SysUserDTO sysUserDTO) {
- PageUtils.startPage(); // 分页
- List<SysUserInfo> list = sysUserInfoDao.selectUserList(sysUserDTO);
- return new PageInfoResult(list).toEntity();
- }
- /**
- * 获取系统用户列表 (在线的)
- */
- @Override
- public PageEntity selectUserOnlineList(SysUserDTO sysUserDTO) {
- PageUtils.startPage(); // 分页
- // 获得 用户最后登录的 tokenUUID
- Collection<String> redisKeys = redisUtil.keys(REDIS_LOGIN_TOKEN_PREFIX + "*");
- List<String> last_login_uuids = redisKeys.stream().map(e -> String.valueOf(e).replace(REDIS_LOGIN_TOKEN_PREFIX, "")).collect(Collectors.toList());
- List<SysUserInfo> list = sysUserInfoDao.selectUserByLastLoginUuids(last_login_uuids);
- return new PageInfoResult(list).toEntity();
- }
- /**
- * 获取系统用户详情
- */
- @Override
- public SysUserInfo selectUserInfo(Long user_id) {
- // 获得 用户账号信息
- SysUser sysUser = sysUserDao.selectOne(new QueryWrapper<SysUser>().eq("id", user_id));
- if (sysUser == null) throw new CustException("用户不存在");
- // 获得 用户基本信息
- SysUserInfo sysUserInfo = sysUserInfoDao.selectOne(new QueryWrapper<SysUserInfo>().eq("user_id", user_id));
- if (sysUserInfo == null) throw new CustException("用户不存在");
- // 用户账号信息 赋值到 用户基本信息
- BeanUtils.copyProperties(sysUser, sysUserInfo);
- // 获得 用户角色
- List<Map<String, Object>> roles = sysUserRoleDao.selectRoleByUserId(user_id);
- sysUserInfo.setRoles(roles);
- // 获得 用户角色Id
- List<Long> role_ids = roles.stream().map(m -> Convert.toLong(m.get("role_id"))).collect(Collectors.toList());
- sysUserInfo.setRole_id(role_ids);
- // 获得 用户角色权限Id (根据角色)
- List<String> permission_ids = sysUserRolePermissionRelationDao.selectUserRolePermissionIdsByRoleIds(role_ids);
- sysUserInfo.setPermission_ids(permission_ids);
- // 获得用户角色菜单 (根据权限)
- List<Map<String, Object>> sysUserRoleMenuList = sysUserRoleMenuService.selectUserRoleMenuList(permission_ids, 1);
- sysUserInfo.setMenus(sysUserRoleMenuList);
- // 获得用户积分 (需要权限)
- Integer integral = sysUserIntegralService.selectIntegralByUserId(user_id);
- sysUserInfo.setIntegral(integral);
- return sysUserInfo;
- }
- /**
- * 获取系统用户详情(简约)
- */
- @Override
- public SysUserInfoSimple selectUserInfoSimple(Long user_id) {
- // 获得 用户账号信息
- SysUser sysUser = sysUserDao.selectOne(new QueryWrapper<SysUser>().eq("id", user_id));
- if (sysUser == null) throw new CustException("用户不存在");
- // 获得 用户基本信息
- SysUserInfo sysUserInfo = sysUserInfoDao.selectOne(new QueryWrapper<SysUserInfo>().eq("user_id", user_id));
- if (sysUserInfo == null) throw new CustException("用户不存在");
- // 获得 用户角色
- List<Map<String, Object>> roles = sysUserRoleDao.selectRoleByUserId(user_id);
- sysUserInfo.setRoles(roles);
- // 获得 用户角色Id
- List<Long> role_ids = roles.stream().map(m -> Convert.toLong(m.get("role_id"))).collect(Collectors.toList());
- sysUserInfo.setRole_id(role_ids);
- // 获得用户积分 (需要权限)
- Integer integral = sysUserIntegralService.selectIntegralByUserId(user_id);
- sysUserInfo.setIntegral(integral);
- // 用户账号信息 赋值到 用户基本信息
- BeanUtils.copyProperties(sysUser, sysUserInfo);
- // 用户基本信息 赋值到 用户基本信息(简约)
- SysUserInfoSimple sysUserInfoSimple = new SysUserInfoSimple();
- BeanUtils.copyProperties(sysUserInfo, sysUserInfoSimple);
- return sysUserInfoSimple;
- }
- /**
- * 获取系统用户权限
- */
- @Override
- public Map<String, Object> selectUserPermission(Long user_id) {
- // 获得当前角色关系(集合)
- List<Long> userRoleIds = sysUserRoleRelationDao.selectUserRoleIds(user_id);
- // 获得当前角色关系(集合) 所对应的权限(集合)
- List<String> rolePermissionIds = new ArrayList<>();
- if (userRoleIds.size() > 0) {
- rolePermissionIds = sysUserRolePermissionRelationDao.selectUserRolePermissionIdsByRoleIds(userRoleIds);
- rolePermissionIds = rolePermissionIds.stream().distinct().collect(Collectors.toList());
- }
- Map<String, Object> resp = new LinkedHashMap<>();
- resp.put("user_id", user_id);
- resp.put("permission_ids", rolePermissionIds);
- return resp;
- }
- /**
- * 获取系统用户菜单
- */
- @Override
- public Map<String, Object> selectUserMenu(Long user_id) {
- // 获取系统用户权限
- Map<String, Object> permissionResp = selectUserPermission(user_id);
- List<String> permission_ids = (List<String>) permissionResp.get("permission_ids");
- // 获取系统用户菜单 (根据权限)
- List<Map<String, Object>> menuList = sysUserRoleMenuService.selectUserRoleMenuList(permission_ids, 1);
- Map<String, Object> resp = new LinkedHashMap<>();
- resp.put("user_id", user_id);
- resp.put("menus", menuList);
- return resp;
- }
- /**
- * 创建系统用户
- */
- @Override
- @Transactional(rollbackFor = Exception.class)
- public Map<String, Object> insertUser(SysUserDTO sysUserDTO) {
- RLock lock = redissonClient.getLock("insertUser");
- try { lock.tryLock(3, TimeUnit.SECONDS);
- String phone = sysUserDTO.getPhone();
- Integer phoneAreaCode = sysUserDTO.getPhone_area_code();
- String username = sysUserDTO.getUsername();
- // [查询] 判断用户名是否存在
- if (username != null) {
- SysUser sysUser1 = sysUserDao.selectOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUsername, username));
- if (sysUser1 != null) throw new CustException("用户名 (" + username + ") 已存在");
- }
- // [查询] 判断手机号是否存在
- if (phone != null) {
- LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
- queryWrapper.eq(SysUser::getPhone, phone);
- queryWrapper.eq(SysUser::getPhone_area_code, phoneAreaCode);
- SysUser sysUser2 = sysUserDao.selectOne(queryWrapper);
- if (sysUser2 != null) throw new CustException("手机号码 (+" + phoneAreaCode + " " + phone + ") 已存在");
- }
- // 密码二次加密
- String password = sysUserDTO.getPassword();
- BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
- String encodedPassword = encoder.encode(password);
- sysUserDTO.setPassword(encodedPassword);
- // 创建用户
- sysUserDao.insertUser(sysUserDTO);
- // 初始化用户积分
- sysUserIntegralService.init(sysUserDTO.getId());
- return Map.of("user_id", sysUserDTO.getId());
- } catch (InterruptedException e) { throw new RuntimeException(e);
- } finally { lock.unlock(); }
- }
- /**
- * 编辑系统用户信息
- */
- @Override
- @Transactional(rollbackFor = Exception.class)
- public Map<String, Object> updateUserInfo(SysUserDTO sysUserDTO) {
- RLock lock = redissonClient.getLock("updateUserInfo");
- try { lock.tryLock(3, TimeUnit.SECONDS);
- // 判断记录是否存在
- MybatisUtil.checkExists(sysUserDao, "id", sysUserDTO.getUser_id(), "用户不存在");
- // 判断手机号码是否存在
- if (sysUserDTO.getPhone() != null) {
- SysUser sysUser = sysUserDao.selectOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getPhone, sysUserDTO.getPhone()));
- if (sysUser != null) throw new CustException("手机号码已存在");
- }
- // 当 status 状态为 -1(禁用) 时,同时清除登录状态
- Integer status = sysUserDTO.getStatus();
- if (status != null && status == -1) {
- // 删除旧的登录缓存
- tokenUtil.deleteRedisLoginToken(sysUserDTO.getLast_login_uuid());
- sysUserDTO.setLast_login_uuid("");
- }
- System.out.println("sysUserDTO = " + sysUserDTO);
- sysUserDao.updateUserInfo(sysUserDTO);
- return Map.of("user_id", sysUserDTO.getUser_id());
- } catch (InterruptedException e) { throw new RuntimeException(e);
- } finally { lock.unlock(); }
- }
- /**
- * 编辑系统用户角色绑定
- */
- @Override
- @Transactional(rollbackFor = Exception.class)
- public Map<String, Object> updateUserRoleRelation(SysUserRoleRelation sysUserRoleRelation) {
- RLock lock = redissonClient.getLock("updateUserRoleRelation");
- try { lock.tryLock(3, TimeUnit.SECONDS);
- List<Long> role_ids = sysUserRoleRelation.getRole_ids();
- Long user_id = sysUserRoleRelation.getUser_id();
- // 1.删除全部用户与角色的关系 (sys_user_role_relation)
- LambdaQueryWrapper<SysUserRoleRelation> wrapperRoleRelation = new LambdaQueryWrapper<>();
- wrapperRoleRelation.eq(SysUserRoleRelation::getUser_id, user_id);
- sysUserRoleRelationDao.delete(wrapperRoleRelation);
- // 2.重新添加参数中的角色与权限的关系 (sys_user_role_relation)
- sysUserRoleRelationDao.insertBatch(user_id, role_ids);
- return Map.of("user_id", sysUserRoleRelation.getUser_id());
- } catch (InterruptedException e) { throw new RuntimeException(e);
- } finally { lock.unlock(); }
- }
- /**
- * 编辑系统用户密码
- */
- @Override
- @Transactional(rollbackFor = Exception.class)
- public Map<String, Object> updateUserPassword(SysUserDTO sysUserDTO) {
- RLock lock = redissonClient.getLock("updateUserPassword");
- try { lock.tryLock(3, TimeUnit.SECONDS);
- // 查询用户
- SysUser sysUser = sysUserDao.selectOne(new QueryWrapper<SysUser>().eq("id", sysUserDTO.getUser_id()));
- if (sysUser == null) throw new CustException("原密码不正确");
- BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
- // [判断] 原密码是否正确
- String old_password_request = sysUserDTO.getOld_password();
- String old_password = sysUser.getPassword();
- if (!encoder.matches(old_password_request, old_password)) {
- throw new CustException("原密码不正确");
- }
- SysUser entity = new SysUser();
- entity.setId(sysUserDTO.getUser_id());
- // // MD5加密
- // String md5Password = MD5Util.encrypt(sysUserDTO.getPassword());
- // 加盐加密 (前端会传已加密过的密码)
- String encodedPassword = encoder.encode(sysUserDTO.getPassword());
- entity.setPassword(encodedPassword);
- System.out.println(entity);
- // [编辑] 用户密码
- sysUserDao.updateById(entity);
- // [SSE] 发送退出登录的消息
- String dataStr = (new SseResponse(SseResponseEnum.LOGOUT)).toJsonStr();
- sseUtil.send(sysUserDTO.getUser_id(), dataStr);
- return Map.of("user_id", sysUserDTO.getUser_id());
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- } finally { lock.unlock(); }
- }
- /**
- * 重置系统用户密码
- */
- @Override
- @Transactional(rollbackFor = Exception.class)
- public Map<String, Object> resetUserPassword(SysUserDTO sysUserDTO) {
- RLock lock = redissonClient.getLock("resetUserPassword");
- try { lock.tryLock(3, TimeUnit.SECONDS);
- // 生成一个六位的随机数密码
- String uuid = UUID.randomUUID().toString().replace("-", "");
- String password = uuid.substring(0, 6);
- // MD5加密
- String md5Password = MD5Util.encrypt(password);
- // 加盐加密
- BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
- String encodedPassword = encoder.encode(md5Password);
- sysUserDTO.setPassword(encodedPassword);
- //
- SysUser entity = new SysUser();
- entity.setId(sysUserDTO.getUser_id());
- entity.setPassword(encodedPassword);
- System.out.println(entity);
- // [编辑] 用户密码
- sysUserDao.updateById(entity);
- // 要先判断连接存不存在?
- // [SSE] 发送退出登录的消息
- try {
- String dataStr = (new SseResponse(SseResponseEnum.LOGOUT)).toJsonStr();
- sseUtil.send(sysUserDTO.getUser_id(), dataStr);
- } catch (Exception e) {
- System.out.println(e.getMessage());
- }
- Map<String, Object> response = new LinkedHashMap<>();
- response.put("user_id", sysUserDTO.getUser_id());
- response.put("plain_password", password);
- return response;
- } catch (InterruptedException | NoSuchAlgorithmException e) {
- throw new RuntimeException(e);
- } finally { lock.unlock(); }
- }
- /**
- * 删除系统用户 (以及部分关联表)
- */
- @Override
- @Transactional(rollbackFor = Exception.class)
- public Map<String, Object> deleteUser(SysUserDTO sysUserDTO) {
- RLock lock = redissonClient.getLock("deleteUser");
- try { lock.tryLock(3, TimeUnit.SECONDS);
- // 单个删除
- Long user_id = sysUserDTO.getUser_id();
- if (user_id != null) {
- sysUserDao.deleteById(user_id);
- sysUserInfoDao.delete(new QueryWrapper<SysUserInfo>().eq("user_id", user_id));
- sysUserRoleRelationDao.delete(new QueryWrapper<SysUserRoleRelation>().eq("user_id", user_id));
- return Map.of("user_id", user_id);
- }
- // 批量删除
- List<Long> user_ids = sysUserDTO.getUser_ids();
- if (user_ids != null && user_ids.size() > 0) {
- sysUserDao.delete(new QueryWrapper<SysUser>().in("id", user_ids));
- sysUserInfoDao.delete(new QueryWrapper<SysUserInfo>().in("user_id", user_ids));
- sysUserRoleRelationDao.delete(new QueryWrapper<SysUserRoleRelation>().in("user_id", user_ids));
- return Map.of("user_ids", user_ids);
- }
- return null;
- } catch (InterruptedException e) { throw new RuntimeException(e);
- } finally { lock.unlock(); }
- }
- /**
- * 踢出系统用户
- */
- @Override
- public Map<String, Object> kickUser(Long user_id) {
- RLock lock = redissonClient.getLock("kickUser");
- try { lock.tryLock(3, TimeUnit.SECONDS);
- // 查询用户信息
- Wrapper queryWrapper = new QueryWrapper<SysUserInfo>().lambda().eq(SysUserInfo::getUser_id, user_id);
- SysUserInfo sysUserInfo = sysUserInfoDao.selectOne(queryWrapper);
- if (sysUserInfo != null) {
- // 删除旧的登录缓存
- tokenUtil.deleteRedisLoginToken(sysUserInfo.getLast_login_uuid());
- // 更新用户信息 (查询最后登录uuid,并清除)
- Wrapper updateWrapper = new UpdateWrapper<SysUserInfo>().lambda().set(SysUserInfo::getLast_login_uuid, "").eq(SysUserInfo::getUser_id, user_id);
- sysUserInfoDao.update(null, updateWrapper);
- // [SSE] 发送退出登录的消息
- String dataStr = (new SseResponse(SseResponseEnum.LOGOUT)).toJsonStr();
- sseUtil.send(sysUserInfo.getUser_id(), dataStr);
- }
- return Map.of("user_id", user_id);
- } catch (InterruptedException e) { throw new RuntimeException(e);
- } finally { lock.unlock(); }
- }
- /**
- * 审核用户
- */
- @Override
- public Map<String, Object> auditUser(SysUserDTO sysUserDTO) {
- RLock lock = redissonClient.getLock("auditUser");
- try { lock.tryLock(3, TimeUnit.SECONDS);
- Long user_id = sysUserDTO.getUser_id();
- SysUserInfo entity = new SysUserInfo();
- entity.setAudit_status(sysUserDTO.getAudit_status());
- entity.setAudit_note(sysUserDTO.getAudit_note());
- sysUserInfoDao.update(entity, new LambdaQueryWrapper<SysUserInfo>().eq(SysUserInfo::getUser_id, user_id));
- return Map.of("user_id", user_id);
- } catch (InterruptedException e) { throw new RuntimeException(e);
- } finally { lock.unlock(); }
- }
- }
|