Last active
July 16, 2021 09:34
-
-
Save luandevpro/e196152980c0b2e895aa61cea8425f1d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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