TpdsController.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. /* eslint-disable
  2. camelcase,
  3. handle-callback-err,
  4. max-len,
  5. */
  6. // TODO: This file was created by bulk-decaffeinate.
  7. // Fix any style issues and re-enable lint.
  8. /*
  9. * decaffeinate suggestions:
  10. * DS102: Remove unnecessary code created because of implicit returns
  11. * DS207: Consider shorter variations of null checks
  12. * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  13. */
  14. let parseParams
  15. const tpdsUpdateHandler = require('./TpdsUpdateHandler')
  16. const UpdateMerger = require('./UpdateMerger')
  17. const logger = require('logger-sharelatex')
  18. const Path = require('path')
  19. const metrics = require('metrics-sharelatex')
  20. const NotificationsBuilder = require('../Notifications/NotificationsBuilder')
  21. const AuthenticationController = require('../Authentication/AuthenticationController')
  22. const TdpsQueueManager = require('./TpdsQueueManager').promises
  23. module.exports = {
  24. // mergeUpdate and deleteUpdate are used by Dropbox, where the project is only passed as the name, as the
  25. // first part of the file path. They have to check the project exists, find it, and create it if not.
  26. // They also ignore 'noisy' files like .DS_Store, .gitignore, etc.
  27. mergeUpdate(req, res) {
  28. metrics.inc('tpds.merge-update')
  29. const { filePath, user_id, projectName } = parseParams(req)
  30. const source = req.headers['x-sl-update-source'] || 'unknown'
  31. return tpdsUpdateHandler.newUpdate(
  32. user_id,
  33. projectName,
  34. filePath,
  35. req,
  36. source,
  37. function(err) {
  38. if (err != null) {
  39. if (err.name === 'TooManyRequestsError') {
  40. logger.warn(
  41. { err, user_id, filePath },
  42. 'tpds update failed to be processed, too many requests'
  43. )
  44. return res.sendStatus(429)
  45. } else if (err.message === 'project_has_too_many_files') {
  46. logger.warn(
  47. { err, user_id, filePath },
  48. 'tpds trying to append to project over file limit'
  49. )
  50. NotificationsBuilder.tpdsFileLimit(user_id).create(projectName)
  51. return res.sendStatus(400)
  52. } else {
  53. logger.err(
  54. { err, user_id, filePath },
  55. 'error reciving update from tpds'
  56. )
  57. return res.sendStatus(500)
  58. }
  59. } else {
  60. return res.sendStatus(200)
  61. }
  62. }
  63. )
  64. },
  65. deleteUpdate(req, res) {
  66. metrics.inc('tpds.delete-update')
  67. const { filePath, user_id, projectName } = parseParams(req)
  68. const source = req.headers['x-sl-update-source'] || 'unknown'
  69. return tpdsUpdateHandler.deleteUpdate(
  70. user_id,
  71. projectName,
  72. filePath,
  73. source,
  74. function(err) {
  75. if (err != null) {
  76. logger.err(
  77. { err, user_id, filePath },
  78. 'error reciving update from tpds'
  79. )
  80. return res.sendStatus(500)
  81. } else {
  82. return res.sendStatus(200)
  83. }
  84. }
  85. )
  86. },
  87. // updateProjectContents and deleteProjectContents are used by GitHub. The project_id is known so we
  88. // can skip right ahead to creating/updating/deleting the file. These methods will not ignore noisy
  89. // files like .DS_Store, .gitignore, etc because people are generally more explicit with the files they
  90. // want in git.
  91. updateProjectContents(req, res, next) {
  92. if (next == null) {
  93. next = function(error) {}
  94. }
  95. const { project_id } = req.params
  96. const path = `/${req.params[0]}` // UpdateMerger expects leading slash
  97. const source = req.headers['x-sl-update-source'] || 'unknown'
  98. return UpdateMerger.mergeUpdate(
  99. null,
  100. project_id,
  101. path,
  102. req,
  103. source,
  104. function(error) {
  105. if (error != null) {
  106. return next(error)
  107. }
  108. return res.sendStatus(200)
  109. }
  110. )
  111. },
  112. deleteProjectContents(req, res, next) {
  113. if (next == null) {
  114. next = function(error) {}
  115. }
  116. const { project_id } = req.params
  117. const path = `/${req.params[0]}` // UpdateMerger expects leading slash
  118. const source = req.headers['x-sl-update-source'] || 'unknown'
  119. return UpdateMerger.deleteUpdate(null, project_id, path, source, function(
  120. error
  121. ) {
  122. if (error != null) {
  123. return next(error)
  124. }
  125. return res.sendStatus(200)
  126. })
  127. },
  128. async getQueues(req, res, next) {
  129. const userId = AuthenticationController.getLoggedInUserId(req)
  130. try {
  131. res.json(await TdpsQueueManager.getQueues(userId))
  132. } catch (err) {
  133. next(err)
  134. }
  135. },
  136. parseParams: (parseParams = function(req) {
  137. let filePath, projectName
  138. let path = req.params[0]
  139. const { user_id } = req.params
  140. path = Path.join('/', path)
  141. if (path.substring(1).indexOf('/') === -1) {
  142. filePath = '/'
  143. projectName = path.substring(1)
  144. } else {
  145. filePath = path.substring(path.indexOf('/', 1))
  146. projectName = path.substring(0, path.indexOf('/', 1))
  147. projectName = projectName.replace('/', '')
  148. }
  149. return { filePath, user_id, projectName }
  150. })
  151. }