124_webcalibre2/src/app/dashboard/actions.ts

116 lines
3.3 KiB
TypeScript
Raw Normal View History

'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.");
}
}