Skip to content

Commit e0f44ac

Browse files
committed
added ecobee.New() and Options
Deprecated ecobee.NewClient() All client creation options are now passed through ecobee.Options. This allows persisting OAuth2 tokens in storage other than files, for example etcd or a database and allows passing custom context.
1 parent 2359387 commit e0f44ac

1 file changed

Lines changed: 69 additions & 11 deletions

File tree

ecobee/auth.go

Lines changed: 69 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ package ecobee
1717
import (
1818
"context"
1919
"encoding/json"
20+
"errors"
2021
"fmt"
2122
"io/ioutil"
2223
"net/http"
@@ -31,17 +32,45 @@ import (
3132
var Scopes = []string{"smartRead", "smartWrite"}
3233

3334
type tokenSource struct {
34-
token oauth2.Token
35-
cacheFile, clientID string
35+
token oauth2.Token
36+
clientID string
37+
authCache AuthCache
38+
}
39+
40+
// AuthCache encapsulates persistent cache for OAuth2 token.
41+
type AuthCache interface {
42+
LoadTokenData() ([]byte, error)
43+
SaveTokenData(data []byte) error
44+
}
45+
46+
type fileAuthCache struct {
47+
fileName string
48+
}
49+
50+
func (p fileAuthCache) LoadTokenData() ([]byte, error) {
51+
return ioutil.ReadFile(p.fileName)
52+
}
53+
54+
func (p fileAuthCache) SaveTokenData(data []byte) error {
55+
return ioutil.WriteFile(p.fileName, data, 0777)
56+
}
57+
58+
// TokenCacheFile returns AuthCache that persists the OAuth2 token in the specified file.
59+
func TokenCacheFile(fileName string) AuthCache {
60+
return fileAuthCache{fileName}
3661
}
3762

3863
func TokenSource(clientID, cacheFile string) oauth2.TokenSource {
39-
return oauth2.ReuseTokenSource(nil, newTokenSource(clientID, cacheFile))
64+
return TokenSourceWithAuthCache(clientID, fileAuthCache{cacheFile})
4065
}
4166

42-
func newTokenSource(clientID, cacheFile string) *tokenSource {
43-
file, err := ioutil.ReadFile(cacheFile)
44-
ets := tokenSource{clientID: clientID, cacheFile: cacheFile}
67+
func TokenSourceWithAuthCache(clientID string, authCache AuthCache) oauth2.TokenSource {
68+
return oauth2.ReuseTokenSource(nil, newTokenSource(clientID, authCache))
69+
}
70+
71+
func newTokenSource(clientID string, authCache AuthCache) *tokenSource {
72+
file, err := authCache.LoadTokenData()
73+
ets := tokenSource{clientID: clientID, authCache: authCache}
4574
if err != nil {
4675
// no file, corrupted, or other problem: just start with an
4776
// empty token.
@@ -56,8 +85,7 @@ func (ts *tokenSource) save() error {
5685
if err != nil {
5786
return err
5887
}
59-
err = ioutil.WriteFile(ts.cacheFile, d, 0777)
60-
return err
88+
return ts.authCache.SaveTokenData(d)
6189
}
6290

6391
func (ts *tokenSource) firstAuth() error {
@@ -204,8 +232,38 @@ type Client struct {
204232
// (Application Key). Use the Ecobee Developer Portal to create the
205233
// Application Key.
206234
// (https://www.ecobee.com/consumerportal/index.html#/dev)
235+
// This function is deprecated - use New() instead.
207236
func NewClient(clientID, authCache string) *Client {
208-
return &Client{oauth2.NewClient(
209-
context.Background(),
210-
TokenSource(clientID, authCache))}
237+
c, err := New(context.TODO(), clientID, Options{
238+
AuthCache: fileAuthCache{authCache},
239+
})
240+
241+
if err != nil {
242+
// can't fail here.
243+
panic("unexpected usage: " + err.Error())
244+
}
245+
246+
return c
247+
}
248+
249+
// Options specifies EcoBee client parameters.
250+
type Options struct {
251+
ApplicationID string // application ID created in Ecobee Developer Portal
252+
AuthCache AuthCache // token cache, typically TokenCacheFile(fileName)
253+
}
254+
255+
// New creates a Ecobee API client for the specific options
256+
// Use the Ecobee Developer Portal to create the Application Key.
257+
// (https://www.ecobee.com/consumerportal/index.html#/dev)
258+
func New(ctx context.Context, clientID string, opt Options) (*Client, error) {
259+
if opt.ApplicationID == "" {
260+
return nil, errors.New("application ID is required")
261+
}
262+
if opt.AuthCache == nil {
263+
return nil, fmt.Errorf("auth cache is required")
264+
}
265+
266+
ts := TokenSourceWithAuthCache(clientID, opt.AuthCache)
267+
cli := oauth2.NewClient(ctx, ts)
268+
return &Client{cli}, nil
211269
}

0 commit comments

Comments
 (0)