2022-04-16 10:48:07 +00:00
|
|
|
package configuration
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2022-06-28 03:15:50 +00:00
|
|
|
"strings"
|
2022-04-16 10:48:07 +00:00
|
|
|
|
|
|
|
"github.com/knadh/koanf"
|
2022-06-28 03:15:50 +00:00
|
|
|
"github.com/knadh/koanf/providers/confmap"
|
2022-04-16 10:48:07 +00:00
|
|
|
|
2022-06-28 03:15:50 +00:00
|
|
|
"github.com/authelia/authelia/v4/internal/configuration/schema"
|
2022-04-16 10:48:07 +00:00
|
|
|
"github.com/authelia/authelia/v4/internal/utils"
|
|
|
|
)
|
|
|
|
|
2022-06-28 03:15:50 +00:00
|
|
|
func koanfGetKeys(ko *koanf.Koanf) (keys []string) {
|
2022-04-16 10:48:07 +00:00
|
|
|
keys = ko.Keys()
|
|
|
|
|
|
|
|
for key, value := range ko.All() {
|
2022-10-05 05:05:23 +00:00
|
|
|
slc, ok := value.([]any)
|
2022-04-16 10:48:07 +00:00
|
|
|
if !ok {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, item := range slc {
|
2022-10-05 05:05:23 +00:00
|
|
|
m, mok := item.(map[string]any)
|
2022-04-16 10:48:07 +00:00
|
|
|
if !mok {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
for k := range m {
|
|
|
|
full := fmt.Sprintf("%s[].%s", key, k)
|
|
|
|
if !utils.IsStringInSlice(full, keys) {
|
|
|
|
keys = append(keys, full)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return keys
|
|
|
|
}
|
2022-06-28 03:15:50 +00:00
|
|
|
|
|
|
|
func koanfRemapKeys(val *schema.StructValidator, ko *koanf.Koanf, ds map[string]Deprecation) (final *koanf.Koanf, err error) {
|
|
|
|
keys := ko.All()
|
|
|
|
|
|
|
|
keys = koanfRemapKeysStandard(keys, val, ds)
|
|
|
|
keys = koanfRemapKeysMapped(keys, val, ds)
|
|
|
|
|
|
|
|
final = koanf.New(".")
|
|
|
|
|
|
|
|
if err = final.Load(confmap.Provider(keys, "."), nil); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return final, nil
|
|
|
|
}
|
|
|
|
|
2022-10-05 05:05:23 +00:00
|
|
|
func koanfRemapKeysStandard(keys map[string]any, val *schema.StructValidator, ds map[string]Deprecation) (keysFinal map[string]interface{}) {
|
2022-06-28 03:15:50 +00:00
|
|
|
var (
|
|
|
|
ok bool
|
|
|
|
d Deprecation
|
|
|
|
key string
|
|
|
|
value interface{}
|
|
|
|
)
|
|
|
|
|
|
|
|
keysFinal = make(map[string]interface{})
|
|
|
|
|
|
|
|
for key, value = range keys {
|
|
|
|
if d, ok = ds[key]; ok {
|
|
|
|
if !d.AutoMap {
|
|
|
|
val.Push(fmt.Errorf("invalid configuration key '%s' was replaced by '%s'", d.Key, d.NewKey))
|
|
|
|
|
|
|
|
keysFinal[key] = value
|
|
|
|
|
|
|
|
continue
|
|
|
|
} else {
|
|
|
|
val.PushWarning(fmt.Errorf("configuration key '%s' is deprecated in %s and has been replaced by '%s': "+
|
|
|
|
"this has been automatically mapped for you but you will need to adjust your configuration to remove this message", d.Key, d.Version.String(), d.NewKey))
|
|
|
|
}
|
|
|
|
|
|
|
|
if !mapHasKey(d.NewKey, keys) && !mapHasKey(d.NewKey, keysFinal) {
|
|
|
|
if d.MapFunc != nil {
|
|
|
|
keysFinal[d.NewKey] = d.MapFunc(value)
|
|
|
|
} else {
|
|
|
|
keysFinal[d.NewKey] = value
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
keysFinal[key] = value
|
|
|
|
}
|
|
|
|
|
|
|
|
return keysFinal
|
|
|
|
}
|
|
|
|
|
|
|
|
func koanfRemapKeysMapped(keys map[string]interface{}, val *schema.StructValidator, ds map[string]Deprecation) (keysFinal map[string]interface{}) {
|
|
|
|
var (
|
|
|
|
key string
|
|
|
|
value interface{}
|
|
|
|
slc, slcFinal []interface{}
|
|
|
|
ok bool
|
|
|
|
m map[string]interface{}
|
|
|
|
d Deprecation
|
|
|
|
)
|
|
|
|
|
|
|
|
keysFinal = make(map[string]interface{})
|
|
|
|
|
|
|
|
for key, value = range keys {
|
|
|
|
if slc, ok = value.([]interface{}); !ok {
|
|
|
|
keysFinal[key] = value
|
|
|
|
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
slcFinal = make([]interface{}, len(slc))
|
|
|
|
|
|
|
|
for i, item := range slc {
|
|
|
|
if m, ok = item.(map[string]interface{}); !ok {
|
|
|
|
slcFinal[i] = item
|
|
|
|
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
itemFinal := make(map[string]interface{})
|
|
|
|
|
|
|
|
for subkey, element := range m {
|
|
|
|
prefix := fmt.Sprintf("%s[].", key)
|
|
|
|
|
|
|
|
fullKey := prefix + subkey
|
|
|
|
|
|
|
|
if d, ok = ds[fullKey]; ok {
|
|
|
|
if !d.AutoMap {
|
|
|
|
val.Push(fmt.Errorf("invalid configuration key '%s' was replaced by '%s'", d.Key, d.NewKey))
|
|
|
|
|
|
|
|
itemFinal[subkey] = element
|
|
|
|
|
|
|
|
continue
|
|
|
|
} else {
|
|
|
|
val.PushWarning(fmt.Errorf("configuration key '%s' is deprecated in %s and has been replaced by '%s': "+
|
|
|
|
"this has been automatically mapped for you but you will need to adjust your configuration to remove this message", d.Key, d.Version.String(), d.NewKey))
|
|
|
|
}
|
|
|
|
|
|
|
|
newkey := strings.Replace(d.NewKey, prefix, "", 1)
|
|
|
|
|
|
|
|
if !mapHasKey(newkey, m) && !mapHasKey(newkey, itemFinal) {
|
|
|
|
if d.MapFunc != nil {
|
|
|
|
itemFinal[newkey] = d.MapFunc(element)
|
|
|
|
} else {
|
|
|
|
itemFinal[newkey] = element
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
itemFinal[subkey] = element
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
slcFinal[i] = itemFinal
|
|
|
|
}
|
|
|
|
|
|
|
|
keysFinal[key] = slcFinal
|
|
|
|
}
|
|
|
|
|
|
|
|
return keysFinal
|
|
|
|
}
|