From 6649361db70647ea3ea707345d37a540da1a2f7e Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Wed, 19 Feb 2020 12:52:15 -0300 Subject: [PATCH 01/30] [FIX] Admin height if the blue banner is opened (#16629) * fix admin height * fix review --- client/components/basic/Page.js | 2 +- client/routes.js | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/client/components/basic/Page.js b/client/components/basic/Page.js index ddf01872c40..67034e0caec 100644 --- a/client/components/basic/Page.js +++ b/client/components/basic/Page.js @@ -5,7 +5,7 @@ import { BurgerMenuButton } from './BurgerMenuButton'; export function Page(props) { return - ({ height: '100vh' }), [])} {...props} /> + ({ height: '100%' }), [])} {...props} /> ; } diff --git a/client/routes.js b/client/routes.js index 515a6b2a6da..ce613e76b18 100644 --- a/client/routes.js +++ b/client/routes.js @@ -233,19 +233,20 @@ FlowRouter.route('/setup-wizard/:step?', { }, }); +const style = 'overflow: hidden; flex: 1 1 auto; height: 1%;'; FlowRouter.route('/admin/:group?', { name: 'admin', action: async ({ group = 'info' } = {}) => { switch (group) { case 'info': { const { InformationRoute } = await import('./components/admin/info/InformationRoute'); - BlazeLayout.render('main', { center: await createTemplateForComponent(InformationRoute) }); + BlazeLayout.render('main', { center: await createTemplateForComponent(InformationRoute, { }, () => HTML.DIV({ style })) }); // eslint-disable-line break; } default: { const { SettingsRoute } = await import('./components/admin/settings/SettingsRoute'); - BlazeLayout.render('main', { center: await createTemplateForComponent(SettingsRoute, { group }) }); + BlazeLayout.render('main', { center: await createTemplateForComponent(SettingsRoute, { group }, () => HTML.DIV({ style })) }); // eslint-disable-line // BlazeLayout.render('main', { center: 'admin' }); } } From 997dcae9d27b65118093461257aee115c0801628 Mon Sep 17 00:00:00 2001 From: Douglas Gubert Date: Tue, 18 Feb 2020 21:39:07 -0300 Subject: [PATCH 02/30] [FIX] Data converters overriding fields added by apps (#16639) --- app/apps/lib/misc/transformMappedData.js | 6 ++++-- app/lib/server/functions/sendMessage.js | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/app/apps/lib/misc/transformMappedData.js b/app/apps/lib/misc/transformMappedData.js index 0bba2c64608..61e57b0a53c 100644 --- a/app/apps/lib/misc/transformMappedData.js +++ b/app/apps/lib/misc/transformMappedData.js @@ -73,8 +73,10 @@ export const transformMappedData = (data, map) => { if (typeof result !== 'undefined') { transformedData[to] = result; } - } else if (typeof from === 'string' && typeof originalData[from] !== 'undefined') { - transformedData[to] = originalData[from]; + } else if (typeof from === 'string') { + if (typeof originalData[from] !== 'undefined') { + transformedData[to] = originalData[from]; + } delete originalData[from]; } }); diff --git a/app/lib/server/functions/sendMessage.js b/app/lib/server/functions/sendMessage.js index ea5ce3088d5..5b7d3c281c1 100644 --- a/app/lib/server/functions/sendMessage.js +++ b/app/lib/server/functions/sendMessage.js @@ -136,6 +136,7 @@ const validateMessage = (message) => { emoji: String, avatar: ValidPartialURLParam, attachments: [Match.Any], + blocks: [Match.Any], })); if (Array.isArray(message.attachments) && message.attachments.length) { From df5b9105b6c29209579c819705751df87f546bf2 Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Tue, 18 Feb 2020 21:38:47 -0300 Subject: [PATCH 03/30] [FIX] Block user option inside admin view (#16626) --- app/ui-flextab/client/tabs/userActions.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/ui-flextab/client/tabs/userActions.js b/app/ui-flextab/client/tabs/userActions.js index 93d49bb9204..d1947e1e866 100644 --- a/app/ui-flextab/client/tabs/userActions.js +++ b/app/ui-flextab/client/tabs/userActions.js @@ -26,11 +26,11 @@ const canBlockUser = () => ChatSubscription.findOne({ rid: Session.get('openedRoom'), 'u._id': Meteor.userId() }, { fields: { blocker: 1 } }) .blocker; -const canDirectMessageTo = (username) => { +const canDirectMessageTo = (username, directActions) => { const subscription = Subscriptions.findOne({ rid: Session.get('openedRoom') }); const canOpenDm = hasAllPermission('create-d') || Subscriptions.findOne({ name: username }); const dmIsNotAlreadyOpen = subscription && subscription.name !== username; - return canOpenDm && dmIsNotAlreadyOpen; + return canOpenDm && (!directActions || dmIsNotAlreadyOpen); }; export const getActions = ({ user, directActions, hideAdminControls }) => { @@ -107,7 +107,7 @@ export const getActions = ({ user, directActions, hideAdminControls }) => { Meteor.call('createDirectMessage', username, success((result) => result.rid && FlowRouter.go('direct', { username }, FlowRouter.current().queryParams))), ), condition() { - return canDirectMessageTo(this.username); + return canDirectMessageTo(this.username, directActions); }, }, @@ -188,7 +188,7 @@ export const getActions = ({ user, directActions, hideAdminControls }) => { }, }; }, function() { - if (!isInDirectMessageRoom() || isSelf(this.username)) { + if (!directActions || !isInDirectMessageRoom() || isSelf(this.username)) { return; } if (canBlockUser()) { From ffbad5888247854798ef89489daff03c37df9d26 Mon Sep 17 00:00:00 2001 From: Douglas Gubert Date: Tue, 18 Feb 2020 18:03:07 -0300 Subject: [PATCH 04/30] [FIX] Regression: New 'app' role with no permissions when updating to 3.0.0 (#16637) --- server/startup/migrations/index.js | 1 + server/startup/migrations/v174.js | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 server/startup/migrations/v174.js diff --git a/server/startup/migrations/index.js b/server/startup/migrations/index.js index 85bc4b3ba7c..6c9b0f4d36d 100644 --- a/server/startup/migrations/index.js +++ b/server/startup/migrations/index.js @@ -171,4 +171,5 @@ import './v170'; import './v171'; import './v172'; import './v173'; +import './v174'; import './xrun'; diff --git a/server/startup/migrations/v174.js b/server/startup/migrations/v174.js new file mode 100644 index 00000000000..0ca59f1e69c --- /dev/null +++ b/server/startup/migrations/v174.js @@ -0,0 +1,26 @@ +import { Migrations } from '../../../app/migrations/server'; +import { Permissions } from '../../../app/models/server'; + +const appRolePermissions = [ + 'api-bypass-rate-limit', + 'create-c', + 'create-d', + 'create-p', + 'join-without-join-code', + 'leave-c', + 'leave-p', + 'send-many-messages', + 'view-c-room', + 'view-d-room', + 'view-joined-room', +]; + +Migrations.add({ + version: 174, + up() { + Permissions.update({ _id: { $in: appRolePermissions } }, { $addToSet: { roles: 'app' } }, { multi: true }); + }, + down() { + Permissions.update({ _id: { $in: appRolePermissions } }, { $pull: { roles: 'app' } }, { multi: true }); + }, +}); From 95e89f687becfb2a7c11fcebd77748a0f0b06770 Mon Sep 17 00:00:00 2001 From: Marcos Spessatto Defendi Date: Mon, 17 Feb 2020 21:14:31 -0300 Subject: [PATCH 05/30] [FIX] livechat/rooms endpoint not working with big amount of livechats (#16623) * Remove aggregate to improve performance * Use a cursor to run query only once * Do not use toArray in model Co-authored-by: Diego Sampaio --- app/livechat/server/api/lib/rooms.js | 33 +++++++----- app/models/server/raw/LivechatDepartment.js | 6 ++- app/models/server/raw/LivechatRooms.js | 58 ++++++--------------- 3 files changed, 39 insertions(+), 58 deletions(-) diff --git a/app/livechat/server/api/lib/rooms.js b/app/livechat/server/api/lib/rooms.js index 54a421d8e6c..72d84803de1 100644 --- a/app/livechat/server/api/lib/rooms.js +++ b/app/livechat/server/api/lib/rooms.js @@ -1,4 +1,4 @@ -import { LivechatRooms } from '../../../../models/server/raw'; +import { LivechatRooms, LivechatDepartment } from '../../../../models/server/raw'; export async function findRooms({ agents, @@ -16,18 +16,7 @@ export async function findRooms({ sort, }, }) { - const total = (await LivechatRooms.findRoomsWithCriteria({ - agents, - roomName, - departmentId, - open, - createdAt, - closedAt, - tags, - customFields, - })).length; - - const rooms = await LivechatRooms.findRoomsWithCriteria({ + const cursor = LivechatRooms.findRoomsWithCriteria({ agents, roomName, departmentId, @@ -44,6 +33,24 @@ export async function findRooms({ }, }); + const total = await cursor.count(); + + const rooms = await cursor.toArray(); + + const departmentsIds = [...new Set(rooms.map((room) => room.departmentId).filter(Boolean))]; + if (departmentsIds.length) { + const departments = await LivechatDepartment.findInIds(departmentsIds, { fields: { name: 1 } }).toArray(); + + rooms.forEach((room) => { + if (!room.departmentId) { + return; + } + const department = departments.find((dept) => dept._id === room.departmentId); + if (department) { + room.department = department; + } + }); + } return { rooms, count: rooms.length, diff --git a/app/models/server/raw/LivechatDepartment.js b/app/models/server/raw/LivechatDepartment.js index 040e156b16d..1b103c03444 100644 --- a/app/models/server/raw/LivechatDepartment.js +++ b/app/models/server/raw/LivechatDepartment.js @@ -1,6 +1,8 @@ import { BaseRaw } from './BaseRaw'; export class LivechatDepartmentRaw extends BaseRaw { - - + findInIds(departmentsIds, options) { + const query = { _id: { $in: departmentsIds } }; + return this.find(query, options); + } } diff --git a/app/models/server/raw/LivechatRooms.js b/app/models/server/raw/LivechatRooms.js index 7f9286d86d0..da9ec4282e4 100644 --- a/app/models/server/raw/LivechatRooms.js +++ b/app/models/server/raw/LivechatRooms.js @@ -1099,73 +1099,45 @@ export class LivechatRoomsRaw extends BaseRaw { } findRoomsWithCriteria({ agents, roomName, departmentId, open, createdAt, closedAt, tags, customFields, options = {} }) { - const match = { - $match: { - t: 'l', - }, + const query = { + t: 'l', }; if (agents) { - match.$match.$or = [{ 'servedBy._id': { $in: agents } }, { 'servedBy.username': { $in: agents } }]; + query.$or = [{ 'servedBy._id': { $in: agents } }, { 'servedBy.username': { $in: agents } }]; } if (roomName) { - match.$match.fname = new RegExp(roomName, 'i'); + query.fname = new RegExp(roomName, 'i'); } if (departmentId) { - match.$match.departmentId = departmentId; + query.departmentId = departmentId; } if (open !== undefined) { - match.$match.open = { $exists: open }; + query.open = { $exists: open }; } if (createdAt) { - match.$match.ts = {}; + query.ts = {}; if (createdAt.start) { - match.$match.ts.$gte = new Date(createdAt.start); + query.ts.$gte = new Date(createdAt.start); } if (createdAt.end) { - match.$match.ts.$lte = new Date(createdAt.end); + query.ts.$lte = new Date(createdAt.end); } } if (closedAt) { - match.$match.closedAt = {}; + query.closedAt = {}; if (closedAt.start) { - match.$match.closedAt.$gte = new Date(closedAt.start); + query.closedAt.$gte = new Date(closedAt.start); } if (closedAt.end) { - match.$match.closedAt.$lte = new Date(closedAt.end); + query.closedAt.$lte = new Date(closedAt.end); } } if (tags) { - match.$match.tags = { $in: tags }; + query.tags = { $in: tags }; } if (customFields) { - match.$match.$and = Object.keys(customFields).map((key) => ({ [`livechatData.${ key }`]: new RegExp(customFields[key], 'i') })); - } - const sort = { $sort: options.sort || { name: 1 } }; - const firstParams = [match, sort]; - if (options.offset) { - firstParams.push({ $skip: options.offset }); + query.$and = Object.keys(customFields).map((key) => ({ [`livechatData.${ key }`]: new RegExp(customFields[key], 'i') })); } - if (options.count) { - firstParams.push({ $limit: options.count }); - } - const lookup = { - $lookup: { - from: 'rocketchat_livechat_department', - localField: 'departmentId', - foreignField: '_id', - as: 'department', - }, - }; - const unwind = { - $unwind: { - path: '$department', - preserveNullAndEmptyArrays: true, - }, - }; - const params = [...firstParams, lookup, unwind]; - if (options.fields) { - params.push({ $project: options.fields }); - } - return this.col.aggregate(params).toArray(); + return this.find(query, { sort: options.sort || { name: 1 }, skip: options.offset, limit: options.count }); } } From 57f28211a5b1e605b6fa801cfac61aa22b969a1b Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Mon, 17 Feb 2020 21:10:19 -0300 Subject: [PATCH 06/30] [FIX] Regression: Jitsi on external window infinite loop (#16625) --- app/videobridge/client/views/videoFlexTab.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/app/videobridge/client/views/videoFlexTab.js b/app/videobridge/client/views/videoFlexTab.js index 1b55095af75..ebc32f1bace 100644 --- a/app/videobridge/client/views/videoFlexTab.js +++ b/app/videobridge/client/views/videoFlexTab.js @@ -1,4 +1,5 @@ import { Meteor } from 'meteor/meteor'; +import { Tracker } from 'meteor/tracker'; import { Session } from 'meteor/session'; import { Template } from 'meteor/templating'; import { TimeSync } from 'meteor/mizzao:timesync'; @@ -58,9 +59,9 @@ Template.videoFlexTab.onRendered(function() { const start = () => { const update = () => { - const { jitsiTimeout } = Rooms.findOne({ _id: rid }, { fields: { jitsiTimeout: 1 }, reactive: false }); + const { jitsiTimeout } = Rooms.findOne({ _id: rid }, { fields: { jitsiTimeout: 1 } }); - if (jitsiTimeout && (TimeSync.serverTime(), - new Date(jitsiTimeout) + CONSTANTS.TIMEOUT < CONSTANTS.DEBOUNCE)) { + if (jitsiTimeout && (TimeSync.serverTime() - new Date(jitsiTimeout) + CONSTANTS.TIMEOUT < CONSTANTS.DEBOUNCE)) { return; } if (Meteor.status().connected) { @@ -70,7 +71,7 @@ Template.videoFlexTab.onRendered(function() { return this.stop(); }; update(); - this.intervalHandler = Meteor.setInterval(update, CONSTANTS.HEARTBEAT); + this.intervalHandler = setInterval(update, CONSTANTS.HEARTBEAT); TabBar.updateButton('video', { class: 'red' }); }; @@ -125,7 +126,7 @@ Template.videoFlexTab.onRendered(function() { jitsiRoomActive = jitsiRoom; if (settings.get('Jitsi_Open_New_Window')) { - start(); + Tracker.nonreactive(() => start()); let queryString = ''; if (accessToken) { queryString = `?jwt=${ accessToken }`; @@ -157,7 +158,7 @@ Template.videoFlexTab.onRendered(function() { * For some reason those aren't working right. */ Meteor.setTimeout(() => this.api.executeCommand('displayName', [name]), 5000); - return start(); + return Tracker.nonreactive(() => start()); } // Execute any commands that might be reactive. Like name changing. From c4621c42a966d7cb2758e5e34f5043c535db8deb Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Mon, 17 Feb 2020 20:51:06 -0300 Subject: [PATCH 07/30] [FIX] UiKit not updating new actionIds received as responses from actions (#16624) --- app/ui-message/client/blocks/ModalBlock.js | 6 +-- package-lock.json | 47 ++++++++++++---------- package.json | 10 ++--- 3 files changed, 34 insertions(+), 29 deletions(-) diff --git a/app/ui-message/client/blocks/ModalBlock.js b/app/ui-message/client/blocks/ModalBlock.js index 36c5c7ab580..bb6a1e48dea 100644 --- a/app/ui-message/client/blocks/ModalBlock.js +++ b/app/ui-message/client/blocks/ModalBlock.js @@ -79,7 +79,7 @@ Template.ModalBlock.onRendered(async function() { appId, viewId, view: { - ...this.data.view, + ...state.get().view, id: viewId, state: groupStateByBlockId(this.state.all()), }, @@ -91,7 +91,7 @@ Template.ModalBlock.onRendered(async function() { appId, viewId, view: { - ...this.data.view, + ...state.get().view, id: viewId, state: groupStateByBlockId(this.state.all()), }, @@ -105,7 +105,7 @@ Template.ModalBlock.onRendered(async function() { appId, payload: { view: { - ...this.data.view, + ...state.get().view, id: viewId, state: groupStateByBlockId(this.state.all()), }, diff --git a/package-lock.json b/package-lock.json index c7c9edd9db8..dee9cb46302 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2716,36 +2716,41 @@ } }, "@rocket.chat/fuselage": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@rocket.chat/fuselage/-/fuselage-0.2.0.tgz", - "integrity": "sha512-APEd9eF9DXVcIrddGov+4yCK18RkOmkGFrNUpCHWqeuAjEy0oApaUWp4e9ISIviIEIijtZ6Q9T2jaLjSKdkzLA==", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@rocket.chat/fuselage/-/fuselage-0.3.0.tgz", + "integrity": "sha512-nZdtJtEjZO2ZKQafo0ijANRAlr+wSQ9PzsjpRcan4XVaOdnS7Yri7ZlqtA2jdmHyr5/bbQzReM0WudujS5JMyg==", "requires": { - "@rocket.chat/fuselage-tokens": "^0.2.0", - "@rocket.chat/icons": "^0.2.0" + "@rocket.chat/fuselage-tokens": "^0.3.0", + "@rocket.chat/icons": "^0.3.0" } }, "@rocket.chat/fuselage-hooks": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@rocket.chat/fuselage-hooks/-/fuselage-hooks-0.2.0.tgz", - "integrity": "sha512-OKQWhsbm3eHU1IDshwEqZhpzMW+loGPdpr1W2mZHbazkcRQYVp7V76Hl3Hh/HHGn8+EPY4fluoPVHgoOm42NiA==" + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@rocket.chat/fuselage-hooks/-/fuselage-hooks-0.3.0.tgz", + "integrity": "sha512-VpRyEhntgJ1HLYtaRmOzdHTpfGxkyyD9ElxBwEENMcu4/Ke6brIttznevndjaZWznfF/VV+15vcFovimRt/giQ==" }, "@rocket.chat/fuselage-tokens": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@rocket.chat/fuselage-tokens/-/fuselage-tokens-0.2.0.tgz", - "integrity": "sha512-mHAoZ4mAXXYJ+Sz6DYwe/StO7HyMUNdYw+2U+9uzyO5Zyy5e88+lxD2+HI0UQ7AC6cM/Y77s1kNhTwDpP70oHw==" + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@rocket.chat/fuselage-tokens/-/fuselage-tokens-0.3.0.tgz", + "integrity": "sha512-PEFww6Q4gRmBo97nA6JHICSYHqQuCDHS4KFS070ofdaRParEaBhrQ8CBF21RpIXZpofk9d4nR96JdI0uf6rWOw==" }, "@rocket.chat/fuselage-ui-kit": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@rocket.chat/fuselage-ui-kit/-/fuselage-ui-kit-0.2.0.tgz", - "integrity": "sha512-slgtaz0gFWaU70XyMFI74L6tIUsrKdSae74/8BLq/w4dm3q1Faoc9jDvsgcvqta+/n0GguxjMNrEi6iOI4L96w==", + "version": "0.3.0", "requires": { - "@rocket.chat/ui-kit": "^0.2.0" + "@rocket.chat/ui-kit": "^0.3.0" + }, + "dependencies": { + "@rocket.chat/ui-kit": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@rocket.chat/ui-kit/-/ui-kit-0.2.0.tgz", + "integrity": "sha512-O6QNicDDRRbiULWXdkVmgUl1Pf3CoVVA8L7JEfiegQcTdPEsHlWGYBxcpbt23gY4hoNmbknlJHfCPNWd7oLcmQ==" + } } }, "@rocket.chat/icons": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@rocket.chat/icons/-/icons-0.2.0.tgz", - "integrity": "sha512-EUXi/TGe2YBVASoWPHm+FeRyq6gxNJjByNtc6wb1s0wyPxESD3rPpRkxR1PKjQtSTzNSFW8woEVT1UNPly7v1g==" + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@rocket.chat/icons/-/icons-0.3.0.tgz", + "integrity": "sha512-cE8tq4MzfqJq3AiSKMQS6RWj5gYKDhnQZNP63q0ljtvcZDzGX/LL3zmACmrCwwjT4Y0XNp2CpPW9mNFtG20iNQ==" }, "@rocket.chat/livechat": { "version": "1.3.1", @@ -2835,9 +2840,9 @@ } }, "@rocket.chat/ui-kit": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@rocket.chat/ui-kit/-/ui-kit-0.2.0.tgz", - "integrity": "sha512-O6QNicDDRRbiULWXdkVmgUl1Pf3CoVVA8L7JEfiegQcTdPEsHlWGYBxcpbt23gY4hoNmbknlJHfCPNWd7oLcmQ==" + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@rocket.chat/ui-kit/-/ui-kit-0.3.0.tgz", + "integrity": "sha512-YAV5l6iVIWuileg5DOU/0NQ/23/AULEr8UblIUSF3OShPN8nWanGMdG0E6xFLyXT+KHvmvzhiQe0/ju3Tk7x8A==" }, "@settlin/spacebars-loader": { "version": "1.0.7", diff --git a/package.json b/package.json index 0d0f66e6678..e238acab719 100644 --- a/package.json +++ b/package.json @@ -123,11 +123,11 @@ "@google-cloud/storage": "^2.3.1", "@google-cloud/vision": "^1.8.0", "@rocket.chat/apps-engine": "^1.12.0", - "@rocket.chat/fuselage": "^0.2.0", - "@rocket.chat/fuselage-hooks": "^0.2.0", - "@rocket.chat/fuselage-ui-kit": "^0.2.0", - "@rocket.chat/icons": "^0.2.0", - "@rocket.chat/ui-kit": "^0.2.0", + "@rocket.chat/fuselage": "^0.3.0", + "@rocket.chat/fuselage-hooks": "^0.3.0", + "@rocket.chat/fuselage-ui-kit": "^0.3.0", + "@rocket.chat/icons": "^0.3.0", + "@rocket.chat/ui-kit": "^0.3.0", "@slack/client": "^4.8.0", "adm-zip": "RocketChat/adm-zip", "archiver": "^3.0.0", From b87ffbbd4d82aadd2da97f81f032c9725b8b400d Mon Sep 17 00:00:00 2001 From: Diego Sampaio Date: Wed, 19 Feb 2020 13:04:19 -0300 Subject: [PATCH 08/30] Bump version to 3.0.1 --- .docker/Dockerfile.rhel | 2 +- .github/history.json | 77 +++++++++++++++++++++++++++++++++++++++ HISTORY.md | 25 +++++++++++++ app/utils/rocketchat.info | 2 +- package.json | 2 +- 5 files changed, 105 insertions(+), 3 deletions(-) diff --git a/.docker/Dockerfile.rhel b/.docker/Dockerfile.rhel index 0a700be61b4..c3d663fc2ba 100644 --- a/.docker/Dockerfile.rhel +++ b/.docker/Dockerfile.rhel @@ -1,6 +1,6 @@ FROM registry.access.redhat.com/rhscl/nodejs-8-rhel7 -ENV RC_VERSION 3.0.0 +ENV RC_VERSION 3.0.1 MAINTAINER buildmaster@rocket.chat diff --git a/.github/history.json b/.github/history.json index afd5cd31de0..56e30e9a729 100644 --- a/.github/history.json +++ b/.github/history.json @@ -39745,6 +39745,83 @@ "4.0" ], "pull_requests": [] + }, + "3.0.1": { + "node_version": "12.14.0", + "npm_version": "6.13.4", + "mongo_versions": [ + "3.4", + "3.6", + "4.0" + ], + "pull_requests": [ + { + "pr": "16624", + "title": "[FIX] UiKit not updating new actionIds received as responses from actions", + "userLogin": "ggazzo", + "milestone": "3.0.1", + "contributors": [ + "ggazzo" + ] + }, + { + "pr": "16625", + "title": "[FIX] Regression: Jitsi on external window infinite loop", + "userLogin": "ggazzo", + "milestone": "3.0.1", + "contributors": [ + "ggazzo" + ] + }, + { + "pr": "16623", + "title": "[FIX] livechat/rooms endpoint not working with big amount of livechats", + "userLogin": "MarcosSpessatto", + "milestone": "3.0.1", + "contributors": [ + "MarcosSpessatto", + "sampaiodiego" + ] + }, + { + "pr": "16637", + "title": "[FIX] Regression: New 'app' role with no permissions when updating to 3.0.0", + "userLogin": "d-gubert", + "milestone": "3.0.1", + "contributors": [ + "d-gubert" + ] + }, + { + "pr": "16626", + "title": "[FIX] Block user option inside admin view", + "userLogin": "ggazzo", + "milestone": "3.0.1", + "contributors": [ + "ggazzo" + ] + }, + { + "pr": "16639", + "title": "[FIX] Data converters overriding fields added by apps", + "userLogin": "d-gubert", + "milestone": "3.0.1", + "contributors": [ + "ggazzo", + "d-gubert", + "web-flow" + ] + }, + { + "pr": "16629", + "title": "[FIX] Admin height if the blue banner is opened", + "userLogin": "ggazzo", + "milestone": "3.0.1", + "contributors": [ + "ggazzo" + ] + } + ] } } } \ No newline at end of file diff --git a/HISTORY.md b/HISTORY.md index 4abcc90030c..e86db17e826 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,4 +1,29 @@ +# 3.0.1 +`2020-02-19 ยท 7 ๐Ÿ› ยท 4 ๐Ÿ‘ฉโ€๐Ÿ’ป๐Ÿ‘จโ€๐Ÿ’ป` + +### Engine versions +- Node: `12.14.0` +- NPM: `6.13.4` +- MongoDB: `3.4, 3.6, 4.0` + +### ๐Ÿ› Bug fixes + +- UiKit not updating new actionIds received as responses from actions ([#16624](https://github.com/RocketChat/Rocket.Chat/pull/16624)) +- Regression: Jitsi on external window infinite loop ([#16625](https://github.com/RocketChat/Rocket.Chat/pull/16625)) +- livechat/rooms endpoint not working with big amount of livechats ([#16623](https://github.com/RocketChat/Rocket.Chat/pull/16623)) +- Regression: New 'app' role with no permissions when updating to 3.0.0 ([#16637](https://github.com/RocketChat/Rocket.Chat/pull/16637)) +- Block user option inside admin view ([#16626](https://github.com/RocketChat/Rocket.Chat/pull/16626)) +- Data converters overriding fields added by apps ([#16639](https://github.com/RocketChat/Rocket.Chat/pull/16639)) +- Admin height if the blue banner is opened ([#16629](https://github.com/RocketChat/Rocket.Chat/pull/16629)) + +### ๐Ÿ‘ฉโ€๐Ÿ’ป๐Ÿ‘จโ€๐Ÿ’ป Core Team ๐Ÿค“ + +- [@MarcosSpessatto](https://github.com/MarcosSpessatto) +- [@d-gubert](https://github.com/d-gubert) +- [@ggazzo](https://github.com/ggazzo) +- [@sampaiodiego](https://github.com/sampaiodiego) + # 3.0.0 `2020-02-14 ยท 7 ๏ธ๏ธ๏ธโš ๏ธ ยท 10 ๐ŸŽ‰ ยท 11 ๐Ÿš€ ยท 32 ๐Ÿ› ยท 43 ๐Ÿ” ยท 21 ๐Ÿ‘ฉโ€๐Ÿ’ป๐Ÿ‘จโ€๐Ÿ’ป` diff --git a/app/utils/rocketchat.info b/app/utils/rocketchat.info index 3d617ac0916..9bc526777aa 100644 --- a/app/utils/rocketchat.info +++ b/app/utils/rocketchat.info @@ -1,3 +1,3 @@ { - "version": "3.0.0" + "version": "3.0.1" } diff --git a/package.json b/package.json index e238acab719..d6970a605cb 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "Rocket.Chat", "description": "The Ultimate Open Source WebChat Platform", - "version": "3.0.0", + "version": "3.0.1", "author": { "name": "Rocket.Chat", "url": "https://rocket.chat/" From 6164f7630f603a78067d0dad058870e993fd13f6 Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Thu, 20 Feb 2020 14:39:03 -0300 Subject: [PATCH 09/30] [FIX] Clear unread red line when the ESC key is pressed (#16668) --- app/ui-utils/client/lib/readMessages.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/ui-utils/client/lib/readMessages.js b/app/ui-utils/client/lib/readMessages.js index 8754af58386..1afcd5d979d 100644 --- a/app/ui-utils/client/lib/readMessages.js +++ b/app/ui-utils/client/lib/readMessages.js @@ -174,7 +174,12 @@ Meteor.startup(function() { .on('keyup', (e) => { const key = e.which; if (key === 27) { // ESCAPE KEY - readMessage.readNow(); + const rid = Session.get('openedRoom'); + if (!rid) { + return; + } + readMessage.readNow(rid); + readMessage.refreshUnreadMark(rid); } }); }); From 00f65d74210a833da8f647f9533ba8f28c1bc5ce Mon Sep 17 00:00:00 2001 From: Marcos Spessatto Defendi Date: Thu, 20 Feb 2020 13:22:15 -0300 Subject: [PATCH 10/30] [FIX] users.info endpoint not handling the error if the user does not exist (#16495) * Prevent user to be undefined * Move findById to Base model Co-authored-by: Diego Sampaio --- app/api/server/v1/users.js | 2 +- app/lib/server/functions/getFullUserData.js | 3 +++ app/models/server/models/Users.js | 6 ------ app/models/server/models/_Base.js | 8 ++++++++ app/models/server/models/_BaseDb.js | 4 ++++ tests/end-to-end/api/01-users.js | 15 +++++++++++++++ 6 files changed, 31 insertions(+), 7 deletions(-) diff --git a/app/api/server/v1/users.js b/app/api/server/v1/users.js index d0115d51fb0..fa40c867f0d 100644 --- a/app/api/server/v1/users.js +++ b/app/api/server/v1/users.js @@ -166,7 +166,7 @@ API.v1.addRoute('users.info', { authRequired: true }, { : getFullUserData(params); if (!result || result.count() !== 1) { - return API.v1.failure(`Failed to get the user data for the userId of "${ this.userId }".`); + return API.v1.failure('User not found.'); } const [user] = result.fetch(); const myself = user._id === this.userId; diff --git a/app/lib/server/functions/getFullUserData.js b/app/lib/server/functions/getFullUserData.js index 317b181ab51..b79cc953adb 100644 --- a/app/lib/server/functions/getFullUserData.js +++ b/app/lib/server/functions/getFullUserData.js @@ -78,6 +78,9 @@ export function getFullUserDataById({ userId, filterId }) { export const getFullUserData = function({ userId, filter, limit: l }) { const username = s.trim(filter); const userToRetrieveFullUserData = username && Users.findOneByUsername(username, { fields: { username: 1 } }); + if (!userToRetrieveFullUserData) { + return; + } const isMyOwnInfo = userToRetrieveFullUserData && userToRetrieveFullUserData._id === userId; const viewFullOtherUserInfo = hasPermission(userId, 'view-full-other-user-info'); diff --git a/app/models/server/models/Users.js b/app/models/server/models/Users.js index 42222ec3738..9d594a9f32b 100644 --- a/app/models/server/models/Users.js +++ b/app/models/server/models/Users.js @@ -493,12 +493,6 @@ export class Users extends Base { } // FIND - findById(userId) { - const query = { _id: userId }; - - return this.find(query); - } - findByIds(users, options) { const query = { _id: { $in: users } }; return this.find(query, options); diff --git a/app/models/server/models/_Base.js b/app/models/server/models/_Base.js index 97315044e36..d5ba676bd7e 100644 --- a/app/models/server/models/_Base.js +++ b/app/models/server/models/_Base.js @@ -119,6 +119,14 @@ export class Base { } } + findById(...args) { + try { + return this[this.origin].findById(...args); + } catch (e) { + console.error('Exception on find', e, ...args); + } + } + findOne(...args) { try { return this[this.origin].findOne(...args); diff --git a/app/models/server/models/_BaseDb.js b/app/models/server/models/_BaseDb.js index d7df328844c..d248544a918 100644 --- a/app/models/server/models/_BaseDb.js +++ b/app/models/server/models/_BaseDb.js @@ -130,6 +130,10 @@ export class BaseDb extends EventEmitter { return this.model.find(...args); } + findById(_id, options) { + return this.find({ _id }, options); + } + findOne(...args) { this._doNotMixInclusionAndExclusionFields(args[1]); return this.model.findOne(...args); diff --git a/tests/end-to-end/api/01-users.js b/tests/end-to-end/api/01-users.js index 3eb83c9106d..3ab97cdb5c9 100644 --- a/tests/end-to-end/api/01-users.js +++ b/tests/end-to-end/api/01-users.js @@ -198,6 +198,21 @@ describe('[Users]', function() { describe('[/users.info]', () => { after(() => updatePermission('view-other-user-channels', ['admin'])); + it('should return an error when the user does not exist', (done) => { + request.get(api('users.info')) + .set(credentials) + .query({ + username: 'invalid-username', + }) + .expect('Content-Type', 'application/json') + .expect(400) + .expect((res) => { + expect(res.body).to.have.property('success', false); + expect(res.body).to.have.property('error').and.to.be.equal('User not found.'); + }) + .end(done); + }); + it('should query information about a user by userId', (done) => { request.get(api('users.info')) .set(credentials) From 0068bdb80d913f0b63ec44d8d81e7fd321e6b5c2 Mon Sep 17 00:00:00 2001 From: Renato Becker Date: Tue, 18 Feb 2020 09:41:02 -0300 Subject: [PATCH 11/30] [FIX] Omnichannel Inquiry queues when removing chats (#16603) * Fix Inquiry stream when removing omnichannel rooms. * Remove unnecessary blank line. * Remove unnecessary import files. --- app/livechat/client/lib/stream/queueManager.js | 6 +++--- app/livechat/client/views/app/livechatReadOnly.js | 4 +--- app/livechat/server/lib/Livechat.js | 15 +++++++++++++++ .../server/methods/removeAllClosedRooms.js | 8 +++----- app/livechat/server/methods/removeRoom.js | 7 +++---- app/models/server/models/LivechatInquiry.js | 8 ++++++++ 6 files changed, 33 insertions(+), 15 deletions(-) diff --git a/app/livechat/client/lib/stream/queueManager.js b/app/livechat/client/lib/stream/queueManager.js index 32eef969cfc..5f58fdc5637 100644 --- a/app/livechat/client/lib/stream/queueManager.js +++ b/app/livechat/client/lib/stream/queueManager.js @@ -15,12 +15,12 @@ const events = { }, changed: (inquiry, collection) => { if (inquiry.status !== 'queued' || (inquiry.department && !agentDepartments.includes(inquiry.department))) { - return collection.remove({ rid: inquiry.rid }); + return collection.remove(inquiry._id); } delete inquiry.type; - collection.upsert({ rid: inquiry.rid }, inquiry); + collection.upsert({ _id: inquiry._id }, inquiry); }, - removed: (inquiry, collection) => collection.remove({ rid: inquiry.rid }), + removed: (inquiry, collection) => collection.remove(inquiry._id), }; const appendListenerToDepartment = (departmentId, collection) => livechatQueueStreamer.on(`${ LIVECHAT_INQUIRY_QUEUE_STREAM_OBSERVER }/${ departmentId }`, (inquiry) => events[inquiry.type](inquiry, collection)); diff --git a/app/livechat/client/views/app/livechatReadOnly.js b/app/livechat/client/views/app/livechatReadOnly.js index dc928e19fe5..da599cb65cb 100644 --- a/app/livechat/client/views/app/livechatReadOnly.js +++ b/app/livechat/client/views/app/livechatReadOnly.js @@ -50,9 +50,7 @@ Template.livechatReadOnly.onCreated(function() { this.preparing = new ReactiveVar(true); this.updateInquiry = (inquiry) => { - if (inquiry && inquiry.rid === this.rid) { - this.inquiry.set(inquiry); - } + this.inquiry.set(inquiry); }; Meteor.call('livechat:getRoutingConfig', (err, config) => { diff --git a/app/livechat/server/lib/Livechat.js b/app/livechat/server/lib/Livechat.js index f2f43691ce7..9853dcb5a28 100644 --- a/app/livechat/server/lib/Livechat.js +++ b/app/livechat/server/lib/Livechat.js @@ -370,6 +370,20 @@ export const Livechat = { return true; }, + removeRoom(rid) { + check(rid, String); + const room = LivechatRooms.findOneById(rid); + if (!room) { + throw new Meteor.Error('error-invalid-room', 'Invalid room', { method: 'livechat:removeRoom' }); + } + + Messages.removeByRoomId(rid); + Subscriptions.removeByRoomId(rid); + LivechatInquiry.removeByRoomId(rid); + return LivechatRooms.removeById(rid); + }, + + setCustomFields({ token, key, value, overwrite } = {}) { check(token, String); check(key, String); @@ -757,6 +771,7 @@ export const Livechat = { Subscriptions.removeByVisitorToken(token); LivechatRooms.removeByVisitorToken(token); + LivechatInquiry.removeByVisitorToken(token); }, saveDepartmentAgents(_id, departmentAgents) { diff --git a/app/livechat/server/methods/removeAllClosedRooms.js b/app/livechat/server/methods/removeAllClosedRooms.js index 6849d2b40e6..ae29e85a030 100644 --- a/app/livechat/server/methods/removeAllClosedRooms.js +++ b/app/livechat/server/methods/removeAllClosedRooms.js @@ -1,7 +1,8 @@ import { Meteor } from 'meteor/meteor'; import { hasPermission } from '../../../authorization'; -import { LivechatRooms, Messages, Subscriptions } from '../../../models'; +import { LivechatRooms } from '../../../models'; +import { Livechat } from '../lib/Livechat'; Meteor.methods({ 'livechat:removeAllClosedRooms'(departmentIds) { @@ -11,10 +12,7 @@ Meteor.methods({ let count = 0; LivechatRooms.findClosedRooms(departmentIds).forEach(({ _id }) => { - Messages.removeByRoomId(_id); - Subscriptions.removeByRoomId(_id); - LivechatRooms.removeById(_id); - + Livechat.removeRoom(_id); count++; }); diff --git a/app/livechat/server/methods/removeRoom.js b/app/livechat/server/methods/removeRoom.js index ef0329ae0b4..f8c251e28a3 100644 --- a/app/livechat/server/methods/removeRoom.js +++ b/app/livechat/server/methods/removeRoom.js @@ -1,7 +1,8 @@ import { Meteor } from 'meteor/meteor'; import { hasPermission } from '../../../authorization'; -import { LivechatRooms, Messages, Subscriptions } from '../../../models'; +import { LivechatRooms } from '../../../models'; +import { Livechat } from '../lib/Livechat'; Meteor.methods({ 'livechat:removeRoom'(rid) { @@ -29,8 +30,6 @@ Meteor.methods({ }); } - Messages.removeByRoomId(rid); - Subscriptions.removeByRoomId(rid); - return LivechatRooms.removeById(rid); + return Livechat.removeRoom(rid); }, }); diff --git a/app/models/server/models/LivechatInquiry.js b/app/models/server/models/LivechatInquiry.js index f7a78064d8a..ccf54c44523 100644 --- a/app/models/server/models/LivechatInquiry.js +++ b/app/models/server/models/LivechatInquiry.js @@ -172,6 +172,14 @@ export class LivechatInquiry extends Base { removeByRoomId(rid) { return this.remove({ rid }); } + + removeByVisitorToken(token) { + const query = { + 'v.token': token, + }; + + this.remove(query); + } } export default new LivechatInquiry(); From be97a51e49d251e727beeca56626248936820d72 Mon Sep 17 00:00:00 2001 From: gabriellsh <40830821+gabriellsh@users.noreply.github.com> Date: Fri, 21 Feb 2020 15:05:23 -0300 Subject: [PATCH 12/30] [FIX] ie11 support (#16682) --- app/ui-sidenav/client/userPresence.js | 22 +++++++++++++++++----- imports/client/query-string | 1 + imports/client/scheduler | 1 + imports/client/split-on-first | 1 + imports/client/strict-uri-encode | 1 + 5 files changed, 21 insertions(+), 5 deletions(-) create mode 120000 imports/client/query-string create mode 120000 imports/client/scheduler create mode 120000 imports/client/split-on-first create mode 120000 imports/client/strict-uri-encode diff --git a/app/ui-sidenav/client/userPresence.js b/app/ui-sidenav/client/userPresence.js index 32501e8d925..f6ae3e82171 100644 --- a/app/ui-sidenav/client/userPresence.js +++ b/app/ui-sidenav/client/userPresence.js @@ -67,7 +67,9 @@ const handleEntries = function(entries) { getAll(); }; -const observer = new IntersectionObserver(handleEntries, options); +const featureExists = !!window.IntersectionObserver; + +const observer = featureExists && new IntersectionObserver(handleEntries, options); Tracker.autorun(() => { if (!Meteor.userId() || !Meteor.status().connected) { @@ -75,13 +77,23 @@ Tracker.autorun(() => { } mem.clear(get); - for (const node of data.keys()) { - observer.unobserve(node); - observer.observe(node); + if (featureExists) { + for (const node of data.keys()) { + observer.unobserve(node); + observer.observe(node); + } } + + get(this.data.uid); + getAll(); }); Template.userPresence.onRendered(function() { data.set(this.firstNode, this.data); - observer.observe(this.firstNode); + if (featureExists) { + return observer.observe(this.firstNode); + } + + get(this.data.uid); + getAll(); }); diff --git a/imports/client/query-string b/imports/client/query-string new file mode 120000 index 00000000000..3d5529bafa0 --- /dev/null +++ b/imports/client/query-string @@ -0,0 +1 @@ +../../node_modules/query-string/ \ No newline at end of file diff --git a/imports/client/scheduler b/imports/client/scheduler new file mode 120000 index 00000000000..d6ef6285d8c --- /dev/null +++ b/imports/client/scheduler @@ -0,0 +1 @@ +../../node_modules/scheduler/ \ No newline at end of file diff --git a/imports/client/split-on-first b/imports/client/split-on-first new file mode 120000 index 00000000000..ac3c7769404 --- /dev/null +++ b/imports/client/split-on-first @@ -0,0 +1 @@ +../../node_modules/split-on-first/ \ No newline at end of file diff --git a/imports/client/strict-uri-encode b/imports/client/strict-uri-encode new file mode 120000 index 00000000000..77c01a2aedb --- /dev/null +++ b/imports/client/strict-uri-encode @@ -0,0 +1 @@ +../../node_modules/strict-uri-encode/ \ No newline at end of file From 031fd615b50728e34c983e243cc4bfc5db4e0a7b Mon Sep 17 00:00:00 2001 From: Diego Sampaio Date: Fri, 21 Feb 2020 15:23:41 -0300 Subject: [PATCH 13/30] Bump version to 3.0.2 --- .docker/Dockerfile.rhel | 2 +- .github/history.json | 48 +++++++++++++++++++++++++++++++++++++++ HISTORY.md | 23 +++++++++++++++++++ app/utils/rocketchat.info | 2 +- package.json | 2 +- 5 files changed, 74 insertions(+), 3 deletions(-) diff --git a/.docker/Dockerfile.rhel b/.docker/Dockerfile.rhel index c3d663fc2ba..26f7053acf2 100644 --- a/.docker/Dockerfile.rhel +++ b/.docker/Dockerfile.rhel @@ -1,6 +1,6 @@ FROM registry.access.redhat.com/rhscl/nodejs-8-rhel7 -ENV RC_VERSION 3.0.1 +ENV RC_VERSION 3.0.2 MAINTAINER buildmaster@rocket.chat diff --git a/.github/history.json b/.github/history.json index 56e30e9a729..0ec310d4b38 100644 --- a/.github/history.json +++ b/.github/history.json @@ -39822,6 +39822,54 @@ ] } ] + }, + "3.0.2": { + "node_version": "12.14.0", + "npm_version": "6.13.4", + "mongo_versions": [ + "3.4", + "3.6", + "4.0" + ], + "pull_requests": [ + { + "pr": "16682", + "title": "[FIX] ie11 support", + "userLogin": "gabriellsh", + "milestone": "3.0.2", + "contributors": [ + "gabriellsh" + ] + }, + { + "pr": "16603", + "title": "[FIX] Omnichannel Inquiry queues when removing chats", + "userLogin": "renatobecker", + "milestone": "3.0.2", + "contributors": [ + "renatobecker" + ] + }, + { + "pr": "16495", + "title": "[FIX] users.info endpoint not handling the error if the user does not exist", + "userLogin": "MarcosSpessatto", + "milestone": "3.0.2", + "contributors": [ + "MarcosSpessatto", + "sampaiodiego" + ] + }, + { + "pr": "16668", + "title": "[FIX] Clear unread red line when the ESC key is pressed ", + "userLogin": "ggazzo", + "milestone": "3.0.2", + "contributors": [ + "ggazzo" + ] + } + ] } } } \ No newline at end of file diff --git a/HISTORY.md b/HISTORY.md index e86db17e826..62686946b4c 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,4 +1,27 @@ +# 3.0.2 +`2020-02-21 ยท 4 ๐Ÿ› ยท 5 ๐Ÿ‘ฉโ€๐Ÿ’ป๐Ÿ‘จโ€๐Ÿ’ป` + +### Engine versions +- Node: `12.14.0` +- NPM: `6.13.4` +- MongoDB: `3.4, 3.6, 4.0` + +### ๐Ÿ› Bug fixes + +- ie11 support ([#16682](https://github.com/RocketChat/Rocket.Chat/pull/16682)) +- Omnichannel Inquiry queues when removing chats ([#16603](https://github.com/RocketChat/Rocket.Chat/pull/16603)) +- users.info endpoint not handling the error if the user does not exist ([#16495](https://github.com/RocketChat/Rocket.Chat/pull/16495)) +- Clear unread red line when the ESC key is pressed ([#16668](https://github.com/RocketChat/Rocket.Chat/pull/16668)) + +### ๐Ÿ‘ฉโ€๐Ÿ’ป๐Ÿ‘จโ€๐Ÿ’ป Core Team ๐Ÿค“ + +- [@MarcosSpessatto](https://github.com/MarcosSpessatto) +- [@gabriellsh](https://github.com/gabriellsh) +- [@ggazzo](https://github.com/ggazzo) +- [@renatobecker](https://github.com/renatobecker) +- [@sampaiodiego](https://github.com/sampaiodiego) + # 3.0.1 `2020-02-19 ยท 7 ๐Ÿ› ยท 4 ๐Ÿ‘ฉโ€๐Ÿ’ป๐Ÿ‘จโ€๐Ÿ’ป` diff --git a/app/utils/rocketchat.info b/app/utils/rocketchat.info index 9bc526777aa..5298a3fef98 100644 --- a/app/utils/rocketchat.info +++ b/app/utils/rocketchat.info @@ -1,3 +1,3 @@ { - "version": "3.0.1" + "version": "3.0.2" } diff --git a/package.json b/package.json index d6970a605cb..b796a24f3c5 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "Rocket.Chat", "description": "The Ultimate Open Source WebChat Platform", - "version": "3.0.1", + "version": "3.0.2", "author": { "name": "Rocket.Chat", "url": "https://rocket.chat/" From 9d7150b574e0016c7155a2db95c80ef305bc94b7 Mon Sep 17 00:00:00 2001 From: Renato Becker Date: Thu, 20 Feb 2020 16:22:11 -0300 Subject: [PATCH 14/30] [IMPROVE] Check agent status when starting a new conversation with an agent assigned (#16618) --- app/livechat/server/lib/Helper.js | 10 ++++++++++ app/livechat/server/lib/QueueManager.js | 5 ++--- app/models/server/models/Users.js | 4 ++-- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/app/livechat/server/lib/Helper.js b/app/livechat/server/lib/Helper.js index 2c02722ff96..b8cf56a241e 100644 --- a/app/livechat/server/lib/Helper.js +++ b/app/livechat/server/lib/Helper.js @@ -275,3 +275,13 @@ export const normalizeTransferredByData = (transferredBy, room) => { type, }; }; + +export const checkServiceStatus = ({ guest, agent }) => { + if (agent) { + const { agentId } = agent; + const users = Users.findOnlineAgents(agentId); + return users && users.count() > 0; + } + + return Livechat.online(guest.department); +}; diff --git a/app/livechat/server/lib/QueueManager.js b/app/livechat/server/lib/QueueManager.js index cdd4aa1c601..aa1632390e2 100644 --- a/app/livechat/server/lib/QueueManager.js +++ b/app/livechat/server/lib/QueueManager.js @@ -2,10 +2,9 @@ import { Meteor } from 'meteor/meteor'; import { Match, check } from 'meteor/check'; import { LivechatRooms, LivechatInquiry } from '../../../models/server'; -import { createLivechatRoom, createLivechatInquiry } from './Helper'; +import { checkServiceStatus, createLivechatRoom, createLivechatInquiry } from './Helper'; import { callbacks } from '../../../callbacks/server'; import { RoutingManager } from './RoutingManager'; -import { Livechat } from './Livechat'; export const QueueManager = { async requestRoom({ guest, message, roomInfo, agent }) { @@ -19,7 +18,7 @@ export const QueueManager = { department: Match.Maybe(String), })); - if (!Livechat.online(guest.department)) { + if (!checkServiceStatus({ guest, agent })) { throw new Meteor.Error('no-agent-online', 'Sorry, no online agents'); } diff --git a/app/models/server/models/Users.js b/app/models/server/models/Users.js index 9d594a9f32b..2e0fd8dc82c 100644 --- a/app/models/server/models/Users.js +++ b/app/models/server/models/Users.js @@ -91,8 +91,8 @@ export class Users extends Base { return this.update(_id, update); } - findOnlineAgents() { - const query = queryStatusAgentOnline(); + findOnlineAgents(agentId) { + const query = queryStatusAgentOnline(agentId && { _id: agentId }); return this.find(query); } From 661ad361bd4438eb7ce607c7720a00969a0d7328 Mon Sep 17 00:00:00 2001 From: Rodrigo Nascimento Date: Thu, 20 Feb 2020 17:44:20 -0300 Subject: [PATCH 15/30] [FIX] LDAP sync admin action was not syncing exisent users (#16671) --- app/ldap/server/ldap.js | 7 ++- app/ldap/server/sync.js | 9 ++-- app/ldap/server/syncUsers.js | 4 +- .../server/functions/setUserActiveStatus.js | 46 +++++++++++++++++++ server/methods/setUserActiveStatus.js | 42 +---------------- 5 files changed, 61 insertions(+), 47 deletions(-) create mode 100644 app/lib/server/functions/setUserActiveStatus.js diff --git a/app/ldap/server/ldap.js b/app/ldap/server/ldap.js index c18370b09ce..0739e688027 100644 --- a/app/ldap/server/ldap.js +++ b/app/ldap/server/ldap.js @@ -2,6 +2,7 @@ import { Meteor } from 'meteor/meteor'; import ldapjs from 'ldapjs'; import Bunyan from 'bunyan'; +import { callbacks } from '../../callbacks/server'; import { settings } from '../../settings'; import { Logger } from '../../logger'; @@ -376,6 +377,8 @@ export default class LDAP { searchAllPaged(BaseDN, options, page) { this.bindIfNecessary(); + ({ BaseDN, options } = callbacks.run('ldap.beforeSearchAll', { BaseDN, options })); + const processPage = ({ entries, title, end, next }) => { logger.search.info(title); // Force LDAP idle to wait the record processing @@ -425,8 +428,8 @@ export default class LDAP { title: 'Final Page', end: true, }); + entries = []; } else if (entries.length) { - logger.search.info('Page'); processPage({ entries, title: 'Page', @@ -453,6 +456,8 @@ export default class LDAP { searchAllAsync(BaseDN, options, callback) { this.bindIfNecessary(); + ({ BaseDN, options } = callbacks.run('ldap.beforeSearchAll', { BaseDN, options })); + this.client.search(BaseDN, options, (error, res) => { if (error) { logger.search.error(error); diff --git a/app/ldap/server/sync.js b/app/ldap/server/sync.js index e9ff3a30a45..5a17a64f9e8 100644 --- a/app/ldap/server/sync.js +++ b/app/ldap/server/sync.js @@ -5,6 +5,7 @@ import { SyncedCron } from 'meteor/littledata:synced-cron'; import _ from 'underscore'; import LDAP from './ldap'; +import { callbacks } from '../../callbacks/server'; import { RocketChatFile } from '../../file'; import { settings } from '../../settings'; import { Notifications } from '../../notifications'; @@ -16,7 +17,7 @@ import { FileUpload } from '../../file-upload'; import { addUserToRoom, removeUserFromRoom, createRoom } from '../../lib/server/functions'; -const logger = new Logger('LDAPSync', {}); +export const logger = new Logger('LDAPSync', {}); export function isUserInLDAPGroup(ldap, ldapUser, user, ldapGroup) { const syncUserRolesFilter = settings.get('LDAP_Sync_User_Data_Groups_Filter').trim(); @@ -531,7 +532,7 @@ export function importNewUsers(ldap) { })); } -function sync() { +export function sync() { if (settings.get('LDAP_Enable') !== true) { return; } @@ -562,9 +563,9 @@ function sync() { if (ldapUser) { syncUserData(user, ldapUser, ldap); - } else { - logger.info('Can\'t sync user', user.username); } + + callbacks.run('ldap.afterSyncExistentUser', { ldapUser, user }); }); } } catch (error) { diff --git a/app/ldap/server/syncUsers.js b/app/ldap/server/syncUsers.js index 8713c8973e5..d1f873af86d 100644 --- a/app/ldap/server/syncUsers.js +++ b/app/ldap/server/syncUsers.js @@ -1,6 +1,6 @@ import { Meteor } from 'meteor/meteor'; -import { importNewUsers } from './sync'; +import { sync } from './sync'; import { hasRole } from '../../authorization'; import { settings } from '../../settings'; @@ -21,7 +21,7 @@ Meteor.methods({ this.unblock(); - importNewUsers(); + sync(); return { message: 'Sync_in_progress', diff --git a/app/lib/server/functions/setUserActiveStatus.js b/app/lib/server/functions/setUserActiveStatus.js new file mode 100644 index 00000000000..5a432d8cb76 --- /dev/null +++ b/app/lib/server/functions/setUserActiveStatus.js @@ -0,0 +1,46 @@ +import { check } from 'meteor/check'; +import { Accounts } from 'meteor/accounts-base'; + +import * as Mailer from '../../../mailer'; +import { Users, Subscriptions } from '../../../models'; +import { settings } from '../../../settings'; + +export function setUserActiveStatus(userId, active) { + check(userId, String); + check(active, Boolean); + + const user = Users.findOneById(userId); + + if (!user) { + return false; + } + + Users.setUserActive(userId, active); + + if (user.username) { + Subscriptions.setArchivedByUsername(user.username, !active); + } + + if (active === false) { + Users.unsetLoginTokens(userId); + } else { + Users.unsetReason(userId); + } + if (active && !settings.get('Accounts_Send_Email_When_Activating')) { + return true; + } + if (!active && !settings.get('Accounts_Send_Email_When_Deactivating')) { + return true; + } + + const destinations = Array.isArray(user.emails) && user.emails.map((email) => `${ user.name || user.username }<${ email.address }>`); + + const email = { + to: destinations, + from: settings.get('From_Email'), + subject: Accounts.emailTemplates.userActivated.subject({ active }), + html: Accounts.emailTemplates.userActivated.html({ active, name: user.name, username: user.username }), + }; + + Mailer.sendNoWrap(email); +} diff --git a/server/methods/setUserActiveStatus.js b/server/methods/setUserActiveStatus.js index 2328d79d54c..d06e2aea0f3 100644 --- a/server/methods/setUserActiveStatus.js +++ b/server/methods/setUserActiveStatus.js @@ -1,11 +1,8 @@ import { Meteor } from 'meteor/meteor'; import { check } from 'meteor/check'; -import { Accounts } from 'meteor/accounts-base'; -import * as Mailer from '../../app/mailer'; import { hasPermission } from '../../app/authorization'; -import { Users, Subscriptions } from '../../app/models'; -import { settings } from '../../app/settings'; +import { setUserActiveStatus } from '../../app/lib/server/functions/setUserActiveStatus'; Meteor.methods({ setUserActiveStatus(userId, active) { @@ -24,42 +21,7 @@ Meteor.methods({ }); } - const user = Users.findOneById(userId); - - if (!user) { - return false; - } - - Users.setUserActive(userId, active); - - if (user.username) { - Subscriptions.setArchivedByUsername(user.username, !active); - } - - if (active === false) { - Users.unsetLoginTokens(userId); - } else { - Users.unsetReason(userId); - } - if (active && !settings.get('Accounts_Send_Email_When_Activating')) { - return true; - } - if (!active && !settings.get('Accounts_Send_Email_When_Deactivating')) { - return true; - } - - const destinations = Array.isArray(user.emails) && user.emails.map((email) => `${ user.name || user.username }<${ email.address }>`); - - - const email = { - to: destinations, - from: settings.get('From_Email'), - subject: Accounts.emailTemplates.userActivated.subject({ active }), - html: Accounts.emailTemplates.userActivated.html({ active, name: user.name, username: user.username }), - }; - - Mailer.sendNoWrap(email); - + setUserActiveStatus(userId, active); return true; }, From 1b333f942dae5c97676cfa37702d4a4770a4a12c Mon Sep 17 00:00:00 2001 From: pierre-lehnen-rc <55164754+pierre-lehnen-rc@users.noreply.github.com> Date: Thu, 27 Feb 2020 15:24:21 -0300 Subject: [PATCH 16/30] [FIX] Rocket.Chat takes too long to set the username when it fails to send enrollment email (#16723) --- app/lib/server/functions/setUsername.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/lib/server/functions/setUsername.js b/app/lib/server/functions/setUsername.js index d705d436c08..7656e7dbe4a 100644 --- a/app/lib/server/functions/setUsername.js +++ b/app/lib/server/functions/setUsername.js @@ -41,7 +41,9 @@ export const _setUsername = function(userId, u) { // If first time setting username, send Enrollment Email try { if (!previousUsername && user.emails && user.emails.length > 0 && settings.get('Accounts_Enrollment_Email')) { - Accounts.sendEnrollmentEmail(user._id); + Meteor.defer(() => { + Accounts.sendEnrollmentEmail(user._id); + }); } } catch (e) { console.error(e); From 8a650e50ab9792b54454f5f321e03b5b6ec69b50 Mon Sep 17 00:00:00 2001 From: Aaron Ogle Date: Thu, 27 Feb 2020 12:25:25 -0600 Subject: [PATCH 17/30] [FIX] Manual Register use correct state for determining registered (#16726) * Fix: Manual Register api call * show button using correct condition * Removed '-->' from modal Co-authored-by: Douglas Gubert --- app/api/server/v1/cloud.js | 2 +- app/cloud/client/admin/cloud.html | 2 +- app/ui-utils/client/lib/modal.html | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/api/server/v1/cloud.js b/app/api/server/v1/cloud.js index 1aa430151c4..7b1b3e72912 100644 --- a/app/api/server/v1/cloud.js +++ b/app/api/server/v1/cloud.js @@ -17,7 +17,7 @@ API.v1.addRoute('cloud.manualRegister', { authRequired: true }, { const registrationInfo = retrieveRegistrationStatus(); - if (registrationInfo.connectToCloud) { + if (registrationInfo.workspaceRegistered) { return API.v1.failure('Workspace is already registered'); } diff --git a/app/cloud/client/admin/cloud.html b/app/cloud/client/admin/cloud.html index 41b24ec93d7..78c1e053390 100644 --- a/app/cloud/client/admin/cloud.html +++ b/app/cloud/client/admin/cloud.html @@ -3,7 +3,7 @@
{{#header sectionName="Connectivity_Services" hideHelp=true fixedHeight=true fullpage=true}}
- {{#unless info.connectToCloud}} + {{#unless info.workspaceRegistered}} diff --git a/app/ui-utils/client/lib/modal.html b/app/ui-utils/client/lib/modal.html index 69cbe1da8bf..19ad6fe23d5 100644 --- a/app/ui-utils/client/lib/modal.html +++ b/app/ui-utils/client/lib/modal.html @@ -6,7 +6,7 @@ {{# if template}} - {{> Template.dynamic template=template data=data}} --> + {{> Template.dynamic template=template data=data}} {{else}}

From 0e9d6ea8ff839a3567efb773750de50ed8689f28 Mon Sep 17 00:00:00 2001 From: Rodrigo Nascimento Date: Mon, 2 Mar 2020 10:36:48 -0300 Subject: [PATCH 18/30] [FIX] Language country has been ignored on translation load (#16757) * [FIX] Language country has been ignored on translation load * Enforce uppercase country on filterLanguage method and change the language list to list with uppercase countries --- app/ui-account/client/accountPreferences.js | 4 ++-- client/startup/i18n.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/ui-account/client/accountPreferences.js b/app/ui-account/client/accountPreferences.js index 7c6c38b8a5f..d17cd1c8094 100644 --- a/app/ui-account/client/accountPreferences.js +++ b/app/ui-account/client/accountPreferences.js @@ -49,7 +49,7 @@ Template.accountPreferences.helpers({ const languages = TAPi18n.getLanguages(); const result = Object.entries(languages) - .map(([key, language]) => ({ ...language, key: key.toLowerCase() })) + .map(([key, language]) => ({ ...language, key })) .sort((a, b) => a.key - b.key); result.unshift({ @@ -62,7 +62,7 @@ Template.accountPreferences.helpers({ }, isUserLanguage(key) { const languageKey = Meteor.user().language; - return typeof languageKey === 'string' && languageKey.toLowerCase() === key; + return typeof languageKey === 'string' && languageKey.toLowerCase() === key.toLowerCase(); }, ifThenElse(condition, val, not = '') { return condition ? val : not; diff --git a/client/startup/i18n.js b/client/startup/i18n.js index 4f9d0a996d2..c0e35e78815 100644 --- a/client/startup/i18n.js +++ b/client/startup/i18n.js @@ -21,7 +21,7 @@ Meteor.startup(() => { const regex = /([a-z]{2,3})-([a-z]{2,4})/; const matches = regex.exec(language); if (matches) { - return `${ matches[1] }-${ matches[2].toLowerCase() }`; + return `${ matches[1] }-${ matches[2].toUpperCase() }`; } return language; From 8cc8a603a5315b0b2bcb5bd9119d987bc988ea5c Mon Sep 17 00:00:00 2001 From: Diego Sampaio Date: Mon, 2 Mar 2020 16:00:13 -0300 Subject: [PATCH 19/30] Bump version to 3.0.3 --- .docker/Dockerfile.rhel | 2 +- .github/history.json | 91 ++++++++++++++++++++++++++++++++++++++- HISTORY.md | 43 +++++++++++++++++- app/utils/rocketchat.info | 2 +- package.json | 2 +- 5 files changed, 135 insertions(+), 5 deletions(-) diff --git a/.docker/Dockerfile.rhel b/.docker/Dockerfile.rhel index 26f7053acf2..3edc448beea 100644 --- a/.docker/Dockerfile.rhel +++ b/.docker/Dockerfile.rhel @@ -1,6 +1,6 @@ FROM registry.access.redhat.com/rhscl/nodejs-8-rhel7 -ENV RC_VERSION 3.0.2 +ENV RC_VERSION 3.0.3 MAINTAINER buildmaster@rocket.chat diff --git a/.github/history.json b/.github/history.json index 0ec310d4b38..44a7272e4ba 100644 --- a/.github/history.json +++ b/.github/history.json @@ -39823,6 +39823,27 @@ } ] }, + "2.4.10": { + "node_version": "8.17.0", + "npm_version": "6.13.4", + "mongo_versions": [ + "3.4", + "3.6", + "4.0" + ], + "pull_requests": [ + { + "pr": "16495", + "title": "[FIX] users.info endpoint not handling the error if the user does not exist", + "userLogin": "MarcosSpessatto", + "milestone": "3.0.2", + "contributors": [ + "MarcosSpessatto", + "sampaiodiego" + ] + } + ] + }, "3.0.2": { "node_version": "12.14.0", "npm_version": "6.13.4", @@ -39870,6 +39891,74 @@ ] } ] + }, + "2.4.11": { + "node_version": "8.17.0", + "npm_version": "6.13.4", + "mongo_versions": [ + "3.4", + "3.6", + "4.0" + ], + "pull_requests": [] + }, + "3.0.3": { + "node_version": "12.14.0", + "npm_version": "6.13.4", + "mongo_versions": [ + "3.4", + "3.6", + "4.0" + ], + "pull_requests": [ + { + "pr": "16757", + "title": "[FIX] Language country has been ignored on translation load", + "userLogin": "rodrigok", + "milestone": "3.0.3", + "contributors": [ + "rodrigok" + ] + }, + { + "pr": "16726", + "title": "[FIX] Manual Register use correct state for determining registered", + "userLogin": "geekgonecrazy", + "milestone": "3.0.3", + "contributors": [ + "geekgonecrazy", + "web-flow", + "d-gubert" + ] + }, + { + "pr": "16723", + "title": "[FIX] Rocket.Chat takes too long to set the username when it fails to send enrollment email", + "userLogin": "pierre-lehnen-rc", + "milestone": "3.0.3", + "contributors": [ + "pierre-lehnen-rc" + ] + }, + { + "pr": "16671", + "title": "[FIX] LDAP sync admin action was not syncing existent users", + "userLogin": "rodrigok", + "milestone": "3.0.3", + "contributors": [ + "rodrigok" + ] + }, + { + "pr": "16618", + "title": "[FIX] Check agent status when starting a new conversation with an agent assigned", + "userLogin": "renatobecker", + "milestone": "3.0.3", + "contributors": [ + "renatobecker" + ] + } + ] } } -} \ No newline at end of file +} diff --git a/HISTORY.md b/HISTORY.md index 62686946b4c..40f27d6c39d 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,4 +1,28 @@ +# 3.0.3 +`2020-03-02 ยท 5 ๐Ÿ› ยท 5 ๐Ÿ‘ฉโ€๐Ÿ’ป๐Ÿ‘จโ€๐Ÿ’ป` + +### Engine versions +- Node: `12.14.0` +- NPM: `6.13.4` +- MongoDB: `3.4, 3.6, 4.0` + +### ๐Ÿ› Bug fixes + +- Language country has been ignored on translation load ([#16757](https://github.com/RocketChat/Rocket.Chat/pull/16757)) +- Manual Register use correct state for determining registered ([#16726](https://github.com/RocketChat/Rocket.Chat/pull/16726)) +- Rocket.Chat takes too long to set the username when it fails to send enrollment email ([#16723](https://github.com/RocketChat/Rocket.Chat/pull/16723)) +- LDAP sync admin action was not syncing existent users ([#16671](https://github.com/RocketChat/Rocket.Chat/pull/16671)) +- Check agent status when starting a new conversation with an agent assigned ([#16618](https://github.com/RocketChat/Rocket.Chat/pull/16618)) + +### ๐Ÿ‘ฉโ€๐Ÿ’ป๐Ÿ‘จโ€๐Ÿ’ป Core Team ๐Ÿค“ + +- [@d-gubert](https://github.com/d-gubert) +- [@geekgonecrazy](https://github.com/geekgonecrazy) +- [@pierre-lehnen-rc](https://github.com/pierre-lehnen-rc) +- [@renatobecker](https://github.com/renatobecker) +- [@rodrigok](https://github.com/rodrigok) + # 3.0.2 `2020-02-21 ยท 4 ๐Ÿ› ยท 5 ๐Ÿ‘ฉโ€๐Ÿ’ป๐Ÿ‘จโ€๐Ÿ’ป` @@ -203,6 +227,23 @@ - [@sampaiodiego](https://github.com/sampaiodiego) - [@tassoevan](https://github.com/tassoevan) +# 2.4.10 +`2020-02-20 ยท 1 ๐Ÿ› ยท 2 ๐Ÿ‘ฉโ€๐Ÿ’ป๐Ÿ‘จโ€๐Ÿ’ป` + +### Engine versions +- Node: `8.17.0` +- NPM: `6.13.4` +- MongoDB: `3.4, 3.6, 4.0` + +### ๐Ÿ› Bug fixes + +- users.info endpoint not handling the error if the user does not exist ([#16495](https://github.com/RocketChat/Rocket.Chat/pull/16495)) + +### ๐Ÿ‘ฉโ€๐Ÿ’ป๐Ÿ‘จโ€๐Ÿ’ป Core Team ๐Ÿค“ + +- [@MarcosSpessatto](https://github.com/MarcosSpessatto) +- [@sampaiodiego](https://github.com/sampaiodiego) + # 2.4.9 `2020-02-10 ยท 1 ๐Ÿ› ยท 1 ๐Ÿ” ยท 1 ๐Ÿ‘ฉโ€๐Ÿ’ป๐Ÿ‘จโ€๐Ÿ’ป` @@ -6632,4 +6673,4 @@ - [@graywolf336](https://github.com/graywolf336) - [@marceloschmidt](https://github.com/marceloschmidt) - [@rodrigok](https://github.com/rodrigok) -- [@sampaiodiego](https://github.com/sampaiodiego) \ No newline at end of file +- [@sampaiodiego](https://github.com/sampaiodiego) diff --git a/app/utils/rocketchat.info b/app/utils/rocketchat.info index 5298a3fef98..ad3aeee82e4 100644 --- a/app/utils/rocketchat.info +++ b/app/utils/rocketchat.info @@ -1,3 +1,3 @@ { - "version": "3.0.2" + "version": "3.0.3" } diff --git a/package.json b/package.json index b796a24f3c5..b63dbf35dc2 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "Rocket.Chat", "description": "The Ultimate Open Source WebChat Platform", - "version": "3.0.2", + "version": "3.0.3", "author": { "name": "Rocket.Chat", "url": "https://rocket.chat/" From c371875cf559257613cd1d6fa581b99fec0c225c Mon Sep 17 00:00:00 2001 From: pierre-lehnen-rc <55164754+pierre-lehnen-rc@users.noreply.github.com> Date: Wed, 26 Feb 2020 16:49:42 -0300 Subject: [PATCH 20/30] [FIX] TypeError when trying to load avatar of an invalid room. (#16699) --- server/routes/avatar/room.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/server/routes/avatar/room.js b/server/routes/avatar/room.js index 450e211e54c..7c97106bfbc 100644 --- a/server/routes/avatar/room.js +++ b/server/routes/avatar/room.js @@ -14,7 +14,7 @@ const getRoom = (roomId) => { const room = Rooms.findOneById(roomId, { fields: { t: 1, prid: 1, name: 1, fname: 1 } }); // if it is a discussion, returns the parent room - if (room.prid) { + if (room && room.prid) { return Rooms.findOneById(room.prid, { fields: { t: 1, name: 1, fname: 1 } }); } return room; @@ -24,6 +24,12 @@ export const roomAvatar = Meteor.bindEnvironment(function(req, res/* , next*/) { const roomId = req.url.substr(1); const room = getRoom(roomId); + if (!room) { + res.writeHead(404); + res.end(); + return; + } + const roomName = roomTypes.getConfig(room.t).roomName(room); setCacheAndDispositionHeaders(req, res); From 98da220c695d127b9836c260af60a55cee63794f Mon Sep 17 00:00:00 2001 From: Diego Sampaio Date: Thu, 12 Mar 2020 18:00:10 -0300 Subject: [PATCH 21/30] [FIX] Integrations page pagination (#16838) --- app/integrations/client/views/integrations.js | 2 +- app/models/server/models/Integrations.js | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/app/integrations/client/views/integrations.js b/app/integrations/client/views/integrations.js index c568fa9293a..0506b21e169 100644 --- a/app/integrations/client/views/integrations.js +++ b/app/integrations/client/views/integrations.js @@ -46,7 +46,7 @@ Template.integrations.onCreated(async function() { this.autorun(async () => { const offset = this.offset.get(); - const { integrations, total } = await APIClient.v1.get(`integrations.list?count=${ ITEMS_COUNT }&offset=${ offset }`); + const { integrations, total } = await APIClient.v1.get(`integrations.list?sort={"type":1}&count=${ ITEMS_COUNT }&offset=${ offset }`); this.total.set(total); this.integrations.set(this.integrations.get().concat(integrations)); }); diff --git a/app/models/server/models/Integrations.js b/app/models/server/models/Integrations.js index 0db8901b959..ffbf40c1dcc 100644 --- a/app/models/server/models/Integrations.js +++ b/app/models/server/models/Integrations.js @@ -5,6 +5,8 @@ import { Base } from './_Base'; export class Integrations extends Base { constructor() { super('integrations'); + + this.tryEnsureIndex({ type: 1 }); } findByType(type, options) { From fe798d977821ea1b20532cda3e203c9adab01b46 Mon Sep 17 00:00:00 2001 From: Guilherme Gazzo Date: Thu, 20 Feb 2020 23:20:51 -0300 Subject: [PATCH 22/30] [IMPROVE] Send files over rest api (#16617) --- app/api/server/v1/rooms.js | 66 +++++++++--------- app/apps/client/admin/appInstall.js | 4 +- app/file-upload/server/lib/FileUpload.js | 2 + app/ui/client/lib/fileUpload.js | 87 +++++++++++++----------- app/utils/client/lib/RestApiClient.js | 28 ++++++-- 5 files changed, 110 insertions(+), 77 deletions(-) diff --git a/app/api/server/v1/rooms.js b/app/api/server/v1/rooms.js index 85924d77d27..2f8a7df23e0 100644 --- a/app/api/server/v1/rooms.js +++ b/app/api/server/v1/rooms.js @@ -59,38 +59,45 @@ API.v1.addRoute('rooms.get', { authRequired: true }, { }, }); -API.v1.addRoute('rooms.upload/:rid', { authRequired: true }, { - post() { - const room = Meteor.call('canAccessRoom', this.urlParams.rid, this.userId); +const getFiles = Meteor.wrapAsync(({ request }, callback) => { + const busboy = new Busboy({ headers: request.headers }); + const files = []; - if (!room) { - return API.v1.unauthorized(); + const fields = {}; + + + busboy.on('file', (fieldname, file, filename, encoding, mimetype) => { + if (fieldname !== 'file') { + return callback(new Meteor.Error('invalid-field')); } - const busboy = new Busboy({ headers: this.request.headers }); - const files = []; - const fields = {}; + const fileDate = []; + file.on('data', (data) => fileDate.push(data)); - Meteor.wrapAsync((callback) => { - busboy.on('file', (fieldname, file, filename, encoding, mimetype) => { - if (fieldname !== 'file') { - return callback(new Meteor.Error('invalid-field')); - } + file.on('end', () => { + files.push({ fieldname, file, filename, encoding, mimetype, fileBuffer: Buffer.concat(fileDate) }); + }); + }); - const fileDate = []; - file.on('data', (data) => fileDate.push(data)); + busboy.on('field', (fieldname, value) => { fields[fieldname] = value; }); - file.on('end', () => { - files.push({ fieldname, file, filename, encoding, mimetype, fileBuffer: Buffer.concat(fileDate) }); - }); - }); + busboy.on('finish', Meteor.bindEnvironment(() => callback(null, { files, fields }))); - busboy.on('field', (fieldname, value) => { fields[fieldname] = value; }); + request.pipe(busboy); +}); - busboy.on('finish', Meteor.bindEnvironment(() => callback())); +API.v1.addRoute('rooms.upload/:rid', { authRequired: true }, { + post() { + const room = Meteor.call('canAccessRoom', this.urlParams.rid, this.userId); + + if (!room) { + return API.v1.unauthorized(); + } - this.request.pipe(busboy); - })(); + + const { files, fields } = getFiles({ + request: this.request, + }); if (files.length === 0) { return API.v1.failure('File required'); @@ -102,8 +109,6 @@ API.v1.addRoute('rooms.upload/:rid', { authRequired: true }, { const file = files[0]; - const fileStore = FileUpload.getStore('Uploads'); - const details = { name: file.filename, size: file.fileBuffer.length, @@ -112,18 +117,17 @@ API.v1.addRoute('rooms.upload/:rid', { authRequired: true }, { userId: this.userId, }; - let fileData = {}; - - Meteor.runAsUser(this.userId, () => { - const uploadedFile = Meteor.wrapAsync(fileStore.insert.bind(fileStore))(details, file.fileBuffer); + const fileData = Meteor.runAsUser(this.userId, () => { + const fileStore = FileUpload.getStore('Uploads'); + const uploadedFile = fileStore.insertSync(details, file.fileBuffer); uploadedFile.description = fields.description; delete fields.description; - API.v1.success(Meteor.call('sendFileMessage', this.urlParams.rid, null, uploadedFile, fields)); + Meteor.call('sendFileMessage', this.urlParams.rid, null, uploadedFile, fields); - fileData = uploadedFile; + return uploadedFile; }); return API.v1.success({ message: Messages.getMessageByFileIdAndUsername(fileData._id, this.userId) }); diff --git a/app/apps/client/admin/appInstall.js b/app/apps/client/admin/appInstall.js index 1db80c13b11..031042ff2f0 100644 --- a/app/apps/client/admin/appInstall.js +++ b/app/apps/client/admin/appInstall.js @@ -148,9 +148,9 @@ Template.appInstall.events({ let result; if (isUpdating) { - result = await APIClient.upload(`apps/${ t.isUpdatingId.get() }`, data); + result = await APIClient.upload(`apps/${ t.isUpdatingId.get() }`, data).promise; } else { - result = await APIClient.upload('apps', data); + result = await APIClient.upload('apps', data).promise; } FlowRouter.go(`/admin/apps/${ result.app.id }?version=${ result.app.version }`); diff --git a/app/file-upload/server/lib/FileUpload.js b/app/file-upload/server/lib/FileUpload.js index b5a9c9d36c4..c66fe0276c7 100644 --- a/app/file-upload/server/lib/FileUpload.js +++ b/app/file-upload/server/lib/FileUpload.js @@ -435,6 +435,8 @@ export class FileUploadClass { } FileUpload.handlers[name] = this; + + this.insertSync = Meteor.wrapAsync(this.insert, this); } getStore() { diff --git a/app/ui/client/lib/fileUpload.js b/app/ui/client/lib/fileUpload.js index 42253997a60..e41ea15116d 100644 --- a/app/ui/client/lib/fileUpload.js +++ b/app/ui/client/lib/fileUpload.js @@ -1,12 +1,11 @@ -import { Meteor } from 'meteor/meteor'; import { Tracker } from 'meteor/tracker'; import { Session } from 'meteor/session'; import s from 'underscore.string'; import { Handlebars } from 'meteor/ui'; +import { Random } from 'meteor/random'; -import { fileUploadHandler } from '../../../file-upload'; import { settings } from '../../../settings/client'; -import { t, fileUploadIsValidContentType } from '../../../utils'; +import { t, fileUploadIsValidContentType, APIClient } from '../../../utils'; import { modal, prependReplies } from '../../../ui-utils'; @@ -193,7 +192,7 @@ export const fileUpload = async (files, input, { rid, tmid }) => { cancelButtonText: t('Cancel'), html: true, onRendered: () => $('#file-name').focus(), - }, (isConfirm) => { + }, async (isConfirm) => { if (!isConfirm) { return; } @@ -206,52 +205,48 @@ export const fileUpload = async (files, input, { rid, tmid }) => { description: document.getElementById('file-description').value, }; - const upload = fileUploadHandler('Uploads', record, file.file); + const fileName = document.getElementById('file-name').value || file.name || file.file.name; + + const data = new FormData(); + record.description && data.append('description', record.description); + msg && data.append('msg', msg); + tmid && data.append('tmid', tmid); + data.append('file', file.file, fileName); - uploadNextFile(); const uploads = Session.get('uploading') || []; - uploads.push({ - id: upload.id, - name: upload.getFileName(), + + const upload = { + id: Random.id(), + name: fileName, percentage: 0, - }); + }; + + uploads.push(upload); Session.set('uploading', uploads); - upload.onProgress = (progress) => { - const uploads = Session.get('uploading') || []; - uploads.filter((u) => u.id === upload.id).forEach((u) => { - u.percentage = Math.round(progress * 100) || 0; - }); - Session.set('uploading', uploads); - }; + uploadNextFile(); - upload.start((error, file, storage) => { - if (error) { + const { xhr, promise } = APIClient.upload(`v1/rooms.upload/${ rid }`, {}, data, { + progress(progress) { + const uploads = Session.get('uploading') || []; + + if (progress === 100) { + return; + } + uploads.filter((u) => u.id === upload.id).forEach((u) => { + u.percentage = Math.round(progress) || 0; + }); + Session.set('uploading', uploads); + }, + error(error) { const uploads = Session.get('uploading') || []; uploads.filter((u) => u.id === upload.id).forEach((u) => { u.error = error.message; u.percentage = 0; }); Session.set('uploading', uploads); - - return; - } - - if (!file) { - return; - } - - Meteor.call('sendFileMessage', rid, storage, file, { msg, tmid }, () => { - $(input) - .removeData('reply') - .trigger('dataChange'); - - setTimeout(() => { - const uploads = Session.get('uploading') || []; - Session.set('uploading', uploads.filter((u) => u.id !== upload.id)); - }, 2000); - }); + }, }); Tracker.autorun((computation) => { @@ -259,13 +254,27 @@ export const fileUpload = async (files, input, { rid, tmid }) => { if (!isCanceling) { return; } - computation.stop(); - upload.stop(); + Session.delete(`uploading-cancel-${ upload.id }`); + + xhr.abort(); const uploads = Session.get('uploading') || {}; Session.set('uploading', uploads.filter((u) => u.id !== upload.id)); }); + + try { + await promise; + const uploads = Session.get('uploading') || []; + return Session.set('uploading', uploads.filter((u) => u.id !== upload.id)); + } catch (error) { + const uploads = Session.get('uploading') || []; + uploads.filter((u) => u.id === upload.id).forEach((u) => { + u.error = error.message; + u.percentage = 0; + }); + Session.set('uploading', uploads); + } })); }; diff --git a/app/utils/client/lib/RestApiClient.js b/app/utils/client/lib/RestApiClient.js index 594927ebca1..6b927743cac 100644 --- a/app/utils/client/lib/RestApiClient.js +++ b/app/utils/client/lib/RestApiClient.js @@ -21,13 +21,13 @@ export const APIClient = { return APIClient._jqueryCall('POST', endpoint, params, body); }, - upload(endpoint, params, formData) { + upload(endpoint, params, formData, xhrOptions) { if (!formData) { formData = params; params = {}; } - return APIClient._jqueryFormDataCall(endpoint, params, formData); + return APIClient._jqueryFormDataCall(endpoint, params, formData, xhrOptions); }, _generateQueryFromParams(params) { @@ -68,15 +68,31 @@ export const APIClient = { }); }, - _jqueryFormDataCall(endpoint, params, formData) { + _jqueryFormDataCall(endpoint, params, formData, { progress = () => {}, error = () => {} } = {}) { + const ret = { }; + const query = APIClient._generateQueryFromParams(params); if (!(formData instanceof FormData)) { throw new Error('The formData parameter MUST be an instance of the FormData class.'); } - return new Promise(function _jqueryFormDataPromise(resolve, reject) { - jQuery.ajax({ + ret.promise = new Promise(function _jqueryFormDataPromise(resolve, reject) { + ret.xhr = jQuery.ajax({ + xhr() { + const xhr = new window.XMLHttpRequest(); + + xhr.upload.addEventListener('progress', function(evt) { + if (evt.lengthComputable) { + const percentComplete = evt.loaded / evt.total; + progress(percentComplete * 100); + } + }, false); + + xhr.upload.addEventListener('error', error, false); + + return xhr; + }, url: `${ baseURI }api/${ endpoint }${ query }`, headers: { 'X-User-Id': Meteor._localStorage.getItem(Accounts.USER_ID_KEY), @@ -96,6 +112,8 @@ export const APIClient = { }, }); }); + + return ret; }, v1: { From 2ecf7f395a264dfa0513791a0d8683682f48a00b Mon Sep 17 00:00:00 2001 From: Diego Sampaio Date: Mon, 16 Mar 2020 16:04:03 -0300 Subject: [PATCH 23/30] Bump version to 3.0.4 --- .docker/Dockerfile.rhel | 2 +- .github/history.json | 41 ++++++++++++++++++++++++++++++++++++++- HISTORY.md | 30 +++++++++++++++++++++++----- app/utils/rocketchat.info | 2 +- package.json | 2 +- 5 files changed, 68 insertions(+), 9 deletions(-) diff --git a/.docker/Dockerfile.rhel b/.docker/Dockerfile.rhel index 3edc448beea..d43a140a37d 100644 --- a/.docker/Dockerfile.rhel +++ b/.docker/Dockerfile.rhel @@ -1,6 +1,6 @@ FROM registry.access.redhat.com/rhscl/nodejs-8-rhel7 -ENV RC_VERSION 3.0.3 +ENV RC_VERSION 3.0.4 MAINTAINER buildmaster@rocket.chat diff --git a/.github/history.json b/.github/history.json index 44a7272e4ba..8d6cdcf14c9 100644 --- a/.github/history.json +++ b/.github/history.json @@ -39959,6 +39959,45 @@ ] } ] + }, + "3.0.4": { + "node_version": "12.14.0", + "npm_version": "6.13.4", + "mongo_versions": [ + "3.4", + "3.6", + "4.0" + ], + "pull_requests": [ + { + "pr": "16617", + "title": "[IMPROVE] Send files over REST API", + "userLogin": "ggazzo", + "milestone": "3.1.0", + "contributors": [ + "ggazzo", + "web-flow", + "sampaiodiego" + ] + }, + { + "pr": "16838", + "title": "[FIX] Integrations page pagination", + "userLogin": "sampaiodiego", + "milestone": "3.1.0", + "contributors": [ + "sampaiodiego" + ] + }, + { + "pr": "16699", + "title": "[FIX] TypeError when trying to load avatar of an invalid room.", + "userLogin": "pierre-lehnen-rc", + "contributors": [ + "pierre-lehnen-rc" + ] + } + ] } } -} +} \ No newline at end of file diff --git a/HISTORY.md b/HISTORY.md index 40f27d6c39d..291cd60288a 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,4 +1,27 @@ +# 3.0.4 +`2020-03-16 ยท 1 ๐Ÿš€ ยท 2 ๐Ÿ› ยท 3 ๐Ÿ‘ฉโ€๐Ÿ’ป๐Ÿ‘จโ€๐Ÿ’ป` + +### Engine versions +- Node: `12.14.0` +- NPM: `6.13.4` +- MongoDB: `3.4, 3.6, 4.0` + +### ๐Ÿš€ Improvements + +- Send files over REST API ([#16617](https://github.com/RocketChat/Rocket.Chat/pull/16617)) + +### ๐Ÿ› Bug fixes + +- Integrations page pagination ([#16838](https://github.com/RocketChat/Rocket.Chat/pull/16838)) +- TypeError when trying to load avatar of an invalid room. ([#16699](https://github.com/RocketChat/Rocket.Chat/pull/16699)) + +### ๐Ÿ‘ฉโ€๐Ÿ’ป๐Ÿ‘จโ€๐Ÿ’ป Core Team ๐Ÿค“ + +- [@ggazzo](https://github.com/ggazzo) +- [@pierre-lehnen-rc](https://github.com/pierre-lehnen-rc) +- [@sampaiodiego](https://github.com/sampaiodiego) + # 3.0.3 `2020-03-02 ยท 5 ๐Ÿ› ยท 5 ๐Ÿ‘ฉโ€๐Ÿ’ป๐Ÿ‘จโ€๐Ÿ’ป` @@ -24,7 +47,7 @@ - [@rodrigok](https://github.com/rodrigok) # 3.0.2 -`2020-02-21 ยท 4 ๐Ÿ› ยท 5 ๐Ÿ‘ฉโ€๐Ÿ’ป๐Ÿ‘จโ€๐Ÿ’ป` +`2020-02-21 ยท 3 ๐Ÿ› ยท 3 ๐Ÿ‘ฉโ€๐Ÿ’ป๐Ÿ‘จโ€๐Ÿ’ป` ### Engine versions - Node: `12.14.0` @@ -35,16 +58,13 @@ - ie11 support ([#16682](https://github.com/RocketChat/Rocket.Chat/pull/16682)) - Omnichannel Inquiry queues when removing chats ([#16603](https://github.com/RocketChat/Rocket.Chat/pull/16603)) -- users.info endpoint not handling the error if the user does not exist ([#16495](https://github.com/RocketChat/Rocket.Chat/pull/16495)) - Clear unread red line when the ESC key is pressed ([#16668](https://github.com/RocketChat/Rocket.Chat/pull/16668)) ### ๐Ÿ‘ฉโ€๐Ÿ’ป๐Ÿ‘จโ€๐Ÿ’ป Core Team ๐Ÿค“ -- [@MarcosSpessatto](https://github.com/MarcosSpessatto) - [@gabriellsh](https://github.com/gabriellsh) - [@ggazzo](https://github.com/ggazzo) - [@renatobecker](https://github.com/renatobecker) -- [@sampaiodiego](https://github.com/sampaiodiego) # 3.0.1 `2020-02-19 ยท 7 ๐Ÿ› ยท 4 ๐Ÿ‘ฉโ€๐Ÿ’ป๐Ÿ‘จโ€๐Ÿ’ป` @@ -6673,4 +6693,4 @@ - [@graywolf336](https://github.com/graywolf336) - [@marceloschmidt](https://github.com/marceloschmidt) - [@rodrigok](https://github.com/rodrigok) -- [@sampaiodiego](https://github.com/sampaiodiego) +- [@sampaiodiego](https://github.com/sampaiodiego) \ No newline at end of file diff --git a/app/utils/rocketchat.info b/app/utils/rocketchat.info index ad3aeee82e4..9b6d281d5f2 100644 --- a/app/utils/rocketchat.info +++ b/app/utils/rocketchat.info @@ -1,3 +1,3 @@ { - "version": "3.0.3" + "version": "3.0.4" } diff --git a/package.json b/package.json index b63dbf35dc2..aafcf6c41fe 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "Rocket.Chat", "description": "The Ultimate Open Source WebChat Platform", - "version": "3.0.3", + "version": "3.0.4", "author": { "name": "Rocket.Chat", "url": "https://rocket.chat/" From e3e542f09eb475c1590b4593aa4b5afb184179e1 Mon Sep 17 00:00:00 2001 From: Diego Sampaio Date: Tue, 24 Mar 2020 11:45:18 -0300 Subject: [PATCH 24/30] [FIX] Race conditions on/before login (#16989) --- app/authorization/client/startup.js | 10 +++++++++- app/ui-sidenav/client/userPresence.js | 3 +++ app/webdav/client/startup/sync.js | 7 ++++--- client/lib/userData.js | 2 +- 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/app/authorization/client/startup.js b/app/authorization/client/startup.js index 99c1f06e760..2edf696d285 100644 --- a/app/authorization/client/startup.js +++ b/app/authorization/client/startup.js @@ -1,4 +1,5 @@ import { Meteor } from 'meteor/meteor'; +import { Tracker } from 'meteor/tracker'; import { hasAtLeastOnePermission } from './hasPermission'; import { CachedCollectionManager } from '../../ui-cached-collection'; @@ -28,5 +29,12 @@ Meteor.startup(() => { }, removed: (role) => Roles.remove({ _id: role.name }), }; - rolesStreamer.on('roles', (role) => events[role.type](role)); + + Tracker.autorun((c) => { + if (!Meteor.userId()) { + return; + } + rolesStreamer.on('roles', (role) => events[role.type](role)); + c.stop(); + }); }); diff --git a/app/ui-sidenav/client/userPresence.js b/app/ui-sidenav/client/userPresence.js index f6ae3e82171..d20687e5392 100644 --- a/app/ui-sidenav/client/userPresence.js +++ b/app/ui-sidenav/client/userPresence.js @@ -89,6 +89,9 @@ Tracker.autorun(() => { }); Template.userPresence.onRendered(function() { + if (!this.data || !this.data.uid) { + return; + } data.set(this.firstNode, this.data); if (featureExists) { return observer.observe(this.firstNode); diff --git a/app/webdav/client/startup/sync.js b/app/webdav/client/startup/sync.js index 5873da9672d..c3547ee4bfe 100644 --- a/app/webdav/client/startup/sync.js +++ b/app/webdav/client/startup/sync.js @@ -11,9 +11,10 @@ const events = { }; Tracker.autorun(async () => { - if (Meteor.userId()) { - const { accounts } = await APIClient.v1.get('webdav.getMyAccounts'); - accounts.forEach((account) => WebdavAccounts.insert(account)); + if (!Meteor.userId()) { + return; } + const { accounts } = await APIClient.v1.get('webdav.getMyAccounts'); + accounts.forEach((account) => WebdavAccounts.insert(account)); Notifications.onUser('webdav', ({ type, account }) => events[type](account)); }); diff --git a/client/lib/userData.js b/client/lib/userData.js index 87c45c2d34a..6a3c5da44b8 100644 --- a/client/lib/userData.js +++ b/client/lib/userData.js @@ -9,7 +9,7 @@ export const isSyncReady = new ReactiveVar(false); function updateUser(userData) { const user = Users.findOne({ _id: userData._id }); - if (!user || userData._updatedAt > user._updatedAt.toISOString()) { + if (!user || !user._updatedAt || userData._updatedAt > user._updatedAt.toISOString()) { userData._updatedAt = new Date(userData._updatedAt); return Meteor.users.upsert({ _id: userData._id }, userData); } From 0d6ae884aba97aa6b44e172e924fb8711c7e1b0a Mon Sep 17 00:00:00 2001 From: Diego Sampaio Date: Tue, 24 Mar 2020 12:40:02 -0300 Subject: [PATCH 25/30] Bump version to 3.0.5 --- .docker/Dockerfile.rhel | 2 +- .github/history.json | 19 +++++++++++++++++++ HISTORY.md | 16 ++++++++++++++++ app/utils/rocketchat.info | 2 +- package.json | 2 +- 5 files changed, 38 insertions(+), 3 deletions(-) diff --git a/.docker/Dockerfile.rhel b/.docker/Dockerfile.rhel index d43a140a37d..dcad419af15 100644 --- a/.docker/Dockerfile.rhel +++ b/.docker/Dockerfile.rhel @@ -1,6 +1,6 @@ FROM registry.access.redhat.com/rhscl/nodejs-8-rhel7 -ENV RC_VERSION 3.0.4 +ENV RC_VERSION 3.0.5 MAINTAINER buildmaster@rocket.chat diff --git a/.github/history.json b/.github/history.json index 8d6cdcf14c9..c630065ab11 100644 --- a/.github/history.json +++ b/.github/history.json @@ -39998,6 +39998,25 @@ ] } ] + }, + "3.0.5": { + "node_version": "12.14.0", + "npm_version": "6.13.4", + "mongo_versions": [ + "3.4", + "3.6", + "4.0" + ], + "pull_requests": [ + { + "pr": "16989", + "title": "[FIX] Race conditions on/before login", + "userLogin": "sampaiodiego", + "contributors": [ + "sampaiodiego" + ] + } + ] } } } \ No newline at end of file diff --git a/HISTORY.md b/HISTORY.md index 291cd60288a..3e5e2c56236 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,4 +1,20 @@ +# 3.0.5 +`2020-03-24 ยท 1 ๐Ÿ› ยท 1 ๐Ÿ‘ฉโ€๐Ÿ’ป๐Ÿ‘จโ€๐Ÿ’ป` + +### Engine versions +- Node: `12.14.0` +- NPM: `6.13.4` +- MongoDB: `3.4, 3.6, 4.0` + +### ๐Ÿ› Bug fixes + +- Race conditions on/before login ([#16989](https://github.com/RocketChat/Rocket.Chat/pull/16989)) + +### ๐Ÿ‘ฉโ€๐Ÿ’ป๐Ÿ‘จโ€๐Ÿ’ป Core Team ๐Ÿค“ + +- [@sampaiodiego](https://github.com/sampaiodiego) + # 3.0.4 `2020-03-16 ยท 1 ๐Ÿš€ ยท 2 ๐Ÿ› ยท 3 ๐Ÿ‘ฉโ€๐Ÿ’ป๐Ÿ‘จโ€๐Ÿ’ป` diff --git a/app/utils/rocketchat.info b/app/utils/rocketchat.info index 9b6d281d5f2..67213e864fd 100644 --- a/app/utils/rocketchat.info +++ b/app/utils/rocketchat.info @@ -1,3 +1,3 @@ { - "version": "3.0.4" + "version": "3.0.5" } diff --git a/package.json b/package.json index aafcf6c41fe..ccfed4889e8 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "Rocket.Chat", "description": "The Ultimate Open Source WebChat Platform", - "version": "3.0.4", + "version": "3.0.5", "author": { "name": "Rocket.Chat", "url": "https://rocket.chat/" From 0bcf99772c1232bcee60e63d307bce3980b09cdb Mon Sep 17 00:00:00 2001 From: Renato Becker Date: Thu, 19 Mar 2020 14:09:50 -0300 Subject: [PATCH 26/30] [FIX] Keeps the agent in the room after accepting a new Omnichannel request (#16787) --- app/livechat/client/views/app/livechatReadOnly.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/livechat/client/views/app/livechatReadOnly.js b/app/livechat/client/views/app/livechatReadOnly.js index da599cb65cb..9ea5baf1b9c 100644 --- a/app/livechat/client/views/app/livechatReadOnly.js +++ b/app/livechat/client/views/app/livechatReadOnly.js @@ -12,7 +12,7 @@ import { inquiryDataStream } from '../../lib/stream/inquiry'; Template.livechatReadOnly.helpers({ inquiryOpen() { const inquiry = Template.instance().inquiry.get(); - return (inquiry && inquiry.status === 'queued') || FlowRouter.go('/home'); + return inquiry && inquiry.status === 'queued'; }, roomOpen() { @@ -49,8 +49,11 @@ Template.livechatReadOnly.onCreated(function() { this.routingConfig = new ReactiveVar({}); this.preparing = new ReactiveVar(true); - this.updateInquiry = (inquiry) => { + this.updateInquiry = async (inquiry) => { this.inquiry.set(inquiry); + if (!await call('canAccessRoom', inquiry.rid, Meteor.userId())) { + FlowRouter.go('/home'); + } }; Meteor.call('livechat:getRoutingConfig', (err, config) => { From dd067bac8cc71da1fac75eb7733666e1b2b9ea57 Mon Sep 17 00:00:00 2001 From: Renato Becker Date: Wed, 25 Mar 2020 09:05:44 -0300 Subject: [PATCH 27/30] [Regression] Replace the Omnichannel queue model observe with Stream (#16999) * Replace LivechatInquiry observe by stream. * Unify stream. * Add hasPermission method. * Add missing importers. * Revert package-lock file. * Improve the codebase. * Add return statement. * Fix remove listeners that were missing. * Removed unnecessary imports. * Remove unnecessary function parameters. --- app/livechat/client/lib/stream/inquiry.js | 4 +- .../client/lib/stream/queueManager.js | 27 ++++---- .../client/views/app/livechatReadOnly.js | 9 +-- app/livechat/lib/stream/constants.js | 1 - app/livechat/server/index.js | 1 - app/livechat/server/lib/stream/inquiry.js | 34 ---------- .../server/lib/stream/queueManager.js | 64 ++++++++++--------- 7 files changed, 53 insertions(+), 87 deletions(-) delete mode 100644 app/livechat/server/lib/stream/inquiry.js diff --git a/app/livechat/client/lib/stream/inquiry.js b/app/livechat/client/lib/stream/inquiry.js index 333f67b3684..03a15c20464 100644 --- a/app/livechat/client/lib/stream/inquiry.js +++ b/app/livechat/client/lib/stream/inquiry.js @@ -1,5 +1,5 @@ import { Meteor } from 'meteor/meteor'; -import { LIVECHAT_INQUIRY_DATA_STREAM_OBSERVER } from '../../../lib/stream/constants'; +import { LIVECHAT_INQUIRY_QUEUE_STREAM_OBSERVER } from '../../../lib/stream/constants'; -export const inquiryDataStream = new Meteor.Streamer(LIVECHAT_INQUIRY_DATA_STREAM_OBSERVER); +export const inquiryDataStream = new Meteor.Streamer(LIVECHAT_INQUIRY_QUEUE_STREAM_OBSERVER); diff --git a/app/livechat/client/lib/stream/queueManager.js b/app/livechat/client/lib/stream/queueManager.js index 5f58fdc5637..497a961c55f 100644 --- a/app/livechat/client/lib/stream/queueManager.js +++ b/app/livechat/client/lib/stream/queueManager.js @@ -1,31 +1,29 @@ -import { Meteor } from 'meteor/meteor'; - import { APIClient } from '../../../../utils/client'; import { getLivechatInquiryCollection } from '../../collections/LivechatInquiry'; -import { LIVECHAT_INQUIRY_QUEUE_STREAM_OBSERVER } from '../../../lib/stream/constants'; +import { inquiryDataStream } from './inquiry'; import { hasRole } from '../../../../authorization/client'; -const livechatQueueStreamer = new Meteor.Streamer('livechat-queue-stream'); let agentDepartments = []; +const collection = getLivechatInquiryCollection(); const events = { - added: (inquiry, collection) => { + added: (inquiry) => { delete inquiry.type; collection.insert(inquiry); }, - changed: (inquiry, collection) => { + changed: (inquiry) => { if (inquiry.status !== 'queued' || (inquiry.department && !agentDepartments.includes(inquiry.department))) { return collection.remove(inquiry._id); } delete inquiry.type; collection.upsert({ _id: inquiry._id }, inquiry); }, - removed: (inquiry, collection) => collection.remove(inquiry._id), + removed: (inquiry) => collection.remove(inquiry._id), }; -const appendListenerToDepartment = (departmentId, collection) => livechatQueueStreamer.on(`${ LIVECHAT_INQUIRY_QUEUE_STREAM_OBSERVER }/${ departmentId }`, (inquiry) => events[inquiry.type](inquiry, collection)); - -const removeListenerOfDepartment = (departmentId) => livechatQueueStreamer.removeListener(`${ LIVECHAT_INQUIRY_QUEUE_STREAM_OBSERVER }/${ departmentId }`); +const updateCollection = (inquiry) => { events[inquiry.type](inquiry); }; +const appendListenerToDepartment = (departmentId) => inquiryDataStream.on(`department/${ departmentId }`, updateCollection); +const removeListenerOfDepartment = (departmentId) => inquiryDataStream.removeListener(`department/${ departmentId }`, updateCollection); const getInquiriesFromAPI = async (url) => { const { inquiries } = await APIClient.v1.get(url); @@ -33,7 +31,6 @@ const getInquiriesFromAPI = async (url) => { }; const updateInquiries = async (inquiries) => { - const collection = getLivechatInquiryCollection(); (inquiries || []).forEach((inquiry) => collection.upsert({ _id: inquiry._id }, inquiry)); }; @@ -43,9 +40,8 @@ const getAgentsDepartments = async (userId) => { }; const addListenerForeachDepartment = async (userId, departments) => { - const collection = getLivechatInquiryCollection(); if (departments && Array.isArray(departments) && departments.length) { - departments.forEach((department) => appendListenerToDepartment(department, collection)); + departments.forEach((department) => appendListenerToDepartment(department)); } }; @@ -54,11 +50,10 @@ const removeDepartmentsListeners = (departments) => { }; const removeGlobalListener = () => { - livechatQueueStreamer.removeListener(LIVECHAT_INQUIRY_QUEUE_STREAM_OBSERVER); + inquiryDataStream.removeListener('public', updateCollection); }; export const initializeLivechatInquiryStream = async (userId) => { - const collection = getLivechatInquiryCollection(); collection.remove({}); if (agentDepartments.length) { removeDepartmentsListeners(agentDepartments); @@ -68,6 +63,6 @@ export const initializeLivechatInquiryStream = async (userId) => { agentDepartments = (await getAgentsDepartments(userId)).map((department) => department.departmentId); await addListenerForeachDepartment(userId, agentDepartments); if (agentDepartments.length === 0 || hasRole(userId, 'livechat-manager')) { - livechatQueueStreamer.on(LIVECHAT_INQUIRY_QUEUE_STREAM_OBSERVER, (inquiry) => events[inquiry.type](inquiry, collection)); + inquiryDataStream.on('public', updateCollection); } }; diff --git a/app/livechat/client/views/app/livechatReadOnly.js b/app/livechat/client/views/app/livechatReadOnly.js index 9ea5baf1b9c..ef516a7ac88 100644 --- a/app/livechat/client/views/app/livechatReadOnly.js +++ b/app/livechat/client/views/app/livechatReadOnly.js @@ -49,11 +49,12 @@ Template.livechatReadOnly.onCreated(function() { this.routingConfig = new ReactiveVar({}); this.preparing = new ReactiveVar(true); - this.updateInquiry = async (inquiry) => { - this.inquiry.set(inquiry); - if (!await call('canAccessRoom', inquiry.rid, Meteor.userId())) { - FlowRouter.go('/home'); + this.updateInquiry = async ({ clientAction, ...inquiry }) => { + if (clientAction === 'removed' || !await call('canAccessRoom', inquiry.rid, Meteor.userId())) { + return FlowRouter.go('/home'); } + + this.inquiry.set(inquiry); }; Meteor.call('livechat:getRoutingConfig', (err, config) => { diff --git a/app/livechat/lib/stream/constants.js b/app/livechat/lib/stream/constants.js index d9c2ec1f0dd..17c85f566f4 100644 --- a/app/livechat/lib/stream/constants.js +++ b/app/livechat/lib/stream/constants.js @@ -1,2 +1 @@ export const LIVECHAT_INQUIRY_QUEUE_STREAM_OBSERVER = 'livechat-inquiry-queue-observer'; -export const LIVECHAT_INQUIRY_DATA_STREAM_OBSERVER = 'livechat-inquiry-data-observer'; diff --git a/app/livechat/server/index.js b/app/livechat/server/index.js index eb3ccee0fec..541cfb16ab4 100644 --- a/app/livechat/server/index.js +++ b/app/livechat/server/index.js @@ -76,7 +76,6 @@ import './lib/routing/External'; import './lib/routing/ManualSelection'; import './lib/routing/AutoSelection'; import './lib/stream/departmentAgents'; -import './lib/stream/inquiry'; import './lib/stream/queueManager'; import './sendMessageBySMS'; import './unclosedLivechats'; diff --git a/app/livechat/server/lib/stream/inquiry.js b/app/livechat/server/lib/stream/inquiry.js deleted file mode 100644 index 5328d07dbcc..00000000000 --- a/app/livechat/server/lib/stream/inquiry.js +++ /dev/null @@ -1,34 +0,0 @@ -import { Meteor } from 'meteor/meteor'; - -import { LivechatInquiry } from '../../../../models/server'; -import { LIVECHAT_INQUIRY_DATA_STREAM_OBSERVER } from '../../../lib/stream/constants'; -import { hasPermission } from '../../../../authorization/server'; - -export const inquiryDataStream = new Meteor.Streamer(LIVECHAT_INQUIRY_DATA_STREAM_OBSERVER); - -inquiryDataStream.allowWrite('none'); - -inquiryDataStream.allowRead(function() { - return this.userId ? hasPermission(this.userId, 'view-l-room') : false; -}); - -const emitInquiryDataEvent = (id, data) => { - if (!data) { - return; - } - - inquiryDataStream.emit(id, data); -}; - -LivechatInquiry.on('change', ({ clientAction, id }) => { - switch (clientAction) { - case 'inserted': - case 'updated': - emitInquiryDataEvent(id, LivechatInquiry.findOneById(id)); - break; - - case 'removed': - emitInquiryDataEvent(id, { _id: id }); - break; - } -}); diff --git a/app/livechat/server/lib/stream/queueManager.js b/app/livechat/server/lib/stream/queueManager.js index 2548ac711ac..dd1a088fec5 100644 --- a/app/livechat/server/lib/stream/queueManager.js +++ b/app/livechat/server/lib/stream/queueManager.js @@ -4,38 +4,44 @@ import { hasPermission } from '../../../../authorization/server'; import { LivechatInquiry } from '../../../../models/server'; import { LIVECHAT_INQUIRY_QUEUE_STREAM_OBSERVER } from '../../../lib/stream/constants'; -const livechatQueueStreamer = new Meteor.Streamer('livechat-queue-stream'); -livechatQueueStreamer.allowWrite('none'); -livechatQueueStreamer.allowRead(function() { +const queueDataStreamer = new Meteor.Streamer(LIVECHAT_INQUIRY_QUEUE_STREAM_OBSERVER); +queueDataStreamer.allowWrite('none'); +queueDataStreamer.allowRead(function() { return this.userId ? hasPermission(this.userId, 'view-l-room') : false; }); -const emitEvent = (event, data) => livechatQueueStreamer.emit(event, data); +const emitQueueDataEvent = (event, data) => queueDataStreamer.emit(event, data); const mountDataToEmit = (type, data) => ({ type, ...data }); -LivechatInquiry.find({}).observeChanges({ - added(_id, record) { - if (record && record.department) { - return emitEvent(`${ LIVECHAT_INQUIRY_QUEUE_STREAM_OBSERVER }/${ record.department }`, mountDataToEmit('added', { ...record, _id })); - } - emitEvent(LIVECHAT_INQUIRY_QUEUE_STREAM_OBSERVER, mountDataToEmit('added', { ...record, _id })); - }, - changed(_id, record) { - const isUpdatingDepartment = record && record.department; - const inquiry = LivechatInquiry.findOneById(_id); - if (inquiry && !inquiry.department) { - return emitEvent(LIVECHAT_INQUIRY_QUEUE_STREAM_OBSERVER, mountDataToEmit('changed', inquiry)); - } - if (isUpdatingDepartment) { - emitEvent(LIVECHAT_INQUIRY_QUEUE_STREAM_OBSERVER, mountDataToEmit('changed', inquiry)); - } - return emitEvent(`${ LIVECHAT_INQUIRY_QUEUE_STREAM_OBSERVER }/${ inquiry.department }`, mountDataToEmit('changed', inquiry)); - }, - removed(_id) { - const inquiry = LivechatInquiry.trashFindOneById(_id); - if (inquiry && inquiry.department) { - return emitEvent(`${ LIVECHAT_INQUIRY_QUEUE_STREAM_OBSERVER }/${ inquiry.department }`, mountDataToEmit('removed', { _id })); - } - emitEvent(LIVECHAT_INQUIRY_QUEUE_STREAM_OBSERVER, mountDataToEmit('removed', { _id })); - }, +LivechatInquiry.on('change', ({ clientAction, id: _id, data: record }) => { + switch (clientAction) { + case 'inserted': + emitQueueDataEvent(_id, { ...record, clientAction }); + if (record && record.department) { + return emitQueueDataEvent(`department/${ record.department }`, mountDataToEmit('added', record)); + } + emitQueueDataEvent('public', mountDataToEmit('added', record)); + break; + case 'updated': + const isUpdatingDepartment = record && record.department; + const updatedRecord = LivechatInquiry.findOneById(_id); + emitQueueDataEvent(_id, { ...updatedRecord, clientAction }); + if (updatedRecord && !updatedRecord.department) { + return emitQueueDataEvent('public', mountDataToEmit('changed', updatedRecord)); + } + if (isUpdatingDepartment) { + emitQueueDataEvent('public', mountDataToEmit('changed', updatedRecord)); + } + emitQueueDataEvent(`department/${ updatedRecord.department }`, mountDataToEmit('changed', updatedRecord)); + break; + + case 'removed': + const removedRecord = LivechatInquiry.trashFindOneById(_id); + emitQueueDataEvent(_id, { _id, clientAction }); + if (removedRecord && removedRecord.department) { + return emitQueueDataEvent(`department/${ removedRecord.department }`, mountDataToEmit('removed', { _id })); + } + emitQueueDataEvent('public', mountDataToEmit('removed', { _id })); + break; + } }); From 972277df8d6b82c3f9912620fe032a9c3cb95e71 Mon Sep 17 00:00:00 2001 From: Diego Sampaio Date: Wed, 25 Mar 2020 11:33:07 -0300 Subject: [PATCH 28/30] Bump version to 3.0.6 --- .docker/Dockerfile.rhel | 2 +- .github/history.json | 30 ++++++++++++++++++++++++++++++ HISTORY.md | 23 +++++++++++++++++++++++ app/utils/rocketchat.info | 2 +- package.json | 2 +- 5 files changed, 56 insertions(+), 3 deletions(-) diff --git a/.docker/Dockerfile.rhel b/.docker/Dockerfile.rhel index dcad419af15..763a2c8f764 100644 --- a/.docker/Dockerfile.rhel +++ b/.docker/Dockerfile.rhel @@ -1,6 +1,6 @@ FROM registry.access.redhat.com/rhscl/nodejs-8-rhel7 -ENV RC_VERSION 3.0.5 +ENV RC_VERSION 3.0.6 MAINTAINER buildmaster@rocket.chat diff --git a/.github/history.json b/.github/history.json index c630065ab11..26e1a6902ba 100644 --- a/.github/history.json +++ b/.github/history.json @@ -40017,6 +40017,36 @@ ] } ] + }, + "3.0.6": { + "node_version": "12.14.0", + "npm_version": "6.13.4", + "mongo_versions": [ + "3.4", + "3.6", + "4.0" + ], + "pull_requests": [ + { + "pr": "16999", + "title": "Regression: Replace the Omnichannel queue model observe with Stream", + "userLogin": "renatobecker", + "milestone": "3.1.0", + "contributors": [ + "renatobecker" + ] + }, + { + "pr": "16787", + "title": "[FIX] Keeps the agent in the room after accepting a new Omnichannel request", + "userLogin": "renatobecker", + "milestone": "3.1.0", + "contributors": [ + "renatobecker", + "web-flow" + ] + } + ] } } } \ No newline at end of file diff --git a/HISTORY.md b/HISTORY.md index 3e5e2c56236..30e23dfddb6 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,4 +1,27 @@ +# 3.0.6 +`2020-03-25 ยท 1 ๐Ÿ› ยท 1 ๐Ÿ” ยท 1 ๐Ÿ‘ฉโ€๐Ÿ’ป๐Ÿ‘จโ€๐Ÿ’ป` + +### Engine versions +- Node: `12.14.0` +- NPM: `6.13.4` +- MongoDB: `3.4, 3.6, 4.0` + +### ๐Ÿ› Bug fixes + +- Keeps the agent in the room after accepting a new Omnichannel request ([#16787](https://github.com/RocketChat/Rocket.Chat/pull/16787)) + +
+๐Ÿ” Minor changes + +- Regression: Replace the Omnichannel queue model observe with Stream ([#16999](https://github.com/RocketChat/Rocket.Chat/pull/16999)) + +
+ +### ๐Ÿ‘ฉโ€๐Ÿ’ป๐Ÿ‘จโ€๐Ÿ’ป Core Team ๐Ÿค“ + +- [@renatobecker](https://github.com/renatobecker) + # 3.0.5 `2020-03-24 ยท 1 ๐Ÿ› ยท 1 ๐Ÿ‘ฉโ€๐Ÿ’ป๐Ÿ‘จโ€๐Ÿ’ป` diff --git a/app/utils/rocketchat.info b/app/utils/rocketchat.info index 67213e864fd..e0039c670d9 100644 --- a/app/utils/rocketchat.info +++ b/app/utils/rocketchat.info @@ -1,3 +1,3 @@ { - "version": "3.0.5" + "version": "3.0.6" } diff --git a/package.json b/package.json index ccfed4889e8..e986faf0608 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "Rocket.Chat", "description": "The Ultimate Open Source WebChat Platform", - "version": "3.0.5", + "version": "3.0.6", "author": { "name": "Rocket.Chat", "url": "https://rocket.chat/" From dfa8fd3c9b0933bc875b44b53b43f70f45731fac Mon Sep 17 00:00:00 2001 From: Renato Becker Date: Wed, 25 Mar 2020 19:26:46 -0300 Subject: [PATCH 29/30] Regression: Remove deprecated Omnichannel setting used to fetch the queue data through subscription (#17017) * Removed deprecated omnichannel setting, * Remove unnecessary setting creation. * Add method to clear the inquiry collection on client-side before set up the stream. --- .../client/collections/LivechatInquiry.js | 10 +--------- app/livechat/client/lib/stream/queueManager.js | 17 +++++++++-------- app/livechat/client/views/sideNav/livechat.js | 11 ++++------- app/livechat/lib/LivechatRoomType.js | 8 ++++---- app/livechat/server/config.js | 9 --------- server/startup/migrations/v178.js | 14 ++++++++++++++ 6 files changed, 32 insertions(+), 37 deletions(-) create mode 100644 server/startup/migrations/v178.js diff --git a/app/livechat/client/collections/LivechatInquiry.js b/app/livechat/client/collections/LivechatInquiry.js index 2b1bd51bbf2..c43a9cb31ca 100644 --- a/app/livechat/client/collections/LivechatInquiry.js +++ b/app/livechat/client/collections/LivechatInquiry.js @@ -1,11 +1,3 @@ import { Mongo } from 'meteor/mongo'; -import { settings } from '../../../settings/client'; - -let collection; -export const getLivechatInquiryCollection = () => { - if (!collection) { - collection = new Mongo.Collection(settings.get('Livechat_enable_inquiry_fetch_by_stream') ? null : 'rocketchat_livechat_inquiry'); - } - return collection; -}; +export const LivechatInquiry = new Mongo.Collection(null); diff --git a/app/livechat/client/lib/stream/queueManager.js b/app/livechat/client/lib/stream/queueManager.js index 497a961c55f..efe6727d275 100644 --- a/app/livechat/client/lib/stream/queueManager.js +++ b/app/livechat/client/lib/stream/queueManager.js @@ -1,24 +1,23 @@ import { APIClient } from '../../../../utils/client'; -import { getLivechatInquiryCollection } from '../../collections/LivechatInquiry'; +import { LivechatInquiry } from '../../collections/LivechatInquiry'; import { inquiryDataStream } from './inquiry'; import { hasRole } from '../../../../authorization/client'; let agentDepartments = []; -const collection = getLivechatInquiryCollection(); const events = { added: (inquiry) => { delete inquiry.type; - collection.insert(inquiry); + LivechatInquiry.insert(inquiry); }, changed: (inquiry) => { if (inquiry.status !== 'queued' || (inquiry.department && !agentDepartments.includes(inquiry.department))) { - return collection.remove(inquiry._id); + return LivechatInquiry.remove(inquiry._id); } delete inquiry.type; - collection.upsert({ _id: inquiry._id }, inquiry); + LivechatInquiry.upsert({ _id: inquiry._id }, inquiry); }, - removed: (inquiry) => collection.remove(inquiry._id), + removed: (inquiry) => LivechatInquiry.remove(inquiry._id), }; const updateCollection = (inquiry) => { events[inquiry.type](inquiry); }; @@ -31,7 +30,7 @@ const getInquiriesFromAPI = async (url) => { }; const updateInquiries = async (inquiries) => { - (inquiries || []).forEach((inquiry) => collection.upsert({ _id: inquiry._id }, inquiry)); + (inquiries || []).forEach((inquiry) => LivechatInquiry.upsert({ _id: inquiry._id }, inquiry)); }; const getAgentsDepartments = async (userId) => { @@ -54,12 +53,14 @@ const removeGlobalListener = () => { }; export const initializeLivechatInquiryStream = async (userId) => { - collection.remove({}); + LivechatInquiry.remove({}); + if (agentDepartments.length) { removeDepartmentsListeners(agentDepartments); } removeGlobalListener(); await updateInquiries(await getInquiriesFromAPI('livechat/inquiries.queued?sort={"ts": 1}')); + agentDepartments = (await getAgentsDepartments(userId)).map((department) => department.departmentId); await addListenerForeachDepartment(userId, agentDepartments); if (agentDepartments.length === 0 || hasRole(userId, 'livechat-manager')) { diff --git a/app/livechat/client/views/sideNav/livechat.js b/app/livechat/client/views/sideNav/livechat.js index d3faba2b309..cf53b572663 100644 --- a/app/livechat/client/views/sideNav/livechat.js +++ b/app/livechat/client/views/sideNav/livechat.js @@ -9,7 +9,7 @@ import { KonchatNotification } from '../../../../ui'; import { settings } from '../../../../settings'; import { hasPermission } from '../../../../authorization'; import { t, handleError, getUserPreference } from '../../../../utils'; -import { getLivechatInquiryCollection } from '../../collections/LivechatInquiry'; +import { LivechatInquiry } from '../../collections/LivechatInquiry'; import { Notifications } from '../../../../notifications/client'; import { initializeLivechatInquiryStream } from '../../lib/stream/queueManager'; @@ -50,7 +50,7 @@ Template.livechat.helpers({ }, inquiries() { - const inqs = getLivechatInquiryCollection().find({ + const inqs = LivechatInquiry.find({ status: 'queued', }, { sort: { @@ -131,11 +131,8 @@ Template.livechat.onCreated(function() { this.statusLivechat.set(); } }); - if (!settings.get('Livechat_enable_inquiry_fetch_by_stream')) { - this.subscribe('livechat:inquiry'); - } else { - initializeLivechatInquiryStream(Meteor.userId()); - } + + initializeLivechatInquiryStream(Meteor.userId()); this.updateAgentDepartments = () => initializeLivechatInquiryStream(Meteor.userId()); this.autorun(() => this.inquiriesLimit.set(settings.get('Livechat_guest_pool_max_number_incoming_livechats_displayed'))); diff --git a/app/livechat/lib/LivechatRoomType.js b/app/livechat/lib/LivechatRoomType.js index c6824041b39..8e6c498cfbd 100644 --- a/app/livechat/lib/LivechatRoomType.js +++ b/app/livechat/lib/LivechatRoomType.js @@ -8,9 +8,9 @@ import { openRoom } from '../../ui-utils'; import { RoomSettingsEnum, UiTextContext, RoomTypeRouteConfig, RoomTypeConfig } from '../../utils'; import { getAvatarURL } from '../../utils/lib/getAvatarURL'; -let getLivechatInquiryCollection; +let LivechatInquiry; if (Meteor.isClient) { - ({ getLivechatInquiryCollection } = require('../client/collections/LivechatInquiry')); + ({ LivechatInquiry } = require('../client/collections/LivechatInquiry')); } class LivechatRoomRoute extends RoomTypeRouteConfig { @@ -68,7 +68,7 @@ export default class LivechatRoomType extends RoomTypeConfig { if (room) { return room.v && room.v.status; } - const inquiry = getLivechatInquiryCollection().findOne({ rid }); + const inquiry = LivechatInquiry.findOne({ rid }); return inquiry && inquiry.v && inquiry.v.status; } @@ -98,7 +98,7 @@ export default class LivechatRoomType extends RoomTypeConfig { return true; } - const inquiry = getLivechatInquiryCollection().findOne({ rid }, { fields: { status: 1 } }); + const inquiry = LivechatInquiry.findOne({ rid }, { fields: { status: 1 } }); if (inquiry && inquiry.status === 'queued') { return true; } diff --git a/app/livechat/server/config.js b/app/livechat/server/config.js index 5ab52d806fe..3df2482685d 100644 --- a/app/livechat/server/config.js +++ b/app/livechat/server/config.js @@ -487,13 +487,4 @@ Meteor.startup(function() { i18nLabel: 'How_long_to_wait_to_consider_visitor_abandonment', i18nDescription: 'Time_in_seconds', }); - - settings.add('Livechat_enable_inquiry_fetch_by_stream', true, { - type: 'boolean', - group: 'Livechat', - section: 'Routing', - public: true, - i18nLabel: 'Enable_inquiry_fetch_by_stream', - enableQuery: { _id: 'Livechat_Routing_Method', value: 'Manual_Selection' }, - }); }); diff --git a/server/startup/migrations/v178.js b/server/startup/migrations/v178.js new file mode 100644 index 00000000000..77a38e3eb50 --- /dev/null +++ b/server/startup/migrations/v178.js @@ -0,0 +1,14 @@ +import { + Migrations, +} from '../../../app/migrations'; +import { + Settings, +} from '../../../app/models'; + + +Migrations.add({ + version: 178, + up() { + Settings.remove({ _id: 'Livechat_enable_inquiry_fetch_by_stream' }); + }, +}); From 5e4bd0739af1ac10f0d86a14db655fe33af2f090 Mon Sep 17 00:00:00 2001 From: Diego Sampaio Date: Wed, 25 Mar 2020 19:43:41 -0300 Subject: [PATCH 30/30] Bump version to 3.0.7 --- .docker/Dockerfile.rhel | 2 +- .github/history.json | 20 ++++++++++++++++++++ HISTORY.md | 19 +++++++++++++++++++ app/utils/rocketchat.info | 2 +- package.json | 2 +- 5 files changed, 42 insertions(+), 3 deletions(-) diff --git a/.docker/Dockerfile.rhel b/.docker/Dockerfile.rhel index 763a2c8f764..6da776c4700 100644 --- a/.docker/Dockerfile.rhel +++ b/.docker/Dockerfile.rhel @@ -1,6 +1,6 @@ FROM registry.access.redhat.com/rhscl/nodejs-8-rhel7 -ENV RC_VERSION 3.0.6 +ENV RC_VERSION 3.0.7 MAINTAINER buildmaster@rocket.chat diff --git a/.github/history.json b/.github/history.json index 26e1a6902ba..8352e9effef 100644 --- a/.github/history.json +++ b/.github/history.json @@ -40047,6 +40047,26 @@ ] } ] + }, + "3.0.7": { + "node_version": "12.14.0", + "npm_version": "6.13.4", + "mongo_versions": [ + "3.4", + "3.6", + "4.0" + ], + "pull_requests": [ + { + "pr": "17017", + "title": "Regression: Remove deprecated Omnichannel setting used to fetch the queue data through subscription ", + "userLogin": "renatobecker", + "milestone": "3.1.0", + "contributors": [ + "renatobecker" + ] + } + ] } } } \ No newline at end of file diff --git a/HISTORY.md b/HISTORY.md index 30e23dfddb6..e5eea1c8a5c 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,4 +1,23 @@ +# 3.0.7 +`2020-03-25 ยท 1 ๐Ÿ” ยท 1 ๐Ÿ‘ฉโ€๐Ÿ’ป๐Ÿ‘จโ€๐Ÿ’ป` + +### Engine versions +- Node: `12.14.0` +- NPM: `6.13.4` +- MongoDB: `3.4, 3.6, 4.0` + +
+๐Ÿ” Minor changes + +- Regression: Remove deprecated Omnichannel setting used to fetch the queue data through subscription ([#17017](https://github.com/RocketChat/Rocket.Chat/pull/17017)) + +
+ +### ๐Ÿ‘ฉโ€๐Ÿ’ป๐Ÿ‘จโ€๐Ÿ’ป Core Team ๐Ÿค“ + +- [@renatobecker](https://github.com/renatobecker) + # 3.0.6 `2020-03-25 ยท 1 ๐Ÿ› ยท 1 ๐Ÿ” ยท 1 ๐Ÿ‘ฉโ€๐Ÿ’ป๐Ÿ‘จโ€๐Ÿ’ป` diff --git a/app/utils/rocketchat.info b/app/utils/rocketchat.info index e0039c670d9..824c3e9bcca 100644 --- a/app/utils/rocketchat.info +++ b/app/utils/rocketchat.info @@ -1,3 +1,3 @@ { - "version": "3.0.6" + "version": "3.0.7" } diff --git a/package.json b/package.json index e986faf0608..6363e22d437 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "Rocket.Chat", "description": "The Ultimate Open Source WebChat Platform", - "version": "3.0.6", + "version": "3.0.7", "author": { "name": "Rocket.Chat", "url": "https://rocket.chat/"