const { Document } = require("../models/documents"); const { normalizePath, documentsPath, isWithin } = require("../utils/files"); const { reqBody } = require("../utils/http"); const { flexUserRoleValid, ROLES, } = require("../utils/middleware/multiUserProtected"); const { validatedRequest } = require("../utils/middleware/validatedRequest"); const fs = require("fs"); const path = require("path"); function documentEndpoints(app) { if (!app) return; app.post( "/document/create-folder", [validatedRequest, flexUserRoleValid([ROLES.admin, ROLES.manager])], async (request, response) => { try { const { name } = reqBody(request); const storagePath = path.join(documentsPath, normalizePath(name)); if (!isWithin(path.resolve(documentsPath), path.resolve(storagePath))) throw new Error("Invalid folder name."); if (fs.existsSync(storagePath)) { response.status(500).json({ success: false, message: "Folder by that name already exists", }); return; } fs.mkdirSync(storagePath, { recursive: true }); response.status(200).json({ success: true, message: null }); } catch (e) { console.error(e); response.status(500).json({ success: false, message: `Failed to create folder: ${e.message} `, }); } } ); app.post( "/document/move-files", [validatedRequest, flexUserRoleValid([ROLES.admin, ROLES.manager])], async (request, response) => { try { const { files } = reqBody(request); const docpaths = files.map(({ from }) => from); const documents = await Document.where({ docpath: { in: docpaths } }); const embeddedFiles = documents.map((doc) => doc.docpath); const moveableFiles = files.filter( ({ from }) => !embeddedFiles.includes(from) ); const movePromises = moveableFiles.map(({ from, to }) => { const sourcePath = path.join(documentsPath, normalizePath(from)); const destinationPath = path.join(documentsPath, normalizePath(to)); return new Promise((resolve, reject) => { if ( !isWithin(documentsPath, sourcePath) || !isWithin(documentsPath, destinationPath) ) return reject("Invalid file location"); fs.rename(sourcePath, destinationPath, (err) => { if (err) { console.error(`Error moving file ${from} to ${to}:`, err); reject(err); } else { resolve(); } }); }); }); Promise.all(movePromises) .then(() => { const unmovableCount = files.length - moveableFiles.length; if (unmovableCount > 0) { response.status(200).json({ success: true, message: `${unmovableCount}/${files.length} files not moved. Unembed them from all workspaces.`, }); } else { response.status(200).json({ success: true, message: null, }); } }) .catch((err) => { console.error("Error moving files:", err); response .status(500) .json({ success: false, message: "Failed to move some files." }); }); } catch (e) { console.error(e); response .status(500) .json({ success: false, message: "Failed to move files." }); } } ); } module.exports = { documentEndpoints };