diff --git a/.docker/Dockerfile.rhel b/.docker/Dockerfile.rhel index 6f5a1a17722..d09083ca54f 100644 --- a/.docker/Dockerfile.rhel +++ b/.docker/Dockerfile.rhel @@ -1,6 +1,6 @@ FROM registry.access.redhat.com/rhscl/nodejs-8-rhel7 -ENV RC_VERSION 3.2.2 +ENV RC_VERSION 3.3.0-rc.4 MAINTAINER buildmaster@rocket.chat diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index dd85ed699b7..d6d6abd54ed 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -1,42 +1,253 @@ # Contributing to Rocket.Chat -:+1::tada: First off, thanks for taking the time to contribute! :tada::+1: +**First off, thanks for taking the time to contribute! :tada::+1:** -The following is a set of guidelines for contributing to Rocket.Chat and its packages, which are hosted in the [Rocket.Chat Organization](https://github.com/RocketChat) on GitHub. +> There are many ways to contribute to Rocket.Chat even if you're not technical or a developer: +> +> * Email us at marketing@rocket.chat to tell us how much you love the project +> * Write about us in your blogs +> * Fix some small typos in our [documentation](https://docs.rocket.chat/contributing) +> * Become our [GitHub sponsor](https://github.com/sponsors/RocketChat) +> * Tell others about us and help us spread the word +> +> Every bit of contribution is appreciated 🙂 thank you! + +The following is a set of guidelines for contributing to Rocket.Chat, which are hosted in the [Rocket.Chat Organization](https://github.com/RocketChat) on GitHub. __Note:__ If there's a feature you'd like, there's a bug you'd like to fix, or you'd just like to get involved please raise an issue and start a conversation. We'll help as much as we can so you can get contributing - although we may not always be able to respond right away :) -## ECMAScript 2015 vs CoffeeScript +## Setup + +Your development workstation needs to have at least 8GB or RAM to be able to build the Rocket.Chat's source code. + +Rocket.Chat runs on top of [Meteor](https://www.meteor.com/). To run it on development mode you need to [install Meteor](https://www.meteor.com/install) and clone/download the Rocket.Chat's code, then just open the code folder and run: +```shell +meteor npm install && meteor +``` +It should build and run the application and database for you, now you can access the UI on (http://localhost:3000) + +It's not necessary to install Nodejs or NPM, every time you need to use them you can run `meteor node` or `meteor npm`. + +It's important to always run the NPM commands using `meteor npm` to ensure that you are installing the modules using the right Nodejs version. + +## Coding + +We provide a [.editorconfig](../.editorconfig) file that will help you to keep some standards in place. + +### ECMAScript vs TypeScript + +We are currently adopting TypeScript as the default language on our projects, the current codebase will be migrated incrementally from JavaScript to TypeScript. + +While we still have a lot of JavaScript files you should not create new ones. As much as possible new code contributions should be in **TypeScript**. -While we still have a lot of CoffeeScript files you should not create new ones. New code contributions should be in **ECMAScript 2015**. +### Blaze vs React -## Coding standards +We are currently adopting React over Blaze as our UI engine, the current codebase is under migration and will continue. You will still find Blaze templates in our code. Code changes or contributions may need to be made in Blaze while we continue to evolve our components library. -Most of the coding standards are covered by `.editorconfig` and `.eslintrc.js`. +[Fuselage](https://github.com/RocketChat/Rocket.Chat.Fuselage) is our component library based on React, check it out when contributing to the Rocket.Chat UI and feel free to contribute new components or fixes. + +### Standards + +Most of the coding standards are covered by ESLint configured at [.eslintrc](../.eslintrc), and most of them came from our own [ESLint Config Package](https://github.com/RocketChat/eslint-config-rocketchat). Things not covered by `eslint`: -* `exports`/`module.exports` should be at the end of the file -* Longer, descriptive variable names are preferred, e.g. `error` vs `err` +* Prefer longer/descriptive variable names, e.g. `error` vs `err`, unless dealing with common record properties already shortened, e.g. `rid` and `uid` +* Use return early pattern. [See more](https://blog.timoxley.com/post/47041269194/avoid-else-return-early) +* Prefer `Promise` over `callbacks` +* Prefer `await` over `then/catch` +* Don't create queries outside models, the query description should be inside the model class. +* Don't hardcode fields inside models. Same method can be used for different purposes, using different fields. +* Prefer create REST endpoints over Meteor methods +* Prefer call REST endpoints over Meteor methods when both are available +* v1 REST endpoints should follow the following pattern: `/api/v1/dashed-namespace.camelCaseAction` +* Prefer TypeScript over JavaScript. Check [ECMAScript vs TypeScript](#ecmascript-vs-typescript) -We acknowledge all the code does not meet these standards but we are working to change this over time. +#### Blaze +* Import the HTML file from it's sibling JS/TS file ### Syntax check Before submitting a PR you should get no errors on `eslint`. -To check your files, first install `eslint`: +To check your files run: + +```shell +meteor npm run lint +``` + +## Tests + +There are 2 types of tests we run on Rocket.Chat, **Unit** tests and **End to End** tests. The major difference is that End to End tests require a Rocket.Chat instance running to execute the API and UI checks. + +### End to End Tests + +First you need to run a Rocket.Chat server on **Test Mode** and on a **Empty Database**: +```shell +# Running with a local mongodb database +MONGO_URL=mongodb://localhost/empty MONGO_OPLOG_URL=mongodb://localhost/local TEST_MODE=true meteor +``` +```shell +# Running with a local mongodb database but cleaning it before +mongo --eval "db.dropDatabase()" empty && MONGO_URL=mongodb://localhost/empty MONGO_OPLOG_URL=mongodb://localhost/local TEST_MODE=true meteor +``` + +Now you can run the tests: +```shell +meteor npm test +``` + +### Unit Tests + +Unit tests are simpler to setup and run. They do not require a working Rocket.Chat instance. +```shell +meteor npm run testunit +``` + +It's possible to run on watch mode as well: +```shell +meteor npm run testunit-watch +``` + + + +## Before Push your code + +It's important to run the lint and tests before push your code or submit a Pull Request, otherwise your contribution may fail quickly on the CI. Reviewers are forced to demand fixes and the review of your contribution will be further delayed. + +Rocket.Chat uses [husky](https://www.npmjs.com/package/husky) to run the **lint** and **unit tests** before proceed to the code push process, so you may notice a delay when pushing your code to your repository. + +## Choosing a good PR title + +It is very important to note that we use PR titles when creating our change log. Keep this in mind when you title your PR. Make sure the title makes sense to a person reading a releases' change log! + +Keep your PR's title as short and concise as possible, use PR's description section, which you can find in the PR's template, to provide more details into the changelog. + +Good titles require thinking from a user's point of view. Don't get technical and talk code or architecture. What is the actual user-facing feature or the bug fixed? For example: + +``` +[NEW] Allow search permissions and settings by name instead of only ID +``` + +Even it's being something new in the code the users already expect the filter to filter by what they see (translations), a better one would be: + +``` +[FIX] Permissions' search doesn't filter base on presented translation, only on internal ids +``` + +## Choosing the right PR tag + +You can use several tags do describe your PR, i.e.: `[FIX]`, `[NEW]`, etc. You can use the descriptions below to better understand the meaning of each one, and decide which one you should use: + +### `[NEW]` + +#### When +- When adding a new feature that is important to the end user + +#### How + +Do not start repeating the section (`Add ...` or `New ...`) +Always describe what's being fixed, improved or added and not *how* it was fixed, improved or added. + +Exemple of **bad** PR titles: + +``` +[NEW] Add ability to set tags in the Omnichannel room closing dialog +[NEW] Adds ability for Rocket.Chat Apps to create discussions +[NEW] Add MMS support to Voxtelesys +[NEW] Add Color variable to left sidebar +``` + +Exemple of **good** PR titles: ``` -npm install -g eslint +[NEW] Ability to set tags in the Omnichannel room closing dialog +[NEW] Ability for Rocket.Chat Apps to create discussions +[NEW] MMS support to Voxtelesys +[NEW] Color variable to left sidebar ``` -Then run: +### `[FIX]` + +#### When +- When fixing something not working or behaving wrong from the end user perspective + +#### How + +Always describe what's being fixed and not *how* it was fixed. + +Exemple of a **bad** PR title: ``` -eslint . +[FIX] Add Content-Type for public files with JWT ``` -# Contributor License Agreement +Exemple of a **good** PR title: + +``` +[FIX] Missing Content-Type header for public files with JWT +``` + +### `[IMPROVE]` + +#### When +- When a change enhances a not buggy behavior. When in doubt if it's a Improve or Fix prefer to use as fix. + +#### How +Always describe what's being improved and not *how* it was improved. + +Exemple of **good** PR title: + +``` +[IMPROVE] Displays Nothing found on admin sidebar when search returns nothing +``` + +### `[BREAK]` + +#### When +- When the changes affect a working feature + +##### Back-End +- When the API contract (data structure and endpoints) are limited, expanded as required or removed +- When the business logic (permissions and roles) are limited, expanded (without migration) or removed + +##### Front-End +- When the change limits (format, size, etc) or removes the ability of read or change the data (when the limitation was not caused by the back-end) + +### Second tag e.g. `[NEW][ENTERPRISE]` + +Use a second tag to group entries on the change log, we currently use it only for the Enterprise items but we are going to expand it's usage soon, please do not use it until we create a patter for it. + +### Minor Changes + +For those PRs that aren't important for the end user, we are working on a better pattern, but for now please use the same tags, use them without the brackets and in camel case: + +``` +Fix: Missing Content-Type header for public files with JWT +``` + +All those PRs will be grouped under the `Minor changes` section which is collapsed, so users can expand it to check for those minor things but they are not visible directly on changelog. + +## Security Best Practices + +- Never expose unnecessary data to the APIs' responses +- Always check for permissions or create new ones when you must expose sensitive data +- Never provide new APIs without rate limiters +- Always escape the user's input when rendering data +- Always limit the user's input size on server side +- Always execute the validations on the server side even when executing on the client side as well + +## Performance Best Practices + +- Prefer inform the fields you want, and only the necessary ones, when querying data from database over query the full documents +- Limit the number of returned records to a reasonable value +- Check if the query is using indexes, it it's not create new indexes +- Prefer queues over long executions +- Create new metrics to mesure things whenever possible +- Cache data and returns whenever possible + +## Contributor License Agreement + +To have your contribution accepted you must sign our [Contributor License Agreement](https://cla-assistant.io/RocketChat/Rocket.Chat). In case you submit a Pull Request before sign the CLA GitHub will alert you with a new comment asking you to sign and will block the Pull Request from be merged by us. Please review and sign our CLA at https://cla-assistant.io/RocketChat/Rocket.Chat diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index db905f2f947..b7ce1a78525 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,11 +1,46 @@ - + + - -Closes #ISSUE_NUMBER +## Proposed changes + - +## Issue(s) + + +## How to test or reproduce + + +## Screenshots + +## Types of changes + + + +- [ ] Bugfix (non-breaking change which fixes an issue) +- [ ] Improvement (non-breaking change which improves a current function) +- [ ] New feature (non-breaking change which adds functionality) +- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) +- [ ] Hotfix (a major bugfix that has to be merged asap) +- [ ] Documentation Update (if none of the other choices apply) + +## Checklist + + +- [ ] I have read the [CONTRIBUTING](https://github.com/RocketChat/Rocket.Chat/blob/develop/.github/CONTRIBUTING.md#contributing-to-rocketchat) doc +- [ ] I have signed the [CLA](https://cla-assistant.io/RocketChat/Rocket.Chat) +- [ ] Lint and unit tests pass locally with my changes +- [ ] I have added tests that prove my fix is effective or that my feature works (if applicable) +- [ ] I have added necessary documentation (if applicable) +- [ ] Any dependent changes have been merged and published in downstream modules + +## Changelog + + + + +## Further comments + - diff --git a/.github/history.json b/.github/history.json index 0eac3ce47c8..2d54ae97943 100644 --- a/.github/history.json +++ b/.github/history.json @@ -43321,6 +43321,13 @@ ] }, "3.2.0-rc.2": { + "node_version": "12.16.1", + "npm_version": "6.13.4", + "mongo_versions": [ + "3.4", + "3.6", + "4.0" + ], "pull_requests": [ { "pr": "17453", @@ -43406,6 +43413,13 @@ ] }, "3.1.2": { + "node_version": "12.16.1", + "npm_version": "6.13.4", + "mongo_versions": [ + "3.4", + "3.6", + "4.0" + ], "pull_requests": [ { "pr": "17454", @@ -43513,6 +43527,13 @@ ] }, "3.2.0": { + "node_version": "12.16.1", + "npm_version": "6.13.4", + "mongo_versions": [ + "3.4", + "3.6", + "4.0" + ], "pull_requests": [ { "pr": "17454", @@ -43619,21 +43640,28 @@ } ] }, - "3.2.1": { + "2.4.12": { + "node_version": "8.17.0", + "npm_version": "6.13.4", + "mongo_versions": [ + "3.4", + "3.6", + "4.0" + ], "pull_requests": [ { - "pr": "17497", - "title": "[FIX] LDAP login error on Enterprise version", - "userLogin": "pierre-lehnen-rc", - "milestone": "3.2.1", + "pr": "17578", + "title": "[FIX] Email configs not updating after setting changes", + "userLogin": "rodrigok", + "milestone": "3.2.2", "contributors": [ - "pierre-lehnen-rc" + "rodrigok" ] } ] }, - "2.4.12": { - "node_version": "8.17.0", + "3.0.13": { + "node_version": "12.14.0", "npm_version": "6.13.4", "mongo_versions": [ "3.4", @@ -43652,7 +43680,7 @@ } ] }, - "3.2.2": { + "3.1.3": { "node_version": "12.16.1", "npm_version": "6.13.4", "mongo_versions": [ @@ -43662,73 +43690,1271 @@ ], "pull_requests": [ { - "pr": "17582", - "title": "[FIX] Push settings enabled when push gateway is selected", - "userLogin": "geekgonecrazy", + "pr": "17578", + "title": "[FIX] Email configs not updating after setting changes", + "userLogin": "rodrigok", "milestone": "3.2.2", "contributors": [ - "geekgonecrazy", + "rodrigok" + ] + } + ] + }, + "3.3.0-rc.0": { + "node_version": "12.16.1", + "npm_version": "6.14.0", + "mongo_versions": [ + "3.4", + "3.6", + "4.0" + ], + "pull_requests": [ + { + "pr": "16537", + "title": "[FIX] Missing dropdown to select custom status color on user's profile", + "userLogin": "ritwizsinha", + "milestone": "3.3.0", + "contributors": [ + "ritwizsinha", + "gabriellsh", + "ggazzo" + ] + }, + { + "pr": "16331", + "title": "[FIX] Password reset/change accepting current password as new password", + "userLogin": "ashwaniYDV", + "milestone": "3.3.0", + "contributors": [ + "ashwaniYDV", + "sampaiodiego", + "web-flow" + ] + }, + { + "pr": "17692", + "title": "[NEW][ENTERPRISE] Support Omnichannel conversations auditing", + "userLogin": "renatobecker", + "milestone": "3.3.0", + "contributors": [ + "renatobecker", "web-flow", - "sampaiodiego" + "rodrigok" ] }, { - "pr": "17508", - "title": "[FIX] LDAP login on Enteprise Version", - "userLogin": "pierre-lehnen-rc", - "milestone": "3.2.2", + "pr": "17710", + "title": "Upgrade Livechat Widget version to 1.5.0", + "userLogin": "renatobecker", + "milestone": "3.3.0", "contributors": [ - "pierre-lehnen-rc" + "renatobecker" ] }, { - "pr": "17579", - "title": "[FIX] Login Forbidden on servers that had LDAP enabled in the past", - "userLogin": "pierre-lehnen-rc", - "milestone": "3.2.2", + "pr": "16548", + "title": "[FIX] Can't click on room's actions menu of sidebar list when in search mode", + "userLogin": "ritvikjain99", + "milestone": "3.3.0", "contributors": [ - "pierre-lehnen-rc" + "ritvikjain99" ] }, { - "pr": "17578", - "title": "[FIX] Email configs not updating after setting changes", - "userLogin": "rodrigok", - "milestone": "3.2.2", + "pr": "17581", + "title": "[NEW][ENTERPRISE] Support for custom Livechat registration form fields", + "userLogin": "renatobecker", + "milestone": "3.3.0", + "contributors": [ + "renatobecker", + "web-flow", + "ggazzo" + ] + }, + { + "pr": "17708", + "title": "Update Fuselage version", + "userLogin": "ggazzo", + "contributors": [ + "ggazzo" + ] + }, + { + "pr": "17666", + "title": "[NEW][ENTERPRISE] Omnichannel Last-Chatted Agent Preferred option", + "userLogin": "renatobecker", + "description": "If activated, this feature will store the last agent that assisted each Omnichannel visitor when a conversation is taken. So, when a visitor returns(it works with any entry point, Livechat, Facebook, REST API, and so on) and starts a new chat, the routing system checks:\r\n\r\n1 - The visitor object for any stored agent that the visitor has previously talked to;\r\n2 - If a previous agent is not found, the system will try to find a previous conversation of the same visitor. If a room is found, the system will get the previous agent from the room;\r\n\r\nAfter this process, if an agent has been found, the system will check the agent's availability to assist the new chat. If it's not available, then the routing system will get the next available agent in the queue.", + "milestone": "3.3.0", + "contributors": [ + "renatobecker", + "web-flow" + ] + }, + { + "pr": "17707", + "title": "Regression: Status presence color", + "userLogin": "mariaeduardacunha", + "contributors": [ + "ggazzo", + "mariaeduardacunha" + ] + }, + { + "pr": "17607", + "title": "Improve: Remove index files from action-links, accounts and assets", + "userLogin": "MarcosSpessatto", + "milestone": "3.3.0", "contributors": [ + "MarcosSpessatto", + "web-flow", "rodrigok" ] }, { - "pr": "17577", - "title": "[FIX] Error during data export for DMs", - "userLogin": "mtmr0x", - "milestone": "3.2.2", + "pr": "15737", + "title": "[FIX] Remove a non working setting \"Notification Duration\"", + "userLogin": "pierre-lehnen-rc", + "milestone": "3.3.0", "contributors": [ - "mtmr0x" + "pierre-lehnen-rc", + "rodrigok", + "web-flow" ] }, { - "pr": "17570", - "title": "[FIX] Emoji picker search broken", - "userLogin": "ggazzo", - "milestone": "3.2.2", + "pr": "17706", + "title": "Update Apps-Engine version", + "userLogin": "d-gubert", + "milestone": "3.3.0", + "contributors": [ + "d-gubert", + "web-flow" + ] + }, + { + "pr": "17705", + "title": "Regression: Click to join button not working", + "userLogin": "gabriellsh", + "contributors": [ + "gabriellsh" + ] + }, + { + "pr": "16394", + "title": "[IMPROVE] Always shows the exact match first on user's and room's autocomplete for mentions and on sidebar search", + "userLogin": "gabriellsh", + "milestone": "3.3.0", + "contributors": [ + "gabriellsh" + ] + }, + { + "pr": "17694", + "title": "[NEW] API endpoint to fetch Omnichannel's room transfer history", + "userLogin": "renatobecker", + "milestone": "3.3.0", + "contributors": [ + "renatobecker" + ] + }, + { + "pr": "17498", + "title": "Fix typo \"You aren't part of any channel yet\"", + "userLogin": "huzaifahj", + "milestone": "3.3.0", + "contributors": [ + "huzaifahj", + "web-flow" + ] + }, + { + "pr": "17701", + "title": "[IMPROVE] Display status information in the Omnichannel Agents list", + "userLogin": "renatobecker", + "milestone": "3.3.0", + "contributors": [ + "renatobecker" + ] + }, + { + "pr": "17619", + "title": "[NEW] Option to remove users from RocketChat if not found in Crowd", + "userLogin": "ocanema", + "contributors": [ + "ocanema" + ] + }, + { + "pr": "17129", + "title": "[FIX] Elements of \"Personal Access Tokens\" section out of alignment and unusable on very small screens", + "userLogin": "Nikhil713", + "milestone": "3.3.0", + "contributors": [ + "Nikhil713", + "engelgabriel", + "web-flow" + ] + }, + { + "pr": "17702", + "title": "Regression: Integrations edit/history crashing", + "userLogin": "gabriellsh", + "contributors": [ + "gabriellsh", + "web-flow" + ] + }, + { + "pr": "17687", + "title": "[FIX] Allow owners to react inside broadcast channels", + "userLogin": "mariaeduardacunha", + "milestone": "3.3.0", "contributors": [ + "mariaeduardacunha", "ggazzo", "web-flow" ] }, { - "pr": "17536", - "title": "[FIX] Reactions may present empty names of who reacted when using Real Names", + "pr": "17699", + "title": "Regression: User edit form missing fields", + "userLogin": "ggazzo", + "milestone": "3.3.0", + "contributors": [ + "ggazzo" + ] + }, + { + "pr": "17522", + "title": "[FIX] Default filters on Omnichannel Current Chats screen not showing on first load", + "userLogin": "renatobecker", + "milestone": "3.3.0", + "contributors": [ + "renatobecker" + ] + }, + { + "pr": "17700", + "title": "Regression: Fix error when performing Omnichannel queue checking", + "userLogin": "renatobecker", + "milestone": "3.3.0", + "contributors": [ + "renatobecker", + "web-flow" + ] + }, + { + "pr": "17697", + "title": "[FIX] UI KIT Modal Width", + "userLogin": "ggazzo", + "milestone": "3.3.0", + "contributors": [ + "ggazzo" + ] + }, + { + "pr": "17653", + "title": "Update Contributing Guide", "userLogin": "rodrigok", - "description": "When changing usernames the reactions became outdated since it's not possible to update the usernames stored there, so when the server users Real Name setting enabled the system process all messages before return to the clients and get the names of the usernames to show since the usernames are outdated the names will not be found. Now the usernames will be displayed when the name can't be found as a temporary fix until we change the architecture of the data to fix the issue.", - "milestone": "3.2.2", + "milestone": "3.3.0", "contributors": [ - "rodrigok" + "rodrigok", + "web-flow" + ] + }, + { + "pr": "17693", + "title": "LingoHub based on develop", + "userLogin": "engelgabriel", + "contributors": [ + "sampaiodiego", + "web-flow" + ] + }, + { + "pr": "17681", + "title": "[NEW] Added custom fields to Add/Edit user", + "userLogin": "gabriellsh", + "milestone": "3.3.0", + "contributors": [ + "gabriellsh", + "ggazzo", + "web-flow" + ] + }, + { + "pr": "17695", + "title": "Regression: Fix incorrect imports of the Apps-Engine", + "userLogin": "d-gubert", + "contributors": [ + "d-gubert" + ] + }, + { + "pr": "17654", + "title": "Improve: Remove uncessary RegExp query by email", + "userLogin": "rodrigok", + "milestone": "3.3.0", + "contributors": [ + "rodrigok" + ] + }, + { + "pr": "17487", + "title": "[NEW] [Apps-Engine] New Room events", + "userLogin": "d-gubert", + "contributors": [ + "d-gubert", + "web-flow" + ] + }, + { + "pr": "16665", + "title": "[IMPROVE] Add env var to configure Chatpal URL and remove it from beta", + "userLogin": "tkurz", + "contributors": [ + "tkurz", + "web-flow" + ] + }, + { + "pr": "17683", + "title": "Regression: Set retryWrites=false as default Mongo options", + "userLogin": "sampaiodiego", + "milestone": "3.3.0", + "contributors": [ + "sampaiodiego" + ] + }, + { + "pr": "17640", + "title": "[FIX] Agent's custom fields being leaked through the Livechat configuration endpoint", + "userLogin": "renatobecker", + "milestone": "3.3.0", + "contributors": [ + "renatobecker", + "web-flow" + ] + }, + { + "pr": "17675", + "title": "[FIX] Avatar url provider ignoring subfolders", + "userLogin": "ggazzo", + "milestone": "3.3.0", + "contributors": [ + "ggazzo" + ] + }, + { + "pr": "17680", + "title": "[IMPROVE] Added divider between tables and paginations", + "userLogin": "ggazzo", + "milestone": "3.3.0", + "contributors": [ + "ggazzo", + "web-flow" + ] + }, + { + "pr": "17685", + "title": "[IMPROVE] Starred Messages", + "userLogin": "gabriellsh", + "milestone": "3.3.0", + "contributors": [ + "gabriellsh" + ] + }, + { + "pr": "17684", + "title": "Regression: status-color-online", + "userLogin": "ggazzo", + "contributors": [ + "ggazzo" + ] + }, + { + "pr": "17611", + "title": "Add snapcraft files to be bumped with Houston", + "userLogin": "geekgonecrazy", + "milestone": "3.3.0", + "contributors": [ + "geekgonecrazy", + "web-flow", + "sampaiodiego" + ] + }, + { + "pr": "17661", + "title": "[FIX] Queued Omnichannel webhook being triggered unnecessarily", + "userLogin": "renatobecker", + "milestone": "3.3.0", + "contributors": [ + "renatobecker", + "web-flow" + ] + }, + { + "pr": "17667", + "title": "Regression: Outgoing List", + "userLogin": "ggazzo", + "contributors": [ + "ggazzo" + ] + }, + { + "pr": "17664", + "title": "[FIX] Not redirecting to `First Channel After Login` on register", + "userLogin": "gabriellsh", + "contributors": [ + "gabriellsh", + "ggazzo" + ] + }, + { + "pr": "17663", + "title": "Regression: Pressing enter on search reloads the page - admin pages", + "userLogin": "gabriellsh", + "contributors": [ + "gabriellsh" + ] + }, + { + "pr": "17551", + "title": "[NEW] Admin refactor Second phase", + "userLogin": "ggazzo", + "contributors": [ + "tassoevan", + "web-flow", + "gabriellsh", + "ggazzo" + ] + }, + { + "pr": "17554", + "title": "[IMPROVE] Unused styles", + "userLogin": "tassoevan", + "milestone": "3.3.0", + "contributors": [ + "tassoevan", + "web-flow" + ] + }, + { + "pr": "17652", + "title": "[FIX] Directory search user placeholder", + "userLogin": "zdumitru", + "contributors": [ + "zdumitru", + "web-flow" + ] + }, + { + "pr": "16250", + "title": "[NEW] Added \"Add custom emoji\" link to emoji picker", + "userLogin": "gabriellsh", + "milestone": "3.3.0", + "contributors": [ + "gabriellsh", + "web-flow", + "ggazzo" + ] + }, + { + "pr": "17644", + "title": "[FIX] Marketplace tiered pricing plan wording", + "userLogin": "geekgonecrazy", + "milestone": "3.3.0", + "contributors": [ + "geekgonecrazy", + "web-flow" + ] + }, + { + "pr": "17618", + "title": "[FIX] Secret Registration not properly validating Invite Token", + "userLogin": "pierre-lehnen-rc", + "milestone": "3.3.0", + "contributors": [ + "pierre-lehnen-rc" + ] + }, + { + "pr": "16968", + "title": "Improve: New PR Template", + "userLogin": "regalstreak", + "contributors": [ + "regalstreak", + "rodrigok", + "web-flow" + ] + }, + { + "pr": "17403", + "title": "Add engine versions for houston with templates", + "userLogin": "rodrigok", + "contributors": [ + "rodrigok", + "sampaiodiego", + "web-flow" + ] + }, + { + "pr": "16480", + "title": "Use Users.findOneByAppId instead of querying directly", + "userLogin": "lolimay", + "contributors": [ + "lolimay", + "d-gubert", + "web-flow" + ] + }, + { + "pr": "17587", + "title": "Remove unnecessary setting redefinition", + "userLogin": "rodrigok", + "milestone": "3.3.0", + "contributors": [ + "rodrigok" + ] + }, + { + "pr": "17586", + "title": "Deprecate compatibility cordova setting", + "userLogin": "rodrigok", + "milestone": "3.3.0", + "contributors": [ + "rodrigok" + ] + }, + { + "pr": "17622", + "title": "[FIX] Hyper.sh went out of business in early 2019", + "userLogin": "fbartels", + "contributors": [ + "fbartels", + "geekgonecrazy", + "web-flow" + ] + }, + { + "pr": "17580", + "title": "[NEW] Add Permissions to deal with Omnichannel visitor past chats history", + "userLogin": "MarcosSpessatto", + "milestone": "3.3.0", + "contributors": [ + "MarcosSpessatto", + "web-flow" + ] + }, + { + "pr": "17567", + "title": "[NEW] Add permissions to deal with Omnichannel custom fields", + "userLogin": "MarcosSpessatto", + "milestone": "3.3.0", + "contributors": [ + "MarcosSpessatto", + "renatobecker", + "web-flow" + ] + }, + { + "pr": "9956", + "title": "Livechat iframe allow microphone and camera", + "userLogin": "kolorafa", + "milestone": "3.3.0", + "contributors": [ + "kolorafa", + "web-flow", + "ggazzo" + ] + }, + { + "pr": "15642", + "title": "[FIX] Do not allow passwords on private channels", + "userLogin": "MartinSchoeler", + "milestone": "3.3.0", + "contributors": [ + "MartinSchoeler" + ] + }, + { + "pr": "17625", + "title": "[FIX] Mail Messages > Cannot mail own user", + "userLogin": "gabriellsh", + "milestone": "3.3.0", + "contributors": [ + "gabriellsh" + ] + }, + { + "pr": "17514", + "title": "[FIX] remove multiple options from dontAskMeAgain", + "userLogin": "TaimurAzhar", + "contributors": [ + "TaimurAzhar" + ] + }, + { + "pr": "17616", + "title": "[FIX] Notification sounds", + "userLogin": "sampaiodiego", + "description": "* Global CDN config was ignored when loading the sound files\r\n* Upload of custom sounds wasn't getting the file extension correctly\r\n* Some translations were missing\r\n* Edit and delete of custom sounds were not working correctly", + "milestone": "3.3.0", + "contributors": [ + "sampaiodiego", + "ggazzo" + ] + }, + { + "pr": "17544", + "title": "[FIX] Resolve 'app already exists' error on app update", + "userLogin": "thassiov", + "contributors": [ + "thassiov", + "web-flow", + "d-gubert" + ] + }, + { + "pr": "16862", + "title": "[NEW] Unread bars on sidebar (#16853)", + "userLogin": "juzser", + "milestone": "3.3.0", + "contributors": [ + "juzser", + "ggazzo", + "web-flow" + ] + }, + { + "pr": "15902", + "title": "[FIX] Relative image path in oembededUrlWidget", + "userLogin": "machester4", + "milestone": "3.3.0", + "contributors": [ + "machester4", + "web-flow" + ] + }, + { + "pr": "17613", + "title": "Regression: Do not show custom status inside sequential messages", + "userLogin": "ggazzo", + "milestone": "3.3.0", + "contributors": [ + "ggazzo" + ] + }, + { + "pr": "17582", + "title": "[FIX] Push settings enabled when push gateway is selected", + "userLogin": "geekgonecrazy", + "milestone": "3.2.2", + "contributors": [ + "geekgonecrazy", + "web-flow", + "sampaiodiego" + ] + }, + { + "pr": "17508", + "title": "[FIX] LDAP login on Enteprise Version", + "userLogin": "pierre-lehnen-rc", + "milestone": "3.2.2", + "contributors": [ + "pierre-lehnen-rc" + ] + }, + { + "pr": "17579", + "title": "[FIX] Login Forbidden on servers that had LDAP enabled in the past", + "userLogin": "pierre-lehnen-rc", + "milestone": "3.2.2", + "contributors": [ + "pierre-lehnen-rc" + ] + }, + { + "pr": "17578", + "title": "[FIX] Email configs not updating after setting changes", + "userLogin": "rodrigok", + "milestone": "3.2.2", + "contributors": [ + "rodrigok" + ] + }, + { + "pr": "17577", + "title": "[FIX] Error during data export for DMs", + "userLogin": "mtmr0x", + "milestone": "3.2.2", + "contributors": [ + "mtmr0x" + ] + }, + { + "pr": "17576", + "title": "Regression: Override via env for string settings not working", + "userLogin": "rodrigok", + "milestone": "3.3.0", + "contributors": [ + "rodrigok" + ] + }, + { + "pr": "17570", + "title": "[FIX] Emoji picker search broken", + "userLogin": "ggazzo", + "milestone": "3.2.2", + "contributors": [ + "ggazzo", + "web-flow" + ] + }, + { + "pr": "17524", + "title": "Add some missing metadata information", + "userLogin": "sampaiodiego", + "contributors": [ + "sampaiodiego" + ] + }, + { + "pr": "17486", + "title": "Bump jquery from 3.3.1 to 3.5.0", + "userLogin": "dependabot[bot]", + "contributors": [ + "dependabot[bot]", + "web-flow" + ] + }, + { + "pr": "14892", + "title": "[NEW] Show user's status description by the usernames in messages list", + "userLogin": "wreiske", + "description": "![image](https://user-images.githubusercontent.com/6295044/60321979-5d191580-994c-11e9-9cd6-15f4565ff0ae.png)", + "milestone": "3.3.0", + "contributors": [ + "wreiske", + "web-flow", + "ggazzo" + ] + }, + { + "pr": "17040", + "title": "DPlatform is deprecated and the replacement does not support rocket.chat", + "userLogin": "ryjones", + "contributors": [ + "ryjones" + ] + }, + { + "pr": "17552", + "title": "Regression: RegExp callbacks of settings were not being called", + "userLogin": "rodrigok", + "milestone": "3.3.0", + "contributors": [ + "rodrigok" + ] + }, + { + "pr": "17533", + "title": "Meteor update to version 1.10.2", + "userLogin": "sampaiodiego", + "contributors": [ + "sampaiodiego" + ] + }, + { + "pr": "17553", + "title": "[FIX] Omnichannel departments are not saved when the offline channel name is not defined", + "userLogin": "renatobecker", + "milestone": "3.3.0", + "contributors": [ + "renatobecker" + ] + }, + { + "pr": "17523", + "title": "[NEW] Screen Lock settings - mobile client", + "userLogin": "djorkaeffalexandre", + "milestone": "3.3.0", + "contributors": [ + "djorkaeffalexandre" + ] + }, + { + "pr": "17542", + "title": "Regression: Fix Avatar Url Provider when CDN_PREFIX_ALL is false", + "userLogin": "ggazzo", + "milestone": "3.3.0", + "contributors": [ + "ggazzo" + ] + }, + { + "pr": "17541", + "title": "[FIX] Invalid CSS syntax", + "userLogin": "tassoevan", + "milestone": "3.3.0", + "contributors": [ + "tassoevan" + ] + }, + { + "pr": "17388", + "title": "[NEW] Rewrite admin pages", + "userLogin": "ggazzo", + "milestone": "3.3.0", + "contributors": [ + "mariaeduardacunha", + "web-flow", + "tassoevan", + "ggazzo", + "gabriellsh", + "MartinSchoeler" + ] + }, + { + "pr": "15929", + "title": "[FIX] Replace postcss Meteor package", + "userLogin": "tassoevan", + "milestone": "4.0.0", + "contributors": [ + "tassoevan", + "sampaiodiego" + ] + }, + { + "pr": "17540", + "title": "[FIX] Increasing highlight time in 3 seconds", + "userLogin": "mariaeduardacunha", + "contributors": [ + "mariaeduardacunha" + ] + }, + { + "pr": "17503", + "title": "[IMPROVE] Add new webhooks to the Omnichannel integration feature", + "userLogin": "renatobecker", + "milestone": "3.3.0", + "contributors": [ + "renatobecker", + "web-flow" + ] + }, + { + "pr": "17387", + "title": "[FIX] Remove deprecated Omnichannel Knowledge Base feature", + "userLogin": "renatobecker", + "milestone": "4.0.0", + "contributors": [ + "renatobecker", + "web-flow" + ] + }, + { + "pr": "17536", + "title": "[FIX] Reactions may present empty names of who reacted when using Real Names", + "userLogin": "rodrigok", + "description": "When changing usernames the reactions became outdated since it's not possible to update the usernames stored there, so when the server users Real Name setting enabled the system process all messages before return to the clients and get the names of the usernames to show since the usernames are outdated the names will not be found. Now the usernames will be displayed when the name can't be found as a temporary fix until we change the architecture of the data to fix the issue.", + "milestone": "3.2.2", + "contributors": [ + "rodrigok" + ] + }, + { + "pr": "17463", + "title": "[NEW] Allow filtering Omnichannel analytics dashboards by department", + "userLogin": "renatobecker", + "milestone": "3.3.0", + "contributors": [ + "renatobecker", + "web-flow", + "MarcosSpessatto" + ] + }, + { + "pr": "17160", + "title": "[FIX] Uncessary updates on Settings, Roles and Permissions on startup", + "userLogin": "rodrigok", + "milestone": "3.3.0", + "contributors": [ + "rodrigok", + "sampaiodiego" + ] + }, + { + "pr": "17442", + "title": "[NEW] Add the ability to send Livechat offline messages to a channel", + "userLogin": "renatobecker", + "milestone": "3.3.0", + "contributors": [ + "renatobecker", + "web-flow" + ] + }, + { + "pr": "16430", + "title": "[FIX] Federation attachment URL for audio and video files", + "userLogin": "qwertiko", + "contributors": [ + "qwertiko", + "web-flow" + ] + }, + { + "pr": "17429", + "title": "[NEW] Add Livechat website URL to the offline message e-mail", + "userLogin": "renatobecker", + "milestone": "3.3.0", + "contributors": [ + "renatobecker", + "MarcosSpessatto", + "web-flow" + ] + }, + { + "pr": "17520", + "title": "LingoHub based on develop", + "userLogin": "engelgabriel", + "contributors": [ + "sampaiodiego", + "web-flow" + ] + }, + { + "pr": "17500", + "title": "RegExp improvements suggested by LGTM", + "userLogin": "rodrigok", + "milestone": "3.3.0", + "contributors": [ + "rodrigok" + ] + }, + { + "pr": "17419", + "title": "[FIX] Replace obsolete X-FRAME-OPTIONS header on Livechat route", + "userLogin": "renatobecker", + "milestone": "3.3.0", + "contributors": [ + "renatobecker", + "MarcosSpessatto", + "web-flow" + ] + }, + { + "pr": "17497", + "title": "[FIX] LDAP login error on Enterprise version", + "userLogin": "pierre-lehnen-rc", + "milestone": "3.2.1", + "contributors": [ + "pierre-lehnen-rc" + ] + }, + { + "pr": "17050", + "title": "[IMPROVE] [Apps-Engine] App user as the default notifier", + "userLogin": "lolimay", + "contributors": [ + "lolimay", + "d-gubert", + "web-flow" + ] + }, + { + "pr": "17033", + "title": "[NEW] [Apps-Engine] New Livechat event handlers", + "userLogin": "lolimay", + "contributors": [ + "lolimay", + "web-flow", + "renatobecker", + "d-gubert" + ] + }, + { + "pr": "17450", + "title": "[FIX] Change email verification label", + "userLogin": "MartinSchoeler", + "milestone": "3.3.0", + "contributors": [ + "MartinSchoeler", + "ggazzo", + "web-flow" + ] + }, + { + "pr": "17468", + "title": "Merge master into develop & Set version to 3.3.0-develop", + "userLogin": "sampaiodiego", + "contributors": [ + "sampaiodiego", + "web-flow" + ] + }, + { + "pr": "17479", + "title": "[FIX] Omnichannel room priorities system messages were create on every saved room info", + "userLogin": "MarcosSpessatto", + "milestone": "3.3.0", + "contributors": [ + "MarcosSpessatto" + ] + } + ] + }, + "3.2.1": { + "node_version": "12.16.1", + "npm_version": "6.13.4", + "mongo_versions": [ + "3.4", + "3.6", + "4.0" + ], + "pull_requests": [ + { + "pr": "17506", + "title": "Release 3.2.1", + "userLogin": "sampaiodiego", + "contributors": [ + "pierre-lehnen-rc", + "sampaiodiego" + ] + }, + { + "pr": "17497", + "title": "[FIX] LDAP login error on Enterprise version", + "userLogin": "pierre-lehnen-rc", + "milestone": "3.2.1", + "contributors": [ + "pierre-lehnen-rc" + ] + } + ] + }, + "3.2.2": { + "node_version": "12.16.1", + "npm_version": "6.13.4", + "mongo_versions": [ + "3.4", + "3.6", + "4.0" + ], + "pull_requests": [ + { + "pr": "17600", + "title": "Release 3.2.2", + "userLogin": "sampaiodiego", + "contributors": [ + "rodrigok", + "sampaiodiego", + "ggazzo", + "mtmr0x", + "pierre-lehnen-rc", + "geekgonecrazy" + ] + }, + { + "pr": "17582", + "title": "[FIX] Push settings enabled when push gateway is selected", + "userLogin": "geekgonecrazy", + "milestone": "3.2.2", + "contributors": [ + "geekgonecrazy", + "web-flow", + "sampaiodiego" + ] + }, + { + "pr": "17508", + "title": "[FIX] LDAP login on Enteprise Version", + "userLogin": "pierre-lehnen-rc", + "milestone": "3.2.2", + "contributors": [ + "pierre-lehnen-rc" + ] + }, + { + "pr": "17579", + "title": "[FIX] Login Forbidden on servers that had LDAP enabled in the past", + "userLogin": "pierre-lehnen-rc", + "milestone": "3.2.2", + "contributors": [ + "pierre-lehnen-rc" + ] + }, + { + "pr": "17578", + "title": "[FIX] Email configs not updating after setting changes", + "userLogin": "rodrigok", + "milestone": "3.2.2", + "contributors": [ + "rodrigok" + ] + }, + { + "pr": "17577", + "title": "[FIX] Error during data export for DMs", + "userLogin": "mtmr0x", + "milestone": "3.2.2", + "contributors": [ + "mtmr0x" + ] + }, + { + "pr": "17570", + "title": "[FIX] Emoji picker search broken", + "userLogin": "ggazzo", + "milestone": "3.2.2", + "contributors": [ + "ggazzo", + "web-flow" + ] + }, + { + "pr": "17536", + "title": "[FIX] Reactions may present empty names of who reacted when using Real Names", + "userLogin": "rodrigok", + "description": "When changing usernames the reactions became outdated since it's not possible to update the usernames stored there, so when the server users Real Name setting enabled the system process all messages before return to the clients and get the names of the usernames to show since the usernames are outdated the names will not be found. Now the usernames will be displayed when the name can't be found as a temporary fix until we change the architecture of the data to fix the issue.", + "milestone": "3.2.2", + "contributors": [ + "rodrigok" + ] + } + ] + }, + "3.3.0-rc.1": { + "node_version": "12.16.1", + "npm_version": "6.14.0", + "mongo_versions": [ + "3.4", + "3.6", + "4.0" + ], + "pull_requests": [ + { + "pr": "17716", + "title": "Regression: Threads list was fetching all threads", + "userLogin": "ggazzo", + "contributors": [ + "ggazzo" + ] + }, + { + "pr": "17715", + "title": "Regression: Add missing return to afterSaveMessage callbacks", + "userLogin": "sampaiodiego", + "milestone": "3.3.0", + "contributors": [ + "sampaiodiego" + ] + } + ] + }, + "3.3.0-rc.2": { + "node_version": "12.16.1", + "npm_version": "6.14.0", + "mongo_versions": [ + "3.4", + "3.6", + "4.0" + ], + "pull_requests": [ + { + "pr": "17726", + "title": "Regression: Fix error preventing creation of group DMs", + "userLogin": "pierre-lehnen-rc", + "contributors": [ + "pierre-lehnen-rc" + ] + }, + { + "pr": "17482", + "title": "[FIX] SAML IDP initiated logout error", + "userLogin": "pierre-lehnen-rc", + "contributors": [ + "pierre-lehnen-rc" + ] + } + ] + }, + "3.3.0-rc.3": { + "node_version": "12.16.1", + "npm_version": "6.14.0", + "mongo_versions": [ + "3.4", + "3.6", + "4.0" + ], + "pull_requests": [ + { + "pr": "17711", + "title": "Regression: Scroll on admin user info", + "userLogin": "ggazzo", + "milestone": "3.3.0", + "contributors": [ + "ggazzo" + ] + }, + { + "pr": "17741", + "title": "Regression: Removed status border on mentions list", + "userLogin": "mariaeduardacunha", + "contributors": [ + "mariaeduardacunha" + ] + }, + { + "pr": "17728", + "title": "Regression: Force unread-rooms bar to appears over the room list", + "userLogin": "mariaeduardacunha", + "contributors": [ + "mariaeduardacunha", + "ggazzo" + ] + }, + { + "pr": "17656", + "title": "[NEW][APPS-ENGINE] Essentials mechanism", + "userLogin": "d-gubert", + "milestone": "3.3.0", + "contributors": [ + "d-gubert", + "web-flow" + ] + } + ] + }, + "3.3.0-rc.4": { + "node_version": "12.16.1", + "npm_version": "6.14.0", + "mongo_versions": [ + "3.4", + "3.6", + "4.0" + ], + "pull_requests": [ + { + "pr": "17750", + "title": "Regression: Fix Unread bar design", + "userLogin": "dudizilla", + "milestone": "3.3.0", + "contributors": [ + "dudizilla", + "ggazzo" + ] + }, + { + "pr": "17745", + "title": "Regression: Adjusting spaces between OAuth login buttons", + "userLogin": "dudizilla", + "milestone": "3.3.0", + "contributors": [ + "dudizilla" ] } ] } } -} \ No newline at end of file +} diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 2d74d00f0e1..bf8c1bed7ff 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -227,7 +227,7 @@ jobs: MONGO_URL: mongodb://localhost:27017/rocketchat MONGO_OPLOG_URL: mongodb://localhost:27017/local run: | - for i in $(seq 1 5); do (docker exec mongo mongo rocketchat --eval 'db.dropDatabase()') && xvfb-run --auto-servernum npm test && s=0 && break || s=$? && sleep 1; done; (exit $s) + for i in $(seq 1 5); do (docker exec mongo mongo rocketchat --eval 'db.dropDatabase()') && xvfb-run --auto-servernum npm run testci && s=0 && break || s=$? && sleep 1; done; (exit $s) # notification: # runs-on: ubuntu-latest diff --git a/.scripts/houstonMetadata.js b/.houston/metadata.js similarity index 100% rename from .scripts/houstonMetadata.js rename to .houston/metadata.js diff --git a/.houston/templates/prs.hbs b/.houston/templates/prs.hbs new file mode 100644 index 00000000000..34a9666df2b --- /dev/null +++ b/.houston/templates/prs.hbs @@ -0,0 +1,2 @@ +{{> versions}} +{{> _prs}} diff --git a/.houston/templates/versions.hbs b/.houston/templates/versions.hbs new file mode 100644 index 00000000000..8ee2a4f9855 --- /dev/null +++ b/.houston/templates/versions.hbs @@ -0,0 +1,13 @@ +{{#if (or release.node_version release.npm_version release.mongo_versions)}} + +### Engine versions +{{#if release.node_version}} +- Node: `{{ release.node_version }}` +{{/if}} +{{#if release.npm_version}} +- NPM: `{{ release.npm_version }}` +{{/if}} +{{#if release.mongo_versions}} +- MongoDB: `{{ join release.mongo_versions ', ' }}` +{{/if}} +{{/if}} diff --git a/.meteor/packages b/.meteor/packages index 84ee48c2bc9..7447d19c969 100644 --- a/.meteor/packages +++ b/.meteor/packages @@ -6,18 +6,18 @@ rocketchat:mongo-config accounts-facebook@1.3.2 -accounts-github@1.4.2 +accounts-github@1.4.3 accounts-google@1.3.3 accounts-meteor-developer@1.4.2 -accounts-password@1.5.2 +accounts-password@1.6.0 accounts-twitter@1.4.2 blaze-html-templates check@1.3.1 ddp-rate-limiter@1.0.7 ddp-common@1.4.0 -dynamic-import@0.5.1 -ecmascript@0.14.2 -typescript@3.7.5 +dynamic-import@0.5.2 +ecmascript@0.14.3 +typescript@3.7.6 ejson@1.1.1 email@1.2.3 fastclick@1.0.13 @@ -25,16 +25,16 @@ http@1.4.2 jquery@1.11.10 logging@1.1.20 meteor-base@1.4.0 -mobile-experience@1.0.5 -mongo@1.8.0 -random@1.1.0 +mobile-experience@1.1.0 +mongo@1.10.0 +random@1.2.0 rate-limit@1.0.9 reactive-dict@1.3.0 reactive-var@1.0.11 reload@1.3.0 service-configuration@1.0.11 session@1.2.0 -shell-server@0.4.0 +shell-server@0.5.0 spacebars standard-minifier-js@2.6.0 tracker@1.2.0 @@ -44,9 +44,6 @@ rocketchat:livechat rocketchat:streamer rocketchat:version -konecty:change-case -konecty:delayed-task -konecty:mongo-counter konecty:multiple-instances-status konecty:user-presence @@ -57,7 +54,6 @@ jalik:ufs-gridfs@1.0.2 jparker:gravatar kadira:blaze-layout kadira:flow-router -keepnox:perfect-scrollbar mizzao:timesync mrt:reactive-store mystor:device-detection @@ -70,28 +66,28 @@ raix:ui-dropped-event rocketchat:tap-i18n underscore@1.0.10 -juliancwirko:postcss littledata:synced-cron edgee:slingshot jalik:ufs-local@1.0.2 -accounts-base@1.5.0 -accounts-oauth@1.1.16 +accounts-base@1.6.0 +accounts-oauth@1.2.0 autoupdate@1.6.0 -babel-compiler@7.5.2 -google-oauth@1.2.6 +babel-compiler@7.5.3 +google-oauth@1.3.0 htmljs less matb33:collection-hooks meteorhacks:inject-initial -oauth@1.2.8 -oauth2@1.2.1 +oauth@1.3.0 +oauth2@1.3.0 routepolicy@1.1.0 sha@1.0.9 templating -webapp@1.8.0 +webapp@1.9.1 webapp-hashing@1.0.9 rocketchat:oauth2-server rocketchat:i18n +rocketchat:postcss dandv:caret-position -facts-base +facts-base@1.0.1 diff --git a/.meteor/release b/.meteor/release index 8558e149237..3ea26528c09 100644 --- a/.meteor/release +++ b/.meteor/release @@ -1 +1 @@ -METEOR@1.9.2 +METEOR@1.10.2 diff --git a/.meteor/versions b/.meteor/versions index 02e97dbc384..f7e78d3598b 100644 --- a/.meteor/versions +++ b/.meteor/versions @@ -1,23 +1,23 @@ -accounts-base@1.5.0 +accounts-base@1.6.0 accounts-facebook@1.3.2 accounts-github@1.4.3 accounts-google@1.3.3 accounts-meteor-developer@1.4.2 -accounts-oauth@1.1.16 -accounts-password@1.5.3 +accounts-oauth@1.2.0 +accounts-password@1.6.0 accounts-twitter@1.4.2 aldeed:simple-schema@1.5.4 allow-deny@1.1.0 autoupdate@1.6.0 -babel-compiler@7.5.2 +babel-compiler@7.5.3 babel-runtime@1.5.0 base64@1.0.12 binary-heap@1.0.11 blaze@2.3.4 blaze-html-templates@1.1.2 blaze-tools@1.0.10 -boilerplate-generator@1.6.0 -caching-compiler@1.2.1 +boilerplate-generator@1.7.0 +caching-compiler@1.2.2 caching-html-compiler@1.1.3 callback-hook@1.3.0 cfs:http-methods@0.0.32 @@ -33,8 +33,8 @@ deepwell:bootstrap-datepicker2@1.3.0 deps@1.0.12 diff-sequence@1.1.1 dispatch:run-as-user@1.1.1 -dynamic-import@0.5.1 -ecmascript@0.14.2 +dynamic-import@0.5.2 +ecmascript@0.14.3 ecmascript-runtime@0.7.0 ecmascript-runtime-client@0.10.0 ecmascript-runtime-server@0.9.0 @@ -42,19 +42,19 @@ edgee:slingshot@0.7.1 ejson@1.1.1 email@1.2.3 es5-shim@4.8.0 -facebook-oauth@1.6.0 +facebook-oauth@1.7.0 facts-base@1.0.1 fastclick@1.0.13 fetch@0.1.1 geojson-utils@1.0.10 github-oauth@1.2.3 -google-oauth@1.2.6 +google-oauth@1.3.0 hot-code-push@1.0.4 html-tools@1.0.11 htmljs@1.0.11 http@1.4.2 id-map@1.1.0 -inter-process-messaging@0.1.0 +inter-process-messaging@0.1.1 jalik:ufs@1.0.2 jalik:ufs-gridfs@1.0.2 jalik:ufs-local@1.0.2 @@ -62,17 +62,12 @@ jparker:crypto-core@0.1.0 jparker:crypto-md5@0.1.1 jparker:gravatar@0.5.1 jquery@1.11.11 -juliancwirko:postcss@2.0.3 kadira:blaze-layout@2.3.0 kadira:flow-router@2.12.1 -keepnox:perfect-scrollbar@0.6.8 -konecty:change-case@2.3.0 -konecty:delayed-task@1.0.0 -konecty:mongo-counter@0.0.5_3 konecty:multiple-instances-status@1.1.0 konecty:user-presence@2.6.3 -launch-screen@1.1.1 -less@2.8.0 +launch-screen@1.2.0 +less@3.0.1 littledata:synced-cron@1.5.1 livedata@1.0.18 localstorage@1.2.0 @@ -86,37 +81,36 @@ meteorhacks:inject-initial@1.0.4 meteorspark:util@0.2.0 minifier-css@1.5.0 minifier-js@2.6.0 -minimongo@1.4.5 +minimongo@1.6.0 mizzao:timesync@0.3.4 -mobile-experience@1.0.5 -mobile-status-bar@1.0.14 +mobile-experience@1.1.0 +mobile-status-bar@1.1.0 modern-browsers@0.1.5 modules@0.15.0 modules-runtime@0.12.0 -mongo@1.8.1 +mongo@1.10.0 mongo-decimal@0.1.1 mongo-dev-server@1.1.0 mongo-id@1.0.7 -mongo-livedata@1.0.12 mrt:reactive-store@0.0.1 mystor:device-detection@0.2.0 nimble:restivus@0.8.12 nooitaf:colors@1.1.2_1 npm-bcrypt@0.9.3 -npm-mongo@3.3.0 -oauth@1.2.8 -oauth1@1.2.2 -oauth2@1.2.1 +npm-mongo@3.7.0 +oauth@1.3.0 +oauth1@1.3.0 +oauth2@1.3.0 observe-sequence@1.0.16 ordered-dict@1.1.0 -ostrio:cookies@2.5.0 +ostrio:cookies@2.6.0 pauli:accounts-linkedin@5.0.0 pauli:linkedin-oauth@5.0.0 promise@0.11.2 raix:eventemitter@0.1.3 raix:handlebar-helpers@0.2.5 raix:ui-dropped-event@0.0.7 -random@1.1.0 +random@1.2.0 rate-limit@1.0.9 reactive-dict@1.3.0 reactive-var@1.0.11 @@ -126,6 +120,7 @@ rocketchat:i18n@0.0.1 rocketchat:livechat@0.0.1 rocketchat:mongo-config@0.0.1 rocketchat:oauth2-server@2.1.0 +rocketchat:postcss@1.0.0 rocketchat:streamer@1.1.0 rocketchat:tap-i18n@1.9.1 rocketchat:version@1.0.0 @@ -133,23 +128,22 @@ routepolicy@1.1.0 service-configuration@1.0.11 session@1.2.0 sha@1.0.9 -shell-server@0.4.0 +shell-server@0.5.0 simple:json-routes@2.1.0 -socket-stream-client@0.2.3 +socket-stream-client@0.3.0 spacebars@1.0.15 spacebars-compiler@1.1.3 -srp@1.0.12 +srp@1.1.0 standard-minifier-js@2.6.0 templating@1.3.2 templating-compiler@1.3.3 templating-runtime@1.3.2 templating-tools@1.1.2 -tmeasday:check-npm-versions@0.3.2 tracker@1.2.0 twitter-oauth@1.2.0 -typescript@3.7.5 +typescript@3.7.6 ui@1.0.13 underscore@1.0.10 -url@1.2.0 -webapp@1.8.2 +url@1.3.0 +webapp@1.9.1 webapp-hashing@1.0.9 diff --git a/.postcssrc b/.postcssrc index 48f60768f66..e0279b84e3c 100644 --- a/.postcssrc +++ b/.postcssrc @@ -10,7 +10,6 @@ "autoprefixer": {} }, "excludedPackages": [ - "deepwell:bootstrap-datepicker2", - "smoral:sweetalert" + "deepwell:bootstrap-datepicker2" ] } diff --git a/.scripts/start.js b/.scripts/start.js index aa9e3b33475..1159290bbbb 100644 --- a/.scripts/start.js +++ b/.scripts/start.js @@ -112,7 +112,7 @@ function startChimp() { startProcess({ name: 'Chimp', command: 'npm', - params: ['run', 'testci'], + params: ['test'], // command: 'exit', // params: ['2'], options: { diff --git a/.snapcraft/resources/prepareRocketChat b/.snapcraft/resources/prepareRocketChat index a016135c0a3..0b7c625a7ad 100755 --- a/.snapcraft/resources/prepareRocketChat +++ b/.snapcraft/resources/prepareRocketChat @@ -1,6 +1,6 @@ #!/bin/bash -curl -SLf "https://releases.rocket.chat/#{RC_VERSION}/download/" -o rocket.chat.tgz +curl -SLf "https://releases.rocket.chat/3.3.0-rc.4/download/" -o rocket.chat.tgz tar xf rocket.chat.tgz --strip 1 diff --git a/.snapcraft/snap/snapcraft.yaml b/.snapcraft/snap/snapcraft.yaml index a6bb5700032..6a8f2b01f30 100644 --- a/.snapcraft/snap/snapcraft.yaml +++ b/.snapcraft/snap/snapcraft.yaml @@ -7,7 +7,7 @@ # 5. `snapcraft snap` name: rocketchat-server -version: #{RC_VERSION} +version: 3.3.0-rc.4 summary: Rocket.Chat server description: Have your own Slack like online chat, built with Meteor. https://rocket.chat/ confinement: strict diff --git a/.storybook/.babelrc b/.storybook/.babelrc deleted file mode 100644 index 97ab12b7f95..00000000000 --- a/.storybook/.babelrc +++ /dev/null @@ -1,19 +0,0 @@ -{ - "presets": [ - [ - "@babel/preset-env", - { - "shippedProposals": true, - "useBuiltIns": "usage", - "corejs": "3", - "modules": "commonjs" - } - ], - "@babel/preset-react", - "@babel/preset-flow" - ], - "plugins": [ - "@babel/plugin-proposal-class-properties", - "@babel/plugin-proposal-optional-chaining" - ] -} diff --git a/.storybook/addons.js b/.storybook/addons.js deleted file mode 100644 index 9d64a3d0a8f..00000000000 --- a/.storybook/addons.js +++ /dev/null @@ -1,4 +0,0 @@ -import '@storybook/addon-actions/register'; -import '@storybook/addon-knobs/register'; -import '@storybook/addon-links/register'; -import '@storybook/addon-viewport/register'; diff --git a/.storybook/babel.config.js b/.storybook/babel.config.js new file mode 100644 index 00000000000..f028aa2d294 --- /dev/null +++ b/.storybook/babel.config.js @@ -0,0 +1,20 @@ +module.exports = { + presets: [ + [ + '@babel/preset-env', + { + shippedProposals: true, + useBuiltIns: 'usage', + corejs: '3', + modules: 'commonjs', + }, + ], + '@babel/preset-react', + '@babel/preset-flow', + ], + plugins: [ + '@babel/plugin-proposal-class-properties', + '@babel/plugin-proposal-optional-chaining', + '@babel/plugin-proposal-nullish-coalescing-operator', + ], +}; diff --git a/.storybook/config.js b/.storybook/config.js deleted file mode 100644 index c7fb95b2124..00000000000 --- a/.storybook/config.js +++ /dev/null @@ -1,20 +0,0 @@ -import { withKnobs } from '@storybook/addon-knobs'; -import { MINIMAL_VIEWPORTS } from '@storybook/addon-viewport/dist/defaults'; -import { addDecorator, addParameters, configure } from '@storybook/react'; - -import { rocketChatDecorator } from './mocks/decorators'; - -addParameters({ - viewport: { - viewports: MINIMAL_VIEWPORTS, - }, -}); - -addDecorator(rocketChatDecorator); -addDecorator(withKnobs); - -configure([ - require.context('../app', true, /\.stories\.js$/), - require.context('../client', true, /\.stories\.js$/), - require.context('../ee/app', true, /\.stories\.js$/), -], module); diff --git a/.storybook/main.js b/.storybook/main.js new file mode 100644 index 00000000000..2b53b2635b3 --- /dev/null +++ b/.storybook/main.js @@ -0,0 +1,11 @@ +module.exports = { + stories: [ + '../app/**/*.stories.js', + '../client/**/*.stories.js', + '../ee/app/**/*.stories.js', + ], + addons: [ + '@storybook/addon-actions', + '@storybook/addon-knobs', + ], +}; diff --git a/.storybook/mocks/decorators.js b/.storybook/mocks/decorators.js index 34a326f1107..0c545d5c161 100644 --- a/.storybook/mocks/decorators.js +++ b/.storybook/mocks/decorators.js @@ -24,7 +24,7 @@ export const rocketChatDecorator = (fn) => { } `}
-
+
{fn()}
; diff --git a/.storybook/mocks/meteor.js b/.storybook/mocks/meteor.js index d85c752a2b2..a690a4db684 100644 --- a/.storybook/mocks/meteor.js +++ b/.storybook/mocks/meteor.js @@ -4,7 +4,10 @@ export const Meteor = { _localStorage: window.localStorage, absoluteUrl: () => {}, userId: () => {}, - Streamer: () => {}, + Streamer: () => ({ + on: () => {}, + removeListener: () => {}, + }), startup: () => {}, methods: () => {}, call: () => {}, @@ -31,10 +34,13 @@ export const Mongo = { }), }; -export const ReactiveVar = () => ({ - get: () => {}, - set: () => {}, -}); +export const ReactiveVar = (val) => { + let currentVal = val; + return { + get: () => currentVal, + set: (val) => { currentVal = val; }, + }; +}; export const ReactiveDict = () => ({ get: () => {}, diff --git a/.storybook/preview.js b/.storybook/preview.js new file mode 100644 index 00000000000..c4b6fca4894 --- /dev/null +++ b/.storybook/preview.js @@ -0,0 +1,7 @@ +import { withKnobs } from '@storybook/addon-knobs'; +import { addDecorator } from '@storybook/react'; + +import { rocketChatDecorator } from './mocks/decorators'; + +addDecorator(rocketChatDecorator); +addDecorator(withKnobs); diff --git a/.storybook/webpack.config.js b/.storybook/webpack.config.js index 03a6a91feed..1d47404d267 100644 --- a/.storybook/webpack.config.js +++ b/.storybook/webpack.config.js @@ -31,15 +31,35 @@ module.exports = async ({ config }) => { use: '@settlin/spacebars-loader', }); - config.plugins.push(new webpack.NormalModuleReplacementPlugin( - /^meteor/, - require.resolve('./mocks/meteor.js'), - )); - - config.plugins.push(new webpack.NormalModuleReplacementPlugin( - /\.\/server\/index.js/, - require.resolve('./mocks/empty.js'), - )); + config.module.rules.push({ + test: /\.(ts|tsx)$/, + use: [ + { + loader: 'ts-loader', + options: { + compilerOptions: { + noEmit: false, + }, + }, + }, + { + loader: 'react-docgen-typescript-loader', + }, + ], + }); + + config.resolve.extensions.push('.ts', '.tsx'); + + config.plugins.push( + new webpack.NormalModuleReplacementPlugin( + /^meteor/, + require.resolve('./mocks/meteor.js'), + ), + new webpack.NormalModuleReplacementPlugin( + /\/server(\/index.js)$/, + require.resolve('./mocks/empty.js'), + ), + ); config.mode = 'development'; config.optimization.usedExports = true; diff --git a/HISTORY.md b/HISTORY.md index b1a5729f71c..d8a8dbb8638 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,6 +1,374 @@ +# 3.3.0 (Under Release Candidate Process) + +## 3.3.0-rc.4 +`2020-05-27 · 2 🔍 · 2 👩‍💻👨‍💻` + +
+🔍 Minor changes + + +- Regression: Fix Unread bar design ([#17750](https://github.com/RocketChat/Rocket.Chat/pull/17750)) + +- Regression: Adjusting spaces between OAuth login buttons ([#17745](https://github.com/RocketChat/Rocket.Chat/pull/17745)) + +
+ +### 👩‍💻👨‍💻 Core Team 🤓 + +- [@dudizilla](https://github.com/dudizilla) +- [@ggazzo](https://github.com/ggazzo) + +## 3.3.0-rc.3 +`2020-05-25 · 1 🎉 · 3 🔍 · 3 👩‍💻👨‍💻` + +### 🎉 New features + + +- **APPS-ENGINE:** Essentials mechanism ([#17656](https://github.com/RocketChat/Rocket.Chat/pull/17656)) + +
+🔍 Minor changes + + +- Regression: Scroll on admin user info ([#17711](https://github.com/RocketChat/Rocket.Chat/pull/17711)) + +- Regression: Removed status border on mentions list ([#17741](https://github.com/RocketChat/Rocket.Chat/pull/17741) by [@mariaeduardacunha](https://github.com/mariaeduardacunha)) + +- Regression: Force unread-rooms bar to appears over the room list ([#17728](https://github.com/RocketChat/Rocket.Chat/pull/17728) by [@mariaeduardacunha](https://github.com/mariaeduardacunha)) + +
+ +### 👩‍💻👨‍💻 Contributors 😍 + +- [@mariaeduardacunha](https://github.com/mariaeduardacunha) + +### 👩‍💻👨‍💻 Core Team 🤓 + +- [@d-gubert](https://github.com/d-gubert) +- [@ggazzo](https://github.com/ggazzo) + +## 3.3.0-rc.2 +`2020-05-22 · 1 🐛 · 1 🔍 · 1 👩‍💻👨‍💻` + +### 🐛 Bug fixes + + +- SAML IDP initiated logout error ([#17482](https://github.com/RocketChat/Rocket.Chat/pull/17482)) + +
+🔍 Minor changes + + +- Regression: Fix error preventing creation of group DMs ([#17726](https://github.com/RocketChat/Rocket.Chat/pull/17726)) + +
+ +### 👩‍💻👨‍💻 Core Team 🤓 + +- [@pierre-lehnen-rc](https://github.com/pierre-lehnen-rc) + +## 3.3.0-rc.1 +`2020-05-21 · 2 🔍 · 2 👩‍💻👨‍💻` + +
+🔍 Minor changes + + +- Regression: Threads list was fetching all threads ([#17716](https://github.com/RocketChat/Rocket.Chat/pull/17716)) + +- Regression: Add missing return to afterSaveMessage callbacks ([#17715](https://github.com/RocketChat/Rocket.Chat/pull/17715)) + +
+ +### 👩‍💻👨‍💻 Core Team 🤓 + +- [@ggazzo](https://github.com/ggazzo) +- [@sampaiodiego](https://github.com/sampaiodiego) + +## 3.3.0-rc.0 +`2020-05-21 · 19 🎉 · 8 🚀 · 40 🐛 · 36 🔍 · 35 👩‍💻👨‍💻` + +### 🎉 New features + + +- **ENTERPRISE:** Support Omnichannel conversations auditing ([#17692](https://github.com/RocketChat/Rocket.Chat/pull/17692)) + +- **ENTERPRISE:** Support for custom Livechat registration form fields ([#17581](https://github.com/RocketChat/Rocket.Chat/pull/17581)) + +- **ENTERPRISE:** Omnichannel Last-Chatted Agent Preferred option ([#17666](https://github.com/RocketChat/Rocket.Chat/pull/17666)) + + If activated, this feature will store the last agent that assisted each Omnichannel visitor when a conversation is taken. So, when a visitor returns(it works with any entry point, Livechat, Facebook, REST API, and so on) and starts a new chat, the routing system checks: + + 1 - The visitor object for any stored agent that the visitor has previously talked to; + 2 - If a previous agent is not found, the system will try to find a previous conversation of the same visitor. If a room is found, the system will get the previous agent from the room; + + After this process, if an agent has been found, the system will check the agent's availability to assist the new chat. If it's not available, then the routing system will get the next available agent in the queue. + +- **Apps-Engine:** New Room events ([#17487](https://github.com/RocketChat/Rocket.Chat/pull/17487)) + +- **Apps-Engine:** New Livechat event handlers ([#17033](https://github.com/RocketChat/Rocket.Chat/pull/17033)) + +- API endpoint to fetch Omnichannel's room transfer history ([#17694](https://github.com/RocketChat/Rocket.Chat/pull/17694)) + +- Option to remove users from RocketChat if not found in Crowd ([#17619](https://github.com/RocketChat/Rocket.Chat/pull/17619) by [@ocanema](https://github.com/ocanema)) + +- Added custom fields to Add/Edit user ([#17681](https://github.com/RocketChat/Rocket.Chat/pull/17681)) + +- Admin refactor Second phase ([#17551](https://github.com/RocketChat/Rocket.Chat/pull/17551)) + +- Added "Add custom emoji" link to emoji picker ([#16250](https://github.com/RocketChat/Rocket.Chat/pull/16250)) + +- Add Permissions to deal with Omnichannel visitor past chats history ([#17580](https://github.com/RocketChat/Rocket.Chat/pull/17580)) + +- Add permissions to deal with Omnichannel custom fields ([#17567](https://github.com/RocketChat/Rocket.Chat/pull/17567)) + +- Unread bars on sidebar (#16853) ([#16862](https://github.com/RocketChat/Rocket.Chat/pull/16862) by [@juzser](https://github.com/juzser)) + +- Show user's status description by the usernames in messages list ([#14892](https://github.com/RocketChat/Rocket.Chat/pull/14892) by [@wreiske](https://github.com/wreiske)) + + ![image](https://user-images.githubusercontent.com/6295044/60321979-5d191580-994c-11e9-9cd6-15f4565ff0ae.png) + +- Screen Lock settings - mobile client ([#17523](https://github.com/RocketChat/Rocket.Chat/pull/17523)) + +- Rewrite admin pages ([#17388](https://github.com/RocketChat/Rocket.Chat/pull/17388) by [@mariaeduardacunha](https://github.com/mariaeduardacunha)) + +- Allow filtering Omnichannel analytics dashboards by department ([#17463](https://github.com/RocketChat/Rocket.Chat/pull/17463)) + +- Add the ability to send Livechat offline messages to a channel ([#17442](https://github.com/RocketChat/Rocket.Chat/pull/17442)) + +- Add Livechat website URL to the offline message e-mail ([#17429](https://github.com/RocketChat/Rocket.Chat/pull/17429)) + +### 🚀 Improvements + + +- **Apps-Engine:** App user as the default notifier ([#17050](https://github.com/RocketChat/Rocket.Chat/pull/17050)) + +- Always shows the exact match first on user's and room's autocomplete for mentions and on sidebar search ([#16394](https://github.com/RocketChat/Rocket.Chat/pull/16394)) + +- Display status information in the Omnichannel Agents list ([#17701](https://github.com/RocketChat/Rocket.Chat/pull/17701)) + +- Add env var to configure Chatpal URL and remove it from beta ([#16665](https://github.com/RocketChat/Rocket.Chat/pull/16665) by [@tkurz](https://github.com/tkurz)) + +- Added divider between tables and paginations ([#17680](https://github.com/RocketChat/Rocket.Chat/pull/17680)) + +- Starred Messages ([#17685](https://github.com/RocketChat/Rocket.Chat/pull/17685)) + +- Unused styles ([#17554](https://github.com/RocketChat/Rocket.Chat/pull/17554)) + +- Add new webhooks to the Omnichannel integration feature ([#17503](https://github.com/RocketChat/Rocket.Chat/pull/17503)) + +### 🐛 Bug fixes + + +- Missing dropdown to select custom status color on user's profile ([#16537](https://github.com/RocketChat/Rocket.Chat/pull/16537) by [@ritwizsinha](https://github.com/ritwizsinha)) + +- Password reset/change accepting current password as new password ([#16331](https://github.com/RocketChat/Rocket.Chat/pull/16331) by [@ashwaniYDV](https://github.com/ashwaniYDV)) + +- Can't click on room's actions menu of sidebar list when in search mode ([#16548](https://github.com/RocketChat/Rocket.Chat/pull/16548) by [@ritvikjain99](https://github.com/ritvikjain99)) + +- Remove a non working setting "Notification Duration" ([#15737](https://github.com/RocketChat/Rocket.Chat/pull/15737)) + +- Elements of "Personal Access Tokens" section out of alignment and unusable on very small screens ([#17129](https://github.com/RocketChat/Rocket.Chat/pull/17129) by [@Nikhil713](https://github.com/Nikhil713)) + +- Allow owners to react inside broadcast channels ([#17687](https://github.com/RocketChat/Rocket.Chat/pull/17687) by [@mariaeduardacunha](https://github.com/mariaeduardacunha)) + +- Default filters on Omnichannel Current Chats screen not showing on first load ([#17522](https://github.com/RocketChat/Rocket.Chat/pull/17522)) + +- UI KIT Modal Width ([#17697](https://github.com/RocketChat/Rocket.Chat/pull/17697)) + +- Agent's custom fields being leaked through the Livechat configuration endpoint ([#17640](https://github.com/RocketChat/Rocket.Chat/pull/17640)) + +- Avatar url provider ignoring subfolders ([#17675](https://github.com/RocketChat/Rocket.Chat/pull/17675)) + +- Queued Omnichannel webhook being triggered unnecessarily ([#17661](https://github.com/RocketChat/Rocket.Chat/pull/17661)) + +- Not redirecting to `First Channel After Login` on register ([#17664](https://github.com/RocketChat/Rocket.Chat/pull/17664)) + +- Directory search user placeholder ([#17652](https://github.com/RocketChat/Rocket.Chat/pull/17652) by [@zdumitru](https://github.com/zdumitru)) + +- Marketplace tiered pricing plan wording ([#17644](https://github.com/RocketChat/Rocket.Chat/pull/17644)) + +- Secret Registration not properly validating Invite Token ([#17618](https://github.com/RocketChat/Rocket.Chat/pull/17618)) + +- Hyper.sh went out of business in early 2019 ([#17622](https://github.com/RocketChat/Rocket.Chat/pull/17622) by [@fbartels](https://github.com/fbartels)) + +- Do not allow passwords on private channels ([#15642](https://github.com/RocketChat/Rocket.Chat/pull/15642)) + +- Mail Messages > Cannot mail own user ([#17625](https://github.com/RocketChat/Rocket.Chat/pull/17625)) + +- remove multiple options from dontAskMeAgain ([#17514](https://github.com/RocketChat/Rocket.Chat/pull/17514) by [@TaimurAzhar](https://github.com/TaimurAzhar)) + +- Notification sounds ([#17616](https://github.com/RocketChat/Rocket.Chat/pull/17616)) + + * Global CDN config was ignored when loading the sound files + * Upload of custom sounds wasn't getting the file extension correctly + * Some translations were missing + * Edit and delete of custom sounds were not working correctly + +- Resolve 'app already exists' error on app update ([#17544](https://github.com/RocketChat/Rocket.Chat/pull/17544)) + +- Relative image path in oembededUrlWidget ([#15902](https://github.com/RocketChat/Rocket.Chat/pull/15902) by [@machester4](https://github.com/machester4)) + +- Push settings enabled when push gateway is selected ([#17582](https://github.com/RocketChat/Rocket.Chat/pull/17582)) + +- LDAP login on Enteprise Version ([#17508](https://github.com/RocketChat/Rocket.Chat/pull/17508)) + +- Login Forbidden on servers that had LDAP enabled in the past ([#17579](https://github.com/RocketChat/Rocket.Chat/pull/17579)) + +- Email configs not updating after setting changes ([#17578](https://github.com/RocketChat/Rocket.Chat/pull/17578)) + +- Error during data export for DMs ([#17577](https://github.com/RocketChat/Rocket.Chat/pull/17577)) + +- Emoji picker search broken ([#17570](https://github.com/RocketChat/Rocket.Chat/pull/17570)) + +- Omnichannel departments are not saved when the offline channel name is not defined ([#17553](https://github.com/RocketChat/Rocket.Chat/pull/17553)) + +- Invalid CSS syntax ([#17541](https://github.com/RocketChat/Rocket.Chat/pull/17541)) + +- Replace postcss Meteor package ([#15929](https://github.com/RocketChat/Rocket.Chat/pull/15929)) + +- Increasing highlight time in 3 seconds ([#17540](https://github.com/RocketChat/Rocket.Chat/pull/17540) by [@mariaeduardacunha](https://github.com/mariaeduardacunha)) + +- Remove deprecated Omnichannel Knowledge Base feature ([#17387](https://github.com/RocketChat/Rocket.Chat/pull/17387)) + +- Reactions may present empty names of who reacted when using Real Names ([#17536](https://github.com/RocketChat/Rocket.Chat/pull/17536)) + + When changing usernames the reactions became outdated since it's not possible to update the usernames stored there, so when the server users Real Name setting enabled the system process all messages before return to the clients and get the names of the usernames to show since the usernames are outdated the names will not be found. Now the usernames will be displayed when the name can't be found as a temporary fix until we change the architecture of the data to fix the issue. + +- Uncessary updates on Settings, Roles and Permissions on startup ([#17160](https://github.com/RocketChat/Rocket.Chat/pull/17160)) + +- Federation attachment URL for audio and video files ([#16430](https://github.com/RocketChat/Rocket.Chat/pull/16430) by [@qwertiko](https://github.com/qwertiko)) + +- Replace obsolete X-FRAME-OPTIONS header on Livechat route ([#17419](https://github.com/RocketChat/Rocket.Chat/pull/17419)) + +- LDAP login error on Enterprise version ([#17497](https://github.com/RocketChat/Rocket.Chat/pull/17497)) + +- Change email verification label ([#17450](https://github.com/RocketChat/Rocket.Chat/pull/17450)) + +- Omnichannel room priorities system messages were create on every saved room info ([#17479](https://github.com/RocketChat/Rocket.Chat/pull/17479)) + +
+🔍 Minor changes + + +- Upgrade Livechat Widget version to 1.5.0 ([#17710](https://github.com/RocketChat/Rocket.Chat/pull/17710)) + +- Update Fuselage version ([#17708](https://github.com/RocketChat/Rocket.Chat/pull/17708)) + +- Regression: Status presence color ([#17707](https://github.com/RocketChat/Rocket.Chat/pull/17707) by [@mariaeduardacunha](https://github.com/mariaeduardacunha)) + +- Improve: Remove index files from action-links, accounts and assets ([#17607](https://github.com/RocketChat/Rocket.Chat/pull/17607)) + +- Update Apps-Engine version ([#17706](https://github.com/RocketChat/Rocket.Chat/pull/17706)) + +- Regression: Click to join button not working ([#17705](https://github.com/RocketChat/Rocket.Chat/pull/17705)) + +- Fix typo "You aren't part of any channel yet" ([#17498](https://github.com/RocketChat/Rocket.Chat/pull/17498) by [@huzaifahj](https://github.com/huzaifahj)) + +- Regression: Integrations edit/history crashing ([#17702](https://github.com/RocketChat/Rocket.Chat/pull/17702)) + +- Regression: User edit form missing fields ([#17699](https://github.com/RocketChat/Rocket.Chat/pull/17699)) + +- Regression: Fix error when performing Omnichannel queue checking ([#17700](https://github.com/RocketChat/Rocket.Chat/pull/17700)) + +- Update Contributing Guide ([#17653](https://github.com/RocketChat/Rocket.Chat/pull/17653)) + +- LingoHub based on develop ([#17693](https://github.com/RocketChat/Rocket.Chat/pull/17693)) + +- Regression: Fix incorrect imports of the Apps-Engine ([#17695](https://github.com/RocketChat/Rocket.Chat/pull/17695)) + +- Improve: Remove uncessary RegExp query by email ([#17654](https://github.com/RocketChat/Rocket.Chat/pull/17654)) + +- Regression: Set retryWrites=false as default Mongo options ([#17683](https://github.com/RocketChat/Rocket.Chat/pull/17683)) + +- Regression: status-color-online ([#17684](https://github.com/RocketChat/Rocket.Chat/pull/17684)) + +- Add snapcraft files to be bumped with Houston ([#17611](https://github.com/RocketChat/Rocket.Chat/pull/17611)) + +- Regression: Outgoing List ([#17667](https://github.com/RocketChat/Rocket.Chat/pull/17667)) + +- Regression: Pressing enter on search reloads the page - admin pages ([#17663](https://github.com/RocketChat/Rocket.Chat/pull/17663)) + +- Improve: New PR Template ([#16968](https://github.com/RocketChat/Rocket.Chat/pull/16968) by [@regalstreak](https://github.com/regalstreak)) + +- Add engine versions for houston with templates ([#17403](https://github.com/RocketChat/Rocket.Chat/pull/17403)) + +- Use Users.findOneByAppId instead of querying directly ([#16480](https://github.com/RocketChat/Rocket.Chat/pull/16480)) + +- Remove unnecessary setting redefinition ([#17587](https://github.com/RocketChat/Rocket.Chat/pull/17587)) + +- Deprecate compatibility cordova setting ([#17586](https://github.com/RocketChat/Rocket.Chat/pull/17586)) + +- Livechat iframe allow microphone and camera ([#9956](https://github.com/RocketChat/Rocket.Chat/pull/9956) by [@kolorafa](https://github.com/kolorafa)) + +- Regression: Do not show custom status inside sequential messages ([#17613](https://github.com/RocketChat/Rocket.Chat/pull/17613)) + +- Regression: Override via env for string settings not working ([#17576](https://github.com/RocketChat/Rocket.Chat/pull/17576)) + +- Add some missing metadata information ([#17524](https://github.com/RocketChat/Rocket.Chat/pull/17524)) + +- Bump jquery from 3.3.1 to 3.5.0 ([#17486](https://github.com/RocketChat/Rocket.Chat/pull/17486) by [@dependabot[bot]](https://github.com/dependabot[bot])) + +- DPlatform is deprecated and the replacement does not support rocket.chat ([#17040](https://github.com/RocketChat/Rocket.Chat/pull/17040) by [@ryjones](https://github.com/ryjones)) + +- Regression: RegExp callbacks of settings were not being called ([#17552](https://github.com/RocketChat/Rocket.Chat/pull/17552)) + +- Meteor update to version 1.10.2 ([#17533](https://github.com/RocketChat/Rocket.Chat/pull/17533)) + +- Regression: Fix Avatar Url Provider when CDN_PREFIX_ALL is false ([#17542](https://github.com/RocketChat/Rocket.Chat/pull/17542)) + +- LingoHub based on develop ([#17520](https://github.com/RocketChat/Rocket.Chat/pull/17520)) + +- RegExp improvements suggested by LGTM ([#17500](https://github.com/RocketChat/Rocket.Chat/pull/17500)) + +- Merge master into develop & Set version to 3.3.0-develop ([#17468](https://github.com/RocketChat/Rocket.Chat/pull/17468)) + +
+ +### 👩‍💻👨‍💻 Contributors 😍 + +- [@Nikhil713](https://github.com/Nikhil713) +- [@TaimurAzhar](https://github.com/TaimurAzhar) +- [@ashwaniYDV](https://github.com/ashwaniYDV) +- [@dependabot[bot]](https://github.com/dependabot[bot]) +- [@fbartels](https://github.com/fbartels) +- [@huzaifahj](https://github.com/huzaifahj) +- [@juzser](https://github.com/juzser) +- [@kolorafa](https://github.com/kolorafa) +- [@machester4](https://github.com/machester4) +- [@mariaeduardacunha](https://github.com/mariaeduardacunha) +- [@ocanema](https://github.com/ocanema) +- [@qwertiko](https://github.com/qwertiko) +- [@regalstreak](https://github.com/regalstreak) +- [@ritvikjain99](https://github.com/ritvikjain99) +- [@ritwizsinha](https://github.com/ritwizsinha) +- [@ryjones](https://github.com/ryjones) +- [@tkurz](https://github.com/tkurz) +- [@wreiske](https://github.com/wreiske) +- [@zdumitru](https://github.com/zdumitru) + +### 👩‍💻👨‍💻 Core Team 🤓 + +- [@MarcosSpessatto](https://github.com/MarcosSpessatto) +- [@MartinSchoeler](https://github.com/MartinSchoeler) +- [@d-gubert](https://github.com/d-gubert) +- [@djorkaeffalexandre](https://github.com/djorkaeffalexandre) +- [@engelgabriel](https://github.com/engelgabriel) +- [@gabriellsh](https://github.com/gabriellsh) +- [@geekgonecrazy](https://github.com/geekgonecrazy) +- [@ggazzo](https://github.com/ggazzo) +- [@lolimay](https://github.com/lolimay) +- [@mtmr0x](https://github.com/mtmr0x) +- [@pierre-lehnen-rc](https://github.com/pierre-lehnen-rc) +- [@renatobecker](https://github.com/renatobecker) +- [@rodrigok](https://github.com/rodrigok) +- [@sampaiodiego](https://github.com/sampaiodiego) +- [@tassoevan](https://github.com/tassoevan) +- [@thassiov](https://github.com/thassiov) + # 3.2.2 -`2020-05-11 · 7 🐛 · 6 👩‍💻👨‍💻` +`2020-05-11 · 7 🐛 · 1 🔍 · 6 👩‍💻👨‍💻` ### Engine versions - Node: `12.16.1` @@ -26,6 +394,14 @@ When changing usernames the reactions became outdated since it's not possible to update the usernames stored there, so when the server users Real Name setting enabled the system process all messages before return to the clients and get the names of the usernames to show since the usernames are outdated the names will not be found. Now the usernames will be displayed when the name can't be found as a temporary fix until we change the architecture of the data to fix the issue. +
+🔍 Minor changes + + +- Release 3.2.2 ([#17600](https://github.com/RocketChat/Rocket.Chat/pull/17600)) + +
+ ### 👩‍💻👨‍💻 Core Team 🤓 - [@geekgonecrazy](https://github.com/geekgonecrazy) @@ -36,20 +412,39 @@ - [@sampaiodiego](https://github.com/sampaiodiego) # 3.2.1 -`2020-05-01 · 1 🐛 · 1 👩‍💻👨‍💻` +`2020-05-01 · 1 🐛 · 1 🔍 · 2 👩‍💻👨‍💻` + +### Engine versions +- Node: `12.16.1` +- NPM: `6.13.4` +- MongoDB: `3.4, 3.6, 4.0` ### 🐛 Bug fixes - LDAP login error on Enterprise version ([#17497](https://github.com/RocketChat/Rocket.Chat/pull/17497)) +
+🔍 Minor changes + + +- Release 3.2.1 ([#17506](https://github.com/RocketChat/Rocket.Chat/pull/17506)) + +
+ ### 👩‍💻👨‍💻 Core Team 🤓 - [@pierre-lehnen-rc](https://github.com/pierre-lehnen-rc) +- [@sampaiodiego](https://github.com/sampaiodiego) # 3.2.0 `2020-04-27 · 19 🎉 · 10 🚀 · 34 🐛 · 19 🔍 · 34 👩‍💻👨‍💻` +### Engine versions +- Node: `12.16.1` +- NPM: `6.13.4` +- MongoDB: `3.4, 3.6, 4.0` + ### 🎉 New features @@ -281,9 +676,31 @@ - [@sampaiodiego](https://github.com/sampaiodiego) - [@tassoevan](https://github.com/tassoevan) +# 3.1.3 +`2020-05-11 · 1 🐛 · 1 👩‍💻👨‍💻` + +### Engine versions +- Node: `12.16.1` +- NPM: `6.13.4` +- MongoDB: `3.4, 3.6, 4.0` + +### 🐛 Bug fixes + + +- Email configs not updating after setting changes ([#17578](https://github.com/RocketChat/Rocket.Chat/pull/17578)) + +### 👩‍💻👨‍💻 Core Team 🤓 + +- [@rodrigok](https://github.com/rodrigok) + # 3.1.2 `2020-04-27 · 8 🐛 · 3 🔍 · 5 👩‍💻👨‍💻` +### Engine versions +- Node: `12.16.1` +- NPM: `6.13.4` +- MongoDB: `3.4, 3.6, 4.0` + ### 🐛 Bug fixes @@ -851,6 +1268,23 @@ - [@sampaiodiego](https://github.com/sampaiodiego) - [@tassoevan](https://github.com/tassoevan) +# 3.0.13 +`2020-05-11 · 1 🐛 · 1 👩‍💻👨‍💻` + +### Engine versions +- Node: `12.14.0` +- NPM: `6.13.4` +- MongoDB: `3.4, 3.6, 4.0` + +### 🐛 Bug fixes + + +- Email configs not updating after setting changes ([#17578](https://github.com/RocketChat/Rocket.Chat/pull/17578)) + +### 👩‍💻👨‍💻 Core Team 🤓 + +- [@rodrigok](https://github.com/rodrigok) + # 3.0.12 `2020-04-03 · 3 🔍 · 2 👩‍💻👨‍💻` @@ -1195,11 +1629,11 @@ ### ⚠️ BREAKING CHANGES -- Filter System messages per room ([#16369](https://github.com/RocketChat/Rocket.Chat/pull/16369)) +- Filter System messages per room ([#16369](https://github.com/RocketChat/Rocket.Chat/pull/16369) by [@mariaeduardacunha](https://github.com/mariaeduardacunha)) - Remove deprecated publications ([#16351](https://github.com/RocketChat/Rocket.Chat/pull/16351)) -- Hide system messages ([#16243](https://github.com/RocketChat/Rocket.Chat/pull/16243)) +- Hide system messages ([#16243](https://github.com/RocketChat/Rocket.Chat/pull/16243) by [@mariaeduardacunha](https://github.com/mariaeduardacunha)) - Upgrade to Meteor 1.9 and NodeJS 12 ([#16252](https://github.com/RocketChat/Rocket.Chat/pull/16252)) @@ -1274,11 +1708,11 @@ - Highlight freezing the UI ([#16378](https://github.com/RocketChat/Rocket.Chat/pull/16378)) -- Adding 'lang' tag ([#16375](https://github.com/RocketChat/Rocket.Chat/pull/16375)) +- Adding 'lang' tag ([#16375](https://github.com/RocketChat/Rocket.Chat/pull/16375) by [@mariaeduardacunha](https://github.com/mariaeduardacunha)) - App removal was moving logs to the trash collection ([#16362](https://github.com/RocketChat/Rocket.Chat/pull/16362)) -- Role tags missing - Description field explanation ([#16356](https://github.com/RocketChat/Rocket.Chat/pull/16356)) +- Role tags missing - Description field explanation ([#16356](https://github.com/RocketChat/Rocket.Chat/pull/16356) by [@mariaeduardacunha](https://github.com/mariaeduardacunha)) - Invite links usage by channel owners/moderators ([#16176](https://github.com/RocketChat/Rocket.Chat/pull/16176)) @@ -1308,7 +1742,7 @@ - SafePorts: Ports 80, 8080 & 443 linked to respective protocols (#16108) ([#16108](https://github.com/RocketChat/Rocket.Chat/pull/16108)) -- Drag and drop disabled when file upload is disabled ([#16049](https://github.com/RocketChat/Rocket.Chat/pull/16049)) +- Drag and drop disabled when file upload is disabled ([#16049](https://github.com/RocketChat/Rocket.Chat/pull/16049) by [@mariaeduardacunha](https://github.com/mariaeduardacunha)) - Video message sent to wrong room ([#16113](https://github.com/RocketChat/Rocket.Chat/pull/16113)) @@ -1318,7 +1752,7 @@ - Thread message icon overlapping text ([#16083](https://github.com/RocketChat/Rocket.Chat/pull/16083)) -- Login change language button ([#16085](https://github.com/RocketChat/Rocket.Chat/pull/16085)) +- Login change language button ([#16085](https://github.com/RocketChat/Rocket.Chat/pull/16085) by [@mariaeduardacunha](https://github.com/mariaeduardacunha)) - api-bypass-rate-limiter permission was not working ([#16080](https://github.com/RocketChat/Rocket.Chat/pull/16080)) @@ -1452,6 +1886,7 @@ - [@antkaz](https://github.com/antkaz) - [@ashwaniYDV](https://github.com/ashwaniYDV) - [@aviral243](https://github.com/aviral243) +- [@mariaeduardacunha](https://github.com/mariaeduardacunha) - [@mrsimpson](https://github.com/mrsimpson) - [@ritwizsinha](https://github.com/ritwizsinha) - [@vickyokrm](https://github.com/vickyokrm) @@ -1466,7 +1901,6 @@ - [@geekgonecrazy](https://github.com/geekgonecrazy) - [@ggazzo](https://github.com/ggazzo) - [@lolimay](https://github.com/lolimay) -- [@mariaeduardacunha](https://github.com/mariaeduardacunha) - [@pierre-lehnen-rc](https://github.com/pierre-lehnen-rc) - [@renatobecker](https://github.com/renatobecker) - [@rodrigok](https://github.com/rodrigok) @@ -1732,20 +2166,23 @@ - Add missing password field back to administration area ([#16171](https://github.com/RocketChat/Rocket.Chat/pull/16171)) -- JS errors on Administration page ([#16139](https://github.com/RocketChat/Rocket.Chat/pull/16139)) +- JS errors on Administration page ([#16139](https://github.com/RocketChat/Rocket.Chat/pull/16139) by [@mariaeduardacunha](https://github.com/mariaeduardacunha))
🔍 Minor changes -- Release 2.4.1 ([#16195](https://github.com/RocketChat/Rocket.Chat/pull/16195)) +- Release 2.4.1 ([#16195](https://github.com/RocketChat/Rocket.Chat/pull/16195) by [@mariaeduardacunha](https://github.com/mariaeduardacunha))
+### 👩‍💻👨‍💻 Contributors 😍 + +- [@mariaeduardacunha](https://github.com/mariaeduardacunha) + ### 👩‍💻👨‍💻 Core Team 🤓 - [@d-gubert](https://github.com/d-gubert) -- [@mariaeduardacunha](https://github.com/mariaeduardacunha) - [@rodrigok](https://github.com/rodrigok) - [@sampaiodiego](https://github.com/sampaiodiego) @@ -1836,17 +2273,17 @@ - Admin Setting descriptions and Storybook ([#15994](https://github.com/RocketChat/Rocket.Chat/pull/15994)) -- width of upload-progress-text ([#16023](https://github.com/RocketChat/Rocket.Chat/pull/16023)) +- width of upload-progress-text ([#16023](https://github.com/RocketChat/Rocket.Chat/pull/16023) by [@mariaeduardacunha](https://github.com/mariaeduardacunha)) -- Message list scrolling to bottom on reactions ([#16018](https://github.com/RocketChat/Rocket.Chat/pull/16018)) +- Message list scrolling to bottom on reactions ([#16018](https://github.com/RocketChat/Rocket.Chat/pull/16018) by [@mariaeduardacunha](https://github.com/mariaeduardacunha)) - SAML logout error ([#15978](https://github.com/RocketChat/Rocket.Chat/pull/15978)) - Added Join button to Read Only rooms. ([#16016](https://github.com/RocketChat/Rocket.Chat/pull/16016)) -- z-index of new message button ([#16013](https://github.com/RocketChat/Rocket.Chat/pull/16013)) +- z-index of new message button ([#16013](https://github.com/RocketChat/Rocket.Chat/pull/16013) by [@mariaeduardacunha](https://github.com/mariaeduardacunha)) -- new message popup ([#16017](https://github.com/RocketChat/Rocket.Chat/pull/16017)) +- new message popup ([#16017](https://github.com/RocketChat/Rocket.Chat/pull/16017) by [@mariaeduardacunha](https://github.com/mariaeduardacunha)) - Changed renderMessage priority, fixed Katex on/off setting ([#16012](https://github.com/RocketChat/Rocket.Chat/pull/16012)) @@ -1939,6 +2376,7 @@ - [@breaking-let](https://github.com/breaking-let) - [@iannuzzelli](https://github.com/iannuzzelli) - [@localguru](https://github.com/localguru) +- [@mariaeduardacunha](https://github.com/mariaeduardacunha) - [@n-se](https://github.com/n-se) - [@ritwizsinha](https://github.com/ritwizsinha) - [@wreiske](https://github.com/wreiske) @@ -1953,7 +2391,6 @@ - [@geekgonecrazy](https://github.com/geekgonecrazy) - [@ggazzo](https://github.com/ggazzo) - [@lolimay](https://github.com/lolimay) -- [@mariaeduardacunha](https://github.com/mariaeduardacunha) - [@pierre-lehnen-rc](https://github.com/pierre-lehnen-rc) - [@renatobecker](https://github.com/renatobecker) - [@rodrigok](https://github.com/rodrigok) @@ -2127,7 +2564,7 @@ - Mentions before blockquote ([#15774](https://github.com/RocketChat/Rocket.Chat/pull/15774)) -- Sidebar font color was not respecting theming ([#15745](https://github.com/RocketChat/Rocket.Chat/pull/15745)) +- Sidebar font color was not respecting theming ([#15745](https://github.com/RocketChat/Rocket.Chat/pull/15745) by [@mariaeduardacunha](https://github.com/mariaeduardacunha)) - Add livechat agents into departments ([#15732](https://github.com/RocketChat/Rocket.Chat/pull/15732)) @@ -2202,6 +2639,7 @@ ### 👩‍💻👨‍💻 Contributors 😍 - [@Exordian](https://github.com/Exordian) +- [@mariaeduardacunha](https://github.com/mariaeduardacunha) - [@mpdbl](https://github.com/mpdbl) - [@nstseek](https://github.com/nstseek) - [@rajvaibhavdubey](https://github.com/rajvaibhavdubey) @@ -2215,7 +2653,6 @@ - [@gabriellsh](https://github.com/gabriellsh) - [@geekgonecrazy](https://github.com/geekgonecrazy) - [@ggazzo](https://github.com/ggazzo) -- [@mariaeduardacunha](https://github.com/mariaeduardacunha) - [@pierre-lehnen-rc](https://github.com/pierre-lehnen-rc) - [@renatobecker](https://github.com/renatobecker) - [@rodrigok](https://github.com/rodrigok) diff --git a/README.md b/README.md index 582baf0ec5c..b2bda6396d0 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,6 @@ * [RocketChatLauncher](#rocketchatlauncher) * [Layershift](#layershift) * [Yunohost.org](#yunohostorg) - * [DPlatform](#dplatform) * [IndieHosters](#indiehosters) * [Ubuntu 16.04](#ubuntu-1604) * [Cloudron.io](#cloudronio) @@ -36,7 +35,6 @@ * [Raspberry Pi 2](#raspberry-pi-2) * [Koozali SME](#koozali-sme) * [Ubuntu VPS](#ubuntu-vps) - * [Hyper.sh](#hypersh) * [WeDeploy](#wedeploy) * [D2C.io](#d2cio) * [Syncloud.org](#syncloudorg) @@ -127,12 +125,6 @@ Host your own Rocket.Chat server in a few seconds. [![Install RocketChat with YunoHost](https://install-app.yunohost.org/install-with-yunohost.png)](https://install-app.yunohost.org/?app=rocketchat) -## DPlatform - -The easiest way to install a ready-to-run Rocket.Chat server on a Linux machine, VM, or VPS. - -[![DP deploy](https://raw.githubusercontent.com/DFabric/DPlatform-ShellCore/images/logo.png)](https://dfabric.github.io/DPlatform-ShellCore) - ## IndieHosters Get your Rocket.Chat instance hosted in an "as a Service" style. You register and we manage it for you! (updates, backup...). @@ -203,9 +195,6 @@ Add Rocket.Chat to this world famous time tested small enterprise server today. ## Ubuntu VPS Follow these [deployment instructions](https://rocket.chat/docs/installation/manual-installation/ubuntu/). -## Hyper.sh -Follow their [deployment instructions](https://rocket.chat/docs/installation/paas-deployments/hyper-sh/) to install a per-second billed Rocket.Chat instance on [Hyper.sh](https://rocket.chat/docs/installation/paas-deployments/hyper-sh/). - ## WeDeploy Install Rocket.Chat on [WeDeploy](https://wedeploy.com): diff --git a/app/accounts/index.js b/app/accounts/index.js deleted file mode 100644 index ca39cd0df4b..00000000000 --- a/app/accounts/index.js +++ /dev/null @@ -1 +0,0 @@ -export * from './server/index'; diff --git a/app/action-links/client/index.js b/app/action-links/client/index.js index 34c929c096f..c09886562a2 100644 --- a/app/action-links/client/index.js +++ b/app/action-links/client/index.js @@ -1,5 +1,4 @@ -import { actionLinks } from '../both/lib/actionLinks'; -import './lib/actionLinks'; +import { actionLinks } from './lib/actionLinks'; import './init'; import './stylesheets/actionLinks.css'; diff --git a/app/action-links/client/init.js b/app/action-links/client/init.js index 2865be4279c..b5f218b1ca1 100644 --- a/app/action-links/client/init.js +++ b/app/action-links/client/init.js @@ -1,14 +1,14 @@ import { Blaze } from 'meteor/blaze'; import { Template } from 'meteor/templating'; -import { handleError } from '../../utils'; -import { fireGlobalEvent, Layout } from '../../ui-utils'; +import { handleError } from '../../utils/client'; +import { fireGlobalEvent, Layout } from '../../ui-utils/client'; import { messageArgs } from '../../ui-utils/client/lib/messageArgs'; -import { actionLinks } from '../both/lib/actionLinks'; +import { actionLinks } from './lib/actionLinks'; Template.room.events({ - 'click .action-link'(event, instance) { + 'click [data-actionlink]'(event, instance) { event.preventDefault(); event.stopPropagation(); diff --git a/app/action-links/client/lib/actionLinks.js b/app/action-links/client/lib/actionLinks.js index 4391eda94af..b3d911398da 100644 --- a/app/action-links/client/lib/actionLinks.js +++ b/app/action-links/client/lib/actionLinks.js @@ -1,27 +1,58 @@ import { Meteor } from 'meteor/meteor'; -import { handleError } from '../../../utils'; -import { actionLinks } from '../../both/lib/actionLinks'; -// Action Links Handler. This method will be called off the client. +import { handleError } from '../../../utils/client'; +import { Messages, Subscriptions } from '../../../models/client'; -actionLinks.run = (name, messageId, instance) => { - const message = actionLinks.getMessage(name, messageId); +// Action Links namespace creation. +export const actionLinks = { + actions: {}, + register(name, funct) { + actionLinks.actions[name] = funct; + }, + getMessage(name, messageId) { + const userId = Meteor.userId(); + if (!userId) { + throw new Meteor.Error('error-invalid-user', 'Invalid user', { function: 'actionLinks.getMessage' }); + } + + const message = Messages.findOne({ _id: messageId }); + if (!message) { + throw new Meteor.Error('error-invalid-message', 'Invalid message', { function: 'actionLinks.getMessage' }); + } + + const subscription = Subscriptions.findOne({ + rid: message.rid, + 'u._id': userId, + }); + if (!subscription) { + throw new Meteor.Error('error-not-allowed', 'Not allowed', { function: 'actionLinks.getMessage' }); + } + + if (!message.actionLinks || !message.actionLinks[name]) { + throw new Meteor.Error('error-invalid-actionlink', 'Invalid action link', { function: 'actionLinks.getMessage' }); + } - const actionLink = message.actionLinks[name]; + return message; + }, + run(name, messageId, instance) { + const message = actionLinks.getMessage(name, messageId); - let ranClient = false; + const actionLink = message.actionLinks[name]; - if (actionLinks && actionLinks.actions && actionLinks.actions[actionLink.method_id]) { - // run just on client side - actionLinks.actions[actionLink.method_id](message, actionLink.params, instance); + let ranClient = false; - ranClient = true; - } + if (actionLinks && actionLinks.actions && actionLinks.actions[actionLink.method_id]) { + // run just on client side + actionLinks.actions[actionLink.method_id](message, actionLink.params, instance); - // and run on server side - Meteor.call('actionLinkHandler', name, messageId, (err) => { - if (err && !ranClient) { - handleError(err); + ranClient = true; } - }); + + // and run on server side + Meteor.call('actionLinkHandler', name, messageId, (err) => { + if (err && !ranClient) { + handleError(err); + } + }); + }, }; diff --git a/app/action-links/index.js b/app/action-links/index.js deleted file mode 100644 index a67eca871ef..00000000000 --- a/app/action-links/index.js +++ /dev/null @@ -1,8 +0,0 @@ -import { Meteor } from 'meteor/meteor'; - -if (Meteor.isClient) { - module.exports = require('./client/index.js'); -} -if (Meteor.isServer) { - module.exports = require('./server/index.js'); -} diff --git a/app/action-links/server/actionLinkHandler.js b/app/action-links/server/actionLinkHandler.js index 067f727e3dd..7ccd1b05775 100644 --- a/app/action-links/server/actionLinkHandler.js +++ b/app/action-links/server/actionLinkHandler.js @@ -1,6 +1,6 @@ import { Meteor } from 'meteor/meteor'; -import { actionLinks } from '../both/lib/actionLinks'; +import { actionLinks } from './lib/actionLinks'; // Action Links Handler. This method will be called off the client. Meteor.methods({ diff --git a/app/action-links/server/index.js b/app/action-links/server/index.js index b1c484f7988..a6fb9f92b74 100644 --- a/app/action-links/server/index.js +++ b/app/action-links/server/index.js @@ -1,4 +1,4 @@ -import { actionLinks } from '../both/lib/actionLinks'; +import { actionLinks } from './lib/actionLinks'; import './actionLinkHandler'; export { diff --git a/app/action-links/both/lib/actionLinks.js b/app/action-links/server/lib/actionLinks.js similarity index 93% rename from app/action-links/both/lib/actionLinks.js rename to app/action-links/server/lib/actionLinks.js index c87c712e079..3f7b2f2e577 100644 --- a/app/action-links/both/lib/actionLinks.js +++ b/app/action-links/server/lib/actionLinks.js @@ -1,6 +1,6 @@ import { Meteor } from 'meteor/meteor'; -import { Messages, Subscriptions } from '../../../models'; +import { Messages, Subscriptions } from '../../../models/server'; // Action Links namespace creation. export const actionLinks = { diff --git a/app/api/index.js b/app/api/index.js deleted file mode 100644 index ca39cd0df4b..00000000000 --- a/app/api/index.js +++ /dev/null @@ -1 +0,0 @@ -export * from './server/index'; diff --git a/app/api/server/api.js b/app/api/server/api.js index d62382af875..5a834be3655 100644 --- a/app/api/server/api.js +++ b/app/api/server/api.js @@ -374,7 +374,7 @@ export class APIClass extends Restivus { 'error-unauthorized': 'unauthorized', }[e.error] || 'failure'; - result = API.v1[apiMethod](typeof e === 'string' ? e : e.message, e.error, undefined, e); + result = API.v1[apiMethod](typeof e === 'string' ? e : e.message, e.error, process.env.TEST_MODE ? e.stack : undefined, e); } finally { delete Accounts._accountData[connection.id]; } diff --git a/app/api/server/lib/rooms.js b/app/api/server/lib/rooms.js index 94eb63685f3..b9e73acbfa6 100644 --- a/app/api/server/lib/rooms.js +++ b/app/api/server/lib/rooms.js @@ -56,6 +56,34 @@ export async function findAdminRooms({ uid, filter, types = [], pagination: { of }; } +export async function findAdminRoom({ uid, rid }) { + if (!await hasPermissionAsync(uid, 'view-room-administration')) { + throw new Error('error-not-authorized'); + } + const fields = { + prid: 1, + fname: 1, + name: 1, + t: 1, + cl: 1, + u: 1, + usernames: 1, + usersCount: 1, + muted: 1, + unmuted: 1, + ro: 1, + default: 1, + favorite: 1, + featured: 1, + topic: 1, + msgs: 1, + archived: 1, + tokenpass: 1, + }; + + return Rooms.findOneById(rid, { fields }); +} + export async function findChannelAndPrivateAutocomplete({ uid, selector }) { if (!await hasPermissionAsync(uid, 'view-other-user-channels')) { return { items: [] }; diff --git a/app/api/server/v1/assets.js b/app/api/server/v1/assets.js index eacf92ae31c..108f9649ffe 100644 --- a/app/api/server/v1/assets.js +++ b/app/api/server/v1/assets.js @@ -1,7 +1,7 @@ import { Meteor } from 'meteor/meteor'; import Busboy from 'busboy'; -import { RocketChatAssets } from '../../../assets'; +import { RocketChatAssets } from '../../../assets/server'; import { API } from '../api'; API.v1.addRoute('assets.setAsset', { authRequired: true }, { diff --git a/app/api/server/v1/chat.js b/app/api/server/v1/chat.js index 8e5ac669d22..69685a3f6f9 100644 --- a/app/api/server/v1/chat.js +++ b/app/api/server/v1/chat.js @@ -4,7 +4,7 @@ import { Match, check } from 'meteor/check'; import { Messages } from '../../../models'; import { canAccessRoom, hasPermission } from '../../../authorization'; import { normalizeMessagesForUser } from '../../../utils/server/lib/normalizeMessagesForUser'; -import { processWebhookMessage } from '../../../lib'; +import { processWebhookMessage } from '../../../lib/server'; import { API } from '../api'; import Rooms from '../../../models/server/models/Rooms'; import Users from '../../../models/server/models/Users'; diff --git a/app/api/server/v1/permissions.js b/app/api/server/v1/permissions.js index c5d79053328..e74c9566251 100644 --- a/app/api/server/v1/permissions.js +++ b/app/api/server/v1/permissions.js @@ -2,7 +2,7 @@ import { Meteor } from 'meteor/meteor'; import { Match, check } from 'meteor/check'; import { hasPermission } from '../../../authorization'; -import { Permissions, Roles } from '../../../models'; +import { Permissions, Roles } from '../../../models/server'; import { API } from '../api'; /** diff --git a/app/api/server/v1/rooms.js b/app/api/server/v1/rooms.js index 2f8a7df23e0..86711691782 100644 --- a/app/api/server/v1/rooms.js +++ b/app/api/server/v1/rooms.js @@ -4,7 +4,7 @@ import Busboy from 'busboy'; import { FileUpload } from '../../../file-upload'; import { Rooms, Messages } from '../../../models'; import { API } from '../api'; -import { findAdminRooms, findChannelAndPrivateAutocomplete } from '../lib/rooms'; +import { findAdminRooms, findChannelAndPrivateAutocomplete, findAdminRoom } from '../lib/rooms'; function findRoomByIdOrName({ params, checkedArchived = true }) { if ((!params.roomId || !params.roomId.trim()) && (!params.roomName || !params.roomName.trim())) { @@ -299,6 +299,22 @@ API.v1.addRoute('rooms.adminRooms', { authRequired: true }, { }, }); +API.v1.addRoute('rooms.adminRooms.getRoom', { authRequired: true }, { + get() { + const { rid } = this.requestParams(); + const room = Promise.await(findAdminRoom({ + uid: this.userId, + rid, + })); + + if (!room) { + return API.v1.failure('not-allowed', 'Not Allowed'); + } + return API.v1.success(room); + }, +}); + + API.v1.addRoute('rooms.autocomplete.channelAndPrivate', { authRequired: true }, { get() { const { selector } = this.queryParams; @@ -312,3 +328,28 @@ API.v1.addRoute('rooms.autocomplete.channelAndPrivate', { authRequired: true }, }))); }, }); + +API.v1.addRoute('rooms.saveRoomSettings', { authRequired: true }, { + post() { + const { rid, ...params } = this.bodyParams; + + const result = Meteor.runAsUser(this.userId, () => Meteor.call('saveRoomSettings', rid, params)); + + return API.v1.success({ rid: result.rid }); + }, +}); + +API.v1.addRoute('rooms.changeArchivationState', { authRequired: true }, { + post() { + const { rid, action } = this.bodyParams; + + let result; + if (action === 'archive') { + result = Meteor.runAsUser(this.userId, () => Meteor.call('archiveRoom', rid)); + } else { + result = Meteor.runAsUser(this.userId, () => Meteor.call('unarchiveRoom', rid)); + } + + return API.v1.success({ result }); + }, +}); diff --git a/app/api/server/v1/settings.js b/app/api/server/v1/settings.js index 1fd8dba80c0..42db479903f 100644 --- a/app/api/server/v1/settings.js +++ b/app/api/server/v1/settings.js @@ -3,7 +3,7 @@ import { Match, check } from 'meteor/check'; import { ServiceConfiguration } from 'meteor/service-configuration'; import _ from 'underscore'; -import { Settings } from '../../../models'; +import { Settings } from '../../../models/server'; import { hasPermission } from '../../../authorization'; import { API } from '../api'; diff --git a/app/api/server/v1/users.js b/app/api/server/v1/users.js index 0598d8a430a..65aee384de9 100644 --- a/app/api/server/v1/users.js +++ b/app/api/server/v1/users.js @@ -30,6 +30,8 @@ API.v1.addRoute('users.create', { authRequired: true }, { password: String, username: String, active: Match.Maybe(Boolean), + bio: Match.Maybe(String), + statusText: Match.Maybe(String), roles: Match.Maybe(Array), joinDefaultChannels: Match.Maybe(Boolean), requirePasswordChange: Match.Maybe(Boolean), @@ -431,6 +433,7 @@ API.v1.addRoute('users.update', { authRequired: true, twoFactorRequired: true }, name: Match.Maybe(String), password: Match.Maybe(String), username: Match.Maybe(String), + bio: Match.Maybe(String), statusText: Match.Maybe(String), active: Match.Maybe(Boolean), roles: Match.Maybe(Array), @@ -536,7 +539,6 @@ API.v1.addRoute('users.setPreferences', { authRequired: true }, { mobileNotifications: Match.Maybe(String), enableAutoAway: Match.Maybe(Boolean), highlights: Match.Maybe(Array), - desktopNotificationDuration: Match.Maybe(Number), desktopNotificationRequireInteraction: Match.Maybe(Boolean), messageViewMode: Match.Maybe(Number), hideUsernames: Match.Maybe(Boolean), diff --git a/app/apps/client/admin/appManage.html b/app/apps/client/admin/appManage.html index 783647e27ae..dbd37a41ee4 100644 --- a/app/apps/client/admin/appManage.html +++ b/app/apps/client/admin/appManage.html @@ -104,6 +104,22 @@
{{/each}} + {{#if essentials}} +
+ {{_ "Apps_Essential_Alert"}} + +
+

{{_ "Apps_Essential_Disclaimer"}}

+
+ {{/if}} + {{#if categories}}

{{_ "Categories"}}

@@ -359,8 +375,8 @@
{{> CodeMirror name=id options=getEditorOptions code=value }}
- - + +
{{/if}} @@ -463,7 +479,7 @@ {{#if hasChanges section}} {{_ "Save_to_enable_this_action"}} {{else}} - + {{/if}} {{/if}} @@ -472,14 +488,14 @@
- +
{{else}}
-
{{_ 'Select_file'}} +
{{_ 'Select_file'}}
diff --git a/app/apps/client/admin/appManage.js b/app/apps/client/admin/appManage.js index fb3a2c52007..daf10f0dd17 100644 --- a/app/apps/client/admin/appManage.js +++ b/app/apps/client/admin/appManage.js @@ -317,6 +317,12 @@ Template.appManage.helpers({ bundleAppNames(apps) { return apps.map((app) => app.latest.name).join(', '); }, + essentials() { + return Template.instance()._app.get('essentials')?.map((interfaceName) => ({ + interfaceName, + i18nKey: `Apps_Interface_${ interfaceName }`, + })); + }, }); Template.appManage.events({ diff --git a/app/apps/client/admin/apps.js b/app/apps/client/admin/apps.js index 86f32c90c23..045ac52571b 100644 --- a/app/apps/client/admin/apps.js +++ b/app/apps/client/admin/apps.js @@ -226,7 +226,7 @@ Template.apps.events({ } = instance.state.get('apps').find(({ id }) => id === currentTarget.dataset.id); FlowRouter.go('app-manage', { appId }, { version }); }, - async 'click .js-install, click .js-update'(event, instance) { + async 'click .js-update'(event, instance) { event.preventDefault(); event.stopPropagation(); @@ -240,7 +240,7 @@ Template.apps.events({ instance.startAppWorking(app.id); try { - const { status } = await Apps.installApp(app.id, app.marketplaceVersion); + const { status } = await Apps.updateApp(app.id, app.marketplaceVersion); warnStatusChange(app.name, status); } catch (error) { handleAPIError(error); diff --git a/app/apps/client/admin/helpers.js b/app/apps/client/admin/helpers.js index f78b4c66159..a1b0b2cdf9c 100644 --- a/app/apps/client/admin/helpers.js +++ b/app/apps/client/admin/helpers.js @@ -363,11 +363,12 @@ export const appStatusSpanProps = ({ export const formatPrice = (price) => `\$${ Number.parseFloat(price).toFixed(2) }`; -export const formatPricingPlan = ({ strategy, price, tiers }) => { +export const formatPricingPlan = ({ strategy, price, tiers = [] }) => { const { perUnit = false } = (Array.isArray(tiers) && tiers.find((tier) => tier.price === price)) || {}; const pricingPlanTranslationString = [ 'Apps_Marketplace_pricingPlan', + Array.isArray(tiers) && tiers.length > 0 && 'startingAt', strategy, perUnit && 'perUser', ].filter(Boolean).join('_'); diff --git a/app/apps/client/admin/marketplace.js b/app/apps/client/admin/marketplace.js index 495bda2a90a..ed39d11b8bc 100644 --- a/app/apps/client/admin/marketplace.js +++ b/app/apps/client/admin/marketplace.js @@ -273,7 +273,7 @@ Template.marketplace.events({ } = instance.state.get('apps').find(({ id }) => id === currentTarget.dataset.id); FlowRouter.go('marketplace-app', { appId }, { version: version || marketplaceVersion }); }, - async 'click .js-install, click .js-update'(event, instance) { + async 'click .js-install'(event, instance) { event.preventDefault(); event.stopPropagation(); @@ -284,6 +284,7 @@ Template.marketplace.events({ } const { currentTarget: button } = event; + const app = instance.state.get('apps').find(({ id }) => id === button.dataset.id); instance.startAppWorking(app.id); @@ -297,6 +298,31 @@ Template.marketplace.events({ instance.stopAppWorking(app.id); } }, + async 'click .js-update'(event, instance) { + event.preventDefault(); + event.stopPropagation(); + + const isLoggedInCloud = await checkCloudLogin(); + instance.state.set('isLoggedInCloud', isLoggedInCloud); + if (!isLoggedInCloud) { + return; + } + + const { currentTarget: button } = event; + + const app = instance.state.get('apps').find(({ id }) => id === button.dataset.id); + + instance.startAppWorking(app.id); + + try { + const { status } = await Apps.updateApp(app.id, app.marketplaceVersion); + warnStatusChange(app.name, status); + } catch (error) { + handleAPIError(error); + } finally { + instance.stopAppWorking(app.id); + } + }, async 'click .js-purchase'(event, instance) { event.preventDefault(); event.stopPropagation(); diff --git a/app/apps/client/orchestrator.js b/app/apps/client/orchestrator.js index 54c614044fe..0b7bdfd5883 100644 --- a/app/apps/client/orchestrator.js +++ b/app/apps/client/orchestrator.js @@ -4,7 +4,7 @@ import toastr from 'toastr'; import { AppWebsocketReceiver } from './communication'; import { APIClient } from '../../utils'; -import { registerAdminSidebarItem } from '../../ui-admin/client'; +import { registerAdminSidebarItem } from '../../../client/admin'; import { CachedCollectionManager } from '../../ui-cached-collection'; import { hasAtLeastOnePermission } from '../../authorization'; import { handleI18nResources } from './i18n'; diff --git a/app/apps/client/routes.js b/app/apps/client/routes.js index 66005d26b87..c8ff516040e 100644 --- a/app/apps/client/routes.js +++ b/app/apps/client/routes.js @@ -1,7 +1,7 @@ import { FlowRouter } from 'meteor/kadira:flow-router'; import { BlazeLayout } from 'meteor/kadira:blaze-layout'; -import { registerAdminRoute } from '../../ui-admin/client'; +import { registerAdminRoute } from '../../../client/admin'; import { Apps } from './orchestrator'; registerAdminRoute('/apps/what-is-it', { diff --git a/app/apps/server/bridges/internal.js b/app/apps/server/bridges/internal.js index ef883a68437..db667154190 100644 --- a/app/apps/server/bridges/internal.js +++ b/app/apps/server/bridges/internal.js @@ -6,6 +6,10 @@ export class AppInternalBridge { } getUsernamesOfRoomById(roomId) { + if (!roomId) { + return []; + } + const records = Subscriptions.findByRoomIdWhenUsernameExists(roomId, { fields: { 'u.username': 1, diff --git a/app/apps/server/bridges/listeners.js b/app/apps/server/bridges/listeners.js index 693c55271c3..c3d481da738 100644 --- a/app/apps/server/bridges/listeners.js +++ b/app/apps/server/bridges/listeners.js @@ -1,8 +1,53 @@ +import { AppInterface } from '@rocket.chat/apps-engine/definition/metadata'; + export class AppListenerBridge { constructor(orch) { this.orch = orch; } + async handleEvent(event, ...payload) { + const method = (() => { + switch (event) { + case AppInterface.IPreMessageSentPrevent: + case AppInterface.IPreMessageSentExtend: + case AppInterface.IPreMessageSentModify: + case AppInterface.IPostMessageSent: + case AppInterface.IPreMessageDeletePrevent: + case AppInterface.IPostMessageDeleted: + case AppInterface.IPreMessageUpdatedPrevent: + case AppInterface.IPreMessageUpdatedExtend: + case AppInterface.IPreMessageUpdatedModify: + case AppInterface.IPostMessageUpdated: + return 'messageEvent'; + case AppInterface.IPreRoomCreatePrevent: + case AppInterface.IPreRoomCreateExtend: + case AppInterface.IPreRoomCreateModify: + case AppInterface.IPostRoomCreate: + case AppInterface.IPreRoomDeletePrevent: + case AppInterface.IPostRoomDeleted: + case AppInterface.IPreRoomUserJoined: + case AppInterface.IPostRoomUserJoined: + return 'roomEvent'; + case AppInterface.IPostExternalComponentOpened: + case AppInterface.IPostExternalComponentClosed: + return 'externalComponentEvent'; + /** + * @deprecated please prefer the AppInterface.IPostLivechatRoomClosed event + */ + case AppInterface.ILivechatRoomClosedHandler: + case AppInterface.IPostLivechatRoomStarted: + case AppInterface.IPostLivechatRoomClosed: + case AppInterface.IPostLivechatAgentAssigned: + case AppInterface.IPostLivechatAgentUnassigned: + return 'livechatEvent'; + case AppInterface.IUIKitInteractionHandler: + return 'uiKitInteractionEvent'; + } + })(); + + return this[method](event, ...payload); + } + async messageEvent(inte, message) { const msg = this.orch.getConverters().get('messages').convertMessage(message); const result = await this.orch.getManager().getListenerManager().executeListener(inte, msg); @@ -11,56 +56,54 @@ export class AppListenerBridge { return result; } return this.orch.getConverters().get('messages').convertAppMessage(result); - - // try { - - // } catch (e) { - // this.orch.debugLog(`${ e.name }: ${ e.message }`); - // this.orch.debugLog(e.stack); - // } } - async roomEvent(inte, room) { + async roomEvent(inte, room, ...payload) { const rm = this.orch.getConverters().get('rooms').convertRoom(room); - const result = await this.orch.getManager().getListenerManager().executeListener(inte, rm); + + const params = (() => { + switch (inte) { + case AppInterface.IPreRoomUserJoined: + case AppInterface.IPostRoomUserJoined: + const [joiningUser, invitingUser] = payload; + return { + room: rm, + joiningUser: this.orch.getConverters().get('users').convertToApp(joiningUser), + invitingUser: this.orch.getConverters().get('users').convertToApp(invitingUser), + }; + default: + return rm; + } + })(); + + const result = await this.orch.getManager().getListenerManager().executeListener(inte, params); if (typeof result === 'boolean') { return result; } return this.orch.getConverters().get('rooms').convertAppRoom(result); - - // try { - - // } catch (e) { - // this.orch.debugLog(`${ e.name }: ${ e.message }`); - // this.orch.debugLog(e.stack); - // } } async externalComponentEvent(inte, externalComponent) { - const result = await this.orch.getManager().getListenerManager().executeListener(inte, externalComponent); - - return result; + return this.orch.getManager().getListenerManager().executeListener(inte, externalComponent); } async uiKitInteractionEvent(inte, action) { return this.orch.getManager().getListenerManager().executeListener(inte, action); - - // try { - - // } catch (e) { - // this.orch.debugLog(`${ e.name }: ${ e.message }`); - // this.orch.debugLog(e.stack); - // } } - async livechatEvent(inte, room) { - const rm = this.orch.getConverters().get('rooms').convertRoom(room); - const result = await this.orch.getManager().getListenerManager().executeListener(inte, rm); + async livechatEvent(inte, data) { + switch (inte) { + case AppInterface.IPostLivechatAgentAssigned: + case AppInterface.IPostLivechatAgentUnassigned: + return this.orch.getManager().getListenerManager().executeListener(inte, { + room: this.orch.getConverters().get('rooms').convertRoom(data.room), + agent: this.orch.getConverters().get('users').convertToApp(data.user), + }); + default: + const room = this.orch.getConverters().get('rooms').convertRoom(data); - if (typeof result === 'boolean') { - return result; + return this.orch.getManager().getListenerManager().executeListener(inte, room); } - return this.orch.getConverters().get('rooms').convertAppRoom(result); } } diff --git a/app/apps/server/bridges/messages.js b/app/apps/server/bridges/messages.js index cc53aa392bd..e3f3e722dc6 100644 --- a/app/apps/server/bridges/messages.js +++ b/app/apps/server/bridges/messages.js @@ -1,6 +1,6 @@ import { Random } from 'meteor/random'; -import { Messages, Users, Subscriptions } from '../../../models'; +import { Messages, Users, Subscriptions } from '../../../models/server'; import { Notifications } from '../../../notifications'; import { updateMessage } from '../../../lib/server/functions/updateMessage'; import { executeSendMessage } from '../../../lib/server/methods/sendMessage'; @@ -48,12 +48,15 @@ export class AppMessageBridge { const msg = this.orch.getConverters().get('messages').convertAppMessage(message); - Notifications.notifyUser(user.id, 'message', Object.assign(msg, { + if (!msg) { + return; + } + + Notifications.notifyUser(user.id, 'message', { + ...msg, _id: Random.id(), ts: new Date(), - u: undefined, - editor: undefined, - })); + }); } async notifyRoom(room, message, appId) { @@ -68,8 +71,6 @@ export class AppMessageBridge { _id: Random.id(), rid: room.id, ts: new Date(), - u: undefined, - editor: undefined, }); const users = Subscriptions.findByRoomIdWhenUserIdExists(room.id, { fields: { 'u._id': 1 } }) diff --git a/app/apps/server/bridges/users.js b/app/apps/server/bridges/users.js index 5aac0567bed..cbcdab1795d 100644 --- a/app/apps/server/bridges/users.js +++ b/app/apps/server/bridges/users.js @@ -1,10 +1,9 @@ import { Random } from 'meteor/random'; import { setUserAvatar, checkUsernameAvailability, deleteUser, _setStatusTextPromise } from '../../../lib/server/functions'; -import { Users } from '../../../models'; +import { Users } from '../../../models/server'; import { Users as UsersRaw } from '../../../models/server/raw'; - export class AppUserBridge { constructor(orch) { this.orch = orch; @@ -25,7 +24,7 @@ export class AppUserBridge { async getAppUser(appId) { this.orch.debugLog(`The App ${ appId } is getting its assigned user`); - const user = Users.findOne({ appId }); + const user = Users.findOneByAppId(appId); return this.orch.getConverters().get('users').convertToApp(user); } diff --git a/app/apps/server/converters/messages.js b/app/apps/server/converters/messages.js index 0da7cbd768d..11bf7f99eb0 100644 --- a/app/apps/server/converters/messages.js +++ b/app/apps/server/converters/messages.js @@ -78,7 +78,7 @@ export class AppMessagesConverter { } convertAppMessage(message) { - if (!message) { + if (!message || !message.room) { return undefined; } diff --git a/app/apps/server/converters/rooms.js b/app/apps/server/converters/rooms.js index 8c8aedbe144..1fac2d4d6b6 100644 --- a/app/apps/server/converters/rooms.js +++ b/app/apps/server/converters/rooms.js @@ -69,7 +69,7 @@ export class AppRoomsConverter { } const newRoom = { - _id: room.id, + ...room.id && { _id: room.id }, fname: room.displayName, name: room.slugifiedName, t: room.type, @@ -116,6 +116,7 @@ export class AppRoomsConverter { customFields: 'customFields', isWaitingResponse: 'waitingResponse', isOpen: 'open', + _USERNAMES: '_USERNAMES', isDefault: (room) => { const result = !!room.default; delete room.default; diff --git a/app/apps/server/index.js b/app/apps/server/index.js index aa24a2d7892..ad3096af315 100644 --- a/app/apps/server/index.js +++ b/app/apps/server/index.js @@ -1,3 +1,3 @@ import './cron'; -export { Apps } from './orchestrator'; +export { Apps, AppEvents } from './orchestrator'; diff --git a/app/apps/server/orchestrator.js b/app/apps/server/orchestrator.js index 502ea2537a7..2034b02ad13 100644 --- a/app/apps/server/orchestrator.js +++ b/app/apps/server/orchestrator.js @@ -1,5 +1,7 @@ -import { Meteor } from 'meteor/meteor'; +import { EssentialAppDisabledException } from '@rocket.chat/apps-engine/definition/exceptions'; +import { AppInterface } from '@rocket.chat/apps-engine/definition/metadata'; import { AppManager } from '@rocket.chat/apps-engine/server/AppManager'; +import { Meteor } from 'meteor/meteor'; import { Logger } from '../../logger'; import { AppsLogsModel, AppsModel, AppsPersistenceModel, Permissions } from '../../models'; @@ -16,7 +18,6 @@ function isTesting() { return process.env.TEST_MODE === 'true'; } - class AppServerOrchestrator { constructor() { this._isInitialized = false; @@ -24,7 +25,7 @@ class AppServerOrchestrator { initialize() { this._rocketchatLogger = new Logger('Rocket.Chat Apps'); - Permissions.createOrUpdate('manage-apps', ['admin']); + Permissions.create('manage-apps', ['admin']); this._marketplaceUrl = 'https://marketplace.rocket.chat'; @@ -155,8 +156,23 @@ class AppServerOrchestrator { return this._manager.updateAppsMarketplaceInfo(apps) .then(() => this._manager.get()); } + + async triggerEvent(event, ...payload) { + if (!this.isLoaded()) { + return; + } + + return this.getBridges().getListenerBridge().handleEvent(event, ...payload).catch((error) => { + if (error instanceof EssentialAppDisabledException) { + throw new Meteor.Error('error-essential-app-disabled'); + } + + throw error; + }); + } } +export const AppEvents = AppInterface; export const Apps = new AppServerOrchestrator(); settings.addGroup('General', function() { diff --git a/app/assets/index.js b/app/assets/index.js deleted file mode 100644 index ca39cd0df4b..00000000000 --- a/app/assets/index.js +++ /dev/null @@ -1 +0,0 @@ -export * from './server/index'; diff --git a/app/authorization/client/route.js b/app/authorization/client/route.js index 95ccd464cc4..2a09c78da6d 100644 --- a/app/authorization/client/route.js +++ b/app/authorization/client/route.js @@ -1,6 +1,6 @@ import { BlazeLayout } from 'meteor/kadira:blaze-layout'; -import { registerAdminRoute } from '../../ui-admin/client'; +import { registerAdminRoute } from '../../../client/admin'; import { t } from '../../utils/client'; registerAdminRoute('/permissions', { diff --git a/app/authorization/client/startup.js b/app/authorization/client/startup.js index 9e437c26c05..2dd50b95fa2 100644 --- a/app/authorization/client/startup.js +++ b/app/authorization/client/startup.js @@ -2,7 +2,7 @@ import { Meteor } from 'meteor/meteor'; import { Tracker } from 'meteor/tracker'; import { hasAtLeastOnePermission } from './hasPermission'; -import { registerAdminSidebarItem } from '../../ui-admin/client'; +import { registerAdminSidebarItem } from '../../../client/admin'; import { CachedCollectionManager } from '../../ui-cached-collection'; import { APIClient } from '../../utils/client'; import { Roles } from '../../models/client'; diff --git a/app/authorization/server/startup.js b/app/authorization/server/startup.js index 16b2f890658..20ab45d3b99 100644 --- a/app/authorization/server/startup.js +++ b/app/authorization/server/startup.js @@ -1,7 +1,7 @@ /* eslint no-multi-spaces: 0 */ import { Meteor } from 'meteor/meteor'; -import { Roles, Permissions, Settings } from '../../models'; +import { Roles, Permissions, Settings } from '../../models/server'; import { settings } from '../../settings/server'; import { getSettingPermissionId, CONSTANTS } from '../lib'; import { clearCache } from './functions/hasPermission'; @@ -12,97 +12,97 @@ Meteor.startup(function() { // then we can define edit--message instead of edit-message // 2. admin, moderator, and user roles should not be deleted as they are referened in the code. const permissions = [ - { _id: 'access-permissions', roles: ['admin'] }, - { _id: 'access-setting-permissions', roles: ['admin'] }, - { _id: 'add-oauth-service', roles: ['admin'] }, - { _id: 'add-user-to-joined-room', roles: ['admin', 'owner', 'moderator'] }, - { _id: 'add-user-to-any-c-room', roles: ['admin'] }, - { _id: 'add-user-to-any-p-room', roles: [] }, - { _id: 'api-bypass-rate-limit', roles: ['admin', 'bot', 'app'] }, - { _id: 'archive-room', roles: ['admin', 'owner'] }, - { _id: 'assign-admin-role', roles: ['admin'] }, - { _id: 'assign-roles', roles: ['admin'] }, - { _id: 'ban-user', roles: ['admin', 'owner', 'moderator'] }, - { _id: 'bulk-register-user', roles: ['admin'] }, - { _id: 'create-c', roles: ['admin', 'user', 'bot', 'app'] }, - { _id: 'create-d', roles: ['admin', 'user', 'bot', 'app'] }, - { _id: 'create-p', roles: ['admin', 'user', 'bot', 'app'] }, - { _id: 'create-personal-access-tokens', roles: ['admin', 'user'] }, - { _id: 'create-user', roles: ['admin'] }, - { _id: 'clean-channel-history', roles: ['admin'] }, - { _id: 'delete-c', roles: ['admin', 'owner'] }, - { _id: 'delete-d', roles: ['admin'] }, - { _id: 'delete-message', roles: ['admin', 'owner', 'moderator'] }, - { _id: 'delete-own-message', roles: ['admin', 'user'] }, - { _id: 'delete-p', roles: ['admin', 'owner'] }, - { _id: 'delete-user', roles: ['admin'] }, - { _id: 'edit-message', roles: ['admin', 'owner', 'moderator'] }, - { _id: 'edit-other-user-active-status', roles: ['admin'] }, - { _id: 'edit-other-user-info', roles: ['admin'] }, - { _id: 'edit-other-user-password', roles: ['admin'] }, - { _id: 'edit-other-user-avatar', roles: ['admin'] }, - { _id: 'edit-privileged-setting', roles: ['admin'] }, - { _id: 'edit-room', roles: ['admin', 'owner', 'moderator'] }, - { _id: 'edit-room-retention-policy', roles: ['admin'] }, - { _id: 'force-delete-message', roles: ['admin', 'owner'] }, - { _id: 'join-without-join-code', roles: ['admin', 'bot', 'app'] }, - { _id: 'leave-c', roles: ['admin', 'user', 'bot', 'anonymous', 'app'] }, - { _id: 'leave-p', roles: ['admin', 'user', 'bot', 'anonymous', 'app'] }, - { _id: 'manage-assets', roles: ['admin'] }, - { _id: 'manage-emoji', roles: ['admin'] }, - { _id: 'manage-user-status', roles: ['admin'] }, - { _id: 'manage-outgoing-integrations', roles: ['admin'] }, - { _id: 'manage-incoming-integrations', roles: ['admin'] }, - { _id: 'manage-own-outgoing-integrations', roles: ['admin'] }, - { _id: 'manage-own-incoming-integrations', roles: ['admin'] }, - { _id: 'manage-oauth-apps', roles: ['admin'] }, - { _id: 'manage-selected-settings', roles: ['admin'] }, - { _id: 'mention-all', roles: ['admin', 'owner', 'moderator', 'user'] }, - { _id: 'mention-here', roles: ['admin', 'owner', 'moderator', 'user'] }, - { _id: 'mute-user', roles: ['admin', 'owner', 'moderator'] }, - { _id: 'remove-user', roles: ['admin', 'owner', 'moderator'] }, - { _id: 'run-import', roles: ['admin'] }, - { _id: 'run-migration', roles: ['admin'] }, - { _id: 'set-moderator', roles: ['admin', 'owner'] }, - { _id: 'set-owner', roles: ['admin', 'owner'] }, - { _id: 'send-many-messages', roles: ['admin', 'bot', 'app'] }, - { _id: 'set-leader', roles: ['admin', 'owner'] }, - { _id: 'unarchive-room', roles: ['admin'] }, - { _id: 'view-c-room', roles: ['admin', 'user', 'bot', 'app', 'anonymous'] }, - { _id: 'user-generate-access-token', roles: ['admin'] }, - { _id: 'view-d-room', roles: ['admin', 'user', 'bot', 'app', 'guest'] }, - { _id: 'view-full-other-user-info', roles: ['admin'] }, - { _id: 'view-history', roles: ['admin', 'user', 'anonymous'] }, - { _id: 'view-joined-room', roles: ['guest', 'bot', 'app', 'anonymous'] }, - { _id: 'view-join-code', roles: ['admin'] }, - { _id: 'view-logs', roles: ['admin'] }, - { _id: 'view-other-user-channels', roles: ['admin'] }, - { _id: 'view-p-room', roles: ['admin', 'user', 'anonymous', 'guest'] }, - { _id: 'view-privileged-setting', roles: ['admin'] }, - { _id: 'view-room-administration', roles: ['admin'] }, - { _id: 'view-statistics', roles: ['admin'] }, - { _id: 'view-user-administration', roles: ['admin'] }, - { _id: 'preview-c-room', roles: ['admin', 'user', 'anonymous'] }, - { _id: 'view-outside-room', roles: ['admin', 'owner', 'moderator', 'user'] }, - { _id: 'view-broadcast-member-list', roles: ['admin', 'owner', 'moderator'] }, - { _id: 'call-management', roles: ['admin', 'owner', 'moderator'] }, - { _id: 'create-invite-links', roles: ['admin', 'owner', 'moderator'] }, - { _id: 'view-l-room', roles: ['livechat-agent', 'livechat-manager', 'admin'] }, - { _id: 'view-livechat-manager', roles: ['livechat-manager', 'admin'] }, - { _id: 'view-livechat-rooms', roles: ['livechat-manager', 'admin'] }, - { _id: 'close-livechat-room', roles: ['livechat-agent', 'livechat-manager', 'admin'] }, - { _id: 'close-others-livechat-room', roles: ['livechat-manager', 'admin'] }, - { _id: 'save-others-livechat-room-info', roles: ['livechat-manager'] }, - { _id: 'remove-closed-livechat-rooms', roles: ['livechat-manager', 'admin'] }, - { _id: 'view-livechat-analytics', roles: ['livechat-manager', 'admin'] }, - { _id: 'view-livechat-queue', roles: ['livechat-manager', 'admin'] }, - { _id: 'transfer-livechat-guest', roles: ['livechat-manager', 'admin'] }, - { _id: 'manage-livechat-managers', roles: ['livechat-manager', 'admin'] }, - { _id: 'manage-livechat-agents', roles: ['livechat-manager', 'admin'] }, - { _id: 'manage-livechat-departments', roles: ['livechat-manager', 'admin'] }, - { _id: 'view-livechat-departments', roles: ['livechat-manager', 'admin'] }, - { _id: 'add-livechat-department-agents', roles: ['livechat-manager', 'admin'] }, - { _id: 'view-livechat-current-chats', roles: ['livechat-manager', 'admin'] }, + { _id: 'access-permissions', roles: ['admin'] }, + { _id: 'access-setting-permissions', roles: ['admin'] }, + { _id: 'add-oauth-service', roles: ['admin'] }, + { _id: 'add-user-to-joined-room', roles: ['admin', 'owner', 'moderator'] }, + { _id: 'add-user-to-any-c-room', roles: ['admin'] }, + { _id: 'add-user-to-any-p-room', roles: [] }, + { _id: 'api-bypass-rate-limit', roles: ['admin', 'bot', 'app'] }, + { _id: 'archive-room', roles: ['admin', 'owner'] }, + { _id: 'assign-admin-role', roles: ['admin'] }, + { _id: 'assign-roles', roles: ['admin'] }, + { _id: 'ban-user', roles: ['admin', 'owner', 'moderator'] }, + { _id: 'bulk-register-user', roles: ['admin'] }, + { _id: 'create-c', roles: ['admin', 'user', 'bot', 'app'] }, + { _id: 'create-d', roles: ['admin', 'user', 'bot', 'app'] }, + { _id: 'create-p', roles: ['admin', 'user', 'bot', 'app'] }, + { _id: 'create-personal-access-tokens', roles: ['admin', 'user'] }, + { _id: 'create-user', roles: ['admin'] }, + { _id: 'clean-channel-history', roles: ['admin'] }, + { _id: 'delete-c', roles: ['admin', 'owner'] }, + { _id: 'delete-d', roles: ['admin'] }, + { _id: 'delete-message', roles: ['admin', 'owner', 'moderator'] }, + { _id: 'delete-own-message', roles: ['admin', 'user'] }, + { _id: 'delete-p', roles: ['admin', 'owner'] }, + { _id: 'delete-user', roles: ['admin'] }, + { _id: 'edit-message', roles: ['admin', 'owner', 'moderator'] }, + { _id: 'edit-other-user-active-status', roles: ['admin'] }, + { _id: 'edit-other-user-info', roles: ['admin'] }, + { _id: 'edit-other-user-password', roles: ['admin'] }, + { _id: 'edit-other-user-avatar', roles: ['admin'] }, + { _id: 'edit-privileged-setting', roles: ['admin'] }, + { _id: 'edit-room', roles: ['admin', 'owner', 'moderator'] }, + { _id: 'edit-room-retention-policy', roles: ['admin'] }, + { _id: 'force-delete-message', roles: ['admin', 'owner'] }, + { _id: 'join-without-join-code', roles: ['admin', 'bot', 'app'] }, + { _id: 'leave-c', roles: ['admin', 'user', 'bot', 'anonymous', 'app'] }, + { _id: 'leave-p', roles: ['admin', 'user', 'bot', 'anonymous', 'app'] }, + { _id: 'manage-assets', roles: ['admin'] }, + { _id: 'manage-emoji', roles: ['admin'] }, + { _id: 'manage-user-status', roles: ['admin'] }, + { _id: 'manage-outgoing-integrations', roles: ['admin'] }, + { _id: 'manage-incoming-integrations', roles: ['admin'] }, + { _id: 'manage-own-outgoing-integrations', roles: ['admin'] }, + { _id: 'manage-own-incoming-integrations', roles: ['admin'] }, + { _id: 'manage-oauth-apps', roles: ['admin'] }, + { _id: 'manage-selected-settings', roles: ['admin'] }, + { _id: 'mention-all', roles: ['admin', 'owner', 'moderator', 'user'] }, + { _id: 'mention-here', roles: ['admin', 'owner', 'moderator', 'user'] }, + { _id: 'mute-user', roles: ['admin', 'owner', 'moderator'] }, + { _id: 'remove-user', roles: ['admin', 'owner', 'moderator'] }, + { _id: 'run-import', roles: ['admin'] }, + { _id: 'run-migration', roles: ['admin'] }, + { _id: 'set-moderator', roles: ['admin', 'owner'] }, + { _id: 'set-owner', roles: ['admin', 'owner'] }, + { _id: 'send-many-messages', roles: ['admin', 'bot', 'app'] }, + { _id: 'set-leader', roles: ['admin', 'owner'] }, + { _id: 'unarchive-room', roles: ['admin'] }, + { _id: 'view-c-room', roles: ['admin', 'user', 'bot', 'app', 'anonymous'] }, + { _id: 'user-generate-access-token', roles: ['admin'] }, + { _id: 'view-d-room', roles: ['admin', 'user', 'bot', 'app', 'guest'] }, + { _id: 'view-full-other-user-info', roles: ['admin'] }, + { _id: 'view-history', roles: ['admin', 'user', 'anonymous'] }, + { _id: 'view-joined-room', roles: ['guest', 'bot', 'app', 'anonymous'] }, + { _id: 'view-join-code', roles: ['admin'] }, + { _id: 'view-logs', roles: ['admin'] }, + { _id: 'view-other-user-channels', roles: ['admin'] }, + { _id: 'view-p-room', roles: ['admin', 'user', 'anonymous', 'guest'] }, + { _id: 'view-privileged-setting', roles: ['admin'] }, + { _id: 'view-room-administration', roles: ['admin'] }, + { _id: 'view-statistics', roles: ['admin'] }, + { _id: 'view-user-administration', roles: ['admin'] }, + { _id: 'preview-c-room', roles: ['admin', 'user', 'anonymous'] }, + { _id: 'view-outside-room', roles: ['admin', 'owner', 'moderator', 'user'] }, + { _id: 'view-broadcast-member-list', roles: ['admin', 'owner', 'moderator'] }, + { _id: 'call-management', roles: ['admin', 'owner', 'moderator'] }, + { _id: 'create-invite-links', roles: ['admin', 'owner', 'moderator'] }, + { _id: 'view-l-room', roles: ['livechat-agent', 'livechat-manager', 'admin'] }, + { _id: 'view-livechat-manager', roles: ['livechat-manager', 'admin'] }, + { _id: 'view-livechat-rooms', roles: ['livechat-manager', 'admin'] }, + { _id: 'close-livechat-room', roles: ['livechat-agent', 'livechat-manager', 'admin'] }, + { _id: 'close-others-livechat-room', roles: ['livechat-manager', 'admin'] }, + { _id: 'save-others-livechat-room-info', roles: ['livechat-manager'] }, + { _id: 'remove-closed-livechat-rooms', roles: ['livechat-manager', 'admin'] }, + { _id: 'view-livechat-analytics', roles: ['livechat-manager', 'admin'] }, + { _id: 'view-livechat-queue', roles: ['livechat-manager', 'admin'] }, + { _id: 'transfer-livechat-guest', roles: ['livechat-manager', 'admin'] }, + { _id: 'manage-livechat-managers', roles: ['livechat-manager', 'admin'] }, + { _id: 'manage-livechat-agents', roles: ['livechat-manager', 'admin'] }, + { _id: 'manage-livechat-departments', roles: ['livechat-manager', 'admin'] }, + { _id: 'view-livechat-departments', roles: ['livechat-manager', 'admin'] }, + { _id: 'add-livechat-department-agents', roles: ['livechat-manager', 'admin'] }, + { _id: 'view-livechat-current-chats', roles: ['livechat-manager', 'admin'] }, { _id: 'view-livechat-real-time-monitoring', roles: ['livechat-manager', 'admin'] }, { _id: 'view-livechat-triggers', roles: ['livechat-manager', 'admin'] }, { _id: 'view-livechat-customfields', roles: ['livechat-manager', 'admin'] }, @@ -111,12 +111,14 @@ Meteor.startup(function() { { _id: 'view-livechat-webhooks', roles: ['livechat-manager', 'admin'] }, { _id: 'view-livechat-facebook', roles: ['livechat-manager', 'admin'] }, { _id: 'view-livechat-officeHours', roles: ['livechat-manager', 'admin'] }, + { _id: 'view-livechat-room-closed-same-department', roles: ['livechat-manager', 'admin'] }, + { _id: 'view-livechat-room-closed-by-another-agent', roles: ['livechat-manager', 'admin'] }, + { _id: 'view-livechat-room-customfields', roles: ['livechat-manager', 'livechat-agent', 'admin'] }, + { _id: 'edit-livechat-room-customfields', roles: ['livechat-manager', 'livechat-agent', 'admin'] }, ]; for (const permission of permissions) { - if (!Permissions.findOneById(permission._id)) { - Permissions.upsert(permission._id, { $set: permission }); - } + Permissions.create(permission._id, permission.roles); } const defaultRoles = [ @@ -134,7 +136,7 @@ Meteor.startup(function() { ]; for (const role of defaultRoles) { - Roles.upsert({ _id: role.name }, { $setOnInsert: { scope: role.scope, description: role.description || '', protected: true, mandatory2fa: false } }); + Roles.createOrUpdate(role.name, role.scope, role.description, true, false); } const getPreviousPermissions = function(settingId) { @@ -155,19 +157,17 @@ Meteor.startup(function() { const createSettingPermission = function(setting, previousSettingPermissions) { const permissionId = getSettingPermissionId(setting._id); const permission = { - _id: permissionId, level: CONSTANTS.SETTINGS_LEVEL, // copy those setting-properties which are needed to properly publish the setting-based permissions settingId: setting._id, group: setting.group, section: setting.section, sorter: setting.sorter, + roles: [], }; // copy previously assigned roles if available if (previousSettingPermissions[permissionId] && previousSettingPermissions[permissionId].roles) { permission.roles = previousSettingPermissions[permissionId].roles; - } else { - permission.roles = []; } if (setting.group) { permission.groupPermissionId = getSettingPermissionId(setting.group); @@ -175,7 +175,16 @@ Meteor.startup(function() { if (setting.section) { permission.sectionPermissionId = getSettingPermissionId(setting.section); } - Permissions.upsert(permission._id, { $set: permission }); + + const existent = Permissions.findOne({ + _id: permissionId, + ...permission, + }, { fields: { _id: 1 } }); + + if (!existent) { + Permissions.upsert({ _id: permissionId }, { $set: permission }); + } + delete previousSettingPermissions[permissionId]; }; diff --git a/app/autotranslate/client/views/autoTranslateFlexTab.html b/app/autotranslate/client/views/autoTranslateFlexTab.html index 5e5d74daeab..161e3793b15 100644 --- a/app/autotranslate/client/views/autoTranslateFlexTab.html +++ b/app/autotranslate/client/views/autoTranslateFlexTab.html @@ -30,8 +30,8 @@
{{_ "AutoTranslate_Change_Language_Description"}}
- - + + {{else}} {{languageName autoTranslateLanguage}} {{/if}} diff --git a/app/autotranslate/server/autotranslate.js b/app/autotranslate/server/autotranslate.js index 3215dbff383..6019dfab37a 100644 --- a/app/autotranslate/server/autotranslate.js +++ b/app/autotranslate/server/autotranslate.js @@ -156,7 +156,7 @@ export class AutoTranslate { message = Markdown.parseMessageNotEscaped(message); // Some parsers (e. g. Marked) wrap the complete message in a

- this is unnecessary and should be ignored with respect to translations - const regexWrappedParagraph = new RegExp('^\s*

|<\/p>\s*$', 'gm'); + const regexWrappedParagraph = new RegExp('^\\s*

|

\\s*$', 'gm'); message.msg = message.msg.replace(regexWrappedParagraph, ''); for (const tokenIndex in message.tokens) { diff --git a/app/bigbluebutton/index.js b/app/bigbluebutton/index.js deleted file mode 100644 index ba58589ba3d..00000000000 --- a/app/bigbluebutton/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from './server/bigbluebutton-api'; diff --git a/app/bigbluebutton/server/index.js b/app/bigbluebutton/server/index.js new file mode 100644 index 00000000000..b6be696a20b --- /dev/null +++ b/app/bigbluebutton/server/index.js @@ -0,0 +1 @@ +export { default } from './bigbluebutton-api'; diff --git a/app/blockstack/server/routes.js b/app/blockstack/server/routes.js index ee4c7cc087d..81902030e42 100644 --- a/app/blockstack/server/routes.js +++ b/app/blockstack/server/routes.js @@ -2,7 +2,7 @@ import { Meteor } from 'meteor/meteor'; import { WebApp } from 'meteor/webapp'; import { settings } from '../../settings'; -import { RocketChatAssets } from '../../assets'; +import { RocketChatAssets } from '../../assets/server'; WebApp.connectHandlers.use('/_blockstack/manifest', Meteor.bindEnvironment(function(req, res) { const name = settings.get('Site_Name'); diff --git a/app/bot-helpers/index.js b/app/bot-helpers/index.js deleted file mode 100644 index f5778a23b60..00000000000 --- a/app/bot-helpers/index.js +++ /dev/null @@ -1 +0,0 @@ -import './server/index'; diff --git a/app/channel-settings-mail-messages/client/views/mailMessagesInstructions.js b/app/channel-settings-mail-messages/client/views/mailMessagesInstructions.js index fb875550185..4bc7442b5ee 100644 --- a/app/channel-settings-mail-messages/client/views/mailMessagesInstructions.js +++ b/app/channel-settings-mail-messages/client/views/mailMessagesInstructions.js @@ -240,9 +240,9 @@ Template.mailMessagesInstructions.onCreated(function() { this.selectedUsers = new ReactiveVar([]); this.userFilter = new ReactiveVar(''); - const filter = { exceptions: [Meteor.user().username].concat(this.selectedUsers.get().map((u) => u.username)) }; + const filter = { exceptions: this.selectedUsers.get().map((u) => u.username) }; Deps.autorun(() => { - filter.exceptions = [Meteor.user().username].concat(this.selectedUsers.get().map((u) => u.username)); + filter.exceptions = this.selectedUsers.get().map((u) => u.username); }); this.ac = new AutoComplete( diff --git a/app/channel-settings-mail-messages/server/lib/startup.js b/app/channel-settings-mail-messages/server/lib/startup.js index a04875ad90d..a079a2c4bc7 100644 --- a/app/channel-settings-mail-messages/server/lib/startup.js +++ b/app/channel-settings-mail-messages/server/lib/startup.js @@ -7,7 +7,5 @@ Meteor.startup(function() { _id: 'mail-messages', roles: ['admin'], }; - return Permissions.upsert(permission._id, { - $setOnInsert: permission, - }); + return Permissions.create(permission._id, permission.roles); }); diff --git a/app/channel-settings/client/views/Multiselect.js b/app/channel-settings/client/views/Multiselect.js index a63fa1981cd..1f90cc45a38 100644 --- a/app/channel-settings/client/views/Multiselect.js +++ b/app/channel-settings/client/views/Multiselect.js @@ -4,7 +4,7 @@ import { createTemplateForComponent } from '../../../../client/reactAdapters'; createTemplateForComponent( 'Multiselect', - () => import('../../../ui-admin/client/components/settings/inputs/MultiSelectSettingInput'), + () => import('../../../../client/admin/settings/inputs/MultiSelectSettingInput'), { // eslint-disable-next-line new-cap renderContainerView: () => HTML.DIV({ class: 'rc-multiselect', style: 'display: flex;' }), diff --git a/app/channel-settings/client/views/channelSettings.html b/app/channel-settings/client/views/channelSettings.html index 67b3fb5ad62..174bea859f9 100644 --- a/app/channel-settings/client/views/channelSettings.html +++ b/app/channel-settings/client/views/channelSettings.html @@ -226,6 +226,7 @@ {{/if}} {{/with}} {{#with settings.joinCode}} + {{#if canView}} + {{/if}} {{/with}} {{#if hasRetentionPermission}} diff --git a/app/channel-settings/server/startup.js b/app/channel-settings/server/startup.js index 698723ebe99..5e9aeb7baaf 100644 --- a/app/channel-settings/server/startup.js +++ b/app/channel-settings/server/startup.js @@ -3,7 +3,7 @@ import { Meteor } from 'meteor/meteor'; import { Permissions } from '../../models'; Meteor.startup(function() { - Permissions.upsert('post-readonly', { $setOnInsert: { roles: ['admin', 'owner', 'moderator'] } }); - Permissions.upsert('set-readonly', { $setOnInsert: { roles: ['admin', 'owner'] } }); - Permissions.upsert('set-react-when-readonly', { $setOnInsert: { roles: ['admin', 'owner'] } }); + Permissions.create('post-readonly', ['admin', 'owner', 'moderator']); + Permissions.create('set-readonly', ['admin', 'owner']); + Permissions.create('set-react-when-readonly', ['admin', 'owner']); }); diff --git a/app/chatpal-search/client/route.js b/app/chatpal-search/client/route.js index 86c6ad276c4..29695aa215a 100644 --- a/app/chatpal-search/client/route.js +++ b/app/chatpal-search/client/route.js @@ -1,6 +1,6 @@ import { BlazeLayout } from 'meteor/kadira:blaze-layout'; -import { registerAdminRoute } from '../../ui-admin/client'; +import { registerAdminRoute } from '../../../client/admin'; import { t } from '../../utils'; registerAdminRoute('/chatpal', { diff --git a/app/chatpal-search/client/template/admin.html b/app/chatpal-search/client/template/admin.html index d59a982a6b2..f9b1e6c83a9 100644 --- a/app/chatpal-search/client/template/admin.html +++ b/app/chatpal-search/client/template/admin.html @@ -37,7 +37,7 @@
- +
diff --git a/app/chatpal-search/server/provider/provider.js b/app/chatpal-search/server/provider/provider.js index 18ee9a36f42..6ce02e17b8f 100644 --- a/app/chatpal-search/server/provider/provider.js +++ b/app/chatpal-search/server/provider/provider.js @@ -3,6 +3,7 @@ import { Meteor } from 'meteor/meteor'; import { searchProviderService, SearchProvider } from '../../../search/server'; import ChatpalLogger from '../utils/logger'; import { Subscriptions } from '../../../models'; +import { baseUrl } from '../utils/settings'; import Index from './index'; @@ -16,7 +17,9 @@ class ChatpalProvider extends SearchProvider { constructor() { super('chatpalProvider'); - this.chatpalBaseUrl = 'https://beta.chatpal.io/v1'; + this.chatpalBaseUrl = `${ baseUrl }`; + + ChatpalLogger.debug(`Using ${ this.chatpalBaseUrl } as chatpal base url`); this._settings.add('Backend', 'select', 'cloud', { values: [ @@ -220,24 +223,24 @@ class ChatpalProvider extends SearchProvider { if (this._settings.get('Backend') === 'cloud') { config.baseurl = this.chatpalBaseUrl; config.language = this._settings.get('Main_Language'); - config.searchpath = '/search/search'; - config.updatepath = '/search/update'; - config.pingpath = '/search/ping'; - config.clearpath = '/search/clear'; - config.suggestionpath = '/search/suggest'; + config.searchpath = 'search/search'; + config.updatepath = 'search/update'; + config.pingpath = 'search/ping'; + config.clearpath = 'search/clear'; + config.suggestionpath = 'search/suggest'; config.httpOptions = { headers: { 'X-Api-Key': this._settings.get('API_Key'), }, }; } else { - config.baseurl = this._settings.get('Base_URL').endsWith('/') ? this._settings.get('Base_URL').slice(0, -1) : this._settings.get('Base_URL'); + config.baseurl = this._settings.get('Base_URL').replace(/\/?$/, '/'); config.language = this._settings.get('Main_Language'); - config.searchpath = '/chatpal/search'; - config.updatepath = '/chatpal/update'; - config.pingpath = '/chatpal/ping'; - config.clearpath = '/chatpal/clear'; - config.suggestionpath = '/chatpal/suggest'; + config.searchpath = 'chatpal/search'; + config.updatepath = 'chatpal/update'; + config.pingpath = 'chatpal/ping'; + config.clearpath = 'chatpal/clear'; + config.suggestionpath = 'chatpal/suggest'; config.httpOptions = { headers: this._parseHeaders(), }; diff --git a/app/chatpal-search/server/utils/settings.js b/app/chatpal-search/server/utils/settings.js new file mode 100644 index 00000000000..a1450bc16b6 --- /dev/null +++ b/app/chatpal-search/server/utils/settings.js @@ -0,0 +1 @@ +export const baseUrl = (process.env.CHATPAL_URL || 'https://api.chatpal.io/v1').replace(/\/?$/, '/'); diff --git a/app/chatpal-search/server/utils/utils.js b/app/chatpal-search/server/utils/utils.js index 91b1ffe64f2..5707ca59b15 100644 --- a/app/chatpal-search/server/utils/utils.js +++ b/app/chatpal-search/server/utils/utils.js @@ -1,10 +1,12 @@ import { Meteor } from 'meteor/meteor'; import { HTTP } from 'meteor/http'; +import { baseUrl } from './settings'; + Meteor.methods({ 'chatpalUtilsCreateKey'(email) { try { - const response = HTTP.call('POST', 'https://beta.chatpal.io/v1/account', { data: { email, tier: 'free' } }); + const response = HTTP.call('POST', `${ baseUrl }account`, { data: { email, tier: 'free' } }); if (response.statusCode === 201) { return response.data.key; } @@ -15,7 +17,7 @@ Meteor.methods({ }, 'chatpalUtilsGetTaC'(lang) { try { - const response = HTTP.call('GET', `https://beta.chatpal.io/v1/terms/${ lang }.html`); + const response = HTTP.call('GET', `${ baseUrl }terms/${ lang }.html`); if (response.statusCode === 200) { return response.content; } diff --git a/app/cloud/client/admin/callback.html b/app/cloud/client/admin/callback.html deleted file mode 100644 index 5d6c9c432f4..00000000000 --- a/app/cloud/client/admin/callback.html +++ /dev/null @@ -1,16 +0,0 @@ - diff --git a/app/cloud/client/admin/callback.js b/app/cloud/client/admin/callback.js deleted file mode 100644 index de860026192..00000000000 --- a/app/cloud/client/admin/callback.js +++ /dev/null @@ -1,46 +0,0 @@ -import './callback.html'; - -import { Meteor } from 'meteor/meteor'; -import { ReactiveVar } from 'meteor/reactive-var'; -import { Template } from 'meteor/templating'; -import { Tracker } from 'meteor/tracker'; -import { FlowRouter } from 'meteor/kadira:flow-router'; -import queryString from 'query-string'; - -import { SideNav } from '../../../ui-utils/client'; - - -Template.cloudCallback.onCreated(function() { - const instance = this; - - instance.loading = new ReactiveVar(true); - instance.callbackError = new ReactiveVar({ error: false }); - - const params = queryString.parse(location.search); - - if (params.error_code) { - instance.callbackError.set({ error: true, errorCode: params.error_code }); - } else { - Meteor.call('cloud:finishOAuthAuthorization', params.code, params.state, (error) => { - if (error) { - console.warn('cloud:finishOAuthAuthorization', error); - return; - } - - FlowRouter.go('/admin/cloud'); - }); - } -}); - -Template.cloudCallback.helpers({ - callbackError() { - return Template.instance().callbackError.get(); - }, -}); - -Template.cloudCallback.onRendered(() => { - Tracker.afterFlush(() => { - SideNav.setFlex('adminFlex'); - SideNav.openFlex(); - }); -}); diff --git a/app/cloud/client/admin/cloud.html b/app/cloud/client/admin/cloud.html deleted file mode 100644 index 78c1e053390..00000000000 --- a/app/cloud/client/admin/cloud.html +++ /dev/null @@ -1,145 +0,0 @@ - diff --git a/app/cloud/client/admin/cloud.js b/app/cloud/client/admin/cloud.js deleted file mode 100644 index cd9edf0a41a..00000000000 --- a/app/cloud/client/admin/cloud.js +++ /dev/null @@ -1,233 +0,0 @@ -import './cloud.html'; - -import { Meteor } from 'meteor/meteor'; -import { ReactiveVar } from 'meteor/reactive-var'; -import { Template } from 'meteor/templating'; -import { Tracker } from 'meteor/tracker'; -import queryString from 'query-string'; -import toastr from 'toastr'; - -import { t } from '../../../utils'; -import { SideNav, modal } from '../../../ui-utils/client'; - - -Template.cloud.onCreated(function() { - const instance = this; - instance.info = new ReactiveVar(); - instance.loading = new ReactiveVar(true); - instance.isLoggedIn = new ReactiveVar(false); - - instance.loadRegStatus = function _loadRegStatus() { - Meteor.call('cloud:checkRegisterStatus', (error, info) => { - if (error) { - console.warn('cloud:checkRegisterStatus', error); - return; - } - - instance.info.set(info); - instance.loading.set(false); - }); - }; - - instance.getLoggedIn = function _getLoggedIn() { - Meteor.call('cloud:checkUserLoggedIn', (error, result) => { - if (error) { - console.warn(error); - return; - } - - instance.isLoggedIn.set(result); - }); - }; - - instance.oauthAuthorize = function _oauthAuthorize() { - Meteor.call('cloud:getOAuthAuthorizationUrl', (error, url) => { - if (error) { - console.warn(error); - return; - } - - window.location.href = url; - }); - }; - - instance.logout = function _logout() { - Meteor.call('cloud:logout', (error) => { - if (error) { - console.warn(error); - return; - } - - instance.getLoggedIn(); - }); - }; - - instance.connectWorkspace = function _connectWorkspace(token) { - Meteor.call('cloud:connectWorkspace', token, (error, success) => { - if (error) { - toastr.error(error); - instance.loadRegStatus(); - return; - } - - if (!success) { - toastr.error('An error occured connecting'); - instance.loadRegStatus(); - return; - } - - toastr.success(t('Connected')); - - instance.loadRegStatus(); - }); - }; - - instance.disconnectWorkspace = function _disconnectWorkspace() { - Meteor.call('cloud:disconnectWorkspace', (error, success) => { - if (error) { - toastr.error(error); - instance.loadRegStatus(); - return; - } - - if (!success) { - toastr.error('An error occured disconnecting'); - instance.loadRegStatus(); - return; - } - - toastr.success(t('Disconnected')); - - instance.loadRegStatus(); - }); - }; - - instance.syncWorkspace = function _syncWorkspace() { - Meteor.call('cloud:syncWorkspace', (error, success) => { - if (error) { - toastr.error(error); - instance.loadRegStatus(); - return; - } - - if (!success) { - toastr.error('An error occured syncing'); - instance.loadRegStatus(); - return; - } - - toastr.success(t('Sync Complete')); - - instance.loadRegStatus(); - }); - }; - - instance.registerWorkspace = function _registerWorkspace() { - Meteor.call('cloud:registerWorkspace', (error, success) => { - if (error) { - toastr.error(error); - instance.loadRegStatus(); - return; - } - - if (!success) { - toastr.error('An error occured'); - instance.loadRegStatus(); - return; - } - - return instance.syncWorkspace(); - }); - }; - - const params = queryString.parse(location.search); - - if (params.token) { - instance.connectWorkspace(params.token); - } else { - instance.loadRegStatus(); - } - - instance.getLoggedIn(); -}); - -Template.cloud.helpers({ - info() { - return Template.instance().info.get(); - }, - isLoggedIn() { - return Template.instance().isLoggedIn.get(); - }, -}); - -Template.cloud.events({ - 'click .js-register'() { - modal.open({ - template: 'cloudRegisterManually', - showCancelButton: false, - showConfirmButton: false, - showFooter: false, - closeOnCancel: true, - html: true, - confirmOnEnter: false, - }); - }, - 'click .update-email-btn'() { - const val = $('input[name=cloudEmail]').val(); - - Meteor.call('cloud:updateEmail', val, false, (error) => { - if (error) { - console.warn(error); - return; - } - - toastr.success(t('Saved')); - }); - }, - - 'click .resend-email-btn'() { - const val = $('input[name=cloudEmail]').val(); - - Meteor.call('cloud:updateEmail', val, true, (error) => { - if (error) { - console.warn(error); - return; - } - - toastr.success(t('Requested')); - }); - }, - - 'click .login-btn'(e, i) { - i.oauthAuthorize(); - }, - - 'click .logout-btn'(e, i) { - i.logout(); - }, - - 'click .connect-btn'(e, i) { - const token = $('input[name=cloudToken]').val(); - - i.connectWorkspace(token); - }, - - 'click .register-btn'(e, i) { - i.registerWorkspace(); - }, - - 'click .disconnect-btn'(e, i) { - i.disconnectWorkspace(); - }, - - 'click .sync-btn'(e, i) { - i.syncWorkspace(); - }, -}); - -Template.cloud.onRendered(() => { - Tracker.afterFlush(() => { - SideNav.setFlex('adminFlex'); - SideNav.openFlex(); - }); -}); diff --git a/app/cloud/client/admin/cloudRegisterManually.css b/app/cloud/client/admin/cloudRegisterManually.css deleted file mode 100644 index 8cd3c5628e3..00000000000 --- a/app/cloud/client/admin/cloudRegisterManually.css +++ /dev/null @@ -1,26 +0,0 @@ -.rc-promtp { - display: flex; - - min-height: 188px; - padding: 1rem; - - border-radius: 2px; - background: #2f343d; - flex-flow: column wrap; - justify-content: space-between; - - &--element, - &--element[disabled] { - flex: 1 1 auto; - - resize: none; - - color: #cbced1; - border: none; - background: none; - - font-family: Menlo, Monaco, Consolas, Liberation Mono, Courier New, monospace; - font-size: 14px; - line-height: 20px; - } -} diff --git a/app/cloud/client/admin/cloudRegisterManually.html b/app/cloud/client/admin/cloudRegisterManually.html deleted file mode 100644 index 738a3642350..00000000000 --- a/app/cloud/client/admin/cloudRegisterManually.html +++ /dev/null @@ -1,36 +0,0 @@ - diff --git a/app/cloud/client/admin/cloudRegisterManually.js b/app/cloud/client/admin/cloudRegisterManually.js deleted file mode 100644 index 223d9bc609c..00000000000 --- a/app/cloud/client/admin/cloudRegisterManually.js +++ /dev/null @@ -1,106 +0,0 @@ -import { Meteor } from 'meteor/meteor'; -import { ReactiveDict } from 'meteor/reactive-dict'; -import { ReactiveVar } from 'meteor/reactive-var'; -import { Template } from 'meteor/templating'; -import { TAPi18n } from 'meteor/rocketchat:tap-i18n'; -import Clipboard from 'clipboard'; -import toastr from 'toastr'; - -import { APIClient } from '../../../utils/client'; -import { modal } from '../../../ui-utils/client'; - -import './cloudRegisterManually.html'; -import './cloudRegisterManually.css'; - -const CLOUD_STEPS = { - COPY: 0, - PASTE: 1, - DONE: 2, - ERROR: 3, -}; - -Template.cloudRegisterManually.events({ - 'submit form'(e) { - e.preventDefault(); - }, - 'input .js-cloud-key'(e, instance) { - instance.state.set('cloudKey', e.currentTarget.value); - }, - 'click .js-next'(event, instance) { - instance.state.set('step', CLOUD_STEPS.PASTE); - }, - 'click .js-back'(event, instance) { - instance.state.set('step', CLOUD_STEPS.COPY); - }, - 'click .js-finish'(event, instance) { - instance.state.set('loading', true); - - APIClient - .post('v1/cloud.manualRegister', {}, { cloudBlob: instance.state.get('cloudKey') }) - .then(() => modal.open({ - type: 'success', - title: TAPi18n.__('Success'), - text: TAPi18n.__('Cloud_register_success'), - confirmButtonText: TAPi18n.__('Ok'), - closeOnConfirm: false, - showCancelButton: false, - }, () => window.location.reload())) - .catch(() => modal.open({ - type: 'error', - title: TAPi18n.__('Error'), - text: TAPi18n.__('Cloud_register_error'), - })) - .then(() => instance.state.set('loading', false)); - }, -}); - -Template.cloudRegisterManually.helpers({ - cloudLink() { - return Template.instance().cloudLink.get(); - }, - copyStep() { - return Template.instance().state.get('step') === CLOUD_STEPS.COPY; - }, - clientKey() { - return Template.instance().state.get('clientKey'); - }, - isLoading() { - return Template.instance().state.get('loading'); - }, - step() { - return Template.instance().state.get('step'); - }, - disabled() { - const { state } = Template.instance(); - - const shouldDisable = state.get('cloudKey').trim().length === 0 || state.get('loading'); - - return shouldDisable && 'disabled'; - }, -}); - -Template.cloudRegisterManually.onRendered(function() { - const clipboard = new Clipboard('.js-copy'); - clipboard.on('success', function() { - toastr.success(TAPi18n.__('Copied')); - }); - - const btn = this.find('.cloud-console-btn'); - // After_copy_the_text_go_to_cloud - this.cloudLink.set(TAPi18n.__('Cloud_click_here').replace(/(\[(.*)\]\(\))/ig, (_, __, text) => btn.outerHTML.replace('', `${ text }`))); -}); - -Template.cloudRegisterManually.onCreated(function() { - this.cloudLink = new ReactiveVar(); - this.state = new ReactiveDict({ - step: CLOUD_STEPS.COPY, - loading: false, - clientKey: '', - cloudKey: '', - error: '', - }); - - Meteor.call('cloud:getWorkspaceRegisterData', (error, result) => { - this.state.set('clientKey', result); - }); -}); diff --git a/app/cloud/client/admin/index.js b/app/cloud/client/admin/index.js deleted file mode 100644 index 92cb6032c24..00000000000 --- a/app/cloud/client/admin/index.js +++ /dev/null @@ -1,2 +0,0 @@ -import './cloud'; -import './callback'; diff --git a/app/cloud/client/index.js b/app/cloud/client/index.js deleted file mode 100644 index 0c8025d22db..00000000000 --- a/app/cloud/client/index.js +++ /dev/null @@ -1,33 +0,0 @@ -import './admin/callback'; -import './admin/cloud'; -import './admin/cloudRegisterManually'; - -import { BlazeLayout } from 'meteor/kadira:blaze-layout'; - -import { registerAdminRoute, registerAdminSidebarItem } from '../../ui-admin/client'; -import { hasAtLeastOnePermission } from '../../authorization'; - -registerAdminRoute('/cloud', { - name: 'cloud', - async action() { - await import('./admin'); - BlazeLayout.render('main', { center: 'cloud', old: true }); - }, -}); - -registerAdminRoute('/cloud/oauth-callback', { - name: 'cloud-oauth-callback', - async action() { - await import('./admin'); - BlazeLayout.render('main', { center: 'cloudCallback', old: true }); - }, -}); - -registerAdminSidebarItem({ - icon: 'cloud-plus', - href: 'cloud', - i18nLabel: 'Connectivity_Services', - permissionGranted() { - return hasAtLeastOnePermission(['manage-cloud']); - }, -}); diff --git a/app/cloud/server/index.js b/app/cloud/server/index.js index 58bd467b4df..f783f488792 100644 --- a/app/cloud/server/index.js +++ b/app/cloud/server/index.js @@ -11,7 +11,7 @@ import { Permissions } from '../../models'; import { settings } from '../../settings/server'; if (Permissions) { - Permissions.createOrUpdate('manage-cloud', ['admin']); + Permissions.create('manage-cloud', ['admin']); } const licenseCronName = 'Cloud Workspace Sync'; diff --git a/app/cors/server/cors.js b/app/cors/server/cors.js index c5853db9405..9c6d8eb3180 100644 --- a/app/cors/server/cors.js +++ b/app/cors/server/cors.js @@ -44,6 +44,7 @@ WebApp.rawConnectHandlers.use(Meteor.bindEnvironment(function(req, res, next) { }); })); +// Deprecated setting let Support_Cordova_App = false; settings.get('Support_Cordova_App', (key, value) => { Support_Cordova_App = value; @@ -53,24 +54,24 @@ WebApp.rawConnectHandlers.use(function(req, res, next) { // XSS Protection for old browsers (IE) res.setHeader('X-XSS-Protection', '1'); - if (Support_Cordova_App !== true) { - return next(); - } - - if (/^\/(api|_timesync|sockjs|tap-i18n)(\/|$)/.test(req.url)) { - res.setHeader('Access-Control-Allow-Origin', '*'); - } if (settings.get('Iframe_Restrict_Access')) { res.setHeader('X-Frame-Options', settings.get('Iframe_X_Frame_Options')); } - const { setHeader } = res; - res.setHeader = function(key, val, ...args) { - if (key.toLowerCase() === 'access-control-allow-origin' && val === 'http://meteor.local') { - return; + // Deprecated behavior + if (Support_Cordova_App === true) { + if (/^\/(api|_timesync|sockjs|tap-i18n)(\/|$)/.test(req.url)) { + res.setHeader('Access-Control-Allow-Origin', '*'); } - return setHeader.apply(this, [key, val, ...args]); - }; + + const { setHeader } = res; + res.setHeader = function(key, val, ...args) { + if (key.toLowerCase() === 'access-control-allow-origin' && val === 'http://meteor.local') { + return; + } + return setHeader.apply(this, [key, val, ...args]); + }; + } return next(); }); diff --git a/app/crowd/server/crowd.js b/app/crowd/server/crowd.js index c91d2de399e..6bbf9561435 100644 --- a/app/crowd/server/crowd.js +++ b/app/crowd/server/crowd.js @@ -9,6 +9,7 @@ import { _setRealName } from '../../lib'; import { Users } from '../../models'; import { settings } from '../../settings'; import { hasRole } from '../../authorization'; +import { deleteUser } from '../../lib/server/functions'; const logger = new Logger('CROWD', {}); @@ -203,6 +204,13 @@ export class CROWD { const response = self.crowdClient.searchSync('user', `email=" ${ email } "`); if (!response || response.users.length === 0) { logger.warn('Could not find user in CROWD with username or email:', crowd_username, email); + if (settings.get('CROWD_Remove_Orphaned_Users') === true) { + logger.info('Removing user:', crowd_username); + Meteor.defer(function() { + deleteUser(user._id); + logger.info('User removed:', crowd_username); + }); + } return; } crowd_username = response.users[0].name; diff --git a/app/crowd/server/settings.js b/app/crowd/server/settings.js index 29307d957a7..b5836296729 100644 --- a/app/crowd/server/settings.js +++ b/app/crowd/server/settings.js @@ -14,6 +14,7 @@ Meteor.startup(function() { this.add('CROWD_APP_PASSWORD', '', { type: 'password', enableQuery, i18nLabel: 'Password', secret: true }); this.add('CROWD_Sync_User_Data', false, { type: 'boolean', enableQuery, i18nLabel: 'Sync_Users' }); this.add('CROWD_Sync_Interval', 'Every 60 mins', { type: 'string', enableQuery: enableSyncQuery, i18nLabel: 'Sync_Interval', i18nDescription: 'Crowd_sync_interval_Description' }); + this.add('CROWD_Remove_Orphaned_Users', false, { type: 'boolean', public: true, i18nLabel: 'Crowd_Remove_Orphaned_Users' }); this.add('CROWD_Clean_Usernames', true, { type: 'boolean', enableQuery, i18nLabel: 'Clean_Usernames', i18nDescription: 'Crowd_clean_usernames_Description' }); this.add('CROWD_Allow_Custom_Username', true, { type: 'boolean', i18nLabel: 'CROWD_Allow_Custom_Username' }); this.add('CROWD_Test_Connection', 'crowd_test_connection', { type: 'action', actionText: 'Test_Connection', i18nLabel: 'Test_Connection' }); diff --git a/app/custom-sounds/assets/stylesheets/customSoundsAdmin.css b/app/custom-sounds/assets/stylesheets/customSoundsAdmin.css deleted file mode 100644 index c96075a621e..00000000000 --- a/app/custom-sounds/assets/stylesheets/customSoundsAdmin.css +++ /dev/null @@ -1,111 +0,0 @@ -.sound-info { - & .icon-play-circled { - cursor: pointer; - } -} - -.sound-view { - z-index: 15; - - overflow-x: hidden; - overflow-y: auto; - - & .thumb { - width: 100%; - height: 350px; - padding: 20px; - } - - & nav { - padding: 0 20px; - } - - & .info { - padding: 0 20px; - - white-space: normal; - - & h3 { - overflow: hidden; - - width: 100%; - margin: 8px 0; - - user-select: text; - white-space: nowrap; - text-overflow: ellipsis; - - font-size: 24px; - line-height: 27px; - - & i::after { - display: inline-block; - - width: 8px; - height: 8px; - - content: " "; - vertical-align: middle; - - border-radius: 4px; - } - } - - & p { - -webkit-user-select: text; - -moz-user-select: text; - -ms-user-select: text; - user-select: text; - - font-size: 12px; - font-weight: 300; - line-height: 18px; - } - } - - & .edit-form { - padding: 20px 20px 0; - - white-space: normal; - - & h3 { - margin-bottom: 8px; - - font-size: 24px; - line-height: 22px; - } - - & p { - font-size: 12px; - font-weight: 300; - line-height: 18px; - } - - & > .input-line { - margin-top: 20px; - } - - & nav { - padding: 0; - - &.buttons { - margin-top: 2em; - } - } - - & .form-divisor { - height: 9px; - margin: 2em 0; - - text-align: center; - - & > span { - padding: 0 1em; - } - } - } - - & .room-info-content > div { - margin: 0 0 20px; - } -} diff --git a/app/custom-sounds/client/admin/adminSoundEdit.html b/app/custom-sounds/client/admin/adminSoundEdit.html deleted file mode 100644 index c6f4ef42f9b..00000000000 --- a/app/custom-sounds/client/admin/adminSoundEdit.html +++ /dev/null @@ -1,7 +0,0 @@ - diff --git a/app/custom-sounds/client/admin/adminSoundInfo.html b/app/custom-sounds/client/admin/adminSoundInfo.html deleted file mode 100644 index f9676c22303..00000000000 --- a/app/custom-sounds/client/admin/adminSoundInfo.html +++ /dev/null @@ -1,7 +0,0 @@ - diff --git a/app/custom-sounds/client/admin/adminSounds.html b/app/custom-sounds/client/admin/adminSounds.html deleted file mode 100644 index c9a20bd9c4f..00000000000 --- a/app/custom-sounds/client/admin/adminSounds.html +++ /dev/null @@ -1,78 +0,0 @@ - diff --git a/app/custom-sounds/client/admin/adminSounds.js b/app/custom-sounds/client/admin/adminSounds.js deleted file mode 100644 index 9de092e3c14..00000000000 --- a/app/custom-sounds/client/admin/adminSounds.js +++ /dev/null @@ -1,176 +0,0 @@ -import { ReactiveVar } from 'meteor/reactive-var'; -import { Tracker } from 'meteor/tracker'; -import { FlowRouter } from 'meteor/kadira:flow-router'; -import { Template } from 'meteor/templating'; -import _ from 'underscore'; - -import { RocketChatTabBar, SideNav, TabBar } from '../../../ui-utils'; -import { CustomSounds } from '../lib/CustomSounds'; -import { APIClient } from '../../../utils/client'; - -const LIST_SIZE = 50; -const DEBOUNCE_TIME_TO_SEARCH_IN_MS = 500; - -Template.adminSounds.helpers({ - searchText() { - const instance = Template.instance(); - return instance.filter && instance.filter.get(); - }, - isPlaying(_id) { - return Template.instance().isPlayingId.get() === _id; - }, - customsounds() { - return Template.instance().sounds.get(); - }, - isLoading() { - return Template.instance().isLoading.get(); - }, - flexData() { - return { - tabBar: Template.instance().tabBar, - data: Template.instance().tabBarData.get(), - }; - }, - - onTableScroll() { - const instance = Template.instance(); - return function(currentTarget) { - if (currentTarget.offsetHeight + currentTarget.scrollTop < currentTarget.scrollHeight - 100) { - return; - } - const sounds = instance.sounds.get(); - if (instance.total.get() > sounds.length) { - instance.offset.set(instance.offset.get() + LIST_SIZE); - } - }; - }, - onTableItemClick() { - const instance = Template.instance(); - return function(item) { - instance.tabBarData.set({ - sound: instance.sounds.get().find((sound) => sound._id === item._id), - onSuccess: instance.onSuccessCallback, - }); - instance.tabBar.showGroup('custom-sounds-selected'); - instance.tabBar.open('admin-sound-info'); - }; - }, -}); - -Template.adminSounds.onCreated(function() { - const instance = this; - this.sounds = new ReactiveVar([]); - this.offset = new ReactiveVar(0); - this.total = new ReactiveVar(0); - this.query = new ReactiveVar({}); - this.isLoading = new ReactiveVar(false); - this.filter = new ReactiveVar(''); - this.isPlayingId = new ReactiveVar(''); - - this.tabBar = new RocketChatTabBar(); - this.tabBar.showGroup(FlowRouter.current().route.name); - this.tabBarData = new ReactiveVar(); - - TabBar.addButton({ - groups: ['custom-sounds', 'custom-sounds-selected'], - id: 'add-sound', - i18nTitle: 'Custom_Sound_Add', - icon: 'plus', - template: 'adminSoundEdit', - order: 1, - }); - - TabBar.addButton({ - groups: ['custom-sounds-selected'], - id: 'admin-sound-info', - i18nTitle: 'Custom_Sound_Info', - icon: 'customize', - template: 'adminSoundInfo', - order: 2, - }); - - this.onSuccessCallback = () => { - this.offset.set(0); - return this.loadSounds(this.query.get(), this.offset.get()); - }; - - this.tabBarData.set({ - onSuccess: instance.onSuccessCallback, - }); - - this.loadSounds = _.debounce(async (query, offset) => { - this.isLoading.set(true); - const { sounds, total } = await APIClient.v1.get(`custom-sounds.list?count=${ LIST_SIZE }&offset=${ offset }&query=${ JSON.stringify(query) }`); - this.total.set(total); - if (offset === 0) { - this.sounds.set(sounds); - } else { - this.sounds.set(this.sounds.get().concat(sounds)); - } - this.isLoading.set(false); - }, DEBOUNCE_TIME_TO_SEARCH_IN_MS); - - this.autorun(() => { - const filter = this.filter.get() && this.filter.get().trim(); - const offset = this.offset.get(); - if (filter) { - const regex = { $regex: filter, $options: 'i' }; - return this.loadSounds({ name: regex }, offset); - } - return this.loadSounds({}, offset); - }); -}); - -Template.adminSounds.onRendered(() => - Tracker.afterFlush(function() { - SideNav.setFlex('adminFlex'); - SideNav.openFlex(); - }), -); - -Template.adminSounds.events({ - 'keydown #sound-filter'(e) { - // stop enter key - if (e.which === 13) { - e.stopPropagation(); - e.preventDefault(); - } - }, - 'keyup #sound-filter'(e, t) { - e.stopPropagation(); - e.preventDefault(); - t.filter.set(e.currentTarget.value); - t.offset.set(0); - }, - 'click .icon-play-circled'(e, t) { - e.preventDefault(); - e.stopPropagation(); - CustomSounds.play(this._id); - const audio = document.getElementById(t.isPlayingId.get()); - if (audio) { - audio.pause(); - } - document.getElementById(this._id).onended = () => { - t.isPlayingId.set(''); - this.onended = null; - }; - t.isPlayingId.set(this._id); - }, - 'click .icon-pause-circled'(e, t) { - e.preventDefault(); - e.stopPropagation(); - const audio = document.getElementById(this._id); - if (audio && !audio.paused) { - audio.pause(); - } - t.isPlayingId.set(''); - }, - 'click .icon-reset-circled'(e) { - e.preventDefault(); - e.stopPropagation(); - const audio = document.getElementById(this._id); - if (audio) { - audio.currentTime = 0; - } - }, -}); diff --git a/app/custom-sounds/client/admin/route.js b/app/custom-sounds/client/admin/route.js deleted file mode 100644 index 0f181fda578..00000000000 --- a/app/custom-sounds/client/admin/route.js +++ /dev/null @@ -1,11 +0,0 @@ -import { BlazeLayout } from 'meteor/kadira:blaze-layout'; - -import { registerAdminRoute } from '../../../ui-admin/client'; - -registerAdminRoute('/custom-sounds', { - name: 'custom-sounds', - async action(/* params*/) { - await import('./views'); - BlazeLayout.render('main', { center: 'adminSounds' }); - }, -}); diff --git a/app/custom-sounds/client/admin/soundEdit.html b/app/custom-sounds/client/admin/soundEdit.html deleted file mode 100644 index 63caf62d4dd..00000000000 --- a/app/custom-sounds/client/admin/soundEdit.html +++ /dev/null @@ -1,25 +0,0 @@ - diff --git a/app/custom-sounds/client/admin/soundEdit.js b/app/custom-sounds/client/admin/soundEdit.js deleted file mode 100644 index cffe9c92d10..00000000000 --- a/app/custom-sounds/client/admin/soundEdit.js +++ /dev/null @@ -1,155 +0,0 @@ -import { Meteor } from 'meteor/meteor'; -import { Template } from 'meteor/templating'; -import { TAPi18n } from 'meteor/rocketchat:tap-i18n'; -import toastr from 'toastr'; -import s from 'underscore.string'; - -import { t, handleError } from '../../../utils'; - -Template.soundEdit.helpers({ - sound() { - return Template.instance().sound; - }, - - name() { - return this.name || this._id; - }, -}); - -Template.soundEdit.events({ - 'click .cancel'(e, t) { - e.stopPropagation(); - e.preventDefault(); - delete Template.instance().soundFile; - t.cancel(t.find('form')); - }, - - 'submit form'(e, t) { - e.stopPropagation(); - e.preventDefault(); - t.save(e.currentTarget); - }, - - 'change input[type=file]'(ev) { - const e = ev.originalEvent != null ? ev.originalEvent : ev; - let { files } = e.target; - if (e.target.files == null || files.length === 0) { - if (e.dataTransfer.files != null) { - files = e.dataTransfer.files; - } else { - files = []; - } - } - - // using let x of y here seems to have incompatibility with some phones - for (const file in files) { - if (files.hasOwnProperty(file)) { - Template.instance().soundFile = files[file]; - } - } - }, -}); - -Template.soundEdit.onCreated(function() { - if (this.data != null) { - this.sound = this.data.sound; - } else { - this.sound = undefined; - this.data.tabBar.showGroup('custom-sounds'); - } - this.onSuccess = Template.currentData().onSuccess; - this.cancel = (form, name) => { - form.reset(); - this.data.tabBar.close(); - if (this.sound) { - this.data.back(name); - } - }; - - this.getSoundData = () => { - const soundData = {}; - if (this.sound != null) { - soundData._id = this.sound._id; - soundData.previousName = this.sound.name; - soundData.extension = this.sound.extension; - soundData.previousExtension = this.sound.extension; - } - soundData.name = s.trim(this.$('#name').val()); - soundData.newFile = false; - return soundData; - }; - - this.validate = () => { - const soundData = this.getSoundData(); - - const errors = []; - if (!soundData.name) { - errors.push('Name'); - } - - if (!soundData._id) { - if (!this.soundFile) { - errors.push('Sound_File_mp3'); - } - } - - for (const error of errors) { - toastr.error(TAPi18n.__('error-the-field-is-required', { field: TAPi18n.__(error) })); - } - - if (this.soundFile) { - if (!/audio\/mp3/.test(this.soundFile.type) && !/audio\/mpeg/.test(this.soundFile.type) && !/audio\/x-mpeg/.test(this.soundFile.type)) { - errors.push('FileType'); - toastr.error(TAPi18n.__('error-invalid-file-type')); - } - } - - return errors.length === 0; - }; - - this.save = (form) => { - if (this.validate()) { - const soundData = this.getSoundData(); - - if (this.soundFile) { - soundData.newFile = true; - soundData.extension = this.soundFile.name.split('.').pop(); - soundData.type = this.soundFile.type; - } - - Meteor.call('insertOrUpdateSound', soundData, (error, result) => { - if (result) { - soundData._id = result; - soundData.random = Math.round(Math.random() * 1000); - - if (this.soundFile) { - toastr.info(TAPi18n.__('Uploading_file')); - - const reader = new FileReader(); - reader.readAsBinaryString(this.soundFile); - reader.onloadend = () => { - Meteor.call('uploadCustomSound', reader.result, this.soundFile.type, soundData, (uploadError/* , data*/) => { - if (uploadError != null) { - handleError(uploadError); - console.log(uploadError); - } - }, - ); - delete this.soundFile; - toastr.success(TAPi18n.__('File_uploaded')); - }; - } - - toastr.success(t('Custom_Sound_Saved_Successfully')); - this.onSuccess(); - - this.cancel(form, soundData.name); - } - - if (error) { - handleError(error); - } - }); - } - }; -}); diff --git a/app/custom-sounds/client/admin/soundInfo.html b/app/custom-sounds/client/admin/soundInfo.html deleted file mode 100644 index 09374f00609..00000000000 --- a/app/custom-sounds/client/admin/soundInfo.html +++ /dev/null @@ -1,19 +0,0 @@ - diff --git a/app/custom-sounds/client/admin/soundInfo.js b/app/custom-sounds/client/admin/soundInfo.js deleted file mode 100644 index a27c74a03b2..00000000000 --- a/app/custom-sounds/client/admin/soundInfo.js +++ /dev/null @@ -1,118 +0,0 @@ -import { Meteor } from 'meteor/meteor'; -import { ReactiveVar } from 'meteor/reactive-var'; -import { Template } from 'meteor/templating'; - -import { modal } from '../../../ui-utils'; -import { t, handleError } from '../../../utils'; - -Template.soundInfo.helpers({ - name() { - const sound = Template.instance().sound.get(); - return sound.name; - }, - - sound() { - return Template.instance().sound.get(); - }, - - editingSound() { - return Template.instance().editingSound.get(); - }, - - soundToEdit() { - const instance = Template.instance(); - return { - tabBar: instance.data.tabBar, - data: instance.data.data, - sound: instance.sound.get(), - onSuccess: instance.onSuccess, - back(name) { - instance.editingSound.set(); - - if (name != null) { - const sound = instance.sound.get(); - if (sound.name != null && sound.name !== name) { - return instance.loadedName.set(name); - } - } - }, - }; - }, -}); - -Template.soundInfo.events({ - 'click .delete'(e, instance) { - e.stopPropagation(); - e.preventDefault(); - const sound = instance.sound.get(); - if (sound != null) { - const { _id } = sound; - modal.open({ - title: t('Are_you_sure'), - text: t('Custom_Sound_Delete_Warning'), - type: 'warning', - showCancelButton: true, - confirmButtonColor: '#DD6B55', - confirmButtonText: t('Yes_delete_it'), - cancelButtonText: t('Cancel'), - closeOnConfirm: false, - html: false, - }, function() { - Meteor.call('deleteCustomSound', _id, (error/* , result*/) => { - if (error) { - handleError(error); - } else { - modal.open({ - title: t('Deleted'), - text: t('Custom_Sound_Has_Been_Deleted'), - type: 'success', - timer: 2000, - showConfirmButton: false, - }); - instance.onSuccess(); - instance.data.tabBar.showGroup('custom-sounds'); - instance.data.tabBar.close(); - } - }); - }); - } - }, - - 'click .edit-sound'(e, instance) { - e.stopPropagation(); - e.preventDefault(); - - instance.editingSound.set(instance.sound.get()._id); - }, -}); - -Template.soundInfo.onCreated(function() { - this.sound = new ReactiveVar(); - - this.editingSound = new ReactiveVar(); - - this.loadedName = new ReactiveVar(); - this.onSuccess = Template.currentData().onSuccess; - - this.autorun(() => { - const data = Template.currentData(); - if (data && data.clear != null) { - this.clear = data.clear; - } - }); - - this.autorun(() => { - const data = Template.currentData().sound; - const sound = this.sound.get(); - if (sound && sound.name != null) { - this.loadedName.set(sound.name); - } else if (data.name != null) { - this.loadedName.set(data.name); - } - }); - - this.autorun(() => { - const data = Template.currentData().sound; - this.sound.set(data); - }); -}); diff --git a/app/custom-sounds/client/admin/startup.js b/app/custom-sounds/client/admin/startup.js deleted file mode 100644 index 2647b17ea42..00000000000 --- a/app/custom-sounds/client/admin/startup.js +++ /dev/null @@ -1,11 +0,0 @@ -import { hasAtLeastOnePermission } from '../../../authorization'; -import { registerAdminSidebarItem } from '../../../ui-admin/client'; - -registerAdminSidebarItem({ - href: 'custom-sounds', - i18nLabel: 'Custom_Sounds', - icon: 'volume', - permissionGranted() { - return hasAtLeastOnePermission(['manage-sounds']); - }, -}); diff --git a/app/custom-sounds/client/admin/views.js b/app/custom-sounds/client/admin/views.js deleted file mode 100644 index 3a2397b2bda..00000000000 --- a/app/custom-sounds/client/admin/views.js +++ /dev/null @@ -1,8 +0,0 @@ -import './adminSoundEdit.html'; -import './adminSoundInfo.html'; -import './adminSounds.html'; -import './adminSounds'; -import './soundEdit.html'; -import './soundEdit'; -import './soundInfo.html'; -import './soundInfo'; diff --git a/app/custom-sounds/client/index.js b/app/custom-sounds/client/index.js index eb17166ef2b..77706dca50e 100644 --- a/app/custom-sounds/client/index.js +++ b/app/custom-sounds/client/index.js @@ -1,7 +1,4 @@ import './notifications/deleteCustomSound'; import './notifications/updateCustomSound'; -import './admin/route'; -import './admin/startup'; -import '../assets/stylesheets/customSoundsAdmin.css'; export { CustomSounds } from './lib/CustomSounds'; diff --git a/app/custom-sounds/client/lib/CustomSounds.js b/app/custom-sounds/client/lib/CustomSounds.js index 09c175ac6c0..27b09ca5a50 100644 --- a/app/custom-sounds/client/lib/CustomSounds.js +++ b/app/custom-sounds/client/lib/CustomSounds.js @@ -3,23 +3,28 @@ import { ReactiveVar } from 'meteor/reactive-var'; import _ from 'underscore'; import { CachedCollectionManager } from '../../../ui-cached-collection'; +import { getURL } from '../../../utils/client'; + +const getCustomSoundId = (sound) => `custom-sound-${ sound }`; class CustomSoundsClass { constructor() { this.list = new ReactiveVar({}); - this.add({ _id: 'beep', name: 'Beep', extension: 'mp3', src: 'sounds/beep.mp3' }); - this.add({ _id: 'chelle', name: 'Chelle', extension: 'mp3', src: 'sounds/chelle.mp3' }); - this.add({ _id: 'ding', name: 'Ding', extension: 'mp3', src: 'sounds/ding.mp3' }); - this.add({ _id: 'droplet', name: 'Droplet', extension: 'mp3', src: 'sounds/droplet.mp3' }); - this.add({ _id: 'highbell', name: 'Highbell', extension: 'mp3', src: 'sounds/highbell.mp3' }); - this.add({ _id: 'seasons', name: 'Seasons', extension: 'mp3', src: 'sounds/seasons.mp3' }); + this.add({ _id: 'chime', name: 'Chime', extension: 'mp3', src: getURL('sounds/chime.mp3') }); + this.add({ _id: 'door', name: 'Door', extension: 'mp3', src: getURL('sounds/door.mp3') }); + this.add({ _id: 'beep', name: 'Beep', extension: 'mp3', src: getURL('sounds/beep.mp3') }); + this.add({ _id: 'chelle', name: 'Chelle', extension: 'mp3', src: getURL('sounds/chelle.mp3') }); + this.add({ _id: 'ding', name: 'Ding', extension: 'mp3', src: getURL('sounds/ding.mp3') }); + this.add({ _id: 'droplet', name: 'Droplet', extension: 'mp3', src: getURL('sounds/droplet.mp3') }); + this.add({ _id: 'highbell', name: 'Highbell', extension: 'mp3', src: getURL('sounds/highbell.mp3') }); + this.add({ _id: 'seasons', name: 'Seasons', extension: 'mp3', src: getURL('sounds/seasons.mp3') }); } add(sound) { if (!sound.src) { sound.src = this.getURL(sound); } - const audio = $('