@@ -16,15 +16,16 @@ const (
1616)
1717
1818type securityTag struct {
19- Option bool
20- Scheme bool
21- Name string
22- Type string
23- SubType string
24- Env string
19+ Option bool
20+ Scheme bool
21+ Composite bool
22+ Name string
23+ Type string
24+ SubType string
25+ Env string
2526}
2627
27- func PopulateSecurity (ctx context.Context , req * http.Request , securitySource func (context.Context ) (interface {}, error )) error {
28+ func PopulateSecurity (ctx context.Context , req * http.Request , securitySource func (context.Context ) (interface {}, error ), allowedFields ... string ) error {
2829 if securitySource == nil {
2930 return nil
3031 }
@@ -49,34 +50,7 @@ func PopulateSecurity(ctx context.Context, req *http.Request, securitySource fun
4950 securityValType = securityValType .Elem ()
5051 }
5152
52- for i := 0 ; i < securityStructType .NumField (); i ++ {
53- fieldType := securityStructType .Field (i )
54- valType := securityValType .Field (i )
55-
56- kind := valType .Kind ()
57-
58- if isNil (fieldType .Type , valType ) {
59- continue
60- }
61-
62- if fieldType .Type .Kind () == reflect .Pointer {
63- kind = valType .Elem ().Kind ()
64- }
65-
66- secTag := parseSecurityTag (fieldType )
67- if secTag != nil {
68- if secTag .Option {
69- handleSecurityOption (headers , queryParams , valType .Interface ())
70- } else if secTag .Scheme {
71- // Special case for basic auth which could be a flattened struct
72- if secTag .SubType == "basic" && kind != reflect .Struct {
73- parseSecurityScheme (headers , queryParams , secTag , security )
74- } else {
75- parseSecurityScheme (headers , queryParams , secTag , valType .Interface ())
76- }
77- }
78- }
79- }
53+ populateSecurityFields (headers , queryParams , securityStructType , securityValType , security , allowedFields )
8054
8155 for key , value := range headers {
8256 req .Header .Add (key , value )
@@ -91,6 +65,61 @@ func PopulateSecurity(ctx context.Context, req *http.Request, securitySource fun
9165 return nil
9266}
9367
68+ func populateSecurityFields (headers , queryParams map [string ]string , securityStructType reflect.Type , securityValType reflect.Value , security interface {}, allowedFields []string ) {
69+ type fieldPair struct {
70+ fieldType reflect.StructField
71+ valType reflect.Value
72+ }
73+
74+ var fields []fieldPair
75+ if len (allowedFields ) > 0 {
76+ for _ , name := range allowedFields {
77+ ft , ok := securityStructType .FieldByName (name )
78+ if ! ok {
79+ continue
80+ }
81+ fields = append (fields , fieldPair {ft , securityValType .FieldByName (name )})
82+ }
83+ } else {
84+ for i := 0 ; i < securityStructType .NumField (); i ++ {
85+ fields = append (fields , fieldPair {securityStructType .Field (i ), securityValType .Field (i )})
86+ }
87+ }
88+
89+ for _ , f := range fields {
90+ kind := f .valType .Kind ()
91+
92+ if isNil (f .fieldType .Type , f .valType ) {
93+ continue
94+ }
95+
96+ if f .fieldType .Type .Kind () == reflect .Pointer {
97+ kind = f .valType .Elem ().Kind ()
98+ }
99+
100+ secTag := parseSecurityTag (f .fieldType )
101+ if secTag == nil {
102+ continue
103+ }
104+
105+ if secTag .Option {
106+ handleSecurityOption (headers , queryParams , f .valType .Interface ())
107+ return
108+ } else if secTag .Scheme {
109+ // Special case for basic auth which could be a flattened struct
110+ if secTag .SubType == "basic" && kind != reflect .Struct {
111+ parseSecurityScheme (headers , queryParams , secTag , security )
112+ } else {
113+ parseSecurityScheme (headers , queryParams , secTag , f .valType .Interface ())
114+ }
115+
116+ if ! secTag .Composite {
117+ return
118+ }
119+ }
120+ }
121+ }
122+
94123func PopulateSecurityFromEnv (security interface {}) bool {
95124 securityValType := trueReflectValue (reflect .ValueOf (security ))
96125 securityStructType := securityValType .Type ()
@@ -194,9 +223,16 @@ func handleSecurityOption(headers, queryParams map[string]string, option interfa
194223 valType := optionValType .Field (i )
195224
196225 secTag := parseSecurityTag (fieldType )
197- if secTag != nil && secTag .Scheme {
198- parseSecurityScheme (headers , queryParams , secTag , valType .Interface ())
226+ if secTag == nil || ! secTag .Scheme {
227+ continue
228+ }
229+
230+ if secTag .Type == "http" && secTag .SubType == "basic" && valType .Kind () != reflect .Struct {
231+ handleBasicAuthScheme (headers , optionValType .Interface ())
232+ return
199233 }
234+
235+ parseSecurityScheme (headers , queryParams , secTag , valType .Interface ())
200236 }
201237}
202238
@@ -323,6 +359,7 @@ func parseSecurityTag(field reflect.StructField) *securityTag {
323359
324360 option := false
325361 scheme := false
362+ composite := false
326363 name := ""
327364 securityType := ""
328365 securitySubType := ""
@@ -346,20 +383,21 @@ func parseSecurityTag(field reflect.StructField) *securityTag {
346383 option = true
347384 case "scheme" :
348385 scheme = true
386+ case "composite" :
387+ composite = true
349388 case "env" :
350389 env = parts [1 ]
351390 }
352391 }
353392
354- // TODO: validate tag?
355-
356393 return & securityTag {
357- Option : option ,
358- Scheme : scheme ,
359- Name : name ,
360- Type : securityType ,
361- SubType : securitySubType ,
362- Env : env ,
394+ Option : option ,
395+ Scheme : scheme ,
396+ Composite : composite ,
397+ Name : name ,
398+ Type : securityType ,
399+ SubType : securitySubType ,
400+ Env : env ,
363401 }
364402}
365403
0 commit comments