diff --git a/orion-ops-service/src/main/java/com/orion/ops/consts/app/ApplicationVcsFieldConst.java b/orion-ops-service/src/main/java/com/orion/ops/consts/app/ApplicationVcsFieldConst.java new file mode 100644 index 00000000..17de6102 --- /dev/null +++ b/orion-ops-service/src/main/java/com/orion/ops/consts/app/ApplicationVcsFieldConst.java @@ -0,0 +1,129 @@ +package com.orion.ops.consts.app; + +import com.orion.ops.entity.dto.importer.ApplicationVcsImportDTO; +import com.orion.ops.utils.Valid; +import com.orion.ops.utils.ValueMix; +import com.orion.utils.Exceptions; +import com.orion.utils.Strings; + +/** + * 应用版本仓库表字段常量 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2022/6/2 10:02 + */ +public class ApplicationVcsFieldConst { + + private ApplicationVcsFieldConst() { + } + + 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 = "认证方式只能为 " + VcsAuthType.PASSWORD.getLabel() + "和" + VcsAuthType.TOKEN.getLabel(); + + public static final String TOKEN_TYPE_EMPTY_MESSAGE = "认证方式为" + VcsAuthType.TOKEN.getLabel() + "时 令牌类型不能为空"; + + public static final String TOKEN_TYPE_VALUE_MESSAGE = "令牌类型只能为 " + VcsTokenType.GITHUB.getLabel() + "," + VcsTokenType.GITEE.getLabel() + "," + VcsTokenType.GITLAB.getLabel(); + + 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 = "令牌类型为 " + VcsTokenType.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 + "位"; + + /** + * 验证数据合法性 + * + * @param o o + */ + public static void validData(Object o) { + if (o instanceof ApplicationVcsImportDTO) { + validImport((ApplicationVcsImportDTO) o); + } + } + + /** + * 验证导入数据 + * + * @param row row + */ + public static void validImport(ApplicationVcsImportDTO 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); + VcsAuthType authType = VcsAuthType.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 (VcsAuthType.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); + VcsTokenType tokenType = VcsTokenType.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 (VcsTokenType.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); + } + } + +} diff --git a/orion-ops-service/src/main/java/com/orion/ops/consts/export/ImportType.java b/orion-ops-service/src/main/java/com/orion/ops/consts/export/ImportType.java index 57a56f42..089fba80 100644 --- a/orion-ops-service/src/main/java/com/orion/ops/consts/export/ImportType.java +++ b/orion-ops-service/src/main/java/com/orion/ops/consts/export/ImportType.java @@ -2,6 +2,7 @@ package com.orion.ops.consts.export; import com.orion.ops.consts.app.ApplicationFieldConst; import com.orion.ops.consts.app.ApplicationProfileFieldConst; +import com.orion.ops.consts.app.ApplicationVcsFieldConst; import com.orion.ops.consts.command.CommandTemplateFieldConst; import com.orion.ops.consts.machine.MachineFieldConst; import com.orion.ops.consts.machine.MachineProxyFieldConst; @@ -54,7 +55,7 @@ public enum ImportType { * 导入日志文件 */ MACHINE_TAIL_FILE(130, - "/templates/machine-tail-file-import-template.xlsx", + "/templates/tail-file-import-template.xlsx", "日志文件导入模板.xlsx", MachineTailFileImportDTO.class, FileTailFieldConst::validData, @@ -93,7 +94,7 @@ public enum ImportType { "/templates/app-vcs-import-template.xlsx", "应用仓库导入模板.xlsx", ApplicationVcsImportDTO.class, - FileTailFieldConst::validData, + ApplicationVcsFieldConst::validData, ApplicationVcsDO.class, MessageType.APP_VCS_IMPORT_SUCCESS, MessageType.APP_VCS_IMPORT_FAILURE), diff --git a/orion-ops-service/src/main/java/com/orion/ops/service/impl/DataImportServiceImpl.java b/orion-ops-service/src/main/java/com/orion/ops/service/impl/DataImportServiceImpl.java index ac3905b8..f4cb8bb9 100644 --- a/orion-ops-service/src/main/java/com/orion/ops/service/impl/DataImportServiceImpl.java +++ b/orion-ops-service/src/main/java/com/orion/ops/service/impl/DataImportServiceImpl.java @@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.serializer.SerializerFeature; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.toolkit.support.SFunction; import com.orion.id.UUIds; import com.orion.office.excel.reader.ExcelBeanReader; import com.orion.ops.consts.KeyConst; @@ -44,6 +45,7 @@ import java.io.File; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Optional; import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; import java.util.function.Consumer; @@ -110,18 +112,8 @@ public class DataImportServiceImpl implements DataImportService { // 检查数据合法性 this.validImportRows(ImportType.MACHINE, rows); // 通过唯一标识查询机器 - List presentMachines; - List tagList = rows.stream() - .filter(s -> Objects.isNull(s.getIllegalMessage())) - .map(MachineInfoImportDTO::getTag) - .collect(Collectors.toList()); - if (tagList.isEmpty()) { - presentMachines = Lists.empty(); - } else { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper() - .in(MachineInfoDO::getMachineTag, tagList); - presentMachines = machineInfoDAO.selectList(wrapper); - } + List presentMachines = this.getImportRowsPresentValues(rows, MachineInfoImportDTO::getTag, + machineInfoDAO, MachineInfoDO::getMachineTag); // 检查数据是否存在 this.checkImportRowsPresent(rows, MachineInfoImportDTO::getTag, presentMachines, MachineInfoDO::getMachineTag, MachineInfoDO::getId); @@ -149,18 +141,8 @@ public class DataImportServiceImpl implements DataImportService { MachineTailFileImportDTO::setMachineId, MessageConst.UNKNOWN_MACHINE_TAG); // 通过别名查询文件 - List presentFiles; - List nameList = rows.stream() - .filter(s -> Objects.isNull(s.getIllegalMessage())) - .map(MachineTailFileImportDTO::getName) - .collect(Collectors.toList()); - if (nameList.isEmpty()) { - presentFiles = Lists.empty(); - } else { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper() - .in(FileTailListDO::getAliasName, nameList); - presentFiles = fileTailListDAO.selectList(wrapper); - } + List presentFiles = this.getImportRowsPresentValues(rows, MachineTailFileImportDTO::getName, + fileTailListDAO, FileTailListDO::getAliasName); // 检查数据是否存在 this.checkImportRowsPresent(rows, MachineTailFileImportDTO::getName, presentFiles, FileTailListDO::getAliasName, FileTailListDO::getId); @@ -173,18 +155,9 @@ public class DataImportServiceImpl implements DataImportService { // 检查数据合法性 this.validImportRows(ImportType.PROFILE, rows); // 通过唯一标识查询环境 - List presentProfiles; - List tagList = rows.stream() - .filter(s -> Objects.isNull(s.getIllegalMessage())) - .map(ApplicationProfileImportDTO::getTag) - .collect(Collectors.toList()); - if (tagList.isEmpty()) { - presentProfiles = Lists.empty(); - } else { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper() - .in(ApplicationProfileDO::getProfileTag, tagList); - presentProfiles = applicationProfileDAO.selectList(wrapper); - } + List presentProfiles = this.getImportRowsPresentValues(rows, + ApplicationProfileImportDTO::getTag, + applicationProfileDAO, ApplicationProfileDO::getProfileTag); // 检查数据是否存在 this.checkImportRowsPresent(rows, ApplicationProfileImportDTO::getTag, presentProfiles, ApplicationProfileDO::getProfileTag, ApplicationProfileDO::getId); @@ -204,18 +177,9 @@ public class DataImportServiceImpl implements DataImportService { ApplicationImportDTO::setVcsId, MessageConst.UNKNOWN_APP_VCS); // 通过唯一标识查询应用 - List presentApps; - List tagList = rows.stream() - .filter(s -> Objects.isNull(s.getIllegalMessage())) - .map(ApplicationImportDTO::getTag) - .collect(Collectors.toList()); - if (tagList.isEmpty()) { - presentApps = Lists.empty(); - } else { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper() - .in(ApplicationInfoDO::getAppTag, tagList); - presentApps = applicationInfoDAO.selectList(wrapper); - } + List presentApps = this.getImportRowsPresentValues(rows, + ApplicationImportDTO::getTag, + applicationInfoDAO, ApplicationInfoDO::getAppTag); // 检查数据是否存在 this.checkImportRowsPresent(rows, ApplicationImportDTO::getTag, presentApps, ApplicationInfoDO::getAppTag, ApplicationInfoDO::getId); @@ -225,7 +189,17 @@ public class DataImportServiceImpl implements DataImportService { @Override public DataImportCheckVO checkAppVcsImportData(List rows) { - return null; + // 检查数据合法性 + this.validImportRows(ImportType.VCS, rows); + // 通过唯一标识查询应用 + List presentVcsList = this.getImportRowsPresentValues(rows, + ApplicationVcsImportDTO::getName, + applicationVcsDAO, ApplicationVcsDO::getVcsName); + // 检查数据是否存在 + this.checkImportRowsPresent(rows, ApplicationVcsImportDTO::getName, + presentVcsList, ApplicationVcsDO::getVcsName, ApplicationVcsDO::getId); + // 设置导入检查数据 + return this.setImportCheckRows(ImportType.VCS, rows); } @Override @@ -233,18 +207,9 @@ public class DataImportServiceImpl implements DataImportService { // 检查数据合法性 this.validImportRows(ImportType.COMMAND_TEMPLATE, rows); // 通过名称查询模板 - List presentTemplates; - List nameList = rows.stream() - .filter(s -> Objects.isNull(s.getIllegalMessage())) - .map(CommandTemplateImportDTO::getName) - .collect(Collectors.toList()); - if (nameList.isEmpty()) { - presentTemplates = Lists.empty(); - } else { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper() - .in(CommandTemplateDO::getTemplateName, nameList); - presentTemplates = commandTemplateDAO.selectList(wrapper); - } + List presentTemplates = this.getImportRowsPresentValues(rows, + CommandTemplateImportDTO::getName, + commandTemplateDAO, CommandTemplateDO::getTemplateName); // 检查数据是否存在 this.checkImportRowsPresent(rows, CommandTemplateImportDTO::getName, presentTemplates, CommandTemplateDO::getTemplateName, CommandTemplateDO::getId); @@ -256,7 +221,15 @@ public class DataImportServiceImpl implements DataImportService { @Override public void importMachineInfoData(DataImportDTO importData) { - this.doImportData(importData, machineInfoDAO); + this.doImportData(importData, machineInfoDAO, v -> { + // ignore + }, v -> { + // 检查是否有代理 + Optional.ofNullable(v.getId()) + .map(machineInfoDAO::selectById) + .map(MachineInfoDO::getProxyId) + .ifPresent(v::setProxyId); + }); } @Override @@ -406,6 +379,35 @@ public class DataImportServiceImpl implements DataImportService { } } + /** + * 获取导入行已存在的数据 + * + * @param rows rows + * @param rowSymbolGetter rowSymbolGetter + * @param mapper mapper + * @param domainSymbolGetter domainSymbolGetter + * @param row type + * @param domain type + * @return present domain + */ + private List getImportRowsPresentValues(List rows, + Function rowSymbolGetter, + BaseMapper mapper, + SFunction domainSymbolGetter) { + List symbolList = rows.stream() + .filter(s -> Objects.isNull(s.getIllegalMessage())) + .map(rowSymbolGetter) + .collect(Collectors.toList()); + if (symbolList.isEmpty()) { + return Lists.empty(); + } else { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper() + .in(domainSymbolGetter, symbolList); + return mapper.selectList(wrapper); + } + } + + /** * 检查导入行是否存在 * diff --git a/orion-ops-service/src/main/resources/templates/app-profile-import-template.xlsx b/orion-ops-service/src/main/resources/templates/app-profile-import-template.xlsx new file mode 100644 index 00000000..8fabfc58 Binary files /dev/null and b/orion-ops-service/src/main/resources/templates/app-profile-import-template.xlsx differ diff --git a/orion-ops-service/src/main/resources/templates/app-vcs-import-template.xlsx b/orion-ops-service/src/main/resources/templates/app-vcs-import-template.xlsx new file mode 100644 index 00000000..526bace5 Binary files /dev/null and b/orion-ops-service/src/main/resources/templates/app-vcs-import-template.xlsx differ diff --git a/orion-ops-service/src/main/resources/templates/application-import-template.xlsx b/orion-ops-service/src/main/resources/templates/application-import-template.xlsx new file mode 100644 index 00000000..4a3b74b1 Binary files /dev/null and b/orion-ops-service/src/main/resources/templates/application-import-template.xlsx differ diff --git a/orion-ops-service/src/main/resources/templates/command-template-import-template.xlsx b/orion-ops-service/src/main/resources/templates/command-template-import-template.xlsx new file mode 100644 index 00000000..912a5ff3 Binary files /dev/null and b/orion-ops-service/src/main/resources/templates/command-template-import-template.xlsx differ diff --git a/orion-ops-service/src/main/resources/templates/machine-import-template.xlsx b/orion-ops-service/src/main/resources/templates/machine-import-template.xlsx index 092eaf6e..a9595b4b 100644 Binary files a/orion-ops-service/src/main/resources/templates/machine-import-template.xlsx and b/orion-ops-service/src/main/resources/templates/machine-import-template.xlsx differ diff --git a/orion-ops-service/src/main/resources/templates/machine-proxy-import-template.xlsx b/orion-ops-service/src/main/resources/templates/machine-proxy-import-template.xlsx new file mode 100644 index 00000000..73f89ac2 Binary files /dev/null and b/orion-ops-service/src/main/resources/templates/machine-proxy-import-template.xlsx differ diff --git a/orion-ops-service/src/main/resources/templates/tail-file-import-template.xlsx b/orion-ops-service/src/main/resources/templates/tail-file-import-template.xlsx new file mode 100644 index 00000000..a5906c5b Binary files /dev/null and b/orion-ops-service/src/main/resources/templates/tail-file-import-template.xlsx differ