@@ -3,7 +3,9 @@ package relationships
33import (
44 "context"
55
6+ log "github.com/authzed/spicedb/internal/logging"
67 "github.com/authzed/spicedb/internal/namespace"
8+ "github.com/authzed/spicedb/internal/services/shared"
79 "github.com/authzed/spicedb/pkg/caveats"
810 caveattypes "github.com/authzed/spicedb/pkg/caveats/types"
911 "github.com/authzed/spicedb/pkg/datastore"
@@ -42,6 +44,7 @@ func ValidateRelationshipUpdates(
4244 }
4345
4446 if err := ValidateOneRelationship (
47+ ctx ,
4548 referencedNamespaceMap ,
4649 referencedCaveatMap ,
4750 caveatTypeSet ,
@@ -74,6 +77,7 @@ func ValidateRelationshipsForCreateOrTouch(
7477 // Validate each relationship's types.
7578 for _ , rel := range rels {
7679 if err := ValidateOneRelationship (
80+ ctx ,
7781 referencedNamespaceMap ,
7882 referencedCaveatMap ,
7983 caveatTypeSet ,
@@ -146,6 +150,7 @@ const (
146150
147151// ValidateOneRelationship validates a single relationship for CREATE/TOUCH or DELETE.
148152func ValidateOneRelationship (
153+ ctx context.Context ,
149154 namespaceMap map [string ]* schema.Definition ,
150155 caveatMap map [string ]* core.CaveatDefinition ,
151156 caveatTypeSet * caveattypes.TypeSet ,
@@ -188,6 +193,11 @@ func ValidateOneRelationship(
188193 return NewCannotWriteToPermissionError (rel )
189194 }
190195
196+ // Validate if the resource, relation or subject is deprecated
197+ if err := checkForDeprecatedRelationsAndObjects (ctx , rel , namespaceMap ); err != nil {
198+ return err
199+ }
200+
191201 // Validate the subject against the allowed relation(s).
192202 var caveat * core.AllowedCaveat
193203 if rel .OptionalCaveat != nil {
@@ -277,3 +287,95 @@ func hasNonEmptyCaveatContext(relationship tuple.Relationship) bool {
277287 relationship .OptionalCaveat .Context != nil &&
278288 len (relationship .OptionalCaveat .Context .GetFields ()) > 0
279289}
290+
291+ func checkForDeprecatedRelationsAndObjects (ctx context.Context , rel tuple.Relationship , nsMap map [string ]* schema.Definition ) error {
292+ // Validate if the resource relation is deprecated
293+ resource := nsMap [rel .Resource .ObjectType ]
294+ resourceTS := resource .TypeSystem ()
295+ relDep , ok , err := resourceTS .GetDeprecationForRelation (ctx , rel .Resource .ObjectType , rel .Resource .Relation )
296+ if err != nil {
297+ return err
298+ }
299+ if ok {
300+ switch relDep .DeprecationType {
301+ case core .DeprecationType_DEPRECATED_TYPE_WARNING :
302+ log .Warn ().
303+ Str ("namespace" , rel .Resource .ObjectType ).
304+ Str ("relation" , rel .Resource .Relation ).
305+ Str ("comments" , relDep .Comments ).
306+ Msg ("write to deprecated relation" )
307+ case core .DeprecationType_DEPRECATED_TYPE_ERROR :
308+ return shared .NewDeprecationError (rel .Resource .ObjectType , rel .Resource .Relation , relDep .Comments )
309+ }
310+ }
311+
312+ // Validate if the resource namespace is deprecated
313+ resDep , ok , err := resourceTS .GetDeprecationForNamespace (ctx , rel .Resource .ObjectType )
314+ if err != nil {
315+ return err
316+ }
317+ if ok {
318+ switch resDep .DeprecationType {
319+ case core .DeprecationType_DEPRECATED_TYPE_WARNING :
320+ log .Warn ().
321+ Str ("namespace" , rel .Resource .ObjectType ).
322+ Str ("comments" , resDep .Comments ).
323+ Msg ("write to deprecated object" )
324+ case core .DeprecationType_DEPRECATED_TYPE_ERROR :
325+ return shared .NewDeprecationError (rel .Resource .ObjectType , "" , resDep .Comments )
326+ }
327+ }
328+
329+ // Validate if the subject namespace is deprecated
330+ subject := nsMap [rel .Subject .ObjectType ]
331+ subjectTS := subject .TypeSystem ()
332+ subDep , ok , err := subjectTS .GetDeprecationForNamespace (ctx , rel .Subject .ObjectType )
333+ if err != nil {
334+ return err
335+ }
336+ if ok {
337+ switch subDep .DeprecationType {
338+ case core .DeprecationType_DEPRECATED_TYPE_WARNING :
339+ log .Warn ().
340+ Str ("namespace" , rel .Subject .ObjectType ).
341+ Str ("comments" , subDep .Comments ).
342+ Msg ("write to deprecated object" )
343+ case core .DeprecationType_DEPRECATED_TYPE_ERROR :
344+ return shared .NewDeprecationError (rel .Subject .ObjectType , "" , subDep .Comments )
345+ }
346+ }
347+
348+ // check deprecation for allowed relation types
349+ dep , ok , err := resourceTS .GetDeprecationForAllowedRelation (
350+ ctx ,
351+ rel .Resource .ObjectType ,
352+ rel .Resource .Relation ,
353+ rel .Subject .ObjectType ,
354+ rel .Subject .Relation ,
355+ rel .Subject .ObjectID == tuple .PublicWildcard ,
356+ )
357+ if err != nil {
358+ return err
359+ }
360+
361+ errMsg := ""
362+ if rel .Subject .ObjectID == tuple .PublicWildcard {
363+ errMsg = tuple .PublicWildcard
364+ }
365+
366+ if ok {
367+ switch dep .DeprecationType {
368+ case core .DeprecationType_DEPRECATED_TYPE_WARNING :
369+ log .Warn ().
370+ Str ("namespace" , rel .Resource .ObjectType ).
371+ Str ("comments" , dep .Comments ).
372+ Msg ("write to deprecated relation" )
373+ case core .DeprecationType_DEPRECATED_TYPE_ERROR :
374+ return shared .NewDeprecationError (
375+ rel .Subject .ObjectType ,
376+ errMsg ,
377+ dep .Comments )
378+ }
379+ }
380+ return nil
381+ }
0 commit comments