From 2960b3310e37b1c5f071bc4ca1756649aced554a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E8=92=B2=E5=85=88=E7=94=9F?= <821039958@qq.com>
Date: Fri, 30 May 2025 10:13:54 +0800
Subject: [PATCH] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E4=BB=93=E7=AE=A1=E7=90=86?=
=?UTF-8?q?=E4=B8=8A?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
dependencies/pom.xml | 5 +
modules/module-ci-repository/pom.xml | 63 ++++++++
.../controller/admin/OpsVcsController.java | 106 +++++++++++++
.../repository/controller/admin/OpsVcsVO.java | 105 +++++++++++++
.../repository/dal/dataobject/OpsVcsDO.java | 110 +++++++++++++
.../dal/mysql/RepositoryServiceMapper.java | 10 ++
.../enums/RepositoryExceptionEnum.java | 46 ++++++
.../exception/RepositoryException.java | 56 +++++++
.../service/OpsRepositoryService.java | 26 ++++
.../service/OpsRepositoryServiceImpl.java | 147 ++++++++++++++++++
.../ci/repository/util/CryptogramUtil.java | 115 ++++++++++++++
.../cd/casic/ci/repository/util/keypair.java | 27 ++++
modules/pom.xml | 1 +
ops-server/pom.xml | 5 +
.../cd/casic/server/OpsServerApplication.java | 3 +-
15 files changed, 824 insertions(+), 1 deletion(-)
create mode 100644 modules/module-ci-repository/pom.xml
create mode 100644 modules/module-ci-repository/src/main/java/cd/casic/ci/repository/controller/admin/OpsVcsController.java
create mode 100644 modules/module-ci-repository/src/main/java/cd/casic/ci/repository/controller/admin/OpsVcsVO.java
create mode 100644 modules/module-ci-repository/src/main/java/cd/casic/ci/repository/dal/dataobject/OpsVcsDO.java
create mode 100644 modules/module-ci-repository/src/main/java/cd/casic/ci/repository/dal/mysql/RepositoryServiceMapper.java
create mode 100644 modules/module-ci-repository/src/main/java/cd/casic/ci/repository/enums/RepositoryExceptionEnum.java
create mode 100644 modules/module-ci-repository/src/main/java/cd/casic/ci/repository/exception/RepositoryException.java
create mode 100644 modules/module-ci-repository/src/main/java/cd/casic/ci/repository/service/OpsRepositoryService.java
create mode 100644 modules/module-ci-repository/src/main/java/cd/casic/ci/repository/service/OpsRepositoryServiceImpl.java
create mode 100644 modules/module-ci-repository/src/main/java/cd/casic/ci/repository/util/CryptogramUtil.java
create mode 100644 modules/module-ci-repository/src/main/java/cd/casic/ci/repository/util/keypair.java
diff --git a/dependencies/pom.xml b/dependencies/pom.xml
index 75c0a7f9..1f78d171 100644
--- a/dependencies/pom.xml
+++ b/dependencies/pom.xml
@@ -210,6 +210,11 @@
module-system-biz
${revision}
+
+ cd.casic.boot
+ module-ci-repository
+ ${revision}
+
cd.casic.boot
diff --git a/modules/module-ci-repository/pom.xml b/modules/module-ci-repository/pom.xml
new file mode 100644
index 00000000..a58fdf48
--- /dev/null
+++ b/modules/module-ci-repository/pom.xml
@@ -0,0 +1,63 @@
+
+
+ 4.0.0
+
+ cd.casic.boot
+ modules
+ ${revision}
+
+
+ module-ci-repository
+
+ ${revision}
+ ${project.artifactId}
+
+
+
+
+ cd.casic.boot
+ commons
+
+
+
+ cd.casic.boot
+ spring-boot-starter-mybatis
+
+
+
+ cd.casic.boot
+ spring-boot-starter-security
+
+
+
+ cd.casic.boot
+ spring-boot-starter-biz-tenant
+
+
+
+ cd.casic.boot
+ module-ci-commons
+
+
+
+
+ com.antherd
+ sm-crypto
+ 0.3.2
+
+
+ org.openjdk.nashorn
+ nashorn-core
+ 15.4
+
+
+
+ org.eclipse.jgit
+ org.eclipse.jgit
+ 6.7.0.202309050840-r
+
+
+
+
\ No newline at end of file
diff --git a/modules/module-ci-repository/src/main/java/cd/casic/ci/repository/controller/admin/OpsVcsController.java b/modules/module-ci-repository/src/main/java/cd/casic/ci/repository/controller/admin/OpsVcsController.java
new file mode 100644
index 00000000..ecedef63
--- /dev/null
+++ b/modules/module-ci-repository/src/main/java/cd/casic/ci/repository/controller/admin/OpsVcsController.java
@@ -0,0 +1,106 @@
+package cd.casic.ci.repository.controller.admin;
+
+import cd.casic.ci.repository.dal.dataobject.OpsVcsDO;
+import cd.casic.ci.repository.service.OpsRepositoryService;
+import cd.casic.framework.commons.pojo.CommonResult;
+import cd.casic.framework.commons.pojo.PageResult;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.validation.Valid;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import static cd.casic.framework.commons.pojo.CommonResult.success;
+
+/**
+ * 应用版本仓库控制器
+ */
+@Tag(name = "版本仓库接口")
+@RestController
+@RequestMapping("/ci/repository")
+@Validated
+public class OpsVcsController {
+
+ @Resource
+ private OpsRepositoryService opsRepositoryService;
+
+ /**
+ * 查询分页应用版本仓库
+ */
+ @GetMapping("/page")
+ @Operation(summary = "应用版本仓库_分页")
+ @PreAuthorize("@ss.hasPermission('ci:Repository:query')")
+ public CommonResult> getCIRepositoryPage(@Valid OpsVcsVO opsVcsVO) {
+ PageResult pageResult = opsRepositoryService.getVcsPage(opsVcsVO);
+ return success(pageResult);
+ }
+
+ /**
+ * 添加应用版本仓库
+ */
+ @PostMapping("/add")
+ @Operation(summary = "应用版本仓库_增加")
+ @PreAuthorize("@ss.hasPermission('ci:Repository:create')")
+ public CommonResult add(@Valid @RequestBody OpsVcsVO opsVcs) {
+ return success(opsRepositoryService.add(opsVcs));
+ }
+
+ /**
+ * 删除应用版本仓库
+ */
+ @DeleteMapping("/delete/{opsVcsId}")
+ @Operation(summary = "应用版本仓库_根据id删除")
+ @PreAuthorize("@ss.hasPermission('ci:Repository:delete')")
+ public CommonResult delete(@PathVariable Long opsVcsId) {
+ return success(opsRepositoryService.delete(opsVcsId));
+ }
+
+ /**
+ * 编辑应用版本仓库
+ */
+ @PutMapping("/edit")
+ @Operation(summary = "应用版本仓库_编辑")
+ @PreAuthorize("@ss.hasPermission('ci:Repository:edit')")
+ public CommonResult edit(@Valid @RequestBody OpsVcsVO opsVcsVO) {
+ return success(opsRepositoryService.edit(opsVcsVO));
+ }
+
+ /**
+ * 查看应用版本仓库
+ */
+ @GetMapping("/detail/{opsVcsId}")
+ @Operation(summary = "应用版本仓库_根据id获取详情")
+// @PreAuthorize("@ss.hasPermission('ci:Repository:detail')")
+ public CommonResult detail(@PathVariable Long opsVcsId) {
+ return success(opsRepositoryService.detail(opsVcsId));
+ }
+
+ /**
+ * 应用版本仓库列表
+ */
+ @GetMapping("/list")
+ @Operation(summary = "应用版本仓库_列表")
+// @PreAuthorize("@ss.hasPermission('ci:Repository:list')")
+ public CommonResult vcsList() {
+ return success(opsRepositoryService.vcsList());
+ }
+
+ /**
+ * 应用版本仓库获取分支
+ *
+ */
+ @GetMapping("/getBranch/{opsVcsId}")
+ @Operation(summary = "应用版本仓库_获取分支")
+ public CommonResult getBranch(@PathVariable Long opsVcsId) {
+ return success(opsRepositoryService.getBranch(opsVcsId));
+ }
+
+ @PostMapping("/checkVcsUrl")
+ @Operation(summary = "应用版本仓库_检测存在,是否有权限")
+ public CommonResult checkVcsUrl(@RequestBody OpsVcsVO opsVcs) {
+ return opsRepositoryService.checkVcsUrl(opsVcs);
+ }
+
+}
diff --git a/modules/module-ci-repository/src/main/java/cd/casic/ci/repository/controller/admin/OpsVcsVO.java b/modules/module-ci-repository/src/main/java/cd/casic/ci/repository/controller/admin/OpsVcsVO.java
new file mode 100644
index 00000000..5187bf83
--- /dev/null
+++ b/modules/module-ci-repository/src/main/java/cd/casic/ci/repository/controller/admin/OpsVcsVO.java
@@ -0,0 +1,105 @@
+package cd.casic.ci.repository.controller.admin;
+
+
+import cd.casic.framework.commons.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.NoArgsConstructor;
+import lombok.experimental.Accessors;
+
+@Schema(description = "管理后台 - 代码仓创建/修改 Request VO")
+@Data
+@Accessors(chain = true)
+@NoArgsConstructor
+@AllArgsConstructor
+@EqualsAndHashCode(callSuper = true)
+public class OpsVcsVO extends PageParam {
+
+
+ /**
+ * id
+ */
+ private Long id;
+
+ /**
+ * 认证类型 10密码 20令牌
+ */
+ private String vcsAuthType;
+
+ /**
+ * 描述
+ */
+ private String vcsDescription;
+
+ /**
+ * 名称
+ */
+ private String vcsName;
+
+ /**
+ * 密码
+ */
+ private String vcsPassword;
+
+ /**
+ * token
+ */
+ private String vcsPrivateToken;
+
+ /**
+ * 状态 10未初始化 20初始化中 30正常 40失败
+ */
+ private String vcsStatus;
+
+ /**
+ * 令牌类型 10github 20gitee 30gitlab
+ */
+ private String vcsTokenType;
+
+ /**
+ * 类型 1git
+ */
+ private String vcsType;
+
+ /**
+ * url
+ */
+ private String vscUrl;
+
+ /**
+ * 用户名
+ */
+ private String vscUsername;
+
+ /**
+ * 一体化项目标识
+ */
+ private String projectId;
+
+ /**
+ * 一体化配置项
+ */
+ private String softCode;
+
+ /**
+ * 一体化项目名称
+ */
+ private String projectName;
+
+ /**
+ * 一体化配置项名称
+ */
+ private String softName;
+ /**
+ * 密级
+ */
+ private String secretId;
+
+ /**
+ * 租户ID
+ */
+ private String tenantId;
+
+}
diff --git a/modules/module-ci-repository/src/main/java/cd/casic/ci/repository/dal/dataobject/OpsVcsDO.java b/modules/module-ci-repository/src/main/java/cd/casic/ci/repository/dal/dataobject/OpsVcsDO.java
new file mode 100644
index 00000000..ca28be8c
--- /dev/null
+++ b/modules/module-ci-repository/src/main/java/cd/casic/ci/repository/dal/dataobject/OpsVcsDO.java
@@ -0,0 +1,110 @@
+package cd.casic.ci.repository.dal.dataobject;
+
+import cd.casic.framework.mybatis.core.dataobject.BaseDO;
+import com.baomidou.mybatisplus.annotation.*;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ * 应用版本仓库
+ */
+@TableName(value = "ops_vcs", autoResultMap = true)
+//@KeySequence("ops_vcs_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@Accessors(chain = true)
+@EqualsAndHashCode(callSuper = true)
+public class OpsVcsDO extends BaseDO {
+
+
+ /**
+ * id
+ */
+ @TableId(type = IdType.ASSIGN_ID)
+ private Long id;
+
+ /**
+ * 认证类型 10密码 20令牌
+ */
+ private String vcsAuthType;
+
+ /**
+ * 描述
+ */
+ private String vcsDescription;
+
+ /**
+ * 名称
+ */
+ private String vcsName;
+
+ /**
+ * 密码
+ */
+ private String vcsPassword;
+
+ /**
+ * token
+ */
+ private String vcsPrivateToken;
+
+ /**
+ * 状态 10未初始化 20初始化中 30正常 40失败
+ */
+ private String vcsStatus;
+
+ /**
+ * 令牌类型 10github 20gitee 30gitlab
+ */
+ private String vcsTokenType;
+
+ /**
+ * 类型 1git
+ */
+ private String vcsType;
+
+ /**
+ * url
+ */
+ private String vscUrl;
+
+ /**
+ * 用户名
+ */
+ private String vscUsername;
+
+ /**
+ *所属部门cod
+ */
+ private String deptCode;
+
+ /**
+ * 一体化项目标识
+ */
+ private String projectId;
+
+ /**
+ * 一体化配置项
+ */
+ private String softCode;
+
+ /**
+ * 一体化项目名称
+ */
+ private String projectName;
+
+ /**
+ * 一体化配置项名称
+ */
+ private String softName;
+ /**
+ * 密级
+ */
+ private String secretId;
+
+ /**
+ * 租户ID
+ */
+ private String tenantId;
+
+}
diff --git a/modules/module-ci-repository/src/main/java/cd/casic/ci/repository/dal/mysql/RepositoryServiceMapper.java b/modules/module-ci-repository/src/main/java/cd/casic/ci/repository/dal/mysql/RepositoryServiceMapper.java
new file mode 100644
index 00000000..091a1c1d
--- /dev/null
+++ b/modules/module-ci-repository/src/main/java/cd/casic/ci/repository/dal/mysql/RepositoryServiceMapper.java
@@ -0,0 +1,10 @@
+package cd.casic.ci.repository.dal.mysql;
+
+import cd.casic.ci.repository.dal.dataobject.OpsVcsDO;
+import cd.casic.framework.mybatis.core.mapper.BaseMapperX;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface RepositoryServiceMapper extends BaseMapperX {
+
+}
diff --git a/modules/module-ci-repository/src/main/java/cd/casic/ci/repository/enums/RepositoryExceptionEnum.java b/modules/module-ci-repository/src/main/java/cd/casic/ci/repository/enums/RepositoryExceptionEnum.java
new file mode 100644
index 00000000..470d1a08
--- /dev/null
+++ b/modules/module-ci-repository/src/main/java/cd/casic/ci/repository/enums/RepositoryExceptionEnum.java
@@ -0,0 +1,46 @@
+package cd.casic.ci.repository.enums;
+
+
+import cd.casic.framework.commons.exception.ErrorCode;
+import cd.casic.framework.commons.pojo.CommonResult;
+
+public enum RepositoryExceptionEnum {
+
+ /**
+ * 数据不存在
+ */
+ NOT_EXIST(1, "此数据不存在"),
+ NODE_EXIST(2, "该节点信息已存在"),
+ NOT_EXIST_PIPELINE(3, "该流水线不存在"),
+ GIT_REMOTE_CONNECT_ERROR(4, "获取分支失败"),
+ VCS_CLONE_ERROR(5, "仓库克隆失败"),
+ VCS_PATH_ABSENT(6, "仓库目录不存在"),
+ VCS_UNABLE_CONNECT(7, "无法连接到远程仓库,请检查用户名或密码"),
+ VCS_UNINITIALIZED(8, "仓库未初始化"),
+ VCS_INITIALIZED(9, "远程仓库已初始化"),
+ VCS_INITIALIZING(10, "远程仓库初始化中"),
+ NODE_EXECUTE_FAIL(11, "节点执行失败"),
+ NOT_EXIST_START(12, "请先添加开始节点"),
+ GIT_USER_OR_PWD_IS_NONE(13, "用户名密码为不能为空"),
+ GIT_INVALID_URL_ERROR(14, "无效的仓库URL地址,或者网络故障问题");
+
+ private final Integer code;
+
+ private final String message;
+
+ public int getCode() {
+ return code;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ RepositoryExceptionEnum(Integer code, String message) {
+ this.code = code;
+ this.message = message;
+ }
+ public static ErrorCode getErrorCode(RepositoryExceptionEnum rx){
+ return new ErrorCode(rx.getCode(), rx.message);
+ }
+}
diff --git a/modules/module-ci-repository/src/main/java/cd/casic/ci/repository/exception/RepositoryException.java b/modules/module-ci-repository/src/main/java/cd/casic/ci/repository/exception/RepositoryException.java
new file mode 100644
index 00000000..606ba45c
--- /dev/null
+++ b/modules/module-ci-repository/src/main/java/cd/casic/ci/repository/exception/RepositoryException.java
@@ -0,0 +1,56 @@
+package cd.casic.ci.repository.exception;
+
+import cd.casic.ci.repository.enums.RepositoryExceptionEnum;
+import cd.casic.framework.commons.exception.ErrorCode;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * 后台管理代码仓异常 Exception
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public final class RepositoryException extends RuntimeException {
+
+ private Integer code;
+
+ private String message;
+
+ public RepositoryException() {
+ }
+
+ public RepositoryException(String message) {
+ this.message = message;
+ }
+
+ public RepositoryException(String message, Throwable cause) {
+ super(cause);
+ this.message = message;
+ }
+
+ public RepositoryException(RepositoryExceptionEnum repositoryExceptionEnum) {
+ this.message = repositoryExceptionEnum.getMessage();
+ this.code = repositoryExceptionEnum.getCode();
+ }
+
+ public RepositoryException(ErrorCode errorCode) {
+ this.code = errorCode.getCode();
+ this.message = errorCode.getMsg();
+ }
+
+ public RepositoryException(Integer code, String message) {
+ this.code = code;
+ this.message = message;
+ }
+
+ public RepositoryException setMessage(String message) {
+ this.message = message;
+ return this;
+ }
+
+ @Override
+ public String getMessage() {
+ return message;
+ }
+
+}
\ No newline at end of file
diff --git a/modules/module-ci-repository/src/main/java/cd/casic/ci/repository/service/OpsRepositoryService.java b/modules/module-ci-repository/src/main/java/cd/casic/ci/repository/service/OpsRepositoryService.java
new file mode 100644
index 00000000..d7f74553
--- /dev/null
+++ b/modules/module-ci-repository/src/main/java/cd/casic/ci/repository/service/OpsRepositoryService.java
@@ -0,0 +1,26 @@
+package cd.casic.ci.repository.service;
+
+import cd.casic.ci.repository.controller.admin.OpsVcsVO;
+import cd.casic.ci.repository.dal.dataobject.OpsVcsDO;
+import cd.casic.framework.commons.pojo.CommonResult;
+import cd.casic.framework.commons.pojo.PageResult;
+import java.util.List;
+
+public interface OpsRepositoryService {
+
+ int add(OpsVcsVO opsVcs);
+
+ Integer delete(Long opsVcsId);
+
+ Integer edit(OpsVcsVO opsVcsVO);
+
+ OpsVcsDO detail(Long opsVcsId);
+
+ List vcsList();
+
+ PageResult getVcsPage(OpsVcsVO opsVcsVO);
+
+ List getBranch(Long opsVcsId);
+
+ CommonResult checkVcsUrl(OpsVcsVO opsVcs);
+}
diff --git a/modules/module-ci-repository/src/main/java/cd/casic/ci/repository/service/OpsRepositoryServiceImpl.java b/modules/module-ci-repository/src/main/java/cd/casic/ci/repository/service/OpsRepositoryServiceImpl.java
new file mode 100644
index 00000000..dacf8e44
--- /dev/null
+++ b/modules/module-ci-repository/src/main/java/cd/casic/ci/repository/service/OpsRepositoryServiceImpl.java
@@ -0,0 +1,147 @@
+package cd.casic.ci.repository.service;
+
+import cd.casic.ci.repository.controller.admin.OpsVcsVO;
+import cd.casic.ci.repository.dal.dataobject.OpsVcsDO;
+import cd.casic.ci.repository.dal.mysql.RepositoryServiceMapper;
+import cd.casic.ci.repository.enums.RepositoryExceptionEnum;
+import cd.casic.ci.repository.exception.RepositoryException;
+import cd.casic.ci.repository.util.CryptogramUtil;
+import cd.casic.framework.commons.pojo.CommonResult;
+import cd.casic.framework.commons.pojo.PageResult;
+import cd.casic.framework.commons.util.object.BeanUtils;
+import cd.casic.framework.security.core.util.SecurityFrameworkUtils;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import jakarta.annotation.Resource;
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.api.LsRemoteCommand;
+import org.eclipse.jgit.api.errors.GitAPIException;
+import org.eclipse.jgit.api.errors.TransportException;
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.transport.CredentialsProvider;
+import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import java.util.*;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * @author: Paul
+ * @create: 2025-05-26 11:13
+ */
+@Service
+@Validated
+public class OpsRepositoryServiceImpl implements OpsRepositoryService {
+
+ @Resource
+ private RepositoryServiceMapper repositoryServiceMapper;
+
+
+ @Override
+// @Transactional(rollbackFor = Exception.class)
+ public int add(OpsVcsVO opsVcs) {
+ OpsVcsDO vcsDO = BeanUtils.toBean(opsVcs, OpsVcsDO.class);
+ Long tenantId = SecurityFrameworkUtils.getLoginUser().getTenantId();//获取租户id
+ vcsDO.setTenantId(tenantId == null ? null : tenantId.toString());
+ vcsDO.setDeptCode(SecurityFrameworkUtils.getLoginUserDeptId().toString());
+ vcsDO.setVcsPassword(CryptogramUtil.doEncrypt(opsVcs.getVcsPassword())); // 加密
+ return repositoryServiceMapper.insert(vcsDO);
+ }
+
+ @Override
+ public Integer delete(Long opsVcsId) {
+ return repositoryServiceMapper.deleteById(opsVcsId);
+ }
+
+ @Override
+ public Integer edit(OpsVcsVO opsVcsVO) {
+ return repositoryServiceMapper.updateById(BeanUtils.toBean(opsVcsVO, OpsVcsDO.class));
+ }
+
+ @Override
+ public OpsVcsDO detail(Long opsVcsId) {
+ return repositoryServiceMapper.selectById(opsVcsId);
+ }
+
+ @Override
+ public List vcsList() {
+ return repositoryServiceMapper.selectList();
+ }
+
+ @Override
+ public PageResult getVcsPage(OpsVcsVO opsVcsVO) {
+ QueryWrapper queryWrapper = new QueryWrapper<>();
+ queryWrapper.lambda().like(Objects.nonNull(opsVcsVO.getVcsName()), OpsVcsDO::getVcsName, opsVcsVO.getVcsName());
+ queryWrapper.lambda().like(Objects.nonNull(opsVcsVO.getVscUsername()), OpsVcsDO::getVscUsername, opsVcsVO.getVscUsername());
+ return repositoryServiceMapper.selectPage(opsVcsVO, queryWrapper.lambda().orderByDesc(OpsVcsDO::getCreateTime));
+ }
+
+ @Override
+ public List getBranch(Long opsVcsId) {
+ OpsVcsDO vcs = detail(opsVcsId);
+ String repositoryUrl = vcs.getVscUrl();
+ String username = Optional.ofNullable(vcs.getVscUsername()).
+ orElseThrow(() -> new RepositoryException(RepositoryExceptionEnum.GIT_USER_OR_PWD_IS_NONE));
+ String vcsPwd = Optional.ofNullable(vcs.getVcsPassword()).
+ orElseThrow(() -> new RepositoryException(RepositoryExceptionEnum.GIT_USER_OR_PWD_IS_NONE));
+ // 解密
+ String password = CryptogramUtil.doDecrypt(vcsPwd);
+ // 创建凭证提供者(如果需要认证)
+ CredentialsProvider credentialsProvider = null;
+ if (username != null && password != null) {
+ credentialsProvider = new UsernamePasswordCredentialsProvider(username, password);
+ }
+ try {
+ Collection[ refs = Git.lsRemoteRepository()
+ .setRemote(repositoryUrl)
+ .setCredentialsProvider(credentialsProvider)
+ .call();
+ List branchNames = new ArrayList<>();
+ for (Ref ref : refs) {
+ String refName = ref.getName();
+ if (refName.startsWith("refs/heads/")) {
+ branchNames.add(refName.substring("refs/heads/".length()));
+ }
+ }
+ return branchNames;
+ } catch (GitAPIException e) {
+ throw new RepositoryException(RepositoryExceptionEnum.GIT_INVALID_URL_ERROR.getMessage(), e);
+ }
+ }
+
+ @Override
+ public CommonResult checkVcsUrl(OpsVcsVO opsVcs) {
+
+ String username = Optional.ofNullable(opsVcs.getVscUsername()).
+ orElseThrow(() -> new RepositoryException(RepositoryExceptionEnum.GIT_USER_OR_PWD_IS_NONE));
+ AtomicReference passwordRef = new AtomicReference<>();
+ passwordRef.set(Optional.ofNullable(opsVcs.getVcsPassword()).
+ orElseThrow(() -> new RepositoryException(RepositoryExceptionEnum.GIT_USER_OR_PWD_IS_NONE)));
+ Optional.ofNullable(opsVcs.getId()).ifPresent(a -> passwordRef.set(CryptogramUtil.doDecrypt(opsVcs.getVcsPassword())));
+ String password = passwordRef.get();
+ LsRemoteCommand lsRemoteCommand = new LsRemoteCommand(null);
+ lsRemoteCommand.setRemote(opsVcs.getVscUrl());
+ lsRemoteCommand.setTimeout(8); // 设置超时时间为8秒
+ // 如果需要认证
+ if (username != null && password != null) {
+ CredentialsProvider credentialsProvider =
+ new UsernamePasswordCredentialsProvider(username, password);
+ lsRemoteCommand.setCredentialsProvider(credentialsProvider);
+ }
+ try {
+ lsRemoteCommand.call();
+ return CommonResult.success(RepositoryExceptionEnum.getErrorCode(RepositoryExceptionEnum.VCS_INITIALIZED));
+ } catch (TransportException e) {
+ if (e.getMessage().contains("not authorized")) {
+ return CommonResult.error(RepositoryExceptionEnum.getErrorCode(RepositoryExceptionEnum.VCS_UNABLE_CONNECT));
+ } else if (e.getMessage().contains("Connection timed out") ||
+ e.getMessage().contains("Unable to connect")) {
+ return CommonResult.error(RepositoryExceptionEnum.getErrorCode(RepositoryExceptionEnum.GIT_INVALID_URL_ERROR));
+ }
+ return CommonResult.error(RepositoryExceptionEnum.getErrorCode(RepositoryExceptionEnum.GIT_INVALID_URL_ERROR));
+ } catch (GitAPIException e) {
+ return CommonResult.error(RepositoryExceptionEnum.getErrorCode(RepositoryExceptionEnum.GIT_INVALID_URL_ERROR));
+ }
+ }
+
+}
diff --git a/modules/module-ci-repository/src/main/java/cd/casic/ci/repository/util/CryptogramUtil.java b/modules/module-ci-repository/src/main/java/cd/casic/ci/repository/util/CryptogramUtil.java
new file mode 100644
index 00000000..b0b62cd3
--- /dev/null
+++ b/modules/module-ci-repository/src/main/java/cd/casic/ci/repository/util/CryptogramUtil.java
@@ -0,0 +1,115 @@
+package cd.casic.ci.repository.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 的专门针对前后端分离,非对称秘钥对的方式,暴露出去的公钥,对传输过程中的密码加个密)
+ *
+ * @author yubaoshan
+ * @param str 待加密数据
+ * @return 加密后的密文
+ */
+ public static String doSm2Encrypt (String str) {
+ return Sm2.doEncrypt(str, keypair.PUBLIC_KEY);
+ }
+
+ /**
+ * 解密方法
+ * 如果采用加密机的方法,用try catch 捕捉异常,返回原文值即可
+ *
+ * @author yubaoshan
+ * @param str 密文
+ * @return 解密后的明文
+ */
+ public static String doSm2Decrypt (String str) {
+ // 解密
+ return Sm2.doDecrypt(str, keypair.PRIVATE_KEY);
+ }
+
+ /**
+ * 加密方法
+ *
+ * @author yubaoshan
+ * @param str 待加密数据
+ * @return 加密后的密文
+ */
+ 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 捕捉异常,返回原文值即可
+ *
+ * @author yubaoshan
+ * @param str 密文
+ * @return 解密后的明文
+ */
+ 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;
+ }
+ }
+
+ /**
+ * 纯签名
+ *
+ * @author yubaoshan
+ * @param str 待签名数据
+ * @return 签名结果
+ */
+ public static String doSignature (String str) {
+ return Sm2.doSignature(str, keypair.PRIVATE_KEY);
+ }
+
+ /**
+ * 验证签名结果
+ *
+ * @author yubaoshan
+ * @param originalStr 签名原文数据
+ * @param str 签名结果
+ * @return 是否通过
+ */
+ public static boolean doVerifySignature (String originalStr, String str) {
+ return Sm2.doVerifySignature(originalStr, str, keypair.PUBLIC_KEY);
+ }
+
+ /**
+ * 通过杂凑算法取得hash值,用于做数据完整性保护
+ *
+ * @author yubaoshan
+ * @param str 字符串
+ * @return hash 值
+ */
+ public static String doHashValue (String str) {
+ return Sm3.sm3(str);
+ }
+
+}
diff --git a/modules/module-ci-repository/src/main/java/cd/casic/ci/repository/util/keypair.java b/modules/module-ci-repository/src/main/java/cd/casic/ci/repository/util/keypair.java
new file mode 100644
index 00000000..550c408c
--- /dev/null
+++ b/modules/module-ci-repository/src/main/java/cd/casic/ci/repository/util/keypair.java
@@ -0,0 +1,27 @@
+package cd.casic.ci.repository.util;
+
+/**
+ * 基于SM2的秘钥对
+ * (本项目中配置的,自己使用可根据自己的需求进行更换)
+ *
+ * @author yubaoshan
+ */
+public 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/pom.xml b/modules/pom.xml
index 297e9f53..0eb383de 100644
--- a/modules/pom.xml
+++ b/modules/pom.xml
@@ -15,6 +15,7 @@
module-system-api
module-system-biz
module-ci-execute
+ module-ci-repository
modules
diff --git a/ops-server/pom.xml b/ops-server/pom.xml
index a64aa125..6da84496 100644
--- a/ops-server/pom.xml
+++ b/ops-server/pom.xml
@@ -25,6 +25,11 @@
module-system-biz
${revision}
]
+
+ cd.casic.boot
+ module-ci-repository
+
+
cd.casic.boot
module-infra-biz
diff --git a/ops-server/src/main/java/cd/casic/server/OpsServerApplication.java b/ops-server/src/main/java/cd/casic/server/OpsServerApplication.java
index 069f1945..b6aaa467 100644
--- a/ops-server/src/main/java/cd/casic/server/OpsServerApplication.java
+++ b/ops-server/src/main/java/cd/casic/server/OpsServerApplication.java
@@ -10,7 +10,8 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
*/
@SuppressWarnings("SpringComponentScan")
-@SpringBootApplication(scanBasePackages = {"${ops.info.base-package}.server", "${ops.info.base-package}.module"})
+@SpringBootApplication(scanBasePackages = {"${ops.info.base-package}.server", "${ops.info.base-package}.module",
+ "${ops.info.base-package}.ci.repository"})
public class OpsServerApplication {
public static void main(String[] args) {