diff --git a/dependencies/pom.xml b/dependencies/pom.xml
index e90b5640..728d2d06 100644
--- a/dependencies/pom.xml
+++ b/dependencies/pom.xml
@@ -89,6 +89,7 @@
1.5.8
2.9.3
2.3.0
+
@@ -650,9 +651,9 @@
- org.pf4j
- pf4j-spring
- ${pf4j-spring.version}
+ io.cloudsoft.windows
+ winrm4j
+ 0.12.0
@@ -761,6 +762,12 @@
${resilience4j-circuitbreaker.version}
+
+
+ io.cloudsoft.windows
+ winrm4j
+ 0.12.3
+
diff --git a/modules/module-ci-process-biz/pom.xml b/modules/module-ci-process-biz/pom.xml
index bb5f9e2e..12740281 100644
--- a/modules/module-ci-process-biz/pom.xml
+++ b/modules/module-ci-process-biz/pom.xml
@@ -29,6 +29,36 @@
cd.casic.boot
spring-boot-starter-biz-tenant
+
+
+ io.cloudsoft.windows
+ winrm4j
+
+
+ com.jcraft
+ jsch
+
+
+ com.antherd
+ sm-crypto
+ 0.3.2
+
+
+ com.hierynomus
+ sshj
+ 0.32.0
+
+
+ net.sf.expectit
+ expectit-core
+ 0.9.0
+
+
+ io.cloudsoft.windows
+ winrm4j
+ 0.12.0
+
+
\ No newline at end of file
diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/constant/CommandConstant.java b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/constant/CommandConstant.java
new file mode 100644
index 00000000..ba447f33
--- /dev/null
+++ b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/constant/CommandConstant.java
@@ -0,0 +1,13 @@
+package cd.casic.ci.process.constant;
+
+/**
+ * 命令常量
+ * @author cww
+ * @date 2022/6/17
+ */
+public class CommandConstant {
+ public static final String ENTER = "\r\n";
+ public static final String EXIT = "exit" + "\r\n";
+ public static final String SOURCE = "source-";
+ public static final String TARGET = "target-";
+}
diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/constant/PipelineFinalConstant.java b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/constant/PipelineFinalConstant.java
deleted file mode 100644
index 75c808b1..00000000
--- a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/constant/PipelineFinalConstant.java
+++ /dev/null
@@ -1,220 +0,0 @@
-package cd.casic.ci.process.constant;
-
-public class PipelineFinalConstant {
-
- /**
- * 项目名称
- */
- public static final String appName = "arbess";
-
- /**
- * DEFAULT
- */
- public static final String DEFAULT = "default";
-
- /**
- * 流水线文件系统
- */
- public static final String MATFLOW_WORKSPACE = "/source";
-
- public static final String MATFLOW_LOGS = "/artifact";
-
-
- /**
- * 流水线运行状态
- */
- //流水线运行状态
- public static final String RUN_SUCCESS = "success";
-
- public static final String RUN_ERROR = "error";
-
- public static final String RUN_WAIT = "wait";
-
- public static final String RUN_HALT = "halt";
-
- public static final String RUN_RUN = "run";
-
- public static final String RUN_SUSPEND = "suspend";
-
-
- /**
- * 系统编码
- */
- //字节编码
- public static final String UTF_8 = "UTF-8";
-
- public static final String GBK = "GBK";
-
-
- /**
- * 消息
- */
- //消息发送类型
- public static final String MES_PIPELINE_RUN = "PIPELINE_RUN";
-
- //消息发送方式
- public static final String MES_SEND_SITE = "site";
- public static final String MES_SEND_EMAIL = "email";
- public static final String MES_SEND_DINGDING = "dingding";
- public static final String MES_SEND_WECHAT = "qywechat";
- public static final String MES_SEND_SMS = "sms";
-
- //消息通知方案
- public static final String MES_UPDATE = "MF_MES_TYPE_UPDATE";
- public static final String MES_DELETE = "MF_MES_TYPE_DELETE";
- public static final String MES_CREATE = "MF_MES_TYPE_CREATE";
- public static final String MES_RUN = "MF_MES_TYPE_RUN";
-
-
- // 日志类型
- public static final String LOG_TYPE_CREATE = "MF_LOG_TYPE_CREATE";
-
- public static final String LOG_TYPE_DELETE = "MF_LOG_TYPE_DELETE";
-
- public static final String LOG_TYPE_UPDATE = "MF_LOG_TYPE_UPDATE";
-
- public static final String LOG_TYPE_RUN = "MF_LOG_TYPE_RUN";
-
-
- public static final String CREATE_LINK = "/pipeline/${pipelineId}/config";
-
- public static final String DELETE_LINK = "/pipeline/${pipelineId}/delete";
-
- public static final String UPDATE_LINK = "/pipeline/${pipelineId}/set/info";
-
- public static final String RUN_LINK = "/pipeline/${pipelineId}/history/${instanceId}";
-
-
- /**
- * 构建产物信息
- */
- // 默认制品地址
- public static final String PROJECT_DEFAULT_ADDRESS = "${PROJECT_DEFAULT_ADDRESS}";
-
- public static final String DEFAULT_ARTIFACT_ADDRESS = "DEFAULT_ARTIFACT_ADDRESS";
-
- // 默认制品
- public static final String DEFAULT_ARTIFACT_NAME = "DEFAULT_ARTIFACT_NAME";
-
- // Docker制品
- public static final String DEFAULT_ARTIFACT_DOCKER = "DEFAULT_ARTIFACT_DOCKER";
-
- // Docker名称
- public static final String DEFAULT_ARTIFACT_DOCKER_NAME = "DEFAULT_ARTIFACT_DOCKER_NAME";
-
-
- // 默认源码位置
- public static final String DEFAULT_CODE_ADDRESS = "${DEFAULT_CODE_ADDRESS}";
-
- public static final String DEFAULT_TYPE = "string";
-
- /**
- * 默认命令
- */
- public static final String TEST_DEFAULT_ORDER = "mvn test";
- public static final String MAVEN_DEFAULT_ORDER = "mvn clean package";
- public static final String NODE_DEFAULT_ORDER = "npm install";
- public static final String DOCKER_DEFAULT_ORDER = "docker image build -t default .";
-
- /**
- * 文件信息
- */
- public static final String FILE_TEMP_PREFIX = "temp";
- public static final String FILE_TYPE_TXT = ".txt";
- public static final String FILE_TYPE_SH = ".sh";
- public static final String FILE_TYPE_BAT = ".bat";
-
- /**
- * 系统任务类型
- */
-
- // 源码应用类型
- public static final String TASK_TYPE_CODE = "code";
- public static final String TASK_CODE_GIT = "git";
- public static final String TASK_CODE_GITLAB = "gitlab";
- public static final String TASK_CODE_GITHUB = "github";
- public static final String TASK_CODE_GITEE = "gitee";
- public static final String TASK_CODE_SVN = "svn";
- public static final String TASK_CODE_XCODE = "gitpuk";
- public static final String TASK_CODE_DEFAULT_BRANCH = "master";
-
-
- // 构建应用类型
- public static final String TASK_TYPE_BUILD = "build";
- public static final String TASK_BUILD_MAVEN = "maven";
- public static final String TASK_BUILD_NODEJS = "nodejs";
-
- public static final String TASK_BUILD_DOCKER = "build_docker";
-
-
- // 测试应用类型
- public static final String TASK_TYPE_TEST = "test";
- public static final String TASK_TEST_MAVENTEST = "maventest";
- public static final String TASK_TEST_TESTON = "testhubo";
-
-
- // 部署应用类型
- public static final String TASK_TYPE_DEPLOY = "deploy";
- public static final String TASK_DEPLOY_LINUX = "liunx";
- public static final String TASK_DEPLOY_DOCKER = "docker";
- public static final String TASK_DEPLOY_K8S = "k8s";
-
-
- // 推送制品应用类型
- public static final String TASK_TYPE_ARTIFACT = "artifact";
- public static final String TASK_ARTIFACT_MAVEN = "artifact_maven";
- public static final String TASK_ARTIFACT_NODEJS = "artifact_nodejs";
- public static final String TASK_ARTIFACT_DOCKER = "artifact_docker";
-
-
- // 制品拉取应用类型
- public static final String TASK_TYPE_PULL = "pull";
- public static final String TASK_PULL_MAVEN = "pull_maven";
- public static final String TASK_PULL_NODEJS = "pull_nodejs";
- public static final String TASK_PULL_DOCKER = "pull_docker";
-
- // 制品推送应用方式
- public static final String TASK_ARTIFACT_XPACK = "hadess";
- public static final String TASK_ARTIFACT_SSH = "ssh";
- public static final String TASK_ARTIFACT_NEXUS = "nexus";
-
- // 代码扫描应用类型
- public static final String TASK_TYPE_CODESCAN = "codescan";
- public static final String TASK_CODESCAN_SONAR = "sonar";
- public static final String TASK_CODESCAN_SPOTBUGS = "spotbugs";
-
- // 消息应用类型
- public static final String TASK_TYPE_MESSAGE = "message";
- public static final String TASK_MESSAGE_MSG = "message";
-
- // 脚本应用类型
- public static final String TASK_TYPE_SCRIPT = "script";
- public static final String TASK_SCRIPT_SHELL = "shell";
- public static final String TASK_SCRIPT_BAT = "bat";
-
-
- //触发器
- public static final String TRIGGER_SCHEDULED = "scheduled";
-
-
- public static final String SIZE_TYPE_MB = "MB";
-
- public static final int DEFAULT_SIZE = 2;
-
-
- public static final String SIZE_TYPE_GB = "GB";
-
-
- public static final Integer DEFAULT_CLEAN_CACHE_DAY = 7;
-
-
-
-
-
-
-
-
-
-
-
-}
diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/engine/constant/DIYImageExecuteCommandConstant.java b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/engine/constant/DIYImageExecuteCommandConstant.java
new file mode 100644
index 00000000..6b2b6257
--- /dev/null
+++ b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/engine/constant/DIYImageExecuteCommandConstant.java
@@ -0,0 +1,13 @@
+package cd.casic.ci.process.engine.constant;
+
+public class DIYImageExecuteCommandConstant {
+ /**
+ * 机器ID
+ */
+ public static final String MACHINE_ID ="machineId";
+ /**
+ * 人工卡点命令脚本
+ */
+ public static final String COMMAND_SCRIPT ="commandScript";
+ public static final String STATUS_CODE = "statusCode";
+}
diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/engine/manager/WorkerManager.java b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/engine/manager/WorkerManager.java
index 47d976c3..b31d67e9 100644
--- a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/engine/manager/WorkerManager.java
+++ b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/engine/manager/WorkerManager.java
@@ -1,6 +1,11 @@
package cd.casic.ci.process.engine.manager;
+
+import cd.casic.ci.process.engine.message.TaskRunMessage;
+import cd.casic.framework.mq.redis.core.stream.AbstractRedisStreamMessageListener;
+import org.springframework.context.ApplicationContextAware;
+
/**
* 负责监听队列,找到ContextManager获取runContext,然后实际执行
* */
-public interface WorkerManager {
+public abstract class WorkerManager extends AbstractRedisStreamMessageListener implements ApplicationContextAware {
}
diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/engine/manager/impl/DefaultWorkerManager.java b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/engine/manager/impl/DefaultWorkerManager.java
index df8163d6..dab5abdc 100644
--- a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/engine/manager/impl/DefaultWorkerManager.java
+++ b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/engine/manager/impl/DefaultWorkerManager.java
@@ -1,9 +1,15 @@
package cd.casic.ci.process.engine.manager.impl;
import cd.casic.ci.common.pipeline.annotation.Plugin;
+import cd.casic.ci.process.engine.enums.ContextStateEnum;
+import cd.casic.ci.process.engine.manager.RunContextManager;
+import cd.casic.ci.process.engine.manager.WorkerManager;
import cd.casic.ci.process.engine.message.TaskRunMessage;
+import cd.casic.ci.process.engine.runContext.BaseRunContext;
import cd.casic.ci.process.engine.worker.BaseWorker;
import cd.casic.ci.process.process.dataObject.task.PipTask;
+import cd.casic.framework.commons.exception.ServiceException;
+import cd.casic.framework.commons.exception.enums.GlobalErrorCodeConstants;
import cd.casic.framework.mq.redis.core.stream.AbstractRedisStreamMessageListener;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
@@ -27,13 +33,15 @@ import java.util.Set;
@Component
@Slf4j
-public class DefaultWorkerManager extends AbstractRedisStreamMessageListener implements ApplicationContextAware {
+public class DefaultWorkerManager extends WorkerManager {
private static final String basePackage = "cd.casic.ci.process.engine.worker";
private Set candidates;
private ApplicationContext applicationContext;
private Map taskTypeWorkerMap = null;
@Resource
private ThreadPoolTaskExecutor workerExecutor;
+ @Resource
+ private RunContextManager contextManager;
private void setTaskTypeWorker(Map taskTypeWorker) {
this.taskTypeWorkerMap = taskTypeWorker;
@@ -70,13 +78,22 @@ public class DefaultWorkerManager extends AbstractRedisStreamMessageListener taskProperties = taskDef.getTaskProperties();
+ Object commandScriptObj = taskProperties.get(DIYImageExecuteCommandConstant.COMMAND_SCRIPT);
+ Object machineIdObj = taskProperties.get(DIYImageExecuteCommandConstant.MACHINE_ID);
+ String commandScript = commandScriptObj instanceof String ? ((String) commandScriptObj) : null;
+ Long machineId = null;
+ try {
+ machineId=Long.valueOf(String.valueOf(machineIdObj));
+ } catch (NumberFormatException e) {
+ log.error("缺少参数:{}",DIYImageExecuteCommandConstant.MACHINE_ID);
+ }
+ if (StringUtils.isEmpty(commandScript) ||machineIdObj == null) {
+ throw new ServiceException(GlobalErrorCodeConstants.PIPELINE_ERROR.getCode(),"缺少参数");
+ }
+
+ try {
+ //将节点的配置信息反编译成对象
+ log.info("构建脚本" + commandScript);
+
+ //如果machineId为0,则说明该节点没有配置机器,则使用开始节点的机器
+
+ //获取机器
+ MachineInfo machineInfoDO = this.getMachineInfoService().getById(machineId);
+ statusCode = shell(machineInfoDO,
+ "echo \"自定义镜像执行命令\"",
+ commandScript
+ );
+ } catch (Exception e) {
+ String errorMessage = "该节点配置信息为空,请先配置该节点信息" + "\r\n";
+// errorHandle(e, errorMessage);
+ }
+ if (statusCode == 0) {
+// log.info("{}节点执行完成", getName());
+ } else {
+// log.error("{}节点执行失败", getName());
+ }
+ context.getLocalVariables().put(DIYImageExecuteCommandConstant.STATUS_CODE,statusCode);
+ }
+ }
+}
diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/engine/worker/SshWorker.java b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/engine/worker/SshWorker.java
new file mode 100644
index 00000000..6eb08b9b
--- /dev/null
+++ b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/engine/worker/SshWorker.java
@@ -0,0 +1,81 @@
+package cd.casic.ci.process.engine.worker;
+
+import cd.casic.ci.process.constant.CommandConstant;
+import cd.casic.ci.process.enums.MachineSystemEnum;
+import cd.casic.ci.process.process.dataObject.machine.MachineInfo;
+import cd.casic.ci.process.ssh.SshClient;
+import cd.casic.ci.process.ssh.SshClientFactory;
+import cd.casic.ci.process.ssh.WinRMHelper;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.Arrays;
+import java.util.List;
+@Slf4j
+public abstract class SshWorker extends BaseWorker{
+ /**
+ * 执行shell命令
+ * @param machineInfo 机器
+ * @param commands 命令
+ * @return 0 成功;其他值 失败
+ */
+ public int shell(MachineInfo machineInfo, String... commands) {
+ List commandList = Arrays.asList(commands);
+ if(MachineSystemEnum.WINDOWS.getSystem().equals(machineInfo.getOsSystem())){
+ return powerShell(machineInfo, commandList);
+ }
+// NodeLogger nodeLogger = nodeLoggerThreadLocal.get();
+ int statusCode = -1;
+// String loggerUuid = nodeLogger.getLoggerUuid();
+// String nodeUuid = nodeLogger.getNodeUuid();
+ //loggerUuid得转换成String类型,才能生成key,然后才能通过websocket实时推送节点执行日志
+ SshClient ssh = null;
+ try {
+ ssh = SshClientFactory.createSsh(machineInfo);
+ //执行命令,并且把命令的执行回传到前端
+ statusCode = ssh.execNew(commandList, var -> {
+ // TODO 记录日志
+// loggerService.sendMessage(key, var);
+// nodeLogger.append(var);
+ });
+ log.info("exit-status: " + statusCode);
+ //主动释放当前socket连接
+// loggerService.close(key);
+ } catch (Exception e) {
+ String errorMessage = "与机器建立SSH连接出错" + CommandConstant.ENTER;
+// errorHandle(e, errorMessage);
+ } finally {
+ if(ssh!=null) {
+ ssh.disconnect();
+ }
+ }
+ return statusCode;
+ }
+ /**
+ * 执行shell命令
+ * @param machineInfo 机器
+ * @param commandList 命令
+ * @return 0 成功;其他值 失败
+ */
+ public int powerShell(MachineInfo machineInfo, List commandList) {
+ int statusCode = -1;
+ //loggerUuid得转换成String类型,才能生成key,然后才能通过websocket实时推送节点执行日志
+
+ try {
+ WinRMHelper winRmHelper = new WinRMHelper(machineInfo);
+ statusCode = winRmHelper.executePs(commandList, var ->{
+ log.info("================================================================" + var);
+ // TODO 记录日志
+// loggerService.sendMessage(key, var);
+// nodeLogger.append(var);
+ });
+
+ log.info("exit-status: " + statusCode);
+ //主动释放当前socket连接
+
+ } catch (Exception e) {
+ String errorMessage = "与Window机器建立winrm连接出错" + CommandConstant.ENTER;
+// errorHandle(e, errorMessage);
+ }
+ return statusCode;
+ }
+}
diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/enums/MachineSystemEnum.java b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/enums/MachineSystemEnum.java
new file mode 100644
index 00000000..69998036
--- /dev/null
+++ b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/enums/MachineSystemEnum.java
@@ -0,0 +1,27 @@
+package cd.casic.ci.process.enums;
+
+/**
+ * 枚举
+ * @author herenbin
+ * @date 2023/6/25
+ */
+public enum MachineSystemEnum {
+ /**
+ * Linux
+ */
+ LINUX("Linux"),
+ /**
+ * Windows
+ */
+ WINDOWS("Windows");
+
+ private final String system;
+
+ MachineSystemEnum(String system) {
+ this.system = system;
+ }
+
+ public String getSystem() {
+ return system;
+ }
+}
diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/dal/machine/MachineInfoDao.java b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/dal/machine/MachineInfoDao.java
new file mode 100644
index 00000000..dd39fc8b
--- /dev/null
+++ b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/dal/machine/MachineInfoDao.java
@@ -0,0 +1,15 @@
+package cd.casic.ci.process.process.dal.machine;
+
+
+import cd.casic.ci.process.process.dataObject.machine.MachineInfo;
+import cd.casic.framework.mybatis.core.mapper.BaseMapperX;
+
+
+/**
+ * 机器信息表
+ *
+ * @author herenbin
+ * @date 2022-09-27 10:10:37
+ */
+public interface MachineInfoDao extends BaseMapperX {
+}
\ No newline at end of file
diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/dataObject/base/PipBaseElement.java b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/dataObject/base/PipBaseElement.java
index fa02ee74..1069a794 100644
--- a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/dataObject/base/PipBaseElement.java
+++ b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/dataObject/base/PipBaseElement.java
@@ -4,7 +4,9 @@ import cd.casic.framework.commons.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
+import lombok.EqualsAndHashCode;
+@EqualsAndHashCode(callSuper = true)
@Data
public class PipBaseElement extends BaseDO {
/**
diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/dataObject/machine/MachineInfo.java b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/dataObject/machine/MachineInfo.java
new file mode 100644
index 00000000..56f48c08
--- /dev/null
+++ b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/dataObject/machine/MachineInfo.java
@@ -0,0 +1,84 @@
+package cd.casic.ci.process.process.dataObject.machine;
+
+
+import cd.casic.framework.commons.dataobject.BaseDO;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 机器信息表
+ *
+ * @author herenbin
+ * @date 2022-09-27 10:10:37
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+@TableName("machine_info")
+public class MachineInfo extends BaseDO {
+
+
+ /**
+ * 机器认证方式 1: 账号认证 2: key认证
+ */
+ private String authType;
+
+ /**
+ * 机器描述
+ */
+ private String description;
+ /**
+ * id
+ */
+ @TableId(type = IdType.ASSIGN_ID)
+ private Long id;
+
+ /**
+ * 主机ip
+ */
+ private String machineHost;
+
+ /**
+ * 机器名称
+ */
+ private String machineName;
+
+ /**
+ * 机器状态 1有效 2无效
+ */
+ private String machineStatus;
+
+ /**
+ * 机器唯一标识
+ */
+ private String machineTag;
+
+ /**
+ * 机器密码
+ */
+ private String password;
+
+ /**
+ * 代理id
+ */
+ private Long proxyId;
+
+ /**
+ * ssh端口
+ */
+ private Integer sshPort;
+
+ /**
+ * 机器账号
+ */
+ private String username;
+ /**
+ * 机器账号
+ */
+ @TableField("os_system")
+ private String osSystem;
+
+}
diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/service/machine/MachineInfoService.java b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/service/machine/MachineInfoService.java
new file mode 100644
index 00000000..0d09a0d2
--- /dev/null
+++ b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/service/machine/MachineInfoService.java
@@ -0,0 +1,17 @@
+package cd.casic.ci.process.process.service.machine;
+
+
+import cd.casic.ci.process.process.dataObject.machine.MachineInfo;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+import java.util.List;
+
+/**
+ * 机器信息表service接口
+ *
+ * @author herenbin
+ * @date 2022-09-27 10:25:29
+ */
+public interface MachineInfoService extends IService {
+
+}
diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/service/machine/impl/MachineInfoServiceImpl.java b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/service/machine/impl/MachineInfoServiceImpl.java
new file mode 100644
index 00000000..16fa7686
--- /dev/null
+++ b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/process/service/machine/impl/MachineInfoServiceImpl.java
@@ -0,0 +1,25 @@
+package cd.casic.ci.process.process.service.machine.impl;
+
+
+import cd.casic.ci.process.process.dal.machine.MachineInfoDao;
+import cd.casic.ci.process.process.dataObject.machine.MachineInfo;
+import cd.casic.ci.process.process.service.machine.MachineInfoService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import lombok.extern.slf4j.Slf4j;
+
+import org.springframework.stereotype.Service;
+
+
+
+
+/**
+ * 机器信息表service接口实现类
+ * @author herenbin
+ * @date 2022-09-27 10:25:29
+ */
+@Slf4j
+@Service
+public class MachineInfoServiceImpl extends ServiceImpl implements MachineInfoService {
+
+
+}
diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/ssh/ExecCallback.java b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/ssh/ExecCallback.java
new file mode 100644
index 00000000..d95c7b22
--- /dev/null
+++ b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/ssh/ExecCallback.java
@@ -0,0 +1,19 @@
+package cd.casic.ci.process.ssh;
+
+/**
+ * @ClassName ops
+ * @Descriptions ssh 命令回调
+ * @Author mianbin
+ * @Date 2022/6/22 15:26
+ * @Version 1.0
+ **/
+@FunctionalInterface
+public interface ExecCallback {
+
+ /**
+ * 回调执行方法
+ * @param out 命令执行的输出
+ */
+ void callback(String out);
+
+}
diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/ssh/SshClient.java b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/ssh/SshClient.java
new file mode 100644
index 00000000..49f18fb0
--- /dev/null
+++ b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/ssh/SshClient.java
@@ -0,0 +1,56 @@
+package cd.casic.ci.process.ssh;
+
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * @ClassName ops
+ * @Description ssh 命令 , 不记录
+ * @Author mianbin
+ * @Date 2022/6/22 15:27
+ * @Version 1.0
+ **/
+public interface SshClient {
+ /**
+ * 执行ssh 命令
+ *
+ * @param command 要执行的命令,多个命令通过";"号隔开
+ * @param execCallback 命令执行过程中的回调器
+ * @return 执行成功返回0,失败返回1
+ * @throws IOException
+ */
+ int exec(String command, ExecCallback execCallback) throws IOException;
+ /**
+ * 执行ssh 命令
+ *
+ * @param commands 要执行的命令,多个命令通过";"号隔开
+ * @param execCallback 命令执行过程中的回调器
+ * @return 执行成功返回0,失败返回1
+ * @throws IOException
+ */
+ int execNew(List commands, ExecCallback execCallback) throws IOException;
+ /**
+ * 执行ssh 命令
+ *
+ * @param commands 要执行的命令,多个命令通过";"号隔开
+ * @param execCallback 命令执行过程中的回调器
+ * @return 执行成功返回0,失败返回1
+ * @throws IOException
+ */
+ int parallelDebugExec(List commands, ExecCallback execCallback) throws IOException;
+
+ /**
+ * 执行多行命令
+ *
+ * @param command
+ * @param execCallback
+ * @return
+ * @throws IOException
+ */
+ int exec(List command, ExecCallback execCallback) throws IOException;
+
+ /**
+ * 断开客户端连接
+ */
+ void disconnect();
+}
diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/ssh/SshClientFactory.java b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/ssh/SshClientFactory.java
new file mode 100644
index 00000000..dc63dd68
--- /dev/null
+++ b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/ssh/SshClientFactory.java
@@ -0,0 +1,45 @@
+package cd.casic.ci.process.ssh;
+
+
+import cd.casic.ci.process.process.dataObject.machine.MachineInfo;
+import com.jcraft.jsch.JSchException;
+
+/**
+ * @ClassName ops
+ * @Description ssh 工厂 ,这里主要使用的是这个,做个封装
+ * @Author mianbin
+ * @Date 2022/6/22 15:40
+ * @Version 1.0
+ **/
+public class SshClientFactory {
+
+ /**
+ * 基于用户名密码认证创建客户端
+ * @param username 用户名
+ * @param password 密码
+ * @param host 主机ip
+ * @param port ssh端口号
+ * @return
+ */
+ public static SshClient createSsh(String username, String password, String host, int port) throws Exception {
+ try {
+ return new SshCommand(username, password, host, port);
+ } catch (JSchException e) {
+ throw new Exception("创建ssh客户端出错", e);
+ }
+ }
+ /**
+ *
+ * 用户名密码或私钥连接客户端
+ * @param properties 配置参数
+ * 主要包含 用户名 密码 私钥 主机ip 端口 认证类型
+ *
+ * */
+ public static SshClient createSsh(MachineInfo properties) throws Exception {
+ try {
+ return new SshCommand(properties);
+ } catch (JSchException e) {
+ throw new Exception("创建ssh客户端出错", e);
+ }
+ }
+}
diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/ssh/SshCommand.java b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/ssh/SshCommand.java
new file mode 100644
index 00000000..25cd34c7
--- /dev/null
+++ b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/ssh/SshCommand.java
@@ -0,0 +1,253 @@
+package cd.casic.ci.process.ssh;
+
+
+import cd.casic.ci.process.constant.CommandConstant;
+import cd.casic.ci.process.process.dataObject.machine.MachineInfo;
+import cd.casic.ci.process.util.ChannelShellUtil;
+import cd.casic.ci.process.util.CryptogramUtil;
+import cn.hutool.extra.ssh.JschUtil;
+import com.jcraft.jsch.ChannelShell;
+import com.jcraft.jsch.JSchException;
+import com.jcraft.jsch.Session;
+
+import java.io.*;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @ClassName ops
+ * @Description ssh 的命令操作的集合 ,这里是做个统一,其他pipleline 和web ternminal 的实现方式不同
+ * @Author mianbin
+ * @Date 2022/6/22 15:43
+ * @Version 1.0
+ **/
+public class SshCommand implements SshClient {
+
+ private static final int BUFF_SIZE = 1024 * 8; // 8KB
+
+ /**
+ * jsch session
+ */
+ Session session;
+
+
+ /**
+ * 基于用户名密码认证的构造器
+ *
+ * @param username 用户名
+ * @param password 密码
+ * @param host 主机ip
+ * @param port ssh端口号
+ * @throws JSchException
+ */
+
+ public SshCommand(String username, String password, String host, int port) throws JSchException {
+ this.session = JschUtil.createSession(host, port, username, password);
+ this.session.setConfig("PreferredAuthentications", "password");
+ this.session.setConfig("StrictHostKeyChecking", "no");
+ this.session.setPassword(password);
+ this.session.connect();
+ }
+
+ /**
+ * 基于用户名密码认证的构造器
+ * Machine实体类
+ *
+ * @throws JSchException
+ */
+ public SshCommand(MachineInfo machine) throws JSchException {
+ // 根据用户名,主机ip,端口获取一个Session对象
+ String decrypt = CryptogramUtil.doDecrypt(machine.getPassword());
+ this.session = JschUtil.createSession(machine.getMachineHost(), machine.getSshPort(), machine.getUsername(), decrypt);
+ this.session.setConfig("PreferredAuthentications", "password");
+ this.session.setConfig("StrictHostKeyChecking", "no");
+ // 通过Session建立链接
+ this.session.connect();
+ }
+
+ @Override
+ public void disconnect() {
+ if(session!=null) {
+ session.disconnect();
+ }
+ }
+
+ @Override
+ public int exec(String command, ExecCallback execCallback) throws IOException {
+
+ ChannelShell channel = null;
+ try {
+ channel = (ChannelShell) session.openChannel("shell");
+ channel.connect();
+ } catch (JSchException e) {
+ e.printStackTrace();
+ }
+
+ InputStream inputStream = channel.getInputStream();
+ OutputStream outputStream = channel.getOutputStream();
+ PrintWriter printWriter = new PrintWriter(outputStream);
+
+ printWriter.println(command);
+
+ printWriter.println("exit");
+ printWriter.flush();
+ BufferedReader in = new BufferedReader(new InputStreamReader(inputStream));
+
+ String msg = null;
+ while ((msg = in.readLine()) != null) {
+ execCallback.callback(msg);
+ }
+ int result = channel.getExitStatus();
+
+ in.close();
+
+ return result;
+ }
+
+
+ @Override
+ public int exec(List commands, ExecCallback execCallback) throws IOException {
+
+ ChannelShell channel = null;
+ try {
+ channel = (ChannelShell) session.openChannel("shell");
+ channel.connect();
+ } catch (JSchException e) {
+ e.printStackTrace();
+ }
+
+ assert channel != null;
+ ChannelShellUtil.setDefault(channel);
+ InputStream inputStream = channel.getInputStream();
+ OutputStream outputStream = channel.getOutputStream();
+ InputStreamReader isr = new InputStreamReader(inputStream);
+ BufferedReader br = new BufferedReader(isr, BUFF_SIZE);
+ PrintStream commander = new PrintStream(outputStream, true);
+
+ for (String command : commands) {
+ commander.append(command).append(CommandConstant.ENTER);
+ }
+ commander.append("exit" + CommandConstant.ENTER);
+
+ try {
+ char[] buff = new char[BUFF_SIZE];
+ int read;
+ while ((read = br.read(buff)) != -1) {
+ String output = String.valueOf(buff, 0, read);
+ execCallback.callback( output + CommandConstant.ENTER);
+ TimeUnit.MILLISECONDS.sleep(10L);
+ // 检测输出,如果满足跳出条件则退出循环
+ if (output.contains("# exit")||output.contains("$ exit")) {
+ commander.append("exit" + CommandConstant.ENTER);
+ TimeUnit.MILLISECONDS.sleep(1000L);
+ break;
+ }
+ }
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ inputStream.close();
+ outputStream.close();
+ channel.disconnect();
+ int result = channel.getExitStatus();
+ commander.close();
+ isr.close();
+ br.close();
+
+ return result;
+ }
+
+ @Override
+ public int execNew(List commands, ExecCallback execCallback) throws IOException {
+
+ ChannelShell channel = null;
+ try {
+ channel = (ChannelShell) session.openChannel("shell");
+ channel.connect();
+ } catch (JSchException e) {
+ e.printStackTrace();
+ }
+
+ assert channel != null;
+ ChannelShellUtil.setDefault(channel);
+ InputStream inputStream = channel.getInputStream();
+ OutputStream outputStream = channel.getOutputStream();
+ InputStreamReader isr = new InputStreamReader(inputStream);
+ BufferedReader br = new BufferedReader(isr, BUFF_SIZE);
+ PrintStream commander = new PrintStream(outputStream, true);
+
+ for (String command : commands) {
+ commander.append(command).append(CommandConstant.ENTER);
+ }
+ commander.append("exit" + CommandConstant.ENTER);
+
+ try {
+ char[] buff = new char[BUFF_SIZE];
+ int read;
+ while ((read = br.read(buff)) != -1) {
+ execCallback.callback(String.valueOf(buff, 0, read) + CommandConstant.ENTER);
+ TimeUnit.MILLISECONDS.sleep(10L);
+ }
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+
+ inputStream.close();
+ outputStream.close();
+ channel.disconnect();
+ int result = channel.getExitStatus();
+ commander.close();
+ isr.close();
+ br.close();
+
+ return result;
+ }
+ @Override
+ public int parallelDebugExec(List commands, ExecCallback execCallback) throws IOException {
+
+ ChannelShell channel = null;
+ try {
+ channel = (ChannelShell) session.openChannel("shell");
+ channel.connect();
+ } catch (JSchException e) {
+ e.printStackTrace();
+ }
+
+ assert channel != null;
+ ChannelShellUtil.setDefault(channel);
+ InputStream inputStream = channel.getInputStream();
+ OutputStream outputStream = channel.getOutputStream();
+ InputStreamReader isr = new InputStreamReader(inputStream);
+ BufferedReader br = new BufferedReader(isr, BUFF_SIZE);
+ PrintStream commander = new PrintStream(outputStream, true);
+
+ for (String command : commands) {
+ commander.append(command).append(CommandConstant.ENTER);
+ }
+
+ try {
+ char[] buff = new char[BUFF_SIZE];
+ int read;
+ while ((read = br.read(buff)) != -1) {
+ String msg = String.valueOf(buff, 0, read);
+ execCallback.callback(msg + CommandConstant.ENTER);
+ TimeUnit.MILLISECONDS.sleep(20L);
+ if(msg.endsWith("$ ") || msg.endsWith("# ")) {
+ commander.append("exit").append(CommandConstant.ENTER);
+ }
+ }
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ }
+ int result = channel.getExitStatus();
+
+ inputStream.close();
+ outputStream.close();
+ channel.disconnect();
+ commander.close();
+ isr.close();
+ br.close();
+
+ return result;
+ }
+}
diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/ssh/WinRMHelper.java b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/ssh/WinRMHelper.java
new file mode 100644
index 00000000..14fa8560
--- /dev/null
+++ b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/ssh/WinRMHelper.java
@@ -0,0 +1,168 @@
+package cd.casic.ci.process.ssh;
+
+import cd.casic.ci.process.process.dataObject.machine.MachineInfo;
+import cd.casic.ci.process.util.CryptogramUtil;
+import io.cloudsoft.winrm4j.client.WinRmClientContext;
+import io.cloudsoft.winrm4j.winrm.WinRmTool;
+import io.cloudsoft.winrm4j.winrm.WinRmToolResponse;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+
+import java.io.*;
+import java.util.List;
+
+/**
+ * @author herenbin
+ * @date 2023/6/26
+ */
+@Slf4j
+public class WinRMHelper {
+
+ private final String ip;
+
+ private final String username;
+
+ private final String password;
+
+ public static final int DEFAULT_PORT = WinRmTool.DEFAULT_WINRM_PORT;
+
+ public WinRMHelper(final String ip, final String username, final String password) {
+ this.ip = ip;
+ this.username = username;
+ this.password = password;
+ }
+
+ public WinRMHelper(MachineInfo machineInfo) {
+ this.ip = machineInfo.getMachineHost();
+ this.username = machineInfo.getUsername();
+ this.password = CryptogramUtil.doDecrypt(machineInfo.getPassword());
+ }
+
+ public int execute(final String command, ExecCallback execCallback) {
+ WinRmClientContext context = WinRmClientContext.newInstance();
+ try {
+ WinRmTool tool = WinRmTool.Builder.builder(ip, username, password)
+ .port(DEFAULT_PORT).useHttps(false).context(context).build();
+ tool.setOperationTimeout(5000L);
+ WinRmToolResponse resp = tool.executeCommand(command);
+ int statusCode = resp.getStatusCode();
+ execCallback.callback(resp.getStdOut());
+ String stdErr = resp.getStdErr();
+ if (StringUtils.isNotEmpty(stdErr)) {
+ execCallback.callback(stdErr);
+ }
+ return statusCode;
+ } finally {
+ context.shutdown();
+ }
+ }
+
+ public int execute(final List commandList, ExecCallback execCallback) {
+ WinRmClientContext context = WinRmClientContext.newInstance();
+ WinRmTool tool = WinRmTool.Builder.builder(ip, username, password)
+ .port(DEFAULT_PORT).useHttps(false).context(context).build();
+ tool.setOperationTimeout(5000L);
+
+ WinRmToolResponse resp = tool.executeCommand(commandList);
+
+ StringReader reader = new StringReader(resp.getStdOut() + resp.getStdErr());
+ try {
+ char[] buffer = new char[1024];
+ int output;
+ while ((output = reader.read(buffer)) != -1) {
+ execCallback.callback(new String(buffer, 0, output));
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ int statusCode = resp.getStatusCode();
+ context.shutdown();
+ return statusCode;
+ }
+
+ public int executePs(final List commandList, ExecCallback execCallback) {
+ WinRmClientContext context = WinRmClientContext.newInstance();
+ WinRmTool tool = WinRmTool.Builder.builder(ip, username, password)
+ .port(DEFAULT_PORT).useHttps(false).context(context).build();
+ tool.setOperationTimeout(5000L);
+
+ WinRmToolResponse resp = tool.executePs(commandList);
+
+ StringReader reader = new StringReader(resp.getStdOut() + resp.getStdErr());
+ try {
+ char[] buffer = new char[1024];
+ int output;
+ while ((output = reader.read(buffer)) != -1) {
+ execCallback.callback(new String(buffer, 0, output));
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ int statusCode = resp.getStatusCode();
+ context.shutdown();
+ return statusCode;
+ }
+
+ public String execute(final List commandList, ExecCallback execCallback, String pass) {
+ WinRmClientContext context = WinRmClientContext.newInstance();
+ WinRmTool tool = WinRmTool.Builder.builder(ip, username, password)
+ .port(DEFAULT_PORT).useHttps(false).context(context).build();
+ tool.setOperationTimeout(5000L);
+ WinRmToolResponse resp = tool.executeCommand(commandList);
+ context.shutdown();
+ return resp.getStdOut();
+ }
+
+ private String join(List commands) {
+ StringBuilder builder = new StringBuilder();
+ boolean first = true;
+ for (String command : commands) {
+ if (first) {
+ first = false;
+ } else {
+ builder.append(" & ");
+ }
+ builder.append(command);
+ }
+ return builder.toString();
+ }
+
+ public static void main(String[] args) throws IOException {
+// WinRMHelper exec = new WinRMHelper("192.168.0.88", "hrb", "1qaz!QAZ");
+// List commands = new ArrayList<>();
+//// commands.add("powershell");
+// commands.add("dir");
+// commands.add("cd /d D:\\Users\\hrb\\Desktop");
+// commands.add("dir");
+// commands.add("git clone -b master http://192.168.0.12:3000/liuyuchao/testrepo.git");
+//// commands.add("rmdir /s /q 456123");
+//
+// int resp = exec.execute(commands, System.out::println);
+// System.out.println(resp);
+ PipedWriter writer = new PipedWriter();
+ PipedReader reader = new PipedReader(writer);
+
+ Thread t = new Thread(() -> {
+ try {
+ for (int i = 0; i < 10; i++) {
+ writer.write("Line " + i + "\n");
+ writer.flush();
+ Thread.sleep(500);
+ }
+ writer.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ });
+ t.start();
+
+ try (BufferedReader br = new BufferedReader(reader)) {
+ String line;
+ while ((line = br.readLine()) != null) {
+ System.out.println(line);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/util/ChannelShellUtil.java b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/util/ChannelShellUtil.java
new file mode 100644
index 00000000..d2c8c50d
--- /dev/null
+++ b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/util/ChannelShellUtil.java
@@ -0,0 +1,14 @@
+package cd.casic.ci.process.util;
+
+import com.jcraft.jsch.ChannelShell;
+
+public class ChannelShellUtil {
+
+ public static void setDefault(ChannelShell channel) {
+ // channel.setEnv("LANG", "zh_CN.UTF-8");
+ channel.setEnv("LANG", "en_US.UTF-8");
+ // SSH 代理转发
+ channel.setAgentForwarding(false);
+ channel.setPtyType("xterm");
+ }
+}
diff --git a/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/util/CryptogramUtil.java b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/util/CryptogramUtil.java
new file mode 100644
index 00000000..20cc788a
--- /dev/null
+++ b/modules/module-ci-process-biz/src/main/java/cd/casic/ci/process/util/CryptogramUtil.java
@@ -0,0 +1,135 @@
+package cd.casic.ci.process.util;
+
+
+import cn.hutool.log.Log;
+import com.antherd.smcrypto.sm2.Sm2;
+import com.antherd.smcrypto.sm3.Sm3;
+import com.antherd.smcrypto.sm4.Sm4;
+import com.antherd.smcrypto.sm4.Sm4Options;
+
+/**
+ * 加密工具类,本框架目前使用 https://github.com/antherd/sm-crypto 项目中一些加解密方式
+ * 使用小伙伴需要过等保密评相关,请在此处更改为自己的加密方法,或加密机,使用加密机同时需要替换公钥,私钥在内部无法导出,提供加密的方法
+ *
+ * @author yubaoshan
+ */
+public class CryptogramUtil {
+
+ private static final Log log = Log.get();
+
+ /**
+ * 加密方法(Sm2 的专门针对前后端分离,非对称秘钥对的方式,暴露出去的公钥,对传输过程中的密码加个密)
+ *
+ * @param str 待加密数据
+ * @return 加密后的密文
+ * @author yubaoshan
+ */
+ public static String doSm2Encrypt(String str) {
+ return Sm2.doEncrypt(str, Keypair.PUBLIC_KEY);
+ }
+
+ /**
+ * 解密方法
+ * 如果采用加密机的方法,用try catch 捕捉异常,返回原文值即可
+ *
+ * @param str 密文
+ * @return 解密后的明文
+ * @author yubaoshan
+ */
+ public static String doSm2Decrypt(String str) {
+ // 解密
+ return Sm2.doDecrypt(str, Keypair.PRIVATE_KEY);
+ }
+
+ /**
+ * 加密方法
+ *
+ * @param str 待加密数据
+ * @return 加密后的密文
+ * @author yubaoshan
+ */
+ public static String doEncrypt(String str) {
+ // SM4 加密 cbc模式
+ Sm4Options sm4Options4 = new Sm4Options();
+ sm4Options4.setMode("cbc");
+ sm4Options4.setIv("fedcba98765432100123456789abcdef");
+ return Sm4.encrypt(str, Keypair.KEY, sm4Options4);
+ }
+
+ /**
+ * 解密方法
+ * 如果采用加密机的方法,用try catch 捕捉异常,返回原文值即可
+ *
+ * @param str 密文
+ * @return 解密后的明文
+ * @author yubaoshan
+ */
+ public static String doDecrypt(String str) {
+ // 解密,cbc 模式,输出 utf8 字符串
+ Sm4Options sm4Options8 = new Sm4Options();
+ sm4Options8.setMode("cbc");
+ sm4Options8.setIv("fedcba98765432100123456789abcdef");
+ String docString = Sm4.decrypt(str, Keypair.KEY, sm4Options8);
+ if (docString.equals("")) {
+ log.warn(">>> 字段解密失败,返回原文值:{}", str);
+ return str;
+ } else {
+ return docString;
+ }
+ }
+
+ /**
+ * 纯签名
+ *
+ * @param str 待签名数据
+ * @return 签名结果
+ * @author yubaoshan
+ */
+ public static String doSignature(String str) {
+ return Sm2.doSignature(str, Keypair.PRIVATE_KEY);
+ }
+
+ /**
+ * 验证签名结果
+ *
+ * @param originalStr 签名原文数据
+ * @param str 签名结果
+ * @return 是否通过
+ * @author yubaoshan
+ */
+ public static boolean doVerifySignature(String originalStr, String str) {
+ return Sm2.doVerifySignature(originalStr, str, Keypair.PUBLIC_KEY);
+ }
+
+ /**
+ * 通过杂凑算法取得hash值,用于做数据完整性保护
+ *
+ * @param str 字符串
+ * @return hash 值
+ * @author yubaoshan
+ */
+ public static String doHashValue(String str) {
+ return Sm3.sm3(str);
+ }
+
+ private static class Keypair{
+
+ /**
+ * 公钥
+ */
+ public static String PUBLIC_KEY = "04298364ec840088475eae92a591e01284d1abefcda348b47eb324bb521bb03b0b2a5bc393f6b71dabb8f15c99a0050818b56b23f31743b93df9cf8948f15ddb54";
+
+ /**
+ * 私钥
+ */
+ public static String PRIVATE_KEY = "3037723d47292171677ec8bd7dc9af696c7472bc5f251b2cec07e65fdef22e25";
+
+ /**
+ * SM4的对称秘钥(生产环境需要改成自己使用的)
+ * 16 进制字符串,要求为 128 比特
+ */
+ public static String KEY = "0123456789abcdeffedcba9876543210";
+
+ }
+
+}
diff --git a/modules/module-system-biz/src/main/java/cd/casic/module/system/convert/dict/DictDataConvert.java b/modules/module-system-biz/src/main/java/cd/casic/module/system/convert/dict/DictDataConvert.java
index 83918554..bf40288a 100644
--- a/modules/module-system-biz/src/main/java/cd/casic/module/system/convert/dict/DictDataConvert.java
+++ b/modules/module-system-biz/src/main/java/cd/casic/module/system/convert/dict/DictDataConvert.java
@@ -14,7 +14,7 @@ public interface DictDataConvert {
DictDataConvert INSTANCE = Mappers.getMapper(DictDataConvert.class);
- List convertList(List list);
+// List convertList(List list);
DictDataRespVO convert(DictDataDO bean);
diff --git a/modules/module-system-biz/src/main/java/cd/casic/module/system/convert/dict/DictTypeConvert.java b/modules/module-system-biz/src/main/java/cd/casic/module/system/convert/dict/DictTypeConvert.java
index db3eaf71..62964554 100644
--- a/modules/module-system-biz/src/main/java/cd/casic/module/system/convert/dict/DictTypeConvert.java
+++ b/modules/module-system-biz/src/main/java/cd/casic/module/system/convert/dict/DictTypeConvert.java
@@ -27,5 +27,6 @@ public interface DictTypeConvert {
// List convertList02(List list);
List convertList03(List list);
+ DictDataTreeVO converter03(DictTypeDO typeDO);
}