From 2813fed6e148a9728cccc77c076bf65171775a97 Mon Sep 17 00:00:00 2001 From: Timur Minulin Date: Wed, 29 May 2019 21:28:14 +0300 Subject: [PATCH] feat(cubejs-cli): add token generation (#67) * feat(cubejs-cli): add token generation * feat(cubejs-cli): add example generation * fix(cubejs-cli): fix zero expiry --- packages/cubejs-cli/cubejsCli.js | 20 +++++++- packages/cubejs-cli/package.json | 2 + packages/cubejs-cli/token.js | 41 +++++++++++++++ packages/cubejs-cli/yarn.lock | 85 ++++++++++++++++++++++++++++++++ 4 files changed, 147 insertions(+), 1 deletion(-) create mode 100644 packages/cubejs-cli/token.js diff --git a/packages/cubejs-cli/cubejsCli.js b/packages/cubejs-cli/cubejsCli.js index 31303058d171..1a41fdfeee0b 100644 --- a/packages/cubejs-cli/cubejsCli.js +++ b/packages/cubejs-cli/cubejsCli.js @@ -17,6 +17,7 @@ const client = new Analytics('dSR8JiNYIGKyQHKid9OaLYugXLao18hA', { flushInterval const { machineIdSync } = require('node-machine-id'); const { promisify } = require('util'); const templates = require('./templates'); +const { token, defaultExpiry, collect } = require('./token'); const packageJson = require('./package.json'); @@ -56,7 +57,7 @@ const writePackageJson = async (json) => fs.writeJson('package.json', json, { EOL: os.EOL }); -const displayError = async (text, options) => { +const displayError = async (text, options = {}) => { console.error(''); console.error(chalk.cyan('Cube.js Error ---------------------------------------')); console.error(''); @@ -275,6 +276,23 @@ program console.log(' $ cubejs generate -t orders,customers'); }); +program + .command('token') + .option('-e, --expiry [expiry]', 'Token expiry. Set to 0 for no expiry', defaultExpiry) + .option('-s, --secret [secret]', 'Cube.js app secret. Also can be set via environment variable CUBEJS_API_SECRET') + .option('-p, --payload [values]', 'Payload. Example: -p foo=bar', collect, []) + .description('Create JWT token') + .action( + (options) => token(options) + .catch(e => displayError(e.stack || e)) + ) + .on('--help', () => { + console.log(''); + console.log('Examples:'); + console.log(''); + console.log(' $ cubejs token -e "1 day" -p foo=bar -p cool=true'); + }); + if (!process.argv.slice(2).length) { program.help(); } diff --git a/packages/cubejs-cli/package.json b/packages/cubejs-cli/package.json index 788538f79ca0..7602c92a5a2b 100644 --- a/packages/cubejs-cli/package.json +++ b/packages/cubejs-cli/package.json @@ -26,7 +26,9 @@ "chalk": "^2.4.2", "commander": "^2.19.0", "cross-spawn": "^6.0.5", + "dotenv": "^7.0.0", "fs-extra": "^7.0.1", + "jsonwebtoken": "^8.5.1", "node-machine-id": "^1.1.10" }, "devDependencies": { diff --git a/packages/cubejs-cli/token.js b/packages/cubejs-cli/token.js new file mode 100644 index 000000000000..2dcad69f969c --- /dev/null +++ b/packages/cubejs-cli/token.js @@ -0,0 +1,41 @@ +const jwt = require('jsonwebtoken'); +require('dotenv').config(); +const chalk = require('chalk'); + +const defaultExpiry = '30 days'; + +const parsePayload = (payloadArray = []) => { + const result = {}; + + payloadArray.forEach((entry = '') => { + const [key, value] = entry.split('='); + if (key && value) result[key] = value; + }); + + return result; +}; + +const token = async (options = {}) => { + const { expiry = defaultExpiry, secret = process.env.CUBEJS_API_SECRET } = options; + if (!secret) throw new Error('No app secret found').message; + + const extraOptions = {}; + if (expiry !== "0") extraOptions.expiresIn = expiry; + + const payload = parsePayload(options.payload); + + console.log("Generating Cube.js JWT token"); + console.log("Expires in: ", chalk.green(expiry)); + console.log("Payload: ", chalk.green(JSON.stringify(payload))); + console.log(""); + + const signedToken = jwt.sign(payload, secret, extraOptions); + console.log(signedToken); + return signedToken; +}; + +const collect = (val, memo) => [val, ...memo]; + +exports.token = token; +exports.defaultExpiry = defaultExpiry; +exports.collect = collect; diff --git a/packages/cubejs-cli/yarn.lock b/packages/cubejs-cli/yarn.lock index 1fc4046c9e21..d2086a12d29a 100644 --- a/packages/cubejs-cli/yarn.lock +++ b/packages/cubejs-cli/yarn.lock @@ -515,6 +515,11 @@ bser@^2.0.0: dependencies: node-int64 "^0.4.0" +buffer-equal-constant-time@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" + integrity sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk= + buffer-from@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" @@ -953,6 +958,11 @@ domexception@^1.0.1: dependencies: webidl-conversions "^4.0.2" +dotenv@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-7.0.0.tgz#a2be3cd52736673206e8a85fb5210eea29628e7c" + integrity sha512-M3NhsLbV1i6HuGzBUH8vXrtxOk+tWmzWKDMbAVSUp3Zsjm7ywFeuwrUXhmhQyRK1q5B5GGy7hcXPbj3bnfZg2g== + ecc-jsbn@~0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" @@ -961,6 +971,13 @@ ecc-jsbn@~0.1.1: jsbn "~0.1.0" safer-buffer "^2.1.0" +ecdsa-sig-formatter@1.0.11: + version "1.0.11" + resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf" + integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ== + dependencies: + safe-buffer "^5.0.1" + emoji-regex@^7.0.1: version "7.0.3" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" @@ -2598,6 +2615,22 @@ jsonfile@^4.0.0: optionalDependencies: graceful-fs "^4.1.6" +jsonwebtoken@^8.5.1: + version "8.5.1" + resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz#00e71e0b8df54c2121a1f26137df2280673bcc0d" + integrity sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w== + dependencies: + jws "^3.2.2" + lodash.includes "^4.3.0" + lodash.isboolean "^3.0.3" + lodash.isinteger "^4.0.4" + lodash.isnumber "^3.0.3" + lodash.isplainobject "^4.0.6" + lodash.isstring "^4.0.1" + lodash.once "^4.0.0" + ms "^2.1.1" + semver "^5.6.0" + jsprim@^1.2.2: version "1.4.1" resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" @@ -2608,6 +2641,23 @@ jsprim@^1.2.2: json-schema "0.2.3" verror "1.10.0" +jwa@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.1.tgz#743c32985cb9e98655530d53641b66c8645b039a" + integrity sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA== + dependencies: + buffer-equal-constant-time "1.0.1" + ecdsa-sig-formatter "1.0.11" + safe-buffer "^5.0.1" + +jws@^3.2.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304" + integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA== + dependencies: + jwa "^1.4.1" + safe-buffer "^5.0.1" + kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" @@ -2704,11 +2754,41 @@ lodash.get@^4.4.2: resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= +lodash.includes@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" + integrity sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8= + +lodash.isboolean@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6" + integrity sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY= + +lodash.isinteger@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343" + integrity sha1-YZwK89A/iwTDH1iChAt3sRzWg0M= + +lodash.isnumber@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc" + integrity sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w= + +lodash.isplainobject@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" + integrity sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs= + lodash.isstring@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451" integrity sha1-1SfftUVuynzJu5XV2ur4i6VKVFE= +lodash.once@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" + integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w= + lodash.sortby@^4.7.0: version "4.7.0" resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" @@ -3785,6 +3865,11 @@ semver@5.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" integrity sha1-myzl094C0XxgEq0yaqa00M9U+U8= +semver@^5.6.0: + version "5.7.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b" + integrity sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA== + set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"