feat: Add email when webhook is disabled (#3721)
fix: Webhook not disabled under some error conditions
This commit is contained in:
63
server/emails/templates/WebhookDisabledEmail.tsx
Normal file
63
server/emails/templates/WebhookDisabledEmail.tsx
Normal file
@@ -0,0 +1,63 @@
|
||||
import * as React from "react";
|
||||
import BaseEmail from "./BaseEmail";
|
||||
import Body from "./components/Body";
|
||||
import Button from "./components/Button";
|
||||
import EmailTemplate from "./components/EmailLayout";
|
||||
import EmptySpace from "./components/EmptySpace";
|
||||
import Footer from "./components/Footer";
|
||||
import Header from "./components/Header";
|
||||
import Heading from "./components/Heading";
|
||||
|
||||
type Props = {
|
||||
to: string;
|
||||
teamUrl: string;
|
||||
webhookName: string;
|
||||
};
|
||||
|
||||
/**
|
||||
* Email sent to the creator of a webhook when the webhook has become disabled
|
||||
* due to repeated failure.
|
||||
*/
|
||||
export default class WebhookDisabledEmail extends BaseEmail<Props> {
|
||||
protected subject() {
|
||||
return `Warning: Webhook disabled`;
|
||||
}
|
||||
|
||||
protected preview({ webhookName }: Props) {
|
||||
return `Your webhook (${webhookName}) has been disabled`;
|
||||
}
|
||||
|
||||
protected renderAsText({ webhookName, teamUrl }: Props): string {
|
||||
return `
|
||||
Your webhook (${webhookName}) has been automatically disabled as the last 25
|
||||
delivery attempts have failed. You can re-enable by editing the webhook.
|
||||
|
||||
Webhook settings: ${teamUrl}/settings/webhooks
|
||||
`;
|
||||
}
|
||||
|
||||
protected render({ webhookName, teamUrl }: Props) {
|
||||
return (
|
||||
<EmailTemplate>
|
||||
<Header />
|
||||
|
||||
<Body>
|
||||
<Heading>Webhook disabled</Heading>
|
||||
<p>
|
||||
Your webhook ({webhookName}) has been automatically disabled as the
|
||||
last 25 delivery attempts have failed. You can re-enable by editing
|
||||
the webhook.
|
||||
</p>
|
||||
<EmptySpace height={10} />
|
||||
<p>
|
||||
<Button href={teamUrl + "/settings/webhooks"}>
|
||||
Webhook settings
|
||||
</Button>
|
||||
</p>
|
||||
</Body>
|
||||
|
||||
<Footer />
|
||||
</EmailTemplate>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
import fetch from "fetch-with-proxy";
|
||||
import { Op } from "sequelize";
|
||||
import WebhookDisabledEmail from "@server/emails/templates/WebhookDisabledEmail";
|
||||
import env from "@server/env";
|
||||
import Logger from "@server/logging/Logger";
|
||||
import {
|
||||
@@ -550,21 +552,52 @@ export default class DeliverWebhookTask extends BaseTask<Props> {
|
||||
: {},
|
||||
});
|
||||
|
||||
if (response && !response.ok) {
|
||||
const recentDeliveries = await WebhookDelivery.findAll({
|
||||
where: {
|
||||
webhookSubscriptionId: subscription.id,
|
||||
},
|
||||
order: [["createdAt", "DESC"]],
|
||||
limit: 25,
|
||||
});
|
||||
if (status === "failed") {
|
||||
try {
|
||||
await this.checkAndDisableSubscription(subscription);
|
||||
} catch (err) {
|
||||
Logger.error("Failed to check and disable recent deliveries", err, {
|
||||
event,
|
||||
deliveryId: delivery.id,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const allFailed = recentDeliveries.every(
|
||||
(delivery) => delivery.status === "failed"
|
||||
);
|
||||
private async checkAndDisableSubscription(subscription: WebhookSubscription) {
|
||||
const recentDeliveries = await WebhookDelivery.findAll({
|
||||
where: {
|
||||
webhookSubscriptionId: subscription.id,
|
||||
},
|
||||
order: [["createdAt", "DESC"]],
|
||||
limit: 25,
|
||||
});
|
||||
|
||||
if (recentDeliveries.length === 25 && allFailed) {
|
||||
await subscription.update({ enabled: false });
|
||||
const allFailed = recentDeliveries.every(
|
||||
(delivery) => delivery.status === "failed"
|
||||
);
|
||||
|
||||
if (recentDeliveries.length === 25 && allFailed) {
|
||||
// If the last 25 deliveries failed, disable the subscription
|
||||
await subscription.update({ enabled: false });
|
||||
|
||||
// Send an email to the creator of the webhook to let them know
|
||||
const [createdBy, team] = await Promise.all([
|
||||
User.findOne({
|
||||
where: {
|
||||
id: subscription.createdById,
|
||||
suspendedAt: { [Op.is]: null },
|
||||
},
|
||||
}),
|
||||
subscription.$get("team"),
|
||||
]);
|
||||
|
||||
if (createdBy && team) {
|
||||
await WebhookDisabledEmail.schedule({
|
||||
to: createdBy.email,
|
||||
teamUrl: team.url,
|
||||
webhookName: subscription.name,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user