From 85072f6102a19a378302cf4e32c6f981f09c4bd9 Mon Sep 17 00:00:00 2001 From: Gabriel Bussolo Date: Wed, 27 Sep 2023 17:30:01 +0300 Subject: [PATCH] feat: create the --simple-json flag for tuple read Signed-off-by: Gabriel Bussolo --- README.md | 17 ++++++++++-- cmd/tuple/read.go | 25 +++++++++++++++--- cmd/tuple/read_test.go | 60 +++++++++++++++++++++++++++++++++++------- 3 files changed, 86 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 14dffad..d315456 100644 --- a/README.md +++ b/README.md @@ -656,7 +656,7 @@ fga tuple **delete** --store-id= If you want to delete all the tuples in a store, you can use the following code: ``` -fga tuple read | jq '[.tuples[] | { user: .key.user, relation: .key.relation, object: .key.object }]' > tuples.json +fga tuple read --simple-json > tuples.json fga tuple delete --file tuples.json ``` @@ -670,6 +670,8 @@ fga tuple **read** [--user=] [--relation=] [--object=] * `--user`: User * `--relation`: Relation * `--object`: Object +* `--max-pages`: Max number of pages to get. (default 20) +* `--simple-json`: Output simpler JSON version. (It can be used by write and delete commands) ###### Example `fga tuple read --store-id=01H0H015178Y2V4CX10C2KGHF4 --user user:anne --relation can_view --object document:roadmap` @@ -689,11 +691,22 @@ fga tuple **read** [--user=] [--relation=] [--object=] ] } ``` +###### Response (--simple-json) +```json5 +[ + { + "object": "document:roadmap", + "relation": "can_view", + "user": "user:anne" + } +] +``` + If you want to transform this output in a way that can be then imported using the `fga tuple import` you can run ``` -fga tuple read | jq '[.tuples[] | { user: .key.user, relation: .key.relation, object: .key.object }]' > tuples.json +fga tuple read --simple-json > tuples.json fga tuple import --file tuples.json ``` diff --git a/cmd/tuple/read.go b/cmd/tuple/read.go index 35418d6..fb6cd33 100644 --- a/cmd/tuple/read.go +++ b/cmd/tuple/read.go @@ -30,8 +30,13 @@ import ( // MaxReadPagesLength Limit the tuples so that we are not paginating indefinitely. var MaxReadPagesLength = 20 +type readResponse struct { + complete *openfga.ReadResponse + simple []openfga.TupleKey +} + func read(fgaClient client.SdkClient, user string, relation string, object string, maxPages int) ( - *openfga.ReadResponse, error, + *readResponse, error, ) { body := &client.ClientReadRequest{} if user != "" { @@ -47,7 +52,6 @@ func read(fgaClient client.SdkClient, user string, relation string, object strin } tuples := make([]openfga.Tuple, 0) - continuationToken := "" pageIndex := 0 options := client.ClientReadOptions{} @@ -70,7 +74,14 @@ func read(fgaClient client.SdkClient, user string, relation string, object strin continuationToken = *response.ContinuationToken } - return &openfga.ReadResponse{Tuples: &tuples}, nil + justKeys := make([]openfga.TupleKey, 0) + for _, tuple := range tuples { + justKeys = append(justKeys, *tuple.Key) + } + + res := readResponse{complete: &openfga.ReadResponse{Tuples: &tuples}, simple: justKeys} + + return &res, nil } // readCmd represents the read command. @@ -101,7 +112,12 @@ var readCmd = &cobra.Command{ return err } - return output.Display(*response) //nolint:wrapcheck + simpleJSON, _ := cmd.Flags().GetBool("simple-json") + if simpleJSON { + return output.Display(response.simple) //nolint:wrapcheck + } + + return output.Display(*response.complete) //nolint:wrapcheck }, } @@ -110,4 +126,5 @@ func init() { readCmd.Flags().String("relation", "", "Relation") readCmd.Flags().String("object", "", "Object") readCmd.Flags().Int("max-pages", MaxReadPagesLength, "Max number of pages to get.") + readCmd.Flags().Bool("simple-json", false, "Output simpler JSON version. (It can be used by write and delete commands)") //nolint:lll } diff --git a/cmd/tuple/read_test.go b/cmd/tuple/read_test.go index 33693a8..ef5c8fb 100644 --- a/cmd/tuple/read_test.go +++ b/cmd/tuple/read_test.go @@ -91,14 +91,24 @@ func TestReadEmpty(t *testing.T) { } expectedOutput := "{\"tuples\":[]}" + simpleOutput := "[]" - outputTxt, err := json.Marshal(output) + outputTxt, err := json.Marshal(output.complete) if err != nil { t.Error(err) } if string(outputTxt) != expectedOutput { - t.Errorf("Expected output %v actual %v", expectedOutput, output) + t.Errorf("Expected output %v actual %v", expectedOutput, output.complete) + } + + simpleTxt, err := json.Marshal(output.simple) + if err != nil { + t.Error(err) + } + + if string(simpleTxt) != simpleOutput { + t.Errorf("Expected output %v actual %v", simpleOutput, output.simple) } } @@ -153,15 +163,25 @@ func TestReadSinglePage(t *testing.T) { t.Error(err) } - expectedOutput := "{\"tuples\":[{\"key\":{\"object\":\"document:doc1\",\"relation\":\"reader\",\"user\":\"user:user1\"},\"timestamp\":\"2009-11-10T23:00:00Z\"}]}" //nolint:lll + expectedOutput := `{"tuples":[{"key":{"object":"document:doc1","relation":"reader","user":"user:user1"},"timestamp":"2009-11-10T23:00:00Z"}]}` //nolint:lll + simpleOutput := `[{"object":"document:doc1","relation":"reader","user":"user:user1"}]` //nolint:lll - outputTxt, err := json.Marshal(output) + outputTxt, err := json.Marshal(output.complete) if err != nil { t.Error(err) } if string(outputTxt) != expectedOutput { - t.Errorf("Expected output %v actual %v", expectedOutput, output) + t.Errorf("Expected output %v actual %v", expectedOutput, output.complete) + } + + simpleTxt, err := json.Marshal(output.simple) + if err != nil { + t.Error(err) + } + + if string(simpleTxt) != simpleOutput { + t.Errorf("Expected output %v actual %v", simpleOutput, output.simple) } } @@ -256,14 +276,24 @@ func TestReadMultiPages(t *testing.T) { } expectedOutput := `{"tuples":[{"key":{"object":"document:doc1","relation":"reader","user":"user:user1"},"timestamp":"2009-11-10T22:00:00Z"},{"key":{"object":"document:doc2","relation":"reader","user":"user:user1"},"timestamp":"2009-11-10T23:00:00Z"}]}` //nolint:lll + simpleOutput := `[{"object":"document:doc1","relation":"reader","user":"user:user1"},{"object":"document:doc2","relation":"reader","user":"user:user1"}]` //nolint:lll - outputTxt, err := json.Marshal(output) + outputTxt, err := json.Marshal(output.complete) if err != nil { t.Error(err) } if string(outputTxt) != expectedOutput { - t.Errorf("Expected output %v actual %v", expectedOutput, output) + t.Errorf("Expected output %v actual %v", expectedOutput, output.complete) + } + + simpleTxt, err := json.Marshal(output.simple) + if err != nil { + t.Error(err) + } + + if string(simpleTxt) != simpleOutput { + t.Errorf("Expected output %v actual %v", simpleOutput, output.simple) } } @@ -318,14 +348,24 @@ func TestReadMultiPagesMaxLimit(t *testing.T) { t.Error(err) } - expectedOutput := "{\"tuples\":[{\"key\":{\"object\":\"document:doc1\",\"relation\":\"reader\",\"user\":\"user:user1\"},\"timestamp\":\"2009-11-10T23:00:00Z\"}]}" //nolint:lll + expectedOutput := `{"tuples":[{"key":{"object":"document:doc1","relation":"reader","user":"user:user1"},"timestamp":"2009-11-10T23:00:00Z"}]}` //nolint:lll + simpleOutput := `[{"object":"document:doc1","relation":"reader","user":"user:user1"}]` //nolint:lll - outputTxt, err := json.Marshal(output) + outputTxt, err := json.Marshal(output.complete) if err != nil { t.Error(err) } if string(outputTxt) != expectedOutput { - t.Errorf("Expected output %v actual %v", expectedOutput, output) + t.Errorf("Expected output %v actual %v", expectedOutput, output.complete) + } + + simpleTxt, err := json.Marshal(output.simple) + if err != nil { + t.Error(err) + } + + if string(simpleTxt) != simpleOutput { + t.Errorf("Expected output %v actual %v", simpleOutput, output.simple) } }