From 3a41d86ee1ab846d444cedd8a3f08ad7ea527f9b Mon Sep 17 00:00:00 2001 From: Dave Shanley Date: Wed, 10 Aug 2022 07:58:15 -0400 Subject: [PATCH] oAuth flows all wired up and tested working through the components, then back to document, then a QA check. Signed-off-by: Dave Shanley --- datamodel/low/3.0/components.go | 4 +++ datamodel/low/3.0/oauth_flows.go | 37 +++++++++++++++++++++++++++- datamodel/low/3.0/security_scheme.go | 10 ++++++++ openapi/create_document_test.go | 25 +++++++++++++++++++ 4 files changed, 75 insertions(+), 1 deletion(-) diff --git a/datamodel/low/3.0/components.go b/datamodel/low/3.0/components.go index 1e2b52a..2a68f65 100644 --- a/datamodel/low/3.0/components.go +++ b/datamodel/low/3.0/components.go @@ -32,6 +32,10 @@ func (co *Components) FindResponse(response string) *low.ValueReference[*Respons return FindItemInMap[*Response](response, co.Responses.Value) } +func (co *Components) FindSecurityScheme(sScheme string) *low.ValueReference[*SecurityScheme] { + return FindItemInMap[*SecurityScheme](sScheme, co.SecuritySchemes.Value) +} + func (co *Components) Build(root *yaml.Node) error { extensionMap, err := ExtractExtensions(root) if err != nil { diff --git a/datamodel/low/3.0/oauth_flows.go b/datamodel/low/3.0/oauth_flows.go index 07b3dbd..801b64a 100644 --- a/datamodel/low/3.0/oauth_flows.go +++ b/datamodel/low/3.0/oauth_flows.go @@ -2,6 +2,7 @@ package v3 import ( "github.com/pb33f/libopenapi/datamodel/low" + "github.com/pb33f/libopenapi/utils" "gopkg.in/yaml.v3" ) @@ -10,6 +11,7 @@ const ( PasswordLabel = "password" ClientCredentialsLabel = "clientCredentials" AuthorizationCodeLabel = "authorizationCode" + ScopesLabel = "scopes" ) type OAuthFlows struct { @@ -58,15 +60,48 @@ type OAuthFlow struct { AuthorizationUrl low.NodeReference[string] TokenURL low.NodeReference[string] RefreshURL low.NodeReference[string] - Scopes map[low.KeyReference[string]]low.ValueReference[string] + Scopes low.NodeReference[map[low.KeyReference[string]]low.ValueReference[string]] Extensions map[low.KeyReference[string]]low.ValueReference[any] } +func (o *OAuthFlow) FindScope(scope string) *low.ValueReference[string] { + return FindItemInMap[string](scope, o.Scopes.Value) +} + func (o *OAuthFlow) Build(root *yaml.Node) error { extensionMap, err := ExtractExtensions(root) if err != nil { return err } o.Extensions = extensionMap + + var currSec *yaml.Node + + // extract scopes + _, scopeLabel, scopeNode := utils.FindKeyNodeFull(ScopesLabel, root.Content) + if scopeNode != nil { + res := make(map[low.KeyReference[string]]low.ValueReference[string]) + for i, r := range scopeNode.Content { + if i%2 == 0 { + currSec = r + continue + } + res[low.KeyReference[string]{ + Value: currSec.Value, + KeyNode: currSec, + }] = low.ValueReference[string]{ + Value: r.Value, + ValueNode: r, + } + } + if len(res) > 0 { + o.Scopes = low.NodeReference[map[low.KeyReference[string]]low.ValueReference[string]]{ + Value: res, + KeyNode: scopeLabel, + ValueNode: scopeNode, + } + } + } + return nil } diff --git a/datamodel/low/3.0/security_scheme.go b/datamodel/low/3.0/security_scheme.go index d2324b1..60711a4 100644 --- a/datamodel/low/3.0/security_scheme.go +++ b/datamodel/low/3.0/security_scheme.go @@ -9,6 +9,7 @@ import ( const ( SecurityLabel = "security" SecuritySchemesLabel = "securitySchemes" + OAuthFlowsLabel = "flows" ) type SecurityScheme struct { @@ -29,6 +30,15 @@ func (ss *SecurityScheme) Build(root *yaml.Node) error { return err } ss.Extensions = extensionMap + + oa, oaErr := ExtractObject[*OAuthFlows](OAuthFlowsLabel, root) + if oaErr != nil { + return oaErr + } + if oa.Value != nil { + ss.Flows = oa + } + return nil } diff --git a/openapi/create_document_test.go b/openapi/create_document_test.go index 6afedff..4b03ee5 100644 --- a/openapi/create_document_test.go +++ b/openapi/create_document_test.go @@ -257,4 +257,29 @@ func TestCreateDocument_Components_Schemas(t *testing.T) { assert.Equal(t, "a frosty cold beverage can be coke or sprite", fries.Value.FindProperty("favoriteDrink").Value.Description.Value) + // check security schemes + securitySchemes := components.SecuritySchemes.Value + assert.Len(t, securitySchemes, 3) + + apiKey := components.FindSecurityScheme("APIKeyScheme").Value + assert.NotNil(t, apiKey) + assert.Equal(t, "an apiKey security scheme", apiKey.Description.Value) + + oAuth := components.FindSecurityScheme("OAuthScheme").Value + assert.NotNil(t, oAuth) + assert.Equal(t, "an oAuth security scheme", oAuth.Description.Value) + assert.NotNil(t, oAuth.Flows.Value.Implicit.Value) + assert.NotNil(t, oAuth.Flows.Value.AuthorizationCode.Value) + + scopes := oAuth.Flows.Value.Implicit.Value.Scopes.Value + assert.NotNil(t, scopes) + + readScope := oAuth.Flows.Value.Implicit.Value.FindScope("write:burgers") + assert.NotNil(t, readScope) + assert.Equal(t, "modify and add new burgers", readScope.Value) + + readScope = oAuth.Flows.Value.AuthorizationCode.Value.FindScope("write:burgers") + assert.NotNil(t, readScope) + assert.Equal(t, "modify burgers and stuff", readScope.Value) + }