snapshot of https://github.com/RocketChat/Rocket.Chat.git (develop, 2026-09-16; blobs > 131072B omitted)
Some checks failed
Create issues from TODOs / todos (push) Failing after 3s
Close inactive issues / close-issues (push) Has been cancelled
Deploy GitHub Pages / deploy-preview (push) Has been cancelled
CI / ⚙️ Variables Setup (push) Has been cancelled
CI / ⚙️ Test Guard (push) Has been cancelled
CI / 🚀 Notify external services - draft (push) Has been cancelled
CI / 📦 Build Packages (push) Has been cancelled
CI / 📦 Meteor Build (coverage) (push) Has been cancelled
CI / 📦 Meteor Build (production) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], fips) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Publish Docker Images (ghcr.io) (push) Has been cancelled
CI / 📦 Track Image Sizes (push) Has been cancelled
CI / 🔎 Code Check - Action Lint (push) Has been cancelled
CI / 🔎 Code Check (push) Has been cancelled
CI / 🔨 Test Storybook (push) Has been cancelled
CI / 🔨 Test Unit (push) Has been cancelled
CI / 🔨 Test API (CE) (push) Has been cancelled
CI / 🔨 Test API Livechat (CE) (push) Has been cancelled
CI / 🔨 Test UI (CE) (push) Has been cancelled
CI / 🔨 Test API (EE) (push) Has been cancelled
CI / 🔨 Test API Livechat (EE) (push) Has been cancelled
CI / 🔨 Test API Apps (deno-runtime - EE) (push) Has been cancelled
CI / 🔨 Test UI (EE) (push) Has been cancelled
CI / 🔨 Test API (FIPS) (push) Has been cancelled
CI / 🔨 Test API Livechat (FIPS) (push) Has been cancelled
CI / 🔨 Test UI (FIPS) (push) Has been cancelled
CI / 🔨 Test Federation Matrix (push) Has been cancelled
CI / 📊 Report Coverage (push) Has been cancelled
CI / ✅ Tests Done (push) Has been cancelled
CI / 🚀 Publish build assets (push) Has been cancelled
CI / 🚀 Publish Docker Images (DockerHub) (push) Has been cancelled
CI / 🚀 Notify external services (push) Has been cancelled
CI / Update Version Durability (push) Has been cancelled
Release / Release (push) Has been cancelled
Auto-close duplicate issues / auto-close-duplicates (push) Failing after 1s
Code scanning - action / CodeQL-Build (push) Failing after 1s
Some checks failed
Create issues from TODOs / todos (push) Failing after 3s
Close inactive issues / close-issues (push) Has been cancelled
Deploy GitHub Pages / deploy-preview (push) Has been cancelled
CI / ⚙️ Variables Setup (push) Has been cancelled
CI / ⚙️ Test Guard (push) Has been cancelled
CI / 🚀 Notify external services - draft (push) Has been cancelled
CI / 📦 Build Packages (push) Has been cancelled
CI / 📦 Meteor Build (coverage) (push) Has been cancelled
CI / 📦 Meteor Build (production) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], fips) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Publish Docker Images (ghcr.io) (push) Has been cancelled
CI / 📦 Track Image Sizes (push) Has been cancelled
CI / 🔎 Code Check - Action Lint (push) Has been cancelled
CI / 🔎 Code Check (push) Has been cancelled
CI / 🔨 Test Storybook (push) Has been cancelled
CI / 🔨 Test Unit (push) Has been cancelled
CI / 🔨 Test API (CE) (push) Has been cancelled
CI / 🔨 Test API Livechat (CE) (push) Has been cancelled
CI / 🔨 Test UI (CE) (push) Has been cancelled
CI / 🔨 Test API (EE) (push) Has been cancelled
CI / 🔨 Test API Livechat (EE) (push) Has been cancelled
CI / 🔨 Test API Apps (deno-runtime - EE) (push) Has been cancelled
CI / 🔨 Test UI (EE) (push) Has been cancelled
CI / 🔨 Test API (FIPS) (push) Has been cancelled
CI / 🔨 Test API Livechat (FIPS) (push) Has been cancelled
CI / 🔨 Test UI (FIPS) (push) Has been cancelled
CI / 🔨 Test Federation Matrix (push) Has been cancelled
CI / 📊 Report Coverage (push) Has been cancelled
CI / ✅ Tests Done (push) Has been cancelled
CI / 🚀 Publish build assets (push) Has been cancelled
CI / 🚀 Publish Docker Images (DockerHub) (push) Has been cancelled
CI / 🚀 Notify external services (push) Has been cancelled
CI / Update Version Durability (push) Has been cancelled
Release / Release (push) Has been cancelled
Auto-close duplicate issues / auto-close-duplicates (push) Failing after 1s
Code scanning - action / CodeQL-Build (push) Failing after 1s
This commit is contained in:
776
ee/packages/omni-core-ee/CHANGELOG.md
Normal file
776
ee/packages/omni-core-ee/CHANGELOG.md
Normal file
@@ -0,0 +1,776 @@
|
||||
# @rocket.chat/omni-core-ee
|
||||
|
||||
## 0.0.25
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies [4947601bbf042cd1b2385f8f5dda438e608faea7, b89a8d411ef65f6931a5fd1cd057740bc00cd9ba, 5deefe2766132f13118f38dc42cf1c9895208961, 8984df841e1ecc46198e073982adabc1f069c352, a9f3e6cd3f31eac17bec626287fcf815d802e9b9, 742009a09148e33d141f50691cdec0f7e9818535]:</summary>
|
||||
|
||||
- @rocket.chat/models@2.5.0
|
||||
- @rocket.chat/core-services@0.16.0
|
||||
- @rocket.chat/omni-core@0.1.4
|
||||
</details>
|
||||
|
||||
## 0.0.25-rc.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies [4947601bbf042cd1b2385f8f5dda438e608faea7, b89a8d411ef65f6931a5fd1cd057740bc00cd9ba, 5deefe2766132f13118f38dc42cf1c9895208961, 8984df841e1ecc46198e073982adabc1f069c352, a9f3e6cd3f31eac17bec626287fcf815d802e9b9, 742009a09148e33d141f50691cdec0f7e9818535]:</summary>
|
||||
|
||||
- @rocket.chat/models@2.5.0-rc.0
|
||||
- @rocket.chat/core-services@0.16.0-rc.0
|
||||
- @rocket.chat/omni-core@0.1.4-rc.0
|
||||
</details>
|
||||
|
||||
## 0.0.24
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies [c7aff48a40a9a78924cbf27fd38930c536ee11e5, 5f92f9a27dca70d506d919351612bd32dc04241a, 13b4a7b2dc203959b77b3b0c5f154d3e34fe2058, 4b34bd62f2ac8d51efd2f48caea7092e87f30ce7, 4b57346a59b5c9433c25845c886be11af1bf71d4, ffe1b646226eeeda5a4d4697c831e568ec1eec64, 3cd7db677a72521439b564dca7a4ca6d6c3a1c07, 719e3db9734708e812ceb33483ffaa2e064b4d59, 1cc7bbdef9330899a8207d3d55130f48321d68f1]:</summary>
|
||||
|
||||
- @rocket.chat/models@2.4.0
|
||||
- @rocket.chat/core-services@0.15.0
|
||||
- @rocket.chat/omni-core@0.1.3
|
||||
</details>
|
||||
|
||||
## 0.0.24-rc.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies [c7aff48a40a9a78924cbf27fd38930c536ee11e5, 5f92f9a27dca70d506d919351612bd32dc04241a, 13b4a7b2dc203959b77b3b0c5f154d3e34fe2058, 4b34bd62f2ac8d51efd2f48caea7092e87f30ce7, 4b57346a59b5c9433c25845c886be11af1bf71d4, ffe1b646226eeeda5a4d4697c831e568ec1eec64, 3cd7db677a72521439b564dca7a4ca6d6c3a1c07, 719e3db9734708e812ceb33483ffaa2e064b4d59, 1cc7bbdef9330899a8207d3d55130f48321d68f1]:</summary>
|
||||
|
||||
- @rocket.chat/models@2.4.0-rc.0
|
||||
- @rocket.chat/core-services@0.15.0-rc.0
|
||||
- @rocket.chat/omni-core@0.1.3-rc.0
|
||||
</details>
|
||||
|
||||
## 0.0.23
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies [73e12e1707baea845395e0582892f65456598672, a7279cebc73edfa4b991eb593730c08e8f5e9001, 7380c44c751eff9ee624d80bf26370411ffed78b]:</summary>
|
||||
|
||||
- @rocket.chat/models@2.3.1
|
||||
- @rocket.chat/core-services@0.14.2
|
||||
- @rocket.chat/omni-core@0.1.2
|
||||
</details>
|
||||
|
||||
## 0.0.23-rc.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies [73e12e1707baea845395e0582892f65456598672, a7279cebc73edfa4b991eb593730c08e8f5e9001, 7380c44c751eff9ee624d80bf26370411ffed78b]:</summary>
|
||||
|
||||
- @rocket.chat/models@2.3.1-rc.0
|
||||
- @rocket.chat/core-services@0.14.2-rc.0
|
||||
- @rocket.chat/omni-core@0.1.2-rc.0
|
||||
</details>
|
||||
|
||||
## 0.0.22
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies [f7d47dd3517ec14ca2ec5c3c95fcdf9e1e2fb8b0, b6b04aadfcc8558f888b334e37c46a77e5816237, 4704bf81ca370f120af32185a7c55407a26f8514, 12897e25d0dc25b7373f5264d38f38a5a7444257, e45585b70a3a7b75434c88e4b2ea9af0a0764a76]:</summary>
|
||||
|
||||
- @rocket.chat/models@2.3.0
|
||||
- @rocket.chat/core-services@0.14.1
|
||||
- @rocket.chat/omni-core@0.1.1
|
||||
</details>
|
||||
|
||||
## 0.0.22-rc.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies [f7d47dd3517ec14ca2ec5c3c95fcdf9e1e2fb8b0, ae9f740d6af20557eac61b4af902c868b4132b49, b6b04aadfcc8558f888b334e37c46a77e5816237, 4704bf81ca370f120af32185a7c55407a26f8514, 12897e25d0dc25b7373f5264d38f38a5a7444257, e45585b70a3a7b75434c88e4b2ea9af0a0764a76]:</summary>
|
||||
|
||||
- @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
|
||||
</details>
|
||||
|
||||
## 0.0.21
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies [21cd54f87de5837fe6c999a44bd15be34b9fe905, 278b84f78360e53792a2e5d7620615039a0e15e9, 12c44d2db65af9f90c741da621164f5738fc19f5, 9713af36f5c0d673f2d2093015f322341706bab0, f3fa3ee2f2e53b777de9abd466f1b76a1ec1b96c, c544b805d1c03f8eae9d061cd48838206207a7c9, 8c0e16ca29b393cfa50b425520db48ba5a74f678, f4dfb8ddc2049692371aeb084110b5768151b5df]:</summary>
|
||||
|
||||
- @rocket.chat/core-services@0.14.0
|
||||
- @rocket.chat/models@2.2.0
|
||||
- @rocket.chat/omni-core@0.1.0
|
||||
</details>
|
||||
|
||||
## 0.0.21-rc.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies []:</summary>
|
||||
|
||||
- @rocket.chat/core-services@0.14.0-rc.2
|
||||
- @rocket.chat/models@2.2.0-rc.2
|
||||
- @rocket.chat/omni-core@0.1.0-rc.2
|
||||
</details>
|
||||
|
||||
## 0.0.21-rc.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies []:</summary>
|
||||
|
||||
- @rocket.chat/core-services@0.14.0-rc.1
|
||||
- @rocket.chat/models@2.2.0-rc.1
|
||||
- @rocket.chat/omni-core@0.1.0-rc.1
|
||||
</details>
|
||||
|
||||
## 0.0.20
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies []:</summary>
|
||||
|
||||
- @rocket.chat/core-services@0.13.4
|
||||
- @rocket.chat/models@2.1.4
|
||||
- @rocket.chat/omni-core@0.0.20
|
||||
</details>
|
||||
|
||||
## 0.0.19
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies []:</summary>
|
||||
|
||||
- @rocket.chat/core-services@0.13.3
|
||||
- @rocket.chat/models@2.1.3
|
||||
- @rocket.chat/omni-core@0.0.19
|
||||
</details>
|
||||
|
||||
## 0.0.21-rc.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies [21cd54f87de5837fe6c999a44bd15be34b9fe905, 278b84f78360e53792a2e5d7620615039a0e15e9, 12c44d2db65af9f90c741da621164f5738fc19f5, 9713af36f5c0d673f2d2093015f322341706bab0, f3fa3ee2f2e53b777de9abd466f1b76a1ec1b96c, c544b805d1c03f8eae9d061cd48838206207a7c9, 8c0e16ca29b393cfa50b425520db48ba5a74f678, f4dfb8ddc2049692371aeb084110b5768151b5df]:</summary>
|
||||
|
||||
- @rocket.chat/core-services@0.14.0-rc.0
|
||||
- @rocket.chat/models@2.2.0-rc.0
|
||||
- @rocket.chat/omni-core@0.1.0-rc.0
|
||||
</details>
|
||||
|
||||
## 0.0.18
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration
|
||||
|
||||
- <details><summary>Updated dependencies [602b20a8c570b895eb296ecfe39c9b7fcb12fabd, e2068892bf1ffc88b15ab71ad743cf84e5d31ed5, cd2fc208d351032c0b729755af4886665dca08b6, 539659af22bc19880eda047dfc0b152472ccb65c, eae3fb3136bd0b48294c050a71b0a36d05ca02b0]:</summary>
|
||||
|
||||
- @rocket.chat/models@2.1.2
|
||||
- @rocket.chat/core-services@0.13.2
|
||||
- @rocket.chat/omni-core@0.0.18
|
||||
- @rocket.chat/logger@1.0.1
|
||||
</details>
|
||||
|
||||
## 0.0.18-rc.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies []:</summary>
|
||||
|
||||
- @rocket.chat/core-services@0.13.2-rc.4
|
||||
- @rocket.chat/models@2.1.2-rc.4
|
||||
- @rocket.chat/omni-core@0.0.18-rc.4
|
||||
</details>
|
||||
|
||||
## 0.0.18-rc.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies []:</summary>
|
||||
|
||||
- @rocket.chat/core-services@0.13.2-rc.3
|
||||
- @rocket.chat/models@2.1.2-rc.3
|
||||
- @rocket.chat/omni-core@0.0.18-rc.3
|
||||
</details>
|
||||
|
||||
## 0.0.18-rc.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies []:</summary>
|
||||
|
||||
- @rocket.chat/core-services@0.13.2-rc.2
|
||||
- @rocket.chat/models@2.1.2-rc.2
|
||||
- @rocket.chat/omni-core@0.0.18-rc.2
|
||||
</details>
|
||||
|
||||
## 0.0.18-rc.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies []:</summary>
|
||||
|
||||
- @rocket.chat/core-services@0.13.2-rc.1
|
||||
- @rocket.chat/models@2.1.2-rc.1
|
||||
- @rocket.chat/omni-core@0.0.18-rc.1
|
||||
</details>
|
||||
|
||||
## 0.0.18-rc.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- ([#38989](https://github.com/RocketChat/Rocket.Chat/pull/38989)) chore(eslint): Upgrades ESLint and its configuration
|
||||
|
||||
- <details><summary>Updated dependencies [602b20a8c570b895eb296ecfe39c9b7fcb12fabd, e2068892bf1ffc88b15ab71ad743cf84e5d31ed5, cd2fc208d351032c0b729755af4886665dca08b6, 539659af22bc19880eda047dfc0b152472ccb65c, eae3fb3136bd0b48294c050a71b0a36d05ca02b0]:</summary>
|
||||
|
||||
- @rocket.chat/models@2.1.2-rc.0
|
||||
- @rocket.chat/core-services@0.13.2-rc.0
|
||||
- @rocket.chat/omni-core@0.0.18-rc.0
|
||||
- @rocket.chat/logger@1.0.1-rc.0
|
||||
</details>
|
||||
|
||||
## 0.0.17
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies []:</summary>
|
||||
|
||||
- @rocket.chat/core-services@0.13.1
|
||||
- @rocket.chat/models@2.1.1
|
||||
- @rocket.chat/omni-core@0.0.17
|
||||
</details>
|
||||
|
||||
## 0.0.16
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies [d3758a7d57ab602745369ef9d2ccdbf9271cf305, e57f15845e4df048dd2f08f11aa08215780a2c34, 11e1c51f0867a35c69ce9b6eeca25dbbe2c71872, 3b003e6b69c11b280d55bcc8db2f3e4ae7a4a573, 87faec13b3c0efc3e85627f9b70c4561b7231416, 508b4a17d76dc1cd7d3a55bdba826216f51432e2, 123aebec2caa74b17d2b5dcbd2a2db2e687cf3ac]:</summary>
|
||||
|
||||
- @rocket.chat/models@2.1.0
|
||||
- @rocket.chat/core-services@0.13.0
|
||||
- @rocket.chat/omni-core@0.0.16
|
||||
</details>
|
||||
|
||||
## 0.0.16-rc.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies []:</summary>
|
||||
|
||||
- @rocket.chat/core-services@0.13.0-rc.2
|
||||
- @rocket.chat/models@2.1.0-rc.2
|
||||
- @rocket.chat/omni-core@0.0.16-rc.2
|
||||
</details>
|
||||
|
||||
## 0.0.16-rc.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies []:</summary>
|
||||
|
||||
- @rocket.chat/core-services@0.13.0-rc.1
|
||||
- @rocket.chat/models@2.1.0-rc.1
|
||||
- @rocket.chat/omni-core@0.0.16-rc.1
|
||||
</details>
|
||||
|
||||
## 0.0.16-rc.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies [d3758a7d57ab602745369ef9d2ccdbf9271cf305, e57f15845e4df048dd2f08f11aa08215780a2c34, 11e1c51f0867a35c69ce9b6eeca25dbbe2c71872, 3b003e6b69c11b280d55bcc8db2f3e4ae7a4a573, 87faec13b3c0efc3e85627f9b70c4561b7231416, 508b4a17d76dc1cd7d3a55bdba826216f51432e2, 123aebec2caa74b17d2b5dcbd2a2db2e687cf3ac]:</summary>
|
||||
|
||||
- @rocket.chat/models@2.1.0-rc.0
|
||||
- @rocket.chat/core-services@0.13.0-rc.0
|
||||
- @rocket.chat/omni-core@0.0.16-rc.0
|
||||
</details>
|
||||
|
||||
## 0.0.15
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies []:</summary>
|
||||
|
||||
- @rocket.chat/core-services@0.12.3
|
||||
- @rocket.chat/models@2.0.3
|
||||
- @rocket.chat/omni-core@0.0.15
|
||||
</details>
|
||||
|
||||
## 0.0.14
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies [f4fa393fccb6abefbe6fb6550563e8ca21fc792d, 7b51ba84340480fa28e85c8f35d9d2f947d3250e, 020dfbcab6a940ca2e03d802d0f6b54714a34aa2, 5fa150953b86ff36face25083ed49e8c97a8044d, 05c415b94cb91907de39a39c6d277579258f334e]:</summary>
|
||||
|
||||
- @rocket.chat/models@2.0.2
|
||||
- @rocket.chat/core-services@0.12.2
|
||||
- @rocket.chat/omni-core@0.0.14
|
||||
</details>
|
||||
|
||||
## 0.0.14-rc.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies []:</summary>
|
||||
|
||||
- @rocket.chat/core-services@0.12.2-rc.2
|
||||
- @rocket.chat/models@2.0.2-rc.2
|
||||
- @rocket.chat/omni-core@0.0.14-rc.2
|
||||
</details>
|
||||
|
||||
## 0.0.14-rc.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies []:</summary>
|
||||
- @rocket.chat/core-services@0.12.1-rc.1
|
||||
- @rocket.chat/models@2.0.1-rc.1
|
||||
- @rocket.chat/omni-core@0.0.13-rc.1
|
||||
</details>
|
||||
|
||||
## 0.0.14-rc.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies [f4fa393fccb6abefbe6fb6550563e8ca21fc792d, 7b51ba84340480fa28e85c8f35d9d2f947d3250e, 020dfbcab6a940ca2e03d802d0f6b54714a34aa2, 5fa150953b86ff36face25083ed49e8c97a8044d, 05c415b94cb91907de39a39c6d277579258f334e]:</summary>
|
||||
|
||||
- @rocket.chat/models@2.0.1-rc.0
|
||||
- @rocket.chat/core-services@0.12.1-rc.0
|
||||
- @rocket.chat/omni-core@0.0.13-rc.0
|
||||
</details>
|
||||
|
||||
## 0.0.13
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies []:</summary>
|
||||
|
||||
- @rocket.chat/core-services@0.12.1
|
||||
- @rocket.chat/models@2.0.1
|
||||
- @rocket.chat/omni-core@0.0.13
|
||||
</details>
|
||||
|
||||
## 0.0.12
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies [ac11ea05ffadeca978c794ff38d5199d9acb2c29, 1baa03cced8f94584da1224ad59cad86f219707a, ac11ea05ffadeca978c794ff38d5199d9acb2c29, ddc935727e9a7275813006d9dcaa7fe866610844, 73d9eb2783176954f42aa2cbeda8abf1d49ac260, be80b724a636877294b5e5baa501d070941131dd, 4aa3634186d97f4144c39f6b42a65107d3d30df0, ec0f8b435dd12c218adffa8892737c7ced4debb8]:</summary>
|
||||
|
||||
- @rocket.chat/models@2.0.0
|
||||
- @rocket.chat/core-services@0.12.0
|
||||
- @rocket.chat/logger@1.0.0
|
||||
- @rocket.chat/omni-core@0.0.12
|
||||
</details>
|
||||
|
||||
## 0.0.12-rc.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies []:</summary>
|
||||
|
||||
- @rocket.chat/core-services@0.12.0-rc.5
|
||||
- @rocket.chat/models@2.0.0-rc.5
|
||||
- @rocket.chat/omni-core@0.0.12-rc.5
|
||||
</details>
|
||||
|
||||
## 0.0.12-rc.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies []:</summary>
|
||||
|
||||
- @rocket.chat/core-services@0.12.0-rc.4
|
||||
- @rocket.chat/models@2.0.0-rc.4
|
||||
- @rocket.chat/omni-core@0.0.12-rc.4
|
||||
</details>
|
||||
|
||||
## 0.0.12-rc.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies []:</summary>
|
||||
|
||||
- @rocket.chat/core-services@0.12.0-rc.3
|
||||
- @rocket.chat/models@2.0.0-rc.3
|
||||
- @rocket.chat/omni-core@0.0.12-rc.3
|
||||
</details>
|
||||
|
||||
## 0.0.12-rc.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies []:</summary>
|
||||
|
||||
- @rocket.chat/core-services@0.12.0-rc.2
|
||||
- @rocket.chat/models@2.0.0-rc.2
|
||||
- @rocket.chat/omni-core@0.0.12-rc.2
|
||||
</details>
|
||||
|
||||
## 0.0.12-rc.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies []:</summary>
|
||||
|
||||
- @rocket.chat/core-services@0.12.0-rc.1
|
||||
- @rocket.chat/models@2.0.0-rc.1
|
||||
- @rocket.chat/omni-core@0.0.12-rc.1
|
||||
</details>
|
||||
|
||||
## 0.0.12-rc.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies [ac11ea05ffadeca978c794ff38d5199d9acb2c29, 1baa03cced8f94584da1224ad59cad86f219707a, ac11ea05ffadeca978c794ff38d5199d9acb2c29, ddc935727e9a7275813006d9dcaa7fe866610844, 73d9eb2783176954f42aa2cbeda8abf1d49ac260, be80b724a636877294b5e5baa501d070941131dd, 4aa3634186d97f4144c39f6b42a65107d3d30df0, ec0f8b435dd12c218adffa8892737c7ced4debb8]:</summary>
|
||||
|
||||
- @rocket.chat/models@2.0.0-rc.0
|
||||
- @rocket.chat/core-services@0.12.0-rc.0
|
||||
- @rocket.chat/logger@1.0.0-rc.0
|
||||
- @rocket.chat/omni-core@0.0.12-rc.0
|
||||
</details>
|
||||
|
||||
## 0.0.11
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies [eef2b390a8e4664ad4b974e7ea579982245efce5]:</summary>
|
||||
|
||||
- @rocket.chat/core-services@0.11.2
|
||||
- @rocket.chat/models@1.8.2
|
||||
- @rocket.chat/omni-core@0.0.11
|
||||
</details>
|
||||
|
||||
## 0.0.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies []:</summary>
|
||||
|
||||
- @rocket.chat/core-services@0.11.1
|
||||
- @rocket.chat/models@1.8.1
|
||||
- @rocket.chat/omni-core@0.0.10
|
||||
</details>
|
||||
|
||||
## 0.0.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies [8596daf01ac84864caa63dd937971e557933d401, 83642cbe499ba399329449fb8cd652a0405c0795, 7f1b834a55b1240c226afde77713262da47f45dc]:</summary>
|
||||
|
||||
- @rocket.chat/core-services@0.11.0
|
||||
- @rocket.chat/models@1.8.0
|
||||
- @rocket.chat/omni-core@0.0.9
|
||||
</details>
|
||||
|
||||
## 0.0.9-rc.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies []:</summary>
|
||||
|
||||
- @rocket.chat/core-services@0.11.0-rc.2
|
||||
- @rocket.chat/models@1.8.0-rc.2
|
||||
- @rocket.chat/omni-core@0.0.9-rc.2
|
||||
</details>
|
||||
|
||||
## 0.0.9-rc.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies []:</summary>
|
||||
- @rocket.chat/core-services@0.11.0-rc.1
|
||||
- @rocket.chat/models@1.8.0-rc.1
|
||||
- @rocket.chat/omni-core@0.0.7-rc.1
|
||||
</details>
|
||||
|
||||
## 0.0.9-rc.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies [8596daf01ac84864caa63dd937971e557933d401, 83642cbe499ba399329449fb8cd652a0405c0795, 7f1b834a55b1240c226afde77713262da47f45dc]:</summary>
|
||||
|
||||
- @rocket.chat/core-services@0.11.0-rc.0
|
||||
- @rocket.chat/models@1.8.0-rc.0
|
||||
- @rocket.chat/omni-core@0.0.7-rc.0
|
||||
</details>
|
||||
|
||||
## 0.0.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies []:</summary>
|
||||
|
||||
- @rocket.chat/core-services@0.10.6
|
||||
- @rocket.chat/models@1.7.3
|
||||
- @rocket.chat/omni-core@0.0.8
|
||||
</details>
|
||||
|
||||
## 0.0.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies [8cbd9bfd0566cbd7d86d8b40ea7d58d6ef382742]:</summary>
|
||||
|
||||
- @rocket.chat/models@1.7.2
|
||||
- @rocket.chat/core-services@0.10.5
|
||||
- @rocket.chat/omni-core@0.0.7
|
||||
</details>
|
||||
|
||||
## 0.0.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies []:</summary>
|
||||
|
||||
- @rocket.chat/core-services@0.10.4
|
||||
- @rocket.chat/models@1.7.1
|
||||
- @rocket.chat/omni-core@0.0.6
|
||||
</details>
|
||||
|
||||
## 0.0.6-rc.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies []:</summary>
|
||||
|
||||
- @rocket.chat/core-services@0.10.4-rc.4
|
||||
- @rocket.chat/models@1.7.1-rc.4
|
||||
- @rocket.chat/omni-core@0.0.6-rc.4
|
||||
</details>
|
||||
|
||||
## 0.0.6-rc.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies []:</summary>
|
||||
|
||||
- @rocket.chat/core-services@0.10.4-rc.3
|
||||
- @rocket.chat/models@1.7.1-rc.3
|
||||
- @rocket.chat/omni-core@0.0.6-rc.3
|
||||
</details>
|
||||
|
||||
## 0.0.6-rc.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies []:</summary>
|
||||
|
||||
- @rocket.chat/core-services@0.10.4-rc.2
|
||||
- @rocket.chat/models@1.7.1-rc.2
|
||||
- @rocket.chat/omni-core@0.0.6-rc.2
|
||||
</details>
|
||||
|
||||
## 0.0.6-rc.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies []:</summary>
|
||||
|
||||
- @rocket.chat/core-services@0.10.4-rc.1
|
||||
- @rocket.chat/models@1.7.1-rc.1
|
||||
- @rocket.chat/omni-core@0.0.6-rc.1
|
||||
</details>
|
||||
|
||||
## 0.0.6-rc.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies []:</summary>
|
||||
|
||||
- @rocket.chat/core-services@0.10.4-rc.0
|
||||
- @rocket.chat/models@1.7.1-rc.0
|
||||
- @rocket.chat/omni-core@0.0.6-rc.0
|
||||
</details>
|
||||
|
||||
## 0.0.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies [c102712222cc18c050f45f9279f8eafcff3e7e8a, 3e177dbd0b65d70bce8587287ba73b30170eb0f7, 3dfb557f723a395bc1e00f2647675968c46656bc]:</summary>
|
||||
|
||||
- @rocket.chat/models@1.7.0
|
||||
- @rocket.chat/core-services@0.10.3
|
||||
- @rocket.chat/omni-core@0.0.5
|
||||
</details>
|
||||
|
||||
## 0.0.5-rc.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies []:</summary>
|
||||
|
||||
- @rocket.chat/core-services@0.10.3-rc.7
|
||||
- @rocket.chat/models@1.7.0-rc.7
|
||||
- @rocket.chat/omni-core@0.0.5-rc.7
|
||||
</details>
|
||||
|
||||
## 0.0.5-rc.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies []:</summary>
|
||||
|
||||
- @rocket.chat/core-services@0.10.2-rc.6
|
||||
- @rocket.chat/models@1.7.0-rc.6
|
||||
- @rocket.chat/omni-core@0.0.4-rc.6
|
||||
</details>
|
||||
|
||||
## 0.0.4-rc.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies []:</summary>
|
||||
|
||||
- @rocket.chat/core-services@0.10.2-rc.5
|
||||
- @rocket.chat/models@1.7.0-rc.5
|
||||
- @rocket.chat/omni-core@0.0.4-rc.5
|
||||
</details>
|
||||
|
||||
## 0.0.4-rc.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies []:</summary>
|
||||
|
||||
- @rocket.chat/core-services@0.10.2-rc.4
|
||||
- @rocket.chat/models@1.7.0-rc.4
|
||||
- @rocket.chat/omni-core@0.0.4-rc.4
|
||||
</details>
|
||||
|
||||
## 0.0.4-rc.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies []:</summary>
|
||||
|
||||
- @rocket.chat/core-services@0.10.2-rc.3
|
||||
- @rocket.chat/models@1.7.0-rc.3
|
||||
- @rocket.chat/omni-core@0.0.4-rc.3
|
||||
</details>
|
||||
|
||||
## 0.0.4-rc.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies []:</summary>
|
||||
- @rocket.chat/core-services@0.10.1-rc.2
|
||||
- @rocket.chat/models@1.7.0-rc.2
|
||||
- @rocket.chat/omni-core@0.0.3-rc.2
|
||||
</details>
|
||||
|
||||
## 0.0.4-rc.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies []:</summary>
|
||||
|
||||
- @rocket.chat/core-services@0.10.1-rc.1
|
||||
- @rocket.chat/models@1.7.0-rc.1
|
||||
- @rocket.chat/omni-core@0.0.3-rc.1
|
||||
</details>
|
||||
|
||||
## 0.0.4-rc.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies [c102712222cc18c050f45f9279f8eafcff3e7e8a, 3e177dbd0b65d70bce8587287ba73b30170eb0f7, 3dfb557f723a395bc1e00f2647675968c46656bc]:</summary>
|
||||
|
||||
- @rocket.chat/models@1.7.0-rc.0
|
||||
- @rocket.chat/core-services@0.10.1-rc.0
|
||||
- @rocket.chat/omni-core@0.0.3-rc.0
|
||||
</details>
|
||||
|
||||
## 0.0.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies []:</summary>
|
||||
|
||||
- @rocket.chat/models@1.6.2
|
||||
- @rocket.chat/omni-core@0.0.4
|
||||
</details>
|
||||
|
||||
## 0.0.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies []:</summary>
|
||||
- @rocket.chat/models@1.6.1
|
||||
- @rocket.chat/omni-core@0.0.3
|
||||
</details>
|
||||
|
||||
## 0.0.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies [b25f05acd07762387fa45d67a1241b982c192f5d, fd32867fd4949bc2951a22075498ccb551cc6bbc, c7db598e9f3c2ad47f6a6be2a9ba7078533c245b]:</summary>
|
||||
|
||||
- @rocket.chat/models@1.6.0
|
||||
- @rocket.chat/omni-core@0.0.2
|
||||
</details>
|
||||
|
||||
## 0.0.2-rc.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies []:</summary>
|
||||
|
||||
- @rocket.chat/models@1.6.0-rc.6
|
||||
- @rocket.chat/omni-core@0.0.2-rc.6
|
||||
</details>
|
||||
|
||||
## 0.0.2-rc.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies []:</summary>
|
||||
|
||||
- @rocket.chat/models@1.6.0-rc.5
|
||||
- @rocket.chat/omni-core@0.0.2-rc.5
|
||||
</details>
|
||||
|
||||
## 0.0.2-rc.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies []:</summary>
|
||||
|
||||
- @rocket.chat/models@1.6.0-rc.4
|
||||
- @rocket.chat/omni-core@0.0.2-rc.4
|
||||
</details>
|
||||
|
||||
## 0.0.2-rc.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies []:</summary>
|
||||
|
||||
- @rocket.chat/models@1.6.0-rc.3
|
||||
- @rocket.chat/omni-core@0.0.2-rc.3
|
||||
</details>
|
||||
|
||||
## 0.0.2-rc.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies []:</summary>
|
||||
|
||||
- @rocket.chat/models@1.6.0-rc.2
|
||||
- @rocket.chat/omni-core@0.0.2-rc.2
|
||||
</details>
|
||||
|
||||
## 0.0.2-rc.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies []:</summary>
|
||||
|
||||
- @rocket.chat/models@1.6.0-rc.1
|
||||
- @rocket.chat/omni-core@0.0.2-rc.1
|
||||
</details>
|
||||
|
||||
## 0.0.2-rc.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- <details><summary>Updated dependencies [b25f05acd07762387fa45d67a1241b982c192f5d, fd32867fd4949bc2951a22075498ccb551cc6bbc, c7db598e9f3c2ad47f6a6be2a9ba7078533c245b]:</summary>
|
||||
|
||||
- @rocket.chat/models@1.6.0-rc.0
|
||||
- @rocket.chat/omni-core@0.0.2-rc.0
|
||||
</details>
|
||||
6
ee/packages/omni-core-ee/jest.config.ts
Normal file
6
ee/packages/omni-core-ee/jest.config.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import server from '@rocket.chat/jest-presets/server';
|
||||
import type { Config } from 'jest';
|
||||
|
||||
export default {
|
||||
preset: server.preset,
|
||||
} satisfies Config;
|
||||
38
ee/packages/omni-core-ee/package.json
Normal file
38
ee/packages/omni-core-ee/package.json
Normal file
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"name": "@rocket.chat/omni-core-ee",
|
||||
"version": "0.0.25",
|
||||
"private": true,
|
||||
"main": "./dist/index.js",
|
||||
"typings": "./dist/index.d.ts",
|
||||
"files": [
|
||||
"/dist"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "rm -rf dist && tsc -p tsconfig.json",
|
||||
"dev": "tsc -p tsconfig.json --watch --preserveWatchOutput",
|
||||
"lint": "eslint .",
|
||||
"lint:fix": "eslint --fix .",
|
||||
"test": "jest",
|
||||
"testunit": "jest",
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"dependencies": {
|
||||
"@rocket.chat/core-services": "workspace:^",
|
||||
"@rocket.chat/logger": "workspace:^",
|
||||
"@rocket.chat/models": "workspace:^",
|
||||
"@rocket.chat/omni-core": "workspace:^",
|
||||
"mem": "^8.1.1",
|
||||
"mongodb": "6.16.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rocket.chat/jest-presets": "workspace:~",
|
||||
"@rocket.chat/tsconfig": "workspace:*",
|
||||
"@types/jest": "~30.0.0",
|
||||
"eslint": "~9.39.5",
|
||||
"jest": "~30.2.0",
|
||||
"typescript": "~5.9.3"
|
||||
},
|
||||
"volta": {
|
||||
"extends": "../../../package.json"
|
||||
}
|
||||
}
|
||||
10
ee/packages/omni-core-ee/src/index.ts
Normal file
10
ee/packages/omni-core-ee/src/index.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { isDepartmentCreationAvailablePatch } from './isDepartmentCreationAvailable';
|
||||
import { applyDepartmentRestrictionsPatch } from './patches/applyDepartmentRestrictions';
|
||||
|
||||
export function patchOmniCore(): void {
|
||||
isDepartmentCreationAvailablePatch();
|
||||
applyDepartmentRestrictionsPatch();
|
||||
}
|
||||
|
||||
export * from './outbound-communication';
|
||||
export * from './units/getUnitsFromUser';
|
||||
@@ -0,0 +1,45 @@
|
||||
import { License, MockedLicenseBuilder } from '@rocket.chat/license';
|
||||
import type { ILivechatDepartmentModel } from '@rocket.chat/model-typings';
|
||||
import { registerModel } from '@rocket.chat/models';
|
||||
import { isDepartmentCreationAvailable } from '@rocket.chat/omni-core';
|
||||
|
||||
import { isDepartmentCreationAvailablePatch } from './isDepartmentCreationAvailable';
|
||||
|
||||
beforeEach(async () => {
|
||||
await License.setWorkspaceUrl('http://localhost:3000');
|
||||
|
||||
License.setLicenseLimitCounter('activeUsers', () => 0);
|
||||
License.setLicenseLimitCounter('guestUsers', () => 0);
|
||||
License.setLicenseLimitCounter('roomsPerGuest', async () => 0);
|
||||
License.setLicenseLimitCounter('privateApps', () => 0);
|
||||
License.setLicenseLimitCounter('marketplaceApps', () => 0);
|
||||
License.setLicenseLimitCounter('monthlyActiveContacts', async () => 0);
|
||||
|
||||
License.setLicenseLimitCounter('activeUsers', () => 1);
|
||||
});
|
||||
|
||||
beforeAll(async () => {
|
||||
isDepartmentCreationAvailablePatch();
|
||||
|
||||
registerModel('ILivechatDepartmentModel', { countTotal: () => 1 } as unknown as ILivechatDepartmentModel);
|
||||
});
|
||||
|
||||
it('should skip the check if Livechat Enterprise is enabled', async () => {
|
||||
const license = new MockedLicenseBuilder();
|
||||
license.withGrantedModules(['livechat-enterprise']);
|
||||
await License.setLicense(await license.sign());
|
||||
|
||||
const isAvailable = await isDepartmentCreationAvailable();
|
||||
|
||||
expect(isAvailable).toBe(true);
|
||||
});
|
||||
|
||||
it('should not skip the check if Livechat Enterprise is not enabled', async () => {
|
||||
const license = new MockedLicenseBuilder();
|
||||
license.withGrantedModules([]);
|
||||
await License.setLicense(await license.sign());
|
||||
|
||||
const isAvailable = await isDepartmentCreationAvailable();
|
||||
|
||||
expect(isAvailable).toBe(false);
|
||||
});
|
||||
@@ -0,0 +1,13 @@
|
||||
import { License } from '@rocket.chat/license';
|
||||
import { isDepartmentCreationAvailable } from '@rocket.chat/omni-core';
|
||||
|
||||
export function isDepartmentCreationAvailablePatch(): void {
|
||||
isDepartmentCreationAvailable.patch(async (next) => {
|
||||
// Skip the standard check when Livechat Enterprise is enabled, as it allows unlimited departments
|
||||
if (License.hasModule('livechat-enterprise')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return next();
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export * from './validators/canSendMessage';
|
||||
@@ -0,0 +1,190 @@
|
||||
import { Authorization } from '@rocket.chat/core-services';
|
||||
import { LivechatDepartment, LivechatDepartmentAgents, Users } from '@rocket.chat/models';
|
||||
|
||||
import { canSendOutboundMessage, validateAgentAssignPermissions } from './canSendMessage';
|
||||
|
||||
jest.mock('@rocket.chat/core-services', () => ({
|
||||
Authorization: {
|
||||
hasPermission: jest.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
jest.mock('@rocket.chat/models', () => ({
|
||||
LivechatDepartment: {
|
||||
findOne: jest.fn(),
|
||||
},
|
||||
LivechatDepartmentAgents: {
|
||||
findOneByAgentIdAndDepartmentId: jest.fn(),
|
||||
},
|
||||
Users: {
|
||||
findOneAgentById: jest.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
const hasPermissionMock = Authorization.hasPermission as unknown as jest.Mock<
|
||||
Promise<boolean>,
|
||||
[userId: string, permission: string, scope?: string]
|
||||
>;
|
||||
|
||||
const findDepartmentMock = LivechatDepartment.findOne as unknown as jest.Mock;
|
||||
const findDepartmentAgentMock = LivechatDepartmentAgents.findOneByAgentIdAndDepartmentId as unknown as jest.Mock;
|
||||
const findUserAgentMock = Users.findOneAgentById as unknown as jest.Mock;
|
||||
|
||||
const setPermissions = (map: Record<string, boolean>) => {
|
||||
hasPermissionMock.mockImplementation(async (_userId: string, permission: string) => {
|
||||
return Boolean(map[permission]);
|
||||
});
|
||||
};
|
||||
|
||||
describe('canSendOutboundMessage', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
// Default: no permissions granted
|
||||
setPermissions({});
|
||||
});
|
||||
|
||||
describe('when departmentId is provided', () => {
|
||||
test('resolves when user has assign-queues permission and department is enabled', async () => {
|
||||
setPermissions({ 'outbound.can-assign-queues': true });
|
||||
findDepartmentMock.mockResolvedValue({ _id: 'dep1', enabled: true });
|
||||
|
||||
await expect(canSendOutboundMessage('u1', undefined, 'dep1')).resolves.toBeUndefined();
|
||||
|
||||
// Should not need to check requester department membership
|
||||
expect(findDepartmentAgentMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('throws error-invalid-department when department is disabled', async () => {
|
||||
setPermissions({ 'outbound.can-assign-queues': true });
|
||||
findDepartmentMock.mockResolvedValue({ _id: 'dep1', enabled: false });
|
||||
|
||||
await expect(canSendOutboundMessage('u1', undefined, 'dep1')).rejects.toThrow('error-invalid-department');
|
||||
});
|
||||
|
||||
describe('and agentId is provided', () => {
|
||||
test('throws error-invalid-agent if user lacks any-agent and has self-only but agentId != userId', async () => {
|
||||
setPermissions({
|
||||
'outbound.can-assign-queues': true, // so it skips requester membership
|
||||
'outbound.can-assign-any-agent': false,
|
||||
'outbound.can-assign-self-only': true,
|
||||
});
|
||||
findDepartmentMock.mockResolvedValue({ _id: 'dep1', enabled: true });
|
||||
|
||||
await expect(canSendOutboundMessage('me', 'other', 'dep1')).rejects.toThrow('error-invalid-agent');
|
||||
|
||||
// Should not check selected agent membership after permission denial
|
||||
expect(findDepartmentAgentMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('throws error-agent-not-in-department if selected agent is not in the department (any-agent allowed)', async () => {
|
||||
setPermissions({
|
||||
'outbound.can-assign-queues': true,
|
||||
'outbound.can-assign-any-agent': true,
|
||||
});
|
||||
findDepartmentMock.mockResolvedValue({ _id: 'dep1', enabled: true });
|
||||
findDepartmentAgentMock.mockResolvedValueOnce(null); // selected agent not in department
|
||||
|
||||
await expect(canSendOutboundMessage('me', 'agentX', 'dep1')).rejects.toThrow('error-agent-not-in-department');
|
||||
|
||||
expect(findDepartmentAgentMock).toHaveBeenCalledWith('agentX', 'dep1', { projection: { _id: 1 } });
|
||||
});
|
||||
|
||||
test('resolves if selected agent is in the department (any-agent allowed)', async () => {
|
||||
setPermissions({
|
||||
'outbound.can-assign-queues': true,
|
||||
'outbound.can-assign-any-agent': true,
|
||||
});
|
||||
findDepartmentMock.mockResolvedValue({ _id: 'dep1', enabled: true });
|
||||
findDepartmentAgentMock.mockResolvedValueOnce({ _id: 'relX' });
|
||||
|
||||
await expect(canSendOutboundMessage('me', 'agentInDep', 'dep1')).resolves.toBeUndefined();
|
||||
});
|
||||
|
||||
test('throws error-agent-not-in-department when self-only is allowed and agentId == userId but agent is not in department', async () => {
|
||||
setPermissions({
|
||||
'outbound.can-assign-queues': true,
|
||||
'outbound.can-assign-any-agent': false,
|
||||
'outbound.can-assign-self-only': true,
|
||||
});
|
||||
findDepartmentMock.mockResolvedValue({ _id: 'dep1', enabled: true });
|
||||
findDepartmentAgentMock.mockResolvedValueOnce(null); // self not in department
|
||||
|
||||
await expect(canSendOutboundMessage('me', 'me', 'dep1')).rejects.toThrow('error-agent-not-in-department');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when departmentId is not provided and agentId is provided', () => {
|
||||
test('throws error-invalid-agent if user lacks any-agent and has self-only but agentId != userId', async () => {
|
||||
setPermissions({
|
||||
'outbound.can-assign-any-agent': false,
|
||||
'outbound.can-assign-self-only': true,
|
||||
});
|
||||
|
||||
await expect(canSendOutboundMessage('me', 'other')).rejects.toThrow('error-invalid-agent');
|
||||
|
||||
// Should not query Users if permission check fails
|
||||
expect(findUserAgentMock).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('throws error-invalid-agent if selected agent is not an agent (any-agent allowed)', async () => {
|
||||
setPermissions({
|
||||
'outbound.can-assign-any-agent': true,
|
||||
});
|
||||
findUserAgentMock.mockResolvedValueOnce(null);
|
||||
|
||||
await expect(canSendOutboundMessage('me', 'notAnAgent')).rejects.toThrow('error-invalid-agent');
|
||||
|
||||
expect(findUserAgentMock).toHaveBeenCalledWith('notAnAgent', { projection: { _id: 1 } });
|
||||
});
|
||||
|
||||
test('resolves if selected agent exists (any-agent allowed)', async () => {
|
||||
setPermissions({
|
||||
'outbound.can-assign-any-agent': true,
|
||||
});
|
||||
findUserAgentMock.mockResolvedValueOnce({ _id: 'agent1' });
|
||||
|
||||
await expect(canSendOutboundMessage('me', 'agent1')).resolves.toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
test('resolves when neither departmentId nor agentId are provided', async () => {
|
||||
await expect(canSendOutboundMessage('u1')).resolves.toBeUndefined();
|
||||
|
||||
expect(hasPermissionMock).not.toHaveBeenCalled();
|
||||
expect(findDepartmentMock).not.toHaveBeenCalled();
|
||||
expect(findDepartmentAgentMock).not.toHaveBeenCalled();
|
||||
expect(findUserAgentMock).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('validateAgentAssignPermissions', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
setPermissions({});
|
||||
});
|
||||
|
||||
test('resolves when user has any-agent permission', async () => {
|
||||
setPermissions({ 'outbound.can-assign-any-agent': true });
|
||||
|
||||
await expect(validateAgentAssignPermissions('u1', 'other')).resolves.toBeUndefined();
|
||||
});
|
||||
|
||||
test('resolves when user has self-only and agentId equals userId', async () => {
|
||||
setPermissions({ 'outbound.can-assign-self-only': true });
|
||||
|
||||
await expect(validateAgentAssignPermissions('me', 'me')).resolves.toBeUndefined();
|
||||
});
|
||||
|
||||
test('throws error-invalid-agent when self-only and agentId != userId', async () => {
|
||||
setPermissions({ 'outbound.can-assign-self-only': true });
|
||||
|
||||
await expect(validateAgentAssignPermissions('me', 'other')).rejects.toThrow('error-invalid-agent');
|
||||
});
|
||||
|
||||
test('throws error-invalid-agent when user lacks both permissions', async () => {
|
||||
setPermissions({});
|
||||
|
||||
await expect(validateAgentAssignPermissions('me', 'other')).rejects.toThrow('error-invalid-agent');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,53 @@
|
||||
import { Authorization } from '@rocket.chat/core-services';
|
||||
import type { ILivechatDepartment } from '@rocket.chat/core-typings';
|
||||
import { LivechatDepartment, LivechatDepartmentAgents, Users } from '@rocket.chat/models';
|
||||
import type { FilterOperators } from 'mongodb';
|
||||
|
||||
import { addQueryRestrictionsToDepartmentsModel } from '../../units/addRoleBasedRestrictionsToDepartment';
|
||||
|
||||
export async function validateAgentAssignPermissions(userId: string, agentId: string): Promise<void> {
|
||||
if (await Authorization.hasPermission(userId, 'outbound.can-assign-any-agent')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((await Authorization.hasPermission(userId, 'outbound.can-assign-self-only')) && agentId === userId) {
|
||||
return;
|
||||
}
|
||||
|
||||
throw new Error('error-invalid-agent');
|
||||
}
|
||||
|
||||
export async function canSendOutboundMessage(userId: string, agentId?: string, departmentId?: string): Promise<void> {
|
||||
// Case 1: Check department and check if agent is in department
|
||||
if (departmentId) {
|
||||
let query: FilterOperators<ILivechatDepartment> = { _id: departmentId };
|
||||
if (!(await Authorization.hasPermission(userId, 'outbound.can-assign-queues'))) {
|
||||
query = await addQueryRestrictionsToDepartmentsModel(query, userId);
|
||||
}
|
||||
|
||||
const department = await LivechatDepartment.findOne<Pick<ILivechatDepartment, '_id' | 'enabled'>>(query, {
|
||||
projection: { _id: 1, enabled: 1 },
|
||||
});
|
||||
if (!department?.enabled) {
|
||||
throw new Error('error-invalid-department');
|
||||
}
|
||||
|
||||
// Case 2: Agent & department: if agent is present, agent must be in department
|
||||
if (agentId) {
|
||||
await validateAgentAssignPermissions(userId, agentId);
|
||||
// On here, we take a shortcut: if the user is here, we assume it's an agent (and we assume the collection is kept up to date :) )
|
||||
const agent = await LivechatDepartmentAgents.findOneByAgentIdAndDepartmentId(agentId, departmentId, { projection: { _id: 1 } });
|
||||
if (!agent) {
|
||||
throw new Error('error-agent-not-in-department');
|
||||
}
|
||||
}
|
||||
// Case 3: Agent & no department: if agent is present and there's no department, agent must be an agent
|
||||
} else if (agentId) {
|
||||
await validateAgentAssignPermissions(userId, agentId);
|
||||
|
||||
const agent = await Users.findOneAgentById(agentId, { projection: { _id: 1 } });
|
||||
if (!agent) {
|
||||
throw new Error('error-invalid-agent');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import type { ILivechatDepartment } from '@rocket.chat/core-typings';
|
||||
import { License } from '@rocket.chat/license';
|
||||
import { applyDepartmentRestrictions } from '@rocket.chat/omni-core';
|
||||
import type { FilterOperators } from 'mongodb';
|
||||
|
||||
import { addQueryRestrictionsToDepartmentsModel } from '../units/addRoleBasedRestrictionsToDepartment';
|
||||
import { hooksLogger } from '../utils/logger';
|
||||
|
||||
export const applyDepartmentRestrictionsPatch = () => {
|
||||
applyDepartmentRestrictions.patch(
|
||||
async (
|
||||
prev: (query: FilterOperators<ILivechatDepartment>, userId: string) => FilterOperators<ILivechatDepartment>,
|
||||
query: FilterOperators<ILivechatDepartment> = {},
|
||||
userId: string,
|
||||
) => {
|
||||
if (!License.hasModule('livechat-enterprise')) {
|
||||
return prev(query, userId);
|
||||
}
|
||||
|
||||
hooksLogger.debug('Applying department query restrictions');
|
||||
return addQueryRestrictionsToDepartmentsModel(query, userId);
|
||||
},
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,297 @@
|
||||
import type { ILivechatDepartment } from '@rocket.chat/core-typings';
|
||||
import type { FilterOperators } from 'mongodb';
|
||||
|
||||
import { addQueryRestrictionsToDepartmentsModel } from './addRoleBasedRestrictionsToDepartment';
|
||||
import { getUnitsFromUser } from './getUnitsFromUser';
|
||||
import { defaultLogger } from '../utils/logger';
|
||||
|
||||
// Mock dependencies
|
||||
jest.mock('./getUnitsFromUser');
|
||||
jest.mock('../utils/logger');
|
||||
|
||||
const mockedGetUnitsFromUser = jest.mocked(getUnitsFromUser);
|
||||
const mockedLogger = jest.mocked(defaultLogger);
|
||||
|
||||
describe('addQueryRestrictionsToDepartmentsModel', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('when getUnitsFromUser returns an array of units', () => {
|
||||
it('should add unit restrictions to the query', async () => {
|
||||
// Arrange
|
||||
const userId = 'user123';
|
||||
const units = ['unit1', 'unit2', 'unit3'];
|
||||
const originalQuery: FilterOperators<ILivechatDepartment> = { name: 'test-department' };
|
||||
|
||||
mockedGetUnitsFromUser.mockResolvedValue(units);
|
||||
|
||||
// Act
|
||||
const result = await addQueryRestrictionsToDepartmentsModel(originalQuery, userId);
|
||||
|
||||
// Assert
|
||||
expect(result).toEqual({
|
||||
$and: [
|
||||
{ name: 'test-department' },
|
||||
{ type: { $ne: 'u' } },
|
||||
{
|
||||
$or: [{ ancestors: { $in: ['unit1', 'unit2', 'unit3'] } }, { _id: { $in: ['unit1', 'unit2', 'unit3'] } }],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
expect(mockedGetUnitsFromUser).toHaveBeenCalledWith(userId);
|
||||
expect(mockedLogger.debug).toHaveBeenCalledWith({
|
||||
msg: 'Applying department query restrictions',
|
||||
userId,
|
||||
units,
|
||||
});
|
||||
});
|
||||
|
||||
it('should work with empty original query', async () => {
|
||||
// Arrange
|
||||
const userId = 'user456';
|
||||
const units = ['unit4', 'unit5'];
|
||||
|
||||
mockedGetUnitsFromUser.mockResolvedValue(units);
|
||||
|
||||
// Act
|
||||
const result = await addQueryRestrictionsToDepartmentsModel({}, userId);
|
||||
|
||||
// Assert
|
||||
expect(result).toEqual({
|
||||
$and: [
|
||||
{},
|
||||
{ type: { $ne: 'u' } },
|
||||
{
|
||||
$or: [{ ancestors: { $in: ['unit4', 'unit5'] } }, { _id: { $in: ['unit4', 'unit5'] } }],
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('should work with undefined original query', async () => {
|
||||
// Arrange
|
||||
const userId = 'user789';
|
||||
const units = ['unit6'];
|
||||
|
||||
mockedGetUnitsFromUser.mockResolvedValue(units);
|
||||
|
||||
// Act
|
||||
const result = await addQueryRestrictionsToDepartmentsModel(undefined, userId);
|
||||
|
||||
// Assert
|
||||
expect(result).toEqual({
|
||||
$and: [
|
||||
{},
|
||||
{ type: { $ne: 'u' } },
|
||||
{
|
||||
$or: [{ ancestors: { $in: ['unit6'] } }, { _id: { $in: ['unit6'] } }],
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle single unit in array', async () => {
|
||||
// Arrange
|
||||
const userId = 'user101';
|
||||
const units = ['single-unit'];
|
||||
const originalQuery: FilterOperators<ILivechatDepartment> = { enabled: true };
|
||||
|
||||
mockedGetUnitsFromUser.mockResolvedValue(units);
|
||||
|
||||
// Act
|
||||
const result = await addQueryRestrictionsToDepartmentsModel(originalQuery, userId);
|
||||
|
||||
// Assert
|
||||
expect(result).toEqual({
|
||||
$and: [
|
||||
{ enabled: true },
|
||||
{ type: { $ne: 'u' } },
|
||||
{
|
||||
$or: [{ ancestors: { $in: ['single-unit'] } }, { _id: { $in: ['single-unit'] } }],
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when getUnitsFromUser returns non-array values', () => {
|
||||
it('should not add unit restrictions when getUnitsFromUser returns null', async () => {
|
||||
// Arrange
|
||||
const userId = 'user202';
|
||||
const originalQuery: FilterOperators<ILivechatDepartment> = { name: 'test' };
|
||||
|
||||
mockedGetUnitsFromUser.mockResolvedValue(undefined);
|
||||
|
||||
// Act
|
||||
const result = await addQueryRestrictionsToDepartmentsModel(originalQuery, userId);
|
||||
|
||||
// Assert
|
||||
expect(result).toEqual({
|
||||
$and: [{ name: 'test' }, { type: { $ne: 'u' } }],
|
||||
});
|
||||
|
||||
expect(mockedLogger.debug).toHaveBeenCalledWith({
|
||||
msg: 'Applying department query restrictions',
|
||||
userId,
|
||||
units: undefined,
|
||||
});
|
||||
});
|
||||
|
||||
it('should not add unit restrictions when getUnitsFromUser returns undefined', async () => {
|
||||
// Arrange
|
||||
const userId = 'user303';
|
||||
const originalQuery: FilterOperators<ILivechatDepartment> = { active: true };
|
||||
|
||||
mockedGetUnitsFromUser.mockResolvedValue(undefined);
|
||||
|
||||
// Act
|
||||
const result = await addQueryRestrictionsToDepartmentsModel(originalQuery, userId);
|
||||
|
||||
// Assert
|
||||
expect(result).toEqual({
|
||||
$and: [{ active: true }, { type: { $ne: 'u' } }],
|
||||
});
|
||||
|
||||
expect(mockedLogger.debug).toHaveBeenCalledWith({
|
||||
msg: 'Applying department query restrictions',
|
||||
userId,
|
||||
units: undefined,
|
||||
});
|
||||
});
|
||||
|
||||
it('should not add unit restrictions when getUnitsFromUser returns a string', async () => {
|
||||
// Arrange
|
||||
const userId = 'user404';
|
||||
const originalQuery: FilterOperators<ILivechatDepartment> = {};
|
||||
|
||||
mockedGetUnitsFromUser.mockResolvedValue('not-an-array' as any);
|
||||
|
||||
// Act
|
||||
const result = await addQueryRestrictionsToDepartmentsModel(originalQuery, userId);
|
||||
|
||||
// Assert
|
||||
expect(result).toEqual({
|
||||
$and: [{}, { type: { $ne: 'u' } }],
|
||||
});
|
||||
|
||||
expect(mockedLogger.debug).toHaveBeenCalledWith({
|
||||
msg: 'Applying department query restrictions',
|
||||
userId,
|
||||
units: 'not-an-array',
|
||||
});
|
||||
});
|
||||
|
||||
it('should not add unit restrictions when getUnitsFromUser returns empty array', async () => {
|
||||
// Arrange
|
||||
const userId = 'user505';
|
||||
const originalQuery: FilterOperators<ILivechatDepartment> = { department: 'support' };
|
||||
|
||||
mockedGetUnitsFromUser.mockResolvedValue([]);
|
||||
|
||||
// Act
|
||||
const result = await addQueryRestrictionsToDepartmentsModel(originalQuery, userId);
|
||||
|
||||
// Assert
|
||||
expect(result).toEqual({
|
||||
$and: [
|
||||
{ department: 'support' },
|
||||
{ type: { $ne: 'u' } },
|
||||
{
|
||||
$or: [{ ancestors: { $in: [] } }, { _id: { $in: [] } }],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
expect(mockedLogger.debug).toHaveBeenCalledWith({
|
||||
msg: 'Applying department query restrictions',
|
||||
userId,
|
||||
units: [],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('error handling', () => {
|
||||
it('should propagate errors from getUnitsFromUser', async () => {
|
||||
// Arrange
|
||||
const userId = 'user606';
|
||||
const error = new Error('Database connection failed');
|
||||
|
||||
mockedGetUnitsFromUser.mockRejectedValue(error);
|
||||
|
||||
// Act & Assert
|
||||
await expect(addQueryRestrictionsToDepartmentsModel({}, userId)).rejects.toThrow('Database connection failed');
|
||||
|
||||
expect(mockedGetUnitsFromUser).toHaveBeenCalledWith(userId);
|
||||
expect(mockedLogger.debug).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('complex query scenarios', () => {
|
||||
it('should handle complex original query with nested conditions', async () => {
|
||||
// Arrange
|
||||
const userId = 'user707';
|
||||
const units = ['unit-a', 'unit-b'];
|
||||
const originalQuery: FilterOperators<ILivechatDepartment> = {
|
||||
$or: [{ name: { $regex: 'support' } }, { enabled: true }],
|
||||
createdAt: { $gte: new Date('2023-01-01') },
|
||||
};
|
||||
|
||||
mockedGetUnitsFromUser.mockResolvedValue(units);
|
||||
|
||||
// Act
|
||||
const result = await addQueryRestrictionsToDepartmentsModel(originalQuery, userId);
|
||||
|
||||
// Assert
|
||||
expect(result).toEqual({
|
||||
$and: [
|
||||
{
|
||||
$or: [{ name: { $regex: 'support' } }, { enabled: true }],
|
||||
createdAt: { $gte: new Date('2023-01-01') },
|
||||
},
|
||||
{ type: { $ne: 'u' } },
|
||||
{
|
||||
$or: [{ ancestors: { $in: ['unit-a', 'unit-b'] } }, { _id: { $in: ['unit-a', 'unit-b'] } }],
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('should always exclude departments with type "u"', async () => {
|
||||
// Arrange
|
||||
const userId = 'user808';
|
||||
const units = ['unit-x'];
|
||||
const originalQuery: FilterOperators<ILivechatDepartment> = { type: 'normal' };
|
||||
|
||||
mockedGetUnitsFromUser.mockResolvedValue(units);
|
||||
|
||||
// Act
|
||||
const result = await addQueryRestrictionsToDepartmentsModel(originalQuery, userId);
|
||||
|
||||
// Assert
|
||||
expect(result.$and).toContainEqual({ type: { $ne: 'u' } });
|
||||
});
|
||||
});
|
||||
|
||||
describe('logging', () => {
|
||||
it('should always call debug logger with correct parameters', async () => {
|
||||
// Arrange
|
||||
const userId = 'user909';
|
||||
const units = ['unit-test'];
|
||||
|
||||
mockedGetUnitsFromUser.mockResolvedValue(units);
|
||||
|
||||
// Act
|
||||
await addQueryRestrictionsToDepartmentsModel({}, userId);
|
||||
|
||||
// Assert
|
||||
expect(mockedLogger.debug).toHaveBeenCalledTimes(1);
|
||||
expect(mockedLogger.debug).toHaveBeenCalledWith({
|
||||
msg: 'Applying department query restrictions',
|
||||
userId: 'user909',
|
||||
units: ['unit-test'],
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,17 @@
|
||||
import type { ILivechatDepartment } from '@rocket.chat/core-typings';
|
||||
import type { FilterOperators } from 'mongodb';
|
||||
|
||||
import { getUnitsFromUser } from './getUnitsFromUser';
|
||||
import { defaultLogger } from '../utils/logger';
|
||||
|
||||
export const addQueryRestrictionsToDepartmentsModel = async (originalQuery: FilterOperators<ILivechatDepartment> = {}, userId: string) => {
|
||||
const query: FilterOperators<ILivechatDepartment> = { $and: [originalQuery, { type: { $ne: 'u' } }] };
|
||||
|
||||
const units = await getUnitsFromUser(userId);
|
||||
if (Array.isArray(units)) {
|
||||
query.$and.push({ $or: [{ ancestors: { $in: units } }, { _id: { $in: units } }] });
|
||||
}
|
||||
|
||||
defaultLogger.debug({ msg: 'Applying department query restrictions', userId, units });
|
||||
return query;
|
||||
};
|
||||
230
ee/packages/omni-core-ee/src/units/getUnitsFromUser.spec.ts
Normal file
230
ee/packages/omni-core-ee/src/units/getUnitsFromUser.spec.ts
Normal file
@@ -0,0 +1,230 @@
|
||||
import { Authorization } from '@rocket.chat/core-services';
|
||||
import { LivechatUnit, LivechatDepartmentAgents } from '@rocket.chat/models';
|
||||
|
||||
import { getUnitsFromUser } from './getUnitsFromUser';
|
||||
import { defaultLogger } from '../utils/logger';
|
||||
|
||||
// Mock the dependencies
|
||||
jest.mock('@rocket.chat/core-services', () => ({
|
||||
Authorization: {
|
||||
hasAnyRole: jest.fn(),
|
||||
},
|
||||
}));
|
||||
jest.mock('@rocket.chat/models', () => ({
|
||||
LivechatUnit: {
|
||||
findByMonitorId: jest.fn(),
|
||||
countUnits: jest.fn(),
|
||||
},
|
||||
LivechatDepartmentAgents: {
|
||||
findByAgentId: jest.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
jest.mock('mem', () => (fn: any) => fn);
|
||||
jest.mock('../utils/logger');
|
||||
|
||||
const mockAuthorization = Authorization as jest.Mocked<typeof Authorization>;
|
||||
const mockLivechatUnit = LivechatUnit as jest.Mocked<typeof LivechatUnit>;
|
||||
const mockLivechatDepartmentAgents = LivechatDepartmentAgents as jest.Mocked<typeof LivechatDepartmentAgents>;
|
||||
const mockLogger = defaultLogger as jest.Mocked<typeof defaultLogger>;
|
||||
describe('getUnitsFromUser', () => {
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
|
||||
// Setup default mock implementations
|
||||
mockLivechatUnit.findByMonitorId.mockResolvedValue(['unit1', 'unit2']);
|
||||
mockLivechatDepartmentAgents.findByAgentId.mockReturnValue({
|
||||
toArray: jest.fn().mockResolvedValue([{ departmentId: 'dept1' }, { departmentId: 'dept2' }]),
|
||||
} as any);
|
||||
mockLivechatUnit.countUnits.mockResolvedValue(5);
|
||||
|
||||
mockAuthorization.hasAnyRole.mockResolvedValue(false);
|
||||
mockLogger.debug.mockImplementation(() => {
|
||||
//
|
||||
});
|
||||
});
|
||||
|
||||
describe('when userId is not provided', () => {
|
||||
it('should return undefined for null userId', async () => {
|
||||
const result = await getUnitsFromUser(null as any);
|
||||
expect(result).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should return undefined for undefined userId', async () => {
|
||||
const result = await getUnitsFromUser(undefined);
|
||||
expect(result).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should return undefined for empty string userId', async () => {
|
||||
const result = await getUnitsFromUser('');
|
||||
expect(result).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when there are no units in the system', () => {
|
||||
it('should return undefined', async () => {
|
||||
mockLivechatUnit.countUnits.mockResolvedValue(0);
|
||||
|
||||
const result = await getUnitsFromUser('user123');
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
expect(mockLivechatUnit.countUnits).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when user has admin role', () => {
|
||||
it('should return undefined for admin users', async () => {
|
||||
mockAuthorization.hasAnyRole
|
||||
.mockResolvedValueOnce(true) // admin/livechat-manager check
|
||||
.mockResolvedValueOnce(false); // livechat-monitor/agent check
|
||||
|
||||
const result = await getUnitsFromUser('admin-user');
|
||||
|
||||
expect(mockLivechatUnit.countUnits).toHaveBeenCalled();
|
||||
expect(result).toBeUndefined();
|
||||
expect(mockAuthorization.hasAnyRole).toHaveBeenCalledWith('admin-user', ['admin', 'livechat-manager']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when user does not have required roles', () => {
|
||||
it('should return undefined for users without livechat-monitor or livechat-agent roles', async () => {
|
||||
mockAuthorization.hasAnyRole
|
||||
.mockResolvedValueOnce(false) // admin/livechat-manager check
|
||||
.mockResolvedValueOnce(false); // livechat-monitor/agent check
|
||||
|
||||
const result = await getUnitsFromUser('regular-user');
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
expect(mockAuthorization.hasAnyRole).toHaveBeenCalledWith('regular-user', ['admin', 'livechat-manager']);
|
||||
expect(mockAuthorization.hasAnyRole).toHaveBeenCalledWith('regular-user', ['livechat-monitor', 'livechat-agent']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when user has livechat-manager role', () => {
|
||||
it('should return undefined for livechat-manager users', async () => {
|
||||
mockAuthorization.hasAnyRole
|
||||
.mockResolvedValueOnce(true) // admin/livechat-manager check
|
||||
.mockResolvedValueOnce(false); // livechat-monitor/agent check
|
||||
|
||||
const result = await getUnitsFromUser('manager-user');
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
expect(mockAuthorization.hasAnyRole).toHaveBeenCalledWith('manager-user', ['admin', 'livechat-manager']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when user has livechat-monitor role', () => {
|
||||
it('should return combined units and departments', async () => {
|
||||
const userId = 'monitor-user';
|
||||
mockAuthorization.hasAnyRole
|
||||
.mockResolvedValueOnce(false) // admin/livechat-manager check
|
||||
.mockResolvedValueOnce(true); // livechat-monitor/agent check
|
||||
|
||||
mockLivechatUnit.findByMonitorId.mockResolvedValue(['unit1', 'unit2']);
|
||||
mockLivechatDepartmentAgents.findByAgentId.mockReturnValue({
|
||||
toArray: jest.fn().mockResolvedValue([{ departmentId: 'dept1' }, { departmentId: 'dept2' }]),
|
||||
} as any);
|
||||
|
||||
const result = await getUnitsFromUser(userId);
|
||||
|
||||
expect(result).toEqual(['unit1', 'unit2', 'dept1', 'dept2']);
|
||||
expect(mockLivechatUnit.findByMonitorId).toHaveBeenCalledWith(userId);
|
||||
expect(mockLivechatDepartmentAgents.findByAgentId).toHaveBeenCalledWith(userId);
|
||||
expect(mockLogger.debug).toHaveBeenCalledWith({
|
||||
msg: 'Calculating units for monitor',
|
||||
user: userId,
|
||||
unitsAndDepartments: ['unit1', 'unit2', 'dept1', 'dept2'],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when user has livechat-agent role', () => {
|
||||
it('should return combined units and departments', async () => {
|
||||
const userId = 'agent-user';
|
||||
mockAuthorization.hasAnyRole
|
||||
.mockResolvedValueOnce(false) // admin/livechat-manager check
|
||||
.mockResolvedValueOnce(true); // livechat-monitor/agent check
|
||||
|
||||
mockLivechatUnit.findByMonitorId.mockResolvedValue(['unit3']);
|
||||
mockLivechatDepartmentAgents.findByAgentId.mockReturnValue({
|
||||
toArray: jest.fn().mockResolvedValue([{ departmentId: 'dept3' }, { departmentId: 'dept4' }]),
|
||||
} as any);
|
||||
|
||||
const result = await getUnitsFromUser(userId);
|
||||
|
||||
expect(result).toEqual(['unit3', 'dept3', 'dept4']);
|
||||
expect(mockLivechatUnit.findByMonitorId).toHaveBeenCalledWith(userId);
|
||||
expect(mockLivechatDepartmentAgents.findByAgentId).toHaveBeenCalledWith(userId);
|
||||
});
|
||||
});
|
||||
|
||||
describe('edge cases', () => {
|
||||
it('should handle empty units and departments arrays', async () => {
|
||||
const userId = 'empty-user';
|
||||
mockAuthorization.hasAnyRole
|
||||
.mockResolvedValueOnce(false) // admin/livechat-manager check
|
||||
.mockResolvedValueOnce(true); // livechat-monitor/agent check
|
||||
|
||||
mockLivechatUnit.findByMonitorId.mockResolvedValue([]);
|
||||
mockLivechatDepartmentAgents.findByAgentId.mockReturnValue({
|
||||
toArray: jest.fn().mockResolvedValue([]),
|
||||
} as any);
|
||||
|
||||
const result = await getUnitsFromUser(userId);
|
||||
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
|
||||
it('should handle when only units are returned', async () => {
|
||||
const userId = 'units-only-user';
|
||||
mockAuthorization.hasAnyRole
|
||||
.mockResolvedValueOnce(false) // admin/livechat-manager check
|
||||
.mockResolvedValueOnce(true); // livechat-monitor/agent check
|
||||
|
||||
mockLivechatUnit.findByMonitorId.mockResolvedValue(['unit1', 'unit2']);
|
||||
mockLivechatDepartmentAgents.findByAgentId.mockReturnValue({
|
||||
toArray: jest.fn().mockResolvedValue([]),
|
||||
} as any);
|
||||
|
||||
const result = await getUnitsFromUser(userId);
|
||||
|
||||
expect(result).toEqual(['unit1', 'unit2']);
|
||||
});
|
||||
|
||||
it('should handle when only departments are returned', async () => {
|
||||
const userId = 'departments-only-user';
|
||||
mockAuthorization.hasAnyRole
|
||||
.mockResolvedValueOnce(false) // admin/livechat-manager check
|
||||
.mockResolvedValueOnce(true); // livechat-monitor/agent check
|
||||
|
||||
mockLivechatUnit.findByMonitorId.mockResolvedValue([]);
|
||||
mockLivechatDepartmentAgents.findByAgentId.mockReturnValue({
|
||||
toArray: jest.fn().mockResolvedValue([{ departmentId: 'dept1' }, { departmentId: 'dept2' }]),
|
||||
} as any);
|
||||
|
||||
const result = await getUnitsFromUser(userId);
|
||||
|
||||
expect(result).toEqual(['dept1', 'dept2']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('memoization', () => {
|
||||
it('should work correctly with memoization disabled in tests', async () => {
|
||||
const userId = 'test-user';
|
||||
mockAuthorization.hasAnyRole
|
||||
.mockResolvedValueOnce(false) // admin/livechat-manager check
|
||||
.mockResolvedValueOnce(true); // livechat-monitor/agent check
|
||||
|
||||
mockLivechatUnit.findByMonitorId.mockResolvedValue(['unit1']);
|
||||
mockLivechatDepartmentAgents.findByAgentId.mockReturnValue({
|
||||
toArray: jest.fn().mockResolvedValue([{ departmentId: 'dept1' }]),
|
||||
} as any);
|
||||
|
||||
const result = await getUnitsFromUser(userId);
|
||||
|
||||
expect(result).toEqual(['unit1', 'dept1']);
|
||||
expect(mockLivechatUnit.findByMonitorId).toHaveBeenCalledWith(userId);
|
||||
expect(mockLivechatDepartmentAgents.findByAgentId).toHaveBeenCalledWith(userId);
|
||||
});
|
||||
});
|
||||
});
|
||||
48
ee/packages/omni-core-ee/src/units/getUnitsFromUser.ts
Normal file
48
ee/packages/omni-core-ee/src/units/getUnitsFromUser.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import { Authorization } from '@rocket.chat/core-services';
|
||||
import { LivechatUnit, LivechatDepartmentAgents } from '@rocket.chat/models';
|
||||
import mem from 'mem';
|
||||
|
||||
import { defaultLogger } from '../utils/logger';
|
||||
|
||||
async function getUnitsFromUserRoles(user: string): Promise<string[]> {
|
||||
return LivechatUnit.findByMonitorId(user);
|
||||
}
|
||||
|
||||
async function getDepartmentsFromUserRoles(user: string): Promise<string[]> {
|
||||
return (await LivechatDepartmentAgents.findByAgentId(user).toArray()).map((department) => department.departmentId);
|
||||
}
|
||||
|
||||
const memoizedGetUnitFromUserRoles = mem(getUnitsFromUserRoles, { maxAge: process.env.TEST_MODE ? 1 : 10000 });
|
||||
const memoizedGetDepartmentsFromUserRoles = mem(getDepartmentsFromUserRoles, { maxAge: process.env.TEST_MODE ? 1 : 10000 });
|
||||
|
||||
async function hasUnits(): Promise<boolean> {
|
||||
// @ts-expect-error - this prop is injected dynamically on ee license
|
||||
return (await LivechatUnit.countUnits({ type: 'u' })) > 0;
|
||||
}
|
||||
|
||||
// Units should't change really often, so we can cache the result
|
||||
const memoizedHasUnits = mem(hasUnits, { maxAge: process.env.TEST_MODE ? 1 : 10000 });
|
||||
|
||||
export const getUnitsFromUser = async (userId?: string): Promise<string[] | undefined> => {
|
||||
if (!userId) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(await memoizedHasUnits())) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: we can combine these 2 calls into one single query
|
||||
if (await Authorization.hasAnyRole(userId, ['admin', 'livechat-manager'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(await Authorization.hasAnyRole(userId, ['livechat-monitor', 'livechat-agent']))) {
|
||||
return;
|
||||
}
|
||||
|
||||
const unitsAndDepartments = [...(await memoizedGetUnitFromUserRoles(userId)), ...(await memoizedGetDepartmentsFromUserRoles(userId))];
|
||||
defaultLogger.debug({ msg: 'Calculating units for monitor', user: userId, unitsAndDepartments });
|
||||
|
||||
return unitsAndDepartments;
|
||||
};
|
||||
4
ee/packages/omni-core-ee/src/utils/logger.ts
Normal file
4
ee/packages/omni-core-ee/src/utils/logger.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
import { Logger } from '@rocket.chat/logger';
|
||||
|
||||
export const defaultLogger = new Logger('OmniCore-ee');
|
||||
export const hooksLogger = defaultLogger.section('hooks');
|
||||
9
ee/packages/omni-core-ee/tsconfig.json
Normal file
9
ee/packages/omni-core-ee/tsconfig.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"extends": "@rocket.chat/tsconfig/server.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src",
|
||||
"outDir": "./dist",
|
||||
"declaration": true
|
||||
},
|
||||
"include": ["./src/**/*"],
|
||||
}
|
||||
Reference in New Issue
Block a user