mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-07 00:27:30 +00:00
Improve query to only use one to retrieve all information
This commit is contained in:
@@ -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
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+29
-18
@@ -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 === " ") {
|
||||||
|
|||||||
Reference in New Issue
Block a user