Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions bin/assign-affiliate.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ const { argv } = require('yargs')
USERS_ALIAS_TO_ID,
} = require('../lib/constants');

const handleRedisPipelineError = require('../lib/utils/pipelineError');
const handleRedisPipelineError = require('../lib/utils/pipeline-error');
const redisKey = require('../lib/utils/key');
const redisConfig = conf.get('/redis', { env: process.env.NODE_ENV });
const audience = conf.get('/jwt/defaultAudience', { env: process.env.NODE_ENV });
const opts = Object.assign({}, redisConfig.options, { lazyConnect: true });
const opts = { ...redisConfig.options, lazyConnect: true };
const redis = new Redis(redisConfig.hosts, opts);
const metaKey = redisKey(argv.id, USERS_METADATA, audience);

Expand Down
12 changes: 6 additions & 6 deletions bin/batch-register.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@ const { prefix } = config.router.routes;
*/
function registerUsers(users) {
return AMQPTransport
.connect(amqpConfig)
.then(amqp => (
.connect({ ...amqpConfig, debug: false })
.then((amqp) => (
Promise
.map(users, user => (
.map(users, (user) => (
amqp.publishAndWait(`${prefix}.register`, user, { timeout: 5000 })
))
.finally(() => amqp.close())
Expand All @@ -37,7 +37,7 @@ function registerUsers(users) {

// read data from stdin
getStdin()
.then(input => JSON.parse(input))
.then((input) => JSON.parse(input))
.then((info) => {
assert.equal(typeof info.common, 'object');
assert.ok(Array.isArray(info.users));
Expand Down Expand Up @@ -66,8 +66,8 @@ getStdin()
});
})
.then(registerUsers)
.then(users => (
users.forEach(user => (
.then((users) => (
users.forEach((user) => (
console.info('[%s] - %s', user.username, user.password)
))
))
Expand Down
4 changes: 2 additions & 2 deletions bin/bearer.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
// quickly generates bearer for a passed username
/* eslint-disable no-console */

const conf = require('../lib/config');
const AMQPTransport = require('@microfleet/transport-amqp');
const assert = require('assert');
const conf = require('../lib/config');

const config = conf.get('/', { env: process.env.NODE_ENV });
const amqpConfig = config.amqp.transport;
Expand All @@ -24,7 +24,7 @@ function approveSchool(amqp) {
// connection options
AMQPTransport
.connect(amqpConfig)
.then(amqp => approveSchool(amqp).tap(() => amqp.close()))
.then((amqp) => approveSchool(amqp).tap(() => amqp.close()))
.then((token) => {
console.info('Created token for %s with name %s:\n\n%s\n\n', username, name, token);
return process.exit();
Expand Down
8 changes: 5 additions & 3 deletions bin/dump.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,9 @@ if (argv.criteria) iterator.criteria = argv.criteria;
/**
* Get transport
*/
const getTransport = () => AMQPTransport.connect(amqpConfig).disposer(amqp => amqp.close());
const getTransport = () => AMQPTransport
.connect({ ...amqpConfig, debug: false })
.disposer((amqp) => amqp.close());

/**
* Output stream
Expand Down Expand Up @@ -140,7 +142,7 @@ const writeUserToOutput = (user) => {
/**
* List users
*/
const listUsers = amqp => (
const listUsers = (amqp) => (
amqp
.publishAndWait(route, iterator, { timeout: 5000 })
.then((data) => {
Expand All @@ -158,4 +160,4 @@ const listUsers = amqp => (

Promise
.using(getTransport(), listUsers)
.catch(err => setImmediate(() => { throw err; }));
.catch((err) => setImmediate(() => { throw err; }));
4 changes: 2 additions & 2 deletions bin/password.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ assert(username, 'must provide id as argv[2]');
assert(password, 'must provide password of token as argv[3]');


const redis = new Redis(redisConfig.hosts, Object.assign({}, redisConfig.options, { lazyConnect: true }));
const redis = new Redis(redisConfig.hosts, ({ ...redisConfig.options, lazyConnect: true }));

// connection options
redis
Expand All @@ -27,4 +27,4 @@ redis
console.info('\nSet password for %s to "%s"\n', username, password);
return redis.disconnect();
})
.catch(err => setImmediate(() => { throw err; }));
.catch((err) => setImmediate(() => { throw err; }));
34 changes: 17 additions & 17 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,19 @@
"@hapi/bell": "^11.1.0",
"@hapi/hapi": "^18.4.0",
"@hapi/vision": "^5.5.4",
"@microfleet/core": "^15.3.1",
"@microfleet/transport-amqp": "^15.0.0",
"@microfleet/core": "^15.5.1",
"@microfleet/transport-amqp": "^15.1.2",
"@microfleet/validation": "^8.1.2",
"bluebird": "^3.7.1",
"bytes": "^3.0.0",
"common-errors": "^1.0.5",
"csv-write-stream": "^2.0.0",
"disposable-email-domains": "^1.0.49",
"disposable-email-domains": "^1.0.50",
"dlock": "^11.0.0",
"flake-idgen": "^1.1.0",
"get-stdin": "^7.0.0",
"get-value": "^3.0.1",
"handlebars": "^4.5.1",
"handlebars": "^4.5.3",
"ioredis": "^4.14.1",
"is": "^3.3.0",
"jsonwebtoken": "^8.5.1",
Expand All @@ -56,33 +56,33 @@
"ms-mailer-templates": "^1.14.1",
"ms-token": "^3.1.0",
"otplib": "^11.0.1",
"password-generator": "^2.2.0",
"password-generator": "^2.2.3",
"prom-client": "^11.5.3",
"qs": "^6.9.0",
"qs": "^6.9.1",
"redis-filtered-sort": "^2.3.0",
"request": "^2.88.0",
"request-promise": "^4.2.4",
"request-promise": "^4.2.5",
"scrypt-kdf": "^2.0.1",
"serialize-error": "^5.0.0",
"serialize-javascript": "^2.1.0",
"stdout-stream": "^1.4.1",
"tough-cookie": "^3.0.0",
"uuid": "^3.3.3",
"yargs": "^14.2.0",
"yargs": "^15.0.2",
"zxcvbn": "^4.4.2"
},
"devDependencies": {
"@babel/cli": "^7.6.4",
"@babel/core": "^7.6.4",
"@babel/plugin-proposal-class-properties": "^7.5.5",
"@babel/cli": "^7.7.0",
"@babel/core": "^7.7.2",
"@babel/plugin-proposal-class-properties": "^7.7.0",
"@babel/plugin-proposal-object-rest-spread": "^7.6.2",
"@babel/plugin-transform-strict-mode": "^7.2.0",
"@babel/register": "^7.6.2",
"@makeomatic/deploy": "^9.3.2",
"@babel/register": "^7.7.0",
"@makeomatic/deploy": "^9.5.0",
"@semantic-release/changelog": "^3.0.5",
"@semantic-release/exec": "^3.3.8",
"@semantic-release/git": "^7.0.17",
"apidoc": "^0.17.7",
"@semantic-release/git": "^7.0.18",
"apidoc": "^0.18.0",
"apidoc-plugin-schema": "^0.1.8",
"babel-eslint": "^10.0.3",
"babel-plugin-istanbul": "^5.2.0",
Expand All @@ -95,9 +95,9 @@
"eslint-plugin-import": "^2.18.2",
"eslint-plugin-mocha": "^6.2.1",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-unicorn": "^12.1.0",
"eslint-plugin-unicorn": "^13.0.0",
"faker": "^4.1.0",
"glob": "^7.1.5",
"glob": "^7.1.6",
"json": "^9.0.6",
"md5": "^2.2.1",
"mocha": "^6.2.2",
Expand Down
72 changes: 43 additions & 29 deletions src/actions/activate.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
const Errors = require('common-errors');
const { ActionTransport } = require('@microfleet/core');
const { HttpStatusError } = require('common-errors');
const Promise = require('bluebird');
const redisKey = require('../utils/key.js');
const jwt = require('../utils/jwt.js');
const { getInternalData } = require('../utils/userData');
const getMetadata = require('../utils/get-metadata');
const handlePipeline = require('../utils/pipeline-error.js');
const handlePipeline = require('../utils/pipeline-error');
const setMetadata = require('../utils/update-metadata');
const {
USERS_INDEX,
USERS_DATA,
Expand All @@ -16,12 +18,13 @@ const {
USERS_REFERRAL_FIELD,
USERS_USERNAME_FIELD,
USERS_ACTION_ACTIVATE,
USERS_ACTIVATED_FIELD,
} = require('../constants.js');

// cache error
const Forbidden = new Errors.HttpStatusError(403, 'invalid token');
const Inactive = new Errors.HttpStatusError(412, 'expired token, please request a new email');
const Active = new Errors.HttpStatusError(409, 'account is already active, please use sign in form');
const Forbidden = new HttpStatusError(403, 'invalid token');
const Inactive = new HttpStatusError(412, 'expired token, please request a new email');
const Active = new HttpStatusError(409, 'account is already active, please use sign in form');

/**
* Helper to determine if something is true
Expand Down Expand Up @@ -103,23 +106,37 @@ function verifyRequest() {
return Promise.resolve(username);
}

throw new Errors.HttpStatusError(400, 'invalid params');
throw new HttpStatusError(400, 'invalid params');
}

/**
* Activates account after it was verified
* @param {Object} data internal user data
* @return {Promise}
*/
function activateAccount(data, metadata) {
async function activateAccount(data, metadata) {
const userId = data[USERS_ID_FIELD];
const alias = data[USERS_ALIAS_FIELD];
const referral = metadata[USERS_REFERRAL_FIELD];
const userKey = redisKey(userId, USERS_DATA);
const { defaultAudience, service } = this;
const { redis } = service;

// if this goes through, but other async calls fail its ok to repeat that
// adds activation field
await setMetadata.call(service, {
userId,
audience: defaultAudience,
metadata: {
$set: {
[USERS_ACTIVATED_FIELD]: Date.now(),
},
},
});

// WARNING: `persist` is very important, otherwise we will lose user's information in 30 days
// set to active & persist
const pipeline = this.redis
const pipeline = redis
.pipeline()
.hget(userKey, USERS_ACTIVE_FLAG)
.hset(userKey, USERS_ACTIVE_FLAG, 'true')
Expand All @@ -134,15 +151,13 @@ function activateAccount(data, metadata) {
pipeline.sadd(`${USERS_REFERRAL_INDEX}:${referral}`, userId);
}

return pipeline
.exec()
.then(handlePipeline)
.spread((isActive) => {
if (isActive === 'true') {
throw new Errors.HttpStatusError(417, `Account ${userId} was already activated`);
}
})
.return(userId);
const [isActive] = handlePipeline(await pipeline.exec());

if (isActive === 'true') {
throw new HttpStatusError(417, `Account ${userId} was already activated`);
}

return userId;
}

/**
Expand Down Expand Up @@ -173,41 +188,40 @@ function hook(userId) {
* @apiParam (Payload) {String} [audience] - additional metadata will be pushed there from custom hooks
*
*/
function activateAction({ params }) {
async function activateAction({ log, params }) {
// TODO: add security logs
// var remoteip = request.params.remoteip;
const { token, username } = params;
const { log, config } = this;
const audience = params.audience || config.defaultAudience;
const { config } = this;
const { jwt: { defaultAudience } } = config;
const audience = params.audience || defaultAudience;

log.debug('incoming request params %j', params);
log.debug({ params }, 'incoming request params');

// basic context
const context = {
audience,
defaultAudience,
token,
username,
service: this,
erase: config.token.erase,
};

return Promise
const userId = await Promise
.bind(context)
.then(verifyRequest)
.bind(this)
.then((resolvedUsername) => getInternalData.call(this, resolvedUsername))
.then((internalData) => Promise.join(
internalData,
getMetadata.call(this, internalData[USERS_ID_FIELD], audience).get(audience)
))
.spread(activateAccount)
.bind(context)
.tap(hook)
.bind(this)
.then((userId) => [userId, audience])
.spread(jwt.login);
.tap(hook);

return jwt.login.call(this, userId, audience);
}

activateAction.transports = [require('@microfleet/core').ActionTransport.amqp];
activateAction.transports = [ActionTransport.amqp];

module.exports = activateAction;
19 changes: 13 additions & 6 deletions src/actions/register.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ const {
USERS_USERNAME_FIELD,
USERS_PASSWORD_FIELD,
USERS_REFERRAL_FIELD,
USERS_ACTIVATED_FIELD,
lockAlias,
lockRegister,
USERS_ACTION_INVITE,
Expand Down Expand Up @@ -211,17 +212,23 @@ async function performRegistration({ service, params }) {
pipeline.expire(userDataKey, config.deleteInactiveAccounts);
}

await pipeline.exec().then(handlePipeline);
handlePipeline(await pipeline.exec());

const commonMeta = {
[USERS_ID_FIELD]: userId,
[USERS_USERNAME_FIELD]: username,
[USERS_CREATED_FIELD]: created,
};

if (activate === true) {
commonMeta[USERS_ACTIVATED_FIELD] = Date.now();
}

await setMetadata.call(service, {
userId,
audience,
metadata: audience.map((metaAudience) => ({
$set: Object.assign(metadata[metaAudience] || {}, metaAudience === defaultAudience && {
[USERS_ID_FIELD]: userId,
[USERS_USERNAME_FIELD]: username,
[USERS_CREATED_FIELD]: created,
}),
$set: Object.assign(metadata[metaAudience] || {}, metaAudience === defaultAudience && commonMeta),
})),
});

Expand Down
1 change: 1 addition & 0 deletions src/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ module.exports = exports = {
USERS_TESTER_ROLE: 'tester',
USERS_BANNED_DATA: 'bannedData',
USERS_CREATED_FIELD: 'created',
USERS_ACTIVATED_FIELD: 'aa',
USERS_USERNAME_FIELD: 'username',
USERS_IS_ORG_FIELD: 'org',
USERS_PASSWORD_FIELD: 'password',
Expand Down
Loading