Skip to content

Commit 9d9763c

Browse files
authored
Merge pull request kubernetes#90 from fredbi/fix-gob-security
Fixed gob encoding/decoding for SwaggerProps
2 parents 53d7765 + cb961e9 commit 9d9763c

File tree

6 files changed

+202
-67
lines changed

6 files changed

+202
-67
lines changed

.golangci.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ linters-settings:
88
maligned:
99
suggest-new: true
1010
dupl:
11-
threshold: 100
11+
threshold: 200
1212
goconst:
1313
min-len: 2
1414
min-occurrences: 2

go.mod

-7
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,9 @@
11
module github.com/go-openapi/spec
22

33
require (
4-
github.com/PuerkitoBio/purell v1.1.0 // indirect
5-
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
6-
github.com/davecgh/go-spew v1.1.1 // indirect
74
github.com/go-openapi/jsonpointer v0.17.0
85
github.com/go-openapi/jsonreference v0.17.0
96
github.com/go-openapi/swag v0.17.0
10-
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329 // indirect
11-
github.com/pmezard/go-difflib v1.0.0 // indirect
127
github.com/stretchr/testify v1.2.2
13-
golang.org/x/net v0.0.0-20181005035420-146acd28ed58 // indirect
14-
golang.org/x/text v0.3.0 // indirect
158
gopkg.in/yaml.v2 v2.2.1
169
)

go.sum

+9-6
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,22 @@ github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV
44
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
55
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
66
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
7-
github.com/go-openapi/jsonpointer v0.17.0 h1:Bpl2DtZ6k7wKqfFs7e+4P08+M9I3FQgn09a1UsRUQbk=
8-
github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
9-
github.com/go-openapi/jsonreference v0.17.0 h1:d/o7/fsLWWQZACbihvZxcyLQ59jfUVs7WOJv/ak7T7A=
10-
github.com/go-openapi/jsonreference v0.17.0/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
11-
github.com/go-openapi/swag v0.17.0 h1:7wu+dZ5k83kvUWeAb+WUkFiUhDzwGqzTR/NhWzeo1JU=
12-
github.com/go-openapi/swag v0.17.0/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
7+
github.com/go-openapi/jsonpointer v0.17.0 h1:nH6xp8XdXHx8dqveo0ZuJBluCO2qGrPbDNZ0dwoRHP0=
8+
github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=
9+
github.com/go-openapi/jsonreference v0.17.0 h1:yJW3HCkTHg7NOA+gZ83IPHzUSnUzGXhGmsdiCcMexbA=
10+
github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
11+
github.com/go-openapi/swag v0.17.0 h1:iqrgMg7Q7SvtbWLlltPrkMs0UBJI6oTSs79JFRUi880=
12+
github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
1313
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329 h1:2gxZ0XQIU/5z3Z3bUBu+FXuk2pFbkN6tcwi/pjyaDic=
1414
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
15+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
1516
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
1617
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
1718
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
1819
golang.org/x/net v0.0.0-20181005035420-146acd28ed58 h1:otZG8yDCO4LVps5+9bxOeNiCvgmOyt96J3roHTYs7oE=
1920
golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
21+
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
2022
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
2123
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
24+
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
2225
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

operation_test.go

+50-51
Original file line numberDiff line numberDiff line change
@@ -286,63 +286,62 @@ func TestOperationGobEncoding(t *testing.T) {
286286

287287
// 2. nil security requirements
288288
doTestOperationGobEncoding(t, `{
289-
"description": "operation description",
290-
"x-framework": "go-swagger",
291-
"consumes": [ "application/json", "application/x-yaml" ],
292-
"produces": [ "application/json", "application/x-yaml" ],
293-
"schemes": ["http", "https"],
294-
"tags": ["dogs"],
295-
"summary": "the summary of the operation",
296-
"operationId": "sendCat",
297-
"deprecated": true,
298-
"parameters": [{"$ref":"Cat"}],
299-
"responses": {
300-
"default": {
301-
"description": "void response"
302-
}
303-
}
304-
}`)
289+
"description": "operation description",
290+
"x-framework": "go-swagger",
291+
"consumes": [ "application/json", "application/x-yaml" ],
292+
"produces": [ "application/json", "application/x-yaml" ],
293+
"schemes": ["http", "https"],
294+
"tags": ["dogs"],
295+
"summary": "the summary of the operation",
296+
"operationId": "sendCat",
297+
"deprecated": true,
298+
"parameters": [{"$ref":"Cat"}],
299+
"responses": {
300+
"default": {
301+
"description": "void response"
302+
}
303+
}
304+
}`)
305305

306306
// 3. empty security requirement
307307
doTestOperationGobEncoding(t, `{
308-
"description": "operation description",
309-
"x-framework": "go-swagger",
310-
"consumes": [ "application/json", "application/x-yaml" ],
311-
"produces": [ "application/json", "application/x-yaml" ],
312-
"schemes": ["http", "https"],
313-
"tags": ["dogs"],
314-
"security": [],
315-
"summary": "the summary of the operation",
316-
"operationId": "sendCat",
317-
"deprecated": true,
318-
"parameters": [{"$ref":"Cat"}],
319-
"responses": {
320-
"default": {
321-
"description": "void response"
322-
}
323-
}
324-
}`)
308+
"description": "operation description",
309+
"x-framework": "go-swagger",
310+
"consumes": [ "application/json", "application/x-yaml" ],
311+
"produces": [ "application/json", "application/x-yaml" ],
312+
"schemes": ["http", "https"],
313+
"tags": ["dogs"],
314+
"security": [],
315+
"summary": "the summary of the operation",
316+
"operationId": "sendCat",
317+
"deprecated": true,
318+
"parameters": [{"$ref":"Cat"}],
319+
"responses": {
320+
"default": {
321+
"description": "void response"
322+
}
323+
}
324+
}`)
325325

326326
// 4. non-empty security requirements
327327
doTestOperationGobEncoding(t, `{
328-
"description": "operation description",
329-
"x-framework": "go-swagger",
330-
"consumes": [ "application/json", "application/x-yaml" ],
331-
"produces": [ "application/json", "application/x-yaml" ],
332-
"schemes": ["http", "https"],
333-
"tags": ["dogs"],
334-
"summary": "the summary of the operation",
335-
"security": [ { "scoped-auth": [ "phone", "email" ] , "api-key": []} ],
336-
"operationId": "sendCat",
337-
"deprecated": true,
338-
"parameters": [{"$ref":"Cat"}],
339-
"responses": {
340-
"default": {
341-
"description": "void response"
342-
}
343-
}
344-
}`)
345-
328+
"description": "operation description",
329+
"x-framework": "go-swagger",
330+
"consumes": [ "application/json", "application/x-yaml" ],
331+
"produces": [ "application/json", "application/x-yaml" ],
332+
"schemes": ["http", "https"],
333+
"tags": ["dogs"],
334+
"summary": "the summary of the operation",
335+
"security": [ { "scoped-auth": [ "phone", "email" ] , "api-key": []} ],
336+
"operationId": "sendCat",
337+
"deprecated": true,
338+
"parameters": [{"$ref":"Cat"}],
339+
"responses": {
340+
"default": {
341+
"description": "void response"
342+
}
343+
}
344+
}`)
346345
}
347346

348347
func doTestOperationGobEncoding(t *testing.T, fixture string) {

swagger.go

+124
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
package spec
1616

1717
import (
18+
"bytes"
19+
"encoding/gob"
1820
"encoding/json"
1921
"fmt"
2022
"strconv"
@@ -68,6 +70,36 @@ func (s *Swagger) UnmarshalJSON(data []byte) error {
6870
return nil
6971
}
7072

73+
// GobEncode provides a safe gob encoder for Swagger, including extensions
74+
func (s Swagger) GobEncode() ([]byte, error) {
75+
var b bytes.Buffer
76+
raw := struct {
77+
Props SwaggerProps
78+
Ext VendorExtensible
79+
}{
80+
Props: s.SwaggerProps,
81+
Ext: s.VendorExtensible,
82+
}
83+
err := gob.NewEncoder(&b).Encode(raw)
84+
return b.Bytes(), err
85+
}
86+
87+
// GobDecode provides a safe gob decoder for Swagger, including extensions
88+
func (s *Swagger) GobDecode(b []byte) error {
89+
var raw struct {
90+
Props SwaggerProps
91+
Ext VendorExtensible
92+
}
93+
buf := bytes.NewBuffer(b)
94+
err := gob.NewDecoder(buf).Decode(&raw)
95+
if err != nil {
96+
return err
97+
}
98+
s.SwaggerProps = raw.Props
99+
s.VendorExtensible = raw.Ext
100+
return nil
101+
}
102+
71103
// SwaggerProps captures the top-level properties of an Api specification
72104
//
73105
// NOTE: validation rules
@@ -93,6 +125,98 @@ type SwaggerProps struct {
93125
ExternalDocs *ExternalDocumentation `json:"externalDocs,omitempty"`
94126
}
95127

128+
type swaggerPropsAlias SwaggerProps
129+
130+
type gobSwaggerPropsAlias struct {
131+
Security []map[string]struct {
132+
List []string
133+
Pad bool
134+
}
135+
Alias *swaggerPropsAlias
136+
SecurityIsEmpty bool
137+
}
138+
139+
// GobEncode provides a safe gob encoder for SwaggerProps, including empty security requirements
140+
func (o SwaggerProps) GobEncode() ([]byte, error) {
141+
raw := gobSwaggerPropsAlias{
142+
Alias: (*swaggerPropsAlias)(&o),
143+
}
144+
145+
var b bytes.Buffer
146+
if o.Security == nil {
147+
// nil security requirement
148+
err := gob.NewEncoder(&b).Encode(raw)
149+
return b.Bytes(), err
150+
}
151+
152+
if len(o.Security) == 0 {
153+
// empty, but non-nil security requirement
154+
raw.SecurityIsEmpty = true
155+
raw.Alias.Security = nil
156+
err := gob.NewEncoder(&b).Encode(raw)
157+
return b.Bytes(), err
158+
}
159+
160+
raw.Security = make([]map[string]struct {
161+
List []string
162+
Pad bool
163+
}, 0, len(o.Security))
164+
for _, req := range o.Security {
165+
v := make(map[string]struct {
166+
List []string
167+
Pad bool
168+
}, len(req))
169+
for k, val := range req {
170+
v[k] = struct {
171+
List []string
172+
Pad bool
173+
}{
174+
List: val,
175+
}
176+
}
177+
raw.Security = append(raw.Security, v)
178+
}
179+
180+
err := gob.NewEncoder(&b).Encode(raw)
181+
return b.Bytes(), err
182+
}
183+
184+
// GobDecode provides a safe gob decoder for SwaggerProps, including empty security requirements
185+
func (o *SwaggerProps) GobDecode(b []byte) error {
186+
var raw gobSwaggerPropsAlias
187+
188+
buf := bytes.NewBuffer(b)
189+
err := gob.NewDecoder(buf).Decode(&raw)
190+
if err != nil {
191+
return err
192+
}
193+
if raw.Alias == nil {
194+
return nil
195+
}
196+
197+
switch {
198+
case raw.SecurityIsEmpty:
199+
// empty, but non-nil security requirement
200+
raw.Alias.Security = []map[string][]string{}
201+
case len(raw.Alias.Security) == 0:
202+
// nil security requirement
203+
raw.Alias.Security = nil
204+
default:
205+
raw.Alias.Security = make([]map[string][]string, 0, len(raw.Security))
206+
for _, req := range raw.Security {
207+
v := make(map[string][]string, len(req))
208+
for k, val := range req {
209+
v[k] = make([]string, 0, len(val.List))
210+
v[k] = append(v[k], val.List...)
211+
}
212+
raw.Alias.Security = append(raw.Alias.Security, v)
213+
}
214+
}
215+
216+
*o = *(*SwaggerProps)(raw.Alias)
217+
return nil
218+
}
219+
96220
// Dependencies represent a dependencies property
97221
type Dependencies map[string]SchemaOrStringArray
98222

swagger_test.go

+18-2
Original file line numberDiff line numberDiff line change
@@ -329,8 +329,7 @@ func TestOptionalSwaggerProps_Serialize(t *testing.T) {
329329
}
330330
}
331331

332-
func TestSecurityRequirements(t *testing.T) {
333-
minimalJSONSpec := []byte(`{
332+
var minimalJSONSpec = []byte(`{
334333
"swagger": "2.0",
335334
"info": {
336335
"version": "0.0.0",
@@ -375,6 +374,7 @@ func TestSecurityRequirements(t *testing.T) {
375374
}
376375
}`)
377376

377+
func TestSecurityRequirements(t *testing.T) {
378378
var minimalSpec Swagger
379379
err := json.Unmarshal(minimalJSONSpec, &minimalSpec)
380380
if assert.NoError(t, err) {
@@ -387,3 +387,19 @@ func TestSecurityRequirements(t *testing.T) {
387387
assert.Contains(t, sec[2], "queryKey")
388388
}
389389
}
390+
391+
func TestSwaggerGobEncoding(t *testing.T) {
392+
doTestSwaggerGobEncoding(t, specJSON)
393+
394+
doTestSwaggerGobEncoding(t, string(minimalJSONSpec))
395+
}
396+
397+
func doTestSwaggerGobEncoding(t *testing.T, fixture string) {
398+
var src, dst Swagger
399+
400+
if !assert.NoError(t, json.Unmarshal([]byte(fixture), &src)) {
401+
t.FailNow()
402+
}
403+
404+
doTestAnyGobEncoding(t, &src, &dst)
405+
}

0 commit comments

Comments
 (0)