From df7fd2e0360a105c07e612945ee7a13fb730755e Mon Sep 17 00:00:00 2001 From: Saravanan Ganesh Date: Mon, 19 Oct 2015 21:43:24 -0700 Subject: [PATCH 1/4] fix(chat): #5864 API should return flagged messages in chat only to mods --- website/src/controllers/groups.js | 8 ++++++++ website/views/options/social/chat-message.jade | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/website/src/controllers/groups.js b/website/src/controllers/groups.js index 573142887c..391a16c15e 100644 --- a/website/src/controllers/groups.js +++ b/website/src/controllers/groups.js @@ -149,6 +149,10 @@ api.get = function(req, res, next) { // so that users with no party don't get a 404 on every access to the site return res.json(group); } + //Remove flagged messages if the user is not mod + if (!user.contributor.admin) { + group.chat = _.filter(group.chat, function(message) { return !message.flagCount || message.flagCount < 2; }); + } //Since we have a limit on how many members are populate to the group, we want to make sure the user is always in the group var userInGroup = _.find(group.members, function(member){ return member._id == user._id; }); //If the group is private or the group is a party, then the user must be a member of the group based on access restrictions above @@ -271,6 +275,10 @@ api.getChat = function(req, res, next) { q.exec(function(err, group){ if (err) return next(err); if (!group && gid!=='party') return res.json(404,{err: "Group not found or you don't have access."}); + //Remove flagged messages if the user is not mod + if (!user.contributor.admin) { + group.chat = _.filter(group.chat, function(message) { return !message.flagCount || message.flagCount < 2; }); + } res.json(res.locals.group.chat); gid = null; }); diff --git a/website/views/options/social/chat-message.jade b/website/views/options/social/chat-message.jade index 9404665ebe..de63f5cd98 100644 --- a/website/views/options/social/chat-message.jade +++ b/website/views/options/social/chat-message.jade @@ -1,7 +1,7 @@ mixin chatMessages(inbox) ul.list-unstyled.tavern-chat - var ngRepeat = inbox ? 'message in user.inbox.messages | toArray:true | orderBy:"sort":true' : 'message in group.chat track by message.id' - li.chat-message(ng-repeat=ngRepeat, ng-class=':: {highlight: isUserMentioned(user,message) || message.uuid=="system", "own-message": user._id == message.uuid}', ng-if="!message.flagCount || message.flagCount < 2 || user.contributor.admin") + li.chat-message(ng-repeat=ngRepeat, ng-class=':: {highlight: isUserMentioned(user,message) || message.uuid=="system", "own-message": user._id == message.uuid}') span.pull-right.text-danger(ng-if="user.contributor.admin && message.flagCount > 0") | {{message.flagCount > 1 ? "Message Hidden" : "1 flag"}} .scrollable-message(ng-class='{"transparent": message.sent || message.flags[user._id] || (user.contributor.admin && message.flagCount > 1)}') From 6f3be779612f386e18f199d2ddfdfaed766a52e4 Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Mon, 2 Nov 2015 07:46:21 -0600 Subject: [PATCH 2/4] Add tests for flagged messages in get group object test --- test/api/groups/GET-groups_id.test.js | 126 ++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) diff --git a/test/api/groups/GET-groups_id.test.js b/test/api/groups/GET-groups_id.test.js index 786bc45b83..aecd6b4c90 100644 --- a/test/api/groups/GET-groups_id.test.js +++ b/test/api/groups/GET-groups_id.test.js @@ -82,6 +82,132 @@ describe('GET /groups/:id', () => { }); }); + context('flagged messages', () => { + let group; + + let chat1 = { + id: 'chat1', + text: 'chat 1', + flags: {}, + }; + + let chat2 = { + id: 'chat2', + text: 'chat 2', + flags: {}, + flagCount: 0, + }; + + let chat3 = { + id: 'chat3', + text: 'chat 3', + flags: { + 'user-id': true, + }, + flagCount: 1, + }; + + let chat4 = { + id: 'chat4', + text: 'chat 4', + flags: { + 'user-id': true, + 'other-user-id': true, + }, + flagCount: 2, + }; + + let chat5 = { + id: 'chat5', + text: 'chat 5', + flags: { + 'user-id': true, + 'other-user-id': true, + 'yet-another-user-id': true, + }, + flagCount: 3, + }; + + beforeEach(() => { + return createAndPopulateGroup({ + groupDetails: { + name: 'test guild', + type: 'guild', + privacy: 'public', + chat: [ + chat1, + chat2, + chat3, + chat4, + chat5, + ], + }, + }).then((res) => { + group = res.group; + }); + }); + + context('non-admin', () => { + let api; + + beforeEach(() => { + return generateUser().then((user) => { + api = requester(user); + }); + }); + + it('does not include messages with a flag count of 2 or greater', () => { + return api.get(`/groups/${group._id}`).then((_group) => { + expect(_group.chat).to.have.lengthOf(3); + expect(_group.chat[0].id).to.eql(chat1.id); + expect(_group.chat[1].id).to.eql(chat2.id); + expect(_group.chat[2].id).to.eql(chat3.id); + }); + }); + + it('does not include user ids in flags object', () => { + return api.get(`/groups/${group._id}`).then((_group) => { + let chatWithOneFlag = _group.chat[2]; + expect(chatWithOneFlag.id).to.eql(chat3.id); + expect(chat3.flags).to.eql({ 'user-id': true }); + expect(chatWithOneFlag.flags).to.eql({}); + }); + }); + }); + + context('admin', () => { + let api; + + beforeEach(() => { + return generateUser({ + 'contributor.admin': true, + }).then((user) => { + api = requester(user); + }); + }); + + it('includes all messages', () => { + return api.get(`/groups/${group._id}`).then((_group) => { + expect(_group.chat).to.have.lengthOf(5); + expect(_group.chat[0].id).to.eql(chat1.id); + expect(_group.chat[1].id).to.eql(chat2.id); + expect(_group.chat[2].id).to.eql(chat3.id); + expect(_group.chat[3].id).to.eql(chat4.id); + expect(_group.chat[4].id).to.eql(chat5.id); + }); + }); + + xit('TODO: Not yet implimented - includes user ids in flags object', () => { + return api.get(`/groups/${group._id}`).then((_group) => { + let chatWithOneFlag = _group.chat[2]; + expect(chatWithOneFlag.id).to.eql(chat3.id); + expect(chat3.flags).to.eql({ 'user-id': true }); + expect(chatWithOneFlag.flags).to.eql(chat3.flags); + }); + }); + }); + }); + context('Non-member of a public guild', () => { let leader, nonMember, createdGroup; From 1a68b5e9ee8cd2e52c2a40706d167172528b01ef Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Tue, 3 Nov 2015 08:00:14 -0600 Subject: [PATCH 3/4] Refactor and add tests to flagged messages. --- test/api/groups/GET-groups_id.test.js | 2 +- .../chat/POST-groups_id_chat_id_flag.test.js | 2 +- website/src/controllers/api-v2/groups.js | 23 ++++++++++++++----- website/src/models/group.js | 5 ---- 4 files changed, 19 insertions(+), 13 deletions(-) diff --git a/test/api/groups/GET-groups_id.test.js b/test/api/groups/GET-groups_id.test.js index aecd6b4c90..f2f69e0d3a 100644 --- a/test/api/groups/GET-groups_id.test.js +++ b/test/api/groups/GET-groups_id.test.js @@ -197,7 +197,7 @@ describe('GET /groups/:id', () => { }); }); - xit('TODO: Not yet implimented - includes user ids in flags object', () => { + it('includes user ids in flags object', () => { return api.get(`/groups/${group._id}`).then((_group) => { let chatWithOneFlag = _group.chat[2]; expect(chatWithOneFlag.id).to.eql(chat3.id); diff --git a/test/api/groups/chat/POST-groups_id_chat_id_flag.test.js b/test/api/groups/chat/POST-groups_id_chat_id_flag.test.js index 16ab13f429..5c822ad081 100644 --- a/test/api/groups/chat/POST-groups_id_chat_id_flag.test.js +++ b/test/api/groups/chat/POST-groups_id_chat_id_flag.test.js @@ -36,7 +36,7 @@ describe('POST /groups/:id/chat/:id/flag', () => { return api.get(`/groups/${group._id}/chat`); }).then((messages) => { let message = messages[0]; - expect(message.flags[user._id]).to.eql(true); + expect(message.flagCount).to.eql(1); }); }); }); diff --git a/website/src/controllers/api-v2/groups.js b/website/src/controllers/api-v2/groups.js index 40a01f32a5..89028f7aff 100644 --- a/website/src/controllers/api-v2/groups.js +++ b/website/src/controllers/api-v2/groups.js @@ -149,10 +149,11 @@ api.get = function(req, res, next) { // so that users with no party don't get a 404 on every access to the site return res.json(group); } - //Remove flagged messages if the user is not mod + if (!user.contributor.admin) { - group.chat = _.filter(group.chat, function(message) { return !message.flagCount || message.flagCount < 2; }); + _purgeFlagInfoFromChat(group); } + //Since we have a limit on how many members are populate to the group, we want to make sure the user is always in the group var userInGroup = _.find(group.members, function(member){ return member._id == user._id; }); //If the group is private or the group is a party, then the user must be a member of the group based on access restrictions above @@ -251,11 +252,17 @@ api.update = function(req, res, next) { // TODO remove from api object? api.attachGroup = function(req, res, next) { + var user = res.locals.user; var gid = req.params.gid; var q = (gid == 'party') ? Group.findOne({type: 'party', members: {'$in': [res.locals.user._id]}}) : Group.findById(gid); q.exec(function(err, group){ if(err) return next(err); if(!group) return res.json(404, {err: shared.i18n.t('messageGroupNotFound')}); + + if (!user.contributor.admin) { + _purgeFlagInfoFromChat(group); + } + res.locals.group = group; next(); }); @@ -275,10 +282,7 @@ api.getChat = function(req, res, next) { q.exec(function(err, group){ if (err) return next(err); if (!group && gid!=='party') return res.json(404,{err: shared.i18n.t('messageGroupNotFound')}); - //Remove flagged messages if the user is not mod - if (!user.contributor.admin) { - group.chat = _.filter(group.chat, function(message) { return !message.flagCount || message.flagCount < 2; }); - } + res.json(res.locals.group.chat); gid = null; }); @@ -1095,3 +1099,10 @@ api.questLeave = function(req, res, next) { return next(error); }); } + +function _purgeFlagInfoFromChat(group) { + group.chat = _.filter(group.chat, function(message) { return !message.flagCount || message.flagCount < 2; }); + _.each(group.chat, function (message) { + message.flags = {}; + }); +} diff --git a/website/src/models/group.js b/website/src/models/group.js index 17817994c1..7ba8dac173 100644 --- a/website/src/models/group.js +++ b/website/src/models/group.js @@ -475,11 +475,6 @@ GroupSchema.methods.leave = function(user, keep, mainCb){ GroupSchema.methods.toJSON = function() { var doc = this.toObject(); - if(doc.chat){ - doc.chat.forEach(function(msg){ - msg.flags = {}; - }); - } return doc; }; From 269fd2a94fca73ba9c8ff87ce6a663813b267a2a Mon Sep 17 00:00:00 2001 From: Blade Barringer Date: Wed, 4 Nov 2015 08:00:35 -0600 Subject: [PATCH 4/4] Add test for admin flagging a message --- .../chat/POST-groups_id_chat_id_flag.test.js | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/test/api/v2/groups/chat/POST-groups_id_chat_id_flag.test.js b/test/api/v2/groups/chat/POST-groups_id_chat_id_flag.test.js index ee9c1eb86d..ac6e48dcac 100644 --- a/test/api/v2/groups/chat/POST-groups_id_chat_id_flag.test.js +++ b/test/api/v2/groups/chat/POST-groups_id_chat_id_flag.test.js @@ -99,4 +99,42 @@ describe('POST /groups/:id/chat/:id/flag', () => { }); }); }); + + context('admin flagging a message', () => { + let group, member, message, user; + + beforeEach(() => { + return createAndPopulateGroup({ + groupDetails: { + type: 'guild', + privacy: 'public', + }, + leaderDetails: { + 'contributor.admin': true, + balance: 10, + }, + members: 1, + }).then((res) => { + group = res.group; + user = res.leader; + member = res.members[0]; + + return requester(member) + .post(`/groups/${group._id}/chat`, null, { message: 'Group member message', }); + }).then((res) => { + message = res.message; + }); + }); + + it('sets flagCount to 5', () => { + let api = requester(user); + + return api.post(`/groups/${group._id}/chat/${message.id}/flag`).then((messages) => { + return api.get(`/groups/${group._id}/chat`); + }).then((messages) => { + let message = messages[0]; + expect(message.flagCount).to.eql(5); + }); + }); + }); });