2019-01-31 10:15:16 +08:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
|
|
|
"net/http"
|
2022-10-09 00:10:40 +08:00
|
|
|
|
|
|
|
"golang.org/x/oauth2"
|
2019-01-31 10:15:16 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
func githubGetPrimaryEmail(accessToken string) (string, error) {
|
2022-10-09 00:10:40 +08:00
|
|
|
client := &http.Client{}
|
|
|
|
req, err := http.NewRequest("GET", "https://api.github.com/user/emails", nil)
|
|
|
|
if err != nil {
|
|
|
|
logger.Errorf("Error creating github email request: %s", err.Error())
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
req.Header.Add("Accept", "application/vnd.github+json")
|
|
|
|
req.Header.Add("Authorization", "Bearer " + accessToken)
|
|
|
|
resp, err := client.Do(req)
|
|
|
|
if err != nil {
|
|
|
|
logger.Errorf("Error adding github auth token: %s", err.Error())
|
|
|
|
return "", err
|
|
|
|
}
|
2019-01-31 10:15:16 +08:00
|
|
|
defer resp.Body.Close()
|
|
|
|
|
|
|
|
contents, err := ioutil.ReadAll(resp.Body)
|
|
|
|
if err != nil {
|
2019-02-05 07:10:59 +08:00
|
|
|
return "", errorCannotReadResponse
|
2019-01-31 10:15:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
user := []map[string]interface{}{}
|
|
|
|
if err := json.Unmarshal(contents, &user); err != nil {
|
|
|
|
logger.Errorf("error unmarshaling github user: %v", err)
|
|
|
|
return "", errorInternal
|
|
|
|
}
|
|
|
|
|
|
|
|
nonPrimaryEmail := ""
|
2019-02-05 07:10:59 +08:00
|
|
|
for _, email := range user {
|
2019-01-31 10:15:16 +08:00
|
|
|
nonPrimaryEmail = email["email"].(string)
|
|
|
|
if email["primary"].(bool) {
|
|
|
|
return email["email"].(string), nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nonPrimaryEmail, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func githubCallbackHandler(w http.ResponseWriter, r *http.Request) {
|
|
|
|
commenterToken := r.FormValue("state")
|
|
|
|
code := r.FormValue("code")
|
|
|
|
|
|
|
|
_, err := commenterGetByCommenterToken(commenterToken)
|
|
|
|
if err != nil && err != errorNoSuchToken {
|
|
|
|
fmt.Fprintf(w, "Error: %s\n", err.Error())
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
token, err := githubConfig.Exchange(oauth2.NoContext, code)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Fprintf(w, "Error: %s", err.Error())
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
email, err := githubGetPrimaryEmail(token.AccessToken)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Fprintf(w, "Error: %s", err.Error())
|
|
|
|
return
|
|
|
|
}
|
2022-10-09 00:10:40 +08:00
|
|
|
client := &http.Client{}
|
2019-01-31 10:15:16 +08:00
|
|
|
|
2022-10-09 00:10:40 +08:00
|
|
|
req, err := http.NewRequest("GET", "https://api.github.com/user", nil)
|
2019-02-23 10:57:13 +08:00
|
|
|
if err != nil {
|
|
|
|
fmt.Fprintf(w, "Error: %s", err.Error())
|
|
|
|
return
|
|
|
|
}
|
2022-10-09 00:10:40 +08:00
|
|
|
req.Header.Add("Accept", "application/vnd.github+json")
|
|
|
|
req.Header.Add("Authorization", "Bearer " + token.AccessToken)
|
|
|
|
resp, err := client.Do(req)
|
|
|
|
if err != nil {
|
|
|
|
logger.Errorf("Error adding github auth token: %s", err.Error())
|
|
|
|
return
|
|
|
|
}
|
2019-01-31 10:15:16 +08:00
|
|
|
defer resp.Body.Close()
|
|
|
|
|
|
|
|
contents, err := ioutil.ReadAll(resp.Body)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Fprintf(w, "Error: %s", errorCannotReadResponse.Error())
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
user := make(map[string]interface{})
|
|
|
|
if err := json.Unmarshal(contents, &user); err != nil {
|
|
|
|
fmt.Fprintf(w, "Error: %s", errorInternal.Error())
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if email == "" {
|
|
|
|
if user["email"] == nil {
|
|
|
|
fmt.Fprintf(w, "Error: no email address returned by Github")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
email = user["email"].(string)
|
|
|
|
}
|
|
|
|
|
2019-04-10 22:36:46 +08:00
|
|
|
name := user["login"].(string)
|
|
|
|
if user["name"] != nil {
|
|
|
|
name = user["name"].(string)
|
2019-02-23 10:57:13 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
link := "undefined"
|
|
|
|
if user["html_url"] != nil {
|
|
|
|
link = user["html_url"].(string)
|
|
|
|
}
|
|
|
|
|
|
|
|
photo := "undefined"
|
|
|
|
if user["avatar_url"] != nil {
|
|
|
|
photo = user["avatar_url"].(string)
|
|
|
|
}
|
|
|
|
|
2019-01-31 10:15:16 +08:00
|
|
|
c, err := commenterGetByEmail("github", email)
|
|
|
|
if err != nil && err != errorNoSuchCommenter {
|
|
|
|
fmt.Fprintf(w, "Error: %s", err.Error())
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
var commenterHex string
|
|
|
|
|
|
|
|
if err == errorNoSuchCommenter {
|
2019-02-23 10:57:13 +08:00
|
|
|
commenterHex, err = commenterNew(email, name, link, photo, "github", "")
|
2019-01-31 10:15:16 +08:00
|
|
|
if err != nil {
|
|
|
|
fmt.Fprintf(w, "Error: %s", err.Error())
|
|
|
|
return
|
|
|
|
}
|
|
|
|
} else {
|
2019-08-12 06:52:56 +08:00
|
|
|
if err = commenterUpdate(c.CommenterHex, email, name, link, photo, "github"); err != nil {
|
|
|
|
logger.Warningf("cannot update commenter: %s", err)
|
|
|
|
// not a serious enough to exit with an error
|
|
|
|
}
|
|
|
|
|
2019-01-31 10:15:16 +08:00
|
|
|
commenterHex = c.CommenterHex
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := commenterSessionUpdate(commenterToken, commenterHex); err != nil {
|
|
|
|
fmt.Fprintf(w, "Error: %s", err.Error())
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
fmt.Fprintf(w, "<html><script>window.parent.close()</script></html>")
|
|
|
|
}
|