github.com/w3security/vervet/v5@v5.3.1-0.20230618081846-5bd9b5d799dc/inliner.go (about)

     1  package vervet
     2  
     3  import (
     4  	"reflect"
     5  
     6  	"github.com/getkin/kin-openapi/openapi3"
     7  	"github.com/mitchellh/reflectwalk"
     8  )
     9  
    10  // Inliner inlines the component.
    11  type Inliner struct {
    12  	refs map[string]struct{}
    13  }
    14  
    15  // NewInliner returns a new Inliner instance.
    16  func NewInliner() *Inliner {
    17  	return &Inliner{refs: map[string]struct{}{}}
    18  }
    19  
    20  // AddRef adds a JSON Reference URI to the set of references to be inlined.
    21  func (in *Inliner) AddRef(ref string) {
    22  	in.refs[ref] = struct{}{}
    23  }
    24  
    25  // Inline inlines all the JSON References previously indicated with AddRef in
    26  // the given OpenAPI document.
    27  func (in *Inliner) Inline(doc *openapi3.T) error {
    28  	return reflectwalk.Walk(doc, in)
    29  }
    30  
    31  // Struct implements reflectwalk.StructWalker.
    32  func (in *Inliner) Struct(v reflect.Value) error {
    33  	if !v.CanInterface() {
    34  		return nil
    35  	}
    36  	switch val := v.Interface().(type) {
    37  	case openapi3.SchemaRef:
    38  		if _, ok := in.refs[val.Ref]; ok {
    39  			valPointer := v.Addr().Interface().(*openapi3.SchemaRef)
    40  			refRemover := NewRefRemover(valPointer)
    41  			err := refRemover.RemoveRef()
    42  			if err != nil {
    43  				return err
    44  			}
    45  		}
    46  	case openapi3.ParameterRef:
    47  		if _, ok := in.refs[val.Ref]; ok {
    48  			valPointer := v.Addr().Interface().(*openapi3.ParameterRef)
    49  			refRemover := NewRefRemover(valPointer)
    50  			err := refRemover.RemoveRef()
    51  			if err != nil {
    52  				return err
    53  			}
    54  		}
    55  	case openapi3.HeaderRef:
    56  		if _, ok := in.refs[val.Ref]; ok {
    57  			valPointer := v.Addr().Interface().(*openapi3.HeaderRef)
    58  			refRemover := NewRefRemover(valPointer)
    59  			err := refRemover.RemoveRef()
    60  			if err != nil {
    61  				return err
    62  			}
    63  		}
    64  	case openapi3.RequestBodyRef:
    65  		if _, ok := in.refs[val.Ref]; ok {
    66  			valPointer := v.Addr().Interface().(*openapi3.RequestBodyRef)
    67  			refRemover := NewRefRemover(valPointer)
    68  			err := refRemover.RemoveRef()
    69  			if err != nil {
    70  				return err
    71  			}
    72  		}
    73  	case openapi3.ResponseRef:
    74  		if _, ok := in.refs[val.Ref]; ok {
    75  			valPointer := v.Addr().Interface().(*openapi3.ResponseRef)
    76  			refRemover := NewRefRemover(valPointer)
    77  			err := refRemover.RemoveRef()
    78  			if err != nil {
    79  				return err
    80  			}
    81  		}
    82  	case openapi3.SecuritySchemeRef:
    83  		if _, ok := in.refs[val.Ref]; ok {
    84  			valPointer := v.Addr().Interface().(*openapi3.SecuritySchemeRef)
    85  			refRemover := NewRefRemover(valPointer)
    86  			err := refRemover.RemoveRef()
    87  			if err != nil {
    88  				return err
    89  			}
    90  		}
    91  	case openapi3.ExampleRef:
    92  		if _, ok := in.refs[val.Ref]; ok {
    93  			valPointer := v.Addr().Interface().(*openapi3.ExampleRef)
    94  			refRemover := NewRefRemover(valPointer)
    95  			err := refRemover.RemoveRef()
    96  			if err != nil {
    97  				return err
    98  			}
    99  		}
   100  	case openapi3.LinkRef:
   101  		if _, ok := in.refs[val.Ref]; ok {
   102  			valPointer := v.Addr().Interface().(*openapi3.LinkRef)
   103  			refRemover := NewRefRemover(valPointer)
   104  			err := refRemover.RemoveRef()
   105  			if err != nil {
   106  				return err
   107  			}
   108  		}
   109  	case openapi3.CallbackRef:
   110  		if _, ok := in.refs[val.Ref]; ok {
   111  			valPointer := v.Addr().Interface().(*openapi3.CallbackRef)
   112  			refRemover := NewRefRemover(valPointer)
   113  			err := refRemover.RemoveRef()
   114  			if err != nil {
   115  				return err
   116  			}
   117  		}
   118  	}
   119  	return nil
   120  }
   121  
   122  // StructField implements reflectwalk.StructWalker.
   123  func (in *Inliner) StructField(field reflect.StructField, v reflect.Value) error {
   124  	return nil
   125  }
   126  
   127  // RefRemover removes the ref from the component.
   128  type RefRemover struct {
   129  	target interface{}
   130  }
   131  
   132  // NewRefRemover returns a new RefRemover instance.
   133  func NewRefRemover(target interface{}) *RefRemover {
   134  	return &RefRemover{target: target}
   135  }
   136  
   137  // RemoveRef removes all $ref locations from an OpenAPI document object
   138  // fragment. If the reference has already been resolved, this has the effect of
   139  // "inlining" the formerly referenced object when serializing the OpenAPI
   140  // document.
   141  func (rr *RefRemover) RemoveRef() error {
   142  	return reflectwalk.Walk(rr.target, rr)
   143  }
   144  
   145  // Struct implements reflectwalk.StructWalker.
   146  func (rr *RefRemover) Struct(v reflect.Value) error {
   147  	if !v.CanInterface() {
   148  		return nil
   149  	}
   150  	switch v.Interface().(type) {
   151  	case openapi3.SchemaRef:
   152  		valPointer := v.Addr().Interface().(*openapi3.SchemaRef)
   153  		valPointer.Ref = ""
   154  	case openapi3.ParameterRef:
   155  		valPointer := v.Addr().Interface().(*openapi3.ParameterRef)
   156  		valPointer.Ref = ""
   157  	case openapi3.HeaderRef:
   158  		valPointer := v.Addr().Interface().(*openapi3.HeaderRef)
   159  		valPointer.Ref = ""
   160  	case openapi3.RequestBodyRef:
   161  		valPointer := v.Addr().Interface().(*openapi3.RequestBodyRef)
   162  		valPointer.Ref = ""
   163  	case openapi3.ResponseRef:
   164  		valPointer := v.Addr().Interface().(*openapi3.ResponseRef)
   165  		valPointer.Ref = ""
   166  	case openapi3.SecuritySchemeRef:
   167  		valPointer := v.Addr().Interface().(*openapi3.SecuritySchemeRef)
   168  		valPointer.Ref = ""
   169  	case openapi3.ExampleRef:
   170  		valPointer := v.Addr().Interface().(*openapi3.ExampleRef)
   171  		valPointer.Ref = ""
   172  	case openapi3.LinkRef:
   173  		valPointer := v.Addr().Interface().(*openapi3.LinkRef)
   174  		valPointer.Ref = ""
   175  	case openapi3.CallbackRef:
   176  		valPointer := v.Addr().Interface().(*openapi3.CallbackRef)
   177  		valPointer.Ref = ""
   178  	}
   179  
   180  	return nil
   181  }
   182  
   183  // StructField implements reflectwalk.StructWalker.
   184  func (rr *RefRemover) StructField(field reflect.StructField, v reflect.Value) error {
   185  	return nil
   186  }