test(mattermost): cover monitor auth gates

This commit is contained in:
Vincent Koc 2026-03-22 18:23:36 -07:00
parent 125e778fe6
commit 1b53918d4f
2 changed files with 235 additions and 0 deletions

View File

@ -0,0 +1,151 @@
import { describe, expect, it, vi } from "vitest";
const evaluateSenderGroupAccessForPolicy = vi.hoisted(() => vi.fn());
const isDangerousNameMatchingEnabled = vi.hoisted(() => vi.fn());
const resolveAllowlistMatchSimple = vi.hoisted(() => vi.fn());
const resolveControlCommandGate = vi.hoisted(() => vi.fn());
const resolveEffectiveAllowFromLists = vi.hoisted(() => vi.fn());
vi.mock("../runtime-api.js", () => ({
evaluateSenderGroupAccessForPolicy,
isDangerousNameMatchingEnabled,
resolveAllowlistMatchSimple,
resolveControlCommandGate,
resolveEffectiveAllowFromLists,
}));
describe("mattermost monitor auth", () => {
it("normalizes allowlist entries and resolves effective lists", async () => {
resolveEffectiveAllowFromLists.mockReturnValue({
effectiveAllowFrom: ["alice"],
effectiveGroupAllowFrom: ["team"],
});
const {
normalizeMattermostAllowEntry,
normalizeMattermostAllowList,
resolveMattermostEffectiveAllowFromLists,
} = await import("./monitor-auth.js");
expect(normalizeMattermostAllowEntry(" @Alice ")).toBe("alice");
expect(normalizeMattermostAllowEntry("mattermost:Bob")).toBe("bob");
expect(normalizeMattermostAllowEntry("*")).toBe("*");
expect(normalizeMattermostAllowList([" Alice ", "user:alice", "ALICE", "*"])).toEqual([
"alice",
"*",
]);
expect(
resolveMattermostEffectiveAllowFromLists({
allowFrom: [" Alice "],
groupAllowFrom: [" Team "],
storeAllowFrom: ["Store"],
dmPolicy: "pairing",
}),
).toEqual({
effectiveAllowFrom: ["alice"],
effectiveGroupAllowFrom: ["team"],
});
expect(resolveEffectiveAllowFromLists).toHaveBeenCalledWith({
allowFrom: ["alice"],
groupAllowFrom: ["team"],
storeAllowFrom: ["store"],
dmPolicy: "pairing",
});
});
it("checks sender allowlists against normalized ids and names", async () => {
resolveAllowlistMatchSimple.mockReturnValue({ allowed: true });
const { isMattermostSenderAllowed } = await import("./monitor-auth.js");
expect(
isMattermostSenderAllowed({
senderId: "@Alice",
senderName: "Alice",
allowFrom: [" mattermost:alice "],
allowNameMatching: true,
}),
).toBe(true);
expect(resolveAllowlistMatchSimple).toHaveBeenCalledWith({
allowFrom: ["alice"],
senderId: "alice",
senderName: "alice",
allowNameMatching: true,
});
});
it("authorizes direct messages in open mode and blocks disabled/group-restricted channels", async () => {
isDangerousNameMatchingEnabled.mockReturnValue(false);
resolveEffectiveAllowFromLists.mockReturnValue({
effectiveAllowFrom: [],
effectiveGroupAllowFrom: [],
});
resolveControlCommandGate.mockReturnValue({
commandAuthorized: false,
shouldBlock: false,
});
evaluateSenderGroupAccessForPolicy.mockReturnValue({
allowed: false,
reason: "empty_allowlist",
});
resolveAllowlistMatchSimple.mockReturnValue({ allowed: false });
const { authorizeMattermostCommandInvocation } = await import("./monitor-auth.js");
expect(
authorizeMattermostCommandInvocation({
account: {
config: { dmPolicy: "open" },
} as never,
cfg: {} as never,
senderId: "alice",
senderName: "Alice",
channelId: "dm-1",
channelInfo: { type: "D", name: "alice", display_name: "Alice" } as never,
allowTextCommands: false,
hasControlCommand: false,
}),
).toMatchObject({
ok: true,
commandAuthorized: true,
kind: "direct",
roomLabel: "#alice",
});
expect(
authorizeMattermostCommandInvocation({
account: {
config: { dmPolicy: "disabled" },
} as never,
cfg: {} as never,
senderId: "alice",
senderName: "Alice",
channelId: "dm-1",
channelInfo: { type: "D", name: "alice", display_name: "Alice" } as never,
allowTextCommands: false,
hasControlCommand: false,
}),
).toMatchObject({
ok: false,
denyReason: "dm-disabled",
});
expect(
authorizeMattermostCommandInvocation({
account: {
config: { groupPolicy: "allowlist" },
} as never,
cfg: {} as never,
senderId: "alice",
senderName: "Alice",
channelId: "chan-1",
channelInfo: { type: "O", name: "town-square", display_name: "Town Square" } as never,
allowTextCommands: true,
hasControlCommand: false,
}),
).toMatchObject({
ok: false,
denyReason: "channel-no-allowlist",
kind: "channel",
});
});
});

View File

@ -0,0 +1,84 @@
import { describe, expect, it, vi } from "vitest";
import {
evaluateMattermostMentionGate,
mapMattermostChannelTypeToChatType,
} from "./monitor-gating.js";
describe("mattermost monitor gating", () => {
it("maps mattermost channel types to chat types", () => {
expect(mapMattermostChannelTypeToChatType("D")).toBe("direct");
expect(mapMattermostChannelTypeToChatType("G")).toBe("group");
expect(mapMattermostChannelTypeToChatType("P")).toBe("group");
expect(mapMattermostChannelTypeToChatType("O")).toBe("channel");
expect(mapMattermostChannelTypeToChatType(undefined)).toBe("channel");
});
it("drops non-mentioned traffic when onchar is enabled but not triggered", () => {
const resolveRequireMention = vi.fn(() => true);
expect(
evaluateMattermostMentionGate({
kind: "channel",
cfg: {} as never,
accountId: "default",
channelId: "chan-1",
resolveRequireMention,
wasMentioned: false,
isControlCommand: false,
commandAuthorized: false,
oncharEnabled: true,
oncharTriggered: false,
canDetectMention: true,
}),
).toEqual({
shouldRequireMention: true,
shouldBypassMention: false,
effectiveWasMentioned: false,
dropReason: "onchar-not-triggered",
});
});
it("bypasses mention for authorized control commands and allows direct chats", () => {
const resolveRequireMention = vi.fn(() => true);
expect(
evaluateMattermostMentionGate({
kind: "channel",
cfg: {} as never,
accountId: "default",
channelId: "chan-1",
resolveRequireMention,
wasMentioned: false,
isControlCommand: true,
commandAuthorized: true,
oncharEnabled: false,
oncharTriggered: false,
canDetectMention: true,
}),
).toEqual({
shouldRequireMention: true,
shouldBypassMention: true,
effectiveWasMentioned: true,
dropReason: null,
});
expect(
evaluateMattermostMentionGate({
kind: "direct",
cfg: {} as never,
accountId: "default",
channelId: "chan-1",
resolveRequireMention,
wasMentioned: false,
isControlCommand: false,
commandAuthorized: false,
oncharEnabled: false,
oncharTriggered: false,
canDetectMention: true,
}),
).toMatchObject({
shouldRequireMention: false,
dropReason: null,
});
});
});