增加接口连接成功时间

This commit is contained in:
戚辰先生 2024-12-03 00:28:43 +08:00
parent 9b16146cd0
commit 46304d6682
9 changed files with 166 additions and 28 deletions

View File

@ -51,7 +51,7 @@ public class ExternalSystem extends Entity<Long> {
private Boolean enabled = true;
/**
* 认证方式BASIC/TOKEN/OAUTH
* 认证方式BASIC/TOKEN/OAUTH<EFBFBD><EFBFBD>
*/
@Column(name = "auth_type", nullable = false)
@Enumerated(EnumType.STRING)
@ -63,7 +63,7 @@ public class ExternalSystem extends Entity<Long> {
private String username;
/**
* 密码/密钥
* 密码
*/
private String password;
@ -85,6 +85,12 @@ public class ExternalSystem extends Entity<Long> {
@Column(name = "last_sync_time")
private LocalDateTime lastSyncTime;
/**
* 最近连接成功时间
*/
@Column(name = "last_connect_time")
private LocalDateTime lastConnectTime;
/**
* 系统特有配置JSON格式
*/

View File

@ -70,7 +70,17 @@ public enum ResponseCode {
EXTERNAL_SYSTEM_TYPE_URL_EXISTS(2501, "external.system.type.url.exists"),
EXTERNAL_SYSTEM_DISABLED(2502, "external.system.disabled"),
EXTERNAL_SYSTEM_SYNC_FAILED(2503, "external.system.sync.failed"),
EXTERNAL_SYSTEM_TYPE_NOT_SUPPORTED(2504, "external.system.type.not.supported");
EXTERNAL_SYSTEM_TYPE_NOT_SUPPORTED(2504, "external.system.type.not.supported"),
/**
* Git系统认证方式错误
*/
EXTERNAL_SYSTEM_GIT_AUTH_TYPE_ERROR(2501, "Git系统只支持Token认证"),
/**
* Git系统Token必填
*/
EXTERNAL_SYSTEM_GIT_TOKEN_REQUIRED(2502, "Git系统必须提供Token");
private final int code;
private final String messageKey; // 国际化消息key

View File

@ -6,6 +6,7 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.client.HttpClientErrorException;
@Slf4j
@Service
@ -16,11 +17,9 @@ public class GitIntegration implements IExternalSystemIntegration {
@Override
public boolean testConnection(ExternalSystem system) {
try {
String url = system.getUrl() + "/api/v4/version"; // GitLab API
String url = system.getUrl() + "/api/v4/version";
HttpHeaders headers = new HttpHeaders();
if (system.getToken() != null) {
headers.set("PRIVATE-TOKEN", system.getToken());
}
headers.set("PRIVATE-TOKEN", system.getToken());
HttpEntity<String> entity = new HttpEntity<>(headers);
ResponseEntity<String> response = restTemplate.exchange(
@ -31,8 +30,14 @@ public class GitIntegration implements IExternalSystemIntegration {
);
return response.getStatusCode() == HttpStatus.OK;
} catch (HttpClientErrorException.Unauthorized e) {
log.error("GitLab token authentication failed: {}", system.getUrl());
return false;
} catch (HttpClientErrorException.NotFound e) {
log.error("GitLab API endpoint not found: {}", system.getUrl());
return false;
} catch (Exception e) {
log.error("Failed to connect to Git: {}", system.getUrl(), e);
log.error("Failed to connect to GitLab: {}", system.getUrl(), e);
return false;
}
}

View File

@ -43,5 +43,7 @@ public class ExternalSystemDTO extends BaseDTO {
private LocalDateTime lastSyncTime;
private LocalDateTime lastConnectTime;
private String config;
}

View File

@ -13,6 +13,7 @@ import com.qqchen.deploy.backend.service.IExternalSystemService;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@ -69,6 +70,31 @@ public class ExternalSystemServiceImpl extends BaseServiceImpl<ExternalSystem, E
throw new UniqueConstraintException(ResponseCode.EXTERNAL_SYSTEM_TYPE_URL_EXISTS,
"type and url", dto.getType() + ":" + dto.getUrl());
}
validateGitAuth(dto);
}
@Override
public ExternalSystemDTO update(Long id, ExternalSystemDTO dto) {
// 先验证Git认证
validateGitAuth(dto);
return super.update(id, dto);
}
/**
* 验证Git系统的认证方式
*
* @param dto 外部系统DTO
*/
private void validateGitAuth(ExternalSystemDTO dto) {
if (dto.getType() == ExternalSystem.SystemType.GIT) {
if (dto.getAuthType() != ExternalSystem.AuthType.TOKEN) {
throw new BusinessException(ResponseCode.EXTERNAL_SYSTEM_GIT_AUTH_TYPE_ERROR);
}
if (StringUtils.isBlank(dto.getToken())) {
throw new BusinessException(ResponseCode.EXTERNAL_SYSTEM_GIT_TOKEN_REQUIRED);
}
}
}
@Override
@ -84,7 +110,12 @@ public class ExternalSystemServiceImpl extends BaseServiceImpl<ExternalSystem, E
throw new BusinessException(ResponseCode.EXTERNAL_SYSTEM_TYPE_NOT_SUPPORTED);
}
return integration.testConnection(system);
boolean success = integration.testConnection(system);
if (success) {
system.setLastConnectTime(LocalDateTime.now());
externalSystemRepository.save(system);
}
return success;
}
@Override

View File

@ -145,7 +145,7 @@ CREATE TABLE sys_role_tag (
version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号',
name VARCHAR(50) NOT NULL COMMENT '标签名称',
color VARCHAR(20) NULL COMMENT '标签色(十六进制颜色码)'
color VARCHAR(20) NULL COMMENT '标签<EFBFBD><EFBFBD>色(十六进制颜色码)'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='角色标签表';
-- 角色标签关联表
@ -249,20 +249,16 @@ CREATE TABLE sys_external_system (
remark TEXT NULL COMMENT '备注说明',
sort INT NULL DEFAULT 0 COMMENT '排序',
enabled BIT NOT NULL DEFAULT 1 COMMENT '是否启用0禁用1启用',
auth_type VARCHAR(50) NOT NULL COMMENT '认证方式BASIC基础认证TOKEN令牌认证OAUTHOAuth认证',
auth_type VARCHAR(50) NOT NULL COMMENT '认证方式BASIC/TOKEN/OAUTH等',
username VARCHAR(100) NULL COMMENT '用户名',
password VARCHAR(255) NULL COMMENT '密码/密钥',
password VARCHAR(255) NULL COMMENT '密码',
token VARCHAR(255) NULL COMMENT '访问令牌',
sync_status ENUM ('SUCCESS', 'FAILED', 'RUNNING') NULL COMMENT '最后同步状态',
sync_status VARCHAR(50) NULL COMMENT '同步状态SUCCESS/FAILED/RUNNING',
last_sync_time DATETIME(6) NULL COMMENT '最后同步时间',
config JSON NULL COMMENT '系统特有配置JSON格式',
last_connect_time DATETIME(6) NULL COMMENT '最近连接成功时间',
config JSON NULL COMMENT '系统特有配置',
CONSTRAINT UK_external_system_name UNIQUE (name),
CONSTRAINT UK_external_system_type_url UNIQUE (type, url),
INDEX IDX_type (type),
INDEX IDX_enabled (enabled)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='外部系统配置表';
CONSTRAINT UK_external_system_type_url UNIQUE (type, url)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='外部系统表';

View File

@ -131,9 +131,18 @@ VALUES
-- --------------------------------------------------------------------------------------
-- 初始化外部系统
INSERT INTO sys_external_system (id, create_time, name, type, url, auth_type, username, password, enabled, sort)
VALUES
(1, NOW(), 'Jenkins测试环境', 'JENKINS', 'http://jenkins-test.example.com', 'BASIC', 'admin', 'jenkins123', 1, 1),
(2, NOW(), 'Jenkins生产环境', 'JENKINS', 'http://jenkins-prod.example.com', 'BASIC', 'admin', 'jenkins123', 1, 2),
(3, NOW(), 'GitLab', 'GIT', 'http://gitlab.example.com', 'TOKEN', NULL, NULL, 1, 3),
(4, NOW(), '禅道', 'ZENTAO', 'http://zentao.example.com', 'BASIC', 'admin', 'zentao123', 1, 4);
INSERT INTO sys_external_system (
id, create_by, create_time, deleted, update_by, update_time, version,
name, type, url, remark, sort, enabled, auth_type, username, password, token,
sync_status, last_sync_time, last_connect_time, config
) VALUES (
1, 'admin', '2023-12-01 00:00:00', 0, 'admin', '2023-12-01 00:00:00', 0,
'Jenkins测试环境', 'JENKINS', 'http://jenkins.test.com', '测试环境Jenkins服务器', 1, 1,
'BASIC', 'admin', 'password123', NULL,
'SUCCESS', '2023-12-01 00:00:00', '2023-12-01 00:00:00', '{}'
), (
2, 'admin', '2023-12-01 00:00:00', 0, 'admin', '2023-12-01 00:00:00', 0,
'GitLab测试环境', 'GIT', 'http://gitlab.test.com', '测试环境GitLab服务器', 2, 1,
'TOKEN', NULL, NULL, 'test-token',
'SUCCESS', '2023-12-01 00:00:00', '2023-12-01 00:00:00', '{}'
);

View File

@ -71,3 +71,7 @@ external.system.type.url.exists=系统类型和URL组合"{0}"已存在
external.system.disabled=系统已禁用
external.system.sync.failed=系统数据同步失败
external.system.type.not.supported=不支持的系统类型
# Git系统相关错误
external.system.git.auth.type.error=Git系统只支持Token认证
external.system.git.token.required=Git系统必须提供Token

View File

@ -145,4 +145,79 @@ class ExternalSystemServiceImplTest {
assertThat(system.getEnabled()).isFalse();
verify(externalSystemRepository).save(system);
}
@Test
void validateUniqueConstraints_WhenGitWithoutToken_ShouldThrowException() {
// 准备数据
systemDTO.setType(ExternalSystem.SystemType.GIT);
systemDTO.setAuthType(ExternalSystem.AuthType.TOKEN);
systemDTO.setToken(null);
// Mock
when(externalSystemRepository.existsByNameAndDeletedFalse(systemDTO.getName())).thenReturn(false);
when(externalSystemRepository.existsByTypeAndUrlAndDeletedFalse(systemDTO.getType(), systemDTO.getUrl()))
.thenReturn(false);
// 验证
assertThatThrownBy(() -> externalSystemService.validateUniqueConstraints(systemDTO))
.isInstanceOf(BusinessException.class)
.hasFieldOrPropertyWithValue("errorCode", ResponseCode.EXTERNAL_SYSTEM_GIT_TOKEN_REQUIRED);
}
@Test
void validateUniqueConstraints_WhenGitWithWrongAuthType_ShouldThrowException() {
// 准备数据
systemDTO.setType(ExternalSystem.SystemType.GIT);
systemDTO.setAuthType(ExternalSystem.AuthType.BASIC);
// Mock
when(externalSystemRepository.existsByNameAndDeletedFalse(systemDTO.getName())).thenReturn(false);
when(externalSystemRepository.existsByTypeAndUrlAndDeletedFalse(systemDTO.getType(), systemDTO.getUrl()))
.thenReturn(false);
// 验证
assertThatThrownBy(() -> externalSystemService.validateUniqueConstraints(systemDTO))
.isInstanceOf(BusinessException.class)
.hasFieldOrPropertyWithValue("errorCode", ResponseCode.EXTERNAL_SYSTEM_GIT_AUTH_TYPE_ERROR);
}
@Test
void update_WhenGitWithoutToken_ShouldThrowException() {
// 准备数据
systemDTO.setType(ExternalSystem.SystemType.GIT);
systemDTO.setAuthType(ExternalSystem.AuthType.TOKEN);
systemDTO.setToken(null);
// 验证
assertThatThrownBy(() -> externalSystemService.update(1L, systemDTO))
.isInstanceOf(BusinessException.class)
.hasFieldOrPropertyWithValue("errorCode", ResponseCode.EXTERNAL_SYSTEM_GIT_TOKEN_REQUIRED);
}
@Test
void update_WhenGitWithWrongAuthType_ShouldThrowException() {
// 准备数据
systemDTO.setType(ExternalSystem.SystemType.GIT);
systemDTO.setAuthType(ExternalSystem.AuthType.BASIC);
// 验证
assertThatThrownBy(() -> externalSystemService.update(1L, systemDTO))
.isInstanceOf(BusinessException.class)
.hasFieldOrPropertyWithValue("errorCode", ResponseCode.EXTERNAL_SYSTEM_GIT_AUTH_TYPE_ERROR);
}
@Test
void testConnection_WhenSuccess_ShouldUpdateLastConnectTime() {
// Mock
when(externalSystemRepository.findById(1L)).thenReturn(Optional.of(system));
when(externalSystemRepository.save(any(ExternalSystem.class))).thenReturn(system);
// 执行
boolean result = externalSystemService.testConnection(1L);
// 验证
assertThat(result).isTrue();
assertThat(system.getLastConnectTime()).isNotNull();
verify(externalSystemRepository).save(system);
}
}