Commit f46d81dab5768b871dea0a84ac1bb00417747abd

Authored by YunaiV
1 parent 5cf68961

增加 OAuth2 客户端

Showing 18 changed files with 798 additions and 3 deletions
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java
@@ -119,8 +119,11 @@ public interface ErrorCodeConstants { @@ -119,8 +119,11 @@ public interface ErrorCodeConstants {
119 ErrorCode SOCIAL_USER_UNBIND_NOT_SELF = new ErrorCode(1002018001, "社交解绑失败,非当前用户绑定"); 119 ErrorCode SOCIAL_USER_UNBIND_NOT_SELF = new ErrorCode(1002018001, "社交解绑失败,非当前用户绑定");
120 ErrorCode SOCIAL_USER_NOT_FOUND = new ErrorCode(1002018002, "社交授权失败,找不到对应的用户"); 120 ErrorCode SOCIAL_USER_NOT_FOUND = new ErrorCode(1002018002, "社交授权失败,找不到对应的用户");
121 121
122 - // ========== 系统铭感词 1002019000 ========= 122 + // ========== 系统敏感词 1002019000 =========
123 ErrorCode SENSITIVE_WORD_NOT_EXISTS = new ErrorCode(1002019000, "系统敏感词在所有标签中都不存在"); 123 ErrorCode SENSITIVE_WORD_NOT_EXISTS = new ErrorCode(1002019000, "系统敏感词在所有标签中都不存在");
124 ErrorCode SENSITIVE_WORD_EXISTS = new ErrorCode(1002019001, "系统敏感词已在标签中存在"); 124 ErrorCode SENSITIVE_WORD_EXISTS = new ErrorCode(1002019001, "系统敏感词已在标签中存在");
125 125
  126 + // ========== 系统敏感词 1002020000 =========
  127 + ErrorCode OAUTH2_CLIENT_NOT_EXISTS = new ErrorCode(1002020000, "OAuth2 客户端不存在");
  128 +
126 } 129 }
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/OAuth2ClientController.java 0 → 100755
  1 +package cn.iocoder.yudao.module.system.controller.admin.auth;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  4 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  5 +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.client.OAuth2ClientCreateReqVO;
  6 +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.client.OAuth2ClientPageReqVO;
  7 +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.client.OAuth2ClientRespVO;
  8 +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.client.OAuth2ClientUpdateReqVO;
  9 +import cn.iocoder.yudao.module.system.convert.auth.OAuth2ClientConvert;
  10 +import cn.iocoder.yudao.module.system.dal.dataobject.auth.OAuth2ClientDO;
  11 +import cn.iocoder.yudao.module.system.service.auth.OAuth2ClientService;
  12 +import io.swagger.annotations.Api;
  13 +import io.swagger.annotations.ApiImplicitParam;
  14 +import io.swagger.annotations.ApiOperation;
  15 +import org.springframework.security.access.prepost.PreAuthorize;
  16 +import org.springframework.validation.annotation.Validated;
  17 +import org.springframework.web.bind.annotation.*;
  18 +
  19 +import javax.annotation.Resource;
  20 +import javax.validation.Valid;
  21 +
  22 +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  23 +
  24 +@Api(tags = "管理后台 - OAuth2 客户端")
  25 +@RestController
  26 +@RequestMapping("/system/oauth2-client")
  27 +@Validated
  28 +public class OAuth2ClientController {
  29 +
  30 + @Resource
  31 + private OAuth2ClientService oAuth2ClientService;
  32 +
  33 + @PostMapping("/create")
  34 + @ApiOperation("创建 OAuth2 客户端")
  35 + @PreAuthorize("@ss.hasPermission('system:oauth2-client:create')")
  36 + public CommonResult<Long> createOAuth2Client(@Valid @RequestBody OAuth2ClientCreateReqVO createReqVO) {
  37 + return success(oAuth2ClientService.createOAuth2Client(createReqVO));
  38 + }
  39 +
  40 + @PutMapping("/update")
  41 + @ApiOperation("更新 OAuth2 客户端")
  42 + @PreAuthorize("@ss.hasPermission('system:oauth2-client:update')")
  43 + public CommonResult<Boolean> updateOAuth2Client(@Valid @RequestBody OAuth2ClientUpdateReqVO updateReqVO) {
  44 + oAuth2ClientService.updateOAuth2Client(updateReqVO);
  45 + return success(true);
  46 + }
  47 +
  48 + @DeleteMapping("/delete")
  49 + @ApiOperation("删除 OAuth2 客户端")
  50 + @ApiImplicitParam(name = "id", value = "编号", required = true, dataTypeClass = Long.class)
  51 + @PreAuthorize("@ss.hasPermission('system:oauth2-client:delete')")
  52 + public CommonResult<Boolean> deleteOAuth2Client(@RequestParam("id") Long id) {
  53 + oAuth2ClientService.deleteOAuth2Client(id);
  54 + return success(true);
  55 + }
  56 +
  57 + @GetMapping("/get")
  58 + @ApiOperation("获得 OAuth2 客户端")
  59 + @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
  60 + @PreAuthorize("@ss.hasPermission('system:oauth2-client:query')")
  61 + public CommonResult<OAuth2ClientRespVO> getOAuth2Client(@RequestParam("id") Long id) {
  62 + OAuth2ClientDO oAuth2Client = oAuth2ClientService.getOAuth2Client(id);
  63 + return success(OAuth2ClientConvert.INSTANCE.convert(oAuth2Client));
  64 + }
  65 +
  66 + @GetMapping("/page")
  67 + @ApiOperation("获得OAuth2 客户端分页")
  68 + @PreAuthorize("@ss.hasPermission('system:oauth2-client:query')")
  69 + public CommonResult<PageResult<OAuth2ClientRespVO>> getOAuth2ClientPage(@Valid OAuth2ClientPageReqVO pageVO) {
  70 + PageResult<OAuth2ClientDO> pageResult = oAuth2ClientService.getOAuth2ClientPage(pageVO);
  71 + return success(OAuth2ClientConvert.INSTANCE.convertPage(pageResult));
  72 + }
  73 +
  74 +}
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/client/OAuth2ClientBaseVO.java 0 → 100755
  1 +package cn.iocoder.yudao.module.system.controller.admin.auth.vo.client;
  2 +
  3 +import io.swagger.annotations.ApiModelProperty;
  4 +import lombok.Data;
  5 +
  6 +import javax.validation.constraints.NotNull;
  7 +import java.util.List;
  8 +
  9 +/**
  10 +* OAuth2 客户端 Base VO,提供给添加、修改、详细的子 VO 使用
  11 +* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
  12 +*/
  13 +@Data
  14 +public class OAuth2ClientBaseVO {
  15 +
  16 + @ApiModelProperty(value = "客户端编号", required = true)
  17 + @NotNull(message = "客户端编号不能为空")
  18 + private Long id;
  19 +
  20 + @ApiModelProperty(value = "客户端密钥", required = true)
  21 + @NotNull(message = "客户端密钥不能为空")
  22 + private String secret;
  23 +
  24 + @ApiModelProperty(value = "应用名", required = true)
  25 + @NotNull(message = "应用名不能为空")
  26 + private String name;
  27 +
  28 + @ApiModelProperty(value = "应用图标", required = true)
  29 + @NotNull(message = "应用图标不能为空")
  30 + private String logo;
  31 +
  32 + @ApiModelProperty(value = "应用描述")
  33 + private String description;
  34 +
  35 + @ApiModelProperty(value = "状态", required = true)
  36 + @NotNull(message = "状态不能为空")
  37 + private Integer status;
  38 +
  39 + @ApiModelProperty(value = "访问令牌的有效期", required = true)
  40 + @NotNull(message = "访问令牌的有效期不能为空")
  41 + private Integer accessTokenValiditySeconds;
  42 +
  43 + @ApiModelProperty(value = "刷新令牌的有效期", required = true)
  44 + @NotNull(message = "刷新令牌的有效期不能为空")
  45 + private Integer refreshTokenValiditySeconds;
  46 +
  47 + @ApiModelProperty(value = "可重定向的 URI 地址", required = true)
  48 + @NotNull(message = "可重定向的 URI 地址不能为空")
  49 + private List<String> redirectUris;
  50 +
  51 +}
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/client/OAuth2ClientCreateReqVO.java 0 → 100755
  1 +package cn.iocoder.yudao.module.system.controller.admin.auth.vo.client;
  2 +
  3 +import lombok.*;
  4 +import io.swagger.annotations.*;
  5 +
  6 +@ApiModel("管理后台 - OAuth2 客户端创建 Request VO")
  7 +@Data
  8 +@EqualsAndHashCode(callSuper = true)
  9 +@ToString(callSuper = true)
  10 +public class OAuth2ClientCreateReqVO extends OAuth2ClientBaseVO {
  11 +
  12 +}
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/client/OAuth2ClientPageReqVO.java 0 → 100755
  1 +package cn.iocoder.yudao.module.system.controller.admin.auth.vo.client;
  2 +
  3 +import lombok.*;
  4 +import io.swagger.annotations.*;
  5 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  6 +
  7 +@ApiModel("管理后台 - OAuth2 客户端分页 Request VO")
  8 +@Data
  9 +@EqualsAndHashCode(callSuper = true)
  10 +@ToString(callSuper = true)
  11 +public class OAuth2ClientPageReqVO extends PageParam {
  12 +
  13 + @ApiModelProperty(value = "应用名")
  14 + private String name;
  15 +
  16 + @ApiModelProperty(value = "状态")
  17 + private Integer status;
  18 +
  19 +}
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/client/OAuth2ClientRespVO.java 0 → 100755
  1 +package cn.iocoder.yudao.module.system.controller.admin.auth.vo.client;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.Data;
  6 +import lombok.EqualsAndHashCode;
  7 +import lombok.ToString;
  8 +
  9 +import java.util.Date;
  10 +
  11 +@ApiModel("管理后台 - OAuth2 客户端 Response VO")
  12 +@Data
  13 +@EqualsAndHashCode(callSuper = true)
  14 +@ToString(callSuper = true)
  15 +public class OAuth2ClientRespVO extends OAuth2ClientBaseVO {
  16 +
  17 + @ApiModelProperty(value = "创建时间", required = true)
  18 + private Date createTime;
  19 +
  20 +}
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/client/OAuth2ClientUpdateReqVO.java 0 → 100755
  1 +package cn.iocoder.yudao.module.system.controller.admin.auth.vo.client;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import lombok.Data;
  5 +import lombok.EqualsAndHashCode;
  6 +import lombok.ToString;
  7 +
  8 +@ApiModel("管理后台 - OAuth2 客户端更新 Request VO")
  9 +@Data
  10 +@EqualsAndHashCode(callSuper = true)
  11 +@ToString(callSuper = true)
  12 +public class OAuth2ClientUpdateReqVO extends OAuth2ClientBaseVO {
  13 +
  14 +}
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/auth/OAuth2ClientConvert.java 0 → 100755
  1 +package cn.iocoder.yudao.module.system.convert.auth;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.client.OAuth2ClientCreateReqVO;
  5 +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.client.OAuth2ClientRespVO;
  6 +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.client.OAuth2ClientUpdateReqVO;
  7 +import cn.iocoder.yudao.module.system.dal.dataobject.auth.OAuth2ClientDO;
  8 +import org.mapstruct.Mapper;
  9 +import org.mapstruct.factory.Mappers;
  10 +
  11 +import java.util.List;
  12 +
  13 +/**
  14 + * OAuth2 客户端 Convert
  15 + *
  16 + * @author 芋道源码
  17 + */
  18 +@Mapper
  19 +public interface OAuth2ClientConvert {
  20 +
  21 + OAuth2ClientConvert INSTANCE = Mappers.getMapper(OAuth2ClientConvert.class);
  22 +
  23 + OAuth2ClientDO convert(OAuth2ClientCreateReqVO bean);
  24 +
  25 + OAuth2ClientDO convert(OAuth2ClientUpdateReqVO bean);
  26 +
  27 + OAuth2ClientRespVO convert(OAuth2ClientDO bean);
  28 +
  29 + List<OAuth2ClientRespVO> convertList(List<OAuth2ClientDO> list);
  30 +
  31 + PageResult<OAuth2ClientRespVO> convertPage(PageResult<OAuth2ClientDO> page);
  32 +
  33 +}
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/auth/OAuth2ClientDO.java
@@ -2,8 +2,11 @@ package cn.iocoder.yudao.module.system.dal.dataobject.auth; @@ -2,8 +2,11 @@ package cn.iocoder.yudao.module.system.dal.dataobject.auth;
2 2
3 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 3 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
4 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; 4 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  5 +import com.baomidou.mybatisplus.annotation.IdType;
  6 +import com.baomidou.mybatisplus.annotation.TableField;
5 import com.baomidou.mybatisplus.annotation.TableId; 7 import com.baomidou.mybatisplus.annotation.TableId;
6 import com.baomidou.mybatisplus.annotation.TableName; 8 import com.baomidou.mybatisplus.annotation.TableName;
  9 +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
7 import lombok.Data; 10 import lombok.Data;
8 import lombok.EqualsAndHashCode; 11 import lombok.EqualsAndHashCode;
9 import lombok.experimental.Accessors; 12 import lombok.experimental.Accessors;
@@ -18,7 +21,7 @@ import java.util.List; @@ -18,7 +21,7 @@ import java.util.List;
18 * 21 *
19 * @author 芋道源码 22 * @author 芋道源码
20 */ 23 */
21 -@TableName("system_oauth2_application") 24 +@TableName(value = "system_oauth2_client", autoResultMap = true)
22 @Data 25 @Data
23 @EqualsAndHashCode(callSuper = true) 26 @EqualsAndHashCode(callSuper = true)
24 @Accessors(chain = true) 27 @Accessors(chain = true)
@@ -29,7 +32,7 @@ public class OAuth2ClientDO extends BaseDO { @@ -29,7 +32,7 @@ public class OAuth2ClientDO extends BaseDO {
29 * 32 *
30 * 由于 SQL Server 在存储 String 主键有点问题,所以暂时使用 Long 类型 33 * 由于 SQL Server 在存储 String 主键有点问题,所以暂时使用 Long 类型
31 */ 34 */
32 - @TableId 35 + @TableId(type = IdType.INPUT)
33 private Long id; 36 private Long id;
34 /** 37 /**
35 * 客户端密钥 38 * 客户端密钥
@@ -64,6 +67,7 @@ public class OAuth2ClientDO extends BaseDO { @@ -64,6 +67,7 @@ public class OAuth2ClientDO extends BaseDO {
64 /** 67 /**
65 * 可重定向的 URI 地址 68 * 可重定向的 URI 地址
66 */ 69 */
  70 + @TableField(typeHandler = JacksonTypeHandler.class)
67 private List<String> redirectUris; 71 private List<String> redirectUris;
68 72
69 } 73 }
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/auth/OAuth2ClientMapper.java 0 → 100755
  1 +package cn.iocoder.yudao.module.system.dal.mysql.auth;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  5 +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
  6 +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.client.OAuth2ClientPageReqVO;
  7 +import cn.iocoder.yudao.module.system.dal.dataobject.auth.OAuth2ClientDO;
  8 +import org.apache.ibatis.annotations.Mapper;
  9 +
  10 +/**
  11 + * OAuth2 客户端 Mapper
  12 + *
  13 + * @author 芋道源码
  14 + */
  15 +@Mapper
  16 +public interface OAuth2ClientMapper extends BaseMapperX<OAuth2ClientDO> {
  17 +
  18 + default PageResult<OAuth2ClientDO> selectPage(OAuth2ClientPageReqVO reqVO) {
  19 + return selectPage(reqVO, new LambdaQueryWrapperX<OAuth2ClientDO>()
  20 + .likeIfPresent(OAuth2ClientDO::getName, reqVO.getName())
  21 + .eqIfPresent(OAuth2ClientDO::getStatus, reqVO.getStatus())
  22 + .orderByDesc(OAuth2ClientDO::getId));
  23 + }
  24 +
  25 +}
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/OAuth2ClientService.java
1 package cn.iocoder.yudao.module.system.service.auth; 1 package cn.iocoder.yudao.module.system.service.auth;
2 2
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.client.OAuth2ClientCreateReqVO;
  5 +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.client.OAuth2ClientPageReqVO;
  6 +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.client.OAuth2ClientUpdateReqVO;
3 import cn.iocoder.yudao.module.system.dal.dataobject.auth.OAuth2ClientDO; 7 import cn.iocoder.yudao.module.system.dal.dataobject.auth.OAuth2ClientDO;
4 8
  9 +import javax.validation.Valid;
  10 +
5 /** 11 /**
6 * OAuth2.0 Client Service 接口 12 * OAuth2.0 Client Service 接口
7 * 13 *
@@ -12,6 +18,44 @@ import cn.iocoder.yudao.module.system.dal.dataobject.auth.OAuth2ClientDO; @@ -12,6 +18,44 @@ import cn.iocoder.yudao.module.system.dal.dataobject.auth.OAuth2ClientDO;
12 public interface OAuth2ClientService { 18 public interface OAuth2ClientService {
13 19
14 /** 20 /**
  21 + * 创建OAuth2 客户端
  22 + *
  23 + * @param createReqVO 创建信息
  24 + * @return 编号
  25 + */
  26 + Long createOAuth2Client(@Valid OAuth2ClientCreateReqVO createReqVO);
  27 +
  28 + /**
  29 + * 更新OAuth2 客户端
  30 + *
  31 + * @param updateReqVO 更新信息
  32 + */
  33 + void updateOAuth2Client(@Valid OAuth2ClientUpdateReqVO updateReqVO);
  34 +
  35 + /**
  36 + * 删除OAuth2 客户端
  37 + *
  38 + * @param id 编号
  39 + */
  40 + void deleteOAuth2Client(Long id);
  41 +
  42 + /**
  43 + * 获得OAuth2 客户端
  44 + *
  45 + * @param id 编号
  46 + * @return OAuth2 客户端
  47 + */
  48 + OAuth2ClientDO getOAuth2Client(Long id);
  49 +
  50 + /**
  51 + * 获得OAuth2 客户端分页
  52 + *
  53 + * @param pageReqVO 分页查询
  54 + * @return OAuth2 客户端分页
  55 + */
  56 + PageResult<OAuth2ClientDO> getOAuth2ClientPage(OAuth2ClientPageReqVO pageReqVO);
  57 +
  58 + /**
15 * 从缓存中,校验客户端是否合法 59 * 从缓存中,校验客户端是否合法
16 * 60 *
17 * @param id 客户端编号 61 * @param id 客户端编号
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/OAuth2ClientServiceImpl.java
1 package cn.iocoder.yudao.module.system.service.auth; 1 package cn.iocoder.yudao.module.system.service.auth;
2 2
  3 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.client.OAuth2ClientCreateReqVO;
  5 +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.client.OAuth2ClientPageReqVO;
  6 +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.client.OAuth2ClientUpdateReqVO;
  7 +import cn.iocoder.yudao.module.system.convert.auth.OAuth2ClientConvert;
3 import cn.iocoder.yudao.module.system.dal.dataobject.auth.OAuth2ClientDO; 8 import cn.iocoder.yudao.module.system.dal.dataobject.auth.OAuth2ClientDO;
  9 +import cn.iocoder.yudao.module.system.dal.mysql.auth.OAuth2ClientMapper;
4 import org.springframework.stereotype.Service; 10 import org.springframework.stereotype.Service;
5 11
  12 +import javax.annotation.Resource;
  13 +
  14 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  15 +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.OAUTH2_CLIENT_NOT_EXISTS;
  16 +
6 /** 17 /**
7 * OAuth2.0 Client Service 实现类 18 * OAuth2.0 Client Service 实现类
8 * 19 *
@@ -11,6 +22,51 @@ import org.springframework.stereotype.Service; @@ -11,6 +22,51 @@ import org.springframework.stereotype.Service;
11 @Service 22 @Service
12 public class OAuth2ClientServiceImpl implements OAuth2ClientService { 23 public class OAuth2ClientServiceImpl implements OAuth2ClientService {
13 24
  25 + @Resource
  26 + private OAuth2ClientMapper oauth2ClientMapper;
  27 +
  28 + @Override
  29 + public Long createOAuth2Client(OAuth2ClientCreateReqVO createReqVO) {
  30 + // 插入
  31 + OAuth2ClientDO oAuth2Client = OAuth2ClientConvert.INSTANCE.convert(createReqVO);
  32 + oauth2ClientMapper.insert(oAuth2Client);
  33 + // 返回
  34 + return oAuth2Client.getId();
  35 + }
  36 +
  37 + @Override
  38 + public void updateOAuth2Client(OAuth2ClientUpdateReqVO updateReqVO) {
  39 + // 校验存在
  40 + this.validateOAuth2ClientExists(updateReqVO.getId());
  41 + // 更新
  42 + OAuth2ClientDO updateObj = OAuth2ClientConvert.INSTANCE.convert(updateReqVO);
  43 + oauth2ClientMapper.updateById(updateObj);
  44 + }
  45 +
  46 + @Override
  47 + public void deleteOAuth2Client(Long id) {
  48 + // 校验存在
  49 + this.validateOAuth2ClientExists(id);
  50 + // 删除
  51 + oauth2ClientMapper.deleteById(id);
  52 + }
  53 +
  54 + private void validateOAuth2ClientExists(Long id) {
  55 + if (oauth2ClientMapper.selectById(id) == null) {
  56 + throw exception(OAUTH2_CLIENT_NOT_EXISTS);
  57 + }
  58 + }
  59 +
  60 + @Override
  61 + public OAuth2ClientDO getOAuth2Client(Long id) {
  62 + return oauth2ClientMapper.selectById(id);
  63 + }
  64 +
  65 + @Override
  66 + public PageResult<OAuth2ClientDO> getOAuth2ClientPage(OAuth2ClientPageReqVO pageReqVO) {
  67 + return oauth2ClientMapper.selectPage(pageReqVO);
  68 + }
  69 +
14 @Override 70 @Override
15 public OAuth2ClientDO validOAuthClientFromCache(Long id) { 71 public OAuth2ClientDO validOAuthClientFromCache(Long id) {
16 return new OAuth2ClientDO().setId(id) 72 return new OAuth2ClientDO().setId(id)
yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/auth/OAuth2ClientServiceImplTest.java 0 → 100755
  1 +package cn.iocoder.yudao.module.system.service.auth;
  2 +
  3 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
  4 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  5 +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
  6 +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.client.OAuth2ClientCreateReqVO;
  7 +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.client.OAuth2ClientPageReqVO;
  8 +import cn.iocoder.yudao.module.system.controller.admin.auth.vo.client.OAuth2ClientUpdateReqVO;
  9 +import cn.iocoder.yudao.module.system.dal.dataobject.auth.OAuth2ClientDO;
  10 +import cn.iocoder.yudao.module.system.dal.mysql.auth.OAuth2ClientMapper;
  11 +import org.junit.jupiter.api.Disabled;
  12 +import org.junit.jupiter.api.Test;
  13 +import org.springframework.context.annotation.Import;
  14 +
  15 +import javax.annotation.Resource;
  16 +
  17 +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
  18 +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
  19 +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
  20 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
  21 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
  22 +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.OAUTH2_CLIENT_NOT_EXISTS;
  23 +import static org.junit.jupiter.api.Assertions.*;
  24 +
  25 +/**
  26 +* {@link OAuth2ClientServiceImpl} 的单元测试类
  27 +*
  28 +* @author 芋道源码
  29 +*/
  30 +@Import(OAuth2ClientServiceImpl.class)
  31 +public class OAuth2ClientServiceImplTest extends BaseDbUnitTest {
  32 +
  33 + @Resource
  34 + private OAuth2ClientServiceImpl oAuth2ClientService;
  35 +
  36 + @Resource
  37 + private OAuth2ClientMapper oAuth2ClientMapper;
  38 +
  39 + @Test
  40 + public void testCreateOAuth2Client_success() {
  41 + // 准备参数
  42 + OAuth2ClientCreateReqVO reqVO = randomPojo(OAuth2ClientCreateReqVO.class);
  43 +
  44 + // 调用
  45 + Long oauth2ClientId = oAuth2ClientService.createOAuth2Client(reqVO);
  46 + // 断言
  47 + assertNotNull(oauth2ClientId);
  48 + // 校验记录的属性是否正确
  49 + OAuth2ClientDO oAuth2Client = oAuth2ClientMapper.selectById(oauth2ClientId);
  50 + assertPojoEquals(reqVO, oAuth2Client);
  51 + }
  52 +
  53 + @Test
  54 + public void testUpdateOAuth2Client_success() {
  55 + // mock 数据
  56 + OAuth2ClientDO dbOAuth2Client = randomPojo(OAuth2ClientDO.class);
  57 + oAuth2ClientMapper.insert(dbOAuth2Client);// @Sql: 先插入出一条存在的数据
  58 + // 准备参数
  59 + OAuth2ClientUpdateReqVO reqVO = randomPojo(OAuth2ClientUpdateReqVO.class, o -> {
  60 + o.setId(dbOAuth2Client.getId()); // 设置更新的 ID
  61 + });
  62 +
  63 + // 调用
  64 + oAuth2ClientService.updateOAuth2Client(reqVO);
  65 + // 校验是否更新正确
  66 + OAuth2ClientDO oAuth2Client = oAuth2ClientMapper.selectById(reqVO.getId()); // 获取最新的
  67 + assertPojoEquals(reqVO, oAuth2Client);
  68 + }
  69 +
  70 + @Test
  71 + public void testUpdateOAuth2Client_notExists() {
  72 + // 准备参数
  73 + OAuth2ClientUpdateReqVO reqVO = randomPojo(OAuth2ClientUpdateReqVO.class);
  74 +
  75 + // 调用, 并断言异常
  76 + assertServiceException(() -> oAuth2ClientService.updateOAuth2Client(reqVO), OAUTH2_CLIENT_NOT_EXISTS);
  77 + }
  78 +
  79 + @Test
  80 + public void testDeleteOAuth2Client_success() {
  81 + // mock 数据
  82 + OAuth2ClientDO dbOAuth2Client = randomPojo(OAuth2ClientDO.class);
  83 + oAuth2ClientMapper.insert(dbOAuth2Client);// @Sql: 先插入出一条存在的数据
  84 + // 准备参数
  85 + Long id = dbOAuth2Client.getId();
  86 +
  87 + // 调用
  88 + oAuth2ClientService.deleteOAuth2Client(id);
  89 + // 校验数据不存在了
  90 + assertNull(oAuth2ClientMapper.selectById(id));
  91 + }
  92 +
  93 + @Test
  94 + public void testDeleteOAuth2Client_notExists() {
  95 + // 准备参数
  96 + Long id = randomLongId();
  97 +
  98 + // 调用, 并断言异常
  99 + assertServiceException(() -> oAuth2ClientService.deleteOAuth2Client(id), OAUTH2_CLIENT_NOT_EXISTS);
  100 + }
  101 +
  102 + @Test
  103 + @Disabled
  104 + public void testGetOAuth2ClientPage() {
  105 + // mock 数据
  106 + OAuth2ClientDO dbOAuth2Client = randomPojo(OAuth2ClientDO.class, o -> { // 等会查询到
  107 + o.setName("潜龙");
  108 + o.setStatus(CommonStatusEnum.ENABLE.getStatus());
  109 + });
  110 + oAuth2ClientMapper.insert(dbOAuth2Client);
  111 + // 测试 name 不匹配
  112 + oAuth2ClientMapper.insert(cloneIgnoreId(dbOAuth2Client, o -> o.setName("凤凰")));
  113 + // 测试 status 不匹配
  114 + oAuth2ClientMapper.insert(cloneIgnoreId(dbOAuth2Client, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus())));
  115 + // 准备参数
  116 + OAuth2ClientPageReqVO reqVO = new OAuth2ClientPageReqVO();
  117 + reqVO.setName("long");
  118 + reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
  119 +
  120 + // 调用
  121 + PageResult<OAuth2ClientDO> pageResult = oAuth2ClientService.getOAuth2ClientPage(reqVO);
  122 + // 断言
  123 + assertEquals(1, pageResult.getTotal());
  124 + assertEquals(1, pageResult.getList().size());
  125 + assertPojoEquals(dbOAuth2Client, pageResult.getList().get(0));
  126 + }
  127 +
  128 +}
yudao-module-system/yudao-module-system-biz/src/test/resources/sql/clean.sql
@@ -20,3 +20,4 @@ DELETE FROM &quot;system_social_user_bind&quot;; @@ -20,3 +20,4 @@ DELETE FROM &quot;system_social_user_bind&quot;;
20 DELETE FROM "system_tenant"; 20 DELETE FROM "system_tenant";
21 DELETE FROM "system_tenant_package"; 21 DELETE FROM "system_tenant_package";
22 DELETE FROM "system_sensitive_word"; 22 DELETE FROM "system_sensitive_word";
  23 +DELETE FROM "system_oauth2_client";
yudao-module-system/yudao-module-system-biz/src/test/resources/sql/create_tables.sql
@@ -470,3 +470,21 @@ CREATE TABLE IF NOT EXISTS &quot;system_sensitive_word&quot; ( @@ -470,3 +470,21 @@ CREATE TABLE IF NOT EXISTS &quot;system_sensitive_word&quot; (
470 "deleted" bit NOT NULL DEFAULT FALSE, 470 "deleted" bit NOT NULL DEFAULT FALSE,
471 PRIMARY KEY ("id") 471 PRIMARY KEY ("id")
472 ) COMMENT '系统敏感词'; 472 ) COMMENT '系统敏感词';
  473 +
  474 +CREATE TABLE IF NOT EXISTS "system_oauth2_client" (
  475 + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
  476 + "secret" varchar NOT NULL,
  477 + "name" varchar NOT NULL,
  478 + "logo" varchar NOT NULL,
  479 + "description" varchar,
  480 + "status" int NOT NULL,
  481 + "access_token_validity_seconds" int NOT NULL,
  482 + "refresh_token_validity_seconds" int NOT NULL,
  483 + "redirect_uris" varchar NOT NULL,
  484 + "creator" varchar DEFAULT '',
  485 + "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  486 + "updater" varchar DEFAULT '',
  487 + "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  488 + "deleted" bit NOT NULL DEFAULT FALSE,
  489 + PRIMARY KEY ("id")
  490 +) COMMENT 'OAuth2 客户端表';
yudao-server/src/main/resources/application.yaml
@@ -114,6 +114,7 @@ yudao: @@ -114,6 +114,7 @@ yudao:
114 - system_sms_template 114 - system_sms_template
115 - system_sms_log 115 - system_sms_log
116 - system_sensitive_word 116 - system_sensitive_word
  117 + - system_oauth2_client
117 - infra_codegen_column 118 - infra_codegen_column
118 - infra_codegen_table 119 - infra_codegen_table
119 - infra_test_demo 120 - infra_test_demo
yudao-ui-admin/src/api/system/oauth2/oauth2Client.js 0 → 100755
  1 +import request from '@/utils/request'
  2 +
  3 +// 创建 OAuth2 客户端
  4 +export function createOAuth2Client(data) {
  5 + return request({
  6 + url: '/system/oauth2-client/create',
  7 + method: 'post',
  8 + data: data
  9 + })
  10 +}
  11 +
  12 +// 更新 OAuth2 客户端
  13 +export function updateOAuth2Client(data) {
  14 + return request({
  15 + url: '/system/oauth2-client/update',
  16 + method: 'put',
  17 + data: data
  18 + })
  19 +}
  20 +
  21 +// 删除 OAuth2 客户端
  22 +export function deleteOAuth2Client(id) {
  23 + return request({
  24 + url: '/system/oauth2-client/delete?id=' + id,
  25 + method: 'delete'
  26 + })
  27 +}
  28 +
  29 +// 获得 OAuth2 客户端
  30 +export function getOAuth2Client(id) {
  31 + return request({
  32 + url: '/system/oauth2-client/get?id=' + id,
  33 + method: 'get'
  34 + })
  35 +}
  36 +
  37 +// 获得 OAuth2 客户端分页
  38 +export function getOAuth2ClientPage(query) {
  39 + return request({
  40 + url: '/system/oauth2-client/page',
  41 + method: 'get',
  42 + params: query
  43 + })
  44 +}
yudao-ui-admin/src/views/system/oauth2/client/index.vue 0 → 100755
  1 +<template>
  2 + <div class="app-container">
  3 +
  4 + <!-- 搜索工作栏 -->
  5 + <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
  6 + <el-form-item label="应用名" prop="name">
  7 + <el-input v-model="queryParams.name" placeholder="请输入应用名" clearable @keyup.enter.native="handleQuery"/>
  8 + </el-form-item>
  9 + <el-form-item label="状态" prop="status">
  10 + <el-select v-model="queryParams.status" placeholder="请选择状态" clearable size="small">
  11 + <el-option v-for="dict in this.getDictDatas(DICT_TYPE.COMMON_STATUS)"
  12 + :key="dict.value" :label="dict.label" :value="dict.value"/>
  13 + </el-select>
  14 + </el-form-item>
  15 + <el-form-item>
  16 + <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
  17 + <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
  18 + </el-form-item>
  19 + </el-form>
  20 +
  21 + <!-- 操作工具栏 -->
  22 + <el-row :gutter="10" class="mb8">
  23 + <el-col :span="1.5">
  24 + <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
  25 + v-hasPermi="['system:oauth2-client:create']">新增</el-button>
  26 + </el-col>
  27 + <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
  28 + </el-row>
  29 +
  30 + <!-- 列表 -->
  31 + <el-table v-loading="loading" :data="list">
  32 + <el-table-column label="客户端编号" align="center" prop="id" />
  33 + <el-table-column label="客户端密钥" align="center" prop="secret" />
  34 + <el-table-column label="应用名" align="center" prop="name" />
  35 + <el-table-column label="应用图标" align="center" prop="logo" />
  36 + <el-table-column label="应用描述" align="center" prop="description" />
  37 + <el-table-column label="状态" align="center" prop="status">
  38 + <template slot-scope="scope">
  39 + <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
  40 + </template>
  41 + </el-table-column>
  42 + <el-table-column label="访问令牌的有效期" align="center" prop="accessTokenValiditySeconds" />
  43 + <el-table-column label="刷新令牌的有效期" align="center" prop="refreshTokenValiditySeconds" />
  44 + <el-table-column label="可重定向的 URI 地址" align="center" prop="redirectUris" />
  45 + <el-table-column label="创建时间" align="center" prop="createTime" width="180">
  46 + <template slot-scope="scope">
  47 + <span>{{ parseTime(scope.row.createTime) }}</span>
  48 + </template>
  49 + </el-table-column>
  50 + <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
  51 + <template slot-scope="scope">
  52 + <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
  53 + v-hasPermi="['system:oauth2-client:update']">修改</el-button>
  54 + <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
  55 + v-hasPermi="['system:oauth2-client:delete']">删除</el-button>
  56 + </template>
  57 + </el-table-column>
  58 + </el-table>
  59 + <!-- 分页组件 -->
  60 + <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
  61 + @pagination="getList"/>
  62 +
  63 + <!-- 对话框(添加 / 修改) -->
  64 + <el-dialog :title="title" :visible.sync="open" width="700px" append-to-body>
  65 + <el-form ref="form" :model="form" :rules="rules" label-width="160px">
  66 + <el-form-item label="客户端密钥" prop="secret">
  67 + <el-input v-model="form.secret" placeholder="请输入客户端密钥" />
  68 + </el-form-item>
  69 + <el-form-item label="应用名" prop="name">
  70 + <el-input v-model="form.name" placeholder="请输入应用名" />
  71 + </el-form-item>
  72 + <el-form-item label="应用图标">
  73 + <imageUpload v-model="form.logo" :limit="1"/>
  74 + </el-form-item>
  75 + <el-form-item label="应用描述">
  76 + <el-input type="textarea" v-model="form.description" placeholder="请输入应用名" />
  77 + </el-form-item>
  78 + <el-form-item label="状态" prop="status">
  79 + <el-radio-group v-model="form.status">
  80 + <el-radio v-for="dict in this.getDictDatas(DICT_TYPE.COMMON_STATUS)"
  81 + :key="dict.value" :label="parseInt(dict.value)">{{dict.label}}</el-radio>
  82 + </el-radio-group>
  83 + </el-form-item>
  84 + <el-form-item label="访问令牌的有效期" prop="accessTokenValiditySeconds">
  85 + <el-input-number v-model="form.accessTokenValiditySeconds" placeholder="单位:秒" />
  86 + </el-form-item>
  87 + <el-form-item label="刷新令牌的有效期" prop="refreshTokenValiditySeconds">
  88 + <el-input-number v-model="form.refreshTokenValiditySeconds" placeholder="单位:秒" />
  89 + </el-form-item>
  90 + <el-form-item label="可重定向的 URI 地址" prop="redirectUris">
  91 + <el-input v-model="form.redirectUris" placeholder="请输入可重定向的 URI 地址" />
  92 + </el-form-item>
  93 + </el-form>
  94 + <div slot="footer" class="dialog-footer">
  95 + <el-button type="primary" @click="submitForm">确 定</el-button>
  96 + <el-button @click="cancel">取 消</el-button>
  97 + </div>
  98 + </el-dialog>
  99 + </div>
  100 +</template>
  101 +
  102 +<script>
  103 +import { createOAuth2Client, updateOAuth2Client, deleteOAuth2Client, getOAuth2Client, getOAuth2ClientPage } from "@/api/system/oauth2/oauth2Client";
  104 +import ImageUpload from '@/components/ImageUpload';
  105 +import Editor from '@/components/Editor';
  106 +import {CommonStatusEnum} from "@/utils/constants";
  107 +
  108 +export default {
  109 + name: "OAuth2Client",
  110 + components: {
  111 + ImageUpload,
  112 + Editor,
  113 + },
  114 + data() {
  115 + return {
  116 + // 遮罩层
  117 + loading: true,
  118 + // 导出遮罩层
  119 + exportLoading: false,
  120 + // 显示搜索条件
  121 + showSearch: true,
  122 + // 总条数
  123 + total: 0,
  124 + // OAuth2 客户端列表
  125 + list: [],
  126 + // 弹出层标题
  127 + title: "",
  128 + // 是否显示弹出层
  129 + open: false,
  130 + // 查询参数
  131 + queryParams: {
  132 + pageNo: 1,
  133 + pageSize: 10,
  134 + name: null,
  135 + status: null,
  136 + },
  137 + // 表单参数
  138 + form: {},
  139 + // 表单校验
  140 + rules: {
  141 + secret: [{ required: true, message: "客户端密钥不能为空", trigger: "blur" }],
  142 + name: [{ required: true, message: "应用名不能为空", trigger: "blur" }],
  143 + logo: [{ required: true, message: "应用图标不能为空", trigger: "blur" }],
  144 + status: [{ required: true, message: "状态不能为空", trigger: "blur" }],
  145 + accessTokenValiditySeconds: [{ required: true, message: "访问令牌的有效期不能为空", trigger: "blur" }],
  146 + refreshTokenValiditySeconds: [{ required: true, message: "刷新令牌的有效期不能为空", trigger: "blur" }],
  147 + redirectUris: [{ required: true, message: "可重定向的 URI 地址不能为空", trigger: "blur" }],
  148 + }
  149 + };
  150 + },
  151 + created() {
  152 + this.getList();
  153 + },
  154 + methods: {
  155 + /** 查询列表 */
  156 + getList() {
  157 + this.loading = true;
  158 + // 处理查询参数
  159 + let params = {...this.queryParams};
  160 + // 执行查询
  161 + getOAuth2ClientPage(params).then(response => {
  162 + this.list = response.data.list;
  163 + this.total = response.data.total;
  164 + this.loading = false;
  165 + });
  166 + },
  167 + /** 取消按钮 */
  168 + cancel() {
  169 + this.open = false;
  170 + this.reset();
  171 + },
  172 + /** 表单重置 */
  173 + reset() {
  174 + this.form = {
  175 + id: undefined,
  176 + secret: undefined,
  177 + name: undefined,
  178 + logo: undefined,
  179 + description: undefined,
  180 + status: CommonStatusEnum.ENABLE,
  181 + accessTokenValiditySeconds: undefined,
  182 + refreshTokenValiditySeconds: undefined,
  183 + redirectUris: undefined,
  184 + };
  185 + this.resetForm("form");
  186 + },
  187 + /** 搜索按钮操作 */
  188 + handleQuery() {
  189 + this.queryParams.pageNo = 1;
  190 + this.getList();
  191 + },
  192 + /** 重置按钮操作 */
  193 + resetQuery() {
  194 + this.resetForm("queryForm");
  195 + this.handleQuery();
  196 + },
  197 + /** 新增按钮操作 */
  198 + handleAdd() {
  199 + this.reset();
  200 + this.open = true;
  201 + this.title = "添加 OAuth2 客户端";
  202 + },
  203 + /** 修改按钮操作 */
  204 + handleUpdate(row) {
  205 + this.reset();
  206 + const id = row.id;
  207 + getOAuth2Client(id).then(response => {
  208 + this.form = response.data;
  209 + this.open = true;
  210 + this.title = "修改 OAuth2 客户端";
  211 + });
  212 + },
  213 + /** 提交按钮 */
  214 + submitForm() {
  215 + this.$refs["form"].validate(valid => {
  216 + if (!valid) {
  217 + return;
  218 + }
  219 + // 修改的提交
  220 + if (this.form.id != null) {
  221 + updateOAuth2Client(this.form).then(response => {
  222 + this.$modal.msgSuccess("修改成功");
  223 + this.open = false;
  224 + this.getList();
  225 + });
  226 + return;
  227 + }
  228 + // 添加的提交
  229 + createOAuth2Client(this.form).then(response => {
  230 + this.$modal.msgSuccess("新增成功");
  231 + this.open = false;
  232 + this.getList();
  233 + });
  234 + });
  235 + },
  236 + /** 删除按钮操作 */
  237 + handleDelete(row) {
  238 + const id = row.id;
  239 + this.$modal.confirm('是否确认删除 OAuth2 客户端编号为"' + id + '"的数据项?').then(function() {
  240 + return deleteOAuth2Client(id);
  241 + }).then(() => {
  242 + this.getList();
  243 + this.$modal.msgSuccess("删除成功");
  244 + }).catch(() => {});
  245 + }
  246 + }
  247 +};
  248 +</script>