Skip to content

Commit ea8c703

Browse files
authored
feat: v2 top level security field (#2030)
1 parent 17c76bd commit ea8c703

File tree

4 files changed

+58
-1
lines changed

4 files changed

+58
-1
lines changed

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,7 @@ func (c *Controller) ListAccounts(ctx *gin.Context) {
429429
| schemes | The transfer protocol for the operation that separated by spaces. | // @schemes http https |
430430
| externalDocs.description | Description of the external document. | // @externalDocs.description OpenAPI |
431431
| externalDocs.url | URL of the external document. | // @externalDocs.url https://swagger.io/resources/open-api/ |
432+
| security | Global security requirements that apply to all operations by default. | // @security ApiKeyAuth |
432433
| x-name | The extension key, must be start by x- and take only json value | // @x-example-key {"key": "value"} |
433434
434435
### Using markdown descriptions
@@ -920,8 +921,13 @@ General API info.
920921
// @tokenUrl https://example.com/oauth/token
921922
// @scope.write Grants write access
922923
// @scope.admin Grants read and write access to administrative information
924+
925+
// @security BasicAuth
926+
// @security OAuth2Application
923927
```
924928
929+
To set global security requirements that apply to all operations by default, use the `@security` annotation in your general API info. This creates a top-level `security` array in the generated OpenAPI specification.
930+
925931
Each API operation.
926932
927933
```go

field_parser_v3_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,8 @@ func TestDefaultFieldParserV3(t *testing.T) {
184184
t.Parallel()
185185

186186
schema := spec.NewSchemaSpec()
187-
schema.Spec.Type = []string{"string"}
187+
typeArray := spec.NewSingleOrArray("string")
188+
schema.Spec.Type = &typeArray
188189
parser := &Parser{}
189190
fieldParser := newTagBaseFieldParserV3(
190191
parser,

parserv3.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,9 @@ func (p *Parser) parseGeneralAPIInfoV3(comments []string) error {
142142

143143
p.openAPI.Components.Spec.SecuritySchemes[key] = schemeSpec
144144

145+
case securityAttr:
146+
p.openAPI.Security = append(p.openAPI.Security, parseSecurity(value))
147+
145148
case "@query.collection.format":
146149
p.collectionFormatInQuery = TransToValidCollectionFormat(value)
147150

parserv3_test.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,53 @@ func TestParserParseServers(t *testing.T) {
497497

498498
}
499499

500+
func TestParserParseGeneralAPIInfoGlobalSecurityV3(t *testing.T) {
501+
t.Parallel()
502+
503+
// Test simple global security
504+
parser := New(GenerateOpenAPI3Doc(true))
505+
err := parser.parseGeneralAPIInfoV3([]string{
506+
"@security ApiKeyAuth",
507+
})
508+
assert.NoError(t, err)
509+
assert.Len(t, parser.openAPI.Security, 1)
510+
assert.Contains(t, parser.openAPI.Security[0], "ApiKeyAuth")
511+
assert.Equal(t, []string{}, parser.openAPI.Security[0]["ApiKeyAuth"])
512+
513+
// Test OAuth2 with scopes
514+
parser2 := New(GenerateOpenAPI3Doc(true))
515+
err2 := parser2.parseGeneralAPIInfoV3([]string{
516+
"@security OAuth2Implicit[read,write]",
517+
})
518+
assert.NoError(t, err2)
519+
assert.Len(t, parser2.openAPI.Security, 1)
520+
assert.Contains(t, parser2.openAPI.Security[0], "OAuth2Implicit")
521+
assert.Equal(t, []string{"read", "write"}, parser2.openAPI.Security[0]["OAuth2Implicit"])
522+
523+
// Test OR logic
524+
parser3 := New(GenerateOpenAPI3Doc(true))
525+
err3 := parser3.parseGeneralAPIInfoV3([]string{
526+
"@security ApiKeyAuth || BasicAuth",
527+
})
528+
assert.NoError(t, err3)
529+
assert.Len(t, parser3.openAPI.Security, 1)
530+
assert.Contains(t, parser3.openAPI.Security[0], "ApiKeyAuth")
531+
assert.Contains(t, parser3.openAPI.Security[0], "BasicAuth")
532+
assert.Equal(t, []string{}, parser3.openAPI.Security[0]["ApiKeyAuth"])
533+
assert.Equal(t, []string{}, parser3.openAPI.Security[0]["BasicAuth"])
534+
535+
// Test AND logic (multiple @security lines)
536+
parser4 := New(GenerateOpenAPI3Doc(true))
537+
err4 := parser4.parseGeneralAPIInfoV3([]string{
538+
"@security ApiKeyAuth",
539+
"@security BasicAuth",
540+
})
541+
assert.NoError(t, err4)
542+
assert.Len(t, parser4.openAPI.Security, 2)
543+
assert.Contains(t, parser4.openAPI.Security[0], "ApiKeyAuth")
544+
assert.Contains(t, parser4.openAPI.Security[1], "BasicAuth")
545+
}
546+
500547
func TestParseTypeAlias(t *testing.T) {
501548
t.Parallel()
502549

0 commit comments

Comments
 (0)