Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
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
106 changes: 62 additions & 44 deletions internal/utils/decoders/decoders.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,27 @@ package decoders

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

"golang.org/x/text/cases"
"golang.org/x/text/language"
)

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 +32,76 @@ 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))) == "" {
parts = append(parts, root)

id := strings.TrimPrefix(key, root+"-")
id = strings.TrimSuffix(id, "-"+suffix)

if id == "" {
continue
}

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

final := ""

for i, p := range clientNameParts {
for i, part := range parts {
if i == 0 {
camelClientName += p
final += kebabToCamel(part)
continue
}
if p == "" {
continue
}
camelClientName += strings.ToUpper(string([]rune(p)[0])) + string([]rune(p)[1:])
final += "." + kebabToCamel(part)
Comment thread
steveiliop56 marked this conversation as resolved.
Outdated
}

finalKey = append(finalKey, camelClientName)
normalized[final] = v
}

fieldParts := strings.Split(suffix, "-")
return normalized
}

for i, p := range fieldParts {
if i == 0 {
camelField += p
continue
}
if p == "" {
func getKnownKeys[T any]() []string {
var keys []string
var t T

v := reflect.ValueOf(t)
typeOfT := v.Type()

re := regexp.MustCompile(`[A-Z]`)

for field := range typeOfT.NumField() {
if typeOfT.Field(field).Tag.Get("field") != "" {
keys = append(keys, typeOfT.Field(field).Tag.Get("field"))
continue
}

var key string

for i, char := range typeOfT.Field(field).Name {
if re.MatchString(string(char)) && i != 0 {
key += "-" + strings.ToLower(string(char))
continue
}
camelField += strings.ToUpper(string([]rune(p)[0])) + string([]rune(p)[1:])
key += strings.ToLower(string(char))
}

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

return normalized
return keys
}
Comment thread
steveiliop56 marked this conversation as resolved.

func getKnownKeys() []string {
var known []string
func kebabToCamel(input string) string {
res := ""
parts := strings.Split(input, "-")

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

for field := range typeOfP.NumField() {
known = append(known, typeOfP.Field(field).Tag.Get("key"))
for i, part := range parts {
if i == 0 {
res += part
continue
}
res += cases.Title(language.English).String(part)
}

return known
return res
}
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