浏览代码

Resolver

- refactor decodeAccessToken
- refactor customer
- add setPassword
Alexey Kim 2 年之前
父节点
当前提交
a6f44f0128

+ 11 - 8
graphql/mutationCustomerAccessTokenDelete.go

@@ -4,36 +4,39 @@ import (
 	"context"
 	"context"
 	"github.com/gshopify/service-wrapper/auth"
 	"github.com/gshopify/service-wrapper/auth"
 	"gshopper.com/gshopify/customer/graphql/generated"
 	"gshopper.com/gshopify/customer/graphql/generated"
+	"gshopper.com/gshopify/customer/model"
 )
 )
 
 
 func (r *mutationResolver) CustomerAccessTokenDelete(
 func (r *mutationResolver) CustomerAccessTokenDelete(
 	ctx context.Context, t string) (*generated.CustomerAccessTokenDeletePayload, error) {
 	ctx context.Context, t string) (*generated.CustomerAccessTokenDeletePayload, error) {
 
 
 	var (
 	var (
-		response  = &generated.CustomerAccessTokenDeletePayload{}
-		session   = auth.SessionManager()
-		sessionId string
-		err       error
+		response = &generated.CustomerAccessTokenDeletePayload{}
+		session  = auth.SessionManager()
+		claims   *model.Claims
+		err      error
 	)
 	)
 
 
-	_, sessionId, err = r.decodeAccessToken(ctx, t)
+	_, claims, err = r.decodeAccessToken(ctx, t)
 	if err != nil {
 	if err != nil {
 		response.UserErrors = append(response.UserErrors, ErrToken(err.Error()))
 		response.UserErrors = append(response.UserErrors, ErrToken(err.Error()))
 		return response, nil
 		return response, nil
 	}
 	}
 
 
-	refresh, err := session.Token(ctx, sessionId)
+	_ = session.DeleteToken(ctx, claims.SessionId)
+
+	admin, err := r.conf.Admin.Token(r.client, ctx)
 	if err != nil {
 	if err != nil {
 		response.UserErrors = append(response.UserErrors, ErrToken(err.Error()))
 		response.UserErrors = append(response.UserErrors, ErrToken(err.Error()))
 		return response, nil
 		return response, nil
 	}
 	}
 
 
-	if err = r.client.Logout(ctx, r.conf.Cli.ClientId, r.conf.Cli.ClientSecret, r.conf.Cli.Realm, refresh); err != nil {
+	if err = r.client.LogoutUserSession(ctx, admin.AccessToken, r.conf.Cli.Realm, claims.SessionId); err != nil {
 		response.UserErrors = append(response.UserErrors, ErrToken(err.Error()))
 		response.UserErrors = append(response.UserErrors, ErrToken(err.Error()))
 		return response, nil
 		return response, nil
 	}
 	}
 
 
 	response.DeletedAccessToken = &t
 	response.DeletedAccessToken = &t
-	response.DeletedCustomerAccessTokenID = &sessionId
+	response.DeletedCustomerAccessTokenID = &claims.SessionId
 	return response, nil
 	return response, nil
 }
 }

+ 7 - 6
graphql/mutationCustomerAccessTokenRenew.go

@@ -5,23 +5,24 @@ import (
 	"github.com/gshopify/service-wrapper/auth"
 	"github.com/gshopify/service-wrapper/auth"
 	"github.com/gshopify/service-wrapper/scalar"
 	"github.com/gshopify/service-wrapper/scalar"
 	"gshopper.com/gshopify/customer/graphql/generated"
 	"gshopper.com/gshopify/customer/graphql/generated"
+	"gshopper.com/gshopify/customer/model"
 )
 )
 
 
 func (r *mutationResolver) CustomerAccessTokenRenew(ctx context.Context, t string) (*generated.CustomerAccessTokenRenewPayload, error) {
 func (r *mutationResolver) CustomerAccessTokenRenew(ctx context.Context, t string) (*generated.CustomerAccessTokenRenewPayload, error) {
 	var (
 	var (
-		response  = &generated.CustomerAccessTokenRenewPayload{}
-		session   = auth.SessionManager()
-		sessionId string
-		err       error
+		response = &generated.CustomerAccessTokenRenewPayload{}
+		session  = auth.SessionManager()
+		claims   *model.Claims
+		err      error
 	)
 	)
 
 
-	_, sessionId, err = r.decodeAccessToken(ctx, t)
+	_, claims, err = r.decodeAccessToken(ctx, t)
 	if err != nil {
 	if err != nil {
 		response.UserErrors = append(response.UserErrors, ErrTokenNotExists)
 		response.UserErrors = append(response.UserErrors, ErrTokenNotExists)
 		return response, nil
 		return response, nil
 	}
 	}
 
 
-	refresh, err := session.Token(ctx, sessionId)
+	refresh, err := session.Token(ctx, claims.SessionId)
 	if err != nil {
 	if err != nil {
 		response.UserErrors = append(response.UserErrors, ErrToken(err.Error()))
 		response.UserErrors = append(response.UserErrors, ErrToken(err.Error()))
 		return response, nil
 		return response, nil

+ 8 - 11
graphql/mutationCustomerUpdate.go

@@ -4,7 +4,6 @@ import (
 	"context"
 	"context"
 	"fmt"
 	"fmt"
 	"github.com/Nerzal/gocloak/v12"
 	"github.com/Nerzal/gocloak/v12"
-	"github.com/gshopify/service-wrapper/model"
 	"github.com/gshopify/service-wrapper/scalar"
 	"github.com/gshopify/service-wrapper/scalar"
 	"github.com/gshopify/service-wrapper/server/middleware"
 	"github.com/gshopify/service-wrapper/server/middleware"
 	"gshopper.com/gshopify/customer/graphql/generated"
 	"gshopper.com/gshopify/customer/graphql/generated"
@@ -17,6 +16,7 @@ func (r *mutationResolver) CustomerUpdate(
 	var (
 	var (
 		inContext, err = middleware.InContext(ctx)
 		inContext, err = middleware.InContext(ctx)
 		response       = &generated.CustomerUpdatePayload{}
 		response       = &generated.CustomerUpdatePayload{}
+		claims         *m.Claims
 		customer       *generated.Customer
 		customer       *generated.Customer
 		phone          *m.Phone
 		phone          *m.Phone
 	)
 	)
@@ -25,13 +25,13 @@ func (r *mutationResolver) CustomerUpdate(
 		return nil, err
 		return nil, err
 	}
 	}
 
 
-	if _, _, err = r.decodeAccessToken(ctx, t); err != nil {
+	if _, claims, err = r.decodeAccessToken(ctx, t); err != nil {
 		response.CustomerUserErrors = append(response.CustomerUserErrors,
 		response.CustomerUserErrors = append(response.CustomerUserErrors,
 			CustomerError(generated.CustomerErrorCodeTokenInvalid, err, "customerAccessToken"))
 			CustomerError(generated.CustomerErrorCodeTokenInvalid, err, "customerAccessToken"))
 		return response, nil
 		return response, nil
 	}
 	}
 
 
-	customer, err = r.customer(ctx, t)
+	customer, err = r.customer(ctx, claims.Sub)
 	if err != nil {
 	if err != nil {
 		response.CustomerUserErrors = append(response.CustomerUserErrors,
 		response.CustomerUserErrors = append(response.CustomerUserErrors,
 			CustomerError(generated.CustomerErrorCodeTokenInvalid, err, "customerAccessToken"))
 			CustomerError(generated.CustomerErrorCodeTokenInvalid, err, "customerAccessToken"))
@@ -75,13 +75,10 @@ func (r *mutationResolver) CustomerUpdate(
 		},
 		},
 	}
 	}
 
 
-	customer.UpdatedAt = scalar.Now()
-	customer.Metafields = append(customer.Metafields,
-		NewMetafield("updated_at", customer.UpdatedAt, model.MetafieldTypeDateTime))
-
 	for _, metafield := range customer.Metafields {
 	for _, metafield := range customer.Metafields {
 		(*user.Attributes)[metafield.Key] = []string{metafield.Value}
 		(*user.Attributes)[metafield.Key] = []string{metafield.Value}
 	}
 	}
+	(*user.Attributes)["updated_at"] = []string{fmt.Sprintf("%d", scalar.Now())}
 
 
 	// update user properties & attributes
 	// update user properties & attributes
 	admin, err := r.conf.Admin.Token(r.client, ctx)
 	admin, err := r.conf.Admin.Token(r.client, ctx)
@@ -91,7 +88,7 @@ func (r *mutationResolver) CustomerUpdate(
 		return response, nil
 		return response, nil
 	}
 	}
 
 
-	if err := r.client.UpdateUser(ctx, admin.AccessToken, r.conf.Cli.Realm, user); err != nil {
+	if err = r.client.UpdateUser(ctx, admin.AccessToken, r.conf.Cli.Realm, user); err != nil {
 		response.CustomerUserErrors = append(response.CustomerUserErrors,
 		response.CustomerUserErrors = append(response.CustomerUserErrors,
 			CustomerError(generated.CustomerErrorCodeInvalid, err))
 			CustomerError(generated.CustomerErrorCodeInvalid, err))
 		return response, nil
 		return response, nil
@@ -99,15 +96,15 @@ func (r *mutationResolver) CustomerUpdate(
 
 
 	// update user password
 	// update user password
 	if udata.Password != nil {
 	if udata.Password != nil {
-		err = r.client.SetPassword(ctx, admin.AccessToken, customer.ID, r.conf.Cli.Realm, *udata.Password, false)
-		if err != nil {
+		var payload *generated.CustomerAccessTokenCreatePayload
+
+		if err = r.setPassword(ctx, customer.ID, *udata.Password, true); err != nil {
 			response.CustomerUserErrors = append(response.CustomerUserErrors,
 			response.CustomerUserErrors = append(response.CustomerUserErrors,
 				CustomerError(generated.CustomerErrorCodeInvalid, err, "password"))
 				CustomerError(generated.CustomerErrorCodeInvalid, err, "password"))
 			return response, nil
 			return response, nil
 		}
 		}
 
 
 		_, _ = r.CustomerAccessTokenDelete(ctx, t)
 		_, _ = r.CustomerAccessTokenDelete(ctx, t)
-		var payload *generated.CustomerAccessTokenCreatePayload
 		payload, err = r.CustomerAccessTokenCreate(ctx, generated.CustomerAccessTokenCreateInput{
 		payload, err = r.CustomerAccessTokenCreate(ctx, generated.CustomerAccessTokenCreateInput{
 			Email:    *customer.Email,
 			Email:    *customer.Email,
 			Password: *udata.Password,
 			Password: *udata.Password,

+ 13 - 2
graphql/queryCustomer.go

@@ -2,13 +2,24 @@ package graphql
 
 
 import (
 import (
 	"context"
 	"context"
+	"github.com/gshopify/service-wrapper/auth"
 	"gshopper.com/gshopify/customer/graphql/generated"
 	"gshopper.com/gshopify/customer/graphql/generated"
+	"gshopper.com/gshopify/customer/model"
 )
 )
 
 
 func (r *queryResolver) Customer(ctx context.Context, t string) (*generated.Customer, error) {
 func (r *queryResolver) Customer(ctx context.Context, t string) (*generated.Customer, error) {
-	if _, _, err := r.decodeAccessToken(ctx, t); err != nil {
+	var (
+		claims *model.Claims
+		err    error
+	)
+
+	if _, claims, err = r.decodeAccessToken(ctx, t); err != nil {
+		return nil, err
+	}
+
+	if _, err = auth.SessionManager().Token(ctx, claims.SessionId); err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
 
 
-	return r.customer(ctx, t)
+	return r.customer(ctx, claims.Sub)
 }
 }

+ 31 - 34
graphql/resolver_impl.go

@@ -7,8 +7,6 @@ import (
 	"github.com/golang-jwt/jwt/v4"
 	"github.com/golang-jwt/jwt/v4"
 	"github.com/gshopify/service-wrapper/auth"
 	"github.com/gshopify/service-wrapper/auth"
 	"github.com/gshopify/service-wrapper/config"
 	"github.com/gshopify/service-wrapper/config"
-	"github.com/gshopify/service-wrapper/model"
-	"github.com/mitchellh/mapstructure"
 	"gshopper.com/gshopify/customer/graphql/generated"
 	"gshopper.com/gshopify/customer/graphql/generated"
 	m "gshopper.com/gshopify/customer/model"
 	m "gshopper.com/gshopify/customer/model"
 	"time"
 	"time"
@@ -32,63 +30,46 @@ func NewResolver() (*Resolver, error) {
 	return r, nil
 	return r, nil
 }
 }
 
 
-func (r *Resolver) decodeAccessToken(ctx context.Context, t string) (*jwt.Token, string, error) {
+func (r *Resolver) decodeAccessToken(ctx context.Context, t string) (*jwt.Token, *m.Claims, error) {
 	if t == "" {
 	if t == "" {
-		return nil, "", fmt.Errorf("could not decode accessToken: Token is empty")
+		return nil, nil, fmt.Errorf("could not decode accessToken: Token is empty")
 	}
 	}
 
 
 	token, claim, err := r.client.DecodeAccessToken(ctx, t, r.conf.Cli.Realm)
 	token, claim, err := r.client.DecodeAccessToken(ctx, t, r.conf.Cli.Realm)
 	if err != nil {
 	if err != nil {
-		return nil, "", err
+		return nil, nil, err
 	}
 	}
 
 
 	if !token.Valid {
 	if !token.Valid {
-		return nil, "", fmt.Errorf("could not decode accessToken: Token is NOT valid")
+		return nil, nil, fmt.Errorf("could not decode accessToken: Token is NOT valid")
 	}
 	}
 
 
-	var sessionId string
-	if claimed, ok := (*claim)["sid"]; ok {
-		if s, ok := claimed.(string); ok {
-			sessionId = s
-		}
-	}
-
-	if sessionId == "" {
-		return nil, "", fmt.Errorf("could not claim session id")
+	claims := &m.Claims{}
+	if err = claims.Unmarshall(*claim); err != nil {
+		return nil, nil, err
 	}
 	}
 
 
-	return token, sessionId, nil
+	return token, claims, nil
 }
 }
 
 
-func (r *Resolver) customer(ctx context.Context, t string) (*generated.Customer, error) {
+func (r *Resolver) customer(ctx context.Context, uid string) (*generated.Customer, error) {
 	var (
 	var (
-		customer = generated.Customer{}
-		udata    map[string]any
-		phone    *m.Phone
-		err      error
+		admin *gocloak.JWT
+		user  *gocloak.User
+		err   error
 	)
 	)
 
 
-	udata, err = r.client.GetRawUserInfo(ctx, t, r.conf.Cli.Realm)
+	admin, err = r.conf.Admin.Token(r.client, ctx)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
 
 
-	if err = mapstructure.Decode(udata, &customer); err != nil {
-		return nil, err
-	}
-
-	customer.Phone = nil
-	phone, err = m.ParsePhoneNumber(udata)
+	user, err = r.client.GetUserByID(ctx, admin.AccessToken, r.conf.Cli.Realm, uid)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
 
 
-	customer.Phone = gocloak.StringP(phone.String())
-	customer.Metafields = append(customer.Metafields,
-		NewMetafield("phone_region", phone.PhoneRegion, model.MetafieldTypeSingleLineTextField),
-		NewMetafield("phone_verified", phone.Verified, model.MetafieldTypeBoolean))
-
-	return &customer, nil
+	return User2Customer(user), nil
 }
 }
 
 
 func (r *Resolver) saveSession(ctx context.Context, token *gocloak.JWT) error {
 func (r *Resolver) saveSession(ctx context.Context, token *gocloak.JWT) error {
@@ -99,6 +80,22 @@ func (r *Resolver) saveSession(ctx context.Context, token *gocloak.JWT) error {
 		time.Duration(token.RefreshExpiresIn)*time.Second)
 		time.Duration(token.RefreshExpiresIn)*time.Second)
 }
 }
 
 
+func (r *Resolver) setPassword(ctx context.Context, uid, password string, shouldValidate bool) error {
+	if shouldValidate {
+		o := generated.CustomerCreateInput{Password: password}
+		if err := o.ValidatePassword(minPasswordEntropy); err != nil {
+			return fmt.Errorf(err.Message)
+		}
+	}
+
+	admin, err := r.conf.Admin.Token(r.client, ctx)
+	if err != nil {
+		return err
+	}
+
+	return r.client.SetPassword(ctx, admin.AccessToken, uid, r.conf.Cli.Realm, password, false)
+}
+
 // Mutation returns generated.MutationResolver implementation.
 // Mutation returns generated.MutationResolver implementation.
 func (r *Resolver) Mutation() generated.MutationResolver { return &mutationResolver{r} }
 func (r *Resolver) Mutation() generated.MutationResolver { return &mutationResolver{r} }