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 01/11] [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 450e211e54c0..7c97106bfbc0 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 02/11] [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 c568fa9293a5..0506b21e1697 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 0db8901b9594..ffbf40c1dcce 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 03/11] [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 85924d77d27f..2f8a7df23e02 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 1db80c13b11e..031042ff2f04 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 b5a9c9d36c46..c66fe0276c73 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 42253997a60b..e41ea15116d9 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 594927ebca19..6b927743cac4 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 04/11] 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 3edc448beeaa..d43a140a37d2 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 44a7272e4ba8..8d6cdcf14c98 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 40f27d6c39d5..291cd60288a4 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 ad3aeee82e4b..9b6d281d5f25 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 b63dbf35dc2f..aafcf6c41fec 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 05/11] [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 99c1f06e760d..2edf696d2856 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 f6ae3e82171a..d20687e53922 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 5873da9672d1..c3547ee4bfe4 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 87c45c2d34ac..6a3c5da44b84 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 06/11] 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 d43a140a37d2..dcad419af158 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 8d6cdcf14c98..c630065ab111 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 291cd60288a4..3e5e2c562365 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 9b6d281d5f25..67213e864fd0 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 aafcf6c41fec..ccfed4889e8f 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 07/11] [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 da599cb65cb0..9ea5baf1b9c5 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 08/11] [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 333f67b3684a..03a15c20464f 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 5f58fdc56376..497a961c55f7 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 9ea5baf1b9c5..ef516a7ac885 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 d9c2ec1f0dd9..17c85f566f44 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 eb3ccee0feca..541cfb16ab4c 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 5328d07dbcca..000000000000 --- 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 2548ac711ac4..dd1a088fec57 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 09/11] 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 dcad419af158..763a2c8f764c 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 c630065ab111..26e1a6902ba6 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 3e5e2c562365..30e23dfddb68 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 67213e864fd0..e0039c670d9c 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 ccfed4889e8f..e986faf06086 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 10/11] 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 2b1bd51bbf2a..c43a9cb31ca5 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 497a961c55f7..efe6727d2756 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 d3faba2b3092..cf53b5726636 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 c6824041b396..8e6c498cfbd5 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 5ab52d806fe6..3df2482685dc 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 000000000000..77a38e3eb50d --- /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 11/11] 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 763a2c8f764c..6da776c4700f 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 26e1a6902ba6..8352e9effef3 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 30e23dfddb68..e5eea1c8a5c0 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 e0039c670d9c..824c3e9bcca4 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 e986faf06086..6363e22d4376 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/"