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

@@ -17,4 +17,5 @@ Bug fixes
| `Bug #3873 <https://redmine.postgresql.org/issues/3873>`_ - Fix context sub-menu alignment on Safari. | `Bug #3873 <https://redmine.postgresql.org/issues/3873>`_ - Fix context sub-menu alignment on Safari.
| `Bug #3942 <https://redmine.postgresql.org/issues/3942>`_ - Close connections gracefully when the user logs out of pgAdmin. | `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 #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 #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') { if (e.button.element.name == 'dialog_help') {
e.cancel = true; e.cancel = true;
pgBrowser.showHelp(e.button.element.name, e.button.element.getAttribute('url'), pgBrowser.showHelp(e.button.element.name, e.button.element.getAttribute('url'),
null, null, e.button.element.getAttribute('label')); null, null);
return; return;
} }
if (e.button.text === gettext('OK')) { if (e.button.text === gettext('OK')) {

View File

@@ -644,18 +644,8 @@ define('pgadmin.browser', [
obj.enable_disable_menus(); obj.enable_disable_menus();
}, },
// General function to handle callbacks for object or dialog help. // General function to handle callbacks for object or dialog help.
showHelp: function(type, url, node, item, label) { showHelp: function(type, url, node, item) {
var iframe, pnlProperties;
if (type == 'object_help') { 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 // Construct the URL
var server = node.getTreeNodeHierarchy(item).server; var server = node.getTreeNodeHierarchy(item).server;
var baseUrl = pgBrowser.utils.pg_help_path; var baseUrl = pgBrowser.utils.pg_help_path;
@@ -670,35 +660,11 @@ define('pgadmin.browser', [
if (!S(baseUrl).endsWith('/')) { if (!S(baseUrl).endsWith('/')) {
baseUrl = baseUrl + '/'; baseUrl = baseUrl + '/';
} }
var fullUrl = baseUrl+ url; var fullUrl = baseUrl + url;
// Update the panel
iframe = $(pnlSqlHelp).data('embeddedFrame');
pnlSqlHelp.title('Help: '+ label);
pnlSqlHelp.focus(); window.open(fullUrl, 'postgres_help');
iframe.openURL(fullUrl);
} else if(type == 'dialog_help') { } else if(type == 'dialog_help') {
if(this.docker) { window.open(url, 'pgadmin_help');
// 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');
}
} }
}, },
_findTreeChildNode: function(_i, _d, _o) { _findTreeChildNode: function(_i, _d, _o) {

View File

@@ -1201,15 +1201,6 @@ define('pgadmin.browser.node', [
j.append(content); j.append(content);
}.bind(panel), }.bind(panel),
onSqlHelp = function() { 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 // Construct the URL
var server = that.getTreeNodeHierarchy(item).server; var server = that.getTreeNodeHierarchy(item).server;
@@ -1237,29 +1228,11 @@ define('pgadmin.browser.node', [
} }
} }
// Update the panel window.open(url, 'postgres_help');
var iframe = $(pnlSqlHelp).data('embeddedFrame');
pnlSqlHelp.title('SQL: ' + that.label);
pnlSqlHelp.focus();
iframe.openURL(url);
}.bind(panel), }.bind(panel),
onDialogHelp = function() { onDialogHelp = function() {
// See if we can find an existing panel, if not, create one window.open(that.dialogHelp, 'pgadmin_help');
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);
}.bind(panel), }.bind(panel),
onSave = function(view, saveBtn) { onSave = function(view, saveBtn) {

View File

@@ -12,8 +12,6 @@ define([
'sources/gettext', 'sources/utils', 'sources/gettext', 'sources/utils',
], function(_, $, Backbone, pgAdmin, pgBrowser, gettext, commonUtils) { ], function(_, $, Backbone, pgAdmin, pgBrowser, gettext, commonUtils) {
var wcDocker = window.wcDocker;
/* Wizard individual Page Model */ /* Wizard individual Page Model */
pgBrowser.WizardPage = Backbone.Model.extend({ pgBrowser.WizardPage = Backbone.Model.extend({
defaults: { defaults: {
@@ -309,20 +307,7 @@ define([
return (_.isFunction(func) ? func.apply(ctx, [self]) : func); return (_.isFunction(func) ? func.apply(ctx, [self]) : func);
}, },
onDialogHelp: function() { onDialogHelp: function() {
// See if we can find an existing panel, if not, create one window.open(this.options.wizard_help, 'pgadmin_help');
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);
}, },
}); });

View File

@@ -47,25 +47,25 @@
<div class="card-body p-2"> <div class="card-body p-2">
<div class="row"> <div class="row">
<div class="col-3 dashboard-link"> <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/> <span class="fa fa-4x dashboard-icon dashboard-pg-doc" aria-hidden="true"></span><br/>
{{ _('PostgreSQL Documentation') }} {{ _('PostgreSQL Documentation') }}
</a> </a>
</div> </div>
<div class="col-3 dashboard-link"> <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/> <span class="fa fa-4x dashboard-icon fa-globe" aria-hidden="true"></span><br/>
{{ _('pgAdmin Website') }} {{ _('pgAdmin Website') }}
</a> </a>
</div> </div>
<div class="col-3 dashboard-link"> <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/> <span class="fa fa-4x dashboard-icon fa-book" aria-hidden="true"></span><br/>
{{ _('Planet PostgreSQL') }} {{ _('Planet PostgreSQL') }}
</a> </a>
</div> </div>
<div class="col-3 dashboard-link"> <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/> <span class="fa fa-4x dashboard-icon fa-users" aria-hidden="true"></span><br/>
{{ _('Community Support') }} {{ _('Community Support') }}
</a> </a>

View File

@@ -26,40 +26,24 @@ class HelpModule(PgAdminModule):
MenuItem(name='mnu_online_help', MenuItem(name='mnu_online_help',
label=gettext('Online Help'), label=gettext('Online Help'),
priority=100, priority=100,
target='_blank', target='pgadmin_help',
icon='fa fa-question', icon='fa fa-question',
url=url_for('help.static', filename='index.html')), url=url_for('help.static', filename='index.html')),
MenuItem(name='mnu_pgadmin_website', MenuItem(name='mnu_pgadmin_website',
label=gettext('pgAdmin Website'), label=gettext('pgAdmin Website'),
priority=200, priority=200,
target='_blank', target='pgadmin_website',
icon='fa fa-external-link', icon='fa fa-external-link',
url='https://www.pgadmin.org/'), url='https://www.pgadmin.org/'),
MenuItem(name='mnu_postgresql_website', MenuItem(name='mnu_postgresql_website',
label=gettext('PostgreSQL Website'), label=gettext('PostgreSQL Website'),
priority=300, priority=300,
target='_blank', target='postgres_website',
icon='fa fa-external-link', icon='fa fa-external-link',
url='https://www.postgresql.org/')]} 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): def register_preferences(self):
""" """
register_preferences register_preferences

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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