overleaf/services/web/app/coffee/Features/LinkedFiles/ProjectOutputFileAgent.coffee

164 lines
5.3 KiB
CoffeeScript

AuthorizationManager = require('../Authorization/AuthorizationManager')
ProjectGetter = require('../Project/ProjectGetter')
Settings = require 'settings-sharelatex'
CompileManager = require '../Compile/CompileManager'
ClsiManager = require '../Compile/ClsiManager'
ProjectFileAgent = require './ProjectFileAgent'
_ = require "underscore"
{
BadDataError,
AccessDeniedError,
BadEntityTypeError,
OutputFileFetchFailedError
} = require './LinkedFilesErrors'
LinkedFilesHandler = require './LinkedFilesHandler'
logger = require 'logger-sharelatex'
module.exports = ProjectOutputFileAgent = {
_prepare: (project_id, linkedFileData, user_id, callback=(err, linkedFileData)->) ->
@_checkAuth project_id, linkedFileData, user_id, (err, allowed) =>
return callback(err) if err?
return callback(new AccessDeniedError()) if !allowed
if !@_validate(linkedFileData)
return callback(new BadDataError())
callback(null, linkedFileData)
createLinkedFile: (project_id, linkedFileData, name, parent_folder_id, user_id, callback) ->
if !@_canCreate(linkedFileData)
return callback(new AccessDeniedError())
linkedFileData = @_sanitizeData(linkedFileData)
@_prepare project_id, linkedFileData, user_id, (err, linkedFileData) =>
return callback(err) if err?
@_getFileStream linkedFileData, user_id, (err, readStream) =>
return callback(err) if err?
readStream.on "error", callback
readStream.on "response", (response) =>
if 200 <= response.statusCode < 300
readStream.resume()
LinkedFilesHandler.importFromStream project_id,
readStream,
linkedFileData,
name,
parent_folder_id,
user_id,
(err, file) ->
return callback(err) if err?
callback(null, file._id) # Created
else
err = new OutputFileFetchFailedError(
"Output file fetch failed: #{linkedFileData.build_id}, #{linkedFileData.source_output_file_path}"
)
err.statusCode = response.statusCode
callback(err)
refreshLinkedFile: (project_id, linkedFileData, name, parent_folder_id, user_id, callback) ->
@_prepare project_id, linkedFileData, user_id, (err, linkedFileData) =>
return callback(err) if err?
@_compileAndGetFileStream linkedFileData, user_id, (err, readStream, new_build_id) =>
return callback(err) if err?
readStream.on "error", callback
readStream.on "response", (response) =>
if 200 <= response.statusCode < 300
readStream.resume()
linkedFileData.build_id = new_build_id
LinkedFilesHandler.importFromStream project_id,
readStream,
linkedFileData,
name,
parent_folder_id,
user_id,
(err, file) ->
return callback(err) if err?
callback(null, file._id) # Created
else
err = new OutputFileFetchFailedError(
"Output file fetch failed: #{linkedFileData.build_id}, #{linkedFileData.source_output_file_path}"
)
err.statusCode = response.statusCode
callback(err)
_sanitizeData: (data) ->
return {
provider: data.provider,
source_project_id: data.source_project_id,
source_output_file_path: data.source_output_file_path,
build_id: data.build_id
}
_canCreate: ProjectFileAgent._canCreate
_getSourceProject: LinkedFilesHandler.getSourceProject
_validate: (data) ->
if data.v1_source_doc_id?
(
data.v1_source_doc_id? &&
data.source_output_file_path?
)
else
(
data.source_project_id? &&
data.source_output_file_path? &&
data.build_id?
)
_checkAuth: (project_id, data, current_user_id, callback = (err, allowed)->) ->
callback = _.once(callback)
if !@_validate(data)
return callback(new BadDataError())
@_getSourceProject data, (err, project) ->
return callback(err) if err?
AuthorizationManager.canUserReadProject current_user_id,
project._id,
null,
(err, canRead) ->
return callback(err) if err?
callback(null, canRead)
_getFileStream: (linkedFileData, user_id, callback=(err, fileStream)->) ->
callback = _.once(callback)
{ source_output_file_path, build_id } = linkedFileData
@_getSourceProject linkedFileData, (err, project) ->
return callback(err) if err?
source_project_id = project._id
ClsiManager.getOutputFileStream source_project_id,
user_id,
build_id,
source_output_file_path,
(err, readStream) ->
return callback(err) if err?
readStream.pause()
callback(null, readStream)
_compileAndGetFileStream: (linkedFileData, user_id, callback=(err, stream, build_id)->) ->
callback = _.once(callback)
{ source_output_file_path } = linkedFileData
@_getSourceProject linkedFileData, (err, project) ->
return callback(err) if err?
source_project_id = project._id
CompileManager.compile source_project_id,
user_id,
{},
(err, status, outputFiles) ->
return callback(err) if err?
if status != 'success'
return callback(new OutputFileFetchFailedError())
outputFile = _.find(
outputFiles,
(o) => o.path == source_output_file_path
)
if !outputFile?
return callback(new OutputFileFetchFailedError())
build_id = outputFile.build
ClsiManager.getOutputFileStream source_project_id,
user_id,
build_id,
source_output_file_path,
(err, readStream) ->
return callback(err) if err?
readStream.pause()
callback(null, readStream, build_id)
}