Merge pull request #6996 from overleaf/tm-expired-project-chat

Add endpoints to chat for deleting expired project chat data

GitOrigin-RevId: e4eb7c7a79472bb116b2095a76c870e204590288
This commit is contained in:
Thomas 2022-03-16 13:20:52 +01:00 committed by Copybot
parent a28e0eaab0
commit 4cc888ce2f
7 changed files with 121 additions and 1 deletions

View file

@ -70,6 +70,18 @@ async function deleteMessage(req, res) {
res.sendStatus(204) res.sendStatus(204)
} }
async function destroyProject(req, res) {
const { projectId } = req.params
logger.log({ projectId }, 'destroying project')
const rooms = await ThreadManager.findAllThreadRoomsAndGlobalThread(projectId)
const roomIds = rooms.map(r => r._id)
logger.log({ projectId, roomIds }, 'deleting all messages in rooms')
await MessageManager.deleteAllMessagesInRooms(roomIds)
logger.log({ projectId }, 'deleting all threads in project')
await ThreadManager.deleteAllThreadsInProject(projectId)
res.sendStatus(204)
}
async function _sendMessage(clientThreadId, req, res) { async function _sendMessage(clientThreadId, req, res) {
const { user_id: userId, content } = req.body const { user_id: userId, content } = req.body
const { projectId } = req.params const { projectId } = req.params
@ -145,4 +157,5 @@ module.exports = {
deleteThread: expressify(deleteThread), deleteThread: expressify(deleteThread),
editMessage: expressify(editMessage), editMessage: expressify(editMessage),
deleteMessage: expressify(deleteMessage), deleteMessage: expressify(deleteMessage),
destroyProject: expressify(destroyProject),
} }

View file

@ -39,6 +39,12 @@ async function deleteAllMessagesInRoom(roomId) {
}) })
} }
async function deleteAllMessagesInRooms(roomIds) {
await db.messages.deleteMany({
room_id: { $in: roomIds },
})
}
async function updateMessage(roomId, messageId, content, timestamp) { async function updateMessage(roomId, messageId, content, timestamp) {
const query = _ensureIdsAreObjectIds({ const query = _ensureIdsAreObjectIds({
_id: messageId, _id: messageId,
@ -78,6 +84,7 @@ module.exports = MessageManager = {
getMessages, getMessages,
findAllMessagesInRooms, findAllMessagesInRooms,
deleteAllMessagesInRoom, deleteAllMessagesInRoom,
deleteAllMessagesInRooms,
updateMessage, updateMessage,
deleteMessage, deleteMessage,
} }

View file

@ -54,6 +54,20 @@ async function findAllThreadRooms(projectId) {
.toArray() .toArray()
} }
async function findAllThreadRoomsAndGlobalThread(projectId) {
return db.rooms
.find(
{
project_id: ObjectId(projectId.toString()),
},
{
thread_id: 1,
resolved: 1,
}
)
.toArray()
}
async function resolveThread(projectId, threadId, userId) { async function resolveThread(projectId, threadId, userId) {
await db.rooms.updateOne( await db.rooms.updateOne(
{ {
@ -93,13 +107,21 @@ async function deleteThread(projectId, threadId) {
return room._id return room._id
} }
async function deleteAllThreadsInProject(projectId) {
await db.rooms.deleteMany({
project_id: ObjectId(projectId.toString()),
})
}
module.exports = ThreadManager = { module.exports = ThreadManager = {
GLOBAL_THREAD, GLOBAL_THREAD,
findOrCreateThread, findOrCreateThread,
findAllThreadRooms, findAllThreadRooms,
findAllThreadRoomsAndGlobalThread,
resolveThread, resolveThread,
reopenThread, reopenThread,
deleteThread, deleteThread,
deleteAllThreadsInProject,
} }
;[ ;[
'findOrCreateThread', 'findOrCreateThread',

View file

@ -66,6 +66,8 @@ module.exports = {
MessageHttpController.deleteThread MessageHttpController.deleteThread
) )
app.delete('/project/:projectId', MessageHttpController.destroyProject)
app.get('/status', (req, res, next) => res.send('chat is alive')) app.get('/status', (req, res, next) => res.send('chat is alive'))
}, },
} }

View file

@ -0,0 +1,67 @@
const { ObjectId } = require('../../../app/js/mongodb')
const { expect } = require('chai')
const ChatClient = require('./helpers/ChatClient')
const ChatApp = require('./helpers/ChatApp')
const db = ChatApp.db
async function getMessage(messageId) {
return await db.messages.findOne({
_id: ObjectId(messageId),
})
}
describe('Destroying a project', async function () {
const projectId = ObjectId().toString()
const userId = ObjectId().toString()
before(async function () {
await ChatApp.ensureRunning()
})
describe('with a project that has threads and messages', async function () {
const threadId = ObjectId().toString()
before(async function () {
const { response } = await ChatClient.sendMessage(
projectId,
threadId,
userId,
'destroyed thread message'
)
expect(response.statusCode).to.equal(201)
this.threadMessageId = response.body.id
const { response: response2 } = await ChatClient.sendGlobalMessage(
projectId,
userId,
'destroyed global message'
)
expect(response2.statusCode).to.equal(201)
this.globalThreadMessageId = response2.body.id
const threadRooms = await db.rooms
.find({ project_id: ObjectId(projectId) })
.toArray()
expect(threadRooms.length).to.equal(2)
const threadMessage = await getMessage(this.threadMessageId)
expect(threadMessage).to.exist
const globalThreadMessage = await getMessage(this.globalThreadMessageId)
expect(globalThreadMessage).to.exist
const { response: responseDestroy } = await ChatClient.destroyProject(
projectId
)
expect(responseDestroy.statusCode).to.equal(204)
})
it('should remove the messages and threads from the database', async function () {
const threadRooms = await db.rooms
.find({ project_id: ObjectId(projectId) })
.toArray()
expect(threadRooms.length).to.equal(0)
const threadMessage = await getMessage(this.threadMessageId)
expect(threadMessage).to.be.null
const globalThreadMessage = await getMessage(this.globalThreadMessageId)
expect(globalThreadMessage).to.be.null
})
})
})

View file

@ -1,4 +1,4 @@
const { waitForDb } = require('../../../../app/js/mongodb') const { db, waitForDb } = require('../../../../app/js/mongodb')
const app = require('../../../../app') const app = require('../../../../app')
let serverPromise = null let serverPromise = null
@ -23,5 +23,6 @@ async function ensureRunning() {
} }
module.exports = { module.exports = {
db,
ensureRunning, ensureRunning,
} }

View file

@ -93,6 +93,13 @@ async function deleteMessage(projectId, threadId, messageId) {
}) })
} }
async function destroyProject(projectId) {
return asyncRequest({
method: 'delete',
url: `/project/${projectId}`,
})
}
module.exports = { module.exports = {
sendGlobalMessage, sendGlobalMessage,
getGlobalMessages, getGlobalMessages,
@ -103,4 +110,5 @@ module.exports = {
deleteThread, deleteThread,
editMessage, editMessage,
deleteMessage, deleteMessage,
destroyProject,
} }