diff --git a/.meteor/packages b/.meteor/packages index 4e496bd5640a..db6caf2a8d31 100644 --- a/.meteor/packages +++ b/.meteor/packages @@ -189,3 +189,4 @@ rocketchat:version-check rocketchat:search chatpal:search +goalifychat:weekly-summary diff --git a/.meteor/versions b/.meteor/versions index 172e46687476..0827d9715e1e 100644 --- a/.meteor/versions +++ b/.meteor/versions @@ -9,7 +9,7 @@ accounts-twitter@1.4.1 aldeed:simple-schema@1.5.4 allow-deny@1.1.0 autoupdate@1.4.0 -babel-compiler@7.0.7 +babel-compiler@7.0.8 babel-runtime@1.2.2 base64@1.0.11 binary-heap@1.0.10 @@ -35,7 +35,7 @@ deps@1.0.12 diff-sequence@1.1.0 dispatch:run-as-user@1.1.1 dynamic-import@0.3.0 -ecmascript@0.10.7 +ecmascript@0.10.8 ecmascript-runtime@0.5.0 ecmascript-runtime-client@0.6.2 ecmascript-runtime-server@0.5.0 @@ -49,6 +49,7 @@ fastclick@1.0.13 francocatena:status@1.5.3 geojson-utils@1.0.10 github-oauth@1.2.0 +goalifychat:weekly-summary@0.0.1 google-oauth@1.2.5 hot-code-push@1.0.4 html-tools@1.0.11 diff --git a/README.md b/README.md index 3b43345ed249..cd69f3a91f4b 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,6 @@ * [Scalingo](#scalingo) * [Sloppy.io](#sloppyio) * [Docker](#docker) - * [FreeBSD](#freebsd) * [Ansible](#ansible) * [Raspberry Pi 2](#raspberry-pi-2) * [Koozali SME](#koozali-sme) @@ -80,10 +79,7 @@ Download the Native Cross-Platform Desktop Application at [Rocket.Chat.Electron] [![Rocket.Chat on Apple App Store](https://user-images.githubusercontent.com/551004/29770691-a2082ff4-8bc6-11e7-89a6-964cd405ea8e.png)](https://itunes.apple.com/us/app/rocket.chat/id1028869439?mt=8) [![Rocket.Chat on Google Play](https://user-images.githubusercontent.com/551004/29770692-a20975c6-8bc6-11e7-8ab0-1cde275496e0.png)](https://play.google.com/store/apps/details?id=com.konecty.rocket.chat) -*Now compatible with all Android devices as old as version 4.0.x - [download here](https://docs.rocket.chat/developer-guides/mobile-apps/), even on BlackBerry Passport!* - -### Also available as FirefoxOS app -[![Firefox OS app now available](https://raw.githubusercontent.com/Sing-Li/bbug/master/images/firefoxos.png)](https://docs.rocket.chat/installation/mobile-and-desktop-apps/#native-firefox-os-app). +*Now compatible with all Android devices as old as version 4.0.x - [download here](https://rocket.chat/docs/developer-guides/mobile-apps/), even on BlackBerry Passport!* # Deployment @@ -102,7 +98,7 @@ Installing snaps is very quick. By running that command you have your full Rocke Our snap features a built-in reverse proxy that can request and maintain free Let's Encrypt SSL certificates. You can go from zero to a public-facing SSL-secured Rocket.Chat server in less than 5 minutes. -Find out more information about our snaps [here](https://docs.rocket.chat/installation/manual-installation/ubuntu/snaps/). +Find out more information about our snaps [here](https://rocket.chat/docs/installation/manual-installation/ubuntu/snaps/). ## RocketChatLauncher @@ -173,7 +169,7 @@ Host your docker container at [sloppy.io](http://sloppy.io). Get an account and ## Docker -[Deploy with docker compose](https://docs.rocket.chat/installation/docker-containers/docker-compose) +[Deploy with docker compose](https://rocket.chat/docs/installation/docker-containers/docker-compose/) [![Rocket.Chat logo](https://d207aa93qlcgug.cloudfront.net/1.95.5.qa/img/nav/docker-logo-loggedout.png)](https://hub.docker.com/r/rocketchat/rocket.chat/) @@ -194,21 +190,10 @@ OR our [official docker registry image](https://hub.docker.com/_/rocket.chat/), docker pull rocket.chat ``` -## FreeBSD -Run solid five-nines deployment on industry workhorse FreeBSD server. - -[![FreeBSD Daemon](https://raw.githubusercontent.com/Sing-Li/bbug/master/images/freebsd.png)](https://docs.rocket.chat/installation/manual-installation/freebsd/) - -## Windows Server - -Deploy on your own enterprise server, or with Microsoft Azure. - -[![Windows 2012 or 2016 Server](https://github.com/Sing-Li/bbug/blob/master/images/windows.png)](https://docs.rocket.chat/installation/manual-installation/windows-server/) - ## Ansible Automated production-grade deployment in minutes, for RHEL / CentOS 7 or Ubuntu 14.04 LTS / 15.04. -[![Ansible deployment](https://raw.githubusercontent.com/Sing-Li/bbug/master/images/ansible.png)](https://docs.rocket.chat/installation/automation-tools/ansible/) +[![Ansible deployment](https://raw.githubusercontent.com/Sing-Li/bbug/master/images/ansible.png)](https://rocket.chat/docs/installation/automation-tools/ansible/) ## Raspberry Pi 2 Run Rocket.Chat on this world famous $30 quad core server. @@ -222,15 +207,15 @@ Add Rocket.Chat to this world famous time tested small enterprise server today. [![Koozali SME](https://raw.githubusercontent.com/Sing-Li/bbug/master/images/koozali.png)](https://wiki.contribs.org/Rocket_Chat) ## Ubuntu VPS -Follow these [deployment instructions](https://docs.rocket.chat/installation/manual-installation/ubuntu/). +Follow these [deployment instructions](https://rocket.chat/docs/installation/manual-installation/ubuntu/). ## Hyper.sh -Follow their [deployment instructions](https://docs.rocket.chat/installation/paas-deployments/hyper-sh/) to install a per-second billed Rocket.Chat instance on [Hyper.sh](https://docs.rocket.chat/installation/paas-deployments/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): -[![Install](https://avatars3.githubusercontent.com/u/10002920?v=4&s=100)](https://docs.rocket.chat/installation/paas-deployments/wedeploy/) +[![Install](https://avatars3.githubusercontent.com/u/10002920?v=4&s=100)](https://rocket.chat/docs/installation/paas-deployments/wedeploy/) ## D2C.io Deploy Rocket.Chat stack to your server with [D2C](https://d2c.io/). Scale with a single click, check live logs and metrics: @@ -320,7 +305,6 @@ It is a great solution for communities and companies wanting to privately host t - Native Cross-Platform Desktop Application [Windows, macOS, or Linux](https://rocket.chat/) - Mobile app for iPhone, iPad, and iPod touch [Download on App Store](https://geo.itunes.apple.com/us/app/rocket-chat/id1148741252?mt=8) - Mobile app for Android phone, tablet, and TV stick [Available now on Google Play](https://play.google.com/store/apps/details?id=chat.rocket.android) -- Native Firefox OS Application (also for Desktop Firefox and Firefox for Android) - [Check the docs page for install instructions](https://docs.rocket.chat/installation/mobile-and-desktop-apps/#native-firefox-os-app) - Sandstorm.io instant Rocket.Chat server [Now on Sandstorm App Store](https://apps.sandstorm.io/app/vfnwptfn02ty21w715snyyczw0nqxkv3jvawcah10c6z7hj1hnu0) - Available on [Cloudron Store](https://cloudron.io/appstore.html#chat.rocket.cloudronapp) @@ -393,7 +377,7 @@ We are developing the APIs based on the competition, so stay tuned and you will ## Documentation -Checkout [Rocket.Chat documentation](https://docs.rocket.chat/). +Checkout [Rocket.Chat documentation](https://rocket.chat/docs/). ## License @@ -415,11 +399,11 @@ cd Rocket.Chat meteor npm start ``` -If you are not a developer and just want to run the server - see [deployment methods](https://docs.rocket.chat/installation/paas-deployments/). +If you are not a developer and just want to run the server - see [deployment methods](https://rocket.chat/docs/installation/paas-deployments/). ## Branching Model -See [Branches and Releases](https://docs.rocket.chat/developer-guides/branches-and-releases/). +See [Branches and Releases](https://rocket.chat/docs/developer-guides/branches-and-releases/). It is based on [Gitflow Workflow](http://nvie.com/posts/a-successful-git-branching-model/), reference section below is derived from Vincent Driessen at nvie. diff --git a/example-build-run.sh b/example-build-run.sh index fc57c8632d6a..8e5f66f1c020 100755 --- a/example-build-run.sh +++ b/example-build-run.sh @@ -10,6 +10,7 @@ DEPLOY_DIR=/var/www/rocket.chat ### BUILD meteor npm install +meteor npm run postinstall # on the very first build, meteor build command should fail due to a bug on emojione package (related to phantomjs installation) # the command below forces the error to happen before build command (not needed on subsequent builds) diff --git a/package-lock.json b/package-lock.json index 293a28ed0d72..b320a3f6b73c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -147,9 +147,9 @@ } }, "@octokit/rest": { - "version": "15.2.6", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-15.2.6.tgz", - "integrity": "sha512-KcqG0zjnjzUqn7wczz/fKiueNpTLiAI7erhUG6bXWAsYKJJlqnwYonFSXrMW/nmes5y+qOk4uSyHBh1mdRXdVQ==", + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-15.3.0.tgz", + "integrity": "sha512-c1nR42ZhZI014lJerh73H2lOLu/3aLXVlpT7gJwg2UqUHQ58lKSGaDbGlRWpwXl7R8bxHeIf0oKpfZjq0Mn+Tw==", "dev": true, "requires": { "before-after-hook": "^1.1.0", @@ -168,7 +168,7 @@ "integrity": "sha512-c+R/U5X+2zz2+UCrCFv6odQzJdoqI+YecuhnAJLa1zYaMc13zPfwMwZrr91Pd1DYNo/yPRbiM4WVf9whgwFsIg==", "dev": true, "requires": { - "es6-promisify": "^5.0.0" + "es6-promisify": "5.0.0" } }, "debug": { @@ -186,8 +186,8 @@ "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==", "dev": true, "requires": { - "agent-base": "^4.1.0", - "debug": "^3.1.0" + "agent-base": "4.2.0", + "debug": "3.1.0" } } } @@ -252,9 +252,9 @@ "integrity": "sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==" }, "@slack/client": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@slack/client/-/client-4.1.0.tgz", - "integrity": "sha512-lcQRQA3/edBlbhkSdBDsn6BW/ynoymCG8yz8kvo96JiLGKGzODxLZJ/FHRs9SMVsqNGsA+sWZcWChUV60gvvRw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@slack/client/-/client-4.2.0.tgz", + "integrity": "sha512-FASaHhy8PPEN/h/eMy9edzwhaRRGfqZA8LklkBcz8z4VYrbWSYljoeup8CfFrl69Atbv4ILrRAPGefytQzoSUA==", "requires": { "@types/delay": "^2.0.1", "@types/form-data": "^2.2.1", @@ -287,9 +287,9 @@ }, "dependencies": { "@types/node": { - "version": "9.6.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-9.6.6.tgz", - "integrity": "sha512-SJe0g5cZeGNDP5sD8mIX3scb+eq8LQQZ60FXiKZHipYSeEFZ5EKml+NNMiO76F74TY4PoMWlNxF/YRY40FOvZQ==" + "version": "9.6.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-9.6.9.tgz", + "integrity": "sha512-xDIb9fSIt1FXbaChHIvoKN1mKoQb+rcqdvtLtIth0Una1V8bnZjznolL5O50TowhuFU9RlqCcldRgzc3iU/KvQ==" }, "loglevel": { "version": "1.6.1", @@ -442,9 +442,9 @@ "integrity": "sha1-R6++GiqSYhkdtoOOT9HTm0CCF0Y=" }, "adm-zip": { - "version": "0.4.8", - "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.8.tgz", - "integrity": "sha512-PcFQf6E2HFbI24MM4wttwKQ/UmBIfPk5qA7+fqXjL+sMQTrE2FykQ3j50TL+MlaEKN+/4IYqTpYfZ2I7Xec2cg==" + "version": "0.4.9", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.9.tgz", + "integrity": "sha512-eknaJ3Io/JasGGinVeqY5TsPlQgHbiNlHnK5zdFPRNs9XRggDykKz8zPesneOMEZJxWji7G3CfsUW0Ds9Dw0Bw==" }, "agent-base": { "version": "2.1.1", @@ -724,16 +724,16 @@ "integrity": "sha512-IKLGtYFb3jzGTtgCpb4bm//1sXmmmgmr0msKshhYoc7EsWmLCFvuyxLcEIfcZ5gbCgZGXrnXkOkcBblOFEnlog==" }, "autoprefixer": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-8.3.0.tgz", - "integrity": "sha512-HY2K4efAvC97v6j83pgV97Lieal51xhIV8EitvS4SrWcI+IGVZgjpihvXImsmIUzA6kb/tglPKzERG1oRFOvRA==", + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-8.4.1.tgz", + "integrity": "sha512-YqUclCBDXUT9Y7aQ8Xv+ja8yhTZYJoMsOD7WS++gZIJLCpCu+gPcKGDlhk6S3WxhLkTcNVdaMZAWys2nzZCH7g==", "dev": true, "requires": { - "browserslist": "^3.2.4", - "caniuse-lite": "^1.0.30000830", + "browserslist": "^3.2.6", + "caniuse-lite": "^1.0.30000832", "normalize-range": "^0.1.2", "num2fraction": "^1.2.2", - "postcss": "^6.0.21", + "postcss": "^6.0.22", "postcss-value-parser": "^3.2.3" }, "dependencies": { @@ -743,29 +743,29 @@ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { - "color-convert": "^1.9.0" + "color-convert": "1.9.1" } }, "browserslist": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.4.tgz", - "integrity": "sha512-Dwe62y/fNAcMfknzGJnkh7feISrrN0SmRvMFozb+Y2+qg7rfTIH5MS8yHzaIXcEWl8fPeIcdhZNQi1Lux+7dlg==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-3.2.6.tgz", + "integrity": "sha512-XCsMSg9V4S1VRdcp265dJ+8kBRjfuFXcavbisY7G6T9QI0H1Z24PP53vvs0WDYWqm38Mco1ILDtafcS8ZR4xiw==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30000821", - "electron-to-chromium": "^1.3.41" + "caniuse-lite": "^1.0.30000830", + "electron-to-chromium": "^1.3.42" } }, "caniuse-lite": { - "version": "1.0.30000830", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000830.tgz", - "integrity": "sha512-yMqGkujkoOIZfvOYiWdqPALgY/PVGiqCHUJb6yNq7xhI/pR+gQO0U2K6lRDqAiJv4+CIU3CtTLblNGw0QGnr6g==", + "version": "1.0.30000833", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000833.tgz", + "integrity": "sha512-tKNuKu4WLImh4NxoTgntxFpDrRiA0Q6Q1NycNhuMST0Kx+Pt8YnRDW6V8xsyH6AtO2CpAoibatEk5eaEhP3O1g==", "dev": true }, "chalk": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.0.tgz", - "integrity": "sha512-Wr/w0f4o9LuE7K53cD0qmbAMM+2XNLzR29vFn5hqko4sxGlUsyy363NvmyGIyk5tpe9cjTr9SJYbysEyPkRnFw==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", @@ -774,9 +774,9 @@ } }, "electron-to-chromium": { - "version": "1.3.42", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.42.tgz", - "integrity": "sha1-lcM78B0MxAVVauyJn+Yf1NduoPk=", + "version": "1.3.45", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.45.tgz", + "integrity": "sha1-RYrBscXHYM6IEaFtK/vZfsMLr7g=", "dev": true }, "has-flag": { @@ -786,14 +786,14 @@ "dev": true }, "postcss": { - "version": "6.0.21", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.21.tgz", - "integrity": "sha512-y/bKfbQz2Nn/QBC08bwvYUxEFOVGfPIUOTsJ2CK5inzlXW9SdYR1x4pEsG9blRAF/PX+wRNdOah+gx/hv4q7dw==", + "version": "6.0.22", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.22.tgz", + "integrity": "sha512-Toc9lLoUASwGqxBSJGTVcOQiDqjK+Z2XlWBg+IgYwQMY9vA2f7iMpXVc1GpPcfTSyM5lkxNo0oDwDRO+wm7XHA==", "dev": true, "requires": { - "chalk": "^2.3.2", + "chalk": "^2.4.1", "source-map": "^0.6.1", - "supports-color": "^5.3.0" + "supports-color": "^5.4.0" } }, "source-map": { @@ -808,15 +808,15 @@ "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "has-flag": "3.0.0" } } } }, "aws-sdk": { - "version": "2.226.1", - "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.226.1.tgz", - "integrity": "sha1-jm4rRmqvJss1cUkF1fk05sgxepk=", + "version": "2.231.1", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.231.1.tgz", + "integrity": "sha1-/wpj9zxxtrCYOJuSa4V7E4Fr1fk=", "requires": { "buffer": "4.9.1", "events": "1.1.1", @@ -840,8 +840,8 @@ "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.17.tgz", "integrity": "sha1-F76T6q4/O3eTWceVtBlwWogX6Gg=", "requires": { - "sax": ">=0.6.0", - "xmlbuilder": "^4.1.0" + "sax": "1.2.1", + "xmlbuilder": "4.2.1" } }, "xmlbuilder": { @@ -849,7 +849,7 @@ "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-4.2.1.tgz", "integrity": "sha1-qlijBBoGb5DqoWwvU4n/GfP0YaU=", "requires": { - "lodash": "^4.0.0" + "lodash": "4.17.5" } } } @@ -2556,6 +2556,20 @@ "isarray": "^1.0.0" } }, + "buffer-alloc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.1.0.tgz", + "integrity": "sha1-BVFNM78WVtNUDGhPZbEgLpDsowM=", + "requires": { + "buffer-alloc-unsafe": "^0.1.0", + "buffer-fill": "^0.1.0" + } + }, + "buffer-alloc-unsafe": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-0.1.1.tgz", + "integrity": "sha1-/+H2dVHdBVc33iUzN7/oU9+rGmo=" + }, "buffer-crc32": { "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", @@ -2571,6 +2585,11 @@ "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" }, + "buffer-fill": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-0.1.1.tgz", + "integrity": "sha512-YgBMBzdRLEfgxJIGu2wrvI2E03tMCFU1p7d1KhB4BOoMN0VxmTFjSyN5JtKt9z8Z9JajMHruI6SE25W96wNv7Q==" + }, "bugsnag": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/bugsnag/-/bugsnag-2.3.1.tgz", @@ -4036,7 +4055,8 @@ "deep-extend": { "version": "0.4.2", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.4.2.tgz", - "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=" + "integrity": "sha1-SLaZwn4zS/ifEIkr5DL25MfTSn8=", + "dev": true }, "deep-is": { "version": "0.1.3", @@ -4785,9 +4805,9 @@ "integrity": "sha1-A9MLX2fdbmMtKUXTDWZScxo01dg=" }, "eventemitter3": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.0.1.tgz", - "integrity": "sha512-QOCPu979MMWX9XNlfRZoin+Wm+bK1SP7vv3NGUniYwuSJK/+cPA10blMaeRgzg31RvoSFk6FsCDVa4vNryBTGA==" + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.0.tgz", + "integrity": "sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA==" }, "events": { "version": "1.1.1", @@ -4832,22 +4852,6 @@ "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-1.1.0.tgz", "integrity": "sha512-kkjwkMqj0h4w/sb32ERCDxCQkREMCAgS39DscDnSwDsbxnwwM1BTZySdC3Bn1lhY7vL08n9GoO/fVTynjDgRyQ==" }, - "express-cookies": { - "version": "1.4.7", - "resolved": "https://registry.npmjs.org/express-cookies/-/express-cookies-1.4.7.tgz", - "integrity": "sha1-63seVFlMApaUEuA8LrUsVjDbrs8=", - "requires": { - "cookie-signature": "1.1.0", - "getcookies": "1.12.3" - }, - "dependencies": { - "cookie-signature": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.1.0.tgz", - "integrity": "sha512-Alvs19Vgq07eunykd3Xy2jF0/qSNv2u7KDbAek9H5liV1UMijbqFs5cycZvv5dVsvseT/U4H8/7/w8Koh35C4A==" - } - } - }, "express-session": { "version": "1.11.3", "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.11.3.tgz", @@ -5343,9 +5347,9 @@ } }, "file-type": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/file-type/-/file-type-7.6.0.tgz", - "integrity": "sha512-EAogdjMKf0PEU26Wk+N/Qkg8JXpMRo9t70dg7+t9QvcYUZb/XfA66Hdt15g4xRdam4wgiQsg/qycKUIuZQDJog==" + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-7.7.1.tgz", + "integrity": "sha512-bTrKkzzZI6wH+NXhyD3SOXtb2zXTw2SbwI2RxUlRcXVsnN7jNL5hJzVQLYv7FOQhxFkK4XWdAflEaWFpaLLWpQ==" }, "filename-regex": { "version": "2.0.1", @@ -5566,6 +5570,11 @@ "readable-stream": "^2.0.0" } }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, "fs-copy-file-sync": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/fs-copy-file-sync/-/fs-copy-file-sync-1.0.1.tgz", @@ -6695,11 +6704,6 @@ "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=" }, - "getcookies": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/getcookies/-/getcookies-1.12.3.tgz", - "integrity": "sha1-3Z9FWmgWtjOd8DVUppxO0C9h1Uk=" - }, "getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", @@ -6956,9 +6960,9 @@ } }, "got": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/got/-/got-8.3.0.tgz", - "integrity": "sha512-kBNy/S2CGwrYgDSec5KTWGKUvupwkkTVAjIsVFF2shXO13xpZdFP4d4kxa//CLX2tN/rV0aYwK8vY6UKWGn2vQ==", + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/got/-/got-8.3.1.tgz", + "integrity": "sha512-tiLX+bnYm5A56T5N/n9Xo89vMaO1mrS9qoDqj3u/anVooqGozvY/HbXzEpDfbNeKsHCBpK40gSbz8wGYSp3i1w==", "requires": { "@sindresorhus/is": "^0.7.0", "cacheable-request": "^2.1.1", @@ -8299,14 +8303,15 @@ "dev": true }, "html-to-text": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-4.0.0.tgz", - "integrity": "sha512-QQl5EEd97h6+3crtgBhkEAO6sQnZyDff8DAeJzoSkOc1Dqe1UvTUZER0B+KjBe6fPZqq549l2VUhtracus3ndA==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-3.3.0.tgz", + "integrity": "sha1-aptjxpm4hbt7qEsURr/mh2u/z7c=", "requires": { "he": "^1.0.0", "htmlparser2": "^3.9.2", - "lodash": "^4.17.4", - "optimist": "^0.6.1" + "optimist": "^0.6.1", + "underscore": "^1.8.3", + "underscore.string": "^3.2.3" }, "dependencies": { "domutils": { @@ -8314,8 +8319,8 @@ "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", "requires": { - "dom-serializer": "0", - "domelementtype": "1" + "dom-serializer": "0.1.0", + "domelementtype": "1.3.0" } }, "htmlparser2": { @@ -8323,12 +8328,12 @@ "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz", "integrity": "sha1-G9+HrMoPP55T+k/M6w9LTLsAszg=", "requires": { - "domelementtype": "^1.3.0", - "domhandler": "^2.3.0", - "domutils": "^1.5.1", - "entities": "^1.1.1", - "inherits": "^2.0.1", - "readable-stream": "^2.0.2" + "domelementtype": "1.3.0", + "domhandler": "2.3.0", + "domutils": "1.7.0", + "entities": "1.1.1", + "inherits": "2.0.3", + "readable-stream": "2.3.4" } } } @@ -8396,14 +8401,6 @@ "statuses": "1" } }, - "http-fetch-cookies": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/http-fetch-cookies/-/http-fetch-cookies-1.0.1.tgz", - "integrity": "sha1-2PNKXL6Ds7mYtHNF4Dl9TwHVK1w=", - "requires": { - "express-cookies": "^1.4.7" - } - }, "http-parser-js": { "version": "0.4.11", "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.4.11.tgz", @@ -9714,19 +9711,25 @@ "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=" }, "mailparser": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/mailparser/-/mailparser-2.2.3.tgz", - "integrity": "sha512-39KOnoRZXWHv69qTI8oYjx+2VwAeM7YAYBKRhqfl4RskLSANQiyjsbIES7+9aQ5/pMNhZcoCrrkcb3oaROLzWQ==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/mailparser/-/mailparser-2.2.0.tgz", + "integrity": "sha512-HVaPa+5xQtG3CQ5SUxbDuJMRnDANC8WllUKXHm46v0tKu3I4YaUlBxg4Lpkvf+qF+kOn0lGcnQgvM6xY5mYALw==", "requires": { "addressparser": "1.0.1", "he": "^1.1.1", - "html-to-text": "4.0.0", - "http-fetch-cookies": "^1.0.1", - "iconv-lite": "0.4.21", + "html-to-text": "3.3.0", + "iconv-lite": "0.4.19", "libmime": "3.1.0", "linkify-it": "2.0.3", "mailsplit": "4.1.2", - "tlds": "1.203.1" + "tlds": "1.199.0" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" + } } }, "mailsplit": { @@ -10333,9 +10336,9 @@ } }, "node-abi": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.3.0.tgz", - "integrity": "sha512-zwm6vU3SsVgw3e9fu48JBaRBCJGIvAgysDsqtf5+vEexFE71bEOtaMWb5zr/zODZNzTPtQlqUUpC79k68Hspow==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.4.0.tgz", + "integrity": "sha512-hRUz0vG+eJfSqwU6rOgW6wNyX85ec8OEE9n4A+u+eoiE8oTePhCkUFTNmwQ+86Kyu429PCLNNyI2P2jL9qKXhw==", "requires": { "semver": "^5.4.1" } @@ -10700,9 +10703,9 @@ "dev": true }, "p-queue": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-2.4.1.tgz", - "integrity": "sha512-xqevcHZy5F9ewg/pnox4S1gFo+9wbLuo+XRMIpdreSaB7d2hAm4JNDuDauOKtHvSmFiS00gTSQoYNbo8rbLoBA==" + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-2.4.2.tgz", + "integrity": "sha512-n8/y+yDJwBjoLQe1GSJbbaYQLTI7QHNZI2+rpmCDbe++WLf9HC3gf6iqj5yfPAV71W4UF3ql5W1+UBPXoXTxng==" }, "p-retry": { "version": "1.0.0", @@ -12178,16 +12181,21 @@ } }, "rc": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.6.tgz", - "integrity": "sha1-6xiYnG1PTxYsOZ953dKfODVWgJI=", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.7.tgz", + "integrity": "sha512-LdLD8xD4zzLsAT5xyushXDNscEjB7+2ulnl8+r1pnESlYtlJtVSoCMBGr30eDRJ3+2Gq89jK9P9e4tCEH1+ywA==", "requires": { - "deep-extend": "~0.4.0", + "deep-extend": "^0.5.1", "ini": "~1.3.0", "minimist": "^1.2.0", "strip-json-comments": "~2.0.1" }, "dependencies": { + "deep-extend": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.5.1.tgz", + "integrity": "sha512-N8vBdOa+DF7zkRrDCsaOXoCs/E2fJfx9B9MrKnnSiHNh4ws7eSys6YQE4KvT1cecKmOASYQBhbKjeuDD9lT81w==" + }, "minimist": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", @@ -13130,19 +13138,19 @@ } }, "sharp": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.20.1.tgz", - "integrity": "sha512-Mj6zWnt3vG8TraXqkrjdql4BkKXhoLmHP8+yZglx7Nc1EH5YaClqur/JKRWpkPzPHbYayBt6rxXqfPd2tgYvvg==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.20.2.tgz", + "integrity": "sha512-cFL2qUT9eyR29bI+gj5kQjWlj+VIuTGdcY/CErQqmwJ4FKTXhmdE6d/zwjmrAokzr5n547KQed8HFQsmyUv9uw==", "requires": { "color": "^3.0.0", "detect-libc": "^1.0.3", "fs-copy-file-sync": "^1.0.1", "nan": "^2.10.0", "npmlog": "^4.1.2", - "prebuild-install": "^2.5.1", + "prebuild-install": "^2.5.3", "semver": "^5.5.0", - "simple-get": "^2.7.0", - "tar": "^4.4.0", + "simple-get": "^2.8.1", + "tar": "^4.4.1", "tunnel-agent": "^0.6.0" }, "dependencies": { @@ -13179,9 +13187,9 @@ "integrity": "sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY=" }, "simple-get": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.7.0.tgz", - "integrity": "sha512-RkE9rGPHcxYZ/baYmgJtOSM63vH0Vyq+ma5TijBcLla41SWlh8t6XYIGMR/oeZcmr+/G8k+zrClkkVrtnQ0esg==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.8.1.tgz", + "integrity": "sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw==", "requires": { "decompress-response": "^3.3.0", "once": "^1.3.1", @@ -14327,19 +14335,24 @@ } }, "tar": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.1.tgz", - "integrity": "sha512-O+v1r9yN4tOsvl90p5HAP4AEqbYhx4036AGMm075fH9F8Qwi3oJ+v4u50FkT/KkvywNGtwkk0zRI+8eYm1X/xg==", + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.2.tgz", + "integrity": "sha512-BfkE9CciGGgDsATqkikUHrQrraBCO+ke/1f6SFAEMnxyyfN9lxC+nW1NFWMpqH865DhHIy9vQi682gk1X7friw==", "requires": { "chownr": "^1.0.1", "fs-minipass": "^1.2.5", "minipass": "^2.2.4", "minizlib": "^1.1.0", "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.1", + "safe-buffer": "^5.1.2", "yallist": "^3.0.2" }, "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, "yallist": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz", @@ -14348,9 +14361,9 @@ } }, "tar-fs": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-1.16.0.tgz", - "integrity": "sha512-I9rb6v7mjWLtOfCau9eH5L7sLJyU2BnxtEZRQ5Mt+eRKmf1F0ohXmT/Jc3fr52kDvjJ/HV5MH3soQfPL5bQ0Yg==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-1.16.2.tgz", + "integrity": "sha512-LdknWjPEiZC1nOBwhv0JBzfJBGPJar08dZg2rwZe0ZTLQoRGEzgrl7vF3qUEkCHpI/wN9e7RyCuDhMsJUCLPPQ==", "requires": { "chownr": "^1.0.1", "mkdirp": "^0.5.1", @@ -14363,20 +14376,23 @@ "resolved": "https://registry.npmjs.org/pump/-/pump-1.0.3.tgz", "integrity": "sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==", "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" + "end-of-stream": "1.4.1", + "once": "1.4.0" } } } }, "tar-stream": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.5.5.tgz", - "integrity": "sha512-mQdgLPc/Vjfr3VWqWbfxW8yQNiJCbAZ+Gf6GDu1Cy0bdb33ofyiNGBtAY96jHFhDuivCwgW1H9DgTON+INiXgg==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.0.tgz", + "integrity": "sha512-lh2iAPG/BHNmN6WB9Ybdynk9rEJ5GD/dy4zscHmVlwa1dq2tpE+BH78i5vjYwYVWEaOXGBjzxr89aVACF17Cpw==", "requires": { "bl": "^1.0.0", + "buffer-alloc": "^1.1.0", "end-of-stream": "^1.0.0", + "fs-constants": "^1.0.0", "readable-stream": "^2.0.0", + "to-buffer": "^1.1.0", "xtend": "^4.0.0" } }, @@ -14450,9 +14466,9 @@ "integrity": "sha512-2NM0auVBGft5tee/OxP4PI3d8WItkDM+fPnaRAVo6xTDI2knbz9eC5ArWGqtGlYqiH3RU5yMpdyTTO7MguC4ow==" }, "tlds": { - "version": "1.203.1", - "resolved": "https://registry.npmjs.org/tlds/-/tlds-1.203.1.tgz", - "integrity": "sha512-7MUlYyGJ6rSitEZ3r1Q1QNV8uSIzapS8SmmhSusBuIc7uIxPPwsKllEP0GRp1NS6Ik6F+fRZvnjDWm3ecv2hDw==" + "version": "1.199.0", + "resolved": "https://registry.npmjs.org/tlds/-/tlds-1.199.0.tgz", + "integrity": "sha512-NM0jUhibJjEX4g0+1ETxOhuODIDpyvCC0A2BjxrTfMUMZ+uRZc6ZnJl9SmFtAW1s5iQgQIxezFpUij6/6OiRbg==" }, "tmp": { "version": "0.0.33", @@ -14463,6 +14479,11 @@ "os-tmpdir": "~1.0.2" } }, + "to-buffer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", + "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==" + }, "to-fast-properties": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", diff --git a/package.json b/package.json index 4c7d0e7bdbb4..9cee9c8477c5 100644 --- a/package.json +++ b/package.json @@ -88,8 +88,8 @@ "email": "support@rocket.chat" }, "devDependencies": { - "@octokit/rest": "^15.2.6", - "autoprefixer": "^8.3.0", + "@octokit/rest": "^15.3.0", + "autoprefixer": "^8.4.1", "babel-mocha-es6-compiler": "^0.1.0", "babel-plugin-array-includes": "^2.0.3", "chimp": "^0.51.1", @@ -114,12 +114,12 @@ "@google-cloud/language": "^1.1.0", "@google-cloud/storage": "^1.6.0", "@google-cloud/vision": "^0.19.0", - "@slack/client": "^4.1.0", - "adm-zip": "^0.4.7", + "@slack/client": "^4.2.0", + "adm-zip": "^0.4.9", "archiver": "^2.1.1", "atlassian-crowd": "^0.5.0", "autolinker": "^1.6.2", - "aws-sdk": "^2.199.0", + "aws-sdk": "^2.231.1", "bad-words": "^1.6.1", "bcrypt": "^2.0.1", "bson": "^1.0.4", @@ -134,7 +134,7 @@ "core-js": "^2.5.3", "csv-parse": "^1.3.3", "emailreplyparser": "^0.0.5", - "file-type": "^7.6.0", + "file-type": "^7.7.1", "filesize": "^3.6.0", "gridfs-stream": "^1.1.1", "he": "^1.1.1", @@ -166,9 +166,9 @@ "querystring": "^0.2.0", "redis": "^2.8.0", "semver": "^5.5.0", - "sharp": "^0.20.1", + "sharp": "^0.20.2", "speakeasy": "^2.0.0", - "tar-stream": "^1.5.5", + "tar-stream": "^1.6.0", "toastr": "^2.1.4", "twilio": "^2.9.1", "twit": "^2.2.9", diff --git a/packages/meteor-accounts-saml/saml_server.js b/packages/meteor-accounts-saml/saml_server.js index 067bbb765a7f..9ffc945bff32 100644 --- a/packages/meteor-accounts-saml/saml_server.js +++ b/packages/meteor-accounts-saml/saml_server.js @@ -170,17 +170,20 @@ Accounts.registerLoginHandler(function(loginRequest) { } }); -Accounts.saml._loginResultForCredentialToken = {}; - Accounts.saml.hasCredential = function(credentialToken) { - return _.has(Accounts.saml._loginResultForCredentialToken, credentialToken); + return RocketChat.models.CredentialTokens.findOneById(credentialToken) != null; }; Accounts.saml.retrieveCredential = function(credentialToken) { // The credentialToken in all these functions corresponds to SAMLs inResponseTo field and is mandatory to check. - const result = Accounts.saml._loginResultForCredentialToken[credentialToken]; - delete Accounts.saml._loginResultForCredentialToken[credentialToken]; - return result; + const data = RocketChat.models.CredentialTokens.findOneById(credentialToken); + if (data) { + return data.userInfo; + } +}; + +Accounts.saml.storeCredential = function(credentialToken, loginResult) { + RocketChat.models.CredentialTokens.create(credentialToken, loginResult); }; const closePopup = function(res, err) { @@ -334,21 +337,21 @@ const middleware = function(req, res, next) { } const credentialToken = (profile.inResponseToId && profile.inResponseToId.value) || profile.inResponseToId || profile.InResponseTo || samlObject.credentialToken; + const loginResult = { + profile + }; if (!credentialToken) { // No credentialToken in IdP-initiated SSO const saml_idp_credentialToken = Random.id(); - Accounts.saml._loginResultForCredentialToken[saml_idp_credentialToken] = { - profile - }; + Accounts.saml.storeCredential(saml_idp_credentialToken, loginResult); + const url = `${ Meteor.absoluteUrl('home') }?saml_idp_credentialToken=${ saml_idp_credentialToken }`; res.writeHead(302, { 'Location': url }); res.end(); } else { - Accounts.saml._loginResultForCredentialToken[credentialToken] = { - profile - }; + Accounts.saml.storeCredential(credentialToken, loginResult); closePopup(res); } }); diff --git a/packages/rocketchat-apps/client/admin/appInstall.html b/packages/rocketchat-apps/client/admin/appInstall.html index 15564eac7a43..fa7b7cdc7206 100644 --- a/packages/rocketchat-apps/client/admin/appInstall.html +++ b/packages/rocketchat-apps/client/admin/appInstall.html @@ -49,8 +49,14 @@
- - + +
{{/if}} diff --git a/packages/rocketchat-apps/client/admin/appInstall.js b/packages/rocketchat-apps/client/admin/appInstall.js index f41dcb84401b..0369f75254c4 100644 --- a/packages/rocketchat-apps/client/admin/appInstall.js +++ b/packages/rocketchat-apps/client/admin/appInstall.js @@ -21,6 +21,11 @@ Template.appInstall.helpers({ disabled() { const instance = Template.instance(); return !(instance.appUrl.get() || instance.file.get()); + }, + isUpdating() { + const instance = Template.instance(); + + return !!instance.isUpdatingId.get(); } }); diff --git a/packages/rocketchat-apps/server/communication/websockets.js b/packages/rocketchat-apps/server/communication/websockets.js index 098f65811f50..1b22c2b7aae3 100644 --- a/packages/rocketchat-apps/server/communication/websockets.js +++ b/packages/rocketchat-apps/server/communication/websockets.js @@ -13,16 +13,17 @@ export const AppEvents = Object.freeze({ }); export class AppServerListener { - constructor(orch, engineStreamer, clientStreamer, recieved) { + constructor(orch, engineStreamer, clientStreamer, received) { this.orch = orch; this.engineStreamer = engineStreamer; this.clientStreamer = clientStreamer; - this.recieved = recieved; + this.received = received; this.engineStreamer.on(AppEvents.APP_ADDED, this.onAppAdded.bind(this)); this.engineStreamer.on(AppEvents.APP_STATUS_CHANGE, this.onAppStatusUpdated.bind(this)); this.engineStreamer.on(AppEvents.APP_SETTING_UPDATED, this.onAppSettingUpdated.bind(this)); this.engineStreamer.on(AppEvents.APP_REMOVED, this.onAppRemoved.bind(this)); + this.engineStreamer.on(AppEvents.APP_UPDATED, this.onAppUpdated.bind(this)); this.engineStreamer.on(AppEvents.COMMAND_ADDED, this.onCommandAdded.bind(this)); this.engineStreamer.on(AppEvents.COMMAND_DISABLED, this.onCommandDisabled.bind(this)); this.engineStreamer.on(AppEvents.COMMAND_UPDATED, this.onCommandUpdated.bind(this)); @@ -35,7 +36,7 @@ export class AppServerListener { } async onAppStatusUpdated({ appId, status }) { - this.recieved.set(`${ AppEvents.APP_STATUS_CHANGE }_${ appId }`, { appId, status, when: new Date() }); + this.received.set(`${ AppEvents.APP_STATUS_CHANGE }_${ appId }`, { appId, status, when: new Date() }); if (AppStatusUtils.isEnabled(status)) { await this.orch.getManager().enable(appId); @@ -47,12 +48,21 @@ export class AppServerListener { } async onAppSettingUpdated({ appId, setting }) { - this.recieved.set(`${ AppEvents.APP_SETTING_UPDATED }_${ appId }_${ setting.id }`, { appId, setting, when: new Date() }); + this.received.set(`${ AppEvents.APP_SETTING_UPDATED }_${ appId }_${ setting.id }`, { appId, setting, when: new Date() }); await this.orch.getManager().getSettingsManager().updateAppSetting(appId, setting); this.clientStreamer.emit(AppEvents.APP_SETTING_UPDATED, { appId }); } + async onAppUpdated(appId) { + this.received.set(`${ AppEvents.APP_UPDATED }_${ appId }`, { appId, when: new Date() }); + + const storageItem = await this.orch.getStorage().retrieveOne(appId); + + await this.orch.getManager().update(storageItem.zip); + this.clientStreamer.emit(AppEvents.APP_UPDATED, appId); + } + async onAppRemoved(appId) { await this.orch.getManager().remove(appId); this.clientStreamer.emit(AppEvents.APP_REMOVED, appId); @@ -90,8 +100,8 @@ export class AppServerNotifier { this.clientStreamer.allowEmit('all'); this.clientStreamer.allowWrite('none'); - this.recieved = new Map(); - this.listener = new AppServerListener(orch, this.engineStreamer, this.clientStreamer, this.recieved); + this.received = new Map(); + this.listener = new AppServerListener(orch, this.engineStreamer, this.clientStreamer, this.received); } async appAdded(appId) { @@ -105,15 +115,20 @@ export class AppServerNotifier { } async appUpdated(appId) { + if (this.received.has(`${ AppEvents.APP_UPDATED }_${ appId }`)) { + this.received.delete(`${ AppEvents.APP_UPDATED }_${ appId }`); + return; + } + this.engineStreamer.emit(AppEvents.APP_UPDATED, appId); this.clientStreamer.emit(AppEvents.APP_UPDATED, appId); } async appStatusUpdated(appId, status) { - if (this.recieved.has(`${ AppEvents.APP_STATUS_CHANGE }_${ appId }`)) { - const details = this.recieved.get(`${ AppEvents.APP_STATUS_CHANGE }_${ appId }`); + if (this.received.has(`${ AppEvents.APP_STATUS_CHANGE }_${ appId }`)) { + const details = this.received.get(`${ AppEvents.APP_STATUS_CHANGE }_${ appId }`); if (details.status === status) { - this.recieved.delete(`${ AppEvents.APP_STATUS_CHANGE }_${ appId }`); + this.received.delete(`${ AppEvents.APP_STATUS_CHANGE }_${ appId }`); return; } } @@ -123,8 +138,8 @@ export class AppServerNotifier { } async appSettingsChange(appId, setting) { - if (this.recieved.has(`${ AppEvents.APP_SETTING_UPDATED }_${ appId }_${ setting.id }`)) { - this.recieved.delete(`${ AppEvents.APP_SETTING_UPDATED }_${ appId }_${ setting.id }`); + if (this.received.has(`${ AppEvents.APP_SETTING_UPDATED }_${ appId }_${ setting.id }`)) { + this.received.delete(`${ AppEvents.APP_SETTING_UPDATED }_${ appId }_${ setting.id }`); return; } diff --git a/packages/rocketchat-apps/server/converters/messages.js b/packages/rocketchat-apps/server/converters/messages.js index b762a16f9f19..d62fbccb377e 100644 --- a/packages/rocketchat-apps/server/converters/messages.js +++ b/packages/rocketchat-apps/server/converters/messages.js @@ -129,7 +129,9 @@ export class AppMessagesConverter { image_url: attachment.imageUrl, audio_url: attachment.audioUrl, video_url: attachment.videoUrl, - fields: attachment.fields + fields: attachment.fields, + type: attachment.type, + description: attachment.description }; }).map((a) => { Object.keys(a).forEach((k) => { @@ -178,7 +180,9 @@ export class AppMessagesConverter { imageUrl: attachment.image_url, audioUrl: attachment.audio_url, videoUrl: attachment.video_url, - fields: attachment.fields + fields: attachment.fields, + type: attachment.type, + description: attachment.description }; }); } diff --git a/packages/rocketchat-cors/cors.js b/packages/rocketchat-cors/cors.js index 5e45911acc9b..4bf4a3403822 100644 --- a/packages/rocketchat-cors/cors.js +++ b/packages/rocketchat-cors/cors.js @@ -11,9 +11,18 @@ tls.DEFAULT_ECDH_CURVE = 'auto'; // Revert change from Meteor 1.6.1 who set ignoreUndefined: true // more information https://github.com/meteor/meteor/pull/9444 -Mongo.setConnectionOptions({ +let mongoOptions = { ignoreUndefined: false -}); +}; + +const mongoOptionStr = process.env.MONGO_OPTIONS; +if (typeof mongoOptionStr !== 'undefined') { + const jsonMongoOptions = JSON.parse(mongoOptionStr); + + mongoOptions = Object.assign({}, mongoOptions, jsonMongoOptions); +} + +Mongo.setConnectionOptions(mongoOptions); WebApp.rawConnectHandlers.use(Meteor.bindEnvironment(function(req, res, next) { if (req._body) { diff --git a/packages/rocketchat-lib/client/lib/RestApiClient.js b/packages/rocketchat-lib/client/lib/RestApiClient.js index cadcbaed02e7..b3e958117654 100644 --- a/packages/rocketchat-lib/client/lib/RestApiClient.js +++ b/packages/rocketchat-lib/client/lib/RestApiClient.js @@ -70,7 +70,7 @@ RocketChat.API = { return new Promise(function _jqueryFormDataPromise(resolve, reject) { jQuery.ajax({ - url: `${ Meteor.absoluteUrl() }api/${ endpoint }${ query }`, + url: `${ window.location.origin }/api/${ endpoint }${ query }`, headers: { 'X-User-Id': localStorage['Meteor.userId'], 'X-Auth-Token': localStorage['Meteor.loginToken'] diff --git a/packages/rocketchat-lib/server/functions/createRoom.js b/packages/rocketchat-lib/server/functions/createRoom.js index 8f78788af264..4fa617950ee8 100644 --- a/packages/rocketchat-lib/server/functions/createRoom.js +++ b/packages/rocketchat-lib/server/functions/createRoom.js @@ -65,12 +65,13 @@ RocketChat.createRoom = function(type, name, owner, members, readOnly, extraData for (const username of members) { const member = RocketChat.models.Users.findOneByUsername(username, { fields: { username: 1 }}); + const isTheOwner = username === owner.username; if (!member) { continue; } - // make all room members muted by default, unless they have the post-readonly permission - if (readOnly === true && !RocketChat.authz.hasPermission(member._id, 'post-readonly')) { + // make all room members (Except the owner) muted by default, unless they have the post-readonly permission + if (readOnly === true && !RocketChat.authz.hasPermission(member._id, 'post-readonly') && !isTheOwner) { RocketChat.models.Rooms.muteUsernameByRoomId(room._id, username); } diff --git a/packages/rocketchat-lib/server/functions/sendMessage.js b/packages/rocketchat-lib/server/functions/sendMessage.js index 585168cfe562..89c58881ac17 100644 --- a/packages/rocketchat-lib/server/functions/sendMessage.js +++ b/packages/rocketchat-lib/server/functions/sendMessage.js @@ -121,31 +121,18 @@ RocketChat.sendMessage = function(user, message, room, upsert = false) { } if (message.parseUrls !== false) { - const urlRegex = /([A-Za-z]{3,9}):\/\/([-;:&=\+\$,\w]+@{1})?([-A-Za-z0-9\.]+)+:?(\d+)?((\/[-\+=!:~%\/\.@\,\(\)\w]*)?\??([-\+=&!:;%@\/\.\,\w]+)?(?:#([^\s\)]+))?)?/g; - const urls = message.msg.match(urlRegex); + message.html = message.msg; + message = RocketChat.Markdown.code(message); + + const urls = message.html.match(/([A-Za-z]{3,9}):\/\/([-;:&=\+\$,\w]+@{1})?([-A-Za-z0-9\.]+)+:?(\d+)?((\/[-\+=!:~%\/\.@\,\(\)\w]*)?\??([-\+=&!:;%@\/\.\,\w]+)?(?:#([^\s\)]+))?)?/g); if (urls) { - // ignoredUrls contain blocks of quotes with urls inside - const ignoredUrls = message.msg.match(/(?:(?:\`{1,3})(?:[\n\r]*?.*?)*?)(([A-Za-z]{3,9}):\/\/([-;:&=\+\$,\w]+@{1})?([-A-Za-z0-9\.]+)+:?(\d+)?((\/[-\+=!:~%\/\.@\,\(\)\w]*)?\??([-\+=&!:;%@\/\.\,\w]+)?(?:#([^\s\)]+))?)?)(?:(?:[\n\r]*.*?)*?(?:\`{1,3}))/gm); - if (ignoredUrls) { - ignoredUrls.forEach((url) => { - const shouldBeIgnored = url.match(urlRegex); - if (shouldBeIgnored) { - shouldBeIgnored.forEach((match) => { - const matchIndex = urls.indexOf(match); - urls.splice(matchIndex, 1); - }); - } - }); - } - if (urls) { - // use the Set to remove duplicity, so it doesn't embed the same link twice - message.urls = [...new Set(urls)].map(function(url) { - return { - url - }; - }); - } + message.urls = urls.map((url) => ({ url })); } + + message = RocketChat.Markdown.mountTokensBack(message, false); + message.msg = message.html; + delete message.html; + delete message.tokens; } message = RocketChat.callbacks.run('beforeSaveMessage', message); diff --git a/packages/rocketchat-lib/server/lib/sendEmailOnMessage.js b/packages/rocketchat-lib/server/lib/sendEmailOnMessage.js index c4351cc46c7c..860f2232860a 100644 --- a/packages/rocketchat-lib/server/lib/sendEmailOnMessage.js +++ b/packages/rocketchat-lib/server/lib/sendEmailOnMessage.js @@ -4,9 +4,9 @@ import s from 'underscore.string'; function getEmailContent({ messageContent, message, user, room }) { const lng = user && user.language || RocketChat.settings.get('language') || 'en'; - const roomName = `#${ RocketChat.settings.get('UI_Allow_room_names_with_special_chars') ? room.fname || room.name : room.name }`; + const roomName = s.escapeHTML(`#${ RocketChat.settings.get('UI_Allow_room_names_with_special_chars') ? room.fname || room.name : room.name }`); - const userName = RocketChat.settings.get('UI_Use_Real_Name') ? message.u.name || message.u.username : message.u.username; + const userName = s.escapeHTML(RocketChat.settings.get('UI_Use_Real_Name') ? message.u.name || message.u.username : message.u.username); const header = TAPi18n.__(room.t === 'd' ? 'User_sent_a_message_to_you' : 'User_sent_a_message_on_channel', { username: userName, @@ -25,10 +25,10 @@ function getEmailContent({ messageContent, message, user, room }) { lng }); - let content = `${ TAPi18n.__('Attachment_File_Uploaded') }: ${ message.file.name }`; + let content = `${ TAPi18n.__('Attachment_File_Uploaded') }: ${ s.escapeHTML(message.file.name) }`; if (message.attachments && message.attachments.length === 1 && message.attachments[0].description !== '') { - content += `

${ message.attachments[0].description }`; + content += `

${ s.escapeHTML(message.attachments[0].description) }`; } return `${ fileHeader }

${ content }`; @@ -40,10 +40,10 @@ function getEmailContent({ messageContent, message, user, room }) { let content = ''; if (attachment.title) { - content += `${ attachment.title }
`; + content += `${ s.escapeHTML(attachment.title) }
`; } if (attachment.text) { - content += `${ attachment.text }
`; + content += `${ s.escapeHTML(attachment.text) }
`; } return `${ header }

${ content }`; @@ -241,9 +241,9 @@ RocketChat.callbacks.add('afterSaveMessage', function(message, room) { }; // using user full-name/channel name in from address if (room.t === 'd') { - email.from = `${ message.u.name } <${ RocketChat.settings.get('From_Email') }>`; + email.from = `${ String(message.u.name).replace(/@/g, '%40').replace(/[<>,]/g, '') } <${ RocketChat.settings.get('From_Email') }>`; } else { - email.from = `${ room.name } <${ RocketChat.settings.get('From_Email') }>`; + email.from = `${ String(room.name).replace(/@/g, '%40').replace(/[<>,]/g, '') } <${ RocketChat.settings.get('From_Email') }>`; } // If direct reply enabled, email content with headers if (RocketChat.settings.get('Direct_Reply_Enable')) { diff --git a/packages/rocketchat-lib/server/lib/sendNotificationsOnMessage.js b/packages/rocketchat-lib/server/lib/sendNotificationsOnMessage.js index aee2caa865ff..e3c811d19366 100644 --- a/packages/rocketchat-lib/server/lib/sendNotificationsOnMessage.js +++ b/packages/rocketchat-lib/server/lib/sendNotificationsOnMessage.js @@ -63,13 +63,24 @@ function notifyDesktopUser(userId, user, message, room, duration) { if (UI_Use_Real_Name) { message.msg = replaceMentionedUsernamesWithFullNames(message.msg, message.mentions); } - let title = UI_Use_Real_Name ? user.name : `@${ user.username }`; - if (room.t !== 'd' && room.name) { - title += ` @ #${ room.name }`; + + let title = ''; + let text = ''; + if (room.t === 'd') { + title = UI_Use_Real_Name ? user.name : `@${ user.username }`; + text = message.msg; + } else if (room.name) { + title = `#${ room.name }`; + text = `${ user.username }: ${ message.msg }`; + } + + if (title === '' || text === '') { + return; } + RocketChat.Notifications.notifyUser(userId, 'notification', { title, - text: message.msg, + text, duration, payload: { _id: message._id, diff --git a/packages/rocketchat-lib/server/startup/settings.js b/packages/rocketchat-lib/server/startup/settings.js index a471b8bda3cf..9434185df598 100644 --- a/packages/rocketchat-lib/server/startup/settings.js +++ b/packages/rocketchat-lib/server/startup/settings.js @@ -708,7 +708,7 @@ RocketChat.settings.addGroup('General', function() { type: 'action', actionText: 'Restart_the_server' }); - this.add('Store_Last_Message', false, { + this.add('Store_Last_Message', true, { type: 'boolean', public: true, i18nDescription: 'Store_Last_Message_Sent_per_Room' diff --git a/packages/rocketchat-livechat/.app/.meteor/versions b/packages/rocketchat-livechat/.app/.meteor/versions index bf8dc0dbce38..25dc26f932d8 100644 --- a/packages/rocketchat-livechat/.app/.meteor/versions +++ b/packages/rocketchat-livechat/.app/.meteor/versions @@ -2,7 +2,7 @@ accounts-base@1.4.2 accounts-password@1.5.1 aldeed:simple-schema@1.5.4 allow-deny@1.1.0 -babel-compiler@7.0.7 +babel-compiler@7.0.8 babel-runtime@1.2.2 base64@1.0.11 binary-heap@1.0.10 @@ -23,7 +23,7 @@ ddp-server@2.1.2 deps@1.0.12 diff-sequence@1.1.0 dynamic-import@0.3.0 -ecmascript@0.10.7 +ecmascript@0.10.8 ecmascript-runtime@0.5.0 ecmascript-runtime-client@0.6.2 ecmascript-runtime-server@0.5.0 diff --git a/packages/rocketchat-markdown/markdown.js b/packages/rocketchat-markdown/markdown.js index 001b39ba57bb..013ddefd2d7f 100644 --- a/packages/rocketchat-markdown/markdown.js +++ b/packages/rocketchat-markdown/markdown.js @@ -10,6 +10,8 @@ import { RocketChat } from 'meteor/rocketchat:lib'; import { marked } from './parser/marked/marked.js'; import { original } from './parser/original/original.js'; +import { code } from './parser/original/code.js'; + const parsers = { original, marked @@ -43,15 +45,19 @@ class MarkdownClass { return parsers['original'](message); } - mountTokensBack(message) { + mountTokensBack(message, useHtml = true) { if (message.tokens && message.tokens.length > 0) { - for (const {token, text} of message.tokens) { - message.html = message.html.replace(token, () => text); // Uses lambda so doesn't need to escape $ + for (const {token, text, noHtml} of message.tokens) { + message.html = message.html.replace(token, () => useHtml ? text : noHtml); // Uses lambda so doesn't need to escape $ } } return message; } + + code(...args) { + return code(...args); + } } const Markdown = new MarkdownClass; diff --git a/packages/rocketchat-markdown/parser/original/code.js b/packages/rocketchat-markdown/parser/original/code.js index e74d271cb317..dc69dcc9f590 100644 --- a/packages/rocketchat-markdown/parser/original/code.js +++ b/packages/rocketchat-markdown/parser/original/code.js @@ -39,7 +39,7 @@ const codeblocks = (message) => { for (let index = 0; index < msgParts.length; index++) { // Verify if this part is code const part = msgParts[index]; - const codeMatch = part.match(/^```(.*[\r\n\ ]?)([\s\S]*?)```+?$/); + const codeMatch = part.match(/^```[\r\n]*(.*[\r\n\ ]?)[\r\n]*([\s\S]*?)```+?$/); if (codeMatch != null) { // Process highlight if this part is code @@ -59,7 +59,7 @@ const codeblocks = (message) => { highlight: true, token, text: `
\`\`\`
${ result.value }
\`\`\`
`, - noHtml: `\`\`\`\n${ s.stripTags(result.value) }\n\`\`\`` + noHtml: codeMatch[0] }); msgParts[index] = token; diff --git a/packages/rocketchat-markdown/tests/client.tests.js b/packages/rocketchat-markdown/tests/client.tests.js index 96c93d98d964..fa376d6bb03d 100644 --- a/packages/rocketchat-markdown/tests/client.tests.js +++ b/packages/rocketchat-markdown/tests/client.tests.js @@ -207,10 +207,10 @@ const inlinecode = { const code = { '```code```': codeWrapper('code', 'clean'), '```code': codeWrapper('code\n', 'stylus'), - '```code\n': codeWrapper('code\n\n', 'stylus'), - '```\ncode\n```': codeWrapper('\ncode\n', 'stylus'), + '```code\n': codeWrapper('code\n', 'stylus'), + '```\ncode\n```': codeWrapper('code\n', 'stylus'), '```code\n```': codeWrapper('code\n', 'stylus'), - '```\ncode```': codeWrapper('\ncode', 'clean'), + '```\ncode```': codeWrapper('code', 'clean'), '```javascript\nvar a = \'log\';\nconsole.log(a);```': codeWrapper('var a = \'log\';\nconsole.log(a);', 'javascript'), '```*code*```': codeWrapper('*code*', 'armasm'), '```**code**```': codeWrapper('**code**', 'armasm'), diff --git a/packages/rocketchat-theme/client/imports/components/message-box.css b/packages/rocketchat-theme/client/imports/components/message-box.css index 18c3d15d9a35..4221b7f2eb1b 100644 --- a/packages/rocketchat-theme/client/imports/components/message-box.css +++ b/packages/rocketchat-theme/client/imports/components/message-box.css @@ -123,6 +123,7 @@ &__icon { display: flex; + flex: auto 0 0; width: 50px; height: 21px; diff --git a/packages/rocketchat-weekly-summary/lib/rocketchat.js b/packages/rocketchat-weekly-summary/lib/rocketchat.js new file mode 100644 index 000000000000..6a14b4b7472a --- /dev/null +++ b/packages/rocketchat-weekly-summary/lib/rocketchat.js @@ -0,0 +1 @@ +RocketChat.weeklySummary = {}; diff --git a/packages/rocketchat-weekly-summary/package.js b/packages/rocketchat-weekly-summary/package.js new file mode 100644 index 000000000000..945be6623397 --- /dev/null +++ b/packages/rocketchat-weekly-summary/package.js @@ -0,0 +1,23 @@ +Package.describe({ + name: 'goalifychat:weekly-summary', + version: '0.0.1', + summary: 'Weekly summary generator', + git: '' +}); + +Package.onUse(function(api) { + api.use([ + 'mongo', + 'ecmascript', + 'rocketchat:lib' + ]); + + // WeeklySummary + api.addFiles('lib/rocketchat.js', [ 'client', 'server' ]); + api.addFiles([ + 'server/models/WeeklySummary.js', + 'server/functions/get.js', + 'server/functions/save.js', + 'server/methods/getWeeklySummary.js' + ], 'server'); +}); diff --git a/packages/rocketchat-weekly-summary/server/functions/get.js b/packages/rocketchat-weekly-summary/server/functions/get.js new file mode 100644 index 000000000000..b8d4f8d1af57 --- /dev/null +++ b/packages/rocketchat-weekly-summary/server/functions/get.js @@ -0,0 +1,57 @@ +import _ from 'underscore'; + +RocketChat.weeklySummary.get = function _getWeeklySummary() { + const weeklySummary = {}; + const now = new Date(); + const weekday = now.getDay(); + const nowDate = now.getDate(); + const lastDayLastWeek = new Date(now.setDate(nowDate - weekday)); + lastDayLastWeek.setHours(23, 59, 59); + const firstDayLastWeek = new Date(now.setDate(nowDate - weekday - 6)); + firstDayLastWeek.setHours(0, 0, 1); + + weeklySummary.startDate = firstDayLastWeek; + weeklySummary.endDate = lastDayLastWeek; + + const weeklyQuery = { + $and: [ + { ts: { $gte: firstDayLastWeek } }, + { ts: { $lte: lastDayLastWeek } } + ] + }; + + // Total User + weeklySummary.totalUsers = Meteor.users.find().count(); + weeklySummary.admins = Meteor.users.find({ roles: { $in: ['admin'] } }).fetch(); + weeklySummary.activeUsers = Meteor.users.find({ active: true }).count(); + weeklySummary.nonActiveUsers = weeklySummary.totalUsers - weeklySummary.activeUsers; + + // Total Room + weeklySummary.totalRooms = RocketChat.models.Rooms.find().count(); + weeklySummary.totalChannels = RocketChat.models.Rooms.findByType('c').count(); + weeklySummary.totalPrivateGroups = RocketChat.models.Rooms.findByType('p').count(); + weeklySummary.totalDirect = RocketChat.models.Rooms.findByType('d').count(); + weeklySummary.totlalLivechat = RocketChat.models.Rooms.findByType('l').count(); + + // Total Message + weeklySummary.totalChannelMessages = _.reduce(RocketChat.models.Rooms.findByType('c', { fields: { 'msgs': 1 }}).fetch(), function _countChannelMessages(num, room) { return num + room.msgs; }, 0); + weeklySummary.totalPrivateGroupMessages = _.reduce(RocketChat.models.Rooms.findByType('p', { fields: { 'msgs': 1 }}).fetch(), function _countPrivateGroupMessages(num, room) { return num + room.msgs; }, 0); + weeklySummary.totalDirectMessages = _.reduce(RocketChat.models.Rooms.findByType('d', { fields: { 'msgs': 1 }}).fetch(), function _countDirectMessages(num, room) { return num + room.msgs; }, 0); + weeklySummary.totalLivechatMessages = _.reduce(RocketChat.models.Rooms.findByType('l', { fields: { 'msgs': 1 }}).fetch(), function _countLivechatMessages(num, room) { return num + room.msgs; }, 0); + + // Message Weekly + let messagesInWeek = RocketChat.models.Messages.find(weeklyQuery); + weeklySummary.totalMessagesInWeek = messagesInWeek.count(); + messagesInWeek = messagesInWeek.map(message => { + return Object.assign({}, message, { + room: RocketChat.models.Rooms.findOne({ _id: message.rid }) + }); + }); + weeklySummary.totalChannelMessagesInWeek = messagesInWeek.filter(message => message.room.t === 'c').length; + weeklySummary.totalPrivateGroupMessagesInWeek = messagesInWeek.filter(message => message.room.t === 'p').length; + weeklySummary.totalDirectMessagesInWeek = messagesInWeek.filter(message => message.room.t === 'd').length; + weeklySummary.totalLivechatMessagesInWeek = messagesInWeek.filter(message => message.room.t === 'l').length; + weeklySummary.totalFiles = messagesInWeek.filter(message => !!message.file).length; + + return weeklySummary; +}; diff --git a/packages/rocketchat-weekly-summary/server/functions/save.js b/packages/rocketchat-weekly-summary/server/functions/save.js new file mode 100644 index 000000000000..845d790abeb6 --- /dev/null +++ b/packages/rocketchat-weekly-summary/server/functions/save.js @@ -0,0 +1,6 @@ +RocketChat.weeklySummary.save = function() { + const weeklySummary = RocketChat.weeklySummary.get(); + weeklySummary.createdAt = new Date; + RocketChat.models.WeeklySummary.insert(weeklySummary); + return weeklySummary; +}; diff --git a/packages/rocketchat-weekly-summary/server/methods/getWeeklySummary.js b/packages/rocketchat-weekly-summary/server/methods/getWeeklySummary.js new file mode 100644 index 000000000000..a3a9f23fa17f --- /dev/null +++ b/packages/rocketchat-weekly-summary/server/methods/getWeeklySummary.js @@ -0,0 +1,17 @@ +Meteor.methods({ + getWeeklySummary(refresh) { + if (!Meteor.userId()) { + throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'getWeeklySummary' }); + } + + if (RocketChat.authz.hasPermission(Meteor.userId(), 'view-statistics') !== true) { + throw new Meteor.Error('error-not-allowed', 'Not allowed', { method: 'getWeeklySummary' }); + } + + if (refresh) { + return RocketChat.statistics.save(); + } else { + return RocketChat.models.WeeklySummary.findLast(); + } + } +}); diff --git a/packages/rocketchat-weekly-summary/server/models/WeeklySummary.js b/packages/rocketchat-weekly-summary/server/models/WeeklySummary.js new file mode 100644 index 000000000000..0b335ad456f2 --- /dev/null +++ b/packages/rocketchat-weekly-summary/server/models/WeeklySummary.js @@ -0,0 +1,24 @@ +RocketChat.models.WeeklySummary = new class extends RocketChat.models._Base { + constructor() { + super('weekly-summary'); + + this.tryEnsureIndex({ 'createdAt': 1 }); + } + + // FIND ONE + findOneById(_id, options) { + const query = { _id }; + return this.findOne(query, options); + } + + findLast() { + const options = { + sort: { + createdAt: -1 + }, + limit: 1 + }; + const records = this.find({}, options).fetch(); + return records && records[0]; + } +}; diff --git a/private/goalify/google-appscript-gola-registrations.js b/private/goalify/google-appscript-gola-registrations.js new file mode 100644 index 000000000000..29b950b7a665 --- /dev/null +++ b/private/goalify/google-appscript-gola-registrations.js @@ -0,0 +1,69 @@ +/*eslint-disable no-var, comma-dangle, guard-for-in, no-use-before-define, no-unused-vars*/ +/*global UrlFetchApp, onSubmit*/ +// Put your Gola webhook here, make sure its connected to the correct channel +var WEBHOOK_POST_URL = 'https://nau.goalify.chat/hooks/INTEGRATION_TOKEN'; + +// register form submit trigger for this function +function onSubmit(entry) { + // Get items submitted + var items = entry.response.getItemResponses(); + + // responses + var responses = []; + + var i; + for (i in items) { + //Logger.log("getItem().getTitle()=%s, getResponse()=%s", items[i].getItem().getTitle(), items[i].getResponse()); + responses.push({ + title: items[i].getItem().getTitle(), + response: items[i].getResponse(), + }); + } + + callWebhook(responses); +} + +// actually call the web hook +function callWebhook(responses) { + // sample responses (actual reponses array does not contain Email): + // responses = [ + // { title: 'Email address', response: 'thanh@naustud.io' }, + // { title: 'Company Name', response: 'Nau Studio' }, + // { title: 'Company Website', response: 'https://naustud.io' }, + // { title: 'Desired Subdomain', response: 'nau' }, + // { title: 'Admin User Full Name', response: 'Thanh Tran' }, + // { title: 'Admin Username', response: 'thanh' }, + // { title: 'Number of intended users', response: '20' }, + // ]; + + var payload = { + text: 'Yay! A new registration', + attachments: [ + { + color: '#5863e0', + title: 'Go to Registration spreadsheet', + title_link: + 'https://docs.google.com/spreadsheets/d/1s19hbazHudS34JYW-sNqFof-fm_bkQPWUKp26lFCCuQ/edit#gid=2049456746', + text: 'Here are the new registration details:', + fields: responses.map(function(field) { + return { + title: field.title, + value: field.response || 'N/A', + short: true, + }; + }), + }, + ], + }; + + // Build request + var options = { + method: 'post', + payload: { + payload: JSON.stringify(payload), + }, + }; + + // Send to Gola + UrlFetchApp.fetch(WEBHOOK_POST_URL, options); +} diff --git a/private/goalify/server-init.sh b/private/goalify/server-init.sh index 3866f60ece15..d87e33792732 100644 --- a/private/goalify/server-init.sh +++ b/private/goalify/server-init.sh @@ -10,15 +10,9 @@ while true; do esac done -while true; do - read -p "IMPORTANT: Have you export GITLAB_TOKEN and GITLAB_PASS env? (y|n)" yn - case $yn in - [Yy]* ) break;; - [Nn]* ) exit;; - * ) echo "Please answer (y)es or (n)o.";; - esac -done - +# Directly set goalify chat bot gitlab token here or export to ENV +GITLAB_TOKEN=$GITLAB_TOKEN_ENV +GITLAB_PASS=$GITLAB_PASS_ENV SUBDOMAIN=public SITE_NAME="Goalify Chat" ADMIN_USER=admin @@ -50,14 +44,11 @@ sudo npm install --global n # Install stable version of Node for Meteor & Goalify Chat sudo n 8.9.3 +# mongo replica set guide: https://rocket.chat/docs/installation/manual-installation/ubuntu/ # Enable replication for mongodb for better concurrency echo "replication:" | sudo tee -a /etc/mongod.conf echo " replSetName: \"rs0\"" | sudo tee -a /etc/mongod.conf -# TODO: enable mongo replica set (https://rocket.chat/docs/installation/manual-installation/ubuntu/) -# Still need to access mongo shell and execute: -# rs.initiate() - # Start mongod service sudo systemctl start mongod # Enable mongod service auto restart @@ -66,17 +57,12 @@ sudo systemctl enable mongod # Create app user sudo useradd goalifychat - -# RC_VERSION=".63.0-develop" -# OR -# RC_VERSION="latest" - -# Download built Rocket Chat server +# Download prebuilt Goalify Chat server # adapted from https://github.com/RocketChat/Rocket.Chat/blob/develop/.docker/Dockerfile set -x \ && curl -SLf "https://s3-ap-southeast-1.amazonaws.com/goalify.chat/downloads/beta/goalify-chat-server.tar.gz" -o goalify.chat.tgz \ && sudo mkdir -p /app \ - && sudo chown -R `whoami` /app + && sudo chown -R `whoami` /app \ && tar -zxf goalify.chat.tgz -C /app \ && rm goalify.chat.tgz \ && cd /app/bundle/programs/server \ @@ -120,9 +106,6 @@ EOF sudo cp goalifychat.service /etc/systemd/system/goalifychat.service rm goalifychat.service -# start rocketchat server and make it run as service (auto start) -sudo systemctl start goalifychat.service && sudo systemctl enable goalifychat.service - # Create Nginx reversed proxy config: cat > nginx-site.conf <${ moment(weeklySummary.startDate).format('dddd, MMMM Do') } - ${ moment(weeklySummary.endDate).format('dddd, MMMM Do') }

Hope you had a good weekend! Here's a summary of what happened in your workspace last week:

Your members sent a total of ${ weeklySummary.totalMessagesInWeek } ${ weeklySummary.totalMessagesInWeek === 1 ? 'message' : 'messages' } last week. Of those, ${ percentPublicChannel }% were in public channels, ${ percentPrivateChannel }% were in private channels, ${ percentDirectMessages }% were direct messages and ${ percentLivechatMessages }% were livechat messages. Your members also uploaded ${ weeklySummary.totalFiles } ${ weeklySummary.totalFiles === 1 ? 'file' : 'files' }.

Your workspace has ${ weeklySummary.admins.length } ${ weeklySummary.admins.length === 1 ? 'admin' : 'admins' }: ${ weeklySummary.admins.map(admin => admin.name).join(',') }. In total there are ${ weeklySummary.totalUsers } people in your workspace.

`; + const adminEmails = weeklySummary.admins.map(admin => { + let email = undefined; + if (admin.emails && admin.emails[0] && admin.emails[0].address) { + email = admin.emails[0].address; + } + return email; + }); + const emailTo = ['support@goalify.chat'].concat(adminEmails.filter(email => !!email)); + if (from) { + Email.send({ + to: emailTo.join(','), + from, + subject, + html: header + html + footer + }); + } else { + console.log('no From_Email'); + } +} + Meteor.startup(function() { return Meteor.defer(function() { generateStatistics(); + // generateWeeklySummary(); SyncedCron.add({ name: 'Generate and save statistics', @@ -51,6 +84,14 @@ Meteor.startup(function() { job: cleanupOEmbedCache }); + SyncedCron.add({ + name: 'Generate and save weekly summary', + schedule(parser) { + return parser.cron('0 8 * * MON'); + }, + job: generateWeeklySummary + }); + return SyncedCron.start(); }); }); diff --git a/tests/end-to-end/api/05-chat.js b/tests/end-to-end/api/05-chat.js index fa4f56e48b02..a4f56aec3fc1 100644 --- a/tests/end-to-end/api/05-chat.js +++ b/tests/end-to-end/api/05-chat.js @@ -5,15 +5,10 @@ import { getCredentials, api, - login, request, credentials, - message, - log, - apiPrivateChannelName + message } from '../../data/api-data.js'; -import { adminEmail, password } from '../../data/user.js'; -import supertest from 'supertest'; describe('[Chat]', function() { this.retries(0); @@ -49,7 +44,7 @@ describe('[Chat]', function() { alias: 'Gruggy', emoji: ':smirk:', avatar: 'http://res.guggy.com/logo_128.png', - attachments: [{ + attachments: [ { color: '#ff0000', text: 'Yay for gruggy!', ts: '2016-12-09T16:53:06.761Z', @@ -66,7 +61,7 @@ describe('[Chat]', function() { audio_url: 'http://www.w3schools.com/tags/horse.mp3', video_url: 'http://www.w3schools.com/tags/movie.mp4', fields: '' - }] + } ] }) .expect('Content-Type', 'application/json') .expect(400) @@ -86,7 +81,7 @@ describe('[Chat]', function() { alias: 'Gruggy', emoji: ':smirk:', avatar: 'http://res.guggy.com/logo_128.png', - attachments: [{ + attachments: [ { color: '#ff0000', text: 'Yay for gruggy!', ts: '2016-12-09T16:53:06.761Z', @@ -102,12 +97,12 @@ describe('[Chat]', function() { image_url: 'http://res.guggy.com/logo_128.png', audio_url: 'http://www.w3schools.com/tags/horse.mp3', video_url: 'http://www.w3schools.com/tags/movie.mp4', - fields: [{ + fields: [ { short: true, title: 12, value: false - }] - }] + } ] + } ] }) .expect('Content-Type', 'application/json') .expect(400) @@ -127,7 +122,7 @@ describe('[Chat]', function() { alias: 'Gruggy', emoji: ':smirk:', avatar: 'http://res.guggy.com/logo_128.png', - attachments: [{ + attachments: [ { color: '#ff0000', text: 'Yay for gruggy!', ts: '2016-12-09T16:53:06.761Z', @@ -143,7 +138,7 @@ describe('[Chat]', function() { image_url: 'http://res.guggy.com/logo_128.png', audio_url: 'http://www.w3schools.com/tags/horse.mp3', video_url: 'http://www.w3schools.com/tags/movie.mp4', - fields: [{ + fields: [ { short: true, title: 'Test', value: 'Testing out something or other' @@ -151,8 +146,8 @@ describe('[Chat]', function() { short: true, title: 'Another Test', value: '[Link](https://google.com/) something and this and that.' - }] - }] + } ] + } ] }) .expect('Content-Type', 'application/json') .expect(200) @@ -163,6 +158,7 @@ describe('[Chat]', function() { }) .end(done); }); + }); describe('/chat.getMessage', () => { @@ -214,7 +210,7 @@ describe('[Chat]', function() { alias: 'Gruggy', emoji: ':smirk:', avatar: 'http://res.guggy.com/logo_128.png', - attachments: [{ + attachments: [ { color: '#ff0000', text: 'Yay for gruggy!', ts: '2016-12-09T16:53:06.761Z', @@ -231,7 +227,7 @@ describe('[Chat]', function() { audio_url: 'http://www.w3schools.com/tags/horse.mp3', video_url: 'http://www.w3schools.com/tags/movie.mp4', fields: '' - }] + } ] } }) .expect('Content-Type', 'application/json') @@ -255,7 +251,7 @@ describe('[Chat]', function() { alias: 'Gruggy', emoji: ':smirk:', avatar: 'http://res.guggy.com/logo_128.png', - attachments: [{ + attachments: [ { color: '#ff0000', text: 'Yay for gruggy!', ts: '2016-12-09T16:53:06.761Z', @@ -271,7 +267,7 @@ describe('[Chat]', function() { image_url: 'http://res.guggy.com/logo_128.png', audio_url: 'http://www.w3schools.com/tags/horse.mp3', video_url: 'http://www.w3schools.com/tags/movie.mp4', - fields: [{ + fields: [ { short: true, title: 'Test', value: 'Testing out something or other' @@ -279,8 +275,8 @@ describe('[Chat]', function() { short: true, title: 'Another Test', value: '[Link](https://google.com/) something and this and that.' - }] - }] + } ] + } ] } }) .expect('Content-Type', 'application/json') @@ -291,6 +287,44 @@ describe('[Chat]', function() { }) .end(done); }); + + describe('Read only channel', () => { + let readOnlyChannel; + + it('Creating a read-only channel', (done) => { + request.post(api('channels.create')) + .set(credentials) + .send({ + name: `readonlychannel${ +new Date() }`, + readOnly: true + }) + .expect('Content-Type', 'application/json') + .expect(200) + .expect((res) => { + expect(res.body).to.have.property('success', true); + readOnlyChannel = res.body.channel; + }) + .end(done); + }); + it('should send a message when the user is the owner of a readonly channel', (done) => { + request.post(api('chat.sendMessage')) + .set(credentials) + .send({ + message: { + rid: readOnlyChannel._id, + msg: 'Sample message' + } + }) + .expect('Content-Type', 'application/json') + .expect(200) + .expect((res) => { + expect(res.body).to.have.property('success', true); + expect(res.body).to.have.property('message').and.to.be.an('object'); + }) + .end(done); + }); + }); + }); describe('/chat.update', () => { diff --git a/tests/end-to-end/ui/04-main-elements-render.js b/tests/end-to-end/ui/04-main-elements-render.js index 9524e43e6b14..eeec85bcec32 100644 --- a/tests/end-to-end/ui/04-main-elements-render.js +++ b/tests/end-to-end/ui/04-main-elements-render.js @@ -137,7 +137,7 @@ describe('[Main Elements Render]', function() { mainContent.favoriteStar.isVisible().should.be.true; }); - it('it should click the star', () => { + it.skip('it should click the star', () => { mainContent.favoriteStar.click(); });