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

     1  package vervet
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"fmt"
     7  	"io/fs"
     8  
     9  	"github.com/getkin/kin-openapi/openapi3"
    10  	"github.com/ghodss/yaml"
    11  )
    12  
    13  // ToSpecJSON renders an OpenAPI document object as JSON.
    14  func ToSpecJSON(v interface{}) ([]byte, error) {
    15  	return json.MarshalIndent(v, "", "  ")
    16  }
    17  
    18  // ToSpecYAML renders an OpenAPI document object as YAML.
    19  func ToSpecYAML(v interface{}) ([]byte, error) {
    20  	jsonBuf, err := json.Marshal(v)
    21  	if err != nil {
    22  		return nil, fmt.Errorf("failed to marshal JSON: %w", err)
    23  	}
    24  	yamlBuf, err := yaml.JSONToYAML(jsonBuf)
    25  	if err != nil {
    26  		return nil, fmt.Errorf("failed to marshal YAML: %w", err)
    27  	}
    28  	return WithGeneratedComment(yamlBuf)
    29  }
    30  
    31  // WithGeneratedComment prepends a comment to YAML output indicating the file
    32  // was generated.
    33  func WithGeneratedComment(yamlBuf []byte) ([]byte, error) {
    34  	var buf bytes.Buffer
    35  	_, err := fmt.Fprintf(&buf, "# OpenAPI spec generated by vervet, DO NOT EDIT\n")
    36  	if err != nil {
    37  		return nil, fmt.Errorf("failed to write output: %w", err)
    38  	}
    39  	_, err = buf.Write(yamlBuf)
    40  	if err != nil {
    41  		return nil, fmt.Errorf("failed to write output: %w", err)
    42  	}
    43  	return buf.Bytes(), nil
    44  }
    45  
    46  // LoadVersions loads all Vervet-compiled and versioned API specs from a
    47  // filesystem root and returns them.
    48  func LoadVersions(root fs.FS) ([]*openapi3.T, error) {
    49  	versions := []*openapi3.T{}
    50  	specFiles, err := fs.Glob(root, "*/spec.json")
    51  	if err != nil {
    52  		return nil, err
    53  	}
    54  	for _, specFile := range specFiles {
    55  		specData, err := fs.ReadFile(root, specFile)
    56  		if err != nil {
    57  			return nil, err
    58  		}
    59  		l := openapi3.NewLoader()
    60  		t, err := l.LoadFromData(specData)
    61  		if err != nil {
    62  			return nil, err
    63  		}
    64  		if _, err := ExtensionString(t.Extensions, ExtW3SecurityApiVersion); IsExtensionNotFound(err) {
    65  			// Not a versioned OpenAPI spec, skip it
    66  			continue
    67  		} else if err != nil {
    68  			return nil, err
    69  		}
    70  		versions = append(versions, t)
    71  	}
    72  	if len(versions) == 0 {
    73  		return nil, ErrNoMatchingVersion
    74  	}
    75  	return versions, nil
    76  }