diff --git a/.changeset/chatty-hounds-hammer.md b/.changeset/chatty-hounds-hammer.md new file mode 100644 index 000000000000..1a2d3a7de559 --- /dev/null +++ b/.changeset/chatty-hounds-hammer.md @@ -0,0 +1,6 @@ +--- +"@rocket.chat/meteor": patch +"@rocket.chat/fuselage-ui-kit": patch +--- + +Fix validations from "UiKit" modal component diff --git a/.changeset/chilled-yaks-beg.md b/.changeset/chilled-yaks-beg.md new file mode 100644 index 000000000000..670fa24887b7 --- /dev/null +++ b/.changeset/chilled-yaks-beg.md @@ -0,0 +1,5 @@ +--- +"@rocket.chat/meteor": patch +--- + +Fixed issue in Marketplace that caused a subscription app to show incorrect modals when subscribing diff --git a/.changeset/cuddly-brooms-approve.md b/.changeset/cuddly-brooms-approve.md new file mode 100644 index 000000000000..24905bb91c62 --- /dev/null +++ b/.changeset/cuddly-brooms-approve.md @@ -0,0 +1,6 @@ +--- +"@rocket.chat/meteor": minor +"@rocket.chat/i18n": minor +--- + +Allows admins to customize the `Subject` field of Omnichannel email transcripts via setting. By passing a value to the setting `Custom email subject for transcript`, system will use it as the `Subject` field, unless a custom subject is passed when requesting a transcript. If there's no custom subject and setting value is empty, the current default value will be used diff --git a/.changeset/dry-pumas-draw.md b/.changeset/dry-pumas-draw.md new file mode 100644 index 000000000000..b66ca5157cd5 --- /dev/null +++ b/.changeset/dry-pumas-draw.md @@ -0,0 +1,6 @@ +--- +"@rocket.chat/meteor": patch +"@rocket.chat/livechat": patch +--- + +Fixed an issue that caused the widget to set the wrong department when using the setDepartment Livechat api endpoint in conjunction with a Livechat Trigger diff --git a/.changeset/funny-wolves-tie.md b/.changeset/funny-wolves-tie.md new file mode 100644 index 000000000000..e2364ccb05e5 --- /dev/null +++ b/.changeset/funny-wolves-tie.md @@ -0,0 +1,5 @@ +--- +'@rocket.chat/meteor': patch +--- + +Fixed issue where bad word filtering was not working in the UI for messages diff --git a/.changeset/hungry-wombats-act.md b/.changeset/hungry-wombats-act.md new file mode 100644 index 000000000000..4e50b172e17e --- /dev/null +++ b/.changeset/hungry-wombats-act.md @@ -0,0 +1,5 @@ +--- +"@rocket.chat/meteor": patch +--- + +Fixed an issue where non-encrypted attachments were not being downloaded diff --git a/.changeset/large-vans-attack.md b/.changeset/large-vans-attack.md new file mode 100644 index 000000000000..c1008b2ca06f --- /dev/null +++ b/.changeset/large-vans-attack.md @@ -0,0 +1,5 @@ +--- +"@rocket.chat/meteor": patch +--- + +fixed the contextual bar closing when editing thread messages instead of cancelling the message edit diff --git a/.changeset/many-tables-love.md b/.changeset/many-tables-love.md new file mode 100644 index 000000000000..8f37283c6a96 --- /dev/null +++ b/.changeset/many-tables-love.md @@ -0,0 +1,6 @@ +--- +"@rocket.chat/meteor": minor +"@rocket.chat/model-typings": minor +--- + +Fixed Livechat rooms being displayed in the Engagement Dashboard's "Channels" tab diff --git a/.changeset/cuddly-ravens-swim.md b/.changeset/mean-hairs-move.md similarity index 84% rename from .changeset/cuddly-ravens-swim.md rename to .changeset/mean-hairs-move.md index 5774ef48202d..c92293d6ae95 100644 --- a/.changeset/cuddly-ravens-swim.md +++ b/.changeset/mean-hairs-move.md @@ -1,5 +1,5 @@ --- -"@rocket.chat/meteor": patch +'@rocket.chat/meteor': minor --- Fixed an issue where adding `OVERWRITE_SETTING_` for any setting wasn't immediately taking effect sometimes, and needed a server restart to reflect. diff --git a/.changeset/new-balloons-speak.md b/.changeset/new-balloons-speak.md new file mode 100644 index 000000000000..7d4e7cd3a57e --- /dev/null +++ b/.changeset/new-balloons-speak.md @@ -0,0 +1,5 @@ +--- +'@rocket.chat/meteor': patch +--- + +Fixed web client crashing on Firefox private window. Firefox disables access to service workers inside private windows. Rocket.Chat needs service workers to process E2EE encrypted files on rooms. These types of files won't be available inside private windows, but the rest of E2EE encrypted features should work normally diff --git a/.changeset/new-scissors-love.md b/.changeset/new-scissors-love.md new file mode 100644 index 000000000000..fb962407b353 --- /dev/null +++ b/.changeset/new-scissors-love.md @@ -0,0 +1,12 @@ +--- +'@rocket.chat/omnichannel-services': minor +'@rocket.chat/pdf-worker': minor +'@rocket.chat/core-services': minor +'@rocket.chat/model-typings': minor +'@rocket.chat/i18n': minor +'@rocket.chat/meteor': minor +--- + +Added system messages support for Omnichannel PDF transcripts and email transcripts. Currently these transcripts don't render system messages and is shown as an empty message in PDF/email. This PR adds this support for all valid livechat system messages. + +Also added a new setting under transcripts, to toggle the inclusion of system messages in email and PDF transcripts. diff --git a/.changeset/nice-laws-eat.md b/.changeset/nice-laws-eat.md new file mode 100644 index 000000000000..e99e4f219ef9 --- /dev/null +++ b/.changeset/nice-laws-eat.md @@ -0,0 +1,15 @@ +--- +'rocketchat-services': minor +'@rocket.chat/core-services': minor +'@rocket.chat/model-typings': minor +'@rocket.chat/ui-video-conf': minor +'@rocket.chat/core-typings': minor +'@rocket.chat/ui-contexts': minor +'@rocket.chat/models': minor +'@rocket.chat/ui-kit': minor +'@rocket.chat/i18n': minor +'@rocket.chat/meteor': minor +--- + +New Feature: Video Conference Persistent Chat. +This feature provides a discussion id for conference provider apps to store the chat messages exchanged during the conferences, so that those users may then access those messages again at any time through Rocket.Chat. \ No newline at end of file diff --git a/.changeset/perfect-coins-camp.md b/.changeset/perfect-coins-camp.md new file mode 100644 index 000000000000..4dbddf965742 --- /dev/null +++ b/.changeset/perfect-coins-camp.md @@ -0,0 +1,5 @@ +--- +"@rocket.chat/meteor": patch +--- + +fixed an issue in the "Create discussion" form, that would have the "Create" action button disabled even though the form is prefilled when opening it from the message action diff --git a/.changeset/polite-foxes-repair.md b/.changeset/polite-foxes-repair.md new file mode 100644 index 000000000000..2f524c7e5f10 --- /dev/null +++ b/.changeset/polite-foxes-repair.md @@ -0,0 +1,5 @@ +--- +'@rocket.chat/meteor': minor +--- + +Added a method to the Apps-Engine that allows apps to read multiple messages from a room diff --git a/.changeset/popular-trees-lay.md b/.changeset/popular-trees-lay.md new file mode 100644 index 000000000000..f38ef1f92367 --- /dev/null +++ b/.changeset/popular-trees-lay.md @@ -0,0 +1,5 @@ +--- +"@rocket.chat/meteor": patch +--- + +Removed 'Hide' option in the room menu for Omnichannel conversations. diff --git a/.changeset/proud-waves-bathe.md b/.changeset/proud-waves-bathe.md new file mode 100644 index 000000000000..556fa3af80e1 --- /dev/null +++ b/.changeset/proud-waves-bathe.md @@ -0,0 +1,6 @@ +--- +"@rocket.chat/meteor": minor +"@rocket.chat/model-typings": minor +--- + +Improved Engagement Dashboard's "Channels" tab performance by not returning rooms that had no activity in the analyzed period diff --git a/.changeset/quick-ducks-live.md b/.changeset/quick-ducks-live.md new file mode 100644 index 000000000000..ad628c13d087 --- /dev/null +++ b/.changeset/quick-ducks-live.md @@ -0,0 +1,5 @@ +--- +"@rocket.chat/meteor": patch +--- + +Fixed LDAP rooms, teams and roles syncs not being triggered on login even when the "Update User Data on Login" setting is enabled diff --git a/.changeset/red-numbers-happen.md b/.changeset/red-numbers-happen.md new file mode 100644 index 000000000000..61cb0d2b7586 --- /dev/null +++ b/.changeset/red-numbers-happen.md @@ -0,0 +1,5 @@ +--- +"@rocket.chat/meteor": patch +--- + +Fixed "Copy link" message action enabled in Starred and Pinned list for End to End Encrypted channels, this action is disabled now diff --git a/.changeset/red-vans-shave.md b/.changeset/red-vans-shave.md new file mode 100644 index 000000000000..ddf76535087e --- /dev/null +++ b/.changeset/red-vans-shave.md @@ -0,0 +1,5 @@ +--- +"@rocket.chat/meteor": patch +--- + +Fixed issue that caused unintentional clicks when scrolling the channels sidebar on safari/chrome in iOS diff --git a/.changeset/rich-carpets-brush.md b/.changeset/rich-carpets-brush.md new file mode 100644 index 000000000000..16741e31e54a --- /dev/null +++ b/.changeset/rich-carpets-brush.md @@ -0,0 +1,5 @@ +--- +'@rocket.chat/meteor': patch +--- + +Fixed some anomalies related to disabled E2EE rooms. Earlier there are some weird issues with disabled E2EE rooms, this PR fixes these anomalies. diff --git a/.changeset/shaggy-hats-raise.md b/.changeset/shaggy-hats-raise.md new file mode 100644 index 000000000000..40ee9f8fbb55 --- /dev/null +++ b/.changeset/shaggy-hats-raise.md @@ -0,0 +1,5 @@ +--- +"@rocket.chat/meteor": minor +--- + +Added a new setting `Livechat_transcript_send_always` that allows admins to decide if email transcript should be sent all the times when a conversation is closed. This setting bypasses agent's preferences. For this setting to work, `Livechat_enable_transcript` should be off, meaning that visitors will no longer receive the option to decide if they want a transcript or not. diff --git a/.changeset/sixty-nails-clean.md b/.changeset/sixty-nails-clean.md new file mode 100644 index 000000000000..7d13e02f0bd3 --- /dev/null +++ b/.changeset/sixty-nails-clean.md @@ -0,0 +1,5 @@ +--- +'@rocket.chat/meteor': patch +--- + +Fixed an issue that prevented the option to start a discussion from being shown on the message actions diff --git a/.changeset/smooth-lobsters-flash.md b/.changeset/smooth-lobsters-flash.md new file mode 100644 index 000000000000..541d5069ee9c --- /dev/null +++ b/.changeset/smooth-lobsters-flash.md @@ -0,0 +1,5 @@ +--- +'@rocket.chat/meteor': patch +--- + +Fix show correct user roles after updating user roles on admin edit user panel. diff --git a/.changeset/soft-donkeys-thank.md b/.changeset/soft-donkeys-thank.md new file mode 100644 index 000000000000..7273ddcffca4 --- /dev/null +++ b/.changeset/soft-donkeys-thank.md @@ -0,0 +1,8 @@ +--- +"@rocket.chat/meteor": patch +"@rocket.chat/mock-providers": patch +"@rocket.chat/ui-contexts": patch +"@rocket.chat/web-ui-registration": patch +--- + +Fixed an issue with blocked login when dismissed 2FA modal by clicking outside of it or pressing the escape key diff --git a/.changeset/violet-brooms-press.md b/.changeset/violet-brooms-press.md new file mode 100644 index 000000000000..632026d6fe2e --- /dev/null +++ b/.changeset/violet-brooms-press.md @@ -0,0 +1,5 @@ +--- +'@rocket.chat/meteor': patch +--- + +Security Hotfix (https://docs.rocket.chat/guides/security/security-updates) diff --git a/.changeset/weak-insects-sort.md b/.changeset/weak-insects-sort.md new file mode 100644 index 000000000000..cbbe7c4aa08c --- /dev/null +++ b/.changeset/weak-insects-sort.md @@ -0,0 +1,5 @@ +--- +"@rocket.chat/meteor": patch +--- + +Improving UX by change the position of room info actions buttons and menu order to avoid missclick in destructive actions. diff --git a/.changeset/weak-pets-talk.md b/.changeset/weak-pets-talk.md new file mode 100644 index 000000000000..abaa9c683d65 --- /dev/null +++ b/.changeset/weak-pets-talk.md @@ -0,0 +1,7 @@ +--- +'@rocket.chat/omnichannel-services': patch +'@rocket.chat/core-services': patch +'@rocket.chat/meteor': patch +--- + +Reduced time on generation of PDF transcripts. Earlier Rocket.Chat was fetching the required translations everytime a PDF transcript was requested, this process was async and was being unnecessarily being performed on every pdf transcript request. This PR improves this and now the translations are loaded at the start and kept in memory to process further pdf transcripts requests. This reduces the time of asynchronously fetching translations again and again. diff --git a/.changeset/weak-taxis-design.md b/.changeset/weak-taxis-design.md new file mode 100644 index 000000000000..a2d435495cd7 --- /dev/null +++ b/.changeset/weak-taxis-design.md @@ -0,0 +1,5 @@ +--- +'@rocket.chat/meteor': minor +--- + +Added handling of attachments in Omnichannel email transcripts. Earlier attachments were being skipped and were being shown as empty space, now it should render the image attachments and should show relevant error message for unsupported attachments. diff --git a/.changeset/weak-tigers-suffer.md b/.changeset/weak-tigers-suffer.md new file mode 100644 index 000000000000..91748a43c677 --- /dev/null +++ b/.changeset/weak-tigers-suffer.md @@ -0,0 +1,7 @@ +--- +"@rocket.chat/meteor": minor +"@rocket.chat/model-typings": minor +"@rocket.chat/rest-typings": minor +--- + +Added the ability to filter chats by `queued` on the Current Chats Omnichannel page diff --git a/.changeset/witty-bats-develop.md b/.changeset/witty-bats-develop.md new file mode 100644 index 000000000000..42c9409d9ef3 --- /dev/null +++ b/.changeset/witty-bats-develop.md @@ -0,0 +1,13 @@ +--- +"@rocket.chat/meteor": patch +"@rocket.chat/apps": patch +"@rocket.chat/core-services": patch +"@rocket.chat/core-typings": patch +"@rocket.chat/fuselage-ui-kit": patch +"@rocket.chat/rest-typings": patch +"@rocket.chat/ddp-streamer": patch +"@rocket.chat/presence": patch +"rocketchat-services": patch +--- + +Added the `user` param to apps-engine update method call, allowing apps' new `onUpdate` hook to know who triggered the update. diff --git a/.github/workflows/ci-test-e2e.yml b/.github/workflows/ci-test-e2e.yml index 920aea0aa308..6ac9d751fc7a 100644 --- a/.github/workflows/ci-test-e2e.yml +++ b/.github/workflows/ci-test-e2e.yml @@ -99,6 +99,15 @@ jobs: job_summary: true comment_on_pr: false + - name: Setup kernel limits + run: | + sudo sysctl -w net.ipv4.ip_local_port_range="500 65535" + sudo sysctl -w net.ipv4.tcp_mem="383865 511820 2303190" + + echo fs.file-max=20000500 | sudo tee -a /etc/sysctl.conf + echo fs.nr_open=20000500 | sudo tee -a /etc/sysctl.conf + sudo sysctl -p + - name: Login to GitHub Container Registry if: (github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'release' || github.ref == 'refs/heads/develop') uses: docker/login-action@v2 diff --git a/README.md b/README.md index 64dec811e1ca..56e38c111e97 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,10 @@ yarn dsv # run only meteor (front and back) with pre-built packages After initialized, you can access the server at http://localhost:3000 +More details at: [Developer Docs](https://developer.rocket.chat/v1/docs/server-environment-setup) +PS: For Windows you MUST use WSL2 and have +12Gb RAM + + # Gitpod Setup 1. Click the button below to open this project in Gitpod. diff --git a/apps/meteor/CHANGELOG.md b/apps/meteor/CHANGELOG.md index a3458db7863b..75ffb7f02d7a 100644 --- a/apps/meteor/CHANGELOG.md +++ b/apps/meteor/CHANGELOG.md @@ -1,5 +1,47 @@ # @rocket.chat/meteor +## 6.10.1 + +### Patch Changes + +- Bump @rocket.chat/meteor version. + +- Bump @rocket.chat/meteor version. + +- ([#32819](https://github.com/RocketChat/Rocket.Chat/pull/32819) by [@dionisio-bot](https://github.com/dionisio-bot)) Fixed issue with livechat agents not being able to leave omnichannel rooms if joining after a room has been closed by the visitor (due to race conditions) + +- ([#32894](https://github.com/RocketChat/Rocket.Chat/pull/32894)) Security Hotfix (https://docs.rocket.chat/docs/security-fixes-and-updates) + +- ([#32829](https://github.com/RocketChat/Rocket.Chat/pull/32829) by [@dionisio-bot](https://github.com/dionisio-bot)) Fixes an issue not displaying all groups in settings list + +- ([#32836](https://github.com/RocketChat/Rocket.Chat/pull/32836) by [@dionisio-bot](https://github.com/dionisio-bot)) Security Hotfix (https://docs.rocket.chat/guides/security/security-updates) + +-
Updated dependencies []: + + - @rocket.chat/core-typings@6.10.1 + - @rocket.chat/rest-typings@6.10.1 + - @rocket.chat/api-client@0.2.1 + - @rocket.chat/license@0.2.1 + - @rocket.chat/omnichannel-services@0.2.1 + - @rocket.chat/pdf-worker@0.1.1 + - @rocket.chat/presence@0.2.1 + - @rocket.chat/apps@0.1.1 + - @rocket.chat/core-services@0.4.1 + - @rocket.chat/cron@0.1.1 + - @rocket.chat/fuselage-ui-kit@8.0.1 + - @rocket.chat/gazzodown@8.0.1 + - @rocket.chat/model-typings@0.5.1 + - @rocket.chat/ui-contexts@8.0.1 + - @rocket.chat/server-cloud-communication@0.0.2 + - @rocket.chat/models@0.1.1 + - @rocket.chat/ui-theming@0.2.0 + - @rocket.chat/ui-avatar@4.0.1 + - @rocket.chat/ui-client@8.0.1 + - @rocket.chat/ui-video-conf@8.0.1 + - @rocket.chat/web-ui-registration@8.0.1 + - @rocket.chat/instance-status@0.1.1 +
+ ## 6.10.0 ### Minor Changes diff --git a/apps/meteor/app/2fa/server/methods/checkCodesRemaining.ts b/apps/meteor/app/2fa/server/methods/checkCodesRemaining.ts index 219a78483cea..f5f5b0e1f275 100644 --- a/apps/meteor/app/2fa/server/methods/checkCodesRemaining.ts +++ b/apps/meteor/app/2fa/server/methods/checkCodesRemaining.ts @@ -1,7 +1,7 @@ -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { '2fa:checkCodesRemaining': () => { remaining: number }; diff --git a/apps/meteor/app/2fa/server/methods/disable.ts b/apps/meteor/app/2fa/server/methods/disable.ts index 0927b3f854ac..d2c71febdc35 100644 --- a/apps/meteor/app/2fa/server/methods/disable.ts +++ b/apps/meteor/app/2fa/server/methods/disable.ts @@ -1,10 +1,10 @@ +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Users } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { TOTP } from '../lib/totp'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { '2fa:disable': (code: string) => Promise; diff --git a/apps/meteor/app/2fa/server/methods/enable.ts b/apps/meteor/app/2fa/server/methods/enable.ts index 3b9f35dfcd9d..dea859d27b62 100644 --- a/apps/meteor/app/2fa/server/methods/enable.ts +++ b/apps/meteor/app/2fa/server/methods/enable.ts @@ -1,10 +1,10 @@ +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Users } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { TOTP } from '../lib/totp'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { '2fa:enable': () => Promise<{ secret: string; url: string }>; @@ -34,6 +34,10 @@ Meteor.methods({ }); } + if (user.services?.totp?.enabled) { + throw new Meteor.Error('error-2fa-already-enabled'); + } + const secret = TOTP.generateSecret(); await Users.disable2FAAndSetTempSecretByUserId(userId, secret.base32); diff --git a/apps/meteor/app/2fa/server/methods/regenerateCodes.ts b/apps/meteor/app/2fa/server/methods/regenerateCodes.ts index e0f4cfaa4797..6968abfb93c2 100644 --- a/apps/meteor/app/2fa/server/methods/regenerateCodes.ts +++ b/apps/meteor/app/2fa/server/methods/regenerateCodes.ts @@ -1,10 +1,10 @@ +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Users } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { TOTP } from '../lib/totp'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { '2fa:regenerateCodes': (userToken: string) => { codes: string[] } | undefined; diff --git a/apps/meteor/app/2fa/server/methods/validateTempToken.ts b/apps/meteor/app/2fa/server/methods/validateTempToken.ts index cc2b44372a04..840fadc8cbf7 100644 --- a/apps/meteor/app/2fa/server/methods/validateTempToken.ts +++ b/apps/meteor/app/2fa/server/methods/validateTempToken.ts @@ -1,11 +1,11 @@ +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Users } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { notifyOnUserChangeAsync } from '../../../lib/server/lib/notifyListener'; import { TOTP } from '../lib/totp'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { '2fa:validateTempToken': (userToken: string) => { codes: string[] } | undefined; diff --git a/apps/meteor/app/api/server/v1/chat.ts b/apps/meteor/app/api/server/v1/chat.ts index c482e3bb784d..3ccc9caeafa0 100644 --- a/apps/meteor/app/api/server/v1/chat.ts +++ b/apps/meteor/app/api/server/v1/chat.ts @@ -18,6 +18,7 @@ import { executeUpdateMessage } from '../../../lib/server/methods/updateMessage' import { OEmbed } from '../../../oembed/server/server'; import { executeSetReaction } from '../../../reactions/server/setReaction'; import { settings } from '../../../settings/server'; +import { MessageTypes } from '../../../ui-utils/server'; import { normalizeMessagesForUser } from '../../../utils/server/lib/normalizeMessagesForUser'; import { API } from '../api'; import { getPaginationItems } from '../helpers/getPaginationItems'; @@ -217,6 +218,10 @@ API.v1.addRoute( throw new Meteor.Error('error-invalid-params', 'The "message" parameter must be provided.'); } + if (MessageTypes.isSystemMessage(this.bodyParams.message)) { + throw new Error("Cannot send system messages using 'chat.sendMessage'"); + } + const sent = await executeSendMessage(this.userId, this.bodyParams.message as Pick, this.bodyParams.previewUrls); const [message] = await normalizeMessagesForUser([sent], this.userId); diff --git a/apps/meteor/app/api/server/v1/users.ts b/apps/meteor/app/api/server/v1/users.ts index 041ef0410df0..7ae585b89dfa 100644 --- a/apps/meteor/app/api/server/v1/users.ts +++ b/apps/meteor/app/api/server/v1/users.ts @@ -44,6 +44,7 @@ import { setStatusText } from '../../../lib/server/functions/setStatusText'; import { setUserAvatar } from '../../../lib/server/functions/setUserAvatar'; import { setUsernameWithValidation } from '../../../lib/server/functions/setUsername'; import { validateCustomFields } from '../../../lib/server/functions/validateCustomFields'; +import { validateNameChars } from '../../../lib/server/functions/validateNameChars'; import { notifyOnUserChange, notifyOnUserChangeAsync } from '../../../lib/server/lib/notifyListener'; import { generateAccessToken } from '../../../lib/server/methods/createToken'; import { settings } from '../../../settings/server'; @@ -95,6 +96,10 @@ API.v1.addRoute( async post() { const userData = { _id: this.bodyParams.userId, ...this.bodyParams.data }; + if (userData.name && !validateNameChars(userData.name)) { + return API.v1.failure('Name contains invalid characters'); + } + await saveUser(this.userId, userData); if (this.bodyParams.data.customFields) { @@ -139,6 +144,10 @@ API.v1.addRoute( typedPassword: this.bodyParams.data.currentPassword, }; + if (userData.realname && !validateNameChars(userData.realname)) { + return API.v1.failure('Name contains invalid characters'); + } + // saveUserProfile now uses the default two factor authentication procedures, so we need to provide that const twoFactorOptions = !userData.typedPassword ? null @@ -281,6 +290,10 @@ API.v1.addRoute( this.bodyParams.joinDefaultChannels = true; } + if (this.bodyParams.name && !validateNameChars(this.bodyParams.name)) { + return API.v1.failure('Name contains invalid characters'); + } + if (this.bodyParams.customFields) { validateCustomFields(this.bodyParams.customFields); } @@ -628,16 +641,20 @@ API.v1.addRoute( }, { async post() { + const { secret: secretURL, ...params } = this.bodyParams; + if (this.userId) { return API.v1.failure('Logged in users can not register again.'); } + if (params.name && !validateNameChars(params.name)) { + return API.v1.failure('Name contains invalid characters'); + } + if (!(await checkUsernameAvailability(this.bodyParams.username))) { return API.v1.failure('Username is already in use'); } - const { secret: secretURL, ...params } = this.bodyParams; - if (this.bodyParams.customFields) { try { await validateCustomFields(this.bodyParams.customFields); @@ -1199,7 +1216,7 @@ API.v1.addRoute( throw new Meteor.Error('error-invalid-user-id', 'Invalid user id'); } - void notifyOnUserChange({ clientAction: 'updated', id: this.userId, diff: { 'services.resume.loginTokens': [] } }); + void notifyOnUserChange({ clientAction: 'updated', id: userId, diff: { 'services.resume.loginTokens': [] } }); return API.v1.success({ message: `User ${userId} has been logged out!`, diff --git a/apps/meteor/app/apps/server/bridges/livechat.ts b/apps/meteor/app/apps/server/bridges/livechat.ts index 4e2f8e69acad..ec5cff29a99b 100644 --- a/apps/meteor/app/apps/server/bridges/livechat.ts +++ b/apps/meteor/app/apps/server/bridges/livechat.ts @@ -246,7 +246,8 @@ export class AppLivechatBridge extends LivechatBridge { username, name, type, - }; + userType: 'user', + } as const; let userId; let transferredTo; diff --git a/apps/meteor/app/apps/server/bridges/rooms.ts b/apps/meteor/app/apps/server/bridges/rooms.ts index 86817c5721e2..344acc74bda4 100644 --- a/apps/meteor/app/apps/server/bridges/rooms.ts +++ b/apps/meteor/app/apps/server/bridges/rooms.ts @@ -1,11 +1,13 @@ import type { IAppServerOrchestrator } from '@rocket.chat/apps'; -import type { IMessage } from '@rocket.chat/apps-engine/definition/messages'; +import type { IMessage, IMessageRaw } from '@rocket.chat/apps-engine/definition/messages'; import type { IRoom } from '@rocket.chat/apps-engine/definition/rooms'; import { RoomType } from '@rocket.chat/apps-engine/definition/rooms'; import type { IUser } from '@rocket.chat/apps-engine/definition/users'; +import type { GetMessagesOptions } from '@rocket.chat/apps-engine/server/bridges/RoomBridge'; import { RoomBridge } from '@rocket.chat/apps-engine/server/bridges/RoomBridge'; -import type { ISubscription, IUser as ICoreUser, IRoom as ICoreRoom } from '@rocket.chat/core-typings'; -import { Subscriptions, Users, Rooms } from '@rocket.chat/models'; +import type { ISubscription, IUser as ICoreUser, IRoom as ICoreRoom, IMessage as ICoreMessage } from '@rocket.chat/core-typings'; +import { Subscriptions, Users, Rooms, Messages } from '@rocket.chat/models'; +import type { FindOptions, Sort } from 'mongodb'; import { createDirectMessage } from '../../../../server/methods/createDirectMessage'; import { createDiscussion } from '../../../discussion/server/methods/createDiscussion'; @@ -103,6 +105,38 @@ export class AppRoomBridge extends RoomBridge { return this.orch.getConverters()?.get('users').convertById(room.u._id); } + protected async getMessages(roomId: string, options: GetMessagesOptions, appId: string): Promise { + this.orch.debugLog(`The App ${appId} is getting the messages of the room: "${roomId}" with options:`, options); + + const { limit, skip = 0, sort: _sort } = options; + + const messageConverter = this.orch.getConverters()?.get('messages'); + if (!messageConverter) { + throw new Error('Message converter not found'); + } + + // We support only one field for now + const sort: Sort | undefined = _sort?.createdAt ? { ts: _sort.createdAt } : undefined; + + const messageQueryOptions: FindOptions = { + limit, + skip, + sort, + }; + + const query = { + rid: roomId, + _hidden: { $ne: true }, + t: { $exists: false }, + }; + + const cursor = Messages.find(query, messageQueryOptions); + + const messagePromises: Promise[] = await cursor.map((message) => messageConverter.convertMessageRaw(message)).toArray(); + + return Promise.all(messagePromises); + } + protected async getMembers(roomId: string, appId: string): Promise> { this.orch.debugLog(`The App ${appId} is getting the room's members by room id: "${roomId}"`); const subscriptions = await Subscriptions.findByRoomId(roomId, {}); @@ -220,12 +254,4 @@ export class AppRoomBridge extends RoomBridge { const members = await Users.findUsersByUsernames(usernames, { limit: 50 }).toArray(); await Promise.all(members.map((user) => removeUserFromRoom(roomId, user))); } - - protected getMessages( - _roomId: string, - _options: { limit: number; skip?: number; sort?: Record }, - _appId: string, - ): Promise { - throw new Error('Method not implemented.'); - } } diff --git a/apps/meteor/app/apps/server/bridges/videoConferences.ts b/apps/meteor/app/apps/server/bridges/videoConferences.ts index bebcb25a6f51..efab0f201f87 100644 --- a/apps/meteor/app/apps/server/bridges/videoConferences.ts +++ b/apps/meteor/app/apps/server/bridges/videoConferences.ts @@ -59,6 +59,10 @@ export class AppVideoConferenceBridge extends VideoConferenceBridge { if (data.status > oldData.status) { await VideoConf.setStatus(call._id, data.status); } + + if (data.discussionRid !== oldData.discussionRid) { + await VideoConf.assignDiscussionToConference(call._id, data.discussionRid); + } } protected async registerProvider(info: IVideoConfProvider, appId: string): Promise { diff --git a/apps/meteor/app/apps/server/converters/cachedFunction.ts b/apps/meteor/app/apps/server/converters/cachedFunction.ts new file mode 100644 index 000000000000..3310574f0160 --- /dev/null +++ b/apps/meteor/app/apps/server/converters/cachedFunction.ts @@ -0,0 +1,17 @@ +export const cachedFunction = any>(fn: F) => { + const cache = new Map(); + + return ((...args) => { + const cacheKey = JSON.stringify(args); + + if (cache.has(cacheKey)) { + return cache.get(cacheKey) as ReturnType; + } + + const result = fn(...args); + + cache.set(cacheKey, result); + + return result; + }) as F; +}; diff --git a/apps/meteor/app/apps/server/converters/messages.js b/apps/meteor/app/apps/server/converters/messages.js index 187a6519339a..d7dae512e9a8 100644 --- a/apps/meteor/app/apps/server/converters/messages.js +++ b/apps/meteor/app/apps/server/converters/messages.js @@ -1,9 +1,13 @@ +import { isMessageFromVisitor } from '@rocket.chat/core-typings'; import { Messages, Rooms, Users } from '@rocket.chat/models'; import { Random } from '@rocket.chat/random'; +import { cachedFunction } from './cachedFunction'; import { transformMappedData } from './transformMappedData'; export class AppMessagesConverter { + mem = new WeakMap(); + constructor(orch) { this.orch = orch; } @@ -14,11 +18,54 @@ export class AppMessagesConverter { return this.convertMessage(msg); } + async convertMessageRaw(msgObj) { + if (!msgObj) { + return undefined; + } + + const { attachments, ...message } = msgObj; + const getAttachments = async () => this._convertAttachmentsToApp(attachments); + + const map = { + id: '_id', + threadId: 'tmid', + reactions: 'reactions', + parseUrls: 'parseUrls', + text: 'msg', + createdAt: 'ts', + updatedAt: '_updatedAt', + editedAt: 'editedAt', + emoji: 'emoji', + avatarUrl: 'avatar', + alias: 'alias', + file: 'file', + customFields: 'customFields', + groupable: 'groupable', + token: 'token', + blocks: 'blocks', + roomId: 'rid', + editor: 'editedBy', + attachments: getAttachments, + sender: 'u', + }; + + return transformMappedData(message, map); + } + async convertMessage(msgObj) { if (!msgObj) { return undefined; } + const cache = + this.mem.get(msgObj) ?? + new Map([ + ['room', cachedFunction(this.orch.getConverters().get('rooms').convertById.bind(this.orch.getConverters().get('rooms')))], + ['user', cachedFunction(this.orch.getConverters().get('users').convertById.bind(this.orch.getConverters().get('users')))], + ]); + + this.mem.set(msgObj, cache); + const map = { id: '_id', threadId: 'tmid', @@ -37,7 +84,7 @@ export class AppMessagesConverter { token: 'token', blocks: 'blocks', room: async (message) => { - const result = await this.orch.getConverters().get('rooms').convertById(message.rid); + const result = await cache.get('room')(message.rid); delete message.rid; return result; }, @@ -49,7 +96,7 @@ export class AppMessagesConverter { return undefined; } - return this.orch.getConverters().get('users').convertById(editedBy._id); + return cache.get('user')(editedBy._id); }, attachments: async (message) => { const result = await this._convertAttachmentsToApp(message.attachments); @@ -61,16 +108,19 @@ export class AppMessagesConverter { return undefined; } - let user = await this.orch.getConverters().get('users').convertById(message.u._id); - - // When the sender of the message is a Guest (livechat) and not a user - if (!user) { - user = this.orch.getConverters().get('users').convertToApp(message.u); - } + // When the message contains token, means the message is from the visitor(omnichannel) + const user = await (isMessageFromVisitor(msgObj) + ? this.orch.getConverters().get('users').convertToApp(message.u) + : cache.get('user')(message.u._id)); delete message.u; - return user; + /** + * Old System Messages from visitor doesn't have the `token` field, to not return + * `sender` as undefined, so we need to add this fallback here. + */ + + return user || this.orch.getConverters().get('users').convertToApp(message.u); }, }; diff --git a/apps/meteor/app/apps/server/converters/threads.ts b/apps/meteor/app/apps/server/converters/threads.ts index 840f4f1613eb..e31ee094b4d7 100644 --- a/apps/meteor/app/apps/server/converters/threads.ts +++ b/apps/meteor/app/apps/server/converters/threads.ts @@ -5,6 +5,7 @@ import type { IUser } from '@rocket.chat/core-typings'; import { isEditedMessage, type IMessage } from '@rocket.chat/core-typings'; import { Messages } from '@rocket.chat/models'; +import { cachedFunction } from './cachedFunction'; import { transformMappedData } from './transformMappedData'; // eslint-disable-next-line @typescript-eslint/naming-convention @@ -18,24 +19,6 @@ interface Orchestrator { }; } -const cachedFunction = any>(fn: F) => { - const cache = new Map(); - - return ((...args) => { - const cacheKey = JSON.stringify(args); - - if (cache.has(cacheKey)) { - return cache.get(cacheKey) as ReturnType; - } - - const result = fn(...args); - - cache.set(cacheKey, result); - - return result; - }) as F; -}; - export class AppThreadsConverter implements IAppThreadsConverter { constructor( private readonly orch: { diff --git a/apps/meteor/app/assets/server/assets.ts b/apps/meteor/app/assets/server/assets.ts index b9653a2f1b9a..5d627a4b1d29 100644 --- a/apps/meteor/app/assets/server/assets.ts +++ b/apps/meteor/app/assets/server/assets.ts @@ -2,8 +2,8 @@ import crypto from 'crypto'; import type { ServerResponse, IncomingMessage } from 'http'; import type { IRocketChatAssets, IRocketChatAsset, ISetting } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Settings } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import type { NextHandleFunction } from 'connect'; import sizeOf from 'image-size'; import { Meteor } from 'meteor/meteor'; @@ -406,7 +406,7 @@ Meteor.startup(() => { }, 200); }); -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { refreshClients(): boolean; diff --git a/apps/meteor/app/authorization/server/methods/addPermissionToRole.ts b/apps/meteor/app/authorization/server/methods/addPermissionToRole.ts index 13a114732bd2..9a336478ca3e 100644 --- a/apps/meteor/app/authorization/server/methods/addPermissionToRole.ts +++ b/apps/meteor/app/authorization/server/methods/addPermissionToRole.ts @@ -1,12 +1,12 @@ +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Permissions } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { notifyOnPermissionChangedById } from '../../../lib/server/lib/notifyListener'; import { CONSTANTS, AuthorizationUtils } from '../../lib'; import { hasPermissionAsync } from '../functions/hasPermission'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'authorization:addPermissionToRole'(permissionId: string, role: string): void; diff --git a/apps/meteor/app/authorization/server/methods/addUserToRole.ts b/apps/meteor/app/authorization/server/methods/addUserToRole.ts index 02ccc76373f1..81582dd7e9fb 100644 --- a/apps/meteor/app/authorization/server/methods/addUserToRole.ts +++ b/apps/meteor/app/authorization/server/methods/addUserToRole.ts @@ -1,14 +1,14 @@ import { api } from '@rocket.chat/core-services'; import type { IRole, IUser } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Roles, Users } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger'; import { settings } from '../../../settings/server'; import { hasPermissionAsync } from '../functions/hasPermission'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'authorization:addUserToRole'(roleId: IRole['_id'], username: IUser['username'], scope: string | undefined): Promise; diff --git a/apps/meteor/app/authorization/server/methods/deleteRole.ts b/apps/meteor/app/authorization/server/methods/deleteRole.ts index 2ff09deadf68..140852e0f1ec 100644 --- a/apps/meteor/app/authorization/server/methods/deleteRole.ts +++ b/apps/meteor/app/authorization/server/methods/deleteRole.ts @@ -1,13 +1,13 @@ import type { IRole } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Roles } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import type { DeleteResult } from 'mongodb'; import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger'; import { hasPermissionAsync } from '../functions/hasPermission'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'authorization:deleteRole'(roleId: IRole['_id'] | IRole['name']): Promise; diff --git a/apps/meteor/app/authorization/server/methods/removeRoleFromPermission.ts b/apps/meteor/app/authorization/server/methods/removeRoleFromPermission.ts index 91a4df1eddf7..68ca11ef9fb5 100644 --- a/apps/meteor/app/authorization/server/methods/removeRoleFromPermission.ts +++ b/apps/meteor/app/authorization/server/methods/removeRoleFromPermission.ts @@ -1,12 +1,12 @@ +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Permissions } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { notifyOnPermissionChangedById } from '../../../lib/server/lib/notifyListener'; import { CONSTANTS } from '../../lib'; import { hasPermissionAsync } from '../functions/hasPermission'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'authorization:removeRoleFromPermission'(permissionId: string, role: string): void; diff --git a/apps/meteor/app/authorization/server/methods/removeUserFromRole.ts b/apps/meteor/app/authorization/server/methods/removeUserFromRole.ts index d5dba40a1e53..56f0c2e307ab 100644 --- a/apps/meteor/app/authorization/server/methods/removeUserFromRole.ts +++ b/apps/meteor/app/authorization/server/methods/removeUserFromRole.ts @@ -1,14 +1,14 @@ import { api } from '@rocket.chat/core-services'; import type { IRole, IUser } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Roles, Users } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger'; import { settings } from '../../../settings/server'; import { hasPermissionAsync } from '../functions/hasPermission'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'authorization:removeUserFromRole'(roleId: IRole['_id'], username: IUser['username'], scope?: string): Promise; diff --git a/apps/meteor/app/authorization/server/streamer/permissions/index.ts b/apps/meteor/app/authorization/server/streamer/permissions/index.ts index ff8fd3c93262..e74cf37869fd 100644 --- a/apps/meteor/app/authorization/server/streamer/permissions/index.ts +++ b/apps/meteor/app/authorization/server/streamer/permissions/index.ts @@ -1,11 +1,11 @@ import type { IPermission, RocketChatRecordDeleted } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Permissions } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { check, Match } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; import type { WithId } from 'mongodb'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'permissions/get'( diff --git a/apps/meteor/app/autotranslate/server/autotranslate.ts b/apps/meteor/app/autotranslate/server/autotranslate.ts index 7a9eb8780a2d..1e6c224c4115 100644 --- a/apps/meteor/app/autotranslate/server/autotranslate.ts +++ b/apps/meteor/app/autotranslate/server/autotranslate.ts @@ -15,7 +15,7 @@ import _ from 'underscore'; import { callbacks } from '../../../lib/callbacks'; import { isTruthy } from '../../../lib/isTruthy'; -import { broadcastMessageFromData } from '../../../server/modules/watchers/lib/messages'; +import { notifyOnMessageChange } from '../../lib/server/lib/notifyListener'; import { Markdown } from '../../markdown/server'; import { settings } from '../../settings/server'; @@ -332,7 +332,7 @@ export abstract class AutoTranslate { } private notifyTranslatedMessage(messageId: string): void { - void broadcastMessageFromData({ + void notifyOnMessageChange({ id: messageId, }); } diff --git a/apps/meteor/app/autotranslate/server/methods/getProviderUiMetadata.ts b/apps/meteor/app/autotranslate/server/methods/getProviderUiMetadata.ts index 30760e854ed1..1d443c21d210 100644 --- a/apps/meteor/app/autotranslate/server/methods/getProviderUiMetadata.ts +++ b/apps/meteor/app/autotranslate/server/methods/getProviderUiMetadata.ts @@ -1,9 +1,9 @@ -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; import { TranslationProviderRegistry } from '../autotranslate'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'autoTranslate.getProviderUiMetadata'(): Record; diff --git a/apps/meteor/app/autotranslate/server/methods/getSupportedLanguages.ts b/apps/meteor/app/autotranslate/server/methods/getSupportedLanguages.ts index e0118e8d95a4..7b9614da7739 100644 --- a/apps/meteor/app/autotranslate/server/methods/getSupportedLanguages.ts +++ b/apps/meteor/app/autotranslate/server/methods/getSupportedLanguages.ts @@ -1,5 +1,5 @@ import type { ISupportedLanguage } from '@rocket.chat/core-typings'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { DDPRateLimiter } from 'meteor/ddp-rate-limiter'; import { Meteor } from 'meteor/meteor'; @@ -7,7 +7,7 @@ import { TranslationProviderRegistry } from '..'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; import { settings } from '../../../settings/server'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'autoTranslate.getSupportedLanguages'(targetLanguage: string): ISupportedLanguage[] | undefined; diff --git a/apps/meteor/app/autotranslate/server/methods/saveSettings.ts b/apps/meteor/app/autotranslate/server/methods/saveSettings.ts index e396d78887a9..2f119c948263 100644 --- a/apps/meteor/app/autotranslate/server/methods/saveSettings.ts +++ b/apps/meteor/app/autotranslate/server/methods/saveSettings.ts @@ -1,11 +1,11 @@ +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Subscriptions, Rooms } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'autoTranslate.saveSettings'(rid: string, field: string, value: string, options: { defaultLanguage: string }): boolean; diff --git a/apps/meteor/app/autotranslate/server/methods/translateMessage.ts b/apps/meteor/app/autotranslate/server/methods/translateMessage.ts index d90cad90ce77..551eba57c005 100644 --- a/apps/meteor/app/autotranslate/server/methods/translateMessage.ts +++ b/apps/meteor/app/autotranslate/server/methods/translateMessage.ts @@ -1,11 +1,11 @@ import type { IMessage } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Rooms } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { TranslationProviderRegistry } from '..'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'autoTranslate.translateMessage'(message: IMessage | undefined, targetLanguage: string): Promise; diff --git a/apps/meteor/app/bot-helpers/server/index.ts b/apps/meteor/app/bot-helpers/server/index.ts index 5e19e1652454..6c0984ae483d 100644 --- a/apps/meteor/app/bot-helpers/server/index.ts +++ b/apps/meteor/app/bot-helpers/server/index.ts @@ -1,7 +1,7 @@ import type { IUser } from '@rocket.chat/core-typings'; import { UserStatus } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Rooms, Users } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import type { Filter, FindCursor } from 'mongodb'; @@ -194,7 +194,7 @@ settings.watch('BotHelpers_userFields', (value) => { botHelpers.setupCursors(value); }); -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { botRequest: (prop: keyof BotHelpers, ...params: unknown[]) => Promise; diff --git a/apps/meteor/app/channel-settings/server/methods/saveRoomSettings.ts b/apps/meteor/app/channel-settings/server/methods/saveRoomSettings.ts index e17faebea384..e3f45daa5b18 100644 --- a/apps/meteor/app/channel-settings/server/methods/saveRoomSettings.ts +++ b/apps/meteor/app/channel-settings/server/methods/saveRoomSettings.ts @@ -1,8 +1,8 @@ import { Team } from '@rocket.chat/core-services'; import type { IRoom, IRoomWithRetentionPolicy, IUser, MessageTypesValues } from '@rocket.chat/core-typings'; import { TEAM_TYPE } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Rooms, Users } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Match } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; @@ -304,7 +304,7 @@ const settingSavers: RoomSettingsSavers = { }, }; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { saveRoomSettings(rid: IRoom['_id'], settings: Partial): Promise<{ result: true; rid: IRoom['_id'] }>; diff --git a/apps/meteor/app/cloud/server/methods.ts b/apps/meteor/app/cloud/server/methods.ts index 0e47a8ba8754..29daefe0d58c 100644 --- a/apps/meteor/app/cloud/server/methods.ts +++ b/apps/meteor/app/cloud/server/methods.ts @@ -1,4 +1,4 @@ -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; @@ -13,7 +13,7 @@ import { startRegisterWorkspace } from './functions/startRegisterWorkspace'; import { syncWorkspace } from './functions/syncWorkspace'; import { userLogout } from './functions/userLogout'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'cloud:checkRegisterStatus': () => { diff --git a/apps/meteor/app/crowd/server/methods.ts b/apps/meteor/app/crowd/server/methods.ts index a621e3c8d027..48faa2fcbcab 100644 --- a/apps/meteor/app/crowd/server/methods.ts +++ b/apps/meteor/app/crowd/server/methods.ts @@ -1,4 +1,5 @@ -import type { ServerMethods, TranslationKey } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; +import type { TranslationKey } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { hasPermissionAsync } from '../../authorization/server/functions/hasPermission'; @@ -6,7 +7,7 @@ import { settings } from '../../settings/server'; import { CROWD } from './crowd'; import { logger } from './logger'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { crowd_test_connection(): { message: TranslationKey; params: string[] }; diff --git a/apps/meteor/app/custom-sounds/server/methods/deleteCustomSound.ts b/apps/meteor/app/custom-sounds/server/methods/deleteCustomSound.ts index 5ddf0cc66e52..1c63c7a67d9f 100644 --- a/apps/meteor/app/custom-sounds/server/methods/deleteCustomSound.ts +++ b/apps/meteor/app/custom-sounds/server/methods/deleteCustomSound.ts @@ -1,13 +1,13 @@ import { api } from '@rocket.chat/core-services'; import type { ICustomSound } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { CustomSounds } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; import { RocketChatFileCustomSoundsInstance } from '../startup/custom-sounds'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { deleteCustomSound(_id: ICustomSound['_id']): Promise; diff --git a/apps/meteor/app/custom-sounds/server/methods/insertOrUpdateSound.ts b/apps/meteor/app/custom-sounds/server/methods/insertOrUpdateSound.ts index 4b48a64dc14c..1b922c6b162e 100644 --- a/apps/meteor/app/custom-sounds/server/methods/insertOrUpdateSound.ts +++ b/apps/meteor/app/custom-sounds/server/methods/insertOrUpdateSound.ts @@ -1,6 +1,6 @@ import { api } from '@rocket.chat/core-services'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { CustomSounds } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; @@ -20,7 +20,7 @@ export type ICustomSoundData = { random?: number; }; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { insertOrUpdateSound(soundData: ICustomSoundData): Promise; diff --git a/apps/meteor/app/custom-sounds/server/methods/listCustomSounds.ts b/apps/meteor/app/custom-sounds/server/methods/listCustomSounds.ts index 2c2130fc0d30..eda1325d7733 100644 --- a/apps/meteor/app/custom-sounds/server/methods/listCustomSounds.ts +++ b/apps/meteor/app/custom-sounds/server/methods/listCustomSounds.ts @@ -1,9 +1,9 @@ import type { ICustomSound } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { CustomSounds } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { listCustomSounds(): ICustomSound[]; diff --git a/apps/meteor/app/custom-sounds/server/methods/uploadCustomSound.ts b/apps/meteor/app/custom-sounds/server/methods/uploadCustomSound.ts index eee693634d7d..f955f373ed4d 100644 --- a/apps/meteor/app/custom-sounds/server/methods/uploadCustomSound.ts +++ b/apps/meteor/app/custom-sounds/server/methods/uploadCustomSound.ts @@ -1,6 +1,6 @@ import { api } from '@rocket.chat/core-services'; import type { RequiredField } from '@rocket.chat/core-typings'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; @@ -8,7 +8,7 @@ import { RocketChatFile } from '../../../file/server'; import { RocketChatFileCustomSoundsInstance } from '../startup/custom-sounds'; import type { ICustomSoundData } from './insertOrUpdateSound'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { uploadCustomSound(binaryContent: string, contentType: string, soundData: RequiredField): void; diff --git a/apps/meteor/app/discussion/client/createDiscussionMessageAction.ts b/apps/meteor/app/discussion/client/createDiscussionMessageAction.ts index 3ad61c4c42f0..ecf014248830 100644 --- a/apps/meteor/app/discussion/client/createDiscussionMessageAction.ts +++ b/apps/meteor/app/discussion/client/createDiscussionMessageAction.ts @@ -44,7 +44,7 @@ Meteor.startup(() => { subscription, user, }) { - if (drid || !Number.isNaN(dcount)) { + if (drid || !Number.isNaN(Number(dcount))) { return false; } if (!subscription) { diff --git a/apps/meteor/app/discussion/client/index.ts b/apps/meteor/app/discussion/client/index.ts index 62e11191b493..7c0a6f72e6cc 100644 --- a/apps/meteor/app/discussion/client/index.ts +++ b/apps/meteor/app/discussion/client/index.ts @@ -1,3 +1,2 @@ // Other UI extensions -import './lib/messageTypes/discussionMessage'; import './createDiscussionMessageAction'; diff --git a/apps/meteor/app/discussion/client/lib/messageTypes/discussionMessage.js b/apps/meteor/app/discussion/client/lib/messageTypes/discussionMessage.js deleted file mode 100644 index a7f0ef0a1d97..000000000000 --- a/apps/meteor/app/discussion/client/lib/messageTypes/discussionMessage.js +++ /dev/null @@ -1,16 +0,0 @@ -import { Meteor } from 'meteor/meteor'; - -import { MessageTypes } from '../../../../ui-utils/client'; - -Meteor.startup(() => { - MessageTypes.registerType({ - id: 'discussion-created', - system: false, - message: 'discussion-created', - data(message) { - return { - message: ` ${message.msg}`, - }; - }, - }); -}); diff --git a/apps/meteor/app/discussion/server/hooks/propagateDiscussionMetadata.ts b/apps/meteor/app/discussion/server/hooks/propagateDiscussionMetadata.ts index 0f42f495e962..05cf2326156f 100644 --- a/apps/meteor/app/discussion/server/hooks/propagateDiscussionMetadata.ts +++ b/apps/meteor/app/discussion/server/hooks/propagateDiscussionMetadata.ts @@ -1,16 +1,16 @@ import type { IRoom } from '@rocket.chat/core-typings'; -import { Messages, Rooms } from '@rocket.chat/models'; +import { Messages, Rooms, VideoConference } from '@rocket.chat/models'; import { callbacks } from '../../../../lib/callbacks'; -import { broadcastMessageFromData } from '../../../../server/modules/watchers/lib/messages'; import { deleteRoom } from '../../../lib/server/functions/deleteRoom'; +import { notifyOnMessageChange } from '../../../lib/server/lib/notifyListener'; const updateAndNotifyParentRoomWithParentMessage = async (room: IRoom): Promise => { const { value: parentMessage } = await Messages.refreshDiscussionMetadata(room); if (!parentMessage) { return; } - void broadcastMessageFromData({ + void notifyOnMessageChange({ id: parentMessage._id, data: parentMessage, }); @@ -108,6 +108,8 @@ callbacks.add( }, }, ); + + await VideoConference.unsetDiscussionRid(drid); return drid; }, callbacks.priority.LOW, diff --git a/apps/meteor/app/discussion/server/methods/createDiscussion.ts b/apps/meteor/app/discussion/server/methods/createDiscussion.ts index 18b42ba1a31f..6e670d723ec9 100644 --- a/apps/meteor/app/discussion/server/methods/createDiscussion.ts +++ b/apps/meteor/app/discussion/server/methods/createDiscussion.ts @@ -1,8 +1,8 @@ import { Message } from '@rocket.chat/core-services'; import type { IMessage, IRoom, IUser, MessageAttachmentDefault } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Messages, Rooms, Users } from '@rocket.chat/models'; import { Random } from '@rocket.chat/random'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { callbacks } from '../../../../lib/callbacks'; @@ -196,7 +196,7 @@ const create = async ({ return discussion; }; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { createDiscussion: typeof create; diff --git a/apps/meteor/app/e2e/client/rocketchat.e2e.ts b/apps/meteor/app/e2e/client/rocketchat.e2e.ts index 0cc344ff5152..bbd6f208f35a 100644 --- a/apps/meteor/app/e2e/client/rocketchat.e2e.ts +++ b/apps/meteor/app/e2e/client/rocketchat.e2e.ts @@ -257,7 +257,7 @@ class E2E extends Emitter { return null; } - if (room.encrypted !== true && !room.e2eKeyId) { + if (!room.encrypted) { return null; } @@ -272,7 +272,7 @@ class E2E extends Emitter { delete this.instancesByRoomId[rid]; } - async persistKeys( + private async persistKeys( { public_key, private_key }: KeyPair, password: string, { force }: { force: boolean } = { force: false }, diff --git a/apps/meteor/app/e2e/server/methods/fetchMyKeys.ts b/apps/meteor/app/e2e/server/methods/fetchMyKeys.ts index 519317cb40fe..df1150cee846 100644 --- a/apps/meteor/app/e2e/server/methods/fetchMyKeys.ts +++ b/apps/meteor/app/e2e/server/methods/fetchMyKeys.ts @@ -1,8 +1,8 @@ +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Users } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'e2e.fetchMyKeys'(): { public_key?: string; private_key?: string }; diff --git a/apps/meteor/app/e2e/server/methods/getUsersOfRoomWithoutKey.ts b/apps/meteor/app/e2e/server/methods/getUsersOfRoomWithoutKey.ts index cc586676482f..1f1a21262de8 100644 --- a/apps/meteor/app/e2e/server/methods/getUsersOfRoomWithoutKey.ts +++ b/apps/meteor/app/e2e/server/methods/getUsersOfRoomWithoutKey.ts @@ -1,12 +1,12 @@ import type { IRoom, IUser } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Subscriptions, Users } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; import { canAccessRoomIdAsync } from '../../../authorization/server/functions/canAccessRoom'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'e2e.getUsersOfRoomWithoutKey'(rid: IRoom['_id']): { users: Pick[] }; diff --git a/apps/meteor/app/e2e/server/methods/requestSubscriptionKeys.ts b/apps/meteor/app/e2e/server/methods/requestSubscriptionKeys.ts index 8c5add77a0bf..cf899a5d64ad 100644 --- a/apps/meteor/app/e2e/server/methods/requestSubscriptionKeys.ts +++ b/apps/meteor/app/e2e/server/methods/requestSubscriptionKeys.ts @@ -1,9 +1,9 @@ import { api } from '@rocket.chat/core-services'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Subscriptions, Rooms } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'e2e.requestSubscriptionKeys'(): boolean; diff --git a/apps/meteor/app/e2e/server/methods/resetOwnE2EKey.ts b/apps/meteor/app/e2e/server/methods/resetOwnE2EKey.ts index 365feb1ac95d..b1d40e48bb5e 100644 --- a/apps/meteor/app/e2e/server/methods/resetOwnE2EKey.ts +++ b/apps/meteor/app/e2e/server/methods/resetOwnE2EKey.ts @@ -1,10 +1,10 @@ -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; import { resetUserE2EEncriptionKey } from '../../../../server/lib/resetUserE2EKey'; import { twoFactorRequired } from '../../../2fa/server/twoFactorRequired'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'e2e.resetOwnE2EKey'(): Promise; diff --git a/apps/meteor/app/e2e/server/methods/setRoomKeyID.ts b/apps/meteor/app/e2e/server/methods/setRoomKeyID.ts index 6b0e685616b5..b52913e4f984 100644 --- a/apps/meteor/app/e2e/server/methods/setRoomKeyID.ts +++ b/apps/meteor/app/e2e/server/methods/setRoomKeyID.ts @@ -1,13 +1,13 @@ import type { IRoom } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Rooms } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; import { canAccessRoomIdAsync } from '../../../authorization/server/functions/canAccessRoom'; import { notifyOnRoomChangedById } from '../../../lib/server/lib/notifyListener'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'e2e.setRoomKeyID'(rid: IRoom['_id'], keyID: string): void; diff --git a/apps/meteor/app/e2e/server/methods/setUserPublicAndPrivateKeys.ts b/apps/meteor/app/e2e/server/methods/setUserPublicAndPrivateKeys.ts index 94d252601bc4..6ef35a063a28 100644 --- a/apps/meteor/app/e2e/server/methods/setUserPublicAndPrivateKeys.ts +++ b/apps/meteor/app/e2e/server/methods/setUserPublicAndPrivateKeys.ts @@ -1,8 +1,8 @@ +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Rooms, Users } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'e2e.setUserPublicAndPrivateKeys'({ public_key, private_key }: { public_key: string; private_key: string; force?: boolean }): void; diff --git a/apps/meteor/app/e2e/server/methods/updateGroupKey.ts b/apps/meteor/app/e2e/server/methods/updateGroupKey.ts index c856f8cf708a..5764a021f54c 100644 --- a/apps/meteor/app/e2e/server/methods/updateGroupKey.ts +++ b/apps/meteor/app/e2e/server/methods/updateGroupKey.ts @@ -1,10 +1,10 @@ +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Subscriptions } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'e2e.updateGroupKey'(rid: string, uid: string, key: string): Promise; diff --git a/apps/meteor/app/emoji-custom/server/methods/deleteEmojiCustom.ts b/apps/meteor/app/emoji-custom/server/methods/deleteEmojiCustom.ts index 555d5544ab33..c16d3b82449b 100644 --- a/apps/meteor/app/emoji-custom/server/methods/deleteEmojiCustom.ts +++ b/apps/meteor/app/emoji-custom/server/methods/deleteEmojiCustom.ts @@ -1,13 +1,13 @@ import { api } from '@rocket.chat/core-services'; import type { ICustomEmojiDescriptor } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { EmojiCustom } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; import { RocketChatFileEmojiCustomInstance } from '../startup/emoji-custom'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { deleteEmojiCustom(emojiID: ICustomEmojiDescriptor['_id']): boolean; diff --git a/apps/meteor/app/emoji-custom/server/methods/insertOrUpdateEmoji.ts b/apps/meteor/app/emoji-custom/server/methods/insertOrUpdateEmoji.ts index 874180097cb9..5d4a6742314b 100644 --- a/apps/meteor/app/emoji-custom/server/methods/insertOrUpdateEmoji.ts +++ b/apps/meteor/app/emoji-custom/server/methods/insertOrUpdateEmoji.ts @@ -1,6 +1,6 @@ import { api } from '@rocket.chat/core-services'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { EmojiCustom } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import limax from 'limax'; import { Meteor } from 'meteor/meteor'; import _ from 'underscore'; @@ -9,7 +9,7 @@ import { trim } from '../../../../lib/utils/stringUtils'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; import { RocketChatFileEmojiCustomInstance } from '../startup/emoji-custom'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { insertOrUpdateEmoji(emojiData: { diff --git a/apps/meteor/app/emoji-custom/server/methods/listEmojiCustom.ts b/apps/meteor/app/emoji-custom/server/methods/listEmojiCustom.ts index 485737b95f9b..a16d536d92d4 100644 --- a/apps/meteor/app/emoji-custom/server/methods/listEmojiCustom.ts +++ b/apps/meteor/app/emoji-custom/server/methods/listEmojiCustom.ts @@ -1,12 +1,12 @@ import type { IEmojiCustom } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { EmojiCustom } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { check, Match } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { listEmojiCustom(options?: { name?: string; aliases?: string[] }): IEmojiCustom[]; diff --git a/apps/meteor/app/emoji-custom/server/methods/uploadEmojiCustom.ts b/apps/meteor/app/emoji-custom/server/methods/uploadEmojiCustom.ts index ded98b7f5469..a46f457cd70f 100644 --- a/apps/meteor/app/emoji-custom/server/methods/uploadEmojiCustom.ts +++ b/apps/meteor/app/emoji-custom/server/methods/uploadEmojiCustom.ts @@ -1,5 +1,5 @@ import { api, Media } from '@rocket.chat/core-services'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import limax from 'limax'; import { Meteor } from 'meteor/meteor'; import sharp from 'sharp'; @@ -16,7 +16,7 @@ const getFile = async (file: Buffer, extension: string) => { return sharp(file).png().toBuffer(); }; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { uploadEmojiCustom( diff --git a/apps/meteor/app/federation/server/endpoints/dispatch.js b/apps/meteor/app/federation/server/endpoints/dispatch.js index 4cab0b0c41e8..6c7fa5cad0e8 100644 --- a/apps/meteor/app/federation/server/endpoints/dispatch.js +++ b/apps/meteor/app/federation/server/endpoints/dispatch.js @@ -3,11 +3,10 @@ import { eventTypes } from '@rocket.chat/core-typings'; import { FederationServers, FederationRoomEvents, Rooms, Messages, Subscriptions, Users, ReadReceipts } from '@rocket.chat/models'; import EJSON from 'ejson'; -import { broadcastMessageFromData } from '../../../../server/modules/watchers/lib/messages'; import { API } from '../../../api/server'; import { FileUpload } from '../../../file-upload/server'; import { deleteRoom } from '../../../lib/server/functions/deleteRoom'; -import { notifyOnRoomChanged, notifyOnRoomChangedById } from '../../../lib/server/lib/notifyListener'; +import { notifyOnMessageChange, notifyOnRoomChanged, notifyOnRoomChangedById } from '../../../lib/server/lib/notifyListener'; import { notifyUsersOnMessage } from '../../../lib/server/lib/notifyUsersOnMessage'; import { sendAllNotifications } from '../../../lib/server/lib/sendNotificationsOnMessage'; import { processThreads } from '../../../threads/server/hooks/aftersavemessage'; @@ -303,7 +302,7 @@ const eventHandlers = { } } if (messageForNotification) { - void broadcastMessageFromData({ + void notifyOnMessageChange({ id: messageForNotification._id, data: messageForNotification, }); @@ -334,7 +333,7 @@ const eventHandlers = { } else { // Update the message await Messages.updateOne({ _id: persistedMessage._id }, { $set: { msg: message.msg, federation: message.federation } }); - void broadcastMessageFromData({ + void notifyOnMessageChange({ id: persistedMessage._id, data: { ...persistedMessage, @@ -404,7 +403,7 @@ const eventHandlers = { // Update the property await Messages.updateOne({ _id: messageId }, { $set: { [`reactions.${reaction}`]: reactionObj } }); - void broadcastMessageFromData({ + void notifyOnMessageChange({ id: persistedMessage._id, data: { ...persistedMessage, @@ -462,7 +461,7 @@ const eventHandlers = { // Otherwise, update the property await Messages.updateOne({ _id: messageId }, { $set: { [`reactions.${reaction}`]: reactionObj } }); } - void broadcastMessageFromData({ + void notifyOnMessageChange({ id: persistedMessage._id, data: { ...persistedMessage, diff --git a/apps/meteor/app/federation/server/methods/dashboard.ts b/apps/meteor/app/federation/server/methods/dashboard.ts index 90a050556893..eacb42b24cbb 100644 --- a/apps/meteor/app/federation/server/methods/dashboard.ts +++ b/apps/meteor/app/federation/server/methods/dashboard.ts @@ -1,10 +1,10 @@ import type { IFederationServer } from '@rocket.chat/core-typings'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; import { federationGetServers, federationGetOverviewData } from '../functions/dashboard'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'federation:getServers': () => { data: IFederationServer[] }; diff --git a/apps/meteor/app/federation/server/methods/loadContextEvents.ts b/apps/meteor/app/federation/server/methods/loadContextEvents.ts index 9e286bbf913a..e20acb7e37c9 100644 --- a/apps/meteor/app/federation/server/methods/loadContextEvents.ts +++ b/apps/meteor/app/federation/server/methods/loadContextEvents.ts @@ -1,11 +1,11 @@ import type { IFederationEvent } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { FederationRoomEvents } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'federation:loadContextEvents'(latestEventTimestamp: number): IFederationEvent[]; diff --git a/apps/meteor/app/federation/server/methods/testSetup.ts b/apps/meteor/app/federation/server/methods/testSetup.ts index 93e501535474..bc50ef158194 100644 --- a/apps/meteor/app/federation/server/methods/testSetup.ts +++ b/apps/meteor/app/federation/server/methods/testSetup.ts @@ -1,11 +1,11 @@ import { eventTypes } from '@rocket.chat/core-typings'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; import { dispatchEvent } from '../handler'; import { getFederationDomain } from '../lib/getFederationDomain'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { FEDERATION_Test_Setup(): { message: string }; diff --git a/apps/meteor/app/file-upload/server/methods/getS3FileUrl.ts b/apps/meteor/app/file-upload/server/methods/getS3FileUrl.ts index fdb8d131916d..3e9bcd192674 100644 --- a/apps/meteor/app/file-upload/server/methods/getS3FileUrl.ts +++ b/apps/meteor/app/file-upload/server/methods/getS3FileUrl.ts @@ -1,5 +1,5 @@ +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Rooms, Uploads } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; @@ -7,7 +7,7 @@ import { UploadFS } from '../../../../server/ufs'; import { canAccessRoomAsync } from '../../../authorization/server'; import { settings } from '../../../settings/server'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { getS3FileUrl(fileId: string): string; diff --git a/apps/meteor/app/file-upload/server/methods/sendFileMessage.ts b/apps/meteor/app/file-upload/server/methods/sendFileMessage.ts index 485528a5e62f..73dfd0216a73 100644 --- a/apps/meteor/app/file-upload/server/methods/sendFileMessage.ts +++ b/apps/meteor/app/file-upload/server/methods/sendFileMessage.ts @@ -7,8 +7,8 @@ import type { FilesAndAttachments, IMessage, } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Rooms, Uploads, Users } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Match, check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; @@ -141,7 +141,7 @@ export const parseFileIntoMessageAttachments = async ( return { files, attachments }; }; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { sendFileMessage: (roomId: string, _store: string, file: Partial, msgData?: Record) => boolean; diff --git a/apps/meteor/app/iframe-login/server/iframe_server.ts b/apps/meteor/app/iframe-login/server/iframe_server.ts index c7e67edf9deb..b3e661cf6ff3 100644 --- a/apps/meteor/app/iframe-login/server/iframe_server.ts +++ b/apps/meteor/app/iframe-login/server/iframe_server.ts @@ -1,5 +1,5 @@ +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Users } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Accounts } from 'meteor/accounts-base'; import { check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; @@ -23,7 +23,7 @@ Accounts.registerLoginHandler('iframe', async (result) => { } }); -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'OAuth.retrieveCredential'(credentialToken: string, credentialSecret: string): unknown; diff --git a/apps/meteor/app/importer/server/methods/downloadPublicImportFile.ts b/apps/meteor/app/importer/server/methods/downloadPublicImportFile.ts index 81e06ec8eb0f..d2da85c7cfd4 100644 --- a/apps/meteor/app/importer/server/methods/downloadPublicImportFile.ts +++ b/apps/meteor/app/importer/server/methods/downloadPublicImportFile.ts @@ -4,7 +4,7 @@ import https from 'https'; import { Import } from '@rocket.chat/core-services'; import type { IUser } from '@rocket.chat/core-typings'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; import { Importers } from '..'; @@ -75,7 +75,7 @@ export const executeDownloadPublicImportFile = async (userId: IUser['_id'], file } }; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { downloadPublicImportFile(fileUrl: string, importerKey: string): void; diff --git a/apps/meteor/app/importer/server/methods/getImportFileData.ts b/apps/meteor/app/importer/server/methods/getImportFileData.ts index 03f9a53abe6c..1d36f7fc5a5e 100644 --- a/apps/meteor/app/importer/server/methods/getImportFileData.ts +++ b/apps/meteor/app/importer/server/methods/getImportFileData.ts @@ -2,8 +2,8 @@ import fs from 'fs'; import path from 'path'; import type { IImportProgress, IImporterSelection } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Imports } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { Importers } from '..'; @@ -61,7 +61,7 @@ export const executeGetImportFileData = async (): Promise => { return instance.getProgress(); }; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { getImportProgress(): IImportProgress; diff --git a/apps/meteor/app/importer/server/methods/getLatestImportOperations.ts b/apps/meteor/app/importer/server/methods/getLatestImportOperations.ts index edf021a19eac..0471cb57955d 100644 --- a/apps/meteor/app/importer/server/methods/getLatestImportOperations.ts +++ b/apps/meteor/app/importer/server/methods/getLatestImportOperations.ts @@ -1,6 +1,6 @@ import type { IImport } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Imports } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; @@ -17,7 +17,7 @@ export const executeGetLatestImportOperations = async () => { return data.toArray(); }; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { getLatestImportOperations(): IImport[]; diff --git a/apps/meteor/app/importer/server/methods/startImport.ts b/apps/meteor/app/importer/server/methods/startImport.ts index af91295ede29..bbb5ce76ad1c 100644 --- a/apps/meteor/app/importer/server/methods/startImport.ts +++ b/apps/meteor/app/importer/server/methods/startImport.ts @@ -1,7 +1,7 @@ import type { IUser } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Imports } from '@rocket.chat/models'; import type { StartImportParamsPOST } from '@rocket.chat/rest-typings'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { Importers, Selection, SelectionChannel, SelectionUser } from '..'; @@ -32,7 +32,7 @@ export const executeStartImport = async ({ input }: StartImportParamsPOST, start await instance.startImport(selection, startedByUserId); }; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { startImport(params: StartImportParamsPOST): void; diff --git a/apps/meteor/app/importer/server/methods/uploadImportFile.ts b/apps/meteor/app/importer/server/methods/uploadImportFile.ts index d6ded455793b..df5d2af883fa 100644 --- a/apps/meteor/app/importer/server/methods/uploadImportFile.ts +++ b/apps/meteor/app/importer/server/methods/uploadImportFile.ts @@ -1,6 +1,6 @@ import { Import } from '@rocket.chat/core-services'; import type { IUser } from '@rocket.chat/core-typings'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; import { Importers } from '..'; @@ -55,7 +55,7 @@ export const executeUploadImportFile = async ( await instance.updateProgress(ProgressStep.FILE_LOADED); }; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { uploadImportFile(binaryContent: string, contentType: string, fileName: string, importerKey: string): void; diff --git a/apps/meteor/app/integrations/server/methods/clearIntegrationHistory.ts b/apps/meteor/app/integrations/server/methods/clearIntegrationHistory.ts index 5b8f13ef1a3a..a30bb9b5ee9a 100644 --- a/apps/meteor/app/integrations/server/methods/clearIntegrationHistory.ts +++ b/apps/meteor/app/integrations/server/methods/clearIntegrationHistory.ts @@ -1,11 +1,11 @@ +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Integrations, IntegrationHistory } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; import notifications from '../../../notifications/server/lib/Notifications'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { clearIntegrationHistory(integrationId: string): Promise; diff --git a/apps/meteor/app/integrations/server/methods/incoming/addIncomingIntegration.ts b/apps/meteor/app/integrations/server/methods/incoming/addIncomingIntegration.ts index db058bec960b..8f1f1b5dd576 100644 --- a/apps/meteor/app/integrations/server/methods/incoming/addIncomingIntegration.ts +++ b/apps/meteor/app/integrations/server/methods/incoming/addIncomingIntegration.ts @@ -1,7 +1,7 @@ import type { INewIncomingIntegration, IIncomingIntegration } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Integrations, Roles, Subscriptions, Users, Rooms } from '@rocket.chat/models'; import { Random } from '@rocket.chat/random'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Babel } from 'meteor/babel-compiler'; import { Match, check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; @@ -13,7 +13,7 @@ import { validateScriptEngine, isScriptEngineFrozen } from '../../lib/validateSc const validChannelChars = ['@', '#']; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { addIncomingIntegration(integration: INewIncomingIntegration): Promise; diff --git a/apps/meteor/app/integrations/server/methods/incoming/deleteIncomingIntegration.ts b/apps/meteor/app/integrations/server/methods/incoming/deleteIncomingIntegration.ts index e73a46bb27db..9a116f51bbaf 100644 --- a/apps/meteor/app/integrations/server/methods/incoming/deleteIncomingIntegration.ts +++ b/apps/meteor/app/integrations/server/methods/incoming/deleteIncomingIntegration.ts @@ -1,11 +1,11 @@ +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Integrations } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { hasPermissionAsync } from '../../../../authorization/server/functions/hasPermission'; import { notifyOnIntegrationChangedById } from '../../../../lib/server/lib/notifyListener'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { deleteIncomingIntegration(integrationId: string): Promise; diff --git a/apps/meteor/app/integrations/server/methods/incoming/updateIncomingIntegration.ts b/apps/meteor/app/integrations/server/methods/incoming/updateIncomingIntegration.ts index 0ea5028130da..c94b7b9fd7a8 100644 --- a/apps/meteor/app/integrations/server/methods/incoming/updateIncomingIntegration.ts +++ b/apps/meteor/app/integrations/server/methods/incoming/updateIncomingIntegration.ts @@ -1,7 +1,7 @@ import type { IIntegration, INewIncomingIntegration, IUpdateIncomingIntegration } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Integrations, Roles, Subscriptions, Users, Rooms } from '@rocket.chat/models'; import { wrapExceptions } from '@rocket.chat/tools'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Babel } from 'meteor/babel-compiler'; import { Meteor } from 'meteor/meteor'; import _ from 'underscore'; @@ -12,7 +12,7 @@ import { isScriptEngineFrozen, validateScriptEngine } from '../../lib/validateSc const validChannelChars = ['@', '#']; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { updateIncomingIntegration( diff --git a/apps/meteor/app/integrations/server/methods/outgoing/addOutgoingIntegration.ts b/apps/meteor/app/integrations/server/methods/outgoing/addOutgoingIntegration.ts index c8dc31e08446..dc54c76b1897 100644 --- a/apps/meteor/app/integrations/server/methods/outgoing/addOutgoingIntegration.ts +++ b/apps/meteor/app/integrations/server/methods/outgoing/addOutgoingIntegration.ts @@ -1,6 +1,6 @@ import type { INewOutgoingIntegration, IOutgoingIntegration } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Integrations } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Match, check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; @@ -9,7 +9,7 @@ import { notifyOnIntegrationChanged } from '../../../../lib/server/lib/notifyLis import { validateOutgoingIntegration } from '../../lib/validateOutgoingIntegration'; import { validateScriptEngine } from '../../lib/validateScriptEngine'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { addOutgoingIntegration(integration: INewOutgoingIntegration): Promise; diff --git a/apps/meteor/app/integrations/server/methods/outgoing/deleteOutgoingIntegration.ts b/apps/meteor/app/integrations/server/methods/outgoing/deleteOutgoingIntegration.ts index c9f2211d835b..46d4c65159c0 100644 --- a/apps/meteor/app/integrations/server/methods/outgoing/deleteOutgoingIntegration.ts +++ b/apps/meteor/app/integrations/server/methods/outgoing/deleteOutgoingIntegration.ts @@ -1,11 +1,11 @@ +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Integrations, IntegrationHistory } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { hasPermissionAsync } from '../../../../authorization/server/functions/hasPermission'; import { notifyOnIntegrationChangedById } from '../../../../lib/server/lib/notifyListener'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { deleteOutgoingIntegration(integrationId: string): Promise; diff --git a/apps/meteor/app/integrations/server/methods/outgoing/replayOutgoingIntegration.ts b/apps/meteor/app/integrations/server/methods/outgoing/replayOutgoingIntegration.ts index 417c308ca6cb..83c13f2d981b 100644 --- a/apps/meteor/app/integrations/server/methods/outgoing/replayOutgoingIntegration.ts +++ b/apps/meteor/app/integrations/server/methods/outgoing/replayOutgoingIntegration.ts @@ -1,11 +1,11 @@ +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Integrations, IntegrationHistory } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { hasPermissionAsync } from '../../../../authorization/server/functions/hasPermission'; import { triggerHandler } from '../../lib/triggerHandler'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { replayOutgoingIntegration(params: { integrationId: string; historyId: string }): Promise; diff --git a/apps/meteor/app/integrations/server/methods/outgoing/updateOutgoingIntegration.ts b/apps/meteor/app/integrations/server/methods/outgoing/updateOutgoingIntegration.ts index 116dbd043039..c9b1f4ed7d64 100644 --- a/apps/meteor/app/integrations/server/methods/outgoing/updateOutgoingIntegration.ts +++ b/apps/meteor/app/integrations/server/methods/outgoing/updateOutgoingIntegration.ts @@ -1,7 +1,7 @@ import type { IIntegration, INewOutgoingIntegration, IUpdateOutgoingIntegration } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Integrations, Users } from '@rocket.chat/models'; import { wrapExceptions } from '@rocket.chat/tools'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { hasPermissionAsync } from '../../../../authorization/server/functions/hasPermission'; @@ -9,7 +9,7 @@ import { notifyOnIntegrationChanged } from '../../../../lib/server/lib/notifyLis import { validateOutgoingIntegration } from '../../lib/validateOutgoingIntegration'; import { isScriptEngineFrozen, validateScriptEngine } from '../../lib/validateScriptEngine'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { updateOutgoingIntegration( diff --git a/apps/meteor/app/irc/server/methods/resetIrcConnection.ts b/apps/meteor/app/irc/server/methods/resetIrcConnection.ts index 24eef975d5d5..aaaeef1c06b8 100644 --- a/apps/meteor/app/irc/server/methods/resetIrcConnection.ts +++ b/apps/meteor/app/irc/server/methods/resetIrcConnection.ts @@ -1,12 +1,12 @@ +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Settings } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { notifyOnSettingChangedById } from '../../../lib/server/lib/notifyListener'; import { settings } from '../../../settings/server'; import Bridge from '../irc-bridge'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { resetIrcConnection(): { message: string; params: unknown[] }; diff --git a/apps/meteor/app/lib/client/methods/sendMessage.ts b/apps/meteor/app/lib/client/methods/sendMessage.ts index e824c9e491af..bdaca587493a 100644 --- a/apps/meteor/app/lib/client/methods/sendMessage.ts +++ b/apps/meteor/app/lib/client/methods/sendMessage.ts @@ -1,5 +1,5 @@ import type { IMessage, IUser } from '@rocket.chat/core-typings'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; import { onClientMessageReceived } from '../../../../client/lib/onClientMessageReceived'; diff --git a/apps/meteor/app/lib/server/functions/addUserToRoom.ts b/apps/meteor/app/lib/server/functions/addUserToRoom.ts index 57ea20f00cb1..b6ffc0ca4629 100644 --- a/apps/meteor/app/lib/server/functions/addUserToRoom.ts +++ b/apps/meteor/app/lib/server/functions/addUserToRoom.ts @@ -15,9 +15,15 @@ import { notifyOnRoomChangedById } from '../lib/notifyListener'; export const addUserToRoom = async function ( rid: string, - user: Pick | string, + user: Pick | string, inviter?: Pick, - silenced?: boolean, + { + skipSystemMessage, + skipAlertSound, + }: { + skipSystemMessage?: boolean; + skipAlertSound?: boolean; + } = {}, ): Promise { const now = new Date(); const room = await Rooms.findOneById(rid); @@ -43,12 +49,12 @@ export const addUserToRoom = async function ( } try { - await callbacks.run('federation.beforeAddUserToARoom', { user, inviter }, room); + await callbacks.run('federation.beforeAddUserToARoom', { user: userToBeAdded, inviter }, room); } catch (error) { throw new Meteor.Error((error as any)?.message); } - await callbacks.run('beforeAddedToRoom', { user: userToBeAdded, inviter: userToBeAdded }); + await callbacks.run('beforeAddedToRoom', { user: userToBeAdded, inviter }); // Check if user is already in room const subscription = await Subscriptions.findOneByRoomIdAndUserId(rid, userToBeAdded._id); @@ -79,7 +85,7 @@ export const addUserToRoom = async function ( await Subscriptions.createWithRoomAndUser(room, userToBeAdded as IUser, { ts: now, open: true, - alert: true, + alert: !skipAlertSound, unread: 1, userMentions: 1, groupMentions: 0, @@ -93,7 +99,7 @@ export const addUserToRoom = async function ( throw new Meteor.Error('error-invalid-user', 'Cannot add an user to a room without a username'); } - if (!silenced) { + if (!skipSystemMessage) { if (inviter) { const extraData = { ts: now, diff --git a/apps/meteor/app/lib/server/functions/checkUrlForSsrf.ts b/apps/meteor/app/lib/server/functions/checkUrlForSsrf.ts new file mode 100644 index 000000000000..c90065d7ad8f --- /dev/null +++ b/apps/meteor/app/lib/server/functions/checkUrlForSsrf.ts @@ -0,0 +1,100 @@ +import { lookup } from 'dns'; + +// https://en.wikipedia.org/wiki/Reserved_IP_addresses + Alibaba Metadata IP +const ranges: string[] = [ + '0.0.0.0/8', + '10.0.0.0/8', + '100.64.0.0/10', + '127.0.0.0/8', + '169.254.0.0/16', + '172.16.0.0/12', + '192.0.0.0/24', + '192.0.2.0/24', + '192.88.99.0/24', + '192.168.0.0/16', + '198.18.0.0/15', + '198.51.100.0/24', + '203.0.113.0/24', + '224.0.0.0/4', + '240.0.0.0/4', + '255.255.255.255', + '100.100.100.200/32', +]; + +export const nslookup = async (hostname: string): Promise => { + return new Promise((resolve, reject) => { + lookup(hostname, (error, address) => { + if (error) { + reject(error); + } else { + resolve(address); + } + }); + }); +}; + +export const ipToLong = (ip: string): number => { + return ip.split('.').reduce((acc, octet) => (acc << 8) + parseInt(octet, 10), 0) >>> 0; +}; + +export const isIpInRange = (ip: string, range: string): boolean => { + const [rangeIp, subnet] = range.split('/'); + const ipLong = ipToLong(ip); + const rangeIpLong = ipToLong(rangeIp); + const mask = ~(2 ** (32 - Number(subnet)) - 1); + return (ipLong & mask) === (rangeIpLong & mask); +}; + +export const isIpInAnyRange = (ip: string): boolean => ranges.some((range) => isIpInRange(ip, range)); + +export const isValidIPv4 = (ip: string): boolean => { + const octets = ip.split('.'); + if (octets.length !== 4) return false; + return octets.every((octet) => { + const num = Number(octet); + return num >= 0 && num <= 255 && octet === num.toString(); + }); +}; + +export const isValidDomain = (domain: string): boolean => { + const domainPattern = /^(?!-)(?!.*--)[A-Za-z0-9-]{1,63}(? => { + if (!(url.startsWith('http://') || url.startsWith('https://'))) { + return false; + } + + const [, address] = url.split('://'); + const ipOrDomain = address.includes('/') ? address.split('/')[0] : address; + + if (!(isValidIPv4(ipOrDomain) || isValidDomain(ipOrDomain))) { + return false; + } + + if (isValidIPv4(ipOrDomain) && isIpInAnyRange(ipOrDomain)) { + return false; + } + + if (isValidDomain(ipOrDomain) && /metadata.google.internal/.test(ipOrDomain.toLowerCase())) { + return false; + } + + if (isValidDomain(ipOrDomain)) { + try { + const ipAddress = await nslookup(ipOrDomain); + if (isIpInAnyRange(ipAddress)) { + return false; + } + } catch (error) { + console.log(error); + return false; + } + } + + return true; +}; diff --git a/apps/meteor/app/lib/server/functions/deleteMessage.ts b/apps/meteor/app/lib/server/functions/deleteMessage.ts index e977874b3454..04542d5f1d27 100644 --- a/apps/meteor/app/lib/server/functions/deleteMessage.ts +++ b/apps/meteor/app/lib/server/functions/deleteMessage.ts @@ -5,11 +5,10 @@ import { Messages, Rooms, Uploads, Users, ReadReceipts } from '@rocket.chat/mode import { Meteor } from 'meteor/meteor'; import { callbacks } from '../../../../lib/callbacks'; -import { broadcastMessageFromData } from '../../../../server/modules/watchers/lib/messages'; import { canDeleteMessageAsync } from '../../../authorization/server/functions/canDeleteMessage'; import { FileUpload } from '../../../file-upload/server'; import { settings } from '../../../settings/server'; -import { notifyOnRoomChangedById } from '../lib/notifyListener'; +import { notifyOnRoomChangedById, notifyOnMessageChange } from '../lib/notifyListener'; export const deleteMessageValidatingPermission = async (message: AtLeast, userId: IUser['_id']): Promise => { if (!message?._id) { @@ -93,7 +92,7 @@ export async function deleteMessage(message: IMessage, user: IUser): Promise => { if (service === 'url' && typeof dataURI === 'string') { let response: Response; + + const isSsrfSafe = await checkUrlForSsrf(dataURI); + if (!isSsrfSafe) { + throw new Meteor.Error('error-avatar-invalid-url', `Invalid avatar URL: ${encodeURI(dataURI)}`, { + function: 'setUserAvatar', + url: dataURI, + }); + } + try { - response = await fetch(dataURI); + response = await fetch(dataURI, { redirect: 'error' }); } catch (e) { SystemLogger.info(`Not a valid response, from the avatar url: ${encodeURI(dataURI)}`); throw new Meteor.Error('error-avatar-invalid-url', `Invalid avatar URL: ${encodeURI(dataURI)}`, { diff --git a/apps/meteor/app/lib/server/functions/updateMessage.ts b/apps/meteor/app/lib/server/functions/updateMessage.ts index 2954517fb018..f51fc83c11d7 100644 --- a/apps/meteor/app/lib/server/functions/updateMessage.ts +++ b/apps/meteor/app/lib/server/functions/updateMessage.ts @@ -5,9 +5,8 @@ import { Messages, Rooms } from '@rocket.chat/models'; import { Meteor } from 'meteor/meteor'; import { callbacks } from '../../../../lib/callbacks'; -import { broadcastMessageFromData } from '../../../../server/modules/watchers/lib/messages'; import { settings } from '../../../settings/server'; -import { notifyOnRoomChangedById } from '../lib/notifyListener'; +import { notifyOnRoomChangedById, notifyOnMessageChange } from '../lib/notifyListener'; import { validateCustomMessageFields } from '../lib/validateCustomMessageFields'; import { parseUrlsInMessage } from './parseUrlsInMessage'; @@ -102,7 +101,7 @@ export const updateMessage = async function ( // so we wait for it to run before broadcasting const data = await callbacks.run('afterSaveMessage', msg, room, user._id); - void broadcastMessageFromData({ + void notifyOnMessageChange({ id: msg._id, data: data as any, // TODO move "afterSaveMessage" type definition to specify a return value }); diff --git a/apps/meteor/app/lib/server/functions/validateNameChars.ts b/apps/meteor/app/lib/server/functions/validateNameChars.ts new file mode 100644 index 000000000000..07330c66b762 --- /dev/null +++ b/apps/meteor/app/lib/server/functions/validateNameChars.ts @@ -0,0 +1,21 @@ +export const validateNameChars = (name: string | undefined): boolean => { + if (typeof name !== 'string') { + return false; + } + + const invalidChars = /[<>\\/]/; + if (invalidChars.test(name)) { + return false; + } + + try { + const decodedName = decodeURI(name); + if (invalidChars.test(decodedName)) { + return false; + } + } catch (err) { + return false; + } + + return true; +}; diff --git a/apps/meteor/app/lib/server/lib/notifyListener.ts b/apps/meteor/app/lib/server/lib/notifyListener.ts index 635c236fda27..83ab5774374a 100644 --- a/apps/meteor/app/lib/server/lib/notifyListener.ts +++ b/apps/meteor/app/lib/server/lib/notifyListener.ts @@ -17,6 +17,9 @@ import type { AtLeast, ISettingColor, IUser, + IMessage, + SettingValue, + MessageTypesValues, } from '@rocket.chat/core-typings'; import { Rooms, @@ -30,7 +33,11 @@ import { LivechatInquiry, LivechatDepartmentAgents, Users, + Messages, } from '@rocket.chat/models'; +import mem from 'mem'; + +import { shouldHideSystemMessage } from '../../../../server/lib/systemMessage/hideSystemMessage'; type ClientAction = 'inserted' | 'updated' | 'removed'; @@ -401,3 +408,65 @@ export const notifyOnUserChangeById = withDbWatcherCheck( void notifyOnUserChange({ id, clientAction, data: user }); }, ); + +const getUserNameCached = mem( + async (userId: string): Promise => { + const user = await Users.findOne>(userId, { projection: { name: 1 } }); + return user?.name; + }, + { maxAge: 10000 }, +); + +const getSettingCached = mem(async (setting: string): Promise => Settings.getValueById(setting), { maxAge: 10000 }); + +export async function getMessageToBroadcast({ id, data }: { id: IMessage['_id']; data?: IMessage }): Promise { + const message = data ?? (await Messages.findOneById(id)); + if (!message) { + return; + } + + if (message.t) { + const hiddenSystemMessages = (await getSettingCached('Hide_System_Messages')) as MessageTypesValues[]; + const shouldHide = shouldHideSystemMessage(message.t, hiddenSystemMessages); + + if (shouldHide) { + return; + } + } + + if (message._hidden || message.imported != null) { + return; + } + + const useRealName = (await getSettingCached('UI_Use_Real_Name')) === true; + if (useRealName) { + if (message.u?._id) { + const name = await getUserNameCached(message.u._id); + if (name) { + message.u.name = name; + } + } + + if (message.mentions?.length) { + for await (const mention of message.mentions) { + const name = await getUserNameCached(mention._id); + if (name) { + mention.name = name; + } + } + } + } + + return message; +} + +export const notifyOnMessageChange = withDbWatcherCheck(async ({ id, data }: { id: IMessage['_id']; data?: IMessage }): Promise => { + if (!dbWatchersDisabled) { + return; + } + const message = await getMessageToBroadcast({ id, data }); + if (!message) { + return; + } + void api.broadcast('watch.messages', { message }); +}); diff --git a/apps/meteor/app/lib/server/lib/sendNotificationsOnMessage.ts b/apps/meteor/app/lib/server/lib/sendNotificationsOnMessage.ts index 44654428ae8f..49fcc0ea4725 100644 --- a/apps/meteor/app/lib/server/lib/sendNotificationsOnMessage.ts +++ b/apps/meteor/app/lib/server/lib/sendNotificationsOnMessage.ts @@ -266,7 +266,7 @@ export async function sendMessageNotifications(message: IMessage, room: IRoom, u return; } - const sender = await roomCoordinator.getRoomDirectives(room.t).getMsgSender(message.u._id); + const sender = await roomCoordinator.getRoomDirectives(room.t).getMsgSender(message); if (!sender) { return message; } diff --git a/apps/meteor/app/lib/server/methods/addOAuthService.ts b/apps/meteor/app/lib/server/methods/addOAuthService.ts index 05b0e5a7e4e6..09287bb9bb74 100644 --- a/apps/meteor/app/lib/server/methods/addOAuthService.ts +++ b/apps/meteor/app/lib/server/methods/addOAuthService.ts @@ -1,11 +1,11 @@ -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; import { addOAuthService } from '../../../../server/lib/oauth/addOAuthService'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { addOAuthService(name: string): void; diff --git a/apps/meteor/app/lib/server/methods/addUserToRoom.ts b/apps/meteor/app/lib/server/methods/addUserToRoom.ts index 880b413d0618..8100cafc33b0 100644 --- a/apps/meteor/app/lib/server/methods/addUserToRoom.ts +++ b/apps/meteor/app/lib/server/methods/addUserToRoom.ts @@ -1,9 +1,9 @@ -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; import { addUsersToRoomMethod } from './addUsersToRoom'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { addUserToRoom(data: { rid: string; username: string }): void; diff --git a/apps/meteor/app/lib/server/methods/addUsersToRoom.ts b/apps/meteor/app/lib/server/methods/addUsersToRoom.ts index 48b7f9db58f5..73fbf6e51a04 100644 --- a/apps/meteor/app/lib/server/methods/addUsersToRoom.ts +++ b/apps/meteor/app/lib/server/methods/addUsersToRoom.ts @@ -1,8 +1,8 @@ import { api } from '@rocket.chat/core-services'; import type { IUser } from '@rocket.chat/core-typings'; import { isRoomFederated } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Subscriptions, Users, Rooms } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Match } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; @@ -12,7 +12,7 @@ import { Federation } from '../../../../server/services/federation/Federation'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; import { addUserToRoom } from '../functions/addUserToRoom'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { addUsersToRoom(data: { rid: string; users: string[] }): boolean; diff --git a/apps/meteor/app/lib/server/methods/archiveRoom.ts b/apps/meteor/app/lib/server/methods/archiveRoom.ts index c30014f59c11..dfa5a2c55412 100644 --- a/apps/meteor/app/lib/server/methods/archiveRoom.ts +++ b/apps/meteor/app/lib/server/methods/archiveRoom.ts @@ -1,6 +1,6 @@ import { isRegisterUser } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Users, Rooms } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; @@ -9,7 +9,7 @@ import { roomCoordinator } from '../../../../server/lib/rooms/roomCoordinator'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; import { archiveRoom } from '../functions/archiveRoom'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { archiveRoom(rid: string): Promise; diff --git a/apps/meteor/app/lib/server/methods/blockUser.ts b/apps/meteor/app/lib/server/methods/blockUser.ts index b65423edf25b..b967e35d7bc1 100644 --- a/apps/meteor/app/lib/server/methods/blockUser.ts +++ b/apps/meteor/app/lib/server/methods/blockUser.ts @@ -1,12 +1,12 @@ +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Subscriptions, Rooms } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; import { RoomMemberActions } from '../../../../definition/IRoomTypeConfig'; import { roomCoordinator } from '../../../../server/lib/rooms/roomCoordinator'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { blockUser({ rid, blocked }: { rid: string; blocked: string }): boolean; diff --git a/apps/meteor/app/lib/server/methods/checkRegistrationSecretURL.ts b/apps/meteor/app/lib/server/methods/checkRegistrationSecretURL.ts index 3f349a8b43e6..ecba6844da26 100644 --- a/apps/meteor/app/lib/server/methods/checkRegistrationSecretURL.ts +++ b/apps/meteor/app/lib/server/methods/checkRegistrationSecretURL.ts @@ -1,4 +1,4 @@ -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; diff --git a/apps/meteor/app/lib/server/methods/checkUsernameAvailability.ts b/apps/meteor/app/lib/server/methods/checkUsernameAvailability.ts index 34ad02ddb2cf..4df2706bb479 100644 --- a/apps/meteor/app/lib/server/methods/checkUsernameAvailability.ts +++ b/apps/meteor/app/lib/server/methods/checkUsernameAvailability.ts @@ -1,4 +1,4 @@ -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; @@ -6,7 +6,7 @@ import { checkUsernameAvailabilityWithValidation } from '../functions/checkUsern import { RateLimiter } from '../lib'; import { methodDeprecationLogger } from '../lib/deprecationWarningLogger'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { checkUsernameAvailability(username: string): boolean; diff --git a/apps/meteor/app/lib/server/methods/cleanRoomHistory.ts b/apps/meteor/app/lib/server/methods/cleanRoomHistory.ts index a724d1b38b2c..d6136eee9131 100644 --- a/apps/meteor/app/lib/server/methods/cleanRoomHistory.ts +++ b/apps/meteor/app/lib/server/methods/cleanRoomHistory.ts @@ -1,11 +1,11 @@ -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Match, check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; import { cleanRoomHistory } from '../functions/cleanRoomHistory'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { cleanRoomHistory(data: { diff --git a/apps/meteor/app/lib/server/methods/createChannel.ts b/apps/meteor/app/lib/server/methods/createChannel.ts index 98cea517bed4..a490fa1e3c42 100644 --- a/apps/meteor/app/lib/server/methods/createChannel.ts +++ b/apps/meteor/app/lib/server/methods/createChannel.ts @@ -1,13 +1,13 @@ import type { ICreatedRoom } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Users } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Match, check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; import { createRoom } from '../functions/createRoom'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { createChannel( diff --git a/apps/meteor/app/lib/server/methods/createPrivateGroup.ts b/apps/meteor/app/lib/server/methods/createPrivateGroup.ts index 75097b5c89b8..3b92b2607829 100644 --- a/apps/meteor/app/lib/server/methods/createPrivateGroup.ts +++ b/apps/meteor/app/lib/server/methods/createPrivateGroup.ts @@ -1,13 +1,13 @@ import type { ICreatedRoom, IUser } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Users } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Match, check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; import { createRoom } from '../functions/createRoom'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { createPrivateGroup( diff --git a/apps/meteor/app/lib/server/methods/createToken.ts b/apps/meteor/app/lib/server/methods/createToken.ts index ed665944415a..de60a7e37fe8 100644 --- a/apps/meteor/app/lib/server/methods/createToken.ts +++ b/apps/meteor/app/lib/server/methods/createToken.ts @@ -1,12 +1,12 @@ import { User } from '@rocket.chat/core-services'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Accounts } from 'meteor/accounts-base'; import { Meteor } from 'meteor/meteor'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; import { methodDeprecationLogger } from '../lib/deprecationWarningLogger'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { createToken(userId: string): { userId: string; authToken: string }; diff --git a/apps/meteor/app/lib/server/methods/deleteMessage.ts b/apps/meteor/app/lib/server/methods/deleteMessage.ts index a1b1000c06b8..b0be64c245ef 100644 --- a/apps/meteor/app/lib/server/methods/deleteMessage.ts +++ b/apps/meteor/app/lib/server/methods/deleteMessage.ts @@ -1,11 +1,11 @@ import type { IMessage } from '@rocket.chat/core-typings'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; import { deleteMessageValidatingPermission } from '../functions/deleteMessage'; import { methodDeprecationLogger } from '../lib/deprecationWarningLogger'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { deleteMessage({ _id }: Pick): void; diff --git a/apps/meteor/app/lib/server/methods/deleteUserOwnAccount.ts b/apps/meteor/app/lib/server/methods/deleteUserOwnAccount.ts index 2d651950da19..7b5663185bc5 100644 --- a/apps/meteor/app/lib/server/methods/deleteUserOwnAccount.ts +++ b/apps/meteor/app/lib/server/methods/deleteUserOwnAccount.ts @@ -1,7 +1,7 @@ import { Apps, AppEvents } from '@rocket.chat/apps'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Users } from '@rocket.chat/models'; import { SHA256 } from '@rocket.chat/sha256'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Accounts } from 'meteor/accounts-base'; import { check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; @@ -10,7 +10,7 @@ import { trim } from '../../../../lib/utils/stringUtils'; import { settings } from '../../../settings/server'; import { deleteUser } from '../functions/deleteUser'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { deleteUserOwnAccount(password: string, confirmRelinquish?: boolean): Promise; diff --git a/apps/meteor/app/lib/server/methods/executeSlashCommandPreview.ts b/apps/meteor/app/lib/server/methods/executeSlashCommandPreview.ts index 80b5428efbef..1c116863610d 100644 --- a/apps/meteor/app/lib/server/methods/executeSlashCommandPreview.ts +++ b/apps/meteor/app/lib/server/methods/executeSlashCommandPreview.ts @@ -1,10 +1,10 @@ import type { IMessage, RequiredField, SlashCommandPreviewItem } from '@rocket.chat/core-typings'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; import { slashCommands } from '../../../utils/server/slashCommand'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { executeSlashCommandPreview( diff --git a/apps/meteor/app/lib/server/methods/getChannelHistory.ts b/apps/meteor/app/lib/server/methods/getChannelHistory.ts index 00ff01639593..8f1f4c586141 100644 --- a/apps/meteor/app/lib/server/methods/getChannelHistory.ts +++ b/apps/meteor/app/lib/server/methods/getChannelHistory.ts @@ -1,6 +1,6 @@ import type { IMessage, MessageTypesValues } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Messages, Subscriptions, Rooms } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; import _ from 'underscore'; @@ -11,7 +11,7 @@ import { settings } from '../../../settings/server/cached'; import { normalizeMessagesForUser } from '../../../utils/server/lib/normalizeMessagesForUser'; import { getHiddenSystemMessages } from '../lib/getHiddenSystemMessages'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { getChannelHistory(params: { diff --git a/apps/meteor/app/lib/server/methods/getMessages.ts b/apps/meteor/app/lib/server/methods/getMessages.ts index 909e3d0c656b..d8684f82453c 100644 --- a/apps/meteor/app/lib/server/methods/getMessages.ts +++ b/apps/meteor/app/lib/server/methods/getMessages.ts @@ -1,12 +1,12 @@ import type { IMessage } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Messages } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; import { canAccessRoomIdAsync } from '../../../authorization/server/functions/canAccessRoom'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { getMessages(messages: IMessage['_id'][]): Promise; diff --git a/apps/meteor/app/lib/server/methods/getRoomJoinCode.ts b/apps/meteor/app/lib/server/methods/getRoomJoinCode.ts index 75e4a4372f57..5ba4b3490722 100644 --- a/apps/meteor/app/lib/server/methods/getRoomJoinCode.ts +++ b/apps/meteor/app/lib/server/methods/getRoomJoinCode.ts @@ -1,12 +1,12 @@ import { isRoomWithJoinCode } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Rooms } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { getRoomJoinCode(rid: string): string | false; diff --git a/apps/meteor/app/lib/server/methods/getRoomRoles.ts b/apps/meteor/app/lib/server/methods/getRoomRoles.ts index ac5fcc734d0f..b411ba8fedf5 100644 --- a/apps/meteor/app/lib/server/methods/getRoomRoles.ts +++ b/apps/meteor/app/lib/server/methods/getRoomRoles.ts @@ -1,6 +1,6 @@ import type { IRoom, ISubscription } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Rooms } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; @@ -8,7 +8,7 @@ import { getRoomRoles } from '../../../../server/lib/roles/getRoomRoles'; import { canAccessRoomAsync } from '../../../authorization/server'; import { settings } from '../../../settings/server'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { getRoomRoles(rid: IRoom['_id']): ISubscription[]; diff --git a/apps/meteor/app/lib/server/methods/getSingleMessage.ts b/apps/meteor/app/lib/server/methods/getSingleMessage.ts index 1aaf2a652257..c4b6f065296b 100644 --- a/apps/meteor/app/lib/server/methods/getSingleMessage.ts +++ b/apps/meteor/app/lib/server/methods/getSingleMessage.ts @@ -1,12 +1,12 @@ import type { IMessage } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Messages } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; import { canAccessRoomIdAsync } from '../../../authorization/server/functions/canAccessRoom'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { getSingleMessage(mid: IMessage['_id']): Promise; diff --git a/apps/meteor/app/lib/server/methods/getSlashCommandPreviews.ts b/apps/meteor/app/lib/server/methods/getSlashCommandPreviews.ts index dcb39c466063..965c91cc502f 100644 --- a/apps/meteor/app/lib/server/methods/getSlashCommandPreviews.ts +++ b/apps/meteor/app/lib/server/methods/getSlashCommandPreviews.ts @@ -1,10 +1,10 @@ import type { IMessage, RequiredField, SlashCommandPreviews } from '@rocket.chat/core-typings'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; import { slashCommands } from '../../../utils/server/slashCommand'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { getSlashCommandPreviews(command: { diff --git a/apps/meteor/app/lib/server/methods/getUserRoles.ts b/apps/meteor/app/lib/server/methods/getUserRoles.ts index cc7588276c33..cbd4712930a2 100644 --- a/apps/meteor/app/lib/server/methods/getUserRoles.ts +++ b/apps/meteor/app/lib/server/methods/getUserRoles.ts @@ -1,9 +1,9 @@ import { Authorization } from '@rocket.chat/core-services'; import type { IUser, IRocketChatRecord } from '@rocket.chat/core-typings'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { getUserRoles(): (IRocketChatRecord & Pick)[]; diff --git a/apps/meteor/app/lib/server/methods/getUsernameSuggestion.ts b/apps/meteor/app/lib/server/methods/getUsernameSuggestion.ts index 5724449a5790..b42799f24081 100644 --- a/apps/meteor/app/lib/server/methods/getUsernameSuggestion.ts +++ b/apps/meteor/app/lib/server/methods/getUsernameSuggestion.ts @@ -1,9 +1,9 @@ -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; import { generateUsernameSuggestion } from '../functions/getUsernameSuggestion'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { getUsernameSuggestion(): Promise; diff --git a/apps/meteor/app/lib/server/methods/insertOrUpdateUser.ts b/apps/meteor/app/lib/server/methods/insertOrUpdateUser.ts index 5a8b1c8d1a58..122b11172d57 100644 --- a/apps/meteor/app/lib/server/methods/insertOrUpdateUser.ts +++ b/apps/meteor/app/lib/server/methods/insertOrUpdateUser.ts @@ -1,4 +1,4 @@ -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; @@ -6,7 +6,7 @@ import { twoFactorRequired } from '../../../2fa/server/twoFactorRequired'; import { saveUser } from '../functions/saveUser'; import { methodDeprecationLogger } from '../lib/deprecationWarningLogger'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { insertOrUpdateUser(userData: Record): Promise; diff --git a/apps/meteor/app/lib/server/methods/joinDefaultChannels.ts b/apps/meteor/app/lib/server/methods/joinDefaultChannels.ts index 309ac4e449be..df654bc4aef0 100644 --- a/apps/meteor/app/lib/server/methods/joinDefaultChannels.ts +++ b/apps/meteor/app/lib/server/methods/joinDefaultChannels.ts @@ -1,11 +1,11 @@ import type { IUser } from '@rocket.chat/core-typings'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Match, check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; import { addUserToDefaultChannels } from '../functions/addUserToDefaultChannels'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { joinDefaultChannels(silenced?: boolean): void; diff --git a/apps/meteor/app/lib/server/methods/joinRoom.ts b/apps/meteor/app/lib/server/methods/joinRoom.ts index 0fa3ac0b3c3b..ef3f069ee614 100644 --- a/apps/meteor/app/lib/server/methods/joinRoom.ts +++ b/apps/meteor/app/lib/server/methods/joinRoom.ts @@ -1,11 +1,11 @@ import { Room } from '@rocket.chat/core-services'; import type { IRoom } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Rooms } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { joinRoom(rid: IRoom['_id'], code?: string): boolean | undefined; diff --git a/apps/meteor/app/lib/server/methods/leaveRoom.ts b/apps/meteor/app/lib/server/methods/leaveRoom.ts index ec1bb1638a21..4fc85b35fd05 100644 --- a/apps/meteor/app/lib/server/methods/leaveRoom.ts +++ b/apps/meteor/app/lib/server/methods/leaveRoom.ts @@ -1,6 +1,6 @@ import type { IUser } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Roles, Subscriptions, Rooms } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; @@ -10,7 +10,7 @@ import { hasPermissionAsync } from '../../../authorization/server/functions/hasP import { hasRoleAsync } from '../../../authorization/server/functions/hasRole'; import { removeUserFromRoom } from '../functions/removeUserFromRoom'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { leaveRoom(rid: string): Promise; diff --git a/apps/meteor/app/lib/server/methods/refreshOAuthService.ts b/apps/meteor/app/lib/server/methods/refreshOAuthService.ts index e5b1c377a33e..1d547b770361 100644 --- a/apps/meteor/app/lib/server/methods/refreshOAuthService.ts +++ b/apps/meteor/app/lib/server/methods/refreshOAuthService.ts @@ -1,10 +1,10 @@ -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; import { refreshLoginServices } from '../../../../server/lib/refreshLoginServices'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { refreshOAuthService(): Promise; diff --git a/apps/meteor/app/lib/server/methods/removeOAuthService.ts b/apps/meteor/app/lib/server/methods/removeOAuthService.ts index 6e16dc8d2d5b..fee2caa911d2 100644 --- a/apps/meteor/app/lib/server/methods/removeOAuthService.ts +++ b/apps/meteor/app/lib/server/methods/removeOAuthService.ts @@ -1,13 +1,13 @@ +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Settings } from '@rocket.chat/models'; import { capitalize } from '@rocket.chat/string-helpers'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; import { notifyOnSettingChangedById } from '../lib/notifyListener'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { removeOAuthService(name: string): Promise; diff --git a/apps/meteor/app/lib/server/methods/restartServer.ts b/apps/meteor/app/lib/server/methods/restartServer.ts index 206824aebe7e..264ab4d1bee6 100644 --- a/apps/meteor/app/lib/server/methods/restartServer.ts +++ b/apps/meteor/app/lib/server/methods/restartServer.ts @@ -1,9 +1,9 @@ -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { restart_server(): { diff --git a/apps/meteor/app/lib/server/methods/saveCustomFields.ts b/apps/meteor/app/lib/server/methods/saveCustomFields.ts index a509c97bdb85..d683e59a905c 100644 --- a/apps/meteor/app/lib/server/methods/saveCustomFields.ts +++ b/apps/meteor/app/lib/server/methods/saveCustomFields.ts @@ -1,11 +1,11 @@ import type { IUser } from '@rocket.chat/core-typings'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; import { saveCustomFields } from '../functions/saveCustomFields'; import { RateLimiter } from '../lib'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { saveCustomFields: (fields: IUser['customFields']) => Promise; diff --git a/apps/meteor/app/lib/server/methods/saveSetting.ts b/apps/meteor/app/lib/server/methods/saveSetting.ts index 7f900d1751d8..4f4d29b9fa24 100644 --- a/apps/meteor/app/lib/server/methods/saveSetting.ts +++ b/apps/meteor/app/lib/server/methods/saveSetting.ts @@ -1,6 +1,6 @@ import type { SettingValue } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Settings } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Match, check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; @@ -9,7 +9,7 @@ import { getSettingPermissionId } from '../../../authorization/lib'; import { hasPermissionAsync, hasAllPermissionAsync } from '../../../authorization/server/functions/hasPermission'; import { notifyOnSettingChanged } from '../lib/notifyListener'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { saveSetting(_id: string, value: SettingValue, editor?: string): Promise; diff --git a/apps/meteor/app/lib/server/methods/saveSettings.ts b/apps/meteor/app/lib/server/methods/saveSettings.ts index 8c4f92cfb88f..dffa986b7217 100644 --- a/apps/meteor/app/lib/server/methods/saveSettings.ts +++ b/apps/meteor/app/lib/server/methods/saveSettings.ts @@ -1,7 +1,7 @@ import type { ISetting } from '@rocket.chat/core-typings'; import { isSettingCode } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Settings } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Match, check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; @@ -11,7 +11,7 @@ import { hasPermissionAsync } from '../../../authorization/server/functions/hasP import { settings } from '../../../settings/server'; import { notifyOnSettingChangedById } from '../lib/notifyListener'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { saveSettings( diff --git a/apps/meteor/app/lib/server/methods/sendMessage.ts b/apps/meteor/app/lib/server/methods/sendMessage.ts index a490b5c4c67f..56009f15fede 100644 --- a/apps/meteor/app/lib/server/methods/sendMessage.ts +++ b/apps/meteor/app/lib/server/methods/sendMessage.ts @@ -1,7 +1,7 @@ import { api } from '@rocket.chat/core-services'; import type { AtLeast, IMessage, IUser } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Messages, Users } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; import moment from 'moment'; @@ -12,6 +12,7 @@ import { canSendMessageAsync } from '../../../authorization/server/functions/can import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; import { metrics } from '../../../metrics/server'; import { settings } from '../../../settings/server'; +import { MessageTypes } from '../../../ui-utils/server'; import { sendMessage } from '../functions/sendMessage'; import { RateLimiter } from '../lib'; @@ -78,6 +79,8 @@ export async function executeSendMessage(uid: IUser['_id'], message: AtLeast, previewUrls?: string[]): any; @@ -126,6 +129,10 @@ Meteor.methods({ }); } + if (MessageTypes.isSystemMessage(message)) { + throw new Error("Cannot send system messages using 'sendMessage'"); + } + try { return await executeSendMessage(uid, message, previewUrls); } catch (error: any) { diff --git a/apps/meteor/app/lib/server/methods/sendSMTPTestEmail.ts b/apps/meteor/app/lib/server/methods/sendSMTPTestEmail.ts index 2ede129dd380..5a04032ad82e 100644 --- a/apps/meteor/app/lib/server/methods/sendSMTPTestEmail.ts +++ b/apps/meteor/app/lib/server/methods/sendSMTPTestEmail.ts @@ -1,11 +1,11 @@ -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { DDPRateLimiter } from 'meteor/ddp-rate-limiter'; import { Meteor } from 'meteor/meteor'; import * as Mailer from '../../../mailer/server/api'; import { settings } from '../../../settings/server'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { sendSMTPTestEmail(): { diff --git a/apps/meteor/app/lib/server/methods/setAdminStatus.ts b/apps/meteor/app/lib/server/methods/setAdminStatus.ts index 42ffdc91f85e..300aa735b014 100644 --- a/apps/meteor/app/lib/server/methods/setAdminStatus.ts +++ b/apps/meteor/app/lib/server/methods/setAdminStatus.ts @@ -1,12 +1,12 @@ import { isUserFederated } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Users } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Match, check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { setAdminStatus(userId: string, admin?: boolean): void; diff --git a/apps/meteor/app/lib/server/methods/setEmail.ts b/apps/meteor/app/lib/server/methods/setEmail.ts index a172eba72555..26540db26b4c 100644 --- a/apps/meteor/app/lib/server/methods/setEmail.ts +++ b/apps/meteor/app/lib/server/methods/setEmail.ts @@ -1,4 +1,4 @@ -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; @@ -6,7 +6,7 @@ import { settings } from '../../../settings/server'; import { setEmail } from '../functions/setEmail'; import { RateLimiter } from '../lib'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { setEmail(email: string): string; diff --git a/apps/meteor/app/lib/server/methods/setRealName.ts b/apps/meteor/app/lib/server/methods/setRealName.ts index 2a55bd102172..f347eef1580e 100644 --- a/apps/meteor/app/lib/server/methods/setRealName.ts +++ b/apps/meteor/app/lib/server/methods/setRealName.ts @@ -1,4 +1,4 @@ -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; @@ -6,7 +6,7 @@ import { settings } from '../../../settings/server'; import { setRealName } from '../functions/setRealName'; import { RateLimiter } from '../lib'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { setRealName(name: string): string; diff --git a/apps/meteor/app/lib/server/methods/setUsername.ts b/apps/meteor/app/lib/server/methods/setUsername.ts index 900848f37783..58fac75ed3bd 100644 --- a/apps/meteor/app/lib/server/methods/setUsername.ts +++ b/apps/meteor/app/lib/server/methods/setUsername.ts @@ -1,11 +1,11 @@ -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; import { setUsernameWithValidation } from '../functions/setUsername'; import { RateLimiter } from '../lib'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { setUsername(username: string, param?: { joinDefaultChannelsSilenced?: boolean }): string; diff --git a/apps/meteor/app/lib/server/methods/unarchiveRoom.ts b/apps/meteor/app/lib/server/methods/unarchiveRoom.ts index 0f9349365f4f..74b74c11e54a 100644 --- a/apps/meteor/app/lib/server/methods/unarchiveRoom.ts +++ b/apps/meteor/app/lib/server/methods/unarchiveRoom.ts @@ -1,13 +1,13 @@ import { isRegisterUser } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Users, Rooms } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; import { unarchiveRoom } from '../functions/unarchiveRoom'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { unarchiveRoom(rid: string): Promise; diff --git a/apps/meteor/app/lib/server/methods/unblockUser.ts b/apps/meteor/app/lib/server/methods/unblockUser.ts index 6c8a9d486bab..2eec5a082109 100644 --- a/apps/meteor/app/lib/server/methods/unblockUser.ts +++ b/apps/meteor/app/lib/server/methods/unblockUser.ts @@ -1,9 +1,9 @@ +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Subscriptions } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { unblockUser({ rid, blocked }: { rid: string; blocked: string }): boolean; diff --git a/apps/meteor/app/lib/server/methods/updateMessage.ts b/apps/meteor/app/lib/server/methods/updateMessage.ts index 161a168a2cdc..aff5e563f666 100644 --- a/apps/meteor/app/lib/server/methods/updateMessage.ts +++ b/apps/meteor/app/lib/server/methods/updateMessage.ts @@ -1,6 +1,6 @@ import type { IEditedMessage, IMessage, IUser, AtLeast } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Messages, Users } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Match, check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; import moment from 'moment'; @@ -90,7 +90,7 @@ export async function executeUpdateMessage(uid: IUser['_id'], message: AtLeast, fileUrl: string) => { - const response = await fetch(fileUrl); + const isSsrfSafe = await checkUrlForSsrf(fileUrl); + if (!isSsrfSafe) { + throw new Meteor.Error('error-invalid-url', 'Invalid URL'); + } + + const response = await fetch(fileUrl, { redirect: 'error' }); const content = Buffer.from(await response.arrayBuffer()); diff --git a/apps/meteor/app/livechat/server/api/lib/rooms.ts b/apps/meteor/app/livechat/server/api/lib/rooms.ts index b130e5c2c73a..26449dce3963 100644 --- a/apps/meteor/app/livechat/server/api/lib/rooms.ts +++ b/apps/meteor/app/livechat/server/api/lib/rooms.ts @@ -14,6 +14,7 @@ export async function findRooms({ tags, customFields, onhold, + queued, options: { offset, count, fields, sort }, }: { agents?: Array; @@ -31,6 +32,7 @@ export async function findRooms({ tags?: Array; customFields?: Record; onhold?: string | boolean; + queued?: string | boolean; options: { offset: number; count: number; fields: Record; sort: Record }; }): Promise }>> { const extraQuery = await callbacks.run('livechat.applyRoomRestrictions', {}); @@ -44,6 +46,7 @@ export async function findRooms({ tags, customFields, onhold: ['t', 'true', '1'].includes(`${onhold}`), + queued: ['t', 'true', '1'].includes(`${queued}`), options: { sort: sort || { ts: -1 }, offset, diff --git a/apps/meteor/app/livechat/server/api/v1/room.ts b/apps/meteor/app/livechat/server/api/v1/room.ts index 94674f801ad5..b0f45a63ff87 100644 --- a/apps/meteor/app/livechat/server/api/v1/room.ts +++ b/apps/meteor/app/livechat/server/api/v1/room.ts @@ -293,8 +293,7 @@ API.v1.addRoute( throw new Error('error-invalid-visitor'); } - const transferedBy = this.user satisfies TransferByData; - transferData.transferredBy = normalizeTransferredByData(transferedBy, room); + transferData.transferredBy = normalizeTransferredByData(this.user, room); if (transferData.userId) { const userToTransfer = await Users.findOneById(transferData.userId); if (userToTransfer) { diff --git a/apps/meteor/app/livechat/server/externalFrame/generateNewKey.ts b/apps/meteor/app/livechat/server/externalFrame/generateNewKey.ts index 11463bcf00d4..a8f145f47d39 100644 --- a/apps/meteor/app/livechat/server/externalFrame/generateNewKey.ts +++ b/apps/meteor/app/livechat/server/externalFrame/generateNewKey.ts @@ -1,7 +1,7 @@ -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { omnichannelExternalFrameGenerateKey(): unknown; diff --git a/apps/meteor/app/livechat/server/lib/Helper.ts b/apps/meteor/app/livechat/server/lib/Helper.ts index 01bb2ff34e9a..c0e85a8c7c2b 100644 --- a/apps/meteor/app/livechat/server/lib/Helper.ts +++ b/apps/meteor/app/livechat/server/lib/Helper.ts @@ -142,7 +142,9 @@ export const createLivechatRoom = async < await callbacks.run('livechat.newRoom', room); - await sendMessage(guest, { t: 'livechat-started', msg: '', groupable: false }, room); + // TODO: replace with `Message.saveSystemMessage` + + await sendMessage(guest, { t: 'livechat-started', msg: '', groupable: false, token: guest.token }, room); return result.value as IOmnichannelRoom; }; @@ -646,6 +648,7 @@ export const forwardRoomToDepartment = async (room: IOmnichannelRoom, guest: ILi '', { _id, username }, { + ...(transferData.transferredBy.userType === 'visitor' && { token: room.v.token }), transferData: { ...transferData, prevDepartment: transferData.originalDepartmentName, @@ -681,18 +684,23 @@ export const forwardRoomToDepartment = async (room: IOmnichannelRoom, guest: ILi return true; }; -export const normalizeTransferredByData = (transferredBy: TransferByData, room: IOmnichannelRoom) => { +type MakePropertyOptional = Omit & { [P in K]?: T[P] }; + +export const normalizeTransferredByData = ( + transferredBy: MakePropertyOptional, + room: IOmnichannelRoom, +): TransferByData => { if (!transferredBy || !room) { throw new Error('You must provide "transferredBy" and "room" params to "getTransferredByData"'); } const { servedBy: { _id: agentId } = {} } = room; const { _id, username, name, userType: transferType } = transferredBy; - const type = transferType || (_id === agentId ? 'agent' : 'user'); + const userType = transferType || (_id === agentId ? 'agent' : 'user'); return { _id, username, ...(name && { name }), - type, + userType, }; }; diff --git a/apps/meteor/app/livechat/server/lib/LivechatTyped.ts b/apps/meteor/app/livechat/server/lib/LivechatTyped.ts index bb56eb81ceb3..ccca7a8eb68e 100644 --- a/apps/meteor/app/livechat/server/lib/LivechatTyped.ts +++ b/apps/meteor/app/livechat/server/lib/LivechatTyped.ts @@ -9,7 +9,6 @@ import type { IUser, MessageTypesValues, ILivechatVisitor, - IOmnichannelSystemMessage, SelectedAgent, ILivechatAgent, IMessage, @@ -41,7 +40,6 @@ import { import { serverFetch as fetch } from '@rocket.chat/server-fetch'; import { Match, check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; -import moment from 'moment-timezone'; import type { Filter, FindCursor } from 'mongodb'; import UAParser from 'ua-parser-js'; @@ -68,12 +66,14 @@ import { import * as Mailer from '../../../mailer/server/api'; import { metrics } from '../../../metrics/server'; import { settings } from '../../../settings/server'; -import { getTimezone } from '../../../utils/server/lib/getTimezone'; import { businessHourManager } from '../business-hour'; import { parseAgentCustomFields, updateDepartmentAgents, validateEmail, normalizeTransferredByData } from './Helper'; import { QueueManager } from './QueueManager'; import { RoutingManager } from './RoutingManager'; import { isDepartmentCreationAvailable } from './isDepartmentCreationAvailable'; +import type { CloseRoomParams, CloseRoomParamsByUser, CloseRoomParamsByVisitor } from './localTypes'; +import { parseTranscriptRequest } from './parseTranscriptRequest'; +import { sendTranscript as sendTranscriptFunc } from './sendTranscript'; type RegisterGuestType = Partial> & { id?: string; @@ -82,36 +82,6 @@ type RegisterGuestType = Partial; - }; - pdfTranscript?: { - requestedBy: string; - }; - }; -}; - -export type CloseRoomParamsByUser = { - user: IUser | null; -} & GenericCloseRoomParams; - -export type CloseRoomParamsByVisitor = { - visitor: ILivechatVisitor; -} & GenericCloseRoomParams; - -export type CloseRoomParams = CloseRoomParamsByUser | CloseRoomParamsByVisitor; - type OfflineMessageData = { message: string; name: string; @@ -326,12 +296,8 @@ class LivechatClass { this.logger.debug(`DB updated for room ${room._id}`); - const message = { - t: 'livechat-close', - msg: comment, - groupable: false, - transcriptRequested: !!transcriptRequest, - }; + const transcriptRequested = + !!transcriptRequest || (!settings.get('Livechat_enable_transcript') && settings.get('Livechat_transcript_send_always')); // Retrieve the closed room const newRoom = await LivechatRooms.findOneById(rid); @@ -341,9 +307,21 @@ class LivechatClass { } this.logger.debug(`Sending closing message to room ${room._id}`); - await sendMessage(chatCloser, message, newRoom); + await sendMessage( + chatCloser, + { + t: 'livechat-close', + msg: comment, + groupable: false, + transcriptRequested, + ...(isRoomClosedByVisitorParams(params) && { token: chatCloser.token }), + }, + newRoom, + ); - await Message.saveSystemMessage('command', rid, 'promptTranscript', closeData.closedBy); + if (settings.get('Livechat_enable_transcript') && !settings.get('Livechat_transcript_send_always')) { + await Message.saveSystemMessage('command', rid, 'promptTranscript', closeData.closedBy); + } this.logger.debug(`Running callbacks for room ${newRoom._id}`); @@ -355,15 +333,18 @@ class LivechatClass { void Apps.self?.getBridges()?.getListenerBridge().livechatEvent(AppEvents.ILivechatRoomClosedHandler, newRoom); void Apps.self?.getBridges()?.getListenerBridge().livechatEvent(AppEvents.IPostLivechatRoomClosed, newRoom); }); + + const visitor = isRoomClosedByVisitorParams(params) ? params.visitor : undefined; + const opts = await parseTranscriptRequest(params.room, options, visitor); if (process.env.TEST_MODE) { await callbacks.run('livechat.closeRoom', { room: newRoom, - options, + options: opts, }); } else { callbacks.runAsync('livechat.closeRoom', { room: newRoom, - options, + options: opts, }); } @@ -562,127 +543,6 @@ class LivechatClass { } } - async sendTranscript({ - token, - rid, - email, - subject, - user, - }: { - token: string; - rid: string; - email: string; - subject?: string; - user?: Pick | null; - }): Promise { - check(rid, String); - check(email, String); - this.logger.debug(`Sending conversation transcript of room ${rid} to user with token ${token}`); - - const room = await LivechatRooms.findOneById(rid); - - const visitor = await LivechatVisitors.getVisitorByToken(token, { - projection: { _id: 1, token: 1, language: 1, username: 1, name: 1 }, - }); - - if (!visitor) { - throw new Error('error-invalid-token'); - } - - // @ts-expect-error - Visitor typings should include language? - const userLanguage = visitor?.language || settings.get('Language') || 'en'; - const timezone = getTimezone(user); - this.logger.debug(`Transcript will be sent using ${timezone} as timezone`); - - if (!room) { - throw new Error('error-invalid-room'); - } - - // allow to only user to send transcripts from their own chats - if (room.t !== 'l' || !room.v || room.v.token !== token) { - throw new Error('error-invalid-room'); - } - - const showAgentInfo = settings.get('Livechat_show_agent_info'); - const closingMessage = await Messages.findLivechatClosingMessage(rid, { projection: { ts: 1 } }); - const ignoredMessageTypes: MessageTypesValues[] = [ - 'livechat_navigation_history', - 'livechat_transcript_history', - 'command', - 'livechat-close', - 'livechat-started', - 'livechat_video_call', - ]; - const messages = await Messages.findVisibleByRoomIdNotContainingTypesBeforeTs( - rid, - ignoredMessageTypes, - closingMessage?.ts ? new Date(closingMessage.ts) : new Date(), - { - sort: { ts: 1 }, - }, - ); - - let html = '

'; - await messages.forEach((message) => { - let author; - if (message.u._id === visitor._id) { - author = i18n.t('You', { lng: userLanguage }); - } else { - author = showAgentInfo ? message.u.name || message.u.username : i18n.t('Agent', { lng: userLanguage }); - } - - const datetime = moment.tz(message.ts, timezone).locale(userLanguage).format('LLL'); - const singleMessage = ` -

${author} ${datetime}

-

${message.msg}

- `; - html += singleMessage; - }); - - html = `${html}
`; - - const fromEmail = settings.get('From_Email').match(/\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,4}\b/i); - let emailFromRegexp = ''; - if (fromEmail) { - emailFromRegexp = fromEmail[0]; - } else { - emailFromRegexp = settings.get('From_Email'); - } - - const mailSubject = subject || i18n.t('Transcript_of_your_livechat_conversation', { lng: userLanguage }); - - await this.sendEmail(emailFromRegexp, email, emailFromRegexp, mailSubject, html); - - setImmediate(() => { - void callbacks.run('livechat.sendTranscript', messages, email); - }); - - const requestData: IOmnichannelSystemMessage['requestData'] = { - type: 'user', - visitor, - user, - }; - - if (!user?.username) { - const cat = await Users.findOneById('rocket.cat', { projection: { _id: 1, username: 1, name: 1 } }); - if (cat) { - requestData.user = cat; - requestData.type = 'visitor'; - } - } - - if (!requestData.user) { - this.logger.error('rocket.cat user not found'); - throw new Error('No user provided and rocket.cat not found'); - } - - await Message.saveSystemMessage('livechat_transcript_history', room._id, '', requestData.user, { - requestData, - }); - - return true; - } - async registerGuest({ id, token, @@ -712,7 +572,9 @@ class LivechatClass { visitorDataToUpdate.visitorEmails = [{ address: visitorEmail }]; } - if (department) { + const livechatVisitor = await LivechatVisitors.getVisitorByToken(token, { projection: { _id: 1 } }); + + if (livechatVisitor?.department !== department && department) { Livechat.logger.debug(`Attempt to find a department with id/name ${department}`); const dep = await LivechatDepartment.findOneByIdOrName(department, { projection: { _id: 1 } }); if (!dep) { @@ -723,8 +585,6 @@ class LivechatClass { visitorDataToUpdate.department = dep._id; } - const livechatVisitor = await LivechatVisitors.getVisitorByToken(token, { projection: { _id: 1 } }); - visitorDataToUpdate.token = livechatVisitor?.token || token; let existingUser = null; @@ -1267,7 +1127,7 @@ class LivechatClass { if (guest.name) { message.alias = guest.name; } - return Object.assign(await sendMessage(guest, message, room), { + return Object.assign(await sendMessage(guest, { ...message, token: guest.token }, room), { newRoom, showConnecting: this.showConnecting(), }); @@ -1386,7 +1246,7 @@ class LivechatClass { _id: String, username: String, name: Match.Maybe(String), - type: String, + userType: String, }), ); @@ -1394,34 +1254,31 @@ class LivechatClass { const scopeData = scope || (nextDepartment ? 'department' : 'agent'); this.logger.info(`Storing new chat transfer of ${room._id} [Transfered by: ${_id} to ${scopeData}]`); - const transfer = { - transferData: { - transferredBy, + await sendMessage( + transferredBy, + { + t: 'livechat_transfer_history', + rid: room._id, ts: new Date(), - scope: scopeData, - comment, - ...(previousDepartment && { previousDepartment }), - ...(nextDepartment && { nextDepartment }), - ...(transferredTo && { transferredTo }), - }, - }; - - const type = 'livechat_transfer_history'; - const transferMessage = { - t: type, - rid: room._id, - ts: new Date(), - msg: '', - u: { - _id, - username, + msg: '', + u: { + _id, + username, + }, + groupable: false, + ...(transferData.transferredBy.userType === 'visitor' && { token: room.v.token }), + transferData: { + transferredBy, + ts: new Date(), + scope: scopeData, + comment, + ...(previousDepartment && { previousDepartment }), + ...(nextDepartment && { nextDepartment }), + ...(transferredTo && { transferredTo }), + }, }, - groupable: false, - }; - - Object.assign(transferMessage, transfer); - - await sendMessage(transferredBy, transferMessage, room); + room, + ); } async saveGuest(guestData: Pick & { email?: string; phone?: string }, userId: string) { @@ -1984,6 +1841,23 @@ class LivechatClass { return departmentDB; } + + async sendTranscript({ + token, + rid, + email, + subject, + user, + }: { + token: string; + rid: string; + email: string; + subject?: string; + user?: Pick | null; + }): Promise { + return sendTranscriptFunc({ token, rid, email, subject, user }); + } } export const Livechat = new LivechatClass(); +export * from './localTypes'; diff --git a/apps/meteor/app/livechat/server/lib/localTypes.ts b/apps/meteor/app/livechat/server/lib/localTypes.ts new file mode 100644 index 000000000000..c6acbbc5bcbd --- /dev/null +++ b/apps/meteor/app/livechat/server/lib/localTypes.ts @@ -0,0 +1,31 @@ +import type { IOmnichannelRoom, IUser, ILivechatVisitor } from '@rocket.chat/core-typings'; + +export type GenericCloseRoomParams = { + room: IOmnichannelRoom; + comment?: string; + options?: { + clientAction?: boolean; + tags?: string[]; + emailTranscript?: + | { + sendToVisitor: false; + } + | { + sendToVisitor: true; + requestData: NonNullable; + }; + pdfTranscript?: { + requestedBy: string; + }; + }; +}; + +export type CloseRoomParamsByUser = { + user: IUser | null; +} & GenericCloseRoomParams; + +export type CloseRoomParamsByVisitor = { + visitor: ILivechatVisitor; +} & GenericCloseRoomParams; + +export type CloseRoomParams = CloseRoomParamsByUser | CloseRoomParamsByVisitor; diff --git a/apps/meteor/app/livechat/server/lib/parseTranscriptRequest.ts b/apps/meteor/app/livechat/server/lib/parseTranscriptRequest.ts new file mode 100644 index 000000000000..76595a7ff640 --- /dev/null +++ b/apps/meteor/app/livechat/server/lib/parseTranscriptRequest.ts @@ -0,0 +1,61 @@ +import type { ILivechatVisitor, IOmnichannelRoom, IUser } from '@rocket.chat/core-typings'; +import { LivechatVisitors, Users } from '@rocket.chat/models'; + +import { settings } from '../../../settings/server'; +import type { CloseRoomParams } from './localTypes'; + +export const parseTranscriptRequest = async ( + room: IOmnichannelRoom, + options: CloseRoomParams['options'], + visitor?: ILivechatVisitor, + user?: IUser, +): Promise => { + const visitorDecideTranscript = settings.get('Livechat_enable_transcript'); + // visitor decides, no changes + if (visitorDecideTranscript) { + return options; + } + + // send always is disabled, no changes + const sendAlways = settings.get('Livechat_transcript_send_always'); + if (!sendAlways) { + return options; + } + + const visitorData = + visitor || + (await LivechatVisitors.findOneById>(room.v._id, { projection: { visitorEmails: 1 } })); + // no visitor, no changes + if (!visitorData) { + return options; + } + const visitorEmail = visitorData?.visitorEmails?.[0]?.address; + // visitor doesnt have email, no changes + if (!visitorEmail) { + return options; + } + + const defOptions = { projection: { _id: 1, username: 1, name: 1 } }; + const requestedBy = + user || + (room.servedBy && (await Users.findOneById(room.servedBy._id, defOptions))) || + (await Users.findOneById('rocket.cat', defOptions)); + + // no user available for backing request, no changes + if (!requestedBy) { + return options; + } + + return { + ...options, + emailTranscript: { + sendToVisitor: true, + requestData: { + email: visitorEmail, + requestedAt: new Date(), + subject: '', + requestedBy, + }, + }, + }; +}; diff --git a/apps/meteor/app/livechat/server/lib/sendTranscript.ts b/apps/meteor/app/livechat/server/lib/sendTranscript.ts new file mode 100644 index 000000000000..74032121ee50 --- /dev/null +++ b/apps/meteor/app/livechat/server/lib/sendTranscript.ts @@ -0,0 +1,227 @@ +import { Message } from '@rocket.chat/core-services'; +import { + type IUser, + type MessageTypesValues, + type IOmnichannelSystemMessage, + isFileAttachment, + isFileImageAttachment, +} from '@rocket.chat/core-typings'; +import colors from '@rocket.chat/fuselage-tokens/colors'; +import { Logger } from '@rocket.chat/logger'; +import { LivechatRooms, LivechatVisitors, Messages, Uploads, Users } from '@rocket.chat/models'; +import { check } from 'meteor/check'; +import moment from 'moment-timezone'; + +import { callbacks } from '../../../../lib/callbacks'; +import { i18n } from '../../../../server/lib/i18n'; +import { FileUpload } from '../../../file-upload/server'; +import * as Mailer from '../../../mailer/server/api'; +import { settings } from '../../../settings/server'; +import { MessageTypes } from '../../../ui-utils/lib/MessageTypes'; +import { getTimezone } from '../../../utils/server/lib/getTimezone'; + +const logger = new Logger('Livechat-SendTranscript'); + +export async function sendTranscript({ + token, + rid, + email, + subject, + user, +}: { + token: string; + rid: string; + email: string; + subject?: string; + user?: Pick | null; +}): Promise { + check(rid, String); + check(email, String); + logger.debug(`Sending conversation transcript of room ${rid} to user with token ${token}`); + + const room = await LivechatRooms.findOneById(rid); + + const visitor = await LivechatVisitors.getVisitorByToken(token, { + projection: { _id: 1, token: 1, language: 1, username: 1, name: 1 }, + }); + + if (!visitor) { + throw new Error('error-invalid-token'); + } + + // @ts-expect-error - Visitor typings should include language? + const userLanguage = visitor?.language || settings.get('Language') || 'en'; + const timezone = getTimezone(user); + logger.debug(`Transcript will be sent using ${timezone} as timezone`); + + if (!room) { + throw new Error('error-invalid-room'); + } + + // allow to only user to send transcripts from their own chats + if (room.t !== 'l' || !room.v || room.v.token !== token) { + throw new Error('error-invalid-room'); + } + + const showAgentInfo = settings.get('Livechat_show_agent_info'); + const showSystemMessages = settings.get('Livechat_transcript_show_system_messages'); + const closingMessage = await Messages.findLivechatClosingMessage(rid, { projection: { ts: 1 } }); + const ignoredMessageTypes: MessageTypesValues[] = [ + 'livechat_navigation_history', + 'livechat_transcript_history', + 'command', + 'livechat-close', + 'livechat-started', + 'livechat_video_call', + 'omnichannel_priority_change_history', + ]; + const acceptableImageMimeTypes = ['image/jpeg', 'image/png', 'image/jpg']; + const messages = await Messages.findVisibleByRoomIdNotContainingTypesBeforeTs( + rid, + ignoredMessageTypes, + closingMessage?.ts ? new Date(closingMessage.ts) : new Date(), + showSystemMessages, + { + sort: { ts: 1 }, + }, + ); + + let html = '

'; + const InvalidFileMessage = `
${i18n.t( + 'This_attachment_is_not_supported', + { lng: userLanguage }, + )}
`; + + for await (const message of messages) { + let author; + if (message.u._id === visitor._id) { + author = i18n.t('You', { lng: userLanguage }); + } else { + author = showAgentInfo ? message.u.name || message.u.username : i18n.t('Agent', { lng: userLanguage }); + } + + const isSystemMessage = MessageTypes.isSystemMessage(message); + const messageType = isSystemMessage && MessageTypes.getType(message); + + let messageContent = messageType + ? `${i18n.t( + messageType.message, + messageType.data + ? { ...messageType.data(message), interpolation: { escapeValue: false } } + : { interpolation: { escapeValue: false } }, + )}` + : message.msg; + + let filesHTML = ''; + + if (message.attachments && message.attachments?.length > 0) { + messageContent = message.attachments[0].description || ''; + + for await (const attachment of message.attachments) { + if (!isFileAttachment(attachment)) { + // ignore other types of attachments + continue; + } + + if (!isFileImageAttachment(attachment)) { + filesHTML += `
${attachment.title || ''}${InvalidFileMessage}
`; + continue; + } + + if (!attachment.image_type || !acceptableImageMimeTypes.includes(attachment.image_type)) { + filesHTML += `
${attachment.title || ''}${InvalidFileMessage}
`; + continue; + } + + // Image attachment can be rendered in email body + const file = message.files?.find((file) => file.name === attachment.title); + + if (!file) { + filesHTML += `
${attachment.title || ''}${InvalidFileMessage}
`; + continue; + } + + const uploadedFile = await Uploads.findOneById(file._id); + + if (!uploadedFile) { + filesHTML += `
${file.name}${InvalidFileMessage}
`; + continue; + } + + const uploadedFileBuffer = await FileUpload.getBuffer(uploadedFile); + filesHTML += `

${file.name}

`; + } + } + + const datetime = moment.tz(message.ts, timezone).locale(userLanguage).format('LLL'); + const singleMessage = ` +

${author} ${datetime}

+

${messageContent}

+

${filesHTML}

+ `; + html += singleMessage; + } + + html = `${html}
`; + + const fromEmail = settings.get('From_Email').match(/\b[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,4}\b/i); + let emailFromRegexp = ''; + if (fromEmail) { + emailFromRegexp = fromEmail[0]; + } else { + emailFromRegexp = settings.get('From_Email'); + } + + // Some endpoints allow the caller to pass a different `subject` via parameter. + // IF subject is passed, we'll use that one and treat it as an override + // IF no subject is passed, we fallback to the setting `Livechat_transcript_email_subject` + // IF that is not configured, we fallback to 'Transcript of your livechat conversation', which is the default value + // As subject and setting value are user input, we don't translate them + const mailSubject = + subject || + settings.get('Livechat_transcript_email_subject') || + i18n.t('Transcript_of_your_livechat_conversation', { lng: userLanguage }); + + await Mailer.send({ + to: email, + from: emailFromRegexp, + replyTo: emailFromRegexp, + subject: mailSubject, + html, + }); + + setImmediate(() => { + void callbacks.run('livechat.sendTranscript', messages, email); + }); + + const requestData: IOmnichannelSystemMessage['requestData'] = { + type: 'user', + visitor, + user, + }; + + if (!user?.username) { + const cat = await Users.findOneById('rocket.cat', { projection: { _id: 1, username: 1, name: 1 } }); + if (cat) { + requestData.user = cat; + requestData.type = 'visitor'; + } + } + + if (!requestData.user) { + logger.error('rocket.cat user not found'); + throw new Error('No user provided and rocket.cat not found'); + } + + await Message.saveSystemMessage('livechat_transcript_history', room._id, '', requestData.user, { + requestData, + }); + + return true; +} diff --git a/apps/meteor/app/livechat/server/methods/addAgent.ts b/apps/meteor/app/livechat/server/methods/addAgent.ts index 6160db590ece..0551e985e18e 100644 --- a/apps/meteor/app/livechat/server/methods/addAgent.ts +++ b/apps/meteor/app/livechat/server/methods/addAgent.ts @@ -1,12 +1,12 @@ import type { IUser } from '@rocket.chat/core-typings'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger'; import { Livechat } from '../lib/LivechatTyped'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'livechat:addAgent'(username: string): Promise; diff --git a/apps/meteor/app/livechat/server/methods/addManager.ts b/apps/meteor/app/livechat/server/methods/addManager.ts index 347c4f07d63f..a954d8111773 100644 --- a/apps/meteor/app/livechat/server/methods/addManager.ts +++ b/apps/meteor/app/livechat/server/methods/addManager.ts @@ -1,12 +1,12 @@ import type { IUser } from '@rocket.chat/core-typings'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger'; import { Livechat } from '../lib/LivechatTyped'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'livechat:addManager'(username: string): Promise; diff --git a/apps/meteor/app/livechat/server/methods/changeLivechatStatus.ts b/apps/meteor/app/livechat/server/methods/changeLivechatStatus.ts index 8ccfcd5ec468..f45588cad6d3 100644 --- a/apps/meteor/app/livechat/server/methods/changeLivechatStatus.ts +++ b/apps/meteor/app/livechat/server/methods/changeLivechatStatus.ts @@ -1,13 +1,13 @@ import { ILivechatAgentStatus } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Users } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger'; import { Livechat as LivechatTS } from '../lib/LivechatTyped'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'livechat:changeLivechatStatus'(params?: { status?: ILivechatAgentStatus; agentId?: string }): unknown; diff --git a/apps/meteor/app/livechat/server/methods/closeRoom.ts b/apps/meteor/app/livechat/server/methods/closeRoom.ts index 5fdf9e7d504f..19c8b2709389 100644 --- a/apps/meteor/app/livechat/server/methods/closeRoom.ts +++ b/apps/meteor/app/livechat/server/methods/closeRoom.ts @@ -1,6 +1,6 @@ import type { IOmnichannelRoom } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Users, LivechatRooms, Subscriptions as SubscriptionRaw } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; @@ -35,7 +35,7 @@ type LivechatCloseRoomOptions = Omit }; }; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'livechat:closeRoom'(roomId: string, comment?: string, options?: CloseRoomOptions): void; diff --git a/apps/meteor/app/livechat/server/methods/discardTranscript.ts b/apps/meteor/app/livechat/server/methods/discardTranscript.ts index d46c8ffea35f..3265aa9c54d2 100644 --- a/apps/meteor/app/livechat/server/methods/discardTranscript.ts +++ b/apps/meteor/app/livechat/server/methods/discardTranscript.ts @@ -1,12 +1,12 @@ +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { LivechatRooms } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'livechat:discardTranscript'(rid: string): boolean; diff --git a/apps/meteor/app/livechat/server/methods/getAgentData.ts b/apps/meteor/app/livechat/server/methods/getAgentData.ts index d32d24d7f7c1..5fe58560806e 100644 --- a/apps/meteor/app/livechat/server/methods/getAgentData.ts +++ b/apps/meteor/app/livechat/server/methods/getAgentData.ts @@ -1,13 +1,13 @@ import type { ILivechatAgent } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { LivechatVisitors, LivechatRooms, Users } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger'; import { settings } from '../../../settings/server'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'livechat:getAgentData'(params: { diff --git a/apps/meteor/app/livechat/server/methods/getAgentOverviewData.ts b/apps/meteor/app/livechat/server/methods/getAgentOverviewData.ts index b5ea8dafe92c..819bac03c5b4 100644 --- a/apps/meteor/app/livechat/server/methods/getAgentOverviewData.ts +++ b/apps/meteor/app/livechat/server/methods/getAgentOverviewData.ts @@ -1,13 +1,13 @@ import type { ConversationData } from '@rocket.chat/core-services'; import { OmnichannelAnalytics } from '@rocket.chat/core-services'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Users } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'livechat:getAgentOverviewData'(options: { chartOptions: { name: string } }): ConversationData | void; diff --git a/apps/meteor/app/livechat/server/methods/getAnalyticsChartData.ts b/apps/meteor/app/livechat/server/methods/getAnalyticsChartData.ts index 85c8e033b8f5..2ff682c1c39c 100644 --- a/apps/meteor/app/livechat/server/methods/getAnalyticsChartData.ts +++ b/apps/meteor/app/livechat/server/methods/getAnalyticsChartData.ts @@ -1,12 +1,12 @@ import type { ChartDataResult } from '@rocket.chat/core-services'; import { OmnichannelAnalytics } from '@rocket.chat/core-services'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Users } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'livechat:getAnalyticsChartData'(options: { chartOptions: { name: string } }): ChartDataResult | void; diff --git a/apps/meteor/app/livechat/server/methods/getAnalyticsOverviewData.ts b/apps/meteor/app/livechat/server/methods/getAnalyticsOverviewData.ts index c9bb3d163457..9f56cfa57069 100644 --- a/apps/meteor/app/livechat/server/methods/getAnalyticsOverviewData.ts +++ b/apps/meteor/app/livechat/server/methods/getAnalyticsOverviewData.ts @@ -1,14 +1,14 @@ import type { AnalyticsOverviewDataResult } from '@rocket.chat/core-services'; import { OmnichannelAnalytics } from '@rocket.chat/core-services'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Users } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger'; import { settings } from '../../../settings/server'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'livechat:getAnalyticsOverviewData'(options: { analyticsOptions: { name: string } }): AnalyticsOverviewDataResult[] | void; diff --git a/apps/meteor/app/livechat/server/methods/getCustomFields.ts b/apps/meteor/app/livechat/server/methods/getCustomFields.ts index ec0ac35d6c21..36dca08f0859 100644 --- a/apps/meteor/app/livechat/server/methods/getCustomFields.ts +++ b/apps/meteor/app/livechat/server/methods/getCustomFields.ts @@ -1,11 +1,11 @@ import type { ILivechatCustomField } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { LivechatCustomField } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'livechat:getCustomFields'(): ILivechatCustomField[]; diff --git a/apps/meteor/app/livechat/server/methods/getDepartmentForwardRestrictions.ts b/apps/meteor/app/livechat/server/methods/getDepartmentForwardRestrictions.ts index b26d9706a8cd..2b891514d03e 100644 --- a/apps/meteor/app/livechat/server/methods/getDepartmentForwardRestrictions.ts +++ b/apps/meteor/app/livechat/server/methods/getDepartmentForwardRestrictions.ts @@ -1,10 +1,10 @@ -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; import { callbacks } from '../../../../lib/callbacks'; import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'livechat:getDepartmentForwardRestrictions'(departmentId: string): unknown; diff --git a/apps/meteor/app/livechat/server/methods/getFirstRoomMessage.ts b/apps/meteor/app/livechat/server/methods/getFirstRoomMessage.ts index 197898e8d2b2..d8accf7f84f5 100644 --- a/apps/meteor/app/livechat/server/methods/getFirstRoomMessage.ts +++ b/apps/meteor/app/livechat/server/methods/getFirstRoomMessage.ts @@ -1,12 +1,12 @@ +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { LivechatRooms, Messages } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'livechat:getFirstRoomMessage'(params: { rid: string }): unknown; diff --git a/apps/meteor/app/livechat/server/methods/getNextAgent.ts b/apps/meteor/app/livechat/server/methods/getNextAgent.ts index 53b8441cad2e..179f1f95dedf 100644 --- a/apps/meteor/app/livechat/server/methods/getNextAgent.ts +++ b/apps/meteor/app/livechat/server/methods/getNextAgent.ts @@ -1,6 +1,6 @@ import type { ILivechatAgent } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { LivechatRooms, Users } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; @@ -9,7 +9,7 @@ import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarn import { settings } from '../../../settings/server'; import { Livechat } from '../lib/LivechatTyped'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'livechat:getNextAgent'(params: { diff --git a/apps/meteor/app/livechat/server/methods/getRoutingConfig.ts b/apps/meteor/app/livechat/server/methods/getRoutingConfig.ts index 364853a74511..02b2840f41cc 100644 --- a/apps/meteor/app/livechat/server/methods/getRoutingConfig.ts +++ b/apps/meteor/app/livechat/server/methods/getRoutingConfig.ts @@ -1,10 +1,10 @@ import type { OmichannelRoutingConfig } from '@rocket.chat/core-typings'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; import { RoutingManager } from '../lib/RoutingManager'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'livechat:getRoutingConfig'(): OmichannelRoutingConfig | undefined; diff --git a/apps/meteor/app/livechat/server/methods/getTagsList.ts b/apps/meteor/app/livechat/server/methods/getTagsList.ts index e9e467d243c8..b3efe5d026a3 100644 --- a/apps/meteor/app/livechat/server/methods/getTagsList.ts +++ b/apps/meteor/app/livechat/server/methods/getTagsList.ts @@ -1,11 +1,11 @@ import type { ILivechatTag } from '@rocket.chat/core-typings'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; import { callbacks } from '../../../../lib/callbacks'; import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'livechat:getTagsList'(): ILivechatTag[]; diff --git a/apps/meteor/app/livechat/server/methods/loadHistory.ts b/apps/meteor/app/livechat/server/methods/loadHistory.ts index 373ede1a3610..1004f9dd604d 100644 --- a/apps/meteor/app/livechat/server/methods/loadHistory.ts +++ b/apps/meteor/app/livechat/server/methods/loadHistory.ts @@ -1,13 +1,13 @@ import type { IMessage } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { LivechatVisitors, LivechatRooms } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { check, Match } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; import { loadMessageHistory } from '../../../lib/server/functions/loadMessageHistory'; import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'livechat:loadHistory'(params: { token: string; rid: string; end?: Date; limit?: number; ls: Date }): diff --git a/apps/meteor/app/livechat/server/methods/loginByToken.ts b/apps/meteor/app/livechat/server/methods/loginByToken.ts index cae23e6d16f7..3b82413e038a 100644 --- a/apps/meteor/app/livechat/server/methods/loginByToken.ts +++ b/apps/meteor/app/livechat/server/methods/loginByToken.ts @@ -1,10 +1,10 @@ +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { LivechatVisitors } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'livechat:loginByToken'(token: string): { _id: string } | undefined; diff --git a/apps/meteor/app/livechat/server/methods/pageVisited.ts b/apps/meteor/app/livechat/server/methods/pageVisited.ts index c226a91de430..7c0864f27b74 100644 --- a/apps/meteor/app/livechat/server/methods/pageVisited.ts +++ b/apps/meteor/app/livechat/server/methods/pageVisited.ts @@ -1,10 +1,10 @@ -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger'; import { Livechat } from '../lib/LivechatTyped'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'livechat:pageVisited'(token: string, room: string, pageInfo: { title: string; location: { href: string }; change: string }): void; diff --git a/apps/meteor/app/livechat/server/methods/registerGuest.ts b/apps/meteor/app/livechat/server/methods/registerGuest.ts index 4a531d0c89e5..c6a119d91591 100644 --- a/apps/meteor/app/livechat/server/methods/registerGuest.ts +++ b/apps/meteor/app/livechat/server/methods/registerGuest.ts @@ -1,13 +1,13 @@ import type { ILivechatVisitor, IRoom } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { LivechatVisitors, Messages, LivechatRooms } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { callbacks } from '../../../../lib/callbacks'; import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger'; import { Livechat as LivechatTyped } from '../lib/LivechatTyped'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'livechat:registerGuest'({ diff --git a/apps/meteor/app/livechat/server/methods/removeAgent.ts b/apps/meteor/app/livechat/server/methods/removeAgent.ts index 643ae696ada0..ebb57383784f 100644 --- a/apps/meteor/app/livechat/server/methods/removeAgent.ts +++ b/apps/meteor/app/livechat/server/methods/removeAgent.ts @@ -1,11 +1,11 @@ -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger'; import { Livechat } from '../lib/LivechatTyped'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'livechat:removeAgent'(username: string): boolean; diff --git a/apps/meteor/app/livechat/server/methods/removeAllClosedRooms.ts b/apps/meteor/app/livechat/server/methods/removeAllClosedRooms.ts index 9be699ae05ed..ba3939bb8573 100644 --- a/apps/meteor/app/livechat/server/methods/removeAllClosedRooms.ts +++ b/apps/meteor/app/livechat/server/methods/removeAllClosedRooms.ts @@ -1,14 +1,14 @@ import type { IOmnichannelRoom } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Logger } from '@rocket.chat/logger'; import { LivechatRooms } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { callbacks } from '../../../../lib/callbacks'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; import { Livechat } from '../lib/LivechatTyped'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'livechat:removeAllClosedRooms'(departmentIds?: string[]): Promise; diff --git a/apps/meteor/app/livechat/server/methods/removeCustomField.ts b/apps/meteor/app/livechat/server/methods/removeCustomField.ts index 1d3e7c817738..ad02df582337 100644 --- a/apps/meteor/app/livechat/server/methods/removeCustomField.ts +++ b/apps/meteor/app/livechat/server/methods/removeCustomField.ts @@ -1,12 +1,12 @@ +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { LivechatCustomField } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; import type { DeleteResult } from 'mongodb'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'livechat:removeCustomField'(_id: string): DeleteResult; diff --git a/apps/meteor/app/livechat/server/methods/removeDepartment.ts b/apps/meteor/app/livechat/server/methods/removeDepartment.ts index 3c46f3a424d6..6e4b11c836f6 100644 --- a/apps/meteor/app/livechat/server/methods/removeDepartment.ts +++ b/apps/meteor/app/livechat/server/methods/removeDepartment.ts @@ -1,4 +1,4 @@ -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; import type { DeleteResult } from 'mongodb'; @@ -7,7 +7,7 @@ import { hasPermissionAsync } from '../../../authorization/server/functions/hasP import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger'; import { DepartmentHelper } from '../lib/Departments'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'livechat:removeDepartment'(_id: string): DeleteResult; diff --git a/apps/meteor/app/livechat/server/methods/removeManager.ts b/apps/meteor/app/livechat/server/methods/removeManager.ts index 4c003ff922bc..85a5f3076c8c 100644 --- a/apps/meteor/app/livechat/server/methods/removeManager.ts +++ b/apps/meteor/app/livechat/server/methods/removeManager.ts @@ -1,11 +1,11 @@ -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger'; import { Livechat } from '../lib/LivechatTyped'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'livechat:removeManager'(username: string): boolean; diff --git a/apps/meteor/app/livechat/server/methods/removeRoom.ts b/apps/meteor/app/livechat/server/methods/removeRoom.ts index db3fcf2c849f..751d51d4f019 100644 --- a/apps/meteor/app/livechat/server/methods/removeRoom.ts +++ b/apps/meteor/app/livechat/server/methods/removeRoom.ts @@ -1,12 +1,12 @@ import type { IRoom } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { LivechatRooms } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; import { Livechat } from '../lib/LivechatTyped'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'livechat:removeRoom'(rid: IRoom['_id']): void; diff --git a/apps/meteor/app/livechat/server/methods/removeTrigger.ts b/apps/meteor/app/livechat/server/methods/removeTrigger.ts index 69f3a4a2d80c..41d79d725176 100644 --- a/apps/meteor/app/livechat/server/methods/removeTrigger.ts +++ b/apps/meteor/app/livechat/server/methods/removeTrigger.ts @@ -1,12 +1,12 @@ +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { LivechatTrigger } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'livechat:removeTrigger'(triggerId: string): boolean; diff --git a/apps/meteor/app/livechat/server/methods/requestTranscript.ts b/apps/meteor/app/livechat/server/methods/requestTranscript.ts index 5abf6a3b72e3..80cb3a9625fe 100644 --- a/apps/meteor/app/livechat/server/methods/requestTranscript.ts +++ b/apps/meteor/app/livechat/server/methods/requestTranscript.ts @@ -1,5 +1,5 @@ +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Users } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; @@ -7,7 +7,7 @@ import { hasPermissionAsync } from '../../../authorization/server/functions/hasP import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger'; import { Livechat } from '../lib/LivechatTyped'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'livechat:requestTranscript'(rid: string, email: string, subject: string): Promise; diff --git a/apps/meteor/app/livechat/server/methods/returnAsInquiry.ts b/apps/meteor/app/livechat/server/methods/returnAsInquiry.ts index 38b58b9d2d42..bf76519a5afb 100644 --- a/apps/meteor/app/livechat/server/methods/returnAsInquiry.ts +++ b/apps/meteor/app/livechat/server/methods/returnAsInquiry.ts @@ -1,13 +1,13 @@ import { Omnichannel } from '@rocket.chat/core-services'; import type { ILivechatDepartment, IRoom } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { LivechatRooms } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; import { Livechat } from '../lib/LivechatTyped'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'livechat:returnAsInquiry'(rid: IRoom['_id'], departmentID?: ILivechatDepartment['_id']): boolean; diff --git a/apps/meteor/app/livechat/server/methods/saveAgentInfo.ts b/apps/meteor/app/livechat/server/methods/saveAgentInfo.ts index 90d9815d4cf1..fe542b67156e 100644 --- a/apps/meteor/app/livechat/server/methods/saveAgentInfo.ts +++ b/apps/meteor/app/livechat/server/methods/saveAgentInfo.ts @@ -1,12 +1,12 @@ +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Users } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; import { hasRoleAsync } from '../../../authorization/server/functions/hasRole'; import { Livechat } from '../lib/LivechatTyped'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'livechat:saveAgentInfo'(_id: string, agentData: Record, agentDepartments: string[]): unknown; diff --git a/apps/meteor/app/livechat/server/methods/saveAppearance.ts b/apps/meteor/app/livechat/server/methods/saveAppearance.ts index cac5d34264d2..619dae147708 100644 --- a/apps/meteor/app/livechat/server/methods/saveAppearance.ts +++ b/apps/meteor/app/livechat/server/methods/saveAppearance.ts @@ -1,12 +1,12 @@ +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Settings } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger'; import { notifyOnSettingChangedById } from '../../../lib/server/lib/notifyListener'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'livechat:saveAppearance'(settings: { _id: string; value: any }[]): Promise; diff --git a/apps/meteor/app/livechat/server/methods/saveBusinessHour.ts b/apps/meteor/app/livechat/server/methods/saveBusinessHour.ts index 2e3e64365649..9bf32697fae9 100644 --- a/apps/meteor/app/livechat/server/methods/saveBusinessHour.ts +++ b/apps/meteor/app/livechat/server/methods/saveBusinessHour.ts @@ -1,10 +1,10 @@ import type { ILivechatBusinessHour } from '@rocket.chat/core-typings'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; import { businessHourManager } from '../business-hour'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'livechat:saveBusinessHour'(businessHourData: ILivechatBusinessHour): void; diff --git a/apps/meteor/app/livechat/server/methods/saveCustomField.ts b/apps/meteor/app/livechat/server/methods/saveCustomField.ts index 8a0435560dd5..c83148ba8d29 100644 --- a/apps/meteor/app/livechat/server/methods/saveCustomField.ts +++ b/apps/meteor/app/livechat/server/methods/saveCustomField.ts @@ -1,12 +1,12 @@ import type { ILivechatCustomField } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { LivechatCustomField } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Match, check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'livechat:saveCustomField'( diff --git a/apps/meteor/app/livechat/server/methods/saveDepartment.ts b/apps/meteor/app/livechat/server/methods/saveDepartment.ts index 971c2189f9a7..b4833523ab3f 100644 --- a/apps/meteor/app/livechat/server/methods/saveDepartment.ts +++ b/apps/meteor/app/livechat/server/methods/saveDepartment.ts @@ -1,11 +1,11 @@ import type { ILivechatDepartment } from '@rocket.chat/core-typings'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; import { Livechat } from '../lib/LivechatTyped'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'livechat:saveDepartment': ( diff --git a/apps/meteor/app/livechat/server/methods/saveDepartmentAgents.ts b/apps/meteor/app/livechat/server/methods/saveDepartmentAgents.ts index 73a471869926..42ee521713c0 100644 --- a/apps/meteor/app/livechat/server/methods/saveDepartmentAgents.ts +++ b/apps/meteor/app/livechat/server/methods/saveDepartmentAgents.ts @@ -1,12 +1,12 @@ import type { ILivechatDepartmentAgents } from '@rocket.chat/core-typings'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger'; import { Livechat } from '../lib/LivechatTyped'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'livechat:saveDepartmentAgents'( diff --git a/apps/meteor/app/livechat/server/methods/saveInfo.ts b/apps/meteor/app/livechat/server/methods/saveInfo.ts index a057706fdc23..bb22c127effa 100644 --- a/apps/meteor/app/livechat/server/methods/saveInfo.ts +++ b/apps/meteor/app/livechat/server/methods/saveInfo.ts @@ -1,6 +1,6 @@ import { isOmnichannelRoom } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { LivechatRooms, Users } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Match, check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; @@ -9,7 +9,7 @@ import { hasPermissionAsync } from '../../../authorization/server/functions/hasP import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger'; import { Livechat as LivechatTyped } from '../lib/LivechatTyped'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'livechat:saveInfo'( diff --git a/apps/meteor/app/livechat/server/methods/saveIntegration.ts b/apps/meteor/app/livechat/server/methods/saveIntegration.ts index de7461d08e10..0a4d82cfbcc1 100644 --- a/apps/meteor/app/livechat/server/methods/saveIntegration.ts +++ b/apps/meteor/app/livechat/server/methods/saveIntegration.ts @@ -1,5 +1,5 @@ +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Settings } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { trim } from '../../../../lib/utils/stringUtils'; @@ -7,7 +7,7 @@ import { hasPermissionAsync } from '../../../authorization/server/functions/hasP import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger'; import { notifyOnSettingChangedById } from '../../../lib/server/lib/notifyListener'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'livechat:saveIntegration'(values: Record): void; diff --git a/apps/meteor/app/livechat/server/methods/saveSurveyFeedback.ts b/apps/meteor/app/livechat/server/methods/saveSurveyFeedback.ts index 48dea8175ea8..36fc3f775b9f 100644 --- a/apps/meteor/app/livechat/server/methods/saveSurveyFeedback.ts +++ b/apps/meteor/app/livechat/server/methods/saveSurveyFeedback.ts @@ -1,5 +1,5 @@ +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { LivechatRooms, LivechatVisitors } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Match, check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; import type { UpdateResult } from 'mongodb'; @@ -7,7 +7,7 @@ import _ from 'underscore'; import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'livechat:saveSurveyFeedback'( diff --git a/apps/meteor/app/livechat/server/methods/saveTrigger.ts b/apps/meteor/app/livechat/server/methods/saveTrigger.ts index 37f78d081203..850dead9a589 100644 --- a/apps/meteor/app/livechat/server/methods/saveTrigger.ts +++ b/apps/meteor/app/livechat/server/methods/saveTrigger.ts @@ -1,13 +1,13 @@ import type { ILivechatTrigger } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { LivechatTrigger } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Match, check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'livechat:saveTrigger'(trigger: ILivechatTrigger): boolean; diff --git a/apps/meteor/app/livechat/server/methods/searchAgent.ts b/apps/meteor/app/livechat/server/methods/searchAgent.ts index 2a69679f2a07..932eb51e89d6 100644 --- a/apps/meteor/app/livechat/server/methods/searchAgent.ts +++ b/apps/meteor/app/livechat/server/methods/searchAgent.ts @@ -1,12 +1,12 @@ import type { IUser } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Users } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'livechat:searchAgent'(username: string): { _id: string; username?: string } | undefined; diff --git a/apps/meteor/app/livechat/server/methods/sendFileLivechatMessage.ts b/apps/meteor/app/livechat/server/methods/sendFileLivechatMessage.ts index 15577abd76e3..0268207b2f6c 100644 --- a/apps/meteor/app/livechat/server/methods/sendFileLivechatMessage.ts +++ b/apps/meteor/app/livechat/server/methods/sendFileLivechatMessage.ts @@ -5,9 +5,9 @@ import type { VideoAttachmentProps, IUpload, } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { LivechatVisitors, LivechatRooms } from '@rocket.chat/models'; import { Random } from '@rocket.chat/random'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Match, check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; @@ -21,7 +21,7 @@ interface ISendFileLivechatMessage { msgData?: { avatar?: string; emoji?: string; alias?: string; groupable?: boolean; msg?: string }; } -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { sendFileLivechatMessage( diff --git a/apps/meteor/app/livechat/server/methods/sendMessageLivechat.ts b/apps/meteor/app/livechat/server/methods/sendMessageLivechat.ts index ad16dea23e4f..6fac80397906 100644 --- a/apps/meteor/app/livechat/server/methods/sendMessageLivechat.ts +++ b/apps/meteor/app/livechat/server/methods/sendMessageLivechat.ts @@ -1,6 +1,6 @@ import { OmnichannelSourceType } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { LivechatVisitors } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Match, check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; @@ -18,7 +18,7 @@ interface ISendMessageLivechat { agent?: ILivechatMessageAgent; } -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { sendMessageLivechat(message: ILivechatMessage, agent: ILivechatMessageAgent): boolean; diff --git a/apps/meteor/app/livechat/server/methods/sendOfflineMessage.ts b/apps/meteor/app/livechat/server/methods/sendOfflineMessage.ts index c3b5537f31be..b620aa434100 100644 --- a/apps/meteor/app/livechat/server/methods/sendOfflineMessage.ts +++ b/apps/meteor/app/livechat/server/methods/sendOfflineMessage.ts @@ -1,4 +1,4 @@ -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { check } from 'meteor/check'; import { DDPRateLimiter } from 'meteor/ddp-rate-limiter'; import { Meteor } from 'meteor/meteor'; @@ -6,7 +6,7 @@ import { Meteor } from 'meteor/meteor'; import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger'; import { Livechat } from '../lib/LivechatTyped'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'livechat:sendOfflineMessage'(data: { name: string; email: string; message: string }): Promise; diff --git a/apps/meteor/app/livechat/server/methods/sendTranscript.ts b/apps/meteor/app/livechat/server/methods/sendTranscript.ts index 366a73c8bb0a..4891f579926a 100644 --- a/apps/meteor/app/livechat/server/methods/sendTranscript.ts +++ b/apps/meteor/app/livechat/server/methods/sendTranscript.ts @@ -1,6 +1,6 @@ import { Omnichannel } from '@rocket.chat/core-services'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { LivechatRooms, Users } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; @@ -8,7 +8,7 @@ import { hasPermissionAsync } from '../../../authorization/server/functions/hasP import { RateLimiter } from '../../../lib/server'; import { Livechat } from '../lib/LivechatTyped'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'livechat:sendTranscript'(token: string, rid: string, email: string, subject: string): boolean; diff --git a/apps/meteor/app/livechat/server/methods/setCustomField.ts b/apps/meteor/app/livechat/server/methods/setCustomField.ts index fb07c2b29a4e..6d3a2384cdd7 100644 --- a/apps/meteor/app/livechat/server/methods/setCustomField.ts +++ b/apps/meteor/app/livechat/server/methods/setCustomField.ts @@ -1,11 +1,11 @@ +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { LivechatVisitors, LivechatCustomField, LivechatRooms } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import type { UpdateResult, Document } from 'mongodb'; import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'livechat:setCustomField'(token: string, key: string, value: string, overwrite?: boolean): Promise; diff --git a/apps/meteor/app/livechat/server/methods/setDepartmentForVisitor.ts b/apps/meteor/app/livechat/server/methods/setDepartmentForVisitor.ts index a14933ed8d47..385f2d989015 100644 --- a/apps/meteor/app/livechat/server/methods/setDepartmentForVisitor.ts +++ b/apps/meteor/app/livechat/server/methods/setDepartmentForVisitor.ts @@ -1,5 +1,5 @@ +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { LivechatVisitors, Messages, LivechatRooms } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; @@ -7,7 +7,7 @@ import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarn import { normalizeTransferredByData } from '../lib/Helper'; import { Livechat } from '../lib/LivechatTyped'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'livechat:setDepartmentForVisitor'({ diff --git a/apps/meteor/app/livechat/server/methods/setUpConnection.ts b/apps/meteor/app/livechat/server/methods/setUpConnection.ts index 788b2384c4d3..21ce09acaa22 100644 --- a/apps/meteor/app/livechat/server/methods/setUpConnection.ts +++ b/apps/meteor/app/livechat/server/methods/setUpConnection.ts @@ -1,11 +1,11 @@ import { UserStatus } from '@rocket.chat/core-typings'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; import { Livechat } from '../lib/LivechatTyped'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'livechat:setUpConnection'(data: { token: string }): void; diff --git a/apps/meteor/app/livechat/server/methods/takeInquiry.ts b/apps/meteor/app/livechat/server/methods/takeInquiry.ts index 30a5dabb5717..733cbd995208 100644 --- a/apps/meteor/app/livechat/server/methods/takeInquiry.ts +++ b/apps/meteor/app/livechat/server/methods/takeInquiry.ts @@ -1,13 +1,13 @@ import { Omnichannel } from '@rocket.chat/core-services'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { LivechatInquiry, LivechatRooms, Users } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; import { settings } from '../../../settings/server'; import { RoutingManager } from '../lib/RoutingManager'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'livechat:takeInquiry'( diff --git a/apps/meteor/app/livechat/server/methods/transfer.ts b/apps/meteor/app/livechat/server/methods/transfer.ts index 64a32c24638c..e0516fa27981 100644 --- a/apps/meteor/app/livechat/server/methods/transfer.ts +++ b/apps/meteor/app/livechat/server/methods/transfer.ts @@ -1,7 +1,7 @@ import { Omnichannel } from '@rocket.chat/core-services'; import type { IUser } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { LivechatVisitors, LivechatRooms, Subscriptions, Users } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Match, check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; @@ -10,7 +10,7 @@ import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarn import { normalizeTransferredByData } from '../lib/Helper'; import { Livechat } from '../lib/LivechatTyped'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'livechat:transfer'(transferData: { diff --git a/apps/meteor/app/livechat/server/methods/webhookTest.ts b/apps/meteor/app/livechat/server/methods/webhookTest.ts index 12a4711d75b4..68800e1a0616 100644 --- a/apps/meteor/app/livechat/server/methods/webhookTest.ts +++ b/apps/meteor/app/livechat/server/methods/webhookTest.ts @@ -1,5 +1,5 @@ +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { serverFetch as fetch } from '@rocket.chat/server-fetch'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { SystemLogger } from '../../../../server/lib/logger/system'; @@ -14,7 +14,7 @@ const postCatchError = async function (url: string, options?: Record; diff --git a/apps/meteor/app/livechat/server/startup.ts b/apps/meteor/app/livechat/server/startup.ts index b61c85c4001e..32cf01d2e640 100644 --- a/apps/meteor/app/livechat/server/startup.ts +++ b/apps/meteor/app/livechat/server/startup.ts @@ -87,7 +87,7 @@ Meteor.startup(async () => { }); // Remove when accounts.onLogout is async - Accounts.onLogout(({ user }: { user: IUser }) => { + Accounts.onLogout(({ user }: { user?: IUser }) => { if (!user?.roles?.includes('livechat-agent') || user?.roles?.includes('bot')) { return; } diff --git a/apps/meteor/app/mail-messages/server/methods/sendMail.ts b/apps/meteor/app/mail-messages/server/methods/sendMail.ts index 158d271d5379..cc6469544df8 100644 --- a/apps/meteor/app/mail-messages/server/methods/sendMail.ts +++ b/apps/meteor/app/mail-messages/server/methods/sendMail.ts @@ -1,11 +1,11 @@ -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger'; import { Mailer } from '../lib/Mailer'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'Mailer.sendMail'(from: string, subject: string, body: string, dryrun?: boolean, query?: string): any; diff --git a/apps/meteor/app/mail-messages/server/methods/unsubscribe.ts b/apps/meteor/app/mail-messages/server/methods/unsubscribe.ts index 24243cc98c2d..e52677b5ee1a 100644 --- a/apps/meteor/app/mail-messages/server/methods/unsubscribe.ts +++ b/apps/meteor/app/mail-messages/server/methods/unsubscribe.ts @@ -1,11 +1,11 @@ -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { DDPRateLimiter } from 'meteor/ddp-rate-limiter'; import { Meteor } from 'meteor/meteor'; import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger'; import { Mailer } from '../lib/Mailer'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'Mailer:unsubscribe'(_id: string, createdAt: string): Promise; diff --git a/apps/meteor/app/mentions/server/methods/getUserMentionsByChannel.ts b/apps/meteor/app/mentions/server/methods/getUserMentionsByChannel.ts index 948187d089ae..6d9a16539704 100644 --- a/apps/meteor/app/mentions/server/methods/getUserMentionsByChannel.ts +++ b/apps/meteor/app/mentions/server/methods/getUserMentionsByChannel.ts @@ -1,12 +1,12 @@ import type { IMessage } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Messages, Users, Rooms } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; import { canAccessRoomAsync } from '../../../authorization/server'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { getUserMentionsByChannel(params: { roomId: string; options: { limit: number; sort: { ts: -1 | 1 } } }): IMessage[]; diff --git a/apps/meteor/app/message-mark-as-unread/server/unreadMessages.ts b/apps/meteor/app/message-mark-as-unread/server/unreadMessages.ts index 2ba0224a0c70..6ef1f5567a20 100644 --- a/apps/meteor/app/message-mark-as-unread/server/unreadMessages.ts +++ b/apps/meteor/app/message-mark-as-unread/server/unreadMessages.ts @@ -1,11 +1,11 @@ import type { IMessage, IRoom } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Messages, Subscriptions } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import logger from './logger'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { unreadMessages(firstUnreadMessage?: IMessage, room?: IRoom['_id']): void; diff --git a/apps/meteor/app/message-pin/server/pinMessage.ts b/apps/meteor/app/message-pin/server/pinMessage.ts index b0eab3f929d6..f691a775cb6a 100644 --- a/apps/meteor/app/message-pin/server/pinMessage.ts +++ b/apps/meteor/app/message-pin/server/pinMessage.ts @@ -2,17 +2,16 @@ import { Apps, AppEvents } from '@rocket.chat/apps'; import { Message } from '@rocket.chat/core-services'; import { isQuoteAttachment, isRegisterUser } from '@rocket.chat/core-typings'; import type { IMessage, MessageAttachment, MessageQuoteAttachment } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Messages, Rooms, Subscriptions, Users, ReadReceipts } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; import { isTruthy } from '../../../lib/isTruthy'; -import { broadcastMessageFromData } from '../../../server/modules/watchers/lib/messages'; import { canAccessRoomAsync, roomAccessAttributes } from '../../authorization/server'; import { hasPermissionAsync } from '../../authorization/server/functions/hasPermission'; import { isTheLastMessage } from '../../lib/server/functions/isTheLastMessage'; -import { notifyOnRoomChangedById } from '../../lib/server/lib/notifyListener'; +import { notifyOnRoomChangedById, notifyOnMessageChange } from '../../lib/server/lib/notifyListener'; import { settings } from '../../settings/server'; import { getUserAvatarURL } from '../../utils/server/getUserAvatarURL'; @@ -36,7 +35,7 @@ const recursiveRemove = (msg: MessageAttachment, deep = 1) => { const shouldAdd = (attachments: MessageAttachment[], attachment: MessageQuoteAttachment) => !attachments.some((_attachment) => isQuoteAttachment(_attachment) && _attachment.message_link === attachment.message_link); -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { pinMessage(message: IMessage, pinnedAt?: Date): IMessage | null; @@ -227,7 +226,7 @@ Meteor.methods({ if (settings.get('Message_Read_Receipt_Store_Users')) { await ReadReceipts.setPinnedByMessageId(originalMessage._id, originalMessage.pinned); } - void broadcastMessageFromData({ + void notifyOnMessageChange({ id: message._id, }); diff --git a/apps/meteor/app/message-star/server/starMessage.ts b/apps/meteor/app/message-star/server/starMessage.ts index 4529efb63f6f..36c67c1f4020 100644 --- a/apps/meteor/app/message-star/server/starMessage.ts +++ b/apps/meteor/app/message-star/server/starMessage.ts @@ -1,16 +1,15 @@ import { Apps, AppEvents } from '@rocket.chat/apps'; import type { IMessage } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Messages, Subscriptions, Rooms } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; -import { broadcastMessageFromData } from '../../../server/modules/watchers/lib/messages'; import { canAccessRoomAsync, roomAccessAttributes } from '../../authorization/server'; import { isTheLastMessage } from '../../lib/server/functions/isTheLastMessage'; -import { notifyOnRoomChangedById } from '../../lib/server/lib/notifyListener'; +import { notifyOnRoomChangedById, notifyOnMessageChange } from '../../lib/server/lib/notifyListener'; import { settings } from '../../settings/server'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { starMessage(message: Omit & { starred: boolean }): boolean; @@ -63,7 +62,7 @@ Meteor.methods({ await Messages.updateUserStarById(message._id, uid, message.starred); - void broadcastMessageFromData({ + void notifyOnMessageChange({ id: message._id, }); diff --git a/apps/meteor/app/meteor-accounts-saml/server/methods/addSamlService.ts b/apps/meteor/app/meteor-accounts-saml/server/methods/addSamlService.ts index f952ce3b3fe3..0b6b5a6c8f6e 100644 --- a/apps/meteor/app/meteor-accounts-saml/server/methods/addSamlService.ts +++ b/apps/meteor/app/meteor-accounts-saml/server/methods/addSamlService.ts @@ -1,9 +1,9 @@ -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; import { addSamlService } from '../lib/settings'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { addSamlService(name: string): void; diff --git a/apps/meteor/app/meteor-accounts-saml/server/methods/samlLogout.ts b/apps/meteor/app/meteor-accounts-saml/server/methods/samlLogout.ts index 956426082d40..a7f9e87a93de 100644 --- a/apps/meteor/app/meteor-accounts-saml/server/methods/samlLogout.ts +++ b/apps/meteor/app/meteor-accounts-saml/server/methods/samlLogout.ts @@ -1,5 +1,5 @@ +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Users } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import type { IServiceProviderOptions } from '../definition/IServiceProviderOptions'; @@ -25,7 +25,7 @@ function getSamlServiceProviderOptions(provider: string): IServiceProviderOption return providers.filter(samlProvider)[0]; } -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { samlLogout(provider: string): string | undefined; diff --git a/apps/meteor/app/models/client/models/Users.ts b/apps/meteor/app/models/client/models/Users.ts index 089486f3a20c..26d333cc8bb1 100644 --- a/apps/meteor/app/models/client/models/Users.ts +++ b/apps/meteor/app/models/client/models/Users.ts @@ -30,5 +30,13 @@ class UsersCollection extends Mongo.Collection { } } +Object.assign(Meteor.users, { + _connection: undefined, + findOneById: UsersCollection.prototype.findOneById, + isUserInRole: UsersCollection.prototype.isUserInRole, + findUsersInRoles: UsersCollection.prototype.findUsersInRoles, + remove: UsersCollection.prototype.remove, +}); + /** @deprecated */ -export const Users = new UsersCollection(); +export const Users = Meteor.users as UsersCollection; diff --git a/apps/meteor/app/notifications/server/lib/Notifications.ts b/apps/meteor/app/notifications/server/lib/Notifications.ts index ed4985777414..3ddb611d76bd 100644 --- a/apps/meteor/app/notifications/server/lib/Notifications.ts +++ b/apps/meteor/app/notifications/server/lib/Notifications.ts @@ -1,5 +1,5 @@ import { api } from '@rocket.chat/core-services'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { DDPCommon } from 'meteor/ddp-common'; import { Meteor } from 'meteor/meteor'; diff --git a/apps/meteor/app/notifications/server/lib/Presence.ts b/apps/meteor/app/notifications/server/lib/Presence.ts index 9955b687701f..17f35a9d39ff 100644 --- a/apps/meteor/app/notifications/server/lib/Presence.ts +++ b/apps/meteor/app/notifications/server/lib/Presence.ts @@ -1,6 +1,6 @@ import type { IUser } from '@rocket.chat/core-typings'; +import type { StreamerEvents } from '@rocket.chat/ddp-client'; import { Emitter } from '@rocket.chat/emitter'; -import type { StreamerEvents } from '@rocket.chat/ui-contexts'; import type { IPublication, IStreamerConstructor, Connection, IStreamer } from 'meteor/rocketchat:streamer'; type UserPresenceStreamProps = { diff --git a/apps/meteor/app/oauth2-server-config/server/admin/methods/addOAuthApp.ts b/apps/meteor/app/oauth2-server-config/server/admin/methods/addOAuthApp.ts index 4556a5be7d9f..3f41b1b01bea 100644 --- a/apps/meteor/app/oauth2-server-config/server/admin/methods/addOAuthApp.ts +++ b/apps/meteor/app/oauth2-server-config/server/admin/methods/addOAuthApp.ts @@ -1,12 +1,12 @@ import type { IOAuthApps } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import type { OauthAppsAddParams } from '@rocket.chat/rest-typings'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { methodDeprecationLogger } from '../../../../lib/server/lib/deprecationWarningLogger'; import { addOAuthApp } from '../functions/addOAuthApp'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { addOAuthApp(application: OauthAppsAddParams): IOAuthApps; diff --git a/apps/meteor/app/oauth2-server-config/server/admin/methods/deleteOAuthApp.ts b/apps/meteor/app/oauth2-server-config/server/admin/methods/deleteOAuthApp.ts index 0209f9d453b5..9c5cbf6fd9ae 100644 --- a/apps/meteor/app/oauth2-server-config/server/admin/methods/deleteOAuthApp.ts +++ b/apps/meteor/app/oauth2-server-config/server/admin/methods/deleteOAuthApp.ts @@ -1,11 +1,11 @@ import type { IOAuthApps } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { OAuthAccessTokens, OAuthApps, OAuthAuthCodes } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { hasPermissionAsync } from '../../../../authorization/server/functions/hasPermission'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { deleteOAuthApp(applicationId: IOAuthApps['_id']): boolean; diff --git a/apps/meteor/app/oauth2-server-config/server/admin/methods/updateOAuthApp.ts b/apps/meteor/app/oauth2-server-config/server/admin/methods/updateOAuthApp.ts index 525d0fa2d124..f2daca1885c9 100644 --- a/apps/meteor/app/oauth2-server-config/server/admin/methods/updateOAuthApp.ts +++ b/apps/meteor/app/oauth2-server-config/server/admin/methods/updateOAuthApp.ts @@ -1,12 +1,12 @@ import type { IOAuthApps } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { OAuthApps, Users } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { hasPermissionAsync } from '../../../../authorization/server/functions/hasPermission'; import { parseUriList } from '../functions/parseUriList'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { updateOAuthApp( diff --git a/apps/meteor/app/otr/server/methods/deleteOldOTRMessages.ts b/apps/meteor/app/otr/server/methods/deleteOldOTRMessages.ts index a994b19dd1a4..1b57c65b4bb7 100644 --- a/apps/meteor/app/otr/server/methods/deleteOldOTRMessages.ts +++ b/apps/meteor/app/otr/server/methods/deleteOldOTRMessages.ts @@ -1,9 +1,9 @@ import type { IRoom } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Messages, Subscriptions, ReadReceipts } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { deleteOldOTRMessages(roomId: IRoom['_id']): Promise; diff --git a/apps/meteor/app/otr/server/methods/sendSystemMessages.ts b/apps/meteor/app/otr/server/methods/sendSystemMessages.ts index a2abf0938b9e..13abbd7511af 100644 --- a/apps/meteor/app/otr/server/methods/sendSystemMessages.ts +++ b/apps/meteor/app/otr/server/methods/sendSystemMessages.ts @@ -1,7 +1,7 @@ -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { sendSystemMessages(rid: string, user: string | undefined, id: string): void; diff --git a/apps/meteor/app/otr/server/methods/updateOTRAck.ts b/apps/meteor/app/otr/server/methods/updateOTRAck.ts index a5a502ddf1a2..4fbd182e9d27 100644 --- a/apps/meteor/app/otr/server/methods/updateOTRAck.ts +++ b/apps/meteor/app/otr/server/methods/updateOTRAck.ts @@ -1,9 +1,9 @@ import { api } from '@rocket.chat/core-services'; import type { IOTRMessage } from '@rocket.chat/core-typings'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { updateOTRAck({ message, ack }: { message: IOTRMessage; ack: string }): void; diff --git a/apps/meteor/app/push-notifications/server/methods/saveNotificationSettings.ts b/apps/meteor/app/push-notifications/server/methods/saveNotificationSettings.ts index a4376c709275..a86ded6f24e5 100644 --- a/apps/meteor/app/push-notifications/server/methods/saveNotificationSettings.ts +++ b/apps/meteor/app/push-notifications/server/methods/saveNotificationSettings.ts @@ -1,6 +1,6 @@ import type { ISubscription } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Subscriptions } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; @@ -9,7 +9,7 @@ import { getUserNotificationPreference } from '../../../utils/server/getUserNoti const saveAudioNotificationValue = (subId: ISubscription['_id'], value: string) => value === 'default' ? Subscriptions.clearAudioNotificationValueById(subId) : Subscriptions.updateAudioNotificationValueById(subId, value); -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { saveNotificationSettings( diff --git a/apps/meteor/app/push/server/methods.ts b/apps/meteor/app/push/server/methods.ts index 364a16cbdb5e..1f1e261eccae 100644 --- a/apps/meteor/app/push/server/methods.ts +++ b/apps/meteor/app/push/server/methods.ts @@ -1,7 +1,7 @@ import type { IAppsTokens } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { AppsTokens } from '@rocket.chat/models'; import { Random } from '@rocket.chat/random'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Accounts } from 'meteor/accounts-base'; import { Match, check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; @@ -9,7 +9,7 @@ import { Meteor } from 'meteor/meteor'; import { logger } from './logger'; import { _matchToken } from './push'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'raix:push-update'(options: { diff --git a/apps/meteor/app/reactions/client/methods/setReaction.ts b/apps/meteor/app/reactions/client/methods/setReaction.ts index a38e6c156790..ed15cda9ab8e 100644 --- a/apps/meteor/app/reactions/client/methods/setReaction.ts +++ b/apps/meteor/app/reactions/client/methods/setReaction.ts @@ -1,5 +1,5 @@ import type { IMessage, IRoom } from '@rocket.chat/core-typings'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; import { roomCoordinator } from '../../../../client/lib/rooms/roomCoordinator'; diff --git a/apps/meteor/app/reactions/server/setReaction.ts b/apps/meteor/app/reactions/server/setReaction.ts index 896e5041bd61..e35103e9d333 100644 --- a/apps/meteor/app/reactions/server/setReaction.ts +++ b/apps/meteor/app/reactions/server/setReaction.ts @@ -1,19 +1,18 @@ import { Apps, AppEvents } from '@rocket.chat/apps'; import { api } from '@rocket.chat/core-services'; import type { IMessage, IRoom, IUser } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Messages, EmojiCustom, Rooms, Users } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import _ from 'underscore'; import { callbacks } from '../../../lib/callbacks'; import { i18n } from '../../../server/lib/i18n'; -import { broadcastMessageFromData } from '../../../server/modules/watchers/lib/messages'; import { canAccessRoomAsync } from '../../authorization/server'; import { hasPermissionAsync } from '../../authorization/server/functions/hasPermission'; import { emoji } from '../../emoji/server'; import { isTheLastMessage } from '../../lib/server/functions/isTheLastMessage'; -import { notifyOnRoomChangedById } from '../../lib/server/lib/notifyListener'; +import { notifyOnRoomChangedById, notifyOnMessageChange } from '../../lib/server/lib/notifyListener'; const removeUserReaction = (message: IMessage, reaction: string, username: string) => { if (!message.reactions) { @@ -111,7 +110,7 @@ async function setReaction(room: IRoom, user: IUser, message: IMessage, reaction await Apps.self?.triggerEvent(AppEvents.IPostMessageReacted, message, user, reaction, isReacted); - void broadcastMessageFromData({ + void notifyOnMessageChange({ id: message._id, }); } @@ -140,7 +139,7 @@ export async function executeSetReaction(userId: string, reaction: string, messa return setReaction(room, user, message, reaction, shouldReact); } -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { setReaction(reaction: string, messageId: IMessage['_id'], shouldReact?: boolean): boolean | undefined; diff --git a/apps/meteor/app/search/server/methods.ts b/apps/meteor/app/search/server/methods.ts index 686b5b429e96..cdb3b4180f7a 100644 --- a/apps/meteor/app/search/server/methods.ts +++ b/apps/meteor/app/search/server/methods.ts @@ -1,12 +1,12 @@ import type { IMessageSearchProvider, IMessageSearchSuggestion, IRoom, IUser } from '@rocket.chat/core-typings'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; import { SearchLogger } from './logger/logger'; import type { IRawSearchResult, ISearchResult } from './model/ISearchResult'; import { searchProviderService, validationService } from './service'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'rocketchatSearch.getProvider'(): IMessageSearchProvider | undefined; diff --git a/apps/meteor/app/settings/server/SettingsRegistry.ts b/apps/meteor/app/settings/server/SettingsRegistry.ts index 443e38ce5d63..e86a391ad8fa 100644 --- a/apps/meteor/app/settings/server/SettingsRegistry.ts +++ b/apps/meteor/app/settings/server/SettingsRegistry.ts @@ -73,7 +73,7 @@ const compareSettingsIgnoringKeys = .filter((key) => !keys.includes(key as keyof ISetting)) .every((key) => isEqual(a[key as keyof ISetting], b[key as keyof ISetting])); -const compareSettings = compareSettingsIgnoringKeys([ +export const compareSettings = compareSettingsIgnoringKeys([ 'value', 'ts', 'createdAt', @@ -138,22 +138,17 @@ export class SettingsRegistry { const settingFromCodeOverwritten = overwriteSetting(settingFromCode); - const settingOverwrittenDefault = overrideSetting(settingFromCode); - const settingStored = this.store.getSetting(_id); - const settingStoredOverwritten = settingStored && overwriteSetting(settingStored); - const isOverwritten = settingFromCode !== settingFromCodeOverwritten || (settingStored && settingStored !== settingStoredOverwritten); - - const updatedSettingAfterApplyingOverwrite = isOverwritten ? settingFromCodeOverwritten : settingOverwrittenDefault; - try { validateSetting(settingFromCode._id, settingFromCode.type, settingFromCode.value); } catch (e) { IS_DEVELOPMENT && SystemLogger.error(`Invalid setting code ${_id}: ${(e as Error).message}`); } + const isOverwritten = settingFromCode !== settingFromCodeOverwritten || (settingStored && settingStored !== settingStoredOverwritten); + const { _id: _, ...settingProps } = settingFromCodeOverwritten; if (settingStored && !compareSettings(settingStored, settingFromCodeOverwritten)) { @@ -171,9 +166,7 @@ export class SettingsRegistry { })(); await this.saveUpdatedSetting(_id, updatedProps, removedKeys); - - this.store.set(updatedSettingAfterApplyingOverwrite); - + this.store.set(settingFromCodeOverwritten); return; } @@ -183,8 +176,7 @@ export class SettingsRegistry { const removedKeys = Object.keys(settingStored).filter((key) => !['_updatedAt'].includes(key) && !overwrittenKeys.includes(key)); await this.saveUpdatedSetting(_id, settingProps, removedKeys); - - this.store.set(updatedSettingAfterApplyingOverwrite); + this.store.set(settingFromCodeOverwritten); } return; } @@ -198,9 +190,13 @@ export class SettingsRegistry { return; } - await this.model.insertOne(updatedSettingAfterApplyingOverwrite); // no need to emit unless we remove the oplog + const settingOverwrittenDefault = overrideSetting(settingFromCode); + + const setting = isOverwritten ? settingFromCodeOverwritten : settingOverwrittenDefault; + + await this.model.insertOne(setting); // no need to emit unless we remove the oplog - this.store.set(updatedSettingAfterApplyingOverwrite); + this.store.set(setting); } /* diff --git a/apps/meteor/app/settings/server/functions/settings.mocks.ts b/apps/meteor/app/settings/server/functions/settings.mocks.ts index 9cd409ba0b83..fb31c3021b1b 100644 --- a/apps/meteor/app/settings/server/functions/settings.mocks.ts +++ b/apps/meteor/app/settings/server/functions/settings.mocks.ts @@ -9,6 +9,12 @@ type Dictionary = { class SettingsClass { settings: ICachedSettings; + private delay = 0; + + setDelay(delay: number): void { + this.delay = delay; + } + find(): any[] { return []; } @@ -65,22 +71,41 @@ class SettingsClass { throw new Error('Invalid upsert'); } - // console.log(query, data); - this.data.set(query._id, data); - - // Can't import before the mock command on end of this file! - // eslint-disable-next-line @typescript-eslint/no-var-requires - this.settings.set(data); + if (this.delay) { + setTimeout(() => { + // console.log(query, data); + this.data.set(query._id, data); + + // Can't import before the mock command on end of this file! + // eslint-disable-next-line @typescript-eslint/no-var-requires + this.settings.set(data); + }, this.delay); + } else { + this.data.set(query._id, data); + // Can't import before the mock command on end of this file! + // eslint-disable-next-line @typescript-eslint/no-var-requires + this.settings.set(data); + } this.upsertCalls++; } + findOneAndUpdate({ _id }: { _id: string }, value: any, options?: any) { + this.updateOne({ _id }, value, options); + return { value: this.findOne({ _id }) }; + } + updateValueById(id: string, value: any): void { this.data.set(id, { ...this.data.get(id), value }); - // Can't import before the mock command on end of this file! // eslint-disable-next-line @typescript-eslint/no-var-requires - this.settings.set(this.data.get(id) as ISetting); + if (this.delay) { + setTimeout(() => { + this.settings.set(this.data.get(id) as ISetting); + }, this.delay); + } else { + this.settings.set(this.data.get(id) as ISetting); + } } } diff --git a/apps/meteor/app/slackbridge/server/SlackAdapter.js b/apps/meteor/app/slackbridge/server/SlackAdapter.js index 78d48deb4993..0263d5369a4c 100644 --- a/apps/meteor/app/slackbridge/server/SlackAdapter.js +++ b/apps/meteor/app/slackbridge/server/SlackAdapter.js @@ -1341,7 +1341,7 @@ export default class SlackAdapter { const user = (await this.rocket.findUser(member)) || (await this.rocket.addUser(member)); if (user) { slackLogger.debug('Adding user to room', user.username, rid); - await addUserToRoom(rid, user, null, true); + await addUserToRoom(rid, user, null, { skipSystemMessage: true }); } } } diff --git a/apps/meteor/app/slackbridge/server/removeChannelLinks.ts b/apps/meteor/app/slackbridge/server/removeChannelLinks.ts index 1a4e6f6a0096..2c89e71f9635 100644 --- a/apps/meteor/app/slackbridge/server/removeChannelLinks.ts +++ b/apps/meteor/app/slackbridge/server/removeChannelLinks.ts @@ -1,11 +1,11 @@ +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Rooms } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { hasPermissionAsync } from '../../authorization/server/functions/hasPermission'; import { settings } from '../../settings/server'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { removeSlackBridgeChannelLinks(): { message: string; params: unknown[] }; diff --git a/apps/meteor/app/statistics/server/methods/getStatistics.ts b/apps/meteor/app/statistics/server/methods/getStatistics.ts index c7eb79b5b985..a804ef83584e 100644 --- a/apps/meteor/app/statistics/server/methods/getStatistics.ts +++ b/apps/meteor/app/statistics/server/methods/getStatistics.ts @@ -1,10 +1,10 @@ import type { IStats } from '@rocket.chat/core-typings'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; import { getLastStatistics } from '../functions/getLastStatistics'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { getStatistics(refresh?: boolean): IStats; diff --git a/apps/meteor/app/threads/server/hooks/aftersavemessage.ts b/apps/meteor/app/threads/server/hooks/aftersavemessage.ts index ab1fa182599b..179cb5ec12b7 100644 --- a/apps/meteor/app/threads/server/hooks/aftersavemessage.ts +++ b/apps/meteor/app/threads/server/hooks/aftersavemessage.ts @@ -4,7 +4,7 @@ import { Messages } from '@rocket.chat/models'; import { Meteor } from 'meteor/meteor'; import { callbacks } from '../../../../lib/callbacks'; -import { broadcastMessageFromData } from '../../../../server/modules/watchers/lib/messages'; +import { notifyOnMessageChange } from '../../../lib/server/lib/notifyListener'; import { updateThreadUsersSubscriptions, getMentions } from '../../../lib/server/lib/notifyUsersOnMessage'; import { sendMessageNotifications } from '../../../lib/server/lib/sendNotificationsOnMessage'; import { settings } from '../../../settings/server'; @@ -62,7 +62,7 @@ export async function processThreads(message: IMessage, room: IRoom) { await notifyUsersOnReply(message, replies); await metaData(message, parentMessage, replies); await notification(message, room, replies); - void broadcastMessageFromData({ + void notifyOnMessageChange({ id: message.tmid, }); diff --git a/apps/meteor/app/threads/server/methods/followMessage.ts b/apps/meteor/app/threads/server/methods/followMessage.ts index 05650d0ad2ef..1790e0607a62 100644 --- a/apps/meteor/app/threads/server/methods/followMessage.ts +++ b/apps/meteor/app/threads/server/methods/followMessage.ts @@ -1,7 +1,7 @@ import { Apps, AppEvents } from '@rocket.chat/apps'; import type { IMessage } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Messages } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; @@ -10,7 +10,7 @@ import { RateLimiter } from '../../../lib/server'; import { settings } from '../../../settings/server'; import { follow } from '../functions'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { followMessage(message: { mid: IMessage['_id'] }): false | undefined; diff --git a/apps/meteor/app/threads/server/methods/getThreadMessages.ts b/apps/meteor/app/threads/server/methods/getThreadMessages.ts index d6c2d65ff4d4..8ae31130df1b 100644 --- a/apps/meteor/app/threads/server/methods/getThreadMessages.ts +++ b/apps/meteor/app/threads/server/methods/getThreadMessages.ts @@ -1,6 +1,6 @@ import type { IMessage } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Messages, Rooms } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { callbacks } from '../../../../lib/callbacks'; @@ -8,7 +8,7 @@ import { canAccessRoomAsync } from '../../../authorization/server'; import { settings } from '../../../settings/server'; import { readThread } from '../functions'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { getThreadMessages(params: { tmid: IMessage['_id']; limit?: number; skip?: number }): Promise; diff --git a/apps/meteor/app/threads/server/methods/getThreadsList.ts b/apps/meteor/app/threads/server/methods/getThreadsList.ts index 5a33dc16280b..c51449ff2d4d 100644 --- a/apps/meteor/app/threads/server/methods/getThreadsList.ts +++ b/apps/meteor/app/threads/server/methods/getThreadsList.ts @@ -1,6 +1,6 @@ import type { IMessage, IRoom } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Messages, Rooms } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { canAccessRoomAsync } from '../../../authorization/server'; @@ -8,7 +8,7 @@ import { settings } from '../../../settings/server'; const MAX_LIMIT = 100; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { getThreadsList(params: { rid: IRoom['_id']; limit?: number; skip?: number }): IMessage[]; diff --git a/apps/meteor/app/threads/server/methods/unfollowMessage.ts b/apps/meteor/app/threads/server/methods/unfollowMessage.ts index afc9206b038f..6371f40af6cb 100644 --- a/apps/meteor/app/threads/server/methods/unfollowMessage.ts +++ b/apps/meteor/app/threads/server/methods/unfollowMessage.ts @@ -1,7 +1,7 @@ import { Apps, AppEvents } from '@rocket.chat/apps'; import type { IMessage } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Messages } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; @@ -10,7 +10,7 @@ import { RateLimiter } from '../../../lib/server'; import { settings } from '../../../settings/server'; import { unfollow } from '../functions'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { unfollowMessage(message: { mid: IMessage['_id'] }): false | undefined; diff --git a/apps/meteor/app/ui-cached-collection/client/models/CachedCollection.ts b/apps/meteor/app/ui-cached-collection/client/models/CachedCollection.ts index 545e1e73342d..602a0eddb8ce 100644 --- a/apps/meteor/app/ui-cached-collection/client/models/CachedCollection.ts +++ b/apps/meteor/app/ui-cached-collection/client/models/CachedCollection.ts @@ -1,5 +1,5 @@ +import type { StreamNames } from '@rocket.chat/ddp-client'; import { Emitter } from '@rocket.chat/emitter'; -import type { StreamNames } from '@rocket.chat/ui-contexts'; import localforage from 'localforage'; import { Accounts } from 'meteor/accounts-base'; import { Meteor } from 'meteor/meteor'; diff --git a/apps/meteor/app/ui-cached-collection/client/models/CachedCollectionManager.ts b/apps/meteor/app/ui-cached-collection/client/models/CachedCollectionManager.ts index 845731e2450a..52d6661d7061 100644 --- a/apps/meteor/app/ui-cached-collection/client/models/CachedCollectionManager.ts +++ b/apps/meteor/app/ui-cached-collection/client/models/CachedCollectionManager.ts @@ -11,15 +11,12 @@ class CachedCollectionManager extends Emitter<{ reconnect: void; login: string | private _syncEnabled: boolean; - private logged: boolean; - private step: number; constructor() { super(); this.items = []; this._syncEnabled = false; - this.logged = false; const { _unstoreLoginToken } = Accounts; Accounts._unstoreLoginToken = (...args) => { @@ -40,14 +37,6 @@ class CachedCollectionManager extends Emitter<{ reconnect: void; login: string | return connected && this.emit('reconnect'); } }); - - Tracker.autorun(() => { - const uid = Meteor.userId(); - this.logged = uid !== null; - if (this.logged) { - this.emit('login', uid); - } - }); } register(cachedCollection: CachedCollection) { @@ -80,10 +69,7 @@ class CachedCollectionManager extends Emitter<{ reconnect: void; login: string | } onLogin(cb: () => void) { - this.on('login', cb); - if (this.logged) { - cb(); - } + Accounts.onLogin(cb); } } diff --git a/apps/meteor/app/ui-utils/lib/MessageTypes.ts b/apps/meteor/app/ui-utils/lib/MessageTypes.ts index a4f77d10cbf7..c108fe55f168 100644 --- a/apps/meteor/app/ui-utils/lib/MessageTypes.ts +++ b/apps/meteor/app/ui-utils/lib/MessageTypes.ts @@ -5,8 +5,6 @@ export type MessageType = { id: MessageTypesValues; system?: boolean; /* deprecated */ - render?: (message: IMessage) => string; - /* deprecated */ template?: (message: IMessage) => unknown; message: TranslationKey; data?: (message: IMessage) => Record; diff --git a/apps/meteor/app/ui-utils/server/Message.ts b/apps/meteor/app/ui-utils/server/Message.ts index 18cf842b1993..06ae59238b42 100644 --- a/apps/meteor/app/ui-utils/server/Message.ts +++ b/apps/meteor/app/ui-utils/server/Message.ts @@ -11,9 +11,6 @@ export const Message = { parse(msg: IMessage, language: string) { const messageType = MessageTypes.getType(msg); if (messageType) { - if (messageType.render) { - return messageType.render(msg); - } if (messageType.template) { // Render message return; diff --git a/apps/meteor/app/user-status/server/methods/deleteCustomUserStatus.ts b/apps/meteor/app/user-status/server/methods/deleteCustomUserStatus.ts index f58fa9551f4c..416bc6f678ed 100644 --- a/apps/meteor/app/user-status/server/methods/deleteCustomUserStatus.ts +++ b/apps/meteor/app/user-status/server/methods/deleteCustomUserStatus.ts @@ -1,11 +1,11 @@ import { api } from '@rocket.chat/core-services'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { CustomUserStatus } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { deleteCustomUserStatus(userStatusID: string): Promise; diff --git a/apps/meteor/app/user-status/server/methods/getUserStatusText.ts b/apps/meteor/app/user-status/server/methods/getUserStatusText.ts index 5aa80627d562..911a69854b95 100644 --- a/apps/meteor/app/user-status/server/methods/getUserStatusText.ts +++ b/apps/meteor/app/user-status/server/methods/getUserStatusText.ts @@ -1,9 +1,9 @@ -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; import { getStatusText } from '../../../lib/server/functions/getStatusText'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { getUserStatusText(userId: string): Promise; diff --git a/apps/meteor/app/user-status/server/methods/insertOrUpdateUserStatus.ts b/apps/meteor/app/user-status/server/methods/insertOrUpdateUserStatus.ts index b6a98895bc2c..6e034f030679 100644 --- a/apps/meteor/app/user-status/server/methods/insertOrUpdateUserStatus.ts +++ b/apps/meteor/app/user-status/server/methods/insertOrUpdateUserStatus.ts @@ -1,14 +1,14 @@ import { api } from '@rocket.chat/core-services'; import type { ICustomUserStatus } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import type { InsertionModel } from '@rocket.chat/model-typings'; import { CustomUserStatus } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { trim } from '../../../../lib/utils/stringUtils'; import { hasPermissionAsync } from '../../../authorization/server/functions/hasPermission'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { insertOrUpdateUserStatus(userStatusData: { diff --git a/apps/meteor/app/user-status/server/methods/listCustomUserStatus.ts b/apps/meteor/app/user-status/server/methods/listCustomUserStatus.ts index 3a962121d65c..d9a58f8b8c72 100644 --- a/apps/meteor/app/user-status/server/methods/listCustomUserStatus.ts +++ b/apps/meteor/app/user-status/server/methods/listCustomUserStatus.ts @@ -1,9 +1,9 @@ import type { ICustomUserStatus } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { CustomUserStatus } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { listCustomUserStatus(): ICustomUserStatus[]; diff --git a/apps/meteor/app/user-status/server/methods/setUserStatus.ts b/apps/meteor/app/user-status/server/methods/setUserStatus.ts index 32db93e722fb..0b40e7e37246 100644 --- a/apps/meteor/app/user-status/server/methods/setUserStatus.ts +++ b/apps/meteor/app/user-status/server/methods/setUserStatus.ts @@ -1,6 +1,6 @@ import { Presence } from '@rocket.chat/core-services'; import type { IUser } from '@rocket.chat/core-typings'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; @@ -8,7 +8,7 @@ import { RateLimiter } from '../../../lib/server'; import { setStatusText } from '../../../lib/server/functions/setStatusText'; import { settings } from '../../../settings/server'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { setUserStatus(statusType: IUser['status'], statusText: IUser['statusText']): void; diff --git a/apps/meteor/app/utils/client/lib/SDKClient.ts b/apps/meteor/app/utils/client/lib/SDKClient.ts index c174f9125f49..7d26adaf546b 100644 --- a/apps/meteor/app/utils/client/lib/SDKClient.ts +++ b/apps/meteor/app/utils/client/lib/SDKClient.ts @@ -1,15 +1,12 @@ import type { RestClientInterface } from '@rocket.chat/api-client'; -import type { SDK } from '@rocket.chat/ddp-client/src/DDPSDK'; -import type { ClientStream } from '@rocket.chat/ddp-client/src/types/ClientStream'; -import type { StreamKeys, StreamNames, StreamerCallbackArgs } from '@rocket.chat/ddp-client/src/types/streams'; +import type { SDK, ClientStream, StreamKeys, StreamNames, StreamerCallbackArgs, ServerMethods } from '@rocket.chat/ddp-client'; import { Emitter } from '@rocket.chat/emitter'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { DDPCommon } from 'meteor/ddp-common'; import { Meteor } from 'meteor/meteor'; import { APIClient } from './RestApiClient'; -declare module '@rocket.chat/ddp-client/src/DDPSDK' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface SDK { stream>( diff --git a/apps/meteor/app/utils/lib/slashCommand.ts b/apps/meteor/app/utils/lib/slashCommand.ts index f4e2cc1b359a..47149807bbd8 100644 --- a/apps/meteor/app/utils/lib/slashCommand.ts +++ b/apps/meteor/app/utils/lib/slashCommand.ts @@ -126,7 +126,7 @@ export const slashCommands = { }, }; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { slashCommand(params: { cmd: string; params: string; msg: IMessage; triggerId: string }): unknown; diff --git a/apps/meteor/app/utils/server/slashCommand.ts b/apps/meteor/app/utils/server/slashCommand.ts index 74f2c5716cc4..dc85fee9b671 100644 --- a/apps/meteor/app/utils/server/slashCommand.ts +++ b/apps/meteor/app/utils/server/slashCommand.ts @@ -1,4 +1,4 @@ -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; import { slashCommands } from '../lib/slashCommand'; diff --git a/apps/meteor/app/version-check/server/methods/banner_dismiss.ts b/apps/meteor/app/version-check/server/methods/banner_dismiss.ts index 5ffebcfbbd5a..a3bf337626f9 100644 --- a/apps/meteor/app/version-check/server/methods/banner_dismiss.ts +++ b/apps/meteor/app/version-check/server/methods/banner_dismiss.ts @@ -1,10 +1,10 @@ +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Users } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { notifyOnUserChange } from '../../../lib/server/lib/notifyListener'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { 'banner/dismiss'({ id }: { id: string }): void; diff --git a/apps/meteor/app/webdav/server/methods/addWebdavAccount.ts b/apps/meteor/app/webdav/server/methods/addWebdavAccount.ts index e2c9a9ddc324..2c3973649091 100644 --- a/apps/meteor/app/webdav/server/methods/addWebdavAccount.ts +++ b/apps/meteor/app/webdav/server/methods/addWebdavAccount.ts @@ -1,14 +1,14 @@ import { api } from '@rocket.chat/core-services'; import type { IWebdavAccountPayload } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { WebdavAccounts } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Match, check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; import { settings } from '../../../settings/server'; import { WebdavClientAdapter } from '../lib/webdavClientAdapter'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { addWebdavAccount(formData: IWebdavAccountPayload): boolean; diff --git a/apps/meteor/app/webdav/server/methods/getFileFromWebdav.ts b/apps/meteor/app/webdav/server/methods/getFileFromWebdav.ts index 346362935d87..38aeb0442c5c 100644 --- a/apps/meteor/app/webdav/server/methods/getFileFromWebdav.ts +++ b/apps/meteor/app/webdav/server/methods/getFileFromWebdav.ts @@ -1,15 +1,15 @@ import type { IWebdavAccount, IWebdavNode } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { WebdavAccounts } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { settings } from '../../../settings/server'; import { getWebdavCredentials } from '../lib/getWebdavCredentials'; import { WebdavClientAdapter } from '../lib/webdavClientAdapter'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention - export interface ServerMethods { + interface ServerMethods { getFileFromWebdav(accountId: IWebdavAccount['_id'], file: IWebdavNode): Promise<{ success: boolean; data: Uint8Array }>; } } diff --git a/apps/meteor/app/webdav/server/methods/getWebdavFileList.ts b/apps/meteor/app/webdav/server/methods/getWebdavFileList.ts index f4d944181928..66e924b719a2 100644 --- a/apps/meteor/app/webdav/server/methods/getWebdavFileList.ts +++ b/apps/meteor/app/webdav/server/methods/getWebdavFileList.ts @@ -1,13 +1,13 @@ import type { IWebdavAccount, IWebdavNode } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { WebdavAccounts } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { settings } from '../../../settings/server'; import { getWebdavCredentials } from '../lib/getWebdavCredentials'; import { WebdavClientAdapter } from '../lib/webdavClientAdapter'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { getWebdavFileList(accountId: IWebdavAccount['_id'], path: string): { success: boolean; data: IWebdavNode[] }; diff --git a/apps/meteor/app/webdav/server/methods/getWebdavFilePreview.ts b/apps/meteor/app/webdav/server/methods/getWebdavFilePreview.ts index 1e01937a0e52..34077babf276 100644 --- a/apps/meteor/app/webdav/server/methods/getWebdavFilePreview.ts +++ b/apps/meteor/app/webdav/server/methods/getWebdavFilePreview.ts @@ -1,13 +1,13 @@ import type { IWebdavAccount } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { WebdavAccounts } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { createClient } from 'webdav'; import { settings } from '../../../settings/server'; import { getWebdavCredentials } from '../lib/getWebdavCredentials'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { getWebdavFilePreview(accountId: IWebdavAccount['_id'], path: string): { success: true; data: ArrayBuffer } | undefined; diff --git a/apps/meteor/app/webdav/server/methods/removeWebdavAccount.ts b/apps/meteor/app/webdav/server/methods/removeWebdavAccount.ts index df6102297cc2..a68a14e29e40 100644 --- a/apps/meteor/app/webdav/server/methods/removeWebdavAccount.ts +++ b/apps/meteor/app/webdav/server/methods/removeWebdavAccount.ts @@ -1,14 +1,14 @@ import { api } from '@rocket.chat/core-services'; import type { IWebdavAccount } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { WebdavAccounts } from '@rocket.chat/models'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; import { check } from 'meteor/check'; import { Meteor } from 'meteor/meteor'; import type { DeleteResult } from 'mongodb'; import { methodDeprecationLogger } from '../../../lib/server/lib/deprecationWarningLogger'; -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { removeWebdavAccount(accountId: IWebdavAccount['_id']): DeleteResult; diff --git a/apps/meteor/app/webdav/server/methods/uploadFileToWebdav.ts b/apps/meteor/app/webdav/server/methods/uploadFileToWebdav.ts index 8a2e1badd27d..97bcf4632216 100644 --- a/apps/meteor/app/webdav/server/methods/uploadFileToWebdav.ts +++ b/apps/meteor/app/webdav/server/methods/uploadFileToWebdav.ts @@ -1,7 +1,8 @@ import { MeteorError } from '@rocket.chat/core-services'; import type { IWebdavAccount } from '@rocket.chat/core-typings'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Logger } from '@rocket.chat/logger'; -import type { ServerMethods, TranslationKey } from '@rocket.chat/ui-contexts'; +import type { TranslationKey } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { settings } from '../../../settings/server'; @@ -9,7 +10,7 @@ import { uploadFileToWebdav } from '../lib/uploadFileToWebdav'; const logger = new Logger('WebDAV_Upload'); -declare module '@rocket.chat/ui-contexts' { +declare module '@rocket.chat/ddp-client' { // eslint-disable-next-line @typescript-eslint/naming-convention interface ServerMethods { uploadFileToWebdav( diff --git a/apps/meteor/client/NavBarV2/NavBarSettingsToolbar/UserMenu/UserMenu.tsx b/apps/meteor/client/NavBarV2/NavBarSettingsToolbar/UserMenu/UserMenu.tsx index fd4498f5fb8e..531ff8a74b66 100644 --- a/apps/meteor/client/NavBarV2/NavBarSettingsToolbar/UserMenu/UserMenu.tsx +++ b/apps/meteor/client/NavBarV2/NavBarSettingsToolbar/UserMenu/UserMenu.tsx @@ -1,5 +1,6 @@ import type { IUser } from '@rocket.chat/core-typings'; import { useTranslation } from '@rocket.chat/ui-contexts'; +import type { ComponentProps } from 'react'; import React, { memo, useState } from 'react'; import GenericMenu from '../../../components/GenericMenu/GenericMenu'; @@ -8,9 +9,9 @@ import { useHandleMenuAction } from '../../../components/GenericMenu/hooks/useHa import UserMenuButton from './UserMenuButton'; import { useUserMenu } from './hooks/useUserMenu'; -type UserMenuProps = { user: IUser; className?: string }; +type UserMenuProps = { user: IUser } & Omit, 'sections' | 'items' | 'title'>; -const UserMenu = function UserMenu({ user }: UserMenuProps) { +const UserMenu = function UserMenu({ user, ...props }: UserMenuProps) { const t = useTranslation(); const [isOpen, setIsOpen] = useState(false); @@ -21,6 +22,7 @@ const UserMenu = function UserMenu({ user }: UserMenuProps) { return ( {t('Topic')} - + } + /> {t('Displayed_next_to_name')} @@ -243,7 +246,7 @@ const CreateDiscussion = ({ onClose, defaultParentRoom, parentMessageId, nameSug - diff --git a/apps/meteor/client/components/GenericMenu/GenericMenu.spec.tsx b/apps/meteor/client/components/GenericMenu/GenericMenu.spec.tsx new file mode 100644 index 000000000000..99e62bac1a60 --- /dev/null +++ b/apps/meteor/client/components/GenericMenu/GenericMenu.spec.tsx @@ -0,0 +1,60 @@ +import '@testing-library/jest-dom'; +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import React from 'react'; + +import GenericMenu from './GenericMenu'; + +const mockedFunction = jest.fn(); +const regular = { + items: [ + { + id: 'edit', + content: 'Edit', + icon: 'pencil' as const, + onClick: mockedFunction, + }, + ], +}; +const danger = { + items: [ + { + id: 'delete', + content: 'Delete', + icon: 'trash' as const, + onClick: () => null, + variant: 'danger', + }, + ], +}; + +const sections = [regular, danger]; + +describe('Room Actions Menu', () => { + it('should render kebab menu with the list content', async () => { + render(); + + userEvent.click(screen.getByRole('button')); + + expect(await screen.findByText('Edit')).toBeInTheDocument(); + expect(await screen.findByText('Delete')).toBeInTheDocument(); + }); + + it('should have two different sections, regular and danger', async () => { + render(); + + userEvent.click(screen.getByRole('button')); + + expect(screen.getAllByRole('presentation')).toHaveLength(2); + expect(screen.getByRole('separator')).toBeInTheDocument(); + }); + + it('should call the action when item clicked', async () => { + render(); + + userEvent.click(screen.getByRole('button')); + userEvent.click(screen.getAllByRole('menuitem')[0]); + + expect(mockedFunction).toHaveBeenCalled(); + }); +}); diff --git a/apps/meteor/client/components/GenericMenu/GenericMenuItem.tsx b/apps/meteor/client/components/GenericMenu/GenericMenuItem.tsx index 44feedf86115..c01a64d708a0 100644 --- a/apps/meteor/client/components/GenericMenu/GenericMenuItem.tsx +++ b/apps/meteor/client/components/GenericMenu/GenericMenuItem.tsx @@ -13,6 +13,7 @@ export type GenericMenuItemProps = { description?: ReactNode; gap?: boolean; tooltip?: string; + variant?: string; }; const GenericMenuItem = ({ icon, content, addon, status, gap, tooltip }: GenericMenuItemProps) => ( diff --git a/apps/meteor/client/components/GenericModal/GenericModal.spec.tsx b/apps/meteor/client/components/GenericModal/GenericModal.spec.tsx new file mode 100644 index 000000000000..0ef7235729c4 --- /dev/null +++ b/apps/meteor/client/components/GenericModal/GenericModal.spec.tsx @@ -0,0 +1,87 @@ +import { useSetModal } from '@rocket.chat/ui-contexts'; +import { act, screen } from '@testing-library/react'; +import { renderHook } from '@testing-library/react-hooks'; +import userEvent from '@testing-library/user-event'; +import type { ReactElement } from 'react'; +import React, { Suspense } from 'react'; + +import ModalProviderWithRegion from '../../providers/ModalProvider/ModalProviderWithRegion'; +import GenericModal from './GenericModal'; + +import '@testing-library/jest-dom'; + +const renderModal = (modalElement: ReactElement) => { + const { + result: { current: setModal }, + } = renderHook(() => useSetModal(), { + wrapper: ({ children }) => ( + + {children} + + ), + }); + + act(() => { + setModal(modalElement); + }); + + return { setModal }; +}; + +describe('callbacks', () => { + it('should call onClose callback when dismissed', async () => { + const handleClose = jest.fn(); + + renderModal(); + + expect(await screen.findByRole('heading', { name: 'Modal', exact: true })).toBeInTheDocument(); + + userEvent.keyboard('{Escape}'); + + expect(screen.queryByRole('heading', { name: 'Modal', exact: true })).not.toBeInTheDocument(); + + expect(handleClose).toHaveBeenCalled(); + }); + + it('should NOT call onClose callback when confirmed', async () => { + const handleConfirm = jest.fn(); + const handleClose = jest.fn(); + + const { setModal } = renderModal(); + + expect(await screen.findByRole('heading', { name: 'Modal', exact: true })).toBeInTheDocument(); + + userEvent.click(screen.getByRole('button', { name: 'Ok', exact: true })); + + expect(handleConfirm).toHaveBeenCalled(); + + act(() => { + setModal(null); + }); + + expect(screen.queryByRole('heading', { name: 'Modal', exact: true })).not.toBeInTheDocument(); + + expect(handleClose).not.toHaveBeenCalled(); + }); + + it('should NOT call onClose callback when cancelled', async () => { + const handleCancel = jest.fn(); + const handleClose = jest.fn(); + + const { setModal } = renderModal(); + + expect(await screen.findByRole('heading', { name: 'Modal', exact: true })).toBeInTheDocument(); + + userEvent.click(screen.getByRole('button', { name: 'Cancel', exact: true })); + + expect(handleCancel).toHaveBeenCalled(); + + act(() => { + setModal(null); + }); + + expect(screen.queryByRole('heading', { name: 'Modal', exact: true })).not.toBeInTheDocument(); + + expect(handleClose).not.toHaveBeenCalled(); + }); +}); diff --git a/apps/meteor/client/components/GenericModal/GenericModal.tsx b/apps/meteor/client/components/GenericModal/GenericModal.tsx index 914928d4d423..d371e1ff4ef2 100644 --- a/apps/meteor/client/components/GenericModal/GenericModal.tsx +++ b/apps/meteor/client/components/GenericModal/GenericModal.tsx @@ -1,9 +1,9 @@ import { Button, Modal } from '@rocket.chat/fuselage'; -import { useUniqueId } from '@rocket.chat/fuselage-hooks'; +import { useEffectEvent, useUniqueId } from '@rocket.chat/fuselage-hooks'; import type { Keys as IconName } from '@rocket.chat/icons'; import { useTranslation } from '@rocket.chat/ui-contexts'; import type { ComponentProps, ReactElement, ReactNode, ComponentPropsWithoutRef } from 'react'; -import React from 'react'; +import React, { useEffect, useRef } from 'react'; import type { RequiredModalProps } from './withDoNotAskAgain'; import { withDoNotAskAgain } from './withDoNotAskAgain'; @@ -78,6 +78,31 @@ const GenericModal = ({ const t = useTranslation(); const genericModalId = useUniqueId(); + const dismissedRef = useRef(true); + + const handleConfirm = useEffectEvent(() => { + dismissedRef.current = false; + onConfirm?.(); + }); + + const handleCancel = useEffectEvent(() => { + dismissedRef.current = false; + onCancel?.(); + }); + + const handleCloseButtonClick = useEffectEvent(() => { + dismissedRef.current = true; + onClose?.(); + }); + + useEffect( + () => () => { + if (!dismissedRef.current) return; + onClose?.(); + }, + [onClose], + ); + return ( @@ -86,7 +111,7 @@ const GenericModal = ({ {tagline && {tagline}} {title ?? t('Are_you_sure')} - + {children} @@ -94,7 +119,7 @@ const GenericModal = ({ {annotation && !dontAskAgain && {annotation}} {onCancel && ( - )} @@ -104,7 +129,7 @@ const GenericModal = ({ )} {!wrapperFunction && onConfirm && ( - )} diff --git a/apps/meteor/client/components/Omnichannel/modals/CloseChatModal.tsx b/apps/meteor/client/components/Omnichannel/modals/CloseChatModal.tsx index 401448ceb396..7c028fb5c876 100644 --- a/apps/meteor/client/components/Omnichannel/modals/CloseChatModal.tsx +++ b/apps/meteor/client/components/Omnichannel/modals/CloseChatModal.tsx @@ -52,6 +52,8 @@ const CloseChatModal = ({ } = useForm(); const commentRequired = useSetting('Livechat_request_comment_when_closing_conversation') as boolean; + const alwaysSendTranscript = useSetting('Livechat_transcript_send_always'); + const customSubject = useSetting('Livechat_transcript_email_subject'); const [tagRequired, setTagRequired] = useState(false); const tags = watch('tags'); @@ -65,7 +67,7 @@ const CloseChatModal = ({ const transcriptPDFPermission = usePermission('request-pdf-transcript'); const transcriptEmailPermission = usePermission('send-omnichannel-chat-transcript'); - const canSendTranscriptEmail = transcriptEmailPermission && visitorEmail; + const canSendTranscriptEmail = transcriptEmailPermission && visitorEmail && !alwaysSendTranscript; const canSendTranscriptPDF = transcriptPDFPermission && hasLicense; const canSendTranscript = canSendTranscriptEmail || canSendTranscriptPDF; @@ -77,7 +79,7 @@ const CloseChatModal = ({ ({ comment, tags, transcriptPDF, transcriptEmail, subject }): void => { const preferences = { omnichannelTranscriptPDF: !!transcriptPDF, - omnichannelTranscriptEmail: !!transcriptEmail, + omnichannelTranscriptEmail: alwaysSendTranscript ? true : !!transcriptEmail, }; const requestData = transcriptEmail && visitorEmail ? { email: visitorEmail, subject } : undefined; @@ -97,7 +99,7 @@ const CloseChatModal = ({ onConfirm(comment, tags, preferences, requestData); } }, - [commentRequired, tagRequired, visitorEmail, errors, setError, t, onConfirm], + [commentRequired, tagRequired, visitorEmail, errors, setError, t, onConfirm, alwaysSendTranscript], ); const cannotSubmit = useMemo(() => { @@ -132,9 +134,9 @@ const CloseChatModal = ({ dispatchToastMessage({ type: 'error', message: t('Customer_without_registered_email') }); return; } - setValue('subject', subject || t('Transcript_of_your_livechat_conversation')); + setValue('subject', subject || customSubject || t('Transcript_of_your_livechat_conversation')); } - }, [transcriptEmail, setValue, visitorEmail, subject, t]); + }, [transcriptEmail, setValue, visitorEmail, subject, t, customSubject]); if (commentRequired || tagRequired || canSendTranscript) { return ( diff --git a/apps/meteor/client/components/message/content/attachments/file/GenericFileAttachment.tsx b/apps/meteor/client/components/message/content/attachments/file/GenericFileAttachment.tsx index b7bcd7d1e9dd..86223cd7f2b4 100644 --- a/apps/meteor/client/components/message/content/attachments/file/GenericFileAttachment.tsx +++ b/apps/meteor/client/components/message/content/attachments/file/GenericFileAttachment.tsx @@ -38,15 +38,21 @@ const GenericFileAttachment = ({ const { t } = useTranslation(); const handleTitleClick = (event: UIEvent): void => { - if (openDocumentViewer && link) { + if (!link) { + return; + } + + if (openDocumentViewer && format === 'PDF') { event.preventDefault(); - if (format === 'PDF') { - const url = new URL(getURL(link), window.location.origin); - url.searchParams.set('contentDisposition', 'inline'); - openDocumentViewer(url.toString(), format, ''); - return; - } + const url = new URL(getURL(link), window.location.origin); + url.searchParams.set('contentDisposition', 'inline'); + openDocumentViewer(url.toString(), format, ''); + return; + } + + if (link.includes('/file-decrypt/')) { + event.preventDefault(); registerDownloadForUid(uid, t, title); forAttachmentDownload(uid, link); diff --git a/apps/meteor/client/components/message/content/attachments/structure/AttachmentDownloadBase.tsx b/apps/meteor/client/components/message/content/attachments/structure/AttachmentDownloadBase.tsx index dae6b9024776..284cb0cecbf2 100644 --- a/apps/meteor/client/components/message/content/attachments/structure/AttachmentDownloadBase.tsx +++ b/apps/meteor/client/components/message/content/attachments/structure/AttachmentDownloadBase.tsx @@ -6,18 +6,19 @@ import Action from '../../Action'; type AttachmentDownloadBaseProps = Omit, 'icon'> & { title?: string | undefined; href: string }; -const AttachmentDownloadBase = ({ title, href, ...props }: AttachmentDownloadBaseProps) => { +const AttachmentDownloadBase = ({ title, href, disabled, ...props }: AttachmentDownloadBaseProps) => { const t = useTranslation(); return ( ); diff --git a/apps/meteor/client/components/message/variants/SystemMessage.tsx b/apps/meteor/client/components/message/variants/SystemMessage.tsx index e2e1d9bf04bd..eeba342c3f31 100644 --- a/apps/meteor/client/components/message/variants/SystemMessage.tsx +++ b/apps/meteor/client/components/message/variants/SystemMessage.tsx @@ -94,14 +94,9 @@ const SystemMessage = ({ message, showUserAvatar, ...props }: SystemMessageProps )} {messageType && ( - + + {t(messageType.message, messageType.data ? messageType.data(message) : {})} + )} {formatTime(message.ts)} diff --git a/apps/meteor/client/hooks/roomActions/useCallsRoomAction.ts b/apps/meteor/client/hooks/roomActions/useCallsRoomAction.ts index 31be4b2300ee..cbc2a594eb6e 100644 --- a/apps/meteor/client/hooks/roomActions/useCallsRoomAction.ts +++ b/apps/meteor/client/hooks/roomActions/useCallsRoomAction.ts @@ -21,7 +21,7 @@ export const useCallsRoomAction = () => { return { id: 'calls', - groups: ['channel', 'group', 'team'], + groups: ['channel', 'group', 'team', 'direct', 'direct_multiple'], icon: 'phone', title: 'Calls', ...(federated && { diff --git a/apps/meteor/client/hooks/useDownloadFromServiceWorker.ts b/apps/meteor/client/hooks/useDownloadFromServiceWorker.ts index 5ab7f804fec7..199d1507e284 100644 --- a/apps/meteor/client/hooks/useDownloadFromServiceWorker.ts +++ b/apps/meteor/client/hooks/useDownloadFromServiceWorker.ts @@ -7,13 +7,15 @@ import { downloadAs } from '../lib/download'; const ee = new Emitter>(); -navigator.serviceWorker.addEventListener('message', (event) => { - if (event.data.type === 'attachment-download-result') { - const { result } = event.data as { result: ArrayBuffer; id: string }; +if ('serviceWorker' in navigator) { + navigator.serviceWorker.addEventListener('message', (event) => { + if (event.data.type === 'attachment-download-result') { + const { result } = event.data as { result: ArrayBuffer; id: string }; - ee.emit(event.data.id, { result, id: event.data.id }); - } -}); + ee.emit(event.data.id, { result, id: event.data.id }); + } + }); +} export const registerDownloadForUid = (uid: string, t: ReturnType['t'], title?: string) => { ee.once(uid, ({ result }) => { @@ -23,8 +25,13 @@ export const registerDownloadForUid = (uid: string, t: ReturnType { if (!controller) { - controller = navigator.serviceWorker.controller; + controller = navigator?.serviceWorker?.controller; + } + + if (!controller) { + return; } + controller?.postMessage({ type: 'attachment-download', url: href, @@ -33,7 +40,7 @@ export const forAttachmentDownload = (uid: string, href: string, controller?: Se }; export const useDownloadFromServiceWorker = (href: string, title?: string) => { - const { controller } = navigator.serviceWorker; + const { controller } = navigator?.serviceWorker || {}; const uid = useUniqueId(); diff --git a/apps/meteor/client/lib/imperativeModal.tsx b/apps/meteor/client/lib/imperativeModal.tsx index 28db6fa107ed..3740eb1ebc9c 100644 --- a/apps/meteor/client/lib/imperativeModal.tsx +++ b/apps/meteor/client/lib/imperativeModal.tsx @@ -1,15 +1,15 @@ import { Emitter } from '@rocket.chat/emitter'; import React, { Suspense, createElement } from 'react'; -import type { ComponentProps, ElementType, ReactNode } from 'react'; +import type { ComponentProps, ComponentType, ReactNode } from 'react'; import { modalStore } from '../providers/ModalProvider/ModalStore'; -type ReactModalDescriptor = { +type ReactModalDescriptor = ComponentType> = { component: TComponent; props?: ComponentProps; }; -type ModalDescriptor = ReactModalDescriptor | null; +type ModalDescriptor = ReactModalDescriptor | null; type ModalInstance = { close: () => void; @@ -41,11 +41,11 @@ class ImperativeModalEmmiter extends Emitter<{ update: ModalDescriptor }> { this.store = store; } - open = (descriptor: ReactModalDescriptor): ModalInstance => { + open = >(descriptor: ReactModalDescriptor): ModalInstance => { return this.store.open(mapCurrentModal(descriptor as ModalDescriptor)); }; - push = (descriptor: ReactModalDescriptor): ModalInstance => { + push = >(descriptor: ReactModalDescriptor): ModalInstance => { return this.store.push(mapCurrentModal(descriptor as ModalDescriptor)); }; diff --git a/apps/meteor/client/lib/utils/callWithErrorHandling.ts b/apps/meteor/client/lib/utils/callWithErrorHandling.ts index ebdb59a388e1..cd3c6c3748b5 100644 --- a/apps/meteor/client/lib/utils/callWithErrorHandling.ts +++ b/apps/meteor/client/lib/utils/callWithErrorHandling.ts @@ -1,4 +1,4 @@ -import type { ServerMethodName, ServerMethodParameters, ServerMethodReturn } from '@rocket.chat/ui-contexts'; +import type { ServerMethodName, ServerMethodParameters, ServerMethodReturn } from '@rocket.chat/ddp-client'; import { sdk } from '../../../app/utils/client/lib/SDKClient'; import { dispatchToastMessage } from '../toast'; diff --git a/apps/meteor/client/meteorOverrides/login/saml.ts b/apps/meteor/client/meteorOverrides/login/saml.ts index f3ff7a8d45dd..14dfcc694e5c 100644 --- a/apps/meteor/client/meteorOverrides/login/saml.ts +++ b/apps/meteor/client/meteorOverrides/login/saml.ts @@ -21,6 +21,12 @@ declare module 'meteor/accounts-base' { credentialToken?: string; credentialSecret?: string; }; + + /** + * There is one case where the onlogout event is triggered with no user: + * during the deletion, the user is logged out, and the framework try to get the user from the database. + */ + function onLogout(func: (options: { user?: Meteor.User; connection: Meteor.Connection }) => void): void; } } diff --git a/apps/meteor/client/methods/hideRoom.ts b/apps/meteor/client/methods/hideRoom.ts index c7bb9317d71c..91cf2a3de04c 100644 --- a/apps/meteor/client/methods/hideRoom.ts +++ b/apps/meteor/client/methods/hideRoom.ts @@ -1,4 +1,4 @@ -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; import { ChatSubscription } from '../../app/models/client'; diff --git a/apps/meteor/client/methods/openRoom.ts b/apps/meteor/client/methods/openRoom.ts index c449c154ec23..81a40989e696 100644 --- a/apps/meteor/client/methods/openRoom.ts +++ b/apps/meteor/client/methods/openRoom.ts @@ -1,4 +1,4 @@ -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; import { ChatSubscription } from '../../app/models/client'; diff --git a/apps/meteor/client/methods/pinMessage.ts b/apps/meteor/client/methods/pinMessage.ts index 7b4247c71870..2fba64be2bf9 100644 --- a/apps/meteor/client/methods/pinMessage.ts +++ b/apps/meteor/client/methods/pinMessage.ts @@ -1,5 +1,5 @@ import type { IMessage } from '@rocket.chat/core-typings'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; import { ChatMessage, ChatSubscription } from '../../app/models/client'; diff --git a/apps/meteor/client/methods/setUserActiveStatus.ts b/apps/meteor/client/methods/setUserActiveStatus.ts index 40370781129f..b6b9e0b778a7 100644 --- a/apps/meteor/client/methods/setUserActiveStatus.ts +++ b/apps/meteor/client/methods/setUserActiveStatus.ts @@ -1,4 +1,4 @@ -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; Meteor.methods({ diff --git a/apps/meteor/client/methods/starMessage.ts b/apps/meteor/client/methods/starMessage.ts index d6d1a91aaca6..bfa74738e283 100644 --- a/apps/meteor/client/methods/starMessage.ts +++ b/apps/meteor/client/methods/starMessage.ts @@ -1,4 +1,4 @@ -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; import { ChatMessage, ChatSubscription } from '../../app/models/client'; diff --git a/apps/meteor/client/methods/toggleFavorite.ts b/apps/meteor/client/methods/toggleFavorite.ts index 2df56e4731eb..5db56fa682f7 100644 --- a/apps/meteor/client/methods/toggleFavorite.ts +++ b/apps/meteor/client/methods/toggleFavorite.ts @@ -1,4 +1,4 @@ -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; import { ChatSubscription } from '../../app/models/client'; diff --git a/apps/meteor/client/methods/unpinMessage.ts b/apps/meteor/client/methods/unpinMessage.ts index 6c497d38ecc2..f05c07e5314d 100644 --- a/apps/meteor/client/methods/unpinMessage.ts +++ b/apps/meteor/client/methods/unpinMessage.ts @@ -1,5 +1,5 @@ import type { IMessage } from '@rocket.chat/core-typings'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; import { ChatMessage, ChatSubscription } from '../../app/models/client'; diff --git a/apps/meteor/client/methods/updateMessage.ts b/apps/meteor/client/methods/updateMessage.ts index 719a036f870c..8efffbe73ee6 100644 --- a/apps/meteor/client/methods/updateMessage.ts +++ b/apps/meteor/client/methods/updateMessage.ts @@ -1,5 +1,5 @@ import type { IEditedMessage } from '@rocket.chat/core-typings'; -import type { ServerMethods } from '@rocket.chat/ui-contexts'; +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Meteor } from 'meteor/meteor'; import { Tracker } from 'meteor/tracker'; import moment from 'moment'; diff --git a/apps/meteor/client/polyfills/hoverTouchClick.ts b/apps/meteor/client/polyfills/hoverTouchClick.ts deleted file mode 100644 index 53706a45fb33..000000000000 --- a/apps/meteor/client/polyfills/hoverTouchClick.ts +++ /dev/null @@ -1,17 +0,0 @@ -import * as domEvents from '../lib/utils/domEvents'; -import { isIOsDevice } from '../lib/utils/isIOsDevice'; - -((): void => { - if (!isIOsDevice || !window.matchMedia('(hover: none)').matches) { - return; - } - - domEvents.delegate({ - parent: document.body, - eventName: 'touchend', - elementSelector: 'a:hover', - listener: (_, element): void => { - domEvents.triggerClick(element); - }, - }); -})(); diff --git a/apps/meteor/client/polyfills/index.ts b/apps/meteor/client/polyfills/index.ts index bc91265b04ba..be470f261e26 100644 --- a/apps/meteor/client/polyfills/index.ts +++ b/apps/meteor/client/polyfills/index.ts @@ -3,5 +3,4 @@ import 'url-polyfill'; import './childNodeRemove'; import './cssVars'; import './customEventPolyfill'; -import './hoverTouchClick'; import './promiseFinally'; diff --git a/apps/meteor/client/portals/ModalPortal.tsx b/apps/meteor/client/portals/ModalPortal.tsx index d7c9ae9caa2d..6b2210d56926 100644 --- a/apps/meteor/client/portals/ModalPortal.tsx +++ b/apps/meteor/client/portals/ModalPortal.tsx @@ -1,18 +1,32 @@ -import type { ReactElement, ReactNode } from 'react'; -import React, { memo, useEffect, useState } from 'react'; +import type { ReactNode } from 'react'; +import { memo } from 'react'; import { createPortal } from 'react-dom'; -import { createAnchor } from '../lib/utils/createAnchor'; -import { deleteAnchor } from '../lib/utils/deleteAnchor'; +const createModalRoot = (): HTMLElement => { + const id = 'modal-root'; + const existing = document.getElementById(id); + + if (existing) return existing; + + const newOne = document.createElement('div'); + newOne.id = id; + document.body.append(newOne); + + return newOne; +}; + +let modalRoot: HTMLElement | null = null; type ModalPortalProps = { children?: ReactNode; }; -const ModalPortal = ({ children }: ModalPortalProps): ReactElement => { - const [modalRoot] = useState(() => createAnchor('modal-root')); - useEffect(() => (): void => deleteAnchor(modalRoot), [modalRoot]); - return <>{createPortal(children, modalRoot)}; +const ModalPortal = ({ children }: ModalPortalProps) => { + if (!modalRoot) { + modalRoot = createModalRoot(); + } + + return createPortal(children, modalRoot); }; export default memo(ModalPortal); diff --git a/apps/meteor/client/providers/ModalProvider/ModalProvider.spec.tsx b/apps/meteor/client/providers/ModalProvider/ModalProvider.spec.tsx index f77933337456..ea062c324807 100644 --- a/apps/meteor/client/providers/ModalProvider/ModalProvider.spec.tsx +++ b/apps/meteor/client/providers/ModalProvider/ModalProvider.spec.tsx @@ -1,115 +1,138 @@ -// import type { IMessage } from '@rocket.chat/core-typings'; -import { Emitter } from '@rocket.chat/emitter'; import { useSetModal } from '@rocket.chat/ui-contexts'; -import { render, screen } from '@testing-library/react'; -import { expect } from 'chai'; -import type { ReactNode } from 'react'; -import React, { Suspense, createContext, useContext, useEffect } from 'react'; +import { act, render, screen } from '@testing-library/react'; +import type { ForwardedRef, ReactElement } from 'react'; +import React, { Suspense, createContext, createRef, forwardRef, useContext, useImperativeHandle } from 'react'; import GenericModal from '../../components/GenericModal'; import { imperativeModal } from '../../lib/imperativeModal'; import ModalRegion from '../../views/modal/ModalRegion'; import ModalProvider from './ModalProvider'; import ModalProviderWithRegion from './ModalProviderWithRegion'; +import '@testing-library/jest-dom'; -const TestContext = createContext({ title: 'default' }); -const emitter = new Emitter(); +const renderWithSuspense = (ui: ReactElement) => + render(ui, { + wrapper: ({ children }) => {children}, + }); -const TestModal = ({ emitterEvent, modalFunc }: { emitterEvent: string; modalFunc?: () => ReactNode }) => { - const setModal = useSetModal(); - const { title } = useContext(TestContext); +describe('via useSetModal', () => { + const ModalTitleContext = createContext('default'); - useEffect(() => { - emitter.on(emitterEvent, () => { - setModal(modalFunc || undefined}>); - }); - }, [emitterEvent, setModal, title, modalFunc]); + type ModalOpenerAPI = { open: () => void }; - return <>; -}; + const ModalOpener = forwardRef((_: unknown, ref: ForwardedRef) => { + const setModal = useSetModal(); + const title = useContext(ModalTitleContext); + useImperativeHandle(ref, () => ({ + open: () => { + setModal(); + }, + })); + + return null; + }); -describe('Modal Provider', () => { it('should render a modal', async () => { - render( - + const modalOpenerRef = createRef(); + + renderWithSuspense( + + + , + ); + + act(() => { + modalOpenerRef.current?.open(); + }); + + expect(await screen.findByRole('dialog', { name: 'default' })).toBeInTheDocument(); + }); + + it('should render a modal that consumes a context', async () => { + const modalOpenerRef = createRef(); + + renderWithSuspense( + - + - , + , ); - emitter.emit('open'); - expect(await screen.findByText('default')).to.exist; + act(() => { + modalOpenerRef.current?.open(); + }); + + expect(await screen.findByRole('dialog', { name: 'title from context' })).toBeInTheDocument(); }); - it('should render a modal that is passed as a function', async () => { - render( - + it('should render a modal in another region', async () => { + const modalOpener1Ref = createRef(); + const modalOpener2Ref = createRef(); + + renderWithSuspense( + - undefined} />} /> + - , + + + + + + , ); - emitter.emit('open'); - expect(await screen.findByText('function modal')).to.exist; + + act(() => { + modalOpener1Ref.current?.open(); + }); + + expect(await screen.findByRole('dialog', { name: 'modal1' })).toBeInTheDocument(); + + act(() => { + modalOpener2Ref.current?.open(); + }); + + expect(await screen.findByRole('dialog', { name: 'modal2' })).toBeInTheDocument(); }); +}); + +describe('via imperativeModal', () => { + it('should render a modal through imperative modal', async () => { + renderWithSuspense( + + + , + ); - it('should render a modal through imperative modal', () => { - async () => { - render( - - - - - , - ); - - const { close } = imperativeModal.open({ + act(() => { + imperativeModal.open({ component: GenericModal, - props: { title: 'imperativeModal' }, + props: { title: 'imperativeModal', open: true }, }); + }); - expect(await screen.findByText('imperativeModal')).to.exist; + expect(await screen.findByRole('dialog', { name: 'imperativeModal' })).toBeInTheDocument(); - close(); + act(() => { + imperativeModal.close(); + }); - expect(screen.queryByText('imperativeModal')).to.not.exist; - }; + expect(screen.queryByText('imperativeModal')).not.toBeInTheDocument(); }); it('should not render a modal if no corresponding region exists', async () => { // ModalProviderWithRegion will always have a region identifier set // and imperativeModal will only render modals in the default region (e.g no region identifier) - render( - - - , - ); - - imperativeModal.open({ - component: GenericModal, - props: { title: 'imperativeModal' }, - }); - expect(screen.queryByText('imperativeModal')).to.not.exist; - }); + renderWithSuspense(); - it('should render a modal in another region', () => { - render( - - - - - - - - - - , - ); + act(() => { + imperativeModal.open({ + component: GenericModal, + props: { title: 'imperativeModal', open: true }, + }); + }); - emitter.emit('openModal1'); - expect(screen.getByText('modal1')).to.exist; - emitter.emit('openModal2'); - expect(screen.getByText('modal2')).to.exist; + expect(screen.queryByRole('dialog', { name: 'imperativeModal' })).not.toBeInTheDocument(); }); }); diff --git a/apps/meteor/client/providers/ModalProvider/ModalProvider.tsx b/apps/meteor/client/providers/ModalProvider/ModalProvider.tsx index 6c3f1026bc51..27092ea602b6 100644 --- a/apps/meteor/client/providers/ModalProvider/ModalProvider.tsx +++ b/apps/meteor/client/providers/ModalProvider/ModalProvider.tsx @@ -33,7 +33,7 @@ const ModalProvider = ({ children, region }: ModalProviderProps) => { }, region, }), - [currentModal, region, setModal], + [currentModal?.node, currentModal?.region, region, setModal], ); return ; diff --git a/apps/meteor/client/providers/RouterProvider.tsx b/apps/meteor/client/providers/RouterProvider.tsx index 8ba6e699b2b1..590c5f20da57 100644 --- a/apps/meteor/client/providers/RouterProvider.tsx +++ b/apps/meteor/client/providers/RouterProvider.tsx @@ -1,3 +1,5 @@ +import type { RoomType, RoomRouteData } from '@rocket.chat/core-typings'; +import { RouterContext } from '@rocket.chat/ui-contexts'; import type { RouterContextValue, RouteName, @@ -6,15 +8,15 @@ import type { SearchParameters, To, RouteObject, + LocationSearch, } from '@rocket.chat/ui-contexts'; -import { RouterContext } from '@rocket.chat/ui-contexts'; -import type { LocationSearch } from '@rocket.chat/ui-contexts/src/RouterContext'; import { FlowRouter } from 'meteor/kadira:flow-router'; import { Tracker } from 'meteor/tracker'; import type { ReactNode } from 'react'; import React from 'react'; import { appLayout } from '../lib/appLayout'; +import { roomCoordinator } from '../lib/rooms/roomCoordinator'; import { queueMicrotask } from '../lib/utils/queueMicrotask'; const subscribers = new Set<() => void>(); @@ -195,6 +197,9 @@ export const router: RouterContextValue = { defineRoutes, getRoutes, subscribeToRoutesChange, + getRoomRoute(roomType: RoomType, routeData: RoomRouteData) { + return { path: roomCoordinator.getRouteLink(roomType, routeData) || '/' }; + }, }; type RouterProviderProps = { diff --git a/apps/meteor/client/providers/ServerProvider.tsx b/apps/meteor/client/providers/ServerProvider.tsx index 53ac92287f78..7bf442671f08 100644 --- a/apps/meteor/client/providers/ServerProvider.tsx +++ b/apps/meteor/client/providers/ServerProvider.tsx @@ -1,14 +1,14 @@ import type { Serialized } from '@rocket.chat/core-typings'; -import type { Method, PathFor, OperationParams, OperationResult, UrlParams, PathPattern } from '@rocket.chat/rest-typings'; import type { ServerMethodName, ServerMethodParameters, ServerMethodReturn, StreamerCallbackArgs, - UploadResult, StreamNames, StreamKeys, -} from '@rocket.chat/ui-contexts'; +} from '@rocket.chat/ddp-client'; +import type { Method, PathFor, OperationParams, OperationResult, UrlParams, PathPattern } from '@rocket.chat/rest-typings'; +import type { UploadResult } from '@rocket.chat/ui-contexts'; import { ServerContext } from '@rocket.chat/ui-contexts'; import { Meteor } from 'meteor/meteor'; import { compile } from 'path-to-regexp'; diff --git a/apps/meteor/client/sidebar/RoomList/SideBarItemTemplateWithData.tsx b/apps/meteor/client/sidebar/RoomList/SideBarItemTemplateWithData.tsx index f9ec077e9e43..cc7cdfbe7761 100644 --- a/apps/meteor/client/sidebar/RoomList/SideBarItemTemplateWithData.tsx +++ b/apps/meteor/client/sidebar/RoomList/SideBarItemTemplateWithData.tsx @@ -8,6 +8,7 @@ import React, { memo, useMemo } from 'react'; import { RoomIcon } from '../../components/RoomIcon'; import { roomCoordinator } from '../../lib/rooms/roomCoordinator'; +import { isIOsDevice } from '../../lib/utils/isIOsDevice'; import { useOmnichannelPriorities } from '../../omnichannel/hooks/useOmnichannelPriorities'; import RoomMenu from '../RoomMenu'; import { OmnichannelBadges } from '../badges/OmnichannelBadges'; @@ -195,6 +196,7 @@ function SideBarItemTemplateWithData({ avatar={AvatarTemplate && } actions={actions} menu={ + !isIOsDevice && !isAnonymous && (!isQueued || (isQueued && isPriorityEnabled)) && ((): ReactElement => ( diff --git a/apps/meteor/client/sidebar/RoomMenu.tsx b/apps/meteor/client/sidebar/RoomMenu.tsx index 8df55bd5d359..06b1352d2803 100644 --- a/apps/meteor/client/sidebar/RoomMenu.tsx +++ b/apps/meteor/client/sidebar/RoomMenu.tsx @@ -200,10 +200,14 @@ const RoomMenu = ({ const menuOptions = useMemo( () => ({ ...(!hideDefaultOptions && { - hideRoom: { - label: { label: t('Hide'), icon: 'eye-off' }, - action: handleHide, - }, + ...(isOmnichannelRoom + ? {} + : { + hideRoom: { + label: { label: t('Hide'), icon: 'eye-off' }, + action: handleHide, + }, + }), toggleRead: { label: { label: isUnread ? t('Mark_read') : t('Mark_unread'), icon: 'flag' }, action: handleToggleRead, diff --git a/apps/meteor/client/sidebar/footer/SidebarFooterDefault.tsx b/apps/meteor/client/sidebar/footer/SidebarFooterDefault.tsx index fbf987fa78af..3d1c17dcebbe 100644 --- a/apps/meteor/client/sidebar/footer/SidebarFooterDefault.tsx +++ b/apps/meteor/client/sidebar/footer/SidebarFooterDefault.tsx @@ -1,7 +1,7 @@ import { css } from '@rocket.chat/css-in-js'; import { Box, SidebarDivider, Palette, SidebarFooter as Footer } from '@rocket.chat/fuselage'; import { useSetting } from '@rocket.chat/ui-contexts'; -import { useThemeMode } from '@rocket.chat/ui-theming/src/hooks/useThemeMode'; +import { useThemeMode } from '@rocket.chat/ui-theming'; import type { ReactElement } from 'react'; import React from 'react'; diff --git a/apps/meteor/client/sidebarv2/RoomList/SideBarItemTemplateWithData.tsx b/apps/meteor/client/sidebarv2/RoomList/SideBarItemTemplateWithData.tsx index 60444540f6fd..4eaba8cc37f0 100644 --- a/apps/meteor/client/sidebarv2/RoomList/SideBarItemTemplateWithData.tsx +++ b/apps/meteor/client/sidebarv2/RoomList/SideBarItemTemplateWithData.tsx @@ -8,6 +8,7 @@ import React, { memo, useMemo } from 'react'; import { RoomIcon } from '../../components/RoomIcon'; import { roomCoordinator } from '../../lib/rooms/roomCoordinator'; +import { isIOsDevice } from '../../lib/utils/isIOsDevice'; import { useOmnichannelPriorities } from '../../omnichannel/hooks/useOmnichannelPriorities'; import RoomMenu from '../RoomMenu'; import { OmnichannelBadges } from '../badges/OmnichannelBadges'; @@ -195,6 +196,7 @@ const SideBarItemTemplateWithData = ({ avatar={AvatarTemplate && } actions={actions} menu={ + !isIOsDevice && !isAnonymous && (!isQueued || (isQueued && isPriorityEnabled)) && ((): ReactElement => ( diff --git a/apps/meteor/client/sidebarv2/footer/SidebarFooterDefault.tsx b/apps/meteor/client/sidebarv2/footer/SidebarFooterDefault.tsx index fbf987fa78af..3d1c17dcebbe 100644 --- a/apps/meteor/client/sidebarv2/footer/SidebarFooterDefault.tsx +++ b/apps/meteor/client/sidebarv2/footer/SidebarFooterDefault.tsx @@ -1,7 +1,7 @@ import { css } from '@rocket.chat/css-in-js'; import { Box, SidebarDivider, Palette, SidebarFooter as Footer } from '@rocket.chat/fuselage'; import { useSetting } from '@rocket.chat/ui-contexts'; -import { useThemeMode } from '@rocket.chat/ui-theming/src/hooks/useThemeMode'; +import { useThemeMode } from '@rocket.chat/ui-theming'; import type { ReactElement } from 'react'; import React from 'react'; diff --git a/apps/meteor/client/sidebarv2/header/SearchSection.tsx b/apps/meteor/client/sidebarv2/header/SearchSection.tsx index 66d8eb65371f..c1f3f8cf8c21 100644 --- a/apps/meteor/client/sidebarv2/header/SearchSection.tsx +++ b/apps/meteor/client/sidebarv2/header/SearchSection.tsx @@ -72,7 +72,7 @@ const SearchSection = () => { { }, order: 5, group: 'menu', + disabled({ message }) { + return isE2EEMessage(message); + }, }); }); diff --git a/apps/meteor/client/startup/actionButtons/permalinkStar.ts b/apps/meteor/client/startup/actionButtons/permalinkStar.ts index bf6deede9b10..a1ee8d79fc44 100644 --- a/apps/meteor/client/startup/actionButtons/permalinkStar.ts +++ b/apps/meteor/client/startup/actionButtons/permalinkStar.ts @@ -1,3 +1,4 @@ +import { isE2EEMessage } from '@rocket.chat/core-typings'; import { Meteor } from 'meteor/meteor'; import { MessageAction } from '../../../app/ui-utils/client'; @@ -32,5 +33,8 @@ Meteor.startup(() => { }, order: 10, group: 'menu', + disabled({ message }) { + return isE2EEMessage(message); + }, }); }); diff --git a/apps/meteor/client/startup/startup.ts b/apps/meteor/client/startup/startup.ts index 2541529a1aef..45c102a72bf4 100644 --- a/apps/meteor/client/startup/startup.ts +++ b/apps/meteor/client/startup/startup.ts @@ -28,10 +28,15 @@ Meteor.startup(() => { removeLocalUserData(); return; } + if (!Meteor.status().connected) { return; } + if (Meteor.loggingIn()) { + return; + } + const user = await synchronizeUserData(uid); if (!user) { return; diff --git a/apps/meteor/client/stories/contexts/ServerContextMock.tsx b/apps/meteor/client/stories/contexts/ServerContextMock.tsx index 4a23d172ced2..2c9f835b35a5 100644 --- a/apps/meteor/client/stories/contexts/ServerContextMock.tsx +++ b/apps/meteor/client/stories/contexts/ServerContextMock.tsx @@ -1,6 +1,7 @@ import type { Serialized } from '@rocket.chat/core-typings'; +import type { ServerMethodName, ServerMethodParameters, ServerMethodReturn } from '@rocket.chat/ddp-client'; import type { Method, OperationParams, OperationResult, PathFor, PathPattern } from '@rocket.chat/rest-typings'; -import type { ServerMethodName, ServerMethodParameters, ServerMethodReturn, UploadResult } from '@rocket.chat/ui-contexts'; +import type { UploadResult } from '@rocket.chat/ui-contexts'; import { ServerContext } from '@rocket.chat/ui-contexts'; import { action } from '@storybook/addon-actions'; import type { ContextType, ReactElement, ReactNode } from 'react'; diff --git a/apps/meteor/client/uikit/hooks/useModalContextValue.ts b/apps/meteor/client/uikit/hooks/useModalContextValue.ts index e10a59902b6b..4a0932c8e1e7 100644 --- a/apps/meteor/client/uikit/hooks/useModalContextValue.ts +++ b/apps/meteor/client/uikit/hooks/useModalContextValue.ts @@ -14,6 +14,7 @@ type UseModalContextValueParams = { blockId?: string | undefined; }; }; + errors?: { [field: string]: string }[] | { [field: string]: string }; updateValues: Dispatch<{ actionId: string; payload: { @@ -25,7 +26,7 @@ type UseModalContextValueParams = { type UseModalContextValueReturn = ContextType; -export const useModalContextValue = ({ view, values, updateValues }: UseModalContextValueParams): UseModalContextValueReturn => { +export const useModalContextValue = ({ view, errors, values, updateValues }: UseModalContextValueParams): UseModalContextValueReturn => { const actionManager = useUiKitActionManager(); const emitInteraction = useMemo(() => actionManager.emitInteraction.bind(actionManager), [actionManager]); @@ -62,6 +63,7 @@ export const useModalContextValue = ({ view, values, updateValues }: UseModalCon }); }, ...view, + errors, values, viewId: view.id, }; diff --git a/apps/meteor/client/views/account/accessibility/hooks/useAcessibilityPreferencesValues.ts b/apps/meteor/client/views/account/accessibility/hooks/useAcessibilityPreferencesValues.ts index 339cdcff7dd9..9620e4286eb5 100644 --- a/apps/meteor/client/views/account/accessibility/hooks/useAcessibilityPreferencesValues.ts +++ b/apps/meteor/client/views/account/accessibility/hooks/useAcessibilityPreferencesValues.ts @@ -1,6 +1,6 @@ +import type { ThemePreference } from '@rocket.chat/core-typings'; import type { FontSize } from '@rocket.chat/rest-typings'; import { useUserPreference } from '@rocket.chat/ui-contexts'; -import type { ThemePreference } from '@rocket.chat/ui-theming/src/types/themes'; export type AccessibilityPreferencesData = { themeAppearence?: ThemePreference; diff --git a/apps/meteor/client/views/account/omnichannel/OmnichannelPreferencesPage.tsx b/apps/meteor/client/views/account/omnichannel/OmnichannelPreferencesPage.tsx index 9abec01df1d0..8489b3cb4b8b 100644 --- a/apps/meteor/client/views/account/omnichannel/OmnichannelPreferencesPage.tsx +++ b/apps/meteor/client/views/account/omnichannel/OmnichannelPreferencesPage.tsx @@ -1,5 +1,5 @@ import { ButtonGroup, Button, Box, Accordion } from '@rocket.chat/fuselage'; -import { useToastMessageDispatch, useTranslation, useEndpoint, useUserPreference } from '@rocket.chat/ui-contexts'; +import { useToastMessageDispatch, useTranslation, useEndpoint, useUserPreference, useSetting } from '@rocket.chat/ui-contexts'; import type { ReactElement } from 'react'; import React from 'react'; import { useForm, FormProvider } from 'react-hook-form'; @@ -17,12 +17,17 @@ const OmnichannelPreferencesPage = (): ReactElement => { const t = useTranslation(); const dispatchToastMessage = useToastMessageDispatch(); + const alwaysSendEmailTranscript = useSetting('Livechat_transcript_send_always'); const omnichannelTranscriptPDF = useUserPreference('omnichannelTranscriptPDF') ?? false; const omnichannelTranscriptEmail = useUserPreference('omnichannelTranscriptEmail') ?? false; const omnichannelHideConversationAfterClosing = useUserPreference('omnichannelHideConversationAfterClosing') ?? true; const methods = useForm({ - defaultValues: { omnichannelTranscriptPDF, omnichannelTranscriptEmail, omnichannelHideConversationAfterClosing }, + defaultValues: { + omnichannelTranscriptPDF, + omnichannelTranscriptEmail: alwaysSendEmailTranscript || omnichannelTranscriptEmail, + omnichannelHideConversationAfterClosing, + }, }); const { diff --git a/apps/meteor/client/views/account/omnichannel/PreferencesConversationTranscript.tsx b/apps/meteor/client/views/account/omnichannel/PreferencesConversationTranscript.tsx index 11bf6634a0e9..a003861c8d57 100644 --- a/apps/meteor/client/views/account/omnichannel/PreferencesConversationTranscript.tsx +++ b/apps/meteor/client/views/account/omnichannel/PreferencesConversationTranscript.tsx @@ -1,6 +1,6 @@ import { Accordion, Box, Field, FieldGroup, FieldLabel, FieldRow, FieldHint, Tag, ToggleSwitch } from '@rocket.chat/fuselage'; import { useUniqueId } from '@rocket.chat/fuselage-hooks'; -import { useTranslation, usePermission } from '@rocket.chat/ui-contexts'; +import { useTranslation, usePermission, useSetting } from '@rocket.chat/ui-contexts'; import React from 'react'; import { useFormContext } from 'react-hook-form'; @@ -12,8 +12,10 @@ const PreferencesConversationTranscript = () => { const { register } = useFormContext(); const hasLicense = useHasLicenseModule('livechat-enterprise'); + const alwaysSendEmailTranscript = useSetting('Livechat_transcript_send_always'); const canSendTranscriptPDF = usePermission('request-pdf-transcript'); - const canSendTranscriptEmail = usePermission('send-omnichannel-chat-transcript'); + const canSendTranscriptEmailPermission = usePermission('send-omnichannel-chat-transcript'); + const canSendTranscriptEmail = canSendTranscriptEmailPermission && !alwaysSendEmailTranscript; const cantSendTranscriptPDF = !canSendTranscriptPDF || !hasLicense; const omnichannelTranscriptPDF = useUniqueId(); @@ -42,7 +44,7 @@ const PreferencesConversationTranscript = () => { {t('Omnichannel_transcript_email')} - {!canSendTranscriptEmail && ( + {!canSendTranscriptEmailPermission && ( {t('No_permission')} diff --git a/apps/meteor/client/views/admin/engagementDashboard/channels/useChannelsList.ts b/apps/meteor/client/views/admin/engagementDashboard/channels/useChannelsList.ts index cd1a338eeab5..f45c620c8b49 100644 --- a/apps/meteor/client/views/admin/engagementDashboard/channels/useChannelsList.ts +++ b/apps/meteor/client/views/admin/engagementDashboard/channels/useChannelsList.ts @@ -24,6 +24,7 @@ export const useChannelsList = ({ period, offset, count }: UseChannelsListOption end: end.toISOString(), offset, count, + hideRoomsWithNoActivity: true, }); return response diff --git a/apps/meteor/client/views/admin/settings/inputs/ActionSettingInput.stories.tsx b/apps/meteor/client/views/admin/settings/inputs/ActionSettingInput.stories.tsx index 5c8a468eed80..d235d716d436 100644 --- a/apps/meteor/client/views/admin/settings/inputs/ActionSettingInput.stories.tsx +++ b/apps/meteor/client/views/admin/settings/inputs/ActionSettingInput.stories.tsx @@ -1,5 +1,6 @@ +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Field } from '@rocket.chat/fuselage'; -import type { ServerMethods, TranslationKey } from '@rocket.chat/ui-contexts'; +import type { TranslationKey } from '@rocket.chat/ui-contexts'; import type { ComponentMeta, ComponentStory } from '@storybook/react'; import React from 'react'; diff --git a/apps/meteor/client/views/admin/settings/inputs/ActionSettingInput.tsx b/apps/meteor/client/views/admin/settings/inputs/ActionSettingInput.tsx index 86c76c86f502..2f94048e3406 100644 --- a/apps/meteor/client/views/admin/settings/inputs/ActionSettingInput.tsx +++ b/apps/meteor/client/views/admin/settings/inputs/ActionSettingInput.tsx @@ -1,5 +1,6 @@ +import type { ServerMethods } from '@rocket.chat/ddp-client'; import { Button, FieldRow, FieldHint } from '@rocket.chat/fuselage'; -import type { ServerMethods, TranslationKey } from '@rocket.chat/ui-contexts'; +import type { TranslationKey } from '@rocket.chat/ui-contexts'; import { useMethod, useToastMessageDispatch, useTranslation } from '@rocket.chat/ui-contexts'; import type { ReactElement } from 'react'; import React from 'react'; diff --git a/apps/meteor/client/views/admin/users/AdminUserFormWithData.tsx b/apps/meteor/client/views/admin/users/AdminUserFormWithData.tsx index 63fe2691d972..e595acc46951 100644 --- a/apps/meteor/client/views/admin/users/AdminUserFormWithData.tsx +++ b/apps/meteor/client/views/admin/users/AdminUserFormWithData.tsx @@ -1,6 +1,7 @@ import type { IUser } from '@rocket.chat/core-typings'; import { isUserFederated } from '@rocket.chat/core-typings'; import { Box, Callout } from '@rocket.chat/fuselage'; +import { useEffectEvent } from '@rocket.chat/fuselage-hooks'; import { useTranslation } from '@rocket.chat/ui-contexts'; import type { ReactElement } from 'react'; import React from 'react'; @@ -16,7 +17,12 @@ type AdminUserFormWithDataProps = { const AdminUserFormWithData = ({ uid, onReload }: AdminUserFormWithDataProps): ReactElement => { const t = useTranslation(); - const { data, isLoading, isError } = useUserInfoQuery({ userId: uid }); + const { data, isLoading, isError, refetch } = useUserInfoQuery({ userId: uid }); + + const handleReload = useEffectEvent(() => { + onReload(); + refetch(); + }); if (isLoading) { return ( @@ -42,7 +48,7 @@ const AdminUserFormWithData = ({ uid, onReload }: AdminUserFormWithDataProps): R ); } - return ; + return ; }; export default AdminUserFormWithData; diff --git a/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppStatus/AppStatus.tsx b/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppStatus/AppStatus.tsx index 26adddffae79..db46d87c18d8 100644 --- a/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppStatus/AppStatus.tsx +++ b/apps/meteor/client/views/marketplace/AppDetailsPage/tabs/AppStatus/AppStatus.tsx @@ -76,13 +76,13 @@ const AppStatus = ({ app, showStatus = true, isAppDetailsPage, installed, ...pro isAppPurchased, onDismiss: cancelAction, onSuccess: confirmAction, + setIsPurchased: setPurchased, }); const handleAcquireApp = useCallback(() => { setLoading(true); - setPurchased(true); appInstallationHandler(); - }, [appInstallationHandler, setLoading, setPurchased]); + }, [appInstallationHandler, setLoading]); // @TODO we should refactor this to not use the label to determine the variant const getStatusVariant = (status: appStatusSpanResponseProps) => { diff --git a/apps/meteor/client/views/marketplace/hooks/useAppInstallationHandler.tsx b/apps/meteor/client/views/marketplace/hooks/useAppInstallationHandler.tsx index 3c0c41798172..ab5962150f04 100644 --- a/apps/meteor/client/views/marketplace/hooks/useAppInstallationHandler.tsx +++ b/apps/meteor/client/views/marketplace/hooks/useAppInstallationHandler.tsx @@ -19,9 +19,17 @@ export type AppInstallationHandlerParams = { isAppPurchased?: boolean; onDismiss: () => void; onSuccess: (action: Actions | '', appPermissions?: App['permissions']) => void; + setIsPurchased: (purchased: boolean) => void; }; -export function useAppInstallationHandler({ app, action, isAppPurchased, onDismiss, onSuccess }: AppInstallationHandlerParams) { +export function useAppInstallationHandler({ + app, + action, + isAppPurchased, + onDismiss, + onSuccess, + setIsPurchased, +}: AppInstallationHandlerParams) { const dispatchToastMessage = useToastMessageDispatch(); const setModal = useSetModal(); @@ -62,7 +70,16 @@ export function useAppInstallationHandler({ app, action, isAppPurchased, onDismi if (action === 'purchase' && !isAppPurchased) { try { const data = await appsOrchestrator.buildExternalUrl(app.id, app.purchaseType, false); - setModal(); + setModal( + { + setIsPurchased(true); + openPermissionModal(); + }} + />, + ); } catch (error) { handleAPIError(error); } @@ -70,7 +87,7 @@ export function useAppInstallationHandler({ app, action, isAppPurchased, onDismi } openPermissionModal(); - }, [action, isAppPurchased, openPermissionModal, appsOrchestrator, app.id, app.purchaseType, setModal, onDismiss]); + }, [action, isAppPurchased, openPermissionModal, appsOrchestrator, app.id, app.purchaseType, setModal, onDismiss, setIsPurchased]); return useCallback(async () => { if (app?.versionIncompatible) { diff --git a/apps/meteor/client/views/marketplace/hooks/useAppMenu.tsx b/apps/meteor/client/views/marketplace/hooks/useAppMenu.tsx index 25ae9bc0ead8..bd2071fe2d82 100644 --- a/apps/meteor/client/views/marketplace/hooks/useAppMenu.tsx +++ b/apps/meteor/client/views/marketplace/hooks/useAppMenu.tsx @@ -91,10 +91,6 @@ export const useAppMenu = (app: App, isAppDetailsPage: boolean) => { const installationSuccess = useCallback( async (action: Actions | '', permissionsGranted) => { if (action) { - if (action === 'purchase') { - setPurchased(true); - } - if (action === 'request') { setRequestedEndUser(true); } else { @@ -119,6 +115,7 @@ export const useAppMenu = (app: App, isAppDetailsPage: boolean) => { action, onDismiss: closeModal, onSuccess: installationSuccess, + setIsPurchased: setPurchased, }); const handleAcquireApp = useCallback(() => { diff --git a/apps/meteor/client/views/modal/ModalRegion.tsx b/apps/meteor/client/views/modal/ModalRegion.tsx index 5cbad2b52bc1..284c460ee043 100644 --- a/apps/meteor/client/views/modal/ModalRegion.tsx +++ b/apps/meteor/client/views/modal/ModalRegion.tsx @@ -1,6 +1,7 @@ -import { useModal, useCurrentModal } from '@rocket.chat/ui-contexts'; +import { useEffectEvent } from '@rocket.chat/fuselage-hooks'; +import { useCurrentModal, useModal } from '@rocket.chat/ui-contexts'; import type { ReactElement } from 'react'; -import React, { lazy, useCallback } from 'react'; +import React, { lazy } from 'react'; import ModalBackdrop from '../../components/ModalBackdrop'; import ModalPortal from '../../portals/ModalPortal'; @@ -10,7 +11,9 @@ const FocusScope = lazy(() => import('react-aria').then((module) => ({ default: const ModalRegion = (): ReactElement | null => { const currentModal = useCurrentModal(); const { setModal } = useModal(); - const handleDismiss = useCallback(() => setModal(null), [setModal]); + const handleDismiss = useEffectEvent(() => { + setModal(null); + }); if (!currentModal) { return null; diff --git a/apps/meteor/client/views/modal/uikit/UiKitModal.tsx b/apps/meteor/client/views/modal/uikit/UiKitModal.tsx index 56242d399ac5..55c6c8a32d71 100644 --- a/apps/meteor/client/views/modal/uikit/UiKitModal.tsx +++ b/apps/meteor/client/views/modal/uikit/UiKitModal.tsx @@ -20,7 +20,7 @@ type UiKitModalProps = { const UiKitModal = ({ initialView }: UiKitModalProps) => { const actionManager = useUiKitActionManager(); const { view, errors, values, updateValues, state } = useUiKitView(initialView); - const contextValue = useModalContextValue({ view, values, updateValues }); + const contextValue = useModalContextValue({ view, errors, values, updateValues }); const handleSubmit = useEffectEvent((e: FormEvent) => { preventSyntheticEvent(e); diff --git a/apps/meteor/client/views/omnichannel/currentChats/CurrentChatsPage.tsx b/apps/meteor/client/views/omnichannel/currentChats/CurrentChatsPage.tsx index 95fb9a54c3ce..c439cc838874 100644 --- a/apps/meteor/client/views/omnichannel/currentChats/CurrentChatsPage.tsx +++ b/apps/meteor/client/views/omnichannel/currentChats/CurrentChatsPage.tsx @@ -54,6 +54,7 @@ type CurrentChatQuery = { customFields?: string; sort: string; count?: number; + queued?: boolean; }; type useQueryType = ( @@ -95,8 +96,9 @@ const currentChatQuery: useQueryType = ( } if (status !== 'all') { - query.open = status === 'opened' || status === 'onhold'; + query.open = status === 'opened' || status === 'onhold' || status === 'queued'; query.onhold = status === 'onhold'; + query.queued = status === 'queued'; } if (servedBy && servedBy !== 'all') { query.agents = [servedBy]; @@ -170,8 +172,9 @@ const CurrentChatsPage = ({ id, onRowClick }: { id?: string; onRowClick: (_id: s const renderRow = useCallback( (room) => { const { _id, fname, servedBy, ts, lm, department, open, onHold, priorityWeight } = room; - const getStatusText = (open: boolean, onHold: boolean): string => { + const getStatusText = (open: boolean, onHold: boolean, servedBy: boolean): string => { if (!open) return t('Closed'); + if (open && !servedBy) return t('Queued'); return onHold ? t('On_Hold_Chats') : t('Room_Status_Open'); }; @@ -198,7 +201,7 @@ const CurrentChatsPage = ({ id, onRowClick }: { id?: string; onRowClick: (_id: s {moment(lm).format('L LTS')} - {getStatusText(open, onHold)} + {getStatusText(open, onHold, !!servedBy?.username)} {canRemoveClosedChats && !open && } diff --git a/apps/meteor/client/views/omnichannel/currentChats/FilterByText.tsx b/apps/meteor/client/views/omnichannel/currentChats/FilterByText.tsx index 131aa06f0a70..cda579387ea1 100644 --- a/apps/meteor/client/views/omnichannel/currentChats/FilterByText.tsx +++ b/apps/meteor/client/views/omnichannel/currentChats/FilterByText.tsx @@ -30,6 +30,7 @@ const FilterByText = ({ setFilter, reload, customFields, setCustomFields, hasCus ['closed', t('Closed')], ['opened', t('Room_Status_Open')], ['onhold', t('On_Hold_Chats')], + ['queued', t('Queued')], ]; const [guest, setGuest] = useLocalStorage('guest', ''); diff --git a/apps/meteor/client/views/room/RoomSkeleton.tsx b/apps/meteor/client/views/room/RoomSkeleton.tsx index 22abbcd3f3a1..083a729c309e 100644 --- a/apps/meteor/client/views/room/RoomSkeleton.tsx +++ b/apps/meteor/client/views/room/RoomSkeleton.tsx @@ -1,14 +1,25 @@ +import { FeaturePreview, FeaturePreviewOff, FeaturePreviewOn } from '@rocket.chat/ui-client'; import type { ReactElement } from 'react'; import React from 'react'; import MessageListSkeleton from '../../components/message/list/MessageListSkeleton'; import HeaderSkeleton from './Header/HeaderSkeleton'; +import HeaderSkeletonV2 from './HeaderV2/HeaderSkeleton'; import RoomComposerSkeleton from './composer/RoomComposer/RoomComposerSkeleton'; import RoomLayout from './layout/RoomLayout'; const RoomSkeleton = (): ReactElement => ( } + header={ + + + + + + + + + } body={ <> diff --git a/apps/meteor/client/views/room/composer/hooks/useComposerBoxPopup.ts b/apps/meteor/client/views/room/composer/hooks/useComposerBoxPopup.ts index fc65ed84ca02..c47f1a5ddab4 100644 --- a/apps/meteor/client/views/room/composer/hooks/useComposerBoxPopup.ts +++ b/apps/meteor/client/views/room/composer/hooks/useComposerBoxPopup.ts @@ -175,7 +175,7 @@ export const useComposerBoxPopup = ({ setPopup(undefined); setFocused(undefined); event.preventDefault(); - event.stopPropagation(); + event.stopImmediatePropagation(); } }); @@ -192,7 +192,7 @@ export const useComposerBoxPopup = ({ select(focused); event.preventDefault(); - event.stopPropagation(); + event.stopImmediatePropagation(); return true; } if (event.which === keys.ARROW_UP && !(event.shiftKey || event.ctrlKey || event.altKey || event.metaKey)) { @@ -211,7 +211,7 @@ export const useComposerBoxPopup = ({ return (focusedIndex > 0 ? list[focusedIndex - 1] : list[list.length - 1]) as T; }); event.preventDefault(); - event.stopPropagation(); + event.stopImmediatePropagation(); return true; } if (event.which === keys.ARROW_DOWN && !(event.shiftKey || event.ctrlKey || event.altKey || event.metaKey)) { @@ -230,7 +230,7 @@ export const useComposerBoxPopup = ({ return (focusedIndex < list.length - 1 ? list[focusedIndex + 1] : list[0]) as T; }); event.preventDefault(); - event.stopPropagation(); + event.stopImmediatePropagation(); return true; } }); diff --git a/apps/meteor/client/views/room/composer/messageBox/MessageBox.tsx b/apps/meteor/client/views/room/composer/messageBox/MessageBox.tsx index 4b7a466d6de0..00d9c66a2046 100644 --- a/apps/meteor/client/views/room/composer/messageBox/MessageBox.tsx +++ b/apps/meteor/client/views/room/composer/messageBox/MessageBox.tsx @@ -14,15 +14,7 @@ import { } from '@rocket.chat/ui-composer'; import { useTranslation, useUserPreference, useLayout, useSetting } from '@rocket.chat/ui-contexts'; import { useMutation } from '@tanstack/react-query'; -import type { - ReactElement, - MouseEventHandler, - FormEvent, - KeyboardEventHandler, - KeyboardEvent, - ClipboardEventHandler, - MouseEvent, -} from 'react'; +import type { ReactElement, MouseEventHandler, FormEvent, ClipboardEventHandler, MouseEvent } from 'react'; import React, { memo, useRef, useReducer, useCallback } from 'react'; import { Trans } from 'react-i18next'; import { useSubscription } from 'use-subscription'; @@ -60,11 +52,7 @@ const reducer = (_: unknown, event: FormEvent): boolean => { return Boolean(target.value.trim()); }; -const handleFormattingShortcut = ( - event: KeyboardEvent, - formattingButtons: FormattingButton[], - composer: ComposerAPI, -) => { +const handleFormattingShortcut = (event: KeyboardEvent, formattingButtons: FormattingButton[], composer: ComposerAPI) => { const isMacOS = navigator.platform.indexOf('Mac') !== -1; const isCmdOrCtrlPressed = (isMacOS && event.metaKey) || (!isMacOS && event.ctrlKey); @@ -196,7 +184,7 @@ const MessageBox = ({ } }; - const handler: KeyboardEventHandler = useMutableCallback((event) => { + const handler = useMutableCallback((event: KeyboardEvent) => { const { which: keyCode } = event; const input = event.target as HTMLTextAreaElement; @@ -357,7 +345,19 @@ const MessageBox = ({ configurations: composerPopupConfig, }); - const mergedRefs = useMessageComposerMergedRefs(c, textareaRef, callbackRef, autofocusRef); + const keyDownHandlerCallbackRef = useCallback( + (node: HTMLTextAreaElement) => { + if (node === null) { + return; + } + node.addEventListener('keydown', (e: KeyboardEvent) => { + handler(e); + }); + }, + [handler], + ); + + const mergedRefs = useMessageComposerMergedRefs(c, textareaRef, callbackRef, autofocusRef, keyDownHandlerCallbackRef); const shouldPopupPreview = useEnablePopupPreview(filter, popup); @@ -411,7 +411,6 @@ const MessageBox = ({ onChange={setTyping} style={textAreaStyle} placeholder={composerPlaceholder} - onKeyDown={handler} onPaste={handlePaste} aria-activedescendant={ariaActiveDescendant} /> diff --git a/apps/meteor/client/views/room/contextualBar/Info/RoomInfo/RoomInfo.tsx b/apps/meteor/client/views/room/contextualBar/Info/RoomInfo/RoomInfo.tsx index 678e5ec9f871..b0bf1d083a71 100644 --- a/apps/meteor/client/views/room/contextualBar/Info/RoomInfo/RoomInfo.tsx +++ b/apps/meteor/client/views/room/contextualBar/Info/RoomInfo/RoomInfo.tsx @@ -1,8 +1,8 @@ import type { IRoom } from '@rocket.chat/core-typings'; -import { Box, Callout, Menu, Option } from '@rocket.chat/fuselage'; +import { Box, Callout, IconButton } from '@rocket.chat/fuselage'; import { RoomAvatar } from '@rocket.chat/ui-avatar'; import { useTranslation } from '@rocket.chat/ui-contexts'; -import React, { useMemo } from 'react'; +import React from 'react'; import { ContextualbarHeader, @@ -12,9 +12,9 @@ import { ContextualbarClose, ContextualbarTitle, } from '../../../../../components/Contextualbar'; +import GenericMenu from '../../../../../components/GenericMenu/GenericMenu'; import { InfoPanel, - InfoPanelAction, InfoPanelActionGroup, InfoPanelAvatar, InfoPanelField, @@ -25,10 +25,10 @@ import { } from '../../../../../components/InfoPanel'; import RetentionPolicyCallout from '../../../../../components/InfoPanel/RetentionPolicyCallout'; import MarkdownText from '../../../../../components/MarkdownText'; -import type { Action } from '../../../../hooks/useActionSpread'; -import { useActionSpread } from '../../../../hooks/useActionSpread'; import { useRetentionPolicy } from '../../../hooks/useRetentionPolicy'; import { useRoomActions } from '../hooks/useRoomActions'; +import { useSplitRoomActions } from '../hooks/useSplitRoomActions'; +import RoomInfoActions from './RoomInfoActions'; type RoomInfoProps = { room: IRoom; @@ -47,35 +47,8 @@ const RoomInfo = ({ room, icon, onClickBack, onClickClose, onClickEnterRoom, onC const isDiscussion = 'prid' in room; const retentionPolicy = useRetentionPolicy(room); - const memoizedActions = useRoomActions(room, { onClickEnterRoom, onClickEdit }, resetState); - const { actions: actionsDefinition, menu: menuOptions } = useActionSpread(memoizedActions); - - const menu = useMemo(() => { - if (!menuOptions) { - return null; - } - - return ( -