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

View File

@@ -1039,9 +1039,7 @@ export const registerRoutes = async (
secretApprovalRequestSecretDAL,
kmsService,
snapshotService,
resourceMetadataDAL,
userDAL,
identityDAL
resourceMetadataDAL
});
const secretApprovalRequestService = secretApprovalRequestServiceFactory({

View File

@@ -116,7 +116,8 @@ export const secretRawSchema = z.object({
.object({
actorId: 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()
.nullable()

View File

@@ -633,11 +633,12 @@ export const reshapeBridgeSecret = (
secret: Omit<TSecretsV2, "encryptedValue" | "encryptedComment"> & {
value: string;
comment: string;
actor?: {
actorType?: string;
actorId?: string;
name?: string;
};
userActorName?: string | null;
identityActorName?: string | null;
userActorId?: string | null;
identityActorId?: string | null;
membershipId?: string | null;
actorType?: string | null;
tags?: {
id: string;
slug: string;
@@ -658,7 +659,14 @@ export const reshapeBridgeSecret = (
_id: secret.id,
id: secret.id,
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,
skipMultilineEncoding: secret.skipMultilineEncoding,
secretReminderRepeatDays: secret.reminderRepeatDays,

View File

@@ -23,7 +23,6 @@ import { logger } from "@app/lib/logger";
import { alphaNumericNanoId } from "@app/lib/nanoid";
import { ActorType } from "../auth/auth-type";
import { TIdentityDALFactory } from "../identity/identity-dal";
import { TKmsServiceFactory } from "../kms/kms-service";
import { KmsDataKey } from "../kms/kms-types";
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 { fnSecretsV2FromImports } from "../secret-import/secret-import-fns";
import { TSecretTagDALFactory } from "../secret-tag/secret-tag-dal";
import { TUserDALFactory } from "../user/user-dal";
import { TSecretV2BridgeDALFactory } from "./secret-v2-bridge-dal";
import {
expandSecretReferencesFactory,
@@ -87,8 +85,6 @@ type TSecretV2BridgeServiceFactoryDep = {
>;
snapshotService: Pick<TSecretSnapshotServiceFactory, "performSnapshot">;
resourceMetadataDAL: Pick<TResourceMetadataDALFactory, "insertMany" | "delete">;
userDAL: Pick<TUserDALFactory, "find">;
identityDAL: Pick<TIdentityDALFactory, "find">;
};
export type TSecretV2BridgeServiceFactory = ReturnType<typeof secretV2BridgeServiceFactory>;
@@ -111,9 +107,7 @@ export const secretV2BridgeServiceFactory = ({
secretApprovalRequestDAL,
secretApprovalRequestSecretDAL,
kmsService,
resourceMetadataDAL,
userDAL,
identityDAL
resourceMetadataDAL
}: TSecretV2BridgeServiceFactoryDep) => {
const $validateSecretReferences = async (
projectId: string,
@@ -1715,36 +1709,15 @@ export const secretV2BridgeServiceFactory = ({
type: KmsDataKey.SecretManager,
projectId: folder.projectId
});
const secretVersions = await secretVersionDAL.find({ secretId }, { offset, limit, sort: [["createdAt", "desc"]] });
const userIds = Array.from(
new Set(secretVersions.map((version) => version.userActorId).filter(Boolean))
) 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);
const secretVersions = await secretVersionDAL.findVersionsBySecretIdWithActors(secretId, folder.projectId, {
offset,
limit,
sort: [["createdAt", "desc"]]
});
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, "/", {
...el,
actor: actorEntity,
value: el.encryptedValue ? secretManagerDecryptor({ cipherTextBlob: el.encryptedValue }).toString() : "",
comment: el.encryptedComment ? secretManagerDecryptor({ cipherTextBlob: el.encryptedComment }).toString() : ""
});

View File

@@ -1,9 +1,10 @@
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import { Knex } from "knex";
import { TDbClient } from "@app/db";
import { TableName, TSecretVersionsV2, TSecretVersionsV2Update } from "@app/db/schemas";
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 { QueueName } from "@app/queue";
@@ -119,11 +120,60 @@ export const secretVersionV2BridgeDALFactory = (db: TDbClient) => {
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 {
...secretVersionV2Orm,
pruneExcessVersions,
findLatestVersionMany,
bulkUpdate,
findLatestVersionByFolderId
findLatestVersionByFolderId,
findVersionsBySecretIdWithActors
};
};

View File

@@ -105,6 +105,7 @@ export type SecretVersions = {
actorId?: string | null;
actorType?: string | null;
name?: string | null;
membershipId?: string | null;
} | null;
};

View File

@@ -5,14 +5,14 @@ import {
faArrowRotateRight,
faCheckCircle,
faClock,
faDesktop,
faEyeSlash,
faPlus,
faServer,
faShare,
faTag,
faTrash,
faUser,
faDesktop,
faServer
faUser
} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { zodResolver } from "@hookform/resolvers/zod";
@@ -48,11 +48,11 @@ import {
useWorkspace
} from "@app/context";
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 { SecretV3RawSanitized, WsTag } from "@app/hooks/api/types";
import { ProjectType } from "@app/hooks/api/workspace/types";
import { ActorType } from "@app/hooks/api/auditLogs/enums";
import { CreateReminderForm } from "./CreateReminderForm";
import { formSchema, SecretActionType, TFormSchema } from "./SecretListView.utils";
@@ -125,7 +125,6 @@ export const SecretDetailSidebar = ({
);
const selectTagSlugs = selectedTags.map((i) => i.slug);
const navigate = useNavigate();
const { data: members = [] } = useGetWorkspaceUsers(currentWorkspace.id);
const cannotEditSecret = permission.cannot(
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) {
case ActorType.PLATFORM:
return "System-generated";
@@ -234,15 +236,14 @@ export const SecretDetailSidebar = ({
}
};
const getUserMembershipId = (actorId: string) => {
const foundMember = members.find((member) => member.user?.id === actorId);
return foundMember?.id || null;
};
const getLinkToModifyHistoryEntity = (actorId: string, actorType: string) => {
const getLinkToModifyHistoryEntity = (
actorId: string,
actorType: string,
membershipId: string | null = ""
) => {
switch (actorType) {
case ActorType.USER:
return `/${ProjectType.SecretManager}/${currentWorkspace.id}/members/${getUserMembershipId(actorId)}`;
return `/${ProjectType.SecretManager}/${currentWorkspace.id}/members/${membershipId}`;
case ActorType.IDENTITY:
return `/${ProjectType.SecretManager}/${currentWorkspace.id}/identities/${actorId}`;
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) {
const redirectLink = getLinkToModifyHistoryEntity(actorId, actorType);
const redirectLink = getLinkToModifyHistoryEntity(actorId, actorType, membershipId);
if (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 */}
<div
onClick={() =>
onModifyHistoryClick(actor.actorId, actor.actorType)
onModifyHistoryClick(
actor.actorId,
actor.actorType,
actor.membershipId
)
}
className="cursor-pointer"
>
@@ -792,7 +801,9 @@ export const SecretDetailSidebar = ({
type="button"
className="ml-1 cursor-pointer"
onClick={(e) => {
e.currentTarget.closest(".group")?.classList.add("show-value");
e.currentTarget
.closest(".group")
?.classList.add("show-value");
}}
onKeyDown={(e) => {
if (e.key === "Enter" || e.key === " ") {