github.com/authzed/spicedb@v1.32.1-0.20240520085336-ebda56537386/internal/datastore/common/errors.go (about) 1 package common 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "regexp" 8 "strings" 9 10 "google.golang.org/grpc/codes" 11 "google.golang.org/grpc/status" 12 13 v1 "github.com/authzed/authzed-go/proto/authzed/api/v1" 14 15 log "github.com/authzed/spicedb/internal/logging" 16 core "github.com/authzed/spicedb/pkg/proto/core/v1" 17 "github.com/authzed/spicedb/pkg/spiceerrors" 18 "github.com/authzed/spicedb/pkg/tuple" 19 ) 20 21 // SerializationError is returned when there's been a serialization 22 // error while performing a datastore operation 23 type SerializationError struct { 24 error 25 } 26 27 func (err SerializationError) GRPCStatus() *status.Status { 28 return spiceerrors.WithCodeAndDetails( 29 err, 30 codes.Aborted, 31 spiceerrors.ForReason( 32 v1.ErrorReason_ERROR_REASON_SERIALIZATION_FAILURE, 33 map[string]string{}, 34 ), 35 ) 36 } 37 38 func (err SerializationError) Unwrap() error { 39 return err.error 40 } 41 42 // NewSerializationError creates a new SerializationError 43 func NewSerializationError(err error) error { 44 return SerializationError{err} 45 } 46 47 // CreateRelationshipExistsError is an error returned when attempting to CREATE an already-existing 48 // relationship. 49 type CreateRelationshipExistsError struct { 50 error 51 52 // Relationship is the relationship that caused the error. May be nil, depending on the datastore. 53 Relationship *core.RelationTuple 54 } 55 56 // GRPCStatus implements retrieving the gRPC status for the error. 57 func (err CreateRelationshipExistsError) GRPCStatus() *status.Status { 58 if err.Relationship == nil { 59 return spiceerrors.WithCodeAndDetails( 60 err, 61 codes.AlreadyExists, 62 spiceerrors.ForReason( 63 v1.ErrorReason_ERROR_REASON_ATTEMPT_TO_RECREATE_RELATIONSHIP, 64 map[string]string{}, 65 ), 66 ) 67 } 68 69 relationship := tuple.ToRelationship(err.Relationship) 70 return spiceerrors.WithCodeAndDetails( 71 err, 72 codes.AlreadyExists, 73 spiceerrors.ForReason( 74 v1.ErrorReason_ERROR_REASON_ATTEMPT_TO_RECREATE_RELATIONSHIP, 75 map[string]string{ 76 "relationship": tuple.StringRelationshipWithoutCaveat(relationship), 77 "resource_type": relationship.Resource.ObjectType, 78 "resource_object_id": relationship.Resource.ObjectId, 79 "resource_relation": relationship.Relation, 80 "subject_type": relationship.Subject.Object.ObjectType, 81 "subject_object_id": relationship.Subject.Object.ObjectId, 82 "subject_relation": relationship.Subject.OptionalRelation, 83 }, 84 ), 85 ) 86 } 87 88 // NewCreateRelationshipExistsError creates a new CreateRelationshipExistsError. 89 func NewCreateRelationshipExistsError(relationship *core.RelationTuple) error { 90 msg := "could not CREATE one or more relationships, as they already existed. If this is persistent, please switch to TOUCH operations or specify a precondition" 91 if relationship != nil { 92 msg = fmt.Sprintf("could not CREATE relationship `%s`, as it already existed. If this is persistent, please switch to TOUCH operations or specify a precondition", tuple.StringWithoutCaveat(relationship)) 93 } 94 95 return CreateRelationshipExistsError{ 96 fmt.Errorf(msg), 97 relationship, 98 } 99 } 100 101 var ( 102 portMatchRegex = regexp.MustCompile("invalid port \\\"(.+)\\\" after host") 103 parseMatchRegex = regexp.MustCompile("parse \\\"(.+)\\\":") 104 ) 105 106 // RedactAndLogSensitiveConnString elides the given error, logging it only at trace 107 // level (after being redacted). 108 func RedactAndLogSensitiveConnString(ctx context.Context, baseErr string, err error, pgURL string) error { 109 if err == nil { 110 return errors.New(baseErr) 111 } 112 113 // See: https://github.com/jackc/pgx/issues/1271 114 filtered := err.Error() 115 filtered = strings.ReplaceAll(filtered, pgURL, "(redacted)") 116 filtered = portMatchRegex.ReplaceAllString(filtered, "(redacted)") 117 filtered = parseMatchRegex.ReplaceAllString(filtered, "(redacted)") 118 log.Ctx(ctx).Trace().Msg(baseErr + ": " + filtered) 119 return fmt.Errorf("%s. To view details of this error (that may contain sensitive information), please run with --log-level=trace", baseErr) 120 }