mirror of
https://github.com/LukeHagar/plexgo.git
synced 2025-12-06 04:20:46 +00:00
286 lines
6.4 KiB
Go
286 lines
6.4 KiB
Go
// Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.
|
|
|
|
package utils
|
|
|
|
import (
|
|
"context"
|
|
"encoding/base64"
|
|
"fmt"
|
|
"net/http"
|
|
"reflect"
|
|
"strings"
|
|
)
|
|
|
|
const (
|
|
securityTagKey = "security"
|
|
)
|
|
|
|
type securityTag struct {
|
|
Option bool
|
|
Scheme bool
|
|
Name string
|
|
Type string
|
|
SubType string
|
|
Env string
|
|
}
|
|
|
|
func PopulateSecurity(ctx context.Context, req *http.Request, securitySource func(context.Context) (interface{}, error)) error {
|
|
if securitySource == nil {
|
|
return nil
|
|
}
|
|
|
|
security, err := securitySource(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
headers := make(map[string]string)
|
|
queryParams := make(map[string]string)
|
|
|
|
securityValType := trueReflectValue(reflect.ValueOf(security))
|
|
securityStructType := securityValType.Type()
|
|
|
|
if isNil(securityStructType, securityValType) {
|
|
return nil
|
|
}
|
|
|
|
if securityStructType.Kind() == reflect.Ptr {
|
|
securityStructType = securityStructType.Elem()
|
|
securityValType = securityValType.Elem()
|
|
}
|
|
|
|
for i := 0; i < securityStructType.NumField(); i++ {
|
|
fieldType := securityStructType.Field(i)
|
|
valType := securityValType.Field(i)
|
|
|
|
kind := valType.Kind()
|
|
|
|
if isNil(fieldType.Type, valType) {
|
|
continue
|
|
}
|
|
|
|
if fieldType.Type.Kind() == reflect.Pointer {
|
|
kind = valType.Elem().Kind()
|
|
}
|
|
|
|
secTag := parseSecurityTag(fieldType)
|
|
if secTag != nil {
|
|
if secTag.Option {
|
|
handleSecurityOption(headers, queryParams, valType.Interface())
|
|
} else if secTag.Scheme {
|
|
// Special case for basic auth which could be a flattened struct
|
|
if secTag.SubType == "basic" && kind != reflect.Struct {
|
|
parseSecurityScheme(headers, queryParams, secTag, security)
|
|
} else {
|
|
parseSecurityScheme(headers, queryParams, secTag, valType.Interface())
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for key, value := range headers {
|
|
req.Header.Add(key, value)
|
|
}
|
|
|
|
query := req.URL.Query()
|
|
for key, value := range queryParams {
|
|
query.Add(key, value)
|
|
}
|
|
req.URL.RawQuery = query.Encode()
|
|
|
|
return nil
|
|
}
|
|
|
|
func handleSecurityOption(headers, queryParams map[string]string, option interface{}) {
|
|
optionValType := trueReflectValue(reflect.ValueOf(option))
|
|
optionStructType := optionValType.Type()
|
|
|
|
if isNil(optionStructType, optionValType) {
|
|
return
|
|
}
|
|
|
|
for i := 0; i < optionStructType.NumField(); i++ {
|
|
fieldType := optionStructType.Field(i)
|
|
valType := optionValType.Field(i)
|
|
|
|
secTag := parseSecurityTag(fieldType)
|
|
if secTag != nil && secTag.Scheme {
|
|
parseSecurityScheme(headers, queryParams, secTag, valType.Interface())
|
|
}
|
|
}
|
|
}
|
|
|
|
func parseSecurityScheme(headers, queryParams map[string]string, schemeTag *securityTag, scheme interface{}) {
|
|
schemeVal := trueReflectValue(reflect.ValueOf(scheme))
|
|
schemeType := schemeVal.Type()
|
|
|
|
if isNil(schemeType, schemeVal) {
|
|
return
|
|
}
|
|
|
|
if schemeType.Kind() == reflect.Struct {
|
|
if schemeTag.Type == "http" {
|
|
switch schemeTag.SubType {
|
|
case "basic":
|
|
handleBasicAuthScheme(headers, schemeVal.Interface())
|
|
return
|
|
case "custom":
|
|
return
|
|
}
|
|
}
|
|
|
|
for i := 0; i < schemeType.NumField(); i++ {
|
|
fieldType := schemeType.Field(i)
|
|
valType := schemeVal.Field(i)
|
|
|
|
if isNil(fieldType.Type, valType) {
|
|
continue
|
|
}
|
|
|
|
if fieldType.Type.Kind() == reflect.Ptr {
|
|
valType = valType.Elem()
|
|
}
|
|
|
|
secTag := parseSecurityTag(fieldType)
|
|
if secTag == nil || secTag.Name == "" {
|
|
return
|
|
}
|
|
|
|
parseSecuritySchemeValue(headers, queryParams, schemeTag, secTag, valType.Interface())
|
|
}
|
|
} else {
|
|
parseSecuritySchemeValue(headers, queryParams, schemeTag, schemeTag, schemeVal.Interface())
|
|
}
|
|
}
|
|
|
|
func parseSecuritySchemeValue(headers, queryParams map[string]string, schemeTag *securityTag, secTag *securityTag, val interface{}) {
|
|
switch schemeTag.Type {
|
|
case "apiKey":
|
|
switch schemeTag.SubType {
|
|
case "header":
|
|
headers[secTag.Name] = valToString(val)
|
|
case "query":
|
|
queryParams[secTag.Name] = valToString(val)
|
|
case "cookie":
|
|
headers["Cookie"] = fmt.Sprintf("%s=%s", secTag.Name, valToString(val))
|
|
default:
|
|
panic("not supported")
|
|
}
|
|
case "openIdConnect":
|
|
headers[secTag.Name] = prefixBearer(valToString(val))
|
|
case "oauth2":
|
|
if schemeTag.SubType != "client_credentials" {
|
|
headers[secTag.Name] = prefixBearer(valToString(val))
|
|
}
|
|
case "http":
|
|
switch schemeTag.SubType {
|
|
case "bearer":
|
|
headers[secTag.Name] = prefixBearer(valToString(val))
|
|
case "custom":
|
|
default:
|
|
panic("not supported")
|
|
}
|
|
default:
|
|
panic("not supported")
|
|
}
|
|
}
|
|
|
|
func prefixBearer(authHeaderValue string) string {
|
|
if strings.HasPrefix(strings.ToLower(authHeaderValue), "bearer ") {
|
|
return authHeaderValue
|
|
}
|
|
|
|
return fmt.Sprintf("Bearer %s", authHeaderValue)
|
|
}
|
|
|
|
func handleBasicAuthScheme(headers map[string]string, scheme interface{}) {
|
|
schemeStructType := reflect.TypeOf(scheme)
|
|
schemeValType := reflect.ValueOf(scheme)
|
|
|
|
var username, password string
|
|
|
|
for i := 0; i < schemeStructType.NumField(); i++ {
|
|
fieldType := schemeStructType.Field(i)
|
|
valType := schemeValType.Field(i)
|
|
|
|
if fieldType.Type.Kind() == reflect.Ptr {
|
|
valType = valType.Elem()
|
|
}
|
|
|
|
secTag := parseSecurityTag(fieldType)
|
|
if secTag == nil || secTag.Name == "" {
|
|
continue
|
|
}
|
|
|
|
switch secTag.Name {
|
|
case "username":
|
|
username = valType.String()
|
|
case "password":
|
|
password = valType.String()
|
|
}
|
|
}
|
|
|
|
headers["Authorization"] = fmt.Sprintf("Basic %s", base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", username, password))))
|
|
}
|
|
|
|
func parseSecurityTag(field reflect.StructField) *securityTag {
|
|
tag := field.Tag.Get(securityTagKey)
|
|
if tag == "" {
|
|
return nil
|
|
}
|
|
|
|
option := false
|
|
scheme := false
|
|
name := ""
|
|
securityType := ""
|
|
securitySubType := ""
|
|
env := ""
|
|
|
|
options := strings.Split(tag, ",")
|
|
for _, optionConf := range options {
|
|
parts := strings.Split(optionConf, "=")
|
|
if len(parts) < 1 || len(parts) > 2 {
|
|
continue
|
|
}
|
|
|
|
switch parts[0] {
|
|
case "name":
|
|
name = parts[1]
|
|
case "type":
|
|
securityType = parts[1]
|
|
case "subtype":
|
|
securitySubType = parts[1]
|
|
case "option":
|
|
option = true
|
|
case "scheme":
|
|
scheme = true
|
|
case "env":
|
|
env = parts[1]
|
|
}
|
|
}
|
|
|
|
// TODO: validate tag?
|
|
|
|
return &securityTag{
|
|
Option: option,
|
|
Scheme: scheme,
|
|
Name: name,
|
|
Type: securityType,
|
|
SubType: securitySubType,
|
|
Env: env,
|
|
}
|
|
}
|
|
|
|
func trueReflectValue(val reflect.Value) reflect.Value {
|
|
kind := val.Type().Kind()
|
|
for kind == reflect.Interface || kind == reflect.Ptr {
|
|
innerVal := val.Elem()
|
|
if !innerVal.IsValid() {
|
|
break
|
|
}
|
|
val = innerVal
|
|
kind = val.Type().Kind()
|
|
}
|
|
return val
|
|
}
|