This repository has been archived by the owner on Jan 21, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 4
/
tokencache.go
76 lines (68 loc) · 1.68 KB
/
tokencache.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
// Copyright 2017 Tamás Gulácsi. All rights reserved.
// Use of this source code is governed by an Apache 2.0
// license that can be found in the LICENSE file.
package picago
import (
"encoding/json"
"io"
"os"
"golang.org/x/oauth2"
)
type FileCache struct {
file *os.File
ts oauth2.TokenSource
Log func(...interface{}) error
}
// NewTokenCache returns a TokenSource wrapped in a file cache,
// which saves tokens into the file.
//
// ts can be nil, and later be set with SetTokenSource.
func NewTokenCache(path string, ts oauth2.TokenSource, Log func(...interface{}) error) (*FileCache, error) {
fh, err := os.OpenFile(path, os.O_CREATE|os.O_RDWR, 0600)
if err != nil {
return nil, err
}
return &FileCache{ts: ts, file: fh, Log: Log}, nil
}
func (fc *FileCache) SetTokenSource(ts oauth2.TokenSource) {
if fc == nil {
return
}
if fc.Log != nil {
fc.Log("msg", "SetTokenSource", ts)
}
fc.ts = ts
}
func (fc *FileCache) Token() (*oauth2.Token, error) {
if fc.Log != nil {
fc.Log("msg", "FileCache.Token")
}
_, _ = fc.file.Seek(0, io.SeekStart)
var t oauth2.Token
err := json.NewDecoder(fc.file).Decode(&t)
if fc.Log != nil {
fc.Log("msg", "decode", fc.file.Name(), "token", t, "error", err)
}
if err == nil && t.Valid() {
return &t, nil
}
if fc.ts == nil {
return nil, err
}
var tp *oauth2.Token
tp, err = fc.ts.Token()
if fc.Log != nil {
fc.Log("msg", "pull new token from source", "token", tp, "error", err)
}
if err != nil {
return tp, err
}
_ = fc.file.Truncate(0)
if _, err := fc.file.Seek(0, io.SeekStart); err != nil {
return nil, err
}
if err = json.NewEncoder(fc.file).Encode(t); err != nil {
return &t, err
}
return &t, fc.file.Sync()
}