fix(wiki): make pageType permission service a mandatory dependency

This commit is contained in:
matevip 2026-05-31 07:58:59 +08:00
parent 6583aa1e42
commit 551321b542
4 changed files with 26 additions and 17 deletions

View File

@ -79,22 +79,24 @@ public class WikiTool {
private WikiTransformationAggregator transformationAggregator; private WikiTransformationAggregator transformationAggregator;
/** /**
* Per-agent pageType permission gate. When absent (e.g. in isolated unit * Per-agent pageType permission gate. Mandatory: this is a security control,
* tests), every page is readable preserving pre-permission behaviour. * so it is a required constructor dependency rather than an optional bean
* a missing gate must fail loudly at startup, never silently fail open.
*/ */
@Autowired(required = false) private final WikiPageTypePermissionService pageTypePermissionService;
private WikiPageTypePermissionService pageTypePermissionService;
public WikiTool(WikiPageService pageService, public WikiTool(WikiPageService pageService,
WikiKnowledgeBaseService kbService, WikiKnowledgeBaseService kbService,
WikiRawMaterialService rawService, WikiRawMaterialService rawService,
HybridRetriever hybridRetriever, HybridRetriever hybridRetriever,
ObjectMapper objectMapper) { ObjectMapper objectMapper,
WikiPageTypePermissionService pageTypePermissionService) {
this.pageService = pageService; this.pageService = pageService;
this.kbService = kbService; this.kbService = kbService;
this.rawService = rawService; this.rawService = rawService;
this.hybridRetriever = hybridRetriever; this.hybridRetriever = hybridRetriever;
this.objectMapper = objectMapper; this.objectMapper = objectMapper;
this.pageTypePermissionService = pageTypePermissionService;
} }
// ==================== Knowledge-base discovery ==================== // ==================== Knowledge-base discovery ====================
@ -1054,12 +1056,12 @@ public class WikiTool {
/** /**
* Resolve the agent's pageType read/write permission view for a KB once, * Resolve the agent's pageType read/write permission view for a KB once,
* so a tool call can filter a whole result set without re-querying. Returns * so a tool call can filter a whole result set without re-querying. Never
* {@code null} when the permission service is absent (isolated unit tests), * null the service is a mandatory dependency, so there is no fail-open
* in which case all reads are allowed. * path; an agent with no rows still resolves to the KB's default policy.
*/ */
private WikiPageTypePermissionService.Access pageTypeAccess(Long agentId, Long kbId) { private WikiPageTypePermissionService.Access pageTypeAccess(Long agentId, Long kbId) {
return pageTypePermissionService == null ? null : pageTypePermissionService.resolve(agentId, kbId); return pageTypePermissionService.resolve(agentId, kbId);
} }
/** Whether the resolved access permits reading {@code page}. Null-safe. */ /** Whether the resolved access permits reading {@code page}. Null-safe. */
@ -1100,9 +1102,6 @@ public class WikiTool {
*/ */
private String checkWrite(Long agentId, Long kbId, String pageType, private String checkWrite(Long agentId, Long kbId, String pageType,
WikiPageTypePermissionService.WriteOp op) { WikiPageTypePermissionService.WriteOp op) {
if (pageTypePermissionService == null) {
return null;
}
WikiPageTypePermissionService.WriteDecision decision = WikiPageTypePermissionService.WriteDecision decision =
pageTypePermissionService.resolveWrite(agentId, kbId, pageType, op); pageTypePermissionService.resolveWrite(agentId, kbId, pageType, op);
String typeLabel = (pageType == null || pageType.isBlank()) ? "(default)" : pageType; String typeLabel = (pageType == null || pageType.isBlank()) ? "(default)" : pageType;

View File

@ -62,8 +62,14 @@ class WikiToolKbNameRoutingTest {
private final HybridRetriever hybridRetriever = mock(HybridRetriever.class); private final HybridRetriever hybridRetriever = mock(HybridRetriever.class);
private final ObjectMapper objectMapper = new ObjectMapper(); private final ObjectMapper objectMapper = new ObjectMapper();
// Allow-all permission service (no rows configured) this test exercises
// KB-name routing, not permissions.
private final vip.mate.wiki.service.WikiPageTypePermissionService permissionService =
new vip.mate.wiki.service.WikiPageTypePermissionService(
mock(vip.mate.wiki.repository.WikiAgentPageTypePermissionMapper.class), kbService, objectMapper);
private final WikiTool tool = new WikiTool(pageService, kbService, rawService, private final WikiTool tool = new WikiTool(pageService, kbService, rawService,
hybridRetriever, objectMapper); hybridRetriever, objectMapper, permissionService);
private static WikiKnowledgeBaseEntity kb(long id, String name, Long agentId) { private static WikiKnowledgeBaseEntity kb(long id, String name, Long agentId) {
WikiKnowledgeBaseEntity entity = new WikiKnowledgeBaseEntity(); WikiKnowledgeBaseEntity entity = new WikiKnowledgeBaseEntity();

View File

@ -2,7 +2,6 @@ package vip.mate.wiki.tool;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.test.util.ReflectionTestUtils;
import vip.mate.wiki.model.WikiAgentPageTypePermissionEntity; import vip.mate.wiki.model.WikiAgentPageTypePermissionEntity;
import vip.mate.wiki.model.WikiKnowledgeBaseEntity; import vip.mate.wiki.model.WikiKnowledgeBaseEntity;
import vip.mate.wiki.model.WikiPageEntity; import vip.mate.wiki.model.WikiPageEntity;
@ -56,8 +55,7 @@ class WikiToolPermissionTest {
WikiPageTypePermissionService permService = WikiPageTypePermissionService permService =
new WikiPageTypePermissionService(permMapper, kbService, om); new WikiPageTypePermissionService(permMapper, kbService, om);
WikiTool tool = new WikiTool(pageService, kbService, rawService, retriever, om); WikiTool tool = new WikiTool(pageService, kbService, rawService, retriever, om, permService);
ReflectionTestUtils.setField(tool, "pageTypePermissionService", permService);
return new Harness(tool, pageService, permMapper); return new Harness(tool, pageService, permMapper);
} }

View File

@ -61,8 +61,14 @@ class WikiToolSpringBindingTest {
private final HybridRetriever hybridRetriever = mock(HybridRetriever.class); private final HybridRetriever hybridRetriever = mock(HybridRetriever.class);
private final ObjectMapper objectMapper = new ObjectMapper(); private final ObjectMapper objectMapper = new ObjectMapper();
// Allow-all permission service (no rows configured) this test exercises
// tool binding, not permissions.
private final vip.mate.wiki.service.WikiPageTypePermissionService permissionService =
new vip.mate.wiki.service.WikiPageTypePermissionService(
mock(vip.mate.wiki.repository.WikiAgentPageTypePermissionMapper.class), kbService, objectMapper);
private final WikiTool tool = new WikiTool(pageService, kbService, rawService, private final WikiTool tool = new WikiTool(pageService, kbService, rawService,
hybridRetriever, objectMapper); hybridRetriever, objectMapper, permissionService);
private ToolCallback callbackFor(String functionName) { private ToolCallback callbackFor(String functionName) {
return Arrays.stream(ToolCallbacks.from(tool)) return Arrays.stream(ToolCallbacks.from(tool))