| | |
| | | |
| | | import com.baomidou.mybatisplus.core.MybatisConfiguration; |
| | | import com.baomidou.mybatisplus.core.metadata.TableInfoHelper; |
| | | import cn.dev33.satoken.stp.SaTokenInfo; |
| | | import com.tcm.training.admin.app.auth.service.AppAuthSessionService; |
| | | import com.tcm.training.admin.app.auth.vo.AppLoginResponse; |
| | | import com.tcm.training.admin.app.auth.service.AppSmsCodeService; |
| | | import com.tcm.training.admin.app.auth.service.AppWechatAuthClient; |
| | | import com.tcm.training.admin.app.settings.dto.AppSettingsPhoneBindRequest; |
| | | import com.tcm.training.admin.app.settings.mapper.AppUserNotificationSettingMapper; |
| | | import com.tcm.training.admin.app.settings.vo.AppSettingsProfileVO; |
| | | import com.tcm.training.admin.app.share.service.AppShareService; |
| | | import com.tcm.training.admin.member.entity.AppUser; |
| | | import com.tcm.training.admin.member.mapper.UserMapper; |
| | |
| | | import static org.mockito.ArgumentMatchers.any; |
| | | import static org.mockito.Mockito.doNothing; |
| | | import static org.mockito.Mockito.never; |
| | | import static org.mockito.Mockito.times; |
| | | import static org.mockito.Mockito.verify; |
| | | import static org.mockito.Mockito.when; |
| | | |
| | |
| | | when(userMapper.selectById(1L)).thenReturn(currentUser); |
| | | when(userMapper.selectOne(any())).thenReturn(null); |
| | | doNothing().when(appSmsCodeService).validatePhoneChangeCode("13800138000", "123456"); |
| | | when(appAuthSessionService.getTokenInfo()).thenReturn(buildToken("bind-token")); |
| | | |
| | | AppSettingsProfileVO response = appSettingsService.bindPhone(request); |
| | | AppLoginResponse response = appSettingsService.bindPhone(request); |
| | | |
| | | verify(userMapper).updateById(appUserCaptor.capture()); |
| | | verify(appAuthSessionService).login(1L); |
| | | assertEquals("13800138000", appUserCaptor.getValue().getPhone()); |
| | | assertEquals("13800138000", response.getPhone()); |
| | | assertEquals("13800138000", response.getUser().getPhone()); |
| | | assertEquals("bind-token", response.getToken()); |
| | | } |
| | | |
| | | /** |
| | |
| | | } |
| | | |
| | | /** |
| | | * 目标手机号被其他有效用户占用时不允许绑定。 |
| | | * 微信临时账号绑定已注册但未绑定微信的手机号时,应合并到手机号账号。 |
| | | */ |
| | | @Test |
| | | void bindPhoneShouldRejectOccupiedPhone() { |
| | | void bindPhoneShouldMergeWechatUserIntoExistingPhoneUser() { |
| | | AppSettingsPhoneBindRequest request = new AppSettingsPhoneBindRequest(); |
| | | request.setNewPhone("13800138000"); |
| | | request.setCode("123456"); |
| | | AppUser currentUser = buildEnabledUser(null); |
| | | currentUser.setWechatOpenid("wx-openid"); |
| | | currentUser.setNickname(null); |
| | | currentUser.setWechatNickname("微信昵称"); |
| | | AppUser occupiedUser = buildEnabledUser("13800138000"); |
| | | occupiedUser.setId(2L); |
| | | occupiedUser.setNickname(null); |
| | | |
| | | when(appAuthSessionService.requireLoginUserId()).thenReturn(1L); |
| | | when(userMapper.selectById(1L)).thenReturn(currentUser); |
| | | when(userMapper.selectOne(any())).thenReturn(occupiedUser); |
| | | doNothing().when(appSmsCodeService).validatePhoneChangeCode("13800138000", "123456"); |
| | | when(appAuthSessionService.getTokenInfo()).thenReturn(buildToken("merged-token")); |
| | | |
| | | AppLoginResponse response = appSettingsService.bindPhone(request); |
| | | |
| | | verify(userMapper, times(2)).updateById(appUserCaptor.capture()); |
| | | AppUser mergedUser = appUserCaptor.getAllValues().get(0); |
| | | AppUser deletedTemporaryUser = appUserCaptor.getAllValues().get(1); |
| | | verify(appAuthSessionService).login(2L); |
| | | assertEquals("wx-openid", mergedUser.getWechatOpenid()); |
| | | assertEquals("微信昵称", mergedUser.getNickname()); |
| | | assertEquals(Integer.valueOf(1), deletedTemporaryUser.getDeleted()); |
| | | assertEquals(Long.valueOf(2L), response.getUser().getId()); |
| | | assertEquals("merged-token", response.getToken()); |
| | | } |
| | | |
| | | /** |
| | | * 微信临时账号绑定已绑定微信的手机号时,应直接覆盖目标账号微信票据。 |
| | | */ |
| | | @Test |
| | | void bindPhoneShouldOverwriteWechatBindingWhenPhoneUserAlreadyBoundWechat() { |
| | | AppSettingsPhoneBindRequest request = new AppSettingsPhoneBindRequest(); |
| | | request.setNewPhone("13800138000"); |
| | | request.setCode("123456"); |
| | | AppUser currentUser = buildEnabledUser(null); |
| | | currentUser.setWechatOpenid("wx-openid"); |
| | | currentUser.setWechatNickname("新微信昵称"); |
| | | AppUser occupiedUser = buildEnabledUser("13800138000"); |
| | | occupiedUser.setId(2L); |
| | | occupiedUser.setWechatOpenid("other-wx-openid"); |
| | | |
| | | when(appAuthSessionService.requireLoginUserId()).thenReturn(1L); |
| | | when(userMapper.selectById(1L)).thenReturn(currentUser); |
| | | when(userMapper.selectOne(any())).thenReturn(occupiedUser); |
| | | doNothing().when(appSmsCodeService).validatePhoneChangeCode("13800138000", "123456"); |
| | | when(appAuthSessionService.getTokenInfo()).thenReturn(buildToken("wechat-overwrite-token")); |
| | | |
| | | AppLoginResponse response = appSettingsService.bindPhone(request); |
| | | |
| | | verify(userMapper, times(2)).updateById(appUserCaptor.capture()); |
| | | AppUser mergedUser = appUserCaptor.getAllValues().get(0); |
| | | AppUser deletedTemporaryUser = appUserCaptor.getAllValues().get(1); |
| | | verify(appAuthSessionService).login(2L); |
| | | assertEquals("wx-openid", mergedUser.getWechatOpenid()); |
| | | assertEquals("新微信昵称", mergedUser.getWechatNickname()); |
| | | assertEquals(Integer.valueOf(1), deletedTemporaryUser.getDeleted()); |
| | | assertEquals(Long.valueOf(2L), response.getUser().getId()); |
| | | } |
| | | |
| | | /** |
| | | * 苹果临时账号绑定已注册但未绑定苹果的手机号时,应合并到手机号账号。 |
| | | */ |
| | | @Test |
| | | void bindPhoneShouldMergeAppleUserIntoExistingPhoneUser() { |
| | | AppSettingsPhoneBindRequest request = new AppSettingsPhoneBindRequest(); |
| | | request.setNewPhone("13800138000"); |
| | | request.setCode("123456"); |
| | | AppUser currentUser = buildEnabledUser(null); |
| | | currentUser.setAppleIdentitySubject("apple-subject"); |
| | | currentUser.setAppleUserIdentifier("apple-user"); |
| | | AppUser occupiedUser = buildEnabledUser("13800138000"); |
| | | occupiedUser.setId(2L); |
| | | |
| | | when(appAuthSessionService.requireLoginUserId()).thenReturn(1L); |
| | | when(userMapper.selectById(1L)).thenReturn(currentUser); |
| | | when(userMapper.selectOne(any())).thenReturn(occupiedUser); |
| | | doNothing().when(appSmsCodeService).validatePhoneChangeCode("13800138000", "123456"); |
| | | when(appAuthSessionService.getTokenInfo()).thenReturn(buildToken("apple-merged-token")); |
| | | |
| | | AppLoginResponse response = appSettingsService.bindPhone(request); |
| | | |
| | | verify(userMapper, times(2)).updateById(appUserCaptor.capture()); |
| | | AppUser mergedUser = appUserCaptor.getAllValues().get(0); |
| | | verify(appAuthSessionService).login(2L); |
| | | assertEquals("apple-subject", mergedUser.getAppleIdentitySubject()); |
| | | assertEquals("apple-user", mergedUser.getAppleUserIdentifier()); |
| | | assertEquals(Long.valueOf(2L), response.getUser().getId()); |
| | | } |
| | | |
| | | /** |
| | | * 苹果临时账号绑定已绑定苹果的手机号时,应直接覆盖目标账号苹果票据。 |
| | | */ |
| | | @Test |
| | | void bindPhoneShouldOverwriteAppleBindingWhenPhoneUserAlreadyBoundApple() { |
| | | AppSettingsPhoneBindRequest request = new AppSettingsPhoneBindRequest(); |
| | | request.setNewPhone("13800138000"); |
| | | request.setCode("123456"); |
| | | AppUser currentUser = buildEnabledUser(null); |
| | | currentUser.setAppleIdentitySubject("apple-subject"); |
| | | currentUser.setAppleUserIdentifier("apple-user"); |
| | | AppUser occupiedUser = buildEnabledUser("13800138000"); |
| | | occupiedUser.setId(2L); |
| | | occupiedUser.setAppleIdentitySubject("other-apple-subject"); |
| | | |
| | | when(appAuthSessionService.requireLoginUserId()).thenReturn(1L); |
| | | when(userMapper.selectById(1L)).thenReturn(currentUser); |
| | | when(userMapper.selectOne(any())).thenReturn(occupiedUser); |
| | | doNothing().when(appSmsCodeService).validatePhoneChangeCode("13800138000", "123456"); |
| | | when(appAuthSessionService.getTokenInfo()).thenReturn(buildToken("apple-overwrite-token")); |
| | | |
| | | AppLoginResponse response = appSettingsService.bindPhone(request); |
| | | |
| | | verify(userMapper, times(2)).updateById(appUserCaptor.capture()); |
| | | AppUser mergedUser = appUserCaptor.getAllValues().get(0); |
| | | AppUser deletedTemporaryUser = appUserCaptor.getAllValues().get(1); |
| | | verify(appAuthSessionService).login(2L); |
| | | assertEquals("apple-subject", mergedUser.getAppleIdentitySubject()); |
| | | assertEquals("apple-user", mergedUser.getAppleUserIdentifier()); |
| | | assertEquals(Integer.valueOf(1), deletedTemporaryUser.getDeleted()); |
| | | assertEquals(Long.valueOf(2L), response.getUser().getId()); |
| | | } |
| | | |
| | | /** |
| | | * 非第三方临时账号绑定已注册手机号时仍按占用处理。 |
| | | */ |
| | | @Test |
| | | void bindPhoneShouldRejectOccupiedPhoneWithoutThirdPartyBinding() { |
| | | AppSettingsPhoneBindRequest request = new AppSettingsPhoneBindRequest(); |
| | | request.setNewPhone("13800138000"); |
| | | request.setCode("123456"); |
| | |
| | | } |
| | | |
| | | /** |
| | | * 构造测试登录态。 |
| | | */ |
| | | private SaTokenInfo buildToken(String tokenValue) { |
| | | SaTokenInfo tokenInfo = new SaTokenInfo(); |
| | | tokenInfo.setTokenValue(tokenValue); |
| | | tokenInfo.setTokenTimeout(7200L); |
| | | return tokenInfo; |
| | | } |
| | | |
| | | /** |
| | | * 构造启用状态 APP 用户。 |
| | | */ |
| | | private AppUser buildEnabledUser(String phone) { |