@kodelyth/googlechat 2026.5.42 → 2026.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/klaw.plugin.json +967 -2
- package/package.json +16 -4
- package/api.ts +0 -3
- package/channel-config-api.ts +0 -1
- package/channel-plugin-api.ts +0 -1
- package/config-api.ts +0 -2
- package/contract-api.ts +0 -5
- package/doctor-contract-api.ts +0 -1
- package/index.ts +0 -20
- package/runtime-api.ts +0 -55
- package/secret-contract-api.ts +0 -5
- package/setup-entry.ts +0 -13
- package/setup-plugin-api.ts +0 -3
- package/src/accounts.ts +0 -181
- package/src/actions.test.ts +0 -289
- package/src/actions.ts +0 -227
- package/src/api.ts +0 -316
- package/src/approval-auth.test.ts +0 -24
- package/src/approval-auth.ts +0 -32
- package/src/auth.ts +0 -218
- package/src/channel-config.test.ts +0 -39
- package/src/channel.adapters.ts +0 -340
- package/src/channel.deps.runtime.ts +0 -29
- package/src/channel.runtime.ts +0 -17
- package/src/channel.setup.ts +0 -98
- package/src/channel.test.ts +0 -784
- package/src/channel.ts +0 -277
- package/src/config-schema.test.ts +0 -31
- package/src/config-schema.ts +0 -3
- package/src/doctor-contract.test.ts +0 -75
- package/src/doctor-contract.ts +0 -182
- package/src/doctor.ts +0 -57
- package/src/gateway.ts +0 -63
- package/src/google-auth.runtime.test.ts +0 -543
- package/src/google-auth.runtime.ts +0 -568
- package/src/group-policy.ts +0 -17
- package/src/monitor-access.test.ts +0 -491
- package/src/monitor-access.ts +0 -465
- package/src/monitor-durable.test.ts +0 -39
- package/src/monitor-durable.ts +0 -23
- package/src/monitor-reply-delivery.ts +0 -156
- package/src/monitor-routing.ts +0 -65
- package/src/monitor-types.ts +0 -33
- package/src/monitor-webhook.test.ts +0 -587
- package/src/monitor-webhook.ts +0 -303
- package/src/monitor.reply-delivery.test.ts +0 -144
- package/src/monitor.test.ts +0 -159
- package/src/monitor.ts +0 -527
- package/src/monitor.webhook-routing.test.ts +0 -257
- package/src/runtime.ts +0 -9
- package/src/secret-contract.test.ts +0 -60
- package/src/secret-contract.ts +0 -161
- package/src/setup-core.ts +0 -40
- package/src/setup-surface.ts +0 -243
- package/src/setup.test.ts +0 -619
- package/src/targets.test.ts +0 -453
- package/src/targets.ts +0 -66
- package/src/types.config.ts +0 -3
- package/src/types.ts +0 -73
- package/test-api.ts +0 -2
- package/tsconfig.json +0 -16
package/src/setup.test.ts
DELETED
|
@@ -1,619 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
expectLifecyclePatch,
|
|
3
|
-
expectPendingUntilAbort,
|
|
4
|
-
startAccountAndTrackLifecycle,
|
|
5
|
-
} from "klaw/plugin-sdk/channel-test-helpers";
|
|
6
|
-
import {
|
|
7
|
-
createPluginSetupWizardConfigure,
|
|
8
|
-
createPluginSetupWizardStatus,
|
|
9
|
-
createTestWizardPrompter,
|
|
10
|
-
runSetupWizardConfigure,
|
|
11
|
-
} from "klaw/plugin-sdk/plugin-test-runtime";
|
|
12
|
-
import type { WizardPrompter } from "klaw/plugin-sdk/plugin-test-runtime";
|
|
13
|
-
import { DEFAULT_ACCOUNT_ID } from "klaw/plugin-sdk/setup";
|
|
14
|
-
import { afterAll, afterEach, describe, expect, it, vi } from "vitest";
|
|
15
|
-
import type { KlawConfig } from "../runtime-api.js";
|
|
16
|
-
import {
|
|
17
|
-
listGoogleChatAccountIds,
|
|
18
|
-
resolveGoogleChatAccount,
|
|
19
|
-
resolveDefaultGoogleChatAccountId,
|
|
20
|
-
type ResolvedGoogleChatAccount,
|
|
21
|
-
} from "./accounts.js";
|
|
22
|
-
import { startGoogleChatGatewayAccount } from "./gateway.js";
|
|
23
|
-
import { googlechatSetupAdapter } from "./setup-core.js";
|
|
24
|
-
import { googlechatSetupWizard } from "./setup-surface.js";
|
|
25
|
-
|
|
26
|
-
const hoisted = vi.hoisted(() => ({
|
|
27
|
-
startGoogleChatMonitor: vi.fn(),
|
|
28
|
-
}));
|
|
29
|
-
|
|
30
|
-
vi.mock("./channel.runtime.js", () => ({
|
|
31
|
-
googleChatChannelRuntime: {
|
|
32
|
-
resolveGoogleChatWebhookPath: ({
|
|
33
|
-
account,
|
|
34
|
-
}: {
|
|
35
|
-
account: { config: { webhookPath?: string } };
|
|
36
|
-
}) => account.config.webhookPath ?? "/googlechat",
|
|
37
|
-
startGoogleChatMonitor: hoisted.startGoogleChatMonitor,
|
|
38
|
-
},
|
|
39
|
-
}));
|
|
40
|
-
|
|
41
|
-
const googlechatSetupPlugin = {
|
|
42
|
-
id: "googlechat",
|
|
43
|
-
meta: {
|
|
44
|
-
label: "Google Chat",
|
|
45
|
-
},
|
|
46
|
-
config: {
|
|
47
|
-
defaultAccountId: resolveDefaultGoogleChatAccountId,
|
|
48
|
-
listAccountIds: listGoogleChatAccountIds,
|
|
49
|
-
},
|
|
50
|
-
setupWizard: googlechatSetupWizard,
|
|
51
|
-
} as never;
|
|
52
|
-
|
|
53
|
-
const googlechatConfigure = createPluginSetupWizardConfigure(googlechatSetupPlugin);
|
|
54
|
-
const googlechatStatus = createPluginSetupWizardStatus(googlechatSetupPlugin);
|
|
55
|
-
|
|
56
|
-
function buildAccount(): ResolvedGoogleChatAccount {
|
|
57
|
-
return {
|
|
58
|
-
accountId: "default",
|
|
59
|
-
enabled: true,
|
|
60
|
-
credentialSource: "inline",
|
|
61
|
-
credentials: {},
|
|
62
|
-
config: {
|
|
63
|
-
webhookPath: "/googlechat",
|
|
64
|
-
webhookUrl: "https://example.com/googlechat",
|
|
65
|
-
audienceType: "app-url",
|
|
66
|
-
audience: "https://example.com/googlechat",
|
|
67
|
-
},
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
async function waitForGoogleChatMonitorStarted() {
|
|
72
|
-
await vi.waitFor(() => expect(hoisted.startGoogleChatMonitor).toHaveBeenCalledOnce());
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
describe("googlechat setup", () => {
|
|
76
|
-
afterEach(() => {
|
|
77
|
-
vi.clearAllMocks();
|
|
78
|
-
vi.unstubAllEnvs();
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
afterAll(() => {
|
|
82
|
-
vi.doUnmock("./channel.runtime.js");
|
|
83
|
-
vi.resetModules();
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
it("rejects env auth for non-default accounts", () => {
|
|
87
|
-
if (!googlechatSetupAdapter.validateInput) {
|
|
88
|
-
throw new Error("Expected googlechatSetupAdapter.validateInput to be defined");
|
|
89
|
-
}
|
|
90
|
-
expect(
|
|
91
|
-
googlechatSetupAdapter.validateInput({
|
|
92
|
-
accountId: "secondary",
|
|
93
|
-
input: { useEnv: true },
|
|
94
|
-
} as never),
|
|
95
|
-
).toBe("GOOGLE_CHAT_SERVICE_ACCOUNT env vars can only be used for the default account.");
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
it("requires inline or file credentials when env auth is not used", () => {
|
|
99
|
-
if (!googlechatSetupAdapter.validateInput) {
|
|
100
|
-
throw new Error("Expected googlechatSetupAdapter.validateInput to be defined");
|
|
101
|
-
}
|
|
102
|
-
expect(
|
|
103
|
-
googlechatSetupAdapter.validateInput({
|
|
104
|
-
accountId: DEFAULT_ACCOUNT_ID,
|
|
105
|
-
input: { useEnv: false, token: "", tokenFile: "" },
|
|
106
|
-
} as never),
|
|
107
|
-
).toBe("Google Chat requires --token (service account JSON) or --token-file.");
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
it("builds a patch from token-file and trims optional webhook fields", () => {
|
|
111
|
-
if (!googlechatSetupAdapter.applyAccountConfig) {
|
|
112
|
-
throw new Error("Expected googlechatSetupAdapter.applyAccountConfig to be defined");
|
|
113
|
-
}
|
|
114
|
-
expect(
|
|
115
|
-
googlechatSetupAdapter.applyAccountConfig({
|
|
116
|
-
cfg: { channels: { googlechat: {} } },
|
|
117
|
-
accountId: DEFAULT_ACCOUNT_ID,
|
|
118
|
-
input: {
|
|
119
|
-
name: "Default",
|
|
120
|
-
tokenFile: "/tmp/googlechat.json",
|
|
121
|
-
audienceType: " app-url ",
|
|
122
|
-
audience: " https://example.com/googlechat ",
|
|
123
|
-
webhookPath: " /googlechat ",
|
|
124
|
-
webhookUrl: " https://example.com/googlechat/hook ",
|
|
125
|
-
},
|
|
126
|
-
} as never),
|
|
127
|
-
).toEqual({
|
|
128
|
-
channels: {
|
|
129
|
-
googlechat: {
|
|
130
|
-
enabled: true,
|
|
131
|
-
name: "Default",
|
|
132
|
-
serviceAccountFile: "/tmp/googlechat.json",
|
|
133
|
-
audienceType: "app-url",
|
|
134
|
-
audience: "https://example.com/googlechat",
|
|
135
|
-
webhookPath: "/googlechat",
|
|
136
|
-
webhookUrl: "https://example.com/googlechat/hook",
|
|
137
|
-
},
|
|
138
|
-
},
|
|
139
|
-
});
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
it("prefers inline token patch when token-file is absent", () => {
|
|
143
|
-
if (!googlechatSetupAdapter.applyAccountConfig) {
|
|
144
|
-
throw new Error("Expected googlechatSetupAdapter.applyAccountConfig to be defined");
|
|
145
|
-
}
|
|
146
|
-
expect(
|
|
147
|
-
googlechatSetupAdapter.applyAccountConfig({
|
|
148
|
-
cfg: { channels: { googlechat: {} } },
|
|
149
|
-
accountId: DEFAULT_ACCOUNT_ID,
|
|
150
|
-
input: {
|
|
151
|
-
name: "Default",
|
|
152
|
-
token: { client_email: "bot@example.com" },
|
|
153
|
-
},
|
|
154
|
-
} as never),
|
|
155
|
-
).toEqual({
|
|
156
|
-
channels: {
|
|
157
|
-
googlechat: {
|
|
158
|
-
enabled: true,
|
|
159
|
-
name: "Default",
|
|
160
|
-
serviceAccount: { client_email: "bot@example.com" },
|
|
161
|
-
},
|
|
162
|
-
},
|
|
163
|
-
});
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
it("configures service-account auth and webhook audience", async () => {
|
|
167
|
-
const prompter = createTestWizardPrompter({
|
|
168
|
-
text: vi.fn(async ({ message }: { message: string }) => {
|
|
169
|
-
if (message === "Service account JSON path") {
|
|
170
|
-
return "/tmp/googlechat-service-account.json";
|
|
171
|
-
}
|
|
172
|
-
if (message === "App URL") {
|
|
173
|
-
return "https://example.com/googlechat";
|
|
174
|
-
}
|
|
175
|
-
throw new Error(`Unexpected prompt: ${message}`);
|
|
176
|
-
}) as WizardPrompter["text"],
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
const result = await runSetupWizardConfigure({
|
|
180
|
-
configure: googlechatConfigure,
|
|
181
|
-
cfg: {} as KlawConfig,
|
|
182
|
-
prompter,
|
|
183
|
-
options: {},
|
|
184
|
-
});
|
|
185
|
-
|
|
186
|
-
expect(result.accountId).toBe("default");
|
|
187
|
-
expect(result.cfg.channels?.googlechat?.enabled).toBe(true);
|
|
188
|
-
expect(result.cfg.channels?.googlechat?.serviceAccountFile).toBe(
|
|
189
|
-
"/tmp/googlechat-service-account.json",
|
|
190
|
-
);
|
|
191
|
-
expect(result.cfg.channels?.googlechat?.audienceType).toBe("app-url");
|
|
192
|
-
expect(result.cfg.channels?.googlechat?.audience).toBe("https://example.com/googlechat");
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
it("reads the named-account DM policy instead of the channel root", () => {
|
|
196
|
-
expect(
|
|
197
|
-
googlechatSetupWizard.dmPolicy?.getCurrent(
|
|
198
|
-
{
|
|
199
|
-
channels: {
|
|
200
|
-
googlechat: {
|
|
201
|
-
dm: {
|
|
202
|
-
policy: "disabled",
|
|
203
|
-
},
|
|
204
|
-
accounts: {
|
|
205
|
-
alerts: {
|
|
206
|
-
serviceAccount: { client_email: "bot@example.com" },
|
|
207
|
-
dm: {
|
|
208
|
-
policy: "allowlist",
|
|
209
|
-
},
|
|
210
|
-
},
|
|
211
|
-
},
|
|
212
|
-
},
|
|
213
|
-
},
|
|
214
|
-
} as KlawConfig,
|
|
215
|
-
"alerts",
|
|
216
|
-
),
|
|
217
|
-
).toBe("allowlist");
|
|
218
|
-
});
|
|
219
|
-
|
|
220
|
-
it("reports configured state for the selected account instead of any account", async () => {
|
|
221
|
-
const status = await googlechatStatus({
|
|
222
|
-
cfg: {
|
|
223
|
-
channels: {
|
|
224
|
-
googlechat: {
|
|
225
|
-
accounts: {
|
|
226
|
-
default: {
|
|
227
|
-
serviceAccount: { client_email: "default@example.com" },
|
|
228
|
-
},
|
|
229
|
-
alerts: {},
|
|
230
|
-
},
|
|
231
|
-
},
|
|
232
|
-
},
|
|
233
|
-
} as KlawConfig,
|
|
234
|
-
accountOverrides: {
|
|
235
|
-
googlechat: "alerts",
|
|
236
|
-
},
|
|
237
|
-
options: {},
|
|
238
|
-
});
|
|
239
|
-
|
|
240
|
-
expect(status.configured).toBe(false);
|
|
241
|
-
});
|
|
242
|
-
|
|
243
|
-
it("reports configured state for the configured defaultAccount instead of any account", async () => {
|
|
244
|
-
const status = await googlechatStatus({
|
|
245
|
-
cfg: {
|
|
246
|
-
channels: {
|
|
247
|
-
googlechat: {
|
|
248
|
-
defaultAccount: "alerts",
|
|
249
|
-
accounts: {
|
|
250
|
-
default: {
|
|
251
|
-
serviceAccount: { client_email: "default@example.com" },
|
|
252
|
-
},
|
|
253
|
-
alerts: {},
|
|
254
|
-
},
|
|
255
|
-
},
|
|
256
|
-
},
|
|
257
|
-
} as KlawConfig,
|
|
258
|
-
accountOverrides: {},
|
|
259
|
-
options: {},
|
|
260
|
-
});
|
|
261
|
-
|
|
262
|
-
expect(status.configured).toBe(false);
|
|
263
|
-
});
|
|
264
|
-
|
|
265
|
-
it("reports account-scoped config keys for named accounts", () => {
|
|
266
|
-
expect(googlechatSetupWizard.dmPolicy?.resolveConfigKeys?.({}, "alerts")).toEqual({
|
|
267
|
-
policyKey: "channels.googlechat.accounts.alerts.dm.policy",
|
|
268
|
-
allowFromKey: "channels.googlechat.accounts.alerts.dm.allowFrom",
|
|
269
|
-
});
|
|
270
|
-
});
|
|
271
|
-
|
|
272
|
-
it("uses configured defaultAccount for omitted DM policy account context", () => {
|
|
273
|
-
const cfg = {
|
|
274
|
-
channels: {
|
|
275
|
-
googlechat: {
|
|
276
|
-
defaultAccount: "alerts",
|
|
277
|
-
dm: {
|
|
278
|
-
policy: "disabled",
|
|
279
|
-
},
|
|
280
|
-
accounts: {
|
|
281
|
-
alerts: {
|
|
282
|
-
serviceAccount: { client_email: "bot@example.com" },
|
|
283
|
-
dm: {
|
|
284
|
-
policy: "allowlist",
|
|
285
|
-
},
|
|
286
|
-
},
|
|
287
|
-
},
|
|
288
|
-
},
|
|
289
|
-
},
|
|
290
|
-
} as KlawConfig;
|
|
291
|
-
|
|
292
|
-
expect(googlechatSetupWizard.dmPolicy?.getCurrent(cfg)).toBe("allowlist");
|
|
293
|
-
expect(googlechatSetupWizard.dmPolicy?.resolveConfigKeys?.(cfg)).toEqual({
|
|
294
|
-
policyKey: "channels.googlechat.accounts.alerts.dm.policy",
|
|
295
|
-
allowFromKey: "channels.googlechat.accounts.alerts.dm.allowFrom",
|
|
296
|
-
});
|
|
297
|
-
|
|
298
|
-
const next = googlechatSetupWizard.dmPolicy?.setPolicy(cfg, "open");
|
|
299
|
-
expect(next?.channels?.googlechat?.dm?.policy).toBe("disabled");
|
|
300
|
-
expect(next?.channels?.googlechat?.accounts?.alerts?.dm?.policy).toBe("open");
|
|
301
|
-
});
|
|
302
|
-
|
|
303
|
-
it("uses configured defaultAccount for omitted allowFrom prompt context", async () => {
|
|
304
|
-
const prompter = {
|
|
305
|
-
note: vi.fn(async () => {}),
|
|
306
|
-
text: vi.fn(async () => "users/123456789"),
|
|
307
|
-
};
|
|
308
|
-
|
|
309
|
-
const next = await googlechatSetupWizard.dmPolicy?.promptAllowFrom?.({
|
|
310
|
-
cfg: {
|
|
311
|
-
channels: {
|
|
312
|
-
googlechat: {
|
|
313
|
-
defaultAccount: "alerts",
|
|
314
|
-
dm: {
|
|
315
|
-
allowFrom: ["users/root"],
|
|
316
|
-
},
|
|
317
|
-
accounts: {
|
|
318
|
-
alerts: {
|
|
319
|
-
serviceAccount: { client_email: "bot@example.com" },
|
|
320
|
-
dm: {
|
|
321
|
-
allowFrom: ["users/alerts"],
|
|
322
|
-
},
|
|
323
|
-
},
|
|
324
|
-
},
|
|
325
|
-
},
|
|
326
|
-
},
|
|
327
|
-
} as KlawConfig,
|
|
328
|
-
prompter: prompter as any,
|
|
329
|
-
});
|
|
330
|
-
|
|
331
|
-
expect(next?.channels?.googlechat?.dm?.allowFrom).toEqual(["users/root"]);
|
|
332
|
-
expect(next?.channels?.googlechat?.accounts?.alerts?.dm?.allowFrom).toEqual([
|
|
333
|
-
"users/123456789",
|
|
334
|
-
]);
|
|
335
|
-
});
|
|
336
|
-
|
|
337
|
-
it('writes open DM policy to the named account and preserves inherited allowFrom with "*"', () => {
|
|
338
|
-
const next = googlechatSetupWizard.dmPolicy?.setPolicy(
|
|
339
|
-
{
|
|
340
|
-
channels: {
|
|
341
|
-
googlechat: {
|
|
342
|
-
dm: {
|
|
343
|
-
allowFrom: ["users/123"],
|
|
344
|
-
},
|
|
345
|
-
accounts: {
|
|
346
|
-
alerts: {
|
|
347
|
-
serviceAccount: { client_email: "bot@example.com" },
|
|
348
|
-
},
|
|
349
|
-
},
|
|
350
|
-
},
|
|
351
|
-
},
|
|
352
|
-
} as KlawConfig,
|
|
353
|
-
"open",
|
|
354
|
-
"alerts",
|
|
355
|
-
);
|
|
356
|
-
|
|
357
|
-
expect(next?.channels?.googlechat?.dm?.policy).toBeUndefined();
|
|
358
|
-
expect(next?.channels?.googlechat?.accounts?.alerts?.dm?.policy).toBe("open");
|
|
359
|
-
expect(next?.channels?.googlechat?.accounts?.alerts?.dm?.allowFrom).toEqual(["users/123", "*"]);
|
|
360
|
-
});
|
|
361
|
-
|
|
362
|
-
it("keeps startAccount pending until abort, then unregisters", async () => {
|
|
363
|
-
const unregister = vi.fn();
|
|
364
|
-
hoisted.startGoogleChatMonitor.mockResolvedValue(unregister);
|
|
365
|
-
|
|
366
|
-
const { abort, patches, task, isSettled } = startAccountAndTrackLifecycle({
|
|
367
|
-
startAccount: startGoogleChatGatewayAccount,
|
|
368
|
-
account: buildAccount(),
|
|
369
|
-
});
|
|
370
|
-
await expectPendingUntilAbort({
|
|
371
|
-
waitForStarted: waitForGoogleChatMonitorStarted,
|
|
372
|
-
isSettled,
|
|
373
|
-
abort,
|
|
374
|
-
task,
|
|
375
|
-
assertBeforeAbort: () => {
|
|
376
|
-
expect(unregister).not.toHaveBeenCalled();
|
|
377
|
-
},
|
|
378
|
-
assertAfterAbort: () => {
|
|
379
|
-
expect(unregister).toHaveBeenCalledOnce();
|
|
380
|
-
},
|
|
381
|
-
});
|
|
382
|
-
expectLifecyclePatch(patches, { running: true });
|
|
383
|
-
expectLifecyclePatch(patches, { running: false });
|
|
384
|
-
});
|
|
385
|
-
});
|
|
386
|
-
|
|
387
|
-
describe("resolveGoogleChatAccount", () => {
|
|
388
|
-
it("parses default-account env JSON credentials only when they decode to an object", () => {
|
|
389
|
-
vi.stubEnv("GOOGLE_CHAT_SERVICE_ACCOUNT", '{"client_email":"bot@example.com"}');
|
|
390
|
-
|
|
391
|
-
const resolved = resolveGoogleChatAccount({
|
|
392
|
-
cfg: { channels: { googlechat: {} } },
|
|
393
|
-
accountId: "default",
|
|
394
|
-
});
|
|
395
|
-
|
|
396
|
-
expect(resolved.credentialSource).toBe("env");
|
|
397
|
-
expect(resolved.credentials).toEqual({ client_email: "bot@example.com" });
|
|
398
|
-
});
|
|
399
|
-
|
|
400
|
-
it("ignores env JSON credentials when they decode to a non-object value", () => {
|
|
401
|
-
vi.stubEnv("GOOGLE_CHAT_SERVICE_ACCOUNT", '["not","an","object"]');
|
|
402
|
-
vi.stubEnv("GOOGLE_CHAT_SERVICE_ACCOUNT_FILE", "/tmp/googlechat.json");
|
|
403
|
-
|
|
404
|
-
const resolved = resolveGoogleChatAccount({
|
|
405
|
-
cfg: { channels: { googlechat: {} } },
|
|
406
|
-
accountId: "default",
|
|
407
|
-
});
|
|
408
|
-
|
|
409
|
-
expect(resolved.credentialSource).toBe("env");
|
|
410
|
-
expect(resolved.credentials).toBeUndefined();
|
|
411
|
-
expect(resolved.credentialsFile).toBe("/tmp/googlechat.json");
|
|
412
|
-
});
|
|
413
|
-
|
|
414
|
-
it("inherits shared defaults from accounts.default for named accounts", () => {
|
|
415
|
-
const cfg: KlawConfig = {
|
|
416
|
-
channels: {
|
|
417
|
-
googlechat: {
|
|
418
|
-
accounts: {
|
|
419
|
-
default: {
|
|
420
|
-
audienceType: "app-url",
|
|
421
|
-
audience: "https://example.com/googlechat",
|
|
422
|
-
webhookPath: "/googlechat",
|
|
423
|
-
},
|
|
424
|
-
andy: {
|
|
425
|
-
serviceAccountFile: "/tmp/andy-sa.json",
|
|
426
|
-
},
|
|
427
|
-
},
|
|
428
|
-
},
|
|
429
|
-
},
|
|
430
|
-
};
|
|
431
|
-
|
|
432
|
-
const resolved = resolveGoogleChatAccount({ cfg, accountId: "andy" });
|
|
433
|
-
expect(resolved.config.audienceType).toBe("app-url");
|
|
434
|
-
expect(resolved.config.audience).toBe("https://example.com/googlechat");
|
|
435
|
-
expect(resolved.config.webhookPath).toBe("/googlechat");
|
|
436
|
-
expect(resolved.config.serviceAccountFile).toBe("/tmp/andy-sa.json");
|
|
437
|
-
});
|
|
438
|
-
|
|
439
|
-
it("prefers top-level and account overrides over accounts.default", () => {
|
|
440
|
-
const cfg: KlawConfig = {
|
|
441
|
-
channels: {
|
|
442
|
-
googlechat: {
|
|
443
|
-
audienceType: "project-number",
|
|
444
|
-
audience: "1234567890",
|
|
445
|
-
accounts: {
|
|
446
|
-
default: {
|
|
447
|
-
audienceType: "app-url",
|
|
448
|
-
audience: "https://default.example.com/googlechat",
|
|
449
|
-
webhookPath: "/googlechat-default",
|
|
450
|
-
},
|
|
451
|
-
april: {
|
|
452
|
-
webhookPath: "/googlechat-april",
|
|
453
|
-
},
|
|
454
|
-
},
|
|
455
|
-
},
|
|
456
|
-
},
|
|
457
|
-
};
|
|
458
|
-
|
|
459
|
-
const resolved = resolveGoogleChatAccount({ cfg, accountId: "april" });
|
|
460
|
-
expect(resolved.config.audienceType).toBe("project-number");
|
|
461
|
-
expect(resolved.config.audience).toBe("1234567890");
|
|
462
|
-
expect(resolved.config.webhookPath).toBe("/googlechat-april");
|
|
463
|
-
});
|
|
464
|
-
|
|
465
|
-
it("merges account bot loop protection over top-level defaults field-by-field", () => {
|
|
466
|
-
const cfg: KlawConfig = {
|
|
467
|
-
channels: {
|
|
468
|
-
googlechat: {
|
|
469
|
-
botLoopProtection: {
|
|
470
|
-
maxEventsPerWindow: 8,
|
|
471
|
-
windowSeconds: 120,
|
|
472
|
-
cooldownSeconds: 240,
|
|
473
|
-
},
|
|
474
|
-
accounts: {
|
|
475
|
-
april: {
|
|
476
|
-
webhookPath: "/googlechat-april",
|
|
477
|
-
botLoopProtection: {
|
|
478
|
-
maxEventsPerWindow: 3,
|
|
479
|
-
},
|
|
480
|
-
},
|
|
481
|
-
},
|
|
482
|
-
},
|
|
483
|
-
},
|
|
484
|
-
};
|
|
485
|
-
|
|
486
|
-
const resolved = resolveGoogleChatAccount({ cfg, accountId: "april" });
|
|
487
|
-
expect(resolved.config.botLoopProtection).toEqual({
|
|
488
|
-
maxEventsPerWindow: 3,
|
|
489
|
-
windowSeconds: 120,
|
|
490
|
-
cooldownSeconds: 240,
|
|
491
|
-
});
|
|
492
|
-
});
|
|
493
|
-
|
|
494
|
-
it("merges account bot loop protection over accounts.default field-by-field", () => {
|
|
495
|
-
const cfg: KlawConfig = {
|
|
496
|
-
channels: {
|
|
497
|
-
googlechat: {
|
|
498
|
-
accounts: {
|
|
499
|
-
default: {
|
|
500
|
-
webhookPath: "/googlechat",
|
|
501
|
-
botLoopProtection: {
|
|
502
|
-
windowSeconds: 120,
|
|
503
|
-
cooldownSeconds: 240,
|
|
504
|
-
},
|
|
505
|
-
},
|
|
506
|
-
april: {
|
|
507
|
-
webhookPath: "/googlechat-april",
|
|
508
|
-
botLoopProtection: {
|
|
509
|
-
maxEventsPerWindow: 3,
|
|
510
|
-
},
|
|
511
|
-
},
|
|
512
|
-
},
|
|
513
|
-
},
|
|
514
|
-
},
|
|
515
|
-
};
|
|
516
|
-
|
|
517
|
-
const resolved = resolveGoogleChatAccount({ cfg, accountId: "april" });
|
|
518
|
-
expect(resolved.config.botLoopProtection).toEqual({
|
|
519
|
-
maxEventsPerWindow: 3,
|
|
520
|
-
windowSeconds: 120,
|
|
521
|
-
cooldownSeconds: 240,
|
|
522
|
-
});
|
|
523
|
-
});
|
|
524
|
-
|
|
525
|
-
it("does not inherit disabled state from accounts.default for named accounts", () => {
|
|
526
|
-
const cfg: KlawConfig = {
|
|
527
|
-
channels: {
|
|
528
|
-
googlechat: {
|
|
529
|
-
accounts: {
|
|
530
|
-
default: {
|
|
531
|
-
enabled: false,
|
|
532
|
-
audienceType: "app-url",
|
|
533
|
-
audience: "https://example.com/googlechat",
|
|
534
|
-
},
|
|
535
|
-
andy: {
|
|
536
|
-
serviceAccountFile: "/tmp/andy-sa.json",
|
|
537
|
-
},
|
|
538
|
-
},
|
|
539
|
-
},
|
|
540
|
-
},
|
|
541
|
-
};
|
|
542
|
-
|
|
543
|
-
const resolved = resolveGoogleChatAccount({ cfg, accountId: "andy" });
|
|
544
|
-
expect(resolved.enabled).toBe(true);
|
|
545
|
-
expect(resolved.config.enabled).toBeUndefined();
|
|
546
|
-
expect(resolved.config.audienceType).toBe("app-url");
|
|
547
|
-
});
|
|
548
|
-
|
|
549
|
-
it("does not inherit default-account credentials into named accounts", () => {
|
|
550
|
-
const cfg: KlawConfig = {
|
|
551
|
-
channels: {
|
|
552
|
-
googlechat: {
|
|
553
|
-
accounts: {
|
|
554
|
-
default: {
|
|
555
|
-
serviceAccountRef: {
|
|
556
|
-
source: "env",
|
|
557
|
-
provider: "test",
|
|
558
|
-
id: "default-sa",
|
|
559
|
-
},
|
|
560
|
-
audienceType: "app-url",
|
|
561
|
-
audience: "https://example.com/googlechat",
|
|
562
|
-
},
|
|
563
|
-
andy: {
|
|
564
|
-
serviceAccountFile: "/tmp/andy-sa.json",
|
|
565
|
-
},
|
|
566
|
-
},
|
|
567
|
-
},
|
|
568
|
-
},
|
|
569
|
-
};
|
|
570
|
-
|
|
571
|
-
const resolved = resolveGoogleChatAccount({ cfg, accountId: "andy" });
|
|
572
|
-
expect(resolved.credentialSource).toBe("file");
|
|
573
|
-
expect(resolved.credentialsFile).toBe("/tmp/andy-sa.json");
|
|
574
|
-
expect(resolved.config.audienceType).toBe("app-url");
|
|
575
|
-
});
|
|
576
|
-
|
|
577
|
-
it("does not inherit dangerous name matching from accounts.default", () => {
|
|
578
|
-
const cfg: KlawConfig = {
|
|
579
|
-
channels: {
|
|
580
|
-
googlechat: {
|
|
581
|
-
accounts: {
|
|
582
|
-
default: {
|
|
583
|
-
dangerouslyAllowNameMatching: true,
|
|
584
|
-
audienceType: "app-url",
|
|
585
|
-
audience: "https://example.com/googlechat",
|
|
586
|
-
},
|
|
587
|
-
andy: {
|
|
588
|
-
serviceAccountFile: "/tmp/andy-sa.json",
|
|
589
|
-
},
|
|
590
|
-
},
|
|
591
|
-
},
|
|
592
|
-
},
|
|
593
|
-
};
|
|
594
|
-
|
|
595
|
-
const resolved = resolveGoogleChatAccount({ cfg, accountId: "andy" });
|
|
596
|
-
expect(resolved.config.dangerouslyAllowNameMatching).toBeUndefined();
|
|
597
|
-
expect(resolved.config.audienceType).toBe("app-url");
|
|
598
|
-
});
|
|
599
|
-
|
|
600
|
-
it("uses configured defaultAccount when accountId is omitted", () => {
|
|
601
|
-
const cfg: KlawConfig = {
|
|
602
|
-
channels: {
|
|
603
|
-
googlechat: {
|
|
604
|
-
defaultAccount: "alerts",
|
|
605
|
-
accounts: {
|
|
606
|
-
alerts: {
|
|
607
|
-
serviceAccountFile: "/tmp/alerts-sa.json",
|
|
608
|
-
},
|
|
609
|
-
},
|
|
610
|
-
},
|
|
611
|
-
},
|
|
612
|
-
};
|
|
613
|
-
|
|
614
|
-
const resolved = resolveGoogleChatAccount({ cfg });
|
|
615
|
-
expect(resolved.accountId).toBe("alerts");
|
|
616
|
-
expect(resolved.credentialSource).toBe("file");
|
|
617
|
-
expect(resolved.credentialsFile).toBe("/tmp/alerts-sa.json");
|
|
618
|
-
});
|
|
619
|
-
});
|