package com.mes.userinfo.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.mes.common.config.Const;
import com.mes.common.utils.JwtUtil;
import com.mes.common.utils.RedisUtil;
import com.mes.common.utils.UserInfoUtils;
import com.mes.entity.request.GeneralRequest;
import com.mes.menu.mapper.SysMenuMapper;
import com.mes.role.entity.SysRole;
import com.mes.role.entity.SysRoleMenu;
import com.mes.role.service.SysRoleService;
import com.mes.userinfo.entity.LoginUser;
import com.mes.userinfo.entity.SysUser;
import com.mes.userinfo.entity.SysUserRole;
import com.mes.userinfo.entity.vo.SysUserVO;
import com.mes.userinfo.mapper.SysUserMapper;
import com.mes.userinfo.service.SysUserRoleService;
import com.mes.userinfo.service.SysUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
*
* 用户表 服务实现类
*
*
* @author zhoush
* @since 2024-04-11
*/
@Service
@Slf4j
public class SysUserServiceImpl extends ServiceImpl implements SysUserService, UserDetailsService {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private RedisUtil redisUtil;
@Resource
private SysMenuMapper sysMenuMapper;
@Resource
private SysUserRoleService sysUserRoleService;
@Resource
private SysRoleService sysRoleService;
@Resource
BCryptPasswordEncoder passwordEncoder;
@Override
public Map login(SysUser user) {
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(user.getUserName(), user.getPassword());
Authentication authenticate = authenticationManager.authenticate(authenticationToken);
if (Objects.isNull(authenticate)) {
throw new RuntimeException("用户名或密码错误");
}
//使用userid生成token
LoginUser loginUser = (LoginUser) authenticate.getPrincipal();
String userId = loginUser.getUser().getId().toString();
String jwt = JwtUtil.generateToken(userId);
//查询权限信息
// List perms = sysMenuMapper.selectPermsByUserId(userId);
//authenticate存入redis
redisUtil.setCacheObject("login:" + userId, loginUser);
//把token响应给前端
HashMap map = new HashMap<>();
map.put("token", jwt);
return map;
}
@Override
public String logout() {
log.info("用户退出");
SysUser user = UserInfoUtils.get();
redisUtil.deleteObject("login:" + user.getId());
return "注销成功";
}
@Transactional
@Override
public String saveUser(SysUserVO user) {
log.info("保存用户信息");
// 默认密码
String password = passwordEncoder.encode(Const.DEFULT_PASSWORD);
user.setPassword(password);
SysUser sysUser = new SysUser();
BeanUtils.copyProperties(user, sysUser);
this.save(sysUser);
saveUserRole(user.getRoleList(), sysUser.getId());
return "success";
}
@Transactional
@Override
public SysUserVO updateUser(SysUserVO user) {
log.info("更新用户信息");
SysUser sysUser = new SysUser();
BeanUtils.copyProperties(user, sysUser);
this.updateById(sysUser);
log.info("删除用户角色信息");
List roleIds = user.getRoleList().stream().map(SysRole::getId).collect(Collectors.toList());
sysUserRoleService.remove(new LambdaQueryWrapper()
.eq(SysUserRole::getUserId, sysUser.getId()).in(CollectionUtil.isNotEmpty(roleIds), SysUserRole::getRoleId, roleIds));
log.info("保存用户角色信息");
saveUserRole(user.getRoleList(), sysUser.getId());
return user;
}
@Override
public String resetPassword(Long userId) {
log.info("重置密码为{}", Const.DEFULT_PASSWORD);
SysUser sysUser = new SysUser();
sysUser.setId(userId);
String password = passwordEncoder.encode(Const.DEFULT_PASSWORD);
sysUser.setPassword(password);
this.updateById(sysUser);
return "success";
}
@Override
public SysUser queryByUserName(String userName) {
return baseMapper.selectOne(new LambdaQueryWrapper().eq(SysUser::getUserName, userName));
}
@Override
public List listByUserName(GeneralRequest request) {
MPJLambdaWrapper wrapper = new MPJLambdaWrapper<>();
wrapper.selectAll(SysUser.class)
.selectCollection(SysRole.class, SysUserVO::getRoleList)
.leftJoin(SysUserRole.class, SysUserRole::getUserId, SysUser::getId)
.leftJoin(SysRole.class, SysRole::getId, SysUserRole::getRoleId)
.like(StringUtils.hasText(request.getKey()), SysUser::getUserName, request.getKey());
return baseMapper.selectJoinList(SysUserVO.class, wrapper);
}
@Transactional
@Override
public String deleteUser(List ids) {
this.removeByIds(ids);
sysUserRoleService.remove(new QueryWrapper().in("user_id", ids));
return "success";
}
@Override
public List getUserAuthorityInfo(Long userId) {
SysUser sysUser = baseMapper.selectById(userId);
// ROLE_admin,ROLE_normal,sys:user:list,....
String authority = "";
if (redisUtil.hasKey("GrantedAuthority:" + sysUser.getUserName())) {
authority = redisUtil.getCacheObject("GrantedAuthority:" + sysUser.getUserName());
} else {
// 获取角色编码
List roles = sysRoleService.list(new QueryWrapper()
.inSql("id", "select role_id from sys_user_role where user_id = " + userId));
if (roles.size() > 0) {
String roleCodes = roles.stream().map(r -> "ROLE_" + r.getRoleKey()).collect(Collectors.joining(","));
authority = roleCodes.concat(",");
}
// 获取菜单操作编码
List perms = sysMenuMapper.selectPermsByUserId(userId);
if (perms.size() > 0) {
String menuPerms = String.join(",", perms);
authority = authority.concat(menuPerms);
}
redisUtil.setCacheObject("GrantedAuthority:" + sysUser.getUserName(), authority, 60 * 60, TimeUnit.SECONDS);
}
return Arrays.stream(authority.split(",")).collect(Collectors.toList());
}
@Override
public void clearUserAuthorityInfo(String userName) {
redisUtil.deleteObject("GrantedAuthority:" + userName);
}
@Override
public void clearUserAuthorityInfoByRoleId(Long roleId) {
List sysUsers = this.list(new QueryWrapper()
.inSql("id", "select user_id from sys_user_role where role_id = " + roleId));
sysUsers.forEach(u -> {
this.clearUserAuthorityInfo(u.getUserName());
});
}
@Override
public void clearUserAuthorityInfoByMenuId(Long menuId) {
MPJLambdaWrapper wrapper = new MPJLambdaWrapper().selectAll(SysUser.class).distinct()
.leftJoin(SysUser.class, SysUser::getId, SysUserRole::getUserId)
.leftJoin(SysRoleMenu.class, SysRoleMenu::getRoleId, SysUserRole::getRoleId)
.eq(SysRoleMenu::getMenuId, menuId);
List sysUsers = sysUserRoleService.selectJoinList(SysUser.class, wrapper);
sysUsers.forEach(u -> {
this.clearUserAuthorityInfo(u.getUserName());
});
}
/**
* 实现UserDetailsService接口,从数据库内获取用户及权限信息
*
* @param username
* @return
* @throws UsernameNotFoundException
*/
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
LambdaQueryWrapper lqw = new LambdaQueryWrapper<>();
lqw.eq(SysUser::getUserName, username);
SysUser user = this.baseMapper.selectOne(lqw);
//判断是否为空
if (Objects.isNull(user)) {
throw new RuntimeException("用户名或密码错误");
}
//查询权限信息
List perms = sysMenuMapper.selectPermsByUserId(user.getId());
return new LoginUser(user, perms);
}
private void saveUserRole(List roles, Long userId) {
log.info("保存用户角色信息");
List userRoles = new ArrayList<>();
if (CollectionUtils.isEmpty(roles)) {
log.info("保存用户角色信息为空,给默认普通用户角色");
userRoles.add(new SysUserRole(userId, Const.DEFULT_ROLE));
} else {
log.info("保存用户角色信息");
userRoles = roles.stream().map(e -> new SysUserRole(userId, e.getId())).collect(Collectors.toList());
}
sysUserRoleService.saveBatch(userRoles);
}
}