diff --git a/services/chat/app/js/Features/Messages/MessageHttpController.js b/services/chat/app/js/Features/Messages/MessageHttpController.js index 25ef35b0ff..f523434c31 100644 --- a/services/chat/app/js/Features/Messages/MessageHttpController.js +++ b/services/chat/app/js/Features/Messages/MessageHttpController.js @@ -70,6 +70,18 @@ async function deleteMessage(req, res) { 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) { const { user_id: userId, content } = req.body const { projectId } = req.params @@ -145,4 +157,5 @@ module.exports = { deleteThread: expressify(deleteThread), editMessage: expressify(editMessage), deleteMessage: expressify(deleteMessage), + destroyProject: expressify(destroyProject), } diff --git a/services/chat/app/js/Features/Messages/MessageManager.js b/services/chat/app/js/Features/Messages/MessageManager.js index e2dcdc5f71..694a56e410 100644 --- a/services/chat/app/js/Features/Messages/MessageManager.js +++ b/services/chat/app/js/Features/Messages/MessageManager.js @@ -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) { const query = _ensureIdsAreObjectIds({ _id: messageId, @@ -78,6 +84,7 @@ module.exports = MessageManager = { getMessages, findAllMessagesInRooms, deleteAllMessagesInRoom, + deleteAllMessagesInRooms, updateMessage, deleteMessage, } diff --git a/services/chat/app/js/Features/Threads/ThreadManager.js b/services/chat/app/js/Features/Threads/ThreadManager.js index 1dcdc191e6..414b78b45a 100644 --- a/services/chat/app/js/Features/Threads/ThreadManager.js +++ b/services/chat/app/js/Features/Threads/ThreadManager.js @@ -54,6 +54,20 @@ async function findAllThreadRooms(projectId) { .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) { await db.rooms.updateOne( { @@ -93,13 +107,21 @@ async function deleteThread(projectId, threadId) { return room._id } +async function deleteAllThreadsInProject(projectId) { + await db.rooms.deleteMany({ + project_id: ObjectId(projectId.toString()), + }) +} + module.exports = ThreadManager = { GLOBAL_THREAD, findOrCreateThread, findAllThreadRooms, + findAllThreadRoomsAndGlobalThread, resolveThread, reopenThread, deleteThread, + deleteAllThreadsInProject, } ;[ 'findOrCreateThread', diff --git a/services/chat/app/js/router.js b/services/chat/app/js/router.js index 46b19c1f25..73a1e6c0bd 100644 --- a/services/chat/app/js/router.js +++ b/services/chat/app/js/router.js @@ -66,6 +66,8 @@ module.exports = { MessageHttpController.deleteThread ) + app.delete('/project/:projectId', MessageHttpController.destroyProject) + app.get('/status', (req, res, next) => res.send('chat is alive')) }, } diff --git a/services/chat/test/acceptance/js/DestroyingAProjectTests.js b/services/chat/test/acceptance/js/DestroyingAProjectTests.js new file mode 100644 index 0000000000..e4a45dbf00 --- /dev/null +++ b/services/chat/test/acceptance/js/DestroyingAProjectTests.js @@ -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 + }) + }) +}) diff --git a/services/chat/test/acceptance/js/helpers/ChatApp.js b/services/chat/test/acceptance/js/helpers/ChatApp.js index b29961a360..dde9648533 100644 --- a/services/chat/test/acceptance/js/helpers/ChatApp.js +++ b/services/chat/test/acceptance/js/helpers/ChatApp.js @@ -1,4 +1,4 @@ -const { waitForDb } = require('../../../../app/js/mongodb') +const { db, waitForDb } = require('../../../../app/js/mongodb') const app = require('../../../../app') let serverPromise = null @@ -23,5 +23,6 @@ async function ensureRunning() { } module.exports = { + db, ensureRunning, } diff --git a/services/chat/test/acceptance/js/helpers/ChatClient.js b/services/chat/test/acceptance/js/helpers/ChatClient.js index 82a695c624..73239792dd 100644 --- a/services/chat/test/acceptance/js/helpers/ChatClient.js +++ b/services/chat/test/acceptance/js/helpers/ChatClient.js @@ -93,6 +93,13 @@ async function deleteMessage(projectId, threadId, messageId) { }) } +async function destroyProject(projectId) { + return asyncRequest({ + method: 'delete', + url: `/project/${projectId}`, + }) +} + module.exports = { sendGlobalMessage, getGlobalMessages, @@ -103,4 +110,5 @@ module.exports = { deleteThread, editMessage, deleteMessage, + destroyProject, }