@@ -123,11 +123,7 @@ func (engine *CheckEngine) check(
123123 var fn CheckFunction
124124
125125 // Determine the type of the reference by name in the given entity definition.
126- tor , err := schema .GetTypeOfReferenceByNameInEntityDefinition (en , request .GetPermission ())
127- if err != nil {
128- // If an error is encountered while determining the type, a CheckFunction is returned that always fails with this error.
129- return checkFail (err )
130- }
126+ tor , _ := schema .GetTypeOfReferenceByNameInEntityDefinition (en , request .GetPermission ())
131127
132128 // Based on the type of the reference, define the CheckFunction in different ways.
133129 switch tor {
@@ -155,11 +151,7 @@ func (engine *CheckEngine) check(
155151 // If the reference is a relation, check the direct relation.
156152 fn = engine .checkDirectRelation (request )
157153 default :
158- // If the reference is not a permission, attribute or relation, check the call.
159- fn = engine .checkCall (request , & base.Call {
160- RuleName : request .GetPermission (),
161- Arguments : request .GetArguments (),
162- })
154+ fn = engine .checkDirectCall (request )
163155 }
164156
165157 // If the CheckFunction is still undefined after the switch, return a CheckFunction that always fails with an error indicating an undefined child kind.
@@ -412,7 +404,7 @@ func (engine *CheckEngine) checkTupleToUserSet(
412404// ComputedUserSet data structure. It returns a CheckFunction closure that performs the check.
413405func (engine * CheckEngine ) checkComputedUserSet (
414406 request * base.PermissionCheckRequest , // The request containing details about the permission to be checked
415- cu * base.ComputedUserSet , // The computed user set containing user set information
407+ cu * base.ComputedUserSet , // The computed user set containing user set information
416408) CheckFunction {
417409 // The returned CheckFunction invokes a permission check with a new request that is almost the same
418410 // as the incoming request, but changes the Permission to be the relation defined in the computed user set.
@@ -496,7 +488,7 @@ func (engine *CheckEngine) checkDirectAttribute(
496488 }
497489
498490 // Unmarshal the attribute value into a BoolValue message.
499- var msg base.BoolValue
491+ var msg base.BooleanValue
500492 if err := val .GetValue ().UnmarshalTo (& msg ); err != nil {
501493 // If there was an error unmarshaling, return a denied response and the error.
502494 return denied (& base.PermissionCheckResponseMetadata {}), err
@@ -512,13 +504,30 @@ func (engine *CheckEngine) checkDirectAttribute(
512504 }
513505}
514506
515- // checkCall is a function that validates a call using the CheckEngine.
516- // It returns a function (CheckFunction) that when called, performs the permission check.
507+ // checkCall creates and returns a CheckFunction based on the provided request and call details.
508+ // It essentially constructs a new PermissionCheckRequest based on the call details and then invokes
509+ // the permission check using the engine's invoke method.
517510func (engine * CheckEngine ) checkCall (
518- request * base.PermissionCheckRequest , // The request containing the details for the permission check
519- call * base.Call , // The specific call to be checked
511+ request * base.PermissionCheckRequest ,
512+ call * base.Call ,
513+ ) CheckFunction {
514+ // Construct a new permission check request based on the input request and call details.
515+ return engine .invoke (& base.PermissionCheckRequest {
516+ TenantId : request .GetTenantId (),
517+ Entity : request .GetEntity (),
518+ Permission : call .GetRuleName (),
519+ Subject : request .GetSubject (),
520+ Metadata : request .GetMetadata (),
521+ Context : request .GetContext (),
522+ Arguments : call .GetArguments (),
523+ })
524+ }
525+
526+ // checkDirectCall creates and returns a CheckFunction that performs direct permission checking.
527+ // The function evaluates permissions based on rule definitions, arguments, and attributes.
528+ func (engine * CheckEngine ) checkDirectCall (
529+ request * base.PermissionCheckRequest ,
520530) CheckFunction {
521- // The function returned by checkCall
522531 return func (ctx context.Context ) (* base.PermissionCheckResponse , error ) {
523532 var err error
524533
@@ -529,52 +538,44 @@ func (engine *CheckEngine) checkCall(
529538
530539 // Read the rule definition from the schema. If an error occurs, return the default denied response.
531540 var ru * base.RuleDefinition
532- ru , _ , err = engine .schemaReader .ReadRuleDefinition (ctx , request .GetTenantId (), call . GetRuleName (), request .GetMetadata ().GetSchemaVersion ())
541+ ru , _ , err = engine .schemaReader .ReadRuleDefinition (ctx , request .GetTenantId (), request . GetPermission (), request .GetMetadata ().GetSchemaVersion ())
533542 if err != nil {
534543 return emptyResp , err
535544 }
536545
537- // Prepare the arguments map to be used in the CEL evaluation
546+ // Initialize an arguments map to hold argument values.
538547 arguments := make (map [string ]interface {})
539548
540- // Prepare a slice for attributes
549+ // List to store computed attributes.
541550 attributes := make ([]string , 0 )
542551
543- // Populate the arguments map based on the type of argument in the call
544- for _ , arg := range call .GetArguments () {
552+ // Iterate over request arguments to classify and process them.
553+ for _ , arg := range request .GetArguments () {
545554 switch actualArg := arg .Type .(type ) {
546555 case * base.Argument_ComputedAttribute :
547- // Get the name of the computed attribute
556+ // Handle computed attributes: Set them to a default empty value.
548557 attrName := actualArg .ComputedAttribute .GetName ()
549-
550- // Get the empty value for this attribute type
551558 emptyValue := getEmptyValueForType (ru .GetArguments ()[attrName ])
552-
553- // Add the attribute with its empty value to the arguments map
554559 arguments [attrName ] = emptyValue
555-
556- // Append the attribute to the attributes slice
557560 attributes = append (attributes , attrName )
561+
558562 case * base.Argument_ContextAttribute :
559- // Get the name of the context attribute
563+ // Handle context attributes: Use the value from context or default to an empty value.
560564 attrName := actualArg .ContextAttribute .GetName ()
561-
562- // Get the value of the context attribute if exists, else get an empty value
563565 value , exists := request .GetContext ().GetData ().AsMap ()[attrName ]
564566 if ! exists {
565567 value = getEmptyValueForType (ru .GetArguments ()[attrName ])
566568 }
567-
568- // Add the attribute with its value to the arguments map
569569 arguments [attrName ] = value
570+
570571 default :
571- // Return an error for unhandled types
572+ // Return an error for any unsupported argument types.
572573 return denied (& base.PermissionCheckResponseMetadata {}), fmt .Errorf (base .ErrorCode_ERROR_CODE_INTERNAL .String ())
573574 }
574575 }
575576
577+ // If there are computed attributes, fetch them from the data source.
576578 if len (attributes ) > 0 {
577- // Prepare the filter for querying attributes from the database
578579 filter := & base.AttributeFilter {
579580 Entity : & base.EntityFilter {
580581 Type : request .GetEntity ().GetType (),
@@ -583,7 +584,6 @@ func (engine *CheckEngine) checkCall(
583584 Attributes : attributes ,
584585 }
585586
586- // Query the database for the attributes and add them to the arguments map
587587 ait , err := engine .dataReader .QueryAttributes (ctx , request .GetTenantId (), filter , request .GetMetadata ().GetSnapToken ())
588588 if err != nil {
589589 return denied (& base.PermissionCheckResponseMetadata {}), err
@@ -594,38 +594,37 @@ func (engine *CheckEngine) checkCall(
594594 return denied (& base.PermissionCheckResponseMetadata {}), err
595595 }
596596
597+ // Combine attributes from different sources ensuring uniqueness.
597598 it := database .NewUniqueAttributeIterator (ait , cta )
598-
599599 for it .HasNext () {
600600 next , ok := it .GetNext ()
601601 if ! ok {
602602 break
603603 }
604-
605604 arguments [next .GetAttribute ()] = utils .ConvertProtoAnyToInterface (next .GetValue ())
606605 }
607606 }
608607
609- // Prepare the CEL environment using the arguments in the rule definition
608+ // Prepare the CEL environment with the argument values.
610609 env , err := utils .ArgumentsAsCelEnv (ru .Arguments )
611610 if err != nil {
612611 return nil , err
613612 }
614613
615- // Prepare the CEL program using the rule's expression
614+ // Compile the rule expression into an executable form.
616615 exp := cel .CheckedExprToAst (ru .Expression )
617616 prg , err := env .Program (exp )
618617 if err != nil {
619618 return nil , err
620619 }
621620
622- // Evaluate the CEL program with the arguments. If an error occurs, return a "denied" response .
621+ // Evaluate the rule expression with the provided arguments .
623622 out , _ , err := prg .Eval (arguments )
624623 if err != nil {
625624 return denied (& base.PermissionCheckResponseMetadata {}), fmt .Errorf ("failed to evaluate expression: %w" , err )
626625 }
627626
628- // Check if the result of the CEL evaluation is a boolean
627+ // Ensure the result of evaluation is boolean and decide on permission.
629628 result , ok := out .Value ().(bool )
630629 if ! ok {
631630 return denied (& base.PermissionCheckResponseMetadata {}), fmt .Errorf ("expected boolean result, but got %T" , out .Value ())
0 commit comments