From 8380fe08a025bd41b242c545f7c1b4f333274cbc Mon Sep 17 00:00:00 2001 From: Hasan Ramezani Date: Wed, 24 Feb 2021 17:16:45 +0100 Subject: [PATCH] Fixed #32456 -- Added dbshell support for specifying a password file on PostgreSQL. --- django/db/backends/postgresql/client.py | 3 +++ docs/ref/databases.txt | 21 +++++++++++++------ docs/releases/4.0.txt | 2 ++ tests/dbshell/test_postgresql.py | 28 +++++++++++++++++++++++++ 4 files changed, 48 insertions(+), 6 deletions(-) diff --git a/django/db/backends/postgresql/client.py b/django/db/backends/postgresql/client.py index 873af8cc14..3effab65a8 100644 --- a/django/db/backends/postgresql/client.py +++ b/django/db/backends/postgresql/client.py @@ -16,6 +16,7 @@ class DatabaseClient(BaseDatabaseClient): dbname = settings_dict.get('NAME') user = settings_dict.get('USER') passwd = settings_dict.get('PASSWORD') + passfile = options.get('passfile') service = options.get('service') sslmode = options.get('sslmode') sslrootcert = options.get('sslrootcert') @@ -48,6 +49,8 @@ class DatabaseClient(BaseDatabaseClient): env['PGSSLCERT'] = str(sslcert) if sslkey: env['PGSSLKEY'] = str(sslkey) + if passfile: + env['PGPASSFILE'] = str(passfile) return args, env def runshell(self, parameters): diff --git a/docs/ref/databases.txt b/docs/ref/databases.txt index 67d6d21eb6..9f9df2fcd3 100644 --- a/docs/ref/databases.txt +++ b/docs/ref/databases.txt @@ -115,9 +115,9 @@ PostgreSQL connection settings See :setting:`HOST` for details. -To connect using a service name from the `connection service file`_, you must -specify it in the :setting:`OPTIONS` part of your database configuration in -:setting:`DATABASES`: +To connect using a service name from the `connection service file`_ and a +password from the `password file`_, you must specify them in the +:setting:`OPTIONS` part of your database configuration in :setting:`DATABASES`: .. code-block:: python :caption: settings.py @@ -125,7 +125,10 @@ specify it in the :setting:`OPTIONS` part of your database configuration in DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', - 'OPTIONS': {'service': 'my_service'}, + 'OPTIONS': { + 'service': 'my_service', + 'passfile': '.my_pgpass', + }, } } @@ -136,14 +139,20 @@ specify it in the :setting:`OPTIONS` part of your database configuration in host=localhost user=USER dbname=NAME - password=PASSWORD port=5432 +.. code-block:: text + :caption: .my_pgpass + + localhost:5432:NAME:USER:PASSWORD + .. _connection service file: https://www.postgresql.org/docs/current/libpq-pgservice.html +.. _password file: https://www.postgresql.org/docs/current/libpq-pgpass.html .. versionchanged:: 4.0 - Support for connecting by a service name was added. + Support for connecting by a service name, and specifying a password file + was added. Optimizing PostgreSQL's configuration ------------------------------------- diff --git a/docs/releases/4.0.txt b/docs/releases/4.0.txt index 50afdb56f2..7ea518cbc9 100644 --- a/docs/releases/4.0.txt +++ b/docs/releases/4.0.txt @@ -206,6 +206,8 @@ Management Commands * The :djadmin:`runserver` management command now supports the :option:`--skip-checks` option. +* On PostgreSQL, :djadmin:`dbshell` now supports specifying a password file. + Migrations ~~~~~~~~~~ diff --git a/tests/dbshell/test_postgresql.py b/tests/dbshell/test_postgresql.py index 3345035a24..a96acac6f1 100644 --- a/tests/dbshell/test_postgresql.py +++ b/tests/dbshell/test_postgresql.py @@ -73,6 +73,34 @@ class PostgreSqlDbshellCommandTestCase(SimpleTestCase): (['psql'], {'PGSERVICE': 'django_test'}), ) + def test_passfile(self): + self.assertEqual( + self.settings_to_cmd_args_env({ + 'NAME': 'dbname', + 'USER': 'someuser', + 'HOST': 'somehost', + 'PORT': '444', + 'OPTIONS': { + 'passfile': '~/.custompgpass', + }, + }), + ( + ['psql', '-U', 'someuser', '-h', 'somehost', '-p', '444', 'dbname'], + {'PGPASSFILE': '~/.custompgpass'}, + ), + ) + self.assertEqual( + self.settings_to_cmd_args_env({ + 'OPTIONS': { + 'service': 'django_test', + 'passfile': '~/.custompgpass', + }, + }), + ( + ['psql'], {'PGSERVICE': 'django_test', 'PGPASSFILE': '~/.custompgpass'}, + ), + ) + def test_column(self): self.assertEqual( self.settings_to_cmd_args_env({