Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ require (
github.com/quic-go/qpack v0.5.1 // indirect
github.com/quic-go/quic-go v0.54.1 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/stoewer/go-strcase v1.3.1 // indirect
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.34.0 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,8 @@ github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU=
github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY=
github.com/stoewer/go-strcase v1.3.1 h1:iS0MdW+kVTxgMoE1LAZyMiYJFKlOzLooE4MxjirtkAs=
github.com/stoewer/go-strcase v1.3.1/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
Expand Down
20 changes: 10 additions & 10 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,16 @@ type Claims struct {
}

type OAuthServiceConfig struct {
ClientID string `key:"client-id"`
ClientSecret string `key:"client-secret"`
ClientSecretFile string `key:"client-secret-file"`
Scopes []string `key:"scopes"`
RedirectURL string `key:"redirect-url"`
AuthURL string `key:"auth-url"`
TokenURL string `key:"token-url"`
UserinfoURL string `key:"user-info-url"`
InsecureSkipVerify bool `key:"insecure-skip-verify"`
Name string `key:"name"`
ClientID string `field:"client-id"`
ClientSecret string
ClientSecretFile string
Scopes []string
RedirectURL string `field:"redirect-url"`
AuthURL string `field:"auth-url"`
TokenURL string `field:"token-url"`
UserinfoURL string `field:"user-info-url"`
InsecureSkipVerify bool
Name string
}

var OverrideProviders = map[string]string{
Expand Down
4 changes: 2 additions & 2 deletions internal/utils/app_utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ func GetOAuthProvidersConfig(env []string, args []string, appUrl string) (map[st
}
}

envProviders, err := decoders.DecodeEnv(envMap)
envProviders, err := decoders.DecodeEnv[config.Providers, config.OAuthServiceConfig](envMap, "providers")

if err != nil {
return nil, err
Expand All @@ -167,7 +167,7 @@ func GetOAuthProvidersConfig(env []string, args []string, appUrl string) (map[st
}
}

flagProviders, err := decoders.DecodeFlags(flagsMap)
flagProviders, err := decoders.DecodeFlags[config.Providers, config.OAuthServiceConfig](flagsMap, "providers")

if err != nil {
return nil, err
Expand Down
83 changes: 35 additions & 48 deletions internal/utils/decoders/decoders.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,24 @@ package decoders
import (
"reflect"
"strings"
"tinyauth/internal/config"

"github.com/stoewer/go-strcase"
)

func NormalizeKeys(keys map[string]string, rootName string, sep string) map[string]string {
func normalizeKeys[T any](input map[string]string, root string, sep string) map[string]string {
knownKeys := getKnownKeys[T]()
normalized := make(map[string]string)
knownKeys := getKnownKeys()

for k, v := range keys {
var finalKey []string
var suffix string
var camelClientName string
var camelField string
for k, v := range input {
parts := []string{"tinyauth"}

finalKey = append(finalKey, rootName)
finalKey = append(finalKey, "providers")
lowerKey := strings.ToLower(k)
key := strings.ToLower(k)
key = strings.ReplaceAll(key, sep, "-")

if !strings.HasPrefix(lowerKey, "providers"+sep) {
continue
}
suffix := ""

for _, known := range knownKeys {
if strings.HasSuffix(lowerKey, strings.ReplaceAll(known, "-", sep)) {
if strings.HasSuffix(key, known) {
suffix = known
break
}
Expand All @@ -35,55 +30,47 @@ func NormalizeKeys(keys map[string]string, rootName string, sep string) map[stri
continue
}

if strings.TrimSpace(strings.TrimSuffix(strings.TrimPrefix(lowerKey, "providers"+sep), strings.ReplaceAll(suffix, "-", sep))) == "" {
continue
}
parts = append(parts, root)

clientNameParts := strings.Split(strings.TrimPrefix(strings.TrimSuffix(lowerKey, sep+strings.ReplaceAll(suffix, "-", sep)), "providers"+sep), sep)
id := strings.TrimPrefix(key, root+"-")
id = strings.TrimSuffix(id, "-"+suffix)

for i, p := range clientNameParts {
if i == 0 {
camelClientName += p
continue
}
if p == "" {
continue
}
camelClientName += strings.ToUpper(string([]rune(p)[0])) + string([]rune(p)[1:])
if id == "" {
continue
}

finalKey = append(finalKey, camelClientName)
parts = append(parts, id)
parts = append(parts, suffix)

fieldParts := strings.Split(suffix, "-")
final := ""

for i, p := range fieldParts {
if i == 0 {
camelField += p
continue
}
if p == "" {
continue
for i, part := range parts {
if i > 0 {
final += "."
}
camelField += strings.ToUpper(string([]rune(p)[0])) + string([]rune(p)[1:])
final += strcase.LowerCamelCase(part)
}

finalKey = append(finalKey, camelField)
normalized[strings.Join(finalKey, ".")] = v
normalized[final] = v
}

return normalized
}

func getKnownKeys() []string {
var known []string
func getKnownKeys[T any]() []string {
var keys []string
var t T

p := config.OAuthServiceConfig{}
v := reflect.ValueOf(p)
typeOfP := v.Type()
v := reflect.ValueOf(t)
typeOfT := v.Type()

for field := range typeOfP.NumField() {
known = append(known, typeOfP.Field(field).Tag.Get("key"))
for field := range typeOfT.NumField() {
if typeOfT.Field(field).Tag.Get("field") != "" {
keys = append(keys, typeOfT.Field(field).Tag.Get("field"))
continue
}
keys = append(keys, strcase.KebabCase(typeOfT.Field(field).Name))
}

return known
return keys
}
49 changes: 0 additions & 49 deletions internal/utils/decoders/decoders_test.go

This file was deleted.

15 changes: 7 additions & 8 deletions internal/utils/decoders/env_decoder.go
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
package decoders

import (
"tinyauth/internal/config"

"github.com/traefik/paerser/parser"
)

func DecodeEnv(env map[string]string) (config.Providers, error) {
normalized := NormalizeKeys(env, "tinyauth", "_")
var providers config.Providers
func DecodeEnv[T any, C any](env map[string]string, subName string) (T, error) {
var result T

normalized := normalizeKeys[C](env, subName, "_")

err := parser.Decode(normalized, &providers, "tinyauth", "tinyauth.providers")
err := parser.Decode(normalized, &result, "tinyauth", "tinyauth."+subName)

if err != nil {
return config.Providers{}, err
return result, err
}

return providers, nil
return result, nil
}
57 changes: 17 additions & 40 deletions internal/utils/decoders/env_decoder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,52 +9,29 @@ import (
)

func TestDecodeEnv(t *testing.T) {
// Variables
// Setup
env := map[string]string{
"PROVIDERS_GOOGLE_CLIENT_ID": "google-client-id",
"PROVIDERS_GOOGLE_CLIENT_SECRET": "google-client-secret",
"PROVIDERS_MY_GITHUB_CLIENT_ID": "github-client-id",
"PROVIDERS_MY_GITHUB_CLIENT_SECRET": "github-client-secret",
}

expected := config.Providers{
Providers: map[string]config.OAuthServiceConfig{
"client1": {
ClientID: "client1-id",
ClientSecret: "client1-secret",
Scopes: []string{"client1-scope1", "client1-scope2"},
RedirectURL: "client1-redirect-url",
AuthURL: "client1-auth-url",
UserinfoURL: "client1-user-info-url",
Name: "Client1",
InsecureSkipVerify: false,
"google": {
ClientID: "google-client-id",
ClientSecret: "google-client-secret",
},
"client2": {
ClientID: "client2-id",
ClientSecret: "client2-secret",
Scopes: []string{"client2-scope1", "client2-scope2"},
RedirectURL: "client2-redirect-url",
AuthURL: "client2-auth-url",
UserinfoURL: "client2-user-info-url",
Name: "My Awesome Client2",
InsecureSkipVerify: false,
"myGithub": {
ClientID: "github-client-id",
ClientSecret: "github-client-secret",
},
},
}
test := map[string]string{
"PROVIDERS_CLIENT1_CLIENT_ID": "client1-id",
"PROVIDERS_CLIENT1_CLIENT_SECRET": "client1-secret",
"PROVIDERS_CLIENT1_SCOPES": "client1-scope1,client1-scope2",
"PROVIDERS_CLIENT1_REDIRECT_URL": "client1-redirect-url",
"PROVIDERS_CLIENT1_AUTH_URL": "client1-auth-url",
"PROVIDERS_CLIENT1_USER_INFO_URL": "client1-user-info-url",
"PROVIDERS_CLIENT1_NAME": "Client1",
"PROVIDERS_CLIENT1_INSECURE_SKIP_VERIFY": "false",
"PROVIDERS_CLIENT2_CLIENT_ID": "client2-id",
"PROVIDERS_CLIENT2_CLIENT_SECRET": "client2-secret",
"PROVIDERS_CLIENT2_SCOPES": "client2-scope1,client2-scope2",
"PROVIDERS_CLIENT2_REDIRECT_URL": "client2-redirect-url",
"PROVIDERS_CLIENT2_AUTH_URL": "client2-auth-url",
"PROVIDERS_CLIENT2_USER_INFO_URL": "client2-user-info-url",
"PROVIDERS_CLIENT2_NAME": "My Awesome Client2",
"PROVIDERS_CLIENT2_INSECURE_SKIP_VERIFY": "false",
}

// Test
res, err := decoders.DecodeEnv(test)
// Execute
result, err := decoders.DecodeEnv[config.Providers, config.OAuthServiceConfig](env, "providers")
assert.NilError(t, err)
assert.DeepEqual(t, expected, res)
assert.DeepEqual(t, result, expected)
}
14 changes: 7 additions & 7 deletions internal/utils/decoders/flags_decoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,23 @@ package decoders

import (
"strings"
"tinyauth/internal/config"

"github.com/traefik/paerser/parser"
)

func DecodeFlags(flags map[string]string) (config.Providers, error) {
func DecodeFlags[T any, C any](flags map[string]string, subName string) (T, error) {
var result T

filtered := filterFlags(flags)
normalized := NormalizeKeys(filtered, "tinyauth", "-")
var providers config.Providers
normalized := normalizeKeys[C](filtered, subName, "_")

err := parser.Decode(normalized, &providers, "tinyauth", "tinyauth.providers")
err := parser.Decode(normalized, &result, "tinyauth", "tinyauth."+subName)

if err != nil {
return config.Providers{}, err
return result, err
}

return providers, nil
return result, nil
}

func filterFlags(flags map[string]string) map[string]string {
Expand Down
Loading