TemplatesManager.js 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. /* eslint-disable
  2. camelcase,
  3. max-len,
  4. */
  5. // TODO: This file was created by bulk-decaffeinate.
  6. // Fix any style issues and re-enable lint.
  7. /*
  8. * decaffeinate suggestions:
  9. * DS102: Remove unnecessary code created because of implicit returns
  10. * DS207: Consider shorter variations of null checks
  11. * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  12. */
  13. const { Project } = require('../../models/Project')
  14. const ProjectDetailsHandler = require('../Project/ProjectDetailsHandler')
  15. const ProjectOptionsHandler = require('../Project/ProjectOptionsHandler')
  16. const ProjectRootDocManager = require('../Project/ProjectRootDocManager')
  17. const ProjectUploadManager = require('../Uploads/ProjectUploadManager')
  18. const FileWriter = require('../../infrastructure/FileWriter')
  19. const async = require('async')
  20. const fs = require('fs')
  21. const util = require('util')
  22. const logger = require('logger-sharelatex')
  23. const request = require('request')
  24. const requestPromise = require('request-promise-native')
  25. const settings = require('settings-sharelatex')
  26. const uuid = require('uuid')
  27. const Errors = require('../Errors/Errors')
  28. const _ = require('underscore')
  29. const TemplatesManager = {
  30. createProjectFromV1Template(
  31. brandVariationId,
  32. compiler,
  33. mainFile,
  34. templateId,
  35. templateName,
  36. templateVersionId,
  37. user_id,
  38. imageName,
  39. _callback
  40. ) {
  41. const callback = _.once(_callback)
  42. const zipUrl = `${
  43. settings.apis.v1.url
  44. }/api/v1/sharelatex/templates/${templateVersionId}`
  45. const zipReq = request(zipUrl, {
  46. auth: {
  47. user: settings.apis.v1.user,
  48. pass: settings.apis.v1.pass
  49. },
  50. timeout: 60 * 1000
  51. })
  52. zipReq.on('error', function(err) {
  53. logger.warn({ err }, 'error getting zip from template API')
  54. return callback(err)
  55. })
  56. return FileWriter.ensureDumpFolderExists(function(err) {
  57. if (err != null) {
  58. return callback(err)
  59. }
  60. const projectName = ProjectDetailsHandler.fixProjectName(templateName)
  61. const dumpPath = `${settings.path.dumpFolder}/${uuid.v4()}`
  62. const writeStream = fs.createWriteStream(dumpPath)
  63. const attributes = {
  64. fromV1TemplateId: templateId,
  65. fromV1TemplateVersionId: templateVersionId
  66. }
  67. writeStream.on('close', function() {
  68. if (zipReq.response.statusCode !== 200) {
  69. logger.warn(
  70. { uri: zipUrl, statusCode: zipReq.response.statusCode },
  71. 'non-success code getting zip from template API'
  72. )
  73. return callback(new Error('get zip failed'))
  74. }
  75. return ProjectUploadManager.createProjectFromZipArchiveWithName(
  76. user_id,
  77. projectName,
  78. dumpPath,
  79. attributes,
  80. function(err, project) {
  81. if (err != null) {
  82. logger.warn({ err, zipReq }, 'problem building project from zip')
  83. return callback(err)
  84. }
  85. return async.series(
  86. [
  87. cb => TemplatesManager._setCompiler(project._id, compiler, cb),
  88. cb => TemplatesManager._setImage(project._id, imageName, cb),
  89. cb => TemplatesManager._setMainFile(project._id, mainFile, cb),
  90. cb =>
  91. TemplatesManager._setBrandVariationId(
  92. project._id,
  93. brandVariationId,
  94. cb
  95. )
  96. ],
  97. function(err) {
  98. if (err != null) {
  99. return callback(err)
  100. }
  101. fs.unlink(dumpPath, function(err) {
  102. if (err != null) {
  103. return logger.err({ err }, 'error unlinking template zip')
  104. }
  105. })
  106. const update = {
  107. fromV1TemplateId: templateId,
  108. fromV1TemplateVersionId: templateVersionId
  109. }
  110. return Project.update(
  111. { _id: project._id },
  112. update,
  113. {},
  114. function(err) {
  115. if (err != null) {
  116. return callback(err)
  117. }
  118. return callback(null, project)
  119. }
  120. )
  121. }
  122. )
  123. }
  124. )
  125. })
  126. return zipReq.pipe(writeStream)
  127. })
  128. },
  129. _setCompiler(project_id, compiler, callback) {
  130. if (compiler == null) {
  131. return callback()
  132. }
  133. return ProjectOptionsHandler.setCompiler(project_id, compiler, callback)
  134. },
  135. _setImage(project_id, imageName, callback) {
  136. if (!imageName) {
  137. imageName = 'wl_texlive:2018.1'
  138. }
  139. return ProjectOptionsHandler.setImageName(project_id, imageName, callback)
  140. },
  141. _setMainFile(project_id, mainFile, callback) {
  142. if (mainFile == null) {
  143. return callback()
  144. }
  145. return ProjectRootDocManager.setRootDocFromName(
  146. project_id,
  147. mainFile,
  148. callback
  149. )
  150. },
  151. _setBrandVariationId(project_id, brandVariationId, callback) {
  152. if (brandVariationId == null) {
  153. return callback()
  154. }
  155. return ProjectOptionsHandler.setBrandVariationId(
  156. project_id,
  157. brandVariationId,
  158. callback
  159. )
  160. },
  161. promises: {
  162. async fetchFromV1(templateId) {
  163. let { body, statusCode } = await requestPromise({
  164. baseUrl: settings.apis.v1.url,
  165. url: `/api/v2/templates/${templateId}`,
  166. method: 'GET',
  167. auth: {
  168. user: settings.apis.v1.user,
  169. pass: settings.apis.v1.pass,
  170. sendImmediately: true
  171. },
  172. resolveWithFullResponse: true,
  173. simple: false,
  174. json: true,
  175. timeout: 60 * 1000
  176. })
  177. if (statusCode === 404) {
  178. throw new Errors.NotFoundError()
  179. }
  180. if (statusCode !== 200) {
  181. logger.warn(
  182. { templateId },
  183. "[TemplateMetrics] Couldn't fetch template data from v1"
  184. )
  185. throw new Error("Couldn't fetch template data from v1")
  186. }
  187. return body
  188. }
  189. }
  190. }
  191. TemplatesManager.fetchFromV1 = util.callbackify(
  192. TemplatesManager.promises.fetchFromV1
  193. )
  194. module.exports = TemplatesManager