fix: view secret value permission (requested changes)

This commit is contained in:
Daniel Hougaard
2025-03-05 22:47:40 +04:00
parent 711cc438f6
commit 77e1ccc8d7
24 changed files with 262 additions and 226 deletions
@@ -31,7 +31,7 @@ export type TImportDataIntoInfisicalDTO = {
projectEnvDAL: Pick<TProjectEnvDALFactory, "find" | "findLastEnvPosition" | "create" | "findOne">;
kmsService: Pick<TKmsServiceFactory, "createCipherPairWithDataKey">;
secretDAL: Pick<TSecretV2BridgeDALFactory, "insertMany" | "upsertSecretReferences" | "findBySecretKeys">;
secretDAL: Pick<TSecretV2BridgeDALFactory, "insertMany" | "upsertSecretReferences" | "findBySecretKeys" | "find">;
secretVersionDAL: Pick<TSecretVersionV2DALFactory, "insertMany" | "create">;
secretTagDAL: Pick<TSecretTagDALFactory, "saveTagsToSecretV2" | "create" | "find">;
secretVersionTagDAL: Pick<TSecretVersionV2TagDALFactory, "insertMany" | "create">;
@@ -27,7 +27,7 @@ export type TExternalMigrationQueueFactoryDep = {
projectEnvDAL: Pick<TProjectEnvDALFactory, "find" | "findLastEnvPosition" | "create" | "findOne">;
kmsService: Pick<TKmsServiceFactory, "createCipherPairWithDataKey">;
secretDAL: Pick<TSecretV2BridgeDALFactory, "insertMany" | "upsertSecretReferences" | "findBySecretKeys">;
secretDAL: Pick<TSecretV2BridgeDALFactory, "insertMany" | "upsertSecretReferences" | "findBySecretKeys" | "find">;
secretVersionDAL: Pick<TSecretVersionV2DALFactory, "insertMany" | "create">;
secretTagDAL: Pick<TSecretTagDALFactory, "saveTagsToSecretV2" | "create" | "find">;
secretVersionTagDAL: Pick<TSecretVersionV2TagDALFactory, "insertMany" | "create">;
@@ -68,7 +68,8 @@ const getIntegrationSecretsV2 = async (
secretDAL: secretV2BridgeDAL,
secretImportDAL,
secretImports,
hasSecretAccess: () => true
hasSecretAccess: () => true,
viewSecretValue: true
});
for (let i = importedSecrets.length - 1; i >= 0; i -= 1) {
@@ -6,6 +6,7 @@ import { TSecretDALFactory } from "../secret/secret-dal";
import { TSecretFolderDALFactory } from "../secret-folder/secret-folder-dal";
import { TSecretV2BridgeDALFactory } from "../secret-v2-bridge/secret-v2-bridge-dal";
import { TSecretImportDALFactory } from "./secret-import-dal";
import { INFISICAL_SECRET_VALUE_HIDDEN_MASK } from "../secret/secret-fns";
type TSecretImportSecrets = {
secretPath: string;
@@ -39,6 +40,7 @@ type TSecretImportSecretsV2 = {
// akhilmhdh: yes i know you can put ?.
// But for somereason ts consider ? and undefined explicit as different just ts things
secretValue: string;
secretValueHidden: boolean;
secretComment: string;
secretMetadata?: ResourceMetadataDTO;
})[];
@@ -150,12 +152,14 @@ export const fnSecretsV2FromImports = async ({
secretImportDAL,
decryptor,
expandSecretReferences,
hasSecretAccess
hasSecretAccess,
viewSecretValue
}: {
secretImports: (Omit<TSecretImports, "importEnv"> & {
importEnv: { id: string; slug: string; name: string };
})[];
folderDAL: Pick<TSecretFolderDALFactory, "findByManySecretPath">;
viewSecretValue: boolean;
secretDAL: Pick<TSecretV2BridgeDALFactory, "find">;
secretImportDAL: Pick<TSecretImportDALFactory, "findByFolderIds">;
decryptor: (value?: Buffer | null) => string;
@@ -168,9 +172,11 @@ export const fnSecretsV2FromImports = async ({
hasSecretAccess: (environment: string, secretPath: string, secretName: string, secretTagSlugs: string[]) => boolean;
}) => {
const cyclicDetector = new Set();
const stack: { secretImports: typeof rootSecretImports; depth: number; parentImportedSecrets: TSecretsV2[] }[] = [
{ secretImports: rootSecretImports, depth: 0, parentImportedSecrets: [] }
];
const stack: {
secretImports: typeof rootSecretImports;
depth: number;
parentImportedSecrets: (TSecretsV2 & { secretValueHidden: boolean })[];
}[] = [{ secretImports: rootSecretImports, depth: 0, parentImportedSecrets: [] }];
const processedImports: TSecretImportSecretsV2[] = [];
@@ -229,7 +235,8 @@ export const fnSecretsV2FromImports = async ({
.map((item) => ({
...item,
secretKey: item.key,
secretValue: decryptor(item.encryptedValue),
secretValue: viewSecretValue ? decryptor(item.encryptedValue) : INFISICAL_SECRET_VALUE_HIDDEN_MASK,
secretValueHidden: !viewSecretValue,
secretComment: decryptor(item.encryptedComment),
environment: importEnv.slug,
workspace: "", // This field should not be used, it's only here to keep the older Python SDK versions backwards compatible with the new Postgres backend.
@@ -267,6 +274,8 @@ export const fnSecretsV2FromImports = async ({
processedImport.secrets = unique(processedImport.secrets, (i) => i.key);
return Promise.allSettled(
processedImport.secrets.map(async (decryptedSecret, index) => {
if (decryptedSecret.secretValueHidden) return;
const expandedSecretValue = await expandSecretReferences({
value: decryptedSecret.secretValue,
secretPath: processedImport.secretPath,
@@ -94,7 +94,7 @@ export const secretImportServiceFactory = ({
// check if user has permission to import from target path
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionSecretActions.ReadValue,
ProjectPermissionSecretActions.DescribeSecret,
subject(ProjectPermissionSub.Secrets, {
environment: data.environment,
secretPath: data.path
@@ -406,7 +406,7 @@ export const secretImportServiceFactory = ({
// check if user has permission to import from target path
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionSecretActions.ReadValue,
ProjectPermissionSecretActions.DescribeSecret,
subject(ProjectPermissionSub.Secrets, {
environment: secretImportDoc.importEnv.slug,
secretPath: secretImportDoc.importPath
@@ -646,6 +646,7 @@ export const secretImportServiceFactory = ({
const importedSecrets = await fnSecretsV2FromImports({
secretImports,
folderDAL,
viewSecretValue: true,
secretDAL: secretV2BridgeDAL,
secretImportDAL,
decryptor: (value) => (value ? secretManagerDecryptor({ cipherTextBlob: value }).toString() : ""),
@@ -249,7 +249,8 @@ export const secretSyncQueueFactory = ({
expandSecretReferences,
secretImportDAL,
secretImports,
hasSecretAccess: () => true
hasSecretAccess: () => true,
viewSecretValue: true
});
for (let i = importedSecrets.length - 1; i >= 0; i -= 1) {
@@ -148,7 +148,16 @@ export const fnSecretBulkInsert = async ({
await secretVersionTagDAL.insertMany(newSecretVersionTags, tx);
}
return newSecrets.map((secret) => ({ ...secret, _id: secret.id }));
const secretsWithTags = await secretDAL.find(
{
$in: {
[`${TableName.SecretV2}.id` as "id"]: newSecrets.map((s) => s.id)
}
},
{ tx }
);
return secretsWithTags.map((secret) => ({ ...secret, _id: secret.id }));
};
export const fnSecretBulkUpdate = async ({
@@ -286,7 +295,15 @@ export const fnSecretBulkUpdate = async ({
tx
);
return newSecrets.map((secret) => ({ ...secret, _id: secret.id }));
const secretsWithTags = await secretDAL.find(
{
$in: {
[`${TableName.SecretV2}.id` as "id"]: newSecrets.map((s) => s.id)
}
},
{ tx }
);
return secretsWithTags.map((secret) => ({ ...secret, _id: secret.id }));
};
export const fnSecretBulkDelete = async ({
@@ -627,7 +644,7 @@ export const reshapeBridgeSecret = (
}[];
secretMetadata?: ResourceMetadataDTO;
},
secretValueHidden?: boolean
secretValueHidden: boolean
) => ({
secretKey: secret.key,
secretPath,
@@ -323,11 +323,17 @@ export const secretV2BridgeServiceFactory = ({
});
}
return reshapeBridgeSecret(projectId, environment, secretPath, {
...secret,
value: inputSecret.secretValue,
comment: inputSecret.secretComment || ""
});
return reshapeBridgeSecret(
projectId,
environment,
secretPath,
{
...secret,
value: inputSecret.secretValue,
comment: inputSecret.secretComment || ""
},
false
);
};
const updateSecret = async ({
@@ -407,9 +413,9 @@ export const secretV2BridgeServiceFactory = ({
// validate tags
// fetch all tags and if not same count throw error meaning one was invalid tags
const tags = inputSecret.tagIds ? await secretTagDAL.find({ projectId, $in: { id: inputSecret.tagIds } }) : [];
if ((inputSecret.tagIds || []).length !== tags.length)
throw new NotFoundError({ message: `Tag not found. Found ${tags.map((el) => el.slug).join(",")}` });
const newTags = inputSecret.tagIds ? await secretTagDAL.find({ projectId, $in: { id: inputSecret.tagIds } }) : [];
if ((inputSecret.tagIds || []).length !== newTags.length)
throw new NotFoundError({ message: `Tag not found. Found ${newTags.map((el) => el.slug).join(",")}` });
// now check with new ids
ForbiddenError.from(permission).throwUnlessCan(
@@ -418,7 +424,7 @@ export const secretV2BridgeServiceFactory = ({
environment,
secretPath,
secretName: inputSecret.secretName,
secretTags: tags?.map((el) => el.slug)
secretTags: newTags?.map((el) => el.slug)
})
);
@@ -435,7 +441,7 @@ export const secretV2BridgeServiceFactory = ({
environment,
secretPath,
secretName: inputSecret.newSecretName,
secretTags: tags?.map((el) => el.slug)
secretTags: newTags?.map((el) => el.slug)
})
);
}
@@ -513,13 +519,14 @@ export const secretV2BridgeServiceFactory = ({
});
}
const tagsToCheck = newTags?.length ? newTags : secret.tags;
const secretValueHidden = !permission.can(
ProjectPermissionSecretActions.ReadValue,
subject(ProjectPermissionSub.Secrets, {
environment,
secretPath,
secretName: inputSecret.secretName, // ! Note(Daniel): We are checking for the EXISTING secret name, not the new secret name.
secretTags: tags?.map((el) => el.slug) // ! Note(Daniel): Same here
secretName: inputSecret.secretName,
secretTags: tagsToCheck.length ? tagsToCheck.map((el) => el.slug) : undefined
})
);
@@ -738,7 +745,13 @@ export const secretV2BridgeServiceFactory = ({
};
const getSecretsByFolderMappings = async (
{ projectId, userId, filters, folderMappings, filterByAction }: TGetSecretsRawByFolderMappingsDTO,
{
projectId,
userId,
filters,
folderMappings,
filterByAction = ProjectPermissionSecretActions.ReadValue
}: TGetSecretsRawByFolderMappingsDTO,
projectPermission: Awaited<ReturnType<typeof permissionService.getProjectPermission>>["permission"]
) => {
const groupedFolderMappings = groupBy(folderMappings, (folderMapping) => folderMapping.folderId);
@@ -755,13 +768,10 @@ export const secretV2BridgeServiceFactory = ({
projectId
});
// eslint-disable-next-line no-param-reassign
if (!filterByAction) filterByAction = ProjectPermissionSecretActions.ReadValue;
const decryptedSecrets = secrets
.filter((el) =>
projectPermission.can(
filterByAction as ProjectPermissionSecretActions, // ? Typescript assumes that filterByAction may be undefined, which is not true, so we are casting it to ProjectPermissionSecretActions
filterByAction,
subject(ProjectPermissionSub.Secrets, {
environment: groupedFolderMappings[el.folderId][0].environment,
secretPath: groupedFolderMappings[el.folderId][0].path,
@@ -870,6 +880,7 @@ export const secretV2BridgeServiceFactory = ({
includeImports,
recursive,
expandSecretReferences: shouldExpandSecretReferences,
throwOnMissingReadValuePermission = true,
...params
}: TGetSecretsDTO) => {
const { permission } = await permissionService.getProjectPermission({
@@ -927,19 +938,7 @@ export const secretV2BridgeServiceFactory = ({
const decryptedSecrets = secrets
.filter((el) => {
if (viewSecretValue) {
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionSecretActions.ReadValue,
subject(ProjectPermissionSub.Secrets, {
environment,
secretPath: groupedPaths[el.folderId][0].path,
secretName: el.key,
secretTags: el.tags.map((i) => i.slug)
})
);
}
return permission.can(
const canDescribeSecret = permission.can(
ProjectPermissionSecretActions.DescribeSecret,
subject(ProjectPermissionSub.Secrets, {
environment,
@@ -948,6 +947,43 @@ export const secretV2BridgeServiceFactory = ({
secretTags: el.tags.map((i) => i.slug)
})
);
if (!canDescribeSecret) {
return false;
}
if (viewSecretValue) {
// Recursive secret, should be filtered out
if (groupedPaths[el.folderId][0].path !== path) {
const canReadRecursiveSecretValue = permission.can(
ProjectPermissionSecretActions.ReadValue,
subject(ProjectPermissionSub.Secrets, {
environment,
secretPath: groupedPaths[el.folderId][0].path,
secretName: el.key,
secretTags: el.tags.map((i) => i.slug)
})
);
if (!canReadRecursiveSecretValue) {
return false;
}
}
if (throwOnMissingReadValuePermission) {
ForbiddenError.from(permission).throwUnlessCan(
ProjectPermissionSecretActions.ReadValue,
subject(ProjectPermissionSub.Secrets, {
environment,
secretPath: groupedPaths[el.folderId][0].path,
secretName: el.key,
secretTags: el.tags.map((i) => i.slug)
})
);
}
}
return canDescribeSecret;
})
.map((secret) => {
const isPersonalSecret = secret.userId === actorId && secret.type === SecretType.Personal;
@@ -1027,6 +1063,7 @@ export const secretV2BridgeServiceFactory = ({
const secretImports = await secretImportDAL.findByFolderIds(paths.map((p) => p.folderId));
const allowedImports = secretImports.filter(({ isReplication }) => !isReplication);
const importedSecrets = await fnSecretsV2FromImports({
viewSecretValue,
secretImports: allowedImports,
secretDAL,
folderDAL,
@@ -1174,6 +1211,7 @@ export const secretV2BridgeServiceFactory = ({
const secretImports = await secretImportDAL.find({ folderId, isReplication: false });
const importedSecrets = await fnSecretsV2FromImports({
secretImports,
viewSecretValue,
secretDAL,
folderDAL,
secretImportDAL,
@@ -1207,11 +1245,17 @@ export const secretV2BridgeServiceFactory = ({
for (let j = 0; j < importedSecrets[i].secrets.length; j += 1) {
const importedSecret = importedSecrets[i].secrets[j];
if (secretName === importedSecret.key) {
return reshapeBridgeSecret(projectId, importedSecrets[i].environment, importedSecrets[i].secretPath, {
...importedSecret,
value: importedSecret.secretValue || "",
comment: importedSecret.secretComment || ""
});
return reshapeBridgeSecret(
projectId,
importedSecrets[i].environment,
importedSecrets[i].secretPath,
{
...importedSecret,
value: importedSecret.secretValue || "",
comment: importedSecret.secretComment || ""
},
importedSecret.secretValueHidden
);
}
}
}
@@ -1365,8 +1409,8 @@ export const secretV2BridgeServiceFactory = ({
const { encryptor: secretManagerEncryptor, decryptor: secretManagerDecryptor } =
await kmsService.createCipherPairWithDataKey({ type: KmsDataKey.SecretManager, projectId });
const newSecrets = await secretDAL.transaction(async (tx) => {
const createdSecrets = await fnSecretBulkInsert({
const newSecrets = await secretDAL.transaction(async (tx) =>
fnSecretBulkInsert({
inputSecrets: inputSecrets.map((el) => {
const references = secretReferencesGroupByInputSecretKey[el.secretKey]?.nestedReferences;
@@ -1395,19 +1439,8 @@ export const secretV2BridgeServiceFactory = ({
secretTagDAL,
secretVersionTagDAL,
tx
});
const secs = await secretDAL.find(
{
$in: {
[`${TableName.SecretV2}.id` as "id"]: createdSecrets.map((el) => el.id)
}
},
{ tx }
);
return secs;
});
})
);
await snapshotService.performSnapshot(folderId);
await secretQueueService.syncSecrets({
@@ -1656,7 +1689,7 @@ export const secretV2BridgeServiceFactory = ({
});
await $validateSecretReferences(projectId, permission, secretReferences, tx);
const bulkUpdatedSecretsRes = await fnSecretBulkUpdate({
const bulkUpdatedSecrets = await fnSecretBulkUpdate({
folderId,
orgId: actorOrgId,
tx,
@@ -1694,20 +1727,9 @@ export const secretV2BridgeServiceFactory = ({
resourceMetadataDAL
});
const bulkUpdatedSecrets = await secretDAL.find(
{
$in: {
[`${TableName.SecretV2}.id` as "id"]: bulkUpdatedSecretsRes.map((el) => el.id)
}
},
{
tx
}
);
updatedSecrets.push(...bulkUpdatedSecrets.map((el) => ({ ...el, secretPath: folder.path })));
if (updateMode === SecretUpdateMode.Upsert) {
const bulkInsertedSecretsRes = await fnSecretBulkInsert({
const bulkInsertedSecrets = await fnSecretBulkInsert({
inputSecrets: secretsToCreate.map((el) => {
const references = secretReferencesGroupByInputSecretKey[el.secretKey]?.nestedReferences;
@@ -1738,15 +1760,6 @@ export const secretV2BridgeServiceFactory = ({
tx
});
const bulkInsertedSecrets = await secretDAL.find(
{
$in: {
[`${TableName.SecretV2}.id` as "id"]: bulkInsertedSecretsRes.map((el) => el.id)
}
},
{ tx }
);
updatedSecrets.push(...bulkInsertedSecrets.map((el) => ({ ...el, secretPath: folder.path })));
}
}
@@ -1957,11 +1970,17 @@ export const secretV2BridgeServiceFactory = ({
const secretVersions = await secretVersionDAL.find({ secretId }, { offset, limit, sort: [["createdAt", "desc"]] });
return secretVersions.map((el) =>
reshapeBridgeSecret(folder.projectId, folder.environment.envSlug, "/", {
...el,
value: el.encryptedValue ? secretManagerDecryptor({ cipherTextBlob: el.encryptedValue }).toString() : "",
comment: el.encryptedComment ? secretManagerDecryptor({ cipherTextBlob: el.encryptedComment }).toString() : ""
})
reshapeBridgeSecret(
folder.projectId,
folder.environment.envSlug,
"/",
{
...el,
value: el.encryptedValue ? secretManagerDecryptor({ cipherTextBlob: el.encryptedValue }).toString() : "",
comment: el.encryptedComment ? secretManagerDecryptor({ cipherTextBlob: el.encryptedComment }).toString() : ""
},
false
)
);
};
@@ -38,6 +38,7 @@ export type TGetSecretsDTO = {
recursive?: boolean;
tagSlugs?: string[];
viewSecretValue: boolean;
throwOnMissingReadValuePermission?: boolean;
metadataFilter?: {
key?: string;
value?: string;
@@ -50,6 +51,11 @@ export type TGetSecretsDTO = {
keys?: string[];
} & TProjectPermission;
export type TGetSecretsMissingReadValuePermissionDTO = Omit<
TGetSecretsDTO,
"viewSecretValue" | "recursive" | "expandSecretReferences"
>;
export type TGetASecretDTO = {
secretName: string;
path: string;
@@ -167,7 +173,7 @@ export type TFnSecretBulkInsert = {
}
>;
resourceMetadataDAL: Pick<TResourceMetadataDALFactory, "insertMany">;
secretDAL: Pick<TSecretV2BridgeDALFactory, "insertMany" | "upsertSecretReferences">;
secretDAL: Pick<TSecretV2BridgeDALFactory, "insertMany" | "upsertSecretReferences" | "find">;
secretVersionDAL: Pick<TSecretVersionV2DALFactory, "insertMany">;
secretTagDAL: Pick<TSecretTagDALFactory, "saveTagsToSecretV2" | "find">;
secretVersionTagDAL: Pick<TSecretVersionV2TagDALFactory, "insertMany">;
@@ -191,7 +197,7 @@ export type TFnSecretBulkUpdate = {
data: TRequireReferenceIfValue & { tags?: string[]; secretMetadata?: ResourceMetadataDTO };
}[];
resourceMetadataDAL: Pick<TResourceMetadataDALFactory, "insertMany" | "delete">;
secretDAL: Pick<TSecretV2BridgeDALFactory, "bulkUpdate" | "upsertSecretReferences">;
secretDAL: Pick<TSecretV2BridgeDALFactory, "bulkUpdate" | "upsertSecretReferences" | "find">;
secretVersionDAL: Pick<TSecretVersionV2DALFactory, "insertMany">;
secretTagDAL: Pick<TSecretTagDALFactory, "saveTagsToSecretV2" | "deleteTagsToSecretV2" | "find">;
secretVersionTagDAL: Pick<TSecretVersionV2TagDALFactory, "insertMany">;
+2 -1
View File
@@ -402,7 +402,8 @@ export const secretQueueFactory = ({
expandSecretReferences,
secretImportDAL,
secretImports,
hasSecretAccess: () => true
hasSecretAccess: () => true,
viewSecretValue: true
});
for (let i = importedSecrets.length - 1; i >= 0; i -= 1) {
+16 -2
View File
@@ -667,7 +667,15 @@ export const secretServiceFactory = ({
environment,
secretPath: groupedPaths[secret.folderId][0].path
})),
imports: importedSecrets
imports: importedSecrets.map((el) => {
return {
...el,
secrets: el.secrets.map((secret) => ({
...secret,
secretValueHidden: false
}))
};
})
};
}
@@ -974,7 +982,7 @@ export const secretServiceFactory = ({
});
const secretValueHidden = !permission.can(
ProjectPermissionSecretActions.Edit,
ProjectPermissionSecretActions.ReadValue,
subject(ProjectPermissionSub.Secrets, { environment, secretPath: path })
);
@@ -1299,6 +1307,7 @@ export const secretServiceFactory = ({
expandSecretReferences,
recursive,
tagSlugs = [],
throwOnMissingReadValuePermission = true,
...paramsV2
}: TGetSecretsRawDTO) => {
const { botKey, shouldUseSecretV2Bridge } = await projectBotService.getBotKey(projectId);
@@ -1310,6 +1319,7 @@ export const secretServiceFactory = ({
actor,
actorOrgId,
viewSecretValue,
throwOnMissingReadValuePermission,
environment,
path,
recursive,
@@ -1318,6 +1328,7 @@ export const secretServiceFactory = ({
tagSlugs,
...paramsV2
});
return { secrets, imports };
}
@@ -1370,6 +1381,7 @@ export const secretServiceFactory = ({
const importedEntries = decryptedImportSecrets.reduce(
(
accum: {
secretValueHidden: boolean;
secretKey: string;
secretPath: string;
workspace: string;
@@ -1413,6 +1425,7 @@ export const secretServiceFactory = ({
Object.keys(secretsGroupByPath).map((groupedPath) =>
Promise.allSettled(
secretsGroupByPath[groupedPath].map(async (decryptedSecret, index) => {
if (decryptedSecret.secretValueHidden) return;
const expandedSecretValue = await expandSecret({
value: decryptedSecret.secretValue,
secretPath: groupedPath,
@@ -1429,6 +1442,7 @@ export const secretServiceFactory = ({
processedImports.map((processedImport) =>
Promise.allSettled(
processedImport.secrets.map(async (decryptedSecret, index) => {
if (decryptedSecret.secretValueHidden) return;
const expandedSecretValue = await expandSecret({
value: decryptedSecret.secretValue,
secretPath: path,
+3 -2
View File
@@ -181,6 +181,7 @@ export type TGetSecretsRawDTO = {
path: string;
environment: string;
viewSecretValue: boolean;
throwOnMissingReadValuePermission?: boolean;
includeImports?: boolean;
recursive?: boolean;
tagSlugs?: string[];
@@ -411,7 +412,7 @@ export type TCreateManySecretsRawFnFactory = {
kmsService: Pick<TKmsServiceFactory, "createCipherPairWithDataKey">;
secretV2BridgeDAL: Pick<
TSecretV2BridgeDALFactory,
"insertMany" | "upsertSecretReferences" | "findBySecretKeys" | "bulkUpdate" | "deleteMany"
"insertMany" | "upsertSecretReferences" | "findBySecretKeys" | "bulkUpdate" | "deleteMany" | "find"
>;
secretVersionV2BridgeDAL: Pick<TSecretVersionV2DALFactory, "insertMany" | "findLatestVersionMany">;
secretVersionTagV2BridgeDAL: Pick<TSecretVersionV2TagDALFactory, "insertMany">;
@@ -448,7 +449,7 @@ export type TUpdateManySecretsRawFnFactory = {
kmsService: Pick<TKmsServiceFactory, "createCipherPairWithDataKey">;
secretV2BridgeDAL: Pick<
TSecretV2BridgeDALFactory,
"insertMany" | "upsertSecretReferences" | "findBySecretKeys" | "bulkUpdate" | "deleteMany"
"insertMany" | "upsertSecretReferences" | "findBySecretKeys" | "bulkUpdate" | "deleteMany" | "find"
>;
secretVersionV2BridgeDAL: Pick<TSecretVersionV2DALFactory, "insertMany" | "findLatestVersionMany">;
secretVersionTagV2BridgeDAL: Pick<TSecretVersionV2TagDALFactory, "insertMany">;