• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

pace / bricks / 12827718001

17 Jan 2025 10:57AM UTC coverage: 56.909% (-0.3%) from 57.237%
12827718001

Pull #384

github

monstermunchkin
Satisfy linters
Pull Request #384: Extend linting

478 of 946 new or added lines in 109 files covered. (50.53%)

133 existing lines in 53 files now uncovered.

5667 of 9958 relevant lines covered (56.91%)

21.51 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.16
/http/jsonapi/generator/generate_security.go
1
// Copyright © 2019 by PACE Telematics GmbH. All rights reserved.
2

3
package generator
4

5
import (
6
        "encoding/json"
7
        "sort"
8

9
        "github.com/dave/jennifer/jen"
10
        "github.com/getkin/kin-openapi/openapi3"
11
        "golang.org/x/text/cases"
12
        "golang.org/x/text/language"
13

14
        "github.com/pace/bricks/maintenance/errors"
15
)
16

17
const (
18
        authBackendInterface  = "AuthorizationBackend"
19
        authFuncPrefix        = "Authorize"
20
        authCanAuthFuncPrefix = "CanAuthorize"
21
)
22

23
// buildSecurityBackendInterface builds the interface that is used to do the authentication.
24
// It creates one method for each security type and an init method for handling the securityConfigs.
25
// The Methods are named AuthenticateNAME and Init.
26
func (g *Generator) buildSecurityBackendInterface(schema *openapi3.Swagger) error {
5✔
27
        if !hasSecuritySchema(schema) {
7✔
28
                return nil
2✔
29
        }
2✔
30

31
        securitySchemes := schema.Components.SecuritySchemes
3✔
32
        // r contains the methods for the security interface
3✔
33
        r := &jen.Group{}
3✔
34

3✔
35
        // Because the order of the values while iterating over a map is randomized the generated result can only be tested if the keys are sorted
3✔
36
        keys := make([]string, len(securitySchemes))
3✔
37
        i := 0
3✔
38

3✔
39
        for k := range securitySchemes {
11✔
40
                keys[i] = k
8✔
41

8✔
42
                i++
8✔
43
        }
8✔
44

45
        sort.Stable(sort.StringSlice(keys))
3✔
46

3✔
47
        hasDuplicatedSecuritySchema := false
3✔
48

3✔
49
        for _, pathItem := range schema.Paths {
37✔
50
                for _, op := range pathItem.Operations() {
79✔
51
                        if op.Security != nil {
83✔
52
                                hasDuplicatedSecuritySchema = hasDuplicatedSecuritySchema || len((*op.Security)[0]) > 1
38✔
53
                        }
38✔
54
                }
55
        }
56

57
        caser := cases.Title(language.Und, cases.NoLower)
3✔
58

3✔
59
        for _, name := range keys {
11✔
60
                value := securitySchemes[name]
8✔
61

8✔
62
                r.Line().Id(authFuncPrefix + caser.String(name))
8✔
63

8✔
64
                switch value.Value.Type {
8✔
65
                case "oauth2":
3✔
66
                        r.Params(jen.Id("r").Id("*http.Request"), jen.Id("w").Id("http.ResponseWriter"), jen.Id("scope").String()).Params(jen.Id("context.Context"), jen.Id("bool"))
3✔
67
                        r.Line().Id("Init" + caser.String(name)).Params(jen.Id("cfg"+caser.String(name)).Op("*").Qual(pkgOAuth2, "Config"))
3✔
68
                case "openIdConnect":
2✔
69
                        r.Params(jen.Id("r").Id("*http.Request"), jen.Id("w").Id("http.ResponseWriter"), jen.Id("scope").String()).Params(jen.Id("context.Context"), jen.Id("bool"))
2✔
70
                        r.Line().Id("Init" + caser.String(name)).Params(jen.Id("cfg"+caser.String(name)).Op("*").Qual(pkgOIDC, "Config"))
2✔
71
                case "apiKey":
3✔
72
                        r.Params(jen.Id("r").Id("*http.Request"), jen.Id("w").Id("http.ResponseWriter")).Params(jen.Id("context.Context"), jen.Id("bool"))
3✔
73
                        r.Line().Id("Init" + caser.String(name)).Params(jen.Id("cfg"+caser.String(name)).Op("*").Qual(pkgAPIKey, "Config"))
3✔
74
                default:
×
75
                        return errors.New("security schema type not supported: " + value.Value.Type)
×
76
                }
77

78
                if hasDuplicatedSecuritySchema {
13✔
79
                        r.Line().Id(authCanAuthFuncPrefix + caser.String(name)).Params(jen.Id("r").Id("*http.Request")).Id("bool")
5✔
80
                }
5✔
81
        }
82

83
        g.goSource.Type().Id(authBackendInterface).Interface(r)
3✔
84

3✔
85
        return nil
3✔
86
}
87

88
// BuildSecurityConfigs creates structs with the config of each security schema.
89
func (g *Generator) buildSecurityConfigs(schema *openapi3.Swagger) error {
5✔
90
        if !hasSecuritySchema(schema) {
7✔
91
                return nil
2✔
92
        }
2✔
93

94
        securitySchemes := schema.Components.SecuritySchemes
3✔
95
        // Because the order of the values while iterating over a map is randomized the generated result can only be tested if the keys are sorted
3✔
96
        keys := make([]string, len(securitySchemes))
3✔
97
        i := 0
3✔
98

3✔
99
        for k := range securitySchemes {
11✔
100
                keys[i] = k
8✔
101

8✔
102
                i++
8✔
103
        }
8✔
104

105
        sort.Stable(sort.StringSlice(keys))
3✔
106

3✔
107
        for _, name := range keys {
11✔
108
                value := securitySchemes[name]
8✔
109
                instanceVal := jen.Dict{}
8✔
110

8✔
111
                var pkgName string
8✔
112

8✔
113
                switch value.Value.Type {
8✔
114
                case "oauth2":
3✔
115
                        pkgName = pkgOAuth2
3✔
116
                        t := value.Value.Description
3✔
117
                        instanceVal[jen.Id("Description")] = jen.Lit(t)
3✔
118
                        // If any flow is present create the flow struct
3✔
119
                        if value.Value.Flows != nil {
6✔
120
                                flows := map[string]*openapi3.OAuthFlow{
3✔
121
                                        "AuthorizationCode": value.Value.Flows.AuthorizationCode,
3✔
122
                                        "ClientCredentials": value.Value.Flows.ClientCredentials,
3✔
123
                                        "Implicit":          value.Value.Flows.Implicit,
3✔
124
                                        "Password":          value.Value.Flows.Password,
3✔
125
                                }
3✔
126
                                for flowname, flow := range flows {
15✔
127
                                        if flow != nil {
15✔
128
                                                instanceVal[jen.Id(flowname)] = jen.Op("&").Qual(pkgOAuth2, "Flow").Values(getValuesFromFlow(flow))
3✔
129
                                        }
3✔
130
                                }
131
                        }
132
                case "openIdConnect":
2✔
133
                        pkgName = pkgOIDC
2✔
134
                        instanceVal[jen.Id("Description")] = jen.Lit(value.Value.Description)
2✔
135

2✔
136
                        if e, ok := value.Value.Extensions["openIdConnectUrl"]; ok {
4✔
137
                                var url string
2✔
138
                                if data, ok := e.(json.RawMessage); ok {
4✔
139
                                        if err := json.Unmarshal(data, &url); err != nil {
2✔
UNCOV
140
                                                return err
×
141
                                        }
×
142

143
                                        instanceVal[jen.Id("OpenIDConnectURL")] = jen.Lit(url)
2✔
144
                                }
145
                        }
146
                case "apiKey":
3✔
147
                        pkgName = pkgAPIKey
3✔
148
                        instanceVal[jen.Id("Description")] = jen.Lit(value.Value.Description)
3✔
149
                        instanceVal[jen.Id("In")] = jen.Lit(value.Value.In)
3✔
150
                        instanceVal[jen.Id("Name")] = jen.Lit(value.Value.Name)
3✔
151
                default:
×
152
                        return errors.New("security schema type not supported: " + value.Value.Type)
×
153
                }
154

155
                caser := cases.Title(language.Und, cases.NoLower)
8✔
156
                g.goSource.Var().Id("cfg"+caser.String(name)).Op("=").Op("&").Qual(pkgName, "Config").Values(instanceVal)
8✔
157
        }
158

159
        return nil
3✔
160
}
161

162
// getValuesFromFlow puts the values from the OAuth Flow in a jen.Dict to generate it.
163
func getValuesFromFlow(flow *openapi3.OAuthFlow) jen.Dict {
3✔
164
        r := jen.Dict{}
3✔
165
        r[jen.Id("AuthorizationURL")] = jen.Lit(flow.AuthorizationURL)
3✔
166
        r[jen.Id("TokenURL")] = jen.Lit(flow.TokenURL)
3✔
167
        r[jen.Id("RefreshURL")] = jen.Lit(flow.RefreshURL)
3✔
168

3✔
169
        scopes := jen.Dict{}
3✔
170
        for scope, descr := range flow.Scopes {
26✔
171
                scopes[jen.Lit(scope)] = jen.Lit(descr)
23✔
172
        }
23✔
173

174
        r[jen.Id("Scopes")] = jen.Map(jen.String()).String().Values(scopes)
3✔
175

3✔
176
        return r
3✔
177
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc