mirror of
https://github.com/hanzo-apps/dataroom.git
synced 2026-11-02 22:04:20 +00:00
265 lines
7.1 KiB
TypeScript
265 lines
7.1 KiB
TypeScript
import { NextApiRequest, NextApiResponse } from "next";
|
|
|
|
import { authOptions } from "@/pages/api/auth/[...nextauth]";
|
|
import { ItemType } from "@prisma/client";
|
|
import { getServerSession } from "next-auth/next";
|
|
|
|
import prisma from "@/lib/prisma";
|
|
import { CustomUser } from "@/lib/types";
|
|
|
|
// Helper function to get parent folder IDs for a given document in a dataroom
|
|
async function getParentFolderIds(
|
|
dataroomId: string,
|
|
documentId: string,
|
|
): Promise<string[]> {
|
|
// Get the dataroom document to find which folder it's in
|
|
const dataroomDocument = await prisma.dataroomDocument.findUnique({
|
|
where: { id: documentId },
|
|
select: { folderId: true },
|
|
});
|
|
|
|
if (!dataroomDocument?.folderId) {
|
|
return []; // Document is at root level
|
|
}
|
|
|
|
// Get the folder and walk up the hierarchy
|
|
const parentFolders: string[] = [];
|
|
let currentFolderId: string | null = dataroomDocument.folderId;
|
|
|
|
while (currentFolderId) {
|
|
parentFolders.push(currentFolderId);
|
|
|
|
const folder: { parentId: string | null } | null =
|
|
await prisma.dataroomFolder.findUnique({
|
|
where: { id: currentFolderId },
|
|
select: { parentId: true },
|
|
});
|
|
|
|
currentFolderId = folder?.parentId || null;
|
|
}
|
|
|
|
return parentFolders;
|
|
}
|
|
|
|
// Helper function to ensure parent folders are visible when child documents are made visible
|
|
async function ensureParentFoldersVisible(
|
|
dataroomId: string,
|
|
groupId: string,
|
|
permissions: Record<
|
|
string,
|
|
{ itemType: ItemType; view: boolean; download: boolean }
|
|
>,
|
|
): Promise<void> {
|
|
const foldersToMakeVisible = new Set<string>();
|
|
|
|
// Find all documents that are being made visible
|
|
const visibleDocuments = Object.entries(permissions)
|
|
.filter(
|
|
([_, perm]) => perm.itemType === ItemType.DATAROOM_DOCUMENT && perm.view,
|
|
)
|
|
.map(([itemId, _]) => itemId);
|
|
|
|
// Get parent folder IDs for all visible documents
|
|
for (const documentId of visibleDocuments) {
|
|
const parentFolders = await getParentFolderIds(dataroomId, documentId);
|
|
parentFolders.forEach((folderId) => foldersToMakeVisible.add(folderId));
|
|
}
|
|
|
|
// Also handle folders that are being made visible - ensure their parent folders are visible too
|
|
const visibleFolders = Object.entries(permissions)
|
|
.filter(
|
|
([_, perm]) => perm.itemType === ItemType.DATAROOM_FOLDER && perm.view,
|
|
)
|
|
.map(([itemId, _]) => itemId);
|
|
|
|
for (const folderId of visibleFolders) {
|
|
let currentFolderId: string | null = folderId;
|
|
|
|
while (currentFolderId) {
|
|
const folder: { parentId: string | null } | null =
|
|
await prisma.dataroomFolder.findUnique({
|
|
where: { id: currentFolderId },
|
|
select: { parentId: true },
|
|
});
|
|
|
|
if (folder?.parentId) {
|
|
foldersToMakeVisible.add(folder.parentId);
|
|
currentFolderId = folder.parentId;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Update or create permissions for parent folders to make them visible
|
|
if (foldersToMakeVisible.size > 0) {
|
|
const foldersToUpdate = Array.from(foldersToMakeVisible);
|
|
|
|
await prisma.$transaction(async (tx) => {
|
|
for (const folderId of foldersToUpdate) {
|
|
await tx.viewerGroupAccessControls.upsert({
|
|
where: {
|
|
groupId_itemId: {
|
|
groupId: groupId,
|
|
itemId: folderId,
|
|
},
|
|
},
|
|
create: {
|
|
groupId: groupId,
|
|
itemId: folderId,
|
|
itemType: ItemType.DATAROOM_FOLDER,
|
|
canView: true,
|
|
canDownload: false,
|
|
},
|
|
update: {
|
|
canView: true, // Always ensure parent folders are visible
|
|
// Don't change canDownload - preserve existing setting
|
|
},
|
|
});
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
export default async function handler(
|
|
req: NextApiRequest,
|
|
res: NextApiResponse,
|
|
) {
|
|
if (req.method !== "POST") {
|
|
return res.status(405).json({ message: "Method not allowed" });
|
|
}
|
|
|
|
// POST /api/teams/:teamId/datarooms/:id/groups/:groupId/permissions
|
|
const session = await getServerSession(req, res, authOptions);
|
|
if (!session) {
|
|
res.status(401).end("Unauthorized");
|
|
return;
|
|
}
|
|
|
|
const userId = (session.user as CustomUser).id;
|
|
const {
|
|
teamId,
|
|
id: dataroomId,
|
|
groupId,
|
|
} = req.query as {
|
|
teamId: string;
|
|
id: string;
|
|
groupId: string;
|
|
};
|
|
|
|
try {
|
|
const { permissions } = req.body as {
|
|
permissions: Record<
|
|
string,
|
|
{ itemType: ItemType; view: boolean; download: boolean }
|
|
>;
|
|
};
|
|
|
|
// Validate input
|
|
if (!permissions) {
|
|
return res.status(400).json({ message: "Missing required fields" });
|
|
}
|
|
|
|
// Check if the user is part of the team
|
|
const team = await prisma.team.findUnique({
|
|
where: {
|
|
id: teamId,
|
|
users: {
|
|
some: {
|
|
userId,
|
|
},
|
|
},
|
|
},
|
|
});
|
|
|
|
if (!team) {
|
|
return res.status(403).json({ message: "Unauthorized" });
|
|
}
|
|
|
|
const existingPermissions = await prisma.viewerGroupAccessControls.findMany(
|
|
{
|
|
where: {
|
|
groupId,
|
|
group: { dataroomId },
|
|
},
|
|
select: { itemId: true, itemType: true },
|
|
},
|
|
);
|
|
|
|
const existingSet = new Set(
|
|
existingPermissions.map((p) => `${p.itemId}-${p.itemType}`),
|
|
);
|
|
|
|
const toUpdate: {
|
|
groupId: string;
|
|
itemId: string;
|
|
itemType: ItemType;
|
|
canView: boolean;
|
|
canDownload: boolean;
|
|
}[] = [];
|
|
const toCreate: {
|
|
groupId: string;
|
|
itemId: string;
|
|
itemType: ItemType;
|
|
canView: boolean;
|
|
canDownload: boolean;
|
|
}[] = [];
|
|
|
|
Object.entries(permissions).forEach(([itemId, itemPermissions]) => {
|
|
const key = `${itemId}-${itemPermissions.itemType}`;
|
|
const data = {
|
|
groupId,
|
|
itemId,
|
|
itemType: itemPermissions.itemType,
|
|
canView: itemPermissions.view,
|
|
canDownload: itemPermissions.download,
|
|
};
|
|
|
|
if (existingSet.has(key)) {
|
|
toUpdate.push(data);
|
|
} else {
|
|
toCreate.push(data);
|
|
}
|
|
});
|
|
|
|
console.log("toUpdate", toUpdate);
|
|
console.log("toCreate", toCreate);
|
|
|
|
// Perform operations
|
|
await prisma.$transaction(async (tx) => {
|
|
if (toUpdate.length > 0) {
|
|
await Promise.all(
|
|
toUpdate.map((item) =>
|
|
tx.viewerGroupAccessControls.update({
|
|
where: {
|
|
groupId_itemId: {
|
|
groupId: item.groupId,
|
|
itemId: item.itemId,
|
|
},
|
|
},
|
|
data: {
|
|
canView: item.canView,
|
|
canDownload: item.canDownload,
|
|
},
|
|
}),
|
|
),
|
|
);
|
|
}
|
|
|
|
if (toCreate.length > 0) {
|
|
await tx.viewerGroupAccessControls.createMany({
|
|
data: toCreate,
|
|
});
|
|
}
|
|
});
|
|
|
|
// After saving permissions, ensure parent folders are visible for any items that were made visible
|
|
await ensureParentFoldersVisible(dataroomId, groupId, permissions);
|
|
|
|
res.status(200).json({ message: "Permissions updated successfully" });
|
|
} catch (error) {
|
|
console.error("Error updating permissions:", error);
|
|
res.status(500).json({ message: "Internal server error" });
|
|
}
|
|
}
|