package graphql import ( "context" "fmt" "github.com/Nerzal/gocloak/v12" "github.com/gshopify/service-wrapper/scalar" "github.com/gshopify/service-wrapper/server/middleware" "gshopper.com/gshopify/customer/graphql/generated" m "gshopper.com/gshopify/customer/model" "time" ) var minPasswordEntropy = 42.0 func (r *mutationResolver) CustomerCreate( ctx context.Context, input generated.CustomerCreateInput) (*generated.CustomerCreatePayload, error) { var ( response = &generated.CustomerCreatePayload{} user = gocloak.User{ Enabled: gocloak.BoolP(true), } err error ) if e := input.ValidateEmail(); e != nil { response.CustomerUserErrors = append(response.CustomerUserErrors, e) return response, nil } if e := input.ValidatePassword(minPasswordEntropy); e != nil { response.CustomerUserErrors = append(response.CustomerUserErrors, e) return response, nil } admin, err := r.conf.Admin.Token(r.client, ctx) if err != nil { response.CustomerUserErrors = append(response.CustomerUserErrors, CustomerError(generated.CustomerErrorCodeTokenInvalid, err, "adminAccessToken")) return response, err } if count, err := r.client.GetUserCount(ctx, admin.AccessToken, r.conf.Cli.Realm, gocloak.GetUsersParams{ Email: gocloak.StringP(input.Email), }); err != nil || count > 0 { if count > 0 { err = fmt.Errorf("email has been already registered") } response.CustomerUserErrors = append(response.CustomerUserErrors, CustomerError(generated.CustomerErrorCodeTaken, err, "email")) } if len(response.CustomerUserErrors) > 0 { return response, nil } now := scalar.Now() user.Email = gocloak.StringP(input.Email) user.LastName = input.LastName user.FirstName = input.FirstName user.CreatedTimestamp = gocloak.Int64P(time.Now().In(time.UTC).Unix()) user.Attributes = &map[string][]string{ "updated_at": {fmt.Sprintf("%d", now)}, "created_at": {fmt.Sprintf("%d", now)}, } if input.AcceptsMarketing != nil { (*user.Attributes)["accepts_marketing"] = []string{fmt.Sprintf("%v", input.AcceptsMarketing)} } if input.Phone != nil { inContext, err := middleware.InContext(ctx) if err != nil { response.CustomerUserErrors = append(response.CustomerUserErrors, CustomerError(generated.CustomerErrorCodeInvalid, err, "inContext")) return response, nil } number, err := m.NewPhoneNumber(*input.Phone, inContext.Country.String(), true) if err != nil { response.CustomerUserErrors = append(response.CustomerUserErrors, CustomerError(generated.CustomerErrorCodeInvalid, err, "phone")) return response, nil } (*user.Attributes)["phone_number"] = []string{number.String()} (*user.Attributes)["phone_region"] = []string{number.PhoneRegion} (*user.Attributes)["phone_verified"] = []string{"false"} } // Create new user uid, err := r.client.CreateUser(ctx, admin.AccessToken, r.conf.Cli.Realm, user) if err != nil { response.CustomerUserErrors = append(response.CustomerUserErrors, CustomerError(generated.CustomerErrorCodeBlank, err)) return response, nil } // Set user password if err = r.setPassword(ctx, uid, input.Password, false); err != nil { response.CustomerUserErrors = append(response.CustomerUserErrors, CustomerError(generated.CustomerErrorCodeBlank, err)) return response, nil } // Email verification if err = r.client.SendVerifyEmail(ctx, admin.AccessToken, uid, r.conf.Cli.Realm, gocloak.SendVerificationMailParams{ ClientID: gocloak.StringP(r.conf.Cli.ClientId), RedirectURI: nil, }); err != nil { response.CustomerUserErrors = append(response.CustomerUserErrors, CustomerError(generated.CustomerErrorCodeBlank, err)) return response, nil } user.ID = &uid response.Customer = User2Customer(&user) return response, nil }