RestoreManager.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. /* eslint-disable
  2. camelcase,
  3. n/handle-callback-err,
  4. max-len,
  5. no-unused-vars,
  6. */
  7. // TODO: This file was created by bulk-decaffeinate.
  8. // Fix any style issues and re-enable lint.
  9. /*
  10. * decaffeinate suggestions:
  11. * DS102: Remove unnecessary code created because of implicit returns
  12. * DS207: Consider shorter variations of null checks
  13. * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  14. */
  15. let RestoreManager
  16. const Settings = require('@overleaf/settings')
  17. const Path = require('path')
  18. const FileWriter = require('../../infrastructure/FileWriter')
  19. const FileSystemImportManager = require('../Uploads/FileSystemImportManager')
  20. const ProjectEntityHandler = require('../Project/ProjectEntityHandler')
  21. const EditorController = require('../Editor/EditorController')
  22. const Errors = require('../Errors/Errors')
  23. const moment = require('moment')
  24. module.exports = RestoreManager = {
  25. restoreDocFromDeletedDoc(user_id, project_id, doc_id, name, callback) {
  26. // This is the legacy method for restoring a doc from the SL track-changes/deletedDocs system.
  27. // It looks up the deleted doc's contents, and then creates a new doc with the same content.
  28. // We don't actually remove the deleted doc entry, just create a new one from its lines.
  29. if (callback == null) {
  30. callback = function () {}
  31. }
  32. return ProjectEntityHandler.getDoc(
  33. project_id,
  34. doc_id,
  35. { include_deleted: true },
  36. function (error, lines) {
  37. if (error != null) {
  38. return callback(error)
  39. }
  40. const addDocWithName = (name, callback) =>
  41. EditorController.addDoc(
  42. project_id,
  43. null,
  44. name,
  45. lines,
  46. 'restore',
  47. user_id,
  48. callback
  49. )
  50. return RestoreManager._addEntityWithUniqueName(
  51. addDocWithName,
  52. name,
  53. callback
  54. )
  55. }
  56. )
  57. },
  58. restoreFileFromV2(user_id, project_id, version, pathname, callback) {
  59. if (callback == null) {
  60. callback = function () {}
  61. }
  62. return RestoreManager._writeFileVersionToDisk(
  63. project_id,
  64. version,
  65. pathname,
  66. function (error, fsPath) {
  67. if (error != null) {
  68. return callback(error)
  69. }
  70. const basename = Path.basename(pathname)
  71. let dirname = Path.dirname(pathname)
  72. if (dirname === '.') {
  73. // no directory
  74. dirname = ''
  75. }
  76. return RestoreManager._findOrCreateFolder(
  77. project_id,
  78. dirname,
  79. function (error, parent_folder_id) {
  80. if (error != null) {
  81. return callback(error)
  82. }
  83. const addEntityWithName = (name, callback) =>
  84. FileSystemImportManager.addEntity(
  85. user_id,
  86. project_id,
  87. parent_folder_id,
  88. name,
  89. fsPath,
  90. false,
  91. callback
  92. )
  93. return RestoreManager._addEntityWithUniqueName(
  94. addEntityWithName,
  95. basename,
  96. callback
  97. )
  98. }
  99. )
  100. }
  101. )
  102. },
  103. _findOrCreateFolder(project_id, dirname, callback) {
  104. if (callback == null) {
  105. callback = function () {}
  106. }
  107. return EditorController.mkdirp(
  108. project_id,
  109. dirname,
  110. function (error, newFolders, lastFolder) {
  111. if (error != null) {
  112. return callback(error)
  113. }
  114. return callback(null, lastFolder != null ? lastFolder._id : undefined)
  115. }
  116. )
  117. },
  118. _addEntityWithUniqueName(addEntityWithName, basename, callback) {
  119. if (callback == null) {
  120. callback = function () {}
  121. }
  122. return addEntityWithName(basename, function (error, entity) {
  123. if (error != null) {
  124. if (error instanceof Errors.InvalidNameError) {
  125. // likely a duplicate name, so try with a prefix
  126. const date = moment(new Date()).format('Do MMM YY H:mm:ss')
  127. // Move extension to the end so the file type is preserved
  128. const extension = Path.extname(basename)
  129. basename = Path.basename(basename, extension)
  130. basename = `${basename} (Restored on ${date})`
  131. if (extension !== '') {
  132. basename = `${basename}${extension}`
  133. }
  134. return addEntityWithName(basename, callback)
  135. } else {
  136. return callback(error)
  137. }
  138. } else {
  139. return callback(null, entity)
  140. }
  141. })
  142. },
  143. _writeFileVersionToDisk(project_id, version, pathname, callback) {
  144. if (callback == null) {
  145. callback = function () {}
  146. }
  147. const url = `${
  148. Settings.apis.project_history.url
  149. }/project/${project_id}/version/${version}/${encodeURIComponent(pathname)}`
  150. return FileWriter.writeUrlToDisk(project_id, url, callback)
  151. },
  152. }