diff --git a/config/sentrypeercfg_test.go b/config/sentrypeercfg_test.go
new file mode 100644
index 000000000..cec9d26b1
--- /dev/null
+++ b/config/sentrypeercfg_test.go
@@ -0,0 +1,127 @@
+/*
+Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments
+Copyright (C) ITsysCOM GmbH
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see
+*/
+
+package config
+
+import (
+ "reflect"
+ "testing"
+
+ "github.com/cgrates/cgrates/utils"
+)
+
+func TestSentryPeerCfgloadFromJsonCfg(t *testing.T) {
+ var sp, expected SentryPeerCfg
+
+ if err := sp.loadFromJSONCfg(nil); err != nil {
+ t.Error(err)
+ } else if !reflect.DeepEqual(sp, expected) {
+ t.Errorf("Expected %+v,Received %+v", expected, sp)
+ }
+
+ cfgJsonStr := `
+{
+ "sentrypeer":{
+ "client_id":"sd5h7rhyrtudjj",
+ "client_secret":"w9buwnbw9ewbegsaovnmn9wr",
+ "token_url":"https://authz.sentrypeer.com/oauth/token",
+ "ips_url":"https://sentrypeer.com/api/ip-addresses",
+ "numbers_url":"https://sentrypeer.com/api/phone-numbers",
+ "audience":"https://sentrypeer.com/api",
+ "grant_type":"client_credentials",
+ }
+ }
+ `
+ expected = SentryPeerCfg{
+ ClientID: "sd5h7rhyrtudjj",
+ ClientSecret: "w9buwnbw9ewbegsaovnmn9wr",
+ TokenUrl: "https://authz.sentrypeer.com/oauth/token",
+ IpsUrl: "https://sentrypeer.com/api/ip-addresses",
+ NumbersUrl: "https://sentrypeer.com/api/phone-numbers",
+ Audience: "https://sentrypeer.com/api",
+ GrantType: "client_credentials",
+ }
+ cfgJson, err := NewCgrJsonCfgFromBytes([]byte(cfgJsonStr))
+ if err != nil {
+ t.Error(err)
+ }
+ sentryPeerJson, err := cfgJson.SentryPeerJson()
+ if err != nil {
+ t.Error(err)
+ }
+ if err := sp.loadFromJSONCfg(sentryPeerJson); err != nil {
+ t.Error(err)
+ } else if !reflect.DeepEqual(sp, expected) {
+ t.Errorf("Expected %+v,Received %+v", expected, sp)
+ }
+}
+
+func TestSentryPeerAsMapInterface(t *testing.T) {
+ var sp SentryPeerCfg
+ cfgJsonStr := `
+{
+ "sentrypeer":{
+ "client_id": "sd5h7rhyrtudjj",
+ "client_secret": "w9buwnbw9ewbegsaovnmn9wr",
+ "token_url": "https://authz.sentrypeer.com/oauth/token",
+ "ips_url": "https://sentrypeer.com/api/ip-addresses",
+ "numbers_url": "https://sentrypeer.com/api/phone-numbers",
+ "audience": "https://sentrypeer.com/api",
+ "grant_type": "client_credentials",
+ }
+}
+`
+ expected := map[string]any{"ClientID": "sd5h7rhyrtudjj",
+ "ClientSecret": "w9buwnbw9ewbegsaovnmn9wr",
+ "TokenURL": "https://authz.sentrypeer.com/oauth/token",
+ "IpUrl": "https://sentrypeer.com/api/ip-addresses",
+ "NumberUrl": "https://sentrypeer.com/api/phone-numbers",
+ "Audience": "https://sentrypeer.com/api",
+ "GrantType": "client_credentials",
+ }
+
+ cfgJson, err := NewCgrJsonCfgFromBytes([]byte(cfgJsonStr))
+ if err != nil {
+ t.Error(err)
+ }
+
+ sentryPeerJson, err := cfgJson.SentryPeerJson()
+ if err != nil {
+ t.Error(err)
+ }
+ if err := sp.loadFromJSONCfg(sentryPeerJson); err != nil {
+ t.Error(err)
+ } else if rcv := sp.AsMapInterface(); !reflect.DeepEqual(expected, rcv) {
+ t.Errorf("Expected %+v,Received %+v", utils.ToJSON(expected), utils.ToJSON(rcv))
+ }
+}
+
+func TestSentryPeerCfgClone(t *testing.T) {
+
+ sp := &SentryPeerCfg{
+ Audience: "https://sentrypeer.com/api",
+ GrantType: "client_credentials",
+ }
+ rcv := sp.Clone()
+ if !reflect.DeepEqual(rcv, sp) {
+ t.Errorf("Expected %+v,Received %+v", rcv, sp)
+ }
+ if rcv.GrantType = ""; sp.GrantType != "client_credentials" {
+ t.Error("Expected clone to not modify the cloned")
+ }
+}
diff --git a/engine/attributes_test.go b/engine/attributes_test.go
index ad4755128..54fedb706 100644
--- a/engine/attributes_test.go
+++ b/engine/attributes_test.go
@@ -1442,3 +1442,112 @@ func TestAttrSV1GetAttributeForEvent(t *testing.T) {
}
}
+
+// func TestAttributesV1ProcessEventSentryPeer(t *testing.T) {
+// testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+// if r.Method == http.MethodPost {
+
+// if r.URL.EscapedPath() != "/oauth/token" {
+// w.WriteHeader(http.StatusNotFound)
+// return
+// }
+// contentType := r.Header.Get(utils.ContentType)
+// if contentType != utils.JsonBody {
+// w.WriteHeader(http.StatusBadRequest)
+// return
+// }
+// var data map[string]string
+// err := json.NewDecoder(r.Body).Decode(&data)
+// if err != nil {
+// w.WriteHeader(http.StatusBadRequest)
+// return
+// }
+// response := struct {
+// AccessToken string `json:"access_token"`
+// }{
+// AccessToken: "302982309u2u30r23203",
+// }
+// w.WriteHeader(http.StatusOK)
+// err = json.NewEncoder(w).Encode(response)
+// if err != nil {
+// http.Error(w, err.Error(), http.StatusInternalServerError)
+// return
+// }
+// return
+// }
+// if r.Method != http.MethodGet {
+// w.WriteHeader(http.StatusMethodNotAllowed)
+// return
+// }
+// responses := map[string]struct {
+// code int
+// body []byte
+// }{
+// "/api/phone-numbers/100": {code: http.StatusOK, body: []byte(`{"IP Address found"}`)},
+// }
+// if val, has := responses[r.URL.EscapedPath()]; has {
+// w.WriteHeader(val.code)
+// if val.body != nil {
+// w.Write(val.body)
+// }
+// return
+// }
+// }))
+// cfg := config.NewDefaultCGRConfig()
+// cfg.SentryPeerCfg().ClientID = "ererwffwssf"
+// cfg.SentryPeerCfg().ClientSecret = "3354rf43f34sf"
+// cfg.SentryPeerCfg().TokenUrl = testServer.URL + "/oauth/token"
+// cfg.SentryPeerCfg().IpsUrl = testServer.URL + "/api/ip-addresses"
+// cfg.SentryPeerCfg().NumbersUrl = testServer.URL + "/api/phone-numbers"
+// dm := NewDataManager(NewInternalDB(nil, nil, true, cfg.DataDbCfg().Items), nil, nil)
+// filterS := NewFilterS(cfg, nil, dm)
+
+// if err := dm.SetAttributeProfile(&AttributeProfile{
+// Tenant: "cgrates.org",
+// ID: "ATTR_CHECK_DESTINATION",
+// Contexts: []string{utils.MetaAny},
+// FilterIDs: []string{"*sentrypeer:~*req.Destination:*number"},
+// Attributes: []*Attribute{
+// {
+// Path: "*req.Destination",
+// Type: utils.MetaConstant,
+// Value: config.NewRSRParsersMustCompile("BANNED_NUM", utils.InfieldSep),
+// }},
+// Blocker: false,
+// Weight: 20}, false); err != nil {
+// t.Error(err)
+// }
+
+// alS := NewAttributeService(dm, filterS, cfg)
+// var rply AttrSProcessEventReply
+// expected := AttrSProcessEventReply{
+// MatchedProfiles: []string{"cgrates.org:ATTR_CHECK_DESTINATION"},
+// AlteredFields: []string{"*req.Destination"},
+// CGREvent: &utils.CGREvent{
+// Tenant: "cgrates.org",
+// Time: nil,
+// Event: map[string]any{
+// utils.AccountField: "account_1001",
+// utils.Destination: "BANNED_NUM",
+// },
+// APIOpts: map[string]any{
+// utils.OptsAttributesProcessRuns: 2,
+// },
+// },
+// blocker: false,
+// }
+// if err = alS.V1ProcessEvent(&utils.CGREvent{
+// Tenant: "cgrates.org",
+// Event: map[string]any{
+// utils.AccountField: "account_1001",
+// utils.Destination: "100",
+// },
+// APIOpts: map[string]any{
+// utils.OptsAttributesProcessRuns: 2,
+// },
+// }, &rply); err != nil {
+// t.Errorf("Expected <%+v>, received <%+v>", nil, err)
+// } else if sort.Strings(rply.AlteredFields); !reflect.DeepEqual(expected, rply) {
+// t.Errorf("Expected <%+v>, received <%+v>", utils.ToJSON(expected), utils.ToJSON(rply))
+// }
+// }
diff --git a/engine/filters_test.go b/engine/filters_test.go
index 21010a7c4..131cc81d8 100644
--- a/engine/filters_test.go
+++ b/engine/filters_test.go
@@ -19,6 +19,7 @@ along with this program. If not, see
package engine
import (
+ "encoding/json"
"fmt"
"net/http"
"net/http/httptest"
@@ -2417,3 +2418,121 @@ func TestFilterLazyPassErr(t *testing.T) {
t.Errorf(err.Error())
}
}
+
+func TestSentryPeer(t *testing.T) {
+ token := "token27072023"
+ testServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ if r.Method == http.MethodPost {
+
+ if r.URL.EscapedPath() != "/oauth/token" {
+ w.WriteHeader(http.StatusNotFound)
+ return
+ }
+ contentType := r.Header.Get(utils.ContentType)
+ if contentType != utils.JsonBody {
+ w.WriteHeader(http.StatusBadRequest)
+ return
+ }
+ var data map[string]string
+ err := json.NewDecoder(r.Body).Decode(&data)
+ if err != nil {
+ w.WriteHeader(http.StatusBadRequest)
+ return
+ }
+
+ if data[utils.ClientIdCfg] != "ererwffwssf" ||
+ data[utils.ClientSecretCfg] != "3354rf43f34sf" ||
+ data[utils.AudienceCfg] != "https://sentrypeer.com/api" ||
+ data[utils.GrantTypeCfg] != "client_credentials" {
+ w.WriteHeader(http.StatusBadRequest)
+ return
+ }
+ response := struct {
+ AccessToken string `json:"access_token"`
+ }{
+ AccessToken: token,
+ }
+ w.WriteHeader(http.StatusOK)
+ err = json.NewEncoder(w).Encode(response)
+ if err != nil {
+ http.Error(w, err.Error(), http.StatusInternalServerError)
+ return
+ }
+ return
+ }
+
+ if r.Method != http.MethodGet {
+ w.WriteHeader(http.StatusMethodNotAllowed)
+ return
+ }
+ responses := map[string]struct {
+ code int
+ body []byte
+ }{
+ "/api/ip-addresses/1.2.3.254": {code: http.StatusNotFound, body: []byte(`{"IP Address not found"}`)},
+ "/api/ip-addresses/184.168.31.232": {code: http.StatusOK, body: []byte(`{"IP Address found"}`)},
+ "/api/phone-numbers/22663272712": {code: http.StatusNotFound, body: []byte(`Phone Number not found`)},
+ "/api/phone-numbers/90046322651795": {code: http.StatusOK, body: []byte(`{"Phone Number found`)},
+ }
+ if val, has := responses[r.URL.EscapedPath()]; has {
+ if r.Header.Get(utils.AuthorizationHdr) != utils.BearerAuth+" "+token {
+ w.WriteHeader(http.StatusUnauthorized)
+ return
+ }
+ w.WriteHeader(val.code)
+ if val.body != nil {
+ w.Write(val.body)
+ }
+ return
+ }
+ w.WriteHeader(http.StatusBadRequest)
+ w.Write([]byte(`Wrong path in the request`))
+ }))
+
+ defer testServer.Close()
+ cfg := config.NewDefaultCGRConfig()
+ data := NewInternalDB(nil, nil, true, cfg.DataDbCfg().Items)
+ dm := NewDataManager(data, config.CgrConfig().CacheCfg(), nil)
+ filterS := FilterS{
+ cfg: cfg,
+ dm: dm,
+ }
+ dp := utils.MapStorage{
+ utils.MetaReq: utils.MapStorage{
+ "BADIP": "184.168.31.232",
+ "IP": "1.2.3.254",
+ "Number": "22663272712",
+ "BadNumber": "90046322651795",
+ },
+ }
+ config.CgrConfig().SentryPeerCfg().ClientID = "ererwffwssf"
+ config.CgrConfig().SentryPeerCfg().ClientSecret = "3354rf43f34sf"
+ config.CgrConfig().SentryPeerCfg().TokenUrl = testServer.URL + "/oauth/token"
+ config.CgrConfig().SentryPeerCfg().IpsUrl = testServer.URL + "/api/ip-addresses"
+ config.CgrConfig().SentryPeerCfg().NumbersUrl = testServer.URL + "/api/phone-numbers"
+
+ if pass, err := filterS.Pass("cgrates.org", []string{"*sentrypeer:~*req.IP:*ip"}, dp); err != nil {
+ t.Error(err)
+ } else if !pass {
+ t.Error("Expected to pass")
+ }
+
+ if pass, err := filterS.Pass("cgrates.org", []string{"*sentrypeer:~*req.BADIP:*ip"}, dp); err != nil {
+ t.Error(err)
+ } else if pass {
+ t.Error("Expected to not pass")
+ }
+
+ if pass, err := filterS.Pass("cgrates.org", []string{"*sentrypeer:~*req.Number:*number"}, dp); err != nil {
+ t.Error(err)
+ } else if !pass {
+ t.Error("Expected to pass")
+ }
+
+ if pass, err := filterS.Pass("cgrates.org", []string{"*sentrypeer:~*req.BadNumber:*number"}, dp); err != nil {
+ t.Error(err)
+ } else if pass {
+ t.Error("Expected to not pass")
+ }
+
+}