X-Git-Url: https://git.octo.it/?p=kraftakt.git;a=blobdiff_plain;f=fitbit%2Ffitbit.go;h=0d032440d3440953b37bf2c8c95ce9f0c37389a3;hp=9466b12f9de0edf8d326705a5a51b8587f3db5d9;hb=HEAD;hpb=b0b4324f51ba7658e5e97b294ebd8ab7008d8f2a diff --git a/fitbit/fitbit.go b/fitbit/fitbit.go index 9466b12..0d03244 100644 --- a/fitbit/fitbit.go +++ b/fitbit/fitbit.go @@ -11,14 +11,17 @@ import ( "fmt" "io/ioutil" "net/http" + "net/url" "strings" "time" "github.com/octo/kraftakt/app" + "github.com/octo/retry" "golang.org/x/oauth2" oauth2fitbit "golang.org/x/oauth2/fitbit" "google.golang.org/appengine" "google.golang.org/appengine/log" + "google.golang.org/appengine/urlfetch" ) func oauthConfig() *oauth2.Config { @@ -228,8 +231,7 @@ func (c *Client) Subscribe(ctx context.Context, collection string) error { if res.StatusCode >= 400 && res.StatusCode != http.StatusConflict { data, _ := ioutil.ReadAll(res.Body) - log.Errorf(ctx, "creating %q subscription failed: status %d %q", collection, res.StatusCode, data) - return fmt.Errorf("creating %q subscription failed", collection) + return fmt.Errorf("creating %q subscription failed: status %d %q", collection, res.StatusCode, data) } if res.StatusCode == http.StatusConflict { log.Infof(ctx, "creating %q subscription: already exists", collection) @@ -258,8 +260,7 @@ func (c *Client) unsubscribe(ctx context.Context, userID, collection, subscripti if res.StatusCode >= 400 && res.StatusCode != http.StatusNotFound { data, _ := ioutil.ReadAll(res.Body) - log.Errorf(ctx, "deleting %q subscription failed: status %d %q", collection, res.StatusCode, data) - return fmt.Errorf("deleting %q subscription failed", collection) + return fmt.Errorf("deleting %q subscription failed: status %d %q", collection, res.StatusCode, data) } if res.StatusCode == http.StatusNotFound { log.Infof(ctx, "deleting %q subscription: not found", collection) @@ -355,8 +356,47 @@ func (c *Client) ListSubscriptions(ctx context.Context, collection string) ([]Su return ret, nil } +func (c *Client) revokeToken(ctx context.Context) error { + tok, err := c.appUser.Token(ctx, "Fitbit") + if err != nil { + return err + } + + httpClient := urlfetch.Client(ctx) + httpClient.Transport = retry.NewTransport(httpClient.Transport) + + url := "https://api.fitbit.com/oauth2/revoke?token=" + url.QueryEscape(tok.AccessToken) + req, err := http.NewRequest(http.MethodGet, url, nil) + if err != nil { + return err + } + req.Header.Set("Authorization", "Basic "+ + base64.StdEncoding.EncodeToString([]byte( + app.Config.FitbitClientID+":"+app.Config.FitbitClientSecret))) + + res, err := httpClient.Do(req) + if err != nil { + return fmt.Errorf("GET %s: %v", url, err) + } + defer res.Body.Close() + + if res.StatusCode != http.StatusOK { + if data, err := ioutil.ReadAll(res.Body); err == nil { + return fmt.Errorf("GET %s: %s", url, data) + } else { + return fmt.Errorf("GET %s: %s", url, res.Status) + } + } + + return nil +} + // DeleteToken deletes the Fitbit OAuth2 token. func (c *Client) DeleteToken(ctx context.Context) error { + if err := c.revokeToken(ctx); err != nil { + log.Warningf(ctx, "revokeToken() = %v", err) + } + return c.appUser.DeleteToken(ctx, "Fitbit") } @@ -377,8 +417,7 @@ func (c *Client) Profile(ctx context.Context) (*Profile, error) { if res.StatusCode >= 400 { data, _ := ioutil.ReadAll(res.Body) - log.Errorf(ctx, "reading profile failed: %s", data) - return nil, fmt.Errorf("HTTP %d error", res.StatusCode) + return nil, fmt.Errorf("reading profile failed: %s", data) } var data struct {