feat(接口测试): 增加定时同步功能

This commit is contained in:
wxg0103 2024-01-11 16:06:42 +08:00 committed by Craftsman
parent 789ab5a880
commit e7635483dc
25 changed files with 922 additions and 288 deletions

View File

@ -15,6 +15,11 @@ public class ApiDefinitionSwagger implements Serializable {
@Size(min = 1, max = 50, message = "{api_definition_swagger.id.length_range}", groups = {Created.class, Updated.class})
private String id;
@Schema(description = "定时任务名称", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{api_definition_swagger.name.not_blank}", groups = {Created.class})
@Size(min = 1, max = 255, message = "{api_definition_swagger.name.length_range}", groups = {Created.class, Updated.class})
private String name;
@Schema(description = "url地址", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{api_definition_swagger.swagger_url.not_blank}", groups = {Created.class})
@Size(min = 1, max = 500, message = "{api_definition_swagger.swagger_url.length_range}", groups = {Created.class, Updated.class})
@ -23,32 +28,35 @@ public class ApiDefinitionSwagger implements Serializable {
@Schema(description = "模块fk")
private String moduleId;
@Schema(description = "模块路径")
private String modulePath;
@Schema(description = "鉴权配置信息")
private String config;
@Schema(description = "导入模式/覆盖/不覆盖")
private Boolean mode;
private Boolean coverData;
@Schema(description = "项目fk")
@Schema(description = "是否覆盖模块")
private Boolean coverModule;
@Schema(description = "项目fk", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{api_definition_swagger.project_id.not_blank}", groups = {Created.class})
@Size(min = 1, max = 50, message = "{api_definition_swagger.project_id.length_range}", groups = {Created.class, Updated.class})
private String projectId;
@Schema(description = "导入版本")
private String versionId;
@Schema(description = "鉴权配置信息")
private byte[] config;
private static final long serialVersionUID = 1L;
public enum Column {
id("id", "id", "VARCHAR", false),
name("name", "name", "VARCHAR", true),
swaggerUrl("swagger_url", "swaggerUrl", "VARCHAR", false),
moduleId("module_id", "moduleId", "VARCHAR", false),
modulePath("module_path", "modulePath", "VARCHAR", false),
mode("mode", "mode", "BIT", true),
config("config", "config", "VARCHAR", false),
coverData("cover_data", "coverData", "BIT", false),
coverModule("cover_module", "coverModule", "BIT", false),
projectId("project_id", "projectId", "VARCHAR", false),
versionId("version_id", "versionId", "VARCHAR", false),
config("config", "config", "LONGVARBINARY", false);
versionId("version_id", "versionId", "VARCHAR", false);
private static final String BEGINNING_DELIMITER = "`";

View File

@ -174,6 +174,76 @@ public class ApiDefinitionSwaggerExample {
return (Criteria) this;
}
public Criteria andNameIsNull() {
addCriterion("`name` is null");
return (Criteria) this;
}
public Criteria andNameIsNotNull() {
addCriterion("`name` is not null");
return (Criteria) this;
}
public Criteria andNameEqualTo(String value) {
addCriterion("`name` =", value, "name");
return (Criteria) this;
}
public Criteria andNameNotEqualTo(String value) {
addCriterion("`name` <>", value, "name");
return (Criteria) this;
}
public Criteria andNameGreaterThan(String value) {
addCriterion("`name` >", value, "name");
return (Criteria) this;
}
public Criteria andNameGreaterThanOrEqualTo(String value) {
addCriterion("`name` >=", value, "name");
return (Criteria) this;
}
public Criteria andNameLessThan(String value) {
addCriterion("`name` <", value, "name");
return (Criteria) this;
}
public Criteria andNameLessThanOrEqualTo(String value) {
addCriterion("`name` <=", value, "name");
return (Criteria) this;
}
public Criteria andNameLike(String value) {
addCriterion("`name` like", value, "name");
return (Criteria) this;
}
public Criteria andNameNotLike(String value) {
addCriterion("`name` not like", value, "name");
return (Criteria) this;
}
public Criteria andNameIn(List<String> values) {
addCriterion("`name` in", values, "name");
return (Criteria) this;
}
public Criteria andNameNotIn(List<String> values) {
addCriterion("`name` not in", values, "name");
return (Criteria) this;
}
public Criteria andNameBetween(String value1, String value2) {
addCriterion("`name` between", value1, value2, "name");
return (Criteria) this;
}
public Criteria andNameNotBetween(String value1, String value2) {
addCriterion("`name` not between", value1, value2, "name");
return (Criteria) this;
}
public Criteria andSwaggerUrlIsNull() {
addCriterion("swagger_url is null");
return (Criteria) this;
@ -314,133 +384,193 @@ public class ApiDefinitionSwaggerExample {
return (Criteria) this;
}
public Criteria andModulePathIsNull() {
addCriterion("module_path is null");
public Criteria andConfigIsNull() {
addCriterion("config is null");
return (Criteria) this;
}
public Criteria andModulePathIsNotNull() {
addCriterion("module_path is not null");
public Criteria andConfigIsNotNull() {
addCriterion("config is not null");
return (Criteria) this;
}
public Criteria andModulePathEqualTo(String value) {
addCriterion("module_path =", value, "modulePath");
public Criteria andConfigEqualTo(String value) {
addCriterion("config =", value, "config");
return (Criteria) this;
}
public Criteria andModulePathNotEqualTo(String value) {
addCriterion("module_path <>", value, "modulePath");
public Criteria andConfigNotEqualTo(String value) {
addCriterion("config <>", value, "config");
return (Criteria) this;
}
public Criteria andModulePathGreaterThan(String value) {
addCriterion("module_path >", value, "modulePath");
public Criteria andConfigGreaterThan(String value) {
addCriterion("config >", value, "config");
return (Criteria) this;
}
public Criteria andModulePathGreaterThanOrEqualTo(String value) {
addCriterion("module_path >=", value, "modulePath");
public Criteria andConfigGreaterThanOrEqualTo(String value) {
addCriterion("config >=", value, "config");
return (Criteria) this;
}
public Criteria andModulePathLessThan(String value) {
addCriterion("module_path <", value, "modulePath");
public Criteria andConfigLessThan(String value) {
addCriterion("config <", value, "config");
return (Criteria) this;
}
public Criteria andModulePathLessThanOrEqualTo(String value) {
addCriterion("module_path <=", value, "modulePath");
public Criteria andConfigLessThanOrEqualTo(String value) {
addCriterion("config <=", value, "config");
return (Criteria) this;
}
public Criteria andModulePathLike(String value) {
addCriterion("module_path like", value, "modulePath");
public Criteria andConfigLike(String value) {
addCriterion("config like", value, "config");
return (Criteria) this;
}
public Criteria andModulePathNotLike(String value) {
addCriterion("module_path not like", value, "modulePath");
public Criteria andConfigNotLike(String value) {
addCriterion("config not like", value, "config");
return (Criteria) this;
}
public Criteria andModulePathIn(List<String> values) {
addCriterion("module_path in", values, "modulePath");
public Criteria andConfigIn(List<String> values) {
addCriterion("config in", values, "config");
return (Criteria) this;
}
public Criteria andModulePathNotIn(List<String> values) {
addCriterion("module_path not in", values, "modulePath");
public Criteria andConfigNotIn(List<String> values) {
addCriterion("config not in", values, "config");
return (Criteria) this;
}
public Criteria andModulePathBetween(String value1, String value2) {
addCriterion("module_path between", value1, value2, "modulePath");
public Criteria andConfigBetween(String value1, String value2) {
addCriterion("config between", value1, value2, "config");
return (Criteria) this;
}
public Criteria andModulePathNotBetween(String value1, String value2) {
addCriterion("module_path not between", value1, value2, "modulePath");
public Criteria andConfigNotBetween(String value1, String value2) {
addCriterion("config not between", value1, value2, "config");
return (Criteria) this;
}
public Criteria andModeIsNull() {
addCriterion("`mode` is null");
public Criteria andCoverDataIsNull() {
addCriterion("cover_data is null");
return (Criteria) this;
}
public Criteria andModeIsNotNull() {
addCriterion("`mode` is not null");
public Criteria andCoverDataIsNotNull() {
addCriterion("cover_data is not null");
return (Criteria) this;
}
public Criteria andModeEqualTo(Boolean value) {
addCriterion("`mode` =", value, "mode");
public Criteria andCoverDataEqualTo(Boolean value) {
addCriterion("cover_data =", value, "coverData");
return (Criteria) this;
}
public Criteria andModeNotEqualTo(Boolean value) {
addCriterion("`mode` <>", value, "mode");
public Criteria andCoverDataNotEqualTo(Boolean value) {
addCriterion("cover_data <>", value, "coverData");
return (Criteria) this;
}
public Criteria andModeGreaterThan(Boolean value) {
addCriterion("`mode` >", value, "mode");
public Criteria andCoverDataGreaterThan(Boolean value) {
addCriterion("cover_data >", value, "coverData");
return (Criteria) this;
}
public Criteria andModeGreaterThanOrEqualTo(Boolean value) {
addCriterion("`mode` >=", value, "mode");
public Criteria andCoverDataGreaterThanOrEqualTo(Boolean value) {
addCriterion("cover_data >=", value, "coverData");
return (Criteria) this;
}
public Criteria andModeLessThan(Boolean value) {
addCriterion("`mode` <", value, "mode");
public Criteria andCoverDataLessThan(Boolean value) {
addCriterion("cover_data <", value, "coverData");
return (Criteria) this;
}
public Criteria andModeLessThanOrEqualTo(Boolean value) {
addCriterion("`mode` <=", value, "mode");
public Criteria andCoverDataLessThanOrEqualTo(Boolean value) {
addCriterion("cover_data <=", value, "coverData");
return (Criteria) this;
}
public Criteria andModeIn(List<Boolean> values) {
addCriterion("`mode` in", values, "mode");
public Criteria andCoverDataIn(List<Boolean> values) {
addCriterion("cover_data in", values, "coverData");
return (Criteria) this;
}
public Criteria andModeNotIn(List<Boolean> values) {
addCriterion("`mode` not in", values, "mode");
public Criteria andCoverDataNotIn(List<Boolean> values) {
addCriterion("cover_data not in", values, "coverData");
return (Criteria) this;
}
public Criteria andModeBetween(Boolean value1, Boolean value2) {
addCriterion("`mode` between", value1, value2, "mode");
public Criteria andCoverDataBetween(Boolean value1, Boolean value2) {
addCriterion("cover_data between", value1, value2, "coverData");
return (Criteria) this;
}
public Criteria andModeNotBetween(Boolean value1, Boolean value2) {
addCriterion("`mode` not between", value1, value2, "mode");
public Criteria andCoverDataNotBetween(Boolean value1, Boolean value2) {
addCriterion("cover_data not between", value1, value2, "coverData");
return (Criteria) this;
}
public Criteria andCoverModuleIsNull() {
addCriterion("cover_module is null");
return (Criteria) this;
}
public Criteria andCoverModuleIsNotNull() {
addCriterion("cover_module is not null");
return (Criteria) this;
}
public Criteria andCoverModuleEqualTo(Boolean value) {
addCriterion("cover_module =", value, "coverModule");
return (Criteria) this;
}
public Criteria andCoverModuleNotEqualTo(Boolean value) {
addCriterion("cover_module <>", value, "coverModule");
return (Criteria) this;
}
public Criteria andCoverModuleGreaterThan(Boolean value) {
addCriterion("cover_module >", value, "coverModule");
return (Criteria) this;
}
public Criteria andCoverModuleGreaterThanOrEqualTo(Boolean value) {
addCriterion("cover_module >=", value, "coverModule");
return (Criteria) this;
}
public Criteria andCoverModuleLessThan(Boolean value) {
addCriterion("cover_module <", value, "coverModule");
return (Criteria) this;
}
public Criteria andCoverModuleLessThanOrEqualTo(Boolean value) {
addCriterion("cover_module <=", value, "coverModule");
return (Criteria) this;
}
public Criteria andCoverModuleIn(List<Boolean> values) {
addCriterion("cover_module in", values, "coverModule");
return (Criteria) this;
}
public Criteria andCoverModuleNotIn(List<Boolean> values) {
addCriterion("cover_module not in", values, "coverModule");
return (Criteria) this;
}
public Criteria andCoverModuleBetween(Boolean value1, Boolean value2) {
addCriterion("cover_module between", value1, value2, "coverModule");
return (Criteria) this;
}
public Criteria andCoverModuleNotBetween(Boolean value1, Boolean value2) {
addCriterion("cover_module not between", value1, value2, "coverModule");
return (Criteria) this;
}

View File

@ -16,22 +16,16 @@ public interface ApiDefinitionSwaggerMapper {
int insertSelective(ApiDefinitionSwagger record);
List<ApiDefinitionSwagger> selectByExampleWithBLOBs(ApiDefinitionSwaggerExample example);
List<ApiDefinitionSwagger> selectByExample(ApiDefinitionSwaggerExample example);
ApiDefinitionSwagger selectByPrimaryKey(String id);
int updateByExampleSelective(@Param("record") ApiDefinitionSwagger record, @Param("example") ApiDefinitionSwaggerExample example);
int updateByExampleWithBLOBs(@Param("record") ApiDefinitionSwagger record, @Param("example") ApiDefinitionSwaggerExample example);
int updateByExample(@Param("record") ApiDefinitionSwagger record, @Param("example") ApiDefinitionSwaggerExample example);
int updateByPrimaryKeySelective(ApiDefinitionSwagger record);
int updateByPrimaryKeyWithBLOBs(ApiDefinitionSwagger record);
int updateByPrimaryKey(ApiDefinitionSwagger record);
int batchInsert(@Param("list") List<ApiDefinitionSwagger> list);

View File

@ -3,16 +3,15 @@
<mapper namespace="io.metersphere.api.mapper.ApiDefinitionSwaggerMapper">
<resultMap id="BaseResultMap" type="io.metersphere.api.domain.ApiDefinitionSwagger">
<id column="id" jdbcType="VARCHAR" property="id" />
<result column="name" jdbcType="VARCHAR" property="name" />
<result column="swagger_url" jdbcType="VARCHAR" property="swaggerUrl" />
<result column="module_id" jdbcType="VARCHAR" property="moduleId" />
<result column="module_path" jdbcType="VARCHAR" property="modulePath" />
<result column="mode" jdbcType="BIT" property="mode" />
<result column="config" jdbcType="VARCHAR" property="config" />
<result column="cover_data" jdbcType="BIT" property="coverData" />
<result column="cover_module" jdbcType="BIT" property="coverModule" />
<result column="project_id" jdbcType="VARCHAR" property="projectId" />
<result column="version_id" jdbcType="VARCHAR" property="versionId" />
</resultMap>
<resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="io.metersphere.api.domain.ApiDefinitionSwagger">
<result column="config" jdbcType="LONGVARBINARY" property="config" />
</resultMap>
<sql id="Example_Where_Clause">
<where>
<foreach collection="oredCriteria" item="criteria" separator="or">
@ -72,27 +71,9 @@
</where>
</sql>
<sql id="Base_Column_List">
id, swagger_url, module_id, module_path, `mode`, project_id, version_id
id, `name`, swagger_url, module_id, config, cover_data, cover_module, project_id,
version_id
</sql>
<sql id="Blob_Column_List">
config
</sql>
<select id="selectByExampleWithBLOBs" parameterType="io.metersphere.api.domain.ApiDefinitionSwaggerExample" resultMap="ResultMapWithBLOBs">
select
<if test="distinct">
distinct
</if>
<include refid="Base_Column_List" />
,
<include refid="Blob_Column_List" />
from api_definition_swagger
<if test="_parameter != null">
<include refid="Example_Where_Clause" />
</if>
<if test="orderByClause != null">
order by ${orderByClause}
</if>
</select>
<select id="selectByExample" parameterType="io.metersphere.api.domain.ApiDefinitionSwaggerExample" resultMap="BaseResultMap">
select
<if test="distinct">
@ -107,11 +88,9 @@
order by ${orderByClause}
</if>
</select>
<select id="selectByPrimaryKey" parameterType="java.lang.String" resultMap="ResultMapWithBLOBs">
<select id="selectByPrimaryKey" parameterType="java.lang.String" resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
,
<include refid="Blob_Column_List" />
from api_definition_swagger
where id = #{id,jdbcType=VARCHAR}
</select>
@ -126,12 +105,14 @@
</if>
</delete>
<insert id="insert" parameterType="io.metersphere.api.domain.ApiDefinitionSwagger">
insert into api_definition_swagger (id, swagger_url, module_id,
module_path, `mode`, project_id,
version_id, config)
values (#{id,jdbcType=VARCHAR}, #{swaggerUrl,jdbcType=VARCHAR}, #{moduleId,jdbcType=VARCHAR},
#{modulePath,jdbcType=VARCHAR}, #{mode,jdbcType=BIT}, #{projectId,jdbcType=VARCHAR},
#{versionId,jdbcType=VARCHAR}, #{config,jdbcType=LONGVARBINARY})
insert into api_definition_swagger (id, `name`, swagger_url,
module_id, config, cover_data,
cover_module, project_id, version_id
)
values (#{id,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{swaggerUrl,jdbcType=VARCHAR},
#{moduleId,jdbcType=VARCHAR}, #{config,jdbcType=VARCHAR}, #{coverData,jdbcType=BIT},
#{coverModule,jdbcType=BIT}, #{projectId,jdbcType=VARCHAR}, #{versionId,jdbcType=VARCHAR}
)
</insert>
<insert id="insertSelective" parameterType="io.metersphere.api.domain.ApiDefinitionSwagger">
insert into api_definition_swagger
@ -139,17 +120,23 @@
<if test="id != null">
id,
</if>
<if test="name != null">
`name`,
</if>
<if test="swaggerUrl != null">
swagger_url,
</if>
<if test="moduleId != null">
module_id,
</if>
<if test="modulePath != null">
module_path,
<if test="config != null">
config,
</if>
<if test="mode != null">
`mode`,
<if test="coverData != null">
cover_data,
</if>
<if test="coverModule != null">
cover_module,
</if>
<if test="projectId != null">
project_id,
@ -157,25 +144,28 @@
<if test="versionId != null">
version_id,
</if>
<if test="config != null">
config,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="id != null">
#{id,jdbcType=VARCHAR},
</if>
<if test="name != null">
#{name,jdbcType=VARCHAR},
</if>
<if test="swaggerUrl != null">
#{swaggerUrl,jdbcType=VARCHAR},
</if>
<if test="moduleId != null">
#{moduleId,jdbcType=VARCHAR},
</if>
<if test="modulePath != null">
#{modulePath,jdbcType=VARCHAR},
<if test="config != null">
#{config,jdbcType=VARCHAR},
</if>
<if test="mode != null">
#{mode,jdbcType=BIT},
<if test="coverData != null">
#{coverData,jdbcType=BIT},
</if>
<if test="coverModule != null">
#{coverModule,jdbcType=BIT},
</if>
<if test="projectId != null">
#{projectId,jdbcType=VARCHAR},
@ -183,9 +173,6 @@
<if test="versionId != null">
#{versionId,jdbcType=VARCHAR},
</if>
<if test="config != null">
#{config,jdbcType=LONGVARBINARY},
</if>
</trim>
</insert>
<select id="countByExample" parameterType="io.metersphere.api.domain.ApiDefinitionSwaggerExample" resultType="java.lang.Long">
@ -200,17 +187,23 @@
<if test="record.id != null">
id = #{record.id,jdbcType=VARCHAR},
</if>
<if test="record.name != null">
`name` = #{record.name,jdbcType=VARCHAR},
</if>
<if test="record.swaggerUrl != null">
swagger_url = #{record.swaggerUrl,jdbcType=VARCHAR},
</if>
<if test="record.moduleId != null">
module_id = #{record.moduleId,jdbcType=VARCHAR},
</if>
<if test="record.modulePath != null">
module_path = #{record.modulePath,jdbcType=VARCHAR},
<if test="record.config != null">
config = #{record.config,jdbcType=VARCHAR},
</if>
<if test="record.mode != null">
`mode` = #{record.mode,jdbcType=BIT},
<if test="record.coverData != null">
cover_data = #{record.coverData,jdbcType=BIT},
</if>
<if test="record.coverModule != null">
cover_module = #{record.coverModule,jdbcType=BIT},
</if>
<if test="record.projectId != null">
project_id = #{record.projectId,jdbcType=VARCHAR},
@ -218,35 +211,20 @@
<if test="record.versionId != null">
version_id = #{record.versionId,jdbcType=VARCHAR},
</if>
<if test="record.config != null">
config = #{record.config,jdbcType=LONGVARBINARY},
</if>
</set>
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
</if>
</update>
<update id="updateByExampleWithBLOBs" parameterType="map">
update api_definition_swagger
set id = #{record.id,jdbcType=VARCHAR},
swagger_url = #{record.swaggerUrl,jdbcType=VARCHAR},
module_id = #{record.moduleId,jdbcType=VARCHAR},
module_path = #{record.modulePath,jdbcType=VARCHAR},
`mode` = #{record.mode,jdbcType=BIT},
project_id = #{record.projectId,jdbcType=VARCHAR},
version_id = #{record.versionId,jdbcType=VARCHAR},
config = #{record.config,jdbcType=LONGVARBINARY}
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
</if>
</update>
<update id="updateByExample" parameterType="map">
update api_definition_swagger
set id = #{record.id,jdbcType=VARCHAR},
`name` = #{record.name,jdbcType=VARCHAR},
swagger_url = #{record.swaggerUrl,jdbcType=VARCHAR},
module_id = #{record.moduleId,jdbcType=VARCHAR},
module_path = #{record.modulePath,jdbcType=VARCHAR},
`mode` = #{record.mode,jdbcType=BIT},
config = #{record.config,jdbcType=VARCHAR},
cover_data = #{record.coverData,jdbcType=BIT},
cover_module = #{record.coverModule,jdbcType=BIT},
project_id = #{record.projectId,jdbcType=VARCHAR},
version_id = #{record.versionId,jdbcType=VARCHAR}
<if test="_parameter != null">
@ -256,17 +234,23 @@
<update id="updateByPrimaryKeySelective" parameterType="io.metersphere.api.domain.ApiDefinitionSwagger">
update api_definition_swagger
<set>
<if test="name != null">
`name` = #{name,jdbcType=VARCHAR},
</if>
<if test="swaggerUrl != null">
swagger_url = #{swaggerUrl,jdbcType=VARCHAR},
</if>
<if test="moduleId != null">
module_id = #{moduleId,jdbcType=VARCHAR},
</if>
<if test="modulePath != null">
module_path = #{modulePath,jdbcType=VARCHAR},
<if test="config != null">
config = #{config,jdbcType=VARCHAR},
</if>
<if test="mode != null">
`mode` = #{mode,jdbcType=BIT},
<if test="coverData != null">
cover_data = #{coverData,jdbcType=BIT},
</if>
<if test="coverModule != null">
cover_module = #{coverModule,jdbcType=BIT},
</if>
<if test="projectId != null">
project_id = #{projectId,jdbcType=VARCHAR},
@ -274,41 +258,31 @@
<if test="versionId != null">
version_id = #{versionId,jdbcType=VARCHAR},
</if>
<if test="config != null">
config = #{config,jdbcType=LONGVARBINARY},
</if>
</set>
where id = #{id,jdbcType=VARCHAR}
</update>
<update id="updateByPrimaryKeyWithBLOBs" parameterType="io.metersphere.api.domain.ApiDefinitionSwagger">
update api_definition_swagger
set swagger_url = #{swaggerUrl,jdbcType=VARCHAR},
module_id = #{moduleId,jdbcType=VARCHAR},
module_path = #{modulePath,jdbcType=VARCHAR},
`mode` = #{mode,jdbcType=BIT},
project_id = #{projectId,jdbcType=VARCHAR},
version_id = #{versionId,jdbcType=VARCHAR},
config = #{config,jdbcType=LONGVARBINARY}
where id = #{id,jdbcType=VARCHAR}
</update>
<update id="updateByPrimaryKey" parameterType="io.metersphere.api.domain.ApiDefinitionSwagger">
update api_definition_swagger
set swagger_url = #{swaggerUrl,jdbcType=VARCHAR},
set `name` = #{name,jdbcType=VARCHAR},
swagger_url = #{swaggerUrl,jdbcType=VARCHAR},
module_id = #{moduleId,jdbcType=VARCHAR},
module_path = #{modulePath,jdbcType=VARCHAR},
`mode` = #{mode,jdbcType=BIT},
config = #{config,jdbcType=VARCHAR},
cover_data = #{coverData,jdbcType=BIT},
cover_module = #{coverModule,jdbcType=BIT},
project_id = #{projectId,jdbcType=VARCHAR},
version_id = #{versionId,jdbcType=VARCHAR}
where id = #{id,jdbcType=VARCHAR}
</update>
<insert id="batchInsert" parameterType="map">
insert into api_definition_swagger
(id, swagger_url, module_id, module_path, `mode`, project_id, version_id, config)
(id, `name`, swagger_url, module_id, config, cover_data, cover_module, project_id,
version_id)
values
<foreach collection="list" item="item" separator=",">
(#{item.id,jdbcType=VARCHAR}, #{item.swaggerUrl,jdbcType=VARCHAR}, #{item.moduleId,jdbcType=VARCHAR},
#{item.modulePath,jdbcType=VARCHAR}, #{item.mode,jdbcType=BIT}, #{item.projectId,jdbcType=VARCHAR},
#{item.versionId,jdbcType=VARCHAR}, #{item.config,jdbcType=LONGVARBINARY})
(#{item.id,jdbcType=VARCHAR}, #{item.name,jdbcType=VARCHAR}, #{item.swaggerUrl,jdbcType=VARCHAR},
#{item.moduleId,jdbcType=VARCHAR}, #{item.config,jdbcType=VARCHAR}, #{item.coverData,jdbcType=BIT},
#{item.coverModule,jdbcType=BIT}, #{item.projectId,jdbcType=VARCHAR}, #{item.versionId,jdbcType=VARCHAR}
)
</foreach>
</insert>
<insert id="batchInsertSelective" parameterType="map">
@ -324,17 +298,23 @@
<if test="'id'.toString() == column.value">
#{item.id,jdbcType=VARCHAR}
</if>
<if test="'name'.toString() == column.value">
#{item.name,jdbcType=VARCHAR}
</if>
<if test="'swagger_url'.toString() == column.value">
#{item.swaggerUrl,jdbcType=VARCHAR}
</if>
<if test="'module_id'.toString() == column.value">
#{item.moduleId,jdbcType=VARCHAR}
</if>
<if test="'module_path'.toString() == column.value">
#{item.modulePath,jdbcType=VARCHAR}
<if test="'config'.toString() == column.value">
#{item.config,jdbcType=VARCHAR}
</if>
<if test="'mode'.toString() == column.value">
#{item.mode,jdbcType=BIT}
<if test="'cover_data'.toString() == column.value">
#{item.coverData,jdbcType=BIT}
</if>
<if test="'cover_module'.toString() == column.value">
#{item.coverModule,jdbcType=BIT}
</if>
<if test="'project_id'.toString() == column.value">
#{item.projectId,jdbcType=VARCHAR}
@ -342,9 +322,6 @@
<if test="'version_id'.toString() == column.value">
#{item.versionId,jdbcType=VARCHAR}
</if>
<if test="'config'.toString() == column.value">
#{item.config,jdbcType=LONGVARBINARY}
</if>
</foreach>
)
</foreach>

View File

@ -434,15 +434,16 @@ CREATE TABLE IF NOT EXISTS api_definition_mock_config(
COMMENT = 'mock期望值配置';
CREATE TABLE IF NOT EXISTS api_definition_swagger(
`id` VARCHAR(50) NOT NULL COMMENT '主键' ,
`swagger_url` VARCHAR(500) NOT NULL COMMENT 'url地址' ,
`module_id` VARCHAR(50) COMMENT '模块fk' ,
`module_path` VARCHAR(1000) COMMENT '模块路径' ,
`config` BLOB COMMENT '鉴权配置信息' ,
`mode` BIT(1) DEFAULT 0 COMMENT '导入模式/覆盖/不覆盖' ,
`project_id` VARCHAR(50) COMMENT '项目fk' ,
`version_id` VARCHAR(50) COMMENT '导入版本' ,
PRIMARY KEY (id)
`id` VARCHAR(50) NOT NULL COMMENT '主键' ,
`name` VARCHAR(255) NOT NULL COMMENT '定时任务名称' ,
`swagger_url` VARCHAR(500) NOT NULL COMMENT 'url地址' ,
`module_id` VARCHAR(50) COMMENT '模块fk' ,
`config` VARCHAR(255) COMMENT '鉴权配置信息' ,
`cover_data` BIT(1) DEFAULT 0 COMMENT '导入模式/覆盖/不覆盖' ,
`cover_module` BIT(1) DEFAULT 0 COMMENT '是否覆盖模块' ,
`project_id` VARCHAR(50) NOT NULL COMMENT '项目fk' ,
`version_id` VARCHAR(50) COMMENT '导入版本' ,
PRIMARY KEY (id)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci COMMENT = '定时同步配置';

View File

@ -305,3 +305,5 @@ api_definition_mock_exist=接口 MOCK 已存在
execute_resource_pool_not_config_error=请在【项目管理-应用管理-接口测试】中选择资源池
resource_pool_execute_error=资源池调用失败
api_swagger_url_error=Swagger url无法连通
schedule_not_exist=定时任务不存在

View File

@ -308,4 +308,5 @@ api_definition_exist=The API already exists
api_definition_mock_exist=The API MOCK already exists
execute_resource_pool_not_config_error=Select a resource pool in 【Project Management - Application Management - Interface Testing】
resource_pool_execute_error=The resource pool call failed
api_swagger_url_error=Swagger url unable to connect
api_swagger_url_error=Swagger url unable to connect
schedule_not_exist=The scheduled task does not exist

View File

@ -309,3 +309,4 @@ api_definition_mock_exist=接口 MOCK 已存在
execute_resource_pool_not_config_error=请在【项目管理-应用管理-接口测试】中选择资源池
resource_pool_execute_error=资源池调用失败
api_swagger_url_error=Swagger url无法连通
schedule_not_exist=定时任务不存在

View File

@ -309,3 +309,4 @@ api_definition_mock_exist=接口 MOCK 已存在
execute_resource_pool_not_config_error=請在【項目管理-應用管理-接口測試】中選擇資源池
resource_pool_execute_error=資源池調用失敗
api_swagger_url_error=Swagger url無法調解
schedule_not_exist=定時任務不存在

View File

@ -202,7 +202,7 @@ public class ApiDefinitionController {
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_IMPORT)
@Operation(summary = "接口测试-接口管理-导入接口定义")
public ApiDefinitionImport testCaseImport(@RequestPart(value = "file", required = false) MultipartFile file, @RequestPart("request") ImportRequest request) {
return apiDefinitionService.apiTestImport(file, request);
return apiDefinitionService.apiTestImport(file, request, SessionUtils.getUserId(), SessionUtils.getCurrentProjectId());
}
@PostMapping("/operation-history")

View File

@ -0,0 +1,68 @@
package io.metersphere.api.controller.definition;
import io.metersphere.api.dto.definition.ApiScheduleDTO;
import io.metersphere.api.dto.definition.SwaggerUrlCheck;
import io.metersphere.api.dto.definition.importdto.ApiScheduleRequest;
import io.metersphere.api.service.definition.ApiDefinitionScheduleService;
import io.metersphere.sdk.constants.PermissionConstants;
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.tags.Tag;
import jakarta.annotation.Resource;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping(value = "/api/definition/schedule")
@Tag(name = "接口测试-接口管理-接口定义-定时同步")
public class ApiDefinitionScheduleController {
@Resource
private ApiDefinitionScheduleService apiDefinitionScheduleService;
@PostMapping(value = "/add")
@Operation(summary = "接口测试-接口管理-定时同步-创建")
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_IMPORT)
public void createSchedule(@RequestBody @Validated({Created.class}) ApiScheduleRequest request) {
apiDefinitionScheduleService.createSchedule(request, SessionUtils.getUserId());
}
@PostMapping(value = "/update")
@Operation(summary = "接口测试-接口管理-定时同步-更新")
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_IMPORT)
public void updateSchedule(@RequestBody @Validated({Updated.class}) ApiScheduleRequest request) {
apiDefinitionScheduleService.updateSchedule(request, SessionUtils.getUserId());
}
@PostMapping(value = "/check")
@Operation(summary = "接口测试-接口管理-定时同步-校验url是否存在")
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_IMPORT)
public Boolean checkSchedule(@RequestBody SwaggerUrlCheck swaggerUrlCheck) {
return apiDefinitionScheduleService.checkSwaggerUrl(swaggerUrlCheck.getProjectId(), swaggerUrlCheck.getSwaggerUrl());
}
@GetMapping(value = "/switch/{id}")
@Operation(summary = "接口测试-接口管理-定时同步-开启/关闭")
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_IMPORT)
public void updateScheduleEnable(@PathVariable String id) {
apiDefinitionScheduleService.switchSchedule(id);
}
@GetMapping("/delete/{id}")
@Operation(summary = "接口测试-接口管理-定时同步-删除")
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_IMPORT)
public void deleteSchedule(@PathVariable String id) {
apiDefinitionScheduleService.deleteSchedule(id);
}
@GetMapping(value = "/get/{id}")
@Operation(summary = "接口测试-接口管理-定时同步-查询")
public ApiScheduleDTO getResourceId(@PathVariable String id) {
return apiDefinitionScheduleService.getSchedule(id);
}
}

View File

@ -0,0 +1,36 @@
package io.metersphere.api.dto.definition;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
public class ApiScheduleDTO {
@Schema(description = "id")
private String id;
@Schema(description = "项目id", requiredMode = Schema.RequiredMode.REQUIRED)
private String projectId;
@Schema(description = "定时任务名称", requiredMode = Schema.RequiredMode.REQUIRED)
private String name;
@Schema(description = "模块ID")
private String moduleId;
@Schema(description = "swagger地址", requiredMode = Schema.RequiredMode.REQUIRED)
private String swaggerUrl;
@Schema(description = "是否覆盖模块")
private Boolean coverModule = false;
@Schema(description = "是否同步导入用例")
private Boolean syncCase = false;
@Schema(description = "是否覆盖数据")
private Boolean coverData = false;
@Schema(description = "是否开启Basic Auth认证")
private boolean authSwitch = false;
@Schema(description = "Basic Auth认证用户名")
private String authUsername;
@Schema(description = "Basic Auth认证密码")
private String authPassword;
@Schema(description = "是否开启")
private Boolean enable = true;
@Schema(description = "cron 表达式", requiredMode = Schema.RequiredMode.REQUIRED)
private String value;
}

View File

@ -0,0 +1,10 @@
package io.metersphere.api.dto.definition;
import lombok.Data;
@Data
public class SwaggerBasicAuth {
private Boolean authSwitch = false;
private String userName;
private String password;
}

View File

@ -0,0 +1,12 @@
package io.metersphere.api.dto.definition;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
public class SwaggerUrlCheck {
@Schema(description = "项目id", requiredMode = Schema.RequiredMode.REQUIRED)
private String projectId;
@Schema(description = "swagger地址", requiredMode = Schema.RequiredMode.REQUIRED)
private String swaggerUrl;
}

View File

@ -0,0 +1,54 @@
package io.metersphere.api.dto.definition.importdto;
import io.metersphere.sdk.constants.ModuleConstants;
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.Size;
import lombok.Data;
@Data
public class ApiScheduleRequest {
@Schema(description = "id")
@NotBlank(message = "id不能为空", groups = {Updated.class})
private String id;
@Schema(description = "项目id", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "项目id不能为空", groups = {Created.class, Updated.class})
private String projectId;
@Schema(description = "定时任务名称", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "定时任务名称不能为空", groups = {Created.class, Updated.class})
private String name;
@Schema(description = "模块ID")
private String moduleId;
@Schema(description = "swagger地址", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "swagger地址不能为空", groups = {Created.class, Updated.class})
private String swaggerUrl;
private String taskId;
@Schema(description = "是否覆盖模块")
private Boolean coverModule = false;
@Schema(description = "是否同步导入用例")
private Boolean syncCase = false;
@Schema(description = "是否覆盖数据")
private Boolean coverData = false;
@Schema(description = "协议")
private String protocol = ModuleConstants.NODE_PROTOCOL_HTTP;
@Schema(description = "是否开启Basic Auth认证")
private boolean authSwitch = false;
@Schema(description = "Basic Auth认证用户名")
private String authUsername;
@Schema(description = "Basic Auth认证密码")
private String authPassword;
@Schema(description = "用户id")
private String userId;
@Schema(description = "是否开启")
private Boolean enable = true;
@Schema(description = "cron 表达式", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{schedule.value.not_blank}", groups = {Created.class})
@Size(min = 1, max = 255, message = "{schedule.value.length_range}", groups = {Created.class, Updated.class})
private String value;
@Schema(description = "配置信息")
private String config;
}

View File

@ -1,40 +0,0 @@
package io.metersphere.api.dto.definition.importdto;
import io.metersphere.api.dto.request.http.Header;
import io.metersphere.api.dto.request.http.QueryParam;
import io.metersphere.api.dto.request.http.auth.HTTPAuth;
import io.metersphere.system.domain.Schedule;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
@Data
public class ScheduleRequest extends Schedule {
//定时任务来源 测试计划/测试场景
private String scheduleFrom;
private String projectId;
private String moduleId;
private String modulePath;
private String modeId;
private String swaggerUrl;
private String taskId;
// 鉴权相关
@Schema(description = "swagger的请求头参数")
private List<Header> headers;
@Schema(description = "swagger的请求参数")
private List<QueryParam> arguments;
@Schema(description = "swagger的认证参数")
private HTTPAuth authManager;
private Boolean coverModule = false;
}

View File

@ -1,18 +1,16 @@
package io.metersphere.api.dto.request;
import io.metersphere.api.dto.request.http.Header;
import io.metersphere.api.dto.request.http.QueryParam;
import io.metersphere.api.dto.request.http.auth.HTTPAuth;
import io.metersphere.sdk.constants.ModuleConstants;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
@Data
public class ImportRequest {
private String id;
private String name;
@Schema(description = "导入的模块id")
private String moduleId;
@Schema(description = "导入的项目id")
private String projectId;
@Schema(description = "导入的swagger地址")
private String swaggerUrl;
@ -21,25 +19,26 @@ public class ImportRequest {
private String versionId; // 新导入选择的版本
private String updateVersionId; // 覆盖导入已存在的接口选择的版本
private String defaultVersion;
@Schema(description = "三方平台 暂定 Metersphere Swagger3 Postman Har")
private String platform;
//调用类型
@Schema(description = "导入的类型 暂定 API Schedule")
private String type;
@Schema(description = "是否覆盖模块")
private Boolean coverModule;
private Boolean coverModule = false;
@Schema(description = "是否同步导入用例")
private Boolean syncCase;
private Boolean syncCase = false;
@Schema(description = "是否覆盖数据")
private Boolean coverData;
// 当前协议
private String protocol;
//上传文件来源目前用于辨别是否是idea插件
private String origin;
@Schema(description = "swagger的请求头参数")
private List<Header> headers;
@Schema(description = "swagger的请求参数")
private List<QueryParam> arguments;
@Schema(description = "swagger的认证参数")
private HTTPAuth authManager;
private Boolean coverData = false;
@Schema(description = "协议")
private String protocol = ModuleConstants.NODE_PROTOCOL_HTTP;
@Schema(description = "是否开启Basic Auth认证")
private boolean authSwitch = false;
@Schema(description = "Basic Auth认证用户名")
private String authUsername;
@Schema(description = "Basic Auth认证密码")
private String authPassword;
@Schema(description = "唯一标识 默认是Method & Path 后续估计会补充")
private String uniquelyIdentifies = "Method & Path";
@Schema(description = "定时任务的资源id")
private String resourceId;
}

View File

@ -231,6 +231,7 @@
and (
api_definition.num like concat('%', #{request.keyword},'%')
or api_definition.name like concat('%', #{request.keyword},'%')
or api_definition.path like concat('%', #{request.keyword},'%')
or api_definition.tags like JSON_CONTAINS(tags, concat('["',#{request.keyword},'"]'))
)
</if>

View File

@ -237,6 +237,7 @@
and (
t1.name like concat('%', #{request.keyword},'%')
or t1.num like concat('%', #{request.keyword},'%')
or a.path like concat('%', #{request.keyword},'%')
or t1.tags like JSON_CONTAINS(t1.tags, concat('["',#{request.keyword},'"]'))
)
</if>

View File

@ -33,7 +33,6 @@ import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.*;
@ -77,42 +76,13 @@ public class Swagger3Parser<T> implements ImportParser<ApiDefinitionImport> {
private List<AuthorizationValue> setAuths(ImportRequest request) {
List<AuthorizationValue> auths = new ArrayList<>();
// TODO 如果有 BaseAuth 参数base64 编码后转换成 headers
// 设置 headers
if (!CollectionUtils.isEmpty(request.getHeaders())) {
for (Header keyValue : request.getHeaders()) {
// 当有 key 时才进行设置
if (keyValue.getValue() != null) {
AuthorizationValue authorizationValue = new AuthorizationValue();
authorizationValue.setType("header");
authorizationValue.setKeyName(keyValue.getKey());
authorizationValue.setValue(String.valueOf(keyValue.getValue()));
authorizationValue.setUrlMatcher((url) -> true);
auths.add(authorizationValue);
}
}
}
// 设置 query 参数
if (!CollectionUtils.isEmpty(request.getArguments())) {
StringBuilder pathBuilder = new StringBuilder();
pathBuilder.append(request.getSwaggerUrl());
if (StringUtils.isNotBlank(request.getSwaggerUrl()) && !request.getSwaggerUrl().contains("?")) {
pathBuilder.append("?");
}
for (QueryParam keyValue : request.getArguments()) {
if (StringUtils.isNotBlank(keyValue.getKey())) {
AuthorizationValue authorizationValue = new AuthorizationValue();
authorizationValue.setType("query");
authorizationValue.setKeyName(keyValue.getKey());
try {
authorizationValue.setValue(URLEncoder.encode(String.valueOf(keyValue.getValue()), StandardCharsets.UTF_8));
} catch (Exception e) {
LogUtils.info("swagger3 url encode error: " + e);
}
pathBuilder.append(keyValue.getKey()).append("=").append(authorizationValue.getValue()).append("&");
}
}
request.setSwaggerUrl(pathBuilder.substring(0, pathBuilder.length() - 1));
if (request.isAuthSwitch()) {
AuthorizationValue authorizationValue = new AuthorizationValue();
authorizationValue.setType("header");
authorizationValue.setKeyName("Authorization");
String authValue = "Basic " + Base64.getUrlEncoder().encodeToString((request.getAuthUsername() + ":" + request.getAuthPassword()).getBytes());
authorizationValue.setValue(authValue);
auths.add(authorizationValue);
}
return CollectionUtils.size(auths) == 0 ? null : auths;
}

View File

@ -1,5 +1,6 @@
package io.metersphere.api.service.definition;
import io.metersphere.api.constants.ApiImportPlatform;
import io.metersphere.api.domain.ApiDefinition;
import io.metersphere.api.domain.ApiDefinitionBlob;
import io.metersphere.api.domain.ApiDefinitionBlobExample;
@ -86,17 +87,17 @@ public class ApiDefinitionImportUtilService {
public void checkFileSuffixName(ImportRequest request, String suffixName) {
if ("jmx".equalsIgnoreCase(suffixName)) {
if (!"JMeter".equalsIgnoreCase(request.getPlatform())) {
if (!ApiImportPlatform.Jmeter.name().equalsIgnoreCase(request.getPlatform())) {
throw new MSException(Translator.get("file_format_does_not_meet_requirements"));
}
}
if ("har".equalsIgnoreCase(suffixName)) {
if (!"Har".equalsIgnoreCase(request.getPlatform())) {
if (!ApiImportPlatform.Har.name().equalsIgnoreCase(request.getPlatform())) {
throw new MSException(Translator.get("file_format_does_not_meet_requirements"));
}
}
if ("json".equalsIgnoreCase(suffixName)) {
if ("Har".equalsIgnoreCase(request.getPlatform()) || "Jmeter".equalsIgnoreCase(request.getPlatform())) {
if (ApiImportPlatform.Har.name().equalsIgnoreCase(request.getPlatform()) || ApiImportPlatform.Jmeter.name().equalsIgnoreCase(request.getPlatform())) {
throw new MSException(Translator.get("file_format_does_not_meet_requirements"));
}
}
@ -545,6 +546,7 @@ public class ApiDefinitionImportUtilService {
if (jsonSchema == null && importJsonSchema == null) {
return true;
}
assert jsonSchema != null;
if (!StringUtils.equals(jsonSchema.getType(), importJsonSchema.getType())) {
return false;
}

View File

@ -0,0 +1,189 @@
package io.metersphere.api.service.definition;
import io.metersphere.api.domain.ApiDefinitionSwagger;
import io.metersphere.api.domain.ApiDefinitionSwaggerExample;
import io.metersphere.api.dto.definition.ApiScheduleDTO;
import io.metersphere.api.dto.definition.SwaggerBasicAuth;
import io.metersphere.api.dto.definition.importdto.ApiScheduleRequest;
import io.metersphere.api.mapper.ApiDefinitionSwaggerMapper;
import io.metersphere.api.service.schedule.SwaggerUrlImportJob;
import io.metersphere.api.utils.ApiDataUtils;
import io.metersphere.project.mapper.ProjectMapper;
import io.metersphere.sdk.constants.HttpMethodConstants;
import io.metersphere.sdk.constants.ScheduleType;
import io.metersphere.sdk.exception.MSException;
import io.metersphere.sdk.util.BeanUtils;
import io.metersphere.sdk.util.JSON;
import io.metersphere.sdk.util.Translator;
import io.metersphere.system.domain.Schedule;
import io.metersphere.system.log.constants.OperationLogModule;
import io.metersphere.system.log.constants.OperationLogType;
import io.metersphere.system.log.dto.LogDTO;
import io.metersphere.system.log.service.OperationLogService;
import io.metersphere.system.mapper.ScheduleMapper;
import io.metersphere.system.sechedule.ScheduleService;
import io.metersphere.system.uid.IDGenerator;
import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
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 ApiDefinitionScheduleService {
@Resource
private ApiDefinitionSwaggerMapper apiDefinitionSwaggerMapper;
@Resource
private ScheduleService scheduleService;
@Resource
private ScheduleMapper scheduleMapper;
@Resource
private OperationLogService operationLogService;
@Resource
private ProjectMapper projectMapper;
public void createSchedule(ApiScheduleRequest request, String userId) {
/*保存swaggerUrl*/
ApiDefinitionSwagger apiSwagger = new ApiDefinitionSwagger();
BeanUtils.copyBean(apiSwagger, request);
apiSwagger.setId(IDGenerator.nextStr());
// 设置鉴权信息
SwaggerBasicAuth basicAuth = new SwaggerBasicAuth();
basicAuth.setUserName(request.getAuthUsername());
basicAuth.setPassword(request.getAuthPassword());
basicAuth.setAuthSwitch(request.isAuthSwitch());
apiSwagger.setConfig(ApiDataUtils.toJSONString(basicAuth));
apiDefinitionSwaggerMapper.insertSelective(apiSwagger);
Schedule schedule = this.buildApiTestSchedule(request, userId);
schedule.setResourceId(apiSwagger.getId());
schedule.setJob(SwaggerUrlImportJob.class.getName());
schedule.setType(ScheduleType.CRON.name());
scheduleService.addSchedule(schedule);
scheduleService.addOrUpdateCronJob(schedule,
SwaggerUrlImportJob.getJobKey(apiSwagger.getId()),
SwaggerUrlImportJob.getTriggerKey(apiSwagger.getId()),
SwaggerUrlImportJob.class);
//TODO 记录日志
LogDTO dto = new LogDTO(
request.getProjectId(),
projectMapper.selectByPrimaryKey(request.getProjectId()).getOrganizationId(),
request.getId(),
userId,
OperationLogType.ADD.name(),
OperationLogModule.API_DEFINITION,
request.getName());
dto.setHistory(false);
dto.setPath("/api/definition/schedule/add");
dto.setMethod(HttpMethodConstants.POST.name());
dto.setOriginalValue(JSON.toJSONBytes(request));
operationLogService.add(dto);
}
public Schedule buildApiTestSchedule(ApiScheduleRequest request, String userId) {
Schedule schedule = new Schedule();
schedule.setName(request.getName());
schedule.setResourceId(request.getId());
schedule.setEnable(request.getEnable());
schedule.setValue(request.getValue().trim());
schedule.setKey(request.getId());
schedule.setCreateUser(userId);
schedule.setProjectId(request.getProjectId());
schedule.setConfig(request.getConfig());
return schedule;
}
public ApiDefinitionSwagger checkSchedule(String id) {
ApiDefinitionSwagger apiDefinitionSwagger = apiDefinitionSwaggerMapper.selectByPrimaryKey(id);
if (apiDefinitionSwagger == null) {
throw new MSException(Translator.get("schedule_not_exist"));
}
return apiDefinitionSwagger;
}
public Boolean checkSwaggerUrl(String projectId, String url) {
ApiDefinitionSwaggerExample example = new ApiDefinitionSwaggerExample();
example.createCriteria().andProjectIdEqualTo(projectId).andSwaggerUrlEqualTo(url);
List<ApiDefinitionSwagger> apiDefinitionSwaggers = apiDefinitionSwaggerMapper.selectByExample(example);
return CollectionUtils.isNotEmpty(apiDefinitionSwaggers);
}
public void updateSchedule(ApiScheduleRequest request, String userId) {
ApiDefinitionSwagger apiDefinitionSwagger = checkSchedule(request.getId());
BeanUtils.copyBean(apiDefinitionSwagger, request);
// 设置鉴权信息
SwaggerBasicAuth basicAuth = new SwaggerBasicAuth();
basicAuth.setUserName(request.getAuthUsername());
basicAuth.setPassword(request.getAuthPassword());
basicAuth.setAuthSwitch(request.isAuthSwitch());
apiDefinitionSwagger.setConfig(ApiDataUtils.toJSONString(basicAuth));
apiDefinitionSwaggerMapper.updateByPrimaryKeySelective(apiDefinitionSwagger);
// 只修改表达式和名称
Schedule schedule = scheduleService.getScheduleByResource(request.getId(), SwaggerUrlImportJob.class.getName());
schedule.setValue(request.getValue().trim());
schedule.setEnable(request.getEnable());
schedule.setName(request.getName());
scheduleService.editSchedule(schedule);
scheduleService.addOrUpdateCronJob(schedule,
SwaggerUrlImportJob.getJobKey(request.getId()),
SwaggerUrlImportJob.getTriggerKey(request.getId()),
SwaggerUrlImportJob.class);
LogDTO dto = new LogDTO(
request.getProjectId(),
projectMapper.selectByPrimaryKey(request.getProjectId()).getOrganizationId(),
request.getId(),
userId,
OperationLogType.UPDATE.name(),
OperationLogModule.API_DEFINITION,
request.getName());
dto.setHistory(false);
dto.setPath("/api/definition/schedule/update");
dto.setMethod(HttpMethodConstants.POST.name());
dto.setOriginalValue(JSON.toJSONBytes(request));
operationLogService.add(dto);
}
public ApiScheduleDTO getSchedule(String id) {
ApiScheduleDTO apiScheduleDTO = new ApiScheduleDTO();
ApiDefinitionSwagger apiDefinitionSwagger = checkSchedule(id);
Schedule schedule = scheduleService.getScheduleByResource(id, SwaggerUrlImportJob.class.getName());
BeanUtils.copyBean(apiScheduleDTO, apiDefinitionSwagger);
if (StringUtils.isNotBlank(apiDefinitionSwagger.getConfig())) {
SwaggerBasicAuth basicAuth = ApiDataUtils.parseObject(apiDefinitionSwagger.getConfig(), SwaggerBasicAuth.class);
apiScheduleDTO.setAuthUsername(basicAuth.getUserName());
apiScheduleDTO.setAuthPassword(basicAuth.getPassword());
apiScheduleDTO.setAuthSwitch(basicAuth.getAuthSwitch());
}
apiScheduleDTO.setEnable(schedule.getEnable());
apiScheduleDTO.setValue(schedule.getValue());
return apiScheduleDTO;
}
public void switchSchedule(String id) {
Schedule schedule = checkScheduleExit(id);
schedule.setEnable(!schedule.getEnable());
scheduleService.editSchedule(schedule);
scheduleService.addOrUpdateCronJob(schedule, SwaggerUrlImportJob.getJobKey(schedule.getResourceId()),
SwaggerUrlImportJob.getTriggerKey(schedule.getResourceId()), SwaggerUrlImportJob.class);
}
public void deleteSchedule(String id) {
Schedule schedule = checkScheduleExit(id);
apiDefinitionSwaggerMapper.deleteByPrimaryKey(schedule.getResourceId());
scheduleService.deleteByResourceId(schedule.getResourceId(), SwaggerUrlImportJob.class.getName());
}
private Schedule checkScheduleExit(String id) {
Schedule schedule = scheduleMapper.selectByPrimaryKey(id);
if (schedule == null) {
throw new MSException(Translator.get("schedule_not_exist"));
}
return schedule;
}
}

View File

@ -16,7 +16,6 @@ import io.metersphere.api.service.ApiFileResourceService;
import io.metersphere.api.utils.ApiDataUtils;
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
import io.metersphere.project.mapper.ExtBaseProjectVersionMapper;
import io.metersphere.project.mapper.ProjectMapper;
import io.metersphere.project.service.ProjectService;
import io.metersphere.sdk.constants.ApiReportStatus;
import io.metersphere.sdk.constants.ApplicationNumScope;
@ -109,8 +108,6 @@ public class ApiDefinitionService {
private ApiDefinitionLogService apiDefinitionLogService;
@Resource
private ApiDefinitionImportUtilService apiDefinitionImportUtilService;
@Resource
private ProjectMapper projectMapper;
@Resource
private ApiDefinitionMockService apiDefinitionMockService;
@ -883,7 +880,7 @@ public class ApiDefinitionService {
return apiDefinitionDocDTO;
}
public ApiDefinitionImport apiTestImport(MultipartFile file, ImportRequest request) {
public ApiDefinitionImport apiTestImport(MultipartFile file, ImportRequest request, String userId, String projectId) {
if (file != null) {
String originalFilename = file.getOriginalFilename();
if (StringUtils.isNotBlank(originalFilename)) {
@ -891,6 +888,10 @@ public class ApiDefinitionService {
apiDefinitionImportUtilService.checkFileSuffixName(request, suffixName);
}
}
request.setUserId(userId);
if (StringUtils.isBlank(request.getProjectId())) {
request.setProjectId(projectId);
}
ImportParser<?> runService = ImportParserFactory.getImportParser(request.getPlatform());
ApiDefinitionImport apiImport = null;
if (StringUtils.equals(request.getType(), "SCHEDULE")) {
@ -924,6 +925,7 @@ public class ApiDefinitionService {
}
return apiImport;
}
public List<OperationHistoryDTO> list(OperationHistoryRequest request) {
List<OperationHistoryDTO> operationHistoryList = operationHistoryService.list(request);
if (CollectionUtils.isNotEmpty(operationHistoryList)) {
@ -959,7 +961,7 @@ public class ApiDefinitionService {
apiDefinitionMapper.insertSelective(apiDefinition);
ApiDefinitionBlob apiDefinitionBlob = new ApiDefinitionBlob();
if(copyApiDefinitionBlob != null) {
if (copyApiDefinitionBlob != null) {
apiDefinitionBlob.setId(apiDefinition.getId());
apiDefinitionBlob.setRequest(copyApiDefinitionBlob.getRequest());
apiDefinitionBlob.setResponse(copyApiDefinitionBlob.getResponse());
@ -981,7 +983,6 @@ public class ApiDefinitionService {
}
public void recoverOperationHistory(OperationHistoryVersionRequest request) {
OperationLogBlob operationLogBlob = operationLogBlobMapper.selectByPrimaryKey(request.getId());
ApiDefinitionDTO apiDefinitionDTO = ApiDataUtils.parseObject(new String(operationLogBlob.getOriginalValue()), ApiDefinitionDTO.class);

View File

@ -0,0 +1,48 @@
package io.metersphere.api.service.schedule;
import io.metersphere.api.constants.ApiImportPlatform;
import io.metersphere.api.dto.definition.ApiScheduleDTO;
import io.metersphere.api.dto.request.ImportRequest;
import io.metersphere.api.service.definition.ApiDefinitionScheduleService;
import io.metersphere.api.service.definition.ApiDefinitionService;
import io.metersphere.sdk.util.BeanUtils;
import io.metersphere.sdk.util.CommonBeanFactory;
import io.metersphere.system.sechedule.BaseScheduleJob;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobKey;
import org.quartz.TriggerKey;
public class SwaggerUrlImportJob extends BaseScheduleJob {
private ApiDefinitionService apiDefinitionService;
private ApiDefinitionScheduleService apiDefinitionScheduleService;
public SwaggerUrlImportJob() {
apiDefinitionService = CommonBeanFactory.getBean(ApiDefinitionService.class);
apiDefinitionScheduleService = CommonBeanFactory.getBean(ApiDefinitionScheduleService.class);
}
@Override
protected void businessExecute(JobExecutionContext context) {
JobDataMap jobDataMap = context.getJobDetail().getJobDataMap();
String resourceId = jobDataMap.getString("resourceId");
ApiScheduleDTO swaggerInfo = apiDefinitionScheduleService.getSchedule(resourceId);
ImportRequest request = new ImportRequest();
BeanUtils.copyBean(request, swaggerInfo);
request.setPlatform(ApiImportPlatform.Swagger3.name());
request.setUserId(jobDataMap.getString("userId"));
request.setType("SCHEDULE");
request.setResourceId(resourceId);
apiDefinitionService.apiTestImport(null, request, request.getUserId(), request.getProjectId());
}
public static JobKey getJobKey(String resourceId) {
return new JobKey(resourceId, SwaggerUrlImportJob.class.getName());
}
public static TriggerKey getTriggerKey(String resourceId) {
return new TriggerKey(resourceId, SwaggerUrlImportJob.class.getName());
}
}

View File

@ -0,0 +1,168 @@
package io.metersphere.api.controller;
import io.metersphere.api.domain.ApiDefinitionSwagger;
import io.metersphere.api.domain.ApiDefinitionSwaggerExample;
import io.metersphere.api.dto.definition.ApiScheduleDTO;
import io.metersphere.api.dto.definition.SwaggerUrlCheck;
import io.metersphere.api.dto.definition.importdto.ApiScheduleRequest;
import io.metersphere.api.mapper.ApiDefinitionSwaggerMapper;
import io.metersphere.api.utils.ApiDataUtils;
import io.metersphere.sdk.util.JSON;
import io.metersphere.system.base.BaseTest;
import io.metersphere.system.domain.Schedule;
import io.metersphere.system.domain.ScheduleExample;
import io.metersphere.system.mapper.ScheduleMapper;
import jakarta.annotation.Resource;
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 org.springframework.test.web.servlet.ResultMatcher;
import java.util.List;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
@AutoConfigureMockMvc
public class ApiDefinitionScheduleControllerTests extends BaseTest {
private static final String BASE_PATH = "/api/definition/schedule/";
private final static String ADD = BASE_PATH + "add";
private final static String UPDATE = BASE_PATH + "update";
private final static String GET = BASE_PATH + "get/";
@Resource
private ApiDefinitionSwaggerMapper apiDefinitionSwaggerMapper;
@Resource
private ScheduleMapper scheduleMapper;
private static String ID;
private static String SCHEDULE_ID;
private static final ResultMatcher BAD_REQUEST_MATCHER = status().isBadRequest();
private static final ResultMatcher ERROR_REQUEST_MATCHER = status().is5xxServerError();
@Order(1)
@Test
public void add() throws Exception {
ApiScheduleRequest request = new ApiScheduleRequest();
request.setName("定时任务1");
request.setValue("0 0/1 * * * ?");
request.setProjectId(DEFAULT_PROJECT_ID);
request.setCoverData(true);
request.setSwaggerUrl("https://petstore3.swagger.io/api/v3/openapi.json");
this.requestPostWithOk(ADD, request);
ApiDefinitionSwaggerExample example = new ApiDefinitionSwaggerExample();
example.createCriteria().andProjectIdEqualTo(DEFAULT_PROJECT_ID);
List<ApiDefinitionSwagger> apiDefinitionSwaggers = apiDefinitionSwaggerMapper.selectByExample(example);
assert apiDefinitionSwaggers.size() == 1;
ID = apiDefinitionSwaggers.get(0).getId();
ScheduleExample scheduleExample = new ScheduleExample();
scheduleExample.createCriteria().andResourceIdEqualTo(apiDefinitionSwaggers.get(0).getId());
List<Schedule> schedules = scheduleMapper.selectByExample(scheduleExample);
assert schedules.size() == 1;
SCHEDULE_ID = schedules.get(0).getId();
request = new ApiScheduleRequest();
request.setName("定时任务2");
request.setValue("0 0/1 * * * ?");
request.setProjectId(DEFAULT_PROJECT_ID);
this.requestPost(ADD, request, BAD_REQUEST_MATCHER);
request.setSwaggerUrl("https://petstore3.swagger.io/api/v3/openapi.json");
request.setName(null);
this.requestPost(ADD, request, BAD_REQUEST_MATCHER);
request.setName("定时任务2");
request.setValue(null);
this.requestPost(ADD, request, BAD_REQUEST_MATCHER);
request.setValue("0 0/1 * * * ?");
request.setProjectId(null);
this.requestPost(ADD, request, BAD_REQUEST_MATCHER);
}
@Order(2)
@Test
public void update() throws Exception {
ApiScheduleRequest request = new ApiScheduleRequest();
request.setName("定时任务2");
request.setValue("0 0/1 * * * ?");
request.setProjectId(DEFAULT_PROJECT_ID);
request.setCoverData(true);
request.setId(ID);
request.setSwaggerUrl("https://petstore3.swagger.io/api/v3/openapi.json");
this.requestPostWithOk(UPDATE, request);
ApiDefinitionSwagger apiDefinitionSwagger = apiDefinitionSwaggerMapper.selectByPrimaryKey(ID);
assert apiDefinitionSwagger.getName().equals("定时任务2");
request.setId("123");
this.requestPost(UPDATE, request, ERROR_REQUEST_MATCHER);
request.setId(null);
this.requestPost(UPDATE, request, BAD_REQUEST_MATCHER);
request.setId("123");
request.setName(null);
this.requestPost(UPDATE, request, BAD_REQUEST_MATCHER);
request.setName("定时任务2");
request.setValue(null);
this.requestPost(UPDATE, request, BAD_REQUEST_MATCHER);
request.setValue("0 0/1 * * * ?");
request.setProjectId(null);
this.requestPost(UPDATE, request, BAD_REQUEST_MATCHER);
request.setProjectId(DEFAULT_PROJECT_ID);
request.setSwaggerUrl(null);
this.requestPost(UPDATE, request, BAD_REQUEST_MATCHER);
}
@Order(3)
@Test
public void get() throws Exception {
this.requestGet(GET + "123", ERROR_REQUEST_MATCHER);
MvcResult mvcResult = this.requestGetWithOk(GET + ID)
.andReturn();
ApiScheduleDTO apiScheduleDTO = ApiDataUtils.parseObject(JSON.toJSONString(parseResponse(mvcResult).get("data")), ApiScheduleDTO.class);
assert apiScheduleDTO.getId().equals(ID);
assert apiScheduleDTO.getName().equals("定时任务2");
assert apiScheduleDTO.getValue().equals("0 0/1 * * * ?");
assert apiScheduleDTO.getSwaggerUrl().equals("https://petstore3.swagger.io/api/v3/openapi.json");
}
@Order(4)
@Test
public void switchSchedule() throws Exception {
this.requestGet(BASE_PATH + "switch/123", ERROR_REQUEST_MATCHER);
this.requestGetWithOk(BASE_PATH + "switch/" + SCHEDULE_ID);
Schedule schedule = scheduleMapper.selectByPrimaryKey(SCHEDULE_ID);
//断言为false
assert !schedule.getEnable();
this.requestGetWithOk(BASE_PATH + "switch/" + SCHEDULE_ID);
schedule = scheduleMapper.selectByPrimaryKey(SCHEDULE_ID);
//断言为true
assert schedule.getEnable();
}
@Order(5)
@Test
public void checkSchedule() throws Exception {
SwaggerUrlCheck swaggerUrlCheck = new SwaggerUrlCheck();
swaggerUrlCheck.setProjectId(DEFAULT_PROJECT_ID);
swaggerUrlCheck.setSwaggerUrl("https://petstore3.swagger.io/api/v3/openapi.json");
this.requestPost(BASE_PATH + "check/", swaggerUrlCheck);
}
@Order(6)
@Test
public void deleteSchedule() throws Exception {
this.requestGet(BASE_PATH + "delete/123", ERROR_REQUEST_MATCHER);
this.requestGetWithOk(BASE_PATH + "delete/" + SCHEDULE_ID);
ApiDefinitionSwaggerExample example = new ApiDefinitionSwaggerExample();
example.createCriteria().andProjectIdEqualTo(DEFAULT_PROJECT_ID);
List<ApiDefinitionSwagger> apiDefinitionSwaggers = apiDefinitionSwaggerMapper.selectByExample(example);
assert apiDefinitionSwaggers.isEmpty();
ScheduleExample scheduleExample = new ScheduleExample();
scheduleExample.createCriteria().andResourceIdEqualTo(ID);
List<Schedule> schedules = scheduleMapper.selectByExample(scheduleExample);
assert schedules.isEmpty();
}
}