-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Add dynamic retrieval for client password #1926
Conversation
354b19f
to
c3aa08d
Compare
Adds option to specify a function for a client password. When the client is connected, if the value of password is a function then it is invoked to get the password to use for that connection. The function must return either a string or a Promise that resolves to a string. If the function throws or rejects with an error then it will be bubbled up to the client.
Add testAsync() helper function to Suite to simplify running tests that return a Promise. The test action is executed and if a syncronous error is thrown then it is immediately considered failed. If the Promise resolves successfully then the test is considered successful. If the Promise rejects with an Error then the test is considered failed.
c3aa08d
to
2d7f9fd
Compare
I force pushed an update to this that changes:
Also added some tests for retrieving a sync, async, and errant passwords via functions. For the tests I added a new helper |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is fantastic. 20 line code change, 150 lines of tests. 😍
lib/client.js
Outdated
if (self.password !== null) { | ||
if (typeof(self.password) === 'function') { | ||
try { | ||
self._Promise.resolve(self.password()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ohhh nice use on supporting BYOP - not sure how popular BYOP is now that promises have shipped natively in node for years, but still nice for backwards compatibility 👌
lib/client.js
Outdated
}) | ||
} catch (err) { | ||
con.emit('error', err) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wow - impressive error handling
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apparently not as impressive as @charmander ;-)
@@ -72,6 +72,19 @@ class Suite { | |||
const test = new Test(name, cb) | |||
this._queue.push(test) | |||
} | |||
|
|||
testAsync (name, action) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i apologize the tests here aren't written w/ a modern node testing framework. There's this cost-benefit thing I keep running into where it's like "Should I re-write all these tests into jest/mocha/etc? They already work and I know they work...but maybe rewriting will introduce some breakage." The original tests in the repo were written before mocha or jest existed so it's kinda like...well....if it ain't broke...otoh I feel like it's probably more confusing to contribute to. I also at the time, coming from ruby, thought i'd be 'clever' and attach a bunch of stuff to the global namespace like assert and other things. That was a mistake. :(
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No worries. I've thought about cleaning up some of them more than once and it's always the same conclusion. Maybe having a separate harness for things going forward as it's definitely easier to write async tests with an async harness. Doesn't even have to be be full on mocha/jest/whatever ... just having something to call out to with async actions should be enough.
I like how you can easily run any one of the tests in this project via "node path/to/test.js".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some formatting consistency options.
const helper = require('./../test-helper') | ||
const suite = new helper.Suite() | ||
const pg = require('../../../lib/index'); | ||
const Client = pg.Client; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const Client = pg.Client; | |
const Client = pg.Client |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(This one still exists)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah i need to turn on linting on the test folder
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would also help if we turned back on the semi rule. This PR passed "make lint" as the semi rule got removed when the eslint config was last cleaned up (by me...).
I pushed some updates to address the comments (thanks @charmander!). As part of this I also cleaned up the error handling in client.js to use the same style of I left the error handling for that piece on L131 of client.js as a separate FYI, taking a peek at the callers of that |
const helper = require('./../test-helper') | ||
const suite = new helper.Suite() | ||
const pg = require('../../../lib/index'); | ||
const Client = pg.Client; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(This one still exists)
No clue why it failed on node v12 in the PR build but passed for me (https://travis-ci.org/sehrope/node-postgres/builds/561008527). There's no specific error in the travis logs either. I think there was some transient error building Postgres. I'm going to push a dummy commit to see if it happens again. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice :)
Btw, checked and tested this change in Prod with RDS Postgres 11.4, works fine! When you plan merge this into master? |
Right now! & I'll document it and release a new minor version. 😄 |
Published |
You missed the types... |
@benkeil Yes the typings are maintained externally in DefinitelyTyped (i.e. |
Naive question: why not migrate the project to typescript? |
I think it will eventually and some of the internal components have already been migrated to Typescript (e.g. see the packet parser). |
yeah i'm very slowly working on that |
This PR and the change are confusing. I thought at first this would actually allow dynamic passwords support, but all it does - makes only one call in the beginning. After that, if the password changes, the callback is never called again. So it is not very useful then. I had to use a connection object, and then do |
Feature introduced in brianc/node-postgres#1926.
PR to add support for dynamic password retrieval. There was already something quite similar to this to support reading passwords from a PGPASS file. This PR expands that section a bit to support invoking an arbitrary function.
Rather than supporting a callback parameter, this PR allows for either a synchronous function that returns a string or one that returns a Promise that resolves to a string. As there's Promise support on every supported runtime I figure it's a better choice for anything new being added.
Here's some examples of how to use it:
This PR does not have any new tests yet, I just tested it with some local examples. If the concept itself seems workable then should be easy to add a few that use a function and check for its side effects. Let me know.