|
@@ -11,7 +11,9 @@ import com.ruoyi.common.core.domain.AjaxResult;
|
|
|
import com.ruoyi.common.core.redis.RedisCache;
|
|
import com.ruoyi.common.core.redis.RedisCache;
|
|
|
import com.ruoyi.common.exception.ServiceException;
|
|
import com.ruoyi.common.exception.ServiceException;
|
|
|
import com.ruoyi.app.user.dto.OAuthBindDto;
|
|
import com.ruoyi.app.user.dto.OAuthBindDto;
|
|
|
-import com.ruoyi.app.utils.oauth.LineOAuthProperties;
|
|
|
|
|
|
|
+import com.ruoyi.app.user.dto.OAuthLoginDto;
|
|
|
|
|
+import com.ruoyi.app.utils.oauth.OAuthVerifyService;
|
|
|
|
|
+import com.ruoyi.app.utils.oauth.LineOAuthStateService;
|
|
|
import com.ruoyi.system.domain.InfoUser;
|
|
import com.ruoyi.system.domain.InfoUser;
|
|
|
import com.ruoyi.system.domain.InfoUserOauth;
|
|
import com.ruoyi.system.domain.InfoUserOauth;
|
|
|
import com.ruoyi.system.domain.PosOrder;
|
|
import com.ruoyi.system.domain.PosOrder;
|
|
@@ -26,6 +28,8 @@ import com.ruoyi.system.utils.JwtUtil;
|
|
|
import com.ruoyi.common.utils.spring.SpringUtils;
|
|
import com.ruoyi.common.utils.spring.SpringUtils;
|
|
|
import org.apache.ibatis.builder.MapperBuilderAssistant;
|
|
import org.apache.ibatis.builder.MapperBuilderAssistant;
|
|
|
import org.junit.jupiter.api.AfterAll;
|
|
import org.junit.jupiter.api.AfterAll;
|
|
|
|
|
+import org.junit.jupiter.params.ParameterizedTest;
|
|
|
|
|
+import org.junit.jupiter.params.provider.CsvSource;
|
|
|
import org.junit.jupiter.api.AfterEach;
|
|
import org.junit.jupiter.api.AfterEach;
|
|
|
import org.junit.jupiter.api.BeforeAll;
|
|
import org.junit.jupiter.api.BeforeAll;
|
|
|
import org.junit.jupiter.api.BeforeEach;
|
|
import org.junit.jupiter.api.BeforeEach;
|
|
@@ -44,7 +48,6 @@ import java.util.ArrayList;
|
|
|
import java.util.Collection;
|
|
import java.util.Collection;
|
|
|
import java.util.Collections;
|
|
import java.util.Collections;
|
|
|
import java.util.Locale;
|
|
import java.util.Locale;
|
|
|
-import java.util.Set;
|
|
|
|
|
|
|
|
|
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
|
import static org.junit.jupiter.api.Assertions.assertNull;
|
|
import static org.junit.jupiter.api.Assertions.assertNull;
|
|
@@ -67,7 +70,7 @@ class InfoUserControllerTest {
|
|
|
private MerchantStoreAccessService merchantStoreAccessService;
|
|
private MerchantStoreAccessService merchantStoreAccessService;
|
|
|
private MerchantTokenSessionService merchantTokenSessionService;
|
|
private MerchantTokenSessionService merchantTokenSessionService;
|
|
|
private BusinessPhoneService businessPhoneService;
|
|
private BusinessPhoneService businessPhoneService;
|
|
|
- private LineOAuthProperties lineOAuthProperties;
|
|
|
|
|
|
|
+ private OAuthVerifyService oauthVerifyService;
|
|
|
private InfoUserOauthMapper infoUserOauthMapper;
|
|
private InfoUserOauthMapper infoUserOauthMapper;
|
|
|
private RedisCache redisCache;
|
|
private RedisCache redisCache;
|
|
|
private static ConfigurableListableBeanFactory originalBeanFactory;
|
|
private static ConfigurableListableBeanFactory originalBeanFactory;
|
|
@@ -78,6 +81,8 @@ class InfoUserControllerTest {
|
|
|
new MapperBuilderAssistant(new MybatisConfiguration(), ""), PosOrder.class);
|
|
new MapperBuilderAssistant(new MybatisConfiguration(), ""), PosOrder.class);
|
|
|
TableInfoHelper.initTableInfo(
|
|
TableInfoHelper.initTableInfo(
|
|
|
new MapperBuilderAssistant(new MybatisConfiguration(), ""), InfoUser.class);
|
|
new MapperBuilderAssistant(new MybatisConfiguration(), ""), InfoUser.class);
|
|
|
|
|
+ TableInfoHelper.initTableInfo(
|
|
|
|
|
+ new MapperBuilderAssistant(new MybatisConfiguration(), ""), InfoUserOauth.class);
|
|
|
originalBeanFactory = (ConfigurableListableBeanFactory)
|
|
originalBeanFactory = (ConfigurableListableBeanFactory)
|
|
|
ReflectionTestUtils.getField(SpringUtils.class, "beanFactory");
|
|
ReflectionTestUtils.getField(SpringUtils.class, "beanFactory");
|
|
|
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
|
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
|
@@ -90,6 +95,9 @@ class InfoUserControllerTest {
|
|
|
messageSource.addMessage("no.oauth.phone.blank", Locale.getDefault(), "手机号不能为空");
|
|
messageSource.addMessage("no.oauth.phone.blank", Locale.getDefault(), "手机号不能为空");
|
|
|
messageSource.addMessage("no.user.login.success", Locale.getDefault(), "登录成功");
|
|
messageSource.addMessage("no.user.login.success", Locale.getDefault(), "登录成功");
|
|
|
messageSource.addMessage("no.user.stop", Locale.getDefault(), "账号已停用");
|
|
messageSource.addMessage("no.user.stop", Locale.getDefault(), "账号已停用");
|
|
|
|
|
+ messageSource.addMessage("no.user.not.exist", Locale.getDefault(), "账号不存在");
|
|
|
|
|
+ messageSource.addMessage("no.system.error", Locale.getDefault(), "系统错误");
|
|
|
|
|
+ messageSource.addMessage("no.user.jcaptcha.error", Locale.getDefault(), "验证码错误");
|
|
|
messageSource.addMessage("no.oauth.tempkey.expired", Locale.getDefault(), "登录凭证已过期");
|
|
messageSource.addMessage("no.oauth.tempkey.expired", Locale.getDefault(), "登录凭证已过期");
|
|
|
beanFactory.registerSingleton("messageSource", messageSource);
|
|
beanFactory.registerSingleton("messageSource", messageSource);
|
|
|
beanFactory.registerSingleton("redisCache", mock(RedisCache.class));
|
|
beanFactory.registerSingleton("redisCache", mock(RedisCache.class));
|
|
@@ -114,7 +122,7 @@ class InfoUserControllerTest {
|
|
|
merchantStoreAccessService = mock(MerchantStoreAccessService.class);
|
|
merchantStoreAccessService = mock(MerchantStoreAccessService.class);
|
|
|
merchantTokenSessionService = mock(MerchantTokenSessionService.class);
|
|
merchantTokenSessionService = mock(MerchantTokenSessionService.class);
|
|
|
businessPhoneService = mock(BusinessPhoneService.class);
|
|
businessPhoneService = mock(BusinessPhoneService.class);
|
|
|
- lineOAuthProperties = mock(LineOAuthProperties.class);
|
|
|
|
|
|
|
+ oauthVerifyService = mock(OAuthVerifyService.class);
|
|
|
infoUserOauthMapper = mock(InfoUserOauthMapper.class);
|
|
infoUserOauthMapper = mock(InfoUserOauthMapper.class);
|
|
|
redisCache = mock(RedisCache.class);
|
|
redisCache = mock(RedisCache.class);
|
|
|
ReflectionTestUtils.setField(controller, "posOrderService", posOrderService);
|
|
ReflectionTestUtils.setField(controller, "posOrderService", posOrderService);
|
|
@@ -123,7 +131,7 @@ class InfoUserControllerTest {
|
|
|
ReflectionTestUtils.setField(controller, "merchantStoreAccessService", merchantStoreAccessService);
|
|
ReflectionTestUtils.setField(controller, "merchantStoreAccessService", merchantStoreAccessService);
|
|
|
ReflectionTestUtils.setField(controller, "merchantTokenSessionService", merchantTokenSessionService);
|
|
ReflectionTestUtils.setField(controller, "merchantTokenSessionService", merchantTokenSessionService);
|
|
|
ReflectionTestUtils.setField(controller, "businessPhoneService", businessPhoneService);
|
|
ReflectionTestUtils.setField(controller, "businessPhoneService", businessPhoneService);
|
|
|
- ReflectionTestUtils.setField(controller, "lineOAuthProperties", lineOAuthProperties);
|
|
|
|
|
|
|
+ ReflectionTestUtils.setField(controller, "oauthVerifyService", oauthVerifyService);
|
|
|
ReflectionTestUtils.setField(controller, "infoUserOauthMapper", infoUserOauthMapper);
|
|
ReflectionTestUtils.setField(controller, "infoUserOauthMapper", infoUserOauthMapper);
|
|
|
ReflectionTestUtils.setField(controller, "redisCache", redisCache);
|
|
ReflectionTestUtils.setField(controller, "redisCache", redisCache);
|
|
|
when(infoUserOauthMapper.insert(any(InfoUserOauth.class))).thenReturn(1);
|
|
when(infoUserOauthMapper.insert(any(InfoUserOauth.class))).thenReturn(1);
|
|
@@ -360,8 +368,6 @@ class InfoUserControllerTest {
|
|
|
when(redisCache.getCacheObject("oauth:bind:temp-key"))
|
|
when(redisCache.getCacheObject("oauth:bind:temp-key"))
|
|
|
.thenReturn("line_user@line-uid");
|
|
.thenReturn("line_user@line-uid");
|
|
|
when(redisCache.deleteObject("oauth:bind:temp-key")).thenReturn(true);
|
|
when(redisCache.deleteObject("oauth:bind:temp-key")).thenReturn(true);
|
|
|
- when(lineOAuthProperties.requireChannel("line_user"))
|
|
|
|
|
- .thenReturn(lineUserChannel());
|
|
|
|
|
|
|
|
|
|
AjaxResult result = controller.oauthBindPhone(request);
|
|
AjaxResult result = controller.oauthBindPhone(request);
|
|
|
|
|
|
|
@@ -379,8 +385,6 @@ class InfoUserControllerTest {
|
|
|
when(redisCache.getCacheObject("oauth:bind:temp-key"))
|
|
when(redisCache.getCacheObject("oauth:bind:temp-key"))
|
|
|
.thenReturn("line_user@line-uid");
|
|
.thenReturn("line_user@line-uid");
|
|
|
when(redisCache.deleteObject("oauth:bind:temp-key")).thenReturn(true);
|
|
when(redisCache.deleteObject("oauth:bind:temp-key")).thenReturn(true);
|
|
|
- when(lineOAuthProperties.requireChannel("line_user"))
|
|
|
|
|
- .thenReturn(lineUserChannel());
|
|
|
|
|
|
|
|
|
|
InfoUser legacyMerchant = activeUser(7L, "1");
|
|
InfoUser legacyMerchant = activeUser(7L, "1");
|
|
|
legacyMerchant.setPhone("0912345678");
|
|
legacyMerchant.setPhone("0912345678");
|
|
@@ -426,10 +430,6 @@ class InfoUserControllerTest {
|
|
|
when(redisCache.getCacheObject("oauth:bind:replayed-key"))
|
|
when(redisCache.getCacheObject("oauth:bind:replayed-key"))
|
|
|
.thenReturn("line_rider@line-uid");
|
|
.thenReturn("line_rider@line-uid");
|
|
|
when(redisCache.deleteObject("oauth:bind:replayed-key")).thenReturn(false);
|
|
when(redisCache.deleteObject("oauth:bind:replayed-key")).thenReturn(false);
|
|
|
- when(lineOAuthProperties.requireChannel("line_rider"))
|
|
|
|
|
- .thenReturn(new LineOAuthProperties.ResolvedChannel(
|
|
|
|
|
- "line_rider", "client", "secret", "redirect", "app-redirect",
|
|
|
|
|
- com.ruoyi.common.constant.CacheConstants.QS_TOKEN_KEY, Set.of("2"), false));
|
|
|
|
|
when(infoUserService.getOne(any(Wrapper.class))).thenReturn(activeUser(22L, "2"));
|
|
when(infoUserService.getOne(any(Wrapper.class))).thenReturn(activeUser(22L, "2"));
|
|
|
|
|
|
|
|
AjaxResult result = controller.oauthBindPhone(request);
|
|
AjaxResult result = controller.oauthBindPhone(request);
|
|
@@ -445,8 +445,6 @@ class InfoUserControllerTest {
|
|
|
when(redisCache.getCacheObject("oauth:bind:merchant-key"))
|
|
when(redisCache.getCacheObject("oauth:bind:merchant-key"))
|
|
|
.thenReturn("line_merchant@line-uid");
|
|
.thenReturn("line_merchant@line-uid");
|
|
|
when(redisCache.deleteObject("oauth:bind:merchant-key")).thenReturn(true);
|
|
when(redisCache.deleteObject("oauth:bind:merchant-key")).thenReturn(true);
|
|
|
- when(lineOAuthProperties.requireChannel("line_merchant"))
|
|
|
|
|
- .thenReturn(lineMerchantChannel());
|
|
|
|
|
InfoUserOauth binding = new InfoUserOauth();
|
|
InfoUserOauth binding = new InfoUserOauth();
|
|
|
binding.setUserId(55L);
|
|
binding.setUserId(55L);
|
|
|
when(infoUserOauthMapper.selectOne(any())).thenReturn(binding);
|
|
when(infoUserOauthMapper.selectOne(any())).thenReturn(binding);
|
|
@@ -482,17 +480,177 @@ class InfoUserControllerTest {
|
|
|
assertEquals("账号已停用", result.get(AjaxResult.MSG_TAG));
|
|
assertEquals("账号已停用", result.get(AjaxResult.MSG_TAG));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- private LineOAuthProperties.ResolvedChannel lineUserChannel() {
|
|
|
|
|
- return new LineOAuthProperties.ResolvedChannel(
|
|
|
|
|
- "line_user", "client", "secret", "redirect", "app-redirect",
|
|
|
|
|
- com.ruoyi.common.constant.CacheConstants.USER_TOKEN_KEY, Set.of("0"), true);
|
|
|
|
|
|
|
+ @ParameterizedTest
|
|
|
|
|
+ @CsvSource({"apple_rider,2,qtw_tokens:qs:", "google_rider,2,qtw_tokens:qs:",
|
|
|
|
|
+ "apple_merchant,1,qtw_tokens:sh:app:", "google_merchant,3,qtw_tokens:sh:app:"})
|
|
|
|
|
+ void businessOauthBindsExistingBusinessPhoneAndIssuesItsOwnSession(
|
|
|
|
|
+ String provider, String role, String tokenPrefix) {
|
|
|
|
|
+ OAuthBindDto request = oauthRequest(provider);
|
|
|
|
|
+ InfoUser business = activeUser(72L, role);
|
|
|
|
|
+ business.setTelPhone(request.getPhone());
|
|
|
|
|
+ when(infoUserService.getOne(any(Wrapper.class))).thenReturn(business);
|
|
|
|
|
+ when(infoUserService.saveOrUpdate(any(InfoUser.class))).thenReturn(true);
|
|
|
|
|
+
|
|
|
|
|
+ AjaxResult result = controller.oauthBindPhone(request);
|
|
|
|
|
+
|
|
|
|
|
+ assertEquals(HttpStatus.SUCCESS, result.get(AjaxResult.CODE_TAG));
|
|
|
|
|
+ String token = (String) result.get("token");
|
|
|
|
|
+ assertTrue(JWT.decode(token).getId().startsWith(tokenPrefix));
|
|
|
|
|
+ assertEquals(provider, JWT.decode(token).getClaim("provider").asString());
|
|
|
|
|
+ ArgumentCaptor<InfoUserOauth> binding = ArgumentCaptor.forClass(InfoUserOauth.class);
|
|
|
|
|
+ verify(infoUserOauthMapper).insert(binding.capture());
|
|
|
|
|
+ assertEquals(72L, binding.getValue().getUserId());
|
|
|
|
|
+ assertEquals(provider, binding.getValue().getProvider());
|
|
|
|
|
+ verify(infoUserService, never()).getuser(any());
|
|
|
|
|
+ ArgumentCaptor<Wrapper<InfoUser>> query = ArgumentCaptor.forClass(Wrapper.class);
|
|
|
|
|
+ verify(infoUserService).getOne(query.capture());
|
|
|
|
|
+ assertTrue(query.getValue().getSqlSegment().contains("tel_phone"));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @ParameterizedTest
|
|
|
|
|
+ @CsvSource({"apple_rider", "google_rider", "apple_merchant", "google_merchant"})
|
|
|
|
|
+ void businessOauthCannotCreateAnAccount(String provider) {
|
|
|
|
|
+ AjaxResult result = controller.oauthBindPhone(oauthRequest(provider));
|
|
|
|
|
+
|
|
|
|
|
+ assertEquals(HttpStatus.ERROR, result.get(AjaxResult.CODE_TAG));
|
|
|
|
|
+ assertEquals("账号不存在", result.get(AjaxResult.MSG_TAG));
|
|
|
|
|
+ verify(infoUserService, never()).saveOrUpdate(any(InfoUser.class));
|
|
|
|
|
+ verify(infoUserOauthMapper, never()).insert(any(InfoUserOauth.class));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @ParameterizedTest
|
|
|
|
|
+ @CsvSource({"apple_rider,1", "google_rider,0", "apple_merchant,2", "google_merchant,0"})
|
|
|
|
|
+ void businessOauthRejectsBindingToTheWrongRole(String provider, String role) {
|
|
|
|
|
+ OAuthBindDto request = oauthRequest(provider);
|
|
|
|
|
+ InfoUserOauth binding = new InfoUserOauth();
|
|
|
|
|
+ binding.setUserId(72L);
|
|
|
|
|
+ when(infoUserOauthMapper.selectOne(any())).thenReturn(binding);
|
|
|
|
|
+ when(infoUserService.getById(72L)).thenReturn(activeUser(72L, role));
|
|
|
|
|
+
|
|
|
|
|
+ AjaxResult result = controller.oauthBindPhone(request);
|
|
|
|
|
+
|
|
|
|
|
+ assertEquals(HttpStatus.ERROR, result.get(AjaxResult.CODE_TAG));
|
|
|
|
|
+ assertNull(result.get("token"));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @ParameterizedTest
|
|
|
|
|
+ @CsvSource({"apple", "google"})
|
|
|
|
|
+ void existingUserOauthKeepsProviderAndUserSession(String provider) {
|
|
|
|
|
+ OAuthBindDto request = oauthRequest(provider);
|
|
|
|
|
+ InfoUserOauth binding = new InfoUserOauth();
|
|
|
|
|
+ binding.setUserId(72L);
|
|
|
|
|
+ InfoUser user = activeUser(72L, "0");
|
|
|
|
|
+ user.setPhone(request.getPhone());
|
|
|
|
|
+ when(infoUserOauthMapper.selectOne(any())).thenReturn(binding);
|
|
|
|
|
+ when(infoUserService.getById(72L)).thenReturn(user);
|
|
|
|
|
+
|
|
|
|
|
+ AjaxResult result = controller.oauthBindPhone(request);
|
|
|
|
|
+
|
|
|
|
|
+ assertEquals(HttpStatus.SUCCESS, result.get(AjaxResult.CODE_TAG));
|
|
|
|
|
+ String token = (String) result.get("token");
|
|
|
|
|
+ assertTrue(JWT.decode(token).getId().startsWith("qtw_tokens:user:"));
|
|
|
|
|
+ assertEquals(provider, JWT.decode(token).getClaim("provider").asString());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @ParameterizedTest
|
|
|
|
|
+ @CsvSource({"apple_rider,2,qtw_tokens:qs:", "google_rider,2,qtw_tokens:qs:",
|
|
|
|
|
+ "apple_merchant,4,qtw_tokens:sh:app:", "google_merchant,1,qtw_tokens:sh:app:",
|
|
|
|
|
+ "apple,0,qtw_tokens:user:", "google,0,qtw_tokens:user:", "line,0,qtw_tokens:user:",
|
|
|
|
|
+ "line_user,0,qtw_tokens:user:"})
|
|
|
|
|
+ void boundOauthLoginKeepsEachClientSession(String provider, String role, String tokenPrefix) {
|
|
|
|
|
+ OAuthLoginDto request = new OAuthLoginDto();
|
|
|
|
|
+ request.setProvider(provider);
|
|
|
|
|
+ request.setCredential("credential");
|
|
|
|
|
+ when(oauthVerifyService.verify(provider, "credential")).thenReturn("provider-uid");
|
|
|
|
|
+ InfoUserOauth binding = new InfoUserOauth();
|
|
|
|
|
+ binding.setUserId(72L);
|
|
|
|
|
+ when(infoUserOauthMapper.selectOne(any())).thenReturn(binding);
|
|
|
|
|
+ InfoUser user = activeUser(72L, role);
|
|
|
|
|
+ user.setPhone("0912345678");
|
|
|
|
|
+ when(infoUserService.getOne(any(Wrapper.class))).thenReturn(user);
|
|
|
|
|
+
|
|
|
|
|
+ AjaxResult result = controller.oauthLogin(request);
|
|
|
|
|
+
|
|
|
|
|
+ assertEquals(HttpStatus.SUCCESS, result.get(AjaxResult.CODE_TAG));
|
|
|
|
|
+ assertTrue(JWT.decode((String) result.get("token")).getId().startsWith(tokenPrefix));
|
|
|
|
|
+ assertEquals(provider, JWT.decode((String) result.get("token")).getClaim("provider").asString());
|
|
|
|
|
+ if (provider.startsWith("line")) {
|
|
|
|
|
+ ArgumentCaptor<LambdaQueryWrapper<InfoUserOauth>> query = ArgumentCaptor.forClass(LambdaQueryWrapper.class);
|
|
|
|
|
+ verify(infoUserOauthMapper).selectOne(query.capture());
|
|
|
|
|
+ query.getValue().getSqlSegment();
|
|
|
|
|
+ assertTrue(query.getValue().getParamNameValuePairs().containsValue("line"));
|
|
|
|
|
+ assertTrue(query.getValue().getParamNameValuePairs().containsValue("line_user"));
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @ParameterizedTest
|
|
|
|
|
+ @CsvSource({"apple", "google"})
|
|
|
|
|
+ void userFirstBindingStillCreatesAUserAndWallet(String provider) {
|
|
|
|
|
+ OAuthBindDto request = oauthRequest(provider);
|
|
|
|
|
+ InfoUser user = activeUser(72L, "0");
|
|
|
|
|
+ user.setPhone(request.getPhone());
|
|
|
|
|
+ when(infoUserService.getuser(request.getPhone())).thenReturn(null, user);
|
|
|
|
|
+ when(infoUserService.saveOrUpdate(any(InfoUser.class))).thenReturn(true);
|
|
|
|
|
+
|
|
|
|
|
+ AjaxResult result = controller.oauthBindPhone(request);
|
|
|
|
|
+
|
|
|
|
|
+ assertEquals(HttpStatus.SUCCESS, result.get(AjaxResult.CODE_TAG));
|
|
|
|
|
+ ArgumentCaptor<InfoUser> created = ArgumentCaptor.forClass(InfoUser.class);
|
|
|
|
|
+ verify(infoUserService).saveOrUpdate(created.capture());
|
|
|
|
|
+ assertEquals("0", created.getValue().getUserType());
|
|
|
|
|
+ assertEquals(request.getPhone(), created.getValue().getPhone());
|
|
|
|
|
+ verify(userWalletService).createUserWallet(72L);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @ParameterizedTest
|
|
|
|
|
+ @CsvSource({"apple_merchant", "google_merchant"})
|
|
|
|
|
+ void businessOauthRejectsSubaccountWhoseOwnerIsUnavailable(String provider) {
|
|
|
|
|
+ OAuthBindDto request = oauthRequest(provider);
|
|
|
|
|
+ InfoUser user = activeUser(72L, "5");
|
|
|
|
|
+ user.setSubaccountStatus("0");
|
|
|
|
|
+ when(infoUserService.getOne(any(Wrapper.class))).thenReturn(user);
|
|
|
|
|
+ doThrow(new ServiceException("owner unavailable")).when(merchantStoreAccessService).resolve(72L);
|
|
|
|
|
+ AjaxResult result = controller.oauthBindPhone(request);
|
|
|
|
|
+ assertEquals(HttpStatus.ERROR, result.get(AjaxResult.CODE_TAG));
|
|
|
|
|
+ verify(infoUserOauthMapper, never()).insert(any(InfoUserOauth.class));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Test
|
|
|
|
|
+ void directBusinessLineLoginCannotBypassStateValidation() {
|
|
|
|
|
+ OAuthLoginDto request = new OAuthLoginDto();
|
|
|
|
|
+ request.setProvider("line_rider");
|
|
|
|
|
+ request.setCredential("code");
|
|
|
|
|
+ LineOAuthStateService stateService = mock(LineOAuthStateService.class);
|
|
|
|
|
+ doThrow(new ServiceException("invalid state")).when(stateService).consume("line_rider", null);
|
|
|
|
|
+ ReflectionTestUtils.setField(controller, "lineOAuthStateService", stateService);
|
|
|
|
|
+ assertThrows(ServiceException.class, () -> controller.oauthLogin(request));
|
|
|
|
|
+ verify(oauthVerifyService, never()).verify(any(), any());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @ParameterizedTest
|
|
|
|
|
+ @CsvSource({"apple_rider", "google_merchant", "line_rider", "line_merchant"})
|
|
|
|
|
+ void businessBindingRequiresAnActualSmsCode(String provider) {
|
|
|
|
|
+ OAuthBindDto request = oauthRequest(provider);
|
|
|
|
|
+ request.setCode("8888");
|
|
|
|
|
+ InfoUser user = activeUser(72L, provider.endsWith("rider") ? "2" : "1");
|
|
|
|
|
+ when(infoUserService.getOne(any(Wrapper.class))).thenReturn(user);
|
|
|
|
|
+ when(infoUserService.saveOrUpdate(any(InfoUser.class))).thenReturn(true);
|
|
|
|
|
+ AjaxResult result = controller.oauthBindPhone(request);
|
|
|
|
|
+ assertEquals(HttpStatus.ERROR, result.get(AjaxResult.CODE_TAG));
|
|
|
|
|
+ assertEquals("验证码错误", result.get(AjaxResult.MSG_TAG));
|
|
|
|
|
+ verify(infoUserOauthMapper, never()).insert(any(InfoUserOauth.class));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- private LineOAuthProperties.ResolvedChannel lineMerchantChannel() {
|
|
|
|
|
- return new LineOAuthProperties.ResolvedChannel(
|
|
|
|
|
- "line_merchant", "client", "secret", "redirect", "app-redirect",
|
|
|
|
|
- com.ruoyi.common.constant.CacheConstants.SH_APP_TOKEN_KEY,
|
|
|
|
|
- Set.of("1", "3", "4", "5"), false);
|
|
|
|
|
|
|
+ private OAuthBindDto oauthRequest(String provider) {
|
|
|
|
|
+ OAuthBindDto request = new OAuthBindDto();
|
|
|
|
|
+ request.setTempKey("business-key");
|
|
|
|
|
+ request.setPhone("0912345678");
|
|
|
|
|
+ request.setCode("456789");
|
|
|
|
|
+ when(redisCache.getCacheObject("oauth:bind:business-key"))
|
|
|
|
|
+ .thenReturn(provider + "@provider-uid");
|
|
|
|
|
+ when(redisCache.deleteObject("oauth:bind:business-key")).thenReturn(true);
|
|
|
|
|
+ when(redisCache.getCacheObject("0912345678")).thenReturn("456789");
|
|
|
|
|
+ return request;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private InfoUser activeUser(Long userId, String userType) {
|
|
private InfoUser activeUser(Long userId, String userType) {
|