mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-08 05:27:52 +00:00
feat: backend fixed bug in permission change
This commit is contained in:
@@ -28,8 +28,8 @@ type TKnexGroupOperator<T extends object> = {
|
|||||||
export type TKnexDynamicOperator<T extends object> = TKnexGroupOperator<T> | TKnexNonGroupOperator<T>;
|
export type TKnexDynamicOperator<T extends object> = TKnexGroupOperator<T> | TKnexNonGroupOperator<T>;
|
||||||
|
|
||||||
export const buildDynamicKnexQuery = <T extends object>(
|
export const buildDynamicKnexQuery = <T extends object>(
|
||||||
dynamicQuery: TKnexDynamicOperator<T>,
|
rootQueryBuild: Knex.QueryBuilder,
|
||||||
rootQueryBuild: Knex.QueryBuilder
|
dynamicQuery: TKnexDynamicOperator<T>
|
||||||
) => {
|
) => {
|
||||||
const stack = [{ filterAst: dynamicQuery, queryBuilder: rootQueryBuild }];
|
const stack = [{ filterAst: dynamicQuery, queryBuilder: rootQueryBuild }];
|
||||||
|
|
||||||
@@ -53,34 +53,25 @@ export const buildDynamicKnexQuery = <T extends object>(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "and": {
|
case "and": {
|
||||||
void queryBuilder.andWhere((subQueryBuilder) => {
|
filterAst.value.forEach((el) => {
|
||||||
filterAst.value.forEach((el) => {
|
void queryBuilder.andWhere((subQueryBuilder) => {
|
||||||
stack.push({
|
buildDynamicKnexQuery(subQueryBuilder, el);
|
||||||
queryBuilder: subQueryBuilder,
|
|
||||||
filterAst: el
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "or": {
|
case "or": {
|
||||||
void queryBuilder.orWhere((subQueryBuilder) => {
|
filterAst.value.forEach((el) => {
|
||||||
filterAst.value.forEach((el) => {
|
void queryBuilder.orWhere((subQueryBuilder) => {
|
||||||
stack.push({
|
buildDynamicKnexQuery(subQueryBuilder, el);
|
||||||
queryBuilder: subQueryBuilder,
|
|
||||||
filterAst: el
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "not": {
|
case "not": {
|
||||||
void queryBuilder.whereNot((subQueryBuilder) => {
|
filterAst.value.forEach((el) => {
|
||||||
filterAst.value.forEach((el) => {
|
void queryBuilder.whereNot((subQueryBuilder) => {
|
||||||
stack.push({
|
buildDynamicKnexQuery(subQueryBuilder, el);
|
||||||
queryBuilder: subQueryBuilder,
|
|
||||||
filterAst: el
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ export const buildFindFilter =
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
if ($complex) {
|
if ($complex) {
|
||||||
buildDynamicKnexQuery($complex, bd);
|
return buildDynamicKnexQuery(bd, $complex);
|
||||||
}
|
}
|
||||||
return bd;
|
return bd;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ export const fastifyErrHandler = fastifyPlugin(async (server: FastifyZodProvider
|
|||||||
void res.status(HttpStatusCodes.Forbidden).send({
|
void res.status(HttpStatusCodes.Forbidden).send({
|
||||||
statusCode: HttpStatusCodes.Forbidden,
|
statusCode: HttpStatusCodes.Forbidden,
|
||||||
error: "PermissionDenied",
|
error: "PermissionDenied",
|
||||||
message: `You are not allowed to ${error.action} on ${error.subjectType}`
|
message: `You are not allowed to ${error.action} on ${error.subjectType} - ${JSON.stringify(error.subject)}`
|
||||||
});
|
});
|
||||||
} else if (error instanceof ForbiddenRequestError) {
|
} else if (error instanceof ForbiddenRequestError) {
|
||||||
void res.status(HttpStatusCodes.Forbidden).send({
|
void res.status(HttpStatusCodes.Forbidden).send({
|
||||||
|
|||||||
@@ -180,7 +180,7 @@ export const fnSecretsV2FromImports = async ({
|
|||||||
({ importPath, importEnv }) => !cyclicDetector.has(getImportUniqKey(importEnv.slug, importPath))
|
({ importPath, importEnv }) => !cyclicDetector.has(getImportUniqKey(importEnv.slug, importPath))
|
||||||
);
|
);
|
||||||
|
|
||||||
if (sanitizedImports.length) continue;
|
if (!sanitizedImports.length) continue;
|
||||||
|
|
||||||
const importedFolders = await folderDAL.findByManySecretPath(
|
const importedFolders = await folderDAL.findByManySecretPath(
|
||||||
sanitizedImports.map(({ importEnv, importPath }) => ({
|
sanitizedImports.map(({ importEnv, importPath }) => ({
|
||||||
@@ -212,7 +212,7 @@ export const fnSecretsV2FromImports = async ({
|
|||||||
const deeperImports = await secretImportDAL.findByFolderIds(importedFolderIds);
|
const deeperImports = await secretImportDAL.findByFolderIds(importedFolderIds);
|
||||||
const deeperImportsGroupByFolderId = groupBy(deeperImports, (i) => i.folderId);
|
const deeperImportsGroupByFolderId = groupBy(deeperImports, (i) => i.folderId);
|
||||||
|
|
||||||
const isFirstIteration = processedImports.length;
|
const isFirstIteration = !processedImports.length;
|
||||||
sanitizedImports.forEach(({ importPath, importEnv, id, folderId }, i) => {
|
sanitizedImports.forEach(({ importPath, importEnv, id, folderId }, i) => {
|
||||||
const sourceImportFolder = importedFolderGroupBySourceImport[`${importEnv.id}-${importPath}`]?.[0];
|
const sourceImportFolder = importedFolderGroupBySourceImport[`${importEnv.id}-${importPath}`]?.[0];
|
||||||
const secretsWithDuplicate = (importedSecretsGroupByFolderId?.[importedFolders?.[i]?.id as string] || [])
|
const secretsWithDuplicate = (importedSecretsGroupByFolderId?.[importedFolders?.[i]?.id as string] || [])
|
||||||
@@ -250,7 +250,7 @@ export const fnSecretsV2FromImports = async ({
|
|||||||
folderId: importedFolders?.[i]?.id,
|
folderId: importedFolders?.[i]?.id,
|
||||||
id,
|
id,
|
||||||
importFolderId: folderId,
|
importFolderId: folderId,
|
||||||
secrets: unique(secretsWithDuplicate, (el) => el.secretKey)
|
secrets: secretsWithDuplicate
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
parentImportedSecrets.push(...secretsWithDuplicate);
|
parentImportedSecrets.push(...secretsWithDuplicate);
|
||||||
@@ -258,7 +258,6 @@ export const fnSecretsV2FromImports = async ({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
/* eslint-enable */
|
/* eslint-enable */
|
||||||
|
|
||||||
if (expandSecretReferences) {
|
if (expandSecretReferences) {
|
||||||
await Promise.allSettled(
|
await Promise.allSettled(
|
||||||
processedImports.map((processedImport) => {
|
processedImports.map((processedImport) => {
|
||||||
|
|||||||
@@ -493,7 +493,7 @@ export const secretImportServiceFactory = ({
|
|||||||
|
|
||||||
ForbiddenError.from(permission).throwUnlessCan(
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
ProjectPermissionActions.Read,
|
ProjectPermissionActions.Read,
|
||||||
subject(ProjectPermissionSub.Secrets, {
|
subject(ProjectPermissionSub.SecretImports, {
|
||||||
environment: folder.environment.envSlug,
|
environment: folder.environment.envSlug,
|
||||||
secretPath: folderWithPath.path
|
secretPath: folderWithPath.path
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -114,12 +114,14 @@ export const secretV2BridgeServiceFactory = ({
|
|||||||
envId: referencesEnvironmentGroupBySlug[el.environment][0].id
|
envId: referencesEnvironmentGroupBySlug[el.environment][0].id
|
||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
const referencesFolderGroupByPath = groupBy(referredFolders.filter(Boolean), (i) => i?.path as string);
|
const referencesFolderGroupByPath = groupBy(referredFolders.filter(Boolean), (i) => `${i?.envId}-${i?.path}`);
|
||||||
const referredSecrets = await secretDAL.find({
|
const referredSecrets = await secretDAL.find({
|
||||||
$complex: {
|
$complex: {
|
||||||
operator: "or",
|
operator: "or",
|
||||||
value: references.map((el) => {
|
value: references.map((el) => {
|
||||||
const folderId = referencesFolderGroupByPath[el.secretPath][0]?.id;
|
const folderId =
|
||||||
|
referencesFolderGroupByPath[`${referencesEnvironmentGroupBySlug[el.environment][0].id}-${el.secretPath}`][0]
|
||||||
|
?.id;
|
||||||
if (!folderId) throw new BadRequestError({ message: `Reference path ${el.secretPath} doesn't exist` });
|
if (!folderId) throw new BadRequestError({ message: `Reference path ${el.secretPath} doesn't exist` });
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -140,6 +142,7 @@ export const secretV2BridgeServiceFactory = ({
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (referredSecrets.length !== references.length)
|
if (referredSecrets.length !== references.length)
|
||||||
throw new BadRequestError({ message: "Reference secret not found" });
|
throw new BadRequestError({ message: "Reference secret not found" });
|
||||||
|
|
||||||
@@ -356,6 +359,17 @@ export const secretV2BridgeServiceFactory = ({
|
|||||||
const tags = inputSecret.tagIds ? await secretTagDAL.find({ projectId, $in: { id: inputSecret.tagIds } }) : [];
|
const tags = inputSecret.tagIds ? await secretTagDAL.find({ projectId, $in: { id: inputSecret.tagIds } }) : [];
|
||||||
if ((inputSecret.tagIds || []).length !== tags.length) throw new NotFoundError({ message: "Tag not found" });
|
if ((inputSecret.tagIds || []).length !== tags.length) throw new NotFoundError({ message: "Tag not found" });
|
||||||
|
|
||||||
|
// now check with new ids
|
||||||
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
|
ProjectPermissionActions.Edit,
|
||||||
|
subject(ProjectPermissionSub.Secrets, {
|
||||||
|
environment,
|
||||||
|
secretPath,
|
||||||
|
secretName: inputSecret.secretName,
|
||||||
|
secretTags: tags?.map((el) => el.slug)
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
if (inputSecret.newSecretName) {
|
if (inputSecret.newSecretName) {
|
||||||
const doesNewNameSecretExist = await secretDAL.findOne({
|
const doesNewNameSecretExist = await secretDAL.findOne({
|
||||||
key: inputSecret.newSecretName,
|
key: inputSecret.newSecretName,
|
||||||
@@ -1229,6 +1243,19 @@ export const secretV2BridgeServiceFactory = ({
|
|||||||
if (tags.length !== sanitizedTagIds.length) throw new NotFoundError({ message: "Tag not found" });
|
if (tags.length !== sanitizedTagIds.length) throw new NotFoundError({ message: "Tag not found" });
|
||||||
const tagsGroupByID = groupBy(tags, (i) => i.id);
|
const tagsGroupByID = groupBy(tags, (i) => i.id);
|
||||||
|
|
||||||
|
// check again to avoid non authorized tags are removed
|
||||||
|
inputSecrets.forEach((el) => {
|
||||||
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
|
ProjectPermissionActions.Edit,
|
||||||
|
subject(ProjectPermissionSub.Secrets, {
|
||||||
|
environment,
|
||||||
|
secretPath,
|
||||||
|
secretName: el.secretKey,
|
||||||
|
secretTags: (el.tagIds || []).map((i) => tagsGroupByID[i][0].slug)
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
// now find any secret that needs to update its name
|
// now find any secret that needs to update its name
|
||||||
// same process as above
|
// same process as above
|
||||||
const secretsWithNewName = inputSecrets.filter(({ newSecretName }) => Boolean(newSecretName));
|
const secretsWithNewName = inputSecrets.filter(({ newSecretName }) => Boolean(newSecretName));
|
||||||
|
|||||||
Reference in New Issue
Block a user