Puberty commit
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
package github
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/juju/errors"
|
||||
|
||||
"github.com/localhots/cmdui/backend/config"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
ID uint `json:"id"`
|
||||
Login string `json:"login"`
|
||||
Name string `json:"name"`
|
||||
Picture string `json:"avatar_url"`
|
||||
}
|
||||
|
||||
const (
|
||||
authorizeURL = "https://github.com/login/oauth/authorize"
|
||||
accessTokenURL = "https://github.com/login/oauth/access_token"
|
||||
userDetailsURL = "https://api.github.com/user"
|
||||
)
|
||||
|
||||
func RedirectToLogin(w http.ResponseWriter, r *http.Request) {
|
||||
urlStr := authorizeURL + "?" + url.Values{
|
||||
"client_id": {config.Get().Github.ClientID},
|
||||
"scope": {"user"},
|
||||
}.Encode()
|
||||
http.Redirect(w, r, urlStr, http.StatusTemporaryRedirect)
|
||||
}
|
||||
|
||||
func ExchangeCode(ctx context.Context, code string) (accessToken string, err error) {
|
||||
cfg := config.Get()
|
||||
reqBody := bytes.NewBufferString(url.Values{
|
||||
"client_id": {cfg.Github.ClientID},
|
||||
"client_secret": {cfg.Github.ClientSecret},
|
||||
"code": {code},
|
||||
}.Encode())
|
||||
req, err := http.NewRequest(http.MethodPost, accessTokenURL, reqBody)
|
||||
if err != nil {
|
||||
return "", errors.Annotate(err, "Failed to create a code exchange request")
|
||||
}
|
||||
|
||||
// Passing client request context
|
||||
req = req.WithContext(ctx)
|
||||
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return "", errors.Annotate(err, "Failed to perform code exchange request")
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
respBody, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return "", errors.Annotate(err, "Failed to read access token response")
|
||||
}
|
||||
|
||||
uri, err := url.ParseQuery(string(respBody))
|
||||
if err != nil {
|
||||
return "", errors.Annotate(err, "Failed to parse access token response")
|
||||
}
|
||||
|
||||
return uri.Get("access_token"), nil
|
||||
}
|
||||
|
||||
func AuthDetails(accessToken string) (User, error) {
|
||||
var u User
|
||||
reqURL := userDetailsURL + "?" + url.Values{
|
||||
"access_token": {accessToken},
|
||||
}.Encode()
|
||||
resp, err := http.Get(reqURL)
|
||||
if err != nil {
|
||||
return u, errors.Annotate(err, "Failed to fetch authenticated user details")
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return u, errors.Annotate(err, "Failed to read authenticated user details")
|
||||
}
|
||||
if err := json.Unmarshal(body, &u); err != nil {
|
||||
return u, errors.Annotate(err, "Failed to parse authenticated user details")
|
||||
}
|
||||
|
||||
return u, nil
|
||||
}
|
||||
Reference in New Issue
Block a user