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

142 lines
5 KiB
CoffeeScript

AuthorizationManager = require('../Authorization/AuthorizationManager')
ProjectLocator = require('../Project/ProjectLocator')
ProjectGetter = require('../Project/ProjectGetter')
Project = require("../../models/Project").Project
DocstoreManager = require('../Docstore/DocstoreManager')
FileStoreHandler = require('../FileStore/FileStoreHandler')
_ = require "underscore"
Settings = require 'settings-sharelatex'
LinkedFilesHandler = require './LinkedFilesHandler'
{
BadDataError,
AccessDeniedError,
BadEntityTypeError,
SourceFileNotFoundError,
ProjectNotFoundError,
V1ProjectNotFoundError
} = require './LinkedFilesErrors'
module.exports = ProjectFileAgent = {
createLinkedFile: (project_id, linkedFileData, name, parent_folder_id, user_id, callback) ->
if !@_canCreate(linkedFileData)
return callback(new AccessDeniedError())
@_go(project_id, linkedFileData, name, parent_folder_id, user_id, callback)
refreshLinkedFile: (project_id, linkedFileData, name, parent_folder_id, user_id, callback) ->
@_go project_id, linkedFileData, name, parent_folder_id, user_id, callback
_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
@_decorateLinkedFileData linkedFileData, (err, newLinkedFileData) =>
return callback(err) if err?
if !@_validate(newLinkedFileData)
return callback(new BadDataError())
callback(null, newLinkedFileData)
_go: (project_id, linkedFileData, name, parent_folder_id, user_id, callback) ->
linkedFileData = @_sanitizeData(linkedFileData)
@_prepare project_id, linkedFileData, user_id, (err, linkedFileData) =>
return callback(err) if err?
if !@_validate(linkedFileData)
return callback(new BadDataError())
@_getEntity linkedFileData, user_id, (err, source_project, entity, type) =>
return callback(err) if err?
if type == 'doc'
DocstoreManager.getDoc source_project._id, entity._id, (err, lines) ->
return callback(err) if err?
LinkedFilesHandler.importContent project_id,
lines.join('\n'),
linkedFileData,
name,
parent_folder_id,
user_id,
(err, file) ->
return callback(err) if err?
callback(null, file._id) # Created
else if type == 'file'
FileStoreHandler.getFileStream source_project._id, entity._id, null, (err, fileStream) ->
return callback(err) if err?
LinkedFilesHandler.importFromStream project_id,
fileStream,
linkedFileData,
name,
parent_folder_id,
user_id,
(err, file) ->
return callback(err) if err?
callback(null, file._id) # Created
else
callback(new BadEntityTypeError())
_getEntity:
(linkedFileData, current_user_id, callback = (err, entity, type) ->) ->
callback = _.once(callback)
{ source_entity_path } = linkedFileData
@_getSourceProject linkedFileData, (err, project) ->
return callback(err) if err?
source_project_id = project._id
ProjectLocator.findElementByPath {
project_id: source_project_id,
path: source_entity_path
}, (err, entity, type) ->
if err?
if err.toString().match(/^not found.*/)
err = new SourceFileNotFoundError()
return callback(err)
callback(null, project, entity, type)
_sanitizeData: (data) ->
return _.pick(
data,
'provider',
'source_project_id',
'v1_source_doc_id',
'source_entity_path'
)
_validate: (data) ->
return (
(data.source_project_id? || data.v1_source_doc_id?) &&
data.source_entity_path?
)
_canCreate: (data) ->
# Don't allow creation of linked-files with v1 doc ids
!data.v1_source_doc_id?
_getSourceProject: (data, callback=(err, project)->) ->
projection = {_id: 1, name: 1}
if data.v1_source_doc_id?
Project.findOne {'overleaf.id': data.v1_source_doc_id}, projection, (err, project) ->
return callback(err) if err?
if !project?
return callback(new V1ProjectNotFoundError())
callback(null, project)
else if data.source_project_id?
ProjectGetter.getProject data.source_project_id, projection, (err, project) ->
return callback(err) if err?
if !project?
return callback(new ProjectNotFoundError())
callback(null, project)
else
callback(new BadDataError('neither v1 nor v2 id present'))
_decorateLinkedFileData: (data, callback = (err, newData) ->) ->
callback = _.once(callback)
@_getSourceProject data, (err, project) ->
return callback(err) if err?
callback(err, _.extend(data, {source_project_display_name: project.name}))
_checkAuth: (project_id, data, current_user_id, callback = (error, allowed)->) ->
callback = _.once(callback)
if !ProjectFileAgent._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)
}