Added support for Two-factor authentication for improving security. Fixes #6543

This commit is contained in:
Ashesh Vashi
2021-12-02 16:47:18 +05:30
committed by Akshay Joshi
parent fe096116be
commit 36c9eb3dfd
56 changed files with 2770 additions and 119 deletions

View File

@@ -25,6 +25,7 @@ from flask import current_app, render_template, url_for, make_response, \
from flask_babel import gettext
from flask_gravatar import Gravatar
from flask_login import current_user, login_required
from flask_login.utils import login_url
from flask_security.changeable import change_user_password
from flask_security.decorators import anonymous_user_required
from flask_security.recoverable import reset_password_token_status, \
@@ -38,6 +39,8 @@ from werkzeug.datastructures import MultiDict
import config
from pgadmin import current_blueprint
from pgadmin.authenticate import get_logout_url
from pgadmin.authenticate.mfa.utils import mfa_required, is_mfa_enabled
from pgadmin.settings import get_setting, store_setting
from pgadmin.utils import PgAdminModule
from pgadmin.utils.ajax import make_json_response
@@ -695,6 +698,7 @@ def check_browser_upgrade():
@blueprint.route("/")
@pgCSRFProtect.exempt
@login_required
@mfa_required
def index():
"""Render and process the main browser window."""
# Register Gravatar module with the app only if required
@@ -753,7 +757,11 @@ def index():
username=current_user.username,
auth_source=auth_source,
is_admin=current_user.has_role("Administrator"),
logout_url=_get_logout_url(),
logout_url=get_logout_url(),
requirejs=True,
basejs=True,
mfa_enabled=is_mfa_enabled(),
login_url=login_url,
_=gettext,
auth_only_internal=auth_only_internal
))
@@ -843,7 +851,7 @@ def utils():
app_version_int=config.APP_VERSION_INT,
pg_libpq_version=pg_libpq_version,
support_ssh_tunnel=config.SUPPORT_SSH_TUNNEL,
logout_url=_get_logout_url(),
logout_url=get_logout_url(),
platform=sys.platform,
qt_default_placeholder=QT_DEFAULT_PLACEHOLDER,
enable_psql=config.ENABLE_PSQL

View File

@@ -22,7 +22,7 @@ define('pgadmin.browser', [
'pgadmin.browser.menu', 'pgadmin.browser.panel', 'pgadmin.browser.layout',
'pgadmin.browser.runtime', 'pgadmin.browser.error', 'pgadmin.browser.frame',
'pgadmin.browser.node', 'pgadmin.browser.collection', 'pgadmin.browser.activity',
'sources/codemirror/addon/fold/pgadmin-sqlfoldcode',
'sources/codemirror/addon/fold/pgadmin-sqlfoldcode', 'pgadmin.browser.dialog',
'pgadmin.browser.keyboard', 'sources/tree/pgadmin_tree_save_state','jquery.acisortable',
'jquery.acifragment',
], function(
@@ -172,7 +172,7 @@ define('pgadmin.browser', [
let ih = window.innerHeight;
if (ih > passed_height){
return passed_height;
}else{
} else {
if (ih > pgAdmin.Browser.stdH.lg)
return pgAdmin.Browser.stdH.lg;
else if (ih > pgAdmin.Browser.stdH.md)

View File

@@ -0,0 +1,110 @@
/////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
// Copyright (C) 2013 - 2021, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
import gettext from 'sources/gettext';
import * as alertify from 'pgadmin.alertifyjs';
import url_for from 'sources/url_for';
import pgAdmin from 'sources/pgadmin';
let counter = 1;
function url_dialog(_title, _url, _help_filename, _width, _height) {
let pgBrowser = pgAdmin.Browser;
const dlgName = 'UrlDialog' + counter++;
alertify.dialog(dlgName, function factory() {
return {
main: function(_title) {
this.set({'title': _title});
},
build: function() {
alertify.pgDialogBuild.apply(this);
},
settings: {
url: _url,
title: _title,
},
setup: function() {
return {
buttons: [{
text: '',
key: 112,
className: 'btn btn-primary-icon pull-left fa fa-question pg-alertify-icon-button',
attrs: {
name: 'dialog_help',
type: 'button',
label: _title,
url: url_for('help.static', {
'filename': _help_filename,
}),
},
}, {
text: gettext('Close'),
key: 27,
className: 'btn btn-secondary fa fa-lg fa-times pg-alertify-button',
attrs: {
name: 'close',
type: 'button',
},
}],
// Set options for dialog
options: {
//disable both padding and overflow control.
padding: !1,
overflow: !1,
modal: false,
resizable: true,
maximizable: true,
pinnable: false,
closableByDimmer: false,
closable: false,
},
};
},
hooks: {
// Triggered when the dialog is closed
onclose: function() {
// Clear the view
return setTimeout((function() {
return (alertify[dlgName]()).destroy();
}), 1000);
},
},
prepare: function() {
// create the iframe element
var iframe = document.createElement('iframe');
iframe.frameBorder = 'no';
iframe.width = '100%';
iframe.height = '100%';
iframe.src = this.setting('url');
// add it to the dialog
this.elements.content.appendChild(iframe);
},
callback: function(e) {
if (e.button.element.name == 'dialog_help') {
e.cancel = true;
pgBrowser.showHelp(
e.button.element.name, e.button.element.getAttribute('url'),
null, null
);
return;
}
},
};
});
(alertify[dlgName](_title)).show().resizeTo(_width || pgBrowser.stdW.lg, _height || pgBrowser.stdH.md);
}
pgAdmin.ui.dialogs.url_dialog = url_dialog;
export {
url_dialog,
};

View File

@@ -152,6 +152,17 @@ window.onload = function(e){
</li>
<li class="dropdown-divider"></li>
{% endif %}
{% if mfa_enabled is defined and mfa_enabled is true %}
<li>
<a class="dropdown-item" href="#" role="menuitem"
onclick="javascript:pgAdmin.ui.dialogs.url_dialog(
'{{ _("Authentiction") }}',
'{{ login_url("mfa.register", next_url="internal") }}',
'mfa.html', '90%', '90%'
);">{{ _('Two-Factor Authentication') }}</a>
</li>
<li class="dropdown-divider"></li>
{% endif %}
{% if is_admin %}
<li><a class="dropdown-item" href="#" role="menuitem" onclick="pgAdmin.Browser.UserManagement.show_users()">{{ _('Users') }}</a></li>
<li class="dropdown-divider"></li>