diff --git a/backend/src/db/migrations/20250305131152_add-actor-id-to-secret-versions-v2.ts b/backend/src/db/migrations/20250305131152_add-actor-id-to-secret-versions-v2.ts new file mode 100644 index 000000000..fb9a047af --- /dev/null +++ b/backend/src/db/migrations/20250305131152_add-actor-id-to-secret-versions-v2.ts @@ -0,0 +1,45 @@ +import { Knex } from "knex"; + +import { TableName } from "@app/db/schemas"; + +export async function up(knex: Knex): Promise { + if (await knex.schema.hasTable(TableName.SecretVersionV2)) { + const hasSecretVersionV2UserActorId = await knex.schema.hasColumn(TableName.SecretVersionV2, "userActorId"); + const hasSecretVersionV2IdentityActorId = await knex.schema.hasColumn(TableName.SecretVersionV2, "identityActorId"); + const hasSecretVersionV2ActorType = await knex.schema.hasColumn(TableName.SecretVersionV2, "actorType"); + + await knex.schema.alterTable(TableName.SecretVersionV2, (t) => { + if (!hasSecretVersionV2UserActorId) { + t.uuid("userActorId"); + t.foreign("userActorId").references("id").inTable(TableName.Users); + } + if (!hasSecretVersionV2IdentityActorId) { + t.uuid("identityActorId"); + t.foreign("identityActorId").references("id").inTable(TableName.Identity); + } + if (!hasSecretVersionV2ActorType) { + t.string("actorType"); + } + }); + } +} + +export async function down(knex: Knex): Promise { + if (await knex.schema.hasTable(TableName.SecretVersionV2)) { + const hasSecretVersionV2UserActorId = await knex.schema.hasColumn(TableName.SecretVersionV2, "userActorId"); + const hasSecretVersionV2IdentityActorId = await knex.schema.hasColumn(TableName.SecretVersionV2, "identityActorId"); + const hasSecretVersionV2ActorType = await knex.schema.hasColumn(TableName.SecretVersionV2, "actorType"); + + await knex.schema.alterTable(TableName.SecretVersionV2, (t) => { + if (hasSecretVersionV2UserActorId) { + t.dropColumn("userActorId"); + } + if (hasSecretVersionV2IdentityActorId) { + t.dropColumn("identityActorId"); + } + if (hasSecretVersionV2ActorType) { + t.dropColumn("actorType"); + } + }); + } +} diff --git a/backend/src/db/schemas/secret-versions-v2.ts b/backend/src/db/schemas/secret-versions-v2.ts index 160ed1c14..593a46b06 100644 --- a/backend/src/db/schemas/secret-versions-v2.ts +++ b/backend/src/db/schemas/secret-versions-v2.ts @@ -25,7 +25,10 @@ export const SecretVersionsV2Schema = z.object({ folderId: z.string().uuid(), userId: z.string().uuid().nullable().optional(), createdAt: z.date(), - updatedAt: z.date() + updatedAt: z.date(), + userActorId: z.string().uuid().nullable().optional(), + identityActorId: z.string().uuid().nullable().optional(), + actorType: z.string().nullable().optional() }); export type TSecretVersionsV2 = z.infer; diff --git a/backend/src/ee/services/secret-rotation/secret-rotation-queue/secret-rotation-queue.ts b/backend/src/ee/services/secret-rotation/secret-rotation-queue/secret-rotation-queue.ts index fdc493b9f..ac8fcc9f2 100644 --- a/backend/src/ee/services/secret-rotation/secret-rotation-queue/secret-rotation-queue.ts +++ b/backend/src/ee/services/secret-rotation/secret-rotation-queue/secret-rotation-queue.ts @@ -13,6 +13,7 @@ import { NotFoundError } from "@app/lib/errors"; import { logger } from "@app/lib/logger"; import { alphaNumericNanoId } from "@app/lib/nanoid"; import { QueueJobs, QueueName, TQueueServiceFactory } from "@app/queue"; +import { ActorType } from "@app/services/auth/auth-type"; import { TKmsServiceFactory } from "@app/services/kms/kms-service"; import { KmsDataKey } from "@app/services/kms/kms-types"; import { TProjectBotServiceFactory } from "@app/services/project-bot/project-bot-service"; @@ -332,6 +333,7 @@ export const secretRotationQueueFactory = ({ await secretVersionV2BridgeDAL.insertMany( updatedSecrets.map(({ id, updatedAt, createdAt, ...el }) => ({ ...el, + actorType: ActorType.PLATFORM, secretId: id })), tx diff --git a/backend/src/ee/services/secret-snapshot/secret-snapshot-service.ts b/backend/src/ee/services/secret-snapshot/secret-snapshot-service.ts index 1c34f6b3d..dc2cff456 100644 --- a/backend/src/ee/services/secret-snapshot/secret-snapshot-service.ts +++ b/backend/src/ee/services/secret-snapshot/secret-snapshot-service.ts @@ -7,6 +7,7 @@ import { decryptSymmetric128BitHexKeyUTF8 } from "@app/lib/crypto"; import { InternalServerError, NotFoundError } from "@app/lib/errors"; import { groupBy } from "@app/lib/fn"; import { logger } from "@app/lib/logger"; +import { ActorType } from "@app/services/auth/auth-type"; import { TKmsServiceFactory } from "@app/services/kms/kms-service"; import { KmsDataKey } from "@app/services/kms/kms-types"; import { TProjectBotServiceFactory } from "@app/services/project-bot/project-bot-service"; @@ -370,7 +371,21 @@ export const secretSnapshotServiceFactory = ({ const secrets = await secretV2BridgeDAL.insertMany( rollbackSnaps.flatMap(({ secretVersions, folderId }) => secretVersions.map( - ({ latestSecretVersion, version, updatedAt, createdAt, secretId, envId, id, tags, ...el }) => ({ + ({ + latestSecretVersion, + version, + updatedAt, + createdAt, + secretId, + envId, + id, + tags, + // exclude the bottom fields from the secret - they are for versioning only. + userActorId, + identityActorId, + actorType, + ...el + }) => ({ ...el, id: secretId, version: deletedTopLevelSecsGroupById[secretId] ? latestSecretVersion + 1 : latestSecretVersion, @@ -401,8 +416,18 @@ export const secretSnapshotServiceFactory = ({ })), tx ); + const userActorId = actor === ActorType.USER ? actorId : undefined; + const identityActorId = actor !== ActorType.USER ? actorId : undefined; + const actorType = actor || ActorType.PLATFORM; + const secretVersions = await secretVersionV2BridgeDAL.insertMany( - secrets.map(({ id, updatedAt, createdAt, ...el }) => ({ ...el, secretId: id })), + secrets.map(({ id, updatedAt, createdAt, ...el }) => ({ + ...el, + secretId: id, + userActorId, + identityActorId, + actorType + })), tx ); await secretVersionV2TagBridgeDAL.insertMany( diff --git a/backend/src/server/routes/sanitizedSchemas.ts b/backend/src/server/routes/sanitizedSchemas.ts index 4d645ac4b..a6cc8bae0 100644 --- a/backend/src/server/routes/sanitizedSchemas.ts +++ b/backend/src/server/routes/sanitizedSchemas.ts @@ -111,7 +111,16 @@ export const secretRawSchema = z.object({ secretReminderRepeatDays: z.number().nullable().optional(), skipMultilineEncoding: z.boolean().default(false).nullable().optional(), createdAt: z.date(), - updatedAt: z.date() + updatedAt: z.date(), + actor: z + .object({ + actorId: z.string().nullable().optional(), + actorType: z.string().nullable().optional(), + name: z.string().nullable().optional(), + membershipId: z.string().nullable().optional() + }) + .optional() + .nullable() }); export const ProjectPermissionSchema = z.object({ diff --git a/backend/src/services/external-migration/external-migration-fns.ts b/backend/src/services/external-migration/external-migration-fns.ts index 744678792..f4a54f0db 100644 --- a/backend/src/services/external-migration/external-migration-fns.ts +++ b/backend/src/services/external-migration/external-migration-fns.ts @@ -772,6 +772,10 @@ export const importDataIntoInfisicalFn = async ({ secretVersionDAL, secretTagDAL, secretVersionTagDAL, + actor: { + type: actor, + actorId + }, tx }); } diff --git a/backend/src/services/secret-v2-bridge/secret-v2-bridge-fns.ts b/backend/src/services/secret-v2-bridge/secret-v2-bridge-fns.ts index cc40b0f26..751235cde 100644 --- a/backend/src/services/secret-v2-bridge/secret-v2-bridge-fns.ts +++ b/backend/src/services/secret-v2-bridge/secret-v2-bridge-fns.ts @@ -5,6 +5,7 @@ import { ForbiddenRequestError, NotFoundError } from "@app/lib/errors"; import { groupBy } from "@app/lib/fn"; import { logger } from "@app/lib/logger"; +import { ActorType } from "../auth/auth-type"; import { TProjectEnvDALFactory } from "../project-env/project-env-dal"; import { ResourceMetadataDTO } from "../resource-metadata/resource-metadata-schema"; import { TSecretFolderDALFactory } from "../secret-folder/secret-folder-dal"; @@ -62,6 +63,7 @@ export const fnSecretBulkInsert = async ({ resourceMetadataDAL, secretTagDAL, secretVersionTagDAL, + actor, tx }: TFnSecretBulkInsert) => { const sanitizedInputSecrets = inputSecrets.map( @@ -90,6 +92,10 @@ export const fnSecretBulkInsert = async ({ }) ); + const userActorId = actor && actor.type === ActorType.USER ? actor.actorId : undefined; + const identityActorId = actor && actor.type !== ActorType.USER ? actor.actorId : undefined; + const actorType = actor?.type || ActorType.PLATFORM; + const newSecrets = await secretDAL.insertMany( sanitizedInputSecrets.map((el) => ({ ...el, folderId })), tx @@ -106,6 +112,9 @@ export const fnSecretBulkInsert = async ({ sanitizedInputSecrets.map((el) => ({ ...el, folderId, + userActorId, + identityActorId, + actorType, secretId: newSecretGroupedByKeyName[el.key][0].id })), tx @@ -157,8 +166,13 @@ export const fnSecretBulkUpdate = async ({ secretVersionDAL, secretTagDAL, secretVersionTagDAL, - resourceMetadataDAL + resourceMetadataDAL, + actor }: TFnSecretBulkUpdate) => { + const userActorId = actor && actor?.type === ActorType.USER ? actor?.actorId : undefined; + const identityActorId = actor && actor?.type !== ActorType.USER ? actor?.actorId : undefined; + const actorType = actor?.type || ActorType.PLATFORM; + const sanitizedInputSecrets = inputSecrets.map( ({ filter, @@ -216,7 +230,10 @@ export const fnSecretBulkUpdate = async ({ encryptedValue, reminderRepeatDays, folderId, - secretId + secretId, + userActorId, + identityActorId, + actorType }) ), tx @@ -616,6 +633,12 @@ export const reshapeBridgeSecret = ( secret: Omit & { value: string; comment: string; + userActorName?: string | null; + identityActorName?: string | null; + userActorId?: string | null; + identityActorId?: string | null; + membershipId?: string | null; + actorType?: string | null; tags?: { id: string; slug: string; @@ -636,6 +659,14 @@ export const reshapeBridgeSecret = ( _id: secret.id, id: secret.id, user: secret.userId, + actor: secret.actorType + ? { + actorType: secret.actorType, + actorId: secret.userActorId || secret.identityActorId, + name: secret.identityActorName || secret.userActorName, + membershipId: secret.membershipId + } + : undefined, tags: secret.tags, skipMultilineEncoding: secret.skipMultilineEncoding, secretReminderRepeatDays: secret.reminderRepeatDays, diff --git a/backend/src/services/secret-v2-bridge/secret-v2-bridge-service.ts b/backend/src/services/secret-v2-bridge/secret-v2-bridge-service.ts index 0ffb0ea4c..9063da5c4 100644 --- a/backend/src/services/secret-v2-bridge/secret-v2-bridge-service.ts +++ b/backend/src/services/secret-v2-bridge/secret-v2-bridge-service.ts @@ -301,6 +301,10 @@ export const secretV2BridgeServiceFactory = ({ secretVersionDAL, secretTagDAL, secretVersionTagDAL, + actor: { + type: actor, + actorId + }, tx }) ); @@ -483,6 +487,10 @@ export const secretV2BridgeServiceFactory = ({ secretVersionDAL, secretTagDAL, secretVersionTagDAL, + actor: { + type: actor, + actorId + }, tx }) ); @@ -1230,6 +1238,10 @@ export const secretV2BridgeServiceFactory = ({ secretVersionDAL, secretTagDAL, secretVersionTagDAL, + actor: { + type: actor, + actorId + }, tx }) ); @@ -1490,6 +1502,10 @@ export const secretV2BridgeServiceFactory = ({ secretVersionDAL, secretTagDAL, secretVersionTagDAL, + actor: { + type: actor, + actorId + }, resourceMetadataDAL }); updatedSecrets.push(...bulkUpdatedSecrets.map((el) => ({ ...el, secretPath: folder.path }))); @@ -1522,6 +1538,10 @@ export const secretV2BridgeServiceFactory = ({ secretVersionDAL, secretTagDAL, secretVersionTagDAL, + actor: { + type: actor, + actorId + }, tx }); updatedSecrets.push(...bulkInsertedSecrets.map((el) => ({ ...el, secretPath: folder.path }))); @@ -1689,14 +1709,19 @@ export const secretV2BridgeServiceFactory = ({ type: KmsDataKey.SecretManager, projectId: folder.projectId }); - const secretVersions = await secretVersionDAL.find({ secretId }, { offset, limit, sort: [["createdAt", "desc"]] }); - return secretVersions.map((el) => - reshapeBridgeSecret(folder.projectId, folder.environment.envSlug, "/", { + const secretVersions = await secretVersionDAL.findVersionsBySecretIdWithActors(secretId, folder.projectId, { + offset, + limit, + sort: [["createdAt", "desc"]] + }); + + return secretVersions.map((el) => { + return reshapeBridgeSecret(folder.projectId, folder.environment.envSlug, "/", { ...el, value: el.encryptedValue ? secretManagerDecryptor({ cipherTextBlob: el.encryptedValue }).toString() : "", comment: el.encryptedComment ? secretManagerDecryptor({ cipherTextBlob: el.encryptedComment }).toString() : "" - }) - ); + }); + }); }; // this is a backfilling API for secret references @@ -1956,6 +1981,10 @@ export const secretV2BridgeServiceFactory = ({ secretTagDAL, resourceMetadataDAL, secretVersionTagDAL, + actor: { + type: actor, + actorId + }, inputSecrets: locallyCreatedSecrets.map((doc) => { return { type: doc.type, @@ -1982,6 +2011,10 @@ export const secretV2BridgeServiceFactory = ({ tx, secretTagDAL, secretVersionTagDAL, + actor: { + type: actor, + actorId + }, inputSecrets: locallyUpdatedSecrets.map((doc) => { return { filter: { diff --git a/backend/src/services/secret-v2-bridge/secret-v2-bridge-types.ts b/backend/src/services/secret-v2-bridge/secret-v2-bridge-types.ts index ad8264e81..22956463d 100644 --- a/backend/src/services/secret-v2-bridge/secret-v2-bridge-types.ts +++ b/backend/src/services/secret-v2-bridge/secret-v2-bridge-types.ts @@ -168,6 +168,10 @@ export type TFnSecretBulkInsert = { secretVersionDAL: Pick; secretTagDAL: Pick; secretVersionTagDAL: Pick; + actor?: { + type: string; + actorId: string; + }; }; type TRequireReferenceIfValue = @@ -192,6 +196,10 @@ export type TFnSecretBulkUpdate = { secretVersionDAL: Pick; secretTagDAL: Pick; secretVersionTagDAL: Pick; + actor?: { + type: string; + actorId: string; + }; tx?: Knex; }; diff --git a/backend/src/services/secret-v2-bridge/secret-version-dal.ts b/backend/src/services/secret-v2-bridge/secret-version-dal.ts index 7772b8518..d06aa1472 100644 --- a/backend/src/services/secret-v2-bridge/secret-version-dal.ts +++ b/backend/src/services/secret-v2-bridge/secret-version-dal.ts @@ -1,9 +1,10 @@ +/* eslint-disable @typescript-eslint/no-unsafe-assignment */ import { Knex } from "knex"; import { TDbClient } from "@app/db"; import { TableName, TSecretVersionsV2, TSecretVersionsV2Update } from "@app/db/schemas"; import { BadRequestError, DatabaseError } from "@app/lib/errors"; -import { ormify, selectAllTableCols } from "@app/lib/knex"; +import { ormify, selectAllTableCols, TFindOpt } from "@app/lib/knex"; import { logger } from "@app/lib/logger"; import { QueueName } from "@app/queue"; @@ -119,11 +120,67 @@ export const secretVersionV2BridgeDALFactory = (db: TDbClient) => { logger.info(`${QueueName.DailyResourceCleanUp}: pruning secret version v2 completed`); }; + const findVersionsBySecretIdWithActors = async ( + secretId: string, + projectId: string, + { offset, limit, sort = [["createdAt", "desc"]] }: TFindOpt = {}, + tx?: Knex + ) => { + try { + const query = (tx || db)(TableName.SecretVersionV2) + .leftJoin(TableName.Users, `${TableName.Users}.id`, `${TableName.SecretVersionV2}.userActorId`) + .leftJoin( + TableName.ProjectMembership, + `${TableName.ProjectMembership}.userId`, + `${TableName.SecretVersionV2}.userActorId` + ) + .leftJoin(TableName.Identity, `${TableName.Identity}.id`, `${TableName.SecretVersionV2}.identityActorId`) + .where((qb) => { + void qb.where(`${TableName.SecretVersionV2}.secretId`, secretId); + void qb.where(`${TableName.ProjectMembership}.projectId`, projectId); + }) + .orWhere((qb) => { + void qb.where(`${TableName.SecretVersionV2}.secretId`, secretId); + void qb.whereNull(`${TableName.ProjectMembership}.projectId`); + }) + .select( + selectAllTableCols(TableName.SecretVersionV2), + `${TableName.Users}.username as userActorName`, + `${TableName.Identity}.name as identityActorName`, + `${TableName.ProjectMembership}.id as membershipId` + ); + + if (limit) void query.limit(limit); + if (offset) void query.offset(offset); + if (sort) { + void query.orderBy( + sort.map(([column, order, nulls]) => ({ + column: `${TableName.SecretVersionV2}.${column as string}`, + order, + nulls + })) + ); + } + + const docs: Array< + TSecretVersionsV2 & { + userActorName: string | undefined | null; + identityActorName: string | undefined | null; + membershipId: string | undefined | null; + } + > = await query; + return docs; + } catch (error) { + throw new DatabaseError({ error, name: "FindVersionsBySecretIdWithActors" }); + } + }; + return { ...secretVersionV2Orm, pruneExcessVersions, findLatestVersionMany, bulkUpdate, - findLatestVersionByFolderId + findLatestVersionByFolderId, + findVersionsBySecretIdWithActors }; }; diff --git a/backend/src/services/secret/secret-fns.ts b/backend/src/services/secret/secret-fns.ts index 1775d1f44..d7c9b86fb 100644 --- a/backend/src/services/secret/secret-fns.ts +++ b/backend/src/services/secret/secret-fns.ts @@ -579,6 +579,7 @@ export const fnSecretBulkInsert = async ({ [`${TableName.Secret}Id` as const]: newSecretGroupByBlindIndex[secretBlindIndex as string][0].id })) ); + const secretVersions = await secretVersionDAL.insertMany( sanitizedInputSecrets.map((el) => ({ ...el, diff --git a/frontend/src/hooks/api/secrets/types.ts b/frontend/src/hooks/api/secrets/types.ts index 92dc220b8..9e0a82dda 100644 --- a/frontend/src/hooks/api/secrets/types.ts +++ b/frontend/src/hooks/api/secrets/types.ts @@ -101,6 +101,12 @@ export type SecretVersions = { skipMultilineEncoding?: boolean; createdAt: string; updatedAt: string; + actor?: { + actorId?: string | null; + actorType?: string | null; + name?: string | null; + membershipId?: string | null; + } | null; }; // dto diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretListView/SecretDetailSidebar.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretListView/SecretDetailSidebar.tsx index 168cd6f43..d78815222 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretListView/SecretDetailSidebar.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretListView/SecretDetailSidebar.tsx @@ -5,15 +5,18 @@ import { faArrowRotateRight, faCheckCircle, faClock, + faDesktop, faEyeSlash, faPlus, + faServer, faShare, faTag, - faTrash + faTrash, + faUser } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { zodResolver } from "@hookform/resolvers/zod"; -import { Link } from "@tanstack/react-router"; +import { Link, useNavigate } from "@tanstack/react-router"; import { format } from "date-fns"; import { UpgradePlanModal } from "@app/components/license/UpgradePlanModal"; @@ -46,6 +49,7 @@ import { } from "@app/context"; import { usePopUp, useToggle } from "@app/hooks"; import { useGetSecretVersion } from "@app/hooks/api"; +import { ActorType } from "@app/hooks/api/auditLogs/enums"; import { useGetSecretAccessList } from "@app/hooks/api/secrets/queries"; import { SecretV3RawSanitized, WsTag } from "@app/hooks/api/types"; import { ProjectType } from "@app/hooks/api/workspace/types"; @@ -120,6 +124,7 @@ export const SecretDetailSidebar = ({ {} ); const selectTagSlugs = selectedTags.map((i) => i.slug); + const navigate = useNavigate(); const cannotEditSecret = permission.cannot( ProjectPermissionActions.Edit, @@ -192,15 +197,73 @@ export const SecretDetailSidebar = ({ await onSaveSecret(secret, { ...secret, ...data }, () => reset()); }; - const handleReminderSubmit = async (reminderRepeatDays: number | null | undefined, reminderNote: string | null | undefined) => { - await onSaveSecret(secret, { ...secret, reminderRepeatDays, reminderNote, isReminderEvent: true }, () => { }); - } + const handleReminderSubmit = async ( + reminderRepeatDays: number | null | undefined, + reminderNote: string | null | undefined + ) => { + await onSaveSecret( + secret, + { ...secret, reminderRepeatDays, reminderNote, isReminderEvent: true }, + () => {} + ); + }; const [createReminderFormOpen, setCreateReminderFormOpen] = useToggle(false); const secretReminderRepeatDays = watch("reminderRepeatDays"); const secretReminderNote = watch("reminderNote"); + const getModifiedByIcon = (userType: string | undefined | null) => { + switch (userType) { + case ActorType.USER: + return faUser; + case ActorType.IDENTITY: + return faDesktop; + default: + return faServer; + } + }; + + const getModifiedByName = ( + userType: string | undefined | null, + userName: string | null | undefined + ) => { + switch (userType) { + case ActorType.PLATFORM: + return "System-generated"; + default: + return userName; + } + }; + + const getLinkToModifyHistoryEntity = ( + actorId: string, + actorType: string, + membershipId: string | null = "" + ) => { + switch (actorType) { + case ActorType.USER: + return `/${ProjectType.SecretManager}/${currentWorkspace.id}/members/${membershipId}`; + case ActorType.IDENTITY: + return `/${ProjectType.SecretManager}/${currentWorkspace.id}/identities/${actorId}`; + default: + return null; + } + }; + + const onModifyHistoryClick = ( + actorId: string | undefined | null, + actorType: string | undefined | null, + membershipId: string | undefined | null + ) => { + if (actorType && actorId && actorType !== ActorType.PLATFORM) { + const redirectLink = getLinkToModifyHistoryEntity(actorId, actorType, membershipId); + if (redirectLink) { + navigate({ to: redirectLink }); + } + } + }; + return ( <> @@ -618,7 +681,7 @@ export const SecretDetailSidebar = ({
Version History
- {secretVersion?.map(({ createdAt, secretValue, version, id }) => ( + {secretVersion?.map(({ createdAt, secretValue, version, id, actor }) => (
@@ -633,36 +696,42 @@ export const SecretDetailSidebar = ({
-
-
- Value: -
-
-
- - + -
- - {secretValue?.replace(/./g, "*")} - +
+ + {secretValue?.replace(/./g, "*")} + - + }} + onKeyDown={(e) => { + if (e.key === "Enter" || e.key === " ") { + e.currentTarget + .closest(".group") + ?.classList.add("show-value"); + } + }} + > + + + +
diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretListView/SecretListView.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretListView/SecretListView.tsx index ec765a361..e817aa1f9 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretListView/SecretListView.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretListView/SecretListView.tsx @@ -238,10 +238,12 @@ export const SecretListView = ({ if (!isReminderEvent) { handlePopUpClose("secretDetail"); } - + let successMessage; if (isReminderEvent) { - successMessage = reminderRepeatDays ? "Successfully saved secret reminder" : "Successfully deleted secret reminder"; + successMessage = reminderRepeatDays + ? "Successfully saved secret reminder" + : "Successfully deleted secret reminder"; } else { successMessage = "Successfully saved secrets"; }