Skip to content

Commit

Permalink
chore(query): add tests for parsing contextual tuples
Browse files Browse the repository at this point in the history
  • Loading branch information
rhamzeh committed Jul 5, 2023
1 parent 192555a commit de9900b
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 6 deletions.
2 changes: 1 addition & 1 deletion cmd/query/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func init() {
QueryCmd.AddCommand(listRelationsCmd)

QueryCmd.PersistentFlags().String("store-id", "", "Store ID")
QueryCmd.PersistentFlags().StringArray("contextual-tuple", []string{}, `Contextual Tuple, format: "user_type:user_id relation object_type:object_id"`) //nolint:lll
QueryCmd.PersistentFlags().StringArray("contextual-tuple", []string{}, `Contextual Tuple, format: "user relation object"`) //nolint:lll

err := QueryCmd.MarkPersistentFlagRequired("store-id")
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion lib/clierrors/clierrors.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ import (
var ErrValidation = errors.New("validation error")

func ValidationError(op string, details string) error {
return fmt.Errorf("%w : %s - %s", ErrValidation, op, details)
return fmt.Errorf("%w - %s: %s", ErrValidation, op, details)
}
13 changes: 9 additions & 4 deletions lib/cmd-utils/get-contextual-tuples.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,16 @@ import (
"github.com/spf13/cobra"
)

func ParseContextualTuples(cmd *cobra.Command) ([]client.ClientTupleKey, error) {
func ParseContextualTuplesInner(contextualTuplesArray []string) ([]client.ClientTupleKey, error) {
contextualTuples := []client.ClientTupleKey{}
contextualTuplesArray, _ := cmd.Flags().GetStringArray("contextual-tuple")

if len(contextualTuplesArray) > 0 {
for index := 0; index < len(contextualTuplesArray); index++ {
tuple := strings.Split(contextualTuplesArray[index], " ")
if len(tuple) != 3 { //nolint:gomnd
return contextualTuples,
clierrors.ValidationError("ParseContextualTuples", "Failed to parse contextual tuples,"+ //nolint:wrapcheck
"they must be of the format\"user_type:user_id relation object_type:object_id\" ")
clierrors.ValidationError("ParseContextualTuplesInner", "Failed to parse contextual tuples, "+ //nolint:wrapcheck
"they must be of the format\"user relation object\" ")
}

contextualTuples = append(contextualTuples, client.ClientTupleKey{
Expand All @@ -31,3 +30,9 @@ func ParseContextualTuples(cmd *cobra.Command) ([]client.ClientTupleKey, error)

return contextualTuples, nil
}

func ParseContextualTuples(cmd *cobra.Command) ([]client.ClientTupleKey, error) {
contextualTuplesArray, _ := cmd.Flags().GetStringArray("contextual-tuple")

return ParseContextualTuplesInner(contextualTuplesArray)
}
102 changes: 102 additions & 0 deletions lib/cmd-utils/get-contextual-tuples_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package cmdutils_test

import (
"testing"

cmdutils "github.com/openfga/cli/lib/cmd-utils"
"github.com/openfga/go-sdk/client"
)

type tupleTestPassing struct {
raw []string
parsed []client.ClientTupleKey
}

type tupleTestFailing struct {
raw []string
}

func TestGetContextualTuplesWithNoError(t *testing.T) {
t.Parallel()

tests := []tupleTestPassing{{
raw: []string{"user:anne can_view document:2"},
parsed: []client.ClientTupleKey{
{User: "user:anne", Relation: "can_view", Object: "document:2"},
},
}, {
raw: []string{
"group:product#member owner document:roadmap",
"user:beth can_delete folder:marketing",
"user:carl can_share repo:openfga/openfga",
},
parsed: []client.ClientTupleKey{
{User: "group:product#member", Relation: "owner", Object: "document:roadmap"},
{User: "user:beth", Relation: "can_delete", Object: "folder:marketing"},
{User: "user:carl", Relation: "can_share", Object: "repo:openfga/openfga"},
},
}, {
// Note that this is an invalid tuple, but the server will let us know that.
// We can validate against it in a future iteration
raw: []string{"anne can_view document-2"},
parsed: []client.ClientTupleKey{
{User: "anne", Relation: "can_view", Object: "document-2"},
},
}}

for index := 0; index < len(tests); index++ {
test := tests[index]
t.Run("TestGetContextualTuplesWithNoError"+string(rune(index)), func(t *testing.T) {
t.Parallel()
tuples, err := cmdutils.ParseContextualTuplesInner(test.raw)
if err != nil {
t.Error(err)
}

if len(tuples) != len(test.parsed) {
t.Errorf("Expected parsed tuples to have length %v actual %v", len(test.parsed), len(tuples))
}

for index := 0; index < len(tuples); index++ {
if tuples[index].User != test.parsed[index].User ||
tuples[index].Relation != test.parsed[index].Relation ||
tuples[index].Object != test.parsed[index].Object {
t.Errorf("Expected parsed tuples to match %v actual %v", test.parsed, tuples)
}
}
})
}
}

func TestGetContextualTuplesWithError(t *testing.T) {
t.Parallel()

tests := []tupleTestFailing{{
raw: []string{"user:anne can_view"},
}, {
raw: []string{"can_view document:2"},
}, {
raw: []string{"can_view"},
}, {
raw: []string{"this is not a valid tuple"},
}, {
raw: []string{
"group:product#member owner document:roadmap",
"user:beth can_delete folder:marketing",
"user:carl can_share repo:openfga/openfga",
"user:dan can_share",
},
}}

for index := 0; index < len(tests); index++ {
test := tests[index]
t.Run("TestGetContextualTuplesWithNoError"+string(rune(index)), func(t *testing.T) {
t.Parallel()
_, err := cmdutils.ParseContextualTuplesInner(test.raw)

if err == nil {
t.Error("Expect error but there is none")
}
})
}
}

0 comments on commit de9900b

Please sign in to comment.