| 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 }; | |