You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

111 lines
3.6 KiB

11 months ago
  1. const { Document } = require("../models/documents");
  2. const { normalizePath, documentsPath, isWithin } = require("../utils/files");
  3. const { reqBody } = require("../utils/http");
  4. const {
  5. flexUserRoleValid,
  6. ROLES,
  7. } = require("../utils/middleware/multiUserProtected");
  8. const { validatedRequest } = require("../utils/middleware/validatedRequest");
  9. const fs = require("fs");
  10. const path = require("path");
  11. function documentEndpoints(app) {
  12. if (!app) return;
  13. app.post(
  14. "/document/create-folder",
  15. [validatedRequest, flexUserRoleValid([ROLES.admin, ROLES.manager])],
  16. async (request, response) => {
  17. try {
  18. const { name } = reqBody(request);
  19. const storagePath = path.join(documentsPath, normalizePath(name));
  20. if (!isWithin(path.resolve(documentsPath), path.resolve(storagePath)))
  21. throw new Error("Invalid folder name.");
  22. if (fs.existsSync(storagePath)) {
  23. response.status(500).json({
  24. success: false,
  25. message: "Folder by that name already exists",
  26. });
  27. return;
  28. }
  29. fs.mkdirSync(storagePath, { recursive: true });
  30. response.status(200).json({ success: true, message: null });
  31. } catch (e) {
  32. console.error(e);
  33. response.status(500).json({
  34. success: false,
  35. message: `Failed to create folder: ${e.message} `,
  36. });
  37. }
  38. }
  39. );
  40. app.post(
  41. "/document/move-files",
  42. [validatedRequest, flexUserRoleValid([ROLES.admin, ROLES.manager])],
  43. async (request, response) => {
  44. try {
  45. const { files } = reqBody(request);
  46. const docpaths = files.map(({ from }) => from);
  47. const documents = await Document.where({ docpath: { in: docpaths } });
  48. const embeddedFiles = documents.map((doc) => doc.docpath);
  49. const moveableFiles = files.filter(
  50. ({ from }) => !embeddedFiles.includes(from)
  51. );
  52. const movePromises = moveableFiles.map(({ from, to }) => {
  53. const sourcePath = path.join(documentsPath, normalizePath(from));
  54. const destinationPath = path.join(documentsPath, normalizePath(to));
  55. return new Promise((resolve, reject) => {
  56. if (
  57. !isWithin(documentsPath, sourcePath) ||
  58. !isWithin(documentsPath, destinationPath)
  59. )
  60. return reject("Invalid file location");
  61. fs.rename(sourcePath, destinationPath, (err) => {
  62. if (err) {
  63. console.error(`Error moving file ${from} to ${to}:`, err);
  64. reject(err);
  65. } else {
  66. resolve();
  67. }
  68. });
  69. });
  70. });
  71. Promise.all(movePromises)
  72. .then(() => {
  73. const unmovableCount = files.length - moveableFiles.length;
  74. if (unmovableCount > 0) {
  75. response.status(200).json({
  76. success: true,
  77. message: `${unmovableCount}/${files.length} files not moved. Unembed them from all workspaces.`,
  78. });
  79. } else {
  80. response.status(200).json({
  81. success: true,
  82. message: null,
  83. });
  84. }
  85. })
  86. .catch((err) => {
  87. console.error("Error moving files:", err);
  88. response
  89. .status(500)
  90. .json({ success: false, message: "Failed to move some files." });
  91. });
  92. } catch (e) {
  93. console.error(e);
  94. response
  95. .status(500)
  96. .json({ success: false, message: "Failed to move files." });
  97. }
  98. }
  99. );
  100. }
  101. module.exports = { documentEndpoints };