Skip to content

Commit eddaf19

Browse files
authored
fix(slack): guard allow-from store resolution in monitor auth (#21967)
1 parent 2a409bb commit eddaf19

File tree

2 files changed

+50
-4
lines changed

2 files changed

+50
-4
lines changed

src/slack/monitor/auth.test.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { beforeEach, describe, expect, it, vi } from "vitest";
2+
import type { SlackMonitorContext } from "./context.js";
3+
4+
const readChannelAllowFromStoreMock = vi.hoisted(() => vi.fn());
5+
6+
vi.mock("../../pairing/pairing-store.js", () => ({
7+
readChannelAllowFromStore: (...args: unknown[]) => readChannelAllowFromStoreMock(...args),
8+
}));
9+
10+
import { resolveSlackEffectiveAllowFrom } from "./auth.js";
11+
12+
function makeSlackCtx(allowFrom: string[]): SlackMonitorContext {
13+
return {
14+
allowFrom,
15+
} as unknown as SlackMonitorContext;
16+
}
17+
18+
describe("resolveSlackEffectiveAllowFrom", () => {
19+
beforeEach(() => {
20+
readChannelAllowFromStoreMock.mockReset();
21+
});
22+
23+
it("falls back to channel config allowFrom when pairing store throws", async () => {
24+
readChannelAllowFromStoreMock.mockRejectedValueOnce(new Error("boom"));
25+
26+
const effective = await resolveSlackEffectiveAllowFrom(makeSlackCtx(["u1"]));
27+
28+
expect(effective.allowFrom).toEqual(["u1"]);
29+
expect(effective.allowFromLower).toEqual(["u1"]);
30+
});
31+
32+
it("treats malformed non-array pairing-store responses as empty", async () => {
33+
readChannelAllowFromStoreMock.mockReturnValueOnce(undefined);
34+
35+
const effective = await resolveSlackEffectiveAllowFrom(makeSlackCtx(["u1"]));
36+
37+
expect(effective.allowFrom).toEqual(["u1"]);
38+
expect(effective.allowFromLower).toEqual(["u1"]);
39+
});
40+
});

src/slack/monitor/auth.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,19 @@ export async function resolveSlackEffectiveAllowFrom(
1313
options?: { includePairingStore?: boolean },
1414
) {
1515
const includePairingStore = options?.includePairingStore === true;
16-
const storeAllowFrom = includePairingStore
17-
? await readStoreAllowFromForDmPolicy({
16+
let storeAllowFrom: string[] = [];
17+
if (includePairingStore) {
18+
try {
19+
const resolved = await readStoreAllowFromForDmPolicy({
1820
provider: "slack",
1921
accountId: ctx.accountId,
2022
dmPolicy: ctx.dmPolicy,
21-
})
22-
: [];
23+
});
24+
storeAllowFrom = Array.isArray(resolved) ? resolved : [];
25+
} catch {
26+
storeAllowFrom = [];
27+
}
28+
}
2329
const allowFrom = normalizeAllowList([...ctx.allowFrom, ...storeAllowFrom]);
2430
const allowFromLower = normalizeAllowListLower(allowFrom);
2531
return { allowFrom, allowFromLower };

0 commit comments

Comments
 (0)