feat(项目管理): 项目管理公共脚本模块

This commit is contained in:
lan-yonghui 2024-01-11 22:23:51 +08:00 committed by Craftsman
parent ac0c2f0301
commit d1e36c20b9
24 changed files with 1841 additions and 82 deletions

View File

@ -6,33 +6,65 @@ import jakarta.validation.constraints.*;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import lombok.Data;
@Data
public class CustomFunction implements Serializable {
@Schema(description = "", requiredMode = Schema.RequiredMode.REQUIRED)
@Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{custom_function.id.not_blank}", groups = {Updated.class})
@Size(min = 1, max = 50, message = "{custom_function.id.length_range}", groups = {Created.class, Updated.class})
private String id;
@Schema(description = "函数名", requiredMode = Schema.RequiredMode.REQUIRED)
@Schema(description = "项目ID", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{custom_function.project_id.not_blank}", groups = {Created.class})
@Size(min = 1, max = 50, message = "{custom_function.project_id.length_range}", groups = {Created.class, Updated.class})
private String projectId;
@Schema(description = "函数名", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{custom_function.name.not_blank}", groups = {Created.class})
@Size(min = 1, max = 255, message = "{custom_function.name.length_range}", groups = {Created.class, Updated.class})
private String name;
@Schema(description = "标签")
private String tags;
@Schema(description = "标签")
private List<String> tags;
@Schema(description = "函数描述")
@Schema(description = "函数描述")
private String description;
@Schema(description = "脚本语言类型")
private String type;
@Schema(description = "脚本状态(进行中/已完成)")
private String status;
@Schema(description = "创建时间")
private Long createTime;
@Schema(description = "更新时间")
private Long updateTime;
@Schema(description = "创建人")
private String createUser;
@Schema(description = "更新人")
private String updateUser;
private static final long serialVersionUID = 1L;
public enum Column {
id("id", "id", "VARCHAR", false),
projectId("project_id", "projectId", "VARCHAR", false),
name("name", "name", "VARCHAR", true),
tags("tags", "tags", "VARCHAR", false),
description("description", "description", "VARCHAR", false);
description("description", "description", "VARCHAR", false),
type("type", "type", "VARCHAR", true),
status("status", "status", "VARCHAR", true),
createTime("create_time", "createTime", "BIGINT", false),
updateTime("update_time", "updateTime", "BIGINT", false),
createUser("create_user", "createUser", "VARCHAR", false),
updateUser("update_user", "updateUser", "VARCHAR", false);
private static final String BEGINNING_DELIMITER = "`";

View File

@ -64,19 +64,50 @@ public class CustomFunctionExample {
}
protected abstract static class GeneratedCriteria {
protected List<Criterion> tagsCriteria;
protected List<Criterion> allCriteria;
protected List<Criterion> criteria;
protected GeneratedCriteria() {
super();
criteria = new ArrayList<Criterion>();
tagsCriteria = new ArrayList<Criterion>();
}
public List<Criterion> getTagsCriteria() {
return tagsCriteria;
}
protected void addTagsCriterion(String condition, Object value, String property) {
if (value == null) {
throw new RuntimeException("Value for " + property + " cannot be null");
}
tagsCriteria.add(new Criterion(condition, value, "io.metersphere.handler.ListTypeHandler"));
allCriteria = null;
}
protected void addTagsCriterion(String condition, List<String> value1, List<String> value2, String property) {
if (value1 == null || value2 == null) {
throw new RuntimeException("Between values for " + property + " cannot be null");
}
tagsCriteria.add(new Criterion(condition, value1, value2, "io.metersphere.handler.ListTypeHandler"));
allCriteria = null;
}
public boolean isValid() {
return criteria.size() > 0;
return criteria.size() > 0
|| tagsCriteria.size() > 0;
}
public List<Criterion> getAllCriteria() {
return criteria;
if (allCriteria == null) {
allCriteria = new ArrayList<Criterion>();
allCriteria.addAll(criteria);
allCriteria.addAll(tagsCriteria);
}
return allCriteria;
}
public List<Criterion> getCriteria() {
@ -88,6 +119,7 @@ public class CustomFunctionExample {
throw new RuntimeException("Value for condition cannot be null");
}
criteria.add(new Criterion(condition));
allCriteria = null;
}
protected void addCriterion(String condition, Object value, String property) {
@ -95,6 +127,7 @@ public class CustomFunctionExample {
throw new RuntimeException("Value for " + property + " cannot be null");
}
criteria.add(new Criterion(condition, value));
allCriteria = null;
}
protected void addCriterion(String condition, Object value1, Object value2, String property) {
@ -102,6 +135,7 @@ public class CustomFunctionExample {
throw new RuntimeException("Between values for " + property + " cannot be null");
}
criteria.add(new Criterion(condition, value1, value2));
allCriteria = null;
}
public Criteria andIdIsNull() {
@ -174,6 +208,76 @@ public class CustomFunctionExample {
return (Criteria) this;
}
public Criteria andProjectIdIsNull() {
addCriterion("project_id is null");
return (Criteria) this;
}
public Criteria andProjectIdIsNotNull() {
addCriterion("project_id is not null");
return (Criteria) this;
}
public Criteria andProjectIdEqualTo(String value) {
addCriterion("project_id =", value, "projectId");
return (Criteria) this;
}
public Criteria andProjectIdNotEqualTo(String value) {
addCriterion("project_id <>", value, "projectId");
return (Criteria) this;
}
public Criteria andProjectIdGreaterThan(String value) {
addCriterion("project_id >", value, "projectId");
return (Criteria) this;
}
public Criteria andProjectIdGreaterThanOrEqualTo(String value) {
addCriterion("project_id >=", value, "projectId");
return (Criteria) this;
}
public Criteria andProjectIdLessThan(String value) {
addCriterion("project_id <", value, "projectId");
return (Criteria) this;
}
public Criteria andProjectIdLessThanOrEqualTo(String value) {
addCriterion("project_id <=", value, "projectId");
return (Criteria) this;
}
public Criteria andProjectIdLike(String value) {
addCriterion("project_id like", value, "projectId");
return (Criteria) this;
}
public Criteria andProjectIdNotLike(String value) {
addCriterion("project_id not like", value, "projectId");
return (Criteria) this;
}
public Criteria andProjectIdIn(List<String> values) {
addCriterion("project_id in", values, "projectId");
return (Criteria) this;
}
public Criteria andProjectIdNotIn(List<String> values) {
addCriterion("project_id not in", values, "projectId");
return (Criteria) this;
}
public Criteria andProjectIdBetween(String value1, String value2) {
addCriterion("project_id between", value1, value2, "projectId");
return (Criteria) this;
}
public Criteria andProjectIdNotBetween(String value1, String value2) {
addCriterion("project_id not between", value1, value2, "projectId");
return (Criteria) this;
}
public Criteria andNameIsNull() {
addCriterion("`name` is null");
return (Criteria) this;
@ -254,63 +358,63 @@ public class CustomFunctionExample {
return (Criteria) this;
}
public Criteria andTagsEqualTo(String value) {
addCriterion("tags =", value, "tags");
public Criteria andTagsEqualTo(List<String> value) {
addTagsCriterion("tags =", value, "tags");
return (Criteria) this;
}
public Criteria andTagsNotEqualTo(String value) {
addCriterion("tags <>", value, "tags");
public Criteria andTagsNotEqualTo(List<String> value) {
addTagsCriterion("tags <>", value, "tags");
return (Criteria) this;
}
public Criteria andTagsGreaterThan(String value) {
addCriterion("tags >", value, "tags");
public Criteria andTagsGreaterThan(List<String> value) {
addTagsCriterion("tags >", value, "tags");
return (Criteria) this;
}
public Criteria andTagsGreaterThanOrEqualTo(String value) {
addCriterion("tags >=", value, "tags");
public Criteria andTagsGreaterThanOrEqualTo(List<String> value) {
addTagsCriterion("tags >=", value, "tags");
return (Criteria) this;
}
public Criteria andTagsLessThan(String value) {
addCriterion("tags <", value, "tags");
public Criteria andTagsLessThan(List<String> value) {
addTagsCriterion("tags <", value, "tags");
return (Criteria) this;
}
public Criteria andTagsLessThanOrEqualTo(String value) {
addCriterion("tags <=", value, "tags");
public Criteria andTagsLessThanOrEqualTo(List<String> value) {
addTagsCriterion("tags <=", value, "tags");
return (Criteria) this;
}
public Criteria andTagsLike(String value) {
addCriterion("tags like", value, "tags");
public Criteria andTagsLike(List<String> value) {
addTagsCriterion("tags like", value, "tags");
return (Criteria) this;
}
public Criteria andTagsNotLike(String value) {
addCriterion("tags not like", value, "tags");
public Criteria andTagsNotLike(List<String> value) {
addTagsCriterion("tags not like", value, "tags");
return (Criteria) this;
}
public Criteria andTagsIn(List<String> values) {
addCriterion("tags in", values, "tags");
public Criteria andTagsIn(List<List<String>> values) {
addTagsCriterion("tags in", values, "tags");
return (Criteria) this;
}
public Criteria andTagsNotIn(List<String> values) {
addCriterion("tags not in", values, "tags");
public Criteria andTagsNotIn(List<List<String>> values) {
addTagsCriterion("tags not in", values, "tags");
return (Criteria) this;
}
public Criteria andTagsBetween(String value1, String value2) {
addCriterion("tags between", value1, value2, "tags");
public Criteria andTagsBetween(List<String> value1, List<String> value2) {
addTagsCriterion("tags between", value1, value2, "tags");
return (Criteria) this;
}
public Criteria andTagsNotBetween(String value1, String value2) {
addCriterion("tags not between", value1, value2, "tags");
public Criteria andTagsNotBetween(List<String> value1, List<String> value2) {
addTagsCriterion("tags not between", value1, value2, "tags");
return (Criteria) this;
}
@ -383,6 +487,406 @@ public class CustomFunctionExample {
addCriterion("description not between", value1, value2, "description");
return (Criteria) this;
}
public Criteria andTypeIsNull() {
addCriterion("`type` is null");
return (Criteria) this;
}
public Criteria andTypeIsNotNull() {
addCriterion("`type` is not null");
return (Criteria) this;
}
public Criteria andTypeEqualTo(String value) {
addCriterion("`type` =", value, "type");
return (Criteria) this;
}
public Criteria andTypeNotEqualTo(String value) {
addCriterion("`type` <>", value, "type");
return (Criteria) this;
}
public Criteria andTypeGreaterThan(String value) {
addCriterion("`type` >", value, "type");
return (Criteria) this;
}
public Criteria andTypeGreaterThanOrEqualTo(String value) {
addCriterion("`type` >=", value, "type");
return (Criteria) this;
}
public Criteria andTypeLessThan(String value) {
addCriterion("`type` <", value, "type");
return (Criteria) this;
}
public Criteria andTypeLessThanOrEqualTo(String value) {
addCriterion("`type` <=", value, "type");
return (Criteria) this;
}
public Criteria andTypeLike(String value) {
addCriterion("`type` like", value, "type");
return (Criteria) this;
}
public Criteria andTypeNotLike(String value) {
addCriterion("`type` not like", value, "type");
return (Criteria) this;
}
public Criteria andTypeIn(List<String> values) {
addCriterion("`type` in", values, "type");
return (Criteria) this;
}
public Criteria andTypeNotIn(List<String> values) {
addCriterion("`type` not in", values, "type");
return (Criteria) this;
}
public Criteria andTypeBetween(String value1, String value2) {
addCriterion("`type` between", value1, value2, "type");
return (Criteria) this;
}
public Criteria andTypeNotBetween(String value1, String value2) {
addCriterion("`type` not between", value1, value2, "type");
return (Criteria) this;
}
public Criteria andStatusIsNull() {
addCriterion("`status` is null");
return (Criteria) this;
}
public Criteria andStatusIsNotNull() {
addCriterion("`status` is not null");
return (Criteria) this;
}
public Criteria andStatusEqualTo(String value) {
addCriterion("`status` =", value, "status");
return (Criteria) this;
}
public Criteria andStatusNotEqualTo(String value) {
addCriterion("`status` <>", value, "status");
return (Criteria) this;
}
public Criteria andStatusGreaterThan(String value) {
addCriterion("`status` >", value, "status");
return (Criteria) this;
}
public Criteria andStatusGreaterThanOrEqualTo(String value) {
addCriterion("`status` >=", value, "status");
return (Criteria) this;
}
public Criteria andStatusLessThan(String value) {
addCriterion("`status` <", value, "status");
return (Criteria) this;
}
public Criteria andStatusLessThanOrEqualTo(String value) {
addCriterion("`status` <=", value, "status");
return (Criteria) this;
}
public Criteria andStatusLike(String value) {
addCriterion("`status` like", value, "status");
return (Criteria) this;
}
public Criteria andStatusNotLike(String value) {
addCriterion("`status` not like", value, "status");
return (Criteria) this;
}
public Criteria andStatusIn(List<String> values) {
addCriterion("`status` in", values, "status");
return (Criteria) this;
}
public Criteria andStatusNotIn(List<String> values) {
addCriterion("`status` not in", values, "status");
return (Criteria) this;
}
public Criteria andStatusBetween(String value1, String value2) {
addCriterion("`status` between", value1, value2, "status");
return (Criteria) this;
}
public Criteria andStatusNotBetween(String value1, String value2) {
addCriterion("`status` not between", value1, value2, "status");
return (Criteria) this;
}
public Criteria andCreateTimeIsNull() {
addCriterion("create_time is null");
return (Criteria) this;
}
public Criteria andCreateTimeIsNotNull() {
addCriterion("create_time is not null");
return (Criteria) this;
}
public Criteria andCreateTimeEqualTo(Long value) {
addCriterion("create_time =", value, "createTime");
return (Criteria) this;
}
public Criteria andCreateTimeNotEqualTo(Long value) {
addCriterion("create_time <>", value, "createTime");
return (Criteria) this;
}
public Criteria andCreateTimeGreaterThan(Long value) {
addCriterion("create_time >", value, "createTime");
return (Criteria) this;
}
public Criteria andCreateTimeGreaterThanOrEqualTo(Long value) {
addCriterion("create_time >=", value, "createTime");
return (Criteria) this;
}
public Criteria andCreateTimeLessThan(Long value) {
addCriterion("create_time <", value, "createTime");
return (Criteria) this;
}
public Criteria andCreateTimeLessThanOrEqualTo(Long value) {
addCriterion("create_time <=", value, "createTime");
return (Criteria) this;
}
public Criteria andCreateTimeIn(List<Long> values) {
addCriterion("create_time in", values, "createTime");
return (Criteria) this;
}
public Criteria andCreateTimeNotIn(List<Long> values) {
addCriterion("create_time not in", values, "createTime");
return (Criteria) this;
}
public Criteria andCreateTimeBetween(Long value1, Long value2) {
addCriterion("create_time between", value1, value2, "createTime");
return (Criteria) this;
}
public Criteria andCreateTimeNotBetween(Long value1, Long value2) {
addCriterion("create_time not between", value1, value2, "createTime");
return (Criteria) this;
}
public Criteria andUpdateTimeIsNull() {
addCriterion("update_time is null");
return (Criteria) this;
}
public Criteria andUpdateTimeIsNotNull() {
addCriterion("update_time is not null");
return (Criteria) this;
}
public Criteria andUpdateTimeEqualTo(Long value) {
addCriterion("update_time =", value, "updateTime");
return (Criteria) this;
}
public Criteria andUpdateTimeNotEqualTo(Long value) {
addCriterion("update_time <>", value, "updateTime");
return (Criteria) this;
}
public Criteria andUpdateTimeGreaterThan(Long value) {
addCriterion("update_time >", value, "updateTime");
return (Criteria) this;
}
public Criteria andUpdateTimeGreaterThanOrEqualTo(Long value) {
addCriterion("update_time >=", value, "updateTime");
return (Criteria) this;
}
public Criteria andUpdateTimeLessThan(Long value) {
addCriterion("update_time <", value, "updateTime");
return (Criteria) this;
}
public Criteria andUpdateTimeLessThanOrEqualTo(Long value) {
addCriterion("update_time <=", value, "updateTime");
return (Criteria) this;
}
public Criteria andUpdateTimeIn(List<Long> values) {
addCriterion("update_time in", values, "updateTime");
return (Criteria) this;
}
public Criteria andUpdateTimeNotIn(List<Long> values) {
addCriterion("update_time not in", values, "updateTime");
return (Criteria) this;
}
public Criteria andUpdateTimeBetween(Long value1, Long value2) {
addCriterion("update_time between", value1, value2, "updateTime");
return (Criteria) this;
}
public Criteria andUpdateTimeNotBetween(Long value1, Long value2) {
addCriterion("update_time not between", value1, value2, "updateTime");
return (Criteria) this;
}
public Criteria andCreateUserIsNull() {
addCriterion("create_user is null");
return (Criteria) this;
}
public Criteria andCreateUserIsNotNull() {
addCriterion("create_user is not null");
return (Criteria) this;
}
public Criteria andCreateUserEqualTo(String value) {
addCriterion("create_user =", value, "createUser");
return (Criteria) this;
}
public Criteria andCreateUserNotEqualTo(String value) {
addCriterion("create_user <>", value, "createUser");
return (Criteria) this;
}
public Criteria andCreateUserGreaterThan(String value) {
addCriterion("create_user >", value, "createUser");
return (Criteria) this;
}
public Criteria andCreateUserGreaterThanOrEqualTo(String value) {
addCriterion("create_user >=", value, "createUser");
return (Criteria) this;
}
public Criteria andCreateUserLessThan(String value) {
addCriterion("create_user <", value, "createUser");
return (Criteria) this;
}
public Criteria andCreateUserLessThanOrEqualTo(String value) {
addCriterion("create_user <=", value, "createUser");
return (Criteria) this;
}
public Criteria andCreateUserLike(String value) {
addCriterion("create_user like", value, "createUser");
return (Criteria) this;
}
public Criteria andCreateUserNotLike(String value) {
addCriterion("create_user not like", value, "createUser");
return (Criteria) this;
}
public Criteria andCreateUserIn(List<String> values) {
addCriterion("create_user in", values, "createUser");
return (Criteria) this;
}
public Criteria andCreateUserNotIn(List<String> values) {
addCriterion("create_user not in", values, "createUser");
return (Criteria) this;
}
public Criteria andCreateUserBetween(String value1, String value2) {
addCriterion("create_user between", value1, value2, "createUser");
return (Criteria) this;
}
public Criteria andCreateUserNotBetween(String value1, String value2) {
addCriterion("create_user not between", value1, value2, "createUser");
return (Criteria) this;
}
public Criteria andUpdateUserIsNull() {
addCriterion("update_user is null");
return (Criteria) this;
}
public Criteria andUpdateUserIsNotNull() {
addCriterion("update_user is not null");
return (Criteria) this;
}
public Criteria andUpdateUserEqualTo(String value) {
addCriterion("update_user =", value, "updateUser");
return (Criteria) this;
}
public Criteria andUpdateUserNotEqualTo(String value) {
addCriterion("update_user <>", value, "updateUser");
return (Criteria) this;
}
public Criteria andUpdateUserGreaterThan(String value) {
addCriterion("update_user >", value, "updateUser");
return (Criteria) this;
}
public Criteria andUpdateUserGreaterThanOrEqualTo(String value) {
addCriterion("update_user >=", value, "updateUser");
return (Criteria) this;
}
public Criteria andUpdateUserLessThan(String value) {
addCriterion("update_user <", value, "updateUser");
return (Criteria) this;
}
public Criteria andUpdateUserLessThanOrEqualTo(String value) {
addCriterion("update_user <=", value, "updateUser");
return (Criteria) this;
}
public Criteria andUpdateUserLike(String value) {
addCriterion("update_user like", value, "updateUser");
return (Criteria) this;
}
public Criteria andUpdateUserNotLike(String value) {
addCriterion("update_user not like", value, "updateUser");
return (Criteria) this;
}
public Criteria andUpdateUserIn(List<String> values) {
addCriterion("update_user in", values, "updateUser");
return (Criteria) this;
}
public Criteria andUpdateUserNotIn(List<String> values) {
addCriterion("update_user not in", values, "updateUser");
return (Criteria) this;
}
public Criteria andUpdateUserBetween(String value1, String value2) {
addCriterion("update_user between", value1, value2, "updateUser");
return (Criteria) this;
}
public Criteria andUpdateUserNotBetween(String value1, String value2) {
addCriterion("update_user not between", value1, value2, "updateUser");
return (Criteria) this;
}
}
public static class Criteria extends GeneratedCriteria {

View File

@ -3,9 +3,16 @@
<mapper namespace="io.metersphere.project.mapper.CustomFunctionMapper">
<resultMap id="BaseResultMap" type="io.metersphere.project.domain.CustomFunction">
<id column="id" jdbcType="VARCHAR" property="id" />
<result column="project_id" jdbcType="VARCHAR" property="projectId" />
<result column="name" jdbcType="VARCHAR" property="name" />
<result column="tags" jdbcType="VARCHAR" property="tags" />
<result column="tags" jdbcType="VARCHAR" property="tags" typeHandler="io.metersphere.handler.ListTypeHandler" />
<result column="description" jdbcType="VARCHAR" property="description" />
<result column="type" jdbcType="VARCHAR" property="type" />
<result column="status" jdbcType="VARCHAR" property="status" />
<result column="create_time" jdbcType="BIGINT" property="createTime" />
<result column="update_time" jdbcType="BIGINT" property="updateTime" />
<result column="create_user" jdbcType="VARCHAR" property="createUser" />
<result column="update_user" jdbcType="VARCHAR" property="updateUser" />
</resultMap>
<sql id="Example_Where_Clause">
<where>
@ -31,6 +38,25 @@
</when>
</choose>
</foreach>
<foreach collection="criteria.tagsCriteria" item="criterion">
<choose>
<when test="criterion.noValue">
and ${criterion.condition}
</when>
<when test="criterion.singleValue">
and ${criterion.condition} #{criterion.value,typeHandler=io.metersphere.handler.ListTypeHandler}
</when>
<when test="criterion.betweenValue">
and ${criterion.condition} #{criterion.value,typeHandler=io.metersphere.handler.ListTypeHandler} and #{criterion.secondValue,typeHandler=io.metersphere.handler.ListTypeHandler}
</when>
<when test="criterion.listValue">
and ${criterion.condition}
<foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
#{listItem,typeHandler=io.metersphere.handler.ListTypeHandler}
</foreach>
</when>
</choose>
</foreach>
</trim>
</if>
</foreach>
@ -60,13 +86,33 @@
</when>
</choose>
</foreach>
<foreach collection="criteria.tagsCriteria" item="criterion">
<choose>
<when test="criterion.noValue">
and ${criterion.condition}
</when>
<when test="criterion.singleValue">
and ${criterion.condition} #{criterion.value,typeHandler=io.metersphere.handler.ListTypeHandler}
</when>
<when test="criterion.betweenValue">
and ${criterion.condition} #{criterion.value,typeHandler=io.metersphere.handler.ListTypeHandler} and #{criterion.secondValue,typeHandler=io.metersphere.handler.ListTypeHandler}
</when>
<when test="criterion.listValue">
and ${criterion.condition}
<foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
#{listItem,typeHandler=io.metersphere.handler.ListTypeHandler}
</foreach>
</when>
</choose>
</foreach>
</trim>
</if>
</foreach>
</where>
</sql>
<sql id="Base_Column_List">
id, `name`, tags, description
id, project_id, `name`, tags, description, `type`, `status`, create_time, update_time,
create_user, update_user
</sql>
<select id="selectByExample" parameterType="io.metersphere.project.domain.CustomFunctionExample" resultMap="BaseResultMap">
select
@ -99,10 +145,16 @@
</if>
</delete>
<insert id="insert" parameterType="io.metersphere.project.domain.CustomFunction">
insert into custom_function (id, `name`, tags,
description)
values (#{id,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{tags,jdbcType=VARCHAR},
#{description,jdbcType=VARCHAR})
insert into custom_function (id, project_id, `name`,
tags, description,
`type`, `status`, create_time,
update_time, create_user, update_user
)
values (#{id,jdbcType=VARCHAR}, #{projectId,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR},
#{tags,jdbcType=VARCHAR,typeHandler=io.metersphere.handler.ListTypeHandler}, #{description,jdbcType=VARCHAR},
#{type,jdbcType=VARCHAR}, #{status,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT},
#{updateTime,jdbcType=BIGINT}, #{createUser,jdbcType=VARCHAR}, #{updateUser,jdbcType=VARCHAR}
)
</insert>
<insert id="insertSelective" parameterType="io.metersphere.project.domain.CustomFunction">
insert into custom_function
@ -110,6 +162,9 @@
<if test="id != null">
id,
</if>
<if test="projectId != null">
project_id,
</if>
<if test="name != null">
`name`,
</if>
@ -119,20 +174,59 @@
<if test="description != null">
description,
</if>
<if test="type != null">
`type`,
</if>
<if test="status != null">
`status`,
</if>
<if test="createTime != null">
create_time,
</if>
<if test="updateTime != null">
update_time,
</if>
<if test="createUser != null">
create_user,
</if>
<if test="updateUser != null">
update_user,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="id != null">
#{id,jdbcType=VARCHAR},
</if>
<if test="projectId != null">
#{projectId,jdbcType=VARCHAR},
</if>
<if test="name != null">
#{name,jdbcType=VARCHAR},
</if>
<if test="tags != null">
#{tags,jdbcType=VARCHAR},
#{tags,jdbcType=VARCHAR,typeHandler=io.metersphere.handler.ListTypeHandler},
</if>
<if test="description != null">
#{description,jdbcType=VARCHAR},
</if>
<if test="type != null">
#{type,jdbcType=VARCHAR},
</if>
<if test="status != null">
#{status,jdbcType=VARCHAR},
</if>
<if test="createTime != null">
#{createTime,jdbcType=BIGINT},
</if>
<if test="updateTime != null">
#{updateTime,jdbcType=BIGINT},
</if>
<if test="createUser != null">
#{createUser,jdbcType=VARCHAR},
</if>
<if test="updateUser != null">
#{updateUser,jdbcType=VARCHAR},
</if>
</trim>
</insert>
<select id="countByExample" parameterType="io.metersphere.project.domain.CustomFunctionExample" resultType="java.lang.Long">
@ -147,15 +241,36 @@
<if test="record.id != null">
id = #{record.id,jdbcType=VARCHAR},
</if>
<if test="record.projectId != null">
project_id = #{record.projectId,jdbcType=VARCHAR},
</if>
<if test="record.name != null">
`name` = #{record.name,jdbcType=VARCHAR},
</if>
<if test="record.tags != null">
tags = #{record.tags,jdbcType=VARCHAR},
tags = #{record.tags,jdbcType=VARCHAR,typeHandler=io.metersphere.handler.ListTypeHandler},
</if>
<if test="record.description != null">
description = #{record.description,jdbcType=VARCHAR},
</if>
<if test="record.type != null">
`type` = #{record.type,jdbcType=VARCHAR},
</if>
<if test="record.status != null">
`status` = #{record.status,jdbcType=VARCHAR},
</if>
<if test="record.createTime != null">
create_time = #{record.createTime,jdbcType=BIGINT},
</if>
<if test="record.updateTime != null">
update_time = #{record.updateTime,jdbcType=BIGINT},
</if>
<if test="record.createUser != null">
create_user = #{record.createUser,jdbcType=VARCHAR},
</if>
<if test="record.updateUser != null">
update_user = #{record.updateUser,jdbcType=VARCHAR},
</if>
</set>
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
@ -164,9 +279,16 @@
<update id="updateByExample" parameterType="map">
update custom_function
set id = #{record.id,jdbcType=VARCHAR},
project_id = #{record.projectId,jdbcType=VARCHAR},
`name` = #{record.name,jdbcType=VARCHAR},
tags = #{record.tags,jdbcType=VARCHAR},
description = #{record.description,jdbcType=VARCHAR}
tags = #{record.tags,jdbcType=VARCHAR,typeHandler=io.metersphere.handler.ListTypeHandler},
description = #{record.description,jdbcType=VARCHAR},
`type` = #{record.type,jdbcType=VARCHAR},
`status` = #{record.status,jdbcType=VARCHAR},
create_time = #{record.createTime,jdbcType=BIGINT},
update_time = #{record.updateTime,jdbcType=BIGINT},
create_user = #{record.createUser,jdbcType=VARCHAR},
update_user = #{record.updateUser,jdbcType=VARCHAR}
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
</if>
@ -174,32 +296,64 @@
<update id="updateByPrimaryKeySelective" parameterType="io.metersphere.project.domain.CustomFunction">
update custom_function
<set>
<if test="projectId != null">
project_id = #{projectId,jdbcType=VARCHAR},
</if>
<if test="name != null">
`name` = #{name,jdbcType=VARCHAR},
</if>
<if test="tags != null">
tags = #{tags,jdbcType=VARCHAR},
tags = #{tags,jdbcType=VARCHAR,typeHandler=io.metersphere.handler.ListTypeHandler},
</if>
<if test="description != null">
description = #{description,jdbcType=VARCHAR},
</if>
<if test="type != null">
`type` = #{type,jdbcType=VARCHAR},
</if>
<if test="status != null">
`status` = #{status,jdbcType=VARCHAR},
</if>
<if test="createTime != null">
create_time = #{createTime,jdbcType=BIGINT},
</if>
<if test="updateTime != null">
update_time = #{updateTime,jdbcType=BIGINT},
</if>
<if test="createUser != null">
create_user = #{createUser,jdbcType=VARCHAR},
</if>
<if test="updateUser != null">
update_user = #{updateUser,jdbcType=VARCHAR},
</if>
</set>
where id = #{id,jdbcType=VARCHAR}
</update>
<update id="updateByPrimaryKey" parameterType="io.metersphere.project.domain.CustomFunction">
update custom_function
set `name` = #{name,jdbcType=VARCHAR},
tags = #{tags,jdbcType=VARCHAR},
description = #{description,jdbcType=VARCHAR}
set project_id = #{projectId,jdbcType=VARCHAR},
`name` = #{name,jdbcType=VARCHAR},
tags = #{tags,jdbcType=VARCHAR,typeHandler=io.metersphere.handler.ListTypeHandler},
description = #{description,jdbcType=VARCHAR},
`type` = #{type,jdbcType=VARCHAR},
`status` = #{status,jdbcType=VARCHAR},
create_time = #{createTime,jdbcType=BIGINT},
update_time = #{updateTime,jdbcType=BIGINT},
create_user = #{createUser,jdbcType=VARCHAR},
update_user = #{updateUser,jdbcType=VARCHAR}
where id = #{id,jdbcType=VARCHAR}
</update>
<insert id="batchInsert" parameterType="map">
insert into custom_function
(id, `name`, tags, description)
(id, project_id, `name`, tags, description, `type`, `status`, create_time, update_time,
create_user, update_user)
values
<foreach collection="list" item="item" separator=",">
(#{item.id,jdbcType=VARCHAR}, #{item.name,jdbcType=VARCHAR}, #{item.tags,jdbcType=VARCHAR},
#{item.description,jdbcType=VARCHAR})
(#{item.id,jdbcType=VARCHAR}, #{item.projectId,jdbcType=VARCHAR}, #{item.name,jdbcType=VARCHAR},
#{item.tags,jdbcType=VARCHAR,typeHandler=io.metersphere.handler.ListTypeHandler},
#{item.description,jdbcType=VARCHAR}, #{item.type,jdbcType=VARCHAR}, #{item.status,jdbcType=VARCHAR},
#{item.createTime,jdbcType=BIGINT}, #{item.updateTime,jdbcType=BIGINT}, #{item.createUser,jdbcType=VARCHAR},
#{item.updateUser,jdbcType=VARCHAR})
</foreach>
</insert>
<insert id="batchInsertSelective" parameterType="map">
@ -215,15 +369,36 @@
<if test="'id'.toString() == column.value">
#{item.id,jdbcType=VARCHAR}
</if>
<if test="'project_id'.toString() == column.value">
#{item.projectId,jdbcType=VARCHAR}
</if>
<if test="'name'.toString() == column.value">
#{item.name,jdbcType=VARCHAR}
</if>
<if test="'tags'.toString() == column.value">
#{item.tags,jdbcType=VARCHAR}
#{item.tags,jdbcType=VARCHAR,typeHandler=io.metersphere.handler.ListTypeHandler}
</if>
<if test="'description'.toString() == column.value">
#{item.description,jdbcType=VARCHAR}
</if>
<if test="'type'.toString() == column.value">
#{item.type,jdbcType=VARCHAR}
</if>
<if test="'status'.toString() == column.value">
#{item.status,jdbcType=VARCHAR}
</if>
<if test="'create_time'.toString() == column.value">
#{item.createTime,jdbcType=BIGINT}
</if>
<if test="'update_time'.toString() == column.value">
#{item.updateTime,jdbcType=BIGINT}
</if>
<if test="'create_user'.toString() == column.value">
#{item.createUser,jdbcType=VARCHAR}
</if>
<if test="'update_user'.toString() == column.value">
#{item.updateUser,jdbcType=VARCHAR}
</if>
</foreach>
)
</foreach>

View File

@ -3,10 +3,17 @@ SET SESSION innodb_lock_wait_timeout = 7200;
CREATE TABLE IF NOT EXISTS custom_function
(
`id` VARCHAR(50) NOT NULL COMMENT '',
`id` VARCHAR(50) NOT NULL COMMENT '主键ID',
`project_id` VARCHAR(50) NOT NULL COMMENT '项目ID' ,
`name` VARCHAR(255) NOT NULL COMMENT '函数名',
`tags` VARCHAR(1000) COMMENT '标签',
`description` VARCHAR(500) COMMENT '函数描述',
`type` VARCHAR(50) DEFAULT NULL COMMENT '脚本语言类型',
`status` VARCHAR(50) COMMENT '脚本状态(进行中/已完成)' ,
`create_time` BIGINT COMMENT '创建时间' ,
`update_time` BIGINT COMMENT '更新时间' ,
`create_user` VARCHAR(50) COMMENT '创建人' ,
`update_user` VARCHAR(50) COMMENT '更新人' ,
PRIMARY KEY (id)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4

View File

@ -198,6 +198,13 @@ public class PermissionConstants {
public static final String PROJECT_CUSTOM_FIELD_DELETE = "PROJECT_CUSTOM_FIELD:READ+DELETE";
/*------ end: PROJECT_CUSTOM_FIELD ------*/
/*------ start: PROJECT_CUSTOM_FUNCTION------*/
public static final String PROJECT_CUSTOM_FUNCTION_READ = "PROJECT_CUSTOM_FUNCTION:READ";
public static final String PROJECT_CUSTOM_FUNCTION_ADD = "PROJECT_CUSTOM_FUNCTION:READ+ADD";
public static final String PROJECT_CUSTOM_FUNCTION_UPDATE = "PROJECT_CUSTOM_FUNCTION:READ+UPDATE";
public static final String PROJECT_CUSTOM_FUNCTION_DELETE = "PROJECT_CUSTOM_FUNCTION:READ+DELETE";
/*------ end: PROJECT_CUSTOM_FUNCTION ------*/
/*------ start: PROJECT_TEMPLATE ------*/
public static final String PROJECT_TEMPLATE_READ = "PROJECT_TEMPLATE:READ";
public static final String PROJECT_TEMPLATE_ADD = "PROJECT_TEMPLATE:READ+ADD";

View File

@ -74,6 +74,8 @@ custom_function.name.length_range=名称长度必须在{min}-{max}之间
custom_function.name.not_blank=名称不能为空
custom_function.type.length_range=类型长度必须在{min}-{max}之间
custom_function.type.not_blank=类型不能为空
custom_function.status.length_range=脚本状态长度必须在{min}-{max}之间
custom_function.status.not_blank=脚本状态不能为空
custom_function.create_user.length_range=创建人长度必须在{min}-{max}之间
custom_function.create_user.not_blank=创建人不能为空
custom_function.project_id.length_range=项目ID长度必须在{min}-{max}之间
@ -470,4 +472,6 @@ plugin_bug_template_remark=模板为系统自动获取,不支持编辑和查
global_params=全局参数.json
env_info_all=环境信息(总).json
# custom_function
custom_function_already_exist= 脚本名称已存在

View File

@ -86,6 +86,8 @@ custom_function.name.length_range=Name length must be between {min} and {max}
custom_function.name.not_blank=Name is required
custom_function.type.length_range=Type length must be between {min} and {max}
custom_function.type.not_blank=Type is required
custom_function.status.length_range=Status length must be between {min} and {max}
custom_function.status.not_blank=Status is required
custom_function.create_user.length_range=Create User length must be between {min} and {max}
custom_function.create_user.not_blank=Create User is required
custom_function.project_id.length_range=Project ID length must be between {min} and {max}
@ -507,3 +509,6 @@ default_template=default template
global_params=Global params.json
env_info_all=All environment info.json
# custom_function
custom_function_already_exist= custom function name already exist

View File

@ -86,6 +86,8 @@ custom_function.name.length_range=名称长度必须在{min}-{max}之间
custom_function.name.not_blank=名称不能为空
custom_function.type.length_range=类型长度必须在{min}-{max}之间
custom_function.type.not_blank=类型不能为空
custom_function.status.length_range=脚本状态长度必须在{min}-{max}之间
custom_function.status.not_blank=脚本状态不能为空
custom_function.create_user.length_range=创建人长度必须在{min}-{max}之间
custom_function.create_user.not_blank=创建人不能为空
custom_function.project_id.length_range=项目ID长度必须在{min}-{max}之间
@ -506,3 +508,6 @@ default_template=默认模板
global_params=全局参数.json
env_info_all=环境信息(总).json
# custom_function
custom_function_already_exist= 脚本名称已存在

View File

@ -86,6 +86,8 @@ custom_function.name.length_range=名稱長度必須在{min}-{max}之間
custom_function.name.not_blank=名稱不能為空
custom_function.type.length_range=類型長度必須在{min}-{max}之間
custom_function.type.not_blank=類型不能為空
custom_function.status.length_range=腳本狀態長度必須在{min}-{max}之間
custom_function.status.not_blank=腳本狀態不能為空
custom_function.create_user.length_range=創建人長度必須在{min}-{max}之間
custom_function.create_user.not_blank=創建人不能為空
custom_function.project_id.length_range=項目ID長度必須在{min}-{max}之間
@ -507,3 +509,6 @@ default_template=默認模板
global_params=全局參數.json
env_info_all=環境信息(总).json
# custom_function
custom_function_already_exist= 腳本名稱已存在

View File

@ -11,6 +11,7 @@
m.id, m.create_time, m.update_time, m.create_user, m.`name`, m.tags, m.`enable`, m.expect_num, m.project_id,
m.api_definition_id, u.name as create_user_name
from api_definition_mock m
left join `api_definition` d on d.id = m.api_definition_id
left join `user` u on u.id = m.create_user
where m.api_definition_id = #{request.apiDefinitionId}
<include refid="queryWhereCondition"/>
@ -31,7 +32,8 @@
and (
m.expect_num like concat('%', #{request.keyword},'%')
or m.name like concat('%', #{request.keyword},'%')
or m.tags like JSON_CONTAINS(tags, concat('["',#{request.keyword},'"]'))
or d.path like concat('%', #{request.keyword},'%')
or m.tags like JSON_CONTAINS(m.tags, concat('["',#{request.keyword},'"]'))
)
</if>
<if test="request.projectId != null and request.projectId != ''">
@ -61,14 +63,6 @@
and m.enable in
<include refid="io.metersphere.system.mapper.BaseMapper.filterInWrapper"/>
</when>
<when test="key=='api_method'">
and m.api_method in
<include refid="io.metersphere.system.mapper.BaseMapper.filterInWrapper"/>
</when>
<when test="key=='api_path'">
and m.api_path in
<include refid="io.metersphere.system.mapper.BaseMapper.filterInWrapper"/>
</when>
<when test="key=='create_user'">
and m.create_user in
<include refid="io.metersphere.system.mapper.BaseMapper.filterInWrapper"/>
@ -115,20 +109,6 @@
</include>
</if>
<if test="${condition}.apiPath != null">
and m.api_path
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="object" value="${condition}.apiPath"/>
</include>
</if>
<if test="${condition}.apiMethod != null">
and m.api_method
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="object" value="${condition}.apiMethod"/>
</include>
</if>
<if test='${condition}.tags != null and ${ObjectTags}.operator == "not like"'>
and (m.tags is null or m.tags
<include refid="io.metersphere.system.mapper.BaseMapper.condition">

View File

@ -114,7 +114,7 @@ public class ApiDefinitionMockService {
}
apiDefinitionMock.setEnable(true);
ApiDefinition apiDefinition = apiDefinitionMapper.selectByPrimaryKey(apiDefinitionMock.getApiDefinitionId());
apiDefinitionMock.setExpectNum(String.valueOf(NumGenerator.nextNum(request.getProjectId() + "_" + apiDefinition.getNum(), ApplicationNumScope.API_TEST_CASE)));
apiDefinitionMock.setExpectNum(String.valueOf(NumGenerator.nextNum(request.getProjectId() + "_" + apiDefinition.getNum(), ApplicationNumScope.API_MOCK)));
apiDefinitionMockMapper.insertSelective(apiDefinitionMock);
ApiDefinitionMockConfig apiDefinitionMockConfig = new ApiDefinitionMockConfig();
@ -208,7 +208,7 @@ public class ApiDefinitionMockService {
apiDefinitionMock.setCreateUser(userId);
apiDefinitionMock.setEnable(true);
ApiDefinition apiDefinition = apiDefinitionMapper.selectByPrimaryKey(apiDefinitionMock.getApiDefinitionId());
apiDefinitionMock.setExpectNum(String.valueOf(NumGenerator.nextNum(request.getProjectId() + "_" + apiDefinition.getNum(), ApplicationNumScope.API_TEST_CASE)));
apiDefinitionMock.setExpectNum(String.valueOf(NumGenerator.nextNum(request.getProjectId() + "_" + apiDefinition.getNum(), ApplicationNumScope.API_MOCK)));
apiDefinitionMockMapper.insertSelective(apiDefinitionMock);
Optional<ApiDefinitionMockConfig> apiDefinitionMockConfigOptional = Optional.ofNullable(apiDefinitionMockConfigMapper.selectByPrimaryKey(request.getId()));

View File

@ -0,0 +1,96 @@
package io.metersphere.project.controller;
import com.github.pagehelper.Page;
import com.github.pagehelper.page.PageMethod;
import io.metersphere.project.domain.CustomFunction;
import io.metersphere.project.dto.customfunction.CustomFunctionDTO;
import io.metersphere.project.dto.customfunction.request.CustomFunctionPageRequest;
import io.metersphere.project.dto.customfunction.request.CustomFunctionRequest;
import io.metersphere.project.dto.customfunction.request.CustomFunctionUpdateRequest;
import io.metersphere.project.service.CustomFunctionLogService;
import io.metersphere.project.service.CustomFunctionService;
import io.metersphere.sdk.constants.PermissionConstants;
import io.metersphere.system.log.annotation.Log;
import io.metersphere.system.log.constants.OperationLogType;
import io.metersphere.system.security.CheckOwner;
import io.metersphere.system.utils.PageUtils;
import io.metersphere.system.utils.Pager;
import io.metersphere.system.utils.SessionUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* @author: LAN
* @date: 2024/1/9 19:19
* @version: 1.0
*/
@RestController
@RequestMapping(value = "/project/custom/func")
@Tag(name = "项目管理-公共脚本")
public class CustomFunctionController {
@Resource
private CustomFunctionService customFunctionService;
@PostMapping("/page")
@Operation(summary = "项目管理-公共脚本-列表")
@RequiresPermissions(PermissionConstants.PROJECT_CUSTOM_FUNCTION_READ)
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
public Pager<List<CustomFunctionDTO>> query(@Validated @RequestBody CustomFunctionPageRequest request) {
Page<Object> page = PageMethod.startPage(request.getCurrent(), request.getPageSize(),
StringUtils.isNotBlank(request.getSortString()) ? request.getSortString() : "create_time desc");
return PageUtils.setPageInfo(page, customFunctionService.getPage(request));
}
@GetMapping("/detail/{id}")
@Operation(summary = "项目管理-公共脚本-脚本详情")
@RequiresPermissions(PermissionConstants.PROJECT_CUSTOM_FUNCTION_READ)
@CheckOwner(resourceId = "#id", resourceType = "custom_function")
public CustomFunctionDTO get(@PathVariable String id) {
return customFunctionService.get(id);
}
@PostMapping("/add")
@Operation(summary = "项目管理-公共脚本-脚本添加")
@RequiresPermissions(PermissionConstants.PROJECT_CUSTOM_FUNCTION_ADD)
@Log(type = OperationLogType.ADD, expression = "#msClass.addLog(#request)", msClass = CustomFunctionLogService.class)
@CheckOwner(resourceId = "#request.getProjectId()", resourceType = "project")
public CustomFunction add(@Validated @RequestBody CustomFunctionRequest request) {
return customFunctionService.add(request, SessionUtils.getUserId());
}
@PostMapping("/update")
@Operation(summary = "项目管理-公共脚本-脚本更新")
@RequiresPermissions(PermissionConstants.PROJECT_CUSTOM_FUNCTION_UPDATE)
@Log(type = OperationLogType.UPDATE, expression = "#msClass.updateLog(#request)", msClass = CustomFunctionLogService.class)
@CheckOwner(resourceId = "#request.getId()", resourceType = "custom_function")
public void update(@Validated @RequestBody CustomFunctionUpdateRequest request) {
customFunctionService.update(request, SessionUtils.getUserId());
}
@PostMapping("/status")
@Operation(summary = "项目管理-公共脚本-脚本更新状态")
@RequiresPermissions(PermissionConstants.PROJECT_CUSTOM_FUNCTION_UPDATE)
@Log(type = OperationLogType.UPDATE, expression = "#msClass.updateStatusLog(#request)", msClass = CustomFunctionLogService.class)
@CheckOwner(resourceId = "#request.getId()", resourceType = "custom_function")
public void updateStatus(@Validated @RequestBody CustomFunctionUpdateRequest request) {
customFunctionService.updateStatus(request, SessionUtils.getUserId());
}
@GetMapping("/delete/{id}")
@Operation(summary = "项目管理-公共脚本-脚本删除")
@RequiresPermissions(PermissionConstants.PROJECT_CUSTOM_FUNCTION_DELETE)
@Log(type = OperationLogType.DELETE, expression = "#msClass.delLog(#id)", msClass = CustomFunctionLogService.class)
@CheckOwner(resourceId = "#id", resourceType = "custom_function")
public void delete(@PathVariable String id) {
customFunctionService.delete(id);
}
}

View File

@ -0,0 +1,26 @@
package io.metersphere.project.dto.customfunction;
import io.metersphere.project.domain.CustomFunction;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
/**
* @author: LAN
* @date: 2024/1/9 19:42
* @version: 1.0
*/
@Data
public class CustomFunctionDTO extends CustomFunction {
@Schema(description = "创建人名称")
private String createUserName;
@Schema(description = "参数列表")
private String params;
@Schema(description = "函数体")
private String script;
@Schema(description = "执行结果")
private String result;
}

View File

@ -0,0 +1,32 @@
package io.metersphere.project.dto.customfunction.request;
import io.metersphere.system.dto.sdk.BasePageRequest;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
/**
* @author: LAN
* @date: 2024/1/9 19:43
* @version: 1.0
*/
@Data
public class CustomFunctionPageRequest extends BasePageRequest implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@Schema(description = "项目ID")
@NotBlank(message = "{custom_function.project_id.not_blank}")
@Size(min = 1, max = 50, message = "{custom_function.project_id.length_range}")
private String projectId;
@Schema(description = "脚本语言类型")
private String type;
@Schema(description = "脚本状态(进行中/已完成)")
private String status;
}

View File

@ -0,0 +1,63 @@
package io.metersphere.project.dto.customfunction.request;
import io.metersphere.validation.groups.Created;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
/**
* @author: LAN
* @date: 2024/1/9 19:51
* @version: 1.0
*/
@Data
public class CustomFunctionRequest implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@Schema(description = "项目ID")
@NotBlank(message = "{custom_function.project_id.not_blank}")
@Size(min = 1, max = 50, message = "{custom_function.project_id.length_range}")
private String projectId;
@Schema(description = "函数名")
@NotBlank(message = "{custom_function.name.not_blank}", groups = {Created.class})
@Size(min = 1, max = 255, message = "{custom_function.name.length_range}")
private String name;
@Schema(description = "脚本语言类型")
private String type;
@Schema(description = "脚本状态(进行中/已完成)")
private String status;
@Schema(description = "标签")
private LinkedHashSet<@NotBlank String> tags;
@Schema(description = "函数描述")
private String description;
@Schema(description = "参数列表")
private String params;
@Schema(description = "函数体")
private String script;
@Schema(description = "执行结果")
private String result;
public List<String> getTags() {
if (tags == null) {
return new ArrayList<>(0);
} else {
return new ArrayList<>(tags);
}
}
}

View File

@ -0,0 +1,20 @@
package io.metersphere.project.dto.customfunction.request;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.Data;
/**
* @author: LAN
* @date: 2024/1/9 19:51
* @version: 1.0
*/
@Data
public class CustomFunctionUpdateRequest extends CustomFunctionRequest {
@Schema(description = "主键ID")
@NotBlank(message = "{custom_function.id.not_blank}")
@Size(min = 1, max = 50, message = "{custom_function.id.length_range}")
private String id;
}

View File

@ -14,7 +14,9 @@ public enum ProjectResultCode implements IResultCode {
/**
* 开启组织模板操作项目模板时会返回
*/
PROJECT_TEMPLATE_PERMISSION(102002, "project_template_permission_error");
PROJECT_TEMPLATE_PERMISSION(102002, "project_template_permission_error"),
CUSTOM_FUNCTION_ALREADY_EXIST(102003, "custom_function_already_exist");
private final int code;
private final String message;

View File

@ -0,0 +1,16 @@
package io.metersphere.project.mapper;
import io.metersphere.project.dto.customfunction.CustomFunctionDTO;
import io.metersphere.project.dto.customfunction.request.CustomFunctionPageRequest;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* @author: LAN
* @date: 2024/1/11 15:45
* @version: 1.0
*/
public interface ExtCustomFunctionMapper {
List<CustomFunctionDTO> list(@Param("request") CustomFunctionPageRequest request);
}

View File

@ -0,0 +1,127 @@
<?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.project.mapper.ExtCustomFunctionMapper">
<resultMap id="CustomFunctionDTO" type="io.metersphere.project.dto.customfunction.CustomFunctionDTO">
<result column="tags" jdbcType="VARCHAR" property="tags" typeHandler="io.metersphere.handler.ListTypeHandler" />
</resultMap>
<select id="list" resultMap="CustomFunctionDTO">
select
c.id, c.`name`, c.project_id, c.tags, c.status, c.`type`, c.description, c.create_time, c.update_time, c.create_user, c.update_user, u.name as create_user_name
from custom_function c
left join `user` u on u.id = c.create_user
where c.project_id = #{request.projectId}
<include refid="queryWhereCondition"/>
</select>
<select id="getIdsByApiIds" resultType="java.lang.String">
select
m.id
from api_definition_mock m
where m.api_definition_id in
<foreach collection="ids" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</select>
<sql id="queryWhereCondition">
<if test="request.keyword != null and request.keyword != ''">
and (
c.name like concat('%', #{request.keyword},'%')
or c.tags like JSON_CONTAINS(tags, concat('["',#{request.keyword},'"]'))
)
</if>
<if test="request.type != null and request.type != ''">
and c.type = #{request.type}
</if>
<if test="request.status != null and request.status != ''">
and c.status = #{request.status}
</if>
<include refid="filters">
<property name="filter" value="request.filter"/>
</include>
<if test="request.combine != null and request.combine != ''">
<include refid="combine">
<property name="condition" value="request.combine"/>
<property name="name" value="request.name"/>
<property name="ObjectTags" value="request.combine.tags"/>
</include>
</if>
</sql>
<sql id="filters">
<if test="${filter} != null and ${filter}.size() > 0">
<foreach collection="${filter}.entrySet()" index="key" item="values">
<if test="values != null and values.size() > 0">
<choose>
<when test="key=='status'">
and c.status in
<include refid="io.metersphere.system.mapper.BaseMapper.filterInWrapper"/>
</when>
</choose>
</if>
</foreach>
</if>
</sql>
<sql id="combine">
<if test='${condition}.name != null and (${name} == null or ${name} == "")'>
and c.name
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="object" value="${condition}.name"/>
</include>
</if>
<if test="${condition}.updateTime != null">
and c.update_time
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="object" value="${condition}.updateTime"/>
</include>
</if>
<if test="${condition}.createTime != null">
and c.create_time
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="object" value="${condition}.createTime"/>
</include>
</if>
<if test="${condition}.createUser != null">
and c.create_user
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="object" value="${condition}.createUser"/>
</include>
</if>
<if test="${condition}.enable != null">
and c.status
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="object" value="${condition}.status"/>
</include>
</if>
<if test='${condition}.tags != null and ${ObjectTags}.operator == "not like"'>
and (c.tags is null or c.tags
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="object" value="${condition}.tags"/>
</include>
)
</if>
<if test='${condition}.tags != null and ${ObjectTags}.operator == "like"'>
and c.tags
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
<property name="object" value="${condition}.tags"/>
</include>
</if>
</sql>
</mapper>

View File

@ -0,0 +1,138 @@
package io.metersphere.project.service;
import io.metersphere.project.domain.CustomFunction;
import io.metersphere.project.dto.customfunction.CustomFunctionDTO;
import io.metersphere.project.dto.customfunction.request.CustomFunctionRequest;
import io.metersphere.project.dto.customfunction.request.CustomFunctionUpdateRequest;
import io.metersphere.project.mapper.CustomFunctionMapper;
import io.metersphere.sdk.constants.HttpMethodConstants;
import io.metersphere.sdk.util.BeanUtils;
import io.metersphere.sdk.util.JSON;
import io.metersphere.system.log.constants.OperationLogModule;
import io.metersphere.system.log.constants.OperationLogType;
import io.metersphere.system.log.dto.LogDTO;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* @author: LAN
* @date: 2024/1/9 19:38
* @version: 1.0
*/
@Service
@Transactional(rollbackFor = Exception.class)
public class CustomFunctionLogService {
@Resource
private CustomFunctionMapper customFunctionMapper;
@Resource
private CustomFunctionService customFunctionService;
/**
* 添加日志
*
* @param request
* @return
*/
public LogDTO addLog(CustomFunctionRequest request) {
LogDTO dto = new LogDTO(
request.getProjectId(),
null,
null,
null,
OperationLogType.ADD.name(),
OperationLogModule.PROJECT_CUSTOM_FUNCTION,
request.getName());
dto.setHistory(true);
dto.setPath("/project/custom/func/add");
dto.setMethod(HttpMethodConstants.POST.name());
dto.setOriginalValue(JSON.toJSONBytes(request));
return dto;
}
/**
* 修改日志
*
* @param request
* @return
*/
public LogDTO updateLog(CustomFunctionUpdateRequest request) {
CustomFunctionDTO customFunctionDTO= getOriginalValue(request.getId());
if(customFunctionDTO.getId() != null){
LogDTO dto = new LogDTO(
request.getProjectId(),
null,
request.getId(),
null,
OperationLogType.UPDATE.name(),
OperationLogModule.PROJECT_CUSTOM_FUNCTION,
request.getName());
dto.setHistory(true);
dto.setPath("/project/custom/func/update");
dto.setMethod(HttpMethodConstants.POST.name());
dto.setOriginalValue(JSON.toJSONBytes(customFunctionDTO));
return dto;
}
return null;
}
public LogDTO updateStatusLog(CustomFunctionUpdateRequest request) {
CustomFunctionDTO customFunctionDTO= getOriginalValue(request.getId());
if(customFunctionDTO.getId() != null){
LogDTO dto = new LogDTO(
customFunctionDTO.getProjectId(),
null,
customFunctionDTO.getId(),
null,
OperationLogType.UPDATE.name(),
OperationLogModule.PROJECT_CUSTOM_FUNCTION,
customFunctionDTO.getName());
dto.setHistory(true);
dto.setPath("/project/custom/func/status" );
dto.setMethod(HttpMethodConstants.GET.name());
dto.setOriginalValue(JSON.toJSONBytes(customFunctionDTO));
return dto;
}
return null;
}
/**
* 删除日志
*
* @param id
* @return
*/
public LogDTO delLog(String id) {
CustomFunctionDTO customFunctionDTO = getOriginalValue(id);
if(customFunctionDTO.getId() != null){
LogDTO dto = new LogDTO(
customFunctionDTO.getProjectId(),
null,
customFunctionDTO.getId(),
null,
OperationLogType.DELETE.name(),
OperationLogModule.PROJECT_CUSTOM_FUNCTION,
customFunctionDTO.getName());
dto.setHistory(true);
dto.setPath("/project/custom/func/delete");
dto.setMethod(HttpMethodConstants.POST.name());
dto.setOriginalValue(JSON.toJSONBytes(customFunctionDTO));
return dto;
}
return null;
}
private CustomFunctionDTO getOriginalValue(String id){
CustomFunctionDTO customFunctionDTO = new CustomFunctionDTO();
CustomFunction customFunction = customFunctionMapper.selectByPrimaryKey(id);
if(null != customFunction){
customFunctionService.handleCustomFunctionBlob(id, customFunctionDTO);
BeanUtils.copyBean(customFunctionDTO, customFunction);
}
return customFunctionDTO;
}
}

View File

@ -0,0 +1,162 @@
package io.metersphere.project.service;
import io.metersphere.project.domain.CustomFunction;
import io.metersphere.project.domain.CustomFunctionBlob;
import io.metersphere.project.domain.CustomFunctionExample;
import io.metersphere.project.dto.customfunction.CustomFunctionDTO;
import io.metersphere.project.dto.customfunction.request.CustomFunctionPageRequest;
import io.metersphere.project.dto.customfunction.request.CustomFunctionRequest;
import io.metersphere.project.dto.customfunction.request.CustomFunctionUpdateRequest;
import io.metersphere.project.enums.result.ProjectResultCode;
import io.metersphere.project.mapper.CustomFunctionBlobMapper;
import io.metersphere.project.mapper.CustomFunctionMapper;
import io.metersphere.project.mapper.ExtCustomFunctionMapper;
import io.metersphere.sdk.exception.MSException;
import io.metersphere.sdk.util.BeanUtils;
import io.metersphere.system.uid.IDGenerator;
import io.metersphere.system.utils.ServiceUtils;
import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Optional;
/**
* @author: LAN
* @date: 2024/1/9 19:38
* @version: 1.0
*/
@Service
@Transactional(rollbackFor = Exception.class)
public class CustomFunctionService {
@Resource
CustomFunctionMapper customFunctionMapper;
@Resource
CustomFunctionBlobMapper customFunctionBlobMapper;
@Resource
ExtCustomFunctionMapper extCustomFunctionMapper;
public List<CustomFunctionDTO> getPage(CustomFunctionPageRequest request) {
return extCustomFunctionMapper.list(request);
}
public CustomFunctionDTO get(String id) {
CustomFunction customFunction = checkCustomFunction(id);
CustomFunctionDTO customFunctionDTO = new CustomFunctionDTO();
handleCustomFunctionBlob(id, customFunctionDTO);
BeanUtils.copyBean(customFunctionDTO, customFunction);
return customFunctionDTO;
}
public void handleCustomFunctionBlob(String id, CustomFunctionDTO customFunctionDTO) {
Optional<CustomFunctionBlob> customFunctionBlobOptional = Optional.ofNullable(customFunctionBlobMapper.selectByPrimaryKey(id));
customFunctionBlobOptional.ifPresent(blob -> {
customFunctionDTO.setParams(new String(blob.getParams(), StandardCharsets.UTF_8));
customFunctionDTO.setScript(new String(blob.getScript(), StandardCharsets.UTF_8));
customFunctionDTO.setResult(new String(blob.getResult(), StandardCharsets.UTF_8));
});
}
public CustomFunction add(CustomFunctionRequest request, String userId) {
ProjectService.checkResourceExist(request.getProjectId());
CustomFunction customFunction = new CustomFunction();
BeanUtils.copyBean(customFunction, request);
checkAddExist(customFunction);
customFunction.setId(IDGenerator.nextStr());
customFunction.setCreateTime(System.currentTimeMillis());
customFunction.setUpdateTime(System.currentTimeMillis());
customFunction.setCreateUser(userId);
customFunction.setUpdateUser(userId);
if (CollectionUtils.isNotEmpty(request.getTags())) {
customFunction.setTags(request.getTags());
}
customFunctionMapper.insertSelective(customFunction);
CustomFunctionBlob customFunctionBlob = new CustomFunctionBlob();
customFunctionBlob.setId(customFunction.getId());
if(request.getParams() != null) {
customFunctionBlob.setParams(request.getParams().getBytes());
}
if(request.getScript() != null) {
customFunctionBlob.setScript(request.getScript().getBytes());
}
if(request.getResult() != null) {
customFunctionBlob.setResult(request.getResult().getBytes());
}
customFunctionBlobMapper.insertSelective(customFunctionBlob);
return customFunction;
}
public void update(CustomFunctionUpdateRequest request, String userId) {
ProjectService.checkResourceExist(request.getProjectId());
CustomFunction customFunction = new CustomFunction();
BeanUtils.copyBean(customFunction, request);
checkUpdateExist(customFunction);
customFunction.setUpdateTime(System.currentTimeMillis());
customFunction.setUpdateUser(userId);
if (CollectionUtils.isNotEmpty(request.getTags())) {
customFunction.setTags(request.getTags());
}
customFunctionMapper.updateByPrimaryKeySelective(customFunction);
CustomFunctionBlob customFunctionBlob = new CustomFunctionBlob();
customFunctionBlob.setId(customFunction.getId());
if(request.getParams() != null) {
customFunctionBlob.setParams(request.getParams().getBytes());
}
if(request.getScript() != null) {
customFunctionBlob.setScript(request.getScript().getBytes());
}
if(request.getResult() != null) {
customFunctionBlob.setResult(request.getResult().getBytes());
}
customFunctionBlobMapper.updateByPrimaryKeySelective(customFunctionBlob);
}
public void updateStatus(CustomFunctionUpdateRequest request, String userId) {
checkCustomFunction(request.getId());
CustomFunction update = new CustomFunction();
update.setId(request.getId());
update.setStatus(request.getStatus());
update.setUpdateTime(System.currentTimeMillis());
update.setUpdateUser(userId);
customFunctionMapper.updateByPrimaryKeySelective(update);
}
public void delete(String id) {
checkCustomFunction(id);
customFunctionMapper.deleteByPrimaryKey(id);
customFunctionBlobMapper.deleteByPrimaryKey(id);
}
private CustomFunction checkCustomFunction(String id) {
return ServiceUtils.checkResourceExist(customFunctionMapper.selectByPrimaryKey(id), "resource_not_exist");
}
private void checkAddExist(CustomFunction customFunction) {
CustomFunctionExample example = new CustomFunctionExample();
example.createCriteria()
.andNameEqualTo(customFunction.getName());
if (customFunctionMapper.countByExample(example) > 0) {
throw new MSException(ProjectResultCode.CUSTOM_FUNCTION_ALREADY_EXIST);
}
}
private void checkUpdateExist(CustomFunction customFunction) {
CustomFunctionExample example = new CustomFunctionExample();
example.createCriteria()
.andIdNotEqualTo(customFunction.getId())
.andNameEqualTo(customFunction.getName());
if (customFunctionMapper.countByExample(example) > 0) {
throw new MSException(ProjectResultCode.CUSTOM_FUNCTION_ALREADY_EXIST);
}
}
}

View File

@ -0,0 +1,352 @@
package io.metersphere.project.controller;
import io.metersphere.project.domain.CustomFunction;
import io.metersphere.project.domain.CustomFunctionBlob;
import io.metersphere.project.dto.customfunction.CustomFunctionDTO;
import io.metersphere.project.dto.customfunction.request.CustomFunctionPageRequest;
import io.metersphere.project.dto.customfunction.request.CustomFunctionRequest;
import io.metersphere.project.dto.customfunction.request.CustomFunctionUpdateRequest;
import io.metersphere.project.enums.result.ProjectResultCode;
import io.metersphere.project.mapper.CustomFunctionBlobMapper;
import io.metersphere.project.mapper.CustomFunctionMapper;
import io.metersphere.sdk.constants.PermissionConstants;
import io.metersphere.sdk.util.BeanUtils;
import io.metersphere.sdk.util.JSON;
import io.metersphere.sdk.util.LogUtils;
import io.metersphere.system.base.BaseTest;
import io.metersphere.system.controller.handler.ResultHolder;
import io.metersphere.system.controller.handler.result.MsHttpResultCode;
import io.metersphere.system.log.constants.OperationLogType;
import io.metersphere.system.utils.Pager;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.*;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MvcResult;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
/**
* @author: LAN
* @date: 2024/1/11 19:02
* @version: 1.0
*/
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
@AutoConfigureMockMvc
public class CustomFunctionControllerTests extends BaseTest {
private static final String BASE_PATH = "/project/custom/func/";
private final static String ADD = BASE_PATH + "add";
private final static String UPDATE = BASE_PATH + "update";
private final static String DELETE = BASE_PATH + "delete/";
private final static String PAGE = BASE_PATH + "page";
private static final String DETAIL = BASE_PATH + "detail/";
private static final String STATUS = BASE_PATH + "status";
private static CustomFunction customFunction;
@Resource
private CustomFunctionMapper customFunctionMapper;
@Resource
private CustomFunctionBlobMapper customFunctionBlobMapper;
@Test
@Order(1)
public void testAdd() throws Exception {
LogUtils.info("create custom function test");
// 创建测试数据
CustomFunctionRequest request = new CustomFunctionRequest();
request.setProjectId(DEFAULT_PROJECT_ID);
request.setName("test1test1test1test1test1test1");
request.setStatus("UNDERWAY");
// 执行方法调用
request.setName("公共脚本test");
this.requestPostWithOkAndReturn(ADD, request);
request.setName("公共脚本test2");
this.requestPostWithOkAndReturn(ADD, request);
request.setScript("vars.get(\"variable_name\")\n" +
"vars.put(\"variable_name\", \"variable_value\")\n" +
"prev.getResponseHeaders()\n" +
"prev.getResponseCode()\n" +
"prev.getResponseDataAsString()");
request.setParams("[{}]");
request.setResult("2024-01-11 19:33:39 INFO 48551350 1-1 Thread started: 48551350 1-1\n" +
"2024-01-11 19:33:39 ERROR 48551350 1-1 Problem in JSR223 script JSR223Sampler, message: {}\n" +
"Both script file and script text are empty for element:JSR223Sampler\n" +
"javax.script.ScriptException\n" +
" at org.apache.jmeter.util.JSR223TestElement.processFileOrScript(JSR223TestElement.java:240)\n" +
" at org.apache.jmeter.protocol.java.sampler.JSR223Sampler.sample(JSR223Sampler.java:72)\n" +
" at org.apache.jmeter.threads.JMeterThread.doSampling(JMeterThread.java:672)\n" +
" at org.apache.jmeter.threads.JMeterThread.executeSamplePackage(JMeterThread.java:590)\n" +
" at org.apache.jmeter.threads.JMeterThread.processSampler(JMeterThread.java:502)\n" +
" at org.apache.jmeter.threads.JMeterThread.run(JMeterThread.java:265)\n" +
" at java.base/java.lang.Thread.run(Thread.java:840)");
request.setName("公共脚本test3");
this.requestPostWithOkAndReturn(ADD, request);
request.setName("公共脚本test4");
this.requestPostWithOkAndReturn(ADD, request);
request.setName("公共脚本test5");
MvcResult mvcResult = this.requestPostWithOkAndReturn(ADD, request);
// 校验请求成功数据
CustomFunction resultData = getResultData(mvcResult, CustomFunction.class);
customFunction = assertAddCustomFunction(request, resultData.getId());
// 再插入一条数据便于修改时重名校验
request.setName("重名公共脚本test");
request.setTags(new LinkedHashSet<>(List.of("tag1", "tag2")));
mvcResult = this.requestPostWithOkAndReturn(ADD, request);
resultData = getResultData(mvcResult, CustomFunction.class);
assertAddCustomFunction(request, resultData.getId());
// @@重名校验异常
assertErrorCode(this.requestPost(ADD, request), ProjectResultCode.CUSTOM_FUNCTION_ALREADY_EXIST);
// 校验项目是否存在
request.setProjectId("111");
request.setName("test123");
assertErrorCode(this.requestPost(ADD, request), MsHttpResultCode.NOT_FOUND);
// @@校验日志
this.checkLog(customFunction.getId(), OperationLogType.ADD, ADD);
// @@异常参数校验
createdGroupParamValidateTest(CustomFunctionRequest.class, ADD);
// @@校验权限
request.setProjectId(DEFAULT_PROJECT_ID);
request.setName("permission-st-6");
requestPostPermissionTest(PermissionConstants.PROJECT_CUSTOM_FUNCTION_ADD, ADD, request);
}
private CustomFunction assertAddCustomFunction(CustomFunctionRequest request, String id) {
CustomFunction customFunctionInfo = customFunctionMapper.selectByPrimaryKey(id);
CustomFunctionBlob customFunctionBlob = customFunctionBlobMapper.selectByPrimaryKey(id);
CustomFunction copyCustomFunction = BeanUtils.copyBean(new CustomFunction(), customFunctionInfo);
BeanUtils.copyBean(copyCustomFunction, request);
Assertions.assertEquals(customFunctionInfo, copyCustomFunction);
if(customFunctionBlob != null){
if(customFunctionBlob.getParams() != null) {
Assertions.assertEquals(request.getParams(), new String(customFunctionBlob.getParams(), StandardCharsets.UTF_8));
}
if(customFunctionBlob.getScript() != null) {
Assertions.assertEquals(request.getScript(), new String(customFunctionBlob.getScript(), StandardCharsets.UTF_8));
}
if(customFunctionBlob.getResult() != null) {
Assertions.assertEquals(request.getResult(), new String(customFunctionBlob.getResult(), StandardCharsets.UTF_8));
}
}
return customFunctionInfo;
}
@Test
@Order(2)
public void get() throws Exception {
// @@请求成功
MvcResult mvcResult = this.requestGetWithOkAndReturn(DETAIL + customFunction.getId());
// 校验请求成功数据
CustomFunctionDTO resultData = getResultData(mvcResult, CustomFunctionDTO.class);
// 校验数据是否正确
CustomFunctionDTO customFunctionDTO = new CustomFunctionDTO();
CustomFunction customFunctionInfo = customFunctionMapper.selectByPrimaryKey(customFunction.getId());
BeanUtils.copyBean(customFunctionDTO, customFunctionInfo);
CustomFunctionBlob customFunctionBlob = customFunctionBlobMapper.selectByPrimaryKey(customFunction.getId());
if (customFunctionBlob != null) {
customFunctionDTO.setParams(new String(customFunctionBlob.getParams(), StandardCharsets.UTF_8));
customFunctionDTO.setScript(new String(customFunctionBlob.getScript(), StandardCharsets.UTF_8));
customFunctionDTO.setResult(new String(customFunctionBlob.getResult(), StandardCharsets.UTF_8));
}
Assertions.assertEquals(resultData, customFunctionDTO);
assertErrorCode(this.requestGet(DETAIL + "111"), MsHttpResultCode.NOT_FOUND);
// @@校验权限
requestGetPermissionTest(PermissionConstants.PROJECT_CUSTOM_FUNCTION_READ, DETAIL + "111");
}
@Test
@Order(3)
public void testUpdate() throws Exception {
LogUtils.info("update custom function test");
CustomFunctionUpdateRequest request = new CustomFunctionUpdateRequest();
BeanUtils.copyBean(request, customFunction);
request.setName("test1test1test1test1test1test1");
request.setScript("update-vars.get(\"variable_name\")\n" +
"vars.put(\"variable_name\", \"variable_value\")\n" +
"prev.getResponseHeaders()\n" +
"prev.getResponseCode()\n" +
"prev.getResponseDataAsString()");
request.setParams("[{\"update-\":\"update-\"}]");
request.setResult("update-2024-01-11 19:33:39 INFO 48551350 1-1 Thread started: 48551350 1-1\n" +
"2024-01-11 19:33:39 ERROR 48551350 1-1 Problem in JSR223 script JSR223Sampler, message: {}\n" +
"Both script file and script text are empty for element:JSR223Sampler\n" +
"javax.script.ScriptException\n" +
" at org.apache.jmeter.util.JSR223TestElement.processFileOrScript(JSR223TestElement.java:240)\n" +
" at org.apache.jmeter.protocol.java.sampler.JSR223Sampler.sample(JSR223Sampler.java:72)\n" +
" at org.apache.jmeter.threads.JMeterThread.doSampling(JMeterThread.java:672)\n" +
" at org.apache.jmeter.threads.JMeterThread.executeSamplePackage(JMeterThread.java:590)\n" +
" at org.apache.jmeter.threads.JMeterThread.processSampler(JMeterThread.java:502)\n" +
" at org.apache.jmeter.threads.JMeterThread.run(JMeterThread.java:265)\n" +
" at java.base/java.lang.Thread.run(Thread.java:840)");
this.requestPostWithOk(UPDATE, request);
// 校验请求成功数据
customFunction = assertUpdateCustomFunction(request, request.getId());
// 修改 tags
request.setTags(new LinkedHashSet<>(List.of("tag1", "tag2-update")));
request.setName("公共脚本test公共脚本test公共脚本test公共脚本test公共脚本test公共脚本test公共脚本test公共脚本test公共脚本test");
this.requestPostWithOk(UPDATE, request);
// 校验请求成功数据
assertUpdateCustomFunction(request, request.getId());
request.setName("重名公共脚本test");
// @@重名校验异常
assertErrorCode(this.requestPost(UPDATE, request), ProjectResultCode.CUSTOM_FUNCTION_ALREADY_EXIST);
// 校验项目是否存在
request.setProjectId("111");
request.setName("test123");
assertErrorCode(this.requestPost(UPDATE, request), MsHttpResultCode.NOT_FOUND);
// 校验数据是否存在
request.setId("111");
request.setName("test123");
assertErrorCode(this.requestPost(UPDATE, request), MsHttpResultCode.NOT_FOUND);
// @@校验日志
checkLog(customFunction.getId(), OperationLogType.UPDATE, UPDATE);
// @@异常参数校验
createdGroupParamValidateTest(CustomFunctionUpdateRequest.class, UPDATE);
// @@校验权限
request.setId(customFunction.getId());
request.setProjectId(DEFAULT_PROJECT_ID);
request.setName("permission-st-6");
requestPostPermissionTest(PermissionConstants.PROJECT_CUSTOM_FUNCTION_UPDATE, UPDATE, request);
}
private CustomFunction assertUpdateCustomFunction(CustomFunctionUpdateRequest request, String id) {
CustomFunction customFunctionInfo = customFunctionMapper.selectByPrimaryKey(id);
CustomFunctionBlob customFunctionBlob = customFunctionBlobMapper.selectByPrimaryKey(id);
CustomFunction copyCustomFunction = new CustomFunction();
BeanUtils.copyBean(copyCustomFunction, customFunctionInfo);
BeanUtils.copyBean(copyCustomFunction, request);
Assertions.assertEquals(customFunctionInfo, copyCustomFunction);
if(customFunctionBlob != null){
if(customFunctionBlob.getParams() != null) {
Assertions.assertEquals(request.getParams(), new String(customFunctionBlob.getParams(), StandardCharsets.UTF_8));
}
if(customFunctionBlob.getScript() != null) {
Assertions.assertEquals(request.getScript(), new String(customFunctionBlob.getScript(), StandardCharsets.UTF_8));
}
if(customFunctionBlob.getResult() != null) {
Assertions.assertEquals(request.getResult(), new String(customFunctionBlob.getResult(), StandardCharsets.UTF_8));
}
}
return customFunctionInfo;
}
@Test
@Order(4)
public void testUpdateStatus() throws Exception {
LogUtils.info("update status custom function test");
// @@请求成功
CustomFunctionUpdateRequest customFunctionUpdateRequest = new CustomFunctionUpdateRequest();
customFunctionUpdateRequest.setId(customFunction.getId());
customFunctionUpdateRequest.setProjectId(customFunction.getProjectId());
customFunctionUpdateRequest.setStatus("COMPLETED");
// 执行方法调用
this.requestPostWithOk(STATUS, customFunctionUpdateRequest);
customFunction = customFunctionMapper.selectByPrimaryKey(customFunction.getId());
Assertions.assertEquals(customFunction.getStatus(), customFunctionUpdateRequest.getStatus());
// @@校验日志
checkLog(customFunction.getId(), OperationLogType.UPDATE, STATUS);
customFunctionUpdateRequest.setId("111");
assertErrorCode(this.requestPost(STATUS, customFunctionUpdateRequest), MsHttpResultCode.NOT_FOUND);
// @@校验权限
requestPostPermissionTest(PermissionConstants.PROJECT_CUSTOM_FUNCTION_UPDATE, STATUS, customFunctionUpdateRequest);
}
@Test
@Order(9)
public void getPage() throws Exception {
doCustomFunctionPage("KEYWORD");
doCustomFunctionPage("FILTER");
}
private void doCustomFunctionPage(String search) throws Exception {
CustomFunctionPageRequest request = new CustomFunctionPageRequest();
request.setProjectId(DEFAULT_PROJECT_ID);
request.setCurrent(1);
request.setPageSize(10);
request.setSort(Map.of("createTime", "asc"));
switch (search) {
case "KEYWORD" -> configureKeywordSearch(request);
case "FILTER" -> configureFilterSearch(request);
default -> {}
}
MvcResult mvcResult = this.requestPostWithOkAndReturn(PAGE, request);
// 获取返回值
String returnData = mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8);
ResultHolder resultHolder = JSON.parseObject(returnData, ResultHolder.class);
// 返回请求正常
Assertions.assertNotNull(resultHolder);
Pager<?> pageData = JSON.parseObject(JSON.toJSONString(resultHolder.getData()), Pager.class);
// 返回值不为空
Assertions.assertNotNull(pageData);
// 返回值的页码和当前页码相同
Assertions.assertEquals(pageData.getCurrent(), request.getCurrent());
// 返回的数据量不超过规定要返回的数据量相同
Assertions.assertTrue(JSON.parseArray(JSON.toJSONString(pageData.getList())).size() <= request.getPageSize());
}
// 进行中UNDERWAY,
// 已完成COMPLETED,
private void configureKeywordSearch(CustomFunctionPageRequest request) {
request.setKeyword("100");
request.setSort(Map.of("status", "asc"));
}
private void configureFilterSearch(CustomFunctionPageRequest request) {
Map<String, List<String>> filters = new HashMap<>();
request.setSort(Map.of());
filters.put("status", List.of("UNDERWAY"));
filters.put("tags", List.of("tag1"));
request.setFilter(filters);
}
@Test
@Order(12)
public void testDel() throws Exception {
LogUtils.info("delete custom function test");
// @@请求成功
this.requestGetWithOk(DELETE + customFunction.getId());
checkLog(customFunction.getId(), OperationLogType.DELETE);
CustomFunction customFunctionInfo = customFunctionMapper.selectByPrimaryKey(customFunction.getId());
Assertions.assertNull(customFunctionInfo);
// blob是否删除
CustomFunctionBlob customFunctionBlob = customFunctionBlobMapper.selectByPrimaryKey(customFunction.getId());
Assertions.assertNull(customFunctionBlob);
checkLog(customFunction.getId(), OperationLogType.DELETE);
assertErrorCode(this.requestGet(DELETE + "111"), MsHttpResultCode.NOT_FOUND);
// @@校验权限
requestGetPermissionTest(PermissionConstants.PROJECT_CUSTOM_FUNCTION_DELETE, DELETE + "222");
}
}

View File

@ -788,7 +788,7 @@ public class EnvironmentControllerTests extends BaseTest {
// 测试500
dataSource.setDriver("com.mysql.cj.jdbc.Driver");
dataSource.setDbUrl("jdbc:mysql://");
this.requestPost(validate, dataSource, ERROR_REQUEST_MATCHER);
this.requestPost(validate + "500", dataSource, ERROR_REQUEST_MATCHER);
}
@Test

View File

@ -87,6 +87,7 @@ public class OperationLogModule {
public static final String PROJECT_MANAGEMENT_PERMISSION_MENU_MANAGEMENT = "PROJECT_MANAGEMENT_PERMISSION_MENU_MANAGEMENT";
public static final String PROJECT_TEMPLATE = "PROJECT_TEMPLATE";// 项目模板
public static final String PROJECT_CUSTOM_FIELD = "PROJECT_CUSTOM_FIELD";// 项目字段
public static final String PROJECT_CUSTOM_FUNCTION = "PROJECT_CUSTOM_FUNCTION";// 项目公共脚本
//用例
public static final String FUNCTIONAL_CASE = "FUNCTIONAL_CASE";