HttpController.js 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. /* eslint-disable
  2. camelcase,
  3. handle-callback-err,
  4. valid-typeof,
  5. */
  6. // TODO: This file was created by bulk-decaffeinate.
  7. // Fix any style issues and re-enable lint.
  8. /*
  9. * decaffeinate suggestions:
  10. * DS101: Remove unnecessary use of Array.from
  11. * DS102: Remove unnecessary code created because of implicit returns
  12. * DS207: Consider shorter variations of null checks
  13. * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  14. */
  15. let HttpController;
  16. const DocManager = require("./DocManager");
  17. const logger = require("logger-sharelatex");
  18. const DocArchive = require("./DocArchiveManager");
  19. const HealthChecker = require("./HealthChecker");
  20. const Settings = require("settings-sharelatex");
  21. module.exports = (HttpController = {
  22. getDoc(req, res, next) {
  23. if (next == null) { next = function(error) {}; }
  24. const {
  25. project_id
  26. } = req.params;
  27. const {
  28. doc_id
  29. } = req.params;
  30. const include_deleted = (req.query != null ? req.query.include_deleted : undefined) === "true";
  31. logger.log({project_id, doc_id}, "getting doc");
  32. return DocManager.getFullDoc(project_id, doc_id, function(error, doc) {
  33. if (error != null) { return next(error); }
  34. logger.log({doc_id, project_id}, "got doc");
  35. if ((doc == null)) {
  36. return res.send(404);
  37. } else if (doc.deleted && !include_deleted) {
  38. return res.send(404);
  39. } else {
  40. return res.json(HttpController._buildDocView(doc));
  41. }
  42. });
  43. },
  44. getRawDoc(req, res, next){
  45. if (next == null) { next = function(error){}; }
  46. const {
  47. project_id
  48. } = req.params;
  49. const {
  50. doc_id
  51. } = req.params;
  52. logger.log({project_id, doc_id}, "getting raw doc");
  53. return DocManager.getDocLines(project_id, doc_id, function(error, doc) {
  54. if (error != null) { return next(error); }
  55. if ((doc == null)) {
  56. return res.send(404);
  57. } else {
  58. res.setHeader('content-type', 'text/plain');
  59. return res.send(HttpController._buildRawDocView(doc));
  60. }
  61. });
  62. },
  63. getAllDocs(req, res, next) {
  64. if (next == null) { next = function(error) {}; }
  65. const {
  66. project_id
  67. } = req.params;
  68. logger.log({project_id}, "getting all docs");
  69. return DocManager.getAllNonDeletedDocs(project_id, {lines: true, rev: true}, function(error, docs) {
  70. if (docs == null) { docs = []; }
  71. if (error != null) { return next(error); }
  72. return res.json(HttpController._buildDocsArrayView(project_id, docs));
  73. });
  74. },
  75. getAllRanges(req, res, next) {
  76. if (next == null) { next = function(error) {}; }
  77. const {
  78. project_id
  79. } = req.params;
  80. logger.log({project_id}, "getting all ranges");
  81. return DocManager.getAllNonDeletedDocs(project_id, {ranges: true}, function(error, docs) {
  82. if (docs == null) { docs = []; }
  83. if (error != null) { return next(error); }
  84. return res.json(HttpController._buildDocsArrayView(project_id, docs));
  85. });
  86. },
  87. updateDoc(req, res, next) {
  88. if (next == null) { next = function(error) {}; }
  89. const {
  90. project_id
  91. } = req.params;
  92. const {
  93. doc_id
  94. } = req.params;
  95. const lines = req.body != null ? req.body.lines : undefined;
  96. const version = req.body != null ? req.body.version : undefined;
  97. const ranges = req.body != null ? req.body.ranges : undefined;
  98. if ((lines == null) || !(lines instanceof Array)) {
  99. logger.error({project_id, doc_id}, "no doc lines provided");
  100. res.send(400); // Bad Request
  101. return;
  102. }
  103. if ((version == null) || (typeof version === !"number")) {
  104. logger.error({project_id, doc_id}, "no doc version provided");
  105. res.send(400); // Bad Request
  106. return;
  107. }
  108. if ((ranges == null)) {
  109. logger.error({project_id, doc_id}, "no doc ranges provided");
  110. res.send(400); // Bad Request
  111. return;
  112. }
  113. const bodyLength = lines.reduce(
  114. (len, line) => line.length + len,
  115. 0
  116. );
  117. if (bodyLength > Settings.max_doc_length) {
  118. logger.error({project_id, doc_id, bodyLength}, "document body too large");
  119. res.status(413).send("document body too large");
  120. return;
  121. }
  122. logger.log({project_id, doc_id}, "got http request to update doc");
  123. return DocManager.updateDoc(project_id, doc_id, lines, version, ranges, function(error, modified, rev) {
  124. if (error != null) { return next(error); }
  125. return res.json({
  126. modified,
  127. rev
  128. });
  129. });
  130. },
  131. deleteDoc(req, res, next) {
  132. if (next == null) { next = function(error) {}; }
  133. const {
  134. project_id
  135. } = req.params;
  136. const {
  137. doc_id
  138. } = req.params;
  139. logger.log({project_id, doc_id}, "deleting doc");
  140. return DocManager.deleteDoc(project_id, doc_id, function(error) {
  141. if (error != null) { return next(error); }
  142. return res.send(204);
  143. });
  144. },
  145. _buildDocView(doc) {
  146. const doc_view = { _id: (doc._id != null ? doc._id.toString() : undefined) };
  147. for (const attribute of ["lines", "rev", "version", "ranges", "deleted"]) {
  148. if (doc[attribute] != null) {
  149. doc_view[attribute] = doc[attribute];
  150. }
  151. }
  152. return doc_view;
  153. },
  154. _buildRawDocView(doc){
  155. return ((doc != null ? doc.lines : undefined) || []).join("\n");
  156. },
  157. _buildDocsArrayView(project_id, docs) {
  158. const docViews = [];
  159. for (const doc of Array.from(docs)) {
  160. if (doc != null) { // There can end up being null docs for some reason :( (probably a race condition)
  161. docViews.push(HttpController._buildDocView(doc));
  162. } else {
  163. logger.error({err: new Error("null doc"), project_id}, "encountered null doc");
  164. }
  165. }
  166. return docViews;
  167. },
  168. archiveAllDocs(req, res, next) {
  169. if (next == null) { next = function(error) {}; }
  170. const {
  171. project_id
  172. } = req.params;
  173. logger.log({project_id}, "archiving all docs");
  174. return DocArchive.archiveAllDocs(project_id, function(error) {
  175. if (error != null) { return next(error); }
  176. return res.send(204);
  177. });
  178. },
  179. unArchiveAllDocs(req, res, next) {
  180. if (next == null) { next = function(error) {}; }
  181. const {
  182. project_id
  183. } = req.params;
  184. logger.log({project_id}, "unarchiving all docs");
  185. return DocArchive.unArchiveAllDocs(project_id, function(error) {
  186. if (error != null) { return next(error); }
  187. return res.send(200);
  188. });
  189. },
  190. destroyAllDocs(req, res, next) {
  191. if (next == null) { next = function(error) {}; }
  192. const {
  193. project_id
  194. } = req.params;
  195. logger.log({project_id}, "destroying all docs");
  196. return DocArchive.destroyAllDocs(project_id, function(error) {
  197. if (error != null) { return next(error); }
  198. return res.send(204);
  199. });
  200. },
  201. healthCheck(req, res){
  202. return HealthChecker.check(function(err){
  203. if (err != null) {
  204. logger.err({err}, "error performing health check");
  205. return res.send(500);
  206. } else {
  207. return res.send(200);
  208. }
  209. });
  210. }
  211. });