Skip to content

Commit d2b263a

Browse files
committed
withAuth -> withUser, fixes #33
1 parent eb1f220 commit d2b263a

File tree

8 files changed

+155
-91
lines changed

8 files changed

+155
-91
lines changed

src/components/App.js

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
11
import React, { Component } from 'react'
22
import { Switch, Route, Redirect } from 'react-router'
33
import { Link } from 'react-router-dom'
4-
import PropTypes from 'prop-types'
54

65
import logo from '../logo.svg'
76
import StarCount from './StarCount'
87
import TableOfContents from './TableOfContents'
98
import Section from './Section'
109
import CurrentUser from './CurrentUser'
1110
import Profile from './Profile'
12-
import withAuth from '../lib/withAuth'
1311
import Reviews from './Reviews'
1412

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

2523
class App extends Component {
2624
render() {
27-
const { logout, ...authProps } = this.props
28-
2925
return (
3026
<div className="App">
3127
<header className="App-header">
@@ -34,27 +30,16 @@ class App extends Component {
3430
<img src={logo} className="App-logo" alt="logo" />
3531
<h1 className="App-title">The GraphQL Guide</h1>
3632
</Link>
37-
<CurrentUser {...authProps} />
33+
<CurrentUser />
3834
</header>
3935
<Switch>
4036
<Route exact path="/" render={() => <Redirect to="/Preface" />} />
41-
<Route
42-
exact
43-
path="/me"
44-
render={() => <Profile logout={logout} {...authProps} />}
45-
/>
46-
<Route render={() => <Book user={this.props.user} />} />
37+
<Route exact path="/me" component={Profile} />
38+
<Route component={Book} />
4739
</Switch>
4840
</div>
4941
)
5042
}
5143
}
5244

53-
App.propTypes = {
54-
user: PropTypes.object,
55-
login: PropTypes.func.isRequired,
56-
logout: PropTypes.func.isRequired,
57-
loading: PropTypes.bool.isRequired
58-
}
59-
60-
export default withAuth(App)
45+
export default App

src/components/CurrentUser.js

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,20 @@ import React from 'react'
22
import PropTypes from 'prop-types'
33
import { Link } from 'react-router-dom'
44

5-
const CurrentUser = ({ user, login, loading }) => {
6-
const User = () => (
7-
<Link to="/me" className="User">
8-
<img src={user.photo} alt={user.firstName} />
9-
{user.firstName}
10-
</Link>
11-
)
5+
import { withUser } from '../lib/withUser'
6+
import { login } from '../lib/auth'
127

8+
const CurrentUser = ({ user, loggingIn }) => {
139
let content
1410

1511
if (user) {
16-
content = <User />
17-
} else if (loading) {
12+
content = (
13+
<Link to="/me" className="User">
14+
<img src={user.photo} alt={user.firstName} />
15+
{user.firstName}
16+
</Link>
17+
)
18+
} else if (loggingIn) {
1819
content = <div className="Spinner" />
1920
} else {
2021
content = <button onClick={login}>Sign in</button>
@@ -28,8 +29,7 @@ CurrentUser.propTypes = {
2829
firstName: PropTypes.string.isRequired,
2930
photo: PropTypes.string.isRequired
3031
}),
31-
login: PropTypes.func.isRequired,
32-
loading: PropTypes.bool.isRequired
32+
loggingIn: PropTypes.bool.isRequired
3333
}
3434

35-
export default CurrentUser
35+
export default withUser(CurrentUser)

src/components/Profile.js

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
import React from 'react'
22
import PropTypes from 'prop-types'
33

4-
const Profile = ({ user, login, logout, loading }) => {
5-
if (loading) {
4+
import { withUser } from '../lib/withUser'
5+
import { login, logout } from '../lib/auth'
6+
7+
const Profile = ({ user, loggingIn }) => {
8+
if (loggingIn) {
69
return (
710
<main className="Profile">
811
<div className="Spinner" />
@@ -63,9 +66,7 @@ Profile.propTypes = {
6366
email: PropTypes.string.isRequired,
6467
hasPurchased: PropTypes.string
6568
}),
66-
login: PropTypes.func.isRequired,
67-
logout: PropTypes.func.isRequired,
68-
loading: PropTypes.bool.isRequired
69+
loggingIn: PropTypes.bool.isRequired
6970
}
7071

71-
export default Profile
72+
export default withUser(Profile)

src/components/Reviews.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React, { Component } from 'react'
22
import PropTypes from 'prop-types'
3-
import { graphql } from 'react-apollo'
3+
import { graphql, compose } from 'react-apollo'
44
import get from 'lodash/get'
55
import FavoriteIcon from 'material-ui-icons/Favorite'
66
import Button from 'material-ui/Button'
@@ -9,6 +9,7 @@ import Modal from 'material-ui/Modal'
99
import { propType } from 'graphql-anywhere'
1010

1111
import Review from './Review'
12+
import { withUser } from '../lib/withUser'
1213
import AddReview from './AddReview'
1314

1415
import { REVIEWS_QUERY, REVIEW_ENTRY } from '../graphql/Review'
@@ -91,4 +92,7 @@ const withReviews = graphql(REVIEWS_QUERY, {
9192
props: ({ data: { reviews, loading } }) => ({ reviews, loading })
9293
})
9394

94-
export default withReviews(Reviews)
95+
export default compose(
96+
withReviews,
97+
withUser
98+
)(Reviews)

src/index.js

Lines changed: 2 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,13 @@
11
import React from 'react'
22
import ReactDOM from 'react-dom'
3-
import { ApolloClient } from 'apollo-client'
43
import { ApolloProvider } from 'react-apollo'
5-
import { InMemoryCache } from 'apollo-cache-inmemory'
6-
import { split } from 'apollo-link'
7-
import { WebSocketLink } from 'apollo-link-ws'
8-
import { createHttpLink } from 'apollo-link-http'
9-
import { getMainDefinition } from 'apollo-utilities'
104
import { BrowserRouter } from 'react-router-dom'
11-
import { setContext } from 'apollo-link-context'
12-
import { getAuthToken } from 'auth0-helpers'
135
import { MuiThemeProvider, createMuiTheme } from 'material-ui/styles'
146

157
import './index.css'
168
import registerServiceWorker from './registerServiceWorker'
179
import App from './components/App'
18-
19-
const httpLink = createHttpLink({
20-
uri: 'https://api.graphql.guide/graphql'
21-
})
22-
23-
const authLink = setContext(async (_, { headers }) => {
24-
const token = await getAuthToken({
25-
doLoginIfTokenExpired: true
26-
})
27-
28-
if (token) {
29-
return {
30-
headers: {
31-
...headers,
32-
authorization: `Bearer ${token}`
33-
}
34-
}
35-
} else {
36-
return { headers }
37-
}
38-
})
39-
40-
const authedHttpLink = authLink.concat(httpLink)
41-
42-
const wsLink = new WebSocketLink({
43-
uri: `wss://api.graphql.guide/subscriptions`,
44-
options: {
45-
reconnect: true
46-
}
47-
})
48-
49-
const link = split(
50-
({ query }) => {
51-
const { kind, operation } = getMainDefinition(query)
52-
return kind === 'OperationDefinition' && operation === 'subscription'
53-
},
54-
wsLink,
55-
authedHttpLink
56-
)
57-
58-
const cache = new InMemoryCache()
59-
60-
const client = new ApolloClient({ link, cache })
10+
import { apollo } from './lib/apollo'
6111

6212
const GRAPHQL_PINK = '#e10098'
6313

@@ -67,7 +17,7 @@ const theme = createMuiTheme({
6717

6818
ReactDOM.render(
6919
<BrowserRouter>
70-
<ApolloProvider client={client}>
20+
<ApolloProvider client={apollo}>
7121
<MuiThemeProvider theme={theme}>
7222
<App />
7323
</MuiThemeProvider>

src/lib/apollo.js

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { ApolloClient } from 'apollo-client'
2+
import { InMemoryCache } from 'apollo-cache-inmemory'
3+
import { split } from 'apollo-link'
4+
import { WebSocketLink } from 'apollo-link-ws'
5+
import { createHttpLink } from 'apollo-link-http'
6+
import { getMainDefinition } from 'apollo-utilities'
7+
import { setContext } from 'apollo-link-context'
8+
import { getAuthToken } from 'auth0-helpers'
9+
10+
const httpLink = createHttpLink({
11+
uri: 'https://api.graphql.guide/graphql'
12+
})
13+
14+
const authLink = setContext(async (_, { headers }) => {
15+
const token = await getAuthToken({
16+
doLoginIfTokenExpired: true
17+
})
18+
19+
if (token) {
20+
return {
21+
headers: {
22+
...headers,
23+
authorization: `Bearer ${token}`
24+
}
25+
}
26+
} else {
27+
return { headers }
28+
}
29+
})
30+
31+
const authedHttpLink = authLink.concat(httpLink)
32+
33+
const wsLink = new WebSocketLink({
34+
uri: `wss://api.graphql.guide/subscriptions`,
35+
options: {
36+
reconnect: true
37+
}
38+
})
39+
40+
const link = split(
41+
({ query }) => {
42+
const { kind, operation } = getMainDefinition(query)
43+
return kind === 'OperationDefinition' && operation === 'subscription'
44+
},
45+
wsLink,
46+
authedHttpLink
47+
)
48+
49+
const cache = new InMemoryCache()
50+
51+
export const apollo = new ApolloClient({ link, cache })

src/lib/auth.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import auth0 from 'auth0-js'
2+
import {
3+
initAuthHelpers,
4+
login as auth0Login,
5+
logout as auth0Logout
6+
} from 'auth0-helpers'
7+
8+
import { apollo } from './apollo'
9+
10+
const client = new auth0.WebAuth({
11+
domain: 'graphql.auth0.com',
12+
clientID: '8fErnZoF3hbzQ2AbMYu5xcS0aVNzQ0PC',
13+
responseType: 'token',
14+
audience: 'https://api.graphql.guide',
15+
scope: 'openid profile guide'
16+
})
17+
18+
initAuthHelpers({
19+
client,
20+
usePopup: true,
21+
authOptions: {
22+
connection: 'github',
23+
owp: true,
24+
popupOptions: { height: 623 } // make tall enough for content
25+
},
26+
checkSessionOptions: {
27+
redirect_uri: window.location.origin
28+
},
29+
onError: e => console.error(e)
30+
})
31+
32+
export const login = () => {
33+
auth0Login({
34+
onCompleted: e => {
35+
if (e) {
36+
console.error(e)
37+
return
38+
}
39+
40+
apollo.reFetchObservableQueries()
41+
}
42+
})
43+
}
44+
45+
export const logout = () => {
46+
auth0Logout()
47+
apollo.resetStore()
48+
}

src/lib/withUser.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { graphql } from 'react-apollo'
2+
import gql from 'graphql-tag'
3+
4+
export const USER_QUERY = gql`
5+
query UserQuery {
6+
currentUser {
7+
firstName
8+
name
9+
username
10+
email
11+
photo
12+
hasPurchased
13+
favoriteReviews {
14+
id
15+
}
16+
}
17+
}
18+
`
19+
20+
export const withUser = graphql(USER_QUERY, {
21+
props: ({ data: { currentUser, loading } }) => ({
22+
user: currentUser,
23+
loggingIn: loading
24+
})
25+
})

0 commit comments

Comments
 (0)