first commit

This commit is contained in:
2026-03-06 14:01:32 +08:00
commit def60e21c7
1074 changed files with 119423 additions and 0 deletions

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>cn.orionsec.ops</groupId>
<artifactId>orion-ops-api</artifactId>
<version>1.3.1</version>
<relativePath>../pom.xml</relativePath>
</parent>
<name>orion-ops-data</name>
<artifactId>orion-ops-data</artifactId>
<modelVersion>4.0.0</modelVersion>
<dependencies>
<!-- orion-kit -->
<dependency>
<groupId>cn.orionsec.kit</groupId>
<artifactId>orion-all</artifactId>
</dependency>
<!-- service -->
<dependency>
<groupId>cn.orionsec.ops</groupId>
<artifactId>orion-ops-service</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,5 @@
package cn.orionsec.ops;
public class DataModuleConversionProvider {
}

View File

@@ -0,0 +1,43 @@
package cn.orionsec.ops.constant;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public enum DataClearRange {
/**
* 保留天数
*/
DAY(10),
/**
* 保留条数
*/
TOTAL(20),
/**
* 关联数据
*/
REL_ID(30),
;
private final Integer range;
public static DataClearRange of(Integer range) {
if (range == null) {
return null;
}
for (DataClearRange value : values()) {
if (value.range.equals(range)) {
return value;
}
}
return null;
}
}

View File

@@ -0,0 +1,70 @@
package cn.orionsec.ops.constant;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public enum DataClearType {
/**
* 批量执行命令记录
*/
BATCH_EXEC(10, "批量执行命令记录"),
/**
* 终端日志记录
*/
TERMINAL_LOG(20, "终端日志记录"),
/**
* 定时调度任务执行记录
*/
SCHEDULER_RECORD(30, "定时调度任务执行记录"),
/**
* 应用构建记录
*/
APP_BUILD(40, "应用构建记录"),
/**
* 应用发布记录
*/
APP_RELEASE(50, "应用发布记录"),
/**
* 应用流水线执行记录
*/
APP_PIPELINE_EXEC(60, "应用流水线执行记录"),
/**
* 用户操作日志
*/
USER_EVENT_LOG(70, "用户操作日志记录"),
/**
* 机器报警历史记录
*/
MACHINE_ALARM_HISTORY(80, "机器报警历史记录"),
;
private final Integer type;
private final String label;
public static DataClearType of(Integer type) {
if (type == null) {
return null;
}
for (DataClearType value : values()) {
if (value.type.equals(type)) {
return value;
}
}
return null;
}
}

View File

@@ -0,0 +1,45 @@
package cn.orionsec.ops.constant;
import cn.orionsec.kit.lang.utils.Strings;
import cn.orionsec.kit.lang.utils.time.Dates;
public class ExportConst {
private ExportConst() {
}
public static final String MACHINE_EXPORT_NAME = "机器信息导出-{}.xlsx";
public static final String MACHINE_PROXY_EXPORT_NAME = "机器代理导出-{}.xlsx";
public static final String MACHINE_ALARM_HISTORY_EXPORT_NAME = "机器报警记录导出-{}.xlsx";
public static final String TERMINAL_LOG_EXPORT_NAME = "终端日志导出-{}.xlsx";
public static final String TAIL_FILE_EXPORT_NAME = "日志文件导出-{}.xlsx";
public static final String APP_PROFILE_EXPORT_NAME = "应用环境导出-{}.xlsx";
public static final String APPLICATION_EXPORT_NAME = "应用信息导出-{}.xlsx";
public static final String APP_REPOSITORY_EXPORT_NAME = "应用版本仓库导出-{}.xlsx";
public static final String COMMAND_TEMPLATE_EXPORT_NAME = "命令模板导出-{}.xlsx";
public static final String USER_EVENT_LOG_EXPORT_NAME = "操作日志导出-{}.xlsx";
public static final String WEBHOOK_EXPORT_NAME = "webhook导出-{}.xlsx";
/**
* 格式导出文件名
*
* @param name name
* @return name
*/
public static String getFileName(String name) {
return Strings.format(name, Dates.current(Dates.YMD_HM2));
}
}

View File

@@ -0,0 +1,124 @@
package cn.orionsec.ops.constant;
import cn.orionsec.ops.entity.exporter.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.function.Supplier;
@Getter
@AllArgsConstructor
public enum ExportType {
/**
* 机器信息
*/
MACHINE_INFO(100,
"机器信息",
MachineInfoExportDTO.class,
() -> ExportConst.getFileName(ExportConst.MACHINE_EXPORT_NAME)),
/**
* 机器代理
*/
MACHINE_PROXY(110,
"机器代理",
MachineProxyExportDTO.class,
() -> ExportConst.getFileName(ExportConst.MACHINE_PROXY_EXPORT_NAME)),
/**
* 终端日志
*/
TERMINAL_LOG(120,
"终端日志",
MachineTerminalLogExportDTO.class,
() -> ExportConst.getFileName(ExportConst.TERMINAL_LOG_EXPORT_NAME)),
/**
* 机器报警记录
*/
MACHINE_ALARM_HISTORY(130,
"机器报警记录",
MachineAlarmHistoryExportDTO.class,
() -> ExportConst.getFileName(ExportConst.MACHINE_ALARM_HISTORY_EXPORT_NAME)),
/**
* 应用环境
*/
APP_PROFILE(200,
"应用环境",
ApplicationProfileExportDTO.class,
() -> ExportConst.getFileName(ExportConst.APP_PROFILE_EXPORT_NAME)),
/**
* 应用信息
*/
APPLICATION(210,
"应用信息",
ApplicationExportDTO.class,
() -> ExportConst.getFileName(ExportConst.APPLICATION_EXPORT_NAME)),
/**
* 应用仓库
*/
APP_REPOSITORY(220,
"应用仓库",
ApplicationRepositoryExportDTO.class,
() -> ExportConst.getFileName(ExportConst.APP_REPOSITORY_EXPORT_NAME)),
/**
* 命令模板
*/
COMMAND_TEMPLATE(300,
"命令模板",
CommandTemplateExportDTO.class
, () -> ExportConst.getFileName(ExportConst.COMMAND_TEMPLATE_EXPORT_NAME)),
/**
* 用户操作日志
*/
USER_EVENT_LOG(310,
"用户操作日志",
EventLogExportDTO.class,
() -> ExportConst.getFileName(ExportConst.USER_EVENT_LOG_EXPORT_NAME)),
/**
* 日志文件
*/
TAIL_FILE(320,
"日志文件",
MachineTailFileExportDTO.class,
() -> ExportConst.getFileName(ExportConst.TAIL_FILE_EXPORT_NAME)),
/**
* webhook
*/
WEBHOOK(330,
"webhook",
WebhookExportDTO.class,
() -> ExportConst.getFileName(ExportConst.WEBHOOK_EXPORT_NAME)),
;
private final Integer type;
private final String label;
private final Class<?> dataClass;
private final Supplier<String> nameSupplier;
public static ExportType of(Integer type) {
if (type == null) {
return null;
}
for (ExportType value : values()) {
if (value.type.equals(type)) {
return value;
}
}
return null;
}
}

View File

@@ -0,0 +1,150 @@
package cn.orionsec.ops.constant;
import cn.orionsec.ops.entity.domain.*;
import cn.orionsec.ops.entity.importer.*;
import cn.orionsec.ops.handler.importer.validator.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.io.Serializable;
@Getter
@AllArgsConstructor
public enum ImportType {
/**
* 机器信息
*/
MACHINE_INFO(100,
"机器信息",
"/templates/import/machine-import-template.xlsx",
"机器导入模板.xlsx",
MachineValidator.INSTANCE,
MachineInfoImportDTO.class,
MachineInfoDO.class),
/**
* 机器代理
*/
MACHINE_PROXY(110,
"机器代理",
"/templates/import/machine-proxy-import-template.xlsx",
"机器代理导入模板.xlsx",
MachineProxyValidator.INSTANCE,
MachineProxyImportDTO.class,
MachineProxyDO.class),
/**
* 日志文件
*/
TAIL_FILE(120,
"日志文件",
"/templates/import/tail-file-import-template.xlsx",
"日志文件导入模板.xlsx",
FileTailValidator.INSTANCE,
MachineTailFileImportDTO.class,
FileTailListDO.class),
/**
* 应用环境
*/
APP_PROFILE(200,
"应用环境",
"/templates/import/app-profile-import-template.xlsx",
"应用环境导入模板.xlsx",
ApplicationProfileValidator.INSTANCE,
ApplicationProfileImportDTO.class,
ApplicationProfileDO.class),
/**
* 应用信息
*/
APPLICATION(210,
"应用信息",
"/templates/import/application-import-template.xlsx",
"应用导入模板.xlsx",
ApplicationValidator.INSTANCE,
ApplicationImportDTO.class,
ApplicationInfoDO.class),
/**
* 应用仓库
*/
APP_REPOSITORY(220,
"版本仓库",
"/templates/import/app-repository-import-template.xlsx",
"应用仓库导入模板.xlsx",
ApplicationRepositoryValidator.INSTANCE,
ApplicationRepositoryImportDTO.class,
ApplicationRepositoryDO.class),
/**
* 命令模板
*/
COMMAND_TEMPLATE(300,
"命令模板",
"/templates/import/command-template-import-template.xlsx",
"命令模板导入模板.xlsx",
CommandTemplateValidator.INSTANCE,
CommandTemplateImportDTO.class,
CommandTemplateDO.class),
/**
* webhook
*/
WEBHOOK(310,
"webhook",
"/templates/import/webhook-import-template.xlsx",
"webhook导入模板.xlsx",
WebhookValidator.INSTANCE,
WebhookImportDTO.class,
WebhookConfigDO.class),
;
/**
* 类型
*/
private final Integer type;
/**
* 导入标签
*/
private final String label;
/**
* 文件路径
*/
private final String templatePath;
/**
* 下载名称
*/
private final String templateName;
/**
* 数据验证器
*/
private final DataValidator validator;
/**
* importClass
*/
private final Class<? extends BaseDataImportDTO> importClass;
private final Class<? extends Serializable> convertClass;
public static ImportType of(Integer type) {
if (type == null) {
return null;
}
for (ImportType value : values()) {
if (value.type.equals(type)) {
return value;
}
}
return null;
}
}

View File

@@ -0,0 +1,50 @@
package cn.orionsec.ops.entity.exporter;
import cn.orionsec.kit.lang.utils.convert.TypeStore;
import cn.orionsec.kit.office.excel.annotation.ExportField;
import cn.orionsec.kit.office.excel.annotation.ExportSheet;
import cn.orionsec.kit.office.excel.annotation.ExportTitle;
import cn.orionsec.ops.entity.domain.ApplicationInfoDO;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(value = "应用信息导出")
@ExportTitle(title = "应用信息导出")
@ExportSheet(name = "应用信息", height = 22, freezeHeader = true, filterHeader = true)
public class ApplicationExportDTO {
@ApiModelProperty(value = "应用名称")
@ExportField(index = 0, header = "应用名称", width = 35)
private String name;
@ApiModelProperty(value = "唯一标识")
@ExportField(index = 1, header = "唯一标识", width = 30)
private String tag;
@ApiModelProperty(value = "应用仓库名称")
@ExportField(index = 2, header = "应用仓库名称", width = 30)
private String repoName;
@ApiModelProperty(value = "描述")
@ExportField(index = 3, header = "描述", width = 35, wrapText = true)
private String description;
@ApiModelProperty(value = "仓库id", hidden = true)
private Long repoId;
static {
TypeStore.STORE.register(ApplicationInfoDO.class, ApplicationExportDTO.class, p -> {
ApplicationExportDTO dto = new ApplicationExportDTO();
dto.setName(p.getAppName());
dto.setTag(p.getAppTag());
dto.setRepoId(p.getRepoId());
dto.setDescription(p.getDescription());
return dto;
});
}
}

View File

@@ -0,0 +1,49 @@
package cn.orionsec.ops.entity.exporter;
import cn.orionsec.kit.lang.utils.convert.TypeStore;
import cn.orionsec.kit.office.excel.annotation.ExportField;
import cn.orionsec.kit.office.excel.annotation.ExportSheet;
import cn.orionsec.kit.office.excel.annotation.ExportTitle;
import cn.orionsec.kit.office.excel.type.ExcelAlignType;
import cn.orionsec.ops.constant.CnConst;
import cn.orionsec.ops.constant.Const;
import cn.orionsec.ops.entity.domain.ApplicationProfileDO;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(value = "应用环境信息导出")
@ExportTitle(title = "应用环境导出")
@ExportSheet(name = "应用环境", height = 22, freezeHeader = true, filterHeader = true)
public class ApplicationProfileExportDTO {
@ApiModelProperty(value = "环境名称")
@ExportField(index = 0, header = "环境名称", width = 30)
private String name;
@ApiModelProperty(value = "唯一标识")
@ExportField(index = 1, header = "唯一标识", width = 30)
private String tag;
@ApiModelProperty(value = "发布审核")
@ExportField(index = 2, header = "发布审核", width = 17, align = ExcelAlignType.CENTER, selectOptions = {CnConst.OPEN, CnConst.CLOSE})
private String releaseAudit;
@ApiModelProperty(value = "描述")
@ExportField(index = 3, header = "描述", width = 35, wrapText = true)
private String description;
static {
TypeStore.STORE.register(ApplicationProfileDO.class, ApplicationProfileExportDTO.class, p -> {
ApplicationProfileExportDTO dto = new ApplicationProfileExportDTO();
dto.setName(p.getProfileName());
dto.setTag(p.getProfileTag());
dto.setReleaseAudit(Const.ENABLE.equals(p.getReleaseAudit()) ? CnConst.OPEN : CnConst.CLOSE);
dto.setDescription(p.getDescription());
return dto;
});
}
}

View File

@@ -0,0 +1,93 @@
package cn.orionsec.ops.entity.exporter;
import cn.orionsec.kit.lang.utils.convert.TypeStore;
import cn.orionsec.kit.office.excel.annotation.ExportField;
import cn.orionsec.kit.office.excel.annotation.ExportSheet;
import cn.orionsec.kit.office.excel.annotation.ExportTitle;
import cn.orionsec.ops.constant.CnConst;
import cn.orionsec.ops.constant.Const;
import cn.orionsec.ops.constant.app.RepositoryAuthType;
import cn.orionsec.ops.constant.app.RepositoryTokenType;
import cn.orionsec.ops.entity.domain.ApplicationRepositoryDO;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Optional;
@Data
@ApiModel(value = "应用仓库导出")
@ExportTitle(title = "应用仓库导出")
@ExportSheet(name = "应用仓库", titleHeight = 22, headerHeight = 22, freezeHeader = true, filterHeader = true)
public class ApplicationRepositoryExportDTO {
@ApiModelProperty(value = "名称")
@ExportField(index = 0, header = "名称", width = 20)
private String name;
@ApiModelProperty(value = "url")
@ExportField(index = 1, header = "url", width = 40, wrapText = true)
private String url;
/**
* @see RepositoryAuthType
*/
@ApiModelProperty(value = "认证方式(密码/令牌)")
@ExportField(index = 2, header = "认证方式(密码/令牌)", width = 23, selectOptions = {CnConst.PASSWORD, CnConst.TOKEN})
private String authType;
/**
* @see RepositoryTokenType
*/
@ApiModelProperty(value = "令牌类型")
@ExportField(index = 3, header = "令牌类型", width = 13, selectOptions = {Const.GITHUB, Const.GITEE, Const.GITLAB})
private String tokenType;
@ApiModelProperty(value = "用户名")
@ExportField(index = 4, header = "用户名", width = 20)
private String username;
@ApiModelProperty(value = "导出密码/令牌 (密文)")
@ExportField(index = 5, header = "导出密码/令牌", width = 21, hidden = true, wrapText = true)
private String encryptAuthValue;
@ApiModelProperty(value = "导入密码/令牌 (明文)")
@ExportField(index = 6, header = "导入密码/令牌", width = 21, wrapText = true)
private String importAuthValue;
@ApiModelProperty(value = "描述")
@ExportField(index = 7, header = "描述", width = 25, wrapText = true)
private String description;
static {
TypeStore.STORE.register(ApplicationRepositoryDO.class, ApplicationRepositoryExportDTO.class, p -> {
ApplicationRepositoryExportDTO dto = new ApplicationRepositoryExportDTO();
dto.setName(p.getRepoName());
dto.setUrl(p.getRepoUrl());
// 认证方式
RepositoryAuthType authType = RepositoryAuthType.of(p.getRepoAuthType());
if (authType != null) {
dto.setAuthType(authType.getLabel());
}
// 令牌类型
if (RepositoryAuthType.TOKEN.equals(authType)) {
Optional.ofNullable(p.getRepoTokenType())
.map(RepositoryTokenType::of)
.map(RepositoryTokenType::getLabel)
.ifPresent(dto::setTokenType);
if (RepositoryTokenType.GITEE.getLabel().equals(dto.getTokenType())) {
dto.setUsername(p.getRepoUsername());
}
dto.setEncryptAuthValue(p.getRepoPrivateToken());
} else {
dto.setUsername(p.getRepoUsername());
dto.setEncryptAuthValue(p.getRepoPassword());
}
dto.setDescription(p.getRepoDescription());
return dto;
});
}
}

View File

@@ -0,0 +1,41 @@
package cn.orionsec.ops.entity.exporter;
import cn.orionsec.kit.lang.utils.convert.TypeStore;
import cn.orionsec.kit.office.excel.annotation.ExportField;
import cn.orionsec.kit.office.excel.annotation.ExportSheet;
import cn.orionsec.kit.office.excel.annotation.ExportTitle;
import cn.orionsec.ops.entity.domain.CommandTemplateDO;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(value = "命令模板导出")
@ExportTitle(title = "命令模板导出")
@ExportSheet(name = "命令模板", titleHeight = 22, headerHeight = 22, freezeHeader = true, filterHeader = true)
public class CommandTemplateExportDTO {
@ApiModelProperty(value = "模板名称")
@ExportField(index = 0, header = "模板名称", width = 25)
private String name;
@ApiModelProperty(value = "模板命令")
@ExportField(index = 1, header = "模板命令", width = 80, wrapText = true)
private String template;
@ApiModelProperty(value = "描述")
@ExportField(index = 2, header = "描述", width = 35, wrapText = true)
private String description;
static {
TypeStore.STORE.register(CommandTemplateDO.class, CommandTemplateExportDTO.class, p -> {
CommandTemplateExportDTO dto = new CommandTemplateExportDTO();
dto.setName(p.getTemplateName());
dto.setTemplate(p.getTemplateValue());
dto.setDescription(p.getDescription());
return dto;
});
}
}

View File

@@ -0,0 +1,76 @@
package cn.orionsec.ops.entity.exporter;
import cn.orionsec.kit.lang.utils.convert.TypeStore;
import cn.orionsec.kit.lang.utils.time.Dates;
import cn.orionsec.kit.office.excel.annotation.ExportField;
import cn.orionsec.kit.office.excel.annotation.ExportSheet;
import cn.orionsec.kit.office.excel.annotation.ExportTitle;
import cn.orionsec.kit.office.excel.type.ExcelFieldType;
import cn.orionsec.ops.constant.event.EventClassify;
import cn.orionsec.ops.constant.event.EventType;
import cn.orionsec.ops.entity.domain.UserEventLogDO;
import cn.orionsec.ops.utils.Utils;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
import java.util.Optional;
@Data
@ApiModel(value = "站内信导出")
@ExportTitle(title = "操作日志导出")
@ExportSheet(name = "操作日志", height = 22, freezeHeader = true, filterHeader = true)
public class EventLogExportDTO {
@ApiModelProperty(value = "用户名")
@ExportField(index = 0, header = "用户名", width = 15, wrapText = true)
private String username;
/**
* @see EventClassify
*/
@ApiModelProperty(value = "事件分类")
@ExportField(index = 1, header = "事件分类", width = 17)
private String classify;
/**
* @see EventType
*/
@ApiModelProperty(value = "事件类型")
@ExportField(index = 2, header = "事件类型", width = 22)
private String type;
@ApiModelProperty(value = "触发时间")
@ExportField(index = 3, header = "触发时间", width = 20, wrapText = true, type = ExcelFieldType.DATE, format = Dates.YMD_HMS)
private Date time;
@ApiModelProperty(value = "日志信息")
@ExportField(index = 4, header = "日志信息", width = 70, wrapText = true)
private String message;
@ApiModelProperty(value = "参数")
@ExportField(index = 5, header = "参数", width = 20, wrapText = true)
private String params;
static {
TypeStore.STORE.register(UserEventLogDO.class, EventLogExportDTO.class, p -> {
EventLogExportDTO dto = new EventLogExportDTO();
dto.setUsername(p.getUsername());
Optional.ofNullable(p.getEventClassify())
.map(EventClassify::of)
.map(EventClassify::getLabel)
.ifPresent(dto::setClassify);
Optional.ofNullable(p.getEventType())
.map(EventType::of)
.map(EventType::getLabel)
.ifPresent(dto::setType);
dto.setTime(p.getCreateTime());
dto.setMessage(Utils.cleanStainTag(p.getLogInfo()));
dto.setParams(p.getParamsJson());
return dto;
});
}
}

View File

@@ -0,0 +1,62 @@
package cn.orionsec.ops.entity.exporter;
import cn.orionsec.kit.lang.utils.convert.TypeStore;
import cn.orionsec.kit.lang.utils.time.Dates;
import cn.orionsec.kit.office.excel.annotation.ExportField;
import cn.orionsec.kit.office.excel.annotation.ExportFont;
import cn.orionsec.kit.office.excel.annotation.ExportSheet;
import cn.orionsec.kit.office.excel.annotation.ExportTitle;
import cn.orionsec.ops.constant.machine.MachineAlarmType;
import cn.orionsec.ops.entity.domain.MachineAlarmHistoryDO;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
@Data
@ApiModel(value = "机器报警记录导出")
@ExportTitle(title = "机器报警记录导出")
@ExportSheet(name = "机器报警记录", height = 22, freezeHeader = true, filterHeader = true)
public class MachineAlarmHistoryExportDTO {
@ApiModelProperty(value = "报警机器名称")
@ExportField(index = 0, header = "报警机器名称", width = 24, wrapText = true)
private String name;
@ApiModelProperty(value = "报警机器主机")
@ExportField(index = 1, header = "报警机器主机", width = 20, wrapText = true)
private String host;
/**
* @see MachineAlarmType
*/
@ApiModelProperty(value = "报警类型 10: cpu使用率 20: 内存使用率")
@ExportField(index = 2, header = "报警类型", width = 18, wrapText = true)
private String alarmType;
@ApiModelProperty(value = "报警值")
@ExportField(index = 3, header = "报警值", width = 15, wrapText = true)
@ExportFont(color = "#F5222D")
private Double alarmValue;
@ApiModelProperty(value = "报警时间")
@ExportField(index = 4, header = "报警时间", width = 25, format = Dates.YMD_HMS)
private Date alarmTime;
@ApiModelProperty(value = "机器id")
private Long machineId;
static {
TypeStore.STORE.register(MachineAlarmHistoryDO.class, MachineAlarmHistoryExportDTO.class, p -> {
MachineAlarmHistoryExportDTO dto = new MachineAlarmHistoryExportDTO();
dto.setMachineId(p.getMachineId());
dto.setAlarmType(MachineAlarmType.of(p.getAlarmType()).getLabel());
dto.setAlarmValue(p.getAlarmValue());
dto.setAlarmTime(p.getAlarmTime());
return dto;
});
}
}

View File

@@ -0,0 +1,88 @@
package cn.orionsec.ops.entity.exporter;
import cn.orionsec.kit.lang.utils.convert.TypeStore;
import cn.orionsec.kit.office.excel.annotation.ExportField;
import cn.orionsec.kit.office.excel.annotation.ExportSheet;
import cn.orionsec.kit.office.excel.annotation.ExportTitle;
import cn.orionsec.ops.constant.CnConst;
import cn.orionsec.ops.constant.machine.MachineAuthType;
import cn.orionsec.ops.entity.domain.MachineInfoDO;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(value = "机器信息导出")
@ExportTitle(title = "机器信息导出")
@ExportSheet(name = "机器信息", height = 22, freezeHeader = true, filterHeader = true)
public class MachineInfoExportDTO {
@ApiModelProperty(value = "id")
private Long id;
@ApiModelProperty(value = "机器名称")
@ExportField(index = 0, header = "机器名称", width = 20, wrapText = true)
private String name;
@ApiModelProperty(value = "唯一标识")
@ExportField(index = 1, header = "唯一标识", width = 20, wrapText = true)
private String tag;
@ApiModelProperty(value = "机器主机")
@ExportField(index = 2, header = "机器主机", width = 20, wrapText = true)
private String host;
@ApiModelProperty(value = "ssh 端口")
@ExportField(index = 3, header = "ssh 端口", width = 10)
private Integer port;
/**
* @see MachineAuthType
*/
@ApiModelProperty(value = "认证方式")
@ExportField(index = 4, header = "认证方式", width = 13, selectOptions = {CnConst.PASSWORD, CnConst.SECRET_KEY})
private String authType;
@ApiModelProperty(value = "用户名")
@ExportField(index = 5, header = "用户名", width = 20, wrapText = true)
private String username;
@ApiModelProperty(value = "导出密码")
@ExportField(index = 6, header = "导出密码", hidden = true, width = 16, wrapText = true)
private String encryptPassword;
@ApiModelProperty(value = "导入密码")
@ExportField(index = 7, header = "导入密码", width = 16, wrapText = true)
private String importPassword;
@ApiModelProperty(value = "密钥名称")
@ExportField(index = 8, header = "密钥名称", width = 16, wrapText = true)
private String keyName;
@ApiModelProperty(value = "描述")
@ExportField(index = 9, header = "描述", width = 25, wrapText = true)
private String description;
static {
TypeStore.STORE.register(MachineInfoDO.class, MachineInfoExportDTO.class, p -> {
MachineInfoExportDTO dto = new MachineInfoExportDTO();
dto.setId(p.getId());
dto.setName(p.getMachineName());
dto.setTag(p.getMachineTag());
dto.setHost(p.getMachineHost());
dto.setPort(p.getSshPort());
dto.setUsername(p.getUsername());
MachineAuthType authType = MachineAuthType.of(p.getAuthType());
if (authType != null) {
dto.setAuthType(authType.getLabel());
}
if (MachineAuthType.PASSWORD.equals(authType)) {
dto.setEncryptPassword(p.getPassword());
}
dto.setDescription(p.getDescription());
return dto;
});
}
}

View File

@@ -0,0 +1,70 @@
package cn.orionsec.ops.entity.exporter;
import cn.orionsec.kit.lang.utils.convert.TypeStore;
import cn.orionsec.kit.office.excel.annotation.ExportField;
import cn.orionsec.kit.office.excel.annotation.ExportSheet;
import cn.orionsec.kit.office.excel.annotation.ExportTitle;
import cn.orionsec.ops.constant.Const;
import cn.orionsec.ops.constant.machine.ProxyType;
import cn.orionsec.ops.entity.domain.MachineProxyDO;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Optional;
@Data
@ApiModel(value = "机器代理导出")
@ExportTitle(title = "机器代理导出")
@ExportSheet(name = "机器代理", height = 22, freezeHeader = true, filterHeader = true)
public class MachineProxyExportDTO {
@ApiModelProperty(value = "代理主机")
@ExportField(index = 0, header = "代理主机", width = 25)
private String host;
@ApiModelProperty(value = "代理端口")
@ExportField(index = 1, header = "代理端口", width = 10)
private Integer port;
/**
* @see ProxyType
*/
@ApiModelProperty(value = "代理类型")
@ExportField(index = 2, header = "代理类型", width = 13, selectOptions = {Const.PROTOCOL_HTTP, Const.SOCKS4, Const.SOCKS5})
private String proxyType;
@ApiModelProperty(value = "用户名")
@ExportField(index = 3, header = "用户名", width = 25)
private String username;
@ApiModelProperty(value = "导出密码")
@ExportField(index = 4, header = "导出密码", hidden = true, width = 16, wrapText = true)
private String encryptPassword;
@ApiModelProperty(value = "导入密码")
@ExportField(index = 5, header = "导入密码", width = 16, wrapText = true)
private String importPassword;
@ApiModelProperty(value = "描述")
@ExportField(index = 6, header = "描述", width = 35, wrapText = true)
private String description;
static {
TypeStore.STORE.register(MachineProxyDO.class, MachineProxyExportDTO.class, p -> {
MachineProxyExportDTO dto = new MachineProxyExportDTO();
dto.setHost(p.getProxyHost());
dto.setPort(p.getProxyPort());
Optional.ofNullable(p.getProxyType())
.map(ProxyType::of)
.map(ProxyType::getLabel)
.ifPresent(dto::setProxyType);
dto.setUsername(p.getProxyUsername());
dto.setEncryptPassword(p.getProxyPassword());
dto.setDescription(p.getDescription());
return dto;
});
}
}

View File

@@ -0,0 +1,63 @@
package cn.orionsec.ops.entity.exporter;
import cn.orionsec.kit.lang.utils.convert.TypeStore;
import cn.orionsec.kit.office.excel.annotation.ExportField;
import cn.orionsec.kit.office.excel.annotation.ExportSheet;
import cn.orionsec.kit.office.excel.annotation.ExportTitle;
import cn.orionsec.ops.entity.domain.FileTailListDO;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(value = "日志文件导出")
@ExportTitle(title = "日志文件导出")
@ExportSheet(name = "日志文件", titleHeight = 22, headerHeight = 22, freezeHeader = true, filterHeader = true)
public class MachineTailFileExportDTO {
@ApiModelProperty(value = "机器名称")
@ExportField(index = 0, header = "机器名称", width = 20, wrapText = true)
private String machineName;
@ApiModelProperty(value = "机器标识")
@ExportField(index = 1, header = "机器标识", width = 20, wrapText = true)
private String machineTag;
@ApiModelProperty(value = "文件别名")
@ExportField(index = 2, header = "文件别名", width = 20, wrapText = true)
private String name;
@ApiModelProperty(value = "文件路径")
@ExportField(index = 3, header = "文件路径", width = 50, wrapText = true)
private String path;
@ApiModelProperty(value = "文件编码")
@ExportField(index = 4, header = "文件编码", width = 12)
private String charset;
@ApiModelProperty(value = "尾部偏移行")
@ExportField(index = 5, header = "尾部偏移行", width = 12)
private Integer offset;
@ApiModelProperty(value = "执行命令")
@ExportField(index = 6, header = "执行命令", width = 35, wrapText = true)
private String command;
@ApiModelProperty(value = "机器id", hidden = true)
private Long machineId;
static {
TypeStore.STORE.register(FileTailListDO.class, MachineTailFileExportDTO.class, p -> {
MachineTailFileExportDTO dto = new MachineTailFileExportDTO();
dto.setMachineId(p.getMachineId());
dto.setName(p.getAliasName());
dto.setPath(p.getFilePath());
dto.setCharset(p.getFileCharset());
dto.setOffset(p.getFileOffset());
dto.setCommand(p.getTailCommand());
return dto;
});
}
}

View File

@@ -0,0 +1,75 @@
package cn.orionsec.ops.entity.exporter;
import cn.orionsec.kit.lang.utils.convert.TypeStore;
import cn.orionsec.kit.lang.utils.time.Dates;
import cn.orionsec.kit.office.excel.annotation.ExportField;
import cn.orionsec.kit.office.excel.annotation.ExportSheet;
import cn.orionsec.kit.office.excel.annotation.ExportTitle;
import cn.orionsec.kit.office.excel.type.ExcelFieldType;
import cn.orionsec.ops.entity.domain.MachineTerminalLogDO;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
@Data
@ApiModel(value = "终端日志导出")
@ExportTitle(title = "终端日志导出")
@ExportSheet(name = "终端日志", height = 22, freezeHeader = true, filterHeader = true)
public class MachineTerminalLogExportDTO {
@ApiModelProperty(value = "用户名")
@ExportField(index = 0, header = "用户名", width = 17, wrapText = true)
private String username;
@ApiModelProperty(value = "机器名称")
@ExportField(index = 1, header = "机器名称", width = 20, wrapText = true)
private String machineName;
@ApiModelProperty(value = "机器标识")
@ExportField(index = 2, header = "机器标识", width = 20, wrapText = true)
private String machineTag;
@ApiModelProperty(value = "机器主机")
@ExportField(index = 3, header = "机器主机", width = 20, wrapText = true)
private String machineHost;
@ApiModelProperty(value = "accessToken")
@ExportField(index = 4, header = "accessToken", width = 5, hidden = true, wrapText = true)
private String accessToken;
@ApiModelProperty(value = "建立连接时间")
@ExportField(index = 5, header = "建立连接时间", width = 20, wrapText = true, type = ExcelFieldType.DATE, format = Dates.YMD_HMS)
private Date connectedTime;
@ApiModelProperty(value = "断开连接时间")
@ExportField(index = 6, header = "断开连接时间", width = 20, wrapText = true, type = ExcelFieldType.DATE, format = Dates.YMD_HMS)
private Date disconnectedTime;
@ApiModelProperty(value = "close code")
@ExportField(index = 7, header = "close code", width = 11, wrapText = true)
private Integer closeCode;
@ApiModelProperty(value = "录屏文件路径")
@ExportField(index = 8, header = "录屏文件路径", width = 35, wrapText = true)
private String screenPath;
static {
TypeStore.STORE.register(MachineTerminalLogDO.class, MachineTerminalLogExportDTO.class, p -> {
MachineTerminalLogExportDTO dto = new MachineTerminalLogExportDTO();
dto.setUsername(p.getUsername());
dto.setMachineName(p.getMachineName());
dto.setMachineTag(p.getMachineTag());
dto.setMachineHost(p.getMachineHost());
dto.setAccessToken(p.getAccessToken());
dto.setConnectedTime(p.getConnectedTime());
dto.setDisconnectedTime(p.getDisconnectedTime());
dto.setCloseCode(p.getCloseCode());
dto.setScreenPath(p.getScreenPath());
return dto;
});
}
}

View File

@@ -0,0 +1,45 @@
package cn.orionsec.ops.entity.exporter;
import cn.orionsec.kit.lang.utils.convert.TypeStore;
import cn.orionsec.kit.office.excel.annotation.ExportField;
import cn.orionsec.kit.office.excel.annotation.ExportSheet;
import cn.orionsec.kit.office.excel.annotation.ExportTitle;
import cn.orionsec.ops.constant.webhook.WebhookType;
import cn.orionsec.ops.entity.domain.WebhookConfigDO;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(value = "webhook导出")
@ExportTitle(title = "webhook导出")
@ExportSheet(name = "webhook", height = 22, freezeHeader = true, filterHeader = true)
public class WebhookExportDTO {
@ApiModelProperty(value = "名称")
@ExportField(index = 0, header = "名称", width = 20, wrapText = true)
private String name;
/**
* @see WebhookType
*/
@ApiModelProperty(value = "类型")
@ExportField(index = 1, header = "类型", width = 20, wrapText = true)
private String type;
@ApiModelProperty(value = "url")
@ExportField(index = 2, header = "url", width = 80, wrapText = true)
private String url;
static {
TypeStore.STORE.register(WebhookConfigDO.class, WebhookExportDTO.class, p -> {
WebhookExportDTO dto = new WebhookExportDTO();
dto.setName(p.getWebhookName());
dto.setType(WebhookType.of(p.getWebhookType()).getLabel());
dto.setUrl(p.getWebhookUrl());
return dto;
});
}
}

View File

@@ -0,0 +1,56 @@
package cn.orionsec.ops.entity.importer;
import cn.orionsec.kit.lang.utils.convert.TypeStore;
import cn.orionsec.kit.office.excel.annotation.ImportField;
import cn.orionsec.ops.entity.domain.ApplicationInfoDO;
import cn.orionsec.ops.entity.vo.data.DataImportCheckRowVO;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = true)
@ApiModel(value = "应用信息导入")
public class ApplicationImportDTO extends BaseDataImportDTO {
@ApiModelProperty(value = "应用名称")
@ImportField(index = 0)
private String name;
@ApiModelProperty(value = "唯一标识")
@ImportField(index = 1)
private String tag;
@ApiModelProperty(value = "应用仓库名称")
@ImportField(index = 2)
private String repositoryName;
@ApiModelProperty(value = "描述")
@ImportField(index = 3)
private String description;
@ApiModelProperty(value = "仓库id", hidden = true)
private Long repositoryId;
static {
TypeStore.STORE.register(ApplicationImportDTO.class, DataImportCheckRowVO.class, p -> {
DataImportCheckRowVO vo = new DataImportCheckRowVO();
vo.setSymbol(p.tag);
vo.setIllegalMessage(p.getIllegalMessage());
vo.setId(p.getId());
return vo;
});
TypeStore.STORE.register(ApplicationImportDTO.class, ApplicationInfoDO.class, p -> {
ApplicationInfoDO d = new ApplicationInfoDO();
d.setId(p.getId());
d.setAppName(p.name);
d.setAppTag(p.tag);
d.setRepoId(p.repositoryId);
d.setDescription(p.description);
return d;
});
}
}

View File

@@ -0,0 +1,55 @@
package cn.orionsec.ops.entity.importer;
import cn.orionsec.kit.lang.utils.convert.TypeStore;
import cn.orionsec.kit.office.excel.annotation.ImportField;
import cn.orionsec.ops.constant.CnConst;
import cn.orionsec.ops.constant.Const;
import cn.orionsec.ops.entity.domain.ApplicationProfileDO;
import cn.orionsec.ops.entity.vo.data.DataImportCheckRowVO;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = true)
@ApiModel(value = "应用环境信息导入")
public class ApplicationProfileImportDTO extends BaseDataImportDTO {
@ApiModelProperty(value = "环境名称")
@ImportField(index = 0)
private String name;
@ApiModelProperty(value = "唯一标识")
@ImportField(index = 1)
private String tag;
@ApiModelProperty(value = "发布审核")
@ImportField(index = 2)
private String releaseAudit;
@ApiModelProperty(value = "描述")
@ImportField(index = 3)
private String description;
static {
TypeStore.STORE.register(ApplicationProfileImportDTO.class, DataImportCheckRowVO.class, p -> {
DataImportCheckRowVO vo = new DataImportCheckRowVO();
vo.setSymbol(p.tag);
vo.setIllegalMessage(p.getIllegalMessage());
vo.setId(p.getId());
return vo;
});
TypeStore.STORE.register(ApplicationProfileImportDTO.class, ApplicationProfileDO.class, p -> {
ApplicationProfileDO d = new ApplicationProfileDO();
d.setId(p.getId());
d.setProfileName(p.name);
d.setProfileTag(p.tag);
d.setReleaseAudit(CnConst.OPEN.equals(p.releaseAudit) ? Const.ENABLE : Const.DISABLE);
d.setDescription(p.description);
return d;
});
}
}

View File

@@ -0,0 +1,109 @@
package cn.orionsec.ops.entity.importer;
import cn.orionsec.kit.lang.utils.Strings;
import cn.orionsec.kit.lang.utils.convert.TypeStore;
import cn.orionsec.kit.office.excel.annotation.ImportField;
import cn.orionsec.ops.constant.app.RepositoryAuthType;
import cn.orionsec.ops.constant.app.RepositoryTokenType;
import cn.orionsec.ops.constant.app.RepositoryType;
import cn.orionsec.ops.entity.domain.ApplicationRepositoryDO;
import cn.orionsec.ops.entity.vo.data.DataImportCheckRowVO;
import cn.orionsec.ops.utils.ValueMix;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Optional;
import java.util.function.BiConsumer;
@Data
@EqualsAndHashCode(callSuper = true)
@ApiModel(value = "应用仓库导入")
public class ApplicationRepositoryImportDTO extends BaseDataImportDTO {
@ApiModelProperty(value = "名称")
@ImportField(index = 0)
private String name;
@ApiModelProperty(value = "url")
@ImportField(index = 1)
private String url;
/**
* @see RepositoryAuthType
*/
@ApiModelProperty(value = "认证方式")
@ImportField(index = 2)
private String authType;
/**
* @see RepositoryTokenType
*/
@ApiModelProperty(value = "令牌类型")
@ImportField(index = 3)
private String tokenType;
@ApiModelProperty(value = "用户名")
@ImportField(index = 4)
private String username;
@ApiModelProperty(value = "导出密码/令牌 (密文)")
@ImportField(index = 5)
private String encryptAuthValue;
@ApiModelProperty(value = "导入密码/令牌 (明文)")
@ImportField(index = 6)
private String importAuthValue;
@ApiModelProperty(value = "描述")
@ImportField(index = 7)
private String description;
@ApiModelProperty(value = "密码/令牌密文解密后的明文")
private String decryptAuthValue;
static {
TypeStore.STORE.register(ApplicationRepositoryImportDTO.class, DataImportCheckRowVO.class, p -> {
DataImportCheckRowVO vo = new DataImportCheckRowVO();
vo.setSymbol(p.name);
vo.setIllegalMessage(p.getIllegalMessage());
vo.setId(p.getId());
return vo;
});
TypeStore.STORE.register(ApplicationRepositoryImportDTO.class, ApplicationRepositoryDO.class, p -> {
ApplicationRepositoryDO d = new ApplicationRepositoryDO();
d.setId(p.getId());
d.setRepoName(p.name);
d.setRepoDescription(p.description);
d.setRepoType(RepositoryType.GIT.getType());
d.setRepoUrl(p.url);
Optional.ofNullable(p.authType)
.map(RepositoryAuthType::of)
.map(RepositoryAuthType::getType)
.ifPresent(d::setRepoAuthType);
if (RepositoryAuthType.PASSWORD.getType().equals(d.getRepoAuthType()) || RepositoryTokenType.GITEE.getLabel().equals(p.tokenType)) {
d.setRepoUsername(p.username);
}
Optional.ofNullable(p.tokenType)
.map(RepositoryTokenType::of)
.map(RepositoryTokenType::getType)
.ifPresent(d::setRepoTokenType);
BiConsumer<ApplicationRepositoryDO, String> authValueSetter;
if (RepositoryAuthType.PASSWORD.getType().equals(d.getRepoAuthType())) {
authValueSetter = ApplicationRepositoryDO::setRepoPassword;
} else {
authValueSetter = ApplicationRepositoryDO::setRepoPrivateToken;
}
if (!Strings.isBlank(p.decryptAuthValue)) {
authValueSetter.accept(d, ValueMix.encrypt(p.decryptAuthValue));
}
if (!Strings.isBlank(p.importAuthValue)) {
authValueSetter.accept(d, ValueMix.encrypt(p.importAuthValue));
}
return d;
});
}
}

View File

@@ -0,0 +1,19 @@
package cn.orionsec.ops.entity.importer;
import lombok.Data;
@Data
public class BaseDataImportDTO {
/**
* 非法信息 非法操作
*/
private String illegalMessage;
/**
* 数据id 更新操作
*/
private Long id;
}

View File

@@ -0,0 +1,49 @@
package cn.orionsec.ops.entity.importer;
import cn.orionsec.kit.lang.utils.convert.TypeStore;
import cn.orionsec.kit.office.excel.annotation.ImportField;
import cn.orionsec.ops.entity.domain.CommandTemplateDO;
import cn.orionsec.ops.entity.vo.data.DataImportCheckRowVO;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = true)
@ApiModel(value = "命令模板导入")
public class CommandTemplateImportDTO extends BaseDataImportDTO {
@ApiModelProperty(value = "模板名称")
@ImportField(index = 0)
private String name;
@ApiModelProperty(value = "模板命令")
@ImportField(index = 1)
private String template;
@ApiModelProperty(value = "描述")
@ImportField(index = 2)
private String description;
static {
TypeStore.STORE.register(CommandTemplateImportDTO.class, DataImportCheckRowVO.class, p -> {
DataImportCheckRowVO vo = new DataImportCheckRowVO();
vo.setSymbol(p.name);
vo.setIllegalMessage(p.getIllegalMessage());
vo.setId(p.getId());
return vo;
});
TypeStore.STORE.register(CommandTemplateImportDTO.class, CommandTemplateDO.class, p -> {
CommandTemplateDO d = new CommandTemplateDO();
d.setId(p.getId());
d.setTemplateName(p.name);
d.setTemplateValue(p.template);
d.setDescription(p.description);
return d;
});
}
}

View File

@@ -0,0 +1,50 @@
package cn.orionsec.ops.entity.importer;
import cn.orionsec.ops.constant.ImportType;
import cn.orionsec.ops.entity.vo.data.DataImportCheckVO;
import lombok.Data;
import java.util.Date;
@Data
public class DataImportDTO {
/**
* token
*/
private String importToken;
/**
* 类型
*
* @see ImportType
*/
private Integer type;
/**
* 导入数据 json
*/
private String data;
/**
* 检查数据
*/
private DataImportCheckVO check;
/**
* 导入用户id 手动
*/
private Long userId;
/**
* 导入用户名称 手动
*/
private String userName;
/**
* 导入时间 手动
*/
private Date importTime;
}

View File

@@ -0,0 +1,106 @@
package cn.orionsec.ops.entity.importer;
import cn.orionsec.kit.lang.utils.Strings;
import cn.orionsec.kit.lang.utils.convert.TypeStore;
import cn.orionsec.kit.office.excel.annotation.ImportField;
import cn.orionsec.ops.constant.machine.MachineAuthType;
import cn.orionsec.ops.entity.domain.MachineInfoDO;
import cn.orionsec.ops.entity.vo.data.DataImportCheckRowVO;
import cn.orionsec.ops.utils.ValueMix;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Optional;
@Data
@EqualsAndHashCode(callSuper = true)
@ApiModel(value = "机器信息导入")
public class MachineInfoImportDTO extends BaseDataImportDTO {
@ApiModelProperty(value = "机器名称")
@ImportField(index = 0)
private String name;
@ApiModelProperty(value = "唯一标识")
@ImportField(index = 1)
private String tag;
@ApiModelProperty(value = "机器主机")
@ImportField(index = 2)
private String host;
@ApiModelProperty(value = "ssh 端口")
@ImportField(index = 3)
private Integer port;
/**
* @see MachineAuthType
*/
@ApiModelProperty(value = "认证方式")
@ImportField(index = 4)
private String authType;
@ApiModelProperty(value = "用户名")
@ImportField(index = 5)
private String username;
@ApiModelProperty(value = "密码 (密文)")
@ImportField(index = 6)
private String encryptPassword;
@ApiModelProperty(value = "导入密码 (明文)")
@ImportField(index = 7)
private String importPassword;
@ApiModelProperty(value = "密钥名称")
@ImportField(index = 8)
private String keyName;
@ApiModelProperty(value = "描述")
@ImportField(index = 9)
private String description;
@ApiModelProperty(value = "密码密文解密后的明文", hidden = true)
private String decryptPassword;
@ApiModelProperty(value = "密钥id", hidden = true)
private Long keyId;
static {
TypeStore.STORE.register(MachineInfoImportDTO.class, DataImportCheckRowVO.class, p -> {
DataImportCheckRowVO vo = new DataImportCheckRowVO();
vo.setSymbol(p.tag);
vo.setIllegalMessage(p.getIllegalMessage());
vo.setId(p.getId());
return vo;
});
TypeStore.STORE.register(MachineInfoImportDTO.class, MachineInfoDO.class, p -> {
MachineInfoDO d = new MachineInfoDO();
d.setId(p.getId());
d.setMachineName(p.name);
d.setMachineTag(p.tag);
d.setMachineHost(p.host);
d.setSshPort(p.port);
d.setKeyId(p.keyId);
Optional.ofNullable(p.authType)
.map(MachineAuthType::of)
.map(MachineAuthType::getType)
.ifPresent(d::setAuthType);
d.setUsername(p.username);
if (MachineAuthType.PASSWORD.getType().equals(d.getAuthType())) {
if (!Strings.isBlank(p.decryptPassword)) {
d.setPassword(ValueMix.encrypt(p.decryptPassword));
}
if (!Strings.isBlank(p.importPassword)) {
d.setPassword(ValueMix.encrypt(p.importPassword));
}
}
d.setDescription(p.description);
return d;
});
}
}

View File

@@ -0,0 +1,86 @@
package cn.orionsec.ops.entity.importer;
import cn.orionsec.kit.lang.utils.Strings;
import cn.orionsec.kit.lang.utils.convert.TypeStore;
import cn.orionsec.kit.office.excel.annotation.ImportField;
import cn.orionsec.ops.constant.machine.ProxyType;
import cn.orionsec.ops.entity.domain.MachineProxyDO;
import cn.orionsec.ops.entity.vo.data.DataImportCheckRowVO;
import cn.orionsec.ops.utils.ValueMix;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Optional;
@Data
@EqualsAndHashCode(callSuper = true)
@ApiModel(value = "机器代理导入")
public class MachineProxyImportDTO extends BaseDataImportDTO {
@ApiModelProperty(value = "代理主机")
@ImportField(index = 0)
private String host;
@ApiModelProperty(value = "代理端口")
@ImportField(index = 1)
private Integer port;
/**
* @see ProxyType
*/
@ApiModelProperty(value = "代理类型")
@ImportField(index = 2)
private String proxyType;
@ApiModelProperty(value = "用户名")
@ImportField(index = 3)
private String username;
@ApiModelProperty(value = "导出密码 (密文)")
@ImportField(index = 4)
private String encryptPassword;
@ApiModelProperty(value = "导入密码 (明文)")
@ImportField(index = 5)
private String importPassword;
@ApiModelProperty(value = "描述")
@ImportField(index = 6)
private String description;
@ApiModelProperty(value = "密码密文解密后的明文", hidden = true)
private String decryptPassword;
static {
TypeStore.STORE.register(MachineProxyImportDTO.class, DataImportCheckRowVO.class, p -> {
DataImportCheckRowVO vo = new DataImportCheckRowVO();
vo.setSymbol(p.host);
vo.setIllegalMessage(p.getIllegalMessage());
vo.setId(p.getId());
return vo;
});
TypeStore.STORE.register(MachineProxyImportDTO.class, MachineProxyDO.class, p -> {
MachineProxyDO d = new MachineProxyDO();
d.setId(p.getId());
d.setProxyHost(p.host);
d.setProxyPort(p.port);
d.setProxyUsername(p.username);
if (!Strings.isBlank(p.decryptPassword)) {
d.setProxyPassword(ValueMix.encrypt(p.decryptPassword));
}
if (!Strings.isBlank(p.importPassword)) {
d.setProxyPassword(ValueMix.encrypt(p.importPassword));
}
Optional.ofNullable(p.proxyType)
.map(ProxyType::of)
.map(ProxyType::getType)
.ifPresent(d::setProxyType);
d.setDescription(p.description);
return d;
});
}
}

View File

@@ -0,0 +1,73 @@
package cn.orionsec.ops.entity.importer;
import cn.orionsec.kit.lang.utils.convert.TypeStore;
import cn.orionsec.kit.office.excel.annotation.ImportField;
import cn.orionsec.ops.constant.Const;
import cn.orionsec.ops.constant.tail.FileTailMode;
import cn.orionsec.ops.entity.domain.FileTailListDO;
import cn.orionsec.ops.entity.vo.data.DataImportCheckRowVO;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = true)
@ApiModel(value = "机器代理导入")
public class MachineTailFileImportDTO extends BaseDataImportDTO {
@ApiModelProperty(value = "机器标识")
@ImportField(index = 1)
private String machineTag;
@ApiModelProperty(value = "别名")
@ImportField(index = 2)
private String name;
@ApiModelProperty(value = "文件路径")
@ImportField(index = 3)
private String path;
@ApiModelProperty(value = "文件编码")
@ImportField(index = 4)
private String charset;
@ApiModelProperty(value = "尾部偏移行")
@ImportField(index = 5)
private Integer offset;
@ApiModelProperty(value = "执行命令")
@ImportField(index = 6)
private String command;
@ApiModelProperty(value = "机器id", hidden = true)
private Long machineId;
static {
TypeStore.STORE.register(MachineTailFileImportDTO.class, DataImportCheckRowVO.class, p -> {
DataImportCheckRowVO vo = new DataImportCheckRowVO();
vo.setSymbol(p.name);
vo.setIllegalMessage(p.getIllegalMessage());
vo.setId(p.getId());
return vo;
});
TypeStore.STORE.register(MachineTailFileImportDTO.class, FileTailListDO.class, p -> {
FileTailListDO d = new FileTailListDO();
d.setId(p.getId());
d.setMachineId(p.machineId);
d.setAliasName(p.name);
d.setFilePath(p.path);
d.setFileCharset(p.charset);
d.setFileOffset(p.offset);
d.setTailCommand(p.command);
if (Const.HOST_MACHINE_ID.equals(p.machineId)) {
d.setTailMode(FileTailMode.TRACKER.getMode());
} else {
d.setTailMode(FileTailMode.TAIL.getMode());
}
return d;
});
}
}

View File

@@ -0,0 +1,57 @@
package cn.orionsec.ops.entity.importer;
import cn.orionsec.kit.lang.utils.convert.TypeStore;
import cn.orionsec.kit.office.excel.annotation.ImportField;
import cn.orionsec.ops.constant.webhook.WebhookType;
import cn.orionsec.ops.entity.domain.WebhookConfigDO;
import cn.orionsec.ops.entity.vo.data.DataImportCheckRowVO;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Optional;
@Data
@EqualsAndHashCode(callSuper = true)
@ApiModel(value = "webhook 导入")
public class WebhookImportDTO extends BaseDataImportDTO {
@ApiModelProperty(value = "名称")
@ImportField(index = 0)
private String name;
/**
* @see WebhookType
*/
@ApiModelProperty(value = "类型")
@ImportField(index = 1)
private String type;
@ApiModelProperty(value = "url")
@ImportField(index = 2)
private String url;
static {
TypeStore.STORE.register(WebhookImportDTO.class, DataImportCheckRowVO.class, p -> {
DataImportCheckRowVO vo = new DataImportCheckRowVO();
vo.setSymbol(p.name);
vo.setIllegalMessage(p.getIllegalMessage());
vo.setId(p.getId());
return vo;
});
TypeStore.STORE.register(WebhookImportDTO.class, WebhookConfigDO.class, p -> {
WebhookConfigDO d = new WebhookConfigDO();
d.setId(p.getId());
d.setWebhookName(p.name);
d.setWebhookUrl(p.url);
Optional.ofNullable(p.type)
.map(WebhookType::of)
.map(WebhookType::getType)
.ifPresent(d::setWebhookType);
return d;
});
}
}

View File

@@ -0,0 +1,105 @@
package cn.orionsec.ops.handler.exporter;
import cn.orionsec.kit.lang.utils.Strings;
import cn.orionsec.kit.lang.utils.io.FileWriters;
import cn.orionsec.kit.lang.utils.io.Files1;
import cn.orionsec.kit.office.excel.writer.exporting.ExcelExport;
import cn.orionsec.kit.web.servlet.web.Servlets;
import cn.orionsec.ops.constant.ExportType;
import cn.orionsec.ops.constant.event.EventKeys;
import cn.orionsec.ops.constant.system.SystemEnvAttr;
import cn.orionsec.ops.entity.request.data.DataExportRequest;
import cn.orionsec.ops.utils.Currents;
import cn.orionsec.ops.utils.EventParamsHolder;
import cn.orionsec.ops.utils.PathBuilders;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.List;
public abstract class AbstractDataExporter<T> implements IDataExporter {
/**
* 导出类型
*/
protected final ExportType exportType;
/**
* 请求参数
*/
protected final DataExportRequest request;
/**
* http response
*/
protected final HttpServletResponse response;
protected ExcelExport<T> exporter;
public AbstractDataExporter(ExportType exportType, DataExportRequest request, HttpServletResponse response) {
this.exportType = exportType;
this.request = request;
this.response = response;
}
@Override
@SuppressWarnings("unchecked")
public void doExport() throws IOException {
// 查询数据
List<T> exportList = this.queryData();
// 初始化导出器
this.exporter = new ExcelExport<T>((Class<T>) exportType.getDataClass()).init();
exporter.addRows(exportList);
// 写入到 workbook
this.writeWorkbook();
// 设置日志参数
this.setEventParams();
}
/**
* 查询数据
*
* @return rows
*/
protected abstract List<T> queryData();
/**
* 写入 workbook
*
* @throws IOException IOException
*/
protected void writeWorkbook() throws IOException {
// 设置 http 响应头
Servlets.setAttachmentHeader(response, exportType.getNameSupplier().get());
// 写入 workbook 到 byte
ByteArrayOutputStream store = new ByteArrayOutputStream();
String password = request.getProtectPassword();
if (!Strings.isBlank(password)) {
exporter.write(store, password);
} else {
exporter.write(store);
}
// 设置 http 返回
byte[] excelData = store.toByteArray();
response.getOutputStream().write(excelData);
// 保存至本地
String exportPath = PathBuilders.getExportDataJsonPath(Currents.getUserId(), exportType.getType(), Strings.def(password));
String path = Files1.getPath(SystemEnvAttr.LOG_PATH.getValue(), exportPath);
FileWriters.write(path, excelData);
}
/**
* 设置日志参数
*/
protected void setEventParams() {
// 设置日志参数
EventParamsHolder.addParam(EventKeys.EXPORT_PASSWORD, request.getExportPassword());
EventParamsHolder.addParam(EventKeys.PROTECT, request.getProtectPassword() != null);
EventParamsHolder.addParam(EventKeys.COUNT, exporter.getRows());
EventParamsHolder.addParam(EventKeys.EXPORT_TYPE, exportType.getType());
EventParamsHolder.addParam(EventKeys.LABEL, exportType.getLabel());
}
}

View File

@@ -0,0 +1,30 @@
package cn.orionsec.ops.handler.exporter;
import cn.orionsec.kit.lang.utils.convert.Converts;
import cn.orionsec.kit.spring.SpringHolder;
import cn.orionsec.ops.constant.ExportType;
import cn.orionsec.ops.dao.ApplicationProfileDAO;
import cn.orionsec.ops.entity.domain.ApplicationProfileDO;
import cn.orionsec.ops.entity.exporter.ApplicationProfileExportDTO;
import cn.orionsec.ops.entity.request.data.DataExportRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
public class AppProfileDataExporter extends AbstractDataExporter<ApplicationProfileExportDTO> {
private static final ApplicationProfileDAO applicationProfileDAO = SpringHolder.getBean(ApplicationProfileDAO.class);
public AppProfileDataExporter(DataExportRequest request, HttpServletResponse response) {
super(ExportType.APP_PROFILE, request, response);
}
@Override
protected List<ApplicationProfileExportDTO> queryData() {
// 查询数据
List<ApplicationProfileDO> profileList = applicationProfileDAO.selectList(null);
return Converts.toList(profileList, ApplicationProfileExportDTO.class);
}
}

View File

@@ -0,0 +1,35 @@
package cn.orionsec.ops.handler.exporter;
import cn.orionsec.kit.lang.utils.convert.Converts;
import cn.orionsec.kit.spring.SpringHolder;
import cn.orionsec.ops.constant.Const;
import cn.orionsec.ops.constant.ExportType;
import cn.orionsec.ops.dao.ApplicationRepositoryDAO;
import cn.orionsec.ops.entity.domain.ApplicationRepositoryDO;
import cn.orionsec.ops.entity.exporter.ApplicationRepositoryExportDTO;
import cn.orionsec.ops.entity.request.data.DataExportRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
public class AppRepositoryDataExporter extends AbstractDataExporter<ApplicationRepositoryExportDTO> {
private static final ApplicationRepositoryDAO applicationRepositoryDAO = SpringHolder.getBean(ApplicationRepositoryDAO.class);
public AppRepositoryDataExporter(DataExportRequest request, HttpServletResponse response) {
super(ExportType.APP_REPOSITORY, request, response);
}
@Override
protected List<ApplicationRepositoryExportDTO> queryData() {
// 查询数据
List<ApplicationRepositoryDO> repoList = applicationRepositoryDAO.selectList(null);
List<ApplicationRepositoryExportDTO> exportList = Converts.toList(repoList, ApplicationRepositoryExportDTO.class);
if (!Const.ENABLE.equals(request.getExportPassword())) {
exportList.forEach(s -> s.setEncryptAuthValue(null));
}
return exportList;
}
}

View File

@@ -0,0 +1,56 @@
package cn.orionsec.ops.handler.exporter;
import cn.orionsec.kit.lang.utils.convert.Converts;
import cn.orionsec.kit.spring.SpringHolder;
import cn.orionsec.ops.constant.ExportType;
import cn.orionsec.ops.dao.ApplicationInfoDAO;
import cn.orionsec.ops.dao.ApplicationRepositoryDAO;
import cn.orionsec.ops.entity.domain.ApplicationInfoDO;
import cn.orionsec.ops.entity.domain.ApplicationRepositoryDO;
import cn.orionsec.ops.entity.exporter.ApplicationExportDTO;
import cn.orionsec.ops.entity.request.data.DataExportRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
public class ApplicationDataExporter extends AbstractDataExporter<ApplicationExportDTO> {
private static final ApplicationInfoDAO applicationInfoDAO = SpringHolder.getBean(ApplicationInfoDAO.class);
private static final ApplicationRepositoryDAO applicationRepositoryDAO = SpringHolder.getBean(ApplicationRepositoryDAO.class);
public ApplicationDataExporter(DataExportRequest request, HttpServletResponse response) {
super(ExportType.APPLICATION, request, response);
}
@Override
protected List<ApplicationExportDTO> queryData() {
// 查询数据
List<ApplicationInfoDO> appList = applicationInfoDAO.selectList(null);
List<ApplicationExportDTO> exportList = Converts.toList(appList, ApplicationExportDTO.class);
// 仓库名称
List<Long> repoIdList = appList.stream()
.map(ApplicationInfoDO::getRepoId)
.filter(Objects::nonNull)
.collect(Collectors.toList());
if (!repoIdList.isEmpty()) {
List<ApplicationRepositoryDO> repoNameList = applicationRepositoryDAO.selectNameByIdList(repoIdList);
// 设置仓库名称
for (ApplicationExportDTO export : exportList) {
Long repoId = export.getRepoId();
if (repoId == null) {
continue;
}
repoNameList.stream()
.filter(s -> s.getId().equals(repoId))
.findFirst()
.ifPresent(s -> export.setRepoName(s.getRepoName()));
}
}
return exportList;
}
}

View File

@@ -0,0 +1,30 @@
package cn.orionsec.ops.handler.exporter;
import cn.orionsec.kit.lang.utils.convert.Converts;
import cn.orionsec.kit.spring.SpringHolder;
import cn.orionsec.ops.constant.ExportType;
import cn.orionsec.ops.dao.CommandTemplateDAO;
import cn.orionsec.ops.entity.domain.CommandTemplateDO;
import cn.orionsec.ops.entity.exporter.CommandTemplateExportDTO;
import cn.orionsec.ops.entity.request.data.DataExportRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
public class CommandTemplateDataExporter extends AbstractDataExporter<CommandTemplateExportDTO> {
private static final CommandTemplateDAO commandTemplateDAO = SpringHolder.getBean(CommandTemplateDAO.class);
public CommandTemplateDataExporter(DataExportRequest request, HttpServletResponse response) {
super(ExportType.COMMAND_TEMPLATE, request, response);
}
@Override
protected List<CommandTemplateExportDTO> queryData() {
List<CommandTemplateDO> templateList = commandTemplateDAO.selectList(null);
return Converts.toList(templateList, CommandTemplateExportDTO.class);
}
}

View File

@@ -0,0 +1,59 @@
package cn.orionsec.ops.handler.exporter;
import cn.orionsec.kit.lang.utils.Exceptions;
import cn.orionsec.ops.constant.ExportType;
import cn.orionsec.ops.constant.MessageConst;
import cn.orionsec.ops.entity.request.data.DataExportRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public interface IDataExporter {
/**
* 执行导出
*
* @throws IOException IOException
*/
void doExport() throws IOException;
/**
* 创建数据导出器
*
* @param exportType 导出类型
* @param request request
* @param response response
* @return exporter
*/
static IDataExporter create(ExportType exportType, DataExportRequest request, HttpServletResponse response) {
switch (exportType) {
case MACHINE_INFO:
return new MachineInfoDataExporter(request, response);
case MACHINE_PROXY:
return new MachineProxyDataExporter(request, response);
case TERMINAL_LOG:
return new TerminalLogDataExporter(request, response);
case MACHINE_ALARM_HISTORY:
return new MachineAlarmHistoryDataExporter(request, response);
case APP_PROFILE:
return new AppProfileDataExporter(request, response);
case APPLICATION:
return new ApplicationDataExporter(request, response);
case APP_REPOSITORY:
return new AppRepositoryDataExporter(request, response);
case COMMAND_TEMPLATE:
return new CommandTemplateDataExporter(request, response);
case USER_EVENT_LOG:
return new UserEventLogDataExporter(request, response);
case TAIL_FILE:
return new TailFileDataExporter(request, response);
case WEBHOOK:
return new WebhookDataExporter(request, response);
default:
throw Exceptions.argument(MessageConst.UNKNOWN_EXPORT_TYPE);
}
}
}

View File

@@ -0,0 +1,67 @@
package cn.orionsec.ops.handler.exporter;
import cn.orionsec.kit.lang.utils.convert.Converts;
import cn.orionsec.kit.spring.SpringHolder;
import cn.orionsec.ops.constant.ExportType;
import cn.orionsec.ops.constant.event.EventKeys;
import cn.orionsec.ops.dao.MachineAlarmHistoryDAO;
import cn.orionsec.ops.dao.MachineInfoDAO;
import cn.orionsec.ops.entity.domain.MachineAlarmHistoryDO;
import cn.orionsec.ops.entity.domain.MachineInfoDO;
import cn.orionsec.ops.entity.exporter.MachineAlarmHistoryExportDTO;
import cn.orionsec.ops.entity.request.data.DataExportRequest;
import cn.orionsec.ops.utils.EventParamsHolder;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
public class MachineAlarmHistoryDataExporter extends AbstractDataExporter<MachineAlarmHistoryExportDTO> {
private static final MachineInfoDAO machineInfoDAO = SpringHolder.getBean(MachineInfoDAO.class);
private static final MachineAlarmHistoryDAO machineAlarmHistoryDAO = SpringHolder.getBean(MachineAlarmHistoryDAO.class);
public MachineAlarmHistoryDataExporter(DataExportRequest request, HttpServletResponse response) {
super(ExportType.MACHINE_ALARM_HISTORY, request, response);
}
@Override
protected List<MachineAlarmHistoryExportDTO> queryData() {
// 查询数据
Long machineId = request.getMachineId();
LambdaQueryWrapper<MachineAlarmHistoryDO> wrapper = new LambdaQueryWrapper<MachineAlarmHistoryDO>()
.eq(Objects.nonNull(machineId), MachineAlarmHistoryDO::getMachineId, machineId)
.orderByDesc(MachineAlarmHistoryDO::getCreateTime);
List<MachineAlarmHistoryDO> history = machineAlarmHistoryDAO.selectList(wrapper);
List<MachineAlarmHistoryExportDTO> historyList = Converts.toList(history, MachineAlarmHistoryExportDTO.class);
// 查询机器名称
List<Long> machineIdList = historyList.stream()
.map(MachineAlarmHistoryExportDTO::getMachineId)
.distinct()
.collect(Collectors.toList());
if (!machineIdList.isEmpty()) {
List<MachineInfoDO> machines = machineInfoDAO.selectNameByIdList(machineIdList);
for (MachineAlarmHistoryExportDTO record : historyList) {
machines.stream()
.filter(s -> s.getId().equals(record.getMachineId()))
.findFirst()
.ifPresent(m -> {
record.setName(m.getMachineName());
record.setHost(m.getMachineHost());
});
}
}
return historyList;
}
@Override
protected void setEventParams() {
super.setEventParams();
EventParamsHolder.addParam(EventKeys.MACHINE_ID, request.getMachineId());
}
}

View File

@@ -0,0 +1,59 @@
package cn.orionsec.ops.handler.exporter;
import cn.orionsec.kit.lang.utils.convert.Converts;
import cn.orionsec.kit.spring.SpringHolder;
import cn.orionsec.ops.constant.Const;
import cn.orionsec.ops.constant.ExportType;
import cn.orionsec.ops.dao.MachineInfoDAO;
import cn.orionsec.ops.dao.MachineSecretKeyDAO;
import cn.orionsec.ops.entity.domain.MachineInfoDO;
import cn.orionsec.ops.entity.domain.MachineSecretKeyDO;
import cn.orionsec.ops.entity.exporter.MachineInfoExportDTO;
import cn.orionsec.ops.entity.request.data.DataExportRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
public class MachineInfoDataExporter extends AbstractDataExporter<MachineInfoExportDTO> {
private static final MachineInfoDAO machineInfoDAO = SpringHolder.getBean(MachineInfoDAO.class);
private static final MachineSecretKeyDAO machineSecretKeyDAO = SpringHolder.getBean(MachineSecretKeyDAO.class);
public MachineInfoDataExporter(DataExportRequest request, HttpServletResponse response) {
super(ExportType.MACHINE_INFO, request, response);
}
@Override
protected List<MachineInfoExportDTO> queryData() {
// 查询机器信息
List<MachineInfoDO> machineList = machineInfoDAO.selectList(null);
List<MachineInfoExportDTO> exportList = Converts.toList(machineList, MachineInfoExportDTO.class);
// 查询密钥
List<Long> keyIdList = machineList.stream()
.map(MachineInfoDO::getKeyId)
.filter(Objects::nonNull)
.distinct()
.collect(Collectors.toList());
if (!keyIdList.isEmpty()) {
// 查询密钥
Map<Long, String> keyNameMap = machineSecretKeyDAO.selectBatchIds(keyIdList)
.stream()
.collect(Collectors.toMap(MachineSecretKeyDO::getId, MachineSecretKeyDO::getKeyName));
// 设置密钥名称
for (MachineInfoExportDTO machine : exportList) {
machine.setKeyName(keyNameMap.get(machine.getId()));
}
}
// 设置密码
if (!Const.ENABLE.equals(request.getExportPassword())) {
exportList.forEach(s -> s.setEncryptPassword(null));
}
return exportList;
}
}

View File

@@ -0,0 +1,35 @@
package cn.orionsec.ops.handler.exporter;
import cn.orionsec.kit.lang.utils.convert.Converts;
import cn.orionsec.kit.spring.SpringHolder;
import cn.orionsec.ops.constant.Const;
import cn.orionsec.ops.constant.ExportType;
import cn.orionsec.ops.dao.MachineProxyDAO;
import cn.orionsec.ops.entity.domain.MachineProxyDO;
import cn.orionsec.ops.entity.exporter.MachineProxyExportDTO;
import cn.orionsec.ops.entity.request.data.DataExportRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
public class MachineProxyDataExporter extends AbstractDataExporter<MachineProxyExportDTO> {
private static final MachineProxyDAO machineProxyDAO = SpringHolder.getBean(MachineProxyDAO.class);
public MachineProxyDataExporter(DataExportRequest request, HttpServletResponse response) {
super(ExportType.MACHINE_PROXY, request, response);
}
@Override
protected List<MachineProxyExportDTO> queryData() {
// 查询数据
List<MachineProxyDO> proxyList = machineProxyDAO.selectList(null);
List<MachineProxyExportDTO> exportList = Converts.toList(proxyList, MachineProxyExportDTO.class);
if (!Const.ENABLE.equals(request.getExportPassword())) {
exportList.forEach(s -> s.setEncryptPassword(null));
}
return exportList;
}
}

View File

@@ -0,0 +1,70 @@
package cn.orionsec.ops.handler.exporter;
import cn.orionsec.kit.lang.utils.convert.Converts;
import cn.orionsec.kit.spring.SpringHolder;
import cn.orionsec.ops.constant.ExportType;
import cn.orionsec.ops.constant.event.EventKeys;
import cn.orionsec.ops.dao.FileTailListDAO;
import cn.orionsec.ops.dao.MachineInfoDAO;
import cn.orionsec.ops.entity.domain.FileTailListDO;
import cn.orionsec.ops.entity.domain.MachineInfoDO;
import cn.orionsec.ops.entity.exporter.MachineTailFileExportDTO;
import cn.orionsec.ops.entity.request.data.DataExportRequest;
import cn.orionsec.ops.utils.EventParamsHolder;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
public class TailFileDataExporter extends AbstractDataExporter<MachineTailFileExportDTO> {
private static final MachineInfoDAO machineInfoDAO = SpringHolder.getBean(MachineInfoDAO.class);
private static final FileTailListDAO fileTailListDAO = SpringHolder.getBean(FileTailListDAO.class);
public TailFileDataExporter(DataExportRequest request, HttpServletResponse response) {
super(ExportType.TAIL_FILE, request, response);
}
@Override
protected List<MachineTailFileExportDTO> queryData() {
// 查询数据
Long queryMachineId = request.getMachineId();
LambdaQueryWrapper<FileTailListDO> wrapper = new LambdaQueryWrapper<FileTailListDO>()
.eq(Objects.nonNull(queryMachineId), FileTailListDO::getMachineId, queryMachineId);
List<FileTailListDO> fileList = fileTailListDAO.selectList(wrapper);
List<MachineTailFileExportDTO> exportList = Converts.toList(fileList, MachineTailFileExportDTO.class);
// 机器名称
List<Long> machineIdList = fileList.stream()
.map(FileTailListDO::getMachineId)
.collect(Collectors.toList());
if (!machineIdList.isEmpty()) {
List<MachineInfoDO> machineNameList = machineInfoDAO.selectNameByIdList(machineIdList);
// 设置机器名称
for (MachineTailFileExportDTO export : exportList) {
Long machineId = export.getMachineId();
if (machineId == null) {
continue;
}
machineNameList.stream()
.filter(s -> s.getId().equals(machineId))
.findFirst()
.ifPresent(s -> {
export.setMachineName(s.getMachineName());
export.setMachineTag(s.getMachineTag());
});
}
}
return exportList;
}
@Override
protected void setEventParams() {
super.setEventParams();
EventParamsHolder.addParam(EventKeys.MACHINE_ID, request.getMachineId());
}
}

View File

@@ -0,0 +1,44 @@
package cn.orionsec.ops.handler.exporter;
import cn.orionsec.kit.lang.utils.convert.Converts;
import cn.orionsec.kit.spring.SpringHolder;
import cn.orionsec.ops.constant.ExportType;
import cn.orionsec.ops.constant.event.EventKeys;
import cn.orionsec.ops.dao.MachineTerminalLogDAO;
import cn.orionsec.ops.entity.domain.MachineTerminalLogDO;
import cn.orionsec.ops.entity.exporter.MachineTerminalLogExportDTO;
import cn.orionsec.ops.entity.request.data.DataExportRequest;
import cn.orionsec.ops.utils.EventParamsHolder;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Objects;
public class TerminalLogDataExporter extends AbstractDataExporter<MachineTerminalLogExportDTO> {
private static final MachineTerminalLogDAO machineTerminalLogDAO = SpringHolder.getBean(MachineTerminalLogDAO.class);
public TerminalLogDataExporter(DataExportRequest request, HttpServletResponse response) {
super(ExportType.TERMINAL_LOG, request, response);
}
@Override
protected List<MachineTerminalLogExportDTO> queryData() {
// 查询数据
Long machineId = request.getMachineId();
LambdaQueryWrapper<MachineTerminalLogDO> wrapper = new LambdaQueryWrapper<MachineTerminalLogDO>()
.eq(Objects.nonNull(machineId), MachineTerminalLogDO::getMachineId, machineId)
.orderByDesc(MachineTerminalLogDO::getCreateTime);
List<MachineTerminalLogDO> terminalList = machineTerminalLogDAO.selectList(wrapper);
return Converts.toList(terminalList, MachineTerminalLogExportDTO.class);
}
@Override
protected void setEventParams() {
super.setEventParams();
EventParamsHolder.addParam(EventKeys.MACHINE_ID, request.getMachineId());
}
}

View File

@@ -0,0 +1,58 @@
package cn.orionsec.ops.handler.exporter;
import cn.orionsec.kit.lang.utils.convert.Converts;
import cn.orionsec.kit.spring.SpringHolder;
import cn.orionsec.ops.constant.Const;
import cn.orionsec.ops.constant.ExportType;
import cn.orionsec.ops.constant.event.EventKeys;
import cn.orionsec.ops.dao.UserEventLogDAO;
import cn.orionsec.ops.entity.domain.UserEventLogDO;
import cn.orionsec.ops.entity.exporter.EventLogExportDTO;
import cn.orionsec.ops.entity.request.data.DataExportRequest;
import cn.orionsec.ops.utils.Currents;
import cn.orionsec.ops.utils.EventParamsHolder;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Objects;
public class UserEventLogDataExporter extends AbstractDataExporter<EventLogExportDTO> {
private static final UserEventLogDAO userEventLogDAO = SpringHolder.getBean(UserEventLogDAO.class);
public UserEventLogDataExporter(DataExportRequest request, HttpServletResponse response) {
super(ExportType.USER_EVENT_LOG, request, response);
// 设置用户id
if (Currents.isAdministrator()) {
if (Const.ENABLE.equals(request.getOnlyMyself())) {
request.setUserId(Currents.getUserId());
}
} else {
request.setUserId(Currents.getUserId());
}
}
@Override
protected List<EventLogExportDTO> queryData() {
// 查询数据
Long userId = request.getUserId();
Integer classify = request.getClassify();
LambdaQueryWrapper<UserEventLogDO> wrapper = new LambdaQueryWrapper<UserEventLogDO>()
.eq(UserEventLogDO::getExecResult, Const.ENABLE)
.eq(Objects.nonNull(userId), UserEventLogDO::getUserId, userId)
.eq(Objects.nonNull(classify), UserEventLogDO::getEventClassify, classify)
.orderByDesc(UserEventLogDO::getCreateTime);
List<UserEventLogDO> logList = userEventLogDAO.selectList(wrapper);
return Converts.toList(logList, EventLogExportDTO.class);
}
@Override
protected void setEventParams() {
super.setEventParams();
EventParamsHolder.addParam(EventKeys.USER_ID, request.getUserId());
EventParamsHolder.addParam(EventKeys.CLASSIFY, request.getClassify());
}
}

View File

@@ -0,0 +1,43 @@
package cn.orionsec.ops.handler.exporter;
import cn.orionsec.kit.lang.utils.convert.Converts;
import cn.orionsec.kit.spring.SpringHolder;
import cn.orionsec.ops.constant.ExportType;
import cn.orionsec.ops.constant.event.EventKeys;
import cn.orionsec.ops.dao.WebhookConfigDAO;
import cn.orionsec.ops.entity.domain.WebhookConfigDO;
import cn.orionsec.ops.entity.exporter.WebhookExportDTO;
import cn.orionsec.ops.entity.request.data.DataExportRequest;
import cn.orionsec.ops.utils.EventParamsHolder;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Objects;
public class WebhookDataExporter extends AbstractDataExporter<WebhookExportDTO> {
private static final WebhookConfigDAO webhookConfigDAO = SpringHolder.getBean(WebhookConfigDAO.class);
public WebhookDataExporter(DataExportRequest request, HttpServletResponse response) {
super(ExportType.WEBHOOK, request, response);
}
@Override
protected List<WebhookExportDTO> queryData() {
// 查询数据
Integer type = request.getType();
LambdaQueryWrapper<WebhookConfigDO> wrapper = new LambdaQueryWrapper<WebhookConfigDO>()
.eq(Objects.nonNull(type), WebhookConfigDO::getWebhookType, type);
List<WebhookConfigDO> list = webhookConfigDAO.selectList(wrapper);
return Converts.toList(list, WebhookExportDTO.class);
}
@Override
protected void setEventParams() {
super.setEventParams();
EventParamsHolder.addParam(EventKeys.TYPE, request.getType());
}
}

View File

@@ -0,0 +1,261 @@
package cn.orionsec.ops.handler.importer.checker;
import cn.orionsec.kit.lang.id.UUIds;
import cn.orionsec.kit.lang.utils.Exceptions;
import cn.orionsec.kit.lang.utils.Strings;
import cn.orionsec.kit.lang.utils.collect.Lists;
import cn.orionsec.kit.lang.utils.collect.Maps;
import cn.orionsec.kit.lang.utils.convert.Converts;
import cn.orionsec.kit.office.excel.Excels;
import cn.orionsec.kit.office.excel.reader.ExcelBeanReader;
import cn.orionsec.kit.spring.SpringHolder;
import cn.orionsec.ops.constant.ImportType;
import cn.orionsec.ops.constant.KeyConst;
import cn.orionsec.ops.entity.importer.BaseDataImportDTO;
import cn.orionsec.ops.entity.importer.DataImportDTO;
import cn.orionsec.ops.entity.vo.data.DataImportCheckRowVO;
import cn.orionsec.ops.entity.vo.data.DataImportCheckVO;
import cn.orionsec.ops.utils.Currents;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.data.redis.core.RedisTemplate;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.stream.Collectors;
public abstract class AbstractDataChecker<T extends BaseDataImportDTO, DO> implements IDataChecker {
private static final RedisTemplate<String, String> redisTemplate = SpringHolder.getBean("redisTemplate");
/**
* 导入类型
*/
private final ImportType importType;
/**
* workbook
*/
private final Workbook workbook;
public AbstractDataChecker(ImportType importType, Workbook workbook) {
this.importType = importType;
this.workbook = workbook;
}
@Override
public DataImportCheckVO doCheck() {
// 解析数据
List<T> rows;
try {
rows = this.parserImportWorkbook();
} catch (Exception e) {
throw Exceptions.parse(e);
} finally {
Excels.close(workbook);
}
// 检查数据
return this.checkImportData(rows);
}
/**
* 检查数据
*
* @param rows rows
* @return check
*/
protected abstract DataImportCheckVO checkImportData(List<T> rows);
/**
* 解析导入数据
*
* @return rows
*/
@SuppressWarnings("unchecked")
protected List<T> parserImportWorkbook() {
ExcelBeanReader<T> reader = new ExcelBeanReader<T>(workbook, workbook.getSheetAt(0), (Class<T>) importType.getImportClass());
return reader.skip(2)
.read()
.getRows();
}
/**
* 验证对象合法性
*
* @param rows rows
*/
protected void validImportRows(List<T> rows) {
for (T row : rows) {
try {
importType.getValidator().validData(row);
} catch (Exception e) {
row.setIllegalMessage(e.getMessage());
}
}
}
/**
* 获取导入行已存在的数据
*
* @param rows rows
* @param rowKeyGetter rowKeyGetter
* @param mapper mapper
* @param domainKeyGetter domainKeyGetter
* @return present domain
*/
protected List<DO> getImportRowsPresentValues(List<T> rows,
Function<T, ?> rowKeyGetter,
BaseMapper<DO> mapper,
SFunction<DO, ?> domainKeyGetter) {
List<?> symbolList = rows.stream()
.filter(s -> Objects.isNull(s.getIllegalMessage()))
.map(rowKeyGetter)
.collect(Collectors.toList());
if (symbolList.isEmpty()) {
return Lists.empty();
} else {
LambdaQueryWrapper<DO> wrapper = new LambdaQueryWrapper<DO>()
.in(domainKeyGetter, symbolList);
return mapper.selectList(wrapper);
}
}
/**
* 检查导入行是否存在
*
* @param rows rows
* @param rowKeyGetter rowKeyGetter
* @param presentValues presentValues
* @param presentKeyGetter presentKeyGetter
* @param presentIdGetter presentIdGetter
*/
protected void checkImportRowsPresent(List<T> rows,
Function<T, ?> rowKeyGetter,
List<DO> presentValues,
Function<DO, ?> presentKeyGetter,
Function<DO, Long> presentIdGetter) {
for (T row : rows) {
presentValues.stream()
.filter(p -> presentKeyGetter.apply(p).equals(rowKeyGetter.apply(row)))
.findFirst()
.map(presentIdGetter)
.ifPresent(row::setId);
}
}
/**
* 设置检查行数据缓存
*
* @param rows rows
* @return checkData
*/
protected DataImportCheckVO setImportCheckRows(List<T> rows) {
// 设置检查对象
String dataJson = JSON.toJSONString(rows);
List<DataImportCheckRowVO> illegalRows = Lists.newList();
List<DataImportCheckRowVO> insertRows = Lists.newList();
List<DataImportCheckRowVO> updateRows = Lists.newList();
// 设置行
for (int i = 0; i < rows.size(); i++) {
// 设置检查数据
T row = rows.get(i);
DataImportCheckRowVO checkRow = Converts.to(row, DataImportCheckRowVO.class);
checkRow.setIndex(i);
checkRow.setRow(i + 3);
// 检查非法数据
if (checkRow.getIllegalMessage() != null) {
illegalRows.add(checkRow);
continue;
}
if (checkRow.getId() == null) {
// 不存在则新增
insertRows.add(checkRow);
} else {
// 存在则修改
updateRows.add(checkRow);
}
}
// 设置缓存并且返回
String token = UUIds.random32();
String cacheKey = Strings.format(KeyConst.DATA_IMPORT_TOKEN, Currents.getUserId(), token);
// 返回数据
DataImportCheckVO check = new DataImportCheckVO();
check.setImportToken(token);
check.setIllegalRows(illegalRows);
check.setInsertRows(insertRows);
check.setUpdateRows(updateRows);
// 设置缓存
DataImportDTO cache = new DataImportDTO();
cache.setImportToken(token);
cache.setType(importType.getType());
cache.setData(dataJson);
cache.setCheck(check);
redisTemplate.opsForValue().set(cacheKey, JSON.toJSONString(cache),
KeyConst.DATA_IMPORT_TOKEN_EXPIRE, TimeUnit.SECONDS);
return check;
}
/**
* 设置引用id
*
* @param rows rows
* @param keyGetter keyGetter
* @param query dataQuery
* @param domainKeyGetter domainKeyGetter
* @param domainIdGetter domainIdGetter
* @param relIdSetter relIdSetter
* @param notPresentTemplate notPresentTemplate
* @param <K> key type
* @param <P> domain type
*/
protected <K, P> void setCheckRowsRelId(List<T> rows,
Function<T, K> keyGetter,
Function<List<K>, List<P>> query,
Function<P, K> domainKeyGetter,
Function<P, Long> domainIdGetter,
BiConsumer<T, Long> relIdSetter,
String notPresentTemplate) {
// 获取合法数据
List<T> validImportList = rows.stream()
.filter(s -> Objects.isNull(s.getIllegalMessage()))
.filter(s -> {
K symbol = keyGetter.apply(s);
return symbol instanceof String ? Strings.isNotBlank((String) symbol) : Objects.nonNull(symbol);
}).collect(Collectors.toList());
if (validImportList.isEmpty()) {
return;
}
// 获取标识
List<K> symbolList = validImportList.stream()
.map(keyGetter)
.filter(Objects::nonNull)
.collect(Collectors.toList());
if (symbolList.isEmpty()) {
return;
}
// 查询id
Map<K, Long> symbolIdMap = Maps.newMap();
List<P> dataList = query.apply(symbolList);
dataList.forEach(s -> symbolIdMap.put(domainKeyGetter.apply(s), domainIdGetter.apply(s)));
// 设置id
for (T row : validImportList) {
K symbol = keyGetter.apply(row);
Long relId = symbolIdMap.get(symbol);
if (relId == null) {
row.setIllegalMessage(Strings.format(notPresentTemplate, symbol));
continue;
}
relIdSetter.accept(row, relId);
}
}
}

View File

@@ -0,0 +1,37 @@
package cn.orionsec.ops.handler.importer.checker;
import cn.orionsec.kit.spring.SpringHolder;
import cn.orionsec.ops.constant.ImportType;
import cn.orionsec.ops.dao.ApplicationProfileDAO;
import cn.orionsec.ops.entity.domain.ApplicationProfileDO;
import cn.orionsec.ops.entity.importer.ApplicationProfileImportDTO;
import cn.orionsec.ops.entity.vo.data.DataImportCheckVO;
import org.apache.poi.ss.usermodel.Workbook;
import java.util.List;
public class AppProfileDataChecker extends AbstractDataChecker<ApplicationProfileImportDTO, ApplicationProfileDO> {
private static final ApplicationProfileDAO applicationProfileDAO = SpringHolder.getBean(ApplicationProfileDAO.class);
public AppProfileDataChecker(Workbook workbook) {
super(ImportType.APP_PROFILE, workbook);
}
@Override
protected DataImportCheckVO checkImportData(List<ApplicationProfileImportDTO> rows) {
// 检查数据合法性
this.validImportRows(rows);
// 通过唯一标识查询环境
List<ApplicationProfileDO> presentProfiles = this.getImportRowsPresentValues(rows,
ApplicationProfileImportDTO::getTag,
applicationProfileDAO, ApplicationProfileDO::getProfileTag);
// 检查数据是否存在
this.checkImportRowsPresent(rows, ApplicationProfileImportDTO::getTag,
presentProfiles, ApplicationProfileDO::getProfileTag, ApplicationProfileDO::getId);
// 设置导入检查数据
return this.setImportCheckRows(rows);
}
}

View File

@@ -0,0 +1,37 @@
package cn.orionsec.ops.handler.importer.checker;
import cn.orionsec.kit.spring.SpringHolder;
import cn.orionsec.ops.constant.ImportType;
import cn.orionsec.ops.dao.ApplicationRepositoryDAO;
import cn.orionsec.ops.entity.domain.ApplicationRepositoryDO;
import cn.orionsec.ops.entity.importer.ApplicationRepositoryImportDTO;
import cn.orionsec.ops.entity.vo.data.DataImportCheckVO;
import org.apache.poi.ss.usermodel.Workbook;
import java.util.List;
public class AppRepositoryDataChecker extends AbstractDataChecker<ApplicationRepositoryImportDTO, ApplicationRepositoryDO> {
private static final ApplicationRepositoryDAO applicationRepositoryDAO = SpringHolder.getBean(ApplicationRepositoryDAO.class);
public AppRepositoryDataChecker(Workbook workbook) {
super(ImportType.APP_REPOSITORY, workbook);
}
@Override
protected DataImportCheckVO checkImportData(List<ApplicationRepositoryImportDTO> rows) {
// 检查数据合法性
this.validImportRows(rows);
// 通过唯一标识查询应用
List<ApplicationRepositoryDO> presentList = this.getImportRowsPresentValues(rows,
ApplicationRepositoryImportDTO::getName,
applicationRepositoryDAO, ApplicationRepositoryDO::getRepoName);
// 检查数据是否存在
this.checkImportRowsPresent(rows, ApplicationRepositoryImportDTO::getName,
presentList, ApplicationRepositoryDO::getRepoName, ApplicationRepositoryDO::getId);
// 设置导入检查数据
return this.setImportCheckRows(rows);
}
}

View File

@@ -0,0 +1,49 @@
package cn.orionsec.ops.handler.importer.checker;
import cn.orionsec.kit.spring.SpringHolder;
import cn.orionsec.ops.constant.ImportType;
import cn.orionsec.ops.constant.MessageConst;
import cn.orionsec.ops.dao.ApplicationInfoDAO;
import cn.orionsec.ops.dao.ApplicationRepositoryDAO;
import cn.orionsec.ops.entity.domain.ApplicationInfoDO;
import cn.orionsec.ops.entity.domain.ApplicationRepositoryDO;
import cn.orionsec.ops.entity.importer.ApplicationImportDTO;
import cn.orionsec.ops.entity.vo.data.DataImportCheckVO;
import org.apache.poi.ss.usermodel.Workbook;
import java.util.List;
public class ApplicationDataChecker extends AbstractDataChecker<ApplicationImportDTO, ApplicationInfoDO> {
private static final ApplicationInfoDAO applicationInfoDAO = SpringHolder.getBean(ApplicationInfoDAO.class);
private static final ApplicationRepositoryDAO applicationRepositoryDAO = SpringHolder.getBean(ApplicationRepositoryDAO.class);
public ApplicationDataChecker(Workbook workbook) {
super(ImportType.APPLICATION, workbook);
}
@Override
protected DataImportCheckVO checkImportData(List<ApplicationImportDTO> rows) {
// 检查数据合法性
this.validImportRows(rows);
// 设置机器id
this.setCheckRowsRelId(rows, ApplicationImportDTO::getRepositoryName,
applicationRepositoryDAO::selectIdByNameList,
ApplicationRepositoryDO::getRepoName,
ApplicationRepositoryDO::getId,
ApplicationImportDTO::setRepositoryId,
MessageConst.UNKNOWN_APP_REPOSITORY);
// 通过唯一标识查询应用
List<ApplicationInfoDO> presentApps = this.getImportRowsPresentValues(rows,
ApplicationImportDTO::getTag,
applicationInfoDAO, ApplicationInfoDO::getAppTag);
// 检查数据是否存在
this.checkImportRowsPresent(rows, ApplicationImportDTO::getTag,
presentApps, ApplicationInfoDO::getAppTag, ApplicationInfoDO::getId);
// 设置导入检查数据
return this.setImportCheckRows(rows);
}
}

View File

@@ -0,0 +1,37 @@
package cn.orionsec.ops.handler.importer.checker;
import cn.orionsec.kit.spring.SpringHolder;
import cn.orionsec.ops.constant.ImportType;
import cn.orionsec.ops.dao.CommandTemplateDAO;
import cn.orionsec.ops.entity.domain.CommandTemplateDO;
import cn.orionsec.ops.entity.importer.CommandTemplateImportDTO;
import cn.orionsec.ops.entity.vo.data.DataImportCheckVO;
import org.apache.poi.ss.usermodel.Workbook;
import java.util.List;
public class CommandTemplateDataChecker extends AbstractDataChecker<CommandTemplateImportDTO, CommandTemplateDO> {
private static final CommandTemplateDAO commandTemplateDAO = SpringHolder.getBean(CommandTemplateDAO.class);
public CommandTemplateDataChecker(Workbook workbook) {
super(ImportType.COMMAND_TEMPLATE, workbook);
}
@Override
protected DataImportCheckVO checkImportData(List<CommandTemplateImportDTO> rows) {
// 检查数据合法性
this.validImportRows(rows);
// 通过名称查询模板
List<CommandTemplateDO> presentTemplates = this.getImportRowsPresentValues(rows,
CommandTemplateImportDTO::getName,
commandTemplateDAO, CommandTemplateDO::getTemplateName);
// 检查数据是否存在
this.checkImportRowsPresent(rows, CommandTemplateImportDTO::getName,
presentTemplates, CommandTemplateDO::getTemplateName, CommandTemplateDO::getId);
// 设置导入检查数据
return this.setImportCheckRows(rows);
}
}

View File

@@ -0,0 +1,48 @@
package cn.orionsec.ops.handler.importer.checker;
import cn.orionsec.kit.lang.utils.Exceptions;
import cn.orionsec.ops.constant.ImportType;
import cn.orionsec.ops.entity.vo.data.DataImportCheckVO;
import org.apache.poi.ss.usermodel.Workbook;
public interface IDataChecker {
/**
* 检查数据
*
* @return check info
*/
DataImportCheckVO doCheck();
/**
* 创建数据检查器
*
* @param importType importType
* @param workbook workbook
* @return checker
*/
static IDataChecker create(ImportType importType, Workbook workbook) {
switch (importType) {
case MACHINE_INFO:
return new MachineInfoDataChecker(workbook);
case MACHINE_PROXY:
return new MachineProxyDataChecker(workbook);
case TAIL_FILE:
return new TailFileDataChecker(workbook);
case APP_PROFILE:
return new AppProfileDataChecker(workbook);
case APPLICATION:
return new ApplicationDataChecker(workbook);
case APP_REPOSITORY:
return new AppRepositoryDataChecker(workbook);
case COMMAND_TEMPLATE:
return new CommandTemplateDataChecker(workbook);
case WEBHOOK:
return new WebhookDataChecker(workbook);
default:
throw Exceptions.unsupported();
}
}
}

View File

@@ -0,0 +1,49 @@
package cn.orionsec.ops.handler.importer.checker;
import cn.orionsec.kit.spring.SpringHolder;
import cn.orionsec.ops.constant.ImportType;
import cn.orionsec.ops.constant.MessageConst;
import cn.orionsec.ops.dao.MachineInfoDAO;
import cn.orionsec.ops.dao.MachineSecretKeyDAO;
import cn.orionsec.ops.entity.domain.MachineInfoDO;
import cn.orionsec.ops.entity.domain.MachineSecretKeyDO;
import cn.orionsec.ops.entity.importer.MachineInfoImportDTO;
import cn.orionsec.ops.entity.vo.data.DataImportCheckVO;
import org.apache.poi.ss.usermodel.Workbook;
import java.util.List;
public class MachineInfoDataChecker extends AbstractDataChecker<MachineInfoImportDTO, MachineInfoDO> {
private static final MachineInfoDAO machineInfoDAO = SpringHolder.getBean(MachineInfoDAO.class);
private static final MachineSecretKeyDAO machineSecretKeyDAO = SpringHolder.getBean(MachineSecretKeyDAO.class);
public MachineInfoDataChecker(Workbook workbook) {
super(ImportType.MACHINE_INFO, workbook);
}
@Override
protected DataImportCheckVO checkImportData(List<MachineInfoImportDTO> rows) {
// 检查数据合法性
this.validImportRows(rows);
// 设置机器id
this.setCheckRowsRelId(rows, MachineInfoImportDTO::getKeyName,
machineSecretKeyDAO::selectIdByNameList,
MachineSecretKeyDO::getKeyName,
MachineSecretKeyDO::getId,
MachineInfoImportDTO::setKeyId,
MessageConst.UNKNOWN_MACHINE_KEY);
// 通过唯一标识查询机器
List<MachineInfoDO> presentMachines = this.getImportRowsPresentValues(rows, MachineInfoImportDTO::getTag,
machineInfoDAO, MachineInfoDO::getMachineTag);
// 检查数据是否存在
this.checkImportRowsPresent(rows, MachineInfoImportDTO::getTag,
presentMachines, MachineInfoDO::getMachineTag, MachineInfoDO::getId);
// 设置导入检查数据
return this.setImportCheckRows(rows);
}
}

View File

@@ -0,0 +1,26 @@
package cn.orionsec.ops.handler.importer.checker;
import cn.orionsec.ops.constant.ImportType;
import cn.orionsec.ops.entity.domain.MachineProxyDO;
import cn.orionsec.ops.entity.importer.MachineProxyImportDTO;
import cn.orionsec.ops.entity.vo.data.DataImportCheckVO;
import org.apache.poi.ss.usermodel.Workbook;
import java.util.List;
public class MachineProxyDataChecker extends AbstractDataChecker<MachineProxyImportDTO, MachineProxyDO> {
public MachineProxyDataChecker(Workbook workbook) {
super(ImportType.MACHINE_PROXY, workbook);
}
@Override
protected DataImportCheckVO checkImportData(List<MachineProxyImportDTO> rows) {
// 检查数据合法性
this.validImportRows(rows);
// 设置导入检查数据
return this.setImportCheckRows(rows);
}
}

View File

@@ -0,0 +1,49 @@
package cn.orionsec.ops.handler.importer.checker;
import cn.orionsec.kit.spring.SpringHolder;
import cn.orionsec.ops.constant.ImportType;
import cn.orionsec.ops.constant.MessageConst;
import cn.orionsec.ops.dao.FileTailListDAO;
import cn.orionsec.ops.dao.MachineInfoDAO;
import cn.orionsec.ops.entity.domain.FileTailListDO;
import cn.orionsec.ops.entity.domain.MachineInfoDO;
import cn.orionsec.ops.entity.importer.MachineTailFileImportDTO;
import cn.orionsec.ops.entity.vo.data.DataImportCheckVO;
import org.apache.poi.ss.usermodel.Workbook;
import java.util.List;
public class TailFileDataChecker extends AbstractDataChecker<MachineTailFileImportDTO, FileTailListDO> {
private static final MachineInfoDAO machineInfoDAO = SpringHolder.getBean(MachineInfoDAO.class);
private static final FileTailListDAO fileTailListDAO = SpringHolder.getBean(FileTailListDAO.class);
public TailFileDataChecker(Workbook workbook) {
super(ImportType.TAIL_FILE, workbook);
}
@Override
protected DataImportCheckVO checkImportData(List<MachineTailFileImportDTO> rows) {
// 检查数据合法性
this.validImportRows(rows);
// 设置机器id
this.setCheckRowsRelId(rows, MachineTailFileImportDTO::getMachineTag,
machineInfoDAO::selectIdByTagList,
MachineInfoDO::getMachineTag,
MachineInfoDO::getId,
MachineTailFileImportDTO::setMachineId,
MessageConst.UNKNOWN_MACHINE_TAG);
// 通过别名查询文件
List<FileTailListDO> presentFiles = this.getImportRowsPresentValues(rows, MachineTailFileImportDTO::getName,
fileTailListDAO, FileTailListDO::getAliasName);
// 检查数据是否存在
this.checkImportRowsPresent(rows, MachineTailFileImportDTO::getName,
presentFiles, FileTailListDO::getAliasName, FileTailListDO::getId);
// 设置导入检查数据
return this.setImportCheckRows(rows);
}
}

View File

@@ -0,0 +1,37 @@
package cn.orionsec.ops.handler.importer.checker;
import cn.orionsec.kit.spring.SpringHolder;
import cn.orionsec.ops.constant.ImportType;
import cn.orionsec.ops.dao.WebhookConfigDAO;
import cn.orionsec.ops.entity.domain.WebhookConfigDO;
import cn.orionsec.ops.entity.importer.WebhookImportDTO;
import cn.orionsec.ops.entity.vo.data.DataImportCheckVO;
import org.apache.poi.ss.usermodel.Workbook;
import java.util.List;
public class WebhookDataChecker extends AbstractDataChecker<WebhookImportDTO, WebhookConfigDO> {
private static final WebhookConfigDAO webhookConfigDAO = SpringHolder.getBean(WebhookConfigDAO.class);
public WebhookDataChecker(Workbook workbook) {
super(ImportType.WEBHOOK, workbook);
}
@Override
protected DataImportCheckVO checkImportData(List<WebhookImportDTO> rows) {
// 检查数据合法性
this.validImportRows(rows);
// 通过名称查询模板
List<WebhookConfigDO> presentTemplates = this.getImportRowsPresentValues(rows,
WebhookImportDTO::getName,
webhookConfigDAO, WebhookConfigDO::getWebhookName);
// 检查数据是否存在
this.checkImportRowsPresent(rows, WebhookImportDTO::getName,
presentTemplates, WebhookConfigDO::getWebhookName, WebhookConfigDO::getId);
// 设置导入检查数据
return this.setImportCheckRows(rows);
}
}

View File

@@ -0,0 +1,227 @@
package cn.orionsec.ops.handler.importer.impl;
import cn.orionsec.kit.lang.utils.Threads;
import cn.orionsec.kit.lang.utils.Valid;
import cn.orionsec.kit.lang.utils.collect.Maps;
import cn.orionsec.kit.lang.utils.convert.Converts;
import cn.orionsec.kit.lang.utils.io.FileWriters;
import cn.orionsec.kit.lang.utils.io.Files1;
import cn.orionsec.kit.lang.utils.time.Dates;
import cn.orionsec.kit.spring.SpringHolder;
import cn.orionsec.ops.constant.ImportType;
import cn.orionsec.ops.constant.SchedulerPools;
import cn.orionsec.ops.constant.event.EventKeys;
import cn.orionsec.ops.constant.message.MessageType;
import cn.orionsec.ops.constant.system.SystemEnvAttr;
import cn.orionsec.ops.entity.importer.BaseDataImportDTO;
import cn.orionsec.ops.entity.importer.DataImportDTO;
import cn.orionsec.ops.entity.vo.data.DataImportCheckRowVO;
import cn.orionsec.ops.entity.vo.data.DataImportCheckVO;
import cn.orionsec.ops.service.api.DataImportService;
import cn.orionsec.ops.service.api.WebSideMessageService;
import cn.orionsec.ops.utils.PathBuilders;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import lombok.extern.slf4j.Slf4j;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Slf4j
public abstract class AbstractDataImporter<DO> implements IDataImporter {
private static final DataImportService dataImportService = SpringHolder.getBean(DataImportService.class);
private static final WebSideMessageService webSideMessageService = SpringHolder.getBean(WebSideMessageService.class);
/**
* 导入数据
*/
protected final DataImportDTO importData;
/**
* domain mapper
*/
protected final BaseMapper<DO> mapper;
/**
* 导入类型
*/
protected ImportType importType;
public AbstractDataImporter(DataImportDTO importData, BaseMapper<DO> mapper) {
this.importData = importData;
this.mapper = mapper;
}
@Override
public void doImport() {
// 异步执行导入
Threads.start(this::doImportData, SchedulerPools.ASYNC_IMPORT_SCHEDULER);
}
/**
* 执行导入数据
*/
@SuppressWarnings("unchecked")
public void doImportData() {
this.importType = ImportType.of(importData.getType());
Exception ex = null;
try {
// 获取缓存数据
DataImportCheckVO dataCheck = importData.getCheck();
List<BaseDataImportDTO> rows = this.getImportData();
// 插入
this.getImportInsertData(dataCheck, rows, (Class<DO>) importType.getConvertClass())
.stream()
.map(s -> (DO) s)
.peek(this::insertFiller)
.peek(mapper::insert)
.forEach(this::insertCallback);
// 更新
this.getImportUpdateData(dataCheck, rows, (Class<DO>) importType.getConvertClass())
.stream()
.map(s -> (DO) s)
.peek(this::updateFiller)
.peek(mapper::updateById)
.forEach(this::updateCallback);
} catch (Exception e) {
ex = e;
log.error("{}导入失败 token: {}, data: {}", importType.name(), importData.getImportToken(), JSON.toJSONString(importData), e);
}
// 发送站内信
this.sendImportWebSideMessage(ex == null);
// 保存日志
this.saveImportDataJson(importData);
// 导入完成回调
this.importFinishCallback(ex == null);
}
/**
* 数据插入填充
*
* @param row row
*/
protected void insertFiller(DO row) {
}
/**
* 数据修改填充
*
* @param row row
*/
protected void updateFiller(DO row) {
}
/**
* 数据插入回调
*
* @param row row
*/
protected void insertCallback(DO row) {
}
/**
* 数据更新回调
*
* @param row row
*/
protected void updateCallback(DO row) {
}
/**
* 导入完成回调
*
* @param isSuccess 是否成功
*/
protected void importFinishCallback(boolean isSuccess) {
}
/**
* 获取导入数据
*
* @param <T> T
* @return list
*/
@SuppressWarnings("unchecked")
private <T extends BaseDataImportDTO> List<T> getImportData() {
ImportType type = ImportType.of(importData.getType());
Valid.notNull(type);
return (List<T>) JSON.parseArray(importData.getData(), type.getImportClass());
}
/**
* 获取导入插入数据
*
* @param dataCheck dataCheck
* @param dataList list
* @param convertClass convertClass
* @param <T> T
* @return rows
*/
private <T extends BaseDataImportDTO> List<DO> getImportInsertData(DataImportCheckVO dataCheck,
List<T> dataList,
Class<DO> convertClass) {
return dataCheck.getInsertRows().stream()
.map(DataImportCheckRowVO::getIndex)
.map(dataList::get)
.map(s -> Converts.to(s, convertClass))
.collect(Collectors.toList());
}
/**
* 获取导入更新数据
*
* @param dataCheck dataCheck
* @param dataList list
* @param convertClass convertClass
* @param <T> T
* @return rows
*/
private <T extends BaseDataImportDTO> List<DO> getImportUpdateData(DataImportCheckVO dataCheck,
List<T> dataList,
Class<DO> convertClass) {
return dataCheck.getUpdateRows().stream()
.map(DataImportCheckRowVO::getIndex)
.map(dataList::get)
.map(s -> Converts.to(s, convertClass))
.collect(Collectors.toList());
}
/**
* 发送站内信
*
* @param isSuccess 是否导入成功
*/
private void sendImportWebSideMessage(boolean isSuccess) {
// 消息类型
MessageType messageType;
if (isSuccess) {
messageType = MessageType.DATA_IMPORT_SUCCESS;
} else {
messageType = MessageType.DATA_IMPORT_FAILURE;
}
// 站内信参数
Map<String, Object> params = Maps.newMap();
params.put(EventKeys.TIME, Dates.format(importData.getImportTime()));
params.put(EventKeys.TOKEN, importData.getImportToken());
params.put(EventKeys.LABEL, importType.getLabel());
webSideMessageService.addMessage(messageType, importData.getType().longValue(), importData.getUserId(), importData.getUserName(), params);
}
/**
* 将导入 json 存储到本地
*
* @param importData json
*/
private void saveImportDataJson(DataImportDTO importData) {
// 将数据存储到本地 log
String importJsonPath = PathBuilders.getImportDataJsonPath(importData.getUserId(), importData.getType(), importData.getImportToken());
String path = Files1.getPath(SystemEnvAttr.LOG_PATH.getValue(), importJsonPath);
FileWriters.write(path, JSON.toJSONString(importData, SerializerFeature.PrettyFormat));
}
}

View File

@@ -0,0 +1,26 @@
package cn.orionsec.ops.handler.importer.impl;
import cn.orionsec.kit.spring.SpringHolder;
import cn.orionsec.ops.dao.ApplicationProfileDAO;
import cn.orionsec.ops.entity.domain.ApplicationProfileDO;
import cn.orionsec.ops.entity.importer.DataImportDTO;
import cn.orionsec.ops.service.api.ApplicationProfileService;
public class AppProfileDataImporter extends AbstractDataImporter<ApplicationProfileDO> {
private static final ApplicationProfileDAO applicationProfileDAO = SpringHolder.getBean(ApplicationProfileDAO.class);
private static final ApplicationProfileService applicationProfileService = SpringHolder.getBean(ApplicationProfileService.class);
public AppProfileDataImporter(DataImportDTO importData) {
super(importData, applicationProfileDAO);
}
@Override
protected void importFinishCallback(boolean isSuccess) {
applicationProfileService.clearProfileCache();
}
}

View File

@@ -0,0 +1,41 @@
package cn.orionsec.ops.handler.importer.impl;
import cn.orionsec.kit.lang.utils.io.Files1;
import cn.orionsec.kit.spring.SpringHolder;
import cn.orionsec.ops.constant.app.RepositoryStatus;
import cn.orionsec.ops.dao.ApplicationRepositoryDAO;
import cn.orionsec.ops.entity.domain.ApplicationRepositoryDO;
import cn.orionsec.ops.entity.importer.DataImportDTO;
import cn.orionsec.ops.utils.Utils;
import java.io.File;
public class AppRepositoryDataImporter extends AbstractDataImporter<ApplicationRepositoryDO> {
private static final ApplicationRepositoryDAO applicationRepositoryDAO = SpringHolder.getBean(ApplicationRepositoryDAO.class);
public AppRepositoryDataImporter(DataImportDTO importData) {
super(importData, applicationRepositoryDAO);
}
@Override
protected void insertFiller(ApplicationRepositoryDO row) {
row.setRepoStatus(RepositoryStatus.UNINITIALIZED.getStatus());
}
@Override
protected void updateFiller(ApplicationRepositoryDO row) {
Long id = row.getId();
ApplicationRepositoryDO beforeRepo = applicationRepositoryDAO.selectById(id);
if (beforeRepo != null && !beforeRepo.getRepoUrl().equals(row.getRepoUrl())) {
// 如果修改了url则状态改为未初始化
row.setRepoStatus(RepositoryStatus.UNINITIALIZED.getStatus());
// 删除 event 目录
File clonePath = new File(Utils.getRepositoryEventDir(id));
Files1.delete(clonePath);
}
}
}

View File

@@ -0,0 +1,26 @@
package cn.orionsec.ops.handler.importer.impl;
import cn.orionsec.kit.spring.SpringHolder;
import cn.orionsec.ops.dao.ApplicationInfoDAO;
import cn.orionsec.ops.entity.domain.ApplicationInfoDO;
import cn.orionsec.ops.entity.importer.DataImportDTO;
import cn.orionsec.ops.service.api.ApplicationInfoService;
public class ApplicationDataImporter extends AbstractDataImporter<ApplicationInfoDO> {
private static final ApplicationInfoDAO applicationInfoDAO = SpringHolder.getBean(ApplicationInfoDAO.class);
private static final ApplicationInfoService applicationInfoService = SpringHolder.getBean(ApplicationInfoService.class);
public ApplicationDataImporter(DataImportDTO importData) {
super(importData, applicationInfoDAO);
}
@Override
protected void insertFiller(ApplicationInfoDO row) {
row.setAppSort(applicationInfoService.getNextSort());
}
}

View File

@@ -0,0 +1,31 @@
package cn.orionsec.ops.handler.importer.impl;
import cn.orionsec.kit.spring.SpringHolder;
import cn.orionsec.ops.dao.CommandTemplateDAO;
import cn.orionsec.ops.entity.domain.CommandTemplateDO;
import cn.orionsec.ops.entity.importer.DataImportDTO;
public class CommandTemplateDataImporter extends AbstractDataImporter<CommandTemplateDO> {
private static final CommandTemplateDAO commandTemplateDAO = SpringHolder.getBean(CommandTemplateDAO.class);
public CommandTemplateDataImporter(DataImportDTO importData) {
super(importData, commandTemplateDAO);
}
@Override
protected void insertFiller(CommandTemplateDO row) {
row.setCreateUserId(importData.getUserId());
row.setCreateUserName(importData.getUserName());
row.setUpdateUserId(importData.getUserId());
row.setUpdateUserName(importData.getUserName());
}
@Override
protected void updateFiller(CommandTemplateDO row) {
row.setUpdateUserId(importData.getUserId());
row.setUpdateUserName(importData.getUserName());
}
}

View File

@@ -0,0 +1,45 @@
package cn.orionsec.ops.handler.importer.impl;
import cn.orionsec.kit.lang.utils.Exceptions;
import cn.orionsec.ops.constant.ImportType;
import cn.orionsec.ops.entity.importer.DataImportDTO;
public interface IDataImporter {
/**
* 执行导入
*/
void doImport();
/**
* 创建数据导入器
*
* @param importData importData
* @return importer
*/
static IDataImporter create(DataImportDTO importData) {
switch (ImportType.of(importData.getType())) {
case MACHINE_INFO:
return new MachineInfoDataImporter(importData);
case MACHINE_PROXY:
return new MachineProxyDataImporter(importData);
case TAIL_FILE:
return new TailFileDataImporter(importData);
case APP_PROFILE:
return new AppProfileDataImporter(importData);
case APPLICATION:
return new ApplicationDataImporter(importData);
case APP_REPOSITORY:
return new AppRepositoryDataImporter(importData);
case COMMAND_TEMPLATE:
return new CommandTemplateDataImporter(importData);
case WEBHOOK:
return new WebhookDataImporter(importData);
default:
throw Exceptions.unsupported();
}
}
}

View File

@@ -0,0 +1,39 @@
package cn.orionsec.ops.handler.importer.impl;
import cn.orionsec.kit.spring.SpringHolder;
import cn.orionsec.ops.dao.MachineInfoDAO;
import cn.orionsec.ops.entity.domain.MachineInfoDO;
import cn.orionsec.ops.entity.importer.DataImportDTO;
import cn.orionsec.ops.service.api.MachineEnvService;
import java.util.Optional;
public class MachineInfoDataImporter extends AbstractDataImporter<MachineInfoDO> {
private static final MachineInfoDAO machineInfoDAO = SpringHolder.getBean(MachineInfoDAO.class);
private static final MachineEnvService machineEnvService = SpringHolder.getBean(MachineEnvService.class);
public MachineInfoDataImporter(DataImportDTO importData) {
super(importData, machineInfoDAO);
}
@Override
protected void updateFiller(MachineInfoDO row) {
// 填充忽略的字段
Optional.ofNullable(row.getId())
.map(machineInfoDAO::selectById)
.ifPresent(m -> {
row.setProxyId(m.getProxyId());
row.setKeyId(m.getKeyId());
});
}
@Override
protected void insertCallback(MachineInfoDO row) {
// 初始化新增机器环境变量
machineEnvService.initEnv(row.getId());
}
}

View File

@@ -0,0 +1,17 @@
package cn.orionsec.ops.handler.importer.impl;
import cn.orionsec.kit.spring.SpringHolder;
import cn.orionsec.ops.dao.MachineProxyDAO;
import cn.orionsec.ops.entity.domain.MachineProxyDO;
import cn.orionsec.ops.entity.importer.DataImportDTO;
public class MachineProxyDataImporter extends AbstractDataImporter<MachineProxyDO> {
private static final MachineProxyDAO machineProxyDAO = SpringHolder.getBean(MachineProxyDAO.class);
public MachineProxyDataImporter(DataImportDTO importData) {
super(importData, machineProxyDAO);
}
}

View File

@@ -0,0 +1,17 @@
package cn.orionsec.ops.handler.importer.impl;
import cn.orionsec.kit.spring.SpringHolder;
import cn.orionsec.ops.dao.FileTailListDAO;
import cn.orionsec.ops.entity.domain.FileTailListDO;
import cn.orionsec.ops.entity.importer.DataImportDTO;
public class TailFileDataImporter extends AbstractDataImporter<FileTailListDO> {
private static final FileTailListDAO fileTailListDAO = SpringHolder.getBean(FileTailListDAO.class);
public TailFileDataImporter(DataImportDTO importData) {
super(importData, fileTailListDAO);
}
}

View File

@@ -0,0 +1,17 @@
package cn.orionsec.ops.handler.importer.impl;
import cn.orionsec.kit.spring.SpringHolder;
import cn.orionsec.ops.dao.WebhookConfigDAO;
import cn.orionsec.ops.entity.domain.WebhookConfigDO;
import cn.orionsec.ops.entity.importer.DataImportDTO;
public class WebhookDataImporter extends AbstractDataImporter<WebhookConfigDO> {
private static final WebhookConfigDAO webhookConfigDAO = SpringHolder.getBean(WebhookConfigDAO.class);
public WebhookDataImporter(DataImportDTO importData) {
super(importData, webhookConfigDAO);
}
}

View File

@@ -0,0 +1,65 @@
package cn.orionsec.ops.handler.importer.validator;
import cn.orionsec.kit.lang.utils.Strings;
import cn.orionsec.ops.constant.CnConst;
import cn.orionsec.ops.entity.importer.ApplicationProfileImportDTO;
import cn.orionsec.ops.utils.Valid;
public class ApplicationProfileValidator implements DataValidator {
private ApplicationProfileValidator() {
}
public static final ApplicationProfileValidator INSTANCE = new ApplicationProfileValidator();
public static final int NAME_MAX_LEN = 32;
public static final int TAG_MAX_LEN = 32;
public static final int DESCRIPTION_MAX_LEN = 64;
public static final String NAME_EMPTY_MESSAGE = "环境名称不能为空";
public static final String NAME_LEN_MESSAGE = "环境名称长度不能大于 " + NAME_MAX_LEN + "";
public static final String TAG_EMPTY_MESSAGE = "唯一标识不能为空";
public static final String TAG_LEN_MESSAGE = "唯一标识长度不能大于 " + TAG_MAX_LEN + "";
public static final String RELEASE_AUDIT_EMPTY_MESSAGE = "发布审核不能为空";
public static final String RELEASE_AUDIT_MESSAGE = "发布审核只能为 " + CnConst.OPEN + "" + CnConst.CLOSE;
public static final String DESCRIPTION_LEN_MESSAGE = "描述长度不能大于 " + DESCRIPTION_MAX_LEN + "";
@Override
public void validData(Object o) {
if (o instanceof ApplicationProfileImportDTO) {
validImport((ApplicationProfileImportDTO) o);
}
}
/**
* 验证导入数据
*
* @param row row
*/
private void validImport(ApplicationProfileImportDTO row) {
String name = row.getName();
String tag = row.getTag();
String releaseAudit = row.getReleaseAudit();
String description = row.getDescription();
Valid.notBlank(name, NAME_EMPTY_MESSAGE);
Valid.validLengthLte(name, NAME_MAX_LEN, NAME_LEN_MESSAGE);
Valid.notBlank(tag, TAG_EMPTY_MESSAGE);
Valid.validLengthLte(tag, TAG_MAX_LEN, TAG_LEN_MESSAGE);
Valid.notBlank(releaseAudit, RELEASE_AUDIT_EMPTY_MESSAGE);
Valid.in(releaseAudit, new String[]{CnConst.OPEN, CnConst.CLOSE}, RELEASE_AUDIT_MESSAGE);
if (!Strings.isBlank(description)) {
Valid.validLengthLte(description, DESCRIPTION_MAX_LEN, DESCRIPTION_LEN_MESSAGE);
}
}
}

View File

@@ -0,0 +1,126 @@
package cn.orionsec.ops.handler.importer.validator;
import cn.orionsec.kit.lang.utils.Exceptions;
import cn.orionsec.kit.lang.utils.Strings;
import cn.orionsec.ops.constant.app.RepositoryAuthType;
import cn.orionsec.ops.constant.app.RepositoryTokenType;
import cn.orionsec.ops.entity.importer.ApplicationRepositoryImportDTO;
import cn.orionsec.ops.utils.Valid;
import cn.orionsec.ops.utils.ValueMix;
import java.util.Arrays;
import java.util.stream.Collectors;
public class ApplicationRepositoryValidator implements DataValidator {
private ApplicationRepositoryValidator() {
}
public static final ApplicationRepositoryValidator INSTANCE = new ApplicationRepositoryValidator();
public static final int NAME_MAX_LEN = 32;
public static final int URL_MAX_LEN = 1024;
public static final int USERNAME_MAX_LEN = 128;
public static final int TOKEN_MAX_LEN = 256;
public static final int PASSWORD_MAX_LEN = 128;
public static final int DESCRIPTION_MAX_LEN = 64;
public static final String NAME_EMPTY_MESSAGE = "名称不能为空";
public static final String NAME_LEN_MESSAGE = "名称长度不能大于 " + NAME_MAX_LEN + "";
public static final String URL_EMPTY_MESSAGE = "url 不能为空";
public static final String URL_LEN_MESSAGE = "url 长度不能大于 " + URL_MAX_LEN + "";
public static final String AUTH_TYPE_EMPTY_MESSAGE = "认证方式不能为空";
public static final String AUTH_TYPE_VALUE_MESSAGE = "认证方式只能为 " + Arrays.stream(RepositoryAuthType.values()).map(RepositoryAuthType::getLabel).collect(Collectors.toList());
public static final String TOKEN_TYPE_EMPTY_MESSAGE = "认证方式为" + RepositoryAuthType.TOKEN.getLabel() + "时 令牌类型不能为空";
public static final String TOKEN_TYPE_VALUE_MESSAGE = "令牌类型只能为 " + Arrays.stream(RepositoryTokenType.values()).map(RepositoryTokenType::getLabel).collect(Collectors.toList());
public static final String PASSWORD_TOKEN_DECRYPT_MESSAGE = "密码/令牌密文解密失败";
public static final String USERNAME_PASSWORD_MESSAGE = "用户名和密码必须同时存在";
public static final String TOKEN_EMPTY_MESSAGE = "令牌不能为空";
public static final String USERNAME_TOKEN_MESSAGE = "令牌类型为 " + RepositoryTokenType.GITEE.getLabel() + " 时 用户名和密钥必须同时存在";
public static final String USERNAME_LEN_MESSAGE = "用户名长度不能大于 " + USERNAME_MAX_LEN + "";
public static final String TOKEN_LEN_MESSAGE = "密钥长度不能大于 " + TOKEN_MAX_LEN + "";
public static final String PASSWORD_LEN_MESSAGE = "密码长度不能大于 " + PASSWORD_MAX_LEN + "";
public static final String DESCRIPTION_LEN_MESSAGE = "描述长度不能大于 " + DESCRIPTION_MAX_LEN + "";
@Override
public void validData(Object o) {
if (o instanceof ApplicationRepositoryImportDTO) {
validImport((ApplicationRepositoryImportDTO) o);
}
}
/**
* 验证导入数据
*
* @param row row
*/
private void validImport(ApplicationRepositoryImportDTO row) {
String name = row.getName();
String url = row.getUrl();
String authTypeValue = row.getAuthType();
String tokenTypeValue = row.getTokenType();
String username = row.getUsername();
String encryptAuthValue = row.getEncryptAuthValue();
String importAuthValue = row.getImportAuthValue();
String description = row.getDescription();
Valid.notBlank(name, NAME_EMPTY_MESSAGE);
Valid.validLengthLte(name, NAME_MAX_LEN, NAME_LEN_MESSAGE);
Valid.notBlank(url, URL_EMPTY_MESSAGE);
Valid.validLengthLte(url, URL_MAX_LEN, URL_LEN_MESSAGE);
Valid.notBlank(authTypeValue, AUTH_TYPE_EMPTY_MESSAGE);
RepositoryAuthType authType = RepositoryAuthType.of(authTypeValue);
Valid.notNull(authType, AUTH_TYPE_VALUE_MESSAGE);
if (!Strings.isEmpty(encryptAuthValue)) {
String decryptValue = ValueMix.decrypt(encryptAuthValue);
Valid.notNull(decryptValue, PASSWORD_TOKEN_DECRYPT_MESSAGE);
row.setDecryptAuthValue(decryptValue);
}
if (RepositoryAuthType.PASSWORD.equals(authType)) {
// 密码验证
if (!Strings.isEmpty(importAuthValue)) {
Valid.validLengthLte(importAuthValue, PASSWORD_MAX_LEN, PASSWORD_LEN_MESSAGE);
}
if (Strings.isEmpty(username) ^ (Strings.isEmpty(row.getDecryptAuthValue()) && Strings.isEmpty(importAuthValue))) {
throw Exceptions.argument(USERNAME_PASSWORD_MESSAGE);
}
} else {
// 令牌验证
Valid.notBlank(tokenTypeValue, TOKEN_TYPE_EMPTY_MESSAGE);
RepositoryTokenType tokenType = RepositoryTokenType.of(tokenTypeValue);
Valid.notNull(tokenType, TOKEN_TYPE_VALUE_MESSAGE);
if (!Strings.isEmpty(importAuthValue)) {
Valid.validLengthLte(importAuthValue, TOKEN_MAX_LEN, TOKEN_LEN_MESSAGE);
}
Valid.isTrue(!Strings.isBlank(importAuthValue) || !Strings.isBlank(row.getDecryptAuthValue()), TOKEN_EMPTY_MESSAGE);
if (RepositoryTokenType.GITEE.equals(tokenType)) {
Valid.notBlank(username, USERNAME_TOKEN_MESSAGE);
Valid.validLengthLte(username, USERNAME_MAX_LEN, USERNAME_LEN_MESSAGE);
}
}
if (!Strings.isBlank(description)) {
Valid.validLengthLte(description, DESCRIPTION_MAX_LEN, DESCRIPTION_LEN_MESSAGE);
}
}
}

View File

@@ -0,0 +1,57 @@
package cn.orionsec.ops.handler.importer.validator;
import cn.orionsec.kit.lang.utils.Strings;
import cn.orionsec.ops.entity.importer.ApplicationImportDTO;
import cn.orionsec.ops.utils.Valid;
public class ApplicationValidator implements DataValidator {
private ApplicationValidator() {
}
public static final ApplicationValidator INSTANCE = new ApplicationValidator();
public static final int NAME_MAX_LEN = 32;
public static final int TAG_MAX_LEN = 32;
public static final int DESCRIPTION_MAX_LEN = 64;
public static final String NAME_EMPTY_MESSAGE = "应用名称不能为空";
public static final String NAME_LEN_MESSAGE = "应用名称长度不能大于 " + NAME_MAX_LEN + "";
public static final String TAG_EMPTY_MESSAGE = "唯一标识不能为空";
public static final String TAG_LEN_MESSAGE = "唯一标识长度不能大于 " + TAG_MAX_LEN + "";
public static final String DESCRIPTION_LEN_MESSAGE = "描述长度不能大于 " + DESCRIPTION_MAX_LEN + "";
@Override
public void validData(Object o) {
if (o instanceof ApplicationImportDTO) {
validImport((ApplicationImportDTO) o);
}
}
/**
* 验证导入数据
*
* @param row row
*/
private static void validImport(ApplicationImportDTO row) {
String name = row.getName();
String tag = row.getTag();
String description = row.getDescription();
Valid.notBlank(name, NAME_EMPTY_MESSAGE);
Valid.validLengthLte(name, NAME_MAX_LEN, NAME_LEN_MESSAGE);
Valid.notBlank(tag, TAG_EMPTY_MESSAGE);
Valid.validLengthLte(tag, TAG_MAX_LEN, TAG_LEN_MESSAGE);
if (!Strings.isBlank(description)) {
Valid.validLengthLte(description, DESCRIPTION_MAX_LEN, DESCRIPTION_LEN_MESSAGE);
}
}
}

View File

@@ -0,0 +1,55 @@
package cn.orionsec.ops.handler.importer.validator;
import cn.orionsec.kit.lang.utils.Strings;
import cn.orionsec.ops.entity.importer.CommandTemplateImportDTO;
import cn.orionsec.ops.utils.Valid;
public class CommandTemplateValidator implements DataValidator {
private CommandTemplateValidator() {
}
public static final CommandTemplateValidator INSTANCE = new CommandTemplateValidator();
public static final int NAME_MAX_LEN = 32;
public static final int TEMPLATE_MAX_LEN = 2048;
public static final int DESCRIPTION_MAX_LEN = 64;
public static final String NAME_EMPTY_MESSAGE = "模板名称不能为空";
public static final String NAME_LEN_MESSAGE = "模板名称长度不能大于 " + NAME_MAX_LEN + "";
public static final String TEMPLATE_EMPTY_MESSAGE = "模板命令不能为空";
public static final String TEMPLATE_LEN_MESSAGE = "模板命令长度不能大于 " + TEMPLATE_MAX_LEN + "";
public static final String DESCRIPTION_LEN_MESSAGE = "描述长度不能大于 " + DESCRIPTION_MAX_LEN + "";
@Override
public void validData(Object o) {
if (o instanceof CommandTemplateImportDTO) {
validImport((CommandTemplateImportDTO) o);
}
}
/**
* 验证导入数据
*
* @param row row
*/
private void validImport(CommandTemplateImportDTO row) {
String name = row.getName();
String template = row.getTemplate();
String description = row.getDescription();
Valid.notBlank(name, NAME_EMPTY_MESSAGE);
Valid.validLengthLte(name, NAME_MAX_LEN, NAME_LEN_MESSAGE);
Valid.notBlank(template, TEMPLATE_EMPTY_MESSAGE);
Valid.validLengthLte(template, TEMPLATE_MAX_LEN, TEMPLATE_LEN_MESSAGE);
if (!Strings.isBlank(description)) {
Valid.validLengthLte(description, DESCRIPTION_MAX_LEN, DESCRIPTION_LEN_MESSAGE);
}
}
}

View File

@@ -0,0 +1,13 @@
package cn.orionsec.ops.handler.importer.validator;
public interface DataValidator {
/**
* 验证数据
*
* @param o o
*/
void validData(Object o);
}

View File

@@ -0,0 +1,87 @@
package cn.orionsec.ops.handler.importer.validator;
import cn.orionsec.kit.lang.utils.Charsets;
import cn.orionsec.ops.entity.importer.MachineTailFileImportDTO;
import cn.orionsec.ops.utils.Valid;
public class FileTailValidator implements DataValidator {
private FileTailValidator() {
}
public static final FileTailValidator INSTANCE = new FileTailValidator();
public static final int NAME_MAX_LEN = 64;
public static final int PATH_MAX_LEN = 1024;
public static final int COMMAND_MAX_LEN = 1024;
public static final int CHARSET_MAX_LEN = 16;
public static final int OFFSET_MIN_RANGE = 0;
public static final int OFFSET_MAX_RANGE = 10000;
public static final int DESCRIPTION_MAX_LEN = 64;
public static final String MACHINE_TAG_EMPTY_MESSAGE = "机器标识不能为空";
public static final String NAME_EMPTY_MESSAGE = "文件别名不能为空";
public static final String NAME_LEN_MESSAGE = "文件别名长度不能大于 " + NAME_MAX_LEN + "";
public static final String PATH_EMPTY_MESSAGE = "文件路径不能为空";
public static final String PATH_LEN_MESSAGE = "文件路径长度不能大于 " + PATH_MAX_LEN + "";
public static final String COMMAND_EMPTY_MESSAGE = "执行命令不能为空";
public static final String COMMAND_LEN_MESSAGE = "执行命令长度不能大于 " + COMMAND_MAX_LEN + "";
public static final String CHARSET_EMPTY_MESSAGE = "文件编码不能为空";
public static final String CHARSET_UNSUPPORTED = "文件编码不合法";
public static final String CHARSET_LEN_MESSAGE = "文件编码不能大于 " + CHARSET_MAX_LEN + "";
public static final String OFFSET_EMPTY_MESSAGE = "尾部偏移行不能为空";
public static final String OFFSET_LEN_MESSAGE = "尾部偏移行必须在" + OFFSET_MIN_RANGE + "~" + OFFSET_MAX_RANGE + "之间";
public static final String DESCRIPTION_LEN_MESSAGE = "描述长度不能大于 " + DESCRIPTION_MAX_LEN + "";
@Override
public void validData(Object o) {
if (o instanceof MachineTailFileImportDTO) {
validImport((MachineTailFileImportDTO) o);
}
}
/**
* 验证导入数据
*
* @param row row
*/
private void validImport(MachineTailFileImportDTO row) {
String machineTag = row.getMachineTag();
String name = row.getName();
String path = row.getPath();
String charset = row.getCharset();
Integer offset = row.getOffset();
String command = row.getCommand();
Valid.notBlank(machineTag, MACHINE_TAG_EMPTY_MESSAGE);
Valid.notBlank(name, NAME_EMPTY_MESSAGE);
Valid.validLengthLte(name, NAME_MAX_LEN, NAME_LEN_MESSAGE);
Valid.notBlank(path, PATH_EMPTY_MESSAGE);
Valid.validLengthLte(path, PATH_MAX_LEN, PATH_LEN_MESSAGE);
Valid.notBlank(charset, CHARSET_EMPTY_MESSAGE);
Valid.validLengthLte(charset, CHARSET_MAX_LEN, CHARSET_LEN_MESSAGE);
Valid.isTrue(Charsets.isSupported(charset), CHARSET_UNSUPPORTED);
Valid.notNull(offset, OFFSET_EMPTY_MESSAGE);
Valid.inRange(offset, OFFSET_MIN_RANGE, OFFSET_MAX_RANGE, OFFSET_LEN_MESSAGE);
Valid.notBlank(command, COMMAND_EMPTY_MESSAGE);
Valid.validLengthLte(command, COMMAND_MAX_LEN, COMMAND_LEN_MESSAGE);
}
}

View File

@@ -0,0 +1,98 @@
package cn.orionsec.ops.handler.importer.validator;
import cn.orionsec.kit.lang.utils.Strings;
import cn.orionsec.ops.constant.machine.ProxyType;
import cn.orionsec.ops.entity.importer.MachineProxyImportDTO;
import cn.orionsec.ops.utils.Valid;
import cn.orionsec.ops.utils.ValueMix;
import java.util.Arrays;
import java.util.stream.Collectors;
public class MachineProxyValidator implements DataValidator {
private MachineProxyValidator() {
}
public static final MachineProxyValidator INSTANCE = new MachineProxyValidator();
public static final int HOST_MAX_LEN = 128;
public static final int USER_NAME_MAX_LEN = 128;
public static final int PASSWORD_MAX_LEN = 128;
public static final int PORT_MIN_RANGE = 2;
public static final int PORT_MAX_RANGE = 65534;
public static final int DESCRIPTION_MAX_LEN = 64;
public static final String HOST_EMPTY_MESSAGE = "主机不能为空";
public static final String HOST_LEN_MESSAGE = "主机长度不能大于 " + HOST_MAX_LEN + "";
public static final String PROXY_TYPE_EMPTY_MESSAGE = "代理类型不能为空";
public static final String PROXY_TYPE_MESSAGE = "代理类型只能为 " + Arrays.stream(ProxyType.values()).map(ProxyType::getLabel).collect(Collectors.toList());
public static final String USER_NAME_LEN_MESSAGE = "用户名长度不能大于 " + USER_NAME_MAX_LEN + "";
public static final String PASSWORD_DECRYPT_MESSAGE = "密码密文解密失败";
public static final String PASSWORD_LEN_MESSAGE = "密码明文长度不能大于 " + PASSWORD_MAX_LEN + "";
public static final String USERNAME_PASSWORD_ABSENT_MESSAGE = "用户名密码需要同时存在";
public static final String PORT_EMPTY_MESSAGE = "端口不能为空";
public static final String PORT_LEN_MESSAGE = "端口必须在" + PORT_MIN_RANGE + "~" + PORT_MAX_RANGE + "之间";
public static final String DESCRIPTION_LEN_MESSAGE = "描述长度不能大于 " + DESCRIPTION_MAX_LEN + "";
@Override
public void validData(Object o) {
if (o instanceof MachineProxyImportDTO) {
validImport((MachineProxyImportDTO) o);
}
}
/**
* 验证导入数据
*
* @param row row
*/
private void validImport(MachineProxyImportDTO row) {
String host = row.getHost();
Integer port = row.getPort();
String proxyType = row.getProxyType();
String username = row.getUsername();
String encryptPassword = row.getEncryptPassword();
String password = row.getImportPassword();
String description = row.getDescription();
Valid.notBlank(host, HOST_EMPTY_MESSAGE);
Valid.validLengthLte(host, HOST_MAX_LEN, HOST_LEN_MESSAGE);
Valid.notNull(port, PORT_EMPTY_MESSAGE);
Valid.inRange(port, PORT_MIN_RANGE, PORT_MAX_RANGE, PORT_LEN_MESSAGE);
Valid.notBlank(proxyType, PROXY_TYPE_EMPTY_MESSAGE);
Valid.notNull(ProxyType.of(proxyType), PROXY_TYPE_MESSAGE);
if (!Strings.isBlank(username)) {
Valid.validLengthLte(username, USER_NAME_MAX_LEN, USER_NAME_LEN_MESSAGE);
}
if (!Strings.isBlank(password)) {
Valid.validLengthLte(password, PASSWORD_MAX_LEN, PASSWORD_LEN_MESSAGE);
}
if (!Strings.isBlank(encryptPassword)) {
String decryptPassword = ValueMix.decrypt(encryptPassword);
Valid.notNull(decryptPassword, PASSWORD_DECRYPT_MESSAGE);
row.setDecryptPassword(decryptPassword);
}
if (!Strings.isBlank(username)) {
Valid.isTrue(!Strings.isBlank(row.getImportPassword()) || !Strings.isBlank(row.getDecryptPassword()), USERNAME_PASSWORD_ABSENT_MESSAGE);
}
if (!Strings.isBlank(description)) {
Valid.validLengthLte(description, DESCRIPTION_MAX_LEN, DESCRIPTION_LEN_MESSAGE);
}
}
}

View File

@@ -0,0 +1,118 @@
package cn.orionsec.ops.handler.importer.validator;
import cn.orionsec.kit.lang.utils.Strings;
import cn.orionsec.ops.constant.machine.MachineAuthType;
import cn.orionsec.ops.entity.importer.MachineInfoImportDTO;
import cn.orionsec.ops.utils.Valid;
import cn.orionsec.ops.utils.ValueMix;
import java.util.Arrays;
import java.util.stream.Collectors;
public class MachineValidator implements DataValidator {
private MachineValidator() {
}
public static final MachineValidator INSTANCE = new MachineValidator();
public static final int NAME_MAX_LEN = 32;
public static final int TAG_MAX_LEN = 32;
public static final int HOST_MAX_LEN = 128;
public static final int USER_NAME_MAX_LEN = 128;
public static final int PASSWORD_MAX_LEN = 128;
public static final int PORT_MIN_RANGE = 2;
public static final int PORT_MAX_RANGE = 65534;
public static final int DESCRIPTION_MAX_LEN = 64;
public static final String NAME_EMPTY_MESSAGE = "名称不能为空";
public static final String NAME_LEN_MESSAGE = "名称长度不能大于 " + NAME_MAX_LEN + "";
public static final String TAG_EMPTY_MESSAGE = "唯一标识不能为空";
public static final String TAG_LEN_MESSAGE = "唯一标识长度不能大于 " + TAG_MAX_LEN + "";
public static final String HOST_EMPTY_MESSAGE = "主机不能为空";
public static final String HOST_LEN_MESSAGE = "主机长度不能大于 " + HOST_MAX_LEN + "";
public static final String AUTH_TYPE_EMPTY_MESSAGE = "认证方式不能为空";
public static final String AUTH_TYPE_MESSAGE = "认证方式只能为 " + Arrays.stream(MachineAuthType.values()).map(MachineAuthType::getLabel).collect(Collectors.toList());
public static final String USER_NAME_EMPTY_MESSAGE = "用户名不能为空";
public static final String USER_NAME_LEN_MESSAGE = "用户名长度不能大于 " + USER_NAME_MAX_LEN + "";
public static final String PASSWORD_DECRYPT_MESSAGE = "密码密文解密失败";
public static final String PASSWORD_LEN_MESSAGE = "密码明文长度不能大于 " + PASSWORD_MAX_LEN + "";
public static final String PASSWORD_EMPTY_MESSAGE = "密码验证密码不能为空";
public static final String PORT_EMPTY_MESSAGE = "端口不能为空";
public static final String PORT_LEN_MESSAGE = "端口必须在" + PORT_MIN_RANGE + "~" + PORT_MAX_RANGE + "之间";
public static final String DESCRIPTION_LEN_MESSAGE = "描述长度不能大于 " + DESCRIPTION_MAX_LEN + "";
@Override
public void validData(Object o) {
if (o instanceof MachineInfoImportDTO) {
validImport((MachineInfoImportDTO) o);
}
}
/**
* 验证导入数据
*
* @param row row
*/
private void validImport(MachineInfoImportDTO row) {
String name = row.getName();
String tag = row.getTag();
String host = row.getHost();
Integer port = row.getPort();
String username = row.getUsername();
String authType = row.getAuthType();
String encryptPassword = row.getEncryptPassword();
String password = row.getImportPassword();
String description = row.getDescription();
Valid.notBlank(name, NAME_EMPTY_MESSAGE);
Valid.validLengthLte(name, NAME_MAX_LEN, NAME_LEN_MESSAGE);
Valid.notBlank(tag, TAG_EMPTY_MESSAGE);
Valid.validLengthLte(tag, TAG_MAX_LEN, TAG_LEN_MESSAGE);
Valid.notBlank(host, HOST_EMPTY_MESSAGE);
Valid.validLengthLte(host, HOST_MAX_LEN, HOST_LEN_MESSAGE);
Valid.notNull(port, PORT_EMPTY_MESSAGE);
Valid.inRange(port, PORT_MIN_RANGE, PORT_MAX_RANGE, PORT_LEN_MESSAGE);
Valid.notBlank(username, USER_NAME_EMPTY_MESSAGE);
Valid.validLengthLte(username, USER_NAME_MAX_LEN, USER_NAME_LEN_MESSAGE);
Valid.notBlank(authType, AUTH_TYPE_EMPTY_MESSAGE);
MachineAuthType machineAuthType = Valid.notNull(MachineAuthType.of(authType), AUTH_TYPE_MESSAGE);
if (!Strings.isBlank(encryptPassword)) {
String decryptPassword = ValueMix.decrypt(encryptPassword);
Valid.notNull(decryptPassword, PASSWORD_DECRYPT_MESSAGE);
row.setDecryptPassword(decryptPassword);
}
if (!Strings.isBlank(password)) {
Valid.validLengthLte(password, PASSWORD_MAX_LEN, PASSWORD_LEN_MESSAGE);
}
if (MachineAuthType.PASSWORD.equals(machineAuthType)) {
Valid.isTrue(!Strings.isBlank(row.getImportPassword()) || !Strings.isBlank(row.getDecryptPassword()), PASSWORD_EMPTY_MESSAGE);
}
if (!Strings.isBlank(description)) {
Valid.validLengthLte(description, DESCRIPTION_MAX_LEN, DESCRIPTION_LEN_MESSAGE);
}
}
}

View File

@@ -0,0 +1,58 @@
package cn.orionsec.ops.handler.importer.validator;
import cn.orionsec.ops.constant.webhook.WebhookType;
import cn.orionsec.ops.entity.importer.WebhookImportDTO;
import cn.orionsec.ops.utils.Valid;
import java.util.Arrays;
import java.util.stream.Collectors;
public class WebhookValidator implements DataValidator {
private WebhookValidator() {
}
public static final WebhookValidator INSTANCE = new WebhookValidator();
public static final int NAME_MAX_LEN = 64;
public static final int URL_MAX_LEN = 2048;
public static final String NAME_EMPTY_MESSAGE = "名称不能为空";
public static final String NAME_LEN_MESSAGE = "名称长度不能大于 " + NAME_MAX_LEN + "";
public static final String TYPE_EMPTY_MESSAGE = "类型不能为空";
public static final String TYPE_MESSAGE = "类型只能为 " + Arrays.stream(WebhookType.values()).map(WebhookType::getLabel).collect(Collectors.toList());
public static final String URL_EMPTY_MESSAGE = "url不能为空";
public static final String URL_LEN_MESSAGE = "url长度不能大于 " + URL_MAX_LEN + "";
@Override
public void validData(Object o) {
if (o instanceof WebhookImportDTO) {
validImport((WebhookImportDTO) o);
}
}
/**
* 验证导入数据
*
* @param row row
*/
private void validImport(WebhookImportDTO row) {
String name = row.getName();
String type = row.getType();
String url = row.getUrl();
Valid.notBlank(name, NAME_EMPTY_MESSAGE);
Valid.validLengthLte(name, NAME_MAX_LEN, NAME_LEN_MESSAGE);
Valid.notBlank(type, TYPE_EMPTY_MESSAGE);
Valid.notNull(WebhookType.of(type), TYPE_MESSAGE);
Valid.notBlank(url, URL_EMPTY_MESSAGE);
Valid.validLengthLte(url, URL_MAX_LEN, URL_LEN_MESSAGE);
}
}

View File

@@ -0,0 +1,72 @@
package cn.orionsec.ops.service.api;
import cn.orionsec.ops.entity.request.data.DataClearRequest;
public interface DataClearService {
/**
* 清理 批量执行数据
*
* @param request request
* @return 删除数量
*/
Integer clearBatchExec(DataClearRequest request);
/**
* 清理 终端日志
*
* @param request request
* @return 删除数量
*/
Integer clearTerminalLog(DataClearRequest request);
/**
* 清理 调度记录
*
* @param request request
* @return 删除数量
*/
Integer clearSchedulerRecord(DataClearRequest request);
/**
* 清理 应用构建
*
* @param request request
* @return 删除数量
*/
Integer clearAppBuild(DataClearRequest request);
/**
* 清理 应用发布
*
* @param request request
* @return 删除数量
*/
Integer clearAppRelease(DataClearRequest request);
/**
* 清理 应用流水线
*
* @param request request
* @return 删除数量
*/
Integer clearAppPipeline(DataClearRequest request);
/**
* 清理 操作日志
*
* @param request request
* @return 删除数量
*/
Integer clearEventLog(DataClearRequest request);
/**
* 清理 机器报警历史
*
* @param request request
* @return 删除数量
*/
Integer clearMachineAlarmHistory(DataClearRequest request);
}

View File

@@ -0,0 +1,23 @@
package cn.orionsec.ops.service.api;
import cn.orionsec.ops.entity.importer.DataImportDTO;
public interface DataImportService {
/**
* 检查导入 token
*
* @param token token
* @return 导入数据
*/
DataImportDTO checkImportToken(String token);
/**
* 清空导入 token
*
* @param token token
*/
void clearImportToken(String token);
}

View File

@@ -0,0 +1,286 @@
package cn.orionsec.ops.service.impl;
import cn.orionsec.kit.lang.utils.time.Dates;
import cn.orionsec.ops.constant.Const;
import cn.orionsec.ops.constant.DataClearRange;
import cn.orionsec.ops.constant.app.BuildStatus;
import cn.orionsec.ops.constant.app.PipelineStatus;
import cn.orionsec.ops.constant.app.ReleaseStatus;
import cn.orionsec.ops.constant.command.ExecStatus;
import cn.orionsec.ops.constant.event.EventKeys;
import cn.orionsec.ops.constant.scheduler.SchedulerTaskStatus;
import cn.orionsec.ops.dao.*;
import cn.orionsec.ops.entity.domain.*;
import cn.orionsec.ops.entity.request.data.DataClearRequest;
import cn.orionsec.ops.service.api.DataClearService;
import cn.orionsec.ops.utils.Currents;
import cn.orionsec.ops.utils.EventParamsHolder;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Date;
@Service("dataClearService")
public class DataClearServiceImpl implements DataClearService {
@Resource
private CommandExecDAO commandExecDAO;
@Resource
private MachineTerminalLogDAO machineTerminalLogDAO;
@Resource
private SchedulerTaskRecordDAO schedulerTaskRecordDAO;
@Resource
private ApplicationBuildDAO applicationBuildDAO;
@Resource
private ApplicationReleaseDAO applicationReleaseDAO;
@Resource
private ApplicationPipelineTaskDAO applicationPipelineTaskDAO;
@Resource
private UserEventLogDAO userEventLogDAO;
@Resource
private MachineAlarmHistoryDAO machineAlarmHistoryDAO;
@Override
public Integer clearBatchExec(DataClearRequest request) {
if (!Currents.isAdministrator()) {
request.setICreated(Const.ENABLE);
}
// 基础删除条件
LambdaQueryWrapper<CommandExecDO> wrapper = new LambdaQueryWrapper<CommandExecDO>()
.ne(CommandExecDO::getExecStatus, ExecStatus.RUNNABLE.getStatus())
.eq(Const.ENABLE.equals(request.getICreated()), CommandExecDO::getUserId, Currents.getUserId());
// 设置删除筛选条件
this.setDeleteWrapper(commandExecDAO, wrapper,
CommandExecDO::getId,
CommandExecDO::getCreateTime,
CommandExecDO::getMachineId,
request);
int count = commandExecDAO.delete(wrapper);
// 设置日志参数
EventParamsHolder.addParams(request);
EventParamsHolder.addParam(EventKeys.COUNT, count);
return count;
}
@Override
public Integer clearTerminalLog(DataClearRequest request) {
LambdaQueryWrapper<MachineTerminalLogDO> wrapper = new LambdaQueryWrapper<>();
// 设置删除筛选条件
this.setDeleteWrapper(machineTerminalLogDAO, wrapper,
MachineTerminalLogDO::getId,
MachineTerminalLogDO::getCreateTime,
MachineTerminalLogDO::getMachineId,
request);
int count = machineTerminalLogDAO.delete(wrapper);
// 设置日志参数
EventParamsHolder.addParams(request);
EventParamsHolder.addParam(EventKeys.COUNT, count);
return count;
}
@Override
public Integer clearSchedulerRecord(DataClearRequest request) {
LambdaQueryWrapper<SchedulerTaskRecordDO> wrapper = new LambdaQueryWrapper<SchedulerTaskRecordDO>()
.ne(SchedulerTaskRecordDO::getTaskStatus, SchedulerTaskStatus.RUNNABLE.getStatus())
.eq(SchedulerTaskRecordDO::getTaskId, request.getRelId());
// 设置删除筛选条件
this.setDeleteWrapper(schedulerTaskRecordDAO, wrapper,
SchedulerTaskRecordDO::getId,
SchedulerTaskRecordDO::getCreateTime,
SchedulerTaskRecordDO::getTaskId,
request);
int count = schedulerTaskRecordDAO.delete(wrapper);
// 设置日志参数
EventParamsHolder.addParams(request);
EventParamsHolder.addParam(EventKeys.COUNT, count);
return count;
}
@Override
public Integer clearAppBuild(DataClearRequest request) {
Long userId = Currents.getUserId();
LambdaQueryWrapper<ApplicationBuildDO> wrapper = new LambdaQueryWrapper<ApplicationBuildDO>()
.ne(ApplicationBuildDO::getBuildStatus, BuildStatus.RUNNABLE.getStatus())
.eq(ApplicationBuildDO::getProfileId, request.getProfileId())
.eq(Const.ENABLE.equals(request.getICreated()), ApplicationBuildDO::getCreateUserId, userId);
// 设置筛选条件
this.setDeleteWrapper(applicationBuildDAO, wrapper,
ApplicationBuildDO::getId,
ApplicationBuildDO::getCreateTime,
ApplicationBuildDO::getAppId,
request);
int count = applicationBuildDAO.delete(wrapper);
// 设置日志参数
EventParamsHolder.addParams(request);
EventParamsHolder.addParam(EventKeys.COUNT, count);
return count;
}
@Override
public Integer clearAppRelease(DataClearRequest request) {
Long userId = Currents.getUserId();
LambdaQueryWrapper<ApplicationReleaseDO> wrapper = new LambdaQueryWrapper<ApplicationReleaseDO>()
.ne(ApplicationReleaseDO::getReleaseStatus, ReleaseStatus.RUNNABLE.getStatus())
.eq(ApplicationReleaseDO::getProfileId, request.getProfileId())
.eq(Const.ENABLE.equals(request.getICreated()), ApplicationReleaseDO::getCreateUserId, userId)
.eq(Const.ENABLE.equals(request.getIAudited()), ApplicationReleaseDO::getAuditUserId, userId)
.eq(Const.ENABLE.equals(request.getIExecute()), ApplicationReleaseDO::getReleaseUserId, userId);
// 设置筛选条件
this.setDeleteWrapper(applicationReleaseDAO, wrapper,
ApplicationReleaseDO::getId,
ApplicationReleaseDO::getCreateTime,
ApplicationReleaseDO::getAppId,
request);
int count = applicationReleaseDAO.delete(wrapper);
// 设置日志参数
EventParamsHolder.addParams(request);
EventParamsHolder.addParam(EventKeys.COUNT, count);
return count;
}
@Override
public Integer clearAppPipeline(DataClearRequest request) {
Long userId = Currents.getUserId();
LambdaQueryWrapper<ApplicationPipelineTaskDO> wrapper = new LambdaQueryWrapper<ApplicationPipelineTaskDO>()
.ne(ApplicationPipelineTaskDO::getExecStatus, PipelineStatus.RUNNABLE.getStatus())
.eq(ApplicationPipelineTaskDO::getProfileId, request.getProfileId())
.eq(Const.ENABLE.equals(request.getICreated()), ApplicationPipelineTaskDO::getCreateUserId, userId)
.eq(Const.ENABLE.equals(request.getIAudited()), ApplicationPipelineTaskDO::getAuditUserId, userId)
.eq(Const.ENABLE.equals(request.getIExecute()), ApplicationPipelineTaskDO::getExecUserId, userId);
// 设置筛选条件
this.setDeleteWrapper(applicationPipelineTaskDAO, wrapper,
ApplicationPipelineTaskDO::getId,
ApplicationPipelineTaskDO::getCreateTime,
ApplicationPipelineTaskDO::getPipelineId,
request);
int count = applicationPipelineTaskDAO.delete(wrapper);
// 设置日志参数
EventParamsHolder.addParams(request);
EventParamsHolder.addParam(EventKeys.COUNT, count);
return count;
}
@Override
public Integer clearEventLog(DataClearRequest request) {
LambdaQueryWrapper<UserEventLogDO> wrapper = new LambdaQueryWrapper<UserEventLogDO>()
.eq(UserEventLogDO::getExecResult, Const.ENABLE);
// 设置删除筛选条件
this.setDeleteWrapper(userEventLogDAO, wrapper,
UserEventLogDO::getId,
UserEventLogDO::getCreateTime,
UserEventLogDO::getEventClassify,
request);
int count = userEventLogDAO.delete(wrapper);
// 设置日志参数
EventParamsHolder.addParams(request);
EventParamsHolder.addParam(EventKeys.COUNT, count);
return count;
}
@Override
public Integer clearMachineAlarmHistory(DataClearRequest request) {
LambdaQueryWrapper<MachineAlarmHistoryDO> wrapper = new LambdaQueryWrapper<MachineAlarmHistoryDO>()
.eq(MachineAlarmHistoryDO::getMachineId, request.getMachineId());
// 设置删除筛选条件
this.setDeleteWrapper(machineAlarmHistoryDAO, wrapper,
MachineAlarmHistoryDO::getId,
MachineAlarmHistoryDO::getCreateTime,
MachineAlarmHistoryDO::getMachineId,
request);
int count = machineAlarmHistoryDAO.delete(wrapper);
// 设置日志参数
EventParamsHolder.addParams(request);
EventParamsHolder.addParam(EventKeys.COUNT, count);
return count;
}
/**
* 设置删除的筛选条件
*
* @param mapper mapper
* @param wrapper wrapper
* @param idGetterFun idGetterFun
* @param dateGetterFun dateGetterFun
* @param relGetterFun relGetterFun
* @param request request
* @param <T> <T>
*/
private <T> void setDeleteWrapper(BaseMapper<T> mapper,
LambdaQueryWrapper<T> wrapper,
SFunction<T, Long> idGetterFun,
SFunction<T, Date> dateGetterFun,
SFunction<T, ?> relGetterFun,
DataClearRequest request) {
if (DataClearRange.DAY.getRange().equals(request.getRange())) {
// 仅保留几天
Integer day = request.getReserveDay();
if (!day.equals(0)) {
this.setReverseDateWhere(wrapper, dateGetterFun, day);
}
} else if (DataClearRange.TOTAL.getRange().equals(request.getRange())) {
// 保留几条
Integer total = request.getReserveTotal();
if (!total.equals(0)) {
this.setReverseTotalWhere(mapper, wrapper, idGetterFun, total);
}
} else if (DataClearRange.REL_ID.getRange().equals(request.getRange())) {
// 删除机器id
wrapper.in(relGetterFun, request.getRelIdList());
}
}
/**
* 设置保留多少天的筛选条件
*
* @param wrapper wrapper
* @param dateGetterFun dateGetterFun
* @param day day
* @param <T> T
*/
private <T> void setReverseDateWhere(LambdaQueryWrapper<T> wrapper,
SFunction<T, Date> dateGetterFun,
Integer day) {
Date lessDayDate = Dates.stream().subDay(day).get();
wrapper.lt(dateGetterFun, lessDayDate);
}
/**
* 设置保留条数的筛选条件
*
* @param mapper mapper
* @param wrapper wrapper
* @param idGetterFun idGetterFun
* @param total total
* @param <T> T
*/
private <T> void setReverseTotalWhere(BaseMapper<T> mapper,
LambdaQueryWrapper<T> wrapper,
SFunction<T, Long> idGetterFun,
Integer total) {
// 查询删除的最大id
LambdaQueryWrapper<T> maxIdWrapper = wrapper.clone()
.orderByDesc(idGetterFun)
.last(Const.LIMIT + Const.SPACE + total + ", 1");
T maxEntity = mapper.selectOne(maxIdWrapper);
// 未查询到则代表条数不满足, 设置一个 false 条件 从而达到不执行的目的
if (maxEntity == null) {
wrapper.eq(idGetterFun, Const.L_N_1);
return;
}
Long maxId = idGetterFun.apply(maxEntity);
// 设置最大id阈值
wrapper.le(idGetterFun, maxId);
}
}

View File

@@ -0,0 +1,48 @@
package cn.orionsec.ops.service.impl;
import cn.orionsec.kit.lang.utils.Exceptions;
import cn.orionsec.kit.lang.utils.Strings;
import cn.orionsec.ops.constant.KeyConst;
import cn.orionsec.ops.constant.MessageConst;
import cn.orionsec.ops.entity.dto.user.UserDTO;
import cn.orionsec.ops.entity.importer.DataImportDTO;
import cn.orionsec.ops.service.api.DataImportService;
import cn.orionsec.ops.utils.Currents;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Date;
@Slf4j
@Service("dataImportService")
public class DataImportServiceImpl implements DataImportService {
@Resource
private RedisTemplate<String, String> redisTemplate;
@Override
public DataImportDTO checkImportToken(String token) {
UserDTO user = Currents.getUser();
// 查询缓存
String data = redisTemplate.opsForValue().get(Strings.format(KeyConst.DATA_IMPORT_TOKEN, user.getId(), token));
if (Strings.isEmpty(data)) {
throw Exceptions.argument(MessageConst.OPERATOR_TIMEOUT);
}
// 设置用户数据
DataImportDTO importData = JSON.parseObject(data, DataImportDTO.class);
importData.setUserId(user.getId());
importData.setUserName(user.getUsername());
importData.setImportTime(new Date());
return importData;
}
@Override
public void clearImportToken(String token) {
redisTemplate.delete(Strings.format(KeyConst.DATA_IMPORT_TOKEN, Currents.getUserId(), token));
}
}