diff --git a/ecobee/auth.go b/ecobee/auth.go index f5da038..70f798c 100644 --- a/ecobee/auth.go +++ b/ecobee/auth.go @@ -31,17 +31,40 @@ import ( var Scopes = []string{"smartRead", "smartWrite"} type tokenSource struct { - token oauth2.Token - cacheFile, clientID string + token oauth2.Token + clientID string + authCache AuthCache +} + +// AuthCache encapsulates persistent cache for OAuth2 token. +type AuthCache interface { + LoadTokenData() ([]byte, error) + SaveTokenData(data []byte) error +} + +type fileAuthCache struct { + fileName string +} + +func (p fileAuthCache) LoadTokenData() ([]byte, error) { + return ioutil.ReadFile(p.fileName) +} + +func (p fileAuthCache) SaveTokenData(data []byte) error { + return ioutil.WriteFile(p.fileName, data, 0777) } func TokenSource(clientID, cacheFile string) oauth2.TokenSource { - return oauth2.ReuseTokenSource(nil, newTokenSource(clientID, cacheFile)) + return TokenSourceWithAuthCache(clientID, fileAuthCache{cacheFile}) +} + +func TokenSourceWithAuthCache(clientID string, authCache AuthCache) oauth2.TokenSource { + return oauth2.ReuseTokenSource(nil, newTokenSource(clientID, authCache)) } -func newTokenSource(clientID, cacheFile string) *tokenSource { - file, err := ioutil.ReadFile(cacheFile) - ets := tokenSource{clientID: clientID, cacheFile: cacheFile} +func newTokenSource(clientID string, authCache AuthCache) *tokenSource { + file, err := authCache.LoadTokenData() + ets := tokenSource{clientID: clientID, authCache: authCache} if err != nil { // no file, corrupted, or other problem: just start with an // empty token. @@ -56,8 +79,7 @@ func (ts *tokenSource) save() error { if err != nil { return err } - err = ioutil.WriteFile(ts.cacheFile, d, 0777) - return err + return ts.authCache.SaveTokenData(d) } func (ts *tokenSource) firstAuth() error { @@ -205,7 +227,15 @@ type Client struct { // Application Key. // (https://www.ecobee.com/consumerportal/index.html#/dev) func NewClient(clientID, authCache string) *Client { + return NewClientWithAuthCache(clientID, fileAuthCache{authCache}) +} + +// NewClientWithAuthCache creates a Ecobee API client for the specific clientID +// (Application Key) and cusom authentication token cache. +// Use the Ecobee Developer Portal to create the Application Key. +// (https://www.ecobee.com/consumerportal/index.html#/dev) +func NewClientWithAuthCache(clientID string, authCache AuthCache) *Client { return &Client{oauth2.NewClient( context.Background(), - TokenSource(clientID, authCache))} + TokenSourceWithAuthCache(clientID, authCache))} }