github.com/openfga/openfga@v1.5.4-rc1/tests/writemodel/writemodel.go (about) 1 // Package writemodel contains integration tests for the WriteAuthorizationModel API. 2 package writemodel 3 4 import ( 5 "context" 6 "testing" 7 8 openfgav1 "github.com/openfga/api/proto/openfga/v1" 9 parser "github.com/openfga/language/pkg/go/transformer" 10 "github.com/stretchr/testify/require" 11 "google.golang.org/grpc" 12 "google.golang.org/grpc/status" 13 14 "github.com/openfga/openfga/pkg/typesystem" 15 ) 16 17 var testCases = map[string]struct { 18 model string 19 code int 20 }{ 21 // implemented in Fails_If_Using_Self_As_Type_Name 22 // "case1": { 23 // model: ` 24 // type user 25 // type self 26 // relations 27 // define member: [user] 28 // `, 29 // code: 2056, 30 // }, 31 // implemented in Fails_If_Using_This_As_Type_Name 32 // "case2": { 33 // model: ` 34 // type user 35 // type this 36 // relations 37 // define member: [user] 38 // `, 39 // code: 2056, 40 // }, 41 // implemented in Fails_If_Using_Self_As_Relation_Name 42 // "case3": { 43 // model: ` 44 // type user 45 // type group 46 // relations 47 // define self: [user] 48 // `, 49 // code: 2056, 50 // }, 51 // implemented in Fails_If_Using_This_As_Relation_Name 52 // "case4": { 53 // model: ` 54 // type user 55 // type group 56 // relations 57 // define this: [user] 58 // `, 59 // code: 2056, 60 // }, 61 "case6": { 62 model: `model 63 schema 1.1 64 type user 65 type group 66 relations 67 define group: group from group`, 68 code: 2056, 69 }, 70 "case7": { 71 model: `model 72 schema 1.1 73 type user 74 type group 75 relations 76 define parent: [group] 77 define viewer: viewer from parent`, 78 code: 2056, 79 }, 80 "case8": { 81 model: `model 82 schema 1.1 83 type group 84 relations 85 define viewer: [group#viewer]`, 86 code: 2056, 87 }, 88 "case9": { 89 model: `model 90 schema 1.1 91 type user 92 type org 93 relations 94 define member: [user] 95 type group 96 relations 97 define parent: [org] 98 define viewer: viewer from parent`, 99 code: 2056, 100 }, 101 "case10": { 102 model: `model 103 schema 1.1 104 type user 105 type group 106 relations 107 define parent: [group] 108 define viewer: reader from parent`, 109 code: 2056, 110 }, 111 "case11": { 112 model: `model 113 schema 1.1 114 type user 115 type org 116 type group 117 relations 118 define parent: [group] 119 define viewer: viewer from org`, 120 code: 2056, 121 }, 122 "case12": { 123 model: `model 124 schema 1.1 125 type user 126 type org 127 type group 128 relations 129 define parent: [group] 130 define viewer: org from parent`, 131 code: 2056, 132 }, 133 "case13": { 134 model: `model 135 schema 1.1 136 type user 137 type org 138 type group 139 relations 140 define parent: [group, group#org]`, 141 code: 2056, 142 }, 143 "case14": { 144 model: `model 145 schema 1.1 146 type user 147 type org 148 relations 149 define viewer: [user] 150 type group 151 relations 152 define parent: [group] 153 define viewer: viewer from parent`, 154 code: 2056, 155 }, 156 "case16": { 157 model: `model 158 schema 1.1 159 type document 160 relations 161 define reader: writer 162 define writer: reader`, 163 code: 2056, 164 }, 165 "case17": { 166 model: `model 167 schema 1.1 168 type user 169 type folder 170 relations 171 define parent: [folder] or parent from parent 172 define viewer: [user] or viewer from parent`, 173 code: 2056, 174 }, 175 "case18": { 176 model: `model 177 schema 1.1 178 type user 179 type folder 180 relations 181 define root: [folder] 182 define parent: [folder] or root 183 define viewer: [user] or viewer from parent`, 184 code: 2056, 185 }, 186 "case19": { 187 model: `model 188 schema 1.1 189 type user 190 type folder 191 relations 192 define root: [folder] 193 define parent: root 194 define viewer: [user] or viewer from parent`, 195 code: 2056, 196 }, 197 "case20": { 198 model: `model 199 schema 1.1 200 type user 201 type folder 202 relations 203 define root: [folder] 204 define parent: [folder, folder#parent] 205 define viewer: [user] or viewer from parent`, 206 code: 2056, 207 }, 208 "case21": { 209 model: `model 210 schema 1.1 211 type user 212 type group 213 relations 214 define member: [user] 215 define reader: member and allowed`, 216 code: 2056, 217 }, 218 "case22": { 219 model: `model 220 schema 1.1 221 type user 222 type group 223 relations 224 define member: [user] 225 define reader: member or allowed`, 226 code: 2056, 227 }, 228 "case23": { 229 model: `model 230 schema 1.1 231 type user 232 type group 233 relations 234 define member: [user] 235 define reader: allowed but not member`, 236 code: 2056, 237 }, 238 "case24": { 239 model: `model 240 schema 1.1 241 type user 242 type group 243 relations 244 define member: [user] 245 define reader: member but not allowed`, 246 code: 2056, 247 }, 248 // "case25": { 249 // model: `model 250 // schema 1.1 251 // type user 252 // type org 253 // relations 254 // define member`, 255 // code: 2056, 256 // }, 257 "same_type_fails": { 258 model: `model 259 schema 1.1 260 type user 261 type user`, 262 code: 2056, 263 }, 264 "difference_includes_itself_in_subtract_fails": { 265 model: `model 266 schema 1.1 267 type user 268 type document 269 relations 270 define viewer: [user] but not viewer`, 271 code: 2056, 272 }, 273 "union_includes_itself_fails": { 274 model: `model 275 schema 1.1 276 type user 277 type document 278 relations 279 define viewer: [user] or viewer`, 280 code: 2056, 281 }, 282 "intersection_includes_itself_fails": { 283 model: `model 284 schema 1.1 285 type user 286 type document 287 relations 288 define viewer: [user] and viewer`, 289 code: 2056, 290 }, 291 "simple_model_succeeds": { 292 model: `model 293 schema 1.1 294 type user 295 type folder 296 relations 297 define viewer: [user] 298 type document 299 relations 300 define parent: [folder] 301 define viewer: viewer from parent`, 302 }, 303 "no_relations_succeeds": { 304 model: `model 305 schema 1.1 306 type user`, 307 }, 308 "union_may_contain_repeated_relations": { 309 model: `model 310 schema 1.1 311 type user 312 type document 313 relations 314 define editor: [user] 315 define viewer: editor or editor`, 316 }, 317 "intersection_may_contain_repeated_relations": { 318 model: `model 319 schema 1.1 320 type user 321 type document 322 relations 323 define editor: [user] 324 define viewer: editor and editor`, 325 }, 326 "exclusion_may_contain_repeated_relations": { 327 model: `model 328 schema 1.1 329 type user 330 type document 331 relations 332 define editor: [user] 333 define viewer: editor but not editor`, 334 }, 335 "as_long_as_one_computed_userset_type_is_valid": { 336 model: `model 337 schema 1.1 338 type user 339 type group 340 relations 341 define parent: [group, team] 342 define viewer: reader from parent 343 type team 344 relations 345 define reader: [user]`, 346 }, 347 } 348 349 // ClientInterface defines interface for running WriteAuthorizationModel tests. 350 type ClientInterface interface { 351 CreateStore(ctx context.Context, in *openfgav1.CreateStoreRequest, opts ...grpc.CallOption) (*openfgav1.CreateStoreResponse, error) 352 WriteAuthorizationModel(ctx context.Context, in *openfgav1.WriteAuthorizationModelRequest, opts ...grpc.CallOption) (*openfgav1.WriteAuthorizationModelResponse, error) 353 } 354 355 // RunAllTests will run all write model tests. 356 func RunAllTests(t *testing.T, client ClientInterface) { 357 t.Run("RunAllTests", func(t *testing.T) { 358 t.Run("WriteTest", func(t *testing.T) { 359 t.Parallel() 360 runTests(t, client) 361 }) 362 }) 363 } 364 365 func runTests(t *testing.T, client ClientInterface) { 366 ctx := context.Background() 367 368 for name, test := range testCases { 369 name := name 370 test := test 371 372 t.Run(name, func(t *testing.T) { 373 t.Parallel() 374 resp, err := client.CreateStore(ctx, &openfgav1.CreateStoreRequest{Name: "write_model_test"}) 375 require.NoError(t, err) 376 377 storeID := resp.GetId() 378 model := parser.MustTransformDSLToProto(test.model) 379 _, err = client.WriteAuthorizationModel(ctx, &openfgav1.WriteAuthorizationModelRequest{ 380 StoreId: storeID, 381 SchemaVersion: typesystem.SchemaVersion1_1, 382 TypeDefinitions: model.GetTypeDefinitions(), 383 Conditions: model.GetConditions(), 384 }) 385 386 if test.code == 0 { 387 require.NoError(t, err) 388 } else { 389 require.Error(t, err) 390 e, ok := status.FromError(err) 391 require.True(t, ok) 392 require.Equal(t, test.code, int(e.Code()), err) 393 } 394 }) 395 } 396 }