github.com/authzed/spicedb@v1.32.1-0.20240520085336-ebda56537386/pkg/development/assertions.go (about) 1 package development 2 3 import ( 4 "fmt" 5 6 v1t "github.com/authzed/authzed-go/proto/authzed/api/v1" 7 8 devinterface "github.com/authzed/spicedb/pkg/proto/developer/v1" 9 v1 "github.com/authzed/spicedb/pkg/proto/dispatch/v1" 10 "github.com/authzed/spicedb/pkg/tuple" 11 "github.com/authzed/spicedb/pkg/validationfile/blocks" 12 ) 13 14 const maxDispatchDepth = 25 15 16 // RunAllAssertions runs all assertions found in the given assertions block against the 17 // developer context, returning whether any errors occurred. 18 func RunAllAssertions(devContext *DevContext, assertions *blocks.Assertions) ([]*devinterface.DeveloperError, error) { 19 trueFailures, err := runAssertions(devContext, assertions.AssertTrue, v1.ResourceCheckResult_MEMBER, "Expected relation or permission %s to exist") 20 if err != nil { 21 return nil, err 22 } 23 24 caveatedFailures, err := runAssertions(devContext, assertions.AssertCaveated, v1.ResourceCheckResult_CAVEATED_MEMBER, "Expected relation or permission %s to be caveated") 25 if err != nil { 26 return nil, err 27 } 28 29 falseFailures, err := runAssertions(devContext, assertions.AssertFalse, v1.ResourceCheckResult_NOT_MEMBER, "Expected relation or permission %s to not exist") 30 if err != nil { 31 return nil, err 32 } 33 34 failures := append(trueFailures, caveatedFailures...) 35 failures = append(failures, falseFailures...) 36 return failures, nil 37 } 38 39 func runAssertions(devContext *DevContext, assertions []blocks.Assertion, expected v1.ResourceCheckResult_Membership, fmtString string) ([]*devinterface.DeveloperError, error) { 40 var failures []*devinterface.DeveloperError 41 42 for _, assertion := range assertions { 43 tpl := tuple.MustFromRelationship[*v1t.ObjectReference, *v1t.SubjectReference, *v1t.ContextualizedCaveat](assertion.Relationship) 44 45 if tpl.Caveat != nil { 46 failures = append(failures, &devinterface.DeveloperError{ 47 Message: fmt.Sprintf("cannot specify a caveat on an assertion: `%s`", assertion.RelationshipWithContextString), 48 Source: devinterface.DeveloperError_ASSERTION, 49 Kind: devinterface.DeveloperError_UNKNOWN_RELATION, 50 Context: assertion.RelationshipWithContextString, 51 Line: uint32(assertion.SourcePosition.LineNumber), 52 Column: uint32(assertion.SourcePosition.ColumnPosition), 53 }) 54 continue 55 } 56 57 cr, err := RunCheck(devContext, tpl.ResourceAndRelation, tpl.Subject, assertion.CaveatContext) 58 if err != nil { 59 devErr, wireErr := DistinguishGraphError( 60 devContext, 61 err, 62 devinterface.DeveloperError_ASSERTION, 63 uint32(assertion.SourcePosition.LineNumber), 64 uint32(assertion.SourcePosition.ColumnPosition), 65 assertion.RelationshipWithContextString, 66 ) 67 if wireErr != nil { 68 return nil, wireErr 69 } 70 if devErr != nil { 71 failures = append(failures, devErr) 72 } 73 } else if cr.Permissionship != expected { 74 failures = append(failures, &devinterface.DeveloperError{ 75 Message: fmt.Sprintf(fmtString, assertion.RelationshipWithContextString), 76 Source: devinterface.DeveloperError_ASSERTION, 77 Kind: devinterface.DeveloperError_ASSERTION_FAILED, 78 Context: assertion.RelationshipWithContextString, 79 Line: uint32(assertion.SourcePosition.LineNumber), 80 Column: uint32(assertion.SourcePosition.ColumnPosition), 81 CheckDebugInformation: cr.DispatchDebugInfo, 82 CheckResolvedDebugInformation: cr.V1DebugInfo, 83 }) 84 } 85 } 86 87 return failures, nil 88 }