1. 新增外部系统编码部门编码关联管理

2. 新增统一的 api 对外门户管理
3. 修正各个模块的 api 命名
This commit is contained in:
chenbowen
2025-10-17 17:40:46 +08:00
parent ce8e06d2a3
commit 78bc88b7a6
106 changed files with 4200 additions and 1377 deletions

View File

@@ -0,0 +1,63 @@
package com.zt.plat.module.databus.controller.admin.gateway;
import com.zt.plat.module.databus.controller.admin.gateway.vo.ApiGatewayInvokeReqVO;
import com.zt.plat.module.databus.framework.integration.gateway.core.ApiGatewayExecutionService;
import com.zt.plat.module.databus.framework.integration.gateway.model.ApiGatewayResponse;
import com.zt.plat.module.databus.service.gateway.ApiDefinitionService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.web.servlet.MockMvc;
import java.util.Map;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@WebMvcTest(ApiGatewayController.class)
@AutoConfigureMockMvc(addFilters = false)
@TestPropertySource(properties = {
"spring.config.import=optional:",
"spring.cloud.nacos.config.enabled=false",
"spring.cloud.nacos.discovery.enabled=false"
})
class ApiGatewayControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private ApiGatewayExecutionService executionService;
@MockBean
private ApiDefinitionService apiDefinitionService;
@Test
void invokeShouldReturnGatewayEnvelope() throws Exception {
ApiGatewayResponse response = ApiGatewayResponse.builder()
.code(200)
.message("OK")
.response(Map.of("code", 0))
.traceId("trace-123")
.build();
when(executionService.invokeForDebug(any(ApiGatewayInvokeReqVO.class)))
.thenReturn(ResponseEntity.ok(response));
mockMvc.perform(post("/databus/gateway/invoke")
.contentType(MediaType.APPLICATION_JSON)
.content("{\"apiCode\":\"demo\",\"version\":\"v1\"}"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value(200))
.andExpect(jsonPath("$.message").value("OK"))
.andExpect(jsonPath("$.response.code").value(0))
.andExpect(jsonPath("$.traceId").value("trace-123"));
}
}

View File

@@ -0,0 +1,56 @@
package com.zt.plat.module.databus.framework.integration.gateway.policy;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zt.plat.module.databus.framework.integration.gateway.security.GatewayJwtResolver;
import org.junit.jupiter.api.Test;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat;
class DefaultAuthPolicyEvaluatorTest {
private final ObjectMapper objectMapper = new ObjectMapper();
@Test
void shouldResolveTokenFromPrimaryHeader() {
Map<String, Object> headers = new HashMap<>();
headers.put(GatewayJwtResolver.HEADER_ZT_AUTH_TOKEN, List.of(" token-123 "));
String token = GatewayJwtResolver.resolveJwtToken(headers, Map.of(), objectMapper);
assertThat(token).isEqualTo("token-123");
}
@Test
void shouldFallbackToAuthorizationHeader() {
Map<String, Object> headers = new HashMap<>();
headers.put("Authorization", "Bearer token-456");
String token = GatewayJwtResolver.resolveJwtToken(headers, Map.of(), objectMapper);
assertThat(token).isEqualTo("token-456");
}
@Test
void shouldParseTokenFromStructuredPayload() {
Map<String, Object> headers = new HashMap<>();
headers.put("Authorization", List.of("", "{\"token\":\"abc-789\"}"));
String token = GatewayJwtResolver.resolveJwtToken(headers, Map.of(), objectMapper);
assertThat(token).isEqualTo("abc-789");
}
@Test
void shouldUseQueryParameterAsLastResort() {
Map<String, Object> headers = Map.of();
Map<String, Object> queryParams = Map.of("token", " token-999 ");
String token = GatewayJwtResolver.resolveJwtToken(headers, queryParams, objectMapper);
assertThat(token).isEqualTo("token-999");
}
}

View File

@@ -0,0 +1,99 @@
package com.zt.plat.module.databus.framework.integration.gateway.step.impl;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.zt.plat.framework.common.exception.ServiceException;
import com.zt.plat.module.databus.dal.dataobject.gateway.ApiStepDO;
import com.zt.plat.module.databus.enums.gateway.ExpressionTypeEnum;
import com.zt.plat.module.databus.framework.integration.gateway.domain.ApiDefinitionAggregate;
import com.zt.plat.module.databus.framework.integration.gateway.domain.ApiStepDefinition;
import com.zt.plat.module.databus.framework.integration.gateway.expression.ExpressionEvaluatorRegistry;
import com.zt.plat.module.databus.framework.integration.gateway.expression.ExpressionExecutor;
import com.zt.plat.module.databus.framework.integration.gateway.expression.JsonataExpressionEvaluator;
import com.zt.plat.module.databus.framework.integration.gateway.model.ApiInvocationContext;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.integration.core.GenericHandler;
import org.springframework.messaging.MessageHeaders;
import java.util.Collections;
import java.util.Map;
import static com.zt.plat.module.databus.service.gateway.impl.GatewayServiceErrorCodeConstants.API_STEP_START_EXECUTION_FAILED;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
class StartStepHandlerTest {
private StartStepHandler handler;
private ApiDefinitionAggregate aggregate;
private static MessageHeaders emptyHeaders() {
return new MessageHeaders(Collections.emptyMap());
}
private static ObjectMapper createObjectMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
return mapper;
}
@BeforeEach
void setUp() {
ExpressionEvaluatorRegistry registry = new ExpressionEvaluatorRegistry();
registry.register(ExpressionTypeEnum.JSON, new JsonataExpressionEvaluator(createObjectMapper()));
handler = new StartStepHandler(new ExpressionExecutor(registry));
aggregate = ApiDefinitionAggregate.builder().build();
}
@Test
void shouldApplyRequestMappingsToInvocationContext() {
ApiStepDO stepDO = new ApiStepDO();
stepDO.setId(101L);
stepDO.setType("START");
stepDO.setRequestMappingExpr("JSON::{\"requestHeaders\": {\"x-trace\": \"trace-1\"}, \"body\": {\"wrapped\": $}, \"requestQuery\": {\"flag\": \"Y\"}} ");
ApiStepDefinition stepDefinition = ApiStepDefinition.builder().step(stepDO).build();
ApiInvocationContext context = ApiInvocationContext.create();
context.setRequestBody(Map.of("original", "value"));
context.getRequestHeaders().put("tenant-id", "42");
GenericHandler<ApiInvocationContext> genericHandler = handler.build(aggregate, stepDefinition);
ApiInvocationContext result = (ApiInvocationContext) genericHandler.handle(context, emptyHeaders());
assertThat(result).isSameAs(context);
assertThat(result.getRequestHeaders()).containsEntry("x-trace", "trace-1");
assertThat(result.getRequestQueryParams()).containsEntry("flag", "Y");
assertThat(result.getRequestBody()).isInstanceOf(Map.class);
@SuppressWarnings("unchecked")
Map<String, ?> mappedBody = (Map<String, ?>) result.getRequestBody();
assertThat(mappedBody).containsKey("wrapped");
assertThat(result.getStepResults()).hasSize(1);
assertThat(result.getStepResults().get(0).isSuccess()).isTrue();
assertThat(result.getStepResults().get(0).getStepId()).isEqualTo(101L);
}
@Test
void shouldRecordFailureWhenExpressionInvalid() {
ApiStepDO stepDO = new ApiStepDO();
stepDO.setId(202L);
stepDO.setType("START");
stepDO.setRequestMappingExpr("JSON::{invalid}");
ApiStepDefinition stepDefinition = ApiStepDefinition.builder().step(stepDO).build();
ApiInvocationContext context = ApiInvocationContext.create();
GenericHandler<ApiInvocationContext> genericHandler = handler.build(aggregate, stepDefinition);
assertThatThrownBy(() -> {
genericHandler.handle(context, emptyHeaders());
})
.isInstanceOf(ServiceException.class)
.extracting(ex -> ((ServiceException) ex).getCode())
.isEqualTo(API_STEP_START_EXECUTION_FAILED.getCode());
assertThat(context.getStepResults()).hasSize(1);
assertThat(context.getStepResults().get(0).isSuccess()).isFalse();
assertThat(context.getStepResults().get(0).getStepId()).isEqualTo(202L);
}
}

View File

@@ -1,7 +1,6 @@
DELETE FROM "databus_api_transform";
DELETE FROM "databus_api_step";
DELETE FROM "databus_api_definition";
DELETE FROM "databus_policy_auth";
DELETE FROM "databus_policy_rate_limit";
DELETE FROM "databus_policy_audit";
DELETE FROM "databus_api_flow_publish";

View File

@@ -1,18 +1,14 @@
CREATE TABLE IF NOT EXISTS databus_api_definition (
id BIGINT PRIMARY KEY,
api_code VARCHAR(255) NOT NULL,
uri_pattern VARCHAR(512),
http_method VARCHAR(16),
version VARCHAR(64),
status INT,
description VARCHAR(1024),
auth_policy_id BIGINT,
rate_limit_id BIGINT,
audit_policy_id BIGINT,
response_template CLOB,
cache_strategy VARCHAR(255),
updated_at TIMESTAMP,
grey_released BOOLEAN,
tenant_id BIGINT,
create_time TIMESTAMP,
update_time TIMESTAMP,
@@ -32,7 +28,6 @@ CREATE TABLE IF NOT EXISTS databus_api_step (
response_mapping_expr VARCHAR(1024),
transform_id BIGINT,
timeout BIGINT,
retry_strategy VARCHAR(255),
fallback_strategy VARCHAR(255),
condition_expr VARCHAR(1024),
stop_on_error BOOLEAN,
@@ -60,20 +55,6 @@ CREATE TABLE IF NOT EXISTS databus_api_transform (
deleted BOOLEAN
);
CREATE TABLE IF NOT EXISTS databus_policy_auth (
id BIGINT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
type VARCHAR(64),
config CLOB,
description VARCHAR(512),
tenant_id BIGINT,
create_time TIMESTAMP,
update_time TIMESTAMP,
creator VARCHAR(64),
updater VARCHAR(64),
deleted BOOLEAN
);
CREATE TABLE IF NOT EXISTS databus_policy_rate_limit (
id BIGINT PRIMARY KEY,
name VARCHAR(255) NOT NULL,