Commit 213adb2cf659dc657901bd16afe3c5c034e83014

Authored by 芋道源码
Committed by Gitee
2 parents 85052c1a 3b3403ff

!1536 ✨ feat(system): 为前端 UserSelect 提供多选支持

Merge pull request !1536 from 半栈幼儿员/hotfix/user
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/UserController.java
... ... @@ -21,6 +21,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
21 21 import jakarta.annotation.Resource;
22 22 import jakarta.servlet.http.HttpServletResponse;
23 23 import jakarta.validation.Valid;
  24 +import java.util.Collections;
24 25 import org.springframework.security.access.prepost.PreAuthorize;
25 26 import org.springframework.validation.annotation.Validated;
26 27 import org.springframework.web.bind.annotation.*;
... ... @@ -34,6 +35,7 @@ import java.util.Map;
34 35 import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
35 36 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
36 37 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
  38 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
37 39  
38 40 @Tag(name = "管理后台 - 用户")
39 41 @RestController
... ... @@ -112,6 +114,20 @@ public class UserController {
112 114 pageResult.getTotal()));
113 115 }
114 116  
  117 + @GetMapping("/list")
  118 + @Operation(summary = "获得用户详情列表")
  119 + @Parameter(name = "ids", description = "编号列表", required = true, example = "[1024]")
  120 + @PreAuthorize("@ss.hasPermission('system:user:query')")
  121 + public CommonResult<List<UserRespVO>> getUserList(@RequestParam("ids") List<Long> ids) {
  122 + List<AdminUserDO> list = userService.getUserList(ids);
  123 + if (CollUtil.isEmpty(list)) {
  124 + return success(Collections.emptyList());
  125 + }
  126 + // 拼接数据
  127 + Map<Long, DeptDO> deptMap = deptService.getDeptMap(convertSet(list, AdminUserDO::getDeptId));
  128 + return success(UserConvert.INSTANCE.convertList(list, deptMap));
  129 + }
  130 +
115 131 @GetMapping({"/list-all-simple", "/simple-list"})
116 132 @Operation(summary = "获取用户精简信息列表", description = "只包含被开启的用户,主要用于前端的下拉选项")
117 133 public CommonResult<List<UserSimpleRespVO>> getSimpleUserList() {
... ...
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/oauth2/OAuth2AccessTokenMapper.java
... ... @@ -6,7 +6,9 @@ import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
6 6 import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
7 7 import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.token.OAuth2AccessTokenPageReqVO;
8 8 import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
  9 +import org.apache.ibatis.annotations.Delete;
9 10 import org.apache.ibatis.annotations.Mapper;
  11 +import org.apache.ibatis.annotations.Param;
10 12  
11 13 import java.time.LocalDateTime;
12 14 import java.util.List;
... ... @@ -37,4 +39,14 @@ public interface OAuth2AccessTokenMapper extends BaseMapperX&lt;OAuth2AccessTokenDO
37 39 OAuth2AccessTokenDO::getUserType, userType);
38 40 }
39 41  
  42 + /**
  43 + * 物理删除指定过期时间之前的访问令牌
  44 + *
  45 + * @param expiresTime 最大时间
  46 + * @param limit 删除条数,防止一次删除太多
  47 + * @return 删除条数
  48 + */
  49 + @Delete("DELETE FROM system_oauth2_access_token WHERE expires_time < #{expiresTime} LIMIT #{limit}")
  50 + Integer deleteByExpiresTimeLt(@Param("expiresTime") LocalDateTime expiresTime, @Param("limit") Integer limit);
  51 +
40 52 }
... ...
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/oauth2/OAuth2RefreshTokenMapper.java
... ... @@ -4,7 +4,11 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
4 4 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
5 5 import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
6 6 import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2RefreshTokenDO;
  7 +import org.apache.ibatis.annotations.Delete;
7 8 import org.apache.ibatis.annotations.Mapper;
  9 +import org.apache.ibatis.annotations.Param;
  10 +
  11 +import java.time.LocalDateTime;
8 12  
9 13 @Mapper
10 14 public interface OAuth2RefreshTokenMapper extends BaseMapperX<OAuth2RefreshTokenDO> {
... ... @@ -19,4 +23,13 @@ public interface OAuth2RefreshTokenMapper extends BaseMapperX&lt;OAuth2RefreshToken
19 23 return selectOne(OAuth2RefreshTokenDO::getRefreshToken, refreshToken);
20 24 }
21 25  
  26 + /**
  27 + * 物理删除指定过期时间之前的刷新令牌
  28 + *
  29 + * @param expiresTime 最大时间
  30 + * @param limit 删除条数,防止一次删除太多
  31 + * @return 删除条数
  32 + */
  33 + @Delete("DELETE FROM system_oauth2_refresh_token WHERE expires_time < #{expiresTime} LIMIT #{limit}")
  34 + Integer deleteByExpiresTimeLt(@Param("expiresTime") LocalDateTime expiresTime, @Param("limit") Integer limit);
22 35 }
... ...
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/job/token/TokenCleanJob.java 0 → 100644
  1 +package cn.iocoder.yudao.module.system.job.token;
  2 +
  3 +import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;
  4 +import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
  5 +import cn.iocoder.yudao.module.system.service.oauth2.OAuth2TokenService;
  6 +import jakarta.annotation.Resource;
  7 +import lombok.extern.slf4j.Slf4j;
  8 +import org.springframework.stereotype.Component;
  9 +
  10 +/**
  11 + * 物理删除过期 N 天的令牌的 Job
  12 + *
  13 + * @author preschooler
  14 + */
  15 +@Component
  16 +@Slf4j
  17 +public class TokenCleanJob implements JobHandler {
  18 +
  19 + @Resource
  20 + private OAuth2TokenService oauth2TokenService;
  21 +
  22 + /**
  23 + * 清理过期(14)天的令牌
  24 + */
  25 + private static final Integer JOB_CLEAN_RETAIN_DAY = 14;
  26 +
  27 + /**
  28 + * 每次删除间隔的条数,如果值太高可能会造成数据库的压力过大
  29 + */
  30 + private static final Integer DELETE_LIMIT = 100;
  31 +
  32 + @Override
  33 + @TenantIgnore
  34 + public String execute(String param) {
  35 + Integer refreshCount = oauth2TokenService.cleanRefreshToken(JOB_CLEAN_RETAIN_DAY, DELETE_LIMIT);
  36 + log.info("[execute][定时执行清理刷新令牌数量 ({}) 个]", refreshCount);
  37 + Integer accessCount = oauth2TokenService.cleanAccessToken(JOB_CLEAN_RETAIN_DAY, DELETE_LIMIT);
  38 + log.info("[execute][定时执行清理访问令牌数量 ({}) 个]", accessCount);
  39 + return String.format("定时执行清理刷新令牌数量 %s 个,访问令牌数量 %s 个", refreshCount, accessCount);
  40 + }
  41 +
  42 +}
... ...
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2TokenService.java
... ... @@ -88,4 +88,19 @@ public interface OAuth2TokenService {
88 88 */
89 89 PageResult<OAuth2AccessTokenDO> getAccessTokenPage(OAuth2AccessTokenPageReqVO reqVO);
90 90  
  91 + /**
  92 + * 清理过期 exceedDay 天的刷新令牌
  93 + *
  94 + * @param exceedDay 过期多少天就进行清理
  95 + * @param deleteLimit 清理的间隔条数
  96 + */
  97 + Integer cleanRefreshToken(Integer exceedDay, Integer deleteLimit);
  98 +
  99 + /**
  100 + * 清理过期 exceedDay 天的访问令牌
  101 + *
  102 + * @param exceedDay 过期多少天就进行清理
  103 + * @param deleteLimit 清理的间隔条数
  104 + */
  105 + Integer cleanAccessToken(Integer exceedDay, Integer deleteLimit);
91 106 }
... ...
yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2TokenServiceImpl.java
... ... @@ -151,6 +151,7 @@ public class OAuth2TokenServiceImpl implements OAuth2TokenService {
151 151 oauth2AccessTokenRedisDAO.delete(accessToken);
152 152 // 删除刷新令牌
153 153 oauth2RefreshTokenMapper.deleteByRefreshToken(accessTokenDO.getRefreshToken());
  154 + oauth2AccessTokenRedisDAO.delete(accessTokenDO.getRefreshToken());
154 155 return accessTokenDO;
155 156 }
156 157  
... ... @@ -166,6 +167,7 @@ public class OAuth2TokenServiceImpl implements OAuth2TokenService {
166 167 oauth2AccessTokenRedisDAO.delete(accessToken.getAccessToken());
167 168 // 删除刷新令牌
168 169 oauth2RefreshTokenMapper.deleteByRefreshToken(accessToken.getRefreshToken());
  170 + oauth2AccessTokenRedisDAO.delete(accessToken.getRefreshToken());
169 171 });
170 172 }
171 173  
... ... @@ -241,4 +243,35 @@ public class OAuth2TokenServiceImpl implements OAuth2TokenService {
241 243 return IdUtil.fastSimpleUUID();
242 244 }
243 245  
  246 + @Override
  247 + public Integer cleanRefreshToken(Integer exceedDay, Integer deleteLimit) {
  248 + int count = 0;
  249 + LocalDateTime expireDate = LocalDateTime.now().minusDays(exceedDay);
  250 + // 循环删除,直到没有满足条件的数据
  251 + for (int i = 0; i < Short.MAX_VALUE; i++) {
  252 + int deleteCount = oauth2RefreshTokenMapper.deleteByExpiresTimeLt(expireDate, deleteLimit);
  253 + count += deleteCount;
  254 + // 达到删除预期条数,说明到底了
  255 + if (deleteCount < deleteLimit) {
  256 + break;
  257 + }
  258 + }
  259 + return count;
  260 + }
  261 +
  262 + @Override
  263 + public Integer cleanAccessToken(Integer exceedDay, Integer deleteLimit) {
  264 + int count = 0;
  265 + LocalDateTime expireDate = LocalDateTime.now().minusDays(exceedDay);
  266 + // 循环删除,直到没有满足条件的数据
  267 + for (int i = 0; i < Short.MAX_VALUE; i++) {
  268 + int deleteCount = oauth2AccessTokenMapper.deleteByExpiresTimeLt(expireDate, deleteLimit);
  269 + count += deleteCount;
  270 + // 达到删除预期条数,说明到底了
  271 + if (deleteCount < deleteLimit) {
  272 + break;
  273 + }
  274 + }
  275 + return count;
  276 + }
244 277 }
... ...