diff --git a/bin/password.js b/bin/password.js index d092fd3de..9bb4cffb5 100755 --- a/bin/password.js +++ b/bin/password.js @@ -1,30 +1,59 @@ #!/usr/bin/env node /* eslint-disable no-console */ -const Redis = require('ioredis').Cluster; +const Redis = require('ioredis'); const assert = require('assert'); const conf = require('../lib/config'); +const { updatePassword } = require('../lib/actions/updatePassword'); const config = conf.get('/', { env: process.env.NODE_ENV }); -const redisConfig = config.redis; -const { updatePassword } = require('../lib/actions/updatePassword'); -const username = process.argv[2]; -const password = process.argv[3]; -assert(username, 'must provide id as argv[2]'); -assert(password, 'must provide password of token as argv[3]'); +const initRedis = (redisConfig) => { + const opts = { + lazyConnect: true, + ...redisConfig.options, + }; + if (redisConfig.sentinels) { + opts.name = redisConfig.name; + opts.sentinels = redisConfig.sentinels; + return new Redis(opts); + } -const redis = new Redis(redisConfig.hosts, ({ ...redisConfig.options, lazyConnect: true })); + return new Redis.Cluster(redisConfig.hosts, opts); +}; + +const redis = initRedis(config.redis); // connection options -redis - .connect() - .bind({ redis }) - .return([username, password]) - .spread(updatePassword) - .then(() => { - console.info('\nSet password for %s to "%s"\n', username, password); - return redis.disconnect(); - }) - .catch((err) => setImmediate(() => { throw err; })); +const main = async (username, password) => { + assert(username, 'must provide user id'); + assert(password, 'must provide password'); + + try { + await redis.connect(); + await updatePassword({ redis }, username, password); + } catch (err) { + setImmediate(() => { + throw err; + }); + } finally { + await redis.disconnect(); + } +}; + +if (module.parent === null) { + const username = process.argv[2]; + const password = process.argv[3]; + assert(username, 'must provide id as argv[2]'); + assert(password, 'must provide password of token as argv[3]'); + + // eslint-disable-next-line promise/catch-or-return + main(username, password) + .then(() => { + console.info('\nSet password for %s to "%s"\n', username, password); + return null; + }); +} + +exports.main = main; diff --git a/test/suites/bin/password.js b/test/suites/bin/password.js new file mode 100644 index 000000000..3467abba0 --- /dev/null +++ b/test/suites/bin/password.js @@ -0,0 +1,29 @@ +const assert = require('assert'); +const path = require('path'); +const exec = require('../../helpers/exec'); + +describe('binary: password', function suite() { + const binaryPath = path.resolve(__dirname, '../../../bin/password.js'); + const username = 'test@test.me'; + const newPassword = 'trickynewpassword'; + // eslint-disable-next-line no-undef + const checkAuth = globalAuthUser(username, newPassword); + + before(global.startService); + before(global.globalRegisterUser(username, { + inactive: false, + })); + // eslint-disable-next-line no-undef + before(globalAuthUser(username)); + after(global.clearRedis); + + it('allows updating password from the command-line', async function test() { + await exec(`${binaryPath} ${this.userId} ${newPassword}`); + // Verify trying to log in with the new password + // unset jwt token just in case + this.jwt = null; + // eslint-disable-next-line no-undef + await checkAuth.call(this); + assert(this.jwt); + }); +});