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) {