summaryrefslogtreecommitdiff
path: root/vendor/github.com/authzed/spicedb/pkg/spiceerrors/withstatus.go
diff options
context:
space:
mode:
authormo khan <mo@mokhan.ca>2025-07-24 17:58:01 -0600
committermo khan <mo@mokhan.ca>2025-07-24 17:58:01 -0600
commit72296119fc9755774719f8f625ad03e0e0ec457a (patch)
treeed236ddee12a20fb55b7cfecf13f62d3a000dcb5 /vendor/github.com/authzed/spicedb/pkg/spiceerrors/withstatus.go
parenta920a8cfe415858bb2777371a77018599ffed23f (diff)
parenteaa1bd3b8e12934aed06413d75e7482ac58d805a (diff)
Merge branch 'the-spice-must-flow' into 'main'
Add SpiceDB Authorization See merge request gitlab-org/software-supply-chain-security/authorization/sparkled!19
Diffstat (limited to 'vendor/github.com/authzed/spicedb/pkg/spiceerrors/withstatus.go')
-rw-r--r--vendor/github.com/authzed/spicedb/pkg/spiceerrors/withstatus.go82
1 files changed, 82 insertions, 0 deletions
diff --git a/vendor/github.com/authzed/spicedb/pkg/spiceerrors/withstatus.go b/vendor/github.com/authzed/spicedb/pkg/spiceerrors/withstatus.go
new file mode 100644
index 0000000..1ee6e0a
--- /dev/null
+++ b/vendor/github.com/authzed/spicedb/pkg/spiceerrors/withstatus.go
@@ -0,0 +1,82 @@
+package spiceerrors
+
+import (
+ "errors"
+
+ log "github.com/authzed/spicedb/internal/logging"
+
+ "google.golang.org/genproto/googleapis/rpc/errdetails"
+ "google.golang.org/grpc/codes"
+ "google.golang.org/grpc/status"
+ "google.golang.org/protobuf/runtime/protoiface"
+
+ v1 "github.com/authzed/authzed-go/proto/authzed/api/v1"
+)
+
+// Domain is the domain used for all errors.
+const Domain = "authzed.com"
+
+// WithCodeAndDetails returns a gRPC status message containing the error's message, the given
+// status code and any supplied details.
+func WithCodeAndDetails(err error, code codes.Code, details ...protoiface.MessageV1) *status.Status {
+ created := status.New(code, err.Error())
+ created, derr := created.WithDetails(details...)
+ if derr != nil {
+ log.Err(derr).Str("provided-error", err.Error()).Msg("could not add details to provided error")
+ }
+ return created
+}
+
+// WithCodeAndDetailsAsError returns an error containing the error's message, the given
+// status code and any supplied details.
+func WithCodeAndDetailsAsError(err error, code codes.Code, details ...protoiface.MessageV1) error {
+ status := WithCodeAndDetails(err, code, details...)
+ return withStatusError{err, status}
+}
+
+// ForReason returns an ErrorInfo block for a specific error reason as defined in the V1 API.
+func ForReason(reason v1.ErrorReason, metadata map[string]string) *errdetails.ErrorInfo {
+ return &errdetails.ErrorInfo{
+ Reason: v1.ErrorReason_name[int32(reason)],
+ Domain: Domain,
+ Metadata: metadata,
+ }
+}
+
+// WithCodeAndReason returns a new error which wraps the existing error with a gRPC code and
+// a reason block.
+func WithCodeAndReason(err error, code codes.Code, reason v1.ErrorReason) error {
+ metadata := map[string]string{}
+
+ var hasMetadata HasMetadata
+ if ok := errors.As(err, &hasMetadata); ok {
+ metadata = hasMetadata.DetailsMetadata()
+ }
+
+ status := WithCodeAndDetails(err, code, ForReason(reason, metadata))
+ return withStatusError{err, status}
+}
+
+type SupportsAdditionalMetadata interface {
+ WithAdditionalDetails(key MetadataKey, value string)
+}
+
+// WithAdditionalDetails adds an additional details field to the error if it is possible.
+func WithAdditionalDetails(err error, key MetadataKey, value string) bool {
+ var supportsAdditionalDetails SupportsAdditionalMetadata
+ if ok := errors.As(err, &supportsAdditionalDetails); ok {
+ supportsAdditionalDetails.WithAdditionalDetails(key, value)
+ return true
+ }
+
+ return false
+}
+
+type withStatusError struct {
+ error
+ status *status.Status
+}
+
+func (err withStatusError) GRPCStatus() *status.Status {
+ return err.status
+}