mirror of
https://github.com/wassname/talk.git
synced 2026-07-08 05:23:06 +08:00
Merge branch 'master' into purge-config-auth-token
This commit is contained in:
+3
-2
@@ -13,6 +13,7 @@ public
|
||||
!plugins/talk-plugin-facebook-auth
|
||||
!plugins/talk-plugin-featured-comments
|
||||
!plugins/talk-plugin-flag-details
|
||||
!plugins/talk-plugin-google-auth
|
||||
!plugins/talk-plugin-ignore-user
|
||||
!plugins/talk-plugin-like
|
||||
!plugins/talk-plugin-love
|
||||
@@ -21,6 +22,7 @@ public
|
||||
!plugins/talk-plugin-moderation-actions
|
||||
!plugins/talk-plugin-offtopic
|
||||
!plugins/talk-plugin-permalink
|
||||
!plugins/talk-plugin-profile-settings
|
||||
!plugins/talk-plugin-remember-sort
|
||||
!plugins/talk-plugin-respect
|
||||
!plugins/talk-plugin-sort-most-liked
|
||||
@@ -31,5 +33,4 @@ public
|
||||
!plugins/talk-plugin-sort-oldest
|
||||
!plugins/talk-plugin-subscriber
|
||||
!plugins/talk-plugin-toxic-comments
|
||||
!plugins/talk-plugin-viewing-options
|
||||
!plugins/talk-plugin-profile-settings
|
||||
!plugins/talk-plugin-viewing-options
|
||||
@@ -1,14 +1,34 @@
|
||||
import { HANDLE_SUCCESSFUL_LOGIN } from 'coral-framework/constants/auth';
|
||||
import { getStaticConfiguration } from 'coral-framework/services/staticConfiguration';
|
||||
import { createPostMessage } from 'coral-framework/services/postMessage';
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
// Get the auth element and parse it as JSON by decoding it.
|
||||
const auth = document.getElementById('auth');
|
||||
const doc = document.implementation.createHTMLDocument('');
|
||||
doc.body.innerHTML = auth.innerText;
|
||||
try {
|
||||
const staticConfig = getStaticConfiguration();
|
||||
const { STATIC_ORIGIN: origin } = staticConfig;
|
||||
const postMessage = createPostMessage(origin);
|
||||
|
||||
// Set the item in localStorage.
|
||||
localStorage.setItem('auth', doc.body.textContent);
|
||||
// Get the auth element and parse it as JSON by decoding it.
|
||||
const auth = document.getElementById('auth');
|
||||
const doc = document.implementation.createHTMLDocument('');
|
||||
doc.body.innerHTML = auth.innerText;
|
||||
|
||||
// Close the window.
|
||||
setTimeout(() => {
|
||||
window.close();
|
||||
}, 50);
|
||||
// Auth state is contained within the node.
|
||||
const { err, data } = JSON.parse(doc.body.textContent);
|
||||
if (err) {
|
||||
// TODO: send back the error message.
|
||||
console.error(err);
|
||||
} else {
|
||||
// The data will contain a user and a token.
|
||||
const { user, token } = data;
|
||||
|
||||
// Send the state back.
|
||||
postMessage.post(HANDLE_SUCCESSFUL_LOGIN, { user, token });
|
||||
}
|
||||
} finally {
|
||||
// Always close the window.
|
||||
setTimeout(() => {
|
||||
window.close();
|
||||
}, 50);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
import * as actions from '../constants/asset';
|
||||
import { notify } from 'coral-framework/actions/notification';
|
||||
|
||||
import t from 'coral-framework/services/i18n';
|
||||
|
||||
export const fetchAssetRequest = () => ({ type: actions.FETCH_ASSET_REQUEST });
|
||||
export const fetchAssetSuccess = asset => ({
|
||||
type: actions.FETCH_ASSET_SUCCESS,
|
||||
asset,
|
||||
});
|
||||
export const fetchAssetFailure = error => ({
|
||||
type: actions.FETCH_ASSET_FAILURE,
|
||||
error,
|
||||
});
|
||||
|
||||
const updateAssetSettingsRequest = () => ({
|
||||
type: actions.UPDATE_ASSET_SETTINGS_REQUEST,
|
||||
});
|
||||
const updateAssetSettingsSuccess = settings => ({
|
||||
type: actions.UPDATE_ASSET_SETTINGS_SUCCESS,
|
||||
settings,
|
||||
});
|
||||
const updateAssetSettingsFailure = error => ({
|
||||
type: actions.UPDATE_ASSET_SETTINGS_FAILURE,
|
||||
error,
|
||||
});
|
||||
|
||||
export const updateConfiguration = newConfig => (
|
||||
dispatch,
|
||||
getState,
|
||||
{ rest }
|
||||
) => {
|
||||
const assetId = getState().asset.id;
|
||||
dispatch(updateAssetSettingsRequest());
|
||||
rest(`/assets/${assetId}/settings`, { method: 'PUT', body: newConfig })
|
||||
.then(() => {
|
||||
dispatch(notify('success', t('framework.success_update_settings')));
|
||||
dispatch(updateAssetSettingsSuccess(newConfig));
|
||||
})
|
||||
.catch(error => {
|
||||
console.error(error);
|
||||
dispatch(updateAssetSettingsFailure(error));
|
||||
});
|
||||
};
|
||||
|
||||
export const updateOpenStream = closedBody => (
|
||||
dispatch,
|
||||
getState,
|
||||
{ rest }
|
||||
) => {
|
||||
const assetId = getState().asset.id;
|
||||
dispatch(fetchAssetRequest());
|
||||
rest(`/assets/${assetId}/status`, { method: 'PUT', body: closedBody })
|
||||
.then(() => {
|
||||
dispatch(notify('success', t('framework.success_update_settings')));
|
||||
dispatch(fetchAssetSuccess(closedBody));
|
||||
})
|
||||
.catch(error => {
|
||||
console.error(error);
|
||||
dispatch(fetchAssetFailure(error));
|
||||
});
|
||||
};
|
||||
|
||||
const openStream = () => ({ type: actions.OPEN_COMMENTS });
|
||||
const closeStream = () => ({ type: actions.CLOSE_COMMENTS });
|
||||
|
||||
export const updateOpenStatus = status => dispatch => {
|
||||
if (status === 'open') {
|
||||
dispatch(openStream());
|
||||
dispatch(updateOpenStream({ closedAt: null }));
|
||||
} else {
|
||||
dispatch(closeStream());
|
||||
dispatch(updateOpenStream({ closedAt: new Date().getTime() }));
|
||||
}
|
||||
};
|
||||
@@ -1,6 +0,0 @@
|
||||
import { ADD_EXTERNAL_CONFIG } from '../constants/config';
|
||||
|
||||
export const addExternalConfig = config => ({
|
||||
type: ADD_EXTERNAL_CONFIG,
|
||||
config,
|
||||
});
|
||||
@@ -1,14 +1,10 @@
|
||||
import * as actions from '../constants/login';
|
||||
import { checkLogin } from 'coral-framework/actions/auth';
|
||||
|
||||
export const showSignInDialog = () => ({
|
||||
type: actions.SHOW_SIGNIN_DIALOG,
|
||||
});
|
||||
|
||||
export const hideSignInDialog = () => dispatch => {
|
||||
dispatch(checkLogin());
|
||||
dispatch({ type: actions.HIDE_SIGNIN_DIALOG });
|
||||
};
|
||||
export const hideSignInDialog = () => ({ type: actions.HIDE_SIGNIN_DIALOG });
|
||||
|
||||
export const focusSignInDialog = () => ({
|
||||
type: actions.FOCUS_SIGNIN_DIALOG,
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
export const FETCH_ASSET_REQUEST = 'FETCH_ASSET_REQUEST';
|
||||
export const FETCH_ASSET_FAILURE = 'FETCH_ASSET_FAILURE';
|
||||
export const FETCH_ASSET_SUCCESS = 'FETCH_ASSET_SUCCESS';
|
||||
|
||||
export const UPDATE_ASSET_SETTINGS_REQUEST = 'UPDATE_ASSET_SETTINGS_REQUEST';
|
||||
export const UPDATE_ASSET_SETTINGS_SUCCESS = 'UPDATE_ASSET_SETTINGS_SUCCESS';
|
||||
export const UPDATE_ASSET_SETTINGS_FAILURE = 'UPDATE_ASSET_SETTINGS_FAILURE';
|
||||
|
||||
export const OPEN_COMMENTS = 'OPEN_COMMENTS';
|
||||
export const CLOSE_COMMENTS = 'CLOSE_COMMENTS';
|
||||
@@ -1 +0,0 @@
|
||||
export const ADD_EXTERNAL_CONFIG = 'ADD_EXTERNAL_CONFIG';
|
||||
@@ -2,7 +2,6 @@ import React from 'react';
|
||||
import { compose, gql } from 'react-apollo';
|
||||
import { connect } from 'react-redux';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import isEqual from 'lodash/isEqual';
|
||||
import get from 'lodash/get';
|
||||
import branch from 'recompose/branch';
|
||||
import renderComponent from 'recompose/renderComponent';
|
||||
@@ -14,12 +13,11 @@ import {
|
||||
hideSignInDialog,
|
||||
} from '../actions/login';
|
||||
import { updateStatus } from 'coral-framework/actions/auth';
|
||||
import { fetchAssetSuccess } from '../actions/asset';
|
||||
import {
|
||||
getDefinitionName,
|
||||
getSlotFragmentSpreads,
|
||||
} from 'coral-framework/utils';
|
||||
import { withQuery } from 'coral-framework/hocs';
|
||||
import { withQuery, withPopupAuthHandler } from 'coral-framework/hocs';
|
||||
import Embed from '../components/Embed';
|
||||
import Stream from '../tabs/stream/containers/Stream';
|
||||
import AutomaticAssetClosure from './AutomaticAssetClosure';
|
||||
@@ -107,12 +105,6 @@ class EmbedContainer extends React.Component {
|
||||
this.props.data.refetch();
|
||||
this.resubscribe(nextProps);
|
||||
}
|
||||
|
||||
const { fetchAssetSuccess } = this.props;
|
||||
if (!isEqual(nextProps.root.asset, this.props.root.asset)) {
|
||||
// TODO: remove asset data from redux store.
|
||||
fetchAssetSuccess(nextProps.root.asset);
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
@@ -298,7 +290,6 @@ EmbedContainer.propTypes = {
|
||||
activeTab: PropTypes.string,
|
||||
parentUrl: PropTypes.string,
|
||||
data: PropTypes.object,
|
||||
fetchAssetSuccess: PropTypes.func,
|
||||
showSignInDialog: PropTypes.bool,
|
||||
signInDialogFocus: PropTypes.bool,
|
||||
};
|
||||
@@ -322,7 +313,6 @@ const mapDispatchToProps = dispatch =>
|
||||
bindActionCreators(
|
||||
{
|
||||
setActiveTab,
|
||||
fetchAssetSuccess,
|
||||
notify,
|
||||
focusSignInDialog,
|
||||
blurSignInDialog,
|
||||
@@ -333,6 +323,7 @@ const mapDispatchToProps = dispatch =>
|
||||
);
|
||||
|
||||
export default compose(
|
||||
withPopupAuthHandler,
|
||||
connect(mapStateToProps, mapDispatchToProps),
|
||||
branch(props => !props.checkedInitialLogin, renderComponent(Spinner)),
|
||||
withEmbedQuery
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
import * as actions from '../constants/asset';
|
||||
|
||||
const initialState = {
|
||||
closedAt: null,
|
||||
settings: null,
|
||||
title: null,
|
||||
url: null,
|
||||
features: {},
|
||||
status: 'open',
|
||||
moderation: null,
|
||||
};
|
||||
|
||||
export default function asset(state = initialState, action) {
|
||||
switch (action.type) {
|
||||
case actions.FETCH_ASSET_SUCCESS:
|
||||
return {
|
||||
...state,
|
||||
...action.asset,
|
||||
};
|
||||
case actions.UPDATE_ASSET_SETTINGS_SUCCESS:
|
||||
return {
|
||||
...state,
|
||||
settings: action.settings,
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
import { ADD_EXTERNAL_CONFIG } from '../constants/config';
|
||||
|
||||
const initialState = {};
|
||||
|
||||
export default function config(state = initialState, action) {
|
||||
switch (action.type) {
|
||||
case ADD_EXTERNAL_CONFIG:
|
||||
return {
|
||||
...state,
|
||||
...action.config,
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
import login from './login';
|
||||
import asset from './asset';
|
||||
import embed from './embed';
|
||||
import configure from './configure';
|
||||
import stream from './stream';
|
||||
@@ -7,7 +6,6 @@ import profile from './profile';
|
||||
|
||||
export default {
|
||||
login,
|
||||
asset,
|
||||
embed,
|
||||
configure,
|
||||
stream,
|
||||
|
||||
@@ -63,13 +63,25 @@ export const setAuthToken = token => (dispatch, _, { localStorage }) => {
|
||||
export const handleSuccessfulLogin = (user, token) => (
|
||||
dispatch,
|
||||
_,
|
||||
{ client, localStorage }
|
||||
{ client, localStorage, postMessage }
|
||||
) => {
|
||||
const { exp } = jwtDecode(token);
|
||||
|
||||
if (localStorage) {
|
||||
localStorage.setItem('exp', jwtDecode(token).exp);
|
||||
localStorage.setItem('exp', exp);
|
||||
localStorage.setItem('token', token);
|
||||
}
|
||||
|
||||
// Send the message via the messages service to the window.opener if it
|
||||
// exists.
|
||||
if (window.opener) {
|
||||
postMessage.post(
|
||||
actions.HANDLE_SUCCESSFUL_LOGIN,
|
||||
{ user, token },
|
||||
window.opener
|
||||
);
|
||||
}
|
||||
|
||||
client.resetWebsocket();
|
||||
|
||||
dispatch({
|
||||
|
||||
@@ -17,6 +17,7 @@ class TalkProvider extends React.Component {
|
||||
store: this.props.store,
|
||||
pymLocalStorage: this.props.pymLocalStorage,
|
||||
pymSessionStorage: this.props.pymSessionStorage,
|
||||
postMessage: this.props.postMessage,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -39,6 +40,7 @@ TalkProvider.childContextTypes = {
|
||||
pymSessionStorage: PropTypes.object,
|
||||
history: PropTypes.object,
|
||||
store: PropTypes.object,
|
||||
postMessage: PropTypes.object,
|
||||
};
|
||||
|
||||
TalkProvider.propTypes = TalkProvider.childContextTypes;
|
||||
|
||||
@@ -698,7 +698,7 @@ export const withCloseAsset = withMutation(
|
||||
const fragmentId = `Asset_${id}`;
|
||||
const data = {
|
||||
__typename: 'Asset',
|
||||
closedAt: new Date(),
|
||||
closedAt: new Date().toISOString(),
|
||||
isClosed: true,
|
||||
};
|
||||
proxy.writeFragment({ fragment, id: fragmentId, data });
|
||||
|
||||
@@ -10,6 +10,7 @@ export { default as withSignIn } from './withSignIn';
|
||||
export { default as withSignUp } from './withSignUp';
|
||||
export { default as withForgotPassword } from './withForgotPassword';
|
||||
export { default as withSetUsername } from './withSetUsername';
|
||||
export { default as withPopupAuthHandler } from './withPopupAuthHandler';
|
||||
export {
|
||||
default as withResendEmailConfirmation,
|
||||
} from './withResendEmailConfirmation';
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
import React from 'react';
|
||||
import hoistStatics from 'recompose/hoistStatics';
|
||||
import PropTypes from 'prop-types';
|
||||
import { HANDLE_SUCCESSFUL_LOGIN } from 'coral-framework/constants/auth';
|
||||
import {
|
||||
handleSuccessfulLogin,
|
||||
setAuthToken,
|
||||
} from 'coral-framework/actions/auth';
|
||||
|
||||
/**
|
||||
* WithPopupAuthHandler listens to successful logins over
|
||||
* the `postMessage` service.
|
||||
*/
|
||||
export default hoistStatics(WrappedComponent => {
|
||||
class WithPopupAuthHandler extends React.Component {
|
||||
static contextTypes = {
|
||||
store: PropTypes.object,
|
||||
postMessage: PropTypes.object,
|
||||
};
|
||||
|
||||
constructor(props, context) {
|
||||
super(props, context);
|
||||
context.postMessage.subscribe(this.handleAuth);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.context.postMessage.unsubscribe(this.handleAuth);
|
||||
}
|
||||
|
||||
handleAuth = ({ name, data }) => {
|
||||
if (name !== HANDLE_SUCCESSFUL_LOGIN) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { store } = this.context;
|
||||
// data will contain the user and token.
|
||||
const { user, token } = data;
|
||||
|
||||
if (user && token) {
|
||||
store.dispatch(handleSuccessfulLogin(user, token));
|
||||
} else if (token) {
|
||||
store.dispatch(setAuthToken(token));
|
||||
} else {
|
||||
console.error('Invalid auth data supplied', data);
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
return <WrappedComponent {...this.props} />;
|
||||
}
|
||||
}
|
||||
|
||||
return WithPopupAuthHandler;
|
||||
});
|
||||
+5
-1
@@ -14,6 +14,7 @@ import { createPluginsService } from './plugins';
|
||||
import { createNotificationService } from './notification';
|
||||
import { createGraphQLRegistry } from './graphqlRegistry';
|
||||
import { createGraphQLService } from './graphql';
|
||||
import { createPostMessage } from './postMessage';
|
||||
import globalFragments from 'coral-framework/graphql/fragments';
|
||||
import {
|
||||
createStorage,
|
||||
@@ -118,7 +119,7 @@ export async function createContext({
|
||||
});
|
||||
|
||||
const staticConfig = getStaticConfiguration();
|
||||
let { LIVE_URI: liveUri } = staticConfig;
|
||||
let { LIVE_URI: liveUri, STATIC_ORIGIN: origin } = staticConfig;
|
||||
if (liveUri == null) {
|
||||
// The protocol must match the origin protocol, secure/insecure.
|
||||
const protocol = location.protocol === 'https:' ? 'wss' : 'ws';
|
||||
@@ -128,6 +129,8 @@ export async function createContext({
|
||||
liveUri = `${protocol}://${location.host}${BASE_PATH}api/v1/live`;
|
||||
}
|
||||
|
||||
const postMessage = createPostMessage(origin);
|
||||
|
||||
const client = createClient({
|
||||
uri: `${BASE_PATH}api/v1/graph/ql`,
|
||||
liveUri,
|
||||
@@ -158,6 +161,7 @@ export async function createContext({
|
||||
pymLocalStorage,
|
||||
pymSessionStorage,
|
||||
inIframe,
|
||||
postMessage,
|
||||
};
|
||||
|
||||
// Load framework fragments.
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
import set from 'lodash/set';
|
||||
import has from 'lodash/has';
|
||||
import get from 'lodash/get';
|
||||
import remove from 'lodash/remove';
|
||||
|
||||
/**
|
||||
* createPostMessage returns a service that deals with cross
|
||||
* window communication using the postMessage API.
|
||||
* @param {string} origin
|
||||
* @param {string} scope
|
||||
* @return {Object} postMessage service
|
||||
*/
|
||||
export function createPostMessage(origin, scope = 'client') {
|
||||
// Store a reference to each listener added.
|
||||
const listeners = {};
|
||||
|
||||
// withOriginCheck wraps a given handler for a messages event with a check to
|
||||
// see if the origin matches.
|
||||
const withOriginCheck = handler => {
|
||||
return event => {
|
||||
if (get(event, 'origin') !== origin) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (get(event, 'data.scope') !== scope) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Pass the handler the event details.
|
||||
handler(event);
|
||||
};
|
||||
};
|
||||
|
||||
// withParseData will parse the data.
|
||||
const withParseData = handler => {
|
||||
return event => {
|
||||
const data = get(event, 'data.data');
|
||||
const name = get(event, 'data.name');
|
||||
if (!data || !name) {
|
||||
return;
|
||||
}
|
||||
|
||||
handler({ data, name, event });
|
||||
};
|
||||
};
|
||||
|
||||
return {
|
||||
post(name, data, target = window.opener) {
|
||||
if (!target) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Serialize the message to be sent via postMessage.
|
||||
const msg = { name, data, scope };
|
||||
|
||||
// Send the message.
|
||||
target.postMessage(msg, origin);
|
||||
},
|
||||
subscribe: (handler, target = window) => {
|
||||
// If this handler is already attached to the target, detach it.
|
||||
if (has(listeners, [target, handler])) {
|
||||
this.unsubscribeFromMessages(handler, target);
|
||||
}
|
||||
|
||||
// Wrap the listener with a origin check.
|
||||
const listener = withOriginCheck(withParseData(handler));
|
||||
|
||||
// Save a reference to the compiled listener.
|
||||
set(listeners, [target, handler], listener);
|
||||
|
||||
// Attach the listener to the target.
|
||||
target.addEventListener('message', listener);
|
||||
},
|
||||
unsubscribe: (handler, target = window) => {
|
||||
if (!has(listeners, [target, handler])) {
|
||||
return;
|
||||
}
|
||||
|
||||
const listener = get(listeners, [target, handler]);
|
||||
|
||||
// Remove the listener from the target.
|
||||
target.removeEventListener('message', listener);
|
||||
|
||||
remove(listeners, [target, handler]);
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -1,9 +1,10 @@
|
||||
import uuid from 'uuid/v4';
|
||||
|
||||
function getStorage(type) {
|
||||
let storage = window[type],
|
||||
x = '__storage_test__';
|
||||
let storage;
|
||||
try {
|
||||
storage = window[type];
|
||||
const x = '__storage_test__';
|
||||
storage.setItem(x, x);
|
||||
storage.removeItem(x);
|
||||
} catch (e) {
|
||||
@@ -11,6 +12,8 @@ function getStorage(type) {
|
||||
e instanceof DOMException &&
|
||||
// everything except Firefox
|
||||
(e.code === 22 ||
|
||||
// SecurityError related to having 3rd party cookies disabled.
|
||||
e.code === 18 ||
|
||||
// Firefox
|
||||
|
||||
e.code === 1014 ||
|
||||
@@ -19,14 +22,18 @@ function getStorage(type) {
|
||||
// everything except Firefox
|
||||
e.name === 'QuotaExceededError' ||
|
||||
// Firefox
|
||||
e.name === 'NS_ERROR_DOM_QUOTA_REACHED') &&
|
||||
// acknowledge QuotaExceededError only if there's something already stored
|
||||
storage.length !== 0;
|
||||
e.name === 'NS_ERROR_DOM_QUOTA_REACHED');
|
||||
if (!ignore) {
|
||||
console.warning(e); // eslint-disable-line
|
||||
return null;
|
||||
console.warn(e);
|
||||
}
|
||||
|
||||
// When third party cookies are disabled, session storage is readable/
|
||||
// writable, but localStorage is not. Try to get the sessionStorage to use.
|
||||
if (type !== 'sessionStorage') {
|
||||
return getStorage('sessionStorage');
|
||||
}
|
||||
}
|
||||
|
||||
return storage;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
const SettingsService = require('../services/settings');
|
||||
|
||||
const { BASE_URL, BASE_PATH, MOUNT_PATH, STATIC_URL } = require('../url');
|
||||
const {
|
||||
BASE_URL,
|
||||
BASE_PATH,
|
||||
MOUNT_PATH,
|
||||
STATIC_URL,
|
||||
STATIC_ORIGIN,
|
||||
} = require('../url');
|
||||
|
||||
const { RECAPTCHA_PUBLIC, WEBSOCKET_LIVE_URI } = require('../config');
|
||||
|
||||
@@ -15,6 +21,7 @@ const TEMPLATE_LOCALS = {
|
||||
TALK_RECAPTCHA_PUBLIC: RECAPTCHA_PUBLIC,
|
||||
LIVE_URI: WEBSOCKET_LIVE_URI,
|
||||
STATIC_URL,
|
||||
STATIC_ORIGIN,
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -4,10 +4,6 @@ import Main from '../components/Main';
|
||||
import { connect } from 'plugin-api/beta/client/hocs';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import { setView } from '../actions';
|
||||
import {
|
||||
setAuthToken,
|
||||
handleSuccessfulLogin,
|
||||
} from 'plugin-api/beta/client/actions/auth';
|
||||
import * as views from '../enums/views';
|
||||
|
||||
class MainContainer extends React.Component {
|
||||
@@ -24,7 +20,6 @@ class MainContainer extends React.Component {
|
||||
|
||||
componentDidMount() {
|
||||
this.resizeHeight();
|
||||
this.listenToStorageChanges();
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps) {
|
||||
@@ -33,40 +28,6 @@ class MainContainer extends React.Component {
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
this.unlisten();
|
||||
}
|
||||
|
||||
listenToStorageChanges() {
|
||||
window.addEventListener('storage', this.handleAuth);
|
||||
}
|
||||
|
||||
unlisten() {
|
||||
window.removeEventListener('storage', this.handleAuth);
|
||||
}
|
||||
|
||||
// External logins store auth data into `auth`, we use it to detect
|
||||
// a successful sign in.
|
||||
handleAuth = e => {
|
||||
if (e.key === 'auth') {
|
||||
const { err, data } = JSON.parse(e.newValue);
|
||||
if (err) {
|
||||
console.error(err);
|
||||
} else if (data && data.token) {
|
||||
if (data.user) {
|
||||
this.props.handleSuccessfulLogin(data.user, data.token);
|
||||
} else {
|
||||
this.props.setAuthToken(data.token);
|
||||
}
|
||||
this.unlisten();
|
||||
localStorage.removeItem('auth');
|
||||
window.close();
|
||||
} else {
|
||||
console.error('auth was set, but did not contain a token');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
return <Main onResetView={this.resetView} view={this.props.view} />;
|
||||
}
|
||||
@@ -75,8 +36,6 @@ class MainContainer extends React.Component {
|
||||
MainContainer.propTypes = {
|
||||
view: PropTypes.string.isRequired,
|
||||
setView: PropTypes.func.isRequired,
|
||||
handleSuccessfulLogin: PropTypes.func.isRequired,
|
||||
setAuthToken: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
const mapStateToProps = ({ talkPluginAuth: state }) => ({
|
||||
@@ -87,8 +46,6 @@ const mapDispatchToProps = dispatch =>
|
||||
bindActionCreators(
|
||||
{
|
||||
setView,
|
||||
handleSuccessfulLogin,
|
||||
setAuthToken,
|
||||
},
|
||||
dispatch
|
||||
);
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
export const loginWithFacebook = () => (dispatch, _, { rest }) => {
|
||||
window.open(
|
||||
`${rest.uri}/auth/facebook`,
|
||||
'Continue with Facebook',
|
||||
'menubar=0,resizable=0,width=500,height=500,top=200,left=500'
|
||||
);
|
||||
window.location = `${rest.uri}/auth/facebook`;
|
||||
};
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
export const loginWithGoogle = () => (dispatch, _, { rest }) => {
|
||||
window.open(
|
||||
`${rest.uri}/auth/google`,
|
||||
'Continue with Google',
|
||||
'menubar=0,resizable=0,width=500,height=500,top=200,left=500'
|
||||
);
|
||||
window.location = `${rest.uri}/auth/google`;
|
||||
};
|
||||
|
||||
@@ -3,7 +3,5 @@ import GoogleButton from '../containers/GoogleButton';
|
||||
import { t } from 'plugin-api/beta/client/services';
|
||||
|
||||
export default () => {
|
||||
return (
|
||||
<GoogleButton>{t('talk-plugin-google-auth.sign_in')}</GoogleButton>
|
||||
);
|
||||
return <GoogleButton>{t('talk-plugin-google-auth.sign_in')}</GoogleButton>;
|
||||
};
|
||||
|
||||
@@ -3,7 +3,5 @@ import GoogleButton from '../containers/GoogleButton';
|
||||
import { t } from 'plugin-api/beta/client/services';
|
||||
|
||||
export default () => {
|
||||
return (
|
||||
<GoogleButton>{t('talk-plugin-google-auth.sign_up')}</GoogleButton>
|
||||
);
|
||||
return <GoogleButton>{t('talk-plugin-google-auth.sign_up')}</GoogleButton>;
|
||||
};
|
||||
|
||||
@@ -18,9 +18,12 @@ const MOUNT_PATH = ROOT_URL_MOUNT_PATH ? BASE_PATH : '/';
|
||||
// The STATIC_URL is the url where static assets should be loaded from.
|
||||
const STATIC_URL = trailingSlash(STATIC_URI);
|
||||
|
||||
const STATIC_ORIGIN = new URL(STATIC_URI).origin;
|
||||
|
||||
module.exports = {
|
||||
BASE_URL,
|
||||
BASE_PATH,
|
||||
MOUNT_PATH,
|
||||
STATIC_URL,
|
||||
STATIC_ORIGIN,
|
||||
};
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<%- include partials/data %>
|
||||
</head>
|
||||
<body>
|
||||
<script type="application/json" id="auth"><%- encodeJSONForHTML(auth) %></script>
|
||||
<script type="text/javascript" src="<%= STATIC_URL %>static/coral-auth-callback/bundle.js"></script>
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
<%_ if (data != null) { _%>
|
||||
<script id="data" type="application/json"><%- JSON.stringify(data) %></script>
|
||||
<%_ } _%>
|
||||
@@ -18,7 +18,5 @@
|
||||
<%_ if (locals.customCssUrl) { _%>
|
||||
<link href="<%= customCssUrl %>" rel="stylesheet" type="text/css">
|
||||
<%_ } _%>
|
||||
<%_ if (data != null) { _%>
|
||||
<script id="data" type="application/json"><%- JSON.stringify(data) %></script>
|
||||
<%_ } _%>
|
||||
<%- include data %>
|
||||
<base href="<%= BASE_URL %>"/>
|
||||
Reference in New Issue
Block a user