package app import ( "context" "fmt" "github.com/google/uuid" legacy_context "golang.org/x/net/context" "golang.org/x/oauth2" "google.golang.org/appengine/datastore" ) type User struct { Email string key *datastore.Key } type dbUser struct { ID string } func NewUser(ctx context.Context, email string) (*User, error) { err := datastore.RunInTransaction(ctx, func(ctx legacy_context.Context) error { key := datastore.NewKey(ctx, "User", email, 0, nil) if err := datastore.Get(ctx, key, &dbUser{}); err != datastore.ErrNoSuchEntity { return err // may be nil } _, err := datastore.Put(ctx, key, &dbUser{ ID: uuid.New().String(), }) return err }, nil) if err != nil { return nil, err } return &User{ Email: email, key: datastore.NewKey(ctx, "User", email, 0, nil), }, nil } func UserByID(ctx context.Context, id string) (*User, error) { q := datastore.NewQuery("User").Filter("ID=", id).KeysOnly() keys, err := q.GetAll(ctx, nil) if err != nil { return nil, fmt.Errorf("datastore.Query.GetAll(): %v", err) } if len(keys) != 1 { return nil, fmt.Errorf("len(keys) = %d, want 1", len(keys)) } return &User{ Email: keys[0].StringID(), key: keys[0], }, nil } func (u *User) ID(ctx context.Context) (string, error) { var db dbUser if err := datastore.Get(ctx, u.key, &db); err != nil { return "", err } return db.ID, nil } func (u *User) Token(ctx context.Context, svc string) (*oauth2.Token, 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 } return &tok, nil } func (u *User) SetToken(ctx context.Context, svc string, tok *oauth2.Token) error { key := datastore.NewKey(ctx, "Token", "Fitbit", 0, u.key) _, err := datastore.Put(ctx, key, tok) return err }