mirror of
https://github.com/wassname/talk.git
synced 2026-07-29 11:28:24 +08:00
Finish refactor embed stream auth
This commit is contained in:
@@ -1,25 +0,0 @@
|
||||
import React from 'react';
|
||||
import { Router, Route } from 'react-router';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import Embed from './containers/Embed';
|
||||
import { LoginContainer } from './containers/LoginContainer';
|
||||
|
||||
const routes = (
|
||||
<div>
|
||||
<Route exact path="/embed/stream/login" component={LoginContainer} />
|
||||
<Route path="*" component={Embed} />
|
||||
</div>
|
||||
);
|
||||
|
||||
class AppRouter extends React.Component {
|
||||
static contextTypes = {
|
||||
history: PropTypes.object,
|
||||
};
|
||||
|
||||
render() {
|
||||
return <Router history={this.context.history} routes={routes} />;
|
||||
}
|
||||
}
|
||||
|
||||
export default AppRouter;
|
||||
@@ -3,12 +3,7 @@ import bowser from 'bowser';
|
||||
import * as actions from '../constants/login';
|
||||
import { notify } from 'coral-framework/actions/notification';
|
||||
import t from 'coral-framework/services/i18n';
|
||||
import get from 'lodash/get';
|
||||
|
||||
export const updateStatus = status => ({
|
||||
type: actions.UPDATE_STATUS,
|
||||
status,
|
||||
});
|
||||
import { checkLogin } from 'coral-framework/actions/auth';
|
||||
|
||||
export const showSignInDialog = () => ({
|
||||
type: actions.SHOW_SIGNIN_DIALOG,
|
||||
@@ -27,10 +22,6 @@ export const hideSignInDialog = () => dispatch => {
|
||||
dispatch({ type: actions.HIDE_SIGNIN_DIALOG });
|
||||
};
|
||||
|
||||
export const resetSignInDialog = () => dispatch => {
|
||||
dispatch({ type: actions.HIDE_SIGNIN_DIALOG });
|
||||
};
|
||||
|
||||
export const focusSignInDialog = () => ({
|
||||
type: actions.FOCUS_SIGNIN_DIALOG,
|
||||
});
|
||||
@@ -39,6 +30,17 @@ export const blurSignInDialog = () => ({
|
||||
type: actions.BLUR_SIGNIN_DIALOG,
|
||||
});
|
||||
|
||||
// TODO: remove the rest.
|
||||
|
||||
export const updateStatus = status => ({
|
||||
type: actions.UPDATE_STATUS,
|
||||
status,
|
||||
});
|
||||
|
||||
export const resetSignInDialog = () => dispatch => {
|
||||
dispatch({ type: actions.HIDE_SIGNIN_DIALOG });
|
||||
};
|
||||
|
||||
export const showCreateUsernameDialog = () => ({
|
||||
type: actions.SHOW_CREATEUSERNAME_DIALOG,
|
||||
});
|
||||
@@ -276,70 +278,6 @@ export const logout = () => async (
|
||||
pym.sendMessage('coral-auth-changed');
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
// CHECK LOGIN
|
||||
//==============================================================================
|
||||
|
||||
const checkLoginRequest = () => ({ type: actions.CHECK_LOGIN_REQUEST });
|
||||
const checkLoginFailure = error => ({
|
||||
type: actions.CHECK_LOGIN_FAILURE,
|
||||
error,
|
||||
});
|
||||
|
||||
const checkLoginSuccess = (user, isAdmin) => ({
|
||||
type: actions.CHECK_LOGIN_SUCCESS,
|
||||
user,
|
||||
isAdmin,
|
||||
});
|
||||
|
||||
const ErrNotLoggedIn = new Error('Not logged in');
|
||||
|
||||
export const checkLogin = () => (
|
||||
dispatch,
|
||||
_,
|
||||
{ rest, client, pym, localStorage }
|
||||
) => {
|
||||
dispatch(checkLoginRequest());
|
||||
rest('/auth')
|
||||
.then(result => {
|
||||
if (!result.user) {
|
||||
if (localStorage) {
|
||||
localStorage.removeItem('token');
|
||||
localStorage.removeItem('exp');
|
||||
}
|
||||
throw ErrNotLoggedIn;
|
||||
}
|
||||
|
||||
// Reset the websocket.
|
||||
client.resetWebsocket();
|
||||
|
||||
dispatch(checkLoginSuccess(result.user));
|
||||
pym.sendMessage('coral-auth-changed', JSON.stringify(result.user));
|
||||
|
||||
// This is for login via social. Usernames should be set.
|
||||
if (
|
||||
get(result.user, 'status.username.status') === 'UNSET' &&
|
||||
!get(result.user, 'status.banned.status')
|
||||
) {
|
||||
dispatch(showCreateUsernameDialog());
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
if (error !== ErrNotLoggedIn) {
|
||||
console.error(error);
|
||||
}
|
||||
if (error.status && error.status === 401 && localStorage) {
|
||||
// Unauthorized.
|
||||
localStorage.removeItem('token');
|
||||
localStorage.removeItem('exp');
|
||||
}
|
||||
const errorMessage = error.translation_key
|
||||
? t(`error.${error.translation_key}`)
|
||||
: error.toString();
|
||||
dispatch(checkLoginFailure(errorMessage));
|
||||
});
|
||||
};
|
||||
|
||||
export const validForm = () => ({ type: actions.VALID_FORM });
|
||||
export const invalidForm = error => ({ type: actions.INVALID_FORM, error });
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ export default class Embed extends React.Component {
|
||||
blurSignInDialog,
|
||||
focusSignInDialog,
|
||||
hideSignInDialog,
|
||||
router: { location: { query: { parentUrl } } },
|
||||
parentUrl,
|
||||
} = this.props;
|
||||
const hasHighlightedComment = !!commentId;
|
||||
|
||||
@@ -75,9 +75,7 @@ export default class Embed extends React.Component {
|
||||
<AutomaticAssetClosure asset={asset} />
|
||||
<IfSlotIsNotEmpty slot="login">
|
||||
<Popup
|
||||
href={`embed/stream/login?parentUrl=${encodeURIComponent(
|
||||
parentUrl
|
||||
)}`}
|
||||
href={`login?parentUrl=${encodeURIComponent(parentUrl)}`}
|
||||
title="Login"
|
||||
features="menubar=0,resizable=0,width=500,height=550,top=200,left=500"
|
||||
open={showSignInDialog}
|
||||
@@ -138,7 +136,7 @@ Embed.propTypes = {
|
||||
blurSignInDialog: PropTypes.func,
|
||||
focusSignInDialog: PropTypes.func,
|
||||
hideSignInDialog: PropTypes.func,
|
||||
router: PropTypes.object,
|
||||
parentUrl: PropTypes.string,
|
||||
commentId: PropTypes.string,
|
||||
root: PropTypes.object,
|
||||
activeTab: PropTypes.string,
|
||||
|
||||
@@ -9,13 +9,11 @@ import renderComponent from 'recompose/renderComponent';
|
||||
|
||||
import { Spinner } from 'coral-ui';
|
||||
import {
|
||||
logout,
|
||||
checkLogin,
|
||||
focusSignInDialog,
|
||||
blurSignInDialog,
|
||||
hideSignInDialog,
|
||||
updateStatus,
|
||||
} from '../actions/login';
|
||||
import { updateStatus } from 'coral-framework/actions/auth';
|
||||
import { fetchAssetSuccess } from '../actions/asset';
|
||||
import {
|
||||
getDefinitionName,
|
||||
@@ -149,6 +147,7 @@ class EmbedContainer extends React.Component {
|
||||
data={this.props.data}
|
||||
showSignInDialog={this.props.showSignInDialog}
|
||||
signInDialogFocus={this.props.signInDialogFocus}
|
||||
parentUrl={this.props.parentUrl}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -297,6 +296,7 @@ EmbedContainer.propTypes = {
|
||||
commentId: PropTypes.string,
|
||||
root: PropTypes.object,
|
||||
activeTab: PropTypes.string,
|
||||
parentUrl: PropTypes.string,
|
||||
data: PropTypes.object,
|
||||
fetchAssetSuccess: PropTypes.func,
|
||||
showSignInDialog: PropTypes.bool,
|
||||
@@ -315,13 +315,12 @@ const mapStateToProps = state => ({
|
||||
sortBy: state.stream.sortBy,
|
||||
showSignInDialog: state.login.showSignInDialog,
|
||||
signInDialogFocus: state.login.signInDialogFocus,
|
||||
parentUrl: state.login.parentUrl,
|
||||
});
|
||||
|
||||
const mapDispatchToProps = dispatch =>
|
||||
bindActionCreators(
|
||||
{
|
||||
logout,
|
||||
checkLogin,
|
||||
setActiveTab,
|
||||
fetchAssetSuccess,
|
||||
notify,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import React from 'react';
|
||||
import { render } from 'react-dom';
|
||||
import Embed from './containers/Embed';
|
||||
|
||||
import graphqlExtension from './graphql';
|
||||
import { createContext } from 'coral-framework/services/bootstrap';
|
||||
import AppRouter from './AppRouter';
|
||||
import reducers from './reducers';
|
||||
import TalkProvider from 'coral-framework/components/TalkProvider';
|
||||
import pluginsConfig from 'pluginsConfig';
|
||||
@@ -16,7 +16,7 @@ async function main() {
|
||||
});
|
||||
render(
|
||||
<TalkProvider {...context}>
|
||||
<AppRouter />
|
||||
<Embed />
|
||||
</TalkProvider>,
|
||||
document.querySelector('#talk-embed-stream-container')
|
||||
);
|
||||
|
||||
@@ -3,11 +3,14 @@ import pym from 'coral-framework/services/pym';
|
||||
import merge from 'lodash/merge';
|
||||
|
||||
const initialState = {
|
||||
parentUrl: pym.parentUrl || location.href,
|
||||
showSignInDialog: false,
|
||||
signInDialogFocus: false,
|
||||
|
||||
// TODO: remove the rest
|
||||
isLoading: false,
|
||||
loggedIn: false,
|
||||
user: null,
|
||||
showSignInDialog: false,
|
||||
signInDialogFocus: false,
|
||||
showCreateUsernameDialog: false,
|
||||
checkedInitialLogin: false,
|
||||
view: 'SIGNIN',
|
||||
@@ -46,8 +49,16 @@ export default function login(state = initialState, action) {
|
||||
showSignInDialog: true,
|
||||
signInDialogFocus: true,
|
||||
};
|
||||
case actions.RESET_SIGNIN_DIALOG:
|
||||
|
||||
case actions.HIDE_SIGNIN_DIALOG:
|
||||
return {
|
||||
...state,
|
||||
showSignInDialog: false,
|
||||
signInDialogFocus: false,
|
||||
};
|
||||
|
||||
// TODO: remove the rest.
|
||||
case actions.RESET_SIGNIN_DIALOG:
|
||||
return {
|
||||
...state,
|
||||
isLoading: false,
|
||||
|
||||
@@ -14,7 +14,10 @@ import {
|
||||
withEditComment,
|
||||
} from 'coral-framework/graphql/mutations';
|
||||
|
||||
import { showSignInDialog, editName } from 'coral-embed-stream/src/actions/login';
|
||||
import {
|
||||
showSignInDialog,
|
||||
editName,
|
||||
} from 'coral-embed-stream/src/actions/login';
|
||||
import { notify } from 'coral-framework/actions/notification';
|
||||
import {
|
||||
setActiveReplyBox,
|
||||
|
||||
@@ -98,3 +98,13 @@ export const logout = () => async (
|
||||
dispatch({ type: actions.LOGOUT });
|
||||
pym.sendMessage('coral-auth-changed');
|
||||
};
|
||||
|
||||
export const updateStatus = status => ({
|
||||
type: actions.UPDATE_STATUS,
|
||||
status,
|
||||
});
|
||||
|
||||
export const updateUsername = username => ({
|
||||
type: actions.UPDATE_USERNAME,
|
||||
username,
|
||||
});
|
||||
|
||||
@@ -6,3 +6,6 @@ export const CHECK_LOGIN_FAILURE = `${prefix}_CHECK_LOGIN_FAILURE`;
|
||||
|
||||
export const LOGOUT = `${prefix}_LOGOUT`;
|
||||
export const HANDLE_SUCCESSFUL_LOGIN = `${prefix}_HANDLE_SUCCESSFUL_LOGIN`;
|
||||
|
||||
export const UPDATE_STATUS = '${prefix}_UPDATE_STATUS';
|
||||
export const UPDATE_USERNAME = '${prefix}_UPDATE_USERNAME';
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import * as actions from '../constants/auth';
|
||||
import merge from 'lodash/merge';
|
||||
|
||||
const initialState = {
|
||||
checkedInitialLogin: false,
|
||||
@@ -36,6 +37,24 @@ export default function auth(state = initialState, action) {
|
||||
...state,
|
||||
user: null,
|
||||
};
|
||||
case actions.UPDATE_STATUS: {
|
||||
return {
|
||||
...state,
|
||||
user: {
|
||||
...state.user,
|
||||
status: merge({}, state.user.status, action.status),
|
||||
},
|
||||
};
|
||||
}
|
||||
case actions.UPDATE_USERNAME:
|
||||
return {
|
||||
...state,
|
||||
user: {
|
||||
...state.user,
|
||||
username: action.username,
|
||||
lowercaseUsername: action.username.toLowerCase(),
|
||||
},
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
import React from 'react';
|
||||
|
||||
class Main extends React.Component {
|
||||
render() {
|
||||
return <div>Hello World</div>;
|
||||
}
|
||||
}
|
||||
|
||||
export default Main;
|
||||
@@ -0,0 +1,23 @@
|
||||
import React from 'react';
|
||||
import { render } from 'react-dom';
|
||||
|
||||
import { createContext } from 'coral-framework/services/bootstrap';
|
||||
import Main from './containers/Main';
|
||||
import reducers from './reducers';
|
||||
import TalkProvider from 'coral-framework/components/TalkProvider';
|
||||
import pluginsConfig from 'pluginsConfig';
|
||||
|
||||
async function main() {
|
||||
const context = await createContext({
|
||||
reducers,
|
||||
pluginsConfig,
|
||||
});
|
||||
render(
|
||||
<TalkProvider {...context}>
|
||||
<Main />
|
||||
</TalkProvider>,
|
||||
document.querySelector('#talk-login-container')
|
||||
);
|
||||
}
|
||||
|
||||
main();
|
||||
@@ -0,0 +1 @@
|
||||
export default {};
|
||||
@@ -3,11 +3,11 @@ import styles from './styles.css';
|
||||
import { connect } from 'react-redux';
|
||||
import { bindActionCreators } from 'redux';
|
||||
import t from 'coral-framework/services/i18n';
|
||||
import { logout } from 'coral-embed-stream/src/actions/login';
|
||||
import { logout } from 'coral-framework/actions/auth';
|
||||
|
||||
const UserBox = ({ loggedIn, user, logout, onShowProfile }) => (
|
||||
const UserBox = ({ user, logout, onShowProfile }) => (
|
||||
<div>
|
||||
{loggedIn ? (
|
||||
{user ? (
|
||||
<div className={`${styles.userBox} talk-stream-auth-userbox`}>
|
||||
<span className={styles.userBoxLoggedIn}>
|
||||
{t('sign_in.logged_in_as')}
|
||||
@@ -25,7 +25,6 @@ const UserBox = ({ loggedIn, user, logout, onShowProfile }) => (
|
||||
);
|
||||
|
||||
const mapStateToProps = ({ auth }) => ({
|
||||
loggedIn: auth.loggedIn,
|
||||
user: auth.user,
|
||||
});
|
||||
|
||||
|
||||
@@ -160,6 +160,10 @@ if (process.env.NODE_ENV !== 'production') {
|
||||
});
|
||||
}
|
||||
|
||||
router.use('/login', staticTemplate, async (req, res, next) => {
|
||||
return res.render('login');
|
||||
});
|
||||
|
||||
// Inject server route plugins.
|
||||
plugins.get('server', 'router').forEach(plugin => {
|
||||
debug(`added plugin '${plugin.plugin.name}'`);
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, user-scalable=no">
|
||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
||||
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
|
||||
<%_ if (locals.customCssUrl) { _%>
|
||||
<link href="<%= customCssUrl %>" rel="stylesheet" type="text/css">
|
||||
<%_ } _%>
|
||||
<%_ if (data != null) { _%>
|
||||
<script id="data" type="application/json"><%- JSON.stringify(data) %></script>
|
||||
<%_ } _%>
|
||||
<base href="<%= BASE_URL %>"/>
|
||||
</head>
|
||||
<body>
|
||||
<div id="talk-login-container"></div>
|
||||
<script src="<%= STATIC_URL %>static/coral-login/bundle.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -21,6 +21,7 @@ debug(`Using ${pluginsPath} as the plugin configuration path`);
|
||||
|
||||
const buildTargets = [
|
||||
'coral-admin',
|
||||
'coral-login',
|
||||
'coral-docs',
|
||||
{ name: 'coral-auth-callback', disablePolyfill: true },
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user