MessageHttpController.js 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. /*
  2. * decaffeinate suggestions:
  3. * DS102: Remove unnecessary code created because of implicit returns
  4. * DS207: Consider shorter variations of null checks
  5. * Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
  6. */
  7. let MessageHttpController;
  8. const logger = require("logger-sharelatex");
  9. const metrics = require("metrics-sharelatex");
  10. const MessageManager = require("./MessageManager");
  11. const MessageFormatter = require("./MessageFormatter");
  12. const ThreadManager = require("../Threads/ThreadManager");
  13. const {ObjectId} = require("../../mongojs");
  14. module.exports = (MessageHttpController = {
  15. DEFAULT_MESSAGE_LIMIT: 50,
  16. MAX_MESSAGE_LENGTH: 10 * 1024, // 10kb, about 1,500 words
  17. getGlobalMessages(req, res, next) {
  18. return MessageHttpController._getMessages(ThreadManager.GLOBAL_THREAD, req, res, next);
  19. },
  20. sendGlobalMessage(req, res, next) {
  21. return MessageHttpController._sendMessage(ThreadManager.GLOBAL_THREAD, req, res, next);
  22. },
  23. sendThreadMessage(req, res, next) {
  24. return MessageHttpController._sendMessage(req.params.thread_id, req, res, next);
  25. },
  26. getAllThreads(req, res, next) {
  27. const {project_id} = req.params;
  28. logger.log({project_id}, "getting all threads");
  29. return ThreadManager.findAllThreadRooms(project_id, function(error, rooms) {
  30. if (error != null) { return next(error); }
  31. const room_ids = rooms.map(r => r._id);
  32. return MessageManager.findAllMessagesInRooms(room_ids, function(error, messages) {
  33. if (error != null) { return next(error); }
  34. const threads = MessageFormatter.groupMessagesByThreads(rooms, messages);
  35. return res.json(threads);
  36. });
  37. });
  38. },
  39. resolveThread(req, res, next) {
  40. const {project_id, thread_id} = req.params;
  41. const {user_id} = req.body;
  42. logger.log({user_id, project_id, thread_id}, "marking thread as resolved");
  43. return ThreadManager.resolveThread(project_id, thread_id, user_id, function(error) {
  44. if (error != null) { return next(error); }
  45. return res.send(204);
  46. });
  47. }, // No content
  48. reopenThread(req, res, next) {
  49. const {project_id, thread_id} = req.params;
  50. logger.log({project_id, thread_id}, "reopening thread");
  51. return ThreadManager.reopenThread(project_id, thread_id, function(error) {
  52. if (error != null) { return next(error); }
  53. return res.send(204);
  54. });
  55. }, // No content
  56. deleteThread(req, res, next) {
  57. const {project_id, thread_id} = req.params;
  58. logger.log({project_id, thread_id}, "deleting thread");
  59. return ThreadManager.deleteThread(project_id, thread_id, function(error, room_id) {
  60. if (error != null) { return next(error); }
  61. return MessageManager.deleteAllMessagesInRoom(room_id, function(error) {
  62. if (error != null) { return next(error); }
  63. return res.send(204);
  64. });
  65. });
  66. }, // No content
  67. editMessage(req, res, next) {
  68. const {content} = req != null ? req.body : undefined;
  69. const {project_id, thread_id, message_id} = req.params;
  70. logger.log({project_id, thread_id, message_id, content}, "editing message");
  71. return ThreadManager.findOrCreateThread(project_id, thread_id, function(error, room) {
  72. if (error != null) { return next(error); }
  73. return MessageManager.updateMessage(room._id, message_id, content, Date.now(), function(error) {
  74. if (error != null) { return next(error); }
  75. return res.send(204);
  76. });
  77. });
  78. },
  79. deleteMessage(req, res, next) {
  80. const {project_id, thread_id, message_id} = req.params;
  81. logger.log({project_id, thread_id, message_id}, "deleting message");
  82. return ThreadManager.findOrCreateThread(project_id, thread_id, function(error, room) {
  83. if (error != null) { return next(error); }
  84. return MessageManager.deleteMessage(room._id, message_id, function(error, message) {
  85. if (error != null) { return next(error); }
  86. return res.send(204);
  87. });
  88. });
  89. },
  90. _sendMessage(client_thread_id, req, res, next) {
  91. const {user_id, content} = req != null ? req.body : undefined;
  92. const {project_id} = req.params;
  93. if (!ObjectId.isValid(user_id)) {
  94. return res.send(400, "Invalid user_id");
  95. }
  96. if ((content == null)) {
  97. return res.send(400, "No content provided");
  98. }
  99. if (content.length > this.MAX_MESSAGE_LENGTH) {
  100. return res.send(400, `Content too long (> ${this.MAX_MESSAGE_LENGTH} bytes)`);
  101. }
  102. logger.log({client_thread_id, project_id, user_id, content}, "new message received");
  103. return ThreadManager.findOrCreateThread(project_id, client_thread_id, function(error, thread) {
  104. if (error != null) { return next(error); }
  105. return MessageManager.createMessage(thread._id, user_id, content, Date.now(), function(error, message) {
  106. if (error != null) { return next(error); }
  107. message = MessageFormatter.formatMessageForClientSide(message);
  108. message.room_id = project_id;
  109. return res.send(201, message);
  110. });
  111. });
  112. },
  113. _getMessages(client_thread_id, req, res, next) {
  114. let before, limit;
  115. const {project_id} = req.params;
  116. if ((req.query != null ? req.query.before : undefined) != null) {
  117. before = parseInt(req.query.before, 10);
  118. } else {
  119. before = null;
  120. }
  121. if ((req.query != null ? req.query.limit : undefined) != null) {
  122. limit = parseInt(req.query.limit, 10);
  123. } else {
  124. limit = MessageHttpController.DEFAULT_MESSAGE_LIMIT;
  125. }
  126. logger.log({limit, before, project_id, client_thread_id}, "get message request received");
  127. return ThreadManager.findOrCreateThread(project_id, client_thread_id, function(error, thread) {
  128. if (error != null) { return next(error); }
  129. const thread_object_id = thread._id;
  130. logger.log({limit, before, project_id, client_thread_id, thread_object_id}, "found or created thread");
  131. return MessageManager.getMessages(thread_object_id, limit, before, function(error, messages) {
  132. if (error != null) { return next(error); }
  133. messages = MessageFormatter.formatMessagesForClientSide(messages);
  134. logger.log({project_id, messages}, "got messages");
  135. return res.send(200, messages);
  136. });
  137. });
  138. }
  139. });