refactor(system): 社交绑定列表逻辑下沉至 Service 层
将 SocialUserBindMapper 从 Controller 移除,数据组装逻辑移至 SocialUserService.getSocialUserBindList(),返回绑定时间字段; 修复 avatar 误用 getNickname() 的 bug Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,82 +1,79 @@
|
||||
package com.viewsh.module.system.controller.admin.socail;
|
||||
|
||||
import com.viewsh.framework.common.enums.UserTypeEnum;
|
||||
import com.viewsh.framework.common.pojo.CommonResult;
|
||||
import com.viewsh.framework.common.pojo.PageResult;
|
||||
import com.viewsh.framework.common.util.object.BeanUtils;
|
||||
import com.viewsh.module.system.api.social.dto.SocialUserBindReqDTO;
|
||||
import com.viewsh.module.system.controller.admin.socail.vo.user.SocialUserBindReqVO;
|
||||
import com.viewsh.module.system.controller.admin.socail.vo.user.SocialUserPageReqVO;
|
||||
import com.viewsh.module.system.controller.admin.socail.vo.user.SocialUserRespVO;
|
||||
import com.viewsh.module.system.controller.admin.socail.vo.user.SocialUserUnbindReqVO;
|
||||
import com.viewsh.module.system.dal.dataobject.social.SocialUserDO;
|
||||
import com.viewsh.module.system.service.social.SocialUserService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static com.viewsh.framework.common.pojo.CommonResult.success;
|
||||
import static com.viewsh.framework.common.util.collection.CollectionUtils.convertList;
|
||||
import static com.viewsh.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
|
||||
|
||||
@Tag(name = "管理后台 - 社交用户")
|
||||
@RestController
|
||||
@RequestMapping("/system/social-user")
|
||||
@Validated
|
||||
public class SocialUserController {
|
||||
|
||||
@Resource
|
||||
private SocialUserService socialUserService;
|
||||
|
||||
@PostMapping("/bind")
|
||||
@Operation(summary = "社交绑定,使用 code 授权码")
|
||||
public CommonResult<Boolean> socialBind(@RequestBody @Valid SocialUserBindReqVO reqVO) {
|
||||
socialUserService.bindSocialUser(new SocialUserBindReqDTO().setSocialType(reqVO.getType())
|
||||
.setCode(reqVO.getCode()).setState(reqVO.getState())
|
||||
.setUserId(getLoginUserId()).setUserType(UserTypeEnum.ADMIN.getValue()));
|
||||
return CommonResult.success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/unbind")
|
||||
@Operation(summary = "取消社交绑定")
|
||||
public CommonResult<Boolean> socialUnbind(@RequestBody SocialUserUnbindReqVO reqVO) {
|
||||
socialUserService.unbindSocialUser(getLoginUserId(), UserTypeEnum.ADMIN.getValue(), reqVO.getType(), reqVO.getOpenid());
|
||||
return CommonResult.success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get-bind-list")
|
||||
@Operation(summary = "获得绑定社交用户列表")
|
||||
public CommonResult<List<SocialUserRespVO>> getBindSocialUserList() {
|
||||
List<SocialUserDO> list = socialUserService.getSocialUserList(getLoginUserId(), UserTypeEnum.ADMIN.getValue());
|
||||
return success(convertList(list, socialUser -> new SocialUserRespVO() // 返回精简信息
|
||||
.setId(socialUser.getId()).setType(socialUser.getType()).setOpenid(socialUser.getOpenid())
|
||||
.setNickname(socialUser.getNickname()).setAvatar(socialUser.getNickname())));
|
||||
}
|
||||
|
||||
// ==================== 社交用户 CRUD ====================
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得社交用户")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('system:social-user:query')")
|
||||
public CommonResult<SocialUserRespVO> getSocialUser(@RequestParam("id") Long id) {
|
||||
SocialUserDO socialUser = socialUserService.getSocialUser(id);
|
||||
return success(BeanUtils.toBean(socialUser, SocialUserRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得社交用户分页")
|
||||
@PreAuthorize("@ss.hasPermission('system:social-user:query')")
|
||||
public CommonResult<PageResult<SocialUserRespVO>> getSocialUserPage(@Valid SocialUserPageReqVO pageVO) {
|
||||
PageResult<SocialUserDO> pageResult = socialUserService.getSocialUserPage(pageVO);
|
||||
return success(BeanUtils.toBean(pageResult, SocialUserRespVO.class));
|
||||
}
|
||||
|
||||
}
|
||||
package com.viewsh.module.system.controller.admin.socail;
|
||||
|
||||
import com.viewsh.framework.common.enums.UserTypeEnum;
|
||||
import com.viewsh.framework.common.pojo.CommonResult;
|
||||
import com.viewsh.framework.common.pojo.PageResult;
|
||||
import com.viewsh.framework.common.util.object.BeanUtils;
|
||||
import com.viewsh.module.system.api.social.dto.SocialUserBindReqDTO;
|
||||
import com.viewsh.module.system.controller.admin.socail.vo.user.SocialUserBindReqVO;
|
||||
import com.viewsh.module.system.controller.admin.socail.vo.user.SocialUserPageReqVO;
|
||||
import com.viewsh.module.system.controller.admin.socail.vo.user.SocialUserRespVO;
|
||||
import com.viewsh.module.system.controller.admin.socail.vo.user.SocialUserUnbindReqVO;
|
||||
import com.viewsh.module.system.dal.dataobject.social.SocialUserDO;
|
||||
import com.viewsh.module.system.service.social.SocialUserService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.Valid;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static com.viewsh.framework.common.pojo.CommonResult.success;
|
||||
import static com.viewsh.framework.common.util.collection.CollectionUtils.convertList;
|
||||
import static com.viewsh.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
|
||||
|
||||
@Tag(name = "管理后台 - 社交用户")
|
||||
@RestController
|
||||
@RequestMapping("/system/social-user")
|
||||
@Validated
|
||||
public class SocialUserController {
|
||||
|
||||
@Resource
|
||||
private SocialUserService socialUserService;
|
||||
|
||||
@PostMapping("/bind")
|
||||
@Operation(summary = "社交绑定,使用 code 授权码")
|
||||
public CommonResult<Boolean> socialBind(@RequestBody @Valid SocialUserBindReqVO reqVO) {
|
||||
socialUserService.bindSocialUser(new SocialUserBindReqDTO().setSocialType(reqVO.getType())
|
||||
.setCode(reqVO.getCode()).setState(reqVO.getState())
|
||||
.setUserId(getLoginUserId()).setUserType(UserTypeEnum.ADMIN.getValue()));
|
||||
return CommonResult.success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/unbind")
|
||||
@Operation(summary = "取消社交绑定")
|
||||
public CommonResult<Boolean> socialUnbind(@RequestBody SocialUserUnbindReqVO reqVO) {
|
||||
socialUserService.unbindSocialUser(getLoginUserId(), UserTypeEnum.ADMIN.getValue(), reqVO.getType(), reqVO.getOpenid());
|
||||
return CommonResult.success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get-bind-list")
|
||||
@Operation(summary = "获得绑定社交用户列表")
|
||||
public CommonResult<List<SocialUserRespVO>> getBindSocialUserList() {
|
||||
return success(socialUserService.getSocialUserBindList(getLoginUserId(), UserTypeEnum.ADMIN.getValue()));
|
||||
}
|
||||
|
||||
// ==================== 社交用户 CRUD ====================
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得社交用户")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('system:social-user:query')")
|
||||
public CommonResult<SocialUserRespVO> getSocialUser(@RequestParam("id") Long id) {
|
||||
SocialUserDO socialUser = socialUserService.getSocialUser(id);
|
||||
return success(BeanUtils.toBean(socialUser, SocialUserRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得社交用户分页")
|
||||
@PreAuthorize("@ss.hasPermission('system:social-user:query')")
|
||||
public CommonResult<PageResult<SocialUserRespVO>> getSocialUserPage(@Valid SocialUserPageReqVO pageVO) {
|
||||
PageResult<SocialUserDO> pageResult = socialUserService.getSocialUserPage(pageVO);
|
||||
return success(BeanUtils.toBean(pageResult, SocialUserRespVO.class));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,48 +1,48 @@
|
||||
package com.viewsh.module.system.controller.admin.socail.vo.user;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - 社交用户 Response VO")
|
||||
@Data
|
||||
public class SocialUserRespVO {
|
||||
|
||||
@Schema(description = "主键(自增策略)", requiredMode = Schema.RequiredMode.REQUIRED, example = "14569")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "社交平台的类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "30")
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "社交 openid", requiredMode = Schema.RequiredMode.REQUIRED, example = "666")
|
||||
private String openid;
|
||||
|
||||
@Schema(description = "社交 token", requiredMode = Schema.RequiredMode.REQUIRED, example = "666")
|
||||
private String token;
|
||||
|
||||
@Schema(description = "原始 Token 数据,一般是 JSON 格式", requiredMode = Schema.RequiredMode.REQUIRED, example = "{}")
|
||||
private String rawTokenInfo;
|
||||
|
||||
@Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿")
|
||||
private String nickname;
|
||||
|
||||
@Schema(description = "用户头像", example = "https://www.iocoder.cn/xxx.png")
|
||||
private String avatar;
|
||||
|
||||
@Schema(description = "原始用户数据,一般是 JSON 格式", requiredMode = Schema.RequiredMode.REQUIRED, example = "{}")
|
||||
private String rawUserInfo;
|
||||
|
||||
@Schema(description = "最后一次的认证 code", requiredMode = Schema.RequiredMode.REQUIRED, example = "666666")
|
||||
private String code;
|
||||
|
||||
@Schema(description = "最后一次的认证 state", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456")
|
||||
private String state;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
||||
package com.viewsh.module.system.controller.admin.socail.vo.user;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - 社交用户 Response VO")
|
||||
@Data
|
||||
public class SocialUserRespVO {
|
||||
|
||||
@Schema(description = "主键(自增策略)", requiredMode = Schema.RequiredMode.REQUIRED, example = "14569")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "社交平台的类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "30")
|
||||
private Integer type;
|
||||
|
||||
@Schema(description = "社交 openid", requiredMode = Schema.RequiredMode.REQUIRED, example = "666")
|
||||
private String openid;
|
||||
|
||||
@Schema(description = "社交 token", requiredMode = Schema.RequiredMode.REQUIRED, example = "666")
|
||||
private String token;
|
||||
|
||||
@Schema(description = "原始 Token 数据,一般是 JSON 格式", requiredMode = Schema.RequiredMode.REQUIRED, example = "{}")
|
||||
private String rawTokenInfo;
|
||||
|
||||
@Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿")
|
||||
private String nickname;
|
||||
|
||||
@Schema(description = "用户头像", example = "https://www.iocoder.cn/xxx.png")
|
||||
private String avatar;
|
||||
|
||||
@Schema(description = "原始用户数据,一般是 JSON 格式", requiredMode = Schema.RequiredMode.REQUIRED, example = "{}")
|
||||
private String rawUserInfo;
|
||||
|
||||
@Schema(description = "最后一次的认证 code", requiredMode = Schema.RequiredMode.REQUIRED, example = "666666")
|
||||
private String code;
|
||||
|
||||
@Schema(description = "最后一次的认证 state", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456")
|
||||
private String state;
|
||||
|
||||
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private LocalDateTime updateTime;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,89 +1,90 @@
|
||||
package com.viewsh.module.system.service.social;
|
||||
|
||||
import com.viewsh.framework.common.exception.ServiceException;
|
||||
import com.viewsh.framework.common.pojo.PageResult;
|
||||
import com.viewsh.module.system.api.social.dto.SocialUserBindReqDTO;
|
||||
import com.viewsh.module.system.api.social.dto.SocialUserRespDTO;
|
||||
import com.viewsh.module.system.controller.admin.socail.vo.user.SocialUserPageReqVO;
|
||||
import com.viewsh.module.system.dal.dataobject.social.SocialUserDO;
|
||||
import com.viewsh.module.system.enums.social.SocialTypeEnum;
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 社交用户 Service 接口,例如说社交平台的授权登录
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public interface SocialUserService {
|
||||
|
||||
/**
|
||||
* 获得指定用户的社交用户列表
|
||||
*
|
||||
* @param userId 用户编号
|
||||
* @param userType 用户类型
|
||||
* @return 社交用户列表
|
||||
*/
|
||||
List<SocialUserDO> getSocialUserList(Long userId, Integer userType);
|
||||
|
||||
/**
|
||||
* 绑定社交用户
|
||||
*
|
||||
* @param reqDTO 绑定信息
|
||||
* @return 社交用户 openid
|
||||
*/
|
||||
String bindSocialUser(@Valid SocialUserBindReqDTO reqDTO);
|
||||
|
||||
/**
|
||||
* 取消绑定社交用户
|
||||
*
|
||||
* @param userId 用户编号
|
||||
* @param userType 全局用户类型
|
||||
* @param socialType 社交平台的类型 {@link SocialTypeEnum}
|
||||
* @param openid 社交平台的 openid
|
||||
*/
|
||||
void unbindSocialUser(Long userId, Integer userType, Integer socialType, String openid);
|
||||
|
||||
/**
|
||||
* 获得社交用户,基于 userId
|
||||
*
|
||||
* @param userType 用户类型
|
||||
* @param userId 用户编号
|
||||
* @param socialType 社交平台的类型
|
||||
* @return 社交用户
|
||||
*/
|
||||
SocialUserRespDTO getSocialUserByUserId(Integer userType, Long userId, Integer socialType);
|
||||
|
||||
/**
|
||||
* 获得社交用户
|
||||
*
|
||||
* 在认证信息不正确的情况下,也会抛出 {@link ServiceException} 业务异常
|
||||
*
|
||||
* @param userType 用户类型
|
||||
* @param socialType 社交平台的类型
|
||||
* @param code 授权码
|
||||
* @param state state
|
||||
* @return 社交用户
|
||||
*/
|
||||
SocialUserRespDTO getSocialUserByCode(Integer userType, Integer socialType, String code, String state);
|
||||
|
||||
// ==================== 社交用户 CRUD ====================
|
||||
|
||||
/**
|
||||
* 获得社交用户
|
||||
*
|
||||
* @param id 编号
|
||||
* @return 社交用户
|
||||
*/
|
||||
SocialUserDO getSocialUser(Long id);
|
||||
|
||||
/**
|
||||
* 获得社交用户分页
|
||||
*
|
||||
* @param pageReqVO 分页查询
|
||||
* @return 社交用户分页
|
||||
*/
|
||||
PageResult<SocialUserDO> getSocialUserPage(SocialUserPageReqVO pageReqVO);
|
||||
|
||||
}
|
||||
package com.viewsh.module.system.service.social;
|
||||
|
||||
import com.viewsh.framework.common.exception.ServiceException;
|
||||
import com.viewsh.framework.common.pojo.PageResult;
|
||||
import com.viewsh.module.system.api.social.dto.SocialUserBindReqDTO;
|
||||
import com.viewsh.module.system.api.social.dto.SocialUserRespDTO;
|
||||
import com.viewsh.module.system.controller.admin.socail.vo.user.SocialUserPageReqVO;
|
||||
import com.viewsh.module.system.controller.admin.socail.vo.user.SocialUserRespVO;
|
||||
import com.viewsh.module.system.dal.dataobject.social.SocialUserDO;
|
||||
import com.viewsh.module.system.enums.social.SocialTypeEnum;
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 社交用户 Service 接口,例如说社交平台的授权登录
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
public interface SocialUserService {
|
||||
|
||||
/**
|
||||
* 获得指定用户的社交用户列表(含绑定时间)
|
||||
*
|
||||
* @param userId 用户编号
|
||||
* @param userType 用户类型
|
||||
* @return 社交用户列表
|
||||
*/
|
||||
List<SocialUserRespVO> getSocialUserBindList(Long userId, Integer userType);
|
||||
|
||||
/**
|
||||
* 绑定社交用户
|
||||
*
|
||||
* @param reqDTO 绑定信息
|
||||
* @return 社交用户 openid
|
||||
*/
|
||||
String bindSocialUser(@Valid SocialUserBindReqDTO reqDTO);
|
||||
|
||||
/**
|
||||
* 取消绑定社交用户
|
||||
*
|
||||
* @param userId 用户编号
|
||||
* @param userType 全局用户类型
|
||||
* @param socialType 社交平台的类型 {@link SocialTypeEnum}
|
||||
* @param openid 社交平台的 openid
|
||||
*/
|
||||
void unbindSocialUser(Long userId, Integer userType, Integer socialType, String openid);
|
||||
|
||||
/**
|
||||
* 获得社交用户,基于 userId
|
||||
*
|
||||
* @param userType 用户类型
|
||||
* @param userId 用户编号
|
||||
* @param socialType 社交平台的类型
|
||||
* @return 社交用户
|
||||
*/
|
||||
SocialUserRespDTO getSocialUserByUserId(Integer userType, Long userId, Integer socialType);
|
||||
|
||||
/**
|
||||
* 获得社交用户
|
||||
*
|
||||
* 在认证信息不正确的情况下,也会抛出 {@link ServiceException} 业务异常
|
||||
*
|
||||
* @param userType 用户类型
|
||||
* @param socialType 社交平台的类型
|
||||
* @param code 授权码
|
||||
* @param state state
|
||||
* @return 社交用户
|
||||
*/
|
||||
SocialUserRespDTO getSocialUserByCode(Integer userType, Integer socialType, String code, String state);
|
||||
|
||||
// ==================== 社交用户 CRUD ====================
|
||||
|
||||
/**
|
||||
* 获得社交用户
|
||||
*
|
||||
* @param id 编号
|
||||
* @return 社交用户
|
||||
*/
|
||||
SocialUserDO getSocialUser(Long id);
|
||||
|
||||
/**
|
||||
* 获得社交用户分页
|
||||
*
|
||||
* @param pageReqVO 分页查询
|
||||
* @return 社交用户分页
|
||||
*/
|
||||
PageResult<SocialUserDO> getSocialUserPage(SocialUserPageReqVO pageReqVO);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,174 +1,188 @@
|
||||
package com.viewsh.module.system.service.social;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import com.viewsh.framework.common.exception.ServiceException;
|
||||
import com.viewsh.framework.common.pojo.PageResult;
|
||||
import com.viewsh.module.system.api.social.dto.SocialUserBindReqDTO;
|
||||
import com.viewsh.module.system.api.social.dto.SocialUserRespDTO;
|
||||
import com.viewsh.module.system.controller.admin.socail.vo.user.SocialUserPageReqVO;
|
||||
import com.viewsh.module.system.dal.dataobject.social.SocialUserBindDO;
|
||||
import com.viewsh.module.system.dal.dataobject.social.SocialUserDO;
|
||||
import com.viewsh.module.system.dal.mysql.social.SocialUserBindMapper;
|
||||
import com.viewsh.module.system.dal.mysql.social.SocialUserMapper;
|
||||
import com.viewsh.module.system.enums.social.SocialTypeEnum;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import me.zhyd.oauth.model.AuthUser;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static com.viewsh.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static com.viewsh.framework.common.util.collection.CollectionUtils.convertSet;
|
||||
import static com.viewsh.framework.common.util.json.JsonUtils.toJsonString;
|
||||
import static com.viewsh.module.system.enums.ErrorCodeConstants.SOCIAL_USER_NOT_FOUND;
|
||||
|
||||
/**
|
||||
* 社交用户 Service 实现类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
@Slf4j
|
||||
public class SocialUserServiceImpl implements SocialUserService {
|
||||
|
||||
@Resource
|
||||
private SocialUserBindMapper socialUserBindMapper;
|
||||
@Resource
|
||||
private SocialUserMapper socialUserMapper;
|
||||
|
||||
@Resource
|
||||
private SocialClientService socialClientService;
|
||||
|
||||
@Override
|
||||
public List<SocialUserDO> getSocialUserList(Long userId, Integer userType) {
|
||||
// 获得绑定
|
||||
List<SocialUserBindDO> socialUserBinds = socialUserBindMapper.selectListByUserIdAndUserType(userId, userType);
|
||||
if (CollUtil.isEmpty(socialUserBinds)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
// 获得社交用户
|
||||
return socialUserMapper.selectByIds(convertSet(socialUserBinds, SocialUserBindDO::getSocialUserId));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public String bindSocialUser(SocialUserBindReqDTO reqDTO) {
|
||||
// 获得社交用户
|
||||
SocialUserDO socialUser = authSocialUser(reqDTO.getSocialType(), reqDTO.getUserType(),
|
||||
reqDTO.getCode(), reqDTO.getState());
|
||||
Assert.notNull(socialUser, "社交用户不能为空");
|
||||
|
||||
// 社交用户可能之前绑定过别的用户,需要进行解绑
|
||||
socialUserBindMapper.deleteByUserTypeAndSocialUserId(reqDTO.getUserType(), socialUser.getId());
|
||||
|
||||
// 用户可能之前已经绑定过该社交类型,需要进行解绑
|
||||
socialUserBindMapper.deleteByUserTypeAndUserIdAndSocialType(reqDTO.getUserType(), reqDTO.getUserId(),
|
||||
socialUser.getType());
|
||||
|
||||
// 绑定当前登录的社交用户
|
||||
SocialUserBindDO socialUserBind = SocialUserBindDO.builder()
|
||||
.userId(reqDTO.getUserId()).userType(reqDTO.getUserType())
|
||||
.socialUserId(socialUser.getId()).socialType(socialUser.getType()).build();
|
||||
socialUserBindMapper.insert(socialUserBind);
|
||||
return socialUser.getOpenid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unbindSocialUser(Long userId, Integer userType, Integer socialType, String openid) {
|
||||
// 获得 openid 对应的 SocialUserDO 社交用户
|
||||
SocialUserDO socialUser = socialUserMapper.selectByTypeAndOpenid(socialType, openid);
|
||||
if (socialUser == null) {
|
||||
throw exception(SOCIAL_USER_NOT_FOUND);
|
||||
}
|
||||
|
||||
// 获得对应的社交绑定关系
|
||||
socialUserBindMapper.deleteByUserTypeAndUserIdAndSocialType(userType, userId, socialUser.getType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public SocialUserRespDTO getSocialUserByUserId(Integer userType, Long userId, Integer socialType) {
|
||||
// 获得绑定用户
|
||||
SocialUserBindDO socialUserBind = socialUserBindMapper.selectByUserIdAndUserTypeAndSocialType(userId, userType, socialType);
|
||||
if (socialUserBind == null) {
|
||||
return null;
|
||||
}
|
||||
// 获得社交用户
|
||||
SocialUserDO socialUser = socialUserMapper.selectById(socialUserBind.getSocialUserId());
|
||||
Assert.notNull(socialUser, "社交用户不能为空");
|
||||
return new SocialUserRespDTO(socialUser.getOpenid(), socialUser.getNickname(), socialUser.getAvatar(),
|
||||
socialUserBind.getUserId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public SocialUserRespDTO getSocialUserByCode(Integer userType, Integer socialType, String code, String state) {
|
||||
// 获得社交用户
|
||||
SocialUserDO socialUser = authSocialUser(socialType, userType, code, state);
|
||||
Assert.notNull(socialUser, "社交用户不能为空");
|
||||
|
||||
// 获得绑定用户
|
||||
SocialUserBindDO socialUserBind = socialUserBindMapper.selectByUserTypeAndSocialUserId(userType,
|
||||
socialUser.getId());
|
||||
return new SocialUserRespDTO(socialUser.getOpenid(), socialUser.getNickname(), socialUser.getAvatar(),
|
||||
socialUserBind != null ? socialUserBind.getUserId() : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 授权获得对应的社交用户
|
||||
* 如果授权失败,则会抛出 {@link ServiceException} 异常
|
||||
*
|
||||
* @param socialType 社交平台的类型 {@link SocialTypeEnum}
|
||||
* @param userType 用户类型
|
||||
* @param code 授权码
|
||||
* @param state state
|
||||
* @return 授权用户
|
||||
*/
|
||||
@NotNull
|
||||
public SocialUserDO authSocialUser(Integer socialType, Integer userType, String code, String state) {
|
||||
// 优先从 DB 中获取,因为 code 有且可以使用一次。
|
||||
// 在社交登录时,当未绑定 User 时,需要绑定登录,此时需要 code 使用两次
|
||||
SocialUserDO socialUser = socialUserMapper.selectByTypeAndCodeAnState(socialType, code, state);
|
||||
if (socialUser != null) {
|
||||
return socialUser;
|
||||
}
|
||||
|
||||
// 请求获取
|
||||
AuthUser authUser = socialClientService.getAuthUser(socialType, userType, code, state);
|
||||
Assert.notNull(authUser, "三方用户不能为空");
|
||||
|
||||
// 保存到 DB 中
|
||||
socialUser = socialUserMapper.selectByTypeAndOpenid(socialType, authUser.getUuid());
|
||||
if (socialUser == null) {
|
||||
socialUser = new SocialUserDO();
|
||||
}
|
||||
socialUser.setType(socialType).setCode(code).setState(state) // 需要保存 code + state 字段,保证后续可查询
|
||||
.setOpenid(authUser.getUuid()).setToken(authUser.getToken().getAccessToken()).setRawTokenInfo((toJsonString(authUser.getToken())))
|
||||
.setNickname(authUser.getNickname()).setAvatar(authUser.getAvatar()).setRawUserInfo(toJsonString(authUser.getRawUserInfo()));
|
||||
if (socialUser.getId() == null) {
|
||||
socialUserMapper.insert(socialUser);
|
||||
} else {
|
||||
socialUser.clean(); // 避免 updateTime 不更新:https://gitee.com/viewshcode/viewsh-boot-mini/issues/ID7FUL
|
||||
socialUserMapper.updateById(socialUser);
|
||||
}
|
||||
return socialUser;
|
||||
}
|
||||
|
||||
// ==================== 社交用户 CRUD ====================
|
||||
|
||||
@Override
|
||||
public SocialUserDO getSocialUser(Long id) {
|
||||
return socialUserMapper.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<SocialUserDO> getSocialUserPage(SocialUserPageReqVO pageReqVO) {
|
||||
return socialUserMapper.selectPage(pageReqVO);
|
||||
}
|
||||
|
||||
}
|
||||
package com.viewsh.module.system.service.social;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import com.viewsh.framework.common.exception.ServiceException;
|
||||
import com.viewsh.framework.common.pojo.PageResult;
|
||||
import com.viewsh.module.system.api.social.dto.SocialUserBindReqDTO;
|
||||
import com.viewsh.module.system.api.social.dto.SocialUserRespDTO;
|
||||
import com.viewsh.module.system.controller.admin.socail.vo.user.SocialUserPageReqVO;
|
||||
import com.viewsh.module.system.controller.admin.socail.vo.user.SocialUserRespVO;
|
||||
import com.viewsh.module.system.dal.dataobject.social.SocialUserBindDO;
|
||||
import com.viewsh.module.system.dal.dataobject.social.SocialUserDO;
|
||||
import com.viewsh.module.system.dal.mysql.social.SocialUserBindMapper;
|
||||
import com.viewsh.module.system.dal.mysql.social.SocialUserMapper;
|
||||
import com.viewsh.module.system.enums.social.SocialTypeEnum;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import me.zhyd.oauth.model.AuthUser;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.viewsh.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static com.viewsh.framework.common.util.collection.CollectionUtils.convertList;
|
||||
import static com.viewsh.framework.common.util.collection.CollectionUtils.convertMap;
|
||||
import static com.viewsh.framework.common.util.collection.CollectionUtils.convertSet;
|
||||
import static com.viewsh.framework.common.util.json.JsonUtils.toJsonString;
|
||||
import static com.viewsh.module.system.enums.ErrorCodeConstants.SOCIAL_USER_NOT_FOUND;
|
||||
|
||||
/**
|
||||
* 社交用户 Service 实现类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
@Slf4j
|
||||
public class SocialUserServiceImpl implements SocialUserService {
|
||||
|
||||
@Resource
|
||||
private SocialUserBindMapper socialUserBindMapper;
|
||||
@Resource
|
||||
private SocialUserMapper socialUserMapper;
|
||||
|
||||
@Resource
|
||||
private SocialClientService socialClientService;
|
||||
|
||||
@Override
|
||||
public List<SocialUserRespVO> getSocialUserBindList(Long userId, Integer userType) {
|
||||
// 获得绑定关系
|
||||
List<SocialUserBindDO> socialUserBinds = socialUserBindMapper.selectListByUserIdAndUserType(userId, userType);
|
||||
if (CollUtil.isEmpty(socialUserBinds)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
// 获得社交用户
|
||||
List<SocialUserDO> socialUsers = socialUserMapper.selectByIds(convertSet(socialUserBinds, SocialUserBindDO::getSocialUserId));
|
||||
Map<Long, SocialUserBindDO> bindMap = convertMap(socialUserBinds, SocialUserBindDO::getSocialUserId);
|
||||
// 组装返回
|
||||
return convertList(socialUsers, socialUser -> {
|
||||
SocialUserBindDO bind = bindMap.get(socialUser.getId());
|
||||
return new SocialUserRespVO()
|
||||
.setId(socialUser.getId()).setType(socialUser.getType()).setOpenid(socialUser.getOpenid())
|
||||
.setNickname(socialUser.getNickname()).setAvatar(socialUser.getAvatar())
|
||||
.setCreateTime(bind != null ? bind.getCreateTime() : null)
|
||||
.setUpdateTime(bind != null ? bind.getUpdateTime() : null);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public String bindSocialUser(SocialUserBindReqDTO reqDTO) {
|
||||
// 获得社交用户
|
||||
SocialUserDO socialUser = authSocialUser(reqDTO.getSocialType(), reqDTO.getUserType(),
|
||||
reqDTO.getCode(), reqDTO.getState());
|
||||
Assert.notNull(socialUser, "社交用户不能为空");
|
||||
|
||||
// 社交用户可能之前绑定过别的用户,需要进行解绑
|
||||
socialUserBindMapper.deleteByUserTypeAndSocialUserId(reqDTO.getUserType(), socialUser.getId());
|
||||
|
||||
// 用户可能之前已经绑定过该社交类型,需要进行解绑
|
||||
socialUserBindMapper.deleteByUserTypeAndUserIdAndSocialType(reqDTO.getUserType(), reqDTO.getUserId(),
|
||||
socialUser.getType());
|
||||
|
||||
// 绑定当前登录的社交用户
|
||||
SocialUserBindDO socialUserBind = SocialUserBindDO.builder()
|
||||
.userId(reqDTO.getUserId()).userType(reqDTO.getUserType())
|
||||
.socialUserId(socialUser.getId()).socialType(socialUser.getType()).build();
|
||||
socialUserBindMapper.insert(socialUserBind);
|
||||
return socialUser.getOpenid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unbindSocialUser(Long userId, Integer userType, Integer socialType, String openid) {
|
||||
// 获得 openid 对应的 SocialUserDO 社交用户
|
||||
SocialUserDO socialUser = socialUserMapper.selectByTypeAndOpenid(socialType, openid);
|
||||
if (socialUser == null) {
|
||||
throw exception(SOCIAL_USER_NOT_FOUND);
|
||||
}
|
||||
|
||||
// 获得对应的社交绑定关系
|
||||
socialUserBindMapper.deleteByUserTypeAndUserIdAndSocialType(userType, userId, socialUser.getType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public SocialUserRespDTO getSocialUserByUserId(Integer userType, Long userId, Integer socialType) {
|
||||
// 获得绑定用户
|
||||
SocialUserBindDO socialUserBind = socialUserBindMapper.selectByUserIdAndUserTypeAndSocialType(userId, userType, socialType);
|
||||
if (socialUserBind == null) {
|
||||
return null;
|
||||
}
|
||||
// 获得社交用户
|
||||
SocialUserDO socialUser = socialUserMapper.selectById(socialUserBind.getSocialUserId());
|
||||
Assert.notNull(socialUser, "社交用户不能为空");
|
||||
return new SocialUserRespDTO(socialUser.getOpenid(), socialUser.getNickname(), socialUser.getAvatar(),
|
||||
socialUserBind.getUserId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public SocialUserRespDTO getSocialUserByCode(Integer userType, Integer socialType, String code, String state) {
|
||||
// 获得社交用户
|
||||
SocialUserDO socialUser = authSocialUser(socialType, userType, code, state);
|
||||
Assert.notNull(socialUser, "社交用户不能为空");
|
||||
|
||||
// 获得绑定用户
|
||||
SocialUserBindDO socialUserBind = socialUserBindMapper.selectByUserTypeAndSocialUserId(userType,
|
||||
socialUser.getId());
|
||||
return new SocialUserRespDTO(socialUser.getOpenid(), socialUser.getNickname(), socialUser.getAvatar(),
|
||||
socialUserBind != null ? socialUserBind.getUserId() : null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 授权获得对应的社交用户
|
||||
* 如果授权失败,则会抛出 {@link ServiceException} 异常
|
||||
*
|
||||
* @param socialType 社交平台的类型 {@link SocialTypeEnum}
|
||||
* @param userType 用户类型
|
||||
* @param code 授权码
|
||||
* @param state state
|
||||
* @return 授权用户
|
||||
*/
|
||||
@NotNull
|
||||
public SocialUserDO authSocialUser(Integer socialType, Integer userType, String code, String state) {
|
||||
// 优先从 DB 中获取,因为 code 有且可以使用一次。
|
||||
// 在社交登录时,当未绑定 User 时,需要绑定登录,此时需要 code 使用两次
|
||||
SocialUserDO socialUser = socialUserMapper.selectByTypeAndCodeAnState(socialType, code, state);
|
||||
if (socialUser != null) {
|
||||
return socialUser;
|
||||
}
|
||||
|
||||
// 请求获取
|
||||
AuthUser authUser = socialClientService.getAuthUser(socialType, userType, code, state);
|
||||
Assert.notNull(authUser, "三方用户不能为空");
|
||||
|
||||
// 保存到 DB 中
|
||||
socialUser = socialUserMapper.selectByTypeAndOpenid(socialType, authUser.getUuid());
|
||||
if (socialUser == null) {
|
||||
socialUser = new SocialUserDO();
|
||||
}
|
||||
socialUser.setType(socialType).setCode(code).setState(state) // 需要保存 code + state 字段,保证后续可查询
|
||||
.setOpenid(authUser.getUuid()).setToken(authUser.getToken().getAccessToken()).setRawTokenInfo((toJsonString(authUser.getToken())))
|
||||
.setNickname(authUser.getNickname()).setAvatar(authUser.getAvatar()).setRawUserInfo(toJsonString(authUser.getRawUserInfo()));
|
||||
if (socialUser.getId() == null) {
|
||||
socialUserMapper.insert(socialUser);
|
||||
} else {
|
||||
socialUser.clean(); // 避免 updateTime 不更新:https://gitee.com/viewshcode/viewsh-boot-mini/issues/ID7FUL
|
||||
socialUserMapper.updateById(socialUser);
|
||||
}
|
||||
return socialUser;
|
||||
}
|
||||
|
||||
// ==================== 社交用户 CRUD ====================
|
||||
|
||||
@Override
|
||||
public SocialUserDO getSocialUser(Long id) {
|
||||
return socialUserMapper.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<SocialUserDO> getSocialUserPage(SocialUserPageReqVO pageReqVO) {
|
||||
return socialUserMapper.selectPage(pageReqVO);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user