Skip to content

Instantly share code, notes, and snippets.

@luandevpro luandevpro/withAuth.js
Last active Jun 29, 2019

Embed
What would you like to do?
import React, { useEffect, useState } from 'react';
import ApolloClient from 'apollo-client';
import { ApolloProvider } from 'react-apollo';
import { split } from 'apollo-link';
import { HttpLink } from 'apollo-link-http';
import { WebSocketLink } from 'apollo-link-ws';
import { getMainDefinition } from 'apollo-utilities';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { ApolloProvider as ApolloHooksProvider } from 'react-apollo-hooks';
import { setContext } from 'apollo-link-context';
import PropTypes from 'prop-types';
import decoded from 'jwt-decode';
import pick from 'lodash/pick';
import { auth, database } from './firebase';
import { getUser, addUser, addUserOnline } from '../graph/user';
import initialApollo from './initialApollo';
const scheme = proto => (window.location.protocol === 'https:' ? `${proto}s` : proto); // eslint-disable-line
const HASURA_GRAPHQL_ENGINE_HOSTNAME = 'cjs-chat.herokuapp.com';
export const GRAPHQL_ENDPOINT = `${scheme('https')}://${HASURA_GRAPHQL_ENGINE_HOSTNAME}/v1/graphql`;
export const WEBSOCKET_ENDPOINT = `${scheme('wss')}://${HASURA_GRAPHQL_ENGINE_HOSTNAME}/v1/graphql`;
function withAuth(BaseComponent) {
function Component(props) {
const [token, setToken] = useState(null);
const [tokens, setTokens] = useState(null);
useEffect(
() =>
auth.onAuthStateChanged(async user => {
if (user) {
const metadataRef = await database.ref(`metadata/${user.uid}/refreshTime`);
const callback = async () => {
const token = await user.getIdToken(true);
const idTokenResult = await user.getIdTokenResult();
const hasuraClaim = await idTokenResult.claims['https://hasura.io/jwt/claims'];
if (hasuraClaim) {
console.log(hasuraClaim);
const result = pick(decoded(token), [
'https://hasura.io/jwt/claims',
'email',
'name',
'picture',
'token',
]);
setToken(token);
setTokens(result);
const initialApolloClient = await initialApollo(token);
initialApolloClient
.query({
query: getUser,
variables: {
id: user.uid,
},
})
.then(users => {
if (users.data.users_by_pk !== null) {
const updateLastSeen = id => {
return initialApolloClient
.mutate({
mutation: addUserOnline,
variables: {
now: new Date().toISOString(),
id,
},
context: {},
})
.then(() => console.log('last seen'));
};
updateLastSeen(result['https://hasura.io/jwt/claims']['x-hasura-user-id']);
setInterval(
() =>
updateLastSeen(
result['https://hasura.io/jwt/claims']['x-hasura-user-id']
),
27000
);
} else {
initialApolloClient
.mutate({
mutation: addUser,
variables: {
objects: [
{
id: user.uid,
email: user.email,
displayName: user.displayName,
photoURL: user.photoURL,
last_seen: new Date().toISOString(),
},
],
},
context: {},
})
.then(() => console.log('success'))
.catch(result => console.log(result));
}
})
.catch(err => {
console.log(err);
});
} else {
const metadataRef = await database.ref(`metadata/${user.uid}/refreshTime`);
const callback = async () => {
await user.getIdToken(true);
};
metadataRef.on('value', callback);
}
};
metadataRef.on('value', callback);
}
}),
[]
);
const httpLink = new HttpLink({
uri: GRAPHQL_ENDPOINT,
headers: {
Authorization: token ? `Bearer ${token}` : '',
},
});
const wsLink = new WebSocketLink({
uri: WEBSOCKET_ENDPOINT,
options: {
reconnect: true,
lazy: true,
connectionParams: async () => {
const getToken = await token;
return {
headers: {
Authorization: getToken ? `Bearer ${getToken}` : '',
authToken: getToken,
},
};
},
},
});
const authLink = setContext((_, { headers }) => {
return {
headers: {
...headers,
Authorization: token ? `Bearer ${token}` : '',
},
};
});
const link = split(
({ query }) => {
const definition = getMainDefinition(query);
return definition.kind === 'OperationDefinition' && definition.operation === 'subscription';
},
wsLink,
authLink.concat(httpLink)
);
const client = new ApolloClient({
link,
cache: new InMemoryCache(),
});
return (
<ApolloProvider client={client}>
<ApolloHooksProvider client={client}>
<BaseComponent {...props} token={tokens} />
</ApolloHooksProvider>
</ApolloProvider>
);
}
Component.propTypes = {
history: PropTypes.object, // eslint-disable-line
};
return Component;
}
export default withAuth;
withAuth.propTypes = {
Component: PropTypes.element, // eslint-disable-line
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.