Skip to content

Commit b614200

Browse files
author
Carlos Rufo Jimenez
committed
5.4-end-authentication-v2.1
1 parent c2888d2 commit b614200

File tree

7 files changed

+178
-63
lines changed

7 files changed

+178
-63
lines changed

server/src/generated/prisma.graphql

Lines changed: 29 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -141,16 +141,15 @@ input LinkUpdateManyWithoutPostedByInput {
141141
connect: [LinkWhereUniqueInput!]
142142
disconnect: [LinkWhereUniqueInput!]
143143
delete: [LinkWhereUniqueInput!]
144-
update: [LinkUpdateWithoutPostedByInput!]
145-
upsert: [LinkUpsertWithoutPostedByInput!]
144+
update: [LinkUpdateWithWhereUniqueWithoutPostedByInput!]
145+
upsert: [LinkUpsertWithWhereUniqueWithoutPostedByInput!]
146146
}
147147

148148
input LinkUpdateOneWithoutVotesInput {
149149
create: LinkCreateWithoutVotesInput
150150
connect: LinkWhereUniqueInput
151-
disconnect: LinkWhereUniqueInput
152-
delete: LinkWhereUniqueInput
153-
update: LinkUpdateWithoutVotesInput
151+
delete: Boolean
152+
update: LinkUpdateWithoutVotesDataInput
154153
upsert: LinkUpsertWithoutVotesInput
155154
}
156155

@@ -160,34 +159,28 @@ input LinkUpdateWithoutPostedByDataInput {
160159
votes: VoteUpdateManyWithoutLinkInput
161160
}
162161

163-
input LinkUpdateWithoutPostedByInput {
164-
where: LinkWhereUniqueInput!
165-
data: LinkUpdateWithoutPostedByDataInput!
166-
}
167-
168162
input LinkUpdateWithoutVotesDataInput {
169163
description: String
170164
url: String
171165
postedBy: UserUpdateOneWithoutLinksInput
172166
}
173167

174-
input LinkUpdateWithoutVotesInput {
175-
where: LinkWhereUniqueInput!
176-
data: LinkUpdateWithoutVotesDataInput!
177-
}
178-
179-
input LinkUpsertWithoutPostedByInput {
168+
input LinkUpdateWithWhereUniqueWithoutPostedByInput {
180169
where: LinkWhereUniqueInput!
181-
update: LinkUpdateWithoutPostedByDataInput!
182-
create: LinkCreateWithoutPostedByInput!
170+
data: LinkUpdateWithoutPostedByDataInput!
183171
}
184172

185173
input LinkUpsertWithoutVotesInput {
186-
where: LinkWhereUniqueInput!
187174
update: LinkUpdateWithoutVotesDataInput!
188175
create: LinkCreateWithoutVotesInput!
189176
}
190177

178+
input LinkUpsertWithWhereUniqueWithoutPostedByInput {
179+
where: LinkWhereUniqueInput!
180+
update: LinkUpdateWithoutPostedByDataInput!
181+
create: LinkCreateWithoutPostedByInput!
182+
}
183+
191184
input LinkWhereInput {
192185
AND: [LinkWhereInput!]
193186
OR: [LinkWhereInput!]
@@ -403,18 +396,17 @@ input UserUpdateInput {
403396
input UserUpdateOneWithoutLinksInput {
404397
create: UserCreateWithoutLinksInput
405398
connect: UserWhereUniqueInput
406-
disconnect: UserWhereUniqueInput
407-
delete: UserWhereUniqueInput
408-
update: UserUpdateWithoutLinksInput
399+
disconnect: Boolean
400+
delete: Boolean
401+
update: UserUpdateWithoutLinksDataInput
409402
upsert: UserUpsertWithoutLinksInput
410403
}
411404

412405
input UserUpdateOneWithoutVotesInput {
413406
create: UserCreateWithoutVotesInput
414407
connect: UserWhereUniqueInput
415-
disconnect: UserWhereUniqueInput
416-
delete: UserWhereUniqueInput
417-
update: UserUpdateWithoutVotesInput
408+
delete: Boolean
409+
update: UserUpdateWithoutVotesDataInput
418410
upsert: UserUpsertWithoutVotesInput
419411
}
420412

@@ -425,31 +417,19 @@ input UserUpdateWithoutLinksDataInput {
425417
votes: VoteUpdateManyWithoutUserInput
426418
}
427419

428-
input UserUpdateWithoutLinksInput {
429-
where: UserWhereUniqueInput!
430-
data: UserUpdateWithoutLinksDataInput!
431-
}
432-
433420
input UserUpdateWithoutVotesDataInput {
434421
name: String
435422
email: String
436423
password: String
437424
links: LinkUpdateManyWithoutPostedByInput
438425
}
439426

440-
input UserUpdateWithoutVotesInput {
441-
where: UserWhereUniqueInput!
442-
data: UserUpdateWithoutVotesDataInput!
443-
}
444-
445427
input UserUpsertWithoutLinksInput {
446-
where: UserWhereUniqueInput!
447428
update: UserUpdateWithoutLinksDataInput!
448429
create: UserCreateWithoutLinksInput!
449430
}
450431

451432
input UserUpsertWithoutVotesInput {
452-
where: UserWhereUniqueInput!
453433
update: UserUpdateWithoutVotesDataInput!
454434
create: UserCreateWithoutVotesInput!
455435
}
@@ -600,44 +580,44 @@ input VoteUpdateManyWithoutLinkInput {
600580
connect: [VoteWhereUniqueInput!]
601581
disconnect: [VoteWhereUniqueInput!]
602582
delete: [VoteWhereUniqueInput!]
603-
update: [VoteUpdateWithoutLinkInput!]
604-
upsert: [VoteUpsertWithoutLinkInput!]
583+
update: [VoteUpdateWithWhereUniqueWithoutLinkInput!]
584+
upsert: [VoteUpsertWithWhereUniqueWithoutLinkInput!]
605585
}
606586

607587
input VoteUpdateManyWithoutUserInput {
608588
create: [VoteCreateWithoutUserInput!]
609589
connect: [VoteWhereUniqueInput!]
610590
disconnect: [VoteWhereUniqueInput!]
611591
delete: [VoteWhereUniqueInput!]
612-
update: [VoteUpdateWithoutUserInput!]
613-
upsert: [VoteUpsertWithoutUserInput!]
592+
update: [VoteUpdateWithWhereUniqueWithoutUserInput!]
593+
upsert: [VoteUpsertWithWhereUniqueWithoutUserInput!]
614594
}
615595

616596
input VoteUpdateWithoutLinkDataInput {
617597
user: UserUpdateOneWithoutVotesInput
618598
}
619599

620-
input VoteUpdateWithoutLinkInput {
621-
where: VoteWhereUniqueInput!
622-
data: VoteUpdateWithoutLinkDataInput!
623-
}
624-
625600
input VoteUpdateWithoutUserDataInput {
626601
link: LinkUpdateOneWithoutVotesInput
627602
}
628603

629-
input VoteUpdateWithoutUserInput {
604+
input VoteUpdateWithWhereUniqueWithoutLinkInput {
605+
where: VoteWhereUniqueInput!
606+
data: VoteUpdateWithoutLinkDataInput!
607+
}
608+
609+
input VoteUpdateWithWhereUniqueWithoutUserInput {
630610
where: VoteWhereUniqueInput!
631611
data: VoteUpdateWithoutUserDataInput!
632612
}
633613

634-
input VoteUpsertWithoutLinkInput {
614+
input VoteUpsertWithWhereUniqueWithoutLinkInput {
635615
where: VoteWhereUniqueInput!
636616
update: VoteUpdateWithoutLinkDataInput!
637617
create: VoteCreateWithoutLinkInput!
638618
}
639619

640-
input VoteUpsertWithoutUserInput {
620+
input VoteUpsertWithWhereUniqueWithoutUserInput {
641621
where: VoteWhereUniqueInput!
642622
update: VoteUpdateWithoutUserDataInput!
643623
create: VoteCreateWithoutUserInput!

server/src/resolvers/Mutation.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@ const jwt = require('jsonwebtoken')
33
const { APP_SECRET, getUserId } = require('../utils')
44

55
function post(parent, { url, description }, ctx, info) {
6-
return ctx.db.mutation.createLink({ data: { url, description } }, info)
6+
const userId = getUserId(ctx)
7+
return ctx.db.mutation.createLink(
8+
{ data: { url, description, postedBy: { connect: { id: userId } } } },
9+
info
10+
)
711
}
812

913
async function signup(parent, args, ctx, info) {
@@ -55,7 +59,7 @@ async function vote(parent, args, ctx, info) {
5559
link: { connect: { id: linkId } },
5660
},
5761
},
58-
info,
62+
info
5963
)
6064
}
6165

src/components/App.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React, { Component } from 'react'
22
import LinkList from './LinkList'
33
import CreateLink from './CreateLink'
44
import Header from './Header'
5+
import Login from './Login'
56
import { Switch, Route } from 'react-router-dom'
67

78
class App extends Component {
@@ -11,6 +12,7 @@ class App extends Component {
1112
<Header />
1213
<div className="ph3 pv1 background-gray">
1314
<Switch>
15+
<Route exact path="/login" component={Login} />
1416
<Route exact path="/" component={LinkList} />
1517
<Route exact path="/create" component={CreateLink} />
1618
</Switch>
@@ -20,4 +22,4 @@ class App extends Component {
2022
}
2123
}
2224

23-
export default App
25+
export default App

src/components/Header.js

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,47 @@
11
import React, { Component } from 'react'
22
import { Link } from 'react-router-dom'
33
import { withRouter } from 'react-router'
4+
import { AUTH_TOKEN } from '../constants'
45

56
class Header extends Component {
67
render() {
8+
const authToken = localStorage.getItem(AUTH_TOKEN)
79
return (
810
<div className="flex pa1 justify-between nowrap orange">
911
<div className="flex flex-fixed black">
1012
<div className="fw7 mr1">Hacker News</div>
1113
<Link to="/" className="ml1 no-underline black">
1214
new
1315
</Link>
14-
<div className="ml1">|</div>
15-
<Link to="/create" className="ml1 no-underline black">
16-
submit
17-
</Link>
16+
{authToken && (
17+
<div className="flex">
18+
<div className="ml1">|</div>
19+
<Link to="/create" className="ml1 no-underline black">
20+
submit
21+
</Link>
22+
</div>
23+
)}
24+
</div>
25+
<div className="flex flex-fixed">
26+
{authToken ? (
27+
<div
28+
className="ml1 pointer black"
29+
onClick={() => {
30+
localStorage.removeItem(AUTH_TOKEN)
31+
this.props.history.push(`/`)
32+
}}
33+
>
34+
logout
35+
</div>
36+
) : (
37+
<Link to="/login" className="ml1 no-underline black">
38+
login
39+
</Link>
40+
)}
1841
</div>
1942
</div>
2043
)
2144
}
2245
}
2346

24-
export default withRouter(Header)
47+
export default withRouter(Header)

src/components/Login.js

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import React, { Component } from 'react'
2+
import { AUTH_TOKEN } from '../constants'
3+
import { compose, Mutation } from 'react-apollo'
4+
import gql from 'graphql-tag'
5+
6+
const SIGNUP_MUTATION = gql`
7+
mutation SignupMutation($email: String!, $password: String!, $name: String!) {
8+
signup(email: $email, password: $password, name: $name) {
9+
token
10+
}
11+
}
12+
`
13+
14+
const LOGIN_MUTATION = gql`
15+
mutation LoginMutation($email: String!, $password: String!) {
16+
login(email: $email, password: $password) {
17+
token
18+
}
19+
}
20+
`
21+
22+
class Login extends Component {
23+
state = {
24+
login: true, // switch between Login and SignUp
25+
email: '',
26+
password: '',
27+
name: '',
28+
}
29+
30+
render() {
31+
const { email, password, name } = this.state
32+
return (
33+
<div>
34+
<h4 className="mv3">{this.state.login ? 'Login' : 'Sign Up'}</h4>
35+
<div className="flex flex-column">
36+
{!this.state.login && (
37+
<input
38+
value={this.state.name}
39+
onChange={e => this.setState({ name: e.target.value })}
40+
type="text"
41+
placeholder="Your name"
42+
/>
43+
)}
44+
<input
45+
value={this.state.email}
46+
onChange={e => this.setState({ email: e.target.value })}
47+
type="text"
48+
placeholder="Your email address"
49+
/>
50+
<input
51+
value={this.state.password}
52+
onChange={e => this.setState({ password: e.target.value })}
53+
type="password"
54+
placeholder="Choose a safe password"
55+
/>
56+
</div>
57+
<div className="flex mt3">
58+
<Mutation
59+
mutation={this.state.login ? LOGIN_MUTATION : SIGNUP_MUTATION}
60+
variables={{ email, password, name }}
61+
onCompleted={data => this._confirm(data)}
62+
>
63+
{mutation => (
64+
<div className="pointer mr2 button" onClick={mutation}>
65+
{this.state.login ? 'login' : 'create account'}
66+
</div>
67+
)}
68+
</Mutation>
69+
<div
70+
className="pointer button"
71+
onClick={() => this.setState({ login: !this.state.login })}
72+
>
73+
{this.state.login
74+
? 'need to create an account?'
75+
: 'already have an account?'}
76+
</div>
77+
</div>
78+
</div>
79+
)
80+
}
81+
82+
_confirm = data => {
83+
const { token } = this.state.login ? data.login : data.signup
84+
this._saveUserData(token) && this.props.history.push(`/`)
85+
}
86+
87+
_saveUserData = token => {
88+
localStorage.setItem(AUTH_TOKEN, token)
89+
}
90+
}
91+
92+
export default Login

src/constants.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const AUTH_TOKEN = 'auth-token'

0 commit comments

Comments
 (0)