Skip to content

Commit

Permalink
Forbid unknown parameters if parent has additionalProperties: false (#33
Browse files Browse the repository at this point in the history
)
  • Loading branch information
vearutop authored Apr 14, 2022
1 parent 8c92e1d commit d01f6e1
Show file tree
Hide file tree
Showing 11 changed files with 119 additions and 24 deletions.
6 changes: 6 additions & 0 deletions .github/workflows/cloc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
name: cloc
on:
pull_request:

# Cancel the workflow in progress in newer build is about to start.
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true

jobs:
cloc:
runs-on: ubuntu-latest
Expand Down
13 changes: 11 additions & 2 deletions .github/workflows/golangci-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,26 @@ on:
- master
- main
pull_request:

# Cancel the workflow in progress in newer build is about to start.
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true

jobs:
golangci:
name: golangci-lint
runs-on: ubuntu-latest
steps:
- uses: actions/setup-go@v3
with:
go-version: 1.18.x
- uses: actions/checkout@v2
- name: golangci-lint
uses: golangci/golangci-lint-action@v2.5.2
uses: golangci/golangci-lint-action@v3.1.0
with:
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
version: v1.43.0
version: v1.45.2

# Optional: working directory, useful for monorepos
# working-directory: somedir
Expand Down
10 changes: 8 additions & 2 deletions .github/workflows/gorelease.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,21 @@
name: gorelease
on:
pull_request:

# Cancel the workflow in progress in newer build is about to start.
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true

env:
GO_VERSION: 1.17.x
GO_VERSION: 1.18.x
jobs:
gorelease:
runs-on: ubuntu-latest
steps:
- name: Install Go stable
if: env.GO_VERSION != 'tip'
uses: actions/setup-go@v2
uses: actions/setup-go@v3
with:
go-version: ${{ env.GO_VERSION }}
- name: Install Go tip
Expand Down
12 changes: 9 additions & 3 deletions .github/workflows/test-unit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,26 @@ on:
- master
- main
pull_request:

# Cancel the workflow in progress in newer build is about to start.
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true

env:
GO111MODULE: "on"
RUN_BASE_COVERAGE: "on" # Runs test for PR base in case base test coverage is missing.
COV_GO_VERSION: 1.17.x # Version of Go to collect coverage
COV_GO_VERSION: 1.18.x # Version of Go to collect coverage
jobs:
test:
strategy:
matrix:
go-version: [ 1.13.x, 1.14.x, 1.15.x, 1.16.x, 1.17.x, tip ]
go-version: [ 1.13.x, 1.14.x, 1.15.x, 1.16.x, 1.17.x, 1.18.x, tip ]
runs-on: ubuntu-latest
steps:
- name: Install Go stable
if: matrix.go-version != 'tip'
uses: actions/setup-go@v2
uses: actions/setup-go@v3
with:
go-version: ${{ matrix.go-version }}
- name: Install Go tip
Expand Down
3 changes: 3 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,7 @@ issues:
- linters:
- errcheck
path: "example_"
- linters:
- staticcheck
text: "SA1019: strings.Title is deprecated"

2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#GOLANGCI_LINT_VERSION := "v1.43.0" # Optional configuration to pinpoint golangci-lint version.
#GOLANGCI_LINT_VERSION := "v1.45.2" # Optional configuration to pinpoint golangci-lint version.

# The head of Makefile determines location of dev-go to include standard targets.
GO ?= go
Expand Down
8 changes: 4 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ module github.com/swaggest/openapi-go
go 1.17

require (
github.com/bool64/dev v0.2.5
github.com/stretchr/testify v1.7.0
github.com/bool64/dev v0.2.10
github.com/stretchr/testify v1.7.1
github.com/swaggest/assertjson v1.6.8
github.com/swaggest/jsonschema-go v0.3.24
github.com/swaggest/refl v1.0.1
github.com/swaggest/jsonschema-go v0.3.32
github.com/swaggest/refl v1.0.2
gopkg.in/yaml.v2 v2.4.0
)

Expand Down
19 changes: 8 additions & 11 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
github.com/bool64/dev v0.1.17/go.mod h1:cTHiTDNc8EewrQPy3p1obNilpMpdmlUesDkFTF2zRWU=
github.com/bool64/dev v0.1.25/go.mod h1:cTHiTDNc8EewrQPy3p1obNilpMpdmlUesDkFTF2zRWU=
github.com/bool64/dev v0.1.41/go.mod h1:cTHiTDNc8EewrQPy3p1obNilpMpdmlUesDkFTF2zRWU=
github.com/bool64/dev v0.1.42/go.mod h1:cTHiTDNc8EewrQPy3p1obNilpMpdmlUesDkFTF2zRWU=
github.com/bool64/dev v0.2.5 h1:H0bylghwcjDBBhEwSFTjArEO9Dr8cCaB54QSOF7esOA=
github.com/bool64/dev v0.2.5/go.mod h1:cTHiTDNc8EewrQPy3p1obNilpMpdmlUesDkFTF2zRWU=
github.com/bool64/dev v0.2.10 h1:ypAGBazcwyIy2JvIJio8V3kdqO7AgIAYvcckW54qxr4=
github.com/bool64/dev v0.2.10/go.mod h1:/csLrm+4oDSsKJRIVS0mrywAonLnYKFG8RvGT7Jh9b8=
github.com/bool64/shared v0.1.3 h1:gj7XZPYa1flQsCg3q9AIju+W2A1jaexK0fdFu2XtaG0=
github.com/bool64/shared v0.1.3/go.mod h1:RF1p1Oi29ofgOvinBpetbF5mceOUP3kpMkvLbWOmtm0=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
Expand Down Expand Up @@ -54,15 +52,14 @@ github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/swaggest/assertjson v1.6.8 h1:1O/9UI5M+2OJI7BeEWKGj0wTvpRXZt5FkOJ4nRkY4rA=
github.com/swaggest/assertjson v1.6.8/go.mod h1:Euf0upn9Vlaf1/llYHTs+Kx5K3vVbpMbsZhth7zlN7M=
github.com/swaggest/jsonschema-go v0.3.24 h1:vVtFhWQWT9sgsvgMdh0n3O1F0+TnhOWz4+lbz5p5ChY=
github.com/swaggest/jsonschema-go v0.3.24/go.mod h1:B2ZSqrrlkj21zhywlkh8VnKBmuqUwDv3dLQoPjgHk7M=
github.com/swaggest/refl v1.0.0/go.mod h1:acYd5x8NNxivp+ZHdRZKJYz66n/qjo3Q9Sa/jAivljQ=
github.com/swaggest/refl v1.0.1 h1:YQHb7Ic6EMpdUpxQmTWmf/O4IWN6iIErxJNWA7LwyyM=
github.com/swaggest/refl v1.0.1/go.mod h1:dnx+n9YaI0o+FH+OR2tJZWLABBVIPs9qc4VY9UdrhLE=
github.com/swaggest/jsonschema-go v0.3.32 h1:C8XiNEoR1L0QwBAWTvRyY0xYdEmEeJYthImF9GzSST0=
github.com/swaggest/jsonschema-go v0.3.32/go.mod h1:JAF1nm+uIaMOXktuQepmkiRcgQ5yJk4Ccwx9HVt2cXw=
github.com/swaggest/refl v1.0.2 h1:VmP8smuDS1EzUPn31++TzMi13CAaVJdlWpIxzj0up88=
github.com/swaggest/refl v1.0.2/go.mod h1:DoiPoBJPYHU6Z9fIA6zXQ9uI6VRL6M8BFX5YFT+ym9g=
github.com/yosuke-furukawa/json5 v0.1.2-0.20201207051438-cf7bb3f354ff/go.mod h1:sw49aWDqNdRJ6DYUtIQiaA3xyj2IL9tjeNYmX2ixwcU=
github.com/yudai/gojsondiff v1.0.0 h1:27cbfqXLVEJ1o8I6v3y9lg8Ydm53EKqHXAOMxEGlCOA=
github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg=
Expand Down
7 changes: 7 additions & 0 deletions openapi3/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,3 +126,10 @@ func (s *Spec) AddOperation(method, path string, operation Operation) error {
return nil
})
}

// UnknownParamIsForbidden indicates forbidden unknown parameters.
func (o Operation) UnknownParamIsForbidden(in ParameterIn) bool {
f, ok := o.MapOfAnything[xForbidUnknown+string(in)].(bool)

return f && ok
}
17 changes: 16 additions & 1 deletion openapi3/reflect.go
Original file line number Diff line number Diff line change
Expand Up @@ -210,18 +210,27 @@ func (r *Reflector) parseRequestBody(
return nil
}

const (
// xForbidUnknown is a prefix of a vendor extension to indicate forbidden unknown parameters.
// It should be used together with ParameterIn as a suffix.
xForbidUnknown = "x-forbid-unknown-"
)

func (r *Reflector) parseParametersIn(
o *Operation, input interface{}, in ParameterIn, propertyMapping map[string]string,
) error {
if refl.IsSliceOrMap(input) {
return nil
}

_, err := r.Reflect(input,
s, err := r.Reflect(input,
jsonschema.DefinitionsPrefix("#/components/schemas/"),
jsonschema.CollectDefinitions(r.collectDefinition),
jsonschema.PropertyNameMapping(propertyMapping),
jsonschema.PropertyNameTag(string(in)),
func(rc *jsonschema.ReflectContext) {
rc.UnnamedFieldWithTag = true
},
jsonschema.SkipEmbeddedMapsSlices,
jsonschema.InterceptProperty(func(name string, field reflect.StructField, propertySchema *jsonschema.Schema) error {
s := SchemaOrRef{}
Expand Down Expand Up @@ -310,6 +319,12 @@ func (r *Reflector) parseParametersIn(
return err
}

if s.AdditionalProperties != nil &&
s.AdditionalProperties.TypeBoolean != nil &&
!*s.AdditionalProperties.TypeBoolean {
o.WithMapOfAnythingItem(xForbidUnknown+string(in), true)
}

return nil
}

Expand Down
46 changes: 46 additions & 0 deletions openapi3/reflect_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -614,6 +614,52 @@ func TestReflector_SetupRequest_jsonQuery(t *testing.T) {
}`), r.SpecEns())
}

func TestReflector_SetupRequest_forbidParams(t *testing.T) {
type req struct {
Query string `query:"query"`
Header string `header:"header"`
Cookie string `cookie:"cookie"`
Path string `path:"path"`

_ struct{} `query:"_" cookie:"_" additionalProperties:"false"`
}

r := openapi3.Reflector{}
oc := openapi3.OperationContext{
Operation: &openapi3.Operation{},
Input: new(req),
}

require.NoError(t, r.SetupRequest(oc))
require.NoError(t, r.SpecEns().AddOperation(http.MethodGet, "/{path}", *oc.Operation))

assertjson.EqualMarshal(t, []byte(`{
"openapi":"3.0.3","info":{"title":"","version":""},
"paths":{
"/{path}":{
"get":{
"parameters":[
{"name":"query","in":"query","schema":{"type":"string"}},
{
"name":"path","in":"path","required":true,
"schema":{"type":"string"}
},
{"name":"cookie","in":"cookie","schema":{"type":"string"}},
{"name":"header","in":"header","schema":{"type":"string"}}
],
"responses":{"204":{"description":"No Content"}},
"x-forbid-unknown-cookie":true,"x-forbid-unknown-query":true
}
}
}
}`), r.SpecEns())

assert.True(t, oc.Operation.UnknownParamIsForbidden(openapi3.ParameterInCookie))
assert.False(t, oc.Operation.UnknownParamIsForbidden(openapi3.ParameterInHeader))
assert.True(t, oc.Operation.UnknownParamIsForbidden(openapi3.ParameterInQuery))
assert.False(t, oc.Operation.UnknownParamIsForbidden(openapi3.ParameterInPath))
}

func TestReflector_SetupRequest_noBody(t *testing.T) {
type req struct {
ID int `json:"id" path:"id"`
Expand Down

0 comments on commit d01f6e1

Please sign in to comment.