From 36e273f86ccc1169c3317f90fd8716a43fadd061 Mon Sep 17 00:00:00 2001 From: Nicolas Humbert Date: Fri, 3 Apr 2020 16:27:54 -0700 Subject: [PATCH] ZENKO-2519 Customizable configuration at runtime --- public/assets/config.json | 3 +- src/js/{pensieveClient.js => apiClient.js} | 14 ++++--- src/react/Routes.jsx | 16 ++++---- src/react/actions/auth.js | 48 ++++++++-------------- src/react/actions/configuration.js | 5 +-- src/react/actions/location.js | 10 ++--- src/react/actions/stats.js | 8 ++-- src/react/reducers/auth.js | 2 +- src/react/utils/actions.js | 2 +- 9 files changed, 50 insertions(+), 58 deletions(-) rename src/js/{pensieveClient.js => apiClient.js} (52%) diff --git a/public/assets/config.json b/public/assets/config.json index 5c51c7809..8b2dfea9a 100644 --- a/public/assets/config.json +++ b/public/assets/config.json @@ -1,3 +1,4 @@ { - "api_endpoint": "http://127.0.0.1:5000" + "apiEndpoint": "http://127.0.0.1:5000", + "instanceId": "c4a88541-2a25-4896-a1f4-65dd7e88fab3" } diff --git a/src/js/pensieveClient.js b/src/js/apiClient.js similarity index 52% rename from src/js/pensieveClient.js rename to src/js/apiClient.js index 81aaeb58f..c6e696eb5 100644 --- a/src/js/pensieveClient.js +++ b/src/js/apiClient.js @@ -1,12 +1,16 @@ import Swagger from 'swagger-client'; -function makePensieveClient(apiEndpoint, instanceId){ +function makeApiClient(apiEndpoint, instanceId){ + // NOTE: This is not production-ready. + // It implements an authentication call based on a hardcoded OIDC token and an instance ID set in the `config.json` file. + // This call returns a JWT token which allows the user to access "pensieve-api" resources that are permitted with that token. const request = { url: `${apiEndpoint}/api/v1/management/${instanceId}/token`, method: 'GET', - headers: { 'X-Management-Authentication-Token': 'coco' }, + headers: { 'X-Management-Authentication-Token': 'oidc.token' }, }; + // TODO: use refreshToken API return Swagger.http(request) .then((res) => { return Swagger(apiEndpoint + '/swagger.json', @@ -14,8 +18,8 @@ function makePensieveClient(apiEndpoint, instanceId){ }) .then(client => { client.spec.schemes = [apiEndpoint.split(':')[0]]; - const pensieveClient = client.apis['ui-facing']; - return pensieveClient; + const apiClient = client.apis['ui-facing']; + return apiClient; }) .catch(error => { throw new Error( @@ -23,4 +27,4 @@ function makePensieveClient(apiEndpoint, instanceId){ }); } -export default makePensieveClient; +export default makeApiClient; diff --git a/src/react/Routes.jsx b/src/react/Routes.jsx index fdedaee69..e31d817f4 100644 --- a/src/react/Routes.jsx +++ b/src/react/Routes.jsx @@ -58,14 +58,14 @@ class Routes extends React.Component{ // link: Groups, // selected: isSelected(location, '/groups'), // }, - { - link: Users, - selected: isSelected(location, '/users'), - }, - { - link: Data Browser, - selected: isSelected(location, '/databrowser'), - }, + // { + // link: Users, + // selected: isSelected(location, '/users'), + // }, + // { + // link: Data Browser, + // selected: isSelected(location, '/databrowser'), + // }, // { // link: Data Workflow, // selected: isSelected(location, '/workflow'), diff --git a/src/react/actions/auth.js b/src/react/actions/auth.js index 6c2f891d3..6008a4920 100644 --- a/src/react/actions/auth.js +++ b/src/react/actions/auth.js @@ -1,54 +1,42 @@ -import { handleApiError, handleClientError, listBuckets, listUsers, loadInstanceLatestStatus, loadInstanceStats} from './'; -import IAMClient from '../../js/IAMClient'; -import S3Client from '../../js/S3Client'; -import creds from '../../../creds'; -import makePensieveClient from '../../js/pensieveClient'; +import { handleApiError, handleClientError, loadInstanceLatestStatus, loadInstanceStats} from './'; +import makeApiClient from '../../js/apiClient'; -const apiEndpoint = 'http://127.0.0.1:5000'; - -export function login(instanceId, clients) { +export function login(instanceId, apiClient) { return { type: 'LOG_IN', instanceId, - clients, + apiClient, }; } -function getAuth() { - return new Promise((resolve) => { - return resolve({ - instanceId: creds.instanceId, - oidcToken: 'oidc', +function getConfig() { + return fetch('/config.json', { credentials: 'same-origin' }) + .then(response => response.json()) + // TODO: validate configuration file + .then((jsonResp) => { + return { + instanceId: jsonResp.instanceId, + apiEndpoint: jsonResp.apiEndpoint, + oidcToken: 'oidc', + }; }); - }); } export function loadCredentials() { return dispatch => { - return getAuth() + return getConfig() .then((resp) => { return Promise.all([ resp.instanceId, // TODO: use oidc token - makePensieveClient(apiEndpoint, resp.instanceId), - new IAMClient({ - accessKey: creds.accessKey, - secretKey: creds.secretKey, - }), - new S3Client({ - // MADEUP KEYS - accessKey: '82XRRF5KN3XBPOSXLVAB', - secretKey: 'PCJukX09Vk2D/LMdxnp4enETgaJuIIc2BC3T6CxV', - }), + makeApiClient(resp.apiEndpoint, resp.instanceId), ]); }) - .then(([instanceId, pensieveClient, iamClient, s3Client]) => { - dispatch(login(instanceId, {pensieveClient, iamClient, s3Client})); + .then(([instanceId, apiClient]) => { + dispatch(login(instanceId, apiClient)); return Promise.all([ dispatch(loadInstanceLatestStatus()), dispatch(loadInstanceStats()), - dispatch(listBuckets()), - dispatch(listUsers()), ]); }) .then(() => {}) diff --git a/src/react/actions/configuration.js b/src/react/actions/configuration.js index 71dabe6a2..e3edc23b2 100644 --- a/src/react/actions/configuration.js +++ b/src/react/actions/configuration.js @@ -1,7 +1,6 @@ // @noflow import { networkEnd, networkStart } from './network'; import type { ConfigurationOverlay } from '../../types/config'; -import creds from '../../../creds'; import { getClients } from '../utils/actions'; export function newConfiguration(configuration: ConfigurationOverlay) { @@ -13,8 +12,8 @@ export function newConfiguration(configuration: ConfigurationOverlay) { export function updateConfiguration() { return async (dispatch, getState) => { - const { pensieveClient, instanceId } = getClients(getState()); - return pensieveClient.getConfigurationOverlayView({ uuid: instanceId }) + const { apiClient, instanceId } = getClients(getState()); + return apiClient.getConfigurationOverlayView({ uuid: instanceId }) .then(res => { dispatch(newConfiguration(res.body)); }) diff --git a/src/react/actions/location.js b/src/react/actions/location.js index 7e49d1a52..ba6a2ae29 100644 --- a/src/react/actions/location.js +++ b/src/react/actions/location.js @@ -33,7 +33,7 @@ export function closeLocationDeleteDialog() { export function saveLocation(location: Location): ThunkStatePromisedAction { return (dispatch, getState) => { - const { pensieveClient, instanceId } = getClients(getState()); + const { apiClient, instanceId } = getClients(getState()); const params = { uuid: instanceId, location, @@ -42,9 +42,9 @@ export function saveLocation(location: Location): ThunkStatePromisedAction { dispatch(networkStart('Saving Location')); const op = location.objectId ? - pensieveClient.updateConfigurationOverlayLocation(params) + apiClient.updateConfigurationOverlayLocation(params) : - pensieveClient.createConfigurationOverlayLocation(params); + apiClient.createConfigurationOverlayLocation(params); return op.then(() => { batch(() => { dispatch(updateConfiguration()); @@ -58,7 +58,7 @@ export function saveLocation(location: Location): ThunkStatePromisedAction { export function deleteLocation(locationName: LocationName): ThunkStatePromisedAction { return (dispatch, getState) => { - const { pensieveClient, instanceId } = getClients(getState()); + const { apiClient, instanceId } = getClients(getState()); const params = { uuid: instanceId, locationName, @@ -66,7 +66,7 @@ export function deleteLocation(locationName: LocationName): ThunkStatePromisedAc dispatch(resetSelectLocation()); dispatch(networkStart('Deleting Location')); - return pensieveClient.deleteConfigurationOverlayLocation(params) + return apiClient.deleteConfigurationOverlayLocation(params) .then(() => { dispatch(updateConfiguration()); dispatch(closeLocationDeleteDialog()); diff --git a/src/react/actions/stats.js b/src/react/actions/stats.js index 77c09aec9..b09bd2a23 100644 --- a/src/react/actions/stats.js +++ b/src/react/actions/stats.js @@ -19,8 +19,8 @@ export function receiveInstanceStats(stats) { export function loadInstanceStats(){ return (dispatch, getState) => { - const { pensieveClient, instanceId } = getClients(getState()); - return pensieveClient.getInstanceStats({ uuid: instanceId}) + const { apiClient, instanceId } = getClients(getState()); + return apiClient.getInstanceStats({ uuid: instanceId}) .then(res => { dispatch(receiveInstanceStats(res.body)); }) @@ -31,8 +31,8 @@ export function loadInstanceStats(){ export function loadInstanceLatestStatus(){ return (dispatch, getState) => { - const { pensieveClient, instanceId } = getClients(getState()); - return pensieveClient.getLatestInstanceStatus({ uuid: instanceId}) + const { apiClient, instanceId } = getClients(getState()); + return apiClient.getLatestInstanceStatus({ uuid: instanceId}) .then(res => { dispatch(instanceStatus(res.body)); }) diff --git a/src/react/reducers/auth.js b/src/react/reducers/auth.js index cc8bf96d3..a8695b407 100644 --- a/src/react/reducers/auth.js +++ b/src/react/reducers/auth.js @@ -3,7 +3,7 @@ export default function auth(state = {}, action) { case 'LOG_IN': return { ...state, - clients: action.clients, + apiClient: action.apiClient, }; default: return state; diff --git a/src/react/utils/actions.js b/src/react/utils/actions.js index 9bfa7f4fa..509906eaa 100644 --- a/src/react/utils/actions.js +++ b/src/react/utils/actions.js @@ -3,7 +3,7 @@ import { Map } from 'immutable'; export function getClients(state) { return { - ...state.auth.clients, + apiClient: state.auth.apiClient, instanceId: state.instances.selectedId, }; }