add oauth flow routes

This commit is contained in:
Jay
2019-12-28 14:38:38 +00:00
parent 369e8d3f6e
commit 6ff437be99
10 changed files with 367 additions and 13 deletions
+139 -1
View File
@@ -1,6 +1,17 @@
package google
import "net/url"
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"go-cal/pkg/config"
"go-cal/pkg/types"
"io/ioutil"
"net/http"
"net/url"
"time"
)
var baseURL = "https://www.googleapis.com/"
@@ -22,3 +33,130 @@ func getHeaders() map[string]string {
return obj
}
// OAuthExchangeCodeToToken -
func OAuthExchangeCodeToToken(code string) (token types.GoogleAuthToken, err error) {
conf := config.Get()
if conf == nil {
return token, errors.New("config not init")
}
u, err := url.Parse(conf.Google.TokenURL)
if err != nil {
return
}
qs := url.Values{}
qs.Set("code", code)
qs.Set("client_id", conf.Google.ClientID)
qs.Set("client_secret", conf.Google.ClientSecret)
qs.Set("redirect_uri", conf.Google.RedirectURL)
qs.Set("grant_type", "authorization_code")
reader := bytes.NewReader([]byte(qs.Encode()))
req, err := http.NewRequest("POST", fmt.Sprintf("%s", u.String()), reader)
if err != nil {
return
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
resp, err := http.DefaultClient.Do(req)
if err != nil {
return
}
defer resp.Body.Close()
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
return
}
err = json.Unmarshal(b, &token)
if err != nil {
return
}
return
}
// OAuthRefreshToken -
func OAuthRefreshToken(refreshToken string) (token string, expiresIn int64, err error) {
if len(refreshToken) == 0 {
return "", 0, errors.New("refresh token is empty")
}
conf := config.Get()
if conf == nil {
return "", 0, errors.New("config not init")
}
u, err := url.Parse(conf.Google.TokenURL)
if err != nil {
return
}
qs := url.Values{}
qs.Set("client_id", conf.Google.ClientID)
qs.Set("client_secret", conf.Google.ClientSecret)
qs.Set("grant_type", "refresh_token")
reader := bytes.NewReader([]byte(qs.Encode()))
req, err := http.NewRequest("POST", u.String(), reader)
if err != nil {
return
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
resp, err := http.DefaultClient.Do(req)
if err != nil {
return
}
defer resp.Body.Close()
var tokenData types.GoogleAuthToken
err = json.NewDecoder(resp.Body).Decode(&tokenData)
if err != nil {
return
}
tokenData.ExpiresIn += time.Now().Unix()
return tokenData.AccessToken, tokenData.ExpiresIn, nil
}
// GetTokenInfo -
func GetTokenInfo(token string) (expire int64, err error) {
u, err := url.Parse("https://oauth2.googleapis.com/tokeninfo")
if err != nil {
return
}
body := struct {
Azp string `json:"azp"`
Aud string `json:"aud"`
Scope string `json:"scope"`
Exp json.Number `json:"exp"`
ExpiresIn json.Number `json:"expires_in"`
AccessType string `json:"access_type"`
}{}
qs := url.Values{}
qs.Set("access_token", token)
resp, err := http.Get(fmt.Sprintf("%s?%s", u.String(), qs.Encode()))
if err != nil {
return
}
defer resp.Body.Close()
err = json.NewDecoder(resp.Body).Decode(&body)
if err != nil {
return
}
expTime, err := body.Exp.Int64()
if err != nil {
return
}
return expTime, nil
}
+15 -3
View File
@@ -13,13 +13,25 @@ import (
// Google config
type Google struct {
APIKey string `yaml:"api_key" env:"GOOGLE_API_KEY"`
APIKey string `yaml:"api_key" env:"GOOGLE_API_KEY"`
ClientID string `yaml:"client_id" env:"GOOGLE_CLIENT_ID"`
AuthURL string `yaml:"auth_url" env:"GOOGLE_AUTH_URL"`
TokenURL string `yaml:"token_url" env:"GOOGLE_TOKEN_URL"`
ClientSecret string `yaml:"client_secret" env:"GOOGLE_CLIENT_SECRET"`
RedirectURL string `yaml:"redirect_url" env:"GOOGLE_REDIRECT_URL"`
Scopes []string `yaml:"scopes" env:"GOOGLE_SCOPES"`
}
// Storage struct
type Storage struct {
Path string `yaml:"path" env:"STORAGE_FILE_PATH"`
}
// Config main struct
type Config struct {
Port int `yaml:"port" env:"PORT"`
Google Google `yaml:"google"`
Port int `yaml:"port" env:"PORT"`
Google Google `yaml:"google"`
Storage Storage `yaml:"storage"`
}
var conf *Config
+24 -9
View File
@@ -4,6 +4,7 @@ import (
"encoding/json"
"errors"
"io/ioutil"
"sync"
"git.trj.tw/golang/utils"
)
@@ -12,6 +13,7 @@ import (
type Storage struct {
m map[string]interface{}
filePath string
sync.Mutex
}
var s *Storage
@@ -30,24 +32,31 @@ func New() *Storage {
func Get() *Storage { return s }
// Load storage data from file
func (p *Storage) Load(filePath string) (err error) {
func (p *Storage) Load(filePath string, ignoreNotExist bool) (err error) {
filePath = utils.ParsePath(filePath)
if !utils.CheckExists(filePath, false) {
exist := utils.CheckExists(filePath, false)
if !exist && !ignoreNotExist {
return errors.New("storage file not found")
}
p.filePath = filePath
b, err := ioutil.ReadFile(filePath)
if err != nil {
return
}
if exist {
b, err := ioutil.ReadFile(filePath)
if err != nil {
return err
}
err = json.Unmarshal(b, &p.m)
if err := json.Unmarshal(b, &p.m); err != nil {
return err
}
}
return
}
func (p *Storage) Write() (err error) {
p.Lock()
defer p.Unlock()
b, err := json.Marshal(p.m)
if err != nil {
return
@@ -64,7 +73,13 @@ func (p *Storage) Get(key string) (data interface{}, ok bool) {
}
// Set data by key
func (p *Storage) Set(key string, value interface{}) { p.m[key] = value }
func (p *Storage) Set(key string, value interface{}) {
p.m[key] = value
_ = p.Write()
}
// Delete data by key
func (p *Storage) Delete(key string) { delete(p.m, key) }
func (p *Storage) Delete(key string) {
delete(p.m, key)
_ = p.Write()
}
+9
View File
@@ -0,0 +1,9 @@
package types
// GoogleAuthToken -
type GoogleAuthToken struct {
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token,omitempty"`
ExpiresIn int64 `json:"expires_in"`
TokenType string `json:"token_type"`
}