Skip to content

Commit

Permalink
refactor Validator
Browse files Browse the repository at this point in the history
  • Loading branch information
SVilgelm committed Dec 17, 2024
1 parent 0a8311c commit c129df8
Show file tree
Hide file tree
Showing 37 changed files with 552 additions and 428 deletions.
4 changes: 2 additions & 2 deletions bool_or_schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,10 @@ func (o *BoolOrSchema) MarshalYAML() (any, error) {
return v, nil
}

func (o *BoolOrSchema) validateSpec(path string, opts *specValidationOptions) []*validationError {
func (o *BoolOrSchema) validateSpec(path string, validator *Validator) []*validationError {
var errs []*validationError
if o.Schema != nil {
errs = append(errs, o.Schema.validateSpec(path, opts)...)
errs = append(errs, o.Schema.validateSpec(path, validator)...)
}
return errs
}
Expand Down
4 changes: 2 additions & 2 deletions callback.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,10 @@ func (o *Callback) UnmarshalYAML(node *yaml.Node) error {
return node.Decode(&o.Paths)
}

func (o *Callback) validateSpec(location string, opts *specValidationOptions) []*validationError {
func (o *Callback) validateSpec(location string, validator *Validator) []*validationError {
var errs []*validationError
for k, v := range o.Paths {
errs = append(errs, v.validateSpec(joinLoc(location, k), opts)...)
errs = append(errs, v.validateSpec(joinLoc(location, k), validator)...)
}
return nil
}
Expand Down
22 changes: 11 additions & 11 deletions components.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,56 +160,56 @@ func (o *Components) Add(name string, v any) *Components {
return o
}

func (o *Components) validateSpec(location string, opts *specValidationOptions) []*validationError {
func (o *Components) validateSpec(location string, validator *Validator) []*validationError {
var errs []*validationError
if o.Schemas != nil {
for k, v := range o.Schemas {
errs = append(errs, v.validateSpec(joinLoc(location, "schemas", k), opts)...)
errs = append(errs, v.validateSpec(joinLoc(location, "schemas", k), validator)...)
}
}
if o.Responses != nil {
for k, v := range o.Responses {
errs = append(errs, v.validateSpec(joinLoc(location, "responses", k), opts)...)
errs = append(errs, v.validateSpec(joinLoc(location, "responses", k), validator)...)
}
}
if o.Parameters != nil {
for k, v := range o.Parameters {
errs = append(errs, v.validateSpec(joinLoc(location, "parameters", k), opts)...)
errs = append(errs, v.validateSpec(joinLoc(location, "parameters", k), validator)...)
}
}
if o.Examples != nil {
for k, v := range o.Examples {
errs = append(errs, v.validateSpec(joinLoc(location, "examples", k), opts)...)
errs = append(errs, v.validateSpec(joinLoc(location, "examples", k), validator)...)
}
}
if o.RequestBodies != nil {
for k, v := range o.RequestBodies {
errs = append(errs, v.validateSpec(joinLoc(location, "requestBodies", k), opts)...)
errs = append(errs, v.validateSpec(joinLoc(location, "requestBodies", k), validator)...)
}
}
if o.Headers != nil {
for k, v := range o.Headers {
errs = append(errs, v.validateSpec(joinLoc(location, "headers", k), opts)...)
errs = append(errs, v.validateSpec(joinLoc(location, "headers", k), validator)...)
}
}
if o.SecuritySchemes != nil {
for k, v := range o.SecuritySchemes {
errs = append(errs, v.validateSpec(joinLoc(location, "securitySchemes", k), opts)...)
errs = append(errs, v.validateSpec(joinLoc(location, "securitySchemes", k), validator)...)
}
}
if o.Links != nil {
for k, v := range o.Links {
errs = append(errs, v.validateSpec(joinLoc(location, "links", k), opts)...)
errs = append(errs, v.validateSpec(joinLoc(location, "links", k), validator)...)
}
}
if o.Callbacks != nil {
for k, v := range o.Callbacks {
errs = append(errs, v.validateSpec(joinLoc(location, "callbacks", k), opts)...)
errs = append(errs, v.validateSpec(joinLoc(location, "callbacks", k), validator)...)
}
}
if o.Paths != nil {
for k, v := range o.Paths {
errs = append(errs, v.validateSpec(joinLoc(location, "paths", k), opts)...)
errs = append(errs, v.validateSpec(joinLoc(location, "paths", k), validator)...)
}
}

Expand Down
2 changes: 1 addition & 1 deletion contact.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ type Contact struct {
Email string `json:"email,omitempty" yaml:"email,omitempty"`
}

func (o *Contact) validateSpec(location string, opts *specValidationOptions) []*validationError {
func (o *Contact) validateSpec(location string, validator *Validator) []*validationError {
var errs []*validationError
if err := checkURL(o.URL); err != nil {
errs = append(errs, newValidationError(joinLoc(location, "url"), err))
Expand Down
4 changes: 2 additions & 2 deletions discriminator.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,14 @@ type Discriminator struct {
PropertyName string `json:"propertyName" yaml:"propertyName"`
}

func (o *Discriminator) validateSpec(location string, opts *specValidationOptions) []*validationError {
func (o *Discriminator) validateSpec(location string, validator *Validator) []*validationError {
var errs []*validationError
if o.PropertyName == "" {
errs = append(errs, newValidationError(joinLoc(location, "propertyName"), ErrRequired))
}
for k, v := range o.Mapping {
ref := NewRefOrSpec[Schema](v)
errs = append(errs, ref.validateSpec(joinLoc(location, "mapping", k), opts)...)
errs = append(errs, ref.validateSpec(joinLoc(location, "mapping", k), validator)...)
}
return errs
}
Expand Down
4 changes: 2 additions & 2 deletions encoding.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,11 @@ type Encoding struct {
AllowReserved bool `json:"allowReserved,omitempty" yaml:"allowReserved,omitempty"`
}

func (o *Encoding) validateSpec(location string, opts *specValidationOptions) []*validationError {
func (o *Encoding) validateSpec(location string, validator *Validator) []*validationError {
var errs []*validationError
if len(o.Headers) > 0 {
for k, v := range o.Headers {
errs = append(errs, v.validateSpec(joinLoc(location, "headers", k), opts)...)
errs = append(errs, v.validateSpec(joinLoc(location, "headers", k), validator)...)
}
}

Expand Down
2 changes: 1 addition & 1 deletion example.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ type Example struct {
ExternalValue string `json:"externalValue,omitempty" yaml:"externalValue,omitempty"`
}

func (o *Example) validateSpec(location string, opts *specValidationOptions) []*validationError {
func (o *Example) validateSpec(location string, validator *Validator) []*validationError {
var errs []*validationError
if o.Value != nil && o.ExternalValue != "" {
errs = append(errs, newValidationError(joinLoc(location, "value&externalValue"), ErrMutuallyExclusive))
Expand Down
6 changes: 3 additions & 3 deletions extensions.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,16 +165,16 @@ func (o *Extendable[T]) UnmarshalYAML(node *yaml.Node) error {

var ErrExtensionNameMustStartWithPrefix = errors.New("extension name must start with `" + ExtensionPrefix + "`")

func (o *Extendable[T]) validateSpec(location string, opts *specValidationOptions) []*validationError {
func (o *Extendable[T]) validateSpec(location string, validator *Validator) []*validationError {
var errs []*validationError
if o.Spec != nil {
if spec, ok := any(o.Spec).(validatable); ok {
errs = append(errs, spec.validateSpec(location, opts)...)
errs = append(errs, spec.validateSpec(location, validator)...)
} else {
errs = append(errs, newValidationError(location, fmt.Errorf("unsupported spec type: %T", o.Spec)))
}
}
if opts.allowExtensionNameWithoutPrefix {
if validator.opts.allowExtensionNameWithoutPrefix {
return errs
}

Expand Down
2 changes: 1 addition & 1 deletion external-docs.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ type ExternalDocs struct {
URL string `json:"url" yaml:"url"`
}

func (o *ExternalDocs) validateSpec(location string, opts *specValidationOptions) []*validationError {
func (o *ExternalDocs) validateSpec(location string, validator *Validator) []*validationError {
var errs []*validationError
if o.URL == "" {
errs = append(errs, newValidationError(joinLoc(location, "url"), ErrRequired))
Expand Down
6 changes: 3 additions & 3 deletions header.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ type Header struct {
Deprecated bool `json:"deprecated,omitempty" yaml:"deprecated,omitempty"`
}

func (o *Header) validateSpec(location string, opts *specValidationOptions) []*validationError {
func (o *Header) validateSpec(location string, validator *Validator) []*validationError {
var errs []*validationError
if o.Schema != nil && o.Content != nil {
errs = append(errs, newValidationError(joinLoc(location, "schema&content"), ErrMutuallyExclusive))
Expand All @@ -49,11 +49,11 @@ func (o *Header) validateSpec(location string, opts *specValidationOptions) []*v
errs = append(errs, newValidationError(joinLoc(location, "content"), "must be only one item, but got '%d'", l))
}
for k, v := range o.Content {
errs = append(errs, v.validateSpec(joinLoc(location, "content", k), opts)...)
errs = append(errs, v.validateSpec(joinLoc(location, "content", k), validator)...)
}
}
if o.Schema != nil {
errs = append(errs, o.Schema.validateSpec(joinLoc(location, "schema"), opts)...)
errs = append(errs, o.Schema.validateSpec(joinLoc(location, "schema"), validator)...)
}

switch o.Style {
Expand Down
6 changes: 3 additions & 3 deletions info.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ type Info struct {
Version string `json:"version" yaml:"version"`
}

func (o *Info) validateSpec(location string, opts *specValidationOptions) []*validationError {
func (o *Info) validateSpec(location string, validator *Validator) []*validationError {
var errs []*validationError
if o.Title == "" {
errs = append(errs, newValidationError(joinLoc(location, "title"), ErrRequired))
Expand All @@ -49,10 +49,10 @@ func (o *Info) validateSpec(location string, opts *specValidationOptions) []*val
errs = append(errs, newValidationError(joinLoc(location, "version"), ErrRequired))
}
if o.Contact != nil {
errs = append(errs, o.Contact.validateSpec(joinLoc(location, "contact"), opts)...)
errs = append(errs, o.Contact.validateSpec(joinLoc(location, "contact"), validator)...)
}
if o.License != nil {
errs = append(errs, o.License.validateSpec(joinLoc(location, "license"), opts)...)
errs = append(errs, o.License.validateSpec(joinLoc(location, "license"), validator)...)
}
if err := checkURL(o.TermsOfService); err != nil {
errs = append(errs, newValidationError(joinLoc(location, "termsOfService"), err))
Expand Down
2 changes: 1 addition & 1 deletion license.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ type License struct {
URL string `json:"url,omitempty" yaml:"url,omitempty"`
}

func (o *License) validateSpec(location string, opts *specValidationOptions) []*validationError {
func (o *License) validateSpec(location string, validator *Validator) []*validationError {
var errs []*validationError
if o.Name == "" {
errs = append(errs, newValidationError(joinLoc(location, "name"), ErrRequired))
Expand Down
10 changes: 5 additions & 5 deletions link.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,24 +80,24 @@ type Link struct {
Description string `json:"description,omitempty" yaml:"description,omitempty"`
}

func (o *Link) validateSpec(location string, opts *specValidationOptions) []*validationError {
func (o *Link) validateSpec(location string, validator *Validator) []*validationError {
var errs []*validationError
if o.OperationRef != "" && o.OperationID != "" {
errs = append(errs, newValidationError(joinLoc(location, "operationRef&operationId"), ErrMutuallyExclusive))
}
if o.OperationID != "" {
id := joinLoc("operations", o.OperationID)
if !opts.visited[id] {
opts.linkToOperationID[joinLoc(location, "operationId")] = o.OperationID
if !validator.visited[id] {
validator.linkToOperationID[joinLoc(location, "operationId")] = o.OperationID
}
}
// uncomment when JSONLookup is implemented
//if o.OperationRef != "" {
// ref := NewRefOrExtSpec[Operation](o.OperationRef)
// errs = append(errs, ref.validateSpec(joinLoc(location, "operationRef"), opts)...)
// errs = append(errs, ref.validateSpec(joinLoc(location, "operationRef"), validator)...)
//}
if o.Server != nil {
errs = append(errs, o.Server.validateSpec(joinLoc(location, "server"), opts)...)
errs = append(errs, o.Server.validateSpec(joinLoc(location, "server"), validator)...)
}
return errs
}
Expand Down
17 changes: 9 additions & 8 deletions media_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,45 +46,46 @@ type MediaType struct {
Encoding map[string]*Extendable[Encoding] `json:"encoding,omitempty" yaml:"encoding,omitempty"`
}

func (o *MediaType) validateSpec(location string, opts *specValidationOptions) []*validationError {
func (o *MediaType) validateSpec(location string, validator *Validator) []*validationError {
var errs []*validationError
if o.Schema != nil {
errs = append(errs, o.Schema.validateSpec(joinLoc(location, "schema"), opts)...)
errs = append(errs, o.Schema.validateSpec(joinLoc(location, "schema"), validator)...)
}
if len(o.Encoding) > 0 {
for k, v := range o.Encoding {
errs = append(errs, v.validateSpec(joinLoc(location, "encoding", k), opts)...)
errs = append(errs, v.validateSpec(joinLoc(location, "encoding", k), validator)...)
}
}
if o.Example != nil && len(o.Examples) > 0 {
errs = append(errs, newValidationError(joinLoc(location, "example&examples"), ErrMutuallyExclusive))
}
if len(o.Examples) > 0 {
for k, v := range o.Examples {
errs = append(errs, v.validateSpec(joinLoc(location, "examples", k), opts)...)
errs = append(errs, v.validateSpec(joinLoc(location, "examples", k), validator)...)
}
}

if opts.doNotValidateExamples {
if validator.opts.doNotValidateExamples {
return errs
}
if o.Schema == nil {
return append(errs, newValidationError(location, "unable to validate examples without schema"))
}
schemaRef := o.Schema.getLocationOrRef(joinLoc(location, "schema"))
if o.Example != nil {
if e := opts.validator.ValidateDataAsJSON(location, o.Example); e != nil {
if e := validator.ValidateData(schemaRef, o.Example); e != nil {
errs = append(errs, newValidationError(joinLoc(location, "example"), e))
}
}
if len(o.Examples) > 0 {
for k, v := range o.Examples {
example, err := v.GetSpec(opts.validator.spec.Spec.Components)
example, err := v.GetSpec(validator.spec.Spec.Components)
if err != nil {
// do not add the error, because it is already validated earlier
continue
}
if value := example.Spec.Value; value != nil {
if e := opts.validator.ValidateDataAsJSON(location, value); e != nil {
if e := validator.ValidateData(schemaRef, value); e != nil {
errs = append(errs, newValidationError(joinLoc(location, "examples", k), e))
}
}
Expand Down
2 changes: 1 addition & 1 deletion oauth-flow.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ type OAuthFlow struct {
RefreshURL string `json:"refreshUrl,omitempty" yaml:"refreshUrl,omitempty"`
}

func (o *OAuthFlow) validateSpec(path string, opts *specValidationOptions) []*validationError {
func (o *OAuthFlow) validateSpec(path string, validator *Validator) []*validationError {
// all the validations are done in the parent object
return nil
}
Expand Down
10 changes: 5 additions & 5 deletions oauth-flows.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,28 +32,28 @@ type OAuthFlows struct {
AuthorizationCode *Extendable[OAuthFlow] `json:"authorizationCode,omitempty" yaml:"authorizationCode,omitempty"`
}

func (o *OAuthFlows) validateSpec(location string, opts *specValidationOptions) []*validationError {
func (o *OAuthFlows) validateSpec(location string, validator *Validator) []*validationError {
var errs []*validationError
if o.Implicit != nil {
errs = append(errs, o.Implicit.validateSpec(joinLoc(location, "implicit"), opts)...)
errs = append(errs, o.Implicit.validateSpec(joinLoc(location, "implicit"), validator)...)
if o.Implicit.Spec.AuthorizationURL == "" {
errs = append(errs, newValidationError(joinLoc(location, "implicit", "authorizationUrl"), ErrRequired))
}
}
if o.Password != nil {
errs = append(errs, o.Password.validateSpec(joinLoc(location, "password"), opts)...)
errs = append(errs, o.Password.validateSpec(joinLoc(location, "password"), validator)...)
if o.Password.Spec.TokenURL == "" {
errs = append(errs, newValidationError(joinLoc(location, "password", "tokenUrl"), ErrRequired))
}
}
if o.ClientCredentials != nil {
errs = append(errs, o.ClientCredentials.validateSpec(joinLoc(location, "clientCredentials"), opts)...)
errs = append(errs, o.ClientCredentials.validateSpec(joinLoc(location, "clientCredentials"), validator)...)
if o.ClientCredentials.Spec.TokenURL == "" {
errs = append(errs, newValidationError(joinLoc(location, "clientCredentials", "tokenUrl"), ErrRequired))
}
}
if o.AuthorizationCode != nil {
errs = append(errs, o.AuthorizationCode.validateSpec(joinLoc(location, "authorizationCode"), opts)...)
errs = append(errs, o.AuthorizationCode.validateSpec(joinLoc(location, "authorizationCode"), validator)...)
if o.AuthorizationCode.Spec.AuthorizationURL == "" {
errs = append(errs, newValidationError(joinLoc(location, "authorizationCode", "authorizationUrl"), ErrRequired))
}
Expand Down
Loading

0 comments on commit c129df8

Please sign in to comment.