mirror of
https://github.com/LukeHagar/libopenapi.git
synced 2025-12-07 12:37:48 +00:00
Refactored SecurityRequirement **breaking change**
The v3 model is wrong and out of sync with the spec. It's been corrected, so the v2 and v2 model for SecurityRequirement have been collapsed down into a base model., they are the same data structures. This has allowed me to delete the complexity of sharing two different models for the same structure, by unifying the model correctly. I am not sure why I decided to change the v3 model, oh well, its been corrected. Long live swagger!
This commit is contained in:
@@ -1,9 +1,11 @@
|
||||
// Copyright 2022 Princess B33f Heavy Industries / Dave Shanley
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v2
|
||||
package base
|
||||
|
||||
import low "github.com/pb33f/libopenapi/datamodel/low/v2"
|
||||
import (
|
||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||
)
|
||||
|
||||
// SecurityRequirement is a high-level representation of a Swagger / OpenAPI 2 SecurityRequirement object.
|
||||
//
|
||||
@@ -14,19 +16,19 @@ import low "github.com/pb33f/libopenapi/datamodel/low/v2"
|
||||
// - https://swagger.io/specification/v2/#securityDefinitionsObject
|
||||
type SecurityRequirement struct {
|
||||
Requirements map[string][]string
|
||||
low *low.SecurityRequirement
|
||||
low *base.SecurityRequirement
|
||||
}
|
||||
|
||||
// NewSecurityRequirement creates a new high-level SecurityRequirement from a low-level one.
|
||||
func NewSecurityRequirement(req *low.SecurityRequirement) *SecurityRequirement {
|
||||
func NewSecurityRequirement(req *base.SecurityRequirement) *SecurityRequirement {
|
||||
r := new(SecurityRequirement)
|
||||
r.low = req
|
||||
values := make(map[string][]string)
|
||||
// to keep things fast, avoiding copying anything - makes it a little hard to read.
|
||||
for reqK := range req.Values.Value {
|
||||
for reqK := range req.Requirements.Value {
|
||||
var vals []string
|
||||
for valK := range req.Values.Value[reqK].Value {
|
||||
vals = append(vals, req.Values.Value[reqK].Value[valK].Value)
|
||||
for valK := range req.Requirements.Value[reqK].Value {
|
||||
vals = append(vals, req.Requirements.Value[reqK].Value[valK].Value)
|
||||
}
|
||||
values[reqK.Value] = vals
|
||||
}
|
||||
@@ -35,6 +37,6 @@ func NewSecurityRequirement(req *low.SecurityRequirement) *SecurityRequirement {
|
||||
}
|
||||
|
||||
// GoLow returns the low-level SecurityRequirement used to create the high-level one.
|
||||
func (s *SecurityRequirement) GoLow() *low.SecurityRequirement {
|
||||
func (s *SecurityRequirement) GoLow() *base.SecurityRequirement {
|
||||
return s.low
|
||||
}
|
||||
@@ -24,7 +24,7 @@ type Operation struct {
|
||||
Responses *Responses
|
||||
Schemes []string
|
||||
Deprecated bool
|
||||
Security []*SecurityRequirement
|
||||
Security []*base.SecurityRequirement
|
||||
Extensions map[string]any
|
||||
low *low.Operation
|
||||
}
|
||||
@@ -88,9 +88,9 @@ func NewOperation(operation *low.Operation) *Operation {
|
||||
o.Deprecated = operation.Deprecated.Value
|
||||
}
|
||||
if !operation.Security.IsEmpty() {
|
||||
var sec []*SecurityRequirement
|
||||
var sec []*base.SecurityRequirement
|
||||
for s := range operation.Security.Value {
|
||||
sec = append(sec, NewSecurityRequirement(operation.Security.Value[s].Value))
|
||||
sec = append(sec, base.NewSecurityRequirement(operation.Security.Value[s].Value))
|
||||
}
|
||||
o.Security = sec
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ type Swagger struct {
|
||||
// The basePath does not support path templating.
|
||||
BasePath string
|
||||
|
||||
// Schemes represents the transfer protocol of the API. Values MUST be from the list: "http", "https", "ws", "wss".
|
||||
// Schemes represents the transfer protocol of the API. Requirements MUST be from the list: "http", "https", "ws", "wss".
|
||||
// If the schemes is not included, the default scheme to be used is the one used to access
|
||||
// the Swagger definition itself.
|
||||
Schemes []string
|
||||
@@ -77,7 +77,7 @@ type Swagger struct {
|
||||
// describes alternative security schemes that can be used (that is, there is a logical OR between the security
|
||||
// requirements). Individual operations can override this definition.
|
||||
// - https://swagger.io/specification/v2/#securityRequirementObject
|
||||
Security []*SecurityRequirement
|
||||
Security []*base.SecurityRequirement
|
||||
|
||||
// Tags are A list of tags used by the specification with additional metadata.
|
||||
// The order of the tags can be used to reflect on their order by the parsing tools. Not all tags that are used
|
||||
@@ -150,9 +150,9 @@ func NewSwaggerDocument(document *low.Swagger) *Swagger {
|
||||
d.SecurityDefinitions = NewSecurityDefinitions(document.SecurityDefinitions.Value)
|
||||
}
|
||||
if !document.Security.IsEmpty() {
|
||||
var security []*SecurityRequirement
|
||||
var security []*base.SecurityRequirement
|
||||
for s := range document.Security.Value {
|
||||
security = append(security, NewSecurityRequirement(document.Security.Value[s].Value))
|
||||
security = append(security, base.NewSecurityRequirement(document.Security.Value[s].Value))
|
||||
}
|
||||
d.Security = security
|
||||
}
|
||||
|
||||
@@ -103,8 +103,8 @@ func TestNewSwaggerDocument_Security(t *testing.T) {
|
||||
assert.Len(t, highDoc.Security[0].Requirements["global_auth"], 2)
|
||||
|
||||
wentLow := highDoc.Security[0].GoLow()
|
||||
assert.Equal(t, 25, wentLow.Values.ValueNode.Line)
|
||||
assert.Equal(t, 5, wentLow.Values.ValueNode.Column)
|
||||
assert.Equal(t, 25, wentLow.Requirements.ValueNode.Line)
|
||||
assert.Equal(t, 5, wentLow.Requirements.ValueNode.Column)
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ type Document struct {
|
||||
// to authorize a request. Individual operations can override this definition. To make security optional,
|
||||
// an empty security requirement ({}) can be included in the array.
|
||||
// - https://spec.openapis.org/oas/v3.1.0#security-requirement-object
|
||||
Security *SecurityRequirement
|
||||
Security *base.SecurityRequirement
|
||||
|
||||
// Tags is a slice of base.Tag instances defined by the specification
|
||||
// A list of tags used by the document with additional metadata. The order of the tags can be used to reflect on
|
||||
|
||||
@@ -337,10 +337,10 @@ func TestNewDocument_Paths(t *testing.T) {
|
||||
assert.Len(t, okResp.Links, 2)
|
||||
assert.Equal(t, "locateBurger", okResp.Links["LocateBurger"].OperationId)
|
||||
assert.Equal(t, 305, okResp.Links["LocateBurger"].GoLow().OperationId.ValueNode.Line)
|
||||
assert.Len(t, burgersOp.Post.Security.ValueRequirements[0], 1)
|
||||
assert.Len(t, burgersOp.Post.Security.ValueRequirements[0]["OAuthScheme"], 2)
|
||||
assert.Equal(t, "read:burgers", burgersOp.Post.Security.ValueRequirements[0]["OAuthScheme"][0])
|
||||
assert.Equal(t, 118, burgersOp.Post.Security.GoLow().ValueRequirements[0].ValueNode.Line)
|
||||
assert.Len(t, burgersOp.Post.Security[0].Requirements, 1)
|
||||
assert.Len(t, burgersOp.Post.Security[0].Requirements["OAuthScheme"], 2)
|
||||
assert.Equal(t, "read:burgers", burgersOp.Post.Security[0].Requirements["OAuthScheme"][0])
|
||||
assert.Equal(t, 118, burgersOp.Post.Security[0].GoLow().Requirements.ValueNode.Line)
|
||||
assert.Len(t, burgersOp.Post.Servers, 1)
|
||||
assert.Equal(t, "https://pb33f.io", burgersOp.Post.Servers[0].URL)
|
||||
|
||||
|
||||
@@ -23,8 +23,8 @@ type Operation struct {
|
||||
RequestBody *RequestBody
|
||||
Responses *Responses
|
||||
Callbacks map[string]*Callback
|
||||
Deprecated bool
|
||||
Security *SecurityRequirement
|
||||
Deprecated *bool
|
||||
Security []*base.SecurityRequirement
|
||||
Servers []*Server
|
||||
Extensions map[string]any
|
||||
low *low.Operation
|
||||
@@ -42,6 +42,7 @@ func NewOperation(operation *low.Operation) *Operation {
|
||||
}
|
||||
o.Tags = tags
|
||||
o.Summary = operation.Summary.Value
|
||||
o.Deprecated = &operation.Deprecated.Value
|
||||
o.Description = operation.Description.Value
|
||||
if !operation.ExternalDocs.IsEmpty() {
|
||||
o.ExternalDocs = base.NewExternalDoc(operation.ExternalDocs.Value)
|
||||
@@ -61,7 +62,11 @@ func NewOperation(operation *low.Operation) *Operation {
|
||||
o.Responses = NewResponses(operation.Responses.Value)
|
||||
}
|
||||
if !operation.Security.IsEmpty() {
|
||||
o.Security = NewSecurityRequirement(operation.Security.Value)
|
||||
var sec []*base.SecurityRequirement
|
||||
for s := range operation.Security.Value {
|
||||
sec = append(sec, base.NewSecurityRequirement(operation.Security.Value[s].Value))
|
||||
}
|
||||
o.Security = sec
|
||||
}
|
||||
var servers []*Server
|
||||
for i := range operation.Servers.Value {
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
// Copyright 2022 Princess B33f Heavy Industries / Dave Shanley
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v3
|
||||
|
||||
import low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||
|
||||
// SecurityRequirement is a high-level representation of an OpenAPI 3+ SecurityRequirement object that is backed
|
||||
// by a low-level one.
|
||||
//
|
||||
// It lists the required security schemes to execute this operation. The name used for each property MUST correspond
|
||||
// to a security scheme declared in the Security Schemes under the Components Object.
|
||||
//
|
||||
// Security Requirement Objects that contain multiple schemes require that all schemes MUST be satisfied for a
|
||||
// request to be authorized. This enables support for scenarios where multiple query parameters or HTTP headers are
|
||||
// required to convey security information.
|
||||
//
|
||||
// When a list of Security Requirement Objects is defined on the OpenAPI Object or Operation Object, only one of the
|
||||
// Security Requirement Objects in the list needs to be satisfied to authorize the request.
|
||||
// - https://spec.openapis.org/oas/v3.1.0#security-requirement-object
|
||||
type SecurityRequirement struct {
|
||||
ValueRequirements []map[string][]string
|
||||
low *low.SecurityRequirement
|
||||
}
|
||||
|
||||
// NewSecurityRequirement will create a new high-level SecurityRequirement instance, from a low-level one.
|
||||
func NewSecurityRequirement(req *low.SecurityRequirement) *SecurityRequirement {
|
||||
r := new(SecurityRequirement)
|
||||
r.low = req
|
||||
var values []map[string][]string
|
||||
for i := range req.ValueRequirements {
|
||||
valmap := make(map[string][]string)
|
||||
for k, v := range req.ValueRequirements[i].Value {
|
||||
var mItems []string
|
||||
for h := range v.Value {
|
||||
mItems = append(mItems, v.Value[h].Value)
|
||||
}
|
||||
valmap[k.Value] = mItems
|
||||
}
|
||||
values = append(values, valmap)
|
||||
}
|
||||
r.ValueRequirements = values
|
||||
return r
|
||||
}
|
||||
|
||||
// GoLow returns the low-level SecurityRequirement instance used to create the high-level one.
|
||||
func (s *SecurityRequirement) GoLow() *low.SecurityRequirement {
|
||||
return s.low
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright 2022 Princess B33f Heavy Industries / Dave Shanley
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package v2
|
||||
package base
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
@@ -13,15 +13,16 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// SecurityRequirement is a low-level representation of a Swagger / OpenAPI 2 SecurityRequirement object.
|
||||
// SecurityRequirement is a low-level representation of a Swagger / OpenAPI 3 SecurityRequirement object.
|
||||
//
|
||||
// SecurityRequirement lists the required security schemes to execute this operation. The object can have multiple
|
||||
// security schemes declared in it which are all required (that is, there is a logical AND between the schemes).
|
||||
//
|
||||
// The name used for each property MUST correspond to a security scheme declared in the Security Definitions
|
||||
// - https://swagger.io/specification/v2/#securityDefinitionsObject
|
||||
// - https://swagger.io/specification/#security-requirement-object
|
||||
type SecurityRequirement struct {
|
||||
Values low.ValueReference[map[low.KeyReference[string]]low.ValueReference[[]low.ValueReference[string]]]
|
||||
Requirements low.ValueReference[map[low.KeyReference[string]]low.ValueReference[[]low.ValueReference[string]]]
|
||||
}
|
||||
|
||||
// Build will extract security requirements from the node (the structure is odd, to be honest)
|
||||
@@ -49,22 +50,32 @@ func (s *SecurityRequirement) Build(root *yaml.Node, _ *index.SpecIndex) error {
|
||||
ValueNode: root.Content[i],
|
||||
}
|
||||
}
|
||||
s.Values = low.ValueReference[map[low.KeyReference[string]]low.ValueReference[[]low.ValueReference[string]]]{
|
||||
s.Requirements = low.ValueReference[map[low.KeyReference[string]]low.ValueReference[[]low.ValueReference[string]]]{
|
||||
Value: valueMap,
|
||||
ValueNode: root,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// FindRequirement will attempt to locate a security requirement string from a supplied name.
|
||||
func (s *SecurityRequirement) FindRequirement(name string) []low.ValueReference[string] {
|
||||
for k := range s.Requirements.Value {
|
||||
if k.Value == name {
|
||||
return s.Requirements.Value[k].Value
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Hash will return a consistent SHA256 Hash of the SecurityRequirement object
|
||||
func (s *SecurityRequirement) Hash() [32]byte {
|
||||
var f []string
|
||||
values := make(map[string][]string, len(s.Values.Value))
|
||||
values := make(map[string][]string, len(s.Requirements.Value))
|
||||
var valKeys []string
|
||||
for k := range s.Values.Value {
|
||||
for k := range s.Requirements.Value {
|
||||
var vals []string
|
||||
for y := range s.Values.Value[k].Value {
|
||||
vals = append(vals, s.Values.Value[k].Value[y].Value)
|
||||
for y := range s.Requirements.Value[k].Value {
|
||||
vals = append(vals, s.Requirements.Value[k].Value[y].Value)
|
||||
// lol, I know. -------^^^^^ <- this is the actual value.
|
||||
}
|
||||
sort.Strings(vals)
|
||||
@@ -487,7 +487,7 @@ func ExtractMap[PT Buildable[N], N any](
|
||||
return nil, labelNode, valueNode, nil
|
||||
}
|
||||
|
||||
// ExtractExtensions will extract any 'x-' prefixed key nodes from a root node into a map. Values have been pre-cast:
|
||||
// ExtractExtensions will extract any 'x-' prefixed key nodes from a root node into a map. Requirements have been pre-cast:
|
||||
//
|
||||
// Maps
|
||||
// map[string]interface{} for maps
|
||||
|
||||
@@ -30,7 +30,7 @@ type Operation struct {
|
||||
Responses low.NodeReference[*Responses]
|
||||
Schemes low.NodeReference[[]low.ValueReference[string]]
|
||||
Deprecated low.NodeReference[bool]
|
||||
Security low.NodeReference[[]low.ValueReference[*SecurityRequirement]]
|
||||
Security low.NodeReference[[]low.ValueReference[*base.SecurityRequirement]]
|
||||
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
||||
}
|
||||
|
||||
@@ -65,13 +65,13 @@ func (o *Operation) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
||||
}
|
||||
o.Responses = respBody
|
||||
|
||||
// extract parameters
|
||||
sec, sln, svn, sErr := low.ExtractArray[*SecurityRequirement](SecurityLabel, root, idx)
|
||||
// extract security
|
||||
sec, sln, svn, sErr := low.ExtractArray[*base.SecurityRequirement](SecurityLabel, root, idx)
|
||||
if sErr != nil {
|
||||
return sErr
|
||||
}
|
||||
if sec != nil {
|
||||
o.Security = low.NodeReference[[]low.ValueReference[*SecurityRequirement]]{
|
||||
o.Security = low.NodeReference[[]low.ValueReference[*base.SecurityRequirement]]{
|
||||
Value: sec,
|
||||
KeyNode: sln,
|
||||
ValueNode: svn,
|
||||
|
||||
@@ -44,7 +44,7 @@ type Swagger struct {
|
||||
// The basePath does not support path templating.
|
||||
BasePath low.NodeReference[string]
|
||||
|
||||
// Schemes represents the transfer protocol of the API. Values MUST be from the list: "http", "https", "ws", "wss".
|
||||
// Schemes represents the transfer protocol of the API. Requirements MUST be from the list: "http", "https", "ws", "wss".
|
||||
// If the schemes is not included, the default scheme to be used is the one used to access
|
||||
// the Swagger definition itself.
|
||||
Schemes low.NodeReference[[]low.ValueReference[string]]
|
||||
@@ -83,7 +83,7 @@ type Swagger struct {
|
||||
// describes alternative security schemes that can be used (that is, there is a logical OR between the security
|
||||
// requirements). Individual operations can override this definition.
|
||||
// - https://swagger.io/specification/v2/#securityRequirementObject
|
||||
Security low.NodeReference[[]low.ValueReference[*SecurityRequirement]]
|
||||
Security low.NodeReference[[]low.ValueReference[*base.SecurityRequirement]]
|
||||
|
||||
// Tags are A list of tags used by the specification with additional metadata.
|
||||
// The order of the tags can be used to reflect on their order by the parsing tools. Not all tags that are used
|
||||
@@ -245,12 +245,12 @@ func extractTags(root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- b
|
||||
}
|
||||
|
||||
func extractSecurity(root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error) {
|
||||
sec, ln, vn, err := low.ExtractArray[*SecurityRequirement](SecurityLabel, root, idx)
|
||||
sec, ln, vn, err := low.ExtractArray[*base.SecurityRequirement](SecurityLabel, root, idx)
|
||||
if err != nil {
|
||||
e <- err
|
||||
return
|
||||
}
|
||||
doc.Security = low.NodeReference[[]low.ValueReference[*SecurityRequirement]]{
|
||||
doc.Security = low.NodeReference[[]low.ValueReference[*base.SecurityRequirement]]{
|
||||
Value: sec,
|
||||
KeyNode: ln,
|
||||
ValueNode: vn,
|
||||
|
||||
@@ -76,11 +76,15 @@ func extractInfo(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex)
|
||||
}
|
||||
|
||||
func extractSecurity(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
||||
sec, sErr := low.ExtractObject[*SecurityRequirement](SecurityLabel, info.RootNode, idx)
|
||||
if sErr != nil {
|
||||
return sErr
|
||||
sec, ln, vn, err := low.ExtractArray[*base.SecurityRequirement](SecurityLabel, info.RootNode, idx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
doc.Security = low.NodeReference[[]low.ValueReference[*base.SecurityRequirement]]{
|
||||
Value: sec,
|
||||
KeyNode: ln,
|
||||
ValueNode: vn,
|
||||
}
|
||||
doc.Security = sec
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -317,11 +317,7 @@ func TestCreateDocument_Paths(t *testing.T) {
|
||||
assert.Equal(t, "$response.body#/id", burgerIdParam.Value)
|
||||
|
||||
// check security requirements
|
||||
security := burgersPost.Security.Value
|
||||
assert.NotNil(t, security)
|
||||
assert.Len(t, security.ValueRequirements, 1)
|
||||
|
||||
oAuthReq := security.FindRequirement("OAuthScheme")
|
||||
oAuthReq := burgersPost.FindSecurityRequirement("OAuthScheme")
|
||||
assert.Len(t, oAuthReq, 2)
|
||||
assert.Equal(t, "read:burgers", oAuthReq[0].Value)
|
||||
|
||||
@@ -453,11 +449,7 @@ func TestCreateDocument_Components_Links(t *testing.T) {
|
||||
|
||||
func TestCreateDocument_Doc_Security(t *testing.T) {
|
||||
initTest()
|
||||
security := doc.Security.Value
|
||||
assert.NotNil(t, security)
|
||||
assert.Len(t, security.ValueRequirements, 1)
|
||||
|
||||
oAuth := security.FindRequirement("OAuthScheme")
|
||||
oAuth := doc.FindSecurityRequirement("OAuthScheme")
|
||||
assert.Len(t, oAuth, 2)
|
||||
}
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ type Document struct {
|
||||
// to authorize a request. Individual operations can override this definition. To make security optional,
|
||||
// an empty security requirement ({}) can be included in the array.
|
||||
// - https://spec.openapis.org/oas/v3.1.0#security-requirement-object
|
||||
Security low.NodeReference[*SecurityRequirement]
|
||||
Security low.NodeReference[[]low.ValueReference[*base.SecurityRequirement]]
|
||||
|
||||
// Tags is a slice of base.Tag instances defined by the specification
|
||||
// A list of tags used by the document with additional metadata. The order of the tags can be used to reflect on
|
||||
@@ -84,6 +84,18 @@ type Document struct {
|
||||
Index *index.SpecIndex
|
||||
}
|
||||
|
||||
// FindSecurityRequirement will attempt to locate a security requirement string from a supplied name.
|
||||
func (d *Document) FindSecurityRequirement(name string) []low.ValueReference[string] {
|
||||
for k := range d.Security.Value {
|
||||
for i := range d.Security.Value[k].Value.Requirements.Value {
|
||||
if i.Value == name {
|
||||
return d.Security.Value[k].Value.Requirements.Value[i].Value
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// TODO: this is early prototype mutation/modification code, keeping it around for later.
|
||||
//func (d *Document) AddTag() *base.Tag {
|
||||
// t := base.NewTag()
|
||||
|
||||
@@ -30,7 +30,7 @@ type Operation struct {
|
||||
Responses low.NodeReference[*Responses]
|
||||
Callbacks low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*Callback]]
|
||||
Deprecated low.NodeReference[bool]
|
||||
Security low.NodeReference[*SecurityRequirement]
|
||||
Security low.NodeReference[[]low.ValueReference[*base.SecurityRequirement]]
|
||||
Servers low.NodeReference[[]low.ValueReference[*Server]]
|
||||
Extensions map[low.KeyReference[string]]low.ValueReference[any]
|
||||
}
|
||||
@@ -40,6 +40,18 @@ func (o *Operation) FindCallback(callback string) *low.ValueReference[*Callback]
|
||||
return low.FindItemInMap[*Callback](callback, o.Callbacks.Value)
|
||||
}
|
||||
|
||||
// FindSecurityRequirement will attempt to locate a security requirement string from a supplied name.
|
||||
func (o *Operation) FindSecurityRequirement(name string) []low.ValueReference[string] {
|
||||
for k := range o.Security.Value {
|
||||
for i := range o.Security.Value[k].Value.Requirements.Value {
|
||||
if i.Value == name {
|
||||
return o.Security.Value[k].Value.Requirements.Value[i].Value
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Build will extract external docs, parameters, request body, responses, callbacks, security and servers.
|
||||
func (o *Operation) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
||||
o.Extensions = low.ExtractExtensions(root)
|
||||
@@ -92,11 +104,17 @@ func (o *Operation) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
||||
}
|
||||
|
||||
// extract security
|
||||
sec, sErr := low.ExtractObject[*SecurityRequirement](SecurityLabel, root, idx)
|
||||
sec, sln, svn, sErr := low.ExtractArray[*base.SecurityRequirement](SecurityLabel, root, idx)
|
||||
if sErr != nil {
|
||||
return sErr
|
||||
}
|
||||
o.Security = sec
|
||||
if sec != nil {
|
||||
o.Security = low.NodeReference[[]low.ValueReference[*base.SecurityRequirement]]{
|
||||
Value: sec,
|
||||
KeyNode: sln,
|
||||
ValueNode: svn,
|
||||
}
|
||||
}
|
||||
|
||||
// extract servers
|
||||
servers, sl, sn, serErr := low.ExtractArray[*Server](ServersLabel, root, idx)
|
||||
|
||||
@@ -65,10 +65,10 @@ servers:
|
||||
assert.Equal(t, "a nice callback",
|
||||
n.FindCallback("niceCallback").Value.FindExpression("ohISee").Value.Description.Value)
|
||||
assert.True(t, n.Deprecated.Value)
|
||||
assert.Len(t, n.Security.Value.ValueRequirements, 1)
|
||||
assert.Len(t, n.Security.Value.FindRequirement("books"), 2)
|
||||
assert.Equal(t, "read:books", n.Security.Value.FindRequirement("books")[0].Value)
|
||||
assert.Equal(t, "write:books", n.Security.Value.FindRequirement("books")[1].Value)
|
||||
assert.Len(t, n.Security.Value, 1)
|
||||
assert.Len(t, n.FindSecurityRequirement("books"), 2)
|
||||
assert.Equal(t, "read:books", n.FindSecurityRequirement("books")[0].Value)
|
||||
assert.Equal(t, "write:books", n.FindSecurityRequirement("books")[1].Value)
|
||||
assert.Len(t, n.Servers.Value, 1)
|
||||
assert.Equal(t, "https://pb33f.io", n.Servers.Value[0].Value.URL.Value)
|
||||
}
|
||||
|
||||
@@ -8,9 +8,7 @@ import (
|
||||
"fmt"
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"gopkg.in/yaml.v3"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@@ -48,11 +46,11 @@ type SecurityScheme struct {
|
||||
// When a list of Security Requirement Objects is defined on the OpenAPI Object or Operation Object, only one of the
|
||||
// Security Requirement Objects in the list needs to be satisfied to authorize the request.
|
||||
// - https://spec.openapis.org/oas/v3.1.0#security-requirement-object
|
||||
type SecurityRequirement struct {
|
||||
|
||||
// FYI, I hate this data structure. Even without the low level wrapping, it sucks.
|
||||
ValueRequirements []low.ValueReference[map[low.KeyReference[string]]low.ValueReference[[]low.ValueReference[string]]]
|
||||
}
|
||||
//type SecurityRequirement struct {
|
||||
//
|
||||
// // FYI, I hate this data structure. Even without the low level wrapping, it sucks.
|
||||
// ValueRequirements []low.ValueReference[map[low.KeyReference[string]]low.ValueReference[[]low.ValueReference[string]]]
|
||||
//}
|
||||
|
||||
// FindExtension attempts to locate an extension using the supplied key.
|
||||
func (ss *SecurityScheme) FindExtension(ext string) *low.ValueReference[any] {
|
||||
@@ -105,89 +103,3 @@ func (ss *SecurityScheme) Hash() [32]byte {
|
||||
}
|
||||
return sha256.Sum256([]byte(strings.Join(f, "|")))
|
||||
}
|
||||
|
||||
// FindRequirement will attempt to locate a security requirement string from a supplied name.
|
||||
func (sr *SecurityRequirement) FindRequirement(name string) []low.ValueReference[string] {
|
||||
for _, r := range sr.ValueRequirements {
|
||||
for k, v := range r.Value {
|
||||
if k.Value == name {
|
||||
return v.Value
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Build will extract all security requirements
|
||||
func (sr *SecurityRequirement) Build(root *yaml.Node, _ *index.SpecIndex) error {
|
||||
if utils.IsNodeArray(root) {
|
||||
var requirements []low.ValueReference[map[low.KeyReference[string]]low.ValueReference[[]low.ValueReference[string]]]
|
||||
for _, n := range root.Content {
|
||||
var currSec *yaml.Node
|
||||
if utils.IsNodeMap(n) {
|
||||
res := make(map[low.KeyReference[string]]low.ValueReference[[]low.ValueReference[string]])
|
||||
var dat []low.ValueReference[string]
|
||||
for i, r := range n.Content {
|
||||
if i%2 == 0 {
|
||||
currSec = r
|
||||
continue
|
||||
}
|
||||
if utils.IsNodeArray(r) {
|
||||
// value (should be) an array of strings
|
||||
var keyValues []low.ValueReference[string]
|
||||
for _, strN := range r.Content {
|
||||
keyValues = append(keyValues, low.ValueReference[string]{
|
||||
Value: strN.Value,
|
||||
ValueNode: strN,
|
||||
})
|
||||
}
|
||||
dat = keyValues
|
||||
}
|
||||
}
|
||||
if currSec != nil {
|
||||
res[low.KeyReference[string]{
|
||||
Value: currSec.Value,
|
||||
KeyNode: currSec,
|
||||
}] = low.ValueReference[[]low.ValueReference[string]]{
|
||||
Value: dat,
|
||||
ValueNode: currSec,
|
||||
}
|
||||
requirements = append(requirements,
|
||||
low.ValueReference[map[low.KeyReference[string]]low.ValueReference[[]low.ValueReference[string]]]{
|
||||
Value: res,
|
||||
ValueNode: n,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
sr.ValueRequirements = requirements
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Hash will return a consistent SHA256 Hash of the SecurityRequirement object
|
||||
func (sr *SecurityRequirement) Hash() [32]byte {
|
||||
var f []string
|
||||
for i := range sr.ValueRequirements {
|
||||
req := sr.ValueRequirements[i].Value
|
||||
values := make(map[string][]string, len(req))
|
||||
var valKeys []string
|
||||
for k := range req {
|
||||
var vals []string
|
||||
for y := range req[k].Value {
|
||||
vals = append(vals, req[k].Value[y].Value)
|
||||
}
|
||||
sort.Strings(vals)
|
||||
valKeys = append(valKeys, k.Value)
|
||||
if len(vals) > 0 {
|
||||
values[k.Value] = vals
|
||||
}
|
||||
}
|
||||
sort.Strings(valKeys)
|
||||
for val := range valKeys {
|
||||
f = append(f, fmt.Sprintf("%s-%s", valKeys[val],
|
||||
strings.Join(values[valKeys[val]], "|")))
|
||||
}
|
||||
}
|
||||
return sha256.Sum256([]byte(strings.Join(f, "|")))
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ package v3
|
||||
|
||||
import (
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"gopkg.in/yaml.v3"
|
||||
@@ -12,7 +13,7 @@ import (
|
||||
)
|
||||
|
||||
func TestSecurityRequirement_Build(t *testing.T) {
|
||||
yml := `- something:
|
||||
yml := `something:
|
||||
- read:me
|
||||
- write:me`
|
||||
|
||||
@@ -20,13 +21,14 @@ func TestSecurityRequirement_Build(t *testing.T) {
|
||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||
idx := index.NewSpecIndex(&idxNode)
|
||||
|
||||
var n SecurityRequirement
|
||||
var n base.SecurityRequirement
|
||||
err := low.BuildModel(&idxNode, &n)
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = n.Build(idxNode.Content[0], idx)
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, n.ValueRequirements, 1)
|
||||
assert.Len(t, n.Requirements.Value, 1)
|
||||
assert.Equal(t, "read:me", n.FindRequirement("something")[0].Value)
|
||||
assert.Equal(t, "write:me", n.FindRequirement("something")[1].Value)
|
||||
assert.Nil(t, n.FindRequirement("none"))
|
||||
|
||||
@@ -5,10 +5,9 @@ package model
|
||||
|
||||
import (
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/datamodel/low/v2"
|
||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||
"github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||
"gopkg.in/yaml.v3"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
type SecurityRequirementChanges struct {
|
||||
@@ -33,76 +32,15 @@ func addedSecurityRequirement(vn *yaml.Node, name string, changes *[]*Change) {
|
||||
nil, vn, false, nil, name)
|
||||
}
|
||||
|
||||
func CompareSecurityRequirement(l, r any) *SecurityRequirementChanges {
|
||||
func CompareSecurityRequirement(l, r *base.SecurityRequirement) *SecurityRequirementChanges {
|
||||
|
||||
var changes []*Change
|
||||
sc := new(SecurityRequirementChanges)
|
||||
|
||||
if reflect.TypeOf(&v2.SecurityRequirement{}) == reflect.TypeOf(l) &&
|
||||
reflect.TypeOf(&v2.SecurityRequirement{}) == reflect.TypeOf(r) {
|
||||
|
||||
lSec := l.(*v2.SecurityRequirement)
|
||||
rSec := r.(*v2.SecurityRequirement)
|
||||
|
||||
if low.AreEqual(lSec, rSec) {
|
||||
if low.AreEqual(l, r) {
|
||||
return nil
|
||||
}
|
||||
checkSecurityRequirement(lSec.Values.Value, rSec.Values.Value, &changes)
|
||||
|
||||
}
|
||||
|
||||
if reflect.TypeOf(&v3.SecurityRequirement{}) == reflect.TypeOf(l) &&
|
||||
reflect.TypeOf(&v3.SecurityRequirement{}) == reflect.TypeOf(r) {
|
||||
|
||||
lSec := l.(*v3.SecurityRequirement)
|
||||
rSec := r.(*v3.SecurityRequirement)
|
||||
|
||||
if low.AreEqual(lSec, rSec) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// can we find anyone to dance with?
|
||||
findPartner := func(key string,
|
||||
search map[low.KeyReference[string]]map[low.KeyReference[string]]low.ValueReference[[]low.ValueReference[string]]) map[low.KeyReference[string]]low.ValueReference[[]low.ValueReference[string]] {
|
||||
for k := range search {
|
||||
if k.Value == key {
|
||||
return search[k]
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Yes, this exists.
|
||||
lValues := make(map[low.KeyReference[string]]map[low.KeyReference[string]]low.ValueReference[[]low.ValueReference[string]])
|
||||
rValues := make(map[low.KeyReference[string]]map[low.KeyReference[string]]low.ValueReference[[]low.ValueReference[string]])
|
||||
for i := range lSec.ValueRequirements {
|
||||
for k := range lSec.ValueRequirements[i].Value {
|
||||
lValues[k] = lSec.ValueRequirements[i].Value
|
||||
}
|
||||
}
|
||||
for i := range rSec.ValueRequirements {
|
||||
for k := range rSec.ValueRequirements[i].Value {
|
||||
rValues[k] = rSec.ValueRequirements[i].Value
|
||||
}
|
||||
}
|
||||
|
||||
// look through left and right slices to see if we recognize anything.
|
||||
for k := range lValues {
|
||||
if p := findPartner(k.Value, rValues); p != nil {
|
||||
checkSecurityRequirement(lValues[k], p, &changes)
|
||||
continue
|
||||
}
|
||||
CreateChange(&changes, ObjectRemoved, v3.SecurityLabel,
|
||||
k.KeyNode, nil, true, lValues[k], nil)
|
||||
}
|
||||
for k := range rValues {
|
||||
if ok := findPartner(k.Value, lValues); ok == nil {
|
||||
CreateChange(&changes, ObjectAdded, v3.SecurityLabel,
|
||||
nil, k.KeyNode, false, nil, rValues[k])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
checkSecurityRequirement(l.Requirements.Value, r.Requirements.Value, &changes)
|
||||
sc.Changes = changes
|
||||
return sc
|
||||
}
|
||||
@@ -199,11 +137,3 @@ func checkSecurityRequirement(lSec, rSec map[low.KeyReference[string]]low.ValueR
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func CompareSecurityRequirementV3(l, r *v3.SecurityRequirement) *SecurityRequirementChanges {
|
||||
return CompareSecurityRequirement(l, r)
|
||||
}
|
||||
|
||||
func CompareSecurityRequirementV2(l, r *v2.SecurityRequirement) *SecurityRequirementChanges {
|
||||
return CompareSecurityRequirement(l, r)
|
||||
}
|
||||
|
||||
@@ -5,8 +5,7 @@ package model
|
||||
|
||||
import (
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/datamodel/low/v2"
|
||||
"github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"gopkg.in/yaml.v3"
|
||||
"testing"
|
||||
@@ -27,15 +26,15 @@ func TestCompareSecurityRequirement_V2(t *testing.T) {
|
||||
_ = yaml.Unmarshal([]byte(right), &rNode)
|
||||
|
||||
// create low level objects
|
||||
var lDoc v2.SecurityRequirement
|
||||
var rDoc v2.SecurityRequirement
|
||||
var lDoc base.SecurityRequirement
|
||||
var rDoc base.SecurityRequirement
|
||||
_ = low.BuildModel(&lNode, &lDoc)
|
||||
_ = low.BuildModel(&rNode, &rDoc)
|
||||
_ = lDoc.Build(lNode.Content[0], nil)
|
||||
_ = rDoc.Build(rNode.Content[0], nil)
|
||||
|
||||
// compare
|
||||
extChanges := CompareSecurityRequirementV2(&lDoc, &rDoc)
|
||||
extChanges := CompareSecurityRequirement(&lDoc, &rDoc)
|
||||
assert.Nil(t, extChanges)
|
||||
}
|
||||
|
||||
@@ -60,15 +59,15 @@ biscuit:
|
||||
_ = yaml.Unmarshal([]byte(right), &rNode)
|
||||
|
||||
// create low level objects
|
||||
var lDoc v2.SecurityRequirement
|
||||
var rDoc v2.SecurityRequirement
|
||||
var lDoc base.SecurityRequirement
|
||||
var rDoc base.SecurityRequirement
|
||||
_ = low.BuildModel(&lNode, &lDoc)
|
||||
_ = low.BuildModel(&rNode, &rDoc)
|
||||
_ = lDoc.Build(lNode.Content[0], nil)
|
||||
_ = rDoc.Build(rNode.Content[0], nil)
|
||||
|
||||
// compare
|
||||
extChanges := CompareSecurityRequirementV2(&lDoc, &rDoc)
|
||||
extChanges := CompareSecurityRequirement(&lDoc, &rDoc)
|
||||
assert.Equal(t, 1, extChanges.TotalChanges())
|
||||
assert.Equal(t, 0, extChanges.TotalBreakingChanges())
|
||||
assert.Equal(t, ObjectAdded, extChanges.Changes[0].ChangeType)
|
||||
@@ -92,15 +91,15 @@ biscuit:
|
||||
_ = yaml.Unmarshal([]byte(right), &rNode)
|
||||
|
||||
// create low level objects
|
||||
var lDoc v2.SecurityRequirement
|
||||
var rDoc v2.SecurityRequirement
|
||||
var lDoc base.SecurityRequirement
|
||||
var rDoc base.SecurityRequirement
|
||||
_ = low.BuildModel(&lNode, &lDoc)
|
||||
_ = low.BuildModel(&rNode, &rDoc)
|
||||
_ = lDoc.Build(lNode.Content[0], nil)
|
||||
_ = rDoc.Build(rNode.Content[0], nil)
|
||||
|
||||
// compare
|
||||
extChanges := CompareSecurityRequirementV2(&rDoc, &lDoc)
|
||||
extChanges := CompareSecurityRequirement(&rDoc, &lDoc)
|
||||
assert.Equal(t, 1, extChanges.TotalChanges())
|
||||
assert.Equal(t, 1, extChanges.TotalBreakingChanges())
|
||||
}
|
||||
@@ -124,15 +123,15 @@ milk:
|
||||
_ = yaml.Unmarshal([]byte(right), &rNode)
|
||||
|
||||
// create low level objects
|
||||
var lDoc v2.SecurityRequirement
|
||||
var rDoc v2.SecurityRequirement
|
||||
var lDoc base.SecurityRequirement
|
||||
var rDoc base.SecurityRequirement
|
||||
_ = low.BuildModel(&lNode, &lDoc)
|
||||
_ = low.BuildModel(&rNode, &rDoc)
|
||||
_ = lDoc.Build(lNode.Content[0], nil)
|
||||
_ = rDoc.Build(rNode.Content[0], nil)
|
||||
|
||||
// compare
|
||||
extChanges := CompareSecurityRequirementV2(&lDoc, &rDoc)
|
||||
extChanges := CompareSecurityRequirement(&lDoc, &rDoc)
|
||||
assert.Equal(t, 4, extChanges.TotalChanges())
|
||||
assert.Equal(t, 2, extChanges.TotalBreakingChanges())
|
||||
assert.Equal(t, ObjectRemoved, extChanges.Changes[0].ChangeType)
|
||||
@@ -160,15 +159,15 @@ milk:
|
||||
_ = yaml.Unmarshal([]byte(right), &rNode)
|
||||
|
||||
// create low level objects
|
||||
var lDoc v2.SecurityRequirement
|
||||
var rDoc v2.SecurityRequirement
|
||||
var lDoc base.SecurityRequirement
|
||||
var rDoc base.SecurityRequirement
|
||||
_ = low.BuildModel(&lNode, &lDoc)
|
||||
_ = low.BuildModel(&rNode, &rDoc)
|
||||
_ = lDoc.Build(lNode.Content[0], nil)
|
||||
_ = rDoc.Build(rNode.Content[0], nil)
|
||||
|
||||
// compare
|
||||
extChanges := CompareSecurityRequirementV2(&lDoc, &rDoc)
|
||||
extChanges := CompareSecurityRequirement(&lDoc, &rDoc)
|
||||
assert.Equal(t, 2, extChanges.TotalChanges())
|
||||
assert.Equal(t, 1, extChanges.TotalBreakingChanges())
|
||||
assert.Equal(t, ObjectRemoved, extChanges.Changes[0].ChangeType)
|
||||
@@ -195,15 +194,15 @@ biscuit:
|
||||
_ = yaml.Unmarshal([]byte(right), &rNode)
|
||||
|
||||
// create low level objects
|
||||
var lDoc v2.SecurityRequirement
|
||||
var rDoc v2.SecurityRequirement
|
||||
var lDoc base.SecurityRequirement
|
||||
var rDoc base.SecurityRequirement
|
||||
_ = low.BuildModel(&lNode, &lDoc)
|
||||
_ = low.BuildModel(&rNode, &rDoc)
|
||||
_ = lDoc.Build(lNode.Content[0], nil)
|
||||
_ = rDoc.Build(rNode.Content[0], nil)
|
||||
|
||||
// compare
|
||||
extChanges := CompareSecurityRequirementV2(&lDoc, &rDoc)
|
||||
extChanges := CompareSecurityRequirement(&lDoc, &rDoc)
|
||||
assert.Equal(t, 1, extChanges.TotalChanges())
|
||||
assert.Equal(t, 0, extChanges.TotalBreakingChanges())
|
||||
assert.Equal(t, ObjectAdded, extChanges.Changes[0].ChangeType)
|
||||
@@ -233,15 +232,15 @@ biscuit:
|
||||
_ = yaml.Unmarshal([]byte(right), &rNode)
|
||||
|
||||
// create low level objects
|
||||
var lDoc v2.SecurityRequirement
|
||||
var rDoc v2.SecurityRequirement
|
||||
var lDoc base.SecurityRequirement
|
||||
var rDoc base.SecurityRequirement
|
||||
_ = low.BuildModel(&lNode, &lDoc)
|
||||
_ = low.BuildModel(&rNode, &rDoc)
|
||||
_ = lDoc.Build(lNode.Content[0], nil)
|
||||
_ = rDoc.Build(rNode.Content[0], nil)
|
||||
|
||||
// compare
|
||||
extChanges := CompareSecurityRequirementV2(&lDoc, &rDoc)
|
||||
extChanges := CompareSecurityRequirement(&lDoc, &rDoc)
|
||||
assert.Equal(t, 2, extChanges.TotalChanges())
|
||||
assert.Equal(t, 0, extChanges.TotalBreakingChanges())
|
||||
assert.Equal(t, ObjectAdded, extChanges.Changes[0].ChangeType)
|
||||
@@ -267,15 +266,15 @@ biscuit:
|
||||
_ = yaml.Unmarshal([]byte(right), &rNode)
|
||||
|
||||
// create low level objects
|
||||
var lDoc v2.SecurityRequirement
|
||||
var rDoc v2.SecurityRequirement
|
||||
var lDoc base.SecurityRequirement
|
||||
var rDoc base.SecurityRequirement
|
||||
_ = low.BuildModel(&lNode, &lDoc)
|
||||
_ = low.BuildModel(&rNode, &rDoc)
|
||||
_ = lDoc.Build(lNode.Content[0], nil)
|
||||
_ = rDoc.Build(rNode.Content[0], nil)
|
||||
|
||||
// compare
|
||||
extChanges := CompareSecurityRequirementV2(&lDoc, &rDoc)
|
||||
extChanges := CompareSecurityRequirement(&lDoc, &rDoc)
|
||||
assert.Equal(t, 3, extChanges.TotalChanges())
|
||||
assert.Equal(t, 1, extChanges.TotalBreakingChanges())
|
||||
}
|
||||
@@ -301,15 +300,15 @@ biscuit:
|
||||
_ = yaml.Unmarshal([]byte(right), &rNode)
|
||||
|
||||
// create low level objects
|
||||
var lDoc v2.SecurityRequirement
|
||||
var rDoc v2.SecurityRequirement
|
||||
var lDoc base.SecurityRequirement
|
||||
var rDoc base.SecurityRequirement
|
||||
_ = low.BuildModel(&lNode, &lDoc)
|
||||
_ = low.BuildModel(&rNode, &rDoc)
|
||||
_ = lDoc.Build(lNode.Content[0], nil)
|
||||
_ = rDoc.Build(rNode.Content[0], nil)
|
||||
|
||||
// compare
|
||||
extChanges := CompareSecurityRequirementV2(&lDoc, &rDoc)
|
||||
extChanges := CompareSecurityRequirement(&lDoc, &rDoc)
|
||||
assert.Nil(t, extChanges)
|
||||
}
|
||||
|
||||
@@ -333,15 +332,15 @@ biscuit:
|
||||
_ = yaml.Unmarshal([]byte(right), &rNode)
|
||||
|
||||
// create low level objects
|
||||
var lDoc v2.SecurityRequirement
|
||||
var rDoc v2.SecurityRequirement
|
||||
var lDoc base.SecurityRequirement
|
||||
var rDoc base.SecurityRequirement
|
||||
_ = low.BuildModel(&lNode, &lDoc)
|
||||
_ = low.BuildModel(&rNode, &rDoc)
|
||||
_ = lDoc.Build(lNode.Content[0], nil)
|
||||
_ = rDoc.Build(rNode.Content[0], nil)
|
||||
|
||||
// compare
|
||||
extChanges := CompareSecurityRequirementV2(&rDoc, &lDoc)
|
||||
extChanges := CompareSecurityRequirement(&rDoc, &lDoc)
|
||||
assert.Equal(t, 1, extChanges.TotalChanges())
|
||||
assert.Equal(t, 1, extChanges.TotalBreakingChanges())
|
||||
assert.Equal(t, ObjectRemoved, extChanges.Changes[0].ChangeType)
|
||||
@@ -369,167 +368,168 @@ biscuit:
|
||||
_ = yaml.Unmarshal([]byte(right), &rNode)
|
||||
|
||||
// create low level objects
|
||||
var lDoc v2.SecurityRequirement
|
||||
var rDoc v2.SecurityRequirement
|
||||
var lDoc base.SecurityRequirement
|
||||
var rDoc base.SecurityRequirement
|
||||
_ = low.BuildModel(&lNode, &lDoc)
|
||||
_ = low.BuildModel(&rNode, &rDoc)
|
||||
_ = lDoc.Build(lNode.Content[0], nil)
|
||||
_ = rDoc.Build(rNode.Content[0], nil)
|
||||
|
||||
// compare
|
||||
extChanges := CompareSecurityRequirementV2(&lDoc, &rDoc)
|
||||
extChanges := CompareSecurityRequirement(&lDoc, &rDoc)
|
||||
assert.Equal(t, 2, extChanges.TotalChanges())
|
||||
assert.Equal(t, 0, extChanges.TotalBreakingChanges())
|
||||
assert.Equal(t, ObjectAdded, extChanges.Changes[0].ChangeType)
|
||||
}
|
||||
|
||||
func TestCompareSecurityRequirement_V3(t *testing.T) {
|
||||
|
||||
left := `- auth:
|
||||
- pizza
|
||||
- pie`
|
||||
|
||||
right := `- auth:
|
||||
- pie
|
||||
- pizza`
|
||||
|
||||
var lNode, rNode yaml.Node
|
||||
_ = yaml.Unmarshal([]byte(left), &lNode)
|
||||
_ = yaml.Unmarshal([]byte(right), &rNode)
|
||||
|
||||
// create low level objects
|
||||
var lDoc v3.SecurityRequirement
|
||||
var rDoc v3.SecurityRequirement
|
||||
_ = low.BuildModel(&lNode, &lDoc)
|
||||
_ = low.BuildModel(&rNode, &rDoc)
|
||||
_ = lDoc.Build(lNode.Content[0], nil)
|
||||
_ = rDoc.Build(rNode.Content[0], nil)
|
||||
|
||||
// compare
|
||||
extChanges := CompareSecurityRequirementV3(&lDoc, &rDoc)
|
||||
assert.Nil(t, extChanges)
|
||||
}
|
||||
|
||||
func TestCompareSecurityRequirement_V3_AddARole(t *testing.T) {
|
||||
|
||||
left := `- auth:
|
||||
- pizza
|
||||
- pie`
|
||||
|
||||
right := `- auth:
|
||||
- pie
|
||||
- pizza
|
||||
- beer`
|
||||
|
||||
var lNode, rNode yaml.Node
|
||||
_ = yaml.Unmarshal([]byte(left), &lNode)
|
||||
_ = yaml.Unmarshal([]byte(right), &rNode)
|
||||
|
||||
// create low level objects
|
||||
var lDoc v3.SecurityRequirement
|
||||
var rDoc v3.SecurityRequirement
|
||||
_ = low.BuildModel(&lNode, &lDoc)
|
||||
_ = low.BuildModel(&rNode, &rDoc)
|
||||
_ = lDoc.Build(lNode.Content[0], nil)
|
||||
_ = rDoc.Build(rNode.Content[0], nil)
|
||||
|
||||
// compare
|
||||
extChanges := CompareSecurityRequirementV3(&lDoc, &rDoc)
|
||||
assert.Equal(t, 1, extChanges.TotalChanges())
|
||||
assert.Equal(t, 0, extChanges.TotalBreakingChanges())
|
||||
assert.Equal(t, ObjectAdded, extChanges.Changes[0].ChangeType)
|
||||
}
|
||||
|
||||
func TestCompareSecurityRequirement_V3_RemoveRole(t *testing.T) {
|
||||
|
||||
left := `- auth:
|
||||
- pizza
|
||||
- pie`
|
||||
|
||||
right := `- auth:
|
||||
- pie
|
||||
- pizza
|
||||
- beer`
|
||||
|
||||
var lNode, rNode yaml.Node
|
||||
_ = yaml.Unmarshal([]byte(left), &lNode)
|
||||
_ = yaml.Unmarshal([]byte(right), &rNode)
|
||||
|
||||
// create low level objects
|
||||
var lDoc v3.SecurityRequirement
|
||||
var rDoc v3.SecurityRequirement
|
||||
_ = low.BuildModel(&lNode, &lDoc)
|
||||
_ = low.BuildModel(&rNode, &rDoc)
|
||||
_ = lDoc.Build(lNode.Content[0], nil)
|
||||
_ = rDoc.Build(rNode.Content[0], nil)
|
||||
|
||||
// compare
|
||||
extChanges := CompareSecurityRequirementV3(&rDoc, &lDoc)
|
||||
assert.Equal(t, 1, extChanges.TotalChanges())
|
||||
assert.Equal(t, 1, extChanges.TotalBreakingChanges())
|
||||
assert.Equal(t, ObjectRemoved, extChanges.Changes[0].ChangeType)
|
||||
}
|
||||
|
||||
func TestCompareSecurityRequirement_V3_AddAReq(t *testing.T) {
|
||||
|
||||
left := `- auth:
|
||||
- pizza
|
||||
- pie`
|
||||
|
||||
right := `- auth:
|
||||
- pie
|
||||
- pizza
|
||||
- coffee:
|
||||
- filter
|
||||
- espresso`
|
||||
|
||||
var lNode, rNode yaml.Node
|
||||
_ = yaml.Unmarshal([]byte(left), &lNode)
|
||||
_ = yaml.Unmarshal([]byte(right), &rNode)
|
||||
|
||||
// create low level objects
|
||||
var lDoc v3.SecurityRequirement
|
||||
var rDoc v3.SecurityRequirement
|
||||
_ = low.BuildModel(&lNode, &lDoc)
|
||||
_ = low.BuildModel(&rNode, &rDoc)
|
||||
_ = lDoc.Build(lNode.Content[0], nil)
|
||||
_ = rDoc.Build(rNode.Content[0], nil)
|
||||
|
||||
// compare
|
||||
extChanges := CompareSecurityRequirementV3(&lDoc, &rDoc)
|
||||
assert.Equal(t, 1, extChanges.TotalChanges())
|
||||
assert.Equal(t, 0, extChanges.TotalBreakingChanges())
|
||||
assert.Equal(t, ObjectAdded, extChanges.Changes[0].ChangeType)
|
||||
}
|
||||
|
||||
func TestCompareSecurityRequirement_V3_RemoveAReq(t *testing.T) {
|
||||
|
||||
left := `- coffee:
|
||||
- filter
|
||||
- espresso`
|
||||
|
||||
right := `- coffee:
|
||||
- filter
|
||||
- espresso
|
||||
- auth:
|
||||
- pizza
|
||||
- pie`
|
||||
|
||||
var lNode, rNode yaml.Node
|
||||
_ = yaml.Unmarshal([]byte(left), &lNode)
|
||||
_ = yaml.Unmarshal([]byte(right), &rNode)
|
||||
|
||||
// create low level objects
|
||||
var lDoc v3.SecurityRequirement
|
||||
var rDoc v3.SecurityRequirement
|
||||
_ = low.BuildModel(&lNode, &lDoc)
|
||||
_ = low.BuildModel(&rNode, &rDoc)
|
||||
_ = lDoc.Build(lNode.Content[0], nil)
|
||||
_ = rDoc.Build(rNode.Content[0], nil)
|
||||
|
||||
// compare
|
||||
extChanges := CompareSecurityRequirementV3(&rDoc, &lDoc)
|
||||
assert.Equal(t, 1, extChanges.TotalChanges())
|
||||
assert.Equal(t, 1, extChanges.TotalBreakingChanges())
|
||||
assert.Equal(t, ObjectRemoved, extChanges.Changes[0].ChangeType)
|
||||
}
|
||||
//
|
||||
//func TestCompareSecurityRequirement_V3(t *testing.T) {
|
||||
//
|
||||
// left := `- auth:
|
||||
// - pizza
|
||||
// - pie`
|
||||
//
|
||||
// right := `- auth:
|
||||
// - pie
|
||||
// - pizza`
|
||||
//
|
||||
// var lNode, rNode yaml.Node
|
||||
// _ = yaml.Unmarshal([]byte(left), &lNode)
|
||||
// _ = yaml.Unmarshal([]byte(right), &rNode)
|
||||
//
|
||||
// // create low level objects
|
||||
// var lDoc v3.SecurityRequirement
|
||||
// var rDoc v3.SecurityRequirement
|
||||
// _ = low.BuildModel(&lNode, &lDoc)
|
||||
// _ = low.BuildModel(&rNode, &rDoc)
|
||||
// _ = lDoc.Build(lNode.Content[0], nil)
|
||||
// _ = rDoc.Build(rNode.Content[0], nil)
|
||||
//
|
||||
// // compare
|
||||
// extChanges := CompareSecurityRequirementV3(&lDoc, &rDoc)
|
||||
// assert.Nil(t, extChanges)
|
||||
//}
|
||||
//
|
||||
//func TestCompareSecurityRequirement_V3_AddARole(t *testing.T) {
|
||||
//
|
||||
// left := `- auth:
|
||||
// - pizza
|
||||
// - pie`
|
||||
//
|
||||
// right := `- auth:
|
||||
// - pie
|
||||
// - pizza
|
||||
// - beer`
|
||||
//
|
||||
// var lNode, rNode yaml.Node
|
||||
// _ = yaml.Unmarshal([]byte(left), &lNode)
|
||||
// _ = yaml.Unmarshal([]byte(right), &rNode)
|
||||
//
|
||||
// // create low level objects
|
||||
// var lDoc v3.SecurityRequirement
|
||||
// var rDoc v3.SecurityRequirement
|
||||
// _ = low.BuildModel(&lNode, &lDoc)
|
||||
// _ = low.BuildModel(&rNode, &rDoc)
|
||||
// _ = lDoc.Build(lNode.Content[0], nil)
|
||||
// _ = rDoc.Build(rNode.Content[0], nil)
|
||||
//
|
||||
// // compare
|
||||
// extChanges := CompareSecurityRequirementV3(&lDoc, &rDoc)
|
||||
// assert.Equal(t, 1, extChanges.TotalChanges())
|
||||
// assert.Equal(t, 0, extChanges.TotalBreakingChanges())
|
||||
// assert.Equal(t, ObjectAdded, extChanges.Changes[0].ChangeType)
|
||||
//}
|
||||
//
|
||||
//func TestCompareSecurityRequirement_V3_RemoveRole(t *testing.T) {
|
||||
//
|
||||
// left := `- auth:
|
||||
// - pizza
|
||||
// - pie`
|
||||
//
|
||||
// right := `- auth:
|
||||
// - pie
|
||||
// - pizza
|
||||
// - beer`
|
||||
//
|
||||
// var lNode, rNode yaml.Node
|
||||
// _ = yaml.Unmarshal([]byte(left), &lNode)
|
||||
// _ = yaml.Unmarshal([]byte(right), &rNode)
|
||||
//
|
||||
// // create low level objects
|
||||
// var lDoc v3.SecurityRequirement
|
||||
// var rDoc v3.SecurityRequirement
|
||||
// _ = low.BuildModel(&lNode, &lDoc)
|
||||
// _ = low.BuildModel(&rNode, &rDoc)
|
||||
// _ = lDoc.Build(lNode.Content[0], nil)
|
||||
// _ = rDoc.Build(rNode.Content[0], nil)
|
||||
//
|
||||
// // compare
|
||||
// extChanges := CompareSecurityRequirementV3(&rDoc, &lDoc)
|
||||
// assert.Equal(t, 1, extChanges.TotalChanges())
|
||||
// assert.Equal(t, 1, extChanges.TotalBreakingChanges())
|
||||
// assert.Equal(t, ObjectRemoved, extChanges.Changes[0].ChangeType)
|
||||
//}
|
||||
//
|
||||
//func TestCompareSecurityRequirement_V3_AddAReq(t *testing.T) {
|
||||
//
|
||||
// left := `- auth:
|
||||
// - pizza
|
||||
// - pie`
|
||||
//
|
||||
// right := `- auth:
|
||||
// - pie
|
||||
// - pizza
|
||||
//- coffee:
|
||||
// - filter
|
||||
// - espresso`
|
||||
//
|
||||
// var lNode, rNode yaml.Node
|
||||
// _ = yaml.Unmarshal([]byte(left), &lNode)
|
||||
// _ = yaml.Unmarshal([]byte(right), &rNode)
|
||||
//
|
||||
// // create low level objects
|
||||
// var lDoc v3.SecurityRequirement
|
||||
// var rDoc v3.SecurityRequirement
|
||||
// _ = low.BuildModel(&lNode, &lDoc)
|
||||
// _ = low.BuildModel(&rNode, &rDoc)
|
||||
// _ = lDoc.Build(lNode.Content[0], nil)
|
||||
// _ = rDoc.Build(rNode.Content[0], nil)
|
||||
//
|
||||
// // compare
|
||||
// extChanges := CompareSecurityRequirementV3(&lDoc, &rDoc)
|
||||
// assert.Equal(t, 1, extChanges.TotalChanges())
|
||||
// assert.Equal(t, 0, extChanges.TotalBreakingChanges())
|
||||
// assert.Equal(t, ObjectAdded, extChanges.Changes[0].ChangeType)
|
||||
//}
|
||||
//
|
||||
//func TestCompareSecurityRequirement_V3_RemoveAReq(t *testing.T) {
|
||||
//
|
||||
// left := `- coffee:
|
||||
// - filter
|
||||
// - espresso`
|
||||
//
|
||||
// right := `- coffee:
|
||||
// - filter
|
||||
// - espresso
|
||||
//- auth:
|
||||
// - pizza
|
||||
// - pie`
|
||||
//
|
||||
// var lNode, rNode yaml.Node
|
||||
// _ = yaml.Unmarshal([]byte(left), &lNode)
|
||||
// _ = yaml.Unmarshal([]byte(right), &rNode)
|
||||
//
|
||||
// // create low level objects
|
||||
// var lDoc v3.SecurityRequirement
|
||||
// var rDoc v3.SecurityRequirement
|
||||
// _ = low.BuildModel(&lNode, &lDoc)
|
||||
// _ = low.BuildModel(&rNode, &rDoc)
|
||||
// _ = lDoc.Build(lNode.Content[0], nil)
|
||||
// _ = rDoc.Build(rNode.Content[0], nil)
|
||||
//
|
||||
// // compare
|
||||
// extChanges := CompareSecurityRequirementV3(&rDoc, &lDoc)
|
||||
// assert.Equal(t, 1, extChanges.TotalChanges())
|
||||
// assert.Equal(t, 1, extChanges.TotalBreakingChanges())
|
||||
// assert.Equal(t, ObjectRemoved, extChanges.Changes[0].ChangeType)
|
||||
//}
|
||||
|
||||
Reference in New Issue
Block a user