Merge branch 'main' into feat/remindersImprovement

This commit is contained in:
Carlos Monastyrski
2025-07-23 11:27:31 -03:00
619 changed files with 15481 additions and 6720 deletions
@@ -2,7 +2,14 @@ import { ForbiddenError, MongoAbility, subject } from "@casl/ability";
import { Knex } from "knex";
import { z } from "zod";
import { ProjectMembershipRole, SecretsV2Schema, SecretType, TableName, TSecretsV2 } from "@app/db/schemas";
import {
ActionProjectType,
ProjectMembershipRole,
SecretsV2Schema,
SecretType,
TableName,
TSecretsV2
} from "@app/db/schemas";
import {
hasSecretReadValueOrDescribePermission,
throwIfMissingSecretReadValueOrDescribePermission
@@ -28,7 +35,7 @@ import { logger } from "@app/lib/logger";
import { alphaNumericNanoId } from "@app/lib/nanoid";
import { ActorType } from "../auth/auth-type";
import { TFolderCommitServiceFactory } from "../folder-commit/folder-commit-service";
import { TCommitResourceChangeDTO, TFolderCommitServiceFactory } from "../folder-commit/folder-commit-service";
import { TKmsServiceFactory } from "../kms/kms-service";
import { KmsDataKey } from "../kms/kms-types";
import { TProjectEnvDALFactory } from "../project-env/project-env-dal";
@@ -239,7 +246,8 @@ export const secretV2BridgeServiceFactory = ({
actorId,
projectId,
actorAuthMethod,
actorOrgId
actorOrgId,
actionProjectType: ActionProjectType.SecretManager
});
const folder = await folderDAL.findBySecretPath(projectId, environment, secretPath);
@@ -394,7 +402,8 @@ export const secretV2BridgeServiceFactory = ({
actorId,
projectId,
actorAuthMethod,
actorOrgId
actorOrgId,
actionProjectType: ActionProjectType.SecretManager
});
if (inputSecret.newSecretName === "") {
@@ -620,7 +629,8 @@ export const secretV2BridgeServiceFactory = ({
actorId,
projectId,
actorAuthMethod,
actorOrgId
actorOrgId,
actionProjectType: ActionProjectType.SecretManager
});
const folder = await folderDAL.findBySecretPath(projectId, environment, secretPath);
@@ -756,7 +766,8 @@ export const secretV2BridgeServiceFactory = ({
actorId,
projectId,
actorAuthMethod,
actorOrgId
actorOrgId,
actionProjectType: ActionProjectType.SecretManager
});
throwIfMissingSecretReadValueOrDescribePermission(permission, ProjectPermissionSecretActions.DescribeSecret);
}
@@ -801,7 +812,8 @@ export const secretV2BridgeServiceFactory = ({
actorId,
projectId,
actorAuthMethod,
actorOrgId
actorOrgId,
actionProjectType: ActionProjectType.SecretManager
});
throwIfMissingSecretReadValueOrDescribePermission(permission, ProjectPermissionSecretActions.DescribeSecret);
@@ -900,7 +912,8 @@ export const secretV2BridgeServiceFactory = ({
actorId,
projectId,
actorAuthMethod,
actorOrgId
actorOrgId,
actionProjectType: ActionProjectType.SecretManager
});
if (!isInternal) {
throwIfMissingSecretReadValueOrDescribePermission(permission, ProjectPermissionSecretActions.DescribeSecret);
@@ -953,7 +966,8 @@ export const secretV2BridgeServiceFactory = ({
actorId,
projectId,
actorAuthMethod,
actorOrgId
actorOrgId,
actionProjectType: ActionProjectType.SecretManager
});
throwIfMissingSecretReadValueOrDescribePermission(permission, ProjectPermissionSecretActions.DescribeSecret);
@@ -1251,7 +1265,8 @@ export const secretV2BridgeServiceFactory = ({
actorId,
projectId: secret.projectId,
actorAuthMethod,
actorOrgId
actorOrgId,
actionProjectType: ActionProjectType.SecretManager
});
throwIfMissingSecretReadValueOrDescribePermission(permission, ProjectPermissionSecretActions.ReadValue, {
@@ -1314,7 +1329,8 @@ export const secretV2BridgeServiceFactory = ({
actorId,
projectId,
actorAuthMethod,
actorOrgId
actorOrgId,
actionProjectType: ActionProjectType.SecretManager
});
const folder = await folderDAL.findBySecretPath(projectId, environment, path);
@@ -1519,14 +1535,17 @@ export const secretV2BridgeServiceFactory = ({
actorOrgId,
environment,
projectId,
secrets: inputSecrets
}: TCreateManySecretDTO) => {
secrets: inputSecrets,
tx: providedTx,
commitChanges
}: TCreateManySecretDTO & { tx?: Knex; commitChanges?: TCommitResourceChangeDTO[] }) => {
const { permission } = await permissionService.getProjectPermission({
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
actorOrgId,
actionProjectType: ActionProjectType.SecretManager
});
const folder = await folderDAL.findBySecretPath(projectId, environment, secretPath);
@@ -1603,8 +1622,8 @@ export const secretV2BridgeServiceFactory = ({
const { encryptor: secretManagerEncryptor, decryptor: secretManagerDecryptor } =
await kmsService.createCipherPairWithDataKey({ type: KmsDataKey.SecretManager, projectId });
const newSecrets = await secretDAL.transaction(async (tx) =>
fnSecretBulkInsert({
const executeBulkInsert = async (tx: Knex) => {
return fnSecretBulkInsert({
inputSecrets: inputSecrets.map((el) => {
const references = secretReferencesGroupByInputSecretKey[el.secretKey]?.nestedReferences;
@@ -1626,6 +1645,7 @@ export const secretV2BridgeServiceFactory = ({
};
}),
folderId,
commitChanges,
orgId: actorOrgId,
secretDAL,
resourceMetadataDAL,
@@ -1638,8 +1658,13 @@ export const secretV2BridgeServiceFactory = ({
actorId
},
tx
})
);
});
};
const newSecrets = providedTx
? await executeBulkInsert(providedTx)
: await secretDAL.transaction(executeBulkInsert);
await secretDAL.invalidateSecretCacheByProjectId(projectId);
await snapshotService.performSnapshot(folderId);
await secretQueueService.syncSecrets({
@@ -1686,14 +1711,17 @@ export const secretV2BridgeServiceFactory = ({
projectId,
secretPath: defaultSecretPath = "/",
secrets: inputSecrets,
mode: updateMode
}: TUpdateManySecretDTO) => {
mode: updateMode,
tx: providedTx,
commitChanges
}: TUpdateManySecretDTO & { tx?: Knex; commitChanges?: TCommitResourceChangeDTO[] }) => {
const { permission } = await permissionService.getProjectPermission({
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
actorOrgId,
actionProjectType: ActionProjectType.SecretManager
});
const secretsToUpdateGroupByPath = groupBy(inputSecrets, (el) => el.secretPath || defaultSecretPath);
@@ -1716,18 +1744,20 @@ export const secretV2BridgeServiceFactory = ({
const { encryptor: secretManagerEncryptor, decryptor: secretManagerDecryptor } =
await kmsService.createCipherPairWithDataKey({ type: KmsDataKey.SecretManager, projectId });
const updatedSecrets: Array<
TSecretsV2 & {
secretPath: string;
tags: {
id: string;
slug: string;
color?: string | null;
name: string;
}[];
}
> = [];
await secretDAL.transaction(async (tx) => {
// Function to execute the bulk update operation
const executeBulkUpdate = async (tx: Knex) => {
const updatedSecrets: Array<
TSecretsV2 & {
secretPath: string;
tags: {
id: string;
slug: string;
color?: string | null;
name: string;
}[];
}
> = [];
for await (const folder of folders) {
if (!folder) throw new NotFoundError({ message: "Folder not found" });
@@ -1846,7 +1876,7 @@ export const secretV2BridgeServiceFactory = ({
{
operator: "eq",
field: `${TableName.SecretV2}.key` as "key",
value: el.secretKey
value: el.newSecretName as string
},
{
operator: "eq",
@@ -1900,6 +1930,7 @@ export const secretV2BridgeServiceFactory = ({
orgId: actorOrgId,
folderCommitService,
tx,
commitChanges,
inputSecrets: secretsToUpdate.map((el) => {
const originalSecret = secretsToUpdateInDBGroupedByKey[el.secretKey][0];
const encryptedValue =
@@ -1977,7 +2008,13 @@ export const secretV2BridgeServiceFactory = ({
updatedSecrets.push(...bulkInsertedSecrets.map((el) => ({ ...el, secretPath: folder.path })));
}
}
});
return updatedSecrets;
};
const updatedSecrets = providedTx
? await executeBulkUpdate(providedTx)
: await secretDAL.transaction(executeBulkUpdate);
await secretDAL.invalidateSecretCacheByProjectId(projectId);
await Promise.allSettled(folders.map((el) => (el?.id ? snapshotService.performSnapshot(el.id) : undefined)));
@@ -2034,14 +2071,17 @@ export const secretV2BridgeServiceFactory = ({
actor,
actorId,
actorAuthMethod,
actorOrgId
}: TDeleteManySecretDTO) => {
actorOrgId,
tx: providedTx,
commitChanges
}: TDeleteManySecretDTO & { tx?: Knex; commitChanges?: TCommitResourceChangeDTO[] }) => {
const { permission } = await permissionService.getProjectPermission({
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId
actorOrgId,
actionProjectType: ActionProjectType.SecretManager
});
const folder = await folderDAL.findBySecretPath(projectId, environment, secretPath);
@@ -2094,24 +2134,29 @@ export const secretV2BridgeServiceFactory = ({
);
});
const executeBulkDelete = async (tx: Knex) => {
return fnSecretBulkDelete({
secretDAL,
secretQueueService,
folderCommitService,
secretVersionDAL,
inputSecrets: inputSecrets.map(({ type, secretKey }) => ({
secretKey,
type: type || SecretType.Shared
})),
projectId,
folderId,
actorId,
actorType: actor,
commitChanges,
tx
});
};
try {
const secretsDeleted = await secretDAL.transaction(async (tx) =>
fnSecretBulkDelete({
secretDAL,
secretQueueService,
folderCommitService,
secretVersionDAL,
inputSecrets: inputSecrets.map(({ type, secretKey }) => ({
secretKey,
type: type || SecretType.Shared
})),
projectId,
folderId,
actorId,
actorType: actor,
tx
})
);
const secretsDeleted = providedTx
? await executeBulkDelete(providedTx)
: await secretDAL.transaction(executeBulkDelete);
await secretDAL.invalidateSecretCacheByProjectId(projectId);
await snapshotService.performSnapshot(folderId);
@@ -2197,7 +2242,8 @@ export const secretV2BridgeServiceFactory = ({
actorId,
projectId: folder.projectId,
actorAuthMethod,
actorOrgId
actorOrgId,
actionProjectType: ActionProjectType.SecretManager
});
const canRead =
@@ -2262,7 +2308,8 @@ export const secretV2BridgeServiceFactory = ({
actorId,
projectId,
actorAuthMethod,
actorOrgId
actorOrgId,
actionProjectType: ActionProjectType.SecretManager
});
if (!hasRole(ProjectMembershipRole.Admin))
@@ -2309,7 +2356,8 @@ export const secretV2BridgeServiceFactory = ({
actorId,
projectId,
actorAuthMethod,
actorOrgId
actorOrgId,
actionProjectType: ActionProjectType.SecretManager
});
const sourceFolder = await folderDAL.findBySecretPath(projectId, sourceEnvironment, sourceSecretPath);
@@ -2693,7 +2741,8 @@ export const secretV2BridgeServiceFactory = ({
actorId,
projectId,
actorAuthMethod,
actorOrgId
actorOrgId,
actionProjectType: ActionProjectType.SecretManager
});
throwIfMissingSecretReadValueOrDescribePermission(permission, ProjectPermissionSecretActions.DescribeSecret, {
@@ -2786,7 +2835,8 @@ export const secretV2BridgeServiceFactory = ({
actorId,
projectId,
actorAuthMethod,
actorOrgId
actorOrgId,
actionProjectType: ActionProjectType.SecretManager
});
throwIfMissingSecretReadValueOrDescribePermission(permission, ProjectPermissionSecretActions.DescribeSecret, {
environment,
@@ -2910,7 +2960,8 @@ export const secretV2BridgeServiceFactory = ({
actorId,
projectId,
actorAuthMethod,
actorOrgId
actorOrgId,
actionProjectType: ActionProjectType.SecretManager
});
const canRead =