resolver_impl.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. package graphql
  2. import (
  3. "context"
  4. "fmt"
  5. "github.com/Nerzal/gocloak/v12"
  6. "github.com/golang-jwt/jwt/v4"
  7. "github.com/gshopify/service-wrapper/auth"
  8. "github.com/gshopify/service-wrapper/config"
  9. "github.com/gshopify/service-wrapper/model"
  10. "github.com/mitchellh/mapstructure"
  11. "gshopper.com/gshopify/customer/graphql/generated"
  12. m "gshopper.com/gshopify/customer/model"
  13. "time"
  14. )
  15. type Resolver struct {
  16. conf *auth.Config
  17. client *gocloak.GoCloak
  18. }
  19. func NewResolver() (*Resolver, error) {
  20. r := &Resolver{
  21. conf: auth.New(),
  22. }
  23. if err := config.Instance().Load(context.Background(), r.conf); err != nil {
  24. return nil, err
  25. }
  26. r.client = gocloak.NewClient(r.conf.Endpoint, gocloak.SetLegacyWildFlySupport())
  27. return r, nil
  28. }
  29. func (r *Resolver) decodeAccessToken(ctx context.Context, t string) (*jwt.Token, string, error) {
  30. if t == "" {
  31. return nil, "", fmt.Errorf("could not decode accessToken: Token is empty")
  32. }
  33. token, claim, err := r.client.DecodeAccessToken(ctx, t, r.conf.Cli.Realm)
  34. if err != nil {
  35. return nil, "", err
  36. }
  37. if !token.Valid {
  38. return nil, "", fmt.Errorf("could not decode accessToken: Token is NOT valid")
  39. }
  40. var sessionId string
  41. if claimed, ok := (*claim)["sid"]; ok {
  42. if s, ok := claimed.(string); ok {
  43. sessionId = s
  44. }
  45. }
  46. if sessionId == "" {
  47. return nil, "", fmt.Errorf("could not claim session id")
  48. }
  49. return token, sessionId, nil
  50. }
  51. func (r *Resolver) customer(ctx context.Context, t string) (*generated.Customer, error) {
  52. var (
  53. customer = generated.Customer{}
  54. udata map[string]any
  55. phone *m.Phone
  56. err error
  57. )
  58. udata, err = r.client.GetRawUserInfo(ctx, t, r.conf.Cli.Realm)
  59. if err != nil {
  60. return nil, err
  61. }
  62. if err = mapstructure.Decode(udata, &customer); err != nil {
  63. return nil, err
  64. }
  65. customer.Phone = nil
  66. phone, err = m.ParsePhoneNumber(udata)
  67. if err != nil {
  68. return nil, err
  69. }
  70. customer.Phone = gocloak.StringP(phone.String())
  71. customer.Metafields = append(customer.Metafields,
  72. NewMetafield("phone_region", phone.PhoneRegion, model.MetafieldTypeSingleLineTextField),
  73. NewMetafield("phone_verified", phone.Verified, model.MetafieldTypeBoolean))
  74. return &customer, nil
  75. }
  76. func (r *Resolver) saveSession(ctx context.Context, token *gocloak.JWT) error {
  77. return auth.SessionManager().PutToken(
  78. ctx,
  79. token.SessionState,
  80. token.RefreshToken,
  81. time.Duration(token.RefreshExpiresIn)*time.Second)
  82. }
  83. // Mutation returns generated.MutationResolver implementation.
  84. func (r *Resolver) Mutation() generated.MutationResolver { return &mutationResolver{r} }
  85. // Query returns generated.QueryResolver implementation.
  86. func (r *Resolver) Query() generated.QueryResolver { return &queryResolver{r} }
  87. type mutationResolver struct{ *Resolver }
  88. type queryResolver struct{ *Resolver }