diff --git a/packages/pg/Makefile b/packages/pg/Makefile index 5575acfd8..a66c107ae 100644 --- a/packages/pg/Makefile +++ b/packages/pg/Makefile @@ -27,6 +27,7 @@ bench: @find benchmark -name "*-bench.js" | $(node-command) test-unit: + @chmod 600 test/unit/client/pgpass.file @find test/unit -name "*-tests.js" | $(node-command) test-connection: diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js index 459439037..0168ce637 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -249,7 +249,7 @@ class Client extends EventEmitter { if (typeof this.password === 'function') { this._Promise .resolve() - .then(() => this.password()) + .then(() => this.password(this.connectionParameters)) .then((pass) => { if (pass !== undefined) { if (typeof pass !== 'string') { diff --git a/packages/pg/test/unit/client/password-callback-tests.js b/packages/pg/test/unit/client/password-callback-tests.js new file mode 100644 index 000000000..bf1885e94 --- /dev/null +++ b/packages/pg/test/unit/client/password-callback-tests.js @@ -0,0 +1,70 @@ +const helper = require('./test-helper') +const assert = require('assert') +const suite = new helper.Suite() +const pgpass = require('pgpass') + +class Wait { + constructor() { + this.promise = new Promise((resolve) => { + this.resolve = resolve + }) + } + + until() { + return this.promise + } + + done(time) { + if (time) { + setTimeout(this.resolve.bind(this), time) + } else { + this.resolve() + } + } +} + +suite.test('password callback is called with conenction params', async function () { + const wait = new Wait() + const client = helper.client({ + user: 'foo', + database: 'bar', + host: 'baz', + password: async (params) => { + assert.equal(params.user, 'foo') + assert.equal(params.database, 'bar') + assert.equal(params.host, 'baz') + wait.done(10) + return 'password' + }, + }) + client.connection.emit('authenticationCleartextPassword') + await wait.until() + assert.equal(client.user, 'foo') + assert.equal(client.database, 'bar') + assert.equal(client.host, 'baz') + assert.equal(client.connectionParameters.password, 'password') +}) + +suite.test('cleartext password auth does not crash with null password using pg-pass', async function () { + process.env.PGPASSFILE = `${__dirname}/pgpass.file` + // set this to undefined so pgpass will use the file + delete process.env.PGPASSWORD + const wait = new Wait() + const client = helper.client({ + host: 'foo', + port: 5432, + database: 'bar', + user: 'baz', + password: (params) => { + return new Promise((resolve) => { + pgpass(params, (pass) => { + wait.done(10) + resolve(pass) + }) + }) + }, + }) + client.connection.emit('authenticationCleartextPassword') + await wait.until() + assert.equal(client.password, 'quz') +}) diff --git a/packages/pg/test/unit/client/test-helper.js b/packages/pg/test/unit/client/test-helper.js index 3e8f75c31..4a3fa9687 100644 --- a/packages/pg/test/unit/client/test-helper.js +++ b/packages/pg/test/unit/client/test-helper.js @@ -3,7 +3,7 @@ const helper = require('../test-helper') const Connection = require('../../../lib/connection') const { Client } = helper -const makeClient = function () { +const makeClient = function (config) { const connection = new Connection({ stream: 'no' }) connection.startup = function () {} connection.connect = function () {} @@ -11,7 +11,7 @@ const makeClient = function () { this.queries.push(text) } connection.queries = [] - const client = new Client({ connection: connection }) + const client = new Client({ connection: connection, ...config }) client.connect() client.connection.emit('connect') return client