From fa63eb69476bec2e7f486e085f01d51913ec2f95 Mon Sep 17 00:00:00 2001 From: James Allen Date: Tue, 24 Jan 2017 15:44:32 +0100 Subject: [PATCH] Allow editing/deleting of comments and threads --- .../Features/Messages/MessageFormatter.coffee | 2 ++ .../Messages/MessageHttpController.coffee | 28 +++++++++++++++ .../Features/Messages/MessageManager.coffee | 31 +++++++++++++++++ .../Features/Threads/ThreadManager.coffee | 9 +++++ services/chat/app/coffee/router.coffee | 6 ++-- .../coffee/DeletingAMessageTests.coffee | 30 ++++++++++++++++ .../coffee/DeletingAThreadTests.coffee | 29 ++++++++++++++++ .../coffee/EditingAMessageTests.coffee | 34 +++++++++++++++++++ .../coffee/helpers/ChatClient.coffee | 19 ++++++++++- 9 files changed, 184 insertions(+), 4 deletions(-) create mode 100644 services/chat/test/acceptance/coffee/DeletingAMessageTests.coffee create mode 100644 services/chat/test/acceptance/coffee/DeletingAThreadTests.coffee create mode 100644 services/chat/test/acceptance/coffee/EditingAMessageTests.coffee diff --git a/services/chat/app/coffee/Features/Messages/MessageFormatter.coffee b/services/chat/app/coffee/Features/Messages/MessageFormatter.coffee index 012f1f8882..8f3fdf3e04 100644 --- a/services/chat/app/coffee/Features/Messages/MessageFormatter.coffee +++ b/services/chat/app/coffee/Features/Messages/MessageFormatter.coffee @@ -8,6 +8,8 @@ module.exports = MessageFormatter = content: message.content timestamp: message.timestamp user_id: message.user_id + if message.edited_at? + formattedMessage.edited_at = message.edited_at return formattedMessage formatMessagesForClientSide: (messages) -> diff --git a/services/chat/app/coffee/Features/Messages/MessageHttpController.coffee b/services/chat/app/coffee/Features/Messages/MessageHttpController.coffee index d36206afe9..ce819e7b00 100644 --- a/services/chat/app/coffee/Features/Messages/MessageHttpController.coffee +++ b/services/chat/app/coffee/Features/Messages/MessageHttpController.coffee @@ -42,6 +42,34 @@ module.exports = MessageHttpController = ThreadManager.reopenThread project_id, thread_id, (error) -> return next(error) if error? res.send 204 # No content + + deleteThread: (req, res, next) -> + {project_id, thread_id} = req.params + logger.log {project_id, thread_id}, "deleting thread" + ThreadManager.deleteThread project_id, thread_id, (error, room_id) -> + return next(error) if error? + MessageManager.deleteAllMessagesInRoom room_id, (error) -> + return next(error) if error? + res.send 204 # No content + + editMessage: (req, res, next) -> + {content} = req?.body + {project_id, thread_id, message_id} = req.params + logger.log {project_id, thread_id, message_id, content}, "editing message" + ThreadManager.findOrCreateThread project_id, thread_id, (error, room) -> + return next(error) if error? + MessageManager.updateMessage room._id, message_id, content, Date.now(), (error) -> + return next(error) if error? + res.send(200) + + deleteMessage: (req, res, next) -> + {project_id, thread_id, message_id} = req.params + logger.log {project_id, thread_id, message_id}, "deleting message" + ThreadManager.findOrCreateThread project_id, thread_id, (error, room) -> + return next(error) if error? + MessageManager.deleteMessage room._id, message_id, (error, message) -> + return next(error) if error? + res.send(204) _sendMessage: (client_thread_id, req, res, next) -> {user_id, content} = req?.body diff --git a/services/chat/app/coffee/Features/Messages/MessageManager.coffee b/services/chat/app/coffee/Features/Messages/MessageManager.coffee index 317721ea28..a5a0fbd362 100644 --- a/services/chat/app/coffee/Features/Messages/MessageManager.coffee +++ b/services/chat/app/coffee/Features/Messages/MessageManager.coffee @@ -27,10 +27,41 @@ module.exports = MessageManager = room_id: { $in: room_ids } }, callback + deleteAllMessagesInRoom: (room_id, callback = (error) ->) -> + db.messages.remove { + room_id: room_id + }, callback + + updateMessage: (room_id, message_id, content, timestamp, callback = (error, message) ->) -> + query = @_ensureIdsAreObjectIds( + _id: message_id + room_id: room_id + ) + db.messages.update query, { + $set: + content: content + edited_at: timestamp + }, (error) -> + return callback(error) if error? + db.messages.find query, (error, messages) -> + return callback(error) if error? + return callback null, messages[0] + + deleteMessage: (room_id, message_id, callback = (error) ->) -> + query = @_ensureIdsAreObjectIds( + _id: message_id + room_id: room_id + ) + db.messages.remove query, (error) -> + return callback(error) if error? + return callback() + _ensureIdsAreObjectIds: (query) -> if query.user_id? and query.user_id not instanceof ObjectId query.user_id = ObjectId(query.user_id) if query.room_id? and query.room_id not instanceof ObjectId query.room_id = ObjectId(query.room_id) + if query._id? and query._id not instanceof ObjectId + query._id = ObjectId(query._id) return query diff --git a/services/chat/app/coffee/Features/Threads/ThreadManager.coffee b/services/chat/app/coffee/Features/Threads/ThreadManager.coffee index 8adee1591e..e8cd943495 100644 --- a/services/chat/app/coffee/Features/Threads/ThreadManager.coffee +++ b/services/chat/app/coffee/Features/Threads/ThreadManager.coffee @@ -53,3 +53,12 @@ module.exports = ThreadManager = resolved: true } }, callback + + deleteThread: (project_id, thread_id, callback = (error, room_id) ->) -> + @findOrCreateThread project_id, thread_id, (error, room) -> + return callback(error) if error? + db.rooms.remove { + _id: room._id + }, (error) -> + return callback(error) if error? + return callback null, room._id diff --git a/services/chat/app/coffee/router.coffee b/services/chat/app/coffee/router.coffee index 88179b7f3a..79004235e7 100644 --- a/services/chat/app/coffee/router.coffee +++ b/services/chat/app/coffee/router.coffee @@ -25,12 +25,12 @@ module.exports = Router = app.post "/project/:project_id/thread/:thread_id/messages", MessageHttpController.sendThreadMessage app.get "/project/:project_id/threads", MessageHttpController.getAllThreads - # app.post "/project/:project_id/thread/:thread_id/messages/:message_id/edit", MessageHttpController.editMessage - # app.del "/project/:project_id/thread/:thread_id/messages/:message_id", MessageHttpController.deleteMessage + app.post "/project/:project_id/thread/:thread_id/messages/:message_id/edit", MessageHttpController.editMessage + app.del "/project/:project_id/thread/:thread_id/messages/:message_id", MessageHttpController.deleteMessage app.post "/project/:project_id/thread/:thread_id/resolve", MessageHttpController.resolveThread app.post "/project/:project_id/thread/:thread_id/reopen", MessageHttpController.reopenThread - # app.del "/project/:project_id/thread/:thread_id", MessageHttpController.deleteThread + app.del "/project/:project_id/thread/:thread_id", MessageHttpController.deleteThread app.get "/status", (req, res, next) -> res.send("chat is alive") diff --git a/services/chat/test/acceptance/coffee/DeletingAMessageTests.coffee b/services/chat/test/acceptance/coffee/DeletingAMessageTests.coffee new file mode 100644 index 0000000000..65c183d0f0 --- /dev/null +++ b/services/chat/test/acceptance/coffee/DeletingAMessageTests.coffee @@ -0,0 +1,30 @@ +{ObjectId} = require "../../../app/js/mongojs" +expect = require("chai").expect + +ChatClient = require "./helpers/ChatClient" + +describe "Deleting a message", -> + before -> + @project_id = ObjectId().toString() + @user_id = ObjectId().toString() + @thread_id = ObjectId().toString() + + describe "in a thread", -> + before (done) -> + ChatClient.sendMessage @project_id, @thread_id, @user_id, "first message", (error, response, @message) => + expect(error).to.be.null + expect(response.statusCode).to.equal 201 + ChatClient.sendMessage @project_id, @thread_id, @user_id, "deleted message", (error, response, @message) => + expect(error).to.be.null + expect(response.statusCode).to.equal 201 + ChatClient.deleteMessage @project_id, @thread_id, @message.id, (error, response, body) => + expect(error).to.be.null + expect(response.statusCode).to.equal 204 + done() + + it "should then remove the message from the threads", (done) -> + ChatClient.getThreads @project_id, (error, response, threads) => + expect(error).to.be.null + expect(response.statusCode).to.equal 200 + expect(threads[@thread_id].messages.length).to.equal 1 + done() \ No newline at end of file diff --git a/services/chat/test/acceptance/coffee/DeletingAThreadTests.coffee b/services/chat/test/acceptance/coffee/DeletingAThreadTests.coffee new file mode 100644 index 0000000000..850bcf0ef0 --- /dev/null +++ b/services/chat/test/acceptance/coffee/DeletingAThreadTests.coffee @@ -0,0 +1,29 @@ +{ObjectId} = require "../../../app/js/mongojs" +expect = require("chai").expect +crypto = require "crypto" + +ChatClient = require "./helpers/ChatClient" + +describe "Deleting a thread", -> + before -> + @project_id = ObjectId().toString() + @user_id = ObjectId().toString() + + describe "with a thread that is deleted", -> + before (done) -> + @thread_id = ObjectId().toString() + @content = "deleted thread message" + ChatClient.sendMessage @project_id, @thread_id, @user_id, @content, (error, response, body) => + expect(error).to.be.null + expect(response.statusCode).to.equal 201 + ChatClient.deleteThread @project_id, @thread_id, (error, response, body) => + expect(error).to.be.null + expect(response.statusCode).to.equal 204 + done() + + it "should then not list the thread for the project", (done) -> + ChatClient.getThreads @project_id, (error, response, threads) => + expect(error).to.be.null + expect(response.statusCode).to.equal 200 + expect(Object.keys(threads).length).to.equal 0 + done() diff --git a/services/chat/test/acceptance/coffee/EditingAMessageTests.coffee b/services/chat/test/acceptance/coffee/EditingAMessageTests.coffee new file mode 100644 index 0000000000..0add6f3825 --- /dev/null +++ b/services/chat/test/acceptance/coffee/EditingAMessageTests.coffee @@ -0,0 +1,34 @@ +{ObjectId} = require "../../../app/js/mongojs" +expect = require("chai").expect + +ChatClient = require "./helpers/ChatClient" + +describe "Editing a message", -> + before -> + @project_id = ObjectId().toString() + @user_id = ObjectId().toString() + @thread_id = ObjectId().toString() + + describe "in a thread", -> + before (done) -> + @content = "thread message" + @new_content = "updated thread message" + ChatClient.sendMessage @project_id, @thread_id, @user_id, @content, (error, response, @message) => + expect(error).to.be.null + expect(response.statusCode).to.equal 201 + expect(@message.id).to.exist + expect(@message.content).to.equal @content + ChatClient.editMessage @project_id, @thread_id, @message.id, @new_content, (error, response, @new_message) => + expect(error).to.be.null + expect(response.statusCode).to.equal 201 + expect(@new_message.edited_at).to.exist + expect(@new_message.content).to.equal @new_content + done() + + it "should then list the updated message in the threads", (done) -> + ChatClient.getThreads @project_id, (error, response, threads) => + expect(error).to.be.null + expect(response.statusCode).to.equal 200 + expect(threads[@thread_id].messages.length).to.equal 1 + expect(threads[@thread_id].messages[0].content).to.equal @new_content + done() \ No newline at end of file diff --git a/services/chat/test/acceptance/coffee/helpers/ChatClient.coffee b/services/chat/test/acceptance/coffee/helpers/ChatClient.coffee index 1b7d747bbe..902d743d21 100644 --- a/services/chat/test/acceptance/coffee/helpers/ChatClient.coffee +++ b/services/chat/test/acceptance/coffee/helpers/ChatClient.coffee @@ -40,4 +40,21 @@ module.exports = reopenThread: (project_id, thread_id, callback) -> request.post { url: "/project/#{project_id}/thread/#{thread_id}/reopen", - }, callback \ No newline at end of file + }, callback + + deleteThread: (project_id, thread_id, callback) -> + request.del { + url: "/project/#{project_id}/thread/#{thread_id}", + }, callback + + editMessage: (project_id, thread_id, message_id, content, callback) -> + request.post { + url: "/project/#{project_id}/thread/#{thread_id}/messages/#{message_id}/edit" + json: + content: content + }, callback + + deleteMessage: (project_id, thread_id, message_id, callback) -> + request.del { + url: "/project/#{project_id}/thread/#{thread_id}/messages/#{message_id}", + }, callback