feat(接口测试): 增加接口模块接口

This commit is contained in:
wxg0103 2023-11-06 14:34:25 +08:00 committed by f2c-ci-robot[bot]
parent 9112726e9a
commit 51ac88e681
35 changed files with 1936 additions and 362 deletions

View File

@ -37,7 +37,7 @@ public class ApiDefinition implements Serializable {
private String status;
@Schema(description = "自定义id")
private Integer num;
private Long num;
@Schema(description = "标签")
private String tags;
@ -51,20 +51,23 @@ public class ApiDefinition implements Serializable {
@Size(min = 1, max = 50, message = "{api_definition.project_id.length_range}", groups = {Created.class, Updated.class})
private String projectId;
@Schema(description = "模块fk")
@Schema(description = "模块fk", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{api_definition.module_id.not_blank}", groups = {Created.class})
@Size(min = 1, max = 50, message = "{api_definition.module_id.length_range}", groups = {Created.class, Updated.class})
private String moduleId;
@Schema(description = "环境fk")
private String environmentId;
@Schema(description = "是否为最新版本 0:否1:是", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "{api_definition.latest.not_blank}", groups = {Created.class})
private Boolean latest;
@Schema(description = "版本fk")
@Schema(description = "版本fk", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{api_definition.version_id.not_blank}", groups = {Created.class})
@Size(min = 1, max = 50, message = "{api_definition.version_id.length_range}", groups = {Created.class, Updated.class})
private String versionId;
@Schema(description = "版本引用fk")
@Schema(description = "版本引用fk", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{api_definition.ref_id.not_blank}", groups = {Created.class})
@Size(min = 1, max = 50, message = "{api_definition.ref_id.length_range}", groups = {Created.class, Updated.class})
private String refId;
@Schema(description = "描述")
@ -101,12 +104,11 @@ public class ApiDefinition implements Serializable {
method("method", "method", "VARCHAR", true),
path("path", "path", "VARCHAR", true),
status("status", "status", "VARCHAR", true),
num("num", "num", "INTEGER", false),
num("num", "num", "BIGINT", false),
tags("tags", "tags", "VARCHAR", false),
pos("pos", "pos", "BIGINT", false),
projectId("project_id", "projectId", "VARCHAR", false),
moduleId("module_id", "moduleId", "VARCHAR", false),
environmentId("environment_id", "environmentId", "VARCHAR", false),
latest("latest", "latest", "BIT", false),
versionId("version_id", "versionId", "VARCHAR", false),
refId("ref_id", "refId", "VARCHAR", false),

View File

@ -534,52 +534,52 @@ public class ApiDefinitionExample {
return (Criteria) this;
}
public Criteria andNumEqualTo(Integer value) {
public Criteria andNumEqualTo(Long value) {
addCriterion("num =", value, "num");
return (Criteria) this;
}
public Criteria andNumNotEqualTo(Integer value) {
public Criteria andNumNotEqualTo(Long value) {
addCriterion("num <>", value, "num");
return (Criteria) this;
}
public Criteria andNumGreaterThan(Integer value) {
public Criteria andNumGreaterThan(Long value) {
addCriterion("num >", value, "num");
return (Criteria) this;
}
public Criteria andNumGreaterThanOrEqualTo(Integer value) {
public Criteria andNumGreaterThanOrEqualTo(Long value) {
addCriterion("num >=", value, "num");
return (Criteria) this;
}
public Criteria andNumLessThan(Integer value) {
public Criteria andNumLessThan(Long value) {
addCriterion("num <", value, "num");
return (Criteria) this;
}
public Criteria andNumLessThanOrEqualTo(Integer value) {
public Criteria andNumLessThanOrEqualTo(Long value) {
addCriterion("num <=", value, "num");
return (Criteria) this;
}
public Criteria andNumIn(List<Integer> values) {
public Criteria andNumIn(List<Long> values) {
addCriterion("num in", values, "num");
return (Criteria) this;
}
public Criteria andNumNotIn(List<Integer> values) {
public Criteria andNumNotIn(List<Long> values) {
addCriterion("num not in", values, "num");
return (Criteria) this;
}
public Criteria andNumBetween(Integer value1, Integer value2) {
public Criteria andNumBetween(Long value1, Long value2) {
addCriterion("num between", value1, value2, "num");
return (Criteria) this;
}
public Criteria andNumNotBetween(Integer value1, Integer value2) {
public Criteria andNumNotBetween(Long value1, Long value2) {
addCriterion("num not between", value1, value2, "num");
return (Criteria) this;
}
@ -854,76 +854,6 @@ public class ApiDefinitionExample {
return (Criteria) this;
}
public Criteria andEnvironmentIdIsNull() {
addCriterion("environment_id is null");
return (Criteria) this;
}
public Criteria andEnvironmentIdIsNotNull() {
addCriterion("environment_id is not null");
return (Criteria) this;
}
public Criteria andEnvironmentIdEqualTo(String value) {
addCriterion("environment_id =", value, "environmentId");
return (Criteria) this;
}
public Criteria andEnvironmentIdNotEqualTo(String value) {
addCriterion("environment_id <>", value, "environmentId");
return (Criteria) this;
}
public Criteria andEnvironmentIdGreaterThan(String value) {
addCriterion("environment_id >", value, "environmentId");
return (Criteria) this;
}
public Criteria andEnvironmentIdGreaterThanOrEqualTo(String value) {
addCriterion("environment_id >=", value, "environmentId");
return (Criteria) this;
}
public Criteria andEnvironmentIdLessThan(String value) {
addCriterion("environment_id <", value, "environmentId");
return (Criteria) this;
}
public Criteria andEnvironmentIdLessThanOrEqualTo(String value) {
addCriterion("environment_id <=", value, "environmentId");
return (Criteria) this;
}
public Criteria andEnvironmentIdLike(String value) {
addCriterion("environment_id like", value, "environmentId");
return (Criteria) this;
}
public Criteria andEnvironmentIdNotLike(String value) {
addCriterion("environment_id not like", value, "environmentId");
return (Criteria) this;
}
public Criteria andEnvironmentIdIn(List<String> values) {
addCriterion("environment_id in", values, "environmentId");
return (Criteria) this;
}
public Criteria andEnvironmentIdNotIn(List<String> values) {
addCriterion("environment_id not in", values, "environmentId");
return (Criteria) this;
}
public Criteria andEnvironmentIdBetween(String value1, String value2) {
addCriterion("environment_id between", value1, value2, "environmentId");
return (Criteria) this;
}
public Criteria andEnvironmentIdNotBetween(String value1, String value2) {
addCriterion("environment_id not between", value1, value2, "environmentId");
return (Criteria) this;
}
public Criteria andLatestIsNull() {
addCriterion("latest is null");
return (Criteria) this;

View File

@ -22,7 +22,7 @@ public class ApiDefinitionModule implements Serializable {
@Schema(description = "协议", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{api_definition_module.protocol.not_blank}", groups = {Created.class})
@Size(min = 1, max = 64, message = "{api_definition_module.protocol.length_range}", groups = {Created.class, Updated.class})
@Size(min = 1, max = 20, message = "{api_definition_module.protocol.length_range}", groups = {Created.class, Updated.class})
private String protocol;
@Schema(description = "父级fk", requiredMode = Schema.RequiredMode.REQUIRED)
@ -35,13 +35,9 @@ public class ApiDefinitionModule implements Serializable {
@Size(min = 1, max = 50, message = "{api_definition_module.project_id.length_range}", groups = {Created.class, Updated.class})
private String projectId;
@Schema(description = "树节点级别", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "{api_definition_module.level.not_blank}", groups = {Created.class})
private Integer level;
@Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "{api_definition_module.pos.not_blank}", groups = {Created.class})
private Integer pos;
private Long pos;
@Schema(description = "创建时间")
private Long createTime;
@ -63,8 +59,7 @@ public class ApiDefinitionModule implements Serializable {
protocol("protocol", "protocol", "VARCHAR", false),
parentId("parent_id", "parentId", "VARCHAR", false),
projectId("project_id", "projectId", "VARCHAR", false),
level("level", "level", "INTEGER", true),
pos("pos", "pos", "INTEGER", false),
pos("pos", "pos", "BIGINT", false),
createTime("create_time", "createTime", "BIGINT", false),
updateTime("update_time", "updateTime", "BIGINT", false),
updateUser("update_user", "updateUser", "VARCHAR", false),

View File

@ -454,66 +454,6 @@ public class ApiDefinitionModuleExample {
return (Criteria) this;
}
public Criteria andLevelIsNull() {
addCriterion("`level` is null");
return (Criteria) this;
}
public Criteria andLevelIsNotNull() {
addCriterion("`level` is not null");
return (Criteria) this;
}
public Criteria andLevelEqualTo(Integer value) {
addCriterion("`level` =", value, "level");
return (Criteria) this;
}
public Criteria andLevelNotEqualTo(Integer value) {
addCriterion("`level` <>", value, "level");
return (Criteria) this;
}
public Criteria andLevelGreaterThan(Integer value) {
addCriterion("`level` >", value, "level");
return (Criteria) this;
}
public Criteria andLevelGreaterThanOrEqualTo(Integer value) {
addCriterion("`level` >=", value, "level");
return (Criteria) this;
}
public Criteria andLevelLessThan(Integer value) {
addCriterion("`level` <", value, "level");
return (Criteria) this;
}
public Criteria andLevelLessThanOrEqualTo(Integer value) {
addCriterion("`level` <=", value, "level");
return (Criteria) this;
}
public Criteria andLevelIn(List<Integer> values) {
addCriterion("`level` in", values, "level");
return (Criteria) this;
}
public Criteria andLevelNotIn(List<Integer> values) {
addCriterion("`level` not in", values, "level");
return (Criteria) this;
}
public Criteria andLevelBetween(Integer value1, Integer value2) {
addCriterion("`level` between", value1, value2, "level");
return (Criteria) this;
}
public Criteria andLevelNotBetween(Integer value1, Integer value2) {
addCriterion("`level` not between", value1, value2, "level");
return (Criteria) this;
}
public Criteria andPosIsNull() {
addCriterion("pos is null");
return (Criteria) this;
@ -524,52 +464,52 @@ public class ApiDefinitionModuleExample {
return (Criteria) this;
}
public Criteria andPosEqualTo(Integer value) {
public Criteria andPosEqualTo(Long value) {
addCriterion("pos =", value, "pos");
return (Criteria) this;
}
public Criteria andPosNotEqualTo(Integer value) {
public Criteria andPosNotEqualTo(Long value) {
addCriterion("pos <>", value, "pos");
return (Criteria) this;
}
public Criteria andPosGreaterThan(Integer value) {
public Criteria andPosGreaterThan(Long value) {
addCriterion("pos >", value, "pos");
return (Criteria) this;
}
public Criteria andPosGreaterThanOrEqualTo(Integer value) {
public Criteria andPosGreaterThanOrEqualTo(Long value) {
addCriterion("pos >=", value, "pos");
return (Criteria) this;
}
public Criteria andPosLessThan(Integer value) {
public Criteria andPosLessThan(Long value) {
addCriterion("pos <", value, "pos");
return (Criteria) this;
}
public Criteria andPosLessThanOrEqualTo(Integer value) {
public Criteria andPosLessThanOrEqualTo(Long value) {
addCriterion("pos <=", value, "pos");
return (Criteria) this;
}
public Criteria andPosIn(List<Integer> values) {
public Criteria andPosIn(List<Long> values) {
addCriterion("pos in", values, "pos");
return (Criteria) this;
}
public Criteria andPosNotIn(List<Integer> values) {
public Criteria andPosNotIn(List<Long> values) {
addCriterion("pos not in", values, "pos");
return (Criteria) this;
}
public Criteria andPosBetween(Integer value1, Integer value2) {
public Criteria andPosBetween(Long value1, Long value2) {
addCriterion("pos between", value1, value2, "pos");
return (Criteria) this;
}
public Criteria andPosNotBetween(Integer value1, Integer value2) {
public Criteria andPosNotBetween(Long value1, Long value2) {
addCriterion("pos not between", value1, value2, "pos");
return (Criteria) this;
}

View File

@ -8,12 +8,11 @@
<result column="method" jdbcType="VARCHAR" property="method" />
<result column="path" jdbcType="VARCHAR" property="path" />
<result column="status" jdbcType="VARCHAR" property="status" />
<result column="num" jdbcType="INTEGER" property="num" />
<result column="num" jdbcType="BIGINT" property="num" />
<result column="tags" jdbcType="VARCHAR" property="tags" />
<result column="pos" jdbcType="BIGINT" property="pos" />
<result column="project_id" jdbcType="VARCHAR" property="projectId" />
<result column="module_id" jdbcType="VARCHAR" property="moduleId" />
<result column="environment_id" jdbcType="VARCHAR" property="environmentId" />
<result column="latest" jdbcType="BIT" property="latest" />
<result column="version_id" jdbcType="VARCHAR" property="versionId" />
<result column="ref_id" jdbcType="VARCHAR" property="refId" />
@ -86,8 +85,8 @@
</sql>
<sql id="Base_Column_List">
id, `name`, protocol, `method`, `path`, `status`, num, tags, pos, project_id, module_id,
environment_id, latest, version_id, ref_id, description, create_time, create_user,
update_time, update_user, delete_user, delete_time, deleted
latest, version_id, ref_id, description, create_time, create_user, update_time, update_user,
delete_user, delete_time, deleted
</sql>
<select id="selectByExample" parameterType="io.metersphere.api.domain.ApiDefinitionExample" resultMap="BaseResultMap">
select
@ -123,19 +122,19 @@
insert into api_definition (id, `name`, protocol,
`method`, `path`, `status`,
num, tags, pos, project_id,
module_id, environment_id, latest,
version_id, ref_id, description,
create_time, create_user, update_time,
update_user, delete_user, delete_time,
deleted)
module_id, latest, version_id,
ref_id, description, create_time,
create_user, update_time, update_user,
delete_user, delete_time, deleted
)
values (#{id,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{protocol,jdbcType=VARCHAR},
#{method,jdbcType=VARCHAR}, #{path,jdbcType=VARCHAR}, #{status,jdbcType=VARCHAR},
#{num,jdbcType=INTEGER}, #{tags,jdbcType=VARCHAR}, #{pos,jdbcType=BIGINT}, #{projectId,jdbcType=VARCHAR},
#{moduleId,jdbcType=VARCHAR}, #{environmentId,jdbcType=VARCHAR}, #{latest,jdbcType=BIT},
#{versionId,jdbcType=VARCHAR}, #{refId,jdbcType=VARCHAR}, #{description,jdbcType=VARCHAR},
#{createTime,jdbcType=BIGINT}, #{createUser,jdbcType=VARCHAR}, #{updateTime,jdbcType=BIGINT},
#{updateUser,jdbcType=VARCHAR}, #{deleteUser,jdbcType=VARCHAR}, #{deleteTime,jdbcType=BIGINT},
#{deleted,jdbcType=BIT})
#{num,jdbcType=BIGINT}, #{tags,jdbcType=VARCHAR}, #{pos,jdbcType=BIGINT}, #{projectId,jdbcType=VARCHAR},
#{moduleId,jdbcType=VARCHAR}, #{latest,jdbcType=BIT}, #{versionId,jdbcType=VARCHAR},
#{refId,jdbcType=VARCHAR}, #{description,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT},
#{createUser,jdbcType=VARCHAR}, #{updateTime,jdbcType=BIGINT}, #{updateUser,jdbcType=VARCHAR},
#{deleteUser,jdbcType=VARCHAR}, #{deleteTime,jdbcType=BIGINT}, #{deleted,jdbcType=BIT}
)
</insert>
<insert id="insertSelective" parameterType="io.metersphere.api.domain.ApiDefinition">
insert into api_definition
@ -173,9 +172,6 @@
<if test="moduleId != null">
module_id,
</if>
<if test="environmentId != null">
environment_id,
</if>
<if test="latest != null">
latest,
</if>
@ -230,7 +226,7 @@
#{status,jdbcType=VARCHAR},
</if>
<if test="num != null">
#{num,jdbcType=INTEGER},
#{num,jdbcType=BIGINT},
</if>
<if test="tags != null">
#{tags,jdbcType=VARCHAR},
@ -244,9 +240,6 @@
<if test="moduleId != null">
#{moduleId,jdbcType=VARCHAR},
</if>
<if test="environmentId != null">
#{environmentId,jdbcType=VARCHAR},
</if>
<if test="latest != null">
#{latest,jdbcType=BIT},
</if>
@ -310,7 +303,7 @@
`status` = #{record.status,jdbcType=VARCHAR},
</if>
<if test="record.num != null">
num = #{record.num,jdbcType=INTEGER},
num = #{record.num,jdbcType=BIGINT},
</if>
<if test="record.tags != null">
tags = #{record.tags,jdbcType=VARCHAR},
@ -324,9 +317,6 @@
<if test="record.moduleId != null">
module_id = #{record.moduleId,jdbcType=VARCHAR},
</if>
<if test="record.environmentId != null">
environment_id = #{record.environmentId,jdbcType=VARCHAR},
</if>
<if test="record.latest != null">
latest = #{record.latest,jdbcType=BIT},
</if>
@ -373,12 +363,11 @@
`method` = #{record.method,jdbcType=VARCHAR},
`path` = #{record.path,jdbcType=VARCHAR},
`status` = #{record.status,jdbcType=VARCHAR},
num = #{record.num,jdbcType=INTEGER},
num = #{record.num,jdbcType=BIGINT},
tags = #{record.tags,jdbcType=VARCHAR},
pos = #{record.pos,jdbcType=BIGINT},
project_id = #{record.projectId,jdbcType=VARCHAR},
module_id = #{record.moduleId,jdbcType=VARCHAR},
environment_id = #{record.environmentId,jdbcType=VARCHAR},
latest = #{record.latest,jdbcType=BIT},
version_id = #{record.versionId,jdbcType=VARCHAR},
ref_id = #{record.refId,jdbcType=VARCHAR},
@ -413,7 +402,7 @@
`status` = #{status,jdbcType=VARCHAR},
</if>
<if test="num != null">
num = #{num,jdbcType=INTEGER},
num = #{num,jdbcType=BIGINT},
</if>
<if test="tags != null">
tags = #{tags,jdbcType=VARCHAR},
@ -427,9 +416,6 @@
<if test="moduleId != null">
module_id = #{moduleId,jdbcType=VARCHAR},
</if>
<if test="environmentId != null">
environment_id = #{environmentId,jdbcType=VARCHAR},
</if>
<if test="latest != null">
latest = #{latest,jdbcType=BIT},
</if>
@ -473,12 +459,11 @@
`method` = #{method,jdbcType=VARCHAR},
`path` = #{path,jdbcType=VARCHAR},
`status` = #{status,jdbcType=VARCHAR},
num = #{num,jdbcType=INTEGER},
num = #{num,jdbcType=BIGINT},
tags = #{tags,jdbcType=VARCHAR},
pos = #{pos,jdbcType=BIGINT},
project_id = #{projectId,jdbcType=VARCHAR},
module_id = #{moduleId,jdbcType=VARCHAR},
environment_id = #{environmentId,jdbcType=VARCHAR},
latest = #{latest,jdbcType=BIT},
version_id = #{versionId,jdbcType=VARCHAR},
ref_id = #{refId,jdbcType=VARCHAR},
@ -495,18 +480,18 @@
<insert id="batchInsert" parameterType="map">
insert into api_definition
(id, `name`, protocol, `method`, `path`, `status`, num, tags, pos, project_id, module_id,
environment_id, latest, version_id, ref_id, description, create_time, create_user,
update_time, update_user, delete_user, delete_time, deleted)
latest, version_id, ref_id, description, create_time, create_user, update_time,
update_user, delete_user, delete_time, deleted)
values
<foreach collection="list" item="item" separator=",">
(#{item.id,jdbcType=VARCHAR}, #{item.name,jdbcType=VARCHAR}, #{item.protocol,jdbcType=VARCHAR},
#{item.method,jdbcType=VARCHAR}, #{item.path,jdbcType=VARCHAR}, #{item.status,jdbcType=VARCHAR},
#{item.num,jdbcType=INTEGER}, #{item.tags,jdbcType=VARCHAR}, #{item.pos,jdbcType=BIGINT},
#{item.projectId,jdbcType=VARCHAR}, #{item.moduleId,jdbcType=VARCHAR}, #{item.environmentId,jdbcType=VARCHAR},
#{item.latest,jdbcType=BIT}, #{item.versionId,jdbcType=VARCHAR}, #{item.refId,jdbcType=VARCHAR},
#{item.description,jdbcType=VARCHAR}, #{item.createTime,jdbcType=BIGINT}, #{item.createUser,jdbcType=VARCHAR},
#{item.updateTime,jdbcType=BIGINT}, #{item.updateUser,jdbcType=VARCHAR}, #{item.deleteUser,jdbcType=VARCHAR},
#{item.deleteTime,jdbcType=BIGINT}, #{item.deleted,jdbcType=BIT})
#{item.num,jdbcType=BIGINT}, #{item.tags,jdbcType=VARCHAR}, #{item.pos,jdbcType=BIGINT},
#{item.projectId,jdbcType=VARCHAR}, #{item.moduleId,jdbcType=VARCHAR}, #{item.latest,jdbcType=BIT},
#{item.versionId,jdbcType=VARCHAR}, #{item.refId,jdbcType=VARCHAR}, #{item.description,jdbcType=VARCHAR},
#{item.createTime,jdbcType=BIGINT}, #{item.createUser,jdbcType=VARCHAR}, #{item.updateTime,jdbcType=BIGINT},
#{item.updateUser,jdbcType=VARCHAR}, #{item.deleteUser,jdbcType=VARCHAR}, #{item.deleteTime,jdbcType=BIGINT},
#{item.deleted,jdbcType=BIT})
</foreach>
</insert>
<insert id="batchInsertSelective" parameterType="map">
@ -538,7 +523,7 @@
#{item.status,jdbcType=VARCHAR}
</if>
<if test="'num'.toString() == column.value">
#{item.num,jdbcType=INTEGER}
#{item.num,jdbcType=BIGINT}
</if>
<if test="'tags'.toString() == column.value">
#{item.tags,jdbcType=VARCHAR}
@ -552,9 +537,6 @@
<if test="'module_id'.toString() == column.value">
#{item.moduleId,jdbcType=VARCHAR}
</if>
<if test="'environment_id'.toString() == column.value">
#{item.environmentId,jdbcType=VARCHAR}
</if>
<if test="'latest'.toString() == column.value">
#{item.latest,jdbcType=BIT}
</if>

View File

@ -7,8 +7,7 @@
<result column="protocol" jdbcType="VARCHAR" property="protocol" />
<result column="parent_id" jdbcType="VARCHAR" property="parentId" />
<result column="project_id" jdbcType="VARCHAR" property="projectId" />
<result column="level" jdbcType="INTEGER" property="level" />
<result column="pos" jdbcType="INTEGER" property="pos" />
<result column="pos" jdbcType="BIGINT" property="pos" />
<result column="create_time" jdbcType="BIGINT" property="createTime" />
<result column="update_time" jdbcType="BIGINT" property="updateTime" />
<result column="update_user" jdbcType="VARCHAR" property="updateUser" />
@ -73,8 +72,8 @@
</where>
</sql>
<sql id="Base_Column_List">
id, `name`, protocol, parent_id, project_id, `level`, pos, create_time, update_time,
update_user, create_user
id, `name`, protocol, parent_id, project_id, pos, create_time, update_time, update_user,
create_user
</sql>
<select id="selectByExample" parameterType="io.metersphere.api.domain.ApiDefinitionModuleExample" resultMap="BaseResultMap">
select
@ -108,13 +107,13 @@
</delete>
<insert id="insert" parameterType="io.metersphere.api.domain.ApiDefinitionModule">
insert into api_definition_module (id, `name`, protocol,
parent_id, project_id, `level`,
pos, create_time, update_time,
update_user, create_user)
parent_id, project_id, pos,
create_time, update_time, update_user,
create_user)
values (#{id,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{protocol,jdbcType=VARCHAR},
#{parentId,jdbcType=VARCHAR}, #{projectId,jdbcType=VARCHAR}, #{level,jdbcType=INTEGER},
#{pos,jdbcType=INTEGER}, #{createTime,jdbcType=BIGINT}, #{updateTime,jdbcType=BIGINT},
#{updateUser,jdbcType=VARCHAR}, #{createUser,jdbcType=VARCHAR})
#{parentId,jdbcType=VARCHAR}, #{projectId,jdbcType=VARCHAR}, #{pos,jdbcType=BIGINT},
#{createTime,jdbcType=BIGINT}, #{updateTime,jdbcType=BIGINT}, #{updateUser,jdbcType=VARCHAR},
#{createUser,jdbcType=VARCHAR})
</insert>
<insert id="insertSelective" parameterType="io.metersphere.api.domain.ApiDefinitionModule">
insert into api_definition_module
@ -134,9 +133,6 @@
<if test="projectId != null">
project_id,
</if>
<if test="level != null">
`level`,
</if>
<if test="pos != null">
pos,
</if>
@ -169,11 +165,8 @@
<if test="projectId != null">
#{projectId,jdbcType=VARCHAR},
</if>
<if test="level != null">
#{level,jdbcType=INTEGER},
</if>
<if test="pos != null">
#{pos,jdbcType=INTEGER},
#{pos,jdbcType=BIGINT},
</if>
<if test="createTime != null">
#{createTime,jdbcType=BIGINT},
@ -213,11 +206,8 @@
<if test="record.projectId != null">
project_id = #{record.projectId,jdbcType=VARCHAR},
</if>
<if test="record.level != null">
`level` = #{record.level,jdbcType=INTEGER},
</if>
<if test="record.pos != null">
pos = #{record.pos,jdbcType=INTEGER},
pos = #{record.pos,jdbcType=BIGINT},
</if>
<if test="record.createTime != null">
create_time = #{record.createTime,jdbcType=BIGINT},
@ -243,8 +233,7 @@
protocol = #{record.protocol,jdbcType=VARCHAR},
parent_id = #{record.parentId,jdbcType=VARCHAR},
project_id = #{record.projectId,jdbcType=VARCHAR},
`level` = #{record.level,jdbcType=INTEGER},
pos = #{record.pos,jdbcType=INTEGER},
pos = #{record.pos,jdbcType=BIGINT},
create_time = #{record.createTime,jdbcType=BIGINT},
update_time = #{record.updateTime,jdbcType=BIGINT},
update_user = #{record.updateUser,jdbcType=VARCHAR},
@ -268,11 +257,8 @@
<if test="projectId != null">
project_id = #{projectId,jdbcType=VARCHAR},
</if>
<if test="level != null">
`level` = #{level,jdbcType=INTEGER},
</if>
<if test="pos != null">
pos = #{pos,jdbcType=INTEGER},
pos = #{pos,jdbcType=BIGINT},
</if>
<if test="createTime != null">
create_time = #{createTime,jdbcType=BIGINT},
@ -295,8 +281,7 @@
protocol = #{protocol,jdbcType=VARCHAR},
parent_id = #{parentId,jdbcType=VARCHAR},
project_id = #{projectId,jdbcType=VARCHAR},
`level` = #{level,jdbcType=INTEGER},
pos = #{pos,jdbcType=INTEGER},
pos = #{pos,jdbcType=BIGINT},
create_time = #{createTime,jdbcType=BIGINT},
update_time = #{updateTime,jdbcType=BIGINT},
update_user = #{updateUser,jdbcType=VARCHAR},
@ -305,14 +290,14 @@
</update>
<insert id="batchInsert" parameterType="map">
insert into api_definition_module
(id, `name`, protocol, parent_id, project_id, `level`, pos, create_time, update_time,
update_user, create_user)
(id, `name`, protocol, parent_id, project_id, pos, create_time, update_time, update_user,
create_user)
values
<foreach collection="list" item="item" separator=",">
(#{item.id,jdbcType=VARCHAR}, #{item.name,jdbcType=VARCHAR}, #{item.protocol,jdbcType=VARCHAR},
#{item.parentId,jdbcType=VARCHAR}, #{item.projectId,jdbcType=VARCHAR}, #{item.level,jdbcType=INTEGER},
#{item.pos,jdbcType=INTEGER}, #{item.createTime,jdbcType=BIGINT}, #{item.updateTime,jdbcType=BIGINT},
#{item.updateUser,jdbcType=VARCHAR}, #{item.createUser,jdbcType=VARCHAR})
#{item.parentId,jdbcType=VARCHAR}, #{item.projectId,jdbcType=VARCHAR}, #{item.pos,jdbcType=BIGINT},
#{item.createTime,jdbcType=BIGINT}, #{item.updateTime,jdbcType=BIGINT}, #{item.updateUser,jdbcType=VARCHAR},
#{item.createUser,jdbcType=VARCHAR})
</foreach>
</insert>
<insert id="batchInsertSelective" parameterType="map">
@ -340,11 +325,8 @@
<if test="'project_id'.toString() == column.value">
#{item.projectId,jdbcType=VARCHAR}
</if>
<if test="'level'.toString() == column.value">
#{item.level,jdbcType=INTEGER}
</if>
<if test="'pos'.toString() == column.value">
#{item.pos,jdbcType=INTEGER}
#{item.pos,jdbcType=BIGINT}
</if>
<if test="'create_time'.toString() == column.value">
#{item.createTime,jdbcType=BIGINT}

View File

@ -61,34 +61,32 @@ CREATE INDEX idx_create_user ON api_debug_module(create_user);
DROP TABLE IF EXISTS api_definition;
CREATE TABLE api_definition(
`id` VARCHAR(50) NOT NULL COMMENT '接口pk' ,
`name` VARCHAR(255) NOT NULL COMMENT '接口名称' ,
`protocol` VARCHAR(20) NOT NULL COMMENT '接口协议' ,
`method` VARCHAR(20) COMMENT 'http协议类型post/get/其它协议则是协议名(mqtt)' ,
`path` VARCHAR(500) COMMENT 'http协议路径/其它协议则为空' ,
`status` VARCHAR(50) NOT NULL COMMENT '接口状态/进行中/已完成' ,
`num` INT COMMENT '自定义id' ,
`tags` VARCHAR(500) COMMENT '标签' ,
`pos` BIGINT NOT NULL COMMENT '自定义排序' ,
`project_id` VARCHAR(50) NOT NULL COMMENT '项目fk' ,
`module_id` VARCHAR(50) DEFAULT 'NONE' COMMENT '模块fk' ,
`environment_id` VARCHAR(50) COMMENT '环境fk' ,
`latest` BIT(1) NOT NULL DEFAULT 0 COMMENT '是否为最新版本 0:否1:是' ,
`version_id` VARCHAR(50) COMMENT '版本fk' ,
`ref_id` VARCHAR(50) COMMENT '版本引用fk' ,
`description` VARCHAR(500) COMMENT '描述' ,
`create_time` BIGINT NOT NULL COMMENT '创建时间' ,
`create_user` VARCHAR(50) NOT NULL COMMENT '创建人' ,
`update_time` BIGINT NOT NULL COMMENT '修改时间' ,
`update_user` VARCHAR(50) NOT NULL COMMENT '修改人' ,
`delete_user` VARCHAR(50) COMMENT '删除人' ,
`delete_time` BIGINT COMMENT '删除时间' ,
`deleted` BIT(1) NOT NULL DEFAULT 0 COMMENT '删除状态' ,
CREATE TABLE api_definition
(
`id` VARCHAR(50) NOT NULL COMMENT '接口pk',
`name` VARCHAR(255) NOT NULL COMMENT '接口名称',
`protocol` VARCHAR(20) NOT NULL COMMENT '接口协议',
`method` VARCHAR(20) COMMENT 'http协议类型post/get/其它协议则是协议名(mqtt)',
`path` VARCHAR(500) COMMENT 'http协议路径/其它协议则为空',
`status` VARCHAR(50) NOT NULL COMMENT '接口状态/进行中/已完成',
`num` BIGINT NOT NULL COMMENT '自定义id',
`tags` VARCHAR(500) COMMENT '标签',
`pos` BIGINT NOT NULL COMMENT '自定义排序',
`project_id` VARCHAR(50) NOT NULL COMMENT '项目fk',
`module_id` VARCHAR(50) NOT NULL DEFAULT 'root' COMMENT '模块fk',
`latest` BIT(1) NOT NULL DEFAULT 0 COMMENT '是否为最新版本 0:否1:是',
`version_id` VARCHAR(50) NOT NULL COMMENT '版本fk',
`ref_id` VARCHAR(50) NOT NULL COMMENT '版本引用fk',
`description` VARCHAR(500) COMMENT '描述',
`create_time` BIGINT NOT NULL COMMENT '创建时间',
`create_user` VARCHAR(50) NOT NULL COMMENT '创建人',
`update_time` BIGINT NOT NULL COMMENT '修改时间',
`update_user` VARCHAR(50) NOT NULL COMMENT '修改人',
`delete_user` VARCHAR(50) COMMENT '删除人',
`delete_time` BIGINT COMMENT '删除时间',
`deleted` BIT(1) NOT NULL DEFAULT 0 COMMENT '删除状态',
PRIMARY KEY (id)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci COMMENT = '接口定义';
) COMMENT = '接口定义';
CREATE INDEX idx_project_id ON api_definition(project_id);
@ -112,7 +110,7 @@ CREATE TABLE api_environment_config(
PRIMARY KEY (id)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci COMMENT = '接口定义公共部分环境-建议干掉这个功能';
COLLATE = utf8mb4_general_ci COMMENT = '接口定义公共部分环境';
DROP TABLE IF EXISTS api_report;
CREATE TABLE api_report(
@ -160,10 +158,9 @@ DROP TABLE IF EXISTS api_definition_module;
CREATE TABLE api_definition_module(
`id` VARCHAR(50) NOT NULL COMMENT '接口模块pk' ,
`name` VARCHAR(255) NOT NULL COMMENT '模块名称' ,
`protocol` VARCHAR(64) NOT NULL COMMENT '协议' ,
`protocol` VARCHAR(20) NOT NULL COMMENT '协议' ,
`parent_id` VARCHAR(50) NOT NULL DEFAULT 'NONE' COMMENT '父级fk' ,
`project_id` VARCHAR(50) NOT NULL COMMENT '项目fk' ,
`level` INT NOT NULL DEFAULT 1 COMMENT '树节点级别' ,
`pos` INT NOT NULL COMMENT '排序' ,
`create_time` BIGINT NOT NULL COMMENT '创建时间' ,
`update_time` BIGINT NOT NULL COMMENT '修改时间' ,

View File

@ -235,4 +235,14 @@ public class PermissionConstants {
public static final String BUG_UPDATE = "BUG:READ+UPDATE";
public static final String BUG_DELETE = "BUG:READ+DELETE";
/*------ end: BUG ------*/
/*------ start: API_MANAGEMENT ------*/
public static final String PROJECT_API_DEFINITION_READ = "PROJECT_API_DEFINITION:READ";
public static final String PROJECT_API_DEFINITION_READ_ADD = "PROJECT_API_DEFINITION:READ+ADD";
public static final String PROJECT_API_DEFINITION_READ_UPDATE = "PROJECT_API_DEFINITION:READ+UPDATE";
public static final String PROJECT_API_DEFINITION_READ_DELETE = "PROJECT_API_DEFINITION:READ+DELETE";
public static final String PROJECT_API_DEFINITION_READ_IMPORT = "PROJECT_API_DEFINITION:READ+IMPORT";
public static final String PROJECT_API_DEFINITION_READ_EXPORT = "PROJECT_API_DEFINITION:READ+EXPORT";
public static final String PROJECT_API_DEFINITION_READ_EXECUTE = "PROJECT_API_DEFINITION:READ+EXECUTE";
/*------ end: API_DEBUG ------*/
}

View File

@ -111,6 +111,9 @@ api_definition.project_id.length_range=项目ID长度必须在1-50之间
api_definition.project_id.not_blank=项目ID不能为空
api_definition.latest.length_range=是否为最新版本 0:否1:是长度必须在1-1之间
api_definition.latest.not_blank=是否为最新版本 0:否1:是不能为空
api_definition.module_id.not_blank=模块ID不能为空
api_definition.version_id.not_blank=版本ID不能为空
api_definition.ref_id.not_blank=引用ID不能为空
#moduleApiDefinitionFollow
api_definition_follow.api_definition_id.length_range=接口ID长度必须在1-50之间
api_definition_follow.api_definition_id.not_blank=接口ID不能为空
@ -213,14 +216,15 @@ api_definition_module.update_user.length_range=修改人长度必须在1-50之
api_definition_module.update_user.not_blank=修改人不能为空
api_definition_module.create_user.length_range=创建人长度必须在1-50之间
api_definition_module.create_user.not_blank=创建人不能为空
api_definition_module.name.length_range=模块名称长度必须在1-64之间
api_definition_module.name.length_range=模块名称长度必须在1-255之间
api_definition_module.name.not_blank=模块名称不能为空
api_definition_module.protocol.length_range=协议长度必须在1-64之间
api_definition_module.protocol.length_range=协议长度必须在1-20之间
api_definition_module.protocol.not_blank=协议不能为空
api_definition_module.parent_id.length_range=父级ID长度必须在1-50之间
api_definition_module.parent_id.not_blank=父级ID不能为空
api_definition_module.project_id.length_range=项目ID长度必须在1-50之间
api_definition_module.project_id.not_blank=项目ID不能为空
api_definition_module.pos.not_blank=模块位置不能为空
#moduleApiDefinitionMockConfig
api_definition_mock_config.api_definition_mock_id.not_blank=接口mock pk不能为空
#moduleApiScenarioModule

View File

@ -111,6 +111,9 @@ api_definition.project_id.length_range=Item fk length must be between 1-50
api_definition.project_id.not_blank=Item fk cannot be empty
api_definition.latest.length_range=Is it the latest version 0: No, 1: Yes The length must be between 1-1
api_definition.latest.not_blank=Is it the latest version 0: No, 1: Yes Cannot be empty
api_definition.module_id.not_blank=Module fk cannot be empty
api_definition.version_id.not_blank=Version fk cannot be empty
api_definition.ref_id.not_blank=Reference fk cannot be empty
#moduleApiDefinitionFollow
api_definition_follow.api_definition_id.length_range=Interface fk length must be between 1-50
api_definition_follow.api_definition_id.not_blank=Interface fk cannot be empty
@ -213,14 +216,15 @@ api_definition_module.update_user.length_range=Modifier length must be between 1
api_definition_module.update_user.not_blank=Modifier cannot be empty
api_definition_module.create_user.length_range=Creator length must be between 1-50
api_definition_module.create_user.not_blank=Creator cannot be empty
api_definition_module.name.length_range=Module name length must be between 1-64
api_definition_module.name.length_range=Module name length must be between 1-255
api_definition_module.name.not_blank=Module name cannot be empty
api_definition_module.protocol.length_range=Protocol length must be between 1-64
api_definition_module.protocol.length_range=Protocol length must be between 1-20
api_definition_module.protocol.not_blank=Agreement cannot be empty
api_definition_module.parent_id.length_range=Parent fk length must be between 1-50
api_definition_module.parent_id.not_blank=parent fk cannot be empty
api_definition_module.project_id.length_range=Item fk length must be between 1-50
api_definition_module.project_id.not_blank=Item fk cannot be empty
api_definition_module.pos.not_blank=Module position cannot be empty
#moduleApiDefinitionMockConfig
api_definition_mock_config.api_definition_mock_id.not_blank=Interface mock pk cannot be empty
#moduleApiScenarioModule
@ -275,6 +279,7 @@ api_debug_module.project_id.length_range=Project ID length must be between 1-50
api_debug_module.pos.not_blank=Module position cannot be blank
api_debug_module.name.not_contain_slash=Module name cannot contain slashes
api_debug_module.unplanned_request=Unplanned request
api_unplanned_request=Unplanned Api
#module: ApiEnvironmentConfig
api_environment_config.id.not_blank=ID不能为空

View File

@ -111,6 +111,9 @@ api_definition.project_id.length_range=项目ID长度必须在1-50之间
api_definition.project_id.not_blank=项目ID不能为空
api_definition.latest.length_range=是否为最新版本 0:否1:是长度必须在1-1之间
api_definition.latest.not_blank=是否为最新版本 0:否1:是不能为空
api_definition.module_id.not_blank=模块ID不能为空
api_definition.version_id.not_blank=版本ID不能为空
api_definition.ref_id.not_blank=引用ID不能为空
#moduleApiDefinitionFollow
api_definition_follow.api_definition_id.length_range=接口ID长度必须在1-50之间
api_definition_follow.api_definition_id.not_blank=接口ID不能为空
@ -213,14 +216,15 @@ api_definition_module.update_user.length_range=修改人长度必须在1-50之
api_definition_module.update_user.not_blank=修改人不能为空
api_definition_module.create_user.length_range=创建人长度必须在1-50之间
api_definition_module.create_user.not_blank=创建人不能为空
api_definition_module.name.length_range=模块名称长度必须在1-64之间
api_definition_module.name.length_range=模块名称长度必须在1-255之间
api_definition_module.name.not_blank=模块名称不能为空
api_definition_module.protocol.length_range=协议长度必须在1-64之间
api_definition_module.protocol.length_range=协议长度必须在1-20之间
api_definition_module.protocol.not_blank=协议不能为空
api_definition_module.parent_id.length_range=父级ID长度必须在1-50之间
api_definition_module.parent_id.not_blank=父级ID不能为空
api_definition_module.project_id.length_range=项目ID长度必须在1-50之间
api_definition_module.project_id.not_blank=项目ID不能为空
api_definition_module.pos.not_blank=模块位置不能为空
#moduleApiDefinitionMockConfig
api_definition_mock_config.api_definition_mock_id.not_blank=接口mock pk不能为空
#moduleApiScenarioModule
@ -275,6 +279,7 @@ api_debug_module.project_id.length_range=项目ID长度必须在1-50之间
api_debug_module.pos.not_blank=模块位置不能为空
api_debug_module.name.not_contain_slash=名称中不能包含正反斜杠
api_debug_module.unplanned_request=未规划请求
api_unplanned_request=未规划接口
#module: ApiEnvironmentConfig
api_environment_config.id.not_blank=ID不能为空

View File

@ -111,6 +111,9 @@ api_definition.project_id.length_range=項目ID長度必須在1-50之間
api_definition.project_id.not_blank=項目ID不能為空
api_definition.latest.length_range=是否為最新版本 0:否1:是長度必須在1-1之間
api_definition.latest.not_blank=是否為最新版本 0:否1:是不能為空
api_definition.module_id.not_blank=模塊ID不能為空
api_definition.version_id.not_blank=版本ID不能為空
api_definition.ref_id.not_blank=引用ID不能為空
#moduleApiDefinitionFollow
api_definition_follow.api_definition_id.length_range=接口ID長度必須在1-50之間
api_definition_follow.api_definition_id.not_blank=接口ID不能為空
@ -213,14 +216,15 @@ api_definition_module.update_user.length_range=修改人長度必須在1-50之
api_definition_module.update_user.not_blank=修改人不能為空
api_definition_module.create_user.length_range=創建人長度必須在1-50之間
api_definition_module.create_user.not_blank=創建人不能為空
api_definition_module.name.length_range=模塊名稱長度必須在1-64之間
api_definition_module.name.length_range=模塊名稱長度必須在1-255之間
api_definition_module.name.not_blank=模塊名稱不能為空
api_definition_module.protocol.length_range=協議長度必須在1-64之間
api_definition_module.protocol.length_range=協議長度必須在1-20之間
api_definition_module.protocol.not_blank=協議不能為空
api_definition_module.parent_id.length_range=父級ID長度必須在1-50之間
api_definition_module.parent_id.not_blank=父級ID不能為空
api_definition_module.project_id.length_range=項目ID長度必須在1-50之間
api_definition_module.project_id.not_blank=項目ID不能為空
api_definition_module.pos.not_blank=模塊位置不能為空
#moduleApiDefinitionMockConfig
api_definition_mock_config.api_definition_mock_id.not_blank=接口mock pk不能為空
#moduleApiScenarioModule
@ -275,6 +279,7 @@ api_debug_module.project_id.length_range=項目ID長度必須在1-50之間
api_debug_module.pos.not_blank=模塊位置不能為空
api_debug_module.name.not_contain_slash=模塊名稱不能包含斜線
api_debug_module.unplanned_request=未規劃請求
api_unplanned_request=未规划接口
#module: ApiEnvironmentConfig
api_environment_config.id.not_blank=ID不能為空

View File

@ -463,4 +463,11 @@ status_item.bug_new=新建
status_item.bug_in_process=处理中
status_item.bug_closed=已关闭
status_item.bug_resolved=已解决
status_item.bug_rejected=已拒绝
status_item.bug_rejected=已拒绝
permission.api_test.name=接口测试
permission.api_debug.name=接口调试
permission.api_definition.name=接口管理
permission.api_definition.import=导入
permission.api_definition.export=导出
permission.api_definition.execute=执行

View File

@ -472,4 +472,11 @@ status_item.bug_new=NEW
status_item.bug_in_process=IN PROCESS
status_item.bug_closed=CLOSED
status_item.bug_resolved=RESOLVED
status_item.bug_rejected=REJECTED
status_item.bug_rejected=REJECTED
permission.api_test.name=API Test
permission.api_debug.name=API Debug
permission.api_definition.name=API Management
permission.api_definition.import=Import
permission.api_definition.export=Export
permission.api_definition.execute=Execute

View File

@ -468,4 +468,11 @@ status_item.bug_new=新建
status_item.bug_in_process=处理中
status_item.bug_closed=已关闭
status_item.bug_resolved=已解决
status_item.bug_rejected=已拒绝
status_item.bug_rejected=已拒绝
permission.api_test.name=接口测试
permission.api_debug.name=接口调试
permission.api_definition.name=接口管理
permission.api_definition.import=导入
permission.api_definition.export=导出
permission.api_definition.execute=执行

View File

@ -468,4 +468,11 @@ status_item.bug_new=新建
status_item.bug_in_process=處理中
status_item.bug_closed=已關閉
status_item.bug_resolved=已解決
status_item.bug_rejected=已拒絕
status_item.bug_rejected=已拒絕
permission.api_test.name=接口測試
permission.api_debug.name=接口調試
permission.api_definition.name=接口管理
permission.api_definition.import=導入
permission.api_definition.export=導出
permission.api_definition.execute=執行

View File

@ -1,8 +1,8 @@
package io.metersphere.api.controller.debug;
import io.metersphere.api.dto.debug.ApiDebugRequest;
import io.metersphere.api.dto.debug.DebugModuleCreateRequest;
import io.metersphere.api.dto.debug.DebugModuleUpdateRequest;
import io.metersphere.api.dto.debug.ModuleCreateRequest;
import io.metersphere.api.dto.debug.ModuleUpdateRequest;
import io.metersphere.api.service.debug.ApiDebugModuleService;
import io.metersphere.sdk.constants.PermissionConstants;
import io.metersphere.system.dto.sdk.BaseTreeNode;
@ -36,14 +36,14 @@ public class ApiDebugModuleController {
@PostMapping("/add")
@Operation(summary = "接口测试-接口调试-模块-添加模块")
@RequiresPermissions(PermissionConstants.PROJECT_API_DEBUG_READ_ADD)
public String add(@RequestBody @Validated DebugModuleCreateRequest request) {
public String add(@RequestBody @Validated ModuleCreateRequest request) {
return apiDebugModuleService.add(request, SessionUtils.getUserId());
}
@PostMapping("/update")
@Operation(summary = "接口测试-接口调试-模块-修改模块")
@RequiresPermissions(PermissionConstants.PROJECT_API_DEBUG_READ_UPDATE)
public boolean list(@RequestBody @Validated DebugModuleUpdateRequest request) {
public boolean list(@RequestBody @Validated ModuleUpdateRequest request) {
apiDebugModuleService.update(request, SessionUtils.getUserId(), SessionUtils.getCurrentProjectId());
return true;
}

View File

@ -0,0 +1,71 @@
package io.metersphere.api.controller.definition;
import io.metersphere.api.dto.debug.ModuleCreateRequest;
import io.metersphere.api.dto.debug.ModuleUpdateRequest;
import io.metersphere.api.dto.definition.ApiModuleRequest;
import io.metersphere.api.service.definition.ApiDefinitionModuleService;
import io.metersphere.sdk.constants.PermissionConstants;
import io.metersphere.system.dto.sdk.BaseTreeNode;
import io.metersphere.system.dto.sdk.request.NodeMoveRequest;
import io.metersphere.system.utils.SessionUtils;
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.*;
import java.util.List;
import java.util.Map;
@Tag(name = "接口测试-接口管理-模块")
@RestController
@RequestMapping("/api/definition/module")
public class ApiDefinitionModuleController {
@Resource
private ApiDefinitionModuleService apiDefinitionModuleService;
@PostMapping("/tree")
@Operation(summary = "接口测试-接口管理-模块-查找模块")
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_READ)
public List<BaseTreeNode> getTree(@RequestBody @Validated ApiModuleRequest request) {
return apiDefinitionModuleService.getTree(request);
}
@PostMapping("/add")
@Operation(summary = "接口测试-接口管理-模块-添加模块")
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_READ_ADD)
public String add(@RequestBody @Validated ModuleCreateRequest request) {
return apiDefinitionModuleService.add(request, SessionUtils.getUserId());
}
@PostMapping("/update")
@Operation(summary = "接口测试-接口管理-模块-修改模块")
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_READ_UPDATE)
public boolean list(@RequestBody @Validated ModuleUpdateRequest request) {
apiDefinitionModuleService.update(request, SessionUtils.getUserId());
return true;
}
@GetMapping("/delete/{deleteId}")
@Operation(summary = "接口测试-接口管理-模块-删除模块")
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_READ_DELETE)
public void deleteNode(@PathVariable String deleteId) {
apiDefinitionModuleService.deleteModule(deleteId, SessionUtils.getUserId());
}
@PostMapping("/move")
@Operation(summary = "接口测试-接口管理-模块-移动模块")
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_READ_UPDATE)
public void moveNode(@Validated @RequestBody NodeMoveRequest request) {
apiDefinitionModuleService.moveNode(request, SessionUtils.getUserId());
}
@PostMapping("/count")
@Operation(summary = "接口测试-接口管理-模块-统计模块数量")
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_READ)
public Map<String, Long> moduleCount(@Validated @RequestBody ApiModuleRequest request) {
return apiDefinitionModuleService.moduleCount(request);
}
}

View File

@ -11,7 +11,7 @@ import jakarta.validation.constraints.Size;
import lombok.Data;
@Data
public class DebugModuleCreateRequest {
public class ModuleCreateRequest {
@Schema(description = "项目ID", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{project.id.not_blank}")

View File

@ -7,7 +7,7 @@ import jakarta.validation.constraints.Pattern;
import lombok.Data;
@Data
public class DebugModuleUpdateRequest {
public class ModuleUpdateRequest {
@Schema(description = "模块ID", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{file_module.id.not_blank}")
private String id;

View File

@ -0,0 +1,27 @@
package io.metersphere.api.dto.definition;
import io.metersphere.sdk.constants.ModuleConstants;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.Data;
import java.util.List;
@Data
public class ApiModuleRequest {
@Schema(description = "模块ID(根据模块树查询时要把当前节点以及子节点都放在这里。)")
private List<String> moduleIds;
@Schema(description = "协议", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{api_definition_module.protocol.not_blank}")
@Size(min = 1, max = 20, message = "{api_definition_module.protocol.length_range}")
private String protocol = ModuleConstants.NODE_PROTOCOL_HTTP;
@Schema(description = "项目ID", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{api_definition_module.project_id.not_blank}")
@Size(min = 1, max = 50, message = "{api_definition_module.project_id.length_range}")
private String projectId;
@Schema(description = "关键字")
private String keyword;
}

View File

@ -17,6 +17,8 @@ public interface ExtApiDebugModuleMapper {
List<String> selectChildrenIdsByParentIds(@Param("ids") List<String> deleteIds);
List<BaseTreeNode> selectBaseNodeByIds(@Param("ids") List<String> ids);
List<String> selectChildrenIdsSortByPos(String parentId);
void deleteByIds(@Param("ids") List<String> deleteId);

View File

@ -103,6 +103,17 @@
</if>
LIMIT 1
</select>
<select id="selectBaseNodeByIds" resultType="io.metersphere.system.dto.sdk.BaseTreeNode">
SELECT id,
NAME,
parent_id AS parentId,
'module' AS type
FROM api_debug_module
WHERE id IN
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</select>
<sql id="debug_page_request">
<where>

View File

@ -0,0 +1,9 @@
package io.metersphere.api.mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface ExtApiDefinitionMapper {
void deleteApiToGc(@Param("ids") List<String> ids, @Param("userId") String userId, @Param("time") long time);
}

View File

@ -0,0 +1,14 @@
<?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.ExtApiDefinitionMapper">
<update id="deleteApiToGc">
update api_definition
set delete_user = #{userId},delete_time = #{time}, deleted = 1
where ref_id in
<foreach collection="ids" item="v" separator="," open="(" close=")">
#{v}
</foreach>
</update>
</mapper>

View File

@ -0,0 +1,35 @@
package io.metersphere.api.mapper;
import io.metersphere.api.dto.debug.ApiTreeNode;
import io.metersphere.api.dto.definition.ApiModuleRequest;
import io.metersphere.project.dto.ModuleCountDTO;
import io.metersphere.project.dto.NodeSortQueryParam;
import io.metersphere.system.dto.sdk.BaseModule;
import io.metersphere.system.dto.sdk.BaseTreeNode;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface ExtApiDefinitionModuleMapper {
List<BaseTreeNode> selectBaseByRequest(@Param("request") ApiModuleRequest request);
List<BaseTreeNode> selectIdAndParentIdByRequest(@Param("request") ApiModuleRequest request);
List<String> selectChildrenIdsByParentIds(@Param("ids") List<String> deleteIds);
List<String> selectChildrenIdsSortByPos(String parentId);
void deleteByIds(@Param("ids") List<String> deleteId);
Long getMaxPosByParentId(String parentId);
BaseModule selectBaseModuleById(String dragNodeId);
BaseModule selectModuleByParentIdAndPosOperator(NodeSortQueryParam nodeSortQueryParam);
List<ApiTreeNode> selectApiDataByRequest(@Param("request") ApiModuleRequest request);
List<ModuleCountDTO> countModuleIdByRequest(@Param("request") ApiModuleRequest request);
List<BaseTreeNode> selectNodeByIds(@Param("ids") List<String> ids);
}

View File

@ -0,0 +1,169 @@
<?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.ExtApiDefinitionModuleMapper">
<select id="selectIdAndParentIdByRequest" resultType="io.metersphere.system.dto.sdk.BaseTreeNode">
SELECT m.id,
m.parent_id AS parentId
FROM api_definition_module m
<include refid="module_request"/>
ORDER BY pos
</select>
<select id="selectIdsByProjectId" resultType="java.lang.String">
SELECT id
FROM api_definition_module
WHERE project_id = #{0}
</select>
<select id="selectChildrenIdsByParentIds" resultType="java.lang.String">
SELECT id
FROM api_definition_module
WHERE parent_id IN
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</select>
<delete id="deleteByIds">
DELETE
FROM api_definition_module
WHERE id IN
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
<select id="getMaxPosByParentId" resultType="java.lang.Long">
SELECT max(pos)
FROM api_definition_module
WHERE parent_id = #{0}
</select>
<select id="selectChildrenIdsSortByPos" resultType="java.lang.String">
SELECT id
FROM api_definition_module
WHERE parent_id = #{0}
ORDER BY pos ASC
</select>
<select id="getLastModuleByParentId" resultType="io.metersphere.api.domain.ApiDebugModule">
SELECT *
FROM api_definition_module
WHERE parent_id = #{0}
ORDER BY pos DESC
LIMIT 1
</select>
<select id="selectApiDataByRequest" resultType="io.metersphere.api.dto.debug.ApiTreeNode">
SELECT id,
NAME,
module_id AS parentId,
'api' AS type,
method
FROM api_definition
<include refid="api_request"/>
ORDER BY update_time DESC
</select>
<select id="countModuleIdByRequest" resultType="io.metersphere.project.dto.ModuleCountDTO">
SELECT module_id AS moduleId, count(id) AS dataCount
FROM api_definition
<include refid="api_request"/>
GROUP BY api_definition.module_id
</select>
<select id="selectBaseModuleById" resultType="io.metersphere.system.dto.sdk.BaseModule">
SELECT id, name, pos, project_Id, parent_id
FROM api_definition_module
WHERE id = #{0}
</select>
<select id="selectModuleByParentIdAndPosOperator"
parameterType="io.metersphere.project.dto.NodeSortQueryParam"
resultType="io.metersphere.system.dto.sdk.BaseModule">
SELECT id, name, pos, project_Id, parent_id
FROM api_definition_module
WHERE parent_id = #{parentId}
<if test="operator == 'moreThan'">
AND pos &gt; #{pos}
</if>
<if test="operator == 'lessThan'">
AND pos &lt; #{pos}
</if>
ORDER BY pos
<if test="operator == 'lessThan' or operator == 'latest'">
DESC
</if>
LIMIT 1
</select>
<select id="selectBaseByRequest" resultType="io.metersphere.system.dto.sdk.BaseTreeNode">
SELECT m.id,
m.parent_id AS parentId,
m.name,
m.pos,
m.project_id,
'module' AS type
FROM api_definition_module m
<include refid="module_request"/>
ORDER BY pos
</select>
<select id="selectNodeByIds" resultType="io.metersphere.system.dto.sdk.BaseTreeNode">
SELECT m.id,
m.parent_id AS parentId,
m.name,
m.pos,
m.project_id,
'module' AS type
FROM api_definition_module m
WHERE m.id IN
<foreach collection="ids" item="id" open="(" separator="," close=")">
#{id}
</foreach>
ORDER BY pos
</select>
<sql id="api_request">
<where>
api_definition.deleted = 0
<if test="request.projectId != null and request.projectId != ''">
AND api_definition.project_id = #{request.projectId}
</if>
<if test="request.keyword != null and request.keyword != ''">
AND api_definition.name like CONCAT('%', #{request.keyword},'%')
</if>
<if test="request.moduleIds != null and request.moduleIds.size() != 0">
AND api_definition.module_id IN
<foreach collection="request.moduleIds" item="item" open="(" separator="," close=")">
#{item}
</foreach>
</if>
<if test="request.protocol != null and request.protocol != ''">
AND api_definition.protocol = #{request.protocol}
</if>
AND api_definition.latest = 1
<!--<if test="request.versionId != null and request.versionId != ''">
and api_definition.version_id = #{request.versionId}
</if>
<if test="request.refId != null and request.refId != ''">
and api_definition.ref_id = #{request.refId}
</if>
<if test="request.versionId == null and request.refId == null and request.id == null">
AND api_definition.latest = 1
</if>-->
</where>
</sql>
<sql id="module_request">
<where>
<if test="request.projectId != null and request.projectId != ''">
AND m.project_id = #{request.projectId}
</if>
<if test="request.keyword != null and request.keyword != ''">
AND m.name like CONCAT('%', #{request.keyword},'%')
</if>
<if test="request.moduleIds != null and request.moduleIds.size() != 0">
AND m.module_id IN
<foreach collection="request.moduleIds" item="item" open="(" separator="," close=")">
#{item}
</foreach>
</if>
<if test="request.protocol != null and request.protocol != ''">
AND m.protocol = #{request.protocol}
</if>
</where>
</sql>
</mapper>

View File

@ -1,5 +1,6 @@
package io.metersphere.api.service.debug;
import io.metersphere.api.domain.ApiDebug;
import io.metersphere.api.domain.ApiDebugModule;
import io.metersphere.project.domain.Project;
import io.metersphere.project.dto.NodeSortDTO;
@ -9,6 +10,7 @@ import io.metersphere.sdk.util.JSON;
import io.metersphere.sdk.util.Translator;
import io.metersphere.system.dto.builder.LogDTOBuilder;
import io.metersphere.system.dto.sdk.BaseModule;
import io.metersphere.system.dto.sdk.BaseTreeNode;
import io.metersphere.system.log.constants.OperationLogModule;
import io.metersphere.system.log.constants.OperationLogType;
import io.metersphere.system.log.dto.LogDTO;
@ -18,6 +20,9 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import java.util.ArrayList;
import java.util.List;
@Service
@Transactional(rollbackFor = Exception.class)
public class ApiDebugModuleLogService {
@ -68,21 +73,46 @@ public class ApiDebugModuleLogService {
operationLogService.add(dto);
}
public void saveDeleteLog(ApiDebugModule deleteModule, String operator) {
Project project = projectMapper.selectByPrimaryKey(deleteModule.getProjectId());
LogDTO dto = LogDTOBuilder.builder()
.projectId(deleteModule.getProjectId())
.organizationId(project.getOrganizationId())
.type(OperationLogType.DELETE.name())
.module(OperationLogModule.API_DEBUG)
.method(HttpMethodConstants.GET.name())
.path(DELETE + "/%s")
.sourceId(deleteModule.getId())
.content(deleteModule.getName() + " " + Translator.get("file.log.delete_module"))
.originalValue(JSON.toJSONBytes(deleteModule))
.createUser(operator)
.build().getLogDTO();
operationLogService.add(dto);
public void saveDeleteModuleLog(List<BaseTreeNode> deleteModule, String operator, String projectId) {
Project project = projectMapper.selectByPrimaryKey(projectId);
List<LogDTO> dtos = new ArrayList<>();
deleteModule.forEach(item -> {
LogDTO dto = LogDTOBuilder.builder()
.projectId(project.getId())
.organizationId(project.getOrganizationId())
.type(OperationLogType.DELETE.name())
.module(OperationLogModule.API_DEBUG)
.method(HttpMethodConstants.GET.name())
.path(DELETE + "/%s")
.sourceId(item.getId())
.content(item.getName() + " " + Translator.get("file.log.delete_module"))
.createUser(operator)
.build().getLogDTO();
dtos.add(dto);
}
);
operationLogService.batchAdd(dtos);
}
public void saveDeleteDataLog(List<ApiDebug> deleteData, String operator, String projectId) {
Project project = projectMapper.selectByPrimaryKey(projectId);
List<LogDTO> logs = new ArrayList<>();
deleteData.forEach(item -> {
LogDTO dto = LogDTOBuilder.builder()
.projectId(project.getId())
.organizationId(project.getOrganizationId())
.type(OperationLogType.DELETE.name())
.module(OperationLogModule.API_DEBUG)
.method(HttpMethodConstants.GET.name())
.path(DELETE + "/%s")
.sourceId(item.getId())
.content(item.getName())
.createUser(operator)
.build().getLogDTO();
logs.add(dto);
}
);
operationLogService.batchAdd(logs);
}
public void saveMoveLog(@Validated NodeSortDTO request, String operator) {

View File

@ -3,8 +3,8 @@ package io.metersphere.api.service.debug;
import io.metersphere.api.domain.*;
import io.metersphere.api.dto.debug.ApiDebugRequest;
import io.metersphere.api.dto.debug.ApiTreeNode;
import io.metersphere.api.dto.debug.DebugModuleCreateRequest;
import io.metersphere.api.dto.debug.DebugModuleUpdateRequest;
import io.metersphere.api.dto.debug.ModuleCreateRequest;
import io.metersphere.api.dto.debug.ModuleUpdateRequest;
import io.metersphere.api.mapper.ApiDebugBlobMapper;
import io.metersphere.api.mapper.ApiDebugMapper;
import io.metersphere.api.mapper.ApiDebugModuleMapper;
@ -28,7 +28,9 @@ import org.mybatis.spring.SqlSessionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Service
@ -55,7 +57,11 @@ public class ApiDebugModuleService extends ModuleTreeService {
List<BaseTreeNode> fileModuleList = extApiDebugModuleMapper.selectBaseByProtocolAndUser(protocol, userId);
List<BaseTreeNode> baseTreeNodes = super.buildTreeAndCountResource(fileModuleList, true, Translator.get(UNPLANNED));
List<ApiTreeNode> apiTreeNodeList = extApiDebugModuleMapper.selectApiDebugByProtocolAndUser(protocol, userId);
//将apiTreeNodeList转换成BaseTreeNode method放入map中
return getBaseTreeNodes(apiTreeNodeList, baseTreeNodes);
}
public List<BaseTreeNode> getBaseTreeNodes(List<ApiTreeNode> apiTreeNodeList, List<BaseTreeNode> baseTreeNodes) {
if (CollectionUtils.isEmpty(apiTreeNodeList)) {
return baseTreeNodes;
}
@ -72,11 +78,10 @@ public class ApiDebugModuleService extends ModuleTreeService {
Map<String, List<BaseTreeNode>> apiTreeNodeMap = nodeList.stream().collect(Collectors.groupingBy(BaseTreeNode::getParentId));
//遍历baseTreeNodes将apiTreeNodeMap中的id相等的数据添加到baseTreeNodes中
return generateTree(baseTreeNodes, apiTreeNodeMap);
}
//生成树结构
public List<BaseTreeNode> generateTree(List<BaseTreeNode> baseTreeNodes, Map<String, List<BaseTreeNode>> apiTreeNodeMap) {
private List<BaseTreeNode> generateTree(List<BaseTreeNode> baseTreeNodes, Map<String, List<BaseTreeNode>> apiTreeNodeMap) {
baseTreeNodes.forEach(baseTreeNode -> {
if (apiTreeNodeMap.containsKey(baseTreeNode.getId())) {
baseTreeNode.getChildren().addAll(apiTreeNodeMap.get(baseTreeNode.getId()));
@ -94,7 +99,7 @@ public class ApiDebugModuleService extends ModuleTreeService {
return super.buildTreeAndCountResource(fileModuleList, moduleCountDTOList, true, Translator.get(UNPLANNED));
}
public String add(DebugModuleCreateRequest request, String operator) {
public String add(ModuleCreateRequest request, String operator) {
ApiDebugModule apiDebugModule = new ApiDebugModule();
apiDebugModule.setId(IDGenerator.nextStr());
apiDebugModule.setName(request.getName());
@ -148,7 +153,7 @@ public class ApiDebugModuleService extends ModuleTreeService {
example.clear();
}
public void update(DebugModuleUpdateRequest request, String userId, String projectId) {
public void update(ModuleUpdateRequest request, String userId, String projectId) {
ApiDebugModule module = apiDebugModuleMapper.selectByPrimaryKey(request.getId());
if (module == null) {
throw new MSException(Translator.get(MODULE_NO_EXIST));
@ -172,17 +177,17 @@ public class ApiDebugModuleService extends ModuleTreeService {
public void deleteModule(String deleteId, String currentUser) {
ApiDebugModule deleteModule = apiDebugModuleMapper.selectByPrimaryKey(deleteId);
if (deleteModule != null) {
this.deleteModule(Collections.singletonList(deleteId));
//记录日志
apiDebugModuleLogService.saveDeleteLog(deleteModule, currentUser);
this.deleteModule(Collections.singletonList(deleteId), currentUser, deleteModule.getProjectId());
}
}
public void deleteModule(List<String> deleteIds) {
public void deleteModule(List<String> deleteIds, String currentUser, String projectId) {
if (CollectionUtils.isEmpty(deleteIds)) {
return;
}
List<BaseTreeNode> baseTreeNodes = extApiDebugModuleMapper.selectBaseNodeByIds(deleteIds);
extApiDebugModuleMapper.deleteByIds(deleteIds);
apiDebugModuleLogService.saveDeleteModuleLog(baseTreeNodes, currentUser, projectId);
//删除模块下的所有接口
ApiDebugExample example = new ApiDebugExample();
example.createCriteria().andModuleIdIn(deleteIds);
@ -193,11 +198,12 @@ public class ApiDebugModuleService extends ModuleTreeService {
ApiDebugBlobExample blobExample = new ApiDebugBlobExample();
blobExample.createCriteria().andIdIn(apiDebugIds);
apiDebugBlobMapper.deleteByExample(blobExample);
apiDebugModuleLogService.saveDeleteDataLog(apiDebugs, currentUser, projectId);
}
List<String> childrenIds = extApiDebugModuleMapper.selectChildrenIdsByParentIds(deleteIds);
if (CollectionUtils.isNotEmpty(childrenIds)) {
deleteModule(childrenIds);
deleteModule(childrenIds, currentUser, projectId);
}
}
@ -211,6 +217,9 @@ public class ApiDebugModuleService extends ModuleTreeService {
//节点换到了别的节点下,要先更新parent节点.
if (apiDebugModuleMapper.countByExample(example) == 0) {
ApiDebugModule fileModule = new ApiDebugModule();
ApiDebugModule currentModule = apiDebugModuleMapper.selectByPrimaryKey(request.getDragNodeId());
currentModule.setParentId(nodeSortDTO.getParent().getId());
checkDataValidity(currentModule);
fileModule.setId(request.getDragNodeId());
fileModule.setParentId(nodeSortDTO.getParent().getId());
apiDebugModuleMapper.updateByPrimaryKeySelective(fileModule);
@ -225,20 +234,9 @@ public class ApiDebugModuleService extends ModuleTreeService {
* 查找当前项目下模块每个节点对应的资源统计
*/
public Map<String, Long> getModuleCountMap(String protocol, String userId, List<ModuleCountDTO> moduleCountDTOList) {
Map<String, Long> returnMap = new HashMap<>();
//构建模块树并计算每个节点下的所有数量包含子节点
List<BaseTreeNode> treeNodeList = this.getTreeOnlyIdsAndResourceCount(protocol, userId, moduleCountDTOList);
//通过广度遍历的方式构建返回值
List<BaseTreeNode> whileList = new ArrayList<>(treeNodeList);
while (CollectionUtils.isNotEmpty(whileList)) {
List<BaseTreeNode> childList = new ArrayList<>();
for (BaseTreeNode treeNode : whileList) {
returnMap.put(treeNode.getId(), treeNode.getCount());
childList.addAll(treeNode.getChildren());
}
whileList = childList;
}
return returnMap;
return super.getIdCountMapByBreadth(treeNodeList);
}

View File

@ -0,0 +1,149 @@
package io.metersphere.api.service.definition;
import io.metersphere.api.domain.ApiDefinition;
import io.metersphere.api.domain.ApiDefinitionModule;
import io.metersphere.project.domain.Project;
import io.metersphere.project.dto.NodeSortDTO;
import io.metersphere.project.mapper.ProjectMapper;
import io.metersphere.sdk.constants.HttpMethodConstants;
import io.metersphere.sdk.util.JSON;
import io.metersphere.sdk.util.Translator;
import io.metersphere.system.dto.builder.LogDTOBuilder;
import io.metersphere.system.dto.sdk.BaseModule;
import io.metersphere.system.dto.sdk.BaseTreeNode;
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 jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import java.util.ArrayList;
import java.util.List;
@Service
@Transactional(rollbackFor = Exception.class)
public class ApiDefinitionModuleLogService {
private static final String API_DEBUG_MODULE = "/api/definition/module";
private static final String ADD = API_DEBUG_MODULE + "/add";
private static final String UPDATE = API_DEBUG_MODULE + "/update";
private static final String DELETE = API_DEBUG_MODULE + "/delete";
private static final String MOVE = API_DEBUG_MODULE + "/move";
private static final String MOVE_TO = "file.log.move_to";
@Resource
private ProjectMapper projectMapper;
@Resource
private OperationLogService operationLogService;
public void saveAddLog(ApiDefinitionModule module, String operator) {
Project project = projectMapper.selectByPrimaryKey(module.getProjectId());
LogDTO dto = LogDTOBuilder.builder()
.projectId(module.getProjectId())
.organizationId(project.getOrganizationId())
.type(OperationLogType.ADD.name())
.module(OperationLogModule.API_DEFINITION)
.method(HttpMethodConstants.POST.name())
.path(ADD)
.sourceId(module.getId())
.content(module.getName())
.originalValue(JSON.toJSONBytes(module))
.createUser(operator)
.build().getLogDTO();
operationLogService.add(dto);
}
public void saveUpdateLog(ApiDefinitionModule module, String operator) {
Project project = projectMapper.selectByPrimaryKey(module.getProjectId());
LogDTO dto = LogDTOBuilder.builder()
.projectId(project.getId())
.organizationId(project.getOrganizationId())
.type(OperationLogType.UPDATE.name())
.module(OperationLogModule.API_DEFINITION)
.method(HttpMethodConstants.POST.name())
.path(UPDATE)
.sourceId(module.getId())
.content(module.getName())
.originalValue(JSON.toJSONBytes(module))
.createUser(operator)
.build().getLogDTO();
operationLogService.add(dto);
}
public void saveDeleteModuleLog(List<BaseTreeNode> deleteModule, String operator, String projectId) {
List<LogDTO> dtoList = new ArrayList<>();
Project project = projectMapper.selectByPrimaryKey(projectId);
deleteModule.forEach(item -> {
LogDTO dto = LogDTOBuilder.builder()
.projectId(project.getId())
.organizationId(project.getOrganizationId())
.type(OperationLogType.DELETE.name())
.module(OperationLogModule.API_DEFINITION)
.method(HttpMethodConstants.GET.name())
.path(DELETE + "/%s")
.sourceId(item.getId())
.content(item.getName() + " " + Translator.get("file.log.delete_module"))
.createUser(operator)
.build().getLogDTO();
dtoList.add(dto);
});
operationLogService.batchAdd(dtoList);
}
public void saveDeleteDataLog(List<ApiDefinition> deleteData, String operator, String projectId) {
Project project = projectMapper.selectByPrimaryKey(projectId);
List<LogDTO> logs = new ArrayList<>();
deleteData.forEach(item -> {
LogDTO dto = LogDTOBuilder.builder()
.projectId(project.getId())
.organizationId(project.getOrganizationId())
.type(OperationLogType.DELETE.name())
.module(OperationLogModule.API_DEFINITION)
.method(HttpMethodConstants.GET.name())
.path(DELETE + "/%s")
.sourceId(item.getId())
.content(item.getName())
.createUser(operator)
.build().getLogDTO();
logs.add(dto);
}
);
operationLogService.batchAdd(logs);
}
public void saveMoveLog(@Validated NodeSortDTO request, String operator) {
BaseModule moveNode = request.getNode();
BaseModule previousNode = request.getPreviousNode();
BaseModule nextNode = request.getNextNode();
BaseModule parentModule = request.getParent();
Project project = projectMapper.selectByPrimaryKey(moveNode.getProjectId());
String logContent;
if (nextNode == null && previousNode == null) {
logContent = moveNode.getName() + " " + Translator.get(MOVE_TO) + parentModule.getName();
} else if (nextNode == null) {
logContent = moveNode.getName() + " " + Translator.get(MOVE_TO) + parentModule.getName() + " " + previousNode.getName() + Translator.get("file.log.next");
} else if (previousNode == null) {
logContent = moveNode.getName() + " " + Translator.get(MOVE_TO) + parentModule.getName() + " " + nextNode.getName() + Translator.get("file.log.previous");
} else {
logContent = moveNode.getName() + " " + Translator.get(MOVE_TO) + parentModule.getName() + " " +
previousNode.getName() + Translator.get("file.log.next") + " " + nextNode.getName() + Translator.get("file.log.previous");
}
LogDTO dto = LogDTOBuilder.builder()
.projectId(moveNode.getProjectId())
.organizationId(project.getOrganizationId())
.type(OperationLogType.UPDATE.name())
.module(OperationLogModule.API_DEFINITION)
.method(HttpMethodConstants.POST.name())
.path(MOVE)
.sourceId(moveNode.getId())
.content(logContent)
.originalValue(JSON.toJSONBytes(moveNode))
.createUser(operator)
.build().getLogDTO();
operationLogService.add(dto);
}
}

View File

@ -0,0 +1,256 @@
package io.metersphere.api.service.definition;
import com.github.pagehelper.PageHelper;
import io.metersphere.api.domain.ApiDefinition;
import io.metersphere.api.domain.ApiDefinitionExample;
import io.metersphere.api.domain.ApiDefinitionModule;
import io.metersphere.api.domain.ApiDefinitionModuleExample;
import io.metersphere.api.dto.debug.ApiTreeNode;
import io.metersphere.api.dto.debug.ModuleCreateRequest;
import io.metersphere.api.dto.debug.ModuleUpdateRequest;
import io.metersphere.api.dto.definition.ApiModuleRequest;
import io.metersphere.api.mapper.ApiDefinitionMapper;
import io.metersphere.api.mapper.ApiDefinitionModuleMapper;
import io.metersphere.api.mapper.ExtApiDefinitionMapper;
import io.metersphere.api.mapper.ExtApiDefinitionModuleMapper;
import io.metersphere.api.service.debug.ApiDebugModuleService;
import io.metersphere.project.dto.ModuleCountDTO;
import io.metersphere.project.dto.NodeSortDTO;
import io.metersphere.project.service.ModuleTreeService;
import io.metersphere.sdk.constants.ModuleConstants;
import io.metersphere.sdk.exception.MSException;
import io.metersphere.sdk.util.Translator;
import io.metersphere.system.dto.sdk.BaseTreeNode;
import io.metersphere.system.dto.sdk.request.NodeMoveRequest;
import io.metersphere.system.uid.IDGenerator;
import jakarta.annotation.Resource;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Map;
@Service
@Transactional(rollbackFor = Exception.class)
public class ApiDefinitionModuleService extends ModuleTreeService {
private static final String UNPLANNED_API = "api_unplanned_request";
private static final String MODULE_NO_EXIST = "api_module.not.exist";
private static final String DEBUG_MODULE_COUNT_ALL = "all";
@Resource
private ApiDefinitionModuleLogService apiDefinitionModuleLogService;
@Resource
private ApiDefinitionModuleMapper apiDefinitionModuleMapper;
@Resource
private ExtApiDefinitionModuleMapper extApiDefinitionModuleMapper;
@Resource
private SqlSessionFactory sqlSessionFactory;
@Resource
private ApiDebugModuleService apiDebugModuleService;
@Resource
private ApiDefinitionMapper apiDefinitionMapper;
@Resource
private ExtApiDefinitionMapper extApiDefinitionMapper;
public List<BaseTreeNode> getTree(ApiModuleRequest request) {
//接口的树结构是 模块子模块+接口 接口为非delete状态的
List<BaseTreeNode> fileModuleList = extApiDefinitionModuleMapper.selectBaseByRequest(request);
List<BaseTreeNode> baseTreeNodes = super.buildTreeAndCountResource(fileModuleList, true, Translator.get(UNPLANNED_API));
List<ApiTreeNode> apiTreeNodeList = extApiDefinitionModuleMapper.selectApiDataByRequest(request);
return apiDebugModuleService.getBaseTreeNodes(apiTreeNodeList, baseTreeNodes);
}
public List<BaseTreeNode> getTreeOnlyIdsAndResourceCount(ApiModuleRequest request, List<ModuleCountDTO> moduleCountDTOList) {
//节点内容只有Id和parentId
List<BaseTreeNode> fileModuleList = extApiDefinitionModuleMapper.selectIdAndParentIdByRequest(request);
return super.buildTreeAndCountResource(fileModuleList, moduleCountDTOList, true, Translator.get(UNPLANNED_API));
}
public String add(ModuleCreateRequest request, String operator) {
ApiDefinitionModule module = new ApiDefinitionModule();
module.setId(IDGenerator.nextStr());
module.setName(request.getName());
module.setParentId(request.getParentId());
module.setProjectId(request.getProjectId());
module.setProtocol(request.getProtocol());
module.setCreateUser(operator);
this.checkDataValidity(module);
module.setCreateTime(System.currentTimeMillis());
module.setUpdateTime(module.getCreateTime());
module.setPos(this.countPos(request.getParentId()));
module.setUpdateUser(operator);
apiDefinitionModuleMapper.insert(module);
//记录日志
apiDefinitionModuleLogService.saveAddLog(module, operator);
return module.getId();
}
private Long countPos(String parentId) {
Long maxPos = extApiDefinitionModuleMapper.getMaxPosByParentId(parentId);
if (maxPos == null) {
return LIMIT_POS;
} else {
return maxPos + LIMIT_POS;
}
}
/**
* 检查数据的合法性
*/
private void checkDataValidity(ApiDefinitionModule module) {
ApiDefinitionModuleExample example = new ApiDefinitionModuleExample();
if (!StringUtils.equals(module.getParentId(), ModuleConstants.ROOT_NODE_PARENT_ID)) {
//检查父ID是否存在 接口模块的逻辑是 同一个协议下的 同一个项目的同层级节点下不能有相同的名称
example.createCriteria().andIdEqualTo(module.getParentId())
.andProtocolEqualTo(module.getProtocol())
.andProjectIdEqualTo(module.getProjectId());
if (apiDefinitionModuleMapper.countByExample(example) == 0) {
throw new MSException(Translator.get("parent.node.not_blank"));
}
example.clear();
}
example.createCriteria().andParentIdEqualTo(module.getParentId())
.andNameEqualTo(module.getName()).andIdNotEqualTo(module.getId())
.andProtocolEqualTo(module.getProtocol()).andProjectIdEqualTo(module.getProjectId());
if (apiDefinitionModuleMapper.countByExample(example) > 0) {
throw new MSException(Translator.get("node.name.repeat"));
}
example.clear();
}
public void update(ModuleUpdateRequest request, String userId) {
ApiDefinitionModule module = apiDefinitionModuleMapper.selectByPrimaryKey(request.getId());
if (module == null) {
throw new MSException(Translator.get(MODULE_NO_EXIST));
}
ApiDefinitionModule updateModule = new ApiDefinitionModule();
updateModule.setId(request.getId());
updateModule.setName(request.getName());
updateModule.setParentId(module.getParentId());
updateModule.setProjectId(module.getProjectId());
updateModule.setProtocol(module.getProtocol());
this.checkDataValidity(updateModule);
updateModule.setUpdateTime(System.currentTimeMillis());
updateModule.setUpdateUser(userId);
apiDefinitionModuleMapper.updateByPrimaryKeySelective(updateModule);
//记录日志
apiDefinitionModuleLogService.saveUpdateLog(updateModule, userId);
}
public void deleteModule(String deleteId, String currentUser) {
ApiDefinitionModule deleteModule = apiDefinitionModuleMapper.selectByPrimaryKey(deleteId);
if (deleteModule != null) {
deleteModule(List.of(deleteId), currentUser, deleteModule.getProjectId());
}
}
public void deleteModule(List<String> deleteIds, String currentUser, String projectId) {
if (CollectionUtils.isEmpty(deleteIds)) {
return;
}
List<BaseTreeNode> baseTreeNodes = extApiDefinitionModuleMapper.selectNodeByIds(deleteIds);
extApiDefinitionModuleMapper.deleteByIds(deleteIds);
//记录日志
apiDefinitionModuleLogService.saveDeleteModuleLog(baseTreeNodes, currentUser, projectId);
//删除模块下的所有接口 TODO 需要掉接口那边的删除方法 分批删除 还需要删除接口下面关联的case数据
batchDeleteData(deleteIds, currentUser, projectId);
List<String> childrenIds = extApiDefinitionModuleMapper.selectChildrenIdsByParentIds(deleteIds);
if (CollectionUtils.isNotEmpty(childrenIds)) {
deleteModule(childrenIds, currentUser, projectId);
}
}
public void batchDeleteData(List<String> ids, String userId, String projectId) {
ApiDefinitionExample example = new ApiDefinitionExample();
example.createCriteria().andModuleIdIn(ids).andDeletedEqualTo(false);
long apiCount = apiDefinitionMapper.countByExample(example);
while (apiCount > 0) {
PageHelper.startPage(1, 500);
List<ApiDefinition> apiDefinitions = apiDefinitionMapper.selectByExample(example);
//提取id为新的集合
List<String> refIds = apiDefinitions.stream().map(ApiDefinition::getRefId).distinct().toList();
//删除接口
extApiDefinitionMapper.deleteApiToGc(refIds, userId, System.currentTimeMillis());
apiDefinitionModuleLogService.saveDeleteDataLog(apiDefinitions, userId, projectId);
//删除接口用例 TODO 这里有点问题 如果把接口下的用例放到回收站里了 把回收站的用例恢复 但是接口没有恢复那这些用例应该挂在哪个接口下面
apiCount = apiDefinitionMapper.countByExample(example);
}
}
public void moveNode(NodeMoveRequest request, String currentUser) {
NodeSortDTO nodeSortDTO = super.getNodeSortDTO(request,
extApiDefinitionModuleMapper::selectBaseModuleById,
extApiDefinitionModuleMapper::selectModuleByParentIdAndPosOperator);
ApiDefinitionModuleExample example = new ApiDefinitionModuleExample();
example.createCriteria().andParentIdEqualTo(nodeSortDTO.getParent().getId()).andIdEqualTo(request.getDragNodeId());
//节点换到了别的节点下,要先更新parent节点.
if (apiDefinitionModuleMapper.countByExample(example) == 0) {
ApiDefinitionModule definitionModule = new ApiDefinitionModule();
ApiDefinitionModule currentModule = apiDefinitionModuleMapper.selectByPrimaryKey(request.getDragNodeId());
currentModule.setParentId(nodeSortDTO.getParent().getId());
checkDataValidity(currentModule);
definitionModule.setId(request.getDragNodeId());
definitionModule.setParentId(nodeSortDTO.getParent().getId());
apiDefinitionModuleMapper.updateByPrimaryKeySelective(definitionModule);
}
super.sort(nodeSortDTO);
//记录日志
apiDefinitionModuleLogService.saveMoveLog(nodeSortDTO, currentUser);
}
/**
* 查找当前项目下模块每个节点对应的资源统计
*/
public Map<String, Long> getModuleCountMap(ApiModuleRequest request, List<ModuleCountDTO> moduleCountDTOList) {
//构建模块树并计算每个节点下的所有数量包含子节点
List<BaseTreeNode> treeNodeList = this.getTreeOnlyIdsAndResourceCount(request, moduleCountDTOList);
return super.getIdCountMapByBreadth(treeNodeList);
}
@Override
public void updatePos(String id, long pos) {
ApiDefinitionModule updateModule = new ApiDefinitionModule();
updateModule.setPos(pos);
updateModule.setId(id);
apiDefinitionModuleMapper.updateByPrimaryKeySelective(updateModule);
}
@Override
public void refreshPos(String parentId) {
List<String> childrenIdSortByPos = extApiDefinitionModuleMapper.selectChildrenIdsSortByPos(parentId);
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
ApiDefinitionModuleMapper batchUpdateMapper = sqlSession.getMapper(ApiDefinitionModuleMapper.class);
for (int i = 0; i < childrenIdSortByPos.size(); i++) {
String nodeId = childrenIdSortByPos.get(i);
ApiDefinitionModule updateModule = new ApiDefinitionModule();
updateModule.setId(nodeId);
updateModule.setPos((i + 1) * LIMIT_POS);
batchUpdateMapper.updateByPrimaryKeySelective(updateModule);
}
sqlSession.flushStatements();
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
}
public Map<String, Long> moduleCount(ApiModuleRequest request) {
request.setModuleIds(null);
//查找根据moduleIds查找模块下的接口数量 查非delete状态的
List<ModuleCountDTO> moduleCountDTOList = extApiDefinitionModuleMapper.countModuleIdByRequest(request);
long allCount = getAllCount(moduleCountDTOList);
Map<String, Long> moduleCountMap = getModuleCountMap(request, moduleCountDTOList);
moduleCountMap.put(DEBUG_MODULE_COUNT_ALL, allCount);
return moduleCountMap;
}
}

View File

@ -0,0 +1,65 @@
[
{
"id": "API",
"name": "permission.api_test.name",
"type": "PROJECT",
"children": [
{
"id": "PROJECT_API_DEBUG",
"name": "permission.api_debug.name",
"permissions": [
{
"id": "PROJECT_API_DEBUG:READ"
},
{
"id": "PROJECT_API_DEBUG:READ+ADD"
},
{
"id": "PROJECT_API_DEBUG:READ+UPDATE"
},
{
"id": "PROJECT_API_DEBUG:READ+DELETE"
},
{
"id": "PROJECT_API_DEBUG:READ+IMPORT",
"name": "permission.api_definition.import"
},
{
"id": "PROJECT_API_DEBUG:READ+EXECUTE",
"name": "permission.api_definition.execute"
}
]
},
{
"id": "PROJECT_API_DEFINITION",
"name": "permission.api_definition.name",
"permissions": [
{
"id": "PROJECT_API_DEFINITION:READ"
},
{
"id": "PROJECT_API_DEFINITION:READ+ADD"
},
{
"id": "PROJECT_API_DEFINITION:READ+UPDATE"
},
{
"id": "PROJECT_API_DEFINITION:READ+DELETE"
},
{
"id": "PROJECT_API_DEFINITION:READ+IMPORT",
"name": "permission.api_definition.import"
},
{
"id": "PROJECT_API_DEFINITION:READ+EXECUTE",
"name": "permission.api_definition.execute"
},
{
"id": "PROJECT_API_DEFINITION:READ+EXPORT",
"name": "permission.api_definition.export"
}
]
}
]
}
]

View File

@ -2,8 +2,8 @@ package io.metersphere.api.controller;
import io.metersphere.api.domain.*;
import io.metersphere.api.dto.debug.ApiDebugRequest;
import io.metersphere.api.dto.debug.DebugModuleCreateRequest;
import io.metersphere.api.dto.debug.DebugModuleUpdateRequest;
import io.metersphere.api.dto.debug.ModuleCreateRequest;
import io.metersphere.api.dto.debug.ModuleUpdateRequest;
import io.metersphere.api.mapper.ApiDebugBlobMapper;
import io.metersphere.api.mapper.ApiDebugMapper;
import io.metersphere.api.mapper.ApiDebugModuleMapper;
@ -133,7 +133,7 @@ public class ApiDebugModuleControllerTests extends BaseTest {
@Order(2)
public void addModuleTestSuccess() throws Exception {
//根目录下创建节点(a1
DebugModuleCreateRequest request = new DebugModuleCreateRequest();
ModuleCreateRequest request = new ModuleCreateRequest();
request.setProjectId(project.getId());
request.setName("a1");
MvcResult mvcResult = this.requestPostWithOkAndReturn(URL_MODULE_ADD, request);
@ -152,7 +152,7 @@ public class ApiDebugModuleControllerTests extends BaseTest {
checkLog(a1Node.getId(), OperationLogType.ADD, URL_MODULE_ADD);
//根目录下创建节点a2和a3在a1下创建子节点a1-b1
request = new DebugModuleCreateRequest();
request = new ModuleCreateRequest();
request.setProjectId(project.getId());
request.setName("a2");
this.requestPostWithOkAndReturn(URL_MODULE_ADD, request);
@ -161,7 +161,7 @@ public class ApiDebugModuleControllerTests extends BaseTest {
request.setName("a3");
this.requestPostWithOkAndReturn(URL_MODULE_ADD, request);
request = new DebugModuleCreateRequest();
request = new ModuleCreateRequest();
request.setProjectId(project.getId());
request.setName("a1-b1");
request.setParentId(a1Node.getId());
@ -191,7 +191,7 @@ public class ApiDebugModuleControllerTests extends BaseTest {
checkLog(a1b1Node.getId(), OperationLogType.ADD, URL_MODULE_ADD);
//a1节点下可以继续添加a1节点
request = new DebugModuleCreateRequest();
request = new ModuleCreateRequest();
request.setProjectId(project.getId());
request.setName("a1");
request.setParentId(a1Node.getId());
@ -216,7 +216,7 @@ public class ApiDebugModuleControllerTests extends BaseTest {
checkLog(a1ChildNode.getId(), OperationLogType.ADD, URL_MODULE_ADD);
//a1的子节点a1下继续创建节点a1-a1-c1
request = new DebugModuleCreateRequest();
request = new ModuleCreateRequest();
request.setProjectId(project.getId());
request.setName("a1-a1-c1");
request.setParentId(a1ChildNode.getId());
@ -244,7 +244,7 @@ public class ApiDebugModuleControllerTests extends BaseTest {
checkLog(a1a1c1Node.getId(), OperationLogType.ADD, URL_MODULE_ADD);
//子节点a1-b1下继续创建节点a1-b1-c1
request = new DebugModuleCreateRequest();
request = new ModuleCreateRequest();
request.setProjectId(project.getId());
request.setName("a1-b1-c1");
request.setParentId(a1b1Node.getId());
@ -270,7 +270,7 @@ public class ApiDebugModuleControllerTests extends BaseTest {
checkLog(a1b1c1Node.getId(), OperationLogType.ADD, URL_MODULE_ADD);
//校验权限
request = new DebugModuleCreateRequest();
request = new ModuleCreateRequest();
request.setProjectId(DEFAULT_PROJECT_ID);
request.setName("defaultProject");
requestPostPermissionTest(PermissionConstants.PROJECT_API_DEBUG_READ_ADD, URL_MODULE_ADD, request);
@ -285,15 +285,15 @@ public class ApiDebugModuleControllerTests extends BaseTest {
assert a1Node != null;
//参数校验
DebugModuleCreateRequest request = new DebugModuleCreateRequest();
ModuleCreateRequest request = new ModuleCreateRequest();
request.setProjectId(project.getId());
this.requestPost(URL_MODULE_ADD, request).andExpect(BAD_REQUEST_MATCHER);
request = new DebugModuleCreateRequest();
request = new ModuleCreateRequest();
request.setName("none");
this.requestPost(URL_MODULE_ADD, request).andExpect(BAD_REQUEST_MATCHER);
request = new DebugModuleCreateRequest();
request = new ModuleCreateRequest();
this.requestPost(URL_MODULE_ADD, request).andExpect(BAD_REQUEST_MATCHER);
request = new DebugModuleCreateRequest();
request = new ModuleCreateRequest();
request.setParentId(null);
this.requestPost(URL_MODULE_ADD, request).andExpect(BAD_REQUEST_MATCHER);
//名称存在特殊字符
@ -302,20 +302,20 @@ public class ApiDebugModuleControllerTests extends BaseTest {
this.requestPost(URL_MODULE_ADD, request).andExpect(BAD_REQUEST_MATCHER);
//父节点ID不存在的
request = new DebugModuleCreateRequest();
request = new ModuleCreateRequest();
request.setProjectId(project.getId());
request.setName("ParentIsUUID");
request.setParentId(IDGenerator.nextStr());
this.requestPost(URL_MODULE_ADD, request).andExpect(ERROR_REQUEST_MATCHER);
//添加重复的a1节点
request = new DebugModuleCreateRequest();
request = new ModuleCreateRequest();
request.setProjectId(project.getId());
request.setName("a1");
this.requestPost(URL_MODULE_ADD, request).andExpect(ERROR_REQUEST_MATCHER);
//a1节点下添加重复的a1-b1节点
request = new DebugModuleCreateRequest();
request = new ModuleCreateRequest();
request.setProjectId(project.getId());
request.setName("a1-b1");
request.setParentId(a1Node.getId());
@ -341,7 +341,7 @@ public class ApiDebugModuleControllerTests extends BaseTest {
}
}
assert a1Node != null;
DebugModuleUpdateRequest updateRequest = new DebugModuleUpdateRequest();
ModuleUpdateRequest updateRequest = new ModuleUpdateRequest();
updateRequest.setId(a1Node.getId());
updateRequest.setName("a1-a1");
//无法拿到当前用户的projectID 所以需要传入
@ -362,7 +362,7 @@ public class ApiDebugModuleControllerTests extends BaseTest {
example.createCriteria().andProjectIdEqualTo(DEFAULT_PROJECT_ID).andNameEqualTo("defaultProject");
List<ApiDebugModule> apiDebugModules = apiDebugModuleMapper.selectByExample(example);
assert CollectionUtils.isNotEmpty(apiDebugModules);
updateRequest = new DebugModuleUpdateRequest();
updateRequest = new ModuleUpdateRequest();
updateRequest.setId(apiDebugModules.get(0).getId());
updateRequest.setName("default-update-Project");
requestPostPermissionTest(PermissionConstants.PROJECT_API_DEBUG_READ_UPDATE, URL_MODULE_UPDATE, updateRequest);
@ -374,22 +374,22 @@ public class ApiDebugModuleControllerTests extends BaseTest {
BaseTreeNode a1Node = getNodeByName(preliminaryTreeNodes, "a1-a1");
assert a1Node != null;
//反例-参数校验
DebugModuleUpdateRequest updateRequest = new DebugModuleUpdateRequest();
ModuleUpdateRequest updateRequest = new ModuleUpdateRequest();
this.requestPost(URL_MODULE_UPDATE, updateRequest).andExpect(BAD_REQUEST_MATCHER);
//参数名称带有特殊字符
updateRequest = new DebugModuleUpdateRequest();
updateRequest = new ModuleUpdateRequest();
updateRequest.setId(a1Node.getId());
updateRequest.setName("a1/a2");
this.requestPost(URL_MODULE_UPDATE, updateRequest).andExpect(BAD_REQUEST_MATCHER);
//id不存在
updateRequest = new DebugModuleUpdateRequest();
updateRequest = new ModuleUpdateRequest();
updateRequest.setId(IDGenerator.nextStr());
updateRequest.setName(IDGenerator.nextStr());
this.requestPost(URL_MODULE_UPDATE, updateRequest).andExpect(ERROR_REQUEST_MATCHER);
//名称重复 a1-a1改为a1-b1
updateRequest = new DebugModuleUpdateRequest();
updateRequest = new ModuleUpdateRequest();
updateRequest.setId(a1Node.getId());
updateRequest.setName("a1-b1");
this.requestPost(URL_MODULE_UPDATE, updateRequest).andExpect(ERROR_REQUEST_MATCHER);
@ -748,7 +748,7 @@ public class ApiDebugModuleControllerTests extends BaseTest {
this.requestGetWithOk(String.format(URL_MODULE_DELETE, ModuleConstants.DEFAULT_NODE_ID));
//service层判断测试删除空集合
apiDebugModuleService.deleteModule(new ArrayList<>());
apiDebugModuleService.deleteModule(new ArrayList<>(), "admin", DEFAULT_PROJECT_ID);
//校验权限
requestGetPermissionTest(PermissionConstants.PROJECT_API_DEBUG_READ_DELETE, String.format(URL_MODULE_DELETE, IDGenerator.nextNum()));

View File

@ -2,9 +2,11 @@ package io.metersphere.api.controller;
import com.jayway.jsonpath.JsonPath;
import io.metersphere.api.dto.definition.ApiDefinitionDTO;
import io.metersphere.sdk.constants.ApplicationNumScope;
import io.metersphere.sdk.constants.SessionConstants;
import io.metersphere.sdk.util.JSON;
import io.metersphere.sdk.util.LogUtils;
import io.metersphere.system.uid.NumGenerator;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.*;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
@ -66,7 +68,10 @@ public class ApiDefinitionControllerTests {
request.setLatest(true);
request.setStatus("test-api-status");
request.setVersionId("test-api-version");
request.setRefId("test-api-version");
request.setDeleted(false);
request.setModuleId("test-api-module-id");
request.setNum(NumGenerator.nextNum("test-project-id", ApplicationNumScope.API_DEFINITION));
mockMvc.perform(MockMvcRequestBuilders.multipart(prefix + "/add")
.file(file)

View File

@ -0,0 +1,848 @@
package io.metersphere.api.controller;
import io.metersphere.api.domain.*;
import io.metersphere.api.dto.debug.ApiDebugRequest;
import io.metersphere.api.dto.debug.ModuleCreateRequest;
import io.metersphere.api.dto.debug.ModuleUpdateRequest;
import io.metersphere.api.dto.definition.ApiModuleRequest;
import io.metersphere.api.mapper.ApiDefinitionBlobMapper;
import io.metersphere.api.mapper.ApiDefinitionMapper;
import io.metersphere.api.mapper.ApiDefinitionModuleMapper;
import io.metersphere.api.service.definition.ApiDefinitionModuleService;
import io.metersphere.project.domain.Project;
import io.metersphere.project.mapper.ProjectMapper;
import io.metersphere.sdk.constants.ApplicationNumScope;
import io.metersphere.sdk.constants.ModuleConstants;
import io.metersphere.sdk.constants.PermissionConstants;
import io.metersphere.sdk.util.JSON;
import io.metersphere.system.base.BaseTest;
import io.metersphere.system.controller.handler.ResultHolder;
import io.metersphere.system.dto.sdk.BaseTreeNode;
import io.metersphere.system.dto.sdk.request.NodeMoveRequest;
import io.metersphere.system.invoker.ProjectServiceInvoker;
import io.metersphere.system.log.constants.OperationLogType;
import io.metersphere.system.uid.IDGenerator;
import io.metersphere.system.uid.NumGenerator;
import jakarta.annotation.Resource;
import org.apache.commons.collections4.CollectionUtils;
import org.junit.jupiter.api.*;
import org.springframework.beans.factory.annotation.Autowired;
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 org.testcontainers.shaded.org.apache.commons.lang3.StringUtils;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
@AutoConfigureMockMvc
public class ApiDefinitionModuleControllerTests extends BaseTest {
private static final String URL_MODULE_ADD = "/api/definition/module/add";
private static final String URL_MODULE_UPDATE = "/api/definition/module/update";
private static final String URL_MODULE_DELETE = "/api/definition/module/delete/%s";
private static final String URL_MODULE_TREE = "/api/definition/module/tree";
private static final String URL_MODULE_MOVE = "/api/definition/module/move";
private static final String URL_FILE_MODULE_COUNT = "/api/definition/module/count";
private static final ResultMatcher BAD_REQUEST_MATCHER = status().isBadRequest();
private static final ResultMatcher ERROR_REQUEST_MATCHER = status().is5xxServerError();
private static Project project;
private static List<BaseTreeNode> preliminaryTreeNodes = new ArrayList<>();
private final ProjectServiceInvoker serviceInvoker;
@Resource
private ProjectMapper projectMapper;
@Resource
private ApiDefinitionModuleMapper apiDefinitionModuleMapper;
@Resource
private ApiDefinitionMapper apiDefinitionMapper;
@Resource
private ApiDefinitionBlobMapper apiDefinitionBlobMapper;
@Resource
private ApiDefinitionModuleService apiDefinitionModuleService;
@Autowired
public ApiDefinitionModuleControllerTests(ProjectServiceInvoker serviceInvoker) {
this.serviceInvoker = serviceInvoker;
}
public static BaseTreeNode getNodeByName(List<BaseTreeNode> preliminaryTreeNodes, String nodeName) {
for (BaseTreeNode firstLevelNode : preliminaryTreeNodes) {
if (StringUtils.equals(firstLevelNode.getName(), nodeName) && StringUtils.equals(firstLevelNode.getType(), ModuleConstants.NODE_TYPE_DEFAULT)) {
return firstLevelNode;
}
if (CollectionUtils.isNotEmpty(firstLevelNode.getChildren())) {
for (BaseTreeNode secondLevelNode : firstLevelNode.getChildren()) {
if (StringUtils.equals(secondLevelNode.getName(), nodeName) && StringUtils.equals(secondLevelNode.getType(), ModuleConstants.NODE_TYPE_DEFAULT)) {
return secondLevelNode;
}
if (CollectionUtils.isNotEmpty(secondLevelNode.getChildren())) {
for (BaseTreeNode thirdLevelNode : secondLevelNode.getChildren()) {
if (StringUtils.equals(thirdLevelNode.getName(), nodeName) && StringUtils.equals(thirdLevelNode.getType(), ModuleConstants.NODE_TYPE_DEFAULT)) {
return thirdLevelNode;
}
}
}
}
}
}
return null;
}
@Test
@Order(1)
public void initTestData() {
if (project == null) {
Project initProject = new Project();
initProject.setId(IDGenerator.nextStr());
initProject.setNum(null);
initProject.setOrganizationId(DEFAULT_ORGANIZATION_ID);
initProject.setName("接口测试模块项目");
initProject.setDescription("接口测试模块项目");
initProject.setCreateUser("admin");
initProject.setUpdateUser("admin");
initProject.setCreateTime(System.currentTimeMillis());
initProject.setUpdateTime(System.currentTimeMillis());
initProject.setEnable(true);
initProject.setModuleSetting("[\"apiTest\",\"uiTest\"]");
projectMapper.insertSelective(initProject);
serviceInvoker.invokeCreateServices(initProject.getId());
project = projectMapper.selectByPrimaryKey(initProject.getId());
}
}
public void initApiDebugData(String moduleId) {
ApiDefinition apiDefinition = new ApiDefinition();
apiDefinition.setId(IDGenerator.nextStr());
apiDefinition.setProjectId(project.getId());
apiDefinition.setName(StringUtils.join("接口定义", apiDefinition.getId()));
apiDefinition.setModuleId(moduleId);
apiDefinition.setProtocol("HTTP");
apiDefinition.setMethod("GET");
apiDefinition.setStatus("未规划");
apiDefinition.setNum(NumGenerator.nextNum(project.getId(), ApplicationNumScope.API_DEFINITION));
apiDefinition.setPos(0L);
apiDefinition.setPath(StringUtils.join("api/definition/", apiDefinition.getId()));
apiDefinition.setLatest(true);
apiDefinition.setVersionId("1.0");
apiDefinition.setRefId(apiDefinition.getId());
apiDefinition.setCreateTime(System.currentTimeMillis());
apiDefinition.setUpdateTime(System.currentTimeMillis());
apiDefinition.setCreateUser("admin");
apiDefinition.setUpdateUser("admin");
apiDefinitionMapper.insertSelective(apiDefinition);
ApiDefinitionBlob apiDefinitionBlob = new ApiDefinitionBlob();
apiDefinitionBlob.setId(apiDefinition.getId());
apiDefinitionBlob.setRequest(new byte[0]);
apiDefinitionBlob.setResponse(new byte[0]);
apiDefinitionBlobMapper.insertSelective(apiDefinitionBlob);
}
@Test
@Order(2)
public void addModuleTestSuccess() throws Exception {
//根目录下创建节点(a1
ModuleCreateRequest request = new ModuleCreateRequest();
request.setProjectId(project.getId());
request.setName("a1");
MvcResult mvcResult = this.requestPostWithOkAndReturn(URL_MODULE_ADD, request);
String returnId = mvcResult.getResponse().getContentAsString();
Assertions.assertNotNull(returnId);
List<BaseTreeNode> treeNodes = this.getModuleTreeNode();
BaseTreeNode a1Node = null;
for (BaseTreeNode baseTreeNode : treeNodes) {
if (StringUtils.equals(baseTreeNode.getName(), request.getName())) {
a1Node = baseTreeNode;
}
Assertions.assertNotNull(baseTreeNode.getParentId());
}
Assertions.assertNotNull(a1Node);
initApiDebugData(a1Node.getId());
checkLog(a1Node.getId(), OperationLogType.ADD, URL_MODULE_ADD);
//根目录下创建节点a2和a3在a1下创建子节点a1-b1
request = new ModuleCreateRequest();
request.setProjectId(project.getId());
request.setName("a2");
this.requestPostWithOkAndReturn(URL_MODULE_ADD, request);
request.setName("a3");
this.requestPostWithOkAndReturn(URL_MODULE_ADD, request);
request = new ModuleCreateRequest();
request.setProjectId(project.getId());
request.setName("a1-b1");
request.setParentId(a1Node.getId());
this.requestPostWithOkAndReturn(URL_MODULE_ADD, request);
treeNodes = this.getModuleTreeNode();
BaseTreeNode a1b1Node = null;
BaseTreeNode a2Node = null;
for (BaseTreeNode baseTreeNode : treeNodes) {
Assertions.assertNotNull(baseTreeNode.getParentId());
if (StringUtils.equals(baseTreeNode.getName(), "a1") && CollectionUtils.isNotEmpty(baseTreeNode.getChildren())) {
for (BaseTreeNode childNode : baseTreeNode.getChildren()) {
if (StringUtils.equals(childNode.getName(), "a1-b1") && StringUtils.equals(childNode.getType(), ModuleConstants.NODE_TYPE_DEFAULT)) {
a1b1Node = childNode;
}
Assertions.assertNotNull(childNode.getParentId());
}
} else if (StringUtils.equals(baseTreeNode.getName(), "a2") && StringUtils.equals(baseTreeNode.getType(), ModuleConstants.NODE_TYPE_DEFAULT)) {
a2Node = baseTreeNode;
}
}
Assertions.assertNotNull(a2Node);
Assertions.assertNotNull(a1b1Node);
initApiDebugData(a2Node.getId());
initApiDebugData(a1b1Node.getId());
checkLog(a2Node.getId(), OperationLogType.ADD, URL_MODULE_ADD);
checkLog(a1b1Node.getId(), OperationLogType.ADD, URL_MODULE_ADD);
//a1节点下可以继续添加a1节点
request = new ModuleCreateRequest();
request.setProjectId(project.getId());
request.setName("a1");
request.setParentId(a1Node.getId());
this.requestPostWithOkAndReturn(URL_MODULE_ADD, request);
//继续创建a1下继续创建a1-a1-b1,
treeNodes = this.getModuleTreeNode();
BaseTreeNode a1ChildNode = null;
for (BaseTreeNode baseTreeNode : treeNodes) {
Assertions.assertNotNull(baseTreeNode.getParentId());
if (StringUtils.equals(baseTreeNode.getName(), "a1") && CollectionUtils.isNotEmpty(baseTreeNode.getChildren())) {
for (BaseTreeNode childNode : baseTreeNode.getChildren()) {
Assertions.assertNotNull(childNode.getParentId());
if (StringUtils.equals(childNode.getName(), "a1") && StringUtils.equals(childNode.getType(), ModuleConstants.NODE_TYPE_DEFAULT)) {
a1ChildNode = childNode;
}
}
}
}
Assertions.assertNotNull(a1ChildNode);
initApiDebugData(a1ChildNode.getId());
checkLog(a1ChildNode.getId(), OperationLogType.ADD, URL_MODULE_ADD);
//a1的子节点a1下继续创建节点a1-a1-c1
request = new ModuleCreateRequest();
request.setProjectId(project.getId());
request.setName("a1-a1-c1");
request.setParentId(a1ChildNode.getId());
this.requestPostWithOkAndReturn(URL_MODULE_ADD, request);
treeNodes = this.getModuleTreeNode();
BaseTreeNode a1a1c1Node = null;
for (BaseTreeNode baseTreeNode : treeNodes) {
Assertions.assertNotNull(baseTreeNode.getParentId());
if (StringUtils.equals(baseTreeNode.getName(), "a1") && CollectionUtils.isNotEmpty(baseTreeNode.getChildren())) {
for (BaseTreeNode secondNode : baseTreeNode.getChildren()) {
Assertions.assertNotNull(secondNode.getParentId());
if (StringUtils.equals(secondNode.getName(), "a1") && CollectionUtils.isNotEmpty(secondNode.getChildren())) {
for (BaseTreeNode thirdNode : secondNode.getChildren()) {
Assertions.assertNotNull(thirdNode.getParentId());
if (StringUtils.equals(thirdNode.getName(), "a1-a1-c1") && StringUtils.equals(thirdNode.getType(), ModuleConstants.NODE_TYPE_DEFAULT)) {
a1a1c1Node = thirdNode;
}
}
}
}
}
}
Assertions.assertNotNull(a1a1c1Node);
initApiDebugData(a1a1c1Node.getId());
checkLog(a1a1c1Node.getId(), OperationLogType.ADD, URL_MODULE_ADD);
//子节点a1-b1下继续创建节点a1-b1-c1
request = new ModuleCreateRequest();
request.setProjectId(project.getId());
request.setName("a1-b1-c1");
request.setParentId(a1b1Node.getId());
this.requestPostWithOkAndReturn(URL_MODULE_ADD, request);
treeNodes = this.getModuleTreeNode();
BaseTreeNode a1b1c1Node = null;
for (BaseTreeNode baseTreeNode : treeNodes) {
if (StringUtils.equals(baseTreeNode.getName(), "a1") && CollectionUtils.isNotEmpty(baseTreeNode.getChildren())) {
for (BaseTreeNode secondNode : baseTreeNode.getChildren()) {
if (StringUtils.equals(secondNode.getName(), "a1-b1") && CollectionUtils.isNotEmpty(secondNode.getChildren())) {
for (BaseTreeNode thirdNode : secondNode.getChildren()) {
if (StringUtils.equals(thirdNode.getName(), "a1-b1-c1") && StringUtils.equals(thirdNode.getType(), ModuleConstants.NODE_TYPE_DEFAULT)) {
a1b1c1Node = thirdNode;
}
}
}
}
}
}
Assertions.assertNotNull(a1b1c1Node);
initApiDebugData(a1b1c1Node.getId());
preliminaryTreeNodes = treeNodes;
checkLog(a1b1c1Node.getId(), OperationLogType.ADD, URL_MODULE_ADD);
//校验权限
request = new ModuleCreateRequest();
request.setProjectId(DEFAULT_PROJECT_ID);
request.setName("defaultProject");
requestPostPermissionTest(PermissionConstants.PROJECT_API_DEFINITION_READ_ADD, URL_MODULE_ADD, request);
}
@Test
@Order(3)
public void addModuleTestError() throws Exception {
this.preliminaryData();
BaseTreeNode a1Node = getNodeByName(preliminaryTreeNodes, "a1");
assert a1Node != null;
//参数校验
ModuleCreateRequest request = new ModuleCreateRequest();
request.setProjectId(project.getId());
this.requestPost(URL_MODULE_ADD, request).andExpect(BAD_REQUEST_MATCHER);
request = new ModuleCreateRequest();
request.setName("none");
this.requestPost(URL_MODULE_ADD, request).andExpect(BAD_REQUEST_MATCHER);
request = new ModuleCreateRequest();
this.requestPost(URL_MODULE_ADD, request).andExpect(BAD_REQUEST_MATCHER);
request = new ModuleCreateRequest();
request.setParentId(null);
this.requestPost(URL_MODULE_ADD, request).andExpect(BAD_REQUEST_MATCHER);
//名称存在特殊字符
request.setName("a1/a2");
request.setParentId(a1Node.getId());
this.requestPost(URL_MODULE_ADD, request).andExpect(BAD_REQUEST_MATCHER);
//父节点ID不存在的
request = new ModuleCreateRequest();
request.setProjectId(project.getId());
request.setName("ParentIsUUID");
request.setParentId(IDGenerator.nextStr());
this.requestPost(URL_MODULE_ADD, request).andExpect(ERROR_REQUEST_MATCHER);
//添加重复的a1节点
request = new ModuleCreateRequest();
request.setProjectId(project.getId());
request.setName("a1");
this.requestPost(URL_MODULE_ADD, request).andExpect(ERROR_REQUEST_MATCHER);
//a1节点下添加重复的a1-b1节点
request = new ModuleCreateRequest();
request.setProjectId(project.getId());
request.setName("a1-b1");
request.setParentId(a1Node.getId());
this.requestPost(URL_MODULE_ADD, request).andExpect(ERROR_REQUEST_MATCHER);
//子节点的项目ID和父节点的不匹配
request = new ModuleCreateRequest();
request.setProjectId(IDGenerator.nextStr());
request.setName("RandomUUID");
request.setParentId(a1Node.getId());
this.requestPost(URL_MODULE_ADD, request).andExpect(status().is5xxServerError());
//项目ID和父节点的不匹配
request = new ModuleCreateRequest();
request.setProjectId(DEFAULT_PROJECT_ID);
request.setName("RandomUUID");
request.setParentId(a1Node.getId());
this.requestPost(URL_MODULE_ADD, request).andExpect(status().is5xxServerError());
}
@Test
@Order(4)
public void updateModuleTestSuccess() throws Exception {
if (CollectionUtils.isEmpty(preliminaryTreeNodes)) {
this.addModuleTestSuccess();
}
//更改名称
BaseTreeNode a1Node = null;
for (BaseTreeNode node : preliminaryTreeNodes) {
if (StringUtils.equals(node.getName(), "a1")) {
for (BaseTreeNode a1ChildrenNode : node.getChildren()) {
if (StringUtils.equals(a1ChildrenNode.getName(), "a1")) {
a1Node = a1ChildrenNode;
}
}
}
}
assert a1Node != null;
ModuleUpdateRequest updateRequest = new ModuleUpdateRequest();
updateRequest.setId(a1Node.getId());
updateRequest.setName("a1-a1");
requestPost(URL_MODULE_UPDATE, updateRequest);
preliminaryTreeNodes = this.getModuleTreeNode();
checkLog(a1Node.getId(), OperationLogType.UPDATE, URL_MODULE_UPDATE);
//校验权限
ApiDefinitionModuleExample example = new ApiDefinitionModuleExample();
example.createCriteria().andProjectIdEqualTo(DEFAULT_PROJECT_ID).andNameEqualTo("defaultProject");
List<ApiDefinitionModule> apiDebugModules = apiDefinitionModuleMapper.selectByExample(example);
assert CollectionUtils.isNotEmpty(apiDebugModules);
updateRequest = new ModuleUpdateRequest();
updateRequest.setId(apiDebugModules.get(0).getId());
updateRequest.setName("default-update-Project");
requestPostPermissionTest(PermissionConstants.PROJECT_API_DEFINITION_READ_UPDATE, URL_MODULE_UPDATE, updateRequest);
}
@Test
@Order(5)
public void updateModuleTestError() throws Exception {
BaseTreeNode a1Node = getNodeByName(preliminaryTreeNodes, "a1-a1");
assert a1Node != null;
//反例-参数校验
ModuleUpdateRequest updateRequest = new ModuleUpdateRequest();
this.requestPost(URL_MODULE_UPDATE, updateRequest).andExpect(BAD_REQUEST_MATCHER);
//参数名称带有特殊字符
updateRequest = new ModuleUpdateRequest();
updateRequest.setId(a1Node.getId());
updateRequest.setName("a1/a2");
this.requestPost(URL_MODULE_UPDATE, updateRequest).andExpect(BAD_REQUEST_MATCHER);
//id不存在
updateRequest = new ModuleUpdateRequest();
updateRequest.setId(IDGenerator.nextStr());
updateRequest.setName(IDGenerator.nextStr());
this.requestPost(URL_MODULE_UPDATE, updateRequest).andExpect(ERROR_REQUEST_MATCHER);
//名称重复 a1-a1改为a1-b1
updateRequest = new ModuleUpdateRequest();
updateRequest.setId(a1Node.getId());
updateRequest.setName("a1-b1");
this.requestPost(URL_MODULE_UPDATE, updateRequest).andExpect(ERROR_REQUEST_MATCHER);
}
@Test
@Order(6)
public void moveTest() throws Exception {
this.preliminaryData();
/*
*默认节点
|
·a1 +
| |
| ·a1-b1 +
| | |
| | ·a1-b1-c1
| |
| *a1-a1 +创建的时候是a1通过修改改为a1-a1
| |
| ·a1-a1-c1
|
·a2
|
·a3
*/
BaseTreeNode a1Node = getNodeByName(preliminaryTreeNodes, "a1");
BaseTreeNode a2Node = getNodeByName(preliminaryTreeNodes, "a2");
BaseTreeNode a3Node = getNodeByName(preliminaryTreeNodes, "a3");
BaseTreeNode a1a1Node = getNodeByName(preliminaryTreeNodes, "a1-a1");
BaseTreeNode a1b1Node = getNodeByName(preliminaryTreeNodes, "a1-b1");
//父节点内移动-移动到首位 a1挪到a3后面
NodeMoveRequest request = new NodeMoveRequest();
{
assert a1Node != null;
request.setDragNodeId(a1Node.getId());
assert a3Node != null;
request.setDropNodeId(a3Node.getId());
request.setDropPosition(1);
this.requestPostWithOk(URL_MODULE_MOVE, request);
this.checkModulePos(a3Node.getId(), a1Node.getId(), null, false);
}
//父节点内移动-移动到末位 在上面的基础上a1挪到a2上面
{
request = new NodeMoveRequest();
request.setDragNodeId(a1Node.getId());
assert a2Node != null;
request.setDropNodeId(a2Node.getId());
request.setDropPosition(-1);
this.requestPostWithOk(URL_MODULE_MOVE, request);
this.checkModulePos(a1Node.getId(), a2Node.getId(), null, false);
}
//父节点内移动-移动到中位 a1移动到a2-a3中间
{
request = new NodeMoveRequest();
request.setDragNodeId(a1Node.getId());
request.setDropNodeId(a2Node.getId());
request.setDropPosition(1);
this.requestPostWithOk(URL_MODULE_MOVE, request);
this.checkModulePos(a2Node.getId(), a1Node.getId(), a3Node.getId(), false);
//移动回去
request = new NodeMoveRequest();
request.setDragNodeId(a1Node.getId());
request.setDropNodeId(a2Node.getId());
request.setDropPosition(-1);
this.requestPostWithOk(URL_MODULE_MOVE, request);
this.checkModulePos(a1Node.getId(), a2Node.getId(), null, false);
}
//跨节点移动-移动到首位 a3移动到a1-b1前面然后移动回来;
{
request = new NodeMoveRequest();
request.setDragNodeId(a3Node.getId());
request.setDropNodeId(a1b1Node.getId());
request.setDropPosition(-1);
this.requestPostWithOk(URL_MODULE_MOVE, request);
this.checkModulePos(a3Node.getId(), a1b1Node.getId(), null, false);
//移动回去
request = new NodeMoveRequest();
request.setDragNodeId(a3Node.getId());
request.setDropNodeId(a2Node.getId());
request.setDropPosition(1);
this.requestPostWithOk(URL_MODULE_MOVE, request);
this.checkModulePos(a2Node.getId(), a3Node.getId(), null, false);
}
//跨节点移动-移动到末尾 a3移动到a1-a1后面然后移动回来;
{
request = new NodeMoveRequest();
request.setDragNodeId(a3Node.getId());
assert a1a1Node != null;
request.setDropNodeId(a1a1Node.getId());
request.setDropPosition(1);
this.requestPostWithOk(URL_MODULE_MOVE, request);
this.checkModulePos(a1a1Node.getId(), a3Node.getId(), null, false);
//移动回去
request = new NodeMoveRequest();
request.setDragNodeId(a3Node.getId());
request.setDropNodeId(a2Node.getId());
request.setDropPosition(1);
this.requestPostWithOk(URL_MODULE_MOVE, request);
this.checkModulePos(a2Node.getId(), a3Node.getId(), null, false);
}
//跨节点移动-移动到中位 a3移动到a1-b1和a1-a1中间然后移动回来;
{
request = new NodeMoveRequest();
request.setDragNodeId(a3Node.getId());
request.setDropNodeId(a1b1Node.getId());
request.setDropPosition(1);
this.requestPostWithOk(URL_MODULE_MOVE, request);
this.checkModulePos(a1b1Node.getId(), a3Node.getId(), a1a1Node.getId(), false);
//移动回去
request = new NodeMoveRequest();
request.setDragNodeId(a3Node.getId());
request.setDropNodeId(a2Node.getId());
request.setDropPosition(1);
this.requestPostWithOk(URL_MODULE_MOVE, request);
this.checkModulePos(a2Node.getId(), a3Node.getId(), null, false);
}
//父节点内移动-a3移动到首位pos小于2是否触发计算函数 先手动更改a1的pos为2然后移动a3到a1前面
{
//更改pos
ApiDefinitionModule updateModule = new ApiDefinitionModule();
updateModule.setId(a1Node.getId());
updateModule.setPos(2L);
apiDefinitionModuleMapper.updateByPrimaryKeySelective(updateModule);
//开始移动
request = new NodeMoveRequest();
request.setDragNodeId(a3Node.getId());
request.setDropNodeId(a1Node.getId());
request.setDropPosition(-1);
this.requestPostWithOk(URL_MODULE_MOVE, request);
this.checkModulePos(a3Node.getId(), a1Node.getId(), null, true);
//移动回去
request = new NodeMoveRequest();
request.setDragNodeId(a3Node.getId());
request.setDropNodeId(a2Node.getId());
request.setDropPosition(1);
this.requestPostWithOk(URL_MODULE_MOVE, request);
this.checkModulePos(a2Node.getId(), a3Node.getId(), null, false);
}
//父节点内移动-移动到中位前后节点pos差不大于2是否触发计算函数在上面的 a3-a1-a2的基础上 先手动更改a1pos为3*64a2的pos为3*64+2然后移动a3到a1和a2中间
{
//更改pos
ApiDefinitionModule updateModule = new ApiDefinitionModule();
updateModule.setId(a1Node.getId());
updateModule.setPos(3 * 64L);
apiDefinitionModuleMapper.updateByPrimaryKeySelective(updateModule);
updateModule.setId(a2Node.getId());
updateModule.setPos(3 * 64 + 2L);
apiDefinitionModuleMapper.updateByPrimaryKeySelective(updateModule);
//开始移动
request = new NodeMoveRequest();
request.setDragNodeId(a3Node.getId());
request.setDropNodeId(a1Node.getId());
request.setDropPosition(1);
this.requestPostWithOk(URL_MODULE_MOVE, request);
this.checkModulePos(a1Node.getId(), a3Node.getId(), a2Node.getId(), true);
//移动回去
request = new NodeMoveRequest();
request.setDragNodeId(a3Node.getId());
request.setDropNodeId(a2Node.getId());
request.setDropPosition(1);
this.requestPostWithOk(URL_MODULE_MOVE, request);
this.checkModulePos(a2Node.getId(), a3Node.getId(), null, false);
}
//跨节点移动-移动到首位pos小于2是否触发计算函数先手动更改a1-b1的pos为2然后移动a3到a1-b1前面最后再移动回来
{
//更改pos
ApiDefinitionModule updateModule = new ApiDefinitionModule();
updateModule.setId(a1b1Node.getId());
updateModule.setPos(2L);
apiDefinitionModuleMapper.updateByPrimaryKeySelective(updateModule);
//开始移动
request = new NodeMoveRequest();
request.setDragNodeId(a3Node.getId());
request.setDropNodeId(a1b1Node.getId());
request.setDropPosition(-1);
this.requestPostWithOk(URL_MODULE_MOVE, request);
this.checkModulePos(a3Node.getId(), a1b1Node.getId(), null, true);
//移动回去
request = new NodeMoveRequest();
request.setDragNodeId(a3Node.getId());
request.setDropNodeId(a2Node.getId());
request.setDropPosition(1);
this.requestPostWithOk(URL_MODULE_MOVE, request);
this.checkModulePos(a2Node.getId(), a3Node.getId(), null, false);
}
//跨节点移动-移动到中位前后节点pos差不大于2是否触发计算函数先手动更改a1-a1的pos为a1-b1+2然后移动a3到a1-a1前面最后再移动回来
{
//更改pos
ApiDefinitionModule updateModule = new ApiDefinitionModule();
updateModule.setId(a1b1Node.getId());
updateModule.setPos(3 * 64L);
apiDefinitionModuleMapper.updateByPrimaryKeySelective(updateModule);
updateModule.setId(a1a1Node.getId());
updateModule.setPos(3 * 64 + 2L);
apiDefinitionModuleMapper.updateByPrimaryKeySelective(updateModule);
//开始移动
request = new NodeMoveRequest();
request.setDragNodeId(a3Node.getId());
request.setDropNodeId(a1a1Node.getId());
request.setDropPosition(-1);
this.requestPostWithOk(URL_MODULE_MOVE, request);
this.checkModulePos(a1b1Node.getId(), a3Node.getId(), a1a1Node.getId(), true);
//移动回去
request = new NodeMoveRequest();
request.setDragNodeId(a3Node.getId());
request.setDropNodeId(a2Node.getId());
request.setDropPosition(1);
this.requestPostWithOk(URL_MODULE_MOVE, request);
this.checkModulePos(a2Node.getId(), a3Node.getId(), null, false);
}
//移动到没有子节点的节点下 a3移动到a2下
{
//开始移动
request = new NodeMoveRequest();
request.setDragNodeId(a3Node.getId());
request.setDropNodeId(a2Node.getId());
request.setDropPosition(0);
this.requestPostWithOk(URL_MODULE_MOVE, request);
ApiDefinitionModule a3Module = apiDefinitionModuleMapper.selectByPrimaryKey(a3Node.getId());
Assertions.assertEquals(a3Module.getParentId(), a2Node.getId());
//移动回去
request = new NodeMoveRequest();
request.setDragNodeId(a3Node.getId());
request.setDropNodeId(a2Node.getId());
request.setDropPosition(1);
this.requestPostWithOk(URL_MODULE_MOVE, request);
this.checkModulePos(a2Node.getId(), a3Node.getId(), null, false);
}
checkLog(a1Node.getId(), OperationLogType.UPDATE, URL_MODULE_MOVE);
checkLog(a3Node.getId(), OperationLogType.UPDATE, URL_MODULE_MOVE);
requestPostPermissionTest(PermissionConstants.PROJECT_API_DEFINITION_READ_UPDATE, URL_MODULE_MOVE, request);
}
@Test
@Order(7)
public void moveTestError() throws Exception {
this.preliminaryData();
BaseTreeNode a1Node = getNodeByName(preliminaryTreeNodes, "a1");
BaseTreeNode a2Node = getNodeByName(preliminaryTreeNodes, "a2");
//drag节点为空
NodeMoveRequest request = new NodeMoveRequest();
request.setDragNodeId(null);
assert a1Node != null;
request.setDropNodeId(a1Node.getId());
request.setDropPosition(1);
this.requestPost(URL_MODULE_MOVE, request).andExpect(BAD_REQUEST_MATCHER);
//drag节点不存在
request = new NodeMoveRequest();
request.setDragNodeId(IDGenerator.nextStr());
request.setDropNodeId(a1Node.getId());
request.setDropPosition(1);
this.requestPost(URL_MODULE_MOVE, request).andExpect(ERROR_REQUEST_MATCHER);
//drop节点为空
request = new NodeMoveRequest();
request.setDragNodeId(a1Node.getId());
request.setDropNodeId(null);
request.setDropPosition(1);
this.requestPost(URL_MODULE_MOVE, request).andExpect(BAD_REQUEST_MATCHER);
//drop节点不存在
request = new NodeMoveRequest();
request.setDragNodeId(a1Node.getId());
request.setDropNodeId(IDGenerator.nextStr());
request.setDropPosition(1);
this.requestPost(URL_MODULE_MOVE, request).andExpect(ERROR_REQUEST_MATCHER);
//position为0的时候节点不存在
request = new NodeMoveRequest();
request.setDragNodeId(a1Node.getId());
request.setDropNodeId(IDGenerator.nextStr());
request.setDropPosition(0);
this.requestPost(URL_MODULE_MOVE, request).andExpect(ERROR_REQUEST_MATCHER);
//dragNode和dropNode一样
request = new NodeMoveRequest();
request.setDragNodeId(a1Node.getId());
request.setDropNodeId(a1Node.getId());
request.setDropPosition(1);
this.requestPost(URL_MODULE_MOVE, request).andExpect(ERROR_REQUEST_MATCHER);
//position不是-1 0 1
request = new NodeMoveRequest();
request.setDragNodeId(a1Node.getId());
assert a2Node != null;
request.setDropNodeId(a2Node.getId());
request.setDropPosition(4);
this.requestPost(URL_MODULE_MOVE, request).andExpect(ERROR_REQUEST_MATCHER);
}
@Test
@Order(8)
public void TestModuleCountSuccess() throws Exception {
this.preliminaryData();
ApiModuleRequest request = new ApiModuleRequest() {{
this.setProtocol("HTTP");
this.setProjectId(project.getId());
}};
MvcResult moduleCountMvcResult = this.requestPostWithOkAndReturn(URL_FILE_MODULE_COUNT, request);
Map<String, Integer> moduleCountResult = JSON.parseObject(JSON.toJSONString(
JSON.parseObject(moduleCountMvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8), ResultHolder.class).getData()),
Map.class);
Assertions.assertTrue(moduleCountResult.containsKey("all"));
request.setProjectId(DEFAULT_PROJECT_ID);
requestPostPermissionTest(PermissionConstants.PROJECT_API_DEFINITION_READ, URL_FILE_MODULE_COUNT, request);
}
@Test
@Order(8)
public void TestModuleCountError() throws Exception {
ApiDebugRequest request = new ApiDebugRequest();
request.setProtocol(null);
this.requestPost(URL_FILE_MODULE_COUNT, request).andExpect(BAD_REQUEST_MATCHER);
}
@Test
@Order(10)
public void deleteModuleTestSuccess() throws Exception {
this.preliminaryData();
// 删除没有文件的节点a1-b1-c1 检查是否级联删除根节点
BaseTreeNode a1b1Node = getNodeByName(this.getModuleTreeNode(), "a1-b1");
assert a1b1Node != null;
this.requestGetWithOk(String.format(URL_MODULE_DELETE, a1b1Node.getId()));
this.checkModuleIsEmpty(a1b1Node.getId());
checkLog(a1b1Node.getId(), OperationLogType.DELETE, URL_MODULE_DELETE);
// 删除有文件的节点 a1-a1 检查是否级联删除根节点
BaseTreeNode a1a1Node = getNodeByName(this.getModuleTreeNode(), "a1-a1");
assert a1a1Node != null;
this.requestGetWithOk(String.format(URL_MODULE_DELETE, a1a1Node.getId()));
this.checkModuleIsEmpty(a1a1Node.getId());
checkLog(a1a1Node.getId(), OperationLogType.DELETE, URL_MODULE_DELETE);
//删除不存在的节点
this.requestGetWithOk(String.format(URL_MODULE_DELETE, IDGenerator.nextNum()));
// 测试删除根节点
this.requestGetWithOk(String.format(URL_MODULE_DELETE, ModuleConstants.DEFAULT_NODE_ID));
//service层判断测试删除空集合
apiDefinitionModuleService.deleteModule(new ArrayList<>(), "admin", DEFAULT_PROJECT_ID);
//校验权限
requestGetPermissionTest(PermissionConstants.PROJECT_API_DEFINITION_READ_DELETE, String.format(URL_MODULE_DELETE, IDGenerator.nextNum()));
}
private List<BaseTreeNode> getModuleTreeNode() throws Exception {
MvcResult result = this.requestPostWithOkAndReturn(URL_MODULE_TREE, new ApiModuleRequest() {{
this.setProtocol("HTTP");
this.setProjectId(project.getId());
}});
String returnData = result.getResponse().getContentAsString(StandardCharsets.UTF_8);
ResultHolder resultHolder = JSON.parseObject(returnData, ResultHolder.class);
return JSON.parseArray(JSON.toJSONString(resultHolder.getData()), BaseTreeNode.class);
}
private void preliminaryData() throws Exception {
if (CollectionUtils.isEmpty(preliminaryTreeNodes)) {
/*
这里需要获取修改过的树的结构期望的最终结构是这样的*为测试用例中挂载文件的节点 · 为空节点
*默认节点
|
·a1 +
| |
| ·a1-b1 +
| | |
| | ·a1-b1-c1
| |
| *a1-a1 +创建的时候是a1通过修改改为a1-a1
| | |
| | ·a1-a1-c1
|
·a2
|
·a3
*/
this.updateModuleTestSuccess();
}
}
private void checkModuleIsEmpty(String id) {
ApiDefinitionModuleExample example = new ApiDefinitionModuleExample();
example.createCriteria().andParentIdEqualTo(id);
Assertions.assertEquals(0, apiDefinitionModuleMapper.countByExample(example));
ApiDefinitionExample apiDebugExample = new ApiDefinitionExample();
example = new ApiDefinitionModuleExample();
example.createCriteria().andIdEqualTo(id);
Assertions.assertEquals(0, apiDefinitionModuleMapper.countByExample(example));
apiDebugExample.createCriteria().andModuleIdEqualTo(id).andDeletedEqualTo(false);
Assertions.assertEquals(0, apiDefinitionMapper.countByExample(apiDebugExample));
}
private void checkModulePos(String firstNode, String secondNode, String thirdNode, boolean isRecalculate) {
ApiDefinitionModule firstModule = apiDefinitionModuleMapper.selectByPrimaryKey(firstNode);
ApiDefinitionModule secondModule = apiDefinitionModuleMapper.selectByPrimaryKey(secondNode);
ApiDefinitionModule thirdModule = null;
Assertions.assertTrue(firstModule.getPos() < secondModule.getPos());
if (StringUtils.isNotBlank(thirdNode)) {
thirdModule = apiDefinitionModuleMapper.selectByPrimaryKey(thirdNode);
Assertions.assertTrue(secondModule.getPos() < thirdModule.getPos());
}
if (isRecalculate) {
int limitPos = 64;
Assertions.assertEquals(0, firstModule.getPos() % limitPos);
Assertions.assertEquals(0, secondModule.getPos() % limitPos);
if (thirdModule != null) {
Assertions.assertEquals(0, thirdModule.getPos() % limitPos);
}
}
}
}