refactor: 重构权限变更逻辑,修改角色、变更用户角色不再下线用户

This commit is contained in:
2024-08-31 20:32:50 +08:00
parent 25240fa819
commit ad9a6000fc
11 changed files with 120 additions and 167 deletions

View File

@@ -25,6 +25,7 @@ import java.io.Serial;
import java.io.Serializable; import java.io.Serializable;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors;
/** /**
* 登录用户信息 * 登录用户信息
@@ -109,16 +110,17 @@ public class LoginUser implements Serializable {
*/ */
private Integer passwordExpirationDays; private Integer passwordExpirationDays;
public LoginUser(Set<String> permissions, public LoginUser(Set<String> permissions, Set<RoleDTO> roles, Integer passwordExpirationDays) {
Set<String> roleCodes,
Set<RoleDTO> roles,
Integer passwordExpirationDays) {
this.permissions = permissions; this.permissions = permissions;
this.roleCodes = roleCodes; this.setRoles(roles);
this.roles = roles;
this.passwordExpirationDays = passwordExpirationDays; this.passwordExpirationDays = passwordExpirationDays;
} }
public void setRoles(Set<RoleDTO> roles) {
this.roles = roles;
this.roleCodes = roles.stream().map(RoleDTO::getCode).collect(Collectors.toSet());
}
/** /**
* 是否为管理员 * 是否为管理员
* *

View File

@@ -69,6 +69,18 @@ public class LoginHelper {
return tokenValue; return tokenValue;
} }
/**
* 更新登录用户信息
*
* @param loginUser
* 登录用户信息
* @param token 令牌
*/
public static void updateLoginUser(LoginUser loginUser, String token) {
SaHolder.getStorage().delete(CacheConstants.LOGIN_USER_KEY);
StpUtil.getTokenSessionByToken(token).set(CacheConstants.LOGIN_USER_KEY, loginUser);
}
/** /**
* 获取登录用户信息 * 获取登录用户信息
* *

View File

@@ -51,4 +51,16 @@ public class OnlineUserQuery implements Serializable {
@Schema(description = "登录时间", example = "2023-08-08 00:00:00,2023-08-08 23:59:59") @Schema(description = "登录时间", example = "2023-08-08 00:00:00,2023-08-08 23:59:59")
@DateTimeFormat(pattern = DatePattern.NORM_DATETIME_PATTERN) @DateTimeFormat(pattern = DatePattern.NORM_DATETIME_PATTERN)
private List<Date> loginTime; private List<Date> loginTime;
/**
* 用户 ID
*/
@Schema(hidden = true)
private Long userId;
/**
* 角色 ID
*/
@Schema(hidden = true)
private Long roleId;
} }

View File

@@ -59,16 +59,9 @@ public interface OnlineUserService {
LocalDateTime getLastActiveTime(String token); LocalDateTime getLastActiveTime(String token);
/** /**
* 根据角色 ID 清除 * 踢出用户
*
* @param roleId 角色 ID
*/
void cleanByRoleId(Long roleId);
/**
* 根据用户 ID 清除登录
* *
* @param userId 用户 ID * @param userId 用户 ID
*/ */
void cleanByUserId(Long userId); void kickOut(Long userId);
} }

View File

@@ -1,44 +0,0 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.continew.admin.auth.service;
import java.util.Set;
/**
* 权限业务接口
*
* @author Charles7c
* @since 2023/3/2 20:40
*/
public interface PermissionService {
/**
* 根据用户 ID 查询权限码
*
* @param userId 用户 ID
* @return 权限码集合
*/
Set<String> listPermissionByUserId(Long userId);
/**
* 根据用户 ID 查询角色编码
*
* @param userId 用户 ID
* @return 角色编码集合
*/
Set<String> listRoleCodeByUserId(Long userId);
}

View File

@@ -36,18 +36,17 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import top.continew.admin.auth.model.resp.RouteResp; import top.continew.admin.auth.model.resp.RouteResp;
import top.continew.admin.auth.service.LoginService; import top.continew.admin.auth.service.LoginService;
import top.continew.admin.auth.service.PermissionService;
import top.continew.admin.common.constant.CacheConstants; import top.continew.admin.common.constant.CacheConstants;
import top.continew.admin.common.constant.RegexConstants; import top.continew.admin.common.constant.RegexConstants;
import top.continew.admin.common.constant.SysConstants; import top.continew.admin.common.constant.SysConstants;
import top.continew.admin.common.enums.DisEnableStatusEnum; import top.continew.admin.common.enums.DisEnableStatusEnum;
import top.continew.admin.common.enums.GenderEnum; import top.continew.admin.common.enums.GenderEnum;
import top.continew.admin.system.enums.MenuTypeEnum;
import top.continew.admin.system.enums.MessageTypeEnum;
import top.continew.admin.common.model.dto.LoginUser; import top.continew.admin.common.model.dto.LoginUser;
import top.continew.admin.common.model.dto.RoleDTO; import top.continew.admin.common.model.dto.RoleDTO;
import top.continew.admin.common.util.helper.LoginHelper; import top.continew.admin.common.util.helper.LoginHelper;
import top.continew.admin.system.enums.MenuTypeEnum;
import top.continew.admin.system.enums.MessageTemplateEnum; import top.continew.admin.system.enums.MessageTemplateEnum;
import top.continew.admin.system.enums.MessageTypeEnum;
import top.continew.admin.system.enums.PasswordPolicyEnum; import top.continew.admin.system.enums.PasswordPolicyEnum;
import top.continew.admin.system.model.entity.DeptDO; import top.continew.admin.system.model.entity.DeptDO;
import top.continew.admin.system.model.entity.RoleDO; import top.continew.admin.system.model.entity.RoleDO;
@@ -81,17 +80,16 @@ import static top.continew.admin.system.enums.PasswordPolicyEnum.PASSWORD_EXPIRA
public class LoginServiceImpl implements LoginService { public class LoginServiceImpl implements LoginService {
private final ProjectProperties projectProperties; private final ProjectProperties projectProperties;
private final PasswordEncoder passwordEncoder;
private final ThreadPoolTaskExecutor threadPoolTaskExecutor;
private final UserService userService; private final UserService userService;
private final DeptService deptService; private final DeptService deptService;
private final RoleService roleService; private final RoleService roleService;
private final MenuService menuService; private final MenuService menuService;
private final PermissionService permissionService;
private final UserRoleService userRoleService; private final UserRoleService userRoleService;
private final UserSocialService userSocialService; private final UserSocialService userSocialService;
private final MessageService messageService;
private final PasswordEncoder passwordEncoder;
private final OptionService optionService; private final OptionService optionService;
private final ThreadPoolTaskExecutor threadPoolTaskExecutor; private final MessageService messageService;
@Override @Override
public String accountLogin(String username, String password, HttpServletRequest request) { public String accountLogin(String username, String password, HttpServletRequest request) {
@@ -163,7 +161,7 @@ public class LoginServiceImpl implements LoginService {
@Override @Override
public List<RouteResp> buildRouteTree(Long userId) { public List<RouteResp> buildRouteTree(Long userId) {
Set<String> roleCodeSet = permissionService.listRoleCodeByUserId(userId); Set<String> roleCodeSet = roleService.listCodeByUserId(userId);
if (CollUtil.isEmpty(roleCodeSet)) { if (CollUtil.isEmpty(roleCodeSet)) {
return new ArrayList<>(0); return new ArrayList<>(0);
} }
@@ -205,17 +203,15 @@ public class LoginServiceImpl implements LoginService {
*/ */
private String login(UserDO user) { private String login(UserDO user) {
Long userId = user.getId(); Long userId = user.getId();
CompletableFuture<Set<String>> permissionFuture = CompletableFuture.supplyAsync(() -> permissionService CompletableFuture<Set<String>> permissionFuture = CompletableFuture.supplyAsync(() -> roleService
.listPermissionByUserId(userId), threadPoolTaskExecutor); .listPermissionByUserId(userId), threadPoolTaskExecutor);
CompletableFuture<Set<String>> roleCodeFuture = CompletableFuture.supplyAsync(() -> permissionService
.listRoleCodeByUserId(userId), threadPoolTaskExecutor);
CompletableFuture<Set<RoleDTO>> roleFuture = CompletableFuture.supplyAsync(() -> roleService CompletableFuture<Set<RoleDTO>> roleFuture = CompletableFuture.supplyAsync(() -> roleService
.listByUserId(userId), threadPoolTaskExecutor); .listByUserId(userId), threadPoolTaskExecutor);
CompletableFuture<Integer> passwordExpirationDaysFuture = CompletableFuture.supplyAsync(() -> optionService CompletableFuture<Integer> passwordExpirationDaysFuture = CompletableFuture.supplyAsync(() -> optionService
.getValueByCode2Int(PASSWORD_EXPIRATION_DAYS.name())); .getValueByCode2Int(PASSWORD_EXPIRATION_DAYS.name()));
CompletableFuture.allOf(permissionFuture, roleCodeFuture, roleFuture); CompletableFuture.allOf(permissionFuture, roleFuture, passwordExpirationDaysFuture);
LoginUser loginUser = new LoginUser(permissionFuture.join(), roleCodeFuture.join(), roleFuture LoginUser loginUser = new LoginUser(permissionFuture.join(), roleFuture.join(), passwordExpirationDaysFuture
.join(), passwordExpirationDaysFuture.join()); .join());
BeanUtil.copyProperties(user, loginUser); BeanUtil.copyProperties(user, loginUser);
return LoginHelper.login(loginUser); return LoginHelper.login(loginUser);
} }

View File

@@ -18,12 +18,12 @@ package top.continew.admin.auth.service.impl;
import cn.crane4j.annotation.AutoOperate; import cn.crane4j.annotation.AutoOperate;
import cn.dev33.satoken.dao.SaTokenDao; import cn.dev33.satoken.dao.SaTokenDao;
import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.stp.StpUtil; import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil; import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import top.continew.admin.auth.model.query.OnlineUserQuery; import top.continew.admin.auth.model.query.OnlineUserQuery;
import top.continew.admin.auth.model.resp.OnlineUserResp; import top.continew.admin.auth.model.resp.OnlineUserResp;
@@ -44,10 +44,10 @@ import java.util.List;
* 在线用户业务实现 * 在线用户业务实现
* *
* @author Charles7c * @author Charles7c
* @author Lion Li<a href="https://gitee.com/dromara/RuoYi-Vue-Plus">RuoYi-Vue-Plus</a>
* @since 2023/3/25 22:49 * @since 2023/3/25 22:49
*/ */
@Service @Service
@RequiredArgsConstructor
public class OnlineUserServiceImpl implements OnlineUserService { public class OnlineUserServiceImpl implements OnlineUserService {
@Override @Override
@@ -63,18 +63,18 @@ public class OnlineUserServiceImpl implements OnlineUserService {
List<LoginUser> loginUserList = new ArrayList<>(); List<LoginUser> loginUserList = new ArrayList<>();
// 查询所有登录用户 // 查询所有登录用户
List<String> tokenKeyList = StpUtil.searchTokenValue(StringConstants.EMPTY, 0, -1, false); List<String> tokenKeyList = StpUtil.searchTokenValue(StringConstants.EMPTY, 0, -1, false);
for (String tokenKey : tokenKeyList) { tokenKeyList.parallelStream().forEach(tokenKey -> {
String token = StrUtil.subAfter(tokenKey, StringConstants.COLON, true); String token = StrUtil.subAfter(tokenKey, StringConstants.COLON, true);
// 忽略已过期或失效 Token // 忽略已过期或失效 Token
if (StpUtil.stpLogic.getTokenActiveTimeoutByToken(token) < SaTokenDao.NEVER_EXPIRE) { if (StpUtil.stpLogic.getTokenActiveTimeoutByToken(token) < SaTokenDao.NEVER_EXPIRE) {
continue; return;
} }
// 检查是否符合查询条件 // 检查是否符合查询条件
LoginUser loginUser = LoginHelper.getLoginUser(token); LoginUser loginUser = LoginHelper.getLoginUser(token);
if (this.isMatchQuery(query, loginUser)) { if (this.isMatchQuery(query, loginUser)) {
loginUserList.add(loginUser); loginUserList.add(loginUser);
} }
} });
// 设置排序 // 设置排序
CollUtil.sort(loginUserList, Comparator.comparing(LoginUser::getLoginTime).reversed()); CollUtil.sort(loginUserList, Comparator.comparing(LoginUser::getLoginTime).reversed());
return loginUserList; return loginUserList;
@@ -87,20 +87,7 @@ public class OnlineUserServiceImpl implements OnlineUserService {
} }
@Override @Override
public void cleanByRoleId(Long roleId) { public void kickOut(Long userId) {
List<LoginUser> loginUserList = this.list(new OnlineUserQuery());
loginUserList.parallelStream().forEach(u -> {
if (u.getRoles().stream().anyMatch(r -> r.getId().equals(roleId))) {
try {
StpUtil.logoutByTokenValue(u.getToken());
} catch (NotLoginException ignored) {
}
}
});
}
@Override
public void cleanByUserId(Long userId) {
if (!StpUtil.isLogin(userId)) { if (!StpUtil.isLogin(userId)) {
return; return;
} }
@@ -121,13 +108,22 @@ public class OnlineUserServiceImpl implements OnlineUserService {
flag1 = StrUtil.contains(loginUser.getUsername(), nickname) || StrUtil.contains(LoginHelper flag1 = StrUtil.contains(loginUser.getUsername(), nickname) || StrUtil.contains(LoginHelper
.getNickname(loginUser.getId()), nickname); .getNickname(loginUser.getId()), nickname);
} }
boolean flag2 = true; boolean flag2 = true;
List<Date> loginTime = query.getLoginTime(); List<Date> loginTime = query.getLoginTime();
if (CollUtil.isNotEmpty(loginTime)) { if (CollUtil.isNotEmpty(loginTime)) {
flag2 = DateUtil.isIn(DateUtil.date(loginUser.getLoginTime()).toJdkDate(), loginTime.get(0), loginTime flag2 = DateUtil.isIn(DateUtil.date(loginUser.getLoginTime()).toJdkDate(), loginTime.get(0), loginTime
.get(1)); .get(1));
} }
return flag1 && flag2; boolean flag3 = true;
Long userId = query.getUserId();
if (null != userId) {
flag3 = userId.equals(loginUser.getId());
}
boolean flag4 = true;
Long roleId = query.getRoleId();
if (null != roleId) {
flag4 = loginUser.getRoles().stream().anyMatch(r -> r.getId().equals(roleId));
}
return flag1 && flag2 && flag3 && flag4;
} }
} }

View File

@@ -1,56 +0,0 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.continew.admin.auth.service.impl;
import cn.hutool.core.collection.CollUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import top.continew.admin.auth.service.PermissionService;
import top.continew.admin.common.constant.SysConstants;
import top.continew.admin.system.service.MenuService;
import top.continew.admin.system.service.RoleService;
import java.util.Set;
/**
* 权限业务实现
*
* @author Charles7c
* @since 2023/3/2 20:40
*/
@Service
@RequiredArgsConstructor
public class PermissionServiceImpl implements PermissionService {
private final MenuService menuService;
private final RoleService roleService;
@Override
public Set<String> listPermissionByUserId(Long userId) {
Set<String> roleCodeSet = this.listRoleCodeByUserId(userId);
// 超级管理员赋予全部权限
if (roleCodeSet.contains(SysConstants.ADMIN_ROLE_CODE)) {
return CollUtil.newHashSet(SysConstants.ALL_PERMISSION);
}
return menuService.listPermissionByUserId(userId);
}
@Override
public Set<String> listRoleCodeByUserId(Long userId) {
return roleService.listCodeByUserId(userId);
}
}

View File

@@ -36,6 +36,14 @@ import java.util.Set;
*/ */
public interface RoleService extends BaseService<RoleResp, RoleDetailResp, RoleQuery, RoleReq>, IService<RoleDO> { public interface RoleService extends BaseService<RoleResp, RoleDetailResp, RoleQuery, RoleReq>, IService<RoleDO> {
/**
* 根据用户 ID 查询权限码
*
* @param userId 用户 ID
* @return 权限码集合
*/
Set<String> listPermissionByUserId(Long userId);
/** /**
* 根据 ID 列表查询 * 根据 ID 列表查询
* *

View File

@@ -26,12 +26,15 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import top.continew.admin.auth.model.query.OnlineUserQuery;
import top.continew.admin.auth.service.OnlineUserService; import top.continew.admin.auth.service.OnlineUserService;
import top.continew.admin.common.constant.CacheConstants; import top.continew.admin.common.constant.CacheConstants;
import top.continew.admin.common.constant.ContainerConstants; import top.continew.admin.common.constant.ContainerConstants;
import top.continew.admin.common.constant.SysConstants; import top.continew.admin.common.constant.SysConstants;
import top.continew.admin.common.enums.DataScopeEnum; import top.continew.admin.common.enums.DataScopeEnum;
import top.continew.admin.common.model.dto.LoginUser;
import top.continew.admin.common.model.dto.RoleDTO; import top.continew.admin.common.model.dto.RoleDTO;
import top.continew.admin.common.util.helper.LoginHelper;
import top.continew.admin.system.mapper.RoleMapper; import top.continew.admin.system.mapper.RoleMapper;
import top.continew.admin.system.model.entity.RoleDO; import top.continew.admin.system.model.entity.RoleDO;
import top.continew.admin.system.model.query.RoleQuery; import top.continew.admin.system.model.query.RoleQuery;
@@ -57,10 +60,10 @@ import java.util.stream.Collectors;
public class RoleServiceImpl extends BaseServiceImpl<RoleMapper, RoleDO, RoleResp, RoleDetailResp, RoleQuery, RoleReq> implements RoleService { public class RoleServiceImpl extends BaseServiceImpl<RoleMapper, RoleDO, RoleResp, RoleDetailResp, RoleQuery, RoleReq> implements RoleService {
private final MenuService menuService; private final MenuService menuService;
private final OnlineUserService onlineUserService;
private final RoleMenuService roleMenuService; private final RoleMenuService roleMenuService;
private final RoleDeptService roleDeptService; private final RoleDeptService roleDeptService;
private final UserRoleService userRoleService; private final UserRoleService userRoleService;
private final OnlineUserService onlineUserService;
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
@@ -92,16 +95,23 @@ public class RoleServiceImpl extends BaseServiceImpl<RoleMapper, RoleDO, RoleRes
} }
// 更新信息 // 更新信息
super.update(req, id); super.update(req, id);
// 更新关联信息 if (SysConstants.ADMIN_ROLE_CODE.equals(req.getCode())) {
if (!SysConstants.ADMIN_ROLE_CODE.equals(oldRole.getCode())) { return;
// 保存角色和菜单关联 }
boolean isSaveMenuSuccess = roleMenuService.add(req.getMenuIds(), id); // 保存角色和菜单关联
// 保存角色和部门关联 boolean isSaveMenuSuccess = roleMenuService.add(req.getMenuIds(), id);
boolean isSaveDeptSuccess = roleDeptService.add(req.getDeptIds(), id); // 保存角色和部门关联
// 如果功能权限或数据权限有变更,则清除关联的在线用户(重新登录以获取最新角色权限) boolean isSaveDeptSuccess = roleDeptService.add(req.getDeptIds(), id);
if (ObjectUtil.notEqual(req.getDataScope(), oldDataScope) || isSaveMenuSuccess || isSaveDeptSuccess) { // 如果功能权限或数据权限有变更,则更新在线用户权限信息
onlineUserService.cleanByRoleId(id); if (ObjectUtil.notEqual(req.getDataScope(), oldDataScope) || isSaveMenuSuccess || isSaveDeptSuccess) {
} OnlineUserQuery query = new OnlineUserQuery();
query.setRoleId(id);
List<LoginUser> loginUserList = onlineUserService.list(query);
loginUserList.parallelStream().forEach(loginUser -> {
loginUser.setRoles(this.listByUserId(loginUser.getId()));
loginUser.setPermissions(this.listPermissionByUserId(loginUser.getId()));
LoginHelper.updateLoginUser(loginUser, loginUser.getToken());
});
} }
} }
@@ -136,6 +146,16 @@ public class RoleServiceImpl extends BaseServiceImpl<RoleMapper, RoleDO, RoleRes
} }
} }
@Override
public Set<String> listPermissionByUserId(Long userId) {
Set<String> roleCodeSet = this.listCodeByUserId(userId);
// 超级管理员赋予全部权限
if (roleCodeSet.contains(SysConstants.ADMIN_ROLE_CODE)) {
return CollUtil.newHashSet(SysConstants.ALL_PERMISSION);
}
return menuService.listPermissionByUserId(userId);
}
@Override @Override
@ContainerMethod(namespace = ContainerConstants.USER_ROLE_NAME_LIST, type = MappingType.ORDER_OF_KEYS) @ContainerMethod(namespace = ContainerConstants.USER_ROLE_NAME_LIST, type = MappingType.ORDER_OF_KEYS)
public List<String> listNameByIds(List<Long> ids) { public List<String> listNameByIds(List<Long> ids) {

View File

@@ -52,11 +52,13 @@ import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import top.continew.admin.auth.model.query.OnlineUserQuery;
import top.continew.admin.auth.service.OnlineUserService; import top.continew.admin.auth.service.OnlineUserService;
import top.continew.admin.common.constant.CacheConstants; import top.continew.admin.common.constant.CacheConstants;
import top.continew.admin.common.constant.SysConstants; import top.continew.admin.common.constant.SysConstants;
import top.continew.admin.common.enums.DisEnableStatusEnum; import top.continew.admin.common.enums.DisEnableStatusEnum;
import top.continew.admin.common.enums.GenderEnum; import top.continew.admin.common.enums.GenderEnum;
import top.continew.admin.common.model.dto.LoginUser;
import top.continew.admin.common.util.SecureUtils; import top.continew.admin.common.util.SecureUtils;
import top.continew.admin.common.util.helper.LoginHelper; import top.continew.admin.common.util.helper.LoginHelper;
import top.continew.admin.system.mapper.UserMapper; import top.continew.admin.system.mapper.UserMapper;
@@ -102,11 +104,11 @@ import static top.continew.admin.system.enums.PasswordPolicyEnum.*;
@RequiredArgsConstructor @RequiredArgsConstructor
public class UserServiceImpl extends BaseServiceImpl<UserMapper, UserDO, UserResp, UserDetailResp, UserQuery, UserReq> implements UserService, CommonUserService { public class UserServiceImpl extends BaseServiceImpl<UserMapper, UserDO, UserResp, UserDetailResp, UserQuery, UserReq> implements UserService, CommonUserService {
private final OnlineUserService onlineUserService;
private final UserRoleService userRoleService;
private final PasswordEncoder passwordEncoder; private final PasswordEncoder passwordEncoder;
private final OptionService optionService;
private final UserPasswordHistoryService userPasswordHistoryService; private final UserPasswordHistoryService userPasswordHistoryService;
private final OnlineUserService onlineUserService;
private final OptionService optionService;
private final UserRoleService userRoleService;
private final RoleService roleService; private final RoleService roleService;
@Resource @Resource
@@ -324,9 +326,21 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, UserDO, UserRes
baseMapper.updateById(newUser); baseMapper.updateById(newUser);
// 保存用户和角色关联 // 保存用户和角色关联
boolean isSaveUserRoleSuccess = userRoleService.add(req.getRoleIds(), id); boolean isSaveUserRoleSuccess = userRoleService.add(req.getRoleIds(), id);
// 如果功能权限或数据权限有变更,则清除关联的在线用户(重新登录以获取最新角色权限) // 如果禁用用户,则踢出在线用户
if (DisEnableStatusEnum.DISABLE.equals(newStatus) || isSaveUserRoleSuccess) { if (DisEnableStatusEnum.DISABLE.equals(newStatus)) {
onlineUserService.cleanByUserId(id); onlineUserService.kickOut(id);
return;
}
// 如果角色有变更,则更新在线用户权限信息
if (isSaveUserRoleSuccess) {
OnlineUserQuery query = new OnlineUserQuery();
query.setUserId(id);
List<LoginUser> loginUserList = onlineUserService.list(query);
loginUserList.parallelStream().forEach(loginUser -> {
loginUser.setRoles(roleService.listByUserId(loginUser.getId()));
loginUser.setPermissions(roleService.listPermissionByUserId(loginUser.getId()));
LoginHelper.updateLoginUser(loginUser, loginUser.getToken());
});
} }
} }