From 013b3516ad3104e29a7c06173bd372041cf461ad Mon Sep 17 00:00:00 2001 From: Diego Sampaio Date: Tue, 3 Jul 2018 09:02:04 -0300 Subject: [PATCH 1/7] [FIX] Notification preferences being lost when switching view mode (#11295) --- package-lock.json | 65 ++++++++++++++++++--------- server/methods/saveUserPreferences.js | 6 +-- server/startup/migrations/v129.js | 60 +++++++++++++++++++++++++ 3 files changed, 106 insertions(+), 25 deletions(-) create mode 100644 server/startup/migrations/v129.js diff --git a/package-lock.json b/package-lock.json index e696dd348d37..1587fdbdda34 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "Rocket.Chat", - "version": "0.66.0-develop", + "version": "0.67.0-develop", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -742,7 +742,7 @@ "autolinker": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/autolinker/-/autolinker-1.6.2.tgz", - "integrity": "sha1-Z66donLoCODY644Cy8jN4wOUdFc=" + "integrity": "sha512-IKLGtYFb3jzGTtgCpb4bm//1sXmmmgmr0msKshhYoc7EsWmLCFvuyxLcEIfcZ5gbCgZGXrnXkOkcBblOFEnlog==" }, "autoprefixer": { "version": "8.6.0", @@ -2957,7 +2957,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -3002,7 +3002,7 @@ "mocha": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/mocha/-/mocha-4.1.0.tgz", - "integrity": "sha1-fYbPvPNcuCnidUwy4XNV7AUzh5Q=", + "integrity": "sha512-0RVnjg1HJsXY2YFDoTNzcc1NKhYuXKRrBAG2gDygmJJA136Cs2QlRliZG1mA0ap7cuaT30mw16luAeln+4RiNA==", "dev": true, "requires": { "browser-stdout": "1.3.0", @@ -3020,13 +3020,13 @@ "commander": { "version": "2.11.0", "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", - "integrity": "sha1-FXFS/R56bI2YpbcVzzdt+SgARWM=", + "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==", "dev": true }, "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "dev": true, "requires": { "fs.realpath": "1.0.0", @@ -3054,7 +3054,7 @@ "supports-color": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", - "integrity": "sha1-iD992rwWUUKyphQn8zUt7RldGj4=", + "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", "dev": true, "requires": { "has-flag": "2.0.0" @@ -4024,6 +4024,14 @@ "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", "dev": true }, + "dbly-linked-list": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dbly-linked-list/-/dbly-linked-list-0.2.0.tgz", + "integrity": "sha512-Ool7y15f6JRDs0YKx7Dh9uiTb1jS1SZLNdT3Y2q16DlaEghXbMsmODS/XittjR2xztt1gJUpz7jVxpqAPF8VGg==", + "requires": { + "lodash.isequal": "4.5.0" + } + }, "ddp-ejson": { "version": "0.8.1-3", "resolved": "https://registry.npmjs.org/ddp-ejson/-/ddp-ejson-0.8.1-3.tgz", @@ -6218,7 +6226,7 @@ "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "requires": { "fs.realpath": "1.0.0", "inflight": "1.0.6", @@ -8178,7 +8186,7 @@ "is-resolvable": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", - "integrity": "sha1-+xj4fOH+uSUWnJpAfBkxijIG7Yg=", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", "dev": true }, "is-retry-allowed": { @@ -8753,6 +8761,11 @@ "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" }, + "lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" + }, "lodash.isinteger": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", @@ -8776,7 +8789,7 @@ "lodash.merge": { "version": "4.6.1", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.1.tgz", - "integrity": "sha1-rcJdnLmbk5HFliTzefu6YNcRHVQ=" + "integrity": "sha512-AOYza4+Hf5z1/0Hztxpm2/xiPZgi/cjMqdnKTUWTBSKchJlxXXuUSxCCl8rJlf4g6yww/j6mA8nC8Hw/EZWxKQ==" }, "lodash.once": { "version": "4.1.1", @@ -8944,7 +8957,7 @@ "mailsplit": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/mailsplit/-/mailsplit-4.1.2.tgz", - "integrity": "sha1-xhi8MRpM/IOyJqHtwbUD9akk0IM=", + "integrity": "sha512-5UWjUfhKlC4OR5PqZKcl4h7vnz2EP4M3Zg2SBbrztvAYX5lM/rA7tvaXkZ6zRcvK32Uul0GkRA037icDbiJIOw==", "requires": { "libbase64": "1.0.2", "libmime": "3.1.0", @@ -8954,7 +8967,7 @@ "libbase64": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/libbase64/-/libbase64-1.0.2.tgz", - "integrity": "sha1-L/E//mmx5AFZ9JNo4w0N2LsWNbU=" + "integrity": "sha512-CyPjvTFbsGps2Sdvy9GVjSRPvUGpji8Hxb+iunp466guzxcd3QaK0k8Hur1sPkgD9FonW8V1z2F1y066YiliEg==" } } }, @@ -9195,7 +9208,7 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "requires": { "brace-expansion": "1.1.11" } @@ -9601,7 +9614,7 @@ "npmlog": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", - "integrity": "sha1-CKfyqL9zRgR3mp76StXMcXq7lUs=", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", "requires": { "are-we-there-yet": "1.1.5", "console-control-strings": "1.1.0", @@ -10006,7 +10019,7 @@ "path-type": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha1-zvMdyOCho7sNEFwM2Xzzv0f0428=", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", "requires": { "pify": "3.0.0" } @@ -10338,7 +10351,7 @@ "postcss-import": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-11.1.0.tgz", - "integrity": "sha1-Vck2LJGSmU7GiGXSJEGd8dspgfA=", + "integrity": "sha512-5l327iI75POonjxkXgdRCUS+AlzAdBx4pOvMEhTKTCjb1p8IEeVR9yx3cPbmN7LIWJLbfnIXxAhoB4jpD0c/Cw==", "dev": true, "requires": { "postcss": "6.0.22", @@ -10387,7 +10400,7 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true }, "supports-color": { @@ -11275,6 +11288,14 @@ "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-1.0.0.tgz", "integrity": "sha1-YoYkIRLFtxL6ZU5SZlK/ahP/Bcs=" }, + "queue-fifo": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/queue-fifo/-/queue-fifo-0.2.5.tgz", + "integrity": "sha512-GrHy3RDy0BOEVjelr+htts/QJyZAJr+7m4TisCA+RlUSsegQT6EGOf+NyxLDhSRflFI5vq3aADFOR/tNZCasxg==", + "requires": { + "dbly-linked-list": "0.2.0" + } + }, "quick-lru": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-1.1.0.tgz", @@ -11814,7 +11835,7 @@ "retry-request": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/retry-request/-/retry-request-3.3.1.tgz", - "integrity": "sha1-+3EnYjWmF+l1Uem+c3q1uRWR+54=", + "integrity": "sha512-PjAmtWIxjNj4Co/6FRtBl8afRP3CxrrIAnUzb1dzydfROd+6xt7xAebFeskgQgkfFf8NmzrXIoaB3HxmswXyxw==", "requires": { "request": "2.87.0", "through2": "2.0.3" @@ -13014,7 +13035,7 @@ "stylelint-order": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/stylelint-order/-/stylelint-order-0.8.1.tgz", - "integrity": "sha1-Nfca86FZVBVODpnlZGuj1vvjT40=", + "integrity": "sha512-8mp1P2wnI9XShYXVXDsxVigE2eXnc0C2O4ktbwUvTBwjCP4xZskIbUVxp1evSG3OK4R7hXVNl/2BnJCZkrcc/w==", "dev": true, "requires": { "lodash": "4.17.10", @@ -13062,7 +13083,7 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true }, "supports-color": { @@ -13632,7 +13653,7 @@ "uc.micro": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.5.tgz", - "integrity": "sha1-DGXxX4FaoItWCmHOi023/8P0U3Y=" + "integrity": "sha512-JoLI4g5zv5qNyT09f4YAvEZIIV1oOjqnewYg5D38dkQljIzpPT296dbIGvKro3digYI1bkb7W6EP1y4uDlmzLg==" }, "uglify-js": { "version": "2.8.29", @@ -14429,7 +14450,7 @@ "xml2js": { "version": "0.4.19", "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", - "integrity": "sha1-aGwg8hMgnpSr8NG88e+qKRx4J6c=", + "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", "requires": { "sax": "1.2.1", "xmlbuilder": "9.0.7" diff --git a/server/methods/saveUserPreferences.js b/server/methods/saveUserPreferences.js index f0516a11cf9f..b13ecc3d41bc 100644 --- a/server/methods/saveUserPreferences.js +++ b/server/methods/saveUserPreferences.js @@ -69,7 +69,7 @@ Meteor.methods({ // propagate changed notification preferences Meteor.defer(() => { - if (oldDesktopNotifications !== settings.desktopNotifications) { + if (settings.desktopNotifications && oldDesktopNotifications !== settings.desktopNotifications) { if (settings.desktopNotifications === 'default') { RocketChat.models.Subscriptions.clearDesktopNotificationUserPreferences(user._id); } else { @@ -77,7 +77,7 @@ Meteor.methods({ } } - if (oldMobileNotifications !== settings.mobileNotifications) { + if (settings.mobileNotifications && oldMobileNotifications !== settings.mobileNotifications) { if (settings.mobileNotifications === 'default') { RocketChat.models.Subscriptions.clearMobileNotificationUserPreferences(user._id); } else { @@ -85,7 +85,7 @@ Meteor.methods({ } } - if (oldEmailNotifications !== settings.emailNotificationMode) { + if (settings.emailNotificationMode && oldEmailNotifications !== settings.emailNotificationMode) { if (settings.emailNotificationMode === 'default') { RocketChat.models.Subscriptions.clearEmailNotificationUserPreferences(user._id); } else { diff --git a/server/startup/migrations/v129.js b/server/startup/migrations/v129.js new file mode 100644 index 000000000000..17a92c8a7ceb --- /dev/null +++ b/server/startup/migrations/v129.js @@ -0,0 +1,60 @@ +RocketChat.Migrations.add({ + version: 129, + up() { + RocketChat.models.Users.find({ + $or: [ + { 'settings.preferences.desktopNotifications': { $exists: true, $ne: 'default' } }, + { 'settings.preferences.mobileNotifications': { $exists: true, $ne: 'default' } }, + { 'settings.preferences.emailNotificationMode': { $exists: true, $ne: 'default' } } + ] + }, { + fields: { + 'settings.preferences.desktopNotifications': 1, + 'settings.preferences.mobileNotifications': 1, + 'settings.preferences.emailNotificationMode': 1 + } + }).forEach(user => { + if (user.settings.preferences.desktopNotifications && user.settings.preferences.desktopNotifications !== 'default') { + RocketChat.models.Subscriptions.update({ + 'u._id': user._id, + desktopPrefOrigin: 'user', + desktopNotifications: null + }, { + $set: { + desktopNotifications: user.settings.preferences.desktopNotifications + } + }, { + multi: true + }); + } + + if (user.settings.preferences.mobileNotifications && user.settings.preferences.mobileNotifications !== 'default') { + RocketChat.models.Subscriptions.update({ + 'u._id': user._id, + mobilePrefOrigin: 'user', + mobilePushNotifications: null + }, { + $set: { + mobilePushNotifications: user.settings.preferences.mobileNotifications + } + }, { + multi: true + }); + } + + if (user.settings.preferences.emailNotificationMode && user.settings.preferences.emailNotificationMode !== 'default') { + RocketChat.models.Subscriptions.update({ + 'u._id': user._id, + emailPrefOrigin: 'user', + emailNotifications: null + }, { + $set: { + emailNotifications: user.settings.preferences.emailNotificationMode === 'disabled' || user.settings.preferences.emailNotificationMode === 'nothing' ? 'nothing' : 'mentions' + } + }, { + multi: true + }); + } + }); + } +}); From a0da53ba5728694b346779ed6fac55eadcbc1428 Mon Sep 17 00:00:00 2001 From: Gabriel Delavald Date: Tue, 3 Jul 2018 09:03:09 -0300 Subject: [PATCH 2/7] [FIX] Livestream muted when audio only option was enabled (#11267) --- .../client/views/liveStreamView.html | 10 ---------- .../client/imports/components/popout.css | 2 +- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/packages/rocketchat-livestream/client/views/liveStreamView.html b/packages/rocketchat-livestream/client/views/liveStreamView.html index 43bec7b18288..765b2b52bcf7 100644 --- a/packages/rocketchat-livestream/client/views/liveStreamView.html +++ b/packages/rocketchat-livestream/client/views/liveStreamView.html @@ -1,15 +1,5 @@ diff --git a/packages/rocketchat-theme/client/imports/components/popout.css b/packages/rocketchat-theme/client/imports/components/popout.css index 96ba48dec29d..8b774f08bc5f 100644 --- a/packages/rocketchat-theme/client/imports/components/popout.css +++ b/packages/rocketchat-theme/client/imports/components/popout.css @@ -180,7 +180,7 @@ &.rc-popout__content { height: 0px; - visibility: hidden; + overflow: hidden; & .streaming-object { visibility: 'hidden'; From afa2d434ea146cae208565ce2962f751105b9a90 Mon Sep 17 00:00:00 2001 From: Tasso Evangelista Date: Tue, 3 Jul 2018 17:39:29 -0300 Subject: [PATCH 3/7] [IMPROVE] Setup Wizard username validation, step progress and optin/optout (#11254) Closes #11198 - [x] Show all steps on info box - [x] Properly display errors in registration process of admin user - [x] Break steps in subtemplates - [x] Redesign "Register Server" step ![Register Server](https://user-images.githubusercontent.com/2263066/42013253-cd691bc2-7a72-11e8-8832-fe9ccd9e89b4.png) - [x] Update end-to-end tests --- packages/rocketchat-i18n/i18n/en.i18n.json | 14 + .../rocketchat-lib/server/startup/settings.js | 3 + .../rocketchat-setup-wizard/client/final.html | 18 + .../rocketchat-setup-wizard/client/final.js | 51 ++ .../client/setupWizard.html | 360 +++++++------ .../client/setupWizard.js | 509 ++++++++++-------- packages/rocketchat-setup-wizard/package.js | 4 +- .../server/getSetupWizardParameters.js | 18 + .../server/lib/getWizardSettings.js | 9 - .../imports/components/setup-wizard.css | 143 ++++- tests/end-to-end/ui/00-login.js | 18 + tests/pageobjects/setup-wizard.page.js | 2 + 12 files changed, 713 insertions(+), 436 deletions(-) create mode 100644 packages/rocketchat-setup-wizard/client/final.html create mode 100644 packages/rocketchat-setup-wizard/client/final.js create mode 100644 packages/rocketchat-setup-wizard/server/getSetupWizardParameters.js delete mode 100644 packages/rocketchat-setup-wizard/server/lib/getWizardSettings.js diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index 4c8582bfa328..96b4e6c56eee 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -234,6 +234,7 @@ "Allow_Invalid_SelfSigned_Certs": "Allow Invalid Self-Signed Certs", "Allow_Invalid_SelfSigned_Certs_Description": "Allow invalid and self-signed SSL certificate's for link validation and previews.", "Allow_switching_departments": "Allow Visitor to Switch Departments", + "Allow_Marketing_Emails": "Allow Marketing Emails", "Alphabetical": "Alphabetical", "Always_open_in_new_window": "Always Open in New Window", "Analytics_features_enabled": "Features Enabled", @@ -1370,6 +1371,7 @@ "InternalHubot_Username_Description": "This must be a valid username of a bot registered on your server.", "Invalid_confirm_pass": "The password confirmation does not match password", "Invalid_email": "The email entered is invalid", + "Invalid_username": "The username entered is invalid", "Invalid_Export_File": "The file uploaded isn't a valid %s export file.", "Invalid_Import_File_Type": "Invalid Import file type.", "Invalid_name": "The name must not be empty", @@ -2035,6 +2037,17 @@ "Regenerate_codes": "Regenerate codes", "Register": "Register a new account", "Register_Server": "Register Server", + "Register_Server_Info": "Use the preconfigured gateways and proxies provided by Rocket.Chat Technologies Corp.", + "Register_Server_Registered": "Register to access", + "Register_Server_Registered_Push_Notifications": "Mobile push notifications gateway", + "Register_Server_Registered_Livechat": "Livechat omnichannel proxy", + "Register_Server_Registered_OAuth": "OAuth proxy for social network", + "Register_Server_Registered_Marketplace": "Apps Marketplace", + "Register_Server_Opt_In": "Newsletter, offers and product updates", + "Register_Server_Standalone": "Keep standalone, you'll need to", + "Register_Server_Standalone_Service_Providers": "Create accounts with service providers", + "Register_Server_Standalone_Update_Settings": "Update the preconfigured settings", + "Register_Server_Standalone_Own_Certificates": "Recompile the mobile apps with your own certificates", "Registration": "Registration", "Registration_Succeeded": "Registration Succeeded", "Registration_via_Admin": "Registration via Admin", @@ -2215,6 +2228,7 @@ "Shared_Location": "Shared Location", "Should_be_a_URL_of_an_image": "Should be a URL of an image.", "Should_exists_a_user_with_this_username": "The user must already exist.", + "Show_Setup_Wizard": "Show Setup Wizard", "Show_agent_email": "Show agent email", "Show_all": "Show All", "Show_Avatars": "Show Avatars", diff --git a/packages/rocketchat-lib/server/startup/settings.js b/packages/rocketchat-lib/server/startup/settings.js index 4d8a0e329f3f..cd870f383ef4 100644 --- a/packages/rocketchat-lib/server/startup/settings.js +++ b/packages/rocketchat-lib/server/startup/settings.js @@ -2902,6 +2902,9 @@ RocketChat.settings.addGroup('Setup_Wizard', function() { order: 2 } }); + this.add('Allow_Marketing_Emails', true, { + type: 'boolean' + }); }); }); diff --git a/packages/rocketchat-setup-wizard/client/final.html b/packages/rocketchat-setup-wizard/client/final.html new file mode 100644 index 000000000000..f44289e9b1c5 --- /dev/null +++ b/packages/rocketchat-setup-wizard/client/final.html @@ -0,0 +1,18 @@ + diff --git a/packages/rocketchat-setup-wizard/client/final.js b/packages/rocketchat-setup-wizard/client/final.js new file mode 100644 index 000000000000..3fea0f68212c --- /dev/null +++ b/packages/rocketchat-setup-wizard/client/final.js @@ -0,0 +1,51 @@ +Template.setupWizardFinal.onCreated(function() { + const isSetupWizardDone = localStorage.getItem('wizardFinal'); + if (isSetupWizardDone === null) { + FlowRouter.go('setup-wizard'); + } + + this.autorun(c => { + const showSetupWizard = RocketChat.settings.get('Show_Setup_Wizard'); + if (!showSetupWizard) { + // Setup Wizard state is not defined yet + return; + } + + const userId = Meteor.userId(); + const user = userId && RocketChat.models.Users.findOne(userId, { fields: { status: true } }); + if (userId && (!user || !user.status)) { + // User and its status are not defined yet + return; + } + + c.stop(); + + const isComplete = showSetupWizard === 'completed'; + const noUserLoggedInAndIsNotPending = !userId && showSetupWizard !== 'pending'; + const userIsLoggedButIsNotAdmin = userId && !RocketChat.authz.hasRole(userId, 'admin'); + if (isComplete || noUserLoggedInAndIsNotPending || userIsLoggedButIsNotAdmin) { + FlowRouter.go('home'); + return; + } + }); +}); + +Template.setupWizardFinal.onRendered(function() { + $('#initial-page-loading').remove(); +}); + +Template.setupWizardFinal.events({ + 'click .js-finish'() { + RocketChat.settings.set('Show_Setup_Wizard', 'completed', function() { + localStorage.removeItem('wizard'); + localStorage.removeItem('wizardFinal'); + FlowRouter.go('home'); + }); + } +}); + +Template.setupWizardFinal.helpers({ + siteUrl() { + return RocketChat.settings.get('Site_Url'); + } +}); diff --git a/packages/rocketchat-setup-wizard/client/setupWizard.html b/packages/rocketchat-setup-wizard/client/setupWizard.html index 6f082939f37c..26a4613d4f3b 100644 --- a/packages/rocketchat-setup-wizard/client/setupWizard.html +++ b/packages/rocketchat-setup-wizard/client/setupWizard.html @@ -1,196 +1,214 @@ - - + + + + + + + + diff --git a/packages/rocketchat-setup-wizard/client/setupWizard.js b/packages/rocketchat-setup-wizard/client/setupWizard.js index 445cb3b504c9..715ea2e83518 100644 --- a/packages/rocketchat-setup-wizard/client/setupWizard.js +++ b/packages/rocketchat-setup-wizard/client/setupWizard.js @@ -1,90 +1,135 @@ -import s from 'underscore.string'; +const cannotSetup = () => { + const showSetupWizard = RocketChat.settings.get('Show_Setup_Wizard'); + if (!showSetupWizard) { + // Setup Wizard state is not defined yet + return; + } -const setSettingsAndGo = (settings, registerServer = true) => { - const settingsFilter = Object.entries(settings) - .filter(([key]) => !/registration-|registerServer|currentStep/.test(key)) - .map(([_id, value]) => ({_id, value})); + const userId = Meteor.userId(); + const user = userId && RocketChat.models.Users.findOne(userId, { fields: { status: true } }); + if (userId && (!user || !user.status)) { + // User and its status are not defined yet + return; + } - settingsFilter.push({ - _id: 'Statistics_reporting', - value: registerServer - }); + const isComplete = showSetupWizard === 'completed'; + const noUserLoggedInAndIsNotPending = !userId && showSetupWizard !== 'pending'; + const userIsLoggedButIsNotAdmin = userId && !RocketChat.authz.hasRole(userId, 'admin'); - RocketChat.settings.batchSet(settingsFilter, function(err) { - if (err) { - return handleError(err); + return isComplete || noUserLoggedInAndIsNotPending || userIsLoggedButIsNotAdmin; +}; + +const registerAdminUser = (state, callback) => { + const registrationData = Object.entries(state) + .filter(([ key ]) => /registration-/.test(key)) + .map(([ key, value ]) => ([ key.replace('registration-', ''), value ])) + .reduce((o, [ key, value ]) => ({ ...o, [key]: value }), {}); + + Meteor.call('registerUser', registrationData, error => { + if (error) { + return handleError(error); } - localStorage.setItem('wizardFinal', true); - FlowRouter.go('setup-wizard-final'); + RocketChat.callbacks.run('userRegistered'); + Meteor.loginWithPassword(registrationData.email, registrationData.pass, error => { + if (error) { + if (error.error === 'error-invalid-email') { + toastr.success(t('We_have_sent_registration_email')); + return false; + } else { + return handleError(error); + } + } + + Session.set('forceLogin', false); + Meteor.call('setUsername', registrationData.username, error => { + if (error) { + return handleError(error); + } + + RocketChat.callbacks.run('usernameSet'); + callback && callback(); + }); + }); }); }; -Template.setupWizard.onCreated(function() { - const userId = Meteor.userId(); - - this.autorun((c) => { - const Show_Setup_Wizard = RocketChat.settings.get('Show_Setup_Wizard'); - const user = Meteor.user(); +const persistSettings = (state, callback) => { + const settings = Object.entries(state) + .filter(([ key ]) => !/registration-|registerServer|optIn|currentStep|invalidUsername|invalidEmail/.test(key)) + .map(([ _id, value ]) => ({ _id, value })) + .concat([ + { + _id: 'Statistics_reporting', + value: state['registerServer'] + }, + { + _id: 'Allow_Marketing_Emails', + value: state['optIn'] + } + ]); - // Wait for roles and setup wizard setting - if ((userId && (!user || !user.status)) || !Show_Setup_Wizard) { - return; + RocketChat.settings.batchSet(settings, error => { + if (error) { + return handleError(error); } - c.stop(); - - if ((!userId && Show_Setup_Wizard !== 'pending') || Show_Setup_Wizard === 'completed' || (userId && !RocketChat.authz.hasRole(userId, 'admin'))) { - FlowRouter.go('home'); - } + callback && callback(); }); +}; + +Template.setupWizard.onCreated(function() { + this.state = new ReactiveDict(); + this.state.set('currentStep', 1); + this.state.set('registerServer', true); + this.state.set('optIn', true); + + this.wizardSettings = new ReactiveVar([]); + this.allowStandaloneServer = new ReactiveVar(false); if (localStorage.getItem('wizardFinal')) { FlowRouter.go('setup-wizard-final'); + return; } - this.hasAdmin = new ReactiveVar(false); - this.state = new ReactiveDict(); - this.wizardSettings = new ReactiveVar([]); - this.invalidEmail = new ReactiveVar(false); + const jsonString = localStorage.getItem('wizard'); + const state = jsonString && JSON.parse(jsonString) || {}; + Object.entries(state).forEach(entry => this.state.set(...entry)); - const storage = JSON.parse(localStorage.getItem('wizard')); - if (storage) { - Object.entries(storage).forEach(([key, value]) => { - this.state.set(key, value); - }); - } + this.autorun(c => { + const cantSetup = cannotSetup(); + if (typeof cantSetup === 'undefined') { + return; + } - this.autorun(() => { - const user = Meteor.user(); - if (user) { - if (!this.hasAdmin.get()) { - if (user.roles && user.roles.includes('admin')) { - this.state.set('currentStep', 2); - this.hasAdmin.set(true); - } else { - this.hasAdmin.set(false); - } - } + if (cantSetup) { + c.stop(); + FlowRouter.go('home'); + return; + } + + const state = this.state.all(); + state['registration-pass'] = ''; + localStorage.setItem('wizard', JSON.stringify(state)); - Meteor.call('getWizardSettings', (error, result) => { + if (Meteor.userId()) { + Meteor.call('getSetupWizardParameters', (error, { settings, allowStandaloneServer }) => { if (error) { return handleError(error); } - this.wizardSettings.set(result); + this.wizardSettings.set(settings); + this.allowStandaloneServer.set(allowStandaloneServer); }); - } else { - this.state.set('currentStep', 1); - } - if (RocketChat.settings.get('Show_Setup_Wizard') === 'completed') { - FlowRouter.go('home'); + if (this.state.get('currentStep') === 1) { + this.state.set('currentStep', 2); + } else { + this.state.set('registration-pass', ''); + } + } else if (this.state.get('currentStep') !== 1) { + this.state.set('currentStep', 1); } - - const states = this.state.all(); - states['registration-pass'] = ''; - localStorage.setItem('wizard', JSON.stringify(states)); }); }); @@ -93,67 +138,83 @@ Template.setupWizard.onRendered(function() { }); Template.setupWizard.events({ + 'submit .setup-wizard-forms__box'() { + return false; + }, 'click .setup-wizard-forms__footer-next'(e, t) { - const currentStep = t.state.get('currentStep'); - const hasAdmin = t.hasAdmin.get(); - - if (!hasAdmin && currentStep === 1) { - const emailValue = t.state.get('registration-email'); - const invalidEmail = !/\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]+\b/i.test(emailValue); - t.invalidEmail.set(invalidEmail); + switch (t.state.get('currentStep')) { + case 1: { + const usernameValue = t.state.get('registration-username'); + const usernameRegex = new RegExp(`^${ RocketChat.settings.get('UTF8_Names_Validation') }$`); + t.state.set('invalidUsername', !usernameRegex.test(usernameValue)); + + const emailValue = t.state.get('registration-email'); + const emailRegex = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]+$/i; + t.state.set('invalidEmail', !emailRegex.test(emailValue)); + + if (t.state.get('invalidUsername') || t.state.get('invalidEmail')) { + return false; + } - if (invalidEmail) { + registerAdminUser(t.state.all(), () => t.state.set('currentStep', 2)); return false; } - - const state = t.state.all(); - const registration = Object.entries(state).filter(([key]) => /registration-/.test(key)); - const registrationData = Object.assign(...registration.map(d => ({[d[0].replace('registration-', '')]: d[1]}))); - - Meteor.call('registerUser', registrationData, error => { - if (error) { - return handleError(error); - } - - RocketChat.callbacks.run('userRegistered'); - - Meteor.loginWithPassword(s.trim(registrationData.email), registrationData.pass, error => { - if (error && error.error === 'error-invalid-email') { - toastr.success(t('We_have_sent_registration_email')); - return false; - } - - Session.set('forceLogin', false); - - Meteor.call('setUsername', registrationData.username, error => { - if (error) { - return handleError(error); - } - - RocketChat.callbacks.run('usernameSet'); - }); + case 2: { + t.state.set('currentStep', 3); + return false; + } + case 3: { + t.state.set('currentStep', 4); + return false; + } + case 4: { + persistSettings(t.state.all(), () => { + localStorage.removeItem('wizard'); + localStorage.setItem('wizardFinal', true); + FlowRouter.go('setup-wizard-final'); }); - }); + return false; + } } - if (hasAdmin && currentStep === 3) { - setSettingsAndGo(t.state.all()); - return false; + return false; + }, + 'click .setup-wizard-forms__footer-back'(e, t) { + switch (t.state.get('currentStep')) { + case 2: + t.state.set('currentStep', 1); + break; + case 3: + t.state.set('currentStep', 2); + break; + case 4: + t.state.set('currentStep', 3); + break; } - if (currentStep === 4) { - setSettingsAndGo(t.state.all(), JSON.parse(t.state.get('registerServer') || true)); + return false; + }, + 'input .js-setting-data'({ currentTarget: { name, value } }, t) { + t.state.set(name, value); + }, + 'click input[name="registerServer"]'({ currentTarget: { value } }, t) { + const oldValue = t.state.get('registerServer'); + const newValue = value === 'true'; + t.state.set('registerServer', newValue); - return false; + if (!oldValue && newValue) { + t.state.set('optIn', true); } - t.state.set('currentStep', currentStep + 1); - }, - 'click .setup-wizard-forms__footer-back'(e, t) { - t.state.set('currentStep', t.state.get('currentStep') - 1); + if (!newValue) { + t.state.set('optIn', false); + } + + return false; }, - 'input .js-setting-data'(e, t) { - t.state.set(e.currentTarget.name, e.currentTarget.value); + 'click input[name="optIn"]'({ currentTarget: { checked } }, t) { + t.state.set('optIn', checked); + return false; } }); @@ -161,144 +222,138 @@ Template.setupWizard.helpers({ currentStep() { return Template.instance().state.get('currentStep'); }, - itemModifier(step) { - const current = Template.instance().state.get('currentStep'); - - if (current === step) { - return 'setup-wizard-info__steps-item--active'; - } - - if (current > step) { - return 'setup-wizard-info__steps-item--past'; + currentStepTitle() { + switch (Template.instance().state.get('currentStep')) { + case 1: + return 'Admin_Info'; + case 2: + return 'Organization_Info'; + case 3: + return 'Server_Info'; + case 4: + return 'Register_Server'; } - - return ''; - }, - getValue(name) { - return Template.instance().state.get(name); - }, - selectedValue(setting, optionValue) { - return Template.instance().state.get(setting) === optionValue; }, - isDisabled() { - const user = Meteor.user(); - if (user && user.roles && !user.roles.includes('admin')) { - return 'disabled'; - } - - if (Template.instance().state.get('currentStep') === 1) { - const state = Template.instance().state.all(); - - if (Object.entries(state).filter(([key, value]) => /registration-/.test(key) && !value).length) { - return 'disabled'; - } + formLoadStateClass() { + switch (Template.instance().state.get('currentStep')) { + case 1: + return RocketChat.settings.get('Show_Setup_Wizard') === 'pending' && 'setup-wizard-forms__box--loaded'; + case 2: + case 3: + return Template.instance().wizardSettings.get().length > 0 && 'setup-wizard-forms__box--loaded'; + case 4: + return 'setup-wizard-forms__box--loaded'; } - - return ''; }, - headerTitle(step) { - if (!step) { - step = Template.instance().state.get('currentStep'); + showBackButton() { + switch (Template.instance().state.get('currentStep')) { + case 3: + return true; + case 4: + return true; } - switch (step) { - case 1: return t('Admin_Info'); - case 2: return t('Organization_Info'); - case 3: return t('Server_Info'); - case 4: return t('Register_Server'); - } + return false; }, - showStep() { - const currentStep = Template.instance().state.get('currentStep'); - if (currentStep === 2 || currentStep === 3) { - return 'setup-wizard-forms__content-step--active'; + isContinueDisabled() { + switch (Template.instance().state.get('currentStep')) { + case 1: + return Object.entries(Template.instance().state.all()) + .filter(([key, value]) => /registration-/.test(key) && !value) + .length !== 0; } - return ''; - }, - getSettings(step) { - return Template.instance().wizardSettings.get() - .filter(setting => setting.wizard.step === step) - .sort((a, b) => a.wizard.order - b.wizard.order); + return false; }, - languages() { - const languages = TAPi18n.getLanguages(); - - const result = Object.entries(languages).map(language => { - const obj = language[1]; - obj.key = language[0]; - return obj; - }).sort((a, b) => a.key - b.key); - - result.unshift({ - 'name': 'Default', - 'en': 'Default', - 'key': '' - }); + infoArgs() { + const t = Template.instance(); - return result; + return { + currentStep: t.state.get('currentStep') + }; }, - hasAdmin() { - return Template.instance().hasAdmin.get(); + adminInfoArgs() { + const t = Template.instance(); + + return { + currentStep: t.state.get('currentStep'), + name: t.state.get('registration-name'), + username: t.state.get('registration-username'), + email: t.state.get('registration-email'), + password: t.state.get('registration-pass'), + invalidUsername: t.state.get('invalidUsername'), + invalidEmail: t.state.get('invalidEmail') + }; }, - invalidEmail() { - return Template.instance().invalidEmail.get(); + registerServerArgs() { + const t = Template.instance(); + + return { + currentStep: t.state.get('currentStep'), + allowStandaloneServer: t.allowStandaloneServer.get(), + registerServer: t.allowStandaloneServer.get() ? t.state.get('registerServer') : true, + optIn: t.state.get('optIn') + }; }, - showBackButton() { - if (Template.instance().hasAdmin.get()) { - if (Template.instance().state.get('currentStep') > 2) { - return true; - } - - return false; - } - - if (Template.instance().state.get('currentStep') > 1) { - return true; - } - - return false; + customStepArgs(step) { + const t = Template.instance(); + + return { + currentStep: t.state.get('currentStep'), + step, + settings: t.wizardSettings.get() + .filter(setting => setting.wizard.step === step) + .sort((a, b) => a.wizard.order - b.wizard.order) + .map(({ type, _id, i18nLabel, values }) => ({ + type, + id: _id, + label: i18nLabel, + value: t.state.get(_id), + options: ( + type === 'select' && + values && + values.map(({ i18nLabel, key }) => ({ optionLabel: i18nLabel, optionValue: key })) + ) || ( + type === 'language' && + ([{ + optionLabel: 'Default', + optionValue: '' + }].concat( + Object.entries(TAPi18n.getLanguages()) + .map(([ key, { name } ]) => ({ optionLabel: name, optionValue: key })) + .sort((a, b) => a.key - b.key) + )) + ), + isValueSelected: (value) => value === t.state.get(_id) + })) + }; } }); -Template.setupWizardFinal.onCreated(function() { - this.autorun(() => { - const userId = Meteor.userId(); - - this.autorun((c) => { - const Show_Setup_Wizard = RocketChat.settings.get('Show_Setup_Wizard'); - const user = Meteor.user(); - - // Wait for roles and setup wizard setting - if ((userId && (!user || !user.status)) || !Show_Setup_Wizard) { - return; - } - - c.stop(); - - if ((!userId && Show_Setup_Wizard !== 'pending') || Show_Setup_Wizard === 'completed' || (userId && !RocketChat.authz.hasRole(userId, 'admin'))) { - FlowRouter.go('home'); - } - }); - }); -}); +Template.setupWizardInfo.helpers({ + stepItemModifier(step) { + const { currentStep } = Template.currentData(); -Template.setupWizardFinal.onRendered(function() { - $('#initial-page-loading').remove(); -}); + if (currentStep === step) { + return 'setup-wizard-info__steps-item--active'; + } -Template.setupWizardFinal.events({ - 'click .js-finish'() { - RocketChat.settings.set('Show_Setup_Wizard', 'completed', function() { - localStorage.removeItem('wizard'); - localStorage.removeItem('wizardFinal'); - FlowRouter.go('home'); - }); - } -}); + if (currentStep > step) { + return 'setup-wizard-info__steps-item--past'; + } -Template.setupWizardFinal.helpers({ - siteUrl() { - return RocketChat.settings.get('Site_Url'); + return ''; + }, + stepTitle(step) { + switch (step) { + case 1: + return 'Admin_Info'; + case 2: + return 'Organization_Info'; + case 3: + return 'Server_Info'; + case 4: + return 'Register_Server'; + } } }); diff --git a/packages/rocketchat-setup-wizard/package.js b/packages/rocketchat-setup-wizard/package.js index b9d07f3caeb3..ba70d31fd112 100644 --- a/packages/rocketchat-setup-wizard/package.js +++ b/packages/rocketchat-setup-wizard/package.js @@ -12,6 +12,8 @@ Package.onUse(function(api) { api.addFiles('client/setupWizard.html', 'client'); api.addFiles('client/setupWizard.js', 'client'); + api.addFiles('client/final.html', 'client'); + api.addFiles('client/final.js', 'client'); - api.addFiles('server/lib/getWizardSettings.js', 'server'); + api.addFiles('server/getSetupWizardParameters.js', 'server'); }); diff --git a/packages/rocketchat-setup-wizard/server/getSetupWizardParameters.js b/packages/rocketchat-setup-wizard/server/getSetupWizardParameters.js new file mode 100644 index 000000000000..910947c0418e --- /dev/null +++ b/packages/rocketchat-setup-wizard/server/getSetupWizardParameters.js @@ -0,0 +1,18 @@ +Meteor.methods({ + getSetupWizardParameters() { + const userId = Meteor.userId(); + const userHasAdminRole = userId && RocketChat.authz.hasRole(userId, 'admin'); + + if (!userHasAdminRole) { + throw new Meteor.Error('error-not-allowed'); + } + + const settings = RocketChat.models.Settings.findSetupWizardSettings().fetch(); + const allowStandaloneServer = process.env.DEPLOY_PLATFORM !== 'rocket-cloud'; + + return { + settings, + allowStandaloneServer + }; + } +}); diff --git a/packages/rocketchat-setup-wizard/server/lib/getWizardSettings.js b/packages/rocketchat-setup-wizard/server/lib/getWizardSettings.js deleted file mode 100644 index 918c3225bd23..000000000000 --- a/packages/rocketchat-setup-wizard/server/lib/getWizardSettings.js +++ /dev/null @@ -1,9 +0,0 @@ -Meteor.methods({ - getWizardSettings() { - if (RocketChat.authz.hasRole(Meteor.userId(), 'admin') && RocketChat.models && RocketChat.models.Settings) { - return RocketChat.models.Settings.findSetupWizardSettings().fetch(); - } - - throw new Meteor.Error('settings-are-not-ready', 'Settings are not ready'); - } -}); diff --git a/packages/rocketchat-theme/client/imports/components/setup-wizard.css b/packages/rocketchat-theme/client/imports/components/setup-wizard.css index fa2825348d28..3dea99d8cd8d 100644 --- a/packages/rocketchat-theme/client/imports/components/setup-wizard.css +++ b/packages/rocketchat-theme/client/imports/components/setup-wizard.css @@ -1,4 +1,7 @@ .setup-wizard { + --step-color: var(--rc-color-button-primary); + --highlight-color: var(--rc-color-button-primary); + display: flex; width: 100%; @@ -12,6 +15,7 @@ flex: 0 1 350px; margin: 55px 65px 30px 80px; + overflow: hidden; &__header{ display: flex; @@ -125,28 +129,30 @@ } &--active { - color: #1d74f5; + color: var(--rc-color-button-primary); &::before { - color: #1d74f5; - border-color: #1d74f5; + color: var(--rc-color-button-primary); + background-color: transparent; + border-color: var(--rc-color-button-primary); } } &--past { - color: #2f343d; + color: var(--rc-color-primary); &::before { - color: #ffffff; - background-color: #1d74f5; + color: var(--rc-color-content); + background-color: var(--rc-color-button-primary); + border-color: var(--rc-color-button-primary); } &::after { - background-color: #1d74f5 !important; + background-color: var(--rc-color-button-primary) !important; } & .setup-wizard-info__steps-item-bonding { - background-color: #1d74f5; + background-color: var(--rc-color-button-primary); } } @@ -177,8 +183,6 @@ height: calc(100% - 2rem); margin: 1rem 1rem 1rem 0; - padding: 3rem; - border-radius: 2px; background: #ffffff; box-shadow: 0 2px 4px 0 rgba(0,0,0,0.08); @@ -190,6 +194,17 @@ flex-direction: column; width: 350px; + min-height: min-content; + margin: 3rem; + + visibility: hidden; + opacity: 0; + transition: opacity 1s linear; + + &--loaded { + visibility: visible; + opacity: 1; + } } &__header { @@ -259,7 +274,7 @@ cursor: pointer; color: #2f343d; - border: 1px solid #e7ebf2; + border: 2px solid #e7ebf2; border-radius: 2px; @@ -267,6 +282,14 @@ line-height: 1.25rem; + &--selected { + border-color: var(--highlight-color); + } + + &--disabled { + opacity: 0.25; + } + &:first-child { margin-bottom: 1rem; } @@ -292,22 +315,21 @@ position: relative; - border-color: #1d74f5; + border-color: var(--highlight-color); &::before { - position: absolute; - - top: 3px; - left: 3px; + content: ""; - width: 12px; - height: 12px; + position: absolute; - content: ""; + width: 100%; + height: 100%; + background-clip: padding-box; border-radius: 50%; + border: 2px solid transparent; - background-color: #1d74f5; + background-color: var(--highlight-color); } } } @@ -319,7 +341,7 @@ height: 20px; margin: 0 0.5rem; - border: 1px solid #cfd8e6; + border: 2px solid #cfd8e6; border-radius: 50px; } @@ -328,6 +350,63 @@ } } + &-checkbox { + position: relative; + + display: flex; + + margin: 0 -0.5rem 1rem; + + cursor: inherit; + + &-element { + position: absolute; + z-index: -1; + top: 0; + left: 0; + + width: 0; + height: 0; + + &:checked + .setup-wizard-forms__content-register-checkbox-fake { + position: relative; + + border-color: var(--highlight-color); + background-color: var(--highlight-color); + color: var(--rc-color-content); + + .setup-wizard-forms__content-register-checkbox-fake-icon { + display: block; + } + } + } + + &-fake { + display: block; + + width: 16px; + height: 16px; + margin: 2px 0.5rem; + + border: 2px solid #cfd8e6; + border-radius: 2px; + + &-icon { + width: 100%; + height: 100%; + display: none; + } + } + + &-text { + color: #666666; + } + } + + &-items + * { + margin-top: 1rem; + } + &-item { display: flex; @@ -340,13 +419,20 @@ } & .setup-wizard-forms__content-register-radio-icon { - margin: 0 calc(4px + 0.5rem); + min-width: 20px; + width: 20px; + height: 20px; + margin: 0 0.5rem; + align-self: baseline; - font-size: 10px; - } + &--check { + color: var(--highlight-color); + } - & .setup-wizard-forms__content-register-radio-icon--check { - color: #1d74f5; + &--circle { + height: 6px; + margin: 7px 0.5rem; + } } } } @@ -354,8 +440,9 @@ &__footer { display: flex; + flex-direction: row; - margin: 0 -0.5rem; + margin: 0 -0.5rem 2rem -0.5rem; & .rc-button { margin: 0 0.5rem; @@ -390,7 +477,7 @@ letter-spacing: 0; - color: #1d74f5; + color: var(--highlight-color); font-size: 1rem; diff --git a/tests/end-to-end/ui/00-login.js b/tests/end-to-end/ui/00-login.js index 4cd6c69f86e6..3934bfb9da9e 100644 --- a/tests/end-to-end/ui/00-login.js +++ b/tests/end-to-end/ui/00-login.js @@ -123,6 +123,24 @@ describe('[Setup Wizard]', () => { }); }); + describe('[Render - Step 3]', () => { + it('it should have option for registered server', () => { + setupWizard.registeredServer.isExisting().should.be.true; + }); + + it('it should have option for standalone server', () => { + setupWizard.standaloneServer.isExisting().should.be.true; + }); + + it('it should check option for registered server by default', () => { + setupWizard.registeredServer.isSelected().should.be.true; + }); + + after(() => { + setupWizard.goNext(); + }); + }); + describe('[Render - Final Step]', () => { it('it should render "Go to your workspace button', () => { setupWizard.goToWorkspace.waitForVisible(15000); diff --git a/tests/pageobjects/setup-wizard.page.js b/tests/pageobjects/setup-wizard.page.js index 593b9b646e75..f6a652fee44a 100644 --- a/tests/pageobjects/setup-wizard.page.js +++ b/tests/pageobjects/setup-wizard.page.js @@ -14,6 +14,8 @@ class SetupWizard extends Page { get siteName() { return browser.element('input[name="Site_Name"]'); } get language() { return browser.element('select[name="Language"]'); } get serverType() { return browser.element('select[name="Server_Type"]'); } + get registeredServer() { return browser.element('input[name="registerServer"][value="true"]'); } + get standaloneServer() { return browser.element('input[name="registerServer"][value="false"]'); } login() { browser.execute(function(email, password) { From 0ecf4990f06fc46d583e87a515b9b46ed3343958 Mon Sep 17 00:00:00 2001 From: Rodrigo Nascimento Date: Wed, 4 Jul 2018 10:23:44 -0300 Subject: [PATCH 4/7] [FIX] Outgoing integrations were stopping the oplog tailing sometimes (#11333) When the integrations has a script that access some kind of async (made sync by Fibers) method the VM timeout would be fired after the timeout time and would generate some zoombie fibers cousing the oplog tailing (that uses Fibers) to stop working util a cursor timeout. --- .../server/lib/triggerHandler.js | 28 +++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/packages/rocketchat-integrations/server/lib/triggerHandler.js b/packages/rocketchat-integrations/server/lib/triggerHandler.js index 887fada828bb..36a9b4777634 100644 --- a/packages/rocketchat-integrations/server/lib/triggerHandler.js +++ b/packages/rocketchat-integrations/server/lib/triggerHandler.js @@ -3,6 +3,8 @@ import _ from 'underscore'; import s from 'underscore.string'; import moment from 'moment'; import vm from 'vm'; +import Fiber from 'fibers'; +import Future from 'fibers/future'; RocketChat.integrations.triggerHandler = new class RocketChatIntegrationHandler { constructor() { @@ -202,7 +204,15 @@ RocketChat.integrations.triggerHandler = new class RocketChatIntegrationHandler buildSandbox(store = {}) { const sandbox = { - _, s, console, moment, + scriptTimeout(reject) { + return setTimeout(() => reject('timed out'), 3000); + }, + _, + s, + console, + moment, + Fiber, + Promise, Store: { set: (key, val) => store[key] = val, get: (key) => store[key] @@ -303,7 +313,21 @@ RocketChat.integrations.triggerHandler = new class RocketChatIntegrationHandler sandbox.params = params; this.updateHistory({ historyId, step: `execute-script-before-running-${ method }` }); - const result = this.vm.runInNewContext('script[method](params)', sandbox, { timeout: 3000 }); + + const result = Future.fromPromise(this.vm.runInNewContext(` + new Promise((resolve, reject) => { + Fiber(() => { + scriptTimeout(reject); + try { + resolve(script[method](params)) + } catch(e) { + reject(e); + } + }).run(); + }).catch((error) => { throw new Error(error); }); + `, sandbox, { + timeout: 3000 + })).wait(); logger.outgoing.debug(`Script method "${ method }" result of the Integration "${ integration.name }" is:`); logger.outgoing.debug(result); From 259a31625bcf36f7bf8149366c39854e0af9feeb Mon Sep 17 00:00:00 2001 From: "Pierre H. Lehnen" Date: Wed, 4 Jul 2018 14:02:16 -0300 Subject: [PATCH 5/7] Fixes issues with SAML attribute mapping (#11315) --- packages/meteor-accounts-saml/saml_utils.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/meteor-accounts-saml/saml_utils.js b/packages/meteor-accounts-saml/saml_utils.js index e1274111ba67..d749f02e9ddc 100644 --- a/packages/meteor-accounts-saml/saml_utils.js +++ b/packages/meteor-accounts-saml/saml_utils.js @@ -395,8 +395,7 @@ SAML.prototype.validateResponse = function(samlResponse, relayState, callback) { if (attributes) { attributes.forEach(function(attribute) { const value = self.getElement(attribute, 'AttributeValue'); - let key = attribute.$.Name.value; - key=key.replace(/\./g, '-'); + const key = attribute.$.Name.value; if (typeof value[0] === 'string') { profile[key] = value[0]; } else { @@ -422,6 +421,16 @@ SAML.prototype.validateResponse = function(samlResponse, relayState, callback) { console.log(`NameID: ${ JSON.stringify(profile) }`); } + const profileKeys = Object.keys(profile); + for (let i = 0; i < profileKeys.length; i++) { + const key = profileKeys[i]; + + if (key.match(/\./)) { + profile[key.replace(/\./g, '-')] = profile[key]; + delete profile[key]; + } + } + callback(null, profile, false); } else { const logoutResponse = self.getElement(doc, 'LogoutResponse'); From fdf7b35c14f27f24b3e7e454b9241d34841a170a Mon Sep 17 00:00:00 2001 From: Rodrigo Nascimento Date: Wed, 4 Jul 2018 14:02:43 -0300 Subject: [PATCH 6/7] [FIX] Some updates were returning errors when based on queries with position operators (#11335) --- packages/rocketchat-lib/server/models/_BaseDb.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/rocketchat-lib/server/models/_BaseDb.js b/packages/rocketchat-lib/server/models/_BaseDb.js index 60dee3248d2b..b93f3e917701 100644 --- a/packages/rocketchat-lib/server/models/_BaseDb.js +++ b/packages/rocketchat-lib/server/models/_BaseDb.js @@ -160,7 +160,7 @@ class ModelsBaseDb extends EventEmitter { } updateHasPositionalOperator(update) { - return Object.keys(update).some(key => key.includes('.$') || (!Match.test(update[key], Object) && this.updateHasPositionalOperator(update[key]))); + return Object.keys(update).some(key => key.includes('.$') || (Match.test(update[key], Object) && this.updateHasPositionalOperator(update[key]))); } processOplogRecord(action) { From d17a8f3717e7578fd15e53990cb4592a7fff2619 Mon Sep 17 00:00:00 2001 From: Rodrigo Nascimento Date: Wed, 4 Jul 2018 14:22:31 -0300 Subject: [PATCH 7/7] Bump version to 0.66.1 --- .docker/Dockerfile.rhel | 2 +- .github/history.json | 64 +++++++++++++++++++++++++ .sandstorm/sandstorm-pkgdef.capnp | 4 +- .travis/snap.sh | 2 +- HISTORY.md | 31 ++++++++++++ package.json | 2 +- packages/rocketchat-lib/rocketchat.info | 2 +- 7 files changed, 101 insertions(+), 6 deletions(-) diff --git a/.docker/Dockerfile.rhel b/.docker/Dockerfile.rhel index 48af2bb2ed9a..ea1549cf6c77 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 0.66.0 +ENV RC_VERSION 0.66.1 MAINTAINER buildmaster@rocket.chat diff --git a/.github/history.json b/.github/history.json index 21cfa973438b..17de9e6052ca 100644 --- a/.github/history.json +++ b/.github/history.json @@ -16727,6 +16727,70 @@ ] } ] + }, + "0.66.1": { + "node_version": "8.11.3", + "npm_version": "5.6.0", + "pull_requests": [ + { + "pr": "11335", + "title": "[FIX] Some updates were returning errors when based on queries with position operators", + "userLogin": "rodrigok", + "milestone": "0.66.1", + "contributors": [ + "rodrigok" + ] + }, + { + "pr": "11315", + "title": "[FIX] SAML attributes with periods are not properly read.", + "userLogin": "Hudell", + "milestone": "0.66.1", + "contributors": [ + "Hudell", + "web-flow" + ] + }, + { + "pr": "11333", + "title": "[FIX] Outgoing integrations were stopping the oplog tailing sometimes", + "userLogin": "rodrigok", + "milestone": "0.66.1", + "contributors": [ + "rodrigok" + ] + }, + { + "pr": "11254", + "title": "[IMPROVE] Setup Wizard username validation, step progress and optin/optout", + "userLogin": "tassoevan", + "milestone": "0.66.1", + "contributors": [ + "tassoevan", + "ggazzo", + "web-flow" + ] + }, + { + "pr": "11267", + "title": "[FIX] Livestream muted when audio only option was enabled", + "userLogin": "gdelavald", + "milestone": "0.66.1", + "contributors": [ + "gdelavald", + "web-flow" + ] + }, + { + "pr": "11295", + "title": "[FIX] Notification preferences being lost when switching view mode", + "userLogin": "sampaiodiego", + "milestone": "0.66.1", + "contributors": [ + "sampaiodiego" + ] + } + ] } } } \ No newline at end of file diff --git a/.sandstorm/sandstorm-pkgdef.capnp b/.sandstorm/sandstorm-pkgdef.capnp index dc00db9464e0..2d5d162dceeb 100644 --- a/.sandstorm/sandstorm-pkgdef.capnp +++ b/.sandstorm/sandstorm-pkgdef.capnp @@ -19,9 +19,9 @@ const pkgdef :Spk.PackageDefinition = ( appTitle = (defaultText = "Rocket.Chat"), - appVersion = 77, # Increment this for every release. + appVersion = 78, # Increment this for every release. - appMarketingVersion = (defaultText = "0.66.0"), + appMarketingVersion = (defaultText = "0.66.1"), # Human-readable representation of appVersion. Should match the way you # identify versions of your app in documentation and marketing. diff --git a/.travis/snap.sh b/.travis/snap.sh index 7f1e84ea2daf..aea6ebf4f3ff 100755 --- a/.travis/snap.sh +++ b/.travis/snap.sh @@ -17,7 +17,7 @@ elif [[ $TRAVIS_TAG ]]; then RC_VERSION=$TRAVIS_TAG else CHANNEL=edge - RC_VERSION=0.66.0 + RC_VERSION=0.66.1 fi echo "Preparing to trigger a snap release for $CHANNEL channel" diff --git a/HISTORY.md b/HISTORY.md index f7da984a470e..66c820ab77c8 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,4 +1,35 @@ +# 0.66.1 +`2018-07-04 ยท 5 ๐Ÿ› ยท 1 ๐Ÿ” ยท 6 ๐Ÿ‘ฉโ€๐Ÿ’ป๐Ÿ‘จโ€๐Ÿ’ป` + +### Engine versions +- Node: `8.11.3` +- NPM: `5.6.0` + +### ๐Ÿ› Bug fixes + +- Some updates were returning errors when based on queries with position operators ([#11335](https://github.com/RocketChat/Rocket.Chat/pull/11335)) +- SAML attributes with periods are not properly read. ([#11315](https://github.com/RocketChat/Rocket.Chat/pull/11315)) +- Outgoing integrations were stopping the oplog tailing sometimes ([#11333](https://github.com/RocketChat/Rocket.Chat/pull/11333)) +- Livestream muted when audio only option was enabled ([#11267](https://github.com/RocketChat/Rocket.Chat/pull/11267)) +- Notification preferences being lost when switching view mode ([#11295](https://github.com/RocketChat/Rocket.Chat/pull/11295)) + +
+๐Ÿ” Minor changes + +- [IMPROVE] Setup Wizard username validation, step progress and optin/optout ([#11254](https://github.com/RocketChat/Rocket.Chat/pull/11254)) + +
+ +### ๐Ÿ‘ฉโ€๐Ÿ’ป๐Ÿ‘จโ€๐Ÿ’ป Core Team ๐Ÿค“ + +- [@Hudell](https://github.com/Hudell) +- [@gdelavald](https://github.com/gdelavald) +- [@ggazzo](https://github.com/ggazzo) +- [@rodrigok](https://github.com/rodrigok) +- [@sampaiodiego](https://github.com/sampaiodiego) +- [@tassoevan](https://github.com/tassoevan) + # 0.66.0 `2018-06-27 ยท 1 ๏ธ๏ธ๏ธโš ๏ธ ยท 23 ๐ŸŽ‰ ยท 61 ๐Ÿ› ยท 50 ๐Ÿ” ยท 45 ๐Ÿ‘ฉโ€๐Ÿ’ป๐Ÿ‘จโ€๐Ÿ’ป` diff --git a/package.json b/package.json index 0844c1edd671..58a54d7e2598 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "Rocket.Chat", "description": "The Ultimate Open Source WebChat Platform", - "version": "0.66.0", + "version": "0.66.1", "author": { "name": "Rocket.Chat", "url": "https://rocket.chat/" diff --git a/packages/rocketchat-lib/rocketchat.info b/packages/rocketchat-lib/rocketchat.info index e04e03c812a5..702a2f66ac82 100644 --- a/packages/rocketchat-lib/rocketchat.info +++ b/packages/rocketchat-lib/rocketchat.info @@ -1,3 +1,3 @@ { - "version": "0.66.0" + "version": "0.66.1" }