'use server'; import { auth } from "@/auth"; import { prisma } from "@/lib/prisma"; import { revalidatePath } from "next/cache"; import { getFreshAccessToken } from "@/lib/auth-utils"; /** * 1. FETCH: Get all file nodes */ export async function getFileNodes() { try { const nodes = await prisma.fileNode.findMany({ orderBy: { updatedAt: 'desc', }, }); return nodes; } catch (error) { console.error("Error fetching file nodes:", error); return []; } } /** * 2. DELETE: Remove from OneDrive and Database * Improved to ensure DB removal even if OneDrive API returns errors. */ export async function deleteFileAction(fileId: string) { const session = await auth(); if (!session?.user?.id) throw new Error("Unauthorized"); // 1. Find the node to check permissions const node = await prisma.fileNode.findUnique({ where: { id: fileId }, }); if (!node) { // If not in DB, trigger a refresh anyway to clear the UI revalidatePath("/dashboard"); return { success: true, message: "Item already removed from database" }; } // @ts-ignore - role added via auth callbacks const isAdmin = session.user.role === "ADMIN"; const isOwner = node.ownerId === session.user.id; if (!isAdmin && !isOwner) { throw new Error("Permission Denied: You do not have authority to delete this item."); } if (node.isFolder && !isAdmin) { throw new Error("Security Restriction: Only Administrators can delete folders."); } // 2. OneDrive Deletion Attempt try { const accessToken = await getFreshAccessToken(session.user.id); if (accessToken) { const rootFolder = "WebCalibre"; // We target the folder on OneDrive by the ID stored in our DB const onedrivePath = `https://graph.microsoft.com/v1.0/me/drive/root:/${rootFolder}/${node.id}`; const onedriveRes = await fetch(onedrivePath, { method: "DELETE", headers: { Authorization: `Bearer ${accessToken}` }, }); if (!onedriveRes.ok && onedriveRes.status !== 404) { const errData = await onedriveRes.json().catch(() => ({})); console.warn("OneDrive Deletion Warning (Cloud record might still exist):", errData); } } } catch (cloudError) { // We catch cloud errors but DO NOT throw them, so we can proceed to delete the DB record console.error("Cloud communication failed, proceeding with DB cleanup:", cloudError); } // 3. Database Deletion (The Source of Truth for your UI) try { await prisma.fileNode.delete({ where: { id: fileId } }); revalidatePath("/dashboard"); revalidatePath("/upload"); return { success: true }; } catch (dbError: any) { console.error("Database deletion failed:", dbError); throw new Error("Failed to remove the record from the database."); } } /** * 3. MOVE: Assign file to folder or folder to another folder */ export async function moveNodeAction(nodeId: string, newParentId: string | null) { const session = await auth(); if (!session?.user?.id) throw new Error("Unauthorized"); if (nodeId === newParentId) throw new Error("Cannot move to self."); try { await prisma.fileNode.update({ where: { id: nodeId }, data: { parentId: newParentId } }); revalidatePath("/dashboard"); return { success: true }; } catch (error) { throw new Error("Move failed."); } }