Refactor AuthProvider
This commit is contained in:
parent
b633e2f470
commit
03a2fff2a5
1 changed files with 66 additions and 143 deletions
|
@ -7,8 +7,7 @@ import {
|
||||||
login as loginWithCredentialsManagementAPI,
|
login as loginWithCredentialsManagementAPI,
|
||||||
saveCredentials
|
saveCredentials
|
||||||
} from "@saleor/utils/credentialsManagement";
|
} from "@saleor/utils/credentialsManagement";
|
||||||
import React from "react";
|
import React, { useContext, useEffect, useState } from "react";
|
||||||
import { MutationFunction, MutationResult } from "react-apollo";
|
|
||||||
import { useIntl } from "react-intl";
|
import { useIntl } from "react-intl";
|
||||||
|
|
||||||
import { UserContext } from "./";
|
import { UserContext } from "./";
|
||||||
|
@ -17,9 +16,6 @@ import {
|
||||||
useTokenRefreshMutation,
|
useTokenRefreshMutation,
|
||||||
useTokenVerifyMutation
|
useTokenVerifyMutation
|
||||||
} from "./mutations";
|
} from "./mutations";
|
||||||
import { RefreshToken, RefreshTokenVariables } from "./types/RefreshToken";
|
|
||||||
import { TokenAuth, TokenAuthVariables } from "./types/TokenAuth";
|
|
||||||
import { VerifyToken, VerifyTokenVariables } from "./types/VerifyToken";
|
|
||||||
import {
|
import {
|
||||||
displayDemoMessage,
|
displayDemoMessage,
|
||||||
getAuthToken,
|
getAuthToken,
|
||||||
|
@ -27,126 +23,61 @@ import {
|
||||||
setAuthToken
|
setAuthToken
|
||||||
} from "./utils";
|
} from "./utils";
|
||||||
|
|
||||||
interface AuthProviderOperationsProps {
|
interface AuthProviderProps {
|
||||||
children: (props: {
|
children: React.ReactNode;
|
||||||
hasToken: boolean;
|
|
||||||
isAuthenticated: boolean;
|
|
||||||
tokenAuthLoading: boolean;
|
|
||||||
tokenVerifyLoading: boolean;
|
|
||||||
user: User;
|
|
||||||
}) => React.ReactNode;
|
|
||||||
}
|
}
|
||||||
const AuthProviderOperations: React.FC<AuthProviderOperationsProps> = ({
|
const AuthProvider: React.FC<AuthProviderProps> = ({ children }) => {
|
||||||
children
|
|
||||||
}) => {
|
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const notify = useNotifier();
|
const notify = useNotifier();
|
||||||
|
|
||||||
const tokenAuth = useTokenAuthMutation({});
|
const [tokenAuth, tokenAuthOpts] = useTokenAuthMutation({});
|
||||||
const tokenRefresh = useTokenRefreshMutation({});
|
const [tokenRefresh] = useTokenRefreshMutation({});
|
||||||
const tokenVerify = useTokenVerifyMutation({});
|
const [tokenVerify, tokenVerifyOpts] = useTokenVerifyMutation({});
|
||||||
|
|
||||||
const handleLogin = () => {
|
const [userContext, setUserContext] = useState<undefined | User>(undefined);
|
||||||
|
const [persistToken] = useState<boolean>(false);
|
||||||
|
|
||||||
|
const onLogin = () => {
|
||||||
if (DEMO_MODE) {
|
if (DEMO_MODE) {
|
||||||
displayDemoMessage(intl, notify);
|
displayDemoMessage(intl, notify);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
useEffect(() => {
|
||||||
<AuthProvider
|
const token = getAuthToken();
|
||||||
tokenAuth={tokenAuth}
|
if (!!token && !userContext) {
|
||||||
tokenVerify={tokenVerify}
|
verifyToken(token);
|
||||||
tokenRefresh={tokenRefresh}
|
} else {
|
||||||
onLogin={handleLogin}
|
loginWithCredentialsManagementAPI(login);
|
||||||
>
|
}
|
||||||
{children}
|
}, []);
|
||||||
</AuthProvider>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
interface AuthProviderProps {
|
|
||||||
children: (props: {
|
|
||||||
hasToken: boolean;
|
|
||||||
isAuthenticated: boolean;
|
|
||||||
tokenAuthLoading: boolean;
|
|
||||||
tokenVerifyLoading: boolean;
|
|
||||||
user: User;
|
|
||||||
}) => React.ReactNode;
|
|
||||||
tokenAuth: [
|
|
||||||
MutationFunction<TokenAuth, TokenAuthVariables>,
|
|
||||||
MutationResult<TokenAuth>
|
|
||||||
];
|
|
||||||
tokenVerify: [
|
|
||||||
MutationFunction<VerifyToken, VerifyTokenVariables>,
|
|
||||||
MutationResult<VerifyToken>
|
|
||||||
];
|
|
||||||
tokenRefresh: [
|
|
||||||
MutationFunction<RefreshToken, RefreshTokenVariables>,
|
|
||||||
MutationResult<RefreshToken>
|
|
||||||
];
|
|
||||||
onLogin?: () => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface AuthProviderState {
|
|
||||||
user: User;
|
|
||||||
persistToken: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
class AuthProvider extends React.Component<
|
|
||||||
AuthProviderProps,
|
|
||||||
AuthProviderState
|
|
||||||
> {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.state = { persistToken: false, user: undefined };
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillReceiveProps(props: AuthProviderProps) {
|
|
||||||
const { tokenAuth, tokenVerify } = props;
|
|
||||||
const tokenAuthOpts = tokenAuth[1];
|
|
||||||
const tokenVerifyOpts = tokenVerify[1];
|
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
if (tokenAuthOpts.error || tokenVerifyOpts.error) {
|
if (tokenAuthOpts.error || tokenVerifyOpts.error) {
|
||||||
this.logout();
|
logout();
|
||||||
}
|
}
|
||||||
if (tokenAuthOpts.data) {
|
if (tokenAuthOpts.data) {
|
||||||
const user = tokenAuthOpts.data.tokenCreate.user;
|
const user = tokenAuthOpts.data.tokenCreate.user;
|
||||||
// FIXME: Now we set state also when auth fails and returned user is
|
// FIXME: Now we set state also when auth fails and returned user is
|
||||||
// `null`, because the LoginView uses this `null` to display error.
|
// `null`, because the LoginView uses this `null` to display error.
|
||||||
this.setState({ user });
|
setUserContext(user);
|
||||||
if (user) {
|
if (user) {
|
||||||
setAuthToken(
|
setAuthToken(tokenAuthOpts.data.tokenCreate.token, persistToken);
|
||||||
tokenAuthOpts.data.tokenCreate.token,
|
|
||||||
this.state.persistToken
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (maybe(() => tokenVerifyOpts.data.tokenVerify === null)) {
|
if (maybe(() => tokenVerifyOpts.data.tokenVerify === null)) {
|
||||||
this.logout();
|
logout();
|
||||||
} else {
|
} else {
|
||||||
const user = maybe(() => tokenVerifyOpts.data.tokenVerify.user);
|
const user = maybe(() => tokenVerifyOpts.data.tokenVerify.user);
|
||||||
if (!!user) {
|
if (!!user) {
|
||||||
this.setState({ user });
|
setUserContext(user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}, [tokenAuthOpts, tokenVerifyOpts]);
|
||||||
|
|
||||||
componentDidMount() {
|
const login = async (email: string, password: string) => {
|
||||||
const { user } = this.state;
|
tokenAuth({ variables: { email, password } }).then(result => {
|
||||||
const token = getAuthToken();
|
|
||||||
if (!!token && !user) {
|
|
||||||
this.verifyToken(token);
|
|
||||||
} else {
|
|
||||||
loginWithCredentialsManagementAPI(this.login);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
login = async (email: string, password: string) => {
|
|
||||||
const { tokenAuth, onLogin } = this.props;
|
|
||||||
const [tokenAuthFn] = tokenAuth;
|
|
||||||
|
|
||||||
tokenAuthFn({ variables: { email, password } }).then(result => {
|
|
||||||
if (result && !result.data.tokenCreate.errors.length) {
|
if (result && !result.data.tokenCreate.errors.length) {
|
||||||
if (!!onLogin) {
|
if (!!onLogin) {
|
||||||
onLogin();
|
onLogin();
|
||||||
|
@ -156,65 +87,57 @@ class AuthProvider extends React.Component<
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
loginByToken = (token: string, user: User) => {
|
const loginByToken = (token: string, user: User) => {
|
||||||
this.setState({ user });
|
setUserContext(user);
|
||||||
setAuthToken(token, this.state.persistToken);
|
setAuthToken(token, persistToken);
|
||||||
};
|
};
|
||||||
|
|
||||||
logout = () => {
|
const logout = () => {
|
||||||
this.setState({ user: undefined });
|
setUserContext(undefined);
|
||||||
if (isCredentialsManagementAPISupported) {
|
if (isCredentialsManagementAPISupported) {
|
||||||
navigator.credentials.preventSilentAccess();
|
navigator.credentials.preventSilentAccess();
|
||||||
}
|
}
|
||||||
removeAuthToken();
|
removeAuthToken();
|
||||||
};
|
};
|
||||||
|
|
||||||
verifyToken = (token: string) => {
|
const verifyToken = (token: string) => tokenVerify({ variables: { token } });
|
||||||
const { tokenVerify } = this.props;
|
|
||||||
const [tokenVerifyFn] = tokenVerify;
|
|
||||||
|
|
||||||
return tokenVerifyFn({ variables: { token } });
|
const refreshToken = async () => {
|
||||||
};
|
|
||||||
|
|
||||||
refreshToken = async () => {
|
|
||||||
const { tokenRefresh } = this.props;
|
|
||||||
const [tokenRefreshFn] = tokenRefresh;
|
|
||||||
const token = getAuthToken();
|
const token = getAuthToken();
|
||||||
|
|
||||||
const refreshData = await tokenRefreshFn({ variables: { token } });
|
const refreshData = await tokenRefresh({ variables: { token } });
|
||||||
|
|
||||||
setAuthToken(refreshData.data.tokenRefresh.token, this.state.persistToken);
|
setAuthToken(refreshData.data.tokenRefresh.token, persistToken);
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
return (
|
||||||
const { children, tokenAuth, tokenVerify } = this.props;
|
<UserContext.Provider
|
||||||
const tokenAuthOpts = tokenAuth[1];
|
value={{
|
||||||
const tokenVerifyOpts = tokenVerify[1];
|
login,
|
||||||
const { user } = this.state;
|
loginByToken,
|
||||||
const isAuthenticated = !!user;
|
logout,
|
||||||
|
tokenAuthLoading: tokenAuthOpts.loading,
|
||||||
|
tokenRefresh: refreshToken,
|
||||||
|
tokenVerifyLoading: tokenVerifyOpts.loading,
|
||||||
|
user: userContext
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</UserContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
export const useAuth = () => {
|
||||||
<UserContext.Provider
|
const user = useContext(UserContext);
|
||||||
value={{
|
const isAuthenticated = !!user;
|
||||||
login: this.login,
|
|
||||||
loginByToken: this.loginByToken,
|
|
||||||
logout: this.logout,
|
|
||||||
tokenAuthLoading: tokenAuthOpts.loading,
|
|
||||||
tokenRefresh: this.refreshToken,
|
|
||||||
tokenVerifyLoading: tokenVerifyOpts.loading,
|
|
||||||
user
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{children({
|
|
||||||
hasToken: !!getAuthToken(),
|
|
||||||
isAuthenticated,
|
|
||||||
tokenAuthLoading: tokenAuthOpts.loading,
|
|
||||||
tokenVerifyLoading: tokenVerifyOpts.loading,
|
|
||||||
user
|
|
||||||
})}
|
|
||||||
</UserContext.Provider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default AuthProviderOperations;
|
return {
|
||||||
|
hasToken: !!getAuthToken(),
|
||||||
|
isAuthenticated,
|
||||||
|
tokenAuthLoading: user.tokenAuthLoading,
|
||||||
|
tokenVerifyLoading: user.tokenVerifyLoading,
|
||||||
|
user
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AuthProvider;
|
||||||
|
|
Loading…
Reference in a new issue