Skip to content

Commit 63895d9

Browse files
committed
feat: import assertions when importing store
1 parent 343dbf9 commit 63895d9

File tree

3 files changed

+135
-3
lines changed

3 files changed

+135
-3
lines changed

cmd/store/create.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@ func CreateStoreWithModel(
6565

6666
response.Store = *createStoreResponse
6767

68+
err = fgaClient.SetStoreId(response.Store.Id)
69+
if err != nil {
70+
return nil, err
71+
}
72+
6873
if inputModel != "" {
6974
authModel := authorizationmodel.AuthzModel{}
7075

cmd/store/import.go

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,11 +123,14 @@ func importStore(
123123
return nil, err
124124
}
125125

126-
if len(storeData.Tuples) == 0 {
127-
return response, nil
126+
if len(storeData.Tuples) != 0 {
127+
err = importTuples(fgaClient, storeData.Tuples, maxTuplesPerWrite, maxParallelRequests)
128+
if err != nil {
129+
return nil, err
130+
}
128131
}
129132

130-
err = importTuples(fgaClient, storeData.Tuples, maxTuplesPerWrite, maxParallelRequests)
133+
err = importAssertions(fgaClient, storeData.Tests, response.Store.Id, response.Model.AuthorizationModelId)
131134
if err != nil {
132135
return nil, err
133136
}
@@ -184,6 +187,47 @@ func importTuples(
184187
return nil
185188
}
186189

190+
func importAssertions(
191+
fgaClient client.SdkClient,
192+
modelTests []storetest.ModelTest,
193+
storeId string,
194+
modelId string,
195+
) error {
196+
var assertions []client.ClientAssertion
197+
198+
for _, modelTest := range modelTests {
199+
checkAssertions := getCheckAssertions(modelTest.Check)
200+
assertions = append(assertions, checkAssertions...)
201+
}
202+
203+
writeOptions := client.ClientWriteAssertionsOptions{
204+
AuthorizationModelId: &modelId,
205+
StoreId: &storeId,
206+
}
207+
208+
if _, err := fgaClient.WriteAssertions(context.Background()).Body(assertions).Options(writeOptions).Execute(); err != nil {
209+
return fmt.Errorf("failed to import assertions: %w", err)
210+
}
211+
return nil
212+
}
213+
214+
func getCheckAssertions(checkTests []storetest.ModelTestCheck) []client.ClientAssertion {
215+
var assertions []client.ClientAssertion
216+
217+
for _, checkTest := range checkTests {
218+
for relation, expectation := range checkTest.Assertions {
219+
assertions = append(assertions, client.ClientAssertion{
220+
User: checkTest.User,
221+
Relation: relation,
222+
Object: checkTest.Object,
223+
Expectation: expectation,
224+
})
225+
}
226+
}
227+
228+
return assertions
229+
}
230+
187231
func createProgressBar(total int) *progressbar.ProgressBar {
188232
return progressbar.NewOptions(total,
189233
progressbar.OptionSetWriter(os.Stderr),

cmd/store/import_test.go

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package store
2+
3+
import (
4+
"context"
5+
"github.com/openfga/cli/internal/fga"
6+
mockclient "github.com/openfga/cli/internal/mocks"
7+
"github.com/openfga/cli/internal/storetest"
8+
"github.com/openfga/go-sdk/client"
9+
"go.uber.org/mock/gomock"
10+
"testing"
11+
)
12+
13+
func TestImportStore(t *testing.T) {
14+
t.Parallel()
15+
16+
t.Run("imports assertions into store", func(t *testing.T) {
17+
mockCtrl := gomock.NewController(t)
18+
defer mockCtrl.Finish()
19+
20+
mockFgaClient := mockclient.NewMockSdkClient(mockCtrl)
21+
clientConfig := fga.ClientConfig{}
22+
23+
mockWriteAssertions := mockclient.NewMockSdkClientWriteAssertionsRequestInterface(mockCtrl)
24+
mockCreateStore := mockclient.NewMockSdkClientCreateStoreRequestInterface(mockCtrl)
25+
mockWriteModel := mockclient.NewMockSdkClientWriteAuthorizationModelRequestInterface(mockCtrl)
26+
27+
expectedAssertions := []client.ClientAssertion{{
28+
User: "user:anne",
29+
Relation: "reader",
30+
Object: "document:doc1",
31+
Expectation: true,
32+
}}
33+
34+
modelID := "model-1"
35+
storeID := "store-1"
36+
expectedOptions := client.ClientWriteAssertionsOptions{
37+
AuthorizationModelId: &modelID,
38+
StoreId: &storeID,
39+
}
40+
41+
mockFgaClient.EXPECT().CreateStore(context.Background()).Return(mockCreateStore)
42+
mockCreateStore.EXPECT().Body(gomock.Any()).Return(mockCreateStore)
43+
mockCreateStore.EXPECT().Execute().Return(&client.ClientCreateStoreResponse{Id: "store-1"}, nil)
44+
45+
mockFgaClient.EXPECT().SetStoreId("store-1")
46+
47+
mockFgaClient.EXPECT().WriteAuthorizationModel(context.Background()).Return(mockWriteModel)
48+
mockWriteModel.EXPECT().Body(gomock.Any()).Return(mockWriteModel)
49+
mockWriteModel.EXPECT().Execute().Return(&client.ClientWriteAuthorizationModelResponse{AuthorizationModelId: "model-1"}, nil)
50+
51+
mockFgaClient.EXPECT().WriteAssertions(context.Background()).Return(mockWriteAssertions)
52+
mockWriteAssertions.EXPECT().Body(expectedAssertions).Return(mockWriteAssertions)
53+
mockWriteAssertions.EXPECT().Options(expectedOptions).Return(mockWriteAssertions)
54+
mockWriteAssertions.EXPECT().Execute().Return(nil, nil)
55+
56+
testStore := &storetest.StoreData{
57+
Name: "test-store",
58+
Model: `type user
59+
type document
60+
relations
61+
define reader: [user]`,
62+
Tests: []storetest.ModelTest{
63+
{
64+
Name: "Test",
65+
Check: []storetest.ModelTestCheck{
66+
{
67+
User: "user:anne",
68+
Object: "document:doc1",
69+
Assertions: map[string]bool{
70+
"reader": true,
71+
},
72+
},
73+
},
74+
},
75+
},
76+
}
77+
_, err := importStore(&clientConfig, mockFgaClient, testStore, "", "", 1, 1, "")
78+
79+
if err != nil {
80+
t.Errorf("expected no error, got %v", err)
81+
}
82+
})
83+
}

0 commit comments

Comments
 (0)