Skip to content

Commit ea23840

Browse files
committed
Implement LinkedIn OAuth login
1 parent 3522692 commit ea23840

File tree

10 files changed

+297
-12
lines changed

10 files changed

+297
-12
lines changed

Godeps/Godeps.json

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cmd/petfindserver/main.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ func main() {
3737
autocertCache = flag.String("autocertdir", "", "directory to cache the Let's Encrypt certificates")
3838
githubID = flag.String("githubid", "", "GitHub Client ID used for Login with GitHub")
3939
githubSecret = flag.String("githubsecret", "", "GitHub Client Secret used for Login with GitHub")
40+
linkedinID = flag.String("linkedinid", "", "LinkedIn Client ID used for Login with LinkedIn")
41+
linkedinSecret = flag.String("linkedinsecret", "", "LinkedIn Client Secret used for Login with LinkedIn")
42+
linkedinURL = flag.String("linkedinurl", "", "LinkedIn redirect URL used for Login with LinkedIn")
4043
cloudinaryKey = flag.String("cloudinarykey", "", "Cloudinary API Key used to upload photos")
4144
cloudinarySecret = flag.String("cloudinarysecret", "", "Cloudinary API Secret used to upload photos")
4245
cloudinaryName = flag.String("cloudinaryname", "", "Cloudinary Cloud Name used to upload photos")
@@ -122,6 +125,7 @@ func main() {
122125
*tmplPath,
123126
photos,
124127
web.NewGitHubOAuthConfig(*githubID, *githubSecret),
128+
web.NewLinkedInOAuthConfig(*linkedinID, *linkedinSecret, *linkedinURL),
125129
)
126130
if err != nil {
127131
log.Println("NewServer failed:", err)

cmd/petfindserver/main_heroku.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ func main() {
5252
photosPath = getenvString("/app/photos", "PHOTOS_PATH")
5353
githubID = getenvString("", "GITHUB_ID")
5454
githubSecret = getenvString("", "GITHUB_SECRET")
55+
linkedinID = getenvString("", "LINKEDIN_ID")
56+
linkedinSecret = getenvString("", "LINKEDIN_SECRET")
57+
linkedinURL = getenvString("", "LINKEDIN_URL")
5558
sessionTTL = getenvInt(1200, "SESSION_TTL")
5659
sessionMaxTTL = getenvInt(3600, "SESSION_MAX_TTL")
5760
redisURL = getenvString("", "REDIS_URL")
@@ -122,6 +125,7 @@ func main() {
122125
tmplPath,
123126
photos,
124127
web.NewGitHubOAuthConfig(githubID, githubSecret),
128+
web.NewLinkedInOAuthConfig(linkedinID, linkedinSecret, linkedinURL),
125129
)
126130
if err != nil {
127131
log.Println("NewServer failed:", err)

petfind/petfind.go

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,8 @@ type Store interface {
116116
GetUser(userID int64) (*User, error)
117117
PutGithubUser(*GithubUser) (*User, error)
118118
GetUserByGithubID(githubID int64) (*User, error)
119+
PutLinkedinUser(*LinkedinUser) (*User, error)
120+
GetUserByLinkedinID(linkedinID string) (*User, error)
119121

120122
AddPhoto(*Photo) error
121123
GetPhoto(photoID int64) (*Photo, error)
@@ -146,13 +148,14 @@ type Search struct {
146148

147149
// User holds information about a user that is signed in the application.
148150
type User struct {
149-
ID int64
150-
GithubID int64
151-
Login string
152-
Name string
153-
Email string
154-
Created time.Time
155-
Updated time.Time
151+
ID int64
152+
GithubID int64
153+
LinkedinID string
154+
Login string
155+
Name string
156+
Email string
157+
Created time.Time
158+
Updated time.Time
156159
}
157160

158161
// GithubUser holds the data that we need to retrieve from a user's GitHub
@@ -164,6 +167,14 @@ type GithubUser struct {
164167
Email string `json:"email"`
165168
}
166169

170+
// LinkedinUser holds the data that we need to retrieve from a user's LinkedIn
171+
// account with their permission.
172+
type LinkedinUser struct {
173+
ID string `json:"id"`
174+
FirstName string `json:"firstName"`
175+
LastName string `json:"lastName"`
176+
}
177+
167178
// TODO(psimika): Useful article in case a custom type needs to be stored in
168179
// the database:
169180
//

petfind/postgres/postgres.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ func (db *store) MakeSchema() error {
3030
// users
3131
const users = `CREATE TABLE IF NOT EXISTS users (
3232
id bigserial PRIMARY KEY,
33-
github_id bigint,
33+
github_id bigint DEFAULT 0,
34+
linkedin_id varchar(100) NOT NULL,
3435
name varchar(70),
3536
login varchar(70),
3637
email varchar(70),

petfind/postgres/users.go

Lines changed: 88 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ import (
99

1010
func (db *store) CreateUser(u *petfind.User) error {
1111
const userInsertStmt = `
12-
INSERT INTO users(github_id, login, name, email, created, updated)
13-
VALUES ($1, $2, $3, $4, now(), now())
12+
INSERT INTO users(github_id, linkedin_id, login, name, email, created, updated)
13+
VALUES ($1, $2, $3, $4, $5, now(), now())
1414
RETURNING id, created, updated
1515
`
1616
stmt, err := db.Prepare(userInsertStmt)
@@ -23,7 +23,7 @@ func (db *store) CreateUser(u *petfind.User) error {
2323
return
2424
}
2525
}()
26-
err = stmt.QueryRow(u.GithubID, u.Login, u.Name, u.Email).Scan(&u.ID, &u.Created, &u.Updated)
26+
err = stmt.QueryRow(u.GithubID, u.LinkedinID, u.Login, u.Name, u.Email).Scan(&u.ID, &u.Created, &u.Updated)
2727
if err != nil {
2828
return err
2929
}
@@ -35,6 +35,7 @@ func (db *store) GetUser(userID int64) (*petfind.User, error) {
3535
SELECT
3636
id,
3737
github_id,
38+
linkedin_id,
3839
login,
3940
name,
4041
email,
@@ -47,6 +48,7 @@ func (db *store) GetUser(userID int64) (*petfind.User, error) {
4748
err := db.QueryRow(userGetQuery, userID).Scan(
4849
&u.ID,
4950
&u.GithubID,
51+
&u.LinkedinID,
5052
&u.Login,
5153
&u.Name,
5254
&u.Email,
@@ -122,6 +124,7 @@ func (db *store) GetUserByGithubID(userID int64) (*petfind.User, error) {
122124
SELECT
123125
id,
124126
github_id,
127+
linkedin_id,
125128
login,
126129
name,
127130
email,
@@ -133,6 +136,88 @@ func (db *store) GetUserByGithubID(userID int64) (*petfind.User, error) {
133136
err := db.QueryRow(userGetByGithubIDQuery, userID).Scan(
134137
&u.ID,
135138
&u.GithubID,
139+
&u.LinkedinID,
140+
&u.Login,
141+
&u.Name,
142+
&u.Email,
143+
&u.Created,
144+
)
145+
if err == sql.ErrNoRows {
146+
return nil, petfind.ErrNotFound
147+
}
148+
if err != nil {
149+
return nil, err
150+
}
151+
return u, nil
152+
}
153+
154+
func (db *store) PutLinkedinUser(llu *petfind.LinkedinUser) (u *petfind.User, err error) {
155+
fmt.Printf("llu: %#v\n", llu)
156+
lluName := fmt.Sprintf("%s %s", llu.FirstName, llu.LastName)
157+
const (
158+
userUpdateStmt = `
159+
UPDATE users SET
160+
name = $2,
161+
updated = now()
162+
WHERE github_id = $1
163+
RETURNING id, github_id, linkedin_id, login, name, email, created, updated
164+
`
165+
userInsertStmt = `
166+
INSERT INTO users(linkedin_id, name, created, updated)
167+
VALUES ($1, $2, now(), now())
168+
RETURNING id, github_id, linkedin_id, login, name, email, created, updated
169+
`
170+
)
171+
172+
tx, err := db.Begin()
173+
if err != nil {
174+
return nil, err
175+
}
176+
defer func() {
177+
if err != nil {
178+
if rerr := tx.Rollback(); rerr != nil {
179+
err = fmt.Errorf("rollback failed: %v: %v", rerr, err)
180+
}
181+
return
182+
}
183+
err = tx.Commit()
184+
}()
185+
186+
u = new(petfind.User)
187+
err = tx.QueryRow(userUpdateStmt, llu.ID, lluName).
188+
Scan(&u.ID, &u.GithubID, &u.LinkedinID, &u.Login, &u.Name, &u.Email, &u.Created, &u.Updated)
189+
if err == sql.ErrNoRows {
190+
err = tx.QueryRow(userInsertStmt, llu.ID, lluName).
191+
Scan(&u.ID, &u.GithubID, &u.LinkedinID, &u.Login, &u.Name, &u.Email, &u.Created, &u.Updated)
192+
if err != nil {
193+
return nil, err
194+
}
195+
return u, nil
196+
}
197+
if err != nil {
198+
return nil, err
199+
}
200+
return u, nil
201+
}
202+
203+
func (db *store) GetUserByLinkedinID(userID string) (*petfind.User, error) {
204+
const userGetByLinkedinIDQuery = `
205+
SELECT
206+
id,
207+
github_id,
208+
linkedin_id,
209+
login,
210+
name,
211+
email,
212+
created
213+
FROM users
214+
WHERE linkedin_id = $1
215+
`
216+
u := new(petfind.User)
217+
err := db.QueryRow(userGetByLinkedinIDQuery, userID).Scan(
218+
&u.ID,
219+
&u.GithubID,
220+
&u.LinkedinID,
136221
&u.Login,
137222
&u.Name,
138223
&u.Email,

vendor/golang.org/x/oauth2/linkedin/linkedin.go

Lines changed: 16 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)