feat(系统设置): 服务集成插件化

This commit is contained in:
chenjianxing 2022-11-11 17:29:24 +08:00 committed by jianxing
parent 122d0fbc00
commit debc072829
33 changed files with 1216 additions and 820 deletions

View File

@ -1,9 +0,0 @@
package io.metersphere.api.dto.plugin;
import io.metersphere.plugin.core.ui.PluginResource;
import lombok.Data;
@Data
public class PluginResourceDTO extends PluginResource {
private String entry;
}

View File

@ -1,409 +0,0 @@
<?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.base.mapper.PluginMapper">
<resultMap id="BaseResultMap" type="io.metersphere.base.domain.Plugin">
<id column="id" jdbcType="VARCHAR" property="id" />
<result column="name" jdbcType="VARCHAR" property="name" />
<result column="plugin_id" jdbcType="VARCHAR" property="pluginId" />
<result column="script_id" jdbcType="VARCHAR" property="scriptId" />
<result column="jmeter_clazz" jdbcType="VARCHAR" property="jmeterClazz" />
<result column="clazz_name" jdbcType="VARCHAR" property="clazzName" />
<result column="source_path" jdbcType="VARCHAR" property="sourcePath" />
<result column="source_name" jdbcType="VARCHAR" property="sourceName" />
<result column="exec_entry" jdbcType="VARCHAR" property="execEntry" />
<result column="create_time" jdbcType="BIGINT" property="createTime" />
<result column="update_time" jdbcType="BIGINT" property="updateTime" />
<result column="create_user_id" jdbcType="VARCHAR" property="createUserId" />
</resultMap>
<resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="io.metersphere.base.domain.PluginWithBLOBs">
<result column="form_option" jdbcType="LONGVARCHAR" property="formOption" />
<result column="form_script" jdbcType="LONGVARCHAR" property="formScript" />
</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">
id, `name`, plugin_id, script_id, jmeter_clazz, clazz_name, source_path, source_name,
exec_entry, create_time, update_time, create_user_id
</sql>
<sql id="Blob_Column_List">
form_option, form_script
</sql>
<select id="selectByExampleWithBLOBs" parameterType="io.metersphere.base.domain.PluginExample" resultMap="ResultMapWithBLOBs">
select
<if test="distinct">
distinct
</if>
<include refid="Base_Column_List" />
,
<include refid="Blob_Column_List" />
from plugin
<if test="_parameter != null">
<include refid="Example_Where_Clause" />
</if>
<if test="orderByClause != null">
order by ${orderByClause}
</if>
</select>
<select id="selectByExample" parameterType="io.metersphere.base.domain.PluginExample" resultMap="BaseResultMap">
select
<if test="distinct">
distinct
</if>
<include refid="Base_Column_List" />
from plugin
<if test="_parameter != null">
<include refid="Example_Where_Clause" />
</if>
<if test="orderByClause != null">
order by ${orderByClause}
</if>
</select>
<select id="selectByPrimaryKey" parameterType="java.lang.String" resultMap="ResultMapWithBLOBs">
select
<include refid="Base_Column_List" />
,
<include refid="Blob_Column_List" />
from plugin
where id = #{id,jdbcType=VARCHAR}
</select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.String">
delete from plugin
where id = #{id,jdbcType=VARCHAR}
</delete>
<delete id="deleteByExample" parameterType="io.metersphere.base.domain.PluginExample">
delete from plugin
<if test="_parameter != null">
<include refid="Example_Where_Clause" />
</if>
</delete>
<insert id="insert" parameterType="io.metersphere.base.domain.PluginWithBLOBs">
insert into plugin (id, `name`, plugin_id,
script_id, jmeter_clazz, clazz_name,
source_path, source_name, exec_entry,
create_time, update_time, create_user_id,
form_option, form_script)
values (#{id,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{pluginId,jdbcType=VARCHAR},
#{scriptId,jdbcType=VARCHAR}, #{jmeterClazz,jdbcType=VARCHAR}, #{clazzName,jdbcType=VARCHAR},
#{sourcePath,jdbcType=VARCHAR}, #{sourceName,jdbcType=VARCHAR}, #{execEntry,jdbcType=VARCHAR},
#{createTime,jdbcType=BIGINT}, #{updateTime,jdbcType=BIGINT}, #{createUserId,jdbcType=VARCHAR},
#{formOption,jdbcType=LONGVARCHAR}, #{formScript,jdbcType=LONGVARCHAR})
</insert>
<insert id="insertSelective" parameterType="io.metersphere.base.domain.PluginWithBLOBs">
insert into plugin
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="id != null">
id,
</if>
<if test="name != null">
`name`,
</if>
<if test="pluginId != null">
plugin_id,
</if>
<if test="scriptId != null">
script_id,
</if>
<if test="jmeterClazz != null">
jmeter_clazz,
</if>
<if test="clazzName != null">
clazz_name,
</if>
<if test="sourcePath != null">
source_path,
</if>
<if test="sourceName != null">
source_name,
</if>
<if test="execEntry != null">
exec_entry,
</if>
<if test="createTime != null">
create_time,
</if>
<if test="updateTime != null">
update_time,
</if>
<if test="createUserId != null">
create_user_id,
</if>
<if test="formOption != null">
form_option,
</if>
<if test="formScript != null">
form_script,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="id != null">
#{id,jdbcType=VARCHAR},
</if>
<if test="name != null">
#{name,jdbcType=VARCHAR},
</if>
<if test="pluginId != null">
#{pluginId,jdbcType=VARCHAR},
</if>
<if test="scriptId != null">
#{scriptId,jdbcType=VARCHAR},
</if>
<if test="jmeterClazz != null">
#{jmeterClazz,jdbcType=VARCHAR},
</if>
<if test="clazzName != null">
#{clazzName,jdbcType=VARCHAR},
</if>
<if test="sourcePath != null">
#{sourcePath,jdbcType=VARCHAR},
</if>
<if test="sourceName != null">
#{sourceName,jdbcType=VARCHAR},
</if>
<if test="execEntry != null">
#{execEntry,jdbcType=VARCHAR},
</if>
<if test="createTime != null">
#{createTime,jdbcType=BIGINT},
</if>
<if test="updateTime != null">
#{updateTime,jdbcType=BIGINT},
</if>
<if test="createUserId != null">
#{createUserId,jdbcType=VARCHAR},
</if>
<if test="formOption != null">
#{formOption,jdbcType=LONGVARCHAR},
</if>
<if test="formScript != null">
#{formScript,jdbcType=LONGVARCHAR},
</if>
</trim>
</insert>
<select id="countByExample" parameterType="io.metersphere.base.domain.PluginExample" resultType="java.lang.Long">
select count(*) from plugin
<if test="_parameter != null">
<include refid="Example_Where_Clause" />
</if>
</select>
<update id="updateByExampleSelective" parameterType="map">
update plugin
<set>
<if test="record.id != null">
id = #{record.id,jdbcType=VARCHAR},
</if>
<if test="record.name != null">
`name` = #{record.name,jdbcType=VARCHAR},
</if>
<if test="record.pluginId != null">
plugin_id = #{record.pluginId,jdbcType=VARCHAR},
</if>
<if test="record.scriptId != null">
script_id = #{record.scriptId,jdbcType=VARCHAR},
</if>
<if test="record.jmeterClazz != null">
jmeter_clazz = #{record.jmeterClazz,jdbcType=VARCHAR},
</if>
<if test="record.clazzName != null">
clazz_name = #{record.clazzName,jdbcType=VARCHAR},
</if>
<if test="record.sourcePath != null">
source_path = #{record.sourcePath,jdbcType=VARCHAR},
</if>
<if test="record.sourceName != null">
source_name = #{record.sourceName,jdbcType=VARCHAR},
</if>
<if test="record.execEntry != null">
exec_entry = #{record.execEntry,jdbcType=VARCHAR},
</if>
<if test="record.createTime != null">
create_time = #{record.createTime,jdbcType=BIGINT},
</if>
<if test="record.updateTime != null">
update_time = #{record.updateTime,jdbcType=BIGINT},
</if>
<if test="record.createUserId != null">
create_user_id = #{record.createUserId,jdbcType=VARCHAR},
</if>
<if test="record.formOption != null">
form_option = #{record.formOption,jdbcType=LONGVARCHAR},
</if>
<if test="record.formScript != null">
form_script = #{record.formScript,jdbcType=LONGVARCHAR},
</if>
</set>
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
</if>
</update>
<update id="updateByExampleWithBLOBs" parameterType="map">
update plugin
set id = #{record.id,jdbcType=VARCHAR},
`name` = #{record.name,jdbcType=VARCHAR},
plugin_id = #{record.pluginId,jdbcType=VARCHAR},
script_id = #{record.scriptId,jdbcType=VARCHAR},
jmeter_clazz = #{record.jmeterClazz,jdbcType=VARCHAR},
clazz_name = #{record.clazzName,jdbcType=VARCHAR},
source_path = #{record.sourcePath,jdbcType=VARCHAR},
source_name = #{record.sourceName,jdbcType=VARCHAR},
exec_entry = #{record.execEntry,jdbcType=VARCHAR},
create_time = #{record.createTime,jdbcType=BIGINT},
update_time = #{record.updateTime,jdbcType=BIGINT},
create_user_id = #{record.createUserId,jdbcType=VARCHAR},
form_option = #{record.formOption,jdbcType=LONGVARCHAR},
form_script = #{record.formScript,jdbcType=LONGVARCHAR}
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
</if>
</update>
<update id="updateByExample" parameterType="map">
update plugin
set id = #{record.id,jdbcType=VARCHAR},
`name` = #{record.name,jdbcType=VARCHAR},
plugin_id = #{record.pluginId,jdbcType=VARCHAR},
script_id = #{record.scriptId,jdbcType=VARCHAR},
jmeter_clazz = #{record.jmeterClazz,jdbcType=VARCHAR},
clazz_name = #{record.clazzName,jdbcType=VARCHAR},
source_path = #{record.sourcePath,jdbcType=VARCHAR},
source_name = #{record.sourceName,jdbcType=VARCHAR},
exec_entry = #{record.execEntry,jdbcType=VARCHAR},
create_time = #{record.createTime,jdbcType=BIGINT},
update_time = #{record.updateTime,jdbcType=BIGINT},
create_user_id = #{record.createUserId,jdbcType=VARCHAR}
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
</if>
</update>
<update id="updateByPrimaryKeySelective" parameterType="io.metersphere.base.domain.PluginWithBLOBs">
update plugin
<set>
<if test="name != null">
`name` = #{name,jdbcType=VARCHAR},
</if>
<if test="pluginId != null">
plugin_id = #{pluginId,jdbcType=VARCHAR},
</if>
<if test="scriptId != null">
script_id = #{scriptId,jdbcType=VARCHAR},
</if>
<if test="jmeterClazz != null">
jmeter_clazz = #{jmeterClazz,jdbcType=VARCHAR},
</if>
<if test="clazzName != null">
clazz_name = #{clazzName,jdbcType=VARCHAR},
</if>
<if test="sourcePath != null">
source_path = #{sourcePath,jdbcType=VARCHAR},
</if>
<if test="sourceName != null">
source_name = #{sourceName,jdbcType=VARCHAR},
</if>
<if test="execEntry != null">
exec_entry = #{execEntry,jdbcType=VARCHAR},
</if>
<if test="createTime != null">
create_time = #{createTime,jdbcType=BIGINT},
</if>
<if test="updateTime != null">
update_time = #{updateTime,jdbcType=BIGINT},
</if>
<if test="createUserId != null">
create_user_id = #{createUserId,jdbcType=VARCHAR},
</if>
<if test="formOption != null">
form_option = #{formOption,jdbcType=LONGVARCHAR},
</if>
<if test="formScript != null">
form_script = #{formScript,jdbcType=LONGVARCHAR},
</if>
</set>
where id = #{id,jdbcType=VARCHAR}
</update>
<update id="updateByPrimaryKeyWithBLOBs" parameterType="io.metersphere.base.domain.PluginWithBLOBs">
update plugin
set `name` = #{name,jdbcType=VARCHAR},
plugin_id = #{pluginId,jdbcType=VARCHAR},
script_id = #{scriptId,jdbcType=VARCHAR},
jmeter_clazz = #{jmeterClazz,jdbcType=VARCHAR},
clazz_name = #{clazzName,jdbcType=VARCHAR},
source_path = #{sourcePath,jdbcType=VARCHAR},
source_name = #{sourceName,jdbcType=VARCHAR},
exec_entry = #{execEntry,jdbcType=VARCHAR},
create_time = #{createTime,jdbcType=BIGINT},
update_time = #{updateTime,jdbcType=BIGINT},
create_user_id = #{createUserId,jdbcType=VARCHAR},
form_option = #{formOption,jdbcType=LONGVARCHAR},
form_script = #{formScript,jdbcType=LONGVARCHAR}
where id = #{id,jdbcType=VARCHAR}
</update>
<update id="updateByPrimaryKey" parameterType="io.metersphere.base.domain.Plugin">
update plugin
set `name` = #{name,jdbcType=VARCHAR},
plugin_id = #{pluginId,jdbcType=VARCHAR},
script_id = #{scriptId,jdbcType=VARCHAR},
jmeter_clazz = #{jmeterClazz,jdbcType=VARCHAR},
clazz_name = #{clazzName,jdbcType=VARCHAR},
source_path = #{sourcePath,jdbcType=VARCHAR},
source_name = #{sourceName,jdbcType=VARCHAR},
exec_entry = #{execEntry,jdbcType=VARCHAR},
create_time = #{createTime,jdbcType=BIGINT},
update_time = #{updateTime,jdbcType=BIGINT},
create_user_id = #{createUserId,jdbcType=VARCHAR}
where id = #{id,jdbcType=VARCHAR}
</update>
</mapper>

View File

@ -1,8 +1,7 @@
package io.metersphere.base.domain;
import lombok.Data;
import java.io.Serializable;
import lombok.Data;
@Data
public class Plugin implements Serializable {
@ -14,10 +13,10 @@ public class Plugin implements Serializable {
private String scriptId;
private String jmeterClazz;
private String clazzName;
private String jmeterClazz;
private String sourcePath;
private String sourceName;
@ -30,5 +29,9 @@ public class Plugin implements Serializable {
private String createUserId;
private Boolean xpack;
private String scenario;
private static final long serialVersionUID = 1L;
}
}

View File

@ -384,76 +384,6 @@ public class PluginExample {
return (Criteria) this;
}
public Criteria andJmeterClazzIsNull() {
addCriterion("jmeter_clazz is null");
return (Criteria) this;
}
public Criteria andJmeterClazzIsNotNull() {
addCriterion("jmeter_clazz is not null");
return (Criteria) this;
}
public Criteria andJmeterClazzEqualTo(String value) {
addCriterion("jmeter_clazz =", value, "jmeterClazz");
return (Criteria) this;
}
public Criteria andJmeterClazzNotEqualTo(String value) {
addCriterion("jmeter_clazz <>", value, "jmeterClazz");
return (Criteria) this;
}
public Criteria andJmeterClazzGreaterThan(String value) {
addCriterion("jmeter_clazz >", value, "jmeterClazz");
return (Criteria) this;
}
public Criteria andJmeterClazzGreaterThanOrEqualTo(String value) {
addCriterion("jmeter_clazz >=", value, "jmeterClazz");
return (Criteria) this;
}
public Criteria andJmeterClazzLessThan(String value) {
addCriterion("jmeter_clazz <", value, "jmeterClazz");
return (Criteria) this;
}
public Criteria andJmeterClazzLessThanOrEqualTo(String value) {
addCriterion("jmeter_clazz <=", value, "jmeterClazz");
return (Criteria) this;
}
public Criteria andJmeterClazzLike(String value) {
addCriterion("jmeter_clazz like", value, "jmeterClazz");
return (Criteria) this;
}
public Criteria andJmeterClazzNotLike(String value) {
addCriterion("jmeter_clazz not like", value, "jmeterClazz");
return (Criteria) this;
}
public Criteria andJmeterClazzIn(List<String> values) {
addCriterion("jmeter_clazz in", values, "jmeterClazz");
return (Criteria) this;
}
public Criteria andJmeterClazzNotIn(List<String> values) {
addCriterion("jmeter_clazz not in", values, "jmeterClazz");
return (Criteria) this;
}
public Criteria andJmeterClazzBetween(String value1, String value2) {
addCriterion("jmeter_clazz between", value1, value2, "jmeterClazz");
return (Criteria) this;
}
public Criteria andJmeterClazzNotBetween(String value1, String value2) {
addCriterion("jmeter_clazz not between", value1, value2, "jmeterClazz");
return (Criteria) this;
}
public Criteria andClazzNameIsNull() {
addCriterion("clazz_name is null");
return (Criteria) this;
@ -524,6 +454,76 @@ public class PluginExample {
return (Criteria) this;
}
public Criteria andJmeterClazzIsNull() {
addCriterion("jmeter_clazz is null");
return (Criteria) this;
}
public Criteria andJmeterClazzIsNotNull() {
addCriterion("jmeter_clazz is not null");
return (Criteria) this;
}
public Criteria andJmeterClazzEqualTo(String value) {
addCriterion("jmeter_clazz =", value, "jmeterClazz");
return (Criteria) this;
}
public Criteria andJmeterClazzNotEqualTo(String value) {
addCriterion("jmeter_clazz <>", value, "jmeterClazz");
return (Criteria) this;
}
public Criteria andJmeterClazzGreaterThan(String value) {
addCriterion("jmeter_clazz >", value, "jmeterClazz");
return (Criteria) this;
}
public Criteria andJmeterClazzGreaterThanOrEqualTo(String value) {
addCriterion("jmeter_clazz >=", value, "jmeterClazz");
return (Criteria) this;
}
public Criteria andJmeterClazzLessThan(String value) {
addCriterion("jmeter_clazz <", value, "jmeterClazz");
return (Criteria) this;
}
public Criteria andJmeterClazzLessThanOrEqualTo(String value) {
addCriterion("jmeter_clazz <=", value, "jmeterClazz");
return (Criteria) this;
}
public Criteria andJmeterClazzLike(String value) {
addCriterion("jmeter_clazz like", value, "jmeterClazz");
return (Criteria) this;
}
public Criteria andJmeterClazzNotLike(String value) {
addCriterion("jmeter_clazz not like", value, "jmeterClazz");
return (Criteria) this;
}
public Criteria andJmeterClazzIn(List<String> values) {
addCriterion("jmeter_clazz in", values, "jmeterClazz");
return (Criteria) this;
}
public Criteria andJmeterClazzNotIn(List<String> values) {
addCriterion("jmeter_clazz not in", values, "jmeterClazz");
return (Criteria) this;
}
public Criteria andJmeterClazzBetween(String value1, String value2) {
addCriterion("jmeter_clazz between", value1, value2, "jmeterClazz");
return (Criteria) this;
}
public Criteria andJmeterClazzNotBetween(String value1, String value2) {
addCriterion("jmeter_clazz not between", value1, value2, "jmeterClazz");
return (Criteria) this;
}
public Criteria andSourcePathIsNull() {
addCriterion("source_path is null");
return (Criteria) this;
@ -923,6 +923,136 @@ public class PluginExample {
addCriterion("create_user_id not between", value1, value2, "createUserId");
return (Criteria) this;
}
public Criteria andXpackIsNull() {
addCriterion("xpack is null");
return (Criteria) this;
}
public Criteria andXpackIsNotNull() {
addCriterion("xpack is not null");
return (Criteria) this;
}
public Criteria andXpackEqualTo(Boolean value) {
addCriterion("xpack =", value, "xpack");
return (Criteria) this;
}
public Criteria andXpackNotEqualTo(Boolean value) {
addCriterion("xpack <>", value, "xpack");
return (Criteria) this;
}
public Criteria andXpackGreaterThan(Boolean value) {
addCriterion("xpack >", value, "xpack");
return (Criteria) this;
}
public Criteria andXpackGreaterThanOrEqualTo(Boolean value) {
addCriterion("xpack >=", value, "xpack");
return (Criteria) this;
}
public Criteria andXpackLessThan(Boolean value) {
addCriterion("xpack <", value, "xpack");
return (Criteria) this;
}
public Criteria andXpackLessThanOrEqualTo(Boolean value) {
addCriterion("xpack <=", value, "xpack");
return (Criteria) this;
}
public Criteria andXpackIn(List<Boolean> values) {
addCriterion("xpack in", values, "xpack");
return (Criteria) this;
}
public Criteria andXpackNotIn(List<Boolean> values) {
addCriterion("xpack not in", values, "xpack");
return (Criteria) this;
}
public Criteria andXpackBetween(Boolean value1, Boolean value2) {
addCriterion("xpack between", value1, value2, "xpack");
return (Criteria) this;
}
public Criteria andXpackNotBetween(Boolean value1, Boolean value2) {
addCriterion("xpack not between", value1, value2, "xpack");
return (Criteria) this;
}
public Criteria andScenarioIsNull() {
addCriterion("scenario is null");
return (Criteria) this;
}
public Criteria andScenarioIsNotNull() {
addCriterion("scenario is not null");
return (Criteria) this;
}
public Criteria andScenarioEqualTo(String value) {
addCriterion("scenario =", value, "scenario");
return (Criteria) this;
}
public Criteria andScenarioNotEqualTo(String value) {
addCriterion("scenario <>", value, "scenario");
return (Criteria) this;
}
public Criteria andScenarioGreaterThan(String value) {
addCriterion("scenario >", value, "scenario");
return (Criteria) this;
}
public Criteria andScenarioGreaterThanOrEqualTo(String value) {
addCriterion("scenario >=", value, "scenario");
return (Criteria) this;
}
public Criteria andScenarioLessThan(String value) {
addCriterion("scenario <", value, "scenario");
return (Criteria) this;
}
public Criteria andScenarioLessThanOrEqualTo(String value) {
addCriterion("scenario <=", value, "scenario");
return (Criteria) this;
}
public Criteria andScenarioLike(String value) {
addCriterion("scenario like", value, "scenario");
return (Criteria) this;
}
public Criteria andScenarioNotLike(String value) {
addCriterion("scenario not like", value, "scenario");
return (Criteria) this;
}
public Criteria andScenarioIn(List<String> values) {
addCriterion("scenario in", values, "scenario");
return (Criteria) this;
}
public Criteria andScenarioNotIn(List<String> values) {
addCriterion("scenario not in", values, "scenario");
return (Criteria) this;
}
public Criteria andScenarioBetween(String value1, String value2) {
addCriterion("scenario between", value1, value2, "scenario");
return (Criteria) this;
}
public Criteria andScenarioNotBetween(String value1, String value2) {
addCriterion("scenario not between", value1, value2, "scenario");
return (Criteria) this;
}
}
public static class Criteria extends GeneratedCriteria {
@ -1017,4 +1147,4 @@ public class PluginExample {
this(condition, value, secondValue, null);
}
}
}
}

View File

@ -1,11 +1,10 @@
package io.metersphere.base.domain;
import java.io.Serializable;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.io.Serializable;
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@ -15,4 +14,4 @@ public class PluginWithBLOBs extends Plugin implements Serializable {
private String formScript;
private static final long serialVersionUID = 1L;
}
}

View File

@ -105,10 +105,21 @@
:default-open="defaultOpen"
:data="data" :disabled="disabled"/>
<el-input class="custom-with"
@input="handleChange"
<el-input v-else-if="data.type === 'password'"
v-model="data[prop]"
class="custom-with"
auto-complete="new-password"
show-password
:disabled="disabled"
@input="handleChange"/>
<el-input v-else
v-model="data[prop]"
class="custom-with"
maxlength="450"
show-word-limit
:disabled="disabled"
v-else v-model="data[prop]" maxlength="450" show-word-limit/>
@input="handleChange"/>
</span>

View File

@ -1256,6 +1256,7 @@ const message = {
jar_file: "Jar Package",
jar_manage: "JAR package management",
delete_tip: "The deletion takes effect after the service is restarted",
delete_confirm: "Confirm to delete the plugin",
file_exist: "The name already exists in the project",
upload_limit_size: "Upload file size cannot exceed 30MB!",
upload_limit_size_warn: "Upload file size cannot exceed {0} MB!",

View File

@ -1266,6 +1266,7 @@ const message = {
jar_file: "jar包",
jar_manage: "JAR包管理",
delete_tip: "删除需重启服务后生效",
delete_confirm: "确认删除插件",
file_exist: "该项目下已存在该jar包",
upload_limit_size: "上传文件大小不能超过 30MB!",
upload_limit_size_warn: "上传文件大小不能超过 {0} MB!",

View File

@ -1264,6 +1264,7 @@ const message = {
jar_manage: "JAR包管理",
delete_tip: "刪除需重啟服務後生效",
file_exist: "該項目下已存在該jar包",
delete_confirm: "確認刪除插件",
upload_limit_size: "上傳文件大小不能超過 30MB!",
upload_limit_size_warn: "上傳文件大小不能超過 {0} MB!",
upload_limit: "上傳文件大小不能超過",

View File

@ -3,9 +3,8 @@ package io.metersphere.base.mapper;
import io.metersphere.base.domain.Plugin;
import io.metersphere.base.domain.PluginExample;
import io.metersphere.base.domain.PluginWithBLOBs;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import org.apache.ibatis.annotations.Param;
public interface PluginMapper {
long countByExample(PluginExample example);
@ -35,4 +34,4 @@ public interface PluginMapper {
int updateByPrimaryKeyWithBLOBs(PluginWithBLOBs record);
int updateByPrimaryKey(Plugin record);
}
}

View File

@ -6,14 +6,16 @@
<result column="name" jdbcType="VARCHAR" property="name" />
<result column="plugin_id" jdbcType="VARCHAR" property="pluginId" />
<result column="script_id" jdbcType="VARCHAR" property="scriptId" />
<result column="jmeter_clazz" jdbcType="VARCHAR" property="jmeterClazz" />
<result column="clazz_name" jdbcType="VARCHAR" property="clazzName" />
<result column="jmeter_clazz" jdbcType="VARCHAR" property="jmeterClazz" />
<result column="source_path" jdbcType="VARCHAR" property="sourcePath" />
<result column="source_name" jdbcType="VARCHAR" property="sourceName" />
<result column="exec_entry" jdbcType="VARCHAR" property="execEntry" />
<result column="create_time" jdbcType="BIGINT" property="createTime" />
<result column="update_time" jdbcType="BIGINT" property="updateTime" />
<result column="create_user_id" jdbcType="VARCHAR" property="createUserId" />
<result column="xpack" jdbcType="BIT" property="xpack" />
<result column="scenario" jdbcType="VARCHAR" property="scenario" />
</resultMap>
<resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="io.metersphere.base.domain.PluginWithBLOBs">
<result column="form_option" jdbcType="LONGVARCHAR" property="formOption" />
@ -78,8 +80,8 @@
</where>
</sql>
<sql id="Base_Column_List">
id, `name`, plugin_id, script_id, jmeter_clazz, clazz_name, source_path, source_name,
exec_entry, create_time, update_time, create_user_id
id, `name`, plugin_id, script_id, clazz_name, jmeter_clazz, source_path, source_name,
exec_entry, create_time, update_time, create_user_id, xpack, scenario
</sql>
<sql id="Blob_Column_List">
form_option, form_script
@ -115,7 +117,7 @@
</if>
</select>
<select id="selectByPrimaryKey" parameterType="java.lang.String" resultMap="ResultMapWithBLOBs">
select
select
<include refid="Base_Column_List" />
,
<include refid="Blob_Column_List" />
@ -133,16 +135,18 @@
</if>
</delete>
<insert id="insert" parameterType="io.metersphere.base.domain.PluginWithBLOBs">
insert into plugin (id, `name`, plugin_id,
script_id, jmeter_clazz, clazz_name,
source_path, source_name, exec_entry,
create_time, update_time, create_user_id,
form_option, form_script)
values (#{id,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{pluginId,jdbcType=VARCHAR},
#{scriptId,jdbcType=VARCHAR}, #{jmeterClazz,jdbcType=VARCHAR}, #{clazzName,jdbcType=VARCHAR},
#{sourcePath,jdbcType=VARCHAR}, #{sourceName,jdbcType=VARCHAR}, #{execEntry,jdbcType=VARCHAR},
#{createTime,jdbcType=BIGINT}, #{updateTime,jdbcType=BIGINT}, #{createUserId,jdbcType=VARCHAR},
#{formOption,jdbcType=LONGVARCHAR}, #{formScript,jdbcType=LONGVARCHAR})
insert into plugin (id, `name`, plugin_id,
script_id, clazz_name, jmeter_clazz,
source_path, source_name, exec_entry,
create_time, update_time, create_user_id,
xpack, scenario, form_option,
form_script)
values (#{id,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{pluginId,jdbcType=VARCHAR},
#{scriptId,jdbcType=VARCHAR}, #{clazzName,jdbcType=VARCHAR}, #{jmeterClazz,jdbcType=VARCHAR},
#{sourcePath,jdbcType=VARCHAR}, #{sourceName,jdbcType=VARCHAR}, #{execEntry,jdbcType=VARCHAR},
#{createTime,jdbcType=BIGINT}, #{updateTime,jdbcType=BIGINT}, #{createUserId,jdbcType=VARCHAR},
#{xpack,jdbcType=BIT}, #{scenario,jdbcType=VARCHAR}, #{formOption,jdbcType=LONGVARCHAR},
#{formScript,jdbcType=LONGVARCHAR})
</insert>
<insert id="insertSelective" parameterType="io.metersphere.base.domain.PluginWithBLOBs">
insert into plugin
@ -159,12 +163,12 @@
<if test="scriptId != null">
script_id,
</if>
<if test="jmeterClazz != null">
jmeter_clazz,
</if>
<if test="clazzName != null">
clazz_name,
</if>
<if test="jmeterClazz != null">
jmeter_clazz,
</if>
<if test="sourcePath != null">
source_path,
</if>
@ -183,6 +187,12 @@
<if test="createUserId != null">
create_user_id,
</if>
<if test="xpack != null">
xpack,
</if>
<if test="scenario != null">
scenario,
</if>
<if test="formOption != null">
form_option,
</if>
@ -203,12 +213,12 @@
<if test="scriptId != null">
#{scriptId,jdbcType=VARCHAR},
</if>
<if test="jmeterClazz != null">
#{jmeterClazz,jdbcType=VARCHAR},
</if>
<if test="clazzName != null">
#{clazzName,jdbcType=VARCHAR},
</if>
<if test="jmeterClazz != null">
#{jmeterClazz,jdbcType=VARCHAR},
</if>
<if test="sourcePath != null">
#{sourcePath,jdbcType=VARCHAR},
</if>
@ -227,6 +237,12 @@
<if test="createUserId != null">
#{createUserId,jdbcType=VARCHAR},
</if>
<if test="xpack != null">
#{xpack,jdbcType=BIT},
</if>
<if test="scenario != null">
#{scenario,jdbcType=VARCHAR},
</if>
<if test="formOption != null">
#{formOption,jdbcType=LONGVARCHAR},
</if>
@ -256,12 +272,12 @@
<if test="record.scriptId != null">
script_id = #{record.scriptId,jdbcType=VARCHAR},
</if>
<if test="record.jmeterClazz != null">
jmeter_clazz = #{record.jmeterClazz,jdbcType=VARCHAR},
</if>
<if test="record.clazzName != null">
clazz_name = #{record.clazzName,jdbcType=VARCHAR},
</if>
<if test="record.jmeterClazz != null">
jmeter_clazz = #{record.jmeterClazz,jdbcType=VARCHAR},
</if>
<if test="record.sourcePath != null">
source_path = #{record.sourcePath,jdbcType=VARCHAR},
</if>
@ -280,6 +296,12 @@
<if test="record.createUserId != null">
create_user_id = #{record.createUserId,jdbcType=VARCHAR},
</if>
<if test="record.xpack != null">
xpack = #{record.xpack,jdbcType=BIT},
</if>
<if test="record.scenario != null">
scenario = #{record.scenario,jdbcType=VARCHAR},
</if>
<if test="record.formOption != null">
form_option = #{record.formOption,jdbcType=LONGVARCHAR},
</if>
@ -297,14 +319,16 @@
`name` = #{record.name,jdbcType=VARCHAR},
plugin_id = #{record.pluginId,jdbcType=VARCHAR},
script_id = #{record.scriptId,jdbcType=VARCHAR},
jmeter_clazz = #{record.jmeterClazz,jdbcType=VARCHAR},
clazz_name = #{record.clazzName,jdbcType=VARCHAR},
jmeter_clazz = #{record.jmeterClazz,jdbcType=VARCHAR},
source_path = #{record.sourcePath,jdbcType=VARCHAR},
source_name = #{record.sourceName,jdbcType=VARCHAR},
exec_entry = #{record.execEntry,jdbcType=VARCHAR},
create_time = #{record.createTime,jdbcType=BIGINT},
update_time = #{record.updateTime,jdbcType=BIGINT},
create_user_id = #{record.createUserId,jdbcType=VARCHAR},
xpack = #{record.xpack,jdbcType=BIT},
scenario = #{record.scenario,jdbcType=VARCHAR},
form_option = #{record.formOption,jdbcType=LONGVARCHAR},
form_script = #{record.formScript,jdbcType=LONGVARCHAR}
<if test="_parameter != null">
@ -317,14 +341,16 @@
`name` = #{record.name,jdbcType=VARCHAR},
plugin_id = #{record.pluginId,jdbcType=VARCHAR},
script_id = #{record.scriptId,jdbcType=VARCHAR},
jmeter_clazz = #{record.jmeterClazz,jdbcType=VARCHAR},
clazz_name = #{record.clazzName,jdbcType=VARCHAR},
jmeter_clazz = #{record.jmeterClazz,jdbcType=VARCHAR},
source_path = #{record.sourcePath,jdbcType=VARCHAR},
source_name = #{record.sourceName,jdbcType=VARCHAR},
exec_entry = #{record.execEntry,jdbcType=VARCHAR},
create_time = #{record.createTime,jdbcType=BIGINT},
update_time = #{record.updateTime,jdbcType=BIGINT},
create_user_id = #{record.createUserId,jdbcType=VARCHAR}
create_user_id = #{record.createUserId,jdbcType=VARCHAR},
xpack = #{record.xpack,jdbcType=BIT},
scenario = #{record.scenario,jdbcType=VARCHAR}
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
</if>
@ -341,12 +367,12 @@
<if test="scriptId != null">
script_id = #{scriptId,jdbcType=VARCHAR},
</if>
<if test="jmeterClazz != null">
jmeter_clazz = #{jmeterClazz,jdbcType=VARCHAR},
</if>
<if test="clazzName != null">
clazz_name = #{clazzName,jdbcType=VARCHAR},
</if>
<if test="jmeterClazz != null">
jmeter_clazz = #{jmeterClazz,jdbcType=VARCHAR},
</if>
<if test="sourcePath != null">
source_path = #{sourcePath,jdbcType=VARCHAR},
</if>
@ -365,6 +391,12 @@
<if test="createUserId != null">
create_user_id = #{createUserId,jdbcType=VARCHAR},
</if>
<if test="xpack != null">
xpack = #{xpack,jdbcType=BIT},
</if>
<if test="scenario != null">
scenario = #{scenario,jdbcType=VARCHAR},
</if>
<if test="formOption != null">
form_option = #{formOption,jdbcType=LONGVARCHAR},
</if>
@ -379,14 +411,16 @@
set `name` = #{name,jdbcType=VARCHAR},
plugin_id = #{pluginId,jdbcType=VARCHAR},
script_id = #{scriptId,jdbcType=VARCHAR},
jmeter_clazz = #{jmeterClazz,jdbcType=VARCHAR},
clazz_name = #{clazzName,jdbcType=VARCHAR},
jmeter_clazz = #{jmeterClazz,jdbcType=VARCHAR},
source_path = #{sourcePath,jdbcType=VARCHAR},
source_name = #{sourceName,jdbcType=VARCHAR},
exec_entry = #{execEntry,jdbcType=VARCHAR},
create_time = #{createTime,jdbcType=BIGINT},
update_time = #{updateTime,jdbcType=BIGINT},
create_user_id = #{createUserId,jdbcType=VARCHAR},
xpack = #{xpack,jdbcType=BIT},
scenario = #{scenario,jdbcType=VARCHAR},
form_option = #{formOption,jdbcType=LONGVARCHAR},
form_script = #{formScript,jdbcType=LONGVARCHAR}
where id = #{id,jdbcType=VARCHAR}
@ -396,14 +430,16 @@
set `name` = #{name,jdbcType=VARCHAR},
plugin_id = #{pluginId,jdbcType=VARCHAR},
script_id = #{scriptId,jdbcType=VARCHAR},
jmeter_clazz = #{jmeterClazz,jdbcType=VARCHAR},
clazz_name = #{clazzName,jdbcType=VARCHAR},
jmeter_clazz = #{jmeterClazz,jdbcType=VARCHAR},
source_path = #{sourcePath,jdbcType=VARCHAR},
source_name = #{sourceName,jdbcType=VARCHAR},
exec_entry = #{execEntry,jdbcType=VARCHAR},
create_time = #{createTime,jdbcType=BIGINT},
update_time = #{updateTime,jdbcType=BIGINT},
create_user_id = #{createUserId,jdbcType=VARCHAR}
create_user_id = #{createUserId,jdbcType=VARCHAR},
xpack = #{xpack,jdbcType=BIT},
scenario = #{scenario,jdbcType=VARCHAR}
where id = #{id,jdbcType=VARCHAR}
</update>
</mapper>
</mapper>

View File

@ -0,0 +1,5 @@
package io.metersphere.commons.constants;
public enum PluginScenario {
api, platform
}

View File

@ -8,6 +8,7 @@ public class ShiroUtils {
filterChainDefinitionMap.put("/resource/md/get/**", "anon");
filterChainDefinitionMap.put("/resource/ui/get/**", "anon");
filterChainDefinitionMap.put("/platform/plugin/resource/**", "anon");
filterChainDefinitionMap.put("/attachment/preview/**", "anon");
filterChainDefinitionMap.put("/*.worker.js", "anon");
filterChainDefinitionMap.put("/*.html", "anon");

View File

@ -5,7 +5,9 @@ import io.metersphere.config.MinioProperties;
import io.metersphere.dto.FileInfoDTO;
import io.metersphere.metadata.vo.FileRequest;
import io.minio.*;
import io.minio.messages.Item;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
@ -56,12 +58,55 @@ public class MinIOFileRepository implements FileRepository {
@Override
public void delete(FileRequest request) throws Exception {
String bucket = minioProperties.getBucket();
String fileName = request.getProjectId() + "/" + request.getFileName();
String fileName = request.getProjectId();
if (StringUtils.isNotBlank(request.getFileName())) {
fileName += "/" + request.getFileName();
}
if (fileName.endsWith("/")) {
// 删除文件夹
removeObjects(bucket, fileName);
} else {
// 删除单个文件
removeObject(bucket, fileName);
}
}
private boolean removeObject(String bucketName, String objectName) throws Exception {
minioClient.removeObject(RemoveObjectArgs.builder()
.bucket(bucket) // 存储桶
.object(fileName) // 文件名
.bucket(bucketName) // 存储桶
.object(objectName) // 文件名
.build());
return true;
}
public void removeObjects(String bucketName, String objectName) throws Exception {
List<String> objects = listObjects(bucketName, objectName);
for (String object : objects) {
removeObject(bucketName, object);
}
}
/**
* 递归获取某路径下的所有文件
*/
public List<String> listObjects(String bucketName, String objectName) throws Exception {
List<String> list = new ArrayList<>(12);
Iterable<Result<Item>> results = minioClient.listObjects(
ListObjectsArgs.builder()
.bucket(bucketName)
.prefix(objectName)
.build());
for (Result<Item> result : results) {
Item item = result.get();
if (item.isDir()) {
List<String> files = listObjects(bucketName, item.objectName());
list.addAll(files);
} else {
list.add(item.objectName());
}
}
return list;
}
@Override

View File

@ -0,0 +1,23 @@
package io.metersphere.service;
import io.metersphere.base.domain.PluginExample;
import io.metersphere.base.domain.PluginWithBLOBs;
import io.metersphere.base.mapper.PluginMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.List;
@Service
@Transactional(rollbackFor = Exception.class)
public class BasePluginService {
@Resource
private PluginMapper pluginMapper;
public List<PluginWithBLOBs> getPlugins(String scenario) {
PluginExample example = new PluginExample();
example.createCriteria().andScenarioEqualTo(scenario);
return pluginMapper.selectByExampleWithBLOBs(example);
}
}

View File

@ -23,6 +23,7 @@
<spring-cloud.version>2021.0.5</spring-cloud.version>
<spring-security.version>5.7.5</spring-security.version>
<dubbo.version>2.7.15</dubbo.version>
<platform-plugin-sdk.version>main</platform-plugin-sdk.version>
<flyway.version>7.15.0</flyway.version>
<shiro.version>1.10.0</shiro.version>
<mssql-jdbc.version>7.4.1.jre8</mssql-jdbc.version>

View File

@ -22,6 +22,11 @@
<artifactId>xpack-interface</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<artifactId>metersphere-platform-plugin-sdk</artifactId>
<groupId>io.metersphere</groupId>
<version>${platform-plugin-sdk.version}</version>
</dependency>
</dependencies>
<build>

View File

@ -1,38 +0,0 @@
package io.metersphere.base.mapper;
import io.metersphere.base.domain.Plugin;
import io.metersphere.base.domain.PluginExample;
import io.metersphere.base.domain.PluginWithBLOBs;
import org.apache.ibatis.annotations.Param;
import java.util.List;
public interface PluginMapper {
long countByExample(PluginExample example);
int deleteByExample(PluginExample example);
int deleteByPrimaryKey(String id);
int insert(PluginWithBLOBs record);
int insertSelective(PluginWithBLOBs record);
List<PluginWithBLOBs> selectByExampleWithBLOBs(PluginExample example);
List<Plugin> selectByExample(PluginExample example);
PluginWithBLOBs selectByPrimaryKey(String id);
int updateByExampleSelective(@Param("record") PluginWithBLOBs record, @Param("example") PluginExample example);
int updateByExampleWithBLOBs(@Param("record") PluginWithBLOBs record, @Param("example") PluginExample example);
int updateByExample(@Param("record") Plugin record, @Param("example") PluginExample example);
int updateByPrimaryKeySelective(PluginWithBLOBs record);
int updateByPrimaryKeyWithBLOBs(PluginWithBLOBs record);
int updateByPrimaryKey(Plugin record);
}

View File

@ -0,0 +1,28 @@
package io.metersphere.controller;
import io.metersphere.service.PlatformPluginService;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
@RestController
@RequestMapping(value = "/platform/plugin")
public class PlatformPluginController {
@Resource
private PlatformPluginService platformPluginService;
@GetMapping("/integration/info")
public Object getIntegrationInfo() {
return platformPluginService.getIntegrationInfo();
}
@GetMapping("/resource/{pluginId}")
public void getPluginResource(@PathVariable("pluginId") String pluginId, @RequestParam("fileName") String fileName, HttpServletResponse response) {
platformPluginService.getPluginResource(pluginId, fileName, response);
}
}

View File

@ -19,12 +19,12 @@ public class PluginController {
@Resource
private PluginService pluginService;
@PostMapping("/add")
public String create(@RequestPart(value = "file", required = false) MultipartFile file) {
@PostMapping("/add/{scenario}")
public void create(@RequestPart(value = "file", required = false) MultipartFile file, @PathVariable String scenario) {
if (file == null) {
MSException.throwException("上传文件/执行入口为空");
}
return pluginService.editPlugin(file);
pluginService.addPlugin(file, scenario);
}
@GetMapping("/list")
@ -37,14 +37,13 @@ public class PluginController {
return pluginService.get(id);
}
@GetMapping("/delete/{id}")
public String delete(@PathVariable String id) {
return pluginService.delete(id);
@GetMapping("/delete/{scenario}/{id}")
public void delete(@PathVariable String scenario, @PathVariable String id) {
pluginService.delete(scenario, id);
}
@PostMapping("/custom/method")
public Object customMethod(@RequestBody PluginRequest request) {
return pluginService.customMethod(request);
}
}

View File

@ -0,0 +1,20 @@
package io.metersphere.listener;
import io.metersphere.service.PlatformPluginService;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@Component
public class InitListener implements ApplicationRunner {
@Resource
private PlatformPluginService platformPluginService;
@Override
public void run(ApplicationArguments applicationArguments) throws Exception {
platformPluginService.loadPlatFormPlugins();
}
}

View File

@ -0,0 +1,157 @@
package io.metersphere.service;
import io.metersphere.base.domain.Plugin;
import io.metersphere.base.domain.PluginExample;
import io.metersphere.base.domain.PluginWithBLOBs;
import io.metersphere.base.mapper.PluginMapper;
import io.metersphere.commons.constants.PluginScenario;
import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.BeanUtils;
import io.metersphere.commons.utils.FileUtils;
import io.metersphere.commons.utils.LogUtil;
import io.metersphere.commons.utils.SessionUtils;
import io.metersphere.dto.PluginResourceDTO;
import io.metersphere.plugin.core.ui.PluginResource;
import io.metersphere.utils.CommonUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.UUID;
@Service
@Transactional(rollbackFor = Exception.class)
public class ApiPluginService {
@Resource
private PluginMapper pluginMapper;
public List<PluginWithBLOBs> addApiPlugin(MultipartFile file) {
String id = UUID.randomUUID().toString();
String path = FileUtils.create(id, file);
List<PluginWithBLOBs> addPlugins = new ArrayList<>();
if (StringUtils.isNotEmpty(path)) {
List<PluginResourceDTO> resources = this.getMethod(path, file.getOriginalFilename());
if (CollectionUtils.isNotEmpty(resources)) {
for (PluginResourceDTO resource : resources) {
PluginExample example = new PluginExample();
example.createCriteria().andPluginIdEqualTo(resource.getPluginId());
List<Plugin> plugins = pluginMapper.selectByExample(example);
if (CollectionUtils.isNotEmpty(plugins)) {
String delPath = plugins.get(0).getSourcePath();
FileUtils.deleteFile(delPath);
pluginMapper.deleteByExample(example);
}
this.create(resource, path, file.getOriginalFilename(), addPlugins);
}
}
}
return addPlugins;
}
private boolean loadJar(String jarPath) {
try {
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
try {
File file = new File(jarPath);
if (!file.exists()) {
return false;
}
Method method = classLoader.getClass().getDeclaredMethod("addURL", URL.class);
method.setAccessible(true);
method.invoke(classLoader, file.toURI().toURL());
} catch (NoSuchMethodException e) {
Method method = classLoader.getClass()
.getDeclaredMethod("appendToClassPathForInstrumentation", String.class);
method.setAccessible(true);
method.invoke(classLoader, jarPath);
}
return true;
} catch (Exception e) {
LogUtil.error(e);
}
return false;
}
private List<PluginResourceDTO> getMethod(String path, String fileName) {
List<PluginResourceDTO> resources = new LinkedList<>();
this.loadJar(path);
List<Class<?>> classes = CommonUtil.getSubClass(fileName);
try {
for (Class<?> aClass : classes) {
Object instance = aClass.newInstance();
Object pluginObj = aClass.getDeclaredMethod("init").invoke(instance);
if (pluginObj != null) {
PluginResourceDTO pluginResourceDTO = new PluginResourceDTO();
BeanUtils.copyBean(pluginResourceDTO, (PluginResource) pluginObj);
pluginResourceDTO.setEntry(aClass.getName());
resources.add(pluginResourceDTO);
}
}
} catch (Exception e) {
LogUtil.error("初始化脚本异常:" + e.getMessage());
MSException.throwException("调用插件初始化脚本失败");
}
return resources;
}
private void create(PluginResourceDTO resource, String path, String name, List<PluginWithBLOBs> addPlugins) {
resource.getUiScripts().forEach(item -> {
PluginWithBLOBs plugin = new PluginWithBLOBs();
plugin.setName(item.getName());
plugin.setPluginId(resource.getPluginId());
plugin.setScriptId(item.getId());
plugin.setSourcePath(path);
plugin.setFormOption(item.getFormOption());
plugin.setFormScript(item.getFormScript());
plugin.setClazzName(item.getClazzName());
plugin.setSourceName(name);
plugin.setJmeterClazz(item.getJmeterClazz());
plugin.setExecEntry(resource.getEntry());
plugin.setCreateUserId(SessionUtils.getUserId());
plugin.setScenario(PluginScenario.api.name());
addPlugins.add(plugin);
});
}
public boolean isXpack(Plugin item) {
try {
Class<?> clazz = Class.forName(item.getExecEntry());
Object instance = clazz.newInstance();
return isXpack(Class.forName(item.getExecEntry()), instance);
} catch (Exception e) {
LogUtil.error(e.getMessage());
}
return false;
}
private boolean isXpack(Class<?> aClass, Object instance) {
try {
Object verify = aClass.getDeclaredMethod("xpack").invoke(instance);
return (Boolean) verify;
} catch (Exception e) {
return false;
}
}
public void delete(String id) {
//通过pluginId判断是否还有其他脚本无则清理加载的jar包
PluginExample example = new PluginExample();
example.createCriteria().andPluginIdEqualTo(id);
List<Plugin> list = pluginMapper.selectByExample(example);
if (CollectionUtils.isNotEmpty(list)) {
FileUtils.deleteFile(list.get(0).getSourcePath());
pluginMapper.deleteByExample(example);
}
}
}

View File

@ -0,0 +1,121 @@
package io.metersphere.service;
import im.metersphere.loader.PluginManager;
import io.metersphere.api.PluginMetaInfo;
import io.metersphere.base.domain.PluginWithBLOBs;
import io.metersphere.base.mapper.PluginMapper;
import io.metersphere.commons.constants.PluginScenario;
import io.metersphere.commons.utils.JSON;
import io.metersphere.commons.utils.LogUtil;
import io.metersphere.commons.utils.SessionUtils;
import io.metersphere.utils.PluginManagerUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
@Service
@Transactional(rollbackFor = Exception.class)
public class PlatformPluginService {
@Resource
private BasePluginService basePluginService;
@Resource
private PluginMapper pluginMapper;
private PluginManager pluginManager;
public PluginWithBLOBs addPlatformPlugin(MultipartFile file) {
if (pluginManager != null) {
pluginManager = new PluginManager();
}
String id = UUID.randomUUID().toString();
PluginManagerUtil.loadPlugin(id, pluginManager, file);
PluginMetaInfo pluginMetaInfo = pluginManager.getImplInstance(id, PluginMetaInfo.class);
Map map = JSON.parseMap(pluginMetaInfo.getFrontendMetaData());
map.put("id", id);
map.put("key", pluginMetaInfo.getKey());
PluginWithBLOBs plugin = new PluginWithBLOBs();
plugin.setId(id);
plugin.setName(file.getOriginalFilename());
plugin.setPluginId(pluginMetaInfo.getKey() + "-" + pluginMetaInfo.getVersion());
plugin.setScriptId(plugin.getPluginId());
plugin.setSourcePath("");
// plugin.setFormOption(item.getFormOption());
plugin.setFormScript(JSON.toJSONString(map));
plugin.setClazzName("");
plugin.setSourceName(file.getOriginalFilename());
plugin.setJmeterClazz("");
plugin.setExecEntry("");
plugin.setCreateUserId(SessionUtils.getUserId());
plugin.setXpack(pluginMetaInfo.isXpack());
plugin.setScenario(PluginScenario.platform.name());
return plugin;
}
/**
* 查询所有平台插件并加载
*/
public void loadPlatFormPlugins() {
pluginManager = new PluginManager();
List<PluginWithBLOBs> plugins = basePluginService.getPlugins(PluginScenario.platform.name());
PluginManagerUtil.loadPlugins(pluginManager, plugins);
}
public void getPluginResource(String pluginId, String name, HttpServletResponse response) {
InputStream inputStream = pluginManager.getClassLoader(pluginId)
.getResourceAsStream(name);
getImage(inputStream, response);
}
public Object getIntegrationInfo() {
List<PluginWithBLOBs> plugins = basePluginService.getPlugins(PluginScenario.platform.name());
List<Map> configs = new ArrayList<>();
plugins.forEach(item ->{
Map metaData = JSON.parseMap(item.getFormScript());
Map serviceIntegration = (Map) metaData.get("serviceIntegration");
serviceIntegration.put("id", metaData.get("id"));
serviceIntegration.put("key", metaData.get("key"));
configs.add(serviceIntegration);
});
return configs;
}
public void getImage(InputStream in, HttpServletResponse response) {
response.setContentType("image/png");
try(OutputStream out = response.getOutputStream()) {
out.write(in.readAllBytes());
out.flush();
} catch (Exception e) {
LogUtil.error(e);
} finally {
try {
in.close();
} catch (IOException e) {
LogUtil.error(e);
}
}
}
public void delete(String id) {
pluginMapper.deleteByPrimaryKey(id);
try {
pluginManager.getClassLoader(id).getStorageStrategy().delete();
pluginManager.deletePlugin(id);
} catch (IOException e) {
LogUtil.error(e);
}
}
}

View File

@ -4,16 +4,12 @@ import io.metersphere.base.domain.Plugin;
import io.metersphere.base.domain.PluginExample;
import io.metersphere.base.domain.PluginWithBLOBs;
import io.metersphere.base.mapper.PluginMapper;
import io.metersphere.commons.constants.PluginScenario;
import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.BeanUtils;
import io.metersphere.commons.utils.FileUtils;
import io.metersphere.commons.utils.LogUtil;
import io.metersphere.commons.utils.SessionUtils;
import io.metersphere.dto.PluginResourceDTO;
import io.metersphere.plugin.core.ui.PluginResource;
import io.metersphere.request.PluginDTO;
import io.metersphere.request.PluginRequest;
import io.metersphere.utils.CommonUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
@ -21,175 +17,57 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.*;
import java.util.stream.Collectors;
@Service
@Transactional(rollbackFor = Exception.class)
public class PluginService {
@Resource
private PluginMapper pluginMapper;
@Resource
private PlatformPluginService platformPluginService;
@Resource
private ApiPluginService apiPluginService;
public String editPlugin(MultipartFile file) {
String id = UUID.randomUUID().toString();
String path = FileUtils.create(id, file);
if (StringUtils.isNotEmpty(path)) {
List<PluginResourceDTO> resources = this.getMethod(path, file.getOriginalFilename());
if (CollectionUtils.isNotEmpty(resources)) {
for (PluginResourceDTO resource : resources) {
PluginExample example = new PluginExample();
example.createCriteria().andPluginIdEqualTo(resource.getPluginId());
List<Plugin> plugins = pluginMapper.selectByExample(example);
if (CollectionUtils.isNotEmpty(plugins)) {
String delPath = plugins.get(0).getSourcePath();
// this.closeJar(delPath);
FileUtils.deleteFile(delPath);
pluginMapper.deleteByExample(example);
}
this.create(resource, path, file.getOriginalFilename());
}
}
}
return null;
}
private void create(PluginResourceDTO resource, String path, String name) {
resource.getUiScripts().forEach(item -> {
PluginWithBLOBs plugin = new PluginWithBLOBs();
public void addPlugin(PluginWithBLOBs plugin) {
if (StringUtils.isBlank(plugin.getId())) {
plugin.setId(UUID.randomUUID().toString());
plugin.setCreateTime(System.currentTimeMillis());
plugin.setUpdateTime(System.currentTimeMillis());
plugin.setName(item.getName());
plugin.setPluginId(resource.getPluginId());
plugin.setScriptId(item.getId());
plugin.setSourcePath(path);
plugin.setFormOption(item.getFormOption());
plugin.setFormScript(item.getFormScript());
plugin.setClazzName(item.getClazzName());
plugin.setSourceName(name);
plugin.setJmeterClazz(item.getJmeterClazz());
plugin.setExecEntry(resource.getEntry());
plugin.setCreateUserId(SessionUtils.getUserId());
pluginMapper.insert(plugin);
});
}
private boolean isXpack(Class<?> aClass, Object instance) {
try {
Object verify = aClass.getDeclaredMethod("xpack").invoke(instance);
return (Boolean) verify;
} catch (Exception e) {
return false;
}
}
private List<PluginResourceDTO> getMethod(String path, String fileName) {
List<PluginResourceDTO> resources = new LinkedList<>();
this.loadJar(path);
List<Class<?>> classes = CommonUtil.getSubClass(fileName);
try {
for (Class<?> aClass : classes) {
Object instance = aClass.newInstance();
Object pluginObj = aClass.getDeclaredMethod("init").invoke(instance);
if (pluginObj != null) {
PluginResourceDTO pluginResourceDTO = new PluginResourceDTO();
BeanUtils.copyBean(pluginResourceDTO, (PluginResource) pluginObj);
pluginResourceDTO.setEntry(aClass.getName());
resources.add(pluginResourceDTO);
}
}
} catch (Exception e) {
LogUtil.error("初始化脚本异常:" + e.getMessage());
MSException.throwException("调用插件初始化脚本失败");
}
return resources;
}
private boolean loadJar(String jarPath) {
try {
ClassLoader classLoader = ClassLoader.getSystemClassLoader();
try {
File file = new File(jarPath);
if (!file.exists()) {
return false;
}
Method method = classLoader.getClass().getDeclaredMethod("addURL", URL.class);
method.setAccessible(true);
method.invoke(classLoader, file.toURI().toURL());
} catch (NoSuchMethodException e) {
Method method = classLoader.getClass()
.getDeclaredMethod("appendToClassPathForInstrumentation", String.class);
method.setAccessible(true);
method.invoke(classLoader, jarPath);
}
return true;
} catch (Exception e) {
LogUtil.error(e);
}
return false;
}
public void loadPlugins() {
try {
PluginExample example = new PluginExample();
List<Plugin> plugins = pluginMapper.selectByExample(example);
if (CollectionUtils.isNotEmpty(plugins)) {
plugins = plugins.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(()
-> new TreeSet<>(Comparator.comparing(Plugin::getPluginId))), ArrayList::new));
if (CollectionUtils.isNotEmpty(plugins)) {
plugins.forEach(item -> {
boolean isLoad = this.loadJar(item.getSourcePath());
if (!isLoad) {
PluginExample pluginExample = new PluginExample();
pluginExample.createCriteria().andPluginIdEqualTo(item.getPluginId());
pluginMapper.deleteByExample(pluginExample);
}
});
}
}
} catch (Exception e) {
LogUtil.error(e);
}
plugin.setCreateTime(System.currentTimeMillis());
plugin.setUpdateTime(System.currentTimeMillis());
pluginMapper.insert(plugin);
}
public List<PluginDTO> list(String name) {
try {
PluginExample example = new PluginExample();
if (StringUtils.isNotBlank(name)) {
name = "%" + name + "%";
example.createCriteria().andNameLike(name);
}
List<Plugin> plugins = pluginMapper.selectByExample(example);
Map<String, Boolean> pluginMap = new HashMap<>();
List<PluginDTO> lists = new LinkedList<>();
if (CollectionUtils.isNotEmpty(plugins)) {
// 校验插件是否是企业版
plugins.forEach(item -> {
PluginDTO dto = new PluginDTO();
BeanUtils.copyBean(dto, item);
PluginExample example = new PluginExample();
if (StringUtils.isNotBlank(name)) {
name = "%" + name + "%";
example.createCriteria().andNameLike(name);
}
List<Plugin> plugins = pluginMapper.selectByExample(example);
Map<String, Boolean> pluginMap = new HashMap<>();
List<PluginDTO> lists = new LinkedList<>();
if (CollectionUtils.isNotEmpty(plugins)) {
// 校验插件是否是企业版
plugins.forEach(item -> {
PluginDTO dto = new PluginDTO();
BeanUtils.copyBean(dto, item);
if (StringUtils.equals(PluginScenario.api.name(), item.getScenario())) {
// api 插件调用
if (!pluginMap.containsKey(item.getPluginId())) {
try {
Class<?> clazz = Class.forName(item.getExecEntry());
Object instance = clazz.newInstance();
dto.setLicense(this.isXpack(Class.forName(item.getExecEntry()), instance));
} catch (Exception e) {
LogUtil.error(e.getMessage());
}
dto.setLicense(apiPluginService.isXpack(item));
} else {
dto.setLicense(pluginMap.get(item.getPluginId()));
}
lists.add(dto);
pluginMap.put(item.getPluginId(), dto.getLicense());
});
return lists;
}
} catch (Exception e) {
LogUtil.error(e);
} else {
// 平台插件加载时已经保存
dto.setLicense(item.getXpack());
}
lists.add(dto);
});
}
return null;
return lists;
}
public Plugin get(String scriptId) {
@ -202,16 +80,14 @@ public class PluginService {
return null;
}
public String delete(String id) {
//通过pluginId判断是否还有其他脚本无则清理加载的jar包
PluginExample example = new PluginExample();
example.createCriteria().andPluginIdEqualTo(id);
List<Plugin> list = pluginMapper.selectByExample(example);
if (CollectionUtils.isNotEmpty(list)) {
FileUtils.deleteFile(list.get(0).getSourcePath());
pluginMapper.deleteByExample(example);
public void delete(String scenario, String id) {
if (StringUtils.equalsIgnoreCase(scenario, PluginScenario.platform.name())) {
// 平台插件传的是 id
platformPluginService.delete(id);
} else {
// 接口传的是 pluginId
apiPluginService.delete(id);
}
return "success";
}
public Object customMethod(PluginRequest request) {
@ -229,4 +105,25 @@ public class PluginService {
PluginExample example = new PluginExample();
return pluginMapper.selectByExample(example);
}
public void addPlugin(MultipartFile file, String scenario) {
checkPluginExist(file);
if (StringUtils.equalsIgnoreCase(scenario, PluginScenario.platform.name())) {
PluginWithBLOBs plugin = platformPluginService.addPlatformPlugin(file);
addPlugin(plugin);
} else {
List<PluginWithBLOBs> plugins = apiPluginService.addApiPlugin(file);
plugins.forEach(this::addPlugin);
}
}
public void checkPluginExist(MultipartFile file) {
String filename = file.getOriginalFilename();
PluginExample example = new PluginExample();
example.createCriteria().andSourceNameEqualTo(filename);
List<Plugin> plugins = pluginMapper.selectByExample(example);
if (CollectionUtils.isNotEmpty(plugins)) {
MSException.throwException("Plugin exist!");
}
}
}

View File

@ -0,0 +1,54 @@
package io.metersphere.service.plugin;
import im.metersphere.storage.StorageStrategy;
import io.metersphere.commons.constants.StorageConstants;
import io.metersphere.commons.utils.CommonBeanFactory;
import io.metersphere.metadata.service.FileManagerService;
import io.metersphere.metadata.vo.FileRequest;
import java.io.IOException;
import java.io.InputStream;
/**
* jar包静态资源存储策略存储在 Minio
*/
public class MinioStorageStrategy implements StorageStrategy {
private FileManagerService fileManagerService;
private String pluginId;
public static final String DIR_PATH = "system/plugin";
public MinioStorageStrategy(String pluginId) {
this.pluginId = pluginId;
fileManagerService = CommonBeanFactory.getBean(FileManagerService.class);
}
@Override
public String store(String name, InputStream in) throws IOException {
FileRequest request = getFileRequest(name);
return fileManagerService.upload(in.readAllBytes(), request);
}
@Override
public InputStream get(String name) {
FileRequest request = getFileRequest(name);
return fileManagerService.downloadFileAsStream(request);
}
@Override
public void delete() throws IOException {
FileRequest request = new FileRequest();
request.setProjectId(DIR_PATH + "/" + this.pluginId + "/");
request.setStorage(StorageConstants.MINIO.name());
fileManagerService.delete(request);
}
private FileRequest getFileRequest(String name) {
FileRequest request = new FileRequest();
request.setProjectId(DIR_PATH + "/" + this.pluginId);
request.setFileName(name);
request.setStorage(StorageConstants.MINIO.name());
return request;
}
}

View File

@ -0,0 +1,55 @@
package io.metersphere.utils;
import im.metersphere.loader.PluginManager;
import io.metersphere.base.domain.PluginWithBLOBs;
import io.metersphere.commons.exception.MSException;
import io.metersphere.commons.utils.LogUtil;
import io.metersphere.service.plugin.MinioStorageStrategy;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
public class PluginManagerUtil {
public static void loadPlugin(String id, PluginManager pluginManager, MultipartFile file) {
if (pluginManager == null) {
pluginManager = new PluginManager();
}
MinioStorageStrategy minioStorageStrategy = new MinioStorageStrategy(id);
try {
// 上传到 sso
minioStorageStrategy.store(file.getOriginalFilename(), file.getInputStream());
} catch (IOException e) {
LogUtil.error("上传 jar 包失败: ", e);
MSException.throwException("上传 jar 包失败: " + e.getMessage());
}
// 加载 jar
try {
pluginManager.loadJar(id, file.getInputStream(), minioStorageStrategy);
} catch (IOException e) {
LogUtil.error("加载jar包失败: ", e);
MSException.throwException("加载jar包失败: " + e.getMessage());
}
}
/**
* 加载插件
*/
public static void loadPlugins(PluginManager pluginManager, List<PluginWithBLOBs> plugins) {
plugins.forEach(plugin -> {
String id = plugin.getId();
MinioStorageStrategy minioStorageStrategy = new MinioStorageStrategy(id);
InputStream inputStream = minioStorageStrategy.get(plugin.getSourceName());
try {
pluginManager.loadJar(id, inputStream, minioStorageStrategy);
} catch (IOException e) {
LogUtil.error("初始化插件失败:", e);
}
});
}
}

View File

@ -0,0 +1,6 @@
import {post, get} from "metersphere-frontend/src/plugins/request";
const BASE_URL = "/platform/plugin/";
export function getIntegrationInfo() {
return get(BASE_URL + 'integration/info');
}

View File

@ -8,22 +8,23 @@ export function getPluginPageByName(name) {
return get(`/plugin/list?name=${name}`);
}
export function delPluginById(pluginId) {
return get(`/plugin/delete/${pluginId}`);
export function delPluginById(scenario, pluginId) {
return get(`/plugin/delete/${scenario}/${pluginId}`);
}
export function getPluginById(pluginId) {
return get(`/plugin/get/${pluginId}`);
}
export function addPlugin(file) {
export function addPlugin(scenario, file) {
let formData = new FormData();
if (file) {
formData.append("file", file);
}
let url = '/plugin/add/' + scenario;
let config = {
method: 'POST',
url: '/plugin/add',
url: url,
data: formData,
headers: {
'Content-Type': undefined

View File

@ -1,28 +1,45 @@
<template>
<el-form :model="currentConfig" :rules="rules" label-width="105px" v-loading="loading" ref="form">
<el-form
v-loading="loading"
label-width="105px"
:model="currentConfig"
:rules="rules"
ref="form">
<el-row>
<el-upload
class="jar-upload"
drag
action="#"
:http-request="upload"
:limit="1"
:beforeUpload="uploadValidate"
:on-remove="handleRemove"
:on-exceed="handleExceed"
:file-list="fileList"
ref="fileUpload">
<i class="el-icon-upload"></i>
<div class="el-upload__text" v-html="$t('load_test.upload_tips')"></div>
<div class="el-upload__tip" slot="tip">{{ $t('api_test.jar_config.upload_tip') }}</div>
</el-upload>
<el-col>
<div class="buttons">
<el-button type="primary" size="small" @click="save()">{{ $t('commons.confirm') }}</el-button>
</div>
<el-col :span="11">
<el-form-item label="使用场景">
<el-select size="small" v-model="currentConfig.scenario" clearable>
<el-option v-for="item in scenarioOptions" :key="item.id" :label="item.text" :value="item.value"/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="1">
<el-divider direction="vertical"/>
</el-col>
<el-col :span="12">
<el-upload
class="jar-upload"
drag
action="#"
:http-request="upload"
:limit="1"
:beforeUpload="uploadValidate"
:on-remove="handleRemove"
:on-exceed="handleExceed"
:file-list="fileList"
ref="fileUpload">
<i class="el-icon-upload"></i>
<div class="el-upload__text" v-html="$t('load_test.upload_tips')"></div>
<div class="el-upload__tip" slot="tip">{{ $t('api_test.jar_config.upload_tip') }}</div>
</el-upload>
</el-col>
<div class="buttons">
<el-button type="primary" size="small" @click="save()">{{ $t('commons.confirm') }}</el-button>
</div>
</el-row>
</el-form>
</template>
@ -40,7 +57,12 @@ export default {
name: '',
description: '',
fileName: '',
scenario: 'api'
},
scenarioOptions: [
{text: '接口测试', value: 'api'},
{text: '平台对接', value: "platform"},
],
rules: {
name: [
{required: true, message: this.$t('commons.input_name'), trigger: 'blur'},
@ -115,7 +137,7 @@ export default {
this.$warning(this.$t('commons.please_upload'));
return;
}
this.loading = addPlugin(this.fileList[0]).then(() => {
this.loading = addPlugin(this.currentConfig.scenario, this.fileList[0]).then(() => {
this.$success(this.$t('organization.integration.successful_operation'));
this.$emit("close");
this.fileList = [];

View File

@ -44,7 +44,7 @@
:tip="$t('commons.delete')"
icon="el-icon-delete"
type="danger"
@exec="handleDelete(scope.row.id)" v-permission="['SYSTEM_PLUGIN:DEL']"/>
@exec="handleDelete(scope.row)" v-permission="['SYSTEM_PLUGIN:DEL']"/>
</div>
<div v-else>
<ms-table-operator-button
@ -57,7 +57,7 @@
</el-table>
</el-card>
<el-dialog :title="$t('commons.import')" :visible.sync="dialogVisible" @close="close" destroy-on-close>
<el-dialog :title="$t('commons.import')" width="900px" :visible.sync="dialogVisible" @close="close" destroy-on-close>
<ms-jar-config @close="close"/>
</el-dialog>
<ms-script-view ref="scriptView"/>
@ -106,10 +106,19 @@ export default {
if (res.data) {
this.format(res.data);
this.dataMap.forEach((values, key) => {
let obj = {id: key, license: values[0].license, name: values[0].sourceName, sourceName: values[0].sourceName, pluginId: key, createUserId: values[0].createUserId, updateTime: values[0].updateTime};
obj.children = values;
this.tableData.push(obj);
})
let item = values[0];
if (item.scenario === 'api') {
let obj = {};
Object.assign(obj, item);
obj.id = key;
obj.pluginId = key;
obj.name = item.sourceName;
obj.children = values;
this.tableData.push(obj);
} else {
this.tableData.push(item);
}
});
}
})
},
@ -131,9 +140,10 @@ export default {
handleView(row) {
this.$refs.scriptView.open(row.scriptId);
},
handleDelete(id) {
operationConfirm(this, this.$t('api_test.jar_config.delete_tip'), () => {
this.loading = delPluginById(id).then(() => {
handleDelete(row) {
let tip = row.scenario === 'api' ? this.$t('api_test.jar_config.delete_tip') : this.$t('api_test.jar_config.delete_confirm');
operationConfirm(this, tip, () => {
this.loading = delPluginById(row.scenario, row.id).then(() => {
this.$success(this.$t('commons.delete_success'));
this.initPlugins();
});

View File

@ -2,13 +2,16 @@
<div class="header-title" v-loading="loading">
<div>
<div>{{ $t('organization.integration.select_defect_platform') }}</div>
<el-radio-group v-model="platform" style="margin-top: 10px" @change="change">
<el-radio-group v-model="platform" style="margin-top: 10px">
<span v-for="config in platformConfigs" :key="config.key">
<el-radio :label="config.label">
<img class="platform" :src="'/platform/plugin/resource/' + config.id + '?fileName=' + config.image"
alt="Jira"/>
</el-radio>
</span>
<el-radio label="Tapd">
<img class="platform" src="/assets/tapd.png" alt="Tapd"/>
</el-radio>
<el-radio label="Jira">
<img class="platform" src="/assets/jira.png" alt="Jira"/>
</el-radio>
<el-radio label="Zentao">
<img class="zentao_platform" src="/assets/zentao.jpg" alt="Zentao"/>
</el-radio>
@ -19,9 +22,15 @@
</div>
<tapd-setting v-if="tapdEnable" ref="tapdSetting"/>
<jira-setting v-if="jiraEnable" ref="jiraSetting"/>
<zentao-setting v-if="zentaoEnable" ref="zentaoSetting"/>
<azuredevops-setting v-if="azuredevopsEnable" ref="azureDevopsSetting"/>
<div v-for="config in platformConfigs" :key="config.key">
<platform-config
:config="config"
v-if="config.key === platform"
/>
</div>
</div>
</template>
@ -30,46 +39,43 @@ import TapdSetting from '@/business/workspace/integration/TapdSetting';
import JiraSetting from '@/business/workspace/integration/JiraSetting';
import ZentaoSetting from '@/business/workspace/integration/ZentaoSetting';
import AzuredevopsSetting from '@/business/workspace/integration/AzureDevopsSetting';
import {AZURE_DEVOPS, JIRA, TAPD, ZEN_TAO} from "metersphere-frontend/src/utils/constants";
import {AZURE_DEVOPS, TAPD, ZEN_TAO} from "metersphere-frontend/src/utils/constants";
import PlatformConfig from "@/business/workspace/integration/PlatformConfig";
import {getIntegrationInfo} from "@/api/platform-plugin";
export default {
name: "BugManagement",
components: {TapdSetting, JiraSetting, ZentaoSetting, AzuredevopsSetting},
components: {PlatformConfig, TapdSetting, JiraSetting, ZentaoSetting, AzuredevopsSetting},
data() {
return {
tapdEnable: true,
jiraEnable: false,
zentaoEnable: false,
azuredevopsEnable: false,
loading: false,
platform: TAPD
platformConfigs: [],
platform: TAPD,
}
},
methods: {
change(platform) {
if (platform === TAPD) {
this.tapdEnable = true;
this.jiraEnable = false;
this.zentaoEnable = false;
this.azuredevopsEnable = false;
} else if (platform === JIRA) {
this.tapdEnable = false;
this.jiraEnable = true;
this.zentaoEnable = false;
this.azuredevopsEnable = false;
} else if (platform === ZEN_TAO) {
this.tapdEnable = false;
this.jiraEnable = false;
this.zentaoEnable = true;
this.azuredevopsEnable = false;
} else if (platform === AZURE_DEVOPS) {
this.tapdEnable = false;
this.jiraEnable = false;
this.zentaoEnable = false;
this.azuredevopsEnable = true;
}
}
}
created() {
this.platformConfigs = [];
getIntegrationInfo()
.then((r) => {
this.platformConfigs = r.data;
});
this.platform = TAPD;
this.platformConfigs[0].key;
},
computed: {
tapdEnable() {
return this.platform === TAPD;
},
zentaoEnable() {
return this.platform === ZEN_TAO;
},
azuredevopsEnable() {
return this.platform === AZURE_DEVOPS;
},
},
methods: {}
}
</script>

View File

@ -0,0 +1,215 @@
<template>
<div>
<div style="width: 500px">
<div style="margin-top: 20px;margin-bottom: 10px">{{ $t('organization.integration.basic_auth_info') }}</div>
<el-form :model="form" ref="form" label-width="100px" size="small" :disabled="show" :rules="rules">
<el-form-item
v-for="item in config.formItems"
:key="item.name"
:label="item.i18n ? $t(item.label) : item.label"
:prop="item.name">
<custom-filed-component :form="form"
:data="item"
prop="defaultValue"/>
</el-form-item>
</el-form>
</div>
<bug-manage-btn @save="save"
@init="init"
:edit-permission="['WORKSPACE_SERVICE:READ+EDIT']"
@testConnection="testConnection"
@cancelIntegration="cancelIntegration"
@reloadPassInput="reloadPassInput"
:form="form"
:show.sync="show"
ref="bugBtn"/>
<div class="defect-tip" v-html="config.tips">
<!-- todo 处理跳转逻辑 -->
<!-- {{config.tips}}-->
<!-- <div>{{ $t('organization.integration.use_tip') }}</div>-->
<!-- <div>-->
<!-- 1. {{ $t('organization.integration.use_tip_jira') }}-->
<!-- </div>-->
<!-- <div>-->
<!-- 2. {{ $t('organization.integration.use_tip_two') }}-->
<!-- <router-link to="/setting/project/all"-->
<!-- style="margin-left: 5px;color: #551A8B; text-decoration: underline; cursor: pointer">-->
<!-- {{ $t('organization.integration.link_the_project_now') }}-->
<!-- </router-link>-->
<!-- </div>-->
<!-- <div>-->
<!-- 3. {{ $t('organization.integration.use_tip_three') }}-->
<!-- <span style="margin-left: 5px;color: #551A8B; text-decoration: underline; cursor: pointer"-->
<!-- @click="resVisible = true">-->
<!-- {{ $t('organization.integration.link_the_info_now') }}-->
<!-- </span>-->
<!-- <el-dialog :close-on-click-modal="false" width="80%"-->
<!-- :visible.sync="resVisible" destroy-on-close @close="closeDialog">-->
<!-- <ms-person-router @closeDialog="closeDialog"/>-->
<!-- </el-dialog>-->
<!-- </div>-->
</div>
</div>
</template>
<script>
import BugManageBtn from "./BugManageBtn";
import {getCurrentUser, getCurrentWorkspaceId} from "metersphere-frontend/src/utils/token";
import {JIRA} from "metersphere-frontend/src/utils/constants";
import MsInstructionsIcon from "metersphere-frontend/src/components/MsInstructionsIcon";
import MsPersonRouter from "metersphere-frontend/src/components/personal/PersonRouter";
import CustomFiledComponent from "metersphere-frontend/src/components/template/CustomFiledComponent";
import {
authServiceIntegration,
delServiceIntegration,
getServiceIntegration,
saveServiceIntegration
} from "../../../api/workspace";
export default {
name: "PlatformConfig",
components: {MsInstructionsIcon, BugManageBtn, MsPersonRouter, CustomFiledComponent},
created() {
this.init();
},
props: {
config: {
type: Object,
default() {
return {}
},
}
},
data() {
return {
show: true,
showInput: true,
resVisible: false,
form: {},
rules: {},
};
},
methods: {
init() {
let rules = {};
this.config.formItems.forEach(item => {
rules[item.name] = {
required: item.required,
message: item.i18n ? this.$t(item.message) : item.message,
trigger: ['change', 'blur']
}
});
this.rules = rules;
const {lastWorkspaceId} = getCurrentUser();
let param = {};
param.platform = JIRA;
param.workspaceId = lastWorkspaceId;
this.$parent.loading = getServiceIntegration(param).then(res => {
let data = res.data;
if (data.configuration) {
let config = JSON.parse(data.configuration);
let form = {};
Object.assign(form, config);
this.form = form;
//
this.config.formItems.forEach(item => {
item.defaultValue = this.form[item.name];
});
} else {
this.clear();
}
});
},
save() {
this.$refs['form'].validate(valid => {
if (valid) {
let config = {};
Object.assign(config, this.form);
const {lastWorkspaceId} = getCurrentUser();
let param = {};
param.workspaceId = lastWorkspaceId;
param.platform = this.config.key;
param.configuration = JSON.stringify(config);
this.$parent.loading = saveServiceIntegration(param).then(() => {
this.show = true;
this.$refs.bugBtn.showEdit = true;
this.$refs.bugBtn.showSave = false;
this.$refs.bugBtn.showCancel = false;
this.reloadPassInput();
this.init();
this.$success(this.$t('commons.save_success'));
});
} else {
return false;
}
});
},
clear() {
this.form = {};
this.$nextTick(() => {
if (this.$refs.form) {
this.$refs.form.clearValidate();
}
});
},
testConnection() {
if (this.form.account && this.form.password) {
// todo
this.$parent.loading = authServiceIntegration(getCurrentWorkspaceId(), JIRA).then(() => {
this.$success(this.$t('organization.integration.verified'));
});
} else {
this.$warning(this.$t('organization.integration.not_integrated'));
return false;
}
},
cancelIntegration() {
if (this.form.account && this.form.password) {
this.$alert(this.$t('organization.integration.cancel_confirm') + JIRA + "", '', {
confirmButtonText: this.$t('commons.confirm'),
callback: (action) => {
if (action === 'confirm') {
const {lastWorkspaceId} = getCurrentUser();
let param = {};
param.workspaceId = lastWorkspaceId;
param.platform = this.config.key;
this.$parent.loading = delServiceIntegration(param).then(() => {
this.$success(this.$t('organization.integration.successful_operation'));
this.init('');
});
}
}
});
} else {
this.$warning(this.$t('organization.integration.not_integrated'));
}
},
reloadPassInput() {
this.showInput = false;
this.$nextTick(function () {
this.showInput = true;
});
},
closeDialog() {
this.resVisible = false;
}
}
};
</script>
<style scoped>
.defect-tip {
background: #EDEDED;
border: solid #E1E1E1 1px;
margin: 10px 0;
padding: 10px;
border-radius: 3px;
}
.el-input {
width: 80%;
}
</style>