@@ -580,7 +580,7 @@ func (e *evaluator) evalCondition(user User, cond configCondition, depth int, co
580
580
case strings .EqualFold (op , "version_neq" ):
581
581
pass = compareVersions (value , cond .TargetValue , func (x , y []int64 ) bool { return compareVersionsHelper (x , y ) != 0 })
582
582
583
- // array operations
583
+ // one to array operations
584
584
case strings .EqualFold (op , "any" ):
585
585
pass = arrayAny (cond .TargetValue , value , func (x , y interface {}) bool {
586
586
if cond .UserBucket != nil {
@@ -606,6 +606,42 @@ func (e *evaluator) evalCondition(user User, cond configCondition, depth int, co
606
606
return compareStrings (x , y , false , func (s1 , s2 string ) bool { return s1 == s2 })
607
607
})
608
608
609
+ // array to array operations
610
+ case strings .EqualFold (op , "array_contains_any" ):
611
+ targetArr , okTarget := cond .TargetValue .([]interface {})
612
+ valArr , okVal := value .([]interface {})
613
+ if ! (okTarget && okVal ) {
614
+ pass = false
615
+ } else {
616
+ pass = arrayContainsAny (targetArr , valArr )
617
+ }
618
+ case strings .EqualFold (op , "array_contains_none" ):
619
+ targetArr , okTarget := cond .TargetValue .([]interface {})
620
+ valArr , okVal := value .([]interface {})
621
+ if ! (okTarget && okVal ) {
622
+ pass = false
623
+ } else {
624
+ pass = ! arrayContainsAny (targetArr , valArr )
625
+ }
626
+ case strings .EqualFold (op , "array_contains_all" ):
627
+ targetArr , okTarget := cond .TargetValue .([]interface {})
628
+ valArr , okVal := value .([]interface {})
629
+
630
+ if ! (okTarget && okVal ) {
631
+ pass = false
632
+ } else {
633
+ pass = arrayContainsAll (targetArr , valArr )
634
+ }
635
+ case strings .EqualFold (op , "not_array_contains_all" ):
636
+ targetArr , okTarget := cond .TargetValue .([]interface {})
637
+ valArr , okVal := value .([]interface {})
638
+
639
+ if ! (okTarget && okVal ) {
640
+ pass = false
641
+ } else {
642
+ pass = ! arrayContainsAll (targetArr , valArr )
643
+ }
644
+
609
645
// string operations
610
646
case strings .EqualFold (op , "str_starts_with_any" ):
611
647
pass = arrayAny (cond .TargetValue , value , func (x , y interface {}) bool {
@@ -835,8 +871,15 @@ func convertToString(a interface{}) string {
835
871
return strconv .FormatBool (aVal .Bool ())
836
872
case reflect .String :
837
873
return fmt .Sprintf ("%v" , a )
874
+ case reflect .Slice , reflect .Array :
875
+ var result []string
876
+ for i := 0 ; i < aVal .Len (); i ++ {
877
+ result = append (result , fmt .Sprintf ("%v" , aVal .Index (i ).Interface ()))
878
+ }
879
+ return strings .Join (result , "," )
838
880
}
839
- return ""
881
+
882
+ return fmt .Sprintf ("%v" , a )
840
883
}
841
884
842
885
func compareNumbers (a , b interface {}, fun func (x , y float64 ) bool ) bool {
@@ -950,6 +993,40 @@ func arrayAny(arr interface{}, val interface{}, fun func(x, y interface{}) bool)
950
993
return false
951
994
}
952
995
996
+ func arrayContainsAll (target []interface {}, value []interface {}) bool {
997
+ valueSet := make (map [string ]struct {})
998
+ for _ , item := range value {
999
+ valStr := convertToString (item )
1000
+ valueSet [valStr ] = struct {}{}
1001
+ }
1002
+
1003
+ for _ , t := range target {
1004
+ strTarget := convertToString (t )
1005
+ _ , strExists := valueSet [strTarget ]
1006
+ if ! strExists {
1007
+ return false
1008
+ }
1009
+ }
1010
+ return true
1011
+ }
1012
+
1013
+ func arrayContainsAny (target []interface {}, value []interface {}) bool {
1014
+ valueSet := make (map [string ]struct {})
1015
+ for _ , item := range value {
1016
+ valStr := convertToString (item )
1017
+ valueSet [valStr ] = struct {}{}
1018
+ }
1019
+
1020
+ for _ , t := range target {
1021
+ strTarget := convertToString (t )
1022
+ _ , strExists := valueSet [strTarget ]
1023
+ if strExists {
1024
+ return true
1025
+ }
1026
+ }
1027
+ return false
1028
+ }
1029
+
953
1030
func getTime (a interface {}) time.Time {
954
1031
switch v := a .(type ) {
955
1032
case float64 , int64 , int32 , int :
0 commit comments