public inbox for [email protected]
help / color / mirror / Atom feedFrom: Nikhil Mohite <[email protected]>
To: pgadmin-hackers <[email protected]>
Subject: [pgAdmin][RM3794]:Allow User to Change Database Connection from an Open Query Tool Tab
Date: Thu, 17 Sep 2020 16:15:03 +0530
Message-ID: <CAOBg0AM=b7hfJjTJAXu=wGkKHEsV_zoZpSO-QU6Z-G9p2wVF0w@mail.gmail.com> (raw)
Hi Team,
Regarding RM-3794 <https://redmine.postgresql.org/issues/3794; allow
the user to change the database connection from an open query tool:
I have implemented the feature and also added documentation for it.
PFA patch.
--
*Thanks & Regards,*
*Nikhil Mohite*
*Software Engineer.*
*EDB Postgres* <https://www.enterprisedb.com/;
*Mob.No: +91-7798364578.*
Attachments:
[application/octet-stream] RM_3794_v1.patch (197.4K, 3-RM_3794_v1.patch)
download | inline diff:
diff --git a/docs/en_US/images/new_connection_dialog.png b/docs/en_US/images/new_connection_dialog.png
new file mode 100644
index 0000000000000000000000000000000000000000..c2f877dc9771b8b697c925438e4abb4f7436db35
GIT binary patch
literal 44942
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
F{{cYfFA@L%
literal 0
HcmV?d00001
diff --git a/docs/en_US/images/new_connection_options.png b/docs/en_US/images/new_connection_options.png
new file mode 100644
index 0000000000000000000000000000000000000000..3de8fc4ee9a50d1c93c35b274cc21fec784c1138
GIT binary patch
literal 47015
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
O-}%!Hr)q!oyY_$PkK4om
literal 0
HcmV?d00001
diff --git a/docs/en_US/query_tool.rst b/docs/en_US/query_tool.rst
index 83933f0..545fb95 100644
--- a/docs/en_US/query_tool.rst
+++ b/docs/en_US/query_tool.rst
@@ -300,3 +300,24 @@ transaction status by clicking on the status icon in the Query Tool:
.. image:: images/query_tool_connection_status.png
:alt: Query tool connection and transaction statuses
:align: center
+
+Change connection
+*****************
+
+User can connect to another server or database from existing open session of query tool.
+
+* Click on the connection link next to connection status.
+* Now click on the *<New Connection>* option from the dropdown.
+
+.. image:: images/new_connection_options.png
+ :alt: Query tool connection options
+ :align: center
+
+* Now select server, database, user, and password to connect and click OK.
+
+.. image:: images/new_connection_dialog.png
+ :alt: Query tool connection dialog
+ :align: center
+
+* A newly created connection will now get listed in the options.
+* To connect, select the newly created connection from the dropdown list.
diff --git a/web/pgadmin/browser/server_groups/servers/roles/tests/utils.py b/web/pgadmin/browser/server_groups/servers/roles/tests/utils.py
index 3a7ee58..028ee64 100644
--- a/web/pgadmin/browser/server_groups/servers/roles/tests/utils.py
+++ b/web/pgadmin/browser/server_groups/servers/roles/tests/utils.py
@@ -152,3 +152,38 @@ def delete_role(connection, role_names):
exception = "Error while deleting role: %s: line:%s %s" % (
file_name, sys.exc_traceback.tb_lineno, exception)
print(exception, file=sys.stderr)
+
+
+def create_role_with_password(server, role_name, role_password):
+ """
+ This function create the role.
+ :param server:
+ :param role_name:
+ :param role_password:
+ :return:
+ """
+ try:
+ connection = utils.get_db_connection(server['db'],
+ server['username'],
+ server['db_password'],
+ server['host'],
+ server['port'],
+ server['sslmode'])
+ pg_cursor = connection.cursor()
+ pg_cursor.execute(
+ "CREATE ROLE %s LOGIN PASSWORD '%s'" % (role_name, role_password))
+ connection.commit()
+ # Get 'oid' from newly created tablespace
+ pg_cursor.execute(
+ "SELECT pr.oid from pg_catalog.pg_roles pr WHERE pr.rolname='%s'" %
+ role_name)
+ oid = pg_cursor.fetchone()
+ role_id = ''
+ if oid:
+ role_id = oid[0]
+ connection.close()
+ return role_id
+ except Exception as exception:
+ exception = "Error while deleting role: %s: line:%s %s" % (
+ file_name, sys.exc_traceback.tb_lineno, exception)
+ print(exception, file=sys.stderr)
diff --git a/web/pgadmin/model/__init__.py b/web/pgadmin/model/__init__.py
index b33adc0..d24a350 100644
--- a/web/pgadmin/model/__init__.py
+++ b/web/pgadmin/model/__init__.py
@@ -94,6 +94,15 @@ class ServerGroup(db.Model):
name = db.Column(db.String(128), nullable=False)
__table_args__ = (db.UniqueConstraint('user_id', 'name'),)
+ @property
+ def serialize(self):
+ """Return object data in easily serializable format"""
+ return {
+ 'id': self.id,
+ 'user_id': self.user_id,
+ 'name': self.name,
+ }
+
class Server(db.Model):
"""Define a registered Postgres server"""
@@ -175,6 +184,44 @@ class Server(db.Model):
tunnel_password = db.Column(db.String(64), nullable=True)
shared = db.Column(db.Boolean(), nullable=False)
+ @property
+ def serialize(self):
+ """Return object data in easily serializable format"""
+ return {
+ "id": self.id,
+ "user_id": self.user_id,
+ "servergroup_id": self.servergroup_id,
+ "name": self.name,
+ "host": self.host,
+ "hostaddr": self.hostaddr,
+ "port": self.port,
+ "maintenance_db": self.maintenance_db,
+ "username": self.username,
+ "password": self.password,
+ "save_password": self.save_password,
+ "role": self.role,
+ "ssl_mode": self.ssl_mode,
+ "comment": self.comment,
+ "discovery_id": self.discovery_id,
+ "db_res": self.db_res,
+ "passfile": self.passfile,
+ "sslcert": self.sslcert,
+ "sslkey": self.sslkey,
+ "sslrootcert": self.sslrootcert,
+ "sslcrl": self.sslcrl,
+ "sslcompression": self.sslcompression,
+ "bgcolor": self.bgcolor,
+ "fgcolor": self.fgcolor,
+ "service": self.service,
+ "connect_timeout": self.connect_timeout,
+ "use_ssh_tunnel": self.use_ssh_tunnel,
+ "tunnel_host": self.tunnel_host,
+ "tunnel_port": self.tunnel_port,
+ "tunnel_authentication": self.tunnel_authentication,
+ "tunnel_identity_file": self.tunnel_identity_file,
+ "tunnel_password": self.tunnel_password
+ }
+
class ModulePreference(db.Model):
"""Define a preferences table for any modules."""
diff --git a/web/pgadmin/static/js/sqleditor/new_connection_dialog.js b/web/pgadmin/static/js/sqleditor/new_connection_dialog.js
new file mode 100644
index 0000000..a56d736
--- /dev/null
+++ b/web/pgadmin/static/js/sqleditor/new_connection_dialog.js
@@ -0,0 +1,252 @@
+/////////////////////////////////////////////////////////////
+//
+// pgAdmin 4 - PostgreSQL Tools
+//
+// Copyright (C) 2013 - 2020, The pgAdmin Development Team
+// This software is released under the PostgreSQL Licence
+//
+//////////////////////////////////////////////////////////////
+
+import gettext from 'sources/gettext';
+import url_for from 'sources/url_for';
+import $ from 'jquery';
+import Alertify from 'pgadmin.alertifyjs';
+import pgAdmin from 'sources/pgadmin';
+import Backform from 'pgadmin.backform';
+import newConnectionDialogModel from 'sources/sqleditor/new_connection_dialog_model';
+
+
+let NewConnectionDialog = {
+ 'dialog': function(handler, reconnect) {
+ let url = url_for('sqleditor.get_new_connection_data', {
+ 'sid': handler.url_params.sid,
+ 'sgid': handler.url_params.sgid,
+ });
+
+ if(reconnect) {
+ url += '?connect=1';
+ }
+
+ let title = gettext('Connect to server');
+
+ $.ajax({
+ url: url,
+ headers: {
+ 'Cache-Control' : 'no-cache',
+ },
+ }).done(function (res) {
+ let response = res.data.result;
+ response.database_list = [];
+ response.user_list = [];
+ if (Alertify.newConnectionDialog) {
+ delete Alertify.newConnectionDialog;
+ }
+
+ // Create Dialog
+ Alertify.dialog('newConnectionDialog', function factory() {
+ let $container = $('<div class=\'new-connection-dialog\'></div>');
+ return {
+ main: function(message) {
+ this.msg = message;
+ },
+ build: function() {
+ this.elements.content.appendChild($container.get(0));
+ Alertify.pgDialogBuild.apply(this);
+ },
+ 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: gettext('Help'),
+ 'aria-label': gettext('Help'),
+ url: url_for('help.static', {
+ 'filename': 'query_tool.html',
+ }),
+ },
+ },
+ {
+ text: gettext('Cancel'),
+ key: 27,
+ className: 'btn btn-secondary fa fa-times pg-alertify-button',
+ 'data-btn-name': 'cancel',
+ }, {
+ text: gettext('OK'),
+ key: 13,
+ className: 'btn btn-primary fa fa-check pg-alertify-button',
+ 'data-btn-name': 'ok',
+ },
+ ],
+ // Set options for dialog
+ options: {
+ title: title,
+ //disable both padding and overflow control.
+ padding: !1,
+ overflow: !1,
+ model: 0,
+ resizable: true,
+ maximizable: false,
+ pinnable: false,
+ closableByDimmer: false,
+ modal: false,
+ autoReset: false,
+ closable: true,
+ },
+ };
+ },
+ prepare: function() {
+ let self = this;
+ $container.html('');
+ // Disable Ok button
+ this.__internal.buttons[2].element.disabled = true;
+
+ // Status bar
+ this.statusBar = $(
+ '<div class=\'pg-prop-status-bar pg-el-xs-12 d-none\'>' +
+ ' <div class="error-in-footer"> ' +
+ ' <div class="d-flex px-2 py-1"> ' +
+ ' <div class="pr-2"> ' +
+ ' <i class="fa fa-exclamation-triangle text-danger" aria-hidden="true"></i> ' +
+ ' </div> ' +
+ ' <div class="alert-text" role="alert"></div> ' +
+ ' </div> ' +
+ ' </div> ' +
+ '</div>').appendTo($container);
+
+ // To show progress on filter Saving/Updating on AJAX
+ this.showNewConnectionProgress = $(
+ `<div id="show_filter_progress" class="pg-sp-container sql-editor-busy-fetching d-none">
+ <div class="pg-sp-content">
+ <div class="row"><div class="col-12 pg-sp-icon sql-editor-busy-icon"></div></div>
+ <div class="row"><div class="col-12 pg-sp-text sql-editor-busy-text">` + gettext('Loading data...') + `</div></div>
+ </div>
+ </div>`
+ ).appendTo($container);
+ $(
+ self.showNewConnectionProgress[0]
+ ).removeClass('d-none');
+
+ self.newConnCollectionModel = newConnectionDialogModel(response, handler.url_params.sgid, handler.url_params.sid);
+ let fields = Backform.generateViewSchema(null, self.newConnCollectionModel, 'create', null, null, true);
+
+ let view = this.view = new Backform.Dialog({
+ el: '<div></div>',
+ model: self.newConnCollectionModel,
+ schema: fields,
+ });
+
+ $(this.elements.body.childNodes[0]).addClass(
+ 'alertify_tools_dialog_properties obj_properties'
+ );
+
+ $container.append(view.render().$el);
+
+ // Enable/disable save button and show/hide statusbar based on session
+ view.listenTo(view.model, 'pgadmin-session:start', function() {
+ view.listenTo(view.model, 'pgadmin-session:invalid', function(msg) {
+ self.statusBar.removeClass('d-none');
+ $(self.statusBar.find('.alert-text')).html(msg);
+ // Disable Okay button
+ self.__internal.buttons[2].element.disabled = true;
+ });
+
+ view.listenTo(view.model, 'pgadmin-session:valid', function() {
+ self.statusBar.addClass('d-none');
+ $(self.statusBar.find('.alert-text')).html('');
+ // Enable Okay button
+ self.__internal.buttons[2].element.disabled = false;
+ });
+ });
+
+ view.listenTo(view.model, 'pgadmin-session:stop', function() {
+ view.stopListening(view.model, 'pgadmin-session:invalid');
+ view.stopListening(view.model, 'pgadmin-session:valid');
+ });
+
+ // Starts monitoring changes to model
+ view.model.startNewSession();
+
+ // Hide Progress ...
+ $(
+ self.showNewConnectionProgress[0]
+ ).addClass('d-none');
+ },
+ callback: function(e) {
+ let self = this;
+ if (e.button.element.name == 'dialog_help') {
+ e.cancel = true;
+ pgAdmin.Browser.showHelp(e.button.element.name, e.button.element.getAttribute('url'),
+ null, null);
+ return;
+ } else if (e.button['data-btn-name'] === 'ok') {
+ e.cancel = true; // Do not close dialog
+ let newConnCollectionModel = this.newConnCollectionModel.toJSON();
+ let selected_database_name = null;
+ response.database_list.forEach(function(data){
+ if(newConnCollectionModel['database'] == data['value']) {
+ selected_database_name = data['label'];
+ return false;
+ }
+ });
+ let is_create_connection = true;
+ let title = selected_database_name + '/' + newConnCollectionModel['user'] + '@' + response.server_name;
+ handler.gridView.connection_list.forEach(function(connection_data){
+ if(parseInt(connection_data['server']) == newConnCollectionModel['server']
+ && parseInt(connection_data['database']) == newConnCollectionModel['database']
+ && connection_data['user'] == newConnCollectionModel['user']) {
+ is_create_connection = false;
+ // break for loop by return false.
+ return false;
+ }
+
+ if(title == connection_data['title']) {
+ is_create_connection = false;
+ return false;
+ }
+ });
+ if(!is_create_connection) {
+ let errmsg = 'Connection with this configuration already present.';
+ Alertify.error(errmsg);
+ }else {
+ let connection_details = {
+ 'server_group': handler.gridView.handler.url_params.sgid,
+ 'server': newConnCollectionModel['server'],
+ 'database': newConnCollectionModel['database'],
+ 'title': title,
+ 'user': newConnCollectionModel['user'],
+ 'password': newConnCollectionModel['password'],
+ };
+ handler.gridView.on_change_connection(connection_details, self);
+ }
+ } else {
+ self.close();
+ }
+ },
+ };
+ });
+ setTimeout(function(){
+ Alertify.newConnectionDialog('Connect to server.').resizeTo(pgAdmin.Browser.stdW.md,pgAdmin.Browser.stdH.md);
+ }, 500);
+ }).fail(function(error) {
+ Alertify.alert().setting({
+ 'title': gettext('Connection lost'),
+ 'label':gettext('Ok'),
+ 'message': gettext('Connection to the server has been lost.'),
+ 'onok': function(){
+ alert(error);
+ //Close the window after connection is lost
+ window.close();
+ },
+ }).show();
+ });
+
+ },
+
+};
+
+module.exports = NewConnectionDialog;
diff --git a/web/pgadmin/static/js/sqleditor/new_connection_dialog_model.js b/web/pgadmin/static/js/sqleditor/new_connection_dialog_model.js
new file mode 100644
index 0000000..7f309cd
--- /dev/null
+++ b/web/pgadmin/static/js/sqleditor/new_connection_dialog_model.js
@@ -0,0 +1,228 @@
+/////////////////////////////////////////////////////////////
+//
+// pgAdmin 4 - PostgreSQL Tools
+//
+// Copyright (C) 2013 - 2020, The pgAdmin Development Team
+// This software is released under the PostgreSQL Licence
+//
+//////////////////////////////////////////////////////////////
+
+import gettext from 'sources/gettext';
+import _ from 'underscore';
+import $ from 'jquery';
+import pgAdmin from 'sources/pgadmin';
+import Backform from 'pgadmin.backform';
+import url_for from 'sources/url_for';
+import alertify from 'pgadmin.alertifyjs';
+
+export default function newConnectionDialogModel(response, sgid, sid) {
+
+ let server_name = '';
+ let database_name = '';
+
+ let NewConnectionSelect2Control = Backform.Select2Control.extend({
+ fetchData: function(){
+ let self = this;
+ url = self.field.get('url');
+
+ let url = url_for(url, {
+ 'sid': self.model.attributes.server,
+ 'sgid': sgid,
+ });
+
+ $.ajax({
+ async: false,
+ url: url,
+ headers: {
+ 'Cache-Control' : 'no-cache',
+ },
+ }).done(function (res) {
+ var transform = self.field.get('transform');
+ if(res.data.status){
+ let data = res.data.result.data;
+
+ if (transform && _.isFunction(transform)) {
+ self.field.set('options', transform.bind(self, data));
+ } else {
+ self.field.set('options', data);
+ }
+ } else {
+ if (transform && _.isFunction(transform)) {
+ self.field.set('options', transform.bind(self, []));
+ } else {
+ self.field.set('options', []);
+ }
+ alertify.error(res.data.msg);
+ }
+ }).fail(function(e){
+ let msg = '';
+ if(e.status == 404) {
+ msg = 'Unable to find url.';
+ } else {
+ msg = e.responseJSON.errormsg;
+ }
+ alertify.error(msg);
+ });
+ },
+ render: function() {
+ this.fetchData();
+ return Backform.Select2Control.prototype.render.apply(this, arguments);
+ },
+ onChange: function() {
+ Backform.Select2Control.prototype.onChange.apply(this, arguments);
+ },
+ });
+
+ let newConnectionModel = pgAdmin.Browser.DataModel.extend({
+ idAttribute: 'name',
+ defaults: {
+ server: parseInt(sid),
+ database: null,
+ user: null,
+ password: null,
+ server_name: server_name,
+ database_name: database_name,
+ },
+ schema: [{
+ id: 'server',
+ name: 'server',
+ label: gettext('Server'),
+ type: 'text',
+ editable: true,
+ disabled: false,
+ select2: {
+ allowClear: false,
+ },
+ control: Backform.Select2Control.extend({
+ onChange: function() {
+ this.model.attributes.database = null;
+ this.model.attributes.user = null;
+ let self = this;
+ Backform.Select2Control.prototype.onChange.apply(this, arguments);
+
+ response.server_list.forEach(function(obj){
+ if(obj.id==self.model.changed.server) {
+ response.server_name = obj.name;
+ }
+ });
+ },
+ }),
+ options: function() {
+ return _.map(response.server_list, (obj) => {
+ if (obj.id == parseInt(sid))
+ response.server_name = obj.name;
+
+ return {
+ value: obj.id,
+ label: obj.name,
+ };
+ });
+ },
+ },
+ {
+ id: 'database',
+ name: 'database',
+ label: gettext('Database'),
+ type: 'text',
+ editable: true,
+ disabled: function(m) {
+ let self_local = this;
+ if (!_.isUndefined(m.get('server')) && !_.isNull(m.get('server'))
+ && m.get('server') !== '') {
+ setTimeout(function() {
+ if(self_local.options.length) {
+ m.set('database', self_local.options[0].value);
+ }
+ }, 10);
+ return false;
+ }
+
+ return true;
+ },
+ deps: ['server'],
+ url: 'sqleditor.get_new_connection_database',
+ select2: {
+ allowClear: false,
+ width: '100%',
+ first_empty: true,
+ select_first: false,
+ },
+ extraClasses:['new-connection-dialog-style'],
+ control: NewConnectionSelect2Control,
+ transform: function(data) {
+ response.database_list = data;
+ return data;
+ },
+ },
+ {
+ id: 'user',
+ name: 'user',
+ label: gettext('User'),
+ type: 'text',
+ editable: true,
+ deps: ['server'],
+ select2: {
+ allowClear: false,
+ width: '100%',
+ },
+ control: NewConnectionSelect2Control,
+ url: 'sqleditor.get_new_connection_user',
+ disabled: function(m) {
+ let self_local = this;
+ if (!_.isUndefined(m.get('server')) && !_.isNull(m.get('server'))
+ && m.get('server') !== '') {
+ setTimeout(function() {
+ if(self_local.options.length) {
+ m.set('user', self_local.options[0].value);
+ }
+ }, 10);
+ return false;
+ }
+ return true;
+ },
+ },
+ {
+ id: 'password',
+ name: 'password',
+ label: gettext('Password'),
+ type: 'password',
+ editable: true,
+ disabled: false,
+ deps: ['user'],
+ control: Backform.InputControl.extend({
+ render: function() {
+ let self = this;
+ self.model.attributes.password = null;
+ Backform.InputControl.prototype.render.apply(self, arguments);
+ return self;
+ },
+ onChange: function() {
+ let self = this;
+ Backform.InputControl.prototype.onChange.apply(self, arguments);
+ },
+ }),
+ },
+ ],
+ validate: function() {
+ let msg = null;
+ this.errorModel.clear();
+ if(_.isUndefined(this.get('database')) || _.isNull(this.get('database'))){
+ msg = gettext('Please select database');
+ this.errorModel.set('database', msg);
+ return msg;
+ } else if(_.isUndefined(this.get('database')) || _.isUndefined(this.get('user'))|| _.isNull(this.get('user'))) {
+ msg = gettext('Please select user');
+ this.errorModel.set('user', msg);
+ return msg;
+ } else if((this.attributes.password == '' || _.isUndefined(this.get('password')) || _.isNull(this.get('password')))) {
+ msg = gettext('Please enter password');
+ this.errorModel.set('password', msg);
+ return msg;
+ }
+ return null;
+ },
+ });
+
+ let model = new newConnectionModel();
+ return model;
+}
diff --git a/web/pgadmin/static/scss/_alert.scss b/web/pgadmin/static/scss/_alert.scss
index dac552b..836f0af 100644
--- a/web/pgadmin/static/scss/_alert.scss
+++ b/web/pgadmin/static/scss/_alert.scss
@@ -92,6 +92,7 @@
right: 0;
left: 0;
bottom: 0;
+ z-index: 1;
}
.pg-prop-status-bar {
diff --git a/web/pgadmin/tools/datagrid/__init__.py b/web/pgadmin/tools/datagrid/__init__.py
index f5fc78c..5f32e74 100644
--- a/web/pgadmin/tools/datagrid/__init__.py
+++ b/web/pgadmin/tools/datagrid/__init__.py
@@ -18,21 +18,22 @@ from flask import Response, url_for, session, request, make_response
from werkzeug.useragents import UserAgent
from flask import current_app as app, render_template
from flask_babelex import gettext
-from flask_security import login_required
+from flask_security import login_required, current_user
from pgadmin.tools.sqleditor.command import ObjectRegistry, SQLFilter
+from pgadmin.tools.sqleditor import check_transaction_status
from pgadmin.utils import PgAdminModule
from pgadmin.utils.ajax import make_json_response, bad_request, \
- internal_server_error
+ internal_server_error, unauthorized
from config import PG_DEFAULT_DRIVER
-from pgadmin.model import Server
+from pgadmin.model import Server, User
from pgadmin.utils.driver import get_driver
from pgadmin.utils.exception import ConnectionLost, SSHTunnelConnectionLost
from pgadmin.utils.preferences import Preferences
from pgadmin.settings import get_setting
from pgadmin.browser.utils import underscore_unescape
from pgadmin.utils.exception import ObjectGone
-from pgadmin.utils.constants import MIMETYPE_APP_JS
+from pgadmin.utils.constants import MIMETYPE_APP_JS, UNAUTH_REQ
MODULE_NAME = 'datagrid'
@@ -73,7 +74,8 @@ class DataGridModule(PgAdminModule):
'datagrid.filter_validate',
'datagrid.filter',
'datagrid.panel',
- 'datagrid.close'
+ 'datagrid.close',
+ 'datagrid.update_query_tool_connection'
]
def on_logout(self, user):
@@ -320,10 +322,23 @@ def initialize_query_tool(trans_id, sgid, sid, did=None):
req_args['recreate'] == '1'):
connect = False
+ is_error, errmsg, conn_id, version = _init_query_tool(trans_id, connect,
+ sgid, sid, did)
+ if is_error:
+ return errmsg
+
+ return make_json_response(
+ data={
+ 'connId': str(conn_id),
+ 'serverVersion': version,
+ }
+ )
+
+
+def _init_query_tool(trans_id, connect, sgid, sid, did, **kwargs):
# Create asynchronous connection using random connection id.
conn_id = str(random.randint(1, 9999999))
- # Use Maintenance database OID
manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(sid)
if did is None:
@@ -334,7 +349,7 @@ def initialize_query_tool(trans_id, sgid, sid, did=None):
)
except Exception as e:
app.logger.error(e)
- return internal_server_error(errormsg=str(e))
+ return True, internal_server_error(errormsg=str(e)), '', ''
try:
conn = manager.connection(did=did, conn_id=conn_id,
@@ -342,16 +357,26 @@ def initialize_query_tool(trans_id, sgid, sid, did=None):
use_binary_placeholder=True,
array_to_string=True)
if connect:
- status, msg = conn.connect()
+ user = None
+ password = None
+
+ if 'user' in kwargs and 'password' in kwargs:
+ user = kwargs['user']
+ password = kwargs['password']
+
+ if user:
+ status, msg = conn.connect(user=user, password=password)
+ else:
+ status, msg = conn.connect()
if not status:
app.logger.error(msg)
- return internal_server_error(errormsg=str(msg))
+ return True, internal_server_error(errormsg=str(msg)), '', ''
except (ConnectionLost, SSHTunnelConnectionLost) as e:
app.logger.error(e)
raise
except Exception as e:
app.logger.error(e)
- return internal_server_error(errormsg=str(e))
+ return True, internal_server_error(errormsg=str(e)), '', ''
if 'gridData' not in session:
sql_grid_data = dict()
@@ -373,10 +398,79 @@ def initialize_query_tool(trans_id, sgid, sid, did=None):
# Store the grid dictionary into the session variable
session['gridData'] = sql_grid_data
+ return False, '', conn_id, manager.version
+
+
[email protected](
+ '/initialize/query_tool/update_connection/<int:trans_id>/'
+ '<int:sgid>/<int:sid>/<int:did>',
+ methods=["POST"], endpoint='update_query_tool_connection'
+)
+def update_query_tool_connection(trans_id, sgid, sid, did):
+ # Remove transaction Id.
+ with query_tool_close_session_lock:
+ data = dict()
+ if request.data:
+ data = json.loads(request.data, encoding='utf-8')
+
+ if 'gridData' not in session:
+ return make_json_response(data={'status': True})
+
+ grid_data = session['gridData']
+
+ # Return from the function if transaction id not found
+ if str(trans_id) not in grid_data:
+ return make_json_response(data={'status': True})
+
+ connect = True
+
+ req_args = request.args
+ if ('recreate' in req_args and
+ req_args['recreate'] == '1'):
+ connect = False
+
+ new_trans_id = str(random.randint(1, 9999999))
+ kwargs = {
+ 'user': data['user'],
+ 'password': data['password']
+ }
+
+ is_error, errmsg, conn_id, version = _init_query_tool(
+ new_trans_id, connect, sgid, sid, did, **kwargs)
+
+ if is_error:
+ return errmsg
+ else:
+ try:
+ # Check the transaction and connection status
+ status, error_msg, conn, trans_obj, session_obj = \
+ check_transaction_status(trans_id)
+
+ status, error_msg, new_conn, new_trans_obj, new_session_obj = \
+ check_transaction_status(new_trans_id)
+
+ new_session_obj['primary_keys'] = session_obj[
+ 'primary_keys'] if 'primary_keys' in session_obj else None
+ new_session_obj['columns_info'] = session_obj[
+ 'columns_info'] if 'columns_info' in session_obj else None
+ new_session_obj['client_primary_key'] = session_obj[
+ 'client_primary_key'] if 'client_primary_key'\
+ in session_obj else None
+
+ close_query_tool_session(trans_id)
+ # Remove the information of unique transaction id from the
+ # session variable.
+ grid_data.pop(str(trans_id), None)
+ session['gridData'] = grid_data
+ except Exception as e:
+ app.logger.error(e)
+ # return internal_server_error(errormsg=str(e))
+
return make_json_response(
data={
'connId': str(conn_id),
- 'serverVersion': manager.version,
+ 'serverVersion': version,
+ 'tran_id': new_trans_id
}
)
diff --git a/web/pgadmin/tools/datagrid/templates/datagrid/index.html b/web/pgadmin/tools/datagrid/templates/datagrid/index.html
index e81a42a..fb2526f 100644
--- a/web/pgadmin/tools/datagrid/templates/datagrid/index.html
+++ b/web/pgadmin/tools/datagrid/templates/datagrid/index.html
@@ -391,8 +391,17 @@
title="" role="img">
</i>
</div>
- <div class="editor-title"
- style="background-color: {% if fgcolor %}{{ bgcolor or '#FFFFFF' }}{% endif %}; color: {% if fgcolor %}{{ fgcolor }}{% endif %};"> </div>
+ <div class="connection-info btn-group mr-1" role="group" aria-label="">
+ <div class="editor-title" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"
+ style="background-color: {% if fgcolor %}{{ bgcolor or '#FFFFFF' }}{% endif %}; color: {% if fgcolor %}{{ fgcolor }}{% endif %};">
+ </div>
+ <span class="conn-info-dd dropdown-toggle dropdown-toggle-split"
+ data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></span>
+ <ul class="dropdown-menu" id="connections-list">
+ </ul>
+ </div>
+
+
</div>
<div id="editor-panel" tabindex="0">
<div id="fetching_data" class="pg-sp-container sql-editor-busy-fetching">
@@ -455,6 +464,7 @@ require(['sources/generated/browser_nodes', 'sources/generated/codemirror', 'sou
var script_type_url = '';
{% endif %}
// Start the query tool.
+
sqlEditorController.start(
{{ uniqueId }},
{{ url_params|safe}},
diff --git a/web/pgadmin/tools/datagrid/tests/__init__.py b/web/pgadmin/tools/datagrid/tests/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/web/pgadmin/tools/datagrid/tests/datagrid_test_data.json b/web/pgadmin/tools/datagrid/tests/datagrid_test_data.json
new file mode 100644
index 0000000..a50992f
--- /dev/null
+++ b/web/pgadmin/tools/datagrid/tests/datagrid_test_data.json
@@ -0,0 +1,134 @@
+{
+ "data_grid_init_query_tool": [
+ {
+ "name": "Datagrid init query tool",
+ "url": "/datagrid/initialize/query_tool/",
+ "is_positive_test": true,
+ "mocking_required": false,
+ "test_data": {},
+ "mock_data": {},
+ "expected_data": {
+ "status_code": 200
+ }
+ }
+ ],
+ "data_grid_query_tool_close": [
+ {
+ "name": "Datagrid query tool close",
+ "url": "/datagrid/close/",
+ "is_positive_test": true,
+ "mocking_required": false,
+ "test_data": {},
+ "mock_data": {},
+ "expected_data": {
+ "status_code": 200
+ }
+ }
+ ],
+ "data_grid_validate_filter": [
+ {
+ "name": "Datagrid validate filter",
+ "url": "/datagrid/filter/validate/",
+ "is_positive_test": true,
+ "mocking_required": false,
+ "test_data": "id = 1",
+ "mock_data": {},
+ "expected_data": {
+ "status_code": 200
+ }
+ },
+ {
+ "name": "Datagrid validate filter",
+ "url": "/datagrid/filter/validate/",
+ "is_positive_test": false,
+ "mocking_required": true,
+ "test_data": "id = 1",
+ "mock_data": {
+ "function_name": "pgadmin.utils.driver.psycopg2.connection.Connection.execute_scalar",
+ "return_value": "(False, 'Mocked Internal Server Error while validate filter')"
+ },
+ "expected_data": {
+ "status_code": 200
+ }
+ }
+ ],
+ "data_grid_update_connection": [
+ {
+ "name": "Datagrid update connection positive",
+ "url": "/datagrid/initialize/query_tool/update_connection/",
+ "is_positive_test": true,
+ "mocking_required": false,
+ "is_create_role": false,
+ "test_data": {},
+ "mock_data": {},
+ "expected_data": {
+ "status_code": 200
+ }
+ },
+ {
+ "name": "Datagrid update connection with new user",
+ "url": "/datagrid/initialize/query_tool/update_connection/",
+ "is_positive_test": true,
+ "mocking_required": false,
+ "is_create_role": true,
+ "test_data": {},
+ "mock_data": {},
+ "expected_data": {
+ "status_code": 200
+ }
+ }
+ ],
+ "data_grid_panel": [
+ {
+ "name": "Datagrid Panel",
+ "url": "/datagrid/panel/",
+ "is_positive_test": true,
+ "mocking_required": false,
+ "test_data": {},
+ "mock_data": {
+ },
+ "expected_data": {
+ "status_code": 500
+ }
+ }
+ ],
+ "data_grid_initialize": [
+ {
+ "name": "Datagrid Initialize",
+ "url": "/datagrid/initialize/datagrid/",
+ "is_positive_test": true,
+ "mocking_required": false,
+ "test_data": "id=1",
+ "mock_data": {
+
+ },
+ "expected_data": {
+ "status_code": 200
+ }
+ },{
+ "name": "Datagrid Initialize",
+ "url": "/datagrid/initialize/datagrid/",
+ "is_positive_test": true,
+ "mocking_required": false,
+ "test_data": null,
+ "mock_data": {},
+ "expected_data": {
+ "status_code": 200
+ }
+ },
+ {
+ "name": "Datagrid Initialize",
+ "url": "/datagrid/initialize/datagrid/",
+ "is_positive_test": false,
+ "mocking_required": true,
+ "test_data": "id=1",
+ "mock_data": {
+ "function_name": "pgadmin.utils.driver.psycopg2.connection.Connection.execute_dict",
+ "return_value": "(False, 'Mocked Internal Server Error while initialize datagrid.')"
+ },
+ "expected_data": {
+ "status_code": 500
+ }
+ }
+ ]
+}
diff --git a/web/pgadmin/tools/datagrid/tests/test_data_grid_init_query_tool.py b/web/pgadmin/tools/datagrid/tests/test_data_grid_init_query_tool.py
new file mode 100644
index 0000000..6ecf5de
--- /dev/null
+++ b/web/pgadmin/tools/datagrid/tests/test_data_grid_init_query_tool.py
@@ -0,0 +1,72 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2020, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+
+
+import json
+import uuid
+import random
+
+from unittest.mock import patch
+from pgadmin.browser.server_groups.servers.databases.tests import utils as \
+ database_utils
+
+from pgadmin.utils.route import BaseTestGenerator
+from regression import parent_node_dict
+from regression.python_test_utils import test_utils as utils
+from regression.test_setup import config_data
+from . import utils as data_grid_utils
+
+
+class DatagridInitQueryToolTestCase(BaseTestGenerator):
+ """
+ This will init query-tool connection.
+ """
+
+ scenarios = utils.generate_scenarios(
+ 'data_grid_init_query_tool',
+ data_grid_utils.test_cases
+ )
+
+ def setUp(self):
+ self.database_info = parent_node_dict["database"][-1]
+ self.db_name = self.database_info["db_name"]
+ self.did = self.database_info["db_id"]
+ self.sid = parent_node_dict["server"][-1]["server_id"]
+ self.sgid = config_data['server_group']
+
+ db_con = database_utils.connect_database(self, utils.SERVER_GROUP,
+ self.sid, self.did)
+
+ self.trans_id = str(random.randint(1, 9999999))
+
+ if not db_con['data']["connected"]:
+ raise Exception("Could not connect to database to add a table.")
+
+ def init_query_tool(self):
+ response = self.tester.post(
+ self.url + str(self.trans_id) + '/' + str(self.sgid) + '/' + str(
+ self.sid) + '/' + str(self.did),
+ content_type='html/json'
+ )
+ return response
+
+ def runTest(self):
+ """ This function will init query tool connection."""
+
+ if self.is_positive_test:
+ response = self.init_query_tool()
+ actual_response_code = response.status_code
+ expected_response_code = self.expected_data['status_code']
+
+ self.assertEqual(actual_response_code, expected_response_code)
+
+ def tearDown(self):
+ """This function disconnect database."""
+ database_utils.disconnect_database(self, self.sid,
+ self.did)
diff --git a/web/pgadmin/tools/datagrid/tests/test_data_grid_panel.py b/web/pgadmin/tools/datagrid/tests/test_data_grid_panel.py
new file mode 100644
index 0000000..5ab6a6b
--- /dev/null
+++ b/web/pgadmin/tools/datagrid/tests/test_data_grid_panel.py
@@ -0,0 +1,92 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2020, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+
+
+import json
+import uuid
+import random
+
+from unittest.mock import patch
+from pgadmin.browser.server_groups.servers.databases.tests import utils as \
+ database_utils
+
+from pgadmin.utils.route import BaseTestGenerator
+from regression import parent_node_dict
+from regression.python_test_utils import test_utils as utils
+from regression.test_setup import config_data
+from pgadmin.browser.server_groups.servers.databases.schemas.tests import \
+ utils as schema_utils
+from pgadmin.browser.server_groups.servers.databases.schemas.tables.tests \
+ import utils as tables_utils
+from . import utils as data_grid_utils
+
+
+class DatagridPanelTestCase(BaseTestGenerator):
+ """
+ This will data grid panel.
+ """
+
+ scenarios = utils.generate_scenarios(
+ 'data_grid_panel',
+ data_grid_utils.test_cases
+ )
+
+ def setUp(self):
+ self.database_info = parent_node_dict["database"][-1]
+ self.db_name = self.database_info["db_name"]
+ self.did = self.database_info["db_id"]
+ self.sid = parent_node_dict["server"][-1]["server_id"]
+ self.sgid = config_data['server_group']
+
+ db_con = database_utils.connect_database(self, utils.SERVER_GROUP,
+ self.sid, self.did)
+ if not db_con['data']["connected"]:
+ raise Exception("Could not connect to database to add a table.")
+
+ self.trans_id = str(random.randint(1, 9999999))
+ qt_init = data_grid_utils._init_query_tool(self, self.trans_id,
+ self.sgid, self.sid,
+ self.did)
+
+ if not qt_init['success']:
+ raise Exception("Could not initialize querty tool.")
+
+ def panel(self):
+ query_param = \
+ '?is_query_tool={0}&sgid={1}&sid={2}&server_type={3}' \
+ '&did={4}'.format(True, self.sgid, self.sid,
+ self.server_information['type'], self.did)
+
+ response = self.tester.post(
+ self.url + str(self.trans_id) + query_param,
+ data=json.dumps(self.test_data),
+ content_type='html/json'
+ )
+ return response
+
+ def runTest(self):
+ """ This function will update query tool connection."""
+
+ if self.is_positive_test:
+ response = self.panel()
+ actual_response_code = response.status_code
+ expected_response_code = self.expected_data['status_code']
+ else:
+ with patch(self.mock_data["function_name"],
+ return_value=eval(self.mock_data["return_value"])):
+ response = self.panel()
+ actual_response_code = response.status_code
+ expected_response_code = self.expected_data['status_code']
+
+ self.assertEqual(actual_response_code, expected_response_code)
+
+ def tearDown(self):
+ """This function disconnect database."""
+ database_utils.disconnect_database(self, self.sid,
+ self.did)
diff --git a/web/pgadmin/tools/datagrid/tests/test_data_grid_query_tool_close.py b/web/pgadmin/tools/datagrid/tests/test_data_grid_query_tool_close.py
new file mode 100644
index 0000000..d1a0a97
--- /dev/null
+++ b/web/pgadmin/tools/datagrid/tests/test_data_grid_query_tool_close.py
@@ -0,0 +1,90 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2020, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+
+
+import json
+import uuid
+import random
+
+from unittest.mock import patch
+from pgadmin.browser.server_groups.servers.databases.tests import utils as \
+ database_utils
+
+from pgadmin.utils.route import BaseTestGenerator
+from regression import parent_node_dict
+from regression.python_test_utils import test_utils as utils
+from regression.test_setup import config_data
+from . import utils as data_grid_utils
+
+
+class DatagridQueryToolCloseTestCase(BaseTestGenerator):
+ """
+ This will close query-tool connection.
+ """
+
+ scenarios = utils.generate_scenarios(
+ 'data_grid_query_tool_close',
+ data_grid_utils.test_cases
+ )
+
+ def setUp(self):
+ self.database_info = parent_node_dict["database"][-1]
+ self.db_name = self.database_info["db_name"]
+ self.did = self.database_info["db_id"]
+ self.sid = parent_node_dict["server"][-1]["server_id"]
+ self.sgid = config_data['server_group']
+
+ db_con = database_utils.connect_database(self, utils.SERVER_GROUP,
+ self.sid, self.did)
+
+ if not db_con['data']["connected"]:
+ raise Exception("Could not connect to database to add a table.")
+
+ self.trans_id = str(random.randint(1, 9999999))
+ qt_init = data_grid_utils._init_query_tool(self, self.trans_id,
+ self.sgid, self.sid,
+ self.did)
+
+ if not qt_init['success']:
+ raise Exception("Could not initialize querty tool.")
+
+ self.test_data = {
+ "database": self.did,
+ "server": self.sid
+ }
+
+ if self.server_information['type'] == 'ppas':
+ self.test_data['password'] = 'enterprisedb'
+ self.test_data['user'] = 'enterprisedb'
+ else:
+ self.test_data['password'] = 'root'
+ self.test_data['user'] = 'postgres'
+
+ def close_connection(self):
+ response = self.tester.delete(
+ self.url + str(self.trans_id),
+
+ content_type='html/json'
+ )
+ return response
+
+ def runTest(self):
+ """ This function will update query tool connection."""
+
+ if self.is_positive_test:
+ response = self.close_connection()
+ actual_response_code = response.status_code
+ expected_response_code = self.expected_data['status_code']
+
+ self.assertEqual(actual_response_code, expected_response_code)
+
+ def tearDown(self):
+ """This function disconnect database."""
+ database_utils.disconnect_database(self, self.sid,
+ self.did)
diff --git a/web/pgadmin/tools/datagrid/tests/test_data_grid_update_connection.py b/web/pgadmin/tools/datagrid/tests/test_data_grid_update_connection.py
new file mode 100644
index 0000000..a21c38e
--- /dev/null
+++ b/web/pgadmin/tools/datagrid/tests/test_data_grid_update_connection.py
@@ -0,0 +1,119 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2020, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+
+
+import json
+import uuid
+import random
+
+from unittest.mock import patch
+from pgadmin.browser.server_groups.servers.databases.tests import utils as \
+ database_utils
+
+from pgadmin.utils.route import BaseTestGenerator
+from regression import parent_node_dict
+from regression.python_test_utils import test_utils as utils
+from regression.test_setup import config_data
+from pgadmin.browser.server_groups.servers.roles.tests import \
+ utils as roles_utils
+from . import utils as data_grid_utils
+
+
+class DatagridUpdateConnectionTestCase(BaseTestGenerator):
+ """
+ This will update query-tool connection.
+ """
+
+ scenarios = utils.generate_scenarios(
+ 'data_grid_update_connection',
+ data_grid_utils.test_cases
+ )
+
+ def setUp(self):
+ self.database_info = parent_node_dict["database"][-1]
+ self.db_name = self.database_info["db_name"]
+ self.did = self.database_info["db_id"]
+ self.sid = parent_node_dict["server"][-1]["server_id"]
+ self.sgid = config_data['server_group']
+
+ db_con = database_utils.connect_database(self, utils.SERVER_GROUP,
+ self.sid, self.did)
+
+ self.trans_id = str(random.randint(1, 9999999))
+ self.roles = None
+
+ if self.is_create_role:
+ data = roles_utils.get_role_data(self.server['db_password'])
+ self.role_name = data['rolname']
+ self.role_password = data['rolpassword']
+ roles_utils.create_role_with_password(
+ self.server, self.role_name, self.role_password)
+
+ if not self.is_positive_test or self.is_create_role:
+ qt_init = data_grid_utils._init_query_tool(self, self.trans_id,
+ self.sgid, self.sid,
+ self.did)
+
+ if not qt_init['success']:
+ raise Exception("Could not initialize querty tool.")
+
+ self.test_data = {
+ "database": self.did,
+ "server": self.sid
+ }
+
+ if self.server_information['type'] == 'ppas':
+ self.test_data['password'] = 'enterprisedb'
+ self.test_data['user'] = 'enterprisedb'
+ else:
+ self.test_data['password'] = 'root'
+ self.test_data['user'] = 'postgres'
+
+ if not db_con['data']["connected"]:
+ raise Exception("Could not connect to database to add a table.")
+
+ def update_connection(self, user_data=None):
+ if user_data:
+ response = self.tester.post(
+ self.url + str(self.trans_id) + '/' + str(self.sgid) +
+ '/' + str(self.sid) + '/' + str(self.did),
+ data=json.dumps(user_data),
+ content_type='html/json'
+ )
+ else:
+ response = self.tester.post(
+ self.url + str(self.trans_id) + '/' + str(self.sgid) + '/' +
+ str(self.sid) + '/' + str(self.did),
+ data=json.dumps(self.test_data),
+ content_type='html/json'
+ )
+ return response
+
+ def runTest(self):
+ """ This function will update query tool connection."""
+
+ if self.is_positive_test:
+ user_data = dict()
+ if self.is_create_role:
+ user_data['user'] = self.role_name
+ user_data['password'] = self.role_password
+ response = self.update_connection(user_data=user_data)
+ actual_response_code = response.status_code
+ expected_response_code = self.expected_data['status_code']
+ else:
+ response = self.update_connection()
+ actual_response_code = response.status_code
+ expected_response_code = self.expected_data['status_code']
+
+ self.assertEqual(actual_response_code, expected_response_code)
+
+ def tearDown(self):
+ """This function disconnect database."""
+ database_utils.disconnect_database(self, self.sid,
+ self.did)
diff --git a/web/pgadmin/tools/datagrid/tests/test_data_grid_validate_filter.py b/web/pgadmin/tools/datagrid/tests/test_data_grid_validate_filter.py
new file mode 100644
index 0000000..0aba5d8
--- /dev/null
+++ b/web/pgadmin/tools/datagrid/tests/test_data_grid_validate_filter.py
@@ -0,0 +1,91 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2020, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+
+
+import json
+import uuid
+import random
+
+from unittest.mock import patch
+from pgadmin.browser.server_groups.servers.databases.tests import utils as \
+ database_utils
+
+from pgadmin.utils.route import BaseTestGenerator
+from regression import parent_node_dict
+from regression.python_test_utils import test_utils as utils
+from regression.test_setup import config_data
+from pgadmin.browser.server_groups.servers.databases.schemas.tests import \
+ utils as schema_utils
+from pgadmin.browser.server_groups.servers.databases.schemas.tables.tests \
+ import utils as tables_utils
+from . import utils as data_grid_utils
+
+
+class DatagridValidateFilterTestCase(BaseTestGenerator):
+ """
+ This will validate filter connection.
+ """
+
+ scenarios = utils.generate_scenarios(
+ 'data_grid_validate_filter',
+ data_grid_utils.test_cases
+ )
+
+ def setUp(self):
+ self.database_info = parent_node_dict["database"][-1]
+ self.db_name = self.database_info["db_name"]
+ self.did = self.database_info["db_id"]
+ self.sid = parent_node_dict["server"][-1]["server_id"]
+ self.sgid = config_data['server_group']
+
+ db_con = database_utils.connect_database(self, utils.SERVER_GROUP,
+ self.sid, self.did)
+ if not db_con['data']["connected"]:
+ raise Exception("Could not connect to database to add a table.")
+ self.schema_id = parent_node_dict['schema'][-1]["schema_id"]
+ self.schema_name = parent_node_dict['schema'][-1]["schema_name"]
+ schema_response = schema_utils.verify_schemas(self.server,
+ self.db_name,
+ self.schema_name)
+ if not schema_response:
+ raise Exception("Could not find the schema to add a table.")
+ self.table_name = "table_for_wizard%s" % (str(uuid.uuid4())[1:8])
+ self.table_id = tables_utils.create_table(self.server, self.db_name,
+ self.schema_name,
+ self.table_name)
+
+ def validate_filter(self):
+ response = self.tester.post(
+ self.url + str(self.sid) + '/' + str(self.did) + '/' +
+ str(self.table_id),
+ data=json.dumps(self.test_data),
+ content_type='html/json'
+ )
+ return response
+
+ def runTest(self):
+ """ This function will update query tool connection."""
+
+ if self.is_positive_test:
+ response = self.validate_filter()
+ actual_response_code = response.status_code
+ expected_response_code = self.expected_data['status_code']
+ else:
+ with patch(self.mock_data["function_name"],
+ return_value=eval(self.mock_data["return_value"])):
+ response = self.validate_filter()
+ actual_response_code = response.status_code
+ expected_response_code = self.expected_data['status_code']
+
+ self.assertEqual(actual_response_code, expected_response_code)
+
+ def tearDown(self):
+ """This function disconnect database."""
+ database_utils.disconnect_database(self, self.sid,
+ self.did)
diff --git a/web/pgadmin/tools/datagrid/tests/test_initialize_data_grid.py b/web/pgadmin/tools/datagrid/tests/test_initialize_data_grid.py
new file mode 100644
index 0000000..130a1d6
--- /dev/null
+++ b/web/pgadmin/tools/datagrid/tests/test_initialize_data_grid.py
@@ -0,0 +1,108 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2020, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+
+
+import json
+import uuid
+import random
+
+from unittest.mock import patch
+from pgadmin.browser.server_groups.servers.databases.tests import utils as \
+ database_utils
+
+from pgadmin.utils.route import BaseTestGenerator
+from regression import parent_node_dict
+from regression.python_test_utils import test_utils as utils
+from regression.test_setup import config_data
+from pgadmin.browser.server_groups.servers.databases.schemas.tests import \
+ utils as schema_utils
+from pgadmin.browser.server_groups.servers.databases.schemas.tables.tests \
+ import utils as tables_utils
+from . import utils as data_grid_utils
+
+
+class DatagridInitializeTestCase(BaseTestGenerator):
+ """
+ This will Initialize datagrid
+ """
+
+ scenarios = utils.generate_scenarios(
+ 'data_grid_initialize',
+ data_grid_utils.test_cases
+ )
+
+ def setUp(self):
+ self.database_info = parent_node_dict["database"][-1]
+ self.db_name = self.database_info["db_name"]
+ self.did = self.database_info["db_id"]
+ self.sid = parent_node_dict["server"][-1]["server_id"]
+ self.sgid = config_data['server_group']
+
+ db_con = database_utils.connect_database(self, utils.SERVER_GROUP,
+ self.sid, self.did)
+ if not db_con['data']["connected"]:
+ raise Exception("Could not connect to database to add a table.")
+
+ self.schema_id = parent_node_dict['schema'][-1]["schema_id"]
+ self.schema_name = parent_node_dict['schema'][-1]["schema_name"]
+ schema_response = schema_utils.verify_schemas(self.server,
+ self.db_name,
+ self.schema_name)
+ if not schema_response:
+ raise Exception("Could not find the schema to add a table.")
+ self.table_name = "table_for_wizard%s" % (str(uuid.uuid4())[1:8])
+ self.table_id = tables_utils.create_table(self.server, self.db_name,
+ self.schema_name,
+ self.table_name)
+ self.trans_id = str(random.randint(1, 9999999))
+ qt_init = data_grid_utils._init_query_tool(self, self.trans_id,
+ self.sgid, self.sid,
+ self.did)
+
+ if not qt_init['success']:
+ raise Exception("Could not initialize query tool.")
+
+ def initialize_datagrid(self):
+ if self.test_data:
+ response = self.tester.post(
+ self.url + str(self.trans_id) + '/4/table/' +
+ str(self.sgid) + '/' + str(self.sid) + '/' +
+ str(self.did) + '/' + str(self.table_id),
+ data=json.dumps(self.test_data),
+ content_type='html/json'
+ )
+ else:
+ response = self.tester.post(
+ self.url + str(self.trans_id) + '/4/table/' +
+ str(self.sgid) + '/' + str(self.sid) + '/' +
+ str(self.did) + '/' + str(self.table_id),
+ content_type='html/json'
+ )
+ return response
+
+ def runTest(self):
+ """ This function will update query tool connection."""
+
+ if self.is_positive_test:
+ response = self.initialize_datagrid()
+ actual_response_code = response.status_code
+ expected_response_code = self.expected_data['status_code']
+ else:
+ with patch(self.mock_data["function_name"],
+ return_value=eval(self.mock_data["return_value"])):
+ response = self.initialize_datagrid()
+ actual_response_code = response.status_code
+ expected_response_code = self.expected_data['status_code']
+
+ self.assertEqual(actual_response_code, expected_response_code)
+
+ def tearDown(self):
+ """This function disconnect database."""
+ database_utils.disconnect_database(self, self.sid,
+ self.did)
diff --git a/web/pgadmin/tools/datagrid/tests/utils.py b/web/pgadmin/tools/datagrid/tests/utils.py
new file mode 100644
index 0000000..82f9427
--- /dev/null
+++ b/web/pgadmin/tools/datagrid/tests/utils.py
@@ -0,0 +1,33 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2020, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+import os
+import json
+
+file_name = os.path.basename(__file__)
+CURRENT_PATH = os.path.dirname(os.path.realpath(__file__))
+with open(CURRENT_PATH + "/datagrid_test_data.json") as data_file:
+ test_cases = json.load(data_file)
+
+
+def _init_query_tool(self, trans_id, server_group, server_id, db_id):
+ QUERY_TOOL_INIT_URL = '/datagrid/initialize/query_tool/'
+
+ qt_init = self.tester.post(
+ '{0}/{1}/{2}/{3}/{4}'.format(
+ QUERY_TOOL_INIT_URL,
+ trans_id,
+ server_group,
+ server_id,
+ db_id
+ ),
+ follow_redirects=True
+ )
+ assert qt_init.status_code == 200
+ qt_init = json.loads(qt_init.data.decode('utf-8'))
+ return qt_init
diff --git a/web/pgadmin/tools/sqleditor/__init__.py b/web/pgadmin/tools/sqleditor/__init__.py
index c62bc7c..434ba88 100644
--- a/web/pgadmin/tools/sqleditor/__init__.py
+++ b/web/pgadmin/tools/sqleditor/__init__.py
@@ -10,33 +10,38 @@
"""A blueprint module implementing the sqleditor frame."""
import os
import pickle
-import sys
import re
+from urllib.parse import unquote
import simplejson as json
-from flask import Response, url_for, render_template, session, request, \
- current_app
+from config import PG_DEFAULT_DRIVER, ON_DEMAND_RECORD_COUNT
+from flask import Response, url_for, render_template, session, current_app
+from flask import request, jsonify
from flask_babelex import gettext
from flask_security import login_required, current_user
-from urllib.parse import unquote
-
-from config import PG_DEFAULT_DRIVER, ON_DEMAND_RECORD_COUNT
from pgadmin.misc.file_manager import Filemanager
from pgadmin.tools.sqleditor.command import QueryToolCommand
from pgadmin.tools.sqleditor.utils.constant_definition import ASYNC_OK, \
ASYNC_EXECUTION_ABORTED, \
CONNECTION_STATUS_MESSAGE_MAPPING, TX_STATUS_INERROR
+from pgadmin.tools.sqleditor.utils.filter_dialog import FilterDialog
+from pgadmin.tools.sqleditor.utils.query_history import QueryHistory
+from pgadmin.tools.sqleditor.utils.query_tool_fs_utils import \
+ read_file_generator
+from pgadmin.tools.sqleditor.utils.query_tool_preferences import \
+ register_query_tool_preferences
from pgadmin.tools.sqleditor.utils.start_running_query import StartRunningQuery
from pgadmin.tools.sqleditor.utils.update_session_grid_transaction import \
update_session_grid_transaction
from pgadmin.utils import PgAdminModule
from pgadmin.utils import get_storage_directory
from pgadmin.utils.ajax import make_json_response, bad_request, \
- success_return, internal_server_error
+ internal_server_error
+from pgadmin.utils.constants import MIMETYPE_APP_JS
from pgadmin.utils.driver import get_driver
-from pgadmin.utils.menu import MenuItem
-from pgadmin.utils.exception import ConnectionLost, SSHTunnelConnectionLost,\
+from pgadmin.utils.exception import ConnectionLost, SSHTunnelConnectionLost, \
CryptKeyMissing
+from pgadmin.utils.menu import MenuItem
from pgadmin.utils.sqlautocomplete.autocomplete import SQLAutoComplete
from pgadmin.tools.sqleditor.utils.query_tool_preferences import \
register_query_tool_preferences
@@ -46,6 +51,8 @@ from pgadmin.tools.sqleditor.utils.filter_dialog import FilterDialog
from pgadmin.tools.sqleditor.utils.query_history import QueryHistory
from pgadmin.utils.constants import MIMETYPE_APP_JS, SERVER_CONNECTION_CLOSED,\
ERROR_MSG_TRANS_ID_NOT_FOUND
+from pgadmin.model import Server
+
MODULE_NAME = 'sqleditor'
@@ -109,6 +116,9 @@ class SqlEditorModule(PgAdminModule):
'sqleditor.get_query_history',
'sqleditor.add_query_history',
'sqleditor.clear_query_history',
+ 'sqleditor.get_new_connection_data',
+ 'sqleditor.get_new_connection_database',
+ 'sqleditor.get_new_connection_user',
]
def register_preferences(self):
@@ -1465,6 +1475,188 @@ def get_filter_data(trans_id):
return FilterDialog.get(status, error_msg, conn, trans_obj, session_ob)
[email protected](
+ '/new_connection_dialog/<int:sgid>/<int:sid>',
+ methods=["GET"], endpoint='get_new_connection_data'
+)
+@login_required
+def get_new_connection_data(sgid, sid=None):
+ """
+ This method is used to get required data for get new connection.
+ :extract_sql_from_network_parameters,
+ """
+ try:
+ # if sid and not did:
+ servers = Server.query.all()
+ server_list = [
+ {'name': server.serialize['name'], "id": server.serialize['id']}
+ for server in servers]
+
+ msg = "Success"
+ return make_json_response(
+ data={
+ 'status': True,
+ 'msg': msg,
+ 'result': {
+ 'server_list': server_list
+ }
+ }
+ )
+
+ except Exception as e:
+ return make_json_response(
+ data={
+ 'status': False,
+ 'msg': 'Unable to fetch data.',
+ 'result': {
+ 'server_list': []
+ }
+ }
+ )
+
+
[email protected](
+ '/new_connection_database/<int:sgid>/<int:sid>',
+ methods=["GET"], endpoint='get_new_connection_database'
+)
+@login_required
+def get_new_connection_database(sgid, sid=None):
+ """
+ This method is used to get required data for get new connection.
+ :extract_sql_from_network_parameters,
+ """
+ try:
+ database_list = []
+ from pgadmin.utils.driver import get_driver
+ manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(sid)
+ conn = manager.connection()
+ if conn.connected():
+ is_connected = True
+ else:
+ # connection = conn.connect()
+ is_connected = False
+ if is_connected:
+ if sid:
+ template_path = 'databases/sql/#{0}#'.format(manager.version)
+ last_system_oid = 0
+ server_node_res = manager
+
+ db_disp_res = None
+ params = None
+ if server_node_res and server_node_res.db_res:
+ db_disp_res = ", ".join(
+ ['%s'] * len(server_node_res.db_res.split(','))
+ )
+ params = tuple(server_node_res.db_res.split(','))
+ sql = render_template(
+ "/".join([template_path, 'nodes.sql']),
+ last_system_oid=last_system_oid,
+ db_restrictions=db_disp_res
+ )
+ status, databases = conn.execute_dict(sql, params)
+ database_list = [
+ {'label': database['name'], 'value': database['did']} for
+ database in databases['rows']]
+ else:
+ status = False
+
+ msg = "Success"
+ return make_json_response(
+ data={
+ 'status': status,
+ 'msg': msg,
+ 'result': {
+ 'data': database_list,
+ }
+ }
+ )
+ else:
+ return make_json_response(
+ data={
+ 'status': False,
+ 'msg': 'Server not connected, '
+ 'Please connect with server and try again.',
+ 'result': {
+ 'database_list': [],
+ }
+ }
+ )
+ except Exception as e:
+ return make_json_response(
+ data={
+ 'status': False,
+ 'msg': 'Unable to fetch data.',
+ 'result': {
+ 'database_list': [],
+ }
+ }
+ )
+
+
[email protected](
+ '/new_connection_user/<int:sgid>/<int:sid>',
+ methods=["GET"], endpoint='get_new_connection_user'
+)
+@login_required
+def get_new_connection_user(sgid, sid=None):
+ """
+ This method is used to get required data for get new connection.
+ :extract_sql_from_network_parameters,
+ """
+ try:
+ from pgadmin.utils.driver import get_driver
+ manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(sid)
+ conn = manager.connection()
+ user_list = []
+ if conn.connected():
+ is_connected = True
+ else:
+ is_connected = False
+ if is_connected:
+ if sid:
+ sql_path = 'roles/sql/#{0}#'.format(manager.version)
+ status, users = conn.execute_2darray(
+ render_template(sql_path + 'nodes.sql')
+ )
+ user_list = [
+ {'value': user['rolname'], 'label': user['rolname']} for
+ user in users['rows'] if user['rolcanlogin']]
+ else:
+ status = False
+
+ msg = "Success"
+ return make_json_response(
+ data={
+ 'status': status,
+ 'msg': msg,
+ 'result': {
+ 'data': user_list,
+ }
+ }
+ )
+ else:
+ return make_json_response(
+ data={
+ 'status': False,
+ 'msg': 'Server not connected, '
+ 'Please connect with server and try again.',
+ 'result': {
+ 'user_list': [],
+ }
+ }
+ )
+ except Exception as e:
+ return make_json_response(
+ data={
+ 'status': False,
+ 'msg': 'Unable to fetch data.',
+ 'result': {
+ 'user_list': [],
+ }
+ }
+ )
+
+
@blueprint.route(
'/filter_dialog/<int:trans_id>',
methods=["PUT"], endpoint='set_filter_data'
diff --git a/web/pgadmin/tools/sqleditor/static/css/sqleditor.css b/web/pgadmin/tools/sqleditor/static/css/sqleditor.css
index 00543ff..b8c2d2e 100644
--- a/web/pgadmin/tools/sqleditor/static/css/sqleditor.css
+++ b/web/pgadmin/tools/sqleditor/static/css/sqleditor.css
@@ -315,10 +315,6 @@ input.editor-checkbox:focus {
padding: 10px 0px;
}
-.editor-title {
- width:100%;
-}
-
.connection-status-hide {
display: none !important;
}
@@ -395,3 +391,7 @@ input.editor-checkbox:focus {
.hide-vertical-scrollbar {
overflow-y: hidden;
}
+
+.new-connection-dialog-style {
+ width: 100% !important;
+}
diff --git a/web/pgadmin/tools/sqleditor/static/js/sqleditor.js b/web/pgadmin/tools/sqleditor/static/js/sqleditor.js
index ce02a53..9720d36 100644
--- a/web/pgadmin/tools/sqleditor/static/js/sqleditor.js
+++ b/web/pgadmin/tools/sqleditor/static/js/sqleditor.js
@@ -14,6 +14,7 @@ define('tools.querytool', [
'jqueryui.position', 'underscore', 'pgadmin.alertifyjs',
'sources/pgadmin', 'backbone', 'bundled_codemirror', 'sources/utils',
'pgadmin.misc.explain',
+ 'pgadmin.user_management.current_user',
'sources/selection/grid_selector',
'sources/selection/active_cell_capture',
'sources/selection/clipboard',
@@ -26,6 +27,7 @@ define('tools.querytool', [
'sources/sqleditor/execute_query',
'sources/sqleditor/query_tool_http_error_handler',
'sources/sqleditor/filter_dialog',
+ 'sources/sqleditor/new_connection_dialog',
'sources/sqleditor/geometry_viewer',
'sources/sqleditor/history/history_collection.js',
'sources/sqleditor/history/query_history',
@@ -52,8 +54,8 @@ define('tools.querytool', [
'pgadmin.tools.user_management',
], function(
gettext, url_for, $, jqueryui, jqueryui_position, _, alertify, pgAdmin, Backbone, codemirror, pgadminUtils,
- pgExplain, GridSelector, ActiveCellCapture, clipboard, copyData, RangeSelectionHelper, handleQueryOutputKeyboardEvent,
- XCellSelectionModel, setStagedRows, SqlEditorUtils, ExecuteQuery, httpErrorHandler, FilterHandler,
+ pgExplain, current_user, GridSelector, ActiveCellCapture, clipboard, copyData, RangeSelectionHelper, handleQueryOutputKeyboardEvent,
+ XCellSelectionModel, setStagedRows, SqlEditorUtils, ExecuteQuery, httpErrorHandler, FilterHandler, newConnectionHandler,
GeometryViewer, historyColl, queryHist, querySources,
keyboardShortcuts, queryToolActions, queryToolNotifications, Datagrid,
modifyAnimation, calculateQueryRunTime, callRenderAfterPoll, queryToolPref, queryTxnStatus, csrfToken, panelTitleFunc,
@@ -89,6 +91,9 @@ define('tools.querytool', [
this.layout = opts.layout;
this.set_server_version(opts.server_ver);
this.trigger('pgadmin-sqleditor:view:initialised');
+ this.connection_list = [
+ {'server_group': null,'server': null, 'database': null, 'user': null, 'password': null, 'title': '<New Connection>'},
+ ];
},
// Bind all the events
@@ -151,6 +156,30 @@ define('tools.querytool', [
'click #btn-rollback': 'on_rollback_transaction',
},
+ render_connection: function(data_list) {
+ var dropdownElement = document.getElementById('connections-list');
+ dropdownElement.innerHTML = '';
+ data_list.forEach((option, index) => {
+ $('#connections-list').append('<li class="connection-list-item" data-index='+ index +'><a class="dropdown-item" href="#" tabindex="0">'+ option.title +'</a></li>');
+
+ });
+ var self = this;
+ $('.connection-list-item').click(function() {
+ self.get_connection_data(this);
+ });
+ },
+
+ get_connection_data: function(event){
+ var index = $(event).attr('data-index');
+ var connection_details = this.connection_list[index];
+ if(connection_details.server_group) {
+ this.on_change_connection(connection_details);
+ } else {
+ this.on_new_connection();
+ }
+
+ },
+
reflectPreferences: function() {
let self = this,
browser = pgWindow.default.pgAdmin.Browser,
@@ -199,8 +228,15 @@ define('tools.querytool', [
});
},
- set_editor_title: function(title) {
- this.$el.find('.editor-title').text(title);
+ set_editor_title: function(title, is_connected) {
+ if(is_connected) {
+ this.$el.find('.editor-title').text(title);
+ this.render_connection(this.connection_list);
+ } else {
+ this.$el.find('.editor-title').text(title);
+ this.render_connection(this.connection_list);
+ }
+
},
// This function is used to render the template.
@@ -684,6 +720,8 @@ define('tools.querytool', [
pgBrowser.register_to_activity_listener(document, ()=>{
alertify.alert(gettext('Timeout'), gettext('Your session has timed out due to inactivity. Please close the window and login again.'));
});
+
+ self.render_connection(self.connection_list);
},
/* Regarding SlickGrid usage in render_grid function.
@@ -1595,6 +1633,17 @@ define('tools.querytool', [
);
},
+ on_new_connection: function() {
+ var self = this;
+
+ // Trigger the show_filter signal to the SqlEditorController class
+ self.handler.trigger(
+ 'pgadmin-sqleditor:button:show_new_connection',
+ self,
+ self.handler
+ );
+ },
+
// Callback function for include filter button click.
on_include_filter: function(ev) {
var self = this;
@@ -2038,6 +2087,55 @@ define('tools.querytool', [
queryToolActions.executeRollback(this.handler);
},
+ on_change_connection: function(connection_details, ref) {
+ var self = this;
+ $.ajax({
+ url: url_for('datagrid.update_query_tool_connection', {
+ 'trans_id': self.transId,
+ 'sgid': connection_details['server_group'],
+ 'sid': connection_details['server'],
+ 'did': connection_details['database'],
+ }),
+ method: 'POST',
+ contentType: 'application/json',
+ data: JSON.stringify(connection_details),
+ })
+ .done(function(res) {
+ if(res.success) {
+ self.transId = res.data.tran_id;
+ self.handler.transId = res.data.tran_id;
+ self.handler.url_params = {
+ 'did': connection_details['database'],
+ 'is_query_tool': self.handler.url_params.is_query_tool,
+ 'server_type': self.handler.url_params.server_type,
+ 'sgid': connection_details['server_group'],
+ 'sid': connection_details['server'],
+ 'title': connection_details['title'],
+ };
+ self.set_editor_title(self.handler.url_params.title);
+ self.handler.setTitle(self.handler.url_params.title);
+ alertify.success('connected successfully');
+ if(ref){
+ let connection_data = {
+ 'server_group': self.handler.url_params.sgid,
+ 'server': connection_details['server'],
+ 'database': connection_details['database'],
+ 'user': connection_details['user'],
+ 'password': connection_details['password'],
+ 'title': connection_details['title'],
+ 'is_allow_new_connection': true,
+ };
+ self.connection_list.unshift(connection_data);
+ self.render_connection(self.connection_list);
+ ref.close();
+ }
+ }
+
+ })
+ .fail(function(xhr) {
+ alertify.error(xhr.responseJSON['errormsg']);
+ });
+ },
});
/* Defining controller class for data grid, which actually
@@ -2357,7 +2455,18 @@ define('tools.querytool', [
});
$('#btn-conn-status i').removeClass('obtaining-conn');
- self.gridView.set_editor_title(_.unescape(url_params.title));
+ self.gridView.set_editor_title(_.unescape(url_params.title), true);
+ let connection_data = {
+ 'server_group': self.gridView.handler.url_params.sgid,
+ 'server': self.gridView.handler.url_params.sid,
+ 'database': self.gridView.handler.url_params.did,
+ 'user': null,
+ 'password': null,
+ 'title': _.unescape(url_params.title),
+ 'is_allow_new_connection': false,
+ };
+ self.gridView.connection_list.unshift(connection_data);
+ self.gridView.render_connection(self.gridView.connection_list);
};
pgBrowser.Events.on('pgadmin:query_tool:connected:' + transId, afterConn);
@@ -2452,6 +2561,7 @@ define('tools.querytool', [
self.on('pgadmin-sqleditor:button:save_file', self._save_file, self);
self.on('pgadmin-sqleditor:button:deleterow', self._delete, self);
self.on('pgadmin-sqleditor:button:show_filter', self._show_filter, self);
+ self.on('pgadmin-sqleditor:button:show_new_connection', self._show_new_connection, self);
self.on('pgadmin-sqleditor:button:include_filter', self._include_filter, self);
self.on('pgadmin-sqleditor:button:exclude_filter', self._exclude_filter, self);
self.on('pgadmin-sqleditor:button:remove_filter', self._remove_filter, self);
@@ -3622,7 +3732,6 @@ define('tools.querytool', [
}
};
},
-
// This function will show the filter in the text area.
_show_filter: function() {
let self = this,
@@ -3637,7 +3746,19 @@ define('tools.querytool', [
}
FilterHandler.dialog(self, reconnect);
},
+ // This function will show the new connection.
+ _show_new_connection: function() {
+ let self = this,
+ reconnect = false;
+ /* When server is disconnected and connected, connection is lost,
+ * To reconnect pass true
+ */
+ if (arguments.length > 0 && arguments[arguments.length - 1] == 'connect') {
+ reconnect = true;
+ }
+ newConnectionHandler.dialog(self, reconnect);
+ },
// This function will include the filter by selection.
_include_filter: function() {
var self = this,
diff --git a/web/pgadmin/tools/sqleditor/static/scss/_sqleditor.scss b/web/pgadmin/tools/sqleditor/static/scss/_sqleditor.scss
index fd1e5d3..53f2449 100644
--- a/web/pgadmin/tools/sqleditor/static/scss/_sqleditor.scss
+++ b/web/pgadmin/tools/sqleditor/static/scss/_sqleditor.scss
@@ -30,6 +30,19 @@
color: $sql-title-fg;
}
+.connection-info {
+ background: $sql-title-bg;
+ color: $sql-title-fg;
+ width:100%;
+ display: inherit;
+}
+
+.conn-info-dd {
+ padding-top: 0.3em;
+ padding-left: 0.2em;
+ cursor: pointer;
+}
+
#editor-panel {
z-index: 0;
diff --git a/web/pgadmin/tools/sqleditor/tests/test_new_connection_database.py b/web/pgadmin/tools/sqleditor/tests/test_new_connection_database.py
new file mode 100644
index 0000000..20fe3e3
--- /dev/null
+++ b/web/pgadmin/tools/sqleditor/tests/test_new_connection_database.py
@@ -0,0 +1,98 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2020, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+
+import json
+from pgadmin.utils.route import BaseTestGenerator
+from regression import parent_node_dict
+from regression.test_setup import config_data
+from regression.python_test_utils import test_utils as utils
+
+
+class TestNewConnectionDatabase(BaseTestGenerator):
+ """ This class will test new connection database. """
+ scenarios = [
+ ('New connection dialog',
+ dict(
+ url="/sqleditor/new_connection_database/",
+ is_positive_test=True,
+ mocking_required=False,
+ is_server_conn_required=False,
+ test_data={},
+ mock_data={},
+ expected_data={
+ "status_code": 200
+ }
+ )),
+ ('New connection dialog connect server',
+ dict(
+ url="/sqleditor/new_connection_database/",
+ is_positive_test=True,
+ mocking_required=False,
+ is_server_conn_required=True,
+ test_data={},
+ mock_data={},
+ expected_data={
+ "status_code": 200
+ }
+ )),
+ ('New connection dialog negative',
+ dict(
+ url="/sqleditor/new_connection_database/",
+ is_positive_test=False,
+ mocking_required=False,
+ is_server_conn_required=True,
+ test_data={},
+ mock_data={},
+ expected_data={
+ "status_code": 200
+ }
+ )),
+ ]
+
+ def setUp(self):
+ self.sid = parent_node_dict["server"][-1]["server_id"]
+ self.sgid = config_data['server_group']
+
+ def get_database(self):
+ response = self.tester.get(
+ self.url + str(self.sgid) + '/' + str(self.sid),
+ content_type='html/json'
+ )
+
+ return response
+
+ def runTest(self):
+ if self.is_positive_test:
+ if self.is_server_conn_required:
+ self.server['password'] = self.server['db_password']
+ server_response = self.tester.post(
+ '/browser/server/connect/{0}/{1}'.format(
+ utils.SERVER_GROUP,
+ self.sid),
+ data=json.dumps(self.server),
+ content_type='html/json'
+ )
+ response = self.get_database()
+ actual_response_code = response.status_code
+ expected_response_code = self.expected_data['status_code']
+ else:
+ if self.is_server_conn_required:
+ self.server['password'] = self.server['db_password']
+ server_response = self.tester.post(
+ '/browser/server/connect/{0}/{1}'.format(
+ utils.SERVER_GROUP,
+ self.sid),
+ data=json.dumps(self.server),
+ content_type='html/json'
+ )
+ self.sid = 0
+ response = self.get_database()
+ actual_response_code = response.status_code
+ expected_response_code = self.expected_data['status_code']
+ self.assertEqual(actual_response_code, expected_response_code)
diff --git a/web/pgadmin/tools/sqleditor/tests/test_new_connection_dialog.py b/web/pgadmin/tools/sqleditor/tests/test_new_connection_dialog.py
new file mode 100644
index 0000000..75a47ef
--- /dev/null
+++ b/web/pgadmin/tools/sqleditor/tests/test_new_connection_dialog.py
@@ -0,0 +1,50 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2020, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+import json
+from pgadmin.utils.route import BaseTestGenerator
+from regression import parent_node_dict
+from regression.test_setup import config_data
+from regression.python_test_utils import test_utils as utils
+
+
+class TestNewConnectionDialog(BaseTestGenerator):
+ """ This class will test new connection dialog. """
+ scenarios = [
+ ('New connection dialog',
+ dict(
+ url="/sqleditor/new_connection_dialog/",
+ is_positive_test=True,
+ mocking_required=False,
+ is_connect_server=False,
+ test_data={},
+ mock_data={},
+ expected_data={
+ "status_code": 200
+ }
+ )),
+ ]
+
+ def setUp(self):
+ self.sid = parent_node_dict["server"][-1]["server_id"]
+ self.sgid = config_data['server_group']
+
+ def new_connection(self):
+ response = self.tester.get(
+ self.url + str(self.sgid) + '/' + str(self.sgid),
+ content_type='html/json'
+ )
+
+ return response
+
+ def runTest(self):
+ if self.is_positive_test:
+ response = self.new_connection()
+ actual_response_code = response.status_code
+ expected_response_code = self.expected_data['status_code']
+ self.assertEqual(actual_response_code, expected_response_code)
diff --git a/web/pgadmin/tools/sqleditor/tests/test_new_connection_user.py b/web/pgadmin/tools/sqleditor/tests/test_new_connection_user.py
new file mode 100644
index 0000000..7b6c12e
--- /dev/null
+++ b/web/pgadmin/tools/sqleditor/tests/test_new_connection_user.py
@@ -0,0 +1,98 @@
+##########################################################################
+#
+# pgAdmin 4 - PostgreSQL Tools
+#
+# Copyright (C) 2013 - 2020, The pgAdmin Development Team
+# This software is released under the PostgreSQL Licence
+#
+##########################################################################
+
+import json
+from pgadmin.utils.route import BaseTestGenerator
+from regression import parent_node_dict
+from regression.test_setup import config_data
+from regression.python_test_utils import test_utils as utils
+
+
+class TestNewConnectionUser(BaseTestGenerator):
+ """ This class will test new connection user. """
+ scenarios = [
+ ('New connection dialog',
+ dict(
+ url="/sqleditor/new_connection_user/",
+ is_positive_test=True,
+ mocking_required=False,
+ is_server_conn_required=False,
+ test_data={},
+ mock_data={},
+ expected_data={
+ "status_code": 200
+ }
+ )),
+ ('New connection dialog connect server',
+ dict(
+ url="/sqleditor/new_connection_user/",
+ is_positive_test=True,
+ mocking_required=False,
+ is_server_conn_required=True,
+ test_data={},
+ mock_data={},
+ expected_data={
+ "status_code": 200
+ }
+ )),
+ ('New connection dialog negative',
+ dict(
+ url="/sqleditor/new_connection_user/",
+ is_positive_test=False,
+ mocking_required=False,
+ is_server_conn_required=True,
+ test_data={},
+ mock_data={},
+ expected_data={
+ "status_code": 200
+ }
+ )),
+ ]
+
+ def setUp(self):
+ self.sid = parent_node_dict["server"][-1]["server_id"]
+ self.sgid = config_data['server_group']
+
+ def get_use(self):
+ response = self.tester.get(
+ self.url + str(self.sgid) + '/' + str(self.sid),
+ content_type='html/json'
+ )
+
+ return response
+
+ def runTest(self):
+ if self.is_positive_test:
+ if self.is_server_conn_required:
+ self.server['password'] = self.server['db_password']
+ server_response = self.tester.post(
+ '/browser/server/connect/{0}/{1}'.format(
+ utils.SERVER_GROUP,
+ self.sid),
+ data=json.dumps(self.server),
+ content_type='html/json'
+ )
+ response = self.get_use()
+ actual_response_code = response.status_code
+ expected_response_code = self.expected_data['status_code']
+ else:
+ if self.is_server_conn_required:
+ self.server['password'] = self.server['db_password']
+ server_response = self.tester.post(
+ '/browser/server/connect/{0}/{1}'.format(
+ utils.SERVER_GROUP,
+ self.sid),
+ data=json.dumps(self.server),
+ content_type='html/json'
+ )
+ self.sid = 0
+ response = self.get_use()
+ actual_response_code = response.status_code
+ expected_response_code = self.expected_data['status_code']
+ self.assertEqual(actual_response_code, expected_response_code)
diff --git a/web/pgadmin/utils/driver/psycopg2/connection.py b/web/pgadmin/utils/driver/psycopg2/connection.py
index 9cb65bc..115598a 100644
--- a/web/pgadmin/utils/driver/psycopg2/connection.py
+++ b/web/pgadmin/utils/driver/psycopg2/connection.py
@@ -21,7 +21,7 @@ import psycopg2
from flask import g, current_app
from flask_babelex import gettext
from flask_security import current_user
-from pgadmin.utils.crypto import decrypt
+from pgadmin.utils.crypto import decrypt, encrypt
from psycopg2.extensions import encodings
import config
@@ -211,8 +211,23 @@ class Connection(BaseConnection):
password = None
passfile = None
manager = self.manager
+ encpass = None
+ is_update_password = True
+ crypt_key_present, crypt_key = get_crypt_key()
+
+ if 'user' in kwargs and kwargs['password']:
+ password = kwargs['password']
+ # kwargs['password'] = encrypt(password, crypt_key)
+ '''
+ Remove the password from kwargs as we don't want to update
+ password in manager when user is connecting through query toll.
+ If we update password in manager will affect existing connections.
+ '''
+ kwargs.pop('password')
+ is_update_password = False
+ else:
+ encpass = kwargs['password'] if 'password' in kwargs else None
- encpass = kwargs['password'] if 'password' in kwargs else None
passfile = kwargs['passfile'] if 'passfile' in kwargs else None
tunnel_password = kwargs['tunnel_password'] if 'tunnel_password' in \
kwargs else ''
@@ -227,16 +242,16 @@ class Connection(BaseConnection):
if manager.use_ssh_tunnel == 1:
manager.check_ssh_tunnel_alive()
- if encpass is None:
- encpass = self.password or getattr(manager, 'password', None)
+ if is_update_password:
+ if encpass is None:
+ encpass = self.password or getattr(manager, 'password', None)
- self.password = encpass
+ self.password = encpass
# Reset the existing connection password
if self.reconnecting is not False:
self.password = None
- crypt_key_present, crypt_key = get_crypt_key()
if not crypt_key_present:
raise CryptKeyMissing()
@@ -269,7 +284,10 @@ class Connection(BaseConnection):
try:
database = self.db
- user = manager.user
+ if 'user' in kwargs and kwargs['user']:
+ user = kwargs['user']
+ else:
+ user = manager.user
conn_id = self.conn_id
import os
@@ -338,10 +356,10 @@ class Connection(BaseConnection):
self.wasConnected = False
raise e
- if status:
+ if status and is_update_password:
manager._update_password(encpass)
else:
- if not self.reconnecting:
+ if not self.reconnecting and is_update_password:
self.wasConnected = False
return status, msg
@@ -491,7 +509,7 @@ WHERE db.datname = current_database()""")
if len(manager.db_info) == 1:
manager.did = res['did']
- self._set_user_info(cur, manager)
+ self._set_user_info(cur, manager, **kwargs)
self._set_server_type_and_password(kwargs, manager)
@@ -499,7 +517,7 @@ WHERE db.datname = current_database()""")
return True, None
- def _set_user_info(self, cur, manager):
+ def _set_user_info(self, cur, manager, **kwargs):
"""
Set user info.
:param cur:
@@ -517,7 +535,7 @@ WHERE db.datname = current_database()""")
WHERE
rolname = current_user""")
- if status is None:
+ if status is None and 'user' not in kwargs:
manager.user_info = dict()
if cur.rowcount > 0:
manager.user_info = cur.fetchmany(1)[0]
view thread (18+ messages) latest in thread
reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: [email protected]
Cc: [email protected]
Subject: Re: [pgAdmin][RM3794]:Allow User to Change Database Connection from an Open Query Tool Tab
In-Reply-To: <CAOBg0AM=b7hfJjTJAXu=wGkKHEsV_zoZpSO-QU6Z-G9p2wVF0w@mail.gmail.com>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox