From 7e0411cf9a8c159261dbfecb8e756d720a90f9db Mon Sep 17 00:00:00 2001 From: Mithun Kamath Date: Sat, 16 Jun 2018 22:12:13 +0530 Subject: [PATCH 1/2] Fix issue where tc-accounts module, relevant for topcoder based authentication, was throwing errors during build --- config/default.js | 2 +- set-env.js | 10 ++- ui/package-lock.json | 28 +++++-- ui/package.json | 3 +- ui/src/App.js | 2 +- ui/src/config/config.js | 13 +-- ui/src/services/tc-auth/README | 5 ++ ui/src/services/tc-auth/connector-wrapper.js | 86 ++++++++++++++++++++ ui/src/services/tc-auth/constants.js | 7 ++ ui/src/services/tc-auth/iframe.js | 13 +++ ui/src/services/tc-auth/index.js | 7 ++ ui/src/services/tc-auth/token.js | 36 ++++++++ 12 files changed, 192 insertions(+), 20 deletions(-) create mode 100644 ui/src/services/tc-auth/README create mode 100644 ui/src/services/tc-auth/connector-wrapper.js create mode 100644 ui/src/services/tc-auth/constants.js create mode 100644 ui/src/services/tc-auth/iframe.js create mode 100644 ui/src/services/tc-auth/index.js create mode 100644 ui/src/services/tc-auth/token.js diff --git a/config/default.js b/config/default.js index b5a32d5..49a17f8 100755 --- a/config/default.js +++ b/config/default.js @@ -3,7 +3,7 @@ */ module.exports = { LOG_LEVEL: process.env.LOG_LEVEL || 'debug', - PORT: process.env.PORT || 4000, + PORT: process.env.PORT || 3000, // see https://www.npmjs.com/package/no-kafka for available options KAFKA_OPTIONS: { connectionString: process.env.KAFKA_URL || 'localhost:9092', diff --git a/set-env.js b/set-env.js index 857b770..90e03ab 100755 --- a/set-env.js +++ b/set-env.js @@ -4,12 +4,16 @@ const targetPath = './ui/src/config/config.js'; const envConfigFile = ` const config = { - API_URL: '${process.env.API_URL || 'http://localhost:4000'}/api/v1', - WS_URL: '${process.env.WS_URL || 'ws://localhost:4000'}', - DEFAULT_MESSAGE_COUNT: ${process.env.DEFAULT_MESSAGE_COUNT || 20} + API_URL: ${process.env.API_URL} || 'http://localhost:3000/api/v1', + WS_URL: ${process.env.WS_URL} || 'ws://localhost:3000', + DEFAULT_MESSAGE_COUNT: ${process.env.DEFAULT_MESSAGE_COUNT} || 20, + TC_AUTH_URL: ${process.env.TC_AUTH_URL} || 'https://accounts.topcoder-dev.com', + ACCOUNTS_APP_CONNECTOR: ${process.env.ACCOUNTS_APP_CONNECTOR} || 'https://accounts.topcoder-dev.com/connector.html', + APP_URL: ${process.env.APP_URL} || 'http://localhost:3000', }; export default config; + `; writeFile(targetPath, envConfigFile, (err) => { diff --git a/ui/package-lock.json b/ui/package-lock.json index dc093b1..c296051 100755 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -3926,11 +3926,13 @@ }, "balanced-match": { "version": "1.0.0", - "bundled": true + "bundled": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -3943,15 +3945,18 @@ }, "code-point-at": { "version": "1.1.0", - "bundled": true + "bundled": true, + "optional": true }, "concat-map": { "version": "0.0.1", - "bundled": true + "bundled": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", - "bundled": true + "bundled": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -4054,7 +4059,8 @@ }, "inherits": { "version": "2.0.3", - "bundled": true + "bundled": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -4064,6 +4070,7 @@ "is-fullwidth-code-point": { "version": "1.0.0", "bundled": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -4076,17 +4083,20 @@ "minimatch": { "version": "3.0.4", "bundled": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } }, "minimist": { "version": "0.0.8", - "bundled": true + "bundled": true, + "optional": true }, "minipass": { "version": "2.2.4", "bundled": true, + "optional": true, "requires": { "safe-buffer": "^5.1.1", "yallist": "^3.0.0" @@ -4103,6 +4113,7 @@ "mkdirp": { "version": "0.5.1", "bundled": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -4175,7 +4186,8 @@ }, "number-is-nan": { "version": "1.0.1", - "bundled": true + "bundled": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -4185,6 +4197,7 @@ "once": { "version": "1.4.0", "bundled": true, + "optional": true, "requires": { "wrappy": "1" } @@ -4290,6 +4303,7 @@ "string-width": { "version": "1.0.2", "bundled": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", diff --git a/ui/package.json b/ui/package.json index 8e7ed7f..2ca12b3 100755 --- a/ui/package.json +++ b/ui/package.json @@ -10,8 +10,7 @@ "react-dom": "^16.3.2", "react-router-dom": "^4.3.1", "react-scripts": "1.1.4", - "superagent": "^3.8.3", - "tc-accounts": "git+https://github.com/appirio-tech/accounts-app.git#dev" + "superagent": "^3.8.3" }, "scripts": { "start": "react-scripts start", diff --git a/ui/src/App.js b/ui/src/App.js index 6d693e9..8751427 100755 --- a/ui/src/App.js +++ b/ui/src/App.js @@ -1,6 +1,6 @@ import React, { Component } from 'react'; import { BrowserRouter as Router } from 'react-router-dom'; -import { getFreshToken, configureConnector, decodeToken } from 'tc-accounts'; +import { getFreshToken, configureConnector, decodeToken } from './services/tc-auth'; import loadingImg from './loading.gif'; import './App.css'; import DayPickerInput from 'react-day-picker/DayPickerInput'; diff --git a/ui/src/config/config.js b/ui/src/config/config.js index 5a1936f..c58a91f 100755 --- a/ui/src/config/config.js +++ b/ui/src/config/config.js @@ -1,11 +1,12 @@ const config = { - API_URL: 'http://localhost:4000/api/v1', - WS_URL: 'ws://localhost:4000', - DEFAULT_MESSAGE_COUNT: 20, - TC_AUTH_URL: 'https://accounts.topcoder-dev.com', - ACCOUNTS_APP_CONNECTOR: 'https://accounts.topcoder-dev.com/connector.html', - APP_URL: 'http://local.topcoder-dev.com:3000', + API_URL: undefined || 'http://localhost:3000/api/v1', + WS_URL: undefined || 'ws://localhost:3000', + DEFAULT_MESSAGE_COUNT: undefined || 20, + TC_AUTH_URL: undefined || 'https://accounts.topcoder-dev.com', + ACCOUNTS_APP_CONNECTOR: undefined || 'https://accounts.topcoder-dev.com/connector.html', + APP_URL: undefined || 'http://localhost:3000', }; export default config; + diff --git a/ui/src/services/tc-auth/README b/ui/src/services/tc-auth/README new file mode 100644 index 0000000..a104125 --- /dev/null +++ b/ui/src/services/tc-auth/README @@ -0,0 +1,5 @@ +This folder contains a sub set of the changes located in https://github.com/appirio-tech/accounts-app + +Create React script is unable to minify that module. + +Hence, we are extracting into this folder only what is necessary for this app to function diff --git a/ui/src/services/tc-auth/connector-wrapper.js b/ui/src/services/tc-auth/connector-wrapper.js new file mode 100644 index 0000000..a51d0a1 --- /dev/null +++ b/ui/src/services/tc-auth/connector-wrapper.js @@ -0,0 +1,86 @@ +import { + GET_FRESH_TOKEN_REQUEST, + GET_FRESH_TOKEN_SUCCESS, + GET_FRESH_TOKEN_FAILURE, + LOGOUT_REQUEST, + LOGOUT_SUCCESS, + LOGOUT_FAILURE, +} from './constants.js'; +import createFrame from './iframe.js'; + +let iframe = null; +let loading = null; +let url = ''; +let mock = false; +let token = ''; + +export function configureConnector({ connectorUrl, frameId, mockMode, mockToken }) { + if (mockMode) { + mock = true; + token = mockToken; + } else if (iframe) { + console.warn('tc-accounts connector can only be configured once, this request has been ignored.'); + } else { + iframe = createFrame(frameId, connectorUrl); + url = connectorUrl; + + loading = new Promise((resolve) => { + iframe.onload = function () { + loading = null; + resolve(); + }; + }); + } +} + +const proxyCall = function (REQUEST, SUCCESS, FAILURE, params = {}) { + if (mock) { + throw new Error('connector is running in mock mode. This method (proxyCall) should not be invoked.'); + } + + if (!iframe) { + throw new Error('connector has not yet been configured.'); + } + + function request() { + return new Promise((resolve, reject) => { + function receiveMessage(e) { + const safeFormat = e.data.type === SUCCESS || e.data.type === FAILURE; + if (safeFormat) { + window.removeEventListener('message', receiveMessage); + if (e.data.type === SUCCESS) resolve(e.data); + if (e.data.type === FAILURE) reject(e.error); + } + } + + window.addEventListener('message', receiveMessage); + + const payload = Object.assign({}, { type: REQUEST }, params); + + iframe.contentWindow.postMessage(payload, url); + }); + } + + if (loading) { + loading = loading.then(request); + return loading; + } + + return request(); +}; + +export function getFreshToken() { + if (mock) { + if (token) { + return Promise.resolve(token); + } + return Promise.reject('connector is running in mock mode, but no token has been specified.'); + } + + return proxyCall(GET_FRESH_TOKEN_REQUEST, GET_FRESH_TOKEN_SUCCESS, GET_FRESH_TOKEN_FAILURE) + .then(data => data.token); +} + +export function logout() { + return proxyCall(LOGOUT_REQUEST, LOGOUT_SUCCESS, LOGOUT_FAILURE); +} diff --git a/ui/src/services/tc-auth/constants.js b/ui/src/services/tc-auth/constants.js new file mode 100644 index 0000000..17d86b0 --- /dev/null +++ b/ui/src/services/tc-auth/constants.js @@ -0,0 +1,7 @@ +export const GET_FRESH_TOKEN_REQUEST = 'GET_FRESH_TOKEN_REQUEST'; +export const GET_FRESH_TOKEN_SUCCESS = 'GET_FRESH_TOKEN_SUCCESS'; +export const GET_FRESH_TOKEN_FAILURE = 'GET_FRESH_TOKEN_FAILURE'; + +export const LOGOUT_REQUEST = 'LOGOUT_REQUEST'; +export const LOGOUT_SUCCESS = 'LOGOUT_SUCCESS'; +export const LOGOUT_FAILURE = 'LOGOUT_FAILURE'; diff --git a/ui/src/services/tc-auth/iframe.js b/ui/src/services/tc-auth/iframe.js new file mode 100644 index 0000000..7fb4bd3 --- /dev/null +++ b/ui/src/services/tc-auth/iframe.js @@ -0,0 +1,13 @@ +export default function createFrame(id, src) { + const iframe = document.createElement('iframe'); + + iframe.id = id; + iframe.src = src; + iframe.width = 0; + iframe.height = 0; + iframe.frameborder = 0; + + document.body.appendChild(iframe); + + return iframe; +} diff --git a/ui/src/services/tc-auth/index.js b/ui/src/services/tc-auth/index.js new file mode 100644 index 0000000..eab6260 --- /dev/null +++ b/ui/src/services/tc-auth/index.js @@ -0,0 +1,7 @@ +export { + configureConnector, + getFreshToken, + logout, +} from './connector-wrapper'; + +export { decodeToken } from './token'; diff --git a/ui/src/services/tc-auth/token.js b/ui/src/services/tc-auth/token.js new file mode 100644 index 0000000..0321d0e --- /dev/null +++ b/ui/src/services/tc-auth/token.js @@ -0,0 +1,36 @@ +function urlBase64Decode(str) { + let output = str.replace(/-/g, '+').replace(/_/g, '/'); + + switch (output.length % 4) { + case 0: + break; + + case 2: + output += '=='; + break; + + case 3: + output += '='; + break; + + default: + throw new Error('Illegal base64url string!'); + } + return decodeURIComponent(escape(atob(output))); +} + +export function decodeToken(token) { + const parts = token.split('.'); + + if (parts.length !== 3) { + throw new Error('The token is invalid'); + } + + const decoded = urlBase64Decode(parts[1]); + + if (!decoded) { + throw new Error('Cannot decode the token'); + } + + return JSON.parse(decoded); +} From 22f8259ac75f18498a3f1eb6c72d84f2dc02ce84 Mon Sep 17 00:00:00 2001 From: Mithun Kamath Date: Sat, 16 Jun 2018 23:04:57 +0530 Subject: [PATCH 2/2] Fix issue where environment variable is not being saved as a string --- set-env.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/set-env.js b/set-env.js index 90e03ab..0c2fb4b 100755 --- a/set-env.js +++ b/set-env.js @@ -4,12 +4,12 @@ const targetPath = './ui/src/config/config.js'; const envConfigFile = ` const config = { - API_URL: ${process.env.API_URL} || 'http://localhost:3000/api/v1', - WS_URL: ${process.env.WS_URL} || 'ws://localhost:3000', + API_URL: '${process.env.API_URL || 'http://localhost:3000'}/api/v1', + WS_URL: '${process.env.WS_URL || 'ws://localhost:3000'}', DEFAULT_MESSAGE_COUNT: ${process.env.DEFAULT_MESSAGE_COUNT} || 20, - TC_AUTH_URL: ${process.env.TC_AUTH_URL} || 'https://accounts.topcoder-dev.com', - ACCOUNTS_APP_CONNECTOR: ${process.env.ACCOUNTS_APP_CONNECTOR} || 'https://accounts.topcoder-dev.com/connector.html', - APP_URL: ${process.env.APP_URL} || 'http://localhost:3000', + TC_AUTH_URL: '${process.env.TC_AUTH_URL || 'https://accounts.topcoder-dev.com'}', + ACCOUNTS_APP_CONNECTOR: '${process.env.ACCOUNTS_APP_CONNECTOR || 'https://accounts.topcoder-dev.com/connector.html'}', + APP_URL: '${process.env.APP_URL || 'http://localhost:3000'}', }; export default config;