diff --git a/.changeset/angry-baboons-trade.md b/.changeset/angry-baboons-trade.md deleted file mode 100644 index 6b78acc776e24..0000000000000 --- a/.changeset/angry-baboons-trade.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@rocket.chat/ui-kit': patch -'@rocket.chat/meteor': patch ---- - -Fixes an issue that prevented BlockAction interactions from having room information when triggered in a ContextualBar surface diff --git a/.changeset/beige-parrots-lead.md b/.changeset/beige-parrots-lead.md deleted file mode 100644 index fdb02b3ec9647..0000000000000 --- a/.changeset/beige-parrots-lead.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': minor ---- - -Swap usage of internal @rocket.chat/apps-engine internal APIs to @rocket.chat/apps package diff --git a/.changeset/big-corners-tie.md b/.changeset/big-corners-tie.md deleted file mode 100644 index d94dbbfb5daca..0000000000000 --- a/.changeset/big-corners-tie.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@rocket.chat/model-typings': patch -'@rocket.chat/models': patch -'@rocket.chat/meteor': patch ---- - -Ensures OAuth tokens are cleaned up after user deactivation diff --git a/.changeset/brave-fans-tie.md b/.changeset/brave-fans-tie.md deleted file mode 100644 index 3d2fa6b1b02af..0000000000000 --- a/.changeset/brave-fans-tie.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@rocket.chat/meteor": minor -"@rocket.chat/i18n": minor ---- - -Adds 4 new permissions (assigned to admins by default) to control the visibility of each tab inside the ABAC Administration panel diff --git a/.changeset/brown-files-work.md b/.changeset/brown-files-work.md deleted file mode 100644 index 9459cee560b56..0000000000000 --- a/.changeset/brown-files-work.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/apps-engine': minor ---- - -Remove files that weren't accessible to apps at development time diff --git a/.changeset/calm-seas-run.md b/.changeset/calm-seas-run.md deleted file mode 100644 index fe74a2e4fc672..0000000000000 --- a/.changeset/calm-seas-run.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -Fixes an issue that allowed a room converted from private to public (while abac is disabled) to retain its abac attributes (if any) diff --git a/.changeset/clever-zebras-melt.md b/.changeset/clever-zebras-melt.md deleted file mode 100644 index 8d02ede87a233..0000000000000 --- a/.changeset/clever-zebras-melt.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Fixes an issue where thread content would disappear after clicking "Jump to recent messages". diff --git a/.changeset/ddp-client-idempotent-reconnect.md b/.changeset/ddp-client-idempotent-reconnect.md deleted file mode 100644 index 207644c5211ad..0000000000000 --- a/.changeset/ddp-client-idempotent-reconnect.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/ddp-client": patch ---- - -Make `Connection.connect()` and `Connection.reconnect()` idempotent. Previously they rejected with `Error('Connection in progress')` when called while a connection was already in flight or established. Because the internal retry timer (`ws.onclose` → `setTimeout(() => void this.reconnect(), …)`) fires with no `.catch`, that rejection surfaced as an unhandled rejection at the page level whenever an external caller (e.g. an SDK consumer's bootstrap path) won the race against the timer. While `status === 'connecting'`, both methods now return the in-flight handshake promise so a later `failed` payload still propagates to every caller instead of being masked by a synthesized success; while `status === 'connected'` they resolve with `true`. The timer also no-ops when the connection has already been re-established, and a stale `ws.onclose` from a replaced socket no longer clobbers the new socket's status or schedules a redundant retry. diff --git a/.changeset/ddp-client-reset-retry-count.md b/.changeset/ddp-client-reset-retry-count.md deleted file mode 100644 index 90730285d3967..0000000000000 --- a/.changeset/ddp-client-reset-retry-count.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/ddp-client": patch ---- - -Reset `Connection.retryCount` to zero on a successful (re)connection. The counter was only ever incremented (in `ws.onclose`), never zeroed, so the retry budget was monotonically consumed across the connection's lifetime. With the default budget of `1`, any chain of two close events — for example the SDK reconnecting after a server force-logout, then the client running a follow-up `Meteor.logout()` whose server handler closes the WS again — drained the budget; the second close handler bailed at `retryCount >= retryOptions.retryCount` and the SDK stayed permanently disconnected. Method frames already in the dispatcher queue (e.g. a fresh `login` retry from the consumer) stayed queued forever. diff --git a/.changeset/ddp-dispatcher-non-method-frames.md b/.changeset/ddp-dispatcher-non-method-frames.md deleted file mode 100644 index c54d34e3b5164..0000000000000 --- a/.changeset/ddp-dispatcher-non-method-frames.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/ddp-client": patch ---- - -Fix `DDPDispatcher` dropping non-method frames (connect, sub, unsub, ping, pong) when a `wait` block is at the head of the queue. Previously every payload flowed through the same wait-serialization path: a `connect` frame dispatched after a `wait: true` method (e.g. `login`) would be queued in a new non-wait block but never actually sent, wedging the DDP handshake — the socket stayed open, the server never replied `connected`, and any caller awaiting the connection hung. Non-method payloads now bypass the queue and emit immediately; wait-method serialization between methods is unchanged. diff --git a/.changeset/dry-squids-wonder.md b/.changeset/dry-squids-wonder.md deleted file mode 100644 index 7fa1417da93cc..0000000000000 --- a/.changeset/dry-squids-wonder.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Fixes the missing edited indicator for the main parent message in the thread panel to ensure visual consistency with the main channel view. diff --git a/.changeset/edit-room-info-multiselect-aria-label.md b/.changeset/edit-room-info-multiselect-aria-label.md deleted file mode 100644 index 0c5b39192087d..0000000000000 --- a/.changeset/edit-room-info-multiselect-aria-label.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Adds an accessible label to the system-messages multi-select in the channel edit panel so screen readers announce its purpose. diff --git a/.changeset/eight-clouds-count.md b/.changeset/eight-clouds-count.md deleted file mode 100644 index 25ecce7dc886a..0000000000000 --- a/.changeset/eight-clouds-count.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Fixes intermittent "Channel Not Joined" screen when opening rooms in embedded mode. diff --git a/.changeset/fix-presence-comma-ids.md b/.changeset/fix-presence-comma-ids.md deleted file mode 100644 index c85d20785e3a6..0000000000000 --- a/.changeset/fix-presence-comma-ids.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@rocket.chat/meteor': patch -'@rocket.chat/rest-typings': patch ---- - -Fixes the `users.presence` endpoint returning an empty array when called with multiple comma-separated IDs, caused by `ajvQuery` coercing the string into a single-element array after the OpenAPI migration \ No newline at end of file diff --git a/.changeset/flat-islands-nail.md b/.changeset/flat-islands-nail.md deleted file mode 100644 index 10e5f4be74d88..0000000000000 --- a/.changeset/flat-islands-nail.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/ui-voip": patch ---- - -Fixes an issue where intentionally cancelling a screen share request would show an error toast by identifying error types and counting consecutive failures. diff --git a/.changeset/good-rules-lie.md b/.changeset/good-rules-lie.md deleted file mode 100644 index 75542e75aa078..0000000000000 --- a/.changeset/good-rules-lie.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@rocket.chat/model-typings': patch -'@rocket.chat/models': patch -'@rocket.chat/meteor': patch ---- - -Ensures that deactivated users have their login tokens cleaned up in users.deactivateidle diff --git a/.changeset/hot-impalas-vanish.md b/.changeset/hot-impalas-vanish.md deleted file mode 100644 index 30c32de851fd5..0000000000000 --- a/.changeset/hot-impalas-vanish.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": minor ---- - -Hides the room announcement, topic and description from the Administration > Rooms panel for ABAC managed rooms. In the channel sidebar Edit Channel form those fields stay visible to room members but are disabled, and the API rejects edits to them. diff --git a/.changeset/hot-spoons-heal.md b/.changeset/hot-spoons-heal.md deleted file mode 100644 index 6bcdabec83e39..0000000000000 --- a/.changeset/hot-spoons-heal.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Disables SAML login when it is set to validate signatures without the proper configuration for it diff --git a/.changeset/little-cars-love.md b/.changeset/little-cars-love.md deleted file mode 100644 index 7b67fa9c679be..0000000000000 --- a/.changeset/little-cars-love.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@rocket.chat/i18n": minor -"@rocket.chat/ui-voip": minor ---- - -Adds "Open in room" button to shared screen card on voice call widget diff --git a/.changeset/lovely-laws-wait.md b/.changeset/lovely-laws-wait.md deleted file mode 100644 index 306cfc7793926..0000000000000 --- a/.changeset/lovely-laws-wait.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -Allows users to search for attribute values when assigning them to rooms diff --git a/.changeset/major-coats-smash.md b/.changeset/major-coats-smash.md deleted file mode 100644 index 387bc777e041f..0000000000000 --- a/.changeset/major-coats-smash.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Fixes test button not playing default sound in Notifications Preferences diff --git a/.changeset/mighty-icons-kiss.md b/.changeset/mighty-icons-kiss.md deleted file mode 100644 index 5d62298c8e0c7..0000000000000 --- a/.changeset/mighty-icons-kiss.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'@rocket.chat/model-typings': minor -'@rocket.chat/rest-typings': minor -'@rocket.chat/models': minor -'@rocket.chat/meteor': minor -'@rocket.chat/i18n': minor ---- - -Adds new API endpoints `custom-sounds.create` and `custom-sounds.update` to manage custom sounds with strict file validation for size and specific MIME types to ensure system compatibility. diff --git a/.changeset/neat-trams-juggle.md b/.changeset/neat-trams-juggle.md deleted file mode 100644 index 56f327f68cc0c..0000000000000 --- a/.changeset/neat-trams-juggle.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Ensures the Meteor method for translateMessage validates access and types diff --git a/.changeset/ninety-lilies-kick.md b/.changeset/ninety-lilies-kick.md deleted file mode 100644 index f507a7fbfe4e0..0000000000000 --- a/.changeset/ninety-lilies-kick.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -'@rocket.chat/gazzodown': patch -'@rocket.chat/i18n': patch -'@rocket.chat/meteor': patch ---- - -Fixes Insert Timestamp relative time preview not updating on input changes and losing the user's locale after the first refresh tick. diff --git a/.changeset/orange-bottles-glow.md b/.changeset/orange-bottles-glow.md deleted file mode 100644 index ffc78906db762..0000000000000 --- a/.changeset/orange-bottles-glow.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@rocket.chat/i18n': patch -'@rocket.chat/meteor': patch ---- - -Fixes signed URL generation for S3 and Google Cloud Storage when the expiry setting is below 5 seconds, which previously caused expired or invalid preview URLs. Adds a dedicated URL expiry setting for Google Cloud Storage since it was incorrectly reusing the AWS S3 setting. diff --git a/.changeset/perky-tires-invite.md b/.changeset/perky-tires-invite.md deleted file mode 100644 index d3824c95cfca4..0000000000000 --- a/.changeset/perky-tires-invite.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Ensures the visitor token is not present in the visitors.info response diff --git a/.changeset/pink-moons-cheer.md b/.changeset/pink-moons-cheer.md deleted file mode 100644 index e753031cdb868..0000000000000 --- a/.changeset/pink-moons-cheer.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"@rocket.chat/meteor": minor -"@rocket.chat/apps-engine": minor -"@rocket.chat/apps": minor ---- - -Allows apps with the right permission to read room's ABAC attributes. diff --git a/.changeset/public-ravens-like.md b/.changeset/public-ravens-like.md deleted file mode 100644 index 95604fc9c8fcd..0000000000000 --- a/.changeset/public-ravens-like.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@rocket.chat/apps-engine': minor -'@rocket.chat/meteor': minor ---- - -Adds the capability for fetching a user by their sip extension to the apps diff --git a/.changeset/red-maps-wink.md b/.changeset/red-maps-wink.md deleted file mode 100644 index c6f130650b185..0000000000000 --- a/.changeset/red-maps-wink.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -'@rocket.chat/ui-client': minor -'@rocket.chat/i18n': minor -'@rocket.chat/meteor': minor ---- - -Adds a new "Drafts" group to the sidebar, providing quick access to all rooms with unfinished messages. -> This feature is available under the `Drafts in sidebar` feature preview and needs to be enabled in settings to be tested. \ No newline at end of file diff --git a/.changeset/rich-doodles-grow.md b/.changeset/rich-doodles-grow.md deleted file mode 100644 index 3699a28550a66..0000000000000 --- a/.changeset/rich-doodles-grow.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'@rocket.chat/model-typings': patch -'@rocket.chat/core-typings': patch -'@rocket.chat/models': patch -'@rocket.chat/i18n': patch -'@rocket.chat/meteor': patch ---- - -Security Hotfix (https://docs.rocket.chat/docs/security-fixes-and-updates) diff --git a/.changeset/room-search-index.md b/.changeset/room-search-index.md deleted file mode 100644 index b7832034ba5ba..0000000000000 --- a/.changeset/room-search-index.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -'@rocket.chat/meteor': minor -'@rocket.chat/models': minor ---- - -Adds the `USE_ROOM_SEARCH_INDEX` environment variable. When set to `true`, the messages collection's text index is created as `{ rid: 1, msg: 'text' }` instead of the default `{ msg: 'text' }`. The compound shape lets per-room `$text` searches use `rid` as a prefix, dramatically reducing the portion of the index scanned on workspaces where global search is disabled. - -The index is reconciled on every startup: if the existing text index already matches the desired shape, nothing happens; otherwise the stale text index is dropped and the desired one is recreated. Unsetting the variable on a later boot reverts to the default shape. diff --git a/.changeset/sanitize-image-element-url.md b/.changeset/sanitize-image-element-url.md deleted file mode 100644 index c2a3a18af8027..0000000000000 --- a/.changeset/sanitize-image-element-url.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@rocket.chat/gazzodown': patch -'@rocket.chat/meteor': patch ---- - -Sanitizes image URLs in rendered messages to block `javascript:`, `data:`, and `vbscript:` schemes — matching the protection already applied to markdown links. Defense-in-depth against XSS via crafted markdown like `![label](javascript:...)`. diff --git a/.changeset/sdk-account-event-handlers.md b/.changeset/sdk-account-event-handlers.md deleted file mode 100644 index ed7bb38fa2d46..0000000000000 --- a/.changeset/sdk-account-event-handlers.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/ddp-client': minor ---- - -Add lifecycle event handlers to `Account`: `onLogin`, `onLogout`, `onEmailVerificationLink`, and `onPageLoadLogin`. `onLogin` / `onLogout` fire on `uid` transitions (the setter now emits only when the value changes, so a single login or logout produces exactly one callback). `onEmailVerificationLink` and `onPageLoadLogin` are convenience wrappers around new `Emitter` events of the same names — fire them externally with `account.emit('emailVerificationLink', token)` / `account.emit('pageLoadLogin', loginAttempt)`. The bridge from Meteor's accounts-base lives in the consumer (`apps/meteor/client`) so the package stays Meteor-independent. All four handlers return an unsubscribe function. diff --git a/.changeset/shaggy-kiwis-burn.md b/.changeset/shaggy-kiwis-burn.md deleted file mode 100644 index 6a5834f65d4cf..0000000000000 --- a/.changeset/shaggy-kiwis-burn.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Ensures the autotranslate.translateMessage endpoint checks for room access diff --git a/.changeset/sharp-planets-throw.md b/.changeset/sharp-planets-throw.md deleted file mode 100644 index 19e01af823bcd..0000000000000 --- a/.changeset/sharp-planets-throw.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': patch ---- - -Fixes action buttons added by apps being rendered in the Marketplace Menu rather than the User Menu diff --git a/.changeset/spicy-phones-breathe.md b/.changeset/spicy-phones-breathe.md deleted file mode 100644 index 71bb6affc744b..0000000000000 --- a/.changeset/spicy-phones-breathe.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@rocket.chat/meteor": patch -"@rocket.chat/abac": patch ---- - -Fixes an issue where some actions made by the abac service were not broadcasting to clients, which affected reactivity diff --git a/.changeset/stale-needles-care.md b/.changeset/stale-needles-care.md deleted file mode 100644 index 5f9e5b4c893bd..0000000000000 --- a/.changeset/stale-needles-care.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/apps': minor ---- - -Receives the migration of internal files from @rocket.chat/apps-engine diff --git a/.changeset/ten-lizards-divide.md b/.changeset/ten-lizards-divide.md deleted file mode 100644 index e272a03e1fe04..0000000000000 --- a/.changeset/ten-lizards-divide.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -Fixes issue that displayed the 'Delete all closed chats' button when user lacks `remove-closed-livechat-rooms` permission diff --git a/.changeset/tidy-donuts-check.md b/.changeset/tidy-donuts-check.md deleted file mode 100644 index 5aeb2717a85bc..0000000000000 --- a/.changeset/tidy-donuts-check.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@rocket.chat/rest-typings': minor -'@rocket.chat/meteor': minor ---- - -Adds `freeSwitchExtension` as a query parameter for `api/v1/users.info` diff --git a/.changeset/tricky-kiwis-sit.md b/.changeset/tricky-kiwis-sit.md deleted file mode 100644 index eac1db7222c36..0000000000000 --- a/.changeset/tricky-kiwis-sit.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@rocket.chat/ui-kit': minor -'@rocket.chat/meteor': minor ---- - -Adds support to room information on ViewSubmit and ViewClose events for ContextualBar surface diff --git a/.changeset/use-format-date-fallback.md b/.changeset/use-format-date-fallback.md deleted file mode 100644 index 6cd6197f2e739..0000000000000 --- a/.changeset/use-format-date-fallback.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@rocket.chat/meteor": patch ---- - -Fixes a `date-fns` crash on routes that mount before the public settings stream finishes loading. `useFormatDate` was passing `String(undefined)` (the literal `"undefined"`) to `formatDate` while `Message_DateFormat` was momentarily unloaded — `date-fns` rejects that token because it contains an unescaped `n`. The hook now uses `'LL'` as the default token via `useSetting`'s second argument, so the formatter always receives a valid format string. diff --git a/.changeset/use-rc-sdk-transport-setting.md b/.changeset/use-rc-sdk-transport-setting.md deleted file mode 100644 index 7e43aa7437fda..0000000000000 --- a/.changeset/use-rc-sdk-transport-setting.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/meteor': minor ---- - -Adds a new admin setting `Use_RC_SDK` (General → Use Rocket.Chat SDK) that opts the workspace into the experimental SDK-over-DDP transport. When enabled, the client routes Meteor DDP traffic through `@rocket.chat/ddp-client` over a single WebSocket instead of the legacy Meteor stream. The flag is dormant by default; the server surfaces the value via a `` tag, and the client also honors a per-tab `?sdk_transport=on|off` URL parameter and a `rc-config-sdk_transport` localStorage key (URL > localStorage > meta tag). diff --git a/.changeset/witty-ravens-end.md b/.changeset/witty-ravens-end.md deleted file mode 100644 index 975623f6a1d8e..0000000000000 --- a/.changeset/witty-ravens-end.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@rocket.chat/media-calls': minor ---- - -Fixes a server error when Drachtio connection is lost while a SIP call is active diff --git a/.github/actions/update-version-durability/action.yml b/.github/actions/update-version-durability/action.yml index 07375ac383b87..85e4ec2f8fd64 100644 --- a/.github/actions/update-version-durability/action.yml +++ b/.github/actions/update-version-durability/action.yml @@ -14,6 +14,9 @@ inputs: D360_ARTICLE_ID: required: true description: Document360 Article ID + D360_USER_ID: + required: true + description: Document360 User ID used to fork and publish the article PUBLISH: required: true description: Publish Draft diff --git a/.github/actions/update-version-durability/index.js b/.github/actions/update-version-durability/index.js index d5fbeffb5de49..062f13e834d7d 100644 --- a/.github/actions/update-version-durability/index.js +++ b/.github/actions/update-version-durability/index.js @@ -11,6 +11,7 @@ import { Octokit } from '@octokit/rest'; const D360_TOKEN = core.getInput('D360_TOKEN'); const D360_ARTICLE_ID = core.getInput('D360_ARTICLE_ID'); +const D360_USER_ID = core.getInput('D360_USER_ID'); const PUBLISH = core.getInput('PUBLISH') === 'true'; const LTS_VERSIONS = (core.getInput('LTS_VERSIONS') || '7.10').split(',').map((v) => v.trim()); @@ -193,11 +194,15 @@ async function generateTable({ owner, repo } = {}) { const forkResponse = await requestDocument360('put', `Articles/${D360_ARTICLE_ID}/fork`, { lang_code: "en", - user_id: "2511fd00-9558-4826-8d8c-4cc0c110f89c", + user_id: D360_USER_ID, version_number: response.data.data.version_number, }); console.log(forkResponse.data); + + if (!forkResponse.data.success) { + throw new Error(`Failed to fork article: ${JSON.stringify(forkResponse.data.errors)}`); + } } console.log('Updating article'); @@ -211,7 +216,7 @@ async function generateTable({ owner, repo } = {}) { console.log('publishing article', updateResponse.data.data.version_number); const forkResponse = await requestDocument360('post', `Articles/${D360_ARTICLE_ID}/en/publish`, { - user_id: "2511fd00-9558-4826-8d8c-4cc0c110f89c", + user_id: D360_USER_ID, version_number: updateResponse.data.data.version_number, publish_message: 'Update support versions table via GitHub Action', }); diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 596ebed8c9002..fc3349487c58a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1100,3 +1100,4 @@ jobs: secrets: CI_PAT: ${{ secrets.CI_PAT }} D360_TOKEN: ${{ secrets.D360_TOKEN }} + D360_USER_ID: ${{ secrets.D360_USER_ID }} diff --git a/.github/workflows/update-version-durability.yml b/.github/workflows/update-version-durability.yml index 55addee753ed4..11fa82711ae1e 100644 --- a/.github/workflows/update-version-durability.yml +++ b/.github/workflows/update-version-durability.yml @@ -12,6 +12,8 @@ on: required: true D360_TOKEN: required: true + D360_USER_ID: + required: true jobs: update-versions: @@ -37,4 +39,5 @@ jobs: GH_TOKEN: ${{ secrets.CI_PAT }} D360_TOKEN: ${{ secrets.D360_TOKEN }} D360_ARTICLE_ID: 800f8d52-409d-478d-b560-f82a2c0eb7fb + D360_USER_ID: ${{ secrets.D360_USER_ID }} PUBLISH: true diff --git a/apps/meteor/CHANGELOG.md b/apps/meteor/CHANGELOG.md index 3c8f58e820083..58955034629d1 100644 --- a/apps/meteor/CHANGELOG.md +++ b/apps/meteor/CHANGELOG.md @@ -1,5 +1,398 @@ # @rocket.chat/meteor +## 8.5.0 + +### Minor Changes + +- ([#40343](https://github.com/RocketChat/Rocket.Chat/pull/40343)) Swap usage of internal @rocket.chat/apps-engine internal APIs to @rocket.chat/apps package + +- ([#40408](https://github.com/RocketChat/Rocket.Chat/pull/40408)) Adds 4 new permissions (assigned to admins by default) to control the visibility of each tab inside the ABAC Administration panel + +- ([#40341](https://github.com/RocketChat/Rocket.Chat/pull/40341)) Hides the room announcement, topic and description from the Administration > Rooms panel for ABAC managed rooms. In the channel sidebar Edit Channel form those fields stay visible to room members but are disabled, and the API rejects edits to them. + +- ([#39617](https://github.com/RocketChat/Rocket.Chat/pull/39617)) Adds new API endpoints `custom-sounds.create` and `custom-sounds.update` to manage custom sounds with strict file validation for size and specific MIME types to ensure system compatibility. + +- ([#40463](https://github.com/RocketChat/Rocket.Chat/pull/40463)) Allows apps with the right permission to read room's ABAC attributes. + +- ([#40604](https://github.com/RocketChat/Rocket.Chat/pull/40604)) Adds the capability for fetching a user by their sip extension to the apps + +- ([#38225](https://github.com/RocketChat/Rocket.Chat/pull/38225)) Adds a new "Drafts" group to the sidebar, providing quick access to all rooms with unfinished messages. + > This feature is available under the `Drafts in sidebar` feature preview and needs to be enabled in settings to be tested. +- ([#40397](https://github.com/RocketChat/Rocket.Chat/pull/40397)) Adds the `USE_ROOM_SEARCH_INDEX` environment variable. When set to `true`, the messages collection's text index is created as `{ rid: 1, msg: 'text' }` instead of the default `{ msg: 'text' }`. The compound shape lets per-room `$text` searches use `rid` as a prefix, dramatically reducing the portion of the index scanned on workspaces where global search is disabled. + + The index is reconciled on every startup: if the existing text index already matches the desired shape, nothing happens; otherwise the stale text index is dropped and the desired one is recreated. Unsetting the variable on a later boot reverts to the default shape. + +- ([#40612](https://github.com/RocketChat/Rocket.Chat/pull/40612)) Adds `freeSwitchExtension` as a query parameter for `api/v1/users.info` + +- ([#39858](https://github.com/RocketChat/Rocket.Chat/pull/39858)) Adds support to room information on ViewSubmit and ViewClose events for ContextualBar surface + +- ([#40430](https://github.com/RocketChat/Rocket.Chat/pull/40430)) Adds a new admin setting `Use_RC_SDK` (General → Use Rocket.Chat SDK) that opts the workspace into the experimental SDK-over-DDP transport. When enabled, the client routes Meteor DDP traffic through `@rocket.chat/ddp-client` over a single WebSocket instead of the legacy Meteor stream. The flag is dormant by default; the server surfaces the value via a `` tag, and the client also honors a per-tab `?sdk_transport=on|off` URL parameter and a `rc-config-sdk_transport` localStorage key (URL > localStorage > meta tag). + +### Patch Changes + +- ([#39858](https://github.com/RocketChat/Rocket.Chat/pull/39858)) Fixes an issue that prevented BlockAction interactions from having room information when triggered in a ContextualBar surface + +- ([#40524](https://github.com/RocketChat/Rocket.Chat/pull/40524)) Ensures OAuth tokens are cleaned up after user deactivation + +- Bump @rocket.chat/meteor version. + +- Bump @rocket.chat/meteor version. + +- Bump @rocket.chat/meteor version. + +- Bump @rocket.chat/meteor version. + +- Bump @rocket.chat/meteor version. + +- Bump @rocket.chat/meteor version. + +- Bump @rocket.chat/meteor version. + +- ([#40537](https://github.com/RocketChat/Rocket.Chat/pull/40537)) Fixes an issue that allowed a room converted from private to public (while abac is disabled) to retain its abac attributes (if any) + +- ([#39859](https://github.com/RocketChat/Rocket.Chat/pull/39859)) Fixes an issue where thread content would disappear after clicking "Jump to recent messages". + +- ([#40063](https://github.com/RocketChat/Rocket.Chat/pull/40063)) Fixes the missing edited indicator for the main parent message in the thread panel to ensure visual consistency with the main channel view. + +- ([#40357](https://github.com/RocketChat/Rocket.Chat/pull/40357)) Adds an accessible label to the system-messages multi-select in the channel edit panel so screen readers announce its purpose. + +- ([#40100](https://github.com/RocketChat/Rocket.Chat/pull/40100)) Fixes intermittent "Channel Not Joined" screen when opening rooms in embedded mode. + +- ([#40513](https://github.com/RocketChat/Rocket.Chat/pull/40513)) Fixes the `users.presence` endpoint returning an empty array when called with multiple comma-separated IDs, caused by `ajvQuery` coercing the string into a single-element array after the OpenAPI migration + +- ([#40496](https://github.com/RocketChat/Rocket.Chat/pull/40496)) Ensures that deactivated users have their login tokens cleaned up in users.deactivateidle + +- ([#40405](https://github.com/RocketChat/Rocket.Chat/pull/40405)) Disables SAML login when it is set to validate signatures without the proper configuration for it + +- ([#40423](https://github.com/RocketChat/Rocket.Chat/pull/40423)) Allows users to search for attribute values when assigning them to rooms + +- ([#40335](https://github.com/RocketChat/Rocket.Chat/pull/40335)) Fixes test button not playing default sound in Notifications Preferences + +- ([#40528](https://github.com/RocketChat/Rocket.Chat/pull/40528)) Ensures the Meteor method for translateMessage validates access and types + +- ([#40420](https://github.com/RocketChat/Rocket.Chat/pull/40420)) Fixes Insert Timestamp relative time preview not updating on input changes and losing the user's locale after the first refresh tick. + +- ([#40456](https://github.com/RocketChat/Rocket.Chat/pull/40456)) Fixes signed URL generation for S3 and Google Cloud Storage when the expiry setting is below 5 seconds, which previously caused expired or invalid preview URLs. Adds a dedicated URL expiry setting for Google Cloud Storage since it was incorrectly reusing the AWS S3 setting. + +- ([#40501](https://github.com/RocketChat/Rocket.Chat/pull/40501)) Ensures the visitor token is not present in the visitors.info response + +- ([#40405](https://github.com/RocketChat/Rocket.Chat/pull/40405)) Security Hotfix (https://docs.rocket.chat/docs/security-fixes-and-updates) + +- ([#40613](https://github.com/RocketChat/Rocket.Chat/pull/40613)) Sanitizes image URLs in rendered messages to block `javascript:`, `data:`, and `vbscript:` schemes — matching the protection already applied to markdown links. Defense-in-depth against XSS via crafted markdown like `![label](javascript:...)`. + +- ([#40508](https://github.com/RocketChat/Rocket.Chat/pull/40508)) Ensures the autotranslate.translateMessage endpoint checks for room access + +- ([#40448](https://github.com/RocketChat/Rocket.Chat/pull/40448)) Fixes action buttons added by apps being rendered in the Marketplace Menu rather than the User Menu + +- ([#40635](https://github.com/RocketChat/Rocket.Chat/pull/40635) by [@copilot-swe-agent](https://github.com/copilot-swe-agent)) Fixes the Chat Limits locking mechanism to allow bot agents to skip the lock as they aren't limited + +- ([#40499](https://github.com/RocketChat/Rocket.Chat/pull/40499)) Fixes an issue where some actions made by the abac service were not broadcasting to clients, which affected reactivity + +- ([#40492](https://github.com/RocketChat/Rocket.Chat/pull/40492)) Fixes issue that displayed the 'Delete all closed chats' button when user lacks `remove-closed-livechat-rooms` permission + +- ([#40393](https://github.com/RocketChat/Rocket.Chat/pull/40393)) Fixes a `date-fns` crash on routes that mount before the public settings stream finishes loading. `useFormatDate` was passing `String(undefined)` (the literal `"undefined"`) to `formatDate` while `Message_DateFormat` was momentarily unloaded — `date-fns` rejects that token because it contains an unescaped `n`. The hook now uses `'LL'` as the default token via `useSetting`'s second argument, so the formatter always receives a valid format string. + +-
Updated dependencies [90f15e32ae843ed146ccf711ee3201408d1e8731, f7d47dd3517ec14ca2ec5c3c95fcdf9e1e2fb8b0, cdb264fec803e234a6ad2000018b31d4b2074e99, 2a927fa1362c9d4bb04bb8e26f23a6e3753d9cea, bede0e2528bb053cb913e93ccf30d78a1c84bc76, bede0e2528bb053cb913e93ccf30d78a1c84bc76, bede0e2528bb053cb913e93ccf30d78a1c84bc76, 4c3984593017d59edd631bf8ae4f35f9d3c3db36, 7f2bdf1809804de7a95c54c3892da30f058ee13d, b6b04aadfcc8558f888b334e37c46a77e5816237, ad7d42400ea36f1eb0aaf7cc3361c77fdabf9ebc, 4704bf81ca370f120af32185a7c55407a26f8514, d427b808c1f79d9d1baa05bb5b5ef805b6ef5f6d, ebc9babf55dd26613027c28dcacf77909116b342, f392d5cc8d956c199f557dcd6beb52094232499d, 2198d9ea565b06f92e3dec29891890086f62f9df, fac64728505b312d5da786e92d3134450ce4a7c1, 12897e25d0dc25b7373f5264d38f38a5a7444257, e45585b70a3a7b75434c88e4b2ea9af0a0764a76, 0b7a76367d650793c271160e01798ebbb5fe0d26, 51833064591b91140d17e403389e1abbc5d9ef7a, 2d32e52073dd1a68bd12a093b3a673ae297cb4ee, 2a927fa1362c9d4bb04bb8e26f23a6e3753d9cea, b1c2668b74bfb49ebaefe2f581b2f8be5d4d1dd6, 90f15e32ae843ed146ccf711ee3201408d1e8731, 22c8d3283f0ea3004fe94c51f8bb32dfb40a0f4f]: + + - @rocket.chat/ui-kit@1.1.0 + - @rocket.chat/model-typings@2.3.0 + - @rocket.chat/models@2.3.0 + - @rocket.chat/i18n@3.1.0 + - @rocket.chat/apps-engine@1.63.0 + - @rocket.chat/ddp-client@1.1.0 + - @rocket.chat/rest-typings@8.5.0 + - @rocket.chat/ui-voip@21.0.0 + - @rocket.chat/gazzodown@31.0.0 + - @rocket.chat/apps@0.7.0 + - @rocket.chat/ui-client@31.0.0 + - @rocket.chat/core-typings@8.5.0 + - @rocket.chat/abac@0.2.1 + - @rocket.chat/media-calls@0.5.0 + - @rocket.chat/ui-composer@2.0.0 + - @rocket.chat/federation-matrix@0.1.4 + - @rocket.chat/network-broker@0.2.36 + - @rocket.chat/omni-core-ee@0.0.22 + - @rocket.chat/omnichannel-services@0.3.54 + - @rocket.chat/presence@0.2.57 + - @rocket.chat/core-services@0.14.1 + - @rocket.chat/cron@0.1.57 + - @rocket.chat/fuselage-ui-kit@31.0.0 + - @rocket.chat/instance-status@0.1.57 + - @rocket.chat/omni-core@0.1.1 + - @rocket.chat/server-fetch@0.2.1 + - @rocket.chat/ui-avatar@27.0.0 + - @rocket.chat/ui-contexts@31.0.0 + - @rocket.chat/ui-video-conf@31.0.0 + - @rocket.chat/web-ui-registration@31.0.0 +
+ +## 8.5.0-rc.6 + +### Patch Changes + +- Bump @rocket.chat/meteor version. + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.5.0-rc.6 + - @rocket.chat/rest-typings@8.5.0-rc.6 +
+ +## 8.5.0-rc.5 + +### Patch Changes + +- Bump @rocket.chat/meteor version. + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.5.0-rc.5 + - @rocket.chat/rest-typings@8.5.0-rc.5 +
+ +## 8.5.0-rc.4 + +### Patch Changes + +- Bump @rocket.chat/meteor version. +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.5.0-rc.4 + - @rocket.chat/rest-typings@8.5.0-rc.4 +
+ +## 8.5.0-rc.3 + +### Patch Changes + +- Bump @rocket.chat/meteor version. +- ([#40635](https://github.com/RocketChat/Rocket.Chat/pull/40635) by [@copilot-swe-agent](https://github.com/copilot-swe-agent)) Fixes the Chat Limits locking mechanism to allow bot agents to skip the lock as they aren't limited + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.5.0-rc.3 + - @rocket.chat/rest-typings@8.5.0-rc.3 +
+ +## 8.5.0-rc.2 + +### Patch Changes + +- Bump @rocket.chat/meteor version. + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.5.0-rc.2 + - @rocket.chat/rest-typings@8.5.0-rc.2 +
+ +## 8.5.0-rc.1 + +### Patch Changes + +- Bump @rocket.chat/meteor version. + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.5.0-rc.1 + - @rocket.chat/rest-typings@8.5.0-rc.1 +
+ +## 8.5.0-rc.0 + +### Minor Changes + +- ([#40343](https://github.com/RocketChat/Rocket.Chat/pull/40343)) Swap usage of internal @rocket.chat/apps-engine internal APIs to @rocket.chat/apps package + +- ([#40408](https://github.com/RocketChat/Rocket.Chat/pull/40408)) Adds 4 new permissions (assigned to admins by default) to control the visibility of each tab inside the ABAC Administration panel + +- ([#39760](https://github.com/RocketChat/Rocket.Chat/pull/39760)) ## Phishing-Resistant Multi-Factor Authentication + + Introduces a more secure and reliable server-side OAuth authentication flow. + + ### What’s New + + - **Improved OAuth login security** + OAuth authentication now happens fully on the server, reducing the risk of token theft, phishing attacks, and client-side credential interception. + - **Built-in CSRF, state validation, and PKCE protection** + OAuth logins now include stronger protection against CSRF attacks, request tampering, and authorization code interception through secure state validation and PKCE support. + - **Improved two-step verification with OAuth logins** + Users with email or TOTP two-factor authentication enabled will now be asked to complete 2FA even when signing in with providers like Google, GitHub, GitLab, and others. + - **Improved mobile & desktop app login** + Mobile and desktop apps now support a smoother and more secure deep-link OAuth login flow. + +- ([#40341](https://github.com/RocketChat/Rocket.Chat/pull/40341)) Hides the room announcement, topic and description from the Administration > Rooms panel for ABAC managed rooms. In the channel sidebar Edit Channel form those fields stay visible to room members but are disabled, and the API rejects edits to them. + +- ([#39617](https://github.com/RocketChat/Rocket.Chat/pull/39617)) Adds new API endpoints `custom-sounds.create` and `custom-sounds.update` to manage custom sounds with strict file validation for size and specific MIME types to ensure system compatibility. + +- ([#40463](https://github.com/RocketChat/Rocket.Chat/pull/40463)) Allows apps with the right permission to read room's ABAC attributes. + +- ([#40604](https://github.com/RocketChat/Rocket.Chat/pull/40604)) Adds the capability for fetching a user by their sip extension to the apps + +- ([#38225](https://github.com/RocketChat/Rocket.Chat/pull/38225)) Adds a new "Drafts" group to the sidebar, providing quick access to all rooms with unfinished messages. + > This feature is available under the `Drafts in sidebar` feature preview and needs to be enabled in settings to be tested. +- ([#40397](https://github.com/RocketChat/Rocket.Chat/pull/40397)) Adds the `USE_ROOM_SEARCH_INDEX` environment variable. When set to `true`, the messages collection's text index is created as `{ rid: 1, msg: 'text' }` instead of the default `{ msg: 'text' }`. The compound shape lets per-room `$text` searches use `rid` as a prefix, dramatically reducing the portion of the index scanned on workspaces where global search is disabled. + + The index is reconciled on every startup: if the existing text index already matches the desired shape, nothing happens; otherwise the stale text index is dropped and the desired one is recreated. Unsetting the variable on a later boot reverts to the default shape. + +- ([#40612](https://github.com/RocketChat/Rocket.Chat/pull/40612)) Adds `freeSwitchExtension` as a query parameter for `api/v1/users.info` + +- ([#39858](https://github.com/RocketChat/Rocket.Chat/pull/39858)) Adds support to room information on ViewSubmit and ViewClose events for ContextualBar surface + +- ([#40430](https://github.com/RocketChat/Rocket.Chat/pull/40430)) Adds a new admin setting `Use_RC_SDK` (General → Use Rocket.Chat SDK) that opts the workspace into the experimental SDK-over-DDP transport. When enabled, the client routes Meteor DDP traffic through `@rocket.chat/ddp-client` over a single WebSocket instead of the legacy Meteor stream. The flag is dormant by default; the server surfaces the value via a `` tag, and the client also honors a per-tab `?sdk_transport=on|off` URL parameter and a `rc-config-sdk_transport` localStorage key (URL > localStorage > meta tag). + +### Patch Changes + +- ([#39858](https://github.com/RocketChat/Rocket.Chat/pull/39858)) Fixes an issue that prevented BlockAction interactions from having room information when triggered in a ContextualBar surface + +- ([#40524](https://github.com/RocketChat/Rocket.Chat/pull/40524)) Ensures OAuth tokens are cleaned up after user deactivation + +- ([#40537](https://github.com/RocketChat/Rocket.Chat/pull/40537)) Fixes an issue that allowed a room converted from private to public (while abac is disabled) to retain its abac attributes (if any) + +- ([#39859](https://github.com/RocketChat/Rocket.Chat/pull/39859)) Fixes an issue where thread content would disappear after clicking "Jump to recent messages". + +- ([#40063](https://github.com/RocketChat/Rocket.Chat/pull/40063)) Fixes the missing edited indicator for the main parent message in the thread panel to ensure visual consistency with the main channel view. + +- ([#40357](https://github.com/RocketChat/Rocket.Chat/pull/40357)) Adds an accessible label to the system-messages multi-select in the channel edit panel so screen readers announce its purpose. + +- ([#40100](https://github.com/RocketChat/Rocket.Chat/pull/40100)) Fixes intermittent "Channel Not Joined" screen when opening rooms in embedded mode. + +- ([#40513](https://github.com/RocketChat/Rocket.Chat/pull/40513)) Fixes the `users.presence` endpoint returning an empty array when called with multiple comma-separated IDs, caused by `ajvQuery` coercing the string into a single-element array after the OpenAPI migration + +- ([#40496](https://github.com/RocketChat/Rocket.Chat/pull/40496)) Ensures that deactivated users have their login tokens cleaned up in users.deactivateidle + +- ([#40405](https://github.com/RocketChat/Rocket.Chat/pull/40405)) Disables SAML login when it is set to validate signatures without the proper configuration for it + +- ([#40423](https://github.com/RocketChat/Rocket.Chat/pull/40423)) Allows users to search for attribute values when assigning them to rooms + +- ([#40335](https://github.com/RocketChat/Rocket.Chat/pull/40335)) Fixes test button not playing default sound in Notifications Preferences + +- ([#40528](https://github.com/RocketChat/Rocket.Chat/pull/40528)) Ensures the Meteor method for translateMessage validates access and types + +- ([#40420](https://github.com/RocketChat/Rocket.Chat/pull/40420)) Fixes Insert Timestamp relative time preview not updating on input changes and losing the user's locale after the first refresh tick. + +- ([#40456](https://github.com/RocketChat/Rocket.Chat/pull/40456)) Fixes signed URL generation for S3 and Google Cloud Storage when the expiry setting is below 5 seconds, which previously caused expired or invalid preview URLs. Adds a dedicated URL expiry setting for Google Cloud Storage since it was incorrectly reusing the AWS S3 setting. + +- ([#40501](https://github.com/RocketChat/Rocket.Chat/pull/40501)) Ensures the visitor token is not present in the visitors.info response + +- ([#40405](https://github.com/RocketChat/Rocket.Chat/pull/40405)) Security Hotfix (https://docs.rocket.chat/docs/security-fixes-and-updates) + +- ([#40613](https://github.com/RocketChat/Rocket.Chat/pull/40613)) Sanitizes image URLs in rendered messages to block `javascript:`, `data:`, and `vbscript:` schemes — matching the protection already applied to markdown links. Defense-in-depth against XSS via crafted markdown like `![label](javascript:...)`. + +- ([#40508](https://github.com/RocketChat/Rocket.Chat/pull/40508)) Ensures the autotranslate.translateMessage endpoint checks for room access + +- ([#40448](https://github.com/RocketChat/Rocket.Chat/pull/40448)) Fixes action buttons added by apps being rendered in the Marketplace Menu rather than the User Menu + +- ([#40499](https://github.com/RocketChat/Rocket.Chat/pull/40499)) Fixes an issue where some actions made by the abac service were not broadcasting to clients, which affected reactivity + +- ([#40492](https://github.com/RocketChat/Rocket.Chat/pull/40492)) Fixes issue that displayed the 'Delete all closed chats' button when user lacks `remove-closed-livechat-rooms` permission + +- ([#40393](https://github.com/RocketChat/Rocket.Chat/pull/40393)) Fixes a `date-fns` crash on routes that mount before the public settings stream finishes loading. `useFormatDate` was passing `String(undefined)` (the literal `"undefined"`) to `formatDate` while `Message_DateFormat` was momentarily unloaded — `date-fns` rejects that token because it contains an unescaped `n`. The hook now uses `'LL'` as the default token via `useSetting`'s second argument, so the formatter always receives a valid format string. + +-
Updated dependencies [90f15e32ae843ed146ccf711ee3201408d1e8731, f7d47dd3517ec14ca2ec5c3c95fcdf9e1e2fb8b0, cdb264fec803e234a6ad2000018b31d4b2074e99, 2a927fa1362c9d4bb04bb8e26f23a6e3753d9cea, bede0e2528bb053cb913e93ccf30d78a1c84bc76, bede0e2528bb053cb913e93ccf30d78a1c84bc76, bede0e2528bb053cb913e93ccf30d78a1c84bc76, 4c3984593017d59edd631bf8ae4f35f9d3c3db36, 7f2bdf1809804de7a95c54c3892da30f058ee13d, ae9f740d6af20557eac61b4af902c868b4132b49, b6b04aadfcc8558f888b334e37c46a77e5816237, ad7d42400ea36f1eb0aaf7cc3361c77fdabf9ebc, 4704bf81ca370f120af32185a7c55407a26f8514, d427b808c1f79d9d1baa05bb5b5ef805b6ef5f6d, ebc9babf55dd26613027c28dcacf77909116b342, f392d5cc8d956c199f557dcd6beb52094232499d, 2198d9ea565b06f92e3dec29891890086f62f9df, fac64728505b312d5da786e92d3134450ce4a7c1, 12897e25d0dc25b7373f5264d38f38a5a7444257, e45585b70a3a7b75434c88e4b2ea9af0a0764a76, 0b7a76367d650793c271160e01798ebbb5fe0d26, 51833064591b91140d17e403389e1abbc5d9ef7a, 2d32e52073dd1a68bd12a093b3a673ae297cb4ee, 2a927fa1362c9d4bb04bb8e26f23a6e3753d9cea, b1c2668b74bfb49ebaefe2f581b2f8be5d4d1dd6, 90f15e32ae843ed146ccf711ee3201408d1e8731, 22c8d3283f0ea3004fe94c51f8bb32dfb40a0f4f]: + + - @rocket.chat/ui-kit@1.1.0-rc.0 + - @rocket.chat/model-typings@2.3.0-rc.0 + - @rocket.chat/models@2.3.0-rc.0 + - @rocket.chat/i18n@3.1.0-rc.0 + - @rocket.chat/apps-engine@1.63.0-rc.0 + - @rocket.chat/ddp-client@1.1.0-rc.0 + - @rocket.chat/rest-typings@8.5.0-rc.0 + - @rocket.chat/ui-voip@21.0.0-rc.0 + - @rocket.chat/web-ui-registration@31.0.0-rc.0 + - @rocket.chat/core-typings@8.5.0-rc.0 + - @rocket.chat/gazzodown@31.0.0-rc.0 + - @rocket.chat/apps@0.7.0-rc.0 + - @rocket.chat/ui-client@31.0.0-rc.0 + - @rocket.chat/abac@0.2.1-rc.0 + - @rocket.chat/media-calls@0.5.0-rc.0 + - @rocket.chat/core-services@0.14.1-rc.0 + - @rocket.chat/fuselage-ui-kit@31.0.0-rc.0 + - @rocket.chat/omnichannel-services@0.3.54-rc.0 + - @rocket.chat/federation-matrix@0.1.4-rc.0 + - @rocket.chat/omni-core-ee@0.0.22-rc.0 + - @rocket.chat/presence@0.2.57-rc.0 + - @rocket.chat/cron@0.1.57-rc.0 + - @rocket.chat/instance-status@0.1.57-rc.0 + - @rocket.chat/omni-core@0.1.1-rc.0 + - @rocket.chat/server-fetch@0.2.1-rc.0 + - @rocket.chat/ui-contexts@31.0.0-rc.0 + - @rocket.chat/ui-composer@2.0.0-rc.0 + - @rocket.chat/network-broker@0.2.36-rc.0 + - @rocket.chat/ui-avatar@27.0.0-rc.0 + - @rocket.chat/ui-video-conf@31.0.0-rc.0 + +
+ +## 8.4.3 + +### Patch Changes + +- Bump @rocket.chat/meteor version. +- Bump @rocket.chat/meteor version. + +- ([#40771](https://github.com/RocketChat/Rocket.Chat/pull/40771) by [@dionisio-bot](https://github.com/dionisio-bot)) Fixes the Chat Limits locking mechanism to allow bot agents to skip the lock as they aren't limited + +-
Updated dependencies []: + + - @rocket.chat/core-typings@8.4.3 + - @rocket.chat/rest-typings@8.4.3 +
+ +## 8.4.2 + +### Patch Changes + +- ([#40627](https://github.com/RocketChat/Rocket.Chat/pull/40627) by [@dionisio-bot](https://github.com/dionisio-bot)) Ensures OAuth tokens are cleaned up after user deactivation + +- Bump @rocket.chat/meteor version. + +- Bump @rocket.chat/meteor version. + +- ([#40527](https://github.com/RocketChat/Rocket.Chat/pull/40527) by [@dionisio-bot](https://github.com/dionisio-bot)) Fixes the `users.presence` endpoint returning an empty array when called with multiple comma-separated IDs, caused by `ajvQuery` coercing the string into a single-element array after the OpenAPI migration + +- ([#40559](https://github.com/RocketChat/Rocket.Chat/pull/40559) by [@dionisio-bot](https://github.com/dionisio-bot)) Ensures that deactivated users have their login tokens cleaned up in users.deactivateidle + +- ([#40539](https://github.com/RocketChat/Rocket.Chat/pull/40539) by [@dionisio-bot](https://github.com/dionisio-bot)) Ensures the Meteor method for translateMessage validates access and types + +- ([#40577](https://github.com/RocketChat/Rocket.Chat/pull/40577) by [@dionisio-bot](https://github.com/dionisio-bot)) Ensures the visitor token is not present in the visitors.info response + +- ([#40547](https://github.com/RocketChat/Rocket.Chat/pull/40547) by [@dionisio-bot](https://github.com/dionisio-bot)) Ensures the autotranslate.translateMessage endpoint checks for room access + +-
Updated dependencies [b0c593db9bc0bbbb603e673ddcdc48aad4f4e721, f422eb613d8cae43dc1e44d71b6ecb5a0a9c5d92, 3a3f0e1103bd0b8aaf93c16300ed664aed7a67a1]: + + - @rocket.chat/model-typings@2.2.2 + - @rocket.chat/models@2.2.2 + - @rocket.chat/rest-typings@8.4.2 + - @rocket.chat/core-typings@8.4.2 +
+ +## 8.4.1 + +### Patch Changes + +- Bump @rocket.chat/meteor version. + +### Patch Changes + +- Bump @rocket.chat/meteor version. +- Bump @rocket.chat/meteor version. + +- ([#40410](https://github.com/RocketChat/Rocket.Chat/pull/40410) by [@dionisio-bot](https://github.com/dionisio-bot)) Disables SAML login when it is set to validate signatures without the proper configuration for it + +- ([#40459](https://github.com/RocketChat/Rocket.Chat/pull/40459) by [@dionisio-bot](https://github.com/dionisio-bot)) Allows users to search for attribute values when assigning them to rooms + +- ([#40410](https://github.com/RocketChat/Rocket.Chat/pull/40410) by [@dionisio-bot](https://github.com/dionisio-bot)) Security Hotfix (https://docs.rocket.chat/docs/security-fixes-and-updates) + +-
Updated dependencies [5b291c38600757482aaf261a02487abdf5f14007]: + + - @rocket.chat/model-typings@2.2.1 + - @rocket.chat/core-typings@8.4.1 + - @rocket.chat/models@2.2.1 + - @rocket.chat/i18n@3.0.1 + - @rocket.chat/rest-typings@8.4.1 +
+ ## 8.4.0 ### Minor Changes diff --git a/apps/meteor/app/api/server/v1/custom-sounds.ts b/apps/meteor/app/api/server/v1/custom-sounds.ts index 4a33b3eb21bc1..6b68b260ae7f6 100644 --- a/apps/meteor/app/api/server/v1/custom-sounds.ts +++ b/apps/meteor/app/api/server/v1/custom-sounds.ts @@ -274,6 +274,13 @@ const customSoundsEndpoints = API.v1 : soundToUpdate.extension; try { + await insertOrUpdateSound({ + _id: fields._id, + name: fields.name, + extension: nextExtension, + previousName: soundToUpdate.name, + previousExtension: soundToUpdate.extension, + }); if (fileBuffer) { await uploadCustomSound(fileBuffer, computedMimeType, { _id: fields._id, @@ -282,13 +289,6 @@ const customSoundsEndpoints = API.v1 extension: nextExtension, }); } - await insertOrUpdateSound({ - _id: fields._id, - name: fields.name, - extension: nextExtension, - previousName: soundToUpdate.name, - previousExtension: soundToUpdate.extension, - }); return API.v1.success({}); } catch (error) { SystemLogger.error({ error }); diff --git a/apps/meteor/app/cloud/server/functions/syncWorkspace/handleCommsSync.ts b/apps/meteor/app/cloud/server/functions/syncWorkspace/handleCommsSync.ts index 4354be6d5bba0..a7617a5465fde 100644 --- a/apps/meteor/app/cloud/server/functions/syncWorkspace/handleCommsSync.ts +++ b/apps/meteor/app/cloud/server/functions/syncWorkspace/handleCommsSync.ts @@ -1,5 +1,5 @@ import { NPS, Banner } from '@rocket.chat/core-services'; -import type { Cloud, IBanner } from '@rocket.chat/core-typings'; +import type { Cloud, IBanner, Optional } from '@rocket.chat/core-typings'; import { getAndCreateNpsSurvey } from '../../../../../server/services/nps/getAndCreateNpsSurvey'; @@ -23,7 +23,7 @@ export const handleNpsOnWorkspaceSync = async (nps: Cloud.NpsSurveyAnnouncement) } }; -export const handleBannerOnWorkspaceSync = async (banners: IBanner[]) => { +export const handleBannerOnWorkspaceSync = async (banners: Optional[]) => { for (const banner of banners) { await Banner.create(banner); } diff --git a/apps/meteor/app/ui-master/server/scripts.ts b/apps/meteor/app/ui-master/server/scripts.ts index b7e423b51d655..485a4636a8da8 100644 --- a/apps/meteor/app/ui-master/server/scripts.ts +++ b/apps/meteor/app/ui-master/server/scripts.ts @@ -33,22 +33,7 @@ window.addEventListener('Custom_Script_On_Logout', function() { ${settings.get('Custom_Script_On_Logout')} }) -${ - settings.get('Accounts_ForgetUserSessionOnWindowClose') - ? ` -window.addEventListener('load', function() { - if (window.localStorage) { - Object.keys(window.localStorage).forEach(function(key) { - window.sessionStorage.setItem(key, window.localStorage.getItem(key)); - }); - window.localStorage.clear(); - Meteor._localStorage = window.sessionStorage; - Accounts.config({ clientStorage: 'session' }); - } -}); -` - : '' -}`; +${settings.get('Accounts_ForgetUserSessionOnWindowClose') ? `window.Accounts_ForgetUserSessionOnWindowClose = true;` : ''}`; settings.watchMultiple( ['Custom_Script_Logged_Out', 'Custom_Script_Logged_In', 'Custom_Script_On_Logout', 'Accounts_ForgetUserSessionOnWindowClose'], diff --git a/apps/meteor/client/components/CreateDiscussion/CreateDiscussion.tsx b/apps/meteor/client/components/CreateDiscussion/CreateDiscussion.tsx index 5557b01bf94ff..0c24e53cdffe2 100644 --- a/apps/meteor/client/components/CreateDiscussion/CreateDiscussion.tsx +++ b/apps/meteor/client/components/CreateDiscussion/CreateDiscussion.tsx @@ -124,7 +124,7 @@ const CreateDiscussion = ({ } + render={() => } /> )} {!defaultParentRoom && ( diff --git a/apps/meteor/client/components/TwoFactorModal/TwoFactorEmailModal.tsx b/apps/meteor/client/components/TwoFactorModal/TwoFactorEmailModal.tsx index 7c5e8e6ec94ab..8fc9c9df7bee2 100644 --- a/apps/meteor/client/components/TwoFactorModal/TwoFactorEmailModal.tsx +++ b/apps/meteor/client/components/TwoFactorModal/TwoFactorEmailModal.tsx @@ -2,6 +2,7 @@ import { Box, Button } from '@rocket.chat/fuselage'; import { FieldGroup, TextInput, Field, FieldLabel, FieldRow, FieldError } from '@rocket.chat/fuselage-forms'; import { GenericModal } from '@rocket.chat/ui-client'; import { useToastMessageDispatch, useEndpoint } from '@rocket.chat/ui-contexts'; +import { useEffect } from 'react'; import { useForm, Controller } from 'react-hook-form'; import { useTranslation } from 'react-i18next'; @@ -11,6 +12,7 @@ import { Method } from './TwoFactorModal'; type TwoFactorEmailModalProps = { onConfirm: OnConfirm; onClose: () => void; + invalidAttempt?: boolean; emailOrUsername: string; }; @@ -18,7 +20,7 @@ type TwoFactorEmailFormData = { code: string; }; -const TwoFactorEmailModal = ({ onConfirm, onClose, emailOrUsername }: TwoFactorEmailModalProps) => { +const TwoFactorEmailModal = ({ onConfirm, onClose, emailOrUsername, invalidAttempt }: TwoFactorEmailModalProps) => { const dispatchToastMessage = useToastMessageDispatch(); const { t } = useTranslation(); @@ -27,11 +29,21 @@ const TwoFactorEmailModal = ({ onConfirm, onClose, emailOrUsername }: TwoFactorE handleSubmit, setError, setValue, + clearErrors, formState: { errors, isSubmitting }, } = useForm({ defaultValues: { code: '' }, }); + useEffect(() => { + if (invalidAttempt) { + setError('code', { + type: 'manual', + message: t('Invalid_two_factor_code'), + }); + } + }, [invalidAttempt, setError, t]); + const sendEmailCode = useEndpoint('POST', '/v1/users.2fa.sendEmailCode'); const onClickResendCode = async (): Promise => { @@ -78,9 +90,13 @@ const TwoFactorEmailModal = ({ onConfirm, onClose, emailOrUsername }: TwoFactorE name='code' control={control} rules={{ required: t('Required_field', { field: t('Code') }) }} - render={({ field }) => ( + render={({ field: { onChange, ...fieldProps } }) => ( { + clearErrors('code'); + onChange(e); + }} placeholder={t('Enter_code_here')} autoComplete='one-time-code' inputMode='numeric' diff --git a/apps/meteor/client/components/TwoFactorModal/TwoFactorModal.tsx b/apps/meteor/client/components/TwoFactorModal/TwoFactorModal.tsx index ffcbcd865ea7b..40bd42706eefa 100644 --- a/apps/meteor/client/components/TwoFactorModal/TwoFactorModal.tsx +++ b/apps/meteor/client/components/TwoFactorModal/TwoFactorModal.tsx @@ -13,6 +13,7 @@ export type OnConfirm = (code: string, method: Method) => void | Promise; type TwoFactorModalProps = { onConfirm: OnConfirm; onClose: () => void; + invalidAttempt?: boolean; } & ( | { method: 'totp' | 'password'; @@ -23,19 +24,19 @@ type TwoFactorModalProps = { } ); -const TwoFactorModal = ({ onConfirm, onClose, ...props }: TwoFactorModalProps) => { +const TwoFactorModal = ({ onConfirm, onClose, invalidAttempt, ...props }: TwoFactorModalProps) => { if (props.method === Method.TOTP) { - return ; + return ; } if (props.method === Method.EMAIL) { const { emailOrUsername } = props; - return ; + return ; } if (props.method === Method.PASSWORD) { - return ; + return ; } throw new Error('Invalid Two Factor method'); diff --git a/apps/meteor/client/components/TwoFactorModal/TwoFactorPasswordModal.tsx b/apps/meteor/client/components/TwoFactorModal/TwoFactorPasswordModal.tsx index 7100f58fbcd01..33fe3a7db7a73 100644 --- a/apps/meteor/client/components/TwoFactorModal/TwoFactorPasswordModal.tsx +++ b/apps/meteor/client/components/TwoFactorModal/TwoFactorPasswordModal.tsx @@ -1,6 +1,7 @@ import { Box } from '@rocket.chat/fuselage'; import { PasswordInput, FieldGroup, Field, FieldLabel, FieldRow, FieldError } from '@rocket.chat/fuselage-forms'; import { GenericModal } from '@rocket.chat/ui-client'; +import { useEffect } from 'react'; import { useForm, Controller } from 'react-hook-form'; import { useTranslation } from 'react-i18next'; @@ -10,13 +11,14 @@ import { Method } from './TwoFactorModal'; type TwoFactorPasswordModalProps = { onConfirm: OnConfirm; onClose: () => void; + invalidAttempt?: boolean; }; type TwoFactorPasswordFormData = { password: string; }; -const TwoFactorPasswordModal = ({ onConfirm, onClose }: TwoFactorPasswordModalProps) => { +const TwoFactorPasswordModal = ({ onConfirm, onClose, invalidAttempt }: TwoFactorPasswordModalProps) => { const { t } = useTranslation(); const { @@ -24,11 +26,21 @@ const TwoFactorPasswordModal = ({ onConfirm, onClose }: TwoFactorPasswordModalPr handleSubmit, setError, setValue, + clearErrors, formState: { errors, isSubmitting }, } = useForm({ defaultValues: { password: '' }, }); + useEffect(() => { + if (invalidAttempt) { + setError('password', { + type: 'manual', + message: t('Invalid_password'), + }); + } + }, [invalidAttempt, setError, t]); + const onSubmit = handleSubmit(async ({ password }) => { try { await onConfirm(password, Method.PASSWORD); @@ -60,8 +72,17 @@ const TwoFactorPasswordModal = ({ onConfirm, onClose }: TwoFactorPasswordModalPr name='password' control={control} rules={{ required: t('Required_field', { field: t('Password') }) }} - render={({ field }) => ( - + render={({ field: { onChange, ...fieldProps } }) => ( + { + clearErrors('password'); + onChange(e); + }} + placeholder={t('Password')} + disabled={isSubmitting} + error={errors.password?.message} + /> )} /> diff --git a/apps/meteor/client/components/TwoFactorModal/TwoFactorTotpModal.tsx b/apps/meteor/client/components/TwoFactorModal/TwoFactorTotpModal.tsx index 3eb2a7f62004d..65f8fe00d440d 100644 --- a/apps/meteor/client/components/TwoFactorModal/TwoFactorTotpModal.tsx +++ b/apps/meteor/client/components/TwoFactorModal/TwoFactorTotpModal.tsx @@ -1,6 +1,7 @@ import { Box } from '@rocket.chat/fuselage'; import { FieldGroup, TextInput, Field, FieldLabel, FieldRow, FieldError } from '@rocket.chat/fuselage-forms'; import { GenericModal } from '@rocket.chat/ui-client'; +import { useEffect } from 'react'; import { useForm, Controller } from 'react-hook-form'; import { useTranslation } from 'react-i18next'; @@ -11,13 +12,14 @@ type TwoFactorTotpModalProps = { onConfirm: OnConfirm; onClose: () => void; onDismiss?: () => void; + invalidAttempt?: boolean; }; type TwoFactorTotpFormData = { code: string; }; -const TwoFactorTotpModal = ({ onConfirm, onClose, onDismiss }: TwoFactorTotpModalProps) => { +const TwoFactorTotpModal = ({ onConfirm, onClose, onDismiss, invalidAttempt }: TwoFactorTotpModalProps) => { const { t } = useTranslation(); const { @@ -25,11 +27,21 @@ const TwoFactorTotpModal = ({ onConfirm, onClose, onDismiss }: TwoFactorTotpModa handleSubmit, setError, setValue, + clearErrors, formState: { errors, isSubmitting }, } = useForm({ defaultValues: { code: '' }, }); + useEffect(() => { + if (invalidAttempt) { + setError('code', { + type: 'manual', + message: t('Invalid_two_factor_code'), + }); + } + }, [invalidAttempt, setError, t]); + const onSubmit = handleSubmit(async ({ code }) => { try { await onConfirm(code, Method.TOTP); @@ -63,9 +75,13 @@ const TwoFactorTotpModal = ({ onConfirm, onClose, onDismiss }: TwoFactorTotpModa name='code' control={control} rules={{ required: t('Required_field', { field: t('Code') }) }} - render={({ field }) => ( + render={({ field: { onChange, ...fieldProps } }) => ( { + clearErrors('code'); + onChange(e); + }} placeholder={t('Enter_code_here')} autoComplete='one-time-code' inputMode='numeric' diff --git a/apps/meteor/client/components/message/toolbar/useReplyInDMAction.spec.ts b/apps/meteor/client/components/message/toolbar/useReplyInDMAction.spec.ts new file mode 100644 index 0000000000000..5542098c4c6fd --- /dev/null +++ b/apps/meteor/client/components/message/toolbar/useReplyInDMAction.spec.ts @@ -0,0 +1,86 @@ +import { mockAppRoot } from '@rocket.chat/mock-providers'; +import { renderHook } from '@testing-library/react'; + +import { useReplyInDMAction } from './useReplyInDMAction'; +import { createFakeMessage, createFakeRoom, createFakeSubscription, createFakeUser } from '../../../../tests/mocks/data'; +import { roomCoordinator } from '../../../lib/rooms/roomCoordinator'; + +jest.mock('../../../lib/rooms/roomCoordinator', () => ({ + roomCoordinator: { + openRouteLink: jest.fn(), + }, +})); + +const mockedOpenRouteLink = jest.mocked(roomCoordinator.openRouteLink); + +const currentUser = createFakeUser({ + _id: 'current-user-id', + username: 'currentuser', +}); + +const messageAuthor = { + _id: 'author-user-id', + username: 'authoruser', + name: 'Author User', +}; + +const message = createFakeMessage({ + _id: 'reply-message-id', + u: messageAuthor, +}); + +const room = createFakeRoom({ + _id: 'channel-id', + t: 'c', + name: 'general', +}); + +const subscription = createFakeSubscription({ + rid: 'channel-id', + t: 'c', +}); + +afterEach(() => { + jest.clearAllMocks(); +}); + +describe('useReplyInDMAction', () => { + it('should not carry over the msg search parameter when opening a direct message', () => { + const getSearchParameters = jest.fn().mockReturnValue({ + msg: 'stale-message-id', + layout: 'embedded', + }); + + const { result } = renderHook(() => useReplyInDMAction(message, { room, subscription }), { + wrapper: mockAppRoot().withUser(currentUser).withPermission('create-d').withRouter({ getSearchParameters }).build(), + }); + + expect(result.current).not.toBeNull(); + + result.current?.action({ stopPropagation: jest.fn() } as unknown as UIEvent); + + expect(getSearchParameters).toHaveBeenCalled(); + expect(mockedOpenRouteLink).toHaveBeenCalledWith( + 'd', + { name: messageAuthor.username }, + { + layout: 'embedded', + reply: 'reply-message-id', + }, + ); + + const searchParams = mockedOpenRouteLink.mock.calls[0]?.[2]; + expect(searchParams).not.toHaveProperty('msg'); + }); + + it('should return null when already in a direct message room', () => { + const dmRoom = createFakeRoom({ t: 'd' }); + const dmSubscription = createFakeSubscription({ t: 'd' }); + + const { result } = renderHook(() => useReplyInDMAction(message, { room: dmRoom, subscription: dmSubscription }), { + wrapper: mockAppRoot().withUser(currentUser).withPermission('create-d').build(), + }); + + expect(result.current).toBeNull(); + }); +}); diff --git a/apps/meteor/client/components/message/toolbar/useReplyInDMAction.ts b/apps/meteor/client/components/message/toolbar/useReplyInDMAction.ts index dd10e3f56c6af..be05dad70f103 100644 --- a/apps/meteor/client/components/message/toolbar/useReplyInDMAction.ts +++ b/apps/meteor/client/components/message/toolbar/useReplyInDMAction.ts @@ -71,11 +71,12 @@ export const useReplyInDMAction = ( context: ['message', 'message-mobile', 'threads', 'federated'], type: 'communication', action() { + const { msg: _, ...searchParameters } = router.getSearchParameters(); roomCoordinator.openRouteLink( 'd', { name: message.u.username }, { - ...router.getSearchParameters(), + ...searchParameters, reply: message._id, }, ); diff --git a/apps/meteor/client/lib/2fa/process2faReturn.ts b/apps/meteor/client/lib/2fa/process2faReturn.ts index 50a0d729d770b..c8b4e5cce34a1 100644 --- a/apps/meteor/client/lib/2fa/process2faReturn.ts +++ b/apps/meteor/client/lib/2fa/process2faReturn.ts @@ -18,7 +18,7 @@ const isTwoFactorMethod = (method: string): method is TwoFactorMethod => twoFact const hasRequiredTwoFactorMethod = ( error: MeteorErrorLike, ): error is MeteorErrorLike & { details: { method: TwoFactorMethod; emailOrUsername?: string } } => { - const details = error.details as unknown; + const { details } = error; return ( typeof details === 'object' && @@ -124,10 +124,12 @@ export const invokeTwoFactorModal = async ( props: { method: 'totp' | 'email' | 'password'; emailOrUsername?: string | undefined; + invalidAttempt?: boolean; }, validateCode?: (code: string, method: string) => Promise, ) => { - assertModalProps(props); + const { invalidAttempt, ...restProps } = props; + assertModalProps(restProps); return new Promise((resolve, reject) => { let isResolved = false; @@ -136,14 +138,15 @@ export const invokeTwoFactorModal = async ( imperativeModal.open({ component: TwoFactorModal, props: { - ...props, + ...restProps, onConfirm: async (code: string, method: string): Promise => { + const actualCode = method === 'password' ? SHA256(code) : code; if (validateCode) { - await validateCode(code, method); + await validateCode(actualCode, method); } isResolved = true; imperativeModal.close(); - resolve(method === 'password' ? SHA256(code) : code); + resolve(actualCode); }, onClose: (): void => { if (isClosed) { @@ -161,6 +164,7 @@ export const invokeTwoFactorModal = async ( reject(new Error('totp-canceled')); } }, + ...(invalidAttempt && { invalidAttempt }), }, }); }); diff --git a/apps/meteor/client/lib/chats/flows/replyBroadcast.spec.ts b/apps/meteor/client/lib/chats/flows/replyBroadcast.spec.ts new file mode 100644 index 0000000000000..d94a9df5ff95e --- /dev/null +++ b/apps/meteor/client/lib/chats/flows/replyBroadcast.spec.ts @@ -0,0 +1,59 @@ +import { replyBroadcast } from './replyBroadcast'; +import { createFakeMessage } from '../../../../tests/mocks/data'; +import { router } from '../../../providers/RouterProvider'; +import { roomCoordinator } from '../../rooms/roomCoordinator'; +import type { ChatAPI } from '../ChatAPI'; + +jest.mock('../../rooms/roomCoordinator', () => ({ + roomCoordinator: { + openRouteLink: jest.fn(), + }, +})); + +jest.mock('../../../providers/RouterProvider', () => ({ + router: { + getSearchParameters: jest.fn(), + }, +})); + +const mockedOpenRouteLink = jest.mocked(roomCoordinator.openRouteLink); +const mockedGetSearchParameters = jest.mocked(router.getSearchParameters); + +const messageAuthor = { + _id: 'author-user-id', + username: 'authoruser', + name: 'Author User', +}; + +const message = createFakeMessage({ + _id: 'reply-message-id', + u: messageAuthor, +}); + +afterEach(() => { + jest.clearAllMocks(); +}); + +describe('replyBroadcast', () => { + it('should not carry over the msg search parameter when opening a direct message', async () => { + mockedGetSearchParameters.mockReturnValue({ + msg: 'stale-message-id', + layout: 'embedded', + }); + + await replyBroadcast({} as ChatAPI, message); + + expect(mockedGetSearchParameters).toHaveBeenCalled(); + expect(mockedOpenRouteLink).toHaveBeenCalledWith( + 'd', + { name: messageAuthor.username }, + { + layout: 'embedded', + reply: 'reply-message-id', + }, + ); + + const searchParams = mockedOpenRouteLink.mock.calls[0]?.[2]; + expect(searchParams).not.toHaveProperty('msg'); + }); +}); diff --git a/apps/meteor/client/lib/chats/flows/replyBroadcast.ts b/apps/meteor/client/lib/chats/flows/replyBroadcast.ts index 69e857ee57cb3..9d58654ae647a 100644 --- a/apps/meteor/client/lib/chats/flows/replyBroadcast.ts +++ b/apps/meteor/client/lib/chats/flows/replyBroadcast.ts @@ -5,11 +5,12 @@ import { roomCoordinator } from '../../rooms/roomCoordinator'; import type { ChatAPI } from '../ChatAPI'; export const replyBroadcast = async (_chat: ChatAPI, message: IMessage) => { + const { msg: _, ...searchParameters } = router.getSearchParameters(); roomCoordinator.openRouteLink( 'd', { name: message.u.username }, { - ...router.getSearchParameters(), + ...searchParameters, reply: message._id, }, ); diff --git a/apps/meteor/client/lib/chats/readStateManager.ts b/apps/meteor/client/lib/chats/readStateManager.ts index e62ba45e1ae7d..0639fd893ec4e 100644 --- a/apps/meteor/client/lib/chats/readStateManager.ts +++ b/apps/meteor/client/lib/chats/readStateManager.ts @@ -72,7 +72,8 @@ export class ReadStateManager extends Emitter { (record) => record.rid === this.subscription?.rid && record.ts.getTime() > (this.subscription.ls?.getTime() ?? 0) && - record.u._id !== getUserId(), + record.u._id !== getUserId() && + (!record.tmid || record.tshow === true), (a, b) => a.ts.getTime() - b.ts.getTime(), ); diff --git a/apps/meteor/client/lib/e2ee/rocketchat.e2e.spec.ts b/apps/meteor/client/lib/e2ee/rocketchat.e2e.spec.ts new file mode 100644 index 0000000000000..65cb44c921df5 --- /dev/null +++ b/apps/meteor/client/lib/e2ee/rocketchat.e2e.spec.ts @@ -0,0 +1,70 @@ +import { imperativeModal } from '@rocket.chat/ui-client'; + +import * as banners from '../banners'; +import { e2e } from './rocketchat.e2e'; +import { dispatchToastMessage } from '../toast'; + +jest.mock('@rocket.chat/ui-client', () => ({ + imperativeModal: { + open: jest.fn(), + close: jest.fn(), + }, +})); + +jest.mock('../../../app/utils/client', () => ({ + getUserAvatarURL: jest.fn(), +})); + +jest.mock('../../../app/utils/lib/i18n', () => ({ + t: (key: string) => key, +})); + +jest.mock('../toast', () => ({ + dispatchToastMessage: jest.fn(), +})); + +jest.mock('../banners', () => ({ + closeById: jest.fn(), + open: jest.fn(), +})); + +describe('E2E password modal', () => { + const getModalProps = () => (imperativeModal.open as jest.Mock).mock.calls.at(-1)?.[0].props; + + afterEach(() => { + jest.restoreAllMocks(); + jest.clearAllMocks(); + }); + + it('keeps the E2EE alert open when the modal header close button is used', () => { + e2e.openEnterE2EEPasswordModal(jest.fn()); + + getModalProps().onClose(); + + expect(imperativeModal.close).toHaveBeenCalledTimes(1); + expect(banners.closeById).not.toHaveBeenCalled(); + }); + + it('dismisses the E2EE alert when the user explicitly cancels entering the password', () => { + e2e.openEnterE2EEPasswordModal(jest.fn()); + + getModalProps().onCancel(); + + expect(dispatchToastMessage).toHaveBeenCalledWith({ type: 'info', message: 'End_To_End_Encryption_Not_Enabled' }); + expect(imperativeModal.close).toHaveBeenCalledTimes(1); + expect(banners.closeById).toHaveBeenCalledWith('e2e'); + }); + + it('dismisses the E2EE alert after the password is entered successfully', async () => { + const onEnterE2EEPassword = jest.fn().mockResolvedValue(undefined); + + e2e.openEnterE2EEPasswordModal(onEnterE2EEPassword); + + await getModalProps().onConfirm('password'); + + expect(onEnterE2EEPassword).toHaveBeenCalledWith('password'); + expect(dispatchToastMessage).toHaveBeenCalledWith({ type: 'success', message: 'E2E_encryption_enabled' }); + expect(imperativeModal.close).toHaveBeenCalledTimes(1); + expect(banners.closeById).toHaveBeenCalledWith('e2e'); + }); +}); diff --git a/apps/meteor/client/lib/e2ee/rocketchat.e2e.ts b/apps/meteor/client/lib/e2ee/rocketchat.e2e.ts index ae6e90498f2b4..6562dc384e36f 100644 --- a/apps/meteor/client/lib/e2ee/rocketchat.e2e.ts +++ b/apps/meteor/client/lib/e2ee/rocketchat.e2e.ts @@ -524,6 +524,9 @@ class E2E extends Emitter { openEnterE2EEPasswordModal(onEnterE2EEPassword: (password: string) => Promise) { const close = () => { + imperativeModal.close(); + }; + const dismiss = () => { this.closeAlert(); imperativeModal.close(); }; @@ -534,12 +537,12 @@ class E2E extends Emitter { onCancel: () => { failedToDecodeKey = false; dispatchToastMessage({ type: 'info', message: t('End_To_End_Encryption_Not_Enabled') }); - close(); + dismiss(); }, onConfirm: async (password) => { await onEnterE2EEPassword(password); dispatchToastMessage({ type: 'success', message: t('E2E_encryption_enabled') }); - close(); + dismiss(); }, }, }); diff --git a/apps/meteor/client/lib/sdk/ddpSdk.ts b/apps/meteor/client/lib/sdk/ddpSdk.ts index 35ed4169e29e3..b8e5d3d17914e 100644 --- a/apps/meteor/client/lib/sdk/ddpSdk.ts +++ b/apps/meteor/client/lib/sdk/ddpSdk.ts @@ -3,7 +3,7 @@ import EJSON from 'ejson'; import { Accounts } from 'meteor/accounts-base'; import { Meteor } from 'meteor/meteor'; -import { createMeteorBackedSdk } from './meteorBackedSdk'; +import { createMeteorBackedSdk, createMeteorBackedStorage } from './meteorBackedSdk'; import { isSdkTransportEnabled } from './sdkTransportEnabled'; import { getRootUrl } from '../meteorRuntimeConfig'; import { STORAGE_KEYS, getStoredItem, removeStoredItem } from './storage'; @@ -53,6 +53,14 @@ export const getDdpSdk = (): DDPSDK => { if (!instance) { if (sdkTransportEnabled) { instance = DDPSDK.create(computeDdpUrl()); + // TODO: This is a temporary fix to ensure Accounts/Meteor and Update Session On Window Close work together. + try { + instance.storage = createMeteorBackedStorage(); + } catch (error) { + // DDPSDK.create may return a sealed/frozen instance under strict mode; failing + // to attach the storage hook must not abort SDK bootstrap. + console.warn('[ddpSdk] failed to attach storage hook to SDK instance', error); + } applyEjsonEncoding(instance); void startConnect(instance); } else { @@ -143,22 +151,41 @@ export const ensureConnectedAndAuthenticated = async (): Promise => { // latter dispatches a `logout` method which itself races against // parallel re-auth flows in CI's parallel-shard environment and // kicked otherwise-healthy tests out. - removeStoredItem(STORAGE_KEYS.USER_ID); - removeStoredItem(STORAGE_KEYS.LOGIN_TOKEN); - removeStoredItem(STORAGE_KEYS.LOGIN_TOKEN_EXPIRES); - Meteor.connection.setUserId(null); + clearStoredCredentials(); return; } console.warn('[ddpSdk] loginWithToken failed', error); } }; -const isAuthError = (error: unknown): boolean => { +/** + * Drop the local session credentials without dispatching Meteor's `logout` + * method. Nulling the connection userId propagates through the + * Accounts.connection.userId() Tracker.autorun (see overrides/userAndUsers.ts) + * into the userIdStore, so `useUserId()` becomes undefined and the router falls + * through to LoginPage. We avoid `Meteor.logout()` on purpose: it dispatches a + * `logout` method that races parallel re-auth flows (fresh registration, + * Meteor's own resume) and has kicked otherwise-healthy sessions/tests out. + */ +export const clearStoredCredentials = (): void => { + removeStoredItem(STORAGE_KEYS.USER_ID); + removeStoredItem(STORAGE_KEYS.LOGIN_TOKEN); + removeStoredItem(STORAGE_KEYS.LOGIN_TOKEN_EXPIRES); + Meteor.connection.setUserId(null); +}; + +export const isAuthError = (error: unknown): boolean => { if (!error || typeof error !== 'object') return false; - const e = error as { error?: unknown; reason?: unknown }; + const e = error as { error?: unknown; reason?: unknown; status?: unknown; statusCode?: unknown }; return ( e.error === 401 || e.error === 403 || + // REST-shaped failures (e.g. sdk.rest.get('/v1/me'), userData stream + // `nosub`) surface the HTTP status instead of a DDP `error` code. + e.status === 401 || + e.status === 403 || + e.statusCode === 401 || + e.statusCode === 403 || e.reason === 'User not found' || e.reason === 'Login token expired' || e.reason === 'You are not allowed to use this token' diff --git a/apps/meteor/client/lib/sdk/meteorBackedSdk.ts b/apps/meteor/client/lib/sdk/meteorBackedSdk.ts index 7ad4b60209f82..95585963d5353 100644 --- a/apps/meteor/client/lib/sdk/meteorBackedSdk.ts +++ b/apps/meteor/client/lib/sdk/meteorBackedSdk.ts @@ -5,6 +5,7 @@ import { Meteor } from 'meteor/meteor'; import { Tracker } from 'meteor/tracker'; import { parseDDP } from './ddpProtocol'; +import { setStorageBackend } from './storage'; /** * Meteor-backed pass-through DDPSDK used when the SDK transport is OFF. @@ -271,12 +272,63 @@ const createMeteorBackedAccount = () => { } as unknown as DDPSDK['account']; }; +export const createMeteorBackedStorage = () => { + let appliedBackend: 'local' | 'session' | undefined; + + return { + changeStorageBackend: () => { + const backend: 'local' | 'session' = window[FORGET_SESSION_SETTING_ID] ? 'session' : 'local'; + + if (appliedBackend === backend) { + return; + } + + if (!setStorageBackend(backend)) { + return; + } + + (Meteor._localStorage as unknown as Storage) = backend === 'session' ? window.sessionStorage : window.localStorage; + + try { + Accounts.config({ clientStorage: backend }); + } catch (error) { + // Accounts.config throws when invoked twice with a conflicting value. Meteor's + // own boot may have already set clientStorage; the _localStorage reassign above + // is what actually switches the backend Meteor reads from, so swallow. + console.warn('[storage] Accounts.config(clientStorage) refused at runtime', error); + } + + appliedBackend = backend; + }, + }; +}; + +export const FORGET_SESSION_SETTING_ID = 'Accounts_ForgetUserSessionOnWindowClose'; + +declare global { + // eslint-disable-next-line @typescript-eslint/naming-convention + interface Window { + [FORGET_SESSION_SETTING_ID]?: boolean; + } +} + +declare module '@rocket.chat/ddp-client' { + // eslint-disable-next-line @typescript-eslint/naming-convention + interface DDPSDK { + storage: { + changeStorageBackend: () => void; + }; + } +} + export const createMeteorBackedSdk = (): DDPSDK => { const connection = createMeteorBackedConnection(); const client = createMeteorBackedClient(); const account = createMeteorBackedAccount(); + const storage = createMeteorBackedStorage(); return { + storage, connection, client, account, diff --git a/apps/meteor/client/lib/sdk/storage.ts b/apps/meteor/client/lib/sdk/storage.ts index 03e437d16959f..b2aa37dd3d5bf 100644 --- a/apps/meteor/client/lib/sdk/storage.ts +++ b/apps/meteor/client/lib/sdk/storage.ts @@ -14,10 +14,83 @@ export const STORAGE_KEYS = { export type StorageKey = (typeof STORAGE_KEYS)[keyof typeof STORAGE_KEYS]; -const getStorage = (): Storage | undefined => (typeof window !== 'undefined' ? window.localStorage : undefined); +type StorageBackend = 'local' | 'session'; -export const getStoredItem = (key: string): string | null => getStorage()?.getItem(key) ?? null; +const getStorageForBackend = (backend: StorageBackend): Storage | undefined => { + if (typeof window === 'undefined') { + return undefined; + } -export const setStoredItem = (key: string, value: string): void => getStorage()?.setItem(key, value); + try { + return backend === 'session' ? window.sessionStorage : window.localStorage; + } catch { + return undefined; + } +}; -export const removeStoredItem = (key: string): void => getStorage()?.removeItem(key); +const getStorage = (): Storage | undefined => { + return getStorageForBackend(storageBackend); +}; + +export const getStoredItem = (key: StorageKey): string | null => getStorage()?.getItem(key) ?? null; + +export const setStoredItem = (key: StorageKey, value: string): void => getStorage()?.setItem(key, value); + +export const removeStoredItem = (key: StorageKey): void => getStorage()?.removeItem(key); + +let storageBackend: StorageBackend = 'local'; + +export const setStorageBackend = (backend: StorageBackend): boolean => { + if (backend === storageBackend) { + return true; + } + + if (!moveLoginKeys(backend)) { + return false; + } + + storageBackend = backend; + return true; +}; + +const moveLoginKeys = (backend: StorageBackend): boolean => { + const keys = [ + STORAGE_KEYS.USER_ID, + STORAGE_KEYS.LOGIN_TOKEN, + STORAGE_KEYS.LOGIN_TOKEN_EXPIRES, + STORAGE_KEYS.E2EE_PUBLIC_KEY, + STORAGE_KEYS.E2EE_PRIVATE_KEY, + STORAGE_KEYS.E2EE_RANDOM_PASSWORD, + ]; + + const sourceStorage = getStorageForBackend(backend === 'session' ? 'local' : 'session'); + const targetStorage = getStorageForBackend(backend); + + if (!sourceStorage || !targetStorage) { + console.warn('Unable to switch storage backend because source or target storage is unavailable'); + return false; + } + + for (const key of keys) { + let value: string | null; + try { + value = sourceStorage.getItem(key); + } catch { + continue; + } + + if (value === null) { + continue; + } + + try { + targetStorage.setItem(key, value); + sourceStorage.removeItem(key); + } catch { + continue; + } + } + sourceStorage.clear(); + + return true; +}; diff --git a/apps/meteor/client/lib/utils/setMessageJumpQueryStringParameter.ts b/apps/meteor/client/lib/utils/setMessageJumpQueryStringParameter.ts index 6e94fe7902351..d30b12790e836 100644 --- a/apps/meteor/client/lib/utils/setMessageJumpQueryStringParameter.ts +++ b/apps/meteor/client/lib/utils/setMessageJumpQueryStringParameter.ts @@ -3,14 +3,14 @@ import type { LocationPathname } from '@rocket.chat/ui-contexts'; import { router } from '../../providers/RouterProvider'; -export const setMessageJumpQueryStringParameter = async (msg: IMessage['_id'] | null) => { - const { msg: _, ...search } = router.getSearchParameters(); +export const setMessageJumpQueryStringParameter = async (msg: IMessage['_id'] | null, context?: 'jumpToUnread') => { + const { msg: _msg, jumpContext: _jumpContext, ...search } = router.getSearchParameters(); const locationPathname = new URL(window.location.href).pathname as LocationPathname; router.navigate( { pathname: locationPathname, - search: msg ? { ...search, msg } : search, + search: msg ? { ...search, msg, ...(context && { jumpContext: context }) } : search, }, { replace: true }, ); diff --git a/apps/meteor/client/meteor/overrides/ddpOverREST.ts b/apps/meteor/client/meteor/overrides/ddpOverREST.ts index 31e7fd660dcb2..a9ad860907fb2 100644 --- a/apps/meteor/client/meteor/overrides/ddpOverREST.ts +++ b/apps/meteor/client/meteor/overrides/ddpOverREST.ts @@ -2,6 +2,7 @@ import { Meteor } from 'meteor/meteor'; import { sdk } from '../../../app/utils/client/lib/SDKClient'; import { parseDDP, stringifyDDP } from '../../lib/sdk/ddpProtocol'; +import { clearStoredCredentials } from '../../lib/sdk/ddpSdk'; import { getUserId } from '../../lib/user'; const bypassMethods: string[] = ['setUserStatus', 'logout']; @@ -102,6 +103,21 @@ const withDDPOverREST = (_send: (this: Meteor.IMeteorConnection, message: Meteor .catch((error: unknown) => { const e = (error ?? {}) as { error?: unknown; reason?: unknown; message?: unknown }; + // Check if it's a session expiration error and clear credentials. + const isExpiredSessionError = + (typeof e.error === 'string' && e.error === 'You must be logged in to do this.') || + (typeof e.message === 'string' && e.message === 'You must be logged in to do this.') || + (typeof e.reason === 'string' && e.reason === 'You must be logged in to do this.'); + + if (isExpiredSessionError) { + console.warn('[ddpOverREST] Expired session detected, clearing credentials', { method: message.method, error }); + try { + clearStoredCredentials(); + } catch (cleanupError) { + console.warn('[ddpOverREST] Failed to clean up expired session', cleanupError); + } + } + // method.call / method.callAnon encode the original Meteor error // inside `body.message` as a DDP `result` frame (mountResult in // app/api/server/v1/misc.ts). Forward it untouched so the original diff --git a/apps/meteor/client/meteor/overrides/totpOnCall.ts b/apps/meteor/client/meteor/overrides/totpOnCall.ts index e50fb22da8ff6..4ed0169dfde3c 100644 --- a/apps/meteor/client/meteor/overrides/totpOnCall.ts +++ b/apps/meteor/client/meteor/overrides/totpOnCall.ts @@ -52,7 +52,7 @@ const withAsyncTOTP = Promise> } catch (error: unknown) { return process2faAsyncReturn({ error, - onCode: (twoFactorCode, twoFactorMethod) => Meteor.callAsync(methodName, ...args, { twoFactorCode, twoFactorMethod }), + onCode: (twoFactorCode, twoFactorMethod) => callAsync(methodName, ...args, { twoFactorCode, twoFactorMethod }), emailOrUsername: undefined, }); } diff --git a/apps/meteor/client/meteor/startup/accounts.ts b/apps/meteor/client/meteor/startup/accounts.ts index 25be6aac9e006..6971f594db49b 100644 --- a/apps/meteor/client/meteor/startup/accounts.ts +++ b/apps/meteor/client/meteor/startup/accounts.ts @@ -2,6 +2,8 @@ import { sdk } from '../../../app/utils/client/lib/SDKClient'; import { t } from '../../../app/utils/lib/i18n'; import { PublicSettingsCachedStore, SubscriptionsCachedStore } from '../../cachedStores'; import { getDdpSdk } from '../../lib/sdk/ddpSdk'; +import { FORGET_SESSION_SETTING_ID } from '../../lib/sdk/meteorBackedSdk'; +import { settings } from '../../lib/settings'; import { dispatchToastMessage } from '../../lib/toast'; import { userIdStore } from '../../lib/user'; import { useUserDataSyncReady } from '../../lib/userData'; @@ -46,6 +48,31 @@ const whenMainReady = (): Promise => { }); }; +let configuredStorageBackend: 'local' | 'session' = 'local'; + +const applyForgetSessionOnWindowClose = (): void => { + const forgetSession = Boolean(settings.peek(FORGET_SESSION_SETTING_ID) ?? window[FORGET_SESSION_SETTING_ID]); + + const storageBackend = forgetSession ? 'session' : 'local'; + + if (configuredStorageBackend === storageBackend) { + return; + } + + window[FORGET_SESSION_SETTING_ID] = forgetSession; + try { + getDdpSdk().storage?.changeStorageBackend(); + } catch (error) { + console.warn('[accounts] changeStorageBackend failed', error); + return; + } + + configuredStorageBackend = storageBackend; +}; + +applyForgetSessionOnWindowClose(); +settings.observe(FORGET_SESSION_SETTING_ID, applyForgetSessionOnWindowClose); + getDdpSdk().account.onEmailVerificationLink(async (token: string) => { try { await sdk.call('verifyEmail', token); diff --git a/apps/meteor/client/startup/incomingMessages.ts b/apps/meteor/client/startup/incomingMessages.ts index 4efd3dba0fbf7..eafdb5e1838d3 100644 --- a/apps/meteor/client/startup/incomingMessages.ts +++ b/apps/meteor/client/startup/incomingMessages.ts @@ -3,6 +3,7 @@ import type { IMessage } from '@rocket.chat/core-typings'; import { sdk } from '../../app/utils/client/lib/SDKClient'; import { onLoggedIn } from '../lib/loggedIn'; import { getUserId } from '../lib/user'; +import { upsertThreadMessageInCache } from '../lib/utils/threadMessageUtils'; import { Messages } from '../stores'; onLoggedIn(() => { @@ -12,6 +13,10 @@ onLoggedIn(() => { msg.u = msg.u || { username: 'rocket.cat' }; msg.private = true; + if (msg.tmid) { + upsertThreadMessageInCache(msg, msg.rid, msg.tmid); + } + return Messages.state.store(msg); }).stop; }); diff --git a/apps/meteor/client/startup/startup.ts b/apps/meteor/client/startup/startup.ts index bf411805637f5..b9bb756cffb26 100644 --- a/apps/meteor/client/startup/startup.ts +++ b/apps/meteor/client/startup/startup.ts @@ -3,8 +3,9 @@ import type { UserStatus } from '@rocket.chat/core-typings'; import 'highlight.js/styles/github.css'; import { sdk } from '../../app/utils/client/lib/SDKClient'; import { onLoggedIn } from '../lib/loggedIn'; -import { ensureConnectedAndAuthenticated, getDdpSdk } from '../lib/sdk/ddpSdk'; +import { clearStoredCredentials, ensureConnectedAndAuthenticated, getDdpSdk, isAuthError } from '../lib/sdk/ddpSdk'; import { isSdkTransportEnabled } from '../lib/sdk/sdkTransportEnabled'; +import { STORAGE_KEYS, getStoredItem } from '../lib/sdk/storage'; import { userIdStore } from '../lib/user'; import { removeLocalUserData, synchronizeUserData } from '../lib/userData'; import { fireGlobalEvent } from '../lib/utils/fireGlobalEvent'; @@ -47,12 +48,33 @@ if (!sdkTransportEnabled) { // of userIdStore, so without sequencing the sub races the auth and // hits the rejection on every re-login. Await the SDK auth here so // the sub fires authenticated. + const tokenBeforeSync = getStoredItem(STORAGE_KEYS.LOGIN_TOKEN); try { await ensureConnectedAndAuthenticated(); } catch { // non-fatal: sdk.stream queues until DDPSDK eventually auths } - const user = await synchronizeUserData(uid); + + let user: Awaited>; + try { + user = await synchronizeUserData(uid); + } catch (error) { + // When the stored token is expired/revoked server-side, the userData + // stream sub + /v1/me come back 401/403, so synchronizeUserData throws + // and useUserDataSyncReady never flips true. useMainReady then stays + // false forever (uid is still truthy from the stale credentials), so + // Preload sits on PageLoading — and because Preload WRAPS + // AuthenticationCheck, the user never reaches LoginPage and the + // workspace looks stuck "loading"/grayed-out. Escalate the dead-session + // signal to a credential wipe so userId drops to null and the router + // falls through to the login screen. Token-stable guard: only clear + // when localStorage still holds the token we synced with, so a parallel + // re-auth that already rotated the token isn't kicked out. + if (isAuthError(error) && getStoredItem(STORAGE_KEYS.LOGIN_TOKEN) === tokenBeforeSync) { + clearStoredCredentials(); + } + throw error; + } if (!user) return; const utcOffset = -new Date().getTimezoneOffset() / 60; diff --git a/apps/meteor/client/views/room/E2EESetup/RoomE2EESetup.tsx b/apps/meteor/client/views/room/E2EESetup/RoomE2EESetup.tsx index cd95b23156a44..5bb58f325af78 100644 --- a/apps/meteor/client/views/room/E2EESetup/RoomE2EESetup.tsx +++ b/apps/meteor/client/views/room/E2EESetup/RoomE2EESetup.tsx @@ -3,6 +3,7 @@ import { useTranslation } from 'react-i18next'; import RoomE2EENotAllowed from './RoomE2EENotAllowed'; import { e2e } from '../../../lib/e2ee'; +import { getStoredItem, STORAGE_KEYS } from '../../../lib/sdk/storage'; import RoomBody from '../body/RoomBody'; import { useRoom } from '../contexts/RoomContext'; import { useE2EERoomState } from '../hooks/useE2EERoomState'; @@ -15,7 +16,7 @@ const RoomE2EESetup = () => { const e2eRoomState = useE2EERoomState(room._id); const { t } = useTranslation(); - const randomPassword = localStorage.getItem('e2e.randomPassword'); + const randomPassword = getStoredItem(STORAGE_KEYS.E2EE_RANDOM_PASSWORD); const onSavePassword = useCallback(() => { if (!randomPassword) { diff --git a/apps/meteor/client/views/room/MessageList/MessageList.spec.tsx b/apps/meteor/client/views/room/MessageList/MessageList.spec.tsx index f2bbdd50f5748..474aa193610f1 100644 --- a/apps/meteor/client/views/room/MessageList/MessageList.spec.tsx +++ b/apps/meteor/client/views/room/MessageList/MessageList.spec.tsx @@ -117,6 +117,7 @@ const defaultProps = { debouncedClearNewMessagesOnScroll: jest.fn(), handleDateScroll: jest.fn(), debouncedMessageRead: jest.fn(), + setKeepAtBottom: jest.fn(), }; describe('MessageList scroll position', () => { @@ -142,14 +143,12 @@ describe('MessageList scroll position', () => { update: jest.fn(), }; (RoomManager.getStore as jest.Mock).mockReturnValue(store); - mockVirtualizerHandle.findItemIndex.mockReturnValue(4); render(, { wrapper: root.build() }); expect(screen.getByTestId('message-list')).toBeInTheDocument(); - expect(mockVirtualizerHandle.findItemIndex).toHaveBeenCalledWith(123); - expect(mockVirtualizerHandle.scrollToIndex).toHaveBeenCalledWith(4, { align: 'start' }); - expect(mockVirtualizerHandle.scrollTo).not.toHaveBeenCalled(); + expect(mockVirtualizerHandle.scrollTo).toHaveBeenCalledWith(123); + expect(mockVirtualizerHandle.scrollToIndex).not.toHaveBeenCalled(); }); it('should jump to bottom if atBottom is true', () => { diff --git a/apps/meteor/client/views/room/MessageList/MessageList.tsx b/apps/meteor/client/views/room/MessageList/MessageList.tsx index bc226f87d7345..e4380624ddc76 100644 --- a/apps/meteor/client/views/room/MessageList/MessageList.tsx +++ b/apps/meteor/client/views/room/MessageList/MessageList.tsx @@ -42,9 +42,10 @@ type MessageListProps = { setUnreadCount: Dispatch>; setLastMessageDate: Dispatch>; debouncedClearNewMessagesOnScroll: () => void; - handleDateScroll: (topMessage: IMessage | undefined) => void; + handleDateScroll: (topMessage: IMessage | undefined, offset: number) => void; setShouldJumpToBottom: Dispatch>; debouncedMessageRead: () => void; + setKeepAtBottom: (keepAtBottom: () => void) => void; }; export const MessageList = function MessageList({ @@ -66,12 +67,17 @@ export const MessageList = function MessageList({ debouncedClearNewMessagesOnScroll, handleDateScroll, debouncedMessageRead, + setKeepAtBottom, }: MessageListProps) { // Prepend ref needed for adjusting the message list shift // https://inokawa.github.io/virtua/?path=/story/advanced-chat--default const isPrepend = useRef(false); useLayoutEffect(() => { isPrepend.current = false; + // FIXME: isAtBottom should be better calculated, as it does no alwas represent the correct value + if (hasMoreNextMessages) { + isAtBottom.current = false; + } }); const virtualizerRef = useRef(null); @@ -79,12 +85,27 @@ export const MessageList = function MessageList({ const messages = useMessages({ rid }); + const messagesLength = canPreview ? messages.length + 1 : messages.length; + + useEffect(() => { + setKeepAtBottom(() => { + if (virtualizerRef.current) { + virtualizerRef.current.scrollToIndex(messagesLength, { + align: 'end', + }); + } + }); + }, [messagesLength, setKeepAtBottom]); + const keepMountedMessages = useKeepMountedMessages(messages, canPreview); useTryToJumpToMessage({ rid, virtualizerRef, setIsJumpingToMessage, messages }); const handlePrepend = useCallback( (offset: number) => { + if (!isRoomInitialized.current) { + return; + } // If the offset is less than 200, it means the user is reaching the top of the list, // so the prepend need to be enabled for smooth scrolling, // if the prepend is enabled when a new message is added, the list will misalign. @@ -95,6 +116,11 @@ export const MessageList = function MessageList({ const scrollSize = virtualizerRef.current?.scrollSize ?? 0; const viewportSize = virtualizerRef.current?.viewportSize ?? 0; + if (hasMoreNextMessages) { + isAtBottom.current = false; + return; + } + if (scrollSize >= viewportSize) { isAtBottom.current = true; } @@ -104,7 +130,7 @@ export const MessageList = function MessageList({ setShouldJumpToBottom(false); } }, - [isAtBottom, setShouldJumpToBottom, shouldJumpToBottom], + [isAtBottom, setShouldJumpToBottom, shouldJumpToBottom, hasMoreNextMessages], ); const isRoomInitialized = useRef(false); @@ -141,14 +167,7 @@ export const MessageList = function MessageList({ setShouldJumpToBottom(false); - const index = virtualizerRef.current?.findItemIndex(store?.scroll); - if (index !== undefined) { - virtualizerRef.current?.scrollToIndex(index, { - align: 'start', - }); - } else { - virtualizerRef.current?.scrollTo(store?.scroll); - } + virtualizerRef.current?.scrollTo(store?.scroll); isAtBottom.current = false; isRoomInitialized.current = true; return; @@ -251,9 +270,12 @@ export const MessageList = function MessageList({ debouncedClearNewMessagesOnScroll(); const handle = virtualizerRef.current; - const topMessage = handle ? messages[handle.findItemIndex(handle.scrollOffset) - (canPreview ? 1 : 0)] : undefined; + const viewportTopPadding = 21; // TODO: we should derive this value from somewhere else. + const topMessage = handle + ? messages[handle.findItemIndex(handle.scrollOffset - viewportTopPadding) - (canPreview ? 1 : 0)] + : undefined; handleTopVisibleMessage(topMessage); - handleDateScroll(topMessage); + handleDateScroll(topMessage, offset); debouncedMessageRead(); }} > diff --git a/apps/meteor/client/views/room/MessageList/MessageListItem.tsx b/apps/meteor/client/views/room/MessageList/MessageListItem.tsx index 6b69cb8d6c3ce..b4846adcf7949 100644 --- a/apps/meteor/client/views/room/MessageList/MessageListItem.tsx +++ b/apps/meteor/client/views/room/MessageList/MessageListItem.tsx @@ -1,4 +1,5 @@ import { isThreadMessage, type IMessage, type ISubscription } from '@rocket.chat/core-typings'; +import { css } from '@rocket.chat/css-in-js'; import { Box, Bubble, MessageDivider } from '@rocket.chat/fuselage'; import { useTranslation } from 'react-i18next'; @@ -50,6 +51,9 @@ export const MessageListItem = ({ ref={ref} data-id={message.ts} role='listitem' + className={css` + transition: opacity 0.2s ease-out; + `} {...(newDay && { 'data-time': new Date(message.ts) .toISOString() @@ -78,7 +82,7 @@ export const MessageListItem = ({ /> )} {isThreadMessage(message) && ( -
  • +
    -
  • + )} {system && } diff --git a/apps/meteor/client/views/room/MessageList/hooks/useKeepAtBottom.ts b/apps/meteor/client/views/room/MessageList/hooks/useKeepAtBottom.ts new file mode 100644 index 0000000000000..24bb2aa5499f4 --- /dev/null +++ b/apps/meteor/client/views/room/MessageList/hooks/useKeepAtBottom.ts @@ -0,0 +1,45 @@ +import { useSafeRefCallback } from '@rocket.chat/fuselage-hooks'; +import type { MutableRefObject } from 'react'; +import { useCallback, useRef } from 'react'; + +// This hook is responsible for keeping the message list at the bottom despite any size changes to the container. +// Some examples of when this is needed are: +// - When the user is at the bottom and a new message arrives, the message list will grow and we want to keep it at the bottom. (This one is already handled in another place, but this hook also does this job) +// - When the user is at the bottom and the composer grows (e.g. when typing a long message), we want to keep it at the bottom. +// - When the user is at the bottom and the window is resized, the elements might reflow. +// - When the user is at the bottom and a thread opens, the horizontal size of the container will shrink, and the elements might reflow. +// - When the user is at the bottom and a message is reacted to, the message will grow and shift the list. +// - When the user is at the bottom and a video is loading, after loading the video element can change sizes and shift the list +export const useKeepAtBottom = (isAtBottom: MutableRefObject) => { + const handleRef = useRef<(() => void) | null>(null); + const keepAtBottomRef = useSafeRefCallback( + useCallback( + (node: HTMLDivElement) => { + const listWrapper = node.firstChild; + const observer = new ResizeObserver(() => { + if (isAtBottom.current) { + if (handleRef.current) { + handleRef.current(); + } + } + }); + + observer.observe(node); + if (listWrapper instanceof HTMLElement) { + observer.observe(listWrapper); + } + + return () => { + observer.disconnect(); + }; + }, + [isAtBottom], + ), + ); + + const setKeepAtBottom = useCallback((handle: () => void | null) => { + handleRef.current = handle; + }, []); + + return { keepAtBottomRef, setKeepAtBottom }; +}; diff --git a/apps/meteor/client/views/room/MessageList/hooks/useTryToJumpToMessage.ts b/apps/meteor/client/views/room/MessageList/hooks/useTryToJumpToMessage.ts index 63909b96249e0..d15ef63a8765b 100644 --- a/apps/meteor/client/views/room/MessageList/hooks/useTryToJumpToMessage.ts +++ b/apps/meteor/client/views/room/MessageList/hooks/useTryToJumpToMessage.ts @@ -38,8 +38,12 @@ const useTryToJumpToMessage = ({ rid, virtualizerRef, setIsJumpingToMessage, mes setIsJumpingToMessage(false); return; } + if (!message) { + return; + } // Thread deep links are handled by useTryToJumpToThreadMessage; do not use the main list virtualizer - if (message && isThreadMessage(message) && !isThreadMainMessage(message)) { + // If tshow is true, there is a preview on the main list, in this case we scroll to it + if (message && isThreadMessage(message) && !isThreadMainMessage(message) && message.tshow !== true) { setIsJumpingToMessage(false); return; } @@ -78,7 +82,7 @@ const useTryToJumpToMessage = ({ rid, virtualizerRef, setIsJumpingToMessage, mes setTimeout(() => { setIsJumpingToMessage(false); setMessageJumpQueryStringParameter(null); - }, 1000); + }, 500); }, [messageJumpParam, virtualizerRef, setIsJumpingToMessage, rid, messages, message]); }; diff --git a/apps/meteor/client/views/room/MessageList/hooks/useTryToJumpToThreadMessage.spec.ts b/apps/meteor/client/views/room/MessageList/hooks/useTryToJumpToThreadMessage.spec.ts new file mode 100644 index 0000000000000..2d99ff0eef2f9 --- /dev/null +++ b/apps/meteor/client/views/room/MessageList/hooks/useTryToJumpToThreadMessage.spec.ts @@ -0,0 +1,132 @@ +import { mockAppRoot } from '@rocket.chat/mock-providers'; +import { renderHook, waitFor } from '@testing-library/react'; + +import useTryToJumpToThreadMessage from './useTryToJumpToThreadMessage'; +import { RoomHistoryManager } from '../../../../../app/ui-utils/client'; + +jest.mock('../../../../../app/ui-utils/client', () => ({ + RoomHistoryManager: { + getSurroundingMessages: jest.fn().mockResolvedValue(undefined), + isLoaded: jest.fn().mockReturnValue(false), + getMore: jest.fn().mockResolvedValue(undefined), + }, +})); + +jest.mock('../../../../lib/RoomManager', () => ({ + RoomManager: { + opened: undefined as string | undefined, + }, +})); + +jest.mock('../../../../lib/rooms/roomCoordinator', () => ({ + roomCoordinator: { + openRouteLink: jest.fn(), + }, +})); + +jest.mock('../../../../providers/RouterProvider', () => ({ + router: { + getSearchParameters: jest.fn().mockReturnValue({}), + getRouteParameters: jest.fn().mockReturnValue({}), + }, +})); + +jest.mock('../../../../stores', () => ({ + Subscriptions: { + state: { + find: jest.fn().mockReturnValue(undefined), + }, + }, +})); + +const mockedRoomHistoryManager = jest.mocked(RoomHistoryManager); + +afterEach(() => { + jest.clearAllMocks(); +}); + +describe('useTryToJumpToThreadMessage', () => { + describe('early return when msg param is absent or jumpContext is jumpToUnread', () => { + it('should not navigate or load messages when msg search parameter is absent', () => { + const endpointSpy = jest.fn(); + + renderHook(() => useTryToJumpToThreadMessage(), { + wrapper: mockAppRoot().withEndpoint('GET', '/v1/chat.getMessage', endpointSpy).build(), + }); + + expect(endpointSpy).not.toHaveBeenCalled(); + expect(mockedRoomHistoryManager.getSurroundingMessages).not.toHaveBeenCalled(); + expect(mockedRoomHistoryManager.getMore).not.toHaveBeenCalled(); + }); + + it('should not navigate or load messages when jumpContext is jumpToUnread', async () => { + const threadMessage = { + _id: 'msg-1', + rid: 'room-1', + tmid: 'parent-msg-1', + ts: new Date('2024-01-01T00:00:00Z').toISOString(), + u: { _id: 'user-1', username: 'john' }, + msg: 'Thread reply', + _updatedAt: new Date('2024-01-01T00:00:00Z').toISOString(), + }; + + const endpointSpy = jest.fn().mockResolvedValue({ message: threadMessage }); + + renderHook(() => useTryToJumpToThreadMessage(), { + wrapper: mockAppRoot() + .withRouter({ getSearchParameters: () => ({ msg: 'msg-1', jumpContext: 'jumpToUnread' }) }) + .withEndpoint('GET', '/v1/chat.getMessage', endpointSpy) + .withMethod('getRoomById', () => ({ _id: 'room-1', t: 'c', name: 'general' }) as any) + .build(), + }); + + await waitFor(() => { + expect(endpointSpy).toHaveBeenCalledWith({ msgId: 'msg-1' }); + }); + + await waitFor(async () => { + await new Promise((resolve) => setTimeout(resolve, 300)); + expect(mockedRoomHistoryManager.getMore).not.toHaveBeenCalled(); + }); + + expect(mockedRoomHistoryManager.getSurroundingMessages).not.toHaveBeenCalled(); + expect(mockedRoomHistoryManager.getMore).not.toHaveBeenCalled(); + }); + }); + + describe('when jumpContext is absent', () => { + it('should load more messages when jumpContext is null', async () => { + const threadMessage = { + _id: 'msg-1', + rid: 'room-1', + tmid: 'parent-msg-1', + ts: new Date('2024-01-01T00:00:00Z').toISOString(), + u: { _id: 'user-1', username: 'john' }, + msg: 'Thread reply', + _updatedAt: new Date('2024-01-01T00:00:00Z').toISOString(), + }; + + mockedRoomHistoryManager.isLoaded.mockReturnValue(false); + + const endpointSpy = jest.fn().mockResolvedValue({ message: threadMessage }); + + renderHook(() => useTryToJumpToThreadMessage(), { + wrapper: mockAppRoot() + .withRouter({ getSearchParameters: () => ({ msg: 'msg-1' }) }) + .withEndpoint('GET', '/v1/chat.getMessage', endpointSpy) + .withMethod('getRoomById', () => ({ _id: 'room-1', t: 'c', name: 'general' }) as any) + .build(), + }); + + await waitFor(() => { + expect(endpointSpy).toHaveBeenCalledWith({ msgId: 'msg-1' }); + }); + + await waitFor(() => { + expect(mockedRoomHistoryManager.getMore).toHaveBeenCalledWith('room-1'); + }); + + expect(mockedRoomHistoryManager.getSurroundingMessages).not.toHaveBeenCalled(); + }); + }); +}); diff --git a/apps/meteor/client/views/room/MessageList/hooks/useTryToJumpToThreadMessage.ts b/apps/meteor/client/views/room/MessageList/hooks/useTryToJumpToThreadMessage.ts index 604aa1e72a9f2..d68f05ad62ac5 100644 --- a/apps/meteor/client/views/room/MessageList/hooks/useTryToJumpToThreadMessage.ts +++ b/apps/meteor/client/views/room/MessageList/hooks/useTryToJumpToThreadMessage.ts @@ -11,6 +11,7 @@ import { useGoToRoom } from '../../hooks/useGoToRoom'; const useTryToJumpToThreadMessage = (): void => { const messageJumpParam = useSearchParameter('msg'); + const messageJumpContext = useSearchParameter('jumpContext'); const goToRoom = useGoToRoom(); const tab = useRouteParameter('tab'); const context = useRouteParameter('context'); @@ -28,7 +29,7 @@ const useTryToJumpToThreadMessage = (): void => { }); useEffect(() => { - if (!messageJumpParam) { + if (!messageJumpParam || messageJumpContext === 'jumpToUnread') { return; } @@ -56,7 +57,7 @@ const useTryToJumpToThreadMessage = (): void => { await RoomHistoryManager.getMore(message.rid); } })(); - }, [messageJumpParam, message, goToRoom, tab, context]); + }, [messageJumpParam, message, goToRoom, tab, context, messageJumpContext]); }; export default useTryToJumpToThreadMessage; diff --git a/apps/meteor/client/views/room/body/RoomBody.tsx b/apps/meteor/client/views/room/body/RoomBody.tsx index 060bdb3937740..90eff2a276c3f 100644 --- a/apps/meteor/client/views/room/body/RoomBody.tsx +++ b/apps/meteor/client/views/room/body/RoomBody.tsx @@ -30,6 +30,7 @@ import { useGetMore } from './hooks/useGetMore'; import { useHasNewMessages } from './hooks/useHasNewMessages'; import { useSelectAllAndScrollToTop } from './hooks/useSelectAllAndScrollToTop'; import { useHandleUnread } from './hooks/useUnreadMessages'; +import { useKeepAtBottom } from '../MessageList/hooks/useKeepAtBottom'; import useTryToJumpToThreadMessage from '../MessageList/hooks/useTryToJumpToThreadMessage'; const RoomBody = () => { @@ -109,7 +110,9 @@ const RoomBody = () => { debouncedClearNewMessagesOnScroll, } = useHasNewMessages(room._id, user?._id, setShouldJumpToBottom, isAtBottom); - const innerRef = useMergedRefsV2(getMoreInnerRef, selectAndScrollRef, messageListRef); + const { keepAtBottomRef, setKeepAtBottom } = useKeepAtBottom(isAtBottom); + + const innerRef = useMergedRefsV2(getMoreInnerRef, selectAndScrollRef, messageListRef, keepAtBottomRef); const handleNavigateToPreviousMessage = useCallback((): void => { chat.messageEditing.toPreviousMessage(); @@ -222,6 +225,7 @@ const RoomBody = () => { debouncedClearNewMessagesOnScroll={debouncedClearNewMessagesOnScroll} handleDateScroll={handleDateScroll} debouncedMessageRead={debouncedMessageRead} + setKeepAtBottom={setKeepAtBottom} /> diff --git a/apps/meteor/client/views/room/body/hooks/useHasNewMessages.spec.ts b/apps/meteor/client/views/room/body/hooks/useHasNewMessages.spec.ts index d13c3a8f001f9..dbdd106892e81 100644 --- a/apps/meteor/client/views/room/body/hooks/useHasNewMessages.spec.ts +++ b/apps/meteor/client/views/room/body/hooks/useHasNewMessages.spec.ts @@ -15,6 +15,7 @@ jest.mock('../../../../../app/ui-utils/client', () => ({ RoomHistoryManager: { clear: jest.fn(), getMoreIfIsEmpty: jest.fn(), + hasMoreNext: jest.fn(), }, })); @@ -27,12 +28,10 @@ describe('useHasNewMessages', () => { beforeEach(() => { jest.clearAllMocks(); clientCallbacks.remove('streamNewMessage', rid); - clientCallbacks.remove('afterSaveMessage', rid); }); afterEach(() => { clientCallbacks.remove('streamNewMessage', rid); - clientCallbacks.remove('afterSaveMessage', rid); }); it('should NOT show new messages button when user sends their own message', () => { @@ -154,7 +153,28 @@ describe('useHasNewMessages', () => { expect(result.current.hasNewMessages).toBe(false); }); - it('should clear hasNewMessages when afterSaveMessage fires for current user', () => { + it('should NOT jump to bottom when streamNewMessage fires for current user editing their own message', () => { + renderHook(() => useHasNewMessages(rid, uid, setShouldJumpToBottom, isAtBottom), { wrapper: mockAppRoot().build() }); + + const editedOwnMsg: IEditedMessage = { + _id: 'msg-edit', + rid, + u: { _id: uid, username: 'current-user', name: 'Current User' }, + msg: 'Edited message', + ts: new Date(), + _updatedAt: new Date(), + editedAt: new Date(), + editedBy: { _id: uid, username: 'current-user' }, + }; + + const streamNewMessageCallbacks = clientCallbacks.getCallbacks('streamNewMessage'); + act(() => { + streamNewMessageCallbacks.forEach((callback) => callback(editedOwnMsg)); + }); + expect(setShouldJumpToBottom).not.toHaveBeenCalled(); + }); + + it('should clear hasNewMessages when streamNewMessage fires for current users message', () => { const { result } = renderHook(() => useHasNewMessages(rid, uid, setShouldJumpToBottom, { current: false }), { wrapper: mockAppRoot().build(), }); @@ -183,9 +203,9 @@ describe('useHasNewMessages', () => { _updatedAt: new Date(), }; - const afterSaveCallbacks = clientCallbacks.getCallbacks('afterSaveMessage'); + const streamNewMessageCallbacks = clientCallbacks.getCallbacks('streamNewMessage'); act(() => { - afterSaveCallbacks.forEach((callback) => callback(ownMsg)); + streamNewMessageCallbacks.forEach((callback) => callback(ownMsg)); }); expect(result.current.hasNewMessages).toBe(false); expect(setShouldJumpToBottom).toHaveBeenCalledWith(true); diff --git a/apps/meteor/client/views/room/body/hooks/useHasNewMessages.ts b/apps/meteor/client/views/room/body/hooks/useHasNewMessages.ts index ab3afcb05c9fd..c0459c67b4e1f 100644 --- a/apps/meteor/client/views/room/body/hooks/useHasNewMessages.ts +++ b/apps/meteor/client/views/room/body/hooks/useHasNewMessages.ts @@ -48,6 +48,12 @@ export const useHasNewMessages = ( } if (msg.u._id === uid) { + // If there are more next messages, jump to the recent messages + if (RoomHistoryManager.hasMoreNext(rid)) { + return handleJumpToRecentButtonClick(); + } + setShouldJumpToBottom(true); + setHasNewMessages(false); return; } @@ -59,26 +65,10 @@ export const useHasNewMessages = ( rid, ); - clientCallbacks.add( - 'afterSaveMessage', - (msg: IMessage) => { - if (msg.tmid) { - return; - } - if (msg.u._id === uid) { - setShouldJumpToBottom(true); - setHasNewMessages(false); - } - }, - clientCallbacks.priority.MEDIUM, - rid, - ); - return () => { clientCallbacks.remove('streamNewMessage', rid); - clientCallbacks.remove('afterSaveMessage', rid); }; - }, [isAtBottom, rid, setShouldJumpToBottom, uid]); + }, [handleJumpToRecentButtonClick, isAtBottom, rid, setShouldJumpToBottom, uid]); const debouncedClearNewMessagesOnScroll = useDebouncedCallback( () => { diff --git a/apps/meteor/client/views/room/body/hooks/useUnreadMessages.ts b/apps/meteor/client/views/room/body/hooks/useUnreadMessages.ts index 80a4105a57fd2..cd552056ed214 100644 --- a/apps/meteor/client/views/room/body/hooks/useUnreadMessages.ts +++ b/apps/meteor/client/views/room/body/hooks/useUnreadMessages.ts @@ -64,14 +64,15 @@ export const useHandleUnread = ( let message = firstUnread; if (!message) { message = findFirstMessage( - (record) => record.rid === rid && record.ts.getTime() > (unread?.since.getTime() ?? -Infinity), + (record) => + record.rid === rid && record.ts.getTime() > (unread?.since.getTime() ?? -Infinity) && (!record.tmid || record.tshow === true), (a, b) => a.ts.getTime() - b.ts.getTime(), ); } if (!message) { return; } - setMessageJumpQueryStringParameter(message?._id); + setMessageJumpQueryStringParameter(message?._id, 'jumpToUnread'); chat.readStateManager.markAsRead(); setUnreadCount(0); }, [room._id, setUnreadCount, findFirstMessage, unread?.since, chat.readStateManager]); diff --git a/apps/meteor/client/views/room/contextualBar/Threads/components/ThreadMessageList.tsx b/apps/meteor/client/views/room/contextualBar/Threads/components/ThreadMessageList.tsx index 3e241190d5a0b..00636af5c35db 100644 --- a/apps/meteor/client/views/room/contextualBar/Threads/components/ThreadMessageList.tsx +++ b/apps/meteor/client/views/room/contextualBar/Threads/components/ThreadMessageList.tsx @@ -11,7 +11,10 @@ import type { VirtualizerHandle } from 'virtua'; import { VList } from 'virtua'; import { ThreadMessageItem } from './ThreadMessageItem'; +import { useMergedRefsV2 } from '../../../../../hooks/useMergedRefsV2'; +import { setMessageJumpQueryStringParameter } from '../../../../../lib/utils/setMessageJumpQueryStringParameter'; import { BubbleDate } from '../../../BubbleDate'; +import { useKeepAtBottom } from '../../../MessageList/hooks/useKeepAtBottom'; import { useKeepMountedMessages } from '../../../MessageList/hooks/useKeepMountedMessages'; import { isMessageNewDay } from '../../../MessageList/lib/isMessageNewDay'; import MessageListProvider from '../../../MessageList/providers/MessageListProvider'; @@ -71,7 +74,23 @@ const ThreadMessageList = ({ mainMessage, shouldJumpToBottom, setShouldJumpToBot const { messageListRef } = useMessageListNavigation(); const virtualizerRef = useRef(null); - const isAtBottom = useRef(true); + const isAtBottom = useRef(null); + + const { keepAtBottomRef, setKeepAtBottom } = useKeepAtBottom(isAtBottom); + const messagesLength = messages.length; + useEffect(() => { + setKeepAtBottom(() => { + if (virtualizerRef.current) { + virtualizerRef.current.scrollToIndex(messagesLength + 1, { + align: 'end', + }); + } + }); + }, [messagesLength, setKeepAtBottom]); + + const mergedRefs = useMergedRefsV2(messageListRef, keepAtBottomRef); + + const lastScrollSizeRef = useRef(0); const items = loading ? [] : [mainMessage, ...messages]; @@ -101,6 +120,10 @@ const ThreadMessageList = ({ mainMessage, shouldJumpToBottom, setShouldJumpToBot setShouldJumpToBottom(false); return; } + if (isAtBottom.current === true && lastScrollSizeRef.current !== handle?.scrollSize) { + lastScrollSizeRef.current = handle?.scrollSize ?? 0; + setShouldJumpToBottom(true); + } if (shouldJumpToBottom) { handle.scrollToIndex(items.length, { align: 'end' }); setShouldJumpToBottom(false); @@ -128,10 +151,28 @@ const ThreadMessageList = ({ mainMessage, shouldJumpToBottom, setShouldJumpToBot }, 2000); }, [threadMsgTargetIndex, msgJumpParam, mainMessage._id, setShouldJumpToBottom]); + useEffect(() => { + if (!msgJumpParam) { + return; + } + const clearMsgJumpParam = () => { + if (messages.find((m) => m._id === msgJumpParam) && mainMessage._id !== msgJumpParam) { + setMessageJumpQueryStringParameter(null); + } + }; + const timeoutId = setTimeout(() => { + clearMsgJumpParam(); + }, 500); + return () => { + clearMsgJumpParam(); + clearTimeout(timeoutId); + }; + }, [msgJumpParam, messages, mainMessage._id]); + useEffect(() => { const handlerId = `thread-scroll-${mainMessage._id}`; clientCallbacks.add( - 'afterSaveMessage', + 'streamNewMessage', (msg: IMessage) => { if (msg.rid !== room._id || isEditedMessage(msg) || msg.tmid !== mainMessage._id) { return; @@ -145,7 +186,7 @@ const ThreadMessageList = ({ mainMessage, shouldJumpToBottom, setShouldJumpToBot ); return () => { - clientCallbacks.remove('afterSaveMessage', handlerId); + clientCallbacks.remove('streamNewMessage', handlerId); }; }, [room._id, uid, mainMessage._id, setShouldJumpToBottom]); @@ -154,7 +195,7 @@ const ThreadMessageList = ({ mainMessage, shouldJumpToBottom, setShouldJumpToBot return (
    - + { + onScroll={(offset) => { const handle = virtualizerRef.current; if (!handle) return; + + // Copied from messageList, I'm unsure why this is necessary, but it seems to be needed to properly set the isAtBottom state + if (handle.scrollSize >= handle.viewportSize) { + isAtBottom.current = true; + } isAtBottom.current = offset - handle.scrollSize + handle.viewportSize >= -20; const topMessage = items[handle.findItemIndex(handle.scrollOffset)]; - handleDateScroll(topMessage); + handleDateScroll(topMessage, offset); }} > {loading ? ( diff --git a/apps/meteor/client/views/room/hooks/useDateScroll.ts b/apps/meteor/client/views/room/hooks/useDateScroll.ts index 7c278b079f5f0..4dbbf317bb5fb 100644 --- a/apps/meteor/client/views/room/hooks/useDateScroll.ts +++ b/apps/meteor/client/views/room/hooks/useDateScroll.ts @@ -7,7 +7,7 @@ import { useRef, useState } from 'react'; import { useDateListController } from '../providers/DateListProvider'; type useDateScrollReturn = { - handleDateScroll: (topMessage: IMessage | undefined) => void; + handleDateScroll: (topMessage: IMessage | undefined, offset: number) => void; bubbleRef: MutableRefObject; listStyle?: ReturnType; } & BubbleDateProps; @@ -19,6 +19,12 @@ export type BubbleDateProps = { bubbleDateStyle?: CSSProperties; }; +// The threshold in pixels to consider a date divider as "visible" when scrolling. +// The divider being a few pixels above the top of the viewport is safe, as it is always contained inside a message +const DATE_DIVIDER_VISIBILITY_THRESHOLD = 100; + +type Matched = [date: string, divider: HTMLElement | undefined, style: { [key: string]: string | number }, showDivider: boolean] | []; + export const useDateScroll = (margin = 8): useDateScrollReturn => { const [bubbleDate, setBubbleDate] = useSafely( useState<{ @@ -27,12 +33,14 @@ export const useDateScroll = (margin = 8): useDateScrollReturn => { style?: CSSProperties; bubbleDateClassName?: ReturnType; offset: number; + showDivider: boolean; }>({ date: '', show: false, style: undefined, bubbleDateClassName: undefined, offset: 0, + showDivider: true, }), ); @@ -43,41 +51,49 @@ export const useDateScroll = (margin = 8): useDateScrollReturn => { const hideBubbleTimeoutRef = useRef | null>(null); const handleDateScroll = useDebouncedCallback( - (topMessage: IMessage | undefined) => { + (topMessage: IMessage | undefined, offset: number) => { if (hideBubbleTimeoutRef.current) { clearTimeout(hideBubbleTimeoutRef.current); hideBubbleTimeoutRef.current = null; } - const bubbleOffset = bubbleRef.current?.getBoundingClientRect().bottom || 0; + const bubbleBottom = bubbleRef.current?.getBoundingClientRect().bottom || 0; - type Matched = [string, HTMLElement | undefined, { [key: string]: string | number }?] | []; // Gets the first non visible message date and sets the bubble date to it let matched: Matched = [...list].reduce((ret, divider) => { + const { top: dividerTop, height: dividerHeight } = divider.getBoundingClientRect(); + // Some dividers might be kept in the DOM if the "new day" message has a file attached + // So we check if they are actually visible to avoid showing old dates in the bubble + // We also need the parent since it has the actual offset inside the scroll container + const parentOffsetTop = divider.parentElement?.offsetTop; + const parentSafeOffset = parentOffsetTop !== undefined ? parentOffsetTop + DATE_DIVIDER_VISIBILITY_THRESHOLD : 0; + // Sanitize elements - if (!divider.dataset.id) { + if (!divider.dataset.id || parentSafeOffset < offset) { return ret; } - const { top, height } = divider.getBoundingClientRect(); const { id } = divider.dataset; // if the bubble if between the divider and the top, position it at the top of the divider - if (top > bubbleOffset && top < bubbleOffset + height) { + if (dividerTop > bubbleBottom && dividerTop < bubbleBottom + dividerHeight) { + // if there's no previous date it means the previous divider is not mounted anymore, so we use the message date or fallback to the divider date as a last resort + const date = ret[0] ? ret[0] : (topMessage && new Date(topMessage.ts).toISOString()) || new Date(id).toISOString(); return [ - ret[0] || new Date(id).toISOString(), + date, ret[1] || divider, { position: 'absolute', - top: `${top - height - bubbleOffset + margin}px`, + top: `${dividerTop - dividerHeight - bubbleBottom + margin}px`, left: ' 50%', translate: '-50%', zIndex: 11, }, + true, ]; } - if (top < bubbleOffset + height) { + if (dividerTop < bubbleBottom + dividerHeight) { return [ new Date(id).toISOString(), divider, @@ -88,6 +104,7 @@ export const useDateScroll = (margin = 8): useDateScrollReturn => { translate: '-50%', zIndex: 11, }, + false, ]; } return ret; @@ -105,10 +122,11 @@ export const useDateScroll = (margin = 8): useDateScrollReturn => { translate: '-50%', zIndex: 11, }, + true, ]; } - const [date, divider, style] = matched; + const [date, divider, style, showDivider] = matched; // We always keep the previous date if we don't have a new one, so when the bubble disappears it doesn't flicker setBubbleDate((current) => ({ @@ -117,6 +135,7 @@ export const useDateScroll = (margin = 8): useDateScrollReturn => { ...(date && { date }), show: Boolean(date), style, + showDivider: showDivider ?? true, bubbleDateClassName: css` opacity: 0; transition: opacity 0.6s; @@ -128,7 +147,7 @@ export const useDateScroll = (margin = 8): useDateScrollReturn => { if (divider) { const { top } = divider.getBoundingClientRect(); - if (top < bubbleOffset && top > 0) { + if (top < bubbleBottom && top > 0) { return; } } @@ -138,6 +157,7 @@ export const useDateScroll = (margin = 8): useDateScrollReturn => { setBubbleDate((current) => ({ ...current, show: false, + showDivider: true, })), 1000, ); @@ -145,18 +165,16 @@ export const useDateScroll = (margin = 8): useDateScrollReturn => { 5, [list, margin, setBubbleDate], ); - // TODO: Make the chip "gliding" work with the new sistem. - // const listStyle = - // bubbleDate.show && bubbleDate.date - // ? css` - // position: relative; - // & [data-time='${bubbleDate.date.replaceAll(/[-T:.]/g, '').substring(0, 8)}'] { - // opacity: 0; - // } - // ` - // : undefined; - - const listStyle = undefined; + // FIXME: This should be handled at the component level + const listStyle = + bubbleDate.show && bubbleDate.date && !bubbleDate.showDivider + ? css` + position: relative; + & [data-time='${bubbleDate.date.replaceAll(/[-T:.]/g, '').substring(0, 8)}'] { + opacity: 0; + } + ` + : undefined; return { handleDateScroll, diff --git a/apps/meteor/client/views/room/layout/RoomLayout.tsx b/apps/meteor/client/views/room/layout/RoomLayout.tsx index 4f212bdd1cfc5..21478ffc35ea0 100644 --- a/apps/meteor/client/views/room/layout/RoomLayout.tsx +++ b/apps/meteor/client/views/room/layout/RoomLayout.tsx @@ -39,6 +39,7 @@ const RoomLayout = ({ header, body, footer, aside, ...props }: RoomLayoutProps) const contextualbarPosition = breakpoints.includes('md') ? 'relative' : 'absolute'; const contextualbarSize = breakpoints.includes('sm') ? (breakpoints.includes('xl') ? '38%' : '380px') : '100%'; + const hideBody = aside && contextualbarSize === '100%'; const layout = useLayout(); @@ -59,7 +60,7 @@ const RoomLayout = ({ header, body, footer, aside, ...props }: RoomLayoutProps) }>{header} - + {body} diff --git a/apps/meteor/client/views/root/MainLayout/EmbeddedPreload.tsx b/apps/meteor/client/views/root/MainLayout/EmbeddedPreload.tsx index cf2ac64aa2ed4..468413d3416ae 100644 --- a/apps/meteor/client/views/root/MainLayout/EmbeddedPreload.tsx +++ b/apps/meteor/client/views/root/MainLayout/EmbeddedPreload.tsx @@ -1,12 +1,15 @@ +import { getObjectKeys } from '@rocket.chat/tools'; import { useEndpoint, useMethod, useRouter, useUserId } from '@rocket.chat/ui-contexts'; import { useQuery } from '@tanstack/react-query'; import type { ReactNode } from 'react'; import { useEffect, useMemo } from 'react'; +import { roomFields } from '../../../../lib/publishFields'; import { RoomsCachedStore, SubscriptionsCachedStore } from '../../../cachedStores'; import { roomsQueryKeys } from '../../../lib/queryKeys'; import { roomCoordinator } from '../../../lib/rooms/roomCoordinator'; import { mapSubscriptionFromApi } from '../../../lib/utils/mapSubscriptionFromApi'; +import { Rooms } from '../../../stores'; import PageLoading from '../PageLoading'; import { useMainReady } from '../hooks/useMainReady'; @@ -51,12 +54,20 @@ const EmbeddedPreload = ({ children }: { children: ReactNode }) => { return null; } + // Populate Rooms store and return same shape as useOpenRoom so the shared + // React Query cache entry is usable when RoomOpenerEmbedded mounts. + const unsetKeys = getObjectKeys(roomData).filter((key) => !(key in roomFields)); + unsetKeys.forEach((key) => { + delete roomData[key]; + }); + Rooms.state.store(roomData); + const subResult = await getSubscription({ roomId: roomData._id }); if (subResult.subscription) { SubscriptionsCachedStore.upsertSubscription(mapSubscriptionFromApi(subResult.subscription)); } - return subResult; + return { rid: roomData._id }; }, enabled: shouldFetch, retry: false, diff --git a/apps/meteor/client/views/root/OutermostErrorBoundary.tsx b/apps/meteor/client/views/root/OutermostErrorBoundary.tsx index 02f47a1bf7559..f72a1b7bad7a7 100644 --- a/apps/meteor/client/views/root/OutermostErrorBoundary.tsx +++ b/apps/meteor/client/views/root/OutermostErrorBoundary.tsx @@ -22,6 +22,14 @@ if (window.__BUGSNAG_KEY__) { apiKey: window.__BUGSNAG_KEY__, appVersion: Info.version, plugins: [new BugsnagPluginReact()], + onError(event) { + // Skip the benign "ResizeObserver loop" browser warning (not a crash; emitted in bulk by + // virtua during message-list scroll). See CORE-2209. + const errorMessage = event.errors?.[0]?.errorMessage; + if (typeof errorMessage === 'string' && errorMessage.startsWith('ResizeObserver loop')) { + return false; + } + }, }); BugsnagErrorBoundary = Bugsnag.getPlugin('react')?.createErrorBoundary(React); diff --git a/apps/meteor/ee/server/services/CHANGELOG.md b/apps/meteor/ee/server/services/CHANGELOG.md index e2183cfed4a31..93446fc15ed59 100644 --- a/apps/meteor/ee/server/services/CHANGELOG.md +++ b/apps/meteor/ee/server/services/CHANGELOG.md @@ -1,5 +1,37 @@ # rocketchat-services +## 2.0.48 + +### Patch Changes + +-
    Updated dependencies [90f15e32ae843ed146ccf711ee3201408d1e8731, f7d47dd3517ec14ca2ec5c3c95fcdf9e1e2fb8b0, 2a927fa1362c9d4bb04bb8e26f23a6e3753d9cea, 4c3984593017d59edd631bf8ae4f35f9d3c3db36, b6b04aadfcc8558f888b334e37c46a77e5816237, 4704bf81ca370f120af32185a7c55407a26f8514, f392d5cc8d956c199f557dcd6beb52094232499d, 2198d9ea565b06f92e3dec29891890086f62f9df, 12897e25d0dc25b7373f5264d38f38a5a7444257, e45585b70a3a7b75434c88e4b2ea9af0a0764a76, b1c2668b74bfb49ebaefe2f581b2f8be5d4d1dd6, 90f15e32ae843ed146ccf711ee3201408d1e8731]: + + - @rocket.chat/ui-kit@1.1.0 + - @rocket.chat/model-typings@2.3.0 + - @rocket.chat/models@2.3.0 + - @rocket.chat/apps-engine@1.63.0 + - @rocket.chat/rest-typings@8.5.0 + - @rocket.chat/core-typings@8.5.0 + - @rocket.chat/network-broker@0.2.36 + - @rocket.chat/core-services@0.14.1 +
    + +## 2.0.48-rc.0 + +### Patch Changes + +-
    Updated dependencies [90f15e32ae843ed146ccf711ee3201408d1e8731, f7d47dd3517ec14ca2ec5c3c95fcdf9e1e2fb8b0, 2a927fa1362c9d4bb04bb8e26f23a6e3753d9cea, 4c3984593017d59edd631bf8ae4f35f9d3c3db36, ae9f740d6af20557eac61b4af902c868b4132b49, b6b04aadfcc8558f888b334e37c46a77e5816237, 4704bf81ca370f120af32185a7c55407a26f8514, f392d5cc8d956c199f557dcd6beb52094232499d, 2198d9ea565b06f92e3dec29891890086f62f9df, 12897e25d0dc25b7373f5264d38f38a5a7444257, e45585b70a3a7b75434c88e4b2ea9af0a0764a76, b1c2668b74bfb49ebaefe2f581b2f8be5d4d1dd6, 90f15e32ae843ed146ccf711ee3201408d1e8731]: + + - @rocket.chat/ui-kit@1.1.0-rc.0 + - @rocket.chat/model-typings@2.3.0-rc.0 + - @rocket.chat/models@2.3.0-rc.0 + - @rocket.chat/apps-engine@1.63.0-rc.0 + - @rocket.chat/rest-typings@8.5.0-rc.0 + - @rocket.chat/core-typings@8.5.0-rc.0 + - @rocket.chat/core-services@0.14.1-rc.0 + - @rocket.chat/network-broker@0.2.36-rc.0 +
    + ## 2.0.47 ### Patch Changes diff --git a/apps/meteor/ee/server/services/package.json b/apps/meteor/ee/server/services/package.json index 77b26bef19a64..3bb9fe3021268 100644 --- a/apps/meteor/ee/server/services/package.json +++ b/apps/meteor/ee/server/services/package.json @@ -1,7 +1,7 @@ { "name": "rocketchat-services", "private": true, - "version": "2.0.47", + "version": "2.0.48", "description": "Rocket.Chat Authorization service", "main": "index.js", "scripts": { diff --git a/apps/meteor/tests/e2e/account-forgetSessionOnWindowClose.spec.ts b/apps/meteor/tests/e2e/account-forgetSessionOnWindowClose.spec.ts index 43ae838968411..6307544bd428f 100644 --- a/apps/meteor/tests/e2e/account-forgetSessionOnWindowClose.spec.ts +++ b/apps/meteor/tests/e2e/account-forgetSessionOnWindowClose.spec.ts @@ -1,6 +1,7 @@ import { DEFAULT_USER_CREDENTIALS } from './config/constants'; -import { Login } from './page-objects'; +import { AccountSecurity, HomeChannel, Login } from './page-objects'; import { test, expect } from './utils/test'; +import { createTestUser, type ITestUser } from './utils/user-helpers'; test.describe.serial('Forget session on window close setting', () => { let poLogin: Login; @@ -28,8 +29,7 @@ test.describe.serial('Forget session on window close setting', () => { }); }); - // TODO: Fix this test - test.describe.skip('Setting on', async () => { + test.describe('Setting on', async () => { test.beforeAll(async ({ api }) => { await api.post('/settings/Accounts_ForgetUserSessionOnWindowClose', { value: true }); }); @@ -38,7 +38,17 @@ test.describe.serial('Forget session on window close setting', () => { await api.post('/settings/Accounts_ForgetUserSessionOnWindowClose', { value: false }); }); - test('Login using credentials and reload to get logged out', async ({ page, context }) => { + test('Login using credentials and reload to stay logged in', async ({ page }) => { + await poLogin.login('user1', DEFAULT_USER_CREDENTIALS.password); + + await expect(page.locator('role=heading[name="Welcome to Rocket.Chat"]')).toBeVisible(); + + await page.reload(); + + await expect(page.locator('role=heading[name="Welcome to Rocket.Chat"]')).toBeVisible(); + }); + + test('Login using credentials in a new tab after first tab logged in', async ({ page, context }) => { await poLogin.login('user1', DEFAULT_USER_CREDENTIALS.password); await expect(page.locator('role=heading[name="Welcome to Rocket.Chat"]')).toBeVisible(); @@ -46,7 +56,55 @@ test.describe.serial('Forget session on window close setting', () => { const newPage = await context.newPage(); await newPage.goto('/home'); - await expect(newPage.locator('role=button[name="Login"]')).toBeVisible(); + const newPoLogin = new Login(newPage); + await newPoLogin.login('user1', DEFAULT_USER_CREDENTIALS.password); + + await expect(newPage.locator('role=heading[name="Welcome to Rocket.Chat"]')).toBeVisible(); + }); + + test.describe('E2EE save password flow', () => { + // Dedicated throwaway user: resetE2EEPassword() calls Users.unsetLoginTokens(), + // which would invalidate the shared admin login token the `api` fixture + // authenticates with — breaking every subsequent admin-authenticated request + // in the worker (e.g. the next spec's beforeAll settings changes silently 401). + let e2eeUser: ITestUser; + + test.beforeAll(async ({ api }) => { + await api.post('/settings/E2E_Enable', { value: true }); + await api.post('/settings/E2E_Allow_Unencrypted_Messages', { value: false }); + + e2eeUser = await createTestUser(api); + }); + + test.afterAll(async ({ api }) => { + await e2eeUser?.delete(); + await api.post('/settings/E2E_Allow_Unencrypted_Messages', { value: true }); + await api.post('/settings/E2E_Enable', { value: false }); + }); + + test('E2EE save password button opens modal in SAVE_PASSWORD state', async ({ page }) => { + const poHomeChannel = new HomeChannel(page); + const poAccountSecurity = new AccountSecurity(page); + + await poLogin.login(e2eeUser.data.username, DEFAULT_USER_CREDENTIALS.password); + await expect(page.locator('role=heading[name="Welcome to Rocket.Chat"]')).toBeVisible(); + + await poAccountSecurity.goto(); + await poAccountSecurity.resetE2EEPassword(); + + await page.locator('role=button[name="Login"]').waitFor(); + + await poLogin.login(e2eeUser.data.username, DEFAULT_USER_CREDENTIALS.password); + await expect(page.locator('role=heading[name="Welcome to Rocket.Chat"]')).toBeVisible(); + await expect(poHomeChannel.bannerSaveEncryptionPassword).toBeVisible(); + await poHomeChannel.bannerSaveEncryptionPassword.click(); + + const randomPassword = await page.evaluate(() => window.sessionStorage.getItem('e2e.randomPassword') ?? ''); + expect(randomPassword).toBeTruthy(); + + await expect(poHomeChannel.dialogSaveE2EEPassword).toBeVisible(); + await expect(poHomeChannel.dialogSaveE2EEPassword).toContainText(randomPassword); + }); }); }); }); diff --git a/apps/meteor/tests/e2e/message-mentions.spec.ts b/apps/meteor/tests/e2e/message-mentions.spec.ts index d03c62edd4f5b..17ea83daa44a8 100644 --- a/apps/meteor/tests/e2e/message-mentions.spec.ts +++ b/apps/meteor/tests/e2e/message-mentions.spec.ts @@ -137,17 +137,17 @@ test.describe.serial('message-mentions', () => { }); await test.step('show "Do nothing" action', async () => { - await expect(adminPage.content.lastUserMessage.locator('button >> text="Do nothing"')).toBeVisible(); + await expect(adminPage.content.getLastMessageActionButton('Do nothing')).toBeVisible(); }); await test.step('show "Add them" action', async () => { - await expect(adminPage.content.lastUserMessage.locator('button >> text="Add them"')).toBeVisible(); + await expect(adminPage.content.getLastMessageActionButton('Add them')).toBeVisible(); }); await test.step('show "Let them know" action', async () => { - await expect(adminPage.content.lastUserMessage.locator('button >> text="Let them know"')).toBeVisible(); + await expect(adminPage.content.getLastMessageActionButton('Let them know')).toBeVisible(); }); await test.step('dismiss', async () => { - await adminPage.content.lastUserMessage.locator('button >> text="Do nothing"').click(); + await adminPage.content.getLastMessageActionButton('Do nothing').click(); }); await test.step('receive second bot message', async () => { @@ -155,7 +155,7 @@ test.describe.serial('message-mentions', () => { await expect(adminPage.content.lastUserMessage.locator('.rcx-message-block')).toContainText(mentionText); }); await test.step('send message to users', async () => { - await adminPage.content.lastUserMessage.locator('button >> text="Let them know"').click(); + await adminPage.content.getLastMessageActionButton('Let them know').click(); await expect(adminPage.content.lastUserMessageBody).toContainText(getMentionText(Users.user1.data.username, 3)); }); @@ -164,11 +164,34 @@ test.describe.serial('message-mentions', () => { await expect(adminPage.content.lastUserMessage.locator('.rcx-message-block')).toContainText(mentionText); }); await test.step('add users to room', async () => { - await adminPage.content.lastUserMessage.locator('button >> text="Add them"').click(); + await adminPage.content.getLastMessageActionButton('Add them').click(); await expect(adminPage.content.lastSystemMessageBody).toContainText('added'); }); }); + test('should show non-member mention warning inside threads', async ({ page }) => { + const adminPage = new HomeChannel(page); + const mentionText = getMentionText(Users.user2.data.username, 1); + + await test.step('open thread', async () => { + await adminPage.navbar.openChat(targetChannel); + await adminPage.content.sendMessage('thread parent for non-member mention warning'); + await adminPage.content.openReplyInThread(); + await adminPage.content.waitForThread(); + }); + + await test.step('receive bot message inside thread', async () => { + await adminPage.content.sendMessageInThread(getMentionText(Users.user2.data.username)); + await expect(adminPage.content.lastUserThreadMessage).toContainText(mentionText); + }); + + await test.step('show actions inside thread', async () => { + await expect(adminPage.content.getLastThreadMessageActionButton('Do nothing')).toBeVisible(); + await expect(adminPage.content.getLastThreadMessageActionButton('Add them')).toBeVisible(); + await expect(adminPage.content.getLastThreadMessageActionButton('Let them know')).toBeVisible(); + }); + }); + test.describe(() => { test.use({ storageState: Users.user1.state }); @@ -183,17 +206,17 @@ test.describe.serial('message-mentions', () => { }); await test.step('show "Do nothing" action', async () => { - await expect(userPage.content.lastUserMessage.locator('button >> text="Do nothing"')).toBeVisible(); + await expect(userPage.content.getLastMessageActionButton('Do nothing')).toBeVisible(); }); await test.step('show "Let them know" action', async () => { - await expect(userPage.content.lastUserMessage.locator('button >> text="Let them know"')).toBeVisible(); + await expect(userPage.content.getLastMessageActionButton('Let them know')).toBeVisible(); }); await test.step('not show "Add them action', async () => { - await expect(userPage.content.lastUserMessage.locator('button >> text="Add them"')).not.toBeVisible(); + await expect(userPage.content.getLastMessageActionButton('Add them')).not.toBeVisible(); }); await test.step('dismiss', async () => { - await userPage.content.lastUserMessage.locator('button >> text="Do nothing"').click(); + await userPage.content.getLastMessageActionButton('Do nothing').click(); }); await test.step('receive second bot message', async () => { @@ -202,7 +225,7 @@ test.describe.serial('message-mentions', () => { await expect(userPage.content.lastUserMessage.locator('.rcx-message-block')).toContainText(mentionText); }); await test.step('send message to users', async () => { - await userPage.content.lastUserMessage.locator('button >> text="Let them know"').click(); + await userPage.content.getLastMessageActionButton('Let them know').click(); await expect(userPage.content.lastUserMessageBody).toContainText(getMentionText(Users.user2.data.username, 3)); }); }); @@ -237,17 +260,17 @@ test.describe.serial('message-mentions', () => { await expect(userPage.content.lastUserMessage.locator('.rcx-message-block')).toContainText(mentionText); }); await test.step('show "Do nothing" action', async () => { - await expect(userPage.content.lastUserMessage.locator('button >> text="Do nothing"')).toBeVisible(); + await expect(userPage.content.getLastMessageActionButton('Do nothing')).toBeVisible(); }); await test.step('show "Add them" action', async () => { - await expect(userPage.content.lastUserMessage.locator('button >> text="Add them"')).toBeVisible(); + await expect(userPage.content.getLastMessageActionButton('Add them')).toBeVisible(); }); await test.step('not show "Let them know" action', async () => { - await expect(userPage.content.lastUserMessage.locator('button >> text="Let them know"')).not.toBeVisible(); + await expect(userPage.content.getLastMessageActionButton('Let them know')).not.toBeVisible(); }); await test.step('dismiss', async () => { - await userPage.content.lastUserMessage.locator('button >> text="Do nothing"').click(); + await userPage.content.getLastMessageActionButton('Do nothing').click(); }); await test.step('receive second bot message', async () => { @@ -256,7 +279,7 @@ test.describe.serial('message-mentions', () => { await expect(userPage.content.lastUserMessage.locator('.rcx-message-block')).toContainText(mentionText); }); await test.step('add users to room', async () => { - await userPage.content.lastUserMessage.locator('button >> text="Add them"').click(); + await userPage.content.getLastMessageActionButton('Add them').click(); await expect(userPage.content.lastSystemMessageBody).toContainText('added'); }); }); @@ -285,13 +308,13 @@ test.describe.serial('message-mentions', () => { }); await test.step('not show "Do nothing" action', async () => { - await expect(userPage.content.lastUserMessage.locator('button >> text="Do nothing"')).not.toBeVisible(); + await expect(userPage.content.getLastMessageActionButton('Do nothing')).not.toBeVisible(); }); await test.step('not show "Add them" action', async () => { - await expect(userPage.content.lastUserMessage.locator('button >> text="Add them"')).not.toBeVisible(); + await expect(userPage.content.getLastMessageActionButton('Add them')).not.toBeVisible(); }); await test.step('not show "Let them know" action', async () => { - await expect(userPage.content.lastUserMessage.locator('button >> text="Let them know"')).not.toBeVisible(); + await expect(userPage.content.getLastMessageActionButton('Let them know')).not.toBeVisible(); }); }); }); diff --git a/apps/meteor/tests/e2e/page-objects/fragments/home-content.ts b/apps/meteor/tests/e2e/page-objects/fragments/home-content.ts index 4feef449186aa..a17e56af0e652 100644 --- a/apps/meteor/tests/e2e/page-objects/fragments/home-content.ts +++ b/apps/meteor/tests/e2e/page-objects/fragments/home-content.ts @@ -544,6 +544,14 @@ export class HomeContent { return this.page.locator('[role="listitem"][aria-roledescription="message"]', { hasText: text }); } + getLastMessageActionButton(name: string): Locator { + return this.lastUserMessage.getByRole('button', { name, exact: true }); + } + + getLastThreadMessageActionButton(name: string): Locator { + return this.lastUserThreadMessage.getByRole('button', { name, exact: true }); + } + getMessageById(id: string): Locator { return this.page.locator(`[role="listitem"][aria-roledescription="message"][id="${id}"]`); } diff --git a/apps/meteor/tests/end-to-end/api/custom-sounds.ts b/apps/meteor/tests/end-to-end/api/custom-sounds.ts index c371161a89a34..bd0e03e0eb671 100644 --- a/apps/meteor/tests/end-to-end/api/custom-sounds.ts +++ b/apps/meteor/tests/end-to-end/api/custom-sounds.ts @@ -1,4 +1,5 @@ import { randomUUID } from 'crypto'; +import fs from 'fs'; import path from 'path'; import type { Credentials } from '@rocket.chat/api-client'; @@ -350,6 +351,61 @@ describe('[CustomSounds]', () => { .expect(403); }); }); + + describe('mutating file on failed validation', () => { + let soundAId: string; + let soundBId: string; + const soundAName = `sound-a-${randomUUID()}`; + const soundBName = `sound-b-${randomUUID()}`; + + before(async () => { + soundAId = await createCustomSound(soundAName, mockWavAudioPath); + soundBId = await createCustomSound(soundBName, mockMp3AudioPath); + }); + + after(async () => { + await deleteCustomSound(soundAId); + await deleteCustomSound(soundBId); + }); + + it('should not mutate the underlying file or metadata if the update fails validation (e.g., name collision)', async () => { + await request + .post(api('custom-sounds.update')) + .set(credentials) + .attach('sound', mockMp3AudioPath) + .field('_id', soundAId) + .field('name', soundBName) + .expect(400) + .expect((res) => { + expect(res.body).to.have.property('success', false); + expect(res.body).to.have.property('error', 'The custom sound name is already in use [Custom_Sound_Error_Name_Already_In_Use]'); + }); + + await request + .get(api('custom-sounds.getOne')) + .set(credentials) + .query({ _id: soundAId }) + .expect(200) + .expect((res) => { + expect(res.body.sound).to.have.property('name', soundAName); + expect(res.body.sound).to.have.property('extension', 'wav'); + }); + + const originalWavBuffer = fs.readFileSync(mockWavAudioPath); + + await request + .get(`/custom-sounds/${soundAId}.wav`) + .set(credentials) + .expect(200) + .expect((res) => { + expect(res.headers).to.have.property('content-type', 'audio/wav'); + expect(Buffer.isBuffer(res.body)).to.be.true; + expect(originalWavBuffer.equals(res.body)).to.be.true; + }); + + await request.get(`/custom-sounds/${soundAId}.mp3`).set(credentials).expect(404); + }); + }); }); describe('[/custom-sounds.list]', () => { diff --git a/apps/uikit-playground/CHANGELOG.md b/apps/uikit-playground/CHANGELOG.md index 67794c1dae733..df7b1a2464d92 100644 --- a/apps/uikit-playground/CHANGELOG.md +++ b/apps/uikit-playground/CHANGELOG.md @@ -1,5 +1,29 @@ # @rocket.chat/uikit-playground +## 0.7.13 + +### Patch Changes + +-
    Updated dependencies [12897e25d0dc25b7373f5264d38f38a5a7444257]: + + - @rocket.chat/core-typings@8.5.0 + - @rocket.chat/fuselage-ui-kit@31.0.0 + - @rocket.chat/ui-avatar@27.0.0 + - @rocket.chat/ui-contexts@31.0.0 +
    + +## 0.7.13-rc.0 + +### Patch Changes + +-
    Updated dependencies [ae9f740d6af20557eac61b4af902c868b4132b49, 12897e25d0dc25b7373f5264d38f38a5a7444257]: + + - @rocket.chat/core-typings@8.5.0-rc.0 + - @rocket.chat/fuselage-ui-kit@31.0.0-rc.0 + - @rocket.chat/ui-contexts@31.0.0-rc.0 + - @rocket.chat/ui-avatar@27.0.0-rc.0 +
    + ## 0.7.12 ### Patch Changes diff --git a/apps/uikit-playground/package.json b/apps/uikit-playground/package.json index 2fd47ac6ab815..5b14a723e1dbd 100644 --- a/apps/uikit-playground/package.json +++ b/apps/uikit-playground/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/uikit-playground", - "version": "0.7.12", + "version": "0.7.13", "private": true, "type": "module", "scripts": { diff --git a/ee/apps/account-service/CHANGELOG.md b/ee/apps/account-service/CHANGELOG.md index 249c8bd30b675..c8912ebe947bd 100644 --- a/ee/apps/account-service/CHANGELOG.md +++ b/ee/apps/account-service/CHANGELOG.md @@ -1,5 +1,33 @@ # @rocket.chat/account-service +## 0.4.57 + +### Patch Changes + +-
    Updated dependencies [f7d47dd3517ec14ca2ec5c3c95fcdf9e1e2fb8b0, 4c3984593017d59edd631bf8ae4f35f9d3c3db36, b6b04aadfcc8558f888b334e37c46a77e5816237, 4704bf81ca370f120af32185a7c55407a26f8514, 12897e25d0dc25b7373f5264d38f38a5a7444257, e45585b70a3a7b75434c88e4b2ea9af0a0764a76, b1c2668b74bfb49ebaefe2f581b2f8be5d4d1dd6]: + + - @rocket.chat/model-typings@2.3.0 + - @rocket.chat/models@2.3.0 + - @rocket.chat/rest-typings@8.5.0 + - @rocket.chat/core-typings@8.5.0 + - @rocket.chat/network-broker@0.2.36 + - @rocket.chat/core-services@0.14.1 +
    + +## 0.4.57-rc.0 + +### Patch Changes + +-
    Updated dependencies [f7d47dd3517ec14ca2ec5c3c95fcdf9e1e2fb8b0, 4c3984593017d59edd631bf8ae4f35f9d3c3db36, ae9f740d6af20557eac61b4af902c868b4132b49, b6b04aadfcc8558f888b334e37c46a77e5816237, 4704bf81ca370f120af32185a7c55407a26f8514, 12897e25d0dc25b7373f5264d38f38a5a7444257, e45585b70a3a7b75434c88e4b2ea9af0a0764a76, b1c2668b74bfb49ebaefe2f581b2f8be5d4d1dd6]: + + - @rocket.chat/model-typings@2.3.0-rc.0 + - @rocket.chat/models@2.3.0-rc.0 + - @rocket.chat/rest-typings@8.5.0-rc.0 + - @rocket.chat/core-typings@8.5.0-rc.0 + - @rocket.chat/core-services@0.14.1-rc.0 + - @rocket.chat/network-broker@0.2.36-rc.0 +
    + ## 0.4.56 ### Patch Changes diff --git a/ee/apps/account-service/package.json b/ee/apps/account-service/package.json index e31f7a1c992ff..968ae4a0108c5 100644 --- a/ee/apps/account-service/package.json +++ b/ee/apps/account-service/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/account-service", - "version": "0.4.56", + "version": "0.4.57", "private": true, "description": "Rocket.Chat Account service", "keywords": [ diff --git a/ee/apps/authorization-service/CHANGELOG.md b/ee/apps/authorization-service/CHANGELOG.md index 7c3279fde4dca..ffedb6c068597 100644 --- a/ee/apps/authorization-service/CHANGELOG.md +++ b/ee/apps/authorization-service/CHANGELOG.md @@ -1,5 +1,35 @@ # @rocket.chat/authorization-service +## 0.6.1 + +### Patch Changes + +-
    Updated dependencies [f7d47dd3517ec14ca2ec5c3c95fcdf9e1e2fb8b0, 4c3984593017d59edd631bf8ae4f35f9d3c3db36, b6b04aadfcc8558f888b334e37c46a77e5816237, 4704bf81ca370f120af32185a7c55407a26f8514, 12897e25d0dc25b7373f5264d38f38a5a7444257, e45585b70a3a7b75434c88e4b2ea9af0a0764a76, 2d32e52073dd1a68bd12a093b3a673ae297cb4ee, b1c2668b74bfb49ebaefe2f581b2f8be5d4d1dd6]: + + - @rocket.chat/model-typings@2.3.0 + - @rocket.chat/models@2.3.0 + - @rocket.chat/rest-typings@8.5.0 + - @rocket.chat/core-typings@8.5.0 + - @rocket.chat/abac@0.2.1 + - @rocket.chat/network-broker@0.2.36 + - @rocket.chat/core-services@0.14.1 +
    + +## 0.6.1-rc.0 + +### Patch Changes + +-
    Updated dependencies [f7d47dd3517ec14ca2ec5c3c95fcdf9e1e2fb8b0, 4c3984593017d59edd631bf8ae4f35f9d3c3db36, ae9f740d6af20557eac61b4af902c868b4132b49, b6b04aadfcc8558f888b334e37c46a77e5816237, 4704bf81ca370f120af32185a7c55407a26f8514, 12897e25d0dc25b7373f5264d38f38a5a7444257, e45585b70a3a7b75434c88e4b2ea9af0a0764a76, 2d32e52073dd1a68bd12a093b3a673ae297cb4ee, b1c2668b74bfb49ebaefe2f581b2f8be5d4d1dd6]: + + - @rocket.chat/model-typings@2.3.0-rc.0 + - @rocket.chat/models@2.3.0-rc.0 + - @rocket.chat/rest-typings@8.5.0-rc.0 + - @rocket.chat/core-typings@8.5.0-rc.0 + - @rocket.chat/abac@0.2.1-rc.0 + - @rocket.chat/core-services@0.14.1-rc.0 + - @rocket.chat/network-broker@0.2.36-rc.0 +
    + ## 0.6.0 ### Minor Changes diff --git a/ee/apps/authorization-service/package.json b/ee/apps/authorization-service/package.json index e8a30772c68e6..ca8614c9ca6b0 100644 --- a/ee/apps/authorization-service/package.json +++ b/ee/apps/authorization-service/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/authorization-service", - "version": "0.6.0", + "version": "0.6.1", "private": true, "description": "Rocket.Chat Authorization service", "keywords": [ diff --git a/ee/apps/ddp-streamer/CHANGELOG.md b/ee/apps/ddp-streamer/CHANGELOG.md index 0a194196e7b09..1d7f8e2c0aef0 100644 --- a/ee/apps/ddp-streamer/CHANGELOG.md +++ b/ee/apps/ddp-streamer/CHANGELOG.md @@ -1,5 +1,35 @@ # @rocket.chat/ddp-streamer +## 0.3.57 + +### Patch Changes + +-
    Updated dependencies [f7d47dd3517ec14ca2ec5c3c95fcdf9e1e2fb8b0, 4c3984593017d59edd631bf8ae4f35f9d3c3db36, b6b04aadfcc8558f888b334e37c46a77e5816237, 4704bf81ca370f120af32185a7c55407a26f8514, 12897e25d0dc25b7373f5264d38f38a5a7444257, e45585b70a3a7b75434c88e4b2ea9af0a0764a76, b1c2668b74bfb49ebaefe2f581b2f8be5d4d1dd6]: + + - @rocket.chat/model-typings@2.3.0 + - @rocket.chat/models@2.3.0 + - @rocket.chat/rest-typings@8.5.0 + - @rocket.chat/core-typings@8.5.0 + - @rocket.chat/network-broker@0.2.36 + - @rocket.chat/core-services@0.14.1 + - @rocket.chat/instance-status@0.1.57 +
    + +## 0.3.57-rc.0 + +### Patch Changes + +-
    Updated dependencies [f7d47dd3517ec14ca2ec5c3c95fcdf9e1e2fb8b0, 4c3984593017d59edd631bf8ae4f35f9d3c3db36, ae9f740d6af20557eac61b4af902c868b4132b49, b6b04aadfcc8558f888b334e37c46a77e5816237, 4704bf81ca370f120af32185a7c55407a26f8514, 12897e25d0dc25b7373f5264d38f38a5a7444257, e45585b70a3a7b75434c88e4b2ea9af0a0764a76, b1c2668b74bfb49ebaefe2f581b2f8be5d4d1dd6]: + + - @rocket.chat/model-typings@2.3.0-rc.0 + - @rocket.chat/models@2.3.0-rc.0 + - @rocket.chat/rest-typings@8.5.0-rc.0 + - @rocket.chat/core-typings@8.5.0-rc.0 + - @rocket.chat/core-services@0.14.1-rc.0 + - @rocket.chat/instance-status@0.1.57-rc.0 + - @rocket.chat/network-broker@0.2.36-rc.0 +
    + ## 0.3.56 ### Patch Changes diff --git a/ee/apps/ddp-streamer/package.json b/ee/apps/ddp-streamer/package.json index 5208f5ada06d0..4c986b920dcb4 100644 --- a/ee/apps/ddp-streamer/package.json +++ b/ee/apps/ddp-streamer/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/ddp-streamer", - "version": "0.3.56", + "version": "0.3.57", "private": true, "description": "Rocket.Chat DDP-Streamer service", "keywords": [ diff --git a/ee/apps/omnichannel-transcript/CHANGELOG.md b/ee/apps/omnichannel-transcript/CHANGELOG.md index 4dc2de0269cc7..71986b5505c30 100644 --- a/ee/apps/omnichannel-transcript/CHANGELOG.md +++ b/ee/apps/omnichannel-transcript/CHANGELOG.md @@ -1,5 +1,35 @@ # @rocket.chat/omnichannel-transcript +## 0.4.57 + +### Patch Changes + +-
    Updated dependencies [f7d47dd3517ec14ca2ec5c3c95fcdf9e1e2fb8b0, cdb264fec803e234a6ad2000018b31d4b2074e99, b6b04aadfcc8558f888b334e37c46a77e5816237, ad7d42400ea36f1eb0aaf7cc3361c77fdabf9ebc, 4704bf81ca370f120af32185a7c55407a26f8514, d427b808c1f79d9d1baa05bb5b5ef805b6ef5f6d, ebc9babf55dd26613027c28dcacf77909116b342, fac64728505b312d5da786e92d3134450ce4a7c1, 12897e25d0dc25b7373f5264d38f38a5a7444257, e45585b70a3a7b75434c88e4b2ea9af0a0764a76]: + + - @rocket.chat/model-typings@2.3.0 + - @rocket.chat/models@2.3.0 + - @rocket.chat/i18n@3.1.0 + - @rocket.chat/core-typings@8.5.0 + - @rocket.chat/network-broker@0.2.36 + - @rocket.chat/omnichannel-services@0.3.54 + - @rocket.chat/core-services@0.14.1 +
    + +## 0.4.57-rc.0 + +### Patch Changes + +-
    Updated dependencies [f7d47dd3517ec14ca2ec5c3c95fcdf9e1e2fb8b0, cdb264fec803e234a6ad2000018b31d4b2074e99, ae9f740d6af20557eac61b4af902c868b4132b49, b6b04aadfcc8558f888b334e37c46a77e5816237, ad7d42400ea36f1eb0aaf7cc3361c77fdabf9ebc, 4704bf81ca370f120af32185a7c55407a26f8514, d427b808c1f79d9d1baa05bb5b5ef805b6ef5f6d, ebc9babf55dd26613027c28dcacf77909116b342, fac64728505b312d5da786e92d3134450ce4a7c1, 12897e25d0dc25b7373f5264d38f38a5a7444257, e45585b70a3a7b75434c88e4b2ea9af0a0764a76]: + + - @rocket.chat/model-typings@2.3.0-rc.0 + - @rocket.chat/models@2.3.0-rc.0 + - @rocket.chat/i18n@3.1.0-rc.0 + - @rocket.chat/core-typings@8.5.0-rc.0 + - @rocket.chat/core-services@0.14.1-rc.0 + - @rocket.chat/omnichannel-services@0.3.54-rc.0 + - @rocket.chat/network-broker@0.2.36-rc.0 +
    + ## 0.4.56 ### Patch Changes diff --git a/ee/apps/omnichannel-transcript/package.json b/ee/apps/omnichannel-transcript/package.json index bfad54193420d..94ee9402bd281 100644 --- a/ee/apps/omnichannel-transcript/package.json +++ b/ee/apps/omnichannel-transcript/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/omnichannel-transcript", - "version": "0.4.56", + "version": "0.4.57", "private": true, "description": "Rocket.Chat service", "keywords": [ diff --git a/ee/apps/presence-service/CHANGELOG.md b/ee/apps/presence-service/CHANGELOG.md index c139726a55dec..225c932f5a9db 100644 --- a/ee/apps/presence-service/CHANGELOG.md +++ b/ee/apps/presence-service/CHANGELOG.md @@ -1,5 +1,33 @@ # @rocket.chat/presence-service +## 0.4.57 + +### Patch Changes + +-
    Updated dependencies [f7d47dd3517ec14ca2ec5c3c95fcdf9e1e2fb8b0, b6b04aadfcc8558f888b334e37c46a77e5816237, 4704bf81ca370f120af32185a7c55407a26f8514, 12897e25d0dc25b7373f5264d38f38a5a7444257, e45585b70a3a7b75434c88e4b2ea9af0a0764a76]: + + - @rocket.chat/model-typings@2.3.0 + - @rocket.chat/models@2.3.0 + - @rocket.chat/core-typings@8.5.0 + - @rocket.chat/network-broker@0.2.36 + - @rocket.chat/presence@0.2.57 + - @rocket.chat/core-services@0.14.1 +
    + +## 0.4.57-rc.0 + +### Patch Changes + +-
    Updated dependencies [f7d47dd3517ec14ca2ec5c3c95fcdf9e1e2fb8b0, ae9f740d6af20557eac61b4af902c868b4132b49, b6b04aadfcc8558f888b334e37c46a77e5816237, 4704bf81ca370f120af32185a7c55407a26f8514, 12897e25d0dc25b7373f5264d38f38a5a7444257, e45585b70a3a7b75434c88e4b2ea9af0a0764a76]: + + - @rocket.chat/model-typings@2.3.0-rc.0 + - @rocket.chat/models@2.3.0-rc.0 + - @rocket.chat/core-typings@8.5.0-rc.0 + - @rocket.chat/core-services@0.14.1-rc.0 + - @rocket.chat/presence@0.2.57-rc.0 + - @rocket.chat/network-broker@0.2.36-rc.0 +
    + ## 0.4.56 ### Patch Changes diff --git a/ee/apps/presence-service/package.json b/ee/apps/presence-service/package.json index f181146320eac..f7c15e626018d 100644 --- a/ee/apps/presence-service/package.json +++ b/ee/apps/presence-service/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/presence-service", - "version": "0.4.56", + "version": "0.4.57", "private": true, "description": "Rocket.Chat Presence service", "keywords": [ diff --git a/ee/apps/queue-worker/CHANGELOG.md b/ee/apps/queue-worker/CHANGELOG.md index c439ba194514d..b55c3e93ef5dc 100644 --- a/ee/apps/queue-worker/CHANGELOG.md +++ b/ee/apps/queue-worker/CHANGELOG.md @@ -1,5 +1,33 @@ # @rocket.chat/queue-worker +## 0.4.57 + +### Patch Changes + +-
    Updated dependencies [f7d47dd3517ec14ca2ec5c3c95fcdf9e1e2fb8b0, b6b04aadfcc8558f888b334e37c46a77e5816237, 4704bf81ca370f120af32185a7c55407a26f8514, 12897e25d0dc25b7373f5264d38f38a5a7444257, e45585b70a3a7b75434c88e4b2ea9af0a0764a76]: + + - @rocket.chat/model-typings@2.3.0 + - @rocket.chat/models@2.3.0 + - @rocket.chat/core-typings@8.5.0 + - @rocket.chat/network-broker@0.2.36 + - @rocket.chat/omnichannel-services@0.3.54 + - @rocket.chat/core-services@0.14.1 +
    + +## 0.4.57-rc.0 + +### Patch Changes + +-
    Updated dependencies [f7d47dd3517ec14ca2ec5c3c95fcdf9e1e2fb8b0, ae9f740d6af20557eac61b4af902c868b4132b49, b6b04aadfcc8558f888b334e37c46a77e5816237, 4704bf81ca370f120af32185a7c55407a26f8514, 12897e25d0dc25b7373f5264d38f38a5a7444257, e45585b70a3a7b75434c88e4b2ea9af0a0764a76]: + + - @rocket.chat/model-typings@2.3.0-rc.0 + - @rocket.chat/models@2.3.0-rc.0 + - @rocket.chat/core-typings@8.5.0-rc.0 + - @rocket.chat/core-services@0.14.1-rc.0 + - @rocket.chat/omnichannel-services@0.3.54-rc.0 + - @rocket.chat/network-broker@0.2.36-rc.0 +
    + ## 0.4.56 ### Patch Changes diff --git a/ee/apps/queue-worker/package.json b/ee/apps/queue-worker/package.json index d1ba5b797aa56..3d3959b7c5336 100644 --- a/ee/apps/queue-worker/package.json +++ b/ee/apps/queue-worker/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/queue-worker", - "version": "0.4.56", + "version": "0.4.57", "private": true, "description": "Rocket.Chat service", "keywords": [ diff --git a/ee/packages/abac/CHANGELOG.md b/ee/packages/abac/CHANGELOG.md index 1fc9f380f9692..147cfd69cd7c5 100644 --- a/ee/packages/abac/CHANGELOG.md +++ b/ee/packages/abac/CHANGELOG.md @@ -1,5 +1,33 @@ # @rocket.chat/abac +## 0.2.1 + +### Patch Changes + +- ([#40499](https://github.com/RocketChat/Rocket.Chat/pull/40499)) Fixes an issue where some actions made by the abac service were not broadcasting to clients, which affected reactivity + +-
    Updated dependencies [f7d47dd3517ec14ca2ec5c3c95fcdf9e1e2fb8b0, b6b04aadfcc8558f888b334e37c46a77e5816237, 4704bf81ca370f120af32185a7c55407a26f8514, 12897e25d0dc25b7373f5264d38f38a5a7444257, e45585b70a3a7b75434c88e4b2ea9af0a0764a76]: + + - @rocket.chat/models@2.3.0 + - @rocket.chat/core-typings@8.5.0 + - @rocket.chat/core-services@0.14.1 + - @rocket.chat/server-fetch@0.2.1 +
    + +## 0.2.1-rc.0 + +### Patch Changes + +- ([#40499](https://github.com/RocketChat/Rocket.Chat/pull/40499)) Fixes an issue where some actions made by the abac service were not broadcasting to clients, which affected reactivity + +-
    Updated dependencies [f7d47dd3517ec14ca2ec5c3c95fcdf9e1e2fb8b0, ae9f740d6af20557eac61b4af902c868b4132b49, b6b04aadfcc8558f888b334e37c46a77e5816237, 4704bf81ca370f120af32185a7c55407a26f8514, 12897e25d0dc25b7373f5264d38f38a5a7444257, e45585b70a3a7b75434c88e4b2ea9af0a0764a76]: + + - @rocket.chat/models@2.3.0-rc.0 + - @rocket.chat/core-typings@8.5.0-rc.0 + - @rocket.chat/core-services@0.14.1-rc.0 + - @rocket.chat/server-fetch@0.2.1-rc.0 +
    + ## 0.2.0 ### Minor Changes diff --git a/ee/packages/abac/package.json b/ee/packages/abac/package.json index bc675e5f103c5..7d1bd2ec24aac 100644 --- a/ee/packages/abac/package.json +++ b/ee/packages/abac/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/abac", - "version": "0.2.0", + "version": "0.2.1", "private": true, "description": "Rocket.Chat - Attribute Based Access Control (ABAC) support utilities", "main": "./dist/index.js", diff --git a/ee/packages/federation-matrix/CHANGELOG.md b/ee/packages/federation-matrix/CHANGELOG.md index 3b6121e4719b2..a0e92b24ec38b 100644 --- a/ee/packages/federation-matrix/CHANGELOG.md +++ b/ee/packages/federation-matrix/CHANGELOG.md @@ -1,5 +1,31 @@ # @rocket.chat/federation-matrix +## 0.1.4 + +### Patch Changes + +-
    Updated dependencies [f7d47dd3517ec14ca2ec5c3c95fcdf9e1e2fb8b0, 4c3984593017d59edd631bf8ae4f35f9d3c3db36, b6b04aadfcc8558f888b334e37c46a77e5816237, 4704bf81ca370f120af32185a7c55407a26f8514, 12897e25d0dc25b7373f5264d38f38a5a7444257, e45585b70a3a7b75434c88e4b2ea9af0a0764a76, b1c2668b74bfb49ebaefe2f581b2f8be5d4d1dd6]: + + - @rocket.chat/models@2.3.0 + - @rocket.chat/rest-typings@8.5.0 + - @rocket.chat/core-typings@8.5.0 + - @rocket.chat/network-broker@0.2.36 + - @rocket.chat/core-services@0.14.1 +
    + +## 0.1.4-rc.0 + +### Patch Changes + +-
    Updated dependencies [f7d47dd3517ec14ca2ec5c3c95fcdf9e1e2fb8b0, 4c3984593017d59edd631bf8ae4f35f9d3c3db36, ae9f740d6af20557eac61b4af902c868b4132b49, b6b04aadfcc8558f888b334e37c46a77e5816237, 4704bf81ca370f120af32185a7c55407a26f8514, 12897e25d0dc25b7373f5264d38f38a5a7444257, e45585b70a3a7b75434c88e4b2ea9af0a0764a76, b1c2668b74bfb49ebaefe2f581b2f8be5d4d1dd6]: + + - @rocket.chat/models@2.3.0-rc.0 + - @rocket.chat/rest-typings@8.5.0-rc.0 + - @rocket.chat/core-typings@8.5.0-rc.0 + - @rocket.chat/core-services@0.14.1-rc.0 + - @rocket.chat/network-broker@0.2.36-rc.0 +
    + ## 0.1.3 ### Patch Changes diff --git a/ee/packages/federation-matrix/package.json b/ee/packages/federation-matrix/package.json index e28e6ec097f1c..e8b631ca29367 100644 --- a/ee/packages/federation-matrix/package.json +++ b/ee/packages/federation-matrix/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/federation-matrix", - "version": "0.1.3", + "version": "0.1.4", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/ee/packages/media-calls/CHANGELOG.md b/ee/packages/media-calls/CHANGELOG.md index 505fa6860b453..784518970b528 100644 --- a/ee/packages/media-calls/CHANGELOG.md +++ b/ee/packages/media-calls/CHANGELOG.md @@ -1,5 +1,33 @@ # @rocket.chat/media-calls +## 0.5.0 + +### Minor Changes + +- ([#40197](https://github.com/RocketChat/Rocket.Chat/pull/40197)) Fixes a server error when Drachtio connection is lost while a SIP call is active + +### Patch Changes + +-
    Updated dependencies [f7d47dd3517ec14ca2ec5c3c95fcdf9e1e2fb8b0, b6b04aadfcc8558f888b334e37c46a77e5816237, 4704bf81ca370f120af32185a7c55407a26f8514, 12897e25d0dc25b7373f5264d38f38a5a7444257, e45585b70a3a7b75434c88e4b2ea9af0a0764a76]: + + - @rocket.chat/models@2.3.0 + - @rocket.chat/core-typings@8.5.0 +
    + +## 0.5.0-rc.0 + +### Minor Changes + +- ([#40197](https://github.com/RocketChat/Rocket.Chat/pull/40197)) Fixes a server error when Drachtio connection is lost while a SIP call is active + +### Patch Changes + +-
    Updated dependencies [f7d47dd3517ec14ca2ec5c3c95fcdf9e1e2fb8b0, ae9f740d6af20557eac61b4af902c868b4132b49, b6b04aadfcc8558f888b334e37c46a77e5816237, 4704bf81ca370f120af32185a7c55407a26f8514, 12897e25d0dc25b7373f5264d38f38a5a7444257, e45585b70a3a7b75434c88e4b2ea9af0a0764a76]: + + - @rocket.chat/models@2.3.0-rc.0 + - @rocket.chat/core-typings@8.5.0-rc.0 +
    + ## 0.4.0 ### Minor Changes diff --git a/ee/packages/media-calls/package.json b/ee/packages/media-calls/package.json index 3216f8e6f4a47..b842dddff1d57 100644 --- a/ee/packages/media-calls/package.json +++ b/ee/packages/media-calls/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/media-calls", - "version": "0.4.0", + "version": "0.5.0", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/ee/packages/network-broker/CHANGELOG.md b/ee/packages/network-broker/CHANGELOG.md index 7d84d2a057a6e..9862f9afea9ca 100644 --- a/ee/packages/network-broker/CHANGELOG.md +++ b/ee/packages/network-broker/CHANGELOG.md @@ -1,5 +1,23 @@ # @rocket.chat/network-broker +## 0.2.36 + +### Patch Changes + +-
    Updated dependencies []: + + - @rocket.chat/core-services@0.14.1 +
    + +## 0.2.36-rc.0 + +### Patch Changes + +-
    Updated dependencies []: + + - @rocket.chat/core-services@0.14.1-rc.0 +
    + ## 0.2.35 ### Patch Changes diff --git a/ee/packages/network-broker/package.json b/ee/packages/network-broker/package.json index b7eb298176ea5..fe908bf29c983 100644 --- a/ee/packages/network-broker/package.json +++ b/ee/packages/network-broker/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/network-broker", - "version": "0.2.35", + "version": "0.2.36", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/ee/packages/omni-core-ee/CHANGELOG.md b/ee/packages/omni-core-ee/CHANGELOG.md index 7f4d11f241498..26eacac550d57 100644 --- a/ee/packages/omni-core-ee/CHANGELOG.md +++ b/ee/packages/omni-core-ee/CHANGELOG.md @@ -1,5 +1,27 @@ # @rocket.chat/omni-core-ee +## 0.0.22 + +### Patch Changes + +-
    Updated dependencies [f7d47dd3517ec14ca2ec5c3c95fcdf9e1e2fb8b0, b6b04aadfcc8558f888b334e37c46a77e5816237, 4704bf81ca370f120af32185a7c55407a26f8514, 12897e25d0dc25b7373f5264d38f38a5a7444257, e45585b70a3a7b75434c88e4b2ea9af0a0764a76]: + + - @rocket.chat/models@2.3.0 + - @rocket.chat/core-services@0.14.1 + - @rocket.chat/omni-core@0.1.1 +
    + +## 0.0.22-rc.0 + +### Patch Changes + +-
    Updated dependencies [f7d47dd3517ec14ca2ec5c3c95fcdf9e1e2fb8b0, ae9f740d6af20557eac61b4af902c868b4132b49, b6b04aadfcc8558f888b334e37c46a77e5816237, 4704bf81ca370f120af32185a7c55407a26f8514, 12897e25d0dc25b7373f5264d38f38a5a7444257, e45585b70a3a7b75434c88e4b2ea9af0a0764a76]: + + - @rocket.chat/models@2.3.0-rc.0 + - @rocket.chat/core-services@0.14.1-rc.0 + - @rocket.chat/omni-core@0.1.1-rc.0 +
    + ## 0.0.21 ### Patch Changes diff --git a/ee/packages/omni-core-ee/package.json b/ee/packages/omni-core-ee/package.json index 82e25524f151c..1a89c3ddd560b 100644 --- a/ee/packages/omni-core-ee/package.json +++ b/ee/packages/omni-core-ee/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/omni-core-ee", - "version": "0.0.21", + "version": "0.0.22", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/ee/packages/omnichannel-services/CHANGELOG.md b/ee/packages/omnichannel-services/CHANGELOG.md index f59907529b2f8..c880a2f26afaa 100644 --- a/ee/packages/omnichannel-services/CHANGELOG.md +++ b/ee/packages/omnichannel-services/CHANGELOG.md @@ -1,5 +1,33 @@ # @rocket.chat/omnichannel-services +## 0.3.54 + +### Patch Changes + +-
    Updated dependencies [f7d47dd3517ec14ca2ec5c3c95fcdf9e1e2fb8b0, cdb264fec803e234a6ad2000018b31d4b2074e99, 4c3984593017d59edd631bf8ae4f35f9d3c3db36, b6b04aadfcc8558f888b334e37c46a77e5816237, ad7d42400ea36f1eb0aaf7cc3361c77fdabf9ebc, 4704bf81ca370f120af32185a7c55407a26f8514, d427b808c1f79d9d1baa05bb5b5ef805b6ef5f6d, ebc9babf55dd26613027c28dcacf77909116b342, fac64728505b312d5da786e92d3134450ce4a7c1, 12897e25d0dc25b7373f5264d38f38a5a7444257, e45585b70a3a7b75434c88e4b2ea9af0a0764a76, b1c2668b74bfb49ebaefe2f581b2f8be5d4d1dd6]: + + - @rocket.chat/model-typings@2.3.0 + - @rocket.chat/models@2.3.0 + - @rocket.chat/i18n@3.1.0 + - @rocket.chat/rest-typings@8.5.0 + - @rocket.chat/core-typings@8.5.0 + - @rocket.chat/core-services@0.14.1 +
    + +## 0.3.54-rc.0 + +### Patch Changes + +-
    Updated dependencies [f7d47dd3517ec14ca2ec5c3c95fcdf9e1e2fb8b0, cdb264fec803e234a6ad2000018b31d4b2074e99, 4c3984593017d59edd631bf8ae4f35f9d3c3db36, ae9f740d6af20557eac61b4af902c868b4132b49, b6b04aadfcc8558f888b334e37c46a77e5816237, ad7d42400ea36f1eb0aaf7cc3361c77fdabf9ebc, 4704bf81ca370f120af32185a7c55407a26f8514, d427b808c1f79d9d1baa05bb5b5ef805b6ef5f6d, ebc9babf55dd26613027c28dcacf77909116b342, fac64728505b312d5da786e92d3134450ce4a7c1, 12897e25d0dc25b7373f5264d38f38a5a7444257, e45585b70a3a7b75434c88e4b2ea9af0a0764a76, b1c2668b74bfb49ebaefe2f581b2f8be5d4d1dd6]: + + - @rocket.chat/model-typings@2.3.0-rc.0 + - @rocket.chat/models@2.3.0-rc.0 + - @rocket.chat/i18n@3.1.0-rc.0 + - @rocket.chat/rest-typings@8.5.0-rc.0 + - @rocket.chat/core-typings@8.5.0-rc.0 + - @rocket.chat/core-services@0.14.1-rc.0 +
    + ## 0.3.53 ### Patch Changes diff --git a/ee/packages/omnichannel-services/package.json b/ee/packages/omnichannel-services/package.json index ce32a970cb410..99eb7175aac5e 100644 --- a/ee/packages/omnichannel-services/package.json +++ b/ee/packages/omnichannel-services/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/omnichannel-services", - "version": "0.3.53", + "version": "0.3.54", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/ee/packages/presence/CHANGELOG.md b/ee/packages/presence/CHANGELOG.md index c78e84e7569da..b2e8aa4d8d0dd 100644 --- a/ee/packages/presence/CHANGELOG.md +++ b/ee/packages/presence/CHANGELOG.md @@ -1,5 +1,27 @@ # @rocket.chat/presence +## 0.2.57 + +### Patch Changes + +-
    Updated dependencies [f7d47dd3517ec14ca2ec5c3c95fcdf9e1e2fb8b0, b6b04aadfcc8558f888b334e37c46a77e5816237, 4704bf81ca370f120af32185a7c55407a26f8514, 12897e25d0dc25b7373f5264d38f38a5a7444257, e45585b70a3a7b75434c88e4b2ea9af0a0764a76]: + + - @rocket.chat/models@2.3.0 + - @rocket.chat/core-typings@8.5.0 + - @rocket.chat/core-services@0.14.1 +
    + +## 0.2.57-rc.0 + +### Patch Changes + +-
    Updated dependencies [f7d47dd3517ec14ca2ec5c3c95fcdf9e1e2fb8b0, ae9f740d6af20557eac61b4af902c868b4132b49, b6b04aadfcc8558f888b334e37c46a77e5816237, 4704bf81ca370f120af32185a7c55407a26f8514, 12897e25d0dc25b7373f5264d38f38a5a7444257, e45585b70a3a7b75434c88e4b2ea9af0a0764a76]: + + - @rocket.chat/models@2.3.0-rc.0 + - @rocket.chat/core-typings@8.5.0-rc.0 + - @rocket.chat/core-services@0.14.1-rc.0 +
    + ## 0.2.56 ### Patch Changes diff --git a/ee/packages/presence/package.json b/ee/packages/presence/package.json index d9fff7da45563..e4c937b93b140 100644 --- a/ee/packages/presence/package.json +++ b/ee/packages/presence/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/presence", - "version": "0.2.56", + "version": "0.2.57", "private": true, "main": "./dist/Presence.js", "typings": "./dist/Presence.d.ts", diff --git a/packages/apps-engine/CHANGELOG.md b/packages/apps-engine/CHANGELOG.md index b8d579c872f13..3d0cd73d97b73 100644 --- a/packages/apps-engine/CHANGELOG.md +++ b/packages/apps-engine/CHANGELOG.md @@ -1,5 +1,25 @@ # @rocket.chat/apps-engine +## 1.63.0 + +### Minor Changes + +- ([#40343](https://github.com/RocketChat/Rocket.Chat/pull/40343)) Remove files that weren't accessible to apps at development time + +- ([#40463](https://github.com/RocketChat/Rocket.Chat/pull/40463)) Allows apps with the right permission to read room's ABAC attributes. + +- ([#40604](https://github.com/RocketChat/Rocket.Chat/pull/40604)) Adds the capability for fetching a user by their sip extension to the apps + +## 1.63.0-rc.0 + +### Minor Changes + +- ([#40343](https://github.com/RocketChat/Rocket.Chat/pull/40343)) Remove files that weren't accessible to apps at development time + +- ([#40463](https://github.com/RocketChat/Rocket.Chat/pull/40463)) Allows apps with the right permission to read room's ABAC attributes. + +- ([#40604](https://github.com/RocketChat/Rocket.Chat/pull/40604)) Adds the capability for fetching a user by their sip extension to the apps + ## 1.62.0 ### Minor Changes diff --git a/packages/apps-engine/package.json b/packages/apps-engine/package.json index a160cbd2952e2..2451228da8608 100644 --- a/packages/apps-engine/package.json +++ b/packages/apps-engine/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/apps-engine", - "version": "1.62.0", + "version": "1.63.0", "description": "The public API and type definitions for Rocket.Chat App development.", "keywords": [ "rocket.chat", @@ -66,11 +66,11 @@ }, "devDependencies": { "@rocket.chat/ui-kit": "workspace:~", - "@types/node": "~22.16.5", - "eslint": "~9.39.3", + "@types/node": "~22.19.17", + "eslint": "~9.39.4", "npm-run-all": "^4.1.5", "rimraf": "^6.0.1", - "typedoc": "~0.28.16", + "typedoc": "~0.28.10", "typescript": "~5.9.3" }, "volta": { diff --git a/packages/apps-engine/src/definition/metadata/AppPermissions.ts b/packages/apps-engine/src/definition/metadata/AppPermissions.ts new file mode 100644 index 0000000000000..4d02fe63abd9e --- /dev/null +++ b/packages/apps-engine/src/definition/metadata/AppPermissions.ts @@ -0,0 +1,166 @@ +import type { INetworkingPermission, IPermission, IReadSettingPermission, IWorkspaceTokenPermission } from '../permissions/IPermission'; + +/** + * @description + * + * App Permission naming rules: + * + * 'scope-name': { + * 'permission-name': { name: 'scope-name.permission-name' } + * } + * + * You can retrieve this permission by using: + * AppPermissions['scope-name']['permission-name'] -> { name: 'scope-name.permission-name' } + * + * @example + * + * AppPermissions.upload.read // { name: 'upload.read', domains: [] } + */ +export const AppPermissions = { + 'user': { + read: { name: 'user.read' }, + write: { name: 'user.write' }, + }, + 'upload': { + read: { name: 'upload.read' }, + write: { name: 'upload.write' }, + }, + 'email': { + send: { name: 'email.send' }, + }, + 'ui': { + interaction: { name: 'ui.interact' }, + registerButtons: { name: 'ui.registerButtons' }, + }, + 'setting': { + read: { name: 'server-setting.read', hiddenSettings: [] } as IReadSettingPermission, + write: { name: 'server-setting.write' }, + }, + 'room': { + 'read': { name: 'room.read' }, + 'write': { name: 'room.write' }, + 'system-view-all': { name: 'room.system.view-all' }, + }, + 'role': { + read: { name: 'role.read' }, + write: { name: 'role.write' }, + }, + 'message': { + read: { name: 'message.read' }, + write: { name: 'message.write' }, + }, + 'moderation': { + read: { name: 'moderation.read' }, + write: { name: 'moderation.write' }, + }, + 'contact': { + read: { name: 'contact.read' }, + write: { name: 'contact.write' }, + }, + 'threads': { + read: { name: 'threads.read' }, + }, + 'livechat-status': { + read: { name: 'livechat-status.read' }, + }, + 'livechat-custom-fields': { + write: { name: 'livechat-custom-fields.write' }, + }, + 'livechat-visitor': { + read: { name: 'livechat-visitor.read' }, + write: { name: 'livechat-visitor.write' }, + }, + 'livechat-message': { + read: { name: 'livechat-message.read' }, + write: { name: 'livechat-message.write' }, + multiple: { name: 'livechat-message.multiple' }, + }, + 'livechat-room': { + read: { name: 'livechat-room.read' }, + write: { name: 'livechat-room.write' }, + }, + 'livechat-department': { + read: { name: 'livechat-department.read' }, + write: { name: 'livechat-department.write' }, + multiple: { name: 'livechat-department.multiple' }, + }, + 'env': { + read: { name: 'env.read' }, + }, + 'cloud': { + 'workspace-token': { name: 'cloud.workspace-token', scopes: [] } as IWorkspaceTokenPermission, + }, + // Internal permissions + 'scheduler': { + default: { name: 'scheduler' }, + }, + 'networking': { + default: { name: 'networking', domains: [] } as INetworkingPermission, + }, + 'persistence': { + default: { name: 'persistence' }, + }, + 'command': { + default: { name: 'slashcommand' }, + }, + 'videoConference': { + read: { name: 'video-conference.read' }, + write: { name: 'video-conference.write' }, + provider: { name: 'video-conference-provider' }, + }, + 'apis': { + default: { name: 'api' }, + }, + 'oauth-app': { + read: { name: 'oauth-app.read' }, + write: { name: 'oauth-app.write' }, + }, + 'outboundComms': { + provide: { name: 'outbound-communication.provide' }, + }, + 'experimental': { + default: { name: 'experimental.default' }, + }, + 'abac': { + read: { name: 'abac.read' }, + }, +}; + +/** + * @description + * Default permissions for apps + * Used to ensure backward compatibility with apps + * that were developed before the permission system was introduced. + */ +export const defaultPermissions: Array = [ + AppPermissions.user.read, + AppPermissions.user.write, + AppPermissions.upload.read, + AppPermissions.upload.write, + AppPermissions.ui.interaction, + AppPermissions.setting.read, + AppPermissions.setting.write, + AppPermissions.room.read, + AppPermissions.room.write, + AppPermissions.message.read, + AppPermissions.message.write, + AppPermissions['livechat-department'].read, + AppPermissions['livechat-department'].write, + AppPermissions['livechat-room'].read, + AppPermissions['livechat-room'].write, + AppPermissions['livechat-message'].read, + AppPermissions['livechat-message'].write, + AppPermissions['livechat-visitor'].read, + AppPermissions['livechat-visitor'].write, + AppPermissions['livechat-status'].read, + AppPermissions['livechat-custom-fields'].write, + AppPermissions.scheduler.default, + AppPermissions.networking.default, + AppPermissions.persistence.default, + AppPermissions.env.read, + AppPermissions.command.default, + AppPermissions.videoConference.provider, + AppPermissions.videoConference.read, + AppPermissions.videoConference.write, + AppPermissions.apis.default, +]; diff --git a/packages/apps-engine/src/definition/metadata/index.ts b/packages/apps-engine/src/definition/metadata/index.ts index 7ebcad79d20d8..37e5aea83c1bb 100644 --- a/packages/apps-engine/src/definition/metadata/index.ts +++ b/packages/apps-engine/src/definition/metadata/index.ts @@ -4,6 +4,7 @@ import type { IAppInfo } from './IAppInfo'; import { RocketChatAssociationModel, RocketChatAssociationRecord } from './RocketChatAssociations'; export * from './AppInterface'; +export * from './AppPermissions'; export type { IAppAuthorInfo, IAppInfo }; export { AppMethod, RocketChatAssociationModel, RocketChatAssociationRecord }; diff --git a/packages/apps-engine/src/definition/version.ts b/packages/apps-engine/src/definition/version.ts deleted file mode 100644 index 8feda95c5ad5d..0000000000000 --- a/packages/apps-engine/src/definition/version.ts +++ /dev/null @@ -1,16 +0,0 @@ -/** - * The version of the Apps-Engine package. - * Consumed by host-side code (e.g. AppPackageParser) to validate app compatibility - * without relying on filesystem path traversal. - * - * Uses require() instead of a static import so TypeScript does not resolve the path - * at compile time. - * - * When running for tests, using ts-node, package.json is located two levels above the current file. - * When running in production, package.json is located one level above the compiled version of this file. - */ -const runningFromSource = __dirname.endsWith('src/definition'); -const requirePath = runningFromSource ? '../../package.json' : '../package.json'; - -// eslint-disable-next-line import/no-dynamic-require, @typescript-eslint/no-require-imports -- Paths are bounded, we just need to decide which package.json file to target -export const ENGINE_VERSION: string = require(requirePath).version; diff --git a/packages/apps/CHANGELOG.md b/packages/apps/CHANGELOG.md index 891ff26383ddc..c6c65b46d68da 100644 --- a/packages/apps/CHANGELOG.md +++ b/packages/apps/CHANGELOG.md @@ -1,5 +1,39 @@ # @rocket.chat/apps +## 0.7.0 + +### Minor Changes + +- ([#40463](https://github.com/RocketChat/Rocket.Chat/pull/40463)) Allows apps with the right permission to read room's ABAC attributes. + +- ([#40343](https://github.com/RocketChat/Rocket.Chat/pull/40343)) Receives the migration of internal files from @rocket.chat/apps-engine + +### Patch Changes + +-
    Updated dependencies [f7d47dd3517ec14ca2ec5c3c95fcdf9e1e2fb8b0, 2a927fa1362c9d4bb04bb8e26f23a6e3753d9cea, b6b04aadfcc8558f888b334e37c46a77e5816237, 4704bf81ca370f120af32185a7c55407a26f8514, f392d5cc8d956c199f557dcd6beb52094232499d, 2198d9ea565b06f92e3dec29891890086f62f9df, 12897e25d0dc25b7373f5264d38f38a5a7444257]: + + - @rocket.chat/model-typings@2.3.0 + - @rocket.chat/apps-engine@1.63.0 + - @rocket.chat/core-typings@8.5.0 +
    + +## 0.7.0-rc.0 + +### Minor Changes + +- ([#40463](https://github.com/RocketChat/Rocket.Chat/pull/40463)) Allows apps with the right permission to read room's ABAC attributes. + +- ([#40343](https://github.com/RocketChat/Rocket.Chat/pull/40343)) Receives the migration of internal files from @rocket.chat/apps-engine + +### Patch Changes + +-
    Updated dependencies [f7d47dd3517ec14ca2ec5c3c95fcdf9e1e2fb8b0, 2a927fa1362c9d4bb04bb8e26f23a6e3753d9cea, ae9f740d6af20557eac61b4af902c868b4132b49, b6b04aadfcc8558f888b334e37c46a77e5816237, 4704bf81ca370f120af32185a7c55407a26f8514, f392d5cc8d956c199f557dcd6beb52094232499d, 2198d9ea565b06f92e3dec29891890086f62f9df, 12897e25d0dc25b7373f5264d38f38a5a7444257]: + + - @rocket.chat/model-typings@2.3.0-rc.0 + - @rocket.chat/apps-engine@1.63.0-rc.0 + - @rocket.chat/core-typings@8.5.0-rc.0 +
    + ## 0.6.9 ### Patch Changes diff --git a/packages/apps/package.json b/packages/apps/package.json index 3b564d197d9f8..6770316b6486b 100644 --- a/packages/apps/package.json +++ b/packages/apps/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/apps", - "version": "0.6.9", + "version": "0.7.0", "private": true, "main": "./dist/index.js", "types": "./dist/index.d.ts", diff --git a/packages/apps/src/server/compiler/AppPackageParser.ts b/packages/apps/src/server/compiler/AppPackageParser.ts index 10990803e1153..c884654efb85d 100644 --- a/packages/apps/src/server/compiler/AppPackageParser.ts +++ b/packages/apps/src/server/compiler/AppPackageParser.ts @@ -2,7 +2,7 @@ import { randomUUID } from 'node:crypto'; import * as path from 'node:path'; import type { IAppInfo } from '@rocket.chat/apps-engine/definition/metadata/IAppInfo'; -import { ENGINE_VERSION } from '@rocket.chat/apps-engine/definition/version'; +import { version } from '@rocket.chat/apps-engine/package.json'; import AdmZip from 'adm-zip'; import * as semver from 'semver'; @@ -15,7 +15,11 @@ export class AppPackageParser { private allowedIconExts: Array = ['.png', '.jpg', '.jpeg', '.gif']; - private appsEngineVersion: string = ENGINE_VERSION; + private readonly appsEngineVersion: string; + + constructor() { + [this.appsEngineVersion] = version.split('-'); // In case there is a suffix like -dev, -rc.0, etc. We just want the version number for semver comparison + } public async unpackageApp(appPackage: Buffer): Promise { const zip = new AdmZip(appPackage); diff --git a/packages/apps/src/server/permissions/AppPermissions.ts b/packages/apps/src/server/permissions/AppPermissions.ts index 9485aff8593d4..821f621dd3281 100644 --- a/packages/apps/src/server/permissions/AppPermissions.ts +++ b/packages/apps/src/server/permissions/AppPermissions.ts @@ -1,171 +1 @@ -import type { - INetworkingPermission, - IPermission, - IReadSettingPermission, - IWorkspaceTokenPermission, -} from '@rocket.chat/apps-engine/definition/permissions/IPermission'; - -/** - * @description - * - * App Permission naming rules: - * - * 'scope-name': { - * 'permission-name': { name: 'scope-name.permission-name' } - * } - * - * You can retrive this permission by using: - * AppPermissions['scope-name']['permission-name'] -> { name: 'scope-name.permission-name' } - * - * @example - * - * AppPermissions.upload.read // { name: 'upload.read', domains: [] } - */ -export const AppPermissions = { - 'user': { - read: { name: 'user.read' }, - write: { name: 'user.write' }, - }, - 'upload': { - read: { name: 'upload.read' }, - write: { name: 'upload.write' }, - }, - 'email': { - send: { name: 'email.send' }, - }, - 'ui': { - interaction: { name: 'ui.interact' }, - registerButtons: { name: 'ui.registerButtons' }, - }, - 'setting': { - read: { name: 'server-setting.read', hiddenSettings: [] } as IReadSettingPermission, - write: { name: 'server-setting.write' }, - }, - 'room': { - 'read': { name: 'room.read' }, - 'write': { name: 'room.write' }, - 'system-view-all': { name: 'room.system.view-all' }, - }, - 'role': { - read: { name: 'role.read' }, - write: { name: 'role.write' }, - }, - 'message': { - read: { name: 'message.read' }, - write: { name: 'message.write' }, - }, - 'moderation': { - read: { name: 'moderation.read' }, - write: { name: 'moderation.write' }, - }, - 'contact': { - read: { name: 'contact.read' }, - write: { name: 'contact.write' }, - }, - 'threads': { - read: { name: 'threads.read' }, - }, - 'livechat-status': { - read: { name: 'livechat-status.read' }, - }, - 'livechat-custom-fields': { - write: { name: 'livechat-custom-fields.write' }, - }, - 'livechat-visitor': { - read: { name: 'livechat-visitor.read' }, - write: { name: 'livechat-visitor.write' }, - }, - 'livechat-message': { - read: { name: 'livechat-message.read' }, - write: { name: 'livechat-message.write' }, - multiple: { name: 'livechat-message.multiple' }, - }, - 'livechat-room': { - read: { name: 'livechat-room.read' }, - write: { name: 'livechat-room.write' }, - }, - 'livechat-department': { - read: { name: 'livechat-department.read' }, - write: { name: 'livechat-department.write' }, - multiple: { name: 'livechat-department.multiple' }, - }, - 'env': { - read: { name: 'env.read' }, - }, - 'cloud': { - 'workspace-token': { name: 'cloud.workspace-token', scopes: [] } as IWorkspaceTokenPermission, - }, - // Internal permissions - 'scheduler': { - default: { name: 'scheduler' }, - }, - 'networking': { - default: { name: 'networking', domains: [] } as INetworkingPermission, - }, - 'persistence': { - default: { name: 'persistence' }, - }, - 'command': { - default: { name: 'slashcommand' }, - }, - 'videoConference': { - read: { name: 'video-conference.read' }, - write: { name: 'video-conference.write' }, - provider: { name: 'video-conference-provider' }, - }, - 'apis': { - default: { name: 'api' }, - }, - 'oauth-app': { - read: { name: 'oauth-app.read' }, - write: { name: 'oauth-app.write' }, - }, - 'outboundComms': { - provide: { name: 'outbound-communication.provide' }, - }, - 'experimental': { - default: { name: 'experimental.default' }, - }, - 'abac': { - read: { name: 'abac.read' }, - }, -}; - -/** - * @description - * Default permissions for apps - * Used to ensure backward compatibility with apps - * that were developed before the permission system was introduced. - */ -export const defaultPermissions: Array = [ - AppPermissions.user.read, - AppPermissions.user.write, - AppPermissions.upload.read, - AppPermissions.upload.write, - AppPermissions.ui.interaction, - AppPermissions.setting.read, - AppPermissions.setting.write, - AppPermissions.room.read, - AppPermissions.room.write, - AppPermissions.message.read, - AppPermissions.message.write, - AppPermissions['livechat-department'].read, - AppPermissions['livechat-department'].write, - AppPermissions['livechat-room'].read, - AppPermissions['livechat-room'].write, - AppPermissions['livechat-message'].read, - AppPermissions['livechat-message'].write, - AppPermissions['livechat-visitor'].read, - AppPermissions['livechat-visitor'].write, - AppPermissions['livechat-status'].read, - AppPermissions['livechat-custom-fields'].write, - AppPermissions.scheduler.default, - AppPermissions.networking.default, - AppPermissions.persistence.default, - AppPermissions.env.read, - AppPermissions.command.default, - AppPermissions.videoConference.provider, - AppPermissions.videoConference.read, - AppPermissions.videoConference.write, - AppPermissions.apis.default, -]; +export { AppPermissions, defaultPermissions } from '@rocket.chat/apps-engine/definition/metadata/AppPermissions'; diff --git a/packages/core-services/CHANGELOG.md b/packages/core-services/CHANGELOG.md index e58ec2460dd3b..e34c2a7fb7118 100644 --- a/packages/core-services/CHANGELOG.md +++ b/packages/core-services/CHANGELOG.md @@ -1,5 +1,29 @@ # @rocket.chat/core-services +## 0.14.1 + +### Patch Changes + +-
    Updated dependencies [90f15e32ae843ed146ccf711ee3201408d1e8731, f7d47dd3517ec14ca2ec5c3c95fcdf9e1e2fb8b0, 4c3984593017d59edd631bf8ae4f35f9d3c3db36, b6b04aadfcc8558f888b334e37c46a77e5816237, 4704bf81ca370f120af32185a7c55407a26f8514, 12897e25d0dc25b7373f5264d38f38a5a7444257, e45585b70a3a7b75434c88e4b2ea9af0a0764a76, b1c2668b74bfb49ebaefe2f581b2f8be5d4d1dd6, 90f15e32ae843ed146ccf711ee3201408d1e8731]: + + - @rocket.chat/ui-kit@1.1.0 + - @rocket.chat/models@2.3.0 + - @rocket.chat/rest-typings@8.5.0 + - @rocket.chat/core-typings@8.5.0 +
    + +## 0.14.1-rc.0 + +### Patch Changes + +-
    Updated dependencies [90f15e32ae843ed146ccf711ee3201408d1e8731, f7d47dd3517ec14ca2ec5c3c95fcdf9e1e2fb8b0, 4c3984593017d59edd631bf8ae4f35f9d3c3db36, ae9f740d6af20557eac61b4af902c868b4132b49, b6b04aadfcc8558f888b334e37c46a77e5816237, 4704bf81ca370f120af32185a7c55407a26f8514, 12897e25d0dc25b7373f5264d38f38a5a7444257, e45585b70a3a7b75434c88e4b2ea9af0a0764a76, b1c2668b74bfb49ebaefe2f581b2f8be5d4d1dd6, 90f15e32ae843ed146ccf711ee3201408d1e8731]: + + - @rocket.chat/ui-kit@1.1.0-rc.0 + - @rocket.chat/models@2.3.0-rc.0 + - @rocket.chat/rest-typings@8.5.0-rc.0 + - @rocket.chat/core-typings@8.5.0-rc.0 +
    + ## 0.14.0 ### Minor Changes diff --git a/packages/core-services/package.json b/packages/core-services/package.json index 30f4f74e1e5a7..ec6e43c19aecb 100644 --- a/packages/core-services/package.json +++ b/packages/core-services/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/core-services", - "version": "0.14.0", + "version": "0.14.1", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/core-typings/CHANGELOG.md b/packages/core-typings/CHANGELOG.md index 98827137dac88..10789fa572617 100644 --- a/packages/core-typings/CHANGELOG.md +++ b/packages/core-typings/CHANGELOG.md @@ -1,5 +1,66 @@ # @rocket.chat/core-typings +## 8.5.0 + +### Patch Changes + +- ([#40405](https://github.com/RocketChat/Rocket.Chat/pull/40405)) Security Hotfix (https://docs.rocket.chat/docs/security-fixes-and-updates) + +-
    Updated dependencies [90f15e32ae843ed146ccf711ee3201408d1e8731, 90f15e32ae843ed146ccf711ee3201408d1e8731]: + + - @rocket.chat/ui-kit@1.1.0 +
    + +## 8.5.0-rc.6 + +## 8.5.0-rc.5 + +## 8.5.0-rc.4 + +## 8.5.0-rc.3 + +## 8.5.0-rc.2 + +## 8.5.0-rc.1 + +## 8.5.0-rc.0 + +### Minor Changes + +- ([#39760](https://github.com/RocketChat/Rocket.Chat/pull/39760)) ## Phishing-Resistant Multi-Factor Authentication + + Introduces a more secure and reliable server-side OAuth authentication flow. + + ### What’s New + + - **Improved OAuth login security** + OAuth authentication now happens fully on the server, reducing the risk of token theft, phishing attacks, and client-side credential interception. + - **Built-in CSRF, state validation, and PKCE protection** + OAuth logins now include stronger protection against CSRF attacks, request tampering, and authorization code interception through secure state validation and PKCE support. + - **Improved two-step verification with OAuth logins** + Users with email or TOTP two-factor authentication enabled will now be asked to complete 2FA even when signing in with providers like Google, GitHub, GitLab, and others. + - **Improved mobile & desktop app login** + Mobile and desktop apps now support a smoother and more secure deep-link OAuth login flow. + +### Patch Changes + +- ([#40405](https://github.com/RocketChat/Rocket.Chat/pull/40405)) Security Hotfix (https://docs.rocket.chat/docs/security-fixes-and-updates) + +-
    Updated dependencies [90f15e32ae843ed146ccf711ee3201408d1e8731, 90f15e32ae843ed146ccf711ee3201408d1e8731]: + + - @rocket.chat/ui-kit@1.1.0-rc.0 +
    + +## 8.4.3 + +## 8.4.2 + +## 8.4.1 + +### Patch Changes + +- ([#40410](https://github.com/RocketChat/Rocket.Chat/pull/40410) by [@dionisio-bot](https://github.com/dionisio-bot)) Security Hotfix (https://docs.rocket.chat/docs/security-fixes-and-updates) + ## 8.4.0 ### Minor Changes diff --git a/packages/core-typings/src/cloud/Announcement.ts b/packages/core-typings/src/cloud/Announcement.ts index 8f07ef22f7a2b..b169b678f7798 100644 --- a/packages/core-typings/src/cloud/Announcement.ts +++ b/packages/core-typings/src/cloud/Announcement.ts @@ -1,9 +1,11 @@ import * as z from 'zod'; import { IBannerSchema } from '../IBanner'; +import { TimestampSchema } from '../utils'; export const AnnouncementSchema = IBannerSchema.extend({ createdBy: z.enum(['cloud', 'system']), + _updatedAt: TimestampSchema.optional(), selector: z.object({ roles: z.array(z.string()) }).optional(), }); diff --git a/packages/core-typings/src/cloud/WorkspaceSyncPayload.ts b/packages/core-typings/src/cloud/WorkspaceSyncPayload.ts index 64e304c685e79..3fcd6301bd9b7 100644 --- a/packages/core-typings/src/cloud/WorkspaceSyncPayload.ts +++ b/packages/core-typings/src/cloud/WorkspaceSyncPayload.ts @@ -29,7 +29,10 @@ export const WorkspaceSyncPayloadSchema = z.object({ /** @deprecated */ nps: NpsSurveyAnnouncementSchema.optional().meta({ deprecated: true }), /** @deprecated */ - banners: z.array(IBannerSchema).optional().meta({ deprecated: true }), + banners: z + .array(IBannerSchema.extend({ _updatedAt: TimestampSchema.optional() })) + .optional() + .meta({ deprecated: true }), }); export type WorkspaceSyncPayload = z.infer; diff --git a/packages/cron/CHANGELOG.md b/packages/cron/CHANGELOG.md index 78e2f6fec3e88..8bf02805c2922 100644 --- a/packages/cron/CHANGELOG.md +++ b/packages/cron/CHANGELOG.md @@ -1,5 +1,25 @@ # @rocket.chat/cron +## 0.1.57 + +### Patch Changes + +-
    Updated dependencies [f7d47dd3517ec14ca2ec5c3c95fcdf9e1e2fb8b0, b6b04aadfcc8558f888b334e37c46a77e5816237, 4704bf81ca370f120af32185a7c55407a26f8514, 12897e25d0dc25b7373f5264d38f38a5a7444257, e45585b70a3a7b75434c88e4b2ea9af0a0764a76]: + + - @rocket.chat/models@2.3.0 + - @rocket.chat/core-typings@8.5.0 +
    + +## 0.1.57-rc.0 + +### Patch Changes + +-
    Updated dependencies [f7d47dd3517ec14ca2ec5c3c95fcdf9e1e2fb8b0, ae9f740d6af20557eac61b4af902c868b4132b49, b6b04aadfcc8558f888b334e37c46a77e5816237, 4704bf81ca370f120af32185a7c55407a26f8514, 12897e25d0dc25b7373f5264d38f38a5a7444257, e45585b70a3a7b75434c88e4b2ea9af0a0764a76]: + + - @rocket.chat/models@2.3.0-rc.0 + - @rocket.chat/core-typings@8.5.0-rc.0 +
    + ## 0.1.56 ### Patch Changes diff --git a/packages/cron/package.json b/packages/cron/package.json index 8e5d95f4d5042..0388d0e6bb703 100644 --- a/packages/cron/package.json +++ b/packages/cron/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/cron", - "version": "0.1.56", + "version": "0.1.57", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/ddp-client/CHANGELOG.md b/packages/ddp-client/CHANGELOG.md index 4e8e6d40f9265..e329ecdc57de6 100644 --- a/packages/ddp-client/CHANGELOG.md +++ b/packages/ddp-client/CHANGELOG.md @@ -1,5 +1,45 @@ # @rocket.chat/ddp-client +## 1.1.0 + +### Minor Changes + +- ([#40442](https://github.com/RocketChat/Rocket.Chat/pull/40442)) Add lifecycle event handlers to `Account`: `onLogin`, `onLogout`, `onEmailVerificationLink`, and `onPageLoadLogin`. `onLogin` / `onLogout` fire on `uid` transitions (the setter now emits only when the value changes, so a single login or logout produces exactly one callback). `onEmailVerificationLink` and `onPageLoadLogin` are convenience wrappers around new `Emitter` events of the same names — fire them externally with `account.emit('emailVerificationLink', token)` / `account.emit('pageLoadLogin', loginAttempt)`. The bridge from Meteor's accounts-base lives in the consumer (`apps/meteor/client`) so the package stays Meteor-independent. All four handlers return an unsubscribe function. + +### Patch Changes + +- ([#40307](https://github.com/RocketChat/Rocket.Chat/pull/40307)) Make `Connection.connect()` and `Connection.reconnect()` idempotent. Previously they rejected with `Error('Connection in progress')` when called while a connection was already in flight or established. Because the internal retry timer (`ws.onclose` → `setTimeout(() => void this.reconnect(), …)`) fires with no `.catch`, that rejection surfaced as an unhandled rejection at the page level whenever an external caller (e.g. an SDK consumer's bootstrap path) won the race against the timer. While `status === 'connecting'`, both methods now return the in-flight handshake promise so a later `failed` payload still propagates to every caller instead of being masked by a synthesized success; while `status === 'connected'` they resolve with `true`. The timer also no-ops when the connection has already been re-established, and a stale `ws.onclose` from a replaced socket no longer clobbers the new socket's status or schedules a redundant retry. + +- ([#40307](https://github.com/RocketChat/Rocket.Chat/pull/40307)) Reset `Connection.retryCount` to zero on a successful (re)connection. The counter was only ever incremented (in `ws.onclose`), never zeroed, so the retry budget was monotonically consumed across the connection's lifetime. With the default budget of `1`, any chain of two close events — for example the SDK reconnecting after a server force-logout, then the client running a follow-up `Meteor.logout()` whose server handler closes the WS again — drained the budget; the second close handler bailed at `retryCount >= retryOptions.retryCount` and the SDK stayed permanently disconnected. Method frames already in the dispatcher queue (e.g. a fresh `login` retry from the consumer) stayed queued forever. + +- ([#40307](https://github.com/RocketChat/Rocket.Chat/pull/40307)) Fix `DDPDispatcher` dropping non-method frames (connect, sub, unsub, ping, pong) when a `wait` block is at the head of the queue. Previously every payload flowed through the same wait-serialization path: a `connect` frame dispatched after a `wait: true` method (e.g. `login`) would be queued in a new non-wait block but never actually sent, wedging the DDP handshake — the socket stayed open, the server never replied `connected`, and any caller awaiting the connection hung. Non-method payloads now bypass the queue and emit immediately; wait-method serialization between methods is unchanged. + +-
    Updated dependencies [4c3984593017d59edd631bf8ae4f35f9d3c3db36, 4704bf81ca370f120af32185a7c55407a26f8514, 12897e25d0dc25b7373f5264d38f38a5a7444257, b1c2668b74bfb49ebaefe2f581b2f8be5d4d1dd6]: + + - @rocket.chat/rest-typings@8.5.0 + - @rocket.chat/core-typings@8.5.0 +
    + +## 1.1.0-rc.0 + +### Minor Changes + +- ([#40442](https://github.com/RocketChat/Rocket.Chat/pull/40442)) Add lifecycle event handlers to `Account`: `onLogin`, `onLogout`, `onEmailVerificationLink`, and `onPageLoadLogin`. `onLogin` / `onLogout` fire on `uid` transitions (the setter now emits only when the value changes, so a single login or logout produces exactly one callback). `onEmailVerificationLink` and `onPageLoadLogin` are convenience wrappers around new `Emitter` events of the same names — fire them externally with `account.emit('emailVerificationLink', token)` / `account.emit('pageLoadLogin', loginAttempt)`. The bridge from Meteor's accounts-base lives in the consumer (`apps/meteor/client`) so the package stays Meteor-independent. All four handlers return an unsubscribe function. + +### Patch Changes + +- ([#40307](https://github.com/RocketChat/Rocket.Chat/pull/40307)) Make `Connection.connect()` and `Connection.reconnect()` idempotent. Previously they rejected with `Error('Connection in progress')` when called while a connection was already in flight or established. Because the internal retry timer (`ws.onclose` → `setTimeout(() => void this.reconnect(), …)`) fires with no `.catch`, that rejection surfaced as an unhandled rejection at the page level whenever an external caller (e.g. an SDK consumer's bootstrap path) won the race against the timer. While `status === 'connecting'`, both methods now return the in-flight handshake promise so a later `failed` payload still propagates to every caller instead of being masked by a synthesized success; while `status === 'connected'` they resolve with `true`. The timer also no-ops when the connection has already been re-established, and a stale `ws.onclose` from a replaced socket no longer clobbers the new socket's status or schedules a redundant retry. + +- ([#40307](https://github.com/RocketChat/Rocket.Chat/pull/40307)) Reset `Connection.retryCount` to zero on a successful (re)connection. The counter was only ever incremented (in `ws.onclose`), never zeroed, so the retry budget was monotonically consumed across the connection's lifetime. With the default budget of `1`, any chain of two close events — for example the SDK reconnecting after a server force-logout, then the client running a follow-up `Meteor.logout()` whose server handler closes the WS again — drained the budget; the second close handler bailed at `retryCount >= retryOptions.retryCount` and the SDK stayed permanently disconnected. Method frames already in the dispatcher queue (e.g. a fresh `login` retry from the consumer) stayed queued forever. + +- ([#40307](https://github.com/RocketChat/Rocket.Chat/pull/40307)) Fix `DDPDispatcher` dropping non-method frames (connect, sub, unsub, ping, pong) when a `wait` block is at the head of the queue. Previously every payload flowed through the same wait-serialization path: a `connect` frame dispatched after a `wait: true` method (e.g. `login`) would be queued in a new non-wait block but never actually sent, wedging the DDP handshake — the socket stayed open, the server never replied `connected`, and any caller awaiting the connection hung. Non-method payloads now bypass the queue and emit immediately; wait-method serialization between methods is unchanged. + +-
    Updated dependencies [4c3984593017d59edd631bf8ae4f35f9d3c3db36, ae9f740d6af20557eac61b4af902c868b4132b49, 4704bf81ca370f120af32185a7c55407a26f8514, 12897e25d0dc25b7373f5264d38f38a5a7444257, b1c2668b74bfb49ebaefe2f581b2f8be5d4d1dd6]: + + - @rocket.chat/rest-typings@8.5.0-rc.0 + - @rocket.chat/core-typings@8.5.0-rc.0 +
    + ## 1.0.9 ### Patch Changes diff --git a/packages/ddp-client/package.json b/packages/ddp-client/package.json index f8588c1547d7e..9562bd849050b 100644 --- a/packages/ddp-client/package.json +++ b/packages/ddp-client/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/ddp-client", - "version": "1.0.9", + "version": "1.1.0", "main": "./dist/index.js", "typings": "./dist/index.d.ts", "files": [ diff --git a/packages/desktop-api/CHANGELOG.md b/packages/desktop-api/CHANGELOG.md index afb32ffd788fd..062fa08e347dc 100644 --- a/packages/desktop-api/CHANGELOG.md +++ b/packages/desktop-api/CHANGELOG.md @@ -1,5 +1,26 @@ # @rocket.chat/desktop-api +## 1.2.0 + +## 1.2.0-rc.0 + +### Minor Changes + +- ([#39760](https://github.com/RocketChat/Rocket.Chat/pull/39760)) ## Phishing-Resistant Multi-Factor Authentication + + Introduces a more secure and reliable server-side OAuth authentication flow. + + ### What’s New + + - **Improved OAuth login security** + OAuth authentication now happens fully on the server, reducing the risk of token theft, phishing attacks, and client-side credential interception. + - **Built-in CSRF, state validation, and PKCE protection** + OAuth logins now include stronger protection against CSRF attacks, request tampering, and authorization code interception through secure state validation and PKCE support. + - **Improved two-step verification with OAuth logins** + Users with email or TOTP two-factor authentication enabled will now be asked to complete 2FA even when signing in with providers like Google, GitHub, GitLab, and others. + - **Improved mobile & desktop app login** + Mobile and desktop apps now support a smoother and more secure deep-link OAuth login flow. + ## 1.1.1 ### Patch Changes diff --git a/packages/desktop-api/package.json b/packages/desktop-api/package.json index 63515e73dd0dc..4e459b19f92ee 100644 --- a/packages/desktop-api/package.json +++ b/packages/desktop-api/package.json @@ -1,7 +1,7 @@ { "$schema": "https://www.schemastore.org/package", "name": "@rocket.chat/desktop-api", - "version": "1.1.1", + "version": "1.2.0", "type": "module", "exports": { ".": { diff --git a/packages/fuselage-ui-kit/CHANGELOG.md b/packages/fuselage-ui-kit/CHANGELOG.md index 525894e528588..60932dae63344 100644 --- a/packages/fuselage-ui-kit/CHANGELOG.md +++ b/packages/fuselage-ui-kit/CHANGELOG.md @@ -1,5 +1,35 @@ # Change Log +## 31.0.0 + +### Patch Changes + +-
    Updated dependencies [90f15e32ae843ed146ccf711ee3201408d1e8731, 2a927fa1362c9d4bb04bb8e26f23a6e3753d9cea, d427b808c1f79d9d1baa05bb5b5ef805b6ef5f6d, f392d5cc8d956c199f557dcd6beb52094232499d, 2198d9ea565b06f92e3dec29891890086f62f9df, 12897e25d0dc25b7373f5264d38f38a5a7444257, 0b7a76367d650793c271160e01798ebbb5fe0d26, 90f15e32ae843ed146ccf711ee3201408d1e8731]: + + - @rocket.chat/ui-kit@1.1.0 + - @rocket.chat/apps-engine@1.63.0 + - @rocket.chat/gazzodown@31.0.0 + - @rocket.chat/core-typings@8.5.0 + - @rocket.chat/ui-avatar@27.0.0 + - @rocket.chat/ui-contexts@31.0.0 + - @rocket.chat/ui-video-conf@31.0.0 +
    + +## 31.0.0-rc.0 + +### Patch Changes + +-
    Updated dependencies [90f15e32ae843ed146ccf711ee3201408d1e8731, 2a927fa1362c9d4bb04bb8e26f23a6e3753d9cea, ae9f740d6af20557eac61b4af902c868b4132b49, d427b808c1f79d9d1baa05bb5b5ef805b6ef5f6d, f392d5cc8d956c199f557dcd6beb52094232499d, 2198d9ea565b06f92e3dec29891890086f62f9df, 12897e25d0dc25b7373f5264d38f38a5a7444257, 0b7a76367d650793c271160e01798ebbb5fe0d26, 90f15e32ae843ed146ccf711ee3201408d1e8731]: + + - @rocket.chat/ui-kit@1.1.0-rc.0 + - @rocket.chat/apps-engine@1.63.0-rc.0 + - @rocket.chat/core-typings@8.5.0-rc.0 + - @rocket.chat/gazzodown@31.0.0-rc.0 + - @rocket.chat/ui-contexts@31.0.0-rc.0 + - @rocket.chat/ui-avatar@27.0.0-rc.0 + - @rocket.chat/ui-video-conf@31.0.0-rc.0 +
    + ## 30.0.0 ### Patch Changes diff --git a/packages/fuselage-ui-kit/package.json b/packages/fuselage-ui-kit/package.json index e188f1323d041..f8888607ade29 100644 --- a/packages/fuselage-ui-kit/package.json +++ b/packages/fuselage-ui-kit/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/fuselage-ui-kit", - "version": "30.0.0", + "version": "31.0.0", "private": true, "description": "UiKit elements for Rocket.Chat Apps built under Fuselage design system", "homepage": "https://rocketchat.github.io/Rocket.Chat.Fuselage/", diff --git a/packages/gazzodown/CHANGELOG.md b/packages/gazzodown/CHANGELOG.md index 47c0e98a5319e..54554afceaa65 100644 --- a/packages/gazzodown/CHANGELOG.md +++ b/packages/gazzodown/CHANGELOG.md @@ -1,5 +1,35 @@ # @rocket.chat/gazzodown +## 31.0.0 + +### Patch Changes + +- ([#40420](https://github.com/RocketChat/Rocket.Chat/pull/40420)) Fixes Insert Timestamp relative time preview not updating on input changes and losing the user's locale after the first refresh tick. + +- ([#40613](https://github.com/RocketChat/Rocket.Chat/pull/40613)) Sanitizes image URLs in rendered messages to block `javascript:`, `data:`, and `vbscript:` schemes — matching the protection already applied to markdown links. Defense-in-depth against XSS via crafted markdown like `![label](javascript:...)`. + +-
    Updated dependencies [fac64728505b312d5da786e92d3134450ce4a7c1, 12897e25d0dc25b7373f5264d38f38a5a7444257]: + + - @rocket.chat/ui-client@31.0.0 + - @rocket.chat/core-typings@8.5.0 + - @rocket.chat/ui-contexts@31.0.0 +
    + +## 31.0.0-rc.0 + +### Patch Changes + +- ([#40420](https://github.com/RocketChat/Rocket.Chat/pull/40420)) Fixes Insert Timestamp relative time preview not updating on input changes and losing the user's locale after the first refresh tick. + +- ([#40613](https://github.com/RocketChat/Rocket.Chat/pull/40613)) Sanitizes image URLs in rendered messages to block `javascript:`, `data:`, and `vbscript:` schemes — matching the protection already applied to markdown links. Defense-in-depth against XSS via crafted markdown like `![label](javascript:...)`. + +-
    Updated dependencies [ae9f740d6af20557eac61b4af902c868b4132b49, fac64728505b312d5da786e92d3134450ce4a7c1, 12897e25d0dc25b7373f5264d38f38a5a7444257]: + + - @rocket.chat/core-typings@8.5.0-rc.0 + - @rocket.chat/ui-client@31.0.0-rc.0 + - @rocket.chat/ui-contexts@31.0.0-rc.0 +
    + ## 30.0.0 ### Patch Changes diff --git a/packages/gazzodown/package.json b/packages/gazzodown/package.json index a481b8f6cc6ff..a850c4993ef11 100644 --- a/packages/gazzodown/package.json +++ b/packages/gazzodown/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/gazzodown", - "version": "30.0.0", + "version": "31.0.0", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/i18n/CHANGELOG.md b/packages/i18n/CHANGELOG.md index cebc35828abb8..02e3569a893e3 100644 --- a/packages/i18n/CHANGELOG.md +++ b/packages/i18n/CHANGELOG.md @@ -1,5 +1,68 @@ # @rocket.chat/i18n +## 3.1.0 + +### Minor Changes + +- ([#40408](https://github.com/RocketChat/Rocket.Chat/pull/40408)) Adds 4 new permissions (assigned to admins by default) to control the visibility of each tab inside the ABAC Administration panel + +- ([#40331](https://github.com/RocketChat/Rocket.Chat/pull/40331)) Adds "Open in room" button to shared screen card on voice call widget + +- ([#39617](https://github.com/RocketChat/Rocket.Chat/pull/39617)) Adds new API endpoints `custom-sounds.create` and `custom-sounds.update` to manage custom sounds with strict file validation for size and specific MIME types to ensure system compatibility. + +- ([#38225](https://github.com/RocketChat/Rocket.Chat/pull/38225)) Adds a new "Drafts" group to the sidebar, providing quick access to all rooms with unfinished messages. + > This feature is available under the `Drafts in sidebar` feature preview and needs to be enabled in settings to be tested. + +### Patch Changes + +- ([#40420](https://github.com/RocketChat/Rocket.Chat/pull/40420)) Fixes Insert Timestamp relative time preview not updating on input changes and losing the user's locale after the first refresh tick. + +- ([#40456](https://github.com/RocketChat/Rocket.Chat/pull/40456)) Fixes signed URL generation for S3 and Google Cloud Storage when the expiry setting is below 5 seconds, which previously caused expired or invalid preview URLs. Adds a dedicated URL expiry setting for Google Cloud Storage since it was incorrectly reusing the AWS S3 setting. + +- ([#40405](https://github.com/RocketChat/Rocket.Chat/pull/40405)) Security Hotfix (https://docs.rocket.chat/docs/security-fixes-and-updates) + +## 3.1.0-rc.0 + +### Minor Changes + +- ([#40408](https://github.com/RocketChat/Rocket.Chat/pull/40408)) Adds 4 new permissions (assigned to admins by default) to control the visibility of each tab inside the ABAC Administration panel + +- ([#39760](https://github.com/RocketChat/Rocket.Chat/pull/39760)) ## Phishing-Resistant Multi-Factor Authentication + + Introduces a more secure and reliable server-side OAuth authentication flow. + + ### What’s New + + - **Improved OAuth login security** + OAuth authentication now happens fully on the server, reducing the risk of token theft, phishing attacks, and client-side credential interception. + - **Built-in CSRF, state validation, and PKCE protection** + OAuth logins now include stronger protection against CSRF attacks, request tampering, and authorization code interception through secure state validation and PKCE support. + - **Improved two-step verification with OAuth logins** + Users with email or TOTP two-factor authentication enabled will now be asked to complete 2FA even when signing in with providers like Google, GitHub, GitLab, and others. + - **Improved mobile & desktop app login** + Mobile and desktop apps now support a smoother and more secure deep-link OAuth login flow. + +- ([#40331](https://github.com/RocketChat/Rocket.Chat/pull/40331)) Adds "Open in room" button to shared screen card on voice call widget + +- ([#39617](https://github.com/RocketChat/Rocket.Chat/pull/39617)) Adds new API endpoints `custom-sounds.create` and `custom-sounds.update` to manage custom sounds with strict file validation for size and specific MIME types to ensure system compatibility. + +- ([#38225](https://github.com/RocketChat/Rocket.Chat/pull/38225)) Adds a new "Drafts" group to the sidebar, providing quick access to all rooms with unfinished messages. + > This feature is available under the `Drafts in sidebar` feature preview and needs to be enabled in settings to be tested. + +### Patch Changes + +- ([#40420](https://github.com/RocketChat/Rocket.Chat/pull/40420)) Fixes Insert Timestamp relative time preview not updating on input changes and losing the user's locale after the first refresh tick. + +- ([#40456](https://github.com/RocketChat/Rocket.Chat/pull/40456)) Fixes signed URL generation for S3 and Google Cloud Storage when the expiry setting is below 5 seconds, which previously caused expired or invalid preview URLs. Adds a dedicated URL expiry setting for Google Cloud Storage since it was incorrectly reusing the AWS S3 setting. + +- ([#40405](https://github.com/RocketChat/Rocket.Chat/pull/40405)) Security Hotfix (https://docs.rocket.chat/docs/security-fixes-and-updates) + +## 3.0.1 + +### Patch Changes + +- ([#40410](https://github.com/RocketChat/Rocket.Chat/pull/40410) by [@dionisio-bot](https://github.com/dionisio-bot)) Security Hotfix (https://docs.rocket.chat/docs/security-fixes-and-updates) + ## 3.0.0 ### Minor Changes diff --git a/packages/i18n/package.json b/packages/i18n/package.json index 05df78881856e..8e132f4e7b9d2 100644 --- a/packages/i18n/package.json +++ b/packages/i18n/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/i18n", - "version": "3.0.0", + "version": "3.1.0", "private": true, "type": "module", "exports": { diff --git a/packages/i18n/src/locales/sv.i18n.json b/packages/i18n/src/locales/sv.i18n.json index 0e32b3b1d7a4d..b8b89a51855f0 100644 --- a/packages/i18n/src/locales/sv.i18n.json +++ b/packages/i18n/src/locales/sv.i18n.json @@ -11,6 +11,132 @@ "2_Erros_Information_and_Debug": "2 - Fel, information och felsökning", "@username": "@användarnamn", "@username_message": "@användarnamn ", + "ABAC": "Attributbaserad åtkomstkontroll", + "ABAC_PDP_Health_OK": "Alla system är operativa", + "ABAC_PDP_Health_No_PDP": "Ingen PDP konfigurerad", + "ABAC_PDP_Health_IdP_Failed": "Kunde inte ansluta till identitetsleverantören (IdP) eller generera en token", + "ABAC_PDP_Health_Platform_Failed": "Kunde inte nå Virtru-plattformens hälsoendpunkt", + "ABAC_PDP_Health_Authorization_Failed": "Kunde inte utföra en autentiserad begäran till Virtru-plattformen. OIDC-klienten kanske inte har administratörsrättigheter.", + "ABAC_PDP_Health_Not_OK": "PDP-hälsokontroll misslyckades på grund av ett oväntat fel", + "ABAC_Virtru_Test_Connection": "Testanslutning", + "ABAC_Virtru_Test_Connection_Action": "Testanslutning", + "ABAC_Enabled": "Aktivera attributbaserad åtkomstkontroll (ABAC)", + "ABAC_Enabled_Description": "Kontrollerar åtkomsten till rum baserat på användar- och rumattribut.", + "ABAC_PDP_Type": "Policy Decision Point (PDP)", + "ABAC_PDP_Type_Description": "Välj vilken Policy Decision Point-motor som ska användas för åtkomstkontrollbeslut.", + "ABAC_PDP_Type_Local": "Lokalt", + "ABAC_PDP_Type_Virtru": "Virtru", + "ABAC_Attribute_Store": "Attributlager", + "ABAC_Attribute_Store_Description": "Var tilldelningsbara rumattribut kommer från. Med Virtru hanteras attribut externt och är begränsade till de som administratören innehar; fliken Rumattribut är dold.", + "ABAC_Attribute_Store_Local": "Lokalt", + "ABAC_Attribute_Store_Virtru": "Virtru", + "ABAC_Attribute_Store_Switch_Alert": "Byte av attributlager rensar permanent alla befintliga tilldelningar av rumattribut. Detta kan inte ångras. Inga användare tas bort från något rum, och rum förblir privata.", + "ABAC_Attribute_Store_Switched": "Attributlager utbytt", + "ABAC_Rooms_Affected": { + "one": "{{count}} rum påverkat", + "other": "{{count}} rum påverkade" + }, + "Abac_Cache_Decision_Time_Seconds": "ABAC-cachningsbeslutid (sekunder)", + "Abac_Cache_Decision_Time_Seconds_Description": "Tid i sekunder för att cachelagra åtkomstkontrollbeslut. Om du ställer in detta värde på 0 inaktiveras cachelagringen.", + "ABAC_Virtru_PDP_Configuration": "Virtru PDP-konfiguration", + "ABAC_Virtru_Base_URL": "Bas-URL", + "ABAC_Virtru_Client_ID": "Klient-ID", + "ABAC_Virtru_Client_Secret": "Klienthemlighet", + "ABAC_Virtru_OIDC_Endpoint": "OIDC-slutpunkt", + "ABAC_Virtru_OIDC_Endpoint_Description": "Bas-URL för OIDC-realm som används för autentisering av klientuppgifter (t.ex. https://keycloak.example.com/auth/realms/opentdf).", + "ABAC_Virtru_Default_Entity_Key": "Standardentitetsnyckel", + "ABAC_Virtru_Default_Entity_Key_Description": "Identifikationen för \"entity\" som kommer att skickas till ERS.", + "ABAC_Virtru_Entity_Key_Email": "E-postadress", + "ABAC_Virtru_Entity_Key_OIDC": "OIDC-identifierare", + "ABAC_Virtru_Attribute_Namespace": "Attributnamnsrymd", + "ABAC_Virtru_Attribute_Namespace_Description": "Namnrymden som används för att bygga attribut-FQN:er (t.ex. opentdf.io producerar https://opentdf.io/attr/{key}/value/{value}).", + "ABAC_Virtru_Sync_Interval": "Synkroniseringsintervall för medlemskap", + "ABAC_Virtru_Sync_Interval_Description": "Cron-uttryck för hur ofta du vill omvärdera allt ABAC-rumsmedlemskap mot Virtru PDP och avlägsna icke-kompatibla användare (t.ex. */5 * * * * för var 5:e minut).", + "ABAC_Enabled_callout": "Användarattribut synkroniseras via LDAP. <1>Läs mer", + "ABAC_Learn_More": "Läs mer om ABAC", + "ABAC_automatically_disabled_callout": "ABAC automatiskt inaktiverat", + "ABAC_automatically_disabled_callout_description": "Förnya din licens för att fortsätta använda alla <1>ABAC-funktioner utan begränsning.", + "ABAC_Warning_Modal_Title": "Inaktivera ABAC", + "ABAC_Warning_Modal_Confirm_Text": "Inaktivera ABAC", + "ABAC_Warning_Modal_Content": "Du kan inte automatiskt eller manuellt hantera användare i befintliga ABAC-hanterade rum. För att återställa ett rums standardåtkomstkontroll måste det tas bort från ABAC-hantering i <1>ABAC > Rum.", + "ABAC_ShowAttributesInRooms": "Visa ABAC-attribut i rum", + "ABAC_ShowAttributesInRooms_Description": "Visa ABAC-attributen tilldelade till rummet i det sammanhangsberoende fältet", + "ABAC_Room": "Rum", + "ABAC_Room_Attribute": "Rumattribut", + "ABAC_Element": "ABAC-element", + "ABAC_Element_Name": "Elementnamn", + "ABAC_Cannot_delete_attribute": "Kan inte ta bort attribut tilldelat rum", + "ABAC_Cannot_delete_attribute_content": "Ta bort tilldelningen av {{attributeName}} från alla rum innan du försöker ta bort det.", + "ABAC_Cannot_delete_attribute_value_in_use": "Kan inte ta bort attributvärde tilldelat rum. <1>Visa rum", + "ABAC_Delete_room_attribute": "Ta bort attribut", + "ABAC_Delete_room_attribute_content": "Är du säker på att du vill ta bort {{attributeName}}?
    Befintliga rum påverkas inte eftersom det för närvarande inte är tilldelat något.", + "ABAC_Attribute_created": "{{attributeName}} attribut skapat", + "ABAC_Attribute_updated": "{{attributeName}} attribut uppdaterat", + "ABAC_Attribute_deleted": "{{attributeName}} attribut borttaget", + "ABAC_New_attribute": "Nytt attribut", + "ABAC_Edit_attribute": "Redigera attribut", + "ABAC_Edit_attribute_description": "Attributvärden kan inte redigeras, men kan läggas till eller tas bort.", + "ABAC_New_attribute_description": "Skapa ett attribut som senare kan tilldelas rum.", + "ABAC_No_logs": "Inga loggar", + "ABAC_No_logs_description": "ABAC-hanteringsrelaterad aktivitet visas här.", + "ABAC_Search_attributes": "Sök attribut", + "ABAC_Remove_attribute": "Ta bort attributvärde", + "ABAC_Delete_room": "Ta bort rum från ABAC-hantering", + "ABAC_Delete_room_annotation": "Fortsätt med försiktighet", + "ABAC_Delete_room_content": "Om du tar bort {{roomName}} från ABAC-hantering kan det resultera i att oönskade användare får åtkomst.", + "ABAC_Room_removed": "Rum {{roomName}} borttaget från ABAC-hantering", + "ABAC_Add_Attribute": "Lägg till attribut", + "ABAC_Attribute_Values": "Attributvärden", + "ABAC_Edit_Room": "Redigera rum", + "ABAC_Add_room": "Lägg till rum", + "ABAC_No_repeated_attributes": "Attribut redan tillagt", + "ABAC_No_repeated_values": "Värde redan tillagt", + "ABAC_Room_created": "Åtkomsten till {{roomName}} är nu begränsad till attributkompatibla användare", + "ABAC_Room_to_be_managed": "Rum som ska hanteras av ABAC", + "ABAC_Room_updated": "{{roomName}} ABAC-rum uppdaterat", + "ABAC_Search_Attribute": "Sökattribut", + "ABAC_Search_rooms": "Sök rum, attribut eller attributvärden", + "ABAC_Select_Attribute_Values": "Välj attributvärden", + "ABAC_Update_room_confirmation_modal_annotation": "Fortsätt med försiktighet", + "ABAC_Update_room_confirmation_modal_title": "Uppdatera ABAC-rum", + "ABAC_Update_room_content": "{{roomName}} hanteras för närvarande av ABAC. Ändringar kan påverka vem som kan komma åt detta rum.", + "abac-management": "Hantera ABAC-konfiguration", + "manage-abac-admin-settings": "Hantera ABAC-inställningar", + "manage-abac-admin-settings_description": "Behörighet att visa och ändra ABAC-inställningar", + "manage-abac-admin-room-attributes": "Hantera ABAC-rumattribut", + "manage-abac-admin-room-attributes_description": "Behörighet att visa, skapa, redigera och ta bort ABAC-attributdefinitioner", + "manage-abac-admin-rooms": "Hantera ABAC-rum", + "manage-abac-admin-rooms_description": "Behörighet att visa rum och tilldela eller ta bort ABAC-attribut på dem", + "view-abac-admin-audit": "Visa ABAC-granskningslogg", + "view-abac-admin-audit_description": "Behörighet att visa ABAC-granskningsloggen", + "bypass-abac-store-validation": "Hoppa över ABAC-butiksvalidering", + "bypass-abac-store-validation_description": "Behörighet att spara eller redigera ABAC-attribut utan att validera dem mot attributlagret", + "abac_removed_user_from_the_room": "togs bort av ABAC", + "ABAC_No_attributes": "Inga attribut", + "ABAC_No_attributes_description": "Skapa anpassade egenskaper för att bestämma vem som kan komma åt ett rum.", + "ABAC_No_rooms": "Inga rum", + "ABAC_No_rooms_description": "ABAC-hanterade rum visas här.", + "ABAC_All_Attributes_deleted": "Alla attribut borttagna", + "ABAC_Key_removed": "Nyckel borttagen", + "ABAC_Key_renamed": "Nyckel döpt om", + "ABAC_Value_removed": "Värde borttaget", + "ABAC_Key_added": "Nyckel tillagd", + "ABAC_Key_updated": "Nyckel uppdaterad", + "ABAC_Revoked_Object_Access": "Automatisk borttagning", + "ABAC_Granted_Object_Access": "Manuell tilläggsgodkänd", + "ABAC_room_membership": "Rumsmedlemskap", + "ABAC_Managed": "ABAC-hanterad", + "ABAC_Managed_description": "Endast kompatibla användare har åtkomst till attributbaserad åtkomstkontrollerade rum. Attribut bestämmer rumåtkomst.", + "ABAC_Room_Attributes": "Rumattribut", + "ABAC_Logs": "Loggar", + "ABAC_Invalid_attribute": "Ogiltiga tecken i attributnamn eller värden", + "ABAC_Attributes_Redacted": "Rumattribut dolda", + "ABAC_Attributes_Redacted_Description": "Du har inte de nödvändiga attributen.", + "ABAC_Redacted_Placeholder": "", + "ABAC_Picker_External_Store_Helper": "Tillgängliga attribut är begränsade till de du innehar.", + "Alternative_text": "Alternativ text", + "Alt_text_description": "Beskriv bilden för att ge sammanhang, inklusive för blinda och personer med nedsatt syn och när den inte kan laddas.", + "Enable_ABAC_and_LDAP_to_sync": "Aktivera ABAC och LDAP för att kunna synkronisera", "AI_Actions": "AI-åtgärder", "API": "API", "API_Add_Personal_Access_Token": "Lägg till ny personlig åtkomsttoken", @@ -34,6 +160,7 @@ "API_EmbedSafePorts_Description": "Kommaseparerad lista över tillåtna portar för förhandsgranskning.", "API_Embed_Description": "Huruvida förhandsvisning av inbäddade länkar är aktiverat eller inte när en användare lägger in en länk till en webbplats.", "API_Embed_UserAgent": "Användaragent för inbäddningsförfrågan", + "API_EmbedTimeout": "Bädda in standardtimeout för begäran (i sekunder)", "API_Enable_CORS": "Aktivera CORS", "API_Enable_Direct_Message_History_EndPoint": "Aktivera ändpunkt för direktmeddelandens historik", "API_Enable_Direct_Message_History_EndPoint_Description": "Detta möjliggör `/api/v1/im.messages.others` som tillåter visning av direktmeddelanden som skickats av andra användare som den som ringer inte är en del av.", @@ -98,6 +225,7 @@ "Accounts_Admin_Email_Approval_Needed_With_Reason_Default": "

    Användaren [name] ([email]) har registrerats.

    Orsak: [reason]

    Kontrollera \"Administration -> Användare\" för att aktivera eller radera.

    ", "Accounts_AllowAnonymousRead": "Tillåt anonym läsning", "Accounts_AllowAnonymousWrite": "Tillåt anonym skrivning", + "Accounts_AllowAnonymousWrite_Deprecation_Alert": "Den här funktionen är föråldrad och kommer att tas bort i version 9.0.0.", "Accounts_AllowDeleteOwnAccount": "Tillåt användare att radera egna konton", "Accounts_AllowEmailChange": "Tillåt byte av e-postadress", "Accounts_AllowEmailNotifications": "Tillåt e-postaviseringar", @@ -339,6 +467,8 @@ "Activity": "Aktivitet", "Actor": "Aktör", "Add": "Lägg till", + "Add_Value": "Lägg till värde", + "Add_room": "Lägg till rum", "Add-on": "Tillägg", "Add-on_required": "Tillägg krävs", "Add-on_required_modal_enable_content": "Appen kan inte aktiveras utan det nödvändiga prenumerationstillägget. Kontakta säljavdelningen för att få tillägget för den här appen.", @@ -409,6 +539,7 @@ "Aliases": "Alias", "All": "Alla", "All_Apps": "Alla appar", + "All_directions": "Alla riktningar", "All_Prices": "Alla priser", "All_Settings": "Alla inställningar", "All_added_tokens_will_be_required_by_the_user": "Alla tillagda tokens kommer att krävas av användaren", @@ -419,10 +550,16 @@ "All_messages": "Alla meddelanden", "All_roles": "Alla roller", "All_rooms": "Alla rum", + "All_statuses": "Alla statusar", "All_time": "Hela tiden", "All_users": "Alla användare", "All_users_in_the_channel_can_write_new_messages": "Alla användare i kanalen kan skriva nya meddelanden", "All_visible": "Alla synliga", + "Allow": "Tillåt", + "allow-external-voice-calls": "Tillåt externa röstsamtal", + "allow-external-voice-calls_description": "Behörighet att tillåta användare att göra och ta emot samtal med användare från externa integrationer.", + "allow-internal-voice-calls": "Tillåt interna röstsamtal", + "allow-internal-voice-calls_description": "Behörighet att tillåta användare att göra och ta emot samtal med andra användare i arbetsytan.", "Allow_Invalid_SelfSigned_Certs": "Tillåt ogiltiga självsignerade certifikat", "Allow_Invalid_SelfSigned_Certs_Description": "Tillåt ogiltiga och självsignerade SSL-certifikat för länkvalidering och förhandsvisningar.", "Allow_Marketing_Emails": "Tillåt e-post med marknadsföring", @@ -617,8 +754,10 @@ "Apps_Permissions_message_read": "Kom åt meddelanden", "Apps_Permissions_message_write": "Skicka och ändra meddelanden", "Apps_Permissions_networking": "Åtkomst till servernätverket", + "Apps_Permissions_experimental_default": "Använd experimentella API:er", "Apps_Permissions_persistence": "Lagra interna data i databasen", "Apps_Permissions_room_read": "Få tillgång till kanalinformation", + "Apps_Permissions_room_system_view-all": "Visa alla rum i arbetsytan", "Apps_Permissions_room_write": "Skapa och ändra rum", "Apps_Permissions_scheduler": "Registrera och hantera schemalagda jobb", "Apps_Permissions_server-setting_read": "Kom åt inställningar på servern", @@ -629,6 +768,7 @@ "Apps_Permissions_upload_write": "Ladda upp filer till servern", "Apps_Permissions_user_read": "Kom åt information om användare", "Apps_Permissions_user_write": "Ändra information om användare", + "Apps_Permissions_abac_read": "Visa ABAC-attribut tilldelade till operativa entitetstyper", "Apps_Private_App_Is_Exempt": "{{appName}} är redan installerad och undantagen från policyn för appbegränsning.\nUndantagna appar kan inte uppdateras.", "Apps_Settings": "Appinställningar", "Apps_User_Already_Exists": "Användarnamnet {{username}} används redan. Ändra namnet eller ta bort användaren om du vill installera appen", @@ -659,6 +799,7 @@ "Are_you_sure_you_want_to_pin_this_message": "Är du säker på att du vill fästa det här meddelandet?", "Are_you_sure_you_want_to_reset_the_name_of_all_priorities": "Är du säker på att du vill återställa namnet på alla prioriteringar?", "Are_you_sure_delete_contact": "Är du säker att du vill ta bort {{contactName}} och alla {{channelsCount}} av deras konversationshistorik? För att bekräfta, skriv '{{confirmationText}}' i fältet nedan.", + "Are_you_sure_you_want_to_discard_this_outbound_message": "Är du säker på att du vill ta bort detta utgående meddelande?", "Ask_enable_advanced_contact_profile": "Be administratören för din arbetsyta att aktivera avancerad kontaktprofil", "Asset_preview": "Förhandsgranskning av tillgång", "Assets": "Tillgångar", @@ -676,6 +817,13 @@ "AtlassianCrowd_Description": "Integrera Atlassian Crowd.", "Attachment_File_Uploaded": "Uppladdad fil", "Attribute_handling": "Attributhantering", + "Attribute_Values": "Attributvärden", + "Attributes": "Attribut", + "Attribute_based_access_control": "Attributbaserad åtkomstkontroll", + "Attribute_based_access_control_title": "Automatisera komplex åtkomsthantering i hela organisationen", + "Attribute_based_access_control_description": "ABAC automatiserar rumåtkomst, beviljar eller återkallar åtkomst baserat på dynamiska användarattribut snarare än fasta roller.", + "ABAC_Attributes": "Användarattribut", + "ABAC_Attributes_description": "Användaregenskaper som ABAC använder för att bestämma rumåtkomst", "Audio": "Ljud", "Audio_Notification_Value_Description": "Kan vara vilket anpassat ljud som helst eller standardljuden: beep, chelle, ding, droplet, highbell, seasons", "Audio_Notifications_Default_Alert": "Ljud för standardvarning", @@ -843,6 +991,7 @@ "Busy": "Upptagen", "Buy": "Köp", "Buy_more": "Köp mer", + "Buy_more_seats": "Köp fler platser", "By": "Av", "CAS": "CAS", "CAS_Creation_User_Enabled": "Tillåt skapande av användare", @@ -883,11 +1032,21 @@ "Calendar_settings": "Kalenderinställningar", "Call": "Ring upp", "Call_Already_Ended": "Samtalet har redan avslutats", + "Call_ID": "Samtal-ID", + "Call_in_progress": "Samtal pågår", + "Call_info": "Samtalsinfo", + "Call_info_could_not_be_loaded": "Samtalsinfo kunde inte laddas", "Call_Information": "Samtalsinformation", "Call_again": "Ring upp igen", "Call_back": "Ring tillbaka", "Call_declined": "Samtalet avvisades.", "Call_ended": "Samtalet avslutades", + "Call_ended_bold": "*Röstsamtal avslutad*", + "Call_not_answered_bold": "*Röstsamtal besvarades inte*", + "Call_failed_bold": "*Röstsamtal misslyckades*", + "Call_feature_unsupported": "Andra parten stöder inte detta", + "Call_transferred_bold": "*Röstsamtal överfördes*", + "Call_history": "Samtalhistorik", "Call_history_provides_a_record_of_when_calls_took_place_and_who_joined": "I samtalshistoriken samlas information om när samtal ägt rum och vilka som deltog.", "Call_not_found": "Samtal inte hittat", "Call_not_found_error": "Detta kan hända när URL:en för samtalet inte är giltig eller om du har problem med anslutningen. Kontrollera källan till URL-adressen och försök igen, eller prata med arbetsytans administratör om problemet kvarstår", @@ -1008,6 +1167,8 @@ "Click_here_for_more_details_or_contact_sales_for_a_new_license": "Klicka här om du vill ha mer information eller kontakta {{email}} om du vill ha en ny licens.", "Click_here_for_more_info": "Klicka här för mer information", "Click_here_to_clear_the_selection": "Klicka här för att rensa urvalet", + "Click_here_to_enter_your_password": "Klicka här för att ange ditt lösenord", + "Click_here_to_view_and_save_your_new_E2EE_password": "Klicka här för att visa och spara ditt nya E2EE-lösenord.", "Click_the_messages_you_would_like_to_send_by_email": "Klicka på de meddelanden som du vill skicka via e-post", "Click_to_join": "Klicka för att ansluta!", "Click_to_load": "Klicka för att läsa in", @@ -1108,6 +1269,7 @@ "Confirm": "Bekräfta", "Confirm_configuration_update": "Bekräfta uppdateringen av konfigurationen", "Confirm_configuration_update_description": "Identifieringsuppgifter och uppgifter om molnanslutning kommer att sparas.

    Varning: Om detta faktiskt är en ny arbetsyta, vänligen gå tillbaka och välj alternativet ny arbetsyta för att undvika kommunikationskonflikter.", + "Confirm_new_E2EE_password": "Bekräfta nytt E2EE-lösenord", "Confirm_new_password": "Bekräfta nytt lösenord", "Confirm_new_workspace": "Bekräfta ny arbetsyta", "Confirm_new_workspace_description": "Identifieringsdata och molnanslutningsdata kommer att återställas.

    Varning: Licensen kan påverkas om arbetsytans URL ändras.", @@ -1130,6 +1292,7 @@ "Contact": "Kontakt", "Contact_Center": "Kontaktcenter", "Contact_Chat_History": "Chatthistorik för kontakt", + "Contact_detail": "Kontaktuppgift", "Contact_Info": "Kontaktuppgifter", "Contact_Manager": "Kontaktansvarig", "Contact_Name": "Kontaktnamn", @@ -1518,6 +1681,7 @@ "Custom_User_Status_Info": "Information om anpassad användarstatus", "Custom_User_Status_Updated_Successfully": "Anpassad användarstatus har uppdaterats", "Custom_agent": "Anpassad agent", + "Custom_content": "Anpassat innehål", "Custom_dates": "Anpassade datum", "Custom_oauth_helper": "När du ställer in din OAuth-provider, måste du ange en callback-webbadress. Använd
     %s 
    .", "Custom_roles": "Anpassade roller", @@ -1575,6 +1739,7 @@ "Delete_File_Warning": "När du tar bort en fil tas den bort permanent. Du kan inte ångra åtgärden.", "Delete_Role_Warning": "När du tar bort en roll tas den bort permanent. Du kan inte ångra åtgärden.", "Delete_Role_Warning_Not_Enterprise": "Detta kan inte ångras. Du kommer inte att kunna skapa en ny anpassad roll, eftersom den funktionen inte längre är tillgänglig för din nuvarande plan.", + "Delete_Room_Warning": "Borttagning av denna {{roomType}} kommer också att ta bort alla meddelanden. Detta kan inte ångras.", "Delete_User_Warning": "Radering av en användare kommer att radera alla meddelanden från den användaren. Detta kan inte ångras.", "Delete_User_Warning_Delete": "Radering av en användare kommer att radera alla meddelanden från den användaren. Detta kan inte ångras.", "Delete_User_Warning_Keep": "Användaren raderas, men deras meddelanden kommer att förbli synliga. Detta kan inte ångras.", @@ -1633,6 +1798,7 @@ "Device_Management_Enable_Login_Emails_Description": "E-postmeddelanden skickas till arbetsytans medlemmar varje gång en ny inloggning till deras konton sker.", "Device_Management_IP": "IP-adress", "Device_Management_OS": "Operativsystem", + "Device_settings_lowercase": "Enhetsinställningar", "Device_settings_not_supported_by_browser": "Enhetsinställningar (stöds inte av webbläsaren)", "Devices": "Enheter", "Devices_Set": "Inställda enheter", @@ -1671,6 +1837,7 @@ "Direction": "Riktning", "Directory": "Katalog", "Disable": "Inaktivera", + "Disable_E2E_encryption": "Inaktivera E2E-kryptering", "Disable_Facebook_integration": "Inaktivera Facebookintegration", "Disable_Notifications": "Inaktivera notifieringar", "Disable_another_app": "Inaktivera en annan app eller uppgradera till Enterprise för att aktivera den här appen.", @@ -1682,6 +1849,7 @@ "Disallow_reacting": "Tillåt ej reaktioner", "Disallow_reacting_Description": "Tillåter ej reaktioner", "Discard": "Ignorera", + "Discard_message": "Kasta meddelande", "Disconnect": "Koppla ifrån", "Disconnect_workspace": "Koppla bort arbetsytan", "Disconnected": "Frånkopplad", @@ -1740,6 +1908,9 @@ "Download_Snippet": "Ladda ned", "Download_file": "Ladda ner fil", "Downloading_file_from_external_URL": "Laddar ned fil från extern URL", + "Drafts": "Utkast", + "Drafts_in_sidebar": "Utkast i sidofältet", + "Drafts_in_sidebar_description": "Snabb åtkomst till alla dina rum med oavslutade meddelanden.", "Drop_to_upload_file": "Släpp för att ladda upp filen", "Dry_run": "Testkörning", "Dry_run_description": "Kommer endast att skicka ett e-postmeddelande, till samma adress som i Från. E-postadressen måste höra till en giltig användare.", @@ -1749,7 +1920,9 @@ "Duplicate_file_name_found": "En fil med samma namn hittades.", "Duplicate_private_group_name": "Det finns redan en privat grupp med namnet %s", "Duplicated_Email_address_will_be_ignored": "Duplicerade e-postadresser kommer ignoreras", + "Duration": "Varaktighet", "E2EE_Composer_Unencrypted_Message": "Du skickar ett okrypterat meddelande", + "E2EE_password_reset": "Återställning av E2EE-lösenord", "E2EE_alert": "Aktivering av E2EE påverkar andra funktioner
    • - Krypterat innehåll kan inte hittas genom sökning
    • - Krypterat innehåll kan inte granskas
    • - Botinteraktioner kanske inte fungerar med krypterade meddelanden
    ", "E2E_Allow_Unencrypted_Messages": "Okrypterade meddelanden i krypterade rum", "E2E_Allow_Unencrypted_Messages_Description": "Tillåt att meddelanden i klartext skickas i rum med krypterat innehåll. Dessa meddelanden kommer inte att krypteras.", @@ -1855,9 +2028,11 @@ "Empty_title": "Tom titel", "Enable": "Aktivera", "Enable_Auto_Away": "Aktivera automatiskt borta från skrivbordet", + "Enable_Auto_Away_Description": "Byter din status till Borta efter en period av inaktivitet. Har ingen effekt om statusen är manuellt inställd på Upptagen eller Borta.", "Enable_CSP": "Aktivera säkerhetspolicy för innehåll", "Enable_CSP_Description": "Inaktivera inte det här alternativet såvida du inte har en anpassad version och har problem på grund av infogade skript", "Enable_Desktop_Notifications": "Aktivera skrivbordsnotifieringar", + "Enable_E2E_encryption": "Aktivera E2E-kryptering", "Enable_Password_History": "Aktivera lösenordshistorik", "Enable_Password_History_Description": "När alternativet är aktiverat kan användare inte uppdatera sina lösenord till något av sina senast använda lösenord", "Enable_Svg_Favicon": "Aktivera SVG favicon", @@ -1889,12 +2064,15 @@ "Encrypted_messages_false": "Meddelandena är inte krypterade", "Encrypted_not_available": "Inte tillgängligt för offentliga {{roomType}}", "Encrypted_setting_changed_successfully": "Krypteringsinställningen har ändrats", + "Enter_current_E2EE_password_to_set_new": "För att ange ett nytt lösenord måste du först <1>ange ditt nuvarande E2EE-lösenord.", "Encryption_key_saved_successfully": "Din krypteringsnyckel sparades.", "End": "Avsluta", + "Ended": "Slutat", "End_Time": "Sluttid", "End_Date": "Slutdatum", "End-to-end_encryption": "End-to-end-kryptering", "End-to-end_encryption_Description": "Se till att konversationer hålls privata", + "E2E_encryption_enabled": "E2E-kryptering aktiverad", "End_To_End_Encryption_Not_Enabled": "End-to-end-kryptering är inte aktiverad", "End_conversation": "Avsluta samtalet", "End_suspicious_sessions": "Avsluta alla misstänkta sessioner", @@ -1941,6 +2119,7 @@ "Entertainment": "Underhållning", "Error": "Fel", "Error_404": "Fel 404", + "Error_encrypting_file": "Fel vid kryptering av fil", "Error_Site_URL": "Ogiltig Site_Url", "Error_Site_URL_description": "Uppdatera inställningen för \"Site_Url\". Du hittar mer information [här](https://go.rocket.chat/i/invalid-site-url)", "Error_changing_password": "Fel vid byte av lösenord", @@ -1950,6 +2129,7 @@ "Error_sending_livechat_offline_message": "Ett fel inträffade när ett offlinemeddelande för Omnichannel skulle skickas", "Error_sending_livechat_transcript": "Ett fel inträffade när Omnichannel-utskriften skulle skickas", "Error_something_went_wrong": "Ojdå! Något gick fel. Läs in sidan igen eller kontakta en administratör.", + "Error_loading__name__information": "Fel vid inläsning av {{name}}-information", "Errors_and_Warnings": "Fel och varningar", "Esc_to": "Esc för att", "Estimated_due_time": "Beräknad förfallotid", @@ -2002,12 +2182,17 @@ "External_service_returned_valid_response": "Extern tjänst returnerade ett giltigt svar", "External_service_test_hint": "Klicka på \"Skicka test\" innan du sparar triggern.", "External_service_url": "URL för extern tjänst", + "Extra_CSP_Domains": "Extra CSP-domäner", + "Extra_CSP_Domains_Description": "Extra domäner att lägga till i Content-Security-Policy", "Extremely_likely": "Extremt troligt", "FEDERATION_Discovery_Method": "Upptäcktsmetod", "FEDERATION_Discovery_Method_Description": "Du kan använda hubben eller en SRV och en TXT-post på dina DNS-poster.", "FEDERATION_Domain": "Domän", "FEDERATION_Domain_Alert": "Ändra inte det här efter det att du har aktiverat funktionen. Vi kan inte hantera domänändringar ännu.", "FEDERATION_Domain_Description": "Lägg till den domän som servern ska länkas till. Till exempel: @rocket.chat.", + "Old_Federation_Alert": "Denna federationsversion stöds inte längre. Konfigurera gärna det nya alternativet ovan med namnet Native Federation.
    Mer information om Matrix Federation-stöd finns här", + "Rocket.Chat Federation": "Rocket.Chat Federation (STÖDS INTE)", + "Matrix Bridge": "Matrix Bridge (STÖDS INTE)", "FEDERATION_Public_Key": "Öppen nyckel", "FEDERATION_Public_Key_Description": "Det här är den nyckel du delar med dina kollegor.", "FEDERATION_Status": "Status", @@ -2073,6 +2258,7 @@ "Federation_Matrix_homeserver_url_alert": "Vi rekommenderar att du använder en ny tom server för vår federation", "Federation_Matrix_hs_token": "Token för hemserver", "Federation_Matrix_id": "Id för apptjänst", + "Federation_Matrix_Federated_Description_invalid_version": "Detta rum skapades av en gamla Federation-version och det är blockerat på obestämd tid. <1>Klicka här för mer information om Matrix Federation-stöd", "Federation_Matrix_join_public_rooms_is_enterprise": "Gå med i federerade rum är en funktion i Enterprise Edition", "Federation_Matrix_join_public_rooms_is_premium": "Gå med i federerade rum är en Premium-funktion", "Federation_Matrix_losing_privileges": "Förlust av privilegier", @@ -2091,6 +2277,33 @@ "Federation_Search_federated_rooms": "Sök federerade rum", "Federation_is_currently_disabled_on_this_workspace": "Federation är för närvarande inaktiverat på den här arbetsytan", "Federation_slash_commands": "Federeringskommandon", + "Federation_Service_Enabled": "Aktivera inbyggd federation", + "Federation_Service_Enabled_Description": "Aktivera inbyggd federation för kommunikation mellan servrar med Matrix Protocol.", + "Federation_Service_EDU_Process_Typing": "Bearbeta skrivningshändelser", + "Federation_Service_EDU_Process_Typing_Description": "Skicka och ta emot händelser för användarens skrivande av ett meddelande mellan federerade servrar.", + "Federation_Service_EDU_Process_Typing_Alert": "Aktivering av skrivningshändelser kan öka belastningen på din server och nätverkstrafiken betydligt, särskilt om du har många användare. Aktivera bara det här alternativet om du förstår konsekvenserna och har nödvändiga resurser för att hantera den extra belastningen.", + "Federation_Service_EDU_Process_Presence": "Bearbeta närvaro-händelser", + "Federation_Service_EDU_Process_Presence_Description": "Skicka och ta emot händelser för användarens närvaro (online, offline, etc.) mellan federerade servrar.", + "Federation_Service_EDU_Process_Presence_Alert": "Aktivering av närvaro-händelser kan öka belastningen på din server och nätverkstrafiken betydligt, särskilt om du har många användare. Aktivera bara det här alternativet om du förstår konsekvenserna och har nödvändiga resurser för att hantera den extra belastningen.", + "Federation_Service_EDU_Process_Receipt": "Bearbeta mottagningshändelser", + "Federation_Service_EDU_Process_Receipt_Alert": "Aktivering av mottagningshändelser kan öka belastningen på din server och nätverkstrafiken betydligt, särskilt om du har många användare. Aktivera bara det här alternativet om du förstår konsekvenserna och har nödvändiga resurser för att hantera den extra belastningen.", + "Federation_Service_EDU_Process_Receipt_Description": "Skicka och ta emot händelser för meddelandeläsning mellan federerade servrar.", + "Federation_Service_Domain": "Federerad domän", + "Federation_Service_Domain_Description": "Domänen som denna server ska svara på, till exempel: `acme.com`. Detta kommer att användas som suffix för användar-ID:n (t.ex. `@user:acme.com`).
    Om din chattserver är tillgänglig från en annan domän än den du vill använda för federation, bör du följa vår dokumentation för att konfigurera `.well-known`-filen på din webbserver.", + "Federation_Service_Domain_Alert": "Ange endast domänen, inkludera inte http(s)://, snedstreck eller någon sökväg efter det.
    Använd något som `acme.com` och inte `https://acme.com/chat`.", + "Federation_Service_Matrix_Signing_Algorithm": "Signeringsalgoritm för nyckel", + "Federation_Service_Matrix_Signing_Version": "Version av signeringsnyckel", + "Federation_Service_Matrix_Signing_Key": "Signeringsnyckel", + "Federation_Service_Matrix_Signing_Key_Description": "Den privata base64-signeringsnyckeln som används för att autentisera federationsbegäranden. Detta är vanligtvis en Ed25519-algoritmnyckel (version 4), kodad som base64. Det är väsentligt för säker kommunikation mellan federerade servrar över Matrix-protokollet och bör hållas konfidentiellt.", + "Federation_Service_max_allowed_size_of_public_rooms_to_join": "Maximalt antal medlemmar när du ansluter till ett offentligt rum på en fjärr-server", + "Federation_Service_max_allowed_size_of_public_rooms_to_join_Alert": "Kom ihåg att ju större rummet du tillåter användare att ansluta till, desto längre tid tar det att ansluta till det rummet, plus mängden resurser det kommer att använda. Läs mer", + "Federation_Service_max_allowed_size_of_public_rooms_to_join_Description": "Användargränsen från ett offentligt rum på en fjärr-server som fortfarande kan ansluta till. Rum som överskrider denna inställning kommer fortfarande att listas, men användare kan inte ansluta till dem", + "Federation_Service_Join_Encrypted_Rooms": "Tillåt anslutning till krypterade federerade rum", + "Federation_Service_Join_Non_Private_Rooms": "Tillåt anslutning till icke-privata rum", + "Federation_Service_Allow_List": "Domän tillåtelselista", + "Federation_Service_Allow_List_Description": "Begränsa federationen till den givna tillåtelselistan över domäner.", + "Federation_Service_Validate_User_Domain": "Begränsningar för användar-e-post", + "Federation_Service_Validate_User_Domain_Description": "Begränsa åtkomsten till verifierade e-postadresser som matchar din federerade domän.", "Field": "Fält", "Field_removed": "Fältet borttaget", "Field_required": "Fält krävs", @@ -2110,17 +2323,22 @@ "FileUpload_Disabled": "Filuppladdningar är inaktiverade.", "FileUpload_Enable_json_web_token_for_files": "Aktivera JSON Web Token-skydd (JWT) för filuppladdningar", "FileUpload_Enable_json_web_token_for_files_description": "Bifogar en JWT till URL:er för uppladdade filer", + "FileUpload_Enable_json_web_token_for_files_Alert": "Det här alternativet gäller bara när en JWT-hemlighet är konfigurerad. Om \"JWT-hemlighet för filer\" lämnas tom kommer ingen token att genereras och JWT-filskydd kommer inte att tillämpas.", "FileUpload_Enabled": "Filuppladdningar aktiverade", "FileUpload_Enabled_Direct": "Filuppladdningar aktiverade i direktmeddelanden", "FileUpload_Error": "Filuppladdningsfel", "FileUpload_FileSystemPath": "System path", "FileUpload_File_Empty": "Tom fil", + "FileUpload_Canceled": "Uppladdning avbruten", + "FileUpload_Update_Failed": "Kunde inte uppdatera filnamn", "FileUpload_GoogleStorage_AccessId": "Google Storage Access ID", "FileUpload_GoogleStorage_AccessId_Description": "Access-id är vanligtvis i ett e-postformat, till exempel: \"`example-test@example.iam.gserviceaccount.com`\"", "FileUpload_GoogleStorage_Bucket": "Google Storage Bucket Name", "FileUpload_GoogleStorage_Bucket_Description": "Namnet på bucket som filerna ska laddas upp till.", "FileUpload_GoogleStorage_ProjectId": "Projekt-ID", "FileUpload_GoogleStorage_ProjectId_Description": "Projekt-ID från Google Developer's Console", + "FileUpload_GoogleStorage_URLExpiryTimeSpan": "URL-utgångsdatum", + "FileUpload_GoogleStorage_URLExpiryTimeSpan_Description": "Tid efter vilken Google Cloud Storage-genererade URL:er inte längre är giltiga (i sekunder). Om detta är inställt på mindre än 5 sekunder ignoreras det här fältet och URL:er använder standardets utgångsdatum (15 minuter).", "FileUpload_GoogleStorage_Proxy_Avatars": "Proxyavatarer", "FileUpload_GoogleStorage_Proxy_Avatars_Description": "Proxyavatar-filöverföringar via din server istället för direkt tillgång till URL", "FileUpload_GoogleStorage_Proxy_Uploads": "Proxy-uppladdningar", @@ -2189,6 +2407,7 @@ "File_not_allowed_direct_messages": "Fildelning får inte användas i direktmeddelanden.", "File_removed_by_automatic_prune": "Filen avlägsnas med automatisk rensning", "File_removed_by_prune": "Fil borttagen av prune", + "File_removed": "Fil borttagen", "File_type_is_not_accepted": "Filtyp accepteras inte.", "File_uploaded": "Uppladdad fil", "File_uploaded_successfully": "Filen har laddats upp", @@ -2331,6 +2550,7 @@ "Hide_Unread_Room_Status": "Dölj oläst rums status", "Hide_additional_fields": "Dölj ytterligare fält", "Hide_counter": "Dölj räknare", + "Hide_chat": "Dölj chatt", "Hide_flextab": "Dölj höger sidofält med klick", "Hide_roles": "Dölj roller", "Hide_room": "Dölj rum", @@ -2463,11 +2683,14 @@ "Incoming_Livechats": "Köade chattar", "Incoming_WebHook": "Inkommande WebHook", "Incoming_call": "Inkommande samtal", + "Incoming_call_ellipsis": "Inkommande samtal...", "Incoming_call_from": "Inkommande samtal från", "Incoming_call_from__roomName__": "Inkommande samtal från {{roomName}}", "Incoming_call_transfer": "Överföring av inkommande samtal", + "Incoming_voice_call": "Inkommande röstsamtal", "Incoming_voice_call_canceled_suddenly": "Ett inkommande röstsamtal avbröts plötsligt.", "Incoming_voice_call_canceled_user_not_registered": "Ett inkommande röstsamtal avbröts på grund av ett oväntat fel.", + "Incorrect_encryption_password": "Felaktigt krypteringslösenord", "Industry": "Industri", "Info": "Info", "Information_to_keep_top_of_mind": "Information att hålla i minnet", @@ -2570,12 +2793,14 @@ "Invalid_username": "Inloggningsnamnet är ogiltigt", "Invisible": "Osynlig", "Invitation": "Inbjudan", + "Invitation_date": "Inbjudningsdatum", "Invitation_Email_Description": "Du kan använda följande platsmarkörer: \n - [email] för mottagarens mejl. \n - [Site_Name] och `[Site_URL]` för programnamn och webbadress. ", "Invitation_HTML": "Inbjudan HTML", "Invitation_HTML_Default": "

    Välkommen till [Site_Name]

    Gå till [Site_URL] och prova den bästa chattlösningen som finns idag!

    ", "Invitation_Subject": "Inbjudan ämne", "Invitation_Subject_Default": "Du har blivit inbjuden till [Site_Name]", "Invite": "Inbjudan", + "Invited__date__": "Inbjuden {{date}}", "Invite_Link": "Inbjudningslänk", "Invite_Users": "Bjud in användare", "Invite_and_add_members_to_this_workspace_to_start_communicating": "Bjud in och lägg till medlemmar i arbetsytan för att börja kommunicera. ", @@ -2627,12 +2852,25 @@ "Katex_Parenthesis_Syntax": "Tillåt parentessyntax", "Katex_Parenthesis_Syntax_Description": "Möjligt att använda \\[katex blockera\\] och \\(inline katex\\) syntax", "Keep_default_user_settings": "Håll standardinställningarna", + "Keep_editing": "Fortsätt redigering", + "Keyboard_Shortcut_Key_Alt": "Alt", + "Keyboard_Shortcut_Key_ArrowDown": "Nedpil", + "Keyboard_Shortcut_Key_ArrowLeft": "Vänsterpil", + "Keyboard_Shortcut_Key_ArrowRight": "Högerpil", + "Keyboard_Shortcut_Key_ArrowUp": "Uppil", + "Keyboard_Shortcut_Key_Command": "Kommando", + "Keyboard_Shortcut_Key_Control": "Ctrl", + "Keyboard_Shortcut_Key_Enter": "Enter", + "Keyboard_Shortcut_Key_Escape": "Esc", + "Keyboard_Shortcut_Key_Option": "Alternativ", + "Keyboard_Shortcut_Key_Shift": "Skift", "Keyboard_Shortcuts_Edit_Previous_Message": "Redigera tidigare meddelande", "Keyboard_Shortcuts_Mark_all_as_read": "Markera alla meddelanden (i alla kanaler) som lästa", "Keyboard_Shortcuts_Move_To_Beginning_Of_Message": "Flytta till början av meddelandet", "Keyboard_Shortcuts_Move_To_End_Of_Message": "Flytta till slutet av meddelandet", "Keyboard_Shortcuts_New_Line_In_Message": "Ny rad i meddelande komponera inmatning", "Keyboard_Shortcuts_Open_Channel_Slash_User_Search": "Öppna kanal/användarsökning", + "Keyboard_Shortcuts_Show_Keyboard_Shortcuts": "Visa kortkommandon", "Keyboard_Shortcuts_Title": "Tangentbordsgenvägar", "Knowledge_Base": "Kunskapsbas", "LDAP": "LDAP", @@ -2657,6 +2895,12 @@ "LDAP_Background_Sync_Keep_Existant_Users_Updated_Description": "Synkroniserar avataren, fälten, användarnamnet, etc (baserat på din konfiguration) av alla användare som redan importerats från LDAP på varje ** Sync Interval **", "LDAP_Background_Sync_Merge_Existent_Users": "Bakgrundssynkronisering Sammanfoga befintliga användare", "LDAP_Background_Sync_Merge_Existent_Users_Description": "Kommer att slå samman alla användare (baserat på dina filterkriterier) som finns i LDAP och som också finns i Rocket.Chat. För att aktivera detta aktiverar du inställningen \"Slå samman befintliga användare\" på fliken Datasynkronisering.", + "LDAP_DataSync_ABAC": "Synkronisera ABAC-attribut", + "LDAP_Background_Sync_ABAC_Attributes": "Bakgrundssynkronisering av ABAC-attribut", + "LDAP_Background_Sync_ABAC_Attributes_Description": "Aktivera en separat bakgrundsprocess för att synkronisera ABAC-attribut för användare.", + "LDAP_Background_Sync_ABAC_Attributes_Interval": "Bakgrundssynkroniseringsintervall för ABAC-attribut", + "LDAP_ABAC_AttributeMap": "Mappning av ABAC-attribut", + "LDAP_ABAC_AttributeMap_Description": "Mappa LDAP-användarattribut till Rocket.Chat ABAC-attribut. \n Som ett exempel kommer `{\"department\":\"dept\", \"region\":\"region\"}` att mappa LDAP-attributet `department` till ABAC-attributet `dept` och `region` till `region`. \n Strukturen måste vara ett JSON-objekt där varje nyckel är ett LDAP-attributnamn och varje värde är ABAC-attributnamnet som ska ställas in på användaren.", "LDAP_BaseDN": "Bas-DN", "LDAP_BaseDN_Description": "Det fullt kvalificerade distinkta namnet (DN) för ett LDAP-underträd som du vill söka igenom efter användare och grupper. Du kan lägga till så många du vill, men varje grupp måste definieras i samma domänbas som de användare som tillhör den. Exempel: `ou=Users+ou=Projects,dc=Example,dc=com`. Om du anger begränsade användargrupper kommer endast användare som tillhör dessa grupper att omfattas. Vi rekommenderar att du anger den översta nivån i LDAP-katalogträdet som domänbas och använder sökfilter för att kontrollera åtkomsten.", "LDAP_CA_Cert": "CA Cert", @@ -2690,6 +2934,7 @@ "LDAP_Encryption": "Kryptering", "LDAP_Encryption_Description": "Krypteringsmetod som används för att säkra kommunikationen till LDAP-servern. Som exempel kan nämnas `plain` (ingen kryptering),` SSL/LDAPS` (krypterad från början), och `StartTLS` (uppgradera till krypterad kommunikation när ansluten).", "LDAP_Enterprise": "Enterprise", + "LDAP_Extension_Field": "Tilläggsfält", "LDAP_FederationHomeServer_Field": "Federation Home Server-fältet", "LDAP_FederationHomeServer_Field_Description": "Hemservern kan endast tilldelas när användaren skapas. Om du ändrar detta har det ingen effekt på användare som redan har synkroniserats.", "LDAP_Find_User_After_Login": "Hitta användare efter inloggning", @@ -2828,6 +3073,7 @@ "Language_Version": "Engelsk Version", "Language_setting_warning": "Serverns språkinställning påverkar inte användarens klient
    Varje användare har sina egna språkpreferenser, som kommer att behållas om den här inställningen ändras.", "Larger_amounts_of_active_connections": "För större mängder aktiva anslutningar kan du överväga vår", + "Last_role_in_permission_warning": "Detta är den sista rollen med denna behörighet. Om du tar bort den låses denna sida mjukt från användargränssnittet, vilket kräver databasåtkomst för att ångra det. Vill du fortsätta?", "Last_5_minutes": "Senaste 5 minuterna", "Last_15_minutes": "Senaste 15 minuterna", "Last_30_minutes": "Senaste 30 minuterna", @@ -2851,6 +3097,8 @@ "Last_message__date__": "Sista meddelandet: {{date}}", "Last_seen": "Senast sedd", "Last_token_part": "Senaste token-del", + "Last_contact__time__": "Senaste kontakt {{time}}", + "Last_message_received__time__": "Senaste meddelandet mottaget {{time}}", "Latest": "Senaste", "Launched_successfully": "Lanserades framgångsrikt", "Layout": "Layout", @@ -2864,6 +3112,7 @@ "Layout_Home_Page_Content_Title": "Innehåll på hemsidan", "Layout_Home_Title": "Hem titel", "Layout_Legal_Notice": "Juridiskt meddelande", + "Layout_Login_Hide_Logo": "Dölj logotyp", "Layout_Login_Hide_Logo_Description": "Dölj logotypen på inloggningssidan.", "Layout_Login_Hide_Powered_By": "Dölj \"Drivs av\"", "Layout_Login_Hide_Powered_By_Description": "Dölj \"Drivs av\" på inloggningssidan.", @@ -2892,6 +3141,7 @@ "Learn_more_about_accessibility": "Läs mer om vårt engagemang för tillgänglighet här:", "Learn_more_about_agents": "Läs mer om agenter", "Learn_more_about_business_hours": "Läs mer om öppettider", + "Learn_more_about_canned_responses": "Läs mer om färdiga svar", "Learn_more_about_contacts": "Läs mer om kontakter", "Learn_more_about_conversations": "Läs mer om konversationer här", "Learn_more_about_current_chats": "Läs mer om aktuella chattar", @@ -2903,6 +3153,8 @@ "Learn_more_about_triggers": "Läs mer om triggers", "Learn_more_about_units": "Läs mer om enheter", "Learn_more_about_voice_channel": "Läs mer om röstsamtal här", + "You_have_been_invited_to_have_a_conversation_with": "Du har blivit inbjuden att ha en konversation med", + "Learn_more_about_Federation": "Läs mer om Federation", "Least_recent_updated": "Uppdaterades senast", "Leave": "Lämna", "Leave_Group_Warning": "Är du säker på att du vill lämna gruppen \"{{roomName}}\"?", @@ -3174,6 +3426,7 @@ "Maximum_number_of_guests_reached": "Det högsta antalet gäster har uppnåtts", "Me": "Jag", "Media": "Media", + "Media_URL": "Medie-URL", "Medium": "Medium", "Members": "Medlemmar", "Members_List": "Medlemslista", @@ -3247,6 +3500,8 @@ "Message_GroupingPeriodDescription": "Meddelanden kommer att grupperas med föregående meddelande om båda är från samma användare och förfluten tid var mindre än den angivna tiden i sekunder.", "Message_HideType_added_user_to_team": "Dölj meddelandet \"Användare lades till i teamet\"", "Message_HideType_au": "Dölj meddelandet \"Användare tillagd\"", + "Message_HideType_ui": "Användare inbjuden till rum", + "Message_HideType_uir": "Användare avvisade inbjudan till rum", "Message_HideType_changed_announcement": "Dölj meddelandet \"Rummets meddelande ändrades till\"", "Message_HideType_changed_description": "Dölj meddelandet \"Rummets beskrivning ändrades till\"", "Message_HideType_livechat_closed": "Dölj meddelanden om att \"konversationen är klar\"", @@ -3275,10 +3530,12 @@ "Message_HideType_ul": "Dölj meddelanden \"Användare lämnade\"", "Message_HideType_ult": "Dölj meddelandet \"Användaren lämnade teamet\"", "Message_HideType_user_added_room_to_team": "Dölj meddelandet \"Användaren lade till rummet till teamet\"", + "Message_HideType_user_banned": "Användare bannlyst", "Message_HideType_user_converted_to_channel": "Dölj meddelandet \"Användaren konverterade teamet till en kanal\"", "Message_HideType_user_converted_to_team": "Dölj meddelandet \"Användaren konverterade kanalen till ett team\"", "Message_HideType_user_deleted_room_from_team": "Dölj meddelandet \"Användaren tog bort rummet från teamet\"", "Message_HideType_user_removed_room_from_team": "Dölj meddelandet \"Användaren tog bort rummet från teamet\"", + "Message_HideType_user_unbanned": "Användare inte längre bannlyst", "Message_HideType_ut": "Dölj meddelandet \"Användare anslöt till konversationen\"", "Message_HideType_wm": "Dölj välkomstmeddelanden", "Message_Id": "Meddelande-id", @@ -3286,10 +3543,20 @@ "Message_KeepHistory": "Behåll meddelandehistorik", "Message_MaxAll": "Maximal kanalstorlek för ALLA meddelanden", "Message_MaxAllowedSize": "Största tillåtna meddelandestorlek", + "Message_not_sent_try_again": "Meddelande inte skickat. \nFörsök igen", "Message_QuoteChainLimit": "Maximalt antal kedjade citat", "Message_Read_Receipt_Enabled": "Visa läskvitton", "Message_Read_Receipt_Store_Users": "Detaljerade läskvitton", "Message_Read_Receipt_Store_Users_Description": "Visar varje användares läskvitton", + "Message_Read_Receipt_Archive_Enabled": "Aktivera arkivering av lästa kvittenser", + "Message_Read_Receipt_Archive_Enabled_Description": "När det är aktiverat kommer lästa kvittenser som är äldre än lagringperioden att flyttas från het lagring till kall lagring.", + "Message_Read_Receipt_Archive_Enabled_Alert": "Varning: Om du aktiverar detta på en arbetsyta med stor volym av lästa kvittenser kan systemet bearbeta migreringen till kall lagring under en längre period, vilket potentiellt kan påverka produktionsprestanda. Det rekommenderas att rensa upp eller manuellt migrera gamla lästa mottagardata innan du aktiverar denna inställning.", + "Message_Read_Receipt_Archive_Retention_Days": "Arkivlagringsperiod i dagar", + "Message_Read_Receipt_Archive_Retention_Days_Description": "Antal dagar att hålla lästa kvittenser i het lagring innan arkivering till kall lagring", + "Message_Read_Receipt_Archive_Cron": "Arkiv-Cron-schema", + "Message_Read_Receipt_Archive_Cron_Description": "Cron-uttryck för arkiveringsschemat (t.ex. \"0 2 * * *\" för dagligt kl. 2 på morgonen)", + "Message_Read_Receipt_Archive_Batch_Size": "Arkivbatchstorlek", + "Message_Read_Receipt_Archive_Batch_Size_Description": "Antal lästa kvittenser att bearbeta per batch under arkivering. Lägre värden minskar serverbelastningen men tar längre tid att slutföra.", "Message_ShowDeletedStatus": "Visa borttagen status", "Message_ShowEditedStatus": "Visa redigerad status", "Message_ShowFormattingTips": "Visa formateringstips", @@ -3324,6 +3591,7 @@ "Message_list": "Lista över meddelanden", "Message_pinning": "Fäst meddelande", "Message_removed": "meddelandet borttaget", + "Message_request": "Meddelandebegäran", "Message_sent": "Meddelande skickat", "Message_sent_by_email": "Meddelande skickat via e-post", "Message_starring": "Stjärnmarkera meddelanden", @@ -3335,6 +3603,7 @@ "Messages_exported_successfully": "Meddelanden exporterades framgångsrikt", "Messages_sent": "Skickade meddelanden", "Messages_that_are_sent_to_the_Incoming_WebHook_will_be_posted_here": "Meddelanden som skickas till inkommande WebHook kommer att publiceras här.", + "Messages_cannot_be_unsent": "Meddelanden kan inte tas bort", "Meta": "Meta", "Meta_Description": "Ange anpassade Meta-egenskaper.", "Meta_custom": "Anpassade metataggar", @@ -3433,6 +3702,7 @@ "Move_end_message": "`%s` - Flytta till slutet av meddelande", "Move_queue": "Flytta till kön", "Msgs": "Meddelanden ", + "Multi_line_code": "Kod på flera rader", "Multiple_monolith_instances_alert": "Du använder flera instanser utan en aktiv licens för Enterprise Edition. Alla funktioner kanske inte fungerar som avsett.", "Mute": "Tysta", "Mute_Focused_Conversations": "Stänga av fokuserade samtal", @@ -3487,6 +3757,7 @@ "New_discussion": "Ny diskussion", "New_discussion_first_message": "En diskussion inleds ofta med en fråga som \"Hur laddar jag upp en bild?\"", "New_discussion_name": "Ett beskrivande namn på diskussionsrummet", + "New_E2EE_password": "Nytt E2EE-lösenord", "New_integration": "Ny integrering", "New_line_message_compose_input": "`%s` - Ny rad i meddelandet som skrivs in", "New_logs": "Nya loggar", @@ -3503,6 +3774,7 @@ "New_version_available_(s)": "Ny version tillgänglig (%s)", "New_videocall_request": "Ny videoanropsförfrågan", "New_visitor_navigation": "Ny navigering: {{history}}", + "New_voice_call": "Nytt röstsamtal", "New_workspace": "Ny arbetsyta", "New_workspace_confirmed": "Ny arbetsyta bekräftad", "Newer_than": "Nyare än", @@ -3530,6 +3802,9 @@ "No_app_matches_for": "Ingen app matchar för", "No_apps_installed": "Inga installerade appar", "No_available_agents_to_transfer": "Inga tillgängliga agenter att överföra", + "No_banned_users": "Inga bannlysta användare", + "No_banned_users_description": "Bannlysta användare från detta rum kommer att visas här.", + "Banned_users_error": "Misslyckades att ladda bannlysta användare", "No_calls_yet": "Inga samtal hittades", "No_calls_yet_description": "Alla samtal kommer dyka upp här", "No_channels_in_team": "Inga Kanaler i teamet", @@ -3593,6 +3868,8 @@ "No_pinned_messages": "Inga pinnade meddelanden", "No_previous_chat_found": "Inga tidigare chattar hittades", "No_private_apps_installed": "Inga privata appar installerade", + "No_phone_number_yet_edit_contact": "Inget telefonnummer än <1>Redigera kontakt", + "No_phone_number_available_for_selected_channel": "Inget telefonnummer tillgängligt för den valda kanalen", "No_release_information_provided": "Ingen information om version har tillhandahållits", "No_requested_apps": "Inga begärda appar", "No_requests": "Inga förfrågningar", @@ -3606,6 +3883,7 @@ "No_tags_yet_description": "Lägg till taggar till ärenden för att göra det enklare att organisera och hitta relaterade konversationer.", "No_triggers_yet": "Inga triggers ännu", "No_triggers_yet_description": "Triggers är händelser som gör att widgeten för livechatt öppnas och skickar meddelanden automatiskt.", + "No_templates_available": "Inga mallar tillgängliga", "No_units_yet": "Inga enheter ännu", "No_units_yet_description": "Använd enheter för att gruppera avdelningar och hantera dem bättre.", "No_user_reports": "Inga användarrapporter", @@ -3617,6 +3895,8 @@ "Nonprofit": "Ideellt", "Normal": "Normal", "Not_Available": "Inte tillgänglig", + "Not_answered": "Inte besvarad", + "Not_available_for_ABAC_enabled_rooms": "Inte tillgänglig i ABAC-aktiverade rum", "Not_Following": "Följer inte", "Not_Imported_Messages_Title": "Följande meddelanden kunde inte importeras", "Not_Visible_To_Workspace": "Inte synlig för arbetsytan", @@ -3635,6 +3915,7 @@ "Nothing_found": "Inget hittat", "Notice_that_public_channels_will_be_public_and_visible_to_everyone": "Tänk på att offentliga Kanaler är öppna för och kan visas av alla.", "Notification_Desktop_Default_For": "Visa skrivbordsmeddelanden för", + "Notification_Desktop_show_voice_calls": "Visa skrivbordsmeddelanden för röstsamtal", "Notification_Push_Default_For": "Skicka push-notiser för", "Notification_RequireInteraction": "Åtgärd krävs för att skrivbordsaviseringen ska avvisas", "Notification_RequireInteraction_Description": "Fungerar bara med version 50 och senare av webbläsaren Chrome. Med parametern *requireInteraction* visas skrivbordsaviseringen på obestämd tid tills användaren interagerar med den.", @@ -3702,6 +3983,8 @@ "Omnichannel": "Omnichannel", "Omnichannel_Agent": "Omnichannel-agent", "Omnichannel_Contact_Center": "Kontaktcenter för Omnichannel", + "Omnichannel_Contact_Center_Chats": "Omnichannel kontaktcenter-chattar", + "Omnichannel_Contact_Center_Contacts": "Omnichannel kontaktcenterkontakter", "Omnichannel_Description": "Ställ in en Omnichannel så att du kan ansluta till kunderna från en och samma plats oavsett hur de ansluter till dig.", "Omnichannel_Directory": "Omnichannel-katalog", "Omnichannel_External_Frame": "Extern ram", @@ -3781,6 +4064,7 @@ "Open_conversations": "Öppna konversationer", "Open_days_of_the_week": "Öppet dagar i veckan", "Open_directory": "Öppna katalogen", + "Open_in_room": "Öppna i rum", "Open_settings": "Öppna inställningarna", "Open_sidebar": "Öppna sidofältet", "Open_thread": "Öppna tråden", @@ -3802,9 +4086,16 @@ "Original": "Original", "Other": "Övrigt", "Others": "Andra", + "Outbound_message": "Utgående meddelande", + "Outbound_message_sent_to__name__": "Utgående meddelande skickat till: {{name}}", + "Outbound_message_not_sent": "Utgående meddelande inte skickat.", + "Outbound_message_department_hint": "Tilldela svar till en avdelning.", + "Outbound_message_agent_hint": "Lämna tomt så kan vilken agent från den utsedda avdelningen hantera svaren.", + "Outbound_message_agent_hint_no_permission": "Du har inte behörighet att tilldela en agent. Svaret kommer att tilldelas avdelningen.", "Out_of_seats": "Slut på användarlicenser", "Outdated": "Föråldrad", "Outgoing": "Utgående", + "Outgoing_voice_call": "Utgående röstsamtal", "Outgoing_WebHook": "Utgående WebHook", "Outgoing_WebHook_Description": "Hämta data från Rocket.Chat i realtid.", "Outlook_Calendar": "Outlook-kalender", @@ -3900,6 +4191,7 @@ "Placeholder_for_email_or_username_login_field": "Platshållare för e-post- eller användarnamnsinloggningsfältet", "Placeholder_for_password_login_confirm_field": "Bekräfta platshållare för fältet för inloggning med lösenord", "Placeholder_for_password_login_field": "Platshållare för lösenordsinloggningsfältet", + "Placeholder": "Platshållare", "Plan_limits_reached": "Planens gränser uppnådda", "Platform_Linux": "Linux", "Platform_Mac": "Mac", @@ -3924,6 +4216,7 @@ "Please_select_an_user": "Välj en användare", "Please_select_enabled_yes_or_no": "Välj ett alternativ för Enabled (Aktiverad)", "Please_select_visibility": "Välj synlighet", + "Please_try_again": "Försök igen.", "Please_wait": "Vänligen vänta", "Please_wait_activation": "Vänligen vänta, detta kan ta lite tid.", "Please_wait_while_your_account_is_being_deleted": "Vänligen vänta medan ditt konto raderas...", @@ -3997,6 +4290,7 @@ "Private_apps_upgrade_empty_state_description": "Skräddarsy Rocket.Chat efter dina behov med privata appar.", "Private_apps_upgrade_empty_state_title": "Uppgradera för att låsa upp privata appar", "Private_channels": "Privata kanaler", + "Proceed_with_caution": "Fortsätt med försiktighet", "Productivity": "Produktivitet", "Profile": "Profil", "Profile_details": "Profildetaljer", @@ -4098,6 +4392,7 @@ "Reconnecting": "Återanslutning", "Record": "Spela in", "Records": "Poster", + "Recipient": "Mottagare", "Redirect_URI": "Omdirigerings-URI", "Redirect_URL_does_not_match": "URL-adressen för omdirigering stämmer inte", "Refresh": "Uppdatera", @@ -4141,6 +4436,7 @@ "RegisterWorkspace_Setup_No_Account_Title": "Har du inget konto?", "RegisterWorkspace_Setup_Steps": "Steg {{step}} av {{numberOfSteps}}", "RegisterWorkspace_Setup_Subtitle": "För att registrera arbetsytan måste det associeras med ett Rocket.Chat Cloud-konto.", + "RegisterWorkspace_Didnt_Receive_Email": "Mottog du inte e-post? <1>Skicka igen eller <3>ändra e-post", "RegisterWorkspace_Syncing_Complete": "Synkronisering slutförd", "RegisterWorkspace_Syncing_Error": "Ett fel inträffade vid synkroniseringen av din arbetsyta", "RegisterWorkspace_Token_Step_Two": "Kopiera ditt token och klistra in det nedan.", @@ -4167,7 +4463,11 @@ "Registration_status": "Registreringsstatus", "Registration_via_Admin": "Registrering via en administratör", "Regular_Expressions": "Vanliga uttryck", + "Reject": "Avvisa", "Reject_call": "Avvisa samtal", + "Reject_invitation": "Avvisa inbjudan", + "Reject_dm_invitation_description": "Du avvisar inbjudan att gå med {{username}} i en konversation. Detta kan inte ångras.", + "Reject_channel_invitation_description": "Du avvisar inbjudan från {{username}} att gå med i {{roomName}}. Detta kan inte ångras.", "Release": "Släpp", "Releases": "Versioner", "Religious": "Religiös", @@ -4211,6 +4511,7 @@ "Report": "Rapportera", "Report_Abuse": "Anmäl inlägg", "Report_User": "Rapportera användare", + "Report_message": "Rapportera meddelande", "Report_has_been_sent": "Rapporten har skickats", "Report_reason": "Rapportera anledning", "Report_sent": "Rapport skickad", @@ -4296,12 +4597,16 @@ "Retention_policy_warning_callout": "Varning för kvarhållandepolicy", "Retention_setting_changed_successfully": "Inställningen för lagringspolicy har ändrats framgångsrikt", "Retry": "Försök igen", + "Retrying": "Försöker igen", "Retry_Count": "Försök igen", "Return_to_home": "Tillbaka till startsidan", "Return_to_previous_page": "Tillbaka till föregående sida", "Return_to_the_queue": "Tillbaka till kön", + "Review": "Granska", "Review_contact": "Granska kontakt", "Review_devices": "Granska när och varifrån enheter ansluter", + "Revoke_invitation": "Återkalla inbjudan", + "Right": "Höger", "Ringing": "Ringer", "Ringtones_and_visual_indicators_notify_people_of_incoming_calls": "Ringsignaler och visuella signaler aviserar användarna om inkommande samtal.", "Robot_Instructions_File_Content": "Robots.txt-filens innehåll", @@ -4392,6 +4697,7 @@ "SAML_Custom_signature_validation_all": "Validera alla signaturer", "SAML_Custom_signature_validation_assertion": "Validera verifieringssignatur", "SAML_Custom_signature_validation_either": "Validera någon av signaturerna", + "SAML_Custom_signature_validation_none": "Validera inte signaturer", "SAML_Custom_signature_validation_response": "Validera svarssignatur", "SAML_Custom_signature_validation_type": "Typ av signaturvalidering", "SAML_Custom_signature_validation_type_description": "Inställningen ignoreras om inget anpassat certifikat har tillhandahållits. ", @@ -4399,6 +4705,8 @@ "SAML_Custom_user_data_custom_fieldmap_description": "Konfigurera hur anpassade användarfält fylls i från en post i SAML (när den hittats)", "SAML_Custom_user_data_fieldmap": "Karta över fält för användardata", "SAML_Custom_user_data_fieldmap_description": "Konfigurera hur användarkontofält (t.ex. e-post) ska fyllas i från en post i SAML (när den har hittats). \nSom ett exempel kommer `{\"name\":\"cn\", \"email\":\"mail\"}` att välja en persons mänskligt läsbara namn från cn-attributet och deras e-post från mail-attributet. \nTillgängliga fält i Rocket.Chat: `namn`, `e-post` och `användarnamn`, allt annat kommer att kasseras. \n`{\"email\": \"mail\",\"användarnamn\": {\"fieldName\": \"mail\",\"regex\": \"(.*)@.+$\",\"template\": \"user-regex\"},\"name\": { \"fieldNames\": [\"firstName\", \"lastName\"],\"template\": \"{{firstName}} {{lastName}}\"}, \"{{identifier}}\": \"uid\"}`", + "SAML_Custom_validate_logout_request_signature": "Verifiera signatur för utloggningsbegäran", + "SAML_Custom_validate_logout_response_signature": "Verifiera signatur för utloggningssvar", "SAML_Default_User_Role": "Standardanvändarroll", "SAML_Default_User_Role_Description": "Du kan ange flera roller avgränsade med kommatecken.", "SAML_Description": "SAML (Security Assertion Markup Language) används för utbyta data för autentisering och auktorisering.", @@ -4458,6 +4766,7 @@ "Save_changes": "Spara ändringar", "Save_to_enable_this_action": "Spara för att aktivera denna åtgärd", "Save_user": "Spara användare", + "Save_your_new_E2EE_password": "Spara ditt nya E2EE-lösenord", "Save_your_encryption_password_to_access": "Spara ditt lösenord för end-to-end-kryptering för åtkomst", "Saved": "Sparad", "Saved_new_url_site_is__url__": "Sparad, ny url för webbplats är: {{url}}", @@ -4476,6 +4785,7 @@ "Search": "Sök", "Search_Apps": "Sök efter appar", "Search_Channels": "Sök kanaler", + "Search_calls": "Sök samtal", "Search_Chat_History": "Sök i chatthistoriken", "Search_Description": "Välj sökleverantör för arbetsytan och konfigurera sökrelaterade inställningar.", "Search_Devices_Users": "Sök efter enheter eller användare", @@ -4504,6 +4814,7 @@ "Search_roles": "Sök roller", "Search_rooms": "Sök", "Searchable": "Sökbart", + "Seat_limit_reached": "Platsgräns nådd", "Seat_limit_reached_Description": "Din arbetsyta har nått sin avtalsenliga platsgräns. Köp fler platser för att lägga till fler användare.", "Seats": "Platser", "Seats_Available": "{{seatsLeft, number}} tillgängliga användarlicenser", @@ -4537,14 +4848,18 @@ "Select_at_least_one_user": "Välj åtminstone en användare", "Select_at_least_two_users": "Välj åtminstone två användare", "Select_atleast_one_channel_to_forward_the_messsage_to": "Välj minst en kanal att vidarebefordra meddelandet till", + "Select_agent": "Välj agent", + "Select_channel": "Välj kanal", "Select_department": "Välj en avdelning", "Select_file": "Välj fil", "Select_messages_to_hide": "Välj meddelanden som ska döljas", "Select_period": "Välj period", + "Select_recipient": "Välj mottagare", "Select_role": "Välj en roll", "Select_service_to_login": "Välj något av nedanstående alternativ för att byta din profilbild", "Select_someone_to_transfer_the_call_to": "Välj vem du vill koppla samtalet till", "Select_tag": "Välj en tagg", + "Select_template": "Välj mall", "Select_the_channels_you_want_the_user_to_be_removed_from": "Välj de kanaler du vill ta bort användaren från", "Select_the_teams_channels_you_would_like_to_delete": "Välj de team-Kanaler du vill ta bort. De du inte väljer flyttas till arbetsytan.", "Select_user": "Välj användare", @@ -4558,6 +4873,7 @@ "Self_managed_hosting": "Självhanterad hosting", "Send": "Skicka", "Send_Email_SMTP_Warning": "För att skicka detta e-postmeddelande måste du konfigurera en SMTP-server", + "Send_anyway": "Skicka ändå", "Send_Test": "Skicka test", "Send_Test_Email": "Skicka test-e-postmeddelande", "Send_Visitor_navigation_history_as_a_message": "Skicka besökarens navigeringshistorik som ett meddelande", @@ -4606,6 +4922,8 @@ "Server_File_Path": "Sökväg till serverfil", "Server_Folder_Path": "Sökväg till servermapp", "Server_Info": "Serverinfo", + "Server_logs_access_has_changed_callout_title": "Serverloggåtkomsten har ändrats i Rocket.Chat 8.0", + "Server_logs_access_has_changed_callout_description": "Loggvisaren togs bort. Vi rekommenderar att du konfigurerar en observabilitetsstapel och använder de loggåtkomstmetoder som stöds och beskrivs i [loggguiden]({{docsUrl}}).", "Server_Type": "Servertyp", "Server_already_added": "Server redan tillagd", "Server_doesnt_exist": "Servern finns inte", @@ -4637,6 +4955,7 @@ "Share": "Dela", "Share_Location_Title": "Dela position?", "Share_screen": "Dela skärm", + "Share_screen_failed_update_or_check_permissions": "Misslyckades att dela din skärm. Prova att uppdatera appen eller kontrollera dina behörigheter.", "Shared_Location": "Delad position", "Shared_Secret": "Delad hemlighet", "Sharing": "Delning", @@ -4654,6 +4973,7 @@ "Show_counter": "Markera som oläst", "Show_default_content": "Visa standardinnehåll", "Show_email_field": "Visa e-postfältet", + "Show_chat": "Visa chatt", "Show_mentions": "Visa märke för omnämnanden", "Show_more": "Visa mer", "Show_name_field": "Visa namnfältet", @@ -4686,6 +5006,9 @@ "Site_Name": "Webbplatsnamn", "Site_Url": "Webbadress", "Site_Url_Description": "Example: `https://chat.domain.com/`", + "SSRF_Allowlist": "SSRF-tillåtelselista", + "SSRF_Allowlist_Description": "Domäner, IP:ar eller IP:port (en per rad eller kommaseparerade) som tillåts för utgående förfrågningar trots SSRF-skydd. Använd endast för betrodda interna värdnamn (t.ex. internal.corp, 192.168.1.1, 192.168.1.1:8080).", + "SSRF_Protection": "SSRF-skydd", "Size": "Storlek", "Skin_tone": "Hudton", "Skip": "Hoppa över", @@ -4770,6 +5093,7 @@ "Source": "Källa", "Speaker": "Högtalare", "Speakers": "Högtalare", + "Spoiler_hidden_activate_to_reveal": "Spoiler gömd. Aktivera för att avslöja.", "Star": "Stjärnmarkera", "Star_Message": "Stjärnmarkera meddelande", "Starred_Messages": "Stjärnmarkerade meddelanden", @@ -4838,6 +5162,8 @@ "Step": "Steg", "Stop_Recording": "Sluta spela in", "Stop_call": "Avsluta samtal", + "Stop_sharing": "Sluta dela", + "Stop_sharing_screen": "Sluta dela skärm", "Store_Last_Message": "Spara senaste meddelandet", "Store_Last_Message_Sent_per_Room": "Spara det senaste meddelandet skickat på varje rum.", "Stream_Cast": "Stream Cast", @@ -4851,6 +5177,7 @@ "Submit": "Skicka", "Subscribe": "Prenumerera", "Subscription": "Prenumeration", + "Subscription_add-on_required": "Tilläggsprenumeration krävs", "Success": "Framgång", "Success_message": "Meddelande om framgång", "Successfully_downloaded_file_from_external_URL_should_start_preparing_soon": "Filen har laddats ned från den externa URL:en och bör börja förberedas inom kort", @@ -4961,6 +5288,8 @@ "Technology_Provider": "Teknikleverantör", "Technology_Services": "Tekniska tjänster", "Temporarily_unavailable": "Temporärt ej tillgänglig", + "template": "mall", + "Template_message": "Mallmeddelande", "Terms": "Villkor", "Terms_of_use": "Användarvillkor", "Test_Connection": "Testa anslutningen", @@ -4987,6 +5316,8 @@ "The_server_will_restart_in_s_seconds": "Servern startas om om %s sekunder", "The_setting_s_is_configured_to_s_and_you_are_accessing_from_s": "Inställningen %s är konfigurerad till %s och du har tillgång från %s!", "The_user_s_will_be_removed_from_role_s": "Användaren %s tas bort från rollen %s", + "The_user_will_be_banned_from__roomName__": "Användaren kommer att bannlysas från {{roomName}}", + "The_user_will_be_unbanned_from__roomName__": "Användaren kommer inte längre att bannlysas från {{roomName}}", "The_user_will_be_removed_from_s": "Användaren tas bort från %s", "The_user_wont_be_able_to_type_in_s": "Användaren kommer inte att kunna skriva i %s", "The_workspace_has_exceeded_the_monthly_limit_of_active_contacts": "Arbetsytan har överskridit den månatliga gränsen för aktiva kontakter.", @@ -5053,6 +5384,7 @@ "Time": "Tid", "Time_in_minutes": "Tid i minuter", "Time_in_seconds": "Tid i sekunder", + "Time_slash_Date": "Tid / Datum", "Timeout": "Tidsgräns", "Timeout_in_miliseconds": "Timeout (i milisekunder)", "Timeout_in_miliseconds_cant_be_negative_number": "Timeout (i milisekunder) kan inte vara ett negativt tal", @@ -5060,6 +5392,8 @@ "Timeouts": "Tidsgränser", "Timestamp": "Tidsstämpel", "Timezone": "Tidszon", + "Timezone_picker_description": "Välj tidszonen för den angivna tiden.", + "Timezone_picker_hint": "Andra ser tidsstämplar konverterade till sin egen tidszon.", "Title": "Titel", "Title_bar_color": "Färg på namnlist", "Title_bar_color_offline": "Titelbar färg offline", @@ -5104,6 +5438,10 @@ "Transfer_call": "Koppla samtal", "Transfer_to": "Överför till", "Transferred": "Överförda", + "Transferred_call__from__to": "{{from}} överförde samtal till", + "Transferring_call": "Överför samtal", + "Transferring_call_incoming": "Inkommande samtalöverföring", + "Transferring_call_incoming__from_": "Från {{from}}", "Translate": "Översätt", "Translate_to": "Översätt till", "Translated": "Översatt", @@ -5147,6 +5485,7 @@ "Turn_on_video": "Slå på video", "Two Factor Authentication": "Tvåfaktorsautentisering", "Two-factor_authentication": "Tvåfaktorsautentisering via TOTP", + "Two-factor_authentication_cancelled": "Tvåfaktorsautentisering avbruten", "Two-factor_authentication_disabled": "Tvåfaktorautentisering inaktiverad", "Two-factor_authentication_email": "Tvåfaktorsautentisering via e-post", "Two-factor_authentication_enabled": "Tvåfaktorautentisering aktiverad", @@ -5173,6 +5512,8 @@ "UI_Use_Real_Name": "Använd riktigt namn", "URL": "URL", "URLs": "URL:er", + "URL_is_required": "URL krävs", + "URL_must_start_with_'http://'_or_'https://'": "URL måste börja med \"http://\" eller \"https://\"", "UTC_Timezone": "UTC-tidszon", "UTF8_Channel_Names_Validation": "Validering av UTF8-kodade Kanalnamn", "UTF8_Channel_Names_Validation_Description": "Reguljärt uttryck som används till att validera kanalnamn", @@ -5185,9 +5526,11 @@ "Unable_to_make_calls_while_another_is_ongoing": "Det går inte att ringa samtal medan ett annat samtal pågår", "Unable_to_negotiate_call_params": "Det gick inte att förhandla om samtalsparametrar.", "Unarchive": "Avarkivera", + "Unassign_extension": "Ta bort tilldelning av tillägg", "Unassigned": "Otilldelad", "Unavailable": "Otillgänglig", "Unavailable_in_encrypted_channels": "Otillgänglig i krypterade kanaler", + "Unban_user_from_room": "Häv bannlysning för användare från rum", "Unblock": "Ta bort blockering", "Unblock_User": "Avblockera användare", "Uncheck_All": "Avmarkera alla", @@ -5208,6 +5551,7 @@ "Unknown_Import_State": "Okänt importtillstånd", "Unknown_User": "Okänd användare", "Unknown_contact_callout_description": "Okänd kontakt. Den här kontakten finns inte med i kontaktlistan.", + "Unknown": "Okänd", "Unlimited": "Obegränsat", "Unlimited_MACs": "Obegränsat antal MACs", "Unlimited_push_notifications": "Obegränsat antal push-meddelanden", @@ -5250,6 +5594,7 @@ "Update_version": "Uppdatera version", "Update_your_RocketChat": "Uppdatera din Rocket.Chat", "Updated_at": "Uppdaterad den", + "Updated": "Uppdaterad", "Upgrade": "Uppgradera", "UpgradeToGetMore_Headline": "Uppgradera för att få mer", "UpgradeToGetMore_Subtitle": "Ladda din arbetsplats med avancerade funktioner.", @@ -5273,6 +5618,7 @@ "Upgrade_tab_upgrade_your_plan": "Uppgradera ditt abonnemang", "Upgrade_to_Pro": "Uppgradera till Pro", "Upload": "Ladda upp", + "Upload_failed": "Uppladdning misslyckades", "Upload_Folder_Path": "Ladda upp mappväg", "Upload_From": "Ladda upp från {{name}}", "Upload_anyway": "Ladda upp ändå", @@ -5283,6 +5629,10 @@ "Upload_private_app": "Ladda upp en privat app", "Upload_user_avatar": "Ladda upp avatar", "Uploading_file": "Laddar upp fil...", + "Uploading__count__file": { + "one": "Laddar upp {{count}} fil", + "other": "Laddar upp {{count}} filer" + }, "Uploads": "Uppladdningar", "Uptime": "Upptid", "Usage": "Användning", @@ -5290,6 +5640,9 @@ "Use_Emojis": "Använd emojis", "Use_Global_Settings": "Använd globala inställningar", "Use_Legacy_Message_Template": "Använd inaktuell meddelandemall", + "Use_RC_SDK": "Använd Rocket.Chat SDK", + "Use_RC_SDK_Description": "Experimentell — när det är aktiverat dirigerar klienten Meteor DDP-trafik genom @rocket.chat/ddp-client (enkel WebSocket).", + "Use_RC_SDK_Alert": "Experimentell funktion. Starta om webbläsarfliken efter växling.", "Use_Room_configuration": "Skriv över serverkonfigurationen och använd rumskonfigurationen", "Use_Server_configuration": "Använd serverkonfiguration", "Use_User_Preferences_or_Global_Settings": "Använd Användarinställningar eller Globala inställningar", @@ -5334,6 +5687,8 @@ "User__username__removed_from__room_name__moderators": "Användaren {{username}} togs bort från {{room_name}} moderatorer", "User__username__removed_from__room_name__owners": "Användarn {{username}} togs bort från {{room_name}} ägare", "User__username__unmuted_in_room__roomName__": "Ljudet slogs på för användaren {{username}} i rummet {{roomName}}", + "User__username__banned_from__roomName__": "Användare {{username}} bannlyst från {{roomName}}", + "User__username__unbanned_from__roomName__": "Användare {{username}} inte längre bannlyst från {{roomName}}", "User_added": "Användare tillagd", "User_added_by": "Användaren {{user_added}} tillagd av {{user_by}}.", "User_added_successfully": "Användare framgångsrikt tillagd", @@ -5347,6 +5702,7 @@ "User_e2e_key_was_reset": "Användarens E2E-nyckel har återställts.", "User_first_log_in": "Användarens första inloggning", "User_has_been_activated": "Användaren har aktiverats", + "User_has_been_banned": "bannlyst {{user_banned}}", "User_has_been_deactivated": "Användaren har deaktiverats", "User_has_been_deleted": "Användaren har blivit borttagen", "User_has_been_ignored": "Användaren har ignorerats", @@ -5355,6 +5711,7 @@ "User_has_been_removed": "tog bort {{user_removed}}", "User_has_been_removed_from_s": "Användaren har tagits bort från %s", "User_has_been_removed_from_team": "Användaren har tagits bort från teamet", + "User_has_been_unbanned": "inte längre bannlyst {{user_unbanned}}", "User_has_been_unignored": "Användaren ignoreras inte längre", "User_has_been_unmuted": "slog på ljudet för {{user_unmuted}}", "User_is_blocked": "Användare är blockerad", @@ -5370,6 +5727,8 @@ "User_left": "Har lämnat kanalen.", "User_left_team": "lämnade teamet", "User_left_this_channel": "lämnade kanalen", + "User_invited_to_room": "inbjuden {{user_invited}} till rummet", + "User_rejected_invitation_to_room": "avvisade inbjudan till rummet", "User_left_this_team": "lämnade teamet", "User_logged_out": "Användaren är utloggad", "User_management": "Användarhantering", @@ -5395,6 +5754,8 @@ "User_updated_successfully": "Användare uppdaterad", "User_uploaded_a_file_on_channel": "{{username}} laddade upp en fil på {{channel}}", "User_uploaded_a_file_to_you": "{{username}} skickade dig en fil", + "User_uploaded_files_on_channel": "{{username}} laddade upp {{count}} filer på {{channel}}", + "User_uploaded_files_to_you": "{{username}} skickade dig {{count}} filer", "User_uploaded_file": "Laddade upp en fil", "User_uploaded_image": "Laddade upp en bild", "Username": "Användarnamn", @@ -5432,8 +5793,10 @@ "Utilities": "Verktyg", "Validate_email_address": "Validera e-postadress", "Validation": "Validering", + "Value": "Värde", "Value_messages": "{{value}} meddelanden", "Value_users": "{{value}} användare", + "Values": "Värden", "Verification": "Verifikation", "Verification_Description": "Du kan använda följande platshållare: \n - `[Verification_Url]` för verifieringsadressen. \n - [namn], [fname], [lname] för användarens fullständiga namn, förnamn eller efternamn. \n - `[email]` för användarens e-post. \n - `[Site_Name]` och `[Site_URL]` för respektive programnamn och URL. ", "Verification_Email": "Klicka härför att verifiera din e-postadress.", @@ -5478,6 +5841,7 @@ "Videos": "Videor", "View_All": "Visa alla medlemmar", "View_Logs": "Visa loggar", + "View_rooms": "Visa rum", "View_channels": "Visa kanaler", "View_full_conversation": "Visa hela konversationen", "View_mode": "Visningsläge", @@ -5511,15 +5875,36 @@ "VoIP_TeamCollab_Ice_Gathering_Timeout_Description": "Tid att vänta på att ICE Gathering ska slutföras innan sändning. Låga värden kan förhindra att ICE servrar används, medan höga värden kan försena starten av VoIP-samtal om en ogiltig ICE server anges.", "VoIP_TeamCollab_Ice_Servers": "ICE-servrar", "VoIP_TeamCollab_Ice_Servers_Description": "En lista över ICE servrar (STUN och/eller TURN), åtskilda med kommatecken. \n Användarnamn, lösenord och port tillåts i formatet `användarnamn:lösenord@stun:host:port` eller `användarnamn:lösenord@turn:host:port`. \n Både användarnamn och lösenord kan vara html-kodade.", + "VoIP_TeamCollab_WebRTC": "WebRTC-inställningar", + "VoIP_TeamCollab_SIP_Integration": "SIP-integration", + "VoIP_TeamCollab_SIP_Integration_Enabled": "SIP-integration aktiverad", + "VoIP_TeamCollab_SIP_Integration_For_Internal_Calls": "Dirigera interna samtal genom SIP-integreringen", + "VoIP_TeamCollab_Mobile_Ringing_Enabled": "Mobil ringning", + "VoIP_TeamCollab_Mobile_Ringing_Enabled_Alert": "Den här funktionen är för närvarande i ett experimentellt stadium och stöds kanske inte helt av mobilappen. När den är aktiverad kommer den att skicka ytterligare push-meddelanden till användare.", + "VoIP_TeamCollab_Mobile_Ringing_Enabled_Description": "Tillåt användare att göra och ta emot samtal i mobilappen.", + "VoIP_TeamCollab_Screen_Sharing_Enabled": "Skärmdelning", + "VoIP_TeamCollab_Screen_Sharing_Enabled_Description": "Tillåt användare att dela sin skärm under röstsamtal.", + "VoIP_TeamCollab_Screen_Sharing_Enabled_Alert": "Skärmdelning är för närvarande i beta.", + "VoIP_TeamCollab_Internal_SIP_Beta_Alert": "Routning av interna samtal genom SIP är i beta och rekommenderas inte för produktionsanvändning.", + "VoIP_TeamCollab_Drachtio_Host": "Drachtio Host", + "VoIP_TeamCollab_Drachtio_Port": "Drachtio Port", + "VoIP_TeamCollab_Drachtio_Password": "Drachtio-lösenord", + "VoIP_TeamCollab_SIP_Server_Host": "SIP-servervärd", + "VoIP_TeamCollab_SIP_Server_Port": "SIP-serverport", "VoIP_device_permission_required": "Tillgång till mikrofon/högtalare krävs", "VoIP_device_permission_required_description": "Din webbläsare hindrade {{workspaceUrl}} från att använda mikrofonen och/eller högtalaren.\n\nTillåt högtalar- och mikrofonåtkomst i webbläsarens inställningar för att förhindra att detta meddelande visas igen.", "VoIP_allow_and_call": "Tillåt och ring", "VoIP_allow_and_accept": "Tillåt och acceptera", "VoIP_cancel_and_reject": "Avbryt och avvisa", + "Voice": "Röstsamtal", "Voice_Call": "Röstsamtal", "Voice_Call_Extension": "Röstsamtal anknytning", "Voice_and_omnichannel": "Röst och omnikanal", "Voice_call": "Röstsamtal", + "Voice_call__user_": "Röstsamtal {{user}}", + "Voice_call__user__hangup": "Avsluta samtal med {{user}}", + "Voice_call__user__cancel": "Avbryt samtal med {{user}}", + "Voice_call__user__reject": "Avvisa samtal från {{user}}", "Voice_call_extension": "Anknytning för röstsamtal", "Voice_calling_disabled": "Röstsamtal är inaktiverat", "Voice_calling_enabled": "Röstsamtal är aktiverat", @@ -5585,6 +5970,7 @@ "Without_SLA": "Utan SLA", "Without_priority": "Utan prioritet", "Workspace": "Arbetsyta", + "Workspace_detail": "Arbetsytesdetalj", "Workspace_and_user_preferences": "Arbetsyta och användarinställningar", "Workspace_exceeded_MAC_limit_disclaimer": "Arbetsytan har överskridit den månatliga gränsen för aktiva kontakter. Prata med din administratör för arbetsytan för att åtgärda problemet.", "Workspace_instance": "Instans för arbetsyta", @@ -5602,6 +5988,11 @@ "Wrap_up_conversation": "Avsluta samtalet", "Yes": "Ja", "Yes_archive_it": "Ja, arkivera!", + "Yes_ban_user": "Ja, bannlys användare!", + "Yes_unban_user": "Ja, häv bannlysning för användare!", + "User_is_banned": "Användaren är bannlyst", + "Unban_and_add": "Häv bannlysning och lägg till", + "User_is_banned_from_room_confirm_unban": "Denna användare är bannlyst från detta rum. Vill du häva bannlysningen och lägga till dem igen?", "Yes_clear_all": "Ja, rensa alla!", "Yes_continue": "Ja, fortsätt!", "Yes_deactivate_it": "Ja, inaktivera!", @@ -5614,16 +6005,23 @@ "Yes_remove_user": "Ja, ta bort användare!", "Yes_unarchive_it": "Ja, avarkivera det!", "Yesterday": "Igår", + "Yesterday_at": "Igår på", "You": "Du", "You_and_users_Reacted_with": "Du och {{users}} reagerade med {{emoji}}", "You_are_converting_team_to_channel": "Du konverterar teamet till en Kanal.", "You_are_logged_in_as": "Du är inloggad som", "You_are_not_authorized_to_view_this_page": "Du saknar behörighet för att se denna sida.", + "You_are_not_authorized_to_access_this_feature": "Du är inte auktoriserad att komma åt den här funktionen.", + "You_are_sharing_your_screen": "Du delar din skärm", "You_can_change_a_different_avatar_too": "Du kan åsidosätta avataren som används för att posta från denna integration.", "You_can_close_this_window_now": "Du kan stänga fönstret nu", "You_can_do_from_account_preferences": "Du kan göra detta senare från dina kontoinställningar", "You_can_search_using_RegExp_eg": "Du kan söka med RegExp. t.ex /^text$/i", "You_can_try_to": "Du kan försöka", + "You_cant_upload_more_than__count__files": { + "one": "Du kan inte ladda upp mer än {{count}} fil åt gången.", + "other": "Du kan inte ladda upp mer än {{count}} filer åt gången." + }, "You_can_use_an_emoji_as_avatar": "Du kan också använda en emoji som avatar.", "You_can_use_webhooks_to_easily_integrate_livechat_with_your_CRM": "Du kan använda webhooks för att enkelt integrera Omnichannel med ditt CRM.", "You_cant_leave_a_livechat_room_Please_use_the_close_button": "Du kan inte lämna ett Omnichannel-rum. Vänligen använd stängknappen.", @@ -5697,6 +6095,8 @@ "access-permissions_description": "Ändra behörigheter för olika roller.", "access-setting-permissions": "Ändra inställningsbaserade behörigheter", "access-setting-permissions_description": "Behörighet att ändra inställningsbaserade behörigheter", + "access-federation": "Åtkomstföderation", + "access-federation_description": "Behörighet att komma åt federationsfunktioner, skapa och gå med i federerade rum", "active": "aktiv", "add-all-to-room": "Lägg till alla användare i ett rum", "add-all-to-room_description": "Behörighet att lägga till alla användare i ett rum", @@ -5741,6 +6141,8 @@ "away": "borta", "ban-user": "Banna Användare", "ban-user_description": "Behörighet att banna en användare från en kanal", + "Ban_user_from_room": "Bannlys användare från rum", + "Banned_Users": "Bannlysta användare", "block-ip-device-management": "Blockera hantering av IP-enhet", "block-ip-device-management_description": "Behörighet att blockera en IP-adress", "block-livechat-contact": "Blockera Omnichannel kontaktkanal", @@ -5759,6 +6161,7 @@ "can-audit-log": "Behörighet för granskningslogg", "can-audit-log_description": "Åtkomstbehörighet till granskningslogg", "can-audit_description": "Behörighet att granska", + "Change_E2EE_password": "Ändra E2EE-lösenord", "change-livechat-room-visitor": "Ändringar av besökare i Livechat-rum", "change-livechat-room-visitor_description": "Behörighet att lägga till ytterligare information för besökaren i Livechat-rummet", "changed_room_announcement_to__room_announcement_": "ändrat rumsmeddelande till: {{room_announcement}}", @@ -5868,11 +6271,17 @@ "email_style_description": "Undvik kapslade väljare", "email_style_label": "E-postformat", "ensure_email_address_valid": "Ogiltig e-postadress", + "error-abac-not-enabled": "Attributbaserad åtkomstkontroll är inte aktiverad på denna arbetsyta.", + "error-abac-unsupported-object-type": "Attributbaserad åtkomstkontroll stöder inte denna objekttyp.", + "error-abac-unsupported-operation": "Denna operation stöds inte av attributbaserad åtkomstkontroll.", "error-action-not-allowed": "{{action}} är inte tillåtet", "error-agent-offline": "Agenten är offline", "error-agent-status-service-offline": "Agentens status är Offline eller så är Omnichannel-tjänsten inte aktiv", "error-application-not-found": "Applikation kunde inte hittas", "error-archived-duplicate-name": "Det finns en arkiverad kanal med namnet \"{{room_name}}\"", + "error-attribute-definition-not-found": "Attributdefinitionen kunde inte hittas.", + "error-attribute-in-use": "Detta attribut är för närvarande tilldelat ett eller flera rum och kan inte tas bort.", + "error-attribute-not-found": "Attributet kunde inte hittas.", "error-avatar-invalid-url": "Ogiltig avatar-URL: {{url}}", "error-avatar-url-handling": "Fel vid hantering av avatarinställning från en URL ({{url}}) för {{username}}", "error-blocked-username": "**{{field}}** är låst och kan inte användas.", @@ -5880,6 +6289,7 @@ "error-business-hour-finish-time-equals-start-time": "Start- och sluttid kan inte vara samma", "error-business-hours-are-closed": "Kontorstiden är slut", "error-canned-response-not-found": "Standardsvaret hittades inte", + "error-cannot-convert-default-room-to-abac": "Standard- och teamstandardrum kan inte konverteras till attributbaserade åtkomstkontrollerade rum.", "error-cannot-delete-app-user": "Det är inte tillåtet att ta bort appanvändaren. Avinstallera den motsvarande appen om du vill ta bort användaren.", "error-cannot-place-chat-on-hold": "Du kan inte sätta chatten i vänteläge", "error-cant-add-federated-users": "Kan inte lägga till samordnade användare i ett icke federerat rum", @@ -5901,6 +6311,7 @@ "error-department-removal-disabled": "Borttagning av avdelning är inaktiverad av administratören. Vänligen kontakta din administratör", "error-direct-message-file-upload-not-allowed": "Fildelning får inte användas i direktmeddelanden", "error-direct-message-max-user-exceeded": "Du kan inte lägga till fler än {{maxUsers}} användare, inklusive dig själv, i ett direktmeddelande", + "error-duplicate-attribute-key": "Ett attribut med denna nyckel finns redan på detta rum.", "error-duplicate-channel-name": "Det finns redan en kanal med namnet {{channel_name}}", "error-duplicate-priority-name": "Det finns redan en prioritet med samma namn", "error-duplicated-sla": "Ett SLA med samma namn eller förfallodag finns redan", @@ -5910,6 +6321,8 @@ "error-email-inbox-not-found": "Inkorgen för e-post hittades inte", "error-email-send-failed": "Fel vid skicka e-post: {{message}}", "error-essential-app-disabled": "Fel: en Rocket.Chat-app som krävs för det här är inaktiverad. Kontakta administratören", + "error-extension-not-assigned": "Tillägg inte tilldelat", + "error-extension-not-available": "Tillägg inte tillgängligt", "error-failed-to-delete-department": "Misslyckades med att ta bort avdelningen", "error-field-unavailable": "{{field}} används redan :(", "error-file-too-large": "Filen är för stor", @@ -5928,6 +6341,8 @@ "error-invalid-actionlink": "Ogiltig åtgärdslänk", "error-invalid-arguments": "Ogiltiga argument", "error-invalid-asset": "Ogiltig tillgång", + "error-invalid-attribute-key": "Den angivna attributnyckeln är ogiltig.", + "error-invalid-attribute-values": "Ett eller flera av de angivna attributvärdena är ogiltiga.", "error-invalid-channel": "Ogiltig kanal.", "error-invalid-channel-start-with-chars": "Ogiltig kanal. Börja med @ eller #", "error-invalid-contact": "Ogiltig kontakt.", @@ -5971,6 +6386,7 @@ "error-invalid-user": "Ogiltig användare", "error-invalid-username": "Ogiltigt användarnamn", "error-invalid-value": "Ogiltigt värde", + "error-removing-tag": "Fel vid borttagning av tag", "error-invalid-webhook-response": "Webhook-URL svarade med en annan status än 200", "error-license-user-limit-reached": "Det högsta antalet användare har uppnåtts.", "error-loading-extension-list": "Misslyckades med att ladda tilläggslistan", @@ -5991,7 +6407,9 @@ "error-no-tokens-for-this-user": "Det finns inga tokens för denna användare", "error-not-allowed": "Inte tillåtet", "error-not-authorized": "Ej tillåtet", + "error-not-authorized-federation": "Inte auktoriserad att komma åt federation", "error-office-hours-are-closed": "Kontoret är stängt.", + "error-only-compliant-users-can-be-added-to-abac-rooms": "Endast kompatibla användare kan läggas till i ABAC-rum.", "error-password-in-history": "Det angivna lösenordet har använts tidigare", "error-password-policy-not-met": "Lösenordet uppfyller inte serverns policy", "error-password-policy-not-met-maxLength": "Lösenordet uppfyller inte serverns policy med maximal längd (lösenord för långt)", @@ -6002,6 +6420,7 @@ "error-password-policy-not-met-oneUppercase": "Lösenordet uppfyller inte serverns policy med minst en stor bokstav", "error-password-policy-not-met-repeatingCharacters": "Lösenordet uppfyller inte serverns policy om förbjudna upprepade tecken (du har för många av samma tecken bredvid varandra)", "error-password-same-as-current": "Det angivna lösenordet är detsamma som det aktuella lösenordet", + "error-pdp-unavailable": "Tjänsten för attributbaserad åtkomstkontrollpolicy är för närvarande otillgänglig. Försök igen senare.", "error-personal-access-tokens-are-current-disabled": "Personliga åtkomsttoken är inaktiverade för närvarande", "error-pinning-message": "Det gick inte att fästa meddelandet", "error-push-disabled": "Push är inaktiverat", @@ -6016,8 +6435,11 @@ "error-room-does-not-exist": "Rummet finns inte", "error-room-is-already-on-hold": "Fel! Rum är redan i vänteläge", "error-room-is-not-closed": "Room är inte stängt", + "error-room-not-found": "Det begärda rummet kunde inte hittas.", "error-room-not-on-hold": "Fel! Rum är inte i vänteläge", "error-room-onHold": "Fel! Rummet är parkerat", + "error-room-is-abac-managed": "Detta rum hanteras av ABAC och nya användare kan inte läggas till", + "error-adding-monitor": "Fel vid tillägg av monitor", "error-saving-sla": "Ett fel inträffade när SLA sparades", "error-selected-agent-room-agent-are-same": "Den valda agenten är densamma som rummets agent", "error-starring-message": "Det gick inte att stjärnmarkera meddelandet", @@ -6030,6 +6452,7 @@ "error-token-already-exists": "Det finns redan en token med det namnet", "error-token-does-not-exists": "Token finns inte", "error-too-many-requests": "Fel, alltför många förfrågningar. Snälla sakta ner. Du måste vänta {{seconds}} sekunder innan du försöker igen.", + "error-too-many-files": "Antalet filer bifogade till meddelandet överskrider gränsen.", "error-transcript-already-requested": "Utskrift har redan begärts", "error-unable-to-update-priority": "Det går inte att uppdatera prioriteringen", "error-unknown-contact": "Kontakten är okänd.", @@ -6120,6 +6543,7 @@ "importer_status_preparing_users": "Läser användarfil", "importer_status_uploading": "Laddar upp fil", "importer_status_user_selection": "Nu kan du välja vad som ska importeras", + "Inbound": "Inkommande", "increments-of-two": "steg om två", "initials_avatar": "Initialavatar", "inline_code": "inline-kod", @@ -6137,6 +6561,8 @@ "joined": "anslöt", "kick-user-from-any-c-room": "Sparka användare från alla offentliga Kanaler", "kick-user-from-any-c-room_description": "Tillstånd att sparka ut en användare från en offentlig kanal", + "kick-user-from-any-p-room": "Sparka användare från all privata kanaler", + "kick-user-from-any-p-room_description": "Behörighet att sparka en användare från alla privata kanaler", "leave-c": "Lämna kanaler", "leave-c_description": "Behörighet att lämna kanaler", "leave-p": "Lämna privata grupper", @@ -6231,6 +6657,7 @@ "message_pruned": "meddelande beskuret", "messages": "Meddelanden", "messages_pruned": "meddelanden beskurna", + "Message_preview": "Förhandsgranskning av meddelande", "meteor_status_connected": "Ansluten", "meteor_status_connecting": "Ansluter...", "meteor_status_failed": "Det gick inte att ansluta till servern", @@ -6356,6 +6783,11 @@ "optional": "valfritt", "or": "eller", "others": "andra", + "Outbound": "Utgående", + "Outbound_message_upsell_title": "Ta första steget i konversationen", + "Outbound_message_upsell_description": "Skicka personaliserade utgående meddelanden på WhatsApp och andra kanaler — perfekt för påminnelser, aviseringar och uppföljningar.", + "Outbound_message_upsell_annotation": "Kontakta din arbetsytesadministratör för att aktivera utgående chatt", + "Outbound_message_upsell_alt": "Illustration av en smartphone som tar emot ett nytt meddelandemeddelande.", "outbound.send-messages": "Skicka utgående meddelanden", "outbound.send-messages_description": "Behörighet att skicka utgående meddelanden", "outbound.can-assign-queues": "Kan tilldela avdelningar att ta emot svar på utgående meddelanden", @@ -6388,10 +6820,12 @@ "registration.component.form.createAnAccount": "Skapa ett konto", "registration.component.form.divider": "eller", "registration.component.form.email": "E-post", + "registration.component.form.emailAlreadyInUse": "E-post redan använd", "registration.component.form.emailOrUsername": "E-postadress eller användarnamn", "registration.component.form.emailPlaceholder": "din@epost.com", "registration.component.form.invalidConfirmPass": "Lösenorden matchar inte varandra", "registration.component.form.invalidEmail": "Den angivna epostadressen är ogiltig", + "registration.component.form.invalidEmailDomain": "Den angivna e-posten har en ogiltig e-postdomän", "registration.component.form.joinYourTeam": "Gå med i ditt team", "registration.component.form.name": "Namn", "registration.component.form.nameContainsInvalidChars": "Namnet innehåller ogiltiga tecken", @@ -6404,6 +6838,7 @@ "registration.component.form.submit": "Skicka", "registration.component.form.username": "Användarnamn", "registration.component.form.usernameAlreadyExists": "Användarnamn existerar redan. Vänligen försök med ett annat användarnamn.", + "registration.component.form.usernameAlreadyInUse": "Användarnamn redan använt", "registration.component.form.usernameContainsInvalidChars": "Användarnamnet innehåller ogiltiga tecken", "registration.component.login": "Logga in", "registration.component.login.incorrectPassword": "Felaktigt lösenord", @@ -6467,6 +6902,7 @@ "room_disallowed_reacting": "{{user_by}} har angett att reaktioner inte tillåts i rummet", "room_disallowed_reactions": "tillåter inte reaktioner", "room_is_blocked": "Rummet är blockerat", + "room_is_archived": "Detta rum är arkiverat", "room_is_read_only": "Detta rum går endast att läsa", "room_name": "Rumsnamn", "room_removed_read_only": "{{user_by}} lade till skrivbehörighet för rummet", @@ -6750,6 +7186,10 @@ "one": "{{count}} fil gallrad", "other": "{{count}} filer gallrade" }, + "__count__files_failed_to_upload": { + "one": "{{count}} fil misslyckades att ladda upp och kommer inte att skickas: {{name}}", + "other": "{{count}} filer misslyckades att ladda upp och kommer inte att skickas." + }, "__count__follower": { "one": "+{{count}} följare", "other": "+{{count}} följare" @@ -6761,6 +7201,10 @@ "__count__messages_selected": "{{count}} valda meddelanden", "__count__replies": "{{count}} svar", "__count__replies__date__": "{{count}} svar, {{date}}", + "__count__result_found": { + "one": "{{count}} resultat hittades", + "other": "{{count}} resultat hittades" + }, "__count__tags__and__count__conversations__period__": "{{count}} taggar och {{conversations}} konversationer, {{period}}", "__count__without__assignee__": "{{count}} utan rättsinnehavare", "__count__without__department__": "{{count}} utan avdelning", @@ -6771,10 +7215,42 @@ "__roomName__was_added_to_favorites": "{{roomName}} lades till i favoriter", "__roomName__was_removed_from_favorites": "{{roomName}} togs bort från favoriter", "__unreadTitle__from__roomTitle__": "{{unreadTitle}} från {{roomTitle}}", + "Insert_timestamp": "Infoga tidsstämpel", + "Insert": "Infoga", "__username__is_no_longer__role__defined_by__user_by_": "{{username}} är inte längre {{role}}, av {{user_by}}", "__username__was_set__role__by__user_by_": "{{username}} sattes {{role}} av {{user_by}}", "__usernames__and__count__more_joined": "{{usernames}} och {{count}} fler tillkom", "__usernames__joined": "{{usernames}} anslöt", "__usersCount__joined": "{{count}} anslöt", - "__usersCount__people_will_be_invited": "{{usersCount}} personer bjuds in" + "__usersCount__people_will_be_invited": "{{usersCount}} personer bjuds in", + "You_cannot_add_external_users_to_non_federated_room": "Du kan inte lägga till externa användare till ett icke-federerat rum", + "UNABLE_TO_VERIFY": "Kunde inte verifiera användare", + "Users_invited": "Användarna har blivit inbjudna", + "timestamps.shortTime": "Kort tid", + "timestamps.longTime": "Långt tid", + "timestamps.shortDate": "Kortdatum", + "timestamps.longDate": "Kortdatum och tid", + "timestamps.fullDateTime": "Fullständigt datum och kort tid", + "timestamps.fullDateTimeLong": "Fullständigt datum och långt tid", + "timestamps.relativeTime": "Relativ", + "timestamps.shortTimeDescription": "12:00", + "timestamps.longTimeDescription": "12:00:00", + "timestamps.shortDateDescription": "31/12/2020", + "timestamps.longDateDescription": "31/12/2020, 12:00", + "timestamps.fullDateTimeDescription": "Torsdag, 31 december 2020 12:00", + "timestamps.fullDateTimeLongDescription": "Torsdag, 31 december 2020 12:00:00", + "__username__profile_picture": "{{username}}s profilbild", + "User_card": "Användarkort", + "timestamps.relativeTimeDescription": "För 1 år sedan", + "Message_composer": "Meddelandekompilatör", + "Thread_composer": "Trådkompilatör", + "Room_composer": "Rumskompilatör", + "Date_range_presets": "Förinställda datumintervall", + "message_body": "meddelandetext", + "message_attachment": "meddelandebilaga", + "system_message_body": "systemmeddelande-text", + "No_changes_to_save": "Inga ändringar att spara", + "Avatar_preview_updated": "Förhandsvisning av avatar uppdaterad", + "Select_message_from_user": "Välj meddelande från {{username}}", + "Select_message_from_user_with_preview": "Välj meddelande från {{username}}: {{message}}" } \ No newline at end of file diff --git a/packages/instance-status/CHANGELOG.md b/packages/instance-status/CHANGELOG.md index 2620f424b1313..34b147283d04e 100644 --- a/packages/instance-status/CHANGELOG.md +++ b/packages/instance-status/CHANGELOG.md @@ -1,5 +1,23 @@ # @rocket.chat/instance-status +## 0.1.57 + +### Patch Changes + +-
    Updated dependencies [f7d47dd3517ec14ca2ec5c3c95fcdf9e1e2fb8b0, b6b04aadfcc8558f888b334e37c46a77e5816237, 4704bf81ca370f120af32185a7c55407a26f8514, 12897e25d0dc25b7373f5264d38f38a5a7444257, e45585b70a3a7b75434c88e4b2ea9af0a0764a76]: + + - @rocket.chat/models@2.3.0 +
    + +## 0.1.57-rc.0 + +### Patch Changes + +-
    Updated dependencies [f7d47dd3517ec14ca2ec5c3c95fcdf9e1e2fb8b0, ae9f740d6af20557eac61b4af902c868b4132b49, b6b04aadfcc8558f888b334e37c46a77e5816237, 4704bf81ca370f120af32185a7c55407a26f8514, 12897e25d0dc25b7373f5264d38f38a5a7444257, e45585b70a3a7b75434c88e4b2ea9af0a0764a76]: + + - @rocket.chat/models@2.3.0-rc.0 +
    + ## 0.1.56 ### Patch Changes diff --git a/packages/instance-status/package.json b/packages/instance-status/package.json index 8449b3afe7d60..9c4ed33f4bce6 100644 --- a/packages/instance-status/package.json +++ b/packages/instance-status/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/instance-status", - "version": "0.1.56", + "version": "0.1.57", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/livechat/CHANGELOG.md b/packages/livechat/CHANGELOG.md index 7ad06356efd4a..ecd34c4107d96 100644 --- a/packages/livechat/CHANGELOG.md +++ b/packages/livechat/CHANGELOG.md @@ -1,5 +1,25 @@ # @rocket.chat/livechat Change Log +## 2.1.4 + +### Patch Changes + +-
    Updated dependencies [90f15e32ae843ed146ccf711ee3201408d1e8731, d427b808c1f79d9d1baa05bb5b5ef805b6ef5f6d, 0b7a76367d650793c271160e01798ebbb5fe0d26, 90f15e32ae843ed146ccf711ee3201408d1e8731]: + + - @rocket.chat/ui-kit@1.1.0 + - @rocket.chat/gazzodown@31.0.0 +
    + +## 2.1.4-rc.0 + +### Patch Changes + +-
    Updated dependencies [90f15e32ae843ed146ccf711ee3201408d1e8731, d427b808c1f79d9d1baa05bb5b5ef805b6ef5f6d, 0b7a76367d650793c271160e01798ebbb5fe0d26, 90f15e32ae843ed146ccf711ee3201408d1e8731]: + + - @rocket.chat/ui-kit@1.1.0-rc.0 + - @rocket.chat/gazzodown@31.0.0-rc.0 +
    + ## 2.1.3 ### Patch Changes diff --git a/packages/livechat/package.json b/packages/livechat/package.json index 4e9b1a6cdd8e9..d26898e33b0a9 100644 --- a/packages/livechat/package.json +++ b/packages/livechat/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/livechat", - "version": "2.1.3", + "version": "2.1.4", "homepage": "https://rocket.chat", "repository": { "type": "git", diff --git a/packages/mock-providers/CHANGELOG.md b/packages/mock-providers/CHANGELOG.md index 4372ce78e65d5..0cb12e403acfb 100644 --- a/packages/mock-providers/CHANGELOG.md +++ b/packages/mock-providers/CHANGELOG.md @@ -1,5 +1,25 @@ # @rocket.chat/mock-providers +## 0.4.17 + +### Patch Changes + +-
    Updated dependencies [cdb264fec803e234a6ad2000018b31d4b2074e99, ad7d42400ea36f1eb0aaf7cc3361c77fdabf9ebc, 4704bf81ca370f120af32185a7c55407a26f8514, d427b808c1f79d9d1baa05bb5b5ef805b6ef5f6d, ebc9babf55dd26613027c28dcacf77909116b342, fac64728505b312d5da786e92d3134450ce4a7c1, 12897e25d0dc25b7373f5264d38f38a5a7444257]: + + - @rocket.chat/i18n@3.1.0 + - @rocket.chat/ui-contexts@31.0.0 +
    + +## 0.4.17-rc.0 + +### Patch Changes + +-
    Updated dependencies [cdb264fec803e234a6ad2000018b31d4b2074e99, ae9f740d6af20557eac61b4af902c868b4132b49, ad7d42400ea36f1eb0aaf7cc3361c77fdabf9ebc, 4704bf81ca370f120af32185a7c55407a26f8514, d427b808c1f79d9d1baa05bb5b5ef805b6ef5f6d, ebc9babf55dd26613027c28dcacf77909116b342, fac64728505b312d5da786e92d3134450ce4a7c1, 12897e25d0dc25b7373f5264d38f38a5a7444257]: + + - @rocket.chat/i18n@3.1.0-rc.0 + - @rocket.chat/ui-contexts@31.0.0-rc.0 +
    + ## 0.4.16 ### Patch Changes diff --git a/packages/mock-providers/package.json b/packages/mock-providers/package.json index 2dca880571aca..7b576204bb875 100644 --- a/packages/mock-providers/package.json +++ b/packages/mock-providers/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/mock-providers", - "version": "0.4.16", + "version": "0.4.17", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/model-typings/CHANGELOG.md b/packages/model-typings/CHANGELOG.md index 100268a12368b..3cd580ff2b899 100644 --- a/packages/model-typings/CHANGELOG.md +++ b/packages/model-typings/CHANGELOG.md @@ -1,5 +1,82 @@ # @rocket.chat/model-typings +## 2.3.0 + +### Minor Changes + +- ([#39617](https://github.com/RocketChat/Rocket.Chat/pull/39617)) Adds new API endpoints `custom-sounds.create` and `custom-sounds.update` to manage custom sounds with strict file validation for size and specific MIME types to ensure system compatibility. + +### Patch Changes + +- ([#40524](https://github.com/RocketChat/Rocket.Chat/pull/40524)) Ensures OAuth tokens are cleaned up after user deactivation + +- ([#40496](https://github.com/RocketChat/Rocket.Chat/pull/40496)) Ensures that deactivated users have their login tokens cleaned up in users.deactivateidle + +- ([#40405](https://github.com/RocketChat/Rocket.Chat/pull/40405)) Security Hotfix (https://docs.rocket.chat/docs/security-fixes-and-updates) + +-
    Updated dependencies [12897e25d0dc25b7373f5264d38f38a5a7444257]: + + - @rocket.chat/core-typings@8.5.0 +
    + +## 2.3.0-rc.0 + +### Minor Changes + +- ([#39760](https://github.com/RocketChat/Rocket.Chat/pull/39760)) ## Phishing-Resistant Multi-Factor Authentication + + Introduces a more secure and reliable server-side OAuth authentication flow. + + ### What’s New + + - **Improved OAuth login security** + OAuth authentication now happens fully on the server, reducing the risk of token theft, phishing attacks, and client-side credential interception. + - **Built-in CSRF, state validation, and PKCE protection** + OAuth logins now include stronger protection against CSRF attacks, request tampering, and authorization code interception through secure state validation and PKCE support. + - **Improved two-step verification with OAuth logins** + Users with email or TOTP two-factor authentication enabled will now be asked to complete 2FA even when signing in with providers like Google, GitHub, GitLab, and others. + - **Improved mobile & desktop app login** + Mobile and desktop apps now support a smoother and more secure deep-link OAuth login flow. + +- ([#39617](https://github.com/RocketChat/Rocket.Chat/pull/39617)) Adds new API endpoints `custom-sounds.create` and `custom-sounds.update` to manage custom sounds with strict file validation for size and specific MIME types to ensure system compatibility. + +### Patch Changes + +- ([#40524](https://github.com/RocketChat/Rocket.Chat/pull/40524)) Ensures OAuth tokens are cleaned up after user deactivation + +- ([#40496](https://github.com/RocketChat/Rocket.Chat/pull/40496)) Ensures that deactivated users have their login tokens cleaned up in users.deactivateidle + +- ([#40405](https://github.com/RocketChat/Rocket.Chat/pull/40405)) Security Hotfix (https://docs.rocket.chat/docs/security-fixes-and-updates) + +-
    Updated dependencies [ae9f740d6af20557eac61b4af902c868b4132b49, 12897e25d0dc25b7373f5264d38f38a5a7444257]: + + - @rocket.chat/core-typings@8.5.0-rc.0 +
    + +## 2.2.2 + +### Patch Changes + +- ([#40627](https://github.com/RocketChat/Rocket.Chat/pull/40627) by [@dionisio-bot](https://github.com/dionisio-bot)) Ensures OAuth tokens are cleaned up after user deactivation + +- ([#40559](https://github.com/RocketChat/Rocket.Chat/pull/40559) by [@dionisio-bot](https://github.com/dionisio-bot)) Ensures that deactivated users have their login tokens cleaned up in users.deactivateidle + +-
    Updated dependencies []: + + - @rocket.chat/core-typings@8.4.2 +
    + +## 2.2.1 + +### Patch Changes + +- ([#40410](https://github.com/RocketChat/Rocket.Chat/pull/40410) by [@dionisio-bot](https://github.com/dionisio-bot)) Security Hotfix (https://docs.rocket.chat/docs/security-fixes-and-updates) + +-
    Updated dependencies [5b291c38600757482aaf261a02487abdf5f14007]: + + - @rocket.chat/core-typings@8.4.1 +
    + ## 2.2.0 ### Minor Changes diff --git a/packages/model-typings/package.json b/packages/model-typings/package.json index 5b8b5d090a9e7..c3d4299461b2c 100644 --- a/packages/model-typings/package.json +++ b/packages/model-typings/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/model-typings", - "version": "2.2.0", + "version": "2.3.0", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/models/CHANGELOG.md b/packages/models/CHANGELOG.md index c3a206df002c5..d93e7740ac5b4 100644 --- a/packages/models/CHANGELOG.md +++ b/packages/models/CHANGELOG.md @@ -1,5 +1,98 @@ # @rocket.chat/models +## 2.3.0 + +### Minor Changes + +- ([#39617](https://github.com/RocketChat/Rocket.Chat/pull/39617)) Adds new API endpoints `custom-sounds.create` and `custom-sounds.update` to manage custom sounds with strict file validation for size and specific MIME types to ensure system compatibility. + +- ([#40397](https://github.com/RocketChat/Rocket.Chat/pull/40397)) Adds the `USE_ROOM_SEARCH_INDEX` environment variable. When set to `true`, the messages collection's text index is created as `{ rid: 1, msg: 'text' }` instead of the default `{ msg: 'text' }`. The compound shape lets per-room `$text` searches use `rid` as a prefix, dramatically reducing the portion of the index scanned on workspaces where global search is disabled. + + The index is reconciled on every startup: if the existing text index already matches the desired shape, nothing happens; otherwise the stale text index is dropped and the desired one is recreated. Unsetting the variable on a later boot reverts to the default shape. + +### Patch Changes + +- ([#40524](https://github.com/RocketChat/Rocket.Chat/pull/40524)) Ensures OAuth tokens are cleaned up after user deactivation + +- ([#40496](https://github.com/RocketChat/Rocket.Chat/pull/40496)) Ensures that deactivated users have their login tokens cleaned up in users.deactivateidle + +- ([#40405](https://github.com/RocketChat/Rocket.Chat/pull/40405)) Security Hotfix (https://docs.rocket.chat/docs/security-fixes-and-updates) + +-
    Updated dependencies [f7d47dd3517ec14ca2ec5c3c95fcdf9e1e2fb8b0, 4c3984593017d59edd631bf8ae4f35f9d3c3db36, b6b04aadfcc8558f888b334e37c46a77e5816237, 4704bf81ca370f120af32185a7c55407a26f8514, 12897e25d0dc25b7373f5264d38f38a5a7444257, b1c2668b74bfb49ebaefe2f581b2f8be5d4d1dd6]: + + - @rocket.chat/model-typings@2.3.0 + - @rocket.chat/rest-typings@8.5.0 + - @rocket.chat/core-typings@8.5.0 +
    + +## 2.3.0-rc.0 + +### Minor Changes + +- ([#39760](https://github.com/RocketChat/Rocket.Chat/pull/39760)) ## Phishing-Resistant Multi-Factor Authentication + + Introduces a more secure and reliable server-side OAuth authentication flow. + + ### What’s New + + - **Improved OAuth login security** + OAuth authentication now happens fully on the server, reducing the risk of token theft, phishing attacks, and client-side credential interception. + - **Built-in CSRF, state validation, and PKCE protection** + OAuth logins now include stronger protection against CSRF attacks, request tampering, and authorization code interception through secure state validation and PKCE support. + - **Improved two-step verification with OAuth logins** + Users with email or TOTP two-factor authentication enabled will now be asked to complete 2FA even when signing in with providers like Google, GitHub, GitLab, and others. + - **Improved mobile & desktop app login** + Mobile and desktop apps now support a smoother and more secure deep-link OAuth login flow. + +- ([#39617](https://github.com/RocketChat/Rocket.Chat/pull/39617)) Adds new API endpoints `custom-sounds.create` and `custom-sounds.update` to manage custom sounds with strict file validation for size and specific MIME types to ensure system compatibility. + +- ([#40397](https://github.com/RocketChat/Rocket.Chat/pull/40397)) Adds the `USE_ROOM_SEARCH_INDEX` environment variable. When set to `true`, the messages collection's text index is created as `{ rid: 1, msg: 'text' }` instead of the default `{ msg: 'text' }`. The compound shape lets per-room `$text` searches use `rid` as a prefix, dramatically reducing the portion of the index scanned on workspaces where global search is disabled. + + The index is reconciled on every startup: if the existing text index already matches the desired shape, nothing happens; otherwise the stale text index is dropped and the desired one is recreated. Unsetting the variable on a later boot reverts to the default shape. + +### Patch Changes + +- ([#40524](https://github.com/RocketChat/Rocket.Chat/pull/40524)) Ensures OAuth tokens are cleaned up after user deactivation + +- ([#40496](https://github.com/RocketChat/Rocket.Chat/pull/40496)) Ensures that deactivated users have their login tokens cleaned up in users.deactivateidle + +- ([#40405](https://github.com/RocketChat/Rocket.Chat/pull/40405)) Security Hotfix (https://docs.rocket.chat/docs/security-fixes-and-updates) + +-
    Updated dependencies [f7d47dd3517ec14ca2ec5c3c95fcdf9e1e2fb8b0, 4c3984593017d59edd631bf8ae4f35f9d3c3db36, ae9f740d6af20557eac61b4af902c868b4132b49, b6b04aadfcc8558f888b334e37c46a77e5816237, 4704bf81ca370f120af32185a7c55407a26f8514, 12897e25d0dc25b7373f5264d38f38a5a7444257, b1c2668b74bfb49ebaefe2f581b2f8be5d4d1dd6]: + + - @rocket.chat/model-typings@2.3.0-rc.0 + - @rocket.chat/rest-typings@8.5.0-rc.0 + - @rocket.chat/core-typings@8.5.0-rc.0 + +## 2.2.2 + +### Patch Changes + +- ([#40627](https://github.com/RocketChat/Rocket.Chat/pull/40627) by [@dionisio-bot](https://github.com/dionisio-bot)) Ensures OAuth tokens are cleaned up after user deactivation + +- ([#40559](https://github.com/RocketChat/Rocket.Chat/pull/40559) by [@dionisio-bot](https://github.com/dionisio-bot)) Ensures that deactivated users have their login tokens cleaned up in users.deactivateidle + +-
    Updated dependencies [b0c593db9bc0bbbb603e673ddcdc48aad4f4e721, f422eb613d8cae43dc1e44d71b6ecb5a0a9c5d92, 3a3f0e1103bd0b8aaf93c16300ed664aed7a67a1]: + + - @rocket.chat/model-typings@2.2.2 + - @rocket.chat/rest-typings@8.4.2 + - @rocket.chat/core-typings@8.4.2 +
    +
    + +## 2.2.1 + +### Patch Changes + +- ([#40410](https://github.com/RocketChat/Rocket.Chat/pull/40410) by [@dionisio-bot](https://github.com/dionisio-bot)) Security Hotfix (https://docs.rocket.chat/docs/security-fixes-and-updates) + +-
    Updated dependencies [5b291c38600757482aaf261a02487abdf5f14007]: + + - @rocket.chat/model-typings@2.2.1 + - @rocket.chat/core-typings@8.4.1 + - @rocket.chat/rest-typings@8.4.1 +
    + ## 2.2.0 ### Minor Changes diff --git a/packages/models/package.json b/packages/models/package.json index 0fc632cdcf821..b322fe0813811 100644 --- a/packages/models/package.json +++ b/packages/models/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/models", - "version": "2.2.0", + "version": "2.3.0", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/omni-core/CHANGELOG.md b/packages/omni-core/CHANGELOG.md index cc30f605ce639..cd74d6f3a8352 100644 --- a/packages/omni-core/CHANGELOG.md +++ b/packages/omni-core/CHANGELOG.md @@ -1,5 +1,23 @@ # @rocket.chat/omni-core +## 0.1.1 + +### Patch Changes + +-
    Updated dependencies [f7d47dd3517ec14ca2ec5c3c95fcdf9e1e2fb8b0, b6b04aadfcc8558f888b334e37c46a77e5816237, 4704bf81ca370f120af32185a7c55407a26f8514, 12897e25d0dc25b7373f5264d38f38a5a7444257, e45585b70a3a7b75434c88e4b2ea9af0a0764a76]: + + - @rocket.chat/models@2.3.0 +
    + +## 0.1.1-rc.0 + +### Patch Changes + +-
    Updated dependencies [f7d47dd3517ec14ca2ec5c3c95fcdf9e1e2fb8b0, ae9f740d6af20557eac61b4af902c868b4132b49, b6b04aadfcc8558f888b334e37c46a77e5816237, 4704bf81ca370f120af32185a7c55407a26f8514, 12897e25d0dc25b7373f5264d38f38a5a7444257, e45585b70a3a7b75434c88e4b2ea9af0a0764a76]: + + - @rocket.chat/models@2.3.0-rc.0 +
    + ## 0.1.0 ### Minor Changes diff --git a/packages/omni-core/package.json b/packages/omni-core/package.json index 8f86eb1eb6880..e2df96d1bfe74 100644 --- a/packages/omni-core/package.json +++ b/packages/omni-core/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/omni-core", - "version": "0.1.0", + "version": "0.1.1", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/rest-typings/CHANGELOG.md b/packages/rest-typings/CHANGELOG.md index 044533574a007..891a03707870f 100644 --- a/packages/rest-typings/CHANGELOG.md +++ b/packages/rest-typings/CHANGELOG.md @@ -1,5 +1,138 @@ # @rocket.chat/rest-typings +## 8.5.0 + +### Minor Changes + +- ([#39617](https://github.com/RocketChat/Rocket.Chat/pull/39617)) Adds new API endpoints `custom-sounds.create` and `custom-sounds.update` to manage custom sounds with strict file validation for size and specific MIME types to ensure system compatibility. + +- ([#40612](https://github.com/RocketChat/Rocket.Chat/pull/40612)) Adds `freeSwitchExtension` as a query parameter for `api/v1/users.info` + +### Patch Changes + +- ([#40513](https://github.com/RocketChat/Rocket.Chat/pull/40513)) Fixes the `users.presence` endpoint returning an empty array when called with multiple comma-separated IDs, caused by `ajvQuery` coercing the string into a single-element array after the OpenAPI migration + +-
    Updated dependencies [90f15e32ae843ed146ccf711ee3201408d1e8731, 12897e25d0dc25b7373f5264d38f38a5a7444257, 90f15e32ae843ed146ccf711ee3201408d1e8731]: + + - @rocket.chat/ui-kit@1.1.0 + - @rocket.chat/core-typings@8.5.0 +
    + +## 8.5.0-rc.6 + +### Patch Changes + +-
    Updated dependencies []: + + - @rocket.chat/core-typings@8.5.0-rc.6 +
    + +## 8.5.0-rc.5 + +### Patch Changes + +-
    Updated dependencies []: + + - @rocket.chat/core-typings@8.5.0-rc.5 +
    + +## 8.5.0-rc.4 + +### Patch Changes + +-
    Updated dependencies []: +- @rocket.chat/core-typings@8.5.0-rc.4 +
    + +## 8.5.0-rc.3 + +### Patch Changes + +-
    Updated dependencies []: + + - @rocket.chat/core-typings@8.5.0-rc.3 +
    + +## 8.5.0-rc.2 + +### Patch Changes + +-
    Updated dependencies []: + + - @rocket.chat/core-typings@8.5.0-rc.2 +
    + +## 8.5.0-rc.1 + +### Patch Changes + +-
    Updated dependencies []: + + - @rocket.chat/core-typings@8.5.0-rc.1 +
    + +## 8.5.0-rc.0 + +### Minor Changes + +- ([#39760](https://github.com/RocketChat/Rocket.Chat/pull/39760)) ## Phishing-Resistant Multi-Factor Authentication + + Introduces a more secure and reliable server-side OAuth authentication flow. + + ### What’s New + + - **Improved OAuth login security** + OAuth authentication now happens fully on the server, reducing the risk of token theft, phishing attacks, and client-side credential interception. + - **Built-in CSRF, state validation, and PKCE protection** + OAuth logins now include stronger protection against CSRF attacks, request tampering, and authorization code interception through secure state validation and PKCE support. + - **Improved two-step verification with OAuth logins** + Users with email or TOTP two-factor authentication enabled will now be asked to complete 2FA even when signing in with providers like Google, GitHub, GitLab, and others. + - **Improved mobile & desktop app login** + Mobile and desktop apps now support a smoother and more secure deep-link OAuth login flow. + +- ([#39617](https://github.com/RocketChat/Rocket.Chat/pull/39617)) Adds new API endpoints `custom-sounds.create` and `custom-sounds.update` to manage custom sounds with strict file validation for size and specific MIME types to ensure system compatibility. + +- ([#40612](https://github.com/RocketChat/Rocket.Chat/pull/40612)) Adds `freeSwitchExtension` as a query parameter for `api/v1/users.info` + +### Patch Changes + +- ([#40513](https://github.com/RocketChat/Rocket.Chat/pull/40513)) Fixes the `users.presence` endpoint returning an empty array when called with multiple comma-separated IDs, caused by `ajvQuery` coercing the string into a single-element array after the OpenAPI migration + +-
    Updated dependencies [90f15e32ae843ed146ccf711ee3201408d1e8731, ae9f740d6af20557eac61b4af902c868b4132b49, 12897e25d0dc25b7373f5264d38f38a5a7444257, 90f15e32ae843ed146ccf711ee3201408d1e8731]: + + - @rocket.chat/ui-kit@1.1.0-rc.0 + - @rocket.chat/core-typings@8.5.0-rc.0 +
    + +## 8.4.3 + +### Patch Changes + +-
    Updated dependencies []: + + - @rocket.chat/core-typings@8.4.3 +
    + +## 8.4.2 + +### Patch Changes + +- ([#40527](https://github.com/RocketChat/Rocket.Chat/pull/40527) by [@dionisio-bot](https://github.com/dionisio-bot)) Fixes the `users.presence` endpoint returning an empty array when called with multiple comma-separated IDs, caused by `ajvQuery` coercing the string into a single-element array after the OpenAPI migration + +-
    Updated dependencies []: + + - @rocket.chat/core-typings@8.4.2 +
    + +## 8.4.1 + +### Patch Changes + +-
    Updated dependencies [5b291c38600757482aaf261a02487abdf5f14007]: + + - @rocket.chat/core-typings@8.4.1 +
    + ## 8.4.0 ### Minor Changes diff --git a/packages/server-fetch/CHANGELOG.md b/packages/server-fetch/CHANGELOG.md index 2901e435392fd..9fc8dfa5d989f 100644 --- a/packages/server-fetch/CHANGELOG.md +++ b/packages/server-fetch/CHANGELOG.md @@ -1,5 +1,23 @@ # @rocket.chat/server-fetch +## 0.2.1 + +### Patch Changes + +-
    Updated dependencies [f7d47dd3517ec14ca2ec5c3c95fcdf9e1e2fb8b0, b6b04aadfcc8558f888b334e37c46a77e5816237, 4704bf81ca370f120af32185a7c55407a26f8514, 12897e25d0dc25b7373f5264d38f38a5a7444257, e45585b70a3a7b75434c88e4b2ea9af0a0764a76]: + + - @rocket.chat/models@2.3.0 +
    + +## 0.2.1-rc.0 + +### Patch Changes + +-
    Updated dependencies [f7d47dd3517ec14ca2ec5c3c95fcdf9e1e2fb8b0, ae9f740d6af20557eac61b4af902c868b4132b49, b6b04aadfcc8558f888b334e37c46a77e5816237, 4704bf81ca370f120af32185a7c55407a26f8514, 12897e25d0dc25b7373f5264d38f38a5a7444257, e45585b70a3a7b75434c88e4b2ea9af0a0764a76]: + + - @rocket.chat/models@2.3.0-rc.0 +
    + ## 0.2.0 ### Minor Changes diff --git a/packages/server-fetch/package.json b/packages/server-fetch/package.json index f2501c22f7b8a..bacd8e9ed0d42 100644 --- a/packages/server-fetch/package.json +++ b/packages/server-fetch/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/server-fetch", - "version": "0.2.0", + "version": "0.2.1", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/ui-avatar/CHANGELOG.md b/packages/ui-avatar/CHANGELOG.md index 0458ea5c10320..9ac35f7f93968 100644 --- a/packages/ui-avatar/CHANGELOG.md +++ b/packages/ui-avatar/CHANGELOG.md @@ -1,5 +1,23 @@ # @rocket.chat/ui-avatar +## 27.0.0 + +### Patch Changes + +-
    Updated dependencies []: + + - @rocket.chat/ui-contexts@31.0.0 +
    + +## 27.0.0-rc.0 + +### Patch Changes + +-
    Updated dependencies []: + + - @rocket.chat/ui-contexts@31.0.0-rc.0 +
    + ## 26.0.0 ### Patch Changes diff --git a/packages/ui-avatar/package.json b/packages/ui-avatar/package.json index f51bebce21e6f..028f22090c1ef 100644 --- a/packages/ui-avatar/package.json +++ b/packages/ui-avatar/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/ui-avatar", - "version": "26.0.0", + "version": "27.0.0", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/ui-client/CHANGELOG.md b/packages/ui-client/CHANGELOG.md index 0781611248d39..523309784cd86 100644 --- a/packages/ui-client/CHANGELOG.md +++ b/packages/ui-client/CHANGELOG.md @@ -1,5 +1,35 @@ # @rocket.chat/ui-client +## 31.0.0 + +### Minor Changes + +- ([#38225](https://github.com/RocketChat/Rocket.Chat/pull/38225)) Adds a new "Drafts" group to the sidebar, providing quick access to all rooms with unfinished messages. + > This feature is available under the `Drafts in sidebar` feature preview and needs to be enabled in settings to be tested. + +### Patch Changes + +-
    Updated dependencies []: + + - @rocket.chat/ui-avatar@27.0.0 + - @rocket.chat/ui-contexts@31.0.0 +
    + +## 31.0.0-rc.0 + +### Minor Changes + +- ([#38225](https://github.com/RocketChat/Rocket.Chat/pull/38225)) Adds a new "Drafts" group to the sidebar, providing quick access to all rooms with unfinished messages. + > This feature is available under the `Drafts in sidebar` feature preview and needs to be enabled in settings to be tested. + +### Patch Changes + +-
    Updated dependencies []: + + - @rocket.chat/ui-contexts@31.0.0-rc.0 + - @rocket.chat/ui-avatar@27.0.0-rc.0 +
    + ## 30.0.0 ### Minor Changes diff --git a/packages/ui-client/package.json b/packages/ui-client/package.json index 5fa764dbdc268..1b9e32d2de599 100644 --- a/packages/ui-client/package.json +++ b/packages/ui-client/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/ui-client", - "version": "30.0.0", + "version": "31.0.0", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/ui-composer/CHANGELOG.md b/packages/ui-composer/CHANGELOG.md index 58dadd0d5a5b8..42add8768552c 100644 --- a/packages/ui-composer/CHANGELOG.md +++ b/packages/ui-composer/CHANGELOG.md @@ -1,5 +1,23 @@ # @rocket.chat/ui-composer +## 2.0.0 + +### Patch Changes + +-
    Updated dependencies [fac64728505b312d5da786e92d3134450ce4a7c1]: + + - @rocket.chat/ui-client@31.0.0 +
    + +## 2.0.0-rc.0 + +### Patch Changes + +-
    Updated dependencies [fac64728505b312d5da786e92d3134450ce4a7c1]: + + - @rocket.chat/ui-client@31.0.0-rc.0 +
    + ## 1.0.0 ### Minor Changes diff --git a/packages/ui-composer/package.json b/packages/ui-composer/package.json index fbb0a7f86100b..dc800fb0b108d 100644 --- a/packages/ui-composer/package.json +++ b/packages/ui-composer/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/ui-composer", - "version": "1.0.0", + "version": "2.0.0", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", @@ -53,7 +53,7 @@ "@react-aria/toolbar": "*", "@rocket.chat/fuselage": "*", "@rocket.chat/icons": "*", - "@rocket.chat/ui-client": "30.0.0", + "@rocket.chat/ui-client": "31.0.0", "react": "*", "react-dom": "*" }, diff --git a/packages/ui-contexts/CHANGELOG.md b/packages/ui-contexts/CHANGELOG.md index 6825da0c98458..c65760251cb1f 100644 --- a/packages/ui-contexts/CHANGELOG.md +++ b/packages/ui-contexts/CHANGELOG.md @@ -1,5 +1,29 @@ # @rocket.chat/ui-contexts +## 31.0.0 + +### Patch Changes + +-
    Updated dependencies [cdb264fec803e234a6ad2000018b31d4b2074e99, bede0e2528bb053cb913e93ccf30d78a1c84bc76, bede0e2528bb053cb913e93ccf30d78a1c84bc76, bede0e2528bb053cb913e93ccf30d78a1c84bc76, 4c3984593017d59edd631bf8ae4f35f9d3c3db36, ad7d42400ea36f1eb0aaf7cc3361c77fdabf9ebc, 4704bf81ca370f120af32185a7c55407a26f8514, d427b808c1f79d9d1baa05bb5b5ef805b6ef5f6d, ebc9babf55dd26613027c28dcacf77909116b342, fac64728505b312d5da786e92d3134450ce4a7c1, 12897e25d0dc25b7373f5264d38f38a5a7444257, 51833064591b91140d17e403389e1abbc5d9ef7a, b1c2668b74bfb49ebaefe2f581b2f8be5d4d1dd6]: + + - @rocket.chat/i18n@3.1.0 + - @rocket.chat/ddp-client@1.1.0 + - @rocket.chat/rest-typings@8.5.0 + - @rocket.chat/core-typings@8.5.0 +
    + +## 31.0.0-rc.0 + +### Patch Changes + +-
    Updated dependencies [cdb264fec803e234a6ad2000018b31d4b2074e99, bede0e2528bb053cb913e93ccf30d78a1c84bc76, bede0e2528bb053cb913e93ccf30d78a1c84bc76, bede0e2528bb053cb913e93ccf30d78a1c84bc76, 4c3984593017d59edd631bf8ae4f35f9d3c3db36, ae9f740d6af20557eac61b4af902c868b4132b49, ad7d42400ea36f1eb0aaf7cc3361c77fdabf9ebc, 4704bf81ca370f120af32185a7c55407a26f8514, d427b808c1f79d9d1baa05bb5b5ef805b6ef5f6d, ebc9babf55dd26613027c28dcacf77909116b342, fac64728505b312d5da786e92d3134450ce4a7c1, 12897e25d0dc25b7373f5264d38f38a5a7444257, 51833064591b91140d17e403389e1abbc5d9ef7a, b1c2668b74bfb49ebaefe2f581b2f8be5d4d1dd6]: + + - @rocket.chat/i18n@3.1.0-rc.0 + - @rocket.chat/ddp-client@1.1.0-rc.0 + - @rocket.chat/rest-typings@8.5.0-rc.0 + - @rocket.chat/core-typings@8.5.0-rc.0 +
    + ## 30.0.0 ### Patch Changes diff --git a/packages/ui-contexts/package.json b/packages/ui-contexts/package.json index c098a3b68c1d5..5d88cf8899664 100644 --- a/packages/ui-contexts/package.json +++ b/packages/ui-contexts/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/ui-contexts", - "version": "30.0.0", + "version": "31.0.0", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/ui-kit/CHANGELOG.md b/packages/ui-kit/CHANGELOG.md index 894e366a019c7..d5210fffdaabd 100644 --- a/packages/ui-kit/CHANGELOG.md +++ b/packages/ui-kit/CHANGELOG.md @@ -1,5 +1,25 @@ # Change Log +## 1.1.0 + +### Minor Changes + +- ([#39858](https://github.com/RocketChat/Rocket.Chat/pull/39858)) Adds support to room information on ViewSubmit and ViewClose events for ContextualBar surface + +### Patch Changes + +- ([#39858](https://github.com/RocketChat/Rocket.Chat/pull/39858)) Fixes an issue that prevented BlockAction interactions from having room information when triggered in a ContextualBar surface + +## 1.1.0-rc.0 + +### Minor Changes + +- ([#39858](https://github.com/RocketChat/Rocket.Chat/pull/39858)) Adds support to room information on ViewSubmit and ViewClose events for ContextualBar surface + +### Patch Changes + +- ([#39858](https://github.com/RocketChat/Rocket.Chat/pull/39858)) Fixes an issue that prevented BlockAction interactions from having room information when triggered in a ContextualBar surface + ## 1.0.0 ### Major Changes diff --git a/packages/ui-kit/package.json b/packages/ui-kit/package.json index 102f8932d1984..47680ff77d5a0 100644 --- a/packages/ui-kit/package.json +++ b/packages/ui-kit/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/ui-kit", - "version": "1.0.0", + "version": "1.1.0", "description": "Interactive UI elements for Rocket.Chat Apps", "homepage": "https://rocket.chat", "bugs": { diff --git a/packages/ui-video-conf/CHANGELOG.md b/packages/ui-video-conf/CHANGELOG.md index 62673a16a8a83..3b272d46c46b9 100644 --- a/packages/ui-video-conf/CHANGELOG.md +++ b/packages/ui-video-conf/CHANGELOG.md @@ -1,5 +1,25 @@ # @rocket.chat/ui-video-conf +## 31.0.0 + +### Patch Changes + +-
    Updated dependencies []: + + - @rocket.chat/ui-avatar@27.0.0 + - @rocket.chat/ui-contexts@31.0.0 +
    + +## 31.0.0-rc.0 + +### Patch Changes + +-
    Updated dependencies []: + + - @rocket.chat/ui-contexts@31.0.0-rc.0 + - @rocket.chat/ui-avatar@27.0.0-rc.0 +
    + ## 30.0.0 ### Patch Changes diff --git a/packages/ui-video-conf/package.json b/packages/ui-video-conf/package.json index 83c0d3ebea85b..d752582797aea 100644 --- a/packages/ui-video-conf/package.json +++ b/packages/ui-video-conf/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/ui-video-conf", - "version": "30.0.0", + "version": "31.0.0", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/ui-voip/CHANGELOG.md b/packages/ui-voip/CHANGELOG.md index 25be30802b1cd..61789008f7ef4 100644 --- a/packages/ui-voip/CHANGELOG.md +++ b/packages/ui-voip/CHANGELOG.md @@ -1,5 +1,43 @@ # @rocket.chat/ui-voip +## 21.0.0 + +### Minor Changes + +- ([#40331](https://github.com/RocketChat/Rocket.Chat/pull/40331)) Adds "Open in room" button to shared screen card on voice call widget + +### Patch Changes + +- ([#40330](https://github.com/RocketChat/Rocket.Chat/pull/40330)) Fixes an issue where intentionally cancelling a screen share request would show an error toast by identifying error types and counting consecutive failures. + +-
    Updated dependencies [fac64728505b312d5da786e92d3134450ce4a7c1]: + + - @rocket.chat/ui-client@31.0.0 + - @rocket.chat/desktop-api@1.2.0 + - @rocket.chat/fuselage-ui-kit@31.0.0 + - @rocket.chat/ui-avatar@27.0.0 + - @rocket.chat/ui-contexts@31.0.0 +
    + +## 21.0.0-rc.0 + +### Minor Changes + +- ([#40331](https://github.com/RocketChat/Rocket.Chat/pull/40331)) Adds "Open in room" button to shared screen card on voice call widget + +### Patch Changes + +- ([#40330](https://github.com/RocketChat/Rocket.Chat/pull/40330)) Fixes an issue where intentionally cancelling a screen share request would show an error toast by identifying error types and counting consecutive failures. + +-
    Updated dependencies [ae9f740d6af20557eac61b4af902c868b4132b49, fac64728505b312d5da786e92d3134450ce4a7c1]: + + - @rocket.chat/desktop-api@1.2.0-rc.0 + - @rocket.chat/ui-client@31.0.0-rc.0 + - @rocket.chat/fuselage-ui-kit@31.0.0-rc.0 + - @rocket.chat/ui-contexts@31.0.0-rc.0 + - @rocket.chat/ui-avatar@27.0.0-rc.0 +
    + ## 20.0.0 ### Minor Changes diff --git a/packages/ui-voip/package.json b/packages/ui-voip/package.json index ea61c625ff897..fcedfdc7d2e3a 100644 --- a/packages/ui-voip/package.json +++ b/packages/ui-voip/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/ui-voip", - "version": "20.0.0", + "version": "21.0.0", "private": true, "main": "./dist/index.js", "typings": "./dist/index.d.ts", diff --git a/packages/web-ui-registration/CHANGELOG.md b/packages/web-ui-registration/CHANGELOG.md index 8d854d81dace3..68ad04f1d6137 100644 --- a/packages/web-ui-registration/CHANGELOG.md +++ b/packages/web-ui-registration/CHANGELOG.md @@ -1,5 +1,40 @@ # @rocket.chat/web-ui-registration +## 31.0.0 + +### Patch Changes + +-
    Updated dependencies []: + + - @rocket.chat/ui-contexts@31.0.0 +
    + +## 31.0.0-rc.0 + +### Minor Changes + +- ([#39760](https://github.com/RocketChat/Rocket.Chat/pull/39760)) ## Phishing-Resistant Multi-Factor Authentication + + Introduces a more secure and reliable server-side OAuth authentication flow. + + ### What’s New + + - **Improved OAuth login security** + OAuth authentication now happens fully on the server, reducing the risk of token theft, phishing attacks, and client-side credential interception. + - **Built-in CSRF, state validation, and PKCE protection** + OAuth logins now include stronger protection against CSRF attacks, request tampering, and authorization code interception through secure state validation and PKCE support. + - **Improved two-step verification with OAuth logins** + Users with email or TOTP two-factor authentication enabled will now be asked to complete 2FA even when signing in with providers like Google, GitHub, GitLab, and others. + - **Improved mobile & desktop app login** + Mobile and desktop apps now support a smoother and more secure deep-link OAuth login flow. + +### Patch Changes + +-
    Updated dependencies []: + + - @rocket.chat/ui-contexts@31.0.0-rc.0 +
    + ## 30.0.0 ### Patch Changes diff --git a/packages/web-ui-registration/package.json b/packages/web-ui-registration/package.json index 697a12d7852bf..ef5eab4ab38b0 100644 --- a/packages/web-ui-registration/package.json +++ b/packages/web-ui-registration/package.json @@ -1,6 +1,6 @@ { "name": "@rocket.chat/web-ui-registration", - "version": "30.0.0", + "version": "31.0.0", "private": true, "homepage": "https://rocket.chat", "main": "./dist/index.js", @@ -60,7 +60,7 @@ "peerDependencies": { "@rocket.chat/layout": "*", "@rocket.chat/tools": "0.3.0", - "@rocket.chat/ui-contexts": "30.0.0", + "@rocket.chat/ui-contexts": "31.0.0", "@tanstack/react-query": "*", "react": "*", "react-hook-form": "*", diff --git a/yarn.lock b/yarn.lock index 9b18fe736edaa..716073c1253ba 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8996,11 +8996,11 @@ __metadata: resolution: "@rocket.chat/apps-engine@workspace:packages/apps-engine" dependencies: "@rocket.chat/ui-kit": "workspace:~" - "@types/node": "npm:~22.16.5" - eslint: "npm:~9.39.3" + "@types/node": "npm:~22.19.17" + eslint: "npm:~9.39.4" npm-run-all: "npm:^4.1.5" rimraf: "npm:^6.0.1" - typedoc: "npm:~0.28.16" + typedoc: "npm:~0.28.10" typescript: "npm:~5.9.3" uuid: "npm:~11.1.1" languageName: unknown @@ -11057,7 +11057,7 @@ __metadata: "@react-aria/toolbar": "*" "@rocket.chat/fuselage": "*" "@rocket.chat/icons": "*" - "@rocket.chat/ui-client": 30.0.0 + "@rocket.chat/ui-client": 31.0.0-rc.0 react: "*" react-dom: "*" languageName: unknown @@ -11328,7 +11328,7 @@ __metadata: peerDependencies: "@rocket.chat/layout": "*" "@rocket.chat/tools": 0.3.0 - "@rocket.chat/ui-contexts": 30.0.0 + "@rocket.chat/ui-contexts": 31.0.0-rc.0 "@tanstack/react-query": "*" react: "*" react-hook-form: "*" @@ -21880,7 +21880,7 @@ __metadata: languageName: node linkType: hard -"eslint@npm:~9.39.3, eslint@npm:~9.39.4": +"eslint@npm:~9.39.4": version: 9.39.4 resolution: "eslint@npm:9.39.4" dependencies: @@ -36369,7 +36369,7 @@ __metadata: languageName: node linkType: hard -"typedoc@npm:~0.28.16": +"typedoc@npm:~0.28.10": version: 0.28.19 resolution: "typedoc@npm:0.28.19" dependencies: