Skip to content

Commit

Permalink
Stage/v5.14.0 (#804)
Browse files Browse the repository at this point in the history
* fix: correctly stream process json data normalization to utf8 for bot… (#764)

* fix: correctly stream process json data normalization to utf8 for both metatag validation and writing to disk

* test: update expected errors in negative tests

* chore: restore go mod files for reverted package

* chore: correct module name

* chore: remove duplicate import

* doc: format inline comment

Co-authored-by: Ulises Rangel <urangel@specterops.io>

---------

Co-authored-by: Ulises Rangel <urangel@specterops.io>

* Bed-4168: fix: Inaccurate asset group counts attempt 2(#794)

* revert BED-4662 PR 767 (#797)

* updated table (#798)

* chore: prep-for-codereview

---------

Co-authored-by: Dillon Lees <dlees@specterops.io>
Co-authored-by: Ulises Rangel <urangel@specterops.io>
Co-authored-by: Michael Lipka <mlipka@specterops.io>
Co-authored-by: stephanieslamb <slamb@specterops.io>
  • Loading branch information
5 people authored Aug 21, 2024
1 parent 9d172ae commit b5aff8b
Show file tree
Hide file tree
Showing 48 changed files with 1,048 additions and 233 deletions.
8 changes: 3 additions & 5 deletions cmd/api/src/api/v2/agi.go
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,7 @@ func (s Resources) getAssetGroupMembers(response http.ResponseWriter, request *h
} else if assetGroup, err := s.DB.GetAssetGroup(request.Context(), int32(assetGroupID)); err != nil {
api.HandleDatabaseError(request, response, err)
return agMembers, err
} else if assetGroupNodes, err := s.GraphQuery.GetAssetGroupNodes(request.Context(), assetGroup.Tag); err != nil {
} else if assetGroupNodes, err := s.GraphQuery.GetAssetGroupNodes(request.Context(), assetGroup.Tag, assetGroup.SystemGroup); err != nil {
api.WriteErrorResponse(request.Context(), api.BuildErrorResponse(http.StatusInternalServerError, fmt.Sprintf("Graph error fetching nodes for asset group ID %v: %v", assetGroup.ID, err), request), response)
return agMembers, err
} else if agMembers, err = parseAGMembersFromNodes(assetGroupNodes, assetGroup.Selectors, int(assetGroup.ID)).SortBy(sortByColumns); err != nil {
Expand Down Expand Up @@ -520,16 +520,14 @@ func parseAGMembersFromNodes(nodes graph.NodeSet, selectors model.AssetGroupSele

if node.Kinds.ContainsOneOf(azure.Entity) {
if tenantID, err := node.Properties.Get(azure.TenantID.String()).String(); err != nil {
log.Warnf("%s is missing for node %d, skipping AG Membership...", azure.TenantID.String(), node.ID)
continue
log.Warnf("%s is missing for node %d", azure.TenantID.String(), node.ID)
} else {
agMember.EnvironmentKind = azure.Tenant.String()
agMember.EnvironmentID = tenantID
}
} else if node.Kinds.ContainsOneOf(ad.Entity) {
if domainSID, err := node.Properties.Get(ad.DomainSID.String()).String(); err != nil {
log.Warnf("%s is missing for node %d, skipping AG Membership...", ad.DomainSID.String(), node.ID)
continue
log.Warnf("%s is missing for node %d", ad.DomainSID.String(), node.ID)
} else {
agMember.EnvironmentKind = ad.Domain.String()
agMember.EnvironmentID = domainSID
Expand Down
4 changes: 2 additions & 2 deletions cmd/api/src/api/v2/agi_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ func TestParseAGMembersFromNodes_(t *testing.T) {

func TestParseAGMembersFromNodes_MissingNodeProperties(t *testing.T) {
nodes := graph.NodeSet{
// the parse fn should handle nodes with missing name and missing properties with warnings and no output
// the parse fn should handle nodes with missing name and missing properties with warnings
1: &graph.Node{
ID: 1,
Kinds: graph.Kinds{ad.Entity, ad.Domain},
Expand All @@ -125,5 +125,5 @@ func TestParseAGMembersFromNodes_MissingNodeProperties(t *testing.T) {
SystemSelector: false,
}}, 1)

require.Equal(t, 0, len(members))
require.Equal(t, 2, len(members))
}
20 changes: 10 additions & 10 deletions cmd/api/src/api/v2/agi_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1211,7 +1211,7 @@ func TestResources_ListAssetGroupMembers(t *testing.T) {
GetAssetGroup(gomock.Any(), gomock.Any()).
Return(assetGroup, nil)
mockGraph.EXPECT().
GetAssetGroupNodes(gomock.Any(), gomock.Any()).
GetAssetGroupNodes(gomock.Any(), gomock.Any(), gomock.Any()).
Return(graph.NodeSet{}, fmt.Errorf("GetAssetGroupNodes fail"))
},
Test: func(output apitest.Output) {
Expand All @@ -1228,7 +1228,7 @@ func TestResources_ListAssetGroupMembers(t *testing.T) {
GetAssetGroup(gomock.Any(), gomock.Any()).
Return(assetGroup, nil)
mockGraph.EXPECT().
GetAssetGroupNodes(gomock.Any(), gomock.Any()).
GetAssetGroupNodes(gomock.Any(), gomock.Any(), gomock.Any()).
Return(graph.NodeSet{
1: &graph.Node{
ID: 1,
Expand Down Expand Up @@ -1278,7 +1278,7 @@ func TestResources_ListAssetGroupMembers(t *testing.T) {
GetAssetGroup(gomock.Any(), gomock.Any()).
Return(assetGroup, nil)
mockGraph.EXPECT().
GetAssetGroupNodes(gomock.Any(), gomock.Any()).
GetAssetGroupNodes(gomock.Any(), gomock.Any(), gomock.Any()).
Return(graph.NodeSet{
1: &graph.Node{
ID: 1,
Expand Down Expand Up @@ -1314,7 +1314,7 @@ func TestResources_ListAssetGroupMembers(t *testing.T) {
GetAssetGroup(gomock.Any(), gomock.Any()).
Return(assetGroup, nil)
mockGraph.EXPECT().
GetAssetGroupNodes(gomock.Any(), gomock.Any()).
GetAssetGroupNodes(gomock.Any(), gomock.Any(), gomock.Any()).
Return(graph.NodeSet{
1: &graph.Node{
ID: 1,
Expand Down Expand Up @@ -1355,7 +1355,7 @@ func TestResources_ListAssetGroupMembers(t *testing.T) {
GetAssetGroup(gomock.Any(), gomock.Any()).
Return(assetGroup, nil)
mockGraph.EXPECT().
GetAssetGroupNodes(gomock.Any(), gomock.Any()).
GetAssetGroupNodes(gomock.Any(), gomock.Any(), gomock.Any()).
Return(graph.NodeSet{
1: &graph.Node{
ID: 1,
Expand Down Expand Up @@ -1398,7 +1398,7 @@ func TestResources_ListAssetGroupMembers(t *testing.T) {
GetAssetGroup(gomock.Any(), gomock.Any()).
Return(assetGroup, nil)
mockGraph.EXPECT().
GetAssetGroupNodes(gomock.Any(), gomock.Any()).
GetAssetGroupNodes(gomock.Any(), gomock.Any(), gomock.Any()).
Return(graph.NodeSet{
1: &graph.Node{
ID: 1,
Expand Down Expand Up @@ -1433,7 +1433,7 @@ func TestResources_ListAssetGroupMembers(t *testing.T) {
GetAssetGroup(gomock.Any(), gomock.Any()).
Return(assetGroup, nil)
mockGraph.EXPECT().
GetAssetGroupNodes(gomock.Any(), gomock.Any()).
GetAssetGroupNodes(gomock.Any(), gomock.Any(), gomock.Any()).
Return(graph.NodeSet{
1: &graph.Node{
ID: 1,
Expand Down Expand Up @@ -1574,7 +1574,7 @@ func TestResources_ListAssetGroupMembersCount(t *testing.T) {
GetAssetGroup(gomock.Any(), gomock.Any()).
Return(assetGroup, nil)
mockGraph.EXPECT().
GetAssetGroupNodes(gomock.Any(), gomock.Any()).
GetAssetGroupNodes(gomock.Any(), gomock.Any(), gomock.Any()).
Return(graph.NodeSet{}, fmt.Errorf("GetAssetGroupNodes fail"))
},
Test: func(output apitest.Output) {
Expand All @@ -1591,7 +1591,7 @@ func TestResources_ListAssetGroupMembersCount(t *testing.T) {
GetAssetGroup(gomock.Any(), gomock.Any()).
Return(assetGroup, nil)
mockGraph.EXPECT().
GetAssetGroupNodes(gomock.Any(), gomock.Any()).
GetAssetGroupNodes(gomock.Any(), gomock.Any(), gomock.Any()).
Return(graph.NodeSet{
1: &graph.Node{
ID: 1,
Expand Down Expand Up @@ -1627,7 +1627,7 @@ func TestResources_ListAssetGroupMembersCount(t *testing.T) {
GetAssetGroup(gomock.Any(), gomock.Any()).
Return(assetGroup, nil)
mockGraph.EXPECT().
GetAssetGroupNodes(gomock.Any(), gomock.Any()).
GetAssetGroupNodes(gomock.Any(), gomock.Any(), gomock.Any()).
Return(graph.NodeSet{
1: &graph.Node{
ID: 1,
Expand Down
13 changes: 6 additions & 7 deletions cmd/api/src/api/v2/file_uploads_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,10 @@ import (
"net/http"
"testing"

"github.com/specterops/bloodhound/mediatypes"
"github.com/specterops/bloodhound/src/services/fileupload"

"github.com/specterops/bloodhound/headers"
"github.com/specterops/bloodhound/mediatypes"
"github.com/specterops/bloodhound/src/api/v2/integration"
"github.com/specterops/bloodhound/src/services/fileupload"
"github.com/specterops/bloodhound/src/test/fixtures/fixtures"
"github.com/stretchr/testify/assert"
)
Expand Down Expand Up @@ -170,7 +169,7 @@ func Test_FileUploadWorkFlowVersion5(t *testing.T) {
"v5/ingest/sessions.json",
})

//Assert that we created stuff we expected
// Assert that we created stuff we expected
testCtx.AssertIngest(fixtures.IngestAssertions)
}

Expand All @@ -189,7 +188,7 @@ func Test_FileUploadWorkFlowVersion6(t *testing.T) {
"v6/ingest/sessions.json",
})

//Assert that we created stuff we expected
// Assert that we created stuff we expected
testCtx.AssertIngest(fixtures.IngestAssertions)
testCtx.AssertIngest(fixtures.IngestAssertionsv6)
testCtx.AssertIngest(fixtures.PropertyAssertions)
Expand Down Expand Up @@ -240,7 +239,7 @@ func Test_CompressedFileUploadWorkFlowVersion5(t *testing.T) {
"v5/ingest/sessions.json",
})

//Assert that we created stuff we expected
// Assert that we created stuff we expected
testCtx.AssertIngest(fixtures.IngestAssertions)
testCtx.AssertIngest(fixtures.PropertyAssertions)
}
Expand All @@ -260,7 +259,7 @@ func Test_CompressedFileUploadWorkFlowVersion6(t *testing.T) {
"v6/ingest/sessions.json",
})

//Assert that we created stuff we expected
// Assert that we created stuff we expected
testCtx.AssertIngest(fixtures.IngestAssertions)
testCtx.AssertIngest(fixtures.IngestAssertionsv6)
testCtx.AssertIngest(fixtures.PropertyAssertions)
Expand Down
3 changes: 1 addition & 2 deletions cmd/api/src/daemons/datapipe/analysis.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import (
"errors"
"fmt"

"github.com/specterops/bloodhound/analysis"
adAnalysis "github.com/specterops/bloodhound/analysis/ad"
"github.com/specterops/bloodhound/dawgs/graph"
"github.com/specterops/bloodhound/log"
Expand Down Expand Up @@ -92,7 +91,7 @@ func RunAnalysisOperations(ctx context.Context, db database.Database, graphDB gr
stats.LogStats()
}

if err := agi.RunAssetGroupIsolationCollections(ctx, db, graphDB, analysis.GetNodeKindDisplayLabel); err != nil {
if err := agi.RunAssetGroupIsolationCollections(ctx, db, graphDB); err != nil {
collectedErrors = append(collectedErrors, fmt.Errorf("asset group isolation collection failed: %w", err))
agiFailed = true
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/api/src/database/saved_queries.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ func (s *BloodhoundDB) GetSharedSavedQueries(ctx context.Context, userID uuid.UU
func (s *BloodhoundDB) GetPublicSavedQueries(ctx context.Context) (model.SavedQueries, error) {
savedQueries := model.SavedQueries{}

result := s.db.WithContext(ctx).Select("sqp.*").Joins("JOIN saved_queries_permissions sqp ON sqp.query_id = saved_queries.id").Where("sqp.public = true").Find(&savedQueries)
result := s.db.WithContext(ctx).Select("saved_queries.*").Joins("JOIN saved_queries_permissions sqp ON sqp.query_id = saved_queries.id").Where("sqp.public = true").Find(&savedQueries)

return savedQueries, CheckError(result)
}
Expand Down
4 changes: 2 additions & 2 deletions cmd/api/src/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ require (
github.com/pquerna/otp v1.4.0
github.com/prometheus/client_golang v1.16.0
github.com/russellhaering/goxmldsig v1.4.0
github.com/stretchr/testify v1.8.4
github.com/stretchr/testify v1.9.0
github.com/unrolled/secure v1.13.0
github.com/zenazn/goji v1.0.1
go.uber.org/mock v0.2.0
Expand Down Expand Up @@ -79,7 +79,7 @@ require (
github.com/prometheus/procfs v0.11.0 // indirect
github.com/rivo/uniseg v0.4.4 // indirect
golang.org/x/sys v0.21.0 // indirect
golang.org/x/text v0.16.0 // indirect
golang.org/x/text v0.17.0 // indirect
golang.org/x/time v0.3.0 // indirect
google.golang.org/protobuf v1.34.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
Expand Down
10 changes: 3 additions & 7 deletions cmd/api/src/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,6 @@ github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH
github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q=
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gorilla/schema v1.2.0 h1:YufUaxZYCKGFuAq3c96BOhjgd5nmXiOY9NGzF247Tsc=
github.com/gorilla/schema v1.2.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU=
github.com/gorilla/schema v1.4.1 h1:jUg5hUjCSDZpNGLuXQOgIWGdlgrIdYvgQ0wZtdK1M3E=
github.com/gorilla/schema v1.4.1/go.mod h1:Dg5SSm5PV60mhF2NFaTV1xuYYj8tV8NOPRo4FggUMnM=
github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo=
Expand Down Expand Up @@ -211,8 +209,7 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.4/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/unrolled/secure v1.13.0 h1:sdr3Phw2+f8Px8HE5sd1EHdj1aV3yUwed/uZXChLFsk=
github.com/unrolled/secure v1.13.0/go.mod h1:BmF5hyM6tXczk3MpQkFf1hpKSRqCyhqcbiQtiAF7+40=
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
Expand Down Expand Up @@ -253,7 +250,7 @@ golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
Expand All @@ -277,8 +274,7 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
Expand Down
24 changes: 4 additions & 20 deletions cmd/api/src/model/filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,13 @@ const (
LessThanOrEquals FilterOperator = "lte"
Equals FilterOperator = "eq"
NotEquals FilterOperator = "neq"
Contains FilterOperator = "in"

GreaterThanSymbol string = ">"
GreaterThanOrEqualsSymbol string = ">="
LessThanSymbol string = "<"
LessThanOrEqualsSymbol string = "<="
EqualsSymbol string = "="
NotEqualsSymbol string = "<>"
ContainsSymbol string = "like"

TrueString = "true"
FalseString = "false"
Expand Down Expand Up @@ -81,9 +79,6 @@ func ParseFilterOperator(raw string) (FilterOperator, error) {
case NotEquals:
return NotEquals, nil

case Contains:
return Contains, nil

default:
return "", fmt.Errorf("unknown query parameter filter predicate: %s", raw)
}
Expand Down Expand Up @@ -170,25 +165,14 @@ func (s QueryParameterFilterMap) BuildSQLFilter() (SQLFilter, error) {
predicate = EqualsSymbol
case NotEquals:
predicate = NotEqualsSymbol
case Contains:
predicate = ContainsSymbol
default:
return SQLFilter{}, fmt.Errorf("invalid filter predicate specified")
}

switch predicate {
case ContainsSymbol:
result.WriteString(filter.Name)
result.WriteString(" ")
result.WriteString(predicate)
filter.Value = fmt.Sprintf("%%%s%%", filter.Value)
result.WriteString(" lower(?)")
default:
result.WriteString(filter.Name)
result.WriteString(" ")
result.WriteString(predicate)
result.WriteString(" ?")
}
result.WriteString(filter.Name)
result.WriteString(" ")
result.WriteString(predicate)
result.WriteString(" ?")

params = append(params, filter.Value)
firstFilter = false
Expand Down
27 changes: 9 additions & 18 deletions cmd/api/src/model/filter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,28 +76,19 @@ func TestModel_BuildSQLFilter_Success(t *testing.T) {
IsStringData: false,
}

stringContains := model.QueryParameterFilter{
Name: "filtercolumn6",
Operator: model.Contains,
Value: "something",
IsStringData: true,
}

expectedResults := map[string]model.SQLFilter{
"numericMin": {SQLString: fmt.Sprintf("%s > ?", numericMin.Name), Params: []any{numericMin.Value}},
"numericMax": {SQLString: fmt.Sprintf("%s < ?", numericMax.Name), Params: []any{numericMax.Value}},
"stringValue": {SQLString: fmt.Sprintf("%s = ?", stringValue.Name), Params: []any{stringValue.Value}},
"boolEquals": {SQLString: fmt.Sprintf("%s = ?", boolEquals.Name), Params: []any{boolEquals.Value}},
"boolNotEquals": {SQLString: fmt.Sprintf("%s <> ?", boolNotEquals.Name), Params: []any{boolNotEquals.Value}},
"stringContains": {SQLString: fmt.Sprintf("%s like lower(?)", stringContains.Name), Params: []any{stringContains.Value}},
"numericMin": {SQLString: fmt.Sprintf("%s > ?", numericMin.Name), Params: []any{numericMin.Value}},
"numericMax": {SQLString: fmt.Sprintf("%s < ?", numericMax.Name), Params: []any{numericMax.Value}},
"stringValue": {SQLString: fmt.Sprintf("%s = ?", stringValue.Name), Params: []any{stringValue.Value}},
"boolEquals": {SQLString: fmt.Sprintf("%s = ?", boolEquals.Name), Params: []any{boolEquals.Value}},
"boolNotEquals": {SQLString: fmt.Sprintf("%s <> ?", boolNotEquals.Name), Params: []any{boolNotEquals.Value}},
}

queryParameterFilterMap := model.QueryParameterFilterMap{
numericMax.Name: model.QueryParameterFilters{numericMin, numericMax},
stringValue.Name: model.QueryParameterFilters{stringValue},
boolEquals.Name: model.QueryParameterFilters{boolEquals},
boolNotEquals.Name: model.QueryParameterFilters{boolNotEquals},
stringContains.Name: model.QueryParameterFilters{stringContains},
numericMax.Name: model.QueryParameterFilters{numericMin, numericMax},
stringValue.Name: model.QueryParameterFilters{stringValue},
boolEquals.Name: model.QueryParameterFilters{boolEquals},
boolNotEquals.Name: model.QueryParameterFilters{boolNotEquals},
}

result, err := queryParameterFilterMap.BuildSQLFilter()
Expand Down
2 changes: 1 addition & 1 deletion cmd/api/src/model/saved_queries.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func (s SavedQueries) ValidFilters() map[string][]FilterOperator {
"user_id": {Equals, NotEquals},
"name": {Equals, NotEquals},
"query": {Equals, NotEquals},
"description": {Equals, NotEquals, Contains},
"description": {Equals, NotEquals},
}
}

Expand Down
7 changes: 1 addition & 6 deletions cmd/api/src/model/saved_queries_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,7 @@ func TestSavedQueries_ValidFilters(t *testing.T) {
for _, column := range []string{"user_id", "name", "query", "description"} {
operators, ok := validFilters[column]
require.True(t, ok)
switch column {
case "description":
require.Equal(t, 3, len(operators))
default:
require.Equal(t, 2, len(operators))
}
require.Equal(t, 2, len(operators))
}
}

Expand Down
Loading

0 comments on commit b5aff8b

Please sign in to comment.