From 422d9196b4458b6c2f5a2e5dc574006b49890e86 Mon Sep 17 00:00:00 2001 From: gezimbll Date: Tue, 12 Dec 2023 10:19:49 -0500 Subject: [PATCH] Added new filter "*contains" --- engine/datamanager_test.go | 63 ++++++++++++++++++++++++++++++++++++++ engine/filters.go | 28 +++++++++++++++-- engine/filters_test.go | 34 ++++++++++++++++++++ utils/consts.go | 2 ++ 4 files changed, 124 insertions(+), 3 deletions(-) diff --git a/engine/datamanager_test.go b/engine/datamanager_test.go index bce8dc628..a0890f4a7 100644 --- a/engine/datamanager_test.go +++ b/engine/datamanager_test.go @@ -5014,3 +5014,66 @@ func TestDmUpdateReverseDestination(t *testing.T) { } } } + +func TestIndxFilterContains(t *testing.T) { + cfg := config.NewDefaultCGRConfig() + dm := NewDataManager(NewInternalDB(nil, nil, true, cfg.DataDbCfg().Items), cfg.CacheCfg(), nil) + + ft := &Filter{ + Tenant: "cgrates.org", + ID: "Filter1", + Rules: []*FilterRule{ + { + Type: utils.MetaContains, + Element: "~*req.EventType", + Values: []string{"Ev"}, + }, + }, + } + if err := dm.SetFilter(ft, true); err != nil { + t.Error(err) + } + fs := &Filter{ + Tenant: "cgrates.org", + ID: "Filter2", + Rules: []*FilterRule{ + { + Type: utils.MetaString, + Element: "~*req.EventType", + Values: []string{"Event1"}, + }, + }, + } + if err := dm.SetFilter(fs, true); err != nil { + t.Error(err) + } + + th := &ThresholdProfile{ + Tenant: "cgrates.org", + ID: "THD_Test", + ActivationInterval: &utils.ActivationInterval{}, + FilterIDs: []string{"Filter1", "Filter2"}, + MaxHits: 12, + MinSleep: 0, + Blocker: true, + Weight: 1.4, + ActionIDs: []string{}, + } + + if err := dm.SetThresholdProfile(th, true); err != nil { + t.Error(err) + } + eIdxes := map[string]utils.StringSet{ + "*string:*req.EventType:Event1": { + "THD_Test": struct{}{}, + }, + } + if rcvIdx, err := dm.GetIndexes( + utils.CacheThresholdFilterIndexes, th.Tenant, + utils.EmptyString, false, false); err != nil { + t.Error(err) + } else if !reflect.DeepEqual(eIdxes, rcvIdx) { + t.Errorf("Expecting %+v, received: %+v", eIdxes, rcvIdx) + } + +} diff --git a/engine/filters.go b/engine/filters.go index 3783b1582..fe55dff11 100644 --- a/engine/filters.go +++ b/engine/filters.go @@ -225,20 +225,20 @@ func (fltr *Filter) Compile() (err error) { } var supportedFiltersType utils.StringSet = utils.NewStringSet([]string{ - utils.MetaString, utils.MetaPrefix, utils.MetaSuffix, + utils.MetaString, utils.MetaContains, utils.MetaPrefix, utils.MetaSuffix, utils.MetaTimings, utils.MetaRSR, utils.MetaDestinations, utils.MetaEmpty, utils.MetaExists, utils.MetaLessThan, utils.MetaLessOrEqual, utils.MetaGreaterThan, utils.MetaGreaterOrEqual, utils.MetaEqual, utils.MetaIPNet, utils.MetaAPIBan, utils.MetaSentryPeer, utils.MetaActivationInterval, utils.MetaRegex}) var needsFieldName utils.StringSet = utils.NewStringSet([]string{ - utils.MetaString, utils.MetaPrefix, utils.MetaSuffix, + utils.MetaString, utils.MetaContains, utils.MetaPrefix, utils.MetaSuffix, utils.MetaTimings, utils.MetaRSR, utils.MetaDestinations, utils.MetaLessThan, utils.MetaEmpty, utils.MetaExists, utils.MetaLessOrEqual, utils.MetaGreaterThan, utils.MetaGreaterOrEqual, utils.MetaEqual, utils.MetaIPNet, utils.MetaAPIBan, utils.MetaSentryPeer, utils.MetaActivationInterval, utils.MetaRegex}) -var needsValues utils.StringSet = utils.NewStringSet([]string{utils.MetaString, utils.MetaPrefix, +var needsValues utils.StringSet = utils.NewStringSet([]string{utils.MetaString, utils.MetaContains, utils.MetaPrefix, utils.MetaSuffix, utils.MetaTimings, utils.MetaRSR, utils.MetaDestinations, utils.MetaLessThan, utils.MetaLessOrEqual, utils.MetaGreaterThan, utils.MetaGreaterOrEqual, utils.MetaEqual, utils.MetaIPNet, utils.MetaAPIBan, utils.MetaSentryPeer, utils.MetaActivationInterval, @@ -330,6 +330,8 @@ func (fltr *FilterRule) Pass(dDP utils.DataProvider) (result bool, err error) { switch fltr.Type { case utils.MetaString, utils.MetaNotString: result, err = fltr.passString(dDP) + case utils.MetaContains, utils.MetaNotContains: + result, err = fltr.passContains(dDP) case utils.MetaEmpty, utils.MetaNotEmpty: result, err = fltr.passEmpty(dDP) case utils.MetaExists, utils.MetaNotExists: @@ -387,6 +389,26 @@ func (fltr *FilterRule) passString(dDP utils.DataProvider) (bool, error) { return false, nil } +func (fltr *FilterRule) passContains(dDP utils.DataProvider) (bool, error) { + strVal, err := fltr.rsrElement.ParseDataProvider(dDP) + if err != nil { + if err == utils.ErrNotFound { + return false, nil + } + return false, err + } + for _, val := range fltr.rsrValues { + sval, err := val.ParseDataProvider(dDP) + if err != nil { + continue + } + if strings.Contains(strVal, sval) { + return true, nil + } + } + return false, nil +} + func (fltr *FilterRule) passExists(dDP utils.DataProvider) (bool, error) { path, err := fltr.rsrElement.CompileDynRule(dDP) if err != nil { diff --git a/engine/filters_test.go b/engine/filters_test.go index 371f86c5e..e96245322 100644 --- a/engine/filters_test.go +++ b/engine/filters_test.go @@ -89,6 +89,40 @@ func TestFilterPassString(t *testing.T) { } } +func TestFilterPassContains(t *testing.T) { + dp := utils.MapStorage{ + utils.MetaReq: map[string]any{ + "Attribute": "AttributeProfile1", + utils.AnswerTime: time.Date(2014, 7, 14, 14, 30, 0, 0, time.UTC), + "UsageInterval": "1s", + utils.Weight: "20.0", + "Account": "1001", + "OriginHost": "22.15.81.122", + }} + + rF, _ := NewFilterRule(utils.MetaContains, "~*req.Attribute", []string{"Profile"}) + + if pass, err := rF.passContains(dp); err != nil { + t.Error(err) + } else if !pass { + t.Error("FilterRule should pass") + } + + rF, _ = NewFilterRule(utils.MetaContains, "~*req.OriginHost", []string{"81"}) + if pass, err := rF.passContains(dp); err != nil { + t.Error(err) + } else if !pass { + t.Error("FilterRule should pass") + } + + rF, _ = NewFilterRule(utils.MetaContains, "~*req.Account", []string{"200"}) + if pass, err := rF.passContains(dp); err != nil { + t.Error(err) + } else if pass { + t.Error("FilterRule should not pass") + } +} + func TestFilterPassRegex(t *testing.T) { cd := &CallDescriptor{ Category: "call", diff --git a/utils/consts.go b/utils/consts.go index 6dfbd12d3..cbbaec677 100644 --- a/utils/consts.go +++ b/utils/consts.go @@ -1177,6 +1177,7 @@ const ( MetaNumber = "*number" MetaActivationInterval = "*ai" MetaRegex = "*regex" + MetaContains = "*contains" MetaNotString = "*notstring" MetaNotPrefix = "*notprefix" @@ -1194,6 +1195,7 @@ const ( MetaNotSentryPeer = "*notsentrypeer" MetaNotActivationInterval = "*notai" MetaNotRegex = "*notregex" + MetaNotContains = "*notcontains" MetaEC = "*ec" )