diff --git a/client/coral-admin/src/index.js b/client/coral-admin/src/index.js index d0dfc5f9a..8cd7685f0 100644 --- a/client/coral-admin/src/index.js +++ b/client/coral-admin/src/index.js @@ -9,9 +9,10 @@ import App from './components/App'; import 'react-mdl/extra/material.js'; import './graphql'; -import {loadPluginsTranslations} from 'coral-framework/helpers/plugins'; +import {loadPluginsTranslations, injectPluginsReducers} from 'coral-framework/helpers/plugins'; loadPluginsTranslations(); +injectPluginsReducers(); render( diff --git a/client/coral-admin/src/reducers/index.js b/client/coral-admin/src/reducers/index.js index 3036d6271..04c8b6590 100644 --- a/client/coral-admin/src/reducers/index.js +++ b/client/coral-admin/src/reducers/index.js @@ -13,5 +13,5 @@ export default { community, moderation, install, - config + config, }; diff --git a/client/coral-admin/src/services/store.js b/client/coral-admin/src/services/store.js index 2ab9d3750..9815a0f70 100644 --- a/client/coral-admin/src/services/store.js +++ b/client/coral-admin/src/services/store.js @@ -14,14 +14,18 @@ if (window.devToolsExtension) { middlewares.push(window.devToolsExtension()); } +const coralReducers = { + ...mainReducer, + apollo: client.reducer() +}; + const store = createStore( - combineReducers({ - ...mainReducer, - apollo: client.reducer() - }), + combineReducers(coralReducers), {}, compose(...middlewares) ); +store.coralReducers = coralReducers; + window.coralStore = store; export default store; diff --git a/client/coral-embed-stream/src/index.js b/client/coral-embed-stream/src/index.js index 06d52649a..4dee04f1e 100644 --- a/client/coral-embed-stream/src/index.js +++ b/client/coral-embed-stream/src/index.js @@ -2,30 +2,29 @@ import React from 'react'; import {render} from 'react-dom'; import {ApolloProvider} from 'react-apollo'; -import {client} from 'coral-framework/services/client'; import {checkLogin} from 'coral-framework/actions/auth'; import './graphql'; import {addExternalConfig} from 'coral-embed-stream/src/actions/config'; - -import reducers from './reducers'; import {getStore, injectReducers} from 'coral-framework/services/store'; +import {client} from 'coral-framework/services/client'; import AppRouter from './AppRouter'; import {pym} from 'coral-framework'; -import {loadPluginsTranslations} from 'coral-framework/helpers/plugins'; +import {loadPluginsTranslations, injectPluginsReducers} from 'coral-framework/helpers/plugins'; +import reducers from './reducers'; const store = getStore(); loadPluginsTranslations(); +injectPluginsReducers(); injectReducers(reducers); // Don't run this in the popup. if (!window.opener) { - store.dispatch(checkLogin()); - pym.sendMessage('getConfig'); pym.onMessage('config', (config) => { store.dispatch(addExternalConfig(JSON.parse(config))); + store.dispatch(checkLogin()); }); } diff --git a/client/coral-embed-stream/src/reducers/index.js b/client/coral-embed-stream/src/reducers/index.js index 590b87eea..5ddac4567 100644 --- a/client/coral-embed-stream/src/reducers/index.js +++ b/client/coral-embed-stream/src/reducers/index.js @@ -5,5 +5,5 @@ import stream from './stream'; export default { embed, stream, - config + config, }; diff --git a/client/coral-embed/src/index.js b/client/coral-embed/src/index.js index 570a63aed..65e77ad1d 100644 --- a/client/coral-embed/src/index.js +++ b/client/coral-embed/src/index.js @@ -147,6 +147,7 @@ function configurePymParent(pymParent, opts) { * @param {String} [opts.title] - Title of Stream (rendered in iframe) * @param {String} [opts.asset_url] - Asset URL * @param {String} [opts.asset_id] - Asset ID + * @param {String} [opts.auth_token] - (optional) A jwt representing the session */ Talk.render = function(el, opts) { if (!el) { diff --git a/client/coral-framework/helpers/plugins.js b/client/coral-framework/helpers/plugins.js index 02ee8c3a7..0eaecbadd 100644 --- a/client/coral-framework/helpers/plugins.js +++ b/client/coral-framework/helpers/plugins.js @@ -7,12 +7,7 @@ import pick from 'lodash/pick'; import plugins from 'pluginsConfig'; import {getDefinitionName, mergeDocuments} from 'coral-framework/utils'; import {loadTranslations} from 'coral-framework/services/i18n'; - -export const pluginReducers = merge( - ...plugins - .filter((o) => o.module.reducer) - .map((o) => ({...o.module.reducer})) -); +import {injectReducers} from 'coral-framework/services/store'; /** * Returns React Elements for given slot. @@ -98,3 +93,12 @@ function getTranslations() { export function loadPluginsTranslations() { getTranslations().forEach((t) => loadTranslations(t)); } + +export function injectPluginsReducers() { + const reducers = merge( + ...plugins + .filter((o) => o.module.reducer) + .map((o) => ({...o.module.reducer})) + ); + injectReducers(reducers); +} diff --git a/client/coral-framework/helpers/request.js b/client/coral-framework/helpers/request.js index 0e15003e1..57e3a6cde 100644 --- a/client/coral-framework/helpers/request.js +++ b/client/coral-framework/helpers/request.js @@ -1,6 +1,30 @@ import bowser from 'bowser'; import * as Storage from './storage'; import merge from 'lodash/merge'; +import {getStore} from 'coral-framework/services/store'; + +/** + * getAuthToken returns the active auth token or null + * Note: this method does not have access to the cookie based token used by + * browsers that don't allow us to use cross domain iframe local storage. + * @return {string|null} + */ +export const getAuthToken = () => { + let state = getStore().getState(); + + if (state.config.auth_token) { + + // if an auth_token exists in config, use it. + return state.config.auth_token; + + } else if (!bowser.safari && !bowser.ios) { + + // Use local storage auth tokens where there's a stable api. + return Storage.getItem('token'); + } + + return null; +}; const buildOptions = (inputOptions = {}) => { const defaultOptions = { @@ -14,12 +38,10 @@ const buildOptions = (inputOptions = {}) => { let options = merge({}, defaultOptions, inputOptions); - if (!bowser.safari && !bowser.ios) { - let authorization = Storage.getItem('token'); - - if (authorization) { - options.headers.Authorization = `Bearer ${authorization}`; - } + // Apply authToken header + let authToken = getAuthToken(); + if (authToken !== null) { + options.headers.Authorization = `Bearer ${authToken}`; } if (options.method.toLowerCase() !== 'get') { diff --git a/client/coral-framework/reducers/index.js b/client/coral-framework/reducers/index.js index d5b66bbae..8928cae93 100644 --- a/client/coral-framework/reducers/index.js +++ b/client/coral-framework/reducers/index.js @@ -2,12 +2,10 @@ import auth from './auth'; import user from './user'; import asset from './asset'; import {reducer as commentBox} from '../../coral-plugin-commentbox'; -import {pluginReducers} from '../helpers/plugins'; export default { auth, user, asset, commentBox, - ...pluginReducers }; diff --git a/client/coral-framework/services/transport.js b/client/coral-framework/services/transport.js index 0c430a021..f11c20888 100644 --- a/client/coral-framework/services/transport.js +++ b/client/coral-framework/services/transport.js @@ -1,6 +1,5 @@ import {createNetworkInterface} from 'apollo-client'; -import * as Storage from '../helpers/storage'; -import bowser from 'bowser'; +import {getAuthToken} from '../helpers/request'; //============================================================================== // NETWORK INTERFACE @@ -23,8 +22,9 @@ networkInterface.use([{ req.options.headers = {}; // Create the header object if needed. } - if (!bowser.safari && !bowser.ios) { - req.options.headers['authorization'] = `Bearer ${Storage.getItem('token')}`; + let authToken = getAuthToken(); + if (authToken) { + req.options.headers['authorization'] = `Bearer ${authToken}`; } next(); diff --git a/plugins/coral-plugin-auth/client/components/SignInContainer.js b/plugins/coral-plugin-auth/client/components/SignInContainer.js index 6f3c460bb..6950f4124 100644 --- a/plugins/coral-plugin-auth/client/components/SignInContainer.js +++ b/plugins/coral-plugin-auth/client/components/SignInContainer.js @@ -18,7 +18,6 @@ import { facebookCallback, invalidForm, validForm, - checkLogin } from 'coral-framework/actions/auth'; class SignInContainer extends React.Component { @@ -38,10 +37,6 @@ class SignInContainer extends React.Component { }; } - componentWillMount() { - this.props.checkLogin(); - } - componentDidMount() { window.addEventListener('storage', this.handleAuth); @@ -187,7 +182,6 @@ const mapStateToProps = (state) => ({ const mapDispatchToProps = (dispatch) => bindActionCreators( { - checkLogin, facebookCallback, fetchSignUp, fetchSignIn, diff --git a/views/article.ejs b/views/article.ejs index bc29467f1..c216f158d 100644 --- a/views/article.ejs +++ b/views/article.ejs @@ -29,6 +29,7 @@ talk: '/', asset_url: '<%= asset_url ? asset_url : '' %>', asset_id: '<%= asset_id ? asset_id : '' %>', + auth_token: '', plugin_config: { test: 'data', debug: false