Hi,

PFA patch to enable/disable the passfile filed on Create/Edit Server dialog
based on supported libpq version.
RM#2768

*Issue:*
passfile connection parameter is only available with latest version of
libpq which is libpq10+
Ref: Link <https://www.postgresql.org/docs/current/static/libpq-pgpass.html>

Please review.

--
Regards,
Murtuza Zabuawala
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
diff --git a/docs/en_US/server_dialog.rst b/docs/en_US/server_dialog.rst
index a82d462..a1a5193 100644
--- a/docs/en_US/server_dialog.rst
+++ b/docs/en_US/server_dialog.rst
@@ -88,9 +88,11 @@ Use the fields in the *Advanced* tab to configure a 
connection:
 * The DB restriction field allows you to enter an SQL restriction that will be 
used against the pg_database table to
   limit the databases that you see. For example, you might enter: *live_db 
test_db* so that only live_db and test_db are
   shown in the pgAdmin browser. Separate entries with a comma or tab as you 
type.
-* Specify the password file which allow user to login without providing 
password, see Section 31 of the Postgres documentation:
+* Specify the password file which allow user to login without providing 
password, see Section 33.15 of the Postgres documentation:
 
-   https://www.postgresql.org/docs/9.6/static/libpq-pgpass.html
+   https://www.postgresql.org/docs/current/static/libpq-pgpass.html
+
+*NOTE:* password file options is only supported with libpq 10+.
 
 * Click the *Save* button to save work.
 * Click the *Cancel* button to exit without saving work.
diff --git a/web/pgadmin/browser/__init__.py b/web/pgadmin/browser/__init__.py
index e74664f..7778805 100644
--- a/web/pgadmin/browser/__init__.py
+++ b/web/pgadmin/browser/__init__.py
@@ -555,6 +555,15 @@ def utils():
     insert_pair_brackets_perf = prefs.preference('insert_pair_brackets')
     insert_pair_brackets = insert_pair_brackets_perf.get()
 
+    # Try to fetch current libpq version from the driver
+    try:
+        from config import PG_DEFAULT_DRIVER
+        from pgadmin.utils.driver import get_driver
+        driver = get_driver(PG_DEFAULT_DRIVER)
+        pg_libpq_version = driver.libpq_version()
+    except:
+        pg_libpq_version = 0
+
     for submodule in current_blueprint.submodules:
         snippets.extend(submodule.jssnippets)
     return make_response(
@@ -569,7 +578,8 @@ def utils():
             editor_wrap_code=editor_wrap_code,
             editor_brace_matching=brace_matching,
             editor_insert_pair_brackets=insert_pair_brackets,
-            app_name=config.APP_NAME
+            app_name=config.APP_NAME,
+            pg_libpq_version=pg_libpq_version
         ),
         200, {'Content-Type': 'application/x-javascript'})
 
diff --git a/web/pgadmin/browser/server_groups/servers/static/js/server.js 
b/web/pgadmin/browser/server_groups/servers/static/js/server.js
index 02324e4..45c0356 100644
--- a/web/pgadmin/browser/server_groups/servers/static/js/server.js
+++ b/web/pgadmin/browser/server_groups/servers/static/js/server.js
@@ -779,7 +779,7 @@ define('pgadmin.node.server', [
         },{
           id: 'passfile', label: gettext('Password File'), type: 'text',
           group: gettext('Advanced'), mode: ['edit', 'create'],
-          disabled: 'isConnected', control: Backform.FileControl,
+          disabled: 'isConnectedWithValidLib', control: Backform.FileControl,
           dialog_type: 'select_file', supp_types: ['*']
         },{
           id: 'passfile', label: gettext('Password File'), type: 'text',
@@ -888,6 +888,14 @@ define('pgadmin.node.server', [
             return true;
           }
           return _.indexOf(SSL_MODES, ssl_mode) == -1;
+        },
+        isConnectedWithValidLib: function(model) {
+          if(model.get('connected')) {
+            return true;
+          }
+          // older version of libpq do not support 'passfile' parameter in
+          // connect method, valid libpq must have version >= 100000
+          return pgBrowser.utils.pg_libpq_version < 100000;
         }
       }),
       connection_lost: function(i, resp) {
diff --git a/web/pgadmin/browser/templates/browser/js/utils.js 
b/web/pgadmin/browser/templates/browser/js/utils.js
index 4b6a737..fc475dd 100644
--- a/web/pgadmin/browser/templates/browser/js/utils.js
+++ b/web/pgadmin/browser/templates/browser/js/utils.js
@@ -24,6 +24,7 @@ define('pgadmin.browser.utils',
     insertPairBrackets: '{{ editor_insert_pair_brackets }}' == 'True',
     braceMatching: '{{ editor_brace_matching }}' == 'True',
     app_name: '{{ app_name }}',
+    pg_libpq_version: {{pg_libpq_version|e}},
 
     counter: {total: 0, loaded: 0},
     registerScripts: function (ctx) {
diff --git a/web/pgadmin/utils/driver/abstract.py 
b/web/pgadmin/utils/driver/abstract.py
index 7db3e37..2f323f0 100644
--- a/web/pgadmin/utils/driver/abstract.py
+++ b/web/pgadmin/utils/driver/abstract.py
@@ -32,6 +32,9 @@ class BaseDriver(object):
     * Version (string):
         Current version string for the database server
 
+    * libpq_version (string):
+        Current version string for the used libpq library
+
     Abstract Methods:
     -------- -------
     * get_connection(*args, **kwargs)
@@ -51,6 +54,10 @@ class BaseDriver(object):
     def Version(cls):
         pass
 
+    @abstractproperty
+    def libpq_version(cls):
+        pass
+
     @abstractmethod
     def get_connection(self, *args, **kwargs):
         pass
diff --git a/web/pgadmin/utils/driver/psycopg2/__init__.py 
b/web/pgadmin/utils/driver/psycopg2/__init__.py
index 527e175..e40a210 100644
--- a/web/pgadmin/utils/driver/psycopg2/__init__.py
+++ b/web/pgadmin/utils/driver/psycopg2/__init__.py
@@ -2043,6 +2043,18 @@ class Driver(BaseDriver):
             "Driver Version information for psycopg2 is not available!"
         )
 
+    def libpq_version(cls):
+        """
+        Returns the loaded libpq version
+        """
+        version = getattr(psycopg2, '__libpq_version__', None)
+        if version:
+            return version
+
+        raise Exception(
+            "libpq version information is not available!"
+        )
+
     def get_connection(
             self, sid, database=None, conn_id=None, auto_reconnect=True
     ):

Reply via email to