Skip to content
Merged
65 changes: 47 additions & 18 deletions bin/password.js
Original file line number Diff line number Diff line change
@@ -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;
29 changes: 29 additions & 0 deletions test/suites/bin/password.js
Original file line number Diff line number Diff line change
@@ -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);
});
});