From 3ea21e43d7d03f2b0268599933d6ec85e327b7ee Mon Sep 17 00:00:00 2001 From: ionutboangiu Date: Thu, 20 Apr 2023 11:08:16 -0400 Subject: [PATCH] Add inline filter validation before writing to database Implement a function that takes as parameters a list of filters and it checks only whether the inline filters are valid. Add it inside the functions that load the profiles inside the TPReader. This prevents the case where it returns error after indexing had already started when it is already too late. Add unit tests for the implemented function. --- engine/filters.go | 11 +++++++++++ engine/filters_test.go | 30 ++++++++++++++++++++++++++++++ engine/tpreader.go | 21 +++++++++++++++++++++ 3 files changed, 62 insertions(+) diff --git a/engine/filters.go b/engine/filters.go index 820b875fa..10bd1ec51 100644 --- a/engine/filters.go +++ b/engine/filters.go @@ -571,3 +571,14 @@ func (fS *FilterS) getFieldValueDataProvider(initialDP utils.DataProvider, return } + +func validateInlineFilters(fltrs []string) (err error) { + for _, fltr := range fltrs { + if strings.HasPrefix(fltr, utils.Meta) { + if _, err = NewFilterFromInline(utils.EmptyString, fltr); err != nil { + return + } + } + } + return +} diff --git a/engine/filters_test.go b/engine/filters_test.go index 2f0a2e913..8aa9e4c81 100644 --- a/engine/filters_test.go +++ b/engine/filters_test.go @@ -18,6 +18,7 @@ along with this program. If not, see package engine import ( + "fmt" "reflect" "strings" "testing" @@ -2180,3 +2181,32 @@ func TestFilterSPass11(t *testing.T) { t.Error(err) } } + +func TestValidateInlineFilters(t *testing.T) { + cases := []struct { + fltrs []string + expectedErr string + }{ + {[]string{"FLTR", "*string:~*req.Account:1001"}, ""}, + {[]string{"FLTR", "*string:~*req,Acoount1001"}, "inline parse error for string: <*string:~*req,Acoount1001>"}, + {[]string{"*exists:~*req.Supplier:"}, ""}, + {[]string{"*exists:*req.Supplier"}, "inline parse error for string: <*exists:*req.Supplier>"}, + {[]string{"*rsr:~*req.Account:(10)"}, "invalid RSRFilter start rule in string: <(10)>"}, + } + computeTestName := func(idx int, params []string) string { + return fmt.Sprintf("Test No %d with parameters: %v", idx, params) + } + + for i, c := range cases { + t.Run(computeTestName(i, c.fltrs), func(t *testing.T) { + err := validateInlineFilters(c.fltrs) + if err != nil { + if c.expectedErr == "" { + t.Errorf("did not expect error, received: %v", err) + } + } else if c.expectedErr != "" { + t.Errorf("expected error: %v", err) + } + }) + } +} diff --git a/engine/tpreader.go b/engine/tpreader.go index c675f24ba..1acd1d4ca 100644 --- a/engine/tpreader.go +++ b/engine/tpreader.go @@ -1128,6 +1128,9 @@ func (tpr *TpReader) LoadResourceProfilesFiltered(tag string) (err error) { } mapRsPfls := make(map[utils.TenantID]*utils.TPResourceProfile) for _, rl := range rls { + if err = validateInlineFilters(rl.FilterIDs); err != nil { + return + } mapRsPfls[utils.TenantID{Tenant: rl.Tenant, ID: rl.ID}] = rl } tpr.resProfiles = mapRsPfls @@ -1152,6 +1155,9 @@ func (tpr *TpReader) LoadStatsFiltered(tag string) (err error) { } mapSTs := make(map[utils.TenantID]*utils.TPStatProfile) for _, st := range tps { + if err = validateInlineFilters(st.FilterIDs); err != nil { + return + } mapSTs[utils.TenantID{Tenant: st.Tenant, ID: st.ID}] = st } tpr.sqProfiles = mapSTs @@ -1176,6 +1182,9 @@ func (tpr *TpReader) LoadThresholdsFiltered(tag string) (err error) { } mapTHs := make(map[utils.TenantID]*utils.TPThresholdProfile) for _, th := range tps { + if err = validateInlineFilters(th.FilterIDs); err != nil { + return + } mapTHs[utils.TenantID{Tenant: th.Tenant, ID: th.ID}] = th } tpr.thProfiles = mapTHs @@ -1217,6 +1226,9 @@ func (tpr *TpReader) LoadSupplierProfilesFiltered(tag string) (err error) { } mapRsPfls := make(map[utils.TenantID]*utils.TPSupplierProfile) for _, rl := range rls { + if err = validateInlineFilters(rl.FilterIDs); err != nil { + return + } mapRsPfls[utils.TenantID{Tenant: rl.Tenant, ID: rl.ID}] = rl } tpr.sppProfiles = mapRsPfls @@ -1234,6 +1246,9 @@ func (tpr *TpReader) LoadAttributeProfilesFiltered(tag string) (err error) { } mapAttrPfls := make(map[utils.TenantID]*utils.TPAttributeProfile) for _, attr := range attrs { + if err = validateInlineFilters(attr.FilterIDs); err != nil { + return + } mapAttrPfls[utils.TenantID{Tenant: attr.Tenant, ID: attr.ID}] = attr } tpr.attributeProfiles = mapAttrPfls @@ -1251,6 +1266,9 @@ func (tpr *TpReader) LoadChargerProfilesFiltered(tag string) (err error) { } mapChargerProfile := make(map[utils.TenantID]*utils.TPChargerProfile) for _, rl := range rls { + if err = validateInlineFilters(rl.FilterIDs); err != nil { + return + } mapChargerProfile[utils.TenantID{Tenant: rl.Tenant, ID: rl.ID}] = rl } tpr.chargerProfiles = mapChargerProfile @@ -1268,6 +1286,9 @@ func (tpr *TpReader) LoadDispatcherProfilesFiltered(tag string) (err error) { } mapDispatcherProfile := make(map[utils.TenantID]*utils.TPDispatcherProfile) for _, rl := range rls { + if err = validateInlineFilters(rl.FilterIDs); err != nil { + return + } mapDispatcherProfile[utils.TenantID{Tenant: rl.Tenant, ID: rl.ID}] = rl } tpr.dispatcherProfiles = mapDispatcherProfile