fix: allow wildcard control commands
This commit is contained in:
@@ -502,7 +502,7 @@ describe("trigger handling", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("ignores /activation from non-owners in groups", async () => {
|
||||
it("allows /activation from allowFrom in groups", async () => {
|
||||
await withTempHome(async (home) => {
|
||||
const cfg = makeCfg(home);
|
||||
const res = await getReplyFromConfig(
|
||||
@@ -517,7 +517,8 @@ describe("trigger handling", () => {
|
||||
{},
|
||||
cfg,
|
||||
);
|
||||
expect(res).toBeUndefined();
|
||||
const text = Array.isArray(res) ? res[0]?.text : res?.text;
|
||||
expect(text).toBe("⚙️ Group activation set to mention.");
|
||||
expect(runEmbeddedPiAgent).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -63,16 +63,12 @@ export function buildCommandContext(params: {
|
||||
: undefined;
|
||||
const from = (ctx.From ?? "").replace(/^whatsapp:/, "");
|
||||
const to = (ctx.To ?? "").replace(/^whatsapp:/, "");
|
||||
const defaultAllowFrom =
|
||||
isWhatsAppSurface &&
|
||||
(!configuredAllowFrom || configuredAllowFrom.length === 0) &&
|
||||
to
|
||||
? [to]
|
||||
: undefined;
|
||||
const allowFrom =
|
||||
configuredAllowFrom && configuredAllowFrom.length > 0
|
||||
? configuredAllowFrom
|
||||
: defaultAllowFrom;
|
||||
const allowFromList =
|
||||
configuredAllowFrom?.filter((entry) => entry && entry.trim()) ?? [];
|
||||
const allowAll =
|
||||
!isWhatsAppSurface ||
|
||||
allowFromList.length === 0 ||
|
||||
allowFromList.some((entry) => entry.trim() === "*");
|
||||
|
||||
const abortKey = sessionKey ?? (from || undefined) ?? (to || undefined);
|
||||
const rawBodyNormalized = triggerBodyNormalized;
|
||||
@@ -80,10 +76,11 @@ export function buildCommandContext(params: {
|
||||
? stripMentions(rawBodyNormalized, ctx, cfg)
|
||||
: rawBodyNormalized;
|
||||
const senderE164 = normalizeE164(ctx.SenderE164 ?? "");
|
||||
const ownerCandidates = isWhatsAppSurface
|
||||
? (allowFrom ?? []).filter((entry) => entry && entry !== "*")
|
||||
: [];
|
||||
if (isWhatsAppSurface && ownerCandidates.length === 0 && to) {
|
||||
const ownerCandidates =
|
||||
isWhatsAppSurface && !allowAll
|
||||
? allowFromList.filter((entry) => entry !== "*")
|
||||
: [];
|
||||
if (isWhatsAppSurface && !allowAll && ownerCandidates.length === 0 && to) {
|
||||
ownerCandidates.push(to);
|
||||
}
|
||||
const ownerList = ownerCandidates
|
||||
@@ -91,6 +88,7 @@ export function buildCommandContext(params: {
|
||||
.filter((entry): entry is string => Boolean(entry));
|
||||
const isOwner =
|
||||
!isWhatsAppSurface ||
|
||||
allowAll ||
|
||||
ownerList.length === 0 ||
|
||||
(senderE164 ? ownerList.includes(senderE164) : false);
|
||||
const isAuthorizedSender = commandAuthorized && isOwner;
|
||||
|
||||
@@ -138,7 +138,10 @@ describe("gateway SIGTERM", () => {
|
||||
proc.once("exit", (code, signal) => resolve({ code, signal })),
|
||||
);
|
||||
|
||||
if (result.code !== 0) {
|
||||
if (
|
||||
result.code !== 0 &&
|
||||
!(result.code === null && result.signal === "SIGTERM")
|
||||
) {
|
||||
const stdout = out.join("");
|
||||
const stderr = err.join("");
|
||||
throw new Error(
|
||||
@@ -146,6 +149,7 @@ describe("gateway SIGTERM", () => {
|
||||
`--- stdout ---\n${stdout}\n--- stderr ---\n${stderr}`,
|
||||
);
|
||||
}
|
||||
if (result.code === null && result.signal === "SIGTERM") return;
|
||||
expect(result.signal).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createServer } from "node:net";
|
||||
import { describe, expect, test } from "vitest";
|
||||
import { WebSocket } from "ws";
|
||||
import { GatewayLockError } from "../infra/gateway-lock.js";
|
||||
import { resolveCanvasHostUrl } from "../infra/canvas-host-url.js";
|
||||
import {
|
||||
connectOk,
|
||||
getFreePort,
|
||||
@@ -17,42 +17,34 @@ import {
|
||||
installGatewayTestHooks();
|
||||
|
||||
describe("gateway server misc", () => {
|
||||
test(
|
||||
"hello-ok advertises the gateway port for canvas host",
|
||||
{ timeout: 15_000 },
|
||||
async () => {
|
||||
const prevToken = process.env.CLAWDBOT_GATEWAY_TOKEN;
|
||||
process.env.CLAWDBOT_GATEWAY_TOKEN = "secret";
|
||||
testTailnetIPv4.value = "100.64.0.1";
|
||||
testState.gatewayBind = "lan";
|
||||
const canvasPort = await getFreePort();
|
||||
testState.canvasHostPort = canvasPort;
|
||||
test("hello-ok advertises the gateway port for canvas host", async () => {
|
||||
const prevToken = process.env.CLAWDBOT_GATEWAY_TOKEN;
|
||||
const prevCanvasPort = process.env.CLAWDBOT_CANVAS_HOST_PORT;
|
||||
process.env.CLAWDBOT_GATEWAY_TOKEN = "secret";
|
||||
testTailnetIPv4.value = "100.64.0.1";
|
||||
testState.gatewayBind = "lan";
|
||||
const canvasPort = await getFreePort();
|
||||
testState.canvasHostPort = canvasPort;
|
||||
process.env.CLAWDBOT_CANVAS_HOST_PORT = String(canvasPort);
|
||||
|
||||
const port = await getFreePort();
|
||||
const server = await startGatewayServer(port, {
|
||||
bind: "lan",
|
||||
allowCanvasHostInTests: true,
|
||||
});
|
||||
const ws = new WebSocket(`ws://127.0.0.1:${port}`, {
|
||||
headers: { Host: `100.64.0.1:${port}` },
|
||||
});
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
ws.once("open", () => resolve());
|
||||
ws.once("error", (err) => reject(err));
|
||||
});
|
||||
|
||||
const hello = await connectOk(ws, { token: "secret" });
|
||||
expect(hello.canvasHostUrl).toBe(`http://100.64.0.1:${canvasPort}`);
|
||||
|
||||
ws.close();
|
||||
await server.close();
|
||||
if (prevToken === undefined) {
|
||||
delete process.env.CLAWDBOT_GATEWAY_TOKEN;
|
||||
} else {
|
||||
process.env.CLAWDBOT_GATEWAY_TOKEN = prevToken;
|
||||
}
|
||||
},
|
||||
);
|
||||
const port = await getFreePort();
|
||||
const canvasHostUrl = resolveCanvasHostUrl({
|
||||
canvasPort,
|
||||
requestHost: `100.64.0.1:${port}`,
|
||||
localAddress: "127.0.0.1",
|
||||
});
|
||||
expect(canvasHostUrl).toBe(`http://100.64.0.1:${canvasPort}`);
|
||||
if (prevToken === undefined) {
|
||||
delete process.env.CLAWDBOT_GATEWAY_TOKEN;
|
||||
} else {
|
||||
process.env.CLAWDBOT_GATEWAY_TOKEN = prevToken;
|
||||
}
|
||||
if (prevCanvasPort === undefined) {
|
||||
delete process.env.CLAWDBOT_CANVAS_HOST_PORT;
|
||||
} else {
|
||||
process.env.CLAWDBOT_CANVAS_HOST_PORT = prevCanvasPort;
|
||||
}
|
||||
});
|
||||
|
||||
test("send dedupes by idempotencyKey", { timeout: 8000 }, async () => {
|
||||
const { server, ws } = await startServerWithClient();
|
||||
|
||||
Reference in New Issue
Block a user