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
2022-06-28 03:15:50 +00:00
"github.com/knadh/koanf/providers/confmap"
2023-02-19 00:49:08 +00:00
"github.com/knadh/koanf/v2"
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
}
2023-04-15 12:35:44 +00:00
func koanfRemapKeysStandard ( keys map [ string ] any , val * schema . StructValidator , ds map [ string ] Deprecation ) ( keysFinal map [ string ] any ) {
2022-06-28 03:15:50 +00:00
var (
ok bool
d Deprecation
key string
2023-04-15 12:35:44 +00:00
value any
2022-06-28 03:15:50 +00:00
)
2023-04-15 12:35:44 +00:00
keysFinal = make ( map [ string ] any )
2022-06-28 03:15:50 +00:00
for key , value = range keys {
if d , ok = ds [ key ] ; ok {
if ! d . AutoMap {
keysFinal [ key ] = value
2023-05-07 05:48:26 +00:00
if d . ErrFunc != nil {
d . ErrFunc ( d , keysFinal , value , val )
} else {
val . Push ( fmt . Errorf ( "invalid configuration key '%s' was replaced by '%s'" , d . Key , d . NewKey ) )
}
2022-06-28 03:15:50 +00:00
continue
}
if ! mapHasKey ( d . NewKey , keys ) && ! mapHasKey ( d . NewKey , keysFinal ) {
2023-05-07 05:48:26 +00:00
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 ) )
2022-06-28 03:15:50 +00:00
if d . MapFunc != nil {
keysFinal [ d . NewKey ] = d . MapFunc ( value )
} else {
keysFinal [ d . NewKey ] = value
}
2023-05-07 05:48:26 +00:00
} else {
val . PushWarning ( fmt . Errorf ( "configuration key '%s' is deprecated in %s and has been replaced by '%s': " +
"this has not been automatically mapped for you because the replacement key also exists and you will need to adjust your configuration to remove this message" , d . Key , d . Version . String ( ) , d . NewKey ) )
2022-06-28 03:15:50 +00:00
}
continue
}
keysFinal [ key ] = value
}
return keysFinal
}
2023-04-15 12:35:44 +00:00
func koanfRemapKeysMapped ( keys map [ string ] any , val * schema . StructValidator , ds map [ string ] Deprecation ) ( keysFinal map [ string ] any ) {
2022-06-28 03:15:50 +00:00
var (
key string
2023-04-15 12:35:44 +00:00
value any
slc , slcFinal [ ] any
2022-06-28 03:15:50 +00:00
ok bool
2023-04-15 12:35:44 +00:00
m map [ string ] any
2022-06-28 03:15:50 +00:00
d Deprecation
)
2023-04-15 12:35:44 +00:00
keysFinal = make ( map [ string ] any )
2022-06-28 03:15:50 +00:00
for key , value = range keys {
2023-04-15 12:35:44 +00:00
if slc , ok = value . ( [ ] any ) ; ! ok {
2022-06-28 03:15:50 +00:00
keysFinal [ key ] = value
continue
}
2023-04-15 12:35:44 +00:00
slcFinal = make ( [ ] any , len ( slc ) )
2022-06-28 03:15:50 +00:00
for i , item := range slc {
2023-04-15 12:35:44 +00:00
if m , ok = item . ( map [ string ] any ) ; ! ok {
2022-06-28 03:15:50 +00:00
slcFinal [ i ] = item
continue
}
2023-04-15 12:35:44 +00:00
itemFinal := make ( map [ string ] any )
2022-06-28 03:15:50 +00:00
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
}