From 7ccdf86d3aa2c7354117858c619ac0fe02b4df42 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Thu, 2 Mar 2023 09:43:03 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BC=93=E5=AD=98=E6=94=B9=E9=80=A0=EF=BC=9AOA?= =?UTF-8?q?uth2Client=20=E4=BD=BF=E7=94=A8=20Redis=20=E4=BD=9C=E4=B8=BA?= =?UTF-8?q?=E7=BC=93=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/redis/TenantRedisCacheManager.java | 2 +- .../core/redis/TenantRedisKeyDefine.java | 2 +- .../dal/mysql/permission/MenuMapper.java | 2 + .../system/dal/redis/RedisKeyConstants.java | 26 ++--- .../dal/redis/common/CaptchaRedisDAO.java | 41 ------- .../auth/OAuth2ClientRefreshConsumer.java | 29 ----- .../auth/OAuth2ClientRefreshMessage.java | 21 ---- .../producer/auth/OAuth2ClientProducer.java | 26 ----- .../service/oauth2/OAuth2ClientService.java | 17 +-- .../oauth2/OAuth2ClientServiceImpl.java | 69 +++++------- .../oauth2/OAuth2ClientServiceImplTest.java | 106 ++++++++---------- .../src/main/resources/application.yaml | 1 + 12 files changed, 103 insertions(+), 239 deletions(-) delete mode 100644 yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/redis/common/CaptchaRedisDAO.java delete mode 100644 yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/consumer/auth/OAuth2ClientRefreshConsumer.java delete mode 100644 yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/message/auth/OAuth2ClientRefreshMessage.java delete mode 100644 yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/producer/auth/OAuth2ClientProducer.java diff --git a/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/redis/TenantRedisCacheManager.java b/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/redis/TenantRedisCacheManager.java index 89ce0b526c..5c4ba7ec95 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/redis/TenantRedisCacheManager.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/redis/TenantRedisCacheManager.java @@ -26,7 +26,7 @@ public class TenantRedisCacheManager extends TimeoutRedisCacheManager { * * 原因:如果只补充租户编号,可读性较差 */ - private static final String PREFIX = "t"; + public static final String PREFIX = "t"; private final TenantProperties tenantProperties; diff --git a/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/redis/TenantRedisKeyDefine.java b/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/redis/TenantRedisKeyDefine.java index c78ae44ec6..2454d4ad36 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/redis/TenantRedisKeyDefine.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/redis/TenantRedisKeyDefine.java @@ -40,7 +40,7 @@ public class TenantRedisKeyDefine extends RedisKeyDefine { @Override public String formatKey(Object... args) { - args = ArrayUtil.append(args, TenantContextHolder.getRequiredTenantId()); + args = ArrayUtil.append(args, TenantRedisCacheManager.PREFIX + TenantContextHolder.getRequiredTenantId()); return super.formatKey(args); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/permission/MenuMapper.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/permission/MenuMapper.java index 8458faa67a..9960f8c7f9 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/permission/MenuMapper.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/permission/MenuMapper.java @@ -4,11 +4,13 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.system.controller.admin.permission.vo.menu.MenuListReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.permission.MenuDO; +import com.baomidou.dynamic.datasource.annotation.Master; import org.apache.ibatis.annotations.Mapper; import java.util.List; @Mapper +@Master public interface MenuMapper extends BaseMapperX { default MenuDO selectByParentIdAndName(Long parentId, String name) { diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/redis/RedisKeyConstants.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/redis/RedisKeyConstants.java index 16862fa841..b9a6cd70c7 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/redis/RedisKeyConstants.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/redis/RedisKeyConstants.java @@ -14,23 +14,15 @@ import static cn.iocoder.yudao.framework.redis.core.RedisKeyDefine.KeyTypeEnum.S */ public interface RedisKeyConstants { - RedisKeyDefine CAPTCHA_CODE = new RedisKeyDefine("验证码的缓存", - "captcha_code:%s", // 参数为 uuid - STRING, String.class, RedisKeyDefine.TimeoutTypeEnum.DYNAMIC); - RedisKeyDefine OAUTH2_ACCESS_TOKEN = new RedisKeyDefine("访问令牌的缓存", "oauth2_access_token:%s", // 参数为访问令牌 token STRING, OAuth2AccessTokenDO.class, RedisKeyDefine.TimeoutTypeEnum.DYNAMIC); - RedisKeyDefine SOCIAL_AUTH_STATE = new RedisKeyDefine("社交登陆的 state", // 注意,它是被 JustAuth 的 justauth.type.prefix 使用到 - "social_auth_state:%s", // 参数为 state - STRING, String.class, Duration.ofHours(24)); // 值为 state - /** * 指定部门的所有子部门编号数组的缓存 * * KEY 格式:dept_children_ids::{id} - * 数据类型:String 子部门编号集合 + * VALUE 数据类型:String 子部门编号集合 */ String DEPT_CHILDREN_ID_LIST = "dept_children_ids"; @@ -38,7 +30,7 @@ public interface RedisKeyConstants { * 角色的缓存 * * KEY 格式:role::{id} - * 数据类型:String 角色编号 + * VALUE 数据类型:String 角色信息 */ String ROLE = "role"; @@ -46,7 +38,7 @@ public interface RedisKeyConstants { * 用户拥有的角色编号的缓存 * * KEY 格式:user_role_ids::{userId} - * 数据类型:String 角色编号集合 + * VALUE 数据类型:String 角色编号集合 */ String USER_ROLE_ID_LIST = "user_role_ids"; @@ -54,7 +46,7 @@ public interface RedisKeyConstants { * 拥有指定菜单的角色编号的缓存 * * KEY 格式:user_role_ids::{menuId} - * 数据类型:String 角色编号集合 + * VALUE 数据类型:String 角色编号集合 */ String MENU_ROLE_ID_LIST = "menu_role_ids"; @@ -62,8 +54,16 @@ public interface RedisKeyConstants { * 拥有权限对应的菜单编号数组的缓存 * * KEY 格式:permission_menu_ids::{permission} - * 数据类型:String 菜单编号数组 + * VALUE 数据类型:String 菜单编号数组 */ String PERMISSION_MENU_ID_LIST = "permission_menu_ids"; + /** + * OAuth2 客户端的缓存 + * + * KEY 格式:user::{id} + * VALUE 数据类型:String 客户端信息 + */ + String OAUTH_CLIENT = "oauth_client"; + } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/redis/common/CaptchaRedisDAO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/redis/common/CaptchaRedisDAO.java deleted file mode 100644 index bfcb7878b1..0000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/redis/common/CaptchaRedisDAO.java +++ /dev/null @@ -1,41 +0,0 @@ -package cn.iocoder.yudao.module.system.dal.redis.common; - -import org.springframework.data.redis.core.StringRedisTemplate; -import org.springframework.stereotype.Repository; - -import javax.annotation.Resource; -import java.time.Duration; - -import static cn.iocoder.yudao.module.system.dal.redis.RedisKeyConstants.CAPTCHA_CODE; - -/** - * 验证码的 Redis DAO - * - * @author 芋道源码 - */ -@Repository -public class CaptchaRedisDAO { - - @Resource - private StringRedisTemplate stringRedisTemplate; - - public String get(String uuid) { - String redisKey = formatKey(uuid); - return stringRedisTemplate.opsForValue().get(redisKey); - } - - public void set(String uuid, String code, Duration timeout) { - String redisKey = formatKey(uuid); - stringRedisTemplate.opsForValue().set(redisKey, code, timeout); - } - - public void delete(String uuid) { - String redisKey = formatKey(uuid); - stringRedisTemplate.delete(redisKey); - } - - private static String formatKey(String uuid) { - return String.format(CAPTCHA_CODE.getKeyTemplate(), uuid); - } - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/consumer/auth/OAuth2ClientRefreshConsumer.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/consumer/auth/OAuth2ClientRefreshConsumer.java deleted file mode 100644 index fc765c425e..0000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/consumer/auth/OAuth2ClientRefreshConsumer.java +++ /dev/null @@ -1,29 +0,0 @@ -package cn.iocoder.yudao.module.system.mq.consumer.auth; - -import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessageListener; -import cn.iocoder.yudao.module.system.mq.message.auth.OAuth2ClientRefreshMessage; -import cn.iocoder.yudao.module.system.service.oauth2.OAuth2ClientService; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -import javax.annotation.Resource; - -/** - * 针对 {@link OAuth2ClientRefreshMessage} 的消费者 - * - * @author 芋道源码 - */ -@Component -@Slf4j -public class OAuth2ClientRefreshConsumer extends AbstractChannelMessageListener { - - @Resource - private OAuth2ClientService oauth2ClientService; - - @Override - public void onMessage(OAuth2ClientRefreshMessage message) { - log.info("[onMessage][收到 OAuth2Client 刷新消息]"); - oauth2ClientService.initLocalCache(); - } - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/message/auth/OAuth2ClientRefreshMessage.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/message/auth/OAuth2ClientRefreshMessage.java deleted file mode 100644 index 3d18df1505..0000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/message/auth/OAuth2ClientRefreshMessage.java +++ /dev/null @@ -1,21 +0,0 @@ -package cn.iocoder.yudao.module.system.mq.message.auth; - -import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessage; -import lombok.Data; -import lombok.EqualsAndHashCode; - -/** - * OAuth 2.0 客户端的数据刷新 Message - * - * @author 芋道源码 - */ -@Data -@EqualsAndHashCode(callSuper = true) -public class OAuth2ClientRefreshMessage extends AbstractChannelMessage { - - @Override - public String getChannel() { - return "system.oauth2-client.refresh"; - } - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/producer/auth/OAuth2ClientProducer.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/producer/auth/OAuth2ClientProducer.java deleted file mode 100644 index 1a849efc62..0000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/mq/producer/auth/OAuth2ClientProducer.java +++ /dev/null @@ -1,26 +0,0 @@ -package cn.iocoder.yudao.module.system.mq.producer.auth; - -import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate; -import cn.iocoder.yudao.module.system.mq.message.auth.OAuth2ClientRefreshMessage; -import org.springframework.stereotype.Component; - -import javax.annotation.Resource; - -/** - * OAuth 2.0 客户端相关消息的 Producer - */ -@Component -public class OAuth2ClientProducer { - - @Resource - private RedisMQTemplate redisMQTemplate; - - /** - * 发送 {@link OAuth2ClientRefreshMessage} 消息 - */ - public void sendOAuth2ClientRefreshMessage() { - OAuth2ClientRefreshMessage message = new OAuth2ClientRefreshMessage(); - redisMQTemplate.send(message); - } - -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2ClientService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2ClientService.java index 60e9f22980..de826c261b 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2ClientService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2ClientService.java @@ -18,11 +18,6 @@ import java.util.Collection; */ public interface OAuth2ClientService { - /** - * 初始化 OAuth2Client 的本地缓存 - */ - void initLocalCache(); - /** * 创建 OAuth2 客户端 * @@ -53,6 +48,14 @@ public interface OAuth2ClientService { */ OAuth2ClientDO getOAuth2Client(Long id); + /** + * 获得 OAuth2 客户端,从缓存中 + * + * @param clientId 客户端编号 + * @return OAuth2 客户端 + */ + OAuth2ClientDO getOAuth2ClientFromCache(String clientId); + /** * 获得 OAuth2 客户端分页 * @@ -82,7 +85,7 @@ public interface OAuth2ClientService { * @param redirectUri 重定向地址 * @return 客户端 */ - OAuth2ClientDO validOAuthClientFromCache(String clientId, String clientSecret, - String authorizedGrantType, Collection scopes, String redirectUri); + OAuth2ClientDO validOAuthClientFromCache(String clientId, String clientSecret, String authorizedGrantType, + Collection scopes, String redirectUri); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2ClientServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2ClientServiceImpl.java index 970387bbb6..20a9ddaed7 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2ClientServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2ClientServiceImpl.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.system.service.oauth2; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; +import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.string.StrUtils; @@ -12,22 +13,18 @@ import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.client.OAuth2Cl import cn.iocoder.yudao.module.system.convert.auth.OAuth2ClientConvert; import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2ClientDO; import cn.iocoder.yudao.module.system.dal.mysql.oauth2.OAuth2ClientMapper; -import cn.iocoder.yudao.module.system.mq.producer.auth.OAuth2ClientProducer; +import cn.iocoder.yudao.module.system.dal.redis.RedisKeyConstants; import com.google.common.annotations.VisibleForTesting; -import lombok.Getter; -import lombok.Setter; import lombok.extern.slf4j.Slf4j; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; -import javax.annotation.PostConstruct; import javax.annotation.Resource; import java.util.Collection; -import java.util.List; -import java.util.Map; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; /** @@ -40,48 +37,21 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; @Slf4j public class OAuth2ClientServiceImpl implements OAuth2ClientService { - /** - * 客户端缓存 - * key:客户端编号 {@link OAuth2ClientDO#getClientId()} ()} - * - * 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向 - */ - @Getter // 解决单测 - @Setter // 解决单测 - private volatile Map clientCache; - @Resource private OAuth2ClientMapper oauth2ClientMapper; - @Resource - private OAuth2ClientProducer oauth2ClientProducer; - - /** - * 初始化 {@link #clientCache} 缓存 - */ - @Override - @PostConstruct - public void initLocalCache() { - // 第一步:查询数据 - List clients = oauth2ClientMapper.selectList(); - log.info("[initLocalCache][缓存 OAuth2 客户端,数量为:{}]", clients.size()); - - // 第二步:构建缓存。 - clientCache = convertMap(clients, OAuth2ClientDO::getClientId); - } - @Override public Long createOAuth2Client(OAuth2ClientCreateReqVO createReqVO) { validateClientIdExists(null, createReqVO.getClientId()); // 插入 OAuth2ClientDO oauth2Client = OAuth2ClientConvert.INSTANCE.convert(createReqVO); oauth2ClientMapper.insert(oauth2Client); - // 发送刷新消息 - oauth2ClientProducer.sendOAuth2ClientRefreshMessage(); return oauth2Client.getId(); } @Override + @CacheEvict(cacheNames = RedisKeyConstants.OAUTH_CLIENT, + allEntries = true) // allEntries 清空所有缓存,因为可能修改到 clientId 字段,不好清理 public void updateOAuth2Client(OAuth2ClientUpdateReqVO updateReqVO) { // 校验存在 validateOAuth2ClientExists(updateReqVO.getId()); @@ -91,18 +61,16 @@ public class OAuth2ClientServiceImpl implements OAuth2ClientService { // 更新 OAuth2ClientDO updateObj = OAuth2ClientConvert.INSTANCE.convert(updateReqVO); oauth2ClientMapper.updateById(updateObj); - // 发送刷新消息 - oauth2ClientProducer.sendOAuth2ClientRefreshMessage(); } @Override + @CacheEvict(cacheNames = RedisKeyConstants.OAUTH_CLIENT, + allEntries = true) // allEntries 清空所有缓存,因为 id 不是直接的缓存 key,不好清理 public void deleteOAuth2Client(Long id) { // 校验存在 validateOAuth2ClientExists(id); // 删除 oauth2ClientMapper.deleteById(id); - // 发送刷新消息 - oauth2ClientProducer.sendOAuth2ClientRefreshMessage(); } private void validateOAuth2ClientExists(Long id) { @@ -131,16 +99,22 @@ public class OAuth2ClientServiceImpl implements OAuth2ClientService { return oauth2ClientMapper.selectById(id); } + @Override + @Cacheable(cacheNames = RedisKeyConstants.OAUTH_CLIENT, key = "#clientId") + public OAuth2ClientDO getOAuth2ClientFromCache(String clientId) { + return oauth2ClientMapper.selectByClientId(clientId); + } + @Override public PageResult getOAuth2ClientPage(OAuth2ClientPageReqVO pageReqVO) { return oauth2ClientMapper.selectPage(pageReqVO); } @Override - public OAuth2ClientDO validOAuthClientFromCache(String clientId, String clientSecret, - String authorizedGrantType, Collection scopes, String redirectUri) { + public OAuth2ClientDO validOAuthClientFromCache(String clientId, String clientSecret, String authorizedGrantType, + Collection scopes, String redirectUri) { // 校验客户端存在、且开启 - OAuth2ClientDO client = clientCache.get(clientId); + OAuth2ClientDO client = getSelf().getOAuth2ClientFromCache(clientId); if (client == null) { throw exception(OAUTH2_CLIENT_NOT_EXISTS); } @@ -167,4 +141,13 @@ public class OAuth2ClientServiceImpl implements OAuth2ClientService { return client; } + /** + * 获得自身的代理对象,解决 AOP 生效问题 + * + * @return 自己 + */ + private OAuth2ClientServiceImpl getSelf() { + return SpringUtil.getBean(getClass()); + } + } diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2ClientServiceImplTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2ClientServiceImplTest.java index 3a671b0b90..49ff99f7ee 100755 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2ClientServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2ClientServiceImplTest.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.system.service.oauth2; -import cn.hutool.core.map.MapUtil; +import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; @@ -9,14 +9,12 @@ import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.client.OAuth2Cl import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.client.OAuth2ClientUpdateReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2ClientDO; import cn.iocoder.yudao.module.system.dal.mysql.oauth2.OAuth2ClientMapper; -import cn.iocoder.yudao.module.system.mq.producer.auth.OAuth2ClientProducer; import org.junit.jupiter.api.Test; -import org.springframework.boot.test.mock.mockito.MockBean; +import org.mockito.MockedStatic; import org.springframework.context.annotation.Import; import javax.annotation.Resource; import java.util.Collections; -import java.util.Map; import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; @@ -24,7 +22,8 @@ import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServic import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.verify; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mockStatic; /** * {@link OAuth2ClientServiceImpl} 的单元测试类 @@ -40,26 +39,6 @@ public class OAuth2ClientServiceImplTest extends BaseDbUnitTest { @Resource private OAuth2ClientMapper oauth2ClientMapper; - @MockBean - private OAuth2ClientProducer oauth2ClientProducer; - - @Test - public void testInitLocalCache() { - // mock 数据 - OAuth2ClientDO clientDO1 = randomPojo(OAuth2ClientDO.class); - oauth2ClientMapper.insert(clientDO1); - OAuth2ClientDO clientDO2 = randomPojo(OAuth2ClientDO.class); - oauth2ClientMapper.insert(clientDO2); - - // 调用 - oauth2ClientService.initLocalCache(); - // 断言 clientCache 缓存 - Map clientCache = oauth2ClientService.getClientCache(); - assertEquals(2, clientCache.size()); - assertPojoEquals(clientDO1, clientCache.get(clientDO1.getClientId())); - assertPojoEquals(clientDO2, clientCache.get(clientDO2.getClientId())); - } - @Test public void testCreateOAuth2Client_success() { // 准备参数 @@ -73,7 +52,6 @@ public class OAuth2ClientServiceImplTest extends BaseDbUnitTest { // 校验记录的属性是否正确 OAuth2ClientDO oAuth2Client = oauth2ClientMapper.selectById(oauth2ClientId); assertPojoEquals(reqVO, oAuth2Client); - verify(oauth2ClientProducer).sendOAuth2ClientRefreshMessage(); } @Test @@ -92,7 +70,6 @@ public class OAuth2ClientServiceImplTest extends BaseDbUnitTest { // 校验是否更新正确 OAuth2ClientDO oAuth2Client = oauth2ClientMapper.selectById(reqVO.getId()); // 获取最新的 assertPojoEquals(reqVO, oAuth2Client); - verify(oauth2ClientProducer).sendOAuth2ClientRefreshMessage(); } @Test @@ -116,7 +93,6 @@ public class OAuth2ClientServiceImplTest extends BaseDbUnitTest { oauth2ClientService.deleteOAuth2Client(id); // 校验数据不存在了 assertNull(oauth2ClientMapper.selectById(id)); - verify(oauth2ClientProducer).sendOAuth2ClientRefreshMessage(); } @Test @@ -166,6 +142,19 @@ public class OAuth2ClientServiceImplTest extends BaseDbUnitTest { assertPojoEquals(clientDO, dbClientDO); } + @Test + public void testGetOAuth2ClientFromCache() { + // mock 数据 + OAuth2ClientDO clientDO = randomPojo(OAuth2ClientDO.class); + oauth2ClientMapper.insert(clientDO); + // 准备参数 + String clientId = clientDO.getClientId(); + + // 调用,并断言 + OAuth2ClientDO dbClientDO = oauth2ClientService.getOAuth2ClientFromCache(clientId); + assertPojoEquals(clientDO, dbClientDO); + } + @Test public void testGetOAuth2ClientPage() { // mock 数据 @@ -193,36 +182,39 @@ public class OAuth2ClientServiceImplTest extends BaseDbUnitTest { @Test public void testValidOAuthClientFromCache() { - // mock 方法 - OAuth2ClientDO client = randomPojo(OAuth2ClientDO.class).setClientId("default") - .setStatus(CommonStatusEnum.ENABLE.getStatus()); - OAuth2ClientDO client02 = randomPojo(OAuth2ClientDO.class).setClientId("disable") - .setStatus(CommonStatusEnum.DISABLE.getStatus()); - Map clientCache = MapUtil.builder() - .put(client.getClientId(), client) - .put(client02.getClientId(), client02).build(); - oauth2ClientService.setClientCache(clientCache); + try (MockedStatic springUtilMockedStatic = mockStatic(SpringUtil.class)) { + springUtilMockedStatic.when(() -> SpringUtil.getBean(eq(OAuth2ClientServiceImpl.class))) + .thenReturn(oauth2ClientService); - // 调用,并断言 - assertServiceException(() -> oauth2ClientService.validOAuthClientFromCache(randomString(), - null, null, null, null), OAUTH2_CLIENT_NOT_EXISTS); - assertServiceException(() -> oauth2ClientService.validOAuthClientFromCache("disable", - null, null, null, null), OAUTH2_CLIENT_DISABLE); - assertServiceException(() -> oauth2ClientService.validOAuthClientFromCache("default", - randomString(), null, null, null), OAUTH2_CLIENT_CLIENT_SECRET_ERROR); - assertServiceException(() -> oauth2ClientService.validOAuthClientFromCache("default", - null, randomString(), null, null), OAUTH2_CLIENT_AUTHORIZED_GRANT_TYPE_NOT_EXISTS); - assertServiceException(() -> oauth2ClientService.validOAuthClientFromCache("default", - null, null, Collections.singleton(randomString()), null), OAUTH2_CLIENT_SCOPE_OVER); - assertServiceException(() -> oauth2ClientService.validOAuthClientFromCache("default", - null, null, null, "test"), OAUTH2_CLIENT_REDIRECT_URI_NOT_MATCH, "test"); - // 成功调用(1:参数完整) - OAuth2ClientDO result = oauth2ClientService.validOAuthClientFromCache(client.getClientId(), client.getSecret(), - client.getAuthorizedGrantTypes().get(0), client.getScopes(), client.getRedirectUris().get(0)); - assertPojoEquals(client, result); - // 成功调用(2:只有 clientId 参数) - result = oauth2ClientService.validOAuthClientFromCache(client.getClientId()); - assertPojoEquals(client, result); + // mock 方法 + OAuth2ClientDO client = randomPojo(OAuth2ClientDO.class).setClientId("default") + .setStatus(CommonStatusEnum.ENABLE.getStatus()); + oauth2ClientMapper.insert(client); + OAuth2ClientDO client02 = randomPojo(OAuth2ClientDO.class).setClientId("disable") + .setStatus(CommonStatusEnum.DISABLE.getStatus()); + oauth2ClientMapper.insert(client02); + + // 调用,并断言 + assertServiceException(() -> oauth2ClientService.validOAuthClientFromCache(randomString(), + null, null, null, null), OAUTH2_CLIENT_NOT_EXISTS); + assertServiceException(() -> oauth2ClientService.validOAuthClientFromCache("disable", + null, null, null, null), OAUTH2_CLIENT_DISABLE); + assertServiceException(() -> oauth2ClientService.validOAuthClientFromCache("default", + randomString(), null, null, null), OAUTH2_CLIENT_CLIENT_SECRET_ERROR); + assertServiceException(() -> oauth2ClientService.validOAuthClientFromCache("default", + null, randomString(), null, null), OAUTH2_CLIENT_AUTHORIZED_GRANT_TYPE_NOT_EXISTS); + assertServiceException(() -> oauth2ClientService.validOAuthClientFromCache("default", + null, null, Collections.singleton(randomString()), null), OAUTH2_CLIENT_SCOPE_OVER); + assertServiceException(() -> oauth2ClientService.validOAuthClientFromCache("default", + null, null, null, "test"), OAUTH2_CLIENT_REDIRECT_URI_NOT_MATCH, "test"); + // 成功调用(1:参数完整) + OAuth2ClientDO result = oauth2ClientService.validOAuthClientFromCache(client.getClientId(), client.getSecret(), + client.getAuthorizedGrantTypes().get(0), client.getScopes(), client.getRedirectUris().get(0)); + assertPojoEquals(client, result); + // 成功调用(2:只有 clientId 参数) + result = oauth2ClientService.validOAuthClientFromCache(client.getClientId()); + assertPojoEquals(client, result); + } } } diff --git a/yudao-server/src/main/resources/application.yaml b/yudao-server/src/main/resources/application.yaml index 9154a5acc9..b183fef70c 100644 --- a/yudao-server/src/main/resources/application.yaml +++ b/yudao-server/src/main/resources/application.yaml @@ -191,6 +191,7 @@ yudao: - tmp_report_data_income ignore-caches: - permission_menu_ids + - oauth_client sms-code: # 短信验证码相关的配置项 expire-times: 10m send-frequency: 1m