MessageHttpController.js 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. /* eslint-disable
  2. camelcase,
  3. max-len,
  4. no-unused-vars,
  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 MessageHttpController
  15. const logger = require('@overleaf/logger')
  16. const metrics = require('@overleaf/metrics')
  17. const MessageManager = require('./MessageManager')
  18. const MessageFormatter = require('./MessageFormatter')
  19. const ThreadManager = require('../Threads/ThreadManager')
  20. const { ObjectId } = require('../../mongodb')
  21. module.exports = MessageHttpController = {
  22. DEFAULT_MESSAGE_LIMIT: 50,
  23. MAX_MESSAGE_LENGTH: 10 * 1024, // 10kb, about 1,500 words
  24. getGlobalMessages(req, res, next) {
  25. return MessageHttpController._getMessages(
  26. ThreadManager.GLOBAL_THREAD,
  27. req,
  28. res,
  29. next
  30. )
  31. },
  32. sendGlobalMessage(req, res, next) {
  33. return MessageHttpController._sendMessage(
  34. ThreadManager.GLOBAL_THREAD,
  35. req,
  36. res,
  37. next
  38. )
  39. },
  40. sendThreadMessage(req, res, next) {
  41. return MessageHttpController._sendMessage(
  42. req.params.thread_id,
  43. req,
  44. res,
  45. next
  46. )
  47. },
  48. getAllThreads(req, res, next) {
  49. const { project_id } = req.params
  50. logger.log({ project_id }, 'getting all threads')
  51. return ThreadManager.findAllThreadRooms(
  52. project_id,
  53. function (error, rooms) {
  54. if (error != null) {
  55. return next(error)
  56. }
  57. const room_ids = rooms.map(r => r._id)
  58. return MessageManager.findAllMessagesInRooms(
  59. room_ids,
  60. function (error, messages) {
  61. if (error != null) {
  62. return next(error)
  63. }
  64. const threads = MessageFormatter.groupMessagesByThreads(
  65. rooms,
  66. messages
  67. )
  68. return res.json(threads)
  69. }
  70. )
  71. }
  72. )
  73. },
  74. resolveThread(req, res, next) {
  75. const { project_id, thread_id } = req.params
  76. const { user_id } = req.body
  77. logger.log({ user_id, project_id, thread_id }, 'marking thread as resolved')
  78. return ThreadManager.resolveThread(
  79. project_id,
  80. thread_id,
  81. user_id,
  82. function (error) {
  83. if (error != null) {
  84. return next(error)
  85. }
  86. return res.sendStatus(204)
  87. }
  88. )
  89. }, // No content
  90. reopenThread(req, res, next) {
  91. const { project_id, thread_id } = req.params
  92. logger.log({ project_id, thread_id }, 'reopening thread')
  93. return ThreadManager.reopenThread(project_id, thread_id, function (error) {
  94. if (error != null) {
  95. return next(error)
  96. }
  97. return res.sendStatus(204)
  98. })
  99. }, // No content
  100. deleteThread(req, res, next) {
  101. const { project_id, thread_id } = req.params
  102. logger.log({ project_id, thread_id }, 'deleting thread')
  103. return ThreadManager.deleteThread(
  104. project_id,
  105. thread_id,
  106. function (error, room_id) {
  107. if (error != null) {
  108. return next(error)
  109. }
  110. return MessageManager.deleteAllMessagesInRoom(
  111. room_id,
  112. function (error) {
  113. if (error != null) {
  114. return next(error)
  115. }
  116. return res.sendStatus(204)
  117. }
  118. )
  119. }
  120. )
  121. }, // No content
  122. editMessage(req, res, next) {
  123. const { content } = req != null ? req.body : undefined
  124. const { project_id, thread_id, message_id } = req.params
  125. logger.log(
  126. { project_id, thread_id, message_id, content },
  127. 'editing message'
  128. )
  129. return ThreadManager.findOrCreateThread(
  130. project_id,
  131. thread_id,
  132. function (error, room) {
  133. if (error != null) {
  134. return next(error)
  135. }
  136. return MessageManager.updateMessage(
  137. room._id,
  138. message_id,
  139. content,
  140. Date.now(),
  141. function (error) {
  142. if (error != null) {
  143. return next(error)
  144. }
  145. return res.sendStatus(204)
  146. }
  147. )
  148. }
  149. )
  150. },
  151. deleteMessage(req, res, next) {
  152. const { project_id, thread_id, message_id } = req.params
  153. logger.log({ project_id, thread_id, message_id }, 'deleting message')
  154. return ThreadManager.findOrCreateThread(
  155. project_id,
  156. thread_id,
  157. function (error, room) {
  158. if (error != null) {
  159. return next(error)
  160. }
  161. return MessageManager.deleteMessage(
  162. room._id,
  163. message_id,
  164. function (error, message) {
  165. if (error != null) {
  166. return next(error)
  167. }
  168. return res.sendStatus(204)
  169. }
  170. )
  171. }
  172. )
  173. },
  174. _sendMessage(client_thread_id, req, res, next) {
  175. const { user_id, content } = req != null ? req.body : undefined
  176. const { project_id } = req.params
  177. if (!ObjectId.isValid(user_id)) {
  178. return res.status(400).send('Invalid user_id')
  179. }
  180. if (content == null) {
  181. return res.status(400).send('No content provided')
  182. }
  183. if (content.length > this.MAX_MESSAGE_LENGTH) {
  184. return res
  185. .status(400)
  186. .send(`Content too long (> ${this.MAX_MESSAGE_LENGTH} bytes)`)
  187. }
  188. logger.log(
  189. { client_thread_id, project_id, user_id, content },
  190. 'new message received'
  191. )
  192. return ThreadManager.findOrCreateThread(
  193. project_id,
  194. client_thread_id,
  195. function (error, thread) {
  196. if (error != null) {
  197. return next(error)
  198. }
  199. return MessageManager.createMessage(
  200. thread._id,
  201. user_id,
  202. content,
  203. Date.now(),
  204. function (error, message) {
  205. if (error != null) {
  206. return next(error)
  207. }
  208. message = MessageFormatter.formatMessageForClientSide(message)
  209. message.room_id = project_id
  210. return res.status(201).send(message)
  211. }
  212. )
  213. }
  214. )
  215. },
  216. _getMessages(client_thread_id, req, res, next) {
  217. let before, limit
  218. const { project_id } = req.params
  219. if ((req.query != null ? req.query.before : undefined) != null) {
  220. before = parseInt(req.query.before, 10)
  221. } else {
  222. before = null
  223. }
  224. if ((req.query != null ? req.query.limit : undefined) != null) {
  225. limit = parseInt(req.query.limit, 10)
  226. } else {
  227. limit = MessageHttpController.DEFAULT_MESSAGE_LIMIT
  228. }
  229. logger.log(
  230. { limit, before, project_id, client_thread_id },
  231. 'get message request received'
  232. )
  233. return ThreadManager.findOrCreateThread(
  234. project_id,
  235. client_thread_id,
  236. function (error, thread) {
  237. if (error != null) {
  238. return next(error)
  239. }
  240. const thread_object_id = thread._id
  241. logger.log(
  242. { limit, before, project_id, client_thread_id, thread_object_id },
  243. 'found or created thread'
  244. )
  245. return MessageManager.getMessages(
  246. thread_object_id,
  247. limit,
  248. before,
  249. function (error, messages) {
  250. if (error != null) {
  251. return next(error)
  252. }
  253. messages = MessageFormatter.formatMessagesForClientSide(messages)
  254. logger.log({ project_id, messages }, 'got messages')
  255. return res.status(200).send(messages)
  256. }
  257. )
  258. }
  259. )
  260. },
  261. }