mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2024-11-29 18:51:53 +08:00
完善 OAuth2ClientServiceImplTest 单元测试
This commit is contained in:
parent
668551350f
commit
b3ab1d9285
@ -52,18 +52,3 @@ tenant-id: {{adminTenentId}}
|
|||||||
POST {{baseUrl}}/system/oauth2/check-token?token=620d307c5b4148df8a98dd6c6c547106
|
POST {{baseUrl}}/system/oauth2/check-token?token=620d307c5b4148df8a98dd6c6c547106
|
||||||
Authorization: Basic ZGVmYXVsdDphZG1pbjEyMw==
|
Authorization: Basic ZGVmYXVsdDphZG1pbjEyMw==
|
||||||
tenant-id: {{adminTenentId}}
|
tenant-id: {{adminTenentId}}
|
||||||
|
|
||||||
### 请求 /system/oauth2/user/get 接口 => 成功
|
|
||||||
GET {{baseUrl}}/system/oauth2/user/get
|
|
||||||
Authorization: Bearer 9502bd7a768a4ade920b90f41e2efd5c
|
|
||||||
tenant-id: {{adminTenentId}}
|
|
||||||
|
|
||||||
### 请求 /system/oauth2/user/update 接口 => 成功
|
|
||||||
PUT {{baseUrl}}/system/oauth2/user/update
|
|
||||||
Content-Type: application/json
|
|
||||||
Authorization: Bearer 9502bd7a768a4ade920b90f41e2efd5c
|
|
||||||
tenant-id: {{adminTenentId}}
|
|
||||||
|
|
||||||
{
|
|
||||||
"nickname": "芋道源码"
|
|
||||||
}
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package cn.iocoder.yudao.module.system.controller.admin.oauth2;
|
package cn.iocoder.yudao.module.system.controller.admin.oauth2;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
|
||||||
import cn.hutool.core.lang.Assert;
|
import cn.hutool.core.lang.Assert;
|
||||||
import cn.hutool.core.util.ArrayUtil;
|
import cn.hutool.core.util.ArrayUtil;
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
@ -13,36 +12,26 @@ import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
|
|||||||
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.OAuth2OpenAccessTokenRespVO;
|
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.OAuth2OpenAccessTokenRespVO;
|
||||||
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.OAuth2OpenAuthorizeInfoRespVO;
|
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.OAuth2OpenAuthorizeInfoRespVO;
|
||||||
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.OAuth2OpenCheckTokenRespVO;
|
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.OAuth2OpenCheckTokenRespVO;
|
||||||
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.user.OAuth2OpenUserInfoRespVO;
|
|
||||||
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.user.OAuth2OpenUserUpdateReqVO;
|
|
||||||
import cn.iocoder.yudao.module.system.convert.oauth2.OAuth2OpenConvert;
|
import cn.iocoder.yudao.module.system.convert.oauth2.OAuth2OpenConvert;
|
||||||
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
|
|
||||||
import cn.iocoder.yudao.module.system.dal.dataobject.dept.PostDO;
|
|
||||||
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
|
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
|
||||||
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2ApproveDO;
|
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2ApproveDO;
|
||||||
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2ClientDO;
|
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2ClientDO;
|
||||||
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
|
|
||||||
import cn.iocoder.yudao.module.system.enums.auth.OAuth2GrantTypeEnum;
|
import cn.iocoder.yudao.module.system.enums.auth.OAuth2GrantTypeEnum;
|
||||||
import cn.iocoder.yudao.module.system.service.dept.DeptService;
|
|
||||||
import cn.iocoder.yudao.module.system.service.dept.PostService;
|
|
||||||
import cn.iocoder.yudao.module.system.service.oauth2.OAuth2ApproveService;
|
import cn.iocoder.yudao.module.system.service.oauth2.OAuth2ApproveService;
|
||||||
import cn.iocoder.yudao.module.system.service.oauth2.OAuth2ClientService;
|
import cn.iocoder.yudao.module.system.service.oauth2.OAuth2ClientService;
|
||||||
import cn.iocoder.yudao.module.system.service.oauth2.OAuth2GrantService;
|
import cn.iocoder.yudao.module.system.service.oauth2.OAuth2GrantService;
|
||||||
import cn.iocoder.yudao.module.system.service.oauth2.OAuth2TokenService;
|
import cn.iocoder.yudao.module.system.service.oauth2.OAuth2TokenService;
|
||||||
import cn.iocoder.yudao.module.system.service.user.AdminUserService;
|
|
||||||
import cn.iocoder.yudao.module.system.util.oauth2.OAuth2Utils;
|
import cn.iocoder.yudao.module.system.util.oauth2.OAuth2Utils;
|
||||||
import io.swagger.annotations.Api;
|
import io.swagger.annotations.Api;
|
||||||
import io.swagger.annotations.ApiImplicitParam;
|
import io.swagger.annotations.ApiImplicitParam;
|
||||||
import io.swagger.annotations.ApiImplicitParams;
|
import io.swagger.annotations.ApiImplicitParams;
|
||||||
import io.swagger.annotations.ApiOperation;
|
import io.swagger.annotations.ApiOperation;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.validation.Valid;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -61,7 +50,9 @@ import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUti
|
|||||||
* 另外,一个公司如果有多个管理后台,它们 client_id 产生的 access token 相互之间是无法互通的,即无法访问它们系统的 API 接口,直到两个 client_id 产生信任授权。
|
* 另外,一个公司如果有多个管理后台,它们 client_id 产生的 access token 相互之间是无法互通的,即无法访问它们系统的 API 接口,直到两个 client_id 产生信任授权。
|
||||||
*
|
*
|
||||||
* 考虑到【本系统】暂时不想做的过于复杂,默认只有获取到 access token 之后,可以访问【本系统】管理后台的 /system-api/* 所有接口,除非手动添加 scope 控制。
|
* 考虑到【本系统】暂时不想做的过于复杂,默认只有获取到 access token 之后,可以访问【本系统】管理后台的 /system-api/* 所有接口,除非手动添加 scope 控制。
|
||||||
* scope 的使用示例,可见当前类的 getUserInfo 和 updateUserInfo 方法,上面有 @PreAuthorize("@ss.hasScope('user.read')") 和 @PreAuthorize("@ss.hasScope('user.write')") 注解
|
* scope 的使用示例,可见 {@link OAuth2UserController} 类
|
||||||
|
*
|
||||||
|
*
|
||||||
*
|
*
|
||||||
* @author 芋道源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
@ -306,43 +297,4 @@ public class OAuth2OpenController {
|
|||||||
return clientIdAndSecret;
|
return clientIdAndSecret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============ 用户操作的示例,展示 scope 的使用 ============
|
|
||||||
|
|
||||||
@Resource
|
|
||||||
private AdminUserService userService;
|
|
||||||
@Resource
|
|
||||||
private DeptService deptService;
|
|
||||||
@Resource
|
|
||||||
private PostService postService;
|
|
||||||
|
|
||||||
@GetMapping("/user/get")
|
|
||||||
@ApiOperation("获得用户基本信息")
|
|
||||||
@PreAuthorize("@ss.hasScope('user.read')")
|
|
||||||
public CommonResult<OAuth2OpenUserInfoRespVO> getUserInfo() {
|
|
||||||
// 获得用户基本信息
|
|
||||||
AdminUserDO user = userService.getUser(getLoginUserId());
|
|
||||||
OAuth2OpenUserInfoRespVO resp = OAuth2OpenConvert.INSTANCE.convert(user);
|
|
||||||
// 获得部门信息
|
|
||||||
if (user.getDeptId() != null) {
|
|
||||||
DeptDO dept = deptService.getDept(user.getDeptId());
|
|
||||||
resp.setDept(OAuth2OpenConvert.INSTANCE.convert(dept));
|
|
||||||
}
|
|
||||||
// 获得岗位信息
|
|
||||||
if (CollUtil.isNotEmpty(user.getPostIds())) {
|
|
||||||
List<PostDO> posts = postService.getPosts(user.getPostIds());
|
|
||||||
resp.setPosts(OAuth2OpenConvert.INSTANCE.convertList(posts));
|
|
||||||
}
|
|
||||||
return success(resp);
|
|
||||||
}
|
|
||||||
|
|
||||||
@PutMapping("/user/update")
|
|
||||||
@ApiOperation("更新用户基本信息")
|
|
||||||
@PreAuthorize("@ss.hasScope('user.write')")
|
|
||||||
public CommonResult<Boolean> updateUserInfo(@Valid @RequestBody OAuth2OpenUserUpdateReqVO reqVO) {
|
|
||||||
// 这里将 UserProfileUpdateReqVO =》UserProfileUpdateReqVO 对象,实现接口的复用。
|
|
||||||
// 主要是,AdminUserService 没有自己的 BO 对象,所以复用只能这么做
|
|
||||||
userService.updateUserProfile(getLoginUserId(), OAuth2OpenConvert.INSTANCE.convert(reqVO));
|
|
||||||
return success(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
### 请求 /system/oauth2/user/get 接口 => 成功
|
||||||
|
GET {{baseUrl}}/system/oauth2/user/get
|
||||||
|
Authorization: Bearer 47f9c74ec11041f193b777ebb95c3b0d
|
||||||
|
tenant-id: {{adminTenentId}}
|
||||||
|
|
||||||
|
### 请求 /system/oauth2/user/update 接口 => 成功
|
||||||
|
PUT {{baseUrl}}/system/oauth2/user/update
|
||||||
|
Content-Type: application/json
|
||||||
|
Authorization: Bearer 47f9c74ec11041f193b777ebb95c3b0d
|
||||||
|
tenant-id: {{adminTenentId}}
|
||||||
|
|
||||||
|
{
|
||||||
|
"nickname": "芋道源码"
|
||||||
|
}
|
@ -0,0 +1,80 @@
|
|||||||
|
package cn.iocoder.yudao.module.system.controller.admin.oauth2;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
|
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.user.OAuth2UserInfoRespVO;
|
||||||
|
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.user.OAuth2UserUpdateReqVO;
|
||||||
|
import cn.iocoder.yudao.module.system.convert.oauth2.OAuth2UserConvert;
|
||||||
|
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
|
||||||
|
import cn.iocoder.yudao.module.system.dal.dataobject.dept.PostDO;
|
||||||
|
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
|
||||||
|
import cn.iocoder.yudao.module.system.service.dept.DeptService;
|
||||||
|
import cn.iocoder.yudao.module.system.service.dept.PostService;
|
||||||
|
import cn.iocoder.yudao.module.system.service.user.AdminUserService;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.validation.Valid;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||||
|
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提供给外部应用调用为主
|
||||||
|
*
|
||||||
|
* 1. 在 getUserInfo 方法上,添加 @PreAuthorize("@ss.hasScope('user.read')") 注解,声明需要满足 scope = user.read
|
||||||
|
* 2. 在 updateUserInfo 方法上,添加 @PreAuthorize("@ss.hasScope('user.write')") 注解,声明需要满足 scope = user.write
|
||||||
|
*
|
||||||
|
* @author 芋道源码
|
||||||
|
*/
|
||||||
|
@Api(tags = "管理后台 - OAuth2.0 用户")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/system/oauth2/user")
|
||||||
|
@Validated
|
||||||
|
@Slf4j
|
||||||
|
public class OAuth2UserController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private AdminUserService userService;
|
||||||
|
@Resource
|
||||||
|
private DeptService deptService;
|
||||||
|
@Resource
|
||||||
|
private PostService postService;
|
||||||
|
|
||||||
|
@GetMapping("/get")
|
||||||
|
@ApiOperation("获得用户基本信息")
|
||||||
|
@PreAuthorize("@ss.hasScope('user.read')") //
|
||||||
|
public CommonResult<OAuth2UserInfoRespVO> getUserInfo() {
|
||||||
|
// 获得用户基本信息
|
||||||
|
AdminUserDO user = userService.getUser(getLoginUserId());
|
||||||
|
OAuth2UserInfoRespVO resp = OAuth2UserConvert.INSTANCE.convert(user);
|
||||||
|
// 获得部门信息
|
||||||
|
if (user.getDeptId() != null) {
|
||||||
|
DeptDO dept = deptService.getDept(user.getDeptId());
|
||||||
|
resp.setDept(OAuth2UserConvert.INSTANCE.convert(dept));
|
||||||
|
}
|
||||||
|
// 获得岗位信息
|
||||||
|
if (CollUtil.isNotEmpty(user.getPostIds())) {
|
||||||
|
List<PostDO> posts = postService.getPosts(user.getPostIds());
|
||||||
|
resp.setPosts(OAuth2UserConvert.INSTANCE.convertList(posts));
|
||||||
|
}
|
||||||
|
return success(resp);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/update")
|
||||||
|
@ApiOperation("更新用户基本信息")
|
||||||
|
@PreAuthorize("@ss.hasScope('user.write')")
|
||||||
|
public CommonResult<Boolean> updateUserInfo(@Valid @RequestBody OAuth2UserUpdateReqVO reqVO) {
|
||||||
|
// 这里将 UserProfileUpdateReqVO =》UserProfileUpdateReqVO 对象,实现接口的复用。
|
||||||
|
// 主要是,AdminUserService 没有自己的 BO 对象,所以复用只能这么做
|
||||||
|
userService.updateUserProfile(getLoginUserId(), OAuth2UserConvert.INSTANCE.convert(reqVO));
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.user;
|
package cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.user;
|
||||||
|
|
||||||
import io.swagger.annotations.ApiModel;
|
import io.swagger.annotations.ApiModel;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
@ -8,11 +8,11 @@ import lombok.NoArgsConstructor;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ApiModel("管理后台 - 【开放接口】获得用户基本信息 Response VO")
|
@ApiModel("管理后台 - OAuth2.0 获得用户基本信息 Response VO")
|
||||||
@Data
|
@Data
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class OAuth2OpenUserInfoRespVO {
|
public class OAuth2UserInfoRespVO {
|
||||||
|
|
||||||
@ApiModelProperty(value = "用户编号", required = true, example = "1")
|
@ApiModelProperty(value = "用户编号", required = true, example = "1")
|
||||||
private Long id;
|
private Long id;
|
@ -1,4 +1,4 @@
|
|||||||
package cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.user;
|
package cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.user;
|
||||||
|
|
||||||
import io.swagger.annotations.ApiModel;
|
import io.swagger.annotations.ApiModel;
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
@ -10,11 +10,11 @@ import org.hibernate.validator.constraints.Length;
|
|||||||
import javax.validation.constraints.Email;
|
import javax.validation.constraints.Email;
|
||||||
import javax.validation.constraints.Size;
|
import javax.validation.constraints.Size;
|
||||||
|
|
||||||
@ApiModel("管理后台 - 【开放接口】更新用户基本信息 Request VO")
|
@ApiModel("管理后台 - OAuth2.0 更新用户基本信息 Request VO")
|
||||||
@Data
|
@Data
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class OAuth2OpenUserUpdateReqVO {
|
public class OAuth2UserUpdateReqVO {
|
||||||
|
|
||||||
@ApiModelProperty(value = "用户昵称", required = true, example = "芋艿")
|
@ApiModelProperty(value = "用户昵称", required = true, example = "芋艿")
|
||||||
@Size(max = 30, message = "用户昵称长度不能超过 30 个字符")
|
@Size(max = 30, message = "用户昵称长度不能超过 30 个字符")
|
@ -7,15 +7,9 @@ import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
|
|||||||
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.OAuth2OpenAccessTokenRespVO;
|
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.OAuth2OpenAccessTokenRespVO;
|
||||||
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.OAuth2OpenAuthorizeInfoRespVO;
|
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.OAuth2OpenAuthorizeInfoRespVO;
|
||||||
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.OAuth2OpenCheckTokenRespVO;
|
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.OAuth2OpenCheckTokenRespVO;
|
||||||
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.user.OAuth2OpenUserInfoRespVO;
|
|
||||||
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.user.OAuth2OpenUserUpdateReqVO;
|
|
||||||
import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO;
|
|
||||||
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
|
|
||||||
import cn.iocoder.yudao.module.system.dal.dataobject.dept.PostDO;
|
|
||||||
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
|
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
|
||||||
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2ApproveDO;
|
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2ApproveDO;
|
||||||
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2ClientDO;
|
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2ClientDO;
|
||||||
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
|
|
||||||
import cn.iocoder.yudao.module.system.util.oauth2.OAuth2Utils;
|
import cn.iocoder.yudao.module.system.util.oauth2.OAuth2Utils;
|
||||||
import org.mapstruct.Mapper;
|
import org.mapstruct.Mapper;
|
||||||
import org.mapstruct.factory.Mappers;
|
import org.mapstruct.factory.Mappers;
|
||||||
@ -46,14 +40,6 @@ public interface OAuth2OpenConvert {
|
|||||||
}
|
}
|
||||||
OAuth2OpenCheckTokenRespVO convert3(OAuth2AccessTokenDO bean);
|
OAuth2OpenCheckTokenRespVO convert3(OAuth2AccessTokenDO bean);
|
||||||
|
|
||||||
// ============ 用户操作的示例 ============
|
|
||||||
|
|
||||||
OAuth2OpenUserInfoRespVO convert(AdminUserDO bean);
|
|
||||||
OAuth2OpenUserInfoRespVO.Dept convert(DeptDO dept);
|
|
||||||
List<OAuth2OpenUserInfoRespVO.Post> convertList(List<PostDO> list);
|
|
||||||
|
|
||||||
UserProfileUpdateReqVO convert(OAuth2OpenUserUpdateReqVO bean);
|
|
||||||
|
|
||||||
default OAuth2OpenAuthorizeInfoRespVO convert(OAuth2ClientDO client, List<OAuth2ApproveDO> approves) {
|
default OAuth2OpenAuthorizeInfoRespVO convert(OAuth2ClientDO client, List<OAuth2ApproveDO> approves) {
|
||||||
// 构建 scopes
|
// 构建 scopes
|
||||||
List<KeyValue<String, Boolean>> scopes = new ArrayList<>(client.getScopes().size());
|
List<KeyValue<String, Boolean>> scopes = new ArrayList<>(client.getScopes().size());
|
||||||
|
@ -0,0 +1,25 @@
|
|||||||
|
package cn.iocoder.yudao.module.system.convert.oauth2;
|
||||||
|
|
||||||
|
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.user.OAuth2UserInfoRespVO;
|
||||||
|
import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.user.OAuth2UserUpdateReqVO;
|
||||||
|
import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO;
|
||||||
|
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
|
||||||
|
import cn.iocoder.yudao.module.system.dal.dataobject.dept.PostDO;
|
||||||
|
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface OAuth2UserConvert {
|
||||||
|
|
||||||
|
OAuth2UserConvert INSTANCE = Mappers.getMapper(OAuth2UserConvert.class);
|
||||||
|
|
||||||
|
OAuth2UserInfoRespVO convert(AdminUserDO bean);
|
||||||
|
OAuth2UserInfoRespVO.Dept convert(DeptDO dept);
|
||||||
|
List<OAuth2UserInfoRespVO.Post> convertList(List<PostDO> list);
|
||||||
|
|
||||||
|
UserProfileUpdateReqVO convert(OAuth2UserUpdateReqVO bean);
|
||||||
|
|
||||||
|
}
|
@ -15,6 +15,7 @@ import cn.iocoder.yudao.module.system.dal.mysql.oauth2.OAuth2ClientMapper;
|
|||||||
import cn.iocoder.yudao.module.system.mq.producer.auth.OAuth2ClientProducer;
|
import cn.iocoder.yudao.module.system.mq.producer.auth.OAuth2ClientProducer;
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.scheduling.annotation.Scheduled;
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@ -51,7 +52,8 @@ public class OAuth2ClientServiceImpl implements OAuth2ClientService {
|
|||||||
*
|
*
|
||||||
* 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向
|
* 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向
|
||||||
*/
|
*/
|
||||||
@Getter
|
@Getter // 解决单测
|
||||||
|
@Setter // 解决单测
|
||||||
private volatile Map<String, OAuth2ClientDO> clientCache;
|
private volatile Map<String, OAuth2ClientDO> clientCache;
|
||||||
/**
|
/**
|
||||||
* 缓存角色的最大更新时间,用于后续的增量轮询,判断是否有更新
|
* 缓存角色的最大更新时间,用于后续的增量轮询,判断是否有更新
|
||||||
@ -151,7 +153,7 @@ public class OAuth2ClientServiceImpl implements OAuth2ClientService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public void validateClientIdExists(Long id, String clientId) {
|
void validateClientIdExists(Long id, String clientId) {
|
||||||
OAuth2ClientDO client = oauth2ClientMapper.selectByClientId(clientId);
|
OAuth2ClientDO client = oauth2ClientMapper.selectByClientId(clientId);
|
||||||
if (client == null) {
|
if (client == null) {
|
||||||
return;
|
return;
|
||||||
@ -160,7 +162,7 @@ public class OAuth2ClientServiceImpl implements OAuth2ClientService {
|
|||||||
if (id == null) {
|
if (id == null) {
|
||||||
throw exception(OAUTH2_CLIENT_EXISTS);
|
throw exception(OAUTH2_CLIENT_EXISTS);
|
||||||
}
|
}
|
||||||
if (!client.getClientId().equals(clientId)) {
|
if (!client.getId().equals(id)) {
|
||||||
throw exception(OAUTH2_CLIENT_EXISTS);
|
throw exception(OAUTH2_CLIENT_EXISTS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -189,7 +191,7 @@ public class OAuth2ClientServiceImpl implements OAuth2ClientService {
|
|||||||
|
|
||||||
// 校验客户端密钥
|
// 校验客户端密钥
|
||||||
if (StrUtil.isNotEmpty(clientSecret) && ObjectUtil.notEqual(client.getSecret(), clientSecret)) {
|
if (StrUtil.isNotEmpty(clientSecret) && ObjectUtil.notEqual(client.getSecret(), clientSecret)) {
|
||||||
throw exception(OAUTH2_CLIENT_CLIENT_SECRET_ERROR, clientSecret);
|
throw exception(OAUTH2_CLIENT_CLIENT_SECRET_ERROR);
|
||||||
}
|
}
|
||||||
// 校验授权方式
|
// 校验授权方式
|
||||||
if (StrUtil.isNotEmpty(authorizedGrantType) && !CollUtil.contains(client.getAuthorizedGrantTypes(), authorizedGrantType)) {
|
if (StrUtil.isNotEmpty(authorizedGrantType) && !CollUtil.contains(client.getAuthorizedGrantTypes(), authorizedGrantType)) {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package cn.iocoder.yudao.module.system.service.auth;
|
package cn.iocoder.yudao.module.system.service.oauth2;
|
||||||
|
|
||||||
|
import cn.hutool.core.map.MapUtil;
|
||||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||||
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
|
||||||
@ -9,13 +10,12 @@ import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.client.OAuth2Cl
|
|||||||
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2ClientDO;
|
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2ClientDO;
|
||||||
import cn.iocoder.yudao.module.system.dal.mysql.oauth2.OAuth2ClientMapper;
|
import cn.iocoder.yudao.module.system.dal.mysql.oauth2.OAuth2ClientMapper;
|
||||||
import cn.iocoder.yudao.module.system.mq.producer.auth.OAuth2ClientProducer;
|
import cn.iocoder.yudao.module.system.mq.producer.auth.OAuth2ClientProducer;
|
||||||
import cn.iocoder.yudao.module.system.service.oauth2.OAuth2ClientServiceImpl;
|
|
||||||
import org.junit.jupiter.api.Disabled;
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||||
import org.springframework.context.annotation.Import;
|
import org.springframework.context.annotation.Import;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
|
import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
|
||||||
@ -23,7 +23,7 @@ import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.max;
|
|||||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
|
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
|
||||||
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
|
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
|
||||||
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
|
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
|
||||||
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.OAUTH2_CLIENT_NOT_EXISTS;
|
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
@ -132,7 +132,31 @@ public class OAuth2ClientServiceImplTest extends BaseDbUnitTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Disabled
|
public void testValidateClientIdExists_withId() {
|
||||||
|
// mock 数据
|
||||||
|
OAuth2ClientDO client = randomPojo(OAuth2ClientDO.class).setClientId("tudou");
|
||||||
|
oauth2ClientMapper.insert(client);
|
||||||
|
// 准备参数
|
||||||
|
Long id = randomLongId();
|
||||||
|
String clientId = "tudou";
|
||||||
|
|
||||||
|
// 调用,不会报错
|
||||||
|
assertServiceException(() -> oauth2ClientService.validateClientIdExists(id, clientId), OAUTH2_CLIENT_EXISTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testValidateClientIdExists_noId() {
|
||||||
|
// mock 数据
|
||||||
|
OAuth2ClientDO client = randomPojo(OAuth2ClientDO.class).setClientId("tudou");
|
||||||
|
oauth2ClientMapper.insert(client);
|
||||||
|
// 准备参数
|
||||||
|
String clientId = "tudou";
|
||||||
|
|
||||||
|
// 调用,不会报错
|
||||||
|
assertServiceException(() -> oauth2ClientService.validateClientIdExists(null, clientId), OAUTH2_CLIENT_EXISTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void testGetOAuth2ClientPage() {
|
public void testGetOAuth2ClientPage() {
|
||||||
// mock 数据
|
// mock 数据
|
||||||
OAuth2ClientDO dbOAuth2Client = randomPojo(OAuth2ClientDO.class, o -> { // 等会查询到
|
OAuth2ClientDO dbOAuth2Client = randomPojo(OAuth2ClientDO.class, o -> { // 等会查询到
|
||||||
@ -143,10 +167,10 @@ public class OAuth2ClientServiceImplTest extends BaseDbUnitTest {
|
|||||||
// 测试 name 不匹配
|
// 测试 name 不匹配
|
||||||
oauth2ClientMapper.insert(cloneIgnoreId(dbOAuth2Client, o -> o.setName("凤凰")));
|
oauth2ClientMapper.insert(cloneIgnoreId(dbOAuth2Client, o -> o.setName("凤凰")));
|
||||||
// 测试 status 不匹配
|
// 测试 status 不匹配
|
||||||
oauth2ClientMapper.insert(cloneIgnoreId(dbOAuth2Client, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus())));
|
oauth2ClientMapper.insert(cloneIgnoreId(dbOAuth2Client, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
|
||||||
// 准备参数
|
// 准备参数
|
||||||
OAuth2ClientPageReqVO reqVO = new OAuth2ClientPageReqVO();
|
OAuth2ClientPageReqVO reqVO = new OAuth2ClientPageReqVO();
|
||||||
reqVO.setName("long");
|
reqVO.setName("龙");
|
||||||
reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||||
|
|
||||||
// 调用
|
// 调用
|
||||||
@ -157,4 +181,35 @@ public class OAuth2ClientServiceImplTest extends BaseDbUnitTest {
|
|||||||
assertPojoEquals(dbOAuth2Client, pageResult.getList().get(0));
|
assertPojoEquals(dbOAuth2Client, pageResult.getList().get(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testValidOAuthClientFromCache() {
|
||||||
|
// mock 方法
|
||||||
|
OAuth2ClientDO client = randomPojo(OAuth2ClientDO.class).setClientId("default")
|
||||||
|
.setStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||||
|
OAuth2ClientDO client02 = randomPojo(OAuth2ClientDO.class).setClientId("disable")
|
||||||
|
.setStatus(CommonStatusEnum.DISABLE.getStatus());
|
||||||
|
Map<String, OAuth2ClientDO> clientCache = MapUtil.<String, OAuth2ClientDO>builder()
|
||||||
|
.put(client.getClientId(), client)
|
||||||
|
.put(client02.getClientId(), client02).build();
|
||||||
|
oauth2ClientService.setClientCache(clientCache);
|
||||||
|
|
||||||
|
// 调用,并断言
|
||||||
|
assertServiceException(() -> oauth2ClientService.validOAuthClientFromCache(randomString(),
|
||||||
|
null, null, null, null), OAUTH2_CLIENT_NOT_EXISTS);
|
||||||
|
assertServiceException(() -> oauth2ClientService.validOAuthClientFromCache("disable",
|
||||||
|
null, null, null, null), OAUTH2_CLIENT_DISABLE);
|
||||||
|
assertServiceException(() -> oauth2ClientService.validOAuthClientFromCache("default",
|
||||||
|
randomString(), null, null, null), OAUTH2_CLIENT_CLIENT_SECRET_ERROR);
|
||||||
|
assertServiceException(() -> oauth2ClientService.validOAuthClientFromCache("default",
|
||||||
|
null, randomString(), null, null), OAUTH2_CLIENT_AUTHORIZED_GRANT_TYPE_NOT_EXISTS);
|
||||||
|
assertServiceException(() -> oauth2ClientService.validOAuthClientFromCache("default",
|
||||||
|
null, null, Collections.singleton(randomString()), null), OAUTH2_CLIENT_SCOPE_OVER);
|
||||||
|
assertServiceException(() -> oauth2ClientService.validOAuthClientFromCache("default",
|
||||||
|
null, null, null, "test"), OAUTH2_CLIENT_REDIRECT_URI_NOT_MATCH, "test");
|
||||||
|
// 成功调用
|
||||||
|
OAuth2ClientDO result = oauth2ClientService.validOAuthClientFromCache(client.getClientId(), client.getSecret(),
|
||||||
|
client.getAuthorizedGrantTypes().get(0), client.getScopes(), client.getRedirectUris().get(0));
|
||||||
|
assertPojoEquals(client, result);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -482,9 +482,9 @@ CREATE TABLE IF NOT EXISTS "system_oauth2_client" (
|
|||||||
"access_token_validity_seconds" int NOT NULL,
|
"access_token_validity_seconds" int NOT NULL,
|
||||||
"refresh_token_validity_seconds" int NOT NULL,
|
"refresh_token_validity_seconds" int NOT NULL,
|
||||||
"redirect_uris" varchar NOT NULL,
|
"redirect_uris" varchar NOT NULL,
|
||||||
"auto_approve" bit NOT NULL DEFAULT FALSE,
|
|
||||||
"authorized_grant_types" varchar NOT NULL,
|
"authorized_grant_types" varchar NOT NULL,
|
||||||
"scopes" varchar NOT NULL DEFAULT '',
|
"scopes" varchar NOT NULL DEFAULT '',
|
||||||
|
"auto_approve_scopes" varchar NOT NULL DEFAULT '',
|
||||||
"authorities" varchar NOT NULL DEFAULT '',
|
"authorities" varchar NOT NULL DEFAULT '',
|
||||||
"resource_ids" varchar NOT NULL DEFAULT '',
|
"resource_ids" varchar NOT NULL DEFAULT '',
|
||||||
"additional_information" varchar NOT NULL DEFAULT '',
|
"additional_information" varchar NOT NULL DEFAULT '',
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
<el-form-item style="width:100%;">
|
<el-form-item style="width:100%;">
|
||||||
<el-button :loading="loading" size="medium" type="primary" style="width:60%;"
|
<el-button :loading="loading" size="medium" type="primary" style="width:60%;"
|
||||||
@click.native.prevent="handleAuthorize(true)">
|
@click.native.prevent="handleAuthorize(true)">
|
||||||
<span v-if="!loading">统一授权</span>
|
<span v-if="!loading">同意授权</span>
|
||||||
<span v-else>授 权 中...</span>
|
<span v-else>授 权 中...</span>
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button size="medium" style="width:36%"
|
<el-button size="medium" style="width:36%"
|
||||||
|
Loading…
Reference in New Issue
Block a user