mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
234 lines
6.4 KiB
TypeScript
234 lines
6.4 KiB
TypeScript
import { Request, Response } from "express";
|
|
import { Secret } from "../../models";
|
|
import Folder from "../../models/folder";
|
|
import { BadRequestError } from "../../utils/errors";
|
|
import {
|
|
appendFolder,
|
|
deleteFolderById,
|
|
getAllFolderIds,
|
|
searchByFolderIdWithDir,
|
|
searchByFolderId,
|
|
validateFolderName,
|
|
generateFolderId,
|
|
getParentFromFolderId,
|
|
} from "../../services/FolderService";
|
|
import { ADMIN, MEMBER } from "../../variables";
|
|
import { validateMembership } from "../../helpers/membership";
|
|
import { FolderVersion } from "../../ee/models";
|
|
import { EESecretService } from "../../ee/services";
|
|
|
|
// TODO
|
|
// verify workspace id/environment
|
|
export const createFolder = async (req: Request, res: Response) => {
|
|
const { workspaceId, environment, folderName, parentFolderId } = req.body;
|
|
if (!validateFolderName(folderName)) {
|
|
throw BadRequestError({
|
|
message: "Folder name cannot contain spaces. Only underscore and dashes",
|
|
});
|
|
}
|
|
|
|
const folders = await Folder.findOne({
|
|
workspace: workspaceId,
|
|
environment,
|
|
}).lean();
|
|
// space has no folders initialized
|
|
if (!folders) {
|
|
const id = generateFolderId();
|
|
const folder = new Folder({
|
|
workspace: workspaceId,
|
|
environment,
|
|
nodes: {
|
|
id: "root",
|
|
name: "root",
|
|
version: 1,
|
|
children: [{ id, name: folderName, children: [], version: 1 }],
|
|
},
|
|
});
|
|
await folder.save();
|
|
const folderVersion = new FolderVersion({
|
|
workspace: workspaceId,
|
|
environment,
|
|
nodes: folder.nodes,
|
|
});
|
|
await folderVersion.save();
|
|
return res.json({ folder: { id, name: folderName } });
|
|
}
|
|
|
|
const folder = appendFolder(folders.nodes, { folderName, parentFolderId });
|
|
await Folder.findByIdAndUpdate(folders._id, folders);
|
|
|
|
const parentFolder = searchByFolderId(folders.nodes, parentFolderId);
|
|
const folderVersion = new FolderVersion({
|
|
workspace: workspaceId,
|
|
environment,
|
|
// root condition
|
|
nodes: parentFolder || folders.nodes,
|
|
});
|
|
await folderVersion.save();
|
|
|
|
return res.json({ folder });
|
|
};
|
|
|
|
export const updateFolderById = async (req: Request, res: Response) => {
|
|
const { folderId } = req.params;
|
|
const { name, workspaceId, environment } = req.body;
|
|
|
|
const folders = await Folder.findOne({ workspace: workspaceId, environment });
|
|
if (!folders) {
|
|
throw BadRequestError({ message: "The folder doesn't exist" });
|
|
}
|
|
|
|
// check that user is a member of the workspace
|
|
await validateMembership({
|
|
userId: req.user._id.toString(),
|
|
workspaceId,
|
|
acceptedRoles: [ADMIN, MEMBER],
|
|
});
|
|
|
|
const parentFolder = getParentFromFolderId(folders.nodes, folderId);
|
|
if (!parentFolder) {
|
|
throw BadRequestError({ message: "The folder doesn't exist" });
|
|
}
|
|
const folder = parentFolder.children.find(({ id }) => id === folderId);
|
|
if (!folder) {
|
|
throw BadRequestError({ message: "The folder doesn't exist" });
|
|
}
|
|
|
|
parentFolder.version += 1;
|
|
folder.name = name;
|
|
folder.version += 1;
|
|
|
|
await Folder.findByIdAndUpdate(folders._id, folders);
|
|
const folderVersion = new FolderVersion({
|
|
workspace: workspaceId,
|
|
environment,
|
|
nodes: parentFolder,
|
|
});
|
|
await folderVersion.save();
|
|
|
|
// decision to take snapshot ot not
|
|
const secretCount = await Secret.count({
|
|
workspace: workspaceId,
|
|
environment,
|
|
folder: folderId,
|
|
});
|
|
if (secretCount || folder.children.length) {
|
|
await EESecretService.takeSecretSnapshot({
|
|
workspaceId,
|
|
environment,
|
|
folderId: parentFolder.name === "root" ? undefined : parentFolder.id,
|
|
});
|
|
}
|
|
|
|
return res.json({
|
|
message: "Successfully updated folder",
|
|
folder: { name: folder.name, id: folder.id },
|
|
});
|
|
};
|
|
|
|
export const deleteFolder = async (req: Request, res: Response) => {
|
|
const { folderId } = req.params;
|
|
const { workspaceId, environment } = req.body;
|
|
|
|
const folders = await Folder.findOne({ workspace: workspaceId, environment });
|
|
if (!folders) {
|
|
throw BadRequestError({ message: "The folder doesn't exist" });
|
|
}
|
|
|
|
// check that user is a member of the workspace
|
|
await validateMembership({
|
|
userId: req.user._id.toString(),
|
|
workspaceId,
|
|
acceptedRoles: [ADMIN, MEMBER],
|
|
});
|
|
|
|
const delOp = deleteFolderById(folders.nodes, folderId);
|
|
if (!delOp) {
|
|
throw BadRequestError({ message: "The folder doesn't exist" });
|
|
}
|
|
const { deletedNode: delFolder, parent: parentFolder } = delOp;
|
|
|
|
const delFolderIds = getAllFolderIds(delFolder);
|
|
|
|
// take a pre-delete snapshot if there are secrets inside the folders
|
|
const secretCount = await Secret.count({
|
|
workspace: workspaceId,
|
|
environment,
|
|
folder: folderId,
|
|
});
|
|
|
|
if (secretCount || delFolder.children.length) {
|
|
await EESecretService.takeSecretSnapshot({
|
|
workspaceId,
|
|
environment,
|
|
folderId: parentFolder.id,
|
|
});
|
|
}
|
|
|
|
await Folder.findByIdAndUpdate(folders._id, folders);
|
|
const folderVersion = new FolderVersion({
|
|
workspace: workspaceId,
|
|
environment,
|
|
nodes: parentFolder,
|
|
});
|
|
await folderVersion.save();
|
|
if (delFolderIds.length) {
|
|
await Secret.deleteMany({
|
|
folder: { $in: delFolderIds.map(({ id }) => id) },
|
|
workspace: workspaceId,
|
|
environment,
|
|
});
|
|
}
|
|
|
|
// post delete snapshot
|
|
await EESecretService.takeSecretSnapshot({
|
|
workspaceId,
|
|
environment,
|
|
folderId: parentFolder.id,
|
|
});
|
|
|
|
res.send({ message: "successfully deleted folders", folders: delFolderIds });
|
|
};
|
|
|
|
// TODO: validate workspace
|
|
export const getFolders = async (req: Request, res: Response) => {
|
|
const { workspaceId, environment, parentFolderId } = req.query as {
|
|
workspaceId: string;
|
|
environment: string;
|
|
parentFolderId?: string;
|
|
};
|
|
|
|
const folders = await Folder.findOne({ workspace: workspaceId, environment });
|
|
if (!folders) {
|
|
res.send({ folders: [], dir: [] });
|
|
return;
|
|
}
|
|
|
|
// check that user is a member of the workspace
|
|
await validateMembership({
|
|
userId: req.user._id.toString(),
|
|
workspaceId,
|
|
acceptedRoles: [ADMIN, MEMBER],
|
|
});
|
|
|
|
if (!parentFolderId) {
|
|
const rootFolders = folders.nodes.children.map(({ id, name }) => ({
|
|
id,
|
|
name,
|
|
}));
|
|
res.send({ folders: rootFolders });
|
|
return;
|
|
}
|
|
|
|
const folderBySearch = searchByFolderIdWithDir(folders.nodes, parentFolderId);
|
|
if (!folderBySearch) {
|
|
throw BadRequestError({ message: "The folder doesn't exist" });
|
|
}
|
|
const { folder, dir } = folderBySearch;
|
|
|
|
res.send({
|
|
folders: folder.children.map(({ id, name }) => ({ id, name })),
|
|
dir,
|
|
});
|
|
};
|