diff --git a/backend/src/controllers/v1/integrationController.ts b/backend/src/controllers/v1/integrationController.ts index e647cfb00..eebf5672a 100644 --- a/backend/src/controllers/v1/integrationController.ts +++ b/backend/src/controllers/v1/integrationController.ts @@ -86,9 +86,15 @@ export const createIntegration = async (req: Request, res: Response) => { integration: integration.integration, environment: integration.environment, secretPath, + url: integration.url, app: integration.app, + appId: integration.appId, targetEnvironment: integration.targetEnvironment, - targetEnvironmentId: integration.targetEnvironmentId + targetEnvironmentId: integration.targetEnvironmentId, + targetService: integration.targetService, + targetServiceId: integration.targetServiceId, + path: integration.path, + region: integration.region } }, { @@ -192,9 +198,15 @@ export const deleteIntegration = async (req: Request, res: Response) => { integration: integration.integration, environment: integration.environment, secretPath: integration.secretPath, + url: integration.url, app: integration.app, + appId: integration.appId, targetEnvironment: integration.targetEnvironment, - targetEnvironmentId: integration.targetEnvironmentId + targetEnvironmentId: integration.targetEnvironmentId, + targetService: integration.targetService, + targetServiceId: integration.targetServiceId, + path: integration.path, + region: integration.region } }, { diff --git a/backend/src/controllers/v1/keyController.ts b/backend/src/controllers/v1/keyController.ts index ed82dfdcc..caf4fbf40 100644 --- a/backend/src/controllers/v1/keyController.ts +++ b/backend/src/controllers/v1/keyController.ts @@ -1,6 +1,9 @@ +import { Types } from "mongoose"; import { Request, Response } from "express"; import { Key } from "../../models"; import { findMembership } from "../../helpers/membership"; +import { EventType } from "../../ee/models"; +import { EEAuditLogService } from "../../ee/services"; /** * Add (encrypted) copy of workspace key for workspace with id [workspaceId] for user with @@ -44,7 +47,7 @@ export const uploadKey = async (req: Request, res: Response) => { */ export const getLatestKey = async (req: Request, res: Response) => { const { workspaceId } = req.params; - + // get latest key const latestKey = await Key.find({ workspace: workspaceId, @@ -58,6 +61,18 @@ export const getLatestKey = async (req: Request, res: Response) => { if (latestKey.length > 0) { resObj["latestKey"] = latestKey[0]; + await EEAuditLogService.createAuditLog( + req.authData, + { + type: EventType.GET_WORKSPACE_KEY, + metadata: { + keyId: latestKey[0]._id.toString() + } + }, + { + workspaceId: new Types.ObjectId(workspaceId) + } + ); } return res.status(200).send(resObj); diff --git a/backend/src/controllers/v1/secretImportController.ts b/backend/src/controllers/v1/secretImportController.ts index 181248553..7cff0a792 100644 --- a/backend/src/controllers/v1/secretImportController.ts +++ b/backend/src/controllers/v1/secretImportController.ts @@ -4,6 +4,8 @@ import SecretImport from "../../models/secretImports"; import { getAllImportedSecrets } from "../../services/SecretImportService"; import { BadRequestError } from "../../utils/errors"; import { ADMIN, MEMBER } from "../../variables"; +import { EEAuditLogService } from "../../ee/services"; +import { EventType } from "../../ee/models"; export const createSecretImport = async (req: Request, res: Response) => { const { workspaceId, environment, folderId, secretImport } = req.body; @@ -20,7 +22,24 @@ export const createSecretImport = async (req: Request, res: Response) => { folderId, imports: [{ environment: secretImport.environment, secretPath: secretImport.secretPath }] }); + await doc.save(); + await EEAuditLogService.createAuditLog( + req.authData, + { + type: EventType.CREATE_SECRET_IMPORT, + metadata: { + environment, + secretImportId: doc._id.toString(), + folderId: doc.folderId.toString(), + importEnvironment: secretImport.environment, + importSecretPath: secretImport.secretPath + } + }, + { + workspaceId: doc.workspace + } + ); return res.status(200).json({ message: "successfully created secret import" }); } @@ -30,11 +49,29 @@ export const createSecretImport = async (req: Request, res: Response) => { if (doesImportExist) { throw BadRequestError({ message: "Secret import already exist" }); } + importSecDoc.imports.push({ environment: secretImport.environment, secretPath: secretImport.secretPath }); await importSecDoc.save(); + + await EEAuditLogService.createAuditLog( + req.authData, + { + type: EventType.CREATE_SECRET_IMPORT, + metadata: { + environment, + secretImportId: importSecDoc._id.toString(), + folderId: importSecDoc.folderId.toString(), + importEnvironment: secretImport.environment, + importSecretPath: secretImport.secretPath + } + }, + { + workspaceId: importSecDoc.workspace + } + ); return res.status(200).json({ message: "successfully created secret import" }); }; @@ -56,6 +93,21 @@ export const updateSecretImport = async (req: Request, res: Response) => { importSecDoc.imports = secretImports; await importSecDoc.save(); + await EEAuditLogService.createAuditLog( + req.authData, + { + type: EventType.UPDATE_SECRET_IMPORT, + metadata: { + environment: importSecDoc.environment, + secretImportId: importSecDoc._id.toString(), + folderId: importSecDoc.folderId.toString(), + numberOfImports: secretImports.length + } + }, + { + workspaceId: importSecDoc.workspace + } + ); return res.status(200).json({ message: "successfully updated secret import" }); }; @@ -77,6 +129,24 @@ export const deleteSecretImport = async (req: Request, res: Response) => { !(environment === secretImportEnv && secretPath === secretImportPath) ); await importSecDoc.save(); + + await EEAuditLogService.createAuditLog( + req.authData, + { + type: EventType.DELETE_SECRET_IMPORT, + metadata: { + environment: importSecDoc.environment, + secretImportId: importSecDoc._id.toString(), + folderId: importSecDoc.folderId.toString(), + importEnvironment: secretImportEnv, + importSecretPath: secretImportPath + } + }, + { + workspaceId: importSecDoc.workspace + } + ); + return res.status(200).json({ message: "successfully delete secret import" }); }; @@ -111,6 +181,22 @@ export const getAllSecretsFromImport = async (req: Request, res: Response) => { return res.status(200).json({ secrets: [] }); } + await EEAuditLogService.createAuditLog( + req.authData, + { + type: EventType.GET_SECRET_IMPORTS, + metadata: { + environment, + secretImportId: importSecDoc._id.toString(), + folderId, + numberOfImports: importSecDoc.imports.length + } + }, + { + workspaceId: importSecDoc.workspace + } + ); + const secrets = await getAllImportedSecrets(workspaceId, environment, folderId); return res.status(200).json({ secrets }); }; diff --git a/backend/src/controllers/v2/secretsController.ts b/backend/src/controllers/v2/secretsController.ts index 14efd452a..4dd281f11 100644 --- a/backend/src/controllers/v2/secretsController.ts +++ b/backend/src/controllers/v2/secretsController.ts @@ -1,7 +1,7 @@ import { Types } from "mongoose"; import { Request, Response } from "express"; import { ISecret, Secret, ServiceTokenData } from "../../models"; -import { IAction, SecretVersion } from "../../ee/models"; +import { IAction, SecretVersion, EventType, AuditLog } from "../../ee/models"; import { ACTION_ADD_SECRETS, ACTION_DELETE_SECRETS, @@ -14,7 +14,7 @@ import { import { BadRequestError, UnauthorizedRequestError } from "../../utils/errors"; import { EventService } from "../../services"; import { eventPushSecrets } from "../../events"; -import { EELogService, EESecretService } from "../../ee/services"; +import { EELogService, EESecretService, EEAuditLogService } from "../../ee/services"; import { SecretService, TelemetryService } from "../../services"; import { getUserAgentType } from "../../utils/posthog"; import { PERMISSION_WRITE_SECRETS } from "../../variables"; @@ -56,12 +56,13 @@ export const batchSecrets = async (req: Request, res: Response) => { environment: string; requests: BatchSecretRequest[]; } = req.body; + let secretPath = req.body.secretPath as string; let folderId = req.body.folderId as string; - + const createSecrets: BatchSecret[] = []; const updateSecrets: BatchSecret[] = []; - const deleteSecrets: Types.ObjectId[] = []; + const deleteSecrets: { _id: Types.ObjectId, secretName: string; }[] = []; const actions: IAction[] = []; // get secret blind index salt @@ -133,7 +134,7 @@ export const batchSecrets = async (req: Request, res: Response) => { }); break; case "DELETE": - deleteSecrets.push(new Types.ObjectId(request.secret._id)); + deleteSecrets.push({ _id: new Types.ObjectId(request.secret._id), secretName: request.secret.secretName }); break; } } @@ -153,7 +154,31 @@ export const batchSecrets = async (req: Request, res: Response) => { }; }) }); + + const auditLogs = await Promise.all( + createdSecrets.map((secret, index) => { + return EEAuditLogService.createAuditLog( + req.authData, + { + type: EventType.CREATE_SECRET, + metadata: { + environment: secret.environment, + secretPath: secretPath ?? "/", + secretId: secret._id.toString(), + secretKey: createSecrets[index].secretName, + secretVersion: secret.version + } + }, + { + workspaceId: secret.workspace + }, + false + ); + }) + ); + await AuditLog.insertMany(auditLogs); + const addAction = (await EELogService.createAction({ name: ACTION_ADD_SECRETS, userId: req.user?._id, @@ -252,6 +277,30 @@ export const batchSecrets = async (req: Request, res: Response) => { $in: updateSecrets.map((u) => new Types.ObjectId(u._id)) } }); + + const auditLogs = await Promise.all( + updateSecrets.map((secret) => { + return EEAuditLogService.createAuditLog( + req.authData, + { + type: EventType.UPDATE_SECRET, + metadata: { + environment, + secretPath: secretPath ?? "/", + secretId: secret._id.toString(), + secretKey: secret.secretName, + secretVersion: listedSecretsObj[secret._id.toString()].version + } + }, + { + workspaceId: new Types.ObjectId(workspaceId) + }, + false + ); + }) + ); + + await AuditLog.insertMany(auditLogs); const updateAction = (await EELogService.createAction({ name: ACTION_UPDATE_SECRETS, @@ -279,21 +328,60 @@ export const batchSecrets = async (req: Request, res: Response) => { // handle delete secrets if (deleteSecrets.length > 0) { + const deleteSecretIds: Types.ObjectId[] = deleteSecrets.map((s) => s._id); + + const deletedSecretsObj = (await Secret.find({ + _id: { + $in: deleteSecretIds + } + })) + .reduce( + (obj: any, secret: ISecret) => ({ + ...obj, + [secret._id.toString()]: secret + }), + {} + ); + await Secret.deleteMany({ _id: { - $in: deleteSecrets + $in: deleteSecretIds } }); - + await EESecretService.markDeletedSecretVersions({ - secretIds: deleteSecrets + secretIds: deleteSecretIds }); + const auditLogs = await Promise.all( + deleteSecrets.map((secret) => { + return EEAuditLogService.createAuditLog( + req.authData, + { + type: EventType.DELETE_SECRET, + metadata: { + environment, + secretPath: secretPath ?? "/", + secretId: secret._id.toString(), + secretKey: secret.secretName, + secretVersion: deletedSecretsObj[secret._id.toString()].version + } + }, + { + workspaceId: new Types.ObjectId(workspaceId) + }, + false + ); + }) + ); + + await AuditLog.insertMany(auditLogs); + const deleteAction = (await EELogService.createAction({ name: ACTION_DELETE_SECRETS, userId: req.user._id, workspaceId: new Types.ObjectId(workspaceId), - secretIds: deleteSecrets + secretIds: deleteSecretIds })) as IAction; actions.push(deleteAction); @@ -351,7 +439,7 @@ export const batchSecrets = async (req: Request, res: Response) => { } if (deleteSecrets.length > 0) { - resObj["deletedSecrets"] = deleteSecrets.map((d) => d.toString()); + resObj["deletedSecrets"] = deleteSecrets.map((d) => d._id.toString()); } return res.status(200).send(resObj); diff --git a/backend/src/controllers/v2/workspaceController.ts b/backend/src/controllers/v2/workspaceController.ts index 123e0b24b..f057298be 100644 --- a/backend/src/controllers/v2/workspaceController.ts +++ b/backend/src/controllers/v2/workspaceController.ts @@ -9,6 +9,8 @@ import { import { pushKeys } from "../../helpers/key"; import { EventService, TelemetryService } from "../../services"; import { eventPushSecrets } from "../../events"; +import { EEAuditLogService } from "../../ee/services"; +import { EventType } from "../../ee/models"; interface V2PushSecret { type: string; // personal or shared @@ -180,16 +182,30 @@ export const getWorkspaceKey = async (req: Request, res: Response) => { } */ const { workspaceId } = req.params; - + const key = await Key.findOne({ workspace: workspaceId, receiver: req.user._id }).populate("sender", "+publicKey"); if (!key) throw new Error("Failed to find workspace key"); + + await EEAuditLogService.createAuditLog( + req.authData, + { + type: EventType.GET_WORKSPACE_KEY, + metadata: { + keyId: key._id.toString() + } + }, + { + workspaceId: new Types.ObjectId(workspaceId) + } + ); return res.status(200).json(key); }; + export const getWorkspaceServiceTokenData = async (req: Request, res: Response) => { const { workspaceId } = req.params; diff --git a/backend/src/ee/models/auditLog/enums.ts b/backend/src/ee/models/auditLog/enums.ts index 73dcd39bc..c1523cc84 100644 --- a/backend/src/ee/models/auditLog/enums.ts +++ b/backend/src/ee/models/auditLog/enums.ts @@ -17,6 +17,7 @@ export enum EventType { CREATE_SECRET = "create-secret", UPDATE_SECRET = "update-secret", DELETE_SECRET = "delete-secret", + GET_WORKSPACE_KEY = "get-workspace-key", AUTHORIZE_INTEGRATION = "authorize-integration", UNAUTHORIZE_INTEGRATION = "unauthorize-integration", CREATE_INTEGRATION = "create-integration", @@ -36,5 +37,9 @@ export enum EventType { DELETE_FOLDER = "delete-folder", CREATE_WEBHOOK = "create-webhook", UPDATE_WEBHOOK_STATUS = "update-webhook-status", - DELETE_WEBHOOK = "delete-webhook" + DELETE_WEBHOOK = "delete-webhook", + GET_SECRET_IMPORTS = "get-secret-imports", + CREATE_SECRET_IMPORT = "create-secret-import", + UPDATE_SECRET_IMPORT = "update-secret-import", + DELETE_SECRET_IMPORT = "delete-secret-import", } \ No newline at end of file diff --git a/backend/src/ee/models/auditLog/types.ts b/backend/src/ee/models/auditLog/types.ts index 04ff317e6..45a006354 100644 --- a/backend/src/ee/models/auditLog/types.ts +++ b/backend/src/ee/models/auditLog/types.ts @@ -80,17 +80,24 @@ interface DeleteSecretEvent { } } +interface GetWorkspaceKeyEvent { + type: EventType.GET_WORKSPACE_KEY, + metadata: { + keyId: string; + } +} + interface AuthorizeIntegrationEvent { type: EventType.AUTHORIZE_INTEGRATION; metadata: { - integration: string; // TODO: fix type + integration: string; } } interface UnauthorizeIntegrationEvent { type: EventType.UNAUTHORIZE_INTEGRATION; metadata: { - integration: string; // TODO: fix type + integration: string; } } @@ -101,9 +108,15 @@ interface CreateIntegrationEvent { integration: string; // TODO: fix type environment: string; secretPath: string; + url?: string; app?: string; + appId?: string; targetEnvironment?: string; - targetEnvironmentId?: string; // TODO: consider adding other vars + targetEnvironmentId?: string; + targetService?: string; + targetServiceId?: string; + path?: string; + region?: string; } } @@ -114,9 +127,15 @@ interface DeleteIntegrationEvent { integration: string; // TODO: fix type environment: string; secretPath: string; + url?: string; app?: string; + appId?: string; targetEnvironment?: string; targetEnvironmentId?: string; + targetService?: string; + targetServiceId?: string; + path?: string; + region?: string; } } @@ -275,12 +294,55 @@ interface DeleteWebhookEvent { } } +interface GetSecretImportsEvent { + type: EventType.GET_SECRET_IMPORTS, + metadata: { + environment: string; + secretImportId: string; + folderId: string; + numberOfImports: number; + } +} + +interface CreateSecretImportEvent { + type: EventType.CREATE_SECRET_IMPORT, + metadata: { + environment: string; + secretImportId: string; + folderId: string; + importEnvironment: string; + importSecretPath: string; + } +} + +interface UpdateSecretImportEvent { + type: EventType.UPDATE_SECRET_IMPORT, + metadata: { + environment: string; + secretImportId: string; + folderId: string; + numberOfImports: number; + } +} + +interface DeleteSecretImportEvent { + type: EventType.DELETE_SECRET_IMPORT, + metadata: { + environment: string; + secretImportId: string; + folderId: string; + importEnvironment: string; + importSecretPath: string; + } +} + export type Event = | GetSecretsEvent | GetSecretEvent | CreateSecretEvent | UpdateSecretEvent | DeleteSecretEvent + | GetWorkspaceKeyEvent | AuthorizeIntegrationEvent | UnauthorizeIntegrationEvent | CreateIntegrationEvent @@ -300,4 +362,8 @@ export type Event = | DeleteFolderEvent | CreateWebhookEvent | UpdateWebhookStatusEvent - | DeleteWebhookEvent; \ No newline at end of file + | DeleteWebhookEvent + | GetSecretImportsEvent + | CreateSecretImportEvent + | UpdateSecretImportEvent + | DeleteSecretImportEvent; \ No newline at end of file diff --git a/backend/src/ee/services/EEAuditLogService.ts b/backend/src/ee/services/EEAuditLogService.ts index 035742077..91fbc4252 100644 --- a/backend/src/ee/services/EEAuditLogService.ts +++ b/backend/src/ee/services/EEAuditLogService.ts @@ -16,7 +16,7 @@ type ValidEventScope = | Required export default class EEAuditLogService { - static async createAuditLog(authData: AuthData, event: Event, eventScope: ValidEventScope) { + static async createAuditLog(authData: AuthData, event: Event, eventScope: ValidEventScope, shouldSave: boolean = true) { const MS_IN_DAY = 24 * 60 * 60 * 1000; @@ -39,7 +39,11 @@ export default class EEAuditLogService { userAgent: authData.userAgent, userAgentType: authData.userAgentType, expiresAt: new Date(Date.now() + ttl) - }).save(); + }); + + if (shouldSave) { + await auditLog.save(); + } return auditLog; } diff --git a/backend/src/types/secret/index.d.ts b/backend/src/types/secret/index.d.ts index 13391549e..f60fdfd4c 100644 --- a/backend/src/types/secret/index.d.ts +++ b/backend/src/types/secret/index.d.ts @@ -30,6 +30,7 @@ export interface BatchSecretRequest { export interface BatchSecret { _id: string; type: "shared" | "personal"; + secretName: string; secretBlindIndex: string; secretKeyCiphertext: string; secretKeyIV: string; diff --git a/frontend/src/hooks/api/auditLogs/constants.tsx b/frontend/src/hooks/api/auditLogs/constants.tsx index 3b15efa91..f76e0f4be 100644 --- a/frontend/src/hooks/api/auditLogs/constants.tsx +++ b/frontend/src/hooks/api/auditLogs/constants.tsx @@ -1,11 +1,12 @@ import { EventType, UserAgentType } from "./enums"; export const eventToNameMap: { [K in EventType]: string } = { - [EventType.GET_SECRETS]: "Get secrets", - [EventType.GET_SECRET]: "Get secret", + [EventType.GET_SECRETS]: "List secrets", + [EventType.GET_SECRET]: "Read secret", [EventType.CREATE_SECRET]: "Create secret", [EventType.UPDATE_SECRET]: "Update secret", [EventType.DELETE_SECRET]: "Delete secret", + [EventType.GET_WORKSPACE_KEY]: "Read project key", [EventType.AUTHORIZE_INTEGRATION]: "Authorize integration", [EventType.UNAUTHORIZE_INTEGRATION]: "Unauthorize integration", [EventType.CREATE_INTEGRATION]: "Create integration", @@ -26,6 +27,11 @@ export const eventToNameMap: { [K in EventType]: string } = { [EventType.CREATE_WEBHOOK]: "Create webhook", [EventType.UPDATE_WEBHOOK_STATUS]: "Update webhook status", [EventType.DELETE_WEBHOOK]: "Delete webhook", + [EventType.GET_SECRET_IMPORTS]: "List secret imports", + [EventType.CREATE_SECRET_IMPORT]: "Create secret import", + [EventType.UPDATE_SECRET_IMPORT]: "Update secret import", + [EventType.DELETE_SECRET_IMPORT]: "Delete secret import", + }; export const userAgentTTypeoNameMap: { [K in UserAgentType]: string } = { diff --git a/frontend/src/hooks/api/auditLogs/enums.tsx b/frontend/src/hooks/api/auditLogs/enums.tsx index 3e159552d..dfc047b03 100644 --- a/frontend/src/hooks/api/auditLogs/enums.tsx +++ b/frontend/src/hooks/api/auditLogs/enums.tsx @@ -16,6 +16,7 @@ export enum EventType { CREATE_SECRET = "create-secret", UPDATE_SECRET = "update-secret", DELETE_SECRET = "delete-secret", + GET_WORKSPACE_KEY = "get-workspace-key", AUTHORIZE_INTEGRATION = "authorize-integration", UNAUTHORIZE_INTEGRATION = "unauthorize-integration", CREATE_INTEGRATION = "create-integration", @@ -35,5 +36,9 @@ export enum EventType { DELETE_FOLDER = "delete-folder", CREATE_WEBHOOK = "create-webhook", UPDATE_WEBHOOK_STATUS = "update-webhook-status", - DELETE_WEBHOOK = "delete-webhook" + DELETE_WEBHOOK = "delete-webhook", + GET_SECRET_IMPORTS = "get-secret-imports", + CREATE_SECRET_IMPORT = "create-secret-import", + UPDATE_SECRET_IMPORT = "update-secret-import", + DELETE_SECRET_IMPORT = "delete-secret-import" } \ No newline at end of file diff --git a/frontend/src/hooks/api/auditLogs/types.tsx b/frontend/src/hooks/api/auditLogs/types.tsx index 71cf01c5c..bcfa8c228 100644 --- a/frontend/src/hooks/api/auditLogs/types.tsx +++ b/frontend/src/hooks/api/auditLogs/types.tsx @@ -82,17 +82,24 @@ interface DeleteSecretEvent { } } +interface GetWorkspaceKeyEvent { + type: EventType.GET_WORKSPACE_KEY, + metadata: { + keyId: string; + } +} + interface AuthorizeIntegrationEvent { type: EventType.AUTHORIZE_INTEGRATION; metadata: { - integration: string; // TODO: fix type + integration: string; } } interface UnauthorizeIntegrationEvent { type: EventType.UNAUTHORIZE_INTEGRATION; metadata: { - integration: string; // TODO: fix type + integration: string; } } @@ -100,12 +107,18 @@ interface CreateIntegrationEvent { type: EventType.CREATE_INTEGRATION; metadata: { integrationId: string; - integration: string; // TODO: fix type + integration: string; environment: string; secretPath: string; + url?: string; app?: string; + appId?: string; targetEnvironment?: string; - targetEnvironmentId?: string; // TODO: consider adding other vars + targetEnvironmentId?: string; + targetService?: string; + targetServiceId?: string; + path?: string; + region?: string; } } @@ -113,12 +126,18 @@ interface DeleteIntegrationEvent { type: EventType.DELETE_INTEGRATION; metadata: { integrationId: string; - integration: string; // TODO: fix type + integration: string; environment: string; secretPath: string; + url?: string; app?: string; + appId?: string; targetEnvironment?: string; targetEnvironmentId?: string; + targetService?: string; + targetServiceId?: string; + path?: string; + region?: string; } } @@ -277,12 +296,55 @@ interface DeleteWebhookEvent { } } +interface GetSecretImportsEvent { + type: EventType.GET_SECRET_IMPORTS, + metadata: { + environment: string; + secretImportId: string; + folderId: string; + numberOfImports: number; + } +} + +interface CreateSecretImportEvent { + type: EventType.CREATE_SECRET_IMPORT, + metadata: { + environment: string; + secretImportId: string; + folderId: string; + importEnvironment: string; + importSecretPath: string; + } +} + +interface UpdateSecretImportEvent { + type: EventType.UPDATE_SECRET_IMPORT, + metadata: { + environment: string; + secretImportId: string; + folderId: string; + numberOfImports: number; + } +} + +interface DeleteSecretImportEvent { + type: EventType.DELETE_SECRET_IMPORT, + metadata: { + environment: string; + secretImportId: string; + folderId: string; + importEnvironment: string; + importSecretPath: string; + } +} + export type Event = | GetSecretsEvent | GetSecretEvent | CreateSecretEvent | UpdateSecretEvent | DeleteSecretEvent + | GetWorkspaceKeyEvent | AuthorizeIntegrationEvent | UnauthorizeIntegrationEvent | CreateIntegrationEvent @@ -302,7 +364,11 @@ export type Event = | DeleteFolderEvent | CreateWebhookEvent | UpdateWebhookStatusEvent - | DeleteWebhookEvent; + | DeleteWebhookEvent + | GetSecretImportsEvent + | CreateSecretImportEvent + | UpdateSecretImportEvent + | DeleteSecretImportEvent; export type AuditLog = { _id: string; diff --git a/frontend/src/hooks/api/secrets/types.ts b/frontend/src/hooks/api/secrets/types.ts index 9e3092257..c317da2c9 100644 --- a/frontend/src/hooks/api/secrets/types.ts +++ b/frontend/src/hooks/api/secrets/types.ts @@ -79,7 +79,7 @@ export type UpdateSecretArg = { export type CreateSecretArg = Omit; -export type DeleteSecretArg = { _id: string }; +export type DeleteSecretArg = { _id: string, secretName: string; }; export type BatchSecretDTO = { workspaceId: string; diff --git a/frontend/src/views/DashboardPage/DashboardPage.tsx b/frontend/src/views/DashboardPage/DashboardPage.tsx index 32133445b..acb0f59ff 100644 --- a/frontend/src/views/DashboardPage/DashboardPage.tsx +++ b/frontend/src/views/DashboardPage/DashboardPage.tsx @@ -149,7 +149,7 @@ export const DashboardPage = () => { const [snapshotId, setSnaphotId] = useState(null); const [selectedEnv, setSelectedEnv] = useState(null); const [sortDir, setSortDir] = useState<"asc" | "desc">("asc"); - const deletedSecretIds = useRef([]); + const deletedSecretIds = useRef<{ id: string; secretName: string; }[]>([]); const { hasUnsavedChanges, setHasUnsavedChanges } = useLeaveConfirm({ initialValue: false }); const folderId = router.query.folderId as string; @@ -498,9 +498,15 @@ export const DashboardPage = () => { // record all deleted ids // This will make final deletion easier - const onSecretDelete = useCallback((index: number, id?: string, overrideId?: string) => { - if (id) deletedSecretIds.current.push(id); - if (overrideId) deletedSecretIds.current.push(overrideId); + const onSecretDelete = useCallback((index: number, secretName: string, id?: string, overrideId?: string) => { + if (id) deletedSecretIds.current.push({ + id, + secretName + }); + if (overrideId) deletedSecretIds.current.push({ + id: overrideId, + secretName + }); remove(index); // just the case if this is called from drawer handlePopUpClose("secretDetails"); diff --git a/frontend/src/views/DashboardPage/DashboardPage.utils.ts b/frontend/src/views/DashboardPage/DashboardPage.utils.ts index 375a05489..a8e63f89f 100644 --- a/frontend/src/views/DashboardPage/DashboardPage.utils.ts +++ b/frontend/src/views/DashboardPage/DashboardPage.utils.ts @@ -182,15 +182,18 @@ const deepCompareSecrets = (lhs: DecryptedSecret, rhs: any) => JSON.stringify(lhs.tags) === JSON.stringify(rhs.tags); export const transformSecretsToBatchSecretReq = ( - deletedSecretIds: string[], + deletedSecretIds: { id: string; secretName: string; }[], latestFileKey: any, secrets: FormData["secrets"], intialValues: DecryptedSecret[] = [] ) => { // deleted secrets - const secretsToBeDeleted: BatchSecretDTO["requests"] = deletedSecretIds.map((id) => ({ + const secretsToBeDeleted: BatchSecretDTO["requests"] = deletedSecretIds.map(({ id, secretName }) => ({ method: "DELETE", - secret: { _id: id } + secret: { + _id: id, + secretName + } })); const secretsToBeUpdated: BatchSecretDTO["requests"] = []; @@ -261,7 +264,7 @@ export const transformSecretsToBatchSecretReq = ( if (idOverride) { // if action is deleted meaning override has been removed but id is kept to collect at this point if (overrideAction === SecretActionType.Deleted) { - secretsToBeDeleted.push({ method: "DELETE", secret: { _id: idOverride } }); + secretsToBeDeleted.push({ method: "DELETE", secret: { _id: idOverride, secretName: key } }); } else { // if not deleted action then as id is there its an updated const initialSecretValue = intialValues?.find(({ _id: secId }) => secId === _id)!; diff --git a/frontend/src/views/DashboardPage/components/SecretInputRow/SecretInputRow.tsx b/frontend/src/views/DashboardPage/components/SecretInputRow/SecretInputRow.tsx index aba283b27..780a36225 100644 --- a/frontend/src/views/DashboardPage/components/SecretInputRow/SecretInputRow.tsx +++ b/frontend/src/views/DashboardPage/components/SecretInputRow/SecretInputRow.tsx @@ -67,7 +67,7 @@ type Props = { isSecretValueHidden: boolean; searchTerm: string; // to record the ids of deleted ones - onSecretDelete: (index: number, id?: string, overrideId?: string) => void; + onSecretDelete: (index: number, secretName: string, id?: string, overrideId?: string) => void; // sidebar control props onRowExpand: (secId: string | undefined, index: number) => void; // tag props @@ -495,7 +495,9 @@ export const SecretInputRow = memo( colorSchema="danger" ariaLabel="delete" isDisabled={isReadOnly || isRollbackMode} - onClick={() => onSecretDelete(index, secId, idOverride)} + onClick={() => { + onSecretDelete(index, secKey, secId, idOverride); + }} > diff --git a/frontend/src/views/Project/LogsPage/components/LogsFilter.tsx b/frontend/src/views/Project/LogsPage/components/LogsFilter.tsx index dce7c4938..88523e012 100644 --- a/frontend/src/views/Project/LogsPage/components/LogsFilter.tsx +++ b/frontend/src/views/Project/LogsPage/components/LogsFilter.tsx @@ -73,7 +73,7 @@ export const LogsFilter = ({ className="w-40 mr-4" > onChange(e)} className="w-full" @@ -121,7 +121,7 @@ export const LogsFilter = ({ className="w-40 mr-4" >