mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
feat(integrations): email when integration sync fails
This commit is contained in:
@@ -562,6 +562,30 @@ export const secretQueueFactory = ({
|
||||
throw new Error("Secret path not found");
|
||||
}
|
||||
|
||||
const sendIntegrationSyncFailedMail = async (integrationId: string, syncMessage: string | null) => {
|
||||
const appCfg = getConfig();
|
||||
|
||||
// If smtp is not configured, we can return early without having to fetch the project members.
|
||||
if (!appCfg.isSmtpConfigured) return;
|
||||
|
||||
const projectMembers = await projectMembershipDAL.findAllProjectMembers(projectId);
|
||||
const project = await projectDAL.findById(projectId);
|
||||
|
||||
const filteredProjectMembers =
|
||||
isManual && actorId ? projectMembers.filter((member) => member.userId === actorId) : projectMembers;
|
||||
|
||||
await smtpService.sendMail({
|
||||
recipients: filteredProjectMembers.map((member) => member.user.email!),
|
||||
template: SmtpTemplates.IntegrationSyncFailed,
|
||||
subjectLine: `Integration Sync Failed`,
|
||||
substitutions: {
|
||||
syncMessage,
|
||||
projectName: project.name,
|
||||
integrationUrl: `${appCfg.SITE_URL}/integrations/details/${integrationId}`
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// find all imports made with the given environment and secret path
|
||||
const linkSourceDto = {
|
||||
projectId,
|
||||
@@ -833,6 +857,11 @@ export const secretQueueFactory = ({
|
||||
syncMessage: response?.syncMessage ?? "",
|
||||
isSynced: response?.isSynced ?? true
|
||||
});
|
||||
|
||||
// May be undefined, if it's undefined we assume the sync was successful, hence the strict equality type check.
|
||||
if (response?.isSynced === false) {
|
||||
await sendIntegrationSyncFailedMail(integration.id, response?.syncMessage);
|
||||
}
|
||||
} catch (err) {
|
||||
logger.error(
|
||||
err,
|
||||
@@ -863,6 +892,8 @@ export const secretQueueFactory = ({
|
||||
syncMessage: message,
|
||||
isSynced: false
|
||||
});
|
||||
|
||||
await sendIntegrationSyncFailedMail(integration.id, message);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
|
||||
@@ -33,7 +33,8 @@ export enum SmtpTemplates {
|
||||
SecretLeakIncident = "secretLeakIncident.handlebars",
|
||||
WorkspaceInvite = "workspaceInvitation.handlebars",
|
||||
ScimUserProvisioned = "scimUserProvisioned.handlebars",
|
||||
PkiExpirationAlert = "pkiExpirationAlert.handlebars"
|
||||
PkiExpirationAlert = "pkiExpirationAlert.handlebars",
|
||||
IntegrationSyncFailed = "integrationSyncFailed.handlebars"
|
||||
}
|
||||
|
||||
export enum SmtpHost {
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="x-ua-compatible" content="ie=edge" />
|
||||
<title>Integration Sync Failed</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h2>Infisical</h2>
|
||||
<p>An integration in your project
|
||||
<b>{{projectName}}</b>
|
||||
failed to sync secrets.<br />
|
||||
<a href="{{integrationUrl}}">
|
||||
View integration details.
|
||||
</a>
|
||||
</p>
|
||||
|
||||
{{#if syncMessage}}
|
||||
<p><b>Reason: </b>{{syncMessage}}</p>
|
||||
{{/if}}
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Reference in New Issue
Block a user