package com.gkhy.assess.system.service.impl;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gkhy.assess.common.api.CommonPage;
import com.gkhy.assess.common.constant.CacheConstant;
import com.gkhy.assess.common.domain.vo.AccountVO;
import com.gkhy.assess.common.domain.vo.LoginBody;
import com.gkhy.assess.common.enums.AttachTypeEnum;
import com.gkhy.assess.common.enums.UserIdentityEnum;
import com.gkhy.assess.common.exception.ApiException;
import com.gkhy.assess.common.utils.*;
import com.gkhy.assess.system.domain.SysAgency;
import com.gkhy.assess.system.domain.SysAttach;
import com.gkhy.assess.system.domain.SysUser;
import com.gkhy.assess.system.mapper.SysAgencyMapper;
import com.gkhy.assess.system.mapper.SysUserMapper;
import com.gkhy.assess.system.service.SysAgencyService;
import com.gkhy.assess.system.service.SysAttachService;
import com.gkhy.assess.system.service.SysConfigService;
import com.gkhy.assess.system.service.SysUserService;
import com.gkhy.assess.system.utils.ShiroUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Validator;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
*
* 用户表 服务实现类
*
*
* @author kzy
* @since 2023-10-17 14:26:29
*/
@Service
public class SysUserServiceImpl extends ServiceImpl implements SysUserService {
@Autowired
private RedisUtils redisUtils;
@Autowired
private SysConfigService configService;
@Autowired
private Validator validator;
@Autowired
private HttpServletRequest request;
@Autowired
private SysAgencyMapper agencyMapper;
@Autowired
private SysAgencyService agencyService;
@Autowired
private SysAttachService attachService;
@Override
public AccountVO login(LoginBody loginBody) {
// 验证码校验
// validateCaptcha(loginBody.getUsername(), loginBody.getCode(), loginBody.getUuid());
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(loginBody.getUsername(), Base64.decodeStr(loginBody.getPassword()), false);
Subject subject= SecurityUtils.getSubject();
String msg ;
try {
subject.login(usernamePasswordToken);
SysUser sysUser = (SysUser) subject.getPrincipal();
AccountVO accountVO = new AccountVO();
BeanUtils.copyProperties(sysUser, accountVO);
String token = JwtTokenUtil.sign(sysUser.getUsername(),sysUser.getPassword());
accountVO.setToken(token);
cacheUserToken(sysUser.getUsername(),token);
return accountVO;
}catch (UnknownAccountException | IncorrectCredentialsException uae){
throw new ApiException("用户名/密码错误,请重新输入");
} catch (LockedAccountException lae) { // 账号已被锁定
msg = "账号已被锁定";
throw new ApiException(msg);
}catch (AuthenticationException ae) { // 其他身份验证异常
msg = "用户认证失败:"+ae.getMessage();
throw new ApiException(msg);
}
}
/**
* 清空旧的登录信息,保证同时只有一个用户再登录,后登录用户会挤掉前一个用户
* @param username
*/
public void cacheUserToken(String username,String newToken){
// String userKey = redisUtils.generateKey(CacheConstant.SYS_USER_TOKEN + ":" + username);
// String oldToken = (String) redisUtils.get(userKey);
// if (StrUtil.isNotBlank(oldToken)) {
// String oldTokenkey = redisUtils.generateKey(CacheConstant.SYS_USER_TOKEN + ":" + JwtTokenUtil.md5Encode(oldToken));
// redisUtils.del(oldTokenkey);
// redisUtils.del(userKey);
// }
// redisUtils.set(userKey, newToken,(JwtTokenUtil.EXPIRATION*2/1000)+2);
String tokenKey= redisUtils.generateKey(CacheConstant.SYS_USER_TOKEN+":"+JwtTokenUtil.md5Encode(newToken));
// 设置超时时间
redisUtils.set(tokenKey,newToken);
redisUtils.expire(tokenKey,JwtTokenUtil.EXPIRATION*2/1000);
}
/**
* 校验验证码
*
* @param username 用户名
* @param code 验证码
* @param uuid 唯一标识
* @return 结果
*/
public void validateCaptcha(String username, String code, String uuid)
{
if(StringUtils.isBlank(code)||StringUtils.isBlank(uuid)){
throw new ApiException("验证码或验证码标识为空");
}
String verifyKey = CacheConstant.CAPTCHA_CODE_KEY +uuid;
String captcha = (String) redisUtils.get(verifyKey);
redisUtils.del(verifyKey);
if (StringUtils.isBlank(captcha))
{
throw new ApiException("验证码已失效");
}
if (!code.equalsIgnoreCase(captcha))
{
throw new ApiException("验证码不正确");
}
}
@Override
public void logout() {
String jwtToken = request.getHeader(JwtTokenUtil.USER_LOGIN_TOKEN);
String key= redisUtils.generateKey(CacheConstant.SYS_USER_TOKEN+":"+JwtTokenUtil.md5Encode(jwtToken));
//删除redis缓存
redisUtils.del(key);
}
@Override
public CommonPage monitorList(SysUser user) {
PageUtil.startPage();
List users=baseMapper.monitorList(user);
return CommonPage.restPage(users);
}
@Override
public CommonPage agencyList(SysUser user) {
PageUtil.startPage();
List users=baseMapper.agencyList(user);
return CommonPage.restPage(users);
}
@Override
public CommonPage expertList(SysUser user) {
PageUtil.startPage();
List users=baseMapper.expertList(user);
return CommonPage.restPage(users);
}
@Override
public SysUser getUserByUsername(String username) {
String key=redisUtils.generateKey(CacheConstant.SYS_USER_NAME+":"+username);
SysUser sysUser =null;
if(redisUtils.hasKey(key)){
sysUser= (SysUser) redisUtils.get(key);
}else {
sysUser = baseMapper.getUserByUsername(username);
redisUtils.set(key,sysUser,10*60);
}
return sysUser;
}
public void delCacheByUsername(String username){
String key=redisUtils.generateKey(CacheConstant.SYS_USER_NAME+":"+username);
redisUtils.del(key);
}
@Override
public SysUser getUserByUsernamePhone(String username) {
String key=redisUtils.generateKey(CacheConstant.SYS_USER_NAME+":"+username);
SysUser sysUser =null;
if(redisUtils.hasKey(key)){
sysUser= (SysUser) redisUtils.get(key);
}else {
sysUser = baseMapper.getUserByUsernamePhone(username);
redisUtils.set(key,sysUser,10*60);
}
return sysUser;
}
public void validatorPassword(String password){
if(password.length()<5||password.length()>30){
throw new ApiException("密码长度须在5-30之间");
}
}
@Override
public int addMonitor(SysUser user) {
//校验用户信息
if(!checkUsernameUnique(new SysUser().setUsername(user.getUsername()))){
throw new ApiException("用户名已存在");
}
if(!checkPhoneUnique(new SysUser().setUsername(user.getPhone()))){
throw new ApiException("手机号已存在");
}
String originPsword=Base64.decodeStr(user.getPassword());
validatorPassword(originPsword);
user.setPassword(JwtTokenUtil.encryptPassword(user.getUsername(),originPsword,user.getSalt()));
user.setIdentity(UserIdentityEnum.MONITOR.getCode());
boolean b=save(user);
if(!b){
throw new ApiException("创建监管用户信息失败");
}
return 1;
}
@Override
@Transactional(rollbackFor = RuntimeException.class)
public int addAgency(SysUser user) {
//校验用户信息
if(!checkUsernameUnique(new SysUser().setUsername(user.getUsername()))){
throw new ApiException("用户名已存在");
}
if(!checkPhoneUnique(new SysUser().setUsername(user.getPhone()))){
throw new ApiException("手机号已存在");
}
String originPsword=Base64.decodeStr(user.getPassword());
validatorPassword(originPsword);
SysAgency agency=user.getAgency();
if(ObjectUtil.isNull(agency)){
throw new ApiException("机构信息不能为空");
}
//查询机构信息是否存在
if(!agencyService.checkAgencyNameUnique(new SysAgency().setName(agency.getName()))){
throw new ApiException("机构名称已存在");
}
int i=agencyMapper.insert(agency);
if(i<1){
throw new ApiException("保存机构信息失败");
}
user.setIdentity(UserIdentityEnum.AGENCY.getCode());
user.setAgencyId(agency.getId());
user.setPassword(JwtTokenUtil.encryptPassword(user.getUsername(),originPsword,user.getSalt()));
boolean b=save(user);
if(!b){
throw new ApiException("创建机构用户信息失败");
}
return 1;
}
@Override
@Transactional(rollbackFor = RuntimeException.class)
public int addExpert(SysUser user) {
//校验用户信息
if(!checkUsernameUnique(new SysUser().setUsername(user.getUsername()))){
throw new ApiException("用户名已存在");
}
if(!checkPhoneUnique(new SysUser().setUsername(user.getPhone()))){
throw new ApiException("手机号已存在");
}
String originPsword=Base64.decodeStr(user.getPassword());
validatorPassword(originPsword);
user.setIdentity(UserIdentityEnum.EXPERT.getCode());
user.setCreateBy(ShiroUtils.getSysUser().getUsername());
user.setPassword(JwtTokenUtil.encryptPassword(user.getUsername(),originPsword,user.getSalt()));
boolean b=save(user);
if(!b){
throw new ApiException("创建专家信息失败");
}
List socialAttach=user.getSocialAttach();
List medicalAttach=user.getMedicalAttach();
List salaryAttach=user.getSalaryAttach();
List attaches=new ArrayList<>();
for(SysAttach attach:socialAttach){
attach.setType(AttachTypeEnum.SOCIAL.getCode());
attach.setUserId(user.getId());
attaches.add(attach);
}
for(SysAttach attach:medicalAttach){
attach.setType(AttachTypeEnum.MEDICAL.getCode());
attach.setUserId(user.getId());
attaches.add(attach);
}
for(SysAttach attach:salaryAttach){
attach.setType(AttachTypeEnum.SALARY.getCode());
attach.setUserId(user.getId());
attaches.add(attach);
}
attachService.saveBatch(attaches);
return 1;
}
@Override
public SysUser getUserByPhone(String phone) {
return baseMapper.getUserByPhone(phone);
}
@Override
public SysUser getUserById(Long userId) {
return baseMapper.getUserById(userId);
}
@Override
public SysUser getUserInfoById(Long userId) {
return baseMapper.getUserInfoById(userId);
}
@Override
@Transactional(rollbackFor = RuntimeException.class)
public int deleteUserById(Long userId) {
SysUser user=getUserById(userId);
if(user==null){
throw new ApiException("用户不存在");
}
if(Objects.equals(ShiroUtils.getUserId(), userId)){
throw new ApiException("不能删除自己账号");
}
//机构用户,将机构信息设置成删除状态
if(user.getIdentity().equals(UserIdentityEnum.AGENCY.getCode())){
if(user.getAgencyId()==null){
throw new ApiException("获取机构id为空");
}
agencyMapper.deleteAgencyById(user.getAgencyId());
}
delCacheByUsername(user.getUsername());
return baseMapper.deleteUserById(userId);
}
@Override
public int editMonitor(SysUser user) {
//校验用户信息
if(!checkUsernameUnique(user)){
throw new ApiException("用户名已存在");
}
if(!checkPhoneUnique(user)){
throw new ApiException("手机号已存在");
}
delCacheByUsername(user.getUsername());
user.setPassword(null);
boolean b=updateById(user);
if(!b){
throw new ApiException("更新监管用户信息失败");
}
return 1;
}
@Override
@Transactional(rollbackFor = RuntimeException.class)
public int editAgency(SysUser user) {
//校验用户信息
if(!checkUsernameUnique(user)){
throw new ApiException("用户名已存在");
}
if(!checkPhoneUnique(user)){
throw new ApiException("手机号已存在");
}
SysAgency agency=user.getAgency();
if(ObjectUtil.isNull(agency)||agency.getId()==null){
throw new ApiException("机构信息或者id不能为空");
}
//查询机构信息是否存在
if(!agencyService.checkAgencyNameUnique(agency)){
throw new ApiException("机构名称已存在");
}
delCacheByUsername(user.getUsername());
agencyService.updateById(agency);
user.setPassword(null);
boolean b=updateById(user);
if(!b){
throw new ApiException("更新用户失败");
}
return 1;
}
@Override
public int editExpert(SysUser user) {
//校验用户信息
if(!checkUsernameUnique(user)){
throw new ApiException("用户名已存在");
}
if(!checkPhoneUnique(user)){
throw new ApiException("手机号已存在");
}
user.setPassword(null);
boolean b=updateById(user);
if(!b){
throw new ApiException("更新专家信息失败");
}
//刪除旧数据
attachService.deleteAttachsByUserId(user.getId(),null);
List socialAttach=user.getSocialAttach();
List medicalAttach=user.getMedicalAttach();
List salaryAttach=user.getSalaryAttach();
List attaches=new ArrayList<>();
for(SysAttach attach:socialAttach){
attach.setType(AttachTypeEnum.SOCIAL.getCode());
attach.setUserId(user.getId());
attaches.add(attach);
}
for(SysAttach attach:medicalAttach){
attach.setType(AttachTypeEnum.MEDICAL.getCode());
attach.setUserId(user.getId());
attaches.add(attach);
}
for(SysAttach attach:salaryAttach){
attach.setType(AttachTypeEnum.SALARY.getCode());
attach.setUserId(user.getId());
attaches.add(attach);
}
attachService.saveBatch(attaches);
delCacheByUsername(user.getUsername());
return 1;
}
@Override
public boolean resetUserPwd(SysUser user) {
String originPsword=Base64.decodeStr(user.getPassword());
validatorPassword(originPsword);
checkUserAllowed(user);
SysUser oldUser=checkUserDataScope(user.getId());
SysUser newUser=new SysUser().setId(user.getId()).setPassword(JwtTokenUtil.encryptPassword(oldUser.getUsername(),originPsword,oldUser.getSalt()));
newUser.setUpdateBy(ShiroUtils.getSysUser().getUsername());
delCacheByUsername(oldUser.getUsername());
return updateById(newUser);
}
@Override
public boolean checkUsernameUnique(SysUser user) {
Long userId = user.getId()==null? -1L : user.getId();
SysUser info = baseMapper.checkLoginNameUnique(user.getUsername());
if (info!=null && info.getId().longValue() != userId.longValue())
{
return false;
}
return true;
}
@Override
public boolean checkPhoneUnique(SysUser user) {
Long userId = user.getId()==null ? -1L : user.getId();
SysUser info = baseMapper.checkPhoneUnique(user.getPhone());
if (info!=null && info.getId().longValue() != userId.longValue())
{
return false;
}
return true;
}
@Override
public boolean checkEmailUnique(SysUser user) {
Long userId = user.getId()==null ? -1L : user.getId();
SysUser info = baseMapper.checkEmailUnique(user.getEmail());
if (info!=null && info.getId().longValue() != userId.longValue())
{
return false;
}
return true;
}
@Override
public void checkUserAllowed(SysUser user) {
}
@Override
public SysUser checkUserDataScope(Long userId) {
if(userId==null){
throw new ApiException("用户id为空!");
}
SysUser user = baseMapper.getUserById(userId);
if (ObjectUtil.isNull(user))
{
throw new ApiException("用户数据不存在!");
}
return user;
}
@Override
public String importUser(List userList,Boolean isUpdateSupport) {
if(ObjectUtil.isEmpty(userList)||userList.size()==0){
throw new ApiException("导入用户数据不能为空");
}
int successNum=0;
int failureNum=0;
StringBuilder successMsg=new StringBuilder();
StringBuilder failureMsg=new StringBuilder();
String password=configService.getConfigByKey("sys.user.initPassword");
for(SysUser user:userList){
try {
SysUser u = baseMapper.getUserByUsername(user.getUsername());
if (ObjectUtil.isNull(u)) {
BeanValidators.validateWithException(validator, user);
user.setPassword(JwtTokenUtil.md5Encode(user.getUsername() + password));
user.setCreateBy("");
save(user);
successNum++;
successMsg.append("
" + successNum + "、账号 " + user.getUsername() + " 导入成功");
} else if (isUpdateSupport) {
BeanValidators.validateWithException(validator, user);
checkUserAllowed(u);
checkUserDataScope(u.getId());
user.setId(u.getId());
user.setUpdateBy("");
updateById(user);
successNum++;
successMsg.append("
" + successNum + "、账号 " + user.getUsername() + " 更新成功");
} else {
failureNum++;
failureMsg.append("
" + failureNum + "、账号 " + user.getUsername() + " 已存在");
}
}catch (Exception e){
failureNum++;
String msg = "
" + failureNum + "、账号 " + user.getUsername() + " 导入失败:";
failureMsg.append(msg + e.getMessage());
log.error(msg, e);
}
}
if (failureNum > 0){
failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:");
throw new ApiException(failureMsg.toString());
}else{
successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:");
}
return successMsg.toString();
}
@Override
public boolean changeUserStatus(SysUser user) {
checkUserAllowed(user);
SysUser existUser=checkUserDataScope(user.getId());
SysUser su=new SysUser().setId(user.getId()).setStatus(user.getStatus());
su.setUpdateBy(ShiroUtils.getSysUser().getUsername());
delCacheByUsername(existUser.getUsername());
return updateById(su);
}
@Override
public boolean changeApprove(SysUser user) {
checkUserAllowed(user);
SysUser existUser=checkUserDataScope(user.getId());
SysUser su=new SysUser().setId(user.getId()).setState(user.getState());
su.setUpdateBy(ShiroUtils.getSysUser().getUsername());
delCacheByUsername(existUser.getUsername());
return updateById(su);
}
}