package com.gkhy.safePlatform.account.service.impl;
|
|
import com.alibaba.fastjson.JSONArray;
|
import com.gkhy.safePlatform.account.entity.enterprise.DepartmentInfoDO;
|
import com.gkhy.safePlatform.account.entity.user.*;
|
import com.gkhy.safePlatform.account.enums.RoleStatusEnum;
|
import com.gkhy.safePlatform.account.enums.UserStatusEnum;
|
import com.gkhy.safePlatform.account.model.dto.req.AccountPwdChangeReqDTO;
|
import com.gkhy.safePlatform.account.service.AuthService;
|
import com.gkhy.safePlatform.account.service.RedisService;
|
import com.gkhy.safePlatform.account.service.baseService.*;
|
import com.gkhy.safePlatform.account.utils.TokenUtil;
|
import com.gkhy.safePlatform.account.utils.MenuUtil;
|
import com.gkhy.safePlatform.account.utils.PasswordUtil;
|
import com.gkhy.safePlatform.account.model.dto.req.LoginReqDTO;
|
import com.gkhy.safePlatform.account.model.dto.resp.MenuRespDTO;
|
import com.gkhy.safePlatform.account.model.dto.resp.UserLoginRespDTO;
|
import com.gkhy.safePlatform.commons.co.ContextCacheUser;
|
import com.gkhy.safePlatform.commons.enums.RedisKeyEnum;
|
import com.gkhy.safePlatform.commons.enums.ResultCodes;
|
import com.gkhy.safePlatform.commons.enums.UserTypeEnum;
|
import com.gkhy.safePlatform.commons.exception.BusinessException;
|
import com.gkhy.safePlatform.commons.utils.StringUtils;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
import org.springframework.security.core.GrantedAuthority;
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.userdetails.UserDetails;
|
import org.springframework.stereotype.Service;
|
|
import java.util.ArrayList;
|
import java.util.Collections;
|
import java.util.List;
|
|
@Service("authService")
|
public class AuthServiceImpl implements AuthService {
|
|
@Autowired
|
private UserInfoService userInfoService;
|
@Autowired
|
private RoleInfoService roleInfoService;
|
@Autowired
|
private PermissionInfoService permissionInfoService;
|
@Autowired
|
private MenuInfoService menuInfoService;
|
@Autowired
|
private TokenUtil tokenConfig;
|
@Autowired
|
private RedisService redisService;
|
@Autowired
|
private DepartmentInfoService departmentInfoService;
|
@Autowired
|
private PositionInfoService positionInfoService;
|
|
|
|
/**
|
* @Description: 登录
|
*/
|
@Override
|
public UserLoginRespDTO authLogin(LoginReqDTO loginParam) {
|
|
// todo 根据入参判断用什么登录
|
String usernameParam = loginParam.getUsername();
|
// 用户名不能为空
|
if (StringUtils.isBlank(usernameParam)) {
|
throw new BusinessException(ResultCodes.CLIENT_ACCOUNT_USERNAME_NULL);
|
}
|
String username = usernameParam.trim();
|
UserInfo userDetail = userInfoService.getUserByUsername(username);
|
// 用户不存在
|
if (userDetail == null) {
|
throw new BusinessException(ResultCodes.CLIENT_ACCOUNT_NOT_EXIST);
|
}
|
// 用户状态 以后可能会有离职、冻结等状态
|
if (!userDetail.getStatus().equals(UserStatusEnum.VALID.getCode())) {
|
throw new BusinessException(ResultCodes.CLIENT_ACCOUNT_NOT_EXIST);
|
}
|
// 密码不为空
|
if (StringUtils.isBlank(loginParam.getPassword())) {
|
throw new BusinessException(ResultCodes.CLIENT_PASSWORD_NULL);
|
}
|
String password = loginParam.getPassword().trim();
|
// 密码匹配
|
if (!PasswordUtil.match(password, userDetail.getSalt(), userDetail.getHash())) {
|
throw new BusinessException(ResultCodes.CLIENT_PASSWORD_ERROR);
|
}
|
// todo 用户过期
|
|
|
// 用户role 需要分配
|
RoleInfoDO roleInfo = roleInfoService.getRoleInfoDOById(userDetail.getRoleId());
|
if (roleInfo == null) {
|
throw new BusinessException(ResultCodes.CLIENT_ACCOUNT_HAS_NO_ROLE);
|
}
|
// 用户dep
|
DepartmentInfoDO department = new DepartmentInfoDO();
|
if (userDetail.getDepId() != null) {
|
department = departmentInfoService.getDepartmentInfoDOById(userDetail.getDepId());
|
}
|
// 用户岗位
|
PositionInfoDO position = new PositionInfoDO();
|
if (userDetail.getPositionId() != null) {
|
position = positionInfoService.getPositionInfoById(userDetail.getPositionId());
|
}
|
|
// security对象中存入登陆者信息
|
List<GrantedAuthority> authorities = new ArrayList<>();
|
// role
|
authorities.add(new SimpleGrantedAuthority("ROLE_"+ roleInfo.getCode()));
|
|
// permission
|
List<PermissionInfo> permissions = this.getUserPermissionByUserId(userDetail.getUid());
|
for (PermissionInfo permission : permissions) {
|
SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority(permission.getCode());
|
authorities.add(simpleGrantedAuthority);
|
}
|
|
// 生成 accessToken
|
String accessToken = TokenUtil.makeToken(username,userDetail.getUid());
|
|
// 存入 redis
|
String accessTokenKey = RedisKeyEnum.authKey(RedisKeyEnum.AUTH_TOKEN, userDetail.getUid());
|
String authoritiesKey = RedisKeyEnum.authKey(RedisKeyEnum.AUTH_AUTHORITIES, userDetail.getUid());
|
|
ContextCacheUser contextCacheUser = new ContextCacheUser(
|
// 用户uid
|
userDetail.getUid(),
|
// 用户基本信息
|
userDetail.getUsername(), userDetail.getRealName(), userDetail.getPhone(), userDetail.getEmail(),
|
// 用户角色信息
|
roleInfo.getId(), roleInfo.getCode(),
|
// 用户部门信息
|
department.getId(), department.getName(),
|
// 用户岗位信息
|
position.getId(), position.getCode(),
|
// 用户类型
|
userDetail.getType(),
|
// token
|
accessToken);
|
// 1.通行认证:auth:token:access
|
redisService.setCacheUserAndExpireTime(accessTokenKey, contextCacheUser, tokenConfig.getExpiration());
|
// 2.角色权限:auth:authorities
|
redisService.setCacheAuthorityAndExpireTime(authoritiesKey, authorities, tokenConfig.getExpiration());
|
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userDetail, accessToken,authorities);
|
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
|
|
return new UserLoginRespDTO(
|
userDetail.getUid(),
|
userDetail.getUsername(),
|
userDetail.getRealName(),
|
userDetail.getType(),
|
userDetail.getStatus(),
|
userDetail.getPhone(),
|
userDetail.getEmail(),
|
department.getName(),
|
position.getName(),
|
Collections.singletonList(roleInfo.getCode()),
|
accessToken,
|
department.getId()
|
);
|
}
|
|
@Override
|
public List<PermissionInfo> getUserPermissionByUserId(Long userId) {
|
if (userId == null) {
|
throw new BusinessException(ResultCodes.CLIENT_PARAM_NULL);
|
}
|
return permissionInfoService.getPermissionsByUserId(userId);
|
}
|
|
@Override
|
public UserInfo getUserInfoByUserId(Long userId) {
|
if (userId == null) {
|
throw new BusinessException(ResultCodes.CLIENT_PARAM_NULL);
|
}
|
return userInfoService.getUserByUserId(userId);
|
}
|
|
|
/**
|
* @Description: 根据用户名登出用户
|
*/
|
@Override
|
public void authLogout(Long userId) {
|
assert userId != null;
|
String accessTokenKey = RedisKeyEnum.authKey(RedisKeyEnum.AUTH_TOKEN, userId);
|
// 1.删除通行认证:auth:token:access
|
redisService.cleanCacheUserByKey(accessTokenKey);
|
// 2.删除用户权限
|
String authoritiesKey = RedisKeyEnum.authKey(RedisKeyEnum.AUTH_AUTHORITIES, userId);
|
redisService.cleanCacheAuthorityByKey(authoritiesKey);
|
|
}
|
|
@Override
|
public UserInfo getUserByUserId(Long userId) {
|
if (userId == null) {
|
throw new BusinessException(ResultCodes.CLIENT_PARAM_NULL);
|
}
|
return userInfoService.getUserByUserId(userId);
|
}
|
|
|
@Override
|
public UserDetails getUserDetailsByUsername(String username) {
|
return userInfoService.getUserByUsername(username);
|
}
|
|
@Override
|
public void pwdChange(ContextCacheUser currentUser, AccountPwdChangeReqDTO reqDTO) {
|
if (reqDTO.getUid() == null) {
|
throw new BusinessException(ResultCodes.CLIENT_PARAM_NULL);
|
}
|
if (StringUtils.isBlank(reqDTO.getNewPassword())) {
|
throw new BusinessException(ResultCodes.CLIENT_PASSWORD_NULL);
|
}
|
String newPassword = reqDTO.getNewPassword().trim();
|
// todo 密码正则
|
UserInfo userInfo = userInfoService.getUserByUserId(reqDTO.getUid());
|
if (userInfo == null) {
|
throw new BusinessException(ResultCodes.CLIENT_ACCOUNT_NOT_EXIST);
|
}
|
if (!userInfo.getStatus().equals(UserStatusEnum.VALID.getCode())) {
|
throw new BusinessException(ResultCodes.CLIENT_ACCOUNT_NOT_EXIST);
|
}
|
|
String salt = PasswordUtil.makeSalt();
|
String hash = PasswordUtil.makePassword(newPassword, salt);
|
userInfoService.updatePassword(reqDTO.getUid(), salt, hash);
|
|
}
|
|
|
@Override
|
public RoleInfo getUserRoleByUserId(Long userId) {
|
if (userId == null) {
|
throw new BusinessException(ResultCodes.CLIENT_PARAM_NULL);
|
}
|
RoleInfo roleInfo = roleInfoService.getRoleInfoByUserId(userId);
|
if (roleInfo == null) {
|
throw new BusinessException(ResultCodes.CLIENT_ROLE_NOT_EXIST);
|
}
|
assert roleInfo.getStatus() != null;
|
RoleStatusEnum status = RoleStatusEnum.parse(roleInfo.getStatus());
|
if (status != RoleStatusEnum.ENABLED) {
|
throw new BusinessException(ResultCodes.CLIENT_ROLE_CODE_NOT_ON);
|
}
|
return roleInfo;
|
}
|
|
|
@Override
|
public List<MenuRespDTO> getUserMenuTreeByUserIdAndProjectId(ContextCacheUser currentUser, Long projectId){
|
if (currentUser.getUid() == null) {
|
throw new BusinessException(ResultCodes.CLIENT_PARAM_NULL);
|
}
|
|
// RoleInfo roleInfo = roleInfoService.getRoleInfoByUserId(currentUser.getUid());
|
// // 角色判断
|
// if (roleInfo == null) {
|
// throw new BusinessException(ResultCodes.CLIENT_ACCOUNT_HAS_NO_ROLE);
|
// }
|
|
List<MenuInfoDO> allMenu;
|
// 1.redis获取所有菜单
|
String oo = redisService.getCacheMenuByKey(RedisKeyEnum.AUTH_MENU.getKey());
|
if (oo != null) {
|
allMenu = JSONArray.parseArray(oo, MenuInfoDO.class);
|
}else{
|
// 2.redis没有则mysql获取
|
allMenu = menuInfoService.getAllMenu();
|
redisService.setCacheMenuAndExpireTime(RedisKeyEnum.AUTH_MENU.getKey(), allMenu, tokenConfig.getExpiration());
|
}
|
|
|
// // 如果project不为空 判断project是否为角色所拥有
|
// if (projectId != null) {
|
// RoleProjectInfo roleProject = roleProjectInfoService.getRoleProjectInfo(roleInfo.getId(), projectId);
|
// if (roleProject == null) {
|
// // 需要返回公共页面
|
// return MenuUtil.generatePublicTree(allMenu);
|
// }
|
// }
|
// 1.根据用户类型判断最高权限
|
// 1.1 type 为 admin的拥有最高菜单可分配和可视权限 不受角色code影响
|
List<MenuInfoDO> userMenu = allMenu;
|
assert currentUser.getType() != null;
|
if (!currentUser.getType().equals(UserTypeEnum.ADMIN.getCode())) {
|
userMenu = MenuUtil.getUserMenuFromAllMenu(allMenu, currentUser.getRoleCode());
|
}
|
|
return MenuUtil.generateMenuTree(userMenu, projectId);
|
}
|
|
|
|
}
|