2019-05-29 05:21:06 -04:00
|
|
|
/* eslint-disable
|
|
|
|
camelcase,
|
|
|
|
max-len,
|
|
|
|
*/
|
|
|
|
// TODO: This file was created by bulk-decaffeinate.
|
|
|
|
// Fix any style issues and re-enable lint.
|
|
|
|
/*
|
|
|
|
* decaffeinate suggestions:
|
|
|
|
* DS102: Remove unnecessary code created because of implicit returns
|
|
|
|
* DS207: Consider shorter variations of null checks
|
|
|
|
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
|
|
|
*/
|
|
|
|
const { Project } = require('../../models/Project')
|
2020-08-11 05:35:08 -04:00
|
|
|
const OError = require('@overleaf/o-error')
|
2019-05-29 05:21:06 -04:00
|
|
|
const ProjectDetailsHandler = require('../Project/ProjectDetailsHandler')
|
|
|
|
const ProjectOptionsHandler = require('../Project/ProjectOptionsHandler')
|
|
|
|
const ProjectRootDocManager = require('../Project/ProjectRootDocManager')
|
|
|
|
const ProjectUploadManager = require('../Uploads/ProjectUploadManager')
|
|
|
|
const FileWriter = require('../../infrastructure/FileWriter')
|
|
|
|
const async = require('async')
|
|
|
|
const fs = require('fs')
|
2019-09-24 04:44:13 -04:00
|
|
|
const util = require('util')
|
2019-05-29 05:21:06 -04:00
|
|
|
const logger = require('logger-sharelatex')
|
|
|
|
const request = require('request')
|
2019-09-24 04:44:13 -04:00
|
|
|
const requestPromise = require('request-promise-native')
|
2019-05-29 05:21:06 -04:00
|
|
|
const settings = require('settings-sharelatex')
|
|
|
|
const uuid = require('uuid')
|
2019-09-24 04:44:13 -04:00
|
|
|
const Errors = require('../Errors/Errors')
|
2019-12-03 05:43:51 -05:00
|
|
|
const _ = require('underscore')
|
2019-05-29 05:21:06 -04:00
|
|
|
|
2019-09-24 04:44:13 -04:00
|
|
|
const TemplatesManager = {
|
2019-05-29 05:21:06 -04:00
|
|
|
createProjectFromV1Template(
|
|
|
|
brandVariationId,
|
|
|
|
compiler,
|
|
|
|
mainFile,
|
|
|
|
templateId,
|
|
|
|
templateName,
|
|
|
|
templateVersionId,
|
|
|
|
user_id,
|
|
|
|
imageName,
|
2019-12-03 05:43:51 -05:00
|
|
|
_callback
|
2019-05-29 05:21:06 -04:00
|
|
|
) {
|
2019-12-03 05:43:51 -05:00
|
|
|
const callback = _.once(_callback)
|
2020-12-15 05:23:54 -05:00
|
|
|
const zipUrl = `${settings.apis.v1.url}/api/v1/sharelatex/templates/${templateVersionId}`
|
2019-05-29 05:21:06 -04:00
|
|
|
const zipReq = request(zipUrl, {
|
|
|
|
auth: {
|
|
|
|
user: settings.apis.v1.user,
|
2021-04-27 03:52:58 -04:00
|
|
|
pass: settings.apis.v1.pass,
|
2019-11-05 09:00:28 -05:00
|
|
|
},
|
2021-04-27 03:52:58 -04:00
|
|
|
timeout: 60 * 1000,
|
2019-05-29 05:21:06 -04:00
|
|
|
})
|
2021-04-14 09:17:21 -04:00
|
|
|
zipReq.on('error', function (err) {
|
2019-07-01 09:48:09 -04:00
|
|
|
logger.warn({ err }, 'error getting zip from template API')
|
2019-05-29 05:21:06 -04:00
|
|
|
return callback(err)
|
|
|
|
})
|
2021-04-14 09:17:21 -04:00
|
|
|
return FileWriter.ensureDumpFolderExists(function (err) {
|
2019-05-29 05:21:06 -04:00
|
|
|
if (err != null) {
|
|
|
|
return callback(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
const projectName = ProjectDetailsHandler.fixProjectName(templateName)
|
|
|
|
const dumpPath = `${settings.path.dumpFolder}/${uuid.v4()}`
|
|
|
|
const writeStream = fs.createWriteStream(dumpPath)
|
2019-06-04 07:08:04 -04:00
|
|
|
const attributes = {
|
|
|
|
fromV1TemplateId: templateId,
|
2021-04-27 03:52:58 -04:00
|
|
|
fromV1TemplateVersionId: templateVersionId,
|
2019-06-04 07:08:04 -04:00
|
|
|
}
|
2021-04-14 09:17:21 -04:00
|
|
|
writeStream.on('close', function () {
|
2019-05-29 05:21:06 -04:00
|
|
|
if (zipReq.response.statusCode !== 200) {
|
2019-07-01 09:48:09 -04:00
|
|
|
logger.warn(
|
2019-05-29 05:21:06 -04:00
|
|
|
{ uri: zipUrl, statusCode: zipReq.response.statusCode },
|
|
|
|
'non-success code getting zip from template API'
|
|
|
|
)
|
|
|
|
return callback(new Error('get zip failed'))
|
|
|
|
}
|
|
|
|
return ProjectUploadManager.createProjectFromZipArchiveWithName(
|
|
|
|
user_id,
|
|
|
|
projectName,
|
|
|
|
dumpPath,
|
2019-06-04 07:08:04 -04:00
|
|
|
attributes,
|
2021-04-14 09:17:21 -04:00
|
|
|
function (err, project) {
|
2019-05-29 05:21:06 -04:00
|
|
|
if (err != null) {
|
2020-08-11 05:35:08 -04:00
|
|
|
OError.tag(err, 'problem building project from zip', {
|
2021-04-27 03:52:58 -04:00
|
|
|
zipReq,
|
2020-08-11 05:35:08 -04:00
|
|
|
})
|
2019-05-29 05:21:06 -04:00
|
|
|
return callback(err)
|
|
|
|
}
|
|
|
|
return async.series(
|
|
|
|
[
|
|
|
|
cb => TemplatesManager._setCompiler(project._id, compiler, cb),
|
|
|
|
cb => TemplatesManager._setImage(project._id, imageName, cb),
|
|
|
|
cb => TemplatesManager._setMainFile(project._id, mainFile, cb),
|
|
|
|
cb =>
|
|
|
|
TemplatesManager._setBrandVariationId(
|
|
|
|
project._id,
|
|
|
|
brandVariationId,
|
|
|
|
cb
|
2021-04-27 03:52:58 -04:00
|
|
|
),
|
2019-05-29 05:21:06 -04:00
|
|
|
],
|
2021-04-14 09:17:21 -04:00
|
|
|
function (err) {
|
2019-05-29 05:21:06 -04:00
|
|
|
if (err != null) {
|
|
|
|
return callback(err)
|
|
|
|
}
|
2021-04-14 09:17:21 -04:00
|
|
|
fs.unlink(dumpPath, function (err) {
|
2019-05-29 05:21:06 -04:00
|
|
|
if (err != null) {
|
|
|
|
return logger.err({ err }, 'error unlinking template zip')
|
|
|
|
}
|
|
|
|
})
|
|
|
|
const update = {
|
|
|
|
fromV1TemplateId: templateId,
|
2021-04-27 03:52:58 -04:00
|
|
|
fromV1TemplateVersionId: templateVersionId,
|
2019-05-29 05:21:06 -04:00
|
|
|
}
|
2020-11-03 04:19:05 -05:00
|
|
|
return Project.updateOne(
|
2019-05-29 05:21:06 -04:00
|
|
|
{ _id: project._id },
|
|
|
|
update,
|
|
|
|
{},
|
2021-04-14 09:17:21 -04:00
|
|
|
function (err) {
|
2019-05-29 05:21:06 -04:00
|
|
|
if (err != null) {
|
|
|
|
return callback(err)
|
|
|
|
}
|
|
|
|
return callback(null, project)
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
)
|
|
|
|
})
|
|
|
|
return zipReq.pipe(writeStream)
|
|
|
|
})
|
|
|
|
},
|
|
|
|
|
|
|
|
_setCompiler(project_id, compiler, callback) {
|
|
|
|
if (compiler == null) {
|
|
|
|
return callback()
|
|
|
|
}
|
|
|
|
return ProjectOptionsHandler.setCompiler(project_id, compiler, callback)
|
|
|
|
},
|
|
|
|
|
|
|
|
_setImage(project_id, imageName, callback) {
|
|
|
|
if (!imageName) {
|
|
|
|
imageName = 'wl_texlive:2018.1'
|
|
|
|
}
|
|
|
|
return ProjectOptionsHandler.setImageName(project_id, imageName, callback)
|
|
|
|
},
|
|
|
|
|
|
|
|
_setMainFile(project_id, mainFile, callback) {
|
|
|
|
if (mainFile == null) {
|
|
|
|
return callback()
|
|
|
|
}
|
|
|
|
return ProjectRootDocManager.setRootDocFromName(
|
|
|
|
project_id,
|
|
|
|
mainFile,
|
|
|
|
callback
|
|
|
|
)
|
|
|
|
},
|
|
|
|
|
|
|
|
_setBrandVariationId(project_id, brandVariationId, callback) {
|
|
|
|
if (brandVariationId == null) {
|
|
|
|
return callback()
|
|
|
|
}
|
|
|
|
return ProjectOptionsHandler.setBrandVariationId(
|
|
|
|
project_id,
|
|
|
|
brandVariationId,
|
|
|
|
callback
|
|
|
|
)
|
2019-09-24 04:44:13 -04:00
|
|
|
},
|
|
|
|
|
|
|
|
promises: {
|
2019-09-26 08:42:07 -04:00
|
|
|
async fetchFromV1(templateId) {
|
2019-09-24 04:44:13 -04:00
|
|
|
let { body, statusCode } = await requestPromise({
|
|
|
|
baseUrl: settings.apis.v1.url,
|
|
|
|
url: `/api/v2/templates/${templateId}`,
|
|
|
|
method: 'GET',
|
|
|
|
auth: {
|
|
|
|
user: settings.apis.v1.user,
|
|
|
|
pass: settings.apis.v1.pass,
|
2021-04-27 03:52:58 -04:00
|
|
|
sendImmediately: true,
|
2019-09-24 04:44:13 -04:00
|
|
|
},
|
|
|
|
resolveWithFullResponse: true,
|
|
|
|
simple: false,
|
2019-11-05 09:00:28 -05:00
|
|
|
json: true,
|
2021-04-27 03:52:58 -04:00
|
|
|
timeout: 60 * 1000,
|
2019-09-24 04:44:13 -04:00
|
|
|
})
|
|
|
|
|
|
|
|
if (statusCode === 404) {
|
|
|
|
throw new Errors.NotFoundError()
|
|
|
|
}
|
|
|
|
|
|
|
|
if (statusCode !== 200) {
|
|
|
|
logger.warn(
|
|
|
|
{ templateId },
|
|
|
|
"[TemplateMetrics] Couldn't fetch template data from v1"
|
|
|
|
)
|
|
|
|
throw new Error("Couldn't fetch template data from v1")
|
|
|
|
}
|
|
|
|
|
|
|
|
return body
|
2021-04-27 03:52:58 -04:00
|
|
|
},
|
|
|
|
},
|
2019-05-29 05:21:06 -04:00
|
|
|
}
|
2019-09-24 04:44:13 -04:00
|
|
|
|
|
|
|
TemplatesManager.fetchFromV1 = util.callbackify(
|
|
|
|
TemplatesManager.promises.fetchFromV1
|
|
|
|
)
|
|
|
|
module.exports = TemplatesManager
|