[MM-25748]Allow access to managed resources (#1311)

* init of a branch

* Add more descriptive comment

* fix for linter errors

* Refactor of popup code
Remove isTrustedPopupWindow check in setPermissionRequestHandler
Check which UA needs to be sent depending on a url

* Update src/utils/util.js

Co-authored-by: Guillermo Vayá <guivaya@gmail.com>

* Remove commented code:

* Revert package.json and package-lock.json to original ones

* Implement buildConfig support for multiple trusted resources

* Fix for a typo

* add comments

* code cleanup

Co-authored-by: Dusan Panic <dusan@salestrekker.com>
Co-authored-by: dpanic <dpanic@0point.co>
Co-authored-by: Guillermo Vayá <guivaya@gmail.com>
This commit is contained in:
Dušan Panić
2020-06-19 15:32:14 +02:00
committed by GitHub
parent 81522a3b2d
commit a5ce5700cc
4 changed files with 54 additions and 8 deletions

View File

@@ -97,6 +97,8 @@ export default class MattermostView extends React.Component {
} else if (Utils.isTeamUrl(this.props.src, e.url, true) || Utils.isPluginUrl(this.props.src, e.url)) {
// New window should disable nodeIntegration.
window.open(e.url, remote.app.name, 'nodeIntegration=no, contextIsolation=yes, show=yes');
} else if (Utils.isManagedResource(this.props.src, e.url)) {
e.preventDefault();
} else {
e.preventDefault();
shell.openExternal(e.url);

View File

@@ -15,6 +15,7 @@
* @prop {boolean} enableServerManagement - Whether users can edit servers configuration.
* Specify at least one server for "defaultTeams"
* when "enableServerManagement is set to false
* @prop {[]} managedResources - Defines which paths are managed
*/
const buildConfig = {
defaultTeams: [/*
@@ -26,6 +27,7 @@ const buildConfig = {
helpLink: 'https://about.mattermost.com/default-desktop-app-documentation/',
enableServerManagement: true,
enableAutoUpdater: true,
managedResources: ['trusted'],
};
export default buildConfig;

View File

@@ -540,12 +540,13 @@ function handleAppWebContentsCreated(dc, contents) {
log.info(`Popup window already open at provided url: ${url}`);
return;
}
if (Utils.isPluginUrl(server.url, parsedURL)) {
if (Utils.isPluginUrl(server.url, parsedURL) || Utils.isManagedResource(server.url, parsedURL)) {
if (!popupWindow || popupWindow.closed) {
popupWindow = new BrowserWindow({
backgroundColor: '#fff', // prevents blurry text: https://electronjs.org/docs/faq#the-font-looks-blurry-what-is-this-and-what-can-i-do
parent: mainWindow,
show: false,
center: true,
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
@@ -559,11 +560,15 @@ function handleAppWebContentsCreated(dc, contents) {
});
}
// currently changing the userAgent for popup windows to allow plugins to go through google's oAuth
// should be removed once a proper oAuth2 implementation is setup.
popupWindow.loadURL(url, {
userAgent: popupUserAgent[process.platform],
});
if (Utils.isManagedResource(server.url, parsedURL)) {
popupWindow.loadURL(url);
} else {
// currently changing the userAgent for popup windows to allow plugins to go through google's oAuth
// should be removed once a proper oAuth2 implementation is setup.
popupWindow.loadURL(url, {
userAgent: popupUserAgent[process.platform],
});
}
}
});
@@ -817,7 +822,6 @@ function initializeAfterAppReady() {
return;
}
// get the requesting webContents url
const requestingURL = webContents.getURL();
// is the requesting url trusted?

View File

@@ -7,6 +7,8 @@ import electron, {remote} from 'electron';
import log from 'electron-log';
import {isUri, isHttpUri, isHttpsUri} from 'valid-url';
import buildConfig from '../common/config/buildConfig';
function getDomain(inputURL) {
const parsedURL = url.parse(inputURL);
return `${parsedURL.protocol}//${parsedURL.host}`;
@@ -69,6 +71,14 @@ function getServerInfo(serverUrl) {
return {origin: parsedServer.origin, subpath, url: parsedServer};
}
function getManagedResources() {
if (!buildConfig) {
return [];
}
return buildConfig.managedResources || [];
}
function isTeamUrl(serverUrl, inputUrl, withApi) {
const parsedURL = parseURL(inputUrl);
const server = getServerInfo(serverUrl);
@@ -76,7 +86,20 @@ function isTeamUrl(serverUrl, inputUrl, withApi) {
return null;
}
const nonTeamUrlPaths = ['plugins', 'signup', 'login', 'admin', 'channel', 'post', 'oauth', 'admin_console'];
// pre process nonTeamUrlPaths
let nonTeamUrlPaths = [
'plugins',
'signup',
'login',
'admin',
'channel',
'post',
'oauth',
'admin_console',
];
const managedResources = getManagedResources();
nonTeamUrlPaths = nonTeamUrlPaths.concat(managedResources);
if (withApi) {
nonTeamUrlPaths.push('api');
}
@@ -97,6 +120,20 @@ function isPluginUrl(serverUrl, inputURL) {
parsedURL.pathname.toLowerCase().startsWith('/plugins/')));
}
function isManagedResource(serverUrl, inputURL) {
const server = getServerInfo(serverUrl);
const parsedURL = parseURL(inputURL);
if (!parsedURL || !server) {
return false;
}
const managedResources = getManagedResources();
return (
equalUrlsIgnoringSubpath(server, parsedURL) && managedResources && managedResources.length &&
managedResources.some((managedResource) => (parsedURL.pathname.toLowerCase().startsWith(`${server.subpath}${managedResource}/`) || parsedURL.pathname.toLowerCase().startsWith(`/${managedResource}/`))));
}
function getServer(inputURL, teams) {
const parsedURL = parseURL(inputURL);
if (!parsedURL) {
@@ -189,6 +226,7 @@ export default {
getServerInfo,
isTeamUrl,
isPluginUrl,
isManagedResource,
getDisplayBoundaries,
dispatchNotification,
getHost,