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..48af65d29 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 @@ -39,6 +39,7 @@ import { secretRotationPreSetFn } from "./secret-rotation-queue-fn"; import { TSecretRotationData, TSecretRotationDbFn, TSecretRotationEncData } from "./secret-rotation-queue-types"; +import { ActorType } from "@app/services/auth/auth-type"; export type TSecretRotationQueueFactory = ReturnType; @@ -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 06ad0cba5..40ac4493f 100644 --- a/backend/src/ee/services/secret-snapshot/secret-snapshot-service.ts +++ b/backend/src/ee/services/secret-snapshot/secret-snapshot-service.ts @@ -34,6 +34,7 @@ import { TSnapshotFolderDALFactory } from "./snapshot-folder-dal"; import { TSnapshotSecretDALFactory } from "./snapshot-secret-dal"; import { TSnapshotSecretV2DALFactory } from "./snapshot-secret-v2-dal"; import { getFullFolderPath } from "./snapshot-service-fns"; +import { ActorType } from "@app/services/auth/auth-type"; type TSecretSnapshotServiceFactoryDep = { snapshotDAL: TSnapshotDALFactory; @@ -414,8 +415,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 16a7396cd..3009993c0 100644 --- a/backend/src/server/routes/sanitizedSchemas.ts +++ b/backend/src/server/routes/sanitizedSchemas.ts @@ -114,8 +114,8 @@ export const secretRawSchema = z.object({ updatedAt: z.date(), actor: z .object({ - actorId: z.string().nullable(), - actorType: z.string().nullable(), + actorId: z.string().nullable().optional(), + actorType: z.string().nullable().optional(), name: z.string().nullable().optional() }) .optional() 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 046b23dec..007df0872 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 @@ -94,6 +94,7 @@ 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 })), @@ -113,7 +114,7 @@ export const fnSecretBulkInsert = async ({ folderId, userActorId, identityActorId, - actorType: actor?.type, + actorType, secretId: newSecretGroupedByKeyName[el.key][0].id })), tx @@ -170,6 +171,7 @@ export const fnSecretBulkUpdate = async ({ }: 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( ({ @@ -231,7 +233,7 @@ export const fnSecretBulkUpdate = async ({ secretId, userActorId, identityActorId, - actorType: actor?.type + actorType }) ), tx diff --git a/backend/src/services/secret/secret-fns.ts b/backend/src/services/secret/secret-fns.ts index 1775d1f44..3ecdcbd08 100644 --- a/backend/src/services/secret/secret-fns.ts +++ b/backend/src/services/secret/secret-fns.ts @@ -525,6 +525,7 @@ export const fnSecretBulkInsert = async ({ secretVersionDAL, secretTagDAL, secretVersionTagDAL, + actor, tx }: TFnSecretBulkInsert) => { const sanitizedInputSecrets = inputSecrets.map( @@ -579,9 +580,17 @@ export const fnSecretBulkInsert = async ({ [`${TableName.Secret}Id` as const]: newSecretGroupByBlindIndex[secretBlindIndex as string][0].id })) ); + + 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 secretVersions = await secretVersionDAL.insertMany( sanitizedInputSecrets.map((el) => ({ ...el, + userActorId, + identityActorId, + actorType, secretId: newSecretGroupByBlindIndex[el.secretBlindIndex as string][0].id })), tx @@ -614,7 +623,8 @@ export const fnSecretBulkUpdate = async ({ secretDAL, secretVersionDAL, secretTagDAL, - secretVersionTagDAL + secretVersionTagDAL, + actor }: TFnSecretBulkUpdate) => { const sanitizedInputSecrets = inputSecrets.map( ({ @@ -664,10 +674,17 @@ export const fnSecretBulkUpdate = 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.bulkUpdate(sanitizedInputSecrets, tx); const secretVersions = await secretVersionDAL.insertMany( newSecrets.map(({ id, createdAt, updatedAt, ...el }) => ({ ...el, + userActorId, + identityActorId, + actorType, secretId: id })), tx diff --git a/backend/src/services/secret/secret-types.ts b/backend/src/services/secret/secret-types.ts index 242296c50..4b671b02d 100644 --- a/backend/src/services/secret/secret-types.ts +++ b/backend/src/services/secret/secret-types.ts @@ -324,7 +324,7 @@ export type TFnSecretBulkInsert = { secretVersionTagDAL: Pick; actor?: { type?: string; - actorId: string; + actorId?: string; }; }; @@ -342,7 +342,7 @@ export type TFnSecretBulkUpdate = { tx?: Knex; actor?: { type?: string; - actorId: string; + actorId?: string; }; }; diff --git a/frontend/src/hooks/api/secrets/types.ts b/frontend/src/hooks/api/secrets/types.ts index 92e671c8b..9fbef1488 100644 --- a/frontend/src/hooks/api/secrets/types.ts +++ b/frontend/src/hooks/api/secrets/types.ts @@ -102,10 +102,10 @@ export type SecretVersions = { createdAt: string; updatedAt: string; actor?: { - actorId?: string, - actorType: string, - name?: string - }; + actorId?: string | null; + actorType?: string | null; + name?: 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 161f9cbf1..2f1a178b9 100644 --- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretListView/SecretDetailSidebar.tsx +++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/SecretListView/SecretDetailSidebar.tsx @@ -48,12 +48,11 @@ import { useWorkspace } from "@app/context"; import { usePopUp, useToggle } from "@app/hooks"; -import { useGetSecretVersion } from "@app/hooks/api"; +import { useGetSecretVersion, useGetWorkspaceUsers } from "@app/hooks/api"; import { useGetSecretAccessList } from "@app/hooks/api/secrets/queries"; import { SecretV3RawSanitized, WsTag } from "@app/hooks/api/types"; import { ProjectType } from "@app/hooks/api/workspace/types"; import { ActorType } from "@app/hooks/api/auditLogs/enums"; -import { useGetWorkspaceUsers } from "@app/hooks/api"; import { CreateReminderForm } from "./CreateReminderForm"; import { formSchema, SecretActionType, TFormSchema } from "./SecretListView.utils"; @@ -127,7 +126,7 @@ export const SecretDetailSidebar = ({ const selectTagSlugs = selectedTags.map((i) => i.slug); const navigate = useNavigate(); const { data: members = [] } = useGetWorkspaceUsers(currentWorkspace.id); - + const cannotEditSecret = permission.cannot( ProjectPermissionActions.Edit, subject(ProjectPermissionSub.Secrets, { @@ -199,9 +198,16 @@ 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); @@ -217,14 +223,23 @@ export const SecretDetailSidebar = ({ default: return faServer; } - } + }; + + const getModifiedByName = (userType: string, userName: string | undefined) => { + switch (userType) { + case ActorType.PLATFORM: + return "System-generated"; + default: + return userName; + } + }; const getUserMembershipId = (actorId: string) => { return members.filter((member) => member.user?.id === actorId)?.[0].id || null; - } + }; const getLinkToModifyHistoryEntity = (actorId: string, actorType: string) => { - switch(actorType) { + switch (actorType) { case ActorType.USER: return `/${ProjectType.SecretManager}/${currentWorkspace.id}/members/${getUserMembershipId(actorId)}`; case ActorType.IDENTITY: @@ -232,16 +247,16 @@ export const SecretDetailSidebar = ({ default: return null; } - } + }; const onModifyHistoryClick = (actorId: string | undefined, actorType: string) => { - if (actorId && actorType !== ActorType.PLATFORM) { + if (actorId && actorType !== ActorType.PLATFORM) { const redirectLink = getLinkToModifyHistoryEntity(actorId, actorType); if (redirectLink) { navigate({ to: redirectLink }); } } - } + }; return ( <> @@ -255,7 +270,7 @@ export const SecretDetailSidebar = ({ if (data) { setValue("reminderRepeatDays", data.days, { shouldDirty: false }); setValue("reminderNote", data.note, { shouldDirty: false }); - handleReminderSubmit(data.days, data.note) + handleReminderSubmit(data.days, data.note); } }} /> @@ -675,15 +690,23 @@ export const SecretDetailSidebar = ({
-
+
{actor && (
-
- Modified by: - +
+ Modified by: + {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */} -
onModifyHistoryClick(actor.actorId, actor.actorType)} className="cursor-pointer"> - +
+ onModifyHistoryClick(actor.actorId, actor.actorType) + } + className="cursor-pointer" + > +
@@ -697,7 +720,7 @@ export const SecretDetailSidebar = ({