Skip to content

Commit

Permalink
RefreshToken取得処理と実際に使うフェーズを分けた refs #1
Browse files Browse the repository at this point in the history
RefreshTokenは事前にLocalで実行してGCSに保存しておいて、後で使う感じにしてみた
  • Loading branch information
sinmetal committed Dec 11, 2020
1 parent 08a96dc commit 0bb7779
Show file tree
Hide file tree
Showing 6 changed files with 187 additions and 134 deletions.
84 changes: 0 additions & 84 deletions gmail_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,8 @@ package main

import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"net/url"
"os"

"cloud.google.com/go/storage"
"golang.org/x/oauth2"
"google.golang.org/api/gmail/v1"
)

Expand Down Expand Up @@ -41,79 +33,3 @@ func (s *GmailService) Watch(ctx context.Context, userID string, req *gmail.Watc
Expiration: res.Expiration,
}, nil
}

func getCredentialFile(ctx context.Context) ([]byte, error) {
gcs, err := storage.NewClient(ctx)
if err != nil {
return nil, err
}
defer func() {
if err := gcs.Close(); err != nil {
fmt.Printf("failed gcs.Close() err=%v", err)
}
}()

r, err := gcs.Bucket("sinmetal-ironhead-config").Object("client_secret.json").NewReader(ctx)
if err != nil {
return nil, err
}
return ioutil.ReadAll(r)
}

// Retrieve a token, saves the token, then returns the generated client.
func getClient(config *oauth2.Config) *http.Client {
// The file token.json stores the user's access and refresh tokens, and is
// created automatically when the authorization flow completes for the first
// time.
tokFile := "token.json"
tok, err := tokenFromFile(tokFile)
if err != nil {
tok = getTokenFromWeb(config)
saveToken(tokFile, tok)
}
return config.Client(context.Background(), tok)
}

// Retrieves a token from a local file.
func tokenFromFile(file string) (*oauth2.Token, error) {
f, err := os.Open(file)
if err != nil {
return nil, err
}
defer f.Close()
tok := &oauth2.Token{}
err = json.NewDecoder(f).Decode(tok)
return tok, err
}

// Saves a token to a file path.
func saveToken(path string, token *oauth2.Token) {
fmt.Printf("Saving credential file to: %s\n", path)
f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil {
log.Fatalf("Unable to cache oauth token: %v", err)
}
defer f.Close()
json.NewEncoder(f).Encode(token)
}

func getTokenFromWeb(config *oauth2.Config) *oauth2.Token {
authURL := config.AuthCodeURL("state-token", oauth2.AccessTypeOffline)
fmt.Printf("Go to the following link in your browser then type the "+
"authorization code: \n%v\n", authURL)

var authCode string
if _, err := fmt.Scan(&authCode); err != nil {
log.Fatalf("Unable to read authorization code: %v", err)
}
unescapeAuthCode, err := url.QueryUnescape(authCode)
if err != nil {
log.Fatalf("url.QueryUnescape: %v", err)
}

tok, err := config.Exchange(context.Background(), unescapeAuthCode)
if err != nil {
log.Fatalf("Unable to retrieve token from web: %v", err)
}
return tok
}
44 changes: 0 additions & 44 deletions gmail_service_test.go
Original file line number Diff line number Diff line change
@@ -1,45 +1 @@
package main

import (
"context"
"testing"

"golang.org/x/oauth2/google"
"google.golang.org/api/gmail/v1"
"google.golang.org/api/option"
)

func TestGmailService_Watch(t *testing.T) {
ctx := context.Background()

clientSecret, err := getCredentialFile(ctx)
if err != nil {
t.Fatal(err)
}

config, err := google.ConfigFromJSON(clientSecret, gmail.GmailMetadataScope)
if err != nil {
t.Fatal(err)
}

token := getTokenFromWeb(config)
client := config.Client(ctx, token)
gmailService, err := gmail.NewService(ctx, option.WithHTTPClient(client))
if err != nil {
t.Fatal(err)
}

s, err := NewGmailService(ctx, gmailService)
if err != nil {
t.Fatal(err)
}

resp, err := s.Watch(ctx, "[email protected]", &gmail.WatchRequest{
TopicName: "projects/sinmetal-ironhead/topics/gmail",
LabelIds: []string{"tbf-stackdriver-notifications"},
})
if err != nil {
t.Fatal(err)
}
t.Logf("%#v", resp)
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ go 1.11
require (
cloud.google.com/go/storage v1.10.0
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1
google.golang.org/api v0.36.0
)
8 changes: 8 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,12 @@ github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/martian/v3 v3.1.0 h1:wCKgOCHuUEVfsaQLpPSJb7VdYCdTVZQAuOdYm1yc/60=
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
Expand All @@ -109,6 +112,7 @@ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
Expand Down Expand Up @@ -156,6 +160,7 @@ golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHl
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
Expand All @@ -164,6 +169,7 @@ golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
Expand Down Expand Up @@ -294,10 +300,12 @@ golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a h1:+77BOOi9CMFjpy3D2P/OnfSSmC/Hx/fGAQJUAQaM2gc=
golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
Expand Down
56 changes: 50 additions & 6 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,30 @@ package main

import (
"context"
"flag"
"fmt"
"log"
"net/http"
"os"

"golang.org/x/oauth2/google"
"cloud.google.com/go/storage"
"google.golang.org/api/gmail/v1"
"google.golang.org/api/option"
)

func main() {
var (
cmd = flag.String("cmd", "default", "command")
)
flag.Parse()
fmt.Printf("cmd=%s\n", *cmd)

if *cmd == "save-token" {
fmt.Println("save-token")
saveToken()
os.Exit(0)
}

watchGmail()

const addr = ":8080"
Expand All @@ -25,20 +39,50 @@ func helloWorldHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, Ironhead")
}

func saveToken() {
ctx := context.Background()

gcs, err := storage.NewClient(ctx)
if err != nil {
log.Fatalf("failed storage.NewClient err=%#v", err)
}
ts, err := NewTokenService(ctx, "sinmetal-ironhead-config", gcs)
if err != nil {
panic(err)
}
defer func() {
if err := ts.Close(); err != nil {
panic(err)
}
}()

if err := ts.SaveToken(ctx, gmail.GmailMetadataScope); err != nil {
panic(err)
}
}

func watchGmail() {
ctx := context.Background()

clientSecret, err := getCredentialFile(ctx)
gcs, err := storage.NewClient(ctx)
if err != nil {
log.Fatalf("failed storage.NewClient err=%#v", err)
}
ts, err := NewTokenService(ctx, "sinmetal-ironhead-config", gcs)
if err != nil {
log.Fatalf("failed getCredentialFile err=%#v", err)
panic(err)
}
defer func() {
if err := ts.Close(); err != nil {
panic(err)
}
}()

config, err := google.ConfigFromJSON(clientSecret, gmail.GmailMetadataScope)
client, err := ts.CreateHTTPClient(ctx, gmail.GmailMetadataScope)
if err != nil {
log.Fatalf("failed google.ConfigFromJSON err=%#v", err)
panic(err)
}

client := getClient(config)
gmailService, err := gmail.NewService(ctx, option.WithHTTPClient(client))
if err != nil {
log.Fatalf("failed gmail.NewService err=%+v", err)
Expand Down
Loading

0 comments on commit 0bb7779

Please sign in to comment.