Added *len dataconverter

This commit is contained in:
Trial97
2021-06-16 18:22:13 +03:00
committed by Dan Christian Bogos
parent c5b22c24ab
commit 5e7860eede
5 changed files with 67 additions and 52 deletions

View File

@@ -550,32 +550,22 @@ func (fltr *FilterRule) passRSR(dDP utils.DataProvider) (bool, error) {
}
func (fltr *FilterRule) passGreaterThan(dDP utils.DataProvider) (bool, error) {
path, err := fltr.rsrElement.CompileDynRule(dDP)
if err != nil {
return false, err
}
fldIf, err := utils.DPDynamicInterface(path, dDP)
fldStr, err := fltr.rsrElement.ParseDataProviderWithInterfaces(dDP)
if err != nil {
if err == utils.ErrNotFound {
return false, nil
}
return false, err
}
if fldStr, castStr := fldIf.(string); castStr { // attempt converting string since deserialization fails here (ie: time.Time fields)
fldIf = utils.StringToInterface(fldStr)
}
fldIf := utils.StringToInterface(fldStr)
orEqual := fltr.Type == utils.MetaGreaterOrEqual ||
fltr.Type == utils.MetaLessThan
for _, val := range fltr.rsrValues {
valPath, err := val.CompileDynRule(dDP)
sval, err := val.ParseDataProviderWithInterfaces(dDP)
if err != nil {
continue
}
sval, err := utils.DPDynamicInterface(valPath, dDP)
if err != nil {
continue
}
if gte, err := utils.GreaterThan(fldIf, sval, orEqual); err != nil {
if gte, err := utils.GreaterThan(fldIf, utils.StringToInterface(sval), orEqual); err != nil {
return false, err
} else if (utils.MetaGreaterThan == fltr.Type || utils.MetaGreaterOrEqual == fltr.Type) && gte {
return true, nil
@@ -587,30 +577,20 @@ func (fltr *FilterRule) passGreaterThan(dDP utils.DataProvider) (bool, error) {
}
func (fltr *FilterRule) passEqualTo(dDP utils.DataProvider) (bool, error) {
path, err := fltr.rsrElement.CompileDynRule(dDP)
if err != nil {
return false, err
}
fldIf, err := utils.DPDynamicInterface(path, dDP)
fldStr, err := fltr.rsrElement.ParseDataProviderWithInterfaces(dDP)
if err != nil {
if err == utils.ErrNotFound {
return false, nil
}
return false, err
}
if fldStr, castStr := fldIf.(string); castStr { // attempt converting string since deserialization fails here (ie: time.Time fields)
fldIf = utils.StringToInterface(fldStr)
}
fldIf := utils.StringToInterface(fldStr)
for _, val := range fltr.rsrValues {
valPath, err := val.CompileDynRule(dDP)
if err != nil {
return false, err
}
sval, err := utils.DPDynamicInterface(valPath, dDP)
sval, err := val.ParseDataProviderWithInterfaces(dDP)
if err != nil {
continue
}
if eq, err := utils.EqualTo(fldIf, sval); err != nil {
if eq, err := utils.EqualTo(fldIf, utils.StringToInterface(sval)); err != nil {
return false, err
} else if eq {
return true, nil
@@ -663,49 +643,42 @@ func (fltr *FilterRule) passAPIBan(dDP utils.DataProvider) (bool, error) {
return dm.GetAPIBan(strVal, config.CgrConfig().APIBanCfg().Keys, fltr.Values[0] != utils.MetaAll, true, true)
}
func parseTime(rsr *config.RSRParser, dDp utils.DataProvider) (_ time.Time, err error) {
var str string
if str, err = rsr.ParseDataProvider(dDp); err != nil {
return
}
return utils.ParseTimeDetectLayout(str, config.CgrConfig().GeneralCfg().DefaultTimezone)
}
func (fltr *FilterRule) passActivationInterval(dDp utils.DataProvider) (bool, error) {
strVal, err := fltr.rsrElement.ParseDataProvider(dDp)
timeVal, err := parseTime(fltr.rsrElement, dDp)
if err != nil {
if err == utils.ErrNotFound {
return false, nil
}
return false, err
}
timeStrVal, err := utils.ParseTimeDetectLayout(strVal, config.CgrConfig().GeneralCfg().DefaultTimezone)
if err != nil {
return false, err
}
if len(fltr.rsrValues) == 2 {
val2, err := fltr.rsrValues[1].CompileDynRule(dDp)
if err != nil {
return false, err
}
endTime, err := utils.ParseTimeDetectLayout(val2, config.CgrConfig().GeneralCfg().DefaultTimezone)
endTime, err := parseTime(fltr.rsrValues[1], dDp)
if err != nil {
return false, err
}
if fltr.rsrValues[0] == nil {
return timeStrVal.Before(endTime), nil
return timeVal.Before(endTime), nil
}
val1, err := fltr.rsrValues[0].CompileDynRule(dDp)
startTime, err := parseTime(fltr.rsrValues[0], dDp)
if err != nil {
return false, err
}
startTime, err := utils.ParseTimeDetectLayout(val1, config.CgrConfig().GeneralCfg().DefaultTimezone)
if err != nil {
return false, err
}
return startTime.Before(timeStrVal) && timeStrVal.Before(endTime), nil
return startTime.Before(timeVal) && timeVal.Before(endTime), nil
}
val1, err := fltr.rsrValues[0].CompileDynRule(dDp)
startTime, err := parseTime(fltr.rsrValues[0], dDp)
if err != nil {
return false, err
}
startTime, err := utils.ParseTimeDetectLayout(val1, config.CgrConfig().GeneralCfg().DefaultTimezone)
if err != nil {
return false, err
}
return startTime.Before(timeStrVal), nil
return startTime.Before(timeVal), nil
}
func verifyInlineFilterS(fltrs []string) (err error) {

View File

@@ -1059,6 +1059,26 @@ func TestInlineFilterPassFiltersForEvent(t *testing.T) {
} else if pass {
t.Errorf("Expecting: %+v, received: %+v", false, pass)
}
pEv = utils.MapStorage{utils.MetaReq: utils.MapStorage{utils.AccountField: "sip:12345678901234567@abcdefg"}}
if pass, err := filterS.Pass("cgrates.org",
[]string{"*regex:~*req.Account:.{29,}"}, pEv); err != nil {
t.Errorf(err.Error())
} else if !pass {
t.Errorf("Expecting: %+v, received: %+v", true, pass)
}
if pass, err := filterS.Pass("cgrates.org",
[]string{"*regex:~*req.Account:^.{28}$"}, pEv); err != nil {
t.Errorf(err.Error())
} else if pass {
t.Errorf("Expecting: %+v, received: %+v", false, pass)
}
if pass, err := filterS.Pass("cgrates.org",
[]string{"*gte:~*req.Account{*len}:29"}, pEv); err != nil {
t.Errorf(err.Error())
} else if !pass {
t.Errorf("Expecting: %+v, received: %+v", true, pass)
}
}
func TestPassFiltersForEventWithEmptyFilter(t *testing.T) {
@@ -2199,7 +2219,7 @@ func TestFiltersPassGreaterThanErrIncomparable(t *testing.T) {
}
dtP := utils.MapStorage{
utils.MetaReq: map[string]interface{}{
utils.MetaUsage: "10",
utils.Usage: nil,
},
}

View File

@@ -165,6 +165,8 @@ cgrates (0.11.0~dev) UNRELEASED; urgency=medium
* [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
* [RSRParsers] Added *len dataconverter
-- DanB <danb@cgrates.org> Wed, 19 Feb 2020 13:25:52 +0200
cgrates (0.10.0) UNRELEASED; urgency=medium

View File

@@ -772,6 +772,7 @@ const (
MetaIP2Hex = "*ip2hex"
MetaString2Hex = "*string2hex"
MetaUnixTime = "*unixtime"
MetaLen = "*len"
MetaSIPURIMethod = "*sipuri_method"
MetaSIPURIHost = "*sipuri_host"
MetaSIPURIUser = "*sipuri_user"

View File

@@ -20,6 +20,7 @@ package utils
import (
"encoding/hex"
"encoding/json"
"fmt"
"math/rand"
"net"
@@ -87,6 +88,8 @@ func NewDataConverter(params string) (conv DataConverter, err error) {
return new(SIPURIMethodConverter), nil
case params == MetaUnixTime:
return new(UnixTimeConverter), nil
case params == MetaLen:
return new(LengthConverter), nil
case strings.HasPrefix(params, MetaLibPhoneNumber):
if len(params) == len(MetaLibPhoneNumber) {
return NewPhoneNumberConverter(EmptyString)
@@ -446,3 +449,19 @@ func (rC *RandomConverter) Convert(in interface{}) (
}
}
}
// LengthConverter converts the interface in the unix time
type LengthConverter struct{}
// Convert implements DataConverter interface
func (LengthConverter) Convert(in interface{}) (out interface{}, err error) {
src := IfaceAsString(in)
if strings.HasPrefix(src, IdxStart) &&
strings.HasSuffix(src, IdxEnd) { // it has a similar structure to a json marshaled slice
var slice []interface{}
if err := json.Unmarshal([]byte(src), &slice); err == nil { // no error when unmarshal safe to asume that this is a slice
return len(slice), nil
}
}
return len(src), nil
}