diff --git a/.docker/Dockerfile.rhel b/.docker/Dockerfile.rhel index 18c9bbe06698..de16afd2a318 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.6.2 +ENV RC_VERSION 3.6.3 MAINTAINER buildmaster@rocket.chat diff --git a/.github/history.json b/.github/history.json index 42943629a467..b3f28dc65772 100644 --- a/.github/history.json +++ b/.github/history.json @@ -49343,6 +49343,64 @@ ] } ] + }, + "3.6.3": { + "node_version": "12.16.1", + "npm_version": "6.14.0", + "apps_engine_version": "1.17.0", + "mongo_versions": [ + "3.4", + "3.6", + "4.0" + ], + "pull_requests": [ + { + "pr": "19020", + "title": "Obey to settings properties", + "userLogin": "sampaiodiego", + "milestone": "3.6.3", + "contributors": [ + "sampaiodiego" + ] + }, + { + "pr": "18978", + "title": "[FIX] Federation issues", + "userLogin": "alansikora", + "milestone": "3.6.3", + "contributors": [ + "alansikora" + ] + }, + { + "pr": "18994", + "title": "[FIX] LDAP avatar upload", + "userLogin": "pierre-lehnen-rc", + "milestone": "3.6.3", + "contributors": [ + "pierre-lehnen-rc" + ] + }, + { + "pr": "18948", + "title": "[FIX] Errors in LDAP avatar sync preventing login", + "userLogin": "pierre-lehnen-rc", + "milestone": "3.6.3", + "contributors": [ + "pierre-lehnen-rc" + ] + }, + { + "pr": "18956", + "title": "[FIX] PDF not rendering", + "userLogin": "gabriellsh", + "milestone": "3.6.3", + "contributors": [ + "gabriellsh", + "web-flow" + ] + } + ] } } } \ No newline at end of file diff --git a/.snapcraft/resources/prepareRocketChat b/.snapcraft/resources/prepareRocketChat index ae80eee9a68d..f3fa54fb1f0e 100755 --- a/.snapcraft/resources/prepareRocketChat +++ b/.snapcraft/resources/prepareRocketChat @@ -1,6 +1,6 @@ #!/bin/bash -curl -SLf "https://releases.rocket.chat/3.6.2/download/" -o rocket.chat.tgz +curl -SLf "https://releases.rocket.chat/3.6.3/download/" -o rocket.chat.tgz tar xf rocket.chat.tgz --strip 1 diff --git a/.snapcraft/snap/snapcraft.yaml b/.snapcraft/snap/snapcraft.yaml index 7227487ad9bf..9b36a2e528f2 100644 --- a/.snapcraft/snap/snapcraft.yaml +++ b/.snapcraft/snap/snapcraft.yaml @@ -7,7 +7,7 @@ # 5. `snapcraft snap` name: rocketchat-server -version: 3.6.2 +version: 3.6.3 summary: Rocket.Chat server description: Have your own Slack like online chat, built with Meteor. https://rocket.chat/ confinement: strict diff --git a/HISTORY.md b/HISTORY.md index 0235eb8abfef..7204e6baf805 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,6 +1,41 @@ +# 3.6.3 +`2020-09-25 ยท 4 ๐Ÿ› ยท 1 ๐Ÿ” ยท 4 ๐Ÿ‘ฉโ€๐Ÿ’ป๐Ÿ‘จโ€๐Ÿ’ป` + +### Engine versions +- Node: `12.16.1` +- NPM: `6.14.0` +- MongoDB: `3.4, 3.6, 4.0` +- Apps-Engine: `1.17.0` + +### ๐Ÿ› Bug fixes + + +- Errors in LDAP avatar sync preventing login ([#18948](https://github.com/RocketChat/Rocket.Chat/pull/18948)) + +- Federation issues ([#18978](https://github.com/RocketChat/Rocket.Chat/pull/18978)) + +- LDAP avatar upload ([#18994](https://github.com/RocketChat/Rocket.Chat/pull/18994)) + +- PDF not rendering ([#18956](https://github.com/RocketChat/Rocket.Chat/pull/18956)) + +
+๐Ÿ” Minor changes + + +- Obey to settings properties ([#19020](https://github.com/RocketChat/Rocket.Chat/pull/19020)) + +
+ +### ๐Ÿ‘ฉโ€๐Ÿ’ป๐Ÿ‘จโ€๐Ÿ’ป Core Team ๐Ÿค“ + +- [@alansikora](https://github.com/alansikora) +- [@gabriellsh](https://github.com/gabriellsh) +- [@pierre-lehnen-rc](https://github.com/pierre-lehnen-rc) +- [@sampaiodiego](https://github.com/sampaiodiego) + # 3.6.2 -`2020-09-17 ยท 7 ๐Ÿ› ยท 6 ๐Ÿ‘ฉโ€๐Ÿ’ป๐Ÿ‘จโ€๐Ÿ’ป` +`2020-09-18 ยท 7 ๐Ÿ› ยท 6 ๐Ÿ‘ฉโ€๐Ÿ’ป๐Ÿ‘จโ€๐Ÿ’ป` ### Engine versions - Node: `12.16.1` @@ -13,13 +48,13 @@ - Create Custom OAuth services from environment variables ([#17377](https://github.com/RocketChat/Rocket.Chat/pull/17377) by [@mrtndwrd](https://github.com/mrtndwrd)) -- Deactivate users that are the last owner of a room using REST API ([#18864](https://github.com/RocketChat/Rocket.Chat/pull/18864)) +- Deactivate users that are the last owner of a room using REST API ([#18864](https://github.com/RocketChat/Rocket.Chat/pull/18864) by [@FelipeParreira](https://github.com/FelipeParreira)) Allow for user deactivation through REST API (even if user is the last owner of a room) - Ignore User action from user card ([#18866](https://github.com/RocketChat/Rocket.Chat/pull/18866)) -- invite-all-from and invite-all-to commands don't work with multibyte room names ([#18919](https://github.com/RocketChat/Rocket.Chat/pull/18919)) +- invite-all-from and invite-all-to commands don't work with multibyte room names ([#18919](https://github.com/RocketChat/Rocket.Chat/pull/18919) by [@FelipeParreira](https://github.com/FelipeParreira)) Fix slash commands (invite-all-from and invite-all-to) to accept multi-byte room names. @@ -31,12 +66,12 @@ ### ๐Ÿ‘ฉโ€๐Ÿ’ป๐Ÿ‘จโ€๐Ÿ’ป Contributors ๐Ÿ˜ +- [@FelipeParreira](https://github.com/FelipeParreira) - [@mrtndwrd](https://github.com/mrtndwrd) - [@wreiske](https://github.com/wreiske) ### ๐Ÿ‘ฉโ€๐Ÿ’ป๐Ÿ‘จโ€๐Ÿ’ป Core Team ๐Ÿค“ -- [@FelipeParreira](https://github.com/FelipeParreira) - [@gabriellsh](https://github.com/gabriellsh) - [@pierre-lehnen-rc](https://github.com/pierre-lehnen-rc) - [@sampaiodiego](https://github.com/sampaiodiego) @@ -113,9 +148,9 @@ - **2FA:** Password enforcement setting and 2FA protection when saving settings or resetting E2E encryption ([#18640](https://github.com/RocketChat/Rocket.Chat/pull/18640)) - Increase the 2FA remembering time from 5min to 30min - + - Add new setting to enforce 2FA password fallback (enabled only for new installations) - + - Require 2FA to save settings and reset E2E Encryption keys - **Omnichannel:** Allow set other agent status via method `livechat:changeLivechatStatus ` ([#18571](https://github.com/RocketChat/Rocket.Chat/pull/18571)) @@ -484,11 +519,11 @@ - Mention autocomplete UI and performance improvements ([#18309](https://github.com/RocketChat/Rocket.Chat/pull/18309)) * New setting to configure the number of suggestions `Admin > Layout > User Interface > Number of users' autocomplete suggestions` (default 5) - + * The UI shows whenever the user is not a member of the room - + * The UI shows when the suggestion came from the last messages for quick selection/reply - + * The suggestions follow this order: * The user with the exact username and member of the room * The user with the exact username but not a member of the room (if allowed to list non-members) @@ -1347,11 +1382,11 @@ - Notification sounds ([#17616](https://github.com/RocketChat/Rocket.Chat/pull/17616)) * Global CDN config was ignored when loading the sound files - + * Upload of custom sounds wasn't getting the file extension correctly - + * Some translations were missing - + * Edit and delete of custom sounds were not working correctly - Omnichannel departments are not saved when the offline channel name is not defined ([#17553](https://github.com/RocketChat/Rocket.Chat/pull/17553)) @@ -1641,15 +1676,15 @@ We are still using the same logic to define which notifications every new message will generate, it takes some servers' settings, users's preferences and subscriptions' settings in consideration to determine who will receive each notification type (desktop, audio, email and mobile push), but now it doesn't check the user's status (online, away, offline) for email and mobile push notifications but send those notifications to a new queue with the following rules: - + - When the user is online the notification is scheduled to be sent in 120 seconds - + - When the user is away the notification is scheduled to be sent in 120 seconds minus the amount of time he is away - + - When the user is offline the notification is scheduled to be sent right away - + - When the user reads a channel all the notifications for that user are removed (clear queue) - + - When a notification is processed to be sent to a user and there are other scheduled notifications: - All the scheduled notifications for that user are rescheduled to now - The current notification goes back to the queue to be processed ordered by creation date @@ -13514,4 +13549,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/authorization/server/streamer/permissions/emitter.js b/app/authorization/server/streamer/permissions/emitter.js index a7062439eb46..5b0a2a13f9b4 100644 --- a/app/authorization/server/streamer/permissions/emitter.js +++ b/app/authorization/server/streamer/permissions/emitter.js @@ -32,7 +32,10 @@ Permissions.on('change', ({ clientAction, id, data, diff }) => { // if the permission changes, the effect on the visible settings depends on the role affected. // The selected-settings-based consumers have to react accordingly and either add or remove the // setting from the user's collection - const setting = Settings.findOneById(data.settingId); + const setting = Settings.findOneNotHiddenById(data.settingId); + if (!setting) { + return; + } Notifications.notifyLoggedInThisInstance( 'private-settings-changed', 'updated', diff --git a/app/federation/server/endpoints/dispatch.js b/app/federation/server/endpoints/dispatch.js index c73270092496..7a1971ff82a0 100644 --- a/app/federation/server/endpoints/dispatch.js +++ b/app/federation/server/endpoints/dispatch.js @@ -444,7 +444,7 @@ const eventHandlers = { }, }; -API.v1.addRoute('federation.events.dispatch', { authRequired: false }, { +API.v1.addRoute('federation.events.dispatch', { authRequired: false, rateLimiterOptions: { numRequestsAllowed: 30, intervalTimeInMS: 1000 } }, { async post() { if (!isFederationEnabled()) { return API.v1.failure('Federation not enabled'); diff --git a/app/federation/server/handler/index.js b/app/federation/server/handler/index.js index a2948293a1ac..8ccb510194a5 100644 --- a/app/federation/server/handler/index.js +++ b/app/federation/server/handler/index.js @@ -67,10 +67,7 @@ export function dispatchEvents(domains, events) { } export function dispatchEvent(domains, event) { - // Ensure the domain list is distinct to avoid excessive events - const distinctDomains = [...new Set(domains)].filter((domain) => domain === event.origin); - - dispatchEvents(distinctDomains, [event]); + dispatchEvents([...new Set(domains)], [event]); } export function getUpload(domain, fileId) { diff --git a/app/federation/server/lib/callbacks.js b/app/federation/server/lib/callbacks.js index c2712ad80d34..3d843554749e 100644 --- a/app/federation/server/lib/callbacks.js +++ b/app/federation/server/lib/callbacks.js @@ -1,14 +1,23 @@ import { callbacks } from '../../../callbacks/server'; +import { settings } from '../../../settings/server'; const callbackDefinitions = []; -export function registerCallback(callbackDefition) { - callbackDefinitions.push(callbackDefition); +function enableCallback(definition) { + callbacks.add(definition.hook, definition.callback, callbacks.priority.LOW, definition.id); +} + +export function registerCallback(callbackDefinition) { + callbackDefinitions.push(callbackDefinition); + + if (settings.get('FEDERATION_Enabled')) { + enableCallback(callbackDefinition); + } } export function enableCallbacks() { for (const definition of callbackDefinitions) { - callbacks.add(definition.hook, definition.callback, callbacks.priority.LOW, definition.id); + enableCallback(definition); } } diff --git a/app/ldap/server/sync.js b/app/ldap/server/sync.js index c11d9ed73367..0c3db0eca372 100644 --- a/app/ldap/server/sync.js +++ b/app/ldap/server/sync.js @@ -337,6 +337,41 @@ export function mapLDAPGroupsToChannels(ldap, ldapUser, user) { return userChannels; } +function syncUserAvatar(user, ldapUser) { + if (!user?._id || settings.get('LDAP_Sync_User_Avatar') !== true) { + return; + } + + const avatarField = (settings.get('LDAP_Avatar_Field') || 'thumbnailPhoto').trim(); + const avatar = ldapUser._raw[avatarField] || ldapUser._raw.thumbnailPhoto || ldapUser._raw.jpegPhoto; + if (!avatar) { + return; + } + + logger.info('Syncing user avatar'); + + Meteor.defer(() => { + const rs = RocketChatFile.bufferToStream(avatar); + const fileStore = FileUpload.getStore('Avatars'); + fileStore.deleteByName(user.username); + + const file = { + userId: user._id, + type: 'image/jpeg', + size: avatar.length, + }; + + Meteor.runAsUser(user._id, () => { + fileStore.insert(file, rs, (err, result) => { + Meteor.setTimeout(function() { + Users.setAvatarData(user._id, 'ldap', result.etag); + Notifications.notifyLogged('updateAvatar', { username: user.username, etag: result.etag }); + }, 500); + }); + }); + }); +} + export function syncUserData(user, ldapUser, ldap) { logger.info('Syncing user data'); logger.debug('user', { email: user.email, _id: user._id }); @@ -397,33 +432,7 @@ export function syncUserData(user, ldapUser, ldap) { } } - const avatarField = (settings.get('LDAP_Avatar_Field') || 'thumbnailPhoto').trim(); - - if (user && user._id && settings.get('LDAP_Sync_User_Avatar') === true) { - const avatar = ldapUser._raw[avatarField] || ldapUser._raw.thumbnailPhoto || ldapUser._raw.jpegPhoto; - - if (avatar) { - logger.info('Syncing user avatar'); - - const rs = RocketChatFile.bufferToStream(avatar); - const fileStore = FileUpload.getStore('Avatars'); - fileStore.deleteByName(user.username); - - const file = { - userId: user._id, - type: 'image/jpeg', - }; - - Meteor.runAsUser(user._id, () => { - fileStore.insert(file, rs, (err, result) => { - Meteor.setTimeout(function() { - Users.setAvatarData(user._id, 'ldap', result.etag); - Notifications.notifyLogged('updateAvatar', { username: user.username, etag: result.etag }); - }, 500); - }); - }); - } - } + syncUserAvatar(user, ldapUser); } export function addLdapUser(ldapUser, username, password, ldap) { diff --git a/app/message-attachments/client/messageAttachment.js b/app/message-attachments/client/messageAttachment.js index 86cf2b16f747..77aaa7c4f88e 100644 --- a/app/message-attachments/client/messageAttachment.js +++ b/app/message-attachments/client/messageAttachment.js @@ -42,10 +42,10 @@ async function renderPdfToCanvas(canvasId, pdfLink) { loader.style.display = 'block'; } - const pdf = await pdfjsLib.getDocument(pdfLink); + const pdf = await pdfjsLib.getDocument(pdfLink).promise; const page = await pdf.getPage(1); const scale = 0.5; - const viewport = page.getViewport(scale); + const viewport = page.getViewport({ scale }); const context = canvas.getContext('2d'); canvas.height = viewport.height; canvas.width = viewport.width; diff --git a/app/utils/rocketchat.info b/app/utils/rocketchat.info index 07887f4dde22..3c28f4f904a6 100644 --- a/app/utils/rocketchat.info +++ b/app/utils/rocketchat.info @@ -1,3 +1,3 @@ { - "version": "3.6.2" + "version": "3.6.3" } diff --git a/package-lock.json b/package-lock.json index 167443b645a2..d88562742c24 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "Rocket.Chat", - "version": "3.6.2", + "version": "3.6.3", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index a28ce677e46d..cfdaa8026293 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "Rocket.Chat", "description": "The Ultimate Open Source WebChat Platform", - "version": "3.6.2", + "version": "3.6.3", "author": { "name": "Rocket.Chat", "url": "https://rocket.chat/" diff --git a/server/publications/settings/emitter.js b/server/publications/settings/emitter.js index 2a9312b22548..20a336644271 100644 --- a/server/publications/settings/emitter.js +++ b/server/publications/settings/emitter.js @@ -17,6 +17,10 @@ Settings.on('change', ({ clientAction, id, data, diff }) => { properties: setting.properties, }; + if (setting.hidden) { + return; + } + if (setting.public === true) { Notifications.notifyAllInThisInstance('public-settings-changed', clientAction, value); }