mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-28 01:02:57 +00:00
fix(slack): fast-path wildcard open DM policy
This commit is contained in:
64
extensions/slack/src/monitor/dm-auth.test.ts
Normal file
64
extensions/slack/src/monitor/dm-auth.test.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import type { SlackMonitorContext } from "./context.js";
|
||||
import { authorizeSlackDirectMessage } from "./dm-auth.js";
|
||||
|
||||
function makeCtx(dmPolicy: SlackMonitorContext["dmPolicy"]): SlackMonitorContext {
|
||||
return {
|
||||
allowNameMatching: false,
|
||||
dmEnabled: true,
|
||||
dmPolicy,
|
||||
} as SlackMonitorContext;
|
||||
}
|
||||
|
||||
function makeParams(
|
||||
dmPolicy: SlackMonitorContext["dmPolicy"],
|
||||
): Parameters<typeof authorizeSlackDirectMessage>[0] {
|
||||
return {
|
||||
ctx: makeCtx(dmPolicy),
|
||||
accountId: "workspace",
|
||||
senderId: "U123",
|
||||
allowFromLower: [],
|
||||
resolveSenderName: vi.fn(async () => ({ name: "Alice" })),
|
||||
sendPairingReply: vi.fn(),
|
||||
onDisabled: vi.fn(),
|
||||
onUnauthorized: vi.fn(),
|
||||
log: vi.fn(),
|
||||
};
|
||||
}
|
||||
|
||||
describe("authorizeSlackDirectMessage", () => {
|
||||
it("allows open DM policy when effective allowFrom includes wildcard", async () => {
|
||||
const params = makeParams("open");
|
||||
params.allowFromLower = ["*"];
|
||||
params.resolveSenderName = vi.fn(async () => {
|
||||
throw new Error("users.info failed");
|
||||
});
|
||||
|
||||
await expect(authorizeSlackDirectMessage(params)).resolves.toBe(true);
|
||||
|
||||
expect(params.onUnauthorized).not.toHaveBeenCalled();
|
||||
expect(params.resolveSenderName).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("rejects open DM policy when effective allowFrom lacks wildcard", async () => {
|
||||
const params = makeParams("open");
|
||||
|
||||
await expect(authorizeSlackDirectMessage(params)).resolves.toBe(false);
|
||||
|
||||
expect(params.onUnauthorized).toHaveBeenCalledWith({
|
||||
allowMatchMeta: "matchKey=none matchSource=none",
|
||||
senderName: "Alice",
|
||||
});
|
||||
});
|
||||
|
||||
it("keeps allowlist DM policy gated by allowFrom", async () => {
|
||||
const params = makeParams("allowlist");
|
||||
|
||||
await expect(authorizeSlackDirectMessage(params)).resolves.toBe(false);
|
||||
|
||||
expect(params.onUnauthorized).toHaveBeenCalledWith({
|
||||
allowMatchMeta: "matchKey=none matchSource=none",
|
||||
senderName: "Alice",
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -21,6 +21,10 @@ export async function authorizeSlackDirectMessage(params: {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (params.ctx.dmPolicy === "open" && params.allowFromLower.includes("*")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const sender = await params.resolveSenderName(params.senderId);
|
||||
const senderName = sender?.name ?? undefined;
|
||||
const allowMatch = resolveSlackAllowListMatch({
|
||||
|
||||
@@ -167,6 +167,42 @@ describe("slack prepareSlackMessage inbound contract", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("prepares wildcard open-policy account DMs", async () => {
|
||||
const ctx = createInboundSlackCtx({
|
||||
cfg: {
|
||||
channels: {
|
||||
slack: {
|
||||
enabled: true,
|
||||
accounts: {
|
||||
soltea: {
|
||||
dmPolicy: "open",
|
||||
dm: { enabled: true, policy: "open" },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
} as OpenClawConfig,
|
||||
});
|
||||
ctx.accountId = "soltea";
|
||||
ctx.allowFrom = ["*"];
|
||||
ctx.dmPolicy = "open";
|
||||
ctx.resolveUserName = async () => ({ name: "External User" }) as any;
|
||||
|
||||
const prepared = await prepareSlackMessage({
|
||||
ctx,
|
||||
account: createSlackAccount({
|
||||
dmPolicy: "open",
|
||||
dm: { enabled: true, policy: "open" },
|
||||
}),
|
||||
message: createSlackMessage({ channel: "D999", user: "U123", text: "hello" }),
|
||||
opts: { source: "message" },
|
||||
});
|
||||
|
||||
assertPrepared(prepared, "open-policy Slack DM");
|
||||
expect(prepared.ctxPayload.RawBody).toContain("hello");
|
||||
expect(prepared.ctxPayload.From).toBe("slack:U123");
|
||||
});
|
||||
|
||||
it("keeps Slack assistant DM threads in a thread-scoped session with assistant context", async () => {
|
||||
const ctx = createDefaultSlackCtx();
|
||||
ctx.saveSlackAssistantThreadContext({
|
||||
|
||||
Reference in New Issue
Block a user