Skip to content

Commit

Permalink
feat: create the --simple-json flag for tuple read (#168)
Browse files Browse the repository at this point in the history
  • Loading branch information
rhamzeh authored Oct 9, 2023
2 parents 7503c3a + 85072f6 commit 4adc839
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 16 deletions.
17 changes: 15 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -656,7 +656,7 @@ fga tuple **delete** <user> <relation> <object> --store-id=<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
```

Expand All @@ -670,6 +670,8 @@ fga tuple **read** [--user=<user>] [--relation=<relation>] [--object=<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`
Expand All @@ -689,11 +691,22 @@ fga tuple **read** [--user=<user>] [--relation=<relation>] [--object=<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
```
Expand Down
25 changes: 21 additions & 4 deletions cmd/tuple/read.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 != "" {
Expand All @@ -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{}
Expand All @@ -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.
Expand Down Expand Up @@ -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
},
}

Expand All @@ -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
}
60 changes: 50 additions & 10 deletions cmd/tuple/read_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}

Expand Down Expand Up @@ -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)
}
}

Expand Down Expand Up @@ -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)
}
}

Expand Down Expand Up @@ -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)
}
}

0 comments on commit 4adc839

Please sign in to comment.