Don't embed docs and external sites in iframes, to allow the external sites to set X-FRAME-OPTIONS = DENY for security. Fxies #3985

This commit is contained in:
Dave Page 2019-02-12 16:07:38 +00:00
parent e0e7d6f1f6
commit 1fc66406f5
15 changed files with 28 additions and 129 deletions

View File

@ -18,3 +18,4 @@ Bug fixes
| `Bug #3942 <https://redmine.postgresql.org/issues/3942>`_ - Close connections gracefully when the user logs out of pgAdmin.
| `Bug #3963 <https://redmine.postgresql.org/issues/3963>`_ - Fix alignment of import/export toggle switch.
| `Bug #3981 <https://redmine.postgresql.org/issues/3981>`_ - Fix the query to set bytea_output so that read-only standbys don't consider it a write query.
| `Bug #3985 <https://redmine.postgresql.org/issues/3985>`_ - Don't embed docs and external sites in iframes, to allow the external sites to set X-FRAME-OPTIONS = DENY for security.

View File

@ -270,7 +270,7 @@ define('pgadmin.node.tablespace', [
if (e.button.element.name == 'dialog_help') {
e.cancel = true;
pgBrowser.showHelp(e.button.element.name, e.button.element.getAttribute('url'),
null, null, e.button.element.getAttribute('label'));
null, null);
return;
}
if (e.button.text === gettext('OK')) {

View File

@ -644,18 +644,8 @@ define('pgadmin.browser', [
obj.enable_disable_menus();
},
// General function to handle callbacks for object or dialog help.
showHelp: function(type, url, node, item, label) {
var iframe, pnlProperties;
showHelp: function(type, url, node, item) {
if (type == 'object_help') {
// See if we can find an existing panel, if not, create one
var pnlSqlHelp = this.docker.findPanels('pnl_sql_help')[0];
if (pnlSqlHelp == null) {
pnlProperties = this.docker.findPanels('properties')[0];
this.docker.addPanel('pnl_sql_help', wcDocker.DOCK.STACKED, pnlProperties);
pnlSqlHelp = this.docker.findPanels('pnl_sql_help')[0];
}
// Construct the URL
var server = node.getTreeNodeHierarchy(item).server;
var baseUrl = pgBrowser.utils.pg_help_path;
@ -671,34 +661,10 @@ define('pgadmin.browser', [
baseUrl = baseUrl + '/';
}
var fullUrl = baseUrl + url;
// Update the panel
iframe = $(pnlSqlHelp).data('embeddedFrame');
pnlSqlHelp.title('Help: '+ label);
pnlSqlHelp.focus();
iframe.openURL(fullUrl);
window.open(fullUrl, 'postgres_help');
} else if(type == 'dialog_help') {
if(this.docker) {
// See if we can find an existing panel, if not, create one
var pnlDialogHelp = this.docker.findPanels('pnl_online_help')[0];
if (pnlDialogHelp == null) {
pnlProperties = this.docker.findPanels('properties')[0];
this.docker.addPanel('pnl_online_help', wcDocker.DOCK.STACKED, pnlProperties);
pnlDialogHelp = this.docker.findPanels('pnl_online_help')[0];
}
// Update the panel
iframe = $(pnlDialogHelp).data('embeddedFrame');
pnlDialogHelp.focus();
iframe.openURL(url);
} else {
// We have added new functionality of opening Query tool & debugger in new
// browser tab, In that case we will not have docker object available
// so we will open dialog help in new browser tab
window.open(url, '_blank');
}
window.open(url, 'pgadmin_help');
}
},
_findTreeChildNode: function(_i, _d, _o) {

View File

@ -1201,15 +1201,6 @@ define('pgadmin.browser.node', [
j.append(content);
}.bind(panel),
onSqlHelp = function() {
// See if we can find an existing panel, if not, create one
var pnlSqlHelp = pgBrowser.docker.findPanels('pnl_sql_help')[0];
if (pnlSqlHelp == null) {
var pnlProperties = pgBrowser.docker.findPanels('properties')[0];
pgBrowser.docker.addPanel('pnl_sql_help', wcDocker.DOCK.STACKED, pnlProperties);
pnlSqlHelp = pgBrowser.docker.findPanels('pnl_sql_help')[0];
}
// Construct the URL
var server = that.getTreeNodeHierarchy(item).server;
@ -1237,29 +1228,11 @@ define('pgadmin.browser.node', [
}
}
// Update the panel
var iframe = $(pnlSqlHelp).data('embeddedFrame');
pnlSqlHelp.title('SQL: ' + that.label);
pnlSqlHelp.focus();
iframe.openURL(url);
window.open(url, 'postgres_help');
}.bind(panel),
onDialogHelp = function() {
// See if we can find an existing panel, if not, create one
var pnlDialogHelp = pgBrowser.docker.findPanels('pnl_online_help')[0];
if (pnlDialogHelp == null) {
var pnlProperties = pgBrowser.docker.findPanels('properties')[0];
pgBrowser.docker.addPanel('pnl_online_help', wcDocker.DOCK.STACKED, pnlProperties);
pnlDialogHelp = pgBrowser.docker.findPanels('pnl_online_help')[0];
}
// Update the panel
var iframe = $(pnlDialogHelp).data('embeddedFrame');
pnlDialogHelp.focus();
iframe.openURL(that.dialogHelp);
window.open(that.dialogHelp, 'pgadmin_help');
}.bind(panel),
onSave = function(view, saveBtn) {

View File

@ -12,8 +12,6 @@ define([
'sources/gettext', 'sources/utils',
], function(_, $, Backbone, pgAdmin, pgBrowser, gettext, commonUtils) {
var wcDocker = window.wcDocker;
/* Wizard individual Page Model */
pgBrowser.WizardPage = Backbone.Model.extend({
defaults: {
@ -309,20 +307,7 @@ define([
return (_.isFunction(func) ? func.apply(ctx, [self]) : func);
},
onDialogHelp: function() {
// See if we can find an existing panel, if not, create one
var pnlDialogHelp = pgBrowser.docker.findPanels('pnl_online_help')[0];
if (pnlDialogHelp == null) {
var pnlProperties = pgBrowser.docker.findPanels('properties')[0];
pgBrowser.docker.addPanel('pnl_online_help', wcDocker.DOCK.STACKED, pnlProperties);
pnlDialogHelp = pgBrowser.docker.findPanels('pnl_online_help')[0];
}
// Update the panel
var iframe = $(pnlDialogHelp).data('embeddedFrame');
pnlDialogHelp.focus();
iframe.openURL(this.options.wizard_help);
window.open(this.options.wizard_help, 'pgadmin_help');
},
});

View File

@ -47,25 +47,25 @@
<div class="card-body p-2">
<div class="row">
<div class="col-3 dashboard-link">
<a href="http://www.postgresql.org/docs" target="_blank">
<a href="http://www.postgresql.org/docs" target="postgres_help">
<span class="fa fa-4x dashboard-icon dashboard-pg-doc" aria-hidden="true"></span><br/>
{{ _('PostgreSQL Documentation') }}
</a>
</div>
<div class="col-3 dashboard-link">
<a href="https://www.pgadmin.org" target="_blank">
<a href="https://www.pgadmin.org" target="pgadmin_website">
<span class="fa fa-4x dashboard-icon fa-globe" aria-hidden="true"></span><br/>
{{ _('pgAdmin Website') }}
</a>
</div>
<div class="col-3 dashboard-link">
<a href="http://planet.postgresql.org" target="_blank">
<a href="http://planet.postgresql.org" target="planet_website">
<span class="fa fa-4x dashboard-icon fa-book" aria-hidden="true"></span><br/>
{{ _('Planet PostgreSQL') }}
</a>
</div>
<div class="col-3 dashboard-link">
<a href="http://www.postgresql.org/community" target="_blank">
<a href="http://www.postgresql.org/community" target="postgres_website">
<span class="fa fa-4x dashboard-icon fa-users" aria-hidden="true"></span><br/>
{{ _('Community Support') }}
</a>

View File

@ -26,40 +26,24 @@ class HelpModule(PgAdminModule):
MenuItem(name='mnu_online_help',
label=gettext('Online Help'),
priority=100,
target='_blank',
target='pgadmin_help',
icon='fa fa-question',
url=url_for('help.static', filename='index.html')),
MenuItem(name='mnu_pgadmin_website',
label=gettext('pgAdmin Website'),
priority=200,
target='_blank',
target='pgadmin_website',
icon='fa fa-external-link',
url='https://www.pgadmin.org/'),
MenuItem(name='mnu_postgresql_website',
label=gettext('PostgreSQL Website'),
priority=300,
target='_blank',
target='postgres_website',
icon='fa fa-external-link',
url='https://www.postgresql.org/')]}
def get_panels(self):
return [
Panel(
name='pnl_online_help',
priority=100,
isPrivate=True,
title=gettext('Online Help'),
icon='fa fa-question').__dict__,
Panel(
name='pnl_sql_help',
priority=200,
isPrivate=True,
icon='fa fa-info',
title=gettext('SQL Help')).__dict__]
def register_preferences(self):
"""
register_preferences

View File

@ -447,7 +447,7 @@ define('pgadmin.preferences', [
if (e.button.element.name == 'dialog_help') {
e.cancel = true;
pgBrowser.showHelp(e.button.element.name, e.button.element.getAttribute('url'),
null, null, e.button.element.getAttribute('label'));
null, null);
return;
}

View File

@ -206,7 +206,7 @@ let FilterDialog = {
if (e.button.element.name == 'dialog_help') {
e.cancel = true;
pgAdmin.Browser.showHelp(e.button.element.name, e.button.element.getAttribute('url'),
null, null, e.button.element.getAttribute('label'));
null, null);
return;
} else if (e.button['data-btn-name'] === 'ok') {
e.cancel = true; // Do not close dialog

View File

@ -114,8 +114,7 @@ export class BackupDialogWrapper extends DialogWrapper {
event.button.element.name,
event.button.element.getAttribute('url'),
node,
selectedTreeNode.getHtmlIdentifier(),
event.button.element.getAttribute('label')
selectedTreeNode.getHtmlIdentifier()
);
return;
}

View File

@ -336,7 +336,7 @@ define([
if (e.button.element.name == 'dialog_help' || e.button.element.name == 'object_help') {
e.cancel = true;
pgBrowser.showHelp(e.button.element.name, e.button.element.getAttribute('url'),
node, i, e.button.element.getAttribute('label'));
node, i);
return;
}

View File

@ -114,8 +114,7 @@ export class RestoreDialogWrapper extends DialogWrapper {
event.button.element.name,
event.button.element.getAttribute('url'),
node,
selectedTreeNode.getHtmlIdentifier(),
event.button.element.getAttribute('label')
selectedTreeNode.getHtmlIdentifier()
);
return;
}

View File

@ -123,7 +123,7 @@ define([
if (e.button.element.name == 'dialog_help') {
e.cancel = true;
pgBrowser.showHelp(e.button.element.name, e.button.element.getAttribute('url'),
null, null, e.button.element.getAttribute('label'));
null, null);
return;
}
},
@ -868,7 +868,7 @@ define([
if (e.button.element.name == 'dialog_help') {
e.cancel = true;
pgBrowser.showHelp(e.button.element.name, e.button.element.getAttribute('url'),
null, null, e.button.element.getAttribute('label'));
null, null);
return;
}
if (e.button.element.name == 'close') {

View File

@ -245,8 +245,6 @@ describe('BackupDialogWrapper', () => {
getAttribute: (attributeName) => {
if (attributeName === 'url') {
return 'http://someurl';
} else if (attributeName === 'label') {
return 'some label';
}
},
},
@ -260,8 +258,7 @@ describe('BackupDialogWrapper', () => {
'dialog_help',
'http://someurl',
pgBrowser.Nodes['server'],
serverTreeNode.getHtmlIdentifier(),
'some label'
serverTreeNode.getHtmlIdentifier()
);
});
@ -288,8 +285,6 @@ describe('BackupDialogWrapper', () => {
getAttribute: (attributeName) => {
if (attributeName === 'url') {
return 'http://someurl';
} else if (attributeName === 'label') {
return 'some label';
}
},
},
@ -303,8 +298,7 @@ describe('BackupDialogWrapper', () => {
'object_help',
'http://someurl',
pgBrowser.Nodes['server'],
serverTreeNode.getHtmlIdentifier(),
'some label'
serverTreeNode.getHtmlIdentifier()
);
});

View File

@ -252,8 +252,7 @@ describe('RestoreDialogWrapper', () => {
'dialog_help',
'http://someurl',
pgBrowser.Nodes['server'],
serverTreeNode.getHtmlIdentifier(),
'some label'
serverTreeNode.getHtmlIdentifier()
);
});
@ -294,8 +293,7 @@ describe('RestoreDialogWrapper', () => {
'object_help',
'http://someurl',
pgBrowser.Nodes['server'],
serverTreeNode.getHtmlIdentifier(),
'some label'
serverTreeNode.getHtmlIdentifier()
);
});