diff --git a/backend/src/queue/queue-service.ts b/backend/src/queue/queue-service.ts index 5a7c92f22..f2f63f57a 100644 --- a/backend/src/queue/queue-service.ts +++ b/backend/src/queue/queue-service.ts @@ -231,6 +231,8 @@ export type TQueueJobTypes = { [QueueName.ImportSecretsFromExternalSource]: { name: QueueJobs.ImportSecretsFromExternalSource; payload: { + orgId: string; + actorId: string; actorEmail: string; importType: ExternalPlatforms; data: { diff --git a/backend/src/server/routes/index.ts b/backend/src/server/routes/index.ts index f47048878..eff862f78 100644 --- a/backend/src/server/routes/index.ts +++ b/backend/src/server/routes/index.ts @@ -1815,7 +1815,8 @@ export const registerRoutes = async ( secretV2BridgeService, resourceMetadataDAL, folderCommitService, - folderVersionDAL + folderVersionDAL, + notificationService }); const migrationService = externalMigrationServiceFactory({ diff --git a/backend/src/services/external-migration/external-migration-queue.ts b/backend/src/services/external-migration/external-migration-queue.ts index b4974d2ae..770cbbe3a 100644 --- a/backend/src/services/external-migration/external-migration-queue.ts +++ b/backend/src/services/external-migration/external-migration-queue.ts @@ -5,6 +5,8 @@ import { QueueJobs, QueueName, TQueueServiceFactory } from "@app/queue"; import { TFolderCommitServiceFactory } from "../folder-commit/folder-commit-service"; import { TKmsServiceFactory } from "../kms/kms-service"; +import { TNotificationServiceFactory } from "../notification/notification-service"; +import { NotificationType } from "../notification/notification-types"; import { TProjectDALFactory } from "../project/project-dal"; import { TProjectServiceFactory } from "../project/project-service"; import { TProjectEnvDALFactory } from "../project-env/project-env-dal"; @@ -42,6 +44,7 @@ export type TExternalMigrationQueueFactoryDep = { folderVersionDAL: Pick; resourceMetadataDAL: Pick; + notificationService: Pick; }; export type TExternalMigrationQueueFactory = ReturnType; @@ -62,9 +65,12 @@ export const externalMigrationQueueFactory = ({ folderDAL, folderCommitService, folderVersionDAL, - resourceMetadataDAL + resourceMetadataDAL, + notificationService }: TExternalMigrationQueueFactoryDep) => { const startImport = async (dto: { + orgId: string; + actorId: string; actorEmail: string; importType: ExternalPlatforms; data: { @@ -87,9 +93,19 @@ export const externalMigrationQueueFactory = ({ }; queueService.start(QueueName.ImportSecretsFromExternalSource, async (job) => { - const { data, actorEmail, importType } = job.data; + const { data, actorEmail, importType, actorId, orgId } = job.data; try { + await notificationService.createUserNotifications([ + { + userId: actorId, + orgId, + type: NotificationType.IMPORT_STARTED, + title: "Import Started", + body: `An import from **${importType}** to Infisical has been started.` + } + ]); + await smtpService.sendMail({ recipients: [actorEmail], subjectLine: "Infisical import started", @@ -137,6 +153,16 @@ export const externalMigrationQueueFactory = ({ ); } + await notificationService.createUserNotifications([ + { + userId: actorId, + orgId, + type: NotificationType.IMPORT_SUCCESSFUL, + title: "Import Successful", + body: `An import from **${importType}** to Infisical has successfully completed.` + } + ]); + await smtpService.sendMail({ recipients: [actorEmail], subjectLine: "Infisical import successful", @@ -146,6 +172,17 @@ export const externalMigrationQueueFactory = ({ template: SmtpTemplates.ExternalImportSuccessful }); } catch (err) { + await notificationService.createUserNotifications([ + { + userId: actorId, + orgId, + type: NotificationType.IMPORT_FAILED, + title: "Import Failed", + // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access + body: `An import from **${importType}** to Infisical has failed: ${(err as any)?.message || "Unknown error"}.` + } + ]); + await smtpService.sendMail({ recipients: [job.data.actorEmail], subjectLine: "Infisical import failed", diff --git a/backend/src/services/external-migration/external-migration-service.ts b/backend/src/services/external-migration/external-migration-service.ts index 73fac00b9..e801b607e 100644 --- a/backend/src/services/external-migration/external-migration-service.ts +++ b/backend/src/services/external-migration/external-migration-service.ts @@ -73,6 +73,8 @@ export const externalMigrationServiceFactory = ({ const encrypted = crypto.encryption().symmetric().encryptWithRootEncryptionKey(stringifiedJson); await externalMigrationQueue.startImport({ + actorId: user.id, + orgId: actorOrgId, actorEmail: user.email!, importType: ExternalPlatforms.EnvKey, data: { @@ -131,6 +133,8 @@ export const externalMigrationServiceFactory = ({ const encrypted = crypto.encryption().symmetric().encryptWithRootEncryptionKey(stringifiedJson); await externalMigrationQueue.startImport({ + actorId: user.id, + orgId: actorOrgId, actorEmail: user.email!, importType: ExternalPlatforms.Vault, data: { diff --git a/backend/src/services/notification/notification-types.ts b/backend/src/services/notification/notification-types.ts index 3377afbc9..5743118a6 100644 --- a/backend/src/services/notification/notification-types.ts +++ b/backend/src/services/notification/notification-types.ts @@ -8,7 +8,10 @@ export enum NotificationType { SECRET_SCANNING_SECRETS_DETECTED = "secret-scanning-secrets-detected", SECRET_SCANNING_SCAN_FAILED = "secret-scanning-scan-failed", LOGIN_FROM_NEW_DEVICE = "login-from-new-device", - ADMIN_SSO_BYPASS = "admin-sso-bypass" + ADMIN_SSO_BYPASS = "admin-sso-bypass", + IMPORT_STARTED = "import-started", + IMPORT_SUCCESSFUL = "import-successful", + IMPORT_FAILED = "import-failed" } export interface TCreateUserNotificationDTO {