Commit 705a5ff6459ec811264c66e501eae7c11fbcd93b

Authored by YunaiV
1 parent 6e404697

重构社交登录的时候,增加独立的社交绑定表

Showing 12 changed files with 324 additions and 368 deletions
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/social/SocialTypeEnum.java
@@ -22,45 +22,48 @@ public enum SocialTypeEnum implements IntArrayValuable { @@ -22,45 +22,48 @@ public enum SocialTypeEnum implements IntArrayValuable {
22 * Gitee 22 * Gitee
23 * 文档链接:https://gitee.com/api/v5/oauth_doc#/ 23 * 文档链接:https://gitee.com/api/v5/oauth_doc#/
24 */ 24 */
25 - GITEE(10, "GITEE"), 25 + GITEE(10, 1, "GITEE"),
26 /** 26 /**
27 * 钉钉 27 * 钉钉
28 * 文档链接:https://developers.dingtalk.com/document/app/obtain-identity-credentials 28 * 文档链接:https://developers.dingtalk.com/document/app/obtain-identity-credentials
29 */ 29 */
30 - DINGTALK(20, "DINGTALK"), 30 + DINGTALK(20, 2, "DINGTALK"),
31 31
32 /** 32 /**
33 * 企业微信 33 * 企业微信
34 * 文档链接:https://xkcoding.com/2019/08/06/use-justauth-integration-wechat-enterprise.html 34 * 文档链接:https://xkcoding.com/2019/08/06/use-justauth-integration-wechat-enterprise.html
35 */ 35 */
36 - WECHAT_ENTERPRISE(30, "WECHAT_ENTERPRISE"), 36 + WECHAT_ENTERPRISE(30, 3, "WECHAT_ENTERPRISE"),
37 /** 37 /**
38 * 微信公众平台 - 移动端 H5 38 * 微信公众平台 - 移动端 H5
39 * 文档链接:https://www.cnblogs.com/juewuzhe/p/11905461.html 39 * 文档链接:https://www.cnblogs.com/juewuzhe/p/11905461.html
40 */ 40 */
41 - WECHAT_MP(31, "WECHAT_MP"), 41 + WECHAT_MP(31, 3, "WECHAT_MP"),
42 /** 42 /**
43 * 微信开放平台 - 网站应用 PC 端扫码授权登录 43 * 微信开放平台 - 网站应用 PC 端扫码授权登录
44 * 文档链接:https://justauth.wiki/guide/oauth/wechat_open/#_2-申请开发者资质认证 44 * 文档链接:https://justauth.wiki/guide/oauth/wechat_open/#_2-申请开发者资质认证
45 */ 45 */
46 - WECHAT_OPEN(32, "WECHAT_OPEN"), 46 + WECHAT_OPEN(32, 3, "WECHAT_OPEN"),
47 /** 47 /**
48 * 微信小程序 48 * 微信小程序
49 * 文档链接:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html 49 * 文档链接:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html
50 */ 50 */
51 - WECHAT_MINI_PROGRAM(33, "WECHAT_MINI_PROGRAM"), 51 + WECHAT_MINI_PROGRAM(33, 3, "WECHAT_MINI_PROGRAM"),
52 ; 52 ;
53 53
54 public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(SocialTypeEnum::getType).toArray(); 54 public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(SocialTypeEnum::getType).toArray();
55 55
56 - public static final List<Integer> WECHAT_ALL = ListUtil.toList(WECHAT_ENTERPRISE.type, WECHAT_MP.type, WECHAT_OPEN.type,  
57 - WECHAT_MINI_PROGRAM.type);  
58 -  
59 /** 56 /**
60 * 类型 57 * 类型
61 */ 58 */
62 private final Integer type; 59 private final Integer type;
63 /** 60 /**
  61 + * 平台
  62 + *
  63 + * 例如说,微信平台下,有企业微信、公众平台、开放平台、小程序等
  64 + */
  65 + private final Integer platform;
  66 + /**
64 * 类型的标识 67 * 类型的标识
65 */ 68 */
66 private final String source; 69 private final String source;
@@ -74,11 +77,4 @@ public enum SocialTypeEnum implements IntArrayValuable { @@ -74,11 +77,4 @@ public enum SocialTypeEnum implements IntArrayValuable {
74 return ArrayUtil.firstMatch(o -> o.getType().equals(type), values()); 77 return ArrayUtil.firstMatch(o -> o.getType().equals(type), values());
75 } 78 }
76 79
77 - public static List<Integer> getRelationTypes(Integer type) {  
78 - if (WECHAT_ALL.contains(type)) {  
79 - return WECHAT_ALL;  
80 - }  
81 - return ListUtil.toList(type);  
82 - }  
83 -  
84 } 80 }
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApiImpl.java
@@ -38,7 +38,7 @@ public class SocialUserApiImpl implements SocialUserApi { @@ -38,7 +38,7 @@ public class SocialUserApiImpl implements SocialUserApi {
38 38
39 @Override 39 @Override
40 public void checkSocialUser(Integer type, String code, String state) { 40 public void checkSocialUser(Integer type, String code, String state) {
41 - socialUserService.checkSocialUser(type, code, state); 41 + socialUserService.authSocialUser(type, code, state);
42 } 42 }
43 43
44 @Override 44 @Override
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/social/SocialUserBindDO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.system.dal.dataobject.social;
  2 +
  3 +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
  4 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  5 +import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum;
  6 +import com.baomidou.mybatisplus.annotation.TableName;
  7 +import lombok.*;
  8 +
  9 +/**
  10 + * 社交用户的绑定
  11 + * 即 {@link SocialUserDO} 与 UserDO 的关联表
  12 + *
  13 + * @author 芋道源码
  14 + */
  15 +@TableName(value = "system_social_user_bind", autoResultMap = true)
  16 +@Data
  17 +@EqualsAndHashCode(callSuper = true)
  18 +@Builder
  19 +@NoArgsConstructor
  20 +@AllArgsConstructor
  21 +public class SocialUserBindDO extends BaseDO {
  22 +
  23 + /**
  24 + * 关联的用户编号
  25 + */
  26 + private Long userId;
  27 + /**
  28 + * 用户类型
  29 + *
  30 + * 枚举 {@link UserTypeEnum}
  31 + */
  32 + private Integer userType;
  33 +
  34 + /**
  35 + * 社交平台
  36 + *
  37 + * 枚举 {@link SocialTypeEnum#getPlatform()}
  38 + */
  39 + private Integer platform;
  40 + /**
  41 + * 社交的全局编号
  42 + */
  43 + private String unionId;
  44 +
  45 +}
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/social/SocialUserDO.java
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.system.dal.dataobject.social; @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.system.dal.dataobject.social;
3 import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; 3 import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
4 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; 4 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
5 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; 5 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  6 +import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum;
6 import com.baomidou.mybatisplus.annotation.TableId; 7 import com.baomidou.mybatisplus.annotation.TableId;
7 import com.baomidou.mybatisplus.annotation.TableName; 8 import com.baomidou.mybatisplus.annotation.TableName;
8 import lombok.*; 9 import lombok.*;
@@ -27,20 +28,9 @@ public class SocialUserDO extends BaseDO { @@ -27,20 +28,9 @@ public class SocialUserDO extends BaseDO {
27 @TableId 28 @TableId
28 private Long id; 29 private Long id;
29 /** 30 /**
30 - * 关联的用户编号  
31 - */  
32 - private Long userId;  
33 - /**  
34 - * 用户类型  
35 - *  
36 - * 枚举 {@link UserTypeEnum}  
37 - */  
38 - private Integer userType;  
39 -  
40 - /**  
41 * 社交平台的类型 31 * 社交平台的类型
42 * 32 *
43 - * 枚举 {@link UserTypeEnum} 33 + * 枚举 {@link SocialTypeEnum}
44 */ 34 */
45 private Integer type; 35 private Integer type;
46 36
@@ -77,6 +67,15 @@ public class SocialUserDO extends BaseDO { @@ -77,6 +67,15 @@ public class SocialUserDO extends BaseDO {
77 */ 67 */
78 private String rawUserInfo; 68 private String rawUserInfo;
79 69
  70 + /**
  71 + * 最后一次的认证 code
  72 + */
  73 + private String code;
  74 + /**
  75 + * 最后一次的认证 state
  76 + */
  77 + private String state;
  78 +
80 } 79 }
81 80
82 81
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/social/SocialUserBindMapper.java 0 → 100644
  1 +package cn.iocoder.yudao.module.system.dal.mysql.social;
  2 +
  3 +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  4 +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
  5 +import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserBindDO;
  6 +import org.apache.ibatis.annotations.Mapper;
  7 +
  8 +@Mapper
  9 +public interface SocialUserBindMapper extends BaseMapperX<SocialUserBindDO> {
  10 +
  11 + default void deleteByUserTypeAndUserIdAndPlatformAndUnionId(Integer userType, Long userId,
  12 + Integer platform, String unionId) {
  13 + delete(new LambdaQueryWrapperX<SocialUserBindDO>()
  14 + .eq(SocialUserBindDO::getUserType, userType)
  15 + .eq(SocialUserBindDO::getUserId, userId)
  16 + .eq(SocialUserBindDO::getPlatform, platform)
  17 + .eq(SocialUserBindDO::getUnionId, unionId));
  18 + }
  19 +
  20 + default SocialUserBindDO selectByUserTypeAndPlatformAndUnionId(Integer userType,
  21 + Integer platform, String unionId) {
  22 + return selectOne(new LambdaQueryWrapperX<SocialUserBindDO>()
  23 + .eq(SocialUserBindDO::getUserType, userType)
  24 + .eq(SocialUserBindDO::getPlatform, platform)
  25 + .eq(SocialUserBindDO::getUnionId, unionId));
  26 + }
  27 +
  28 +}
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/social/SocialUserMapper.java
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.system.dal.mysql.social; @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.system.dal.mysql.social;
2 2
3 import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserDO; 3 import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserDO;
4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; 4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  5 +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
5 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 6 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
6 import org.apache.ibatis.annotations.Mapper; 7 import org.apache.ibatis.annotations.Mapper;
7 8
@@ -11,14 +12,17 @@ import java.util.List; @@ -11,14 +12,17 @@ import java.util.List;
11 @Mapper 12 @Mapper
12 public interface SocialUserMapper extends BaseMapperX<SocialUserDO> { 13 public interface SocialUserMapper extends BaseMapperX<SocialUserDO> {
13 14
14 - default List<SocialUserDO> selectListByTypeAndUnionId(Integer userType, Collection<Integer> types, String unionId) {  
15 - return selectList(new QueryWrapper<SocialUserDO>().eq("user_type", userType)  
16 - .in("type", types).eq("union_id", unionId)); 15 + default SocialUserDO selectByTypeAndCodeAnState(Integer type, String code, String state) {
  16 + return selectOne(new LambdaQueryWrapper<SocialUserDO>()
  17 + .eq(SocialUserDO::getType, type)
  18 + .eq(SocialUserDO::getCode, code)
  19 + .eq(SocialUserDO::getState, state));
17 } 20 }
18 21
19 - default List<SocialUserDO> selectListByTypeAndUserId(Integer userType, Collection<Integer> types, Long userId) {  
20 - return selectList(new QueryWrapper<SocialUserDO>().eq("user_type", userType)  
21 - .in("type", types).eq("user_id", userId)); 22 + default SocialUserDO selectByTypeAndOpenid(Integer type, String openid) {
  23 + return selectOne(new LambdaQueryWrapper<SocialUserDO>()
  24 + .eq(SocialUserDO::getType, type)
  25 + .eq(SocialUserDO::getCode, openid));
22 } 26 }
23 27
24 default List<SocialUserDO> selectListByUserId(Integer userType, Long userId) { 28 default List<SocialUserDO> selectListByUserId(Integer userType, Long userId) {
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/redis/RedisKeyConstants.java
@@ -23,10 +23,6 @@ public interface RedisKeyConstants { @@ -23,10 +23,6 @@ public interface RedisKeyConstants {
23 "login_user:%s", // 参数为 sessionId 23 "login_user:%s", // 参数为 sessionId
24 STRING, LoginUser.class, RedisKeyDefine.TimeoutTypeEnum.DYNAMIC); 24 STRING, LoginUser.class, RedisKeyDefine.TimeoutTypeEnum.DYNAMIC);
25 25
26 - RedisKeyDefine SOCIAL_AUTH_USER = new RedisKeyDefine("社交登陆的授权用户",  
27 - "social_auth_user:%d:%s", // 参数为 type,code  
28 - STRING, AuthUser.class, Duration.ofDays(1));  
29 -  
30 RedisKeyDefine SOCIAL_AUTH_STATE = new RedisKeyDefine("社交登陆的 state", // 注意,它是被 JustAuth 的 justauth.type.prefix 使用到 26 RedisKeyDefine SOCIAL_AUTH_STATE = new RedisKeyDefine("社交登陆的 state", // 注意,它是被 JustAuth 的 justauth.type.prefix 使用到
31 "social_auth_state:%s", // 参数为 state 27 "social_auth_state:%s", // 参数为 state
32 STRING, String.class, Duration.ofHours(24)); // 值为 state 28 STRING, String.class, Duration.ofHours(24)); // 值为 state
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/redis/social/SocialAuthUserRedisDAO.java deleted
1 -package cn.iocoder.yudao.module.system.dal.redis.social;  
2 -  
3 -import cn.iocoder.yudao.framework.common.util.json.JsonUtils;  
4 -import me.zhyd.oauth.model.AuthCallback;  
5 -import me.zhyd.oauth.model.AuthUser;  
6 -import org.springframework.data.redis.core.StringRedisTemplate;  
7 -import org.springframework.stereotype.Repository;  
8 -  
9 -import javax.annotation.Resource;  
10 -  
11 -import static cn.iocoder.yudao.module.system.dal.redis.RedisKeyConstants.SOCIAL_AUTH_USER;  
12 -  
13 -  
14 -/**  
15 - * 社交 {@link me.zhyd.oauth.model.AuthUser} 的 RedisDAO  
16 - *  
17 - * @author 芋道源码  
18 - */  
19 -@Repository  
20 -public class SocialAuthUserRedisDAO {  
21 -  
22 - @Resource  
23 - private StringRedisTemplate stringRedisTemplate;  
24 -  
25 - public AuthUser get(Integer type, AuthCallback authCallback) {  
26 - String redisKey = formatKey(type, authCallback.getCode());  
27 - return JsonUtils.parseObject(stringRedisTemplate.opsForValue().get(redisKey), AuthUser.class);  
28 - }  
29 -  
30 - public void set(Integer type, AuthCallback authCallback, AuthUser authUser) {  
31 - String redisKey = formatKey(type, authCallback.getCode());  
32 - stringRedisTemplate.opsForValue().set(redisKey, JsonUtils.toJsonString(authUser), SOCIAL_AUTH_USER.getTimeout());  
33 - }  
34 -  
35 - private static String formatKey(Integer type, String code) {  
36 - return String.format(SOCIAL_AUTH_USER.getKeyTemplate(), type, code);  
37 - }  
38 -  
39 -}  
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java
@@ -219,8 +219,7 @@ public class AdminAuthServiceImpl implements AdminAuthService { @@ -219,8 +219,7 @@ public class AdminAuthServiceImpl implements AdminAuthService {
219 @Override 219 @Override
220 public String socialLogin2(AuthSocialLogin2ReqVO reqVO, String userIp, String userAgent) { 220 public String socialLogin2(AuthSocialLogin2ReqVO reqVO, String userIp, String userAgent) {
221 // 使用 code 授权码,进行登录 221 // 使用 code 授权码,进行登录
222 - AuthUser authUser = socialUserService.getAuthUser(reqVO.getType(), reqVO.getCode(), reqVO.getState());  
223 - Assert.notNull(authUser, "授权用户不为空"); 222 + socialUserService.authSocialUser(reqVO.getType(), reqVO.getCode(), reqVO.getState());
224 223
225 // 使用账号密码,进行登录。 224 // 使用账号密码,进行登录。
226 LoginUser loginUser = this.login0(reqVO.getUsername(), reqVO.getPassword()); 225 LoginUser loginUser = this.login0(reqVO.getUsername(), reqVO.getPassword());
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserService.java
1 package cn.iocoder.yudao.module.system.service.social; 1 package cn.iocoder.yudao.module.system.service.social;
2 2
3 -import cn.hutool.core.util.StrUtil;  
4 import cn.iocoder.yudao.framework.common.exception.ServiceException; 3 import cn.iocoder.yudao.framework.common.exception.ServiceException;
5 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; 4 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO;
6 import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserDO; 5 import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserDO;
7 import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; 6 import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum;
8 -import me.zhyd.oauth.model.AuthUser;  
9 7
10 import javax.validation.Valid; 8 import javax.validation.Valid;
11 import javax.validation.constraints.NotNull; 9 import javax.validation.constraints.NotNull;
@@ -28,7 +26,7 @@ public interface SocialUserService { @@ -28,7 +26,7 @@ public interface SocialUserService {
28 String getAuthorizeUrl(Integer type, String redirectUri); 26 String getAuthorizeUrl(Integer type, String redirectUri);
29 27
30 /** 28 /**
31 - * 获得授权的用户 29 + * 授权获得对应的社交用户
32 * 如果授权失败,则会抛出 {@link ServiceException} 异常 30 * 如果授权失败,则会抛出 {@link ServiceException} 异常
33 * 31 *
34 * @param type 社交平台的类型 {@link SocialTypeEnum} 32 * @param type 社交平台的类型 {@link SocialTypeEnum}
@@ -37,17 +35,7 @@ public interface SocialUserService { @@ -37,17 +35,7 @@ public interface SocialUserService {
37 * @return 授权用户 35 * @return 授权用户
38 */ 36 */
39 @NotNull 37 @NotNull
40 - AuthUser getAuthUser(Integer type, String code, String state);  
41 -  
42 - /**  
43 - * 获得社交用户的 unionId 编号  
44 - *  
45 - * @param authUser 社交用户  
46 - * @return unionId 编号  
47 - */  
48 - default String getAuthUserUnionId(AuthUser authUser) {  
49 - return StrUtil.blankToDefault(authUser.getToken().getUnionId(), authUser.getUuid());  
50 - } 38 + SocialUserDO authSocialUser(Integer type, String code, String state);
51 39
52 /** 40 /**
53 * 获得指定用户的社交用户列表 41 * 获得指定用户的社交用户列表
@@ -71,25 +59,14 @@ public interface SocialUserService { @@ -71,25 +59,14 @@ public interface SocialUserService {
71 * @param userId 用户编号 59 * @param userId 用户编号
72 * @param userType 全局用户类型 60 * @param userType 全局用户类型
73 * @param type 社交平台的类型 {@link SocialTypeEnum} 61 * @param type 社交平台的类型 {@link SocialTypeEnum}
74 - * @param unionId 社交平台的 unionId  
75 - */  
76 - void unbindSocialUser(Long userId, Integer userType, Integer type, String unionId);  
77 -  
78 - /**  
79 - * 校验社交用户的认证信息是否正确  
80 - * 如果校验不通过,则抛出 {@link ServiceException} 业务异常  
81 - *  
82 - * @param type 社交平台的类型  
83 - * @param code 授权码  
84 - * @param state state 62 + * @param openid 社交平台的 openid
85 */ 63 */
86 - void checkSocialUser(Integer type, String code, String state); 64 + void unbindSocialUser(Long userId, Integer userType, Integer type, String openid);
87 65
88 /** 66 /**
89 * 获得社交用户的绑定用户编号 67 * 获得社交用户的绑定用户编号
90 * 注意,返回的是 MemberUser 或者 AdminUser 的 id 编号! 68 * 注意,返回的是 MemberUser 或者 AdminUser 的 id 编号!
91 - * 该方法会执行和 {@link #checkSocialUser(Integer, String, String)} 一样的逻辑。  
92 - * 所以在认证信息不正确的情况下,也会抛出 {@link ServiceException} 业务异常 69 + * 在认证信息不正确的情况下,也会抛出 {@link ServiceException} 业务异常
93 * 70 *
94 * @param userType 用户类型 71 * @param userType 用户类型
95 * @param type 社交平台的类型 72 * @param type 社交平台的类型
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImpl.java
1 package cn.iocoder.yudao.module.system.service.social; 1 package cn.iocoder.yudao.module.system.service.social;
2 2
3 -import cn.hutool.core.collection.CollUtil;  
4 -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; 3 +import cn.hutool.core.lang.Assert;
  4 +import cn.hutool.core.util.StrUtil;
5 import cn.iocoder.yudao.framework.common.util.http.HttpUtils; 5 import cn.iocoder.yudao.framework.common.util.http.HttpUtils;
6 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; 6 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO;
  7 +import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserBindDO;
7 import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserDO; 8 import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserDO;
  9 +import cn.iocoder.yudao.module.system.dal.mysql.social.SocialUserBindMapper;
8 import cn.iocoder.yudao.module.system.dal.mysql.social.SocialUserMapper; 10 import cn.iocoder.yudao.module.system.dal.mysql.social.SocialUserMapper;
9 -import cn.iocoder.yudao.module.system.dal.redis.social.SocialAuthUserRedisDAO;  
10 import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum; 11 import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum;
11 -import com.google.common.annotations.VisibleForTesting;  
12 import com.xkcoding.justauth.AuthRequestFactory; 12 import com.xkcoding.justauth.AuthRequestFactory;
13 import lombok.extern.slf4j.Slf4j; 13 import lombok.extern.slf4j.Slf4j;
14 import me.zhyd.oauth.model.AuthCallback; 14 import me.zhyd.oauth.model.AuthCallback;
@@ -22,7 +22,6 @@ import org.springframework.validation.annotation.Validated; @@ -22,7 +22,6 @@ import org.springframework.validation.annotation.Validated;
22 22
23 import javax.annotation.Resource; 23 import javax.annotation.Resource;
24 import java.util.List; 24 import java.util.List;
25 -import java.util.Objects;  
26 25
27 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 26 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
28 import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString; 27 import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
@@ -42,8 +41,7 @@ public class SocialUserServiceImpl implements SocialUserService { @@ -42,8 +41,7 @@ public class SocialUserServiceImpl implements SocialUserService {
42 private AuthRequestFactory authRequestFactory; 41 private AuthRequestFactory authRequestFactory;
43 42
44 @Resource 43 @Resource
45 - private SocialAuthUserRedisDAO authSocialUserRedisDAO;  
46 - 44 + private SocialUserBindMapper socialUserBindMapper;
47 @Resource 45 @Resource
48 private SocialUserMapper socialUserMapper; 46 private SocialUserMapper socialUserMapper;
49 47
@@ -57,149 +55,85 @@ public class SocialUserServiceImpl implements SocialUserService { @@ -57,149 +55,85 @@ public class SocialUserServiceImpl implements SocialUserService {
57 } 55 }
58 56
59 @Override 57 @Override
60 - public AuthUser getAuthUser(Integer type, String code, String state) {  
61 - AuthCallback authCallback = buildAuthCallback(code, state);  
62 - // 从缓存中获取  
63 - AuthUser authUser = authSocialUserRedisDAO.get(type, authCallback);  
64 - if (authUser != null) {  
65 - return authUser; 58 + public SocialUserDO authSocialUser(Integer type, String code, String state) {
  59 + // 优先从 DB 中获取,因为 code 有且可以使用一次。
  60 + // 在社交登录时,当未绑定 User 时,需要绑定登录,此时需要 code 使用两次
  61 + SocialUserDO socialUser = socialUserMapper.selectByTypeAndCodeAnState(type, code, state);
  62 + if (socialUser != null) {
  63 + return socialUser;
66 } 64 }
67 65
68 // 请求获取 66 // 请求获取
69 - authUser = this.getAuthUser0(type, authCallback);  
70 - // 缓存。原因是 code 有且可以使用一次。在社交登录时,当未绑定 User 时,需要绑定登录,此时需要 code 使用两次  
71 - authSocialUserRedisDAO.set(type, authCallback, authUser);  
72 - return authUser;  
73 - }  
74 -  
75 - /**  
76 - * 获得 unionId 对应的某个社交平台的“所有”社交用户  
77 - * 注意,这里的“所有”,指的是类似【微信】平台,包括了小程序、公众号、PC 网站,他们的 unionId 是一致的  
78 - *  
79 - * @param type 社交平台的类型 {@link SocialTypeEnum}  
80 - * @param unionId 社交平台的 unionId  
81 - * @param userType 全局用户类型  
82 - * @return 社交用户列表  
83 - */  
84 - private List<SocialUserDO> getAllSocialUserList(Integer type, String unionId, Integer userType) {  
85 - List<Integer> types = SocialTypeEnum.getRelationTypes(type);  
86 - return socialUserMapper.selectListByTypeAndUnionId(userType, types, unionId);  
87 - }  
88 -  
89 - @Override  
90 - public List<SocialUserDO> getSocialUserList(Long userId, Integer userType) {  
91 - return socialUserMapper.selectListByUserId(userType, userId);  
92 - }  
93 -  
94 - @Override  
95 - public void bindSocialUser(SocialUserBindReqDTO reqDTO) {  
96 - // 使用 code 授权  
97 - AuthUser authUser = getAuthUser(reqDTO.getType(), reqDTO.getCode(),  
98 - reqDTO.getState()); 67 + AuthUser authUser = getAuthUser(type, buildAuthCallback(code, state));
99 if (authUser == null) { 68 if (authUser == null) {
100 throw exception(SOCIAL_USER_NOT_FOUND); 69 throw exception(SOCIAL_USER_NOT_FOUND);
101 } 70 }
102 71
103 - // 绑定社交用户(新增)  
104 - bindSocialUser(reqDTO.getUserId(), reqDTO.getUserType(),  
105 - reqDTO.getType(), authUser);  
106 - }  
107 -  
108 - /**  
109 - * 绑定社交用户  
110 - * @param userId 用户编号  
111 - * @param userType 用户类型  
112 - * @param type 社交平台的类型 {@link SocialTypeEnum}  
113 - * @param authUser 授权用户  
114 - */  
115 - @Transactional(rollbackFor = Exception.class)  
116 - protected void bindSocialUser(Long userId, Integer userType, Integer type, AuthUser authUser) {  
117 - // 获得 unionId 对应的 SocialUserDO 列表  
118 - String unionId = getAuthUserUnionId(authUser);  
119 - List<SocialUserDO> socialUsers = this.getAllSocialUserList(type, unionId, userType);  
120 -  
121 - // 逻辑一:如果 userId 之前绑定过该 type 的其它账号,需要进行解绑  
122 - this.unbindOldSocialUser(userId, userType, type, unionId);  
123 -  
124 - // 逻辑二:如果 socialUsers 指定的 userId 改变,需要进行更新  
125 - // 例如说,一个微信 unionId 对应了多个社交账号,结果其中有个关联了新的 userId,则其它也要跟着修改  
126 - // 考虑到 socialUsers 一般比较少,直接 for 循环更新即可  
127 - socialUsers.forEach(socialUser -> {  
128 - if (Objects.equals(socialUser.getUserId(), userId)) {  
129 - return;  
130 - }  
131 - socialUserMapper.updateById(new SocialUserDO().setId(socialUser.getId()).setUserId(userId));  
132 - });  
133 -  
134 - // 逻辑三:如果 authUser 不存在于 socialUsers 中,则进行新增;否则,进行更新  
135 - SocialUserDO socialUser = CollUtil.findOneByField(socialUsers, "openid", authUser.getUuid());  
136 - SocialUserDO saveSocialUser = SocialUserDO.builder() // 新增和更新的通用属性  
137 - .token(authUser.getToken().getAccessToken()).rawTokenInfo(toJsonString(authUser.getToken()))  
138 - .nickname(authUser.getNickname()).avatar(authUser.getAvatar()).rawUserInfo(toJsonString(authUser.getRawUserInfo()))  
139 - .build(); 72 + // 保存到 DB 中
  73 + socialUser = socialUserMapper.selectByTypeAndOpenid(type, authUser.getUuid());
140 if (socialUser == null) { 74 if (socialUser == null) {
141 - saveSocialUser.setUserId(userId).setUserType(userType)  
142 - .setType(type).setOpenid(authUser.getUuid()).setUnionId(unionId);  
143 - socialUserMapper.insert(saveSocialUser); 75 + socialUser = new SocialUserDO();
  76 + }
  77 + socialUser.setOpenid(authUser.getUuid()).setToken(authUser.getToken().getAccessToken()).setRawTokenInfo((toJsonString(authUser.getToken())))
  78 + .setUnionId(StrUtil.blankToDefault(authUser.getToken().getUnionId(), authUser.getUuid())) // unionId 识别多个用户
  79 + .setNickname(authUser.getNickname()).setAvatar(authUser.getAvatar()).setRawUserInfo(toJsonString(authUser.getRawUserInfo()))
  80 + .setCode(code).setState(state); // 需要保存 code + state 字段,保证后续可查询
  81 + if (socialUser.getId() == null) {
  82 + socialUserMapper.insert(socialUser);
144 } else { 83 } else {
145 - saveSocialUser.setId(socialUser.getId());  
146 - socialUserMapper.updateById(saveSocialUser); 84 + socialUserMapper.updateById(socialUser);
147 } 85 }
  86 + return socialUser;
148 } 87 }
149 88
150 @Override 89 @Override
151 - public void unbindSocialUser(Long userId, Integer userType, Integer type, String unionId) {  
152 - // 获得 unionId 对应的所有 SocialUserDO 社交用户  
153 - List<SocialUserDO> socialUsers = this.getAllSocialUserList(type, unionId, userType);  
154 - if (CollUtil.isEmpty(socialUsers)) {  
155 - return;  
156 - }  
157 - // 校验,是否解绑的是非自己的  
158 - socialUsers.forEach(socialUser -> {  
159 - if (!Objects.equals(socialUser.getUserId(), userId)) {  
160 - throw exception(SOCIAL_USER_UNBIND_NOT_SELF);  
161 - }  
162 - });  
163 -  
164 - // 解绑  
165 - socialUserMapper.deleteBatchIds(CollectionUtils.convertSet(socialUsers, SocialUserDO::getId)); 90 + public List<SocialUserDO> getSocialUserList(Long userId, Integer userType) {
  91 + return socialUserMapper.selectListByUserId(userType, userId);
166 } 92 }
167 93
168 @Override 94 @Override
169 - public void checkSocialUser(Integer type, String code, String state) {  
170 - AuthUser authUser = getAuthUser(type, code, state);  
171 - if (authUser == null) {  
172 - throw exception(SOCIAL_USER_NOT_FOUND);  
173 - } 95 + @Transactional
  96 + public void bindSocialUser(SocialUserBindReqDTO reqDTO) {
  97 + // 获得社交用户
  98 + SocialUserDO socialUser = authSocialUser(reqDTO.getType(), reqDTO.getCode(), reqDTO.getState());
  99 + Assert.notNull(socialUser, "社交用户不能为空");
  100 +
  101 + // 如果 userId 之前绑定过该 type 的其它账号,需要进行解绑
  102 + socialUserBindMapper.deleteByUserTypeAndUserIdAndPlatformAndUnionId(reqDTO.getUserType(), reqDTO.getUserId(),
  103 + SocialTypeEnum.valueOfType(socialUser.getType()).getPlatform(), socialUser.getUnionId());
  104 +
  105 + // 绑定当前登录的社交用户
  106 + SocialUserBindDO socialUserBind = SocialUserBindDO.builder().userId(reqDTO.getUserId()).userType(reqDTO.getUserType())
  107 + .unionId(socialUser.getUnionId()).build();
  108 + socialUserBindMapper.insert(socialUserBind);
174 } 109 }
175 110
176 @Override 111 @Override
177 - public Long getBindUserId(Integer userType, Integer type, String code, String state) {  
178 - AuthUser authUser = getAuthUser(type, code, state);  
179 - if (authUser == null) { 112 + public void unbindSocialUser(Long userId, Integer userType, Integer type, String openid) {
  113 + // 获得 openid 对应的 SocialUserDO 社交用户
  114 + SocialUserDO socialUser = socialUserMapper.selectByTypeAndOpenid(type, openid);
  115 + if (socialUser == null) {
180 throw exception(SOCIAL_USER_NOT_FOUND); 116 throw exception(SOCIAL_USER_NOT_FOUND);
181 } 117 }
182 118
183 - // 如果未绑定 SocialUserDO 用户,则无法自动登录,进行报错  
184 - String unionId = getAuthUserUnionId(authUser);  
185 - List<SocialUserDO> socialUsers = getAllSocialUserList(type, unionId, userType);  
186 - if (CollUtil.isEmpty(socialUsers)) {  
187 - throw exception(AUTH_THIRD_LOGIN_NOT_BIND);  
188 - }  
189 - return socialUsers.get(0).getUserId(); 119 + // 获得对应的社交绑定关系
  120 + socialUserBindMapper.deleteByUserTypeAndUserIdAndPlatformAndUnionId(userType, userId,
  121 + SocialTypeEnum.valueOfType(socialUser.getType()).getPlatform(), socialUser.getUnionId());
190 } 122 }
191 123
192 - @VisibleForTesting  
193 - public void unbindOldSocialUser(Long userId, Integer userType, Integer type, String newUnionId) {  
194 - List<Integer> types = SocialTypeEnum.getRelationTypes(type);  
195 - List<SocialUserDO> oldSocialUsers = socialUserMapper.selectListByTypeAndUserId(userType, types, userId);  
196 - // 如果新老的 unionId 是一致的,说明无需解绑  
197 - if (CollUtil.isEmpty(oldSocialUsers) || Objects.equals(newUnionId, oldSocialUsers.get(0).getUnionId())) {  
198 - return; 124 + @Override
  125 + public Long getBindUserId(Integer userType, Integer type, String code, String state) {
  126 + // 获得社交用户
  127 + SocialUserDO socialUser = authSocialUser(type, code, state);
  128 + Assert.notNull(socialUser, "社交用户不能为空");
  129 +
  130 + // 如果未绑定的社交用户,则无法自动登录,进行报错
  131 + SocialUserBindDO socialUserBind = socialUserBindMapper.selectByUserTypeAndPlatformAndUnionId(userType,
  132 + SocialTypeEnum.valueOfType(socialUser.getType()).getPlatform(), socialUser.getUnionId());
  133 + if (socialUserBind == null) {
  134 + throw exception(AUTH_THIRD_LOGIN_NOT_BIND);
199 } 135 }
200 -  
201 - // 解绑  
202 - socialUserMapper.deleteBatchIds(CollectionUtils.convertSet(oldSocialUsers, SocialUserDO::getId)); 136 + return socialUserBind.getUserId();
203 } 137 }
204 138
205 /** 139 /**
@@ -209,7 +143,7 @@ public class SocialUserServiceImpl implements SocialUserService { @@ -209,7 +143,7 @@ public class SocialUserServiceImpl implements SocialUserService {
209 * @param authCallback 授权回调 143 * @param authCallback 授权回调
210 * @return 授权的用户 144 * @return 授权的用户
211 */ 145 */
212 - private AuthUser getAuthUser0(Integer type, AuthCallback authCallback) { 146 + private AuthUser getAuthUser(Integer type, AuthCallback authCallback) {
213 AuthRequest authRequest = authRequestFactory.get(SocialTypeEnum.valueOfType(type).getSource()); 147 AuthRequest authRequest = authRequestFactory.get(SocialTypeEnum.valueOfType(type).getSource());
214 AuthResponse<?> authResponse = authRequest.login(authCallback); 148 AuthResponse<?> authResponse = authRequest.login(authCallback);
215 log.info("[getAuthUser0][请求社交平台 type({}) request({}) response({})]", type, toJsonString(authCallback), 149 log.info("[getAuthUser0][请求社交平台 type({}) request({}) response({})]", type, toJsonString(authCallback),
yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceTest.java
1 package cn.iocoder.yudao.module.system.service.social; 1 package cn.iocoder.yudao.module.system.service.social;
2 2
3 -import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserDO;  
4 import cn.iocoder.yudao.module.system.dal.mysql.social.SocialUserMapper; 3 import cn.iocoder.yudao.module.system.dal.mysql.social.SocialUserMapper;
5 -import cn.iocoder.yudao.module.system.dal.redis.social.SocialAuthUserRedisDAO;  
6 -import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum;  
7 -import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;  
8 import cn.iocoder.yudao.framework.test.core.ut.BaseDbAndRedisUnitTest; 4 import cn.iocoder.yudao.framework.test.core.ut.BaseDbAndRedisUnitTest;
  5 +import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
9 import com.xkcoding.justauth.AuthRequestFactory; 6 import com.xkcoding.justauth.AuthRequestFactory;
10 -import me.zhyd.oauth.model.AuthUser; 7 +import me.zhyd.oauth.request.AuthRequest;
  8 +import me.zhyd.oauth.utils.AuthStateUtils;
11 import org.junit.jupiter.api.Test; 9 import org.junit.jupiter.api.Test;
  10 +import org.mockito.MockedStatic;
12 import org.springframework.boot.test.mock.mockito.MockBean; 11 import org.springframework.boot.test.mock.mockito.MockBean;
13 import org.springframework.context.annotation.Import; 12 import org.springframework.context.annotation.Import;
14 13
15 import javax.annotation.Resource; 14 import javax.annotation.Resource;
16 -import java.util.List;  
17 15
18 import static cn.hutool.core.util.RandomUtil.randomEle; 16 import static cn.hutool.core.util.RandomUtil.randomEle;
19 import static cn.hutool.core.util.RandomUtil.randomString; 17 import static cn.hutool.core.util.RandomUtil.randomString;
20 -import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;  
21 -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;  
22 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; 18 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
23 import static org.junit.jupiter.api.Assertions.assertEquals; 19 import static org.junit.jupiter.api.Assertions.assertEquals;
  20 +import static org.mockito.Mockito.*;
24 21
25 -@Import({SocialUserServiceImpl.class, SocialAuthUserRedisDAO.class}) 22 +@Import(SocialUserServiceImpl.class)
26 public class SocialUserServiceTest extends BaseDbAndRedisUnitTest { 23 public class SocialUserServiceTest extends BaseDbAndRedisUnitTest {
27 24
28 @Resource 25 @Resource
29 - private SocialUserServiceImpl socialService; 26 + private SocialUserServiceImpl socialUserService;
30 27
31 @Resource 28 @Resource
32 private SocialUserMapper socialUserMapper; 29 private SocialUserMapper socialUserMapper;
@@ -34,132 +31,152 @@ public class SocialUserServiceTest extends BaseDbAndRedisUnitTest { @@ -34,132 +31,152 @@ public class SocialUserServiceTest extends BaseDbAndRedisUnitTest {
34 @MockBean 31 @MockBean
35 private AuthRequestFactory authRequestFactory; 32 private AuthRequestFactory authRequestFactory;
36 33
37 - /**  
38 - * 情况一,创建 SocialUserDO 的情况  
39 - */  
40 @Test 34 @Test
41 - public void testBindSocialUser_create() {  
42 - // mock 数据  
43 - // 准备参数  
44 - Long userId = randomLongId();  
45 - Integer type = randomEle(SocialTypeEnum.values()).getType();  
46 - AuthUser authUser = randomPojo(AuthUser.class);  
47 - // mock 方法  
48 -  
49 - // 调用  
50 - socialService.bindSocialUser(userId, UserTypeEnum.ADMIN.getValue(), type, authUser);  
51 - // 断言  
52 - List<SocialUserDO> socialUsers = socialUserMapper.selectList("user_id", userId);  
53 - assertEquals(1, socialUsers.size());  
54 - assertBindSocialUser(socialUsers.get(0), authUser, userId, type);  
55 - }  
56 -  
57 - /**  
58 - * 情况二,更新 SocialUserDO 的情况  
59 - */  
60 - @Test  
61 - public void testBindSocialUser_update() {  
62 - // mock 数据  
63 - SocialUserDO dbSocialUser = randomPojo(SocialUserDO.class, socialUserDO -> {  
64 - socialUserDO.setUserType(UserTypeEnum.ADMIN.getValue());  
65 - socialUserDO.setType(randomEle(SocialTypeEnum.values()).getType());  
66 - });  
67 - socialUserMapper.insert(dbSocialUser);  
68 - // 准备参数  
69 - Long userId = dbSocialUser.getUserId();  
70 - Integer type = dbSocialUser.getType();  
71 - AuthUser authUser = randomPojo(AuthUser.class);  
72 - // mock 方法  
73 -  
74 - // 调用  
75 - socialService.bindSocialUser(userId, UserTypeEnum.ADMIN.getValue(), type, authUser);  
76 - // 断言  
77 - List<SocialUserDO> socialUsers = socialUserMapper.selectList("user_id", userId);  
78 - assertEquals(1, socialUsers.size());  
79 - assertBindSocialUser(socialUsers.get(0), authUser, userId, type); 35 + public void testGetAuthorizeUrl() {
  36 + try (MockedStatic<AuthStateUtils> authStateUtilsMock = mockStatic(AuthStateUtils.class)) {
  37 + // 准备参数
  38 + Integer type = 31;
  39 + String redirectUri = "sss";
  40 + // mock 获得对应的 AuthRequest 实现
  41 + AuthRequest authRequest = mock(AuthRequest.class);
  42 + when(authRequestFactory.get(eq("WECHAT_MP"))).thenReturn(authRequest);
  43 + // mock 方法
  44 + authStateUtilsMock.when(AuthStateUtils::createState).thenReturn("aoteman");
  45 + when(authRequest.authorize(eq("aoteman"))).thenReturn("https://www.iocoder.cn?redirect_uri=yyy");
  46 +
  47 + // 调用
  48 + String url = socialUserService.getAuthorizeUrl(type, redirectUri);
  49 + // 断言
  50 + assertEquals("https://www.iocoder.cn/?redirect_uri=sss", url);
  51 + }
80 } 52 }
81 53
82 - /**  
83 - * 情况一和二都存在的,逻辑二的场景  
84 - */  
85 - @Test  
86 - public void testBindSocialUser_userId() {  
87 - // mock 数据  
88 - SocialUserDO dbSocialUser = randomPojo(SocialUserDO.class, socialUserDO -> {  
89 - socialUserDO.setUserType(UserTypeEnum.ADMIN.getValue());  
90 - socialUserDO.setType(randomEle(SocialTypeEnum.values()).getType());  
91 - });  
92 - socialUserMapper.insert(dbSocialUser);  
93 - // 准备参数  
94 - Long userId = randomLongId();  
95 - Integer type = dbSocialUser.getType();  
96 - AuthUser authUser = randomPojo(AuthUser.class);  
97 - // mock 方法  
98 -  
99 - // 调用  
100 - socialService.bindSocialUser(userId, UserTypeEnum.ADMIN.getValue(), type, authUser);  
101 - // 断言  
102 - List<SocialUserDO> socialUsers = socialUserMapper.selectList("user_id", userId);  
103 - assertEquals(1, socialUsers.size());  
104 - }  
105 -  
106 - private void assertBindSocialUser(SocialUserDO socialUser, AuthUser authUser, Long userId,  
107 - Integer type) {  
108 - assertEquals(authUser.getToken().getAccessToken(), socialUser.getToken());  
109 - assertEquals(toJsonString(authUser.getToken()), socialUser.getRawTokenInfo());  
110 - assertEquals(authUser.getNickname(), socialUser.getNickname());  
111 - assertEquals(authUser.getAvatar(), socialUser.getAvatar());  
112 - assertEquals(toJsonString(authUser.getRawUserInfo()), socialUser.getRawUserInfo());  
113 - assertEquals(userId, socialUser.getUserId());  
114 - assertEquals(UserTypeEnum.ADMIN.getValue(), socialUser.getUserType());  
115 - assertEquals(type, socialUser.getType());  
116 - assertEquals(authUser.getUuid(), socialUser.getOpenid());  
117 - assertEquals(socialService.getAuthUserUnionId(authUser), socialUser.getUnionId());  
118 - }  
119 -  
120 - /**  
121 - * 情况一,如果新老的 unionId 是一致的,无需解绑  
122 - */  
123 - @Test  
124 - public void testUnbindOldSocialUser_no() {  
125 - // mock 数据  
126 - SocialUserDO oldSocialUser = randomPojo(SocialUserDO.class, socialUserDO -> {  
127 - socialUserDO.setUserType(UserTypeEnum.ADMIN.getValue());  
128 - socialUserDO.setType(randomEle(SocialTypeEnum.values()).getType());  
129 - });  
130 - socialUserMapper.insert(oldSocialUser);  
131 - // 准备参数  
132 - Long userId = oldSocialUser.getUserId();  
133 - Integer type = oldSocialUser.getType();  
134 - String newUnionId = oldSocialUser.getUnionId();  
135 -  
136 - // 调用  
137 - socialService.unbindOldSocialUser(userId, UserTypeEnum.ADMIN.getValue(), type, newUnionId);  
138 - // 断言  
139 - assertEquals(1L, socialUserMapper.selectCount(null).longValue());  
140 - }  
141 -  
142 -  
143 - /**  
144 - * 情况二,如果新老的 unionId 不一致的,需解绑  
145 - */  
146 - @Test  
147 - public void testUnbindOldSocialUser_yes() {  
148 - // mock 数据  
149 - SocialUserDO oldSocialUser = randomPojo(SocialUserDO.class, socialUserDO -> {  
150 - socialUserDO.setUserType(UserTypeEnum.ADMIN.getValue());  
151 - socialUserDO.setType(randomEle(SocialTypeEnum.values()).getType());  
152 - });  
153 - socialUserMapper.insert(oldSocialUser);  
154 - // 准备参数  
155 - Long userId = oldSocialUser.getUserId();  
156 - Integer type = oldSocialUser.getType();  
157 - String newUnionId = randomString(10);  
158 -  
159 - // 调用  
160 - socialService.unbindOldSocialUser(userId, UserTypeEnum.ADMIN.getValue(), type, newUnionId);  
161 - // 断言  
162 - assertEquals(0L, socialUserMapper.selectCount(null).longValue());  
163 - } 54 +// /**
  55 +// * 情况一,创建 SocialUserDO 的情况
  56 +// */
  57 +// @Test
  58 +// public void testBindSocialUser_create() {
  59 +// // mock 数据
  60 +// // 准备参数
  61 +// Long userId = randomLongId();
  62 +// Integer type = randomEle(SocialTypeEnum.values()).getType();
  63 +// AuthUser authUser = randomPojo(AuthUser.class);
  64 +// // mock 方法
  65 +//
  66 +// // 调用
  67 +// socialService.bindSocialUser(userId, UserTypeEnum.ADMIN.getValue(), type, authUser);
  68 +// // 断言
  69 +// List<SocialUserDO> socialUsers = socialUserMapper.selectList("user_id", userId);
  70 +// assertEquals(1, socialUsers.size());
  71 +// assertBindSocialUser(socialUsers.get(0), authUser, userId, type);
  72 +// }
  73 +//
  74 +// /**
  75 +// * 情况二,更新 SocialUserDO 的情况
  76 +// */
  77 +// @Test
  78 +// public void testBindSocialUser_update() {
  79 +// // mock 数据
  80 +// SocialUserDO dbSocialUser = randomPojo(SocialUserDO.class, socialUserDO -> {
  81 +// socialUserDO.setUserType(UserTypeEnum.ADMIN.getValue());
  82 +// socialUserDO.setType(randomEle(SocialTypeEnum.values()).getType());
  83 +// });
  84 +// socialUserMapper.insert(dbSocialUser);
  85 +// // 准备参数
  86 +// Long userId = dbSocialUser.getUserId();
  87 +// Integer type = dbSocialUser.getType();
  88 +// AuthUser authUser = randomPojo(AuthUser.class);
  89 +// // mock 方法
  90 +//
  91 +// // 调用
  92 +// socialService.bindSocialUser(userId, UserTypeEnum.ADMIN.getValue(), type, authUser);
  93 +// // 断言
  94 +// List<SocialUserDO> socialUsers = socialUserMapper.selectList("user_id", userId);
  95 +// assertEquals(1, socialUsers.size());
  96 +// assertBindSocialUser(socialUsers.get(0), authUser, userId, type);
  97 +// }
  98 +//
  99 +// /**
  100 +// * 情况一和二都存在的,逻辑二的场景
  101 +// */
  102 +// @Test
  103 +// public void testBindSocialUser_userId() {
  104 +// // mock 数据
  105 +// SocialUserDO dbSocialUser = randomPojo(SocialUserDO.class, socialUserDO -> {
  106 +// socialUserDO.setUserType(UserTypeEnum.ADMIN.getValue());
  107 +// socialUserDO.setType(randomEle(SocialTypeEnum.values()).getType());
  108 +// });
  109 +// socialUserMapper.insert(dbSocialUser);
  110 +// // 准备参数
  111 +// Long userId = randomLongId();
  112 +// Integer type = dbSocialUser.getType();
  113 +// AuthUser authUser = randomPojo(AuthUser.class);
  114 +// // mock 方法
  115 +//
  116 +// // 调用
  117 +// socialService.bindSocialUser(userId, UserTypeEnum.ADMIN.getValue(), type, authUser);
  118 +// // 断言
  119 +// List<SocialUserDO> socialUsers = socialUserMapper.selectList("user_id", userId);
  120 +// assertEquals(1, socialUsers.size());
  121 +// }
  122 +//
  123 +// private void assertBindSocialUser(SocialUserDO socialUser, AuthUser authUser, Long userId,
  124 +// Integer type) {
  125 +// assertEquals(authUser.getToken().getAccessToken(), socialUser.getToken());
  126 +// assertEquals(toJsonString(authUser.getToken()), socialUser.getRawTokenInfo());
  127 +// assertEquals(authUser.getNickname(), socialUser.getNickname());
  128 +// assertEquals(authUser.getAvatar(), socialUser.getAvatar());
  129 +// assertEquals(toJsonString(authUser.getRawUserInfo()), socialUser.getRawUserInfo());
  130 +// assertEquals(userId, socialUser.getUserId());
  131 +// assertEquals(UserTypeEnum.ADMIN.getValue(), socialUser.getUserType());
  132 +// assertEquals(type, socialUser.getType());
  133 +// assertEquals(authUser.getUuid(), socialUser.getOpenid());
  134 +// assertEquals(socialService.getAuthUserUnionId(authUser), socialUser.getUnionId());
  135 +// }
  136 +//
  137 +// /**
  138 +// * 情况一,如果新老的 unionId 是一致的,无需解绑
  139 +// */
  140 +// @Test
  141 +// public void testUnbindOldSocialUser_no() {
  142 +// // mock 数据
  143 +// SocialUserDO oldSocialUser = randomPojo(SocialUserDO.class, socialUserDO -> {
  144 +// socialUserDO.setUserType(UserTypeEnum.ADMIN.getValue());
  145 +// socialUserDO.setType(randomEle(SocialTypeEnum.values()).getType());
  146 +// });
  147 +// socialUserMapper.insert(oldSocialUser);
  148 +// // 准备参数
  149 +// Long userId = oldSocialUser.getUserId();
  150 +// Integer type = oldSocialUser.getType();
  151 +// String newUnionId = oldSocialUser.getUnionId();
  152 +//
  153 +// // 调用
  154 +// socialService.unbindOldSocialUser(userId, UserTypeEnum.ADMIN.getValue(), type, newUnionId);
  155 +// // 断言
  156 +// assertEquals(1L, socialUserMapper.selectCount(null).longValue());
  157 +// }
  158 +//
  159 +//
  160 +// /**
  161 +// * 情况二,如果新老的 unionId 不一致的,需解绑
  162 +// */
  163 +// @Test
  164 +// public void testUnbindOldSocialUser_yes() {
  165 +// // mock 数据
  166 +// SocialUserDO oldSocialUser = randomPojo(SocialUserDO.class, socialUserDO -> {
  167 +// socialUserDO.setUserType(UserTypeEnum.ADMIN.getValue());
  168 +// socialUserDO.setType(randomEle(SocialTypeEnum.values()).getType());
  169 +// });
  170 +// socialUserMapper.insert(oldSocialUser);
  171 +// // 准备参数
  172 +// Long userId = oldSocialUser.getUserId();
  173 +// Integer type = oldSocialUser.getType();
  174 +// String newUnionId = randomString(10);
  175 +//
  176 +// // 调用
  177 +// socialService.unbindOldSocialUser(userId, UserTypeEnum.ADMIN.getValue(), type, newUnionId);
  178 +// // 断言
  179 +// assertEquals(0L, socialUserMapper.selectCount(null).longValue());
  180 +// }
164 181
165 } 182 }