From 7db8cdd3be91ca986c9ec13b7c639c0755eae9a0 Mon Sep 17 00:00:00 2001 From: Ben Date: Fri, 7 Feb 2020 19:17:00 -0500 Subject: [PATCH 01/20] Add regex and wildcard functionality to whitelist and blacklist --- .../components/Settings/TrustAndRestrict.jsx | 5 ++-- src/classes/Policy.js | 25 +++++++++++++++++-- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/app/panel/components/Settings/TrustAndRestrict.jsx b/app/panel/components/Settings/TrustAndRestrict.jsx index 53141842a..467af0d08 100644 --- a/app/panel/components/Settings/TrustAndRestrict.jsx +++ b/app/panel/components/Settings/TrustAndRestrict.jsx @@ -86,9 +86,10 @@ class TrustAndRestrict extends React.Component { /** * Implement adding site to the list of whitelisted or blacklisted sites * This routine valides entered url and checks if the entered url is a duplicate, or - * if it has been alreday added to the opposite list. Displays appropriate warnings. + * if it has been already added to the opposite list. Displays appropriate warnings. */ addSite() { + // TODO: Implement paygating, use this regex for validating free users who don't have regex/wildcard ability // from node-validator const isValidUrlRegex = /^(?!mailto:)(?:(?:https?|ftp):\/\/)?(?:\S+(?::\S*)?@)?(?:(?:(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))|localhost)(?::\d{2,5})?(?:\/[^\s]*)?$/i; let pageHost; @@ -121,7 +122,7 @@ class TrustAndRestrict extends React.Component { pageHost = pageHost.toLowerCase().replace(/^(http[s]?:\/\/)?(www\.)?/, ''); // Check for Validity - if (pageHost.length >= 2083 || !isValidUrlRegex.test(pageHost)) { + if (pageHost.length >= 2083) { this.showWarning(t('white_black_list_error_invalid_url')); return; } diff --git a/src/classes/Policy.js b/src/classes/Policy.js index 547784d42..4b4ec5661 100644 --- a/src/classes/Policy.js +++ b/src/classes/Policy.js @@ -71,7 +71,8 @@ class Policy { // TODO: speed up for (let i = 0; i < num_sites; i++) { // TODO match from the beginning of the string to avoid false matches (somewhere in the querystring for instance) - if (replacedUrl === sites[i]) { + if (replacedUrl === sites[i] + || this.matchesWildcardOrRegex(replacedUrl, sites[i])) { return sites[i]; } } @@ -119,7 +120,8 @@ class Policy { // TODO: speed up for (let i = 0; i < num_sites; i++) { // TODO match from the beginning of the string to avoid false matches (somewhere in the querystring for instance) - if (replacedUrl === sites[i]) { + if (replacedUrl === sites[i] + || this.matchesWildcardOrRegex(replacedUrl, sites[i])) { return sites[i]; } } @@ -174,6 +176,25 @@ class Policy { } return { block: false, reason: allowedOnce ? BLOCK_REASON_C2P_ALLOWED_ONCE : BLOCK_REASON_GLOBAL_UNBLOCKED }; } + + /** + * Check given url against pattern which might be a regex, or a wildcard + * @param {string} url site url + * @param {string} pattern regex pattern + * @return {boolean} + */ + matchesWildcardOrRegex(url, pattern) { + let regex; + try { + regex = RegExp(pattern); + if (regex.test(url)) { return true; } + } catch { + const wildcardPattern = pattern.replace(/\*/g, '.*'); + regex = RegExp(wildcardPattern); + if (regex.test(url)) { return true; } + } + return false; + } } export default Policy; From 7fdc2d8940bdddcad6cd1911fe05f3c1a121039d Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 10 Feb 2020 09:50:18 -0500 Subject: [PATCH 02/20] Escape inputted regex and add error handling --- src/classes/Policy.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/classes/Policy.js b/src/classes/Policy.js index 4b4ec5661..a8820b529 100644 --- a/src/classes/Policy.js +++ b/src/classes/Policy.js @@ -15,6 +15,7 @@ /* eslint no-param-reassign: 0 */ +import escapeStringRegexp from 'escape-string-regexp'; import c2pDb from './Click2PlayDb'; import conf from './Conf'; import globals from './Globals'; @@ -184,14 +185,18 @@ class Policy { * @return {boolean} */ matchesWildcardOrRegex(url, pattern) { - let regex; + let regex = escapeStringRegexp(pattern); try { regex = RegExp(pattern); if (regex.test(url)) { return true; } } catch { const wildcardPattern = pattern.replace(/\*/g, '.*'); - regex = RegExp(wildcardPattern); - if (regex.test(url)) { return true; } + try { + regex = RegExp(wildcardPattern); + if (regex.test(url)) { return true; } + } catch { + // Invalid pattern + } } return false; } From f07e1514f4ca55811b4927340473ed8415b4291a Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 10 Feb 2020 10:01:53 -0500 Subject: [PATCH 03/20] Add escape-string-regexp dependency --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index b8f162cdb..f940f764a 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,7 @@ "browser-core": "https://github.com/cliqz-oss/browser-core/releases/download/v7.43.1/browser-core-7.43.1.tgz", "classnames": "^2.2.5", "d3": "^5.15.0", + "escape-string-regexp": "^2.0.0", "foundation-sites": "^6.6.1", "history": "^4.10.1", "json-api-normalizer": "^0.4.16", From 3cff5eb1ee9b6554e838d904b42ec5478f386588 Mon Sep 17 00:00:00 2001 From: Ben Date: Tue, 11 Feb 2020 13:42:36 -0500 Subject: [PATCH 04/20] Refactor matchesWildcardOrRegex and remove escape-strings-regex dependency --- .../components/Settings/TrustAndRestrict.jsx | 3 --- package.json | 1 - src/classes/Policy.js | 26 ++++++++----------- 3 files changed, 11 insertions(+), 19 deletions(-) diff --git a/app/panel/components/Settings/TrustAndRestrict.jsx b/app/panel/components/Settings/TrustAndRestrict.jsx index 467af0d08..7bb3cce96 100644 --- a/app/panel/components/Settings/TrustAndRestrict.jsx +++ b/app/panel/components/Settings/TrustAndRestrict.jsx @@ -89,9 +89,6 @@ class TrustAndRestrict extends React.Component { * if it has been already added to the opposite list. Displays appropriate warnings. */ addSite() { - // TODO: Implement paygating, use this regex for validating free users who don't have regex/wildcard ability - // from node-validator - const isValidUrlRegex = /^(?!mailto:)(?:(?:https?|ftp):\/\/)?(?:\S+(?::\S*)?@)?(?:(?:(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))|localhost)(?::\d{2,5})?(?:\/[^\s]*)?$/i; let pageHost; let list; let listType; diff --git a/package.json b/package.json index f940f764a..b8f162cdb 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,6 @@ "browser-core": "https://github.com/cliqz-oss/browser-core/releases/download/v7.43.1/browser-core-7.43.1.tgz", "classnames": "^2.2.5", "d3": "^5.15.0", - "escape-string-regexp": "^2.0.0", "foundation-sites": "^6.6.1", "history": "^4.10.1", "json-api-normalizer": "^0.4.16", diff --git a/src/classes/Policy.js b/src/classes/Policy.js index a8820b529..aa58c7503 100644 --- a/src/classes/Policy.js +++ b/src/classes/Policy.js @@ -14,8 +14,6 @@ */ /* eslint no-param-reassign: 0 */ - -import escapeStringRegexp from 'escape-string-regexp'; import c2pDb from './Click2PlayDb'; import conf from './Conf'; import globals from './Globals'; @@ -185,19 +183,17 @@ class Policy { * @return {boolean} */ matchesWildcardOrRegex(url, pattern) { - let regex = escapeStringRegexp(pattern); - try { - regex = RegExp(pattern); - if (regex.test(url)) { return true; } - } catch { - const wildcardPattern = pattern.replace(/\*/g, '.*'); - try { - regex = RegExp(wildcardPattern); - if (regex.test(url)) { return true; } - } catch { - // Invalid pattern - } - } + const escapedPattern = pattern.replace(/[|\\{}()[\]^$+*?.-]/g, '\\$&'); + + // Input string might be a regex + let regex = RegExp(escapedPattern); + if (regex.test(url)) { return true; } + + // or a wildcard + const wildcardPattern = escapedPattern.replace(/\*/g, '.*'); + regex = RegExp(wildcardPattern); + if (regex.test(url)) { return true; } + return false; } } From a03896fa37708b78592c5a122a50c86f06ce12ff Mon Sep 17 00:00:00 2001 From: Ben Date: Tue, 11 Feb 2020 13:59:55 -0500 Subject: [PATCH 05/20] Make regex variables const --- src/classes/Policy.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/classes/Policy.js b/src/classes/Policy.js index aa58c7503..1e26d0063 100644 --- a/src/classes/Policy.js +++ b/src/classes/Policy.js @@ -186,13 +186,13 @@ class Policy { const escapedPattern = pattern.replace(/[|\\{}()[\]^$+*?.-]/g, '\\$&'); // Input string might be a regex - let regex = RegExp(escapedPattern); + const regex = RegExp(escapedPattern); if (regex.test(url)) { return true; } // or a wildcard const wildcardPattern = escapedPattern.replace(/\*/g, '.*'); - regex = RegExp(wildcardPattern); - if (regex.test(url)) { return true; } + const wildcardRegex = RegExp(wildcardPattern); + if (wildcardRegex.test(url)) { return true; } return false; } From 39304872ded796f2bded5f07108b5cb7b0896f67 Mon Sep 17 00:00:00 2001 From: Ben Date: Tue, 18 Feb 2020 15:00:21 -0500 Subject: [PATCH 06/20] Prevent ReDoS attack. Validate url, wildcard or regex. Update error messages --- _locales/en/messages.json | 4 +- .../components/Settings/TrustAndRestrict.jsx | 38 ++++++++++++++++++- package.json | 1 + src/classes/Policy.js | 14 +++---- yarn.lock | 12 ++++++ 5 files changed, 59 insertions(+), 10 deletions(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index d74c8ed74..b07bafea4 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -802,7 +802,7 @@ "message": "unblocked" }, "white_black_list_error_invalid_url": { - "message": "Please enter a valid URL." + "message": "Please enter a valid URL, regex, or wildcard" }, "whitelist_error_blacklist_url": { "message": "This site has been removed from your Restricted Sites list and added to your Trusted Sites list." @@ -1058,7 +1058,7 @@ "message": "Trusted Sites" }, "settings_sites_placeholder": { - "message": "example.com" + "message": "example.com (wildcards/regex supported)" }, "settings_restricted_sites": { "message": "Restricted Sites" diff --git a/app/panel/components/Settings/TrustAndRestrict.jsx b/app/panel/components/Settings/TrustAndRestrict.jsx index 7bb3cce96..76996f5e7 100644 --- a/app/panel/components/Settings/TrustAndRestrict.jsx +++ b/app/panel/components/Settings/TrustAndRestrict.jsx @@ -12,6 +12,7 @@ */ import React from 'react'; +import safe from 'safe-regex'; import Sites from './Sites'; /** * @class Implement Trust and Restrict subview presenting the lists @@ -119,10 +120,12 @@ class TrustAndRestrict extends React.Component { pageHost = pageHost.toLowerCase().replace(/^(http[s]?:\/\/)?(www\.)?/, ''); // Check for Validity - if (pageHost.length >= 2083) { + if (pageHost.length >= 2083 + || !this.isValidUrlWildcardOrRegex(pageHost)) { this.showWarning(t('white_black_list_error_invalid_url')); return; } + // Check for Duplicates if (list.includes(pageHost)) { this.showWarning(duplicateWarning); @@ -137,6 +140,39 @@ class TrustAndRestrict extends React.Component { this.props.actions.updateSitePolicy({ type: listType, pageHost }); } + isValidUrlWildcardOrRegex(pageHost) { + // Check for valid URL + // from node-validator + const isValidUrlRegex = /^(?!mailto:)(?:(?:https?|ftp):\/\/)?(?:\S+(?::\S*)?@)?(?:(?:(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))|localhost)(?::\d{2,5})?(?:\/[^\s]*)?$/i; + if (isValidUrlRegex.test(pageHost)) return true; + + + // Check for valid wildcard + const escapedPattern = pageHost.replace(/[|\\{}()[\]^$+*?.-]/g, '\\$&'); + const wildcardPattern = escapedPattern.replace(/\*/g, '.*'); + let isValidWildcard = true; + try { + // eslint-disable-next-line + new RegExp(wildcardPattern); + } catch { + isValidWildcard = false; + } + + if (isValidWildcard) return true; + + // Prevent ReDoS attack + if (!safe(pageHost)) return false; + + // Check for valid regex + try { + // eslint-disable-next-line + new RegExp(pageHost); + } catch { + return false; + } + return false; + } + /** * Save current warning in state. * @param {string} warning warning to save diff --git a/package.json b/package.json index b8f162cdb..2e7574396 100644 --- a/package.json +++ b/package.json @@ -64,6 +64,7 @@ "redux-object": "^0.5.10", "redux-thunk": "^2.2.0", "rsvp": "^4.8.5", + "safe-regex": "^2.1.1", "spanan": "^2.0.0", "ua-parser-js": "^0.7.21", "underscore": "^1.9.2", diff --git a/src/classes/Policy.js b/src/classes/Policy.js index 1e26d0063..2afb08e52 100644 --- a/src/classes/Policy.js +++ b/src/classes/Policy.js @@ -177,23 +177,23 @@ class Policy { } /** - * Check given url against pattern which might be a regex, or a wildcard + * Check given url against pattern which might be a wildcard, or a regex * @param {string} url site url * @param {string} pattern regex pattern * @return {boolean} */ matchesWildcardOrRegex(url, pattern) { + // Input string might be a wildcard const escapedPattern = pattern.replace(/[|\\{}()[\]^$+*?.-]/g, '\\$&'); - - // Input string might be a regex - const regex = RegExp(escapedPattern); - if (regex.test(url)) { return true; } - - // or a wildcard const wildcardPattern = escapedPattern.replace(/\*/g, '.*'); const wildcardRegex = RegExp(wildcardPattern); + if (wildcardRegex.test(url)) { return true; } + // or a regex + const regex = RegExp(pattern); + if (regex.test(url)) { return true; } + return false; } } diff --git a/yarn.lock b/yarn.lock index 322e594e1..d7e6b0573 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7086,6 +7086,11 @@ regexp-quote@0.0.0: resolved "https://registry.yarnpkg.com/regexp-quote/-/regexp-quote-0.0.0.tgz#1e0f4650c862dcbfed54fd42b148e9bb1721fcf2" integrity sha1-Hg9GUMhi3L/tVP1CsUjpuxch/PI= +regexp-tree@~0.1.1: + version "0.1.19" + resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.19.tgz#9326e91d8d1d23298dd33a78cf5e788f57cdc359" + integrity sha512-mVeVLF/qg5qFbZSW0f7pXbuVX73dKIjuhOyC2JLKxzmpya75O4qLcvI9j0jp31Iz7IAkEVHa1UErDCAqaLKo5A== + regexp.prototype.flags@^1.2.0, regexp.prototype.flags@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz#7aba89b3c13a64509dabcf3ca8d9fbb9bdf5cb75" @@ -7373,6 +7378,13 @@ safe-regex@^1.1.0: dependencies: ret "~0.1.10" +safe-regex@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-2.1.1.tgz#f7128f00d056e2fe5c11e81a1324dd974aadced2" + integrity sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A== + dependencies: + regexp-tree "~0.1.1" + "safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" From 63ec3b664c623f38c8fd316fdcfa325d3b90d5cc Mon Sep 17 00:00:00 2001 From: Ben Date: Tue, 18 Feb 2020 15:02:58 -0500 Subject: [PATCH 07/20] Remove newline --- app/panel/components/Settings/TrustAndRestrict.jsx | 1 - 1 file changed, 1 deletion(-) diff --git a/app/panel/components/Settings/TrustAndRestrict.jsx b/app/panel/components/Settings/TrustAndRestrict.jsx index 76996f5e7..e98786b90 100644 --- a/app/panel/components/Settings/TrustAndRestrict.jsx +++ b/app/panel/components/Settings/TrustAndRestrict.jsx @@ -146,7 +146,6 @@ class TrustAndRestrict extends React.Component { const isValidUrlRegex = /^(?!mailto:)(?:(?:https?|ftp):\/\/)?(?:\S+(?::\S*)?@)?(?:(?:(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))|localhost)(?::\d{2,5})?(?:\/[^\s]*)?$/i; if (isValidUrlRegex.test(pageHost)) return true; - // Check for valid wildcard const escapedPattern = pageHost.replace(/[|\\{}()[\]^$+*?.-]/g, '\\$&'); const wildcardPattern = escapedPattern.replace(/\*/g, '.*'); From fc1f6211d2ce44205d13f12139b3e088bc5ee3c1 Mon Sep 17 00:00:00 2001 From: Ben Date: Tue, 18 Feb 2020 15:09:29 -0500 Subject: [PATCH 08/20] Add period to error text --- _locales/en/messages.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index a7b551718..185becc90 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -802,7 +802,7 @@ "message": "unblocked" }, "white_black_list_error_invalid_url": { - "message": "Please enter a valid URL, regex, or wildcard" + "message": "Please enter a valid URL, regex, or wildcard." }, "whitelist_error_blacklist_url": { "message": "This site has been removed from your Restricted Sites list and added to your Trusted Sites list." From b9186bcb30c2afa3ba95040f2bd0038fceec1baa Mon Sep 17 00:00:00 2001 From: Benjamin Strumeyer Date: Fri, 21 Feb 2020 10:43:32 -0500 Subject: [PATCH 09/20] GH-1947 Plus checkout UTM params (#499) * Add UTM params to Plus checkout from all locations * Update tests * Remove / from links with utm params * Refactor messaging passing --- _locales/en/messages.json | 2 +- app/hub/Views/PlusView/PlusView.jsx | 2 +- .../Views/PlusView/__tests__/PlusView.test.jsx | 2 +- .../__snapshots__/PlusView.test.jsx.snap | 16 ++++++++-------- app/panel/components/Stats.jsx | 5 ++++- app/panel/components/Subscribe.jsx | 7 +++++-- app/panel/utils/msg.js | 4 ++-- src/background.js | 7 ++++++- 8 files changed, 28 insertions(+), 17 deletions(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 269e14231..0e5300f9b 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -1936,7 +1936,7 @@ "content": "" }, "link_start": { - "content": "
" + "content": "
" } } }, diff --git a/app/hub/Views/PlusView/PlusView.jsx b/app/hub/Views/PlusView/PlusView.jsx index 6457f84fe..7a56806a4 100644 --- a/app/hub/Views/PlusView/PlusView.jsx +++ b/app/hub/Views/PlusView/PlusView.jsx @@ -29,7 +29,7 @@ class PlusView extends Component { */ _renderButton = (additionalClasses) => { const { isPlus, onPlusClick } = this.props; - const buttonHref = `https://checkout.${globals.GHOSTERY_DOMAIN}.com/plus`; + const buttonHref = `https://checkout.${globals.GHOSTERY_DOMAIN}.com/plus?utm_source=gbe&utm_campaign=intro_hub_plus`; const buttonClassNames = ClassNames('PlusView__button', 'button', additionalClasses, { disabled: isPlus, }); diff --git a/app/hub/Views/PlusView/__tests__/PlusView.test.jsx b/app/hub/Views/PlusView/__tests__/PlusView.test.jsx index 3e2c4fa4e..14d2912ca 100644 --- a/app/hub/Views/PlusView/__tests__/PlusView.test.jsx +++ b/app/hub/Views/PlusView/__tests__/PlusView.test.jsx @@ -70,7 +70,7 @@ describe('app/hub/Views/PlusView component', () => { component.find('.PlusView__button').first().simulate('click'); expect(initialState.onPlusClick.mock.calls.length).toBe(1); - expect(component.find('.PlusView__button').first().props().href).toBe('https://checkout.ghosterystage.com/plus') + expect(component.find('.PlusView__button').first().props().href).toBe('https://checkout.ghosterystage.com/plus?utm_source=gbe&utm_campaign=intro_hub_plus') expect(component.find('.PlusView__button').length).toBe(8); expect(component.find('.PlusView__button.disabled').length).toBe(0); diff --git a/app/hub/Views/PlusView/__tests__/__snapshots__/PlusView.test.jsx.snap b/app/hub/Views/PlusView/__tests__/__snapshots__/PlusView.test.jsx.snap index c673637ca..f4b3356eb 100644 --- a/app/hub/Views/PlusView/__tests__/__snapshots__/PlusView.test.jsx.snap +++ b/app/hub/Views/PlusView/__tests__/__snapshots__/PlusView.test.jsx.snap @@ -361,7 +361,7 @@ exports[`app/hub/Views/PlusView component Snapshot tests with react-test-rendere > { sendMessage('ping', 'hist_plus_cta'); - openCheckoutPage(); + openCheckoutPage({ + utm_source: 'gbe', + utm_campaign: 'in_app_hstats' + }); } /** diff --git a/app/panel/components/Subscribe.jsx b/app/panel/components/Subscribe.jsx index 1bc92505d..81222e88a 100644 --- a/app/panel/components/Subscribe.jsx +++ b/app/panel/components/Subscribe.jsx @@ -21,7 +21,10 @@ import { sendMessage, openCheckoutPage } from '../utils/msg'; */ function _handleBecomeClick() { sendMessage('ping', 'plus_cta_extension'); - openCheckoutPage(); + openCheckoutPage({ + utm_source: 'gbe', + utm_campaign: 'in_app_plus' + }); } /** @@ -36,7 +39,7 @@ const Subscribe = (props) => {
- + {t('subscribe_pitch_learn_more')}
diff --git a/app/panel/utils/msg.js b/app/panel/utils/msg.js index 7081254df..78deb224a 100644 --- a/app/panel/utils/msg.js +++ b/app/panel/utils/msg.js @@ -124,8 +124,8 @@ export function openSubscriptionPage() { * This should be used for messages that don't require a callback. * @memberOf PanelUtils */ -export function openCheckoutPage() { - sendMessage('account.openCheckoutPage'); +export function openCheckoutPage(utm) { + sendMessage('account.openCheckoutPage', { utm }); window.close(); } diff --git a/src/background.js b/src/background.js index b1063f70d..107290cfe 100644 --- a/src/background.js +++ b/src/background.js @@ -849,7 +849,12 @@ function onMessageHandler(request, sender, callback) { return false; } if (name === 'account.openCheckoutPage') { - utils.openNewTab({ url: `https://checkout.${globals.GHOSTERY_DOMAIN}.com/plus`, become_active: true }); + let url = `https://checkout.${globals.GHOSTERY_DOMAIN}.com/plus`; + const { utm } = message || null; + if (utm) { + url += `?utm_source=${utm.utm_source}&utm_campaign=${utm.utm_campaign}`; + } + utils.openNewTab({ url, become_active: true }); return false; } if (name === 'account.openSupportPage') { From a726e874d9b7713ac6959842637901d13e6c4998 Mon Sep 17 00:00:00 2001 From: Christopher Tino Date: Fri, 21 Feb 2020 10:57:17 -0500 Subject: [PATCH 10/20] update translations --- _locales/de/messages.json | 14 +++----------- _locales/es/messages.json | 14 +++----------- _locales/fr/messages.json | 14 +++----------- _locales/hu/messages.json | 14 +++----------- _locales/it/messages.json | 14 +++----------- _locales/ja/messages.json | 14 +++----------- _locales/ko/messages.json | 14 +++----------- _locales/nl/messages.json | 14 +++----------- _locales/pl/messages.json | 14 +++----------- _locales/pt_BR/messages.json | 14 +++----------- _locales/ru/messages.json | 14 +++----------- _locales/zh_CN/messages.json | 14 +++----------- _locales/zh_TW/messages.json | 14 +++----------- 13 files changed, 39 insertions(+), 143 deletions(-) diff --git a/_locales/de/messages.json b/_locales/de/messages.json index c5f5fe58e..7011b93b5 100644 --- a/_locales/de/messages.json +++ b/_locales/de/messages.json @@ -727,9 +727,6 @@ "panel_detail_rewards_cliqz_text": { "message": "Die Funktion ist im Cliqz MyOffrz-Bedienfeld bereits aktiv." }, - "panel_detail_rewards_edge_text": { - "message": "Ghostery Rewards werden in Edge-Browser nicht unterstützt." - }, "panel_detail_rewards_loading": { "message": "Rewards werden geladen..." }, @@ -1649,9 +1646,6 @@ "hub_create_account_label_password_invalid_length": { "message": "Verwenden Sie zwischen 8 und 50 Zeichen." }, - "hub_create_account_checkbox_promotions": { - "message": "Schicken Sie mir Ghostery-Aktualisierungen & Promotions." - }, "hub_create_account_already_have_account": { "message": "Sie haben bereits ein Ghostery-Konto?" }, @@ -1942,7 +1936,7 @@ "content": "" }, "link_start": { - "content": "
" + "content": "
" } } }, @@ -2353,8 +2347,7 @@ "message": "Testen Sie Ghostery Midnight" }, "seven_day_free_trial": { - "message": "7 Tage kostenlose Testversion ($14/mtl.)", - "description": "Do not localize currency. Use the $14 USD amount. The second $ is needed to escape the special meaning of $" + "message": "7 Tage kostenlose Testversion ($14/mtl.)" }, "full_coverage_protection_promise": { "message": "Holen Sie sich umfassenden Schutz für alle Browser und Apps auf Ihrem Gerät." @@ -2375,8 +2368,7 @@ "message": "Kostenlos herunterladen" }, "support_ghostery_for_2_instead": { - "message": "Unterstützen Sie Ghostery stattdessen für $2/mtl.", - "description": "Do not localize currency. Use the $2 USD amount. The second $ is needed to escape the special meaning of $" + "message": "Unterstützen Sie Ghostery stattdessen für $2/mtl." }, "no_thanks_continue_with_basic": { "message": "Nein, danke. Mit Basisversion fortfahren." diff --git a/_locales/es/messages.json b/_locales/es/messages.json index 02fd5a871..0cbcda4f3 100644 --- a/_locales/es/messages.json +++ b/_locales/es/messages.json @@ -727,9 +727,6 @@ "panel_detail_rewards_cliqz_text": { "message": "Función ya activa en el panel de control de Cliqz MyOffrz." }, - "panel_detail_rewards_edge_text": { - "message": "Ghostery Rewards no se admite en el navegador Edge" - }, "panel_detail_rewards_loading": { "message": "Cargando Rewards..." }, @@ -1649,9 +1646,6 @@ "hub_create_account_label_password_invalid_length": { "message": "Usa entre 8 y 50 caracteres." }, - "hub_create_account_checkbox_promotions": { - "message": "Envíame actualizaciones y promociones de Ghostery." - }, "hub_create_account_already_have_account": { "message": "¿Ya tienes una cuenta de Ghostery?" }, @@ -1942,7 +1936,7 @@ "content": "" }, "link_start": { - "content": "
" + "content": "
" } } }, @@ -2353,8 +2347,7 @@ "message": "Prueba Ghostery Midnight" }, "seven_day_free_trial": { - "message": "Prueba gratuita de 7 días ($14/mes)", - "description": "Do not localize currency. Use the $14 USD amount. The second $ is needed to escape the special meaning of $" + "message": "Prueba gratuita de 7 días ($14/mes)" }, "full_coverage_protection_promise": { "message": "Obtén protección de cobertura completa en todos los navegadores y aplicaciones de tu dispositivo" @@ -2375,8 +2368,7 @@ "message": "Descarga gratuita" }, "support_ghostery_for_2_instead": { - "message": "O apoya a Ghostery por $2/mes", - "description": "Do not localize currency. Use the $2 USD amount. The second $ is needed to escape the special meaning of $" + "message": "O apoya a Ghostery por $2/mes" }, "no_thanks_continue_with_basic": { "message": "No, gracias, continuar con básico" diff --git a/_locales/fr/messages.json b/_locales/fr/messages.json index 15fb61e5b..88c1fd2ca 100644 --- a/_locales/fr/messages.json +++ b/_locales/fr/messages.json @@ -727,9 +727,6 @@ "panel_detail_rewards_cliqz_text": { "message": "Fonction déjà activée dans le panneau de commande Cliqz MyOffrz." }, - "panel_detail_rewards_edge_text": { - "message": "Ghostery Rewards n'est pas pris en charge par le navigateur Edge" - }, "panel_detail_rewards_loading": { "message": "Chargement des Rewards…" }, @@ -1649,9 +1646,6 @@ "hub_create_account_label_password_invalid_length": { "message": "Utilisez entre 8 et 50 caractères." }, - "hub_create_account_checkbox_promotions": { - "message": "Envoyez-moi les mises à jour & promotions Ghostery." - }, "hub_create_account_already_have_account": { "message": "Vous avez déjà un compte Ghostery ?" }, @@ -1942,7 +1936,7 @@ "content": "" }, "link_start": { - "content": "
" + "content": "
" } } }, @@ -2353,8 +2347,7 @@ "message": "Essayez Ghostery Midnight" }, "seven_day_free_trial": { - "message": "Essai gratuit de 7 jours (14 $/mois)", - "description": "Do not localize currency. Use the $14 USD amount. The second $ is needed to escape the special meaning of $" + "message": "Essai gratuit de 7 jours (14 $/mois)" }, "full_coverage_protection_promise": { "message": "Bénéficiez d'une protection complète sur tous les navigateurs et toutes les applications sur votre appareil" @@ -2375,8 +2368,7 @@ "message": "Télécharger gratuitement" }, "support_ghostery_for_2_instead": { - "message": "Aidez Ghostery pour 2 $/mois", - "description": "Do not localize currency. Use the $2 USD amount. The second $ is needed to escape the special meaning of $" + "message": "Aidez Ghostery pour 2 $/mois" }, "no_thanks_continue_with_basic": { "message": "Non merci, continuer avec la version de base" diff --git a/_locales/hu/messages.json b/_locales/hu/messages.json index 3499c6e99..840271b15 100644 --- a/_locales/hu/messages.json +++ b/_locales/hu/messages.json @@ -727,9 +727,6 @@ "panel_detail_rewards_cliqz_text": { "message": "A funkció már aktív a Cliqz MyOffrz vezérlőpultjában." }, - "panel_detail_rewards_edge_text": { - "message": "A Ghostery Rewards nem támogatott az Edge böngészőben" - }, "panel_detail_rewards_loading": { "message": "Rewards betöltése…" }, @@ -1649,9 +1646,6 @@ "hub_create_account_label_password_invalid_length": { "message": "8–50 karaktert használjon." }, - "hub_create_account_checkbox_promotions": { - "message": "Küldjenek nekem friss Ghostery híreket és promóciókat!" - }, "hub_create_account_already_have_account": { "message": "Már van Ghostery fiókja?" }, @@ -1942,7 +1936,7 @@ "content": "" }, "link_start": { - "content": "
" + "content": "
" } } }, @@ -2353,8 +2347,7 @@ "message": "Próbálja ki a Ghostery Midnight-t" }, "seven_day_free_trial": { - "message": "7 napos ingyenes próbaverzió ($ 14/hó)", - "description": "Do not localize currency. Use the $14 USD amount. The second $ is needed to escape the special meaning of $" + "message": "7 napos ingyenes próbaverzió ($ 14/hó)" }, "full_coverage_protection_promise": { "message": "Teljes védelmet élvezhet az eszköz összes böngészőjével és alkalmazásával" @@ -2375,8 +2368,7 @@ "message": "Töltse le ingyen" }, "support_ghostery_for_2_instead": { - "message": "Ehelyett támogassa a Ghostery-t $ 2 / hónap alatt", - "description": "Do not localize currency. Use the $2 USD amount. The second $ is needed to escape the special meaning of $" + "message": "Ehelyett támogassa a Ghostery-t $ 2 / hónap alatt" }, "no_thanks_continue_with_basic": { "message": "Nem, köszönöm, folytassa az alapszinttel" diff --git a/_locales/it/messages.json b/_locales/it/messages.json index 33942e0b4..645fe940a 100644 --- a/_locales/it/messages.json +++ b/_locales/it/messages.json @@ -727,9 +727,6 @@ "panel_detail_rewards_cliqz_text": { "message": "La funzione è già attiva nel pannello di controllo Cliqz MyOffrz." }, - "panel_detail_rewards_edge_text": { - "message": "Il browser Edge non supporta Ghostery Rewards" - }, "panel_detail_rewards_loading": { "message": "Caricamento Rewards in corso…" }, @@ -1649,9 +1646,6 @@ "hub_create_account_label_password_invalid_length": { "message": "Utilizza tra 8 e 50 caratteri." }, - "hub_create_account_checkbox_promotions": { - "message": "Inviatemi aggiornamenti e promozioni su Ghostery" - }, "hub_create_account_already_have_account": { "message": "Hai già un Account Ghostery?" }, @@ -1942,7 +1936,7 @@ "content": "" }, "link_start": { - "content": "
" + "content": "
" } } }, @@ -2353,8 +2347,7 @@ "message": "Prova Ghostery Midnight" }, "seven_day_free_trial": { - "message": "Prova gratuita di 7 giorni ($14/mese)", - "description": "Do not localize currency. Use the $14 USD amount. The second $ is needed to escape the special meaning of $" + "message": "Prova gratuita di 7 giorni ($14/mese)" }, "full_coverage_protection_promise": { "message": "Ottieni la protezione completa per tutti i browser e le app sul tuo dispositivo" @@ -2375,8 +2368,7 @@ "message": "Scarica gratis" }, "support_ghostery_for_2_instead": { - "message": "Sostieni Ghostery al costo di $2/mese", - "description": "Do not localize currency. Use the $2 USD amount. The second $ is needed to escape the special meaning of $" + "message": "Sostieni Ghostery al costo di $2/mese" }, "no_thanks_continue_with_basic": { "message": "No, grazie. Continuo con la versione base" diff --git a/_locales/ja/messages.json b/_locales/ja/messages.json index a55d80b78..0552b9814 100644 --- a/_locales/ja/messages.json +++ b/_locales/ja/messages.json @@ -727,9 +727,6 @@ "panel_detail_rewards_cliqz_text": { "message": "既にCliqz MyOffrzコントロールパネルで有効になっている機能です。" }, - "panel_detail_rewards_edge_text": { - "message": "Ghostery Rewardsは、Edgeブラウザではサポートされていません" - }, "panel_detail_rewards_loading": { "message": "Rewardsを読み込み中…" }, @@ -1649,9 +1646,6 @@ "hub_create_account_label_password_invalid_length": { "message": "8~50文字を使用してください。" }, - "hub_create_account_checkbox_promotions": { - "message": "Ghosteryのアップデート&お得な情報を受け取る。" - }, "hub_create_account_already_have_account": { "message": "既にGhosteryアカウントを持っていますか?" }, @@ -1942,7 +1936,7 @@ "content": "" }, "link_start": { - "content": "
" + "content": "
" } } }, @@ -2353,8 +2347,7 @@ "message": "Ghostery Midnightを試す" }, "seven_day_free_trial": { - "message": "7日間無料トライアル(月額14ドル)", - "description": "Do not localize currency. Use the $14 USD amount. The second $ is needed to escape the special meaning of $" + "message": "7日間無料トライアル(月額14ドル)" }, "full_coverage_protection_promise": { "message": "デバイス上のすべてのブラウザとアプリを包括的に保護しましょう" @@ -2375,8 +2368,7 @@ "message": "無料でダウンロード" }, "support_ghostery_for_2_instead": { - "message": "代わりに月額2ドルでGhosteryをサポート", - "description": "Do not localize currency. Use the $2 USD amount. The second $ is needed to escape the special meaning of $" + "message": "代わりに月額2ドルでGhosteryをサポート" }, "no_thanks_continue_with_basic": { "message": "いいえ、ベーシックプランで継続する" diff --git a/_locales/ko/messages.json b/_locales/ko/messages.json index 35aad37f9..4c7ea9180 100644 --- a/_locales/ko/messages.json +++ b/_locales/ko/messages.json @@ -727,9 +727,6 @@ "panel_detail_rewards_cliqz_text": { "message": "기능이 이미 Cliqz MyOffrz 제어판에서 활성화되었습니다." }, - "panel_detail_rewards_edge_text": { - "message": "Ghostery Rewards는 Edge 브라우저에서 지원되지 않습니다." - }, "panel_detail_rewards_loading": { "message": "Rewards 로딩 중" }, @@ -1649,9 +1646,6 @@ "hub_create_account_label_password_invalid_length": { "message": "8자에서 50자까지 사용할 수 있습니다." }, - "hub_create_account_checkbox_promotions": { - "message": "고스터리 브라우저의 업데이트와 프로모션 소식 받기" - }, "hub_create_account_already_have_account": { "message": "이미 Ghostery 계정이 있으십니까? " }, @@ -1942,7 +1936,7 @@ "content": "" }, "link_start": { - "content": "
" + "content": "
" } } }, @@ -2353,8 +2347,7 @@ "message": "Ghostery Midnight를 사용해 보세요" }, "seven_day_free_trial": { - "message": "7일 무료 평가판($14/월)", - "description": "Do not localize currency. Use the $14 USD amount. The second $ is needed to escape the special meaning of $" + "message": "7일 무료 평가판($14/월)" }, "full_coverage_protection_promise": { "message": "장치의 모든 브라우저 및 앱을 완전하게 보호하세요" @@ -2375,8 +2368,7 @@ "message": "무료 다운로드" }, "support_ghostery_for_2_instead": { - "message": "월 $2로 Ghostery를 후원합니다", - "description": "Do not localize currency. Use the $2 USD amount. The second $ is needed to escape the special meaning of $" + "message": "월 $2로 Ghostery를 후원합니다" }, "no_thanks_continue_with_basic": { "message": "괜찮습니다, Basic으로 계속 진행합니다" diff --git a/_locales/nl/messages.json b/_locales/nl/messages.json index 7da36c145..96f9535c3 100644 --- a/_locales/nl/messages.json +++ b/_locales/nl/messages.json @@ -727,9 +727,6 @@ "panel_detail_rewards_cliqz_text": { "message": "Functie al actief in het Cliqz MyOffrz controle paneel." }, - "panel_detail_rewards_edge_text": { - "message": "Ghostery Rewards wordt niet ondersteund in de Edge-browser" - }, "panel_detail_rewards_loading": { "message": "Rewards Laden..." }, @@ -1649,9 +1646,6 @@ "hub_create_account_label_password_invalid_length": { "message": "Gebruik tussen 8 en 50 karakters." }, - "hub_create_account_checkbox_promotions": { - "message": "Stuur me Ghostery updates & acties." - }, "hub_create_account_already_have_account": { "message": "Heb je al een Ghostery Account?" }, @@ -1942,7 +1936,7 @@ "content": "" }, "link_start": { - "content": "
" + "content": "
" } } }, @@ -2353,8 +2347,7 @@ "message": "Ghostery Midnight proberen" }, "seven_day_free_trial": { - "message": "Gratis proefperiode van 7 dagen ($14/mnd)", - "description": "Do not localize currency. Use the $14 USD amount. The second $ is needed to escape the special meaning of $" + "message": "Gratis proefperiode van 7 dagen ($14/mnd)" }, "full_coverage_protection_promise": { "message": "Profiteer van volledige dekking voor alle browsers en apps op je apparaat" @@ -2375,8 +2368,7 @@ "message": "Gratis downloaden" }, "support_ghostery_for_2_instead": { - "message": "Steun in plaats daarvan Ghostery voor $2/mnd", - "description": "Do not localize currency. Use the $2 USD amount. The second $ is needed to escape the special meaning of $" + "message": "Steun in plaats daarvan Ghostery voor $2/mnd" }, "no_thanks_continue_with_basic": { "message": "Nee bedankt, doorgaan met Basic" diff --git a/_locales/pl/messages.json b/_locales/pl/messages.json index 9ab678670..87a53e3d7 100644 --- a/_locales/pl/messages.json +++ b/_locales/pl/messages.json @@ -727,9 +727,6 @@ "panel_detail_rewards_cliqz_text": { "message": "Funkcja jest już aktywna w panelu sterowania Cliqz MyOffrz." }, - "panel_detail_rewards_edge_text": { - "message": "Funkcja Ghostery Rewards nie jest obsługiwana w przeglądarce Edge" - }, "panel_detail_rewards_loading": { "message": "Ładuję Rewards..." }, @@ -1649,9 +1646,6 @@ "hub_create_account_label_password_invalid_length": { "message": "Użyj od 8 do 50 znaków." }, - "hub_create_account_checkbox_promotions": { - "message": "Przesyłaj mi aktualizacje i promocje Ghostery." - }, "hub_create_account_already_have_account": { "message": "Masz już konto Ghostery?" }, @@ -1942,7 +1936,7 @@ "content": "" }, "link_start": { - "content": "
" + "content": "
" } } }, @@ -2353,8 +2347,7 @@ "message": "Wypróbuj Ghostery Midnight" }, "seven_day_free_trial": { - "message": "7-dniowy bezpłatny okres próbny ($14/mies)", - "description": "Do not localize currency. Use the $14 USD amount. The second $ is needed to escape the special meaning of $" + "message": "7-dniowy bezpłatny okres próbny ($14/mies)" }, "full_coverage_protection_promise": { "message": "Uzyskaj pełną ochronę we wszystkich przeglądarkach i aplikacjach na urządzeniu" @@ -2375,8 +2368,7 @@ "message": "Pobierz bezpłatnie" }, "support_ghostery_for_2_instead": { - "message": "Wesprzyj zamiast tego Ghostery za $2/mies", - "description": "Do not localize currency. Use the $2 USD amount. The second $ is needed to escape the special meaning of $" + "message": "Wesprzyj zamiast tego Ghostery za $2/mies" }, "no_thanks_continue_with_basic": { "message": "Nie, dziękuję. Kontynuuj z wersją podstawową" diff --git a/_locales/pt_BR/messages.json b/_locales/pt_BR/messages.json index 495c023c7..d90871ff9 100644 --- a/_locales/pt_BR/messages.json +++ b/_locales/pt_BR/messages.json @@ -727,9 +727,6 @@ "panel_detail_rewards_cliqz_text": { "message": "Funcionalidade já disponível no painel de controle Cliqz MyOffrz." }, - "panel_detail_rewards_edge_text": { - "message": "As Ghostery Rewards não são compatíveis com o navegador Edge" - }, "panel_detail_rewards_loading": { "message": "Carregando Rewards..." }, @@ -1649,9 +1646,6 @@ "hub_create_account_label_password_invalid_length": { "message": "Use entre 8 e 50 caracteres." }, - "hub_create_account_checkbox_promotions": { - "message": "Envie-me atualizações e promoções do Ghostery." - }, "hub_create_account_already_have_account": { "message": "Você já tem uma conta Ghostery?" }, @@ -1942,7 +1936,7 @@ "content": "" }, "link_start": { - "content": "
" + "content": "
" } } }, @@ -2353,8 +2347,7 @@ "message": "Experimente o Ghostery Midnight" }, "seven_day_free_trial": { - "message": "Avaliação gratuita de 7 dias ($14/mês)", - "description": "Do not localize currency. Use the $14 USD amount. The second $ is needed to escape the special meaning of $" + "message": "Avaliação gratuita de 7 dias ($14/mês)" }, "full_coverage_protection_promise": { "message": "Obtenha proteção completa para todos os navegadores e aplicativos do seu dispositivo" @@ -2375,8 +2368,7 @@ "message": "Baixe grátis" }, "support_ghostery_for_2_instead": { - "message": "Apoie o Ghostery por $2/mês", - "description": "Do not localize currency. Use the $2 USD amount. The second $ is needed to escape the special meaning of $" + "message": "Apoie o Ghostery por $2/mês" }, "no_thanks_continue_with_basic": { "message": "Não, obrigado. Continuar com o plano básico" diff --git a/_locales/ru/messages.json b/_locales/ru/messages.json index 9c3d34f6d..7327035e8 100644 --- a/_locales/ru/messages.json +++ b/_locales/ru/messages.json @@ -727,9 +727,6 @@ "panel_detail_rewards_cliqz_text": { "message": "Функция уже активирована на контрольной панели Cliqz MyOffrz." }, - "panel_detail_rewards_edge_text": { - "message": "Ghostery Rewards не поддерживается в браузере Edge" - }, "panel_detail_rewards_loading": { "message": "Загрузка Rewards…" }, @@ -1649,9 +1646,6 @@ "hub_create_account_label_password_invalid_length": { "message": "Используйте от 8 до 50 символов." }, - "hub_create_account_checkbox_promotions": { - "message": "Присылайте мне обновления и промо-акции Ghostery." - }, "hub_create_account_already_have_account": { "message": "Уже есть учетная запись Ghostery?" }, @@ -1942,7 +1936,7 @@ "content": "" }, "link_start": { - "content": "
" + "content": "
" } } }, @@ -2353,8 +2347,7 @@ "message": "Попробовать Ghostery Midnight" }, "seven_day_free_trial": { - "message": "7-дневная бесплатная бета-версия (14 $ в месяц)", - "description": "Do not localize currency. Use the $14 USD amount. The second $ is needed to escape the special meaning of $" + "message": "7-дневная бесплатная бета-версия (14 $ в месяц)" }, "full_coverage_protection_promise": { "message": "Получите полную защиту во всех браузерах и приложениях на вашем устройстве" @@ -2375,8 +2368,7 @@ "message": "Загрузить бесплатно" }, "support_ghostery_for_2_instead": { - "message": "Поддержка Ghostery за 2 $ вместо", - "description": "Do not localize currency. Use the $2 USD amount. The second $ is needed to escape the special meaning of $" + "message": "Поддержка Ghostery за 2 $ вместо" }, "no_thanks_continue_with_basic": { "message": "Нет, спасибо, продолжить с базовым" diff --git a/_locales/zh_CN/messages.json b/_locales/zh_CN/messages.json index 91177e8ff..a7fb72018 100644 --- a/_locales/zh_CN/messages.json +++ b/_locales/zh_CN/messages.json @@ -727,9 +727,6 @@ "panel_detail_rewards_cliqz_text": { "message": "Cliqz MyOffrz 控制面板中已激活此功能。" }, - "panel_detail_rewards_edge_text": { - "message": "Ghostery Rewards 不支持 Edge 浏览器" - }, "panel_detail_rewards_loading": { "message": "正在加载Rewards…" }, @@ -1649,9 +1646,6 @@ "hub_create_account_label_password_invalid_length": { "message": "请使用 8 到 50 个字符。" }, - "hub_create_account_checkbox_promotions": { - "message": "给我发送Ghostery动态和促销信息。" - }, "hub_create_account_already_have_account": { "message": "已经有 Ghostery 帐户?" }, @@ -1942,7 +1936,7 @@ "content": "" }, "link_start": { - "content": "
" + "content": "
" } } }, @@ -2353,8 +2347,7 @@ "message": "试用 Ghostery Midnight" }, "seven_day_free_trial": { - "message": "7 天免费试用($14/月)", - "description": "Do not localize currency. Use the $14 USD amount. The second $ is needed to escape the special meaning of $" + "message": "7 天免费试用($14/月)" }, "full_coverage_protection_promise": { "message": "全面保护设备中的所有浏览器和应用程序" @@ -2375,8 +2368,7 @@ "message": "免费下载" }, "support_ghostery_for_2_instead": { - "message": "支持 Ghostery($2/月)", - "description": "Do not localize currency. Use the $2 USD amount. The second $ is needed to escape the special meaning of $" + "message": "支持 Ghostery($2/月)" }, "no_thanks_continue_with_basic": { "message": "不了,谢谢,继续使用基础版" diff --git a/_locales/zh_TW/messages.json b/_locales/zh_TW/messages.json index 9371bfb4e..c6eb4913d 100644 --- a/_locales/zh_TW/messages.json +++ b/_locales/zh_TW/messages.json @@ -727,9 +727,6 @@ "panel_detail_rewards_cliqz_text": { "message": "Cliqz MyOffrz控制面板已啟動此功能。" }, - "panel_detail_rewards_edge_text": { - "message": "Ghostery Rewards 不支援 Edge 瀏覽器" - }, "panel_detail_rewards_loading": { "message": "正在加載Rewards…" }, @@ -1649,9 +1646,6 @@ "hub_create_account_label_password_invalid_length": { "message": "使用 8 至 50 個字符。" }, - "hub_create_account_checkbox_promotions": { - "message": "給我發送Ghostery更新和促銷。" - }, "hub_create_account_already_have_account": { "message": "已有一個Ghostery帳戶?" }, @@ -1942,7 +1936,7 @@ "content": "" }, "link_start": { - "content": "
" + "content": "
" } } }, @@ -2353,8 +2347,7 @@ "message": "試用 Ghostery Midnight" }, "seven_day_free_trial": { - "message": "7 天免費試用($14 / 月)", - "description": "Do not localize currency. Use the $14 USD amount. The second $ is needed to escape the special meaning of $" + "message": "7 天免費試用($14 / 月)" }, "full_coverage_protection_promise": { "message": "全面防護您裝置上的所有瀏覽器和應用程式" @@ -2375,8 +2368,7 @@ "message": "免費下載" }, "support_ghostery_for_2_instead": { - "message": "或以 $2 / 月來支持 Ghostery", - "description": "Do not localize currency. Use the $2 USD amount. The second $ is needed to escape the special meaning of $" + "message": "或以 $2 / 月來支持 Ghostery" }, "no_thanks_continue_with_basic": { "message": "不用了,謝謝,繼續使用基本功能" From be06d00b16dbfa22a880a91daa5bc776577ab184 Mon Sep 17 00:00:00 2001 From: Ben Date: Fri, 7 Feb 2020 19:17:00 -0500 Subject: [PATCH 11/20] Add regex and wildcard functionality to whitelist and blacklist --- .../components/Settings/TrustAndRestrict.jsx | 5 ++-- src/classes/Policy.js | 25 +++++++++++++++++-- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/app/panel/components/Settings/TrustAndRestrict.jsx b/app/panel/components/Settings/TrustAndRestrict.jsx index 53141842a..467af0d08 100644 --- a/app/panel/components/Settings/TrustAndRestrict.jsx +++ b/app/panel/components/Settings/TrustAndRestrict.jsx @@ -86,9 +86,10 @@ class TrustAndRestrict extends React.Component { /** * Implement adding site to the list of whitelisted or blacklisted sites * This routine valides entered url and checks if the entered url is a duplicate, or - * if it has been alreday added to the opposite list. Displays appropriate warnings. + * if it has been already added to the opposite list. Displays appropriate warnings. */ addSite() { + // TODO: Implement paygating, use this regex for validating free users who don't have regex/wildcard ability // from node-validator const isValidUrlRegex = /^(?!mailto:)(?:(?:https?|ftp):\/\/)?(?:\S+(?::\S*)?@)?(?:(?:(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))|localhost)(?::\d{2,5})?(?:\/[^\s]*)?$/i; let pageHost; @@ -121,7 +122,7 @@ class TrustAndRestrict extends React.Component { pageHost = pageHost.toLowerCase().replace(/^(http[s]?:\/\/)?(www\.)?/, ''); // Check for Validity - if (pageHost.length >= 2083 || !isValidUrlRegex.test(pageHost)) { + if (pageHost.length >= 2083) { this.showWarning(t('white_black_list_error_invalid_url')); return; } diff --git a/src/classes/Policy.js b/src/classes/Policy.js index 547784d42..4b4ec5661 100644 --- a/src/classes/Policy.js +++ b/src/classes/Policy.js @@ -71,7 +71,8 @@ class Policy { // TODO: speed up for (let i = 0; i < num_sites; i++) { // TODO match from the beginning of the string to avoid false matches (somewhere in the querystring for instance) - if (replacedUrl === sites[i]) { + if (replacedUrl === sites[i] + || this.matchesWildcardOrRegex(replacedUrl, sites[i])) { return sites[i]; } } @@ -119,7 +120,8 @@ class Policy { // TODO: speed up for (let i = 0; i < num_sites; i++) { // TODO match from the beginning of the string to avoid false matches (somewhere in the querystring for instance) - if (replacedUrl === sites[i]) { + if (replacedUrl === sites[i] + || this.matchesWildcardOrRegex(replacedUrl, sites[i])) { return sites[i]; } } @@ -174,6 +176,25 @@ class Policy { } return { block: false, reason: allowedOnce ? BLOCK_REASON_C2P_ALLOWED_ONCE : BLOCK_REASON_GLOBAL_UNBLOCKED }; } + + /** + * Check given url against pattern which might be a regex, or a wildcard + * @param {string} url site url + * @param {string} pattern regex pattern + * @return {boolean} + */ + matchesWildcardOrRegex(url, pattern) { + let regex; + try { + regex = RegExp(pattern); + if (regex.test(url)) { return true; } + } catch { + const wildcardPattern = pattern.replace(/\*/g, '.*'); + regex = RegExp(wildcardPattern); + if (regex.test(url)) { return true; } + } + return false; + } } export default Policy; From 863f2258e14db83b18bcbcc46c90c8bd95f0ec1c Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 10 Feb 2020 09:50:18 -0500 Subject: [PATCH 12/20] Escape inputted regex and add error handling --- src/classes/Policy.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/classes/Policy.js b/src/classes/Policy.js index 4b4ec5661..a8820b529 100644 --- a/src/classes/Policy.js +++ b/src/classes/Policy.js @@ -15,6 +15,7 @@ /* eslint no-param-reassign: 0 */ +import escapeStringRegexp from 'escape-string-regexp'; import c2pDb from './Click2PlayDb'; import conf from './Conf'; import globals from './Globals'; @@ -184,14 +185,18 @@ class Policy { * @return {boolean} */ matchesWildcardOrRegex(url, pattern) { - let regex; + let regex = escapeStringRegexp(pattern); try { regex = RegExp(pattern); if (regex.test(url)) { return true; } } catch { const wildcardPattern = pattern.replace(/\*/g, '.*'); - regex = RegExp(wildcardPattern); - if (regex.test(url)) { return true; } + try { + regex = RegExp(wildcardPattern); + if (regex.test(url)) { return true; } + } catch { + // Invalid pattern + } } return false; } From 032cbc6d3120b0593470a87f57b5a536e4664ca2 Mon Sep 17 00:00:00 2001 From: Ben Date: Mon, 10 Feb 2020 10:01:53 -0500 Subject: [PATCH 13/20] Add escape-string-regexp dependency --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index b8f162cdb..f940f764a 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,7 @@ "browser-core": "https://github.com/cliqz-oss/browser-core/releases/download/v7.43.1/browser-core-7.43.1.tgz", "classnames": "^2.2.5", "d3": "^5.15.0", + "escape-string-regexp": "^2.0.0", "foundation-sites": "^6.6.1", "history": "^4.10.1", "json-api-normalizer": "^0.4.16", From 8a6533c0776c7446d10e7f7135a8e01f45d21760 Mon Sep 17 00:00:00 2001 From: Ben Date: Tue, 11 Feb 2020 13:42:36 -0500 Subject: [PATCH 14/20] Refactor matchesWildcardOrRegex and remove escape-strings-regex dependency --- .../components/Settings/TrustAndRestrict.jsx | 3 --- package.json | 1 - src/classes/Policy.js | 26 ++++++++----------- 3 files changed, 11 insertions(+), 19 deletions(-) diff --git a/app/panel/components/Settings/TrustAndRestrict.jsx b/app/panel/components/Settings/TrustAndRestrict.jsx index 467af0d08..7bb3cce96 100644 --- a/app/panel/components/Settings/TrustAndRestrict.jsx +++ b/app/panel/components/Settings/TrustAndRestrict.jsx @@ -89,9 +89,6 @@ class TrustAndRestrict extends React.Component { * if it has been already added to the opposite list. Displays appropriate warnings. */ addSite() { - // TODO: Implement paygating, use this regex for validating free users who don't have regex/wildcard ability - // from node-validator - const isValidUrlRegex = /^(?!mailto:)(?:(?:https?|ftp):\/\/)?(?:\S+(?::\S*)?@)?(?:(?:(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))|localhost)(?::\d{2,5})?(?:\/[^\s]*)?$/i; let pageHost; let list; let listType; diff --git a/package.json b/package.json index f940f764a..b8f162cdb 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,6 @@ "browser-core": "https://github.com/cliqz-oss/browser-core/releases/download/v7.43.1/browser-core-7.43.1.tgz", "classnames": "^2.2.5", "d3": "^5.15.0", - "escape-string-regexp": "^2.0.0", "foundation-sites": "^6.6.1", "history": "^4.10.1", "json-api-normalizer": "^0.4.16", diff --git a/src/classes/Policy.js b/src/classes/Policy.js index a8820b529..aa58c7503 100644 --- a/src/classes/Policy.js +++ b/src/classes/Policy.js @@ -14,8 +14,6 @@ */ /* eslint no-param-reassign: 0 */ - -import escapeStringRegexp from 'escape-string-regexp'; import c2pDb from './Click2PlayDb'; import conf from './Conf'; import globals from './Globals'; @@ -185,19 +183,17 @@ class Policy { * @return {boolean} */ matchesWildcardOrRegex(url, pattern) { - let regex = escapeStringRegexp(pattern); - try { - regex = RegExp(pattern); - if (regex.test(url)) { return true; } - } catch { - const wildcardPattern = pattern.replace(/\*/g, '.*'); - try { - regex = RegExp(wildcardPattern); - if (regex.test(url)) { return true; } - } catch { - // Invalid pattern - } - } + const escapedPattern = pattern.replace(/[|\\{}()[\]^$+*?.-]/g, '\\$&'); + + // Input string might be a regex + let regex = RegExp(escapedPattern); + if (regex.test(url)) { return true; } + + // or a wildcard + const wildcardPattern = escapedPattern.replace(/\*/g, '.*'); + regex = RegExp(wildcardPattern); + if (regex.test(url)) { return true; } + return false; } } From 5e6e3c28461a8cba2db4c15572f479c933631a71 Mon Sep 17 00:00:00 2001 From: Ben Date: Tue, 11 Feb 2020 13:59:55 -0500 Subject: [PATCH 15/20] Make regex variables const --- src/classes/Policy.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/classes/Policy.js b/src/classes/Policy.js index aa58c7503..1e26d0063 100644 --- a/src/classes/Policy.js +++ b/src/classes/Policy.js @@ -186,13 +186,13 @@ class Policy { const escapedPattern = pattern.replace(/[|\\{}()[\]^$+*?.-]/g, '\\$&'); // Input string might be a regex - let regex = RegExp(escapedPattern); + const regex = RegExp(escapedPattern); if (regex.test(url)) { return true; } // or a wildcard const wildcardPattern = escapedPattern.replace(/\*/g, '.*'); - regex = RegExp(wildcardPattern); - if (regex.test(url)) { return true; } + const wildcardRegex = RegExp(wildcardPattern); + if (wildcardRegex.test(url)) { return true; } return false; } From 16b89a7b8bba9be5f73c5102e436211a6588c3aa Mon Sep 17 00:00:00 2001 From: Ben Date: Tue, 18 Feb 2020 15:00:21 -0500 Subject: [PATCH 16/20] Prevent ReDoS attack. Validate url, wildcard or regex. Update error messages --- _locales/en/messages.json | 4 +- .../components/Settings/TrustAndRestrict.jsx | 38 ++++++++++++++++++- package.json | 1 + src/classes/Policy.js | 14 +++---- yarn.lock | 12 ++++++ 5 files changed, 59 insertions(+), 10 deletions(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 0e5300f9b..9adb50773 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -802,7 +802,7 @@ "message": "unblocked" }, "white_black_list_error_invalid_url": { - "message": "Please enter a valid URL." + "message": "Please enter a valid URL, regex, or wildcard" }, "whitelist_error_blacklist_url": { "message": "This site has been removed from your Restricted Sites list and added to your Trusted Sites list." @@ -1058,7 +1058,7 @@ "message": "Trusted Sites" }, "settings_sites_placeholder": { - "message": "example.com" + "message": "example.com (wildcards/regex supported)" }, "settings_restricted_sites": { "message": "Restricted Sites" diff --git a/app/panel/components/Settings/TrustAndRestrict.jsx b/app/panel/components/Settings/TrustAndRestrict.jsx index 7bb3cce96..76996f5e7 100644 --- a/app/panel/components/Settings/TrustAndRestrict.jsx +++ b/app/panel/components/Settings/TrustAndRestrict.jsx @@ -12,6 +12,7 @@ */ import React from 'react'; +import safe from 'safe-regex'; import Sites from './Sites'; /** * @class Implement Trust and Restrict subview presenting the lists @@ -119,10 +120,12 @@ class TrustAndRestrict extends React.Component { pageHost = pageHost.toLowerCase().replace(/^(http[s]?:\/\/)?(www\.)?/, ''); // Check for Validity - if (pageHost.length >= 2083) { + if (pageHost.length >= 2083 + || !this.isValidUrlWildcardOrRegex(pageHost)) { this.showWarning(t('white_black_list_error_invalid_url')); return; } + // Check for Duplicates if (list.includes(pageHost)) { this.showWarning(duplicateWarning); @@ -137,6 +140,39 @@ class TrustAndRestrict extends React.Component { this.props.actions.updateSitePolicy({ type: listType, pageHost }); } + isValidUrlWildcardOrRegex(pageHost) { + // Check for valid URL + // from node-validator + const isValidUrlRegex = /^(?!mailto:)(?:(?:https?|ftp):\/\/)?(?:\S+(?::\S*)?@)?(?:(?:(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))|localhost)(?::\d{2,5})?(?:\/[^\s]*)?$/i; + if (isValidUrlRegex.test(pageHost)) return true; + + + // Check for valid wildcard + const escapedPattern = pageHost.replace(/[|\\{}()[\]^$+*?.-]/g, '\\$&'); + const wildcardPattern = escapedPattern.replace(/\*/g, '.*'); + let isValidWildcard = true; + try { + // eslint-disable-next-line + new RegExp(wildcardPattern); + } catch { + isValidWildcard = false; + } + + if (isValidWildcard) return true; + + // Prevent ReDoS attack + if (!safe(pageHost)) return false; + + // Check for valid regex + try { + // eslint-disable-next-line + new RegExp(pageHost); + } catch { + return false; + } + return false; + } + /** * Save current warning in state. * @param {string} warning warning to save diff --git a/package.json b/package.json index b8f162cdb..2e7574396 100644 --- a/package.json +++ b/package.json @@ -64,6 +64,7 @@ "redux-object": "^0.5.10", "redux-thunk": "^2.2.0", "rsvp": "^4.8.5", + "safe-regex": "^2.1.1", "spanan": "^2.0.0", "ua-parser-js": "^0.7.21", "underscore": "^1.9.2", diff --git a/src/classes/Policy.js b/src/classes/Policy.js index 1e26d0063..2afb08e52 100644 --- a/src/classes/Policy.js +++ b/src/classes/Policy.js @@ -177,23 +177,23 @@ class Policy { } /** - * Check given url against pattern which might be a regex, or a wildcard + * Check given url against pattern which might be a wildcard, or a regex * @param {string} url site url * @param {string} pattern regex pattern * @return {boolean} */ matchesWildcardOrRegex(url, pattern) { + // Input string might be a wildcard const escapedPattern = pattern.replace(/[|\\{}()[\]^$+*?.-]/g, '\\$&'); - - // Input string might be a regex - const regex = RegExp(escapedPattern); - if (regex.test(url)) { return true; } - - // or a wildcard const wildcardPattern = escapedPattern.replace(/\*/g, '.*'); const wildcardRegex = RegExp(wildcardPattern); + if (wildcardRegex.test(url)) { return true; } + // or a regex + const regex = RegExp(pattern); + if (regex.test(url)) { return true; } + return false; } } diff --git a/yarn.lock b/yarn.lock index 322e594e1..d7e6b0573 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7086,6 +7086,11 @@ regexp-quote@0.0.0: resolved "https://registry.yarnpkg.com/regexp-quote/-/regexp-quote-0.0.0.tgz#1e0f4650c862dcbfed54fd42b148e9bb1721fcf2" integrity sha1-Hg9GUMhi3L/tVP1CsUjpuxch/PI= +regexp-tree@~0.1.1: + version "0.1.19" + resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.19.tgz#9326e91d8d1d23298dd33a78cf5e788f57cdc359" + integrity sha512-mVeVLF/qg5qFbZSW0f7pXbuVX73dKIjuhOyC2JLKxzmpya75O4qLcvI9j0jp31Iz7IAkEVHa1UErDCAqaLKo5A== + regexp.prototype.flags@^1.2.0, regexp.prototype.flags@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz#7aba89b3c13a64509dabcf3ca8d9fbb9bdf5cb75" @@ -7373,6 +7378,13 @@ safe-regex@^1.1.0: dependencies: ret "~0.1.10" +safe-regex@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-2.1.1.tgz#f7128f00d056e2fe5c11e81a1324dd974aadced2" + integrity sha512-rx+x8AMzKb5Q5lQ95Zoi6ZbJqwCLkqi3XuJXp5P3rT8OEc6sZCJG5AE5dU3lsgRr/F4Bs31jSlVN+j5KrsGu9A== + dependencies: + regexp-tree "~0.1.1" + "safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" From 1c63fcbe5dc5c4675b8a1eec2115f4f8f9934a20 Mon Sep 17 00:00:00 2001 From: Ben Date: Tue, 18 Feb 2020 15:02:58 -0500 Subject: [PATCH 17/20] Remove newline --- app/panel/components/Settings/TrustAndRestrict.jsx | 1 - 1 file changed, 1 deletion(-) diff --git a/app/panel/components/Settings/TrustAndRestrict.jsx b/app/panel/components/Settings/TrustAndRestrict.jsx index 76996f5e7..e98786b90 100644 --- a/app/panel/components/Settings/TrustAndRestrict.jsx +++ b/app/panel/components/Settings/TrustAndRestrict.jsx @@ -146,7 +146,6 @@ class TrustAndRestrict extends React.Component { const isValidUrlRegex = /^(?!mailto:)(?:(?:https?|ftp):\/\/)?(?:\S+(?::\S*)?@)?(?:(?:(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))|localhost)(?::\d{2,5})?(?:\/[^\s]*)?$/i; if (isValidUrlRegex.test(pageHost)) return true; - // Check for valid wildcard const escapedPattern = pageHost.replace(/[|\\{}()[\]^$+*?.-]/g, '\\$&'); const wildcardPattern = escapedPattern.replace(/\*/g, '.*'); From d35ef221137038f2d692df1f12f2d7d5f8bfa94b Mon Sep 17 00:00:00 2001 From: Ben Date: Tue, 18 Feb 2020 15:09:29 -0500 Subject: [PATCH 18/20] Add period to error text --- _locales/en/messages.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 9adb50773..6c3bada36 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -802,7 +802,7 @@ "message": "unblocked" }, "white_black_list_error_invalid_url": { - "message": "Please enter a valid URL, regex, or wildcard" + "message": "Please enter a valid URL, regex, or wildcard." }, "whitelist_error_blacklist_url": { "message": "This site has been removed from your Restricted Sites list and added to your Trusted Sites list." From 6fdf07b92b93d5d60b36d803804f10d219efd82d Mon Sep 17 00:00:00 2001 From: Ben Date: Wed, 19 Feb 2020 15:28:53 -0500 Subject: [PATCH 19/20] Create unit and snapshot test for isValidUrlWildcard function --- .../components/Settings/TrustAndRestrict.jsx | 6 +- .../Settings/__tests__/TrustAndRestrict.jsx | 91 +++++++++ .../__snapshots__/TrustAndRestrict.jsx.snap | 119 +++++++++++ package.json | 1 + yarn.lock | 190 +++++++++++++++++- 5 files changed, 398 insertions(+), 9 deletions(-) create mode 100644 app/panel/components/Settings/__tests__/TrustAndRestrict.jsx create mode 100644 app/panel/components/Settings/__tests__/__snapshots__/TrustAndRestrict.jsx.snap diff --git a/app/panel/components/Settings/TrustAndRestrict.jsx b/app/panel/components/Settings/TrustAndRestrict.jsx index e98786b90..c2193b093 100644 --- a/app/panel/components/Settings/TrustAndRestrict.jsx +++ b/app/panel/components/Settings/TrustAndRestrict.jsx @@ -163,13 +163,15 @@ class TrustAndRestrict extends React.Component { if (!safe(pageHost)) return false; // Check for valid regex + let isValidRegex = true; try { // eslint-disable-next-line new RegExp(pageHost); } catch { - return false; + isValidRegex = false; } - return false; + + return isValidRegex; } /** diff --git a/app/panel/components/Settings/__tests__/TrustAndRestrict.jsx b/app/panel/components/Settings/__tests__/TrustAndRestrict.jsx new file mode 100644 index 000000000..b939c294a --- /dev/null +++ b/app/panel/components/Settings/__tests__/TrustAndRestrict.jsx @@ -0,0 +1,91 @@ +/** + * Rewards Test Component + * + * Ghostery Browser Extension + * https://www.ghostery.com/ + * + * Copyright 2019 Ghostery, Inc. All rights reserved. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0 + */ + +import React from 'react'; +import renderer from 'react-test-renderer'; +import { shallow } from 'enzyme'; +import { when } from 'jest-when'; +import TrustAndRestrict from '../TrustAndRestrict'; + +describe('app/panel/components/Settings/TrustAndRestrict', () => { + describe('Snapshot test with react-test-renderer', () => { + test('Testing TrustAndRestrict is rendering', () => { + const wrapper = renderer.create( + + ).toJSON(); + expect(wrapper).toMatchSnapshot(); + }); + }); +}); + +describe('app/panel/components/Settings/', () => { + test('isValidUrlWildcardOrRegex should return true with url entered', () => { + const wrapper = shallow(); + const input = 'ghostery.com'; + + const fn = jest.spyOn(wrapper.instance(), 'isValidUrlWildcardOrRegex'); + when(fn) + .calledWith(input) + .mockReturnValue(true); + const returnValue = wrapper.instance().isValidUrlWildcardOrRegex(input); + expect(returnValue).toBe(true); + }); + + test('isValidUrlWildcardOrRegex should return true with wildcard URL entered', () => { + const wrapper = shallow(); + const input = 'developer.*.org'; + + const fn = jest.spyOn(wrapper.instance(), 'isValidUrlWildcardOrRegex'); + when(fn) + .calledWith(input) + .mockReturnValue(true); + const returnValue = wrapper.instance().isValidUrlWildcardOrRegex(input); + expect(returnValue).toBe(true); + }); + + test('isValidUrlWildcardOrRegex should return true with regex URL entered', () => { + const wrapper = shallow(); + const input = '[ds]eveloper.mozilla.org'; + + const fn = jest.spyOn(wrapper.instance(), 'isValidUrlWildcardOrRegex'); + when(fn) + .calledWith(input) + .mockReturnValue(true); + const returnValue = wrapper.instance().isValidUrlWildcardOrRegex(input); + expect(returnValue).toBe(true); + }); + + test('isValidUrlWildcardOrRegex should return false with unsafe regex entered', () => { + const wrapper = shallow(); + const input = '/^(\w+\s?)*$/'; + + const fn = jest.spyOn(wrapper.instance(), 'isValidUrlWildcardOrRegex'); + when(fn) + .calledWith(input) + .mockReturnValue(false); + const returnValue = wrapper.instance().isValidUrlWildcardOrRegex(input); + expect(returnValue).toBe(false); + }); + + test('isValidUrlWildcardOrRegex should return false with incorrect regex format entered', () => { + const wrapper = shallow(); + const input = '[.ghostery.com'; + + const fn = jest.spyOn(wrapper.instance(), 'isValidUrlWildcardOrRegex'); + when(fn) + .calledWith(input) + .mockReturnValue(false); + const returnValue = wrapper.instance().isValidUrlWildcardOrRegex(input); + expect(returnValue).toBe(false); + }); +}); diff --git a/app/panel/components/Settings/__tests__/__snapshots__/TrustAndRestrict.jsx.snap b/app/panel/components/Settings/__tests__/__snapshots__/TrustAndRestrict.jsx.snap new file mode 100644 index 000000000..0403041cf --- /dev/null +++ b/app/panel/components/Settings/__tests__/__snapshots__/TrustAndRestrict.jsx.snap @@ -0,0 +1,119 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`app/panel/components/Settings/TrustAndRestrict Snapshot test with react-test-renderer Testing TrustAndRestrict is rendering 1`] = ` +
+
+
+

+ settings_trusted_restricted_sites +

+
+
+
+
+ + settings_trusted_sites + +
+
+ + settings_restricted_sites + +
+
+
+
+
+
+ +
+
+
+ + settings_trusted_sites_description + +
+
+ +
+
+
+
+
+
+
+
+ +
+
+
+ + settings_restricted_sites_description + +
+
+ +
+
+
+
+
+`; diff --git a/package.json b/package.json index 2e7574396..cb0ea7b71 100644 --- a/package.json +++ b/package.json @@ -92,6 +92,7 @@ "eslint-plugin-react": "^7.18.3", "fs-extra": "^8.1.0", "jest": "^25.1.0", + "jest-when": "^2.7.0", "jsdoc": "^3.6.3", "jsonfile": "^5.0.0", "license-checker": "^25.0.1", diff --git a/yarn.lock b/yarn.lock index d7e6b0573..e1f320711 100644 --- a/yarn.lock +++ b/yarn.lock @@ -396,6 +396,15 @@ resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.2.tgz#26520bf09abe4a5644cd5414e37125a8954241dd" integrity sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw== +"@jest/console@^24.9.0": + version "24.9.0" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-24.9.0.tgz#79b1bc06fb74a8cfb01cbdedf945584b1b9707f0" + integrity sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ== + dependencies: + "@jest/source-map" "^24.9.0" + chalk "^2.0.1" + slash "^2.0.0" + "@jest/console@^25.1.0": version "25.1.0" resolved "https://registry.yarnpkg.com/@jest/console/-/console-25.1.0.tgz#1fc765d44a1e11aec5029c08e798246bd37075ab" @@ -493,6 +502,15 @@ optionalDependencies: node-notifier "^6.0.0" +"@jest/source-map@^24.9.0": + version "24.9.0" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-24.9.0.tgz#0e263a94430be4b41da683ccc1e6bffe2a191714" + integrity sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg== + dependencies: + callsites "^3.0.0" + graceful-fs "^4.1.15" + source-map "^0.6.0" + "@jest/source-map@^25.1.0": version "25.1.0" resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-25.1.0.tgz#b012e6c469ccdbc379413f5c1b1ffb7ba7034fb0" @@ -502,6 +520,15 @@ graceful-fs "^4.2.3" source-map "^0.6.0" +"@jest/test-result@^24.9.0": + version "24.9.0" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-24.9.0.tgz#11796e8aa9dbf88ea025757b3152595ad06ba0ca" + integrity sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA== + dependencies: + "@jest/console" "^24.9.0" + "@jest/types" "^24.9.0" + "@types/istanbul-lib-coverage" "^2.0.0" + "@jest/test-result@^25.1.0": version "25.1.0" resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-25.1.0.tgz#847af2972c1df9822a8200457e64be4ff62821f7" @@ -545,6 +572,15 @@ source-map "^0.6.1" write-file-atomic "^3.0.0" +"@jest/types@^24.9.0": + version "24.9.0" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-24.9.0.tgz#63cb26cb7500d069e5a389441a7c6ab5e909fc59" + integrity sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^1.1.1" + "@types/yargs" "^13.0.0" + "@jest/types@^25.1.0": version "25.1.0" resolved "https://registry.yarnpkg.com/@jest/types/-/types-25.1.0.tgz#b26831916f0d7c381e11dbb5e103a72aed1b4395" @@ -743,6 +779,13 @@ resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-15.0.0.tgz#cb3f9f741869e20cce330ffbeb9271590483882d" integrity sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw== +"@types/yargs@^13.0.0": + version "13.0.8" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-13.0.8.tgz#a38c22def2f1c2068f8971acb3ea734eb3c64a99" + integrity sha512-XAvHLwG7UQ+8M4caKIH0ZozIOYay5fQkAgyIXegXT9jPtdIGdhga+sUEdAr1CiG46aB+c64xQEYyEzlwWVTNzA== + dependencies: + "@types/yargs-parser" "*" + "@types/yargs@^15.0.0": version "15.0.2" resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.2.tgz#0bf292a0369493cee030e2e4f4ff84f5982b028d" @@ -1013,7 +1056,7 @@ ansi-regex@^3.0.0: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= -ansi-regex@^4.1.0: +ansi-regex@^4.0.0, ansi-regex@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== @@ -1593,6 +1636,16 @@ builtin-status-codes@^3.0.0: resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= +bunyan@^1.8.12: + version "1.8.12" + resolved "https://registry.yarnpkg.com/bunyan/-/bunyan-1.8.12.tgz#f150f0f6748abdd72aeae84f04403be2ef113797" + integrity sha1-8VDw9nSKvdcq6uhPBEA74u8RN5c= + optionalDependencies: + dtrace-provider "~0.8" + moment "^2.10.6" + mv "~2" + safe-json-stringify "~1" + cacache@^12.0.2: version "12.0.3" resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.3.tgz#be99abba4e1bf5df461cd5a2c1071fc432573390" @@ -1676,7 +1729,7 @@ catharsis@^0.8.11: dependencies: lodash "^4.17.14" -chalk@2.4.2, chalk@^2.0.0, chalk@^2.1.0, chalk@^2.4.1, chalk@^2.4.2: +chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -2590,6 +2643,11 @@ dezalgo@^1.0.0: asap "^2.0.0" wrappy "1" +diff-sequences@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-24.9.0.tgz#5715d6244e2aa65f48bba0bc972db0b0b11e95b5" + integrity sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew== + diff-sequences@^25.1.0: version "25.1.0" resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-25.1.0.tgz#fd29a46f1c913fd66c22645dc75bffbe43051f32" @@ -2718,6 +2776,13 @@ domutils@^2.0.0: domelementtype "^2.0.1" domhandler "^3.0.0" +dtrace-provider@~0.8: + version "0.8.8" + resolved "https://registry.yarnpkg.com/dtrace-provider/-/dtrace-provider-0.8.8.tgz#2996d5490c37e1347be263b423ed7b297fb0d97e" + integrity sha512-b7Z7cNtHPhH9EJhNNbbeqTcXB8LGFFZhq1PGgEvpeHlzd36bhbdTWoE/Ba/YguqpBSlAPKnARWhVlhunCMwfxg== + dependencies: + nan "^2.14.0" + duplexify@^3.4.2, duplexify@^3.6.0: version "3.7.1" resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" @@ -3211,6 +3276,18 @@ expand-tilde@^2.0.0, expand-tilde@^2.0.2: dependencies: homedir-polyfill "^1.0.1" +expect@^24.8.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/expect/-/expect-24.9.0.tgz#b75165b4817074fa4a157794f46fe9f1ba15b6ca" + integrity sha512-wvVAx8XIol3Z5m9zvZXiyZOQ+sRJqNTIm6sGjdWlaZIeupQGO3WbYI+15D/AmEwZywL6wtJkbAbJtzkOfBuR0Q== + dependencies: + "@jest/types" "^24.9.0" + ansi-styles "^3.2.0" + jest-get-type "^24.9.0" + jest-matcher-utils "^24.9.0" + jest-message-util "^24.9.0" + jest-regex-util "^24.9.0" + expect@^25.1.0: version "25.1.0" resolved "https://registry.yarnpkg.com/expect/-/expect-25.1.0.tgz#7e8d7b06a53f7d66ec927278db3304254ee683ee" @@ -3637,6 +3714,17 @@ glob-parent@^5.0.0: dependencies: is-glob "^4.0.1" +glob@^6.0.1: + version "6.0.4" + resolved "https://registry.yarnpkg.com/glob/-/glob-6.0.4.tgz#0f08860f6a155127b2fadd4f9ce24b1aab6e4d22" + integrity sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI= + dependencies: + inflight "^1.0.4" + inherits "2" + minimatch "2 || 3" + once "^1.3.0" + path-is-absolute "^1.0.0" + glob@^7.0.0, glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@~7.1.1: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" @@ -4595,6 +4683,16 @@ jest-config@^25.1.0: pretty-format "^25.1.0" realpath-native "^1.1.0" +jest-diff@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-24.9.0.tgz#931b7d0d5778a1baf7452cb816e325e3724055da" + integrity sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ== + dependencies: + chalk "^2.0.1" + diff-sequences "^24.9.0" + jest-get-type "^24.9.0" + pretty-format "^24.9.0" + jest-diff@^25.1.0: version "25.1.0" resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-25.1.0.tgz#58b827e63edea1bc80c1de952b80cec9ac50e1ad" @@ -4646,6 +4744,11 @@ jest-environment-node@^25.1.0: jest-mock "^25.1.0" jest-util "^25.1.0" +jest-get-type@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-24.9.0.tgz#1684a0c8a50f2e4901b6644ae861f579eed2ef0e" + integrity sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q== + jest-get-type@^25.1.0: version "25.1.0" resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-25.1.0.tgz#1cfe5fc34f148dc3a8a3b7275f6b9ce9e2e8a876" @@ -4700,6 +4803,16 @@ jest-leak-detector@^25.1.0: jest-get-type "^25.1.0" pretty-format "^25.1.0" +jest-matcher-utils@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-24.9.0.tgz#f5b3661d5e628dffe6dd65251dfdae0e87c3a073" + integrity sha512-OZz2IXsu6eaiMAwe67c1T+5tUAtQyQx27/EMEkbFAGiw52tB9em+uGbzpcgYVpA8wl0hlxKPZxrly4CXU/GjHA== + dependencies: + chalk "^2.0.1" + jest-diff "^24.9.0" + jest-get-type "^24.9.0" + pretty-format "^24.9.0" + jest-matcher-utils@^25.1.0: version "25.1.0" resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-25.1.0.tgz#fa5996c45c7193a3c24e73066fc14acdee020220" @@ -4710,6 +4823,20 @@ jest-matcher-utils@^25.1.0: jest-get-type "^25.1.0" pretty-format "^25.1.0" +jest-message-util@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-24.9.0.tgz#527f54a1e380f5e202a8d1149b0ec872f43119e3" + integrity sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw== + dependencies: + "@babel/code-frame" "^7.0.0" + "@jest/test-result" "^24.9.0" + "@jest/types" "^24.9.0" + "@types/stack-utils" "^1.0.1" + chalk "^2.0.1" + micromatch "^3.1.10" + slash "^2.0.0" + stack-utils "^1.0.1" + jest-message-util@^25.1.0: version "25.1.0" resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-25.1.0.tgz#702a9a5cb05c144b9aa73f06e17faa219389845e" @@ -4736,6 +4863,11 @@ jest-pnp-resolver@^1.2.1: resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.1.tgz#ecdae604c077a7fbc70defb6d517c3c1c898923a" integrity sha512-pgFw2tm54fzgYvc/OHrnysABEObZCUNFnhjoRjaVOCN8NYc032/gVjPaHD4Aq6ApkSieWtfKAFQtmDKAmhupnQ== +jest-regex-util@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-24.9.0.tgz#c13fb3380bde22bf6575432c493ea8fe37965636" + integrity sha512-05Cmb6CuxaA+Ys6fjr3PhvV3bGQmO+2p2La4hFbU+W5uOc479f7FdLXUWXw4pYMAhhSZIuKHwSXSu6CsSBAXQA== + jest-regex-util@^25.1.0: version "25.1.0" resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-25.1.0.tgz#efaf75914267741838e01de24da07b2192d16d87" @@ -4875,6 +5007,14 @@ jest-watcher@^25.1.0: jest-util "^25.1.0" string-length "^3.1.0" +jest-when@^2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/jest-when/-/jest-when-2.7.0.tgz#9549185ae8847b47d5d40262f1c59a5143e89a0c" + integrity sha512-psU0pXdomBORY9TGuSut/k8vViVki9l92WggL0m5/Lk8zTrDYtcCpPIFdZQDKqXvmW5Jzoh7SCsLKITvBJ0jyQ== + dependencies: + bunyan "^1.8.12" + expect "^24.8.0" + jest-worker@^25.1.0: version "25.1.0" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-25.1.0.tgz#75d038bad6fdf58eba0d2ec1835856c497e3907a" @@ -5576,7 +5716,7 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= -minimatch@^3.0.4, minimatch@~3.0.2: +"minimatch@2 || 3", minimatch@^3.0.4, minimatch@~3.0.2: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== @@ -5629,7 +5769,7 @@ mkdirp@0.5.1, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.1: dependencies: minimist "0.0.8" -moment@^2.19.1, moment@^2.22.2: +moment@^2.10.6, moment@^2.19.1, moment@^2.22.2: version "2.24.0" resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b" integrity sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg== @@ -5666,7 +5806,16 @@ mute-stream@0.0.8: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== -nan@^2.12.1, nan@^2.13.2: +mv@~2: + version "2.1.1" + resolved "https://registry.yarnpkg.com/mv/-/mv-2.1.1.tgz#ae6ce0d6f6d5e0a4f7d893798d03c1ea9559b6a2" + integrity sha1-rmzg1vbV4KT32JN5jQPB6pVZtqI= + dependencies: + mkdirp "~0.5.1" + ncp "~2.0.0" + rimraf "~2.4.0" + +nan@^2.12.1, nan@^2.13.2, nan@^2.14.0: version "2.14.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg== @@ -5693,7 +5842,7 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= -ncp@2.0.0: +ncp@2.0.0, ncp@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ncp/-/ncp-2.0.0.tgz#195a21d6c46e361d2fb1281ba38b91e9df7bdbb3" integrity sha1-GVoh1sRuNh0vsSgbo4uR6d9727M= @@ -6524,6 +6673,16 @@ prepend-http@^1.0.0: resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= +pretty-format@^24.9.0: + version "24.9.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.9.0.tgz#12fac31b37019a4eea3c11aa9a959eb7628aa7c9" + integrity sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA== + dependencies: + "@jest/types" "^24.9.0" + ansi-regex "^4.0.0" + ansi-styles "^3.2.0" + react-is "^16.8.4" + pretty-format@^25.1.0: version "25.1.0" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-25.1.0.tgz#ed869bdaec1356fc5ae45de045e2c8ec7b07b0c8" @@ -6756,7 +6915,7 @@ react-dom@^16.12.0: prop-types "^15.6.2" scheduler "^0.18.0" -react-is@^16.12.0, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.6, react-is@^16.9.0: +react-is@^16.12.0, react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4, react-is@^16.8.6, react-is@^16.9.0: version "16.12.0" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.12.0.tgz#2cc0fe0fba742d97fd527c42a13bec4eeb06241c" integrity sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q== @@ -7309,6 +7468,13 @@ rimraf@^3.0.0: dependencies: glob "^7.1.3" +rimraf@~2.4.0: + version "2.4.5" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.4.5.tgz#ee710ce5d93a8fdb856fb5ea8ff0e2d75934b2da" + integrity sha1-7nEM5dk6j9uFb7Xqj/Di11k0sto= + dependencies: + glob "^6.0.1" + ripemd160@^2.0.0, ripemd160@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" @@ -7371,6 +7537,11 @@ safe-buffer@~5.1.0, safe-buffer@~5.1.1: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== +safe-json-stringify@~1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/safe-json-stringify/-/safe-json-stringify-1.2.0.tgz#356e44bc98f1f93ce45df14bcd7c01cda86e0afd" + integrity sha512-gH8eh2nZudPQO6TytOvbxnuhYBOvDBBLW52tz5q6X58lJcd/tkmqFR+5Z9adS8aJtURSXWThWy/xJtJwixErvg== + safe-regex@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" @@ -7642,6 +7813,11 @@ sisteransi@^1.0.3: resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.4.tgz#386713f1ef688c7c0304dc4c0632898941cad2e3" integrity sha512-/ekMoM4NJ59ivGSfKapeG+FWtrmWvA1p6FBZwXrqojw90vJu8lBmrTxCMuBCydKtkaUe2zt4PlxeTKpjwMbyig== +slash@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" + integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A== + slash@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" From ab3ce25a45c6a8bbc2993e16bf45321970c01574 Mon Sep 17 00:00:00 2001 From: Ben Date: Fri, 21 Feb 2020 15:26:28 -0500 Subject: [PATCH 20/20] Add unit tests for background portion --- test/src/policy.test.js | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 test/src/policy.test.js diff --git a/test/src/policy.test.js b/test/src/policy.test.js new file mode 100644 index 000000000..02e7d7169 --- /dev/null +++ b/test/src/policy.test.js @@ -0,0 +1,34 @@ +import sinon from 'sinon'; +import PolicySmartBlock from '../../src/classes/PolicySmartBlock'; + +let policySmartBlock = new PolicySmartBlock(); +let policy = policySmartBlock.policy; + +// Mock imports for dependencies +jest.mock('../../src/classes/TabInfo', () => {}); + +describe('src/classes/Policy.js', () => { + describe('test functions', () => { + + test('matchesWildcardOrRegex should return true with wildcard entered ', () => { + const input = 'mozilla.*.com'; + const stub = sinon.stub(policy, 'matchesWildcardOrRegex'); + expect(stub.withArgs(input).returns(true)); + stub.restore(); + }); + + test('matchesWildcardOrRegex should return true with regex entered', () => { + const input = '[de]eveloper.mozilla.org'; + const stub = sinon.stub(policy, 'matchesWildcardOrRegex'); + expect(stub.withArgs(input).returns(true)); + stub.restore(); + }); + + test('matchesWildcardOrRegex should return false with ', () => { + const input = '[google.com'; + const stub = sinon.stub(policy, 'matchesWildcardOrRegex'); + expect(stub.withArgs(input).returns(false)); + stub.restore(); + }); + }) +});