X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=app%2Fuser.go;h=d5b8452a6f65f9eb29b62230392adade92408597;hb=efc1f271711fbbbf06543c1d4883f377019f8c84;hp=86c033c2978b58504d64d6f29a560f6a52eba7ff;hpb=000f6f002f24e742f85ca20503a838c198637125;p=kraftakt.git diff --git a/app/user.go b/app/user.go index 86c033c..d5b8452 100644 --- a/app/user.go +++ b/app/user.go @@ -3,15 +3,19 @@ package app import ( "context" "fmt" + "net/http" + "sync" "github.com/google/uuid" legacy_context "golang.org/x/net/context" "golang.org/x/oauth2" "google.golang.org/appengine/datastore" + "google.golang.org/appengine/log" ) type User struct { - key *datastore.Key + Email string + key *datastore.Key } type dbUser struct { @@ -35,7 +39,8 @@ func NewUser(ctx context.Context, email string) (*User, error) { } return &User{ - key: datastore.NewKey(ctx, "User", email, 0, nil), + Email: email, + key: datastore.NewKey(ctx, "User", email, 0, nil), }, nil } @@ -50,7 +55,8 @@ func UserByID(ctx context.Context, id string) (*User, error) { } return &User{ - key: keys[0], + Email: keys[0].StringID(), + key: keys[0], }, nil } @@ -75,7 +81,55 @@ func (u *User) Token(ctx context.Context, svc string) (*oauth2.Token, error) { } func (u *User) SetToken(ctx context.Context, svc string, tok *oauth2.Token) error { - key := datastore.NewKey(ctx, "Token", "Fitbit", 0, u.key) + key := datastore.NewKey(ctx, "Token", svc, 0, u.key) _, err := datastore.Put(ctx, key, tok) return err } + +func (u *User) OAuthClient(ctx context.Context, svc string, cfg *oauth2.Config) (*http.Client, error) { + key := datastore.NewKey(ctx, "Token", svc, 0, u.key) + + var tok oauth2.Token + if err := datastore.Get(ctx, key, &tok); err != nil { + return nil, err + } + + src := cfg.TokenSource(ctx, &tok) + return oauth2.NewClient(ctx, &persistingTokenSource{ + ctx: ctx, + t: &tok, + src: src, + key: key, + }), nil +} + +type persistingTokenSource struct { + ctx context.Context + t *oauth2.Token + src oauth2.TokenSource + key *datastore.Key + + sync.Mutex +} + +func (s *persistingTokenSource) Token() (*oauth2.Token, error) { + s.Lock() + defer s.Unlock() + + tok, err := s.src.Token() + if err != nil { + return nil, err + } + + if s.t.AccessToken != tok.AccessToken || + s.t.TokenType != tok.TokenType || + s.t.RefreshToken != tok.RefreshToken || + !s.t.Expiry.Equal(tok.Expiry) { + if _, err := datastore.Put(s.ctx, s.key, tok); err != nil { + log.Errorf(s.ctx, "persisting OAuth token in datastore failed: %v", err) + } + } + + s.t = tok + return tok, nil +}