Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions internal/services/v1/relationships.go
Original file line number Diff line number Diff line change
Expand Up @@ -577,9 +577,21 @@ func validateRelationshipsFilter(ctx context.Context, filter *v1.RelationshipFil
}
}

// Ensure the resource ID and the resource ID prefix are not set at the same time.
if filter.OptionalResourceId != "" && filter.OptionalResourceIdPrefix != "" {
return NewInvalidFilterErr("resource_id and resource_id_prefix cannot be set at the same time", filter.String())
// Use counter-based validation for mutual exclusion of resource ID fields
resourceIdFieldsCount := 0
if filter.OptionalResourceId != "" {
resourceIdFieldsCount++
}
if filter.OptionalResourceIdPrefix != "" {
resourceIdFieldsCount++
}
if len(filter.OptionalResourceIds) > 0 {
resourceIdFieldsCount++
}

// Ensure only one resource ID field type is set at a time
if resourceIdFieldsCount > 1 {
return NewInvalidFilterErr("only one of resource_id, resource_id_prefix, or resource_ids can be set at the same time", filter.String())
}

// Ensure that at least one field is set.
Expand All @@ -590,6 +602,7 @@ func checkIfFilterIsEmpty(filter *v1.RelationshipFilter) error {
if filter.ResourceType == "" &&
filter.OptionalResourceId == "" &&
filter.OptionalResourceIdPrefix == "" &&
len(filter.OptionalResourceIds) == 0 &&
filter.OptionalRelation == "" &&
filter.OptionalSubjectFilter == nil {
return NewInvalidFilterErr("at least one field must be set", filter.String())
Expand Down
20 changes: 16 additions & 4 deletions pkg/datastore/datastore.go
Original file line number Diff line number Diff line change
Expand Up @@ -331,9 +331,25 @@ func RelationshipsFilterFromCoreFilter(filter *core.RelationshipFilter) (Relatio
// RelationshipsFilterFromPublicFilter constructs a datastore RelationshipsFilter from an API-defined RelationshipFilter.
func RelationshipsFilterFromPublicFilter(filter *v1.RelationshipFilter) (RelationshipsFilter, error) {
var resourceIds []string

// Handle resource ID fields with mutual exclusion logic
resourceIdFieldsCount := 0
if filter.OptionalResourceId != "" {
resourceIdFieldsCount++
resourceIds = []string{filter.OptionalResourceId}
}
if filter.OptionalResourceIdPrefix != "" {
resourceIdFieldsCount++
}
if len(filter.OptionalResourceIds) > 0 {
resourceIdFieldsCount++
resourceIds = filter.OptionalResourceIds
}

// Ensure only one resource ID field type is set
if resourceIdFieldsCount > 1 {
return RelationshipsFilter{}, fmt.Errorf("cannot specify more than one of OptionalResourceId, OptionalResourceIdPrefix, or OptionalResourceIds")
}

var subjectsSelectors []SubjectsSelector
if filter.OptionalSubjectFilter != nil {
Expand All @@ -360,10 +376,6 @@ func RelationshipsFilterFromPublicFilter(filter *v1.RelationshipFilter) (Relatio
})
}

if filter.OptionalResourceId != "" && filter.OptionalResourceIdPrefix != "" {
return RelationshipsFilter{}, fmt.Errorf("cannot specify both OptionalResourceId and OptionalResourceIDPrefix")
}

if filter.ResourceType == "" && filter.OptionalRelation == "" && len(resourceIds) == 0 && filter.OptionalResourceIdPrefix == "" && len(subjectsSelectors) == 0 {
return RelationshipsFilter{}, fmt.Errorf("at least one filter field must be set")
}
Expand Down
81 changes: 81 additions & 0 deletions pkg/datastore/datastore_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,87 @@ func TestRelationshipsFilterFromPublicFilter(t *testing.T) {
},
"",
},
{
"bulk resource ids single",
&v1.RelationshipFilter{
ResourceType: "sometype",
OptionalResourceIds: []string{"id1"},
OptionalRelation: "somerel",
},
RelationshipsFilter{
OptionalResourceType: "sometype",
OptionalResourceIds: []string{"id1"},
OptionalResourceRelation: "somerel",
},
"",
},
{
"bulk resource ids multiple",
&v1.RelationshipFilter{
ResourceType: "sometype",
OptionalResourceIds: []string{"id1", "id2", "id3"},
OptionalRelation: "somerel",
},
RelationshipsFilter{
OptionalResourceType: "sometype",
OptionalResourceIds: []string{"id1", "id2", "id3"},
OptionalResourceRelation: "somerel",
},
"",
},
{
"bulk resource ids with subject filter",
&v1.RelationshipFilter{
ResourceType: "sometype",
OptionalResourceIds: []string{"id1", "id2"},
OptionalRelation: "somerel",
OptionalSubjectFilter: &v1.SubjectFilter{
SubjectType: "someothertype",
},
},
RelationshipsFilter{
OptionalResourceType: "sometype",
OptionalResourceIds: []string{"id1", "id2"},
OptionalResourceRelation: "somerel",
OptionalSubjectsSelectors: []SubjectsSelector{
{
OptionalSubjectType: "someothertype",
},
},
},
"",
},
{
"error: resource_id and resource_ids both set",
&v1.RelationshipFilter{
ResourceType: "sometype",
OptionalResourceId: "single_id",
OptionalResourceIds: []string{"id1", "id2"},
},
RelationshipsFilter{},
"cannot specify more than one of OptionalResourceId, OptionalResourceIdPrefix, or OptionalResourceIds",
},
{
"error: resource_id_prefix and resource_ids both set",
&v1.RelationshipFilter{
ResourceType: "sometype",
OptionalResourceIdPrefix: "prefix_",
OptionalResourceIds: []string{"id1", "id2"},
},
RelationshipsFilter{},
"cannot specify more than one of OptionalResourceId, OptionalResourceIdPrefix, or OptionalResourceIds",
},
{
"error: all three resource id fields set",
&v1.RelationshipFilter{
ResourceType: "sometype",
OptionalResourceId: "single_id",
OptionalResourceIdPrefix: "prefix_",
OptionalResourceIds: []string{"id1", "id2"},
},
RelationshipsFilter{},
"cannot specify more than one of OptionalResourceId, OptionalResourceIdPrefix, or OptionalResourceIds",
},
}

for _, test := range tests {
Expand Down