From 00212f1c72d039c931598d810908f292276ae36c Mon Sep 17 00:00:00 2001 From: Daniel Hougaard <62331820+DanielHougaard@users.noreply.github.com> Date: Fri, 19 Jan 2024 00:26:13 +0400 Subject: [PATCH] Secret reminder queue factory --- .../secret-reminder-queue/index.ts | 105 ++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 backend-pg/src/services/secret-reminder/secret-reminder-queue/index.ts diff --git a/backend-pg/src/services/secret-reminder/secret-reminder-queue/index.ts b/backend-pg/src/services/secret-reminder/secret-reminder-queue/index.ts new file mode 100644 index 000000000..100df7f5a --- /dev/null +++ b/backend-pg/src/services/secret-reminder/secret-reminder-queue/index.ts @@ -0,0 +1,105 @@ +import { getConfig } from "@app/lib/config/env"; +import { daysToMillisecond, secondsToMillis } from "@app/lib/dates"; +import { logger } from "@app/lib/logger"; +import { QueueJobs, QueueName, TQueueJobTypes, TQueueServiceFactory } from "@app/queue"; +import { TOrgDalFactory } from "@app/services/org/org-dal"; +import { TProjectDalFactory } from "@app/services/project/project-dal"; +import { TProjectMembershipDalFactory } from "@app/services/project-membership/project-membership-dal"; +import { SmtpTemplates, TSmtpService } from "@app/services/smtp/smtp-service"; + +export type TSecretReminderQueueFactory = ReturnType; + +type TSecretReminderQueueFactoryDep = { + queue: TQueueServiceFactory; + projectMembershipDal: Pick; + orgDal: Pick; + projectDal: Pick; + smtpService: TSmtpService; +}; + +export const secretReminderQueueFactory = ({ + queue, + projectMembershipDal, + smtpService, + orgDal, + projectDal +}: TSecretReminderQueueFactoryDep) => { + const addToQueue = async (data: TQueueJobTypes["secret-reminder"]["payload"]) => { + const appCfg = getConfig(); + queue.queue(QueueName.SecretReminder, QueueJobs.SecretReminder, data, { + jobId: `reminder-${data.secretId}`, + repeat: { + // on prod it this will be in days, in development this will be second + every: + appCfg.NODE_ENV === "development" + ? secondsToMillis(data.repeatDays) + : daysToMillisecond(data.repeatDays), + immediately: true + } + }); + }; + + const removeFromQueue = async (secretId: string, repeatDays: number) => { + const appCfg = getConfig(); + await queue.stopRepeatableJob( + QueueName.SecretReminder, + QueueJobs.SecretReminder, + { + // on prod it this will be in days, in development this will be second + every: + appCfg.NODE_ENV === "development" + ? secondsToMillis(repeatDays) + : daysToMillisecond(repeatDays) + }, + `reminder-${secretId}` + ); + }; + + queue.start(QueueName.SecretReminder, async ({ data }) => { + logger.info(`secretReminderQueue.process: [secretDocument=${data.secretId}]`); + + const { projectId } = data; + + const organization = await orgDal.findOrgByProjectId(projectId); + const project = await projectDal.findById(projectId); + + if (!organization) { + logger.info( + `secretReminderQueue.process: [secretDocument=${data.secretId}] no organization found` + ); + return; + } + + if (!project) { + logger.info( + `secretReminderQueue.process: [secretDocument=${data.secretId}] no project found` + ); + return; + } + + const projectMembers = await projectMembershipDal.findAllProjectMembers(projectId); + + if (!projectMembers || !projectMembers.length) { + logger.info( + `secretReminderQueue.process: [secretDocument=${data.secretId}] no project members found` + ); + return; + } + + await smtpService.sendMail({ + template: SmtpTemplates.SecretReminder, + subjectLine: "Infisical secret reminder", + recipients: [...projectMembers.map((m) => m.user.email)], + substitutions: { + reminderNote: data.note, // May not be present. + projectName: project.name, + organizationName: organization.name + } + }); + }); + + return { + addToQueue, + removeFromQueue + }; +};