feat(接口测试): 接口管理模块接口定义自定义字段处理
This commit is contained in:
parent
c2fa378954
commit
aa85ff2ba3
|
@ -0,0 +1,100 @@
|
|||
package io.metersphere.api.domain;
|
||||
|
||||
import io.metersphere.validation.groups.*;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.*;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class ApiDefinitionCustomField implements Serializable {
|
||||
@Schema(description = "接口ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{api_definition_custom_field.api_id.not_blank}", groups = {Created.class})
|
||||
@Size(min = 1, max = 50, message = "{api_definition_custom_field.api_id.length_range}", groups = {Created.class, Updated.class})
|
||||
private String apiId;
|
||||
|
||||
@Schema(description = "字段ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{api_definition_custom_field.field_id.not_blank}", groups = {Created.class})
|
||||
@Size(min = 1, max = 50, message = "{api_definition_custom_field.field_id.length_range}", groups = {Created.class, Updated.class})
|
||||
private String fieldId;
|
||||
|
||||
@Schema(description = "字段值")
|
||||
private String value;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public enum Column {
|
||||
apiId("api_id", "apiId", "VARCHAR", false),
|
||||
fieldId("field_id", "fieldId", "VARCHAR", false),
|
||||
value("value", "value", "VARCHAR", true);
|
||||
|
||||
private static final String BEGINNING_DELIMITER = "`";
|
||||
|
||||
private static final String ENDING_DELIMITER = "`";
|
||||
|
||||
private final String column;
|
||||
|
||||
private final boolean isColumnNameDelimited;
|
||||
|
||||
private final String javaProperty;
|
||||
|
||||
private final String jdbcType;
|
||||
|
||||
public String value() {
|
||||
return this.column;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return this.column;
|
||||
}
|
||||
|
||||
public String getJavaProperty() {
|
||||
return this.javaProperty;
|
||||
}
|
||||
|
||||
public String getJdbcType() {
|
||||
return this.jdbcType;
|
||||
}
|
||||
|
||||
Column(String column, String javaProperty, String jdbcType, boolean isColumnNameDelimited) {
|
||||
this.column = column;
|
||||
this.javaProperty = javaProperty;
|
||||
this.jdbcType = jdbcType;
|
||||
this.isColumnNameDelimited = isColumnNameDelimited;
|
||||
}
|
||||
|
||||
public String desc() {
|
||||
return this.getEscapedColumnName() + " DESC";
|
||||
}
|
||||
|
||||
public String asc() {
|
||||
return this.getEscapedColumnName() + " ASC";
|
||||
}
|
||||
|
||||
public static Column[] excludes(Column ... excludes) {
|
||||
ArrayList<Column> columns = new ArrayList<>(Arrays.asList(Column.values()));
|
||||
if (excludes != null && excludes.length > 0) {
|
||||
columns.removeAll(new ArrayList<>(Arrays.asList(excludes)));
|
||||
}
|
||||
return columns.toArray(new Column[]{});
|
||||
}
|
||||
|
||||
public static Column[] all() {
|
||||
return Column.values();
|
||||
}
|
||||
|
||||
public String getEscapedColumnName() {
|
||||
if (this.isColumnNameDelimited) {
|
||||
return new StringBuilder().append(BEGINNING_DELIMITER).append(this.column).append(ENDING_DELIMITER).toString();
|
||||
} else {
|
||||
return this.column;
|
||||
}
|
||||
}
|
||||
|
||||
public String getAliasedEscapedColumnName() {
|
||||
return this.getEscapedColumnName();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,410 @@
|
|||
package io.metersphere.api.domain;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ApiDefinitionCustomFieldExample {
|
||||
protected String orderByClause;
|
||||
|
||||
protected boolean distinct;
|
||||
|
||||
protected List<Criteria> oredCriteria;
|
||||
|
||||
public ApiDefinitionCustomFieldExample() {
|
||||
oredCriteria = new ArrayList<Criteria>();
|
||||
}
|
||||
|
||||
public void setOrderByClause(String orderByClause) {
|
||||
this.orderByClause = orderByClause;
|
||||
}
|
||||
|
||||
public String getOrderByClause() {
|
||||
return orderByClause;
|
||||
}
|
||||
|
||||
public void setDistinct(boolean distinct) {
|
||||
this.distinct = distinct;
|
||||
}
|
||||
|
||||
public boolean isDistinct() {
|
||||
return distinct;
|
||||
}
|
||||
|
||||
public List<Criteria> getOredCriteria() {
|
||||
return oredCriteria;
|
||||
}
|
||||
|
||||
public void or(Criteria criteria) {
|
||||
oredCriteria.add(criteria);
|
||||
}
|
||||
|
||||
public Criteria or() {
|
||||
Criteria criteria = createCriteriaInternal();
|
||||
oredCriteria.add(criteria);
|
||||
return criteria;
|
||||
}
|
||||
|
||||
public Criteria createCriteria() {
|
||||
Criteria criteria = createCriteriaInternal();
|
||||
if (oredCriteria.size() == 0) {
|
||||
oredCriteria.add(criteria);
|
||||
}
|
||||
return criteria;
|
||||
}
|
||||
|
||||
protected Criteria createCriteriaInternal() {
|
||||
Criteria criteria = new Criteria();
|
||||
return criteria;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
oredCriteria.clear();
|
||||
orderByClause = null;
|
||||
distinct = false;
|
||||
}
|
||||
|
||||
protected abstract static class GeneratedCriteria {
|
||||
protected List<Criterion> criteria;
|
||||
|
||||
protected GeneratedCriteria() {
|
||||
super();
|
||||
criteria = new ArrayList<Criterion>();
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
return criteria.size() > 0;
|
||||
}
|
||||
|
||||
public List<Criterion> getAllCriteria() {
|
||||
return criteria;
|
||||
}
|
||||
|
||||
public List<Criterion> getCriteria() {
|
||||
return criteria;
|
||||
}
|
||||
|
||||
protected void addCriterion(String condition) {
|
||||
if (condition == null) {
|
||||
throw new RuntimeException("Value for condition cannot be null");
|
||||
}
|
||||
criteria.add(new Criterion(condition));
|
||||
}
|
||||
|
||||
protected void addCriterion(String condition, Object value, String property) {
|
||||
if (value == null) {
|
||||
throw new RuntimeException("Value for " + property + " cannot be null");
|
||||
}
|
||||
criteria.add(new Criterion(condition, value));
|
||||
}
|
||||
|
||||
protected void addCriterion(String condition, Object value1, Object value2, String property) {
|
||||
if (value1 == null || value2 == null) {
|
||||
throw new RuntimeException("Between values for " + property + " cannot be null");
|
||||
}
|
||||
criteria.add(new Criterion(condition, value1, value2));
|
||||
}
|
||||
|
||||
public Criteria andApiIdIsNull() {
|
||||
addCriterion("api_id is null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andApiIdIsNotNull() {
|
||||
addCriterion("api_id is not null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andApiIdEqualTo(String value) {
|
||||
addCriterion("api_id =", value, "apiId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andApiIdNotEqualTo(String value) {
|
||||
addCriterion("api_id <>", value, "apiId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andApiIdGreaterThan(String value) {
|
||||
addCriterion("api_id >", value, "apiId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andApiIdGreaterThanOrEqualTo(String value) {
|
||||
addCriterion("api_id >=", value, "apiId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andApiIdLessThan(String value) {
|
||||
addCriterion("api_id <", value, "apiId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andApiIdLessThanOrEqualTo(String value) {
|
||||
addCriterion("api_id <=", value, "apiId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andApiIdLike(String value) {
|
||||
addCriterion("api_id like", value, "apiId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andApiIdNotLike(String value) {
|
||||
addCriterion("api_id not like", value, "apiId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andApiIdIn(List<String> values) {
|
||||
addCriterion("api_id in", values, "apiId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andApiIdNotIn(List<String> values) {
|
||||
addCriterion("api_id not in", values, "apiId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andApiIdBetween(String value1, String value2) {
|
||||
addCriterion("api_id between", value1, value2, "apiId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andApiIdNotBetween(String value1, String value2) {
|
||||
addCriterion("api_id not between", value1, value2, "apiId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andFieldIdIsNull() {
|
||||
addCriterion("field_id is null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andFieldIdIsNotNull() {
|
||||
addCriterion("field_id is not null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andFieldIdEqualTo(String value) {
|
||||
addCriterion("field_id =", value, "fieldId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andFieldIdNotEqualTo(String value) {
|
||||
addCriterion("field_id <>", value, "fieldId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andFieldIdGreaterThan(String value) {
|
||||
addCriterion("field_id >", value, "fieldId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andFieldIdGreaterThanOrEqualTo(String value) {
|
||||
addCriterion("field_id >=", value, "fieldId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andFieldIdLessThan(String value) {
|
||||
addCriterion("field_id <", value, "fieldId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andFieldIdLessThanOrEqualTo(String value) {
|
||||
addCriterion("field_id <=", value, "fieldId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andFieldIdLike(String value) {
|
||||
addCriterion("field_id like", value, "fieldId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andFieldIdNotLike(String value) {
|
||||
addCriterion("field_id not like", value, "fieldId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andFieldIdIn(List<String> values) {
|
||||
addCriterion("field_id in", values, "fieldId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andFieldIdNotIn(List<String> values) {
|
||||
addCriterion("field_id not in", values, "fieldId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andFieldIdBetween(String value1, String value2) {
|
||||
addCriterion("field_id between", value1, value2, "fieldId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andFieldIdNotBetween(String value1, String value2) {
|
||||
addCriterion("field_id not between", value1, value2, "fieldId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andValueIsNull() {
|
||||
addCriterion("`value` is null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andValueIsNotNull() {
|
||||
addCriterion("`value` is not null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andValueEqualTo(String value) {
|
||||
addCriterion("`value` =", value, "value");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andValueNotEqualTo(String value) {
|
||||
addCriterion("`value` <>", value, "value");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andValueGreaterThan(String value) {
|
||||
addCriterion("`value` >", value, "value");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andValueGreaterThanOrEqualTo(String value) {
|
||||
addCriterion("`value` >=", value, "value");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andValueLessThan(String value) {
|
||||
addCriterion("`value` <", value, "value");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andValueLessThanOrEqualTo(String value) {
|
||||
addCriterion("`value` <=", value, "value");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andValueLike(String value) {
|
||||
addCriterion("`value` like", value, "value");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andValueNotLike(String value) {
|
||||
addCriterion("`value` not like", value, "value");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andValueIn(List<String> values) {
|
||||
addCriterion("`value` in", values, "value");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andValueNotIn(List<String> values) {
|
||||
addCriterion("`value` not in", values, "value");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andValueBetween(String value1, String value2) {
|
||||
addCriterion("`value` between", value1, value2, "value");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andValueNotBetween(String value1, String value2) {
|
||||
addCriterion("`value` not between", value1, value2, "value");
|
||||
return (Criteria) this;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Criteria extends GeneratedCriteria {
|
||||
|
||||
protected Criteria() {
|
||||
super();
|
||||
}
|
||||
}
|
||||
|
||||
public static class Criterion {
|
||||
private String condition;
|
||||
|
||||
private Object value;
|
||||
|
||||
private Object secondValue;
|
||||
|
||||
private boolean noValue;
|
||||
|
||||
private boolean singleValue;
|
||||
|
||||
private boolean betweenValue;
|
||||
|
||||
private boolean listValue;
|
||||
|
||||
private String typeHandler;
|
||||
|
||||
public String getCondition() {
|
||||
return condition;
|
||||
}
|
||||
|
||||
public Object getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public Object getSecondValue() {
|
||||
return secondValue;
|
||||
}
|
||||
|
||||
public boolean isNoValue() {
|
||||
return noValue;
|
||||
}
|
||||
|
||||
public boolean isSingleValue() {
|
||||
return singleValue;
|
||||
}
|
||||
|
||||
public boolean isBetweenValue() {
|
||||
return betweenValue;
|
||||
}
|
||||
|
||||
public boolean isListValue() {
|
||||
return listValue;
|
||||
}
|
||||
|
||||
public String getTypeHandler() {
|
||||
return typeHandler;
|
||||
}
|
||||
|
||||
protected Criterion(String condition) {
|
||||
super();
|
||||
this.condition = condition;
|
||||
this.typeHandler = null;
|
||||
this.noValue = true;
|
||||
}
|
||||
|
||||
protected Criterion(String condition, Object value, String typeHandler) {
|
||||
super();
|
||||
this.condition = condition;
|
||||
this.value = value;
|
||||
this.typeHandler = typeHandler;
|
||||
if (value instanceof List<?>) {
|
||||
this.listValue = true;
|
||||
} else {
|
||||
this.singleValue = true;
|
||||
}
|
||||
}
|
||||
|
||||
protected Criterion(String condition, Object value) {
|
||||
this(condition, value, null);
|
||||
}
|
||||
|
||||
protected Criterion(String condition, Object value, Object secondValue, String typeHandler) {
|
||||
super();
|
||||
this.condition = condition;
|
||||
this.value = value;
|
||||
this.secondValue = secondValue;
|
||||
this.typeHandler = typeHandler;
|
||||
this.betweenValue = true;
|
||||
}
|
||||
|
||||
protected Criterion(String condition, Object value, Object secondValue) {
|
||||
this(condition, value, secondValue, null);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package io.metersphere.api.mapper;
|
||||
|
||||
import io.metersphere.api.domain.ApiDefinitionCustomField;
|
||||
import io.metersphere.api.domain.ApiDefinitionCustomFieldExample;
|
||||
import java.util.List;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
public interface ApiDefinitionCustomFieldMapper {
|
||||
long countByExample(ApiDefinitionCustomFieldExample example);
|
||||
|
||||
int deleteByExample(ApiDefinitionCustomFieldExample example);
|
||||
|
||||
int deleteByPrimaryKey(@Param("apiId") String apiId, @Param("fieldId") String fieldId);
|
||||
|
||||
int insert(ApiDefinitionCustomField record);
|
||||
|
||||
int insertSelective(ApiDefinitionCustomField record);
|
||||
|
||||
List<ApiDefinitionCustomField> selectByExample(ApiDefinitionCustomFieldExample example);
|
||||
|
||||
ApiDefinitionCustomField selectByPrimaryKey(@Param("apiId") String apiId, @Param("fieldId") String fieldId);
|
||||
|
||||
int updateByExampleSelective(@Param("record") ApiDefinitionCustomField record, @Param("example") ApiDefinitionCustomFieldExample example);
|
||||
|
||||
int updateByExample(@Param("record") ApiDefinitionCustomField record, @Param("example") ApiDefinitionCustomFieldExample example);
|
||||
|
||||
int updateByPrimaryKeySelective(ApiDefinitionCustomField record);
|
||||
|
||||
int updateByPrimaryKey(ApiDefinitionCustomField record);
|
||||
|
||||
int batchInsert(@Param("list") List<ApiDefinitionCustomField> list);
|
||||
|
||||
int batchInsertSelective(@Param("list") List<ApiDefinitionCustomField> list, @Param("selective") ApiDefinitionCustomField.Column ... selective);
|
||||
}
|
|
@ -0,0 +1,213 @@
|
|||
<?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.ApiDefinitionCustomFieldMapper">
|
||||
<resultMap id="BaseResultMap" type="io.metersphere.api.domain.ApiDefinitionCustomField">
|
||||
<id column="api_id" jdbcType="VARCHAR" property="apiId" />
|
||||
<id column="field_id" jdbcType="VARCHAR" property="fieldId" />
|
||||
<result column="value" jdbcType="VARCHAR" property="value" />
|
||||
</resultMap>
|
||||
<sql id="Example_Where_Clause">
|
||||
<where>
|
||||
<foreach collection="oredCriteria" item="criteria" separator="or">
|
||||
<if test="criteria.valid">
|
||||
<trim prefix="(" prefixOverrides="and" suffix=")">
|
||||
<foreach collection="criteria.criteria" item="criterion">
|
||||
<choose>
|
||||
<when test="criterion.noValue">
|
||||
and ${criterion.condition}
|
||||
</when>
|
||||
<when test="criterion.singleValue">
|
||||
and ${criterion.condition} #{criterion.value}
|
||||
</when>
|
||||
<when test="criterion.betweenValue">
|
||||
and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
|
||||
</when>
|
||||
<when test="criterion.listValue">
|
||||
and ${criterion.condition}
|
||||
<foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
|
||||
#{listItem}
|
||||
</foreach>
|
||||
</when>
|
||||
</choose>
|
||||
</foreach>
|
||||
</trim>
|
||||
</if>
|
||||
</foreach>
|
||||
</where>
|
||||
</sql>
|
||||
<sql id="Update_By_Example_Where_Clause">
|
||||
<where>
|
||||
<foreach collection="example.oredCriteria" item="criteria" separator="or">
|
||||
<if test="criteria.valid">
|
||||
<trim prefix="(" prefixOverrides="and" suffix=")">
|
||||
<foreach collection="criteria.criteria" item="criterion">
|
||||
<choose>
|
||||
<when test="criterion.noValue">
|
||||
and ${criterion.condition}
|
||||
</when>
|
||||
<when test="criterion.singleValue">
|
||||
and ${criterion.condition} #{criterion.value}
|
||||
</when>
|
||||
<when test="criterion.betweenValue">
|
||||
and ${criterion.condition} #{criterion.value} and #{criterion.secondValue}
|
||||
</when>
|
||||
<when test="criterion.listValue">
|
||||
and ${criterion.condition}
|
||||
<foreach close=")" collection="criterion.value" item="listItem" open="(" separator=",">
|
||||
#{listItem}
|
||||
</foreach>
|
||||
</when>
|
||||
</choose>
|
||||
</foreach>
|
||||
</trim>
|
||||
</if>
|
||||
</foreach>
|
||||
</where>
|
||||
</sql>
|
||||
<sql id="Base_Column_List">
|
||||
api_id, field_id, `value`
|
||||
</sql>
|
||||
<select id="selectByExample" parameterType="io.metersphere.api.domain.ApiDefinitionCustomFieldExample" resultMap="BaseResultMap">
|
||||
select
|
||||
<if test="distinct">
|
||||
distinct
|
||||
</if>
|
||||
<include refid="Base_Column_List" />
|
||||
from api_definition_custom_field
|
||||
<if test="_parameter != null">
|
||||
<include refid="Example_Where_Clause" />
|
||||
</if>
|
||||
<if test="orderByClause != null">
|
||||
order by ${orderByClause}
|
||||
</if>
|
||||
</select>
|
||||
<select id="selectByPrimaryKey" parameterType="map" resultMap="BaseResultMap">
|
||||
select
|
||||
<include refid="Base_Column_List" />
|
||||
from api_definition_custom_field
|
||||
where api_id = #{apiId,jdbcType=VARCHAR}
|
||||
and field_id = #{fieldId,jdbcType=VARCHAR}
|
||||
</select>
|
||||
<delete id="deleteByPrimaryKey" parameterType="map">
|
||||
delete from api_definition_custom_field
|
||||
where api_id = #{apiId,jdbcType=VARCHAR}
|
||||
and field_id = #{fieldId,jdbcType=VARCHAR}
|
||||
</delete>
|
||||
<delete id="deleteByExample" parameterType="io.metersphere.api.domain.ApiDefinitionCustomFieldExample">
|
||||
delete from api_definition_custom_field
|
||||
<if test="_parameter != null">
|
||||
<include refid="Example_Where_Clause" />
|
||||
</if>
|
||||
</delete>
|
||||
<insert id="insert" parameterType="io.metersphere.api.domain.ApiDefinitionCustomField">
|
||||
insert into api_definition_custom_field (api_id, field_id, `value`
|
||||
)
|
||||
values (#{apiId,jdbcType=VARCHAR}, #{fieldId,jdbcType=VARCHAR}, #{value,jdbcType=VARCHAR}
|
||||
)
|
||||
</insert>
|
||||
<insert id="insertSelective" parameterType="io.metersphere.api.domain.ApiDefinitionCustomField">
|
||||
insert into api_definition_custom_field
|
||||
<trim prefix="(" suffix=")" suffixOverrides=",">
|
||||
<if test="apiId != null">
|
||||
api_id,
|
||||
</if>
|
||||
<if test="fieldId != null">
|
||||
field_id,
|
||||
</if>
|
||||
<if test="value != null">
|
||||
`value`,
|
||||
</if>
|
||||
</trim>
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
<if test="apiId != null">
|
||||
#{apiId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="fieldId != null">
|
||||
#{fieldId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="value != null">
|
||||
#{value,jdbcType=VARCHAR},
|
||||
</if>
|
||||
</trim>
|
||||
</insert>
|
||||
<select id="countByExample" parameterType="io.metersphere.api.domain.ApiDefinitionCustomFieldExample" resultType="java.lang.Long">
|
||||
select count(*) from api_definition_custom_field
|
||||
<if test="_parameter != null">
|
||||
<include refid="Example_Where_Clause" />
|
||||
</if>
|
||||
</select>
|
||||
<update id="updateByExampleSelective" parameterType="map">
|
||||
update api_definition_custom_field
|
||||
<set>
|
||||
<if test="record.apiId != null">
|
||||
api_id = #{record.apiId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.fieldId != null">
|
||||
field_id = #{record.fieldId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.value != null">
|
||||
`value` = #{record.value,jdbcType=VARCHAR},
|
||||
</if>
|
||||
</set>
|
||||
<if test="_parameter != null">
|
||||
<include refid="Update_By_Example_Where_Clause" />
|
||||
</if>
|
||||
</update>
|
||||
<update id="updateByExample" parameterType="map">
|
||||
update api_definition_custom_field
|
||||
set api_id = #{record.apiId,jdbcType=VARCHAR},
|
||||
field_id = #{record.fieldId,jdbcType=VARCHAR},
|
||||
`value` = #{record.value,jdbcType=VARCHAR}
|
||||
<if test="_parameter != null">
|
||||
<include refid="Update_By_Example_Where_Clause" />
|
||||
</if>
|
||||
</update>
|
||||
<update id="updateByPrimaryKeySelective" parameterType="io.metersphere.api.domain.ApiDefinitionCustomField">
|
||||
update api_definition_custom_field
|
||||
<set>
|
||||
<if test="value != null">
|
||||
`value` = #{value,jdbcType=VARCHAR},
|
||||
</if>
|
||||
</set>
|
||||
where api_id = #{apiId,jdbcType=VARCHAR}
|
||||
and field_id = #{fieldId,jdbcType=VARCHAR}
|
||||
</update>
|
||||
<update id="updateByPrimaryKey" parameterType="io.metersphere.api.domain.ApiDefinitionCustomField">
|
||||
update api_definition_custom_field
|
||||
set `value` = #{value,jdbcType=VARCHAR}
|
||||
where api_id = #{apiId,jdbcType=VARCHAR}
|
||||
and field_id = #{fieldId,jdbcType=VARCHAR}
|
||||
</update>
|
||||
<insert id="batchInsert" parameterType="map">
|
||||
insert into api_definition_custom_field
|
||||
(api_id, field_id, `value`)
|
||||
values
|
||||
<foreach collection="list" item="item" separator=",">
|
||||
(#{item.apiId,jdbcType=VARCHAR}, #{item.fieldId,jdbcType=VARCHAR}, #{item.value,jdbcType=VARCHAR}
|
||||
)
|
||||
</foreach>
|
||||
</insert>
|
||||
<insert id="batchInsertSelective" parameterType="map">
|
||||
insert into api_definition_custom_field (
|
||||
<foreach collection="selective" item="column" separator=",">
|
||||
${column.escapedColumnName}
|
||||
</foreach>
|
||||
)
|
||||
values
|
||||
<foreach collection="list" item="item" separator=",">
|
||||
(
|
||||
<foreach collection="selective" item="column" separator=",">
|
||||
<if test="'api_id'.toString() == column.value">
|
||||
#{item.apiId,jdbcType=VARCHAR}
|
||||
</if>
|
||||
<if test="'field_id'.toString() == column.value">
|
||||
#{item.fieldId,jdbcType=VARCHAR}
|
||||
</if>
|
||||
<if test="'value'.toString() == column.value">
|
||||
#{item.value,jdbcType=VARCHAR}
|
||||
</if>
|
||||
</foreach>
|
||||
)
|
||||
</foreach>
|
||||
</insert>
|
||||
</mapper>
|
|
@ -506,7 +506,20 @@ CREATE TABLE IF NOT EXISTS api_file_resource(
|
|||
`create_time` BIGINT NOT NULL COMMENT '创建时间' ,
|
||||
`project_id` VARCHAR(50) NOT NULL COMMENT '项目ID' ,
|
||||
PRIMARY KEY (resource_id,file_id)
|
||||
) COMMENT = '接口和所需文件资源的关联表';
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci COMMENT = '接口和所需文件资源的关联表';
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS api_definition_custom_field(
|
||||
`api_id` VARCHAR(50) NOT NULL COMMENT '接口ID' ,
|
||||
`field_id` VARCHAR(50) NOT NULL COMMENT '字段ID' ,
|
||||
`value` VARCHAR(1000) COMMENT '字段值' ,
|
||||
PRIMARY KEY (api_id,field_id)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci COMMENT = '自定义字段接口定义关系';
|
||||
|
||||
|
||||
-- set innodb lock wait timeout to default
|
||||
SET SESSION innodb_lock_wait_timeout = DEFAULT;
|
|
@ -289,6 +289,11 @@ api_debug_module.name.not_contain_slash=模块名称不能包含斜杠
|
|||
api_environment_config.id.not_blank=ID不能为空
|
||||
api_environment_config.environment_id.length_range=环境ID长度必须在1-50之间
|
||||
api_environment_config.environment_id.not_blank=环境ID不能为空
|
||||
|
||||
#module:ApiDefinitionCustomField
|
||||
api_definition_custom_field.api_id.not_blank=接口ID不能为空
|
||||
api_definition_custom_field.field_id.not_blank=自定义字段ID不能为空
|
||||
|
||||
api_module.not.exist=模块不存在
|
||||
|
||||
permission.api.name=接口测试
|
||||
|
|
|
@ -297,6 +297,11 @@ api_unplanned_request=Unplanned Api
|
|||
api_environment_config.id.not_blank=ID cannot be blank
|
||||
api_environment_config.environment_id.length_range=Environment ID length must be between 1-50
|
||||
api_environment_config.environment_id.not_blank=Environment ID cannot be blank
|
||||
|
||||
#module:ApiDefinitionCustomField
|
||||
api_definition_custom_field.api_id.not_blank=Interface pk cannot be empty
|
||||
api_definition_custom_field.field_id.not_blank=Field ID cannot be empty
|
||||
|
||||
api_module.not.exist=The module does not exist
|
||||
|
||||
permission.api.name=API Test
|
||||
|
|
|
@ -297,6 +297,11 @@ api_unplanned_request=未规划接口
|
|||
api_environment_config.id.not_blank=ID不能为空
|
||||
api_environment_config.environment_id.length_range=环境ID长度必须在1-50之间
|
||||
api_environment_config.environment_id.not_blank=环境ID不能为空
|
||||
|
||||
#module:ApiDefinitionCustomField
|
||||
api_definition_custom_field.api_id.not_blank=接口ID不能为空
|
||||
api_definition_custom_field.field_id.not_blank=自定义字段ID不能为空
|
||||
|
||||
api_module.not.exist=模块不存在
|
||||
|
||||
permission.api.name=接口测试
|
||||
|
|
|
@ -297,6 +297,11 @@ api_unplanned_request=未规划接口
|
|||
api_environment_config.id.not_blank=ID不能為空
|
||||
api_environment_config.environment_id.length_range=環境ID長度必須在1-50之間
|
||||
api_environment_config.environment_id.not_blank=環境ID不能為空
|
||||
|
||||
#module:ApiDefinitionCustomField
|
||||
api_definition_custom_field.api_id.not_blank=接口ID不能為空
|
||||
api_definition_custom_field.field_id.not_blank=自定義字段ID不能爲空
|
||||
|
||||
api_module.not.exist=模塊不存在
|
||||
|
||||
permission.api.name=接口測試
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package io.metersphere.api.enums;
|
||||
package io.metersphere.api.constants;
|
||||
|
||||
/**
|
||||
* @author: LAN
|
|
@ -57,8 +57,6 @@ public class ApiDefinitionController {
|
|||
@PostMapping(value = "/batch-update")
|
||||
@Operation(summary = "接口测试-接口管理-批量更新接口定义")
|
||||
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_UPDATE)
|
||||
// 添加修改Log示例
|
||||
@Log(type = OperationLogType.UPDATE, expression = "#msClass.batchUpdateLog(#request)", msClass = ApiDefinitionLogService.class)
|
||||
public void batchUpdate(@Validated @RequestBody ApiDefinitionBatchUpdateRequest request) {
|
||||
apiDefinitionService.batchUpdate(request, SessionUtils.getUserId());
|
||||
}
|
||||
|
@ -73,7 +71,6 @@ public class ApiDefinitionController {
|
|||
@PostMapping(value = "/batch-del")
|
||||
@Operation(summary = "接口测试-接口管理-批量删除接口定义到回收站")
|
||||
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_DELETE)
|
||||
@Log(type = OperationLogType.DELETE, expression = "#msClass.batchDelLog(#request)", msClass = ApiDefinitionLogService.class)
|
||||
public void batchDelete(@Validated @RequestBody ApiDefinitionBatchRequest request) {
|
||||
apiDefinitionService.batchDelete(request, SessionUtils.getUserId());
|
||||
}
|
||||
|
@ -89,7 +86,6 @@ public class ApiDefinitionController {
|
|||
@PostMapping("/batch-move")
|
||||
@Operation(summary = "接口测试-接口管理-批量移动接口定义")
|
||||
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_UPDATE)
|
||||
@Log(type = OperationLogType.UPDATE, expression = "#msClass.batchMoveLog(#request)", msClass = ApiDefinitionLogService.class)
|
||||
public void batchMove(@Validated @RequestBody ApiDefinitionBatchMoveRequest request) {
|
||||
apiDefinitionService.batchMove(request, SessionUtils.getUserId());
|
||||
}
|
||||
|
@ -122,7 +118,7 @@ public class ApiDefinitionController {
|
|||
public Pager<List<ApiDefinitionDTO>> getPage(@Validated @RequestBody ApiDefinitionPageRequest request) {
|
||||
Page<Object> page = PageHelper.startPage(request.getCurrent(), request.getPageSize(),
|
||||
StringUtils.isNotBlank(request.getSortString()) ? request.getSortString() : "create_time desc");
|
||||
return PageUtils.setPageInfo(page, apiDefinitionService.getApiDefinitionPage(request));
|
||||
return PageUtils.setPageInfo(page, apiDefinitionService.getApiDefinitionPage(request, SessionUtils.getUserId()));
|
||||
}
|
||||
|
||||
@PostMapping(value = "/restore")
|
||||
|
@ -142,7 +138,6 @@ public class ApiDefinitionController {
|
|||
@PostMapping(value = "/batch-restore")
|
||||
@Operation(summary = "接口测试-接口管理-批量从回收站恢复接口定义")
|
||||
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_UPDATE)
|
||||
@Log(type = OperationLogType.UPDATE, expression = "#msClass.batchRestoreLog(#request)", msClass = ApiDefinitionLogService.class)
|
||||
public void batchRestore(@Validated @RequestBody ApiDefinitionBatchRequest request) {
|
||||
apiDefinitionService.batchRestore(request, SessionUtils.getUserId());
|
||||
}
|
||||
|
@ -150,7 +145,6 @@ public class ApiDefinitionController {
|
|||
@PostMapping(value = "/batch-trash-del")
|
||||
@Operation(summary = "接口测试-接口管理-批量从回收站删除接口定义")
|
||||
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_DELETE)
|
||||
@Log(type = OperationLogType.UPDATE, expression = "#msClass.batchTrashDelLog(#request)", msClass = ApiDefinitionLogService.class)
|
||||
public void batchTrashDel(@Validated @RequestBody ApiDefinitionBatchRequest request) {
|
||||
apiDefinitionService.batchTrashDel(request, SessionUtils.getUserId());
|
||||
}
|
||||
|
@ -161,7 +155,7 @@ public class ApiDefinitionController {
|
|||
public Pager<List<ApiDefinitionDTO>> getDocPage(@Validated @RequestBody ApiDefinitionPageRequest request) {
|
||||
Page<Object> page = PageHelper.startPage(request.getCurrent(), request.getPageSize(),
|
||||
StringUtils.isNotBlank(request.getSortString()) ? request.getSortString() : "create_time desc");
|
||||
return PageUtils.setPageInfo(page, apiDefinitionService.getDocPage(request));
|
||||
return PageUtils.setPageInfo(page, apiDefinitionService.getDocPage(request, SessionUtils.getUserId()));
|
||||
}
|
||||
|
||||
@PostMapping("/upload/temp/file")
|
||||
|
|
|
@ -5,11 +5,13 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
|||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author lan
|
||||
|
@ -81,7 +83,10 @@ public class ApiDefinitionAddRequest implements Serializable {
|
|||
@Schema(description = "关联文件ID")
|
||||
private List<String> linkFileIds;
|
||||
|
||||
@Schema(description = "自定义字段集合")
|
||||
private Map<String, String> customFields;
|
||||
|
||||
public void setPath(String path) {
|
||||
this.path = (path != null) ? path.trim() : null;
|
||||
this.path = StringUtils.trim(path);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,6 +36,9 @@ public class ApiDefinitionBatchUpdateRequest extends ApiDefinitionBatchRequest {
|
|||
@Schema(description = "标签")
|
||||
private LinkedHashSet<@NotBlank String> tags;
|
||||
|
||||
@Schema(description = "自定义字段")
|
||||
private ApiDefinitionCustomFieldDTO customField;
|
||||
|
||||
@Schema(description = "是否追加", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private boolean append = false;
|
||||
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
package io.metersphere.api.dto.definition;
|
||||
|
||||
import io.metersphere.system.domain.CustomField;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @author: LAN
|
||||
* @date: 2023/12/12 10:17
|
||||
* @version: 1.0
|
||||
*/
|
||||
@Data
|
||||
public class ApiDefinitionCustomFieldDTO extends CustomField {
|
||||
@Schema(description = "字段值")
|
||||
private String value;
|
||||
|
||||
@Schema(description = "接口ID")
|
||||
private String apiId;
|
||||
}
|
|
@ -45,4 +45,7 @@ public class ApiDefinitionDTO extends ApiDefinition{
|
|||
@Schema(description = "是否关注")
|
||||
private Boolean follow;
|
||||
|
||||
@Schema(description = "自定义字段集合")
|
||||
private List<ApiDefinitionCustomFieldDTO> customFields;
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
package io.metersphere.api.mapper;
|
||||
|
||||
import io.metersphere.api.dto.definition.ApiDefinitionCustomFieldDTO;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author: LAN
|
||||
* @date: 2023/12/12 10:12
|
||||
* @version: 1.0
|
||||
*/
|
||||
public interface ExtApiDefinitionCustomFieldMapper {
|
||||
/**
|
||||
* 获取缺陷自定义字段值
|
||||
* @param apiIds 接口集合
|
||||
* @param projectId 项目ID
|
||||
* @return 缺陷自定义字段值
|
||||
*/
|
||||
List<ApiDefinitionCustomFieldDTO> getApiCustomFields(@Param("ids") List<String> apiIds, @Param("projectId") String projectId);
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<?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.ExtApiDefinitionCustomFieldMapper">
|
||||
<select id="getApiCustomFields" resultType="io.metersphere.api.dto.definition.ApiDefinitionCustomFieldDTO">
|
||||
select cf.*, adcf.value, adcf.api_id from api_definition_custom_field adcf join custom_field cf on adcf.field_id = cf.id
|
||||
where cf.scene = 'API' and cf.scope_type = 'PROJECT' and scope_id = #{projectId}
|
||||
and api_id in
|
||||
<foreach collection="ids" item="id" separator="," open="(" close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
</select>
|
||||
</mapper>
|
|
@ -281,6 +281,20 @@
|
|||
and api_definition.version_id in
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.filterInWrapper"/>
|
||||
</when>
|
||||
<when test="key.startsWith('custom_single')">
|
||||
and api_definition.id in (
|
||||
select api_id from api_definition_custom_field where concat('custom_single_', field_id) = #{key}
|
||||
and trim(both '"' from `value`) in
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.filterInWrapper"/>
|
||||
)
|
||||
</when>
|
||||
<when test="key.startsWith('custom_multiple')">
|
||||
and api_definition.id in (
|
||||
select api_id from api_definition_custom_field where concat('custom_multiple_', field_id) = #{key}
|
||||
and
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.filterMultipleWrapper"/>
|
||||
)
|
||||
</when>
|
||||
</choose>
|
||||
</if>
|
||||
</foreach>
|
||||
|
@ -351,6 +365,44 @@
|
|||
<property name="object" value="${condition}.tags"/>
|
||||
</include>
|
||||
</if>
|
||||
|
||||
<if test="${condition}.customs != null and ${condition}.customs.size() > 0">
|
||||
<foreach collection="${condition}.customs" item="custom" separator="" open="" close="">
|
||||
<if test="custom.value != ''">
|
||||
<if test='custom.operator == "not like" or custom.operator == "not in"'>
|
||||
and api_definition.id not in (
|
||||
</if>
|
||||
<if test='custom.operator != "not like" and custom.operator != "not in"'>
|
||||
and api_definition.id in (
|
||||
</if>
|
||||
select api_id from api_definition_custom_field where field_id = #{custom.id}
|
||||
<choose>
|
||||
<when test="custom.type == 'richText' or custom.type == 'textarea' or custom.operator == 'current user'">
|
||||
and `value`
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
|
||||
<property name="object" value="custom"/>
|
||||
</include>
|
||||
</when>
|
||||
<when test="custom.type == 'multipleMember' or custom.type == 'checkbox' or custom.type == 'multipleSelect'">
|
||||
and ${custom.value}
|
||||
</when>
|
||||
<when test="custom.type == 'date' or custom.type == 'datetime'">
|
||||
and left(replace(unix_timestamp(trim(both '"' from `value`)), '.', ''), 13)
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
|
||||
<property name="object" value="custom"/>
|
||||
</include>
|
||||
</when>
|
||||
<otherwise>
|
||||
and trim(both '"' from `value`)
|
||||
<include refid="io.metersphere.system.mapper.BaseMapper.condition">
|
||||
<property name="object" value="custom"/>
|
||||
</include>
|
||||
</otherwise>
|
||||
</choose>
|
||||
)
|
||||
</if>
|
||||
</foreach>
|
||||
</if>
|
||||
</sql>
|
||||
|
||||
<sql id="queryVersionCondition">
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
package io.metersphere.api.service.definition;
|
||||
|
||||
import io.metersphere.api.domain.ApiDefinition;
|
||||
import io.metersphere.api.domain.ApiDefinitionBlob;
|
||||
import io.metersphere.api.domain.ApiDefinitionExample;
|
||||
import io.metersphere.api.dto.definition.*;
|
||||
import io.metersphere.api.mapper.ApiDefinitionBlobMapper;
|
||||
import io.metersphere.api.mapper.ApiDefinitionMapper;
|
||||
import io.metersphere.api.utils.ApiDataUtils;
|
||||
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
|
||||
import io.metersphere.project.domain.Project;
|
||||
import io.metersphere.project.mapper.ProjectMapper;
|
||||
import io.metersphere.sdk.constants.HttpMethodConstants;
|
||||
|
@ -14,6 +17,7 @@ import io.metersphere.sdk.util.Translator;
|
|||
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.apache.commons.collections.CollectionUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
@ -21,6 +25,7 @@ import org.springframework.transaction.annotation.Transactional;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Service
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
|
@ -29,14 +34,15 @@ public class ApiDefinitionLogService {
|
|||
@Resource
|
||||
private ApiDefinitionMapper apiDefinitionMapper;
|
||||
|
||||
@Resource
|
||||
private ApiDefinitionBlobMapper apiDefinitionBlobMapper;
|
||||
|
||||
@Resource
|
||||
private ProjectMapper projectMapper;
|
||||
|
||||
@Resource
|
||||
private ApiDefinitionService apiDefinitionService;
|
||||
private OperationLogService operationLogService;
|
||||
|
||||
@Resource
|
||||
private ApiDefinitionBlobMapper apiDefinitionBlobMapper;
|
||||
|
||||
/**
|
||||
* 添加接口日志
|
||||
|
@ -118,31 +124,8 @@ public class ApiDefinitionLogService {
|
|||
*
|
||||
* @return
|
||||
*/
|
||||
public List<LogDTO> batchDelLog(ApiDefinitionBatchRequest request) {
|
||||
List<String> ids = apiDefinitionService.getBatchApiIds(request, request.getProjectId(), request.getProtocol(), false);
|
||||
List<LogDTO> dtoList = new ArrayList<>();
|
||||
if (CollectionUtils.isNotEmpty(ids)) {
|
||||
ApiDefinitionExample example = new ApiDefinitionExample();
|
||||
example.createCriteria().andIdIn(ids).andDeletedEqualTo(false);
|
||||
List<ApiDefinition> apiDefinitions = apiDefinitionMapper.selectByExample(example);
|
||||
apiDefinitions.forEach(item -> {
|
||||
LogDTO dto = new LogDTO(
|
||||
item.getProjectId(),
|
||||
"",
|
||||
item.getId(),
|
||||
item.getCreateUser(),
|
||||
OperationLogType.DELETE.name(),
|
||||
OperationLogModule.API_DEFINITION,
|
||||
item.getName());
|
||||
dto.setHistory(true);
|
||||
dto.setPath("/api/definition/batch-delete");
|
||||
dto.setMethod(HttpMethodConstants.POST.name());
|
||||
dto.setOriginalValue(JSON.toJSONBytes(item));
|
||||
dtoList.add(dto);
|
||||
});
|
||||
}
|
||||
|
||||
return dtoList;
|
||||
public void batchDelLog(List<String> ids, String userId, String projectId) {
|
||||
saveBatchLog(projectId, ids, "/api/definition/batch-delete", userId, OperationLogType.DELETE.name(), true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -150,30 +133,8 @@ public class ApiDefinitionLogService {
|
|||
*
|
||||
* @return
|
||||
*/
|
||||
public List<LogDTO> batchUpdateLog(ApiDefinitionBatchUpdateRequest request) {
|
||||
List<String> ids = apiDefinitionService.getBatchApiIds(request, request.getProjectId(), request.getProtocol(), false);
|
||||
List<LogDTO> dtoList = new ArrayList<>();
|
||||
if (CollectionUtils.isNotEmpty(ids)) {
|
||||
ApiDefinitionExample example = new ApiDefinitionExample();
|
||||
example.createCriteria().andIdIn(ids);
|
||||
List<ApiDefinition> apiDefinitions = apiDefinitionMapper.selectByExample(example);
|
||||
apiDefinitions.forEach(item -> {
|
||||
LogDTO dto = new LogDTO(
|
||||
item.getProjectId(),
|
||||
"",
|
||||
item.getId(),
|
||||
item.getCreateUser(),
|
||||
OperationLogType.UPDATE.name(),
|
||||
OperationLogModule.API_DEFINITION,
|
||||
item.getName());
|
||||
dto.setHistory(true);
|
||||
dto.setPath("/api/definition/batch-update");
|
||||
dto.setMethod(HttpMethodConstants.POST.name());
|
||||
dto.setOriginalValue(JSON.toJSONBytes(item));
|
||||
dtoList.add(dto);
|
||||
});
|
||||
}
|
||||
return dtoList;
|
||||
public void batchUpdateLog(List<String> ids, String userId, String projectId) {
|
||||
saveBatchLog(projectId, ids, "/api/definition/batch-update", userId, OperationLogType.UPDATE.name(), true);
|
||||
}
|
||||
|
||||
public LogDTO copyLog(ApiDefinitionCopyRequest request) {
|
||||
|
@ -196,30 +157,8 @@ public class ApiDefinitionLogService {
|
|||
return null;
|
||||
}
|
||||
|
||||
public List<LogDTO> batchMoveLog(ApiDefinitionBatchMoveRequest request) {
|
||||
List<String> ids = apiDefinitionService.getBatchApiIds(request, request.getProjectId(), request.getProtocol(), false);
|
||||
List<LogDTO> dtoList = new ArrayList<>();
|
||||
if (CollectionUtils.isNotEmpty(ids)) {
|
||||
ApiDefinitionExample example = new ApiDefinitionExample();
|
||||
example.createCriteria().andIdIn(ids);
|
||||
List<ApiDefinition> apiDefinitions = apiDefinitionMapper.selectByExample(example);
|
||||
apiDefinitions.forEach(item -> {
|
||||
LogDTO dto = new LogDTO(
|
||||
item.getProjectId(),
|
||||
"",
|
||||
item.getId(),
|
||||
item.getCreateUser(),
|
||||
OperationLogType.UPDATE.name(),
|
||||
OperationLogModule.API_DEFINITION,
|
||||
item.getName());
|
||||
dto.setHistory(true);
|
||||
dto.setPath("/api/definition/batch-move");
|
||||
dto.setMethod(HttpMethodConstants.POST.name());
|
||||
dto.setOriginalValue(JSON.toJSONBytes(item));
|
||||
dtoList.add(dto);
|
||||
});
|
||||
}
|
||||
return dtoList;
|
||||
public void batchMoveLog(List<String> ids, String userId, String projectId) {
|
||||
saveBatchLog(projectId, ids, "/api/definition/batch-move", userId, OperationLogType.UPDATE.name(), true);
|
||||
}
|
||||
|
||||
public LogDTO followLog(String id) {
|
||||
|
@ -276,31 +215,8 @@ public class ApiDefinitionLogService {
|
|||
*
|
||||
* @return
|
||||
*/
|
||||
public List<LogDTO> batchRestoreLog(ApiDefinitionBatchRequest request) {
|
||||
List<String> ids = apiDefinitionService.getBatchApiIds(request, request.getProjectId(), request.getProtocol(), false);
|
||||
List<LogDTO> dtoList = new ArrayList<>();
|
||||
if (CollectionUtils.isNotEmpty(ids)) {
|
||||
ApiDefinitionExample example = new ApiDefinitionExample();
|
||||
example.createCriteria().andIdIn(ids).andDeletedEqualTo(false);
|
||||
List<ApiDefinition> apiDefinitions = apiDefinitionMapper.selectByExample(example);
|
||||
apiDefinitions.forEach(item -> {
|
||||
LogDTO dto = new LogDTO(
|
||||
item.getProjectId(),
|
||||
"",
|
||||
item.getId(),
|
||||
item.getCreateUser(),
|
||||
OperationLogType.UPDATE.name(),
|
||||
OperationLogModule.API_DEFINITION,
|
||||
item.getName());
|
||||
dto.setHistory(true);
|
||||
dto.setPath("/api/definition/batch-restore");
|
||||
dto.setMethod(HttpMethodConstants.POST.name());
|
||||
dto.setOriginalValue(JSON.toJSONBytes(item));
|
||||
dtoList.add(dto);
|
||||
});
|
||||
}
|
||||
|
||||
return dtoList;
|
||||
public void batchRestoreLog(List<String> ids, String userId, String projectId) {
|
||||
saveBatchLog(projectId, ids, "/api/definition/batch-restore", userId, OperationLogType.UPDATE.name(), true);
|
||||
}
|
||||
|
||||
|
||||
|
@ -331,31 +247,8 @@ public class ApiDefinitionLogService {
|
|||
/**
|
||||
* 删除回收站接口定义接口日志
|
||||
*/
|
||||
public List<LogDTO> batchTrashDelLog(ApiDefinitionBatchRequest request) {
|
||||
List<String> ids = apiDefinitionService.getBatchApiIds(request, request.getProjectId(), request.getProtocol(), false);
|
||||
List<LogDTO> dtoList = new ArrayList<>();
|
||||
if (CollectionUtils.isNotEmpty(ids)) {
|
||||
ApiDefinitionExample example = new ApiDefinitionExample();
|
||||
example.createCriteria().andIdIn(ids).andDeletedEqualTo(true);
|
||||
List<ApiDefinition> apiDefinitions = apiDefinitionMapper.selectByExample(example);
|
||||
apiDefinitions.forEach(item -> {
|
||||
LogDTO dto = new LogDTO(
|
||||
item.getProjectId(),
|
||||
"",
|
||||
item.getId(),
|
||||
item.getCreateUser(),
|
||||
OperationLogType.DELETE.name(),
|
||||
OperationLogModule.API_DEFINITION,
|
||||
item.getName());
|
||||
|
||||
dto.setPath("/api/definition/batch-trash-del");
|
||||
dto.setMethod(HttpMethodConstants.POST.name());
|
||||
dto.setOriginalValue(JSON.toJSONBytes(item));
|
||||
dtoList.add(dto);
|
||||
});
|
||||
}
|
||||
|
||||
return dtoList;
|
||||
public void batchTrashDelLog(List<String> ids, String userId, String projectId) {
|
||||
saveBatchLog(projectId, ids, "/api/definition/batch-trash-del", userId, OperationLogType.DELETE.name(), true);
|
||||
}
|
||||
|
||||
private ApiDefinitionDTO getOriginalValue(String id){
|
||||
|
@ -363,12 +256,52 @@ public class ApiDefinitionLogService {
|
|||
ApiDefinition apiDefinition = apiDefinitionMapper.selectByPrimaryKey(id);
|
||||
if(null != apiDefinition){
|
||||
// 2. 使用Optional避免空指针异常
|
||||
apiDefinitionService.handleBlob(id, apiDefinitionDTO);
|
||||
handleBlob(id, apiDefinitionDTO);
|
||||
BeanUtils.copyBean(apiDefinitionDTO, apiDefinition);
|
||||
}
|
||||
return apiDefinitionDTO;
|
||||
}
|
||||
|
||||
public void handleBlob(String id, ApiDefinitionDTO apiDefinitionDTO) {
|
||||
Optional<ApiDefinitionBlob> apiDefinitionBlobOptional = Optional.ofNullable(apiDefinitionBlobMapper.selectByPrimaryKey(id));
|
||||
apiDefinitionBlobOptional.ifPresent(blob -> {
|
||||
apiDefinitionDTO.setRequest(ApiDataUtils.parseObject(new String(blob.getRequest()), AbstractMsTestElement.class));
|
||||
// blob.getResponse() 为 null 时不进行转换
|
||||
if (blob.getResponse() != null) {
|
||||
apiDefinitionDTO.setResponse(ApiDataUtils.parseArray(new String(blob.getResponse()), HttpResponse.class));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void saveBatchLog(String projectId, List<String> ids, String path, String userId, String operationType, boolean isHistory) {
|
||||
List<LogDTO> dtoList = new ArrayList<>();
|
||||
if (CollectionUtils.isNotEmpty(ids)) {
|
||||
Project project = projectMapper.selectByPrimaryKey(projectId);
|
||||
ApiDefinitionExample example = new ApiDefinitionExample();
|
||||
example.createCriteria().andIdIn(ids);
|
||||
List<ApiDefinition> apiDefinitions = apiDefinitionMapper.selectByExample(example);
|
||||
apiDefinitions.forEach(item -> {
|
||||
ApiDefinitionDTO apiDefinitionDTO = new ApiDefinitionDTO();
|
||||
handleBlob(item.getId(), apiDefinitionDTO);
|
||||
BeanUtils.copyBean(apiDefinitionDTO, item);
|
||||
LogDTO dto = new LogDTO(
|
||||
project.getId(),
|
||||
project.getOrganizationId(),
|
||||
item.getId(),
|
||||
userId,
|
||||
operationType,
|
||||
OperationLogModule.API_DEFINITION,
|
||||
item.getName());
|
||||
|
||||
dto.setHistory(isHistory);
|
||||
dto.setPath(path);
|
||||
dto.setMethod(HttpMethodConstants.POST.name());
|
||||
dto.setOriginalValue(JSON.toJSONBytes(apiDefinitionDTO));
|
||||
dtoList.add(dto);
|
||||
});
|
||||
operationLogService.batchAdd(dtoList);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,30 +1,32 @@
|
|||
package io.metersphere.api.service.definition;
|
||||
|
||||
import io.metersphere.api.constants.ApiDefinitionDocType;
|
||||
import io.metersphere.api.constants.ApiResourceType;
|
||||
import io.metersphere.api.controller.result.ApiResultCode;
|
||||
import io.metersphere.api.domain.*;
|
||||
import io.metersphere.api.dto.debug.ApiFileResourceUpdateRequest;
|
||||
import io.metersphere.api.dto.definition.*;
|
||||
import io.metersphere.api.enums.ApiDefinitionDocType;
|
||||
import io.metersphere.api.mapper.*;
|
||||
import io.metersphere.api.service.ApiFileResourceService;
|
||||
import io.metersphere.api.utils.ApiDataUtils;
|
||||
import io.metersphere.sdk.constants.ApiReportStatus;
|
||||
import io.metersphere.sdk.util.*;
|
||||
import io.metersphere.plugin.api.spi.AbstractMsTestElement;
|
||||
import io.metersphere.project.mapper.ExtBaseProjectVersionMapper;
|
||||
import io.metersphere.project.service.ProjectService;
|
||||
import io.metersphere.sdk.constants.ApiReportStatus;
|
||||
import io.metersphere.sdk.constants.ApplicationNumScope;
|
||||
import io.metersphere.sdk.constants.DefaultRepositoryDir;
|
||||
import io.metersphere.sdk.constants.ModuleConstants;
|
||||
import io.metersphere.sdk.exception.MSException;
|
||||
import io.metersphere.sdk.util.*;
|
||||
import io.metersphere.system.dto.table.TableBatchProcessDTO;
|
||||
import io.metersphere.system.log.constants.OperationLogModule;
|
||||
import io.metersphere.system.service.UserLoginService;
|
||||
import io.metersphere.system.uid.IDGenerator;
|
||||
import io.metersphere.system.uid.NumGenerator;
|
||||
import io.metersphere.system.utils.CustomFieldUtils;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.collections.MapUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.ibatis.session.ExecutorType;
|
||||
import org.apache.ibatis.session.SqlSession;
|
||||
|
@ -39,7 +41,7 @@ import java.util.function.Function;
|
|||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static io.metersphere.api.controller.result.ApiResultCode.*;
|
||||
import static io.metersphere.api.controller.result.ApiResultCode.API_DEFINITION_MODULE_NOT_EXIST;
|
||||
|
||||
@Service
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
|
@ -83,7 +85,17 @@ public class ApiDefinitionService {
|
|||
@Resource
|
||||
private ApiDefinitionModuleMapper apiDefinitionModuleMapper;
|
||||
|
||||
public List<ApiDefinitionDTO> getApiDefinitionPage(ApiDefinitionPageRequest request){
|
||||
@Resource
|
||||
private ApiDefinitionCustomFieldMapper apiDefinitionCustomFieldMapper;
|
||||
|
||||
@Resource
|
||||
private ExtApiDefinitionCustomFieldMapper extApiDefinitionCustomFieldMapper;
|
||||
|
||||
@Resource
|
||||
private ApiDefinitionLogService apiDefinitionLogService;
|
||||
|
||||
public List<ApiDefinitionDTO> getApiDefinitionPage(ApiDefinitionPageRequest request, String userId){
|
||||
CustomFieldUtils.setBaseQueryRequestCustomMultipleFields(request, userId);
|
||||
List<ApiDefinitionDTO> list = extApiDefinitionMapper.list(request);
|
||||
if (!CollectionUtils.isEmpty(list)) {
|
||||
processApiDefinitions(list, request.getProjectId());
|
||||
|
@ -91,7 +103,8 @@ public class ApiDefinitionService {
|
|||
return list;
|
||||
}
|
||||
|
||||
public List<ApiDefinitionDTO> getDocPage(ApiDefinitionPageRequest request){
|
||||
public List<ApiDefinitionDTO> getDocPage(ApiDefinitionPageRequest request, String userId){
|
||||
CustomFieldUtils.setBaseQueryRequestCustomMultipleFields(request, userId);
|
||||
List<ApiDefinitionDTO> list = extApiDefinitionMapper.list(request);
|
||||
if (!CollectionUtils.isEmpty(list)) {
|
||||
processApiDefinitionsDoc(list);
|
||||
|
@ -159,6 +172,14 @@ public class ApiDefinitionService {
|
|||
resourceUpdateRequest.setLinkFileIds(request.getLinkFileIds());
|
||||
apiFileResourceService.addFileResource(resourceUpdateRequest);
|
||||
|
||||
//保存自定义字段
|
||||
Map<String, String> customFields = request.getCustomFields();
|
||||
if (MapUtils.isNotEmpty(customFields)) {
|
||||
List<ApiDefinitionCustomField> list = new ArrayList<>();
|
||||
customFields.keySet().forEach(key -> createNewCustomField(apiDefinition.getId(), key, customFields.get(key), list));
|
||||
batchInsertCustomFields(list);
|
||||
}
|
||||
|
||||
return apiDefinition;
|
||||
}
|
||||
|
||||
|
@ -197,6 +218,9 @@ public class ApiDefinitionService {
|
|||
apiDefinitionBlob.setResponse(request.getResponse().getBytes());
|
||||
apiDefinitionBlobMapper.updateByPrimaryKeySelective(apiDefinitionBlob);
|
||||
|
||||
// 自定义字段
|
||||
handleUpdateCustomFields(request, false);
|
||||
|
||||
// 处理文件
|
||||
ApiFileResourceUpdateRequest resourceUpdateRequest = getApiFileResourceUpdateRequest(originApiDefinition.getId(), originApiDefinition.getProjectId(), userId);
|
||||
resourceUpdateRequest.setUploadFileIds(request.getUploadFileIds());
|
||||
|
@ -210,11 +234,24 @@ public class ApiDefinitionService {
|
|||
|
||||
public void batchUpdate(ApiDefinitionBatchUpdateRequest request, String userId) {
|
||||
ProjectService.checkResourceExist(request.getProjectId());
|
||||
List<String> ids = getBatchApiIds(request, request.getProjectId(), request.getProtocol(), false);
|
||||
List<String> ids = getBatchApiIds(request, request.getProjectId(), request.getProtocol(), false, userId);
|
||||
// 记录更新前的数据
|
||||
apiDefinitionLogService.batchUpdateLog(ids, userId, request.getProjectId());
|
||||
if (CollectionUtils.isNotEmpty(ids)) {
|
||||
if (request.getType().equals("tags")) {
|
||||
handleTags(request, userId, ids);
|
||||
} else {
|
||||
} else if(request.getType().equals("customs")){
|
||||
// 自定义字段处理
|
||||
ApiDefinitionCustomFieldDTO customField = request.getCustomField();
|
||||
Map<String, String> customFieldMap = Collections.singletonMap(customField.getId(), customField.getValue());
|
||||
ApiDefinitionUpdateRequest apiDefinitionUpdateRequest = new ApiDefinitionUpdateRequest();
|
||||
BeanUtils.copyBean(apiDefinitionUpdateRequest, request);
|
||||
apiDefinitionUpdateRequest.setCustomFields(customFieldMap);
|
||||
ids.forEach(id -> {
|
||||
apiDefinitionUpdateRequest.setId(id);
|
||||
handleUpdateCustomFields(apiDefinitionUpdateRequest, request.isAppend());
|
||||
});
|
||||
}else {
|
||||
ApiDefinition apiDefinition = new ApiDefinition();
|
||||
BeanUtils.copyBean(apiDefinition, request);
|
||||
apiDefinition.setUpdateUser(userId);
|
||||
|
@ -226,6 +263,69 @@ public class ApiDefinitionService {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private void handleUpdateCustomFields(ApiDefinitionUpdateRequest request, boolean append) {
|
||||
Map<String, String> customFields = request.getCustomFields();
|
||||
if (MapUtils.isNotEmpty(customFields)) {
|
||||
List<ApiDefinitionCustomField> addFields = new ArrayList<>();
|
||||
List<ApiDefinitionCustomField> updateFields = new ArrayList<>();
|
||||
List<ApiDefinitionCustomFieldDTO> originalFields = extApiDefinitionCustomFieldMapper.getApiCustomFields(List.of(request.getId()), request.getProjectId());
|
||||
Map<String, String> originalFieldMap = originalFields.stream().collect(Collectors.toMap(ApiDefinitionCustomFieldDTO::getId, ApiDefinitionCustomFieldDTO::getValue));
|
||||
customFields.keySet().forEach(fieldId -> {
|
||||
if (!originalFieldMap.containsKey(fieldId)) {
|
||||
// New custom field relationship
|
||||
createNewCustomField(request.getId(), fieldId, customFields.get(fieldId), addFields);
|
||||
} else {
|
||||
// Existing custom field relationship
|
||||
updateExistingCustomField(request.getId(), fieldId, append, customFields.get(fieldId), updateFields, originalFieldMap);
|
||||
}
|
||||
});
|
||||
|
||||
batchInsertCustomFields(addFields);
|
||||
batchUpdateCustomFields(updateFields);
|
||||
}
|
||||
}
|
||||
|
||||
private void createNewCustomField(String apiId, String fieldId, String value, List<ApiDefinitionCustomField> addFields) {
|
||||
ApiDefinitionCustomField apiDefinitionCustomField = new ApiDefinitionCustomField();
|
||||
apiDefinitionCustomField.setApiId(apiId);
|
||||
apiDefinitionCustomField.setFieldId(fieldId);
|
||||
apiDefinitionCustomField.setValue(value);
|
||||
addFields.add(apiDefinitionCustomField);
|
||||
}
|
||||
|
||||
private void updateExistingCustomField(String apiId, String fieldId, boolean append, String value, List<ApiDefinitionCustomField> updateFields, Map<String, String> originalFieldMap) {
|
||||
ApiDefinitionCustomField apiDefinitionCustomField = new ApiDefinitionCustomField();
|
||||
apiDefinitionCustomField.setApiId(apiId);
|
||||
apiDefinitionCustomField.setFieldId(fieldId);
|
||||
if (append) {
|
||||
apiDefinitionCustomField.setValue(CustomFieldUtils.appendToMultipleCustomField(originalFieldMap.get(fieldId), value));
|
||||
} else {
|
||||
apiDefinitionCustomField.setValue(value);
|
||||
}
|
||||
updateFields.add(apiDefinitionCustomField);
|
||||
}
|
||||
|
||||
private void batchInsertCustomFields(List<ApiDefinitionCustomField> addFields) {
|
||||
if (CollectionUtils.isNotEmpty(addFields)) {
|
||||
apiDefinitionCustomFieldMapper.batchInsert(addFields);
|
||||
}
|
||||
}
|
||||
|
||||
private void batchUpdateCustomFields(List<ApiDefinitionCustomField> updateFields) {
|
||||
if (CollectionUtils.isNotEmpty(updateFields)) {
|
||||
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
|
||||
ApiDefinitionCustomFieldMapper apiCustomFieldMapper = sqlSession.getMapper(ApiDefinitionCustomFieldMapper.class);
|
||||
for (ApiDefinitionCustomField apiDefinitionCustomField : updateFields) {
|
||||
ApiDefinitionCustomFieldExample apiDefinitionCustomFieldExample = new ApiDefinitionCustomFieldExample();
|
||||
apiDefinitionCustomFieldExample.createCriteria().andApiIdEqualTo(apiDefinitionCustomField.getApiId()).andFieldIdEqualTo(apiDefinitionCustomField.getFieldId());
|
||||
apiCustomFieldMapper.updateByExample(apiDefinitionCustomField, apiDefinitionCustomFieldExample);
|
||||
}
|
||||
sqlSession.flushStatements();
|
||||
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
|
||||
}
|
||||
}
|
||||
|
||||
public ApiDefinition copy(ApiDefinitionCopyRequest request, String userId) {
|
||||
ApiDefinition copyApiDefinition = checkApiDefinition(request.getId());
|
||||
ApiDefinition apiDefinition = new ApiDefinition();
|
||||
|
@ -260,21 +360,25 @@ public class ApiDefinitionService {
|
|||
|
||||
public void delete(ApiDefinitionDeleteRequest request, String userId) {
|
||||
checkApiDefinition(request.getId());
|
||||
handleDeleteApiDefinition(Collections.singletonList(request.getId()),request.getDeleteAll(), request.getProjectId(), userId);
|
||||
handleDeleteApiDefinition(Collections.singletonList(request.getId()),request.getDeleteAll(), request.getProjectId(), userId, false);
|
||||
}
|
||||
|
||||
public void batchDelete(ApiDefinitionBatchRequest request, String userId) {
|
||||
List<String> ids = getBatchApiIds(request, request.getProjectId(), request.getProtocol(), false);
|
||||
List<String> ids = getBatchApiIds(request, request.getProjectId(), request.getProtocol(), false, userId);
|
||||
if (CollectionUtils.isNotEmpty(ids)) {
|
||||
handleDeleteApiDefinition(ids, request.getDeleteAll(), request.getProjectId(), userId);
|
||||
handleDeleteApiDefinition(ids, request.getDeleteAll(), request.getProjectId(), userId, true);
|
||||
}
|
||||
}
|
||||
|
||||
public void batchMove(ApiDefinitionBatchMoveRequest request, String userId) {
|
||||
List<String> ids = getBatchApiIds(request, request.getProjectId(), request.getProtocol(), false);
|
||||
List<String> ids = getBatchApiIds(request, request.getProjectId(), request.getProtocol(), false, userId);
|
||||
if (!ids.isEmpty()) {
|
||||
// 移动接口所有版本引用的数据
|
||||
List<String> refIds = extApiDefinitionMapper.getRefIds(ids, false);
|
||||
if (!refIds.isEmpty()) {
|
||||
// 记录批量移动日志
|
||||
apiDefinitionLogService.batchMoveLog(extApiDefinitionMapper.getIdsByRefId(refIds, false), userId, request.getProjectId());
|
||||
|
||||
extApiDefinitionMapper.batchMove(request, refIds, userId);
|
||||
}
|
||||
}
|
||||
|
@ -287,12 +391,18 @@ public class ApiDefinitionService {
|
|||
List<ApiCaseComputeDTO> apiCaseComputeList = extApiDefinitionMapper.selectApiCaseByIdsAndStatusIsNotTrash(apiDefinitionIds, projectId);
|
||||
Map<String, ApiCaseComputeDTO> resultMap = apiCaseComputeList.stream().collect(Collectors.toMap(ApiCaseComputeDTO::getApiDefinitionId, Function.identity()));
|
||||
|
||||
List<ApiDefinitionCustomFieldDTO> customFields = extApiDefinitionCustomFieldMapper.getApiCustomFields(apiDefinitionIds, projectId);
|
||||
Map<String, List<ApiDefinitionCustomFieldDTO>> customFieldMap = customFields.stream().collect(Collectors.groupingBy(ApiDefinitionCustomFieldDTO::getApiId));
|
||||
|
||||
list.forEach(item -> {
|
||||
// Convert User IDs to Names
|
||||
item.setCreateUserName(userMap.get(item.getCreateUser()));
|
||||
item.setDeleteUserName(userMap.get(item.getDeleteUser()));
|
||||
item.setUpdateUserName(userMap.get(item.getUpdateUser()));
|
||||
|
||||
// Custom Fields
|
||||
item.setCustomFields(customFieldMap.get(item.getId()));
|
||||
|
||||
// Calculate API Case Metrics
|
||||
ApiCaseComputeDTO apiCaseComputeDTO = resultMap.get(item.getId());
|
||||
if (apiCaseComputeDTO != null) {
|
||||
|
@ -442,7 +552,7 @@ public class ApiDefinitionService {
|
|||
return copyName;
|
||||
}
|
||||
|
||||
private void handleDeleteApiDefinition(List<String> ids, boolean deleteAll, String projectId, String userId) {
|
||||
private void handleDeleteApiDefinition(List<String> ids, boolean deleteAll, String projectId, String userId, boolean isBatch) {
|
||||
if (deleteAll) {
|
||||
//全部删除 进入回收站
|
||||
List<String> refIds = extApiDefinitionMapper.getRefIds(ids, false);
|
||||
|
@ -455,13 +565,17 @@ public class ApiDefinitionService {
|
|||
deleteApiRelatedData(subList, userId, projectId);
|
||||
}
|
||||
});
|
||||
// 记录删除到回收站的日志, 单条注解记录
|
||||
if(isBatch){
|
||||
apiDefinitionLogService.batchDelLog(delApiIds, userId, projectId);
|
||||
}
|
||||
extApiDefinitionMapper.batchDeleteByRefId(subRefIds, userId, projectId);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// 列表删除
|
||||
if (!ids.isEmpty()) {
|
||||
SubListUtils.dealForSubList(ids, 2000, subList -> doDelete(subList, userId, projectId));
|
||||
SubListUtils.dealForSubList(ids, 2000, subList -> doDelete(subList, userId, projectId, isBatch));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -496,7 +610,7 @@ public class ApiDefinitionService {
|
|||
extApiDefinitionMapper.updateLatestVersion(id, projectId);
|
||||
}
|
||||
|
||||
private void doDelete(List<String> ids, String userId, String projectId) {
|
||||
private void doDelete(List<String> ids, String userId, String projectId, boolean isBatch) {
|
||||
if(CollectionUtils.isNotEmpty(ids)){
|
||||
// 需要判断是否存在多个版本问题
|
||||
ids.forEach(id -> {
|
||||
|
@ -511,6 +625,11 @@ public class ApiDefinitionService {
|
|||
});
|
||||
// 删除 case
|
||||
deleteApiRelatedData(ids, userId, projectId);
|
||||
// 记录删除到回收站的日志, 单条注解记录
|
||||
if(isBatch){
|
||||
apiDefinitionLogService.batchDelLog(ids, userId, projectId);
|
||||
}
|
||||
// 删除接口到回收站
|
||||
extApiDefinitionMapper.batchDeleteById(ids, userId, projectId);
|
||||
}
|
||||
|
||||
|
@ -531,16 +650,20 @@ public class ApiDefinitionService {
|
|||
|
||||
public void restore(ApiDefinitionDeleteRequest request, String userId) {
|
||||
// 恢复接口到接口列表
|
||||
handleRestoreApiDefinition(Collections.singletonList(request.getId()), userId, request.getProjectId());
|
||||
handleRestoreApiDefinition(Collections.singletonList(request.getId()), userId, request.getProjectId(), false);
|
||||
}
|
||||
private void handleRestoreApiDefinition(List<String> ids, String userId, String projectId){
|
||||
private void handleRestoreApiDefinition(List<String> ids, String userId, String projectId, boolean isBatch){
|
||||
if (CollectionUtils.isNotEmpty(ids)) {
|
||||
SubListUtils.dealForSubList(ids, 2000, subList -> doRestore(subList, userId, projectId));
|
||||
SubListUtils.dealForSubList(ids, 2000, subList -> doRestore(subList, userId, projectId, isBatch));
|
||||
}
|
||||
}
|
||||
|
||||
private void doRestore(List<String> apiIds, String userId, String projectId) {
|
||||
private void doRestore(List<String> apiIds, String userId, String projectId, boolean isBatch) {
|
||||
if (CollectionUtils.isNotEmpty(apiIds)) {
|
||||
// 记录恢复数据之前的原数据,单条通过注解记录
|
||||
if(isBatch){
|
||||
apiDefinitionLogService.batchRestoreLog(apiIds, userId, projectId);
|
||||
}
|
||||
extApiDefinitionMapper.batchRestoreById(apiIds, userId, projectId);
|
||||
|
||||
apiIds.forEach(id -> {
|
||||
|
@ -550,16 +673,7 @@ public class ApiDefinitionService {
|
|||
List<ApiDefinitionVersionDTO> apiDefinitionVersions = extApiDefinitionMapper.getApiDefinitionByRefId(apiDefinition.getRefId());
|
||||
|
||||
if (CollectionUtils.isNotEmpty(apiDefinitionVersions) && apiDefinitionVersions.size() > 1) {
|
||||
String defaultVersion = extBaseProjectVersionMapper.getDefaultVersion(apiDefinition.getProjectId());
|
||||
// 清除所有最新标识
|
||||
clearLatestVersion(apiDefinition.getRefId(), apiDefinition.getProjectId());
|
||||
|
||||
// 获取最新数据,恢复的数据最新标识,则最新数据,反之获取最新一条数据
|
||||
ApiDefinition latestData = apiDefinition.getLatest() ? apiDefinition : getLatestData(apiDefinition.getRefId(), apiDefinition.getProjectId());
|
||||
// 恢复的数据不为最新标识,同时接口版本为默认版本,则更新此数据为最新标识
|
||||
if (!latestData.getLatest() && latestData.getVersionId().equals(defaultVersion)) {
|
||||
updateLatestVersion(apiDefinition.getId(), apiDefinition.getProjectId());
|
||||
}
|
||||
handleMultipleVersions(apiDefinition);
|
||||
}
|
||||
});
|
||||
// 恢复接口关联数据
|
||||
|
@ -567,6 +681,19 @@ public class ApiDefinitionService {
|
|||
}
|
||||
}
|
||||
|
||||
private void handleMultipleVersions(ApiDefinition apiDefinition) {
|
||||
String defaultVersion = extBaseProjectVersionMapper.getDefaultVersion(apiDefinition.getProjectId());
|
||||
// 清除所有最新标识
|
||||
clearLatestVersion(apiDefinition.getRefId(), apiDefinition.getProjectId());
|
||||
|
||||
// 获取最新数据,恢复的数据最新标识,则最新数据,反之获取最新一条数据
|
||||
ApiDefinition latestData = apiDefinition.getLatest() ? apiDefinition : getLatestData(apiDefinition.getRefId(), apiDefinition.getProjectId());
|
||||
// 恢复的数据不为最新标识,同时接口版本为默认版本,则更新此数据为最新标识
|
||||
if (!latestData.getLatest() && latestData.getVersionId().equals(defaultVersion)) {
|
||||
updateLatestVersion(apiDefinition.getId(), apiDefinition.getProjectId());
|
||||
}
|
||||
}
|
||||
|
||||
private void recoverApiRelatedData(List<String> apiIds, String userId, String projectId){
|
||||
// 是否存在 case 恢复 case
|
||||
List<ApiTestCase> caseLists = extApiTestCaseMapper.getCaseInfoByApiIds(apiIds, true);
|
||||
|
@ -575,30 +702,30 @@ public class ApiDefinitionService {
|
|||
}
|
||||
}
|
||||
public void trashDel(ApiDefinitionDeleteRequest request, String userId) {
|
||||
handleTrashDelApiDefinition(Collections.singletonList(request.getId()), userId, request.getProjectId());
|
||||
handleTrashDelApiDefinition(Collections.singletonList(request.getId()), userId, request.getProjectId(), false);
|
||||
}
|
||||
|
||||
public void batchRestore(ApiDefinitionBatchRequest request, String userId) {
|
||||
List<String> ids = getBatchApiIds(request, request.getProjectId(), request.getProtocol(), true);
|
||||
List<String> ids = getBatchApiIds(request, request.getProjectId(), request.getProtocol(), true, userId);
|
||||
if (CollectionUtils.isNotEmpty(ids)) {
|
||||
handleRestoreApiDefinition(ids, userId, request.getProjectId());
|
||||
handleRestoreApiDefinition(ids, userId, request.getProjectId(), true);
|
||||
}
|
||||
}
|
||||
|
||||
public void batchTrashDel(ApiDefinitionBatchRequest request, String userId) {
|
||||
List<String> ids = getBatchApiIds(request, request.getProjectId(), request.getProtocol(), true);
|
||||
List<String> ids = getBatchApiIds(request, request.getProjectId(), request.getProtocol(), true, userId);
|
||||
if (CollectionUtils.isNotEmpty(ids)) {
|
||||
handleTrashDelApiDefinition(ids, userId, request.getProjectId());
|
||||
handleTrashDelApiDefinition(ids, userId, request.getProjectId(), true);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleTrashDelApiDefinition(List<String> ids, String userId, String projectId){
|
||||
private void handleTrashDelApiDefinition(List<String> ids, String userId, String projectId, boolean isBatch){
|
||||
if (CollectionUtils.isNotEmpty(ids)) {
|
||||
SubListUtils.dealForSubList(ids, 2000, subList -> doTrashDel(subList, userId, projectId));
|
||||
SubListUtils.dealForSubList(ids, 2000, subList -> doTrashDel(subList, userId, projectId, isBatch));
|
||||
}
|
||||
}
|
||||
|
||||
private void doTrashDel(List<String> ids, String userId, String projectId){
|
||||
private void doTrashDel(List<String> ids, String userId, String projectId, boolean isBatch){
|
||||
if(CollectionUtils.isNotEmpty(ids)){
|
||||
// 删除上传的文件
|
||||
ids.forEach(id -> {
|
||||
|
@ -613,10 +740,15 @@ public class ApiDefinitionService {
|
|||
// 删除接口关联数据
|
||||
trashDelApiRelatedData(ids, userId, projectId);
|
||||
|
||||
// 记录批量删除日志,单条删除通过注解记录
|
||||
if(isBatch){
|
||||
apiDefinitionLogService.batchTrashDelLog(ids, userId, projectId);
|
||||
}
|
||||
// 删除接口
|
||||
ApiDefinitionExample apiDefinitionExample = new ApiDefinitionExample();
|
||||
apiDefinitionExample.createCriteria().andIdIn(ids).andDeletedEqualTo(true).andProjectIdEqualTo(projectId);
|
||||
apiDefinitionMapper.deleteByExample(apiDefinitionExample);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -632,9 +764,11 @@ public class ApiDefinitionService {
|
|||
}
|
||||
|
||||
// 获取批量操作选中的ID
|
||||
public <T> List<String> getBatchApiIds(T dto, String projectId, String protocol, boolean deleted) {
|
||||
public <T> List<String> getBatchApiIds(T dto, String projectId, String protocol, boolean deleted, String userId) {
|
||||
TableBatchProcessDTO request = (TableBatchProcessDTO) dto;
|
||||
if (request.isSelectAll()) {
|
||||
// 全选
|
||||
CustomFieldUtils.setBaseQueryRequestCustomMultipleFields(request.getCondition(), userId);
|
||||
List<String> ids = extApiDefinitionMapper.getIds(request, projectId, protocol, deleted);
|
||||
if (CollectionUtils.isNotEmpty(request.getExcludeIds())) {
|
||||
ids.removeAll(request.getExcludeIds());
|
||||
|
@ -652,7 +786,9 @@ public class ApiDefinitionService {
|
|||
public ApiDefinitionDTO getApiDefinitionInfo(String id, String userId, ApiDefinition apiDefinition) {
|
||||
ApiDefinitionDTO apiDefinitionDTO = new ApiDefinitionDTO();
|
||||
// 2. 使用Optional避免空指针异常
|
||||
handleBlob(id, apiDefinitionDTO);
|
||||
apiDefinitionLogService.handleBlob(id, apiDefinitionDTO);
|
||||
// 3. 查询自定义字段
|
||||
handleCustomFields(id, apiDefinition.getProjectId(), apiDefinitionDTO);
|
||||
// 3. 使用Stream简化集合操作
|
||||
ApiDefinitionFollowerExample example = new ApiDefinitionFollowerExample();
|
||||
example.createCriteria().andApiDefinitionIdEqualTo(id).andUserIdEqualTo(userId);
|
||||
|
@ -661,15 +797,10 @@ public class ApiDefinitionService {
|
|||
return apiDefinitionDTO;
|
||||
}
|
||||
|
||||
public void handleBlob(String id, ApiDefinitionDTO apiDefinitionDTO) {
|
||||
Optional<ApiDefinitionBlob> apiDefinitionBlobOptional = Optional.ofNullable(apiDefinitionBlobMapper.selectByPrimaryKey(id));
|
||||
apiDefinitionBlobOptional.ifPresent(blob -> {
|
||||
apiDefinitionDTO.setRequest(ApiDataUtils.parseObject(new String(blob.getRequest()), AbstractMsTestElement.class));
|
||||
// blob.getResponse() 为 null 时不进行转换
|
||||
if (blob.getResponse() != null) {
|
||||
apiDefinitionDTO.setResponse(ApiDataUtils.parseArray(new String(blob.getResponse()), HttpResponse.class));
|
||||
}
|
||||
});
|
||||
public void handleCustomFields(String id, String projectId, ApiDefinitionDTO apiDefinitionDTO) {
|
||||
List<ApiDefinitionCustomFieldDTO> customFields = extApiDefinitionCustomFieldMapper.getApiCustomFields(Collections.singletonList(id), projectId);
|
||||
Map<String, List<ApiDefinitionCustomFieldDTO>> customFieldMap = customFields.stream().collect(Collectors.groupingBy(ApiDefinitionCustomFieldDTO::getApiId));
|
||||
apiDefinitionDTO.setCustomFields(customFieldMap.get(id));
|
||||
}
|
||||
|
||||
public ApiDefinitionDocDTO getDocInfo(ApiDefinitionDocRequest request, String userId) {
|
||||
|
@ -680,7 +811,7 @@ public class ApiDefinitionService {
|
|||
List<ApiDefinitionDTO> list = extApiDefinitionMapper.listDoc(request);
|
||||
if (!list.isEmpty()) {
|
||||
ApiDefinitionDTO first = list.get(0);
|
||||
handleBlob(first.getId(), first);
|
||||
apiDefinitionLogService.handleBlob(first.getId(), first);
|
||||
if(ApiDefinitionDocType.ALL.name().equals(request.getType())){
|
||||
apiDefinitionDocDTO.setDocTitle(Translator.get(ALL_API));
|
||||
} else {
|
||||
|
|
|
@ -99,6 +99,7 @@
|
|||
<table tableName="api_test_case_follower"/>
|
||||
<table tableName="api_definition_mock"/>
|
||||
<table tableName="api_definition_mock_config"/>
|
||||
<table tableName="api_definition_custom_field"/>
|
||||
|
||||
|
||||
</context>
|
||||
|
|
|
@ -5,7 +5,7 @@ import io.metersphere.api.controller.result.ApiResultCode;
|
|||
import io.metersphere.api.domain.*;
|
||||
import io.metersphere.api.dto.definition.*;
|
||||
import io.metersphere.api.dto.request.http.MsHTTPElement;
|
||||
import io.metersphere.api.enums.ApiDefinitionDocType;
|
||||
import io.metersphere.api.constants.ApiDefinitionDocType;
|
||||
import io.metersphere.api.mapper.*;
|
||||
import io.metersphere.api.service.ApiFileResourceService;
|
||||
import io.metersphere.api.utils.ApiDataUtils;
|
||||
|
@ -28,8 +28,8 @@ import io.metersphere.system.log.constants.OperationLogType;
|
|||
import io.metersphere.system.utils.Pager;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.junit.jupiter.api.*;
|
||||
import org.junit.platform.commons.util.StringUtils;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.http.MediaType;
|
||||
|
@ -40,6 +40,7 @@ import org.springframework.test.web.servlet.MvcResult;
|
|||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static io.metersphere.api.controller.result.ApiResultCode.API_DEFINITION_NOT_EXIST;
|
||||
import static io.metersphere.system.controller.handler.result.MsHttpResultCode.NOT_FOUND;
|
||||
|
@ -101,6 +102,9 @@ public class ApiDefinitionControllerTests extends BaseTest {
|
|||
@Resource
|
||||
private ApiDefinitionModuleMapper apiDefinitionModuleMapper;
|
||||
|
||||
@Resource
|
||||
private ExtApiDefinitionCustomFieldMapper extApiDefinitionCustomFieldMapper;
|
||||
|
||||
@Resource
|
||||
private FileMetadataService fileMetadataService;
|
||||
private static String fileMetadataId;
|
||||
|
@ -197,7 +201,7 @@ public class ApiDefinitionControllerTests extends BaseTest {
|
|||
// 创建并返回一个 ApiDefinitionAddRequest 对象,用于测试
|
||||
String defaultVersion = extBaseProjectVersionMapper.getDefaultVersion(DEFAULT_PROJECT_ID);
|
||||
ApiDefinitionAddRequest request = new ApiDefinitionAddRequest();
|
||||
request.setName("接口定义");
|
||||
request.setName("接口定义test");
|
||||
request.setProtocol("HTTP");
|
||||
request.setProjectId(DEFAULT_PROJECT_ID);
|
||||
request.setMethod("POST");
|
||||
|
@ -207,6 +211,11 @@ public class ApiDefinitionControllerTests extends BaseTest {
|
|||
request.setVersionId(defaultVersion);
|
||||
request.setDescription("描述内容");
|
||||
request.setTags(new LinkedHashSet<>(List.of("tag1", "tag2")));
|
||||
Map<String, String> customFieldMap = new HashMap<>();
|
||||
customFieldMap.put("custom-field", "oasis");
|
||||
customFieldMap.put("test_field", JSON.toJSONString(List.of("test")));
|
||||
|
||||
request.setCustomFields(customFieldMap);
|
||||
return request;
|
||||
}
|
||||
|
||||
|
@ -241,6 +250,12 @@ public class ApiDefinitionControllerTests extends BaseTest {
|
|||
example.createCriteria().andApiDefinitionIdEqualTo(apiDefinition.getId()).andUserIdEqualTo("admin");
|
||||
List<ApiDefinitionFollower> followers = apiDefinitionFollowerMapper.selectByExample(example);
|
||||
copyApiDefinitionDTO.setFollow(CollectionUtils.isNotEmpty(followers));
|
||||
|
||||
List<ApiDefinitionCustomFieldDTO> customFields = extApiDefinitionCustomFieldMapper.getApiCustomFields(Collections.singletonList(apiDefinition.getId()), apiDefinition.getProjectId());
|
||||
if(!customFields.isEmpty()) {
|
||||
Map<String, List<ApiDefinitionCustomFieldDTO>> customFieldMap = customFields.stream().collect(Collectors.groupingBy(ApiDefinitionCustomFieldDTO::getApiId));
|
||||
copyApiDefinitionDTO.setCustomFields(customFieldMap.get(apiDefinition.getId()));
|
||||
}
|
||||
if(apiDefinitionBlob != null){
|
||||
copyApiDefinitionDTO.setRequest(ApiDataUtils.parseObject(new String(apiDefinitionBlob.getRequest()), AbstractMsTestElement.class));
|
||||
copyApiDefinitionDTO.setResponse(ApiDataUtils.parseArray(new String(apiDefinitionBlob.getResponse()), HttpResponse.class));
|
||||
|
@ -268,6 +283,11 @@ public class ApiDefinitionControllerTests extends BaseTest {
|
|||
request.setMethod("POST");
|
||||
request.setModuleId("default1");
|
||||
request.setTags(new LinkedHashSet<>(List.of("tag1", "tag2-update")));
|
||||
Map<String, String> customFieldMap = new HashMap<>();
|
||||
customFieldMap.put("custom-field", "oasis-update");
|
||||
customFieldMap.put("test_field", JSON.toJSONString(List.of("test-update")));
|
||||
|
||||
request.setCustomFields(customFieldMap);
|
||||
MsHTTPElement msHttpElement = MsHTTPElementTest.getMsHttpElement();
|
||||
request.setRequest(ApiDataUtils.toJSONString(msHttpElement));
|
||||
List<HttpResponse> msHttpResponse = MsHTTPElementTest.getMsHttpResponse();
|
||||
|
@ -424,6 +444,18 @@ public class ApiDefinitionControllerTests extends BaseTest {
|
|||
apiDefinitionBatchUpdateRequest.setAppend(false);
|
||||
this.requestPostWithOk(BATCH_UPDATE, apiDefinitionBatchUpdateRequest);
|
||||
assertBatchUpdateApiDefinition(apiDefinitionBatchUpdateRequest, List.of("1003","1004"));
|
||||
// 自定义字段追加
|
||||
apiDefinitionBatchUpdateRequest.setType("customs");
|
||||
apiDefinitionBatchUpdateRequest.setSelectIds(List.of("1002","1003","1004"));
|
||||
ApiDefinitionCustomFieldDTO field = new ApiDefinitionCustomFieldDTO();
|
||||
field.setId("test_field");
|
||||
field.setValue(JSON.toJSONString(List.of("test1-batch")));
|
||||
apiDefinitionBatchUpdateRequest.setCustomField(field);
|
||||
apiDefinitionBatchUpdateRequest.setAppend(true);
|
||||
this.requestPostWithOk(BATCH_UPDATE, apiDefinitionBatchUpdateRequest);
|
||||
// 自定义字段覆盖
|
||||
apiDefinitionBatchUpdateRequest.setAppend(false);
|
||||
this.requestPostWithOk(BATCH_UPDATE, apiDefinitionBatchUpdateRequest);
|
||||
// 修改协议类型
|
||||
apiDefinitionBatchUpdateRequest.setType("method");
|
||||
apiDefinitionBatchUpdateRequest.setMethod("batch-method");
|
||||
|
@ -662,13 +694,30 @@ public class ApiDefinitionControllerTests extends BaseTest {
|
|||
filters.put("status", Arrays.asList("Underway", "Completed"));
|
||||
filters.put("method", List.of("GET"));
|
||||
filters.put("version_id", List.of("1005704995741369851"));
|
||||
filters.put("custom_multiple_custom-field", List.of("oasis"));
|
||||
request.setFilter(filters);
|
||||
}
|
||||
|
||||
private void configureCombineSearch(ApiDefinitionPageRequest request) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("name", Map.of("operator", "like", "value", "test-1"));
|
||||
map.put("name", Map.of("operator", "like", "value", "test"));
|
||||
map.put("method", Map.of("operator", "in", "value", Arrays.asList("GET", "POST")));
|
||||
map.put("createUser", Map.of("operator", "current user", "value", StringUtils.EMPTY));
|
||||
List<Map<String, Object>> customs = new ArrayList<>();
|
||||
Map<String, Object> custom = new HashMap<>();
|
||||
custom.put("id", "test_field");
|
||||
custom.put("operator", "in");
|
||||
custom.put("type", "multipleSelect");
|
||||
custom.put("value", JSON.toJSONString(List.of("test", "default")));
|
||||
customs.add(custom);
|
||||
Map<String, Object> currentUserCustom = new HashMap<>();
|
||||
currentUserCustom.put("id", "test_field");
|
||||
currentUserCustom.put("operator", "current user");
|
||||
currentUserCustom.put("type", "multipleMember");
|
||||
currentUserCustom.put("value", "current user");
|
||||
customs.add(currentUserCustom);
|
||||
map.put("customs", customs);
|
||||
|
||||
request.setCombine(map);
|
||||
}
|
||||
|
||||
|
@ -969,7 +1018,6 @@ public class ApiDefinitionControllerTests extends BaseTest {
|
|||
// @@校验日志
|
||||
checkLog("1002", OperationLogType.UPDATE);
|
||||
checkLog("1004", OperationLogType.UPDATE);
|
||||
checkLog("1005", OperationLogType.UPDATE);
|
||||
|
||||
// 恢复全部 条件为关键字为st-6的数据
|
||||
request.setSelectAll(true);
|
||||
|
|
|
@ -42,3 +42,17 @@ INSERT INTO `api_definition_blob` (`id`, `request`, `response`) VALUES ('1003',
|
|||
INSERT INTO `api_definition_blob` (`id`, `request`, `response`) VALUES ('1004', 0x504B03041400080808004A547857000000000000000000000000030000007A6970CD92B14EC3301040FFE5E6A8296B36842A180055281B62709D4B6D61FBDCF3991055FD779C840C949185C5A77BB6CFEF6C9F21921B3D7134563F2B8FD0C0537A68DBFDCEA1C720504158F01C2AC0A00EAEE4BD72092BD0C6BA8E314013B27315647665AD11894D5D0FC3B0114CB2D1E4CBD6A8C494C97A4225F52886BA02EE776D490FD48D6B1583AA434ED0BC9EE11D0B9EC70A3E94CB93CB127FC9749834DB28968ACF9CC1E5AD029ECEFB7BA9A90156BE1D23AE9E8CA76C194B13C2B9ECF2363C62384E6D2E0BBCFAFC093068EAD66326B953461EFFAD1D8941BEA3D0DB233467D014026A69AD47CAE54E6FB6DBED7CBF9142C22BAC91C5F6562BC15B6755794D5073ACA027E76878C1AEE86949ABA0CA4257F03253B32A2C9A9171CFA431259A3EC937A424D7F4F205504B070852639A522B010000E0020000504B010214001400080808004A54785752639A522B010000E00200000300000000000000000000000000000000007A6970504B05060000000001000100310000005C0100000000, 0x504B03041400080808004A547857000000000000000000000000030000007A6970A58F414BC4301085FFCB9C03B69EA4B74559141465295E9622B3CD743798263199C82EA5FFDD49EB82772F19DECB9BEF25FB098C86A656C09740D0C063DBBE81028763513B4AC1BB44B55827424D3141B39FE0932E725B4E05DF6873C9AE5301393C583106B48914684A7D34818D77122A0AE64EC1C16B414CCB6CD7EAEDEBEEE5E361D36E0432443FBE17E03FFB98124B2660C4F1B786E95CAC485FD94492CF73CCB2371AF74CEEC82768EE44E1F9AAEA4A41EF1D93E33F849B60D1B8A5BEF79AAE94C1587A12A6CBD6CEDDAC2031724EF74B046EAB0ACA0B07CC96B7168FEBDADCFD00504B0708FF595995E400000087010000504B010214001400080808004A547857FF595995E4000000870100000300000000000000000000000000000000007A6970504B0506000000000100010031000000150100000000);
|
||||
INSERT INTO `api_definition_blob` (`id`, `request`, `response`) VALUES ('1005', 0x504B030414000808080049547857000000000000000000000000030000007A6970CD92B14EC3301040FFE5E6A8296B36842A180055281B62709D4B6D61FBDCF3991055FD779C840C949185C5A77BB6CFEF6C9F21921B3D7134563F2B8FD0C0537A68DBFDCEA1C720504158F01C2AC0A00EAEE4BD72092BD0C6BA8E314013B27315647665AD11894D5D0FC3B0114CB2D1E4CBD6A8C494C97A4225F52886BA02EE776D490FD48D6B1583AA434ED0BC9EE11D0B9EC70A3E94CB93CB127FC9749834DB28968ACF9CC1E5AD029ECEFB7BA9A90156BE1D23AE9E8CA76C194B13C2B9ECF2363C62384E6D2E0BBCFAFC093068EAD66326B953461EFFAD1D8941BEA3D0DB233467D014026A69AD47CAE54E6FB6DBED7CBF9142C22BAC91C5F6562BC15B6755794D5073ACA027E76878C1AEE86949ABA0CA4257F03253B32A2C9A9171CFA431259A3EC937A424D7F4F205504B070852639A522B010000E0020000504B010214001400080808004954785752639A522B010000E00200000300000000000000000000000000000000007A6970504B05060000000001000100310000005C0100000000, 0x504B030414000808080049547857000000000000000000000000030000007A6970A58F414BC4301085FFCB9C03B69EA4B74559141465295E9622B3CD743798263199C82EA5FFDD49EB82772F19DECB9BEF25FB098C86A656C09740D0C063DBBE81028763513B4AC1BB44B55827424D3141B39FE0932E725B4E05DF6873C9AE5301393C583106B48914684A7D34818D77122A0AE64EC1C16B414CCB6CD7EAEDEBEEE5E361D36E0432443FBE17E03FFB98124B2660C4F1B786E95CAC485FD94492CF73CCB2371AF74CEEC82768EE44E1F9AAEA4A41EF1D93E33F849B60D1B8A5BEF79AAE94C1587A12A6CBD6CEDDAC2031724EF74B046EAB0ACA0B07CC96B7168FEBDADCFD00504B0708FF595995E400000087010000504B0102140014000808080049547857FF595995E4000000870100000300000000000000000000000000000000007A6970504B0506000000000100010031000000150100000000);
|
||||
INSERT INTO `api_definition_blob` (`id`, `request`, `response`) VALUES ('1006', 0x504B030414000808080049547857000000000000000000000000030000007A6970CD92B14EC3301040FFE5E6A8296B36842A180055281B62709D4B6D61FBDCF3991055FD779C840C949185C5A77BB6CFEF6C9F21921B3D7134563F2B8FD0C0537A68DBFDCEA1C720504158F01C2AC0A00EAEE4BD72092BD0C6BA8E314013B27315647665AD11894D5D0FC3B0114CB2D1E4CBD6A8C494C97A4225F52886BA02EE776D490FD48D6B1583AA434ED0BC9EE11D0B9EC70A3E94CB93CB127FC9749834DB28968ACF9CC1E5AD029ECEFB7BA9A90156BE1D23AE9E8CA76C194B13C2B9ECF2363C62384E6D2E0BBCFAFC093068EAD66326B953461EFFAD1D8941BEA3D0DB233467D014026A69AD47CAE54E6FB6DBED7CBF9142C22BAC91C5F6562BC15B6755794D5073ACA027E76878C1AEE86949ABA0CA4257F03253B32A2C9A9171CFA431259A3EC937A424D7F4F205504B070852639A522B010000E0020000504B010214001400080808004954785752639A522B010000E00200000300000000000000000000000000000000007A6970504B05060000000001000100310000005C0100000000, 0x504B030414000808080049547857000000000000000000000000030000007A6970A58F414BC4301085FFCB9C03B69EA4B74559141465295E9622B3CD743798263199C82EA5FFDD49EB82772F19DECB9BEF25FB098C86A656C09740D0C063DBBE81028763513B4AC1BB44B55827424D3141B39FE0932E725B4E05DF6873C9AE5301393C583106B48914684A7D34818D77122A0AE64EC1C16B414CCB6CD7EAEDEBEEE5E361D36E0432443FBE17E03FFB98124B2660C4F1B786E95CAC485FD94492CF73CCB2371AF74CEEC82768EE44E1F9AAEA4A41EF1D93E33F849B60D1B8A5BEF79AAE94C1587A12A6CBD6CEDDAC2031724EF74B046EAB0ACA0B07CC96B7168FEBDADCFD00504B0708FF595995E400000087010000504B0102140014000808080049547857FF595995E4000000870100000300000000000000000000000000000000007A6970504B0506000000000100010031000000150100000000);
|
||||
|
||||
DELETE FROM `api_definition_custom_field` WHERE `api_id` in ('1003', '1004');
|
||||
INSERT INTO api_definition_custom_field (api_id, field_id, value) VALUE ('1003', 'test_field', '["default", "default-1"]');
|
||||
INSERT INTO api_definition_custom_field (api_id, field_id, value) VALUE ('1004', 'test_field', '[]');
|
||||
|
||||
DELETE FROM `custom_field` WHERE `id` in ('test_field', 'custom-field');
|
||||
INSERT INTO custom_field (id, name, scene, type, remark, internal, scope_type, create_time, update_time, create_user, scope_id) VALUE
|
||||
('test_field', '测试字段', 'API', 'MULTIPLE_SELECT', '', 0, 'PROJECT', UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, 'admin', '100001100001'),
|
||||
('custom-field', '测试字段', 'API', 'SELECT', '', 0, 'PROJECT', UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, 'admin', '100001100001');
|
||||
|
||||
DELETE FROM `template` WHERE `id` in ('api-template-id', 'default-api-template-id');
|
||||
INSERT INTO template (id, name, remark, internal, update_time, create_time, create_user, scope_type, scope_id, enable_third_part, scene) VALUES
|
||||
('api-template-id', 'api-template', '', 0, UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, 'admin', 'PROJECT', '100001100001', 0, 'API'),
|
||||
('default-api-template-id', 'api-default-template', '', 0, UNIX_TIMESTAMP() * 1000, UNIX_TIMESTAMP() * 1000, 'admin', 'PROJECT', '100001100001', 0, 'API');
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
package io.metersphere.system.utils;
|
||||
|
||||
import io.metersphere.sdk.constants.CustomFieldType;
|
||||
import io.metersphere.sdk.util.JSON;
|
||||
import io.metersphere.system.dto.sdk.BaseCondition;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.collections.MapUtils;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 自定义字段处理工具类
|
||||
*/
|
||||
@UtilityClass
|
||||
public class CustomFieldUtils {
|
||||
|
||||
public static final String COMBINE_CUSTOM = "customs";
|
||||
public static final String COMBINE_CUSTOM_FIELD_TYPE = "type";
|
||||
public static final String COMBINE_CUSTOM_FIELD_VALUE = "value";
|
||||
public static final String COMBINE_CUSTOM_FIELD_OPERATOR = "operator";
|
||||
public static final String IS_CURRENT_USER = "current user";
|
||||
public static final String CUSTOM_MULTIPLE_PREFIX = "custom_multiple";
|
||||
|
||||
/**
|
||||
* 设置列表查询的多选字段参数
|
||||
* @param request 请求参数
|
||||
*/
|
||||
public static void setBaseQueryRequestCustomMultipleFields(BaseCondition request, String userId) {
|
||||
handleFilterCustomMultipleFields(request);
|
||||
handleCombineFields(request, userId);
|
||||
}
|
||||
|
||||
private static void handleFilterCustomMultipleFields(BaseCondition request) {
|
||||
if (MapUtils.isNotEmpty(request.getFilter())) {
|
||||
request.getFilter().forEach((key, value) -> {
|
||||
if (key.startsWith(CUSTOM_MULTIPLE_PREFIX) && CollectionUtils.isNotEmpty(value)) {
|
||||
List<String> jsonValues = value.stream().map(item -> "[\"".concat(item).concat("\"]")).toList();
|
||||
request.getFilter().put(key, jsonValues);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private static void handleCombineFields(BaseCondition request, String userId) {
|
||||
Map<String, Object> combine = request.getCombine();
|
||||
if (MapUtils.isNotEmpty(combine)) {
|
||||
combine.forEach((k, v) -> {
|
||||
if (StringUtils.equals(k, COMBINE_CUSTOM) && ObjectUtils.isNotEmpty(v)) {
|
||||
handleCombineCustomFields((List<Map<String, Object>>) v, userId);
|
||||
} else {
|
||||
handleCombineField(v, userId);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private static void handleCombineCustomFields(List<Map<String, Object>> customs, String userId) {
|
||||
customs.forEach(custom -> {
|
||||
String operator = custom.get(COMBINE_CUSTOM_FIELD_OPERATOR).toString();
|
||||
if (StringUtils.equalsIgnoreCase(operator, IS_CURRENT_USER)) {
|
||||
custom.put(COMBINE_CUSTOM_FIELD_VALUE, userId);
|
||||
return;
|
||||
}
|
||||
String fieldType = custom.get(COMBINE_CUSTOM_FIELD_TYPE).toString();
|
||||
String fieldValue = custom.get(COMBINE_CUSTOM_FIELD_VALUE).toString();
|
||||
|
||||
if (StringUtils.equalsAny(fieldType, CustomFieldType.MULTIPLE_MEMBER.getType(),
|
||||
CustomFieldType.CHECKBOX.getType(), CustomFieldType.MULTIPLE_SELECT.getType()) && StringUtils.isNotEmpty(fieldValue)) {
|
||||
List<String> customValues = JSON.parseArray(fieldValue, String.class);
|
||||
List<String> jsonValues = customValues.stream().map(item -> "JSON_CONTAINS(`value`, '[\"".concat(item).concat("\"]')")).toList();
|
||||
custom.put(COMBINE_CUSTOM_FIELD_VALUE, "(".concat(StringUtils.join(jsonValues, " OR ")).concat(")"));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static void handleCombineField(Object v, String userId) {
|
||||
Map<String, Object> combineField = new HashMap<>((Map<String, Object>) v);
|
||||
if (StringUtils.equalsIgnoreCase(combineField.get(COMBINE_CUSTOM_FIELD_OPERATOR).toString(), IS_CURRENT_USER)) {
|
||||
combineField.put(COMBINE_CUSTOM_FIELD_VALUE, userId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 多选字段追加值
|
||||
* @param originalVal 原始值
|
||||
* @param appendVal 追加值
|
||||
* @return 追加后的值
|
||||
*/
|
||||
public static String appendToMultipleCustomField(String originalVal, String appendVal) {
|
||||
if (StringUtils.isEmpty(originalVal)) {
|
||||
return appendVal;
|
||||
}
|
||||
List<String> orignalList = JSON.parseArray(originalVal, String.class);
|
||||
List<String> appendList = JSON.parseArray(appendVal, String.class);
|
||||
orignalList.addAll(appendList);
|
||||
// 追加后需去重
|
||||
return JSON.toJSONString(orignalList.stream().distinct().toList());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
package io.metersphere.system.controller;
|
||||
|
||||
import io.metersphere.sdk.util.JSON;
|
||||
import io.metersphere.system.base.BaseTest;
|
||||
import io.metersphere.system.dto.sdk.BaseCondition;
|
||||
import io.metersphere.system.utils.CustomFieldUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.junit.jupiter.api.*;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author: LAN
|
||||
* @date: 2023/12/14 10:18
|
||||
* @version: 1.0
|
||||
*/
|
||||
|
||||
@SpringBootTest(webEnvironment= SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||
@AutoConfigureMockMvc
|
||||
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
||||
class CustomFieldTests extends BaseTest {
|
||||
@Test
|
||||
@Order(1)
|
||||
void testSetBaseQueryRequestCustomMultipleFields() {
|
||||
BaseCondition baseCondition = new BaseCondition();
|
||||
Map<String, List<String>> filters = new HashMap<>();
|
||||
filters.put("status", Arrays.asList("Underway", "Completed"));
|
||||
filters.put("custom_multiple_custom-field", List.of("oasis"));
|
||||
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("name", Map.of("operator", "like", "value", "test"));
|
||||
map.put("method", Map.of("operator", "in", "value", Arrays.asList("GET", "POST")));
|
||||
map.put("createUser", Map.of("operator", "current user", "value", StringUtils.EMPTY));
|
||||
List<Map<String, Object>> customs = new ArrayList<>();
|
||||
Map<String, Object> custom = new HashMap<>();
|
||||
custom.put("id", "test_field");
|
||||
custom.put("operator", "in");
|
||||
custom.put("type", "multipleSelect");
|
||||
custom.put("value", JSON.toJSONString(List.of("test", "default")));
|
||||
customs.add(custom);
|
||||
Map<String, Object> currentUserCustom = new HashMap<>();
|
||||
currentUserCustom.put("id", "test_field");
|
||||
currentUserCustom.put("operator", "current user");
|
||||
currentUserCustom.put("type", "multipleMember");
|
||||
currentUserCustom.put("value", "current user");
|
||||
customs.add(currentUserCustom);
|
||||
map.put("customs", customs);
|
||||
|
||||
baseCondition.setFilter(filters);
|
||||
baseCondition.setCombine(map);
|
||||
|
||||
// 调用测试方法
|
||||
CustomFieldUtils.setBaseQueryRequestCustomMultipleFields(baseCondition, "admin");
|
||||
|
||||
// 验证预期结果
|
||||
Assertions.assertNotNull(baseCondition.getFilter());
|
||||
Assertions.assertNotNull(baseCondition.getCombine());
|
||||
|
||||
// 验证多选字段是否被正确处理
|
||||
List<String> customMultipleValues = baseCondition.getFilter().get("custom_multiple_custom-field");
|
||||
Assertions.assertNotNull(customMultipleValues);
|
||||
Assertions.assertEquals(1, customMultipleValues.size());
|
||||
Assertions.assertTrue(customMultipleValues.contains("[\"oasis\"]"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(2)
|
||||
void testAppendToMultipleCustomFieldWithEmptyOriginalValue() {
|
||||
// 创建测试数据,originalValue 为空
|
||||
String originalValue = "";
|
||||
String appendValue = "[\"value2\",\"value3\"]";
|
||||
|
||||
// 调用被测试方法
|
||||
String resultEmptyOriginal = CustomFieldUtils.appendToMultipleCustomField(originalValue, appendValue);
|
||||
|
||||
// 验证预期结果
|
||||
Assertions.assertNotNull(resultEmptyOriginal);
|
||||
Assertions.assertEquals("[\"value2\",\"value3\"]", resultEmptyOriginal);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(3)
|
||||
void testAppendToMultipleCustomField() {
|
||||
// 创建测试数据
|
||||
String originalValue = "[\"value1\", \"value2\"]";
|
||||
String appendValue = "[\"value2\", \"value3\"]";
|
||||
|
||||
// 调用被测试方法
|
||||
String result = CustomFieldUtils.appendToMultipleCustomField(originalValue, appendValue);
|
||||
|
||||
|
||||
// 验证预期结果
|
||||
Assertions.assertNotNull(result);
|
||||
Assertions.assertEquals("[\"value1\",\"value2\",\"value3\"]", result);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue