Improve query to only use one to retrieve all information

This commit is contained in:
carlosmonastyrski
2025-03-06 15:15:52 -03:00
parent 9116acd37b
commit 8e311658d4
7 changed files with 105 additions and 63 deletions
+1 -3
View File
@@ -1039,9 +1039,7 @@ export const registerRoutes = async (
secretApprovalRequestSecretDAL, secretApprovalRequestSecretDAL,
kmsService, kmsService,
snapshotService, snapshotService,
resourceMetadataDAL, resourceMetadataDAL
userDAL,
identityDAL
}); });
const secretApprovalRequestService = secretApprovalRequestServiceFactory({ const secretApprovalRequestService = secretApprovalRequestServiceFactory({
@@ -116,7 +116,8 @@ export const secretRawSchema = z.object({
.object({ .object({
actorId: z.string().nullable().optional(), actorId: z.string().nullable().optional(),
actorType: z.string().nullable().optional(), actorType: z.string().nullable().optional(),
name: z.string().nullable().optional() name: z.string().nullable().optional(),
membershipId: z.string().nullable().optional()
}) })
.optional() .optional()
.nullable() .nullable()
@@ -633,11 +633,12 @@ export const reshapeBridgeSecret = (
secret: Omit<TSecretsV2, "encryptedValue" | "encryptedComment"> & { secret: Omit<TSecretsV2, "encryptedValue" | "encryptedComment"> & {
value: string; value: string;
comment: string; comment: string;
actor?: { userActorName?: string | null;
actorType?: string; identityActorName?: string | null;
actorId?: string; userActorId?: string | null;
name?: string; identityActorId?: string | null;
}; membershipId?: string | null;
actorType?: string | null;
tags?: { tags?: {
id: string; id: string;
slug: string; slug: string;
@@ -658,7 +659,14 @@ export const reshapeBridgeSecret = (
_id: secret.id, _id: secret.id,
id: secret.id, id: secret.id,
user: secret.userId, user: secret.userId,
actor: secret.actor, actor: secret.actorType
? {
actorType: secret.actorType,
actorId: secret.userActorId || secret.identityActorId,
name: secret.identityActorName || secret.userActorName,
membershipId: secret.membershipId
}
: undefined,
tags: secret.tags, tags: secret.tags,
skipMultilineEncoding: secret.skipMultilineEncoding, skipMultilineEncoding: secret.skipMultilineEncoding,
secretReminderRepeatDays: secret.reminderRepeatDays, secretReminderRepeatDays: secret.reminderRepeatDays,
@@ -23,7 +23,6 @@ import { logger } from "@app/lib/logger";
import { alphaNumericNanoId } from "@app/lib/nanoid"; import { alphaNumericNanoId } from "@app/lib/nanoid";
import { ActorType } from "../auth/auth-type"; import { ActorType } from "../auth/auth-type";
import { TIdentityDALFactory } from "../identity/identity-dal";
import { TKmsServiceFactory } from "../kms/kms-service"; import { TKmsServiceFactory } from "../kms/kms-service";
import { KmsDataKey } from "../kms/kms-types"; import { KmsDataKey } from "../kms/kms-types";
import { TProjectEnvDALFactory } from "../project-env/project-env-dal"; import { TProjectEnvDALFactory } from "../project-env/project-env-dal";
@@ -33,7 +32,6 @@ import { TSecretFolderDALFactory } from "../secret-folder/secret-folder-dal";
import { TSecretImportDALFactory } from "../secret-import/secret-import-dal"; import { TSecretImportDALFactory } from "../secret-import/secret-import-dal";
import { fnSecretsV2FromImports } from "../secret-import/secret-import-fns"; import { fnSecretsV2FromImports } from "../secret-import/secret-import-fns";
import { TSecretTagDALFactory } from "../secret-tag/secret-tag-dal"; import { TSecretTagDALFactory } from "../secret-tag/secret-tag-dal";
import { TUserDALFactory } from "../user/user-dal";
import { TSecretV2BridgeDALFactory } from "./secret-v2-bridge-dal"; import { TSecretV2BridgeDALFactory } from "./secret-v2-bridge-dal";
import { import {
expandSecretReferencesFactory, expandSecretReferencesFactory,
@@ -87,8 +85,6 @@ type TSecretV2BridgeServiceFactoryDep = {
>; >;
snapshotService: Pick<TSecretSnapshotServiceFactory, "performSnapshot">; snapshotService: Pick<TSecretSnapshotServiceFactory, "performSnapshot">;
resourceMetadataDAL: Pick<TResourceMetadataDALFactory, "insertMany" | "delete">; resourceMetadataDAL: Pick<TResourceMetadataDALFactory, "insertMany" | "delete">;
userDAL: Pick<TUserDALFactory, "find">;
identityDAL: Pick<TIdentityDALFactory, "find">;
}; };
export type TSecretV2BridgeServiceFactory = ReturnType<typeof secretV2BridgeServiceFactory>; export type TSecretV2BridgeServiceFactory = ReturnType<typeof secretV2BridgeServiceFactory>;
@@ -111,9 +107,7 @@ export const secretV2BridgeServiceFactory = ({
secretApprovalRequestDAL, secretApprovalRequestDAL,
secretApprovalRequestSecretDAL, secretApprovalRequestSecretDAL,
kmsService, kmsService,
resourceMetadataDAL, resourceMetadataDAL
userDAL,
identityDAL
}: TSecretV2BridgeServiceFactoryDep) => { }: TSecretV2BridgeServiceFactoryDep) => {
const $validateSecretReferences = async ( const $validateSecretReferences = async (
projectId: string, projectId: string,
@@ -1715,36 +1709,15 @@ export const secretV2BridgeServiceFactory = ({
type: KmsDataKey.SecretManager, type: KmsDataKey.SecretManager,
projectId: folder.projectId projectId: folder.projectId
}); });
const secretVersions = await secretVersionDAL.find({ secretId }, { offset, limit, sort: [["createdAt", "desc"]] }); const secretVersions = await secretVersionDAL.findVersionsBySecretIdWithActors(secretId, folder.projectId, {
offset,
const userIds = Array.from( limit,
new Set(secretVersions.map((version) => version.userActorId).filter(Boolean)) sort: [["createdAt", "desc"]]
) as string[]; });
const users = userIds.length > 0 ? await userDAL.find({ $in: { id: userIds } }) : [];
const usersById = groupBy(users, (user) => user.id);
const identitiesIds = Array.from(
new Set(secretVersions.map((version) => version.identityActorId).filter(Boolean))
) as string[];
const identities = identitiesIds.length > 0 ? await identityDAL.find({ $in: { id: identitiesIds } }) : [];
const identitiesById = groupBy(identities, (identity) => identity.id);
return secretVersions.map((el) => { return secretVersions.map((el) => {
let entityId;
let actorName;
if (el.userActorId) {
actorName = usersById[el.userActorId]?.[0]?.username;
entityId = el.userActorId;
} else if (el.identityActorId) {
actorName = identitiesById[el.identityActorId]?.[0]?.name;
entityId = el.identityActorId;
}
const actorEntity = el.actorType ? { actorType: el.actorType, actorId: entityId, name: actorName } : undefined;
return reshapeBridgeSecret(folder.projectId, folder.environment.envSlug, "/", { return reshapeBridgeSecret(folder.projectId, folder.environment.envSlug, "/", {
...el, ...el,
actor: actorEntity,
value: el.encryptedValue ? secretManagerDecryptor({ cipherTextBlob: el.encryptedValue }).toString() : "", value: el.encryptedValue ? secretManagerDecryptor({ cipherTextBlob: el.encryptedValue }).toString() : "",
comment: el.encryptedComment ? secretManagerDecryptor({ cipherTextBlob: el.encryptedComment }).toString() : "" comment: el.encryptedComment ? secretManagerDecryptor({ cipherTextBlob: el.encryptedComment }).toString() : ""
}); });
@@ -1,9 +1,10 @@
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import { Knex } from "knex"; import { Knex } from "knex";
import { TDbClient } from "@app/db"; import { TDbClient } from "@app/db";
import { TableName, TSecretVersionsV2, TSecretVersionsV2Update } from "@app/db/schemas"; import { TableName, TSecretVersionsV2, TSecretVersionsV2Update } from "@app/db/schemas";
import { BadRequestError, DatabaseError } from "@app/lib/errors"; import { BadRequestError, DatabaseError } from "@app/lib/errors";
import { ormify, selectAllTableCols } from "@app/lib/knex"; import { ormify, selectAllTableCols, TFindOpt } from "@app/lib/knex";
import { logger } from "@app/lib/logger"; import { logger } from "@app/lib/logger";
import { QueueName } from "@app/queue"; import { QueueName } from "@app/queue";
@@ -119,11 +120,60 @@ export const secretVersionV2BridgeDALFactory = (db: TDbClient) => {
logger.info(`${QueueName.DailyResourceCleanUp}: pruning secret version v2 completed`); logger.info(`${QueueName.DailyResourceCleanUp}: pruning secret version v2 completed`);
}; };
const findVersionsBySecretIdWithActors = async (
secretId: string,
projectId: string,
{ offset, limit, sort = [["createdAt", "desc"]] }: TFindOpt<TSecretVersionsV2> = {},
tx?: Knex
) => {
try {
const query = (tx || db)(TableName.SecretVersionV2)
.where(`${TableName.SecretVersionV2}.secretId`, secretId)
.leftJoin(TableName.Users, `${TableName.Users}.id`, `${TableName.SecretVersionV2}.userActorId`)
.leftJoin(
TableName.ProjectMembership,
`${TableName.ProjectMembership}.userId`,
`${TableName.SecretVersionV2}.userActorId`
)
.leftJoin(TableName.Identity, `${TableName.Identity}.id`, `${TableName.SecretVersionV2}.identityActorId`)
.select(
selectAllTableCols(TableName.SecretVersionV2),
`${TableName.Users}.username as userActorName`,
`${TableName.Identity}.name as identityActorName`,
`${TableName.ProjectMembership}.id as membershipId`
);
if (limit) void query.limit(limit);
if (offset) void query.offset(offset);
if (sort) {
void query.orderBy(
sort.map(([column, order, nulls]) => ({
column: `${TableName.SecretVersionV2}.${column as string}`,
order,
nulls
}))
);
}
const docs: Array<
TSecretVersionsV2 & {
userActorName: string | undefined | null;
identityActorName: string | undefined | null;
membershipId: string | undefined | null;
}
> = await query;
return docs;
} catch (error) {
throw new DatabaseError({ error, name: "FindVersionsBySecretIdWithActors" });
}
};
return { return {
...secretVersionV2Orm, ...secretVersionV2Orm,
pruneExcessVersions, pruneExcessVersions,
findLatestVersionMany, findLatestVersionMany,
bulkUpdate, bulkUpdate,
findLatestVersionByFolderId findLatestVersionByFolderId,
findVersionsBySecretIdWithActors
}; };
}; };
+1
View File
@@ -105,6 +105,7 @@ export type SecretVersions = {
actorId?: string | null; actorId?: string | null;
actorType?: string | null; actorType?: string | null;
name?: string | null; name?: string | null;
membershipId?: string | null;
} | null; } | null;
}; };
@@ -5,14 +5,14 @@ import {
faArrowRotateRight, faArrowRotateRight,
faCheckCircle, faCheckCircle,
faClock, faClock,
faDesktop,
faEyeSlash, faEyeSlash,
faPlus, faPlus,
faServer,
faShare, faShare,
faTag, faTag,
faTrash, faTrash,
faUser, faUser
faDesktop,
faServer
} from "@fortawesome/free-solid-svg-icons"; } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { zodResolver } from "@hookform/resolvers/zod"; import { zodResolver } from "@hookform/resolvers/zod";
@@ -48,11 +48,11 @@ import {
useWorkspace useWorkspace
} from "@app/context"; } from "@app/context";
import { usePopUp, useToggle } from "@app/hooks"; import { usePopUp, useToggle } from "@app/hooks";
import { useGetSecretVersion, useGetWorkspaceUsers } from "@app/hooks/api"; import { useGetSecretVersion } from "@app/hooks/api";
import { ActorType } from "@app/hooks/api/auditLogs/enums";
import { useGetSecretAccessList } from "@app/hooks/api/secrets/queries"; import { useGetSecretAccessList } from "@app/hooks/api/secrets/queries";
import { SecretV3RawSanitized, WsTag } from "@app/hooks/api/types"; import { SecretV3RawSanitized, WsTag } from "@app/hooks/api/types";
import { ProjectType } from "@app/hooks/api/workspace/types"; import { ProjectType } from "@app/hooks/api/workspace/types";
import { ActorType } from "@app/hooks/api/auditLogs/enums";
import { CreateReminderForm } from "./CreateReminderForm"; import { CreateReminderForm } from "./CreateReminderForm";
import { formSchema, SecretActionType, TFormSchema } from "./SecretListView.utils"; import { formSchema, SecretActionType, TFormSchema } from "./SecretListView.utils";
@@ -125,7 +125,6 @@ export const SecretDetailSidebar = ({
); );
const selectTagSlugs = selectedTags.map((i) => i.slug); const selectTagSlugs = selectedTags.map((i) => i.slug);
const navigate = useNavigate(); const navigate = useNavigate();
const { data: members = [] } = useGetWorkspaceUsers(currentWorkspace.id);
const cannotEditSecret = permission.cannot( const cannotEditSecret = permission.cannot(
ProjectPermissionActions.Edit, ProjectPermissionActions.Edit,
@@ -225,7 +224,10 @@ export const SecretDetailSidebar = ({
} }
}; };
const getModifiedByName = (userType: string | undefined | null, userName: string | null | undefined) => { const getModifiedByName = (
userType: string | undefined | null,
userName: string | null | undefined
) => {
switch (userType) { switch (userType) {
case ActorType.PLATFORM: case ActorType.PLATFORM:
return "System-generated"; return "System-generated";
@@ -234,15 +236,14 @@ export const SecretDetailSidebar = ({
} }
}; };
const getUserMembershipId = (actorId: string) => { const getLinkToModifyHistoryEntity = (
const foundMember = members.find((member) => member.user?.id === actorId); actorId: string,
return foundMember?.id || null; actorType: string,
}; membershipId: string | null = ""
) => {
const getLinkToModifyHistoryEntity = (actorId: string, actorType: string) => {
switch (actorType) { switch (actorType) {
case ActorType.USER: case ActorType.USER:
return `/${ProjectType.SecretManager}/${currentWorkspace.id}/members/${getUserMembershipId(actorId)}`; return `/${ProjectType.SecretManager}/${currentWorkspace.id}/members/${membershipId}`;
case ActorType.IDENTITY: case ActorType.IDENTITY:
return `/${ProjectType.SecretManager}/${currentWorkspace.id}/identities/${actorId}`; return `/${ProjectType.SecretManager}/${currentWorkspace.id}/identities/${actorId}`;
default: default:
@@ -250,9 +251,13 @@ export const SecretDetailSidebar = ({
} }
}; };
const onModifyHistoryClick = (actorId: string | undefined | null, actorType: string | undefined | null) => { const onModifyHistoryClick = (
actorId: string | undefined | null,
actorType: string | undefined | null,
membershipId: string | undefined | null
) => {
if (actorType && actorId && actorType !== ActorType.PLATFORM) { if (actorType && actorId && actorType !== ActorType.PLATFORM) {
const redirectLink = getLinkToModifyHistoryEntity(actorId, actorType); const redirectLink = getLinkToModifyHistoryEntity(actorId, actorType, membershipId);
if (redirectLink) { if (redirectLink) {
navigate({ to: redirectLink }); navigate({ to: redirectLink });
} }
@@ -700,7 +705,11 @@ export const SecretDetailSidebar = ({
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */} {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */}
<div <div
onClick={() => onClick={() =>
onModifyHistoryClick(actor.actorId, actor.actorType) onModifyHistoryClick(
actor.actorId,
actor.actorType,
actor.membershipId
)
} }
className="cursor-pointer" className="cursor-pointer"
> >
@@ -792,7 +801,9 @@ export const SecretDetailSidebar = ({
type="button" type="button"
className="ml-1 cursor-pointer" className="ml-1 cursor-pointer"
onClick={(e) => { onClick={(e) => {
e.currentTarget.closest(".group")?.classList.add("show-value"); e.currentTarget
.closest(".group")
?.classList.add("show-value");
}} }}
onKeyDown={(e) => { onKeyDown={(e) => {
if (e.key === "Enter" || e.key === " ") { if (e.key === "Enter" || e.key === " ") {