Skip to content
This repository was archived by the owner on Mar 12, 2025. It is now read-only.

Fix issue where tc-accounts module, relevant for topcoder based authentication, was throwing errors during build #8

Merged
merged 2 commits into from
Jun 18, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion config/default.js
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
10 changes: 7 additions & 3 deletions set-env.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
Expand Down
28 changes: 21 additions & 7 deletions ui/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
2 changes: 1 addition & 1 deletion ui/src/App.js
Original file line number Diff line number Diff line change
@@ -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';
Expand Down
13 changes: 7 additions & 6 deletions ui/src/config/config.js
Original file line number Diff line number Diff line change
@@ -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;

5 changes: 5 additions & 0 deletions ui/src/services/tc-auth/README
Original file line number Diff line number Diff line change
@@ -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
86 changes: 86 additions & 0 deletions ui/src/services/tc-auth/connector-wrapper.js
Original file line number Diff line number Diff line change
@@ -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);
}
7 changes: 7 additions & 0 deletions ui/src/services/tc-auth/constants.js
Original file line number Diff line number Diff line change
@@ -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';
13 changes: 13 additions & 0 deletions ui/src/services/tc-auth/iframe.js
Original file line number Diff line number Diff line change
@@ -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;
}
7 changes: 7 additions & 0 deletions ui/src/services/tc-auth/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export {
configureConnector,
getFreshToken,
logout,
} from './connector-wrapper';

export { decodeToken } from './token';
36 changes: 36 additions & 0 deletions ui/src/services/tc-auth/token.js
Original file line number Diff line number Diff line change
@@ -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);
}