feat(condition): SERVICE 判断收口——flw_router 增 direct_host/reg_app_key 两列(登记即持有,跨应用覆盖拒绝);新端点 POST /oapi/flow/router/reg(应用签名即归属);RouteJudgeClient 对 direct_host 行跳过服务目录解析直连(TargetSpec.fromUrl),存量手工行走目录解析零变化;契约测试与 SQL 留档
This commit is contained in:
@@ -3,7 +3,9 @@ package com.yunhai.flowcenter.oapi;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.yunhai.flowcenter.entity.FlwDef;
|
||||
import com.yunhai.flowcenter.entity.FlwRouter;
|
||||
import com.yunhai.flowcenter.service.DiagramTokenService;
|
||||
import com.yunhai.flowcenter.service.FlowRouterAdminService;
|
||||
import com.yunhai.flowcenter.service.OapiFlowService;
|
||||
import com.yunhai.flowcenter.support.FlowTestSupport;
|
||||
import com.yunhai.flowcenter.support.OapiSignedClient;
|
||||
@@ -50,6 +52,9 @@ class OapiFlowContractIT extends FlowTestSupport {
|
||||
@Autowired
|
||||
private OapiFlowService flowService;
|
||||
|
||||
@Autowired
|
||||
private FlowRouterAdminService routerAdminService;
|
||||
|
||||
@Autowired
|
||||
private DiagramTokenService tokenService;
|
||||
|
||||
@@ -507,6 +512,78 @@ class OapiFlowContractIT extends FlowTestSupport {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断服务自注册契约(2026-10-12 SERVICE 收口,yh-flow-callback starter 的落点):未验签 401;
|
||||
* 登记即持有(新增行带 directHost、regAppKey/serviceKey=签名 appKey);同键重复登记幂等更新
|
||||
* (status 不被翻正);校验项业务码拒绝。跨应用覆盖拒绝见 FlowRouterAdminServiceRegisterTest。
|
||||
*/
|
||||
@Test
|
||||
void routerReg_selfRegistration_contract() {
|
||||
String reg = "{\"routerKey\":\"svc-hall.demo-judge\",\"name\":\"演示判断\","
|
||||
+ "\"judgePath\":\"/oapi/flow/route/judge\","
|
||||
+ "\"directHost\":\"http://open-gateway-service:10013/svc-hall\"}";
|
||||
|
||||
// 未验签(不带签名头)→ 401,不落行(本路径同受 /oapi/* 强制验签保护)
|
||||
assertEquals(401, client.getRaw("/oapi/flow/router/reg").getStatusCodeValue());
|
||||
assertFalse(routerRepository.findByRouterKey("svc-hall.demo-judge").isPresent());
|
||||
|
||||
// 登记 → 行落库,归属=签名 appKey
|
||||
assertEquals(0, client.post("/oapi/flow/router/reg", reg, JsonNode.class)
|
||||
.getBody().get("code").asInt(), "自注册应成功");
|
||||
FlwRouter row = routerRepository.findByRouterKey("svc-hall.demo-judge").get();
|
||||
assertEquals(APP_KEY, row.getRegAppKey());
|
||||
assertEquals(APP_KEY, row.getServiceKey(), "serviceKey 填归属 appKey(管理端『来源』展示用)");
|
||||
assertEquals("http://open-gateway-service:10013/svc-hall", row.getDirectHost());
|
||||
assertEquals("/oapi/flow/route/judge", row.getPath());
|
||||
assertEquals(1, row.getStatus().intValue());
|
||||
Long id = row.getId();
|
||||
|
||||
// 管理员停用后自注册 → 仍成功但不翻正 status(控制权在管理员)
|
||||
routerAdminService.setStatus(id, false);
|
||||
assertEquals(0, client.post("/oapi/flow/router/reg", reg, JsonNode.class).getBody().get("code").asInt());
|
||||
assertEquals(0, routerRepository.findByRouterKey("svc-hall.demo-judge").get().getStatus().intValue(),
|
||||
"停用状态不被自注册翻正");
|
||||
|
||||
// 重复登记(改名+换址)→ 同一行更新,不新增
|
||||
String again = "{\"routerKey\":\"svc-hall.demo-judge\",\"name\":\"演示判断2\","
|
||||
+ "\"judgePath\":\"/oapi/flow/route/judge2\",\"directHost\":\"http://new-host:9000/svc-hall\"}";
|
||||
assertEquals(0, client.post("/oapi/flow/router/reg", again, JsonNode.class)
|
||||
.getBody().get("code").asInt());
|
||||
FlwRouter updated = routerRepository.findByRouterKey("svc-hall.demo-judge").get();
|
||||
assertEquals(id, updated.getId(), "幂等 upsert,不应产生第二行");
|
||||
assertEquals("演示判断2", updated.getName());
|
||||
assertEquals("http://new-host:9000/svc-hall", updated.getDirectHost());
|
||||
assertEquals("/oapi/flow/route/judge2", updated.getPath());
|
||||
|
||||
// 校验项拒绝
|
||||
assertNotEquals(0, client.post("/oapi/flow/router/reg",
|
||||
"{\"routerKey\":\"a.b\",\"name\":\"n\",\"judgePath\":\"oapi/x\",\"directHost\":\"http://h:1\"}",
|
||||
JsonNode.class).getBody().get("code").asInt(), "judgePath 缺前导 / 应拒绝");
|
||||
assertNotEquals(0, client.post("/oapi/flow/router/reg",
|
||||
"{\"routerKey\":\"a.b\",\"name\":\"n\",\"judgePath\":\"/oapi/x\",\"directHost\":\"h:1\"}",
|
||||
JsonNode.class).getBody().get("code").asInt(), "directHost 非 http(s) 基址应拒绝");
|
||||
assertNotEquals(0, client.post("/oapi/flow/router/reg",
|
||||
"{\"name\":\"n\",\"judgePath\":\"/oapi/x\",\"directHost\":\"http://h:1\"}",
|
||||
JsonNode.class).getBody().get("code").asInt(), "routerKey 缺失应拒绝");
|
||||
}
|
||||
|
||||
/**
|
||||
* 自注册行天然满足 SERVICE 发布校验(2026-10-12 验收项):DefValidator 只认 routerKey
|
||||
* 已注册且启用,与 serviceKey 形态无关(自注册行 serviceKey 填的是数值 appKey)。
|
||||
*/
|
||||
@Test
|
||||
void routerReg_selfRegisteredRow_passesServicePublishValidation() {
|
||||
mapDept("km", 101, "甲");
|
||||
mapDept("kb", 102, "乙");
|
||||
String reg = "{\"routerKey\":\"svc-hall.cond-judge\",\"name\":\"条件判断\","
|
||||
+ "\"judgePath\":\"/oapi/flow/route/judge\",\"directHost\":\"http://h:1/svc-hall\"}";
|
||||
assertEquals(0, client.post("/oapi/flow/router/reg", reg, JsonNode.class)
|
||||
.getBody().get("code").asInt());
|
||||
|
||||
FlwDef def = saveAndPublishDef("t17", "自注册引用", conditionDef("svc-hall.cond-judge", "km", "kb"));
|
||||
assertEquals(1, def.getVersion().intValue(), "引用自注册行的 SERVICE 定义应发布成功");
|
||||
}
|
||||
|
||||
/** 轮询等异步回调推送(AFTER_COMMIT + 推送池),最长约 5s */
|
||||
private boolean awaitPayloadContains(List<String> payloads, String needle) throws InterruptedException {
|
||||
for (int i = 0; i < 25; i++) {
|
||||
|
||||
Reference in New Issue
Block a user