mirror of
https://gitee.com/fit2cloud-feizhiyun/MeterSphere.git
synced 2024-12-02 03:58:33 +08:00
feat(测试计划): 补充接口文档分享功能
--story=1016179 --user=宋昌昌 【接口测试】接口文档 https://www.tapd.cn/55049933/s/1589978
This commit is contained in:
parent
b08ce1508b
commit
ec1d26522c
@ -31,7 +31,8 @@ public class ApiDocShare implements Serializable {
|
||||
@Schema(title = "访问密码;私有时需要访问密码")
|
||||
private String password;
|
||||
|
||||
@Schema(title = "允许导出; 0: 不允许、1: 允许")
|
||||
@Schema(title = "允许导出;0: 不允许、1: 允许", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "{api_doc_share.allow_export.not_blank}", groups = {Created.class})
|
||||
private Boolean allowExport;
|
||||
|
||||
@Schema(title = "接口范围;全部接口(ALL)、模块(MODULE)、路径(PATH)、标签(TAG)", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@ -51,6 +52,11 @@ public class ApiDocShare implements Serializable {
|
||||
@Schema(title = "失效时间单位;小时(HOUR)、天(DAY)、月(MONTH)、年(YEAR)")
|
||||
private String invalidUnit;
|
||||
|
||||
@Schema(title = "项目ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{api_doc_share.project_id.not_blank}", groups = {Created.class})
|
||||
@Size(min = 1, max = 50, message = "{api_doc_share.project_id.length_range}", groups = {Created.class, Updated.class})
|
||||
private String projectId;
|
||||
|
||||
@Schema(title = "创建时间")
|
||||
private Long createTime;
|
||||
|
||||
@ -70,6 +76,7 @@ public class ApiDocShare implements Serializable {
|
||||
rangeMatchVal("range_match_val", "rangeMatchVal", "VARCHAR", false),
|
||||
invalidTime("invalid_time", "invalidTime", "INTEGER", false),
|
||||
invalidUnit("invalid_unit", "invalidUnit", "VARCHAR", false),
|
||||
projectId("project_id", "projectId", "VARCHAR", false),
|
||||
createTime("create_time", "createTime", "BIGINT", false),
|
||||
createUser("create_user", "createUser", "VARCHAR", false);
|
||||
|
||||
|
@ -774,6 +774,76 @@ public class ApiDocShareExample {
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andProjectIdIsNull() {
|
||||
addCriterion("project_id is null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andProjectIdIsNotNull() {
|
||||
addCriterion("project_id is not null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andProjectIdEqualTo(String value) {
|
||||
addCriterion("project_id =", value, "projectId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andProjectIdNotEqualTo(String value) {
|
||||
addCriterion("project_id <>", value, "projectId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andProjectIdGreaterThan(String value) {
|
||||
addCriterion("project_id >", value, "projectId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andProjectIdGreaterThanOrEqualTo(String value) {
|
||||
addCriterion("project_id >=", value, "projectId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andProjectIdLessThan(String value) {
|
||||
addCriterion("project_id <", value, "projectId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andProjectIdLessThanOrEqualTo(String value) {
|
||||
addCriterion("project_id <=", value, "projectId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andProjectIdLike(String value) {
|
||||
addCriterion("project_id like", value, "projectId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andProjectIdNotLike(String value) {
|
||||
addCriterion("project_id not like", value, "projectId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andProjectIdIn(List<String> values) {
|
||||
addCriterion("project_id in", values, "projectId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andProjectIdNotIn(List<String> values) {
|
||||
addCriterion("project_id not in", values, "projectId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andProjectIdBetween(String value1, String value2) {
|
||||
addCriterion("project_id between", value1, value2, "projectId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andProjectIdNotBetween(String value1, String value2) {
|
||||
addCriterion("project_id not between", value1, value2, "projectId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andCreateTimeIsNull() {
|
||||
addCriterion("create_time is null");
|
||||
return (Criteria) this;
|
||||
|
@ -12,6 +12,7 @@
|
||||
<result column="range_match_val" jdbcType="VARCHAR" property="rangeMatchVal" />
|
||||
<result column="invalid_time" jdbcType="INTEGER" property="invalidTime" />
|
||||
<result column="invalid_unit" jdbcType="VARCHAR" property="invalidUnit" />
|
||||
<result column="project_id" jdbcType="VARCHAR" property="projectId" />
|
||||
<result column="create_time" jdbcType="BIGINT" property="createTime" />
|
||||
<result column="create_user" jdbcType="VARCHAR" property="createUser" />
|
||||
</resultMap>
|
||||
@ -75,7 +76,7 @@
|
||||
</sql>
|
||||
<sql id="Base_Column_List">
|
||||
id, `name`, is_public, `password`, allow_export, api_range, range_match_symbol, range_match_val,
|
||||
invalid_time, invalid_unit, create_time, create_user
|
||||
invalid_time, invalid_unit, project_id, create_time, create_user
|
||||
</sql>
|
||||
<select id="selectByExample" parameterType="io.metersphere.api.domain.ApiDocShareExample" resultMap="BaseResultMap">
|
||||
select
|
||||
@ -111,13 +112,13 @@
|
||||
insert into api_doc_share (id, `name`, is_public,
|
||||
`password`, allow_export, api_range,
|
||||
range_match_symbol, range_match_val, invalid_time,
|
||||
invalid_unit, create_time, create_user
|
||||
)
|
||||
invalid_unit, project_id, create_time,
|
||||
create_user)
|
||||
values (#{id,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{isPublic,jdbcType=BIT},
|
||||
#{password,jdbcType=VARCHAR}, #{allowExport,jdbcType=BIT}, #{apiRange,jdbcType=VARCHAR},
|
||||
#{rangeMatchSymbol,jdbcType=VARCHAR}, #{rangeMatchVal,jdbcType=VARCHAR}, #{invalidTime,jdbcType=INTEGER},
|
||||
#{invalidUnit,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT}, #{createUser,jdbcType=VARCHAR}
|
||||
)
|
||||
#{invalidUnit,jdbcType=VARCHAR}, #{projectId,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT},
|
||||
#{createUser,jdbcType=VARCHAR})
|
||||
</insert>
|
||||
<insert id="insertSelective" parameterType="io.metersphere.api.domain.ApiDocShare">
|
||||
insert into api_doc_share
|
||||
@ -152,6 +153,9 @@
|
||||
<if test="invalidUnit != null">
|
||||
invalid_unit,
|
||||
</if>
|
||||
<if test="projectId != null">
|
||||
project_id,
|
||||
</if>
|
||||
<if test="createTime != null">
|
||||
create_time,
|
||||
</if>
|
||||
@ -190,6 +194,9 @@
|
||||
<if test="invalidUnit != null">
|
||||
#{invalidUnit,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="projectId != null">
|
||||
#{projectId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="createTime != null">
|
||||
#{createTime,jdbcType=BIGINT},
|
||||
</if>
|
||||
@ -237,6 +244,9 @@
|
||||
<if test="record.invalidUnit != null">
|
||||
invalid_unit = #{record.invalidUnit,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.projectId != null">
|
||||
project_id = #{record.projectId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.createTime != null">
|
||||
create_time = #{record.createTime,jdbcType=BIGINT},
|
||||
</if>
|
||||
@ -260,6 +270,7 @@
|
||||
range_match_val = #{record.rangeMatchVal,jdbcType=VARCHAR},
|
||||
invalid_time = #{record.invalidTime,jdbcType=INTEGER},
|
||||
invalid_unit = #{record.invalidUnit,jdbcType=VARCHAR},
|
||||
project_id = #{record.projectId,jdbcType=VARCHAR},
|
||||
create_time = #{record.createTime,jdbcType=BIGINT},
|
||||
create_user = #{record.createUser,jdbcType=VARCHAR}
|
||||
<if test="_parameter != null">
|
||||
@ -296,6 +307,9 @@
|
||||
<if test="invalidUnit != null">
|
||||
invalid_unit = #{invalidUnit,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="projectId != null">
|
||||
project_id = #{projectId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="createTime != null">
|
||||
create_time = #{createTime,jdbcType=BIGINT},
|
||||
</if>
|
||||
@ -316,6 +330,7 @@
|
||||
range_match_val = #{rangeMatchVal,jdbcType=VARCHAR},
|
||||
invalid_time = #{invalidTime,jdbcType=INTEGER},
|
||||
invalid_unit = #{invalidUnit,jdbcType=VARCHAR},
|
||||
project_id = #{projectId,jdbcType=VARCHAR},
|
||||
create_time = #{createTime,jdbcType=BIGINT},
|
||||
create_user = #{createUser,jdbcType=VARCHAR}
|
||||
where id = #{id,jdbcType=VARCHAR}
|
||||
@ -323,14 +338,15 @@
|
||||
<insert id="batchInsert" parameterType="map">
|
||||
insert into api_doc_share
|
||||
(id, `name`, is_public, `password`, allow_export, api_range, range_match_symbol,
|
||||
range_match_val, invalid_time, invalid_unit, create_time, create_user)
|
||||
range_match_val, invalid_time, invalid_unit, project_id, create_time, create_user
|
||||
)
|
||||
values
|
||||
<foreach collection="list" item="item" separator=",">
|
||||
(#{item.id,jdbcType=VARCHAR}, #{item.name,jdbcType=VARCHAR}, #{item.isPublic,jdbcType=BIT},
|
||||
#{item.password,jdbcType=VARCHAR}, #{item.allowExport,jdbcType=BIT}, #{item.apiRange,jdbcType=VARCHAR},
|
||||
#{item.rangeMatchSymbol,jdbcType=VARCHAR}, #{item.rangeMatchVal,jdbcType=VARCHAR},
|
||||
#{item.invalidTime,jdbcType=INTEGER}, #{item.invalidUnit,jdbcType=VARCHAR}, #{item.createTime,jdbcType=BIGINT},
|
||||
#{item.createUser,jdbcType=VARCHAR})
|
||||
#{item.invalidTime,jdbcType=INTEGER}, #{item.invalidUnit,jdbcType=VARCHAR}, #{item.projectId,jdbcType=VARCHAR},
|
||||
#{item.createTime,jdbcType=BIGINT}, #{item.createUser,jdbcType=VARCHAR})
|
||||
</foreach>
|
||||
</insert>
|
||||
<insert id="batchInsertSelective" parameterType="map">
|
||||
@ -373,6 +389,9 @@
|
||||
<if test="'invalid_unit'.toString() == column.value">
|
||||
#{item.invalidUnit,jdbcType=VARCHAR}
|
||||
</if>
|
||||
<if test="'project_id'.toString() == column.value">
|
||||
#{item.projectId,jdbcType=VARCHAR}
|
||||
</if>
|
||||
<if test="'create_time'.toString() == column.value">
|
||||
#{item.createTime,jdbcType=BIGINT}
|
||||
</if>
|
||||
|
@ -84,12 +84,13 @@ CREATE TABLE api_doc_share (
|
||||
`name` VARCHAR(255) NOT NULL COMMENT '名称' ,
|
||||
`is_public` BIT(1) NOT NULL DEFAULT 0 COMMENT '是否公开; 0: 私有、1: 公开' ,
|
||||
`password` VARCHAR(10) COMMENT '访问密码; 私有时需要访问密码' ,
|
||||
`allow_export` BIT(1) DEFAULT 0 COMMENT '允许导出; 0: 不允许、1: 允许' ,
|
||||
`allow_export` BIT(1) NOT NULL DEFAULT 0 COMMENT '允许导出; 0: 不允许、1: 允许' ,
|
||||
`api_range` VARCHAR(10) NOT NULL DEFAULT 'ALL' COMMENT '接口范围; 全部接口(ALL)、模块(MODULE)、路径(PATH)、标签(TAG)' ,
|
||||
`range_match_symbol` VARCHAR(10) COMMENT '范围匹配符; 包含(CONTAINS)、等于(EQUALS)' ,
|
||||
`range_match_val` VARCHAR(1000) COMMENT '范围匹配值; eg: 选中路径范围时, 该值作为路径匹配' ,
|
||||
`invalid_time` INT COMMENT '失效时间值' ,
|
||||
`invalid_unit` VARCHAR(10) COMMENT '失效时间单位; 小时(HOUR)、天(DAY)、月(MONTH)、年(YEAR)' ,
|
||||
`project_id` VARCHAR(50) NOT NULL COMMENT '项目ID' ,
|
||||
`create_time` BIGINT NOT NULL COMMENT '创建时间' ,
|
||||
`create_user` VARCHAR(50) NOT NULL COMMENT '创建人' ,
|
||||
PRIMARY KEY (id)
|
||||
|
@ -447,15 +447,21 @@ api_definition.status.continuous=连调中
|
||||
|
||||
api_test_case.clear.api_change=忽略本次变更差异
|
||||
api_test_case.ignore.api_change=忽略全部变更差异
|
||||
|
||||
# api doc share i18n
|
||||
api_doc_share.not_exist=接口文档分享不存在
|
||||
api_doc_share.id.not_blank=主键不能为空
|
||||
api_doc_share.id.length_range=主键长度必须在{min}和{max}之间
|
||||
api_doc_share.name.not_blank=名称不能为空
|
||||
api_doc_share.name.length_range=名称长度必须在{min}和{max}之间
|
||||
api_doc_share.is_public.not_blank=是否公开不能为空
|
||||
api_doc_share.is_public.length_range=是否公开长度必须在{min}和{max}之间
|
||||
api_doc_share.allow_export.not_blank=允许导出不能為空
|
||||
api_doc_share.allow_export.length_range=允许导出長度必須在{min}和{max}之间
|
||||
api_doc_share.api_range.not_blank=接口范围不能为空
|
||||
api_doc_share.api_range.length_range=接口范围长度必须在{min}和{max}之间
|
||||
api_doc_share.create_user.not_blank=创建人不能为空
|
||||
api_doc_share.create_user.length_range=创建人长度必须在{min}和{max}之间
|
||||
api_doc_share.project_id.not_blank=项目ID不能为空
|
||||
api_doc_share.project_id.length_range=项目ID长度必须在{min}和{max}之间
|
||||
|
||||
|
@ -457,14 +457,20 @@ api_test_case.ignore.api_change=Ignore all change differences
|
||||
curl_script_is_empty=Curl script cannot be empty
|
||||
curl_script_is_invalid=Curl script is invalid
|
||||
curl_raw_content_is_invalid=Raw content is invalid
|
||||
|
||||
# api doc share i18n
|
||||
api_doc_share.not_exist=api doc share not exist
|
||||
api_doc_share.id.not_blank=id cannot be empty
|
||||
api_doc_share.id.length_range=id length must be between {min} and {max}
|
||||
api_doc_share.name.not_blank=name cannot be empty
|
||||
api_doc_share.name.length_range=name length must be between {min} and {max}
|
||||
api_doc_share.is_public.not_blank=isPublic cannot be empty
|
||||
api_doc_share.is_public.length_range=isPublic length must be between {min} and {max}
|
||||
api_doc_share.allow_export.not_blank=allowExport cannot be empty
|
||||
api_doc_share.allow_export.length_range=allowExport length must be between {min} and {max}
|
||||
api_doc_share.api_range.not_blank=apiRange cannot be empty
|
||||
api_doc_share.api_range.length_range=apiRange length must be between {min} and {max}
|
||||
api_doc_share.create_user.not_blank=createUser cannot be empty
|
||||
api_doc_share.create_user.length_range=createUser length must be between {min} and {max}
|
||||
api_doc_share.project_id.not_blank=projectId cannot be empty
|
||||
api_doc_share.project_id.length_range=projectId length must be between {min} and {max}
|
@ -425,14 +425,20 @@ api_test_case.ignore.api_change=忽略全部变更差异
|
||||
curl_script_is_empty=cURL脚本不能为空
|
||||
curl_script_is_invalid=cURL脚本格式不正确
|
||||
curl_raw_content_is_invalid=raw内容格式不正确
|
||||
|
||||
# api doc share i18n
|
||||
api_doc_share.not_exist=接口文档分享不存在
|
||||
api_doc_share.id.not_blank=主键不能为空
|
||||
api_doc_share.id.length_range=主键长度必须在{min}和{max}之间
|
||||
api_doc_share.name.not_blank=名称不能为空
|
||||
api_doc_share.name.length_range=名称长度必须在{min}和{max}之间
|
||||
api_doc_share.is_public.not_blank=是否公开不能为空
|
||||
api_doc_share.is_public.length_range=是否公开长度必须在{min}和{max}之间
|
||||
api_doc_share.allow_export.not_blank=允许导出不能為空
|
||||
api_doc_share.allow_export.length_range=允许导出長度必須在{min}和{max}之间
|
||||
api_doc_share.api_range.not_blank=接口范围不能为空
|
||||
api_doc_share.api_range.length_range=接口范围长度必须在{min}和{max}之间
|
||||
api_doc_share.create_user.not_blank=创建人不能为空
|
||||
api_doc_share.create_user.length_range=创建人长度必须在{min}和{max}之间
|
||||
api_doc_share.project_id.not_blank=项目ID不能为空
|
||||
api_doc_share.project_id.length_range=项目ID长度必须在{min}和{max}之间
|
@ -425,14 +425,20 @@ api_test_case.ignore.api_change=忽略全部變更差異
|
||||
curl_script_is_empty=curl脚本不能爲空
|
||||
curl_script_is_invalid=curl脚本格式不正確
|
||||
curl_raw_content_is_invalid=raw内容格式不正確
|
||||
|
||||
# api doc share i18n
|
||||
api_doc_share.not_exist=接口文檔分享不存在
|
||||
api_doc_share.id.not_blank=主键不能為空
|
||||
api_doc_share.id.length_range=主键長度必須在{min}和{max}之间
|
||||
api_doc_share.name.not_blank=名称不能為空
|
||||
api_doc_share.name.length_range=名称長度必須在{min}和{max}之间
|
||||
api_doc_share.is_public.not_blank=是否公开不能為空
|
||||
api_doc_share.is_public.length_range=是否公开長度必須在{min}和{max}之间
|
||||
api_doc_share.allow_export.not_blank=允许导出不能為空
|
||||
api_doc_share.allow_export.length_range=允许导出長度必須在{min}和{max}之间
|
||||
api_doc_share.api_range.not_blank=接口范围不能為空
|
||||
api_doc_share.api_range.length_range=接口范围長度必須在{min}和{max}之间
|
||||
api_doc_share.create_user.not_blank=创建人不能為空
|
||||
api_doc_share.create_user.length_range=创建人長度必須在{min}和{max}之间
|
||||
api_doc_share.project_id.not_blank=项目ID不能為空
|
||||
api_doc_share.project_id.length_range=项目ID長度必須在{min}和{max}之间
|
@ -0,0 +1,75 @@
|
||||
package io.metersphere.api.controller.definition;
|
||||
|
||||
import com.github.pagehelper.Page;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import io.metersphere.api.domain.ApiDocShare;
|
||||
import io.metersphere.api.dto.definition.ApiDocShareDTO;
|
||||
import io.metersphere.api.dto.definition.request.ApiDocShareEditRequest;
|
||||
import io.metersphere.api.dto.definition.request.ApiDocSharePageRequest;
|
||||
import io.metersphere.api.service.definition.ApiDocShareService;
|
||||
import io.metersphere.sdk.constants.PermissionConstants;
|
||||
import io.metersphere.system.security.CheckOwner;
|
||||
import io.metersphere.system.utils.PageUtils;
|
||||
import io.metersphere.system.utils.Pager;
|
||||
import io.metersphere.system.utils.SessionUtils;
|
||||
import io.metersphere.validation.groups.Created;
|
||||
import io.metersphere.validation.groups.Updated;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author song-cc-rock
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping(value = "/api/doc/share")
|
||||
@Tag(name = "接口测试-接口管理-分享")
|
||||
public class ApiDocShareController {
|
||||
|
||||
@Resource
|
||||
private ApiDocShareService apiDocShareService;
|
||||
|
||||
@PostMapping(value = "/page")
|
||||
@Operation(summary = "接口测试-接口管理-分页获取分享列表")
|
||||
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_DOC_SHARE)
|
||||
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
|
||||
public Pager<List<ApiDocShareDTO>> page(@Validated @RequestBody ApiDocSharePageRequest request) {
|
||||
Page<Object> page = PageHelper.startPage(request.getCurrent(), request.getPageSize(),
|
||||
StringUtils.isNotBlank(request.getSortString()) ? request.getSortString() : "create_time desc");
|
||||
return PageUtils.setPageInfo(page, apiDocShareService.list(request));
|
||||
}
|
||||
|
||||
@PostMapping(value = "/add")
|
||||
@Operation(summary = "接口测试-接口管理-新增分享")
|
||||
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_DOC_SHARE)
|
||||
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
|
||||
public ApiDocShare add(@Validated({Created.class}) @RequestBody ApiDocShareEditRequest request) {
|
||||
return apiDocShareService.create(request, SessionUtils.getUserId());
|
||||
}
|
||||
|
||||
@PostMapping(value = "/update")
|
||||
@Operation(summary = "接口测试-接口管理-更新分享")
|
||||
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_DOC_SHARE)
|
||||
@CheckOwner(resourceId = "#request.getId()", resourceType = "api_doc_share")
|
||||
public ApiDocShare update(@Validated({Updated.class}) @RequestBody ApiDocShareEditRequest request) {
|
||||
return apiDocShareService.update(request);
|
||||
}
|
||||
|
||||
@GetMapping("/delete/{id}")
|
||||
@Operation(summary = "接口测试-接口管理-删除分享")
|
||||
@Parameter(name = "id", description = "分享ID", schema = @Schema(requiredMode = Schema.RequiredMode.REQUIRED))
|
||||
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_DOC_SHARE)
|
||||
@CheckOwner(resourceId = "#id", resourceType = "api_doc_share")
|
||||
public void delete(@PathVariable String id) {
|
||||
apiDocShareService.delete(id);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package io.metersphere.api.dto.definition;
|
||||
|
||||
import io.metersphere.api.domain.ApiDocShare;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = false)
|
||||
public class ApiDocShareDTO extends ApiDocShare {
|
||||
|
||||
@Schema(title = "分享是否失效")
|
||||
private Boolean invalid;
|
||||
|
||||
@Schema(title = "分享接口数量")
|
||||
private Integer apiShareNum;
|
||||
|
||||
@Schema(title = "截止日期")
|
||||
private Long deadline;
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
package io.metersphere.api.dto.definition.request;
|
||||
|
||||
import io.metersphere.validation.groups.Created;
|
||||
import io.metersphere.validation.groups.Updated;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
public class ApiDocShareEditRequest implements Serializable {
|
||||
|
||||
@Schema(title = "主键", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{api_doc_share.id.not_blank}", groups = {Updated.class})
|
||||
@Size(min = 1, max = 50, message = "{api_doc_share.id.length_range}", groups = {Created.class, Updated.class})
|
||||
private String id;
|
||||
|
||||
@Schema(description = "分享名称", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{api_doc_share.name.not_blank}")
|
||||
@Size(min = 1, max = 255, message = "{api_doc_share.name.length_range}")
|
||||
private String name;
|
||||
|
||||
@Schema(title = "接口范围;全部接口(ALL)、模块(MODULE)、路径(PATH)、标签(TAG)", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{api_doc_share.api_range.not_blank}", groups = {Created.class})
|
||||
@Size(min = 1, max = 10, message = "{api_doc_share.api_range.length_range}", groups = {Created.class, Updated.class})
|
||||
private String apiRange;
|
||||
|
||||
@Schema(title = "范围匹配符;包含(CONTAINS)、等于(EQUALS)")
|
||||
private String rangeMatchSymbol;
|
||||
|
||||
@Schema(title = "范围匹配值;eg: 选中路径范围时, 该值作为路径匹配")
|
||||
private String rangeMatchVal;
|
||||
|
||||
@Schema(title = "失效时间值")
|
||||
private Integer invalidTime;
|
||||
|
||||
@Schema(title = "失效时间单位;小时(HOUR)、天(DAY)、月(MONTH)、年(YEAR)")
|
||||
private String invalidUnit;
|
||||
|
||||
@Schema(title = "是否公开;0: 私有、1: 公开", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "{api_doc_share.is_public.not_blank}", groups = {Created.class})
|
||||
private Boolean isPublic;
|
||||
|
||||
@Schema(title = "访问密码;私有时需要访问密码")
|
||||
private String password;
|
||||
|
||||
@Schema(title = "允许导出;0: 不允许、1: 允许", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private Boolean allowExport;
|
||||
|
||||
@Schema(title = "项目ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{api_doc_share.project_id.not_blank}", groups = {Created.class})
|
||||
@Size(min = 1, max = 50, message = "{api_doc_share.project_id.length_range}", groups = {Created.class, Updated.class})
|
||||
private String projectId;
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package io.metersphere.api.dto.definition.request;
|
||||
|
||||
import io.metersphere.system.dto.sdk.BasePageRequest;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class ApiDocSharePageRequest extends BasePageRequest {
|
||||
|
||||
@Schema(description = "项目ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{api_doc_share.project_id.not_blank}")
|
||||
@Size(min = 1, max = 50, message = "{api_doc_share.project_id.length_range}")
|
||||
private String projectId;
|
||||
}
|
@ -101,4 +101,6 @@ public interface ExtApiDefinitionMapper {
|
||||
List<ApiDefinition> getListBySelectModules(@Param("projectId") String projectId, @Param("moduleIds") List<String> moduleIds, @Param("protocols") List<String> protocols);
|
||||
|
||||
List<ApiDefinition> getListBySelectIds(@Param("projectId") String projectId, @Param("ids") List<String> ids, @Param("protocols") List<String> protocols);
|
||||
|
||||
Long countByShareParam(@Param("projectId") String projectId, @Param("condition") String condition);
|
||||
}
|
||||
|
@ -749,5 +749,10 @@
|
||||
</if>
|
||||
</select>
|
||||
|
||||
|
||||
<select id="countByShareParam" resultType="java.lang.Long">
|
||||
select count(*) from api_definition where project_id = #{projectId} and deleted = 0
|
||||
<if test="condition != null and condition != ''">
|
||||
and ${condition}
|
||||
</if>
|
||||
</select>
|
||||
</mapper>
|
||||
|
@ -0,0 +1,19 @@
|
||||
package io.metersphere.api.mapper;
|
||||
|
||||
import io.metersphere.api.dto.definition.ApiDocShareDTO;
|
||||
import io.metersphere.api.dto.definition.request.ApiDocSharePageRequest;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface ExtApiDocShareMapper {
|
||||
|
||||
/**
|
||||
* 分页获取分享列表
|
||||
* @param request 请求参数
|
||||
* @return 分享列表
|
||||
*/
|
||||
List<ApiDocShareDTO> list(@Param("request")ApiDocSharePageRequest request);
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
|
||||
<mapper namespace="io.metersphere.api.mapper.ExtApiDocShareMapper">
|
||||
|
||||
<select id="list" resultType="io.metersphere.api.dto.definition.ApiDocShareDTO">
|
||||
select id, name, is_public isPublic, create_user createUser, create_time createTime,
|
||||
api_range apiRange, range_match_symbol rangeMatchSymbol, range_match_val rangeMatchVal,
|
||||
invalid_time invalidTime, invalid_unit invalidUnit, project_id projectId
|
||||
from api_doc_share
|
||||
<include refid="queryWhereCondition"/>
|
||||
</select>
|
||||
|
||||
<sql id="queryWhereCondition">
|
||||
<where>
|
||||
<if test="request.projectId != null and request.projectId != ''">
|
||||
and project_id = #{request.projectId}
|
||||
</if>
|
||||
<if test="request.keyword != null and request.keyword != ''">
|
||||
and name like concat('%', #{request.keyword},'%')
|
||||
</if>
|
||||
</where>
|
||||
</sql>
|
||||
</mapper>
|
@ -0,0 +1,139 @@
|
||||
package io.metersphere.api.service.definition;
|
||||
|
||||
import io.metersphere.api.domain.ApiDocShare;
|
||||
import io.metersphere.api.dto.definition.ApiDocShareDTO;
|
||||
import io.metersphere.api.dto.definition.request.ApiDocShareEditRequest;
|
||||
import io.metersphere.api.dto.definition.request.ApiDocSharePageRequest;
|
||||
import io.metersphere.api.mapper.ApiDocShareMapper;
|
||||
import io.metersphere.api.mapper.ExtApiDefinitionMapper;
|
||||
import io.metersphere.api.mapper.ExtApiDocShareMapper;
|
||||
import io.metersphere.sdk.constants.MsAssertionCondition;
|
||||
import io.metersphere.sdk.exception.MSException;
|
||||
import io.metersphere.sdk.util.BeanUtils;
|
||||
import io.metersphere.sdk.util.Translator;
|
||||
import io.metersphere.system.uid.IDGenerator;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public class ApiDocShareService {
|
||||
|
||||
@Resource
|
||||
private ExtApiDefinitionMapper extApiDefinitionMapper;
|
||||
@Resource
|
||||
private ApiDocShareMapper apiDocShareMapper;
|
||||
@Resource
|
||||
private ExtApiDocShareMapper extApiDocShareMapper;
|
||||
|
||||
public static final String RANGE_ALL = "ALL";
|
||||
|
||||
public List<ApiDocShareDTO> list(ApiDocSharePageRequest request) {
|
||||
List<ApiDocShareDTO> list = extApiDocShareMapper.list(request);
|
||||
return buildApiShareExtra(list);
|
||||
}
|
||||
|
||||
public ApiDocShare create(ApiDocShareEditRequest request, String currentUser) {
|
||||
ApiDocShare docShare = new ApiDocShare();
|
||||
BeanUtils.copyBean(docShare, request);
|
||||
docShare.setId(IDGenerator.nextStr());
|
||||
docShare.setCreateUser(currentUser);
|
||||
docShare.setCreateTime(System.currentTimeMillis());
|
||||
apiDocShareMapper.insert(docShare);
|
||||
return docShare;
|
||||
}
|
||||
|
||||
public ApiDocShare update(ApiDocShareEditRequest request) {
|
||||
checkExit(request.getId());
|
||||
ApiDocShare docShare = new ApiDocShare();
|
||||
BeanUtils.copyBean(docShare, request);
|
||||
apiDocShareMapper.updateByPrimaryKeySelective(docShare);
|
||||
return docShare;
|
||||
}
|
||||
|
||||
public void delete(String id) {
|
||||
checkExit(id);
|
||||
apiDocShareMapper.deleteByPrimaryKey(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建分享额外信息
|
||||
* @param docShares 分享列表
|
||||
* @return 分享列表
|
||||
*/
|
||||
public List<ApiDocShareDTO> buildApiShareExtra(List<ApiDocShareDTO> docShares) {
|
||||
docShares.forEach(docShare -> {
|
||||
docShare.setDeadline(calculateDeadline(docShare.getInvalidTime(), docShare.getInvalidUnit(), docShare.getCreateTime()));
|
||||
docShare.setInvalid(docShare.getDeadline() != null && docShare.getDeadline() < System.currentTimeMillis());
|
||||
docShare.setApiShareNum(countApiShare(docShare));
|
||||
});
|
||||
return docShares;
|
||||
}
|
||||
|
||||
/**
|
||||
* 统计接口访范围分享接口数量
|
||||
* @param docShare 接口分享
|
||||
* @return 数量
|
||||
*/
|
||||
public Integer countApiShare(ApiDocShareDTO docShare) {
|
||||
StringBuilder condition = new StringBuilder();
|
||||
if (!StringUtils.equals(docShare.getApiRange(), RANGE_ALL) && !StringUtils.isBlank(docShare.getRangeMatchVal())) {
|
||||
switch (docShare.getApiRange()) {
|
||||
case "MODULE" -> condition.append("module_id = '").append(docShare.getRangeMatchVal()).append("'");
|
||||
case "PATH" -> {
|
||||
if (StringUtils.equals(docShare.getRangeMatchSymbol(), MsAssertionCondition.EQUALS.name())) {
|
||||
condition.append("path = '").append(docShare.getRangeMatchVal()).append("'");
|
||||
} else {
|
||||
condition.append("path like \"%").append(docShare.getRangeMatchVal()).append("%\"");
|
||||
}
|
||||
}
|
||||
case "TAG" -> {
|
||||
condition.append("(1=2 ");
|
||||
String[] tags = StringUtils.split(docShare.getRangeMatchVal(), ",");
|
||||
for (String tag : tags) {
|
||||
condition.append("OR JSON_CONTAINS(tags, JSON_ARRAY(\"").append(tag).append("\"))");
|
||||
}
|
||||
condition.append(")");
|
||||
}
|
||||
default -> {
|
||||
}
|
||||
}
|
||||
}
|
||||
return extApiDefinitionMapper.countByShareParam(docShare.getProjectId(), condition.toString()).intValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算截止时间
|
||||
* @param val 时间值
|
||||
* @param unit 时间单位
|
||||
* @param stareTime 起始时间
|
||||
* @return 截止时间
|
||||
*/
|
||||
private Long calculateDeadline(Integer val, String unit, Long stareTime) {
|
||||
if (val == null) {
|
||||
return null;
|
||||
}
|
||||
return switch (unit) {
|
||||
case "HOUR" -> stareTime + val * 60 * 60 * 1000L;
|
||||
case "DAY" -> stareTime + val * 24 * 60 * 60 * 1000L;
|
||||
case "MONTH" -> stareTime + val * 30 * 24 * 60 * 60 * 1000L;
|
||||
case "YEAR" -> stareTime + val * 365 * 24 * 60 * 60 * 1000L;
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否存在
|
||||
* @param id 分享ID
|
||||
*/
|
||||
private void checkExit(String id) {
|
||||
ApiDocShare docShare = apiDocShareMapper.selectByPrimaryKey(id);
|
||||
if (docShare == null) {
|
||||
throw new MSException(Translator.get("api_doc_share.not_exist"));
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
package io.metersphere.api.controller;
|
||||
|
||||
import io.metersphere.api.domain.ApiDocShare;
|
||||
import io.metersphere.api.dto.definition.request.ApiDocShareEditRequest;
|
||||
import io.metersphere.api.dto.definition.request.ApiDocSharePageRequest;
|
||||
import io.metersphere.sdk.util.JSON;
|
||||
import io.metersphere.system.base.BaseTest;
|
||||
import io.metersphere.system.controller.handler.ResultHolder;
|
||||
import org.junit.jupiter.api.MethodOrderer;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestMethodOrder;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
||||
@AutoConfigureMockMvc
|
||||
public class ApiDocShareControllerTests extends BaseTest {
|
||||
|
||||
private static final String BASE_PATH = "/api/doc/share/";
|
||||
private final static String ADD = BASE_PATH + "add";
|
||||
private final static String UPDATE = BASE_PATH + "update";
|
||||
private final static String DELETE = BASE_PATH + "delete/";
|
||||
private final static String PAGE = BASE_PATH + "page";
|
||||
|
||||
@Order(1)
|
||||
@Test
|
||||
public void addOrUpdate() throws Exception {
|
||||
ApiDocShareEditRequest request = new ApiDocShareEditRequest();
|
||||
request.setName("share-1");
|
||||
request.setProjectId(DEFAULT_PROJECT_ID);
|
||||
request.setApiRange("ALL");
|
||||
request.setIsPublic(false);
|
||||
request.setAllowExport(false);
|
||||
MvcResult mvcResult = this.requestPostWithOk(ADD, request).andReturn();
|
||||
String returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
|
||||
ResultHolder resultHolder = JSON.parseObject(returnData, ResultHolder.class);
|
||||
ApiDocShare docShare = JSON.parseObject(JSON.toJSONString(resultHolder.getData()), ApiDocShare.class);
|
||||
request.setId(docShare.getId());
|
||||
request.setName("share-2");
|
||||
request.setApiRange("MODULE");
|
||||
request.setRangeMatchVal("module-1");
|
||||
request.setInvalidTime(1);
|
||||
request.setInvalidUnit("HOUR");
|
||||
this.requestPostWithOk(UPDATE, request);
|
||||
this.requestGetWithOk(DELETE + docShare.getId());
|
||||
// 不存在的ID
|
||||
this.requestGet(DELETE + "not-exist-id").andExpect(status().is5xxServerError());
|
||||
}
|
||||
|
||||
@Order(2)
|
||||
@Test
|
||||
public void page() throws Exception {
|
||||
ApiDocShareEditRequest request = new ApiDocShareEditRequest();
|
||||
request.setName("share-1");
|
||||
request.setProjectId(DEFAULT_PROJECT_ID);
|
||||
request.setApiRange("ALL");
|
||||
request.setIsPublic(false);
|
||||
request.setAllowExport(false);
|
||||
this.requestPostWithOk(ADD, request);
|
||||
request.setInvalidTime(1);
|
||||
request.setInvalidUnit("HOUR");
|
||||
request.setApiRange("MODULE");
|
||||
request.setRangeMatchVal("module-1");
|
||||
this.requestPostWithOk(ADD, request);
|
||||
request.setApiRange("PATH");
|
||||
request.setRangeMatchSymbol("EQUALS");
|
||||
request.setRangeMatchVal("path-1");
|
||||
this.requestPostWithOk(ADD, request);
|
||||
request.setRangeMatchSymbol("CONTAINS");
|
||||
this.requestPostWithOk(ADD, request);
|
||||
request.setApiRange("TAG");
|
||||
request.setRangeMatchVal("tag-1,tag-2");
|
||||
this.requestPostWithOk(ADD, request);
|
||||
ApiDocSharePageRequest pageRequest = new ApiDocSharePageRequest();
|
||||
pageRequest.setProjectId(DEFAULT_PROJECT_ID);
|
||||
pageRequest.setCurrent(1);
|
||||
pageRequest.setPageSize(10);
|
||||
this.requestPostWithOk(PAGE, pageRequest);
|
||||
}
|
||||
}
|
@ -147,7 +147,7 @@
|
||||
<if test="!request.useTrash">
|
||||
b.deleted = 0
|
||||
</if>
|
||||
<if test="request.projectId">
|
||||
<if test="request.projectId != null and request.projectId != ''">
|
||||
and b.project_id = #{request.projectId}
|
||||
</if>
|
||||
<if test="request.keyword != null and request.keyword != ''">
|
||||
|
@ -49,7 +49,7 @@ public enum UserViewType implements ValueEnum {
|
||||
List.of(InternalUserView.ALL_DATA, InternalUserView.MY_CREATE)),
|
||||
PLAN_API_SCENARIO_DRAWER("plan-api-scenario-drawer",
|
||||
List.of(InternalUserView.ALL_DATA, InternalUserView.MY_CREATE)),
|
||||
PLAN_BUG_DRAWER("plan-bug--drawer",
|
||||
PLAN_BUG_DRAWER("plan-bug-drawer",
|
||||
List.of(InternalUserView.ALL_DATA, InternalUserView.MY_CREATE));
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user