Commit b3ab1d9285be30ec00d8f62e14b1294b17e888d8
1 parent
66855135
完善 OAuth2ClientServiceImplTest 单元测试
Showing
12 changed files
with
198 additions
and
99 deletions
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/OAuth2OpenController.http
| ... | ... | @@ -52,18 +52,3 @@ tenant-id: {{adminTenentId}} |
| 52 | 52 | POST {{baseUrl}}/system/oauth2/check-token?token=620d307c5b4148df8a98dd6c6c547106 |
| 53 | 53 | Authorization: Basic ZGVmYXVsdDphZG1pbjEyMw== |
| 54 | 54 | tenant-id: {{adminTenentId}} |
| 55 | - | |
| 56 | -### 请求 /system/oauth2/user/get 接口 => 成功 | |
| 57 | -GET {{baseUrl}}/system/oauth2/user/get | |
| 58 | -Authorization: Bearer 9502bd7a768a4ade920b90f41e2efd5c | |
| 59 | -tenant-id: {{adminTenentId}} | |
| 60 | - | |
| 61 | -### 请求 /system/oauth2/user/update 接口 => 成功 | |
| 62 | -PUT {{baseUrl}}/system/oauth2/user/update | |
| 63 | -Content-Type: application/json | |
| 64 | -Authorization: Bearer 9502bd7a768a4ade920b90f41e2efd5c | |
| 65 | -tenant-id: {{adminTenentId}} | |
| 66 | - | |
| 67 | -{ | |
| 68 | - "nickname": "芋道源码" | |
| 69 | -} | ... | ... |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/OAuth2OpenController.java
| 1 | 1 | package cn.iocoder.yudao.module.system.controller.admin.oauth2; |
| 2 | 2 | |
| 3 | -import cn.hutool.core.collection.CollUtil; | |
| 4 | 3 | import cn.hutool.core.lang.Assert; |
| 5 | 4 | import cn.hutool.core.util.ArrayUtil; |
| 6 | 5 | import cn.hutool.core.util.ObjectUtil; |
| ... | ... | @@ -13,36 +12,26 @@ import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; |
| 13 | 12 | import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.OAuth2OpenAccessTokenRespVO; |
| 14 | 13 | import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.OAuth2OpenAuthorizeInfoRespVO; |
| 15 | 14 | import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.OAuth2OpenCheckTokenRespVO; |
| 16 | -import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.user.OAuth2OpenUserInfoRespVO; | |
| 17 | -import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.user.OAuth2OpenUserUpdateReqVO; | |
| 18 | 15 | import cn.iocoder.yudao.module.system.convert.oauth2.OAuth2OpenConvert; |
| 19 | -import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; | |
| 20 | -import cn.iocoder.yudao.module.system.dal.dataobject.dept.PostDO; | |
| 21 | 16 | import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO; |
| 22 | 17 | import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2ApproveDO; |
| 23 | 18 | import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2ClientDO; |
| 24 | -import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; | |
| 25 | 19 | import cn.iocoder.yudao.module.system.enums.auth.OAuth2GrantTypeEnum; |
| 26 | -import cn.iocoder.yudao.module.system.service.dept.DeptService; | |
| 27 | -import cn.iocoder.yudao.module.system.service.dept.PostService; | |
| 28 | 20 | import cn.iocoder.yudao.module.system.service.oauth2.OAuth2ApproveService; |
| 29 | 21 | import cn.iocoder.yudao.module.system.service.oauth2.OAuth2ClientService; |
| 30 | 22 | import cn.iocoder.yudao.module.system.service.oauth2.OAuth2GrantService; |
| 31 | 23 | import cn.iocoder.yudao.module.system.service.oauth2.OAuth2TokenService; |
| 32 | -import cn.iocoder.yudao.module.system.service.user.AdminUserService; | |
| 33 | 24 | import cn.iocoder.yudao.module.system.util.oauth2.OAuth2Utils; |
| 34 | 25 | import io.swagger.annotations.Api; |
| 35 | 26 | import io.swagger.annotations.ApiImplicitParam; |
| 36 | 27 | import io.swagger.annotations.ApiImplicitParams; |
| 37 | 28 | import io.swagger.annotations.ApiOperation; |
| 38 | 29 | import lombok.extern.slf4j.Slf4j; |
| 39 | -import org.springframework.security.access.prepost.PreAuthorize; | |
| 40 | 30 | import org.springframework.validation.annotation.Validated; |
| 41 | 31 | import org.springframework.web.bind.annotation.*; |
| 42 | 32 | |
| 43 | 33 | import javax.annotation.Resource; |
| 44 | 34 | import javax.servlet.http.HttpServletRequest; |
| 45 | -import javax.validation.Valid; | |
| 46 | 35 | import java.util.Collections; |
| 47 | 36 | import java.util.List; |
| 48 | 37 | import java.util.Map; |
| ... | ... | @@ -61,7 +50,9 @@ import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUti |
| 61 | 50 | * 另外,一个公司如果有多个管理后台,它们 client_id 产生的 access token 相互之间是无法互通的,即无法访问它们系统的 API 接口,直到两个 client_id 产生信任授权。 |
| 62 | 51 | * |
| 63 | 52 | * 考虑到【本系统】暂时不想做的过于复杂,默认只有获取到 access token 之后,可以访问【本系统】管理后台的 /system-api/* 所有接口,除非手动添加 scope 控制。 |
| 64 | - * scope 的使用示例,可见当前类的 getUserInfo 和 updateUserInfo 方法,上面有 @PreAuthorize("@ss.hasScope('user.read')") 和 @PreAuthorize("@ss.hasScope('user.write')") 注解 | |
| 53 | + * scope 的使用示例,可见 {@link OAuth2UserController} 类 | |
| 54 | + * | |
| 55 | + * | |
| 65 | 56 | * |
| 66 | 57 | * @author 芋道源码 |
| 67 | 58 | */ |
| ... | ... | @@ -306,43 +297,4 @@ public class OAuth2OpenController { |
| 306 | 297 | return clientIdAndSecret; |
| 307 | 298 | } |
| 308 | 299 | |
| 309 | - // ============ 用户操作的示例,展示 scope 的使用 ============ | |
| 310 | - | |
| 311 | - @Resource | |
| 312 | - private AdminUserService userService; | |
| 313 | - @Resource | |
| 314 | - private DeptService deptService; | |
| 315 | - @Resource | |
| 316 | - private PostService postService; | |
| 317 | - | |
| 318 | - @GetMapping("/user/get") | |
| 319 | - @ApiOperation("获得用户基本信息") | |
| 320 | - @PreAuthorize("@ss.hasScope('user.read')") | |
| 321 | - public CommonResult<OAuth2OpenUserInfoRespVO> getUserInfo() { | |
| 322 | - // 获得用户基本信息 | |
| 323 | - AdminUserDO user = userService.getUser(getLoginUserId()); | |
| 324 | - OAuth2OpenUserInfoRespVO resp = OAuth2OpenConvert.INSTANCE.convert(user); | |
| 325 | - // 获得部门信息 | |
| 326 | - if (user.getDeptId() != null) { | |
| 327 | - DeptDO dept = deptService.getDept(user.getDeptId()); | |
| 328 | - resp.setDept(OAuth2OpenConvert.INSTANCE.convert(dept)); | |
| 329 | - } | |
| 330 | - // 获得岗位信息 | |
| 331 | - if (CollUtil.isNotEmpty(user.getPostIds())) { | |
| 332 | - List<PostDO> posts = postService.getPosts(user.getPostIds()); | |
| 333 | - resp.setPosts(OAuth2OpenConvert.INSTANCE.convertList(posts)); | |
| 334 | - } | |
| 335 | - return success(resp); | |
| 336 | - } | |
| 337 | - | |
| 338 | - @PutMapping("/user/update") | |
| 339 | - @ApiOperation("更新用户基本信息") | |
| 340 | - @PreAuthorize("@ss.hasScope('user.write')") | |
| 341 | - public CommonResult<Boolean> updateUserInfo(@Valid @RequestBody OAuth2OpenUserUpdateReqVO reqVO) { | |
| 342 | - // 这里将 UserProfileUpdateReqVO =》UserProfileUpdateReqVO 对象,实现接口的复用。 | |
| 343 | - // 主要是,AdminUserService 没有自己的 BO 对象,所以复用只能这么做 | |
| 344 | - userService.updateUserProfile(getLoginUserId(), OAuth2OpenConvert.INSTANCE.convert(reqVO)); | |
| 345 | - return success(true); | |
| 346 | - } | |
| 347 | - | |
| 348 | 300 | } | ... | ... |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/OAuth2UserController.http
0 → 100644
| 1 | +### 请求 /system/oauth2/user/get 接口 => 成功 | |
| 2 | +GET {{baseUrl}}/system/oauth2/user/get | |
| 3 | +Authorization: Bearer 47f9c74ec11041f193b777ebb95c3b0d | |
| 4 | +tenant-id: {{adminTenentId}} | |
| 5 | + | |
| 6 | +### 请求 /system/oauth2/user/update 接口 => 成功 | |
| 7 | +PUT {{baseUrl}}/system/oauth2/user/update | |
| 8 | +Content-Type: application/json | |
| 9 | +Authorization: Bearer 47f9c74ec11041f193b777ebb95c3b0d | |
| 10 | +tenant-id: {{adminTenentId}} | |
| 11 | + | |
| 12 | +{ | |
| 13 | + "nickname": "芋道源码" | |
| 14 | +} | ... | ... |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/OAuth2UserController.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.controller.admin.oauth2; | |
| 2 | + | |
| 3 | +import cn.hutool.core.collection.CollUtil; | |
| 4 | +import cn.iocoder.yudao.framework.common.pojo.CommonResult; | |
| 5 | +import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.user.OAuth2UserInfoRespVO; | |
| 6 | +import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.user.OAuth2UserUpdateReqVO; | |
| 7 | +import cn.iocoder.yudao.module.system.convert.oauth2.OAuth2UserConvert; | |
| 8 | +import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; | |
| 9 | +import cn.iocoder.yudao.module.system.dal.dataobject.dept.PostDO; | |
| 10 | +import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; | |
| 11 | +import cn.iocoder.yudao.module.system.service.dept.DeptService; | |
| 12 | +import cn.iocoder.yudao.module.system.service.dept.PostService; | |
| 13 | +import cn.iocoder.yudao.module.system.service.user.AdminUserService; | |
| 14 | +import io.swagger.annotations.Api; | |
| 15 | +import io.swagger.annotations.ApiOperation; | |
| 16 | +import lombok.extern.slf4j.Slf4j; | |
| 17 | +import org.springframework.security.access.prepost.PreAuthorize; | |
| 18 | +import org.springframework.validation.annotation.Validated; | |
| 19 | +import org.springframework.web.bind.annotation.*; | |
| 20 | + | |
| 21 | +import javax.annotation.Resource; | |
| 22 | +import javax.validation.Valid; | |
| 23 | +import java.util.List; | |
| 24 | + | |
| 25 | +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; | |
| 26 | +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; | |
| 27 | + | |
| 28 | +/** | |
| 29 | + * 提供给外部应用调用为主 | |
| 30 | + * | |
| 31 | + * 1. 在 getUserInfo 方法上,添加 @PreAuthorize("@ss.hasScope('user.read')") 注解,声明需要满足 scope = user.read | |
| 32 | + * 2. 在 updateUserInfo 方法上,添加 @PreAuthorize("@ss.hasScope('user.write')") 注解,声明需要满足 scope = user.write | |
| 33 | + * | |
| 34 | + * @author 芋道源码 | |
| 35 | + */ | |
| 36 | +@Api(tags = "管理后台 - OAuth2.0 用户") | |
| 37 | +@RestController | |
| 38 | +@RequestMapping("/system/oauth2/user") | |
| 39 | +@Validated | |
| 40 | +@Slf4j | |
| 41 | +public class OAuth2UserController { | |
| 42 | + | |
| 43 | + @Resource | |
| 44 | + private AdminUserService userService; | |
| 45 | + @Resource | |
| 46 | + private DeptService deptService; | |
| 47 | + @Resource | |
| 48 | + private PostService postService; | |
| 49 | + | |
| 50 | + @GetMapping("/get") | |
| 51 | + @ApiOperation("获得用户基本信息") | |
| 52 | + @PreAuthorize("@ss.hasScope('user.read')") // | |
| 53 | + public CommonResult<OAuth2UserInfoRespVO> getUserInfo() { | |
| 54 | + // 获得用户基本信息 | |
| 55 | + AdminUserDO user = userService.getUser(getLoginUserId()); | |
| 56 | + OAuth2UserInfoRespVO resp = OAuth2UserConvert.INSTANCE.convert(user); | |
| 57 | + // 获得部门信息 | |
| 58 | + if (user.getDeptId() != null) { | |
| 59 | + DeptDO dept = deptService.getDept(user.getDeptId()); | |
| 60 | + resp.setDept(OAuth2UserConvert.INSTANCE.convert(dept)); | |
| 61 | + } | |
| 62 | + // 获得岗位信息 | |
| 63 | + if (CollUtil.isNotEmpty(user.getPostIds())) { | |
| 64 | + List<PostDO> posts = postService.getPosts(user.getPostIds()); | |
| 65 | + resp.setPosts(OAuth2UserConvert.INSTANCE.convertList(posts)); | |
| 66 | + } | |
| 67 | + return success(resp); | |
| 68 | + } | |
| 69 | + | |
| 70 | + @PutMapping("/update") | |
| 71 | + @ApiOperation("更新用户基本信息") | |
| 72 | + @PreAuthorize("@ss.hasScope('user.write')") | |
| 73 | + public CommonResult<Boolean> updateUserInfo(@Valid @RequestBody OAuth2UserUpdateReqVO reqVO) { | |
| 74 | + // 这里将 UserProfileUpdateReqVO =》UserProfileUpdateReqVO 对象,实现接口的复用。 | |
| 75 | + // 主要是,AdminUserService 没有自己的 BO 对象,所以复用只能这么做 | |
| 76 | + userService.updateUserProfile(getLoginUserId(), OAuth2UserConvert.INSTANCE.convert(reqVO)); | |
| 77 | + return success(true); | |
| 78 | + } | |
| 79 | + | |
| 80 | +} | ... | ... |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/open/user/OAuth2OpenUserInfoRespVO.java renamed to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/user/OAuth2UserInfoRespVO.java
| 1 | -package cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.user; | |
| 1 | +package cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.user; | |
| 2 | 2 | |
| 3 | 3 | import io.swagger.annotations.ApiModel; |
| 4 | 4 | import io.swagger.annotations.ApiModelProperty; |
| ... | ... | @@ -8,11 +8,11 @@ import lombok.NoArgsConstructor; |
| 8 | 8 | |
| 9 | 9 | import java.util.List; |
| 10 | 10 | |
| 11 | -@ApiModel("管理后台 - 【开放接口】获得用户基本信息 Response VO") | |
| 11 | +@ApiModel("管理后台 - OAuth2.0 获得用户基本信息 Response VO") | |
| 12 | 12 | @Data |
| 13 | 13 | @NoArgsConstructor |
| 14 | 14 | @AllArgsConstructor |
| 15 | -public class OAuth2OpenUserInfoRespVO { | |
| 15 | +public class OAuth2UserInfoRespVO { | |
| 16 | 16 | |
| 17 | 17 | @ApiModelProperty(value = "用户编号", required = true, example = "1") |
| 18 | 18 | private Long id; | ... | ... |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/open/user/OAuth2OpenUserUpdateReqVO.java renamed to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/oauth2/vo/user/OAuth2UserUpdateReqVO.java
| 1 | -package cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.user; | |
| 1 | +package cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.user; | |
| 2 | 2 | |
| 3 | 3 | import io.swagger.annotations.ApiModel; |
| 4 | 4 | import io.swagger.annotations.ApiModelProperty; |
| ... | ... | @@ -10,11 +10,11 @@ import org.hibernate.validator.constraints.Length; |
| 10 | 10 | import javax.validation.constraints.Email; |
| 11 | 11 | import javax.validation.constraints.Size; |
| 12 | 12 | |
| 13 | -@ApiModel("管理后台 - 【开放接口】更新用户基本信息 Request VO") | |
| 13 | +@ApiModel("管理后台 - OAuth2.0 更新用户基本信息 Request VO") | |
| 14 | 14 | @Data |
| 15 | 15 | @NoArgsConstructor |
| 16 | 16 | @AllArgsConstructor |
| 17 | -public class OAuth2OpenUserUpdateReqVO { | |
| 17 | +public class OAuth2UserUpdateReqVO { | |
| 18 | 18 | |
| 19 | 19 | @ApiModelProperty(value = "用户昵称", required = true, example = "芋艿") |
| 20 | 20 | @Size(max = 30, message = "用户昵称长度不能超过 30 个字符") | ... | ... |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/oauth2/OAuth2OpenConvert.java
| ... | ... | @@ -7,15 +7,9 @@ import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; |
| 7 | 7 | import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.OAuth2OpenAccessTokenRespVO; |
| 8 | 8 | import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.OAuth2OpenAuthorizeInfoRespVO; |
| 9 | 9 | import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.OAuth2OpenCheckTokenRespVO; |
| 10 | -import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.user.OAuth2OpenUserInfoRespVO; | |
| 11 | -import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.open.user.OAuth2OpenUserUpdateReqVO; | |
| 12 | -import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO; | |
| 13 | -import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; | |
| 14 | -import cn.iocoder.yudao.module.system.dal.dataobject.dept.PostDO; | |
| 15 | 10 | import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO; |
| 16 | 11 | import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2ApproveDO; |
| 17 | 12 | import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2ClientDO; |
| 18 | -import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; | |
| 19 | 13 | import cn.iocoder.yudao.module.system.util.oauth2.OAuth2Utils; |
| 20 | 14 | import org.mapstruct.Mapper; |
| 21 | 15 | import org.mapstruct.factory.Mappers; |
| ... | ... | @@ -46,14 +40,6 @@ public interface OAuth2OpenConvert { |
| 46 | 40 | } |
| 47 | 41 | OAuth2OpenCheckTokenRespVO convert3(OAuth2AccessTokenDO bean); |
| 48 | 42 | |
| 49 | - // ============ 用户操作的示例 ============ | |
| 50 | - | |
| 51 | - OAuth2OpenUserInfoRespVO convert(AdminUserDO bean); | |
| 52 | - OAuth2OpenUserInfoRespVO.Dept convert(DeptDO dept); | |
| 53 | - List<OAuth2OpenUserInfoRespVO.Post> convertList(List<PostDO> list); | |
| 54 | - | |
| 55 | - UserProfileUpdateReqVO convert(OAuth2OpenUserUpdateReqVO bean); | |
| 56 | - | |
| 57 | 43 | default OAuth2OpenAuthorizeInfoRespVO convert(OAuth2ClientDO client, List<OAuth2ApproveDO> approves) { |
| 58 | 44 | // 构建 scopes |
| 59 | 45 | List<KeyValue<String, Boolean>> scopes = new ArrayList<>(client.getScopes().size()); | ... | ... |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/oauth2/OAuth2UserConvert.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.convert.oauth2; | |
| 2 | + | |
| 3 | +import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.user.OAuth2UserInfoRespVO; | |
| 4 | +import cn.iocoder.yudao.module.system.controller.admin.oauth2.vo.user.OAuth2UserUpdateReqVO; | |
| 5 | +import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO; | |
| 6 | +import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; | |
| 7 | +import cn.iocoder.yudao.module.system.dal.dataobject.dept.PostDO; | |
| 8 | +import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; | |
| 9 | +import org.mapstruct.Mapper; | |
| 10 | +import org.mapstruct.factory.Mappers; | |
| 11 | + | |
| 12 | +import java.util.List; | |
| 13 | + | |
| 14 | +@Mapper | |
| 15 | +public interface OAuth2UserConvert { | |
| 16 | + | |
| 17 | + OAuth2UserConvert INSTANCE = Mappers.getMapper(OAuth2UserConvert.class); | |
| 18 | + | |
| 19 | + OAuth2UserInfoRespVO convert(AdminUserDO bean); | |
| 20 | + OAuth2UserInfoRespVO.Dept convert(DeptDO dept); | |
| 21 | + List<OAuth2UserInfoRespVO.Post> convertList(List<PostDO> list); | |
| 22 | + | |
| 23 | + UserProfileUpdateReqVO convert(OAuth2UserUpdateReqVO bean); | |
| 24 | + | |
| 25 | +} | ... | ... |
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2ClientServiceImpl.java
| ... | ... | @@ -15,6 +15,7 @@ import cn.iocoder.yudao.module.system.dal.mysql.oauth2.OAuth2ClientMapper; |
| 15 | 15 | import cn.iocoder.yudao.module.system.mq.producer.auth.OAuth2ClientProducer; |
| 16 | 16 | import com.google.common.annotations.VisibleForTesting; |
| 17 | 17 | import lombok.Getter; |
| 18 | +import lombok.Setter; | |
| 18 | 19 | import lombok.extern.slf4j.Slf4j; |
| 19 | 20 | import org.springframework.scheduling.annotation.Scheduled; |
| 20 | 21 | import org.springframework.stereotype.Service; |
| ... | ... | @@ -51,7 +52,8 @@ public class OAuth2ClientServiceImpl implements OAuth2ClientService { |
| 51 | 52 | * |
| 52 | 53 | * 这里声明 volatile 修饰的原因是,每次刷新时,直接修改指向 |
| 53 | 54 | */ |
| 54 | - @Getter | |
| 55 | + @Getter // 解决单测 | |
| 56 | + @Setter // 解决单测 | |
| 55 | 57 | private volatile Map<String, OAuth2ClientDO> clientCache; |
| 56 | 58 | /** |
| 57 | 59 | * 缓存角色的最大更新时间,用于后续的增量轮询,判断是否有更新 |
| ... | ... | @@ -151,7 +153,7 @@ public class OAuth2ClientServiceImpl implements OAuth2ClientService { |
| 151 | 153 | } |
| 152 | 154 | |
| 153 | 155 | @VisibleForTesting |
| 154 | - public void validateClientIdExists(Long id, String clientId) { | |
| 156 | + void validateClientIdExists(Long id, String clientId) { | |
| 155 | 157 | OAuth2ClientDO client = oauth2ClientMapper.selectByClientId(clientId); |
| 156 | 158 | if (client == null) { |
| 157 | 159 | return; |
| ... | ... | @@ -160,7 +162,7 @@ public class OAuth2ClientServiceImpl implements OAuth2ClientService { |
| 160 | 162 | if (id == null) { |
| 161 | 163 | throw exception(OAUTH2_CLIENT_EXISTS); |
| 162 | 164 | } |
| 163 | - if (!client.getClientId().equals(clientId)) { | |
| 165 | + if (!client.getId().equals(id)) { | |
| 164 | 166 | throw exception(OAUTH2_CLIENT_EXISTS); |
| 165 | 167 | } |
| 166 | 168 | } |
| ... | ... | @@ -189,7 +191,7 @@ public class OAuth2ClientServiceImpl implements OAuth2ClientService { |
| 189 | 191 | |
| 190 | 192 | // 校验客户端密钥 |
| 191 | 193 | if (StrUtil.isNotEmpty(clientSecret) && ObjectUtil.notEqual(client.getSecret(), clientSecret)) { |
| 192 | - throw exception(OAUTH2_CLIENT_CLIENT_SECRET_ERROR, clientSecret); | |
| 194 | + throw exception(OAUTH2_CLIENT_CLIENT_SECRET_ERROR); | |
| 193 | 195 | } |
| 194 | 196 | // 校验授权方式 |
| 195 | 197 | if (StrUtil.isNotEmpty(authorizedGrantType) && !CollUtil.contains(client.getAuthorizedGrantTypes(), authorizedGrantType)) { | ... | ... |
yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/auth/OAuth2ClientServiceImplTest.java renamed to yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/oauth2/OAuth2ClientServiceImplTest.java
| 1 | -package cn.iocoder.yudao.module.system.service.auth; | |
| 1 | +package cn.iocoder.yudao.module.system.service.oauth2; | |
| 2 | 2 | |
| 3 | +import cn.hutool.core.map.MapUtil; | |
| 3 | 4 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| 4 | 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 5 | 6 | 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 |
| 9 | 10 | import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2ClientDO; |
| 10 | 11 | import cn.iocoder.yudao.module.system.dal.mysql.oauth2.OAuth2ClientMapper; |
| 11 | 12 | import cn.iocoder.yudao.module.system.mq.producer.auth.OAuth2ClientProducer; |
| 12 | -import cn.iocoder.yudao.module.system.service.oauth2.OAuth2ClientServiceImpl; | |
| 13 | -import org.junit.jupiter.api.Disabled; | |
| 14 | 13 | import org.junit.jupiter.api.Test; |
| 15 | 14 | import org.springframework.boot.test.mock.mockito.MockBean; |
| 16 | 15 | import org.springframework.context.annotation.Import; |
| 17 | 16 | |
| 18 | 17 | import javax.annotation.Resource; |
| 18 | +import java.util.Collections; | |
| 19 | 19 | import java.util.Map; |
| 20 | 20 | |
| 21 | 21 | 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; |
| 23 | 23 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; |
| 24 | 24 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; |
| 25 | 25 | import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; |
| 26 | -import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.OAUTH2_CLIENT_NOT_EXISTS; | |
| 26 | +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; | |
| 27 | 27 | import static org.junit.jupiter.api.Assertions.*; |
| 28 | 28 | import static org.mockito.Mockito.verify; |
| 29 | 29 | |
| ... | ... | @@ -132,7 +132,31 @@ public class OAuth2ClientServiceImplTest extends BaseDbUnitTest { |
| 132 | 132 | } |
| 133 | 133 | |
| 134 | 134 | @Test |
| 135 | - @Disabled | |
| 135 | + public void testValidateClientIdExists_withId() { | |
| 136 | + // mock 数据 | |
| 137 | + OAuth2ClientDO client = randomPojo(OAuth2ClientDO.class).setClientId("tudou"); | |
| 138 | + oauth2ClientMapper.insert(client); | |
| 139 | + // 准备参数 | |
| 140 | + Long id = randomLongId(); | |
| 141 | + String clientId = "tudou"; | |
| 142 | + | |
| 143 | + // 调用,不会报错 | |
| 144 | + assertServiceException(() -> oauth2ClientService.validateClientIdExists(id, clientId), OAUTH2_CLIENT_EXISTS); | |
| 145 | + } | |
| 146 | + | |
| 147 | + @Test | |
| 148 | + public void testValidateClientIdExists_noId() { | |
| 149 | + // mock 数据 | |
| 150 | + OAuth2ClientDO client = randomPojo(OAuth2ClientDO.class).setClientId("tudou"); | |
| 151 | + oauth2ClientMapper.insert(client); | |
| 152 | + // 准备参数 | |
| 153 | + String clientId = "tudou"; | |
| 154 | + | |
| 155 | + // 调用,不会报错 | |
| 156 | + assertServiceException(() -> oauth2ClientService.validateClientIdExists(null, clientId), OAUTH2_CLIENT_EXISTS); | |
| 157 | + } | |
| 158 | + | |
| 159 | + @Test | |
| 136 | 160 | public void testGetOAuth2ClientPage() { |
| 137 | 161 | // mock 数据 |
| 138 | 162 | OAuth2ClientDO dbOAuth2Client = randomPojo(OAuth2ClientDO.class, o -> { // 等会查询到 |
| ... | ... | @@ -143,10 +167,10 @@ public class OAuth2ClientServiceImplTest extends BaseDbUnitTest { |
| 143 | 167 | // 测试 name 不匹配 |
| 144 | 168 | oauth2ClientMapper.insert(cloneIgnoreId(dbOAuth2Client, o -> o.setName("凤凰"))); |
| 145 | 169 | // 测试 status 不匹配 |
| 146 | - oauth2ClientMapper.insert(cloneIgnoreId(dbOAuth2Client, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus()))); | |
| 170 | + oauth2ClientMapper.insert(cloneIgnoreId(dbOAuth2Client, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus()))); | |
| 147 | 171 | // 准备参数 |
| 148 | 172 | OAuth2ClientPageReqVO reqVO = new OAuth2ClientPageReqVO(); |
| 149 | - reqVO.setName("long"); | |
| 173 | + reqVO.setName("龙"); | |
| 150 | 174 | reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus()); |
| 151 | 175 | |
| 152 | 176 | // 调用 |
| ... | ... | @@ -157,4 +181,35 @@ public class OAuth2ClientServiceImplTest extends BaseDbUnitTest { |
| 157 | 181 | assertPojoEquals(dbOAuth2Client, pageResult.getList().get(0)); |
| 158 | 182 | } |
| 159 | 183 | |
| 184 | + @Test | |
| 185 | + public void testValidOAuthClientFromCache() { | |
| 186 | + // mock 方法 | |
| 187 | + OAuth2ClientDO client = randomPojo(OAuth2ClientDO.class).setClientId("default") | |
| 188 | + .setStatus(CommonStatusEnum.ENABLE.getStatus()); | |
| 189 | + OAuth2ClientDO client02 = randomPojo(OAuth2ClientDO.class).setClientId("disable") | |
| 190 | + .setStatus(CommonStatusEnum.DISABLE.getStatus()); | |
| 191 | + Map<String, OAuth2ClientDO> clientCache = MapUtil.<String, OAuth2ClientDO>builder() | |
| 192 | + .put(client.getClientId(), client) | |
| 193 | + .put(client02.getClientId(), client02).build(); | |
| 194 | + oauth2ClientService.setClientCache(clientCache); | |
| 195 | + | |
| 196 | + // 调用,并断言 | |
| 197 | + assertServiceException(() -> oauth2ClientService.validOAuthClientFromCache(randomString(), | |
| 198 | + null, null, null, null), OAUTH2_CLIENT_NOT_EXISTS); | |
| 199 | + assertServiceException(() -> oauth2ClientService.validOAuthClientFromCache("disable", | |
| 200 | + null, null, null, null), OAUTH2_CLIENT_DISABLE); | |
| 201 | + assertServiceException(() -> oauth2ClientService.validOAuthClientFromCache("default", | |
| 202 | + randomString(), null, null, null), OAUTH2_CLIENT_CLIENT_SECRET_ERROR); | |
| 203 | + assertServiceException(() -> oauth2ClientService.validOAuthClientFromCache("default", | |
| 204 | + null, randomString(), null, null), OAUTH2_CLIENT_AUTHORIZED_GRANT_TYPE_NOT_EXISTS); | |
| 205 | + assertServiceException(() -> oauth2ClientService.validOAuthClientFromCache("default", | |
| 206 | + null, null, Collections.singleton(randomString()), null), OAUTH2_CLIENT_SCOPE_OVER); | |
| 207 | + assertServiceException(() -> oauth2ClientService.validOAuthClientFromCache("default", | |
| 208 | + null, null, null, "test"), OAUTH2_CLIENT_REDIRECT_URI_NOT_MATCH, "test"); | |
| 209 | + // 成功调用 | |
| 210 | + OAuth2ClientDO result = oauth2ClientService.validOAuthClientFromCache(client.getClientId(), client.getSecret(), | |
| 211 | + client.getAuthorizedGrantTypes().get(0), client.getScopes(), client.getRedirectUris().get(0)); | |
| 212 | + assertPojoEquals(client, result); | |
| 213 | + } | |
| 214 | + | |
| 160 | 215 | } | ... | ... |
yudao-module-system/yudao-module-system-biz/src/test/resources/sql/create_tables.sql
| ... | ... | @@ -482,9 +482,9 @@ CREATE TABLE IF NOT EXISTS "system_oauth2_client" ( |
| 482 | 482 | "access_token_validity_seconds" int NOT NULL, |
| 483 | 483 | "refresh_token_validity_seconds" int NOT NULL, |
| 484 | 484 | "redirect_uris" varchar NOT NULL, |
| 485 | - "auto_approve" bit NOT NULL DEFAULT FALSE, | |
| 486 | 485 | "authorized_grant_types" varchar NOT NULL, |
| 487 | 486 | "scopes" varchar NOT NULL DEFAULT '', |
| 487 | + "auto_approve_scopes" varchar NOT NULL DEFAULT '', | |
| 488 | 488 | "authorities" varchar NOT NULL DEFAULT '', |
| 489 | 489 | "resource_ids" varchar NOT NULL DEFAULT '', |
| 490 | 490 | "additional_information" varchar NOT NULL DEFAULT '', | ... | ... |
yudao-ui-admin/src/views/sso.vue
| ... | ... | @@ -37,7 +37,7 @@ |
| 37 | 37 | <el-form-item style="width:100%;"> |
| 38 | 38 | <el-button :loading="loading" size="medium" type="primary" style="width:60%;" |
| 39 | 39 | @click.native.prevent="handleAuthorize(true)"> |
| 40 | - <span v-if="!loading">统一授权</span> | |
| 40 | + <span v-if="!loading">同意授权</span> | |
| 41 | 41 | <span v-else>授 权 中...</span> |
| 42 | 42 | </el-button> |
| 43 | 43 | <el-button size="medium" style="width:36%" | ... | ... |