LinkedFilesController.js 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. /* eslint-disable
  2. camelcase,
  3. max-len,
  4. no-unused-vars,
  5. */
  6. // TODO: This file was created by bulk-decaffeinate.
  7. // Fix any style issues and re-enable lint.
  8. /*
  9. * decaffeinate suggestions:
  10. * DS101: Remove unnecessary use of Array.from
  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 LinkedFilesController
  16. const SessionManager = require('../Authentication/SessionManager')
  17. const EditorController = require('../Editor/EditorController')
  18. const ProjectLocator = require('../Project/ProjectLocator')
  19. const Settings = require('@overleaf/settings')
  20. const logger = require('@overleaf/logger')
  21. const _ = require('underscore')
  22. const LinkedFilesHandler = require('./LinkedFilesHandler')
  23. const {
  24. CompileFailedError,
  25. UrlFetchFailedError,
  26. InvalidUrlError,
  27. OutputFileFetchFailedError,
  28. AccessDeniedError,
  29. BadEntityTypeError,
  30. BadDataError,
  31. ProjectNotFoundError,
  32. V1ProjectNotFoundError,
  33. SourceFileNotFoundError,
  34. NotOriginalImporterError,
  35. FeatureNotAvailableError,
  36. RemoteServiceError,
  37. FileCannotRefreshError,
  38. } = require('./LinkedFilesErrors')
  39. const Modules = require('../../infrastructure/Modules')
  40. const { plainTextResponse } = require('../../infrastructure/Response')
  41. module.exports = LinkedFilesController = {
  42. Agents: _.extend(
  43. {
  44. url: require('./UrlAgent'),
  45. project_file: require('./ProjectFileAgent'),
  46. project_output_file: require('./ProjectOutputFileAgent'),
  47. },
  48. Modules.linkedFileAgentsIncludes()
  49. ),
  50. _getAgent(provider) {
  51. if (
  52. !Object.prototype.hasOwnProperty.call(
  53. LinkedFilesController.Agents,
  54. provider
  55. )
  56. ) {
  57. return null
  58. }
  59. if (!Array.from(Settings.enabledLinkedFileTypes).includes(provider)) {
  60. return null
  61. }
  62. return LinkedFilesController.Agents[provider]
  63. },
  64. createLinkedFile(req, res, next) {
  65. const { project_id } = req.params
  66. const { name, provider, data, parent_folder_id } = req.body
  67. const user_id = SessionManager.getLoggedInUserId(req.session)
  68. const Agent = LinkedFilesController._getAgent(provider)
  69. if (Agent == null) {
  70. return res.sendStatus(400)
  71. }
  72. data.provider = provider
  73. return Agent.createLinkedFile(
  74. project_id,
  75. data,
  76. name,
  77. parent_folder_id,
  78. user_id,
  79. function (err, newFileId) {
  80. if (err != null) {
  81. return LinkedFilesController.handleError(err, req, res, next)
  82. }
  83. return res.json({ new_file_id: newFileId })
  84. }
  85. )
  86. },
  87. refreshLinkedFile(req, res, next) {
  88. const { project_id, file_id } = req.params
  89. const user_id = SessionManager.getLoggedInUserId(req.session)
  90. return LinkedFilesHandler.getFileById(
  91. project_id,
  92. file_id,
  93. function (err, file, path, parentFolder) {
  94. if (err != null) {
  95. return next(err)
  96. }
  97. if (file == null) {
  98. return res.sendStatus(404)
  99. }
  100. const { name } = file
  101. const { linkedFileData } = file
  102. if (
  103. linkedFileData == null ||
  104. (linkedFileData != null ? linkedFileData.provider : undefined) == null
  105. ) {
  106. return res.sendStatus(409)
  107. }
  108. const { provider } = linkedFileData
  109. const parent_folder_id = parentFolder._id
  110. const Agent = LinkedFilesController._getAgent(provider)
  111. if (Agent == null) {
  112. return res.sendStatus(400)
  113. }
  114. return Agent.refreshLinkedFile(
  115. project_id,
  116. linkedFileData,
  117. name,
  118. parent_folder_id,
  119. user_id,
  120. function (err, newFileId) {
  121. if (err != null) {
  122. return LinkedFilesController.handleError(err, req, res, next)
  123. }
  124. return res.json({ new_file_id: newFileId })
  125. }
  126. )
  127. }
  128. )
  129. },
  130. handleError(error, req, res, next) {
  131. if (error instanceof AccessDeniedError) {
  132. res.status(403)
  133. plainTextResponse(res, 'You do not have access to this project')
  134. } else if (error instanceof BadDataError) {
  135. res.status(400)
  136. plainTextResponse(res, 'The submitted data is not valid')
  137. } else if (error instanceof BadEntityTypeError) {
  138. res.status(400)
  139. plainTextResponse(res, 'The file is the wrong type')
  140. } else if (error instanceof SourceFileNotFoundError) {
  141. res.status(404)
  142. plainTextResponse(res, 'Source file not found')
  143. } else if (error instanceof ProjectNotFoundError) {
  144. res.status(404)
  145. plainTextResponse(res, 'Project not found')
  146. } else if (error instanceof V1ProjectNotFoundError) {
  147. res.status(409)
  148. plainTextResponse(
  149. res,
  150. 'Sorry, the source project is not yet imported to Overleaf v2. Please import it to Overleaf v2 to refresh this file'
  151. )
  152. } else if (error instanceof CompileFailedError) {
  153. res.status(422)
  154. plainTextResponse(
  155. res,
  156. res.locals.translate('generic_linked_file_compile_error')
  157. )
  158. } else if (error instanceof OutputFileFetchFailedError) {
  159. res.status(404)
  160. plainTextResponse(res, 'Could not get output file')
  161. } else if (error instanceof UrlFetchFailedError) {
  162. res.status(422)
  163. plainTextResponse(
  164. res,
  165. `Your URL could not be reached (${error.statusCode} status code). Please check it and try again.`
  166. )
  167. } else if (error instanceof InvalidUrlError) {
  168. res.status(422)
  169. plainTextResponse(
  170. res,
  171. 'Your URL is not valid. Please check it and try again.'
  172. )
  173. } else if (error instanceof NotOriginalImporterError) {
  174. res.status(400)
  175. plainTextResponse(
  176. res,
  177. 'You are not the user who originally imported this file'
  178. )
  179. } else if (error instanceof FeatureNotAvailableError) {
  180. res.status(400)
  181. plainTextResponse(res, 'This feature is not enabled on your account')
  182. } else if (error instanceof RemoteServiceError) {
  183. if (error.info?.statusCode === 403) {
  184. res.status(400).json({ relink: true })
  185. } else {
  186. res.status(502)
  187. plainTextResponse(res, 'The remote service produced an error')
  188. }
  189. } else if (error instanceof FileCannotRefreshError) {
  190. res.status(400)
  191. plainTextResponse(res, 'This file cannot be refreshed')
  192. } else if (error.message === 'project_has_too_many_files') {
  193. res.status(400)
  194. plainTextResponse(res, 'too many files')
  195. } else if (/\bECONNREFUSED\b/.test(error.message)) {
  196. res.status(500)
  197. plainTextResponse(res, 'Importing references is not currently available')
  198. } else {
  199. next(error)
  200. }
  201. },
  202. }