diff --git a/.changeset/afraid-parents-bake.md b/.changeset/afraid-parents-bake.md deleted file mode 100644 index af2b8a10d4899..0000000000000 --- a/.changeset/afraid-parents-bake.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@rocket.chat/rest-typings': minor -'@rocket.chat/meteor': minor ---- - -REST endpoint `/v1/users.createToken` is not deprecated anymore. It now requires a `secret` parameter to generate a token for a user. This change is part of the effort to enhance security by ensuring that tokens are generated with an additional layer of validation. The `secret` parameter is validated against a new environment variable `CREATE_TOKENS_FOR_USERS_SECRET`. diff --git a/.changeset/beige-seahorses-reply.md b/.changeset/beige-seahorses-reply.md deleted file mode 100644 index bf87249b57e07..0000000000000 --- a/.changeset/beige-seahorses-reply.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@rocket.chat/meteor": major -"@rocket.chat/web-ui-registration": major ---- - -Removes the deprecated sendConfirmationEmail method diff --git a/.changeset/blue-beans-check.md b/.changeset/blue-beans-check.md deleted file mode 100644 index f1d66153e3f1f..0000000000000 --- a/.changeset/blue-beans-check.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': major ---- - -Removes deprecated `livechat:removeUnit` method diff --git a/.changeset/breezy-timers-flow.md b/.changeset/breezy-timers-flow.md deleted file mode 100644 index 5894d387b05de..0000000000000 --- a/.changeset/breezy-timers-flow.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -Removes the deprecated meteor method: `livechat:saveTag` diff --git a/.changeset/brown-carrots-bathe.md b/.changeset/brown-carrots-bathe.md deleted file mode 100644 index 9e39e63edc9b9..0000000000000 --- a/.changeset/brown-carrots-bathe.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@rocket.chat/meteor': patch -'@rocket.chat/rest-typings': patch ---- - -Adds deprecation warning for `livechat:removeMonitor` and new endpoint replacing it; `livechat/monitor.remove` diff --git a/.changeset/brown-llamas-worry.md b/.changeset/brown-llamas-worry.md deleted file mode 100644 index 9cbf74ba7317f..0000000000000 --- a/.changeset/brown-llamas-worry.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@rocket.chat/meteor": patch -"@rocket.chat/rest-typings": patch ---- - -Adds a deprecation warning for `livechat:saveBusinessHour` and new endpoint replacing it; `livechat/business-hours.save` diff --git a/.changeset/bump-patch-1766456337926.md b/.changeset/bump-patch-1766456337926.md deleted file mode 100644 index e1eaa7980afb1..0000000000000 --- a/.changeset/bump-patch-1766456337926.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Bump @rocket.chat/meteor version. diff --git a/.changeset/chatty-dingos-bathe.md b/.changeset/chatty-dingos-bathe.md deleted file mode 100644 index e09c5e1c667e0..0000000000000 --- a/.changeset/chatty-dingos-bathe.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@rocket.chat/apps-engine': minor -'@rocket.chat/apps': minor -'@rocket.chat/meteor': minor ---- - -Adds a new method to the Apps-Engine that allows apps to retrieve multiple rooms from database diff --git a/.changeset/chatty-lizards-reflect.md b/.changeset/chatty-lizards-reflect.md deleted file mode 100644 index 17f269cb70a20..0000000000000 --- a/.changeset/chatty-lizards-reflect.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -"@rocket.chat/meteor": major -"@rocket.chat/ddp-client": major ---- - -Removes the deprecated livechat:getTagsList method - -Removes the deprecated livechat:getUnitsFromUser method - -Removes the deprecated livechat:getFirstRoomMessage method - -Removes the deprecated livechat:getDepartmentForwardRestrictions method - diff --git a/.changeset/chatty-roses-help.md b/.changeset/chatty-roses-help.md deleted file mode 100644 index 3c4a5849c8daa..0000000000000 --- a/.changeset/chatty-roses-help.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"@rocket.chat/meteor": patch -"@rocket.chat/core-typings": patch -"@rocket.chat/i18n": patch ---- - -Adds invitation request support to rooms diff --git a/.changeset/chilly-cobras-look.md b/.changeset/chilly-cobras-look.md deleted file mode 100644 index 9e7bba192bba2..0000000000000 --- a/.changeset/chilly-cobras-look.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@rocket.chat/i18n': major -'@rocket.chat/meteor': major ---- - -Removes deprecated VoIP permissions diff --git a/.changeset/cold-chairs-taste.md b/.changeset/cold-chairs-taste.md deleted file mode 100644 index e12a576569534..0000000000000 --- a/.changeset/cold-chairs-taste.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Fixes an issue where its not being possible to change the password in account security page diff --git a/.changeset/cold-chefs-rhyme.md b/.changeset/cold-chefs-rhyme.md deleted file mode 100644 index 5dc1bbdc43c81..0000000000000 --- a/.changeset/cold-chefs-rhyme.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -Disables read receipts indicators in federated rooms. This feature will be re-enabled when fully compatible with federation. diff --git a/.changeset/cool-turtles-bathe.md b/.changeset/cool-turtles-bathe.md deleted file mode 100644 index ab3f8b80285c6..0000000000000 --- a/.changeset/cool-turtles-bathe.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@rocket.chat/meteor': major -'@rocket.chat/media-calls': minor -'@rocket.chat/i18n': minor ---- - -Makes Voice Calls enabled by default when available diff --git a/.changeset/cuddly-eels-perform.md b/.changeset/cuddly-eels-perform.md deleted file mode 100644 index bc99f3c96e302..0000000000000 --- a/.changeset/cuddly-eels-perform.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Fixes members tab > add members not removing selected items diff --git a/.changeset/curly-bats-wink.md b/.changeset/curly-bats-wink.md deleted file mode 100644 index 79bd2e7e37918..0000000000000 --- a/.changeset/curly-bats-wink.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -'@rocket.chat/model-typings': major -'@rocket.chat/core-typings': major -'@rocket.chat/rest-typings': major -'@rocket.chat/ui-contexts': major -'@rocket.chat/ui-voip': major -'@rocket.chat/models': major -'@rocket.chat/i18n': major -'@rocket.chat/meteor': major -'@rocket.chat/apps-engine': minor -'@rocket.chat/core-services': minor -'@rocket.chat/message-types': minor -'@rocket.chat/ddp-client': minor ---- - -Removes deprecated VoIP from Omnichannel diff --git a/.changeset/cyan-mayflies-juggle.md b/.changeset/cyan-mayflies-juggle.md deleted file mode 100644 index 593798b63ba1c..0000000000000 --- a/.changeset/cyan-mayflies-juggle.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': major ---- - -Removes deprecated `livechat:saveUnit` method diff --git a/.changeset/dull-rabbits-add.md b/.changeset/dull-rabbits-add.md deleted file mode 100644 index 1cfd27a2c7701..0000000000000 --- a/.changeset/dull-rabbits-add.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": major ---- - -Removes the deprecated `authorization:removeUserFromRole` method diff --git a/.changeset/dull-tips-look.md b/.changeset/dull-tips-look.md deleted file mode 100644 index 8867fc650dc12..0000000000000 --- a/.changeset/dull-tips-look.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"@rocket.chat/meteor": patch -"@rocket.chat/core-services": patch -"@rocket.chat/federation-matrix": patch ---- - -Fixes an issue where cases of invites that were canceled or disinvited were not being handled. diff --git a/.changeset/early-dots-leave.md b/.changeset/early-dots-leave.md new file mode 100644 index 0000000000000..43b71a88ec2a0 --- /dev/null +++ b/.changeset/early-dots-leave.md @@ -0,0 +1,5 @@ +--- +'@rocket.chat/meteor': patch +--- + +Fixes an issue where cancelling a file upload results in an uncaught exception diff --git a/.changeset/empty-buses-walk.md b/.changeset/empty-buses-walk.md deleted file mode 100644 index c24e5acce300e..0000000000000 --- a/.changeset/empty-buses-walk.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -"@rocket.chat/meteor": major -"@rocket.chat/gazzodown": major -"@rocket.chat/i18n": major -"@rocket.chat/ui-client": major ---- - -Promotes Timestamp Parser from preview state to stable diff --git a/.changeset/fair-dryers-behave.md b/.changeset/fair-dryers-behave.md deleted file mode 100644 index a9c57c42042e3..0000000000000 --- a/.changeset/fair-dryers-behave.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@rocket.chat/rest-typings': major -'@rocket.chat/meteor': major ---- - -Removes ecdh functionality and related settings diff --git a/.changeset/fast-ligers-unite.md b/.changeset/fast-ligers-unite.md deleted file mode 100644 index eacb88108a0f7..0000000000000 --- a/.changeset/fast-ligers-unite.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Security Hotfix (https://docs.rocket.chat/docs/security-fixes-and-updates) diff --git a/.changeset/fast-walls-eat.md b/.changeset/fast-walls-eat.md deleted file mode 100644 index 1c82cd4c32513..0000000000000 --- a/.changeset/fast-walls-eat.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -Removes deprecated meteor method `unmuteUserInRoom` diff --git a/.changeset/few-masks-punch.md b/.changeset/few-masks-punch.md deleted file mode 100644 index cf455b251bd8d..0000000000000 --- a/.changeset/few-masks-punch.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": major ---- - -Removes deprecated `canAccessRoom` meteor method diff --git a/.changeset/fifty-rice-smash.md b/.changeset/fifty-rice-smash.md deleted file mode 100644 index 51ca36cdc84d4..0000000000000 --- a/.changeset/fifty-rice-smash.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": major ---- - -Removes deprecated Realtime API method: `livechat:getAnalyticsChartData` diff --git a/.changeset/fifty-starfishes-collect.md b/.changeset/fifty-starfishes-collect.md new file mode 100644 index 0000000000000..584b873249ebb --- /dev/null +++ b/.changeset/fifty-starfishes-collect.md @@ -0,0 +1,5 @@ +--- +"@rocket.chat/meteor": patch +--- + +Fixes browser slowdowns by preventing a rare cascading of language preference updates when multiple tabs reload diff --git a/.changeset/five-months-shake.md b/.changeset/five-months-shake.md deleted file mode 100644 index b694672c84358..0000000000000 --- a/.changeset/five-months-shake.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': major ---- - -Removes deprecated `livechat:returnAsInquiry` method diff --git a/.changeset/flat-berries-sell.md b/.changeset/flat-berries-sell.md new file mode 100644 index 0000000000000..a46de3658945d --- /dev/null +++ b/.changeset/flat-berries-sell.md @@ -0,0 +1,5 @@ +--- +'@rocket.chat/pdf-worker': patch +--- + +Fixes broken chat transcript when there are more than one file per message diff --git a/.changeset/forty-pears-divide.md b/.changeset/forty-pears-divide.md deleted file mode 100644 index b7c9c57357aff..0000000000000 --- a/.changeset/forty-pears-divide.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -Removes deprecated method `livechat:removeBusinessHour` diff --git a/.changeset/forty-spiders-sneeze.md b/.changeset/forty-spiders-sneeze.md deleted file mode 100644 index f09f83231e92d..0000000000000 --- a/.changeset/forty-spiders-sneeze.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': major ---- - -Removes deprecated `removeCustomField` method diff --git a/.changeset/four-timers-enjoy.md b/.changeset/four-timers-enjoy.md deleted file mode 100644 index 8ce7068fa7bb1..0000000000000 --- a/.changeset/four-timers-enjoy.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -'@rocket.chat/model-typings': major -'@rocket.chat/core-typings': major -'@rocket.chat/rest-typings': major -'@rocket.chat/models': major -'@rocket.chat/i18n': major -'@rocket.chat/meteor': major -'@rocket.chat/core-services': minor ---- - -Removes Deprecated FreeSwitch integration diff --git a/.changeset/fresh-hats-kneel.md b/.changeset/fresh-hats-kneel.md new file mode 100644 index 0000000000000..5d2738f5ee2d9 --- /dev/null +++ b/.changeset/fresh-hats-kneel.md @@ -0,0 +1,5 @@ +--- +"@rocket.chat/meteor": patch +--- + +Fixes an issue where words are breaking mid-character in user card's bio diff --git a/.changeset/fresh-tables-raise.md b/.changeset/fresh-tables-raise.md deleted file mode 100644 index 89978df7f5421..0000000000000 --- a/.changeset/fresh-tables-raise.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': major ---- - -Removes the deprecated `getUserRoles` method in favor of the `/v1/roles.getUsersInPublicRoles` endpoint. diff --git a/.changeset/fuzzy-plants-hammer.md b/.changeset/fuzzy-plants-hammer.md deleted file mode 100644 index 5b4f0a647f889..0000000000000 --- a/.changeset/fuzzy-plants-hammer.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': minor ---- - -Changes the position of the buttons in Unique ID change detected modal in order to highlight configuration update instead of new workspace diff --git a/.changeset/fuzzy-teachers-juggle.md b/.changeset/fuzzy-teachers-juggle.md deleted file mode 100644 index fce7559bbcb6a..0000000000000 --- a/.changeset/fuzzy-teachers-juggle.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@rocket.chat/mock-providers': patch -'@rocket.chat/meteor': patch ---- - -Fixes an issue that could cause slashcommands to disappear for the user in certain high-availability scenarios diff --git a/.changeset/gentle-dingos-retire.md b/.changeset/gentle-dingos-retire.md deleted file mode 100644 index 526facc864e23..0000000000000 --- a/.changeset/gentle-dingos-retire.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': major ---- - -Removes deprecated `setAdminStatus` method diff --git a/.changeset/gold-keys-compare.md b/.changeset/gold-keys-compare.md deleted file mode 100644 index 452169781c04c..0000000000000 --- a/.changeset/gold-keys-compare.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -"@rocket.chat/meteor": major ---- -Removes support of MongoDB versions 5.x and 6.x diff --git a/.changeset/gold-zoos-sneeze.md b/.changeset/gold-zoos-sneeze.md deleted file mode 100644 index a38ff5c5fb604..0000000000000 --- a/.changeset/gold-zoos-sneeze.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": major ---- - -Removes deprecated meteor method `muteUserInRoom` diff --git a/.changeset/good-files-accept.md b/.changeset/good-files-accept.md deleted file mode 100644 index ccc6ce33f5b25..0000000000000 --- a/.changeset/good-files-accept.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@rocket.chat/meteor": major -"@rocket.chat/rest-typings": major ---- - -Removes the deprecated method `createToken` diff --git a/.changeset/grumpy-colts-collect.md b/.changeset/grumpy-colts-collect.md deleted file mode 100644 index 9406052d0b132..0000000000000 --- a/.changeset/grumpy-colts-collect.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Fixes an issue where custom status is not updating immediately if the value is empty diff --git a/.changeset/grumpy-readers-give.md b/.changeset/grumpy-readers-give.md deleted file mode 100644 index 085e9e3d88cc0..0000000000000 --- a/.changeset/grumpy-readers-give.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@rocket.chat/apps-engine': patch -'@rocket.chat/meteor': patch ---- - -Adds an execution flag to apps-engine runtime that helps prevent the publishing of faulty builds diff --git a/.changeset/happy-carpets-draw.md b/.changeset/happy-carpets-draw.md deleted file mode 100644 index f59a1a06c7bbf..0000000000000 --- a/.changeset/happy-carpets-draw.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@rocket.chat/ui-client': major -'@rocket.chat/i18n': major -'@rocket.chat/meteor': major ---- - -Promotes Resizable Contextualbars from preview state to stable. diff --git a/.changeset/happy-news-reflect.md b/.changeset/happy-news-reflect.md deleted file mode 100644 index c69eb08eacdd1..0000000000000 --- a/.changeset/happy-news-reflect.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/fuselage-ui-kit": patch ---- - -Fixes an issue with the `action` block inside `Info Card` ui-kit element not dispatching actions. diff --git a/.changeset/honest-knives-cough.md b/.changeset/honest-knives-cough.md deleted file mode 100644 index 2329bec3a251a..0000000000000 --- a/.changeset/honest-knives-cough.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": major ---- - -Removes the deprecated `setReaction` meteor method diff --git a/.changeset/hungry-fans-wait.md b/.changeset/hungry-fans-wait.md deleted file mode 100644 index 7d8594f3470aa..0000000000000 --- a/.changeset/hungry-fans-wait.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': minor ---- - -Validates attachment fields to require `title` and `value` properties on APIs `chat.postMessage` and `chat.sendMessage`. diff --git a/.changeset/large-jobs-smell.md b/.changeset/large-jobs-smell.md deleted file mode 100644 index a04338844742b..0000000000000 --- a/.changeset/large-jobs-smell.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Fixes an issue with the build that prevented Deno runtime to run on air-gapped environments diff --git a/.changeset/large-planes-destroy.md b/.changeset/large-planes-destroy.md deleted file mode 100644 index e2541e1df68f5..0000000000000 --- a/.changeset/large-planes-destroy.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -Fixes create channel modal not validating federated access permission diff --git a/.changeset/lazy-pianos-care.md b/.changeset/lazy-pianos-care.md deleted file mode 100644 index d5afd4cb714af..0000000000000 --- a/.changeset/lazy-pianos-care.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'@rocket.chat/model-typings': minor -'@rocket.chat/core-typings': minor -'@rocket.chat/rest-typings': minor -'@rocket.chat/models': minor -'@rocket.chat/meteor': minor ---- - -Enhance user's deactivated state handling to correctly distinguish between pending and deactivated users. diff --git a/.changeset/lemon-garlics-check.md b/.changeset/lemon-garlics-check.md deleted file mode 100644 index 6216aaf24dd9a..0000000000000 --- a/.changeset/lemon-garlics-check.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -Fixes license add-on validations for federated rooms diff --git a/.changeset/loud-elephants-happen.md b/.changeset/loud-elephants-happen.md deleted file mode 100644 index 0f505ff2445dd..0000000000000 --- a/.changeset/loud-elephants-happen.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/media-signaling': patch ---- - -Fixes an issue where the client would play the Call Ended sound effect when the user started calling someone on a different session diff --git a/.changeset/many-walls-cheat.md b/.changeset/many-walls-cheat.md deleted file mode 100644 index 190539f09b1f2..0000000000000 --- a/.changeset/many-walls-cheat.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@rocket.chat/fuselage-ui-kit": minor -"@rocket.chat/ui-kit": minor ---- - -Introduces a new variation of the `Icon` element to `ui-kit` through the new `framed` optional property. diff --git a/.changeset/many-walls-impress.md b/.changeset/many-walls-impress.md deleted file mode 100644 index 058723b41d421..0000000000000 --- a/.changeset/many-walls-impress.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@rocket.chat/meteor": patch -"@rocket.chat/rest-typings": patch ---- - -Adds deprecation warning on `livechat:addMonitor` with new endpoint replacing it; `livechat/monitors.create` diff --git a/.changeset/many-windows-perform.md b/.changeset/many-windows-perform.md deleted file mode 100644 index d84dce497937c..0000000000000 --- a/.changeset/many-windows-perform.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": major ---- - -Removes deprecated Realtime API method: `livechat:closeRoom` diff --git a/.changeset/mean-eagles-complain.md b/.changeset/mean-eagles-complain.md new file mode 100644 index 0000000000000..3f442526d3706 --- /dev/null +++ b/.changeset/mean-eagles-complain.md @@ -0,0 +1,5 @@ +--- +"@rocket.chat/meteor": patch +--- + +Fixes a variable shadowing issue preventing new visitor registration in `livechat/messages` API. diff --git a/.changeset/metal-moose-travel.md b/.changeset/metal-moose-travel.md deleted file mode 100644 index 71c2f66f5e02c..0000000000000 --- a/.changeset/metal-moose-travel.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Fixes a condition where the `SAML_Custom_Default_default_user_role` setting, used to define the default SAML role when none is provided, would fail when a role name was used instead of an ID. diff --git a/.changeset/metal-rocks-behave.md b/.changeset/metal-rocks-behave.md deleted file mode 100644 index f6db936b32968..0000000000000 --- a/.changeset/metal-rocks-behave.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -Removes deprecated method `saveUserProfile` diff --git a/.changeset/nasty-beans-breathe.md b/.changeset/nasty-beans-breathe.md deleted file mode 100644 index 8ba5361d40462..0000000000000 --- a/.changeset/nasty-beans-breathe.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": major ---- - -Removes the deprecated `setCustomFields` method diff --git a/.changeset/nasty-moons-speak.md b/.changeset/nasty-moons-speak.md deleted file mode 100644 index d709bd58c2021..0000000000000 --- a/.changeset/nasty-moons-speak.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Adds invitation badge to room members list diff --git a/.changeset/neat-spoons-cover.md b/.changeset/neat-spoons-cover.md deleted file mode 100644 index ed5941e748a69..0000000000000 --- a/.changeset/neat-spoons-cover.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": major ---- - -Removes deprecated Realtime API method: `livechat:removeAllClosedRooms` diff --git a/.changeset/nervous-clouds-carry.md b/.changeset/nervous-clouds-carry.md new file mode 100644 index 0000000000000..fcb81addfb3c8 --- /dev/null +++ b/.changeset/nervous-clouds-carry.md @@ -0,0 +1,6 @@ +--- +'@rocket.chat/ui-client': minor +'@rocket.chat/meteor': minor +--- + +Enables the password policy by default to ensure security by default and alters SetupWizard to handle errors diff --git a/.changeset/nervous-doors-knock.md b/.changeset/nervous-doors-knock.md deleted file mode 100644 index aa4084d7b8ded..0000000000000 --- a/.changeset/nervous-doors-knock.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": major ---- - -Removes the deprecated `getAvatarSuggestion` method diff --git a/.changeset/nervous-melons-cough.md b/.changeset/nervous-melons-cough.md deleted file mode 100644 index 870cdfacdff37..0000000000000 --- a/.changeset/nervous-melons-cough.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -Removes the deprecated meteor method: `livechat:addMonitor` diff --git a/.changeset/nervous-wombats-look.md b/.changeset/nervous-wombats-look.md deleted file mode 100644 index 6a3baaea2f50c..0000000000000 --- a/.changeset/nervous-wombats-look.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': major ---- - -Removes deprecated `livechat:saveDepartment` method diff --git a/.changeset/ninety-dodos-confess.md b/.changeset/ninety-dodos-confess.md deleted file mode 100644 index b85badf29d0bf..0000000000000 --- a/.changeset/ninety-dodos-confess.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -'@rocket.chat/authorization-service': minor -'@rocket.chat/core-services': minor -'@rocket.chat/message-types': minor -'@rocket.chat/model-typings': minor -'@rocket.chat/core-typings': minor -'@rocket.chat/apps-engine': minor -'@rocket.chat/abac': minor -'@rocket.chat/models': minor -'@rocket.chat/i18n': minor -'@rocket.chat/jwt': minor -'@rocket.chat/meteor': minor ---- - -Adds Attribute Based Access Control (ABAC) for private channels & private teams. diff --git a/.changeset/ninety-hats-swim.md b/.changeset/ninety-hats-swim.md deleted file mode 100644 index 43ea75a82d383..0000000000000 --- a/.changeset/ninety-hats-swim.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': major ---- - -Removes deprecated `livechat:setUpConnection` method diff --git a/.changeset/ninety-pans-search.md b/.changeset/ninety-pans-search.md new file mode 100644 index 0000000000000..555010b66f29b --- /dev/null +++ b/.changeset/ninety-pans-search.md @@ -0,0 +1,6 @@ +--- +'@rocket.chat/rest-typings': minor +'@rocket.chat/meteor': minor +--- + +Changes list of Room Files to only show files that have been successfully attached to a message diff --git a/.changeset/odd-pigs-hang.md b/.changeset/odd-pigs-hang.md deleted file mode 100644 index b3db5fdbdafaf..0000000000000 --- a/.changeset/odd-pigs-hang.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Fixes an issue where iframe external commands sent via `window.postMessage` were not being handled correctly when Rocket.Chat was embedded inside an iframe. diff --git a/.changeset/olive-pens-think.md b/.changeset/olive-pens-think.md deleted file mode 100644 index 994b14dad0833..0000000000000 --- a/.changeset/olive-pens-think.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Fixes incorrect URL generation in Global Search "Jump to message" feature, resolving navigation issues when jumping to messages across different channels. diff --git a/.changeset/orange-poets-marry.md b/.changeset/orange-poets-marry.md deleted file mode 100644 index 8da7abd288b76..0000000000000 --- a/.changeset/orange-poets-marry.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": major ---- - -Removes the deprecated `getRoomRoles` method diff --git a/.changeset/pink-months-compare.md b/.changeset/pink-months-compare.md deleted file mode 100644 index 27e345823957a..0000000000000 --- a/.changeset/pink-months-compare.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": major ---- - -Removes the deprecated `authorization:deleteRole` method diff --git a/.changeset/plenty-flowers-help.md b/.changeset/plenty-flowers-help.md deleted file mode 100644 index 65f178303d5cc..0000000000000 --- a/.changeset/plenty-flowers-help.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': major ---- - -Removes deprecated `livechat:removeRoom` method diff --git a/.changeset/poor-apricots-heal.md b/.changeset/poor-apricots-heal.md deleted file mode 100644 index 420ed96068488..0000000000000 --- a/.changeset/poor-apricots-heal.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Fixes push notifications continuing after logout due to missing token cleanup. diff --git a/.changeset/poor-trains-mate.md b/.changeset/poor-trains-mate.md deleted file mode 100644 index 90b7882bab726..0000000000000 --- a/.changeset/poor-trains-mate.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': major ---- - -Removes deprecated `appId` parameter from the `oauth-apps.get` endpoint. diff --git a/.changeset/popular-items-smash.md b/.changeset/popular-items-smash.md deleted file mode 100644 index 84316444911ba..0000000000000 --- a/.changeset/popular-items-smash.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': major ---- - -Removes deprecated `sendFileLivechatMessage` method diff --git a/.changeset/pre.json b/.changeset/pre.json deleted file mode 100644 index ff78be3fb84cc..0000000000000 --- a/.changeset/pre.json +++ /dev/null @@ -1,194 +0,0 @@ -{ - "mode": "pre", - "tag": "rc", - "initialVersions": { - "@rocket.chat/meteor": "8.0.0-develop", - "rocketchat-services": "2.0.37", - "@rocket.chat/uikit-playground": "0.7.2", - "@rocket.chat/account-service": "0.4.46", - "@rocket.chat/authorization-service": "0.4.46", - "@rocket.chat/ddp-streamer": "0.3.46", - "@rocket.chat/omnichannel-transcript": "0.4.46", - "@rocket.chat/presence-service": "0.4.46", - "@rocket.chat/queue-worker": "0.4.46", - "@rocket.chat/abac": "0.0.1", - "@rocket.chat/federation-matrix": "0.0.8", - "@rocket.chat/license": "1.1.6", - "@rocket.chat/media-calls": "0.1.2", - "@rocket.chat/network-broker": "0.2.25", - "@rocket.chat/omni-core-ee": "0.0.11", - "@rocket.chat/omnichannel-services": "0.3.43", - "@rocket.chat/pdf-worker": "0.3.25", - "@rocket.chat/presence": "0.2.46", - "@rocket.chat/ui-theming": "0.4.4", - "@rocket.chat/account-utils": "0.0.2", - "@rocket.chat/agenda": "0.1.0", - "@rocket.chat/api-client": "0.2.46", - "@rocket.chat/apps": "0.5.25", - "@rocket.chat/apps-engine": "1.58.0", - "@rocket.chat/base64": "1.0.13", - "@rocket.chat/cas-validate": "0.0.3", - "@rocket.chat/core-services": "0.11.2", - "@rocket.chat/core-typings": "8.0.0-develop", - "@rocket.chat/cron": "0.1.46", - "@rocket.chat/ddp-client": "0.3.46", - "@rocket.chat/desktop-api": "1.1.0", - "@rocket.chat/eslint-config": "0.7.0", - "@rocket.chat/favicon": "0.0.4", - "@rocket.chat/fuselage-ui-kit": "25.0.2", - "@rocket.chat/gazzodown": "25.0.2", - "@rocket.chat/http-router": "7.9.13", - "@rocket.chat/i18n": "1.13.0", - "@rocket.chat/instance-status": "0.1.46", - "@rocket.chat/jest-presets": "0.0.1", - "@rocket.chat/jwt": "0.1.1", - "@rocket.chat/livechat": "1.23.17", - "@rocket.chat/log-format": "0.0.2", - "@rocket.chat/logger": "0.0.2", - "@rocket.chat/media-signaling": "0.1.0", - "@rocket.chat/message-parser": "0.31.32", - "@rocket.chat/message-types": "0.0.1", - "@rocket.chat/mock-providers": "0.4.6", - "@rocket.chat/model-typings": "1.9.2", - "@rocket.chat/models": "1.8.2", - "@rocket.chat/mongo-adapter": "0.0.2", - "@rocket.chat/poplib": "0.0.2", - "@rocket.chat/omni-core": "0.0.11", - "@rocket.chat/password-policies": "0.1.0", - "@rocket.chat/patch-injection": "0.0.1", - "@rocket.chat/peggy-loader": "0.31.27", - "@rocket.chat/random": "1.2.2", - "@rocket.chat/release-action": "2.2.3", - "@rocket.chat/release-changelog": "0.1.0", - "@rocket.chat/rest-typings": "8.0.0-develop", - "@rocket.chat/server-cloud-communication": "0.0.2", - "@rocket.chat/server-fetch": "0.0.3", - "@rocket.chat/sha256": "1.0.12", - "@rocket.chat/storybook-config": "0.0.2", - "@rocket.chat/tools": "0.2.3", - "@rocket.chat/tracing": "0.0.1", - "@rocket.chat/tsconfig": "0.0.0", - "@rocket.chat/ui-avatar": "21.0.2", - "@rocket.chat/ui-client": "25.0.2", - "@rocket.chat/ui-composer": "0.5.3", - "@rocket.chat/ui-contexts": "25.0.2", - "@rocket.chat/ui-kit": "0.38.0", - "@rocket.chat/ui-video-conf": "25.0.2", - "@rocket.chat/ui-voip": "15.0.2", - "@rocket.chat/web-ui-registration": "25.0.2" - }, - "changesets": [ - "afraid-parents-bake", - "beige-seahorses-reply", - "blue-beans-check", - "breezy-timers-flow", - "brown-carrots-bathe", - "brown-llamas-worry", - "bump-patch-1766456337926", - "chatty-dingos-bathe", - "chatty-lizards-reflect", - "chatty-roses-help", - "chilly-cobras-look", - "cold-chairs-taste", - "cold-chefs-rhyme", - "cool-turtles-bathe", - "cuddly-eels-perform", - "curly-bats-wink", - "cyan-mayflies-juggle", - "dull-rabbits-add", - "dull-tips-look", - "empty-buses-walk", - "fair-dryers-behave", - "fast-ligers-unite", - "fast-walls-eat", - "few-masks-punch", - "fifty-rice-smash", - "five-months-shake", - "forty-pears-divide", - "forty-spiders-sneeze", - "four-timers-enjoy", - "fresh-tables-raise", - "fuzzy-plants-hammer", - "fuzzy-teachers-juggle", - "gentle-dingos-retire", - "gold-keys-compare", - "gold-zoos-sneeze", - "good-files-accept", - "grumpy-colts-collect", - "grumpy-readers-give", - "happy-carpets-draw", - "happy-news-reflect", - "honest-knives-cough", - "hungry-fans-wait", - "large-jobs-smell", - "large-planes-destroy", - "lazy-pianos-care", - "lemon-garlics-check", - "loud-elephants-happen", - "many-walls-cheat", - "many-walls-impress", - "many-windows-perform", - "metal-moose-travel", - "metal-rocks-behave", - "nasty-beans-breathe", - "nasty-moons-speak", - "neat-spoons-cover", - "nervous-doors-knock", - "nervous-melons-cough", - "nervous-wombats-look", - "ninety-dodos-confess", - "ninety-hats-swim", - "odd-pigs-hang", - "olive-pens-think", - "orange-poets-marry", - "pink-months-compare", - "plenty-flowers-help", - "poor-apricots-heal", - "poor-trains-mate", - "popular-items-smash", - "proud-dingos-sell", - "purple-mayflies-approve", - "quick-turtles-count", - "quiet-bees-turn", - "real-grapes-itch", - "rich-dogs-wonder", - "rotten-bees-behave", - "rotten-pugs-trade", - "selfish-countries-sleep", - "seven-badgers-dress", - "seven-otters-turn", - "shaggy-otters-think", - "sharp-beers-search", - "short-pots-lay", - "six-squids-pretend", - "sixty-bikes-know", - "slimy-ads-sing", - "slimy-hairs-wink", - "smooth-birds-crash", - "spicy-nails-design", - "strange-spiders-act", - "strong-bags-train", - "strong-bats-swim", - "strong-maps-act", - "swift-ears-sparkle", - "ten-carrots-melt", - "tender-wolves-promise", - "thick-badgers-grab", - "thick-guests-compete", - "thick-wasps-turn", - "tidy-laws-wink", - "tough-baboons-wash", - "tricky-trees-tan", - "twelve-feet-repeat", - "twelve-forks-destroy", - "twelve-years-act", - "twenty-cars-decide", - "two-pets-knock", - "two-turtles-try", - "weak-frogs-relax", - "wet-papayas-buy", - "wet-walls-drive", - "wicked-yaks-join", - "wild-hairs-carry" - ] -} diff --git a/.changeset/proud-dingos-sell.md b/.changeset/proud-dingos-sell.md deleted file mode 100644 index 17d7910431550..0000000000000 --- a/.changeset/proud-dingos-sell.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': major ---- - -Removes the setting `API_Use_REST_For_DDP_Calls`. Turning this on meant websocket was only used for realtime data/events, and any other meteor method calls goes over method.call endpoint. For microservice deployments, this had to be turned on. Now method calls will always happen over http endpoints. diff --git a/.changeset/purple-mayflies-approve.md b/.changeset/purple-mayflies-approve.md deleted file mode 100644 index 997daff3dce0a..0000000000000 --- a/.changeset/purple-mayflies-approve.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@rocket.chat/ui-client': major -'@rocket.chat/i18n': major -'@rocket.chat/meteor': major ---- - -Promotes quick reactions from preview state to stable diff --git a/.changeset/quick-turtles-count.md b/.changeset/quick-turtles-count.md deleted file mode 100644 index 028ea55d86eb6..0000000000000 --- a/.changeset/quick-turtles-count.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@rocket.chat/meteor": major -"@rocket.chat/rest-typings": major ---- - -Removes `/api/v1/banners.getnew` deprecated endpoint diff --git a/.changeset/quiet-bees-turn.md b/.changeset/quiet-bees-turn.md deleted file mode 100644 index e2312ccb478af..0000000000000 --- a/.changeset/quiet-bees-turn.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -"@rocket.chat/meteor": major -"@rocket.chat/ddp-client": major -"@rocket.chat/livechat": major -"@rocket.chat/rest-typings": major ---- - -Removes the `livechat:transfer` deprecated method -Removes the `livechat/room.transfer` deprecated endpoint -Creates the `livechat/visitor.department.transfer` for visitors department transfer use diff --git a/.changeset/real-grapes-itch.md b/.changeset/real-grapes-itch.md deleted file mode 100644 index e4eda2815fa45..0000000000000 --- a/.changeset/real-grapes-itch.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -Fixes an issue where it‘s not being possible to configure department's `chatClosingTags` without enabling `requestTagBeforeClosingTag` diff --git a/.changeset/rich-dogs-wonder.md b/.changeset/rich-dogs-wonder.md deleted file mode 100644 index 2eeb95649f61d..0000000000000 --- a/.changeset/rich-dogs-wonder.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Fixes an issue that caused Third-party login to not work properly diff --git a/.changeset/rotten-bees-behave.md b/.changeset/rotten-bees-behave.md deleted file mode 100644 index 1a14da3c2cbf0..0000000000000 --- a/.changeset/rotten-bees-behave.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -removes the deprecated meteor method: `livechat:removeMonitor` diff --git a/.changeset/rotten-pugs-trade.md b/.changeset/rotten-pugs-trade.md deleted file mode 100644 index 37515336702d6..0000000000000 --- a/.changeset/rotten-pugs-trade.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@rocket.chat/meteor": patch -"@rocket.chat/tools": patch ---- - -Adds improvements to the push notifications logic; the logic now truncates messages and titles larger than 240, and 65 characters respectively. diff --git a/.changeset/selfish-countries-sleep.md b/.changeset/selfish-countries-sleep.md deleted file mode 100644 index 63227b9df6271..0000000000000 --- a/.changeset/selfish-countries-sleep.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": major ---- - -Removes deprecated Realtime API method: `livechat:getRoutingConfig` diff --git a/.changeset/seven-badgers-dress.md b/.changeset/seven-badgers-dress.md deleted file mode 100644 index 3d2b1ef6ad85b..0000000000000 --- a/.changeset/seven-badgers-dress.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": major ---- - -Removes deprecated Realtime API method: `livechat:changeLivechatStatus` diff --git a/.changeset/seven-otters-turn.md b/.changeset/seven-otters-turn.md deleted file mode 100644 index f67e3d7fe6016..0000000000000 --- a/.changeset/seven-otters-turn.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@rocket.chat/meteor": patch -"@rocket.chat/rest-typings": patch ---- - -Adds deprecation warning for `livechat:saveTag` and new endpoint to replace it; `livechat/tags.save` diff --git a/.changeset/shaggy-otters-think.md b/.changeset/shaggy-otters-think.md deleted file mode 100644 index 961fea652556b..0000000000000 --- a/.changeset/shaggy-otters-think.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': major ---- - -Removes the deprecated param `hideRoomsWithNoActivity` and adjust the api tests accordingly. Endpoint always returns rooms that are not empty. diff --git a/.changeset/sharp-beers-search.md b/.changeset/sharp-beers-search.md deleted file mode 100644 index 0b674b3318eec..0000000000000 --- a/.changeset/sharp-beers-search.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": major ---- - -Removes the deprecated `insertOrUpdateUser` meteor method diff --git a/.changeset/short-pots-lay.md b/.changeset/short-pots-lay.md deleted file mode 100644 index aa14ad39ed4eb..0000000000000 --- a/.changeset/short-pots-lay.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': major ---- - -Removes deprecated `livechat:removeTag` method diff --git a/.changeset/six-cameras-turn.md b/.changeset/six-cameras-turn.md new file mode 100644 index 0000000000000..37529a6bb0ba3 --- /dev/null +++ b/.changeset/six-cameras-turn.md @@ -0,0 +1,7 @@ +--- +'@rocket.chat/core-typings': patch +'@rocket.chat/license': patch +'@rocket.chat/meteor': patch +--- + +Fixes premium capability popup showing despite active enterprise license. diff --git a/.changeset/six-squids-pretend.md b/.changeset/six-squids-pretend.md deleted file mode 100644 index f150528ffb545..0000000000000 --- a/.changeset/six-squids-pretend.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': major ---- - -Fixes role assignment precedence in SAML provisioning, ensuring that SAML-specific default roles take priority over global registration roles, and preventing role merging when both are configured. diff --git a/.changeset/sixty-bikes-know.md b/.changeset/sixty-bikes-know.md deleted file mode 100644 index dd74fbbc1ff0c..0000000000000 --- a/.changeset/sixty-bikes-know.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Fixes an issue where the client failed to load properly when the “First Channel After Login” setting began with a hash (#), ensuring users are routed to the correct channel. diff --git a/.changeset/slimy-hairs-wink.md b/.changeset/slimy-hairs-wink.md deleted file mode 100644 index 46357b7cf4418..0000000000000 --- a/.changeset/slimy-hairs-wink.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@rocket.chat/meteor": major ---- - -Removes the deprecated setUsername method - diff --git a/.changeset/smart-carpets-clean.md b/.changeset/smart-carpets-clean.md new file mode 100644 index 0000000000000..073e969e1424f --- /dev/null +++ b/.changeset/smart-carpets-clean.md @@ -0,0 +1,5 @@ +--- +'@rocket.chat/models': patch +--- + +Fixes a condition where deleting a message with multiple file attachments would not always delete all of those files diff --git a/.changeset/smooth-birds-crash.md b/.changeset/smooth-birds-crash.md deleted file mode 100644 index 6dfe28b72b16c..0000000000000 --- a/.changeset/smooth-birds-crash.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': major ---- - -Removes deprecated `removeCannedResponse` method diff --git a/.changeset/soft-dryers-count.md b/.changeset/soft-dryers-count.md new file mode 100644 index 0000000000000..83d84ed24af30 --- /dev/null +++ b/.changeset/soft-dryers-count.md @@ -0,0 +1,5 @@ +--- +'@rocket.chat/meteor': patch +--- + +Changes users.getAvatar endpoint to prevent unauthorized access. diff --git a/.changeset/spicy-nails-design.md b/.changeset/spicy-nails-design.md deleted file mode 100644 index 23a5f82e7bb5e..0000000000000 --- a/.changeset/spicy-nails-design.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -"@rocket.chat/meteor": patch -"@rocket.chat/core-services": patch -"@rocket.chat/ddp-streamer": patch -"@rocket.chat/presence": patch ---- - -Ensures presence stays accurate by refreshing connections on heartbeats and removing stale sessions. \ No newline at end of file diff --git a/.changeset/strange-spiders-act.md b/.changeset/strange-spiders-act.md deleted file mode 100644 index 5cbdafc2f2ab9..0000000000000 --- a/.changeset/strange-spiders-act.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': major ---- - -Removes deprecated `saveCannedResponse` method diff --git a/.changeset/strong-bags-train.md b/.changeset/strong-bags-train.md deleted file mode 100644 index 3f53beead4969..0000000000000 --- a/.changeset/strong-bags-train.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@rocket.chat/meteor": patch -"@rocket.chat/federation-matrix": patch ---- - -Fixes an issue where membership updates were not reflected when the user was the first member on their own server. diff --git a/.changeset/strong-bats-swim.md b/.changeset/strong-bats-swim.md deleted file mode 100644 index d0287981e1e08..0000000000000 --- a/.changeset/strong-bats-swim.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': major ---- - -Removes deprecated `livechat:sendTranscript` method diff --git a/.changeset/strong-maps-act.md b/.changeset/strong-maps-act.md deleted file mode 100644 index 04c8c2c6c64ae..0000000000000 --- a/.changeset/strong-maps-act.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@rocket.chat/meteor": minor -"@rocket.chat/ui-voip": minor ---- - -Introduces an info button to voice call's in-chat history message, which opens a contextual bar with more detailed information about the voice call. diff --git a/.changeset/slimy-ads-sing.md b/.changeset/stupid-keys-double.md similarity index 52% rename from .changeset/slimy-ads-sing.md rename to .changeset/stupid-keys-double.md index cad18a974e9c4..76505d6ee8f69 100644 --- a/.changeset/slimy-ads-sing.md +++ b/.changeset/stupid-keys-double.md @@ -4,4 +4,4 @@ '@rocket.chat/meteor': patch --- -Fixes /v1/users.logout not marking user sessions as logged out, leaving stale sessions active. +Fixes user deletion not removing thumbnails of images sent by the deleted user diff --git a/.changeset/swift-ears-sparkle.md b/.changeset/swift-ears-sparkle.md deleted file mode 100644 index d332456dba3af..0000000000000 --- a/.changeset/swift-ears-sparkle.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@rocket.chat/meteor": major -"@rocket.chat/rest-typings": major ---- - -Removes the deprecated `/api/v1/rooms.upload` endpoint diff --git a/.changeset/ten-carrots-melt.md b/.changeset/ten-carrots-melt.md deleted file mode 100644 index 7dcb452a2f92c..0000000000000 --- a/.changeset/ten-carrots-melt.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@rocket.chat/meteor": major ---- - -Removes the deprecated livechat:resumeOnHold method - diff --git a/.changeset/tender-wolves-promise.md b/.changeset/tender-wolves-promise.md deleted file mode 100644 index 234a01290239b..0000000000000 --- a/.changeset/tender-wolves-promise.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Fixes the missing dispatch of `startup` iframe event on client startup. diff --git a/.changeset/thick-badgers-grab.md b/.changeset/thick-badgers-grab.md deleted file mode 100644 index 5cfa0235a6871..0000000000000 --- a/.changeset/thick-badgers-grab.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': major ---- - -Removes `addUserToRole` and `removeUserFromRole` type declaration and deprecation logger diff --git a/.changeset/thick-guests-compete.md b/.changeset/thick-guests-compete.md deleted file mode 100644 index 20b7fb8ca0405..0000000000000 --- a/.changeset/thick-guests-compete.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': major ---- - -Removes deprecated `livechat:saveAgentInfo` method diff --git a/.changeset/thick-wasps-turn.md b/.changeset/thick-wasps-turn.md deleted file mode 100644 index ea892a87f5556..0000000000000 --- a/.changeset/thick-wasps-turn.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Fixes inconsistency in roomLeft event payload by aligning it to the standard outgoing events signature. diff --git a/.changeset/tidy-laws-wink.md b/.changeset/tidy-laws-wink.md deleted file mode 100644 index 6a745931a3855..0000000000000 --- a/.changeset/tidy-laws-wink.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@rocket.chat/meteor": major -"@rocket.chat/rest-typings": major ---- - -Removes the deprecated `GET` Method from `/api/v1/apps` diff --git a/.changeset/tough-baboons-wash.md b/.changeset/tough-baboons-wash.md deleted file mode 100644 index b8655b4514868..0000000000000 --- a/.changeset/tough-baboons-wash.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -'@rocket.chat/rest-typings': major -'@rocket.chat/ddp-client': major -'@rocket.chat/logger': major -'@rocket.chat/meteor': major ---- - -Removes stdout logging functionality, related components and settings diff --git a/.changeset/tricky-trees-tan.md b/.changeset/tricky-trees-tan.md deleted file mode 100644 index f1cb631d720b6..0000000000000 --- a/.changeset/tricky-trees-tan.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Removes sensitive data from outgoing events debug logs. diff --git a/.changeset/twelve-feet-repeat.md b/.changeset/twelve-feet-repeat.md deleted file mode 100644 index 577096ec2b015..0000000000000 --- a/.changeset/twelve-feet-repeat.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': major ---- - -Removes deprecated 'e2e.updateGroupKey' method and related type declarations diff --git a/.changeset/twelve-forks-destroy.md b/.changeset/twelve-forks-destroy.md deleted file mode 100644 index b4cc7321bed9f..0000000000000 --- a/.changeset/twelve-forks-destroy.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@rocket.chat/meteor": patch -"@rocket.chat/i18n": patch ---- - -Adds invitation badge to sidebar diff --git a/.changeset/twelve-years-act.md b/.changeset/twelve-years-act.md deleted file mode 100644 index d118252c3fffe..0000000000000 --- a/.changeset/twelve-years-act.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -Removes deprecated method `livechat:saveBusinessHour` diff --git a/.changeset/twenty-cars-decide.md b/.changeset/twenty-cars-decide.md deleted file mode 100644 index f7ac52c68a517..0000000000000 --- a/.changeset/twenty-cars-decide.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': major ---- - -Removes deprecated `livechat:saveCustomField` method diff --git a/.changeset/two-pets-knock.md b/.changeset/two-pets-knock.md deleted file mode 100644 index c568f32c9a6ea..0000000000000 --- a/.changeset/two-pets-knock.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -"@rocket.chat/meteor": major -"@rocket.chat/rest-typings": major ---- - -Removes the deprecated roleName parameter from /api/v1/roles.addUserToRole and /api/v1/roles.removeUserFromRole - -Removes the ability to pass a role name to the role parameter type from /api/v1/roles.getUsersInRole diff --git a/.changeset/two-turtles-try.md b/.changeset/two-turtles-try.md deleted file mode 100644 index 1d8816caad368..0000000000000 --- a/.changeset/two-turtles-try.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@rocket.chat/meteor": major -"@rocket.chat/ddp-client": major ---- - -Removes the deprecated `setUserPassword` method diff --git a/.changeset/weak-frogs-relax.md b/.changeset/weak-frogs-relax.md deleted file mode 100644 index 4a19730ec1462..0000000000000 --- a/.changeset/weak-frogs-relax.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@rocket.chat/meteor": patch -"@rocket.chat/rest-typings": patch ---- - -Adds deprecation warning for `livechat:removeBusinessHour` and new endpoint to replace it; `livechat/business-hours.remove` diff --git a/.changeset/wet-papayas-buy.md b/.changeset/wet-papayas-buy.md deleted file mode 100644 index 1995c1acd95e2..0000000000000 --- a/.changeset/wet-papayas-buy.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/media-calls': patch ---- - -Fixes improper handling of errors when SIP integration is configured incorrectly diff --git a/.changeset/wet-walls-drive.md b/.changeset/wet-walls-drive.md deleted file mode 100644 index b8297000fa903..0000000000000 --- a/.changeset/wet-walls-drive.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@rocket.chat/ui-client': major -'@rocket.chat/meteor': major ---- - -Promotes Enhanced Navigation from preview state to stable. diff --git a/.changeset/wicked-yaks-join.md b/.changeset/wicked-yaks-join.md deleted file mode 100644 index 92946e56e2a8e..0000000000000 --- a/.changeset/wicked-yaks-join.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': major ---- - -Removes deprecated `livechat:takeInquiry` method diff --git a/.changeset/wild-hairs-carry.md b/.changeset/wild-hairs-carry.md deleted file mode 100644 index 9a7c69766ee80..0000000000000 --- a/.changeset/wild-hairs-carry.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": major ---- - -Removes the deprecated `authorization:addUserToRole` method diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3c36030e2b19b..7d589614476d6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -659,7 +659,7 @@ jobs: working-directory: ./ee/packages/federation-matrix env: ROCKETCHAT_IMAGE: ghcr.io/${{ needs.release-versions.outputs.lowercase-repo }}/rocket.chat:${{ needs.release-versions.outputs.gh-docker-tag }}-amd64 - ENTERPRISE_LICENSE_RC1: ZEuDWcAxkdBZ0iOzn+JIi7Ri0GKPR43hTueeqEEeTjJhzhp1jM7+fA9LiT3aCzU/oJwudwWLFAwqjrtR13axza+Us6lHuAMdfut/1Z6upRWdSgose1LfDP9Nzce6xOVbO3InQonwTQVQJotlYEGRjiry7jn68TSIKhmjMgC6SVYt6v+syEKRgj+r2oT0xNkurQYGGG1AIYHDqGWa1cX0FVd1ddOKU/DNuCJQxH8Rz5aJC2grIKMIzmRVHfBDJAipeTDl6VI28VM5ExEl3w8zDlUk8wCxXawXGCht0A7jZGCd4IQLDNZs/3Zv+nHC4lcDVzjDu+o17vUIEad4m+nhZgGTNlHqkrH3cqEEEPa3bSh8GKBzLmKHB+i0H3dweT9iqGwz56Nue7twyt5yuGq6qYdtrEx0pEKjystU15DUiQxDPqkBL8yRkp5WScsvJIlhiY+4tU6yKI/GAYtU0g+fCYzjzwxXc7tLg5NeY9kiRMdQ+jRytl3ztHGiv5ERhjQKT9ZpUWiCSCmdr8L3njfLLW1e5/AKmXpg00D6HfJvI30xDcoJwmWnCzFvd7KlSbVwNVBlD6KE9+0j6GV1h0JEml1YrpXUxbpEBz5ALdLn2iVPQ3MT5RODRI5yffSX9ikFkwcH360ewU6Zp63WKRkHyfnzE+tsYe96XdaMZowe7Lw= + ENTERPRISE_LICENSE_RC1: ZAikY+LLaal7mT6RNYxpyWEmMQyucrl50/7pYBXqHczc90j+RLwF+T0xuCT2pIpKMC5DxcZ1TtkV6MYJk5whrwmap+mQ0FV+VpILJlL0i4T21K4vMfzZXTWm/pzcAy2fMTUNH+mUA9HTBD6lYYh40KnbGXPAd80VbZk0MO/WbWBm2dOT0YCwfvlRyurRqkDAQrftLaffzCNUsMKk0fh+MKs73UDHZQDp1yvs7WoGpPu5ZVi5mTBOt3ZKVz5KjGfClLwJptFPmW1w6nKelAiJBDPpjcX1ylfjxpnBoixko7uN52zlyaeoAYwfRcdDLnZ8k0Ou6tui/vTQUXjGIjHw2AhMaKwonn4E9LYpuA1KEXt08qJL5J3ZtjSCV1T+A9Z3zFhhLgp5dxP/PPUbxDn/P8XKp7nXM9duIfcCMlnea7V8ixEyCHwwvKQaXVVidcsUGtB8CwS0GlsAEBLOzqMehuQUK2rdQ4WgEz3AYveikeVvSzgBHvyXsxssWAThc0Mht0eEJqdDhUB2QeZ2WmPsaSSD639Z4WgjSUoR0zh8bfqepH+2XRcUryXe2yN+iU+3POzi9wfg0k65MxXT8pBg3PD5RHnR8oflEP0tpZts33JiBhYRxX3MKplAFm4dMuphTsDJTh+e534pT7IPuZF79QSVaLEWZfVVVb7nGFtmMwA= QASE_TESTOPS_JEST_API_TOKEN: ${{ secrets.QASE_TESTOPS_JEST_API_TOKEN }} PR_NUMBER: ${{ github.event.number }} run: yarn test:integration --image "${ROCKETCHAT_IMAGE}" diff --git a/apps/meteor/.mocharc.js b/apps/meteor/.mocharc.js index f9f780024f964..cf4b306318cfc 100644 --- a/apps/meteor/.mocharc.js +++ b/apps/meteor/.mocharc.js @@ -28,5 +28,6 @@ module.exports = { 'tests/unit/server/**/*.spec.ts', 'app/api/server/lib/**/*.spec.ts', 'app/file-upload/server/**/*.spec.ts', + 'app/statistics/server/**/*.spec.ts', ], }; diff --git a/apps/meteor/CHANGELOG.md b/apps/meteor/CHANGELOG.md index 25c87769347a2..021d7f749b194 100644 --- a/apps/meteor/CHANGELOG.md +++ b/apps/meteor/CHANGELOG.md @@ -1,5 +1,459 @@ # @rocket.chat/meteor +## 8.0.0 + +### Major Changes + +- ([#36829](https://github.com/RocketChat/Rocket.Chat/pull/36829)) Removes the deprecated sendConfirmationEmail method + +- ([#37460](https://github.com/RocketChat/Rocket.Chat/pull/37460)) Removes deprecated `livechat:removeUnit` method + +- ([#36836](https://github.com/RocketChat/Rocket.Chat/pull/36836)) Removes the deprecated livechat:getTagsList method + + Removes the deprecated livechat:getUnitsFromUser method + + Removes the deprecated livechat:getFirstRoomMessage method + + Removes the deprecated livechat:getDepartmentForwardRestrictions method + +- ([#37672](https://github.com/RocketChat/Rocket.Chat/pull/37672)) Removes deprecated VoIP permissions + +- ([#36941](https://github.com/RocketChat/Rocket.Chat/pull/36941)) Makes Voice Calls enabled by default when available + +- ([#37672](https://github.com/RocketChat/Rocket.Chat/pull/37672)) Removes deprecated VoIP from Omnichannel + +- ([#37461](https://github.com/RocketChat/Rocket.Chat/pull/37461)) Removes deprecated `livechat:saveUnit` method + +- ([#36864](https://github.com/RocketChat/Rocket.Chat/pull/36864)) Removes the deprecated `authorization:removeUserFromRole` method + +- ([#36976](https://github.com/RocketChat/Rocket.Chat/pull/36976)) Promotes Timestamp Parser from preview state to stable + +- ([#37123](https://github.com/RocketChat/Rocket.Chat/pull/37123)) Removes ecdh functionality and related settings + +- ([#35436](https://github.com/RocketChat/Rocket.Chat/pull/35436) by [@blackmamba1231](https://github.com/blackmamba1231)) Removes deprecated `canAccessRoom` meteor method + +- ([#36925](https://github.com/RocketChat/Rocket.Chat/pull/36925) by [@lucas-a-pelegrino](https://github.com/lucas-a-pelegrino)) Removes deprecated Realtime API method: `livechat:getAnalyticsChartData` + +- ([#37392](https://github.com/RocketChat/Rocket.Chat/pull/37392)) Removes deprecated `livechat:returnAsInquiry` method + +- ([#37390](https://github.com/RocketChat/Rocket.Chat/pull/37390)) Removes deprecated `removeCustomField` method + +- ([#37672](https://github.com/RocketChat/Rocket.Chat/pull/37672)) Removes Deprecated FreeSwitch integration + +- ([#36851](https://github.com/RocketChat/Rocket.Chat/pull/36851)) Removes the deprecated `getUserRoles` method in favor of the `/v1/roles.getUsersInPublicRoles` endpoint. + +- ([#37388](https://github.com/RocketChat/Rocket.Chat/pull/37388)) Removes deprecated `setAdminStatus` method + +- ([#35961](https://github.com/RocketChat/Rocket.Chat/pull/35961)) Removes support of MongoDB versions 5.x and 6.x + +- ([#36823](https://github.com/RocketChat/Rocket.Chat/pull/36823)) Removes deprecated meteor method `muteUserInRoom` + +- ([#36825](https://github.com/RocketChat/Rocket.Chat/pull/36825)) Removes the deprecated method `createToken` + +- ([#37022](https://github.com/RocketChat/Rocket.Chat/pull/37022)) Promotes Resizable Contextualbars from preview state to stable. + +- ([#36837](https://github.com/RocketChat/Rocket.Chat/pull/36837)) Removes the deprecated `setReaction` meteor method + +- ([#36824](https://github.com/RocketChat/Rocket.Chat/pull/36824) by [@lucas-a-pelegrino](https://github.com/lucas-a-pelegrino)) Removes deprecated Realtime API method: `livechat:closeRoom` + +- ([#36832](https://github.com/RocketChat/Rocket.Chat/pull/36832)) Removes the deprecated `setCustomFields` method + +- ([#36931](https://github.com/RocketChat/Rocket.Chat/pull/36931) by [@lucas-a-pelegrino](https://github.com/lucas-a-pelegrino)) Removes deprecated Realtime API method: `livechat:removeAllClosedRooms` + +- ([#36830](https://github.com/RocketChat/Rocket.Chat/pull/36830)) Removes the deprecated `getAvatarSuggestion` method + +- ([#37462](https://github.com/RocketChat/Rocket.Chat/pull/37462)) Removes deprecated `livechat:saveDepartment` method + +- ([#37397](https://github.com/RocketChat/Rocket.Chat/pull/37397)) Removes deprecated `livechat:setUpConnection` method + +- Removes the deprecated `getRoomRoles` method + +- Removes the deprecated `authorization:deleteRole` method + +- ([#37391](https://github.com/RocketChat/Rocket.Chat/pull/37391)) Removes deprecated `livechat:removeRoom` method + +- ([#36849](https://github.com/RocketChat/Rocket.Chat/pull/36849)) Removes deprecated `appId` parameter from the `oauth-apps.get` endpoint. + +- ([#37463](https://github.com/RocketChat/Rocket.Chat/pull/37463)) Removes deprecated `sendFileLivechatMessage` method + +- ([#32590](https://github.com/RocketChat/Rocket.Chat/pull/32590)) Removes the setting `API_Use_REST_For_DDP_Calls`. Turning this on meant websocket was only used for realtime data/events, and any other meteor method calls goes over method.call endpoint. For microservice deployments, this had to be turned on. Now method calls will always happen over http endpoints. + +- ([#36966](https://github.com/RocketChat/Rocket.Chat/pull/36966)) Promotes quick reactions from preview state to stable + +- ([#36821](https://github.com/RocketChat/Rocket.Chat/pull/36821)) Removes `/api/v1/banners.getnew` deprecated endpoint + +- ([#36871](https://github.com/RocketChat/Rocket.Chat/pull/36871)) Removes the `livechat:transfer` deprecated method + Removes the `livechat/room.transfer` deprecated endpoint + Creates the `livechat/visitor.department.transfer` for visitors department transfer use +- ([#36924](https://github.com/RocketChat/Rocket.Chat/pull/36924) by [@lucas-a-pelegrino](https://github.com/lucas-a-pelegrino)) Removes deprecated Realtime API method: `livechat:getRoutingConfig` + +- ([#36809](https://github.com/RocketChat/Rocket.Chat/pull/36809) by [@lucas-a-pelegrino](https://github.com/lucas-a-pelegrino)) Removes deprecated Realtime API method: `livechat:changeLivechatStatus` + +- ([#36951](https://github.com/RocketChat/Rocket.Chat/pull/36951)) Removes the deprecated param `hideRoomsWithNoActivity` and adjust the api tests accordingly. Endpoint always returns rooms that are not empty. + +- ([#36838](https://github.com/RocketChat/Rocket.Chat/pull/36838)) Removes the deprecated `insertOrUpdateUser` meteor method + +- ([#37406](https://github.com/RocketChat/Rocket.Chat/pull/37406)) Removes deprecated `livechat:removeTag` method + +- ([#37810](https://github.com/RocketChat/Rocket.Chat/pull/37810)) Fixes role assignment precedence in SAML provisioning, ensuring that SAML-specific default roles take priority over global registration roles, and preventing role merging when both are configured. + +- ([#36831](https://github.com/RocketChat/Rocket.Chat/pull/36831)) Removes the deprecated setUsername method + +- ([#37446](https://github.com/RocketChat/Rocket.Chat/pull/37446)) Removes deprecated `removeCannedResponse` method + +- ([#37405](https://github.com/RocketChat/Rocket.Chat/pull/37405)) Removes deprecated `saveCannedResponse` method + +- ([#37396](https://github.com/RocketChat/Rocket.Chat/pull/37396)) Removes deprecated `livechat:sendTranscript` method + +- ([#36857](https://github.com/RocketChat/Rocket.Chat/pull/36857)) Removes the deprecated `/api/v1/rooms.upload` endpoint + +- ([#36908](https://github.com/RocketChat/Rocket.Chat/pull/36908)) Removes the deprecated livechat:resumeOnHold method + +- ([#36935](https://github.com/RocketChat/Rocket.Chat/pull/36935)) Removes `addUserToRole` and `removeUserFromRole` type declaration and deprecation logger + +- ([#37393](https://github.com/RocketChat/Rocket.Chat/pull/37393)) Removes deprecated `livechat:saveAgentInfo` method + +- ([#36907](https://github.com/RocketChat/Rocket.Chat/pull/36907)) Removes the deprecated `GET` Method from `/api/v1/apps` + +- ([#37114](https://github.com/RocketChat/Rocket.Chat/pull/37114)) Removes stdout logging functionality, related components and settings + +- ([#36647](https://github.com/RocketChat/Rocket.Chat/pull/36647)) Removes deprecated 'e2e.updateGroupKey' method and related type declarations + +- ([#37421](https://github.com/RocketChat/Rocket.Chat/pull/37421)) Removes deprecated `livechat:saveCustomField` method + +- ([#36896](https://github.com/RocketChat/Rocket.Chat/pull/36896)) Removes the deprecated roleName parameter from /api/v1/roles.addUserToRole and /api/v1/roles.removeUserFromRole + + Removes the ability to pass a role name to the role parameter type from /api/v1/roles.getUsersInRole + +- ([#36828](https://github.com/RocketChat/Rocket.Chat/pull/36828)) Removes the deprecated `setUserPassword` method + +- ([#37285](https://github.com/RocketChat/Rocket.Chat/pull/37285)) Promotes Enhanced Navigation from preview state to stable. + +- ([#37464](https://github.com/RocketChat/Rocket.Chat/pull/37464)) Removes deprecated `livechat:takeInquiry` method + +- ([#36865](https://github.com/RocketChat/Rocket.Chat/pull/36865)) Removes the deprecated `authorization:addUserToRole` method + +### Minor Changes + +- ([#36570](https://github.com/RocketChat/Rocket.Chat/pull/36570)) REST endpoint `/v1/users.createToken` is not deprecated anymore. It now requires a `secret` parameter to generate a token for a user. This change is part of the effort to enhance security by ensuring that tokens are generated with an additional layer of validation. The `secret` parameter is validated against a new environment variable `CREATE_TOKENS_FOR_USERS_SECRET`. + +- ([#37719](https://github.com/RocketChat/Rocket.Chat/pull/37719)) Adds a new method to the Apps-Engine that allows apps to retrieve multiple rooms from database + +- ([#37659](https://github.com/RocketChat/Rocket.Chat/pull/37659)) Changes the position of the buttons in Unique ID change detected modal in order to highlight configuration update instead of new workspace + +- ([#37233](https://github.com/RocketChat/Rocket.Chat/pull/37233)) Validates attachment fields to require `title` and `value` properties on APIs `chat.postMessage` and `chat.sendMessage`. + +- ([#37224](https://github.com/RocketChat/Rocket.Chat/pull/37224)) Enhance user's deactivated state handling to correctly distinguish between pending and deactivated users. + +- ([#37091](https://github.com/RocketChat/Rocket.Chat/pull/37091)) Adds Attribute Based Access Control (ABAC) for private channels & private teams. + +- ([#37771](https://github.com/RocketChat/Rocket.Chat/pull/37771)) Introduces an info button to voice call's in-chat history message, which opens a contextual bar with more detailed information about the voice call. + +### Patch Changes + +- ([#37663](https://github.com/RocketChat/Rocket.Chat/pull/37663) by [@lucas-a-pelegrino](https://github.com/lucas-a-pelegrino)) Removes the deprecated meteor method: `livechat:saveTag` + +- ([#37688](https://github.com/RocketChat/Rocket.Chat/pull/37688) by [@lucas-a-pelegrino](https://github.com/lucas-a-pelegrino)) Adds deprecation warning for `livechat:removeMonitor` and new endpoint replacing it; `livechat/monitor.remove` + +- ([#37690](https://github.com/RocketChat/Rocket.Chat/pull/37690) by [@lucas-a-pelegrino](https://github.com/lucas-a-pelegrino)) Adds a deprecation warning for `livechat:saveBusinessHour` and new endpoint replacing it; `livechat/business-hours.save` + +- Bump @rocket.chat/meteor version. + +- Bump @rocket.chat/meteor version. + +- Bump @rocket.chat/meteor version. + +- Bump @rocket.chat/meteor version. + +- Bump @rocket.chat/meteor version. + +- Bump @rocket.chat/meteor version. + +- ([#37612](https://github.com/RocketChat/Rocket.Chat/pull/37612)) Adds invitation request support to rooms + +- ([#37745](https://github.com/RocketChat/Rocket.Chat/pull/37745)) Fixes an issue where its not being possible to change the password in account security page + +- ([#37721](https://github.com/RocketChat/Rocket.Chat/pull/37721)) Disables read receipts indicators in federated rooms. This feature will be re-enabled when fully compatible with federation. + +- ([#37823](https://github.com/RocketChat/Rocket.Chat/pull/37823)) Fixes members tab > add members not removing selected items + +- ([#37791](https://github.com/RocketChat/Rocket.Chat/pull/37791)) Fixes an issue where cases of invites that were canceled or disinvited were not being handled. + +- ([#37874](https://github.com/RocketChat/Rocket.Chat/pull/37874)) Security Hotfix (https://docs.rocket.chat/docs/security-fixes-and-updates) + +- ([#36822](https://github.com/RocketChat/Rocket.Chat/pull/36822)) Removes deprecated meteor method `unmuteUserInRoom` + +- ([#37819](https://github.com/RocketChat/Rocket.Chat/pull/37819) by [@lucas-a-pelegrino](https://github.com/lucas-a-pelegrino)) Removes deprecated method `livechat:removeBusinessHour` + +- ([#37654](https://github.com/RocketChat/Rocket.Chat/pull/37654)) Fixes an issue that could cause slashcommands to disappear for the user in certain high-availability scenarios + +- ([#37443](https://github.com/RocketChat/Rocket.Chat/pull/37443)) Fixes an issue where custom status is not updating immediately if the value is empty + +- ([#37730](https://github.com/RocketChat/Rocket.Chat/pull/37730)) Adds an execution flag to apps-engine runtime that helps prevent the publishing of faulty builds + +- ([#37722](https://github.com/RocketChat/Rocket.Chat/pull/37722)) Fixes an issue with the build that prevented Deno runtime to run on air-gapped environments + +- ([#37504](https://github.com/RocketChat/Rocket.Chat/pull/37504)) Fixes create channel modal not validating federated access permission + +- ([#37523](https://github.com/RocketChat/Rocket.Chat/pull/37523)) Fixes license add-on validations for federated rooms + +- ([#38007](https://github.com/RocketChat/Rocket.Chat/pull/38007)) Changes the HTTP code of `/api/v1/method.call` and `/api/v1/method.callAnon` in case of internal errors + +- ([#37061](https://github.com/RocketChat/Rocket.Chat/pull/37061) by [@lucas-a-pelegrino](https://github.com/lucas-a-pelegrino)) Adds deprecation warning on `livechat:addMonitor` with new endpoint replacing it; `livechat/monitors.create` + +- ([#37713](https://github.com/RocketChat/Rocket.Chat/pull/37713)) Fixes a condition where the `SAML_Custom_Default_default_user_role` setting, used to define the default SAML role when none is provided, would fail when a role name was used instead of an ID. + +- ([#36827](https://github.com/RocketChat/Rocket.Chat/pull/36827)) Removes deprecated method `saveUserProfile` + +- ([#37643](https://github.com/RocketChat/Rocket.Chat/pull/37643)) Adds invitation badge to room members list + +- ([#37664](https://github.com/RocketChat/Rocket.Chat/pull/37664) by [@lucas-a-pelegrino](https://github.com/lucas-a-pelegrino)) Removes the deprecated meteor method: `livechat:addMonitor` + +- ([#37829](https://github.com/RocketChat/Rocket.Chat/pull/37829)) Fixes an issue where iframe external commands sent via `window.postMessage` were not being handled correctly when Rocket.Chat was embedded inside an iframe. + +- ([#37717](https://github.com/RocketChat/Rocket.Chat/pull/37717)) Fixes incorrect URL generation in Global Search "Jump to message" feature, resolving navigation issues when jumping to messages across different channels. + +- ([#37845](https://github.com/RocketChat/Rocket.Chat/pull/37845)) Fixes push notifications continuing after logout due to missing token cleanup. + +- ([#37822](https://github.com/RocketChat/Rocket.Chat/pull/37822) by [@lucas-a-pelegrino](https://github.com/lucas-a-pelegrino)) Fixes an issue where it‘s not being possible to configure department's `chatClosingTags` without enabling `requestTagBeforeClosingTag` + +- ([#37707](https://github.com/RocketChat/Rocket.Chat/pull/37707)) Fixes an issue that caused Third-party login to not work properly + +- ([#37662](https://github.com/RocketChat/Rocket.Chat/pull/37662) by [@lucas-a-pelegrino](https://github.com/lucas-a-pelegrino)) removes the deprecated meteor method: `livechat:removeMonitor` + +- ([#37852](https://github.com/RocketChat/Rocket.Chat/pull/37852) by [@lucas-a-pelegrino](https://github.com/lucas-a-pelegrino)) Adds improvements to the push notifications logic; the logic now truncates messages and titles larger than 240, and 65 characters respectively. + +- ([#37281](https://github.com/RocketChat/Rocket.Chat/pull/37281) by [@lucas-a-pelegrino](https://github.com/lucas-a-pelegrino)) Adds deprecation warning for `livechat:saveTag` and new endpoint to replace it; `livechat/tags.save` + +- ([#37656](https://github.com/RocketChat/Rocket.Chat/pull/37656)) Fixes an issue where the client failed to load properly when the “First Channel After Login” setting began with a hash (#), ensuring users are routed to the correct channel. + +- ([#37846](https://github.com/RocketChat/Rocket.Chat/pull/37846)) Fixes /v1/users.logout not marking user sessions as logged out, leaving stale sessions active. + +- ([#37551](https://github.com/RocketChat/Rocket.Chat/pull/37551)) Ensures presence stays accurate by refreshing connections on heartbeats and removing stale sessions. + +- ([#37677](https://github.com/RocketChat/Rocket.Chat/pull/37677)) Fixes an issue where membership updates were not reflected when the user was the first member on their own server. + +- ([#37718](https://github.com/RocketChat/Rocket.Chat/pull/37718)) Fixes the missing dispatch of `startup` iframe event on client startup. + +- ([#37729](https://github.com/RocketChat/Rocket.Chat/pull/37729)) Fixes inconsistency in roomLeft event payload by aligning it to the standard outgoing events signature. + +- ([#37729](https://github.com/RocketChat/Rocket.Chat/pull/37729)) Removes sensitive data from outgoing events debug logs. + +- ([#37635](https://github.com/RocketChat/Rocket.Chat/pull/37635)) Adds invitation badge to sidebar + +- ([#37772](https://github.com/RocketChat/Rocket.Chat/pull/37772) by [@lucas-a-pelegrino](https://github.com/lucas-a-pelegrino)) Removes deprecated method `livechat:saveBusinessHour` + +- ([#37775](https://github.com/RocketChat/Rocket.Chat/pull/37775) by [@lucas-a-pelegrino](https://github.com/lucas-a-pelegrino)) Adds deprecation warning for `livechat:removeBusinessHour` and new endpoint to replace it; `livechat/business-hours.remove` + +-
Updated dependencies [347b8f973440f3e2239f79c00c2d9b430859eef2, 04d24848bd8733caefc45d42c53f004177865a53, b802430fbfdc7fa69a976468dc6dee6f3c4de26f, 872da49986436d2efa65fc42e416b45d706fd59c, 0ccb9692b434bc88b4bc5009d39e024c03f01b86, 176d5eae3fb249d7d20c3e260d9fadc1a56a2fca, ac11ea05ffadeca978c794ff38d5199d9acb2c29, 2de4547580c472f4458568629d7bf98fd5faf342, ac11ea05ffadeca978c794ff38d5199d9acb2c29, 1baa03cced8f94584da1224ad59cad86f219707a, 0c0258604632342f42fc36cabac2d6cfe0e477c4, f3f0b273ab49e9d1048ba43d52eb36005274905e, ac11ea05ffadeca978c794ff38d5199d9acb2c29, a1d65f493fdb039d34ef4f65d243a97931763f4b, 70872896b912004dc016297b6e875d873d81dc3a, bd5edfc2993c93bd77f42dcd30d38b57eeb50481, 94b87d9ef40647d77fe83f3f84dca46a94515b39, ddc935727e9a7275813006d9dcaa7fe866610844, 733c94b996204151f580de2dd7f3402124b70977, d3538e7045c41f91b8c561d44e5485ff93b93745, a5a7343a835b04812c70699be1b13e54f0e10d48, 73d9eb2783176954f42aa2cbeda8abf1d49ac260, 611e4cdfa04849416a58071646b853b95e9b817b, 476a070b0099b95e4c463ee85960c4dcfbd87120, 239f4b1171bcf448cfba345cc90c4b5cd7c21afc, 9e03ed5c5ea829c62c2da2de9413a27a4696f8a3, dc67590d14d510b069dee074c55314c56f74bb11, be80b724a636877294b5e5baa501d070941131dd, 4aa3634186d97f4144c39f6b42a65107d3d30df0, 4793aca8796d8a3b4c645a2ed685028067119d8d, 0b660a5933b137ae142d78318d8c4022f1f4f1ca, dccdcc5b4a0da4814f72a020bc4eccb8ea2497d8, 5ac1863be4c6e82666989f4b569928c0805691ff, ec0f8b435dd12c218adffa8892737c7ced4debb8, f056c451c2926e849f52b95fed957945398ef5f6, cb3c5e3455606a045f95f168dae6ed32a387697c, ae1e2faaeb6f7a086f8affde4c8a81e55e2a0e04, 5b3f93c47a03b628d613a77005e92021cd6cee4b, 8bf0bab1eb84f903976b7833691d17236eac8dcd, 55dc368f3f679e93bffb9f04efe3944832cf3336]: + + - @rocket.chat/rest-typings@8.0.0 + - @rocket.chat/web-ui-registration@26.0.0 + - @rocket.chat/apps-engine@1.59.0 + - @rocket.chat/apps@0.6.0 + - @rocket.chat/core-typings@8.0.0 + - @rocket.chat/i18n@2.0.0 + - @rocket.chat/media-calls@0.2.0 + - @rocket.chat/model-typings@2.0.0 + - @rocket.chat/ui-contexts@26.0.0 + - @rocket.chat/ui-voip@16.0.0 + - @rocket.chat/models@2.0.0 + - @rocket.chat/core-services@0.12.0 + - @rocket.chat/message-types@0.1.0 + - @rocket.chat/federation-matrix@0.0.9 + - @rocket.chat/gazzodown@26.0.0 + - @rocket.chat/ui-client@26.0.0 + - @rocket.chat/fuselage-ui-kit@26.0.0 + - @rocket.chat/media-signaling@0.1.1 + - @rocket.chat/ui-kit@0.39.0 + - @rocket.chat/abac@0.1.0 + - @rocket.chat/jwt@0.2.0 + - @rocket.chat/tools@0.2.4 + - @rocket.chat/presence@0.2.47 + - @rocket.chat/logger@1.0.0 + - @rocket.chat/omnichannel-services@0.3.44 + - @rocket.chat/api-client@0.2.47 + - @rocket.chat/http-router@7.9.14 + - @rocket.chat/license@1.1.7 + - @rocket.chat/pdf-worker@0.3.26 + - @rocket.chat/cron@0.1.47 + - @rocket.chat/ui-avatar@22.0.0 + - @rocket.chat/ui-theming@0.4.4 + - @rocket.chat/ui-video-conf@26.0.0 + - @rocket.chat/omni-core-ee@0.0.12 + - @rocket.chat/instance-status@0.1.47 + - @rocket.chat/omni-core@0.0.12 + - @rocket.chat/network-broker@0.2.26 + - @rocket.chat/server-cloud-communication@0.0.2 +
+ +## 8.0.0-rc.5 + +### Patch Changes + +- Bump @rocket.chat/meteor version. + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.0.0-rc.5 + - @rocket.chat/rest-typings@8.0.0-rc.5 + - @rocket.chat/abac@0.1.0-rc.5 + - @rocket.chat/federation-matrix@0.0.9-rc.5 + - @rocket.chat/license@1.1.7-rc.5 + - @rocket.chat/media-calls@0.2.0-rc.5 + - @rocket.chat/omnichannel-services@0.3.44-rc.5 + - @rocket.chat/pdf-worker@0.3.26-rc.5 + - @rocket.chat/presence@0.2.47-rc.5 + - @rocket.chat/api-client@0.2.47-rc.5 + - @rocket.chat/apps@0.6.0-rc.5 + - @rocket.chat/core-services@0.12.0-rc.5 + - @rocket.chat/cron@0.1.47-rc.5 + - @rocket.chat/fuselage-ui-kit@26.0.0-rc.5 + - @rocket.chat/gazzodown@26.0.0-rc.5 + - @rocket.chat/http-router@7.9.14-rc.5 + - @rocket.chat/message-types@0.1.0-rc.0 + - @rocket.chat/model-typings@2.0.0-rc.5 + - @rocket.chat/ui-avatar@22.0.0-rc.5 + - @rocket.chat/ui-client@26.0.0-rc.5 + - @rocket.chat/ui-contexts@26.0.0-rc.5 + - @rocket.chat/ui-voip@16.0.0-rc.5 + - @rocket.chat/web-ui-registration@26.0.0-rc.5 + - @rocket.chat/models@2.0.0-rc.5 + - @rocket.chat/server-cloud-communication@0.0.2 + - @rocket.chat/network-broker@0.2.26-rc.5 + - @rocket.chat/omni-core-ee@0.0.12-rc.5 + - @rocket.chat/ui-theming@0.4.4 + - @rocket.chat/ui-video-conf@26.0.0-rc.5 + - @rocket.chat/instance-status@0.1.47-rc.5 + - @rocket.chat/omni-core@0.0.12-rc.5 +
+ +## 8.0.0-rc.4 + +### Patch Changes + +- Bump @rocket.chat/meteor version. + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.0.0-rc.4 + - @rocket.chat/rest-typings@8.0.0-rc.4 + - @rocket.chat/abac@0.1.0-rc.4 + - @rocket.chat/federation-matrix@0.0.9-rc.4 + - @rocket.chat/license@1.1.7-rc.4 + - @rocket.chat/media-calls@0.2.0-rc.4 + - @rocket.chat/omnichannel-services@0.3.44-rc.4 + - @rocket.chat/pdf-worker@0.3.26-rc.4 + - @rocket.chat/presence@0.2.47-rc.4 + - @rocket.chat/api-client@0.2.47-rc.4 + - @rocket.chat/apps@0.6.0-rc.4 + - @rocket.chat/core-services@0.12.0-rc.4 + - @rocket.chat/cron@0.1.47-rc.4 + - @rocket.chat/fuselage-ui-kit@26.0.0-rc.4 + - @rocket.chat/gazzodown@26.0.0-rc.4 + - @rocket.chat/http-router@7.9.14-rc.4 + - @rocket.chat/message-types@0.1.0-rc.0 + - @rocket.chat/model-typings@2.0.0-rc.4 + - @rocket.chat/ui-avatar@22.0.0-rc.4 + - @rocket.chat/ui-client@26.0.0-rc.4 + - @rocket.chat/ui-contexts@26.0.0-rc.4 + - @rocket.chat/ui-voip@16.0.0-rc.4 + - @rocket.chat/web-ui-registration@26.0.0-rc.4 + - @rocket.chat/models@2.0.0-rc.4 + - @rocket.chat/server-cloud-communication@0.0.2 + - @rocket.chat/network-broker@0.2.26-rc.4 + - @rocket.chat/omni-core-ee@0.0.12-rc.4 + - @rocket.chat/ui-theming@0.4.4 + - @rocket.chat/ui-video-conf@26.0.0-rc.4 + - @rocket.chat/instance-status@0.1.47-rc.4 + - @rocket.chat/omni-core@0.0.12-rc.4 +
+ +## 8.0.0-rc.3 + +### Patch Changes + +- Bump @rocket.chat/meteor version. + +-
Updated dependencies [ae1e2faaeb6f7a086f8affde4c8a81e55e2a0e04]: + + - @rocket.chat/media-signaling@0.1.1-rc.1 + - @rocket.chat/media-calls@0.2.0-rc.3 + - @rocket.chat/core-services@0.12.0-rc.3 + - @rocket.chat/ui-voip@16.0.0-rc.3 + - @rocket.chat/abac@0.1.0-rc.3 + - @rocket.chat/federation-matrix@0.0.9-rc.3 + - @rocket.chat/network-broker@0.2.26-rc.3 + - @rocket.chat/omni-core-ee@0.0.12-rc.3 + - @rocket.chat/omnichannel-services@0.3.44-rc.3 + - @rocket.chat/presence@0.2.47-rc.3 + - @rocket.chat/ui-contexts@26.0.0-rc.3 + - @rocket.chat/ui-theming@0.4.4 + - @rocket.chat/fuselage-ui-kit@26.0.0-rc.3 + - @rocket.chat/gazzodown@26.0.0-rc.3 + - @rocket.chat/ui-avatar@22.0.0-rc.3 + - @rocket.chat/ui-client@26.0.0-rc.3 + - @rocket.chat/ui-video-conf@26.0.0-rc.3 + - @rocket.chat/web-ui-registration@26.0.0-rc.3 + - @rocket.chat/core-typings@8.0.0-rc.3 + - @rocket.chat/rest-typings@8.0.0-rc.3 + - @rocket.chat/license@1.1.7-rc.3 + - @rocket.chat/pdf-worker@0.3.26-rc.3 + - @rocket.chat/api-client@0.2.47-rc.3 + - @rocket.chat/apps@0.6.0-rc.3 + - @rocket.chat/cron@0.1.47-rc.3 + - @rocket.chat/http-router@7.9.14-rc.3 + - @rocket.chat/message-types@0.1.0-rc.0 + - @rocket.chat/model-typings@2.0.0-rc.3 + - @rocket.chat/models@2.0.0-rc.3 + - @rocket.chat/server-cloud-communication@0.0.2 + - @rocket.chat/instance-status@0.1.47-rc.3 + - @rocket.chat/omni-core@0.0.12-rc.3 +
+ +## 8.0.0-rc.2 + +### Patch Changes + +- Bump @rocket.chat/meteor version. + +- ([#38007](https://github.com/RocketChat/Rocket.Chat/pull/38007)) Changes the HTTP code of `/api/v1/method.call` and `/api/v1/method.callAnon` in case of internal errors + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.0.0-rc.2 + - @rocket.chat/rest-typings@8.0.0-rc.2 + - @rocket.chat/abac@0.1.0-rc.2 + - @rocket.chat/federation-matrix@0.0.9-rc.2 + - @rocket.chat/license@1.1.7-rc.2 + - @rocket.chat/media-calls@0.2.0-rc.2 + - @rocket.chat/omnichannel-services@0.3.44-rc.2 + - @rocket.chat/pdf-worker@0.3.26-rc.2 + - @rocket.chat/presence@0.2.47-rc.2 + - @rocket.chat/api-client@0.2.47-rc.2 + - @rocket.chat/apps@0.6.0-rc.2 + - @rocket.chat/core-services@0.12.0-rc.2 + - @rocket.chat/cron@0.1.47-rc.2 + - @rocket.chat/fuselage-ui-kit@26.0.0-rc.2 + - @rocket.chat/gazzodown@26.0.0-rc.2 + - @rocket.chat/http-router@7.9.14-rc.2 + - @rocket.chat/message-types@0.1.0-rc.0 + - @rocket.chat/model-typings@2.0.0-rc.2 + - @rocket.chat/ui-avatar@22.0.0-rc.2 + - @rocket.chat/ui-client@26.0.0-rc.2 + - @rocket.chat/ui-contexts@26.0.0-rc.2 + - @rocket.chat/ui-voip@16.0.0-rc.2 + - @rocket.chat/web-ui-registration@26.0.0-rc.2 + - @rocket.chat/models@2.0.0-rc.2 + - @rocket.chat/server-cloud-communication@0.0.2 + - @rocket.chat/network-broker@0.2.26-rc.2 + - @rocket.chat/omni-core-ee@0.0.12-rc.2 + - @rocket.chat/ui-theming@0.4.4 + - @rocket.chat/ui-video-conf@26.0.0-rc.2 + - @rocket.chat/instance-status@0.1.47-rc.2 + - @rocket.chat/omni-core@0.0.12-rc.2 +
+ ## 8.0.0-rc.1 ### Patch Changes diff --git a/apps/meteor/app/api/server/ApiClass.ts b/apps/meteor/app/api/server/ApiClass.ts index 60af03b031fdc..3da37938ed43c 100644 --- a/apps/meteor/app/api/server/ApiClass.ts +++ b/apps/meteor/app/api/server/ApiClass.ts @@ -37,6 +37,7 @@ import type { RedirectResult, UnavailableResult, GenericRouteExecutionContext, + TooManyRequestsResult, } from './definition'; import { getUserInfo } from './helpers/getUserInfo'; import { parseJsonQuery } from './helpers/parseJsonQuery'; @@ -383,7 +384,7 @@ export class APIClass & { success?: boolean } } { + public tooManyRequests(msg?: T): TooManyRequestsResult { return { statusCode: 429, body: { diff --git a/apps/meteor/app/api/server/definition.ts b/apps/meteor/app/api/server/definition.ts index 478acc01d0252..9684b99c798c8 100644 --- a/apps/meteor/app/api/server/definition.ts +++ b/apps/meteor/app/api/server/definition.ts @@ -56,6 +56,14 @@ export type ForbiddenResult = { }; }; +export type TooManyRequestsResult = { + statusCode: 429; + body: { + success: false; + error: T | 'Too many requests'; + }; +}; + export type InternalError = { statusCode: StatusCode; body: { diff --git a/apps/meteor/app/api/server/lib/getUploadFormData.spec.ts b/apps/meteor/app/api/server/lib/getUploadFormData.spec.ts index 49cd58fd8ab1f..bcca1cf795f67 100644 --- a/apps/meteor/app/api/server/lib/getUploadFormData.spec.ts +++ b/apps/meteor/app/api/server/lib/getUploadFormData.spec.ts @@ -12,6 +12,7 @@ const createMockRequest = ( content: string | Buffer; mimetype?: string; }, + options: { simulateError?: boolean } = {}, ): Request => { const boundary = '----WebKitFormBoundary7MA4YWxkTrZu0gW'; const parts: string[] = []; @@ -40,6 +41,10 @@ const createMockRequest = ( }, body: new ReadableStream({ async pull(controller) { + if (options.simulateError) { + controller.error(new Error('aborted')); + return; + } controller.enqueue(buffer); controller.close(); }, @@ -177,4 +182,15 @@ describe('getUploadFormData', () => { expect((error as Error).message).to.equal('[error-file-too-large]'); } }); + + it('should handle an aborted request stream', async () => { + const mockRequest = createMockRequest({}, undefined, { simulateError: true }); + + try { + await getUploadFormData({ request: mockRequest }, { fileOptional: true }); + throw new Error('Expected function to throw'); + } catch (error) { + expect((error as Error).message).to.equal('aborted'); + } + }); }); diff --git a/apps/meteor/app/api/server/lib/getUploadFormData.ts b/apps/meteor/app/api/server/lib/getUploadFormData.ts index cf797ebf70af8..5841a5b58c32b 100644 --- a/apps/meteor/app/api/server/lib/getUploadFormData.ts +++ b/apps/meteor/app/api/server/lib/getUploadFormData.ts @@ -165,7 +165,9 @@ export async function getUploadFormData< }); // Unclear why typescript complains that the ReadableStream from request.body is incompatible here - Readable.fromWeb(request.body satisfies ReadableStream).pipe(bb); + Readable.fromWeb(request.body satisfies ReadableStream) + .on('error', (err) => reject(err)) + .pipe(bb); return resultPromise; } diff --git a/apps/meteor/app/api/server/v1/channels.ts b/apps/meteor/app/api/server/v1/channels.ts index b5574e239ee4b..578a741efd52f 100644 --- a/apps/meteor/app/api/server/v1/channels.ts +++ b/apps/meteor/app/api/server/v1/channels.ts @@ -807,7 +807,7 @@ API.v1.addRoute( { authRequired: true, validateParams: isChannelsFilesListProps }, { async get() { - const { typeGroup, name, roomId, roomName } = this.queryParams; + const { typeGroup, name, roomId, roomName, onlyConfirmed } = this.queryParams; const findResult = await findChannelByIdOrName({ params: { @@ -829,6 +829,7 @@ API.v1.addRoute( ...query, ...(name ? { name: { $regex: name || '', $options: 'i' } } : {}), ...(typeGroup ? { typeGroup } : {}), + ...(onlyConfirmed && { expiresAt: { $exists: false } }), }; const { cursor, totalCount } = await Uploads.findPaginatedWithoutThumbs(filter, { diff --git a/apps/meteor/app/api/server/v1/chat.ts b/apps/meteor/app/api/server/v1/chat.ts index 5a6707beb6a10..9884afc7e7367 100644 --- a/apps/meteor/app/api/server/v1/chat.ts +++ b/apps/meteor/app/api/server/v1/chat.ts @@ -291,7 +291,7 @@ const chatEndpoints = API.v1 200: ajv.compile<{ message: IMessage }>({ type: 'object', properties: { - message: { $ref: '#/components/schemas/IMessage' }, + message: { type: 'object' }, success: { type: 'boolean', enum: [true], @@ -434,7 +434,7 @@ API.v1.addRoute( } const sent = await applyAirGappedRestrictionsValidation(() => - executeSendMessage(this.userId, this.bodyParams.message as Pick, this.bodyParams.previewUrls), + executeSendMessage(this.userId, this.bodyParams.message as Pick, { previewUrls: this.bodyParams.previewUrls }), ); const [message] = await normalizeMessagesForUser([sent], this.userId); @@ -456,7 +456,7 @@ API.v1.addRoute( throw new Meteor.Error('error-message-not-found', 'The provided "messageId" does not match any existing message.'); } - await starMessage(this.userId, { + await starMessage(this.user, { _id: msg._id, rid: msg.rid, starred: true, @@ -478,7 +478,7 @@ API.v1.addRoute( throw new Meteor.Error('error-message-not-found', 'The provided "messageId" does not match any existing message.'); } - await starMessage(this.userId, { + await starMessage(this.user, { _id: msg._id, rid: msg.rid, starred: false, diff --git a/apps/meteor/app/api/server/v1/groups.ts b/apps/meteor/app/api/server/v1/groups.ts index 311e383232171..72ea8402d4c0c 100644 --- a/apps/meteor/app/api/server/v1/groups.ts +++ b/apps/meteor/app/api/server/v1/groups.ts @@ -392,7 +392,7 @@ API.v1.addRoute( { authRequired: true, validateParams: isGroupsFilesProps }, { async get() { - const { typeGroup, name, roomId, roomName } = this.queryParams; + const { typeGroup, name, roomId, roomName, onlyConfirmed } = this.queryParams; const findResult = await findPrivateGroupByIdOrName({ params: roomId ? { roomId } : { roomName }, @@ -408,6 +408,7 @@ API.v1.addRoute( rid: findResult.rid, ...(name ? { name: { $regex: name || '', $options: 'i' } } : {}), ...(typeGroup ? { typeGroup } : {}), + ...(onlyConfirmed && { expiresAt: { $exists: false } }), }; const { cursor, totalCount } = await Uploads.findPaginatedWithoutThumbs(filter, { diff --git a/apps/meteor/app/api/server/v1/im.ts b/apps/meteor/app/api/server/v1/im.ts index b7251e67b1829..2e13de8023259 100644 --- a/apps/meteor/app/api/server/v1/im.ts +++ b/apps/meteor/app/api/server/v1/im.ts @@ -279,7 +279,7 @@ API.v1.addRoute( }, { async get() { - const { typeGroup, name, roomId, username } = this.queryParams; + const { typeGroup, name, roomId, username, onlyConfirmed } = this.queryParams; const { offset, count } = await getPaginationItems(this.queryParams); const { sort, fields, query } = await this.parseJsonQuery(); @@ -296,6 +296,7 @@ API.v1.addRoute( rid: room._id, ...(name ? { name: { $regex: name || '', $options: 'i' } } : {}), ...(typeGroup ? { typeGroup } : {}), + ...(onlyConfirmed && { expiresAt: { $exists: false } }), }; const { cursor, totalCount } = Uploads.findPaginatedWithoutThumbs(filter, { diff --git a/apps/meteor/app/api/server/v1/misc.ts b/apps/meteor/app/api/server/v1/misc.ts index 75803bbed759d..403ffcc29b4ce 100644 --- a/apps/meteor/app/api/server/v1/misc.ts +++ b/apps/meteor/app/api/server/v1/misc.ts @@ -525,7 +525,8 @@ API.v1.addRoute( if (settings.get('Log_Level') === '2') { Meteor._debug(`Exception while invoking method ${method}`, err); } - return API.v1.success(mountResult({ id, error: err })); + + return API.v1.failure(mountResult({ id, error: err })); } }, }, @@ -580,7 +581,7 @@ API.v1.addRoute( if (settings.get('Log_Level') === '2') { Meteor._debug(`Exception while invoking method ${method}`, err); } - return API.v1.success(mountResult({ id, error: err })); + return API.v1.failure(mountResult({ id, error: err })); } }, }, diff --git a/apps/meteor/app/api/server/v1/users.ts b/apps/meteor/app/api/server/v1/users.ts index e567970508438..fd546426e84b5 100644 --- a/apps/meteor/app/api/server/v1/users.ts +++ b/apps/meteor/app/api/server/v1/users.ts @@ -81,7 +81,7 @@ import { findPaginatedUsersByStatus, findUsersToAutocomplete, getInclusiveFields API.v1.addRoute( 'users.getAvatar', - { authRequired: false }, + { authRequired: true }, { async get() { const user = await getUserFromParams(this.queryParams); diff --git a/apps/meteor/app/authentication/server/lib/restrictLoginAttempts.ts b/apps/meteor/app/authentication/server/lib/restrictLoginAttempts.ts index 3b6cd6c894090..6f260c8a129c0 100644 --- a/apps/meteor/app/authentication/server/lib/restrictLoginAttempts.ts +++ b/apps/meteor/app/authentication/server/lib/restrictLoginAttempts.ts @@ -22,7 +22,7 @@ const notifyFailedLogin = async (ipOrUsername: string, blockedUntil: Date, faile // to avoid issues when "fname" is presented in the UI, check if the name matches it as well const room = await Rooms.findOneByNameOrFname(channelToNotify); if (!room) { - logger.error("Cannot notify failed logins: channel provided doesn't exists"); + logger.error({ msg: 'Cannot notify failed logins: channel provided does not exist', channelToNotify }); return; } diff --git a/apps/meteor/app/authentication/server/startup/index.js b/apps/meteor/app/authentication/server/startup/index.js index 12825cde0f678..13f757b37bc38 100644 --- a/apps/meteor/app/authentication/server/startup/index.js +++ b/apps/meteor/app/authentication/server/startup/index.js @@ -381,7 +381,7 @@ Accounts.insertUserDoc = async function (options, user) { if (!options.skipAppsEngineEvent) { // `post` triggered events don't need to wait for the promise to resolve Apps.self?.triggerEvent(AppEvents.IPostUserCreated, { user, performedBy: await safeGetMeteorUser() }).catch((e) => { - Apps.self?.getRocketChatLogger().error('Error while executing post user created event:', e); + Apps.self?.getRocketChatLogger().error({ msg: 'Error while executing post user created event', err: e }); }); } diff --git a/apps/meteor/app/custom-oauth/server/custom_oauth_server.js b/apps/meteor/app/custom-oauth/server/custom_oauth_server.js index f25405c8b14a0..b9071709f2cce 100644 --- a/apps/meteor/app/custom-oauth/server/custom_oauth_server.js +++ b/apps/meteor/app/custom-oauth/server/custom_oauth_server.js @@ -25,7 +25,7 @@ const BeforeUpdateOrCreateUserFromExternalService = []; export class CustomOAuth { constructor(name, options) { - logger.debug('Init CustomOAuth', name, options); + logger.debug({ msg: 'Init CustomOAuth', name, options }); this.name = name; if (!Match.test(this.name, String)) { @@ -307,7 +307,7 @@ export class CustomOAuth { const value = fromTemplate(this.avatarField, data); if (!value) { - logger.debug(`Avatar field "${this.avatarField}" not found in data`, data); + logger.debug({ msg: 'Avatar field not found in data', avatarField: this.avatarField, data }); } return value; } catch (error) { diff --git a/apps/meteor/app/integrations/server/api/api.ts b/apps/meteor/app/integrations/server/api/api.ts index 00bf1d911f565..8e1a37c8e76fa 100644 --- a/apps/meteor/app/integrations/server/api/api.ts +++ b/apps/meteor/app/integrations/server/api/api.ts @@ -14,11 +14,15 @@ import { APIClass } from '../../../api/server/ApiClass'; import type { RateLimiterOptions } from '../../../api/server/api'; import { API, defaultRateLimiterOptions } from '../../../api/server/api'; import type { FailureResult, GenericRouteExecutionContext, SuccessResult, UnavailableResult } from '../../../api/server/definition'; +import { loggerMiddleware } from '../../../api/server/middlewares/logger'; +import { metricsMiddleware } from '../../../api/server/middlewares/metrics'; +import { tracerSpanMiddleware } from '../../../api/server/middlewares/tracer'; import type { WebhookResponseItem } from '../../../lib/server/functions/processWebhookMessage'; import { processWebhookMessage } from '../../../lib/server/functions/processWebhookMessage'; +import { metrics } from '../../../metrics/server'; import { settings } from '../../../settings/server'; import { IsolatedVMScriptEngine } from '../lib/isolated-vm/isolated-vm'; -import { incomingLogger } from '../logger'; +import { incomingLogger, integrationLogger } from '../logger'; import { addOutgoingIntegration } from '../methods/outgoing/addOutgoingIntegration'; import { deleteOutgoingIntegration } from '../methods/outgoing/deleteOutgoingIntegration'; @@ -247,8 +251,9 @@ async function executeIntegrationRest( return API.v1.success({ responses: messageResponse }); } return API.v1.success(); - } catch ({ error, message }: any) { - return API.v1.failure(error || message); + } catch (err: any) { + incomingLogger.error({ msg: 'Error processing webhook message', err }); + return API.v1.failure(err?.error || err?.message || 'Unknown error'); } } @@ -378,6 +383,11 @@ const Api = new WebHookAPI({ prettyJson: process.env.NODE_ENV === 'development', }); +Api.router + .use(loggerMiddleware(integrationLogger)) + .use(metricsMiddleware({ basePathRegex: new RegExp(/^\/hooks\//), api: Api, settings, summary: metrics.rocketchatRestApi })) + .use(tracerSpanMiddleware); + const middleware = async (c: Context, next: Next): Promise => { const { req } = c; if (req.raw.headers.get('content-type') !== 'application/x-www-form-urlencoded') { diff --git a/apps/meteor/app/integrations/server/lib/ScriptEngine.ts b/apps/meteor/app/integrations/server/lib/ScriptEngine.ts index 9a177029f26dd..906dbcd4024f3 100644 --- a/apps/meteor/app/integrations/server/lib/ScriptEngine.ts +++ b/apps/meteor/app/integrations/server/lib/ScriptEngine.ts @@ -276,7 +276,11 @@ export abstract class IntegrationScriptEngine { } if (!script[method]) { - this.logger.error(`Method "${method}" not found in the Integration "${integration.name}"`); + this.logger.error({ + msg: 'Script method not found in the Integration', + method, + integration: integration.name, + }); await updateHistory({ historyId, step: `execute-script-no-method-${method}` }); return; } @@ -327,12 +331,20 @@ export abstract class IntegrationScriptEngine { } const script = await wrapExceptions(() => this.getIntegrationScript(integration)).catch((e) => { - this.logger.error(e); + this.logger.error({ + msg: 'Error getting Integration script', + integration: integration.name, + err: e, + }); throw e; }); if (!script[method]) { - this.logger.error(`Method "${method}" not found in the Integration "${integration.name}"`); + this.logger.error({ + msg: 'Script method not found in the Integration', + method, + integration: integration.name, + }); return; } diff --git a/apps/meteor/app/integrations/server/logger.ts b/apps/meteor/app/integrations/server/logger.ts index 47da6bcf22c51..73c77ccebac2d 100644 --- a/apps/meteor/app/integrations/server/logger.ts +++ b/apps/meteor/app/integrations/server/logger.ts @@ -1,6 +1,6 @@ import { Logger } from '@rocket.chat/logger'; -const logger = new Logger('Integrations'); +export const integrationLogger = new Logger('Integrations'); -export const incomingLogger = logger.section('Incoming WebHook'); -export const outgoingLogger = logger.section('Outgoing WebHook'); +export const incomingLogger = integrationLogger.section('Incoming WebHook'); +export const outgoingLogger = integrationLogger.section('Outgoing WebHook'); diff --git a/apps/meteor/app/irc/server/irc-bridge/index.js b/apps/meteor/app/irc/server/irc-bridge/index.js index b86dff943e45f..25f6b5b9f0a29 100644 --- a/apps/meteor/app/irc/server/irc-bridge/index.js +++ b/apps/meteor/app/irc/server/irc-bridge/index.js @@ -135,7 +135,7 @@ class Bridge { // Get the command const item = this.queue.dequeue(); - this.logQueue(`Processing "${item.command}" command from "${item.from}"`); + this.logQueue({ msg: 'Processing command from source', command: item.command, from: item.from }); // Handle the command accordingly try { diff --git a/apps/meteor/app/irc/server/servers/RFC2813/index.js b/apps/meteor/app/irc/server/servers/RFC2813/index.js index 8c5b8abf19c84..531338d939827 100644 --- a/apps/meteor/app/irc/server/servers/RFC2813/index.js +++ b/apps/meteor/app/irc/server/servers/RFC2813/index.js @@ -39,9 +39,9 @@ class RFC2813 { this.socket.on('data', this.onReceiveFromPeer.bind(this)); this.socket.on('connect', this.onConnect.bind(this)); - this.socket.on('error', (err) => logger.error(err)); - this.socket.on('timeout', () => this.log('Timeout')); - this.socket.on('close', () => this.log('Connection Closed')); + this.socket.on('error', (err) => logger.error({ msg: 'Socket error', err })); + this.socket.on('timeout', () => this.log({ msg: 'Timeout' })); + this.socket.on('close', () => this.log({ msg: 'Connection Closed' })); // Setup local this.on('onReceiveFromLocal', this.onReceiveFromLocal.bind(this)); } @@ -51,6 +51,11 @@ class RFC2813 { */ log(message) { // TODO logger: debug? + if (typeof message === 'string') { + logger.info({ msg: message }); + return; + } + logger.info(message); } @@ -58,7 +63,11 @@ class RFC2813 { * Connect */ register() { - this.log(`Connecting to @${this.config.server.host}:${this.config.server.port}`); + this.log({ + msg: 'Connecting to IRC server', + host: this.config.server.host, + port: this.config.server.port, + }); if (!this.socket) { this.setupSocket(); @@ -114,7 +123,7 @@ class RFC2813 { buffer += ` :${command.trailer}`; } - this.log(`Sending Command: ${buffer}`); + this.log({ msg: 'Sending Command', buffer }); return this.socket.write(`${buffer}\r\n`); } @@ -148,7 +157,7 @@ class RFC2813 { const parsedMessage = parseMessage(line); if (peerCommandHandlers[parsedMessage.command]) { - this.log(`Handling peer message: ${line}`); + this.log({ msg: 'Handling peer message', line }); const command = peerCommandHandlers[parsedMessage.command].call(this, parsedMessage); @@ -172,7 +181,7 @@ class RFC2813 { */ onReceiveFromLocal(command, parameters) { if (localCommandHandlers[command]) { - this.log(`Handling local command: ${command}`); + this.log({ msg: 'Handling local command', command }); localCommandHandlers[command].call(this, parameters, this); } else { diff --git a/apps/meteor/app/lib/client/methods/sendMessage.ts b/apps/meteor/app/lib/client/methods/sendMessage.ts index 0969ea8d9cf36..ee67688a0b6ae 100644 --- a/apps/meteor/app/lib/client/methods/sendMessage.ts +++ b/apps/meteor/app/lib/client/methods/sendMessage.ts @@ -44,7 +44,13 @@ Meteor.methods({ await onClientMessageReceived(message as IMessage).then((message) => { Messages.state.store(message); - return clientCallbacks.run('afterSaveMessage', message, { room, user }); + void clientCallbacks.run('afterSaveMessage', message, { room, user }); + + // Now that the message is stored, we can go ahead and mark as sent + Messages.state.update( + (record) => record._id === message._id && record.temp === true, + ({ temp: _, ...record }) => record, + ); }); }, }); diff --git a/apps/meteor/app/lib/server/functions/createRoom.ts b/apps/meteor/app/lib/server/functions/createRoom.ts index bb99ae7237f19..7b64ec9e68b09 100644 --- a/apps/meteor/app/lib/server/functions/createRoom.ts +++ b/apps/meteor/app/lib/server/functions/createRoom.ts @@ -2,7 +2,7 @@ import { AppEvents, Apps } from '@rocket.chat/apps'; import { AppsEngineException } from '@rocket.chat/apps-engine/definition/exceptions'; import { FederationMatrix, Message, Room, Team } from '@rocket.chat/core-services'; import type { ICreateRoomParams, ISubscriptionExtraData } from '@rocket.chat/core-services'; -import type { ICreatedRoom, IUser, IRoom, RoomType } from '@rocket.chat/core-typings'; +import { type ICreatedRoom, type IUser, type IRoom, type RoomType, isUserNativeFederated } from '@rocket.chat/core-typings'; import { Rooms, Subscriptions, Users } from '@rocket.chat/models'; import { Meteor } from 'meteor/meteor'; @@ -184,7 +184,12 @@ export const createRoom = async ( const shouldBeHandledByFederation = extraData.federated === true; - if (shouldBeHandledByFederation && owner && !(await hasPermissionAsync(owner._id, 'access-federation'))) { + if ( + shouldBeHandledByFederation && + owner && + !isUserNativeFederated(owner) && + !(await hasPermissionAsync(owner._id, 'access-federation')) + ) { throw new Meteor.Error('error-not-authorized-federation', 'Not authorized to access federation', { method: 'createRoom', }); diff --git a/apps/meteor/app/lib/server/functions/deleteUser.ts b/apps/meteor/app/lib/server/functions/deleteUser.ts index 02847707a8765..620726da5a722 100644 --- a/apps/meteor/app/lib/server/functions/deleteUser.ts +++ b/apps/meteor/app/lib/server/functions/deleteUser.ts @@ -73,11 +73,17 @@ export async function deleteUser(userId: string, confirmRelinquish = false, dele const store = FileUpload.getStore('Uploads'); const cursor = Messages.findFilesByUserId(userId); - for await (const { file } of cursor) { - if (!file) { - continue; + for await (const { file, files } of cursor) { + const fileIds = files?.map(({ _id }) => _id) || []; + for await (const fileId of fileIds) { + if (fileId) { + await store.deleteById(fileId); + } + } + + if (file?._id && !fileIds.includes(file._id)) { + await store.deleteById(file._id); } - await store.deleteById(file._id); } await Messages.removeByUserId(userId); diff --git a/apps/meteor/app/lib/server/functions/getFullUserData.ts b/apps/meteor/app/lib/server/functions/getFullUserData.ts index f1e1be0af0499..df3b977a777e1 100644 --- a/apps/meteor/app/lib/server/functions/getFullUserData.ts +++ b/apps/meteor/app/lib/server/functions/getFullUserData.ts @@ -60,7 +60,10 @@ settings.watch('Accounts_CustomFields', (settingValue) => { customFields[`customFields.${key}`] = 1; }); } catch (e) { - logger.warn(`The JSON specified for "Accounts_CustomFields" is invalid. The following error was thrown: ${e}`); + logger.warn({ + msg: 'The JSON specified for "Accounts_CustomFields" is invalid. The following error was thrown', + err: e, + }); } }); diff --git a/apps/meteor/app/lib/server/functions/getRoomByNameOrIdWithOptionToJoin.ts b/apps/meteor/app/lib/server/functions/getRoomByNameOrIdWithOptionToJoin.ts index e1aeabe1b46a5..6217342d0c534 100644 --- a/apps/meteor/app/lib/server/functions/getRoomByNameOrIdWithOptionToJoin.ts +++ b/apps/meteor/app/lib/server/functions/getRoomByNameOrIdWithOptionToJoin.ts @@ -14,7 +14,7 @@ export const getRoomByNameOrIdWithOptionToJoin = async ({ joinChannel = true, errorOnEmpty = true, }: { - user: Pick; + user: Pick; nameOrId: string; type?: RoomType; tryDirectByUserIdOnly?: boolean; diff --git a/apps/meteor/app/lib/server/lib/deprecationWarningLogger.ts b/apps/meteor/app/lib/server/lib/deprecationWarningLogger.ts index 6a7fc267caaa4..ee74d472ff05c 100644 --- a/apps/meteor/app/lib/server/lib/deprecationWarningLogger.ts +++ b/apps/meteor/app/lib/server/lib/deprecationWarningLogger.ts @@ -41,7 +41,7 @@ export const apiDeprecationLogger = ((logger) => { metrics.deprecations.inc({ type: 'deprecation', kind: 'endpoint', name: endpoint }); - logger.warn(message); + logger.warn({ msg: message, endpoint, version, info }); }, parameter: ( endpoint: string, @@ -66,7 +66,7 @@ export const apiDeprecationLogger = ((logger) => { writeDeprecationHeader(res, 'parameter-deprecation', message, version); - logger.warn(message); + logger.warn({ msg: message, endpoint, parameter, version }); }, deprecatedParameterUsage: ( @@ -95,7 +95,7 @@ export const apiDeprecationLogger = ((logger) => { writeDeprecationHeader(res, 'invalid-usage', message, version); - logger.warn(message); + logger.warn({ msg: message, endpoint, parameter, version }); }, }; })(deprecationLogger.section('API')); @@ -114,7 +114,7 @@ export const methodDeprecationLogger = ((logger) => { } compareVersions(version, message); metrics.deprecations.inc({ type: 'deprecation', name: method, kind: 'method' }); - logger.warn(message); + logger.warn({ msg: message, method, version, replacement }); }, parameter: (method: string, parameter: string, version: DeprecationLoggerNextPlannedVersion) => { const message = `The parameter "${parameter}" in the method "${method}" is deprecated and will be removed on version ${version}`; @@ -125,7 +125,7 @@ export const methodDeprecationLogger = ((logger) => { metrics.deprecations.inc({ type: 'parameter-deprecation', name: method, params: parameter }); compareVersions(version, message); - logger.warn(message); + logger.warn({ msg: message, method, parameter, version }); }, deprecatedParameterUsage: ( method: string, @@ -150,7 +150,7 @@ export const methodDeprecationLogger = ((logger) => { metrics.deprecations.inc({ type: 'invalid-usage', name: method, params: parameter, kind: 'method' }); - logger.warn(message); + logger.warn({ msg: message, method, parameter, version }); }, /** @deprecated */ warn: (message: string) => { @@ -159,7 +159,7 @@ export const methodDeprecationLogger = ((logger) => { } compareVersions('0.0.0', message); - logger.warn(message); + logger.warn({ msg: message }); }, }; })(deprecationLogger.section('METHOD')); diff --git a/apps/meteor/app/lib/server/methods/getChannelHistory.ts b/apps/meteor/app/lib/server/methods/getChannelHistory.ts index e0a2a844a75eb..cd2096a82a1a9 100644 --- a/apps/meteor/app/lib/server/methods/getChannelHistory.ts +++ b/apps/meteor/app/lib/server/methods/getChannelHistory.ts @@ -48,10 +48,6 @@ export const getChannelHistory = async ({ }): Promise => { check(rid, String); - if (!Meteor.userId()) { - throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'getChannelHistory' }); - } - if (!fromUserId) { return false; } diff --git a/apps/meteor/app/lib/server/methods/joinRoom.ts b/apps/meteor/app/lib/server/methods/joinRoom.ts index 8960936d7c33d..d11050bbb2201 100644 --- a/apps/meteor/app/lib/server/methods/joinRoom.ts +++ b/apps/meteor/app/lib/server/methods/joinRoom.ts @@ -16,8 +16,8 @@ Meteor.methods({ async joinRoom(rid, code) { check(rid, String); - const userId = await Meteor.userId(); - if (!userId) { + const user = await Meteor.userAsync(); + if (!user) { throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'joinRoom' }); } @@ -26,6 +26,6 @@ Meteor.methods({ throw new Meteor.Error('error-invalid-room', 'Invalid room', { method: 'joinRoom' }); } - return Room.join({ room, user: { _id: userId }, ...(code ? { joinCode: code } : {}) }); + return Room.join({ room, user, ...(code ? { joinCode: code } : {}) }); }, }); diff --git a/apps/meteor/app/lib/server/methods/sendMessage.ts b/apps/meteor/app/lib/server/methods/sendMessage.ts index 66758bc7faa1c..db7a017ee7a01 100644 --- a/apps/meteor/app/lib/server/methods/sendMessage.ts +++ b/apps/meteor/app/lib/server/methods/sendMessage.ts @@ -19,7 +19,21 @@ import { settings } from '../../../settings/server'; import { sendMessage } from '../functions/sendMessage'; import { RateLimiter } from '../lib'; -export async function executeSendMessage(uid: IUser['_id'], message: AtLeast, previewUrls?: string[]) { +/** + * + * @param uid + * @param message + * @param extraInfo + * - ts: The timestamp of the message. the message object already has a ts, but this value is validated and only a window of 10 seconds is allowed to be used. this value overrides the message.ts value without validation. + * + * + * @returns + */ +export async function executeSendMessage( + uid: IUser['_id'], + message: AtLeast, + extraInfo?: { ts?: Date; previewUrls?: string[] }, +) { if (message.tshow && !message.tmid) { throw new Meteor.Error('invalid-params', 'tshow provided but missing tmid', { method: 'sendMessage', @@ -32,7 +46,10 @@ export async function executeSendMessage(uid: IUser['_id'], message: AtLeast 60000) { throw new Meteor.Error('error-message-ts-out-of-sync', 'Message timestamp is out of sync', { @@ -40,11 +57,10 @@ export async function executeSendMessage(uid: IUser['_id'], message: AtLeast 10000) { - message.ts = new Date(); } - } else { - message.ts = new Date(); + if (tsDiff > 10000) { + message.ts = now; + } } if (message.msg) { @@ -90,7 +106,7 @@ export async function executeSendMessage(uid: IUser['_id'], message: AtLeast({ } try { - return await applyAirGappedRestrictionsValidation(() => executeSendMessage(uid, message, previewUrls)); + return await applyAirGappedRestrictionsValidation(() => executeSendMessage(uid, message, { previewUrls })); } catch (error: any) { if (['error-not-allowed', 'restricted-workspace'].includes(error.error || error.message)) { throw new Meteor.Error(error.error || error.message, error.reason, { diff --git a/apps/meteor/app/livechat/server/api/v1/message.ts b/apps/meteor/app/livechat/server/api/v1/message.ts index bfce5e98e23ea..3e90c1df1efe5 100644 --- a/apps/meteor/app/livechat/server/api/v1/message.ts +++ b/apps/meteor/app/livechat/server/api/v1/message.ts @@ -253,7 +253,7 @@ API.v1.addRoute( async post() { const visitorToken = this.bodyParams.visitor.token; - const visitor = await LivechatVisitors.getVisitorByToken(visitorToken, {}); + let visitor = await LivechatVisitors.getVisitorByToken(visitorToken, {}); let rid: string; if (visitor) { const extraQuery = await callbacks.run('livechat.applyRoomRestrictions', {}, { userId: this.userId }); @@ -272,7 +272,7 @@ API.v1.addRoute( guest.connectionData = normalizeHttpHeaderData(this.request.headers); } - const visitor = await registerGuest(guest, { shouldConsiderIdleAgent: settings.get('Livechat_enabled_when_agent_idle') }); + visitor = await registerGuest(guest, { shouldConsiderIdleAgent: settings.get('Livechat_enabled_when_agent_idle') }); if (!visitor) { throw new Error('error-livechat-visitor-registration'); } diff --git a/apps/meteor/app/livechat/server/api/v1/room.ts b/apps/meteor/app/livechat/server/api/v1/room.ts index d8c751b17c9a1..a06c8c2743753 100644 --- a/apps/meteor/app/livechat/server/api/v1/room.ts +++ b/apps/meteor/app/livechat/server/api/v1/room.ts @@ -516,7 +516,7 @@ const livechatRoomsEndpoints = API.v1 body: isPOSTLivechatRoomsCloseAll, }, async function action() { - livechatLogger.info(`User ${this.userId} is removing all closed rooms`); + livechatLogger.info({ msg: 'User is removing all closed rooms', userId: this.userId }); const params = this.bodyParams; @@ -527,7 +527,7 @@ const livechatRoomsEndpoints = API.v1 }); await Promise.all(promises); - livechatLogger.info(`User ${this.userId} removed ${promises.length} closed rooms`); + livechatLogger.info({ msg: 'User removed closed rooms', userId: this.userId, removedRooms: promises.length }); return API.v1.success({ removedRooms: promises.length }); }, ); diff --git a/apps/meteor/app/livechat/server/api/v1/visitor.ts b/apps/meteor/app/livechat/server/api/v1/visitor.ts index be6a974db958f..706260f80afba 100644 --- a/apps/meteor/app/livechat/server/api/v1/visitor.ts +++ b/apps/meteor/app/livechat/server/api/v1/visitor.ts @@ -151,7 +151,7 @@ API.v1.addRoute('livechat/visitor/:token', { }, }); } catch (e) { - livechatLogger.error(e); + livechatLogger.error({ msg: 'Error removing visitor', err: e }); throw new Meteor.Error('error-removing-visitor', 'An error ocurred while deleting visitor'); } }, diff --git a/apps/meteor/app/livechat/server/api/v1/webhooks.ts b/apps/meteor/app/livechat/server/api/v1/webhooks.ts index af7c97d5145cb..917fbeeb43dbc 100644 --- a/apps/meteor/app/livechat/server/api/v1/webhooks.ts +++ b/apps/meteor/app/livechat/server/api/v1/webhooks.ts @@ -72,18 +72,18 @@ API.v1.addRoute( } try { - logger.debug(`Testing webhook ${webhookUrl}`); + logger.debug({ msg: 'Testing webhook', webhookUrl }); const request = await fetch(webhookUrl, options); const response = await request.text(); - logger.debug({ response }); + logger.debug({ msg: 'Webhook response', response }); if (request.status === 200) { return API.v1.success(); } throw new Error('Invalid status code'); } catch (error) { - logger.error(`Error testing webhook: ${error}`); + logger.error({ msg: 'Error testing webhook', err: error }); throw new Error('error-invalid-webhook-response'); } }, diff --git a/apps/meteor/app/livechat/server/business-hour/BusinessHourManager.ts b/apps/meteor/app/livechat/server/business-hour/BusinessHourManager.ts index 4fe6bff2d0d88..e83bb6bbf37a3 100644 --- a/apps/meteor/app/livechat/server/business-hour/BusinessHourManager.ts +++ b/apps/meteor/app/livechat/server/business-hour/BusinessHourManager.ts @@ -287,7 +287,7 @@ export class BusinessHourManager { const failed = result.filter((r) => r.status === 'rejected'); if (failed.length > 0) { failed.forEach((error: any) => { - businessHourLogger.error('Failed to update business hours with new timezone', error.reason); + businessHourLogger.error({ msg: 'Failed to update business hours with new timezone', err: error }); }); } diff --git a/apps/meteor/app/livechat/server/business-hour/Single.ts b/apps/meteor/app/livechat/server/business-hour/Single.ts index 13a8673ad7fab..e427db9d2f59f 100644 --- a/apps/meteor/app/livechat/server/business-hour/Single.ts +++ b/apps/meteor/app/livechat/server/business-hour/Single.ts @@ -30,7 +30,8 @@ export class SingleBusinessHourBehavior extends AbstractBusinessHourBehavior imp async onNewAgentCreated(agentId: string): Promise { const defaultBusinessHour = await LivechatBusinessHours.findOneDefaultBusinessHour(); if (!defaultBusinessHour) { - businessHourLogger.debug('No default business hour found for agentId', { + businessHourLogger.debug({ + msg: 'No default business hour found for agentId', agentId, }); return; diff --git a/apps/meteor/app/livechat/server/lib/Helper.ts b/apps/meteor/app/livechat/server/lib/Helper.ts index 440b77a934a31..2ce0a3a66fe40 100644 --- a/apps/meteor/app/livechat/server/lib/Helper.ts +++ b/apps/meteor/app/livechat/server/lib/Helper.ts @@ -109,7 +109,7 @@ export const prepareLivechatRoom = async ( const activity = guest.activity || contact.activity; logger.debug({ - msg: `Creating livechat room for visitor ${_id}`, + msg: 'Creating livechat room for visitor', visitor: { _id, username, departmentId, status, activity }, }); @@ -209,7 +209,7 @@ export const createLivechatInquiry = async ({ const ts = new Date(); logger.debug({ - msg: `Creating livechat inquiry for visitor`, + msg: 'Creating livechat inquiry for visitor', visitor: { _id, username, department, status, activity }, }); @@ -245,7 +245,11 @@ export const createLivechatInquiry = async ({ session, }, ); - logger.debug(`Inquiry ${result} created for visitor ${_id}`); + logger.debug({ + msg: 'Inquiry created for visitor', + inquiryId: result, + visitorId: _id, + }); if (!result) { throw new Error('Inquiry not created'); @@ -357,7 +361,7 @@ export const parseAgentCustomFields = (customFields?: Record) => { const parseCustomFields = JSON.parse(accountCustomFields); return Object.keys(parseCustomFields).filter((customFieldKey) => parseCustomFields[customFieldKey].sendToIntegrations === true); } catch (error) { - logger.error(error); + logger.error({ msg: 'Error parsing agent custom fields', err: error }); return []; } }; @@ -406,7 +410,11 @@ export const dispatchInquiryQueued = async (inquiry: ILivechatInquiryRecord, age if (!inquiry?._id) { return; } - logger.debug(`Notifying agents of new inquiry ${inquiry._id} queued`); + logger.debug({ + msg: 'Notifying agents of queued inquiry', + inquiryId: inquiry._id, + agentId: agent?.agentId, + }); const { department, rid, v } = inquiry; const room = await LivechatRooms.findOneById(rid); @@ -429,7 +437,7 @@ export const dispatchInquiryQueued = async (inquiry: ILivechatInquiryRecord, age // Alert only the online agents of the queued request const onlineAgents = await getOnlineAgents(department, agent); if (!onlineAgents) { - logger.debug('Cannot notify agents of queued inquiry. No online agents found'); + logger.debug({ msg: 'Cannot notify agents of queued inquiry. No online agents found' }); return; } @@ -475,7 +483,11 @@ export const forwardRoomToAgent = async (room: IOmnichannelRoom, transferData: T return false; } - logger.debug(`Forwarding room ${room._id} to agent ${transferData.userId}`); + logger.debug({ + msg: 'Forwarding room to agent', + roomId: room._id, + userId: transferData.userId, + }); const { userId: agentId, clientAction } = transferData; if (!agentId) { @@ -483,14 +495,20 @@ export const forwardRoomToAgent = async (room: IOmnichannelRoom, transferData: T } const user = await Users.findOneOnlineAgentById(agentId, settings.get('Livechat_enabled_when_agent_idle')); if (!user) { - logger.debug(`Agent ${agentId} is offline. Cannot forward`); + logger.debug({ + msg: 'Agent is offline. Cannot forward', + agentId, + }); throw new Error('error-user-is-offline'); } const { _id: rid, servedBy: oldServedBy } = room; const inquiry = await LivechatInquiry.findOneByRoomId(rid, {}); if (!inquiry) { - logger.debug(`No inquiries found for room ${room._id}. Cannot forward`); + logger.debug({ + msg: 'No inquiries found for room. Cannot forward', + roomId: room._id, + }); throw new Error('error-invalid-inquiry'); } @@ -504,7 +522,11 @@ export const forwardRoomToAgent = async (room: IOmnichannelRoom, transferData: T delete inquiry.department; // There are some Enterprise features that may interrupt the forwarding process // Due to that we need to check whether the agent has been changed or not - logger.debug(`Forwarding inquiry ${inquiry._id} to agent ${agent.agentId}`); + logger.debug({ + msg: 'Forwarding inquiry to agent', + inquiryId: inquiry._id, + agentId: agent.agentId, + }); const roomTaken = await RoutingManager.takeInquiry( inquiry, agent, @@ -514,7 +536,10 @@ export const forwardRoomToAgent = async (room: IOmnichannelRoom, transferData: T room, ); if (!roomTaken) { - logger.debug(`Cannot forward inquiry ${inquiry._id}`); + logger.debug({ + msg: 'Cannot forward inquiry', + inquiryId: inquiry._id, + }); return false; } @@ -536,7 +561,11 @@ export const forwardRoomToAgent = async (room: IOmnichannelRoom, transferData: T }); } - logger.debug(`Inquiry ${inquiry._id} taken by agent ${agent.agentId}`); + logger.debug({ + msg: 'Inquiry taken by agent after forwarding', + inquiryId: inquiry._id, + agentId: agent.agentId, + }); await callbacks.run('livechat.afterForwardChatToAgent', { rid, servedBy, oldServedBy }); return true; }; @@ -586,7 +615,11 @@ export const forwardRoomToDepartment = async (room: IOmnichannelRoom, guest: ILi if (!room?.open) { return false; } - logger.debug(`Attempting to forward room ${room._id} to department ${transferData.departmentId}`); + logger.debug({ + msg: 'Attempting to forward room to department', + roomId: room._id, + departmentId: transferData.departmentId, + }); await callbacks.run('livechat.beforeForwardRoomToDepartment', { room, transferData }); const { _id: rid, servedBy: oldServedBy, departmentId: oldDepartmentId } = room; @@ -594,13 +627,19 @@ export const forwardRoomToDepartment = async (room: IOmnichannelRoom, guest: ILi const inquiry = await LivechatInquiry.findOneByRoomId(rid, {}); if (!inquiry) { - logger.debug(`Cannot forward room ${room._id}. No inquiries found`); + logger.debug({ + msg: 'Cannot forward room. No inquiries found', + roomId: room._id, + }); throw new Error('error-transferring-inquiry'); } const { departmentId } = transferData; if (!departmentId) { - logger.debug(`Cannot forward room ${room._id}. No departmentId provided`); + logger.debug({ + msg: 'Cannot forward room. No departmentId provided', + roomId: room._id, + }); throw new Error('error-transferring-inquiry-no-department'); } if (oldDepartmentId === departmentId) { @@ -609,7 +648,12 @@ export const forwardRoomToDepartment = async (room: IOmnichannelRoom, guest: ILi const { userId: agentId, clientAction } = transferData; if (agentId) { - logger.debug(`Forwarding room ${room._id} to department ${departmentId} (to user ${agentId})`); + logger.debug({ + msg: 'Forwarding room to department and user', + roomId: room._id, + departmentId, + agentId, + }); const user = await Users.findOneOnlineAgentById(agentId, settings.get('Livechat_enabled_when_agent_idle')); if (!user) { throw new Error('error-user-is-offline'); @@ -672,14 +716,22 @@ export const forwardRoomToDepartment = async (room: IOmnichannelRoom, guest: ILi room, ); if (!roomTaken) { - logger.debug(`Cannot forward room ${room._id}. Unable to delegate inquiry`); + logger.debug({ + msg: 'Cannot forward room. Unable to delegate inquiry', + roomId: room._id, + }); return false; } const { servedBy, chatQueued } = roomTaken; if (!chatQueued && oldServedBy && servedBy && oldServedBy._id === servedBy._id) { if (!department?.fallbackForwardDepartment?.length) { - logger.debug(`Cannot forward room ${room._id}. Chat assigned to agent ${servedBy._id} (Previous was ${oldServedBy._id})`); + logger.debug({ + msg: 'Cannot forward room. Chat assigned to agent instead', + roomId: room._id, + agentId: servedBy._id, + previousAgentId: oldServedBy._id, + }); throw new Error('error-no-agents-available-for-service-on-department'); } @@ -690,7 +742,10 @@ export const forwardRoomToDepartment = async (room: IOmnichannelRoom, guest: ILi const transferSuccess = !!(await callbacks.run('livechat:onTransferFailure', room, { guest, transferData, department })); // On CE theres no callback so it will return the room if (typeof transferSuccess !== 'boolean' || !transferSuccess) { - logger.debug(`Cannot forward room ${room._id}. Unable to delegate inquiry`); + logger.debug({ + msg: 'Cannot forward room. Unable to delegate inquiry', + roomId: room._id, + }); return false; } @@ -725,18 +780,27 @@ export const forwardRoomToDepartment = async (room: IOmnichannelRoom, guest: ILi await updateChatDepartment({ rid, newDepartmentId: departmentId, oldDepartmentId }); if (chatQueued) { - logger.debug(`Forwarding succesful. Marking inquiry ${inquiry._id} as ready`); + logger.debug({ + msg: 'Forwarding successful. Marking inquiry as ready', + inquiryId: inquiry._id, + }); await LivechatInquiry.readyInquiry(inquiry._id); await LivechatRooms.removeAgentByRoomId(rid); await dispatchAgentDelegated(rid); const newInquiry = await LivechatInquiry.findOneById(inquiry._id); if (!newInquiry) { - logger.debug(`Inquiry ${inquiry._id} not found`); + logger.debug({ + msg: 'Inquiry not found after forwarding', + inquiryId: inquiry._id, + }); throw new Error('error-invalid-inquiry'); } await queueInquiry(newInquiry); - logger.debug(`Inquiry ${inquiry._id} queued succesfully`); + logger.debug({ + msg: 'Inquiry queued successfully after forwarding', + inquiryId: inquiry._id, + }); } return true; diff --git a/apps/meteor/app/livechat/server/lib/QueueManager.ts b/apps/meteor/app/livechat/server/lib/QueueManager.ts index 5fd12908f5b7b..8e28c3334a828 100644 --- a/apps/meteor/app/livechat/server/lib/QueueManager.ts +++ b/apps/meteor/app/livechat/server/lib/QueueManager.ts @@ -100,7 +100,11 @@ export class QueueManager { } const inquiryAgent = await RoutingManager.delegateAgent(defaultAgent, inquiry); - logger.debug(`Delegating inquiry with id ${inquiry._id} to agent ${defaultAgent?.username}`); + logger.debug({ + msg: 'Delegating inquiry', + inquiryId: inquiry._id, + defaultAgentUsername: defaultAgent?.username, + }); const dbInquiry = await beforeRouteChat(inquiry, inquiryAgent); if (!dbInquiry) { @@ -108,7 +112,11 @@ export class QueueManager { } if (dbInquiry.status === 'ready') { - logger.debug(`Inquiry with id ${inquiry._id} is ready. Delegating to agent ${inquiryAgent?.username}`); + logger.debug({ + msg: 'Inquiry is ready. Delegating to agent', + inquiryId: inquiry._id, + agentUsername: inquiryAgent?.username, + }); return RoutingManager.delegateInquiry(dbInquiry, inquiryAgent, undefined, room); } } @@ -160,7 +168,12 @@ export class QueueManager { static async processNewInquiry(inquiry: ILivechatInquiryRecord, room: IOmnichannelRoom, defaultAgent?: SelectedAgent | null) { if (inquiry.status === LivechatInquiryStatus.VERIFYING) { - logger.debug({ msg: 'Inquiry is waiting for contact verification. Ignoring it', inquiry, defaultAgent }); + logger.debug({ + msg: 'Inquiry is waiting for contact verification. Ignoring it', + inquiryId: inquiry._id, + defaultAgentUsername: defaultAgent?.username, + status: inquiry.status, + }); if (defaultAgent) { await LivechatInquiry.setDefaultAgentById(inquiry._id, defaultAgent); @@ -169,7 +182,12 @@ export class QueueManager { } if (inquiry.status === LivechatInquiryStatus.READY) { - logger.debug({ msg: 'Inquiry is ready. Delegating', inquiry, defaultAgent }); + logger.debug({ + msg: 'Inquiry is ready. Delegating', + inquiryId: inquiry._id, + defaultAgentUsername: defaultAgent?.username, + status: inquiry.status, + }); return RoutingManager.delegateInquiry(inquiry, defaultAgent, undefined, room); } diff --git a/apps/meteor/app/livechat/server/lib/RoutingManager.ts b/apps/meteor/app/livechat/server/lib/RoutingManager.ts index 20f7a82e4c664..ff91d04819846 100644 --- a/apps/meteor/app/livechat/server/lib/RoutingManager.ts +++ b/apps/meteor/app/livechat/server/lib/RoutingManager.ts @@ -47,7 +47,7 @@ type Routing = { agent?: SelectedAgent | null, options?: { clientAction?: boolean; forwardingToDepartment?: { oldDepartmentId?: string; transferData?: any } }, room?: IOmnichannelRoom, - ): Promise<(IOmnichannelRoom & { chatQueued?: boolean }) | null | void>; + ): Promise<(IOmnichannelRoom & { chatQueued?: boolean }) | null | false>; unassignAgent( inquiry: ILivechatInquiryRecord, departmentId?: string, @@ -62,7 +62,7 @@ type Routing = { agent: SelectedAgent | null, options: { clientAction?: boolean; forwardingToDepartment?: { oldDepartmentId?: string; transferData?: any } }, room: IOmnichannelRoom, - ): Promise; + ): Promise; transferRoom(room: IOmnichannelRoom, guest: ILivechatVisitor, transferData: TransferData): Promise; delegateAgent(agent: SelectedAgent | undefined, inquiry: ILivechatInquiryRecord): Promise; removeAllRoomSubscriptions(room: Pick, ignoreUser?: { _id: string }): Promise; @@ -101,16 +101,16 @@ export const RoutingManager: Routing = { async delegateInquiry(inquiry, agent, options = {}, room) { const { department, rid } = inquiry; - logger.debug(`Attempting to delegate inquiry ${inquiry._id}`); + logger.debug({ msg: 'Attempting to delegate inquiry', inquiryId: inquiry._id }); if ( !agent || (agent.username && !(await Users.findOneOnlineAgentByUserList(agent.username, {}, settings.get('Livechat_enabled_when_agent_idle'))) && !(await allowAgentSkipQueue(agent))) ) { - logger.debug(`Agent offline or invalid. Using routing method to get next agent for inquiry ${inquiry._id}`); + logger.debug({ msg: 'Agent offline or invalid. Using routing method to get next agent', inquiryId: inquiry._id }); agent = await this.getNextAgent(department); - logger.debug(`Routing method returned agent ${agent?.agentId} for inquiry ${inquiry._id}`); + logger.debug({ msg: 'Routing method returned agent for inquiry', inquiryId: inquiry._id, agentId: agent?.agentId }); } if (!agent) { @@ -124,7 +124,7 @@ export const RoutingManager: Routing = { throw new Meteor.Error('error-invalid-room'); } - logger.debug(`Inquiry ${inquiry._id} will be taken by agent ${agent.agentId}`); + logger.debug({ msg: 'Inquiry will be taken by agent', inquiryId: inquiry._id, agentId: agent.agentId }); return this.takeInquiry(inquiry, agent, options, room); }, @@ -137,7 +137,7 @@ export const RoutingManager: Routing = { }), ); - logger.debug(`Assigning agent ${agent.agentId} to inquiry ${inquiry._id}`); + logger.debug({ msg: 'Assigning agent to inquiry', agentId: agent.agentId, inquiryId: inquiry._id }); const { rid, name, v, department } = inquiry; if (!(await createLivechatSubscription(rid, name, v, agent, department))) { @@ -181,7 +181,12 @@ export const RoutingManager: Routing = { } if (departmentId && departmentId !== department) { - logger.debug(`Switching department for inquiry ${inquiry._id} [Current: ${department} | Next: ${departmentId}]`); + logger.debug({ + msg: 'Switching department for inquiry', + inquiryId: inquiry._id, + currentDepartment: department, + nextDepartment: departmentId, + }); await updateChatDepartment({ rid, newDepartmentId: departmentId, @@ -234,7 +239,7 @@ export const RoutingManager: Routing = { }), ); - logger.debug(`Attempting to take Inquiry ${inquiry._id} [Agent ${agent.agentId}] `); + logger.debug({ msg: 'Attempting to take Inquiry', inquiryId: inquiry._id, agentId: agent.agentId }); const { _id, rid } = inquiry; if (!room?.open) { @@ -271,11 +276,11 @@ export const RoutingManager: Routing = { const result = await LivechatInquiry.takeInquiry(_id, inquiry.lockedAt); if (result.modifiedCount === 0) { - logger.error('Failed to take inquiry, could not match lockedAt', { inquiryId: _id, lockedAt: inquiry.lockedAt }); + logger.error({ msg: 'Failed to take inquiry, could not match lockedAt', inquiryId: _id, lockedAt: inquiry.lockedAt }); throw new Error('error-taking-inquiry-lockedAt-mismatch'); } - logger.info(`Inquiry ${inquiry._id} taken by agent ${agent.agentId}`); + logger.info({ msg: 'Inquiry taken by agent', inquiryId: inquiry._id, agentId: agent.agentId }); // assignAgent changes the room data to add the agent serving the conversation. afterTakeInquiry expects room object to be updated const { inquiry: returnedInquiry, user } = await this.assignAgent(inquiry as InquiryWithAgentInfo, agent); @@ -301,9 +306,9 @@ export const RoutingManager: Routing = { }, async transferRoom(room, guest, transferData) { - logger.debug(`Transfering room ${room._id} by ${transferData.transferredBy._id}`); + logger.debug({ msg: 'Transferring room', roomId: room._id, transferredBy: transferData.transferredBy._id }); if (transferData.departmentId) { - logger.debug(`Transfering room ${room._id} to department ${transferData.departmentId}`); + logger.debug({ msg: 'Transferring room to department', roomId: room._id, departmentId: transferData.departmentId }); return forwardRoomToDepartment(room, guest, transferData); } @@ -322,12 +327,12 @@ export const RoutingManager: Routing = { }); if (defaultAgent) { - logger.debug(`Delegating Inquiry ${inquiry._id} to agent ${defaultAgent.username}`); + logger.debug({ msg: 'Delegating Inquiry to agent', inquiryId: inquiry._id, agentUsername: defaultAgent.username }); await LivechatInquiry.setDefaultAgentById(inquiry._id, defaultAgent); void notifyOnLivechatInquiryChanged(inquiry, 'updated', { defaultAgent }); } - logger.debug(`Queueing inquiry ${inquiry._id}`); + logger.debug({ msg: 'Queueing inquiry', inquiryId: inquiry._id }); await dispatchInquiryQueued(inquiry, defaultAgent); return defaultAgent; }, diff --git a/apps/meteor/app/livechat/server/lib/sendTranscript.ts b/apps/meteor/app/livechat/server/lib/sendTranscript.ts index ca0148742846d..8a6f861907488 100644 --- a/apps/meteor/app/livechat/server/lib/sendTranscript.ts +++ b/apps/meteor/app/livechat/server/lib/sendTranscript.ts @@ -41,7 +41,7 @@ export async function sendTranscript({ subject?: string; user?: Pick | null; }): Promise { - logger.debug(`Sending conversation transcript of room ${rid} to user with token ${token}`); + logger.debug({ msg: 'Sending conversation transcript', rid, token }); const room = await LivechatRooms.findOneById>(rid, { projection: { _id: 1, v: 1 } }); if (!room) { @@ -55,7 +55,7 @@ export async function sendTranscript({ const userLanguage = settings.get('Language') || 'en'; const timezone = getTimezone(user); - logger.debug(`Transcript will be sent using ${timezone} as timezone`); + logger.debug({ msg: 'Transcript will be sent using timezone', timezone }); const showAgentInfo = settings.get('Livechat_show_agent_info'); const showSystemMessages = settings.get('Livechat_transcript_show_system_messages'); diff --git a/apps/meteor/app/livechat/server/startup.ts b/apps/meteor/app/livechat/server/startup.ts index 73219b781bf4f..813644d5a51c9 100644 --- a/apps/meteor/app/livechat/server/startup.ts +++ b/apps/meteor/app/livechat/server/startup.ts @@ -113,7 +113,7 @@ Meteor.startup(async () => { settings.watch( 'Livechat_enable_business_hours', async (value) => { - logger.debug(`Starting business hour manager ${value}`); + logger.debug({ msg: 'Starting business hour manager', enabled: value }); if (value) { await businessHourManager.startManager(); return; diff --git a/apps/meteor/app/message-star/server/starMessage.ts b/apps/meteor/app/message-star/server/starMessage.ts index 96b342f8bfa69..38cfc648af04d 100644 --- a/apps/meteor/app/message-star/server/starMessage.ts +++ b/apps/meteor/app/message-star/server/starMessage.ts @@ -1,11 +1,12 @@ import { Apps, AppEvents } from '@rocket.chat/apps'; -import type { IMessage } from '@rocket.chat/core-typings'; +import type { IMessage, IUser } from '@rocket.chat/core-typings'; import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Messages, Subscriptions, Rooms } from '@rocket.chat/models'; import { Meteor } from 'meteor/meteor'; import { canAccessRoomAsync, roomAccessAttributes } from '../../authorization/server'; import { isTheLastMessage } from '../../lib/server/functions/isTheLastMessage'; +import { methodDeprecationLogger } from '../../lib/server/lib/deprecationWarningLogger'; import { notifyOnRoomChangedById, notifyOnMessageChange } from '../../lib/server/lib/notifyListener'; import { settings } from '../../settings/server'; @@ -16,7 +17,7 @@ declare module '@rocket.chat/ddp-client' { } } -export const starMessage = async (userId: string, message: Pick & { starred: boolean }): Promise => { +export const starMessage = async (user: IUser, message: Pick & { starred: boolean }): Promise => { if (!settings.get('Message_AllowStarring')) { throw new Meteor.Error('error-action-not-allowed', 'Message starring not allowed', { method: 'starMessage', @@ -24,7 +25,7 @@ export const starMessage = async (userId: string, message: Pick({ async starMessage(message) { - const uid = Meteor.userId(); + methodDeprecationLogger.method('starMessage', '9.0.0', '/v1/chat.starMessage'); + const user = (await Meteor.userAsync()) as IUser; - if (!uid) { + if (!user) { throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'starMessage', }); } - return starMessage(uid, message); + return starMessage(user, message); }, }); diff --git a/apps/meteor/app/oembed/server/server.ts b/apps/meteor/app/oembed/server/server.ts index 4a4b6a8b30fe2..1018e7426d1d9 100644 --- a/apps/meteor/app/oembed/server/server.ts +++ b/apps/meteor/app/oembed/server/server.ts @@ -98,7 +98,7 @@ const getUrlContent = async (urlObj: URL, redirectCount = 5): Promise { - log.debug('Obtaining metadata for URL', url); + log.debug({ msg: 'Obtaining metadata for URL', url }); const urlObj = new URL(url); if (withFragment) { urlObj.searchParams.set('_escaped_fragment_', ''); } - log.debug('Fetching url content', urlObj.toString()); + log.debug({ msg: 'Fetching URL content', url: urlObj.toString() }); let content: OEmbedUrlContentResult | undefined; try { content = await getUrlContent(urlObj, 5); } catch (err) { - log.error({ msg: 'Error fetching url content', err }); + log.error({ msg: 'Error fetching URL content', url: urlObj.toString(), err }); } if (!content) { return; } - log.debug('Parsing metadata for URL', url); + log.debug({ msg: 'Parsing metadata for URL', url }); const metas: { [k: string]: string } = {}; if (content?.body) { @@ -245,11 +245,11 @@ const getUrlMetaWithCache = async function ( url: string, withFragment?: boolean, ): Promise { - log.debug('Getting oembed metadata for', url); + log.debug({ msg: 'Getting OEmbed metadata for URL', url }); const cache = await OEmbedCache.findOneById(url); if (cache) { - log.debug('Found oembed metadata in cache for', url); + log.debug({ msg: 'Found OEmbed metadata in cache for URL', url }); return cache.data; } @@ -260,7 +260,7 @@ const getUrlMetaWithCache = async function ( } try { - log.debug('Saving oembed metadata in cache for', url); + log.debug({ msg: 'Saving OEmbed metadata in cache for URL', url }); await OEmbedCache.createWithIdAndData(url, data); } catch (_error) { log.error({ msg: 'OEmbed duplicated record', url }); @@ -287,19 +287,19 @@ const insertMaxWidthInOembedHtml = (oembedHtml?: string): string | undefined => oembedHtml?.replace('iframe', 'iframe style="max-width: 100%;width:400px;height:225px"'); const rocketUrlParser = async function (message: IMessage): Promise { - log.debug('Parsing message URLs'); + log.debug({ msg: 'Parsing message URLs' }); if (!Array.isArray(message.urls)) { return message; } - log.debug('URLs found', message.urls.length); + log.debug({ msg: 'URLs found in message', count: message.urls.length }); if ( (message.attachments && message.attachments.length > 0) || message.urls.filter((item) => !item.url.includes(settings.get('Site_Url'))).length > MAX_EXTERNAL_URL_PREVIEWS ) { - log.debug('All URL ignored'); + log.debug({ msg: 'All URLs ignored for OEmbed' }); return message; } @@ -308,7 +308,7 @@ const rocketUrlParser = async function (message: IMessage): Promise { let changed = false; for await (const item of message.urls) { if (item.ignoreParse === true) { - log.debug('URL ignored', item.url); + log.debug({ msg: 'URL ignored for OEmbed', url: item.url }); continue; } diff --git a/apps/meteor/app/slackbridge/server/RocketAdapter.js b/apps/meteor/app/slackbridge/server/RocketAdapter.js index 17fce65133090..624d4a72de068 100644 --- a/apps/meteor/app/slackbridge/server/RocketAdapter.js +++ b/apps/meteor/app/slackbridge/server/RocketAdapter.js @@ -65,7 +65,7 @@ export default class RocketAdapter { continue; } - rocketLogger.debug('onRocketMessageDelete', rocketMessageDeleted); + rocketLogger.debug({ msg: 'onRocketMessageDelete', rocketMessageDeleted }); await slack.postDeleteMessage(rocketMessageDeleted); } catch (err) { rocketLogger.error({ msg: 'Unhandled error onMessageDelete', err }); @@ -137,7 +137,7 @@ export default class RocketAdapter { // This is on a channel that the rocket bot is not subscribed continue; } - rocketLogger.debug('onRocketMessage', rocketMessage); + rocketLogger.debug({ msg: 'onRocketMessage', rocketMessage }); if (rocketMessage.editedAt) { // This is an Edit Event @@ -260,7 +260,7 @@ export default class RocketAdapter { } async addChannel(slackChannelID, hasRetried = false) { - rocketLogger.debug('Adding Rocket.Chat channel from Slack', slackChannelID); + rocketLogger.debug({ msg: 'Adding Rocket.Chat channel from Slack', slackChannelID }); let addedRoom; for await (const slack of this.slackAdapters) { @@ -296,12 +296,12 @@ export default class RocketAdapter { slackChannel.rocketId = rocketChannel.rid; } catch (e) { if (!hasRetried) { - rocketLogger.debug('Error adding channel from Slack. Will retry in 1s.', e.message); + rocketLogger.debug({ msg: 'Error adding channel from Slack. Will retry in 1s.', err: e }); // If first time trying to create channel fails, could be because of multiple messages received at the same time. Try again once after 1s. await sleep(1000); return (await this.findChannel(slackChannelID)) || this.addChannel(slackChannelID, true); } - rocketLogger.error(e); + rocketLogger.error({ msg: 'Error adding channel from Slack', err: e }); } const roomUpdate = { diff --git a/apps/meteor/app/slashcommands-join/server/server.ts b/apps/meteor/app/slashcommands-join/server/server.ts index 6497324ae9e0e..2a70552ef839f 100644 --- a/apps/meteor/app/slashcommands-join/server/server.ts +++ b/apps/meteor/app/slashcommands-join/server/server.ts @@ -1,6 +1,6 @@ import { api, Room } from '@rocket.chat/core-services'; import type { SlashCommandCallbackParams } from '@rocket.chat/core-typings'; -import { Rooms, Subscriptions } from '@rocket.chat/models'; +import { Rooms, Subscriptions, Users } from '@rocket.chat/models'; import { Meteor } from 'meteor/meteor'; import { i18n } from '../../../server/lib/i18n'; @@ -43,7 +43,13 @@ slashCommands.add({ }); } - await Room.join({ room, user: { _id: userId } }); + const user = await Users.findOneById(userId, { projection: { federated: 1, federation: 1 } }); + if (!user) { + throw new Meteor.Error('error-invalid-user', 'Invalid user', { + method: 'slashCommands', + }); + } + await Room.join({ room, user }); }, options: { description: 'Join_the_given_channel', diff --git a/apps/meteor/app/statistics/server/functions/sendUsageReport.spec.ts b/apps/meteor/app/statistics/server/functions/sendUsageReport.spec.ts new file mode 100644 index 0000000000000..2e9da97aa733f --- /dev/null +++ b/apps/meteor/app/statistics/server/functions/sendUsageReport.spec.ts @@ -0,0 +1,63 @@ +import { expect } from 'chai'; +import { describe, it, beforeEach, afterEach } from 'mocha'; +import proxyquire from 'proxyquire'; +import sinon from 'sinon'; + +const sandbox = sinon.createSandbox(); + +const mocks = { + Statistics: { + findLast: sandbox.stub(), + updateOne: sandbox.stub(), + }, + statistics: { + save: sandbox.stub(), + }, + serverFetch: sandbox.stub(), + getWorkspaceAccessToken: sandbox.stub().resolves('workspace-token'), + Meteor: { + absoluteUrl: sandbox.stub().returns('http://localhost:3000/'), + }, + logger: { + error: sandbox.stub(), + }, +}; + +const { sendUsageReport } = proxyquire.noCallThru().load('./sendUsageReport', { + '@rocket.chat/models': { Statistics: mocks.Statistics }, + '@rocket.chat/server-fetch': { serverFetch: mocks.serverFetch }, + '..': { statistics: mocks.statistics }, + '../../../cloud/server': { getWorkspaceAccessToken: mocks.getWorkspaceAccessToken }, + 'meteor/meteor': { Meteor: mocks.Meteor }, +}); + +describe('sendUsageReport', () => { + beforeEach(() => { + sandbox.resetHistory(); + }); + + afterEach(() => { + delete process.env.RC_DISABLE_STATISTICS_REPORTING; + }); + + it('should save statistics locally and not send to collector when RC_DISABLE_STATISTICS_REPORTING is true', async () => { + process.env.RC_DISABLE_STATISTICS_REPORTING = 'true'; + + const result = await sendUsageReport(mocks.logger); + + expect(mocks.statistics.save.called).to.be.true; + expect(mocks.serverFetch.called).to.be.false; + expect(result).to.be.undefined; + }); + + it('should save statistics locally and send to collector when RC_DISABLE_STATISTICS_REPORTING is false', async () => { + process.env.RC_DISABLE_STATISTICS_REPORTING = 'false'; + + const result = await sendUsageReport(mocks.logger); + + expect(mocks.statistics.save.called).to.be.true; + expect(mocks.serverFetch.calledOnce).to.be.true; + expect(mocks.serverFetch.calledWith('https://collector.rocket.chat/', sinon.match({ method: 'POST' }))).to.be.true; + expect(result).to.be.undefined; + }); +}); diff --git a/apps/meteor/app/statistics/server/functions/sendUsageReport.ts b/apps/meteor/app/statistics/server/functions/sendUsageReport.ts index c39276be6f357..a5bc91a639621 100644 --- a/apps/meteor/app/statistics/server/functions/sendUsageReport.ts +++ b/apps/meteor/app/statistics/server/functions/sendUsageReport.ts @@ -6,6 +6,7 @@ import { tracerSpan } from '@rocket.chat/tracing'; import { Meteor } from 'meteor/meteor'; import { statistics } from '..'; +import { shouldReportStatistics } from '../../../../server/cron/usageReport'; import { getWorkspaceAccessToken } from '../../../cloud/server'; async function sendStats(logger: Logger, cronStatistics: IStats): Promise { @@ -34,6 +35,10 @@ async function sendStats(logger: Logger, cronStatistics: IStats): Promise { + // Even when disabled, we still generate statistics locally to avoid breaking + // internal processes, such as restriction checks for air-gapped workspaces. + const shouldSendToCollector = shouldReportStatistics(); + return tracerSpan('generateStatistics', {}, async () => { const last = await Statistics.findLast(); if (last) { @@ -48,13 +53,18 @@ export async function sendUsageReport(logger: Logger): Promise { @@ -75,7 +75,7 @@ export class SAUMonitorClass { await this.scheduler.remove(this._dailyFinishSessionsJobName); } - logger.debug('[stop]'); + logger.debug({ msg: '[stop]' }); } isRunning(): boolean { @@ -131,13 +131,13 @@ export class SAUMonitorClass { } if (!userId) { - logger.warn(`Received 'accounts.logout' event without 'userId'`); + logger.warn({ msg: "Received 'accounts.logout' event without 'userId'" }); return; } const { id: sessionId } = connection; if (!sessionId) { - logger.warn(`Received 'accounts.logout' event without 'sessionId'`); + logger.warn({ msg: "Received 'accounts.logout' event without 'sessionId'" }); return; } @@ -148,7 +148,7 @@ export class SAUMonitorClass { if (!isProdEnv) { throw new Error('Session not found during logout'); } - logger.error('Session not found during logout', { userId, sessionId }); + logger.error({ msg: 'Session not found during logout', userId, sessionId }); return; } @@ -323,7 +323,7 @@ export class SAUMonitorClass { } private async _startCronjobs(): Promise { - logger.info('[aggregate] - Start Cron.'); + logger.info({ msg: '[aggregate] - Start Cron.' }); const dailyComputeProcessTime = '0 2 * * *'; const dailyFinishSessionProcessTime = '5 1 * * *'; await this.scheduler.add(this._dailyComputeJobName, dailyComputeProcessTime, async () => this._aggregate()); diff --git a/apps/meteor/app/ui-utils/client/lib/LegacyRoomManager.ts b/apps/meteor/app/ui-utils/client/lib/LegacyRoomManager.ts index d6a8abf9c35da..0c1513e42fbe1 100644 --- a/apps/meteor/app/ui-utils/client/lib/LegacyRoomManager.ts +++ b/apps/meteor/app/ui-utils/client/lib/LegacyRoomManager.ts @@ -177,7 +177,17 @@ const openRoom = (typeName: string, record: OpenedRoom) => { if (msg.t !== 'command') { const subscription = Subscriptions.state.find(({ rid }) => rid === record.rid); const isNew = !Messages.state.find((record) => record._id === msg._id && record.temp !== true); - ({ _id: msg._id, temp: { $ne: true } }); + + // Measure and log message receive delay for messages + if (msg.ts) { + const receiveDelay = Date.now() - new Date(msg.ts).getTime(); + + // Log warning if delay is significant (>2 seconds) + if (receiveDelay > 2000) { + console.warn(`[Message Delivery] High delay detected: ${receiveDelay}ms. Possible network or backend issue.`); + } + } + await upsertMessage({ msg, subscription }); if (isNew) { await clientCallbacks.run('streamNewMessage', msg); diff --git a/apps/meteor/client/components/GenericUpsellModal/hooks/useUpsellActions.spec.ts b/apps/meteor/client/components/GenericUpsellModal/hooks/useUpsellActions.spec.ts new file mode 100644 index 0000000000000..50aff1697fae3 --- /dev/null +++ b/apps/meteor/client/components/GenericUpsellModal/hooks/useUpsellActions.spec.ts @@ -0,0 +1,67 @@ +import { mockAppRoot } from '@rocket.chat/mock-providers'; +import type { UseQueryResult } from '@tanstack/react-query'; +import { renderHook, waitFor } from '@testing-library/react'; + +import { useUpsellActions } from './useUpsellActions'; +import { createFakeLicenseInfo } from '../../../../tests/mocks/data'; +import { useIsEnterprise } from '../../../hooks/useIsEnterprise'; + +jest.mock('../../../hooks/useIsEnterprise', () => ({ + useIsEnterprise: jest.fn(), +})); + +const appRoot = mockAppRoot() + .withJohnDoe() + .withEndpoint('GET', '/v1/licenses.info', async () => ({ license: createFakeLicenseInfo({ hasValidLicense: true }) })) + .build(); + +describe('useUpsellActions hook', () => { + beforeEach(() => { + (useIsEnterprise as jest.Mock).mockImplementation(jest.requireActual('../../../hooks/useIsEnterprise').useIsEnterprise); + }); + + afterAll(() => { + jest.clearAllMocks(); + }); + + it('should show upsell modal if not enterprise', () => { + const { result } = renderHook(() => useUpsellActions(), { + wrapper: mockAppRoot().build(), + }); + + expect(result.current.shouldShowUpsell).toBe(true); + expect(result.current.cloudWorkspaceHadTrial).toBe(false); + }); + + it('should show upsell modal if enterprise but has no license module', async () => { + const { result } = renderHook(() => useUpsellActions(false), { + wrapper: appRoot, + }); + + await waitFor(() => { + expect(result.current.shouldShowUpsell).toBe(true); + }); + }); + + it('should NOT show upsell if enterprise and has license module', async () => { + const { result } = renderHook(() => useUpsellActions(true), { + wrapper: appRoot, + }); + + await waitFor(() => { + expect(result.current.shouldShowUpsell).toBe(false); + }); + }); + + it('should show upsell if useIsEnterprise is undefined', async () => { + (useIsEnterprise as jest.Mock).mockReturnValue({ + data: undefined, + } as UseQueryResult); + + const { result } = renderHook(() => useUpsellActions(true), { + wrapper: mockAppRoot().build(), + }); + + expect(result.current.shouldShowUpsell).toBe(true); + }); +}); diff --git a/apps/meteor/client/components/UserAutoCompleteMultiple/UserAutoCompleteMultiple.tsx b/apps/meteor/client/components/UserAutoCompleteMultiple/UserAutoCompleteMultiple.tsx index 827f88ee309e4..413cab7f6ea0c 100644 --- a/apps/meteor/client/components/UserAutoCompleteMultiple/UserAutoCompleteMultiple.tsx +++ b/apps/meteor/client/components/UserAutoCompleteMultiple/UserAutoCompleteMultiple.tsx @@ -94,7 +94,6 @@ const UserAutoCompleteMultiple = ({ onChange, value, placeholder, federated, ... } icon={_federated ? 'globe' : undefined} key={username} diff --git a/apps/meteor/client/components/UserCard/UserCard.tsx b/apps/meteor/client/components/UserCard/UserCard.tsx index 7482621c49ae4..8a042c0733e72 100644 --- a/apps/meteor/client/components/UserCard/UserCard.tsx +++ b/apps/meteor/client/components/UserCard/UserCard.tsx @@ -18,7 +18,7 @@ const clampStyle = css` overflow: hidden; -webkit-line-clamp: 3; -webkit-box-orient: vertical; - word-break: break-all; + word-break: break-word; `; type UserCardProps = { diff --git a/apps/meteor/client/hooks/useIsEnterprise.ts b/apps/meteor/client/hooks/useIsEnterprise.ts index 884d138211444..e5fa08e0c8ef9 100644 --- a/apps/meteor/client/hooks/useIsEnterprise.ts +++ b/apps/meteor/client/hooks/useIsEnterprise.ts @@ -2,5 +2,5 @@ import { useLicenseBase } from '@rocket.chat/ui-client'; import type { UseQueryResult } from '@tanstack/react-query'; export const useIsEnterprise = (): UseQueryResult<{ isEnterprise: boolean }> => { - return useLicenseBase({ select: (data) => ({ isEnterprise: Boolean(data?.license.license) }) }); + return useLicenseBase({ select: (data) => ({ isEnterprise: Boolean(data?.license.hasValidLicense) }) }); }; diff --git a/apps/meteor/client/hooks/useVoipWarningModal.tsx b/apps/meteor/client/hooks/useVoipWarningModal.tsx deleted file mode 100644 index 568475d3a5efa..0000000000000 --- a/apps/meteor/client/hooks/useVoipWarningModal.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import { useEffectEvent } from '@rocket.chat/fuselage-hooks'; -import { useRole, useRoute, useSetModal } from '@rocket.chat/ui-contexts'; -import { useMemo } from 'react'; - -import { useHasLicenseModule } from './useHasLicenseModule'; -import TeamsVoipConfigModal from '../views/room/contextualBar/TeamsVoipConfigModal'; - -export const useVoipWarningModal = (): (() => void) => { - const setModal = useSetModal(); - const isAdmin = useRole('admin'); - const { data: hasModule = false } = useHasLicenseModule('teams-voip'); - const teamsVoipSettingsRoute = useRoute('admin-settings'); - - const handleClose = useEffectEvent(() => setModal(null)); - - const handleRedirectToConfiguration = useEffectEvent(() => { - handleClose(); - teamsVoipSettingsRoute.push({ - group: 'VoIP_TeamCollab', - }); - }); - - return useMemo( - () => (): void => - setModal( - , - ), - [handleClose, handleRedirectToConfiguration, isAdmin, setModal, hasModule], - ); -}; diff --git a/apps/meteor/client/lib/e2ee/crypto/shared.ts b/apps/meteor/client/lib/e2ee/crypto/shared.ts index ea95b651c6f57..1605a106e53b3 100644 --- a/apps/meteor/client/lib/e2ee/crypto/shared.ts +++ b/apps/meteor/client/lib/e2ee/crypto/shared.ts @@ -1,5 +1,5 @@ const { subtle } = crypto; -export const randomUUID = crypto.randomUUID.bind(crypto); +export const randomUUID = () => crypto.randomUUID(); export const getRandomValues = crypto.getRandomValues.bind(crypto); interface IAesGcmParams extends AesGcmParams { @@ -40,7 +40,7 @@ export const decryptBuffer = ( params: ParamsOf, data: BufferSource, ): Promise => subtle.decrypt(params, key, data) as Promise; -export const deriveBits = subtle.deriveBits.bind(subtle); +export const deriveBits = (...args: Parameters) => subtle.deriveBits(...args); type AesParams = { name: 'AES-CBC' | 'AES-GCM' | 'AES-CTR'; diff --git a/apps/meteor/client/lib/e2ee/rocketchat.e2e.ts b/apps/meteor/client/lib/e2ee/rocketchat.e2e.ts index 7632ee64e9e39..4268630bb50b2 100644 --- a/apps/meteor/client/lib/e2ee/rocketchat.e2e.ts +++ b/apps/meteor/client/lib/e2ee/rocketchat.e2e.ts @@ -345,6 +345,10 @@ class E2E extends Emitter { } async startClient(userId: string): Promise { + if (!isSecureContext) { + throw new Error('E2E encryption can only be enabled in secure contexts (HTTPS)'); + } + const span = log.span('startClient'); if (this.userId === userId) { return; diff --git a/apps/meteor/client/lib/queryKeys.ts b/apps/meteor/client/lib/queryKeys.ts index a619b03178100..9d1a86dea8f3a 100644 --- a/apps/meteor/client/lib/queryKeys.ts +++ b/apps/meteor/client/lib/queryKeys.ts @@ -26,6 +26,10 @@ export const roomsQueryKeys = { threads: (rid: IRoom['_id']) => [...roomsQueryKeys.room(rid), 'threads'] as const, roles: (rid: IRoom['_id']) => [...roomsQueryKeys.room(rid), 'roles'] as const, info: (rid: IRoom['_id']) => [...roomsQueryKeys.room(rid), 'info'] as const, + members: (rid: IRoom['_id'], roomType: RoomType, type?: 'all' | 'online', filter?: string) => + !type && !filter + ? ([...roomsQueryKeys.room(rid), 'members', roomType] as const) + : ([...roomsQueryKeys.room(rid), 'members', roomType, type, filter] as const), }; export const subscriptionsQueryKeys = { @@ -128,17 +132,17 @@ export const ABACQueryKeys = { all: ['abac'] as const, logs: { all: () => [...ABACQueryKeys.all, 'logs'] as const, - list: (query?: PaginatedRequest) => [...ABACQueryKeys.logs.all(), 'list', query] as const, + list: (...args: [query?: PaginatedRequest]) => [...ABACQueryKeys.logs.all(), 'list', ...args] as const, }, roomAttributes: { all: () => [...ABACQueryKeys.all, 'room-attributes'] as const, - list: (query?: PaginatedRequest) => [...ABACQueryKeys.roomAttributes.all(), query] as const, + list: (...args: [query?: PaginatedRequest]) => [...ABACQueryKeys.roomAttributes.all(), ...args] as const, attribute: (attributeId: string) => [...ABACQueryKeys.roomAttributes.all(), attributeId] as const, }, rooms: { all: () => [...ABACQueryKeys.all, 'rooms'] as const, - list: (query?: PaginatedRequest) => [...ABACQueryKeys.rooms.all(), query] as const, - autocomplete: (query?: PaginatedRequest) => [...ABACQueryKeys.rooms.all(), 'autocomplete', query] as const, + list: (...args: [query?: PaginatedRequest]) => [...ABACQueryKeys.rooms.all(), ...args] as const, + autocomplete: (...args: [query?: PaginatedRequest]) => [...ABACQueryKeys.rooms.all(), 'autocomplete', ...args] as const, room: (roomId: string) => [...ABACQueryKeys.rooms.all(), roomId] as const, }, }; diff --git a/apps/meteor/client/meteor/overrides/ddpOverREST.ts b/apps/meteor/client/meteor/overrides/ddpOverREST.ts index 205f0d5a4c6ac..e7fb05275e3ab 100644 --- a/apps/meteor/client/meteor/overrides/ddpOverREST.ts +++ b/apps/meteor/client/meteor/overrides/ddpOverREST.ts @@ -88,7 +88,10 @@ const withDDPOverREST = (_send: (this: Meteor.IMeteorConnection, message: Meteor processResult(_message); }) - .catch((error) => { + .catch(async (error) => { + if ('message' in error && error.message) { + processResult(error.message); + } console.error(error); }); }; diff --git a/apps/meteor/client/navbar/NavBarControls/NavBarControlsWithData.tsx b/apps/meteor/client/navbar/NavBarControls/NavBarControlsWithData.tsx index 04a28da309b3c..1a54983ac5e93 100644 --- a/apps/meteor/client/navbar/NavBarControls/NavBarControlsWithData.tsx +++ b/apps/meteor/client/navbar/NavBarControls/NavBarControlsWithData.tsx @@ -1,6 +1,7 @@ import type { GenericMenuItemProps } from '@rocket.chat/ui-client'; +import { useRouter } from '@rocket.chat/ui-contexts'; import { useMediaCallAction } from '@rocket.chat/ui-voip'; -import type { HTMLAttributes } from 'react'; +import { useCallback, type HTMLAttributes } from 'react'; import { useTranslation } from 'react-i18next'; import NavBarControlsMenu from './NavBarControlsMenu'; @@ -14,6 +15,11 @@ const NavBarControlsWithData = (props: NavBarControlsMenuProps) => { const { t } = useTranslation(); const callAction = useMediaCallAction(); + const router = useRouter(); + const openCallHistory = useCallback(() => { + router.navigate('/call-history'); + }, [router]); + const { isEnabled: queueEnabled, icon: queueIcon, @@ -49,6 +55,7 @@ const NavBarControlsWithData = (props: NavBarControlsMenuProps) => { id: 'rcx-media-call-history', icon: 'clock' as const, content: t('Call_history'), + onClick: openCallHistory, } : undefined; diff --git a/apps/meteor/client/providers/MediaCallProvider.tsx b/apps/meteor/client/providers/MediaCallProvider.tsx index a1e8f552808a0..68d773d49e776 100644 --- a/apps/meteor/client/providers/MediaCallProvider.tsx +++ b/apps/meteor/client/providers/MediaCallProvider.tsx @@ -4,11 +4,8 @@ import type { ReactNode } from 'react'; import { useMemo } from 'react'; import { useHasLicenseModule } from '../hooks/useHasLicenseModule'; -import { useVoipWarningModal } from '../hooks/useVoipWarningModal'; const MediaCallProvider = ({ children }: { children: ReactNode }) => { - const dispatchWarning = useVoipWarningModal(); - const canMakeInternalCall = usePermission('allow-internal-voice-calls'); const canMakeExternalCall = usePermission('allow-external-voice-calls'); @@ -24,21 +21,7 @@ const MediaCallProvider = ({ children }: { children: ReactNode }) => { [], ); - const unlicensedContextValue = useMemo( - () => ({ - state: 'unlicensed' as const, - onToggleWidget: dispatchWarning, - onEndCall: undefined, - peerInfo: undefined, - }), - [dispatchWarning], - ); - - if (!hasModule) { - return {children}; - } - - if (!canMakeInternalCall && !canMakeExternalCall) { + if (!hasModule || (!canMakeInternalCall && !canMakeExternalCall)) { return {children}; } diff --git a/apps/meteor/client/providers/UserProvider/UserProvider.tsx b/apps/meteor/client/providers/UserProvider/UserProvider.tsx index ae9ffd8806f5a..1faeac2f31dab 100644 --- a/apps/meteor/client/providers/UserProvider/UserProvider.tsx +++ b/apps/meteor/client/providers/UserProvider/UserProvider.tsx @@ -4,7 +4,7 @@ import { useLocalStorage } from '@rocket.chat/fuselage-hooks'; import { createPredicateFromFilter } from '@rocket.chat/mongo-adapter'; import { afterLogoutCleanUpCallback } from '@rocket.chat/ui-client'; import type { FindOptions, SubscriptionWithRoom } from '@rocket.chat/ui-contexts'; -import { UserContext, useEndpoint, useRouteParameter, useSearchParameter } from '@rocket.chat/ui-contexts'; +import { UserContext, useRouteParameter, useSearchParameter } from '@rocket.chat/ui-contexts'; import { useQueryClient } from '@tanstack/react-query'; import { Accounts } from 'meteor/accounts-base'; import { Meteor } from 'meteor/meteor'; @@ -79,8 +79,6 @@ const UserProvider = ({ children }: UserProviderProps): ReactElement => { const samlCredentialToken = useSearchParameter('saml_idp_credentialToken'); const inviteTokenHash = useRouteParameter('hash'); - const setUserPreferences = useEndpoint('POST', '/v1/users.setPreferences'); - useEmailVerificationWarning(user ?? undefined); useClearRemovedRoomsHistory(userId); @@ -156,17 +154,22 @@ const UserProvider = ({ children }: UserProviderProps): ReactElement => { [userId, user, querySubscription, querySubscriptions], ); + // Mirror local preference changes into the live userLanguage state without hitting the server. useEffect(() => { - if (!!userId && preferedLanguage !== userLanguage) { - setUserPreferences({ data: { language: preferedLanguage } }); - setUserLanguage(preferedLanguage); + if (preferedLanguage === userLanguage) { + return; } + setUserLanguage(preferedLanguage); + }, [preferedLanguage, setUserLanguage, userLanguage]); + + // When the server reports a new language, overwrite both storage keys so every tab stays aligned. + useEffect(() => { if (user?.language !== undefined && user.language !== userLanguage) { setUserLanguage(user.language); setPreferedLanguage(user.language); } - }, [preferedLanguage, setPreferedLanguage, setUserLanguage, user?.language, userLanguage, userId, setUserPreferences]); + }, [setPreferedLanguage, setUserLanguage, user?.language, userLanguage]); useEffect(() => { if (!samlCredentialToken && !inviteTokenHash) { diff --git a/apps/meteor/client/stores/Messages.ts b/apps/meteor/client/stores/Messages.ts index ff9fcdeee9f38..09706de1d95b2 100644 --- a/apps/meteor/client/stores/Messages.ts +++ b/apps/meteor/client/stores/Messages.ts @@ -6,5 +6,12 @@ import { createGlobalStore } from '../lib/cachedStores/createGlobalStore'; /** @deprecated prefer fetching data from the REST API, listening to changes via streamer events, and storing the state in a Tanstack Query */ export const Messages = createGlobalStore( - createDocumentMapStore(), + createDocumentMapStore< + IMessage & { + ignored?: boolean; + autoTranslateFetching?: boolean; + autoTranslateShowInverse?: boolean; + temp?: boolean; + } + >(), ); diff --git a/apps/meteor/client/views/admin/ABAC/ABACAttributesTab/AttributesContextualBar.tsx b/apps/meteor/client/views/admin/ABAC/ABACAttributesTab/AttributesContextualBar.tsx index a1f22fd11a1dd..7e0971a421097 100644 --- a/apps/meteor/client/views/admin/ABAC/ABACAttributesTab/AttributesContextualBar.tsx +++ b/apps/meteor/client/views/admin/ABAC/ABACAttributesTab/AttributesContextualBar.tsx @@ -30,7 +30,7 @@ const AttributesContextualBar = ({ attributeData, onClose }: AttributesContextua defaultValues: attributeData ? { name: attributeData.key, - attributeValues: [{ value: '' }], + attributeValues: [], lockedAttributes: attributeData.values.map((value) => ({ value })), } : { @@ -71,11 +71,15 @@ const AttributesContextualBar = ({ attributeData, onClose }: AttributesContextua } onClose(); }, - onError: (error) => { - dispatchToastMessage({ type: 'error', message: error }); + onError: (error: { errorType: string; error: string }) => { + if (error.errorType === 'invalid-params') { + dispatchToastMessage({ type: 'error', message: t('ABAC_Invalid_attribute') }); + } else { + dispatchToastMessage({ type: 'error', message: error }); + } }, onSettled: () => { - queryClient.invalidateQueries({ queryKey: ABACQueryKeys.roomAttributes.list({}) }); + queryClient.invalidateQueries({ queryKey: ABACQueryKeys.roomAttributes.list() }); }, }); diff --git a/apps/meteor/client/views/admin/ABAC/ABACSettingTab/__snapshots__/SettingToggle.spec.tsx.snap b/apps/meteor/client/views/admin/ABAC/ABACSettingTab/__snapshots__/SettingToggle.spec.tsx.snap index 7c48a94fb6800..78b091fbbf32f 100644 --- a/apps/meteor/client/views/admin/ABAC/ABACSettingTab/__snapshots__/SettingToggle.spec.tsx.snap +++ b/apps/meteor/client/views/admin/ABAC/ABACSettingTab/__snapshots__/SettingToggle.spec.tsx.snap @@ -31,7 +31,6 @@ exports[`AbacEnabledToggle should be disabled when abac license is not installed diff --git a/apps/meteor/client/views/admin/settings/Setting/inputs/BooleanSettingInput.tsx b/apps/meteor/client/views/admin/settings/Setting/inputs/BooleanSettingInput.tsx index 624150b1709b6..367a8efe5aff7 100644 --- a/apps/meteor/client/views/admin/settings/Setting/inputs/BooleanSettingInput.tsx +++ b/apps/meteor/client/views/admin/settings/Setting/inputs/BooleanSettingInput.tsx @@ -30,14 +30,8 @@ function BooleanSettingInput({ {label} - {hasResetButton && } - + {hasResetButton && } + {hint && {hint}} diff --git a/apps/meteor/client/views/admin/settings/Setting/inputs/CodeSettingInput.tsx b/apps/meteor/client/views/admin/settings/Setting/inputs/CodeSettingInput.tsx index 4302ad165000e..bed4565cf80aa 100644 --- a/apps/meteor/client/views/admin/settings/Setting/inputs/CodeSettingInput.tsx +++ b/apps/meteor/client/views/admin/settings/Setting/inputs/CodeSettingInput.tsx @@ -38,12 +38,11 @@ function CodeSettingInput({ {label} - {hasResetButton && } + {hasResetButton && } {hint && {hint}} {label} - {hasResetButton && } + {hasResetButton && } @@ -61,7 +61,6 @@ function ColorSettingInput({ {editor === 'color' && ( {label} - {hasResetButton && } + {hasResetButton && } {label} - {hasResetButton && } + {hasResetButton && } onChangeType(key as TypeFilter)} /> - - - + + +