优化:优化修改角色的代码逻辑
1.变更角色编码、功能权限或数据权限后,关联在线用户会自动下线 2.优化角色和菜单关联、角色和部门关联、用户和角色关联的业务代码(增加返回结果) 3.重构在线用户功能,抽取在线用户业务实现
This commit is contained in:
parent
c5b748fe52
commit
267ad9be13
@ -73,7 +73,7 @@ public class LoginHelper {
|
|||||||
/**
|
/**
|
||||||
* 获取登录用户信息
|
* 获取登录用户信息
|
||||||
*
|
*
|
||||||
* @return /
|
* @return 登录用户信息
|
||||||
*/
|
*/
|
||||||
public static LoginUser getLoginUser() {
|
public static LoginUser getLoginUser() {
|
||||||
LoginUser loginUser = (LoginUser)SaHolder.getStorage().get(CacheConsts.LOGIN_USER_KEY);
|
LoginUser loginUser = (LoginUser)SaHolder.getStorage().get(CacheConsts.LOGIN_USER_KEY);
|
||||||
@ -85,6 +85,17 @@ public class LoginHelper {
|
|||||||
return loginUser;
|
return loginUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据 Token 获取登录用户信息
|
||||||
|
*
|
||||||
|
* @param token
|
||||||
|
* 用户 Token
|
||||||
|
* @return 登录用户信息
|
||||||
|
*/
|
||||||
|
public static LoginUser getLoginUser(String token) {
|
||||||
|
return StpUtil.getTokenSessionByToken(token).get(CacheConsts.LOGIN_USER_KEY, new LoginUser());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新登录用户信息
|
* 更新登录用户信息
|
||||||
*
|
*
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package top.charles7c.cnadmin.monitor.model.query;
|
package top.charles7c.cnadmin.auth.model.query;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package top.charles7c.cnadmin.monitor.model.vo;
|
package top.charles7c.cnadmin.auth.model.vo;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* 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.charles7c.cnadmin.auth.service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import top.charles7c.cnadmin.auth.model.query.OnlineUserQuery;
|
||||||
|
import top.charles7c.cnadmin.auth.model.vo.OnlineUserVO;
|
||||||
|
import top.charles7c.cnadmin.common.model.dto.LoginUser;
|
||||||
|
import top.charles7c.cnadmin.common.model.query.PageQuery;
|
||||||
|
import top.charles7c.cnadmin.common.model.vo.PageDataVO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在线用户业务接口
|
||||||
|
*
|
||||||
|
* @author Charles7c
|
||||||
|
* @since 2023/3/25 22:48
|
||||||
|
*/
|
||||||
|
public interface OnlineUserService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询列表
|
||||||
|
*
|
||||||
|
* @param query
|
||||||
|
* 查询条件
|
||||||
|
* @param pageQuery
|
||||||
|
* 分页查询条件
|
||||||
|
* @return 分页列表信息
|
||||||
|
*/
|
||||||
|
PageDataVO<OnlineUserVO> page(OnlineUserQuery query, PageQuery pageQuery);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询列表
|
||||||
|
*
|
||||||
|
* @param query
|
||||||
|
* 查询条件
|
||||||
|
* @return 列表信息
|
||||||
|
*/
|
||||||
|
List<LoginUser> list(OnlineUserQuery query);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据角色 ID 清除
|
||||||
|
*
|
||||||
|
* @param roleId
|
||||||
|
* 角色 ID
|
||||||
|
*/
|
||||||
|
void cleanByRoleId(Long roleId);
|
||||||
|
}
|
@ -0,0 +1,123 @@
|
|||||||
|
/*
|
||||||
|
* 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.charles7c.cnadmin.auth.service.impl;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.dao.SaTokenDao;
|
||||||
|
import cn.dev33.satoken.exception.NotLoginException;
|
||||||
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import cn.hutool.core.date.DateUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
|
||||||
|
import top.charles7c.cnadmin.auth.model.query.OnlineUserQuery;
|
||||||
|
import top.charles7c.cnadmin.auth.model.vo.OnlineUserVO;
|
||||||
|
import top.charles7c.cnadmin.auth.service.OnlineUserService;
|
||||||
|
import top.charles7c.cnadmin.common.constant.StringConsts;
|
||||||
|
import top.charles7c.cnadmin.common.model.dto.LoginUser;
|
||||||
|
import top.charles7c.cnadmin.common.model.query.PageQuery;
|
||||||
|
import top.charles7c.cnadmin.common.model.vo.PageDataVO;
|
||||||
|
import top.charles7c.cnadmin.common.util.helper.LoginHelper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在线用户业务实现类
|
||||||
|
*
|
||||||
|
* @author Charles7c
|
||||||
|
* @author Lion Li(RuoYi-Vue-Plus)
|
||||||
|
* @since 2023/3/25 22:49
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class OnlineUserServiceImpl implements OnlineUserService {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PageDataVO<OnlineUserVO> page(OnlineUserQuery query, PageQuery pageQuery) {
|
||||||
|
List<LoginUser> loginUserList = this.list(query);
|
||||||
|
List<OnlineUserVO> list = BeanUtil.copyToList(loginUserList, OnlineUserVO.class);
|
||||||
|
return PageDataVO.build(pageQuery.getPage(), pageQuery.getSize(), list);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<LoginUser> list(OnlineUserQuery query) {
|
||||||
|
List<LoginUser> loginUserList = new ArrayList<>();
|
||||||
|
// 查询所有登录用户
|
||||||
|
List<String> tokenKeyList = StpUtil.searchTokenValue(StringConsts.EMPTY, 0, -1, false);
|
||||||
|
for (String tokenKey : tokenKeyList) {
|
||||||
|
String token = StrUtil.subAfter(tokenKey, StringConsts.COLON, true);
|
||||||
|
// 忽略已过期或失效 Token
|
||||||
|
if (StpUtil.stpLogic.getTokenActivityTimeoutByToken(token) < SaTokenDao.NEVER_EXPIRE) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// 检查是否符合查询条件
|
||||||
|
LoginUser loginUser = LoginHelper.getLoginUser(token);
|
||||||
|
if (this.checkQuery(query, loginUser)) {
|
||||||
|
loginUserList.add(loginUser);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 设置排序
|
||||||
|
CollUtil.sort(loginUserList, Comparator.comparing(LoginUser::getLoginTime).reversed());
|
||||||
|
return loginUserList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void cleanByRoleId(Long roleId) {
|
||||||
|
List<LoginUser> loginUserList = this.list(new OnlineUserQuery());
|
||||||
|
loginUserList.parallelStream().forEach(u -> {
|
||||||
|
if (u.getRoleSet().stream().anyMatch(r -> r.getId().equals(roleId))) {
|
||||||
|
try {
|
||||||
|
StpUtil.logoutByTokenValue(u.getToken());
|
||||||
|
} catch (NotLoginException ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查是否符合查询条件
|
||||||
|
*
|
||||||
|
* @param query
|
||||||
|
* 查询条件
|
||||||
|
* @param loginUser
|
||||||
|
* 登录用户信息
|
||||||
|
* @return 是否符合查询条件
|
||||||
|
*/
|
||||||
|
private boolean checkQuery(OnlineUserQuery query, LoginUser loginUser) {
|
||||||
|
boolean flag1 = true;
|
||||||
|
String nickname = query.getNickname();
|
||||||
|
if (StrUtil.isNotBlank(nickname)) {
|
||||||
|
flag1 = StrUtil.contains(loginUser.getUsername(), nickname)
|
||||||
|
|| StrUtil.contains(loginUser.getNickname(), nickname);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean flag2 = true;
|
||||||
|
List<Date> loginTime = query.getLoginTime();
|
||||||
|
if (CollUtil.isNotEmpty(loginTime)) {
|
||||||
|
flag2 =
|
||||||
|
DateUtil.isIn(DateUtil.date(loginUser.getLoginTime()).toJdkDate(), loginTime.get(0), loginTime.get(1));
|
||||||
|
}
|
||||||
|
return flag1 && flag2;
|
||||||
|
}
|
||||||
|
}
|
@ -33,8 +33,9 @@ public interface RoleDeptService {
|
|||||||
* 部门 ID 列表
|
* 部门 ID 列表
|
||||||
* @param roleId
|
* @param roleId
|
||||||
* 角色 ID
|
* 角色 ID
|
||||||
|
* @return true:成功,false:无变更/失败
|
||||||
*/
|
*/
|
||||||
void save(List<Long> deptIds, Long roleId);
|
boolean save(List<Long> deptIds, Long roleId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据角色 ID 查询
|
* 根据角色 ID 查询
|
||||||
|
@ -33,8 +33,9 @@ public interface RoleMenuService {
|
|||||||
* 菜单 ID 列表
|
* 菜单 ID 列表
|
||||||
* @param roleId
|
* @param roleId
|
||||||
* 角色 ID
|
* 角色 ID
|
||||||
|
* @return true:成功,false:无变更/失败
|
||||||
*/
|
*/
|
||||||
void save(List<Long> menuIds, Long roleId);
|
boolean save(List<Long> menuIds, Long roleId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据角色 ID 查询
|
* 根据角色 ID 查询
|
||||||
|
@ -33,8 +33,9 @@ public interface UserRoleService {
|
|||||||
* 角色 ID 列表
|
* 角色 ID 列表
|
||||||
* @param userId
|
* @param userId
|
||||||
* 用户 ID
|
* 用户 ID
|
||||||
|
* @return true:成功,false:无变更/失败
|
||||||
*/
|
*/
|
||||||
void save(List<Long> roleIds, Long userId);
|
boolean save(List<Long> roleIds, Long userId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据角色 ID 列表查询
|
* 根据角色 ID 列表查询
|
||||||
|
@ -23,6 +23,8 @@ import lombok.RequiredArgsConstructor;
|
|||||||
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
|
||||||
import top.charles7c.cnadmin.system.mapper.RoleDeptMapper;
|
import top.charles7c.cnadmin.system.mapper.RoleDeptMapper;
|
||||||
import top.charles7c.cnadmin.system.model.entity.RoleDeptDO;
|
import top.charles7c.cnadmin.system.model.entity.RoleDeptDO;
|
||||||
import top.charles7c.cnadmin.system.service.RoleDeptService;
|
import top.charles7c.cnadmin.system.service.RoleDeptService;
|
||||||
@ -40,13 +42,19 @@ public class RoleDeptServiceImpl implements RoleDeptService {
|
|||||||
private final RoleDeptMapper roleDeptMapper;
|
private final RoleDeptMapper roleDeptMapper;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void save(List<Long> deptIds, Long roleId) {
|
public boolean save(List<Long> deptIds, Long roleId) {
|
||||||
|
// 检查是否有变更
|
||||||
|
List<Long> oldDeptIdList = roleDeptMapper.lambdaQuery().select(RoleDeptDO::getDeptId)
|
||||||
|
.eq(RoleDeptDO::getRoleId, roleId).list().stream().map(RoleDeptDO::getDeptId).collect(Collectors.toList());
|
||||||
|
if (CollUtil.isEmpty(CollUtil.disjunction(deptIds, oldDeptIdList))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
// 删除原有关联
|
// 删除原有关联
|
||||||
roleDeptMapper.lambdaUpdate().eq(RoleDeptDO::getRoleId, roleId).remove();
|
roleDeptMapper.lambdaUpdate().eq(RoleDeptDO::getRoleId, roleId).remove();
|
||||||
// 保存最新关联
|
// 保存最新关联
|
||||||
List<RoleDeptDO> roleDeptList =
|
List<RoleDeptDO> roleDeptList =
|
||||||
deptIds.stream().map(deptId -> new RoleDeptDO(roleId, deptId)).collect(Collectors.toList());
|
deptIds.stream().map(deptId -> new RoleDeptDO(roleId, deptId)).collect(Collectors.toList());
|
||||||
roleDeptMapper.insertBatch(roleDeptList);
|
return roleDeptMapper.insertBatch(roleDeptList);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -43,13 +43,19 @@ public class RoleMenuServiceImpl implements RoleMenuService {
|
|||||||
private final RoleMenuMapper roleMenuMapper;
|
private final RoleMenuMapper roleMenuMapper;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void save(List<Long> menuIds, Long roleId) {
|
public boolean save(List<Long> menuIds, Long roleId) {
|
||||||
|
// 检查是否有变更
|
||||||
|
List<Long> oldMenuIdList = roleMenuMapper.lambdaQuery().select(RoleMenuDO::getMenuId)
|
||||||
|
.eq(RoleMenuDO::getRoleId, roleId).list().stream().map(RoleMenuDO::getMenuId).collect(Collectors.toList());
|
||||||
|
if (CollUtil.isEmpty(CollUtil.disjunction(menuIds, oldMenuIdList))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
// 删除原有关联
|
// 删除原有关联
|
||||||
roleMenuMapper.lambdaUpdate().eq(RoleMenuDO::getRoleId, roleId).remove();
|
roleMenuMapper.lambdaUpdate().eq(RoleMenuDO::getRoleId, roleId).remove();
|
||||||
// 保存最新关联
|
// 保存最新关联
|
||||||
List<RoleMenuDO> roleMenuList =
|
List<RoleMenuDO> roleMenuList =
|
||||||
menuIds.stream().map(menuId -> new RoleMenuDO(roleId, menuId)).collect(Collectors.toList());
|
menuIds.stream().map(menuId -> new RoleMenuDO(roleId, menuId)).collect(Collectors.toList());
|
||||||
roleMenuMapper.insertBatch(roleMenuList);
|
return roleMenuMapper.insertBatch(roleMenuList);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -26,9 +26,12 @@ import org.springframework.transaction.annotation.Transactional;
|
|||||||
|
|
||||||
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.util.ObjectUtil;
|
||||||
|
|
||||||
|
import top.charles7c.cnadmin.auth.service.OnlineUserService;
|
||||||
import top.charles7c.cnadmin.common.base.BaseServiceImpl;
|
import top.charles7c.cnadmin.common.base.BaseServiceImpl;
|
||||||
import top.charles7c.cnadmin.common.constant.SysConsts;
|
import top.charles7c.cnadmin.common.constant.SysConsts;
|
||||||
|
import top.charles7c.cnadmin.common.enums.DataScopeEnum;
|
||||||
import top.charles7c.cnadmin.common.enums.DataTypeEnum;
|
import top.charles7c.cnadmin.common.enums.DataTypeEnum;
|
||||||
import top.charles7c.cnadmin.common.enums.DisEnableStatusEnum;
|
import top.charles7c.cnadmin.common.enums.DisEnableStatusEnum;
|
||||||
import top.charles7c.cnadmin.common.model.dto.RoleDTO;
|
import top.charles7c.cnadmin.common.model.dto.RoleDTO;
|
||||||
@ -54,9 +57,10 @@ import top.charles7c.cnadmin.system.service.*;
|
|||||||
public class RoleServiceImpl extends BaseServiceImpl<RoleMapper, RoleDO, RoleVO, RoleDetailVO, RoleQuery, RoleRequest>
|
public class RoleServiceImpl extends BaseServiceImpl<RoleMapper, RoleDO, RoleVO, RoleDetailVO, RoleQuery, RoleRequest>
|
||||||
implements RoleService {
|
implements RoleService {
|
||||||
|
|
||||||
|
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 MenuService menuService;
|
|
||||||
private final UserRoleService userRoleService;
|
private final UserRoleService userRoleService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -85,22 +89,30 @@ public class RoleServiceImpl extends BaseServiceImpl<RoleMapper, RoleDO, RoleVO,
|
|||||||
String code = request.getCode();
|
String code = request.getCode();
|
||||||
CheckUtils.throwIf(this.checkCodeExists(code, id), "修改失败,[{}] 已存在", code);
|
CheckUtils.throwIf(this.checkCodeExists(code, id), "修改失败,[{}] 已存在", code);
|
||||||
RoleDO oldRole = super.getById(id);
|
RoleDO oldRole = super.getById(id);
|
||||||
|
DataScopeEnum oldDataScope = oldRole.getDataScope();
|
||||||
|
String oldCode = oldRole.getCode();
|
||||||
if (DataTypeEnum.SYSTEM.equals(oldRole.getType())) {
|
if (DataTypeEnum.SYSTEM.equals(oldRole.getType())) {
|
||||||
CheckUtils.throwIfEqual(DisEnableStatusEnum.DISABLE, request.getStatus(), "[{}] 是系统内置角色,不允许禁用",
|
CheckUtils.throwIfEqual(DisEnableStatusEnum.DISABLE, request.getStatus(), "[{}] 是系统内置角色,不允许禁用",
|
||||||
oldRole.getName());
|
oldRole.getName());
|
||||||
CheckUtils.throwIfNotEqual(request.getCode(), oldRole.getCode(), "[{}] 是系统内置角色,不允许修改角色编码",
|
CheckUtils.throwIfNotEqual(request.getCode(), oldCode, "[{}] 是系统内置角色,不允许修改角色编码", oldRole.getName());
|
||||||
oldRole.getName());
|
CheckUtils.throwIfNotEqual(request.getDataScope(), oldDataScope, "[{}] 是系统内置角色,不允许修改角色数据权限",
|
||||||
CheckUtils.throwIfNotEqual(request.getDataScope(), oldRole.getDataScope(), "[{}] 是系统内置角色,不允许修改角色数据权限",
|
|
||||||
oldRole.getName());
|
oldRole.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新信息
|
// 更新信息
|
||||||
super.update(request, id);
|
super.update(request, id);
|
||||||
|
// 更新关联信息
|
||||||
if (!SysConsts.ADMIN_ROLE_CODE.equals(oldRole.getCode())) {
|
if (!SysConsts.ADMIN_ROLE_CODE.equals(oldRole.getCode())) {
|
||||||
// 保存角色和菜单关联
|
// 保存角色和菜单关联
|
||||||
roleMenuService.save(request.getMenuIds(), id);
|
boolean isSaveMenuSuccess = roleMenuService.save(request.getMenuIds(), id);
|
||||||
// 保存角色和部门关联
|
// 保存角色和部门关联
|
||||||
roleDeptService.save(request.getDeptIds(), id);
|
boolean isSaveDeptSuccess = roleDeptService.save(request.getDeptIds(), id);
|
||||||
|
// 如果角色编码、功能权限或数据权限有变更,则清除关联的在线用户(重新登录以获取最新角色权限)
|
||||||
|
if (ObjectUtil.notEqual(request.getCode(), oldCode)
|
||||||
|
|| ObjectUtil.notEqual(request.getDataScope(), oldDataScope) || isSaveMenuSuccess
|
||||||
|
|| isSaveDeptSuccess) {
|
||||||
|
onlineUserService.cleanByRoleId(id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,6 +23,8 @@ import lombok.RequiredArgsConstructor;
|
|||||||
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
|
||||||
import top.charles7c.cnadmin.system.mapper.UserRoleMapper;
|
import top.charles7c.cnadmin.system.mapper.UserRoleMapper;
|
||||||
import top.charles7c.cnadmin.system.model.entity.UserRoleDO;
|
import top.charles7c.cnadmin.system.model.entity.UserRoleDO;
|
||||||
import top.charles7c.cnadmin.system.service.UserRoleService;
|
import top.charles7c.cnadmin.system.service.UserRoleService;
|
||||||
@ -40,13 +42,19 @@ public class UserRoleServiceImpl implements UserRoleService {
|
|||||||
private final UserRoleMapper userRoleMapper;
|
private final UserRoleMapper userRoleMapper;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void save(List<Long> roleIds, Long userId) {
|
public boolean save(List<Long> roleIds, Long userId) {
|
||||||
|
// 检查是否有变更
|
||||||
|
List<Long> oldRoleIdList = userRoleMapper.lambdaQuery().select(UserRoleDO::getRoleId)
|
||||||
|
.eq(UserRoleDO::getUserId, userId).list().stream().map(UserRoleDO::getRoleId).collect(Collectors.toList());
|
||||||
|
if (CollUtil.isEmpty(CollUtil.disjunction(roleIds, oldRoleIdList))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
// 删除原有关联
|
// 删除原有关联
|
||||||
userRoleMapper.lambdaUpdate().eq(UserRoleDO::getUserId, userId).remove();
|
userRoleMapper.lambdaUpdate().eq(UserRoleDO::getUserId, userId).remove();
|
||||||
// 保存最新关联
|
// 保存最新关联
|
||||||
List<UserRoleDO> userRoleList =
|
List<UserRoleDO> userRoleList =
|
||||||
roleIds.stream().map(roleId -> new UserRoleDO(userId, roleId)).collect(Collectors.toList());
|
roleIds.stream().map(roleId -> new UserRoleDO(userId, roleId)).collect(Collectors.toList());
|
||||||
userRoleMapper.insertBatch(userRoleList);
|
return userRoleMapper.insertBatch(userRoleList);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -204,6 +204,9 @@
|
|||||||
@cancel="handleCancel"
|
@cancel="handleCancel"
|
||||||
>
|
>
|
||||||
<a-form ref="formRef" :model="form" :rules="rules" size="large">
|
<a-form ref="formRef" :model="form" :rules="rules" size="large">
|
||||||
|
<a-alert v-if="!form.disabled" type="warning" style="margin-bottom: 15px;">
|
||||||
|
变更角色编码、功能权限或数据权限后,关联在线用户会自动下线!
|
||||||
|
</a-alert>
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>基础信息</legend>
|
<legend>基础信息</legend>
|
||||||
<a-form-item label="角色名称" field="name">
|
<a-form-item label="角色名称" field="name">
|
||||||
|
@ -16,11 +16,6 @@
|
|||||||
|
|
||||||
package top.charles7c.cnadmin.webapi.controller.monitor;
|
package top.charles7c.cnadmin.webapi.controller.monitor;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
@ -30,28 +25,19 @@ import org.springframework.validation.annotation.Validated;
|
|||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||||
import cn.dev33.satoken.dao.SaTokenDao;
|
|
||||||
import cn.dev33.satoken.session.SaSession;
|
|
||||||
import cn.dev33.satoken.stp.StpUtil;
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
import cn.hutool.core.bean.BeanUtil;
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
|
||||||
import cn.hutool.core.date.DateUtil;
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
|
||||||
|
|
||||||
import top.charles7c.cnadmin.common.constant.CacheConsts;
|
import top.charles7c.cnadmin.auth.model.query.OnlineUserQuery;
|
||||||
import top.charles7c.cnadmin.common.constant.StringConsts;
|
import top.charles7c.cnadmin.auth.model.vo.OnlineUserVO;
|
||||||
import top.charles7c.cnadmin.common.model.dto.LoginUser;
|
import top.charles7c.cnadmin.auth.service.OnlineUserService;
|
||||||
import top.charles7c.cnadmin.common.model.query.PageQuery;
|
import top.charles7c.cnadmin.common.model.query.PageQuery;
|
||||||
import top.charles7c.cnadmin.common.model.vo.PageDataVO;
|
import top.charles7c.cnadmin.common.model.vo.PageDataVO;
|
||||||
import top.charles7c.cnadmin.common.model.vo.R;
|
import top.charles7c.cnadmin.common.model.vo.R;
|
||||||
import top.charles7c.cnadmin.common.util.validate.CheckUtils;
|
import top.charles7c.cnadmin.common.util.validate.CheckUtils;
|
||||||
import top.charles7c.cnadmin.monitor.model.query.OnlineUserQuery;
|
|
||||||
import top.charles7c.cnadmin.monitor.model.vo.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 在线用户 API
|
* 在线用户 API
|
||||||
*
|
*
|
||||||
* @author Lion Li(RuoYi-Vue-Plus)
|
|
||||||
* @author Charles7c
|
* @author Charles7c
|
||||||
* @since 2023/1/20 21:51
|
* @since 2023/1/20 21:51
|
||||||
*/
|
*/
|
||||||
@ -61,59 +47,13 @@ import top.charles7c.cnadmin.monitor.model.vo.*;
|
|||||||
@RequestMapping("/monitor/online/user")
|
@RequestMapping("/monitor/online/user")
|
||||||
public class OnlineUserController {
|
public class OnlineUserController {
|
||||||
|
|
||||||
|
private final OnlineUserService onlineUserService;
|
||||||
|
|
||||||
@Operation(summary = "分页查询列表")
|
@Operation(summary = "分页查询列表")
|
||||||
@SaCheckPermission("monitor:online:user:list")
|
@SaCheckPermission("monitor:online:user:list")
|
||||||
@GetMapping
|
@GetMapping
|
||||||
public R<PageDataVO<OnlineUserVO>> page(@Validated OnlineUserQuery query, @Validated PageQuery pageQuery) {
|
public R<PageDataVO<OnlineUserVO>> page(@Validated OnlineUserQuery query, @Validated PageQuery pageQuery) {
|
||||||
List<LoginUser> loginUserList = new ArrayList<>();
|
return R.ok(onlineUserService.page(query, pageQuery));
|
||||||
List<String> tokenKeyList = StpUtil.searchTokenValue(StringConsts.EMPTY, 0, -1, false);
|
|
||||||
for (String tokenKey : tokenKeyList) {
|
|
||||||
String token = StrUtil.subAfter(tokenKey, StringConsts.COLON, true);
|
|
||||||
// 忽略已过期或失效 Token
|
|
||||||
if (StpUtil.stpLogic.getTokenActivityTimeoutByToken(token) < SaTokenDao.NEVER_EXPIRE) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取 Token Session
|
|
||||||
SaSession saSession = StpUtil.getTokenSessionByToken(token);
|
|
||||||
LoginUser loginUser = saSession.get(CacheConsts.LOGIN_USER_KEY, new LoginUser());
|
|
||||||
|
|
||||||
// 检查是否符合查询条件
|
|
||||||
if (Boolean.TRUE.equals(checkQuery(query, loginUser))) {
|
|
||||||
loginUserList.add(loginUser);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建分页数据
|
|
||||||
List<OnlineUserVO> list = BeanUtil.copyToList(loginUserList, OnlineUserVO.class);
|
|
||||||
CollUtil.sort(list, Comparator.comparing(OnlineUserVO::getLoginTime).reversed());
|
|
||||||
PageDataVO<OnlineUserVO> pageDataVO = PageDataVO.build(pageQuery.getPage(), pageQuery.getSize(), list);
|
|
||||||
return R.ok(pageDataVO);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 检查是否符合查询条件
|
|
||||||
*
|
|
||||||
* @param query
|
|
||||||
* 查询条件
|
|
||||||
* @param loginUser
|
|
||||||
* 登录用户信息
|
|
||||||
* @return 是否符合查询条件
|
|
||||||
*/
|
|
||||||
private boolean checkQuery(OnlineUserQuery query, LoginUser loginUser) {
|
|
||||||
boolean flag1 = true;
|
|
||||||
String nickname = query.getNickname();
|
|
||||||
if (StrUtil.isNotBlank(nickname)) {
|
|
||||||
flag1 = loginUser.getUsername().contains(nickname) || loginUser.getNickname().contains(nickname);
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean flag2 = true;
|
|
||||||
List<Date> loginTime = query.getLoginTime();
|
|
||||||
if (CollUtil.isNotEmpty(loginTime)) {
|
|
||||||
flag2 =
|
|
||||||
DateUtil.isIn(DateUtil.date(loginUser.getLoginTime()).toJdkDate(), loginTime.get(0), loginTime.get(1));
|
|
||||||
}
|
|
||||||
return flag1 && flag2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "强退在线用户")
|
@Operation(summary = "强退在线用户")
|
||||||
|
Loading…
Reference in New Issue
Block a user