From e19bef3028edb62c2752b8e7466b8d62fe797cf9 Mon Sep 17 00:00:00 2001 From: zepatrik <11patti1@gmx.de> Date: Thu, 30 Jan 2020 16:19:15 +0100 Subject: [PATCH 1/6] u --- driver/configuration/provider.go | 16 +++- driver/configuration/provider_viper.go | 6 +- schema/schema.go | 48 ++++++++++++ selfservice/flow/profile/handler.go | 73 +++++++++++++------ selfservice/flow/profile/handler_test.go | 20 +++-- .../flow/registration/request_method.go | 1 + selfservice/form/container.go | 4 + selfservice/form/fields.go | 36 +++++++-- selfservice/form/html_form.go | 13 +++- selfservice/form/html_form_test.go | 22 +++--- selfservice/strategy/oidc/strategy.go | 5 ++ selfservice/strategy/password/registration.go | 10 ++- .../strategy/password/registration_test.go | 12 ++- session/manager_http.go | 8 +- 14 files changed, 203 insertions(+), 71 deletions(-) diff --git a/driver/configuration/provider.go b/driver/configuration/provider.go index 9ce4a77ff3fe..9c86d292ff85 100644 --- a/driver/configuration/provider.go +++ b/driver/configuration/provider.go @@ -5,6 +5,8 @@ import ( "net/url" "time" + "github.com/pkg/errors" + "github.com/ory/x/tracing" ) @@ -31,6 +33,18 @@ type SchemaConfig struct { URL string `json:"url"` } +type SchemaConfigs []SchemaConfig + +func (s SchemaConfigs) FindSchemaByID(id string) (*SchemaConfig, error) { + for _, sc := range s { + if sc.ID == id { + return &sc, nil + } + } + + return nil, errors.Errorf("could not find schema with id \"%s\"", id) +} + const DefaultIdentityTraitsSchemaID = "default" type Provider interface { @@ -67,7 +81,7 @@ type Provider interface { CourierTemplatesRoot() string DefaultIdentityTraitsSchemaURL() *url.URL - IdentityTraitsSchemas() []SchemaConfig + IdentityTraitsSchemas() SchemaConfigs WhitelistedReturnToDomains() []url.URL diff --git a/driver/configuration/provider_viper.go b/driver/configuration/provider_viper.go index 582d4a210106..65d8e5a11d34 100644 --- a/driver/configuration/provider_viper.go +++ b/driver/configuration/provider_viper.go @@ -107,17 +107,17 @@ func (p *ViperProvider) DefaultIdentityTraitsSchemaURL() *url.URL { return mustParseURLFromViper(p.l, ViperKeyDefaultIdentityTraitsSchemaURL) } -func (p *ViperProvider) IdentityTraitsSchemas() []SchemaConfig { +func (p *ViperProvider) IdentityTraitsSchemas() SchemaConfigs { ds := SchemaConfig{ ID: DefaultIdentityTraitsSchemaID, URL: p.DefaultIdentityTraitsSchemaURL().String(), } var b bytes.Buffer - var ss []SchemaConfig + var ss SchemaConfigs raw := viper.Get(ViperKeyIdentityTraitsSchemas) if raw == nil { - return []SchemaConfig{ds} + return SchemaConfigs{ds} } if err := json.NewEncoder(&b).Encode(raw); err != nil { diff --git a/schema/schema.go b/schema/schema.go index 35aada4cc5df..bd0beb5b9673 100644 --- a/schema/schema.go +++ b/schema/schema.go @@ -1,7 +1,13 @@ package schema import ( + "io/ioutil" "net/url" + "strings" + "sync" + + "github.com/santhosh-tekuri/jsonschema/v2" + "github.com/tidwall/gjson" "github.com/ory/kratos/driver/configuration" @@ -26,6 +32,48 @@ func (s Schemas) GetByID(id string) (*Schema, error) { return nil, errors.WithStack(errors.Errorf("unable to find JSON schema with ID: %s", id)) } +var orderedKeyCacheMutex sync.RWMutex +var orderedKeyCache map[string][]string + +func init() { + orderedKeyCache = make(map[string][]string) +} + +func computeKeyPositions(schema []byte, dest *[]string, parents []string) { + switch gjson.GetBytes(schema, "type").String() { + case "object": + gjson.GetBytes(schema, "properties").ForEach(func(key, value gjson.Result) bool { + computeKeyPositions([]byte(value.Raw), dest, append(parents, strings.Replace(key.String(), ".", "\\.", -1))) + return true + }) + default: + *dest = append(*dest, strings.Join(parents, ".")) + } +} + +func GetKeysInOrder(schemaRef string) ([]string, error) { + orderedKeyCacheMutex.RLock() + keysInOrder, ok := orderedKeyCache[schemaRef] + orderedKeyCacheMutex.RUnlock() + if !ok { + sio, err := jsonschema.LoadURL(schemaRef) + if err != nil { + return nil, errors.WithStack(err) + } + schema, err := ioutil.ReadAll(sio) + if err != nil { + return nil, errors.WithStack(err) + } + + computeKeyPositions(schema, &keysInOrder, []string{}) + orderedKeyCacheMutex.Lock() + orderedKeyCache[schemaRef] = keysInOrder + orderedKeyCacheMutex.Unlock() + } + + return keysInOrder, nil +} + type Schema struct { ID string `json:"id"` URL *url.URL `json:"-"` diff --git a/selfservice/flow/profile/handler.go b/selfservice/flow/profile/handler.go index eb8a9fbd6ab7..af8705f1c4ca 100644 --- a/selfservice/flow/profile/handler.go +++ b/selfservice/flow/profile/handler.go @@ -4,11 +4,9 @@ import ( "encoding/json" "net/http" "net/url" - "sort" "github.com/ory/kratos/schema" - "github.com/gofrs/uuid" "github.com/julienschmidt/httprouter" "github.com/justinas/nosurf" "github.com/pkg/errors" @@ -96,7 +94,18 @@ func (h *Handler) initUpdateProfile(w http.ResponseWriter, r *http.Request, ps h } a := NewRequest(h.c.SelfServiceProfileRequestLifespan(), r, s) - a.Form = form.NewHTMLFormFromJSON(urlx.AppendPaths(h.c.SelfPublicURL(), BrowserProfilePath).String(), json.RawMessage(s.Identity.Traits), "traits") + a.Form = form.NewHTMLFormFromJSON(urlx.CopyWithQuery(urlx.AppendPaths(h.c.SelfPublicURL(), BrowserProfilePath), url.Values{"request": {a.ID.String()}}).String(), json.RawMessage(s.Identity.Traits), "traits") + + traitsSchema, err := h.c.IdentityTraitsSchemas().FindSchemaByID(s.Identity.TraitsSchemaID) + if err != nil { + h.d.SelfServiceErrorManager().ForwardError(r.Context(), w, r, err) + return + } + if err := a.Form.SortFields(traitsSchema.URL, "traits"); err != nil { + h.d.SelfServiceErrorManager().ForwardError(r.Context(), w, r, err) + return + } + //a.Form.Action = urlx.CopyWithQuery(h.c.ProfileURL(), url.Values{"request": {a.ID.String()}}).String() if err := h.d.ProfileRequestPersister().CreateProfileRequest(r.Context(), a); err != nil { h.d.SelfServiceErrorManager().ForwardError(r.Context(), w, r, err) return @@ -192,14 +201,19 @@ func (h *Handler) fetchUpdateProfileRequest(w http.ResponseWriter, r *http.Reque return } - ar.Form.SetField("request", form.Field{ - Name: "request", - Type: "hidden", - Required: true, - Value: rid, - }) ar.Form.SetCSRF(nosurf.Token(r)) - sort.Sort(ar.Form.Fields) + + traitsSchema, err := h.c.IdentityTraitsSchemas().FindSchemaByID(ar.Identity.TraitsSchemaID) + if err != nil { + h.d.Writer().WriteError(w, r, err) + return + } + + if err := ar.Form.SortFields(traitsSchema.URL, "traits"); err != nil { + h.d.Writer().WriteError(w, r, err) + return + } + h.d.Writer().Write(w, r, ar) } @@ -221,12 +235,6 @@ type ( // format: binary // required: true Traits json.RawMessage `json:"traits"` - - // Request is the request ID. - // - // type: string - // required: true - Request uuid.UUID `json:"request"` } ) @@ -272,12 +280,13 @@ func (h *Handler) completeProfileManagementFlow(w http.ResponseWriter, r *http.R return } - if x.IsZeroUUID(p.Request) { + rid := x.ParseUUID(r.URL.Query().Get("request")) + if x.IsZeroUUID(rid) { h.handleProfileManagementError(w, r, nil, s.Identity.Traits, errors.WithStack(herodot.ErrBadRequest.WithReasonf("The request query parameter is missing."))) return } - ar, err := h.d.ProfileRequestPersister().GetProfileRequest(r.Context(), p.Request) + ar, err := h.d.ProfileRequestPersister().GetProfileRequest(r.Context(), rid) if err != nil { h.handleProfileManagementError(w, r, nil, s.Identity.Traits, err) return @@ -346,9 +355,18 @@ func (h *Handler) completeProfileManagementFlow(w http.ResponseWriter, r *http.R for _, field := range form.NewHTMLFormFromJSON("", json.RawMessage(i.Traits), "traits").Fields { ar.Form.SetField(field.Name, field) } - ar.Form.SetValue("request", r.Form.Get("request")) ar.Form.SetCSRF(nosurf.Token(r)) - sort.Sort(ar.Form.Fields) + + traitsSchema, err := h.c.IdentityTraitsSchemas().FindSchemaByID(i.TraitsSchemaID) + if err != nil { + h.handleProfileManagementError(w, r, ar, i.Traits, err) + return + } + err = ar.Form.SortFields(traitsSchema.URL, "traits") + if err != nil { + h.handleProfileManagementError(w, r, ar, i.Traits, err) + return + } if err := h.d.ProfileRequestPersister().UpdateProfileRequest(r.Context(), ar); err != nil { h.handleProfileManagementError(w, r, ar, i.Traits, err) @@ -373,9 +391,19 @@ func (h *Handler) handleProfileManagementError(w http.ResponseWriter, r *http.Re rr.Form.SetField(field.Name, field) } } - rr.Form.SetValue("request", r.Form.Get("request")) rr.Form.SetCSRF(nosurf.Token(r)) - sort.Sort(rr.Form.Fields) + + // try to sort, might fail if the error before was sorting related + traitsSchema, err := h.c.IdentityTraitsSchemas().FindSchemaByID(rr.Identity.TraitsSchemaID) + if err != nil { + h.d.ProfileRequestRequestErrorHandler().HandleProfileManagementError(w, r, identity.CredentialsTypePassword, rr, err) + return + } + err = rr.Form.SortFields(traitsSchema.URL, "traits") + if err != nil { + h.d.ProfileRequestRequestErrorHandler().HandleProfileManagementError(w, r, identity.CredentialsTypePassword, rr, err) + return + } } h.d.ProfileRequestRequestErrorHandler().HandleProfileManagementError(w, r, identity.CredentialsTypePassword, rr, err) @@ -391,7 +419,6 @@ func (h *Handler) newProfileManagementDecoder(i *identity.Identity) (decoderx.HT "type": "object", "required": ["traits"], "properties": { - "request": { "type": "string" }, "traits": {} } } diff --git a/selfservice/flow/profile/handler_test.go b/selfservice/flow/profile/handler_test.go index 36d316d5b248..936aed1ca0ff 100644 --- a/selfservice/flow/profile/handler_test.go +++ b/selfservice/flow/profile/handler_test.go @@ -216,17 +216,15 @@ func TestUpdateProfile(t *testing.T) { } require.True(t, found) - assert.Equal(t, &models.Form{ - Action: kratos.URL + profile.BrowserProfilePath, - Method: "POST", - Fields: models.FormFields{ - &models.FormField{Name: "request", Required: true, Type: "hidden", Value: rid}, - &models.FormField{Name: "traits.booly", Required: false, Type: "checkbox", Value: false}, - &models.FormField{Name: "traits.email", Required: false, Type: "text", Value: "john@doe.com"}, - &models.FormField{Name: "traits.numby", Required: false, Type: "number", Value: json.Number("2.5")}, - &models.FormField{Name: "traits.stringy", Required: false, Type: "text", Value: "foobar"}, - }, - }, pr.Payload.Form) + assert.True(t, strings.HasPrefix(pr.Payload.Form.Action, fmt.Sprintf("%s%s?request=", kratos.URL, profile.BrowserProfilePath))) + assert.Equal(t, models.FormFields{ + &models.FormField{Name: "traits.email", Required: false, Type: "text", Value: "john@doe.com"}, + &models.FormField{Name: "traits.stringy", Required: false, Type: "text", Value: "foobar"}, + &models.FormField{Name: "traits.numby", Required: false, Type: "number", Value: json.Number("2.5")}, + &models.FormField{Name: "traits.booly", Required: false, Type: "checkbox", Value: false}, + }, pr.Payload.Form.Fields) + assert.Equal(t, "POST", pr.Payload.Form.Method) + assert.Empty(t, pr.Payload.Form.Errors) }) submitForm := func(t *testing.T, req *public.GetProfileManagementRequestOK, values url.Values) (string, *public.GetProfileManagementRequestOK) { diff --git a/selfservice/flow/registration/request_method.go b/selfservice/flow/registration/request_method.go index 7a7480969b19..747d0526185a 100644 --- a/selfservice/flow/registration/request_method.go +++ b/selfservice/flow/registration/request_method.go @@ -60,6 +60,7 @@ type RequestMethodConfigurator interface { form.ValueSetter form.Resetter form.CSRFSetter + form.FieldSorter } // swagger:model registrationRequestMethodConfig diff --git a/selfservice/form/container.go b/selfservice/form/container.go index cb028924ae87..b0fd483325f9 100644 --- a/selfservice/form/container.go +++ b/selfservice/form/container.go @@ -27,3 +27,7 @@ type Resetter interface { // Reset resets errors. Reset() } + +type FieldSorter interface { + SortFields(schemaRef string, prefix string) error +} diff --git a/selfservice/form/fields.go b/selfservice/form/fields.go index ec67b862e234..1c0a29bb63f6 100644 --- a/selfservice/form/fields.go +++ b/selfservice/form/fields.go @@ -3,6 +3,9 @@ package form import ( "encoding/json" "fmt" + "strings" + + "github.com/ory/kratos/schema" ) // Fields contains multiple fields @@ -32,16 +35,33 @@ func (f *Field) Reset() { f.Value = nil } -func (ff Fields) Len() int { - return len(ff) -} +func (ff *Fields) sortBySchema(schemaRef, prefix string) (func(i, j int) bool, error) { + schemaKeys, err := schema.GetKeysInOrder(schemaRef) + if err != nil { + return nil, err + } + keysInOrder := []string{ + CSRFTokenName, + "identifier", + "password", + } + for _, k := range schemaKeys { + keysInOrder = append(keysInOrder, fmt.Sprintf("%s.%s", prefix, k)) + } -func (ff Fields) Swap(i, j int) { - ff[i], ff[j] = ff[j], ff[i] -} + getKeyPosition := func(name string) int { + lastPrefix := len(keysInOrder) + for i, n := range keysInOrder { + if strings.HasPrefix(name, n) { + lastPrefix = i + } + } + return lastPrefix + } -func (ff Fields) Less(i, j int) bool { - return ff[i].Name < ff[j].Name + return func(i, j int) bool { + return getKeyPosition((*ff)[i].Name) < getKeyPosition((*ff)[j].Name) + }, nil } func toFormType(n string, i interface{}) string { diff --git a/selfservice/form/html_form.go b/selfservice/form/html_form.go index b5cc5a2c468f..18931b1b802d 100644 --- a/selfservice/form/html_form.go +++ b/selfservice/form/html_form.go @@ -72,7 +72,6 @@ func NewHTMLFormFromRequestBody(r *http.Request, action string, compiler decoder for k, v := range jsonx.Flatten(raw) { c.SetValue(k, v) } - sort.Sort(c.Fields) return c, nil } @@ -86,7 +85,6 @@ func NewHTMLFormFromJSON(action string, raw json.RawMessage, prefix string) *HTM } c.SetValue(k, v) } - sort.Sort(c.Fields) return c } @@ -107,11 +105,20 @@ func NewHTMLFormFromJSONSchema(action, jsonSchemaRef, prefix string) (*HTMLForm, Type: toFormType(value.Name, value.Type), }) } - sort.Sort(c.Fields) return c, nil } +func (c *HTMLForm) SortFields(schemaRef, prefix string) error { + sortFunc, err := c.Fields.sortBySchema(schemaRef, prefix) + if err != nil { + return err + } + + sort.SliceStable(c.Fields, sortFunc) + return nil +} + // Reset resets the container's errors as well as each field's value and errors. func (c *HTMLForm) Reset() { c.defaults() diff --git a/selfservice/form/html_form_test.go b/selfservice/form/html_form_test.go index 3f64f12233ac..4437e6e903a1 100644 --- a/selfservice/form/html_form_test.go +++ b/selfservice/form/html_form_test.go @@ -47,9 +47,9 @@ func TestContainer(t *testing.T) { expect: &HTMLForm{ Fields: Fields{ Field{Name: "numby", Type: "number", Value: 1.5}, - Field{Name: "stringy", Type: "text", Value: "foobar"}, Field{Name: "objy.numby", Type: "number", Value: 1.5}, Field{Name: "objy.stringy", Type: "text", Value: "foobar"}, + Field{Name: "stringy", Type: "text", Value: "foobar"}, }, }, }, @@ -59,16 +59,19 @@ func TestContainer(t *testing.T) { expect: &HTMLForm{ Fields: Fields{ Field{Name: "traits.numby", Type: "number", Value: 1.5}, - Field{Name: "traits.stringy", Type: "text", Value: "foobar"}, Field{Name: "traits.objy.numby", Type: "number", Value: 1.5}, Field{Name: "traits.objy.stringy", Type: "text", Value: "foobar"}, + Field{Name: "traits.stringy", Type: "text", Value: "foobar"}, }, }, }, } { t.Run(fmt.Sprintf("case=%d", k), func(t *testing.T) { actual := NewHTMLFormFromJSON("action", json.RawMessage(tc.r), tc.prefix) - sort.Sort(tc.expect.Fields) + // sort actual.fields lexicographically to have a deterministic order + sort.SliceStable(actual.Fields, func(i, j int) bool { + return actual.Fields[i].Name < actual.Fields[j].Name + }) assert.Equal(t, "action", actual.Action) assert.EqualValues(t, tc.expect.Fields, actual.Fields) }) @@ -87,9 +90,9 @@ func TestContainer(t *testing.T) { expect: &HTMLForm{ Fields: Fields{ Field{Name: "numby", Type: "number", Value: 1.5}, - Field{Name: "stringy", Type: "text", Value: "foobar"}, Field{Name: "objy.numby", Type: "number", Value: 1.5}, Field{Name: "objy.stringy", Type: "text", Value: "foobar"}, + Field{Name: "stringy", Type: "text", Value: "foobar"}, }, }, }, @@ -104,9 +107,9 @@ func TestContainer(t *testing.T) { expect: &HTMLForm{ Fields: Fields{ Field{Name: "numby", Type: "number", Value: 1.5}, - Field{Name: "stringy", Type: "text", Value: "foobar"}, Field{Name: "objy.numby", Type: "number", Value: 1.5}, Field{Name: "objy.stringy", Type: "text", Value: "foobar"}, + Field{Name: "stringy", Type: "text", Value: "foobar"}, }, }, }, @@ -117,8 +120,8 @@ func TestContainer(t *testing.T) { }), expect: &HTMLForm{ Fields: Fields{ - Field{Name: "meal.name", Errors: []Error{{Message: "missing properties: \"name\""}}}, Field{Name: "meal.chef", Type: "text", Value: "aeneas"}, + Field{Name: "meal.name", Errors: []Error{{Message: "missing properties: \"name\""}}}, }, }, }, @@ -126,7 +129,10 @@ func TestContainer(t *testing.T) { t.Run(fmt.Sprintf("case=%d", k), func(t *testing.T) { actual, err := NewHTMLFormFromRequestBody(tc.r, "action", decoderx.HTTPJSONSchemaCompiler(tc.ref, nil)) require.NoError(t, err) - sort.Sort(tc.expect.Fields) + // sort actual.fields lexicographically to have a deterministic order + sort.SliceStable(actual.Fields, func(i, j int) bool { + return actual.Fields[i].Name < actual.Fields[j].Name + }) assert.Equal(t, "action", actual.Action) assert.EqualValues(t, tc.expect.Fields, actual.Fields) }) @@ -180,7 +186,6 @@ func TestContainer(t *testing.T) { t.Run(fmt.Sprintf("case=%d", k), func(t *testing.T) { actual, err := NewHTMLFormFromJSONSchema("action", tc.ref, tc.prefix) require.NoError(t, err) - sort.Sort(tc.expect.Fields) assert.Equal(t, "action", actual.Action) assert.EqualValues(t, tc.expect.Errors, actual.Errors) assert.EqualValues(t, tc.expect.Fields, actual.Fields) @@ -210,7 +215,6 @@ func TestContainer(t *testing.T) { return } require.NoError(t, err) - sort.Sort(tc.expect.Fields) assert.EqualValues(t, tc.expect.Errors, c.Errors) assert.EqualValues(t, tc.expect.Fields, c.Fields) } diff --git a/selfservice/strategy/oidc/strategy.go b/selfservice/strategy/oidc/strategy.go index dff73703086a..51324e311a2a 100644 --- a/selfservice/strategy/oidc/strategy.go +++ b/selfservice/strategy/oidc/strategy.go @@ -468,6 +468,7 @@ func (s *Strategy) populateMethod(r *http.Request, request uuid.UUID) (*RequestM f := form.NewHTMLForm(s.authURL(request, "")) f.SetCSRF(s.cg(r)) + // does not need sorting because there is only one field return NewRequestMethodConfig(f).AddProviders(conf.Providers), nil } @@ -540,6 +541,10 @@ func (s *Strategy) handleError(w http.ResponseWriter, r *http.Request, rid uuid. } method.Config.SetCSRF(s.cg(r)) + if errSec := method.Config.SortFields(s.c.DefaultIdentityTraitsSchemaURL().String(), "traits"); errSec != nil { + s.d.RegistrationRequestErrorHandler().HandleRegistrationError(w, r, identity.CredentialsTypeOIDC, rr, errors.Wrap(err, errSec.Error())) + return + } rr.Methods[s.ID()] = method } diff --git a/selfservice/strategy/password/registration.go b/selfservice/strategy/password/registration.go index c63f39916f19..683f6039be21 100644 --- a/selfservice/strategy/password/registration.go +++ b/selfservice/strategy/password/registration.go @@ -5,7 +5,6 @@ import ( "fmt" "net/http" "net/url" - "sort" "github.com/ory/kratos/driver/configuration" @@ -71,6 +70,10 @@ func (s *Strategy) handleRegistrationError(w http.ResponseWriter, r *http.Reques method.Config.SetCSRF(s.cg(r)) rr.Methods[identity.CredentialsTypePassword] = method + if errSec := method.Config.SortFields(s.c.DefaultIdentityTraitsSchemaURL().String(), "traits"); errSec != nil { + s.d.RegistrationRequestErrorHandler().HandleRegistrationError(w, r, identity.CredentialsTypePassword, rr, errors.Wrap(err, errSec.Error())) + return + } } } @@ -215,7 +218,10 @@ func (s *Strategy) PopulateRegistrationMethod(r *http.Request, sr *registration. htmlf.Method = "POST" htmlf.SetCSRF(s.cg(r)) htmlf.SetField("password", form.Field{Name: "password", Type: "password", Required: true}) - sort.Sort(htmlf.Fields) + + if err := htmlf.SortFields(s.c.DefaultIdentityTraitsSchemaURL().String(), "traits"); err != nil { + return err + } sr.Methods[identity.CredentialsTypePassword] = ®istration.RequestMethod{ Method: identity.CredentialsTypePassword, diff --git a/selfservice/strategy/password/registration_test.go b/selfservice/strategy/password/registration_test.go index 8e4bed35ee53..75ebf73eb572 100644 --- a/selfservice/strategy/password/registration_test.go +++ b/selfservice/strategy/password/registration_test.go @@ -8,7 +8,6 @@ import ( "net/http/cookiejar" "net/http/httptest" "net/url" - "sort" "strings" "testing" "time" @@ -307,17 +306,17 @@ func TestRegistration(t *testing.T) { Action: "https://foo" + password.RegistrationPath + "?request=" + sr.ID.String(), Method: "POST", Fields: form.Fields{ - { - Name: "password", - Type: "password", - Required: true, - }, { Name: "csrf_token", Type: "hidden", Required: true, Value: "nosurf", }, + { + Name: "password", + Type: "password", + Required: true, + }, { Name: "traits.foobar", Type: "text", @@ -331,7 +330,6 @@ func TestRegistration(t *testing.T) { }, }, } - sort.Sort(expected.Config.RequestMethodConfigurator.(*password.RequestMethod).HTMLForm.Fields) actual := sr.Methods[identity.CredentialsTypePassword] assert.EqualValues(t, expected.Config.RequestMethodConfigurator.(*password.RequestMethod).HTMLForm, actual.Config.RequestMethodConfigurator.(*password.RequestMethod).HTMLForm) diff --git a/session/manager_http.go b/session/manager_http.go index 9d5efb099555..181207332bab 100644 --- a/session/manager_http.go +++ b/session/manager_http.go @@ -6,9 +6,10 @@ import ( "time" "github.com/gorilla/securecookie" - "github.com/ory/x/sqlcon" "github.com/pkg/errors" + "github.com/ory/x/sqlcon" + "github.com/ory/herodot" "github.com/ory/kratos/identity" @@ -85,9 +86,8 @@ func (s *ManagerHTTP) FetchFromRequest(ctx context.Context, w http.ResponseWrite } se, err := s.r.SessionPersister().GetSession(ctx, x.ParseUUID(sid)) - if err != nil && ( - err.Error() == herodot.ErrNotFound.Error() || - err.Error() == sqlcon.ErrNoRows.Error()) { + if err != nil && (err.Error() == herodot.ErrNotFound.Error() || + err.Error() == sqlcon.ErrNoRows.Error()) { return nil, errors.WithStack(ErrNoActiveSessionFound) } else if err != nil { return nil, err From ac49e33c8bd98800c4695d2899e12e6641eaa4d4 Mon Sep 17 00:00:00 2001 From: zepatrik <11patti1@gmx.de> Date: Thu, 30 Jan 2020 16:26:41 +0100 Subject: [PATCH 2/6] u --- selfservice/flow/profile/handler_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/selfservice/flow/profile/handler_test.go b/selfservice/flow/profile/handler_test.go index 08789ab8cf86..f22c1862f2bd 100644 --- a/selfservice/flow/profile/handler_test.go +++ b/selfservice/flow/profile/handler_test.go @@ -222,10 +222,10 @@ func TestUpdateProfile(t *testing.T) { Action: kratos.URL + profile.BrowserProfileUpdatePath + "?request=" + rid, Method: "POST", Fields: models.FormFields{ - &models.FormField{Name: "traits.booly", Required: false, Type: "checkbox", Value: false}, &models.FormField{Name: "traits.email", Required: false, Type: "text", Value: "john@doe.com"}, - &models.FormField{Name: "traits.numby", Required: false, Type: "number", Value: json.Number("2.5")}, &models.FormField{Name: "traits.stringy", Required: false, Type: "text", Value: "foobar"}, + &models.FormField{Name: "traits.numby", Required: false, Type: "number", Value: json.Number("2.5")}, + &models.FormField{Name: "traits.booly", Required: false, Type: "checkbox", Value: false}, }, }, pr.Payload.Form) }) From cd72e7c980e5f5e75950b2e987c2b1a226706604 Mon Sep 17 00:00:00 2001 From: zepatrik <11patti1@gmx.de> Date: Thu, 30 Jan 2020 16:40:18 +0100 Subject: [PATCH 3/6] add test --- schema/schema_test.go | 16 +++++++++ schema/stub/complex.schema.json | 52 +++++++++++++++++++++++++++++ selfservice/flow/profile/handler.go | 1 + 3 files changed, 69 insertions(+) create mode 100644 schema/stub/complex.schema.json diff --git a/schema/schema_test.go b/schema/schema_test.go index d5c38aaf2e10..4b92cc5d0af9 100644 --- a/schema/schema_test.go +++ b/schema/schema_test.go @@ -69,3 +69,19 @@ func TestSchemas_GetByID(t *testing.T) { assert.Equal(t, (*Schema)(nil), s) }) } + +func TestGetKeysInOrder(t *testing.T) { + for i, tc := range []struct{ + schemaRef string + keys []string + }{ + {schemaRef: "file://./stub/identity.schema.json", keys: []string{"bar", "email"}}, + {schemaRef: "file://./stub/complex.schema.json", keys: []string{"meal.name", "meal.chef", "fruits", "vegetables"}}, + } { + t.Run(fmt.Sprintf("case=%d schemaRef=%s", i, tc.schemaRef), func(t *testing.T) { + actual, err := GetKeysInOrder(tc.schemaRef) + require.NoError(t, err) + assert.Equal(t, tc.keys, actual) + }) + } +} diff --git a/schema/stub/complex.schema.json b/schema/stub/complex.schema.json new file mode 100644 index 000000000000..989823be8f9f --- /dev/null +++ b/schema/stub/complex.schema.json @@ -0,0 +1,52 @@ +{ + "$id": "https://example.com/complex.schema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "required": ["meal"], + "properties": { + "meal": { + "type": "object", + "required": ["name"], + "properties": { + "name": { + "type": "string" + }, + "chef": { + "type": "string" + } + } + }, + "fruits": { + "type": "array", + "items": { + "type": "string" + } + }, + "vegetables": { + "type": "array", + "items": { + "$ref": "#/definitions/veggie" + } + } + }, + "definitions": { + "veggie": { + "type": "object", + "required": [ + "veggieName", + "veggieLike" + ], + "properties": { + "veggieName": { + "type": "string" + }, + "veggieLike": { + "type": "boolean" + }, + "veggieAmount": { + "type": "number" + } + } + } + } +} diff --git a/selfservice/flow/profile/handler.go b/selfservice/flow/profile/handler.go index e43b808d289a..3fa74ad5d33a 100644 --- a/selfservice/flow/profile/handler.go +++ b/selfservice/flow/profile/handler.go @@ -2,6 +2,7 @@ package profile import ( "encoding/json" + "github.com/gofrs/uuid" "net/http" "net/url" From 7d95fc0c22cf346aee3cb1e264aad028be06b64b Mon Sep 17 00:00:00 2001 From: zepatrik <11patti1@gmx.de> Date: Thu, 30 Jan 2020 17:20:01 +0100 Subject: [PATCH 4/6] u --- selfservice/flow/profile/handler.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/selfservice/flow/profile/handler.go b/selfservice/flow/profile/handler.go index bd968f4b8786..7b68495ea95f 100644 --- a/selfservice/flow/profile/handler.go +++ b/selfservice/flow/profile/handler.go @@ -194,13 +194,13 @@ func (h *Handler) fetchUpdateProfileRequest(w http.ResponseWriter, r *http.Reque traitsSchema, err := h.c.IdentityTraitsSchemas().FindSchemaByID(ar.Identity.TraitsSchemaID) if err != nil { - h.d.Writer().WriteError(w, r, err) - return + h.d.Logger().Error(err) + return errors.WithStack(herodot.ErrInternalServerError.WithReason("The traits schema for this identity could not be found. This is an configuration error.")) } if err := ar.Form.SortFields(traitsSchema.URL, "traits"); err != nil { - h.d.Writer().WriteError(w, r, err) - return + h.d.Logger().Error(err) + return errors.WithStack(herodot.ErrInternalServerError.WithReason("There was an error with sorting the form fields. This is an configuration error.")) } h.d.Writer().Write(w, r, ar) From 14c9072e5f1778b74dd841a8bccf9e132a1bf27a Mon Sep 17 00:00:00 2001 From: aeneasr Date: Thu, 30 Jan 2020 16:25:04 +0000 Subject: [PATCH 5/6] Update SDK --- docs/api.swagger.json | 49 +++++++++---------- ...browser_profile_management_flow_payload.go | 2 +- .../httpclient/models/credentials_type.go | 2 +- internal/httpclient/models/error.go | 2 +- internal/httpclient/models/form_field.go | 2 +- internal/httpclient/models/form_fields.go | 2 +- internal/httpclient/models/generic_error.go | 2 +- .../models/generic_error_payload.go | 2 +- internal/httpclient/models/identity.go | 2 +- internal/httpclient/models/login_request.go | 4 +- .../httpclient/models/login_request_method.go | 24 ++++++++- .../models/login_request_method_config.go | 2 +- .../models/profile_management_request.go | 4 +- .../httpclient/models/registration_request.go | 4 +- .../registration_request_method_config.go | 23 ++++++++- internal/httpclient/models/session.go | 3 ++ internal/httpclient/models/traits.go | 2 +- internal/httpclient/models/version.go | 2 +- schema/schema_test.go | 14 +++--- selfservice/flow/profile/handler.go | 3 +- 20 files changed, 96 insertions(+), 54 deletions(-) diff --git a/docs/api.swagger.json b/docs/api.swagger.json index 46a3940388d5..4a65e69fe17c 100755 --- a/docs/api.swagger.json +++ b/docs/api.swagger.json @@ -676,10 +676,10 @@ "CredentialsType": { "description": "and so on.", "type": "string", - "title": "CredentialsType CredentialsType represents several different credential types, like password credentials, passwordless credentials," + "title": "CredentialsType CredentialsType CredentialsType represents several different credential types, like password credentials, passwordless credentials," }, "Error": { - "description": "Error error", + "description": "Error Error error", "type": "object", "properties": { "message": { @@ -689,7 +689,7 @@ } }, "Identity": { - "description": "Identity identity", + "description": "Identity Identity identity", "type": "object", "required": [ "id", @@ -713,7 +713,7 @@ } }, "Traits": { - "description": "Traits traits", + "description": "Traits Traits traits", "type": "object" }, "UUID": { @@ -721,7 +721,7 @@ "format": "uuid4" }, "completeSelfServiceBrowserProfileManagementFlowPayload": { - "description": "CompleteSelfServiceBrowserProfileManagementFlowPayload complete self service browser profile management flow payload", + "description": "CompleteSelfServiceBrowserProfileManagementFlowPayload CompleteSelfServiceBrowserProfileManagementFlowPayload complete self service browser profile management flow payload", "type": "object", "required": [ "traits" @@ -758,7 +758,7 @@ } }, "formField": { - "description": "Field represents a HTML Form Field", + "description": "FormField Field represents a HTML Form Field", "type": "object", "properties": { "errors": { @@ -787,7 +787,7 @@ } }, "formFields": { - "description": "FormFields Fields contains multiple fields", + "description": "Fields contains multiple fields", "type": "array", "items": { "$ref": "#/definitions/formField" @@ -796,7 +796,7 @@ "genericError": { "description": "Error responses are sent when an error (e.g. unauthorized, bad request, ...) occurred.", "type": "object", - "title": "Error response", + "title": "GenericError Error response", "properties": { "error": { "$ref": "#/definitions/genericErrorPayload" @@ -804,7 +804,7 @@ } }, "genericErrorPayload": { - "description": "GenericErrorPayload nolint:deadcode,unused", + "description": "GenericErrorPayload GenericErrorPayload nolint:deadcode,unused", "type": "object", "properties": { "code": { @@ -866,14 +866,13 @@ } }, "loginRequest": { - "description": "LoginRequest login request", "type": "object", "properties": { "active": { "$ref": "#/definitions/CredentialsType" }, "expires_at": { - "description": "ExpiresAt is the time (UTC) when the request expires. If the user still wishes to log in,\na new request has to be initiated.\nFormat: date-time", + "description": "ExpiresAt is the time (UTC) when the request expires. If the user still wishes to log in,\na new request has to be initiated.", "type": "string", "format": "date-time" }, @@ -881,7 +880,7 @@ "$ref": "#/definitions/UUID" }, "issued_at": { - "description": "IssuedAt is the time (UTC) when the request occurred.\nFormat: date-time", + "description": "IssuedAt is the time (UTC) when the request occurred.", "type": "string", "format": "date-time" }, @@ -899,7 +898,6 @@ } }, "loginRequestMethod": { - "description": "LoginRequestMethod login request method", "type": "object", "properties": { "config": { @@ -911,7 +909,6 @@ } }, "loginRequestMethodConfig": { - "description": "LoginRequestMethodConfig login request method config", "type": "object", "allOf": [ { @@ -931,10 +928,10 @@ "profileManagementRequest": { "description": "This request is used when an identity wants to update profile information\n(especially traits) in a selfservice manner.\n\nFor more information head over to: https://www.ory.sh/docs/kratos/selfservice/profile", "type": "object", - "title": "ProfileManagementRequest Request presents a profile management request", + "title": "Request presents a profile management request", "properties": { "expires_at": { - "description": "ExpiresAt is the time (UTC) when the request expires. If the user still wishes to update the profile,\na new request has to be initiated.\nFormat: date-time", + "description": "ExpiresAt is the time (UTC) when the request expires. If the user still wishes to update the profile,\na new request has to be initiated.", "type": "string", "format": "date-time" }, @@ -948,7 +945,7 @@ "$ref": "#/definitions/Identity" }, "issued_at": { - "description": "IssuedAt is the time (UTC) when the request occurred.\nFormat: date-time", + "description": "IssuedAt is the time (UTC) when the request occurred.", "type": "string", "format": "date-time" }, @@ -963,14 +960,14 @@ } }, "registrationRequest": { - "description": "RegistrationRequest registration request", + "description": "RegistrationRequest RegistrationRequest registration request", "type": "object", "properties": { "active": { "$ref": "#/definitions/CredentialsType" }, "expires_at": { - "description": "ExpiresAt is the time (UTC) when the request expires. If the user still wishes to log in,\na new request has to be initiated.\nFormat: date-time", + "description": "ExpiresAt is the time (UTC) when the request expires. If the user still wishes to log in,\na new request has to be initiated.\nFormat: date-time\nFormat: date-time", "type": "string", "format": "date-time" }, @@ -978,7 +975,7 @@ "$ref": "#/definitions/UUID" }, "issued_at": { - "description": "IssuedAt is the time (UTC) when the request occurred.\nFormat: date-time", + "description": "IssuedAt is the time (UTC) when the request occurred.\nFormat: date-time\nFormat: date-time", "type": "string", "format": "date-time" }, @@ -1007,7 +1004,7 @@ } }, "registrationRequestMethodConfig": { - "description": "RegistrationRequestMethodConfig registration request method config", + "description": "RegistrationRequestMethodConfig RegistrationRequestMethodConfig registration request method config", "type": "object", "allOf": [ { @@ -1022,6 +1019,9 @@ { "type": "object" }, + { + "type": "object" + }, { "type": "object" } @@ -1031,12 +1031,12 @@ "type": "object", "properties": { "authenticated_at": { - "description": "authenticated at\nFormat: date-time", + "description": "authenticated at\nFormat: date-time\nFormat: date-time", "type": "string", "format": "date-time" }, "expires_at": { - "description": "expires at\nFormat: date-time", + "description": "expires at\nFormat: date-time\nFormat: date-time", "type": "string", "format": "date-time" }, @@ -1044,7 +1044,7 @@ "$ref": "#/definitions/Identity" }, "issued_at": { - "description": "issued at\nFormat: date-time", + "description": "issued at\nFormat: date-time\nFormat: date-time", "type": "string", "format": "date-time" }, @@ -1054,7 +1054,6 @@ } }, "version": { - "description": "Version version", "type": "object", "properties": { "version": { diff --git a/internal/httpclient/models/complete_self_service_browser_profile_management_flow_payload.go b/internal/httpclient/models/complete_self_service_browser_profile_management_flow_payload.go index 757e0675f72c..741fa511a8a8 100644 --- a/internal/httpclient/models/complete_self_service_browser_profile_management_flow_payload.go +++ b/internal/httpclient/models/complete_self_service_browser_profile_management_flow_payload.go @@ -13,7 +13,7 @@ import ( "github.com/go-openapi/validate" ) -// CompleteSelfServiceBrowserProfileManagementFlowPayload CompleteSelfServiceBrowserProfileManagementFlowPayload complete self service browser profile management flow payload +// CompleteSelfServiceBrowserProfileManagementFlowPayload CompleteSelfServiceBrowserProfileManagementFlowPayload CompleteSelfServiceBrowserProfileManagementFlowPayload complete self service browser profile management flow payload // swagger:model completeSelfServiceBrowserProfileManagementFlowPayload type CompleteSelfServiceBrowserProfileManagementFlowPayload struct { diff --git a/internal/httpclient/models/credentials_type.go b/internal/httpclient/models/credentials_type.go index 6cfba2b66651..93d2adb2e510 100644 --- a/internal/httpclient/models/credentials_type.go +++ b/internal/httpclient/models/credentials_type.go @@ -9,7 +9,7 @@ import ( strfmt "github.com/go-openapi/strfmt" ) -// CredentialsType CredentialsType CredentialsType represents several different credential types, like password credentials, passwordless credentials, +// CredentialsType CredentialsType CredentialsType CredentialsType represents several different credential types, like password credentials, passwordless credentials, // // and so on. // swagger:model CredentialsType diff --git a/internal/httpclient/models/error.go b/internal/httpclient/models/error.go index 3e97c334e412..b74a17466816 100644 --- a/internal/httpclient/models/error.go +++ b/internal/httpclient/models/error.go @@ -11,7 +11,7 @@ import ( "github.com/go-openapi/swag" ) -// Error Error error +// Error Error Error error // swagger:model Error type Error struct { diff --git a/internal/httpclient/models/form_field.go b/internal/httpclient/models/form_field.go index f0bf69079eae..74f3842d4886 100644 --- a/internal/httpclient/models/form_field.go +++ b/internal/httpclient/models/form_field.go @@ -14,7 +14,7 @@ import ( "github.com/go-openapi/swag" ) -// FormField Field represents a HTML Form Field +// FormField FormField Field represents a HTML Form Field // swagger:model formField type FormField struct { diff --git a/internal/httpclient/models/form_fields.go b/internal/httpclient/models/form_fields.go index ad0d2afc4837..f7c877fd3e38 100644 --- a/internal/httpclient/models/form_fields.go +++ b/internal/httpclient/models/form_fields.go @@ -14,7 +14,7 @@ import ( "github.com/go-openapi/swag" ) -// FormFields FormFields Fields contains multiple fields +// FormFields Fields contains multiple fields // swagger:model formFields type FormFields []*FormField diff --git a/internal/httpclient/models/generic_error.go b/internal/httpclient/models/generic_error.go index 5e2a72a6dca7..4d2b17ee1132 100644 --- a/internal/httpclient/models/generic_error.go +++ b/internal/httpclient/models/generic_error.go @@ -12,7 +12,7 @@ import ( "github.com/go-openapi/swag" ) -// GenericError Error response +// GenericError GenericError Error response // // Error responses are sent when an error (e.g. unauthorized, bad request, ...) occurred. // swagger:model genericError diff --git a/internal/httpclient/models/generic_error_payload.go b/internal/httpclient/models/generic_error_payload.go index ca7362164077..d241e406bfab 100644 --- a/internal/httpclient/models/generic_error_payload.go +++ b/internal/httpclient/models/generic_error_payload.go @@ -11,7 +11,7 @@ import ( "github.com/go-openapi/swag" ) -// GenericErrorPayload GenericErrorPayload nolint:deadcode,unused +// GenericErrorPayload GenericErrorPayload GenericErrorPayload nolint:deadcode,unused // swagger:model genericErrorPayload type GenericErrorPayload struct { diff --git a/internal/httpclient/models/identity.go b/internal/httpclient/models/identity.go index 15162359e7ba..04e810f9387d 100644 --- a/internal/httpclient/models/identity.go +++ b/internal/httpclient/models/identity.go @@ -13,7 +13,7 @@ import ( "github.com/go-openapi/validate" ) -// Identity Identity identity +// Identity Identity Identity identity // swagger:model Identity type Identity struct { diff --git a/internal/httpclient/models/login_request.go b/internal/httpclient/models/login_request.go index f254821f4e9c..70de61bff636 100644 --- a/internal/httpclient/models/login_request.go +++ b/internal/httpclient/models/login_request.go @@ -13,7 +13,7 @@ import ( "github.com/go-openapi/validate" ) -// LoginRequest LoginRequest login request +// LoginRequest login request // swagger:model loginRequest type LoginRequest struct { @@ -23,7 +23,6 @@ type LoginRequest struct { // ExpiresAt is the time (UTC) when the request expires. If the user still wishes to log in, // a new request has to be initiated. // Format: date-time - // Format: date-time ExpiresAt strfmt.DateTime `json:"expires_at,omitempty"` // id @@ -32,7 +31,6 @@ type LoginRequest struct { // IssuedAt is the time (UTC) when the request occurred. // Format: date-time - // Format: date-time IssuedAt strfmt.DateTime `json:"issued_at,omitempty"` // Methods contains context for all enabled login methods. If a login request has been diff --git a/internal/httpclient/models/login_request_method.go b/internal/httpclient/models/login_request_method.go index 4561244e15be..c9938f84d55f 100644 --- a/internal/httpclient/models/login_request_method.go +++ b/internal/httpclient/models/login_request_method.go @@ -12,7 +12,7 @@ import ( "github.com/go-openapi/swag" ) -// LoginRequestMethod LoginRequestMethod login request method +// LoginRequestMethod login request method // swagger:model loginRequestMethod type LoginRequestMethod struct { @@ -27,6 +27,10 @@ type LoginRequestMethod struct { func (m *LoginRequestMethod) Validate(formats strfmt.Registry) error { var res []error + if err := m.validateConfig(formats); err != nil { + res = append(res, err) + } + if err := m.validateMethod(formats); err != nil { res = append(res, err) } @@ -37,6 +41,24 @@ func (m *LoginRequestMethod) Validate(formats strfmt.Registry) error { return nil } +func (m *LoginRequestMethod) validateConfig(formats strfmt.Registry) error { + + if swag.IsZero(m.Config) { // not required + return nil + } + + if m.Config != nil { + if err := m.Config.Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("config") + } + return err + } + } + + return nil +} + func (m *LoginRequestMethod) validateMethod(formats strfmt.Registry) error { if swag.IsZero(m.Method) { // not required diff --git a/internal/httpclient/models/login_request_method_config.go b/internal/httpclient/models/login_request_method_config.go index 16737d5c43ec..6127fe0388d7 100644 --- a/internal/httpclient/models/login_request_method_config.go +++ b/internal/httpclient/models/login_request_method_config.go @@ -11,7 +11,7 @@ import ( "github.com/go-openapi/swag" ) -// LoginRequestMethodConfig LoginRequestMethodConfig login request method config +// LoginRequestMethodConfig login request method config // swagger:model loginRequestMethodConfig type LoginRequestMethodConfig struct { LoginRequestMethodConfigAllOf0 diff --git a/internal/httpclient/models/profile_management_request.go b/internal/httpclient/models/profile_management_request.go index 3012598ba8a8..816c8afb917f 100644 --- a/internal/httpclient/models/profile_management_request.go +++ b/internal/httpclient/models/profile_management_request.go @@ -13,7 +13,7 @@ import ( "github.com/go-openapi/validate" ) -// ProfileManagementRequest ProfileManagementRequest Request presents a profile management request +// ProfileManagementRequest Request presents a profile management request // // This request is used when an identity wants to update profile information // (especially traits) in a selfservice manner. @@ -25,7 +25,6 @@ type ProfileManagementRequest struct { // ExpiresAt is the time (UTC) when the request expires. If the user still wishes to update the profile, // a new request has to be initiated. // Format: date-time - // Format: date-time ExpiresAt strfmt.DateTime `json:"expires_at,omitempty"` // form @@ -40,7 +39,6 @@ type ProfileManagementRequest struct { // IssuedAt is the time (UTC) when the request occurred. // Format: date-time - // Format: date-time IssuedAt strfmt.DateTime `json:"issued_at,omitempty"` // RequestURL is the initial URL that was requested from ORY Kratos. It can be used diff --git a/internal/httpclient/models/registration_request.go b/internal/httpclient/models/registration_request.go index 098374dc41b5..3152e1a07039 100644 --- a/internal/httpclient/models/registration_request.go +++ b/internal/httpclient/models/registration_request.go @@ -13,7 +13,7 @@ import ( "github.com/go-openapi/validate" ) -// RegistrationRequest RegistrationRequest registration request +// RegistrationRequest RegistrationRequest RegistrationRequest registration request // swagger:model registrationRequest type RegistrationRequest struct { @@ -24,6 +24,7 @@ type RegistrationRequest struct { // a new request has to be initiated. // Format: date-time // Format: date-time + // Format: date-time ExpiresAt strfmt.DateTime `json:"expires_at,omitempty"` // id @@ -33,6 +34,7 @@ type RegistrationRequest struct { // IssuedAt is the time (UTC) when the request occurred. // Format: date-time // Format: date-time + // Format: date-time IssuedAt strfmt.DateTime `json:"issued_at,omitempty"` // Methods contains context for all enabled registration methods. If a registration request has been diff --git a/internal/httpclient/models/registration_request_method_config.go b/internal/httpclient/models/registration_request_method_config.go index 2ad7a932c8a7..f712aa76907b 100644 --- a/internal/httpclient/models/registration_request_method_config.go +++ b/internal/httpclient/models/registration_request_method_config.go @@ -11,7 +11,7 @@ import ( "github.com/go-openapi/swag" ) -// RegistrationRequestMethodConfig RegistrationRequestMethodConfig registration request method config +// RegistrationRequestMethodConfig RegistrationRequestMethodConfig RegistrationRequestMethodConfig registration request method config // swagger:model registrationRequestMethodConfig type RegistrationRequestMethodConfig struct { RegistrationRequestMethodConfigAllOf0 @@ -23,6 +23,8 @@ type RegistrationRequestMethodConfig struct { RegistrationRequestMethodConfigAllOf3 RegistrationRequestMethodConfigAllOf4 + + RegistrationRequestMethodConfigAllOf5 } // UnmarshalJSON unmarshals this object from a JSON structure @@ -62,12 +64,19 @@ func (m *RegistrationRequestMethodConfig) UnmarshalJSON(raw []byte) error { } m.RegistrationRequestMethodConfigAllOf4 = aO4 + // AO5 + var aO5 RegistrationRequestMethodConfigAllOf5 + if err := swag.ReadJSON(raw, &aO5); err != nil { + return err + } + m.RegistrationRequestMethodConfigAllOf5 = aO5 + return nil } // MarshalJSON marshals this object to a JSON structure func (m RegistrationRequestMethodConfig) MarshalJSON() ([]byte, error) { - _parts := make([][]byte, 0, 5) + _parts := make([][]byte, 0, 6) aO0, err := swag.WriteJSON(m.RegistrationRequestMethodConfigAllOf0) if err != nil { @@ -99,6 +108,12 @@ func (m RegistrationRequestMethodConfig) MarshalJSON() ([]byte, error) { } _parts = append(_parts, aO4) + aO5, err := swag.WriteJSON(m.RegistrationRequestMethodConfigAllOf5) + if err != nil { + return nil, err + } + _parts = append(_parts, aO5) + return swag.ConcatJSON(_parts...), nil } @@ -144,3 +159,7 @@ type RegistrationRequestMethodConfigAllOf3 interface{} // RegistrationRequestMethodConfigAllOf4 registration request method config all of4 // swagger:model RegistrationRequestMethodConfigAllOf4 type RegistrationRequestMethodConfigAllOf4 interface{} + +// RegistrationRequestMethodConfigAllOf5 registration request method config all of5 +// swagger:model RegistrationRequestMethodConfigAllOf5 +type RegistrationRequestMethodConfigAllOf5 interface{} diff --git a/internal/httpclient/models/session.go b/internal/httpclient/models/session.go index 2501e2f3590f..f599c504a3d1 100644 --- a/internal/httpclient/models/session.go +++ b/internal/httpclient/models/session.go @@ -20,11 +20,13 @@ type Session struct { // authenticated at // Format: date-time // Format: date-time + // Format: date-time AuthenticatedAt strfmt.DateTime `json:"authenticated_at,omitempty"` // expires at // Format: date-time // Format: date-time + // Format: date-time ExpiresAt strfmt.DateTime `json:"expires_at,omitempty"` // identity @@ -33,6 +35,7 @@ type Session struct { // issued at // Format: date-time // Format: date-time + // Format: date-time IssuedAt strfmt.DateTime `json:"issued_at,omitempty"` // sid diff --git a/internal/httpclient/models/traits.go b/internal/httpclient/models/traits.go index 2e61ece25d0b..8ce4c691a404 100644 --- a/internal/httpclient/models/traits.go +++ b/internal/httpclient/models/traits.go @@ -5,6 +5,6 @@ package models // This file was generated by the swagger tool. // Editing this file might prove futile when you re-run the swagger generate command -// Traits Traits traits +// Traits Traits Traits traits // swagger:model Traits type Traits interface{} diff --git a/internal/httpclient/models/version.go b/internal/httpclient/models/version.go index 45e0beeaf16e..8331ddbdfa5f 100644 --- a/internal/httpclient/models/version.go +++ b/internal/httpclient/models/version.go @@ -11,7 +11,7 @@ import ( "github.com/go-openapi/swag" ) -// Version Version version +// Version version // swagger:model version type Version struct { diff --git a/schema/schema_test.go b/schema/schema_test.go index 4b92cc5d0af9..2b78465cc452 100644 --- a/schema/schema_test.go +++ b/schema/schema_test.go @@ -71,17 +71,17 @@ func TestSchemas_GetByID(t *testing.T) { } func TestGetKeysInOrder(t *testing.T) { - for i, tc := range []struct{ + for i, tc := range []struct { schemaRef string - keys []string + keys []string }{ {schemaRef: "file://./stub/identity.schema.json", keys: []string{"bar", "email"}}, {schemaRef: "file://./stub/complex.schema.json", keys: []string{"meal.name", "meal.chef", "fruits", "vegetables"}}, } { - t.Run(fmt.Sprintf("case=%d schemaRef=%s", i, tc.schemaRef), func(t *testing.T) { - actual, err := GetKeysInOrder(tc.schemaRef) - require.NoError(t, err) - assert.Equal(t, tc.keys, actual) - }) + t.Run(fmt.Sprintf("case=%d schemaRef=%s", i, tc.schemaRef), func(t *testing.T) { + actual, err := GetKeysInOrder(tc.schemaRef) + require.NoError(t, err) + assert.Equal(t, tc.keys, actual) + }) } } diff --git a/selfservice/flow/profile/handler.go b/selfservice/flow/profile/handler.go index 7b68495ea95f..76100709b46d 100644 --- a/selfservice/flow/profile/handler.go +++ b/selfservice/flow/profile/handler.go @@ -2,10 +2,11 @@ package profile import ( "encoding/json" - "github.com/gofrs/uuid" "net/http" "net/url" + "github.com/gofrs/uuid" + "github.com/ory/kratos/schema" "github.com/julienschmidt/httprouter" From a77347f4199df849929ec122fb9730c6d344b3b2 Mon Sep 17 00:00:00 2001 From: aeneasr Date: Thu, 30 Jan 2020 16:34:18 +0000 Subject: [PATCH 6/6] Update SDK --- docs/api.swagger.json | 3 +++ internal/httpclient/models/form_field.go | 2 +- internal/httpclient/models/generic_error.go | 2 +- .../httpclient/models/login_request_method.go | 22 ------------------- .../models/registration_request_method.go | 22 +++++++++++++++++++ .../registration_request_method_config.go | 21 +++++++++++++++++- 6 files changed, 47 insertions(+), 25 deletions(-) diff --git a/docs/api.swagger.json b/docs/api.swagger.json index a43823f13d0a..12090fc2e4f8 100755 --- a/docs/api.swagger.json +++ b/docs/api.swagger.json @@ -1010,6 +1010,9 @@ { "type": "object" }, + { + "type": "object" + }, { "type": "object" } diff --git a/internal/httpclient/models/form_field.go b/internal/httpclient/models/form_field.go index 74f3842d4886..f0bf69079eae 100644 --- a/internal/httpclient/models/form_field.go +++ b/internal/httpclient/models/form_field.go @@ -14,7 +14,7 @@ import ( "github.com/go-openapi/swag" ) -// FormField FormField Field represents a HTML Form Field +// FormField Field represents a HTML Form Field // swagger:model formField type FormField struct { diff --git a/internal/httpclient/models/generic_error.go b/internal/httpclient/models/generic_error.go index 4d2b17ee1132..5e2a72a6dca7 100644 --- a/internal/httpclient/models/generic_error.go +++ b/internal/httpclient/models/generic_error.go @@ -12,7 +12,7 @@ import ( "github.com/go-openapi/swag" ) -// GenericError GenericError Error response +// GenericError Error response // // Error responses are sent when an error (e.g. unauthorized, bad request, ...) occurred. // swagger:model genericError diff --git a/internal/httpclient/models/login_request_method.go b/internal/httpclient/models/login_request_method.go index c9938f84d55f..ff13f554ee12 100644 --- a/internal/httpclient/models/login_request_method.go +++ b/internal/httpclient/models/login_request_method.go @@ -27,10 +27,6 @@ type LoginRequestMethod struct { func (m *LoginRequestMethod) Validate(formats strfmt.Registry) error { var res []error - if err := m.validateConfig(formats); err != nil { - res = append(res, err) - } - if err := m.validateMethod(formats); err != nil { res = append(res, err) } @@ -41,24 +37,6 @@ func (m *LoginRequestMethod) Validate(formats strfmt.Registry) error { return nil } -func (m *LoginRequestMethod) validateConfig(formats strfmt.Registry) error { - - if swag.IsZero(m.Config) { // not required - return nil - } - - if m.Config != nil { - if err := m.Config.Validate(formats); err != nil { - if ve, ok := err.(*errors.Validation); ok { - return ve.ValidateName("config") - } - return err - } - } - - return nil -} - func (m *LoginRequestMethod) validateMethod(formats strfmt.Registry) error { if swag.IsZero(m.Method) { // not required diff --git a/internal/httpclient/models/registration_request_method.go b/internal/httpclient/models/registration_request_method.go index 9a563398e79a..f4c89c6ff760 100644 --- a/internal/httpclient/models/registration_request_method.go +++ b/internal/httpclient/models/registration_request_method.go @@ -27,6 +27,10 @@ type RegistrationRequestMethod struct { func (m *RegistrationRequestMethod) Validate(formats strfmt.Registry) error { var res []error + if err := m.validateConfig(formats); err != nil { + res = append(res, err) + } + if err := m.validateMethod(formats); err != nil { res = append(res, err) } @@ -37,6 +41,24 @@ func (m *RegistrationRequestMethod) Validate(formats strfmt.Registry) error { return nil } +func (m *RegistrationRequestMethod) validateConfig(formats strfmt.Registry) error { + + if swag.IsZero(m.Config) { // not required + return nil + } + + if m.Config != nil { + if err := m.Config.Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("config") + } + return err + } + } + + return nil +} + func (m *RegistrationRequestMethod) validateMethod(formats strfmt.Registry) error { if swag.IsZero(m.Method) { // not required diff --git a/internal/httpclient/models/registration_request_method_config.go b/internal/httpclient/models/registration_request_method_config.go index a876669502d0..f818fc702025 100644 --- a/internal/httpclient/models/registration_request_method_config.go +++ b/internal/httpclient/models/registration_request_method_config.go @@ -23,6 +23,8 @@ type RegistrationRequestMethodConfig struct { RegistrationRequestMethodConfigAllOf3 RegistrationRequestMethodConfigAllOf4 + + RegistrationRequestMethodConfigAllOf5 } // UnmarshalJSON unmarshals this object from a JSON structure @@ -62,12 +64,19 @@ func (m *RegistrationRequestMethodConfig) UnmarshalJSON(raw []byte) error { } m.RegistrationRequestMethodConfigAllOf4 = aO4 + // AO5 + var aO5 RegistrationRequestMethodConfigAllOf5 + if err := swag.ReadJSON(raw, &aO5); err != nil { + return err + } + m.RegistrationRequestMethodConfigAllOf5 = aO5 + return nil } // MarshalJSON marshals this object to a JSON structure func (m RegistrationRequestMethodConfig) MarshalJSON() ([]byte, error) { - _parts := make([][]byte, 0, 5) + _parts := make([][]byte, 0, 6) aO0, err := swag.WriteJSON(m.RegistrationRequestMethodConfigAllOf0) if err != nil { @@ -99,6 +108,12 @@ func (m RegistrationRequestMethodConfig) MarshalJSON() ([]byte, error) { } _parts = append(_parts, aO4) + aO5, err := swag.WriteJSON(m.RegistrationRequestMethodConfigAllOf5) + if err != nil { + return nil, err + } + _parts = append(_parts, aO5) + return swag.ConcatJSON(_parts...), nil } @@ -144,3 +159,7 @@ type RegistrationRequestMethodConfigAllOf3 interface{} // RegistrationRequestMethodConfigAllOf4 registration request method config all of4 // swagger:model RegistrationRequestMethodConfigAllOf4 type RegistrationRequestMethodConfigAllOf4 interface{} + +// RegistrationRequestMethodConfigAllOf5 registration request method config all of5 +// swagger:model RegistrationRequestMethodConfigAllOf5 +type RegistrationRequestMethodConfigAllOf5 interface{}