Merge branch 'master' of https://github.com/YunaiV/ruoyi-vue-pro
commit
8f333562af
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,14 @@
|
||||
### 请求 /system/oauth2/user/get 接口 => 成功
|
||||
GET {{baseUrl}}/system/oauth2/user/get
|
||||
Authorization: Bearer 47f9c74ec11041f193b777ebb95c3b0d
|
||||
tenant-id: {{adminTenentId}}
|
||||
|
||||
### 请求 /system/oauth2/user/update 接口 => 成功
|
||||
PUT {{baseUrl}}/system/oauth2/user/update
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer 47f9c74ec11041f193b777ebb95c3b0d
|
||||
tenant-id: {{adminTenentId}}
|
||||
|
||||
{
|
||||
"nickname": "芋道源码"
|
||||
}
|
||||
6
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/open/user/OAuth2OpenUserInfoRespVO.java → yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/user/OAuth2UserInfoRespVO.java
6
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/open/user/OAuth2OpenUserInfoRespVO.java → yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/user/OAuth2UserInfoRespVO.java
6
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/open/user/OAuth2OpenUserUpdateReqVO.java → yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/user/OAuth2UserUpdateReqVO.java
6
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/open/user/OAuth2OpenUserUpdateReqVO.java → yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/user/OAuth2UserUpdateReqVO.java
@ -0,0 +1,25 @@
|
||||
package cn.iocoder.yudao.module.system.convert.oauth2;
|
||||
|
||||
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.user.OAuth2UserInfoRespVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.user.OAuth2UserUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.dept.PostDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface OAuth2UserConvert {
|
||||
|
||||
OAuth2UserConvert INSTANCE = Mappers.getMapper(OAuth2UserConvert.class);
|
||||
|
||||
OAuth2UserInfoRespVO convert(AdminUserDO bean);
|
||||
OAuth2UserInfoRespVO.Dept convert(DeptDO dept);
|
||||
List<OAuth2UserInfoRespVO.Post> convertList(List<PostDO> list);
|
||||
|
||||
UserProfileUpdateReqVO convert(OAuth2UserUpdateReqVO bean);
|
||||
|
||||
}
|
||||
@ -0,0 +1,267 @@
|
||||
package cn.iocoder.yudao.module.system.service.oauth2;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
||||
import cn.iocoder.yudao.framework.common.util.date.DateUtils;
|
||||
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2ApproveDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2ClientDO;
|
||||
import cn.iocoder.yudao.module.system.dal.mysql.oauth2.OAuth2ApproveMapper;
|
||||
import org.assertj.core.util.Lists;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.time.Duration;
|
||||
import java.util.*;
|
||||
|
||||
import static cn.hutool.core.util.RandomUtil.*;
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.addTime;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* {@link OAuth2ApproveServiceImpl} 的单元测试类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Import(OAuth2ApproveServiceImpl.class)
|
||||
public class OAuth2ApproveServiceImplTest extends BaseDbUnitTest {
|
||||
|
||||
@Resource
|
||||
private OAuth2ApproveServiceImpl oauth2ApproveService;
|
||||
|
||||
@Resource
|
||||
private OAuth2ApproveMapper oauth2ApproveMapper;
|
||||
|
||||
@MockBean
|
||||
private OAuth2ClientService oauth2ClientService;
|
||||
|
||||
@Test
|
||||
public void checkForPreApproval_clientAutoApprove() {
|
||||
// 准备参数
|
||||
Long userId = randomLongId();
|
||||
Integer userType = randomEle(UserTypeEnum.values()).getValue();
|
||||
String clientId = randomString();
|
||||
List<String> requestedScopes = Lists.newArrayList("read");
|
||||
// mock 方法
|
||||
when(oauth2ClientService.validOAuthClientFromCache(eq(clientId)))
|
||||
.thenReturn(randomPojo(OAuth2ClientDO.class).setAutoApproveScopes(requestedScopes));
|
||||
|
||||
// 调用
|
||||
boolean success = oauth2ApproveService.checkForPreApproval(userId, userType,
|
||||
clientId, requestedScopes);
|
||||
// 断言
|
||||
assertTrue(success);
|
||||
List<OAuth2ApproveDO> result = oauth2ApproveMapper.selectList();
|
||||
assertEquals(1, result.size());
|
||||
assertEquals(userId, result.get(0).getUserId());
|
||||
assertEquals(userType, result.get(0).getUserType());
|
||||
assertEquals(clientId, result.get(0).getClientId());
|
||||
assertEquals("read", result.get(0).getScope());
|
||||
assertTrue(result.get(0).getApproved());
|
||||
assertFalse(DateUtils.isExpired(result.get(0).getExpiresTime()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkForPreApproval_approve() {
|
||||
// 准备参数
|
||||
Long userId = randomLongId();
|
||||
Integer userType = randomEle(UserTypeEnum.values()).getValue();
|
||||
String clientId = randomString();
|
||||
List<String> requestedScopes = Lists.newArrayList("read");
|
||||
// mock 方法
|
||||
when(oauth2ClientService.validOAuthClientFromCache(eq(clientId)))
|
||||
.thenReturn(randomPojo(OAuth2ClientDO.class).setAutoApproveScopes(null));
|
||||
// mock 数据
|
||||
OAuth2ApproveDO approve = randomPojo(OAuth2ApproveDO.class).setUserId(userId)
|
||||
.setUserType(userType).setClientId(clientId).setScope("read")
|
||||
.setExpiresTime(addTime(Duration.ofDays(1))).setApproved(true); // 同意
|
||||
oauth2ApproveMapper.insert(approve);
|
||||
|
||||
// 调用
|
||||
boolean success = oauth2ApproveService.checkForPreApproval(userId, userType,
|
||||
clientId, requestedScopes);
|
||||
// 断言
|
||||
assertTrue(success);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkForPreApproval_reject() {
|
||||
// 准备参数
|
||||
Long userId = randomLongId();
|
||||
Integer userType = randomEle(UserTypeEnum.values()).getValue();
|
||||
String clientId = randomString();
|
||||
List<String> requestedScopes = Lists.newArrayList("read");
|
||||
// mock 方法
|
||||
when(oauth2ClientService.validOAuthClientFromCache(eq(clientId)))
|
||||
.thenReturn(randomPojo(OAuth2ClientDO.class).setAutoApproveScopes(null));
|
||||
// mock 数据
|
||||
OAuth2ApproveDO approve = randomPojo(OAuth2ApproveDO.class).setUserId(userId)
|
||||
.setUserType(userType).setClientId(clientId).setScope("read")
|
||||
.setExpiresTime(addTime(Duration.ofDays(1))).setApproved(false); // 拒绝
|
||||
oauth2ApproveMapper.insert(approve);
|
||||
|
||||
// 调用
|
||||
boolean success = oauth2ApproveService.checkForPreApproval(userId, userType,
|
||||
clientId, requestedScopes);
|
||||
// 断言
|
||||
assertFalse(success);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateAfterApproval_none() {
|
||||
// 准备参数
|
||||
Long userId = randomLongId();
|
||||
Integer userType = randomEle(UserTypeEnum.values()).getValue();
|
||||
String clientId = randomString();
|
||||
|
||||
// 调用
|
||||
boolean success = oauth2ApproveService.updateAfterApproval(userId, userType, clientId,
|
||||
null);
|
||||
// 断言
|
||||
assertTrue(success);
|
||||
List<OAuth2ApproveDO> result = oauth2ApproveMapper.selectList();
|
||||
assertEquals(0, result.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateAfterApproval_approved() {
|
||||
// 准备参数
|
||||
Long userId = randomLongId();
|
||||
Integer userType = randomEle(UserTypeEnum.values()).getValue();
|
||||
String clientId = randomString();
|
||||
Map<String, Boolean> requestedScopes = new LinkedHashMap<>(); // 有序,方便判断
|
||||
requestedScopes.put("read", true);
|
||||
requestedScopes.put("write", false);
|
||||
// mock 方法
|
||||
|
||||
// 调用
|
||||
boolean success = oauth2ApproveService.updateAfterApproval(userId, userType, clientId,
|
||||
requestedScopes);
|
||||
// 断言
|
||||
assertTrue(success);
|
||||
List<OAuth2ApproveDO> result = oauth2ApproveMapper.selectList();
|
||||
assertEquals(2, result.size());
|
||||
// read
|
||||
assertEquals(userId, result.get(0).getUserId());
|
||||
assertEquals(userType, result.get(0).getUserType());
|
||||
assertEquals(clientId, result.get(0).getClientId());
|
||||
assertEquals("read", result.get(0).getScope());
|
||||
assertTrue(result.get(0).getApproved());
|
||||
assertFalse(DateUtils.isExpired(result.get(0).getExpiresTime()));
|
||||
// write
|
||||
assertEquals(userId, result.get(1).getUserId());
|
||||
assertEquals(userType, result.get(1).getUserType());
|
||||
assertEquals(clientId, result.get(1).getClientId());
|
||||
assertEquals("write", result.get(1).getScope());
|
||||
assertFalse(result.get(1).getApproved());
|
||||
assertFalse(DateUtils.isExpired(result.get(1).getExpiresTime()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateAfterApproval_reject() {
|
||||
// 准备参数
|
||||
Long userId = randomLongId();
|
||||
Integer userType = randomEle(UserTypeEnum.values()).getValue();
|
||||
String clientId = randomString();
|
||||
Map<String, Boolean> requestedScopes = new LinkedHashMap<>();
|
||||
requestedScopes.put("write", false);
|
||||
// mock 方法
|
||||
|
||||
// 调用
|
||||
boolean success = oauth2ApproveService.updateAfterApproval(userId, userType, clientId,
|
||||
requestedScopes);
|
||||
// 断言
|
||||
assertFalse(success);
|
||||
List<OAuth2ApproveDO> result = oauth2ApproveMapper.selectList();
|
||||
assertEquals(1, result.size());
|
||||
// write
|
||||
assertEquals(userId, result.get(0).getUserId());
|
||||
assertEquals(userType, result.get(0).getUserType());
|
||||
assertEquals(clientId, result.get(0).getClientId());
|
||||
assertEquals("write", result.get(0).getScope());
|
||||
assertFalse(result.get(0).getApproved());
|
||||
assertFalse(DateUtils.isExpired(result.get(0).getExpiresTime()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetApproveList() {
|
||||
// 准备参数
|
||||
Long userId = 10L;
|
||||
Integer userType = UserTypeEnum.ADMIN.getValue();
|
||||
String clientId = randomString();
|
||||
// mock 数据
|
||||
OAuth2ApproveDO approve = randomPojo(OAuth2ApproveDO.class).setUserId(userId)
|
||||
.setUserType(userType).setClientId(clientId).setExpiresTime(addTime(Duration.ofDays(1L)));
|
||||
oauth2ApproveMapper.insert(approve); // 未过期
|
||||
oauth2ApproveMapper.insert(ObjectUtil.clone(approve).setId(null)
|
||||
.setExpiresTime(addTime(Duration.ofDays(-1L)))); // 已过期
|
||||
|
||||
// 调用
|
||||
List<OAuth2ApproveDO> result = oauth2ApproveService.getApproveList(userId, userType, clientId);
|
||||
// 断言
|
||||
assertEquals(1, result.size());
|
||||
assertPojoEquals(approve, result.get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSaveApprove_insert() {
|
||||
// 准备参数
|
||||
Long userId = randomLongId();
|
||||
Integer userType = randomEle(UserTypeEnum.values()).getValue();
|
||||
String clientId = randomString();
|
||||
String scope = randomString();
|
||||
Boolean approved = randomBoolean();
|
||||
Date expireTime = randomDay(1, 30);
|
||||
// mock 方法
|
||||
|
||||
// 调用
|
||||
oauth2ApproveService.saveApprove(userId, userType, clientId,
|
||||
scope, approved, expireTime);
|
||||
// 断言
|
||||
List<OAuth2ApproveDO> result = oauth2ApproveMapper.selectList();
|
||||
assertEquals(1, result.size());
|
||||
assertEquals(userId, result.get(0).getUserId());
|
||||
assertEquals(userType, result.get(0).getUserType());
|
||||
assertEquals(clientId, result.get(0).getClientId());
|
||||
assertEquals(scope, result.get(0).getScope());
|
||||
assertEquals(approved, result.get(0).getApproved());
|
||||
assertEquals(expireTime, result.get(0).getExpiresTime());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSaveApprove_update() {
|
||||
// mock 数据
|
||||
OAuth2ApproveDO approve = randomPojo(OAuth2ApproveDO.class);
|
||||
oauth2ApproveMapper.insert(approve);
|
||||
// 准备参数
|
||||
Long userId = approve.getUserId();
|
||||
Integer userType = approve.getUserType();
|
||||
String clientId = approve.getClientId();
|
||||
String scope = approve.getScope();
|
||||
Boolean approved = randomBoolean();
|
||||
Date expireTime = randomDay(1, 30);
|
||||
// mock 方法
|
||||
|
||||
// 调用
|
||||
oauth2ApproveService.saveApprove(userId, userType, clientId,
|
||||
scope, approved, expireTime);
|
||||
// 断言
|
||||
List<OAuth2ApproveDO> result = oauth2ApproveMapper.selectList();
|
||||
assertEquals(1, result.size());
|
||||
assertEquals(approve.getId(), result.get(0).getId());
|
||||
assertEquals(userId, result.get(0).getUserId());
|
||||
assertEquals(userType, result.get(0).getUserType());
|
||||
assertEquals(clientId, result.get(0).getClientId());
|
||||
assertEquals(scope, result.get(0).getScope());
|
||||
assertEquals(approved, result.get(0).getApproved());
|
||||
assertEquals(expireTime, result.get(0).getExpiresTime());
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,100 @@
|
||||
package cn.iocoder.yudao.module.system.service.oauth2;
|
||||
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
||||
import cn.iocoder.yudao.framework.common.util.date.DateUtils;
|
||||
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2CodeDO;
|
||||
import cn.iocoder.yudao.module.system.dal.mysql.oauth2.OAuth2CodeMapper;
|
||||
import org.assertj.core.util.Lists;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.addTime;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
|
||||
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.OAUTH2_CODE_EXPIRE;
|
||||
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.OAUTH2_CODE_NOT_EXISTS;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
* {@link OAuth2CodeServiceImpl} 的单元测试类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Import(OAuth2CodeServiceImpl.class)
|
||||
class OAuth2CodeServiceImplTest extends BaseDbUnitTest {
|
||||
|
||||
@Resource
|
||||
private OAuth2CodeServiceImpl oauth2CodeService;
|
||||
|
||||
@Resource
|
||||
private OAuth2CodeMapper oauth2CodeMapper;
|
||||
|
||||
@Test
|
||||
public void testCreateAuthorizationCode() {
|
||||
// 准备参数
|
||||
Long userId = randomLongId();
|
||||
Integer userType = RandomUtil.randomEle(UserTypeEnum.values()).getValue();
|
||||
String clientId = randomString();
|
||||
List<String> scopes = Lists.newArrayList("read", "write");
|
||||
String redirectUri = randomString();
|
||||
String state = randomString();
|
||||
|
||||
// 调用
|
||||
OAuth2CodeDO codeDO = oauth2CodeService.createAuthorizationCode(userId, userType, clientId,
|
||||
scopes, redirectUri, state);
|
||||
// 断言
|
||||
OAuth2CodeDO dbCodeDO = oauth2CodeMapper.selectByCode(codeDO.getCode());
|
||||
assertPojoEquals(codeDO, dbCodeDO, "createTime", "updateTime", "deleted");
|
||||
assertEquals(userId, codeDO.getUserId());
|
||||
assertEquals(userType, codeDO.getUserType());
|
||||
assertEquals(clientId, codeDO.getClientId());
|
||||
assertEquals(scopes, codeDO.getScopes());
|
||||
assertEquals(redirectUri, codeDO.getRedirectUri());
|
||||
assertEquals(state, codeDO.getState());
|
||||
assertFalse(DateUtils.isExpired(codeDO.getExpiresTime()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConsumeAuthorizationCode_null() {
|
||||
// 调用,并断言
|
||||
assertServiceException(() -> oauth2CodeService.consumeAuthorizationCode(randomString()),
|
||||
OAUTH2_CODE_NOT_EXISTS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConsumeAuthorizationCode_expired() {
|
||||
// 准备参数
|
||||
String code = "test_code";
|
||||
// mock 数据
|
||||
OAuth2CodeDO codeDO = randomPojo(OAuth2CodeDO.class).setCode(code)
|
||||
.setExpiresTime(addTime(Duration.ofDays(-1)));
|
||||
oauth2CodeMapper.insert(codeDO);
|
||||
|
||||
// 调用,并断言
|
||||
assertServiceException(() -> oauth2CodeService.consumeAuthorizationCode(code),
|
||||
OAUTH2_CODE_EXPIRE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConsumeAuthorizationCode_success() {
|
||||
// 准备参数
|
||||
String code = "test_code";
|
||||
// mock 数据
|
||||
OAuth2CodeDO codeDO = randomPojo(OAuth2CodeDO.class).setCode(code)
|
||||
.setExpiresTime(addTime(Duration.ofDays(1)));
|
||||
oauth2CodeMapper.insert(codeDO);
|
||||
|
||||
// 调用
|
||||
OAuth2CodeDO result = oauth2CodeService.consumeAuthorizationCode(code);
|
||||
assertPojoEquals(codeDO, result);
|
||||
assertNull(oauth2CodeMapper.selectByCode(code));
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,289 @@
|
||||
package cn.iocoder.yudao.module.system.service.oauth2;
|
||||
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
|
||||
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.date.DateUtils;
|
||||
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
|
||||
import cn.iocoder.yudao.framework.test.core.ut.BaseDbAndRedisUnitTest;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.token.OAuth2AccessTokenPageReqVO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2ClientDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2RefreshTokenDO;
|
||||
import cn.iocoder.yudao.module.system.dal.mysql.oauth2.OAuth2AccessTokenMapper;
|
||||
import cn.iocoder.yudao.module.system.dal.mysql.oauth2.OAuth2RefreshTokenMapper;
|
||||
import cn.iocoder.yudao.module.system.dal.redis.oauth2.OAuth2AccessTokenRedisDAO;
|
||||
import org.assertj.core.util.Lists;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.context.annotation.Import;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.time.Duration;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.addTime;
|
||||
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
|
||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* {@link OAuth2TokenServiceImpl} 的单元测试类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Import({OAuth2TokenServiceImpl.class, OAuth2AccessTokenRedisDAO.class})
|
||||
public class OAuth2TokenServiceImplTest extends BaseDbAndRedisUnitTest {
|
||||
|
||||
@Resource
|
||||
private OAuth2TokenServiceImpl oauth2TokenService;
|
||||
|
||||
@Resource
|
||||
private OAuth2AccessTokenMapper oauth2AccessTokenMapper;
|
||||
@Resource
|
||||
private OAuth2RefreshTokenMapper oauth2RefreshTokenMapper;
|
||||
|
||||
@Resource
|
||||
private OAuth2AccessTokenRedisDAO oauth2AccessTokenRedisDAO;
|
||||
|
||||
@MockBean
|
||||
private OAuth2ClientService oauth2ClientService;
|
||||
|
||||
@Test
|
||||
public void testCreateAccessToken() {
|
||||
TenantContextHolder.setTenantId(0L);
|
||||
// 准备参数
|
||||
Long userId = randomLongId();
|
||||
Integer userType = RandomUtil.randomEle(UserTypeEnum.values()).getValue();
|
||||
String clientId = randomString();
|
||||
List<String> scopes = Lists.newArrayList("read", "write");
|
||||
// mock 方法
|
||||
OAuth2ClientDO clientDO = randomPojo(OAuth2ClientDO.class).setClientId(clientId)
|
||||
.setAccessTokenValiditySeconds(30).setRefreshTokenValiditySeconds(60);
|
||||
when(oauth2ClientService.validOAuthClientFromCache(eq(clientId))).thenReturn(clientDO);
|
||||
|
||||
// 调用
|
||||
OAuth2AccessTokenDO accessTokenDO = oauth2TokenService.createAccessToken(userId, userType, clientId, scopes);
|
||||
// 断言访问令牌
|
||||
OAuth2AccessTokenDO dbAccessTokenDO = oauth2AccessTokenMapper.selectByAccessToken(accessTokenDO.getAccessToken());
|
||||
assertPojoEquals(accessTokenDO, dbAccessTokenDO, "createTime", "updateTime", "deleted");
|
||||
assertEquals(userId, accessTokenDO.getUserId());
|
||||
assertEquals(userType, accessTokenDO.getUserType());
|
||||
assertEquals(clientId, accessTokenDO.getClientId());
|
||||
assertEquals(scopes, accessTokenDO.getScopes());
|
||||
assertFalse(DateUtils.isExpired(accessTokenDO.getExpiresTime()));
|
||||
// 断言访问令牌的缓存
|
||||
OAuth2AccessTokenDO redisAccessTokenDO = oauth2AccessTokenRedisDAO.get(accessTokenDO.getAccessToken());
|
||||
assertPojoEquals(accessTokenDO, redisAccessTokenDO, "createTime", "updateTime", "deleted");
|
||||
// 断言刷新令牌
|
||||
OAuth2RefreshTokenDO refreshTokenDO = oauth2RefreshTokenMapper.selectList().get(0);
|
||||
assertPojoEquals(accessTokenDO, refreshTokenDO, "id", "expiresTime", "createTime", "updateTime", "deleted");
|
||||
assertFalse(DateUtils.isExpired(refreshTokenDO.getExpiresTime()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRefreshAccessToken_null() {
|
||||
// 准备参数
|
||||
String refreshToken = randomString();
|
||||
String clientId = randomString();
|
||||
// mock 方法
|
||||
|
||||
// 调用,并断言
|
||||
assertServiceException(() -> oauth2TokenService.refreshAccessToken(refreshToken, clientId),
|
||||
new ErrorCode(400, "无效的刷新令牌"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRefreshAccessToken_clientIdError() {
|
||||
// 准备参数
|
||||
String refreshToken = randomString();
|
||||
String clientId = randomString();
|
||||
// mock 方法
|
||||
OAuth2ClientDO clientDO = randomPojo(OAuth2ClientDO.class).setClientId(clientId);
|
||||
when(oauth2ClientService.validOAuthClientFromCache(eq(clientId))).thenReturn(clientDO);
|
||||
// mock 数据(访问令牌)
|
||||
OAuth2RefreshTokenDO refreshTokenDO = randomPojo(OAuth2RefreshTokenDO.class)
|
||||
.setRefreshToken(refreshToken).setClientId("error");
|
||||
oauth2RefreshTokenMapper.insert(refreshTokenDO);
|
||||
|
||||
// 调用,并断言
|
||||
assertServiceException(() -> oauth2TokenService.refreshAccessToken(refreshToken, clientId),
|
||||
new ErrorCode(400, "刷新令牌的客户端编号不正确"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRefreshAccessToken_expired() {
|
||||
// 准备参数
|
||||
String refreshToken = randomString();
|
||||
String clientId = randomString();
|
||||
// mock 方法
|
||||
OAuth2ClientDO clientDO = randomPojo(OAuth2ClientDO.class).setClientId(clientId);
|
||||
when(oauth2ClientService.validOAuthClientFromCache(eq(clientId))).thenReturn(clientDO);
|
||||
// mock 数据(访问令牌)
|
||||
OAuth2RefreshTokenDO refreshTokenDO = randomPojo(OAuth2RefreshTokenDO.class)
|
||||
.setRefreshToken(refreshToken).setClientId(clientId)
|
||||
.setExpiresTime(addTime(Duration.ofDays(-1)));
|
||||
oauth2RefreshTokenMapper.insert(refreshTokenDO);
|
||||
|
||||
// 调用,并断言
|
||||
assertServiceException(() -> oauth2TokenService.refreshAccessToken(refreshToken, clientId),
|
||||
new ErrorCode(401, "刷新令牌已过期"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRefreshAccessToken_success() {
|
||||
TenantContextHolder.setTenantId(0L);
|
||||
// 准备参数
|
||||
String refreshToken = randomString();
|
||||
String clientId = randomString();
|
||||
// mock 方法
|
||||
OAuth2ClientDO clientDO = randomPojo(OAuth2ClientDO.class).setClientId(clientId)
|
||||
.setAccessTokenValiditySeconds(30);
|
||||
when(oauth2ClientService.validOAuthClientFromCache(eq(clientId))).thenReturn(clientDO);
|
||||
// mock 数据(访问令牌)
|
||||
OAuth2RefreshTokenDO refreshTokenDO = randomPojo(OAuth2RefreshTokenDO.class)
|
||||
.setRefreshToken(refreshToken).setClientId(clientId)
|
||||
.setExpiresTime(addTime(Duration.ofDays(1)));
|
||||
oauth2RefreshTokenMapper.insert(refreshTokenDO);
|
||||
// mock 数据(访问令牌)
|
||||
OAuth2AccessTokenDO accessTokenDO = randomPojo(OAuth2AccessTokenDO.class).setRefreshToken(refreshToken);
|
||||
oauth2AccessTokenMapper.insert(accessTokenDO);
|
||||
oauth2AccessTokenRedisDAO.set(accessTokenDO);
|
||||
|
||||
// 调用
|
||||
OAuth2AccessTokenDO newAccessTokenDO = oauth2TokenService.refreshAccessToken(refreshToken, clientId);
|
||||
// 断言,老的访问令牌被删除
|
||||
assertNull(oauth2AccessTokenMapper.selectByAccessToken(accessTokenDO.getAccessToken()));
|
||||
assertNull(oauth2AccessTokenRedisDAO.get(accessTokenDO.getAccessToken()));
|
||||
// 断言,新的访问令牌
|
||||
OAuth2AccessTokenDO dbAccessTokenDO = oauth2AccessTokenMapper.selectByAccessToken(newAccessTokenDO.getAccessToken());
|
||||
assertPojoEquals(newAccessTokenDO, dbAccessTokenDO, "createTime", "updateTime", "deleted");
|
||||
assertPojoEquals(newAccessTokenDO, refreshTokenDO, "id", "expiresTime", "createTime", "updateTime", "deleted",
|
||||
"creator", "updater");
|
||||
assertFalse(DateUtils.isExpired(newAccessTokenDO.getExpiresTime()));
|
||||
// 断言,新的访问令牌的缓存
|
||||
OAuth2AccessTokenDO redisAccessTokenDO = oauth2AccessTokenRedisDAO.get(newAccessTokenDO.getAccessToken());
|
||||
assertPojoEquals(newAccessTokenDO, redisAccessTokenDO, "createTime", "updateTime", "deleted");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAccessToken() {
|
||||
// mock 数据(访问令牌)
|
||||
OAuth2AccessTokenDO accessTokenDO = randomPojo(OAuth2AccessTokenDO.class)
|
||||
.setExpiresTime(addTime(Duration.ofDays(1)));
|
||||
oauth2AccessTokenMapper.insert(accessTokenDO);
|
||||
// 准备参数
|
||||
String accessToken = accessTokenDO.getAccessToken();
|
||||
|
||||
// 调用
|
||||
OAuth2AccessTokenDO result = oauth2TokenService.getAccessToken(accessToken);
|
||||
// 断言
|
||||
assertPojoEquals(accessTokenDO, result, "createTime", "updateTime", "deleted",
|
||||
"creator", "updater");
|
||||
assertPojoEquals(accessTokenDO, oauth2AccessTokenRedisDAO.get(accessToken), "createTime", "updateTime", "deleted",
|
||||
"creator", "updater");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCheckAccessToken_null() {
|
||||
// 调研,并断言
|
||||
assertServiceException(() -> oauth2TokenService.checkAccessToken(randomString()),
|
||||
new ErrorCode(401, "访问令牌不存在"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCheckAccessToken_expired() {
|
||||
// mock 数据(访问令牌)
|
||||
OAuth2AccessTokenDO accessTokenDO = randomPojo(OAuth2AccessTokenDO.class)
|
||||
.setExpiresTime(addTime(Duration.ofDays(-1)));
|
||||
oauth2AccessTokenMapper.insert(accessTokenDO);
|
||||
// 准备参数
|
||||
String accessToken = accessTokenDO.getAccessToken();
|
||||
|
||||
// 调研,并断言
|
||||
assertServiceException(() -> oauth2TokenService.checkAccessToken(accessToken),
|
||||
new ErrorCode(401, "访问令牌已过期"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCheckAccessToken_success() {
|
||||
// mock 数据(访问令牌)
|
||||
OAuth2AccessTokenDO accessTokenDO = randomPojo(OAuth2AccessTokenDO.class)
|
||||
.setExpiresTime(addTime(Duration.ofDays(1)));
|
||||
oauth2AccessTokenMapper.insert(accessTokenDO);
|
||||
// 准备参数
|
||||
String accessToken = accessTokenDO.getAccessToken();
|
||||
|
||||
// 调研,并断言
|
||||
OAuth2AccessTokenDO result = oauth2TokenService.getAccessToken(accessToken);
|
||||
// 断言
|
||||
assertPojoEquals(accessTokenDO, result, "createTime", "updateTime", "deleted",
|
||||
"creator", "updater");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveAccessToken_null() {
|
||||
// 调用,并断言
|
||||
assertNull(oauth2TokenService.removeAccessToken(randomString()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveAccessToken_success() {
|
||||
// mock 数据(访问令牌)
|
||||
OAuth2AccessTokenDO accessTokenDO = randomPojo(OAuth2AccessTokenDO.class)
|
||||
.setExpiresTime(addTime(Duration.ofDays(1)));
|
||||
oauth2AccessTokenMapper.insert(accessTokenDO);
|
||||
// mock 数据(刷新令牌)
|
||||
OAuth2RefreshTokenDO refreshTokenDO = randomPojo(OAuth2RefreshTokenDO.class)
|
||||
.setRefreshToken(accessTokenDO.getRefreshToken());
|
||||
oauth2RefreshTokenMapper.insert(refreshTokenDO);
|
||||
// 调用
|
||||
OAuth2AccessTokenDO result = oauth2TokenService.removeAccessToken(accessTokenDO.getAccessToken());
|
||||
assertPojoEquals(accessTokenDO, result, "createTime", "updateTime", "deleted",
|
||||
"creator", "updater");
|
||||
// 断言数据
|
||||
assertNull(oauth2AccessTokenMapper.selectByAccessToken(accessTokenDO.getAccessToken()));
|
||||
assertNull(oauth2RefreshTokenMapper.selectByRefreshToken(accessTokenDO.getRefreshToken()));
|
||||
assertNull(oauth2AccessTokenRedisDAO.get(accessTokenDO.getAccessToken()));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testGetAccessTokenPage() {
|
||||
// mock 数据
|
||||
OAuth2AccessTokenDO dbAccessToken = randomPojo(OAuth2AccessTokenDO.class, o -> { // 等会查询到
|
||||
o.setUserId(10L);
|
||||
o.setUserType(1);
|
||||
o.setClientId("test_client");
|
||||
o.setExpiresTime(DateUtils.addTime(Duration.ofDays(1)));
|
||||
});
|
||||
oauth2AccessTokenMapper.insert(dbAccessToken);
|
||||
// 测试 userId 不匹配
|
||||
oauth2AccessTokenMapper.insert(cloneIgnoreId(dbAccessToken, o -> o.setUserId(20L)));
|
||||
// 测试 userType 不匹配
|
||||
oauth2AccessTokenMapper.insert(cloneIgnoreId(dbAccessToken, o -> o.setUserType(2)));
|
||||
// 测试 userType 不匹配
|
||||
oauth2AccessTokenMapper.insert(cloneIgnoreId(dbAccessToken, o -> o.setClientId("it_client")));
|
||||
// 测试 expireTime 不匹配
|
||||
oauth2AccessTokenMapper.insert(cloneIgnoreId(dbAccessToken, o -> o.setExpiresTime(new Date())));
|
||||
// 准备参数
|
||||
OAuth2AccessTokenPageReqVO reqVO = new OAuth2AccessTokenPageReqVO();
|
||||
reqVO.setUserId(10L);
|
||||
reqVO.setUserType(1);
|
||||
reqVO.setClientId("test");
|
||||
|
||||
// 调用
|
||||
PageResult<OAuth2AccessTokenDO> pageResult = oauth2TokenService.getAccessTokenPage(reqVO);
|
||||
// 断言
|
||||
assertEquals(1, pageResult.getTotal());
|
||||
assertEquals(1, pageResult.getList().size());
|
||||
assertPojoEquals(dbAccessToken, pageResult.getList().get(0));
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue