

























@@ -182,6 +182,77 @@ describe("createNextcloudTalkWebhookServer replay handling", () => {
182182});
183183184184describe("createNextcloudTalkWebhookServer payload validation", () => {
185+it("acknowledges signed non-message Create events instead of rejecting them", async () => {
186+const payload = {
187+type: "Create",
188+actor: { type: "Person", id: "alice", name: "Alice" },
189+object: {
190+type: "Document",
191+id: "file-1",
192+name: "report.pdf",
193+content: "",
194+mediaType: "application/pdf",
195+},
196+target: { type: "Collection", id: "room-1", name: "Room 1" },
197+};
198+const body = JSON.stringify(payload);
199+const { random, signature } = generateNextcloudTalkSignature({
200+ body,
201+secret: "nextcloud-secret", // pragma: allowlist secret
202+});
203+const onMessage = vi.fn();
204+const harness = await startWebhookServer({
205+path: "/nextcloud-non-message-event",
206+ onMessage,
207+});
208+209+const response = await fetch(harness.webhookUrl, {
210+method: "POST",
211+headers: {
212+"content-type": "application/json",
213+"x-nextcloud-talk-random": random,
214+"x-nextcloud-talk-signature": signature,
215+"x-nextcloud-talk-backend": "https://nextcloud.example",
216+},
217+ body,
218+});
219+220+expect(response.status).toBe(200);
221+expect(onMessage).not.toHaveBeenCalled();
222+});
223+224+it("acknowledges signed non-Create Talk events instead of rejecting them", async () => {
225+const payload = {
226+type: "Join",
227+actor: { type: "Application", id: "bots/bot-1", name: "Bot" },
228+object: { type: "Collection", id: "room-1", name: "Room 1" },
229+};
230+const body = JSON.stringify(payload);
231+const { random, signature } = generateNextcloudTalkSignature({
232+ body,
233+secret: "nextcloud-secret", // pragma: allowlist secret
234+});
235+const onMessage = vi.fn();
236+const harness = await startWebhookServer({
237+path: "/nextcloud-lifecycle-event",
238+ onMessage,
239+});
240+241+const response = await fetch(harness.webhookUrl, {
242+method: "POST",
243+headers: {
244+"content-type": "application/json",
245+"x-nextcloud-talk-random": random,
246+"x-nextcloud-talk-signature": signature,
247+"x-nextcloud-talk-backend": "https://nextcloud.example",
248+},
249+ body,
250+});
251+252+expect(response.status).toBe(200);
253+expect(onMessage).not.toHaveBeenCalled();
254+});
255+185256it("rejects malformed webhook payloads after signature verification", async () => {
186257const payload = {
187258type: "Create",
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。