Hi,

Plz find attached patch to fix session expired issue
from sqleditor/datadrid.

-- 
*Harshal Dhumal*
*Sr. Software Engineer*

EnterpriseDB India: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
diff --git a/web/pgadmin/__init__.py b/web/pgadmin/__init__.py
index db676c5..220ea6b 100644
--- a/web/pgadmin/__init__.py
+++ b/web/pgadmin/__init__.py
@@ -25,7 +25,7 @@ from flask_paranoid import Paranoid
 
 from pgadmin.utils import PgAdminModule, driver
 from pgadmin.utils.versioned_template_loader import VersionedTemplateLoader
-from pgadmin.utils.session import create_session_interface
+from pgadmin.utils.session import create_session_interface, pga_unauthorised
 from werkzeug.local import LocalProxy
 from werkzeug.utils import find_modules
 
@@ -344,6 +344,9 @@ def create_app(app_name=None):
 
     security.init_app(app, user_datastore)
 
+    # register custom unauthorised handler.
+    app.login_manager.unauthorized_handler(pga_unauthorised)
+
     app.session_interface = create_session_interface(app)
 
     # Make the Session more secure against XSS & CSRF when running in web mode
diff --git a/web/pgadmin/browser/server_groups/servers/__init__.py b/web/pgadmin/browser/server_groups/servers/__init__.py
index 5330942..626526c 100644
--- a/web/pgadmin/browser/server_groups/servers/__init__.py
+++ b/web/pgadmin/browser/server_groups/servers/__init__.py
@@ -202,6 +202,9 @@ class ServerModule(sg.ServerGroupPluginModule):
         """
         ServerType.register_preferences()
 
+    def get_exposed_url_endpoints(self):
+        return ['NODE-server.connect_id']
+
 
 class ServerMenuItem(MenuItem):
     def __init__(self, **kwargs):
diff --git a/web/pgadmin/tools/datagrid/__init__.py b/web/pgadmin/tools/datagrid/__init__.py
index 6b1d699..75f63d7 100644
--- a/web/pgadmin/tools/datagrid/__init__.py
+++ b/web/pgadmin/tools/datagrid/__init__.py
@@ -17,7 +17,6 @@ import random
 from flask import Response, url_for, session, request, make_response
 from werkzeug.useragents import UserAgent
 from flask import current_app as app
-from flask_babel import gettext
 from flask_security import login_required
 from pgadmin.tools.sqleditor.command import *
 from pgadmin.utils import PgAdminModule
@@ -27,6 +26,9 @@ from pgadmin.utils.ajax import make_json_response, bad_request, \
 from config import PG_DEFAULT_DRIVER
 from pgadmin.utils.preferences import Preferences
 from pgadmin.model import Server
+from pgadmin.utils.driver import get_driver
+from pgadmin.utils.exception import ConnectionLost
+
 
 class DataGridModule(PgAdminModule):
     """
@@ -90,11 +92,11 @@ def show_filter():
 
 
 @blueprint.route(
-    '/initialize/datagrid/<int:cmd_type>/<obj_type>/<int:sid>/<int:did>/<int:obj_id>',
+    '/initialize/datagrid/<int:cmd_type>/<obj_type>/<int:sgid>/<int:sid>/<int:did>/<int:obj_id>',
     methods=["PUT", "POST"], endpoint="initialize_datagrid"
 )
 @login_required
-def initialize_datagrid(cmd_type, obj_type, sid, did, obj_id):
+def initialize_datagrid(cmd_type, obj_type, sgid, sid, did, obj_id):
     """
     This method is responsible for creating an asynchronous connection.
     After creating the connection it will instantiate and initialize
@@ -104,6 +106,7 @@ def initialize_datagrid(cmd_type, obj_type, sid, did, obj_id):
     Args:
         cmd_type: Contains value for which menu item is clicked.
         obj_type: Contains type of selected object for which data grid to be render
+        sgid: Server group Id
         sid: Server Id
         did: Database Id
         obj_id: Id of currently selected object
@@ -118,15 +121,26 @@ def initialize_datagrid(cmd_type, obj_type, sid, did, obj_id):
     conn_id = str(random.randint(1, 9999999))
     try:
         manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(sid)
+        # default_conn is same connection which is created when user connect to
+        # database from tree
+        default_conn = manager.connection(did=did)
         conn = manager.connection(did=did, conn_id=conn_id,
                                   use_binary_placeholder=True,
                                   array_to_string=True)
+    except ConnectionLost as e:
+        raise
     except Exception as e:
+        app.logger.error(e)
         return internal_server_error(errormsg=str(e))
 
-    # Connect the Server
+    status, msg = default_conn.connect()
+    if not status:
+        app.logger.error(msg)
+        return internal_server_error(errormsg=str(msg))
+
     status, msg = conn.connect()
     if not status:
+        app.logger.error(msg)
         return internal_server_error(errormsg=str(msg))
 
     try:
@@ -135,10 +149,13 @@ def initialize_datagrid(cmd_type, obj_type, sid, did, obj_id):
             obj_type = 'table'
 
         # Get the object as per the object type
-        command_obj = ObjectRegistry.get_object(obj_type, conn_id=conn_id, sid=sid,
-                                                did=did, obj_id=obj_id, cmd_type=cmd_type,
+        command_obj = ObjectRegistry.get_object(obj_type, conn_id=conn_id,
+                                                sgid=sgid, sid=sid, did=did,
+                                                obj_id=obj_id,
+                                                cmd_type=cmd_type,
                                                 sql_filter=filter_sql)
     except Exception as e:
+        app.logger.error(e)
         return internal_server_error(errormsg=str(e))
 
     # Create a unique id for the transaction
@@ -217,11 +234,6 @@ def panel(trans_id, is_query_tool, editor_title):
     else:
         new_browser_tab = 'false'
 
-    if is_query_tool == 'true':
-        prompt_save_changes = pref.preference('prompt_save_query_changes').get()
-    else:
-        prompt_save_changes = pref.preference('prompt_save_data_changes').get()
-
     # Fetch the server details
     #
     bgcolor = None
@@ -239,6 +251,21 @@ def panel(trans_id, is_query_tool, editor_title):
                 bgcolor = s.bgcolor
             fgcolor = s.fgcolor or 'black'
 
+    url_params = dict()
+    if is_query_tool == 'true':
+        prompt_save_changes = pref.preference('prompt_save_query_changes').get()
+        url_params['sgid'] = trans_obj.sgid
+        url_params['sid'] = trans_obj.sid
+        url_params['did'] = trans_obj.did
+    else:
+        prompt_save_changes = pref.preference('prompt_save_data_changes').get()
+        url_params['cmd_type'] = trans_obj.cmd_type
+        url_params['obj_type'] = trans_obj.object_type
+        url_params['sgid'] = trans_obj.sgid
+        url_params['sid'] = trans_obj.sid
+        url_params['did'] = trans_obj.did
+        url_params['obj_id'] = trans_obj.obj_id
+
     return render_template(
         "datagrid/index.html", _=gettext, uniqueId=trans_id,
         is_query_tool=is_query_tool,
@@ -252,48 +279,41 @@ def panel(trans_id, is_query_tool, editor_title):
         fgcolor=fgcolor,
         # convert python boolean value to equivalent js boolean literal before
         # passing it to html template.
-        prompt_save_changes='true' if prompt_save_changes else 'false'
+        prompt_save_changes='true' if prompt_save_changes else 'false',
+        url_params=json.dumps(url_params)
     )
 
 
 @blueprint.route(
-    '/initialize/query_tool/<int:sid>/<int:did>',
+    '/initialize/query_tool/<int:sgid>/<int:sid>/<int:did>',
     methods=["POST"], endpoint='initialize_query_tool_with_did'
 )
 @blueprint.route(
-    '/initialize/query_tool/<int:sid>',
+    '/initialize/query_tool/<int:sgid>/<int:sid>',
     methods=["POST"], endpoint='initialize_query_tool'
 )
 @login_required
-def initialize_query_tool(sid, did=None):
+def initialize_query_tool(sgid, sid, did=None):
     """
     This method is responsible for instantiating and initializing
     the query tool object. It will also create a unique
     transaction id and store the information into session variable.
 
     Args:
+        sgid: Server group Id
         sid: Server Id
         did: Database Id
     """
 
     if did is None:
         # Use Maintenance database OID
-        from pgadmin.utils.driver import get_driver
-        driver = get_driver(PG_DEFAULT_DRIVER)
-        manager = driver.connection_manager(sid)
-        conn = manager.connection()
-        if conn.connected():
-            did = manager.did
-        else:
-            internal_server_error(
-                errormsg=gettext(
-                    'Server disconnected. Please connect and try again.'
-                )
-            )
-
+        manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(sid)
+        did = manager.did
     try:
-        command_obj = ObjectRegistry.get_object('query_tool', sid=sid, did=did)
+        command_obj = ObjectRegistry.get_object('query_tool', sgid=sgid,
+                                                sid=sid, did=did)
     except Exception as e:
+        app.logger.error(e)
         return internal_server_error(errormsg=str(e))
 
     # Create a unique id for the transaction
@@ -330,6 +350,8 @@ def close(trans_id):
     Args:
         trans_id: unique transaction id
     """
+    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
@@ -346,13 +368,15 @@ def close(trans_id):
             manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(cmd_obj.sid)
             conn = manager.connection(did=cmd_obj.did, conn_id=cmd_obj.conn_id)
         except Exception as e:
+            app.logger.error(e)
             return internal_server_error(errormsg=str(e))
 
         # Release the connection
         if conn.connected():
             manager.release(did=cmd_obj.did, conn_id=cmd_obj.conn_id)
 
-        # Remove the information of unique transaction id from the session variable.
+        # Remove the information of unique transaction id from the session
+        # variable.
         grid_data.pop(str(trans_id), None)
         session['gridData'] = grid_data
 
@@ -384,6 +408,7 @@ def validate_filter(sid, did, obj_id):
         # Call validate_filter method to validate the SQL.
         status, res = sql_filter_obj.validate_filter(filter_sql)
     except Exception as e:
+        app.logger.error(e)
         return internal_server_error(errormsg=str(e))
 
     return make_json_response(data={'status': status, 'result': res})
diff --git a/web/pgadmin/tools/datagrid/static/js/datagrid.js b/web/pgadmin/tools/datagrid/static/js/datagrid.js
index c44fbb1..28082b8 100644
--- a/web/pgadmin/tools/datagrid/static/js/datagrid.js
+++ b/web/pgadmin/tools/datagrid/static/js/datagrid.js
@@ -1,7 +1,9 @@
 define('pgadmin.datagrid', [
   'sources/gettext', 'sources/url_for', 'jquery', 'underscore', 'pgadmin.alertifyjs',
-  'sources/pgadmin', 'bundled_codemirror', 'sources/sqleditor_utils', 'wcdocker'
-], function(gettext, url_for, $, _, alertify, pgAdmin, codemirror, sqlEditorUtils) {
+  'sources/pgadmin', 'bundled_codemirror', 'sources/sqleditor_utils',
+  'backbone', 'wcdocker'
+], function(gettext, url_for, $, _, alertify, pgAdmin, codemirror,
+sqlEditorUtils, Backbone) {
     // Some scripts do export their object in the window only.
     // Generally the one, which do no have AMD support.
     var wcDocker = window.wcDocker,
@@ -12,7 +14,9 @@ define('pgadmin.datagrid', [
     if (pgAdmin.DataGrid)
       return pgAdmin.DataGrid;
 
-    pgAdmin.DataGrid = {
+    pgAdmin.DataGrid =
+    _.extend(
+    {
       init: function() {
         if (this.initialized)
             return;
@@ -112,6 +116,9 @@ define('pgadmin.datagrid', [
 
         // Load the newly created frame
         dataGridFrameType.load(pgBrowser.docker);
+        this.on("pgadmin-datagrid:transaction:created", function(trans_obj) {
+          this.launch_grid(trans_obj);
+        });
       },
 
       // This is a callback function to show data when user click on menu item.
@@ -154,6 +161,7 @@ define('pgadmin.datagrid', [
         var url_params = {
           'cmd_type': data.mnuid,
           'obj_type': d._type,
+          'sgid': parentData.server_group._id,
           'sid': parentData.server._id,
           'did': parentData.database._id,
           'obj_id': d._id
@@ -163,8 +171,7 @@ define('pgadmin.datagrid', [
         var grid_title = parentData.server.label + ' - ' + parentData.database.label + ' - '
                         + nsp_name + '.' + d.label;
 
-        // Initialize the data grid.
-        self.initialize_data_grid(baseUrl, grid_title, '', parentData.server.server_type);
+        self.create_transaction(baseUrl, null, 'false', parentData.server.server_type, '', grid_title, '');
       },
 
       // This is a callback function to show filtered data when user click on menu item.
@@ -209,10 +216,10 @@ define('pgadmin.datagrid', [
         var url_params = {
           'cmd_type': data.mnuid,
           'obj_type': d._type,
+          'sgid': parentData.server_group._id,
           'sid': parentData.server._id,
           'did': parentData.database._id,
           'obj_id': d._id
-
         };
 
         var baseUrl = url_for('datagrid.initialize_datagrid', url_params);
@@ -295,7 +302,7 @@ define('pgadmin.datagrid', [
                     success: function(res) {
                       if (res.data.status) {
                         // Initialize the data grid.
-                        self.initialize_data_grid(that.baseUrl, grid_title, sql, parentData.server.server_type);
+                        self.create_transaction(that.baseUrl, null, 'false', parentData.server.server_type, '', grid_title, sql);
                       }
                       else {
                         alertify.alert(
@@ -348,88 +355,6 @@ define('pgadmin.datagrid', [
                 parentData.server.label;
         return grid_title;
       },
-
-      initialize_data_grid: function(baseUrl, grid_title, sql_filter, server_type) {
-        var self = this;
-          self.grid_title = grid_title;
-
-        /* Ajax call to initialize the edit grid, which creates
-         * an asynchronous connection and create appropriate query
-         * for the selected node.
-         */
-        $.ajax({
-          url: baseUrl,
-          method: 'POST',
-          dataType: 'json',
-          contentType: "application/json",
-          data: JSON.stringify(sql_filter),
-          success: function(res) {
-
-            /* On successfully initialization find the dashboard panel,
-             * create new panel and add it to the dashboard panel.
-             */
-            var url_params = {
-              'trans_id': res.data.gridTransId,
-              'is_query_tool': 'false',
-              'editor_title': encodeURIComponent(self.grid_title)
-            };
-
-            var baseUrl = url_for('datagrid.panel', url_params) +
-              "?query_url=&server_type=" + encodeURIComponent(server_type);
-            var grid_title = gettext('Edit Data - ') + self.grid_title;
-            if (res.data.newBrowserTab) {
-              var newWin = window.open(baseUrl, '_blank');
-
-              // add a load listener to the window so that the title gets changed on page load
-              newWin.addEventListener("load", function() {
-                newWin.document.title = grid_title;
-              });
-            } else {
-              var propertiesPanel = pgBrowser.docker.findPanels('properties');
-              var dataGridPanel = pgBrowser.docker.addPanel('frm_datagrid', wcDocker.DOCK.STACKED, propertiesPanel[0]);
-
-              // Set panel title and icon
-              dataGridPanel.title('<span title="'+grid_title+'">'+grid_title+'</span>');
-              dataGridPanel.icon('fa fa-bolt');
-              dataGridPanel.focus();
-
-              // Listen on the panel closed event.
-              dataGridPanel.on(wcDocker.EVENT.CLOSED, function() {
-                $.ajax({
-                  url: url_for('datagrid.close', {'trans_id': res.data.gridTransId}),
-                  method: 'GET'
-                });
-              });
-
-              var openDataGridURL = function(j) {
-                // add spinner element
-                $(j).data('embeddedFrame').$container.append(self.spinner_el);
-                setTimeout(function() {
-                  var frameInitialized = $(j).data('frameInitialized');
-                  if (frameInitialized) {
-                    var frame = $(j).data('embeddedFrame');
-                    if (frame) {
-                      frame.openURL(baseUrl);
-                      frame.$container.find('.wcLoadingContainer').hide(1);
-                    }
-                  } else {
-                    openDataGridURL(j);
-                  }
-                }, 100);
-              };
-
-              openDataGridURL(dataGridPanel);
-            }
-          },
-          error: function(e) {
-            alertify.alert(
-              gettext('Error'),
-              gettext('Query Tool Initialization Error')
-            );
-          }
-        });
-      },
-
       // This is a callback function to show query tool when user click on menu item.
       show_query_tool: function(url, i, panel_title) {
         var self = this,
@@ -454,9 +379,10 @@ define('pgadmin.datagrid', [
         }
 
         var url_params = {
-          'sid': parentData.server._id
-        };
-        var url_endpoint = 'datagrid.initialize_query_tool'
+            'sgid': parentData.server_group._id,
+            'sid': parentData.server._id
+          },
+          url_endpoint = 'datagrid.initialize_query_tool';
         // If database not present then use Maintenance database
         // We will handle this at server side
         if (parentData.database) {
@@ -465,87 +391,123 @@ define('pgadmin.datagrid', [
         }
         var baseUrl = url_for(url_endpoint, url_params);
 
+        this.create_transaction(baseUrl, null, 'true', parentData.server.server_type, sURL, panel_title, '');
+      },
+      create_transaction: function(baseUrl, target, is_query_tool, server_type, sURL, panel_title, sql_filter) {
+        var self = this;
+        target =  target || self;
+
         $.ajax({
           url: baseUrl,
           method: 'POST',
           dataType: 'json',
+          data: JSON.stringify(sql_filter),
           contentType: "application/json",
           success: function(res) {
-            var grid_title = self.get_panel_title();
-            // Open the panel if frame is initialized
-            var url_params = {
-              'trans_id': res.data.gridTransId,
-              'is_query_tool': 'true',
-              'editor_title': encodeURIComponent(grid_title)
+            res.data.is_query_tool = is_query_tool;
+            res.data.server_type = server_type;
+            res.data.sURL = sURL;
+            res.data.panel_title = panel_title;
+            target.trigger("pgadmin-datagrid:transaction:created", res.data);
+          },
+          error: function(xhr, status, error) {
+            if (target !== self) {
+              if(xhr.status == 503 && xhr.responseJSON.info != undefined &&
+                  xhr.responseJSON.info == "CONNECTION_LOST") {
+                setTimeout(function() {
+                  target.handle_connection_lost(true);
+                });
+                return;
+              }
             }
 
-            var baseUrl = url_for('datagrid.panel', url_params) +
-                '?' + "query_url=" + encodeURI(sURL) + "&server_type=" + encodeURIComponent(parentData.server.server_type);
-
-            // Create title for CREATE/DELETE scripts
-            if (panel_title) {
-              panel_title =
-                sqlEditorUtils.capitalizeFirstLetter(panel_title) + ' script';
-            }
-            else {
-              panel_title = gettext('Query - ') + grid_title;
+            try {
+              var err = $.parseJSON(xhr.responseText);
+              alertify.alert(gettext("Query Tool Initialize Error"),
+                err.errormsg
+              );
+            } catch (e) {
+              alertify.alert(
+                e.statusText, gettext("Query Tool Initialize Error")
+              );
             }
+          }
+        });
+      },
+      launch_grid: function(trans_obj) {
+        var self = this,
+          panel_title = trans_obj.panel_title,
+          grid_title = self.get_panel_title(),
+          // Open the panel if frame is initialized
+          url_params = {
+            'trans_id': trans_obj.gridTransId,
+            'is_query_tool': trans_obj.is_query_tool,
+            'editor_title': encodeURIComponent(grid_title)
+          },
+          baseUrl = url_for('datagrid.panel', url_params) +
+            '?' + "query_url=" + encodeURI(trans_obj.sURL) + "&server_type=" + encodeURIComponent(trans_obj.server_type);
+
+        if(trans_obj.is_query_tool == 'false') {
+          panel_title = gettext('Edit Data - ') + grid_title;
+        } else {
+          // Create title for CREATE/DELETE scripts
+          if (panel_title) {
+            panel_title =
+              sqlEditorUtils.capitalizeFirstLetter(panel_title) + ' script';
+          } else {
+            panel_title = gettext('Query - ') + grid_title;
+          }
+        }
 
-            if (res.data.newBrowserTab) {
-              var newWin = window.open(baseUrl, '_blank');
-
-              // add a load listener to the window so that the title gets changed on page load
-              newWin.addEventListener("load", function() {
-                newWin.document.title = panel_title;
-              });
-            } else {
-              /* On successfully initialization find the dashboard panel,
-               * create new panel and add it to the dashboard panel.
-               */
-              var propertiesPanel = pgBrowser.docker.findPanels('properties');
-              var queryToolPanel = pgBrowser.docker.addPanel('frm_datagrid', wcDocker.DOCK.STACKED, propertiesPanel[0]);
-
-              // Set panel title and icon
-              queryToolPanel.title('<span title="'+panel_title+'">'+panel_title+'</span>');
-              queryToolPanel.icon('fa fa-bolt');
-              queryToolPanel.focus();
-
-              // Listen on the panel closed event.
-              queryToolPanel.on(wcDocker.EVENT.CLOSED, function() {
-                $.ajax({
-                  url: url_for('datagrid.close', {'trans_id': res.data.gridTransId}),
-                  method: 'GET'
-                });
-              });
+        if (trans_obj.newBrowserTab) {
+          var newWin = window.open(baseUrl, '_blank');
 
-              var openQueryToolURL = function(j) {
-                // add spinner element
-                $(j).data('embeddedFrame').$container.append(pgAdmin.DataGrid.spinner_el);
-                setTimeout(function() {
-                  var frameInitialized = $(j).data('frameInitialized');
-                  if (frameInitialized) {
-                    var frame = $(j).data('embeddedFrame');
-                    if (frame) {
-                      frame.openURL(baseUrl);
-                      frame.$container.find('.wcLoadingContainer').delay(1000).hide(1);
-                    }
-                  } else {
-                    openQueryToolURL(j);
-                  }
-                }, 100);
-              };
+          // add a load listener to the window so that the title gets changed on page load
+          newWin.addEventListener("load", function() {
+            newWin.document.title = panel_title;
+          });
+        } else {
+          /* On successfully initialization find the dashboard panel,
+           * create new panel and add it to the dashboard panel.
+           */
+          var propertiesPanel = pgBrowser.docker.findPanels('properties');
+          var queryToolPanel = pgBrowser.docker.addPanel('frm_datagrid', wcDocker.DOCK.STACKED, propertiesPanel[0]);
+
+          // Set panel title and icon
+          queryToolPanel.title('<span title="'+panel_title+'">'+panel_title+'</span>');
+          queryToolPanel.icon('fa fa-bolt');
+          queryToolPanel.focus();
+
+          // Listen on the panel closed event.
+          queryToolPanel.on(wcDocker.EVENT.CLOSED, function() {
+            $.ajax({
+              url: url_for('datagrid.close', {'trans_id': trans_obj.gridTransId}),
+              method: 'GET'
+            });
+          });
 
-              openQueryToolURL(queryToolPanel);
-            }
-          },
-          error: function(e) {
-            alertify.alert(
-              gettext("Query Tool Initialize Error")
-            );
-          }
-        });
+          var openQueryToolURL = function(j) {
+            // add spinner element
+            $(j).data('embeddedFrame').$container.append(pgAdmin.DataGrid.spinner_el);
+            setTimeout(function() {
+              var frameInitialized = $(j).data('frameInitialized');
+              if (frameInitialized) {
+                var frame = $(j).data('embeddedFrame');
+                if (frame) {
+                  frame.openURL(baseUrl);
+                  frame.$container.find('.wcLoadingContainer').delay(1000).hide(1);
+                }
+              } else {
+                openQueryToolURL(j);
+              }
+            }, 100);
+          };
+
+          openQueryToolURL(queryToolPanel);
+        }
       }
-    };
+    },
+    Backbone.Events);
 
     return pgAdmin.DataGrid;
   });
diff --git a/web/pgadmin/tools/datagrid/templates/datagrid/index.html b/web/pgadmin/tools/datagrid/templates/datagrid/index.html
index ff4368d..427d51f 100644
--- a/web/pgadmin/tools/datagrid/templates/datagrid/index.html
+++ b/web/pgadmin/tools/datagrid/templates/datagrid/index.html
@@ -337,38 +337,14 @@
           loadingDiv.addClass('hide');
           }
           });
-
-    // Fetch the SQL for Scripts (eg: CREATE/UPDATE/DELETE/SELECT)
-    var script_sql = '';
-{% if script_type_url%}
-    // Call AJAX only if script type url is present
-    $.ajax({
-      url: '{{ script_type_url }}',
-      type:'GET',
-      async: false,
-      success: function(res) {
-        script_sql = res;
-      },
-      error: function(jqx) {
-        var msg = jqx.responseText;
-        /* Error from the server */
-        if (jqx.status == 410 || jqx.status == 500) {
-          try {
-            var data = $.parseJSON(jqx.responseText);
-            msg = data.errormsg;
-          } catch (e) {}
-        }
-        pgBrowser.report_error(
-          S('{{ _('Error fetching SQL for script: "%s"') }}')
-          .sprintf(msg)
-          .value(), msg
-        );
-      }
-    });
-{% endif %}
-
+    {% if script_type_url %}
+        var script_type_url = '{{ script_type_url }}';
+    {% else %}
+        var script_type_url = '';
+    {% endif %}
     // Start the query tool.
     sqlEditorController.start({{ is_query_tool }}, "{{ editor_title }}",
-                    script_sql, {{ is_new_browser_tab }}, "{{ server_type }}", {{ prompt_save_changes }});
+            script_type_url, {{ is_new_browser_tab }}, "{{ server_type }}", {{ prompt_save_changes }}, {{ url_params|safe}});
+
 });
 {% endblock %}
diff --git a/web/pgadmin/tools/sqleditor/__init__.py b/web/pgadmin/tools/sqleditor/__init__.py
index d2b5f2e..4215ea9 100644
--- a/web/pgadmin/tools/sqleditor/__init__.py
+++ b/web/pgadmin/tools/sqleditor/__init__.py
@@ -14,7 +14,8 @@ import pickle
 import random
 import codecs
 
-from flask import Response, url_for, render_template, session, request
+from flask import Response, url_for, render_template, session, request,\
+    current_app
 from flask_babel import gettext
 from flask_security import login_required
 from pgadmin.tools.sqleditor.command import QueryToolCommand
@@ -26,6 +27,7 @@ from pgadmin.utils.driver import get_driver
 from pgadmin.utils.sqlautocomplete.autocomplete import SQLAutoComplete
 from pgadmin.misc.file_manager import Filemanager
 from pgadmin.utils.menu import MenuItem
+from pgadmin.utils.exception import ConnectionLost
 
 from config import PG_DEFAULT_DRIVER, ON_DEMAND_RECORD_COUNT
 
@@ -77,7 +79,6 @@ class SqlEditorModule(PgAdminModule):
             'when': None
         }]
 
-
     def get_panels(self):
         return []
 
@@ -363,6 +364,12 @@ def check_transaction_status(trans_id):
     Returns: status and connection object
 
     """
+
+    if 'gridData' not in session:
+        return False, gettext(
+            'Transaction ID not found in the session.'
+        ), None, None, None
+
     grid_data = session['gridData']
 
     # Return from the function if transaction id not found
@@ -381,7 +388,10 @@ def check_transaction_status(trans_id):
         conn = manager.connection(did=trans_obj.did, conn_id=trans_obj.conn_id,
                                   use_binary_placeholder=True,
                                   array_to_string=True)
+    except ConnectionLost as e:
+        raise
     except Exception as e:
+        current_app.logger.error(e)
         return False, internal_server_error(errormsg=str(e)), None, None, None
 
     if conn.connected():
@@ -408,12 +418,23 @@ def start_view_data(trans_id):
     # Check the transaction and connection status
     status, error_msg, conn, trans_obj, session_obj = check_transaction_status(trans_id)
 
+    if error_msg == gettext(
+            'Transaction ID not found in the session.'):
+        return make_json_response(success=0, errormsg=error_msg,
+                                  info='DATAGRID_TRANSACTION_REQUIRED', status=404)
+
     # get the default connection as current connection which is attached to
     # trans id holds the cursor which has query result so we cannot use that
     # connection to execute another query otherwise we'll lose query result.
 
-    manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(trans_obj.sid)
-    default_conn = manager.connection(did=trans_obj.did)
+    try:
+        manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(trans_obj.sid)
+        default_conn = manager.connection(did=trans_obj.did)
+    except ConnectionLost as e:
+        raise
+    except Exception as e:
+        current_app.logger.error(e)
+        return internal_server_error(errormsg=str(e))
 
     # Connect to the Server if not connected.
     if not default_conn.connected():
@@ -435,7 +456,10 @@ def start_view_data(trans_id):
             pk_names, primary_keys = trans_obj.get_primary_keys(default_conn)
 
             # Fetch OIDs status
-            has_oids = trans_obj.has_oids(default_conn)
+            if trans_obj.object_type == 'table':
+                has_oids = trans_obj.has_oids(default_conn)
+            else:
+                has_oids = False
 
             # Fetch the applied filter.
             filter_applied = trans_obj.is_filter_applied()
@@ -495,16 +519,20 @@ def start_query_tool(trans_id):
     else:
         sql = request.args or request.form
 
+    if 'gridData' not in session:
+        return make_json_response(
+            success=0,
+            errormsg=gettext('Transaction ID not found in the session.'),
+            info='DATAGRID_TRANSACTION_REQUIRED', status=404)
+
     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': False, 'result': gettext('Transaction ID not found in the session.'),
-                'can_edit': False, 'can_filter': False
-            }
-        )
+            success=0,
+            errormsg=gettext('Transaction ID not found in the session.'),
+            info='DATAGRID_TRANSACTION_REQUIRED', status=404)
 
     # Fetch the object for the specified transaction id.
     # Use pickle.loads function to get the command object
@@ -529,13 +557,17 @@ def start_query_tool(trans_id):
             conn = manager.connection(did=trans_obj.did, conn_id=conn_id,
                                       use_binary_placeholder=True,
                                       array_to_string=True)
+        except ConnectionLost as e:
+            raise
         except Exception as e:
+            current_app.logger.error(e)
             return internal_server_error(errormsg=str(e))
 
         # Connect to the Server if not connected.
         if not conn.connected():
             status, msg = conn.connect()
             if not status:
+                current_app.logger.error(msg)
                 return internal_server_error(errormsg=str(msg))
 
         if conn.connected():
@@ -602,9 +634,16 @@ def preferences(trans_id):
 
         # Check the transaction and connection status
         status, error_msg, conn, trans_obj, session_obj = check_transaction_status(trans_id)
+
+        if error_msg == gettext(
+                'Transaction ID not found in the session.'):
+            return make_json_response(success=0, errormsg=error_msg,
+                                      info='DATAGRID_TRANSACTION_REQUIRED', status=404)
+
         if status and conn is not None \
                 and trans_obj is not None and session_obj is not None:
-            # Call the set_auto_commit and set_auto_rollback method of transaction object
+            # Call the set_auto_commit and set_auto_rollback method of
+            # transaction object
             trans_obj.set_auto_commit(blueprint.auto_commit.get())
             trans_obj.set_auto_rollback(blueprint.auto_rollback.get())
 
@@ -668,6 +707,12 @@ def poll(trans_id):
 
     # Check the transaction and connection status
     status, error_msg, conn, trans_obj, session_obj = check_transaction_status(trans_id)
+
+    if error_msg == gettext(
+            'Transaction ID not found in the session.'):
+        return make_json_response(success=0, errormsg=error_msg,
+                                  info='DATAGRID_TRANSACTION_REQUIRED', status=404)
+
     if status and conn is not None and session_obj is not None:
         status, result = conn.poll(formatted_exception_msg=True, no_result=True)
         if not status:
@@ -846,6 +891,12 @@ def fetch(trans_id, fetch_all=None):
 
     # Check the transaction and connection status
     status, error_msg, conn, trans_obj, session_obj = check_transaction_status(trans_id)
+
+    if error_msg == gettext(
+            'Transaction ID not found in the session.'):
+        return make_json_response(success=0, errormsg=error_msg,
+                                  info='DATAGRID_TRANSACTION_REQUIRED', status=404)
+
     if status and conn is not None and session_obj is not None:
         status, result = conn.async_fetchmany_2darray(fetch_row_cnt)
         if not status:
@@ -959,6 +1010,12 @@ def save(trans_id):
 
     # Check the transaction and connection status
     status, error_msg, conn, trans_obj, session_obj = check_transaction_status(trans_id)
+
+    if error_msg == gettext(
+            'Transaction ID not found in the session.'):
+        return make_json_response(success=0, errormsg=error_msg,
+                                  info='DATAGRID_TRANSACTION_REQUIRED', status=404)
+
     if status and conn is not None \
             and trans_obj is not None and session_obj is not None:
 
@@ -1017,6 +1074,11 @@ def get_filter(trans_id):
 
     # Check the transaction and connection status
     status, error_msg, conn, trans_obj, session_obj = check_transaction_status(trans_id)
+
+    if error_msg == gettext(
+            'Transaction ID not found in the session.'):
+        return make_json_response(success=0, errormsg=error_msg,
+                                  info='DATAGRID_TRANSACTION_REQUIRED', status=404)
     if status and conn is not None \
             and trans_obj is not None and session_obj is not None:
 
@@ -1047,6 +1109,12 @@ def apply_filter(trans_id):
 
     # Check the transaction and connection status
     status, error_msg, conn, trans_obj, session_obj = check_transaction_status(trans_id)
+
+    if error_msg == gettext(
+            'Transaction ID not found in the session.'):
+        return make_json_response(success=0, errormsg=error_msg,
+                                  info='DATAGRID_TRANSACTION_REQUIRED', status=404)
+
     if status and conn is not None \
             and trans_obj is not None and session_obj is not None:
 
@@ -1082,6 +1150,12 @@ def append_filter_inclusive(trans_id):
 
     # Check the transaction and connection status
     status, error_msg, conn, trans_obj, session_obj = check_transaction_status(trans_id)
+
+    if error_msg == gettext(
+            'Transaction ID not found in the session.'):
+        return make_json_response(success=0, errormsg=error_msg,
+                                  info='DATAGRID_TRANSACTION_REQUIRED', status=404)
+
     if status and conn is not None \
             and trans_obj is not None and session_obj is not None:
 
@@ -1128,6 +1202,11 @@ def append_filter_exclusive(trans_id):
 
     # Check the transaction and connection status
     status, error_msg, conn, trans_obj, session_obj = check_transaction_status(trans_id)
+
+    if error_msg == gettext(
+            'Transaction ID not found in the session.'):
+        return make_json_response(success=0, errormsg=error_msg,
+                                  info='DATAGRID_TRANSACTION_REQUIRED', status=404)
     if status and conn is not None \
             and trans_obj is not None and session_obj is not None:
 
@@ -1171,6 +1250,12 @@ def remove_filter(trans_id):
 
     # Check the transaction and connection status
     status, error_msg, conn, trans_obj, session_obj = check_transaction_status(trans_id)
+
+    if error_msg == gettext(
+            'Transaction ID not found in the session.'):
+        return make_json_response(success=0, errormsg=error_msg,
+                                  info='DATAGRID_TRANSACTION_REQUIRED', status=404)
+
     if status and conn is not None \
             and trans_obj is not None and session_obj is not None:
 
@@ -1208,6 +1293,12 @@ def set_limit(trans_id):
 
     # Check the transaction and connection status
     status, error_msg, conn, trans_obj, session_obj = check_transaction_status(trans_id)
+
+    if error_msg == gettext(
+            'Transaction ID not found in the session.'):
+        return make_json_response(success=0, errormsg=error_msg,
+                                  info='DATAGRID_TRANSACTION_REQUIRED', status=404)
+
     if status and conn is not None \
             and trans_obj is not None and session_obj is not None:
 
@@ -1240,15 +1331,20 @@ def cancel_transaction(trans_id):
         trans_id: unique transaction id
     """
 
+    if 'gridData' not in session:
+        return make_json_response(
+            success=0,
+            errormsg=gettext('Transaction ID not found in the session.'),
+            info='DATAGRID_TRANSACTION_REQUIRED', status=404)
+
     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': False, 'result': gettext('Transaction ID not found in the session.')
-            }
-        )
+            success=0,
+            errormsg=gettext('Transaction ID not found in the session.'),
+            info='DATAGRID_TRANSACTION_REQUIRED', status=404)
 
     # Fetch the object for the specified transaction id.
     # Use pickle.loads function to get the command object
@@ -1310,6 +1406,12 @@ def get_object_name(trans_id):
 
     # Check the transaction and connection status
     status, error_msg, conn, trans_obj, session_obj = check_transaction_status(trans_id)
+
+    if error_msg == gettext(
+            'Transaction ID not found in the session.'):
+        return make_json_response(success=0, errormsg=error_msg,
+                                  info='DATAGRID_TRANSACTION_REQUIRED', status=404)
+
     if status and conn is not None \
             and trans_obj is not None and session_obj is not None:
 
@@ -1340,6 +1442,12 @@ def set_auto_commit(trans_id):
 
     # Check the transaction and connection status
     status, error_msg, conn, trans_obj, session_obj = check_transaction_status(trans_id)
+
+    if error_msg == gettext(
+            'Transaction ID not found in the session.'):
+        return make_json_response(success=0, errormsg=error_msg,
+                                  info='DATAGRID_TRANSACTION_REQUIRED', status=404)
+
     if status and conn is not None \
             and trans_obj is not None and session_obj is not None:
 
@@ -1381,6 +1489,12 @@ def set_auto_rollback(trans_id):
 
     # Check the transaction and connection status
     status, error_msg, conn, trans_obj, session_obj = check_transaction_status(trans_id)
+
+    if error_msg == gettext(
+            'Transaction ID not found in the session.'):
+        return make_json_response(success=0, errormsg=error_msg,
+                                  info='DATAGRID_TRANSACTION_REQUIRED', status=404)
+
     if status and conn is not None \
             and trans_obj is not None and session_obj is not None:
 
@@ -1429,6 +1543,12 @@ def auto_complete(trans_id):
 
     # Check the transaction and connection status
     status, error_msg, conn, trans_obj, session_obj = check_transaction_status(trans_id)
+
+    if error_msg == gettext(
+            'Transaction ID not found in the session.'):
+        return make_json_response(success=0, errormsg=error_msg,
+                                  info='DATAGRID_TRANSACTION_REQUIRED', status=404)
+
     if status and conn is not None \
             and trans_obj is not None and session_obj is not None:
 
diff --git a/web/pgadmin/tools/sqleditor/command.py b/web/pgadmin/tools/sqleditor/command.py
index 70db0c9..919c4dc 100644
--- a/web/pgadmin/tools/sqleditor/command.py
+++ b/web/pgadmin/tools/sqleditor/command.py
@@ -103,7 +103,9 @@ class BaseCommand(object):
             **kwargs : N number of parameters
         """
 
-        # Save the server id and database id, namespace id, object id
+        # Save the server group id, server id and database id, namespace id,
+        # object id
+        self.sgid = kwargs['sgid'] if 'sgid' in kwargs else None
         self.sid = kwargs['sid'] if 'sid' in kwargs else None
         self.did = kwargs['did'] if 'did' in kwargs else None
 
diff --git a/web/pgadmin/tools/sqleditor/static/js/sqleditor.js b/web/pgadmin/tools/sqleditor/static/js/sqleditor.js
index dbc416e..2154962 100644
--- a/web/pgadmin/tools/sqleditor/static/js/sqleditor.js
+++ b/web/pgadmin/tools/sqleditor/static/js/sqleditor.js
@@ -17,18 +17,19 @@ define('tools.querytool', [
     'react', 'react-dom',
     'sources/sqleditor/keyboard_shortcuts',
     'sources/sqleditor/query_tool_actions',
-  'sources/../bundle/slickgrid',
+    'pgadmin.datagrid',
+    'sources/../bundle/slickgrid',
     'pgadmin.file_manager',
     'backgrid.sizeable.columns',
     'slick.pgadmin.formatters',
     'slick.pgadmin.editors',
-    'pgadmin.browser'
+    'pgadmin.browser',
+    'pgadmin.tools.user_management'
 ], function(
   babelPollyfill,gettext, url_for, $, _, S, alertify, pgAdmin, Backbone, codemirror,
   pgExplain, GridSelector, ActiveCellCapture, clipboard, copyData, RangeSelectionHelper, handleQueryOutputKeyboardEvent,
   XCellSelectionModel, setStagedRows,  SqlEditorUtils, HistoryBundle, queryHistory, React, ReactDOM,
-  keyboardShortcuts
-, queryToolActions) {
+  keyboardShortcuts, queryToolActions, Datagrid) {
     /* Return back, this has been called more than once */
     if (pgAdmin.SqlEditor)
       return pgAdmin.SqlEditor;
@@ -41,6 +42,11 @@ define('tools.querytool', [
 
   var is_query_running = false;
 
+  var is_new_transaction_required = function(xhr) {
+    return xhr.status == 404 && xhr.responseJSON &&
+                xhr.responseJSON.info &&
+                xhr.responseJSON.info == 'DATAGRID_TRANSACTION_REQUIRED'
+  }
   // Defining Backbone view for the sql grid.
   var SQLEditorView = Backbone.View.extend({
     initialize: function (opts) {
@@ -398,6 +404,14 @@ define('tools.querytool', [
                   from: {line: self.current_line, ch: start},
                   to: {line: self.current_line, ch: end}
                 });
+              },
+              error:function(e) {
+                if (pgAdmin.Browser.UserManagement.is_pga_login_required(e)) {
+                  return pgAdmin.Browser.UserManagement.pga_login();
+                }
+                if(is_new_transaction_required(e)) {
+                  return self.init_transaction();
+                }
               }
             });
           }.bind(ctx)
@@ -1010,7 +1024,10 @@ define('tools.querytool', [
             self.update_msg_history(false,
               gettext('Not connected to the server or the connection to the server has been closed.')
             );
-            return;
+          }
+
+          if (pgAdmin.Browser.UserManagement.is_pga_login_required(e)) {
+            pgAdmin.Browser.UserManagement.pga_login();
           }
         }
       });
@@ -1580,14 +1597,128 @@ define('tools.querytool', [
     Backbone.Events,
     {
       initialize: function (container, opts) {
+        self= this;
         this.container = container;
+        if (!alertify.dlgGetServerPass) {
+          alertify.dialog('dlgGetServerPass', function factory() {
+            return {
+              main: function(
+                title, message
+              ) {
+                this.set('title', title);
+                this.setting('message',message);
+              },
+              setup:function() {
+                return {
+                  buttons:[
+                    {
+                      text: gettext("OK"), key: 13, className: "btn btn-primary"
+                    },
+                    {
+                      text: gettext("Cancel"), className: "btn btn-danger"
+                    }
+                  ],
+                  focus: { element: '#password', select: true },
+                  options: {
+                    modal: 0, resizable: false, maximizable: false, pinnable: false
+                  }
+                };
+              },
+              build:function() {},
+              settings:{
+                message: null
+              },
+              prepare:function() {
+                this.setContent(this.setting('message'));
+              },
+              callback: function(closeEvent) {
+                if (closeEvent.button.text == gettext("OK")) {
+                  var passdata = $(this.elements.content).find('#frmPassword').serialize();
+                   self.init_connection(false, passdata);
+                }
+              }
+            };
+          });
+        }
+        this.on("pgadmin-datagrid:transaction:created", function(trans_obj) {
+          self.transId = trans_obj.gridTransId;
+          if (self.is_query_tool) {
+            alertify.success(gettext('New SQL editor session created.'));
+          } else {
+            alertify.success(gettext('New Data grid session created.'));
+          }
+        });
+        pgBrowser.Events.on('pgadmin:user:logged-in', function() {
+          self.init_transaction();
+        });
+      },
+
+      init_transaction: function() {
+        var url_endpoint;
+        if (this.is_query_tool) {
+          url_endpoint = 'datagrid.initialize_query_tool';
+
+          // If database not present then use Maintenance database
+          // We will handle this at server side
+          if (this.url_params.did) {
+            url_endpoint = 'datagrid.initialize_query_tool_with_did';
+          }
+
+        } else {
+          url_endpoint = 'datagrid.initialize_datagrid';
+        }
+
+        var baseUrl = url_for(url_endpoint, this.url_params);
+
+        Datagrid.create_transaction(baseUrl, this, this.is_query_tool,
+            this.server_type, '', '', '');
       },
 
+      handle_connection_lost: function(create_transaction) {
+        var self= this;
+        alertify.confirm(
+            gettext('Connection lost'),
+            gettext('Would you like to reconnect to the server?'),
+            function() {
+              self.init_connection(create_transaction);
+            }, function() {});
+      },
+
+      init_connection: function(create_transaction, passdata) {
+        var self = this;
+        $.post(url_for('NODE-server.connect_id', {'gid': this.url_params.sgid,
+                                                  'sid': this.url_params.sid}),
+                                                  passdata)
+        .done(function(res) {
+          if (res.success == 1) {
+            alertify.success(res.info);
+            if (create_transaction) {
+              self.init_transaction();
+            }
+          }
+        })
+        .fail(function(xhr, status, error) {
+          if (pgAdmin.Browser.UserManagement.is_pga_login_required(xhr)) {
+            pgAdmin.Browser.UserManagement.pga_login();
+          } else {
+            if(xhr.responseJSON &&
+                xhr.responseJSON.result) {
+              alertify.dlgGetServerPass(gettext('Connect to Server'),
+                xhr.responseJSON.result);
+            } else {
+              alertify.dlgGetServerPass(gettext('Connect to Server'),
+                xhr.responseText);
+            }
+          }
+        });
+      },
       /* This function is used to create instance of SQLEditorView,
        * call the render method of the grid view to render the backgrid
        * header and loading icon and start execution of the sql query.
        */
-      start: function (is_query_tool, editor_title, script_sql, is_new_browser_tab, server_type, prompt_save_changes) {
+      start: function (is_query_tool, editor_title, script_type_url,
+          is_new_browser_tab, server_type, prompt_save_changes, url_params
+      ) {
         var self = this;
 
         self.is_query_tool = is_query_tool;
@@ -1603,6 +1734,8 @@ define('tools.querytool', [
         self.close_on_save = false;
         self.server_type = server_type;
         self.prompt_save_changes = prompt_save_changes;
+        self.url_params = url_params;
+        self.script_type_url = script_type_url;
 
         // We do not allow to call the start multiple times.
         if (self.gridView)
@@ -1620,6 +1753,59 @@ define('tools.querytool', [
         // Render the header
         self.gridView.render();
 
+        if (self.is_query_tool) {
+          // Fetch the SQL for Scripts (eg: CREATE/UPDATE/DELETE/SELECT)
+          // Call AJAX only if script type url is present
+          if (script_type_url) {
+            $.ajax({
+              url: script_type_url,
+              type:'GET',
+              success: function(res) {
+                self.gridView.query_tool_obj.refresh();
+                if (res && res !== '') {
+                  self.gridView.query_tool_obj.setValue(res);
+                }
+                self.init_events();
+              },
+              error: function(jqx) {
+                var msg = jqx.responseText;
+                self.init_events();
+
+                if (pgAdmin.Browser.UserManagement.is_pga_login_required(e)) {
+                  return pgAdmin.Browser.UserManagement.pga_login();
+                }
+
+                /* Error from the server */
+                if (jqx.status == 410 || jqx.status == 500) {
+                  try {
+                    var data = $.parseJSON(jqx.responseText);
+                    msg = data.errormsg;
+                  } catch (e) {}
+                }
+                pgBrowser.report_error(
+                  S(gettext("Error fetching SQL for script: %s.")).sprintf(msg).value()
+                );
+              }
+            });
+          } else {
+            self.init_events();
+          }
+        }
+        else {
+          // Disable codemirror by setting cursor to nocursor and background to dark.
+          self.init_events();
+          self.gridView.query_tool_obj.setOption("readOnly", 'nocursor');
+          var cm = self.gridView.query_tool_obj.getWrapperElement();
+          if (cm) {
+            cm.className += ' bg-gray-1 opacity-5';
+          }
+          self.disable_tool_buttons(true);
+          self.execute_data_query();
+        }
+      },
+
+      init_events: function() {
+        var self = this;
         // Listen to the file manager button events
         pgAdmin.Browser.Events.on('pgadmin-storage:finish_btn:select_file', self._select_file_handler, self);
         pgAdmin.Browser.Events.on('pgadmin-storage:finish_btn:create_file', self._save_file_handler, self);
@@ -1653,23 +1839,6 @@ define('tools.querytool', [
         // Indentation related
         self.on('pgadmin-sqleditor:indent_selected_code', self._indent_selected_code, self);
         self.on('pgadmin-sqleditor:unindent_selected_code', self._unindent_selected_code, self);
-
-        if (self.is_query_tool) {
-          self.gridView.query_tool_obj.refresh();
-          if (script_sql && script_sql !== '') {
-            self.gridView.query_tool_obj.setValue(script_sql);
-          }
-        }
-        else {
-          // Disable codemirror by setting cursor to nocursor and background to dark.
-          self.gridView.query_tool_obj.setOption("readOnly", 'nocursor');
-          var cm = self.gridView.query_tool_obj.getWrapperElement();
-          if (cm) {
-            cm.className += ' bg-gray-1 opacity-5';
-          }
-          self.disable_tool_buttons(true);
-          self.execute_data_query();
-        }
       },
 
       // This function checks if there is any dirty data in the grid before
@@ -1778,11 +1947,27 @@ define('tools.querytool', [
               );
               return;
             }
+            if (pgAdmin.Browser.UserManagement.is_pga_login_required(e)) {
+              pgAdmin.Browser.UserManagement.pga_login();
+            }
+
+            if(is_new_transaction_required(e)) {
+              self.init_transaction();
+            }
 
             var msg = e.responseText;
-            if (e.responseJSON != undefined &&
-              e.responseJSON.errormsg != undefined)
-              msg = e.responseJSON.errormsg;
+            if (e.responseJSON != undefined) {
+              if(e.responseJSON.errormsg != undefined) {
+                msg = e.responseJSON.errormsg;
+              }
+
+              if(e.status == 503 && e.responseJSON.info != undefined &&
+                  e.responseJSON.info == "CONNECTION_LOST") {
+                setTimeout(function() {
+                  self.handle_connection_lost();
+                });
+              }
+            }
 
             self.update_msg_history(false, msg);
           }
@@ -1886,6 +2071,10 @@ define('tools.querytool', [
                   return;
                 }
 
+                if (pgAdmin.Browser.UserManagement.is_pga_login_required(e)) {
+                  return pgAdmin.Browser.UserManagement.pga_login();
+                }
+
                 var msg = e.responseText;
                 if (e.responseJSON != undefined &&
                   e.responseJSON.errormsg != undefined)
@@ -2512,6 +2701,10 @@ define('tools.querytool', [
                   return;
                 }
 
+                if (pgAdmin.Browser.UserManagement.is_pga_login_required(e)) {
+                  pgAdmin.Browser.UserManagement.pga_login();
+                }
+
               var msg = e.responseText;
               if (e.responseJSON != undefined &&
                 e.responseJSON.errormsg != undefined)
@@ -2653,9 +2846,13 @@ define('tools.querytool', [
               self.is_query_changed = false;
             },
             error: function(e) {
+              self.trigger('pgadmin-sqleditor:loading-icon:hide');
+              if (pgAdmin.Browser.UserManagement.is_pga_login_required(e)) {
+                return pgAdmin.Browser.UserManagement.pga_login();
+              }
+
               var errmsg = $.parseJSON(e.responseText).errormsg;
               alertify.error(errmsg);
-              self.trigger('pgadmin-sqleditor:loading-icon:hide');
               // hide cursor
               $busy_icon_div.removeClass('show_progress');
             }
@@ -2699,6 +2896,9 @@ define('tools.querytool', [
           },
           error: function (e) {
             self.trigger('pgadmin-sqleditor:loading-icon:hide');
+            if (pgAdmin.Browser.UserManagement.is_pga_login_required(e)) {
+              return pgAdmin.Browser.UserManagement.pga_login();
+            }
 
               var errmsg = $.parseJSON(e.responseText).errormsg;
               setTimeout(
@@ -2806,6 +3006,14 @@ define('tools.querytool', [
           error: function (e) {
             self.trigger('pgadmin-sqleditor:loading-icon:hide');
 
+            if (pgAdmin.Browser.UserManagement.is_pga_login_required(e)) {
+              return pgAdmin.Browser.UserManagement.pga_login();
+            }
+
+            if(is_new_transaction_required(e)) {
+              return self.init_transaction();
+            }
+
             var msg;
             if (e.readyState == 0) {
               msg =
@@ -2874,6 +3082,14 @@ define('tools.querytool', [
           },
           error: function (e) {
             self.trigger('pgadmin-sqleditor:loading-icon:hide');
+            if (pgAdmin.Browser.UserManagement.is_pga_login_required(e)) {
+              return pgAdmin.Browser.UserManagement.pga_login();
+            }
+
+            if(is_new_transaction_required(e)) {
+              return self.init_transaction();
+            }
+
             setTimeout(
               function () {
                 if (e.readyState == 0) {
@@ -2944,6 +3160,13 @@ define('tools.querytool', [
           },
           error: function (e) {
             self.trigger('pgadmin-sqleditor:loading-icon:hide');
+            if (pgAdmin.Browser.UserManagement.is_pga_login_required(e)) {
+              return pgAdmin.Browser.UserManagement.pga_login();
+            }
+
+            if(is_new_transaction_required(e)) {
+              return self.init_transaction();
+            }
 
             setTimeout(
               function () {
@@ -2995,6 +3218,14 @@ define('tools.querytool', [
           },
           error: function (e) {
             self.trigger('pgadmin-sqleditor:loading-icon:hide');
+            if (pgAdmin.Browser.UserManagement.is_pga_login_required(e)) {
+              return pgAdmin.Browser.UserManagement.pga_login();
+            }
+
+            if(is_new_transaction_required(e)) {
+              return self.init_transaction();
+            }
+
             setTimeout(
               function () {
                 if (e.readyState == 0) {
@@ -3050,6 +3281,14 @@ define('tools.querytool', [
           },
           error: function (e) {
             self.trigger('pgadmin-sqleditor:loading-icon:hide');
+            if (pgAdmin.Browser.UserManagement.is_pga_login_required(e)) {
+              return pgAdmin.Browser.UserManagement.pga_login();
+            }
+
+            if(is_new_transaction_required(e)) {
+              return self.init_transaction();
+            }
+
             setTimeout(
               function () {
                 if (e.readyState == 0) {
@@ -3184,6 +3423,14 @@ define('tools.querytool', [
           },
           error: function (e) {
             self.trigger('pgadmin-sqleditor:loading-icon:hide');
+            if (pgAdmin.Browser.UserManagement.is_pga_login_required(e)) {
+              return pgAdmin.Browser.UserManagement.pga_login();
+            }
+
+            if(is_new_transaction_required(e)) {
+              return self.init_transaction();
+            }
+
             setTimeout(
               function () {
                 if (e.readyState == 0) {
@@ -3306,11 +3553,26 @@ define('tools.querytool', [
               return;
             }
 
+            if (pgAdmin.Browser.UserManagement.is_pga_login_required(e)) {
+              pgAdmin.Browser.UserManagement.pga_login();
+            }
+
+            if(is_new_transaction_required(e)) {
+              self.init_transaction();
+            }
             var msg = e.responseText;
-            if (e.responseJSON != undefined &&
-              e.responseJSON.errormsg != undefined)
-              msg = e.responseJSON.errormsg;
+            if (e.responseJSON != undefined) {
+              if(e.responseJSON.errormsg != undefined) {
+                msg = e.responseJSON.errormsg;
+              }
 
+              if(e.status == 503 && e.responseJSON.info != undefined &&
+                  e.responseJSON.info == "CONNECTION_LOST") {
+                setTimeout(function() {
+                  self.handle_connection_lost();
+                });
+              }
+            }
             self.update_msg_history(false, msg);
           }
         });
@@ -3404,6 +3666,10 @@ define('tools.querytool', [
               return;
             }
 
+            if (pgAdmin.Browser.UserManagement.is_pga_login_required(e)) {
+              return pgAdmin.Browser.UserManagement.pga_login();
+            }
+
             var msg = e.responseText;
             if (e.responseJSON != undefined &&
               e.responseJSON.errormsg != undefined)
@@ -3453,6 +3719,10 @@ define('tools.querytool', [
               return;
             }
 
+            if (pgAdmin.Browser.UserManagement.is_pga_login_required(e)) {
+              return pgAdmin.Browser.UserManagement.pga_login();
+            }
+
             var msg = e.responseText;
             if (e.responseJSON != undefined &&
               e.responseJSON.errormsg != undefined)
@@ -3474,7 +3744,7 @@ define('tools.querytool', [
           auto_commit = false;
         }
 
-        // Make ajax call to change the limit
+        // Make ajax call to toggle auto commit
         $.ajax({
           url: url_for('sqleditor.auto_commit', {'trans_id': self.transId}),
           method: 'POST',
@@ -3492,6 +3762,14 @@ define('tools.querytool', [
               return;
             }
 
+            if (pgAdmin.Browser.UserManagement.is_pga_login_required(e)) {
+              return pgAdmin.Browser.UserManagement.pga_login();
+            }
+
+            if(is_new_transaction_required(e)) {
+              return self.init_transaction();
+            }
+
             var msg = e.responseText;
             if (e.responseJSON != undefined &&
               e.responseJSON.errormsg != undefined)
@@ -3532,6 +3810,15 @@ define('tools.querytool', [
             }
           },
           error: function (e) {
+
+            if (pgAdmin.Browser.UserManagement.is_pga_login_required(e)) {
+              return pgAdmin.Browser.UserManagement.pga_login();
+            }
+
+            if(is_new_transaction_required(e)) {
+              return self.init_transaction();
+            }
+
             alertify.alert(gettext('Explain options error'),
               gettext("Error occurred while setting verbose option in explain.")
             );
@@ -3570,6 +3857,14 @@ define('tools.querytool', [
             }
           },
           error: function (e) {
+            if (pgAdmin.Browser.UserManagement.is_pga_login_required(e)) {
+              return pgAdmin.Browser.UserManagement.pga_login();
+            }
+
+            if(is_new_transaction_required(e)) {
+              return self.init_transaction();
+            }
+
             alertify.alert(gettext('Explain options error'),
               gettext("Error occurred while setting costs option in explain.")
             );
@@ -3607,6 +3902,14 @@ define('tools.querytool', [
             }
           },
           error: function (e) {
+            if (pgAdmin.Browser.UserManagement.is_pga_login_required(e)) {
+              return pgAdmin.Browser.UserManagement.pga_login();
+            }
+
+            if(is_new_transaction_required(e)) {
+              return self.init_transaction();
+            }
+
             alertify.alert(gettext('Explain options error'),
               gettext("Error occurred while setting buffers option in explain.")
             );
@@ -3643,6 +3946,14 @@ define('tools.querytool', [
             }
           },
           error: function (e) {
+            if (pgAdmin.Browser.UserManagement.is_pga_login_required(e)) {
+              return pgAdmin.Browser.UserManagement.pga_login();
+            }
+
+            if(is_new_transaction_required(e)) {
+              return self.init_transaction();
+            }
+
             alertify.alert(gettext('Explain options error'),
               gettext("Error occurred while setting timing option in explain.")
             );
@@ -3739,6 +4050,9 @@ define('tools.querytool', [
             }
           },
           error: function (e) {
+            if (pgAdmin.Browser.UserManagement.is_pga_login_required(e)) {
+              return pgAdmin.Browser.UserManagement.pga_login();
+            }
             updateUI();
             alertify.alert(gettext('Get Preferences error'),
               gettext("Error occurred while getting query tool options.")
@@ -3748,6 +4062,8 @@ define('tools.querytool', [
       },
       close: function () {
         var self = this;
+
+        pgBrowser.Events.off('pgadmin:user:logged-in', this.init_transaction);
         _.each(window.top.pgAdmin.Browser.docker.findPanels('frm_datagrid'), function (panel) {
           if (panel.isVisible()) {
             window.onbeforeunload = null;
diff --git a/web/pgadmin/tools/user_management/__init__.py b/web/pgadmin/tools/user_management/__init__.py
index 77c1b4e..2cf4dfb 100644
--- a/web/pgadmin/tools/user_management/__init__.py
+++ b/web/pgadmin/tools/user_management/__init__.py
@@ -13,7 +13,7 @@ import simplejson as json
 import re
 
 from flask import render_template, request, \
-    url_for, Response, abort
+    url_for, Response, abort, current_app
 from flask_babel import gettext as _
 from flask_security import login_required, roles_required, current_user
 from flask_security.utils import encrypt_password
@@ -73,7 +73,7 @@ class UserManagementModule(PgAdminModule):
             'user_management.roles', 'user_management.role',
             'user_management.update_user', 'user_management.delete_user',
             'user_management.create_user', 'user_management.users',
-            'user_management.user'
+            'user_management.user', current_app.login_manager.login_view
         ]
 
 
diff --git a/web/pgadmin/tools/user_management/static/js/user_management.js b/web/pgadmin/tools/user_management/static/js/user_management.js
index d51d6b4..a55594b 100644
--- a/web/pgadmin/tools/user_management/static/js/user_management.js
+++ b/web/pgadmin/tools/user_management/static/js/user_management.js
@@ -122,6 +122,95 @@ define([
         alertify.ChangePassword(title, url).resizeTo('75%','70%');
       },
 
+      is_pga_login_required(xhr) {
+        return xhr.status == 401 && xhr.responseJSON &&
+                xhr.responseJSON.info &&
+                xhr.responseJSON.info == 'PGADMIN_LOGIN_REQUIRED'
+      },
+
+      // Callback to draw pgAdmin4 login dialog.
+      pga_login: function(url) {
+        var title = gettext('pgAdmin 4 login');
+        url = url || url_for('security.login');
+        if(!alertify.PgaLogin) {
+          alertify.dialog('PgaLogin' ,function factory() {
+            return {
+              main: function(title, url) {
+                this.set({
+                  'title': title,
+                  'url': url
+                });
+              },
+              build: function() {
+                alertify.pgDialogBuild.apply(this)
+              },
+              settings:{
+                  url: undefined
+              },
+              setup:function() {
+                return {
+                  buttons: [{
+                    text: gettext('Close'), key: 27,
+                    className: 'btn btn-danger 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: true,
+                    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.PgaLogin().destroy();
+                  }));
+                }
+              },
+              prepare: function() {
+                // create the iframe element
+                var self = this,
+                    iframe = document.createElement('iframe'),
+                    url = this.setting('url');
+
+                iframe.onload = function() {
+                  var doc = this.contentDocument || this.contentWindow.document;
+                  if (doc.location.href.indexOf(url) == -1) {
+                    // login successful.
+
+                    this.contentWindow.stop();
+                    this.onload = null;
+
+                    // close the dialog.
+                    self.close();
+                    pgBrowser.Events.trigger('pgadmin:user:logged-in');
+                  }
+                };
+
+                iframe.frameBorder = "no";
+                iframe.width = "100%";
+                iframe.height = "100%";
+                iframe.src = url;
+                // add it to the dialog
+                self.elements.content.appendChild(iframe);
+              }
+            };
+          });
+        }
+
+        alertify.PgaLogin(title, url).resizeTo('75%','70%');
+      },
+
       // Callback to draw User Management Dialog.
       show_users: function(action, item, params) {
         if (!userInfo['is_admin']) return;
diff --git a/web/pgadmin/utils/exception.py b/web/pgadmin/utils/exception.py
index dab0d09..04a7d4b 100644
--- a/web/pgadmin/utils/exception.py
+++ b/web/pgadmin/utils/exception.py
@@ -28,7 +28,7 @@ class ConnectionLost(HTTPException):
 
     @property
     def name(self):
-        return HTTP_STATUS_CODES.get(505, 'Service Unavailable')
+        return HTTP_STATUS_CODES.get(503, 'Service Unavailable')
 
     def get_response(self, environ=None):
         return service_unavailable(
diff --git a/web/pgadmin/utils/session.py b/web/pgadmin/utils/session.py
index 8f2ae61..84e7471 100644
--- a/web/pgadmin/utils/session.py
+++ b/web/pgadmin/utils/session.py
@@ -24,6 +24,9 @@ import random
 import string
 import time
 from uuid import uuid4
+from flask import current_app, request, flash, redirect
+from flask_login import login_url
+from pgadmin.utils.ajax import make_json_response
 
 try:
     from cPickle import dump, load
@@ -298,3 +301,32 @@ def create_session_interface(app, skip_paths=[]):
             1000
         ), skip_paths,
         datetime.timedelta(days=1))
+
+
+def pga_unauthorised():
+
+    lm = current_app.login_manager
+    login_message = None
+
+    if lm.login_message:
+        if lm.localize_callback is not None:
+            login_message = lm.localize_callback(lm.login_message)
+        else:
+            login_message = lm.login_message
+
+    if not lm.login_view or request.is_xhr:
+        # Only 401 is not enough to distinguish pgAdmin login is required.
+        # There are other cases when we return 401. For eg. wrong password
+        # supplied while connecting to server.
+        # So send additional 'info' message.
+        return make_json_response(
+            status=401,
+            success=0,
+            errormsg=login_message,
+            info='PGADMIN_LOGIN_REQUIRED'
+        )
+
+    if login_message:
+        flash(login_message, category=lm.login_message_category)
+
+    return redirect(login_url(lm.login_view, request.url))

Reply via email to