LogOut working
This commit is contained in:
parent
1b8544b758
commit
6c6d6297f9
8 changed files with 44 additions and 12 deletions
|
@ -1,8 +1,10 @@
|
||||||
import api from '../api';
|
import api from '../api';
|
||||||
|
import { showAlert } from 'gabsocial/actions/alerts';
|
||||||
|
|
||||||
export const AUTH_APP_CREATED = 'AUTH_APP_CREATED';
|
export const AUTH_APP_CREATED = 'AUTH_APP_CREATED';
|
||||||
export const AUTH_APP_AUTHORIZED = 'AUTH_APP_AUTHORIZED';
|
export const AUTH_APP_AUTHORIZED = 'AUTH_APP_AUTHORIZED';
|
||||||
export const AUTH_LOGGED_IN = 'AUTH_LOGGED_IN';
|
export const AUTH_LOGGED_IN = 'AUTH_LOGGED_IN';
|
||||||
|
export const AUTH_LOGGED_OUT = 'AUTH_LOGGED_OUT';
|
||||||
|
|
||||||
export function createAuthApp() {
|
export function createAuthApp() {
|
||||||
return (dispatch, getState) => {
|
return (dispatch, getState) => {
|
||||||
|
@ -39,10 +41,20 @@ export function logIn(username, password) {
|
||||||
password: password
|
password: password
|
||||||
}).then(response => {
|
}).then(response => {
|
||||||
dispatch(authLoggedIn(response.data));
|
dispatch(authLoggedIn(response.data));
|
||||||
|
}).catch((error) => {
|
||||||
|
dispatch(showAlert('Login failed.', 'Invalid username or password.'));
|
||||||
|
throw error;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function logOut() {
|
||||||
|
return (dispatch, getState) => {
|
||||||
|
dispatch({ type: AUTH_LOGGED_OUT });
|
||||||
|
dispatch(showAlert('Successfully logged out.', ''));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function authAppCreated(app) {
|
export function authAppCreated(app) {
|
||||||
return {
|
return {
|
||||||
type: AUTH_APP_CREATED,
|
type: AUTH_APP_CREATED,
|
||||||
|
|
|
@ -13,6 +13,7 @@ import DisplayName from './display_name';
|
||||||
import { closeSidebar } from '../actions/sidebar';
|
import { closeSidebar } from '../actions/sidebar';
|
||||||
import { shortNumberFormat } from '../utils/numbers';
|
import { shortNumberFormat } from '../utils/numbers';
|
||||||
import { makeGetAccount } from '../selectors';
|
import { makeGetAccount } from '../selectors';
|
||||||
|
import { logOut } from 'gabsocial/actions/auth';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
followers: { id: 'account.followers', defaultMessage: 'Followers' },
|
followers: { id: 'account.followers', defaultMessage: 'Followers' },
|
||||||
|
@ -46,6 +47,10 @@ const mapDispatchToProps = (dispatch) => ({
|
||||||
onClose () {
|
onClose () {
|
||||||
dispatch(closeSidebar());
|
dispatch(closeSidebar());
|
||||||
},
|
},
|
||||||
|
onClickLogOut(e) {
|
||||||
|
dispatch(logOut());
|
||||||
|
e.preventDefault();
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export default @connect(mapStateToProps, mapDispatchToProps)
|
export default @connect(mapStateToProps, mapDispatchToProps)
|
||||||
|
@ -60,7 +65,7 @@ class SidebarMenu extends ImmutablePureComponent {
|
||||||
};
|
};
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { sidebarOpen, onClose, intl, account } = this.props;
|
const { sidebarOpen, onClose, intl, account, onClickLogOut } = this.props;
|
||||||
if (!account) return null;
|
if (!account) return null;
|
||||||
const acct = account.get('acct');
|
const acct = account.get('acct');
|
||||||
|
|
||||||
|
@ -150,9 +155,9 @@ class SidebarMenu extends ImmutablePureComponent {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='sidebar-menu__section'>
|
<div className='sidebar-menu__section'>
|
||||||
<a className='sidebar-menu-item' href='/auth/sign_out' data-method='delete'>
|
<Link className='sidebar-menu-item' to='/auth/sign_out' onClick={onClickLogOut}>
|
||||||
<span className='sidebar-menu-item__title'>{intl.formatMessage(messages.logout)}</span>
|
<span className='sidebar-menu-item__title'>{intl.formatMessage(messages.logout)}</span>
|
||||||
</a>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -4,7 +4,6 @@ import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
import { createAuthApp, logIn } from 'gabsocial/actions/auth';
|
import { createAuthApp, logIn } from 'gabsocial/actions/auth';
|
||||||
import { fetchMe } from 'gabsocial/actions/me';
|
import { fetchMe } from 'gabsocial/actions/me';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { showAlert } from 'gabsocial/actions/alerts';
|
|
||||||
|
|
||||||
export default @connect()
|
export default @connect()
|
||||||
class LoginForm extends ImmutablePureComponent {
|
class LoginForm extends ImmutablePureComponent {
|
||||||
|
@ -29,7 +28,6 @@ class LoginForm extends ImmutablePureComponent {
|
||||||
dispatch(logIn(username, password)).then(() => {
|
dispatch(logIn(username, password)).then(() => {
|
||||||
return dispatch(fetchMe());
|
return dispatch(fetchMe());
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
dispatch(showAlert('Login failed', 'Invalid username or password.'));
|
|
||||||
this.setState({isLoading: false});
|
this.setState({isLoading: false});
|
||||||
});
|
});
|
||||||
this.setState({isLoading: true});
|
this.setState({isLoading: true});
|
||||||
|
|
|
@ -6,6 +6,7 @@ import PropTypes from 'prop-types';
|
||||||
import DropdownMenuContainer from '../../../containers/dropdown_menu_container';
|
import DropdownMenuContainer from '../../../containers/dropdown_menu_container';
|
||||||
import { defineMessages, injectIntl } from 'react-intl';
|
import { defineMessages, injectIntl } from 'react-intl';
|
||||||
import { meUsername } from 'gabsocial/initial_state';
|
import { meUsername } from 'gabsocial/initial_state';
|
||||||
|
import { logOut } from 'gabsocial/actions/auth';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
profile: { id: 'account.profile', defaultMessage: 'Profile' },
|
profile: { id: 'account.profile', defaultMessage: 'Profile' },
|
||||||
|
@ -24,6 +25,10 @@ const mapDispatchToProps = (dispatch) => ({
|
||||||
onOpenHotkeys() {
|
onOpenHotkeys() {
|
||||||
dispatch(openModal('HOTKEYS'));
|
dispatch(openModal('HOTKEYS'));
|
||||||
},
|
},
|
||||||
|
onClickLogOut(e) {
|
||||||
|
dispatch(logOut());
|
||||||
|
e.preventDefault();
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
class ActionBar extends React.PureComponent {
|
class ActionBar extends React.PureComponent {
|
||||||
|
@ -38,7 +43,7 @@ class ActionBar extends React.PureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { intl, onOpenHotkeys } = this.props;
|
const { intl, onOpenHotkeys, onClickLogOut } = this.props;
|
||||||
const size = this.props.size || 16;
|
const size = this.props.size || 16;
|
||||||
|
|
||||||
let menu = [];
|
let menu = [];
|
||||||
|
@ -50,11 +55,11 @@ class ActionBar extends React.PureComponent {
|
||||||
menu.push({ text: intl.formatMessage(messages.mutes), to: '/mutes' });
|
menu.push({ text: intl.formatMessage(messages.mutes), to: '/mutes' });
|
||||||
menu.push({ text: intl.formatMessage(messages.blocks), to: '/blocks' });
|
menu.push({ text: intl.formatMessage(messages.blocks), to: '/blocks' });
|
||||||
menu.push({ text: intl.formatMessage(messages.domain_blocks), to: '/domain_blocks' });
|
menu.push({ text: intl.formatMessage(messages.domain_blocks), to: '/domain_blocks' });
|
||||||
menu.push({ text: intl.formatMessage(messages.filters), href: '/filters' });
|
menu.push({ text: intl.formatMessage(messages.filters), to: '/filters' });
|
||||||
menu.push(null);
|
menu.push(null);
|
||||||
menu.push({ text: intl.formatMessage(messages.keyboard_shortcuts), action: this.handleHotkeyClick });
|
menu.push({ text: intl.formatMessage(messages.keyboard_shortcuts), action: this.handleHotkeyClick });
|
||||||
menu.push({ text: intl.formatMessage(messages.preferences), href: '/settings/preferences' });
|
menu.push({ text: intl.formatMessage(messages.preferences), to: '/settings/preferences' });
|
||||||
menu.push({ text: intl.formatMessage(messages.logout), href: '/auth/sign_out', isLogout: true });
|
menu.push({ text: intl.formatMessage(messages.logout), to: '/auth/sign_out', action: onClickLogOut });
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='compose__action-bar' style={{'marginTop':'-6px'}}>
|
<div className='compose__action-bar' style={{'marginTop':'-6px'}}>
|
||||||
|
|
|
@ -5,6 +5,7 @@ import { Link } from 'react-router-dom';
|
||||||
import { invitesEnabled, version, repository, source_url } from 'gabsocial/initial_state';
|
import { invitesEnabled, version, repository, source_url } from 'gabsocial/initial_state';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { openModal } from '../../../actions/modal';
|
import { openModal } from '../../../actions/modal';
|
||||||
|
import { logOut } from 'gabsocial/actions/auth';
|
||||||
|
|
||||||
const mapStateToProps = state => {
|
const mapStateToProps = state => {
|
||||||
const me = state.get('me');
|
const me = state.get('me');
|
||||||
|
@ -18,9 +19,13 @@ const mapDispatchToProps = (dispatch) => ({
|
||||||
onOpenHotkeys() {
|
onOpenHotkeys() {
|
||||||
dispatch(openModal('HOTKEYS'));
|
dispatch(openModal('HOTKEYS'));
|
||||||
},
|
},
|
||||||
|
onClickLogOut(e) {
|
||||||
|
dispatch(logOut());
|
||||||
|
e.preventDefault();
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const LinkFooter = ({ onOpenHotkeys, account, siteTitle }) => (
|
const LinkFooter = ({ onOpenHotkeys, account, siteTitle, onClickLogOut }) => (
|
||||||
<div className='getting-started__footer'>
|
<div className='getting-started__footer'>
|
||||||
<ul>
|
<ul>
|
||||||
{(invitesEnabled && account) && <li><a href='/invites'><FormattedMessage id='getting_started.invite' defaultMessage='Invite people' /></a> · </li>}
|
{(invitesEnabled && account) && <li><a href='/invites'><FormattedMessage id='getting_started.invite' defaultMessage='Invite people' /></a> · </li>}
|
||||||
|
@ -31,7 +36,7 @@ const LinkFooter = ({ onOpenHotkeys, account, siteTitle }) => (
|
||||||
<li><a href='/about/tos'><FormattedMessage id='getting_started.terms' defaultMessage='Terms of Service' /></a> · </li>
|
<li><a href='/about/tos'><FormattedMessage id='getting_started.terms' defaultMessage='Terms of Service' /></a> · </li>
|
||||||
<li><a href='/about/dmca'><FormattedMessage id='getting_started.dmca' defaultMessage='DMCA' /></a> · </li>
|
<li><a href='/about/dmca'><FormattedMessage id='getting_started.dmca' defaultMessage='DMCA' /></a> · </li>
|
||||||
<li><a href='/about/privacy'><FormattedMessage id='getting_started.privacy' defaultMessage='Privacy Policy' /></a></li>
|
<li><a href='/about/privacy'><FormattedMessage id='getting_started.privacy' defaultMessage='Privacy Policy' /></a></li>
|
||||||
{account && <li> · <a href='/auth/sign_out' data-method='delete'><FormattedMessage id='navigation_bar.logout' defaultMessage='Logout' /></a></li>}
|
{account && <li> · <Link to='/auth/sign_out' onClick={onClickLogOut}><FormattedMessage id='navigation_bar.logout' defaultMessage='Logout' /></Link></li>}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
|
@ -479,7 +479,7 @@ class UI extends React.PureComponent {
|
||||||
const { me } = this.props;
|
const { me } = this.props;
|
||||||
this.hotkeys = c;
|
this.hotkeys = c;
|
||||||
|
|
||||||
if (!me) return;
|
if (!me || !this.hotkeys) return;
|
||||||
this.hotkeys.__mousetrap__.stopCallback = (e, element) => {
|
this.hotkeys.__mousetrap__.stopCallback = (e, element) => {
|
||||||
return ['TEXTAREA', 'SELECT', 'INPUT'].includes(element.tagName);
|
return ['TEXTAREA', 'SELECT', 'INPUT'].includes(element.tagName);
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,6 +2,7 @@ import {
|
||||||
AUTH_APP_CREATED,
|
AUTH_APP_CREATED,
|
||||||
AUTH_LOGGED_IN,
|
AUTH_LOGGED_IN,
|
||||||
AUTH_APP_AUTHORIZED,
|
AUTH_APP_AUTHORIZED,
|
||||||
|
AUTH_LOGGED_OUT,
|
||||||
} from '../actions/auth';
|
} from '../actions/auth';
|
||||||
import { Map as ImmutableMap, fromJS } from 'immutable';
|
import { Map as ImmutableMap, fromJS } from 'immutable';
|
||||||
|
|
||||||
|
@ -22,6 +23,9 @@ export default function auth(state = initialState, action) {
|
||||||
case AUTH_LOGGED_IN:
|
case AUTH_LOGGED_IN:
|
||||||
localStorage.setItem('soapbox:auth:user', JSON.stringify(action.user)); // TODO: Better persistence
|
localStorage.setItem('soapbox:auth:user', JSON.stringify(action.user)); // TODO: Better persistence
|
||||||
return state.set('user', ImmutableMap(action.user));
|
return state.set('user', ImmutableMap(action.user));
|
||||||
|
case AUTH_LOGGED_OUT:
|
||||||
|
localStorage.removeItem('soapbox:auth:user');
|
||||||
|
return state.setIn(['user'], ImmutableMap());
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { ME_FETCH_SUCCESS, ME_FETCH_FAIL } from '../actions/me';
|
import { ME_FETCH_SUCCESS, ME_FETCH_FAIL } from '../actions/me';
|
||||||
|
import { AUTH_LOGGED_OUT } from '../actions/auth';
|
||||||
import { Map as ImmutableMap, fromJS } from 'immutable';
|
import { Map as ImmutableMap, fromJS } from 'immutable';
|
||||||
|
|
||||||
const initialState = null;
|
const initialState = null;
|
||||||
|
@ -9,6 +10,8 @@ export default function me(state = initialState, action) {
|
||||||
return fromJS(action.me.id);
|
return fromJS(action.me.id);
|
||||||
case ME_FETCH_FAIL:
|
case ME_FETCH_FAIL:
|
||||||
return false;
|
return false;
|
||||||
|
case AUTH_LOGGED_OUT:
|
||||||
|
return false;
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue