refactor: 添加变更历史源数据收集

This commit is contained in:
fit2-zhao 2023-07-10 17:28:29 +08:00 committed by fit2-zhao
parent 67bf1bc381
commit 56f2b63eb6
39 changed files with 1717 additions and 543 deletions

View File

@ -1,4 +1,4 @@
package io.metersphere.system.domain; package io.metersphere.sdk.domain;
import io.metersphere.validation.groups.Created; import io.metersphere.validation.groups.Created;
import io.metersphere.validation.groups.Updated; import io.metersphere.validation.groups.Updated;
@ -43,8 +43,8 @@ public class OperationLog implements Serializable {
@Schema(title = "操作模块/api/case/scenario/ui") @Schema(title = "操作模块/api/case/scenario/ui")
private String module; private String module;
@Schema(title = "操作详情") @Schema(title = "操作内容")
private String details; private String content;
@Schema(title = "操作路径") @Schema(title = "操作路径")
private String path; private String path;

View File

@ -0,0 +1,26 @@
package io.metersphere.sdk.domain;
import io.metersphere.validation.groups.Created;
import io.metersphere.validation.groups.Updated;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.Data;
import java.io.Serializable;
@Data
public class OperationLogBlob implements Serializable {
@Schema(title = "主键", requiredMode = Schema.RequiredMode.REQUIRED)
@NotBlank(message = "{operation_log_blob.id.not_blank}", groups = {Updated.class})
@Size(min = 1, max = 50, message = "{operation_log_blob.id.length_range}", groups = {Created.class, Updated.class})
private String id;
@Schema(title = "变更前内容")
private byte[] originalValue;
@Schema(title = "变更后内容")
private byte[] modifiedValue;
private static final long serialVersionUID = 1L;
}

View File

@ -0,0 +1,270 @@
package io.metersphere.sdk.domain;
import java.util.ArrayList;
import java.util.List;
public class OperationLogBlobExample {
protected String orderByClause;
protected boolean distinct;
protected List<Criteria> oredCriteria;
public OperationLogBlobExample() {
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 andIdIsNull() {
addCriterion("id is null");
return (Criteria) this;
}
public Criteria andIdIsNotNull() {
addCriterion("id is not null");
return (Criteria) this;
}
public Criteria andIdEqualTo(String value) {
addCriterion("id =", value, "id");
return (Criteria) this;
}
public Criteria andIdNotEqualTo(String value) {
addCriterion("id <>", value, "id");
return (Criteria) this;
}
public Criteria andIdGreaterThan(String value) {
addCriterion("id >", value, "id");
return (Criteria) this;
}
public Criteria andIdGreaterThanOrEqualTo(String value) {
addCriterion("id >=", value, "id");
return (Criteria) this;
}
public Criteria andIdLessThan(String value) {
addCriterion("id <", value, "id");
return (Criteria) this;
}
public Criteria andIdLessThanOrEqualTo(String value) {
addCriterion("id <=", value, "id");
return (Criteria) this;
}
public Criteria andIdLike(String value) {
addCriterion("id like", value, "id");
return (Criteria) this;
}
public Criteria andIdNotLike(String value) {
addCriterion("id not like", value, "id");
return (Criteria) this;
}
public Criteria andIdIn(List<String> values) {
addCriterion("id in", values, "id");
return (Criteria) this;
}
public Criteria andIdNotIn(List<String> values) {
addCriterion("id not in", values, "id");
return (Criteria) this;
}
public Criteria andIdBetween(String value1, String value2) {
addCriterion("id between", value1, value2, "id");
return (Criteria) this;
}
public Criteria andIdNotBetween(String value1, String value2) {
addCriterion("id not between", value1, value2, "id");
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);
}
}
}

View File

@ -1,4 +1,4 @@
package io.metersphere.system.domain; package io.metersphere.sdk.domain;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -654,73 +654,73 @@ public class OperationLogExample {
return (Criteria) this; return (Criteria) this;
} }
public Criteria andDetailsIsNull() { public Criteria andContentIsNull() {
addCriterion("details is null"); addCriterion("content is null");
return (Criteria) this; return (Criteria) this;
} }
public Criteria andDetailsIsNotNull() { public Criteria andContentIsNotNull() {
addCriterion("details is not null"); addCriterion("content is not null");
return (Criteria) this; return (Criteria) this;
} }
public Criteria andDetailsEqualTo(String value) { public Criteria andContentEqualTo(String value) {
addCriterion("details =", value, "details"); addCriterion("content =", value, "content");
return (Criteria) this; return (Criteria) this;
} }
public Criteria andDetailsNotEqualTo(String value) { public Criteria andContentNotEqualTo(String value) {
addCriterion("details <>", value, "details"); addCriterion("content <>", value, "content");
return (Criteria) this; return (Criteria) this;
} }
public Criteria andDetailsGreaterThan(String value) { public Criteria andContentGreaterThan(String value) {
addCriterion("details >", value, "details"); addCriterion("content >", value, "content");
return (Criteria) this; return (Criteria) this;
} }
public Criteria andDetailsGreaterThanOrEqualTo(String value) { public Criteria andContentGreaterThanOrEqualTo(String value) {
addCriterion("details >=", value, "details"); addCriterion("content >=", value, "content");
return (Criteria) this; return (Criteria) this;
} }
public Criteria andDetailsLessThan(String value) { public Criteria andContentLessThan(String value) {
addCriterion("details <", value, "details"); addCriterion("content <", value, "content");
return (Criteria) this; return (Criteria) this;
} }
public Criteria andDetailsLessThanOrEqualTo(String value) { public Criteria andContentLessThanOrEqualTo(String value) {
addCriterion("details <=", value, "details"); addCriterion("content <=", value, "content");
return (Criteria) this; return (Criteria) this;
} }
public Criteria andDetailsLike(String value) { public Criteria andContentLike(String value) {
addCriterion("details like", value, "details"); addCriterion("content like", value, "content");
return (Criteria) this; return (Criteria) this;
} }
public Criteria andDetailsNotLike(String value) { public Criteria andContentNotLike(String value) {
addCriterion("details not like", value, "details"); addCriterion("content not like", value, "content");
return (Criteria) this; return (Criteria) this;
} }
public Criteria andDetailsIn(List<String> values) { public Criteria andContentIn(List<String> values) {
addCriterion("details in", values, "details"); addCriterion("content in", values, "content");
return (Criteria) this; return (Criteria) this;
} }
public Criteria andDetailsNotIn(List<String> values) { public Criteria andContentNotIn(List<String> values) {
addCriterion("details not in", values, "details"); addCriterion("content not in", values, "content");
return (Criteria) this; return (Criteria) this;
} }
public Criteria andDetailsBetween(String value1, String value2) { public Criteria andContentBetween(String value1, String value2) {
addCriterion("details between", value1, value2, "details"); addCriterion("content between", value1, value2, "content");
return (Criteria) this; return (Criteria) this;
} }
public Criteria andDetailsNotBetween(String value1, String value2) { public Criteria andContentNotBetween(String value1, String value2) {
addCriterion("details not between", value1, value2, "details"); addCriterion("content not between", value1, value2, "content");
return (Criteria) this; return (Criteria) this;
} }

View File

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

View File

@ -0,0 +1,211 @@
<?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.sdk.mapper.OperationLogBlobMapper">
<resultMap id="BaseResultMap" type="io.metersphere.sdk.domain.OperationLogBlob">
<id column="id" jdbcType="VARCHAR" property="id" />
</resultMap>
<resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="io.metersphere.sdk.domain.OperationLogBlob">
<result column="original_value" jdbcType="LONGVARBINARY" property="originalValue" />
<result column="modified_value" jdbcType="LONGVARBINARY" property="modifiedValue" />
</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
</sql>
<sql id="Blob_Column_List">
original_value, modified_value
</sql>
<select id="selectByExampleWithBLOBs" parameterType="io.metersphere.sdk.domain.OperationLogBlobExample" resultMap="ResultMapWithBLOBs">
select
<if test="distinct">
distinct
</if>
<include refid="Base_Column_List" />
,
<include refid="Blob_Column_List" />
from operation_log_blob
<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.sdk.domain.OperationLogBlobExample" resultMap="BaseResultMap">
select
<if test="distinct">
distinct
</if>
<include refid="Base_Column_List" />
from operation_log_blob
<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 operation_log_blob
where id = #{id,jdbcType=VARCHAR}
</select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.String">
delete from operation_log_blob
where id = #{id,jdbcType=VARCHAR}
</delete>
<delete id="deleteByExample" parameterType="io.metersphere.sdk.domain.OperationLogBlobExample">
delete from operation_log_blob
<if test="_parameter != null">
<include refid="Example_Where_Clause" />
</if>
</delete>
<insert id="insert" parameterType="io.metersphere.sdk.domain.OperationLogBlob">
insert into operation_log_blob (id, original_value, modified_value
)
values (#{id,jdbcType=VARCHAR}, #{originalValue,jdbcType=LONGVARBINARY}, #{modifiedValue,jdbcType=LONGVARBINARY}
)
</insert>
<insert id="insertSelective" parameterType="io.metersphere.sdk.domain.OperationLogBlob">
insert into operation_log_blob
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="id != null">
id,
</if>
<if test="originalValue != null">
original_value,
</if>
<if test="modifiedValue != null">
modified_value,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="id != null">
#{id,jdbcType=VARCHAR},
</if>
<if test="originalValue != null">
#{originalValue,jdbcType=LONGVARBINARY},
</if>
<if test="modifiedValue != null">
#{modifiedValue,jdbcType=LONGVARBINARY},
</if>
</trim>
</insert>
<select id="countByExample" parameterType="io.metersphere.sdk.domain.OperationLogBlobExample" resultType="java.lang.Long">
select count(*) from operation_log_blob
<if test="_parameter != null">
<include refid="Example_Where_Clause" />
</if>
</select>
<update id="updateByExampleSelective" parameterType="map">
update operation_log_blob
<set>
<if test="record.id != null">
id = #{record.id,jdbcType=VARCHAR},
</if>
<if test="record.originalValue != null">
original_value = #{record.originalValue,jdbcType=LONGVARBINARY},
</if>
<if test="record.modifiedValue != null">
modified_value = #{record.modifiedValue,jdbcType=LONGVARBINARY},
</if>
</set>
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
</if>
</update>
<update id="updateByExampleWithBLOBs" parameterType="map">
update operation_log_blob
set id = #{record.id,jdbcType=VARCHAR},
original_value = #{record.originalValue,jdbcType=LONGVARBINARY},
modified_value = #{record.modifiedValue,jdbcType=LONGVARBINARY}
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
</if>
</update>
<update id="updateByExample" parameterType="map">
update operation_log_blob
set id = #{record.id,jdbcType=VARCHAR}
<if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" />
</if>
</update>
<update id="updateByPrimaryKeySelective" parameterType="io.metersphere.sdk.domain.OperationLogBlob">
update operation_log_blob
<set>
<if test="originalValue != null">
original_value = #{originalValue,jdbcType=LONGVARBINARY},
</if>
<if test="modifiedValue != null">
modified_value = #{modifiedValue,jdbcType=LONGVARBINARY},
</if>
</set>
where id = #{id,jdbcType=VARCHAR}
</update>
<update id="updateByPrimaryKeyWithBLOBs" parameterType="io.metersphere.sdk.domain.OperationLogBlob">
update operation_log_blob
set original_value = #{originalValue,jdbcType=LONGVARBINARY},
modified_value = #{modifiedValue,jdbcType=LONGVARBINARY}
where id = #{id,jdbcType=VARCHAR}
</update>
</mapper>

View File

@ -1,7 +1,7 @@
package io.metersphere.system.mapper; package io.metersphere.sdk.mapper;
import io.metersphere.system.domain.OperationLog; import io.metersphere.sdk.domain.OperationLog;
import io.metersphere.system.domain.OperationLogExample; import io.metersphere.sdk.domain.OperationLogExample;
import java.util.List; import java.util.List;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?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"> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="io.metersphere.system.mapper.OperationLogMapper"> <mapper namespace="io.metersphere.sdk.mapper.OperationLogMapper">
<resultMap id="BaseResultMap" type="io.metersphere.system.domain.OperationLog"> <resultMap id="BaseResultMap" type="io.metersphere.sdk.domain.OperationLog">
<id column="id" jdbcType="VARCHAR" property="id" /> <id column="id" jdbcType="VARCHAR" property="id" />
<result column="project_id" jdbcType="VARCHAR" property="projectId" /> <result column="project_id" jdbcType="VARCHAR" property="projectId" />
<result column="create_time" jdbcType="BIGINT" property="createTime" /> <result column="create_time" jdbcType="BIGINT" property="createTime" />
@ -10,7 +10,7 @@
<result column="method" jdbcType="VARCHAR" property="method" /> <result column="method" jdbcType="VARCHAR" property="method" />
<result column="type" jdbcType="VARCHAR" property="type" /> <result column="type" jdbcType="VARCHAR" property="type" />
<result column="module" jdbcType="VARCHAR" property="module" /> <result column="module" jdbcType="VARCHAR" property="module" />
<result column="details" jdbcType="VARCHAR" property="details" /> <result column="content" jdbcType="VARCHAR" property="content" />
<result column="path" jdbcType="VARCHAR" property="path" /> <result column="path" jdbcType="VARCHAR" property="path" />
</resultMap> </resultMap>
<sql id="Example_Where_Clause"> <sql id="Example_Where_Clause">
@ -73,9 +73,9 @@
</sql> </sql>
<sql id="Base_Column_List"> <sql id="Base_Column_List">
id, project_id, create_time, create_user, source_id, `method`, `type`, `module`, id, project_id, create_time, create_user, source_id, `method`, `type`, `module`,
details, `path` content, `path`
</sql> </sql>
<select id="selectByExample" parameterType="io.metersphere.system.domain.OperationLogExample" resultMap="BaseResultMap"> <select id="selectByExample" parameterType="io.metersphere.sdk.domain.OperationLogExample" resultMap="BaseResultMap">
select select
<if test="distinct"> <if test="distinct">
distinct distinct
@ -99,23 +99,23 @@
delete from operation_log delete from operation_log
where id = #{id,jdbcType=VARCHAR} where id = #{id,jdbcType=VARCHAR}
</delete> </delete>
<delete id="deleteByExample" parameterType="io.metersphere.system.domain.OperationLogExample"> <delete id="deleteByExample" parameterType="io.metersphere.sdk.domain.OperationLogExample">
delete from operation_log delete from operation_log
<if test="_parameter != null"> <if test="_parameter != null">
<include refid="Example_Where_Clause" /> <include refid="Example_Where_Clause" />
</if> </if>
</delete> </delete>
<insert id="insert" parameterType="io.metersphere.system.domain.OperationLog"> <insert id="insert" parameterType="io.metersphere.sdk.domain.OperationLog">
insert into operation_log (id, project_id, create_time, insert into operation_log (id, project_id, create_time,
create_user, source_id, `method`, create_user, source_id, `method`,
`type`, `module`, details, `type`, `module`, content,
`path`) `path`)
values (#{id,jdbcType=VARCHAR}, #{projectId,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT}, values (#{id,jdbcType=VARCHAR}, #{projectId,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT},
#{createUser,jdbcType=VARCHAR}, #{sourceId,jdbcType=VARCHAR}, #{method,jdbcType=VARCHAR}, #{createUser,jdbcType=VARCHAR}, #{sourceId,jdbcType=VARCHAR}, #{method,jdbcType=VARCHAR},
#{type,jdbcType=VARCHAR}, #{module,jdbcType=VARCHAR}, #{details,jdbcType=VARCHAR}, #{type,jdbcType=VARCHAR}, #{module,jdbcType=VARCHAR}, #{content,jdbcType=VARCHAR},
#{path,jdbcType=VARCHAR}) #{path,jdbcType=VARCHAR})
</insert> </insert>
<insert id="insertSelective" parameterType="io.metersphere.system.domain.OperationLog"> <insert id="insertSelective" parameterType="io.metersphere.sdk.domain.OperationLog">
insert into operation_log insert into operation_log
<trim prefix="(" suffix=")" suffixOverrides=","> <trim prefix="(" suffix=")" suffixOverrides=",">
<if test="id != null"> <if test="id != null">
@ -142,8 +142,8 @@
<if test="module != null"> <if test="module != null">
`module`, `module`,
</if> </if>
<if test="details != null"> <if test="content != null">
details, content,
</if> </if>
<if test="path != null"> <if test="path != null">
`path`, `path`,
@ -174,15 +174,15 @@
<if test="module != null"> <if test="module != null">
#{module,jdbcType=VARCHAR}, #{module,jdbcType=VARCHAR},
</if> </if>
<if test="details != null"> <if test="content != null">
#{details,jdbcType=VARCHAR}, #{content,jdbcType=VARCHAR},
</if> </if>
<if test="path != null"> <if test="path != null">
#{path,jdbcType=VARCHAR}, #{path,jdbcType=VARCHAR},
</if> </if>
</trim> </trim>
</insert> </insert>
<select id="countByExample" parameterType="io.metersphere.system.domain.OperationLogExample" resultType="java.lang.Long"> <select id="countByExample" parameterType="io.metersphere.sdk.domain.OperationLogExample" resultType="java.lang.Long">
select count(*) from operation_log select count(*) from operation_log
<if test="_parameter != null"> <if test="_parameter != null">
<include refid="Example_Where_Clause" /> <include refid="Example_Where_Clause" />
@ -215,8 +215,8 @@
<if test="record.module != null"> <if test="record.module != null">
`module` = #{record.module,jdbcType=VARCHAR}, `module` = #{record.module,jdbcType=VARCHAR},
</if> </if>
<if test="record.details != null"> <if test="record.content != null">
details = #{record.details,jdbcType=VARCHAR}, content = #{record.content,jdbcType=VARCHAR},
</if> </if>
<if test="record.path != null"> <if test="record.path != null">
`path` = #{record.path,jdbcType=VARCHAR}, `path` = #{record.path,jdbcType=VARCHAR},
@ -236,13 +236,13 @@
`method` = #{record.method,jdbcType=VARCHAR}, `method` = #{record.method,jdbcType=VARCHAR},
`type` = #{record.type,jdbcType=VARCHAR}, `type` = #{record.type,jdbcType=VARCHAR},
`module` = #{record.module,jdbcType=VARCHAR}, `module` = #{record.module,jdbcType=VARCHAR},
details = #{record.details,jdbcType=VARCHAR}, content = #{record.content,jdbcType=VARCHAR},
`path` = #{record.path,jdbcType=VARCHAR} `path` = #{record.path,jdbcType=VARCHAR}
<if test="_parameter != null"> <if test="_parameter != null">
<include refid="Update_By_Example_Where_Clause" /> <include refid="Update_By_Example_Where_Clause" />
</if> </if>
</update> </update>
<update id="updateByPrimaryKeySelective" parameterType="io.metersphere.system.domain.OperationLog"> <update id="updateByPrimaryKeySelective" parameterType="io.metersphere.sdk.domain.OperationLog">
update operation_log update operation_log
<set> <set>
<if test="projectId != null"> <if test="projectId != null">
@ -266,8 +266,8 @@
<if test="module != null"> <if test="module != null">
`module` = #{module,jdbcType=VARCHAR}, `module` = #{module,jdbcType=VARCHAR},
</if> </if>
<if test="details != null"> <if test="content != null">
details = #{details,jdbcType=VARCHAR}, content = #{content,jdbcType=VARCHAR},
</if> </if>
<if test="path != null"> <if test="path != null">
`path` = #{path,jdbcType=VARCHAR}, `path` = #{path,jdbcType=VARCHAR},
@ -275,7 +275,7 @@
</set> </set>
where id = #{id,jdbcType=VARCHAR} where id = #{id,jdbcType=VARCHAR}
</update> </update>
<update id="updateByPrimaryKey" parameterType="io.metersphere.system.domain.OperationLog"> <update id="updateByPrimaryKey" parameterType="io.metersphere.sdk.domain.OperationLog">
update operation_log update operation_log
set project_id = #{projectId,jdbcType=VARCHAR}, set project_id = #{projectId,jdbcType=VARCHAR},
create_time = #{createTime,jdbcType=BIGINT}, create_time = #{createTime,jdbcType=BIGINT},
@ -284,7 +284,7 @@
`method` = #{method,jdbcType=VARCHAR}, `method` = #{method,jdbcType=VARCHAR},
`type` = #{type,jdbcType=VARCHAR}, `type` = #{type,jdbcType=VARCHAR},
`module` = #{module,jdbcType=VARCHAR}, `module` = #{module,jdbcType=VARCHAR},
details = #{details,jdbcType=VARCHAR}, content = #{content,jdbcType=VARCHAR},
`path` = #{path,jdbcType=VARCHAR} `path` = #{path,jdbcType=VARCHAR}
where id = #{id,jdbcType=VARCHAR} where id = #{id,jdbcType=VARCHAR}
</update> </update>

View File

@ -1,5 +1,31 @@
-- set innodb lock wait timeout -- set innodb lock wait timeout
SET SESSION innodb_lock_wait_timeout = 7200; SET SESSION innodb_lock_wait_timeout = 7200;
CREATE TABLE IF NOT EXISTS operation_log
(
`id` VARCHAR(50) NOT NULL COMMENT '主键',
`project_id` VARCHAR(50) NOT NULL DEFAULT 'NONE' COMMENT '项目id',
`create_time` BIGINT NOT NULL COMMENT '操作时间',
`create_user` VARCHAR(50) COMMENT '操作人',
`source_id` VARCHAR(50) COMMENT '资源id',
`method` VARCHAR(255) NOT NULL COMMENT '操作方法',
`type` VARCHAR(20) NOT NULL COMMENT '操作类型/add/update/delete',
`module` VARCHAR(50) COMMENT '操作模块/api/case/scenario/ui',
`content` VARCHAR(500) COMMENT '操作详情',
`path` VARCHAR(255) COMMENT '操作路径',
PRIMARY KEY (id)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci COMMENT = '操作日志';
DROP TABLE IF EXISTS operation_log_blob;
CREATE TABLE operation_log_blob(
`id` VARCHAR(50) NOT NULL COMMENT '主键' ,
`original_value` LONGBLOB COMMENT '变更前内容' ,
`modified_value` LONGBLOB COMMENT '变更后内容' ,
PRIMARY KEY (id)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci COMMENT = '操作日志内容详情';
-- set innodb lock wait timeout to default -- set innodb lock wait timeout to default
SET SESSION innodb_lock_wait_timeout = DEFAULT; SET SESSION innodb_lock_wait_timeout = DEFAULT;

View File

@ -27,6 +27,11 @@
<artifactId>ApacheJMeter_core</artifactId> <artifactId>ApacheJMeter_core</artifactId>
<version>${jmeter.version}</version> <version>${jmeter.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.apache.jmeter</groupId>
<artifactId>jorphan</artifactId>
<version>${jmeter.version}</version>
</dependency>
<dependency> <dependency>
<groupId>org.projectlombok</groupId> <groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId> <artifactId>lombok</artifactId>

View File

@ -2,10 +2,15 @@ package io.metersphere.plugin.api.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.JsonTypeInfo;
import io.metersphere.plugin.util.PluginLogUtils;
import lombok.Data; import lombok.Data;
import org.apache.jmeter.save.SaveService;
import org.apache.jorphan.collections.ListedHashTree;
import java.io.ByteArrayOutputStream;
import java.io.Serializable; import java.io.Serializable;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List;
@Data @Data
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type") @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
@ -34,6 +39,50 @@ public abstract class TestElementDTO implements Serializable {
// 父类 // 父类
private TestElementDTO parent; private TestElementDTO parent;
/**
* 自组件重新这个方法
*
* @param tree
* @param hashTree
* @param config
*/
public void toHashTree(ListedHashTree tree, List<TestElementDTO> hashTree, BaseConfigDTO config) {
if (hashTree != null && hashTree.size() > 0) {
for (TestElementDTO el : hashTree) {
el.toHashTree(tree, el.hashTree, config);
}
}
}
/**
* 转换JMX
*
* @param hashTree
* @return
*/
public String getJmx(ListedHashTree hashTree) {
try (ByteArrayOutputStream bas = new ByteArrayOutputStream()) {
SaveService.saveTree(hashTree, bas);
return bas.toString();
} catch (Exception e) {
PluginLogUtils.error("ListedHashTree error, can't log jmx scenarioDefinition");
}
return null;
}
/**
* 生成hashTree
*
* @param config
* @return
*/
public ListedHashTree generateHashTree(BaseConfigDTO config) {
ListedHashTree listedHashTree = new ListedHashTree();
this.toHashTree(listedHashTree, this.hashTree, config);
return listedHashTree;
}
} }

View File

@ -0,0 +1,23 @@
package io.metersphere.sdk.config.interceptor;
import io.metersphere.sdk.domain.OperationLogBlob;
import io.metersphere.sdk.util.CompressUtils;
import io.metersphere.sdk.util.MybatisInterceptorConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.ArrayList;
import java.util.List;
@Configuration
public class SdkInterceptor {
@Bean
public List<MybatisInterceptorConfig> sdkCompressConfigs() {
List<MybatisInterceptorConfig> configList = new ArrayList<>();
configList.add(new MybatisInterceptorConfig(OperationLogBlob.class, "originalValue", CompressUtils.class, "zip", "unzip"));
configList.add(new MybatisInterceptorConfig(OperationLogBlob.class, "modifiedValue", CompressUtils.class, "zip", "unzip"));
return configList;
}
}

View File

@ -0,0 +1,29 @@
package io.metersphere.sdk.dto;
import io.metersphere.sdk.domain.OperationLog;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.UUID;
@Data
public class LogDTO extends OperationLog {
@Schema(title = "变更前内容")
private byte[] originalValue;
@Schema(title = "变更后内容")
private byte[] modifiedValue;
public LogDTO() {
}
public LogDTO(String projectId, String sourceId, String createUser, String type, String module, String content) {
this.setProjectId(projectId);
this.setSourceId(sourceId);
this.setCreateUser(createUser);
this.setType(type);
this.setModule(module);
this.setContent(content);
this.setId(UUID.randomUUID().toString());
this.setCreateTime(System.currentTimeMillis());
}
}

View File

@ -13,19 +13,6 @@ import java.lang.annotation.*;
* @author mr.zhao * @author mr.zhao
*/ */
public @interface Log { public @interface Log {
/**
* 功能模块
*
* @return
*/
String module() default OperationLogModule.UNKNOWN_MODULE;
/**
* 项目系统模块没有项目id默认系统
*
* @return
*/
String projectId() default "system";
/** /**
* 操作类型 * 操作类型
@ -34,38 +21,10 @@ public @interface Log {
*/ */
OperationLogType type() default OperationLogType.SELECT; OperationLogType type() default OperationLogType.SELECT;
/** /***
* 资源ID * 操作函数
*/ */
String sourceId() default ""; String expression();
/**
* 创建用户
*
* @return
*/
String createUser() default "admin";
/**
* 操作内容
*
* @return
*/
String details() default "";
/**
* 是否是批量删除操作
*
* @return
*/
boolean isBatch() default false;
/**
* 是否在业务代码执行前记录内容
*
* @return
*/
boolean isBefore() default false;
/** /**
* 传入执行类 * 传入执行类

View File

@ -1,13 +1,14 @@
package io.metersphere.sdk.log.aspect; package io.metersphere.sdk.log.aspect;
import io.metersphere.sdk.dto.LogDTO;
import io.metersphere.sdk.log.annotation.Log; import io.metersphere.sdk.log.annotation.Log;
import io.metersphere.sdk.log.constants.OperationLogType;
import io.metersphere.sdk.log.service.OperationLogService; import io.metersphere.sdk.log.service.OperationLogService;
import io.metersphere.sdk.util.JSON; import io.metersphere.sdk.util.JSON;
import io.metersphere.sdk.util.LogUtils; import io.metersphere.sdk.util.LogUtils;
import io.metersphere.sdk.util.SessionUtils; import io.metersphere.sdk.util.SessionUtils;
import io.metersphere.system.domain.OperationLog;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint; import org.aspectj.lang.JoinPoint;
@ -24,14 +25,13 @@ import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext; import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.stream.Collectors;
/** /**
* 系统日志切面处理类 * 系统日志切面处理类
@ -55,16 +55,15 @@ public class OperationLogAspect {
@Resource @Resource
private OperationLogService operationLogService; private OperationLogService operationLogService;
// 批量变更前后内容
private ThreadLocal<List<OperationLog>> beforeValue = new ThreadLocal<>(); private ThreadLocal<List<LogDTO>> beforeValues = new ThreadLocal<>();
private ThreadLocal<String> treadLocalDetails = new ThreadLocal<>();
private ThreadLocal<String> treadLocalSourceId = new ThreadLocal<>();
private ThreadLocal<String> localUser = new ThreadLocal<>(); private ThreadLocal<String> localUser = new ThreadLocal<>();
private final String[] methodNames = new String[]{"delete", "update", "add"}; // 此方法随时补充类型需要在内容变更前执行的类型都可以加入
private final OperationLogType[] beforeMethodNames = new OperationLogType[]{OperationLogType.UPDATE, OperationLogType.DELETE};
// 需要后置执行合并内容的
private final OperationLogType[] postMethodNames = new OperationLogType[]{OperationLogType.ADD, OperationLogType.UPDATE};
/** /**
* 定义切点 @Pointcut 在注解的位置切入代码 * 定义切点 @Pointcut 在注解的位置切入代码
@ -76,12 +75,13 @@ public class OperationLogAspect {
@Before("logPointCut()") @Before("logPointCut()")
public void before(JoinPoint joinPoint) { public void before(JoinPoint joinPoint) {
try { try {
localUser.set(SessionUtils.getUserId());
//从切面织入点处通过反射机制获取织入点处的方法 //从切面织入点处通过反射机制获取织入点处的方法
MethodSignature signature = (MethodSignature) joinPoint.getSignature(); MethodSignature signature = (MethodSignature) joinPoint.getSignature();
//获取切入点所在的方法 //获取切入点所在的方法
Method method = signature.getMethod(); Method method = signature.getMethod();
Log msLog = method.getAnnotation(Log.class); Log msLog = method.getAnnotation(Log.class);
if (msLog != null && msLog.isBefore()) { if (msLog != null && isMatch(msLog.type())) {
//获取参数对象数组 //获取参数对象数组
Object[] args = joinPoint.getArgs(); Object[] args = joinPoint.getArgs();
//获取方法参数名 //获取方法参数名
@ -94,10 +94,6 @@ public class OperationLogAspect {
} }
boolean isNext = false; boolean isNext = false;
for (Class clazz : msLog.msClass()) { for (Class clazz : msLog.msClass()) {
if (clazz.getName().endsWith("SessionUtils")) {
localUser.set(SessionUtils.getUserId());
continue;
}
context.setVariable("msClass", applicationContext.getBean(clazz)); context.setVariable("msClass", applicationContext.getBean(clazz));
isNext = true; isNext = true;
} }
@ -105,134 +101,87 @@ public class OperationLogAspect {
return; return;
} }
// 初始化details内容 // 初始化details内容
initDetails(msLog, context); initBeforeDetails(msLog, context);
// 初始化资源id
initResourceId(msLog, context);
} }
} catch (Exception e) { } catch (Exception e) {
LogUtils.error("操作日志写入异常:" + joinPoint.getSignature()); LogUtils.error("操作日志写入异常:" + joinPoint.getSignature());
} }
} }
public boolean isMatch(String keyword) { public boolean isMatch(OperationLogType keyword) {
return Arrays.stream(methodNames) return Arrays.stream(beforeMethodNames)
.anyMatch(input -> input.contains(keyword)); .anyMatch(input -> input.contains(keyword));
} }
private void initDetails(Log msLog, EvaluationContext context) { private void initBeforeDetails(Log msLog, EvaluationContext context) {
try { try {
// 批量内容处理 // 批量内容处理
if (StringUtils.isNotBlank(msLog.details()) && msLog.details().startsWith("#msClass")) { Expression expression = parser.parseExpression(msLog.expression());
if (msLog.isBatch()) { Object obj = expression.getValue(context);
Expression expression = parser.parseExpression(msLog.details()); if (obj == null) {
List<OperationLog> beforeContent = expression.getValue(context, List.class); return;
beforeValue.set(beforeContent);
} else {
Expression detailsEx = parser.parseExpression(msLog.details());
String details = detailsEx.getValue(context, String.class);
this.treadLocalDetails.set(details);
}
} else if (StringUtils.isNotBlank(msLog.details()) && msLog.details().startsWith("#")) {
Expression titleExp = parser.parseExpression(msLog.details());
String details = titleExp.getValue(context, String.class);
this.treadLocalDetails.set(details);
} else {
this.treadLocalDetails.set(msLog.details());
} }
if (obj instanceof List<?>) {
beforeValues.set((List<LogDTO>) obj);
} else {
List<LogDTO> LogDTOs = new ArrayList<>();
LogDTOs.add((LogDTO) obj);
beforeValues.set(LogDTOs);
}
} catch (Exception e) { } catch (Exception e) {
LogUtils.error("未获取到details内容", e); LogUtils.error("未获取到details内容", e);
this.treadLocalDetails.set(msLog.details());
} }
} }
private void initResourceId(Log msLog, EvaluationContext context) { public void mergeLists(List<LogDTO> beforeLogs, List<LogDTO> postLogs) {
try { if (CollectionUtils.isEmpty(beforeLogs) && CollectionUtils.isNotEmpty(postLogs)) {
// 批量内容处理 beforeValues.set(postLogs);
if (StringUtils.isNotBlank(msLog.sourceId()) && msLog.sourceId().startsWith("#msClass")) {
Expression detailsEx = parser.parseExpression(msLog.sourceId());
String sourceId = detailsEx.getValue(context, String.class);
treadLocalSourceId.set(sourceId);
} else if (StringUtils.isNotBlank(msLog.sourceId()) && msLog.sourceId().startsWith("#")) {
Expression titleExp = parser.parseExpression(msLog.sourceId());
String sourceId = titleExp.getValue(context, String.class);
treadLocalSourceId.set(sourceId);
} else {
treadLocalSourceId.set(msLog.sourceId());
}
} catch (Exception e) {
LogUtils.error("未获取到资源id", e);
treadLocalSourceId.set(msLog.sourceId());
}
}
private String getProjectId(Log msLog, EvaluationContext context) {
try {
if (StringUtils.isNotBlank(msLog.projectId()) && msLog.projectId().startsWith("#")) {
Expression titleExp = parser.parseExpression(msLog.projectId());
return titleExp.getValue(context, String.class);
} else {
return msLog.projectId();
}
} catch (Exception e) {
return msLog.projectId();
}
}
private void add(OperationLog operationLog, Log msLog, JoinPoint joinPoint, Object result) {
//从切面织入点处通过反射机制获取织入点处的方法
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
//获取切入点所在的方法
Method method = signature.getMethod();
//获取参数对象数组
Object[] args = joinPoint.getArgs();
// 操作类型
operationLog.setType(msLog.type().name());
// 创建用户
if (StringUtils.isNotBlank(msLog.createUser())) {
operationLog.setCreateUser(msLog.createUser());
}
// 项目ID
operationLog.setProjectId(msLog.projectId());
operationLog.setModule(msLog.module());
//获取方法参数名
String[] params = discoverer.getParameterNames(method);
//将参数纳入Spring管理
EvaluationContext context = new StandardEvaluationContext();
for (int len = 0; len < params.length; len++) {
context.setVariable(params[len], args[len]);
}
for (Class clazz : msLog.msClass()) {
context.setVariable("msClass", applicationContext.getBean(clazz));
}
// 批量编辑操作
if (msLog.isBatch()) {
operationLogService.batchAdd(beforeValue.get());
return; return;
} }
// 项目ID表达式 if (CollectionUtils.isEmpty(beforeLogs) && CollectionUtils.isEmpty(postLogs)) {
operationLog.setProjectId(getProjectId(msLog, context)); return;
if (!msLog.isBefore()) {
// 初始化资源id
initResourceId(msLog, context);
// 初始化内容详情
initDetails(msLog, context);
} }
// 内容详情 Map<String, LogDTO> postDto = postLogs.stream().collect(Collectors.toMap(LogDTO::getSourceId, item -> item));
operationLog.setDetails(treadLocalDetails.get()); beforeLogs.forEach(item -> {
// 资源id LogDTO post = postDto.get(item.getSourceId());
operationLog.setSourceId(treadLocalSourceId.get()); if (post != null) {
item.setModifiedValue(post.getOriginalValue());
if (StringUtils.isBlank(operationLog.getCreateUser())) { }
operationLog.setCreateUser(localUser.get()); });
}
// 从返回内容中获取资源id
if (StringUtils.isEmpty(operationLog.getSourceId()) && !msLog.isBatch()) {
operationLog.setSourceId(getId(result));
}
operationLogService.add(operationLog);
} }
private void initPostDetails(Log msLog, EvaluationContext context) {
try {
if (StringUtils.isBlank(msLog.expression())) {
return;
}
// 批量内容处理
Expression expression = parser.parseExpression(msLog.expression());
Object obj = expression.getValue(context);
if (obj == null) {
return;
}
if (obj instanceof List<?>) {
mergeLists(beforeValues.get(), (List<LogDTO>) obj);
} else if (obj instanceof LogDTO) {
LogDTO log = (LogDTO) obj;
if (CollectionUtils.isNotEmpty(beforeValues.get())) {
beforeValues.get().get(0).setModifiedValue(log.getOriginalValue());
} else {
beforeValues.set(new ArrayList<>() {{
this.add(log);
}});
}
}
} catch (Exception e) {
LogUtils.error("未获取到details内容", e);
}
}
public String getId(Object result) { public String getId(Object result) {
try { try {
if (result != null) { if (result != null) {
@ -251,6 +200,26 @@ public class OperationLogAspect {
return null; return null;
} }
private void save(Object result) {
List<LogDTO> logDTOList = beforeValues.get();
if (CollectionUtils.isEmpty(logDTOList)) {
return;
}
// 单条存储
if (logDTOList.size() == 1) {
LogDTO logDTO = logDTOList.get(0);
if (StringUtils.isBlank(logDTO.getSourceId())) {
logDTO.setSourceId(getId(result));
}
if (StringUtils.isBlank(logDTO.getCreateUser())) {
logDTO.setCreateUser(localUser.get());
}
operationLogService.add(logDTO);
} else {
operationLogService.batchAdd(logDTOList);
}
}
/** /**
* 切面 配置通知 * 切面 配置通知
*/ */
@ -261,30 +230,33 @@ public class OperationLogAspect {
MethodSignature signature = (MethodSignature) joinPoint.getSignature(); MethodSignature signature = (MethodSignature) joinPoint.getSignature();
//获取切入点所在的方法 //获取切入点所在的方法
Method method = signature.getMethod(); Method method = signature.getMethod();
//保存日志
OperationLog operationLog = new OperationLog();
//保存获取的操作
operationLog.setId(UUID.randomUUID().toString());
operationLog.setMethod(method.getName());
operationLog.setCreateTime(System.currentTimeMillis());
operationLog.setCreateUser(SessionUtils.getUserId());
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
operationLog.setPath(request.getServletPath());
// 获取操作 // 获取操作
Log msLog = method.getAnnotation(Log.class); Log msLog = method.getAnnotation(Log.class);
if (msLog != null) { if (msLog != null) {
add(operationLog, msLog, joinPoint, result); //获取参数对象数组
} Object[] args = joinPoint.getArgs();
// 兼容遗漏注解的内容 //获取方法参数名
else if (isMatch(method.getName())) { String[] params = discoverer.getParameterNames(method);
operationLogService.add(operationLog); //将参数纳入Spring管理
EvaluationContext context = new StandardEvaluationContext();
for (int len = 0; len < params.length; len++) {
context.setVariable(params[len], args[len]);
}
for (Class clazz : msLog.msClass()) {
context.setVariable("msClass", applicationContext.getBean(clazz));
}
// 需要后置再次执行的方法
if (Arrays.stream(postMethodNames).anyMatch(input -> input.contains(msLog.type()))) {
initPostDetails(msLog, context);
}
// 存储日志结果
save(result);
} }
} catch (Exception e) { } catch (Exception e) {
LogUtils.error("操作日志写入异常:", e); LogUtils.error("操作日志写入异常:", e);
} finally { } finally {
localUser.remove(); localUser.remove();
beforeValue.remove(); beforeValues.remove();
treadLocalDetails.remove();
} }
} }

View File

@ -14,5 +14,9 @@ public enum OperationLogType {
EXPORT, EXPORT,
LOGIN, LOGIN,
SELECT, SELECT,
RECOVER RECOVER;
public boolean contains(OperationLogType keyword) {
return this.name().contains(keyword.name());
}
} }

View File

@ -1,7 +1,9 @@
package io.metersphere.sdk.log.service; package io.metersphere.sdk.log.service;
import io.metersphere.system.domain.OperationLog; import io.metersphere.sdk.domain.OperationLogBlob;
import io.metersphere.system.mapper.OperationLogMapper; import io.metersphere.sdk.dto.LogDTO;
import io.metersphere.sdk.mapper.OperationLogBlobMapper;
import io.metersphere.sdk.mapper.OperationLogMapper;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
@ -13,6 +15,7 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.util.List; import java.util.List;
import java.util.UUID;
@Service @Service
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
@ -20,9 +23,11 @@ public class OperationLogService {
@Resource @Resource
private OperationLogMapper operationLogMapper; private OperationLogMapper operationLogMapper;
@Resource @Resource
private OperationLogBlobMapper operationLogBlobMapper;
@Resource
private SqlSessionFactory sqlSessionFactory; private SqlSessionFactory sqlSessionFactory;
public void add(OperationLog log) { public void add(LogDTO log) {
if (StringUtils.isBlank(log.getProjectId())) { if (StringUtils.isBlank(log.getProjectId())) {
log.setProjectId("none"); log.setProjectId("none");
} }
@ -30,25 +35,24 @@ public class OperationLogService {
log.setCreateUser("admin"); log.setCreateUser("admin");
} }
// 限制长度 // 限制长度
if (StringUtils.isNotBlank(log.getDetails()) && log.getDetails().length() > 500) { saveBlob(operationLogMapper, operationLogBlobMapper, log);
log.setDetails(log.getDetails().substring(0, 499));
}
operationLogMapper.insert(log);
} }
public void batchAdd(List<OperationLog> logs) { public void batchAdd(List<LogDTO> logs) {
if (CollectionUtils.isEmpty(logs)) { if (CollectionUtils.isEmpty(logs)) {
return; return;
} }
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH); SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
OperationLogMapper logMapper = sqlSession.getMapper(OperationLogMapper.class); OperationLogMapper logMapper = sqlSession.getMapper(OperationLogMapper.class);
OperationLogBlobMapper logBlobMapper = sqlSession.getMapper(OperationLogBlobMapper.class);
if (CollectionUtils.isNotEmpty(logs)) { if (CollectionUtils.isNotEmpty(logs)) {
logs.forEach(item -> { logs.forEach(item -> {
// 限制长度 if (StringUtils.isBlank(item.getId())) {
if (StringUtils.isNotBlank(item.getDetails()) && item.getDetails().length() > 500) { item.setId(UUID.randomUUID().toString());
item.setDetails(item.getDetails().substring(0, 499));
} }
logMapper.insert(item); // 限制长度
saveBlob(logMapper, logBlobMapper, item);
}); });
} }
sqlSession.flushStatements(); sqlSession.flushStatements();
@ -56,4 +60,16 @@ public class OperationLogService {
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory); SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
} }
} }
private void saveBlob(OperationLogMapper logMapper, OperationLogBlobMapper logBlobMapper, LogDTO item) {
if (StringUtils.isNotBlank(item.getContent()) && item.getContent().length() > 500) {
item.setContent(item.getContent().substring(0, 499));
}
logMapper.insert(item);
OperationLogBlob blob = new OperationLogBlob();
blob.setId(item.getId());
blob.setOriginalValue(item.getOriginalValue());
blob.setModifiedValue(item.getModifiedValue());
logBlobMapper.insert(blob);
}
} }

View File

@ -1,11 +1,16 @@
package io.metersphere.sdk.service; package io.metersphere.sdk.service;
import io.metersphere.constants.HttpMethodConstants;
import io.metersphere.dto.BaseSystemConfigDTO; import io.metersphere.dto.BaseSystemConfigDTO;
import io.metersphere.sdk.constants.ParamConstants; import io.metersphere.sdk.constants.ParamConstants;
import io.metersphere.sdk.dto.EMailInfoDto; import io.metersphere.sdk.dto.EMailInfoDto;
import io.metersphere.sdk.dto.LogDTO;
import io.metersphere.sdk.exception.MSException; import io.metersphere.sdk.exception.MSException;
import io.metersphere.sdk.log.constants.OperationLogModule;
import io.metersphere.sdk.log.constants.OperationLogType;
import io.metersphere.sdk.notice.sender.impl.MailNoticeSender; import io.metersphere.sdk.notice.sender.impl.MailNoticeSender;
import io.metersphere.sdk.util.EncryptUtils; import io.metersphere.sdk.util.EncryptUtils;
import io.metersphere.sdk.util.JSON;
import io.metersphere.sdk.util.LogUtils; import io.metersphere.sdk.util.LogUtils;
import io.metersphere.sdk.util.Translator; import io.metersphere.sdk.util.Translator;
import io.metersphere.system.domain.SystemParameter; import io.metersphere.system.domain.SystemParameter;
@ -204,4 +209,38 @@ public class SystemParameterService {
} }
} }
/**
* 添加接口日志
* @return
*/
public LogDTO addLog(List<SystemParameter> systemParameter) {
LogDTO dto = new LogDTO(
"system",
"system-parameter",
null,
OperationLogType.ADD.name(),
OperationLogModule.SYSTEM_USER_ROLE_RELATION,
"系统参数");
dto.setPath("/system/parameter/save/base-info");
dto.setMethod(HttpMethodConstants.POST.name());
dto.setOriginalValue(JSON.toJSONBytes(systemParameter));
return dto;
}
public LogDTO updateLog(List<SystemParameter> systemParameter) {
LogDTO dto = new LogDTO(
"system",
"system-parameter",
null,
OperationLogType.ADD.name(),
OperationLogModule.SYSTEM_USER_ROLE_RELATION,
"编辑邮件信息");
dto.setPath("/system/parameter/edit/email-info");
dto.setMethod(HttpMethodConstants.POST.name());
dto.setOriginalValue(JSON.toJSONBytes(systemParameter));
return dto;
}
} }

View File

@ -1,12 +1,16 @@
package io.metersphere.sdk.service; package io.metersphere.sdk.service;
import groovy.util.logging.Slf4j; import groovy.util.logging.Slf4j;
import io.metersphere.constants.HttpMethodConstants;
import io.metersphere.sdk.constants.ResourcePoolTypeEnum; import io.metersphere.sdk.constants.ResourcePoolTypeEnum;
import io.metersphere.sdk.dto.QueryResourcePoolRequest; import io.metersphere.sdk.dto.*;
import io.metersphere.sdk.dto.TestResourceDTO;
import io.metersphere.sdk.dto.TestResourcePoolDTO;
import io.metersphere.sdk.exception.MSException; import io.metersphere.sdk.exception.MSException;
import io.metersphere.sdk.util.*; import io.metersphere.sdk.log.constants.OperationLogModule;
import io.metersphere.sdk.log.constants.OperationLogType;
import io.metersphere.sdk.util.BeanUtils;
import io.metersphere.sdk.util.CommonBeanFactory;
import io.metersphere.sdk.util.JSON;
import io.metersphere.sdk.util.Translator;
import io.metersphere.system.domain.*; import io.metersphere.system.domain.*;
import io.metersphere.system.mapper.TestResourcePoolBlobMapper; import io.metersphere.system.mapper.TestResourcePoolBlobMapper;
import io.metersphere.system.mapper.TestResourcePoolMapper; import io.metersphere.system.mapper.TestResourcePoolMapper;
@ -65,21 +69,21 @@ public class TestResourcePoolService {
private void checkAndSaveOrgRelation(TestResourcePool testResourcePool, String id, TestResourceDTO testResourceDTO) { private void checkAndSaveOrgRelation(TestResourcePool testResourcePool, String id, TestResourceDTO testResourceDTO) {
//防止前端传入的应用组织为空 //防止前端传入的应用组织为空
if ((testResourcePool.getAllOrg() == null || !testResourcePool.getAllOrg())&& CollectionUtils.isEmpty(testResourceDTO.getOrgIds())){ if ((testResourcePool.getAllOrg() == null || !testResourcePool.getAllOrg()) && CollectionUtils.isEmpty(testResourceDTO.getOrgIds())) {
throw new MSException(Translator.get("resource_pool_application_organization_is_empty")); throw new MSException(Translator.get("resource_pool_application_organization_is_empty"));
} }
//前端应用组织选择了全部但是也传了部分组织以全部组织为主 //前端应用组织选择了全部但是也传了部分组织以全部组织为主
if ((testResourcePool.getAllOrg() != null && testResourcePool.getAllOrg()) && CollectionUtils.isNotEmpty(testResourceDTO.getOrgIds()) ) { if ((testResourcePool.getAllOrg() != null && testResourcePool.getAllOrg()) && CollectionUtils.isNotEmpty(testResourceDTO.getOrgIds())) {
testResourceDTO.setOrgIds(new ArrayList<>()); testResourceDTO.setOrgIds(new ArrayList<>());
} }
//前端选择部分组织保存资源池与组织关系 //前端选择部分组织保存资源池与组织关系
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH); SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
TestResourcePoolOrganizationMapper poolOrganizationMapper = sqlSession.getMapper(TestResourcePoolOrganizationMapper.class); TestResourcePoolOrganizationMapper poolOrganizationMapper = sqlSession.getMapper(TestResourcePoolOrganizationMapper.class);
if ((testResourcePool.getAllOrg() == null || !testResourcePool.getAllOrg())&& CollectionUtils.isNotEmpty(testResourceDTO.getOrgIds())){ if ((testResourcePool.getAllOrg() == null || !testResourcePool.getAllOrg()) && CollectionUtils.isNotEmpty(testResourceDTO.getOrgIds())) {
testResourcePool.setAllOrg(false); testResourcePool.setAllOrg(false);
testResourceDTO.getOrgIds().forEach(orgId->{ testResourceDTO.getOrgIds().forEach(orgId -> {
TestResourcePoolOrganization testResourcePoolOrganization = new TestResourcePoolOrganization(); TestResourcePoolOrganization testResourcePoolOrganization = new TestResourcePoolOrganization();
testResourcePoolOrganization.setId(UUID.randomUUID().toString()); testResourcePoolOrganization.setId(UUID.randomUUID().toString());
testResourcePoolOrganization.setOrgId(orgId); testResourcePoolOrganization.setOrgId(orgId);
@ -110,7 +114,7 @@ public class TestResourcePoolService {
} }
private static boolean checkNodeOrK8s(TestResourceDTO testResourceDTO, String type, Boolean usedApiType) { private static boolean checkNodeOrK8s(TestResourceDTO testResourceDTO, String type, Boolean usedApiType) {
if (StringUtils.equalsIgnoreCase(type,ResourcePoolTypeEnum.NODE.name())) { if (StringUtils.equalsIgnoreCase(type, ResourcePoolTypeEnum.NODE.name())) {
NodeResourcePoolService resourcePoolService = CommonBeanFactory.getBean(NodeResourcePoolService.class); NodeResourcePoolService resourcePoolService = CommonBeanFactory.getBean(NodeResourcePoolService.class);
if (resourcePoolService != null) { if (resourcePoolService != null) {
return resourcePoolService.validate(testResourceDTO); return resourcePoolService.validate(testResourceDTO);
@ -249,10 +253,56 @@ public class TestResourcePoolService {
return testResourcePoolDTO; return testResourcePoolDTO;
} }
public String getLogDetails(String id) { public LogDTO addLog(TestResourcePoolRequest request) {
LogDTO dto = new LogDTO(
"system",
request.getId(),
null,
OperationLogType.ADD.name(),
OperationLogModule.SYSTEM_TEST_RESOURCE_POOL,
request.getName());
dto.setPath("/test/resource/pool/add");
dto.setMethod(HttpMethodConstants.POST.name());
dto.setOriginalValue(JSON.toJSONBytes(request));
return dto;
}
public LogDTO deleteLog(String id) {
TestResourcePool pool = testResourcePoolMapper.selectByPrimaryKey(id); TestResourcePool pool = testResourcePoolMapper.selectByPrimaryKey(id);
if (pool != null) { if (pool != null) {
return pool.getName(); LogDTO dto = new LogDTO(
"system",
id,
pool.getCreateUser(),
OperationLogType.DELETE.name(),
OperationLogModule.SYSTEM_TEST_RESOURCE_POOL,
pool.getName());
dto.setPath("/delete");
dto.setMethod(HttpMethodConstants.POST.name());
dto.setOriginalValue(JSON.toJSONBytes(pool));
return dto;
}
return null;
}
public LogDTO updateLog(TestResourcePoolRequest request) {
TestResourcePool pool = testResourcePoolMapper.selectByPrimaryKey(request.getId());
if (pool != null) {
LogDTO dto = new LogDTO(
"system",
pool.getId(),
pool.getCreateUser(),
OperationLogType.UPDATE.name(),
OperationLogModule.SYSTEM_TEST_RESOURCE_POOL,
"编辑全局用户组对应的权限配置");
dto.setPath("/update");
dto.setMethod(HttpMethodConstants.POST.name());
dto.setOriginalValue(JSON.toJSONBytes(pool));
return dto;
} }
return null; return null;
} }

View File

@ -37,6 +37,14 @@ public class JSON {
} }
} }
public static byte[] toJSONBytes(Object value) {
try {
return objectMapper.writeValueAsBytes(value);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static Object parseObject(String content) { public static Object parseObject(String content) {
return parseObject(content, Object.class); return parseObject(content, Object.class);
} }

View File

@ -8,8 +8,8 @@ import io.metersphere.sdk.controller.handler.result.IResultCode;
import io.metersphere.sdk.log.constants.OperationLogType; import io.metersphere.sdk.log.constants.OperationLogType;
import io.metersphere.sdk.util.JSON; import io.metersphere.sdk.util.JSON;
import io.metersphere.sdk.util.Pager; import io.metersphere.sdk.util.Pager;
import io.metersphere.system.domain.OperationLogExample; import io.metersphere.sdk.domain.OperationLogExample;
import io.metersphere.system.mapper.OperationLogMapper; import io.metersphere.sdk.mapper.OperationLogMapper;
import io.metersphere.validation.groups.Created; import io.metersphere.validation.groups.Created;
import io.metersphere.validation.groups.Updated; import io.metersphere.validation.groups.Updated;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;

View File

@ -1,20 +1,14 @@
package io.metersphere.api.controller; package io.metersphere.api.controller;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import io.metersphere.api.domain.ApiDefinition;
import io.metersphere.api.dto.definition.ApiDefinitionDTO; import io.metersphere.api.dto.definition.ApiDefinitionDTO;
import io.metersphere.api.dto.definition.ListRequestDTO; import io.metersphere.api.service.ApiDefinitionLogService;
import io.metersphere.api.service.ApiDefinitionService; import io.metersphere.api.service.ApiDefinitionService;
import io.metersphere.sdk.constants.PermissionConstants; import io.metersphere.sdk.constants.PermissionConstants;
import io.metersphere.sdk.log.annotation.Log; import io.metersphere.sdk.log.annotation.Log;
import io.metersphere.sdk.log.constants.OperationLogModule;
import io.metersphere.sdk.log.constants.OperationLogType; import io.metersphere.sdk.log.constants.OperationLogType;
import io.metersphere.sdk.util.PageUtils;
import io.metersphere.sdk.util.Pager;
import io.metersphere.validation.groups.Created; import io.metersphere.validation.groups.Created;
import io.metersphere.validation.groups.Updated;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions; import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
@ -32,25 +26,40 @@ public class ApiDefinitionController {
@PostMapping(value = "/add", consumes = MediaType.APPLICATION_JSON_VALUE) @PostMapping(value = "/add", consumes = MediaType.APPLICATION_JSON_VALUE)
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_READ_ADD_API) @RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_READ_ADD_API)
@Log(type = OperationLogType.ADD, module = OperationLogModule.API_DEFINITION, projectId = "#request.projectId", details = "#request.name") // 添加接口Log示例
@Log(type = OperationLogType.ADD, expression = "#msClass.addLog(#request)", msClass = ApiDefinitionLogService.class)
public ApiDefinitionDTO add(@Validated({Created.class}) @RequestBody ApiDefinitionDTO request, public ApiDefinitionDTO add(@Validated({Created.class}) @RequestBody ApiDefinitionDTO request,
@RequestParam(value = "files") List<MultipartFile> bodyFiles) { @RequestParam(value = "files") List<MultipartFile> bodyFiles) {
return apiDefinitionService.create(request, bodyFiles); return apiDefinitionService.create(request, bodyFiles);
} }
@PostMapping(value = "/update", consumes = MediaType.APPLICATION_JSON_VALUE)
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_READ_ADD_API)
// 添加修改Log示例
@Log(type = OperationLogType.UPDATE, expression = "#msClass.updateLog(#request)", msClass = ApiDefinitionLogService.class)
public ApiDefinitionDTO update(@Validated({Updated.class}) @RequestBody ApiDefinitionDTO request) {
return request;
}
@PostMapping(value = "/batch-update", consumes = MediaType.APPLICATION_JSON_VALUE)
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_READ_ADD_API)
// 添加修改Log示例
@Log(type = OperationLogType.UPDATE, expression = "#msClass.batchUpdateLog(#ids)", msClass = ApiDefinitionLogService.class)
public ApiDefinitionDTO batchUpdate(@RequestBody List<String> ids) {
return null;
}
@PostMapping(value = "/delete")
@RequiresPermissions(PermissionConstants.PROJECT_API_REPORT_READ_DELETE)
@Log(type = OperationLogType.DELETE, expression = "#msClass.delLog(#id)", msClass = ApiDefinitionLogService.class)
public void batchDelete(@RequestBody String id) {
}
@PostMapping(value = "/batch-del") @PostMapping(value = "/batch-del")
@RequiresPermissions(PermissionConstants.PROJECT_API_REPORT_READ_DELETE) @RequiresPermissions(PermissionConstants.PROJECT_API_REPORT_READ_DELETE)
@Log(isBatch = true, isBefore = true, details = "#msClass.getLogs(#ids)", msClass = ApiDefinitionService.class) @Log(type = OperationLogType.DELETE, expression = "#msClass.batchDelLog(#ids)", msClass = ApiDefinitionLogService.class)
public void batchDelete(@RequestBody List<String> ids) { public void batchDelete(@RequestBody List<String> ids) {
apiDefinitionService.batchDelete(ids); apiDefinitionService.batchDelete(ids);
} }
@PostMapping(value = "/page")
@RequiresPermissions(PermissionConstants.PROJECT_API_DEFINITION_READ)
public Pager<List<ApiDefinition>> list(@Validated @RequestBody ListRequestDTO request) {
Page<Object> page = PageHelper.startPage(request.getCurrent(), request.getPageSize(),
StringUtils.isNotBlank(request.getOrderColumn()) ? request.getOrderColumn() : "create_time desc");
return PageUtils.setPageInfo(page, apiDefinitionService.list(request));
}
} }

View File

@ -0,0 +1,148 @@
package io.metersphere.api.service;
import io.metersphere.api.domain.ApiDefinition;
import io.metersphere.api.domain.ApiDefinitionExample;
import io.metersphere.api.dto.definition.ApiDefinitionDTO;
import io.metersphere.api.mapper.ApiDefinitionMapper;
import io.metersphere.constants.HttpMethodConstants;
import io.metersphere.sdk.dto.LogDTO;
import io.metersphere.sdk.log.constants.OperationLogModule;
import io.metersphere.sdk.log.constants.OperationLogType;
import io.metersphere.sdk.util.JSON;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
@Service
public class ApiDefinitionLogService {
@Resource
private ApiDefinitionMapper apiDefinitionMapper;
/**
* 添加接口日志
*
* @param request
* @return
*/
public LogDTO addLog(ApiDefinitionDTO request) {
LogDTO dto = new LogDTO(
request.getProjectId(),
request.getId(),
request.getCreateUser(),
OperationLogType.ADD.name(),
OperationLogModule.API_DEFINITION,
request.getName());
dto.setPath("/api/definition/add");
dto.setMethod(HttpMethodConstants.POST.name());
dto.setOriginalValue(JSON.toJSONBytes(request));
return dto;
}
/**
* 修改接口日志
*
* @param request
* @return
*/
public LogDTO updateLog(ApiDefinitionDTO request) {
ApiDefinition apiDefinition = apiDefinitionMapper.selectByPrimaryKey(request.getId());
LogDTO dto = new LogDTO(
request.getProjectId(),
request.getId(),
request.getCreateUser(),
OperationLogType.UPDATE.name(),
OperationLogModule.API_DEFINITION,
request.getName());
dto.setPath("/api/definition/update");
dto.setMethod(HttpMethodConstants.POST.name());
if (apiDefinition == null) {
return dto;
}
dto.setOriginalValue(JSON.toJSONBytes(apiDefinition));
return dto;
}
/**
* 删除接口日志
*
* @param request
* @return
*/
public LogDTO delLog(ApiDefinitionDTO request) {
ApiDefinition apiDefinition = apiDefinitionMapper.selectByPrimaryKey(request.getId());
LogDTO dto = new LogDTO(
request.getProjectId(),
request.getId(),
request.getCreateUser(),
OperationLogType.DELETE.name(),
OperationLogModule.API_DEFINITION,
request.getName());
dto.setPath("/api/definition/delete");
dto.setMethod(HttpMethodConstants.POST.name());
if (apiDefinition == null) {
return dto;
}
dto.setOriginalValue(JSON.toJSONBytes(apiDefinition));
return dto;
}
/**
* 批量删除接口日志
*
* @return
*/
public List<LogDTO> batchDelLog(List<String> ids) {
ApiDefinitionExample example = new ApiDefinitionExample();
example.createCriteria().andIdIn(ids);
List<ApiDefinition> apiDefinitions = apiDefinitionMapper.selectByExample(example);
List<LogDTO> dtoList = new ArrayList<>();
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-delete");
dto.setMethod(HttpMethodConstants.POST.name());
dto.setOriginalValue(JSON.toJSONBytes(item));
dtoList.add(dto);
});
return dtoList;
}
/**
* 批量更新接口日志
* @return
*/
public List<LogDTO> batchUpdateLog(List<String> ids) {
ApiDefinitionExample example = new ApiDefinitionExample();
example.createCriteria().andIdIn(ids);
List<ApiDefinition> apiDefinitions = apiDefinitionMapper.selectByExample(example);
List<LogDTO> dtoList = new ArrayList<>();
apiDefinitions.forEach(item -> {
LogDTO dto = new LogDTO(
item.getProjectId(),
item.getId(),
item.getCreateUser(),
OperationLogType.UPDATE.name(),
OperationLogModule.API_DEFINITION,
item.getName());
dto.setPath("/api/definition/batch-update");
dto.setMethod(HttpMethodConstants.POST.name());
dto.setOriginalValue(JSON.toJSONBytes(item));
dtoList.add(dto);
});
return dtoList;
}
}

View File

@ -5,19 +5,13 @@ import io.metersphere.api.domain.ApiDefinitionExample;
import io.metersphere.api.dto.definition.ApiDefinitionDTO; import io.metersphere.api.dto.definition.ApiDefinitionDTO;
import io.metersphere.api.dto.definition.ListRequestDTO; import io.metersphere.api.dto.definition.ListRequestDTO;
import io.metersphere.api.mapper.ApiDefinitionMapper; import io.metersphere.api.mapper.ApiDefinitionMapper;
import io.metersphere.sdk.log.constants.OperationLogModule;
import io.metersphere.sdk.log.constants.OperationLogType;
import io.metersphere.system.domain.OperationLog;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID;
@Service @Service
public class ApiDefinitionService { public class ApiDefinitionService {
@ -53,31 +47,4 @@ public class ApiDefinitionService {
public void batchDelete(List<String> ids) { public void batchDelete(List<String> ids) {
} }
/**
* 批量操作日志由切面触发
*
* @param ids
*/
public List<OperationLog> getLogs(List<String> ids) {
if (CollectionUtils.isEmpty(ids)) {
return new ArrayList<>();
}
List<OperationLog> logs = new ArrayList<>();
ApiDefinitionExample example = new ApiDefinitionExample();
example.createCriteria().andIdIn(ids);
List<ApiDefinition> definitions = apiDefinitionMapper.selectByExample(example);
definitions.forEach(definition -> {
OperationLog log = new OperationLog();
log.setId(UUID.randomUUID().toString());
log.setCreateUser(definition.getUpdateUser());
log.setProjectId(definition.getProjectId());
log.setType(OperationLogType.DELETE.name());
log.setModule(OperationLogModule.API_DEFINITION);
log.setSourceId(definition.getId());
log.setDetails(definition.getName());
logs.add(log);
});
return logs;
}
} }

View File

@ -1,24 +1,17 @@
package io.metersphere.api.controller; package io.metersphere.api.controller;
import com.jayway.jsonpath.JsonPath; import com.jayway.jsonpath.JsonPath;
import io.metersphere.api.domain.ApiDefinition;
import io.metersphere.api.dto.definition.ApiDefinitionDTO; import io.metersphere.api.dto.definition.ApiDefinitionDTO;
import io.metersphere.api.dto.definition.ListRequestDTO;
import io.metersphere.sdk.constants.SessionConstants; import io.metersphere.sdk.constants.SessionConstants;
import io.metersphere.sdk.controller.handler.ResultHolder;
import io.metersphere.sdk.util.JSON; import io.metersphere.sdk.util.JSON;
import io.metersphere.sdk.util.LogUtils; import io.metersphere.sdk.util.LogUtils;
import io.metersphere.sdk.util.Pager;
import io.metersphere.utils.JsonUtils; import io.metersphere.utils.JsonUtils;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.junit.jupiter.api.*; import org.junit.jupiter.api.*;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.mock.web.MockMultipartFile; import org.springframework.mock.web.MockMultipartFile;
import org.springframework.test.context.jdbc.Sql;
import org.springframework.test.context.jdbc.SqlConfig;
import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
@ -90,86 +83,69 @@ public class ApiDefinitionControllerTests {
.andExpect(jsonPath("$.data.id").value("test-api-id")); .andExpect(jsonPath("$.data.id").value("test-api-id"));
} }
//正常接口获取
@Test @Test
@Sql(scripts = {"/sql/init_api_definition.sql"},
config = @SqlConfig(encoding = "utf-8", transactionMode = SqlConfig.TransactionMode.ISOLATED),
executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD)
@Order(2) @Order(2)
public void testPageSuccess() throws Exception { public void testUpdate() throws Exception {
int pageSize = 10; LogUtils.info("delete api test");
int current = 1; ApiDefinitionDTO request = new ApiDefinitionDTO();
ListRequestDTO request = new ListRequestDTO(); // 补充属性内容
request.setCurrent(current); request.setId("test-api-id");
request.setPageSize(pageSize); request.setCreateUser("test-user");
request.setCreateTime(System.currentTimeMillis());
request.setUpdateUser("test-api-id");
request.setUpdateTime(System.currentTimeMillis());
request.setProjectId("test-project-id"); request.setProjectId("test-project-id");
request.setName("test-api-name");
MvcResult mvcResult = mockMvc.perform(MockMvcRequestBuilders.multipart(prefix + "/page") request.setMethod("test-api-method");
request.setPath("test-api-path");
request.setProtocol("test-api-protocol");
request.setPos(1l);
request.setLatest(true);
request.setSyncEnable(true);
request.setStatus("test-api-status");
request.setVersionId("test-api-version");
request.setDeleted(false);
mockMvc.perform(MockMvcRequestBuilders.multipart(prefix + "/update")
.contentType(MediaType.APPLICATION_JSON_VALUE) .contentType(MediaType.APPLICATION_JSON_VALUE)
.content(JsonUtils.toJSONString(request)) .content(JSON.toJSONString(request))
.header(SessionConstants.HEADER_TOKEN, sessionId) .header(SessionConstants.HEADER_TOKEN, sessionId)
.header(SessionConstants.CSRF_TOKEN, csrfToken)) .header(SessionConstants.CSRF_TOKEN, csrfToken))
.andExpect(status().isOk()) .andExpect(status().isOk());
.andReturn();
MockHttpServletResponse mockResponse = mvcResult.getResponse();
String returnData = mockResponse.getContentAsString();
ResultHolder resultHolder = JsonUtils.parseObject(returnData, ResultHolder.class);
//返回请求正常
Assertions.assertNotNull(resultHolder);
Pager<ApiDefinition> returnPager = JSON.parseObject(JSON.toJSONString(resultHolder.getData()), Pager.class);
//返回值不为空
Assertions.assertNotNull(returnPager);
//返回值的页码和当前页码相同
Assertions.assertEquals(returnPager.getCurrent(), current);
//返回的数据量不超过规定要返回的数据量相同
Assertions.assertTrue(((List<ApiDefinition>) returnPager.getList()).size() <= pageSize);
} }
//没有传入必填值
@Test @Test
@Order(3) @Order(2)
public void testPageError() throws Exception { public void testBatchUpdate() throws Exception {
// projectId为空 LogUtils.info("delete api test");
ListRequestDTO request = new ListRequestDTO(); List<String> tests = new ArrayList<>();
request.setCurrent(1); tests.add("test-api-id");
request.setPageSize(20);
mockMvc.perform(MockMvcRequestBuilders.multipart(prefix + "/page")
.contentType(MediaType.APPLICATION_JSON_VALUE)
.content(JsonUtils.toJSONString(request))
.header(SessionConstants.HEADER_TOKEN, sessionId)
.header(SessionConstants.CSRF_TOKEN, csrfToken))
.andExpect(status().isBadRequest());
//pageSize为空 mockMvc.perform(MockMvcRequestBuilders.multipart(prefix + "/batch-update")
request = new ListRequestDTO();
request.setCurrent(1);
request.setProjectId("test-project-id");
mockMvc.perform(MockMvcRequestBuilders.multipart(prefix + "/page")
.contentType(MediaType.APPLICATION_JSON_VALUE) .contentType(MediaType.APPLICATION_JSON_VALUE)
.content(JsonUtils.toJSONString(request)) .content(JSON.toJSONString(tests))
.header(SessionConstants.HEADER_TOKEN, sessionId) .header(SessionConstants.HEADER_TOKEN, sessionId)
.header(SessionConstants.CSRF_TOKEN, csrfToken)) .header(SessionConstants.CSRF_TOKEN, csrfToken))
.andExpect(status().isBadRequest()); .andExpect(status().isOk());
//current为空
request = new ListRequestDTO();
request.setPageSize(20);
request.setProjectId("test-project-id");
mockMvc.perform(MockMvcRequestBuilders.multipart(prefix + "/page")
.contentType(MediaType.APPLICATION_JSON_VALUE)
.content(JsonUtils.toJSONString(request))
.header(SessionConstants.HEADER_TOKEN, sessionId)
.header(SessionConstants.CSRF_TOKEN, csrfToken))
.andExpect(status().isBadRequest());
} }
@Test @Test
@Order(4) @Order(4)
public void testDel() throws Exception {
LogUtils.info("delete api test");
mockMvc.perform(MockMvcRequestBuilders.multipart(prefix + "/delete")
.contentType(MediaType.APPLICATION_JSON_VALUE)
.content("test-api-id")
.header(SessionConstants.HEADER_TOKEN, sessionId)
.header(SessionConstants.CSRF_TOKEN, csrfToken))
.andExpect(status().isOk());
}
@Test
@Order(5)
public void testBatchDel() throws Exception { public void testBatchDel() throws Exception {
LogUtils.info("delete api test"); LogUtils.info("delete api test");
List<String> tests = new ArrayList<>(); List<String> tests = new ArrayList<>();
@ -183,4 +159,5 @@ public class ApiDefinitionControllerTests {
.andExpect(status().isOk()); .andExpect(status().isOk());
} }
} }

View File

@ -5,12 +5,12 @@ import com.github.pagehelper.PageHelper;
import io.metersphere.sdk.constants.PermissionConstants; import io.metersphere.sdk.constants.PermissionConstants;
import io.metersphere.sdk.dto.BasePageRequest; import io.metersphere.sdk.dto.BasePageRequest;
import io.metersphere.sdk.log.annotation.Log; import io.metersphere.sdk.log.annotation.Log;
import io.metersphere.sdk.log.constants.OperationLogModule;
import io.metersphere.sdk.log.constants.OperationLogType; import io.metersphere.sdk.log.constants.OperationLogType;
import io.metersphere.sdk.util.PageUtils; import io.metersphere.sdk.util.PageUtils;
import io.metersphere.sdk.util.Pager; import io.metersphere.sdk.util.Pager;
import io.metersphere.system.domain.AuthSource; import io.metersphere.system.domain.AuthSource;
import io.metersphere.system.request.AuthSourceRequest; import io.metersphere.system.request.AuthSourceRequest;
import io.metersphere.system.service.AuthSourceLogService;
import io.metersphere.system.service.AuthSourceService; import io.metersphere.system.service.AuthSourceService;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
@ -39,8 +39,7 @@ public class AuthSourceController {
@PostMapping("/add") @PostMapping("/add")
@Operation(summary = "新增认证设置") @Operation(summary = "新增认证设置")
@RequiresPermissions(PermissionConstants.SYSTEM_SETTING_READ_CREAT) @RequiresPermissions(PermissionConstants.SYSTEM_SETTING_READ_CREAT)
@Log(type = OperationLogType.ADD, module = OperationLogModule.SYSTEM_PARAMETER_SETTING, @Log(type = OperationLogType.ADD, expression = "#msClass.addLog(#authSource)", msClass = AuthSourceLogService.class)
details = "认证设置")
public void add(@Validated @RequestBody AuthSourceRequest authSource) { public void add(@Validated @RequestBody AuthSourceRequest authSource) {
authSourceService.addAuthSource(authSource); authSourceService.addAuthSource(authSource);
} }
@ -48,8 +47,7 @@ public class AuthSourceController {
@PostMapping("/update") @PostMapping("/update")
@Operation(summary = "更新认证设置") @Operation(summary = "更新认证设置")
@RequiresPermissions(PermissionConstants.SYSTEM_SETTING_READ_UPDATE) @RequiresPermissions(PermissionConstants.SYSTEM_SETTING_READ_UPDATE)
@Log(type = OperationLogType.UPDATE, module = OperationLogModule.SYSTEM_PARAMETER_SETTING, @Log(type = OperationLogType.UPDATE, expression = "#msClass.updateLog(#authSource)", msClass = AuthSourceLogService.class)
details = "认证设置", sourceId = "#authSource.id")
public void update(@Validated @RequestBody AuthSourceRequest authSource) { public void update(@Validated @RequestBody AuthSourceRequest authSource) {
authSourceService.updateAuthSource(authSource); authSourceService.updateAuthSource(authSource);
} }
@ -64,8 +62,7 @@ public class AuthSourceController {
@GetMapping("/delete/{id}") @GetMapping("/delete/{id}")
@Operation(summary = "删除认证设置") @Operation(summary = "删除认证设置")
@RequiresPermissions(PermissionConstants.SYSTEM_SETTING_READ_DELETE) @RequiresPermissions(PermissionConstants.SYSTEM_SETTING_READ_DELETE)
@Log(type = OperationLogType.DELETE, module = OperationLogModule.SYSTEM_PARAMETER_SETTING, @Log(type = OperationLogType.DELETE, expression = "#msClass.deleteLog(#id)", msClass = AuthSourceLogService.class)
details = "认证设置", sourceId = "#id")
public void delete(@PathVariable(value = "id") String id) { public void delete(@PathVariable(value = "id") String id) {
authSourceService.deleteAuthSource(id); authSourceService.deleteAuthSource(id);
} }
@ -74,8 +71,7 @@ public class AuthSourceController {
@GetMapping("/update/{authId}/status/{status}") @GetMapping("/update/{authId}/status/{status}")
@Operation(summary = "更新状态") @Operation(summary = "更新状态")
@RequiresPermissions(PermissionConstants.SYSTEM_SETTING_READ_UPDATE) @RequiresPermissions(PermissionConstants.SYSTEM_SETTING_READ_UPDATE)
@Log(type = OperationLogType.UPDATE, module = OperationLogModule.SYSTEM_PARAMETER_SETTING, @Log(type = OperationLogType.UPDATE, expression = "#msClass.updateLog(#authId)", msClass = AuthSourceLogService.class)
details = "认证设置", sourceId = "#authSource.authId")
public void updateStatus(@PathVariable(value = "authId") String authId, @PathVariable("status") String status) { public void updateStatus(@PathVariable(value = "authId") String authId, @PathVariable("status") String status) {
authSourceService.updateStatus(authId, status); authSourceService.updateStatus(authId, status);
} }

View File

@ -5,11 +5,11 @@ import io.metersphere.sdk.dto.PermissionDefinitionItem;
import io.metersphere.sdk.dto.request.PermissionSettingUpdateRequest; import io.metersphere.sdk.dto.request.PermissionSettingUpdateRequest;
import io.metersphere.sdk.dto.request.UserRoleUpdateRequest; import io.metersphere.sdk.dto.request.UserRoleUpdateRequest;
import io.metersphere.sdk.log.annotation.Log; import io.metersphere.sdk.log.annotation.Log;
import io.metersphere.sdk.log.constants.OperationLogModule;
import io.metersphere.sdk.log.constants.OperationLogType; import io.metersphere.sdk.log.constants.OperationLogType;
import io.metersphere.sdk.util.BeanUtils; import io.metersphere.sdk.util.BeanUtils;
import io.metersphere.sdk.util.SessionUtils; import io.metersphere.sdk.util.SessionUtils;
import io.metersphere.system.domain.UserRole; import io.metersphere.system.domain.UserRole;
import io.metersphere.system.service.GlobalUserRoleLogService;
import io.metersphere.system.service.GlobalUserRoleService; import io.metersphere.system.service.GlobalUserRoleService;
import io.metersphere.validation.groups.Created; import io.metersphere.validation.groups.Created;
import io.metersphere.validation.groups.Updated; import io.metersphere.validation.groups.Updated;
@ -51,8 +51,7 @@ public class GlobalUserRoleController {
@PostMapping("/permission/update") @PostMapping("/permission/update")
@Operation(summary = "编辑全局用户组对应的权限配置") @Operation(summary = "编辑全局用户组对应的权限配置")
@RequiresPermissions(PermissionConstants.SYSTEM_USER_ROLE_UPDATE) @RequiresPermissions(PermissionConstants.SYSTEM_USER_ROLE_UPDATE)
@Log(type = OperationLogType.UPDATE, module = OperationLogModule.SYSTEM_USER_ROLE, @Log(type = OperationLogType.UPDATE, expression = "#msClass.updateLog(#request)", msClass = GlobalUserRoleLogService.class)
details = "#msClass.getLogDetails(#request.userRoleId)", msClass = GlobalUserRoleService.class)
public void updatePermissionSetting(@Validated @RequestBody PermissionSettingUpdateRequest request) { public void updatePermissionSetting(@Validated @RequestBody PermissionSettingUpdateRequest request) {
globalUserRoleService.updatePermissionSetting(request); globalUserRoleService.updatePermissionSetting(request);
} }
@ -60,7 +59,7 @@ public class GlobalUserRoleController {
@PostMapping("/add") @PostMapping("/add")
@Operation(summary = "添加自定义全局用户组") @Operation(summary = "添加自定义全局用户组")
@RequiresPermissions(PermissionConstants.SYSTEM_USER_ROLE_ADD) @RequiresPermissions(PermissionConstants.SYSTEM_USER_ROLE_ADD)
@Log(type = OperationLogType.ADD, module = OperationLogModule.SYSTEM_USER_ROLE, details = "#request.name") @Log(type = OperationLogType.ADD, expression = "#msClass.addLog(#request)", msClass = GlobalUserRoleLogService.class)
public UserRole add(@Validated({Created.class}) @RequestBody UserRoleUpdateRequest request) { public UserRole add(@Validated({Created.class}) @RequestBody UserRoleUpdateRequest request) {
UserRole userRole = new UserRole(); UserRole userRole = new UserRole();
userRole.setCreateUser(SessionUtils.getUserId()); userRole.setCreateUser(SessionUtils.getUserId());
@ -71,8 +70,7 @@ public class GlobalUserRoleController {
@PostMapping("/update") @PostMapping("/update")
@Operation(summary = "更新自定义全局用户组") @Operation(summary = "更新自定义全局用户组")
@RequiresPermissions(PermissionConstants.SYSTEM_USER_ROLE_UPDATE) @RequiresPermissions(PermissionConstants.SYSTEM_USER_ROLE_UPDATE)
@Log(type = OperationLogType.UPDATE, module = OperationLogModule.SYSTEM_USER_ROLE, @Log(type = OperationLogType.UPDATE, expression = "#msClass.updateLog(#request)", msClass = GlobalUserRoleLogService.class)
sourceId = "#request.id", details = "#request.name")
public UserRole update(@Validated({Updated.class}) @RequestBody UserRoleUpdateRequest request) { public UserRole update(@Validated({Updated.class}) @RequestBody UserRoleUpdateRequest request) {
UserRole userRole = new UserRole(); UserRole userRole = new UserRole();
BeanUtils.copyBean(userRole, request); BeanUtils.copyBean(userRole, request);
@ -82,8 +80,7 @@ public class GlobalUserRoleController {
@GetMapping("/delete/{id}") @GetMapping("/delete/{id}")
@Operation(summary = "删除自定义全局用户组") @Operation(summary = "删除自定义全局用户组")
@RequiresPermissions(PermissionConstants.SYSTEM_USER_ROLE_DELETE) @RequiresPermissions(PermissionConstants.SYSTEM_USER_ROLE_DELETE)
@Log(isBefore = true, type = OperationLogType.DELETE, module = OperationLogModule.SYSTEM_USER_ROLE, @Log(type = OperationLogType.DELETE, expression = "#msClass.deleteLog(#id)", msClass = GlobalUserRoleLogService.class)
sourceId = "#id", details = "#msClass.getLogDetails(#id)", msClass = GlobalUserRoleService.class)
public void delete(@PathVariable String id) { public void delete(@PathVariable String id) {
globalUserRoleService.delete(id); globalUserRoleService.delete(id);
} }

View File

@ -6,7 +6,6 @@ import io.metersphere.sdk.constants.PermissionConstants;
import io.metersphere.sdk.dto.UserRoleRelationUserDTO; import io.metersphere.sdk.dto.UserRoleRelationUserDTO;
import io.metersphere.sdk.dto.request.GlobalUserRoleRelationUpdateRequest; import io.metersphere.sdk.dto.request.GlobalUserRoleRelationUpdateRequest;
import io.metersphere.sdk.log.annotation.Log; import io.metersphere.sdk.log.annotation.Log;
import io.metersphere.sdk.log.constants.OperationLogModule;
import io.metersphere.sdk.log.constants.OperationLogType; import io.metersphere.sdk.log.constants.OperationLogType;
import io.metersphere.sdk.util.BeanUtils; import io.metersphere.sdk.util.BeanUtils;
import io.metersphere.sdk.util.PageUtils; import io.metersphere.sdk.util.PageUtils;
@ -14,6 +13,7 @@ import io.metersphere.sdk.util.Pager;
import io.metersphere.sdk.util.SessionUtils; import io.metersphere.sdk.util.SessionUtils;
import io.metersphere.system.domain.UserRoleRelation; import io.metersphere.system.domain.UserRoleRelation;
import io.metersphere.system.dto.request.GlobalUserRoleRelationQueryRequest; import io.metersphere.system.dto.request.GlobalUserRoleRelationQueryRequest;
import io.metersphere.system.service.GlobalUserRoleRelationLogService;
import io.metersphere.system.service.GlobalUserRoleRelationService; import io.metersphere.system.service.GlobalUserRoleRelationService;
import io.metersphere.validation.groups.Created; import io.metersphere.validation.groups.Created;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
@ -48,7 +48,7 @@ public class GlobalUserRoleRelationController {
@PostMapping("/add") @PostMapping("/add")
@Operation(summary = "创建全局用户组和用户的关联关系") @Operation(summary = "创建全局用户组和用户的关联关系")
@RequiresPermissions(PermissionConstants.SYSTEM_USER_ROLE_RELATION_ADD) @RequiresPermissions(PermissionConstants.SYSTEM_USER_ROLE_RELATION_ADD)
@Log(type = OperationLogType.ADD, module = OperationLogModule.SYSTEM_USER_ROLE_RELATION, details = "#request.name") @Log(type = OperationLogType.ADD, expression = "#msClass.addLog(#request)", msClass = GlobalUserRoleRelationLogService.class)
public UserRoleRelation add(@Validated({Created.class}) @RequestBody GlobalUserRoleRelationUpdateRequest request) { public UserRoleRelation add(@Validated({Created.class}) @RequestBody GlobalUserRoleRelationUpdateRequest request) {
UserRoleRelation userRoleRelation = new UserRoleRelation(); UserRoleRelation userRoleRelation = new UserRoleRelation();
BeanUtils.copyBean(userRoleRelation, request); BeanUtils.copyBean(userRoleRelation, request);
@ -59,8 +59,7 @@ public class GlobalUserRoleRelationController {
@GetMapping("/delete/{id}") @GetMapping("/delete/{id}")
@Operation(summary = "删除全局用户组和用户的关联关系") @Operation(summary = "删除全局用户组和用户的关联关系")
@RequiresPermissions(PermissionConstants.SYSTEM_USER_ROLE_RELATION_DELETE) @RequiresPermissions(PermissionConstants.SYSTEM_USER_ROLE_RELATION_DELETE)
@Log(isBefore = true, type = OperationLogType.DELETE, sourceId = "#id", module = OperationLogModule.SYSTEM_USER_ROLE_RELATION, @Log(type = OperationLogType.DELETE, expression = "#msClass.deleteLog(#id)", msClass = GlobalUserRoleRelationLogService.class)
details = "#msClass.getLogDetails(#id)", msClass = GlobalUserRoleRelationService.class)
public void delete(@PathVariable String id) { public void delete(@PathVariable String id) {
globalUserRoleRelationService.delete(id); globalUserRoleRelationService.delete(id);
} }

View File

@ -5,7 +5,6 @@ import io.metersphere.dto.BaseSystemConfigDTO;
import io.metersphere.sdk.constants.PermissionConstants; import io.metersphere.sdk.constants.PermissionConstants;
import io.metersphere.sdk.dto.EMailInfoDto; import io.metersphere.sdk.dto.EMailInfoDto;
import io.metersphere.sdk.log.annotation.Log; import io.metersphere.sdk.log.annotation.Log;
import io.metersphere.sdk.log.constants.OperationLogModule;
import io.metersphere.sdk.log.constants.OperationLogType; import io.metersphere.sdk.log.constants.OperationLogType;
import io.metersphere.sdk.service.SystemParameterService; import io.metersphere.sdk.service.SystemParameterService;
import io.metersphere.system.domain.SystemParameter; import io.metersphere.system.domain.SystemParameter;
@ -32,7 +31,7 @@ public class SystemParameterController {
@PostMapping("/save/base-info") @PostMapping("/save/base-info")
@Operation(summary = "保存基本信息") @Operation(summary = "保存基本信息")
@RequiresPermissions(value= {PermissionConstants.SYSTEM_SETTING_READ_UPDATE, PermissionConstants.SYSTEM_SETTING_READ_CREAT}, logical = Logical.OR) @RequiresPermissions(value= {PermissionConstants.SYSTEM_SETTING_READ_UPDATE, PermissionConstants.SYSTEM_SETTING_READ_CREAT}, logical = Logical.OR)
@Log(type = OperationLogType.UPDATE, module = OperationLogModule.SYSTEM_PARAMETER_SETTING, details = "基本配置", sourceId = "#systemParameter.get(0).paramKey") @Log(type = OperationLogType.ADD, expression = "#msClass.addLog(#systemParameter)", msClass = SystemParameterService.class)
public void saveBaseParameter(@Validated @RequestBody List<SystemParameter> systemParameter) { public void saveBaseParameter(@Validated @RequestBody List<SystemParameter> systemParameter) {
systemParameterService.saveBaseInfo(systemParameter); systemParameterService.saveBaseInfo(systemParameter);
} }
@ -57,7 +56,7 @@ public class SystemParameterController {
@PostMapping("/edit/email-info") @PostMapping("/edit/email-info")
@Operation(summary = "保存邮件信息") @Operation(summary = "保存邮件信息")
@RequiresPermissions(value= {PermissionConstants.SYSTEM_SETTING_READ_UPDATE, PermissionConstants.SYSTEM_SETTING_READ_CREAT}, logical = Logical.OR) @RequiresPermissions(value= {PermissionConstants.SYSTEM_SETTING_READ_UPDATE, PermissionConstants.SYSTEM_SETTING_READ_CREAT}, logical = Logical.OR)
@Log(type = OperationLogType.UPDATE, module = OperationLogModule.SYSTEM_PARAMETER_SETTING, details = "邮件配置", sourceId = "#systemParameter.get(0).paramKey") @Log(type = OperationLogType.UPDATE, expression = "#msClass.updateLog(#systemParameter)", msClass = SystemParameterService.class)
public void editEMailInfo(@Validated @RequestBody List<SystemParameter> systemParameter) { public void editEMailInfo(@Validated @RequestBody List<SystemParameter> systemParameter) {
systemParameterService.editEMailInfo(systemParameter); systemParameterService.editEMailInfo(systemParameter);
} }

View File

@ -9,7 +9,6 @@ import io.metersphere.sdk.dto.AddProjectRequest;
import io.metersphere.sdk.dto.ProjectDTO; import io.metersphere.sdk.dto.ProjectDTO;
import io.metersphere.sdk.dto.UpdateProjectRequest; import io.metersphere.sdk.dto.UpdateProjectRequest;
import io.metersphere.sdk.log.annotation.Log; import io.metersphere.sdk.log.annotation.Log;
import io.metersphere.sdk.log.constants.OperationLogModule;
import io.metersphere.sdk.log.constants.OperationLogType; import io.metersphere.sdk.log.constants.OperationLogType;
import io.metersphere.sdk.util.PageUtils; import io.metersphere.sdk.util.PageUtils;
import io.metersphere.sdk.util.Pager; import io.metersphere.sdk.util.Pager;
@ -18,6 +17,7 @@ import io.metersphere.system.dto.UserExtend;
import io.metersphere.system.request.ProjectAddMemberRequest; import io.metersphere.system.request.ProjectAddMemberRequest;
import io.metersphere.system.request.ProjectMemberRequest; import io.metersphere.system.request.ProjectMemberRequest;
import io.metersphere.system.request.ProjectRequest; import io.metersphere.system.request.ProjectRequest;
import io.metersphere.system.service.SystemProjectLogService;
import io.metersphere.system.service.SystemProjectService; import io.metersphere.system.service.SystemProjectService;
import io.metersphere.validation.groups.Created; import io.metersphere.validation.groups.Created;
import io.metersphere.validation.groups.Updated; import io.metersphere.validation.groups.Updated;
@ -39,7 +39,7 @@ public class SystemProjectController {
@PostMapping("/add") @PostMapping("/add")
@RequiresPermissions(PermissionConstants.SYSTEM_ORGANIZATION_PROJECT_READ_ADD) @RequiresPermissions(PermissionConstants.SYSTEM_ORGANIZATION_PROJECT_READ_ADD)
@Log(type = OperationLogType.ADD, module = OperationLogModule.SYSTEM_PROJECT, details = "#project.name") @Log(type = OperationLogType.ADD, expression = "#msClass.addLog(#project)", msClass = SystemProjectLogService.class)
@Operation(summary = "添加项目") @Operation(summary = "添加项目")
public Project addProject(@RequestBody @Validated({Created.class}) AddProjectRequest project) { public Project addProject(@RequestBody @Validated({Created.class}) AddProjectRequest project) {
return systemProjectService.add(project, SessionUtils.getUserId()); return systemProjectService.add(project, SessionUtils.getUserId());
@ -63,8 +63,7 @@ public class SystemProjectController {
} }
@PostMapping("/update") @PostMapping("/update")
@Log(type = OperationLogType.UPDATE, module = OperationLogModule.SYSTEM_PROJECT, @Log(type = OperationLogType.UPDATE, expression = "#msClass.updateLog(#project)", msClass = SystemProjectLogService.class)
sourceId = "#project.id", details = "#project.name")
@Operation(summary = "更新项目信息") @Operation(summary = "更新项目信息")
@RequiresPermissions(PermissionConstants.SYSTEM_ORGANIZATION_PROJECT_READ_UPDATE) @RequiresPermissions(PermissionConstants.SYSTEM_ORGANIZATION_PROJECT_READ_UPDATE)
public Project updateProject(@RequestBody @Validated({Updated.class}) UpdateProjectRequest project) { public Project updateProject(@RequestBody @Validated({Updated.class}) UpdateProjectRequest project) {
@ -74,16 +73,14 @@ public class SystemProjectController {
@GetMapping("/delete/{id}") @GetMapping("/delete/{id}")
@RequiresPermissions(PermissionConstants.SYSTEM_ORGANIZATION_PROJECT_READ_DELETE) @RequiresPermissions(PermissionConstants.SYSTEM_ORGANIZATION_PROJECT_READ_DELETE)
@Operation(summary = "删除项目") @Operation(summary = "删除项目")
@Log(isBefore = true, type = OperationLogType.DELETE, module = OperationLogModule.SYSTEM_PROJECT, @Log(type = OperationLogType.DELETE, expression = "#msClass.deleteLog(#id)", msClass = SystemProjectLogService.class)
details = "#msClass.getLogDetails(#id)", msClass = SystemProjectService.class, sourceId = "#id")
public int deleteProject(@PathVariable String id) { public int deleteProject(@PathVariable String id) {
return systemProjectService.delete(id, SessionUtils.getUserId()); return systemProjectService.delete(id, SessionUtils.getUserId());
} }
@GetMapping("/revoke/{id}") @GetMapping("/revoke/{id}")
@RequiresPermissions(PermissionConstants.SYSTEM_ORGANIZATION_PROJECT_READ_RECOVER) @RequiresPermissions(PermissionConstants.SYSTEM_ORGANIZATION_PROJECT_READ_RECOVER)
@Log(isBefore = true, type = OperationLogType.UPDATE, module = OperationLogModule.SYSTEM_PROJECT, @Log(type = OperationLogType.UPDATE, expression = "#msClass.updateLog(#project)", msClass = SystemProjectLogService.class)
details = "#msClass.getLogDetails(#id)", msClass = SystemProjectService.class, sourceId = "#id")
public int revokeProject(@PathVariable String id) { public int revokeProject(@PathVariable String id) {
return systemProjectService.revoke(id); return systemProjectService.revoke(id);
} }
@ -107,8 +104,7 @@ public class SystemProjectController {
@GetMapping("/remove-member/{projectId}/{userId}") @GetMapping("/remove-member/{projectId}/{userId}")
@Operation(summary = "移除项目成员") @Operation(summary = "移除项目成员")
@RequiresPermissions(PermissionConstants.SYSTEM_ORGANIZATION_PROJECT_READ_UPDATE) @RequiresPermissions(PermissionConstants.SYSTEM_ORGANIZATION_PROJECT_READ_UPDATE)
@Log(isBefore = true, type = OperationLogType.DELETE, module = OperationLogModule.SYSTEM_PROJECT_MEMBER, sourceId = "#projectId", @Log(type = OperationLogType.DELETE, expression = "#msClass.deleteLog(#projectId)", msClass = SystemProjectLogService.class)
details = "#msClass.getLogs(#userId)", msClass = SystemProjectService.class)
public int removeProjectMember(@PathVariable String projectId, @PathVariable String userId) { public int removeProjectMember(@PathVariable String projectId, @PathVariable String userId) {
return systemProjectService.removeProjectMember(projectId, userId); return systemProjectService.removeProjectMember(projectId, userId);
} }

View File

@ -3,18 +3,17 @@ package io.metersphere.system.controller;
import com.github.pagehelper.Page; import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageHelper;
import io.metersphere.sdk.constants.PermissionConstants; import io.metersphere.sdk.constants.PermissionConstants;
import io.metersphere.sdk.dto.QueryResourcePoolRequest;
import io.metersphere.sdk.dto.TestResourcePoolDTO; import io.metersphere.sdk.dto.TestResourcePoolDTO;
import io.metersphere.sdk.dto.TestResourcePoolRequest; import io.metersphere.sdk.dto.TestResourcePoolRequest;
import io.metersphere.sdk.log.annotation.Log; import io.metersphere.sdk.log.annotation.Log;
import io.metersphere.sdk.log.constants.OperationLogModule;
import io.metersphere.sdk.log.constants.OperationLogType; import io.metersphere.sdk.log.constants.OperationLogType;
import io.metersphere.sdk.service.TestResourcePoolService;
import io.metersphere.sdk.util.BeanUtils; import io.metersphere.sdk.util.BeanUtils;
import io.metersphere.sdk.util.PageUtils; import io.metersphere.sdk.util.PageUtils;
import io.metersphere.sdk.util.Pager; import io.metersphere.sdk.util.Pager;
import io.metersphere.sdk.util.SessionUtils; import io.metersphere.sdk.util.SessionUtils;
import io.metersphere.system.consul.CacheNode; import io.metersphere.system.consul.CacheNode;
import io.metersphere.sdk.dto.QueryResourcePoolRequest;
import io.metersphere.sdk.service.TestResourcePoolService;
import io.metersphere.system.domain.TestResourcePool; import io.metersphere.system.domain.TestResourcePool;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import org.apache.shiro.authz.annotation.RequiresPermissions; import org.apache.shiro.authz.annotation.RequiresPermissions;
@ -33,7 +32,7 @@ public class TestResourcePoolController {
@PostMapping("/add") @PostMapping("/add")
@RequiresPermissions(PermissionConstants.SYSTEM_TEST_RESOURCE_POOL_READ_ADD) @RequiresPermissions(PermissionConstants.SYSTEM_TEST_RESOURCE_POOL_READ_ADD)
@Log(type = OperationLogType.ADD, module = OperationLogModule.SYSTEM_TEST_RESOURCE_POOL, details = "#request.name") @Log(type = OperationLogType.ADD, expression = "#msClass.addLog(#request)", msClass = TestResourcePoolService.class)
public TestResourcePool addTestResourcePool(@Validated @RequestBody TestResourcePoolRequest request) { public TestResourcePool addTestResourcePool(@Validated @RequestBody TestResourcePoolRequest request) {
String userId = SessionUtils.getUserId(); String userId = SessionUtils.getUserId();
TestResourcePoolDTO testResourcePool = new TestResourcePoolDTO(); TestResourcePoolDTO testResourcePool = new TestResourcePoolDTO();
@ -46,8 +45,7 @@ public class TestResourcePoolController {
@GetMapping("/delete/{poolId}") @GetMapping("/delete/{poolId}")
@CacheNode // 把监控节点缓存起来 @CacheNode // 把监控节点缓存起来
@RequiresPermissions(PermissionConstants.SYSTEM_TEST_RESOURCE_POOL_READ_DELETE) @RequiresPermissions(PermissionConstants.SYSTEM_TEST_RESOURCE_POOL_READ_DELETE)
@Log(isBefore = true, type = OperationLogType.DELETE, module = OperationLogModule.SYSTEM_TEST_RESOURCE_POOL, @Log(type = OperationLogType.DELETE, expression = "#msClass.deleteLog(#testResourcePoolId)", msClass = TestResourcePoolService.class)
details = "#msClass.getLogDetails(#testResourcePoolId)", msClass = TestResourcePoolService.class)
public void deleteTestResourcePool(@PathVariable(value = "poolId") String testResourcePoolId) { public void deleteTestResourcePool(@PathVariable(value = "poolId") String testResourcePoolId) {
testResourcePoolService.deleteTestResourcePool(testResourcePoolId); testResourcePoolService.deleteTestResourcePool(testResourcePoolId);
} }
@ -55,8 +53,7 @@ public class TestResourcePoolController {
@PostMapping("/update") @PostMapping("/update")
@CacheNode // 把监控节点缓存起来 @CacheNode // 把监控节点缓存起来
@RequiresPermissions(PermissionConstants.SYSTEM_TEST_RESOURCE_POOL_READ_UPDATE) @RequiresPermissions(PermissionConstants.SYSTEM_TEST_RESOURCE_POOL_READ_UPDATE)
@Log(type = OperationLogType.UPDATE, module = OperationLogModule.SYSTEM_TEST_RESOURCE_POOL, @Log(type = OperationLogType.UPDATE, expression = "#msClass.updateLog(#request)", msClass = TestResourcePoolService.class)
sourceId = "#request.id", details = "#request.name")
public void updateTestResourcePool(@Validated @RequestBody TestResourcePoolRequest request) { public void updateTestResourcePool(@Validated @RequestBody TestResourcePoolRequest request) {
TestResourcePoolDTO testResourcePool = new TestResourcePoolDTO(); TestResourcePoolDTO testResourcePool = new TestResourcePoolDTO();
BeanUtils.copyBean(testResourcePool, request); BeanUtils.copyBean(testResourcePool, request);

View File

@ -8,7 +8,6 @@ import io.metersphere.sdk.constants.UserSourceEnum;
import io.metersphere.sdk.dto.BasePageRequest; import io.metersphere.sdk.dto.BasePageRequest;
import io.metersphere.sdk.dto.UserDTO; import io.metersphere.sdk.dto.UserDTO;
import io.metersphere.sdk.log.annotation.Log; import io.metersphere.sdk.log.annotation.Log;
import io.metersphere.sdk.log.constants.OperationLogModule;
import io.metersphere.sdk.log.constants.OperationLogType; import io.metersphere.sdk.log.constants.OperationLogType;
import io.metersphere.sdk.util.PageUtils; import io.metersphere.sdk.util.PageUtils;
import io.metersphere.sdk.util.Pager; import io.metersphere.sdk.util.Pager;
@ -61,8 +60,7 @@ public class UserController {
@PostMapping("/update") @PostMapping("/update")
@RequiresPermissions(PermissionConstants.SYSTEM_USER_READ_UPDATE) @RequiresPermissions(PermissionConstants.SYSTEM_USER_READ_UPDATE)
@Log(type = OperationLogType.UPDATE, module = OperationLogModule.SYSTEM_USER, @Log(type = OperationLogType.UPDATE, expression = "#msClass.updateLog(#request)", msClass = UserService.class)
sourceId = "#request.id", details = "#request.name")
public UserEditRequest updateUser(@Validated({Updated.class}) @RequestBody UserEditRequest request) { public UserEditRequest updateUser(@Validated({Updated.class}) @RequestBody UserEditRequest request) {
return userService.updateUser(request, SessionUtils.getUserId()); return userService.updateUser(request, SessionUtils.getUserId());
} }
@ -89,8 +87,7 @@ public class UserController {
@PostMapping("/delete") @PostMapping("/delete")
@Log(isBefore = true, type = OperationLogType.DELETE, module = OperationLogModule.SYSTEM_USER, isBatch = true, @Log(type = OperationLogType.DELETE, expression = "#msClass.deleteLog(#userBatchProcessRequest)", msClass = UserService.class)
details = "#msClass.getLogs(#userBatchProcessRequest)", msClass = UserService.class)
@RequiresPermissions(PermissionConstants.SYSTEM_USER_READ_DELETE) @RequiresPermissions(PermissionConstants.SYSTEM_USER_READ_DELETE)
public UserBatchProcessResponse deleteUser(@Validated @RequestBody UserChangeEnableRequest userBatchProcessRequest) { public UserBatchProcessResponse deleteUser(@Validated @RequestBody UserChangeEnableRequest userBatchProcessRequest) {
return userService.deleteUser(userBatchProcessRequest.getUserIdList()); return userService.deleteUser(userBatchProcessRequest.getUserIdList());

View File

@ -0,0 +1,115 @@
package io.metersphere.system.service;
import io.metersphere.constants.HttpMethodConstants;
import io.metersphere.sdk.dto.LogDTO;
import io.metersphere.sdk.log.constants.OperationLogModule;
import io.metersphere.sdk.log.constants.OperationLogType;
import io.metersphere.sdk.util.JSON;
import io.metersphere.system.domain.AuthSource;
import io.metersphere.system.mapper.AuthSourceMapper;
import io.metersphere.system.request.AuthSourceRequest;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@Transactional(rollbackFor = Exception.class)
public class AuthSourceLogService {
@Resource
private AuthSourceMapper authSourceMapper;
private static final String PRE_URI = "/system/authsource";
/**
* 添加接口日志
*
* @param request
* @return
*/
public LogDTO addLog(AuthSourceRequest request) {
LogDTO dto = new LogDTO(
"system",
request.getId(),
null,
OperationLogType.ADD.name(),
OperationLogModule.SYSTEM_PARAMETER_SETTING,
request.getName());
dto.setPath(PRE_URI + "/add");
dto.setMethod(HttpMethodConstants.POST.name());
dto.setOriginalValue(JSON.toJSONBytes(request));
return dto;
}
/**
* 修改接口日志
*
* @param request
* @return
*/
public LogDTO updateLog(AuthSourceRequest request) {
AuthSource authSource = authSourceMapper.selectByPrimaryKey(request.getId());
if (authSource != null) {
LogDTO dto = new LogDTO(
"system",
request.getId(),
null,
OperationLogType.UPDATE.name(),
OperationLogModule.SYSTEM_PARAMETER_SETTING,
request.getName());
dto.setPath("/update");
dto.setMethod(HttpMethodConstants.POST.name());
dto.setOriginalValue(JSON.toJSONBytes(authSource));
return dto;
}
return null;
}
public LogDTO updateLog(String id) {
AuthSource authSource = authSourceMapper.selectByPrimaryKey(id);
if (authSource != null) {
LogDTO dto = new LogDTO(
"system",
id,
null,
OperationLogType.UPDATE.name(),
OperationLogModule.SYSTEM_PARAMETER_SETTING,
authSource.getName());
dto.setPath("/update");
dto.setMethod(HttpMethodConstants.POST.name());
dto.setOriginalValue(JSON.toJSONBytes(authSource));
return dto;
}
return null;
}
/**
* 删除接口日志
*
* @param id
* @return
*/
public LogDTO deleteLog(String id) {
AuthSource authSource = authSourceMapper.selectByPrimaryKey(id);
if (authSource == null) {
return null;
}
LogDTO dto = new LogDTO(
"system",
authSource.getId(),
null,
OperationLogType.DELETE.name(),
OperationLogModule.SYSTEM_PARAMETER_SETTING,
authSource.getName());
dto.setPath("/delete");
dto.setMethod(HttpMethodConstants.POST.name());
dto.setOriginalValue(JSON.toJSONBytes(authSource));
return dto;
}
}

View File

@ -0,0 +1,120 @@
package io.metersphere.system.service;
import io.metersphere.constants.HttpMethodConstants;
import io.metersphere.sdk.dto.LogDTO;
import io.metersphere.sdk.dto.request.PermissionSettingUpdateRequest;
import io.metersphere.sdk.dto.request.UserRoleUpdateRequest;
import io.metersphere.sdk.log.constants.OperationLogModule;
import io.metersphere.sdk.log.constants.OperationLogType;
import io.metersphere.sdk.service.BaseUserRoleService;
import io.metersphere.sdk.util.JSON;
import io.metersphere.system.domain.UserRole;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* 系统设置的接口增删改查都是针对全局用户组
*
* @author jianxing
* @date : 2023-6-8
*/
@Service
@Transactional(rollbackFor = Exception.class)
public class GlobalUserRoleLogService extends BaseUserRoleService {
@Resource
private BaseUserRoleService baseUserRoleService;
private static final String PRE_URI = "/user/role/global";
/**
* 添加接口日志
*
* @param request
* @return
*/
public LogDTO addLog(UserRoleUpdateRequest request) {
LogDTO dto = new LogDTO(
"system",
request.getId(),
null,
OperationLogType.ADD.name(),
OperationLogModule.SYSTEM_PROJECT,
request.getName());
dto.setPath(PRE_URI + "/permission/update");
dto.setMethod(HttpMethodConstants.POST.name());
dto.setOriginalValue(JSON.toJSONBytes(request));
return dto;
}
/**
* @param request
* @return
*/
public LogDTO updateLog(UserRoleUpdateRequest request) {
UserRole userRole = baseUserRoleService.get(request.getId());
if (userRole != null) {
LogDTO dto = new LogDTO(
"system",
userRole.getId(),
userRole.getCreateUser(),
OperationLogType.UPDATE.name(),
OperationLogModule.SYSTEM_PROJECT,
userRole.getName());
dto.setPath("/update");
dto.setMethod(HttpMethodConstants.POST.name());
dto.setOriginalValue(JSON.toJSONBytes(userRole));
return dto;
}
return null;
}
public LogDTO updateLog(PermissionSettingUpdateRequest request) {
UserRole userRole = get(request.getUserRoleId());
if (userRole != null) {
LogDTO dto = new LogDTO(
"system",
request.getUserRoleId(),
userRole.getCreateUser(),
OperationLogType.UPDATE.name(),
OperationLogModule.SYSTEM_PROJECT,
userRole.getName());
dto.setPath("/update");
dto.setMethod(HttpMethodConstants.POST.name());
dto.setOriginalValue(JSON.toJSONBytes(request));
return dto;
}
return null;
}
/**
* 删除接口日志
*
* @param id
* @return
*/
public LogDTO deleteLog(String id) {
UserRole userRole = baseUserRoleService.get(id);
if (userRole == null) {
return null;
}
LogDTO dto = new LogDTO(
"system",
userRole.getId(),
null,
OperationLogType.DELETE.name(),
OperationLogModule.SYSTEM_PROJECT,
userRole.getName());
dto.setPath("/delete");
dto.setMethod(HttpMethodConstants.POST.name());
dto.setOriginalValue(JSON.toJSONBytes(userRole));
return dto;
}
}

View File

@ -0,0 +1,73 @@
package io.metersphere.system.service;
import io.metersphere.constants.HttpMethodConstants;
import io.metersphere.sdk.dto.LogDTO;
import io.metersphere.sdk.dto.request.GlobalUserRoleRelationUpdateRequest;
import io.metersphere.sdk.log.constants.OperationLogModule;
import io.metersphere.sdk.log.constants.OperationLogType;
import io.metersphere.sdk.service.BaseUserRoleRelationService;
import io.metersphere.sdk.util.JSON;
import io.metersphere.system.domain.UserRoleRelation;
import io.metersphere.system.mapper.UserRoleRelationMapper;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
/**
* @author jianxing
* @date : 2023-6-12
*/
@Service
public class GlobalUserRoleRelationLogService extends BaseUserRoleRelationService {
@Resource
private UserRoleRelationMapper userRoleRelationMapper;
private static final String PRE_URI = "/user/role/relation/global";
/**
* 添加接口日志
*
* @param request
* @return
*/
public LogDTO addLog(GlobalUserRoleRelationUpdateRequest request) {
LogDTO dto = new LogDTO(
"system",
null,
null,
OperationLogType.ADD.name(),
OperationLogModule.SYSTEM_USER_ROLE_RELATION,
request.getUserId());
dto.setPath(PRE_URI + "/add");
dto.setMethod(HttpMethodConstants.POST.name());
dto.setOriginalValue(JSON.toJSONBytes(request));
return dto;
}
/**
* 删除接口日志
*
* @param id
* @return
*/
public LogDTO deleteLog(String id) {
UserRoleRelation userRoleRelation = userRoleRelationMapper.selectByPrimaryKey(id);
if (userRoleRelation != null) {
LogDTO dto = new LogDTO(
"system",
id,
userRoleRelation.getCreateUser(),
OperationLogType.DELETE.name(),
OperationLogModule.SYSTEM_USER_ROLE_RELATION,
userRoleRelation.getUserId());
dto.setPath("/delete");
dto.setMethod(HttpMethodConstants.POST.name());
dto.setOriginalValue(JSON.toJSONBytes(userRoleRelation));
return dto;
}
return null;
}
}

View File

@ -0,0 +1,112 @@
package io.metersphere.system.service;
import io.metersphere.constants.HttpMethodConstants;
import io.metersphere.project.domain.Project;
import io.metersphere.project.mapper.ProjectMapper;
import io.metersphere.sdk.dto.AddProjectRequest;
import io.metersphere.sdk.dto.LogDTO;
import io.metersphere.sdk.dto.UpdateProjectRequest;
import io.metersphere.sdk.log.constants.OperationLogModule;
import io.metersphere.sdk.log.constants.OperationLogType;
import io.metersphere.sdk.util.JSON;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@Transactional(rollbackFor = Exception.class)
public class SystemProjectLogService {
@Resource
private ProjectMapper projectMapper;
private static final String PRE_URI = "/system/project";
/**
* 添加接口日志
*
* @return
*/
public LogDTO addLog(AddProjectRequest project) {
LogDTO dto = new LogDTO(
"system",
null,
null,
OperationLogType.ADD.name(),
OperationLogModule.SYSTEM_USER_ROLE,
project.getName());
dto.setPath(PRE_URI + "/add");
dto.setMethod(HttpMethodConstants.POST.name());
dto.setOriginalValue(JSON.toJSONBytes(project));
return dto;
}
/**
* @param request
* @return
*/
public LogDTO updateLog(UpdateProjectRequest request) {
Project project = projectMapper.selectByPrimaryKey(request.getId());
if (project != null) {
LogDTO dto = new LogDTO(
"system",
project.getId(),
project.getCreateUser(),
OperationLogType.UPDATE.name(),
OperationLogModule.SYSTEM_USER_ROLE,
"编辑全局用户组对应的权限配置");
dto.setPath("/update");
dto.setMethod(HttpMethodConstants.POST.name());
dto.setOriginalValue(JSON.toJSONBytes(project));
return dto;
}
return null;
}
public LogDTO updateLog(String id) {
Project project = projectMapper.selectByPrimaryKey(id);
if (project != null) {
LogDTO dto = new LogDTO(
"system",
project.getId(),
project.getCreateUser(),
OperationLogType.UPDATE.name(),
OperationLogModule.SYSTEM_USER_ROLE,
"编辑全局用户组对应的权限配置");
dto.setPath("/revoke");
dto.setMethod(HttpMethodConstants.POST.name());
dto.setOriginalValue(JSON.toJSONBytes(project));
return dto;
}
return null;
}
/**
* 删除接口日志
*
* @param id
* @return
*/
public LogDTO deleteLog(String id) {
Project project = projectMapper.selectByPrimaryKey(id);
if (project != null) {
LogDTO dto = new LogDTO(
"system",
id,
project.getCreateUser(),
OperationLogType.DELETE.name(),
OperationLogModule.SYSTEM_USER_ROLE,
project.getName());
dto.setPath("/delete");
dto.setMethod(HttpMethodConstants.POST.name());
dto.setOriginalValue(JSON.toJSONBytes(project));
return dto;
}
return null;
}
}

View File

@ -8,11 +8,7 @@ import io.metersphere.sdk.dto.AddProjectRequest;
import io.metersphere.sdk.dto.ProjectDTO; import io.metersphere.sdk.dto.ProjectDTO;
import io.metersphere.sdk.dto.UpdateProjectRequest; import io.metersphere.sdk.dto.UpdateProjectRequest;
import io.metersphere.sdk.exception.MSException; import io.metersphere.sdk.exception.MSException;
import io.metersphere.sdk.log.constants.OperationLogModule;
import io.metersphere.sdk.log.constants.OperationLogType;
import io.metersphere.sdk.log.service.OperationLogService;
import io.metersphere.sdk.util.Translator; import io.metersphere.sdk.util.Translator;
import io.metersphere.system.domain.OperationLog;
import io.metersphere.system.domain.User; import io.metersphere.system.domain.User;
import io.metersphere.system.domain.UserRoleRelation; import io.metersphere.system.domain.UserRoleRelation;
import io.metersphere.system.domain.UserRoleRelationExample; import io.metersphere.system.domain.UserRoleRelationExample;
@ -25,14 +21,12 @@ import io.metersphere.system.request.ProjectMemberRequest;
import io.metersphere.system.request.ProjectRequest; import io.metersphere.system.request.ProjectRequest;
import io.metersphere.utils.LoggerUtil; import io.metersphere.utils.LoggerUtil;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -49,8 +43,6 @@ public class SystemProjectService {
private UserRoleRelationMapper userRoleRelationMapper; private UserRoleRelationMapper userRoleRelationMapper;
@Resource @Resource
private ExtSystemProjectMapper extSystemProjectMapper; private ExtSystemProjectMapper extSystemProjectMapper;
@Resource
private OperationLogService operationLogService;
public Project get(String id) { public Project get(String id) {
return projectMapper.selectByPrimaryKey(id); return projectMapper.selectByPrimaryKey(id);
@ -189,8 +181,6 @@ public class SystemProjectService {
createUser); createUser);
userRoleRelationMapper.insertSelective(memberRole); userRoleRelationMapper.insertSelective(memberRole);
}); });
//写入操作日志
operationLogService.batchAdd(this.getBatchAddLogs(request, createUser, OperationLogType.ADD.name(), "addMember"));
} }
@ -217,7 +207,6 @@ public class SystemProjectService {
} }
public void deleteProject(List<Project> projects) { public void deleteProject(List<Project> projects) {
List<OperationLog> operationLogs = new ArrayList<>();
// 删除项目 // 删除项目
projects.forEach(project -> { projects.forEach(project -> {
LoggerUtil.info("send delete_project message, project id: " + project.getId()); LoggerUtil.info("send delete_project message, project id: " + project.getId());
@ -228,11 +217,7 @@ public class SystemProjectService {
// delete project // delete project
projectMapper.deleteByPrimaryKey(project.getId()); projectMapper.deleteByPrimaryKey(project.getId());
//记录日志
operationLogs.add(this.getDeleteLogs(project));
}); });
operationLogService.batchAdd(operationLogs);
} }
private void deleteProjectUserGroup(String projectId) { private void deleteProjectUserGroup(String projectId) {
@ -240,65 +225,4 @@ public class SystemProjectService {
userGroupExample.createCriteria().andSourceIdEqualTo(projectId); userGroupExample.createCriteria().andSourceIdEqualTo(projectId);
userRoleRelationMapper.deleteByExample(userGroupExample); userRoleRelationMapper.deleteByExample(userGroupExample);
} }
public OperationLog getDeleteLogs(Project project) {
OperationLog log = new OperationLog();
log.setId(UUID.randomUUID().toString());
log.setProjectId(project.getId());
log.setCreateUser("system");
log.setType(OperationLogType.DELETE.name());
log.setModule(OperationLogModule.SYSTEM_PROJECT);
log.setCreateTime(System.currentTimeMillis());
log.setDetails(project.getName());
log.setMethod("deleteProject");
return log;
}
public List<OperationLog> getBatchAddLogs(@Valid ProjectAddMemberRequest request,
String createUser,
String operationType,
String operationMethod) {
long operationTime = System.currentTimeMillis();
List<OperationLog> logs = new ArrayList<>();
request.getUserIds().forEach(userId -> {
User userInfo = userMapper.selectByPrimaryKey(userId);
OperationLog log = new OperationLog();
log.setId(UUID.randomUUID().toString());
log.setCreateUser(createUser);
log.setProjectId(request.getProjectId());
log.setType(operationType);
log.setModule(OperationLogModule.SYSTEM_PROJECT_MEMBER);
log.setMethod(operationMethod);
log.setCreateTime(operationTime);
log.setSourceId(request.getProjectId());
log.setDetails(userInfo.getName());
logs.add(log);
});
return logs;
}
public String getLogDetails(String id) {
Project project = projectMapper.selectByPrimaryKey(id);
if (ObjectUtils.isNotEmpty(project)) {
return project.getName();
}
return null;
}
public String getLogs(String userId) {
User user = userMapper.selectByPrimaryKey(userId);
if (ObjectUtils.isNotEmpty(user)) {
return user.getName();
}
return null;
}
/*public String getCreateLogDetail(@Validated AddProjectDTO request) {
List<String> addMemberNames = new ArrayList<>();
request.getUserIds().forEach(memberId -> {
User user = userMapper.selectByPrimaryKey(memberId);
addMemberNames.add(user.getName());
});
return request.getName() + StringUtils.SPACE + "并添加项目管理员" + StringUtils.SPACE
+ StringUtils.join(addMemberNames, ",");
}*/
} }

View File

@ -1,9 +1,11 @@
package io.metersphere.system.service; package io.metersphere.system.service;
import io.metersphere.sdk.constants.UserRoleEnum; import io.metersphere.sdk.constants.UserRoleEnum;
import io.metersphere.sdk.dto.LogDTO;
import io.metersphere.sdk.log.constants.OperationLogModule; import io.metersphere.sdk.log.constants.OperationLogModule;
import io.metersphere.sdk.log.constants.OperationLogType; import io.metersphere.sdk.log.constants.OperationLogType;
import io.metersphere.sdk.log.service.OperationLogService; import io.metersphere.sdk.log.service.OperationLogService;
import io.metersphere.sdk.util.JSON;
import io.metersphere.system.domain.*; import io.metersphere.system.domain.*;
import io.metersphere.system.dto.response.UserTableResponse; import io.metersphere.system.dto.response.UserTableResponse;
import io.metersphere.system.mapper.ExtUserRoleRelationMapper; import io.metersphere.system.mapper.ExtUserRoleRelationMapper;
@ -46,18 +48,18 @@ public class UserRoleRelationService {
private OperationLogService operationLogService; private OperationLogService operationLogService;
//批量添加用户记录日志 //批量添加用户记录日志
public List<OperationLog> getBatchLogs(@Valid @NotEmpty List<String> userRoleId, public List<LogDTO> getBatchLogs(@Valid @NotEmpty List<String> userRoleId,
@Valid User user, @Valid User user,
@Valid @NotEmpty String operationMethod, @Valid @NotEmpty String operationMethod,
@Valid @NotEmpty String operator, @Valid @NotEmpty String operator,
@Valid @NotEmpty String operationType) { @Valid @NotEmpty String operationType) {
long operationTime = System.currentTimeMillis(); long operationTime = System.currentTimeMillis();
List<OperationLog> logs = new ArrayList<>(); List<LogDTO> logs = new ArrayList<>();
UserRoleExample example = new UserRoleExample(); UserRoleExample example = new UserRoleExample();
example.createCriteria().andIdIn(userRoleId); example.createCriteria().andIdIn(userRoleId);
List<UserRole> userRoleList = userRoleMapper.selectByExample(example); List<UserRole> userRoleList = userRoleMapper.selectByExample(example);
userRoleList.forEach(userRole -> { userRoleList.forEach(userRole -> {
OperationLog log = new OperationLog(); LogDTO log = new LogDTO();
log.setId(UUID.randomUUID().toString()); log.setId(UUID.randomUUID().toString());
log.setProjectId("system"); log.setProjectId("system");
log.setType(operationType); log.setType(operationType);
@ -66,10 +68,11 @@ public class UserRoleRelationService {
log.setMethod(operationMethod); log.setMethod(operationMethod);
log.setCreateTime(operationTime); log.setCreateTime(operationTime);
log.setSourceId(user.getId()); log.setSourceId(user.getId());
log.setDetails(user.getName() + StringUtils.SPACE log.setContent(user.getName() + StringUtils.SPACE
+ operationType + StringUtils.SPACE + operationType + StringUtils.SPACE
+ "UserRole" + StringUtils.SPACE + "UserRole" + StringUtils.SPACE
+ userRole.getName()); + userRole.getName());
log.setOriginalValue(JSON.toJSONBytes(userRole));
logs.add(log); logs.add(log);
}); });
return logs; return logs;

View File

@ -1,8 +1,10 @@
package io.metersphere.system.service; package io.metersphere.system.service;
import com.alibaba.excel.EasyExcelFactory; import com.alibaba.excel.EasyExcelFactory;
import io.metersphere.constants.HttpMethodConstants;
import io.metersphere.sdk.dto.BasePageRequest; import io.metersphere.sdk.dto.BasePageRequest;
import io.metersphere.sdk.dto.ExcelParseDTO; import io.metersphere.sdk.dto.ExcelParseDTO;
import io.metersphere.sdk.dto.LogDTO;
import io.metersphere.sdk.dto.UserDTO; import io.metersphere.sdk.dto.UserDTO;
import io.metersphere.sdk.exception.MSException; import io.metersphere.sdk.exception.MSException;
import io.metersphere.sdk.log.constants.OperationLogModule; import io.metersphere.sdk.log.constants.OperationLogModule;
@ -10,14 +12,12 @@ import io.metersphere.sdk.log.constants.OperationLogType;
import io.metersphere.sdk.log.service.OperationLogService; import io.metersphere.sdk.log.service.OperationLogService;
import io.metersphere.sdk.mapper.BaseUserMapper; import io.metersphere.sdk.mapper.BaseUserMapper;
import io.metersphere.sdk.util.*; import io.metersphere.sdk.util.*;
import io.metersphere.system.domain.OperationLog;
import io.metersphere.system.domain.User; import io.metersphere.system.domain.User;
import io.metersphere.system.domain.UserExample; import io.metersphere.system.domain.UserExample;
import io.metersphere.system.dto.UserBatchCreateDTO; import io.metersphere.system.dto.UserBatchCreateDTO;
import io.metersphere.system.dto.UserCreateInfo; import io.metersphere.system.dto.UserCreateInfo;
import io.metersphere.system.dto.excel.UserExcel; import io.metersphere.system.dto.excel.UserExcel;
import io.metersphere.system.dto.excel.UserExcelRowDTO; import io.metersphere.system.dto.excel.UserExcelRowDTO;
import io.metersphere.system.dto.request.UserBatchProcessRequest;
import io.metersphere.system.dto.request.UserChangeEnableRequest; import io.metersphere.system.dto.request.UserChangeEnableRequest;
import io.metersphere.system.dto.request.UserEditRequest; import io.metersphere.system.dto.request.UserEditRequest;
import io.metersphere.system.dto.response.UserBatchProcessResponse; import io.metersphere.system.dto.response.UserBatchProcessResponse;
@ -58,10 +58,10 @@ public class UserService {
private UserRoleService userRoleService; private UserRoleService userRoleService;
//批量添加用户记录日志 //批量添加用户记录日志
public List<OperationLog> getBatchAddLogs(@Valid List<User> userList) { public List<LogDTO> getBatchAddLogs(@Valid List<User> userList) {
List<OperationLog> logs = new ArrayList<>(); List<LogDTO> logs = new ArrayList<>();
userList.forEach(user -> { userList.forEach(user -> {
OperationLog log = new OperationLog(); LogDTO log = new LogDTO();
log.setId(UUID.randomUUID().toString()); log.setId(UUID.randomUUID().toString());
log.setCreateUser(user.getCreateUser()); log.setCreateUser(user.getCreateUser());
log.setProjectId("system"); log.setProjectId("system");
@ -70,7 +70,8 @@ public class UserService {
log.setMethod("addUser"); log.setMethod("addUser");
log.setCreateTime(user.getCreateTime()); log.setCreateTime(user.getCreateTime());
log.setSourceId(user.getId()); log.setSourceId(user.getId());
log.setDetails(user.getName() + "(" + user.getEmail() + ")"); log.setContent(user.getName() + "(" + user.getEmail() + ")");
log.setOriginalValue(JSON.toJSONBytes(user));
logs.add(log); logs.add(log);
}); });
return logs; return logs;
@ -82,26 +83,6 @@ public class UserService {
return userMapper.selectByExample(example); return userMapper.selectByExample(example);
} }
//切面方法调用获取接口日志
public List<OperationLog> getLogs(UserBatchProcessRequest request) {
List<OperationLog> logs = new ArrayList<>();
List<User> userList = this.selectByIdList(request.getUserIdList());
userList.forEach(user -> {
OperationLog log = new OperationLog();
log.setId(UUID.randomUUID().toString());
log.setCreateUser(SessionUtils.getUserId());
log.setProjectId("system");
log.setType(OperationLogType.DELETE.name());
log.setModule(OperationLogModule.SYSTEM_USER);
log.setCreateTime(System.currentTimeMillis());
log.setMethod("deleteUser");
log.setSourceId(user.getId());
log.setDetails(user.getName());
logs.add(log);
});
return logs;
}
private void validateUserInfo(List<UserCreateInfo> userList) { private void validateUserInfo(List<UserCreateInfo> userList) {
//判断参数内是否含有重复邮箱 //判断参数内是否含有重复邮箱
List<String> emailList = new ArrayList<>(); List<String> emailList = new ArrayList<>();
@ -303,4 +284,46 @@ public class UserService {
userRoleRelationService.deleteByUserIdList(userIdList); userRoleRelationService.deleteByUserIdList(userIdList);
return response; return response;
} }
public LogDTO updateLog(UserEditRequest request) {
User user = userMapper.selectByPrimaryKey(request.getId());
if (user != null) {
LogDTO dto = new LogDTO(
"system",
request.getId(),
null,
OperationLogType.UPDATE.name(),
OperationLogModule.SYSTEM_USER,
request.getName());
dto.setPath("/update");
dto.setMethod(HttpMethodConstants.POST.name());
dto.setOriginalValue(JSON.toJSONBytes(user));
return dto;
}
return null;
}
public List<LogDTO> deleteLog(UserChangeEnableRequest request) {
List<LogDTO> logDTOList = new ArrayList<>();
request.getUserIdList().forEach(item -> {
User user = userMapper.selectByPrimaryKey(item);
if (user != null) {
LogDTO dto = new LogDTO(
"system",
user.getId(),
user.getCreateUser(),
OperationLogType.DELETE.name(),
OperationLogModule.SYSTEM_PROJECT,
user.getName());
dto.setPath("/delete");
dto.setMethod(HttpMethodConstants.POST.name());
dto.setOriginalValue(JSON.toJSONBytes(user));
logDTOList.add(dto);
}
});
return logDTOList;
}
} }