test: split WhatsApp inbound access control tests

This commit is contained in:
Peter Steinberger
2026-02-14 19:49:18 +01:00
parent 743f4b2849
commit 8719f381d1
2 changed files with 105 additions and 38 deletions

View File

@@ -0,0 +1,105 @@
import { beforeEach, describe, expect, it, vi } from "vitest";
import { checkInboundAccessControl } from "./access-control.js";
const sendMessageMock = vi.fn();
const readAllowFromStoreMock = vi.fn();
const upsertPairingRequestMock = vi.fn();
let config: Record<string, unknown> = {};
vi.mock("../../config/config.js", async (importOriginal) => {
const actual = await importOriginal<typeof import("../../config/config.js")>();
return {
...actual,
loadConfig: () => config,
};
});
vi.mock("../../pairing/pairing-store.js", () => ({
readChannelAllowFromStore: (...args: unknown[]) => readAllowFromStoreMock(...args),
upsertChannelPairingRequest: (...args: unknown[]) => upsertPairingRequestMock(...args),
}));
beforeEach(() => {
config = {
channels: {
whatsapp: {
dmPolicy: "pairing",
allowFrom: [],
},
},
};
sendMessageMock.mockReset().mockResolvedValue(undefined);
readAllowFromStoreMock.mockReset().mockResolvedValue([]);
upsertPairingRequestMock.mockReset().mockResolvedValue({ code: "PAIRCODE", created: true });
});
describe("WhatsApp dmPolicy precedence", () => {
it("uses account-level dmPolicy instead of channel-level (#8736)", async () => {
// Channel-level says "pairing" but the account-level says "allowlist".
// The account-level override should take precedence, so an unauthorized
// sender should be blocked silently (no pairing reply).
config = {
channels: {
whatsapp: {
dmPolicy: "pairing",
accounts: {
work: {
dmPolicy: "allowlist",
allowFrom: ["+15559999999"],
},
},
},
},
};
const result = await checkInboundAccessControl({
accountId: "work",
from: "+15550001111",
selfE164: "+15550009999",
senderE164: "+15550001111",
group: false,
pushName: "Stranger",
isFromMe: false,
sock: { sendMessage: sendMessageMock },
remoteJid: "15550001111@s.whatsapp.net",
});
expect(result.allowed).toBe(false);
expect(upsertPairingRequestMock).not.toHaveBeenCalled();
expect(sendMessageMock).not.toHaveBeenCalled();
});
it("inherits channel-level dmPolicy when account-level dmPolicy is unset", async () => {
// Account has allowFrom set, but no dmPolicy override. Should inherit the channel default.
// With dmPolicy=allowlist, unauthorized senders are silently blocked.
config = {
channels: {
whatsapp: {
dmPolicy: "allowlist",
accounts: {
work: {
allowFrom: ["+15559999999"],
},
},
},
},
};
const result = await checkInboundAccessControl({
accountId: "work",
from: "+15550001111",
selfE164: "+15550009999",
senderE164: "+15550001111",
group: false,
pushName: "Stranger",
isFromMe: false,
sock: { sendMessage: sendMessageMock },
remoteJid: "15550001111@s.whatsapp.net",
});
expect(result.allowed).toBe(false);
expect(upsertPairingRequestMock).not.toHaveBeenCalled();
expect(sendMessageMock).not.toHaveBeenCalled();
});
});

View File

@@ -83,41 +83,3 @@ describe("checkInboundAccessControl", () => {
expect(sendMessageMock).toHaveBeenCalled();
});
});
describe("account-level dmPolicy override (#8736)", () => {
it("uses account-level dmPolicy instead of channel-level", async () => {
// Channel-level says "pairing" but the account-level says "allowlist".
// The account-level override should take precedence, so an unauthorized
// sender should be blocked silently (no pairing reply).
config = {
channels: {
whatsapp: {
dmPolicy: "pairing",
accounts: {
work: {
dmPolicy: "allowlist",
allowFrom: ["+15559999999"],
},
},
},
},
};
const result = await checkInboundAccessControl({
accountId: "work",
from: "+15550001111",
selfE164: "+15550009999",
senderE164: "+15550001111",
group: false,
pushName: "Stranger",
isFromMe: false,
sock: { sendMessage: sendMessageMock },
remoteJid: "15550001111@s.whatsapp.net",
});
expect(result.allowed).toBe(false);
// dmPolicy "allowlist" should silently block — no pairing request, no reply
expect(upsertPairingRequestMock).not.toHaveBeenCalled();
expect(sendMessageMock).not.toHaveBeenCalled();
});
});