增加接口连接成功时间
This commit is contained in:
parent
9b16146cd0
commit
46304d6682
@ -51,7 +51,7 @@ public class ExternalSystem extends Entity<Long> {
|
|||||||
private Boolean enabled = true;
|
private Boolean enabled = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 认证方式:BASIC/TOKEN/OAUTH等
|
* 认证方式:BASIC/TOKEN/OAUTH<EFBFBD><EFBFBD>
|
||||||
*/
|
*/
|
||||||
@Column(name = "auth_type", nullable = false)
|
@Column(name = "auth_type", nullable = false)
|
||||||
@Enumerated(EnumType.STRING)
|
@Enumerated(EnumType.STRING)
|
||||||
@ -63,7 +63,7 @@ public class ExternalSystem extends Entity<Long> {
|
|||||||
private String username;
|
private String username;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 密码/密钥
|
* 密码
|
||||||
*/
|
*/
|
||||||
private String password;
|
private String password;
|
||||||
|
|
||||||
@ -85,6 +85,12 @@ public class ExternalSystem extends Entity<Long> {
|
|||||||
@Column(name = "last_sync_time")
|
@Column(name = "last_sync_time")
|
||||||
private LocalDateTime lastSyncTime;
|
private LocalDateTime lastSyncTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最近连接成功时间
|
||||||
|
*/
|
||||||
|
@Column(name = "last_connect_time")
|
||||||
|
private LocalDateTime lastConnectTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 系统特有配置,JSON格式
|
* 系统特有配置,JSON格式
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -70,7 +70,17 @@ public enum ResponseCode {
|
|||||||
EXTERNAL_SYSTEM_TYPE_URL_EXISTS(2501, "external.system.type.url.exists"),
|
EXTERNAL_SYSTEM_TYPE_URL_EXISTS(2501, "external.system.type.url.exists"),
|
||||||
EXTERNAL_SYSTEM_DISABLED(2502, "external.system.disabled"),
|
EXTERNAL_SYSTEM_DISABLED(2502, "external.system.disabled"),
|
||||||
EXTERNAL_SYSTEM_SYNC_FAILED(2503, "external.system.sync.failed"),
|
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 int code;
|
||||||
private final String messageKey; // 国际化消息key
|
private final String messageKey; // 国际化消息key
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import org.springframework.http.*;
|
import org.springframework.http.*;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.web.client.RestTemplate;
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
import org.springframework.web.client.HttpClientErrorException;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
@ -16,11 +17,9 @@ public class GitIntegration implements IExternalSystemIntegration {
|
|||||||
@Override
|
@Override
|
||||||
public boolean testConnection(ExternalSystem system) {
|
public boolean testConnection(ExternalSystem system) {
|
||||||
try {
|
try {
|
||||||
String url = system.getUrl() + "/api/v4/version"; // GitLab API
|
String url = system.getUrl() + "/api/v4/version";
|
||||||
HttpHeaders headers = new HttpHeaders();
|
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);
|
HttpEntity<String> entity = new HttpEntity<>(headers);
|
||||||
ResponseEntity<String> response = restTemplate.exchange(
|
ResponseEntity<String> response = restTemplate.exchange(
|
||||||
@ -31,8 +30,14 @@ public class GitIntegration implements IExternalSystemIntegration {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return response.getStatusCode() == HttpStatus.OK;
|
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) {
|
} 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;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -43,5 +43,7 @@ public class ExternalSystemDTO extends BaseDTO {
|
|||||||
|
|
||||||
private LocalDateTime lastSyncTime;
|
private LocalDateTime lastSyncTime;
|
||||||
|
|
||||||
|
private LocalDateTime lastConnectTime;
|
||||||
|
|
||||||
private String config;
|
private String config;
|
||||||
}
|
}
|
||||||
@ -13,6 +13,7 @@ import com.qqchen.deploy.backend.service.IExternalSystemService;
|
|||||||
import jakarta.annotation.PostConstruct;
|
import jakarta.annotation.PostConstruct;
|
||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
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,
|
throw new UniqueConstraintException(ResponseCode.EXTERNAL_SYSTEM_TYPE_URL_EXISTS,
|
||||||
"type and url", dto.getType() + ":" + dto.getUrl());
|
"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
|
@Override
|
||||||
@ -84,7 +110,12 @@ public class ExternalSystemServiceImpl extends BaseServiceImpl<ExternalSystem, E
|
|||||||
throw new BusinessException(ResponseCode.EXTERNAL_SYSTEM_TYPE_NOT_SUPPORTED);
|
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
|
@Override
|
||||||
|
|||||||
@ -145,7 +145,7 @@ CREATE TABLE sys_role_tag (
|
|||||||
version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号',
|
version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号',
|
||||||
|
|
||||||
name VARCHAR(50) NOT NULL 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='角色标签表';
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='角色标签表';
|
||||||
|
|
||||||
-- 角色标签关联表
|
-- 角色标签关联表
|
||||||
@ -249,20 +249,16 @@ CREATE TABLE sys_external_system (
|
|||||||
remark TEXT NULL COMMENT '备注说明',
|
remark TEXT NULL COMMENT '备注说明',
|
||||||
sort INT NULL DEFAULT 0 COMMENT '排序',
|
sort INT NULL DEFAULT 0 COMMENT '排序',
|
||||||
enabled BIT NOT NULL DEFAULT 1 COMMENT '是否启用(0:禁用,1:启用)',
|
enabled BIT NOT NULL DEFAULT 1 COMMENT '是否启用(0:禁用,1:启用)',
|
||||||
|
auth_type VARCHAR(50) NOT NULL COMMENT '认证方式(BASIC/TOKEN/OAUTH等)',
|
||||||
auth_type VARCHAR(50) NOT NULL COMMENT '认证方式(BASIC:基础认证,TOKEN:令牌认证,OAUTH:OAuth认证)',
|
|
||||||
username VARCHAR(100) NULL COMMENT '用户名',
|
username VARCHAR(100) NULL COMMENT '用户名',
|
||||||
password VARCHAR(255) NULL COMMENT '密码/密钥',
|
password VARCHAR(255) NULL COMMENT '密码',
|
||||||
token VARCHAR(255) NULL COMMENT '访问令牌',
|
token VARCHAR(255) NULL COMMENT '访问令牌',
|
||||||
|
sync_status VARCHAR(50) NULL COMMENT '同步状态(SUCCESS/FAILED/RUNNING)',
|
||||||
sync_status ENUM ('SUCCESS', 'FAILED', 'RUNNING') NULL COMMENT '最后同步状态',
|
|
||||||
last_sync_time DATETIME(6) NULL COMMENT '最后同步时间',
|
last_sync_time DATETIME(6) NULL COMMENT '最后同步时间',
|
||||||
|
last_connect_time DATETIME(6) NULL COMMENT '最近连接成功时间',
|
||||||
config JSON NULL COMMENT '系统特有配置(JSON格式)',
|
config JSON NULL COMMENT '系统特有配置',
|
||||||
|
|
||||||
CONSTRAINT UK_external_system_name UNIQUE (name),
|
CONSTRAINT UK_external_system_name UNIQUE (name),
|
||||||
CONSTRAINT UK_external_system_type_url UNIQUE (type, url),
|
CONSTRAINT UK_external_system_type_url UNIQUE (type, url)
|
||||||
INDEX IDX_type (type),
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='外部系统表';
|
||||||
INDEX IDX_enabled (enabled)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='外部系统配置表';
|
|
||||||
|
|
||||||
@ -131,9 +131,18 @@ VALUES
|
|||||||
-- --------------------------------------------------------------------------------------
|
-- --------------------------------------------------------------------------------------
|
||||||
|
|
||||||
-- 初始化外部系统
|
-- 初始化外部系统
|
||||||
INSERT INTO sys_external_system (id, create_time, name, type, url, auth_type, username, password, enabled, sort)
|
INSERT INTO sys_external_system (
|
||||||
VALUES
|
id, create_by, create_time, deleted, update_by, update_time, version,
|
||||||
(1, NOW(), 'Jenkins测试环境', 'JENKINS', 'http://jenkins-test.example.com', 'BASIC', 'admin', 'jenkins123', 1, 1),
|
name, type, url, remark, sort, enabled, auth_type, username, password, token,
|
||||||
(2, NOW(), 'Jenkins生产环境', 'JENKINS', 'http://jenkins-prod.example.com', 'BASIC', 'admin', 'jenkins123', 1, 2),
|
sync_status, last_sync_time, last_connect_time, config
|
||||||
(3, NOW(), 'GitLab', 'GIT', 'http://gitlab.example.com', 'TOKEN', NULL, NULL, 1, 3),
|
) VALUES (
|
||||||
(4, NOW(), '禅道', 'ZENTAO', 'http://zentao.example.com', 'BASIC', 'admin', 'zentao123', 1, 4);
|
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', '{}'
|
||||||
|
);
|
||||||
@ -71,3 +71,7 @@ external.system.type.url.exists=系统类型和URL组合"{0}"已存在
|
|||||||
external.system.disabled=系统已禁用
|
external.system.disabled=系统已禁用
|
||||||
external.system.sync.failed=系统数据同步失败
|
external.system.sync.failed=系统数据同步失败
|
||||||
external.system.type.not.supported=不支持的系统类型
|
external.system.type.not.supported=不支持的系统类型
|
||||||
|
|
||||||
|
# Git系统相关错误
|
||||||
|
external.system.git.auth.type.error=Git系统只支持Token认证
|
||||||
|
external.system.git.token.required=Git系统必须提供Token
|
||||||
@ -145,4 +145,79 @@ class ExternalSystemServiceImplTest {
|
|||||||
assertThat(system.getEnabled()).isFalse();
|
assertThat(system.getEnabled()).isFalse();
|
||||||
verify(externalSystemRepository).save(system);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user