Separated user and auth stores
This commit is contained in:
@ -13,6 +13,7 @@ import { textColor, headerHeight } from 'styles/constants.scss';
|
|||||||
import DropdownMenu, { MenuItem } from 'components/DropdownMenu';
|
import DropdownMenu, { MenuItem } from 'components/DropdownMenu';
|
||||||
import LoadingIndicator from 'components/LoadingIndicator';
|
import LoadingIndicator from 'components/LoadingIndicator';
|
||||||
import UserStore from 'stores/UserStore';
|
import UserStore from 'stores/UserStore';
|
||||||
|
import AuthStore from 'stores/AuthStore';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
history: Object,
|
history: Object,
|
||||||
@ -21,6 +22,7 @@ type Props = {
|
|||||||
title?: ?React.Element<any>,
|
title?: ?React.Element<any>,
|
||||||
loading?: boolean,
|
loading?: boolean,
|
||||||
user: UserStore,
|
user: UserStore,
|
||||||
|
auth: AuthStore,
|
||||||
search: ?boolean,
|
search: ?boolean,
|
||||||
notifications?: React.Element<any>,
|
notifications?: React.Element<any>,
|
||||||
};
|
};
|
||||||
@ -34,23 +36,23 @@ type Props = {
|
|||||||
|
|
||||||
@keydown(['/', 't'])
|
@keydown(['/', 't'])
|
||||||
search() {
|
search() {
|
||||||
if (!this.props.user) return;
|
if (this.props.auth.isAuthenticated)
|
||||||
_.defer(() => this.props.history.push('/search'));
|
_.defer(() => this.props.history.push('/search'));
|
||||||
}
|
}
|
||||||
|
|
||||||
@keydown(['d'])
|
@keydown(['d'])
|
||||||
dashboard() {
|
dashboard() {
|
||||||
if (!this.props.user) return;
|
if (this.props.auth.isAuthenticated)
|
||||||
_.defer(() => this.props.history.push('/'));
|
_.defer(() => this.props.history.push('/'));
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
handleLogout = () => {
|
||||||
const user = this.props.user;
|
this.props.auth.logout(() => this.props.history.push('/'));
|
||||||
|
|
||||||
const handleLogout = () => {
|
|
||||||
user.logout(() => this.props.history.push('/'));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { auth, user } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container column auto>
|
<Container column auto>
|
||||||
<Helmet
|
<Helmet
|
||||||
@ -79,7 +81,8 @@ type Props = {
|
|||||||
<Flex align="center">
|
<Flex align="center">
|
||||||
{this.props.actions}
|
{this.props.actions}
|
||||||
</Flex>
|
</Flex>
|
||||||
{user.user &&
|
{auth.authenticated &&
|
||||||
|
user &&
|
||||||
<Flex>
|
<Flex>
|
||||||
{this.props.search &&
|
{this.props.search &&
|
||||||
<Flex>
|
<Flex>
|
||||||
@ -101,7 +104,7 @@ type Props = {
|
|||||||
<MenuLink to="/developers">
|
<MenuLink to="/developers">
|
||||||
<MenuItem>API</MenuItem>
|
<MenuItem>API</MenuItem>
|
||||||
</MenuLink>
|
</MenuLink>
|
||||||
<MenuItem onClick={handleLogout}>Logout</MenuItem>
|
<MenuItem onClick={this.handleLogout}>Logout</MenuItem>
|
||||||
</DropdownMenu>
|
</DropdownMenu>
|
||||||
</Flex>}
|
</Flex>}
|
||||||
</Flex>
|
</Flex>
|
||||||
@ -182,4 +185,4 @@ const Content = styled(Flex)`
|
|||||||
overflow: scroll;
|
overflow: scroll;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export default withRouter(inject('user')(Layout));
|
export default withRouter(inject('user', 'auth')(Layout));
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { observer, inject } from 'mobx-react';
|
import { observer, inject } from 'mobx-react';
|
||||||
import UserStore from 'stores/UserStore';
|
import AuthStore from 'stores/AuthStore';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
children: React.Element<any>,
|
children: React.Element<any>,
|
||||||
scopes?: Array<string>,
|
scopes?: Array<string>,
|
||||||
user: UserStore,
|
auth: AuthStore,
|
||||||
redirectUri: string,
|
redirectUri: string,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -28,7 +28,7 @@ type Props = {
|
|||||||
client_id: SLACK_KEY,
|
client_id: SLACK_KEY,
|
||||||
scope: this.props.scopes ? this.props.scopes.join(' ') : '',
|
scope: this.props.scopes ? this.props.scopes.join(' ') : '',
|
||||||
redirect_uri: this.props.redirectUri || SLACK_REDIRECT_URI,
|
redirect_uri: this.props.redirectUri || SLACK_REDIRECT_URI,
|
||||||
state: this.props.user.getOauthState(),
|
state: this.props.auth.getOauthState(),
|
||||||
};
|
};
|
||||||
|
|
||||||
const urlParams = Object.keys(params)
|
const urlParams = Object.keys(params)
|
||||||
@ -45,4 +45,4 @@ type Props = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default inject('user')(SlackAuthLink);
|
export default inject('auth')(SlackAuthLink);
|
||||||
|
@ -45,15 +45,17 @@ type AuthProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const Auth = ({ children }: AuthProps) => {
|
const Auth = ({ children }: AuthProps) => {
|
||||||
if (stores.user.authenticated && stores.user.team) {
|
if (stores.auth.authenticated && stores.auth.team) {
|
||||||
// Only initialize stores once. Kept in global scope
|
// Only initialize stores once. Kept in global scope
|
||||||
// because otherwise they will get overriden on route
|
// because otherwise they will get overriden on route
|
||||||
// change
|
// change
|
||||||
if (!authenticatedStores) {
|
if (!authenticatedStores) {
|
||||||
// Stores for authenticated user
|
// Stores for authenticated user
|
||||||
|
const user = stores.auth.getUserStore();
|
||||||
authenticatedStores = {
|
authenticatedStores = {
|
||||||
|
user,
|
||||||
collections: new CollectionsStore({
|
collections: new CollectionsStore({
|
||||||
teamId: stores.user.team.id,
|
teamId: user.team.id,
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2,22 +2,23 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { observer, inject } from 'mobx-react';
|
import { observer, inject } from 'mobx-react';
|
||||||
import { Redirect } from 'react-router';
|
import { Redirect } from 'react-router';
|
||||||
|
|
||||||
import { Flex } from 'reflexbox';
|
import { Flex } from 'reflexbox';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
|
||||||
|
import AuthStore from 'stores/AuthStore';
|
||||||
|
|
||||||
import Layout from 'components/Layout';
|
import Layout from 'components/Layout';
|
||||||
import CenteredContent from 'components/CenteredContent';
|
import CenteredContent from 'components/CenteredContent';
|
||||||
import SlackAuthLink from 'components/SlackAuthLink';
|
import SlackAuthLink from 'components/SlackAuthLink';
|
||||||
import Alert from 'components/Alert';
|
import Alert from 'components/Alert';
|
||||||
|
|
||||||
import styles from './Home.scss';
|
type Props = {
|
||||||
|
auth: AuthStore,
|
||||||
|
location: Object,
|
||||||
|
};
|
||||||
|
|
||||||
@inject('user')
|
@observer class Home extends React.Component {
|
||||||
@observer
|
props: Props;
|
||||||
export default class Home extends React.Component {
|
|
||||||
static propTypes = {
|
|
||||||
user: React.PropTypes.object.isRequired,
|
|
||||||
location: React.PropTypes.object.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
get notifications(): React.Element<any>[] {
|
get notifications(): React.Element<any>[] {
|
||||||
const notifications = [];
|
const notifications = [];
|
||||||
@ -40,17 +41,17 @@ export default class Home extends React.Component {
|
|||||||
return (
|
return (
|
||||||
<Flex auto>
|
<Flex auto>
|
||||||
<Layout notifications={this.notifications}>
|
<Layout notifications={this.notifications}>
|
||||||
{this.props.user.authenticated && <Redirect to="/dashboard" />}
|
{this.props.auth.authenticated && <Redirect to="/dashboard" />}
|
||||||
|
|
||||||
<CenteredContent>
|
<CenteredContent>
|
||||||
{showLandingPageCopy &&
|
{showLandingPageCopy &&
|
||||||
<div className={styles.intro}>
|
<div>
|
||||||
<h1 className={styles.title}>Simple, fast, markdown.</h1>
|
<Title>Simple, fast, markdown.</Title>
|
||||||
<p className={styles.copy}>
|
<Copy>
|
||||||
We're building a modern wiki for engineering teams.
|
We're building a modern wiki for engineering teams.
|
||||||
</p>
|
</Copy>
|
||||||
</div>}
|
</div>}
|
||||||
<div className={styles.action}>
|
<div>
|
||||||
<SlackAuthLink redirectUri={`${BASE_URL}/auth/slack`}>
|
<SlackAuthLink redirectUri={`${BASE_URL}/auth/slack`}>
|
||||||
<img
|
<img
|
||||||
alt="Sign in with Slack"
|
alt="Sign in with Slack"
|
||||||
@ -67,3 +68,15 @@ export default class Home extends React.Component {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Title = styled.h1`
|
||||||
|
font-size: 36px;
|
||||||
|
margin-bottom: 24px;
|
||||||
|
}`;
|
||||||
|
|
||||||
|
const Copy = styled.p`
|
||||||
|
font-size: 20px;
|
||||||
|
margin-bottom: 36px;
|
||||||
|
}`;
|
||||||
|
|
||||||
|
export default inject('auth')(Home);
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
.title {
|
|
||||||
font-size: 36px;
|
|
||||||
margin-bottom: 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.copy {
|
|
||||||
font-size: 20px;
|
|
||||||
margin-bottom: 36px;
|
|
||||||
}
|
|
@ -5,19 +5,20 @@ import queryString from 'query-string';
|
|||||||
import { observer, inject } from 'mobx-react';
|
import { observer, inject } from 'mobx-react';
|
||||||
import { client } from 'utils/ApiClient';
|
import { client } from 'utils/ApiClient';
|
||||||
|
|
||||||
import UserStore from 'stores/UserStore';
|
import AuthStore from 'stores/AuthStore';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
user: UserStore,
|
auth: AuthStore,
|
||||||
location: Object,
|
location: Object,
|
||||||
};
|
};
|
||||||
|
|
||||||
@inject('user')
|
type State = {
|
||||||
@observer
|
redirectTo: string,
|
||||||
class SlackAuth extends React.Component {
|
};
|
||||||
props: Props;
|
|
||||||
|
|
||||||
state: { redirectTo?: string };
|
@observer class SlackAuth extends React.Component {
|
||||||
|
props: Props;
|
||||||
|
state: State;
|
||||||
state = {};
|
state = {};
|
||||||
|
|
||||||
// $FlowIssue Flow doesn't like async lifecycle components https://github.com/facebook/flow/issues/1803
|
// $FlowIssue Flow doesn't like async lifecycle components https://github.com/facebook/flow/issues/1803
|
||||||
@ -47,7 +48,7 @@ class SlackAuth extends React.Component {
|
|||||||
const redirectTo = sessionStorage.getItem('redirectTo');
|
const redirectTo = sessionStorage.getItem('redirectTo');
|
||||||
sessionStorage.removeItem('redirectTo');
|
sessionStorage.removeItem('redirectTo');
|
||||||
|
|
||||||
const { success } = await this.props.user.authWithSlack(code, state);
|
const { success } = await this.props.auth.authWithSlack(code, state);
|
||||||
success
|
success
|
||||||
? this.setState({ redirectTo: redirectTo || '/dashboard' })
|
? this.setState({ redirectTo: redirectTo || '/dashboard' })
|
||||||
: this.setState({ redirectTo: '/auth/error' });
|
: this.setState({ redirectTo: '/auth/error' });
|
||||||
@ -64,4 +65,4 @@ class SlackAuth extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default SlackAuth;
|
export default inject('auth')(SlackAuth);
|
||||||
|
100
frontend/stores/AuthStore.js
Normal file
100
frontend/stores/AuthStore.js
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
// @flow
|
||||||
|
import { observable, action, computed, autorunAsync } from 'mobx';
|
||||||
|
import invariant from 'invariant';
|
||||||
|
import { client } from 'utils/ApiClient';
|
||||||
|
import UserStore from 'stores/UserStore';
|
||||||
|
import type { User, Team } from 'types';
|
||||||
|
|
||||||
|
const AUTH_STORE = 'AUTH_STORE';
|
||||||
|
|
||||||
|
class AuthStore {
|
||||||
|
@observable user: ?User;
|
||||||
|
@observable team: ?Team;
|
||||||
|
@observable token: ?string;
|
||||||
|
@observable oauthState: string;
|
||||||
|
@observable isLoading: boolean = false;
|
||||||
|
|
||||||
|
/* Computed */
|
||||||
|
|
||||||
|
@computed get authenticated(): boolean {
|
||||||
|
return !!this.token;
|
||||||
|
}
|
||||||
|
|
||||||
|
@computed get asJson(): string {
|
||||||
|
return JSON.stringify({
|
||||||
|
user: this.user,
|
||||||
|
team: this.team,
|
||||||
|
token: this.token,
|
||||||
|
oauthState: this.oauthState,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Actions */
|
||||||
|
|
||||||
|
@action logout = (cb: Function) => {
|
||||||
|
this.user = null;
|
||||||
|
this.token = null;
|
||||||
|
cb();
|
||||||
|
};
|
||||||
|
|
||||||
|
@action getOauthState = () => {
|
||||||
|
const state = Math.random().toString(36).substring(7);
|
||||||
|
this.oauthState = state;
|
||||||
|
return this.oauthState;
|
||||||
|
};
|
||||||
|
|
||||||
|
@action authWithSlack = async (code: string, state: string) => {
|
||||||
|
if (state !== this.oauthState) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
let res;
|
||||||
|
try {
|
||||||
|
res = await client.post('/auth.slack', { code });
|
||||||
|
} catch (e) {
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
invariant(
|
||||||
|
res && res.data && res.data.user && res.data.team && res.data.accessToken,
|
||||||
|
'All values should be available'
|
||||||
|
);
|
||||||
|
this.user = res.data.user;
|
||||||
|
this.team = res.data.team;
|
||||||
|
this.token = res.data.accessToken;
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
getUserStore(): UserStore {
|
||||||
|
invariant(
|
||||||
|
this.user && this.team,
|
||||||
|
'Tried to create a user store without data'
|
||||||
|
);
|
||||||
|
return new UserStore({
|
||||||
|
user: this.user,
|
||||||
|
team: this.team,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
// Rehydrate
|
||||||
|
const data = JSON.parse(localStorage.getItem(AUTH_STORE) || '{}');
|
||||||
|
this.user = data.user;
|
||||||
|
this.team = data.team;
|
||||||
|
this.token = data.token;
|
||||||
|
this.oauthState = data.oauthState;
|
||||||
|
|
||||||
|
autorunAsync(() => {
|
||||||
|
localStorage.setItem(AUTH_STORE, this.asJson);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default AuthStore;
|
@ -2,6 +2,7 @@
|
|||||||
import { observable, action, runInAction, ObservableArray } from 'mobx';
|
import { observable, action, runInAction, ObservableArray } from 'mobx';
|
||||||
import ApiClient, { client } from 'utils/ApiClient';
|
import ApiClient, { client } from 'utils/ApiClient';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
import invariant from 'invariant';
|
||||||
|
|
||||||
import stores from 'stores';
|
import stores from 'stores';
|
||||||
import Collection from 'models/Collection';
|
import Collection from 'models/Collection';
|
||||||
@ -26,6 +27,7 @@ class CollectionsStore {
|
|||||||
const res = await this.client.post('/collections.list', {
|
const res = await this.client.post('/collections.list', {
|
||||||
id: this.teamId,
|
id: this.teamId,
|
||||||
});
|
});
|
||||||
|
invariant(res && res.data, 'Collection list not available');
|
||||||
const { data } = res;
|
const { data } = res;
|
||||||
runInAction('CollectionsStore#fetch', () => {
|
runInAction('CollectionsStore#fetch', () => {
|
||||||
this.data.replace(
|
this.data.replace(
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import { observable, action, computed } from 'mobx';
|
import { observable, action, computed, autorunAsync } from 'mobx';
|
||||||
|
|
||||||
const UI_STORE = 'UI_STORE';
|
const UI_STORE = 'UI_STORE';
|
||||||
|
|
||||||
@ -24,8 +24,11 @@ class UiStore {
|
|||||||
// Rehydrate
|
// Rehydrate
|
||||||
const data = JSON.parse(localStorage.getItem(UI_STORE) || '{}');
|
const data = JSON.parse(localStorage.getItem(UI_STORE) || '{}');
|
||||||
this.sidebar = data.sidebar;
|
this.sidebar = data.sidebar;
|
||||||
|
|
||||||
|
autorunAsync(() => {
|
||||||
|
localStorage.setItem(UI_STORE, this.asJson);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default UiStore;
|
export default UiStore;
|
||||||
export { UI_STORE };
|
|
||||||
|
@ -1,87 +1,32 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import { observable, action, computed } from 'mobx';
|
import { observable, computed } from 'mobx';
|
||||||
import invariant from 'invariant';
|
|
||||||
import { client } from 'utils/ApiClient';
|
|
||||||
import type { User, Team } from 'types';
|
import type { User, Team } from 'types';
|
||||||
|
|
||||||
const USER_STORE = 'USER_STORE';
|
type Options = {
|
||||||
|
user: User,
|
||||||
|
team: Team,
|
||||||
|
};
|
||||||
|
|
||||||
class UserStore {
|
class UserStore {
|
||||||
@observable user: ?User;
|
@observable user: User;
|
||||||
@observable team: ?Team;
|
@observable team: Team;
|
||||||
|
|
||||||
@observable token: ?string;
|
|
||||||
@observable oauthState: string;
|
|
||||||
|
|
||||||
@observable isLoading: boolean = false;
|
@observable isLoading: boolean = false;
|
||||||
|
|
||||||
/* Computed */
|
/* Computed */
|
||||||
|
|
||||||
@computed get authenticated(): boolean {
|
|
||||||
return !!this.token;
|
|
||||||
}
|
|
||||||
|
|
||||||
@computed get asJson(): string {
|
@computed get asJson(): string {
|
||||||
return JSON.stringify({
|
return JSON.stringify({
|
||||||
user: this.user,
|
user: this.user,
|
||||||
team: this.team,
|
team: this.team,
|
||||||
token: this.token,
|
|
||||||
oauthState: this.oauthState,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Actions */
|
constructor(options: Options) {
|
||||||
|
|
||||||
@action logout = (cb: Function) => {
|
|
||||||
this.user = null;
|
|
||||||
this.token = null;
|
|
||||||
cb();
|
|
||||||
};
|
|
||||||
|
|
||||||
@action getOauthState = () => {
|
|
||||||
const state = Math.random().toString(36).substring(7);
|
|
||||||
this.oauthState = state;
|
|
||||||
return this.oauthState;
|
|
||||||
};
|
|
||||||
|
|
||||||
@action authWithSlack = async (code: string, state: string) => {
|
|
||||||
if (state !== this.oauthState) {
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
let res;
|
|
||||||
try {
|
|
||||||
res = await client.post('/auth.slack', { code });
|
|
||||||
} catch (e) {
|
|
||||||
return {
|
|
||||||
success: false,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
invariant(
|
|
||||||
res && res.data && res.data.user && res.data.team && res.data.accessToken,
|
|
||||||
'All values should be available'
|
|
||||||
);
|
|
||||||
this.user = res.data.user;
|
|
||||||
this.team = res.data.team;
|
|
||||||
this.token = res.data.accessToken;
|
|
||||||
|
|
||||||
return {
|
|
||||||
success: true,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
// Rehydrate
|
// Rehydrate
|
||||||
const data = JSON.parse(localStorage.getItem(USER_STORE) || '{}');
|
this.user = options.user;
|
||||||
this.user = data.user;
|
this.team = options.team;
|
||||||
this.team = data.team;
|
|
||||||
this.token = data.token;
|
|
||||||
this.oauthState = data.oauthState;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default UserStore;
|
export default UserStore;
|
||||||
export { USER_STORE };
|
|
||||||
|
@ -1,20 +1,13 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import { autorunAsync } from 'mobx';
|
import AuthStore from './AuthStore';
|
||||||
import UserStore, { USER_STORE } from './UserStore';
|
import UiStore from './UiStore';
|
||||||
import UiStore, { UI_STORE } from './UiStore';
|
|
||||||
import ErrorsStore from './ErrorsStore';
|
import ErrorsStore from './ErrorsStore';
|
||||||
|
|
||||||
const stores = {
|
const stores = {
|
||||||
user: new UserStore(),
|
user: null, // Including for Layout
|
||||||
|
auth: new AuthStore(),
|
||||||
ui: new UiStore(),
|
ui: new UiStore(),
|
||||||
errors: new ErrorsStore(),
|
errors: new ErrorsStore(),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Persist stores to localStorage
|
|
||||||
// TODO: move to store constructors
|
|
||||||
autorunAsync(() => {
|
|
||||||
localStorage.setItem(USER_STORE, stores.user.asJson);
|
|
||||||
localStorage.setItem(UI_STORE, stores.ui.asJson);
|
|
||||||
});
|
|
||||||
|
|
||||||
export default stores;
|
export default stores;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
import invariant from 'invariant';
|
||||||
import stores from 'stores';
|
import stores from 'stores';
|
||||||
|
|
||||||
type Options = {
|
type Options = {
|
||||||
@ -39,9 +40,9 @@ class ApiClient {
|
|||||||
Accept: 'application/json',
|
Accept: 'application/json',
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
});
|
});
|
||||||
if (stores.user.authenticated) {
|
if (stores.auth.authenticated) {
|
||||||
// $FlowFixMe this is not great, need to refactor
|
invariant(stores.auth.token, 'JWT token not set properly');
|
||||||
headers.set('Authorization', `Bearer ${stores.user.token}`);
|
headers.set('Authorization', `Bearer ${stores.auth.token}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Construct request
|
// Construct request
|
||||||
@ -62,15 +63,10 @@ class ApiClient {
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
// // Handle 404
|
// Handle 401, log out user
|
||||||
// if (response.status === 404) {
|
if (response.status === 401) {
|
||||||
// // return browserHistory.push('/404');
|
return stores.auth.logout(() => (window.location = '/'));
|
||||||
// }
|
}
|
||||||
|
|
||||||
// // Handle 401, log out user
|
|
||||||
// if (response.status === 401) {
|
|
||||||
// return stores.user.logout();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Handle failed responses
|
// Handle failed responses
|
||||||
const error = {};
|
const error = {};
|
||||||
@ -112,5 +108,4 @@ class ApiClient {
|
|||||||
export default ApiClient;
|
export default ApiClient;
|
||||||
|
|
||||||
// In case you don't want to always initiate, just import with `import { client } ...`
|
// In case you don't want to always initiate, just import with `import { client } ...`
|
||||||
const client = new ApiClient();
|
export const client = new ApiClient();
|
||||||
export { client };
|
|
||||||
|
Reference in New Issue
Block a user