fix: Disable webhooks when deleting associated user (#12524)

* fix: Disable webhooks created by deleted users

* Delete -> disable
This commit is contained in:
Tom Moor
2026-05-29 17:44:29 -04:00
committed by GitHub
parent 5aff60e28b
commit e044014cea
4 changed files with 35 additions and 4 deletions
+1 -1
View File
@@ -71,7 +71,7 @@ export function UserDeleteDialog({ user, onSubmit }: Props) {
danger
>
{t(
"Are you sure you want to permanently delete {{ userName }}? This operation is unrecoverable, consider suspending the user instead.",
"Are you sure you want to permanently delete {{ userName }}? This operation is unrecoverable. Any API keys, webhooks, and integrations they created will stop working — consider suspending the user instead.",
{
userName: user.name,
}
@@ -1,11 +1,11 @@
import UserAuthentication from "@server/models/UserAuthentication";
import { buildUser } from "@server/test/factories";
import { buildUser, buildWebhookSubscription } from "@server/test/factories";
import UserDeletedProcessor from "./UserDeletedProcessor";
const ip = "127.0.0.1";
describe("UserDeletedProcessor", () => {
test("should remove relationships", async () => {
it("should remove relationships", async () => {
const user = await buildUser();
expect(
await UserAuthentication.count({
@@ -32,4 +32,24 @@ describe("UserDeletedProcessor", () => {
})
).toBe(0);
});
it("should disable webhook subscriptions created by the user", async () => {
const user = await buildUser();
const webhook = await buildWebhookSubscription({
teamId: user.teamId,
createdById: user.id,
});
const processor = new UserDeletedProcessor();
await processor.perform({
name: "users.delete",
userId: user.id,
actorId: user.id,
teamId: user.teamId,
ip,
});
await webhook.reload();
expect(webhook.enabled).toEqual(false);
});
});
@@ -6,6 +6,7 @@ import {
Subscription,
UserAuthentication,
UserMembership,
WebhookSubscription,
} from "@server/models";
import { sequelize } from "@server/storage/database";
import type { Event as TEvent, UserEvent } from "@server/types";
@@ -59,6 +60,16 @@ export default class UserDeletedProcessor extends BaseProcessor {
},
transaction,
});
await WebhookSubscription.update(
{ enabled: false },
{
where: {
createdById: event.userId,
enabled: true,
},
transaction,
}
);
});
}
}
+1 -1
View File
@@ -542,7 +542,7 @@
"Viewers can only view and comment on documents.": "Viewers can only view and comment on documents.",
"Are you sure you want to make {{ userName }} a {{ role }}?": "Are you sure you want to make {{ userName }} a {{ role }}?",
"I understand, delete": "I understand, delete",
"Are you sure you want to permanently delete {{ userName }}? This operation is unrecoverable, consider suspending the user instead.": "Are you sure you want to permanently delete {{ userName }}? This operation is unrecoverable, consider suspending the user instead.",
"Are you sure you want to permanently delete {{ userName }}? This operation is unrecoverable. Any API keys, webhooks, and integrations they created will stop working — consider suspending the user instead.": "Are you sure you want to permanently delete {{ userName }}? This operation is unrecoverable. Any API keys, webhooks, and integrations they created will stop working — consider suspending the user instead.",
"Are you sure you want to suspend {{ userName }}? Suspended users will be prevented from logging in.": "Are you sure you want to suspend {{ userName }}? Suspended users will be prevented from logging in.",
"New name": "New name",
"Name can't be empty": "Name can't be empty",