feat(项目管理): 文件管理的模块树功能开发
This commit is contained in:
parent
9e3e2c471e
commit
39f2f6c888
|
@ -82,4 +82,6 @@ spring.freemarker.check-template-location=false
|
|||
spring.groovy.template.check-template-location=false
|
||||
|
||||
# swagger docs group
|
||||
springdoc.api-docs.groups.enabled=true
|
||||
springdoc.api-docs.groups.enabled=true
|
||||
#批量文件下载的最大值
|
||||
metersphere.file.batch-download-max=600MB
|
|
@ -1,78 +1,82 @@
|
|||
package io.metersphere.project.domain;
|
||||
|
||||
import io.metersphere.validation.groups.*;
|
||||
import io.metersphere.validation.groups.Created;
|
||||
import io.metersphere.validation.groups.Updated;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.*;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class FileMetadata implements Serializable {
|
||||
@Schema(description = "文件ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@Schema(description = "文件ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{file_metadata.id.not_blank}", groups = {Updated.class})
|
||||
@Size(min = 1, max = 50, message = "{file_metadata.id.length_range}", groups = {Created.class, Updated.class})
|
||||
private String id;
|
||||
|
||||
@Schema(description = "文件名", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@Schema(description = "文件名", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{file_metadata.name.not_blank}", groups = {Created.class})
|
||||
@Size(min = 1, max = 255, message = "{file_metadata.name.length_range}", groups = {Created.class, Updated.class})
|
||||
private String name;
|
||||
|
||||
@Schema(description = "文件类型")
|
||||
@Schema(description = "文件类型")
|
||||
private String type;
|
||||
|
||||
@Schema(description = "文件大小", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@Schema(description = "文件大小", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "{file_metadata.size.not_blank}", groups = {Created.class})
|
||||
private Long size;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@Schema(description = "创建时间")
|
||||
private Long createTime;
|
||||
|
||||
@Schema(description = "更新时间")
|
||||
@Schema(description = "更新时间")
|
||||
private Long updateTime;
|
||||
|
||||
@Schema(description = "项目ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@Schema(description = "项目ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{file_metadata.project_id.not_blank}", groups = {Created.class})
|
||||
@Size(min = 1, max = 50, message = "{file_metadata.project_id.length_range}", groups = {Created.class, Updated.class})
|
||||
private String projectId;
|
||||
|
||||
@Schema(description = "文件存储方式")
|
||||
@Schema(description = "文件存储方式", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{file_metadata.storage.not_blank}", groups = {Created.class})
|
||||
@Size(min = 1, max = 50, message = "{file_metadata.storage.length_range}", groups = {Created.class, Updated.class})
|
||||
private String storage;
|
||||
|
||||
@Schema(description = "创建人")
|
||||
@Schema(description = "创建人")
|
||||
private String createUser;
|
||||
|
||||
@Schema(description = "修改人")
|
||||
@Schema(description = "修改人")
|
||||
private String updateUser;
|
||||
|
||||
@Schema(description = "标签")
|
||||
@Schema(description = "标签")
|
||||
private String tags;
|
||||
|
||||
@Schema(description = "描述")
|
||||
@Schema(description = "描述")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "文件所属模块")
|
||||
@Schema(description = "文件所属模块")
|
||||
private String moduleId;
|
||||
|
||||
@Schema(description = "是否加载jar(开启后用于接口测试执行时使用)")
|
||||
private Boolean loadJar;
|
||||
|
||||
@Schema(description = "文件存储路径")
|
||||
@Schema(description = "文件存储路径")
|
||||
private String path;
|
||||
|
||||
@Schema(description = "资源作用范围,主要兼容2.1版本前的历史数据,后续版本不再产生数据")
|
||||
private String resourceType;
|
||||
|
||||
@Schema(description = "是否是最新版")
|
||||
@Schema(description = "是否是最新版", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "{file_metadata.latest.not_blank}", groups = {Created.class})
|
||||
private Boolean latest;
|
||||
|
||||
@Schema(description = "同版本数据关联的ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@Schema(description = "同版本数据关联的ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{file_metadata.ref_id.not_blank}", groups = {Created.class})
|
||||
@Size(min = 1, max = 50, message = "{file_metadata.ref_id.length_range}", groups = {Created.class, Updated.class})
|
||||
private String refId;
|
||||
|
||||
@Schema(description = "文件版本号")
|
||||
private String fileVersion;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public enum Column {
|
||||
|
@ -89,11 +93,10 @@ public class FileMetadata implements Serializable {
|
|||
tags("tags", "tags", "VARCHAR", false),
|
||||
description("description", "description", "VARCHAR", false),
|
||||
moduleId("module_id", "moduleId", "VARCHAR", false),
|
||||
loadJar("load_jar", "loadJar", "BIT", false),
|
||||
path("path", "path", "VARCHAR", true),
|
||||
resourceType("resource_type", "resourceType", "VARCHAR", false),
|
||||
latest("latest", "latest", "BIT", false),
|
||||
refId("ref_id", "refId", "VARCHAR", false);
|
||||
refId("ref_id", "refId", "VARCHAR", false),
|
||||
fileVersion("file_version", "fileVersion", "VARCHAR", false);
|
||||
|
||||
private static final String BEGINNING_DELIMITER = "`";
|
||||
|
||||
|
|
|
@ -984,66 +984,6 @@ public class FileMetadataExample {
|
|||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andLoadJarIsNull() {
|
||||
addCriterion("load_jar is null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andLoadJarIsNotNull() {
|
||||
addCriterion("load_jar is not null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andLoadJarEqualTo(Boolean value) {
|
||||
addCriterion("load_jar =", value, "loadJar");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andLoadJarNotEqualTo(Boolean value) {
|
||||
addCriterion("load_jar <>", value, "loadJar");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andLoadJarGreaterThan(Boolean value) {
|
||||
addCriterion("load_jar >", value, "loadJar");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andLoadJarGreaterThanOrEqualTo(Boolean value) {
|
||||
addCriterion("load_jar >=", value, "loadJar");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andLoadJarLessThan(Boolean value) {
|
||||
addCriterion("load_jar <", value, "loadJar");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andLoadJarLessThanOrEqualTo(Boolean value) {
|
||||
addCriterion("load_jar <=", value, "loadJar");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andLoadJarIn(List<Boolean> values) {
|
||||
addCriterion("load_jar in", values, "loadJar");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andLoadJarNotIn(List<Boolean> values) {
|
||||
addCriterion("load_jar not in", values, "loadJar");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andLoadJarBetween(Boolean value1, Boolean value2) {
|
||||
addCriterion("load_jar between", value1, value2, "loadJar");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andLoadJarNotBetween(Boolean value1, Boolean value2) {
|
||||
addCriterion("load_jar not between", value1, value2, "loadJar");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andPathIsNull() {
|
||||
addCriterion("`path` is null");
|
||||
return (Criteria) this;
|
||||
|
@ -1114,76 +1054,6 @@ public class FileMetadataExample {
|
|||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andResourceTypeIsNull() {
|
||||
addCriterion("resource_type is null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andResourceTypeIsNotNull() {
|
||||
addCriterion("resource_type is not null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andResourceTypeEqualTo(String value) {
|
||||
addCriterion("resource_type =", value, "resourceType");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andResourceTypeNotEqualTo(String value) {
|
||||
addCriterion("resource_type <>", value, "resourceType");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andResourceTypeGreaterThan(String value) {
|
||||
addCriterion("resource_type >", value, "resourceType");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andResourceTypeGreaterThanOrEqualTo(String value) {
|
||||
addCriterion("resource_type >=", value, "resourceType");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andResourceTypeLessThan(String value) {
|
||||
addCriterion("resource_type <", value, "resourceType");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andResourceTypeLessThanOrEqualTo(String value) {
|
||||
addCriterion("resource_type <=", value, "resourceType");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andResourceTypeLike(String value) {
|
||||
addCriterion("resource_type like", value, "resourceType");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andResourceTypeNotLike(String value) {
|
||||
addCriterion("resource_type not like", value, "resourceType");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andResourceTypeIn(List<String> values) {
|
||||
addCriterion("resource_type in", values, "resourceType");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andResourceTypeNotIn(List<String> values) {
|
||||
addCriterion("resource_type not in", values, "resourceType");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andResourceTypeBetween(String value1, String value2) {
|
||||
addCriterion("resource_type between", value1, value2, "resourceType");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andResourceTypeNotBetween(String value1, String value2) {
|
||||
addCriterion("resource_type not between", value1, value2, "resourceType");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andLatestIsNull() {
|
||||
addCriterion("latest is null");
|
||||
return (Criteria) this;
|
||||
|
@ -1313,6 +1183,76 @@ public class FileMetadataExample {
|
|||
addCriterion("ref_id not between", value1, value2, "refId");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andFileVersionIsNull() {
|
||||
addCriterion("file_version is null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andFileVersionIsNotNull() {
|
||||
addCriterion("file_version is not null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andFileVersionEqualTo(String value) {
|
||||
addCriterion("file_version =", value, "fileVersion");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andFileVersionNotEqualTo(String value) {
|
||||
addCriterion("file_version <>", value, "fileVersion");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andFileVersionGreaterThan(String value) {
|
||||
addCriterion("file_version >", value, "fileVersion");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andFileVersionGreaterThanOrEqualTo(String value) {
|
||||
addCriterion("file_version >=", value, "fileVersion");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andFileVersionLessThan(String value) {
|
||||
addCriterion("file_version <", value, "fileVersion");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andFileVersionLessThanOrEqualTo(String value) {
|
||||
addCriterion("file_version <=", value, "fileVersion");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andFileVersionLike(String value) {
|
||||
addCriterion("file_version like", value, "fileVersion");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andFileVersionNotLike(String value) {
|
||||
addCriterion("file_version not like", value, "fileVersion");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andFileVersionIn(List<String> values) {
|
||||
addCriterion("file_version in", values, "fileVersion");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andFileVersionNotIn(List<String> values) {
|
||||
addCriterion("file_version not in", values, "fileVersion");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andFileVersionBetween(String value1, String value2) {
|
||||
addCriterion("file_version between", value1, value2, "fileVersion");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andFileVersionNotBetween(String value1, String value2) {
|
||||
addCriterion("file_version not between", value1, value2, "fileVersion");
|
||||
return (Criteria) this;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Criteria extends GeneratedCriteria {
|
||||
|
|
|
@ -9,13 +9,13 @@ import java.util.Arrays;
|
|||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class FileMetadataBlob implements Serializable {
|
||||
@Schema(description = "文件ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{file_metadata_blob.id.not_blank}", groups = {Updated.class})
|
||||
@Size(min = 1, max = 50, message = "{file_metadata_blob.id.length_range}", groups = {Created.class, Updated.class})
|
||||
public class FileMetadataRepository implements Serializable {
|
||||
@Schema(title = "文件ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{file_metadata_repository.id.not_blank}", groups = {Updated.class})
|
||||
@Size(min = 1, max = 50, message = "{file_metadata_repository.id.length_range}", groups = {Created.class, Updated.class})
|
||||
private String id;
|
||||
|
||||
@Schema(description = "储存库")
|
||||
@Schema(title = "储存库")
|
||||
private byte[] gitInfo;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
|
@ -3,14 +3,14 @@ package io.metersphere.project.domain;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class FileMetadataBlobExample {
|
||||
public class FileMetadataRepositoryExample {
|
||||
protected String orderByClause;
|
||||
|
||||
protected boolean distinct;
|
||||
|
||||
protected List<Criteria> oredCriteria;
|
||||
|
||||
public FileMetadataBlobExample() {
|
||||
public FileMetadataRepositoryExample() {
|
||||
oredCriteria = new ArrayList<Criteria>();
|
||||
}
|
||||
|
|
@ -1,49 +1,52 @@
|
|||
package io.metersphere.project.domain;
|
||||
|
||||
import io.metersphere.validation.groups.*;
|
||||
import io.metersphere.validation.groups.Created;
|
||||
import io.metersphere.validation.groups.Updated;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.*;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class FileModule implements Serializable {
|
||||
@Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@Schema(description = "ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{file_module.id.not_blank}", groups = {Updated.class})
|
||||
@Size(min = 1, max = 50, message = "{file_module.id.length_range}", groups = {Created.class, Updated.class})
|
||||
private String id;
|
||||
|
||||
@Schema(description = "项目ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@Schema(description = "项目ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{file_module.project_id.not_blank}", groups = {Created.class})
|
||||
@Size(min = 1, max = 50, message = "{file_module.project_id.length_range}", groups = {Created.class, Updated.class})
|
||||
private String projectId;
|
||||
|
||||
@Schema(description = "模块名称", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@Schema(description = "模块名称", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{file_module.name.not_blank}", groups = {Created.class})
|
||||
@Size(min = 1, max = 64, message = "{file_module.name.length_range}", groups = {Created.class, Updated.class})
|
||||
private String name;
|
||||
|
||||
@Schema(description = "父级ID")
|
||||
@Schema(description = "父级ID")
|
||||
private String parentId;
|
||||
|
||||
@Schema(description = "层数")
|
||||
private Integer level;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@Schema(description = "创建时间")
|
||||
private Long createTime;
|
||||
|
||||
@Schema(description = "更新时间")
|
||||
@Schema(description = "更新时间")
|
||||
private Long updateTime;
|
||||
|
||||
@Schema(description = "排序用的标识")
|
||||
private Double pos;
|
||||
@Schema(description = "排序用的标识")
|
||||
private Integer pos;
|
||||
|
||||
@Schema(description = "创建人")
|
||||
@Schema(description = "修改人")
|
||||
private String updateUser;
|
||||
|
||||
@Schema(description = "创建人")
|
||||
private String createUser;
|
||||
|
||||
@Schema(description = "模块类型: module/repository")
|
||||
@Schema(description = "模块类型: module/repository")
|
||||
private String moduleType;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
@ -53,10 +56,10 @@ public class FileModule implements Serializable {
|
|||
projectId("project_id", "projectId", "VARCHAR", false),
|
||||
name("name", "name", "VARCHAR", true),
|
||||
parentId("parent_id", "parentId", "VARCHAR", false),
|
||||
level("level", "level", "INTEGER", true),
|
||||
createTime("create_time", "createTime", "BIGINT", false),
|
||||
updateTime("update_time", "updateTime", "BIGINT", false),
|
||||
pos("pos", "pos", "DOUBLE", false),
|
||||
pos("pos", "pos", "INTEGER", false),
|
||||
updateUser("update_user", "updateUser", "VARCHAR", false),
|
||||
createUser("create_user", "createUser", "VARCHAR", false),
|
||||
moduleType("module_type", "moduleType", "VARCHAR", false);
|
||||
|
||||
|
|
|
@ -384,66 +384,6 @@ public class FileModuleExample {
|
|||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andLevelIsNull() {
|
||||
addCriterion("`level` is null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andLevelIsNotNull() {
|
||||
addCriterion("`level` is not null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andLevelEqualTo(Integer value) {
|
||||
addCriterion("`level` =", value, "level");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andLevelNotEqualTo(Integer value) {
|
||||
addCriterion("`level` <>", value, "level");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andLevelGreaterThan(Integer value) {
|
||||
addCriterion("`level` >", value, "level");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andLevelGreaterThanOrEqualTo(Integer value) {
|
||||
addCriterion("`level` >=", value, "level");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andLevelLessThan(Integer value) {
|
||||
addCriterion("`level` <", value, "level");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andLevelLessThanOrEqualTo(Integer value) {
|
||||
addCriterion("`level` <=", value, "level");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andLevelIn(List<Integer> values) {
|
||||
addCriterion("`level` in", values, "level");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andLevelNotIn(List<Integer> values) {
|
||||
addCriterion("`level` not in", values, "level");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andLevelBetween(Integer value1, Integer value2) {
|
||||
addCriterion("`level` between", value1, value2, "level");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andLevelNotBetween(Integer value1, Integer value2) {
|
||||
addCriterion("`level` not between", value1, value2, "level");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andCreateTimeIsNull() {
|
||||
addCriterion("create_time is null");
|
||||
return (Criteria) this;
|
||||
|
@ -574,56 +514,126 @@ public class FileModuleExample {
|
|||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andPosEqualTo(Double value) {
|
||||
public Criteria andPosEqualTo(Integer value) {
|
||||
addCriterion("pos =", value, "pos");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andPosNotEqualTo(Double value) {
|
||||
public Criteria andPosNotEqualTo(Integer value) {
|
||||
addCriterion("pos <>", value, "pos");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andPosGreaterThan(Double value) {
|
||||
public Criteria andPosGreaterThan(Integer value) {
|
||||
addCriterion("pos >", value, "pos");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andPosGreaterThanOrEqualTo(Double value) {
|
||||
public Criteria andPosGreaterThanOrEqualTo(Integer value) {
|
||||
addCriterion("pos >=", value, "pos");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andPosLessThan(Double value) {
|
||||
public Criteria andPosLessThan(Integer value) {
|
||||
addCriterion("pos <", value, "pos");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andPosLessThanOrEqualTo(Double value) {
|
||||
public Criteria andPosLessThanOrEqualTo(Integer value) {
|
||||
addCriterion("pos <=", value, "pos");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andPosIn(List<Double> values) {
|
||||
public Criteria andPosIn(List<Integer> values) {
|
||||
addCriterion("pos in", values, "pos");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andPosNotIn(List<Double> values) {
|
||||
public Criteria andPosNotIn(List<Integer> values) {
|
||||
addCriterion("pos not in", values, "pos");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andPosBetween(Double value1, Double value2) {
|
||||
public Criteria andPosBetween(Integer value1, Integer value2) {
|
||||
addCriterion("pos between", value1, value2, "pos");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andPosNotBetween(Double value1, Double value2) {
|
||||
public Criteria andPosNotBetween(Integer value1, Integer value2) {
|
||||
addCriterion("pos not between", value1, value2, "pos");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andUpdateUserIsNull() {
|
||||
addCriterion("update_user is null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andUpdateUserIsNotNull() {
|
||||
addCriterion("update_user is not null");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andUpdateUserEqualTo(String value) {
|
||||
addCriterion("update_user =", value, "updateUser");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andUpdateUserNotEqualTo(String value) {
|
||||
addCriterion("update_user <>", value, "updateUser");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andUpdateUserGreaterThan(String value) {
|
||||
addCriterion("update_user >", value, "updateUser");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andUpdateUserGreaterThanOrEqualTo(String value) {
|
||||
addCriterion("update_user >=", value, "updateUser");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andUpdateUserLessThan(String value) {
|
||||
addCriterion("update_user <", value, "updateUser");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andUpdateUserLessThanOrEqualTo(String value) {
|
||||
addCriterion("update_user <=", value, "updateUser");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andUpdateUserLike(String value) {
|
||||
addCriterion("update_user like", value, "updateUser");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andUpdateUserNotLike(String value) {
|
||||
addCriterion("update_user not like", value, "updateUser");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andUpdateUserIn(List<String> values) {
|
||||
addCriterion("update_user in", values, "updateUser");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andUpdateUserNotIn(List<String> values) {
|
||||
addCriterion("update_user not in", values, "updateUser");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andUpdateUserBetween(String value1, String value2) {
|
||||
addCriterion("update_user between", value1, value2, "updateUser");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andUpdateUserNotBetween(String value1, String value2) {
|
||||
addCriterion("update_user not between", value1, value2, "updateUser");
|
||||
return (Criteria) this;
|
||||
}
|
||||
|
||||
public Criteria andCreateUserIsNull() {
|
||||
addCriterion("create_user is null");
|
||||
return (Criteria) this;
|
||||
|
|
|
@ -1,30 +1,33 @@
|
|||
package io.metersphere.project.domain;
|
||||
|
||||
import io.metersphere.validation.groups.*;
|
||||
import io.metersphere.validation.groups.Created;
|
||||
import io.metersphere.validation.groups.Updated;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.*;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class FileModuleRepository implements Serializable {
|
||||
@Schema(title = "file_module_id", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@Schema(description = "file_module_id", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{file_module_repository.file_module_id.not_blank}", groups = {Created.class})
|
||||
@Size(min = 1, max = 50, message = "{file_module_repository.file_module_id.length_range}", groups = {Created.class, Updated.class})
|
||||
private String fileModuleId;
|
||||
|
||||
@Schema(title = "所属平台;GitHub/Gitlab/Gitee")
|
||||
@Schema(description = "所属平台;GitHub/Gitlab/Gitee")
|
||||
private String platform;
|
||||
|
||||
@Schema(title = "存储库地址")
|
||||
@Schema(description = "存储库地址")
|
||||
private String repositoryPath;
|
||||
|
||||
@Schema(title = "存储库Token;platform为Gitee时必填")
|
||||
@Schema(description = "存储库Token;platform为Gitee时必填")
|
||||
private String repositoryUserName;
|
||||
|
||||
@Schema(title = "存储库Token")
|
||||
@Schema(description = "存储库Token")
|
||||
private String repositoryToken;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
package io.metersphere.project.mapper;
|
||||
|
||||
import io.metersphere.project.domain.FileMetadataBlob;
|
||||
import io.metersphere.project.domain.FileMetadataBlobExample;
|
||||
import java.util.List;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
public interface FileMetadataBlobMapper {
|
||||
long countByExample(FileMetadataBlobExample example);
|
||||
|
||||
int deleteByExample(FileMetadataBlobExample example);
|
||||
|
||||
int deleteByPrimaryKey(String id);
|
||||
|
||||
int insert(FileMetadataBlob record);
|
||||
|
||||
int insertSelective(FileMetadataBlob record);
|
||||
|
||||
List<FileMetadataBlob> selectByExampleWithBLOBs(FileMetadataBlobExample example);
|
||||
|
||||
List<FileMetadataBlob> selectByExample(FileMetadataBlobExample example);
|
||||
|
||||
FileMetadataBlob selectByPrimaryKey(String id);
|
||||
|
||||
int updateByExampleSelective(@Param("record") FileMetadataBlob record, @Param("example") FileMetadataBlobExample example);
|
||||
|
||||
int updateByExampleWithBLOBs(@Param("record") FileMetadataBlob record, @Param("example") FileMetadataBlobExample example);
|
||||
|
||||
int updateByExample(@Param("record") FileMetadataBlob record, @Param("example") FileMetadataBlobExample example);
|
||||
|
||||
int updateByPrimaryKeySelective(FileMetadataBlob record);
|
||||
|
||||
int updateByPrimaryKeyWithBLOBs(FileMetadataBlob record);
|
||||
|
||||
int batchInsert(@Param("list") List<FileMetadataBlob> list);
|
||||
|
||||
int batchInsertSelective(@Param("list") List<FileMetadataBlob> list, @Param("selective") FileMetadataBlob.Column ... selective);
|
||||
}
|
|
@ -15,11 +15,10 @@
|
|||
<result column="tags" jdbcType="VARCHAR" property="tags" />
|
||||
<result column="description" jdbcType="VARCHAR" property="description" />
|
||||
<result column="module_id" jdbcType="VARCHAR" property="moduleId" />
|
||||
<result column="load_jar" jdbcType="BIT" property="loadJar" />
|
||||
<result column="path" jdbcType="VARCHAR" property="path" />
|
||||
<result column="resource_type" jdbcType="VARCHAR" property="resourceType" />
|
||||
<result column="latest" jdbcType="BIT" property="latest" />
|
||||
<result column="ref_id" jdbcType="VARCHAR" property="refId" />
|
||||
<result column="file_version" jdbcType="VARCHAR" property="fileVersion" />
|
||||
</resultMap>
|
||||
<sql id="Example_Where_Clause">
|
||||
<where>
|
||||
|
@ -81,8 +80,7 @@
|
|||
</sql>
|
||||
<sql id="Base_Column_List">
|
||||
id, `name`, `type`, `size`, create_time, update_time, project_id, `storage`, create_user,
|
||||
update_user, tags, description, module_id, load_jar, `path`, resource_type, latest,
|
||||
ref_id
|
||||
update_user, tags, description, module_id, `path`, latest, ref_id, file_version
|
||||
</sql>
|
||||
<select id="selectByExample" parameterType="io.metersphere.project.domain.FileMetadataExample" resultMap="BaseResultMap">
|
||||
select
|
||||
|
@ -119,16 +117,14 @@
|
|||
`size`, create_time, update_time,
|
||||
project_id, `storage`, create_user,
|
||||
update_user, tags, description,
|
||||
module_id, load_jar, `path`,
|
||||
resource_type, latest, ref_id
|
||||
)
|
||||
module_id, `path`, latest,
|
||||
ref_id, file_version)
|
||||
values (#{id,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR}, #{type,jdbcType=VARCHAR},
|
||||
#{size,jdbcType=BIGINT}, #{createTime,jdbcType=BIGINT}, #{updateTime,jdbcType=BIGINT},
|
||||
#{projectId,jdbcType=VARCHAR}, #{storage,jdbcType=VARCHAR}, #{createUser,jdbcType=VARCHAR},
|
||||
#{updateUser,jdbcType=VARCHAR}, #{tags,jdbcType=VARCHAR}, #{description,jdbcType=VARCHAR},
|
||||
#{moduleId,jdbcType=VARCHAR}, #{loadJar,jdbcType=BIT}, #{path,jdbcType=VARCHAR},
|
||||
#{resourceType,jdbcType=VARCHAR}, #{latest,jdbcType=BIT}, #{refId,jdbcType=VARCHAR}
|
||||
)
|
||||
#{moduleId,jdbcType=VARCHAR}, #{path,jdbcType=VARCHAR}, #{latest,jdbcType=BIT},
|
||||
#{refId,jdbcType=VARCHAR}, #{fileVersion,jdbcType=VARCHAR})
|
||||
</insert>
|
||||
<insert id="insertSelective" parameterType="io.metersphere.project.domain.FileMetadata">
|
||||
insert into file_metadata
|
||||
|
@ -172,21 +168,18 @@
|
|||
<if test="moduleId != null">
|
||||
module_id,
|
||||
</if>
|
||||
<if test="loadJar != null">
|
||||
load_jar,
|
||||
</if>
|
||||
<if test="path != null">
|
||||
`path`,
|
||||
</if>
|
||||
<if test="resourceType != null">
|
||||
resource_type,
|
||||
</if>
|
||||
<if test="latest != null">
|
||||
latest,
|
||||
</if>
|
||||
<if test="refId != null">
|
||||
ref_id,
|
||||
</if>
|
||||
<if test="fileVersion != null">
|
||||
file_version,
|
||||
</if>
|
||||
</trim>
|
||||
<trim prefix="values (" suffix=")" suffixOverrides=",">
|
||||
<if test="id != null">
|
||||
|
@ -228,21 +221,18 @@
|
|||
<if test="moduleId != null">
|
||||
#{moduleId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="loadJar != null">
|
||||
#{loadJar,jdbcType=BIT},
|
||||
</if>
|
||||
<if test="path != null">
|
||||
#{path,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="resourceType != null">
|
||||
#{resourceType,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="latest != null">
|
||||
#{latest,jdbcType=BIT},
|
||||
</if>
|
||||
<if test="refId != null">
|
||||
#{refId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="fileVersion != null">
|
||||
#{fileVersion,jdbcType=VARCHAR},
|
||||
</if>
|
||||
</trim>
|
||||
</insert>
|
||||
<select id="countByExample" parameterType="io.metersphere.project.domain.FileMetadataExample" resultType="java.lang.Long">
|
||||
|
@ -293,21 +283,18 @@
|
|||
<if test="record.moduleId != null">
|
||||
module_id = #{record.moduleId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.loadJar != null">
|
||||
load_jar = #{record.loadJar,jdbcType=BIT},
|
||||
</if>
|
||||
<if test="record.path != null">
|
||||
`path` = #{record.path,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.resourceType != null">
|
||||
resource_type = #{record.resourceType,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.latest != null">
|
||||
latest = #{record.latest,jdbcType=BIT},
|
||||
</if>
|
||||
<if test="record.refId != null">
|
||||
ref_id = #{record.refId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.fileVersion != null">
|
||||
file_version = #{record.fileVersion,jdbcType=VARCHAR},
|
||||
</if>
|
||||
</set>
|
||||
<if test="_parameter != null">
|
||||
<include refid="Update_By_Example_Where_Clause" />
|
||||
|
@ -328,11 +315,10 @@
|
|||
tags = #{record.tags,jdbcType=VARCHAR},
|
||||
description = #{record.description,jdbcType=VARCHAR},
|
||||
module_id = #{record.moduleId,jdbcType=VARCHAR},
|
||||
load_jar = #{record.loadJar,jdbcType=BIT},
|
||||
`path` = #{record.path,jdbcType=VARCHAR},
|
||||
resource_type = #{record.resourceType,jdbcType=VARCHAR},
|
||||
latest = #{record.latest,jdbcType=BIT},
|
||||
ref_id = #{record.refId,jdbcType=VARCHAR}
|
||||
ref_id = #{record.refId,jdbcType=VARCHAR},
|
||||
file_version = #{record.fileVersion,jdbcType=VARCHAR}
|
||||
<if test="_parameter != null">
|
||||
<include refid="Update_By_Example_Where_Clause" />
|
||||
</if>
|
||||
|
@ -376,21 +362,18 @@
|
|||
<if test="moduleId != null">
|
||||
module_id = #{moduleId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="loadJar != null">
|
||||
load_jar = #{loadJar,jdbcType=BIT},
|
||||
</if>
|
||||
<if test="path != null">
|
||||
`path` = #{path,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="resourceType != null">
|
||||
resource_type = #{resourceType,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="latest != null">
|
||||
latest = #{latest,jdbcType=BIT},
|
||||
</if>
|
||||
<if test="refId != null">
|
||||
ref_id = #{refId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="fileVersion != null">
|
||||
file_version = #{fileVersion,jdbcType=VARCHAR},
|
||||
</if>
|
||||
</set>
|
||||
where id = #{id,jdbcType=VARCHAR}
|
||||
</update>
|
||||
|
@ -408,27 +391,25 @@
|
|||
tags = #{tags,jdbcType=VARCHAR},
|
||||
description = #{description,jdbcType=VARCHAR},
|
||||
module_id = #{moduleId,jdbcType=VARCHAR},
|
||||
load_jar = #{loadJar,jdbcType=BIT},
|
||||
`path` = #{path,jdbcType=VARCHAR},
|
||||
resource_type = #{resourceType,jdbcType=VARCHAR},
|
||||
latest = #{latest,jdbcType=BIT},
|
||||
ref_id = #{refId,jdbcType=VARCHAR}
|
||||
ref_id = #{refId,jdbcType=VARCHAR},
|
||||
file_version = #{fileVersion,jdbcType=VARCHAR}
|
||||
where id = #{id,jdbcType=VARCHAR}
|
||||
</update>
|
||||
<insert id="batchInsert" parameterType="map">
|
||||
insert into file_metadata
|
||||
(id, `name`, `type`, `size`, create_time, update_time, project_id, `storage`, create_user,
|
||||
update_user, tags, description, module_id, load_jar, `path`, resource_type, latest,
|
||||
ref_id)
|
||||
update_user, tags, description, module_id, `path`, latest, ref_id, file_version
|
||||
)
|
||||
values
|
||||
<foreach collection="list" item="item" separator=",">
|
||||
(#{item.id,jdbcType=VARCHAR}, #{item.name,jdbcType=VARCHAR}, #{item.type,jdbcType=VARCHAR},
|
||||
#{item.size,jdbcType=BIGINT}, #{item.createTime,jdbcType=BIGINT}, #{item.updateTime,jdbcType=BIGINT},
|
||||
#{item.projectId,jdbcType=VARCHAR}, #{item.storage,jdbcType=VARCHAR}, #{item.createUser,jdbcType=VARCHAR},
|
||||
#{item.updateUser,jdbcType=VARCHAR}, #{item.tags,jdbcType=VARCHAR}, #{item.description,jdbcType=VARCHAR},
|
||||
#{item.moduleId,jdbcType=VARCHAR}, #{item.loadJar,jdbcType=BIT}, #{item.path,jdbcType=VARCHAR},
|
||||
#{item.resourceType,jdbcType=VARCHAR}, #{item.latest,jdbcType=BIT}, #{item.refId,jdbcType=VARCHAR}
|
||||
)
|
||||
#{item.moduleId,jdbcType=VARCHAR}, #{item.path,jdbcType=VARCHAR}, #{item.latest,jdbcType=BIT},
|
||||
#{item.refId,jdbcType=VARCHAR}, #{item.fileVersion,jdbcType=VARCHAR})
|
||||
</foreach>
|
||||
</insert>
|
||||
<insert id="batchInsertSelective" parameterType="map">
|
||||
|
@ -480,21 +461,18 @@
|
|||
<if test="'module_id'.toString() == column.value">
|
||||
#{item.moduleId,jdbcType=VARCHAR}
|
||||
</if>
|
||||
<if test="'load_jar'.toString() == column.value">
|
||||
#{item.loadJar,jdbcType=BIT}
|
||||
</if>
|
||||
<if test="'path'.toString() == column.value">
|
||||
#{item.path,jdbcType=VARCHAR}
|
||||
</if>
|
||||
<if test="'resource_type'.toString() == column.value">
|
||||
#{item.resourceType,jdbcType=VARCHAR}
|
||||
</if>
|
||||
<if test="'latest'.toString() == column.value">
|
||||
#{item.latest,jdbcType=BIT}
|
||||
</if>
|
||||
<if test="'ref_id'.toString() == column.value">
|
||||
#{item.refId,jdbcType=VARCHAR}
|
||||
</if>
|
||||
<if test="'file_version'.toString() == column.value">
|
||||
#{item.fileVersion,jdbcType=VARCHAR}
|
||||
</if>
|
||||
</foreach>
|
||||
)
|
||||
</foreach>
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
package io.metersphere.project.mapper;
|
||||
|
||||
import io.metersphere.project.domain.FileMetadataRepository;
|
||||
import io.metersphere.project.domain.FileMetadataRepositoryExample;
|
||||
import java.util.List;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
public interface FileMetadataRepositoryMapper {
|
||||
long countByExample(FileMetadataRepositoryExample example);
|
||||
|
||||
int deleteByExample(FileMetadataRepositoryExample example);
|
||||
|
||||
int deleteByPrimaryKey(String id);
|
||||
|
||||
int insert(FileMetadataRepository record);
|
||||
|
||||
int insertSelective(FileMetadataRepository record);
|
||||
|
||||
List<FileMetadataRepository> selectByExampleWithBLOBs(FileMetadataRepositoryExample example);
|
||||
|
||||
List<FileMetadataRepository> selectByExample(FileMetadataRepositoryExample example);
|
||||
|
||||
FileMetadataRepository selectByPrimaryKey(String id);
|
||||
|
||||
int updateByExampleSelective(@Param("record") FileMetadataRepository record, @Param("example") FileMetadataRepositoryExample example);
|
||||
|
||||
int updateByExampleWithBLOBs(@Param("record") FileMetadataRepository record, @Param("example") FileMetadataRepositoryExample example);
|
||||
|
||||
int updateByExample(@Param("record") FileMetadataRepository record, @Param("example") FileMetadataRepositoryExample example);
|
||||
|
||||
int updateByPrimaryKeySelective(FileMetadataRepository record);
|
||||
|
||||
int updateByPrimaryKeyWithBLOBs(FileMetadataRepository record);
|
||||
|
||||
int batchInsert(@Param("list") List<FileMetadataRepository> list);
|
||||
|
||||
int batchInsertSelective(@Param("list") List<FileMetadataRepository> list, @Param("selective") FileMetadataRepository.Column ... selective);
|
||||
}
|
|
@ -1,10 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="io.metersphere.project.mapper.FileMetadataBlobMapper">
|
||||
<resultMap id="BaseResultMap" type="io.metersphere.project.domain.FileMetadataBlob">
|
||||
<mapper namespace="io.metersphere.project.mapper.FileMetadataRepositoryMapper">
|
||||
<resultMap id="BaseResultMap" type="io.metersphere.project.domain.FileMetadataRepository">
|
||||
<id column="id" jdbcType="VARCHAR" property="id" />
|
||||
</resultMap>
|
||||
<resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="io.metersphere.project.domain.FileMetadataBlob">
|
||||
<resultMap extends="BaseResultMap" id="ResultMapWithBLOBs" type="io.metersphere.project.domain.FileMetadataRepository">
|
||||
<result column="git_info" jdbcType="LONGVARBINARY" property="gitInfo" />
|
||||
</resultMap>
|
||||
<sql id="Example_Where_Clause">
|
||||
|
@ -71,7 +71,7 @@
|
|||
<sql id="Blob_Column_List">
|
||||
git_info
|
||||
</sql>
|
||||
<select id="selectByExampleWithBLOBs" parameterType="io.metersphere.project.domain.FileMetadataBlobExample" resultMap="ResultMapWithBLOBs">
|
||||
<select id="selectByExampleWithBLOBs" parameterType="io.metersphere.project.domain.FileMetadataRepositoryExample" resultMap="ResultMapWithBLOBs">
|
||||
select
|
||||
<if test="distinct">
|
||||
distinct
|
||||
|
@ -79,7 +79,7 @@
|
|||
<include refid="Base_Column_List" />
|
||||
,
|
||||
<include refid="Blob_Column_List" />
|
||||
from file_metadata_blob
|
||||
from file_metadata_repository
|
||||
<if test="_parameter != null">
|
||||
<include refid="Example_Where_Clause" />
|
||||
</if>
|
||||
|
@ -87,13 +87,13 @@
|
|||
order by ${orderByClause}
|
||||
</if>
|
||||
</select>
|
||||
<select id="selectByExample" parameterType="io.metersphere.project.domain.FileMetadataBlobExample" resultMap="BaseResultMap">
|
||||
<select id="selectByExample" parameterType="io.metersphere.project.domain.FileMetadataRepositoryExample" resultMap="BaseResultMap">
|
||||
select
|
||||
<if test="distinct">
|
||||
distinct
|
||||
</if>
|
||||
<include refid="Base_Column_List" />
|
||||
from file_metadata_blob
|
||||
from file_metadata_repository
|
||||
<if test="_parameter != null">
|
||||
<include refid="Example_Where_Clause" />
|
||||
</if>
|
||||
|
@ -106,25 +106,25 @@
|
|||
<include refid="Base_Column_List" />
|
||||
,
|
||||
<include refid="Blob_Column_List" />
|
||||
from file_metadata_blob
|
||||
from file_metadata_repository
|
||||
where id = #{id,jdbcType=VARCHAR}
|
||||
</select>
|
||||
<delete id="deleteByPrimaryKey" parameterType="java.lang.String">
|
||||
delete from file_metadata_blob
|
||||
delete from file_metadata_repository
|
||||
where id = #{id,jdbcType=VARCHAR}
|
||||
</delete>
|
||||
<delete id="deleteByExample" parameterType="io.metersphere.project.domain.FileMetadataBlobExample">
|
||||
delete from file_metadata_blob
|
||||
<delete id="deleteByExample" parameterType="io.metersphere.project.domain.FileMetadataRepositoryExample">
|
||||
delete from file_metadata_repository
|
||||
<if test="_parameter != null">
|
||||
<include refid="Example_Where_Clause" />
|
||||
</if>
|
||||
</delete>
|
||||
<insert id="insert" parameterType="io.metersphere.project.domain.FileMetadataBlob">
|
||||
insert into file_metadata_blob (id, git_info)
|
||||
<insert id="insert" parameterType="io.metersphere.project.domain.FileMetadataRepository">
|
||||
insert into file_metadata_repository (id, git_info)
|
||||
values (#{id,jdbcType=VARCHAR}, #{gitInfo,jdbcType=LONGVARBINARY})
|
||||
</insert>
|
||||
<insert id="insertSelective" parameterType="io.metersphere.project.domain.FileMetadataBlob">
|
||||
insert into file_metadata_blob
|
||||
<insert id="insertSelective" parameterType="io.metersphere.project.domain.FileMetadataRepository">
|
||||
insert into file_metadata_repository
|
||||
<trim prefix="(" suffix=")" suffixOverrides=",">
|
||||
<if test="id != null">
|
||||
id,
|
||||
|
@ -142,14 +142,14 @@
|
|||
</if>
|
||||
</trim>
|
||||
</insert>
|
||||
<select id="countByExample" parameterType="io.metersphere.project.domain.FileMetadataBlobExample" resultType="java.lang.Long">
|
||||
select count(*) from file_metadata_blob
|
||||
<select id="countByExample" parameterType="io.metersphere.project.domain.FileMetadataRepositoryExample" resultType="java.lang.Long">
|
||||
select count(*) from file_metadata_repository
|
||||
<if test="_parameter != null">
|
||||
<include refid="Example_Where_Clause" />
|
||||
</if>
|
||||
</select>
|
||||
<update id="updateByExampleSelective" parameterType="map">
|
||||
update file_metadata_blob
|
||||
update file_metadata_repository
|
||||
<set>
|
||||
<if test="record.id != null">
|
||||
id = #{record.id,jdbcType=VARCHAR},
|
||||
|
@ -163,7 +163,7 @@
|
|||
</if>
|
||||
</update>
|
||||
<update id="updateByExampleWithBLOBs" parameterType="map">
|
||||
update file_metadata_blob
|
||||
update file_metadata_repository
|
||||
set id = #{record.id,jdbcType=VARCHAR},
|
||||
git_info = #{record.gitInfo,jdbcType=LONGVARBINARY}
|
||||
<if test="_parameter != null">
|
||||
|
@ -171,14 +171,14 @@
|
|||
</if>
|
||||
</update>
|
||||
<update id="updateByExample" parameterType="map">
|
||||
update file_metadata_blob
|
||||
update file_metadata_repository
|
||||
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.project.domain.FileMetadataBlob">
|
||||
update file_metadata_blob
|
||||
<update id="updateByPrimaryKeySelective" parameterType="io.metersphere.project.domain.FileMetadataRepository">
|
||||
update file_metadata_repository
|
||||
<set>
|
||||
<if test="gitInfo != null">
|
||||
git_info = #{gitInfo,jdbcType=LONGVARBINARY},
|
||||
|
@ -186,13 +186,13 @@
|
|||
</set>
|
||||
where id = #{id,jdbcType=VARCHAR}
|
||||
</update>
|
||||
<update id="updateByPrimaryKeyWithBLOBs" parameterType="io.metersphere.project.domain.FileMetadataBlob">
|
||||
update file_metadata_blob
|
||||
<update id="updateByPrimaryKeyWithBLOBs" parameterType="io.metersphere.project.domain.FileMetadataRepository">
|
||||
update file_metadata_repository
|
||||
set git_info = #{gitInfo,jdbcType=LONGVARBINARY}
|
||||
where id = #{id,jdbcType=VARCHAR}
|
||||
</update>
|
||||
<insert id="batchInsert" parameterType="map">
|
||||
insert into file_metadata_blob
|
||||
insert into file_metadata_repository
|
||||
(id, git_info)
|
||||
values
|
||||
<foreach collection="list" item="item" separator=",">
|
||||
|
@ -200,7 +200,7 @@
|
|||
</foreach>
|
||||
</insert>
|
||||
<insert id="batchInsertSelective" parameterType="map">
|
||||
insert into file_metadata_blob (
|
||||
insert into file_metadata_repository (
|
||||
<foreach collection="selective" item="column" separator=",">
|
||||
${column.escapedColumnName}
|
||||
</foreach>
|
|
@ -6,10 +6,10 @@
|
|||
<result column="project_id" jdbcType="VARCHAR" property="projectId" />
|
||||
<result column="name" jdbcType="VARCHAR" property="name" />
|
||||
<result column="parent_id" jdbcType="VARCHAR" property="parentId" />
|
||||
<result column="level" jdbcType="INTEGER" property="level" />
|
||||
<result column="create_time" jdbcType="BIGINT" property="createTime" />
|
||||
<result column="update_time" jdbcType="BIGINT" property="updateTime" />
|
||||
<result column="pos" jdbcType="DOUBLE" property="pos" />
|
||||
<result column="pos" jdbcType="INTEGER" property="pos" />
|
||||
<result column="update_user" jdbcType="VARCHAR" property="updateUser" />
|
||||
<result column="create_user" jdbcType="VARCHAR" property="createUser" />
|
||||
<result column="module_type" jdbcType="VARCHAR" property="moduleType" />
|
||||
</resultMap>
|
||||
|
@ -72,7 +72,7 @@
|
|||
</where>
|
||||
</sql>
|
||||
<sql id="Base_Column_List">
|
||||
id, project_id, `name`, parent_id, `level`, create_time, update_time, pos, create_user,
|
||||
id, project_id, `name`, parent_id, create_time, update_time, pos, update_user, create_user,
|
||||
module_type
|
||||
</sql>
|
||||
<select id="selectByExample" parameterType="io.metersphere.project.domain.FileModuleExample" resultMap="BaseResultMap">
|
||||
|
@ -107,12 +107,12 @@
|
|||
</delete>
|
||||
<insert id="insert" parameterType="io.metersphere.project.domain.FileModule">
|
||||
insert into file_module (id, project_id, `name`,
|
||||
parent_id, `level`, create_time,
|
||||
update_time, pos, create_user,
|
||||
parent_id, create_time, update_time,
|
||||
pos, update_user, create_user,
|
||||
module_type)
|
||||
values (#{id,jdbcType=VARCHAR}, #{projectId,jdbcType=VARCHAR}, #{name,jdbcType=VARCHAR},
|
||||
#{parentId,jdbcType=VARCHAR}, #{level,jdbcType=INTEGER}, #{createTime,jdbcType=BIGINT},
|
||||
#{updateTime,jdbcType=BIGINT}, #{pos,jdbcType=DOUBLE}, #{createUser,jdbcType=VARCHAR},
|
||||
#{parentId,jdbcType=VARCHAR}, #{createTime,jdbcType=BIGINT}, #{updateTime,jdbcType=BIGINT},
|
||||
#{pos,jdbcType=INTEGER}, #{updateUser,jdbcType=VARCHAR}, #{createUser,jdbcType=VARCHAR},
|
||||
#{moduleType,jdbcType=VARCHAR})
|
||||
</insert>
|
||||
<insert id="insertSelective" parameterType="io.metersphere.project.domain.FileModule">
|
||||
|
@ -130,9 +130,6 @@
|
|||
<if test="parentId != null">
|
||||
parent_id,
|
||||
</if>
|
||||
<if test="level != null">
|
||||
`level`,
|
||||
</if>
|
||||
<if test="createTime != null">
|
||||
create_time,
|
||||
</if>
|
||||
|
@ -142,6 +139,9 @@
|
|||
<if test="pos != null">
|
||||
pos,
|
||||
</if>
|
||||
<if test="updateUser != null">
|
||||
update_user,
|
||||
</if>
|
||||
<if test="createUser != null">
|
||||
create_user,
|
||||
</if>
|
||||
|
@ -162,9 +162,6 @@
|
|||
<if test="parentId != null">
|
||||
#{parentId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="level != null">
|
||||
#{level,jdbcType=INTEGER},
|
||||
</if>
|
||||
<if test="createTime != null">
|
||||
#{createTime,jdbcType=BIGINT},
|
||||
</if>
|
||||
|
@ -172,7 +169,10 @@
|
|||
#{updateTime,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="pos != null">
|
||||
#{pos,jdbcType=DOUBLE},
|
||||
#{pos,jdbcType=INTEGER},
|
||||
</if>
|
||||
<if test="updateUser != null">
|
||||
#{updateUser,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="createUser != null">
|
||||
#{createUser,jdbcType=VARCHAR},
|
||||
|
@ -203,9 +203,6 @@
|
|||
<if test="record.parentId != null">
|
||||
parent_id = #{record.parentId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.level != null">
|
||||
`level` = #{record.level,jdbcType=INTEGER},
|
||||
</if>
|
||||
<if test="record.createTime != null">
|
||||
create_time = #{record.createTime,jdbcType=BIGINT},
|
||||
</if>
|
||||
|
@ -213,7 +210,10 @@
|
|||
update_time = #{record.updateTime,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="record.pos != null">
|
||||
pos = #{record.pos,jdbcType=DOUBLE},
|
||||
pos = #{record.pos,jdbcType=INTEGER},
|
||||
</if>
|
||||
<if test="record.updateUser != null">
|
||||
update_user = #{record.updateUser,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="record.createUser != null">
|
||||
create_user = #{record.createUser,jdbcType=VARCHAR},
|
||||
|
@ -232,10 +232,10 @@
|
|||
project_id = #{record.projectId,jdbcType=VARCHAR},
|
||||
`name` = #{record.name,jdbcType=VARCHAR},
|
||||
parent_id = #{record.parentId,jdbcType=VARCHAR},
|
||||
`level` = #{record.level,jdbcType=INTEGER},
|
||||
create_time = #{record.createTime,jdbcType=BIGINT},
|
||||
update_time = #{record.updateTime,jdbcType=BIGINT},
|
||||
pos = #{record.pos,jdbcType=DOUBLE},
|
||||
pos = #{record.pos,jdbcType=INTEGER},
|
||||
update_user = #{record.updateUser,jdbcType=VARCHAR},
|
||||
create_user = #{record.createUser,jdbcType=VARCHAR},
|
||||
module_type = #{record.moduleType,jdbcType=VARCHAR}
|
||||
<if test="_parameter != null">
|
||||
|
@ -254,9 +254,6 @@
|
|||
<if test="parentId != null">
|
||||
parent_id = #{parentId,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="level != null">
|
||||
`level` = #{level,jdbcType=INTEGER},
|
||||
</if>
|
||||
<if test="createTime != null">
|
||||
create_time = #{createTime,jdbcType=BIGINT},
|
||||
</if>
|
||||
|
@ -264,7 +261,10 @@
|
|||
update_time = #{updateTime,jdbcType=BIGINT},
|
||||
</if>
|
||||
<if test="pos != null">
|
||||
pos = #{pos,jdbcType=DOUBLE},
|
||||
pos = #{pos,jdbcType=INTEGER},
|
||||
</if>
|
||||
<if test="updateUser != null">
|
||||
update_user = #{updateUser,jdbcType=VARCHAR},
|
||||
</if>
|
||||
<if test="createUser != null">
|
||||
create_user = #{createUser,jdbcType=VARCHAR},
|
||||
|
@ -280,23 +280,23 @@
|
|||
set project_id = #{projectId,jdbcType=VARCHAR},
|
||||
`name` = #{name,jdbcType=VARCHAR},
|
||||
parent_id = #{parentId,jdbcType=VARCHAR},
|
||||
`level` = #{level,jdbcType=INTEGER},
|
||||
create_time = #{createTime,jdbcType=BIGINT},
|
||||
update_time = #{updateTime,jdbcType=BIGINT},
|
||||
pos = #{pos,jdbcType=DOUBLE},
|
||||
pos = #{pos,jdbcType=INTEGER},
|
||||
update_user = #{updateUser,jdbcType=VARCHAR},
|
||||
create_user = #{createUser,jdbcType=VARCHAR},
|
||||
module_type = #{moduleType,jdbcType=VARCHAR}
|
||||
where id = #{id,jdbcType=VARCHAR}
|
||||
</update>
|
||||
<insert id="batchInsert" parameterType="map">
|
||||
insert into file_module
|
||||
(id, project_id, `name`, parent_id, `level`, create_time, update_time, pos, create_user,
|
||||
(id, project_id, `name`, parent_id, create_time, update_time, pos, update_user, create_user,
|
||||
module_type)
|
||||
values
|
||||
<foreach collection="list" item="item" separator=",">
|
||||
(#{item.id,jdbcType=VARCHAR}, #{item.projectId,jdbcType=VARCHAR}, #{item.name,jdbcType=VARCHAR},
|
||||
#{item.parentId,jdbcType=VARCHAR}, #{item.level,jdbcType=INTEGER}, #{item.createTime,jdbcType=BIGINT},
|
||||
#{item.updateTime,jdbcType=BIGINT}, #{item.pos,jdbcType=DOUBLE}, #{item.createUser,jdbcType=VARCHAR},
|
||||
#{item.parentId,jdbcType=VARCHAR}, #{item.createTime,jdbcType=BIGINT}, #{item.updateTime,jdbcType=BIGINT},
|
||||
#{item.pos,jdbcType=INTEGER}, #{item.updateUser,jdbcType=VARCHAR}, #{item.createUser,jdbcType=VARCHAR},
|
||||
#{item.moduleType,jdbcType=VARCHAR})
|
||||
</foreach>
|
||||
</insert>
|
||||
|
@ -322,9 +322,6 @@
|
|||
<if test="'parent_id'.toString() == column.value">
|
||||
#{item.parentId,jdbcType=VARCHAR}
|
||||
</if>
|
||||
<if test="'level'.toString() == column.value">
|
||||
#{item.level,jdbcType=INTEGER}
|
||||
</if>
|
||||
<if test="'create_time'.toString() == column.value">
|
||||
#{item.createTime,jdbcType=BIGINT}
|
||||
</if>
|
||||
|
@ -332,7 +329,10 @@
|
|||
#{item.updateTime,jdbcType=BIGINT}
|
||||
</if>
|
||||
<if test="'pos'.toString() == column.value">
|
||||
#{item.pos,jdbcType=DOUBLE}
|
||||
#{item.pos,jdbcType=INTEGER}
|
||||
</if>
|
||||
<if test="'update_user'.toString() == column.value">
|
||||
#{item.updateUser,jdbcType=VARCHAR}
|
||||
</if>
|
||||
<if test="'create_user'.toString() == column.value">
|
||||
#{item.createUser,jdbcType=VARCHAR}
|
||||
|
|
|
@ -1,35 +1,39 @@
|
|||
package io.metersphere.system.domain;
|
||||
|
||||
import io.metersphere.validation.groups.*;
|
||||
import io.metersphere.validation.groups.Created;
|
||||
import io.metersphere.validation.groups.Updated;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.*;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Size;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class UserInvite implements Serializable {
|
||||
@Schema(title = "用户ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@Schema(description = "用户ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{user_invite.id.not_blank}", groups = {Updated.class})
|
||||
@Size(min = 1, max = 50, message = "{user_invite.id.length_range}", groups = {Created.class, Updated.class})
|
||||
private String id;
|
||||
|
||||
@Schema(title = "邀请邮箱", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@Schema(description = "邀请邮箱", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{user_invite.email.not_blank}", groups = {Created.class})
|
||||
@Size(min = 1, max = 255, message = "{user_invite.email.length_range}", groups = {Created.class, Updated.class})
|
||||
private String email;
|
||||
|
||||
@Schema(title = "邀请用户", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@Schema(description = "邀请用户", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{user_invite.invite_user.not_blank}", groups = {Created.class})
|
||||
@Size(min = 1, max = 50, message = "{user_invite.invite_user.length_range}", groups = {Created.class, Updated.class})
|
||||
private String inviteUser;
|
||||
|
||||
@Schema(title = "邀请时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@Schema(description = "邀请时间", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotNull(message = "{user_invite.invite_time.not_blank}", groups = {Created.class})
|
||||
private Long inviteTime;
|
||||
|
||||
@Schema(title = "所属权限")
|
||||
@Schema(description = "所属权限")
|
||||
private String roles;
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
|
|
@ -62,30 +62,41 @@ CREATE INDEX idx_file_metadata_id ON file_association (file_metadata_id);
|
|||
CREATE INDEX idx_project_id ON file_association (project_id);
|
||||
CREATE INDEX idx_source_id ON file_association (source_id);
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS file_metadata_repository
|
||||
(
|
||||
`id` VARCHAR(50) NOT NULL COMMENT '文件ID',
|
||||
`git_info` LONGBLOB COMMENT '储存库',
|
||||
PRIMARY KEY (id)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci
|
||||
COMMENT = '文件基础信息大字段';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS file_metadata
|
||||
(
|
||||
`id` VARCHAR(50) NOT NULL COMMENT '文件ID',
|
||||
`name` VARCHAR(255) NOT NULL COMMENT '文件名',
|
||||
`type` VARCHAR(64) COMMENT '文件类型',
|
||||
`size` BIGINT NOT NULL COMMENT '文件大小',
|
||||
`create_time` BIGINT NOT NULL COMMENT '创建时间',
|
||||
`update_time` BIGINT NOT NULL COMMENT '更新时间',
|
||||
`project_id` VARCHAR(50) NOT NULL COMMENT '项目ID',
|
||||
`storage` VARCHAR(50) NOT NULL DEFAULT 'MINIO' COMMENT '文件存储方式',
|
||||
`create_user` VARCHAR(50) NOT NULL COMMENT '创建人',
|
||||
`update_user` VARCHAR(50) NOT NULL COMMENT '修改人',
|
||||
`tags` VARCHAR(1000) COMMENT '标签',
|
||||
`description` VARCHAR(500) COMMENT '描述',
|
||||
`module_id` VARCHAR(50) COMMENT '文件所属模块',
|
||||
`load_jar` BIT DEFAULT 0 COMMENT '是否加载jar(开启后用于接口测试执行时使用)',
|
||||
`path` VARCHAR(1000) COMMENT '文件存储路径',
|
||||
`resource_type` VARCHAR(50) COMMENT '资源作用范围,主要兼容2.1版本前的历史数据,后续版本不再产生数据',
|
||||
`latest` BIT NOT NULL DEFAULT 1 COMMENT '是否是最新版',
|
||||
`ref_id` VARCHAR(50) NOT NULL COMMENT '同版本数据关联的ID',
|
||||
`id` VARCHAR(50) NOT NULL COMMENT '文件ID',
|
||||
`name` VARCHAR(255) NOT NULL COMMENT '文件名',
|
||||
`type` VARCHAR(64) COMMENT '文件类型',
|
||||
`size` BIGINT NOT NULL COMMENT '文件大小',
|
||||
`create_time` BIGINT NOT NULL COMMENT '创建时间',
|
||||
`update_time` BIGINT NOT NULL COMMENT '更新时间',
|
||||
`project_id` VARCHAR(50) NOT NULL COMMENT '项目ID',
|
||||
`storage` VARCHAR(50) NOT NULL DEFAULT 'MINIO' COMMENT '文件存储方式',
|
||||
`create_user` VARCHAR(50) NOT NULL COMMENT '创建人',
|
||||
`update_user` VARCHAR(50) NOT NULL COMMENT '修改人',
|
||||
`tags` VARCHAR(1000) COMMENT '标签',
|
||||
`description` VARCHAR(500) COMMENT '描述',
|
||||
`module_id` VARCHAR(50) COMMENT '文件所属模块',
|
||||
`path` VARCHAR(1000) COMMENT '文件存储路径',
|
||||
`latest` BIT NOT NULL DEFAULT 1 COMMENT '是否是最新版',
|
||||
`ref_id` VARCHAR(50) NOT NULL COMMENT '同版本数据关联的ID',
|
||||
`file_version` VARCHAR(50) COMMENT '文件版本号',
|
||||
PRIMARY KEY (id)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci COMMENT = '文件基础信息';
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci
|
||||
COMMENT = '文件基础信息';
|
||||
|
||||
|
||||
CREATE INDEX idx_file_name ON file_metadata (name);
|
||||
|
@ -95,22 +106,24 @@ CREATE INDEX idx_storage ON file_metadata (storage);
|
|||
CREATE INDEX idx_module_id ON file_metadata (module_id);
|
||||
CREATE INDEX idx_project_id ON file_metadata (project_id);
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS file_module
|
||||
(
|
||||
`id` VARCHAR(50) NOT NULL COMMENT 'ID',
|
||||
`project_id` VARCHAR(50) NOT NULL COMMENT '项目ID',
|
||||
`name` VARCHAR(64) NOT NULL COMMENT '模块名称',
|
||||
`parent_id` VARCHAR(50) COMMENT '父级ID',
|
||||
`level` INT DEFAULT 1 COMMENT '层数',
|
||||
`create_time` BIGINT NOT NULL COMMENT '创建时间',
|
||||
`update_time` BIGINT NOT NULL COMMENT '更新时间',
|
||||
`pos` DOUBLE COMMENT '排序用的标识',
|
||||
`pos` INT NOT NULL DEFAULT 0 COMMENT '排序用的标识',
|
||||
`update_user` VARCHAR(50) COMMENT '修改人',
|
||||
`create_user` VARCHAR(50) COMMENT '创建人',
|
||||
`module_type` VARCHAR(20) DEFAULT 'module' COMMENT '模块类型: module/repository',
|
||||
PRIMARY KEY (id)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci COMMENT = '文件管理模块';
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci
|
||||
COMMENT = '文件管理模块';
|
||||
|
||||
|
||||
CREATE INDEX idx_project_id ON file_module (project_id);
|
||||
|
@ -120,6 +133,7 @@ CREATE INDEX idx_update_timed ON file_module (update_time);
|
|||
CREATE INDEX idx_pos ON file_module (pos);
|
||||
CREATE INDEX idx_create_user ON file_module (create_user);
|
||||
|
||||
|
||||
CREATE TABLE IF NOT EXISTS project
|
||||
(
|
||||
`id` VARCHAR(50) NOT NULL COMMENT '项目ID',
|
||||
|
@ -214,15 +228,6 @@ CREATE TABLE IF NOT EXISTS custom_function_blob
|
|||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci COMMENT = '自定义函数-代码片段大字段';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS file_metadata_blob
|
||||
(
|
||||
`id` VARCHAR(50) NOT NULL COMMENT '文件ID',
|
||||
`git_info` LONGBLOB COMMENT '储存库',
|
||||
PRIMARY KEY (id)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci COMMENT = '文件基础信息大字段';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS message_task
|
||||
(
|
||||
`id` VARCHAR(50) NOT NULL COMMENT '' ,
|
||||
|
|
|
@ -90,6 +90,11 @@ INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT
|
|||
INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_admin', 'PROJECT_ENVIRONMENT:READ+UPDATE');
|
||||
INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_admin', 'PROJECT_ENVIRONMENT:READ+DELETE');
|
||||
INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_admin', 'PROJECT_FILE:READ');
|
||||
INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_admin', 'PROJECT_FILE_MANAGEMENT:READ');
|
||||
INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_admin', 'PROJECT_FILE_MANAGEMENT:READ+ADD');
|
||||
INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_admin', 'PROJECT_FILE_MANAGEMENT:READ+UPDATE');
|
||||
INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_admin', 'PROJECT_FILE_MANAGEMENT:READ+DOWNLOAD');
|
||||
INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_admin', 'PROJECT_FILE_MANAGEMENT:READ+DELETE');
|
||||
INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_admin', 'PROJECT_TEMPLATE:READ');
|
||||
INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_admin', 'PROJECT_MESSAGE:READ');
|
||||
INSERT INTO user_role_permission (id, role_id, permission_id) VALUES (UUID_SHORT(), 'project_admin', 'PROJECT_MESSAGE:READ+ADD');
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
package io.metersphere.sdk.constants;
|
||||
|
||||
public class ModuleConstants {
|
||||
//未规划节点的ID
|
||||
public static final String DEFAULT_NODE_ID = "root";
|
||||
//没有父类的节点,parent_id为none
|
||||
public static final String ROOT_NODE_PARENT_ID = "none";
|
||||
//默认节点类型
|
||||
public static final String NODE_TYPE_DEFAULT = "module";
|
||||
//GitHub节点类型
|
||||
public static final String NODE_TYPE_GITHUB = "GitHub";
|
||||
//Gitee节点类型
|
||||
public static final String NODE_TYPE_GITEE = "Gitee";
|
||||
//GitLab节点类型
|
||||
public static final String NODE_TYPE_GITLAB = "GitLab";
|
||||
}
|
|
@ -185,4 +185,20 @@ public class PermissionConstants {
|
|||
public static final String PROJECT_VERSION_READ_UPDATE = "PROJECT_VERSION:READ+UPDATE";
|
||||
public static final String PROJECT_VERSION_READ_DELETE = "PROJECT_VERSION:READ+DELETE";
|
||||
/*------ end: PROJECT_VERSION ------*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 文件模块树
|
||||
* 查看文件: 项目管理-文件管理-查询权限
|
||||
* 添加文件: 项目管理-文件管理-创建权限
|
||||
* 编辑文件: 项目管理-文件管理-编辑权限
|
||||
* 下载文件: 项目管理-文件管理-下载权限
|
||||
* 删除文件: 项目管理-文件管理-删除权限
|
||||
*/
|
||||
public static final String PROJECT_FILE_MANAGEMENT_READ = "PROJECT_FILE_MANAGEMENT:READ";
|
||||
public static final String PROJECT_FILE_MANAGEMENT_READ_ADD = "PROJECT_FILE_MANAGEMENT:READ+ADD";
|
||||
public static final String PROJECT_FILE_MANAGEMENT_READ_UPDATE = "PROJECT_FILE_MANAGEMENT:READ+UPDATE";
|
||||
public static final String PROJECT_FILE_MANAGEMENT_READ_DOWNLOAD = "PROJECT_FILE_MANAGEMENT:READ+DOWNLOAD";
|
||||
public static final String PROJECT_FILE_MANAGEMENT_READ_DELETE = "PROJECT_FILE_MANAGEMENT:READ+DELETE";
|
||||
}
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
package io.metersphere.sdk.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class BaseModule {
|
||||
@Schema(description = "节点id")
|
||||
private String id;
|
||||
|
||||
@Schema(description = "节点名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "排序单位")
|
||||
private int pos;
|
||||
|
||||
@Schema(description = "项目ID")
|
||||
private String projectId;
|
||||
|
||||
@Schema(description = "父节点id")
|
||||
private String parentId;
|
||||
|
||||
}
|
|
@ -21,18 +21,27 @@ public class BaseTreeNode {
|
|||
private String type;
|
||||
|
||||
@Schema(description = "是否是叶子节点")
|
||||
private boolean leafNode;
|
||||
private boolean leafNode = false;
|
||||
|
||||
// @Schema(description = "排序单位")
|
||||
// private int pos;
|
||||
|
||||
@Schema(description = "子节点")
|
||||
private List<BaseTreeNode> children = new ArrayList<>();
|
||||
|
||||
public BaseTreeNode(String id, String name, String type, boolean isLeafNode) {
|
||||
public BaseTreeNode(String id, String name, String type) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
this.leafNode = isLeafNode;
|
||||
}
|
||||
|
||||
// public BaseTreeNode(String id, String name, String type, int pos) {
|
||||
// this.id = id;
|
||||
// this.name = name;
|
||||
// this.type = type;
|
||||
// this.pos = pos;
|
||||
// }
|
||||
|
||||
public void addChild(BaseTreeNode node) {
|
||||
this.leafNode = false;
|
||||
children.add(node);
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
package io.metersphere.sdk.dto;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class RemoteFileAttachInfo implements Serializable {
|
||||
private String repositoryPath;
|
||||
private String userName;
|
||||
private String token;
|
||||
private String branch;
|
||||
private String commitId;
|
||||
private String filePath;
|
||||
private String commitMessage;
|
||||
private long size;
|
||||
|
||||
public String getRepositoryInfo() {
|
||||
return repositoryPath + "-" + userName + "-" + token;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package io.metersphere.sdk.dto.request;
|
||||
|
||||
import io.metersphere.sdk.constants.ModuleConstants;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class NodeMoveRequest {
|
||||
@Schema(description = "模块ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotEmpty(message = "{node.not_blank}")
|
||||
private String nodeId;
|
||||
|
||||
@Schema(description = "父模块ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotEmpty(message = "{parent.node.not_blank}")
|
||||
private String parentId = ModuleConstants.ROOT_NODE_PARENT_ID;
|
||||
|
||||
@Schema(description = "前一个节点ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private String previousNodeId;
|
||||
|
||||
@Schema(description = "后一个节点ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
private String nextNodeId;
|
||||
}
|
||||
|
|
@ -17,6 +17,16 @@ public class FileCenter {
|
|||
return fileRepository == null ? getDefaultRepository() : fileRepository;
|
||||
}
|
||||
|
||||
public static FileRepository getRepository(String storage) {
|
||||
Map<String, StorageType> storageTypeMap = new HashMap<>() {{
|
||||
put(StorageType.MINIO.name(), StorageType.MINIO);
|
||||
put(StorageType.LOCAL.name(), StorageType.LOCAL);
|
||||
put(StorageType.GIT.name(), StorageType.GIT);
|
||||
}};
|
||||
|
||||
return getRepository(storageTypeMap.get(storage.toUpperCase()));
|
||||
}
|
||||
|
||||
public static FileRepository getDefaultRepository() {
|
||||
return CommonBeanFactory.getBean(MinioRepository.class);
|
||||
}
|
||||
|
|
|
@ -8,7 +8,10 @@ import org.apache.commons.lang3.StringUtils;
|
|||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.*;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -38,7 +41,7 @@ public class MinioRepository implements FileRepository {
|
|||
.object(filePath)
|
||||
.stream(file.getInputStream(), file.getSize(), -1) // 文件内容
|
||||
.build());
|
||||
return request.getFileName();
|
||||
return filePath;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
package io.metersphere.sdk.mapper;
|
||||
|
||||
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
public interface BaseModuleMapper {
|
||||
long addResourceCount(@Param("tableName") String tableName, @Param("primaryKey") String primaryKey, @Param("count") int count);
|
||||
long subResourceCount(@Param("tableName") String tableName, @Param("primaryKey") String primaryKey, @Param("count") int count);
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
<?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.BaseModuleMapper">
|
||||
|
||||
<update id="addResourceCount">
|
||||
UPDATE #{tableName}
|
||||
SET resource_count = resource_count + #{count}
|
||||
WHERE id = #{primaryKey}
|
||||
</update>
|
||||
<update id="subResourceCount">
|
||||
UPDATE #{tableName}
|
||||
SET resource_count = resource_count - #{count}
|
||||
WHERE id = #{primaryKey}
|
||||
</update>
|
||||
</mapper>
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
package io.metersphere.sdk.service;
|
||||
|
||||
import io.metersphere.sdk.file.FileCenter;
|
||||
import io.metersphere.sdk.file.FileRequest;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
@Service
|
||||
public class FileService {
|
||||
public String upload(MultipartFile file, FileRequest request) throws Exception {
|
||||
return FileCenter.getRepository(request.getStorage()).saveFile(file, request);
|
||||
}
|
||||
|
||||
public byte[] download(FileRequest request) throws Exception {
|
||||
return FileCenter.getRepository(request.getStorage()).getFile(request);
|
||||
}
|
||||
|
||||
public void deleteFile(FileRequest request) throws Exception {
|
||||
FileCenter.getRepository(request.getStorage()).delete(request);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
package io.metersphere.sdk.service;
|
||||
|
||||
import io.metersphere.sdk.constants.ModuleConstants;
|
||||
import io.metersphere.sdk.dto.BaseModule;
|
||||
import io.metersphere.sdk.dto.BaseTreeNode;
|
||||
import io.metersphere.sdk.dto.request.NodeMoveRequest;
|
||||
import io.metersphere.sdk.mapper.BaseModuleMapper;
|
||||
import io.metersphere.sdk.util.Translator;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
public abstract class ModuleTreeService {
|
||||
|
||||
protected static final int LIMIT_POS = 64;
|
||||
|
||||
public BaseTreeNode getDefaultModule() {
|
||||
//默认模块下不允许创建子模块。 它本身也就是叶子节点。
|
||||
return new BaseTreeNode(ModuleConstants.DEFAULT_NODE_ID, Translator.get("default.module"), ModuleConstants.NODE_TYPE_DEFAULT);
|
||||
}
|
||||
|
||||
public long changeResourceCount(String tableName, String primaryKey, int count, boolean isAdd, BaseModuleMapper baseModuleMapper) {
|
||||
if (isAdd) {
|
||||
return baseModuleMapper.addResourceCount(tableName, primaryKey, count);
|
||||
} else {
|
||||
return baseModuleMapper.subResourceCount(tableName, primaryKey, count);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 模块树排序
|
||||
*/
|
||||
public void sort(NodeMoveRequest nodeMoveRequest) {
|
||||
if (StringUtils.isAllBlank(nodeMoveRequest.getPreviousNodeId(), nodeMoveRequest.getNextNodeId())) {
|
||||
// 没有相邻节点,pos为0
|
||||
updatePos(nodeMoveRequest.getNodeId(), 0);
|
||||
} else {
|
||||
BaseModule previousNode = null;
|
||||
BaseModule nextNode = null;
|
||||
// 获取相邻节点
|
||||
if (StringUtils.isNotBlank(nodeMoveRequest.getPreviousNodeId())) {
|
||||
previousNode = getNode(nodeMoveRequest.getPreviousNodeId());
|
||||
}
|
||||
if (StringUtils.isNotBlank(nodeMoveRequest.getNextNodeId())) {
|
||||
nextNode = getNode(nodeMoveRequest.getNextNodeId());
|
||||
}
|
||||
boolean refreshPos = false;
|
||||
int pos;
|
||||
if (nextNode == null) {
|
||||
pos = previousNode.getPos() + LIMIT_POS;
|
||||
} else if (previousNode == null) {
|
||||
pos = nextNode.getPos() / 2;
|
||||
if (pos < 2) {
|
||||
refreshPos = true;
|
||||
}
|
||||
} else {
|
||||
int quantityDifference = (nextNode.getPos() - previousNode.getPos()) / 2;
|
||||
if (quantityDifference <= 2) {
|
||||
refreshPos = true;
|
||||
}
|
||||
pos = previousNode.getPos() + quantityDifference;
|
||||
}
|
||||
|
||||
updatePos(nodeMoveRequest.getNodeId(), pos);
|
||||
if (refreshPos) {
|
||||
refreshPos(nodeMoveRequest.getParentId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public abstract BaseModule getNode(String id);
|
||||
|
||||
public abstract void updatePos(String id, int pos);
|
||||
|
||||
public abstract void refreshPos(String parentId);
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
package io.metersphere.sdk.util;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
public class FilePreviewUtil {
|
||||
private static final String BASE_FILE_FOLDER = File.separator + "opt" + File.separator + "metersphere" + File.separator + "data" + File.separator + "file" + File.separator + "preview" + File.separator;
|
||||
|
||||
public static boolean isImage(String type) {
|
||||
return StringUtils.equalsAnyIgnoreCase(type, "jpg", "jpeg", "png", "gif", "bmp", "svg", "ico");
|
||||
}
|
||||
|
||||
//生成执行文件的绝对路径
|
||||
public static String getFileAbsolutePath(String fileName) {
|
||||
return BASE_FILE_FOLDER + fileName;
|
||||
}
|
||||
|
||||
public static File getFile(String fileName) {
|
||||
File file = new File(getFileAbsolutePath(fileName));
|
||||
if (file.exists()) {
|
||||
return file;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static String catchFileIfNotExists(String fileName, byte[] fileBytes) {
|
||||
if (getFile(fileName) == null && fileBytes != null) {
|
||||
createFile(getFileAbsolutePath(fileName), fileBytes);
|
||||
}
|
||||
return getFileAbsolutePath(fileName);
|
||||
}
|
||||
|
||||
public static void deleteFile(String deleteFileName) {
|
||||
File file = new File(getFileAbsolutePath(deleteFileName));
|
||||
if (file.exists()) {
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
|
||||
private static void createFile(String filePath, byte[] fileBytes) {
|
||||
File file = new File(filePath);
|
||||
if (file.exists()) {
|
||||
file.delete();
|
||||
}
|
||||
try {
|
||||
File dir = file.getParentFile();
|
||||
if (!dir.exists()) {
|
||||
dir.mkdirs();
|
||||
}
|
||||
file.createNewFile();
|
||||
} catch (Exception e) {
|
||||
LogUtils.error(e);
|
||||
}
|
||||
|
||||
try (InputStream in = new ByteArrayInputStream(fileBytes); OutputStream out = new FileOutputStream(file)) {
|
||||
final int MAX = 4096;
|
||||
byte[] buf = new byte[MAX];
|
||||
for (int bytesRead = in.read(buf, 0, MAX); bytesRead != -1; bytesRead = in.read(buf, 0, MAX)) {
|
||||
out.write(buf, 0, bytesRead);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
LogUtils.error(e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -33,7 +33,6 @@ public class JSON {
|
|||
// 设置JSON处理字符长度限制
|
||||
objectMapper.getFactory()
|
||||
.setStreamReadConstraints(StreamReadConstraints.builder().maxStringLength(DEFAULT_MAX_STRING_LEN).build());
|
||||
|
||||
// 处理时间格式
|
||||
objectMapper.registerModule(new JavaTimeModule());
|
||||
}
|
||||
|
|
|
@ -444,4 +444,8 @@ template_scene_illegal_error=使用场景不合法
|
|||
|
||||
# 内置的模板或字段
|
||||
custom_field.functional_priority=优先级
|
||||
template.functional_default=默认模板
|
||||
template.functional_default=默认模板
|
||||
parent.node.not_blank=父节点不能为空
|
||||
node.not_blank=节点不能为空
|
||||
node.name.repeat=节点名称重复
|
||||
project.cannot.match.parent=和父节点的项目无法匹配
|
|
@ -453,3 +453,8 @@ global_parameters_already_exist=Global parameters already exist
|
|||
global_parameters_is_not_exist=Global parameters is not exist
|
||||
api_test_environment_not_exist=Environment is not exist
|
||||
|
||||
|
||||
parent.node.not_blank=Parent node can not blank
|
||||
node.not_blank=Node can not blank
|
||||
node.name.repeat=Name repeat
|
||||
project.cannot.match.parent=Project can not match parent
|
|
@ -449,4 +449,8 @@ template.functional_default=默认模板
|
|||
|
||||
global_parameters_already_exist=全局参数已存在
|
||||
global_parameters_is_not_exist=全局参数不存在
|
||||
parent.node.not_blank=父节点不能为空
|
||||
node.not_blank=节点不能为空
|
||||
node.name.repeat=节点名称重复
|
||||
project.cannot.match.parent=和父节点的项目无法匹配
|
||||
api_test_environment_not_exist=环境不存在
|
|
@ -448,4 +448,9 @@ template.functional_default=默認模板
|
|||
|
||||
global_parameters_already_exist=全局參數已存在
|
||||
global_parameters_is_not_exist=全局參數不存在
|
||||
|
||||
parent.node.not_blank=父節點不能為空
|
||||
node.not_blank=節點不能為空
|
||||
node.name.repeat=節點名稱重複
|
||||
project.cannot.match.parent=和父節點的項目無法匹配
|
||||
api_test_environment_not_exist=環境不存在
|
|
@ -114,3 +114,18 @@ permission.project_application_ui.read=UI测试-查询
|
|||
permission.project_application_ui.update=UI测试-编辑
|
||||
permission.project_base_info.name=基本信息
|
||||
permission.project_log.name=日志
|
||||
#file management
|
||||
file_module.not.exist=文件模块不存在
|
||||
upload.file.error=上传文件失败
|
||||
file.not.exist=文件不存在
|
||||
old.file.not.exist=旧文件不存在
|
||||
file.name.exist=文件名已存在
|
||||
file.log.delete_module=模块下的所有数据全部被删除
|
||||
file.module.root=根目录
|
||||
file.log.move_to=移动到
|
||||
file.log.next=之后
|
||||
file.log.previous=之前
|
||||
file.log.upload=上传
|
||||
file.log.re-upload=重新上传
|
||||
file.name.cannot.be.empty=文件名称不能为空
|
||||
#file management over
|
|
@ -115,6 +115,7 @@ permission.project_user.name=User
|
|||
permission.project_group.name=User group
|
||||
permission.project_environment.name=Environment config
|
||||
permission.project_file.name=File management
|
||||
permission.project_file.download=Download file
|
||||
permission.project_template.name=Template management
|
||||
permission.project_message.name=Message management
|
||||
permission.project_version.name=Version management
|
||||
|
@ -146,3 +147,19 @@ environment_datasource.driverId.not_blank=Driver ID is required
|
|||
environment_datasource.dbUrl.not_blank=Db Url is required
|
||||
environment_name_is_null=Environment name is required
|
||||
environment_config_is_null=Environment config is required
|
||||
|
||||
#file management
|
||||
file_module.not.exist=File module does not exist
|
||||
upload.file.error=Upload file error
|
||||
file.not.exist=File does not exist
|
||||
old.file.not.exist=Old file does not exist
|
||||
file.name.exist=File name already exists
|
||||
file.log.delete_module=has be deleted
|
||||
file.module.root=root module
|
||||
file.log.move_to=move to
|
||||
file.log.next=next
|
||||
file.log.previous=behind
|
||||
file.log.upload=upload
|
||||
file.log.re-upload=re-upload
|
||||
file.name.cannot.be.empty=File name cannot be empty
|
||||
#file management over
|
|
@ -115,6 +115,7 @@ permission.project_user.name=用户
|
|||
permission.project_group.name=用户组
|
||||
permission.project_environment.name=环境配置
|
||||
permission.project_file.name=文件管理
|
||||
permission.project_file.download=文件下载
|
||||
permission.project_template.name=模版管理
|
||||
permission.project_message.name=消息管理
|
||||
permission.project_version.name=版本管理
|
||||
|
@ -146,3 +147,19 @@ environment_datasource.driverId.not_blank=驱动ID不能为空
|
|||
environment_datasource.dbUrl.not_blank=数据库连接不能为空
|
||||
environment_name_is_null=环境名称不能为空
|
||||
environment_config_is_null=环境配置不能为空
|
||||
|
||||
#file management
|
||||
file_module.not.exist=文件模块不存在
|
||||
upload.file.error=上传文件失败
|
||||
file.not.exist=文件不存在
|
||||
old.file.not.exist=旧文件不存在
|
||||
file.name.exist=文件名已存在
|
||||
file.log.delete_module=模块下的所有数据全部被删除
|
||||
file.module.root=根目录
|
||||
file.log.move_to=移动到
|
||||
file.log.next=之后
|
||||
file.log.previous=之前
|
||||
file.log.upload=上传
|
||||
file.log.re-upload=重新上传
|
||||
file.name.cannot.be.empty=文件名称不能为空
|
||||
#file management over
|
|
@ -115,6 +115,7 @@ permission.project_user.name=用戶
|
|||
permission.project_group.name=用戶組
|
||||
permission.project_environment.name=環境配置
|
||||
permission.project_file.name=文件管理
|
||||
permission.project_file.download=文件下載
|
||||
permission.project_template.name=模版管理
|
||||
permission.project_message.name=消息管理
|
||||
permission.project_version.name=版本管理
|
||||
|
@ -145,4 +146,19 @@ environment_datasource.driver.not_blank=驅動不能為空
|
|||
environment_datasource.driverId.not_blank=驅動ID不能為空
|
||||
environment_datasource.dbUrl.not_blank=數據庫地址不能為空
|
||||
environment_name_is_null=環境名稱不能為空
|
||||
environment_config_is_null=環境配置不能為空
|
||||
environment_config_is_null=環境配置不能為空
|
||||
#file management
|
||||
file_module.not.exist=文件模塊不存在
|
||||
upload.file.error=上傳文件失敗
|
||||
file.not.exist=文件不存在
|
||||
old.file.not.exist=舊文件不存在
|
||||
file.name.exist=文件名已存在
|
||||
file.log.delete_module=模塊下的所有數據全部被刪除
|
||||
file.module.root=根目錄
|
||||
file.log.move_to=移動到
|
||||
file.log.next=之後
|
||||
file.log.previous=之前
|
||||
file.log.upload=上傳
|
||||
file.log.re-upload=重新上傳
|
||||
file.name.cannot.be.empty=文件名稱不能為空
|
||||
#file management over
|
|
@ -4,6 +4,7 @@ role.not.global.system=Role is not global system role
|
|||
role.not.contains.member=Role not contains member
|
||||
user.not.login=User not login
|
||||
user.not.exist=User not exist
|
||||
default.module=Default module
|
||||
user.not.empty=User can not empty
|
||||
auth_source.id.not_blank=Auth source id must not be blank
|
||||
auth_source.status.length_range=Auth source status must be between {min} and {max} characters long
|
||||
|
|
|
@ -5,6 +5,7 @@ role.not.contains.member=角色不包含系统成员角色
|
|||
user.not.login=未获取到登录用户
|
||||
user.not.empty=用户不呢为空
|
||||
user.not.exist=用户不存在
|
||||
default.module=默认模块
|
||||
auth_source.id.not_blank=认证源ID不能为空
|
||||
auth_source.status.length_range=认证源状态长度必须在{min}和{max}之间
|
||||
auth_source.status.not_blank=认证源状态不能为空
|
||||
|
|
|
@ -5,6 +5,7 @@ role.not.contains.member=角色不包含系統成員角色
|
|||
user.not.login=未獲取到登錄用戶
|
||||
user.not.empty=用戶不呢為空
|
||||
user.not.exist=用戶不存在
|
||||
default.module=默認模塊
|
||||
auth_source.id.not_blank=認證源ID不能為空
|
||||
auth_source.status.length_range=認證源狀態長度必須在{min}和{max}之間
|
||||
auth_source.status.not_blank=認證源狀態不能為空
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
package io.metersphere.project.controller;
|
||||
|
||||
import io.metersphere.project.dto.FileTableResult;
|
||||
import io.metersphere.project.request.filemanagement.*;
|
||||
import io.metersphere.project.service.FileManagementService;
|
||||
import io.metersphere.project.service.FileMetadataService;
|
||||
import io.metersphere.sdk.constants.PermissionConstants;
|
||||
import io.metersphere.sdk.exception.MSException;
|
||||
import io.metersphere.sdk.util.Translator;
|
||||
import io.metersphere.system.utils.SessionUtils;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
@Tag(name = "项目管理-文件管理-文件")
|
||||
@RestController
|
||||
@RequestMapping("/project/file")
|
||||
public class FileManagementController {
|
||||
|
||||
@Resource
|
||||
private FileMetadataService fileMetadataService;
|
||||
@Resource
|
||||
private FileManagementService fileManagementService;
|
||||
|
||||
@PostMapping("/page")
|
||||
@Operation(summary = "项目管理-文件管理-表格分页查询文件")
|
||||
@RequiresPermissions(PermissionConstants.PROJECT_FILE_MANAGEMENT_READ)
|
||||
public FileTableResult page(@Validated @RequestBody FileMetadataTableRequest request) {
|
||||
return fileMetadataService.page(request);
|
||||
}
|
||||
|
||||
|
||||
@PostMapping("/upload")
|
||||
@Operation(summary = "项目管理-文件管理-上传文件")
|
||||
@RequiresPermissions(PermissionConstants.PROJECT_FILE_MANAGEMENT_READ_ADD)
|
||||
public String upload(@Validated @RequestPart("request") FileUploadRequest request, @RequestPart(value = "file", required = false) MultipartFile uploadFile) {
|
||||
try {
|
||||
return fileMetadataService.upload(request, SessionUtils.getUserId(), uploadFile);
|
||||
} catch (Exception e) {
|
||||
throw new MSException(Translator.get("upload.file.error"), e);
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/re-upload")
|
||||
@Operation(summary = "项目管理-文件管理-重新上传文件")
|
||||
@RequiresPermissions(PermissionConstants.PROJECT_FILE_MANAGEMENT_READ_UPDATE)
|
||||
public String reUpload(@Validated @RequestPart("request") FileReUploadRequest request, @RequestPart(value = "file", required = false) MultipartFile uploadFile) {
|
||||
try {
|
||||
return fileMetadataService.reUpload(request, SessionUtils.getUserId(), uploadFile);
|
||||
} catch (Exception e) {
|
||||
throw new MSException(Translator.get("upload.file.error"), e);
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping(value = "/download/{id}")
|
||||
@Operation(summary = "项目管理-文件管理-下载文件")
|
||||
@RequiresPermissions(PermissionConstants.PROJECT_FILE_MANAGEMENT_READ_DOWNLOAD)
|
||||
public ResponseEntity<byte[]> download(@PathVariable String id) throws Exception {
|
||||
return fileMetadataService.downloadById(id);
|
||||
}
|
||||
|
||||
@PostMapping(value = "/delete")
|
||||
@Operation(summary = "项目管理-文件管理-删除文件")
|
||||
@RequiresPermissions(PermissionConstants.PROJECT_FILE_MANAGEMENT_READ_DELETE)
|
||||
public void delete(@Validated @RequestBody FileBatchProcessDTO request) throws Exception {
|
||||
fileManagementService.delete(request, SessionUtils.getUserId());
|
||||
}
|
||||
|
||||
@PostMapping(value = "/update")
|
||||
@Operation(summary = "项目管理-文件管理-修改文件")
|
||||
@RequiresPermissions(PermissionConstants.PROJECT_FILE_MANAGEMENT_READ_UPDATE)
|
||||
public void update(@Validated @RequestBody FileUpdateRequest request) throws Exception {
|
||||
fileMetadataService.update(request, SessionUtils.getUserId());
|
||||
}
|
||||
|
||||
@PostMapping(value = "/batch-download")
|
||||
@Operation(summary = "项目管理-文件管理-批量下载文件")
|
||||
@RequiresPermissions(PermissionConstants.PROJECT_FILE_MANAGEMENT_READ_DOWNLOAD)
|
||||
public ResponseEntity<byte[]> downloadBodyFiles(@Validated @RequestBody FileBatchProcessDTO request) {
|
||||
return fileMetadataService.batchDownload(request);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
package io.metersphere.project.controller;
|
||||
|
||||
import io.metersphere.project.request.filemanagement.FileModuleCreateRequest;
|
||||
import io.metersphere.project.request.filemanagement.FileModuleUpdateRequest;
|
||||
import io.metersphere.project.service.FileModuleLogService;
|
||||
import io.metersphere.project.service.FileModuleService;
|
||||
import io.metersphere.sdk.constants.PermissionConstants;
|
||||
import io.metersphere.sdk.dto.BaseTreeNode;
|
||||
import io.metersphere.sdk.dto.request.NodeMoveRequest;
|
||||
import io.metersphere.system.log.annotation.Log;
|
||||
import io.metersphere.system.log.constants.OperationLogType;
|
||||
import io.metersphere.system.utils.SessionUtils;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Tag(name = "项目管理-文件管理-模块")
|
||||
@RestController
|
||||
@RequestMapping("/project/file-module")
|
||||
public class FileModuleController {
|
||||
|
||||
@Resource
|
||||
private FileModuleService fileModuleService;
|
||||
|
||||
@GetMapping("/tree/{projectId}")
|
||||
@Operation(summary = "项目管理-文件管理-模块-查找模块")
|
||||
@RequiresPermissions(PermissionConstants.PROJECT_FILE_MANAGEMENT_READ)
|
||||
public List<BaseTreeNode> getTree(@PathVariable String projectId) {
|
||||
return fileModuleService.getTree(projectId);
|
||||
}
|
||||
|
||||
@PostMapping("/add")
|
||||
@Operation(summary = "项目管理-文件管理-模块-添加模块")
|
||||
@RequiresPermissions(PermissionConstants.PROJECT_FILE_MANAGEMENT_READ_ADD)
|
||||
public String add(@RequestBody @Validated FileModuleCreateRequest request) {
|
||||
return fileModuleService.add(request, SessionUtils.getUserId());
|
||||
}
|
||||
|
||||
@PostMapping("/update")
|
||||
@Operation(summary = "项目管理-文件管理-模块-修改模块")
|
||||
@RequiresPermissions(PermissionConstants.PROJECT_FILE_MANAGEMENT_READ_UPDATE)
|
||||
public boolean list(@RequestBody @Validated FileModuleUpdateRequest request) {
|
||||
fileModuleService.update(request, SessionUtils.getUserId());
|
||||
return true;
|
||||
}
|
||||
|
||||
@GetMapping("/delete/{deleteId}")
|
||||
@Operation(summary = "项目管理-文件管理-模块-删除模块")
|
||||
@RequiresPermissions(PermissionConstants.PROJECT_FILE_MANAGEMENT_READ_DELETE)
|
||||
@Log(type = OperationLogType.DELETE, expression = "#msClass.deleteLog(#deleteId)", msClass = FileModuleLogService.class)
|
||||
public void deleteNode(@PathVariable String deleteId) {
|
||||
fileModuleService.deleteModule(deleteId);
|
||||
}
|
||||
|
||||
@PostMapping("/move")
|
||||
@Operation(summary = "项目管理-文件管理-模块-移动模块")
|
||||
@RequiresPermissions(PermissionConstants.PROJECT_FILE_MANAGEMENT_READ_UPDATE)
|
||||
public void moveNode(@RequestBody NodeMoveRequest request) {
|
||||
/**
|
||||
* 拖拽操作。 两种:同级移动 和 跨级移动
|
||||
* 1.判断移动后的parentID,判断是否是移动到其余的目录下
|
||||
* 2.拖拽后的前后ID。 用于排序。
|
||||
*/
|
||||
fileModuleService.moveNode(request);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
package io.metersphere.project.dto;
|
||||
|
||||
import io.metersphere.project.domain.FileMetadata;
|
||||
import io.metersphere.sdk.util.JSON;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
public class FileInformationDTO {
|
||||
@Schema(description = "ID")
|
||||
private String id;
|
||||
|
||||
@Schema(description = "文件名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "文件类型")
|
||||
private String fileType;
|
||||
|
||||
@Schema(description = "标签")
|
||||
private List<String> tags;
|
||||
|
||||
@Schema(description = "描述")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "更新人")
|
||||
private String updateUser;
|
||||
|
||||
@Schema(description = "更新时间")
|
||||
private long updateTime;
|
||||
|
||||
@Schema(description = "预览路径")
|
||||
private String previewSrc;
|
||||
|
||||
@Schema(description = "文件大小")
|
||||
private long size;
|
||||
|
||||
public FileInformationDTO(FileMetadata fileMetadata) {
|
||||
this.id = fileMetadata.getId();
|
||||
this.name = fileMetadata.getName();
|
||||
this.fileType = fileMetadata.getType();
|
||||
this.size = fileMetadata.getSize();
|
||||
if (StringUtils.isNotBlank(fileMetadata.getTags())) {
|
||||
tags = JSON.parseArray(fileMetadata.getTags(), String.class);
|
||||
}
|
||||
this.description = fileMetadata.getDescription();
|
||||
this.updateUser = fileMetadata.getUpdateUser();
|
||||
this.updateTime = fileMetadata.getUpdateTime();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package io.metersphere.project.dto;
|
||||
|
||||
import io.metersphere.sdk.util.Pager;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Data
|
||||
public class FileTableResult {
|
||||
@Schema(description = "表格数据")
|
||||
Pager<List<FileInformationDTO>> tableData;
|
||||
|
||||
@Schema(description = "模块统计")
|
||||
Map<String, Long> moduleCount = new HashMap<>();
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package io.metersphere.project.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class ModuleCountDTO {
|
||||
private String moduleId;
|
||||
private long dataCount;
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package io.metersphere.project.mapper;
|
||||
|
||||
import io.metersphere.project.domain.FileMetadata;
|
||||
import io.metersphere.project.dto.ModuleCountDTO;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ExtFileMetadataMapper {
|
||||
List<FileMetadata> selectByKeywordAndFileType(@Param("projectId") String projectId, @Param("keyword") String keyword, @Param("moduleIds") List<String> moduleIds, @Param("fileTypes") List<String> fileTypes, @Param("isRefId") boolean isRefId);
|
||||
|
||||
List<ModuleCountDTO> countModuleIdByKeywordAndFileType(@Param("projectId") String projectId, @Param("keyword") String keyword, @Param("moduleIds") List<String> moduleIds, @Param("fileTypes") List<String> fileTypes);
|
||||
|
||||
List<String> selectIdByRefIdList(@Param("refIdList") List<String> refIdList);
|
||||
|
||||
List<FileMetadata> selectDeleteFileInfoByIds(@Param("ids") List<String> ids);
|
||||
|
||||
List<FileMetadata> selectDeleteFileInfoByRefIdList(@Param("refIdList") List<String> refIdList);
|
||||
|
||||
List<FileMetadata> selectRefIdByIds(@Param("fileIds") List<String> processIds);
|
||||
|
||||
List<FileMetadata> selectRefIdByModuleIds(@Param("moduleIds") List<String> moduleIds);
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="io.metersphere.project.mapper.ExtFileMetadataMapper">
|
||||
<select id="selectByKeywordAndFileType" resultType="io.metersphere.project.domain.FileMetadata">
|
||||
SELECT
|
||||
f.id,
|
||||
<if test="isRefId">
|
||||
f.ref_id
|
||||
</if>
|
||||
<if test="!isRefId">
|
||||
f.name,
|
||||
f.type,
|
||||
f.tags,
|
||||
f.description,
|
||||
u.name as update_user,
|
||||
f.update_time,
|
||||
f.path,
|
||||
f.project_id,
|
||||
f.size,
|
||||
f.storage
|
||||
</if>
|
||||
FROM file_metadata f
|
||||
INNER JOIN user u ON f.update_user = u.id
|
||||
WHERE latest = true
|
||||
AND f.project_id = #{projectId}
|
||||
<if test="keyword != null and keyword != ''">
|
||||
AND f.name = #{keyword}
|
||||
</if>
|
||||
<if test="moduleIds != null and moduleIds.size() != 0">
|
||||
AND f.module_id IN
|
||||
<foreach collection="moduleIds" item="item" open="(" separator="," close=")">
|
||||
#{item}
|
||||
</foreach>
|
||||
</if>
|
||||
<if test="fileTypes != null and fileTypes.size() != 0 ">
|
||||
AND f.type IN
|
||||
<foreach collection="fileTypes" item="item" open="(" separator="," close=")">
|
||||
#{item}
|
||||
</foreach>
|
||||
</if>
|
||||
</select>
|
||||
<select id="selectIdByRefIdList" resultType="java.lang.String">
|
||||
SELECT id FROM file_metadata WHERE ref_id IN
|
||||
<foreach collection="refIdList" item="item" open="(" separator="," close=")">
|
||||
#{item}
|
||||
</foreach>
|
||||
</select>
|
||||
<select id="selectDeleteFileInfoByIds" resultType="io.metersphere.project.domain.FileMetadata">
|
||||
SELECT
|
||||
f.id,
|
||||
f.project_id,
|
||||
f.storage
|
||||
FROM file_metadata f WHERE f.id IN
|
||||
<foreach collection="ids" item="item" open="(" separator="," close=")">
|
||||
#{item}
|
||||
</foreach>
|
||||
</select>
|
||||
<select id="countModuleIdByKeywordAndFileType" resultType="io.metersphere.project.dto.ModuleCountDTO">
|
||||
SELECT f.module_id AS moduleId, count(f.id) AS dataCount
|
||||
FROM file_metadata f
|
||||
INNER JOIN user u ON f.update_user = u.id
|
||||
WHERE latest = true
|
||||
AND f.project_id = #{projectId}
|
||||
<if test="keyword != null and keyword != ''">
|
||||
AND f.name = #{keyword}
|
||||
</if>
|
||||
<if test="moduleIds != null and moduleIds.size() != 0">
|
||||
AND f.module_id IN
|
||||
<foreach collection="moduleIds" item="item" open="(" separator="," close=")">
|
||||
#{item}
|
||||
</foreach>
|
||||
</if>
|
||||
<if test="fileTypes != null and fileTypes.size() != 0 ">
|
||||
AND f.type IN
|
||||
<foreach collection="fileTypes" item="item" open="(" separator="," close=")">
|
||||
#{item}
|
||||
</foreach>
|
||||
</if>
|
||||
GROUP BY f.module_id
|
||||
</select>
|
||||
<select id="selectRefIdByIds" resultType="io.metersphere.project.domain.FileMetadata">
|
||||
SELECT DISTINCT f.ref_id FROM file_metadata f
|
||||
WHERE
|
||||
f.id IN
|
||||
<foreach collection="fileIds" item="item" open="(" separator="," close=")">
|
||||
#{item}
|
||||
</foreach>
|
||||
</select>
|
||||
<select id="selectDeleteFileInfoByRefIdList" resultType="io.metersphere.project.domain.FileMetadata">
|
||||
SELECT
|
||||
f.id,
|
||||
f.project_id,
|
||||
f.storage
|
||||
FROM file_metadata f WHERE f.ref_id IN
|
||||
<foreach collection="refIdList" item="item" open="(" separator="," close=")">
|
||||
#{item}
|
||||
</foreach>
|
||||
</select>
|
||||
<select id="selectRefIdByModuleIds" resultType="io.metersphere.project.domain.FileMetadata">
|
||||
SELECT
|
||||
f.ref_id
|
||||
FROM file_metadata f
|
||||
WHERE f.module_id IN
|
||||
<foreach collection="moduleIds" item="item" open="(" separator="," close=")">
|
||||
#{item}
|
||||
</foreach>
|
||||
</select>
|
||||
|
||||
|
||||
</mapper>
|
|
@ -0,0 +1,20 @@
|
|||
package io.metersphere.project.mapper;
|
||||
|
||||
import io.metersphere.project.domain.FileModule;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ExtFileModuleMapper {
|
||||
List<FileModule> selectBaseByProjectId(String projectId);
|
||||
|
||||
List<String> selectChildrenIdsByParentIds(@Param("ids") List<String> deleteIds);
|
||||
|
||||
List<String> selectChildrenIdsSortByPos(String parentId);
|
||||
|
||||
void deleteByIds(@Param("ids") List<String> deleteId);
|
||||
|
||||
Integer getMaxPosByParentId(String parentId);
|
||||
|
||||
List<String> selectIdsByProjectId(String projectId);
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="io.metersphere.project.mapper.ExtFileModuleMapper">
|
||||
<select id="selectBaseByProjectId" resultType="io.metersphere.project.domain.FileModule">
|
||||
SELECT id, name, parent_id, pos
|
||||
FROM file_module
|
||||
WHERE project_id = #{0}
|
||||
ORDER BY pos
|
||||
</select>
|
||||
<select id="selectIdsByProjectId" resultType="java.lang.String">
|
||||
SELECT id
|
||||
FROM file_module
|
||||
WHERE project_id = #{0}
|
||||
</select>
|
||||
<select id="selectChildrenIdsByParentIds" resultType="java.lang.String">
|
||||
SELECT id FROM file_module WHERE parent_id IN
|
||||
<foreach collection="ids" item="id" open="(" separator="," close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
</select>
|
||||
<delete id="deleteByIds">
|
||||
DELETE FROM file_module WHERE id IN
|
||||
<foreach collection="ids" item="id" open="(" separator="," close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
</delete>
|
||||
<select id="getMaxPosByParentId" resultType="java.lang.Integer">
|
||||
SELECT max(pos) FROM file_module
|
||||
WHERE parent_id = #{0}
|
||||
</select>
|
||||
<select id="selectChildrenIdsSortByPos" resultType="java.lang.String">
|
||||
SELECT id FROM file_module WHERE parent_id = #{0}
|
||||
ORDER BY pos ASC
|
||||
</select>
|
||||
</mapper>
|
|
@ -0,0 +1,38 @@
|
|||
package io.metersphere.project.request.filemanagement;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class FileBatchProcessDTO {
|
||||
@Schema(description = "不处理的ID")
|
||||
List<String> excludeIds;
|
||||
|
||||
@Schema(description = "项目ID")
|
||||
@NotBlank(message = "{id must not be blank}")
|
||||
private String projectId;
|
||||
|
||||
@Schema(description = "选择的ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@Valid
|
||||
private List<
|
||||
@NotBlank(message = "{id must not be blank}")
|
||||
String
|
||||
> selectIds = new ArrayList<>();
|
||||
|
||||
@Schema(description = "是否选择所有数据")
|
||||
private boolean selectAll;
|
||||
|
||||
@Schema(description = "文件类型")
|
||||
private List<String> fileTypes;
|
||||
|
||||
@Schema(description = "关键字")
|
||||
private String keyword;
|
||||
|
||||
@Schema(description = "模块ID")
|
||||
private List<String> moduleIds;
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package io.metersphere.project.request.filemanagement;
|
||||
|
||||
import io.metersphere.sdk.dto.BasePageRequest;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class FileMetadataTableRequest extends BasePageRequest {
|
||||
@Schema(description = "模块ID(根据模块树查询时要把当前节点以及子节点都放在这里。)")
|
||||
private List<String> moduleIds;
|
||||
|
||||
@Schema(description = "文件类型")
|
||||
private List<String> fileTypes;
|
||||
|
||||
@Schema(description = "项目ID")
|
||||
@NotBlank(message = "{id must not be blank}")
|
||||
private String projectId;
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package io.metersphere.project.request.filemanagement;
|
||||
|
||||
import io.metersphere.sdk.constants.ModuleConstants;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class FileModuleCreateRequest {
|
||||
@Schema(description = "项目ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{project.id.not_blank}")
|
||||
private String projectId;
|
||||
|
||||
@Schema(description = "模块名称", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotEmpty(message = "{file_module.name.not_blank}")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "父模块ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotEmpty(message = "{parent.node.not_blank}")
|
||||
private String parentId = ModuleConstants.ROOT_NODE_PARENT_ID;
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package io.metersphere.project.request.filemanagement;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class FileModuleUpdateRequest {
|
||||
@Schema(description = "模块ID", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotBlank(message = "{file_module.id.not_blank}")
|
||||
private String id;
|
||||
|
||||
@Schema(description = "模块名称", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
@NotEmpty(message = "{file_module.name.not_blank}")
|
||||
private String name;
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package io.metersphere.project.request.filemanagement;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class FileReUploadRequest {
|
||||
@Schema(description = "文件Id")
|
||||
@NotBlank(message = "{file_metadata.id.not_blank}")
|
||||
private String fileId;
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package io.metersphere.project.request.filemanagement;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class FileUpdateRequest {
|
||||
@Schema(description = "文件Id")
|
||||
@NotBlank(message = "{file_metadata.id.not_blank}")
|
||||
private String id;
|
||||
|
||||
@Schema(description = "文件名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "标签")
|
||||
private List<
|
||||
@NotBlank
|
||||
String> tags;
|
||||
|
||||
@Schema(description = "文件描述")
|
||||
private String description;
|
||||
|
||||
@Schema(description = "模块ID")
|
||||
private String moduleId;
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package io.metersphere.project.request.filemanagement;
|
||||
|
||||
import io.metersphere.sdk.constants.ModuleConstants;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class FileUploadRequest {
|
||||
@Schema(description = "项目Id")
|
||||
@NotBlank(message = "{project.id.not_blank}")
|
||||
private String projectId;
|
||||
|
||||
@Schema(description = "模块Id")
|
||||
@NotBlank(message = "{file_module.id.not_blank}")
|
||||
private String moduleId = ModuleConstants.DEFAULT_NODE_ID;
|
||||
}
|
|
@ -0,0 +1,139 @@
|
|||
package io.metersphere.project.service;
|
||||
|
||||
import io.metersphere.project.domain.FileMetadata;
|
||||
import io.metersphere.project.domain.FileMetadataExample;
|
||||
import io.metersphere.project.domain.FileModuleExample;
|
||||
import io.metersphere.project.mapper.ExtFileMetadataMapper;
|
||||
import io.metersphere.project.mapper.FileMetadataMapper;
|
||||
import io.metersphere.project.mapper.FileModuleMapper;
|
||||
import io.metersphere.project.request.filemanagement.FileBatchProcessDTO;
|
||||
import io.metersphere.sdk.constants.ModuleConstants;
|
||||
import io.metersphere.sdk.exception.MSException;
|
||||
import io.metersphere.sdk.file.FileRequest;
|
||||
import io.metersphere.sdk.service.FileService;
|
||||
import io.metersphere.sdk.util.LogUtils;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public class FileManagementService {
|
||||
@Resource
|
||||
private FileMetadataMapper fileMetadataMapper;
|
||||
@Resource
|
||||
private FileModuleMapper fileModuleMapper;
|
||||
@Resource
|
||||
private FileService fileService;
|
||||
@Resource
|
||||
private FileMetadataLogService fileMetadataLogService;
|
||||
|
||||
@Resource
|
||||
private ExtFileMetadataMapper extFileMetadataMapper;
|
||||
|
||||
|
||||
public void checkModule(String moduleId, String nodeTypeDefault) {
|
||||
if (!StringUtils.equals(moduleId, ModuleConstants.DEFAULT_NODE_ID)) {
|
||||
FileModuleExample example = new FileModuleExample();
|
||||
example.createCriteria().andIdEqualTo(moduleId).andModuleTypeEqualTo(nodeTypeDefault);
|
||||
if (fileModuleMapper.countByExample(example) == 0) {
|
||||
throw new MSException("file_module.not.exist");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void delete(FileBatchProcessDTO request, String operator) {
|
||||
List<FileMetadata> deleteList = this.getDeleteList(request);
|
||||
List<String> deleteIds = deleteList.stream().map(FileMetadata::getId).collect(Collectors.toList());
|
||||
if (CollectionUtils.isNotEmpty(deleteIds)) {
|
||||
FileMetadataExample example = new FileMetadataExample();
|
||||
example.createCriteria().andIdIn(deleteIds);
|
||||
fileMetadataMapper.deleteByExample(example);
|
||||
|
||||
//记录日志
|
||||
fileMetadataLogService.saveDeleteLog(deleteList, request.getProjectId(), operator);
|
||||
|
||||
deleteList.forEach(fileMetadata -> {
|
||||
FileRequest fileRequest = new FileRequest();
|
||||
fileRequest.setFileName(fileMetadata.getId());
|
||||
fileRequest.setProjectId(fileMetadata.getProjectId());
|
||||
fileRequest.setStorage(fileMetadata.getStorage());
|
||||
try {
|
||||
fileService.deleteFile(fileRequest);
|
||||
} catch (Exception e) {
|
||||
LogUtils.error("删除文件失败", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public List<FileMetadata> getDeleteList(FileBatchProcessDTO request) {
|
||||
List<String> processIds = request.getSelectIds();
|
||||
List<FileMetadata> refFileList = new ArrayList<>();
|
||||
if (request.isSelectAll()) {
|
||||
refFileList = extFileMetadataMapper.selectByKeywordAndFileType(request.getProjectId(), request.getKeyword(), request.getModuleIds(), request.getFileTypes(), true);
|
||||
if (CollectionUtils.isNotEmpty(request.getExcludeIds())) {
|
||||
refFileList = refFileList.stream().filter(fileMetadata -> !request.getExcludeIds().contains(fileMetadata.getId())).collect(Collectors.toList());
|
||||
}
|
||||
} else if (CollectionUtils.isNotEmpty(processIds)) {
|
||||
refFileList = extFileMetadataMapper.selectRefIdByIds(processIds);
|
||||
}
|
||||
|
||||
List<String> refIdList = refFileList.stream().map(FileMetadata::getRefId).collect(Collectors.toList());
|
||||
if (CollectionUtils.isNotEmpty(refIdList)) {
|
||||
processIds = extFileMetadataMapper.selectIdByRefIdList(refIdList);
|
||||
return extFileMetadataMapper.selectDeleteFileInfoByIds(processIds);
|
||||
} else {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
public List<FileMetadata> getProcessList(FileBatchProcessDTO request) {
|
||||
List<String> processIds = request.getSelectIds();
|
||||
List<FileMetadata> refFileList = new ArrayList<>();
|
||||
if (request.isSelectAll()) {
|
||||
refFileList = extFileMetadataMapper.selectByKeywordAndFileType(request.getProjectId(), request.getKeyword(), request.getModuleIds(), request.getFileTypes(), false);
|
||||
if (CollectionUtils.isNotEmpty(request.getExcludeIds())) {
|
||||
refFileList = refFileList.stream().filter(fileMetadata -> !request.getExcludeIds().contains(fileMetadata.getId())).collect(Collectors.toList());
|
||||
}
|
||||
} else if (CollectionUtils.isNotEmpty(processIds)) {
|
||||
refFileList = extFileMetadataMapper.selectRefIdByIds(processIds);
|
||||
}
|
||||
|
||||
return refFileList;
|
||||
}
|
||||
|
||||
public void deleteByModuleIds(List<String> deleteModuleIds) {
|
||||
//获取要删除的文件引用ID
|
||||
List<FileMetadata> refFileList = extFileMetadataMapper.selectRefIdByModuleIds(deleteModuleIds);
|
||||
List<String> refIdList = refFileList.stream().map(FileMetadata::getRefId).collect(Collectors.toList());
|
||||
if (CollectionUtils.isNotEmpty(refIdList)) {
|
||||
//获取要删除的所有文件ID
|
||||
List<FileMetadata> deleteList = extFileMetadataMapper.selectDeleteFileInfoByRefIdList(refIdList);
|
||||
if (CollectionUtils.isNotEmpty(deleteList)) {
|
||||
FileMetadataExample example = new FileMetadataExample();
|
||||
example.createCriteria().andIdIn(
|
||||
deleteList.stream().map(FileMetadata::getId).collect(Collectors.toList()));
|
||||
fileMetadataMapper.deleteByExample(example);
|
||||
|
||||
deleteList.forEach(fileMetadata -> {
|
||||
FileRequest fileRequest = new FileRequest();
|
||||
fileRequest.setFileName(fileMetadata.getId());
|
||||
fileRequest.setProjectId(fileMetadata.getProjectId());
|
||||
fileRequest.setStorage(fileMetadata.getStorage());
|
||||
try {
|
||||
fileService.deleteFile(fileRequest);
|
||||
} catch (Exception e) {
|
||||
LogUtils.error("删除文件失败", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
package io.metersphere.project.service;
|
||||
|
||||
import io.metersphere.project.domain.FileMetadata;
|
||||
import io.metersphere.project.domain.Project;
|
||||
import io.metersphere.project.mapper.FileMetadataMapper;
|
||||
import io.metersphere.project.mapper.ProjectMapper;
|
||||
import io.metersphere.sdk.constants.HttpMethodConstants;
|
||||
import io.metersphere.sdk.dto.LogDTO;
|
||||
import io.metersphere.sdk.dto.builder.LogDTOBuilder;
|
||||
import io.metersphere.sdk.util.JSON;
|
||||
import io.metersphere.sdk.util.Translator;
|
||||
import io.metersphere.system.log.constants.OperationLogModule;
|
||||
import io.metersphere.system.log.constants.OperationLogType;
|
||||
import io.metersphere.system.log.service.OperationLogService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public class FileMetadataLogService {
|
||||
@Resource
|
||||
private FileMetadataMapper fileMetadataMapper;
|
||||
@Resource
|
||||
private ProjectMapper projectMapper;
|
||||
@Resource
|
||||
private OperationLogService operationLogService;
|
||||
|
||||
public void saveUploadLog(FileMetadata module, String operator) {
|
||||
Project project = projectMapper.selectByPrimaryKey(module.getProjectId());
|
||||
LogDTO dto = LogDTOBuilder.builder()
|
||||
.projectId(module.getProjectId())
|
||||
.organizationId(project.getOrganizationId())
|
||||
.type(OperationLogType.ADD.name())
|
||||
.module(OperationLogModule.PROJECT_FILE_MANAGEMENT)
|
||||
.method(HttpMethodConstants.POST.name())
|
||||
.path("/project/file/upload")
|
||||
.sourceId(module.getId())
|
||||
.content(Translator.get("file.log.upload") + " " + module.getName())
|
||||
.originalValue(JSON.toJSONBytes(module))
|
||||
.createUser(operator)
|
||||
.build().getLogDTO();
|
||||
operationLogService.add(dto);
|
||||
}
|
||||
|
||||
public void saveReUploadLog(FileMetadata module, String operator) {
|
||||
Project project = projectMapper.selectByPrimaryKey(module.getProjectId());
|
||||
LogDTO dto = LogDTOBuilder.builder()
|
||||
.projectId(module.getProjectId())
|
||||
.organizationId(project.getOrganizationId())
|
||||
.type(OperationLogType.UPDATE.name())
|
||||
.module(OperationLogModule.PROJECT_FILE_MANAGEMENT)
|
||||
.method(HttpMethodConstants.POST.name())
|
||||
.path("/project/file/re-upload")
|
||||
.sourceId(module.getId())
|
||||
.content(Translator.get("file.log.re-upload") + " " + module.getName())
|
||||
.originalValue(JSON.toJSONBytes(module))
|
||||
.createUser(operator)
|
||||
.build().getLogDTO();
|
||||
operationLogService.add(dto);
|
||||
}
|
||||
|
||||
public void saveUpdateLog(FileMetadata module, String projectId, String operator) {
|
||||
Project project = projectMapper.selectByPrimaryKey(projectId);
|
||||
LogDTO dto = LogDTOBuilder.builder()
|
||||
.projectId(projectId)
|
||||
.organizationId(project.getOrganizationId())
|
||||
.type(OperationLogType.UPDATE.name())
|
||||
.module(OperationLogModule.PROJECT_FILE_MANAGEMENT)
|
||||
.method(HttpMethodConstants.POST.name())
|
||||
.path("/project/file/update")
|
||||
.sourceId(module.getId())
|
||||
.content(module.getName())
|
||||
.originalValue(JSON.toJSONBytes(module))
|
||||
.createUser(operator)
|
||||
.build().getLogDTO();
|
||||
operationLogService.add(dto);
|
||||
}
|
||||
|
||||
public void saveDeleteLog(List<FileMetadata> deleteList, String projectId, String operator) {
|
||||
Project project = projectMapper.selectByPrimaryKey(projectId);
|
||||
List<LogDTO> list = new ArrayList<>();
|
||||
for (FileMetadata fileMetadata : deleteList) {
|
||||
LogDTO dto = LogDTOBuilder.builder()
|
||||
.projectId(projectId)
|
||||
.organizationId(project.getOrganizationId())
|
||||
.type(OperationLogType.DELETE.name())
|
||||
.module(OperationLogModule.PROJECT_FILE_MANAGEMENT)
|
||||
.method(HttpMethodConstants.POST.name())
|
||||
.path("/project/file/delete")
|
||||
.sourceId(fileMetadata.getId())
|
||||
.content(fileMetadata.getName())
|
||||
.originalValue(JSON.toJSONBytes(fileMetadata))
|
||||
.createUser(operator)
|
||||
.build().getLogDTO();
|
||||
list.add(dto);
|
||||
}
|
||||
|
||||
operationLogService.batchAdd(list);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,297 @@
|
|||
package io.metersphere.project.service;
|
||||
|
||||
import com.github.pagehelper.Page;
|
||||
import com.github.pagehelper.PageHelper;
|
||||
import io.metersphere.project.domain.FileMetadata;
|
||||
import io.metersphere.project.domain.FileMetadataExample;
|
||||
import io.metersphere.project.dto.FileInformationDTO;
|
||||
import io.metersphere.project.dto.FileTableResult;
|
||||
import io.metersphere.project.dto.ModuleCountDTO;
|
||||
import io.metersphere.project.mapper.ExtFileMetadataMapper;
|
||||
import io.metersphere.project.mapper.FileMetadataMapper;
|
||||
import io.metersphere.project.request.filemanagement.*;
|
||||
import io.metersphere.project.utils.FileDownloadUtils;
|
||||
import io.metersphere.sdk.constants.ModuleConstants;
|
||||
import io.metersphere.sdk.constants.StorageType;
|
||||
import io.metersphere.sdk.exception.MSException;
|
||||
import io.metersphere.sdk.file.FileRequest;
|
||||
import io.metersphere.sdk.service.FileService;
|
||||
import io.metersphere.sdk.util.*;
|
||||
import io.metersphere.system.uid.UUID;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.unit.DataSize;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public class FileMetadataService {
|
||||
@Resource
|
||||
private FileMetadataMapper fileMetadataMapper;
|
||||
@Resource
|
||||
private ExtFileMetadataMapper extFileMetadataMapper;
|
||||
@Resource
|
||||
private FileMetadataLogService fileMetadataLogService;
|
||||
@Resource
|
||||
private FileManagementService fileManagementService;
|
||||
@Resource
|
||||
private FileService fileService;
|
||||
|
||||
@Value("${metersphere.file.batch-download-max:600MB}")
|
||||
private DataSize maxFileSize;
|
||||
|
||||
public List<FileInformationDTO> list(FileMetadataTableRequest request) {
|
||||
List<FileInformationDTO> returnList = new ArrayList<>();
|
||||
List<FileMetadata> fileMetadataList = extFileMetadataMapper.selectByKeywordAndFileType(request.getProjectId(), request.getKeyword(), request.getModuleIds(), request.getFileTypes(), false);
|
||||
fileMetadataList.forEach(fileMetadata -> {
|
||||
FileInformationDTO fileInformationDTO = new FileInformationDTO(fileMetadata);
|
||||
if (FilePreviewUtil.isImage(fileMetadata.getType())) {
|
||||
fileInformationDTO.setPreviewSrc(FilePreviewUtil.catchFileIfNotExists(fileMetadata.getPath() + "." + fileMetadata.getType(), this.getFile(fileMetadata)));
|
||||
}
|
||||
returnList.add(fileInformationDTO);
|
||||
});
|
||||
return returnList;
|
||||
}
|
||||
|
||||
public String upload(FileUploadRequest request, String operator, MultipartFile uploadFile) throws Exception {
|
||||
//检查模块的合法性
|
||||
fileManagementService.checkModule(request.getModuleId(), ModuleConstants.NODE_TYPE_DEFAULT);
|
||||
|
||||
String fileName = StringUtils.trim(uploadFile.getOriginalFilename());
|
||||
|
||||
FileMetadata fileMetadata = new FileMetadata();
|
||||
if (StringUtils.contains(fileName, ".")) {
|
||||
fileMetadata.setName(StringUtils.substring(fileName, 0, fileName.lastIndexOf(".")));
|
||||
fileMetadata.setType(StringUtils.substring(fileName, fileName.lastIndexOf(".") + 1));
|
||||
} else {
|
||||
fileMetadata.setName(fileName);
|
||||
fileMetadata.setType(StringUtils.EMPTY);
|
||||
}
|
||||
//检查处理后的用户名合法性
|
||||
this.checkFileName(null, fileMetadata.getName(), request.getProjectId());
|
||||
|
||||
fileMetadata.setId(UUID.randomUUID().toString());
|
||||
fileMetadata.setStorage(StorageType.MINIO.name());
|
||||
fileMetadata.setProjectId(request.getProjectId());
|
||||
fileMetadata.setModuleId(request.getModuleId());
|
||||
long operationTime = System.currentTimeMillis();
|
||||
fileMetadata.setCreateTime(operationTime);
|
||||
fileMetadata.setCreateUser(operator);
|
||||
fileMetadata.setUpdateTime(operationTime);
|
||||
fileMetadata.setUpdateUser(operator);
|
||||
fileMetadata.setSize(uploadFile.getSize());
|
||||
fileMetadata.setLatest(true);
|
||||
fileMetadata.setRefId(fileMetadata.getId());
|
||||
fileMetadataMapper.insert(fileMetadata);
|
||||
|
||||
//记录日志
|
||||
fileMetadataLogService.saveUploadLog(fileMetadata, operator);
|
||||
|
||||
// 上传文件
|
||||
String filePath = this.uploadFile(fileMetadata, uploadFile);
|
||||
FileMetadata updateFileMetadata = new FileMetadata();
|
||||
updateFileMetadata.setId(fileMetadata.getId());
|
||||
updateFileMetadata.setPath(filePath);
|
||||
updateFileMetadata.setFileVersion(fileMetadata.getId());
|
||||
fileMetadataMapper.updateByPrimaryKeySelective(updateFileMetadata);
|
||||
|
||||
return fileMetadata.getId();
|
||||
}
|
||||
|
||||
private void checkFileName(String id, String fileName, String projectId) {
|
||||
if (StringUtils.isBlank(fileName)) {
|
||||
throw new MSException(Translator.get("file.name.cannot.be.empty"));
|
||||
}
|
||||
FileMetadataExample example = new FileMetadataExample();
|
||||
if (StringUtils.isBlank(id)) {
|
||||
example.createCriteria().andNameEqualTo(fileName).andProjectIdEqualTo(projectId);
|
||||
} else {
|
||||
example.createCriteria().andNameEqualTo(fileName).andProjectIdEqualTo(projectId).andIdNotEqualTo(id);
|
||||
}
|
||||
if (fileMetadataMapper.countByExample(example) > 0) {
|
||||
throw new MSException(Translator.get("file.name.exist"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 重新上传
|
||||
*/
|
||||
public String reUpload(FileReUploadRequest request, String operator, MultipartFile uploadFile) throws Exception {
|
||||
//检查模块的合法性
|
||||
FileMetadata oldFile = fileMetadataMapper.selectByPrimaryKey(request.getFileId());
|
||||
if (oldFile == null) {
|
||||
throw new MSException(Translator.get("old.file.not.exist"));
|
||||
}
|
||||
oldFile.setLatest(false);
|
||||
fileMetadataMapper.updateByPrimaryKeySelective(oldFile);
|
||||
|
||||
long operationTime = System.currentTimeMillis();
|
||||
FileMetadata fileMetadata = new FileMetadata();
|
||||
fileMetadata.setId(UUID.randomUUID().toString());
|
||||
fileMetadata.setStorage(oldFile.getStorage());
|
||||
fileMetadata.setProjectId(oldFile.getProjectId());
|
||||
fileMetadata.setModuleId(oldFile.getModuleId());
|
||||
fileMetadata.setName(oldFile.getName());
|
||||
fileMetadata.setType(oldFile.getType());
|
||||
fileMetadata.setCreateTime(operationTime);
|
||||
fileMetadata.setCreateUser(operator);
|
||||
fileMetadata.setUpdateTime(operationTime);
|
||||
fileMetadata.setUpdateUser(operator);
|
||||
fileMetadata.setSize(uploadFile.getSize());
|
||||
fileMetadata.setRefId(oldFile.getRefId());
|
||||
fileMetadata.setLatest(true);
|
||||
fileMetadataMapper.insert(fileMetadata);
|
||||
|
||||
//记录日志
|
||||
fileMetadataLogService.saveReUploadLog(fileMetadata, operator);
|
||||
|
||||
// 上传文件
|
||||
String filePath = this.uploadFile(fileMetadata, uploadFile);
|
||||
FileMetadata updateFileMetadata = new FileMetadata();
|
||||
updateFileMetadata.setId(fileMetadata.getId());
|
||||
updateFileMetadata.setPath(filePath);
|
||||
updateFileMetadata.setFileVersion(fileMetadata.getId());
|
||||
fileMetadataMapper.updateByPrimaryKeySelective(updateFileMetadata);
|
||||
|
||||
return fileMetadata.getId();
|
||||
}
|
||||
|
||||
private String uploadFile(FileMetadata fileMetadata, MultipartFile file) throws Exception {
|
||||
FileRequest uploadFileRequest = new FileRequest();
|
||||
uploadFileRequest.setFileName(fileMetadata.getId());
|
||||
uploadFileRequest.setProjectId(fileMetadata.getProjectId());
|
||||
uploadFileRequest.setStorage(StorageType.MINIO.name());
|
||||
return fileService.upload(file, uploadFileRequest);
|
||||
}
|
||||
|
||||
public ResponseEntity<byte[]> downloadById(String id) {
|
||||
|
||||
FileMetadata fileMetadata = fileMetadataMapper.selectByPrimaryKey(id);
|
||||
byte[] bytes = this.getFile(fileMetadata);
|
||||
return ResponseEntity.ok()
|
||||
.contentType(MediaType.parseMediaType("application/octet-stream"))
|
||||
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + this.getFileName(fileMetadata.getName(), fileMetadata.getType()) + "\"")
|
||||
.body(bytes);
|
||||
}
|
||||
|
||||
private String getFileName(String fileName, String type) {
|
||||
if (StringUtils.isBlank(type)) {
|
||||
return fileName;
|
||||
}
|
||||
return fileName + "." + type;
|
||||
}
|
||||
|
||||
private byte[] getFile(FileMetadata fileMetadata) {
|
||||
if (fileMetadata == null) {
|
||||
throw new MSException(Translator.get("file.not.exist"));
|
||||
}
|
||||
FileRequest fileRequest = new FileRequest();
|
||||
fileRequest.setFileName(fileMetadata.getId());
|
||||
fileRequest.setProjectId(fileMetadata.getProjectId());
|
||||
fileRequest.setStorage(fileMetadata.getStorage());
|
||||
try {
|
||||
return fileService.download(fileRequest);
|
||||
} catch (Exception e) {
|
||||
LogUtils.error("获取文件失败", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void update(FileUpdateRequest request, String operator) {
|
||||
//检查模块的合法性
|
||||
FileMetadata fileMetadata = fileMetadataMapper.selectByPrimaryKey(request.getId());
|
||||
if (fileMetadata == null) {
|
||||
throw new MSException(Translator.get("file.not.exist"));
|
||||
}
|
||||
|
||||
//检查是否是空参数
|
||||
if (!StringUtils.isAllBlank(request.getName(), request.getDescription(), request.getModuleId()) && CollectionUtils.isNotEmpty(request.getTags())) {
|
||||
FileMetadata updateExample = new FileMetadata();
|
||||
updateExample.setId(request.getId());
|
||||
updateExample.setDescription(request.getDescription());
|
||||
updateExample.setModuleId(request.getModuleId());
|
||||
if (StringUtils.isNotBlank(request.getName())) {
|
||||
this.checkFileName(request.getId(), request.getName(), fileMetadata.getProjectId());
|
||||
updateExample.setName(request.getName());
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(request.getTags())) {
|
||||
updateExample.setTags(JSON.toJSONString(request.getTags()));
|
||||
}
|
||||
updateExample.setUpdateUser(operator);
|
||||
updateExample.setUpdateTime(System.currentTimeMillis());
|
||||
fileMetadataMapper.updateByPrimaryKeySelective(updateExample);
|
||||
//记录日志
|
||||
fileMetadataLogService.saveUpdateLog(fileMetadata, fileMetadata.getProjectId(), operator);
|
||||
}
|
||||
}
|
||||
|
||||
public FileTableResult page(FileMetadataTableRequest request) {
|
||||
FileTableResult dto = new FileTableResult();
|
||||
Page<Object> page = PageHelper.startPage(request.getCurrent(), request.getPageSize(),
|
||||
StringUtils.isNotBlank(request.getSortString()) ? request.getSortString() : "update_time desc");
|
||||
dto.setTableData(PageUtils.setPageInfo(page, this.list(request)));
|
||||
|
||||
//获取模块统计
|
||||
List<ModuleCountDTO> moduleCountDTOList = extFileMetadataMapper.countModuleIdByKeywordAndFileType(request.getProjectId(), request.getKeyword(), request.getModuleIds(), request.getFileTypes());
|
||||
Map<String, Long> moduleCountMap = moduleCountDTOList.stream().collect(Collectors.toMap(ModuleCountDTO::getModuleId, ModuleCountDTO::getDataCount));
|
||||
dto.setModuleCount(moduleCountMap);
|
||||
return dto;
|
||||
}
|
||||
|
||||
public ResponseEntity<byte[]> batchDownload(FileBatchProcessDTO request) {
|
||||
List<FileMetadata> fileMetadataList = fileManagementService.getProcessList(request);
|
||||
this.checkDownloadSize(fileMetadataList);
|
||||
try {
|
||||
byte[] bytes = this.batchDownload(fileMetadataList);
|
||||
return ResponseEntity.ok()
|
||||
.contentType(MediaType.parseMediaType("application/octet-stream"))
|
||||
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=" + "files.zip")
|
||||
.body(bytes);
|
||||
} catch (Exception e) {
|
||||
return ResponseEntity.status(509).body(e.getMessage().getBytes());
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] batchDownload(List<FileMetadata> fileMetadataList) {
|
||||
Map<String, byte[]> files = new LinkedHashMap<>();
|
||||
fileMetadataList.forEach(fileMetadata -> {
|
||||
byte[] bytes = this.getFile(fileMetadata);
|
||||
if (bytes != null) {
|
||||
files.put(this.getFileName(fileMetadata.getName(), fileMetadata.getType()), bytes);
|
||||
}
|
||||
});
|
||||
|
||||
return FileDownloadUtils.listBytesToZip(files);
|
||||
}
|
||||
|
||||
//检查下载的文件的大小
|
||||
private void checkDownloadSize(List<FileMetadata> fileMetadataList) {
|
||||
AtomicLong fileSize = new AtomicLong();
|
||||
if (CollectionUtils.isNotEmpty(fileMetadataList)) {
|
||||
fileMetadataList.forEach(item -> fileSize.addAndGet(item.getSize()));
|
||||
}
|
||||
|
||||
if (fileSize.get() == 0) {
|
||||
throw new MSException(Translator.get("file.size.is.zero"));
|
||||
}
|
||||
|
||||
DataSize dataSize = DataSize.ofBytes(fileSize.get());
|
||||
if (maxFileSize.compareTo(dataSize) < 0) {
|
||||
throw new MSException(Translator.get("file.size.is.too.large"));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,127 @@
|
|||
package io.metersphere.project.service;
|
||||
|
||||
import io.metersphere.project.domain.FileModule;
|
||||
import io.metersphere.project.domain.Project;
|
||||
import io.metersphere.project.mapper.FileModuleMapper;
|
||||
import io.metersphere.project.mapper.ProjectMapper;
|
||||
import io.metersphere.sdk.constants.HttpMethodConstants;
|
||||
import io.metersphere.sdk.dto.LogDTO;
|
||||
import io.metersphere.sdk.dto.builder.LogDTOBuilder;
|
||||
import io.metersphere.sdk.dto.request.NodeMoveRequest;
|
||||
import io.metersphere.sdk.util.JSON;
|
||||
import io.metersphere.sdk.util.Translator;
|
||||
import io.metersphere.system.log.constants.OperationLogModule;
|
||||
import io.metersphere.system.log.constants.OperationLogType;
|
||||
import io.metersphere.system.log.service.OperationLogService;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public class FileModuleLogService {
|
||||
@Resource
|
||||
private FileModuleMapper fileModuleMapper;
|
||||
@Resource
|
||||
private ProjectMapper projectMapper;
|
||||
@Resource
|
||||
private OperationLogService operationLogService;
|
||||
|
||||
public void saveAddLog(FileModule module, String operator) {
|
||||
Project project = projectMapper.selectByPrimaryKey(module.getProjectId());
|
||||
LogDTO dto = LogDTOBuilder.builder()
|
||||
.projectId(module.getProjectId())
|
||||
.organizationId(project.getOrganizationId())
|
||||
.type(OperationLogType.ADD.name())
|
||||
.module(OperationLogModule.PROJECT_FILE_MANAGEMENT)
|
||||
.method(HttpMethodConstants.POST.name())
|
||||
.path("/project/file-module/add")
|
||||
.sourceId(module.getId())
|
||||
.content(module.getName())
|
||||
.originalValue(JSON.toJSONBytes(module))
|
||||
.createUser(operator)
|
||||
.build().getLogDTO();
|
||||
operationLogService.add(dto);
|
||||
}
|
||||
|
||||
public void saveUpdateLog(FileModule module, String projectId, String operator) {
|
||||
Project project = projectMapper.selectByPrimaryKey(projectId);
|
||||
LogDTO dto = LogDTOBuilder.builder()
|
||||
.projectId(projectId)
|
||||
.organizationId(project.getOrganizationId())
|
||||
.type(OperationLogType.UPDATE.name())
|
||||
.module(OperationLogModule.PROJECT_FILE_MANAGEMENT)
|
||||
.method(HttpMethodConstants.POST.name())
|
||||
.path("/project/file-module/update")
|
||||
.sourceId(module.getId())
|
||||
.content(module.getName())
|
||||
.originalValue(JSON.toJSONBytes(module))
|
||||
.createUser(operator)
|
||||
.build().getLogDTO();
|
||||
|
||||
operationLogService.add(dto);
|
||||
}
|
||||
|
||||
public void saveDeleteLog(FileModule deleteModule, String operator) {
|
||||
Project project = projectMapper.selectByPrimaryKey(deleteModule.getProjectId());
|
||||
LogDTO dto = LogDTOBuilder.builder()
|
||||
.projectId(deleteModule.getProjectId())
|
||||
.organizationId(project.getOrganizationId())
|
||||
.type(OperationLogType.DELETE.name())
|
||||
.module(OperationLogModule.PROJECT_FILE_MANAGEMENT)
|
||||
.method(HttpMethodConstants.GET.name())
|
||||
.path("/project/file-module/delete/%s")
|
||||
.sourceId(deleteModule.getId())
|
||||
.content(deleteModule.getName() + " " + Translator.get("file.log.delete_module"))
|
||||
.originalValue(JSON.toJSONBytes(deleteModule))
|
||||
.createUser(operator)
|
||||
.build().getLogDTO();
|
||||
operationLogService.add(dto);
|
||||
}
|
||||
|
||||
public void saveMoveLog(NodeMoveRequest request, String operator) {
|
||||
FileModule moveNode;
|
||||
FileModule previousNode = null;
|
||||
FileModule nextNode = null;
|
||||
FileModule parentModule;
|
||||
moveNode = fileModuleMapper.selectByPrimaryKey(request.getNodeId());
|
||||
if (request.getPreviousNodeId() != null) {
|
||||
previousNode = fileModuleMapper.selectByPrimaryKey(request.getPreviousNodeId());
|
||||
}
|
||||
if (request.getNextNodeId() != null) {
|
||||
nextNode = fileModuleMapper.selectByPrimaryKey(request.getNextNodeId());
|
||||
}
|
||||
|
||||
parentModule = fileModuleMapper.selectByPrimaryKey(request.getParentId());
|
||||
if (parentModule == null) {
|
||||
parentModule = new FileModule();
|
||||
parentModule.setName(Translator.get("file.module.root"));
|
||||
}
|
||||
|
||||
Project project = projectMapper.selectByPrimaryKey(moveNode.getProjectId());
|
||||
String logContent;
|
||||
if (nextNode == null && previousNode == null) {
|
||||
logContent = moveNode.getName() + " " + Translator.get("file.log.move_to") + parentModule.getName();
|
||||
} else if (nextNode == null) {
|
||||
logContent = moveNode.getName() + " " + Translator.get("file.log.move_to") + parentModule.getName() + " " + previousNode.getName() + Translator.get("file.log.next");
|
||||
} else if (previousNode == null) {
|
||||
logContent = moveNode.getName() + " " + Translator.get("file.log.move_to") + parentModule.getName() + " " + nextNode.getName() + Translator.get("file.log.previous");
|
||||
} else {
|
||||
logContent = moveNode.getName() + " " + Translator.get("file.log.move_to") + parentModule.getName() + " " +
|
||||
previousNode.getName() + Translator.get("file.log.next") + " " + nextNode.getName() + Translator.get("file.log.previous");
|
||||
}
|
||||
LogDTO dto = LogDTOBuilder.builder()
|
||||
.projectId(moveNode.getProjectId())
|
||||
.organizationId(project.getOrganizationId())
|
||||
.type(OperationLogType.UPDATE.name())
|
||||
.module(OperationLogModule.PROJECT_FILE_MANAGEMENT)
|
||||
.method(HttpMethodConstants.POST.name())
|
||||
.path("/project/file-module/move")
|
||||
.sourceId(moveNode.getId())
|
||||
.content(logContent)
|
||||
.originalValue(JSON.toJSONBytes(moveNode))
|
||||
.createUser(operator)
|
||||
.build().getLogDTO();
|
||||
operationLogService.add(dto);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,234 @@
|
|||
package io.metersphere.project.service;
|
||||
|
||||
import io.metersphere.project.domain.FileModule;
|
||||
import io.metersphere.project.domain.FileModuleExample;
|
||||
import io.metersphere.project.mapper.ExtFileModuleMapper;
|
||||
import io.metersphere.project.mapper.FileModuleMapper;
|
||||
import io.metersphere.project.request.filemanagement.FileModuleCreateRequest;
|
||||
import io.metersphere.project.request.filemanagement.FileModuleUpdateRequest;
|
||||
import io.metersphere.sdk.constants.ModuleConstants;
|
||||
import io.metersphere.sdk.dto.BaseModule;
|
||||
import io.metersphere.sdk.dto.BaseTreeNode;
|
||||
import io.metersphere.sdk.dto.request.NodeMoveRequest;
|
||||
import io.metersphere.sdk.exception.MSException;
|
||||
import io.metersphere.sdk.service.ModuleTreeService;
|
||||
import io.metersphere.sdk.util.Translator;
|
||||
import io.metersphere.system.service.CleanupProjectResourceService;
|
||||
import io.metersphere.system.uid.UUID;
|
||||
import io.metersphere.system.utils.SessionUtils;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.ibatis.session.ExecutorType;
|
||||
import org.apache.ibatis.session.SqlSession;
|
||||
import org.apache.ibatis.session.SqlSessionFactory;
|
||||
import org.mybatis.spring.SqlSessionUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@Service
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public class FileModuleService extends ModuleTreeService implements CleanupProjectResourceService {
|
||||
@Resource
|
||||
private FileModuleLogService fileModuleLogService;
|
||||
@Resource
|
||||
private FileModuleMapper fileModuleMapper;
|
||||
@Resource
|
||||
private ExtFileModuleMapper extFileModuleMapper;
|
||||
@Resource
|
||||
private SqlSessionFactory sqlSessionFactory;
|
||||
@Resource
|
||||
private FileManagementService fileManagementService;
|
||||
|
||||
public List<BaseTreeNode> getTree(String projectId) {
|
||||
BaseTreeNode defaultNode = this.getDefaultModule();
|
||||
List<BaseTreeNode> baseTreeNodeList = new ArrayList<>();
|
||||
baseTreeNodeList.add(defaultNode);
|
||||
List<FileModule> fileModuleList = extFileModuleMapper.selectBaseByProjectId(projectId);
|
||||
int lastSize = 0;
|
||||
Map<String, BaseTreeNode> baseTreeNodeMap = new HashMap<>();
|
||||
while (CollectionUtils.isNotEmpty(fileModuleList) && fileModuleList.size() != lastSize) {
|
||||
List<FileModule> notMatchedList = new ArrayList<>();
|
||||
for (FileModule fileModule : fileModuleList) {
|
||||
if (StringUtils.equals(fileModule.getParentId(), ModuleConstants.ROOT_NODE_PARENT_ID)) {
|
||||
BaseTreeNode node = new BaseTreeNode(fileModule.getId(), fileModule.getName(), ModuleConstants.NODE_TYPE_DEFAULT);
|
||||
baseTreeNodeList.add(node);
|
||||
baseTreeNodeMap.put(fileModule.getId(), node);
|
||||
} else {
|
||||
if (baseTreeNodeMap.containsKey(fileModule.getParentId())) {
|
||||
BaseTreeNode node = new BaseTreeNode(fileModule.getId(), fileModule.getName(), ModuleConstants.NODE_TYPE_DEFAULT);
|
||||
baseTreeNodeMap.get(fileModule.getParentId()).addChild(node);
|
||||
baseTreeNodeMap.put(fileModule.getId(), node);
|
||||
} else {
|
||||
notMatchedList.add(fileModule);
|
||||
}
|
||||
}
|
||||
}
|
||||
fileModuleList = notMatchedList;
|
||||
}
|
||||
return baseTreeNodeList;
|
||||
}
|
||||
|
||||
public String add(FileModuleCreateRequest request, String operator) {
|
||||
FileModule fileModule = new FileModule();
|
||||
fileModule.setId(UUID.randomUUID().toString());
|
||||
fileModule.setName(request.getName());
|
||||
fileModule.setParentId(request.getParentId());
|
||||
fileModule.setProjectId(request.getProjectId());
|
||||
this.checkDataValidity(fileModule);
|
||||
fileModule.setCreateTime(System.currentTimeMillis());
|
||||
fileModule.setUpdateTime(fileModule.getCreateTime());
|
||||
fileModule.setPos(this.countPos(request.getParentId()));
|
||||
fileModule.setCreateUser(operator);
|
||||
fileModule.setUpdateUser(operator);
|
||||
fileModule.setModuleType(ModuleConstants.NODE_TYPE_DEFAULT);
|
||||
fileModuleMapper.insert(fileModule);
|
||||
|
||||
//记录日志
|
||||
fileModuleLogService.saveAddLog(fileModule, operator);
|
||||
return fileModule.getId();
|
||||
}
|
||||
|
||||
private Integer countPos(String parentId) {
|
||||
Integer maxPos = extFileModuleMapper.getMaxPosByParentId(parentId);
|
||||
if (maxPos == null) {
|
||||
return LIMIT_POS;
|
||||
} else {
|
||||
return maxPos + LIMIT_POS;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查数据的合法性
|
||||
*/
|
||||
private void checkDataValidity(FileModule fileModule) {
|
||||
FileModuleExample example = new FileModuleExample();
|
||||
if (!StringUtils.equals(fileModule.getParentId(), ModuleConstants.ROOT_NODE_PARENT_ID)) {
|
||||
//检查父ID是否存在
|
||||
example.createCriteria().andIdEqualTo(fileModule.getParentId());
|
||||
if (fileModuleMapper.countByExample(example) == 0) {
|
||||
throw new MSException(Translator.get("parent.node.not_blank"));
|
||||
}
|
||||
example.clear();
|
||||
|
||||
if (StringUtils.isNotBlank(fileModule.getProjectId())) {
|
||||
//检查项目ID是否和父节点ID一致
|
||||
example.createCriteria().andProjectIdEqualTo(fileModule.getProjectId()).andIdEqualTo(fileModule.getParentId());
|
||||
if (fileModuleMapper.countByExample(example) == 0) {
|
||||
throw new MSException(Translator.get("project.cannot.match.parent"));
|
||||
}
|
||||
example.clear();
|
||||
}
|
||||
}
|
||||
example.createCriteria().andParentIdEqualTo(fileModule.getParentId()).andNameEqualTo(fileModule.getName()).andIdNotEqualTo(fileModule.getId());
|
||||
if (fileModuleMapper.countByExample(example) > 0) {
|
||||
throw new MSException(Translator.get("node.name.repeat"));
|
||||
}
|
||||
example.clear();
|
||||
}
|
||||
|
||||
public void update(FileModuleUpdateRequest request, String userId) {
|
||||
FileModule module = fileModuleMapper.selectByPrimaryKey(request.getId());
|
||||
if (module == null) {
|
||||
throw new MSException("file_module.not.exist");
|
||||
}
|
||||
FileModule updateModule = new FileModule();
|
||||
updateModule.setId(request.getId());
|
||||
updateModule.setName(request.getName());
|
||||
updateModule.setParentId(module.getParentId());
|
||||
this.checkDataValidity(updateModule);
|
||||
updateModule.setUpdateTime(System.currentTimeMillis());
|
||||
updateModule.setUpdateUser(userId);
|
||||
fileModuleMapper.updateByPrimaryKeySelective(updateModule);
|
||||
//记录日志
|
||||
fileModuleLogService.saveUpdateLog(updateModule, module.getProjectId(), userId);
|
||||
}
|
||||
|
||||
|
||||
public void deleteModule(String deleteId) {
|
||||
FileModule deleteModule = fileModuleMapper.selectByPrimaryKey(deleteId);
|
||||
if (deleteModule != null) {
|
||||
this.deleteModule(Collections.singletonList(deleteId));
|
||||
//记录日志
|
||||
fileModuleLogService.saveDeleteLog(deleteModule, SessionUtils.getUserId());
|
||||
}
|
||||
}
|
||||
public void deleteModule(List<String> deleteIds) {
|
||||
if (CollectionUtils.isEmpty(deleteIds)) {
|
||||
return;
|
||||
}
|
||||
extFileModuleMapper.deleteByIds(deleteIds);
|
||||
fileManagementService.deleteByModuleIds(deleteIds);
|
||||
|
||||
List<String> childrenIds = extFileModuleMapper.selectChildrenIdsByParentIds(deleteIds);
|
||||
if (CollectionUtils.isNotEmpty(childrenIds)) {
|
||||
deleteModule(childrenIds);
|
||||
}
|
||||
}
|
||||
|
||||
public void moveNode(NodeMoveRequest request) {
|
||||
FileModuleExample example = new FileModuleExample();
|
||||
example.createCriteria().andParentIdEqualTo(request.getParentId()).andIdEqualTo(request.getNodeId());
|
||||
if (fileModuleMapper.countByExample(example) == 0) {
|
||||
//节点换到了别的节点下
|
||||
FileModule fileModule = new FileModule();
|
||||
fileModule.setId(request.getNodeId());
|
||||
fileModule.setParentId(request.getParentId());
|
||||
fileModuleMapper.updateByPrimaryKeySelective(fileModule);
|
||||
}
|
||||
this.sort(request);
|
||||
|
||||
//记录日志
|
||||
fileModuleLogService.saveMoveLog(request, SessionUtils.getUserId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseModule getNode(String id) {
|
||||
FileModule module = fileModuleMapper.selectByPrimaryKey(id);
|
||||
if (module == null) {
|
||||
return null;
|
||||
} else {
|
||||
return new BaseModule(module.getId(), module.getName(), module.getPos(), module.getProjectId(), module.getParentId());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updatePos(String id, int pos) {
|
||||
FileModule updateModule = new FileModule();
|
||||
updateModule.setPos(pos);
|
||||
updateModule.setId(id);
|
||||
fileModuleMapper.updateByPrimaryKeySelective(updateModule);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshPos(String parentId) {
|
||||
List<String> childrenIdSortByPos = extFileModuleMapper.selectChildrenIdsSortByPos(parentId);
|
||||
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
|
||||
FileModuleMapper batchUpdateMapper = sqlSession.getMapper(FileModuleMapper.class);
|
||||
for (int i = 0; i < childrenIdSortByPos.size(); i++) {
|
||||
String nodeId = childrenIdSortByPos.get(i);
|
||||
FileModule updateModule = new FileModule();
|
||||
updateModule.setId(nodeId);
|
||||
updateModule.setPos((i + 1) * LIMIT_POS);
|
||||
batchUpdateMapper.updateByPrimaryKeySelective(updateModule);
|
||||
}
|
||||
sqlSession.flushStatements();
|
||||
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteResources(String projectId) {
|
||||
List<String> fileModuleIdList = extFileModuleMapper.selectIdsByProjectId(projectId);
|
||||
if (CollectionUtils.isNotEmpty(fileModuleIdList)) {
|
||||
this.deleteModule(fileModuleIdList);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanReportResources(String projectId) {
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package io.metersphere.project.utils;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.util.Map;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
public class FileDownloadUtils {
|
||||
public static byte[] listBytesToZip(Map<String, byte[]> mapReport) {
|
||||
try {
|
||||
if (!mapReport.isEmpty()) {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ZipOutputStream zos = new ZipOutputStream(baos);
|
||||
for (Map.Entry<String, byte[]> report : mapReport.entrySet()) {
|
||||
ZipEntry entry = new ZipEntry(report.getKey());
|
||||
entry.setSize(report.getValue().length);
|
||||
zos.putNextEntry(entry);
|
||||
zos.write(report.getValue());
|
||||
}
|
||||
zos.closeEntry();
|
||||
zos.close();
|
||||
return baos.toByteArray();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return new byte[10];
|
||||
}
|
||||
return new byte[10];
|
||||
}
|
||||
}
|
|
@ -137,6 +137,28 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "PROJECT_FILE_MANAGEMENT",
|
||||
"name": "permission.project_file.name",
|
||||
"permissions": [
|
||||
{
|
||||
"id": "PROJECT_FILE_MANAGEMENT:READ"
|
||||
},
|
||||
{
|
||||
"id": "PROJECT_FILE_MANAGEMENT:READ+ADD"
|
||||
},
|
||||
{
|
||||
"id": "PROJECT_FILE_MANAGEMENT:READ+UPDATE"
|
||||
},
|
||||
{
|
||||
"id": "PROJECT_FILE_MANAGEMENT:READ+DOWNLOAD",
|
||||
"name": "permission.project_file.download"
|
||||
},
|
||||
{
|
||||
"id": "PROJECT_FILE_MANAGEMENT:READ+DELETE"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "PROJECT_FAKE_ERROR",
|
||||
"name": "permission.project_fake_error.name",
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,137 @@
|
|||
package io.metersphere.project.controller.filemanagement;
|
||||
|
||||
import io.metersphere.project.request.filemanagement.*;
|
||||
import io.metersphere.project.utils.FileManagementBaseUtils;
|
||||
import io.metersphere.project.utils.FileManagementRequestUtils;
|
||||
import io.metersphere.sdk.constants.ModuleConstants;
|
||||
import io.metersphere.sdk.constants.PermissionConstants;
|
||||
import io.metersphere.sdk.dto.request.NodeMoveRequest;
|
||||
import io.metersphere.sdk.util.JSON;
|
||||
import io.metersphere.system.base.BaseTest;
|
||||
import org.junit.jupiter.api.MethodOrderer;
|
||||
import org.junit.jupiter.api.Order;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.TestMethodOrder;
|
||||
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.mock.web.MockMultipartFile;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Objects;
|
||||
|
||||
@SpringBootTest
|
||||
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
||||
@AutoConfigureMockMvc
|
||||
public class FileManagementPermissionControllerTests extends BaseTest {
|
||||
private static final String TEST_ID = "test";
|
||||
|
||||
@Test
|
||||
@Order(1)
|
||||
public void addModuleTestSuccess() throws Exception {
|
||||
FileModuleCreateRequest request = new FileModuleCreateRequest();
|
||||
request.setProjectId(DEFAULT_PROJECT_ID);
|
||||
request.setName("a1");
|
||||
this.requestPostPermissionTest(PermissionConstants.PROJECT_FILE_MANAGEMENT_READ_ADD, FileManagementRequestUtils.URL_MODULE_ADD, request);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@Order(2)
|
||||
public void updateModuleTestSuccess() throws Exception {
|
||||
FileModuleUpdateRequest updateRequest = new FileModuleUpdateRequest();
|
||||
updateRequest.setId(TEST_ID);
|
||||
updateRequest.setName("a1-a1");
|
||||
this.requestPostPermissionTest(PermissionConstants.PROJECT_FILE_MANAGEMENT_READ_UPDATE, FileManagementRequestUtils.URL_MODULE_UPDATE, updateRequest);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(3)
|
||||
public void fileUploadTestSuccess() throws Exception {
|
||||
//这个权限无法校验
|
||||
FileUploadRequest fileUploadRequest = new FileUploadRequest();
|
||||
fileUploadRequest.setProjectId(DEFAULT_PROJECT_ID);
|
||||
String filePath = Objects.requireNonNull(this.getClass().getClassLoader().getResource("file/file_upload.JPG")).getPath();
|
||||
MockMultipartFile file = new MockMultipartFile("file", "file_upload.JPG", MediaType.APPLICATION_OCTET_STREAM_VALUE, FileManagementBaseUtils.getFileBytes(filePath));
|
||||
MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<>();
|
||||
paramMap.add("file", file);
|
||||
paramMap.add("request", JSON.toJSONString(fileUploadRequest));
|
||||
this.requestMultipartPermissionTest(PermissionConstants.PROJECT_FILE_MANAGEMENT_READ_ADD, FileManagementRequestUtils.URL_FILE_UPLOAD, paramMap);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@Order(4)
|
||||
public void fileReUploadTestSuccess() throws Exception {
|
||||
|
||||
FileUploadRequest fileUploadRequest = new FileUploadRequest();
|
||||
fileUploadRequest.setProjectId(DEFAULT_PROJECT_ID);
|
||||
|
||||
//重新上传并修改文件版本
|
||||
FileReUploadRequest fileReUploadRequest = new FileReUploadRequest();
|
||||
fileReUploadRequest.setFileId(TEST_ID);
|
||||
String filePath = Objects.requireNonNull(this.getClass().getClassLoader().getResource("file/file_re-upload.JPG")).getPath();
|
||||
MockMultipartFile file = new MockMultipartFile("file", "file_re-upload.JPG", MediaType.APPLICATION_OCTET_STREAM_VALUE, FileManagementBaseUtils.getFileBytes(filePath));
|
||||
LinkedMultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<>();
|
||||
paramMap.add("file", file);
|
||||
paramMap.add("request", JSON.toJSONString(fileReUploadRequest));
|
||||
|
||||
this.requestMultipartPermissionTest(PermissionConstants.PROJECT_FILE_MANAGEMENT_READ_UPDATE, FileManagementRequestUtils.URL_FILE_RE_UPLOAD, paramMap);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(5)
|
||||
public void filePageTestSuccess() throws Exception {
|
||||
FileMetadataTableRequest request = new FileMetadataTableRequest() {{
|
||||
this.setCurrent(1);
|
||||
this.setPageSize(10);
|
||||
this.setProjectId(DEFAULT_PROJECT_ID);
|
||||
}};
|
||||
this.requestPostPermissionTest(PermissionConstants.PROJECT_FILE_MANAGEMENT_READ, FileManagementRequestUtils.URL_FILE_PAGE, request);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void fileDeleteSuccess() throws Exception {
|
||||
FileBatchProcessDTO fileBatchProcessDTO = new FileBatchProcessDTO();
|
||||
fileBatchProcessDTO.setProjectId(DEFAULT_PROJECT_ID);
|
||||
fileBatchProcessDTO.setSelectIds(new ArrayList<>() {{
|
||||
this.add(TEST_ID);
|
||||
}});
|
||||
this.requestPostPermissionTest(PermissionConstants.PROJECT_FILE_MANAGEMENT_READ_DELETE, FileManagementRequestUtils.URL_FILE_DELETE, fileBatchProcessDTO);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fileUpdateSuccess() throws Exception {
|
||||
|
||||
FileUpdateRequest updateRequest = new FileUpdateRequest();
|
||||
updateRequest.setId(TEST_ID);
|
||||
updateRequest.setName("update_" + TEST_ID);
|
||||
updateRequest.setTags(new ArrayList<>() {{
|
||||
this.add("tag1");
|
||||
}});
|
||||
this.requestPostPermissionTest(PermissionConstants.PROJECT_FILE_MANAGEMENT_READ_UPDATE, FileManagementRequestUtils.URL_FILE_UPDATE, updateRequest);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void moveTest() throws Exception {
|
||||
|
||||
{
|
||||
NodeMoveRequest request = new NodeMoveRequest();
|
||||
request.setNodeId(TEST_ID);
|
||||
request.setParentId(ModuleConstants.ROOT_NODE_PARENT_ID);
|
||||
this.requestPostPermissionTest(PermissionConstants.PROJECT_FILE_MANAGEMENT_READ_UPDATE, FileManagementRequestUtils.URL_MODULE_MOVE, request);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Order(90)
|
||||
public void deleteModuleTestSuccess() throws Exception {
|
||||
this.requestGetPermissionTest(PermissionConstants.PROJECT_FILE_MANAGEMENT_READ_DELETE, String.format(FileManagementRequestUtils.URL_MODULE_DELETE, TEST_ID));
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,127 @@
|
|||
package io.metersphere.project.utils;
|
||||
|
||||
import io.metersphere.project.dto.FileInformationDTO;
|
||||
import io.metersphere.project.dto.FileTableResult;
|
||||
import io.metersphere.project.request.filemanagement.FileMetadataTableRequest;
|
||||
import io.metersphere.sdk.dto.BaseTreeNode;
|
||||
import io.metersphere.sdk.util.FilePreviewUtil;
|
||||
import io.metersphere.sdk.util.JSON;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.testcontainers.shaded.org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.math.BigInteger;
|
||||
import java.security.MessageDigest;
|
||||
import java.util.List;
|
||||
|
||||
public class FileManagementBaseUtils {
|
||||
public static BaseTreeNode getNodeByName(List<BaseTreeNode> preliminaryTreeNodes, String nodeName) {
|
||||
for (BaseTreeNode firstLevelNode : preliminaryTreeNodes) {
|
||||
if (StringUtils.equals(firstLevelNode.getName(), nodeName)) {
|
||||
return firstLevelNode;
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(firstLevelNode.getChildren())) {
|
||||
for (BaseTreeNode secondLevelNode : firstLevelNode.getChildren()) {
|
||||
if (StringUtils.equals(secondLevelNode.getName(), nodeName)) {
|
||||
return secondLevelNode;
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(secondLevelNode.getChildren())) {
|
||||
for (BaseTreeNode thirdLevelNode : secondLevelNode.getChildren()) {
|
||||
if (StringUtils.equals(thirdLevelNode.getName(), nodeName)) {
|
||||
return thirdLevelNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static byte[] getFileBytes(String filePath) {
|
||||
File file = new File(filePath);
|
||||
byte[] buffer = new byte[0];
|
||||
try (FileInputStream fi = new FileInputStream(file)) {
|
||||
buffer = new byte[(int) file.length()];
|
||||
int offset = 0;
|
||||
int numRead;
|
||||
while (offset < buffer.length
|
||||
&& (numRead = fi.read(buffer, offset, buffer.length - offset)) >= 0) {
|
||||
offset += numRead;
|
||||
}
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public static String getFileMD5(File file) {
|
||||
if (!file.isFile()) {
|
||||
return null;
|
||||
}
|
||||
MessageDigest digest = null;
|
||||
FileInputStream in = null;
|
||||
byte buffer[] = new byte[8192];
|
||||
int len;
|
||||
try {
|
||||
digest = MessageDigest.getInstance("MD5");
|
||||
in = new FileInputStream(file);
|
||||
while ((len = in.read(buffer)) != -1) {
|
||||
digest.update(buffer, 0, len);
|
||||
}
|
||||
BigInteger bigInt = new BigInteger(1, digest.digest());
|
||||
return bigInt.toString(16);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
} finally {
|
||||
try {
|
||||
in.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static String getFileMD5(byte[] bytes) {
|
||||
try {
|
||||
MessageDigest digest = MessageDigest.getInstance("MD5");
|
||||
digest.update(bytes, 0, bytes.length);
|
||||
BigInteger bigInt = new BigInteger(1, digest.digest());
|
||||
return bigInt.toString(16);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static void checkFilePage(FileTableResult result, FileMetadataTableRequest request, boolean hasData) {
|
||||
//返回值的页码和当前页码相同
|
||||
Assertions.assertEquals(result.getTableData().getCurrent(), request.getCurrent());
|
||||
//返回的数据量不超过规定要返回的数据量相同
|
||||
Assertions.assertTrue(JSON.parseArray(JSON.toJSONString(result.getTableData().getList())).size() <= request.getPageSize());
|
||||
List<FileInformationDTO> fileInformationDTOList = JSON.parseArray(JSON.toJSONString(result.getTableData().getList()), FileInformationDTO.class);
|
||||
for (FileInformationDTO fileInformationDTO : fileInformationDTOList) {
|
||||
if (FilePreviewUtil.isImage(fileInformationDTO.getFileType())) {
|
||||
//检查是否有预览文件
|
||||
String previewPath = fileInformationDTO.getPreviewSrc();
|
||||
File file = new File(previewPath);
|
||||
Assertions.assertTrue(file.exists());
|
||||
}
|
||||
}
|
||||
|
||||
//判断返回的节点统计总量是否和表格总量匹配
|
||||
long allResult = 0;
|
||||
for (Long countByModuleId : result.getModuleCount().values()) {
|
||||
allResult += countByModuleId;
|
||||
}
|
||||
Assertions.assertEquals(allResult, result.getTableData().getTotal());
|
||||
Assertions.assertEquals(request.getPageSize(), result.getTableData().getPageSize());
|
||||
if (hasData) {
|
||||
Assertions.assertTrue(allResult > 0);
|
||||
} else {
|
||||
Assertions.assertTrue(allResult == 0);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package io.metersphere.project.utils;
|
||||
|
||||
public class FileManagementRequestUtils {
|
||||
//文件模块树查询
|
||||
public static final String URL_MODULE_TREE = "/project/file-module/tree/%s";
|
||||
//添加文件模块
|
||||
public static final String URL_MODULE_ADD = "/project/file-module/add";
|
||||
//修改文件模块
|
||||
public static final String URL_MODULE_UPDATE = "/project/file-module/update";
|
||||
//删除文件模块
|
||||
public static final String URL_MODULE_DELETE = "/project/file-module/delete/%s";
|
||||
//移动文件模块
|
||||
public static final String URL_MODULE_MOVE = "/project/file-module/move";
|
||||
|
||||
//文件上传
|
||||
public static final String URL_FILE_UPLOAD = "/project/file/upload";
|
||||
//文件列表查询
|
||||
public static final String URL_FILE_PAGE = "/project/file/page";
|
||||
//文件重传
|
||||
public static final String URL_FILE_RE_UPLOAD = "/project/file/re-upload";
|
||||
//文件下载
|
||||
public static final String URL_FILE_DOWNLOAD = "/project/file/download/%s";
|
||||
//文件批量下载
|
||||
public static final String URL_FILE_BATCH_DOWNLOAD = "/project/file/batch-download";
|
||||
//文件批量删除
|
||||
public static final String URL_FILE_DELETE = "/project/file/delete";
|
||||
//文件信息修改
|
||||
public static final String URL_FILE_UPDATE = "/project/file/update";
|
||||
|
||||
}
|
|
@ -83,4 +83,5 @@ minio.secret-key=${embedded.minio.secretKey}
|
|||
|
||||
logging.level.org.springframework.jdbc.core=info
|
||||
logging.level.io.metersphere.sdk.mapper=info
|
||||
logging.level.io.metersphere.project.mapper=info
|
||||
logging.level.io.metersphere.project.mapper=info
|
||||
metersphere.file.batch-download-max=600MB
|
|
@ -0,0 +1 @@
|
|||
这是用来做反例测试的
|
Binary file not shown.
After Width: | Height: | Size: 710 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.3 MiB |
|
@ -0,0 +1 @@
|
|||
这是证明文件没后缀的
|
|
@ -0,0 +1 @@
|
|||
普通txt文件
|
|
@ -1,7 +1,7 @@
|
|||
package io.metersphere.system.config.interceptor;
|
||||
|
||||
import io.metersphere.project.domain.CustomFunctionBlob;
|
||||
import io.metersphere.project.domain.FileMetadataBlob;
|
||||
import io.metersphere.project.domain.FileMetadataRepository;
|
||||
import io.metersphere.sdk.util.CompressUtils;
|
||||
import io.metersphere.sdk.util.MybatisInterceptorConfig;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
@ -16,7 +16,7 @@ public class ProjectInterceptor {
|
|||
public List<MybatisInterceptorConfig> projectCompressConfigs() {
|
||||
List<MybatisInterceptorConfig> configList = new ArrayList<>();
|
||||
|
||||
configList.add(new MybatisInterceptorConfig(FileMetadataBlob.class, "gitInfo", CompressUtils.class, "zip", "unzip"));
|
||||
configList.add(new MybatisInterceptorConfig(FileMetadataRepository.class, "gitInfo", CompressUtils.class, "zip", "unzip"));
|
||||
configList.add(new MybatisInterceptorConfig(CustomFunctionBlob.class, "script", CompressUtils.class, "zip", "unzip"));
|
||||
configList.add(new MybatisInterceptorConfig(CustomFunctionBlob.class, "result", CompressUtils.class, "zip", "unzip"));
|
||||
configList.add(new MybatisInterceptorConfig(CustomFunctionBlob.class, "params", CompressUtils.class, "zip", "unzip"));
|
||||
|
|
|
@ -4,8 +4,8 @@ package io.metersphere.system.service;
|
|||
* 清理项目资源
|
||||
*/
|
||||
public interface CleanupProjectResourceService {
|
||||
void deleteResources(String projectId);
|
||||
|
||||
void deleteResources(String projectId);
|
||||
|
||||
/**
|
||||
* 清理报告资源
|
||||
|
|
|
@ -8,12 +8,12 @@ import io.metersphere.sdk.constants.OperationLogConstants;
|
|||
import io.metersphere.sdk.dto.LogDTO;
|
||||
import io.metersphere.sdk.dto.TableBatchProcessDTO;
|
||||
import io.metersphere.sdk.dto.builder.LogDTOBuilder;
|
||||
import io.metersphere.system.log.constants.OperationLogModule;
|
||||
import io.metersphere.system.log.constants.OperationLogType;
|
||||
import io.metersphere.system.log.service.OperationLogService;
|
||||
import io.metersphere.sdk.util.JSON;
|
||||
import io.metersphere.sdk.util.Translator;
|
||||
import io.metersphere.system.domain.*;
|
||||
import io.metersphere.system.log.constants.OperationLogModule;
|
||||
import io.metersphere.system.log.constants.OperationLogType;
|
||||
import io.metersphere.system.log.service.OperationLogService;
|
||||
import io.metersphere.system.mapper.OrganizationMapper;
|
||||
import io.metersphere.system.mapper.UserMapper;
|
||||
import io.metersphere.system.mapper.UserRoleMapper;
|
||||
|
@ -56,7 +56,7 @@ public class UserLogService {
|
|||
.type(OperationLogType.ADD.name())
|
||||
.module(OperationLogModule.SETTING_SYSTEM_USER_SINGLE)
|
||||
.method(HttpMethodConstants.POST.name())
|
||||
.path("/addUser")
|
||||
.path("/system/user/addUser")
|
||||
.sourceId(user.getId())
|
||||
.content(user.getName() + "(" + user.getEmail() + ")")
|
||||
.originalValue(JSON.toJSONBytes(user))
|
||||
|
@ -76,7 +76,7 @@ public class UserLogService {
|
|||
.type(OperationLogType.UPDATE.name())
|
||||
.module(OperationLogModule.SETTING_SYSTEM_USER_SINGLE)
|
||||
.method(HttpMethodConstants.POST.name())
|
||||
.path("/update")
|
||||
.path("/system/user/update")
|
||||
.sourceId(request.getId())
|
||||
.content(user.getName())
|
||||
.originalValue(JSON.toJSONBytes(user))
|
||||
|
@ -98,7 +98,7 @@ public class UserLogService {
|
|||
.type(OperationLogType.UPDATE.name())
|
||||
.module(OperationLogModule.SETTING_SYSTEM_USER_SINGLE)
|
||||
.method(HttpMethodConstants.POST.name())
|
||||
.path("/update/enable")
|
||||
.path("/system/user/update/enable")
|
||||
.sourceId(user.getId())
|
||||
.content((request.isEnable() ? Translator.get("user.enable") : Translator.get("user.disable")) + ":" + user.getName())
|
||||
.originalValue(JSON.toJSONBytes(user))
|
||||
|
@ -122,7 +122,7 @@ public class UserLogService {
|
|||
.type(OperationLogType.UPDATE.name())
|
||||
.module(OperationLogModule.SETTING_SYSTEM_USER_SINGLE)
|
||||
.method(HttpMethodConstants.POST.name())
|
||||
.path("/reset/password")
|
||||
.path("/system/user/reset/password")
|
||||
.sourceId(user.getId())
|
||||
.content(Translator.get("user.reset.password") + " : " + user.getName())
|
||||
.originalValue(JSON.toJSONBytes(user))
|
||||
|
@ -144,7 +144,7 @@ public class UserLogService {
|
|||
.type(OperationLogType.DELETE.name())
|
||||
.module(OperationLogModule.SETTING_SYSTEM_USER_SINGLE)
|
||||
.method(HttpMethodConstants.POST.name())
|
||||
.path("/delete")
|
||||
.path("/system/user/delete")
|
||||
.sourceId(user.getId())
|
||||
.content(Translator.get("user.delete") + " : " + user.getName())
|
||||
.originalValue(JSON.toJSONBytes(user))
|
||||
|
|
|
@ -15,11 +15,11 @@ public class TreeNodeParseUtils {
|
|||
Organization organization = entry.getKey();
|
||||
List<Project> projects = entry.getValue();
|
||||
|
||||
BaseTreeNode orgNode = new BaseTreeNode(organization.getId(), organization.getName(), Organization.class.getName(), true);
|
||||
BaseTreeNode orgNode = new BaseTreeNode(organization.getId(), organization.getName(), Organization.class.getName());
|
||||
returnList.add(orgNode);
|
||||
|
||||
for (Project project : projects) {
|
||||
BaseTreeNode projectNode = new BaseTreeNode(project.getId(), project.getName(), Project.class.getName(), true);
|
||||
BaseTreeNode projectNode = new BaseTreeNode(project.getId(), project.getName(), Project.class.getName());
|
||||
orgNode.addChild(projectNode);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -224,11 +224,12 @@ public abstract class BaseTest {
|
|||
File file = (File) o;
|
||||
multipartFile = new MockMultipartFile(key, file.getName(),
|
||||
MediaType.APPLICATION_OCTET_STREAM_VALUE, Files.readAllBytes(file.toPath()));
|
||||
} else if (o instanceof MockMultipartFile) {
|
||||
multipartFile = (MockMultipartFile) o;
|
||||
} else {
|
||||
multipartFile = new MockMultipartFile(key, null,
|
||||
MediaType.APPLICATION_JSON_VALUE, o.toString().getBytes());
|
||||
}
|
||||
|
||||
requestBuilder.file(multipartFile);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
|
|
|
@ -226,6 +226,7 @@ public class UserControllerTests extends BaseTest {
|
|||
Assertions.assertNotNull(returnPager);
|
||||
//返回值的页码和当前页码相同
|
||||
Assertions.assertEquals(returnPager.getCurrent(), basePageRequest.getCurrent());
|
||||
Assertions.assertEquals(returnPager.getPageSize(), basePageRequest.getPageSize());
|
||||
//返回的数据量不超过规定要返回的数据量相同
|
||||
Assertions.assertTrue(JSON.parseArray(JSON.toJSONString(returnPager.getList())).size() <= basePageRequest.getPageSize());
|
||||
List<UserTableResponse> userList = JSON.parseArray(JSON.toJSONString(returnPager.getList()), UserTableResponse.class);
|
||||
|
@ -244,6 +245,7 @@ public class UserControllerTests extends BaseTest {
|
|||
Assertions.assertNotNull(returnPager);
|
||||
//返回值的页码和当前页码相同
|
||||
Assertions.assertEquals(returnPager.getCurrent(), basePageRequest.getCurrent());
|
||||
Assertions.assertEquals(returnPager.getPageSize(), basePageRequest.getPageSize());
|
||||
//返回的数据量不超过规定要返回的数据量相同
|
||||
Assertions.assertTrue(JSON.parseArray(JSON.toJSONString(returnPager.getList())).size() <= basePageRequest.getPageSize());
|
||||
//用户组不存在非全局用户组
|
||||
|
@ -282,6 +284,7 @@ public class UserControllerTests extends BaseTest {
|
|||
Assertions.assertNotNull(returnPager);
|
||||
//返回值的页码和当前页码相同
|
||||
Assertions.assertEquals(returnPager.getTotal(), 0);
|
||||
Assertions.assertEquals(returnPager.getPageSize(), basePageRequest.getPageSize());
|
||||
//返回的数据量不超过规定要返回的数据量相同
|
||||
Assertions.assertEquals(0, JSON.parseArray(JSON.toJSONString(returnPager.getList())).size());
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue