diff --git a/.docker/Dockerfile.rhel b/.docker/Dockerfile.rhel index dbc1bd418c3be..d55091c02acd6 100644 --- a/.docker/Dockerfile.rhel +++ b/.docker/Dockerfile.rhel @@ -1,6 +1,6 @@ FROM registry.access.redhat.com/ubi8/nodejs-12 -ENV RC_VERSION 3.11.1 +ENV RC_VERSION 3.11.2 MAINTAINER buildmaster@rocket.chat diff --git a/.github/history-manual.json b/.github/history-manual.json index 87583c83bfa9f..bc95e8c181b07 100644 --- a/.github/history-manual.json +++ b/.github/history-manual.json @@ -56,5 +56,12 @@ "contributors": [ "sampaiodiego" ] + }], + "3.11.2": [{ + "title": "[FIX] Security Hotfix (https://docs.rocket.chat/guides/security/security-updates)", + "userLogin": "sampaiodiego", + "contributors": [ + "sampaiodiego" + ] }] } diff --git a/.github/history.json b/.github/history.json index aa889cac99312..6146bb8c3014e 100644 --- a/.github/history.json +++ b/.github/history.json @@ -55308,6 +55308,47 @@ ] } ] + }, + "3.11.2": { + "node_version": "12.18.4", + "npm_version": "6.14.8", + "apps_engine_version": "1.22.2", + "mongo_versions": [ + "3.4", + "3.6", + "4.0" + ], + "pull_requests": [ + { + "pr": "20727", + "title": "[FIX] Room owner not being able to override global retention policy", + "userLogin": "g-thome", + "description": "use correct permissions to check if room owner can override global retention policy", + "milestone": "3.11.2", + "contributors": [ + "g-thome" + ] + }, + { + "pr": "20860", + "title": "[FIX] Prevent Message Attachment rendering", + "userLogin": "ggazzo", + "milestone": "3.11.2", + "contributors": [ + "ggazzo" + ] + }, + { + "pr": "20740", + "title": "[FIX] External systems not being able to change Omnichannel Inquiry priorities ", + "userLogin": "renatobecker", + "description": "Due to a wrong property name, external applications were not able to change the priority of Omnichannel Inquires.", + "milestone": "3.11.2", + "contributors": [ + "renatobecker" + ] + } + ] } } } \ No newline at end of file diff --git a/.snapcraft/resources/prepareRocketChat b/.snapcraft/resources/prepareRocketChat index 8388f031d5c5c..e48d9bcd5e8a2 100755 --- a/.snapcraft/resources/prepareRocketChat +++ b/.snapcraft/resources/prepareRocketChat @@ -1,6 +1,6 @@ #!/bin/bash -curl -SLf "https://releases.rocket.chat/3.11.1/download/" -o rocket.chat.tgz +curl -SLf "https://releases.rocket.chat/3.11.2/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 19e9d98c5f81e..e27edb458392a 100644 --- a/.snapcraft/snap/snapcraft.yaml +++ b/.snapcraft/snap/snapcraft.yaml @@ -7,7 +7,7 @@ # 5. `snapcraft snap` name: rocketchat-server -version: 3.11.1 +version: 3.11.2 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 ae6f7fccf5320..8b38fbc88c869 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,4 +1,35 @@ +# 3.11.2 +`2021-02-28 ยท 4 ๐Ÿ› ยท 4 ๐Ÿ‘ฉโ€๐Ÿ’ป๐Ÿ‘จโ€๐Ÿ’ป` + +### Engine versions +- Node: `12.18.4` +- NPM: `6.14.8` +- MongoDB: `3.4, 3.6, 4.0` +- Apps-Engine: `1.22.2` + +### ๐Ÿ› Bug fixes + + +- Security Hotfix (https://docs.rocket.chat/guides/security/security-updates) + +- External systems not being able to change Omnichannel Inquiry priorities ([#20740](https://github.com/RocketChat/Rocket.Chat/pull/20740)) + + Due to a wrong property name, external applications were not able to change the priority of Omnichannel Inquires. + +- Prevent Message Attachment rendering ([#20860](https://github.com/RocketChat/Rocket.Chat/pull/20860)) + +- Room owner not being able to override global retention policy ([#20727](https://github.com/RocketChat/Rocket.Chat/pull/20727)) + + use correct permissions to check if room owner can override global retention policy + +### ๐Ÿ‘ฉโ€๐Ÿ’ป๐Ÿ‘จโ€๐Ÿ’ป Core Team ๐Ÿค“ + +- [@g-thome](https://github.com/g-thome) +- [@ggazzo](https://github.com/ggazzo) +- [@renatobecker](https://github.com/renatobecker) +- [@sampaiodiego](https://github.com/sampaiodiego) + # 3.11.1 `2021-02-10 ยท 5 ๐Ÿ› ยท 6 ๐Ÿ‘ฉโ€๐Ÿ’ป๐Ÿ‘จโ€๐Ÿ’ป` @@ -59,18 +90,20 @@ - **ENTERPRISE:** Omnichannel Contact Manager as preferred agent for routing ([#20244](https://github.com/RocketChat/Rocket.Chat/pull/20244)) - If the `Contact-Manager` is assigned to a Visitor, the chat will automatically get transferred to the respective Contact-Manager, provided the Contact-Manager is online. In-case the Contact-Manager is offline, the chat will be transferred to any other online agent. - We have provided a setting to control this auto-assignment feature - ![image](https://user-images.githubusercontent.com/34130764/104880961-8104d780-5986-11eb-9d87-82b99814b028.png) - - Behavior based-on Routing method - - 1. Auto-selection, Load-Balancing, or External Service (`autoAssignAgent = true`) - This is straightforward, - - if the Contact-manager is online, the chat will be transferred to the Contact-Manger only - - if the Contact-manager is offline, the chat will be transferred to any other online-agent based on the Routing system - 2. Manual-selection (`autoAssignAgent = false`) - - If the Contact-Manager is online, the chat will appear in the Queue of Contact-Manager **ONLY** + If the `Contact-Manager` is assigned to a Visitor, the chat will automatically get transferred to the respective Contact-Manager, provided the Contact-Manager is online. In-case the Contact-Manager is offline, the chat will be transferred to any other online agent. + We have provided a setting to control this auto-assignment feature + ![image](https://user-images.githubusercontent.com/34130764/104880961-8104d780-5986-11eb-9d87-82b99814b028.png) + + Behavior based-on Routing method + + + 1. Auto-selection, Load-Balancing, or External Service (`autoAssignAgent = true`) + This is straightforward, + - if the Contact-manager is online, the chat will be transferred to the Contact-Manger only + - if the Contact-manager is offline, the chat will be transferred to any other online-agent based on the Routing system + + 2. Manual-selection (`autoAssignAgent = false`) + - If the Contact-Manager is online, the chat will appear in the Queue of Contact-Manager **ONLY** - If the Contact-Manager is offline, the chat will appear in the Queue of all related Agents/Manager ( like it's done right now ) - Banner system and NPS ([#20221](https://github.com/RocketChat/Rocket.Chat/pull/20221)) @@ -79,34 +112,34 @@ - Email Inboxes for Omnichannel ([#20101](https://github.com/RocketChat/Rocket.Chat/pull/20101)) - With this new feature, email accounts will receive email messages(threads) which will be transformed into Omnichannel chats. It'll be possible to set up multiple email accounts, test the connection with email server(email provider) and define the behaviour of each account. - - https://user-images.githubusercontent.com/2493803/105430398-242d4980-5c32-11eb-835a-450c94837d23.mp4 - - ### New item on admin menu - - ![image](https://user-images.githubusercontent.com/2493803/105428723-bc293400-5c2e-11eb-8c02-e8d36ea82726.png) - - - ### Send test email tooltip - - ![image](https://user-images.githubusercontent.com/2493803/104366986-eaa16380-54f8-11eb-9ba7-831cfde2319c.png) - - - ### Inbox Info - - ![image](https://user-images.githubusercontent.com/2493803/104366796-ab731280-54f8-11eb-9941-a3cc8eb610e1.png) - - ### SMTP Info - - ![image](https://user-images.githubusercontent.com/2493803/104366868-c47bc380-54f8-11eb-969e-ccc29070957c.png) - - ### IMAP Info - - ![image](https://user-images.githubusercontent.com/2493803/104366897-cd6c9500-54f8-11eb-80c4-97d5b0c002d5.png) - - ### Messages - + With this new feature, email accounts will receive email messages(threads) which will be transformed into Omnichannel chats. It'll be possible to set up multiple email accounts, test the connection with email server(email provider) and define the behaviour of each account. + + https://user-images.githubusercontent.com/2493803/105430398-242d4980-5c32-11eb-835a-450c94837d23.mp4 + + ### New item on admin menu + + ![image](https://user-images.githubusercontent.com/2493803/105428723-bc293400-5c2e-11eb-8c02-e8d36ea82726.png) + + + ### Send test email tooltip + + ![image](https://user-images.githubusercontent.com/2493803/104366986-eaa16380-54f8-11eb-9ba7-831cfde2319c.png) + + + ### Inbox Info + + ![image](https://user-images.githubusercontent.com/2493803/104366796-ab731280-54f8-11eb-9941-a3cc8eb610e1.png) + + ### SMTP Info + + ![image](https://user-images.githubusercontent.com/2493803/104366868-c47bc380-54f8-11eb-969e-ccc29070957c.png) + + ### IMAP Info + + ![image](https://user-images.githubusercontent.com/2493803/104366897-cd6c9500-54f8-11eb-80c4-97d5b0c002d5.png) + + ### Messages + ![image](https://user-images.githubusercontent.com/2493803/105428971-45d90180-5c2f-11eb-992a-022a3df94471.png) - Encrypted Discussions and new Encryption Permissions ([#20201](https://github.com/RocketChat/Rocket.Chat/pull/20201)) @@ -118,7 +151,7 @@ - Add extra SAML settings to update room subs and add private room subs. ([#19489](https://github.com/RocketChat/Rocket.Chat/pull/19489) by [@tlskinneriv](https://github.com/tlskinneriv)) - Added a SAML setting to support updating room subscriptions each time a user logs in via SAML. + Added a SAML setting to support updating room subscriptions each time a user logs in via SAML. Added a SAML setting to support including private rooms in SAML updated subscriptions (whether initial or on each logon). - Autofocus on directory ([#20509](https://github.com/RocketChat/Rocket.Chat/pull/20509)) @@ -145,7 +178,7 @@ - Tooltip added for Kebab menu on chat header ([#20116](https://github.com/RocketChat/Rocket.Chat/pull/20116) by [@yash-rajpal](https://github.com/yash-rajpal)) - Added the missing Tooltip for kebab menu on chat header. + Added the missing Tooltip for kebab menu on chat header. ![tooltip after](https://user-images.githubusercontent.com/58601732/104031406-b07f4b80-51f2-11eb-87a4-1e8da78a254f.gif) ### ๐Ÿ› Bug fixes @@ -167,7 +200,7 @@ - Added context check for closing active tabbar for member-list ([#20228](https://github.com/RocketChat/Rocket.Chat/pull/20228) by [@yash-rajpal](https://github.com/yash-rajpal)) - When we click on a username and then click on see user's full profile, a tab gets active and shows us the user's profile, the problem occurs when the tab is still active and we try to see another user's profile. In this case, tabbar gets closed. + When we click on a username and then click on see user's full profile, a tab gets active and shows us the user's profile, the problem occurs when the tab is still active and we try to see another user's profile. In this case, tabbar gets closed. To resolve this, added context check for closing action of active tabbar. - Added Margin between status bullet and status label ([#20199](https://github.com/RocketChat/Rocket.Chat/pull/20199) by [@yash-rajpal](https://github.com/yash-rajpal)) @@ -176,8 +209,8 @@ - Added success message on saving notification preference. ([#20220](https://github.com/RocketChat/Rocket.Chat/pull/20220) by [@Darshilp326](https://github.com/Darshilp326)) - Added success message after saving notification preferences. - + Added success message after saving notification preferences. + https://user-images.githubusercontent.com/55157259/104774617-03ca3e80-579d-11eb-8fa4-990b108dd8d9.mp4 - Admin User Info email verified status ([#20110](https://github.com/RocketChat/Rocket.Chat/pull/20110) by [@bdelwood](https://github.com/bdelwood)) @@ -186,10 +219,10 @@ - Change header's favorite icon to filled star ([#20174](https://github.com/RocketChat/Rocket.Chat/pull/20174)) - ### Before: - ![image](https://user-images.githubusercontent.com/27704687/104351819-a60bcd00-54e4-11eb-8b43-7d281a6e5dcb.png) - - ### After: + ### Before: + ![image](https://user-images.githubusercontent.com/27704687/104351819-a60bcd00-54e4-11eb-8b43-7d281a6e5dcb.png) + + ### After: ![image](https://user-images.githubusercontent.com/27704687/104351632-67761280-54e4-11eb-87ba-25b940494bb5.png) - Changed success message for adding custom sound. ([#20272](https://github.com/RocketChat/Rocket.Chat/pull/20272) by [@Darshilp326](https://github.com/Darshilp326)) @@ -198,24 +231,24 @@ - Changed success message for ignoring member. ([#19996](https://github.com/RocketChat/Rocket.Chat/pull/19996) by [@Darshilp326](https://github.com/Darshilp326)) - Different messages for ignoring/unignoring will be displayed. - + Different messages for ignoring/unignoring will be displayed. + https://user-images.githubusercontent.com/55157259/103310307-4241c880-4a3d-11eb-8c6c-4c9b99d023db.mp4 - Creation of Omnichannel rooms not working correctly through the Apps when the agent parameter is set ([#19997](https://github.com/RocketChat/Rocket.Chat/pull/19997)) - Engagement dashboard graphs labels superposing each other ([#20267](https://github.com/RocketChat/Rocket.Chat/pull/20267)) - Now after a certain breakpoint, the graphs should stack vertically, and overlapping text rotated. - + Now after a certain breakpoint, the graphs should stack vertically, and overlapping text rotated. + ![image](https://user-images.githubusercontent.com/40830821/105098926-93b40500-5a89-11eb-9a56-2fc3b1552914.png) - Fields overflowing page ([#20287](https://github.com/RocketChat/Rocket.Chat/pull/20287)) - ### Before - ![image](https://user-images.githubusercontent.com/40830821/105246952-c1b14c00-5b52-11eb-8671-cff88edf242d.png) - - ### After + ### Before + ![image](https://user-images.githubusercontent.com/40830821/105246952-c1b14c00-5b52-11eb-8671-cff88edf242d.png) + + ### After ![image](https://user-images.githubusercontent.com/40830821/105247125-0a690500-5b53-11eb-9f3c-d6a68108e336.png) - Fix error that occurs on changing archive status of room ([#20098](https://github.com/RocketChat/Rocket.Chat/pull/20098) by [@aKn1ghtOut](https://github.com/aKn1ghtOut)) @@ -232,7 +265,7 @@ - Livechat.RegisterGuest method removing unset fields ([#20124](https://github.com/RocketChat/Rocket.Chat/pull/20124)) - After changes made on https://github.com/RocketChat/Rocket.Chat/pull/19931, the `Livechat.RegisterGuest` method started removing properties from the visitor inappropriately. The properties that did not receive value were removed from the object. + After changes made on https://github.com/RocketChat/Rocket.Chat/pull/19931, the `Livechat.RegisterGuest` method started removing properties from the visitor inappropriately. The properties that did not receive value were removed from the object. Those changes were made to support the new Contact Form, but now the form has its own method to deal with Contact data so those changes are no longer necessary. - Markdown added for Header Room topic ([#20021](https://github.com/RocketChat/Rocket.Chat/pull/20021) by [@yash-rajpal](https://github.com/yash-rajpal)) @@ -253,18 +286,18 @@ - Omnichannel - Contact Center form is not validating custom fields properly ([#20196](https://github.com/RocketChat/Rocket.Chat/pull/20196)) - The contact form is accepting undefined values in required custom fields when creating or editing contacts, and, the errror message isn't following Rocket.chat design system. - - ### Before - ![image](https://user-images.githubusercontent.com/2493803/104522668-31688980-55dd-11eb-92c5-83f96073edc4.png) - - ### After - - #### New - ![image](https://user-images.githubusercontent.com/2493803/104770494-68f74300-574f-11eb-94a3-c8fd73365308.png) - - - #### Edit + The contact form is accepting undefined values in required custom fields when creating or editing contacts, and, the errror message isn't following Rocket.chat design system. + + ### Before + ![image](https://user-images.githubusercontent.com/2493803/104522668-31688980-55dd-11eb-92c5-83f96073edc4.png) + + ### After + + #### New + ![image](https://user-images.githubusercontent.com/2493803/104770494-68f74300-574f-11eb-94a3-c8fd73365308.png) + + + #### Edit ![image](https://user-images.githubusercontent.com/2493803/104770538-7b717c80-574f-11eb-829f-1ae304103369.png) - Omnichannel Agents unable to take new chats in the queue ([#20022](https://github.com/RocketChat/Rocket.Chat/pull/20022)) @@ -285,15 +318,15 @@ - Room special name in prompts ([#20277](https://github.com/RocketChat/Rocket.Chat/pull/20277) by [@aKn1ghtOut](https://github.com/aKn1ghtOut)) - The "Hide room" and "Leave Room" confirmation prompts use the "name" key from the room info. When the setting " - Allow Special Characters in Room Names" is enabled, the prompts show the normalized names instead of those that contain the special characters. - - Changed the value being used from name to fname, which always has the user-set name. - - Previous: - ![Screenshot from 2021-01-20 15-52-29](https://user-images.githubusercontent.com/38764067/105161642-9b31e780-5b37-11eb-8b0c-ec4b1414c948.png) - - Updated: + The "Hide room" and "Leave Room" confirmation prompts use the "name" key from the room info. When the setting " + Allow Special Characters in Room Names" is enabled, the prompts show the normalized names instead of those that contain the special characters. + + Changed the value being used from name to fname, which always has the user-set name. + + Previous: + ![Screenshot from 2021-01-20 15-52-29](https://user-images.githubusercontent.com/38764067/105161642-9b31e780-5b37-11eb-8b0c-ec4b1414c948.png) + + Updated: ![Screenshot from 2021-01-20 15-50-19](https://user-images.githubusercontent.com/38764067/105161627-966d3380-5b37-11eb-9812-3dd9352b4f95.png) - Room's list showing all rooms with same name ([#20176](https://github.com/RocketChat/Rocket.Chat/pull/20176)) @@ -304,9 +337,9 @@ - Saving with blank email in edit user ([#20259](https://github.com/RocketChat/Rocket.Chat/pull/20259) by [@RonLek](https://github.com/RonLek)) - Disallows showing a success popup when email field is made blank in Edit User and instead shows the relevant error popup. - - + Disallows showing a success popup when email field is made blank in Edit User and instead shows the relevant error popup. + + https://user-images.githubusercontent.com/28918901/104960749-dbd81680-59fa-11eb-9c7b-2b257936f894.mp4 - Search list filter ([#19937](https://github.com/RocketChat/Rocket.Chat/pull/19937)) @@ -353,7 +386,7 @@ - Add translation of Edit Status in all languages ([#19916](https://github.com/RocketChat/Rocket.Chat/pull/19916) by [@sushant52](https://github.com/sushant52)) - Closes [#19915](https://github.com/RocketChat/Rocket.Chat/issues/19915) + Closes [#19915](https://github.com/RocketChat/Rocket.Chat/issues/19915) The profile options menu is well translated in many languages. However, Edit Status is the only button which is not well translated. With this change, the whole profile options will be properly translated in a lot of languages. - Bump axios from 0.18.0 to 0.18.1 ([#20055](https://github.com/RocketChat/Rocket.Chat/pull/20055) by [@dependabot[bot]](https://github.com/dependabot[bot])) @@ -388,10 +421,10 @@ - Regression: Announcement bar not showing properly Markdown content ([#20290](https://github.com/RocketChat/Rocket.Chat/pull/20290)) - **Before**: - ![image](https://user-images.githubusercontent.com/27704687/105273746-a4907380-5b7a-11eb-8121-aff665251c44.png) - - **After**: + **Before**: + ![image](https://user-images.githubusercontent.com/27704687/105273746-a4907380-5b7a-11eb-8121-aff665251c44.png) + + **After**: ![image](https://user-images.githubusercontent.com/27704687/105274050-2e404100-5b7b-11eb-93b2-b6282a7bed95.png) - regression: Announcement link open in new tab ([#20435](https://github.com/RocketChat/Rocket.Chat/pull/20435)) @@ -406,23 +439,23 @@ - Regression: Change sort icon ([#20177](https://github.com/RocketChat/Rocket.Chat/pull/20177)) - ### Before - ![image](https://user-images.githubusercontent.com/40830821/104366414-1bcd6400-54f8-11eb-9fc7-c6f13f07a61e.png) - - ### After + ### Before + ![image](https://user-images.githubusercontent.com/40830821/104366414-1bcd6400-54f8-11eb-9fc7-c6f13f07a61e.png) + + ### After ![image](https://user-images.githubusercontent.com/40830821/104366542-4cad9900-54f8-11eb-83ca-acb99899515a.png) - Regression: Custom field labels are not displayed properly on Omnichannel Contact Profile form ([#20393](https://github.com/RocketChat/Rocket.Chat/pull/20393)) - ### Before - ![image](https://user-images.githubusercontent.com/2493803/105780399-20116c80-5f4f-11eb-9620-0901472e453b.png) - - ![image](https://user-images.githubusercontent.com/2493803/105780420-2e5f8880-5f4f-11eb-8e93-8115ebc685be.png) - - ### After - - ![image](https://user-images.githubusercontent.com/2493803/105780832-1ccab080-5f50-11eb-8042-188dd0c41904.png) - + ### Before + ![image](https://user-images.githubusercontent.com/2493803/105780399-20116c80-5f4f-11eb-9620-0901472e453b.png) + + ![image](https://user-images.githubusercontent.com/2493803/105780420-2e5f8880-5f4f-11eb-8e93-8115ebc685be.png) + + ### After + + ![image](https://user-images.githubusercontent.com/2493803/105780832-1ccab080-5f50-11eb-8042-188dd0c41904.png) + ![image](https://user-images.githubusercontent.com/2493803/105780911-500d3f80-5f50-11eb-96e0-7df3f179dbd5.png) - Regression: ESLint Warning - explicit-function-return-type ([#20434](https://github.com/RocketChat/Rocket.Chat/pull/20434) by [@aditya-mitra](https://github.com/aditya-mitra)) @@ -439,8 +472,8 @@ - Regression: Fixed update room avatar issue. ([#20433](https://github.com/RocketChat/Rocket.Chat/pull/20433) by [@Darshilp326](https://github.com/Darshilp326)) - Users can now update their room avatar without any error. - + Users can now update their room avatar without any error. + https://user-images.githubusercontent.com/55157259/105951602-560d3880-6096-11eb-97a5-b5eb9a28b58d.mp4 - Regression: Info Page Icon style and usage graph breaking ([#20180](https://github.com/RocketChat/Rocket.Chat/pull/20180)) @@ -457,11 +490,11 @@ - Regression: Unread superposing announcement. ([#20306](https://github.com/RocketChat/Rocket.Chat/pull/20306)) - ### Before - ![image](https://user-images.githubusercontent.com/40830821/105412619-c2f67d80-5c13-11eb-8204-5932ea880c8a.png) - - - ### After + ### Before + ![image](https://user-images.githubusercontent.com/40830821/105412619-c2f67d80-5c13-11eb-8204-5932ea880c8a.png) + + + ### After ![image](https://user-images.githubusercontent.com/40830821/105411176-d1439a00-5c11-11eb-8d1b-ea27c8485214.png) - Regression: User Dropdown margin ([#20222](https://github.com/RocketChat/Rocket.Chat/pull/20222)) @@ -746,8 +779,8 @@ - Hightlights validation on Account Preferences page ([#19902](https://github.com/RocketChat/Rocket.Chat/pull/19902) by [@aKn1ghtOut](https://github.com/aKn1ghtOut)) - This PR fixes two issues in the account settings "preferences" panel. - Once set, the "Highlighted Words" setting cannot be reset to an empty string. This was fixed by changing the string validation from checking the length to checking the type of variable. + This PR fixes two issues in the account settings "preferences" panel. + Once set, the "Highlighted Words" setting cannot be reset to an empty string. This was fixed by changing the string validation from checking the length to checking the type of variable. Secondly, it tracks the changes to correctly identify if changes after the last "save changes" action have been made, using an "updates" state variable, instead of just comparing against the initialValue that does not change on clicking "save changes". - Image preview for image URLs on messages ([#19734](https://github.com/RocketChat/Rocket.Chat/pull/19734)) @@ -806,10 +839,14 @@ - Chore: Update Pull Request template ([#19768](https://github.com/RocketChat/Rocket.Chat/pull/19768)) - Improve the template of Pull Requests in order to make it clear reducing duplicated information and removing the visible checklists that were generating noise and misunderstanding with the PR progress. - - Moved the checklists to inside comments - - Merge the changelog and proposed changes sections to have a single source of description that goes to the changelog - - Remove the screenshot section, they can be added inside the description + Improve the template of Pull Requests in order to make it clear reducing duplicated information and removing the visible checklists that were generating noise and misunderstanding with the PR progress. + + - Moved the checklists to inside comments + + - Merge the changelog and proposed changes sections to have a single source of description that goes to the changelog + + - Remove the screenshot section, they can be added inside the description + - Changed the proposed changes title to incentivizing the usage of images and videos - Frontend folder structure ([#19631](https://github.com/RocketChat/Rocket.Chat/pull/19631)) @@ -844,11 +881,11 @@ - Regression: Double Scrollbars on tables ([#19980](https://github.com/RocketChat/Rocket.Chat/pull/19980)) - Before: - ![image](https://user-images.githubusercontent.com/40830821/103242719-0ec84680-4936-11eb-87a7-68b6eea8de7b.png) - - - After: + Before: + ![image](https://user-images.githubusercontent.com/40830821/103242719-0ec84680-4936-11eb-87a7-68b6eea8de7b.png) + + + After: ![image](https://user-images.githubusercontent.com/40830821/103242680-ee988780-4935-11eb-99e2-a95de99f78f1.png) - Regression: Failed autolinker and markdown rendering ([#19831](https://github.com/RocketChat/Rocket.Chat/pull/19831)) @@ -867,7 +904,7 @@ - Regression: Omnichannel Custom Fields Form no longer working after refactoring ([#19948](https://github.com/RocketChat/Rocket.Chat/pull/19948)) - The Omnichannel `Custom Fields` form is not working anymore after some refactorings on client-side. + The Omnichannel `Custom Fields` form is not working anymore after some refactorings on client-side. When the user clicks on `Custom Field` in the Omnichannel menu, a blank page appears. - Regression: polishing licenses endpoints ([#19981](https://github.com/RocketChat/Rocket.Chat/pull/19981)) @@ -1060,8 +1097,8 @@ - Bundle Size Client ([#19533](https://github.com/RocketChat/Rocket.Chat/pull/19533)) - temporarily removes some codeblock languages - Moved some libraries to dynamic imports + temporarily removes some codeblock languages + Moved some libraries to dynamic imports Removed some shared code not used on the client side - Forward Omnichannel room to agent in another department ([#19576](https://github.com/RocketChat/Rocket.Chat/pull/19576) by [@mrfigueiredo](https://github.com/mrfigueiredo)) @@ -2139,8 +2176,10 @@ - **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) + - 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)) @@ -2158,7 +2197,7 @@ - 2FA by Email setting showing for the user even when disabled by the admin ([#18473](https://github.com/RocketChat/Rocket.Chat/pull/18473)) - The option to disable/enable the **Two-factor authentication via Email** at `Account > Security > Two Factor Authentication + The option to disable/enable the **Two-factor authentication via Email** at `Account > Security > Two Factor Authentication ` was visible even when the setting **Enable Two Factor Authentication via Email** at `Admin > Accounts > Two Factor Authentication` was disabled leading to misbehavior since the functionality was disabled. - Agents enabledDepartment attribute not set on collection ([#18614](https://github.com/RocketChat/Rocket.Chat/pull/18614) by [@paulobernardoaf](https://github.com/paulobernardoaf)) @@ -2508,13 +2547,16 @@ - 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) - * The users containing the text in username, name or nickname and member of the room + * 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) + * The users containing the text in username, name or nickname and member of the room * The users containing the text in username, name or nickname and not a member of the room (if allowed to list non-members) - Message action styles ([#18190](https://github.com/RocketChat/Rocket.Chat/pull/18190)) @@ -2856,10 +2898,10 @@ - Split NOTIFICATIONS_SCHEDULE_DELAY into three separate variables ([#17669](https://github.com/RocketChat/Rocket.Chat/pull/17669) by [@jazztickets](https://github.com/jazztickets)) - Email notification delay can now be customized with the following environment variables: - NOTIFICATIONS_SCHEDULE_DELAY_ONLINE - NOTIFICATIONS_SCHEDULE_DELAY_AWAY - NOTIFICATIONS_SCHEDULE_DELAY_OFFLINE + Email notification delay can now be customized with the following environment variables: + NOTIFICATIONS_SCHEDULE_DELAY_ONLINE + NOTIFICATIONS_SCHEDULE_DELAY_AWAY + NOTIFICATIONS_SCHEDULE_DELAY_OFFLINE Setting the value to -1 disable notifications for that type. - Threads ([#17416](https://github.com/RocketChat/Rocket.Chat/pull/17416)) @@ -3259,11 +3301,11 @@ - **ENTERPRISE:** Omnichannel Last-Chatted Agent Preferred option ([#17666](https://github.com/RocketChat/Rocket.Chat/pull/17666)) - If activated, this feature will store the last agent that assisted each Omnichannel visitor when a conversation is taken. So, when a visitor returns(it works with any entry point, Livechat, Facebook, REST API, and so on) and starts a new chat, the routing system checks: - - 1 - The visitor object for any stored agent that the visitor has previously talked to; - 2 - If a previous agent is not found, the system will try to find a previous conversation of the same visitor. If a room is found, the system will get the previous agent from the room; - + If activated, this feature will store the last agent that assisted each Omnichannel visitor when a conversation is taken. So, when a visitor returns(it works with any entry point, Livechat, Facebook, REST API, and so on) and starts a new chat, the routing system checks: + + 1 - The visitor object for any stored agent that the visitor has previously talked to; + 2 - If a previous agent is not found, the system will try to find a previous conversation of the same visitor. If a room is found, the system will get the previous agent from the room; + After this process, if an agent has been found, the system will check the agent's availability to assist the new chat. If it's not available, then the routing system will get the next available agent in the queue. - **ENTERPRISE:** Support for custom Livechat registration form fields ([#17581](https://github.com/RocketChat/Rocket.Chat/pull/17581)) @@ -3368,9 +3410,12 @@ - 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 + * 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)) @@ -3658,14 +3703,19 @@ - Better Push and Email Notification logic ([#17357](https://github.com/RocketChat/Rocket.Chat/pull/17357)) - 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 + 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 - Buttons to check/uncheck all users and channels on import ([#17207](https://github.com/RocketChat/Rocket.Chat/pull/17207)) @@ -4028,7 +4078,7 @@ - Translation via MS translate ([#16363](https://github.com/RocketChat/Rocket.Chat/pull/16363) by [@mrsimpson](https://github.com/mrsimpson)) - Adds Microsoft's translation service (https://translator.microsoft.com/) as a provider for translation of messages. + Adds Microsoft's translation service (https://translator.microsoft.com/) as a provider for translation of messages. In addition to implementing the interface (similar to google and DeepL), a small change has been done in order to display the translation provider on the UI. - Two Factor authentication via email ([#15949](https://github.com/RocketChat/Rocket.Chat/pull/15949)) @@ -15567,4 +15617,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/functions/hasRole.js b/app/authorization/server/functions/hasRole.js index e5d8927cbb747..545adc3f737b6 100644 --- a/app/authorization/server/functions/hasRole.js +++ b/app/authorization/server/functions/hasRole.js @@ -1,7 +1,10 @@ import { Roles } from '../../../models/server/raw'; export const hasRoleAsync = async (userId, roleNames, scope) => { - roleNames = [].concat(roleNames); + if (!userId || userId === '') { + return false; + } + return Roles.isUserInRoles(userId, roleNames, scope); }; diff --git a/app/lib/server/functions/setUserAvatar.js b/app/lib/server/functions/setUserAvatar.js index 7229d5a294e4e..bae4c45809af9 100644 --- a/app/lib/server/functions/setUserAvatar.js +++ b/app/lib/server/functions/setUserAvatar.js @@ -18,13 +18,13 @@ export const setUserAvatar = function(user, dataURI, contentType, service) { try { result = HTTP.get(dataURI, { npmRequestOptions: { encoding: 'binary', rejectUnauthorized: false } }); if (!result) { - console.log(`Not a valid response, from the avatar url: ${ dataURI }`); - throw new Meteor.Error('error-avatar-invalid-url', `Invalid avatar URL: ${ dataURI }`, { function: 'setUserAvatar', url: dataURI }); + console.log(`Not a valid response, from the avatar url: ${ encodeURI(dataURI) }`); + throw new Meteor.Error('error-avatar-invalid-url', `Invalid avatar URL: ${ encodeURI(dataURI) }`, { function: 'setUserAvatar', url: dataURI }); } } catch (error) { if (!error.response || error.response.statusCode !== 404) { - console.log(`Error while handling the setting of the avatar from a url (${ dataURI }) for ${ user.username }:`, error); - throw new Meteor.Error('error-avatar-url-handling', `Error while handling avatar setting from a URL (${ dataURI }) for ${ user.username }`, { function: 'RocketChat.setUserAvatar', url: dataURI, username: user.username }); + console.log(`Error while handling the setting of the avatar from a url (${ encodeURI(dataURI) }) for ${ user.username }:`, error); + throw new Meteor.Error('error-avatar-url-handling', `Error while handling avatar setting from a URL (${ encodeURI(dataURI) }) for ${ user.username }`, { function: 'RocketChat.setUserAvatar', url: dataURI, username: user.username }); } } diff --git a/app/meteor-accounts-saml/server/lib/SAML.ts b/app/meteor-accounts-saml/server/lib/SAML.ts index 277084414a552..2514cce35ccb6 100644 --- a/app/meteor-accounts-saml/server/lib/SAML.ts +++ b/app/meteor-accounts-saml/server/lib/SAML.ts @@ -376,7 +376,7 @@ export class SAML { }); } - private static processValidateAction(req: IIncomingMessage, res: ServerResponse, service: IServiceProviderOptions, samlObject: ISAMLAction): void { + private static processValidateAction(req: IIncomingMessage, res: ServerResponse, service: IServiceProviderOptions, _samlObject: ISAMLAction): void { const serviceProvider = new SAMLServiceProvider(service); SAMLUtils.relayState = req.body.RelayState; serviceProvider.validateResponse(req.body.SAMLResponse, (err, profile/* , loggedOut*/) => { @@ -390,21 +390,15 @@ export class SAML { throw new Error('No user data collected from IdP response.'); } - let credentialToken = (profile.inResponseToId && profile.inResponseToId.value) || profile.inResponseToId || profile.InResponseTo || samlObject.credentialToken; + // create a random token to store the login result + // to test an IdP initiated login on localhost, use the following URL (assuming SimpleSAMLPHP on localhost:8080): + // http://localhost:8080/simplesaml/saml2/idp/SSOService.php?spentityid=http://localhost:3000/_saml/metadata/test-sp + const credentialToken = Random.id(); + const loginResult = { profile, }; - if (!credentialToken) { - // If the login was initiated by the IDP, then we don't have a credentialToken as there was no AuthorizeRequest on our side - // so we create a random token now to use the same url to end the login - // - // to test an IdP initiated login on localhost, use the following URL (assuming SimpleSAMLPHP on localhost:8080): - // http://localhost:8080/simplesaml/saml2/idp/SSOService.php?spentityid=http://localhost:3000/_saml/metadata/test-sp - credentialToken = Random.id(); - SAMLUtils.log('[SAML] Using random credentialToken: ', credentialToken); - } - this.storeCredential(credentialToken, loginResult); const url = `${ Meteor.absoluteUrl('home') }?saml_idp_credentialToken=${ credentialToken }`; res.writeHead(302, { diff --git a/app/meteor-accounts-saml/server/loginHandler.ts b/app/meteor-accounts-saml/server/loginHandler.ts index 0dcec76d04c3a..84beec3091aae 100644 --- a/app/meteor-accounts-saml/server/loginHandler.ts +++ b/app/meteor-accounts-saml/server/loginHandler.ts @@ -11,7 +11,7 @@ const makeError = (message: string): Record => ({ }); Accounts.registerLoginHandler('saml', function(loginRequest) { - if (!loginRequest.saml || !loginRequest.credentialToken) { + if (!loginRequest.saml || !loginRequest.credentialToken || typeof loginRequest.credentialToken !== 'string') { return undefined; } diff --git a/app/models/server/raw/Roles.js b/app/models/server/raw/Roles.js index 523aa968057d1..de771bcad9b01 100644 --- a/app/models/server/raw/Roles.js +++ b/app/models/server/raw/Roles.js @@ -8,13 +8,15 @@ export class RolesRaw extends BaseRaw { } async isUserInRoles(userId, roles, scope) { - roles = [].concat(roles); + if (!Array.isArray(roles)) { + roles = [roles]; + } for (let i = 0, total = roles.length; i < total; i++) { const roleName = roles[i]; // eslint-disable-next-line no-await-in-loop - const role = await this.findOne({ _id: roleName }); + const role = await this.findOne({ _id: roleName }, { scope: 1 }); const roleScope = (role && role.scope) || 'Users'; const model = this.models[roleScope]; diff --git a/app/ui-utils/client/lib/Layout.js b/app/ui-utils/client/lib/Layout.js index 758f58a99fa78..2158d80f2a9be 100644 --- a/app/ui-utils/client/lib/Layout.js +++ b/app/ui-utils/client/lib/Layout.js @@ -1,14 +1,17 @@ import { Tracker } from 'meteor/tracker'; import { FlowRouter } from 'meteor/kadira:flow-router'; +import { ReactiveVar } from 'meteor/reactive-var'; export const Layout = new class RocketChatLayout { constructor() { + this.embedded = new ReactiveVar(); Tracker.autorun(() => { this.layout = FlowRouter.getQueryParam('layout'); + this.embedded.set(this.layout === 'embedded'); }); } isEmbedded() { - return FlowRouter.getQueryParam('layout') === 'embedded'; + return this.embedded.get(); } }(); diff --git a/app/ui-utils/client/lib/messageContext.js b/app/ui-utils/client/lib/messageContext.js index d10e7cd8ccbf8..283cddf5bb9e0 100644 --- a/app/ui-utils/client/lib/messageContext.js +++ b/app/ui-utils/client/lib/messageContext.js @@ -1,6 +1,7 @@ import { Meteor } from 'meteor/meteor'; import { Template } from 'meteor/templating'; import { FlowRouter } from 'meteor/kadira:flow-router'; +import { Tracker } from 'meteor/tracker'; import { Subscriptions, Rooms, Users } from '../../../models/client'; import { hasPermission } from '../../../authorization/client'; @@ -17,7 +18,7 @@ const fields = { name: 1, username: 1, 'settings.preferences.showMessageInMainTh export function messageContext({ rid } = Template.instance()) { const uid = Meteor.userId(); const user = Users.findOne({ _id: uid }, { fields }) || {}; - const instace = Template.instance(); + const instance = Template.instance(); const openThread = (e) => { const { rid, mid, tmid } = e.currentTarget.dataset; const room = Rooms.findOne({ _id: rid }); @@ -40,7 +41,7 @@ export function messageContext({ rid } = Template.instance()) { }); } : (msg, e) => { const { actionlink } = e.currentTarget.dataset; - actionLinks.run(actionlink, msg._id, instace, (err) => { + actionLinks.run(actionlink, msg._id, instance, (err) => { if (err) { handleError(err); } @@ -60,13 +61,12 @@ export function messageContext({ rid } = Template.instance()) { return { u: user, - room: Rooms.findOne({ _id: rid }, { - reactive: false, + room: Tracker.nonreactive(() => Rooms.findOne({ _id: rid }, { fields: { _updatedAt: 0, lastMessage: 0, }, - }), + })), subscription: Subscriptions.findOne({ rid }, { fields: { name: 1, diff --git a/app/utils/rocketchat.info b/app/utils/rocketchat.info index 510b977ecfb6a..55d145f9ac7fd 100644 --- a/app/utils/rocketchat.info +++ b/app/utils/rocketchat.info @@ -1,3 +1,3 @@ { - "version": "3.11.1" + "version": "3.11.2" } diff --git a/client/views/room/contextualBar/Info/EditRoomInfo/EditRoomInfo.js b/client/views/room/contextualBar/Info/EditRoomInfo/EditRoomInfo.js index 318ec2623c84f..0f346929ec472 100644 --- a/client/views/room/contextualBar/Info/EditRoomInfo/EditRoomInfo.js +++ b/client/views/room/contextualBar/Info/EditRoomInfo/EditRoomInfo.js @@ -226,7 +226,7 @@ function EditChannel({ room, onClickClose, onClickBack }) { const canChangeType = getCanChangeType(room, canCreateChannel, canCreateGroup, isAdmin); const canSetRo = usePermission('set-readonly', room._id); const canSetReactWhenRo = usePermission('set-react-when-readonly', room._id); - const canEditPrivilegedSetting = usePermission('edit-privileged-setting', room._id); + const canEditRoomRetentionPolicy = usePermission('edit-room-retention-policy', room._id); const canArchiveOrUnarchive = useAtLeastOnePermission(useMemo(() => ['archive-room', 'unarchive-room'], [])); const canDelete = usePermission(`delete-${ room.t }`); const canToggleEncryption = usePermission('toggle-room-e2e-encryption', room._id) && (room.encrypted || e2e.isReady()); @@ -390,7 +390,7 @@ function EditChannel({ room, onClickClose, onClickBack }) { {t('RetentionPolicyRoom_OverrideGlobal')} - + diff --git a/ee/app/livechat-enterprise/server/api/lib/inquiries.js b/ee/app/livechat-enterprise/server/api/lib/inquiries.js index 8a7423c98b477..ac1527155e8ed 100644 --- a/ee/app/livechat-enterprise/server/api/lib/inquiries.js +++ b/ee/app/livechat-enterprise/server/api/lib/inquiries.js @@ -7,7 +7,7 @@ export async function setPriorityToInquiry({ userId, roomId, priority }) { if (!await hasPermissionAsync(userId, 'manage-livechat-priorities') && !await hasPermissionAsync(userId, 'view-l-room')) { throw new Error('error-not-authorized'); } - const inquiry = await LivechatInquiry.findOneByRoomId(roomId, { fields: { queued: 1 } }); + const inquiry = await LivechatInquiry.findOneByRoomId(roomId, { fields: { status: 1 } }); if (!inquiry || inquiry.status !== 'queued') { throw new Error('error-invalid-inquiry'); } diff --git a/package-lock.json b/package-lock.json index 6d8b13fb1e45e..d7a67774062b5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "Rocket.Chat", - "version": "3.11.1", + "version": "3.11.2", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 19cbf5138b617..d43572679a2b8 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "Rocket.Chat", "description": "The Ultimate Open Source WebChat Platform", - "version": "3.11.1", + "version": "3.11.2", "author": { "name": "Rocket.Chat", "url": "https://rocket.chat/" diff --git a/server/methods/addAllUserToRoom.js b/server/methods/addAllUserToRoom.js index d8379b2030c71..83dffa5abc9e7 100644 --- a/server/methods/addAllUserToRoom.js +++ b/server/methods/addAllUserToRoom.js @@ -11,52 +11,54 @@ Meteor.methods({ check(rid, String); check(activeUsersOnly, Boolean); - if (hasRole(this.userId, 'admin') === true) { - const userCount = Users.find().count(); - if (userCount > settings.get('API_User_Limit')) { - throw new Meteor.Error('error-user-limit-exceeded', 'User Limit Exceeded', { - method: 'addAllToRoom', - }); - } + if (!hasRole(this.userId, 'admin')) { + throw new Meteor.Error(403, 'Access to Method Forbidden', { + method: 'addAllToRoom', + }); + } - const room = Rooms.findOneById(rid); - if (room == null) { - throw new Meteor.Error('error-invalid-room', 'Invalid room', { - method: 'addAllToRoom', - }); - } + const userFilter = {}; + if (activeUsersOnly === true) { + userFilter.active = true; + } - const userFilter = {}; - if (activeUsersOnly === true) { - userFilter.active = true; - } + const userCursor = Users.find(userFilter); + const usersCount = userCursor.count(); + if (usersCount > settings.get('API_User_Limit')) { + throw new Meteor.Error('error-user-limit-exceeded', 'User Limit Exceeded', { + method: 'addAllToRoom', + }); + } - const users = Users.find(userFilter).fetch(); - const now = new Date(); - users.forEach(function(user) { - const subscription = Subscriptions.findOneByRoomIdAndUserId(rid, user._id); - if (subscription != null) { - return; - } - callbacks.run('beforeJoinRoom', user, room); - Subscriptions.createWithRoomAndUser(room, user, { - ts: now, - open: true, - alert: true, - unread: 1, - userMentions: 1, - groupMentions: 0, - }); - Messages.createUserJoinWithRoomIdAndUser(rid, user, { - ts: now, - }); - Meteor.defer(function() {}); - return callbacks.run('afterJoinRoom', user, room); + const room = Rooms.findOneById(rid); + if (!room) { + throw new Meteor.Error('error-invalid-room', 'Invalid room', { + method: 'addAllToRoom', }); - return true; } - throw new Meteor.Error(403, 'Access to Method Forbidden', { - method: 'addAllToRoom', + + const users = userCursor.fetch(); + const now = new Date(); + users.forEach(function(user) { + const subscription = Subscriptions.findOneByRoomIdAndUserId(rid, user._id); + if (subscription != null) { + return; + } + callbacks.run('beforeJoinRoom', user, room); + Subscriptions.createWithRoomAndUser(room, user, { + ts: now, + open: true, + alert: true, + unread: 1, + userMentions: 1, + groupMentions: 0, + }); + Messages.createUserJoinWithRoomIdAndUser(rid, user, { + ts: now, + }); + Meteor.defer(function() {}); + return callbacks.run('afterJoinRoom', user, room); }); + return true; }, });