|
@@ -1,236 +1,221 @@
|
|
|
-let MessageHttpController
|
|
|
|
|
const logger = require('@overleaf/logger')
|
|
const logger = require('@overleaf/logger')
|
|
|
const MessageManager = require('./MessageManager')
|
|
const MessageManager = require('./MessageManager')
|
|
|
const MessageFormatter = require('./MessageFormatter')
|
|
const MessageFormatter = require('./MessageFormatter')
|
|
|
const ThreadManager = require('../Threads/ThreadManager')
|
|
const ThreadManager = require('../Threads/ThreadManager')
|
|
|
const { ObjectId } = require('../../mongodb')
|
|
const { ObjectId } = require('../../mongodb')
|
|
|
|
|
|
|
|
-module.exports = MessageHttpController = {
|
|
|
|
|
- DEFAULT_MESSAGE_LIMIT: 50,
|
|
|
|
|
- MAX_MESSAGE_LENGTH: 10 * 1024, // 10kb, about 1,500 words
|
|
|
|
|
|
|
+const DEFAULT_MESSAGE_LIMIT = 50
|
|
|
|
|
+const MAX_MESSAGE_LENGTH = 10 * 1024 // 10kb, about 1,500 words
|
|
|
|
|
|
|
|
- getGlobalMessages(req, res, next) {
|
|
|
|
|
- MessageHttpController._getMessages(
|
|
|
|
|
- ThreadManager.GLOBAL_THREAD,
|
|
|
|
|
- req,
|
|
|
|
|
- res,
|
|
|
|
|
- next
|
|
|
|
|
- )
|
|
|
|
|
- },
|
|
|
|
|
|
|
+function getGlobalMessages(req, res, next) {
|
|
|
|
|
+ _getMessages(ThreadManager.GLOBAL_THREAD, req, res, next)
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- sendGlobalMessage(req, res, next) {
|
|
|
|
|
- MessageHttpController._sendMessage(
|
|
|
|
|
- ThreadManager.GLOBAL_THREAD,
|
|
|
|
|
- req,
|
|
|
|
|
- res,
|
|
|
|
|
- next
|
|
|
|
|
- )
|
|
|
|
|
- },
|
|
|
|
|
|
|
+function sendGlobalMessage(req, res, next) {
|
|
|
|
|
+ _sendMessage(ThreadManager.GLOBAL_THREAD, req, res, next)
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- sendThreadMessage(req, res, next) {
|
|
|
|
|
- MessageHttpController._sendMessage(req.params.threadId, req, res, next)
|
|
|
|
|
- },
|
|
|
|
|
|
|
+function sendThreadMessage(req, res, next) {
|
|
|
|
|
+ _sendMessage(req.params.threadId, req, res, next)
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- getAllThreads(req, res, next) {
|
|
|
|
|
- const { projectId } = req.params
|
|
|
|
|
- logger.log({ projectId }, 'getting all threads')
|
|
|
|
|
- ThreadManager.findAllThreadRooms(projectId, function (error, rooms) {
|
|
|
|
|
|
|
+function getAllThreads(req, res, next) {
|
|
|
|
|
+ const { projectId } = req.params
|
|
|
|
|
+ logger.log({ projectId }, 'getting all threads')
|
|
|
|
|
+ ThreadManager.findAllThreadRooms(projectId, function (error, rooms) {
|
|
|
|
|
+ if (error) {
|
|
|
|
|
+ return next(error)
|
|
|
|
|
+ }
|
|
|
|
|
+ const roomIds = rooms.map(r => r._id)
|
|
|
|
|
+ MessageManager.findAllMessagesInRooms(roomIds, function (error, messages) {
|
|
|
if (error) {
|
|
if (error) {
|
|
|
return next(error)
|
|
return next(error)
|
|
|
}
|
|
}
|
|
|
- const roomIds = rooms.map(r => r._id)
|
|
|
|
|
- MessageManager.findAllMessagesInRooms(
|
|
|
|
|
- roomIds,
|
|
|
|
|
- function (error, messages) {
|
|
|
|
|
- if (error) {
|
|
|
|
|
- return next(error)
|
|
|
|
|
- }
|
|
|
|
|
- const threads = MessageFormatter.groupMessagesByThreads(
|
|
|
|
|
- rooms,
|
|
|
|
|
- messages
|
|
|
|
|
- )
|
|
|
|
|
- res.json(threads)
|
|
|
|
|
- }
|
|
|
|
|
- )
|
|
|
|
|
|
|
+ const threads = MessageFormatter.groupMessagesByThreads(rooms, messages)
|
|
|
|
|
+ res.json(threads)
|
|
|
})
|
|
})
|
|
|
- },
|
|
|
|
|
|
|
+ })
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- resolveThread(req, res, next) {
|
|
|
|
|
- const { projectId, threadId } = req.params
|
|
|
|
|
- const { user_id: userId } = req.body
|
|
|
|
|
- logger.log({ userId, projectId, threadId }, 'marking thread as resolved')
|
|
|
|
|
- ThreadManager.resolveThread(projectId, threadId, userId, function (error) {
|
|
|
|
|
- if (error) {
|
|
|
|
|
- return next(error)
|
|
|
|
|
- }
|
|
|
|
|
- res.sendStatus(204)
|
|
|
|
|
- })
|
|
|
|
|
- }, // No content
|
|
|
|
|
|
|
+function resolveThread(req, res, next) {
|
|
|
|
|
+ const { projectId, threadId } = req.params
|
|
|
|
|
+ const { user_id: userId } = req.body
|
|
|
|
|
+ logger.log({ userId, projectId, threadId }, 'marking thread as resolved')
|
|
|
|
|
+ ThreadManager.resolveThread(projectId, threadId, userId, function (error) {
|
|
|
|
|
+ if (error) {
|
|
|
|
|
+ return next(error)
|
|
|
|
|
+ }
|
|
|
|
|
+ res.sendStatus(204)
|
|
|
|
|
+ })
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- reopenThread(req, res, next) {
|
|
|
|
|
- const { projectId, threadId } = req.params
|
|
|
|
|
- logger.log({ projectId, threadId }, 'reopening thread')
|
|
|
|
|
- ThreadManager.reopenThread(projectId, threadId, function (error) {
|
|
|
|
|
|
|
+function reopenThread(req, res, next) {
|
|
|
|
|
+ const { projectId, threadId } = req.params
|
|
|
|
|
+ logger.log({ projectId, threadId }, 'reopening thread')
|
|
|
|
|
+ ThreadManager.reopenThread(projectId, threadId, function (error) {
|
|
|
|
|
+ if (error) {
|
|
|
|
|
+ return next(error)
|
|
|
|
|
+ }
|
|
|
|
|
+ res.sendStatus(204)
|
|
|
|
|
+ })
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function deleteThread(req, res, next) {
|
|
|
|
|
+ const { projectId, threadId } = req.params
|
|
|
|
|
+ logger.log({ projectId, threadId }, 'deleting thread')
|
|
|
|
|
+ ThreadManager.deleteThread(projectId, threadId, function (error, roomId) {
|
|
|
|
|
+ if (error) {
|
|
|
|
|
+ return next(error)
|
|
|
|
|
+ }
|
|
|
|
|
+ MessageManager.deleteAllMessagesInRoom(roomId, function (error) {
|
|
|
if (error) {
|
|
if (error) {
|
|
|
return next(error)
|
|
return next(error)
|
|
|
}
|
|
}
|
|
|
res.sendStatus(204)
|
|
res.sendStatus(204)
|
|
|
})
|
|
})
|
|
|
- }, // No content
|
|
|
|
|
|
|
+ })
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- deleteThread(req, res, next) {
|
|
|
|
|
- const { projectId, threadId } = req.params
|
|
|
|
|
- logger.log({ projectId, threadId }, 'deleting thread')
|
|
|
|
|
- ThreadManager.deleteThread(projectId, threadId, function (error, roomId) {
|
|
|
|
|
- if (error) {
|
|
|
|
|
- return next(error)
|
|
|
|
|
- }
|
|
|
|
|
- MessageManager.deleteAllMessagesInRoom(roomId, function (error) {
|
|
|
|
|
|
|
+function editMessage(req, res, next) {
|
|
|
|
|
+ const { content } = req.body
|
|
|
|
|
+ const { projectId, threadId, messageId } = req.params
|
|
|
|
|
+ logger.log({ projectId, threadId, messageId, content }, 'editing message')
|
|
|
|
|
+ ThreadManager.findOrCreateThread(projectId, threadId, function (error, room) {
|
|
|
|
|
+ if (error) {
|
|
|
|
|
+ return next(error)
|
|
|
|
|
+ }
|
|
|
|
|
+ MessageManager.updateMessage(
|
|
|
|
|
+ room._id,
|
|
|
|
|
+ messageId,
|
|
|
|
|
+ content,
|
|
|
|
|
+ Date.now(),
|
|
|
|
|
+ function (error) {
|
|
|
if (error) {
|
|
if (error) {
|
|
|
return next(error)
|
|
return next(error)
|
|
|
}
|
|
}
|
|
|
res.sendStatus(204)
|
|
res.sendStatus(204)
|
|
|
- })
|
|
|
|
|
- })
|
|
|
|
|
- }, // No content
|
|
|
|
|
-
|
|
|
|
|
- editMessage(req, res, next) {
|
|
|
|
|
- const { content } = req.body
|
|
|
|
|
- const { projectId, threadId, messageId } = req.params
|
|
|
|
|
- logger.log({ projectId, threadId, messageId, content }, 'editing message')
|
|
|
|
|
- ThreadManager.findOrCreateThread(
|
|
|
|
|
- projectId,
|
|
|
|
|
- threadId,
|
|
|
|
|
- function (error, room) {
|
|
|
|
|
- if (error) {
|
|
|
|
|
- return next(error)
|
|
|
|
|
- }
|
|
|
|
|
- MessageManager.updateMessage(
|
|
|
|
|
- room._id,
|
|
|
|
|
- messageId,
|
|
|
|
|
- content,
|
|
|
|
|
- Date.now(),
|
|
|
|
|
- function (error) {
|
|
|
|
|
- if (error) {
|
|
|
|
|
- return next(error)
|
|
|
|
|
- }
|
|
|
|
|
- res.sendStatus(204)
|
|
|
|
|
- }
|
|
|
|
|
- )
|
|
|
|
|
- }
|
|
|
|
|
- )
|
|
|
|
|
- },
|
|
|
|
|
-
|
|
|
|
|
- deleteMessage(req, res, next) {
|
|
|
|
|
- const { projectId, threadId, messageId } = req.params
|
|
|
|
|
- logger.log({ projectId, threadId, messageId }, 'deleting message')
|
|
|
|
|
- ThreadManager.findOrCreateThread(
|
|
|
|
|
- projectId,
|
|
|
|
|
- threadId,
|
|
|
|
|
- function (error, room) {
|
|
|
|
|
- if (error) {
|
|
|
|
|
- return next(error)
|
|
|
|
|
- }
|
|
|
|
|
- MessageManager.deleteMessage(
|
|
|
|
|
- room._id,
|
|
|
|
|
- messageId,
|
|
|
|
|
- function (error, message) {
|
|
|
|
|
- if (error) {
|
|
|
|
|
- return next(error)
|
|
|
|
|
- }
|
|
|
|
|
- res.sendStatus(204)
|
|
|
|
|
- }
|
|
|
|
|
- )
|
|
|
|
|
}
|
|
}
|
|
|
)
|
|
)
|
|
|
- },
|
|
|
|
|
|
|
+ })
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- _sendMessage(clientThreadId, req, res, next) {
|
|
|
|
|
- const { user_id: userId, content } = req.body
|
|
|
|
|
- const { projectId } = req.params
|
|
|
|
|
- if (!ObjectId.isValid(userId)) {
|
|
|
|
|
- return res.status(400).send('Invalid userId')
|
|
|
|
|
- }
|
|
|
|
|
- if (!content) {
|
|
|
|
|
- return res.status(400).send('No content provided')
|
|
|
|
|
|
|
+function deleteMessage(req, res, next) {
|
|
|
|
|
+ const { projectId, threadId, messageId } = req.params
|
|
|
|
|
+ logger.log({ projectId, threadId, messageId }, 'deleting message')
|
|
|
|
|
+ ThreadManager.findOrCreateThread(projectId, threadId, function (error, room) {
|
|
|
|
|
+ if (error) {
|
|
|
|
|
+ return next(error)
|
|
|
}
|
|
}
|
|
|
- if (content.length > this.MAX_MESSAGE_LENGTH) {
|
|
|
|
|
- return res
|
|
|
|
|
- .status(400)
|
|
|
|
|
- .send(`Content too long (> ${this.MAX_MESSAGE_LENGTH} bytes)`)
|
|
|
|
|
- }
|
|
|
|
|
- logger.log(
|
|
|
|
|
- { clientThreadId, projectId, userId, content },
|
|
|
|
|
- 'new message received'
|
|
|
|
|
- )
|
|
|
|
|
- ThreadManager.findOrCreateThread(
|
|
|
|
|
- projectId,
|
|
|
|
|
- clientThreadId,
|
|
|
|
|
- function (error, thread) {
|
|
|
|
|
|
|
+ MessageManager.deleteMessage(
|
|
|
|
|
+ room._id,
|
|
|
|
|
+ messageId,
|
|
|
|
|
+ function (error, message) {
|
|
|
if (error) {
|
|
if (error) {
|
|
|
return next(error)
|
|
return next(error)
|
|
|
}
|
|
}
|
|
|
- MessageManager.createMessage(
|
|
|
|
|
- thread._id,
|
|
|
|
|
- userId,
|
|
|
|
|
- content,
|
|
|
|
|
- Date.now(),
|
|
|
|
|
- function (error, message) {
|
|
|
|
|
- if (error) {
|
|
|
|
|
- return next(error)
|
|
|
|
|
- }
|
|
|
|
|
- message = MessageFormatter.formatMessageForClientSide(message)
|
|
|
|
|
- message.room_id = projectId
|
|
|
|
|
- res.status(201).send(message)
|
|
|
|
|
- }
|
|
|
|
|
- )
|
|
|
|
|
|
|
+ res.sendStatus(204)
|
|
|
}
|
|
}
|
|
|
)
|
|
)
|
|
|
- },
|
|
|
|
|
|
|
+ })
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- _getMessages(clientThreadId, req, res, next) {
|
|
|
|
|
- let before, limit
|
|
|
|
|
- const { projectId } = req.params
|
|
|
|
|
- if (req.query.before) {
|
|
|
|
|
- before = parseInt(req.query.before, 10)
|
|
|
|
|
- } else {
|
|
|
|
|
- before = null
|
|
|
|
|
- }
|
|
|
|
|
- if (req.query.limit) {
|
|
|
|
|
- limit = parseInt(req.query.limit, 10)
|
|
|
|
|
- } else {
|
|
|
|
|
- limit = MessageHttpController.DEFAULT_MESSAGE_LIMIT
|
|
|
|
|
- }
|
|
|
|
|
- logger.log(
|
|
|
|
|
- { limit, before, projectId, clientThreadId },
|
|
|
|
|
- 'get message request received'
|
|
|
|
|
- )
|
|
|
|
|
- ThreadManager.findOrCreateThread(
|
|
|
|
|
- projectId,
|
|
|
|
|
- clientThreadId,
|
|
|
|
|
- function (error, thread) {
|
|
|
|
|
- if (error) {
|
|
|
|
|
- return next(error)
|
|
|
|
|
- }
|
|
|
|
|
- const threadObjectId = thread._id
|
|
|
|
|
- logger.log(
|
|
|
|
|
- { limit, before, projectId, clientThreadId, threadObjectId },
|
|
|
|
|
- 'found or created thread'
|
|
|
|
|
- )
|
|
|
|
|
- MessageManager.getMessages(
|
|
|
|
|
- threadObjectId,
|
|
|
|
|
- limit,
|
|
|
|
|
- before,
|
|
|
|
|
- function (error, messages) {
|
|
|
|
|
- if (error) {
|
|
|
|
|
- return next(error)
|
|
|
|
|
- }
|
|
|
|
|
- messages = MessageFormatter.formatMessagesForClientSide(messages)
|
|
|
|
|
- logger.log({ projectId, messages }, 'got messages')
|
|
|
|
|
- res.status(200).send(messages)
|
|
|
|
|
|
|
+function _sendMessage(clientThreadId, req, res, next) {
|
|
|
|
|
+ const { user_id: userId, content } = req.body
|
|
|
|
|
+ const { projectId } = req.params
|
|
|
|
|
+ if (!ObjectId.isValid(userId)) {
|
|
|
|
|
+ return res.status(400).send('Invalid userId')
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!content) {
|
|
|
|
|
+ return res.status(400).send('No content provided')
|
|
|
|
|
+ }
|
|
|
|
|
+ if (content.length > MAX_MESSAGE_LENGTH) {
|
|
|
|
|
+ return res
|
|
|
|
|
+ .status(400)
|
|
|
|
|
+ .send(`Content too long (> ${MAX_MESSAGE_LENGTH} bytes)`)
|
|
|
|
|
+ }
|
|
|
|
|
+ logger.log(
|
|
|
|
|
+ { clientThreadId, projectId, userId, content },
|
|
|
|
|
+ 'new message received'
|
|
|
|
|
+ )
|
|
|
|
|
+ ThreadManager.findOrCreateThread(
|
|
|
|
|
+ projectId,
|
|
|
|
|
+ clientThreadId,
|
|
|
|
|
+ function (error, thread) {
|
|
|
|
|
+ if (error) {
|
|
|
|
|
+ return next(error)
|
|
|
|
|
+ }
|
|
|
|
|
+ MessageManager.createMessage(
|
|
|
|
|
+ thread._id,
|
|
|
|
|
+ userId,
|
|
|
|
|
+ content,
|
|
|
|
|
+ Date.now(),
|
|
|
|
|
+ function (error, message) {
|
|
|
|
|
+ if (error) {
|
|
|
|
|
+ return next(error)
|
|
|
}
|
|
}
|
|
|
- )
|
|
|
|
|
|
|
+ message = MessageFormatter.formatMessageForClientSide(message)
|
|
|
|
|
+ message.room_id = projectId
|
|
|
|
|
+ res.status(201).send(message)
|
|
|
|
|
+ }
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+ )
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function _getMessages(clientThreadId, req, res, next) {
|
|
|
|
|
+ let before, limit
|
|
|
|
|
+ const { projectId } = req.params
|
|
|
|
|
+ if (req.query.before) {
|
|
|
|
|
+ before = parseInt(req.query.before, 10)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ before = null
|
|
|
|
|
+ }
|
|
|
|
|
+ if (req.query.limit) {
|
|
|
|
|
+ limit = parseInt(req.query.limit, 10)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ limit = DEFAULT_MESSAGE_LIMIT
|
|
|
|
|
+ }
|
|
|
|
|
+ logger.log(
|
|
|
|
|
+ { limit, before, projectId, clientThreadId },
|
|
|
|
|
+ 'get message request received'
|
|
|
|
|
+ )
|
|
|
|
|
+ ThreadManager.findOrCreateThread(
|
|
|
|
|
+ projectId,
|
|
|
|
|
+ clientThreadId,
|
|
|
|
|
+ function (error, thread) {
|
|
|
|
|
+ if (error) {
|
|
|
|
|
+ return next(error)
|
|
|
}
|
|
}
|
|
|
- )
|
|
|
|
|
- },
|
|
|
|
|
|
|
+ const threadObjectId = thread._id
|
|
|
|
|
+ logger.log(
|
|
|
|
|
+ { limit, before, projectId, clientThreadId, threadObjectId },
|
|
|
|
|
+ 'found or created thread'
|
|
|
|
|
+ )
|
|
|
|
|
+ MessageManager.getMessages(
|
|
|
|
|
+ threadObjectId,
|
|
|
|
|
+ limit,
|
|
|
|
|
+ before,
|
|
|
|
|
+ function (error, messages) {
|
|
|
|
|
+ if (error) {
|
|
|
|
|
+ return next(error)
|
|
|
|
|
+ }
|
|
|
|
|
+ messages = MessageFormatter.formatMessagesForClientSide(messages)
|
|
|
|
|
+ logger.log({ projectId, messages }, 'got messages')
|
|
|
|
|
+ res.status(200).send(messages)
|
|
|
|
|
+ }
|
|
|
|
|
+ )
|
|
|
|
|
+ }
|
|
|
|
|
+ )
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+module.exports = {
|
|
|
|
|
+ getGlobalMessages,
|
|
|
|
|
+ sendGlobalMessage,
|
|
|
|
|
+ sendThreadMessage,
|
|
|
|
|
+ getAllThreads,
|
|
|
|
|
+ resolveThread,
|
|
|
|
|
+ reopenThread,
|
|
|
|
|
+ deleteThread,
|
|
|
|
|
+ editMessage,
|
|
|
|
|
+ deleteMessage,
|
|
|
}
|
|
}
|