checkTupleToUserSet is a method of CheckEngine that checks permissions using the TupleToUserSet data structure. It returns a CheckFunction closure that does the check.
( request *base.PermissionCheckRequest, ttu *base.TupleToUserSet, )
| 329 | // checkTupleToUserSet is a method of CheckEngine that checks permissions using the |
| 330 | // TupleToUserSet data structure. It returns a CheckFunction closure that does the check. |
| 331 | func (engine *CheckEngine) checkTupleToUserSet( |
| 332 | request *base.PermissionCheckRequest, |
| 333 | ttu *base.TupleToUserSet, |
| 334 | ) CheckFunction { |
| 335 | // The returned CheckFunction is a closure over the provided context, request, and ttu. |
| 336 | return func(ctx context.Context) (*base.PermissionCheckResponse, error) { |
| 337 | // Define a TupleFilter. This specifies which tuples we're interested in. |
| 338 | // We want tuples that match the entity type and ID from the request, and have a specific relation. |
| 339 | filter := &base.TupleFilter{ |
| 340 | Entity: &base.EntityFilter{ |
| 341 | Type: request.GetEntity().GetType(), // Filter by entity type from request |
| 342 | Ids: []string{request.GetEntity().GetId()}, // Filter by entity ID from request |
| 343 | }, |
| 344 | Relation: ttu.GetTupleSet().GetRelation(), // Filter by relation from tuple set |
| 345 | } |
| 346 | |
| 347 | // Use the filter to query for relationships in the given context. |
| 348 | // NewContextualRelationships() creates a ContextualRelationships instance from tuples in the request. |
| 349 | // QueryRelationships() then uses the filter to find and return matching relationships. |
| 350 | cti, err := storageContext.NewContextualTuples(request.GetContext().GetTuples()...).QueryRelationships(filter, database.NewCursorPagination()) |
| 351 | if err != nil { |
| 352 | // If an error occurred while querying, return a "denied" response and the error. |
| 353 | return denied(emptyResponseMetadata()), err |
| 354 | } |
| 355 | |
| 356 | // Use the filter to query for relationships in the database. |
| 357 | // relationshipReader.QueryRelationships() uses the filter to find and return matching relationships. |
| 358 | rit, err := engine.dataReader.QueryRelationships(ctx, request.GetTenantId(), filter, request.GetMetadata().GetSnapToken(), database.NewCursorPagination()) |
| 359 | if err != nil { |
| 360 | // If an error occurred while querying, return a "denied" response and the error. |
| 361 | return denied(emptyResponseMetadata()), err |
| 362 | } |
| 363 | |
| 364 | // Create a new UniqueTupleIterator from the two TupleIterators. |
| 365 | // NewUniqueTupleIterator() ensures that the iterator only returns unique tuples. |
| 366 | it := database.NewUniqueTupleIterator(rit, cti) |
| 367 | |
| 368 | // Define a slice of CheckFunctions to hold the check functions for each subject. |
| 369 | checkFunctions := make([]CheckFunction, 0, 4) |
| 370 | // Iterate over all tuples returned by the iterator. |
| 371 | for it.HasNext() { |
| 372 | // Get the next tuple's subject. |
| 373 | next, ok := it.GetNext() |
| 374 | if !ok { |
| 375 | break |
| 376 | } |
| 377 | subject := next.GetSubject() |
| 378 | |
| 379 | // For each subject, generate a check function for its computed user set and append it to the list. |
| 380 | checkFunctions = append(checkFunctions, engine.checkComputedUserSet(&base.PermissionCheckRequest{ |
| 381 | TenantId: request.GetTenantId(), |
| 382 | Entity: &base.Entity{ |
| 383 | Type: subject.GetType(), |
| 384 | Id: subject.GetId(), |
| 385 | }, |
| 386 | Permission: subject.GetRelation(), |
| 387 | Subject: request.GetSubject(), |
| 388 | Metadata: request.GetMetadata(), |
no test coverage detected