package com.backendsys.modules.system.service.impl; import cn.hutool.core.convert.Convert; import cn.hutool.core.util.StrUtil; import com.backendsys.exception.CustException; import com.backendsys.modules.common.config.redis.utils.RedisUtil; import com.backendsys.modules.common.utils.MybatisUtil; import com.backendsys.modules.system.dao.*; import com.backendsys.modules.system.entity.SysUser; import com.backendsys.modules.system.entity.SysUserDTO; import com.backendsys.modules.system.entity.SysUserInfo; import com.backendsys.modules.system.entity.SysUserRoleRelation; import com.backendsys.modules.system.service.SysUserV2Service; 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.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.context.annotation.Lazy; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.*; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; @Service public class SysUserV2ServiceImpl extends ServiceImpl implements SysUserV2Service { @Lazy @Autowired RedissonClient redissonClient; @Autowired private RedisUtil redisUtil; @Autowired private SysUserDao sysUserDao; @Autowired private SysUserInfoDao sysUserInfoDao; @Autowired private SysUserRoleDao sysUserRoleDao; @Autowired private SysUserRoleRelationDao sysUserRoleRelationDao; @Autowired private SysUserRoleModuleRelationDao sysUserRoleModuleRelationDao; /** * 获取系统用户列表 */ @Override public PageEntity selectUserList(SysUserDTO sysUserDTO) { PageUtils.startPage(); // 分页 List list = sysUserInfoDao.selectUserList(sysUserDTO); return new PageInfoResult(list).toEntity(); } /** * 获取系统用户列表 (在线的) */ @Override public PageEntity selectUserOnlineList(SysUserDTO sysUserDTO) { PageUtils.startPage(); // 分页 // 获得 用户最后登录的 tokenUUID Collection redisKeys = redisUtil.keys("token:*"); List last_login_uuids = redisKeys.stream().map(e -> String.valueOf(e).replace("token:id:", "")).collect(Collectors.toList()); List list = sysUserInfoDao.selectUserByLastLoginUuids(last_login_uuids); return new PageInfoResult(list).toEntity(); } /** * 获取系统用户详情 */ @Override public SysUserInfo selectUserInfo(Long user_id) { // 获得 用户账号信息 SysUser sysUser = sysUserDao.selectOne(new QueryWrapper().eq("id", user_id)); Objects.requireNonNull(sysUser, "用户不存在"); // 获得 用户基本信息 SysUserInfo sysUserInfo = sysUserInfoDao.selectOne(new QueryWrapper().eq("user_id", user_id)); Objects.requireNonNull(sysUserInfo, "用户不存在"); // 用户账号信息 赋值到 用户基本信息 BeanUtils.copyProperties(sysUser, sysUserInfo); // 获得 用户角色(绑定关系) List> roles = sysUserRoleDao.selectRoleByUserId(user_id); sysUserInfo.setRoles(roles); // List role_ids = roles.stream().map(SysUserRole::getRole_id).collect(Collectors.toList()); List role_ids = roles.stream().map(m -> Convert.toLong(m.get("role_id"))).collect(Collectors.toList()); sysUserInfo.setRole_id(role_ids); List modules = sysUserRoleModuleRelationDao.selectUserRoleModuleIdsByRoleIds(role_ids); sysUserInfo.setModules(modules); return sysUserInfo; } /** * 获取系统用户权限 */ @Override public List selectUserModule(Long user_id) { // 获得当前角色关系(集合) List userRoleIds = sysUserRoleRelationDao.selectUserRoleIds(user_id); // 获得当前角色关系(集合) 所对应的权限(集合) List roleModuleIds = new ArrayList<>(); if (userRoleIds.size() > 0) { roleModuleIds = sysUserRoleModuleRelationDao.selectUserRoleModuleIdsByRoleIds(userRoleIds); roleModuleIds = roleModuleIds.stream().distinct().collect(Collectors.toList()); } return roleModuleIds; } /** * 创建系统用户 */ @Override @Transactional public Map insertUser(SysUserDTO sysUserDTO) { RLock lock = redissonClient.getLock("insertUser"); try { lock.tryLock(3, TimeUnit.SECONDS); // 密码二次加密 String password = sysUserDTO.getPassword(); BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); String encodedPassword = encoder.encode(password); sysUserDTO.setPassword(encodedPassword); sysUserDao.insertUser(sysUserDTO); return Map.of("user_id", sysUserDTO.getId()); } catch (InterruptedException e) { throw new RuntimeException(e); } finally { lock.unlock(); } } /** * 编辑系统用户信息 */ @Override @Transactional public Map updateUserInfo(SysUserDTO sysUserDTO) { RLock lock = redissonClient.getLock("updateUserInfo"); try { lock.tryLock(3, TimeUnit.SECONDS); // 判断记录是否存在 MybatisUtil.checkExists(sysUserDao, "id", sysUserDTO.getUser_id(), "用户不存在"); // 当 status 状态为 -1(禁用) 时,同时清除登录状态 Integer status = sysUserDTO.getStatus(); if (status != null && status == -1) { String last_login_uuid = sysUserDTO.getLast_login_uuid(); redisUtil.delete("token:id:" + last_login_uuid); sysUserDTO.setLast_login_uuid(""); } sysUserDao.updateUserInfo(sysUserDTO); return Map.of("user_id", sysUserDTO.getUser_id()); } catch (InterruptedException e) { throw new RuntimeException(e); } finally { lock.unlock(); } } /** * 编辑系统用户密码 */ @Override @Transactional public Map updateUserPassword(SysUserDTO sysUserDTO) { RLock lock = redissonClient.getLock("updateUserPassword"); try { lock.tryLock(3, TimeUnit.SECONDS); // 查询用户 SysUser sysUser = sysUserDao.selectOne(new QueryWrapper().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()); entity.setPassword(encoder.encode(sysUserDTO.getPassword())); System.out.println(entity); sysUserDao.updateById(entity); return Map.of("user_id", sysUserDTO.getUser_id()); } catch (InterruptedException e) { throw new RuntimeException(e); } finally { lock.unlock(); } } /** * 删除系统用户 (以及部分关联表) */ @Override @Transactional public Map deleteUser(List user_ids) { RLock lock = redissonClient.getLock("deleteUser"); try { lock.tryLock(3, TimeUnit.SECONDS); sysUserDao.delete(new QueryWrapper().in("id", user_ids)); sysUserInfoDao.delete(new QueryWrapper().in("user_id", user_ids)); sysUserRoleRelationDao.delete(new QueryWrapper().in("user_id", user_ids)); return Map.of("user_ids", user_ids); } catch (InterruptedException e) { throw new RuntimeException(e); } finally { lock.unlock(); } } /** * 踢出系统用户 */ @Override public Map kickUser(Long user_id) { RLock lock = redissonClient.getLock("kickUser"); try { lock.tryLock(3, TimeUnit.SECONDS); // 查询用户信息 Wrapper queryWrapper = new QueryWrapper().lambda().eq(SysUserInfo::getUser_id, user_id); SysUserInfo sysUserInfo = sysUserInfoDao.selectOne(queryWrapper); if (sysUserInfo != null) { // 清除缓存 String last_login_uuid = Convert.toStr(sysUserInfo.getLast_login_uuid()); if (StrUtil.isNotEmpty(last_login_uuid)) redisUtil.delete("token:id:" + last_login_uuid); // 更新用户信息 (查询最后登录uuid,并清除) Wrapper updateWrapper = new UpdateWrapper().lambda().set(SysUserInfo::getLast_login_uuid, "").eq(SysUserInfo::getUser_id, user_id); sysUserInfoDao.update(null, updateWrapper); } return Map.of("user_id", user_id); } catch (InterruptedException e) { throw new RuntimeException(e); } finally { lock.unlock(); } } }