ProjectOutputFileAgent.coffee 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. AuthorizationManager = require('../Authorization/AuthorizationManager')
  2. ProjectGetter = require('../Project/ProjectGetter')
  3. Settings = require 'settings-sharelatex'
  4. CompileManager = require '../Compile/CompileManager'
  5. ClsiManager = require '../Compile/ClsiManager'
  6. ProjectFileAgent = require './ProjectFileAgent'
  7. _ = require "underscore"
  8. {
  9. BadDataError,
  10. AccessDeniedError,
  11. BadEntityTypeError,
  12. OutputFileFetchFailedError
  13. } = require './LinkedFilesErrors'
  14. LinkedFilesHandler = require './LinkedFilesHandler'
  15. logger = require 'logger-sharelatex'
  16. module.exports = ProjectOutputFileAgent = {
  17. _prepare: (project_id, linkedFileData, user_id, callback=(err, linkedFileData)->) ->
  18. @_checkAuth project_id, linkedFileData, user_id, (err, allowed) =>
  19. return callback(err) if err?
  20. return callback(new AccessDeniedError()) if !allowed
  21. if !@_validate(linkedFileData)
  22. return callback(new BadDataError())
  23. callback(null, linkedFileData)
  24. createLinkedFile: (project_id, linkedFileData, name, parent_folder_id, user_id, callback) ->
  25. if !@_canCreate(linkedFileData)
  26. return callback(new AccessDeniedError())
  27. linkedFileData = @_sanitizeData(linkedFileData)
  28. @_prepare project_id, linkedFileData, user_id, (err, linkedFileData) =>
  29. return callback(err) if err?
  30. @_getFileStream linkedFileData, user_id, (err, readStream) =>
  31. return callback(err) if err?
  32. readStream.on "error", callback
  33. readStream.on "response", (response) =>
  34. if 200 <= response.statusCode < 300
  35. readStream.resume()
  36. LinkedFilesHandler.importFromStream project_id,
  37. readStream,
  38. linkedFileData,
  39. name,
  40. parent_folder_id,
  41. user_id,
  42. (err, file) ->
  43. return callback(err) if err?
  44. callback(null, file._id) # Created
  45. else
  46. err = new OutputFileFetchFailedError(
  47. "Output file fetch failed: #{linkedFileData.build_id}, #{linkedFileData.source_output_file_path}"
  48. )
  49. err.statusCode = response.statusCode
  50. callback(err)
  51. refreshLinkedFile: (project_id, linkedFileData, name, parent_folder_id, user_id, callback) ->
  52. @_prepare project_id, linkedFileData, user_id, (err, linkedFileData) =>
  53. return callback(err) if err?
  54. @_compileAndGetFileStream linkedFileData, user_id, (err, readStream, new_build_id) =>
  55. return callback(err) if err?
  56. readStream.on "error", callback
  57. readStream.on "response", (response) =>
  58. if 200 <= response.statusCode < 300
  59. readStream.resume()
  60. linkedFileData.build_id = new_build_id
  61. LinkedFilesHandler.importFromStream project_id,
  62. readStream,
  63. linkedFileData,
  64. name,
  65. parent_folder_id,
  66. user_id,
  67. (err, file) ->
  68. return callback(err) if err?
  69. callback(null, file._id) # Created
  70. else
  71. err = new OutputFileFetchFailedError(
  72. "Output file fetch failed: #{linkedFileData.build_id}, #{linkedFileData.source_output_file_path}"
  73. )
  74. err.statusCode = response.statusCode
  75. callback(err)
  76. _sanitizeData: (data) ->
  77. return {
  78. provider: data.provider,
  79. source_project_id: data.source_project_id,
  80. source_output_file_path: data.source_output_file_path,
  81. build_id: data.build_id
  82. }
  83. _canCreate: ProjectFileAgent._canCreate
  84. _getSourceProject: LinkedFilesHandler.getSourceProject
  85. _validate: (data) ->
  86. return (
  87. (data.source_project_id? || data.v1_source_doc_id?) &&
  88. data.source_output_file_path? &&
  89. data.build_id?
  90. )
  91. _checkAuth: (project_id, data, current_user_id, callback = (err, allowed)->) ->
  92. callback = _.once(callback)
  93. if !@_validate(data)
  94. return callback(new BadDataError())
  95. @_getSourceProject data, (err, project) ->
  96. return callback(err) if err?
  97. AuthorizationManager.canUserReadProject current_user_id,
  98. project._id,
  99. null,
  100. (err, canRead) ->
  101. return callback(err) if err?
  102. callback(null, canRead)
  103. _getFileStream: (linkedFileData, user_id, callback=(err, fileStream)->) ->
  104. callback = _.once(callback)
  105. { source_output_file_path, build_id } = linkedFileData
  106. @_getSourceProject linkedFileData, (err, project) ->
  107. return callback(err) if err?
  108. source_project_id = project._id
  109. ClsiManager.getOutputFileStream source_project_id,
  110. user_id,
  111. build_id,
  112. source_output_file_path,
  113. (err, readStream) ->
  114. return callback(err) if err?
  115. readStream.pause()
  116. callback(null, readStream)
  117. _compileAndGetFileStream: (linkedFileData, user_id, callback=(err, stream, build_id)->) ->
  118. callback = _.once(callback)
  119. { source_output_file_path } = linkedFileData
  120. @_getSourceProject linkedFileData, (err, project) ->
  121. return callback(err) if err?
  122. source_project_id = project._id
  123. CompileManager.compile source_project_id,
  124. user_id,
  125. {},
  126. (err, status, outputFiles) ->
  127. return callback(err) if err?
  128. if status != 'success'
  129. return callback(new OutputFileFetchFailedError())
  130. outputFile = _.find(
  131. outputFiles,
  132. (o) => o.path == source_output_file_path
  133. )
  134. if !outputFile?
  135. return callback(new OutputFileFetchFailedError())
  136. build_id = outputFile.build
  137. ClsiManager.getOutputFileStream source_project_id,
  138. user_id,
  139. build_id,
  140. source_output_file_path,
  141. (err, readStream) ->
  142. return callback(err) if err?
  143. readStream.pause()
  144. callback(null, readStream, build_id)
  145. }