feat: completed basic CRUD

This commit is contained in:
Sheen Capadngan
2024-12-19 17:47:39 +08:00
parent e9358cd1d8
commit 8c98565715
15 changed files with 157 additions and 22 deletions
@@ -92,7 +92,7 @@ type TSecretApprovalRequestServiceFactoryDep = {
secretBlindIndexDAL: Pick<TSecretBlindIndexDALFactory, "findOne">; secretBlindIndexDAL: Pick<TSecretBlindIndexDALFactory, "findOne">;
snapshotService: Pick<TSecretSnapshotServiceFactory, "performSnapshot">; snapshotService: Pick<TSecretSnapshotServiceFactory, "performSnapshot">;
secretVersionDAL: Pick<TSecretVersionDALFactory, "findLatestVersionMany" | "insertMany">; secretVersionDAL: Pick<TSecretVersionDALFactory, "findLatestVersionMany" | "insertMany">;
resourceMetadataDAL: Pick<TResourceMetadataDALFactory, "insertMany">; resourceMetadataDAL: Pick<TResourceMetadataDALFactory, "insertMany" | "delete">;
secretVersionTagDAL: Pick<TSecretVersionTagDALFactory, "insertMany">; secretVersionTagDAL: Pick<TSecretVersionTagDALFactory, "insertMany">;
smtpService: Pick<TSmtpService, "sendMail">; smtpService: Pick<TSmtpService, "sendMail">;
userDAL: Pick<TUserDALFactory, "find" | "findOne" | "findById">; userDAL: Pick<TUserDALFactory, "find" | "findOne" | "findById">;
@@ -573,6 +573,7 @@ export const secretApprovalRequestServiceFactory = ({
const updatedSecrets = secretUpdationCommits.length const updatedSecrets = secretUpdationCommits.length
? await fnSecretV2BridgeBulkUpdate({ ? await fnSecretV2BridgeBulkUpdate({
folderId, folderId,
orgId: actorOrgId,
tx, tx,
inputSecrets: secretUpdationCommits.map((el) => { inputSecrets: secretUpdationCommits.map((el) => {
const encryptedValue = const encryptedValue =
@@ -604,7 +605,8 @@ export const secretApprovalRequestServiceFactory = ({
secretDAL: secretV2BridgeDAL, secretDAL: secretV2BridgeDAL,
secretVersionDAL: secretVersionV2BridgeDAL, secretVersionDAL: secretVersionV2BridgeDAL,
secretTagDAL, secretTagDAL,
secretVersionTagDAL: secretVersionTagV2BridgeDAL secretVersionTagDAL: secretVersionTagV2BridgeDAL,
resourceMetadataDAL
}) })
: []; : [];
const deletedSecret = secretDeletionCommits.length const deletedSecret = secretDeletionCommits.length
@@ -57,7 +57,7 @@ type TSecretReplicationServiceFactoryDep = {
>; >;
secretVersionTagDAL: Pick<TSecretVersionTagDALFactory, "find" | "insertMany">; secretVersionTagDAL: Pick<TSecretVersionTagDALFactory, "find" | "insertMany">;
secretVersionV2TagBridgeDAL: Pick<TSecretVersionV2TagDALFactory, "find" | "insertMany">; secretVersionV2TagBridgeDAL: Pick<TSecretVersionV2TagDALFactory, "find" | "insertMany">;
resourceMetadataDAL: Pick<TResourceMetadataDALFactory, "insertMany">; resourceMetadataDAL: Pick<TResourceMetadataDALFactory, "insertMany" | "delete">;
secretQueueService: Pick<TSecretQueueFactory, "syncSecrets" | "replicateSecrets">; secretQueueService: Pick<TSecretQueueFactory, "syncSecrets" | "replicateSecrets">;
queueService: Pick<TQueueServiceFactory, "start" | "listen" | "queue" | "stopJobById">; queueService: Pick<TQueueServiceFactory, "start" | "listen" | "queue" | "stopJobById">;
secretApprovalPolicyService: Pick<TSecretApprovalPolicyServiceFactory, "getSecretApprovalPolicy">; secretApprovalPolicyService: Pick<TSecretApprovalPolicyServiceFactory, "getSecretApprovalPolicy">;
@@ -433,10 +433,12 @@ export const secretReplicationServiceFactory = ({
} }
if (locallyUpdatedSecrets.length) { if (locallyUpdatedSecrets.length) {
await fnSecretV2BridgeBulkUpdate({ await fnSecretV2BridgeBulkUpdate({
orgId,
folderId: destinationReplicationFolderId, folderId: destinationReplicationFolderId,
secretVersionDAL: secretVersionV2BridgeDAL, secretVersionDAL: secretVersionV2BridgeDAL,
secretDAL: secretV2BridgeDAL, secretDAL: secretV2BridgeDAL,
tx, tx,
resourceMetadataDAL,
secretTagDAL, secretTagDAL,
secretVersionTagDAL: secretVersionV2TagBridgeDAL, secretVersionTagDAL: secretVersionV2TagBridgeDAL,
inputSecrets: locallyUpdatedSecrets.map((doc) => { inputSecrets: locallyUpdatedSecrets.map((doc) => {
+2 -1
View File
@@ -1311,7 +1311,8 @@ export const registerRoutes = async (
folderDAL, folderDAL,
secretDAL: secretV2BridgeDAL, secretDAL: secretV2BridgeDAL,
queueService, queueService,
secretV2BridgeService secretV2BridgeService,
resourceMetadataDAL
}); });
const migrationService = externalMigrationServiceFactory({ const migrationService = externalMigrationServiceFactory({
@@ -17,6 +17,7 @@ import { getUserAgentType } from "@app/server/plugins/audit-log";
import { verifyAuth } from "@app/server/plugins/auth/verify-auth"; import { verifyAuth } from "@app/server/plugins/auth/verify-auth";
import { SanitizedDynamicSecretSchema, secretRawSchema } from "@app/server/routes/sanitizedSchemas"; import { SanitizedDynamicSecretSchema, secretRawSchema } from "@app/server/routes/sanitizedSchemas";
import { AuthMode } from "@app/services/auth/auth-type"; import { AuthMode } from "@app/services/auth/auth-type";
import { ResourceMetadataSchema } from "@app/services/resource-metadata/resource-metadata-schema";
import { SecretsOrderBy } from "@app/services/secret/secret-types"; import { SecretsOrderBy } from "@app/services/secret/secret-types";
import { PostHogEventTypes } from "@app/services/telemetry/telemetry-types"; import { PostHogEventTypes } from "@app/services/telemetry/telemetry-types";
@@ -116,6 +117,7 @@ export const registerDashboardRouter = async (server: FastifyZodProvider) => {
secrets: secretRawSchema secrets: secretRawSchema
.extend({ .extend({
secretPath: z.string().optional(), secretPath: z.string().optional(),
secretMetadata: ResourceMetadataSchema.optional(),
tags: SecretTagsSchema.pick({ tags: SecretTagsSchema.pick({
id: true, id: true,
slug: true, slug: true,
@@ -408,6 +410,7 @@ export const registerDashboardRouter = async (server: FastifyZodProvider) => {
secrets: secretRawSchema secrets: secretRawSchema
.extend({ .extend({
secretPath: z.string().optional(), secretPath: z.string().optional(),
secretMetadata: ResourceMetadataSchema.optional(),
tags: SecretTagsSchema.pick({ tags: SecretTagsSchema.pick({
id: true, id: true,
slug: true, slug: true,
@@ -693,6 +696,7 @@ export const registerDashboardRouter = async (server: FastifyZodProvider) => {
secrets: secretRawSchema secrets: secretRawSchema
.extend({ .extend({
secretPath: z.string().optional(), secretPath: z.string().optional(),
secretMetadata: ResourceMetadataSchema.optional(),
tags: SecretTagsSchema.pick({ tags: SecretTagsSchema.pick({
id: true, id: true,
slug: true, slug: true,
@@ -864,6 +868,7 @@ export const registerDashboardRouter = async (server: FastifyZodProvider) => {
secrets: secretRawSchema secrets: secretRawSchema
.extend({ .extend({
secretPath: z.string().optional(), secretPath: z.string().optional(),
secretMetadata: ResourceMetadataSchema.optional(),
tags: SecretTagsSchema.pick({ tags: SecretTagsSchema.pick({
id: true, id: true,
slug: true, slug: true,
@@ -206,6 +206,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
secrets: secretRawSchema secrets: secretRawSchema
.extend({ .extend({
secretPath: z.string().optional(), secretPath: z.string().optional(),
secretMetadata: ResourceMetadataSchema.optional(),
tags: SecretTagsSchema.pick({ tags: SecretTagsSchema.pick({
id: true, id: true,
slug: true, slug: true,
@@ -349,7 +350,8 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
}) })
.extend({ name: z.string() }) .extend({ name: z.string() })
.array() .array()
.optional() .optional(),
secretMetadata: ResourceMetadataSchema.optional()
}) })
}) })
} }
@@ -561,6 +563,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
type: z.nativeEnum(SecretType).default(SecretType.Shared).describe(RAW_SECRETS.UPDATE.type), type: z.nativeEnum(SecretType).default(SecretType.Shared).describe(RAW_SECRETS.UPDATE.type),
tagIds: z.string().array().optional().describe(RAW_SECRETS.UPDATE.tagIds), tagIds: z.string().array().optional().describe(RAW_SECRETS.UPDATE.tagIds),
metadata: z.record(z.string()).optional(), metadata: z.record(z.string()).optional(),
secretMetadata: ResourceMetadataSchema.optional(),
secretReminderNote: z.string().optional().nullable().describe(RAW_SECRETS.UPDATE.secretReminderNote), secretReminderNote: z.string().optional().nullable().describe(RAW_SECRETS.UPDATE.secretReminderNote),
secretReminderRepeatDays: z secretReminderRepeatDays: z
.number() .number()
@@ -598,8 +601,10 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
secretReminderNote: req.body.secretReminderNote, secretReminderNote: req.body.secretReminderNote,
metadata: req.body.metadata, metadata: req.body.metadata,
newSecretName: req.body.newSecretName, newSecretName: req.body.newSecretName,
secretComment: req.body.secretComment secretComment: req.body.secretComment,
secretMetadata: req.body.secretMetadata
}); });
if (secretOperation.type === SecretProtectionType.Approval) { if (secretOperation.type === SecretProtectionType.Approval) {
return { approval: secretOperation.approval }; return { approval: secretOperation.approval };
} }
@@ -1853,6 +1858,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
secretComment: z.string().trim().optional().default("").describe(RAW_SECRETS.CREATE.secretComment), secretComment: z.string().trim().optional().default("").describe(RAW_SECRETS.CREATE.secretComment),
skipMultilineEncoding: z.boolean().optional().describe(RAW_SECRETS.CREATE.skipMultilineEncoding), skipMultilineEncoding: z.boolean().optional().describe(RAW_SECRETS.CREATE.skipMultilineEncoding),
metadata: z.record(z.string()).optional(), metadata: z.record(z.string()).optional(),
secretMetadata: ResourceMetadataSchema.optional(),
tagIds: z.string().array().optional().describe(RAW_SECRETS.CREATE.tagIds) tagIds: z.string().array().optional().describe(RAW_SECRETS.CREATE.tagIds)
}) })
.array() .array()
@@ -1955,6 +1961,7 @@ export const registerSecretRouter = async (server: FastifyZodProvider) => {
newSecretName: z.string().min(1).optional().describe(RAW_SECRETS.UPDATE.newSecretName), newSecretName: z.string().min(1).optional().describe(RAW_SECRETS.UPDATE.newSecretName),
tagIds: z.string().array().optional().describe(RAW_SECRETS.UPDATE.tagIds), tagIds: z.string().array().optional().describe(RAW_SECRETS.UPDATE.tagIds),
secretReminderNote: z.string().optional().nullable().describe(RAW_SECRETS.UPDATE.secretReminderNote), secretReminderNote: z.string().optional().nullable().describe(RAW_SECRETS.UPDATE.secretReminderNote),
secretMetadata: ResourceMetadataSchema.optional(),
secretReminderRepeatDays: z secretReminderRepeatDays: z
.number() .number()
.optional() .optional()
@@ -8,6 +8,7 @@ import { TProjectDALFactory } from "../project/project-dal";
import { TProjectServiceFactory } from "../project/project-service"; import { TProjectServiceFactory } from "../project/project-service";
import { TProjectEnvDALFactory } from "../project-env/project-env-dal"; import { TProjectEnvDALFactory } from "../project-env/project-env-dal";
import { TProjectEnvServiceFactory } from "../project-env/project-env-service"; import { TProjectEnvServiceFactory } from "../project-env/project-env-service";
import { TResourceMetadataDALFactory } from "../resource-metadata/resource-metadata-dal";
import { TSecretFolderDALFactory } from "../secret-folder/secret-folder-dal"; import { TSecretFolderDALFactory } from "../secret-folder/secret-folder-dal";
import { TSecretTagDALFactory } from "../secret-tag/secret-tag-dal"; import { TSecretTagDALFactory } from "../secret-tag/secret-tag-dal";
import { TSecretV2BridgeDALFactory } from "../secret-v2-bridge/secret-v2-bridge-dal"; import { TSecretV2BridgeDALFactory } from "../secret-v2-bridge/secret-v2-bridge-dal";
@@ -35,6 +36,8 @@ export type TExternalMigrationQueueFactoryDep = {
projectService: Pick<TProjectServiceFactory, "createProject">; projectService: Pick<TProjectServiceFactory, "createProject">;
projectEnvService: Pick<TProjectEnvServiceFactory, "createEnvironment">; projectEnvService: Pick<TProjectEnvServiceFactory, "createEnvironment">;
secretV2BridgeService: Pick<TSecretV2BridgeServiceFactory, "createManySecret">; secretV2BridgeService: Pick<TSecretV2BridgeServiceFactory, "createManySecret">;
resourceMetadataDAL: Pick<TResourceMetadataDALFactory, "insertMany" | "delete">;
}; };
export type TExternalMigrationQueueFactory = ReturnType<typeof externalMigrationQueueFactory>; export type TExternalMigrationQueueFactory = ReturnType<typeof externalMigrationQueueFactory>;
@@ -52,7 +55,8 @@ export const externalMigrationQueueFactory = ({
secretVersionDAL, secretVersionDAL,
secretTagDAL, secretTagDAL,
secretVersionTagDAL, secretVersionTagDAL,
folderDAL folderDAL,
resourceMetadataDAL
}: TExternalMigrationQueueFactoryDep) => { }: TExternalMigrationQueueFactoryDep) => {
const startImport = async (dto: { const startImport = async (dto: {
actorEmail: string; actorEmail: string;
@@ -109,7 +113,8 @@ export const externalMigrationQueueFactory = ({
kmsService, kmsService,
projectService, projectService,
projectEnvService, projectEnvService,
secretV2BridgeService secretV2BridgeService,
resourceMetadataDAL
}); });
if (projectsNotImported.length) { if (projectsNotImported.length) {
@@ -160,6 +160,7 @@ export const secretImportServiceFactory = ({
if (secImport.isReplication && sourceFolder) { if (secImport.isReplication && sourceFolder) {
await secretQueueService.replicateSecrets({ await secretQueueService.replicateSecrets({
secretPath: secImport.importPath, secretPath: secImport.importPath,
orgId: actorOrgId,
projectId, projectId,
environmentSlug: importEnv.slug, environmentSlug: importEnv.slug,
pickOnlyImportIds: [secImport.id], pickOnlyImportIds: [secImport.id],
@@ -169,6 +170,7 @@ export const secretImportServiceFactory = ({
} else { } else {
await secretQueueService.syncSecrets({ await secretQueueService.syncSecrets({
secretPath, secretPath,
orgId: actorOrgId,
projectId, projectId,
environmentSlug: environment, environmentSlug: environment,
actorId, actorId,
@@ -340,6 +342,7 @@ export const secretImportServiceFactory = ({
await secretQueueService.syncSecrets({ await secretQueueService.syncSecrets({
secretPath, secretPath,
orgId: actorOrgId,
projectId, projectId,
environmentSlug: environment, environmentSlug: environment,
actor, actor,
@@ -415,6 +418,7 @@ export const secretImportServiceFactory = ({
if (membership && sourceFolder) { if (membership && sourceFolder) {
await secretQueueService.replicateSecrets({ await secretQueueService.replicateSecrets({
orgId: actorOrgId,
secretPath: secretImportDoc.importPath, secretPath: secretImportDoc.importPath,
projectId, projectId,
environmentSlug: secretImportDoc.importEnv.slug, environmentSlug: secretImportDoc.importEnv.slug,
@@ -221,7 +221,9 @@ export const secretV2BridgeDALFactory = (db: TDbClient) => {
const secs = await (tx || db.replicaNode())(TableName.SecretV2) const secs = await (tx || db.replicaNode())(TableName.SecretV2)
.where({ folderId }) .where({ folderId })
.where((bd) => { .where((bd) => {
void bd.whereNull("userId").orWhere({ userId: userId || null }); void bd
.whereNull(`${TableName.SecretV2}.userId`)
.orWhere({ [`${TableName.SecretV2}.userId` as "userId"]: userId || null });
}) })
.leftJoin( .leftJoin(
TableName.SecretV2JnTag, TableName.SecretV2JnTag,
@@ -233,10 +235,16 @@ export const secretV2BridgeDALFactory = (db: TDbClient) => {
`${TableName.SecretV2JnTag}.${TableName.SecretTag}Id`, `${TableName.SecretV2JnTag}.${TableName.SecretTag}Id`,
`${TableName.SecretTag}.id` `${TableName.SecretTag}.id`
) )
.leftJoin(TableName.ResourceMetadata, `${TableName.SecretV2}.id`, `${TableName.ResourceMetadata}.secretId`)
.select(selectAllTableCols(TableName.SecretV2)) .select(selectAllTableCols(TableName.SecretV2))
.select(db.ref("id").withSchema(TableName.SecretTag).as("tagId")) .select(db.ref("id").withSchema(TableName.SecretTag).as("tagId"))
.select(db.ref("color").withSchema(TableName.SecretTag).as("tagColor")) .select(db.ref("color").withSchema(TableName.SecretTag).as("tagColor"))
.select(db.ref("slug").withSchema(TableName.SecretTag).as("tagSlug")) .select(db.ref("slug").withSchema(TableName.SecretTag).as("tagSlug"))
.select(
db.ref("id").withSchema(TableName.ResourceMetadata).as("metadataId"),
db.ref("key").withSchema(TableName.ResourceMetadata).as("metadataKey"),
db.ref("value").withSchema(TableName.ResourceMetadata).as("metadataValue")
)
.orderBy("id", "asc"); .orderBy("id", "asc");
const data = sqlNestRelationships({ const data = sqlNestRelationships({
@@ -253,6 +261,15 @@ export const secretV2BridgeDALFactory = (db: TDbClient) => {
slug, slug,
name: slug name: slug
}) })
},
{
key: "metadataId",
label: "secretMetadata" as const,
mapper: ({ metadataKey, metadataValue, metadataId }) => ({
id: metadataId,
key: metadataKey,
value: metadataValue
})
} }
] ]
}); });
@@ -367,7 +384,9 @@ export const secretV2BridgeDALFactory = (db: TDbClient) => {
} }
}) })
.where((bd) => { .where((bd) => {
void bd.whereNull(`${TableName.SecretV2}.userId`).orWhere({ userId: userId || null }); void bd
.whereNull(`${TableName.SecretV2}.userId`)
.orWhere({ [`${TableName.SecretV2}.userId` as "userId"]: userId || null });
}) })
.leftJoin( .leftJoin(
TableName.SecretV2JnTag, TableName.SecretV2JnTag,
@@ -379,13 +398,23 @@ export const secretV2BridgeDALFactory = (db: TDbClient) => {
`${TableName.SecretV2JnTag}.${TableName.SecretTag}Id`, `${TableName.SecretV2JnTag}.${TableName.SecretTag}Id`,
`${TableName.SecretTag}.id` `${TableName.SecretTag}.id`
) )
.leftJoin(TableName.ResourceMetadata, `${TableName.SecretV2}.id`, `${TableName.ResourceMetadata}.secretId`)
.select( .select(
selectAllTableCols(TableName.SecretV2), selectAllTableCols(TableName.SecretV2),
db.raw(`DENSE_RANK() OVER (ORDER BY "key" ${filters?.orderDirection ?? OrderByDirection.ASC}) as rank`) db.raw(
`DENSE_RANK() OVER (ORDER BY "${TableName.SecretV2}".key ${
filters?.orderDirection ?? OrderByDirection.ASC
}) as rank`
)
) )
.select(db.ref("id").withSchema(TableName.SecretTag).as("tagId")) .select(db.ref("id").withSchema(TableName.SecretTag).as("tagId"))
.select(db.ref("color").withSchema(TableName.SecretTag).as("tagColor")) .select(db.ref("color").withSchema(TableName.SecretTag).as("tagColor"))
.select(db.ref("slug").withSchema(TableName.SecretTag).as("tagSlug")) .select(db.ref("slug").withSchema(TableName.SecretTag).as("tagSlug"))
.select(
db.ref("id").withSchema(TableName.ResourceMetadata).as("metadataId"),
db.ref("key").withSchema(TableName.ResourceMetadata).as("metadataKey"),
db.ref("value").withSchema(TableName.ResourceMetadata).as("metadataValue")
)
.where((bd) => { .where((bd) => {
const slugs = filters?.tagSlugs?.filter(Boolean); const slugs = filters?.tagSlugs?.filter(Boolean);
if (slugs && slugs.length > 0) { if (slugs && slugs.length > 0) {
@@ -425,6 +454,15 @@ export const secretV2BridgeDALFactory = (db: TDbClient) => {
slug, slug,
name: slug name: slug
}) })
},
{
key: "metadataId",
label: "secretMetadata" as const,
mapper: ({ metadataKey, metadataValue, metadataId }) => ({
id: metadataId,
key: metadataKey,
value: metadataValue
})
} }
] ]
}); });
@@ -545,10 +583,17 @@ export const secretV2BridgeDALFactory = (db: TDbClient) => {
`${TableName.SecretV2JnTag}.${TableName.SecretTag}Id`, `${TableName.SecretV2JnTag}.${TableName.SecretTag}Id`,
`${TableName.SecretTag}.id` `${TableName.SecretTag}.id`
) )
.leftJoin(TableName.ResourceMetadata, `${TableName.SecretV2}.id`, `${TableName.ResourceMetadata}.secretId`)
.select(selectAllTableCols(TableName.SecretV2)) .select(selectAllTableCols(TableName.SecretV2))
.select(db.ref("id").withSchema(TableName.SecretTag).as("tagId")) .select(db.ref("id").withSchema(TableName.SecretTag).as("tagId"))
.select(db.ref("color").withSchema(TableName.SecretTag).as("tagColor")) .select(db.ref("color").withSchema(TableName.SecretTag).as("tagColor"))
.select(db.ref("slug").withSchema(TableName.SecretTag).as("tagSlug")); .select(db.ref("slug").withSchema(TableName.SecretTag).as("tagSlug"))
.select(
db.ref("id").withSchema(TableName.ResourceMetadata).as("metadataId"),
db.ref("key").withSchema(TableName.ResourceMetadata).as("metadataKey"),
db.ref("value").withSchema(TableName.ResourceMetadata).as("metadataValue")
);
const docs = sqlNestRelationships({ const docs = sqlNestRelationships({
data: rawDocs, data: rawDocs,
key: "id", key: "id",
@@ -563,6 +608,15 @@ export const secretV2BridgeDALFactory = (db: TDbClient) => {
slug, slug,
name: slug name: slug
}) })
},
{
key: "metadataId",
label: "secretMetadata" as const,
mapper: ({ metadataKey, metadataValue, metadataId }) => ({
id: metadataId,
key: metadataKey,
value: metadataValue
})
} }
] ]
}); });
@@ -6,6 +6,7 @@ import { groupBy } from "@app/lib/fn";
import { logger } from "@app/lib/logger"; import { logger } from "@app/lib/logger";
import { TProjectEnvDALFactory } from "../project-env/project-env-dal"; import { TProjectEnvDALFactory } from "../project-env/project-env-dal";
import { ResourceMetadataDTO } from "../resource-metadata/resource-metadata-schema";
import { TSecretFolderDALFactory } from "../secret-folder/secret-folder-dal"; import { TSecretFolderDALFactory } from "../secret-folder/secret-folder-dal";
import { TSecretV2BridgeDALFactory } from "./secret-v2-bridge-dal"; import { TSecretV2BridgeDALFactory } from "./secret-v2-bridge-dal";
import { TFnSecretBulkDelete, TFnSecretBulkInsert, TFnSecretBulkUpdate } from "./secret-v2-bridge-types"; import { TFnSecretBulkDelete, TFnSecretBulkInsert, TFnSecretBulkUpdate } from "./secret-v2-bridge-types";
@@ -151,10 +152,12 @@ export const fnSecretBulkUpdate = async ({
tx, tx,
inputSecrets, inputSecrets,
folderId, folderId,
orgId,
secretDAL, secretDAL,
secretVersionDAL, secretVersionDAL,
secretTagDAL, secretTagDAL,
secretVersionTagDAL secretVersionTagDAL,
resourceMetadataDAL
}: TFnSecretBulkUpdate) => { }: TFnSecretBulkUpdate) => {
const sanitizedInputSecrets = inputSecrets.map( const sanitizedInputSecrets = inputSecrets.map(
({ ({
@@ -252,6 +255,34 @@ export const fnSecretBulkUpdate = async ({
} }
} }
const inputSecretIdsWithMetadata = inputSecrets
.filter((sec) => Boolean(sec.data.secretMetadata))
.map((sec) => sec.filter.id);
await resourceMetadataDAL.delete(
{
$in: {
secretId: inputSecretIdsWithMetadata
}
},
tx
);
await resourceMetadataDAL.insertMany(
inputSecrets.flatMap(({ filter: { id }, data: { secretMetadata } }) => {
if (secretMetadata) {
return secretMetadata.map(({ key, value }) => ({
key,
value,
secretId: id,
orgId
}));
}
return [];
}),
tx
);
return newSecrets.map((secret) => ({ ...secret, _id: secret.id })); return newSecrets.map((secret) => ({ ...secret, _id: secret.id }));
}; };
@@ -591,6 +622,7 @@ export const reshapeBridgeSecret = (
color?: string | null; color?: string | null;
name: string; name: string;
}[]; }[];
secretMetadata?: ResourceMetadataDTO;
} }
) => ({ ) => ({
secretKey: secret.key, secretKey: secret.key,
@@ -609,6 +641,7 @@ export const reshapeBridgeSecret = (
secretReminderRepeatDays: secret.reminderRepeatDays, secretReminderRepeatDays: secret.reminderRepeatDays,
secretReminderNote: secret.reminderNote, secretReminderNote: secret.reminderNote,
metadata: secret.metadata, metadata: secret.metadata,
secretMetadata: secret.secretMetadata,
createdAt: secret.createdAt, createdAt: secret.createdAt,
updatedAt: secret.updatedAt updatedAt: secret.updatedAt
}); });
@@ -75,7 +75,7 @@ type TSecretV2BridgeServiceFactoryDep = {
"insertV2Bridge" | "insertApprovalSecretV2Tags" "insertV2Bridge" | "insertApprovalSecretV2Tags"
>; >;
snapshotService: Pick<TSecretSnapshotServiceFactory, "performSnapshot">; snapshotService: Pick<TSecretSnapshotServiceFactory, "performSnapshot">;
resourceMetadataDAL: Pick<TResourceMetadataDALFactory, "insertMany">; resourceMetadataDAL: Pick<TResourceMetadataDALFactory, "insertMany" | "delete">;
}; };
export type TSecretV2BridgeServiceFactory = ReturnType<typeof secretV2BridgeServiceFactory>; export type TSecretV2BridgeServiceFactory = ReturnType<typeof secretV2BridgeServiceFactory>;
@@ -317,6 +317,7 @@ export const secretV2BridgeServiceFactory = ({
actorAuthMethod, actorAuthMethod,
projectId, projectId,
secretPath, secretPath,
secretMetadata,
...inputSecret ...inputSecret
}: TUpdateSecretDTO) => { }: TUpdateSecretDTO) => {
const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission( const { permission, ForbidOnInvalidProjectType } = await permissionService.getProjectPermission(
@@ -443,6 +444,8 @@ export const secretV2BridgeServiceFactory = ({
const updatedSecret = await secretDAL.transaction(async (tx) => const updatedSecret = await secretDAL.transaction(async (tx) =>
fnSecretBulkUpdate({ fnSecretBulkUpdate({
folderId, folderId,
orgId: actorOrgId,
resourceMetadataDAL,
inputSecrets: [ inputSecrets: [
{ {
filter: { id: secretId }, filter: { id: secretId },
@@ -456,6 +459,7 @@ export const secretV2BridgeServiceFactory = ({
skipMultilineEncoding: inputSecret.skipMultilineEncoding, skipMultilineEncoding: inputSecret.skipMultilineEncoding,
key: inputSecret.newSecretName || secretName, key: inputSecret.newSecretName || secretName,
tags: inputSecret.tagIds, tags: inputSecret.tagIds,
secretMetadata,
...encryptedValue ...encryptedValue
} }
} }
@@ -971,8 +975,8 @@ export const secretV2BridgeServiceFactory = ({
? secretDAL.findOneWithTags({ ? secretDAL.findOneWithTags({
folderId, folderId,
type: secretType, type: secretType,
key: secretName, [`${TableName.SecretV2}.key` as "key"]: secretName,
userId: secretType === SecretType.Personal ? actorId : null [`${TableName.SecretV2}.userId` as "userId"]: secretType === SecretType.Personal ? actorId : null
}) })
: secretVersionDAL : secretVersionDAL
.findOne({ .findOne({
@@ -1384,6 +1388,7 @@ export const secretV2BridgeServiceFactory = ({
const secrets = await secretDAL.transaction(async (tx) => const secrets = await secretDAL.transaction(async (tx) =>
fnSecretBulkUpdate({ fnSecretBulkUpdate({
folderId, folderId,
orgId: actorOrgId,
tx, tx,
inputSecrets: inputSecrets.map((el) => { inputSecrets: inputSecrets.map((el) => {
const originalSecret = secretsToUpdateInDBGroupedByKey[el.secretKey][0]; const originalSecret = secretsToUpdateInDBGroupedByKey[el.secretKey][0];
@@ -1407,6 +1412,7 @@ export const secretV2BridgeServiceFactory = ({
skipMultilineEncoding: el.skipMultilineEncoding, skipMultilineEncoding: el.skipMultilineEncoding,
key: el.newSecretName || el.secretKey, key: el.newSecretName || el.secretKey,
tags: el.tagIds, tags: el.tagIds,
secretMetadata: el.secretMetadata,
...encryptedValue ...encryptedValue
} }
}; };
@@ -1414,7 +1420,8 @@ export const secretV2BridgeServiceFactory = ({
secretDAL, secretDAL,
secretVersionDAL, secretVersionDAL,
secretTagDAL, secretTagDAL,
secretVersionTagDAL secretVersionTagDAL,
resourceMetadataDAL
}) })
); );
await snapshotService.performSnapshot(folderId); await snapshotService.performSnapshot(folderId);
@@ -1855,6 +1862,8 @@ export const secretV2BridgeServiceFactory = ({
if (locallyUpdatedSecrets.length) { if (locallyUpdatedSecrets.length) {
await fnSecretBulkUpdate({ await fnSecretBulkUpdate({
folderId: destinationFolder.id, folderId: destinationFolder.id,
orgId: actorOrgId,
resourceMetadataDAL,
secretVersionDAL, secretVersionDAL,
secretDAL, secretDAL,
tx, tx,
@@ -78,6 +78,7 @@ export type TUpdateSecretDTO = TProjectPermission & {
metadata?: { metadata?: {
source?: string; source?: string;
}; };
secretMetadata?: ResourceMetadataDTO;
}; };
export type TDeleteSecretDTO = TProjectPermission & { export type TDeleteSecretDTO = TProjectPermission & {
@@ -116,6 +117,7 @@ export type TUpdateManySecretDTO = Omit<TProjectPermission, "projectId"> & {
tagIds?: string[]; tagIds?: string[];
secretReminderRepeatDays?: number | null; secretReminderRepeatDays?: number | null;
secretReminderNote?: string | null; secretReminderNote?: string | null;
secretMetadata?: ResourceMetadataDTO;
}[]; }[];
}; };
@@ -167,10 +169,12 @@ type TRequireReferenceIfValue =
export type TFnSecretBulkUpdate = { export type TFnSecretBulkUpdate = {
folderId: string; folderId: string;
orgId: string;
inputSecrets: { inputSecrets: {
filter: Partial<TSecretsV2>; filter: Partial<TSecretsV2>;
data: TRequireReferenceIfValue & { tags?: string[] }; data: TRequireReferenceIfValue & { tags?: string[]; secretMetadata?: ResourceMetadataDTO };
}[]; }[];
resourceMetadataDAL: Pick<TResourceMetadataDALFactory, "insertMany" | "delete">;
secretDAL: Pick<TSecretV2BridgeDALFactory, "bulkUpdate" | "upsertSecretReferences">; secretDAL: Pick<TSecretV2BridgeDALFactory, "bulkUpdate" | "upsertSecretReferences">;
secretVersionDAL: Pick<TSecretVersionV2DALFactory, "insertMany">; secretVersionDAL: Pick<TSecretVersionV2DALFactory, "insertMany">;
secretTagDAL: Pick<TSecretTagDALFactory, "saveTagsToSecretV2" | "deleteTagsToSecretV2">; secretTagDAL: Pick<TSecretTagDALFactory, "saveTagsToSecretV2" | "deleteTagsToSecretV2">;
@@ -912,6 +912,7 @@ export const updateManySecretsRawFnFactory = ({
secretVersionTagV2BridgeDAL, secretVersionTagV2BridgeDAL,
secretVersionV2BridgeDAL, secretVersionV2BridgeDAL,
secretV2BridgeDAL, secretV2BridgeDAL,
resourceMetadataDAL,
kmsService kmsService
}: TUpdateManySecretsRawFnFactory) => { }: TUpdateManySecretsRawFnFactory) => {
const getBotKeyFn = getBotKeyFnFactory(projectBotDAL, projectDAL); const getBotKeyFn = getBotKeyFnFactory(projectBotDAL, projectDAL);
@@ -923,6 +924,7 @@ export const updateManySecretsRawFnFactory = ({
userId userId
}: TUpdateManySecretsRawFn): Promise<Array<{ id: string }>> => { }: TUpdateManySecretsRawFn): Promise<Array<{ id: string }>> => {
const { botKey, shouldUseSecretV2Bridge } = await getBotKeyFn(projectId); const { botKey, shouldUseSecretV2Bridge } = await getBotKeyFn(projectId);
const project = await projectDAL.findById(projectId);
const folder = await folderDAL.findBySecretPath(projectId, environment, secretPath); const folder = await folderDAL.findBySecretPath(projectId, environment, secretPath);
if (!folder) if (!folder)
@@ -991,11 +993,13 @@ export const updateManySecretsRawFnFactory = ({
const updatedSecrets = await secretDAL.transaction(async (tx) => const updatedSecrets = await secretDAL.transaction(async (tx) =>
fnSecretV2BridgeBulkUpdate({ fnSecretV2BridgeBulkUpdate({
folderId, folderId,
orgId: project.orgId,
tx, tx,
inputSecrets: inputSecrets.map((el) => ({ inputSecrets: inputSecrets.map((el) => ({
filter: { id: secretsToUpdateInDBGroupedByKey[el.key][0].id, type: SecretType.Shared }, filter: { id: secretsToUpdateInDBGroupedByKey[el.key][0].id, type: SecretType.Shared },
data: el data: el
})), })),
resourceMetadataDAL,
secretDAL: secretV2BridgeDAL, secretDAL: secretV2BridgeDAL,
secretVersionDAL: secretVersionV2BridgeDAL, secretVersionDAL: secretVersionV2BridgeDAL,
secretTagDAL, secretTagDAL,
+3 -2
View File
@@ -104,7 +104,7 @@ type TSecretQueueFactoryDep = {
auditLogService: Pick<TAuditLogServiceFactory, "createAuditLog">; auditLogService: Pick<TAuditLogServiceFactory, "createAuditLog">;
orgService: Pick<TOrgServiceFactory, "addGhostUser">; orgService: Pick<TOrgServiceFactory, "addGhostUser">;
projectUserMembershipRoleDAL: Pick<TProjectUserMembershipRoleDALFactory, "create">; projectUserMembershipRoleDAL: Pick<TProjectUserMembershipRoleDALFactory, "create">;
resourceMetadataDAL: Pick<TResourceMetadataDALFactory, "insertMany">; resourceMetadataDAL: Pick<TResourceMetadataDALFactory, "insertMany" | "delete">;
}; };
export type TGetSecrets = { export type TGetSecrets = {
@@ -318,7 +318,8 @@ export const secretQueueFactory = ({
kmsService, kmsService,
secretVersionV2BridgeDAL, secretVersionV2BridgeDAL,
secretV2BridgeDAL, secretV2BridgeDAL,
secretVersionTagV2BridgeDAL secretVersionTagV2BridgeDAL,
resourceMetadataDAL
}); });
/** /**
@@ -1533,7 +1533,8 @@ export const secretServiceFactory = ({
secretReminderRepeatDays, secretReminderRepeatDays,
metadata, metadata,
secretComment, secretComment,
newSecretName newSecretName,
secretMetadata
}: TUpdateSecretRawDTO) => { }: TUpdateSecretRawDTO) => {
const { botKey, shouldUseSecretV2Bridge } = await projectBotService.getBotKey(projectId); const { botKey, shouldUseSecretV2Bridge } = await projectBotService.getBotKey(projectId);
const policy = const policy =
@@ -1585,7 +1586,8 @@ export const secretServiceFactory = ({
secretName, secretName,
newSecretName, newSecretName,
metadata, metadata,
secretValue secretValue,
secretMetadata
}); });
return { type: SecretProtectionType.Direct as const, secret }; return { type: SecretProtectionType.Direct as const, secret };
} }
@@ -231,6 +231,7 @@ export type TUpdateSecretRawDTO = TProjectPermission & {
metadata?: { metadata?: {
source?: string; source?: string;
}; };
secretMetadata?: ResourceMetadataDTO;
}; };
export type TDeleteSecretRawDTO = TProjectPermission & { export type TDeleteSecretRawDTO = TProjectPermission & {
@@ -435,6 +436,7 @@ export type TUpdateManySecretsRawFnFactory = {
>; >;
secretVersionV2BridgeDAL: Pick<TSecretVersionV2DALFactory, "insertMany" | "findLatestVersionMany">; secretVersionV2BridgeDAL: Pick<TSecretVersionV2DALFactory, "insertMany" | "findLatestVersionMany">;
secretVersionTagV2BridgeDAL: Pick<TSecretVersionV2TagDALFactory, "insertMany">; secretVersionTagV2BridgeDAL: Pick<TSecretVersionV2TagDALFactory, "insertMany">;
resourceMetadataDAL: Pick<TResourceMetadataDALFactory, "insertMany" | "delete">;
}; };
export type TUpdateManySecretsRawFn = { export type TUpdateManySecretsRawFn = {