mirror of
https://github.com/cgrates/cgrates.git
synced 2026-02-11 18:16:24 +05:00
Added *regex filter
This commit is contained in:
committed by
Dan Christian Bogos
parent
566af40c68
commit
30d4b5aa98
@@ -19,6 +19,7 @@ import (
|
||||
"fmt"
|
||||
"net"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -216,19 +217,20 @@ var supportedFiltersType utils.StringSet = utils.NewStringSet([]string{
|
||||
utils.MetaCronExp, utils.MetaRSR,
|
||||
utils.MetaEmpty, utils.MetaExists, utils.MetaLessThan, utils.MetaLessOrEqual,
|
||||
utils.MetaGreaterThan, utils.MetaGreaterOrEqual, utils.MetaEqual,
|
||||
utils.MetaNotEqual, utils.MetaIPNet, utils.MetaAPIBan,
|
||||
utils.MetaActivationInterval})
|
||||
utils.MetaIPNet, utils.MetaAPIBan, utils.MetaActivationInterval,
|
||||
utils.MetaRegex})
|
||||
var needsFieldName utils.StringSet = utils.NewStringSet([]string{
|
||||
utils.MetaString, utils.MetaPrefix, utils.MetaSuffix,
|
||||
utils.MetaCronExp, utils.MetaRSR, utils.MetaLessThan,
|
||||
utils.MetaEmpty, utils.MetaExists, utils.MetaLessOrEqual, utils.MetaGreaterThan,
|
||||
utils.MetaGreaterOrEqual, utils.MetaEqual, utils.MetaNotEqual, utils.MetaIPNet, utils.MetaAPIBan,
|
||||
utils.MetaActivationInterval})
|
||||
utils.MetaGreaterOrEqual, utils.MetaEqual, utils.MetaIPNet, utils.MetaAPIBan,
|
||||
utils.MetaActivationInterval,
|
||||
utils.MetaRegex})
|
||||
var needsValues utils.StringSet = utils.NewStringSet([]string{utils.MetaString, utils.MetaPrefix,
|
||||
utils.MetaSuffix, utils.MetaCronExp, utils.MetaRSR,
|
||||
utils.MetaLessThan, utils.MetaLessOrEqual, utils.MetaGreaterThan, utils.MetaGreaterOrEqual,
|
||||
utils.MetaEqual, utils.MetaNotEqual, utils.MetaIPNet, utils.MetaAPIBan,
|
||||
utils.MetaActivationInterval})
|
||||
utils.MetaEqual, utils.MetaIPNet, utils.MetaAPIBan, utils.MetaActivationInterval,
|
||||
utils.MetaRegex})
|
||||
|
||||
// NewFilterRule returns a new filter
|
||||
func NewFilterRule(rfType, fieldName string, vals []string) (*FilterRule, error) {
|
||||
@@ -262,55 +264,47 @@ func NewFilterRule(rfType, fieldName string, vals []string) (*FilterRule, error)
|
||||
// FilterRule filters requests coming into various places
|
||||
// Pass rule: default negative, one matching rule should pass the filter
|
||||
type FilterRule struct {
|
||||
Type string // Filter type (*string, *rsr_filters, *stats, *lt, *lte, *gt, *gte)
|
||||
Element string // Name of the field providing us the Values to check (used in case of some )
|
||||
Values []string // Filter definition
|
||||
rsrValues config.RSRParsers // Cache here the
|
||||
rsrElement *config.RSRParser // Cache here the
|
||||
rsrFilters utils.RSRFilters // Cache here the RSRFilter Values
|
||||
negative *bool
|
||||
Type string // Filter type (*string, *timing, *rsr_filters, *stats, *lt, *lte, *gt, *gte)
|
||||
Element string // Name of the field providing us the Values to check (used in case of some )
|
||||
Values []string // Filter definition
|
||||
rsrValues config.RSRParsers // Cache here the
|
||||
rsrElement *config.RSRParser // Cache here the
|
||||
rsrFilters utils.RSRFilters // Cache here the RSRFilter Values
|
||||
regexValues []*regexp.Regexp
|
||||
negative *bool
|
||||
}
|
||||
|
||||
// CompileValues compiles RSR fields
|
||||
func (fltr *FilterRule) CompileValues() (err error) {
|
||||
switch fltr.Type {
|
||||
case utils.MetaRegex, utils.MetaNotRegex:
|
||||
fltr.regexValues = make([]*regexp.Regexp, len(fltr.Values))
|
||||
for i, val := range fltr.Values {
|
||||
if fltr.regexValues[i], err = regexp.Compile(val); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
case utils.MetaRSR, utils.MetaNotRSR:
|
||||
if fltr.rsrFilters, err = utils.ParseRSRFiltersFromSlice(fltr.Values); err != nil {
|
||||
return
|
||||
}
|
||||
if fltr.rsrElement, err = config.NewRSRParser(fltr.Element); err != nil {
|
||||
return
|
||||
} else if fltr.rsrElement == nil {
|
||||
return fmt.Errorf("emtpy RSRParser in rule: <%s>", fltr.Element)
|
||||
}
|
||||
case utils.MetaExists, utils.MetaNotExists, utils.MetaEmpty, utils.MetaNotEmpty: // only the element is builded
|
||||
if fltr.rsrElement, err = config.NewRSRParser(fltr.Element); err != nil {
|
||||
return
|
||||
} else if fltr.rsrElement == nil {
|
||||
return fmt.Errorf("emtpy RSRParser in rule: <%s>", fltr.Element)
|
||||
}
|
||||
case utils.MetaActivationInterval, utils.MetaNotActivationInterval:
|
||||
if fltr.rsrElement, err = config.NewRSRParser(fltr.Element); err != nil {
|
||||
return
|
||||
} else if fltr.rsrElement == nil {
|
||||
return fmt.Errorf("emtpy RSRParser in rule: <%s>", fltr.Element)
|
||||
}
|
||||
for _, strVal := range fltr.Values {
|
||||
rsrPrsr, err := config.NewRSRParser(strVal)
|
||||
if err != nil {
|
||||
return err
|
||||
fltr.rsrValues = make(config.RSRParsers, len(fltr.Values))
|
||||
for i, strVal := range fltr.Values {
|
||||
if fltr.rsrValues[i], err = config.NewRSRParser(strVal); err != nil {
|
||||
return
|
||||
}
|
||||
fltr.rsrValues = append(fltr.rsrValues, rsrPrsr)
|
||||
}
|
||||
default:
|
||||
if fltr.rsrValues, err = config.NewRSRParsersFromSlice(fltr.Values); err != nil {
|
||||
return
|
||||
}
|
||||
if fltr.rsrElement, err = config.NewRSRParser(fltr.Element); err != nil {
|
||||
return
|
||||
} else if fltr.rsrElement == nil {
|
||||
return fmt.Errorf("emtpy RSRParser in rule: <%s>", fltr.Element)
|
||||
}
|
||||
}
|
||||
if fltr.rsrElement, err = config.NewRSRParser(fltr.Element); err != nil {
|
||||
return
|
||||
} else if fltr.rsrElement == nil {
|
||||
return fmt.Errorf("emtpy RSRParser in rule: <%s>", fltr.Element)
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -346,6 +340,8 @@ func (fltr *FilterRule) Pass(ctx *context.Context, dDP utils.DataProvider) (resu
|
||||
result, err = fltr.passAPIBan(ctx, dDP)
|
||||
case utils.MetaActivationInterval, utils.MetaNotActivationInterval:
|
||||
result, err = fltr.passActivationInterval(dDP)
|
||||
case utils.MetaRegex, utils.MetaNotRegex:
|
||||
result, err = fltr.passRegex(dDP)
|
||||
default:
|
||||
err = utils.ErrPrefixNotErrNotImplemented(fltr.Type)
|
||||
}
|
||||
@@ -677,3 +673,19 @@ func verifyInlineFilterS(fltrs []string) (err error) {
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (fltr *FilterRule) passRegex(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.regexValues {
|
||||
if val.MatchString(strVal) {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
@@ -291,6 +291,18 @@ func TestFilterNewRequestFilter(t *testing.T) {
|
||||
if !reflect.DeepEqual(erf, rf) {
|
||||
t.Errorf("Expecting: %+v, received: %+v", erf, rf)
|
||||
}
|
||||
|
||||
rf, err = NewFilterRule(utils.MetaRegex, "~MetaRegex", []string{"Regex"})
|
||||
if err != nil {
|
||||
t.Errorf("Error: %+v", err)
|
||||
}
|
||||
erf = &FilterRule{Type: utils.MetaRegex, Element: "~MetaRegex", Values: []string{"Regex"}, negative: utils.BoolPointer(false)}
|
||||
if err = erf.CompileValues(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(erf, rf) {
|
||||
t.Errorf("Expecting: %+v, received: %+v", erf, rf)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInlineFilterPassFiltersForEvent(t *testing.T) {
|
||||
@@ -477,6 +489,42 @@ func TestInlineFilterPassFiltersForEvent(t *testing.T) {
|
||||
} else if !pass {
|
||||
t.Errorf("For NewKey expecting: %+v, received: %+v", true, pass)
|
||||
}
|
||||
|
||||
failEvent = map[string]interface{}{
|
||||
"Account": "1001",
|
||||
}
|
||||
passEvent = map[string]interface{}{
|
||||
"Account": "1007",
|
||||
}
|
||||
fEv = utils.MapStorage{}
|
||||
fEv.Set([]string{utils.MetaReq}, failEvent)
|
||||
if pass, err := filterS.Pass(context.TODO(), "cgrates.org",
|
||||
[]string{"*regex:~*req.Account:^1007:error"}, fEv); err != nil {
|
||||
t.Error(err)
|
||||
} else if pass {
|
||||
t.Errorf("Expecting: %+v, received: %+v", false, pass)
|
||||
}
|
||||
if pass, err := filterS.Pass(context.TODO(), "cgrates.org",
|
||||
[]string{"*regex:~*req.Account:\\d{3}7"}, fEv); err != nil {
|
||||
t.Errorf(err.Error())
|
||||
} else if pass {
|
||||
t.Errorf("Expecting: %+v, received: %+v", false, pass)
|
||||
}
|
||||
pEv = utils.MapStorage{}
|
||||
pEv.Set([]string{utils.MetaReq}, passEvent)
|
||||
if pass, err := filterS.Pass(context.TODO(), "cgrates.org",
|
||||
[]string{"*regex:~*req.Account:\\d{3}7"}, pEv); err != nil {
|
||||
t.Errorf(err.Error())
|
||||
} else if !pass {
|
||||
t.Errorf("Expecting: %+v, received: %+v", true, pass)
|
||||
}
|
||||
//not
|
||||
if pass, err := filterS.Pass(context.TODO(), "cgrates.org",
|
||||
[]string{"*notregex:~*req.Account:\\d{3}7"}, pEv); err != nil {
|
||||
t.Errorf(err.Error())
|
||||
} else if pass {
|
||||
t.Errorf("Expecting: %+v, received: %+v", false, pass)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPassFiltersForEventWithEmptyFilter(t *testing.T) {
|
||||
|
||||
@@ -8,7 +8,8 @@ cgrates (1.0) UNRELEASED; urgency=medium
|
||||
* [DispatcherS] Added any_subsyste config to control the matching dispatchers
|
||||
* [StatS] AverageCallCost and TotalCallCost now returns error for negative Cost field
|
||||
* [SessionS] The sessions are no longer terminated on shutdown if the replication_conns are set
|
||||
|
||||
* [FilterS] Added *regex filter
|
||||
|
||||
-- DanB <danb@cgrates.org> Thu, 4 May 2021 12:05:00 +0200
|
||||
|
||||
cgrates (0.11.0) UNRELEASED; urgency=medium
|
||||
|
||||
@@ -1052,6 +1052,7 @@ const (
|
||||
MetaIPNet = "*ipnet"
|
||||
MetaAPIBan = "*apiban"
|
||||
MetaActivationInterval = "*ai"
|
||||
MetaRegex = "*regex"
|
||||
|
||||
MetaNotString = "*notstring"
|
||||
MetaNotPrefix = "*notprefix"
|
||||
@@ -1066,6 +1067,7 @@ const (
|
||||
MetaNotIPNet = "*notipnet"
|
||||
MetaNotAPIBan = "*notapiban"
|
||||
MetaNotActivationInterval = "*notai"
|
||||
MetaNotRegex = "*notregex"
|
||||
|
||||
MetaEC = "*ec"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user