github.com/greenpau/go-authcrunch@v1.1.4/pkg/acl/condition.go (about)

     1  // Copyright 2022 Paul Greenberg greenpau@outlook.com
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package acl
    16  
    17  import (
    18  	"context"
    19  	"github.com/greenpau/go-authcrunch/pkg/errors"
    20  	"regexp"
    21  	"strings"
    22  )
    23  
    24  type dataType int
    25  type fieldMatchStrategy int
    26  
    27  var (
    28  	matchWithStrategyRgx *regexp.Regexp
    29  	matchFieldRgx        *regexp.Regexp
    30  
    31  	inputDataTypes = map[string]dataType{
    32  		"roles":  dataTypeListStr,
    33  		"email":  dataTypeStr,
    34  		"origin": dataTypeStr,
    35  		"name":   dataTypeStr,
    36  		"realm":  dataTypeStr,
    37  		"aud":    dataTypeListStr,
    38  		"scopes": dataTypeListStr,
    39  		"org":    dataTypeListStr,
    40  		"jti":    dataTypeStr,
    41  		"iss":    dataTypeStr,
    42  		"sub":    dataTypeStr,
    43  		"addr":   dataTypeStr,
    44  		"method": dataTypeStr,
    45  		"path":   dataTypeStr,
    46  	}
    47  
    48  	inputDataAliases = map[string]string{
    49  		"id":           "jti",
    50  		"audience":     "aud",
    51  		"expires":      "exp",
    52  		"issued":       "iat",
    53  		"issuer":       "iss",
    54  		"subject":      "sub",
    55  		"mail":         "email",
    56  		"role":         "roles",
    57  		"group":        "roles",
    58  		"groups":       "roles",
    59  		"scope":        "scopes",
    60  		"organization": "org",
    61  		"address":      "addr",
    62  		"ip":           "addr",
    63  		"ipv4":         "addr",
    64  		"http_method":  "method",
    65  		"http_path":    "path",
    66  	}
    67  )
    68  
    69  const (
    70  	dataTypeUnknown dataType = 0
    71  	dataTypeListStr dataType = 1
    72  	dataTypeStr     dataType = 2
    73  	dataTypeAny     dataType = 3
    74  
    75  	fieldMatchUnknown  fieldMatchStrategy = 0
    76  	fieldMatchReserved fieldMatchStrategy = 1
    77  	fieldMatchExact    fieldMatchStrategy = 2
    78  	fieldMatchPartial  fieldMatchStrategy = 3
    79  	fieldMatchPrefix   fieldMatchStrategy = 4
    80  	fieldMatchSuffix   fieldMatchStrategy = 5
    81  	fieldMatchRegex    fieldMatchStrategy = 6
    82  	fieldFound         fieldMatchStrategy = 7
    83  	fieldNotFound      fieldMatchStrategy = 8
    84  	fieldMatchAlways   fieldMatchStrategy = 9
    85  )
    86  
    87  type field struct {
    88  	name   string
    89  	length int
    90  }
    91  
    92  type expr struct {
    93  	value  string
    94  	length int
    95  }
    96  
    97  type config struct {
    98  	field         string
    99  	matchStrategy fieldMatchStrategy
   100  	values        []string
   101  	regexEnabled  bool
   102  	alwaysTrue    bool
   103  	matchAny      bool
   104  	exprDataType  dataType
   105  	inputDataType dataType
   106  	conditionType string
   107  }
   108  
   109  type aclRuleCondition interface {
   110  	match(context.Context, interface{}) bool
   111  	getConfig(context.Context) *config
   112  }
   113  
   114  // ruleAnyCondAlwaysMatchAnyInput returns positive match regardless of
   115  // input fields, values, or conditions.
   116  type ruleAnyCondAlwaysMatchAnyInput struct {
   117  	field  *field
   118  	exprs  []*expr
   119  	config *config
   120  }
   121  
   122  // ruleCondFieldFound returns positive match regardless of input fields, values,
   123  // or conditions, because the condition is only relevant to ACL rule itself.
   124  type ruleCondFieldFound struct {
   125  	field  *field
   126  	exprs  []*expr
   127  	config *config
   128  }
   129  
   130  // ruleCondFieldNotFound returns positive match regardless of input fields, values,
   131  // or conditions, because the condition is only relevant to ACL rule itself.
   132  type ruleCondFieldNotFound struct {
   133  	field  *field
   134  	exprs  []*expr
   135  	config *config
   136  }
   137  
   138  func (c *ruleAnyCondAlwaysMatchAnyInput) match(ctx context.Context, v interface{}) bool {
   139  	return true
   140  }
   141  
   142  func (c *ruleAnyCondAlwaysMatchAnyInput) getConfig(ctx context.Context) *config {
   143  	return c.config
   144  }
   145  
   146  func (c *ruleCondFieldFound) match(ctx context.Context, v interface{}) bool {
   147  	return true
   148  }
   149  
   150  func (c *ruleCondFieldFound) getConfig(ctx context.Context) *config {
   151  	return c.config
   152  }
   153  
   154  func (c *ruleCondFieldNotFound) match(ctx context.Context, v interface{}) bool {
   155  	return true
   156  }
   157  
   158  func (c *ruleCondFieldNotFound) getConfig(ctx context.Context) *config {
   159  	return c.config
   160  }
   161  
   162  // ruleListStrCondExactNegativeMatchListStrInput not matches a list of strings
   163  // input against a list of strings where any of the input values not match at least
   164  // one value of the condition using exact not match.
   165  type ruleListStrCondExactNegativeMatchListStrInput struct {
   166  	field  *field
   167  	exprs  []*expr
   168  	config *config
   169  }
   170  
   171  // ruleListStrCondPartialNegativeMatchListStrInput not matches a list of strings
   172  // input against a list of strings where any of the input values not match at least
   173  // one value of the condition using substring not match.
   174  type ruleListStrCondPartialNegativeMatchListStrInput struct {
   175  	field  *field
   176  	exprs  []*expr
   177  	config *config
   178  }
   179  
   180  // ruleListStrCondPrefixNegativeMatchListStrInput not matches a list of strings
   181  // input against a list of strings where any of the input values not match at least
   182  // one value of the condition using string prefix not match.
   183  type ruleListStrCondPrefixNegativeMatchListStrInput struct {
   184  	field  *field
   185  	exprs  []*expr
   186  	config *config
   187  }
   188  
   189  // ruleListStrCondSuffixNegativeMatchListStrInput not matches a list of strings
   190  // input against a list of strings where any of the input values not match at least
   191  // one value of the condition using string suffix not match.
   192  type ruleListStrCondSuffixNegativeMatchListStrInput struct {
   193  	field  *field
   194  	exprs  []*expr
   195  	config *config
   196  }
   197  
   198  // ruleListStrCondRegexNegativeMatchListStrInput not matches a list of strings
   199  // input against a list of strings where any of the input values not match at least
   200  // one value of the condition using regular expressions not match.
   201  type ruleListStrCondRegexNegativeMatchListStrInput struct {
   202  	field  *field
   203  	exprs  []*regexp.Regexp
   204  	config *config
   205  }
   206  
   207  // ruleStrCondExactNegativeMatchListStrInput not matches a list of strings input
   208  // against a string condition using exact not match.
   209  type ruleStrCondExactNegativeMatchListStrInput struct {
   210  	field  *field
   211  	expr   *expr
   212  	config *config
   213  }
   214  
   215  // ruleStrCondPartialNegativeMatchListStrInput not matches a list of strings input
   216  // against a string condition using substring not match.
   217  type ruleStrCondPartialNegativeMatchListStrInput struct {
   218  	field  *field
   219  	expr   *expr
   220  	config *config
   221  }
   222  
   223  // ruleStrCondPrefixNegativeMatchListStrInput not matches a list of strings input
   224  // against a string condition using string prefix not match.
   225  type ruleStrCondPrefixNegativeMatchListStrInput struct {
   226  	field  *field
   227  	expr   *expr
   228  	config *config
   229  }
   230  
   231  // ruleStrCondSuffixNegativeMatchListStrInput not matches a list of strings input
   232  // against a string condition using string suffix not match.
   233  type ruleStrCondSuffixNegativeMatchListStrInput struct {
   234  	field  *field
   235  	expr   *expr
   236  	config *config
   237  }
   238  
   239  // ruleStrCondRegexNegativeMatchListStrInput not matches a list of strings input
   240  // against a string condition using regular expressions not match.
   241  type ruleStrCondRegexNegativeMatchListStrInput struct {
   242  	field  *field
   243  	expr   *regexp.Regexp
   244  	config *config
   245  }
   246  
   247  // ruleListStrCondExactNegativeMatchStrInput not matches an input string against a
   248  // list of strings where any of the input values not match at least one value of
   249  // the condition using exact not match.
   250  type ruleListStrCondExactNegativeMatchStrInput struct {
   251  	field  *field
   252  	exprs  []*expr
   253  	config *config
   254  }
   255  
   256  // ruleListStrCondPartialNegativeMatchStrInput not matches an input string against
   257  // a list of strings where any of the input values not match at least one value of
   258  // the condition using substring not match.
   259  type ruleListStrCondPartialNegativeMatchStrInput struct {
   260  	field  *field
   261  	exprs  []*expr
   262  	config *config
   263  }
   264  
   265  // ruleListStrCondPrefixNegativeMatchStrInput not matches an input string against a
   266  // list of strings where any of the input values not match at least one value of
   267  // the condition using string prefix not match.
   268  type ruleListStrCondPrefixNegativeMatchStrInput struct {
   269  	field  *field
   270  	exprs  []*expr
   271  	config *config
   272  }
   273  
   274  // ruleListStrCondSuffixNegativeMatchStrInput not matches an input string against a
   275  // list of strings where any of the input values not match at least one value of
   276  // the condition using string suffix not match.
   277  type ruleListStrCondSuffixNegativeMatchStrInput struct {
   278  	field  *field
   279  	exprs  []*expr
   280  	config *config
   281  }
   282  
   283  // ruleListStrCondRegexNegativeMatchStrInput not matches an input string against a
   284  // list of strings where any of the input values not match at least one value of
   285  // the condition using regular expressions not match.
   286  type ruleListStrCondRegexNegativeMatchStrInput struct {
   287  	field  *field
   288  	exprs  []*regexp.Regexp
   289  	config *config
   290  }
   291  
   292  // ruleStrCondExactNegativeMatchStrInput not matches an input string against a
   293  // string condition using exact not match.
   294  type ruleStrCondExactNegativeMatchStrInput struct {
   295  	field  *field
   296  	expr   *expr
   297  	config *config
   298  }
   299  
   300  // ruleStrCondPartialNegativeMatchStrInput not matches an input string against a
   301  // string condition using substring not match.
   302  type ruleStrCondPartialNegativeMatchStrInput struct {
   303  	field  *field
   304  	expr   *expr
   305  	config *config
   306  }
   307  
   308  // ruleStrCondPrefixNegativeMatchStrInput not matches an input string against a
   309  // string condition using string prefix not match.
   310  type ruleStrCondPrefixNegativeMatchStrInput struct {
   311  	field  *field
   312  	expr   *expr
   313  	config *config
   314  }
   315  
   316  // ruleStrCondSuffixNegativeMatchStrInput not matches an input string against a
   317  // string condition using string suffix not match.
   318  type ruleStrCondSuffixNegativeMatchStrInput struct {
   319  	field  *field
   320  	expr   *expr
   321  	config *config
   322  }
   323  
   324  // ruleStrCondRegexNegativeMatchStrInput not matches an input string against a
   325  // string condition using regular expressions not match.
   326  type ruleStrCondRegexNegativeMatchStrInput struct {
   327  	field  *field
   328  	expr   *regexp.Regexp
   329  	config *config
   330  }
   331  
   332  // ruleListStrCondExactMatchListStrInput matches a list of strings input against a
   333  // list of strings where any of the input values match at least one value of the
   334  // condition using exact match.
   335  type ruleListStrCondExactMatchListStrInput struct {
   336  	field  *field
   337  	exprs  []*expr
   338  	config *config
   339  }
   340  
   341  // ruleListStrCondPartialMatchListStrInput matches a list of strings input against
   342  // a list of strings where any of the input values match at least one value of the
   343  // condition using substring match.
   344  type ruleListStrCondPartialMatchListStrInput struct {
   345  	field  *field
   346  	exprs  []*expr
   347  	config *config
   348  }
   349  
   350  // ruleListStrCondPrefixMatchListStrInput matches a list of strings input against a
   351  // list of strings where any of the input values match at least one value of the
   352  // condition using string prefix match.
   353  type ruleListStrCondPrefixMatchListStrInput struct {
   354  	field  *field
   355  	exprs  []*expr
   356  	config *config
   357  }
   358  
   359  // ruleListStrCondSuffixMatchListStrInput matches a list of strings input against a
   360  // list of strings where any of the input values match at least one value of the
   361  // condition using string suffix match.
   362  type ruleListStrCondSuffixMatchListStrInput struct {
   363  	field  *field
   364  	exprs  []*expr
   365  	config *config
   366  }
   367  
   368  // ruleListStrCondRegexMatchListStrInput matches a list of strings input against a
   369  // list of strings where any of the input values match at least one value of the
   370  // condition using regular expressions match.
   371  type ruleListStrCondRegexMatchListStrInput struct {
   372  	field  *field
   373  	exprs  []*regexp.Regexp
   374  	config *config
   375  }
   376  
   377  // ruleStrCondExactMatchListStrInput matches a list of strings input against a
   378  // string condition using exact match.
   379  type ruleStrCondExactMatchListStrInput struct {
   380  	field  *field
   381  	expr   *expr
   382  	config *config
   383  }
   384  
   385  // ruleStrCondPartialMatchListStrInput matches a list of strings input against a
   386  // string condition using substring match.
   387  type ruleStrCondPartialMatchListStrInput struct {
   388  	field  *field
   389  	expr   *expr
   390  	config *config
   391  }
   392  
   393  // ruleStrCondPrefixMatchListStrInput matches a list of strings input against a
   394  // string condition using string prefix match.
   395  type ruleStrCondPrefixMatchListStrInput struct {
   396  	field  *field
   397  	expr   *expr
   398  	config *config
   399  }
   400  
   401  // ruleStrCondSuffixMatchListStrInput matches a list of strings input against a
   402  // string condition using string suffix match.
   403  type ruleStrCondSuffixMatchListStrInput struct {
   404  	field  *field
   405  	expr   *expr
   406  	config *config
   407  }
   408  
   409  // ruleStrCondRegexMatchListStrInput matches a list of strings input against a
   410  // string condition using regular expressions match.
   411  type ruleStrCondRegexMatchListStrInput struct {
   412  	field  *field
   413  	expr   *regexp.Regexp
   414  	config *config
   415  }
   416  
   417  // ruleListStrCondExactMatchStrInput matches an input string against a list of
   418  // strings where any of the input values match at least one value of the condition
   419  // using exact match.
   420  type ruleListStrCondExactMatchStrInput struct {
   421  	field  *field
   422  	exprs  []*expr
   423  	config *config
   424  }
   425  
   426  // ruleListStrCondPartialMatchStrInput matches an input string against a list of
   427  // strings where any of the input values match at least one value of the condition
   428  // using substring match.
   429  type ruleListStrCondPartialMatchStrInput struct {
   430  	field  *field
   431  	exprs  []*expr
   432  	config *config
   433  }
   434  
   435  // ruleListStrCondPrefixMatchStrInput matches an input string against a list of
   436  // strings where any of the input values match at least one value of the condition
   437  // using string prefix match.
   438  type ruleListStrCondPrefixMatchStrInput struct {
   439  	field  *field
   440  	exprs  []*expr
   441  	config *config
   442  }
   443  
   444  // ruleListStrCondSuffixMatchStrInput matches an input string against a list of
   445  // strings where any of the input values match at least one value of the condition
   446  // using string suffix match.
   447  type ruleListStrCondSuffixMatchStrInput struct {
   448  	field  *field
   449  	exprs  []*expr
   450  	config *config
   451  }
   452  
   453  // ruleListStrCondRegexMatchStrInput matches an input string against a list of
   454  // strings where any of the input values match at least one value of the condition
   455  // using regular expressions match.
   456  type ruleListStrCondRegexMatchStrInput struct {
   457  	field  *field
   458  	exprs  []*regexp.Regexp
   459  	config *config
   460  }
   461  
   462  // ruleStrCondExactMatchStrInput matches an input string against a string condition
   463  // using exact match.
   464  type ruleStrCondExactMatchStrInput struct {
   465  	field  *field
   466  	expr   *expr
   467  	config *config
   468  }
   469  
   470  // ruleStrCondPartialMatchStrInput matches an input string against a string
   471  // condition using substring match.
   472  type ruleStrCondPartialMatchStrInput struct {
   473  	field  *field
   474  	expr   *expr
   475  	config *config
   476  }
   477  
   478  // ruleStrCondPrefixMatchStrInput matches an input string against a string
   479  // condition using string prefix match.
   480  type ruleStrCondPrefixMatchStrInput struct {
   481  	field  *field
   482  	expr   *expr
   483  	config *config
   484  }
   485  
   486  // ruleStrCondSuffixMatchStrInput matches an input string against a string
   487  // condition using string suffix match.
   488  type ruleStrCondSuffixMatchStrInput struct {
   489  	field  *field
   490  	expr   *expr
   491  	config *config
   492  }
   493  
   494  // ruleStrCondRegexMatchStrInput matches an input string against a string condition
   495  // using regular expressions match.
   496  type ruleStrCondRegexMatchStrInput struct {
   497  	field  *field
   498  	expr   *regexp.Regexp
   499  	config *config
   500  }
   501  
   502  func (c *ruleListStrCondExactNegativeMatchListStrInput) match(ctx context.Context, values interface{}) bool {
   503  	for _, exp := range c.exprs {
   504  		for _, v := range values.([]string) {
   505  			if v == exp.value {
   506  				return false
   507  			}
   508  		}
   509  	}
   510  	return true
   511  }
   512  
   513  func (c *ruleListStrCondPartialNegativeMatchListStrInput) match(ctx context.Context, values interface{}) bool {
   514  	for _, exp := range c.exprs {
   515  		for _, v := range values.([]string) {
   516  			if strings.Contains(v, exp.value) {
   517  				return false
   518  			}
   519  		}
   520  	}
   521  	return true
   522  }
   523  
   524  func (c *ruleListStrCondPrefixNegativeMatchListStrInput) match(ctx context.Context, values interface{}) bool {
   525  	for _, exp := range c.exprs {
   526  		for _, v := range values.([]string) {
   527  			if strings.HasPrefix(v, exp.value) {
   528  				return false
   529  			}
   530  		}
   531  	}
   532  	return true
   533  }
   534  
   535  func (c *ruleListStrCondSuffixNegativeMatchListStrInput) match(ctx context.Context, values interface{}) bool {
   536  	for _, exp := range c.exprs {
   537  		for _, v := range values.([]string) {
   538  			if strings.HasSuffix(v, exp.value) {
   539  				return false
   540  			}
   541  		}
   542  	}
   543  	return true
   544  }
   545  
   546  func (c *ruleListStrCondRegexNegativeMatchListStrInput) match(ctx context.Context, values interface{}) bool {
   547  	if c.config.matchAny {
   548  		for _, exp := range c.exprs {
   549  			for _, v := range values.([]string) {
   550  				if !exp.MatchString(v) {
   551  					return true
   552  				}
   553  			}
   554  		}
   555  		return false
   556  	}
   557  	for _, exp := range c.exprs {
   558  		for _, v := range values.([]string) {
   559  			if exp.MatchString(v) {
   560  				return false
   561  			}
   562  		}
   563  	}
   564  	return true
   565  }
   566  
   567  func (c *ruleStrCondExactNegativeMatchListStrInput) match(ctx context.Context, values interface{}) bool {
   568  	for _, v := range values.([]string) {
   569  		if v == c.expr.value {
   570  			return false
   571  		}
   572  	}
   573  	return true
   574  }
   575  
   576  func (c *ruleStrCondPartialNegativeMatchListStrInput) match(ctx context.Context, values interface{}) bool {
   577  	for _, v := range values.([]string) {
   578  		if strings.Contains(v, c.expr.value) {
   579  			return false
   580  		}
   581  	}
   582  	return true
   583  }
   584  
   585  func (c *ruleStrCondPrefixNegativeMatchListStrInput) match(ctx context.Context, values interface{}) bool {
   586  	for _, v := range values.([]string) {
   587  		if strings.HasPrefix(v, c.expr.value) {
   588  			return false
   589  		}
   590  	}
   591  	return true
   592  }
   593  
   594  func (c *ruleStrCondSuffixNegativeMatchListStrInput) match(ctx context.Context, values interface{}) bool {
   595  	for _, v := range values.([]string) {
   596  		if strings.HasSuffix(v, c.expr.value) {
   597  			return false
   598  		}
   599  	}
   600  	return true
   601  }
   602  
   603  func (c *ruleStrCondRegexNegativeMatchListStrInput) match(ctx context.Context, values interface{}) bool {
   604  	if c.config.matchAny {
   605  		for _, v := range values.([]string) {
   606  			if !c.expr.MatchString(v) {
   607  				return true
   608  			}
   609  		}
   610  		return false
   611  	}
   612  	for _, v := range values.([]string) {
   613  		if c.expr.MatchString(v) {
   614  			return false
   615  		}
   616  	}
   617  	return true
   618  }
   619  
   620  func (c *ruleListStrCondExactNegativeMatchStrInput) match(ctx context.Context, v interface{}) bool {
   621  	for _, exp := range c.exprs {
   622  		if v.(string) == exp.value {
   623  			return false
   624  		}
   625  	}
   626  	return true
   627  }
   628  
   629  func (c *ruleListStrCondPartialNegativeMatchStrInput) match(ctx context.Context, v interface{}) bool {
   630  	for _, exp := range c.exprs {
   631  		if strings.Contains(v.(string), exp.value) {
   632  			return false
   633  		}
   634  	}
   635  	return true
   636  }
   637  
   638  func (c *ruleListStrCondPrefixNegativeMatchStrInput) match(ctx context.Context, v interface{}) bool {
   639  	for _, exp := range c.exprs {
   640  		if strings.HasPrefix(v.(string), exp.value) {
   641  			return false
   642  		}
   643  	}
   644  	return true
   645  }
   646  
   647  func (c *ruleListStrCondSuffixNegativeMatchStrInput) match(ctx context.Context, v interface{}) bool {
   648  	for _, exp := range c.exprs {
   649  		if strings.HasSuffix(v.(string), exp.value) {
   650  			return false
   651  		}
   652  	}
   653  	return true
   654  }
   655  
   656  func (c *ruleListStrCondRegexNegativeMatchStrInput) match(ctx context.Context, v interface{}) bool {
   657  	if c.config.matchAny {
   658  		for _, exp := range c.exprs {
   659  			if !exp.MatchString(v.(string)) {
   660  				return true
   661  			}
   662  		}
   663  		return false
   664  	}
   665  	for _, exp := range c.exprs {
   666  		if exp.MatchString(v.(string)) {
   667  			return false
   668  		}
   669  	}
   670  	return true
   671  }
   672  
   673  func (c *ruleStrCondExactNegativeMatchStrInput) match(ctx context.Context, v interface{}) bool {
   674  	if v.(string) == c.expr.value {
   675  		return false
   676  	}
   677  	return true
   678  }
   679  
   680  func (c *ruleStrCondPartialNegativeMatchStrInput) match(ctx context.Context, v interface{}) bool {
   681  	if strings.Contains(v.(string), c.expr.value) {
   682  		return false
   683  	}
   684  	return true
   685  }
   686  
   687  func (c *ruleStrCondPrefixNegativeMatchStrInput) match(ctx context.Context, v interface{}) bool {
   688  	if strings.HasPrefix(v.(string), c.expr.value) {
   689  		return false
   690  	}
   691  	return true
   692  }
   693  
   694  func (c *ruleStrCondSuffixNegativeMatchStrInput) match(ctx context.Context, v interface{}) bool {
   695  	if strings.HasSuffix(v.(string), c.expr.value) {
   696  		return false
   697  	}
   698  	return true
   699  }
   700  
   701  func (c *ruleStrCondRegexNegativeMatchStrInput) match(ctx context.Context, v interface{}) bool {
   702  	if c.expr.MatchString(v.(string)) {
   703  		return false
   704  	}
   705  	return true
   706  }
   707  
   708  func (c *ruleListStrCondExactMatchListStrInput) match(ctx context.Context, values interface{}) bool {
   709  	for _, exp := range c.exprs {
   710  		for _, v := range values.([]string) {
   711  			if v == exp.value {
   712  				return true
   713  			}
   714  		}
   715  	}
   716  	return false
   717  }
   718  
   719  func (c *ruleListStrCondPartialMatchListStrInput) match(ctx context.Context, values interface{}) bool {
   720  	for _, exp := range c.exprs {
   721  		for _, v := range values.([]string) {
   722  			if strings.Contains(v, exp.value) {
   723  				return true
   724  			}
   725  		}
   726  	}
   727  	return false
   728  }
   729  
   730  func (c *ruleListStrCondPrefixMatchListStrInput) match(ctx context.Context, values interface{}) bool {
   731  	for _, exp := range c.exprs {
   732  		for _, v := range values.([]string) {
   733  			if strings.HasPrefix(v, exp.value) {
   734  				return true
   735  			}
   736  		}
   737  	}
   738  	return false
   739  }
   740  
   741  func (c *ruleListStrCondSuffixMatchListStrInput) match(ctx context.Context, values interface{}) bool {
   742  	for _, exp := range c.exprs {
   743  		for _, v := range values.([]string) {
   744  			if strings.HasSuffix(v, exp.value) {
   745  				return true
   746  			}
   747  		}
   748  	}
   749  	return false
   750  }
   751  
   752  func (c *ruleListStrCondRegexMatchListStrInput) match(ctx context.Context, values interface{}) bool {
   753  	for _, exp := range c.exprs {
   754  		for _, v := range values.([]string) {
   755  			if exp.MatchString(v) {
   756  				return true
   757  			}
   758  		}
   759  	}
   760  	return false
   761  }
   762  
   763  func (c *ruleStrCondExactMatchListStrInput) match(ctx context.Context, values interface{}) bool {
   764  	for _, v := range values.([]string) {
   765  		if v == c.expr.value {
   766  			return true
   767  		}
   768  	}
   769  	return false
   770  }
   771  
   772  func (c *ruleStrCondPartialMatchListStrInput) match(ctx context.Context, values interface{}) bool {
   773  	for _, v := range values.([]string) {
   774  		if strings.Contains(v, c.expr.value) {
   775  			return true
   776  		}
   777  	}
   778  	return false
   779  }
   780  
   781  func (c *ruleStrCondPrefixMatchListStrInput) match(ctx context.Context, values interface{}) bool {
   782  	for _, v := range values.([]string) {
   783  		if strings.HasPrefix(v, c.expr.value) {
   784  			return true
   785  		}
   786  	}
   787  	return false
   788  }
   789  
   790  func (c *ruleStrCondSuffixMatchListStrInput) match(ctx context.Context, values interface{}) bool {
   791  	for _, v := range values.([]string) {
   792  		if strings.HasSuffix(v, c.expr.value) {
   793  			return true
   794  		}
   795  	}
   796  	return false
   797  }
   798  
   799  func (c *ruleStrCondRegexMatchListStrInput) match(ctx context.Context, values interface{}) bool {
   800  	for _, v := range values.([]string) {
   801  		if c.expr.MatchString(v) {
   802  			return true
   803  		}
   804  	}
   805  	return false
   806  }
   807  
   808  func (c *ruleListStrCondExactMatchStrInput) match(ctx context.Context, v interface{}) bool {
   809  	for _, exp := range c.exprs {
   810  		if v.(string) == exp.value {
   811  			return true
   812  		}
   813  	}
   814  	return false
   815  }
   816  
   817  func (c *ruleListStrCondPartialMatchStrInput) match(ctx context.Context, v interface{}) bool {
   818  	for _, exp := range c.exprs {
   819  		if strings.Contains(v.(string), exp.value) {
   820  			return true
   821  		}
   822  	}
   823  	return false
   824  }
   825  
   826  func (c *ruleListStrCondPrefixMatchStrInput) match(ctx context.Context, v interface{}) bool {
   827  	for _, exp := range c.exprs {
   828  		if strings.HasPrefix(v.(string), exp.value) {
   829  			return true
   830  		}
   831  	}
   832  	return false
   833  }
   834  
   835  func (c *ruleListStrCondSuffixMatchStrInput) match(ctx context.Context, v interface{}) bool {
   836  	for _, exp := range c.exprs {
   837  		if strings.HasSuffix(v.(string), exp.value) {
   838  			return true
   839  		}
   840  	}
   841  	return false
   842  }
   843  
   844  func (c *ruleListStrCondRegexMatchStrInput) match(ctx context.Context, v interface{}) bool {
   845  	for _, exp := range c.exprs {
   846  		if exp.MatchString(v.(string)) {
   847  			return true
   848  		}
   849  	}
   850  	return false
   851  }
   852  
   853  func (c *ruleStrCondExactMatchStrInput) match(ctx context.Context, v interface{}) bool {
   854  	if v.(string) == c.expr.value {
   855  		return true
   856  	}
   857  	return false
   858  }
   859  
   860  func (c *ruleStrCondPartialMatchStrInput) match(ctx context.Context, v interface{}) bool {
   861  	if strings.Contains(v.(string), c.expr.value) {
   862  		return true
   863  	}
   864  	return false
   865  }
   866  
   867  func (c *ruleStrCondPrefixMatchStrInput) match(ctx context.Context, v interface{}) bool {
   868  	if strings.HasPrefix(v.(string), c.expr.value) {
   869  		return true
   870  	}
   871  	return false
   872  }
   873  
   874  func (c *ruleStrCondSuffixMatchStrInput) match(ctx context.Context, v interface{}) bool {
   875  	if strings.HasSuffix(v.(string), c.expr.value) {
   876  		return true
   877  	}
   878  	return false
   879  }
   880  
   881  func (c *ruleStrCondRegexMatchStrInput) match(ctx context.Context, v interface{}) bool {
   882  	if c.expr.MatchString(v.(string)) {
   883  		return true
   884  	}
   885  	return false
   886  }
   887  
   888  func (c *ruleListStrCondExactNegativeMatchListStrInput) getConfig(ctx context.Context) *config {
   889  	return c.config
   890  }
   891  
   892  func (c *ruleListStrCondPartialNegativeMatchListStrInput) getConfig(ctx context.Context) *config {
   893  	return c.config
   894  }
   895  
   896  func (c *ruleListStrCondPrefixNegativeMatchListStrInput) getConfig(ctx context.Context) *config {
   897  	return c.config
   898  }
   899  
   900  func (c *ruleListStrCondSuffixNegativeMatchListStrInput) getConfig(ctx context.Context) *config {
   901  	return c.config
   902  }
   903  
   904  func (c *ruleListStrCondRegexNegativeMatchListStrInput) getConfig(ctx context.Context) *config {
   905  	return c.config
   906  }
   907  
   908  func (c *ruleStrCondExactNegativeMatchListStrInput) getConfig(ctx context.Context) *config {
   909  	return c.config
   910  }
   911  
   912  func (c *ruleStrCondPartialNegativeMatchListStrInput) getConfig(ctx context.Context) *config {
   913  	return c.config
   914  }
   915  
   916  func (c *ruleStrCondPrefixNegativeMatchListStrInput) getConfig(ctx context.Context) *config {
   917  	return c.config
   918  }
   919  
   920  func (c *ruleStrCondSuffixNegativeMatchListStrInput) getConfig(ctx context.Context) *config {
   921  	return c.config
   922  }
   923  
   924  func (c *ruleStrCondRegexNegativeMatchListStrInput) getConfig(ctx context.Context) *config {
   925  	return c.config
   926  }
   927  
   928  func (c *ruleListStrCondExactNegativeMatchStrInput) getConfig(ctx context.Context) *config {
   929  	return c.config
   930  }
   931  
   932  func (c *ruleListStrCondPartialNegativeMatchStrInput) getConfig(ctx context.Context) *config {
   933  	return c.config
   934  }
   935  
   936  func (c *ruleListStrCondPrefixNegativeMatchStrInput) getConfig(ctx context.Context) *config {
   937  	return c.config
   938  }
   939  
   940  func (c *ruleListStrCondSuffixNegativeMatchStrInput) getConfig(ctx context.Context) *config {
   941  	return c.config
   942  }
   943  
   944  func (c *ruleListStrCondRegexNegativeMatchStrInput) getConfig(ctx context.Context) *config {
   945  	return c.config
   946  }
   947  
   948  func (c *ruleStrCondExactNegativeMatchStrInput) getConfig(ctx context.Context) *config {
   949  	return c.config
   950  }
   951  
   952  func (c *ruleStrCondPartialNegativeMatchStrInput) getConfig(ctx context.Context) *config {
   953  	return c.config
   954  }
   955  
   956  func (c *ruleStrCondPrefixNegativeMatchStrInput) getConfig(ctx context.Context) *config {
   957  	return c.config
   958  }
   959  
   960  func (c *ruleStrCondSuffixNegativeMatchStrInput) getConfig(ctx context.Context) *config {
   961  	return c.config
   962  }
   963  
   964  func (c *ruleStrCondRegexNegativeMatchStrInput) getConfig(ctx context.Context) *config {
   965  	return c.config
   966  }
   967  
   968  func (c *ruleListStrCondExactMatchListStrInput) getConfig(ctx context.Context) *config {
   969  	return c.config
   970  }
   971  
   972  func (c *ruleListStrCondPartialMatchListStrInput) getConfig(ctx context.Context) *config {
   973  	return c.config
   974  }
   975  
   976  func (c *ruleListStrCondPrefixMatchListStrInput) getConfig(ctx context.Context) *config {
   977  	return c.config
   978  }
   979  
   980  func (c *ruleListStrCondSuffixMatchListStrInput) getConfig(ctx context.Context) *config {
   981  	return c.config
   982  }
   983  
   984  func (c *ruleListStrCondRegexMatchListStrInput) getConfig(ctx context.Context) *config {
   985  	return c.config
   986  }
   987  
   988  func (c *ruleStrCondExactMatchListStrInput) getConfig(ctx context.Context) *config {
   989  	return c.config
   990  }
   991  
   992  func (c *ruleStrCondPartialMatchListStrInput) getConfig(ctx context.Context) *config {
   993  	return c.config
   994  }
   995  
   996  func (c *ruleStrCondPrefixMatchListStrInput) getConfig(ctx context.Context) *config {
   997  	return c.config
   998  }
   999  
  1000  func (c *ruleStrCondSuffixMatchListStrInput) getConfig(ctx context.Context) *config {
  1001  	return c.config
  1002  }
  1003  
  1004  func (c *ruleStrCondRegexMatchListStrInput) getConfig(ctx context.Context) *config {
  1005  	return c.config
  1006  }
  1007  
  1008  func (c *ruleListStrCondExactMatchStrInput) getConfig(ctx context.Context) *config {
  1009  	return c.config
  1010  }
  1011  
  1012  func (c *ruleListStrCondPartialMatchStrInput) getConfig(ctx context.Context) *config {
  1013  	return c.config
  1014  }
  1015  
  1016  func (c *ruleListStrCondPrefixMatchStrInput) getConfig(ctx context.Context) *config {
  1017  	return c.config
  1018  }
  1019  
  1020  func (c *ruleListStrCondSuffixMatchStrInput) getConfig(ctx context.Context) *config {
  1021  	return c.config
  1022  }
  1023  
  1024  func (c *ruleListStrCondRegexMatchStrInput) getConfig(ctx context.Context) *config {
  1025  	return c.config
  1026  }
  1027  
  1028  func (c *ruleStrCondExactMatchStrInput) getConfig(ctx context.Context) *config {
  1029  	return c.config
  1030  }
  1031  
  1032  func (c *ruleStrCondPartialMatchStrInput) getConfig(ctx context.Context) *config {
  1033  	return c.config
  1034  }
  1035  
  1036  func (c *ruleStrCondPrefixMatchStrInput) getConfig(ctx context.Context) *config {
  1037  	return c.config
  1038  }
  1039  
  1040  func (c *ruleStrCondSuffixMatchStrInput) getConfig(ctx context.Context) *config {
  1041  	return c.config
  1042  }
  1043  
  1044  func (c *ruleStrCondRegexMatchStrInput) getConfig(ctx context.Context) *config {
  1045  	return c.config
  1046  }
  1047  
  1048  func init() {
  1049  	matchWithStrategyRgx = regexp.MustCompile(`^\s*((?P<negative_match>no)\s)?((?P<match_strategy>exact|partial|prefix|suffix|regex)\s)?match\s*((?P<match_any>any)\s)?`)
  1050  	matchFieldRgx = regexp.MustCompile(`^\s*field\s+(?P<field_name>\S+)\s+(?P<field_exists>exists|not\s+exists)\s*$`)
  1051  }
  1052  
  1053  func (cfg *config) AsMap() map[string]interface{} {
  1054  	m := make(map[string]interface{})
  1055  	m["field"] = cfg.field
  1056  	m["match_strategy"] = getMatchStrategyName(cfg.matchStrategy)
  1057  	if len(cfg.values) > 0 {
  1058  		m["values"] = cfg.values
  1059  	}
  1060  	m["regex_enabled"] = cfg.regexEnabled
  1061  	m["always_true"] = cfg.alwaysTrue
  1062  	m["expr_data_type"] = getDataTypeName(cfg.exprDataType)
  1063  	m["input_data_type"] = getDataTypeName(cfg.inputDataType)
  1064  	m["condition_type"] = cfg.conditionType
  1065  	m["match_any"] = cfg.matchAny
  1066  	return m
  1067  }
  1068  
  1069  func extractMatchStrategy(s string) fieldMatchStrategy {
  1070  	switch s {
  1071  	case "", "exact":
  1072  		return fieldMatchExact
  1073  	case "partial":
  1074  		return fieldMatchPartial
  1075  	case "prefix":
  1076  		return fieldMatchPrefix
  1077  	case "suffix":
  1078  		return fieldMatchSuffix
  1079  	case "regex":
  1080  		return fieldMatchRegex
  1081  	case "exists":
  1082  		return fieldFound
  1083  	case "not exists":
  1084  		return fieldNotFound
  1085  	}
  1086  	return fieldMatchUnknown
  1087  }
  1088  
  1089  func extractFieldNameValues(arr []string) (string, []string) {
  1090  	var k string
  1091  	var v []string
  1092  	var matchFound, fieldFound bool
  1093  	for i, a := range arr {
  1094  		if a == "match" {
  1095  			matchFound = true
  1096  			continue
  1097  		}
  1098  		if !matchFound {
  1099  			continue
  1100  		}
  1101  		if a == "any" && arr[i-1] == "match" {
  1102  			continue
  1103  		}
  1104  		if !fieldFound {
  1105  			k = a
  1106  			fieldFound = true
  1107  			continue
  1108  		}
  1109  		v = append(v, a)
  1110  	}
  1111  	if fieldFound {
  1112  		if alias, exists := inputDataAliases[k]; exists {
  1113  			k = alias
  1114  		}
  1115  	}
  1116  	return k, v
  1117  }
  1118  
  1119  func validateFieldNameValues(line, k string, v []string) error {
  1120  	if k == "" {
  1121  		return errors.ErrACLRuleConditionSyntaxMatchFieldNotFound.WithArgs(line)
  1122  	}
  1123  	if len(v) == 0 {
  1124  		return errors.ErrACLRuleConditionSyntaxMatchValueNotFound.WithArgs(line)
  1125  	}
  1126  	for _, s := range v {
  1127  		switch s {
  1128  		case "exact", "partial", "prefix", "suffix", "regex":
  1129  			return errors.ErrACLRuleConditionSyntaxReservedWordUsage.WithArgs(s, line)
  1130  		}
  1131  	}
  1132  	return nil
  1133  }
  1134  
  1135  func extractCondDataType(line string, inputDataType dataType, values []string) (dataType, error) {
  1136  	switch inputDataType {
  1137  	case dataTypeListStr, dataTypeStr:
  1138  		if len(values) == 1 {
  1139  			return dataTypeStr, nil
  1140  		}
  1141  		return dataTypeListStr, nil
  1142  	case dataTypeAny:
  1143  		return dataTypeAny, nil
  1144  	}
  1145  	return dataTypeUnknown, errors.ErrACLRuleConditionSyntaxCondDataType.WithArgs(line)
  1146  }
  1147  
  1148  func extractInputDataType(fieldName string) dataType {
  1149  	if tp, exists := inputDataTypes[fieldName]; exists {
  1150  		return tp
  1151  	}
  1152  	return dataTypeAny
  1153  }
  1154  
  1155  func newACLRuleCondition(ctx context.Context, tokens []string) (aclRuleCondition, error) {
  1156  	var inputDataType, condDataType dataType
  1157  	var matchStrategy fieldMatchStrategy
  1158  	var negativeMatch bool
  1159  	var fieldName string
  1160  	var values []string
  1161  	var matchAny bool
  1162  
  1163  	line := strings.Join(tokens, " ")
  1164  
  1165  	switch {
  1166  	case line == "match any":
  1167  		matchStrategy = fieldMatchAlways
  1168  		fieldName = "exp"
  1169  		inputDataType = dataTypeAny
  1170  		condDataType = dataTypeAny
  1171  	case matchFieldRgx.Match([]byte(line)):
  1172  		matched := matchFieldRgx.FindStringSubmatch(line)
  1173  		for i, k := range matchFieldRgx.SubexpNames() {
  1174  			if i > 0 && i <= len(matched) {
  1175  				switch k {
  1176  				case "field_exists":
  1177  					matchStrategy = extractMatchStrategy(matched[i])
  1178  				case "field_name":
  1179  					fieldName = matched[i]
  1180  					if alias, exists := inputDataAliases[fieldName]; exists {
  1181  						fieldName = alias
  1182  					}
  1183  				}
  1184  			}
  1185  		}
  1186  		inputDataType = dataTypeAny
  1187  		condDataType = dataTypeAny
  1188  	case matchWithStrategyRgx.Match([]byte(line)):
  1189  		matched := matchWithStrategyRgx.FindStringSubmatch(line)
  1190  		for i, k := range matchWithStrategyRgx.SubexpNames() {
  1191  			if i > 0 && i <= len(matched) {
  1192  				switch k {
  1193  				case "match_strategy":
  1194  					matchStrategy = extractMatchStrategy(matched[i])
  1195  					if matchStrategy == fieldMatchUnknown {
  1196  						matchStrategy = fieldMatchExact
  1197  					}
  1198  				case "negative_match":
  1199  					if matched[i] == "no" {
  1200  						negativeMatch = true
  1201  					}
  1202  				case "match_any":
  1203  					if matched[i] == "any" {
  1204  						matchAny = true
  1205  					}
  1206  				}
  1207  			}
  1208  		}
  1209  		fieldName, values = extractFieldNameValues(tokens)
  1210  	default:
  1211  		return nil, errors.ErrACLRuleConditionSyntaxMatchNotFound.WithArgs(line)
  1212  	}
  1213  
  1214  	if matchStrategy == fieldMatchUnknown {
  1215  		return nil, errors.ErrACLRuleConditionSyntaxStrategyNotFound.WithArgs(line)
  1216  	}
  1217  
  1218  	switch matchStrategy {
  1219  	case fieldMatchAlways, fieldFound, fieldNotFound:
  1220  	default:
  1221  		if err := validateFieldNameValues(line, fieldName, values); err != nil {
  1222  			return nil, err
  1223  		}
  1224  		inputDataType = extractInputDataType(fieldName)
  1225  		var err error
  1226  		condDataType, err = extractCondDataType(line, inputDataType, values)
  1227  		if err != nil {
  1228  			return nil, err
  1229  		}
  1230  	}
  1231  
  1232  	switch {
  1233  	case matchStrategy == fieldFound:
  1234  		// Match: Field Found, Condition Type: Any, Input Type: Any
  1235  		c := &ruleCondFieldFound{
  1236  			config: &config{
  1237  				field:         fieldName,
  1238  				matchStrategy: fieldFound,
  1239  				values:        values,
  1240  				regexEnabled:  false,
  1241  				alwaysTrue:    false,
  1242  				exprDataType:  inputDataType,
  1243  				inputDataType: condDataType,
  1244  				conditionType: `ruleCondFieldFound`,
  1245  				matchAny:      matchAny,
  1246  			},
  1247  			field: &field{
  1248  				name:   fieldName,
  1249  				length: len(fieldName),
  1250  			},
  1251  			exprs: []*expr{},
  1252  		}
  1253  		return c, nil
  1254  	case matchStrategy == fieldNotFound:
  1255  		// Match: Field Found, Condition Type: Any, Input Type: Any
  1256  		c := &ruleCondFieldNotFound{
  1257  			config: &config{
  1258  				field:         fieldName,
  1259  				matchStrategy: fieldNotFound,
  1260  				values:        values,
  1261  				regexEnabled:  false,
  1262  				alwaysTrue:    false,
  1263  				exprDataType:  inputDataType,
  1264  				inputDataType: condDataType,
  1265  				conditionType: `ruleCondFieldNotFound`,
  1266  				matchAny:      matchAny,
  1267  			},
  1268  			field: &field{
  1269  				name:   fieldName,
  1270  				length: len(fieldName),
  1271  			},
  1272  			exprs: []*expr{},
  1273  		}
  1274  		return c, nil
  1275  	case matchStrategy == fieldMatchAlways:
  1276  		// Match: Always, Condition Type: Any, Input Type: Any
  1277  		c := &ruleAnyCondAlwaysMatchAnyInput{
  1278  			config: &config{
  1279  				field:         fieldName,
  1280  				matchStrategy: fieldMatchAlways,
  1281  				values:        values,
  1282  				regexEnabled:  false,
  1283  				alwaysTrue:    true,
  1284  				exprDataType:  inputDataType,
  1285  				inputDataType: condDataType,
  1286  				conditionType: `ruleAnyCondAlwaysMatchAnyInput`,
  1287  				matchAny:      matchAny,
  1288  			},
  1289  			field: &field{
  1290  				name:   fieldName,
  1291  				length: len(fieldName),
  1292  			},
  1293  			exprs: []*expr{},
  1294  		}
  1295  		return c, nil
  1296  	case negativeMatch && matchStrategy == fieldMatchExact && condDataType == dataTypeListStr && inputDataType == dataTypeListStr:
  1297  		// No match: Exact, Condition Type: ListStr, Input Type: ListStr
  1298  		c := &ruleListStrCondExactNegativeMatchListStrInput{
  1299  			config: &config{
  1300  				field:         fieldName,
  1301  				matchStrategy: fieldMatchExact,
  1302  				values:        values,
  1303  				regexEnabled:  false,
  1304  				alwaysTrue:    false,
  1305  				exprDataType:  condDataType,
  1306  				inputDataType: inputDataType,
  1307  				conditionType: `ruleListStrCondExactNegativeMatchListStrInput`,
  1308  				matchAny:      matchAny,
  1309  			},
  1310  			field: &field{
  1311  				name:   fieldName,
  1312  				length: len(fieldName),
  1313  			},
  1314  		}
  1315  		c.exprs = []*expr{}
  1316  		for _, val := range values {
  1317  			c.exprs = append(c.exprs, &expr{
  1318  				value: val,
  1319  			})
  1320  		}
  1321  		return c, nil
  1322  	case negativeMatch && matchStrategy == fieldMatchPartial && condDataType == dataTypeListStr && inputDataType == dataTypeListStr:
  1323  		// No match: Partial, Condition Type: ListStr, Input Type: ListStr
  1324  		c := &ruleListStrCondPartialNegativeMatchListStrInput{
  1325  			config: &config{
  1326  				field:         fieldName,
  1327  				matchStrategy: fieldMatchPartial,
  1328  				values:        values,
  1329  				regexEnabled:  false,
  1330  				alwaysTrue:    false,
  1331  				exprDataType:  condDataType,
  1332  				inputDataType: inputDataType,
  1333  				conditionType: `ruleListStrCondPartialNegativeMatchListStrInput`,
  1334  				matchAny:      matchAny,
  1335  			},
  1336  			field: &field{
  1337  				name:   fieldName,
  1338  				length: len(fieldName),
  1339  			},
  1340  		}
  1341  		c.exprs = []*expr{}
  1342  		for _, val := range values {
  1343  			c.exprs = append(c.exprs, &expr{
  1344  				value: val,
  1345  			})
  1346  		}
  1347  		return c, nil
  1348  	case negativeMatch && matchStrategy == fieldMatchPrefix && condDataType == dataTypeListStr && inputDataType == dataTypeListStr:
  1349  		// No match: Prefix, Condition Type: ListStr, Input Type: ListStr
  1350  		c := &ruleListStrCondPrefixNegativeMatchListStrInput{
  1351  			config: &config{
  1352  				field:         fieldName,
  1353  				matchStrategy: fieldMatchPrefix,
  1354  				values:        values,
  1355  				regexEnabled:  false,
  1356  				alwaysTrue:    false,
  1357  				exprDataType:  condDataType,
  1358  				inputDataType: inputDataType,
  1359  				conditionType: `ruleListStrCondPrefixNegativeMatchListStrInput`,
  1360  				matchAny:      matchAny,
  1361  			},
  1362  			field: &field{
  1363  				name:   fieldName,
  1364  				length: len(fieldName),
  1365  			},
  1366  		}
  1367  		c.exprs = []*expr{}
  1368  		for _, val := range values {
  1369  			c.exprs = append(c.exprs, &expr{
  1370  				value: val,
  1371  			})
  1372  		}
  1373  		return c, nil
  1374  	case negativeMatch && matchStrategy == fieldMatchSuffix && condDataType == dataTypeListStr && inputDataType == dataTypeListStr:
  1375  		// No match: Suffix, Condition Type: ListStr, Input Type: ListStr
  1376  		c := &ruleListStrCondSuffixNegativeMatchListStrInput{
  1377  			config: &config{
  1378  				field:         fieldName,
  1379  				matchStrategy: fieldMatchSuffix,
  1380  				values:        values,
  1381  				regexEnabled:  false,
  1382  				alwaysTrue:    false,
  1383  				exprDataType:  condDataType,
  1384  				inputDataType: inputDataType,
  1385  				conditionType: `ruleListStrCondSuffixNegativeMatchListStrInput`,
  1386  				matchAny:      matchAny,
  1387  			},
  1388  			field: &field{
  1389  				name:   fieldName,
  1390  				length: len(fieldName),
  1391  			},
  1392  		}
  1393  		c.exprs = []*expr{}
  1394  		for _, val := range values {
  1395  			c.exprs = append(c.exprs, &expr{
  1396  				value: val,
  1397  			})
  1398  		}
  1399  		return c, nil
  1400  	case negativeMatch && matchStrategy == fieldMatchRegex && condDataType == dataTypeListStr && inputDataType == dataTypeListStr:
  1401  		// No match: Regex, Condition Type: ListStr, Input Type: ListStr
  1402  		c := &ruleListStrCondRegexNegativeMatchListStrInput{
  1403  			config: &config{
  1404  				field:         fieldName,
  1405  				matchStrategy: fieldMatchRegex,
  1406  				values:        values,
  1407  				regexEnabled:  true,
  1408  				alwaysTrue:    false,
  1409  				exprDataType:  condDataType,
  1410  				inputDataType: inputDataType,
  1411  				conditionType: `ruleListStrCondRegexNegativeMatchListStrInput`,
  1412  				matchAny:      matchAny,
  1413  			},
  1414  			field: &field{
  1415  				name:   fieldName,
  1416  				length: len(fieldName),
  1417  			},
  1418  		}
  1419  		c.exprs = []*regexp.Regexp{}
  1420  		for _, val := range values {
  1421  			re, err := regexp.Compile(val)
  1422  			if err != nil {
  1423  				return nil, err
  1424  			}
  1425  			c.exprs = append(c.exprs, re)
  1426  		}
  1427  		return c, nil
  1428  	case negativeMatch && matchStrategy == fieldMatchExact && condDataType == dataTypeStr && inputDataType == dataTypeListStr:
  1429  		// No match: Exact, Condition Type: Str, Input Type: ListStr
  1430  		c := &ruleStrCondExactNegativeMatchListStrInput{
  1431  			config: &config{
  1432  				field:         fieldName,
  1433  				matchStrategy: fieldMatchExact,
  1434  				values:        values,
  1435  				regexEnabled:  false,
  1436  				alwaysTrue:    false,
  1437  				exprDataType:  condDataType,
  1438  				inputDataType: inputDataType,
  1439  				conditionType: `ruleStrCondExactNegativeMatchListStrInput`,
  1440  				matchAny:      matchAny,
  1441  			},
  1442  			field: &field{
  1443  				name:   fieldName,
  1444  				length: len(fieldName),
  1445  			},
  1446  		}
  1447  		c.expr = &expr{
  1448  			value: values[0],
  1449  		}
  1450  		return c, nil
  1451  	case negativeMatch && matchStrategy == fieldMatchPartial && condDataType == dataTypeStr && inputDataType == dataTypeListStr:
  1452  		// No match: Partial, Condition Type: Str, Input Type: ListStr
  1453  		c := &ruleStrCondPartialNegativeMatchListStrInput{
  1454  			config: &config{
  1455  				field:         fieldName,
  1456  				matchStrategy: fieldMatchPartial,
  1457  				values:        values,
  1458  				regexEnabled:  false,
  1459  				alwaysTrue:    false,
  1460  				exprDataType:  condDataType,
  1461  				inputDataType: inputDataType,
  1462  				conditionType: `ruleStrCondPartialNegativeMatchListStrInput`,
  1463  				matchAny:      matchAny,
  1464  			},
  1465  			field: &field{
  1466  				name:   fieldName,
  1467  				length: len(fieldName),
  1468  			},
  1469  		}
  1470  		c.expr = &expr{
  1471  			value: values[0],
  1472  		}
  1473  		return c, nil
  1474  	case negativeMatch && matchStrategy == fieldMatchPrefix && condDataType == dataTypeStr && inputDataType == dataTypeListStr:
  1475  		// No match: Prefix, Condition Type: Str, Input Type: ListStr
  1476  		c := &ruleStrCondPrefixNegativeMatchListStrInput{
  1477  			config: &config{
  1478  				field:         fieldName,
  1479  				matchStrategy: fieldMatchPrefix,
  1480  				values:        values,
  1481  				regexEnabled:  false,
  1482  				alwaysTrue:    false,
  1483  				exprDataType:  condDataType,
  1484  				inputDataType: inputDataType,
  1485  				conditionType: `ruleStrCondPrefixNegativeMatchListStrInput`,
  1486  				matchAny:      matchAny,
  1487  			},
  1488  			field: &field{
  1489  				name:   fieldName,
  1490  				length: len(fieldName),
  1491  			},
  1492  		}
  1493  		c.expr = &expr{
  1494  			value: values[0],
  1495  		}
  1496  		return c, nil
  1497  	case negativeMatch && matchStrategy == fieldMatchSuffix && condDataType == dataTypeStr && inputDataType == dataTypeListStr:
  1498  		// No match: Suffix, Condition Type: Str, Input Type: ListStr
  1499  		c := &ruleStrCondSuffixNegativeMatchListStrInput{
  1500  			config: &config{
  1501  				field:         fieldName,
  1502  				matchStrategy: fieldMatchSuffix,
  1503  				values:        values,
  1504  				regexEnabled:  false,
  1505  				alwaysTrue:    false,
  1506  				exprDataType:  condDataType,
  1507  				inputDataType: inputDataType,
  1508  				conditionType: `ruleStrCondSuffixNegativeMatchListStrInput`,
  1509  				matchAny:      matchAny,
  1510  			},
  1511  			field: &field{
  1512  				name:   fieldName,
  1513  				length: len(fieldName),
  1514  			},
  1515  		}
  1516  		c.expr = &expr{
  1517  			value: values[0],
  1518  		}
  1519  		return c, nil
  1520  	case negativeMatch && matchStrategy == fieldMatchRegex && condDataType == dataTypeStr && inputDataType == dataTypeListStr:
  1521  		// No match: Regex, Condition Type: Str, Input Type: ListStr
  1522  		c := &ruleStrCondRegexNegativeMatchListStrInput{
  1523  			config: &config{
  1524  				field:         fieldName,
  1525  				matchStrategy: fieldMatchRegex,
  1526  				values:        values,
  1527  				regexEnabled:  true,
  1528  				alwaysTrue:    false,
  1529  				exprDataType:  condDataType,
  1530  				inputDataType: inputDataType,
  1531  				conditionType: `ruleStrCondRegexNegativeMatchListStrInput`,
  1532  				matchAny:      matchAny,
  1533  			},
  1534  			field: &field{
  1535  				name:   fieldName,
  1536  				length: len(fieldName),
  1537  			},
  1538  		}
  1539  		re, err := regexp.Compile(values[0])
  1540  		if err != nil {
  1541  			return nil, err
  1542  		}
  1543  		c.expr = re
  1544  		return c, nil
  1545  	case negativeMatch && matchStrategy == fieldMatchExact && condDataType == dataTypeListStr && inputDataType == dataTypeStr:
  1546  		// No match: Exact, Condition Type: ListStr, Input Type: Str
  1547  		c := &ruleListStrCondExactNegativeMatchStrInput{
  1548  			config: &config{
  1549  				field:         fieldName,
  1550  				matchStrategy: fieldMatchExact,
  1551  				values:        values,
  1552  				regexEnabled:  false,
  1553  				alwaysTrue:    false,
  1554  				exprDataType:  condDataType,
  1555  				inputDataType: inputDataType,
  1556  				conditionType: `ruleListStrCondExactNegativeMatchStrInput`,
  1557  				matchAny:      matchAny,
  1558  			},
  1559  			field: &field{
  1560  				name:   fieldName,
  1561  				length: len(fieldName),
  1562  			},
  1563  		}
  1564  		c.exprs = []*expr{}
  1565  		for _, val := range values {
  1566  			c.exprs = append(c.exprs, &expr{
  1567  				value: val,
  1568  			})
  1569  		}
  1570  		return c, nil
  1571  	case negativeMatch && matchStrategy == fieldMatchPartial && condDataType == dataTypeListStr && inputDataType == dataTypeStr:
  1572  		// No match: Partial, Condition Type: ListStr, Input Type: Str
  1573  		c := &ruleListStrCondPartialNegativeMatchStrInput{
  1574  			config: &config{
  1575  				field:         fieldName,
  1576  				matchStrategy: fieldMatchPartial,
  1577  				values:        values,
  1578  				regexEnabled:  false,
  1579  				alwaysTrue:    false,
  1580  				exprDataType:  condDataType,
  1581  				inputDataType: inputDataType,
  1582  				conditionType: `ruleListStrCondPartialNegativeMatchStrInput`,
  1583  				matchAny:      matchAny,
  1584  			},
  1585  			field: &field{
  1586  				name:   fieldName,
  1587  				length: len(fieldName),
  1588  			},
  1589  		}
  1590  		c.exprs = []*expr{}
  1591  		for _, val := range values {
  1592  			c.exprs = append(c.exprs, &expr{
  1593  				value: val,
  1594  			})
  1595  		}
  1596  		return c, nil
  1597  	case negativeMatch && matchStrategy == fieldMatchPrefix && condDataType == dataTypeListStr && inputDataType == dataTypeStr:
  1598  		// No match: Prefix, Condition Type: ListStr, Input Type: Str
  1599  		c := &ruleListStrCondPrefixNegativeMatchStrInput{
  1600  			config: &config{
  1601  				field:         fieldName,
  1602  				matchStrategy: fieldMatchPrefix,
  1603  				values:        values,
  1604  				regexEnabled:  false,
  1605  				alwaysTrue:    false,
  1606  				exprDataType:  condDataType,
  1607  				inputDataType: inputDataType,
  1608  				conditionType: `ruleListStrCondPrefixNegativeMatchStrInput`,
  1609  				matchAny:      matchAny,
  1610  			},
  1611  			field: &field{
  1612  				name:   fieldName,
  1613  				length: len(fieldName),
  1614  			},
  1615  		}
  1616  		c.exprs = []*expr{}
  1617  		for _, val := range values {
  1618  			c.exprs = append(c.exprs, &expr{
  1619  				value: val,
  1620  			})
  1621  		}
  1622  		return c, nil
  1623  	case negativeMatch && matchStrategy == fieldMatchSuffix && condDataType == dataTypeListStr && inputDataType == dataTypeStr:
  1624  		// No match: Suffix, Condition Type: ListStr, Input Type: Str
  1625  		c := &ruleListStrCondSuffixNegativeMatchStrInput{
  1626  			config: &config{
  1627  				field:         fieldName,
  1628  				matchStrategy: fieldMatchSuffix,
  1629  				values:        values,
  1630  				regexEnabled:  false,
  1631  				alwaysTrue:    false,
  1632  				exprDataType:  condDataType,
  1633  				inputDataType: inputDataType,
  1634  				conditionType: `ruleListStrCondSuffixNegativeMatchStrInput`,
  1635  				matchAny:      matchAny,
  1636  			},
  1637  			field: &field{
  1638  				name:   fieldName,
  1639  				length: len(fieldName),
  1640  			},
  1641  		}
  1642  		c.exprs = []*expr{}
  1643  		for _, val := range values {
  1644  			c.exprs = append(c.exprs, &expr{
  1645  				value: val,
  1646  			})
  1647  		}
  1648  		return c, nil
  1649  	case negativeMatch && matchStrategy == fieldMatchRegex && condDataType == dataTypeListStr && inputDataType == dataTypeStr:
  1650  		// No match: Regex, Condition Type: ListStr, Input Type: Str
  1651  		c := &ruleListStrCondRegexNegativeMatchStrInput{
  1652  			config: &config{
  1653  				field:         fieldName,
  1654  				matchStrategy: fieldMatchRegex,
  1655  				values:        values,
  1656  				regexEnabled:  true,
  1657  				alwaysTrue:    false,
  1658  				exprDataType:  condDataType,
  1659  				inputDataType: inputDataType,
  1660  				conditionType: `ruleListStrCondRegexNegativeMatchStrInput`,
  1661  				matchAny:      matchAny,
  1662  			},
  1663  			field: &field{
  1664  				name:   fieldName,
  1665  				length: len(fieldName),
  1666  			},
  1667  		}
  1668  		c.exprs = []*regexp.Regexp{}
  1669  		for _, val := range values {
  1670  			re, err := regexp.Compile(val)
  1671  			if err != nil {
  1672  				return nil, err
  1673  			}
  1674  			c.exprs = append(c.exprs, re)
  1675  		}
  1676  		return c, nil
  1677  	case negativeMatch && matchStrategy == fieldMatchExact && condDataType == dataTypeStr && inputDataType == dataTypeStr:
  1678  		// No match: Exact, Condition Type: Str, Input Type: Str
  1679  		c := &ruleStrCondExactNegativeMatchStrInput{
  1680  			config: &config{
  1681  				field:         fieldName,
  1682  				matchStrategy: fieldMatchExact,
  1683  				values:        values,
  1684  				regexEnabled:  false,
  1685  				alwaysTrue:    false,
  1686  				exprDataType:  condDataType,
  1687  				inputDataType: inputDataType,
  1688  				conditionType: `ruleStrCondExactNegativeMatchStrInput`,
  1689  				matchAny:      matchAny,
  1690  			},
  1691  			field: &field{
  1692  				name:   fieldName,
  1693  				length: len(fieldName),
  1694  			},
  1695  		}
  1696  		c.expr = &expr{
  1697  			value: values[0],
  1698  		}
  1699  		return c, nil
  1700  	case negativeMatch && matchStrategy == fieldMatchPartial && condDataType == dataTypeStr && inputDataType == dataTypeStr:
  1701  		// No match: Partial, Condition Type: Str, Input Type: Str
  1702  		c := &ruleStrCondPartialNegativeMatchStrInput{
  1703  			config: &config{
  1704  				field:         fieldName,
  1705  				matchStrategy: fieldMatchPartial,
  1706  				values:        values,
  1707  				regexEnabled:  false,
  1708  				alwaysTrue:    false,
  1709  				exprDataType:  condDataType,
  1710  				inputDataType: inputDataType,
  1711  				conditionType: `ruleStrCondPartialNegativeMatchStrInput`,
  1712  				matchAny:      matchAny,
  1713  			},
  1714  			field: &field{
  1715  				name:   fieldName,
  1716  				length: len(fieldName),
  1717  			},
  1718  		}
  1719  		c.expr = &expr{
  1720  			value: values[0],
  1721  		}
  1722  		return c, nil
  1723  	case negativeMatch && matchStrategy == fieldMatchPrefix && condDataType == dataTypeStr && inputDataType == dataTypeStr:
  1724  		// No match: Prefix, Condition Type: Str, Input Type: Str
  1725  		c := &ruleStrCondPrefixNegativeMatchStrInput{
  1726  			config: &config{
  1727  				field:         fieldName,
  1728  				matchStrategy: fieldMatchPrefix,
  1729  				values:        values,
  1730  				regexEnabled:  false,
  1731  				alwaysTrue:    false,
  1732  				exprDataType:  condDataType,
  1733  				inputDataType: inputDataType,
  1734  				conditionType: `ruleStrCondPrefixNegativeMatchStrInput`,
  1735  				matchAny:      matchAny,
  1736  			},
  1737  			field: &field{
  1738  				name:   fieldName,
  1739  				length: len(fieldName),
  1740  			},
  1741  		}
  1742  		c.expr = &expr{
  1743  			value: values[0],
  1744  		}
  1745  		return c, nil
  1746  	case negativeMatch && matchStrategy == fieldMatchSuffix && condDataType == dataTypeStr && inputDataType == dataTypeStr:
  1747  		// No match: Suffix, Condition Type: Str, Input Type: Str
  1748  		c := &ruleStrCondSuffixNegativeMatchStrInput{
  1749  			config: &config{
  1750  				field:         fieldName,
  1751  				matchStrategy: fieldMatchSuffix,
  1752  				values:        values,
  1753  				regexEnabled:  false,
  1754  				alwaysTrue:    false,
  1755  				exprDataType:  condDataType,
  1756  				inputDataType: inputDataType,
  1757  				conditionType: `ruleStrCondSuffixNegativeMatchStrInput`,
  1758  				matchAny:      matchAny,
  1759  			},
  1760  			field: &field{
  1761  				name:   fieldName,
  1762  				length: len(fieldName),
  1763  			},
  1764  		}
  1765  		c.expr = &expr{
  1766  			value: values[0],
  1767  		}
  1768  		return c, nil
  1769  	case negativeMatch && matchStrategy == fieldMatchRegex && condDataType == dataTypeStr && inputDataType == dataTypeStr:
  1770  		// No match: Regex, Condition Type: Str, Input Type: Str
  1771  		c := &ruleStrCondRegexNegativeMatchStrInput{
  1772  			config: &config{
  1773  				field:         fieldName,
  1774  				matchStrategy: fieldMatchRegex,
  1775  				values:        values,
  1776  				regexEnabled:  true,
  1777  				alwaysTrue:    false,
  1778  				exprDataType:  condDataType,
  1779  				inputDataType: inputDataType,
  1780  				conditionType: `ruleStrCondRegexNegativeMatchStrInput`,
  1781  				matchAny:      matchAny,
  1782  			},
  1783  			field: &field{
  1784  				name:   fieldName,
  1785  				length: len(fieldName),
  1786  			},
  1787  		}
  1788  		re, err := regexp.Compile(values[0])
  1789  		if err != nil {
  1790  			return nil, err
  1791  		}
  1792  		c.expr = re
  1793  		return c, nil
  1794  	case matchStrategy == fieldMatchExact && condDataType == dataTypeListStr && inputDataType == dataTypeListStr:
  1795  		// Match: Exact, Condition Type: ListStr, Input Type: ListStr
  1796  		c := &ruleListStrCondExactMatchListStrInput{
  1797  			config: &config{
  1798  				field:         fieldName,
  1799  				matchStrategy: fieldMatchExact,
  1800  				values:        values,
  1801  				regexEnabled:  false,
  1802  				alwaysTrue:    false,
  1803  				exprDataType:  condDataType,
  1804  				inputDataType: inputDataType,
  1805  				conditionType: `ruleListStrCondExactMatchListStrInput`,
  1806  				matchAny:      matchAny,
  1807  			},
  1808  			field: &field{
  1809  				name:   fieldName,
  1810  				length: len(fieldName),
  1811  			},
  1812  		}
  1813  		c.exprs = []*expr{}
  1814  		for _, val := range values {
  1815  			c.exprs = append(c.exprs, &expr{
  1816  				value: val,
  1817  			})
  1818  		}
  1819  		return c, nil
  1820  	case matchStrategy == fieldMatchPartial && condDataType == dataTypeListStr && inputDataType == dataTypeListStr:
  1821  		// Match: Partial, Condition Type: ListStr, Input Type: ListStr
  1822  		c := &ruleListStrCondPartialMatchListStrInput{
  1823  			config: &config{
  1824  				field:         fieldName,
  1825  				matchStrategy: fieldMatchPartial,
  1826  				values:        values,
  1827  				regexEnabled:  false,
  1828  				alwaysTrue:    false,
  1829  				exprDataType:  condDataType,
  1830  				inputDataType: inputDataType,
  1831  				conditionType: `ruleListStrCondPartialMatchListStrInput`,
  1832  				matchAny:      matchAny,
  1833  			},
  1834  			field: &field{
  1835  				name:   fieldName,
  1836  				length: len(fieldName),
  1837  			},
  1838  		}
  1839  		c.exprs = []*expr{}
  1840  		for _, val := range values {
  1841  			c.exprs = append(c.exprs, &expr{
  1842  				value: val,
  1843  			})
  1844  		}
  1845  		return c, nil
  1846  	case matchStrategy == fieldMatchPrefix && condDataType == dataTypeListStr && inputDataType == dataTypeListStr:
  1847  		// Match: Prefix, Condition Type: ListStr, Input Type: ListStr
  1848  		c := &ruleListStrCondPrefixMatchListStrInput{
  1849  			config: &config{
  1850  				field:         fieldName,
  1851  				matchStrategy: fieldMatchPrefix,
  1852  				values:        values,
  1853  				regexEnabled:  false,
  1854  				alwaysTrue:    false,
  1855  				exprDataType:  condDataType,
  1856  				inputDataType: inputDataType,
  1857  				conditionType: `ruleListStrCondPrefixMatchListStrInput`,
  1858  				matchAny:      matchAny,
  1859  			},
  1860  			field: &field{
  1861  				name:   fieldName,
  1862  				length: len(fieldName),
  1863  			},
  1864  		}
  1865  		c.exprs = []*expr{}
  1866  		for _, val := range values {
  1867  			c.exprs = append(c.exprs, &expr{
  1868  				value: val,
  1869  			})
  1870  		}
  1871  		return c, nil
  1872  	case matchStrategy == fieldMatchSuffix && condDataType == dataTypeListStr && inputDataType == dataTypeListStr:
  1873  		// Match: Suffix, Condition Type: ListStr, Input Type: ListStr
  1874  		c := &ruleListStrCondSuffixMatchListStrInput{
  1875  			config: &config{
  1876  				field:         fieldName,
  1877  				matchStrategy: fieldMatchSuffix,
  1878  				values:        values,
  1879  				regexEnabled:  false,
  1880  				alwaysTrue:    false,
  1881  				exprDataType:  condDataType,
  1882  				inputDataType: inputDataType,
  1883  				conditionType: `ruleListStrCondSuffixMatchListStrInput`,
  1884  				matchAny:      matchAny,
  1885  			},
  1886  			field: &field{
  1887  				name:   fieldName,
  1888  				length: len(fieldName),
  1889  			},
  1890  		}
  1891  		c.exprs = []*expr{}
  1892  		for _, val := range values {
  1893  			c.exprs = append(c.exprs, &expr{
  1894  				value: val,
  1895  			})
  1896  		}
  1897  		return c, nil
  1898  	case matchStrategy == fieldMatchRegex && condDataType == dataTypeListStr && inputDataType == dataTypeListStr:
  1899  		// Match: Regex, Condition Type: ListStr, Input Type: ListStr
  1900  		c := &ruleListStrCondRegexMatchListStrInput{
  1901  			config: &config{
  1902  				field:         fieldName,
  1903  				matchStrategy: fieldMatchRegex,
  1904  				values:        values,
  1905  				regexEnabled:  true,
  1906  				alwaysTrue:    false,
  1907  				exprDataType:  condDataType,
  1908  				inputDataType: inputDataType,
  1909  				conditionType: `ruleListStrCondRegexMatchListStrInput`,
  1910  				matchAny:      matchAny,
  1911  			},
  1912  			field: &field{
  1913  				name:   fieldName,
  1914  				length: len(fieldName),
  1915  			},
  1916  		}
  1917  		c.exprs = []*regexp.Regexp{}
  1918  		for _, val := range values {
  1919  			re, err := regexp.Compile(val)
  1920  			if err != nil {
  1921  				return nil, err
  1922  			}
  1923  			c.exprs = append(c.exprs, re)
  1924  		}
  1925  		return c, nil
  1926  	case matchStrategy == fieldMatchExact && condDataType == dataTypeStr && inputDataType == dataTypeListStr:
  1927  		// Match: Exact, Condition Type: Str, Input Type: ListStr
  1928  		c := &ruleStrCondExactMatchListStrInput{
  1929  			config: &config{
  1930  				field:         fieldName,
  1931  				matchStrategy: fieldMatchExact,
  1932  				values:        values,
  1933  				regexEnabled:  false,
  1934  				alwaysTrue:    false,
  1935  				exprDataType:  condDataType,
  1936  				inputDataType: inputDataType,
  1937  				conditionType: `ruleStrCondExactMatchListStrInput`,
  1938  				matchAny:      matchAny,
  1939  			},
  1940  			field: &field{
  1941  				name:   fieldName,
  1942  				length: len(fieldName),
  1943  			},
  1944  		}
  1945  		c.expr = &expr{
  1946  			value: values[0],
  1947  		}
  1948  		return c, nil
  1949  	case matchStrategy == fieldMatchPartial && condDataType == dataTypeStr && inputDataType == dataTypeListStr:
  1950  		// Match: Partial, Condition Type: Str, Input Type: ListStr
  1951  		c := &ruleStrCondPartialMatchListStrInput{
  1952  			config: &config{
  1953  				field:         fieldName,
  1954  				matchStrategy: fieldMatchPartial,
  1955  				values:        values,
  1956  				regexEnabled:  false,
  1957  				alwaysTrue:    false,
  1958  				exprDataType:  condDataType,
  1959  				inputDataType: inputDataType,
  1960  				conditionType: `ruleStrCondPartialMatchListStrInput`,
  1961  				matchAny:      matchAny,
  1962  			},
  1963  			field: &field{
  1964  				name:   fieldName,
  1965  				length: len(fieldName),
  1966  			},
  1967  		}
  1968  		c.expr = &expr{
  1969  			value: values[0],
  1970  		}
  1971  		return c, nil
  1972  	case matchStrategy == fieldMatchPrefix && condDataType == dataTypeStr && inputDataType == dataTypeListStr:
  1973  		// Match: Prefix, Condition Type: Str, Input Type: ListStr
  1974  		c := &ruleStrCondPrefixMatchListStrInput{
  1975  			config: &config{
  1976  				field:         fieldName,
  1977  				matchStrategy: fieldMatchPrefix,
  1978  				values:        values,
  1979  				regexEnabled:  false,
  1980  				alwaysTrue:    false,
  1981  				exprDataType:  condDataType,
  1982  				inputDataType: inputDataType,
  1983  				conditionType: `ruleStrCondPrefixMatchListStrInput`,
  1984  				matchAny:      matchAny,
  1985  			},
  1986  			field: &field{
  1987  				name:   fieldName,
  1988  				length: len(fieldName),
  1989  			},
  1990  		}
  1991  		c.expr = &expr{
  1992  			value: values[0],
  1993  		}
  1994  		return c, nil
  1995  	case matchStrategy == fieldMatchSuffix && condDataType == dataTypeStr && inputDataType == dataTypeListStr:
  1996  		// Match: Suffix, Condition Type: Str, Input Type: ListStr
  1997  		c := &ruleStrCondSuffixMatchListStrInput{
  1998  			config: &config{
  1999  				field:         fieldName,
  2000  				matchStrategy: fieldMatchSuffix,
  2001  				values:        values,
  2002  				regexEnabled:  false,
  2003  				alwaysTrue:    false,
  2004  				exprDataType:  condDataType,
  2005  				inputDataType: inputDataType,
  2006  				conditionType: `ruleStrCondSuffixMatchListStrInput`,
  2007  				matchAny:      matchAny,
  2008  			},
  2009  			field: &field{
  2010  				name:   fieldName,
  2011  				length: len(fieldName),
  2012  			},
  2013  		}
  2014  		c.expr = &expr{
  2015  			value: values[0],
  2016  		}
  2017  		return c, nil
  2018  	case matchStrategy == fieldMatchRegex && condDataType == dataTypeStr && inputDataType == dataTypeListStr:
  2019  		// Match: Regex, Condition Type: Str, Input Type: ListStr
  2020  		c := &ruleStrCondRegexMatchListStrInput{
  2021  			config: &config{
  2022  				field:         fieldName,
  2023  				matchStrategy: fieldMatchRegex,
  2024  				values:        values,
  2025  				regexEnabled:  true,
  2026  				alwaysTrue:    false,
  2027  				exprDataType:  condDataType,
  2028  				inputDataType: inputDataType,
  2029  				conditionType: `ruleStrCondRegexMatchListStrInput`,
  2030  				matchAny:      matchAny,
  2031  			},
  2032  			field: &field{
  2033  				name:   fieldName,
  2034  				length: len(fieldName),
  2035  			},
  2036  		}
  2037  		re, err := regexp.Compile(values[0])
  2038  		if err != nil {
  2039  			return nil, err
  2040  		}
  2041  		c.expr = re
  2042  		return c, nil
  2043  	case matchStrategy == fieldMatchExact && condDataType == dataTypeListStr && inputDataType == dataTypeStr:
  2044  		// Match: Exact, Condition Type: ListStr, Input Type: Str
  2045  		c := &ruleListStrCondExactMatchStrInput{
  2046  			config: &config{
  2047  				field:         fieldName,
  2048  				matchStrategy: fieldMatchExact,
  2049  				values:        values,
  2050  				regexEnabled:  false,
  2051  				alwaysTrue:    false,
  2052  				exprDataType:  condDataType,
  2053  				inputDataType: inputDataType,
  2054  				conditionType: `ruleListStrCondExactMatchStrInput`,
  2055  				matchAny:      matchAny,
  2056  			},
  2057  			field: &field{
  2058  				name:   fieldName,
  2059  				length: len(fieldName),
  2060  			},
  2061  		}
  2062  		c.exprs = []*expr{}
  2063  		for _, val := range values {
  2064  			c.exprs = append(c.exprs, &expr{
  2065  				value: val,
  2066  			})
  2067  		}
  2068  		return c, nil
  2069  	case matchStrategy == fieldMatchPartial && condDataType == dataTypeListStr && inputDataType == dataTypeStr:
  2070  		// Match: Partial, Condition Type: ListStr, Input Type: Str
  2071  		c := &ruleListStrCondPartialMatchStrInput{
  2072  			config: &config{
  2073  				field:         fieldName,
  2074  				matchStrategy: fieldMatchPartial,
  2075  				values:        values,
  2076  				regexEnabled:  false,
  2077  				alwaysTrue:    false,
  2078  				exprDataType:  condDataType,
  2079  				inputDataType: inputDataType,
  2080  				conditionType: `ruleListStrCondPartialMatchStrInput`,
  2081  				matchAny:      matchAny,
  2082  			},
  2083  			field: &field{
  2084  				name:   fieldName,
  2085  				length: len(fieldName),
  2086  			},
  2087  		}
  2088  		c.exprs = []*expr{}
  2089  		for _, val := range values {
  2090  			c.exprs = append(c.exprs, &expr{
  2091  				value: val,
  2092  			})
  2093  		}
  2094  		return c, nil
  2095  	case matchStrategy == fieldMatchPrefix && condDataType == dataTypeListStr && inputDataType == dataTypeStr:
  2096  		// Match: Prefix, Condition Type: ListStr, Input Type: Str
  2097  		c := &ruleListStrCondPrefixMatchStrInput{
  2098  			config: &config{
  2099  				field:         fieldName,
  2100  				matchStrategy: fieldMatchPrefix,
  2101  				values:        values,
  2102  				regexEnabled:  false,
  2103  				alwaysTrue:    false,
  2104  				exprDataType:  condDataType,
  2105  				inputDataType: inputDataType,
  2106  				conditionType: `ruleListStrCondPrefixMatchStrInput`,
  2107  				matchAny:      matchAny,
  2108  			},
  2109  			field: &field{
  2110  				name:   fieldName,
  2111  				length: len(fieldName),
  2112  			},
  2113  		}
  2114  		c.exprs = []*expr{}
  2115  		for _, val := range values {
  2116  			c.exprs = append(c.exprs, &expr{
  2117  				value: val,
  2118  			})
  2119  		}
  2120  		return c, nil
  2121  	case matchStrategy == fieldMatchSuffix && condDataType == dataTypeListStr && inputDataType == dataTypeStr:
  2122  		// Match: Suffix, Condition Type: ListStr, Input Type: Str
  2123  		c := &ruleListStrCondSuffixMatchStrInput{
  2124  			config: &config{
  2125  				field:         fieldName,
  2126  				matchStrategy: fieldMatchSuffix,
  2127  				values:        values,
  2128  				regexEnabled:  false,
  2129  				alwaysTrue:    false,
  2130  				exprDataType:  condDataType,
  2131  				inputDataType: inputDataType,
  2132  				conditionType: `ruleListStrCondSuffixMatchStrInput`,
  2133  				matchAny:      matchAny,
  2134  			},
  2135  			field: &field{
  2136  				name:   fieldName,
  2137  				length: len(fieldName),
  2138  			},
  2139  		}
  2140  		c.exprs = []*expr{}
  2141  		for _, val := range values {
  2142  			c.exprs = append(c.exprs, &expr{
  2143  				value: val,
  2144  			})
  2145  		}
  2146  		return c, nil
  2147  	case matchStrategy == fieldMatchRegex && condDataType == dataTypeListStr && inputDataType == dataTypeStr:
  2148  		// Match: Regex, Condition Type: ListStr, Input Type: Str
  2149  		c := &ruleListStrCondRegexMatchStrInput{
  2150  			config: &config{
  2151  				field:         fieldName,
  2152  				matchStrategy: fieldMatchRegex,
  2153  				values:        values,
  2154  				regexEnabled:  true,
  2155  				alwaysTrue:    false,
  2156  				exprDataType:  condDataType,
  2157  				inputDataType: inputDataType,
  2158  				conditionType: `ruleListStrCondRegexMatchStrInput`,
  2159  				matchAny:      matchAny,
  2160  			},
  2161  			field: &field{
  2162  				name:   fieldName,
  2163  				length: len(fieldName),
  2164  			},
  2165  		}
  2166  		c.exprs = []*regexp.Regexp{}
  2167  		for _, val := range values {
  2168  			re, err := regexp.Compile(val)
  2169  			if err != nil {
  2170  				return nil, err
  2171  			}
  2172  			c.exprs = append(c.exprs, re)
  2173  		}
  2174  		return c, nil
  2175  	case matchStrategy == fieldMatchExact && condDataType == dataTypeStr && inputDataType == dataTypeStr:
  2176  		// Match: Exact, Condition Type: Str, Input Type: Str
  2177  		c := &ruleStrCondExactMatchStrInput{
  2178  			config: &config{
  2179  				field:         fieldName,
  2180  				matchStrategy: fieldMatchExact,
  2181  				values:        values,
  2182  				regexEnabled:  false,
  2183  				alwaysTrue:    false,
  2184  				exprDataType:  condDataType,
  2185  				inputDataType: inputDataType,
  2186  				conditionType: `ruleStrCondExactMatchStrInput`,
  2187  				matchAny:      matchAny,
  2188  			},
  2189  			field: &field{
  2190  				name:   fieldName,
  2191  				length: len(fieldName),
  2192  			},
  2193  		}
  2194  		c.expr = &expr{
  2195  			value: values[0],
  2196  		}
  2197  		return c, nil
  2198  	case matchStrategy == fieldMatchPartial && condDataType == dataTypeStr && inputDataType == dataTypeStr:
  2199  		// Match: Partial, Condition Type: Str, Input Type: Str
  2200  		c := &ruleStrCondPartialMatchStrInput{
  2201  			config: &config{
  2202  				field:         fieldName,
  2203  				matchStrategy: fieldMatchPartial,
  2204  				values:        values,
  2205  				regexEnabled:  false,
  2206  				alwaysTrue:    false,
  2207  				exprDataType:  condDataType,
  2208  				inputDataType: inputDataType,
  2209  				conditionType: `ruleStrCondPartialMatchStrInput`,
  2210  				matchAny:      matchAny,
  2211  			},
  2212  			field: &field{
  2213  				name:   fieldName,
  2214  				length: len(fieldName),
  2215  			},
  2216  		}
  2217  		c.expr = &expr{
  2218  			value: values[0],
  2219  		}
  2220  		return c, nil
  2221  	case matchStrategy == fieldMatchPrefix && condDataType == dataTypeStr && inputDataType == dataTypeStr:
  2222  		// Match: Prefix, Condition Type: Str, Input Type: Str
  2223  		c := &ruleStrCondPrefixMatchStrInput{
  2224  			config: &config{
  2225  				field:         fieldName,
  2226  				matchStrategy: fieldMatchPrefix,
  2227  				values:        values,
  2228  				regexEnabled:  false,
  2229  				alwaysTrue:    false,
  2230  				exprDataType:  condDataType,
  2231  				inputDataType: inputDataType,
  2232  				conditionType: `ruleStrCondPrefixMatchStrInput`,
  2233  				matchAny:      matchAny,
  2234  			},
  2235  			field: &field{
  2236  				name:   fieldName,
  2237  				length: len(fieldName),
  2238  			},
  2239  		}
  2240  		c.expr = &expr{
  2241  			value: values[0],
  2242  		}
  2243  		return c, nil
  2244  	case matchStrategy == fieldMatchSuffix && condDataType == dataTypeStr && inputDataType == dataTypeStr:
  2245  		// Match: Suffix, Condition Type: Str, Input Type: Str
  2246  		c := &ruleStrCondSuffixMatchStrInput{
  2247  			config: &config{
  2248  				field:         fieldName,
  2249  				matchStrategy: fieldMatchSuffix,
  2250  				values:        values,
  2251  				regexEnabled:  false,
  2252  				alwaysTrue:    false,
  2253  				exprDataType:  condDataType,
  2254  				inputDataType: inputDataType,
  2255  				conditionType: `ruleStrCondSuffixMatchStrInput`,
  2256  				matchAny:      matchAny,
  2257  			},
  2258  			field: &field{
  2259  				name:   fieldName,
  2260  				length: len(fieldName),
  2261  			},
  2262  		}
  2263  		c.expr = &expr{
  2264  			value: values[0],
  2265  		}
  2266  		return c, nil
  2267  	case matchStrategy == fieldMatchRegex && condDataType == dataTypeStr && inputDataType == dataTypeStr:
  2268  		// Match: Regex, Condition Type: Str, Input Type: Str
  2269  		c := &ruleStrCondRegexMatchStrInput{
  2270  			config: &config{
  2271  				field:         fieldName,
  2272  				matchStrategy: fieldMatchRegex,
  2273  				values:        values,
  2274  				regexEnabled:  true,
  2275  				alwaysTrue:    false,
  2276  				exprDataType:  condDataType,
  2277  				inputDataType: inputDataType,
  2278  				conditionType: `ruleStrCondRegexMatchStrInput`,
  2279  				matchAny:      matchAny,
  2280  			},
  2281  			field: &field{
  2282  				name:   fieldName,
  2283  				length: len(fieldName),
  2284  			},
  2285  		}
  2286  		re, err := regexp.Compile(values[0])
  2287  		if err != nil {
  2288  			return nil, err
  2289  		}
  2290  		c.expr = re
  2291  		return c, nil
  2292  
  2293  	}
  2294  	return nil, errors.ErrACLRuleConditionSyntaxUnsupported.WithArgs(line)
  2295  }
  2296  
  2297  func getMatchStrategyName(s fieldMatchStrategy) string {
  2298  	switch s {
  2299  	case fieldMatchExact:
  2300  		return "fieldMatchExact"
  2301  	case fieldMatchPartial:
  2302  		return "fieldMatchPartial"
  2303  	case fieldMatchPrefix:
  2304  		return "fieldMatchPrefix"
  2305  	case fieldMatchSuffix:
  2306  		return "fieldMatchSuffix"
  2307  	case fieldMatchRegex:
  2308  		return "fieldMatchRegex"
  2309  	case fieldFound:
  2310  		return "fieldFound"
  2311  	case fieldNotFound:
  2312  		return "fieldNotFound"
  2313  	case fieldMatchAlways:
  2314  		return "fieldMatchAlways"
  2315  	case fieldMatchReserved:
  2316  		return "fieldMatchReserved"
  2317  	}
  2318  	return "fieldMatchUnknown"
  2319  }
  2320  func getDataTypeName(s dataType) string {
  2321  	switch s {
  2322  	case dataTypeListStr:
  2323  		return "dataTypeListStr"
  2324  	case dataTypeStr:
  2325  		return "dataTypeStr"
  2326  	case dataTypeAny:
  2327  		return "dataTypeAny"
  2328  	}
  2329  	return "dataTypeUnknown"
  2330  }