diff --git a/.circleci/config.yml b/.circleci/config.yml index eed75ca..9ae216a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -82,7 +82,7 @@ workflows: - "build-dev": filters: branches: - only: dev + only: [dev, 'feature/discourseMigration'] - "build-prod": filters: branches: diff --git a/README.md b/README.md index 9b7ec23..38a2543 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,12 @@ The following parameters can be set in config files or in env variables: - KAFKA_CLIENT_CERT_KEY: Kafka connection private key, optional; if not provided, then SSL connection is not used, direct insecure connection is used; if provided, it can be either path to private key file or private key content - +- BUS_API_BASE_URL: Bus API url +- BUS_API_AUTH_TOKEN: Bus API auth token +- REPLY_EMAIL_PREFIX: prefix of the genereated reply email address +- REPLY_EMAIL_DOMAIN: email domain +- DEFAULT_REPLY_EMAIL: default reply to email address, for example no-reply@topcoder.com +- MENTION_EMAIL: recipient email used for email.project.post.mention event Configuration for the connect notification server is at `connect/config.js`. The following parameters can be set in config files or in env variables: diff --git a/config/default.js b/config/default.js index 3ab7a2b..be3abf0 100644 --- a/config/default.js +++ b/config/default.js @@ -27,5 +27,20 @@ module.exports = { KAFKA_CLIENT_CERT: process.env.KAFKA_CLIENT_CERT ? process.env.KAFKA_CLIENT_CERT.replace('\\n', '\n') : null, KAFKA_CLIENT_CERT_KEY: process.env.KAFKA_CLIENT_CERT_KEY ? process.env.KAFKA_CLIENT_CERT_KEY.replace('\\n', '\n') : null, - API_CONTEXT_PATH: process.env.API_CONTEXT_PATH || '/v5/notifications', + + BUS_API_AUTH_TOKEN: process.env.BUS_API_AUTH_TOKEN, + MENTION_EMAIL: process.env.MENTION_EMAIL, + REPLY_EMAIL_PREFIX: process.env.REPLY_EMAIL_PREFIX, + REPLY_EMAIL_DOMAIN: process.env.REPLY_EMAIL_DOMAIN, + + TC_ADMIN_TOKEN: process.env.TC_ADMIN_TOKEN, + TC_API_BASE_URL: process.env.TC_API_BASE_URL || 'https://api.topcoder-dev.com', + TC_API_V3_BASE_URL: process.env.TC_API_V3_BASE_URL || 'https://api.topcoder-dev.com/v3', + TC_API_V4_BASE_URL: process.env.TC_API_V4_BASE_URL || 'https://api.topcoder-dev.com/v4', + TC_API_V5_BASE_URL: process.env.TC_API_V5_BASE_URL || 'https://api.topcoder-dev.com/v5', + MESSAGE_API_BASE_URL: process.env.MESSAGE_API_BASE_URL || 'https://api.topcoder-dev.com/v4', + ENABLE_EMAILS: process.env.ENABLE_EMAILS || true, + ENABLE_DEV_MODE: process.env.ENABLE_DEV_MODE || true, + DEV_MODE_EMAIL: process.env.DEV_MODE_EMAIL, + API_CONTEXT_PATH: process.env.API_CONTEXT_PATH || '/v5/notifications', }; diff --git a/connect/config.js b/connect/config.js index 267c0ae..66691ad 100644 --- a/connect/config.js +++ b/connect/config.js @@ -5,6 +5,7 @@ module.exports = { TC_API_V3_BASE_URL: process.env.TC_API_V3_BASE_URL || 'https://api.topcoder-dev.com/v3', TC_API_V4_BASE_URL: process.env.TC_API_V4_BASE_URL || 'https://api.topcoder-dev.com/v4', + MESSAGE_API_BASE_URL: process.env.MESSAGE_API_BASE_URL || 'https://api.topcoder-dev.com/v4', // eslint-disable-next-line max-len TC_ADMIN_TOKEN: process.env.TC_ADMIN_TOKEN, diff --git a/connect/connectNotificationServer.js b/connect/connectNotificationServer.js index 4872aa1..249a1df 100644 --- a/connect/connectNotificationServer.js +++ b/connect/connectNotificationServer.js @@ -66,12 +66,12 @@ const getNotificationsForMentionedUser = (eventConfig, content) => { } let notifications = []; + // eslint-disable-next-line const regexUserHandle = /title=\"@([a-zA-Z0-9-_.{}\[\]]+)\"/g; - let handles=[]; - let matches = regexUserHandle.exec(content); - console.log(content) + const handles = []; + let matches = regexUserHandle.exec(content); while (matches) { - let handle = matches[1].toString(); + const handle = matches[1].toString(); notifications.push({ userHandle: handle, newType: 'notifications.connect.project.post.mention', @@ -85,13 +85,13 @@ const getNotificationsForMentionedUser = (eventConfig, content) => { // only one per userHandle notifications = _.uniqBy(notifications, 'userHandle'); - return new Promise((resolve)=>{ - service.getUsersByHandle(handles).then((users)=>{ - _.map(notifications,(notification)=>{ - notification.userId = _.find(users,{handle:notification.userHandle}).userId; + return new Promise((resolve) => { + service.getUsersByHandle(handles).then((users) => { + _.map(notifications, (notification) => { + notification.userId = _.find(users, { handle: notification.userHandle }).userId.toString(); }); resolve(notifications); - }) + }); }); }; @@ -307,7 +307,7 @@ const handler = (topic, message, callback) => { project, }) )).then((notifications) => { - allNotifications = _.filter(notifications,notification=>notification.userId!=message.initiatorUserId); + allNotifications = _.filter(notifications, notification => notification.userId !== message.initiatorUserId); // now let's retrieve some additional data @@ -326,6 +326,7 @@ const handler = (topic, message, callback) => { if (users.length) { notification.contents.userHandle = users[0].handle; notification.contents.userFullName = `${users[0].firstName} ${users[0].lastName}`; + notification.contents.userEmail = users[0].email; } }); callback(null, allNotifications); diff --git a/connect/service.js b/connect/service.js index e49f0ad..3156895 100644 --- a/connect/service.js +++ b/connect/service.js @@ -69,7 +69,7 @@ const getRoleMembers = (roleId) => request const getUsersById = (ids) => { const query = _.map(ids, (id) => 'userId:' + id).join(' OR '); return request - .get(`${config.TC_API_V3_BASE_URL}/members/_search?fields=userId,handle,firstName,lastName&query=${query}`) + .get(`${config.TC_API_V3_BASE_URL}/members/_search?fields=userId,email,handle,firstName,lastName&query=${query}`) .set('accept', 'application/json') .set('authorization', `Bearer ${config.TC_ADMIN_TOKEN}`) .then((res) => { @@ -78,7 +78,6 @@ const getUsersById = (ids) => { } const users = _.get(res, 'body.result.content'); - return users; }).catch((err) => { const errorDetails = _.get(err, 'response.body.result.content.message'); @@ -126,8 +125,8 @@ const getUsersByHandle = (handles) => { * * @return {Promise} promise resolved to topic details */ -const getTopic = (topicId) => request - .get(`${config.TC_API_V4_BASE_URL}/topics/${topicId}`) +const getTopic = (topicId, logger) => request + .get(`${config.MESSAGE_API_BASE_URL}/topics/${topicId}/read`) .set('accept', 'application/json') .set('authorization', `Bearer ${config.TC_ADMIN_TOKEN}`) .then((res) => { @@ -137,6 +136,9 @@ const getTopic = (topicId) => request return _.get(res, 'body.result.content'); }).catch((err) => { + if (logger) { + logger.error(err, `Error while calling ${config.MESSAGE_API_BASE_URL}/topics/${topicId}/read`); + } const errorDetails = _.get(err, 'response.body.result.content.message'); throw new Error( `Failed to get topic details of topic id: ${topicId}.` + @@ -144,7 +146,6 @@ const getTopic = (topicId) => request ); }); - module.exports = { getProject, getRoleMembers, diff --git a/deploy.sh b/deploy.sh index 7a2dad5..cfb915e 100755 --- a/deploy.sh +++ b/deploy.sh @@ -45,8 +45,19 @@ TC_ADMIN_TOKEN=$(eval "echo \$${ENV}_TC_ADMIN_TOKEN") LOG_LEVEL=$(eval "echo \$${ENV}_LOG_LEVEL") PORT=$(eval "echo \$${ENV}_PORT") +# email notifications config +ENABLE_EMAILS=$(eval "echo \$${ENV}_ENABLE_EMAILS") +BUS_API_AUTH_TOKEN=$(eval "echo \$${ENV}_BUS_API_AUTH_TOKEN") +MENTION_EMAIL=$(eval "echo \$${ENV}_MENTION_EMAIL") +REPLY_EMAIL_PREFIX=$(eval "echo \$${ENV}_REPLY_EMAIL_PREFIX") +REPLY_EMAIL_DOMAIN=$(eval "echo \$${ENV}_REPLY_EMAIL_DOMAIN") +ENABLE_DEV_MODE=$(eval "echo \$${ENV}_ENABLE_DEV_MODE") +DEV_MODE_EMAIL=$(eval "echo \$${ENV}_DEV_MODE_EMAIL") + TC_API_V3_BASE_URL=$(eval "echo \$${ENV}_TC_API_V3_BASE_URL") TC_API_V4_BASE_URL=$(eval "echo \$${ENV}_TC_API_V4_BASE_URL") +TC_API_V5_BASE_URL=$(eval "echo \$${ENV}_TC_API_V5_BASE_URL") +MESSAGE_API_BASE_URL=$(eval "echo \$${ENV}_MESSAGE_API_BASE_URL") DB_USER=$(eval "echo \$${ENV}_DB_USER") DB_PASSWORD=$(eval "echo \$${ENV}_DB_PASSWORD") @@ -159,10 +170,46 @@ make_task_def(){ "name": "TC_API_V4_BASE_URL", "value": "%s" }, + { + "name": "TC_API_V5_BASE_URL", + "value": "%s" + }, + { + "name": "MESSAGE_API_BASE_URL", + "value": "%s" + }, { "name": "TC_ADMIN_TOKEN", "value": "%s" }, + { + "name": "ENABLE_EMAILS", + "value": "%s" + }, + { + "name": "MENTION_EMAIL", + "value": "%s" + }, + { + "name": "REPLY_EMAIL_PREFIX", + "value": "%s" + }, + { + "name": "REPLY_EMAIL_DOMAIN", + "value": "%s" + }, + { + "name": "ENABLE_DEV_MODE", + "value": "%s" + }, + { + "name": "DEV_MODE_EMAIL", + "value": "%s" + }, + { + "name": "BUS_API_AUTH_TOKEN", + "value": "%s" + }, { "name": "LOG_LEVEL", "value": "%s" @@ -198,7 +245,7 @@ make_task_def(){ } ]' - task_def=$(printf "$task_template" $AWS_ECS_CONTAINER_NAME $AWS_ACCOUNT_ID $AWS_REGION $AWS_REPOSITORY $TAG $ENV "$KAFKA_CLIENT_CERT" "$KAFKA_CLIENT_CERT_KEY" $KAFKA_GROUP_ID "$KAFKA_TOPIC_IGNORE_PREFIX" $KAFKA_URL $DATABASE_URL $AUTHSECRET "$AUTHDOMAIN" "$JWKSURI" $TC_API_BASE_URL $TC_API_V3_BASE_URL $TC_API_V4_BASE_URL $TC_ADMIN_TOKEN $LOG_LEVEL $VALID_ISSUERS $PORT "$API_CONTEXT_PATH" $AWS_ECS_CLUSTER $AWS_REGION $AWS_ECS_CLUSTER $ENV) + task_def=$(printf "$task_template" $AWS_ECS_CONTAINER_NAME $AWS_ACCOUNT_ID $AWS_REGION $AWS_REPOSITORY $TAG $ENV "$KAFKA_CLIENT_CERT" "$KAFKA_CLIENT_CERT_KEY" $KAFKA_GROUP_ID "$KAFKA_TOPIC_IGNORE_PREFIX" $KAFKA_URL $DATABASE_URL $AUTHSECRET "$AUTHDOMAIN" "$JWKSURI" $TC_API_BASE_URL $TC_API_V3_BASE_URL $TC_API_V4_BASE_URL $TC_API_V5_BASE_URL $MESSAGE_API_BASE_URL $TC_ADMIN_TOKEN $ENABLE_EMAILS $MENTION_EMAIL $REPLY_EMAIL_PREFIX $REPLY_EMAIL_DOMAIN $ENABLE_DEV_MODE $DEV_MODE_EMAIL $BUS_API_AUTH_TOKEN $LOG_LEVEL $VALID_ISSUERS $PORT "$API_CONTEXT_PATH" $AWS_ECS_CLUSTER $AWS_REGION $AWS_ECS_CLUSTER $ENV) } register_definition() { diff --git a/package-lock.json b/package-lock.json index 73f97ee..c2347ab 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,17 +14,22 @@ "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.16.8.tgz", "integrity": "sha512-BdN2PXxOFnTXFcyONPW6t0fHjz2fvRZHVMFpaS0wYr+Y8fWEaNOs4V8LEu/fpzQlMx+ahdndgTaGTwPC+J/EeA==", "requires": { - "@types/express": "4.0.39", - "@types/node": "8.0.53" + "@types/express": "4.11.1", + "@types/node": "9.6.6" } }, + "@types/events": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@types/events/-/events-1.2.0.tgz", + "integrity": "sha512-KEIlhXnIutzKwRbQkGWb/I4HFqBuUykAdHgDED6xqwXJfONCjF5VoE0cXEiurh3XauygxzeDzgtXUqvLkxFzzA==" + }, "@types/express": { - "version": "4.0.39", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.0.39.tgz", - "integrity": "sha512-dBUam7jEjyuEofigUXCtublUHknRZvcRgITlGsTbFgPvnTwtQUt2NgLakbsf+PsGo/Nupqr3IXCYsOpBpofyrA==", + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.11.1.tgz", + "integrity": "sha512-ttWle8cnPA5rAelauSWeWJimtY2RsUf2aspYZs7xPHiWgOlPn6nnUfBMtrkcnjFJuIHJF4gNOdVvpLK2Zmvh6g==", "requires": { "@types/body-parser": "1.16.8", - "@types/express-serve-static-core": "4.0.57", + "@types/express-serve-static-core": "4.11.1", "@types/serve-static": "1.13.1" } }, @@ -33,16 +38,17 @@ "resolved": "https://registry.npmjs.org/@types/express-jwt/-/express-jwt-0.0.34.tgz", "integrity": "sha1-/b7kxq9cCiRu8qkz9VGZc8dxfwI=", "requires": { - "@types/express": "4.0.39", + "@types/express": "4.11.1", "@types/express-unless": "0.0.32" } }, "@types/express-serve-static-core": { - "version": "4.0.57", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.0.57.tgz", - "integrity": "sha512-QLAHjdLwEICm3thVbXSKRoisjfgMVI4xJH/HU8F385BR2HI7PmM6ax4ELXf8Du6sLmSpySXMYaI+xc//oQ/IFw==", + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.11.1.tgz", + "integrity": "sha512-EehCl3tpuqiM8RUb+0255M8PhhSwTtLfmO7zBBdv0ay/VTd/zmrqDfQdZFsa5z/PVMbH2yCMZPXsnrImpATyIw==", "requires": { - "@types/node": "8.0.53" + "@types/events": "1.2.0", + "@types/node": "9.6.6" } }, "@types/express-unless": { @@ -50,7 +56,7 @@ "resolved": "https://registry.npmjs.org/@types/express-unless/-/express-unless-0.0.32.tgz", "integrity": "sha512-6YpJyFNlDDnPnRjMOvJCoDYlSDDmG/OEEUsPk7yhNkL4G9hUYtgab6vi1CcWsGSSSM0CsvNlWTG+ywAGnvF03g==", "requires": { - "@types/express": "4.0.39" + "@types/express": "4.11.1" } }, "@types/geojson": { @@ -59,9 +65,9 @@ "integrity": "sha512-Xqg/lIZMrUd0VRmSRbCAewtwGZiAk3mEUDvV4op1tGl+LvyPcb/MIOSxTl9z+9+J+R4/vpjiCAT4xeKzH9ji1w==" }, "@types/lodash": { - "version": "4.14.85", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.85.tgz", - "integrity": "sha512-HrZiwDl62if0z31+rB99CLlg7WzS7b+KmyW75XAHEl/ZG0De2ACo6skZ89Zh3jOWkjKObN0Apq3MUezg7u9NKQ==" + "version": "4.14.107", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.107.tgz", + "integrity": "sha512-afvjfP2rl3yvtv2qrCRN23zIQcDinF+munMJCoHEw2BXF22QJogTlVfNPTACQ6ieDyA6VnyKT4WLuN/wK368ng==" }, "@types/mime": { "version": "2.0.0", @@ -69,32 +75,32 @@ "integrity": "sha512-A2TAGbTFdBw9azHbpVd+/FkdW2T6msN1uct1O9bH3vTerEHKZhTXJUQXy+hNq1B0RagfU8U+KBdqiZpxjhOUQA==" }, "@types/node": { - "version": "8.0.53", - "resolved": "https://registry.npmjs.org/@types/node/-/node-8.0.53.tgz", - "integrity": "sha512-54Dm6NwYeiSQmRB1BLXKr5GELi0wFapR1npi8bnZhEcu84d/yQKqnwwXQ56hZ0RUbTG6L5nqDZaN3dgByQXQRQ==" + "version": "9.6.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-9.6.6.tgz", + "integrity": "sha512-SJe0g5cZeGNDP5sD8mIX3scb+eq8LQQZ60FXiKZHipYSeEFZ5EKml+NNMiO76F74TY4PoMWlNxF/YRY40FOvZQ==" }, "@types/serve-static": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.1.tgz", "integrity": "sha512-jDMH+3BQPtvqZVIcsH700Dfi8Q3MIcEx16g/VdxjoqiGR/NntekB10xdBpirMKnPe9z2C5cBmL0vte0YttOr3Q==", "requires": { - "@types/express-serve-static-core": "4.0.57", + "@types/express-serve-static-core": "4.11.1", "@types/mime": "2.0.0" } }, "accepts": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.4.tgz", - "integrity": "sha1-hiRnWMfdbSGmR0/whKR0DsBesh8=", + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", "requires": { - "mime-types": "2.1.17", + "mime-types": "2.1.18", "negotiator": "0.6.1" } }, "acorn": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.2.1.tgz", - "integrity": "sha512-jG0u7c4Ly+3QkkW18V+NRDN+4bWHdln30NL1ZL2AvFZZmQe/BfopYCtghCKKVBUSetZ4QKcyA0pY6/4Gw8Pv8w==", + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.5.3.tgz", + "integrity": "sha512-jd5MkIUlbbmb07nXH0DT3y7rDVtkzDi4XZOUVWAer8ajmF/DTSSbl5oNFyDOl/OXA33Bl79+ypHhl2pN20VeOQ==", "dev": true }, "acorn-jsx": { @@ -115,13 +121,14 @@ } }, "ajv": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", - "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", - "dev": true, + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", "requires": { "co": "4.6.0", - "json-stable-stringify": "1.0.1" + "fast-deep-equal": "1.1.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1" } }, "ajv-keywords": { @@ -149,9 +156,9 @@ "dev": true }, "argparse": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", - "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, "requires": { "sprintf-js": "1.0.3" @@ -209,9 +216,9 @@ "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" }, "aws4": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", - "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=" + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.7.0.tgz", + "integrity": "sha512-32NDda82rhwD9/JBCCkB+MRYDp0oSvlo2IL6rQWA10PQi7tDUM3eqMSltXmY+Oyl/7N3P3qNtAlv7X0d9bI28w==" }, "axios": { "version": "0.12.0", @@ -226,7 +233,7 @@ "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.6.1.tgz", "integrity": "sha1-eIuUtvY04luRvWxd9y1GdFevsAA=", "requires": { - "core-js": "2.5.1" + "core-js": "2.5.5" } }, "backoff": { @@ -242,6 +249,11 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, + "base-64": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/base-64/-/base-64-0.1.0.tgz", + "integrity": "sha1-eAqZyE59YAJgNhURxId2E78k9rs=" + }, "base64url": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/base64url/-/base64url-2.0.0.tgz", @@ -261,7 +273,7 @@ "resolved": "https://registry.npmjs.org/bin-protocol/-/bin-protocol-3.0.4.tgz", "integrity": "sha1-RlqdNQb+sOEmtStbIWDZNuFbJ/Q=", "requires": { - "lodash": "4.17.4", + "lodash": "4.17.5", "long": "3.2.0", "protocol-buffers-schema": "3.3.2" } @@ -279,13 +291,13 @@ "bytes": "3.0.0", "content-type": "1.0.4", "debug": "2.6.9", - "depd": "1.1.1", - "http-errors": "1.6.2", + "depd": "1.1.2", + "http-errors": "1.6.3", "iconv-lite": "0.4.19", "on-finished": "2.3.0", "qs": "6.5.1", "raw-body": "2.3.2", - "type-is": "1.6.15" + "type-is": "1.6.16" } }, "boom": { @@ -293,13 +305,13 @@ "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", "requires": { - "hoek": "4.2.0" + "hoek": "4.2.1" } }, "brace-expansion": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", - "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "requires": { "balanced-match": "1.0.0", "concat-map": "0.0.1" @@ -315,6 +327,12 @@ "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" }, + "buffer-from": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.0.0.tgz", + "integrity": "sha512-83apNb8KK0Se60UE1+4Ukbe3HbfELJ6UlI4ldtOGs7So4KD26orJM8hIY9lxdzP+UpItH1Yh/Y8GUvNFWFFRxA==", + "dev": true + }, "buffer-writer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-1.0.1.tgz", @@ -331,10 +349,10 @@ "resolved": "https://registry.npmjs.org/bunyan/-/bunyan-1.8.12.tgz", "integrity": "sha1-8VDw9nSKvdcq6uhPBEA74u8RN5c=", "requires": { - "dtrace-provider": "0.8.5", - "moment": "2.19.2", + "dtrace-provider": "0.8.6", + "moment": "2.22.1", "mv": "2.1.1", - "safe-json-stringify": "1.0.4" + "safe-json-stringify": "1.1.0" } }, "bytes": { @@ -397,9 +415,9 @@ "dev": true }, "cls-bluebird": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/cls-bluebird/-/cls-bluebird-2.0.1.tgz", - "integrity": "sha1-wlmkgK4CwOUGE0MHuxPbMERu4uc=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cls-bluebird/-/cls-bluebird-2.1.0.tgz", + "integrity": "sha1-N+8eCAqP+1XC9BZPU28ZGeeWiu4=", "requires": { "is-bluebird": "1.0.2", "shimmer": "1.2.0" @@ -437,9 +455,9 @@ "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=" }, "combined-stream": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", - "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.6.tgz", + "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", "requires": { "delayed-stream": "1.0.0" } @@ -455,20 +473,21 @@ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "concat-stream": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", - "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", "dev": true, "requires": { + "buffer-from": "1.0.0", "inherits": "2.0.3", - "readable-stream": "2.3.3", + "readable-stream": "2.3.6", "typedarray": "0.0.6" } }, "config": { - "version": "1.28.1", - "resolved": "https://registry.npmjs.org/config/-/config-1.28.1.tgz", - "integrity": "sha1-diXSoeTJDxMdinM0eYLZPDhzKC0=", + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/config/-/config-1.30.0.tgz", + "integrity": "sha1-HWCp81NIoTwXV5jThOgaWhbDum4=", "requires": { "json5": "0.4.0", "os-homedir": "1.0.2" @@ -516,9 +535,9 @@ "integrity": "sha1-Qa1XsbVVlR7BcUEqgZQrHoIA00o=" }, "core-js": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.1.tgz", - "integrity": "sha1-rmh03GaTd4m4B1T/VCjfZoGcpQs=" + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.5.tgz", + "integrity": "sha1-sU3ek2xkDAV5prUMq8wTLdYSfjs=" }, "core-util-is": { "version": "1.0.2", @@ -547,7 +566,7 @@ "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", "requires": { - "hoek": "4.2.0" + "hoek": "4.2.1" } } } @@ -563,7 +582,7 @@ "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", "dev": true, "requires": { - "es5-ext": "0.10.37" + "es5-ext": "0.10.42" } }, "dashdash": { @@ -596,7 +615,7 @@ "requires": { "globby": "5.0.0", "is-path-cwd": "1.0.0", - "is-path-in-cwd": "1.0.0", + "is-path-in-cwd": "1.0.1", "object-assign": "4.1.1", "pify": "2.3.0", "pinkie-promise": "2.0.1", @@ -609,9 +628,9 @@ "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" }, "depd": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", - "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" }, "destroy": { "version": "1.0.4", @@ -634,12 +653,12 @@ "integrity": "sha1-2hkZgci41xPKARXViYzzl8Lw3dA=" }, "dtrace-provider": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/dtrace-provider/-/dtrace-provider-0.8.5.tgz", - "integrity": "sha1-mOu6Ihr6xG4cOf02hY2Pk2dSS5I=", + "version": "0.8.6", + "resolved": "https://registry.npmjs.org/dtrace-provider/-/dtrace-provider-0.8.6.tgz", + "integrity": "sha1-QooiOv4DQl0s1tY0f99AxmkDVj0=", "optional": true, "requires": { - "nan": "2.8.0" + "nan": "2.10.0" } }, "ecc-jsbn": { @@ -666,18 +685,19 @@ "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" }, "encodeurl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.1.tgz", - "integrity": "sha1-eePVhlU0aQn+bw9Fpd5oEDspTSA=" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" }, "es5-ext": { - "version": "0.10.37", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.37.tgz", - "integrity": "sha1-DudB0Ui4AGm6J9AgOTdWryV978M=", + "version": "0.10.42", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.42.tgz", + "integrity": "sha512-AJxO1rmPe1bDEfSR6TJ/FgMFYuTBhR5R57KW58iCkYACMyFbrkqVyzXSurYoScDGvgyMpk7uRF/lPUPPTmsRSA==", "dev": true, "requires": { "es6-iterator": "2.0.3", - "es6-symbol": "3.1.1" + "es6-symbol": "3.1.1", + "next-tick": "1.0.0" } }, "es6-iterator": { @@ -687,7 +707,7 @@ "dev": true, "requires": { "d": "1.0.0", - "es5-ext": "0.10.37", + "es5-ext": "0.10.42", "es6-symbol": "3.1.1" } }, @@ -698,7 +718,7 @@ "dev": true, "requires": { "d": "1.0.0", - "es5-ext": "0.10.37", + "es5-ext": "0.10.42", "es6-iterator": "2.0.3", "es6-set": "0.1.5", "es6-symbol": "3.1.1", @@ -712,7 +732,7 @@ "dev": true, "requires": { "d": "1.0.0", - "es5-ext": "0.10.37", + "es5-ext": "0.10.42", "es6-iterator": "2.0.3", "es6-symbol": "3.1.1", "event-emitter": "0.3.5" @@ -725,7 +745,7 @@ "dev": true, "requires": { "d": "1.0.0", - "es5-ext": "0.10.37" + "es5-ext": "0.10.42" } }, "es6-weak-map": { @@ -735,7 +755,7 @@ "dev": true, "requires": { "d": "1.0.0", - "es5-ext": "0.10.37", + "es5-ext": "0.10.42", "es6-iterator": "2.0.3", "es6-symbol": "3.1.1" } @@ -759,7 +779,7 @@ "requires": { "es6-map": "0.1.5", "es6-weak-map": "2.0.2", - "esrecurse": "4.2.0", + "esrecurse": "4.2.1", "estraverse": "4.2.0" } }, @@ -770,12 +790,12 @@ "dev": true, "requires": { "chalk": "1.1.3", - "concat-stream": "1.6.0", + "concat-stream": "1.6.2", "debug": "2.6.9", "doctrine": "1.5.0", "es6-map": "0.1.5", "escope": "3.6.0", - "espree": "3.5.2", + "espree": "3.5.4", "estraverse": "4.2.0", "esutils": "2.0.2", "file-entry-cache": "1.3.1", @@ -784,12 +804,12 @@ "ignore": "3.3.7", "imurmurhash": "0.1.4", "inquirer": "0.12.0", - "is-my-json-valid": "2.16.1", - "is-resolvable": "1.0.0", - "js-yaml": "3.10.0", + "is-my-json-valid": "2.17.2", + "is-resolvable": "1.1.0", + "js-yaml": "3.11.0", "json-stable-stringify": "1.0.1", "levn": "0.3.0", - "lodash": "4.17.4", + "lodash": "4.17.5", "mkdirp": "0.5.1", "optionator": "0.8.2", "path-is-absolute": "1.0.1", @@ -834,7 +854,7 @@ "requires": { "debug": "2.6.9", "object-assign": "4.1.1", - "resolve": "1.5.0" + "resolve": "1.7.1" } }, "eslint-plugin-import": { @@ -874,12 +894,12 @@ } }, "espree": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.2.tgz", - "integrity": "sha512-sadKeYwaR/aJ3stC2CdvgXu1T16TdYN+qwCpcWbMnGJ8s0zNWemzrvb2GbD4OhmJ/fwpJjudThAlLobGbWZbCQ==", + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", + "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", "dev": true, "requires": { - "acorn": "5.2.1", + "acorn": "5.5.3", "acorn-jsx": "3.0.1" } }, @@ -890,13 +910,12 @@ "dev": true }, "esrecurse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz", - "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", "dev": true, "requires": { - "estraverse": "4.2.0", - "object-assign": "4.1.1" + "estraverse": "4.2.0" } }, "estraverse": { @@ -923,7 +942,7 @@ "dev": true, "requires": { "d": "1.0.0", - "es5-ext": "0.10.37" + "es5-ext": "0.10.42" } }, "exit-hook": { @@ -933,11 +952,11 @@ "dev": true }, "express": { - "version": "4.16.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.16.2.tgz", - "integrity": "sha1-41xt/i1kt9ygpc1PIXgb4ymeB2w=", + "version": "4.16.3", + "resolved": "https://registry.npmjs.org/express/-/express-4.16.3.tgz", + "integrity": "sha1-avilAjUNsyRuzEvs9rWjTSL37VM=", "requires": { - "accepts": "1.3.4", + "accepts": "1.3.5", "array-flatten": "1.1.1", "body-parser": "1.18.2", "content-disposition": "0.5.2", @@ -945,39 +964,34 @@ "cookie": "0.3.1", "cookie-signature": "1.0.6", "debug": "2.6.9", - "depd": "1.1.1", - "encodeurl": "1.0.1", + "depd": "1.1.2", + "encodeurl": "1.0.2", "escape-html": "1.0.3", "etag": "1.8.1", - "finalhandler": "1.1.0", + "finalhandler": "1.1.1", "fresh": "0.5.2", "merge-descriptors": "1.0.1", "methods": "1.1.2", "on-finished": "2.3.0", "parseurl": "1.3.2", "path-to-regexp": "0.1.7", - "proxy-addr": "2.0.2", + "proxy-addr": "2.0.3", "qs": "6.5.1", "range-parser": "1.2.0", "safe-buffer": "5.1.1", - "send": "0.16.1", - "serve-static": "1.13.1", + "send": "0.16.2", + "serve-static": "1.13.2", "setprototypeof": "1.1.0", - "statuses": "1.3.1", - "type-is": "1.6.15", + "statuses": "1.4.0", + "type-is": "1.6.16", "utils-merge": "1.0.1", "vary": "1.1.2" }, "dependencies": { - "setprototypeof": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", - "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" - }, "statuses": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", - "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=" + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" } } }, @@ -997,9 +1011,9 @@ "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=" }, "fast-deep-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz", - "integrity": "sha1-liVqO8l1WV6zbYLpkp0GDYk0Of8=" + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" }, "fast-json-stable-stringify": { "version": "2.0.0", @@ -1033,23 +1047,23 @@ } }, "finalhandler": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.0.tgz", - "integrity": "sha1-zgtoVbRYU+eRsvzGgARtiCU91/U=", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", + "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", "requires": { "debug": "2.6.9", - "encodeurl": "1.0.1", + "encodeurl": "1.0.2", "escape-html": "1.0.3", "on-finished": "2.3.0", "parseurl": "1.3.2", - "statuses": "1.3.1", + "statuses": "1.4.0", "unpipe": "1.0.0" }, "dependencies": { "statuses": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", - "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=" + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" } } }, @@ -1081,7 +1095,7 @@ "integrity": "sha1-NLkLqyqRGqNHVx2pDyK9NuzYqRk=", "requires": { "debug": "2.6.9", - "stream-consume": "0.1.0" + "stream-consume": "0.1.1" } }, "forever-agent": { @@ -1090,19 +1104,19 @@ "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" }, "form-data": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.1.tgz", - "integrity": "sha1-b7lPvXGIUwbXPRXMSX/kzE7NRL8=", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.2.tgz", + "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", "requires": { "asynckit": "0.4.0", - "combined-stream": "1.0.5", - "mime-types": "2.1.17" + "combined-stream": "1.0.6", + "mime-types": "2.1.18" } }, "formidable": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.1.1.tgz", - "integrity": "sha1-lriIb3w8NQi5Mta9cMTTqI818ak=" + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.1.tgz", + "integrity": "sha512-Fs9VRguL0gqGHkXS5GQiMCr1VhZBxz0JnJs4JmMp/2jL18Fmbzvv7vOFRU+U8TBkHEE/CX1qDXzJplVULgsLeg==" }, "forwarded": { "version": "0.1.2", @@ -1142,9 +1156,9 @@ } }, "generic-pool": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.2.0.tgz", - "integrity": "sha512-JjcXDHT84icN/kFaF5+rNd1trZsgJFVqTSgM9dv6eayxSIQKMq0ilBJ+5pvf0SgimacMlZEsav4oL+4dUE4E2g==" + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.4.2.tgz", + "integrity": "sha512-H7cUpwCQSiJmAHM4c/aFu6fUfrhWXW1ncyh8ftxEPMu6AiYkHw9K8br720TGPZJbk5eOH2bynjZD1yPvdDAmag==" }, "get-parameter-names": { "version": "0.3.0", @@ -1223,21 +1237,8 @@ "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.0.3.tgz", "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", "requires": { - "ajv": "5.5.1", + "ajv": "5.5.2", "har-schema": "2.0.0" - }, - "dependencies": { - "ajv": { - "version": "5.5.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.1.tgz", - "integrity": "sha1-s4u4h22ehr7plJVqBOch6IskjrI=", - "requires": { - "co": "4.6.0", - "fast-deep-equal": "1.0.0", - "fast-json-stable-stringify": "2.0.0", - "json-schema-traverse": "0.3.1" - } - } } }, "has": { @@ -1274,24 +1275,24 @@ "requires": { "boom": "4.3.1", "cryptiles": "3.1.2", - "hoek": "4.2.0", + "hoek": "4.2.1", "sntp": "2.1.0" } }, "hoek": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", - "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==" + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", + "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==" }, "http-errors": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", - "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", "requires": { - "depd": "1.1.1", + "depd": "1.1.2", "inherits": "2.0.3", - "setprototypeof": "1.0.3", - "statuses": "1.4.0" + "setprototypeof": "1.1.0", + "statuses": "1.5.0" } }, "http-signature": { @@ -1301,7 +1302,7 @@ "requires": { "assert-plus": "1.0.0", "jsprim": "1.4.1", - "sshpk": "1.13.1" + "sshpk": "1.14.1" } }, "iconv-lite": { @@ -1352,7 +1353,7 @@ "cli-cursor": "1.0.2", "cli-width": "2.2.0", "figures": "1.7.0", - "lodash": "4.17.4", + "lodash": "4.17.5", "readline2": "1.0.1", "run-async": "0.1.0", "rx-lite": "3.1.2", @@ -1362,9 +1363,9 @@ } }, "ipaddr.js": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.5.2.tgz", - "integrity": "sha1-1LUFvemUaYfM8PxY2QEP+WB+P6A=" + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.6.0.tgz", + "integrity": "sha1-4/o1e3c9phnybpXwSdBVxyeW+Gs=" }, "is-bluebird": { "version": "1.0.2", @@ -1380,14 +1381,21 @@ "number-is-nan": "1.0.1" } }, + "is-my-ip-valid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz", + "integrity": "sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ==", + "dev": true + }, "is-my-json-valid": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.16.1.tgz", - "integrity": "sha512-ochPsqWS1WXj8ZnMIV0vnNXooaMhp7cyL4FMSIPKTtnV0Ha/T19G2b9kkhcNsabV9bxYkze7/aLZJb/bYuFduQ==", + "version": "2.17.2", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.17.2.tgz", + "integrity": "sha512-IBhBslgngMQN8DDSppmgDv7RNrlFotuuDsKcrCP3+HbFaVivIBU7u9oiiErw8sH4ynx3+gOGQ3q2otkgiSi6kg==", "dev": true, "requires": { "generate-function": "2.0.0", "generate-object-property": "1.2.0", + "is-my-ip-valid": "1.0.0", "jsonpointer": "4.0.1", "xtend": "4.0.1" } @@ -1399,18 +1407,18 @@ "dev": true }, "is-path-in-cwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", - "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", + "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", "dev": true, "requires": { - "is-path-inside": "1.0.0" + "is-path-inside": "1.0.1" } }, "is-path-inside": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz", - "integrity": "sha1-/AbloWg/vaE95mev9xe7wQpI838=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", "dev": true, "requires": { "path-is-inside": "1.0.2" @@ -1423,13 +1431,10 @@ "dev": true }, "is-resolvable": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.0.tgz", - "integrity": "sha1-jfV8YeouPFAUCNEA+wE8+NbgzGI=", - "dev": true, - "requires": { - "tryit": "1.0.3" - } + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", + "dev": true }, "is-typedarray": { "version": "1.0.0", @@ -1461,10 +1466,10 @@ "resolved": "https://registry.npmjs.org/joi/-/joi-9.2.0.tgz", "integrity": "sha1-M4WseQGSEwy+Iw6ALsAskhW7/to=", "requires": { - "hoek": "4.2.0", + "hoek": "4.2.1", "isemail": "2.2.1", "items": "2.1.1", - "moment": "2.19.2", + "moment": "2.22.1", "topo": "2.0.2" } }, @@ -1474,12 +1479,12 @@ "integrity": "sha1-4mJbrbwNZ8dTPp7cEGjFh65BN+8=" }, "js-yaml": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", - "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==", + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.11.0.tgz", + "integrity": "sha512-saJstZWv7oNeOyBh3+Dx1qWzhW0+e6/8eDzo7p5rDFqxntSztloLtuKu+Ejhtq82jsilwOIZYsCz+lIjthg1Hw==", "dev": true, "requires": { - "argparse": "1.0.9", + "argparse": "1.0.10", "esprima": "4.0.0" } }, @@ -1531,9 +1536,9 @@ "dev": true }, "jsonwebtoken": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.1.0.tgz", - "integrity": "sha1-xjl80uX9WD1lwAeoPce7eOaYK4M=", + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.2.1.tgz", + "integrity": "sha512-l8rUBr0fqYYwPc8/ZGrue7GiW7vWdZtZqelxo4Sd5lMvuEeCK8/wS54sEo6tJhdZ6hqfutsj6COgC0d1XdbHGw==", "requires": { "jws": "3.1.4", "lodash.includes": "4.3.0", @@ -1543,8 +1548,15 @@ "lodash.isplainobject": "4.0.6", "lodash.isstring": "4.0.1", "lodash.once": "4.1.1", - "ms": "2.0.0", + "ms": "2.1.1", "xtend": "4.0.1" + }, + "dependencies": { + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + } } }, "jsprim": { @@ -1576,10 +1588,10 @@ "requires": { "@types/express-jwt": "0.0.34", "debug": "2.6.9", - "limiter": "1.1.2", - "lru-memoizer": "1.11.1", + "limiter": "1.1.3", + "lru-memoizer": "1.12.0", "ms": "2.0.0", - "request": "2.83.0" + "request": "2.85.0" } }, "jws": { @@ -1628,9 +1640,9 @@ } }, "limiter": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.2.tgz", - "integrity": "sha512-JIKZ0xb6fZZYa3deZ0BgXCgX6HgV8Nx3mFGeFHmFWW8Fb2c08e0CyE+G3nalpD0xGvGssjGb1UdFr+PprxZEbw==" + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/limiter/-/limiter-1.1.3.tgz", + "integrity": "sha512-zrycnIMsLw/3ZxTbW7HCez56rcFGecWTx5OZNplzcXUUmJLmoYArC6qdJzmAN5BWiNXGcpjhF9RQ1HSv5zebEw==" }, "lock": { "version": "0.1.4", @@ -1638,9 +1650,9 @@ "integrity": "sha1-/sfervF+fDoKVeHaBCgD4l2RdF0=" }, "lodash": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" + "version": "4.17.5", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz", + "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==" }, "lodash.cond": { "version": "4.5.2", @@ -1716,21 +1728,14 @@ } }, "lru-memoizer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/lru-memoizer/-/lru-memoizer-1.11.1.tgz", - "integrity": "sha1-BpP2EAWTkUwC4ZK/m42TiEy/UNM=", + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/lru-memoizer/-/lru-memoizer-1.12.0.tgz", + "integrity": "sha1-7+ZXBsyKnMZT+A8NWm6jitlQ41I=", "requires": { "lock": "0.1.4", - "lodash": "4.5.1", + "lodash": "4.17.5", "lru-cache": "4.0.2", "very-fast-args": "1.1.0" - }, - "dependencies": { - "lodash": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.5.1.tgz", - "integrity": "sha1-gOigdMpfOJOmscELKmNkktcQwxY=" - } } }, "media-typer": { @@ -1759,16 +1764,16 @@ "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" }, "mime-db": { - "version": "1.30.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", - "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=" + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==" }, "mime-types": { - "version": "2.1.17", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", - "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", "requires": { - "mime-db": "1.30.0" + "mime-db": "1.33.0" } }, "minimatch": { @@ -1776,7 +1781,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "requires": { - "brace-expansion": "1.1.8" + "brace-expansion": "1.1.11" } }, "minimist": { @@ -1793,16 +1798,16 @@ } }, "moment": { - "version": "2.19.2", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.19.2.tgz", - "integrity": "sha512-Rf6jiHPEfxp9+dlzxPTmRHbvoFXsh2L/U8hOupUMpnuecHQmI6cF6lUbJl3QqKPko1u6ujO+FxtcajLVfLpAtA==" + "version": "2.22.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.22.1.tgz", + "integrity": "sha512-shJkRTSebXvsVqk56I+lkb2latjBs8I+pc2TzWc545y2iFnSjm7Wg0QMh+ZWcdSLQyGEau5jI8ocnmkyTgr9YQ==" }, "moment-timezone": { - "version": "0.5.14", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.14.tgz", - "integrity": "sha1-TrOP+VOLgBCLpGekWPPtQmjM/LE=", + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.16.tgz", + "integrity": "sha512-4d1l92plNNqnMkqI/7boWNVXJvwGL2WyByl1Hxp3h/ao3HZiAqaoQY+6KBkYdiN5QtNDpndq+58ozl8W4GVoNw==", "requires": { - "moment": "2.19.2" + "moment": "2.22.1" } }, "ms": { @@ -1833,9 +1838,9 @@ } }, "nan": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.8.0.tgz", - "integrity": "sha1-7XFfP+neArV6XmJS2QqWZ14fCFo=", + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", + "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==", "optional": true }, "ncp": { @@ -1849,21 +1854,27 @@ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" }, + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", + "dev": true + }, "nice-simple-logger": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/nice-simple-logger/-/nice-simple-logger-1.0.1.tgz", "integrity": "sha1-D55khSe+e+PkmrdvqMjAmK+VG/Y=", "requires": { - "lodash": "4.17.4" + "lodash": "4.17.5" } }, "no-kafka": { - "version": "3.2.8", - "resolved": "https://registry.npmjs.org/no-kafka/-/no-kafka-3.2.8.tgz", - "integrity": "sha1-F2bgIb8z0iCGPbZBIKr3pQR6Cko=", + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/no-kafka/-/no-kafka-3.2.9.tgz", + "integrity": "sha1-jLSk8aDVDqYUXFvAZ6A1Dl5CmMc=", "requires": { "@types/bluebird": "3.5.0", - "@types/lodash": "4.14.85", + "@types/lodash": "4.14.107", "bin-protocol": "3.0.4", "bluebird": "3.5.1", "buffer-crc32": "0.2.13", @@ -1915,7 +1926,7 @@ }, "onetime": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", "dev": true }, @@ -1985,9 +1996,9 @@ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" }, "pg": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/pg/-/pg-7.4.0.tgz", - "integrity": "sha1-4lYGHSxScjw8hY3vuX8RWcpmD4M=", + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/pg/-/pg-7.4.1.tgz", + "integrity": "sha512-Pi5qYuXro5PAD9xXx8h7bFtmHgAQEG6/SCNyi7gS3rvb/ZQYDmxKchfB0zYtiSJNWq9iXTsYsHjrM+21eBcN1A==", "requires": { "buffer-writer": "1.0.1", "js-string-escape": "1.0.1", @@ -2108,9 +2119,9 @@ "dev": true }, "process-nextick-args": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" }, "progress": { "version": "1.1.8", @@ -2124,12 +2135,12 @@ "integrity": "sha512-Xdayp8sB/mU+sUV4G7ws8xtYMGdQnxbeIfLjyO9TZZRJdztBGhlmbI5x1qcY4TG5hBkIKGnc28i7nXxaugu88w==" }, "proxy-addr": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.2.tgz", - "integrity": "sha1-ZXFQT0e7mI7IGAJT+F3X4UlSvew=", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.3.tgz", + "integrity": "sha512-jQTChiCJteusULxjBp8+jftSQE5Obdl3k4cnmLA6WXtK6XFuWRnvVL7aCiBqaLPM8c4ph0S4tKna8XvmIwEnXQ==", "requires": { "forwarded": "0.1.2", - "ipaddr.js": "1.5.2" + "ipaddr.js": "1.6.0" } }, "pseudomap": { @@ -2161,19 +2172,42 @@ "http-errors": "1.6.2", "iconv-lite": "0.4.19", "unpipe": "1.0.0" + }, + "dependencies": { + "depd": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", + "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" + }, + "http-errors": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", + "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", + "requires": { + "depd": "1.1.1", + "inherits": "2.0.3", + "setprototypeof": "1.0.3", + "statuses": "1.5.0" + } + }, + "setprototypeof": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", + "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" + } } }, "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "requires": { "core-util-is": "1.0.2", "inherits": "2.0.3", "isarray": "1.0.0", - "process-nextick-args": "1.0.7", + "process-nextick-args": "2.0.0", "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", + "string_decoder": "1.1.1", "util-deprecate": "1.0.2" } }, @@ -2197,32 +2231,32 @@ } }, "request": { - "version": "2.83.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.83.0.tgz", - "integrity": "sha512-lR3gD69osqm6EYLk9wB/G1W/laGWjzH90t1vEa2xuxHD5KUrSzp9pUSfTm+YC5Nxt2T8nMPEvKlhbQayU7bgFw==", + "version": "2.85.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.85.0.tgz", + "integrity": "sha512-8H7Ehijd4js+s6wuVPLjwORxD4zeuyjYugprdOXlPSqaApmL/QOy+EB/beICHVCHkGMKNh5rvihb5ov+IDw4mg==", "requires": { "aws-sign2": "0.7.0", - "aws4": "1.6.0", + "aws4": "1.7.0", "caseless": "0.12.0", - "combined-stream": "1.0.5", + "combined-stream": "1.0.6", "extend": "3.0.1", "forever-agent": "0.6.1", - "form-data": "2.3.1", + "form-data": "2.3.2", "har-validator": "5.0.3", "hawk": "6.0.2", "http-signature": "1.2.0", "is-typedarray": "1.0.0", "isstream": "0.1.2", "json-stringify-safe": "5.0.1", - "mime-types": "2.1.17", + "mime-types": "2.1.18", "oauth-sign": "0.8.2", "performance-now": "2.1.0", "qs": "6.5.1", "safe-buffer": "5.1.1", "stringstream": "0.0.5", - "tough-cookie": "2.3.3", + "tough-cookie": "2.3.4", "tunnel-agent": "0.6.0", - "uuid": "3.1.0" + "uuid": "3.2.1" } }, "require-uncached": { @@ -2236,9 +2270,9 @@ } }, "resolve": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", - "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz", + "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==", "dev": true, "requires": { "path-parse": "1.0.5" @@ -2298,9 +2332,9 @@ "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" }, "safe-json-stringify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/safe-json-stringify/-/safe-json-stringify-1.0.4.tgz", - "integrity": "sha1-gaCY9Efku8P/MxKiQ1IbwGDvWRE=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-json-stringify/-/safe-json-stringify-1.1.0.tgz", + "integrity": "sha512-EzBtUaFH9bHYPc69wqjp0efJI/DPNHdFbGE3uIMn4sVbO0zx8vZ8cG4WKxQfOpUOKsQyGBiT2mTqnCw+6nLswA==", "optional": true }, "semver": { @@ -2309,54 +2343,54 @@ "integrity": "sha1-x6BxWKgL7dBSNVt3DYLWZA+AO+c=" }, "send": { - "version": "0.16.1", - "resolved": "https://registry.npmjs.org/send/-/send-0.16.1.tgz", - "integrity": "sha512-ElCLJdJIKPk6ux/Hocwhk7NFHpI3pVm/IZOYWqUmoxcgeyM+MpxHHKhb8QmlJDX1pU6WrgaHBkVNm73Sv7uc2A==", + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", + "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", "requires": { "debug": "2.6.9", - "depd": "1.1.1", + "depd": "1.1.2", "destroy": "1.0.4", - "encodeurl": "1.0.1", + "encodeurl": "1.0.2", "escape-html": "1.0.3", "etag": "1.8.1", "fresh": "0.5.2", - "http-errors": "1.6.2", + "http-errors": "1.6.3", "mime": "1.4.1", "ms": "2.0.0", "on-finished": "2.3.0", "range-parser": "1.2.0", - "statuses": "1.3.1" + "statuses": "1.4.0" }, "dependencies": { "statuses": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.3.1.tgz", - "integrity": "sha1-+vUbnrdKrvOzrPStX2Gr8ky3uT4=" + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" } } }, "sequelize": { - "version": "4.23.1", - "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-4.23.1.tgz", - "integrity": "sha512-v0iXooqGDJpccLh4bHESf0Ltt88PokOGiMFro/xTXCm5If9WLeJ4ObtPlq7xRu15BAXz+nTsJAXJ418PLj9u7w==", + "version": "4.37.6", + "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-4.37.6.tgz", + "integrity": "sha512-x/6099L+6+3LQWms23wng/AR6yUE3X/VhrwSTSMbgOIk2ELY3DchI/9f9Ii7LIQRPxW1BHGpwboH7kxS/froXg==", "requires": { "bluebird": "3.5.1", - "cls-bluebird": "2.0.1", + "cls-bluebird": "2.1.0", "debug": "3.1.0", - "depd": "1.1.1", + "depd": "1.1.2", "dottie": "2.0.0", - "generic-pool": "3.2.0", + "generic-pool": "3.4.2", "inflection": "1.12.0", - "lodash": "4.17.4", - "moment": "2.19.2", - "moment-timezone": "0.5.14", + "lodash": "4.17.5", + "moment": "2.22.1", + "moment-timezone": "0.5.16", "retry-as-promised": "2.3.2", - "semver": "5.4.1", + "semver": "5.5.0", "terraformer-wkt-parser": "1.1.2", "toposort-class": "1.0.1", - "uuid": "3.1.0", - "validator": "9.1.2", - "wkx": "0.4.2" + "uuid": "3.2.1", + "validator": "9.4.1", + "wkx": "0.4.4" }, "dependencies": { "debug": { @@ -2368,27 +2402,27 @@ } }, "semver": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", - "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==" + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==" } } }, "serve-static": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.1.tgz", - "integrity": "sha512-hSMUZrsPa/I09VYFJwa627JJkNs0NrfL1Uzuup+GqHfToR2KcsXFymXSV90hoyw3M+msjFuQly+YzIH/q0MGlQ==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", + "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", "requires": { - "encodeurl": "1.0.1", + "encodeurl": "1.0.2", "escape-html": "1.0.3", "parseurl": "1.3.2", - "send": "0.16.1" + "send": "0.16.2" } }, "setprototypeof": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", - "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" }, "shelljs": { "version": "0.6.1", @@ -2417,7 +2451,7 @@ "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", "requires": { - "hoek": "4.2.0" + "hoek": "4.2.1" } }, "split": { @@ -2435,9 +2469,9 @@ "dev": true }, "sshpk": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", - "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.1.tgz", + "integrity": "sha1-Ew9Zde3a2WPx1W+SuaxsUfqfg+s=", "requires": { "asn1": "0.2.3", "assert-plus": "1.0.0", @@ -2455,14 +2489,22 @@ "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" }, "statuses": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", - "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" }, "stream-consume": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.0.tgz", - "integrity": "sha1-pB6tGm1ggc63n2WwYZAbbY89HQ8=" + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.1.tgz", + "integrity": "sha512-tNa3hzgkjEP7XbCkbRXe1jpg+ievoa0O4SCFlMOYEscGSS4JJsckGL8swUyAa/ApGU3Ae4t6Honor4HhL+tRyg==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "5.1.1" + } }, "string-width": { "version": "1.0.2", @@ -2475,14 +2517,6 @@ "strip-ansi": "3.0.1" } }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "requires": { - "safe-buffer": "5.1.1" - } - }, "stringstream": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", @@ -2504,20 +2538,20 @@ "dev": true }, "superagent": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.1.tgz", - "integrity": "sha512-VMBFLYgFuRdfeNQSMLbxGSLfmXL/xc+OO+BZp41Za/NRDBet/BNbkRJrYzCUu0u4GU0i/ml2dtT8b9qgkw9z6Q==", + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-3.8.2.tgz", + "integrity": "sha512-gVH4QfYHcY3P0f/BZzavLreHW3T1v7hG9B+hpMQotGQqurOvhv87GcMCd6LWySmBuf+BDR44TQd0aISjVHLeNQ==", "requires": { "component-emitter": "1.2.1", "cookiejar": "2.1.1", "debug": "3.1.0", "extend": "3.0.1", - "form-data": "2.3.1", - "formidable": "1.1.1", + "form-data": "2.3.2", + "formidable": "1.2.1", "methods": "1.1.2", "mime": "1.4.1", "qs": "6.5.1", - "readable-stream": "2.3.3" + "readable-stream": "2.3.6" }, "dependencies": { "debug": { @@ -2545,11 +2579,21 @@ "ajv": "4.11.8", "ajv-keywords": "1.5.1", "chalk": "1.1.3", - "lodash": "4.17.4", + "lodash": "4.17.5", "slice-ansi": "0.0.4", "string-width": "2.1.1" }, "dependencies": { + "ajv": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "dev": true, + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + } + }, "ansi-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", @@ -2584,14 +2628,16 @@ } }, "tc-core-library-js": { - "version": "github:gondzo/tc-core-library-js#d6c6a6f8b8509538e696833b37ea7fa7bf0533fb", + "version": "github:appirio-tech/tc-core-library-js#eedc98867f640858fc021fd7dbaec6f7b6732051", "requires": { "axios": "0.12.0", "bunyan": "1.8.12", - "config": "1.28.1", + "config": "1.30.0", "jsonwebtoken": "7.4.3", + "jwks-rsa": "1.2.1", "le_node": "1.7.1", - "lodash": "4.17.4" + "lodash": "4.17.5", + "millisecond": "0.1.2" }, "dependencies": { "hoek": { @@ -2611,7 +2657,7 @@ "requires": { "hoek": "2.16.3", "isemail": "1.2.0", - "moment": "2.19.2", + "moment": "2.22.1", "topo": "1.1.0" } }, @@ -2669,7 +2715,7 @@ "resolved": "https://registry.npmjs.org/topo/-/topo-2.0.2.tgz", "integrity": "sha1-zVYVdSU5BXwNwEkaYhw7xvvh0YI=", "requires": { - "hoek": "4.2.0" + "hoek": "4.2.1" } }, "toposort-class": { @@ -2678,19 +2724,13 @@ "integrity": "sha1-f/0feMi+KMO6Rc1OGj9e4ZO9mYg=" }, "tough-cookie": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", - "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.4.tgz", + "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", "requires": { "punycode": "1.4.1" } }, - "tryit": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tryit/-/tryit-1.0.3.tgz", - "integrity": "sha1-OTvnMKlEb9Hq1tpZoBQwjzbCics=", - "dev": true - }, "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -2715,12 +2755,12 @@ } }, "type-is": { - "version": "1.6.15", - "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.15.tgz", - "integrity": "sha1-yrEPtJCeRByChC6v4a1kbIGARBA=", + "version": "1.6.16", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", + "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", "requires": { "media-typer": "0.3.0", - "mime-types": "2.1.17" + "mime-types": "2.1.18" } }, "typedarray": { @@ -2754,14 +2794,14 @@ "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" }, "uuid": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", - "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==" + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", + "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==" }, "validator": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/validator/-/validator-9.1.2.tgz", - "integrity": "sha512-1Tml6crNdsSC61jHssWksQxq6C7MmSFCCmf99Eb+l/V/cwVlw4/Pg3YXBP1WKcHLsyqe3E+iJXUZgoTTQFcqQg==" + "version": "9.4.1", + "resolved": "https://registry.npmjs.org/validator/-/validator-9.4.1.tgz", + "integrity": "sha512-YV5KjzvRmSyJ1ee/Dm5UED0G+1L4GZnLN3w6/T+zZm8scVua4sOhYKWTUrKa0H/tMiJyO9QLHMPN+9mB/aMunA==" }, "vary": { "version": "1.1.2", @@ -2784,9 +2824,9 @@ "integrity": "sha1-4W0dH6+KbllqJGQh/ZCneWPQs5Y=" }, "winston": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.0.tgz", - "integrity": "sha1-gIBQuT1SZh7Z+2wms/DIJnCLCu4=", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/winston/-/winston-2.4.2.tgz", + "integrity": "sha512-4S/Ad4ZfSNl8OccCLxnJmNISWcm2joa6Q0YGDxlxMzH0fgSwWsjMt+SmlNwCqdpaPg3ev1HKkMBsIiXeSUwpbA==", "requires": { "async": "1.0.0", "colors": "1.0.3", @@ -2797,11 +2837,11 @@ } }, "wkx": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.4.2.tgz", - "integrity": "sha1-d201pjSlwi5lbkdEvetU+D/Szo0=", + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.4.4.tgz", + "integrity": "sha512-eVVHka2jRaAp9QanKhLpxWs3AGDV0b8cijlavxBnn4ryXzq5N/3Xe3nkQsI0XMRA16RURwviCWuOCj4mXCmrxw==", "requires": { - "@types/node": "8.0.53" + "@types/node": "9.6.6" } }, "wordwrap": { @@ -2829,7 +2869,7 @@ "resolved": "https://registry.npmjs.org/wrr-pool/-/wrr-pool-1.1.3.tgz", "integrity": "sha1-/a0i8uofMDY//l14HPeUl6d/8H4=", "requires": { - "lodash": "4.17.4" + "lodash": "4.17.5" } }, "xtend": { diff --git a/package.json b/package.json index f55a132..48e720c 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,8 @@ "main": "./index.js", "scripts": { "start": "node connect/connectNotificationServer", - "lint": "eslint *.js src config test connect || true" + "lint": "eslint *.js src config test connect || true", + "lint:fix": "eslint *.js --fix src config test connect || true" }, "author": "TCSCODER", "license": "none", @@ -15,6 +16,7 @@ "eslint-plugin-import": "^1.5.0" }, "dependencies": { + "base-64": "^0.1.0", "bluebird": "^3.5.1", "body-parser": "^1.15.2", "co": "^4.6.0", diff --git a/src/app.js b/src/app.js index 3dd02d9..2d8ec96 100644 --- a/src/app.js +++ b/src/app.js @@ -7,12 +7,16 @@ require('./bootstrap'); const config = require('config'); const express = require('express'); const jwtAuth = require('tc-core-library-js').middleware.jwtAuthenticator; +const jwt = require('jsonwebtoken'); const _ = require('lodash'); const cors = require('cors'); const bodyParser = require('body-parser'); +const { BUS_API_EVENT } = require('./constants') const helper = require('./common/helper'); +const helperService = require('./services/helper'); const logger = require('./common/logger'); const errors = require('./common/errors'); +const service = require('./services/BusAPI'); const models = require('./models'); const Kafka = require('no-kafka'); @@ -49,15 +53,92 @@ function startKafkaConsumer(handlers) { const handlerAsync = Promise.promisify(handler); // use handler to create notification instances for each recipient return handlerAsync(topicName, messageJSON) - // save notifications - .then((notifications) => Promise.all(_.map(notifications, (notification) => models.Notification.create({ - userId: notification.userId, - type: notification.newType || topicName, - version: notification.version || null, - contents: _.extend({}, messageJSON, notification.contents), - read: false, - seen: false, - })))) + .then((notifications) => Promise.all(_.map(notifications, (notification) => + // save notifications + models.Notification.create({ + userId: notification.userId, + type: notification.newType || topicName, + version: notification.version || null, + contents: _.extend({}, messageJSON, notification.contents), + read: false, + seen: false, + }) + .then(() => { + if (config.ENABLE_EMAILS) { + // if it's interesting event, create email event and send to bus api + const notificationType = notification.newType || topicName; + logger.debug(`checking ${notificationType} notification ${JSON.stringify(notification)}`); + let eventType; + + if (notificationType === BUS_API_EVENT.CONNECT.TOPIC_CREATED) { + eventType = BUS_API_EVENT.EMAIL.TOPIC_CREATED; + } else if (notificationType === BUS_API_EVENT.CONNECT.POST_CREATED) { + eventType = BUS_API_EVENT.EMAIL.POST_CREATED; + } else if (notificationType === BUS_API_EVENT.CONNECT.MENTIONED_IN_POST) { + eventType = BUS_API_EVENT.EMAIL.MENTIONED_IN_POST; + } + if (!!eventType) { + const topicId = parseInt(messageJSON.topicId, 10); + const postId = messageJSON.postId ? parseInt(messageJSON.postId, 10) : null; + + helperService.getUsersById([notification.userId]).then((users) => { + logger.debug(`got users ${JSON.stringify(users)}`); + helperService.getTopic(topicId, logger).then((connectTopic) => { + logger.debug(`got topic ${JSON.stringify(connectTopic)}`); + const user = users[0]; + let userEmail = user.email; + if (config.ENABLE_DEV_MODE === 'true') { + userEmail = config.DEV_MODE_EMAIL; + } + const recipients = [userEmail]; + if (notificationType === BUS_API_EVENT.EMAIL.MENTIONED_IN_POST) { + recipients.push(config.MENTION_EMAIL); + } + + // get jwt token then encode it with base64 + const body = { + userId: parseInt(notification.userId, 10), + topicId, + userEmail: helper.sanitizeEmail(user.email), + }; + logger.debug(`body for generating token: ${JSON.stringify(body)}`); + logger.debug(`authSecret: ${config.authSecret.substring(-5)}`); + const token = jwt.sign(body, config.authSecret, { noTimestamp: true }).split('.')[2]; + logger.debug(`token: ${token}`); + + const replyTo = `${config.REPLY_EMAIL_PREFIX}+${topicId}/${token}@${config.REPLY_EMAIL_DOMAIN}`; + + const eventMessage = { + data: { + name: user.firstName + ' ' + user.lastName, + handle: user.handle, + topicTitle: connectTopic.title || '', + post: messageJSON.postContent, + date: (new Date()).toISOString(), + projectName: notification.contents.projectName, + projectId: messageJSON.projectId, + topicId, + postId, + }, + recipients, + replyTo, + }; + // send event to bus api + return service.postEvent({ + "topic": eventType, + "originator": "tc-notifications", + "timestamp": (new Date()).toISOString(), + "mime-type": "application/json", + "payload": eventMessage, + }).then(() => { + logger.info(`sent ${eventType} event with body ${eventMessage} to bus api`); + }); + }); + }); + } + } + }) + ))) // commit offset .then(() => consumer.commitOffset({ topic, partition, offset: m.offset })) .catch((err) => logger.error(err)); diff --git a/src/common/helper.js b/src/common/helper.js index c788f72..80aea57 100644 --- a/src/common/helper.js +++ b/src/common/helper.js @@ -38,7 +38,24 @@ function autoWrapExpress(obj) { return obj; } +/** + * Helper method to clean up the provided email address for deducing the final address that matters for + * the delivery of the email i.e. removing any non standard parts in the email address e.g. getting rid + * of anything after + sign in the local part of the email. + * + * @param {String} email email address to be sanitized + * + * @returns {String} sanitized email + */ +function sanitizeEmail(email) { + if (email) { + return email.substring(0, email.indexOf('+')) + email.substring(email.indexOf('@')); + } + return ''; +} + module.exports = { wrapExpress, autoWrapExpress, + sanitizeEmail, }; diff --git a/src/constants.js b/src/constants.js new file mode 100644 index 0000000..fda41c5 --- /dev/null +++ b/src/constants.js @@ -0,0 +1,17 @@ +module.exports = { + BUS_API_EVENT: { + CONNECT : { + TOPIC_CREATED: 'notifications.connect.project.topic.created', + TOPIC_DELETED: 'notifications.connect.project.topic.deleted', + POST_CREATED: 'notifications.connect.project.post.created', + POST_UPDATED: 'notifications.connect.project.post.edited', + POST_DELETED: 'notifications.connect.project.post.deleted', + MENTIONED_IN_POST: 'notifications.connect.project.post.mention', + }, + EMAIL : { + TOPIC_CREATED: 'notifications.action.email.connect.project.topic.created', + POST_CREATED: 'notifications.action.email.connect.project.post.created', + MENTIONED_IN_POST: 'notifications.action.email.connect.project.post.mention', + }, + }, +}; diff --git a/src/services/BusAPI.js b/src/services/BusAPI.js new file mode 100644 index 0000000..a72d24e --- /dev/null +++ b/src/services/BusAPI.js @@ -0,0 +1,28 @@ +const request = require('superagent'); +const config = require('config'); +const _ = require('lodash'); + +/** + * Post event to bus api + * + * @param {Object} event event + * + * @return {Promise} promise resolved to post event + */ +const postEvent = (event) => request + .post(`${config.TC_API_V5_BASE_URL}/bus/events`) + .set('Content-Type', 'application/json') + .set('Authorization', `Bearer ${config.BUS_API_AUTH_TOKEN}`) + .send(event) + .then(() => '') + .catch((err) => { + const errorDetails = _.get(err, 'message'); + throw new Error( + `Failed to post event ${event}.` + + (errorDetails ? ' Server response: ' + errorDetails : '') + ); + }); + +module.exports = { + postEvent, +}; diff --git a/src/services/helper.js b/src/services/helper.js new file mode 100644 index 0000000..0fe0311 --- /dev/null +++ b/src/services/helper.js @@ -0,0 +1,69 @@ +/** + * Service to get data from TopCoder API + */ +const request = require('superagent'); +const config = require('config'); +const _ = require('lodash'); + + +/** + * Get users details by ids + * + * @param {Array} ids list of user ids + * + * @return {Promise} resolves to the list of user details + */ +const getUsersById = (ids) => { + const query = _.map(ids, (id) => 'id=' + id).join(' OR '); + return request + .get(`${config.TC_API_V3_BASE_URL}/users?fields=userId,email,handle,firstName,lastName&filter=${query}`) + .set('accept', 'application/json') + .set('authorization', `Bearer ${config.TC_ADMIN_TOKEN}`) + .then((res) => { + if (!_.get(res, 'body.result.success')) { + throw new Error(`Failed to get users by id: ${ids}`); + } + const users = _.get(res, 'body.result.content'); + return users; + }).catch((err) => { + const errorDetails = _.get(err, 'response.body.result.content.message'); + throw new Error( + `Failed to get users by ids: ${ids}.` + + (errorDetails ? ' Server response: ' + errorDetails : '') + ); + }); +}; + +/** + * Get topic details + * + * @param {String} topicId topic id + * + * @return {Promise} promise resolved to topic details + */ +const getTopic = (topicId, logger) => request + .get(`${config.MESSAGE_API_BASE_URL}/topics/${topicId}/read`) + .set('accept', 'application/json') + .set('authorization', `Bearer ${config.TC_ADMIN_TOKEN}`) + .then((res) => { + if (!_.get(res, 'body.result.success')) { + throw new Error(`Failed to get topic details of topic id: ${topicId}`); + } + + return _.get(res, 'body.result.content'); + }).catch((err) => { + if (logger) { + logger.error(err, `Error while calling ${config.MESSAGE_API_BASE_URL}/topics/${topicId}/read`); + } + const errorDetails = _.get(err, 'response.body.result.content.message'); + throw new Error( + `Failed to get topic details of topic id: ${topicId}.` + + (errorDetails ? ' Server response: ' + errorDetails : '') + ); + }); + + +module.exports = { + getUsersById, + getTopic, +};