github.com/openfga/openfga@v1.5.4-rc1/pkg/server/test/write_assertions.go (about) 1 package test 2 3 import ( 4 "context" 5 "fmt" 6 "testing" 7 8 "github.com/google/go-cmp/cmp" 9 openfgav1 "github.com/openfga/api/proto/openfga/v1" 10 parser "github.com/openfga/language/pkg/go/transformer" 11 "github.com/stretchr/testify/require" 12 "google.golang.org/protobuf/testing/protocmp" 13 14 "github.com/openfga/openfga/pkg/server/commands" 15 serverErrors "github.com/openfga/openfga/pkg/server/errors" 16 "github.com/openfga/openfga/pkg/storage" 17 "github.com/openfga/openfga/pkg/testutils" 18 "github.com/openfga/openfga/pkg/tuple" 19 "github.com/openfga/openfga/pkg/typesystem" 20 ) 21 22 func TestWriteAndReadAssertions(t *testing.T, datastore storage.OpenFGADatastore) { 23 type writeAssertionsTestSettings struct { 24 _name string 25 assertions []*openfgav1.Assertion 26 } 27 28 store := testutils.CreateRandomString(10) 29 30 githubModelReq := &openfgav1.WriteAuthorizationModelRequest{ 31 StoreId: store, 32 TypeDefinitions: parser.MustTransformDSLToProto(`model 33 schema 1.1 34 type user 35 36 type repo 37 relations 38 define reader: [user] 39 define can_read: reader`).GetTypeDefinitions(), 40 SchemaVersion: typesystem.SchemaVersion1_1, 41 } 42 43 var tests = []writeAssertionsTestSettings{ 44 { 45 _name: "writing_assertions_succeeds", 46 assertions: []*openfgav1.Assertion{{ 47 TupleKey: tuple.NewAssertionTupleKey("repo:test", "reader", "user:elbuo"), 48 Expectation: false, 49 }}, 50 }, 51 { 52 _name: "writing_assertions_succeeds_when_it_is_not_directly_assignable", 53 assertions: []*openfgav1.Assertion{{ 54 TupleKey: tuple.NewAssertionTupleKey("repo:test", "can_read", "user:elbuo"), 55 Expectation: false, 56 }}, 57 }, 58 { 59 _name: "writing_multiple_assertions_succeeds", 60 assertions: []*openfgav1.Assertion{ 61 { 62 TupleKey: tuple.NewAssertionTupleKey("repo:test", "reader", "user:elbuo"), 63 Expectation: false, 64 }, 65 { 66 TupleKey: tuple.NewAssertionTupleKey("repo:test", "reader", "user:maria"), 67 Expectation: true, 68 }, 69 { 70 TupleKey: tuple.NewAssertionTupleKey("repo:test", "reader", "user:jon"), 71 Expectation: false, 72 }, 73 { 74 TupleKey: tuple.NewAssertionTupleKey("repo:test", "reader", "user:jose"), 75 Expectation: true, 76 }, 77 }, 78 }, 79 { 80 _name: "writing_multiple_assertions_succeeds_when_it_is_not_directly_assignable", 81 assertions: []*openfgav1.Assertion{ 82 { 83 TupleKey: tuple.NewAssertionTupleKey("repo:test", "can_read", "user:elbuo"), 84 Expectation: false, 85 }, 86 { 87 TupleKey: tuple.NewAssertionTupleKey("repo:test", "can_read", "user:maria"), 88 Expectation: false, 89 }, 90 { 91 TupleKey: tuple.NewAssertionTupleKey("repo:test", "can_read", "user:jon"), 92 Expectation: true, 93 }, 94 }, 95 }, 96 { 97 _name: "writing_empty_assertions_succeeds", 98 assertions: []*openfgav1.Assertion{}, 99 }, 100 } 101 102 ctx := context.Background() 103 104 for _, test := range tests { 105 t.Run(test._name, func(t *testing.T) { 106 model := githubModelReq 107 108 writeAuthzModelCmd := commands.NewWriteAuthorizationModelCommand(datastore) 109 110 modelID, err := writeAuthzModelCmd.Execute(ctx, model) 111 require.NoError(t, err) 112 request := &openfgav1.WriteAssertionsRequest{ 113 StoreId: store, 114 Assertions: test.assertions, 115 AuthorizationModelId: modelID.GetAuthorizationModelId(), 116 } 117 118 writeAssertionCmd := commands.NewWriteAssertionsCommand(datastore) 119 _, err = writeAssertionCmd.Execute(ctx, request) 120 require.NoError(t, err) 121 query := commands.NewReadAssertionsQuery(datastore) 122 actualResponse, actualError := query.Execute(ctx, store, modelID.GetAuthorizationModelId()) 123 require.NoError(t, actualError) 124 125 expectedResponse := &openfgav1.ReadAssertionsResponse{ 126 AuthorizationModelId: modelID.GetAuthorizationModelId(), 127 Assertions: test.assertions, 128 } 129 if diff := cmp.Diff(expectedResponse, actualResponse, protocmp.Transform()); diff != "" { 130 t.Errorf("store mismatch (-want +got):\n%s", diff) 131 } 132 }) 133 } 134 } 135 136 func TestWriteAssertionsFailure(t *testing.T, datastore storage.OpenFGADatastore) { 137 type writeAssertionsTestSettings struct { 138 _name string 139 assertions []*openfgav1.Assertion 140 modelID string 141 err error 142 } 143 144 store := testutils.CreateRandomString(10) 145 146 githubModelReq := &openfgav1.WriteAuthorizationModelRequest{ 147 StoreId: store, 148 TypeDefinitions: parser.MustTransformDSLToProto(`model 149 schema 1.1 150 type user 151 152 type repo 153 relations 154 define reader: [user] 155 define can_read: reader`).GetTypeDefinitions(), 156 SchemaVersion: typesystem.SchemaVersion1_1, 157 } 158 ctx := context.Background() 159 160 writeAuthzModelCmd := commands.NewWriteAuthorizationModelCommand(datastore) 161 modelID, err := writeAuthzModelCmd.Execute(ctx, githubModelReq) 162 require.NoError(t, err) 163 164 var tests = []writeAssertionsTestSettings{ 165 { 166 _name: "writing_assertion_with_invalid_relation_fails", 167 assertions: []*openfgav1.Assertion{ 168 { 169 TupleKey: tuple.NewAssertionTupleKey( 170 "repo:test", 171 "invalidrelation", 172 "user:elbuo", 173 ), 174 Expectation: false, 175 }, 176 }, 177 modelID: modelID.GetAuthorizationModelId(), 178 err: serverErrors.ValidationError( 179 fmt.Errorf("relation 'repo#invalidrelation' not found"), 180 ), 181 }, 182 { 183 _name: "writing_assertion_with_not_found_id", 184 assertions: []*openfgav1.Assertion{ 185 { 186 TupleKey: tuple.NewAssertionTupleKey("repo:test", "can_read", "user:elbuo"), 187 Expectation: false, 188 }, 189 }, 190 modelID: "not_valid_id", 191 err: serverErrors.AuthorizationModelNotFound( 192 "not_valid_id", 193 ), 194 }, 195 } 196 197 for _, test := range tests { 198 t.Run(test._name, func(t *testing.T) { 199 request := &openfgav1.WriteAssertionsRequest{ 200 StoreId: store, 201 Assertions: test.assertions, 202 AuthorizationModelId: test.modelID, 203 } 204 205 writeAssertionCmd := commands.NewWriteAssertionsCommand(datastore) 206 _, err = writeAssertionCmd.Execute(ctx, request) 207 require.ErrorIs(t, test.err, err) 208 }) 209 } 210 }