Skip to content

Commit

Permalink
withAuth -> withUser, fixes #33
Browse files Browse the repository at this point in the history
  • Loading branch information
lorensr committed Aug 29, 2018
1 parent 99ca1eb commit 7220c47
Show file tree
Hide file tree
Showing 8 changed files with 145 additions and 199 deletions.
21 changes: 3 additions & 18 deletions src/components/App.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import React, { Component } from 'react'
import { Switch, Route, Redirect } from 'react-router'
import { Link } from 'react-router-dom'
import PropTypes from 'prop-types'

import logo from '../logo.svg'
import StarCount from './StarCount'
import TableOfContents from './TableOfContents'
import Section from './Section'
import CurrentUser from './CurrentUser'
import Profile from './Profile'
import withAuth from '../lib/withAuth'

const Book = () => (
<div>
Expand All @@ -20,8 +18,6 @@ const Book = () => (

class App extends Component {
render() {
const { logout, ...authProps } = this.props

return (
<div className="App">
<header className="App-header">
Expand All @@ -30,27 +26,16 @@ class App extends Component {
<img src={logo} className="App-logo" alt="logo" />
<h1 className="App-title">The GraphQL Guide</h1>
</Link>
<CurrentUser {...authProps} />
<CurrentUser />
</header>
<Switch>
<Route exact path="/" render={() => <Redirect to="/Preface" />} />
<Route
exact
path="/me"
render={() => <Profile logout={logout} {...authProps} />}
/>
<Route exact path="/me" component={Profile} />
<Route component={Book} />
</Switch>
</div>
)
}
}

App.propTypes = {
user: PropTypes.object,
login: PropTypes.func.isRequired,
logout: PropTypes.func.isRequired,
loading: PropTypes.bool.isRequired
}

export default withAuth(App)
export default App
24 changes: 12 additions & 12 deletions src/components/CurrentUser.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,20 @@ import React from 'react'
import PropTypes from 'prop-types'
import { Link } from 'react-router-dom'

const CurrentUser = ({ user, login, loading }) => {
const User = () => (
<Link to="/me" className="User">
<img src={user.photo} alt={user.firstName} />
{user.firstName}
</Link>
)
import { withUser } from '../lib/withUser'
import { login } from '../lib/auth'

const CurrentUser = ({ user, loggingIn }) => {
let content

if (user) {
content = <User />
} else if (loading) {
content = (
<Link to="/me" className="User">
<img src={user.photo} alt={user.firstName} />
{user.firstName}
</Link>
)
} else if (loggingIn) {
content = <div className="Spinner" />
} else {
content = <button onClick={login}>Sign in</button>
Expand All @@ -28,8 +29,7 @@ CurrentUser.propTypes = {
firstName: PropTypes.string.isRequired,
photo: PropTypes.string.isRequired
}),
login: PropTypes.func.isRequired,
loading: PropTypes.bool.isRequired
loggingIn: PropTypes.bool.isRequired
}

export default CurrentUser
export default withUser(CurrentUser)
13 changes: 7 additions & 6 deletions src/components/Profile.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import React from 'react'
import PropTypes from 'prop-types'

const Profile = ({ user, login, logout, loading }) => {
if (loading) {
import { withUser } from '../lib/withUser'
import { login, logout } from '../lib/auth'

const Profile = ({ user, loggingIn }) => {
if (loggingIn) {
return (
<main className="Profile">
<div className="Spinner" />
Expand Down Expand Up @@ -63,9 +66,7 @@ Profile.propTypes = {
email: PropTypes.string.isRequired,
hasPurchased: PropTypes.string
}),
login: PropTypes.func.isRequired,
logout: PropTypes.func.isRequired,
loading: PropTypes.bool.isRequired
loggingIn: PropTypes.bool.isRequired
}

export default Profile
export default withUser(Profile)
54 changes: 2 additions & 52 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,66 +1,16 @@
import React from 'react'
import ReactDOM from 'react-dom'
import { ApolloClient } from 'apollo-client'
import { ApolloProvider } from 'react-apollo'
import { InMemoryCache } from 'apollo-cache-inmemory'
import { split } from 'apollo-link'
import { WebSocketLink } from 'apollo-link-ws'
import { createHttpLink } from 'apollo-link-http'
import { getMainDefinition } from 'apollo-utilities'
import { BrowserRouter } from 'react-router-dom'
import { setContext } from 'apollo-link-context'
import { getAuthToken } from 'auth0-helpers'

import './index.css'
import registerServiceWorker from './registerServiceWorker'
import App from './components/App'

const httpLink = createHttpLink({
uri: 'https://api.graphql.guide/graphql'
})

const authLink = setContext(async (_, { headers }) => {
const token = await getAuthToken({
doLoginIfTokenExpired: true
})

if (token) {
return {
headers: {
...headers,
authorization: `Bearer ${token}`
}
}
} else {
return { headers }
}
})

const authedHttpLink = authLink.concat(httpLink)

const wsLink = new WebSocketLink({
uri: `wss://api.graphql.guide/subscriptions`,
options: {
reconnect: true
}
})

const link = split(
({ query }) => {
const { kind, operation } = getMainDefinition(query)
return kind === 'OperationDefinition' && operation === 'subscription'
},
wsLink,
authedHttpLink
)

const cache = new InMemoryCache()

const client = new ApolloClient({ link, cache })
import { apollo } from './lib/apollo'

ReactDOM.render(
<BrowserRouter>
<ApolloProvider client={client}>
<ApolloProvider client={apollo}>
<App />
</ApolloProvider>
</BrowserRouter>,
Expand Down
51 changes: 51 additions & 0 deletions src/lib/apollo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { ApolloClient } from 'apollo-client'
import { InMemoryCache } from 'apollo-cache-inmemory'
import { split } from 'apollo-link'
import { WebSocketLink } from 'apollo-link-ws'
import { createHttpLink } from 'apollo-link-http'
import { getMainDefinition } from 'apollo-utilities'
import { setContext } from 'apollo-link-context'
import { getAuthToken } from 'auth0-helpers'

const httpLink = createHttpLink({
uri: 'https://api.graphql.guide/graphql'
})

const authLink = setContext(async (_, { headers }) => {
const token = await getAuthToken({
doLoginIfTokenExpired: true
})

if (token) {
return {
headers: {
...headers,
authorization: `Bearer ${token}`
}
}
} else {
return { headers }
}
})

const authedHttpLink = authLink.concat(httpLink)

const wsLink = new WebSocketLink({
uri: `wss://api.graphql.guide/subscriptions`,
options: {
reconnect: true
}
})

const link = split(
({ query }) => {
const { kind, operation } = getMainDefinition(query)
return kind === 'OperationDefinition' && operation === 'subscription'
},
wsLink,
authedHttpLink
)

const cache = new InMemoryCache()

export const apollo = new ApolloClient({ link, cache })
48 changes: 48 additions & 0 deletions src/lib/auth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import auth0 from 'auth0-js'
import {
initAuthHelpers,
login as auth0Login,
logout as auth0Logout
} from 'auth0-helpers'

import { apollo } from './apollo'

const client = new auth0.WebAuth({
domain: 'graphql.auth0.com',
clientID: '8fErnZoF3hbzQ2AbMYu5xcS0aVNzQ0PC',
responseType: 'token',
audience: 'https://api.graphql.guide',
scope: 'openid profile guide'
})

initAuthHelpers({
client,
usePopup: true,
authOptions: {
connection: 'github',
owp: true,
popupOptions: { height: 623 } // make tall enough for content
},
checkSessionOptions: {
redirect_uri: window.location.origin
},
onError: e => console.error(e)
})

export const login = () => {
auth0Login({
onCompleted: e => {
if (e) {
console.error(e)
return
}

apollo.reFetchObservableQueries()
}
})
}

export const logout = () => {
auth0Logout()
apollo.resetStore()
}
Loading

0 comments on commit 7220c47

Please sign in to comment.