test: share gateway route auth helpers

This commit is contained in:
Peter Steinberger 2026-03-14 00:31:48 +00:00
parent 727fc79ed2
commit 4523260dda
2 changed files with 34 additions and 46 deletions

View File

@ -30,16 +30,20 @@ async function invokeSingleRunAbort({
});
}
function createSingleAbortContext() {
return createChatAbortContext({
chatAbortControllers: new Map([
[
"run-1",
createActiveRun("main", { owner: { connId: "conn-owner", deviceId: "dev-owner" } }),
],
]),
});
}
describe("chat.abort authorization", () => {
it("rejects explicit run aborts from other clients", async () => {
const context = createChatAbortContext({
chatAbortControllers: new Map([
[
"run-1",
createActiveRun("main", { owner: { connId: "conn-owner", deviceId: "dev-owner" } }),
],
]),
});
const context = createSingleAbortContext();
const respond = await invokeSingleRunAbort({
context,
@ -104,14 +108,7 @@ describe("chat.abort authorization", () => {
});
it("allows operator.admin clients to bypass owner checks", async () => {
const context = createChatAbortContext({
chatAbortControllers: new Map([
[
"run-1",
createActiveRun("main", { owner: { connId: "conn-owner", deviceId: "dev-owner" } }),
],
]),
});
const context = createSingleAbortContext();
const respond = await invokeSingleRunAbort({
context,

View File

@ -111,6 +111,23 @@ function createSecurePluginRouteHandler(params: {
});
}
async function invokeSecureGatewayRoute(params: { gatewayAuthSatisfied: boolean }) {
const exactPluginHandler = vi.fn(async () => false);
const prefixGatewayHandler = vi.fn(async () => true);
const handler = createSecurePluginRouteHandler({
exactPluginHandler,
prefixGatewayHandler,
});
const { res } = makeMockHttpResponse();
const handled = await handler(
{ url: "/plugin/secure/report" } as IncomingMessage,
res,
undefined,
{ gatewayAuthSatisfied: params.gatewayAuthSatisfied },
);
return { handled, exactPluginHandler, prefixGatewayHandler };
}
describe("createGatewayPluginRequestHandler", () => {
it("caps unauthenticated plugin routes to non-admin subagent scopes", async () => {
loadOpenClawPlugins.mockReset();
@ -232,44 +249,18 @@ describe("createGatewayPluginRequestHandler", () => {
});
it("fails closed when a matched gateway route reaches dispatch without auth", async () => {
const exactPluginHandler = vi.fn(async () => false);
const prefixGatewayHandler = vi.fn(async () => true);
const handler = createSecurePluginRouteHandler({
exactPluginHandler,
prefixGatewayHandler,
const { handled, exactPluginHandler, prefixGatewayHandler } = await invokeSecureGatewayRoute({
gatewayAuthSatisfied: false,
});
const { res } = makeMockHttpResponse();
const handled = await handler(
{ url: "/plugin/secure/report" } as IncomingMessage,
res,
undefined,
{
gatewayAuthSatisfied: false,
},
);
expect(handled).toBe(false);
expect(exactPluginHandler).not.toHaveBeenCalled();
expect(prefixGatewayHandler).not.toHaveBeenCalled();
});
it("allows gateway route fallthrough only after gateway auth succeeds", async () => {
const exactPluginHandler = vi.fn(async () => false);
const prefixGatewayHandler = vi.fn(async () => true);
const handler = createSecurePluginRouteHandler({
exactPluginHandler,
prefixGatewayHandler,
const { handled, exactPluginHandler, prefixGatewayHandler } = await invokeSecureGatewayRoute({
gatewayAuthSatisfied: true,
});
const { res } = makeMockHttpResponse();
const handled = await handler(
{ url: "/plugin/secure/report" } as IncomingMessage,
res,
undefined,
{
gatewayAuthSatisfied: true,
},
);
expect(handled).toBe(true);
expect(exactPluginHandler).toHaveBeenCalledTimes(1);
expect(prefixGatewayHandler).toHaveBeenCalledTimes(1);