/
keys.go
121 lines (96 loc) · 2.49 KB
/
keys.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
package validator
import (
"errors"
"fmt"
"regexp"
"strings"
"github.com/authelia/authelia/v4/internal/configuration/schema"
"github.com/authelia/authelia/v4/internal/utils"
)
// ValidateKeys determines if all provided keys are valid.
func ValidateKeys(keys, remapped []string, prefix string, validator *schema.StructValidator) {
var errStrings []string
var patterns []*regexp.Regexp
for _, key := range schema.Keys {
pattern, _ := NewKeyPattern(key)
switch {
case pattern == nil:
continue
default:
patterns = append(patterns, pattern)
}
}
KEYS:
for _, key := range keys {
expectedKey := reKeyReplacer.ReplaceAllString(key, "[]")
if utils.IsStringInSlice(expectedKey, schema.Keys) {
continue
}
if newKey, ok := replacedKeys[expectedKey]; ok {
validator.Push(fmt.Errorf(errFmtReplacedConfigurationKey, key, newKey))
continue
}
for _, p := range patterns {
if p.MatchString(expectedKey) {
continue KEYS
}
}
if utils.IsStringInSlice(expectedKey, remapped) {
continue
}
if err, ok := specificErrorKeys[expectedKey]; ok {
if !utils.IsStringInSlice(err, errStrings) {
errStrings = append(errStrings, err)
}
} else {
if strings.HasPrefix(key, prefix) {
validator.PushWarning(fmt.Errorf("configuration environment variable not expected: %s", key))
} else {
validator.Push(fmt.Errorf("configuration key not expected: %s", key))
}
}
}
for _, err := range errStrings {
validator.Push(errors.New(err))
}
}
// NewKeyPattern returns patterns which are required to match key patterns.
func NewKeyPattern(key string) (pattern *regexp.Regexp, err error) {
switch {
case reIsMapKey.MatchString(key):
return NewKeyMapPattern(key)
default:
return nil, nil
}
}
var reIsMapKey = regexp.MustCompile(`\.\*(\[]|\.)`)
// NewKeyMapPattern returns a pattern required to match map keys.
func NewKeyMapPattern(key string) (pattern *regexp.Regexp, err error) {
parts := strings.Split(key, ".*")
buf := &strings.Builder{}
buf.WriteString("^")
n := len(parts) - 1
for i, part := range parts {
if i != 0 && !strings.HasPrefix(part, "[]") {
buf.WriteString("\\.")
}
for j, r := range part {
// Skip prefixed period.
if j == 0 && r == '.' {
continue
}
switch r {
case '[', ']', '.', '{', '}':
buf.WriteRune('\\')
fallthrough
default:
buf.WriteRune(r)
}
}
if i < n {
buf.WriteString("\\.[a-z0-9](([a-z0-9-_]+)?[a-z0-9])?")
}
}
buf.WriteString("$")
return regexp.Compile(buf.String())
}