@kodelyth/nextcloud-talk 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 +799 -2
- package/package.json +16 -4
- package/api.ts +0 -1
- package/channel-plugin-api.ts +0 -1
- package/contract-api.ts +0 -4
- package/doctor-contract-api.ts +0 -1
- package/index.ts +0 -20
- package/runtime-api.ts +0 -29
- package/secret-contract-api.ts +0 -5
- package/setup-entry.ts +0 -13
- package/src/accounts.test.ts +0 -31
- package/src/accounts.ts +0 -149
- package/src/api-credentials.ts +0 -31
- package/src/approval-auth.test.ts +0 -17
- package/src/approval-auth.ts +0 -27
- package/src/bot-preflight.test.ts +0 -135
- package/src/bot-preflight.ts +0 -183
- package/src/channel-api.ts +0 -5
- package/src/channel.adapters.ts +0 -52
- package/src/channel.core.test.ts +0 -75
- package/src/channel.lifecycle.test.ts +0 -91
- package/src/channel.status.test.ts +0 -28
- package/src/channel.ts +0 -225
- package/src/config-schema.ts +0 -79
- package/src/core.test.ts +0 -325
- package/src/doctor-contract.ts +0 -9
- package/src/doctor.test.ts +0 -87
- package/src/doctor.ts +0 -40
- package/src/gateway.ts +0 -109
- package/src/inbound.authz.test.ts +0 -146
- package/src/inbound.behavior.test.ts +0 -309
- package/src/inbound.ts +0 -392
- package/src/message-actions.test.ts +0 -270
- package/src/message-actions.ts +0 -82
- package/src/message-adapter.ts +0 -28
- package/src/monitor-runtime.ts +0 -138
- package/src/monitor.replay.test.ts +0 -276
- package/src/monitor.test-fixtures.ts +0 -30
- package/src/monitor.test-harness.ts +0 -59
- package/src/monitor.ts +0 -385
- package/src/normalize.ts +0 -44
- package/src/policy.ts +0 -111
- package/src/replay-guard.ts +0 -128
- package/src/room-info.test.ts +0 -160
- package/src/room-info.ts +0 -130
- package/src/runtime.ts +0 -9
- package/src/secret-contract.ts +0 -103
- package/src/secret-input.ts +0 -4
- package/src/send.cfg-threading.test.ts +0 -359
- package/src/send.runtime.ts +0 -8
- package/src/send.ts +0 -269
- package/src/session-route.ts +0 -40
- package/src/setup-core.ts +0 -250
- package/src/setup-surface.ts +0 -195
- package/src/setup.test.ts +0 -445
- package/src/signature.ts +0 -82
- package/src/types.ts +0 -195
- package/tsconfig.json +0 -16
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it, vi } from "vitest";
|
|
2
|
-
import type { PluginRuntime, RuntimeEnv } from "../runtime-api.js";
|
|
3
|
-
import type { ResolvedNextcloudTalkAccount } from "./accounts.js";
|
|
4
|
-
import { handleNextcloudTalkInbound } from "./inbound.js";
|
|
5
|
-
import { setNextcloudTalkRuntime } from "./runtime.js";
|
|
6
|
-
import type { CoreConfig, NextcloudTalkInboundMessage } from "./types.js";
|
|
7
|
-
|
|
8
|
-
function installInboundAuthzRuntime(params: {
|
|
9
|
-
readAllowFromStore: () => Promise<string[]>;
|
|
10
|
-
buildMentionRegexes: () => RegExp[];
|
|
11
|
-
}) {
|
|
12
|
-
setNextcloudTalkRuntime({
|
|
13
|
-
channel: {
|
|
14
|
-
pairing: {
|
|
15
|
-
readAllowFromStore: params.readAllowFromStore,
|
|
16
|
-
},
|
|
17
|
-
commands: {
|
|
18
|
-
shouldHandleTextCommands: () => false,
|
|
19
|
-
},
|
|
20
|
-
text: {
|
|
21
|
-
hasControlCommand: () => false,
|
|
22
|
-
},
|
|
23
|
-
mentions: {
|
|
24
|
-
buildMentionRegexes: params.buildMentionRegexes,
|
|
25
|
-
matchesMentionPatterns: () => false,
|
|
26
|
-
},
|
|
27
|
-
},
|
|
28
|
-
} as unknown as PluginRuntime);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function createTestRuntimeEnv(): RuntimeEnv {
|
|
32
|
-
return {
|
|
33
|
-
log: vi.fn(),
|
|
34
|
-
error: vi.fn(),
|
|
35
|
-
} as unknown as RuntimeEnv;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
describe("nextcloud-talk inbound authz", () => {
|
|
39
|
-
it("does not treat DM pairing-store entries as group allowlist entries", async () => {
|
|
40
|
-
const readAllowFromStore = vi.fn(async () => ["attacker"]);
|
|
41
|
-
const buildMentionRegexes = vi.fn(() => [/@kodelyth/i]);
|
|
42
|
-
|
|
43
|
-
installInboundAuthzRuntime({ readAllowFromStore, buildMentionRegexes });
|
|
44
|
-
|
|
45
|
-
const message: NextcloudTalkInboundMessage = {
|
|
46
|
-
messageId: "m-1",
|
|
47
|
-
roomToken: "room-1",
|
|
48
|
-
roomName: "Room 1",
|
|
49
|
-
senderId: "attacker",
|
|
50
|
-
senderName: "Attacker",
|
|
51
|
-
text: "hello",
|
|
52
|
-
mediaType: "text/plain",
|
|
53
|
-
timestamp: Date.now(),
|
|
54
|
-
isGroupChat: true,
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
const account: ResolvedNextcloudTalkAccount = {
|
|
58
|
-
accountId: "default",
|
|
59
|
-
enabled: true,
|
|
60
|
-
baseUrl: "",
|
|
61
|
-
secret: "",
|
|
62
|
-
secretSource: "none", // pragma: allowlist secret
|
|
63
|
-
config: {
|
|
64
|
-
dmPolicy: "pairing",
|
|
65
|
-
allowFrom: [],
|
|
66
|
-
groupPolicy: "allowlist",
|
|
67
|
-
groupAllowFrom: [],
|
|
68
|
-
},
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
const config: CoreConfig = {
|
|
72
|
-
channels: {
|
|
73
|
-
"nextcloud-talk": {
|
|
74
|
-
dmPolicy: "pairing",
|
|
75
|
-
allowFrom: [],
|
|
76
|
-
groupPolicy: "allowlist",
|
|
77
|
-
groupAllowFrom: [],
|
|
78
|
-
},
|
|
79
|
-
},
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
await handleNextcloudTalkInbound({
|
|
83
|
-
message,
|
|
84
|
-
account,
|
|
85
|
-
config,
|
|
86
|
-
runtime: createTestRuntimeEnv(),
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
expect(readAllowFromStore).not.toHaveBeenCalled();
|
|
90
|
-
expect(buildMentionRegexes).not.toHaveBeenCalled();
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
it("matches group rooms by token instead of colliding room names", async () => {
|
|
94
|
-
const readAllowFromStore = vi.fn(async () => []);
|
|
95
|
-
const buildMentionRegexes = vi.fn(() => [/@kodelyth/i]);
|
|
96
|
-
|
|
97
|
-
installInboundAuthzRuntime({ readAllowFromStore, buildMentionRegexes });
|
|
98
|
-
|
|
99
|
-
const message: NextcloudTalkInboundMessage = {
|
|
100
|
-
messageId: "m-2",
|
|
101
|
-
roomToken: "room-attacker",
|
|
102
|
-
roomName: "Room Trusted",
|
|
103
|
-
senderId: "trusted-user",
|
|
104
|
-
senderName: "Trusted User",
|
|
105
|
-
text: "hello",
|
|
106
|
-
mediaType: "text/plain",
|
|
107
|
-
timestamp: Date.now(),
|
|
108
|
-
isGroupChat: true,
|
|
109
|
-
};
|
|
110
|
-
|
|
111
|
-
const account: ResolvedNextcloudTalkAccount = {
|
|
112
|
-
accountId: "default",
|
|
113
|
-
enabled: true,
|
|
114
|
-
baseUrl: "",
|
|
115
|
-
secret: "",
|
|
116
|
-
secretSource: "none",
|
|
117
|
-
config: {
|
|
118
|
-
dmPolicy: "pairing",
|
|
119
|
-
allowFrom: [],
|
|
120
|
-
groupPolicy: "allowlist",
|
|
121
|
-
groupAllowFrom: ["trusted-user"],
|
|
122
|
-
rooms: {
|
|
123
|
-
"room-trusted": {
|
|
124
|
-
enabled: true,
|
|
125
|
-
},
|
|
126
|
-
},
|
|
127
|
-
},
|
|
128
|
-
};
|
|
129
|
-
|
|
130
|
-
await handleNextcloudTalkInbound({
|
|
131
|
-
message,
|
|
132
|
-
account,
|
|
133
|
-
config: {
|
|
134
|
-
channels: {
|
|
135
|
-
"nextcloud-talk": {
|
|
136
|
-
groupPolicy: "allowlist",
|
|
137
|
-
groupAllowFrom: ["trusted-user"],
|
|
138
|
-
},
|
|
139
|
-
},
|
|
140
|
-
},
|
|
141
|
-
runtime: createTestRuntimeEnv(),
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
expect(buildMentionRegexes).not.toHaveBeenCalled();
|
|
145
|
-
});
|
|
146
|
-
});
|
|
@@ -1,309 +0,0 @@
|
|
|
1
|
-
import { createPluginRuntimeMock } from "klaw/plugin-sdk/channel-test-helpers";
|
|
2
|
-
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
3
|
-
import type { PluginRuntime, RuntimeEnv } from "../runtime-api.js";
|
|
4
|
-
import type { ResolvedNextcloudTalkAccount } from "./accounts.js";
|
|
5
|
-
import { handleNextcloudTalkInbound } from "./inbound.js";
|
|
6
|
-
import { setNextcloudTalkRuntime } from "./runtime.js";
|
|
7
|
-
import type { CoreConfig, NextcloudTalkInboundMessage } from "./types.js";
|
|
8
|
-
|
|
9
|
-
const {
|
|
10
|
-
createChannelPairingControllerMock,
|
|
11
|
-
resolveAllowlistProviderRuntimeGroupPolicyMock,
|
|
12
|
-
resolveDefaultGroupPolicyMock,
|
|
13
|
-
warnMissingProviderGroupPolicyFallbackOnceMock,
|
|
14
|
-
} = vi.hoisted(() => {
|
|
15
|
-
return {
|
|
16
|
-
createChannelPairingControllerMock: vi.fn(),
|
|
17
|
-
resolveAllowlistProviderRuntimeGroupPolicyMock: vi.fn(),
|
|
18
|
-
resolveDefaultGroupPolicyMock: vi.fn(),
|
|
19
|
-
warnMissingProviderGroupPolicyFallbackOnceMock: vi.fn(),
|
|
20
|
-
};
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
const sendMessageNextcloudTalkMock = vi.hoisted(() => vi.fn());
|
|
24
|
-
const resolveNextcloudTalkRoomKindMock = vi.hoisted(() => vi.fn());
|
|
25
|
-
|
|
26
|
-
vi.mock("../runtime-api.js", async () => {
|
|
27
|
-
const actual = await vi.importActual<typeof import("../runtime-api.js")>("../runtime-api.js");
|
|
28
|
-
return {
|
|
29
|
-
...actual,
|
|
30
|
-
createChannelPairingController: createChannelPairingControllerMock,
|
|
31
|
-
resolveAllowlistProviderRuntimeGroupPolicy: resolveAllowlistProviderRuntimeGroupPolicyMock,
|
|
32
|
-
resolveDefaultGroupPolicy: resolveDefaultGroupPolicyMock,
|
|
33
|
-
warnMissingProviderGroupPolicyFallbackOnce: warnMissingProviderGroupPolicyFallbackOnceMock,
|
|
34
|
-
};
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
vi.mock("./send.js", () => ({
|
|
38
|
-
sendMessageNextcloudTalk: sendMessageNextcloudTalkMock,
|
|
39
|
-
}));
|
|
40
|
-
|
|
41
|
-
vi.mock("./room-info.js", async () => {
|
|
42
|
-
const actual = await vi.importActual<typeof import("./room-info.js")>("./room-info.js");
|
|
43
|
-
return {
|
|
44
|
-
...actual,
|
|
45
|
-
resolveNextcloudTalkRoomKind: resolveNextcloudTalkRoomKindMock,
|
|
46
|
-
};
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
function installRuntime(params?: {
|
|
50
|
-
buildMentionRegexes?: () => RegExp[];
|
|
51
|
-
hasControlCommand?: (body: string) => boolean;
|
|
52
|
-
matchesMentionPatterns?: (body: string, regexes: RegExp[]) => boolean;
|
|
53
|
-
shouldHandleTextCommands?: () => boolean;
|
|
54
|
-
}) {
|
|
55
|
-
const runtime = {
|
|
56
|
-
channel: {
|
|
57
|
-
turn: {
|
|
58
|
-
runAssembled: vi.fn(async () => undefined),
|
|
59
|
-
},
|
|
60
|
-
pairing: {
|
|
61
|
-
readAllowFromStore: vi.fn(async () => []),
|
|
62
|
-
upsertPairingRequest: vi.fn(async () => ({ code: "123456", created: true })),
|
|
63
|
-
},
|
|
64
|
-
commands: {
|
|
65
|
-
shouldHandleTextCommands: params?.shouldHandleTextCommands ?? vi.fn(() => false),
|
|
66
|
-
},
|
|
67
|
-
text: {
|
|
68
|
-
hasControlCommand: params?.hasControlCommand ?? vi.fn(() => false),
|
|
69
|
-
},
|
|
70
|
-
mentions: {
|
|
71
|
-
buildMentionRegexes: params?.buildMentionRegexes ?? vi.fn(() => []),
|
|
72
|
-
matchesMentionPatterns: params?.matchesMentionPatterns ?? vi.fn(() => false),
|
|
73
|
-
},
|
|
74
|
-
},
|
|
75
|
-
};
|
|
76
|
-
setNextcloudTalkRuntime(runtime as unknown as PluginRuntime);
|
|
77
|
-
return runtime;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
function createRuntimeEnv() {
|
|
81
|
-
return {
|
|
82
|
-
log: vi.fn(),
|
|
83
|
-
error: vi.fn(),
|
|
84
|
-
} as unknown as RuntimeEnv;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
function requireFirstMockArg(mock: ReturnType<typeof vi.fn>, label: string): unknown {
|
|
88
|
-
const [call] = mock.mock.calls;
|
|
89
|
-
if (!call) {
|
|
90
|
-
throw new Error(`expected ${label}`);
|
|
91
|
-
}
|
|
92
|
-
return call[0];
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
function requireFirstSendMessageCall(): [unknown, unknown, unknown] {
|
|
96
|
-
const [call] = sendMessageNextcloudTalkMock.mock.calls;
|
|
97
|
-
if (!call) {
|
|
98
|
-
throw new Error("expected Nextcloud Talk send call");
|
|
99
|
-
}
|
|
100
|
-
return call as [unknown, unknown, unknown];
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
function createAccount(
|
|
104
|
-
overrides?: Partial<ResolvedNextcloudTalkAccount>,
|
|
105
|
-
): ResolvedNextcloudTalkAccount {
|
|
106
|
-
return {
|
|
107
|
-
accountId: "default",
|
|
108
|
-
enabled: true,
|
|
109
|
-
baseUrl: "https://cloud.example.com",
|
|
110
|
-
secret: "secret",
|
|
111
|
-
secretSource: "config",
|
|
112
|
-
config: {
|
|
113
|
-
dmPolicy: "pairing",
|
|
114
|
-
allowFrom: [],
|
|
115
|
-
groupPolicy: "allowlist",
|
|
116
|
-
groupAllowFrom: [],
|
|
117
|
-
},
|
|
118
|
-
...overrides,
|
|
119
|
-
};
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
function createMessage(
|
|
123
|
-
overrides?: Partial<NextcloudTalkInboundMessage>,
|
|
124
|
-
): NextcloudTalkInboundMessage {
|
|
125
|
-
return {
|
|
126
|
-
messageId: "msg-1",
|
|
127
|
-
roomToken: "room-1",
|
|
128
|
-
roomName: "Room 1",
|
|
129
|
-
senderId: "user-1",
|
|
130
|
-
senderName: "Alice",
|
|
131
|
-
text: "hello",
|
|
132
|
-
mediaType: "text/plain",
|
|
133
|
-
timestamp: Date.now(),
|
|
134
|
-
isGroupChat: false,
|
|
135
|
-
...overrides,
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
describe("nextcloud-talk inbound behavior", () => {
|
|
140
|
-
beforeEach(() => {
|
|
141
|
-
vi.clearAllMocks();
|
|
142
|
-
installRuntime();
|
|
143
|
-
resolveNextcloudTalkRoomKindMock.mockResolvedValue("direct");
|
|
144
|
-
resolveDefaultGroupPolicyMock.mockReturnValue("allowlist");
|
|
145
|
-
resolveAllowlistProviderRuntimeGroupPolicyMock.mockReturnValue({
|
|
146
|
-
groupPolicy: "allowlist",
|
|
147
|
-
providerMissingFallbackApplied: false,
|
|
148
|
-
});
|
|
149
|
-
warnMissingProviderGroupPolicyFallbackOnceMock.mockReturnValue(undefined);
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
it("issues a DM pairing challenge and sends the challenge text", async () => {
|
|
153
|
-
const issueChallenge = vi.fn(
|
|
154
|
-
async (params: { sendPairingReply: (text: string) => Promise<void> }) => {
|
|
155
|
-
await params.sendPairingReply("Pair with code 123456");
|
|
156
|
-
},
|
|
157
|
-
);
|
|
158
|
-
createChannelPairingControllerMock.mockReturnValue({
|
|
159
|
-
readStoreForDmPolicy: vi.fn(),
|
|
160
|
-
issueChallenge,
|
|
161
|
-
});
|
|
162
|
-
sendMessageNextcloudTalkMock.mockResolvedValue(undefined);
|
|
163
|
-
|
|
164
|
-
const statusSink = vi.fn();
|
|
165
|
-
await handleNextcloudTalkInbound({
|
|
166
|
-
message: createMessage({ timestamp: 1_736_380_800_000 }),
|
|
167
|
-
account: createAccount(),
|
|
168
|
-
config: { channels: { "nextcloud-talk": {} } } as CoreConfig,
|
|
169
|
-
runtime: createRuntimeEnv(),
|
|
170
|
-
statusSink,
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
const challengeParams = requireFirstMockArg(
|
|
174
|
-
issueChallenge,
|
|
175
|
-
"Nextcloud Talk pairing challenge",
|
|
176
|
-
) as {
|
|
177
|
-
meta?: { name?: string };
|
|
178
|
-
senderId?: string;
|
|
179
|
-
senderIdLine?: string;
|
|
180
|
-
};
|
|
181
|
-
expect(challengeParams.senderId).toBe("user-1");
|
|
182
|
-
expect(challengeParams.senderIdLine).toBe("Your Nextcloud user id: user-1");
|
|
183
|
-
expect(challengeParams.meta).toEqual({ name: "Alice" });
|
|
184
|
-
expect(sendMessageNextcloudTalkMock).toHaveBeenCalledTimes(1);
|
|
185
|
-
const sendArgs = requireFirstSendMessageCall();
|
|
186
|
-
expect(sendArgs[0]).toBe("room-1");
|
|
187
|
-
expect(sendArgs[1]).toBe("Pair with code 123456");
|
|
188
|
-
expect(sendArgs[2]).toEqual({
|
|
189
|
-
cfg: { channels: { "nextcloud-talk": {} } },
|
|
190
|
-
accountId: "default",
|
|
191
|
-
});
|
|
192
|
-
expect(statusSink).toHaveBeenCalledWith({ lastInboundAt: 1_736_380_800_000 });
|
|
193
|
-
const outboundStatus = statusSink.mock.calls
|
|
194
|
-
.map(([status]) => status as { lastOutboundAt?: unknown })
|
|
195
|
-
.find((status) => status.lastOutboundAt !== undefined);
|
|
196
|
-
expect(typeof outboundStatus?.lastOutboundAt).toBe("number");
|
|
197
|
-
expect(outboundStatus?.lastOutboundAt).toBeGreaterThanOrEqual(1_736_380_800_000);
|
|
198
|
-
expect(sendMessageNextcloudTalkMock).toHaveBeenCalledTimes(1);
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
it("drops unmentioned group traffic before dispatch", async () => {
|
|
202
|
-
installRuntime({
|
|
203
|
-
buildMentionRegexes: vi.fn(() => [/@kodelyth/i]),
|
|
204
|
-
matchesMentionPatterns: vi.fn(() => false),
|
|
205
|
-
});
|
|
206
|
-
createChannelPairingControllerMock.mockReturnValue({
|
|
207
|
-
readStoreForDmPolicy: vi.fn(),
|
|
208
|
-
issueChallenge: vi.fn(),
|
|
209
|
-
});
|
|
210
|
-
resolveNextcloudTalkRoomKindMock.mockResolvedValue("group");
|
|
211
|
-
const runtime = createRuntimeEnv();
|
|
212
|
-
|
|
213
|
-
await handleNextcloudTalkInbound({
|
|
214
|
-
message: createMessage({
|
|
215
|
-
roomToken: "room-group",
|
|
216
|
-
roomName: "Ops",
|
|
217
|
-
isGroupChat: true,
|
|
218
|
-
}),
|
|
219
|
-
account: createAccount({
|
|
220
|
-
config: {
|
|
221
|
-
dmPolicy: "pairing",
|
|
222
|
-
allowFrom: [],
|
|
223
|
-
groupPolicy: "allowlist",
|
|
224
|
-
groupAllowFrom: ["user-1"],
|
|
225
|
-
},
|
|
226
|
-
}),
|
|
227
|
-
config: { channels: { "nextcloud-talk": {} } } as CoreConfig,
|
|
228
|
-
runtime,
|
|
229
|
-
});
|
|
230
|
-
|
|
231
|
-
expect(sendMessageNextcloudTalkMock).not.toHaveBeenCalled();
|
|
232
|
-
expect(runtime.log).toHaveBeenCalledWith("nextcloud-talk: drop room room-group (no mention)");
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
it("blocks unauthorized group text control commands even when room sender access allows chat", async () => {
|
|
236
|
-
const buildMentionRegexes = vi.fn(() => [/@kodelyth/i]);
|
|
237
|
-
const coreRuntime = installRuntime({
|
|
238
|
-
buildMentionRegexes,
|
|
239
|
-
hasControlCommand: vi.fn(() => true),
|
|
240
|
-
shouldHandleTextCommands: vi.fn(() => true),
|
|
241
|
-
});
|
|
242
|
-
createChannelPairingControllerMock.mockReturnValue({
|
|
243
|
-
readStoreForDmPolicy: vi.fn(),
|
|
244
|
-
issueChallenge: vi.fn(),
|
|
245
|
-
});
|
|
246
|
-
resolveNextcloudTalkRoomKindMock.mockResolvedValue("group");
|
|
247
|
-
const runtime = createRuntimeEnv();
|
|
248
|
-
|
|
249
|
-
await handleNextcloudTalkInbound({
|
|
250
|
-
message: createMessage({
|
|
251
|
-
roomToken: "room-group",
|
|
252
|
-
roomName: "Ops",
|
|
253
|
-
isGroupChat: true,
|
|
254
|
-
text: "/klaw reload",
|
|
255
|
-
}),
|
|
256
|
-
account: createAccount({
|
|
257
|
-
config: {
|
|
258
|
-
dmPolicy: "pairing",
|
|
259
|
-
allowFrom: [],
|
|
260
|
-
groupPolicy: "allowlist",
|
|
261
|
-
groupAllowFrom: [],
|
|
262
|
-
rooms: {
|
|
263
|
-
"room-group": {
|
|
264
|
-
allowFrom: ["user-1"],
|
|
265
|
-
requireMention: false,
|
|
266
|
-
},
|
|
267
|
-
},
|
|
268
|
-
},
|
|
269
|
-
}),
|
|
270
|
-
config: { channels: { "nextcloud-talk": {} } } as CoreConfig,
|
|
271
|
-
runtime,
|
|
272
|
-
});
|
|
273
|
-
|
|
274
|
-
expect(coreRuntime.channel.turn.runAssembled).not.toHaveBeenCalled();
|
|
275
|
-
expect(buildMentionRegexes).not.toHaveBeenCalled();
|
|
276
|
-
expect(runtime.log).toHaveBeenCalledWith(
|
|
277
|
-
"nextcloud-talk: drop control command (unauthorized) target=user-1",
|
|
278
|
-
);
|
|
279
|
-
});
|
|
280
|
-
|
|
281
|
-
it("passes the shared reply pipeline for dispatched replies", async () => {
|
|
282
|
-
const coreRuntime = createPluginRuntimeMock();
|
|
283
|
-
setNextcloudTalkRuntime(coreRuntime as unknown as PluginRuntime);
|
|
284
|
-
createChannelPairingControllerMock.mockReturnValue({
|
|
285
|
-
readStoreForDmPolicy: vi.fn(async () => []),
|
|
286
|
-
issueChallenge: vi.fn(),
|
|
287
|
-
});
|
|
288
|
-
|
|
289
|
-
await handleNextcloudTalkInbound({
|
|
290
|
-
message: createMessage(),
|
|
291
|
-
account: createAccount({
|
|
292
|
-
config: {
|
|
293
|
-
dmPolicy: "allowlist",
|
|
294
|
-
allowFrom: ["user-1"],
|
|
295
|
-
groupPolicy: "allowlist",
|
|
296
|
-
groupAllowFrom: [],
|
|
297
|
-
},
|
|
298
|
-
}),
|
|
299
|
-
config: { channels: { "nextcloud-talk": {} } } as CoreConfig,
|
|
300
|
-
runtime: createRuntimeEnv(),
|
|
301
|
-
});
|
|
302
|
-
|
|
303
|
-
const assembledRequest = requireFirstMockArg(
|
|
304
|
-
coreRuntime.channel.turn.runAssembled as ReturnType<typeof vi.fn>,
|
|
305
|
-
"Nextcloud Talk assembled request",
|
|
306
|
-
) as { replyPipeline?: unknown };
|
|
307
|
-
expect(assembledRequest.replyPipeline).toEqual({});
|
|
308
|
-
});
|
|
309
|
-
});
|