7
7
"regexp"
8
8
"strconv"
9
9
"strings"
10
+
11
+ semver "github.com/Masterminds/semver/v3"
10
12
)
11
13
12
14
type condition struct {
@@ -27,7 +29,7 @@ func findMatchingRule(subjectAttributes dictionary, rules []rule) (rule, error)
27
29
}
28
30
}
29
31
30
- return rule {}, errors .New ("No matching rule" )
32
+ return rule {}, errors .New ("no matching rule" )
31
33
}
32
34
33
35
func matchesRule (subjectAttributes dictionary , rule rule ) bool {
@@ -41,25 +43,48 @@ func matchesRule(subjectAttributes dictionary, rule rule) bool {
41
43
}
42
44
43
45
func evaluateCondition (subjectAttributes dictionary , condition condition ) bool {
44
- subjectValue := subjectAttributes [condition .Attribute ]
46
+ subjectValue , exists := subjectAttributes [condition .Attribute ]
47
+ if ! exists {
48
+ return false
49
+ }
45
50
46
- if subjectValue != nil {
47
- if condition .Operator == "MATCHES" {
48
- v := reflect .ValueOf (subjectValue )
49
- if v .Kind () != reflect .String {
50
- subjectValue = strconv .Itoa (subjectValue .(int ))
51
+ switch condition .Operator {
52
+ case "MATCHES" :
53
+ v := reflect .ValueOf (subjectValue )
54
+ if v .Kind () != reflect .String {
55
+ subjectValue = strconv .Itoa (subjectValue .(int ))
56
+ }
57
+ r , _ := regexp .MatchString (condition .Value .(string ), subjectValue .(string ))
58
+ return r
59
+ case "ONE_OF" :
60
+ return isOneOf (subjectValue , convertToStringArray (condition .Value ))
61
+ case "NOT_ONE_OF" :
62
+ return isNotOneOf (subjectValue , convertToStringArray (condition .Value ))
63
+ default :
64
+ // Attempt to evaluate as numeric condition if both values are numeric.
65
+ subjectValueNumeric , isNumericSubject := subjectValue .(float64 ) // Assuming float64 for general numeric comparison; adjust as needed.
66
+ conditionValueNumeric , isNumericCondition := condition .Value .(float64 ) // Same assumption as above.
67
+ if isNumericSubject && isNumericCondition {
68
+ return evaluateNumericCondition (subjectValueNumeric , conditionValueNumeric , condition )
69
+ }
70
+
71
+ // Attempt to compare using semantic versioning if both values are strings.
72
+ subjectValueStr , isStringSubject := subjectValue .(string )
73
+ conditionValueStr , isStringCondition := condition .Value .(string )
74
+ if isStringSubject && isStringCondition {
75
+ // Attempt to parse both values as semantic versions.
76
+ subjectSemVer , errSubject := semver .NewVersion (subjectValueStr )
77
+ conditionSemVer , errCondition := semver .NewVersion (conditionValueStr )
78
+
79
+ // If parsing succeeds, evaluate the semver condition.
80
+ if errSubject == nil && errCondition == nil {
81
+ return evaluateSemVerCondition (subjectSemVer , conditionSemVer , condition )
51
82
}
52
- r , _ := regexp .MatchString (condition .Value .(string ), subjectValue .(string ))
53
- return r
54
- } else if condition .Operator == "ONE_OF" {
55
- return isOneOf (subjectValue , convertToStringArray (condition .Value ))
56
- } else if condition .Operator == "NOT_ONE_OF" {
57
- return isNotOneOf (subjectValue , convertToStringArray (condition .Value ))
58
- } else {
59
- return evaluateNumericCondition (subjectValue , condition )
60
83
}
84
+
85
+ // Fallback logic if neither numeric nor semver comparison is applicable.
86
+ return false
61
87
}
62
- return false
63
88
}
64
89
65
90
func convertToStringArray (conditionValue interface {}) []string {
@@ -101,26 +126,31 @@ func getMatchingStringValues(attributeValue interface{}, conditionValue []string
101
126
return result
102
127
}
103
128
104
- func evaluateNumericCondition (subjectValue interface {}, condition condition ) bool {
105
- v := reflect .ValueOf (subjectValue )
106
-
107
- if v .Kind () == reflect .String {
108
- return false
109
- }
110
-
111
- if v .Kind () == reflect .Int {
112
- subjectValue = float64 (subjectValue .(int ))
129
+ func evaluateSemVerCondition (subjectValue * semver.Version , conditionValue * semver.Version , condition condition ) bool {
130
+ switch condition .Operator {
131
+ case "GT" :
132
+ return subjectValue .GreaterThan (conditionValue )
133
+ case "GTE" :
134
+ return subjectValue .GreaterThan (conditionValue ) || subjectValue .Equal (conditionValue )
135
+ case "LT" :
136
+ return subjectValue .LessThan (conditionValue )
137
+ case "LTE" :
138
+ return subjectValue .LessThan (conditionValue ) || subjectValue .Equal (conditionValue )
139
+ default :
140
+ panic ("Incorrect condition operator" )
113
141
}
142
+ }
114
143
144
+ func evaluateNumericCondition (subjectValue float64 , conditionValue float64 , condition condition ) bool {
115
145
switch condition .Operator {
116
146
case "GT" :
117
- return subjectValue .( float64 ) > condition . Value .( float64 )
147
+ return subjectValue > conditionValue
118
148
case "GTE" :
119
- return subjectValue .( float64 ) >= condition . Value .( float64 )
149
+ return subjectValue >= conditionValue
120
150
case "LT" :
121
- return subjectValue .( float64 ) < condition . Value .( float64 )
151
+ return subjectValue < conditionValue
122
152
case "LTE" :
123
- return subjectValue .( float64 ) <= condition . Value .( float64 )
153
+ return subjectValue <= conditionValue
124
154
default :
125
155
panic ("Incorrect condition operator" )
126
156
}
0 commit comments