import React from "react"; import { getMutationProviderData } from "../misc"; import { PartialMutationProviderOutput } from "../types"; import { getAuthToken, removeAuthToken, setAuthToken, UserContext } from "./"; import { TypedTokenAuthMutation, TypedVerifyTokenMutation } from "./mutations"; import { TokenAuth, TokenAuthVariables } from "./types/TokenAuth"; import { User } from "./types/User"; import { VerifyToken, VerifyTokenVariables } from "./types/VerifyToken"; interface AuthProviderOperationsProps { children: ( props: { hasToken: boolean; isAuthenticated: boolean; tokenAuthLoading: boolean; tokenVerifyLoading: boolean; user: User; } ) => React.ReactNode; } const AuthProviderOperations: React.StatelessComponent< AuthProviderOperationsProps > = ({ children }) => { return ( {(...tokenAuth) => ( {(...tokenVerify) => ( {children} )} )} ); }; interface AuthProviderProps { children: ( props: { hasToken: boolean; isAuthenticated: boolean; tokenAuthLoading: boolean; tokenVerifyLoading: boolean; user: User; } ) => React.ReactNode; tokenAuth: PartialMutationProviderOutput; tokenVerify: PartialMutationProviderOutput; } interface AuthProviderState { user: User; persistToken: boolean; } class AuthProvider extends React.Component< AuthProviderProps, AuthProviderState > { constructor(props) { super(props); this.state = { user: undefined, persistToken: false }; } componentWillReceiveProps(props: AuthProviderProps) { const { tokenAuth, tokenVerify } = props; if (tokenAuth.opts.error || tokenVerify.opts.error) { this.logout(); } if (tokenAuth.opts.data) { const user = tokenAuth.opts.data.tokenCreate.user; // FIXME: Now we set state also when auth fails and returned user is // `null`, because the LoginView uses this `null` to display error. this.setState({ user }); if (user) { setAuthToken( tokenAuth.opts.data.tokenCreate.token, this.state.persistToken ); } } else { if (tokenVerify.opts.data && tokenVerify.opts.data.tokenVerify.user) { const user = tokenVerify.opts.data.tokenVerify.user; this.setState({ user }); } } } componentDidMount() { const { user } = this.state; const { tokenVerify } = this.props; const token = getAuthToken(); if (!!token && !user) { tokenVerify.mutate({ token }); } } login = (email: string, password: string, persistToken: boolean) => { const { tokenAuth } = this.props; this.setState({ persistToken }); tokenAuth.mutate({ email, password }); }; logout = () => { this.setState({ user: undefined }); removeAuthToken(); }; render() { const { children, tokenAuth, tokenVerify } = this.props; const { user } = this.state; const isAuthenticated = !!user; return ( {children({ hasToken: !!getAuthToken(), isAuthenticated, tokenAuthLoading: tokenAuth.opts.loading, tokenVerifyLoading: tokenVerify.opts.loading, user })} ); } } export default AuthProviderOperations;