Add query param to filter decisions by scenarios and origin (#1294)
* Add query param to filter decisions by scenarios
This commit is contained in:
parent
bb30a3f966
commit
42a1bc0260
8 changed files with 369 additions and 34 deletions
|
@ -3,7 +3,6 @@ package apiclient
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/crowdsecurity/crowdsec/pkg/models"
|
||||
qs "github.com/google/go-querystring/query"
|
||||
|
@ -18,10 +17,24 @@ type DecisionsListOpts struct {
|
|||
IPEquals *string `url:"ip,omitempty"`
|
||||
RangeEquals *string `url:"range,omitempty"`
|
||||
Contains *bool `url:"contains,omitempty"`
|
||||
|
||||
ListOpts
|
||||
}
|
||||
|
||||
type DecisionsStreamOpts struct {
|
||||
Startup bool `url:"startup,omitempty"`
|
||||
Scopes string `url:"scopes,omitempty"`
|
||||
ScenariosContaining string `url:"scenarios_containing,omitempty"`
|
||||
ScenariosNotContaining string `url:"scenarios_not_containing,omitempty"`
|
||||
}
|
||||
|
||||
func (o *DecisionsStreamOpts) addQueryParamsToURL(url string) (string, error) {
|
||||
params, err := qs.Values(o)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return fmt.Sprintf("%s?%s", url, params.Encode()), nil
|
||||
}
|
||||
|
||||
type DecisionsDeleteOpts struct {
|
||||
ScopeEquals *string `url:"scope,omitempty"`
|
||||
ValueEquals *string `url:"value,omitempty"`
|
||||
|
@ -53,11 +66,11 @@ func (s *DecisionsService) List(ctx context.Context, opts DecisionsListOpts) (*m
|
|||
return &decisions, resp, nil
|
||||
}
|
||||
|
||||
func (s *DecisionsService) GetStream(ctx context.Context, startup bool, scopes []string) (*models.DecisionsStreamResponse, *Response, error) {
|
||||
func (s *DecisionsService) GetStream(ctx context.Context, opts DecisionsStreamOpts) (*models.DecisionsStreamResponse, *Response, error) {
|
||||
var decisions models.DecisionsStreamResponse
|
||||
u := fmt.Sprintf("%s/decisions/stream?startup=%t", s.client.URLPrefix, startup)
|
||||
if len(scopes) > 0 {
|
||||
u += "&scopes=" + strings.Join(scopes, ",")
|
||||
u, err := opts.addQueryParamsToURL(s.client.URLPrefix + "/decisions/stream")
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
req, err := s.client.NewRequest("GET", u, nil)
|
||||
if err != nil {
|
||||
|
|
|
@ -160,7 +160,7 @@ func TestDecisionsStream(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
decisions, resp, err := newcli.Decisions.GetStream(context.Background(), true, []string{})
|
||||
decisions, resp, err := newcli.Decisions.GetStream(context.Background(), DecisionsStreamOpts{Startup: true})
|
||||
require.NoError(t, err)
|
||||
|
||||
if resp.Response.StatusCode != http.StatusOK {
|
||||
|
@ -175,7 +175,7 @@ func TestDecisionsStream(t *testing.T) {
|
|||
}
|
||||
|
||||
//and second call, we get empty lists
|
||||
decisions, resp, err = newcli.Decisions.GetStream(context.Background(), false, []string{})
|
||||
decisions, resp, err = newcli.Decisions.GetStream(context.Background(), DecisionsStreamOpts{Startup: false})
|
||||
require.NoError(t, err)
|
||||
|
||||
if resp.Response.StatusCode != http.StatusOK {
|
||||
|
@ -234,6 +234,73 @@ func TestDeleteDecisions(t *testing.T) {
|
|||
defer teardown()
|
||||
}
|
||||
|
||||
func TestDecisionsStreamOpts_addQueryParamsToURL(t *testing.T) {
|
||||
baseURLString := "http://localhost:8080/v1/decisions/stream"
|
||||
type fields struct {
|
||||
Startup bool
|
||||
Scopes string
|
||||
ScenariosContaining string
|
||||
ScenariosNotContaining string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
want string
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "no filter",
|
||||
want: baseURLString + "?",
|
||||
},
|
||||
{
|
||||
name: "startup=true",
|
||||
fields: fields{
|
||||
Startup: true,
|
||||
},
|
||||
want: baseURLString + "?startup=true",
|
||||
},
|
||||
{
|
||||
name: "set all params",
|
||||
fields: fields{
|
||||
Startup: true,
|
||||
Scopes: "ip,range",
|
||||
ScenariosContaining: "ssh",
|
||||
ScenariosNotContaining: "bf",
|
||||
},
|
||||
want: baseURLString + "?scenarios_containing=ssh&scenarios_not_containing=bf&scopes=ip%2Crange&startup=true",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
o := &DecisionsStreamOpts{
|
||||
Startup: tt.fields.Startup,
|
||||
Scopes: tt.fields.Scopes,
|
||||
ScenariosContaining: tt.fields.ScenariosContaining,
|
||||
ScenariosNotContaining: tt.fields.ScenariosNotContaining,
|
||||
}
|
||||
got, err := o.addQueryParamsToURL(baseURLString)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("DecisionsStreamOpts.addQueryParamsToURL() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
|
||||
gotURL, err := url.Parse(got)
|
||||
if err != nil {
|
||||
t.Errorf("DecisionsStreamOpts.addQueryParamsToURL() got error while parsing URL: %s", err)
|
||||
}
|
||||
|
||||
expectedURL, err := url.Parse(tt.want)
|
||||
if err != nil {
|
||||
t.Errorf("DecisionsStreamOpts.addQueryParamsToURL() got error while parsing URL: %s", err)
|
||||
}
|
||||
|
||||
if *gotURL != *expectedURL {
|
||||
t.Errorf("DecisionsStreamOpts.addQueryParamsToURL() = %v, want %v", *gotURL, *expectedURL)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// func TestDeleteOneDecision(t *testing.T) {
|
||||
// mux, urlx, teardown := setup()
|
||||
// mux.HandleFunc("/watchers/login", func(w http.ResponseWriter, r *http.Request) {
|
||||
|
|
|
@ -275,7 +275,7 @@ func (a *apic) PullTop() error {
|
|||
log.Printf("last CAPI pull is newer than 1h30, skip.")
|
||||
return nil
|
||||
}
|
||||
data, _, err := a.apiClient.Decisions.GetStream(context.Background(), a.startup, []string{})
|
||||
data, _, err := a.apiClient.Decisions.GetStream(context.Background(), apiclient.DecisionsStreamOpts{Startup: a.startup})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "get stream")
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ import (
|
|||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/crowdsecurity/crowdsec/pkg/database/ent"
|
||||
|
@ -127,10 +126,9 @@ func (c *Controller) StreamDecision(gctx *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
filters := make(map[string][]string)
|
||||
filters["scope"] = []string{"ip", "range"}
|
||||
if val, ok := gctx.Request.URL.Query()["scopes"]; ok {
|
||||
filters["scope"] = strings.Split(val[0], ",")
|
||||
filters := gctx.Request.URL.Query()
|
||||
if _, ok := filters["scopes"]; !ok {
|
||||
filters["scopes"] = []string{"ip,range"}
|
||||
}
|
||||
|
||||
// if the blocker just start, return all decisions
|
||||
|
|
|
@ -120,7 +120,7 @@ func TestDeleteDecisionFilter(t *testing.T) {
|
|||
|
||||
// delete by scope/value
|
||||
w = httptest.NewRecorder()
|
||||
req, _ = http.NewRequest("DELETE", "/v1/decisions?scope=Ip&value=91.121.79.178", strings.NewReader(""))
|
||||
req, _ = http.NewRequest("DELETE", "/v1/decisions?scopes=Ip&value=91.121.79.178", strings.NewReader(""))
|
||||
AddAuthHeaders(req, loginResp)
|
||||
router.ServeHTTP(w, req)
|
||||
assert.Equal(t, 200, w.Code)
|
||||
|
@ -185,7 +185,7 @@ func TestGetDecisionFilters(t *testing.T) {
|
|||
|
||||
// Get Decision : scope/value
|
||||
w = httptest.NewRecorder()
|
||||
req, _ = http.NewRequest("GET", "/v1/decisions?scope=Ip&value=91.121.79.179", strings.NewReader(""))
|
||||
req, _ = http.NewRequest("GET", "/v1/decisions?scopes=Ip&value=91.121.79.179", strings.NewReader(""))
|
||||
req.Header.Add("User-Agent", UserAgent)
|
||||
req.Header.Add("X-Api-Key", APIKey)
|
||||
router.ServeHTTP(w, req)
|
||||
|
@ -249,19 +249,19 @@ func TestGetDecision(t *testing.T) {
|
|||
log.Fatalf("%s", err.Error())
|
||||
}
|
||||
|
||||
// Get Decision with invalid filter
|
||||
// Get Decision
|
||||
w = httptest.NewRecorder()
|
||||
req, _ = http.NewRequest("GET", "/v1/decisions?test=test", strings.NewReader(""))
|
||||
req, _ = http.NewRequest("GET", "/v1/decisions", strings.NewReader(""))
|
||||
req.Header.Add("User-Agent", UserAgent)
|
||||
req.Header.Add("X-Api-Key", APIKey)
|
||||
router.ServeHTTP(w, req)
|
||||
|
||||
assert.Equal(t, 500, w.Code)
|
||||
assert.Equal(t, "{\"message\":\"'test' doesn't exist: invalid filter\"}", w.Body.String())
|
||||
assert.Equal(t, 200, w.Code)
|
||||
assert.Contains(t, w.Body.String(), "\"id\":1,\"origin\":\"test\",\"scenario\":\"crowdsecurity/test\",\"scope\":\"Ip\",\"type\":\"ban\",\"value\":\"127.0.0.1\"}]")
|
||||
|
||||
// Get Decision
|
||||
// Get Decision with invalid filter. It should ignore this filter
|
||||
w = httptest.NewRecorder()
|
||||
req, _ = http.NewRequest("GET", "/v1/decisions", strings.NewReader(""))
|
||||
req, _ = http.NewRequest("GET", "/v1/decisions?test=test", strings.NewReader(""))
|
||||
req.Header.Add("User-Agent", UserAgent)
|
||||
req.Header.Add("X-Api-Key", APIKey)
|
||||
router.ServeHTTP(w, req)
|
||||
|
@ -388,7 +388,7 @@ func TestStreamDecision(t *testing.T) {
|
|||
}
|
||||
|
||||
// Create Valid Alert
|
||||
alertContentBytes, err := ioutil.ReadFile("./tests/alert_sample.json")
|
||||
alertContentBytes, err := ioutil.ReadFile("./tests/alert_stream_fixture.json")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
@ -432,5 +432,51 @@ func TestStreamDecision(t *testing.T) {
|
|||
router.ServeHTTP(w, req)
|
||||
|
||||
assert.Equal(t, 200, w.Code)
|
||||
assert.Contains(t, w.Body.String(), "\"id\":1,\"origin\":\"test\",\"scenario\":\"crowdsecurity/test\",\"scope\":\"Ip\",\"type\":\"ban\",\"value\":\"127.0.0.1\"}]}")
|
||||
assert.Contains(t, w.Body.String(), "\"id\":1,\"origin\":\"test1\",\"scenario\":\"crowdsecurity/http_bf\",\"scope\":\"Ip\",\"type\":\"ban\",\"value\":\"127.0.0.1\"")
|
||||
assert.Contains(t, w.Body.String(), "\"id\":2,\"origin\":\"test2\",\"scenario\":\"crowdsecurity/ssh_bf\",\"scope\":\"Ip\",\"type\":\"ban\",\"value\":\"127.0.0.1\"")
|
||||
assert.Contains(t, w.Body.String(), "\"id\":3,\"origin\":\"test3\",\"scenario\":\"crowdsecurity/ddos\",\"scope\":\"Ip\",\"type\":\"ban\",\"value\":\"127.0.0.1\"")
|
||||
|
||||
// test filter scenarios_not_containing
|
||||
w = httptest.NewRecorder()
|
||||
req, _ = http.NewRequest("GET", "/v1/decisions/stream?startup=true&scenarios_not_containing=http", strings.NewReader(""))
|
||||
req.Header.Add("X-Api-Key", APIKey)
|
||||
router.ServeHTTP(w, req)
|
||||
|
||||
assert.Equal(t, 200, w.Code)
|
||||
assert.NotContains(t, w.Body.String(), "\"id\":1,\"origin\":\"test1\",\"scenario\":\"crowdsecurity/http_bf\",\"scope\":\"Ip\",\"type\":\"ban\",\"value\":\"127.0.0.1\"")
|
||||
assert.Contains(t, w.Body.String(), "\"id\":2,\"origin\":\"test2\",\"scenario\":\"crowdsecurity/ssh_bf\",\"scope\":\"Ip\",\"type\":\"ban\",\"value\":\"127.0.0.1\"")
|
||||
assert.Contains(t, w.Body.String(), "\"id\":3,\"origin\":\"test3\",\"scenario\":\"crowdsecurity/ddos\",\"scope\":\"Ip\",\"type\":\"ban\",\"value\":\"127.0.0.1\"")
|
||||
|
||||
// test filter scenarios_containing
|
||||
w = httptest.NewRecorder()
|
||||
req, _ = http.NewRequest("GET", "/v1/decisions/stream?startup=true&scenarios_containing=http", strings.NewReader(""))
|
||||
req.Header.Add("X-Api-Key", APIKey)
|
||||
router.ServeHTTP(w, req)
|
||||
|
||||
assert.Equal(t, 200, w.Code)
|
||||
assert.Contains(t, w.Body.String(), "\"id\":1,\"origin\":\"test1\",\"scenario\":\"crowdsecurity/http_bf\",\"scope\":\"Ip\",\"type\":\"ban\",\"value\":\"127.0.0.1\"")
|
||||
assert.NotContains(t, w.Body.String(), "\"id\":2,\"origin\":\"test2\",\"scenario\":\"crowdsecurity/ssh_bf\",\"scope\":\"Ip\",\"type\":\"ban\",\"value\":\"127.0.0.1\"")
|
||||
assert.NotContains(t, w.Body.String(), "\"id\":3,\"origin\":\"test3\",\"scenario\":\"crowdsecurity/ddos\",\"scope\":\"Ip\",\"type\":\"ban\",\"value\":\"127.0.0.1\"")
|
||||
|
||||
// test filters both by scenarios_not_containing and scenarios_containing
|
||||
w = httptest.NewRecorder()
|
||||
req, _ = http.NewRequest("GET", "/v1/decisions/stream?startup=true&scenarios_not_containing=ssh&scenarios_containing=ddos", strings.NewReader(""))
|
||||
req.Header.Add("X-Api-Key", APIKey)
|
||||
router.ServeHTTP(w, req)
|
||||
|
||||
assert.Equal(t, 200, w.Code)
|
||||
assert.NotContains(t, w.Body.String(), "\"id\":1,\"origin\":\"test1\",\"scenario\":\"crowdsecurity/http_bf\",\"scope\":\"Ip\",\"type\":\"ban\",\"value\":\"127.0.0.1\"")
|
||||
assert.NotContains(t, w.Body.String(), "\"id\":2,\"origin\":\"test2\",\"scenario\":\"crowdsecurity/ssh_bf\",\"scope\":\"Ip\",\"type\":\"ban\",\"value\":\"127.0.0.1\"")
|
||||
assert.Contains(t, w.Body.String(), "\"id\":3,\"origin\":\"test3\",\"scenario\":\"crowdsecurity/ddos\",\"scope\":\"Ip\",\"type\":\"ban\",\"value\":\"127.0.0.1\"")
|
||||
|
||||
// test filter by origin
|
||||
w = httptest.NewRecorder()
|
||||
req, _ = http.NewRequest("GET", "/v1/decisions/stream?startup=true&origins=test1,test2", strings.NewReader(""))
|
||||
req.Header.Add("X-Api-Key", APIKey)
|
||||
router.ServeHTTP(w, req)
|
||||
|
||||
assert.Equal(t, 200, w.Code)
|
||||
assert.Contains(t, w.Body.String(), "\"id\":1,\"origin\":\"test1\",\"scenario\":\"crowdsecurity/http_bf\",\"scope\":\"Ip\",\"type\":\"ban\",\"value\":\"127.0.0.1\"")
|
||||
assert.Contains(t, w.Body.String(), "\"id\":2,\"origin\":\"test2\",\"scenario\":\"crowdsecurity/ssh_bf\",\"scope\":\"Ip\",\"type\":\"ban\",\"value\":\"127.0.0.1\"")
|
||||
assert.NotContains(t, w.Body.String(), "\"id\":3,\"origin\":\"test3\",\"scenario\":\"crowdsecurity/ddos\",\"scope\":\"Ip\",\"type\":\"ban\",\"value\":\"127.0.0.1\"")
|
||||
}
|
||||
|
|
173
pkg/apiserver/tests/alert_stream_fixture.json
Normal file
173
pkg/apiserver/tests/alert_stream_fixture.json
Normal file
|
@ -0,0 +1,173 @@
|
|||
[
|
||||
{
|
||||
"id": 42,
|
||||
"machine_id": "test",
|
||||
"capacity": 1,
|
||||
"created_at": "2020-10-09T10:00:10Z",
|
||||
"decisions": [
|
||||
{
|
||||
"id": 1,
|
||||
"duration": "1h",
|
||||
"origin": "test1",
|
||||
"scenario": "crowdsecurity/http_bf",
|
||||
"scope": "Ip",
|
||||
"value": "127.0.0.1",
|
||||
"type": "ban"
|
||||
}
|
||||
],
|
||||
"Events": [
|
||||
{
|
||||
"meta": [
|
||||
{
|
||||
"key": "test",
|
||||
"value": "test"
|
||||
}
|
||||
],
|
||||
"timestamp": "2020-10-09T10:00:01Z"
|
||||
}
|
||||
],
|
||||
"events_count": 1,
|
||||
"labels": [
|
||||
"test"
|
||||
],
|
||||
"leakspeed": "0.5s",
|
||||
"message": "test",
|
||||
"meta": [
|
||||
{
|
||||
"key": "test",
|
||||
"value": "test"
|
||||
}
|
||||
],
|
||||
"scenario": "crowdsecurity/http_bf",
|
||||
"scenario_hash": "hashtest",
|
||||
"scenario_version": "v1",
|
||||
"simulated": false,
|
||||
"source": {
|
||||
"as_name": "test",
|
||||
"as_number": "0123456",
|
||||
"cn": "france",
|
||||
"ip": "127.0.0.1",
|
||||
"latitude": 46.227638,
|
||||
"logitude": 2.213749,
|
||||
"range": "127.0.0.1/32",
|
||||
"scope": "ip",
|
||||
"value": "127.0.0.1"
|
||||
},
|
||||
"start_at": "2020-10-09T10:00:01Z",
|
||||
"stop_at": "2020-10-09T10:00:05Z"
|
||||
},
|
||||
{
|
||||
"id": 43,
|
||||
"machine_id": "test",
|
||||
"capacity": 1,
|
||||
"created_at": "2020-10-09T10:00:10Z",
|
||||
"decisions": [
|
||||
{
|
||||
"id": 2,
|
||||
"duration": "1h",
|
||||
"origin": "test2",
|
||||
"scenario": "crowdsecurity/ssh_bf",
|
||||
"scope": "Ip",
|
||||
"value": "127.0.0.1",
|
||||
"type": "ban"
|
||||
}
|
||||
],
|
||||
"Events": [
|
||||
{
|
||||
"meta": [
|
||||
{
|
||||
"key": "test",
|
||||
"value": "test"
|
||||
}
|
||||
],
|
||||
"timestamp": "2020-10-09T10:00:01Z"
|
||||
}
|
||||
],
|
||||
"events_count": 1,
|
||||
"labels": [
|
||||
"test"
|
||||
],
|
||||
"leakspeed": "0.5s",
|
||||
"message": "test",
|
||||
"meta": [
|
||||
{
|
||||
"key": "test",
|
||||
"value": "test"
|
||||
}
|
||||
],
|
||||
"scenario": "crowdsecurity/ssh_bf",
|
||||
"scenario_hash": "hashtest",
|
||||
"scenario_version": "v1",
|
||||
"simulated": false,
|
||||
"source": {
|
||||
"as_name": "test",
|
||||
"as_number": "0123456",
|
||||
"cn": "france",
|
||||
"ip": "127.0.0.1",
|
||||
"latitude": 46.227638,
|
||||
"logitude": 2.213749,
|
||||
"range": "127.0.0.1/32",
|
||||
"scope": "ip",
|
||||
"value": "127.0.0.1"
|
||||
},
|
||||
"start_at": "2020-10-09T10:00:01Z",
|
||||
"stop_at": "2020-10-09T10:00:05Z"
|
||||
},
|
||||
{
|
||||
"id": 44,
|
||||
"machine_id": "test",
|
||||
"capacity": 1,
|
||||
"created_at": "2020-10-09T10:00:10Z",
|
||||
"decisions": [
|
||||
{
|
||||
"id": 3,
|
||||
"duration": "1h",
|
||||
"origin": "test3",
|
||||
"scenario": "crowdsecurity/ddos",
|
||||
"scope": "Ip",
|
||||
"value": "127.0.0.1",
|
||||
"type": "ban"
|
||||
}
|
||||
],
|
||||
"Events": [
|
||||
{
|
||||
"meta": [
|
||||
{
|
||||
"key": "test",
|
||||
"value": "test"
|
||||
}
|
||||
],
|
||||
"timestamp": "2020-10-09T10:00:01Z"
|
||||
}
|
||||
],
|
||||
"events_count": 1,
|
||||
"labels": [
|
||||
"test"
|
||||
],
|
||||
"leakspeed": "0.5s",
|
||||
"message": "test",
|
||||
"meta": [
|
||||
{
|
||||
"key": "test",
|
||||
"value": "test"
|
||||
}
|
||||
],
|
||||
"scenario": "crowdsecurity/ddos",
|
||||
"scenario_hash": "hashtest",
|
||||
"scenario_version": "v1",
|
||||
"simulated": false,
|
||||
"source": {
|
||||
"as_name": "test",
|
||||
"as_number": "0123456",
|
||||
"cn": "france",
|
||||
"ip": "127.0.0.1",
|
||||
"latitude": 46.227638,
|
||||
"logitude": 2.213749,
|
||||
"range": "127.0.0.1/32",
|
||||
"scope": "ip",
|
||||
"value": "127.0.0.1"
|
||||
},
|
||||
"start_at": "2020-10-09T10:00:01Z",
|
||||
"stop_at": "2020-10-09T10:00:05Z"
|
||||
}
|
||||
]
|
|
@ -9,6 +9,7 @@ import (
|
|||
|
||||
"github.com/crowdsecurity/crowdsec/pkg/database/ent"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/database/ent/decision"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/database/ent/predicate"
|
||||
"github.com/crowdsecurity/crowdsec/pkg/types"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
@ -39,31 +40,44 @@ func BuildDecisionRequestWithFilter(query *ent.DecisionQuery, filter map[string]
|
|||
if err != nil {
|
||||
return nil, errors.Wrapf(InvalidFilter, "invalid contains value : %s", err)
|
||||
}
|
||||
case "scope":
|
||||
for i, scope := range value {
|
||||
case "scopes":
|
||||
scopes := strings.Split(value[0], ",")
|
||||
for i, scope := range scopes {
|
||||
switch strings.ToLower(scope) {
|
||||
case "ip":
|
||||
value[i] = types.Ip
|
||||
scopes[i] = types.Ip
|
||||
case "range":
|
||||
value[i] = types.Range
|
||||
scopes[i] = types.Range
|
||||
case "country":
|
||||
value[i] = types.Country
|
||||
scopes[i] = types.Country
|
||||
case "as":
|
||||
value[i] = types.AS
|
||||
scopes[i] = types.AS
|
||||
}
|
||||
}
|
||||
query = query.Where(decision.ScopeIn(value...))
|
||||
query = query.Where(decision.ScopeIn(scopes...))
|
||||
case "value":
|
||||
query = query.Where(decision.ValueEQ(value[0]))
|
||||
case "type":
|
||||
query = query.Where(decision.TypeEQ(value[0]))
|
||||
case "origins":
|
||||
query = query.Where(
|
||||
decision.OriginIn(strings.Split(value[0], ",")...),
|
||||
)
|
||||
case "scenarios_containing":
|
||||
predicates := decisionPredicatesFromStr(value[0], decision.ScenarioContainsFold)
|
||||
query = query.Where(decision.Or(predicates...))
|
||||
case "scenarios_not_containing":
|
||||
predicates := decisionPredicatesFromStr(value[0], decision.ScenarioContainsFold)
|
||||
query = query.Where(decision.Not(
|
||||
decision.Or(
|
||||
predicates...,
|
||||
),
|
||||
))
|
||||
case "ip", "range":
|
||||
ip_sz, start_ip, start_sfx, end_ip, end_sfx, err = types.Addr2Ints(value[0])
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(InvalidIPOrRange, "unable to convert '%s' to int: %s", value[0], err)
|
||||
}
|
||||
default:
|
||||
return query, errors.Wrapf(InvalidFilter, "'%s' doesn't exist", param)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -367,7 +381,7 @@ func (c *Client) SoftDeleteDecisionsWithFilter(filter map[string][]string) (stri
|
|||
if err != nil {
|
||||
return "0", errors.Wrapf(InvalidFilter, "invalid contains value : %s", err)
|
||||
}
|
||||
case "scope":
|
||||
case "scopes":
|
||||
decisions = decisions.Where(decision.ScopeEQ(value[0]))
|
||||
case "value":
|
||||
decisions = decisions.Where(decision.ValueEQ(value[0]))
|
||||
|
@ -474,3 +488,12 @@ func (c *Client) SoftDeleteDecisionByID(decisionID int) error {
|
|||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func decisionPredicatesFromStr(s string, predicateFunc func(string) predicate.Decision) []predicate.Decision {
|
||||
words := strings.Split(s, ",")
|
||||
predicates := make([]predicate.Decision, len(words))
|
||||
for i, word := range words {
|
||||
predicates[i] = predicateFunc(word)
|
||||
}
|
||||
return predicates
|
||||
}
|
||||
|
|
|
@ -45,6 +45,21 @@ paths:
|
|||
required: false
|
||||
type: string
|
||||
description: 'Comma separated scopes of decisions to fetch'
|
||||
- name: origins
|
||||
in: query
|
||||
required: false
|
||||
type: string
|
||||
description: 'Comma separated name of origins. If provided, then only the decisions originating from provided origins would be returned.'
|
||||
- name: scenarios_containing
|
||||
in: query
|
||||
required: false
|
||||
type: string
|
||||
description: 'Comma separated words. If provided, only the decisions created by scenarios containing any of the provided word would be returned.'
|
||||
- name: scenarios_not_containing
|
||||
in: query
|
||||
required: false
|
||||
type: string
|
||||
description: 'Comma separated words. If provided, only the decisions created by scenarios, not containing any of the provided word would be returned.'
|
||||
responses:
|
||||
'200':
|
||||
description: successful operation
|
||||
|
|
Loading…
Add table
Reference in a new issue