登录后,返回 OAuth2 的 access token + refresh token

This commit is contained in:
YunaiV
2022-05-09 19:40:10 +08:00
parent 5ea9cc3cd7
commit 86e6c04e07
29 changed files with 134 additions and 680 deletions

View File

@ -1,11 +1,13 @@
package cn.iocoder.yudao.module.system.service.auth;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
import cn.iocoder.yudao.framework.test.core.util.AssertUtils;
import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi;
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth.AuthLoginReqVO;
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.auth.AuthLoginRespVO;
import cn.iocoder.yudao.module.system.dal.dataobject.auth.OAuth2AccessTokenDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.enums.logger.LoginLogTypeEnum;
import cn.iocoder.yudao.module.system.enums.logger.LoginResultEnum;
@ -26,7 +28,6 @@ import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServic
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.*;
@ -43,11 +44,11 @@ public class AuthServiceImplTest extends BaseDbUnitTest {
@MockBean
private LoginLogService loginLogService;
@MockBean
private UserSessionService userSessionService;
@MockBean
private SocialUserService socialService;
@MockBean
private SmsCodeApi smsCodeApi;
@MockBean
private OAuth2TokenService oauth2TokenService;
@MockBean
private Validator validator;
@ -188,22 +189,20 @@ public class AuthServiceImplTest extends BaseDbUnitTest {
// mock 验证码正确
when(captchaService.getCaptchaCode(reqVO.getUuid())).thenReturn(reqVO.getCode());
// mock user 数据
AdminUserDO user = randomPojo(AdminUserDO.class, o -> o.setUsername("test_username")
AdminUserDO user = randomPojo(AdminUserDO.class, o -> o.setId(1L).setUsername("test_username")
.setPassword("test_password").setStatus(CommonStatusEnum.ENABLE.getStatus()));
when(userService.getUserByUsername(eq("test_username"))).thenReturn(user);
// mock password 匹配
when(userService.isPasswordMatch(eq("test_password"), eq(user.getPassword()))).thenReturn(true);
// mock 缓存登录用户到 Redis
String token = randomString();
// when(userSessionService.createUserSession(argThat(argument -> {
// AssertUtils.assertPojoEquals(user, argument);
// return true;
// }), eq(userIp), eq(userAgent))).thenReturn(token);
// TODO 芋艿oauth2
OAuth2AccessTokenDO accessTokenDO = randomPojo(OAuth2AccessTokenDO.class, o -> o.setUserId(1L)
.setUserType(UserTypeEnum.ADMIN.getValue()));
when(oauth2TokenService.createAccessToken(eq(1L), eq(UserTypeEnum.ADMIN.getValue()), eq(1L)))
.thenReturn(accessTokenDO);
// 调用, 并断言异常
String result = authService.login(reqVO);
assertEquals(token, result);
AuthLoginRespVO loginRespVO = authService.login(reqVO);
assertPojoEquals(accessTokenDO, loginRespVO);
// 校验调用参数
verify(loginLogService).createLoginLog(
argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGIN_USERNAME.getType())
@ -216,18 +215,28 @@ public class AuthServiceImplTest extends BaseDbUnitTest {
public void testLogout_success() {
// 准备参数
String token = randomString();
LoginUser loginUser = randomPojo(LoginUser.class);
// mock
// when(userSessionService.getLoginUser(token)).thenReturn(loginUser);
// TODO @芋艿oauth2
OAuth2AccessTokenDO accessTokenDO = randomPojo(OAuth2AccessTokenDO.class, o -> o.setUserId(1L)
.setUserType(UserTypeEnum.ADMIN.getValue()));
when(oauth2TokenService.removeAccessToken(eq(token))).thenReturn(accessTokenDO);
// 调用
authService.logout(token);
// 校验调用参数
verify(userSessionService, times(1)).deleteUserSession(token);
verify(loginLogService, times(1)).createLoginLog(
argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGOUT_SELF.getType())
verify(loginLogService).createLoginLog(argThat(o -> o.getLogType().equals(LoginLogTypeEnum.LOGOUT_SELF.getType())
&& o.getResult().equals(LoginResultEnum.SUCCESS.getResult()))
);
}
@Test
public void testLogout_fail() {
// 准备参数
String token = randomString();
// 调用
authService.logout(token);
// 校验调用参数
verify(loginLogService, never()).createLoginLog(any());
}
}

View File

@ -1,139 +0,0 @@
package cn.iocoder.yudao.module.system.service.auth;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
import cn.iocoder.yudao.framework.security.config.SecurityProperties;
import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.framework.test.core.ut.BaseDbAndRedisUnitTest;
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.session.UserSessionPageReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.auth.UserSessionDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.dal.mysql.auth.UserSessionMapper;
import cn.iocoder.yudao.module.system.dal.redis.auth.LoginUserRedisDAO;
import cn.iocoder.yudao.module.system.enums.common.SexEnum;
import cn.iocoder.yudao.module.system.service.logger.LoginLogService;
import cn.iocoder.yudao.module.system.service.user.AdminUserService;
import org.junit.jupiter.api.BeforeEach;
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 static cn.hutool.core.util.RandomUtil.randomEle;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomString;
import static java.util.Collections.singletonList;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
/**
* {@link UserSessionServiceImpl} 的单元测试
*
* @author Lyon
*/
@Import({UserSessionServiceImpl.class, LoginUserRedisDAO.class})
public class UserSessionServiceImplTest extends BaseDbAndRedisUnitTest {
@Resource
private UserSessionServiceImpl userSessionService;
@Resource
private UserSessionMapper userSessionMapper;
@MockBean
private AdminUserService userService;
@MockBean
private LoginLogService loginLogService;
@Resource
private LoginUserRedisDAO loginUserRedisDAO;
@MockBean
private SecurityProperties securityProperties;
@BeforeEach
public void setUp() {
when(securityProperties.getSessionTimeout()).thenReturn(Duration.ofDays(1L));
}
@Test
public void testGetUserSessionPage_success() {
// mock 数据
AdminUserDO dbUser = randomPojo(AdminUserDO.class, o -> {
o.setSex(randomEle(SexEnum.values()).getSex());
o.setStatus(CommonStatusEnum.ENABLE.getStatus());
});
when(userService.getUsersByUsername(eq(dbUser.getUsername()))).thenReturn(singletonList(dbUser));
// 插入可被查询到的数据
String userIp = randomString();
UserSessionDO dbSession = randomPojo(UserSessionDO.class, o -> {
o.setUserId(dbUser.getId());
o.setUserType(randomEle(UserTypeEnum.values()).getValue());
o.setUserIp(userIp);
});
userSessionMapper.insert(dbSession);
// 测试 username 不匹配
userSessionMapper.insert(ObjectUtils.cloneIgnoreId(dbSession, o -> o.setUserId(123456L)));
// 测试 userIp 不匹配
userSessionMapper.insert(ObjectUtils.cloneIgnoreId(dbSession, o -> o.setUserIp("testUserIp")));
// 准备参数
UserSessionPageReqVO reqVO = new UserSessionPageReqVO();
reqVO.setUsername(dbUser.getUsername());
reqVO.setUserIp(userIp);
// 调用
PageResult<UserSessionDO> pageResult = userSessionService.getUserSessionPage(reqVO);
// 断言
assertEquals(1, pageResult.getTotal());
assertEquals(1, pageResult.getList().size());
assertPojoEquals(dbSession, pageResult.getList().get(0));
}
@Test
public void testDeleteUserSession_Token() {
// 准备参数
String token = randomString();
// mock redis 数据
loginUserRedisDAO.set(token, new LoginUser());
// mock db 数据
UserSessionDO userSession = randomPojo(UserSessionDO.class, o -> {
o.setUserType(randomEle(UserTypeEnum.values()).getValue());
o.setToken(token);
});
userSessionMapper.insert(userSession);
// 调用
userSessionService.deleteUserSession(token);
// 校验数据不存在了
assertNull(loginUserRedisDAO.get(token));
assertNull(userSessionMapper.selectOne(UserSessionDO::getToken, token));
}
@Test
public void testDeleteUserSession_Id() {
// mock db 数据
UserSessionDO userSession = randomPojo(UserSessionDO.class, o -> {
o.setUserType(randomEle(UserTypeEnum.values()).getValue());
});
userSessionMapper.insert(userSession);
// mock redis 数据
loginUserRedisDAO.set(userSession.getToken(), new LoginUser());
// 准备参数
Long id = userSession.getId();
// 调用
userSessionService.deleteUserSession(id);
// 校验数据不存在了
assertNull(loginUserRedisDAO.get(userSession.getToken()));
assertNull(userSessionMapper.selectById(id));
}
}