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 621e844 commit 07dbe66
Show file tree
Hide file tree
Showing 8 changed files with 163 additions and 98 deletions.
23 changes: 4 additions & 19 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'
import Reviews from './Reviews'

const Book = ({ user }) => (
Expand All @@ -24,8 +22,6 @@ const Book = ({ user }) => (

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

return (
<div className="App">
<header className="App-header">
Expand All @@ -34,27 +30,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 render={() => <Book user={this.props.user} />} />
<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)
16 changes: 10 additions & 6 deletions src/components/Reviews.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { graphql } from 'react-apollo'
import { graphql, compose } from 'react-apollo'
import get from 'lodash/get'
import FavoriteIcon from 'material-ui-icons/Favorite'
import Button from 'material-ui/Button'
Expand All @@ -9,6 +9,7 @@ import Modal from 'material-ui/Modal'
import { propType } from 'graphql-anywhere'

import Review from './Review'
import { withUser } from '../lib/withUser'
import ReviewForm from './ReviewForm'

import { REVIEWS_QUERY, REVIEW_ENTRY } from '../graphql/Review'
Expand Down Expand Up @@ -47,10 +48,10 @@ class Reviews extends Component {
{loading ? (
<div className="Spinner" />
) : (
reviews.map(review => (
<Review key={review.id} review={review} user={user} />
))
)}
reviews.map(review => (
<Review key={review.id} review={review} user={user} />
))
)}

{user && (
<div>
Expand Down Expand Up @@ -97,4 +98,7 @@ const withReviews = graphql(REVIEWS_QUERY, {
})
})

export default withReviews(Reviews)
export default compose(
withReviews,
withUser
)(Reviews)
57 changes: 2 additions & 55 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,66 +1,13 @@
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 { MuiThemeProvider, createMuiTheme } from 'material-ui/styles'

import './index.css'
import registerServiceWorker from './registerServiceWorker'
import App from './components/App'
import { errorLink } from './lib/errorLink'

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 networkLink = split(
({ query }) => {
const { kind, operation } = getMainDefinition(query)
return kind === 'OperationDefinition' && operation === 'subscription'
},
wsLink,
authedHttpLink
)

const link = errorLink.concat(networkLink)

const cache = new InMemoryCache()

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

const GRAPHQL_PINK = '#e10098'

Expand All @@ -70,7 +17,7 @@ const theme = createMuiTheme({

ReactDOM.render(
<BrowserRouter>
<ApolloProvider client={client}>
<ApolloProvider client={apollo}>
<MuiThemeProvider theme={theme}>
<App />
</MuiThemeProvider>
Expand Down
55 changes: 55 additions & 0 deletions src/lib/apollo.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
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'

import { errorLink } from './errorLink'

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 networkLink = split(
({ query }) => {
const { kind, operation } = getMainDefinition(query)
return kind === 'OperationDefinition' && operation === 'subscription'
},
wsLink,
authedHttpLink
)

const link = errorLink.concat(networkLink)

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()
}
25 changes: 25 additions & 0 deletions src/lib/withUser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { graphql } from 'react-apollo'
import gql from 'graphql-tag'

export const USER_QUERY = gql`
query UserQuery {
currentUser {
firstName
name
username
email
photo
hasPurchased
favoriteReviews {
id
}
}
}
`

export const withUser = graphql(USER_QUERY, {
props: ({ data: { currentUser, loading } }) => ({
user: currentUser,
loggingIn: loading
})
})

0 comments on commit 07dbe66

Please sign in to comment.