mirror of
https://github.com/finos/SymphonyElectron.git
synced 2025-02-25 18:55:29 -06:00
Merge pull request #263 from KiranNiranjan/ELECTRON-217
Electron-217 (Whitelisting domains & sub-domains)
This commit is contained in:
commit
243144ed4a
@ -3,6 +3,7 @@
|
||||
"minimizeOnClose" : true,
|
||||
"launchOnStartup" : true,
|
||||
"alwaysOnTop" : false,
|
||||
"whitelistUrl": "*",
|
||||
"notificationSettings": {
|
||||
"position": "upper-right",
|
||||
"display": ""
|
||||
|
@ -425,6 +425,9 @@ module.exports = {
|
||||
saveUserConfig,
|
||||
clearCachedConfigs,
|
||||
|
||||
readConfigFileSync
|
||||
readConfigFileSync,
|
||||
|
||||
// use only if you specifically need to read global config fields
|
||||
getGlobalConfigField,
|
||||
|
||||
};
|
||||
|
120
js/utils/whitelistHandler.js
Normal file
120
js/utils/whitelistHandler.js
Normal file
@ -0,0 +1,120 @@
|
||||
'use strict';
|
||||
|
||||
const { getGlobalConfigField } = require('./../config.js');
|
||||
const parseDomain = require('parse-domain');
|
||||
const isEqual = require('lodash.isequal');
|
||||
|
||||
/**
|
||||
* Loops through the list of whitelist urls
|
||||
* @param url {String} - url the electron is navigated to
|
||||
* @returns {Promise}
|
||||
*/
|
||||
function isWhitelisted(url) {
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
getGlobalConfigField('whitelistUrl').then((whitelist) => {
|
||||
|
||||
if (checkWhitelist(url, whitelist)) {
|
||||
return resolve();
|
||||
}
|
||||
|
||||
return reject(new Error('URL does not match with the whitelist'));
|
||||
|
||||
}).catch((err) => {
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Method that compares url against a list of whitelist
|
||||
* returns true if hostName or domain present in the whitelist
|
||||
* @param url {String} - url the electron is navigated to
|
||||
* @param whitelist {String} - coma separated whitelists
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function checkWhitelist(url, whitelist) {
|
||||
let whitelistArray = whitelist.split(',');
|
||||
const parsedUrl = parseDomain(url);
|
||||
|
||||
if (!parsedUrl) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!whitelist) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!whitelistArray.length || whitelistArray.indexOf('*') !== -1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return whitelistArray.some((whitelistHost) => {
|
||||
let parsedWhitelist = parseDomain(whitelistHost);
|
||||
|
||||
if (!parsedWhitelist) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return matchDomains(parsedUrl, parsedWhitelist);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches the respective hostName
|
||||
* @param parsedUrl {Object} - parsed url
|
||||
* @param parsedWhitelist {Object} - parsed whitelist
|
||||
*
|
||||
* example:
|
||||
* matchDomain({ subdomain: www, domain: example, tld: com }, { subdomain: app, domain: example, tld: com })
|
||||
*
|
||||
* @returns {*}
|
||||
*/
|
||||
function matchDomains(parsedUrl, parsedWhitelist) {
|
||||
|
||||
if (isEqual(parsedUrl, parsedWhitelist)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const hostNameFromUrl = parsedUrl.domain + parsedUrl.tld;
|
||||
const hostNameFromWhitelist = parsedWhitelist.domain + parsedWhitelist.tld;
|
||||
|
||||
if (!parsedWhitelist.subdomain) {
|
||||
return hostNameFromUrl === hostNameFromWhitelist
|
||||
}
|
||||
|
||||
return hostNameFromUrl === hostNameFromWhitelist && matchSubDomains(parsedUrl.subdomain, parsedWhitelist.subdomain);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches the last occurrence in the sub-domain
|
||||
* @param subDomainUrl {String} - sub-domain from url
|
||||
* @param subDomainWhitelist {String} - sub-domain from whitelist
|
||||
*
|
||||
* example: matchSubDomains('www', 'app')
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function matchSubDomains(subDomainUrl, subDomainWhitelist) {
|
||||
|
||||
if (subDomainUrl === subDomainWhitelist) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const subDomainUrlArray = subDomainUrl.split('.');
|
||||
const lastCharSubDomainUrl = subDomainUrlArray[subDomainUrlArray.length - 1];
|
||||
|
||||
const subDomainWhitelistArray = subDomainWhitelist.split('.');
|
||||
const lastCharWhitelist = subDomainWhitelistArray[subDomainWhitelistArray.length - 1];
|
||||
|
||||
return lastCharSubDomainUrl === lastCharWhitelist;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
isWhitelisted,
|
||||
|
||||
// items below here are only exported for testing, do NOT use!
|
||||
checkWhitelist
|
||||
|
||||
};
|
@ -21,6 +21,7 @@ const eventEmitter = require('./eventEmitter');
|
||||
const throttle = require('./utils/throttle.js');
|
||||
const { getConfigField, updateConfigField } = require('./config.js');
|
||||
const { isMac, isNodeEnv } = require('./utils/misc');
|
||||
const { isWhitelisted } = require('./utils/whitelistHandler');
|
||||
|
||||
// show dialog when certificate errors occur
|
||||
require('./dialogs/showCertError.js');
|
||||
@ -462,6 +463,20 @@ function doCreateMainWindow(initialUrl, initialBounds) {
|
||||
}
|
||||
});
|
||||
|
||||
// whenever the main window is navigated for ex: window.location.href or url redirect
|
||||
mainWindow.webContents.on('will-navigate', function(event, navigatedURL) {
|
||||
isWhitelisted(navigatedURL)
|
||||
.catch(() => {
|
||||
event.preventDefault();
|
||||
electron.dialog.showMessageBox(mainWindow, {
|
||||
type: 'warning',
|
||||
buttons: [ 'Ok' ],
|
||||
title: 'Not Allowed',
|
||||
message: `Sorry, you are not allowed to access this website (${navigatedURL}), please contact your administrator for more details`,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -104,9 +104,11 @@
|
||||
"electron-squirrel-startup": "^1.0.0",
|
||||
"filesize": "^3.5.10",
|
||||
"keymirror": "0.1.1",
|
||||
"lodash.difference": "^4.5.0",
|
||||
"lodash.isequal": "^4.5.0",
|
||||
"lodash.omit": "^4.5.0",
|
||||
"lodash.pick": "^4.4.0",
|
||||
"lodash.difference": "^4.5.0",
|
||||
"parse-domain": "^2.0.0",
|
||||
"winreg": "^1.2.3"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
|
74
tests/utils/whitelist.test.js
Normal file
74
tests/utils/whitelist.test.js
Normal file
@ -0,0 +1,74 @@
|
||||
const { checkWhitelist } = require('../../js/utils/whitelistHandler');
|
||||
|
||||
describe('validate url with whitelist', function() {
|
||||
|
||||
describe('checkWhitelist truth tests', function() {
|
||||
|
||||
it('should return true when the url is valid', function() {
|
||||
const whitelist = 'www.symphony.com, app.symphony.com, my.symphony.com';
|
||||
const url = 'https://my.symphony.com/';
|
||||
|
||||
return expect(checkWhitelist(url, whitelist)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should return true when if hostName is defined', function() {
|
||||
const whitelist = 'www.symphony.com, app.symphony.com, symphony.com';
|
||||
const url = 'https://xyz.symphony.com/';
|
||||
|
||||
return expect(checkWhitelist(url, whitelist)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should return true when the first occurrence of sub-domain is matched', function() {
|
||||
const whitelist = 'www.symphony.com, app.symphony.com, my.symphony.com';
|
||||
const url = 'https://xyz.my.symphony.com/';
|
||||
|
||||
return expect(checkWhitelist(url, whitelist)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should return true when for any URL if whitelist has *', function() {
|
||||
const whitelist = '*';
|
||||
const url = 'https://www.example.com/';
|
||||
|
||||
return expect(checkWhitelist(url, whitelist)).toBeTruthy();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('checkWhitelist falsity tests', function () {
|
||||
|
||||
it('should return false when sub-domain does not match', function () {
|
||||
const whitelist = 'www.symphony.com, app.symphony.com, my.symphony.com';
|
||||
const url = 'https://xyz.symphony.com/';
|
||||
|
||||
return expect(checkWhitelist(url, whitelist)).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should return false when hostName does not match', function () {
|
||||
const whitelist = 'www.symphony.com, app.symphony.com, my.symphony.com';
|
||||
const url = 'https://my.example.com/';
|
||||
|
||||
return expect(checkWhitelist(url, whitelist)).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should return false when the URL is invalid', function () {
|
||||
const whitelist = 'www.symphony.com, app.symphony.com, my.symphony.com';
|
||||
const url = 'invalidUrl';
|
||||
|
||||
return expect(checkWhitelist(url, whitelist)).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should return false when the whitelist is invalid', function () {
|
||||
const whitelist = 'invalidWhitelist';
|
||||
const url = 'https://www.symphony.com';
|
||||
|
||||
return expect(checkWhitelist(url, whitelist)).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should return false if whitelist is empty', function() {
|
||||
const whitelist = '';
|
||||
const url = 'https://www.example.com/';
|
||||
|
||||
return expect(checkWhitelist(url, whitelist)).toBeFalsy();
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user