checkIntersection checks if the subject has permission by running multiple CheckFunctions concurrently, the permission check is successful only when all CheckFunctions succeed (intersection).
(ctx context.Context, functions []CheckFunction, limit int)
| 687 | // checkIntersection checks if the subject has permission by running multiple CheckFunctions concurrently, |
| 688 | // the permission check is successful only when all CheckFunctions succeed (intersection). |
| 689 | func checkIntersection(ctx context.Context, functions []CheckFunction, limit int) (*base.PermissionCheckResponse, error) { |
| 690 | // Initialize the response metadata |
| 691 | responseMetadata := emptyResponseMetadata() |
| 692 | |
| 693 | // If there are no functions, deny the permission and return |
| 694 | if len(functions) == 0 { |
| 695 | return denied(responseMetadata), nil |
| 696 | } |
| 697 | |
| 698 | // Create a channel to receive the results of the CheckFunctions |
| 699 | decisionChan := make(chan CheckResponse, len(functions)) |
| 700 | // Create a context that can be cancelled |
| 701 | cancelCtx, cancel := context.WithCancel(ctx) |
| 702 | |
| 703 | // Run the CheckFunctions concurrently |
| 704 | clean := checkRun(cancelCtx, functions, decisionChan, limit) |
| 705 | |
| 706 | // When the function returns, ensure to cancel the context and clean up the resources |
| 707 | defer func() { |
| 708 | cancel() |
| 709 | clean() |
| 710 | close(decisionChan) |
| 711 | }() |
| 712 | |
| 713 | // Iterate over the results of the CheckFunctions |
| 714 | for range len(functions) { |
| 715 | select { |
| 716 | // If a result is received |
| 717 | case d := <-decisionChan: |
| 718 | // Merge the response metadata with the received metadata |
| 719 | responseMetadata = joinResponseMetas(responseMetadata, d.resp.Metadata) |
| 720 | // If there was an error, deny the permission and return the error |
| 721 | if d.err != nil { |
| 722 | return denied(responseMetadata), d.err |
| 723 | } |
| 724 | // If the CheckFunction denied the permission, deny the permission and return |
| 725 | if d.resp.GetCan() == base.CheckResult_CHECK_RESULT_DENIED { |
| 726 | return denied(responseMetadata), nil |
| 727 | } |
| 728 | // If the context is done, deny the permission and return a cancellation error |
| 729 | case <-ctx.Done(): |
| 730 | return denied(responseMetadata), errors.New(base.ErrorCode_ERROR_CODE_CANCELLED.String()) |
| 731 | } |
| 732 | } |
| 733 | |
| 734 | // If all CheckFunctions allowed the permission, allow the permission and return |
| 735 | return allowed(responseMetadata), nil |
| 736 | } |
| 737 | |
| 738 | // checkExclusion is a function that checks if there are any exclusions for given CheckFunctions |
| 739 | func checkExclusion(ctx context.Context, functions []CheckFunction, limit int) (*base.PermissionCheckResponse, error) { |
nothing calls this directly
no test coverage detected