mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-06 05:26:43 +00:00
Chore: Documentation
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import { ForbiddenError } from "@casl/ability";
|
import { ForbiddenError, subject } from "@casl/ability";
|
||||||
|
|
||||||
import { TableName, TSecretTagJunctionInsert } from "@app/db/schemas";
|
import { TableName, TSecretTagJunctionInsert } from "@app/db/schemas";
|
||||||
import { BadRequestError, InternalServerError } from "@app/lib/errors";
|
import { BadRequestError, InternalServerError } from "@app/lib/errors";
|
||||||
@@ -23,6 +23,7 @@ import {
|
|||||||
import { TSnapshotDALFactory } from "./snapshot-dal";
|
import { TSnapshotDALFactory } from "./snapshot-dal";
|
||||||
import { TSnapshotFolderDALFactory } from "./snapshot-folder-dal";
|
import { TSnapshotFolderDALFactory } from "./snapshot-folder-dal";
|
||||||
import { TSnapshotSecretDALFactory } from "./snapshot-secret-dal";
|
import { TSnapshotSecretDALFactory } from "./snapshot-secret-dal";
|
||||||
|
import { getFullFolderPath } from "./snapshot-service-fns";
|
||||||
|
|
||||||
type TSecretSnapshotServiceFactoryDep = {
|
type TSecretSnapshotServiceFactoryDep = {
|
||||||
snapshotDAL: TSnapshotDALFactory;
|
snapshotDAL: TSnapshotDALFactory;
|
||||||
@@ -33,7 +34,7 @@ type TSecretSnapshotServiceFactoryDep = {
|
|||||||
secretDAL: Pick<TSecretDALFactory, "delete" | "insertMany">;
|
secretDAL: Pick<TSecretDALFactory, "delete" | "insertMany">;
|
||||||
secretTagDAL: Pick<TSecretTagDALFactory, "saveTagsToSecret">;
|
secretTagDAL: Pick<TSecretTagDALFactory, "saveTagsToSecret">;
|
||||||
secretVersionTagDAL: Pick<TSecretVersionTagDALFactory, "insertMany">;
|
secretVersionTagDAL: Pick<TSecretVersionTagDALFactory, "insertMany">;
|
||||||
folderDAL: Pick<TSecretFolderDALFactory, "findById" | "findBySecretPath" | "delete" | "insertMany">;
|
folderDAL: Pick<TSecretFolderDALFactory, "findById" | "findBySecretPath" | "delete" | "insertMany" | "find">;
|
||||||
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">;
|
permissionService: Pick<TPermissionServiceFactory, "getProjectPermission">;
|
||||||
licenseService: Pick<TLicenseServiceFactory, "isValidLicense">;
|
licenseService: Pick<TLicenseServiceFactory, "isValidLicense">;
|
||||||
};
|
};
|
||||||
@@ -71,6 +72,12 @@ export const secretSnapshotServiceFactory = ({
|
|||||||
);
|
);
|
||||||
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback);
|
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback);
|
||||||
|
|
||||||
|
// We need to check if the user has access to the secrets in the folder. If we don't do this, a user could theoretically access snapshot secret values even if they don't have read access to the secrets in the folder.
|
||||||
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
|
ProjectPermissionActions.Read,
|
||||||
|
subject(ProjectPermissionSub.Secrets, { environment, secretPath: path })
|
||||||
|
);
|
||||||
|
|
||||||
const folder = await folderDAL.findBySecretPath(projectId, environment, path);
|
const folder = await folderDAL.findBySecretPath(projectId, environment, path);
|
||||||
if (!folder) throw new BadRequestError({ message: "Folder not found" });
|
if (!folder) throw new BadRequestError({ message: "Folder not found" });
|
||||||
|
|
||||||
@@ -98,6 +105,12 @@ export const secretSnapshotServiceFactory = ({
|
|||||||
);
|
);
|
||||||
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback);
|
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback);
|
||||||
|
|
||||||
|
// We need to check if the user has access to the secrets in the folder. If we don't do this, a user could theoretically access snapshot secret values even if they don't have read access to the secrets in the folder.
|
||||||
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
|
ProjectPermissionActions.Read,
|
||||||
|
subject(ProjectPermissionSub.Secrets, { environment, secretPath: path })
|
||||||
|
);
|
||||||
|
|
||||||
const folder = await folderDAL.findBySecretPath(projectId, environment, path);
|
const folder = await folderDAL.findBySecretPath(projectId, environment, path);
|
||||||
if (!folder) throw new BadRequestError({ message: "Folder not found" });
|
if (!folder) throw new BadRequestError({ message: "Folder not found" });
|
||||||
|
|
||||||
@@ -116,6 +129,19 @@ export const secretSnapshotServiceFactory = ({
|
|||||||
actorOrgId
|
actorOrgId
|
||||||
);
|
);
|
||||||
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback);
|
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Read, ProjectPermissionSub.SecretRollback);
|
||||||
|
|
||||||
|
const fullFolderPath = await getFullFolderPath({
|
||||||
|
folderDAL,
|
||||||
|
folderId: snapshot.folderId,
|
||||||
|
envId: snapshot.environment.id
|
||||||
|
});
|
||||||
|
|
||||||
|
// We need to check if the user has access to the secrets in the folder. If we don't do this, a user could theoretically access snapshot secret values even if they don't have read access to the secrets in the folder.
|
||||||
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
|
ProjectPermissionActions.Read,
|
||||||
|
subject(ProjectPermissionSub.Secrets, { environment: snapshot.environment.slug, secretPath: fullFolderPath })
|
||||||
|
);
|
||||||
|
|
||||||
return snapshot;
|
return snapshot;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -101,6 +101,7 @@ export const snapshotDALFactory = (db: TDbClient) => {
|
|||||||
key: "snapshotId",
|
key: "snapshotId",
|
||||||
parentMapper: ({
|
parentMapper: ({
|
||||||
snapshotId: id,
|
snapshotId: id,
|
||||||
|
folderId,
|
||||||
projectId,
|
projectId,
|
||||||
envId,
|
envId,
|
||||||
envSlug,
|
envSlug,
|
||||||
@@ -109,6 +110,7 @@ export const snapshotDALFactory = (db: TDbClient) => {
|
|||||||
snapshotUpdatedAt: updatedAt
|
snapshotUpdatedAt: updatedAt
|
||||||
}) => ({
|
}) => ({
|
||||||
id,
|
id,
|
||||||
|
folderId,
|
||||||
projectId,
|
projectId,
|
||||||
createdAt,
|
createdAt,
|
||||||
updatedAt,
|
updatedAt,
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import { TSecretFolderDALFactory } from "@app/services/secret-folder/secret-folder-dal";
|
||||||
|
|
||||||
|
type GetFullFolderPath = {
|
||||||
|
folderDAL: Pick<TSecretFolderDALFactory, "findById" | "find">; // Added findAllInEnv
|
||||||
|
folderId: string;
|
||||||
|
envId: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getFullFolderPath = async ({ folderDAL, folderId, envId }: GetFullFolderPath): Promise<string> => {
|
||||||
|
// Helper function to remove duplicate slashes
|
||||||
|
const removeDuplicateSlashes = (path: string) => path.replace(/\/{2,}/g, "/");
|
||||||
|
|
||||||
|
// Fetch all folders at once based on environment ID to avoid multiple queries
|
||||||
|
const folders = await folderDAL.find({ envId });
|
||||||
|
const folderMap = new Map(folders.map((folder) => [folder.id, folder]));
|
||||||
|
|
||||||
|
const buildPath = (currFolderId: string): string => {
|
||||||
|
const folder = folderMap.get(currFolderId);
|
||||||
|
if (!folder) return "";
|
||||||
|
const folderPathSegment = !folder.parentId && folder.name === "root" ? "/" : `/${folder.name}`;
|
||||||
|
if (folder.parentId) {
|
||||||
|
return removeDuplicateSlashes(`${buildPath(folder.parentId)}${folderPathSegment}`);
|
||||||
|
}
|
||||||
|
return removeDuplicateSlashes(folderPathSegment);
|
||||||
|
};
|
||||||
|
|
||||||
|
return buildPath(folderId);
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user