package db import ( "context" "encoding/json" "fmt" "net/http" "strings" "time" "github.com/hhhapz/codequest/models" "golang.org/x/oauth2" ) func (db *DB) Users(ctx context.Context) ([]*models.User, error) { return models.Users(ctx, db.DB) } func (db *DB) User(ctx context.Context, email string) (*models.User, error) { return models.UserByEmail(ctx, db.DB, email) } func (db *DB) UpdateUser(ctx context.Context, user *models.User) error { if err := user.Upsert(ctx, db.DB); err != nil { return fmt.Errorf("could not upsert user: %w", err) } return nil } func (db *DB) DeleteUser(ctx context.Context, user *models.User) error { if err := user.Delete(ctx, db.DB); err != nil { return fmt.Errorf("could not delete user: %w", err) } return nil } const ( userinfoEndpoint = "https://www.googleapis.com/oauth2/v2/userinfo?access_token=" emailDomain = "@jisedu.or.id" ) func (db *DB) ConsumeToken(ctx context.Context, token *oauth2.Token) (*models.Token, error) { endpoint := userinfoEndpoint + token.AccessToken var cancel context.CancelFunc ctx, cancel = context.WithTimeout(ctx, time.Second*5) defer cancel() r, err := http.NewRequestWithContext(ctx, "GET", endpoint, nil) if err != nil { return nil, fmt.Errorf("could not create request: %w", err) } res, err := http.DefaultClient.Do(r) if err != nil { return nil, fmt.Errorf("could not get userinfo: %w", err) } defer res.Body.Close() user := &models.User{ CreatedAt: models.NewTime(time.Now()), } if err := json.NewDecoder(res.Body).Decode(&user); err != nil { return nil, fmt.Errorf("could not decode userinfo json: %w", err) } // register new user if _, err := db.User(ctx, user.Email); err != nil { if !strings.HasSuffix(user.Email, emailDomain) { return nil, models.NewUserError("invalid registration email: %s", user.Email) } err = db.UpdateUser(ctx, user) if err != nil { return nil, fmt.Errorf("could not create user: %w", err) } } // gen new token tk, err := db.CreateToken(ctx, user) if err != nil { return nil, fmt.Errorf("could not create user token: %w", err) } return tk, nil }