From 26dae4dc6652b7835c2d88f94fa4f7e3594cabe5 Mon Sep 17 00:00:00 2001 From: jkoberg Date: Wed, 4 Oct 2023 12:16:55 +0200 Subject: [PATCH] improve error handling in utils package Signed-off-by: jkoberg --- changelog/unreleased/utils-error-handling.md | 5 ++ pkg/utils/grpc.go | 60 ++++++++++++++++---- 2 files changed, 54 insertions(+), 11 deletions(-) create mode 100644 changelog/unreleased/utils-error-handling.md diff --git a/changelog/unreleased/utils-error-handling.md b/changelog/unreleased/utils-error-handling.md new file mode 100644 index 0000000000..1b1a347755 --- /dev/null +++ b/changelog/unreleased/utils-error-handling.md @@ -0,0 +1,5 @@ +Enhancement: Improve error handling in utils package + +Improves error handling in the utils package. This has no impact on users. + +https://github.com/cs3org/reva/pull/4232 diff --git a/pkg/utils/grpc.go b/pkg/utils/grpc.go index 662a0b32f9..0be65a67db 100644 --- a/pkg/utils/grpc.go +++ b/pkg/utils/grpc.go @@ -27,6 +27,14 @@ var ( ManagerRole SpaceRole = func(perms *storageprovider.ResourcePermissions) bool { return perms.DenyGrant } ) +var _errStatusCodeTmpl = "unexpected status code while %s: %v" + +// Package error checkers +var ( + IsErrNotFound = func(err error) bool { return IsStatusCodeError(err, rpc.Code_CODE_NOT_FOUND) } + IsErrPermissionDenied = func(err error) bool { return IsStatusCodeError(err, rpc.Code_CODE_PERMISSION_DENIED) } +) + // GetServiceUserContext returns an authenticated context of the given service user func GetServiceUserContext(serviceUserID string, gwc gateway.GatewayAPIClient, serviceUserSecret string) (context.Context, error) { ctx := context.Background() @@ -38,8 +46,9 @@ func GetServiceUserContext(serviceUserID string, gwc gateway.GatewayAPIClient, s if err != nil { return nil, err } - if authRes.GetStatus().GetCode() != rpc.Code_CODE_OK { - return nil, fmt.Errorf("error authenticating service user: %s", authRes.Status.Message) + + if err := checkStatusCode("authenticating service user", authRes.GetStatus().GetCode()); err != nil { + return nil, err } return metadata.AppendToOutgoingContext(ctx, revactx.TokenHeader, authRes.Token), nil @@ -51,8 +60,9 @@ func GetUser(userID *user.UserId, gwc gateway.GatewayAPIClient) (*user.User, err if err != nil { return nil, err } - if getUserResponse.Status.Code != rpc.Code_CODE_OK { - return nil, fmt.Errorf("error getting user: %s", getUserResponse.Status.Message) + + if err := checkStatusCode("getting user", getUserResponse.GetStatus().GetCode()); err != nil { + return nil, err } return getUserResponse.GetUser(), nil @@ -65,12 +75,12 @@ func GetSpace(ctx context.Context, spaceID string, gwc gateway.GatewayAPIClient) return nil, err } - if res.GetStatus().GetCode() != rpc.Code_CODE_OK { - return nil, fmt.Errorf("error while getting space: (%v) %s", res.GetStatus().GetCode(), res.GetStatus().GetMessage()) + if err := checkStatusCode("getting space", res.GetStatus().GetCode()); err != nil { + return nil, err } if len(res.StorageSpaces) == 0 { - return nil, fmt.Errorf("error getting storage space %s: no space returned", spaceID) + return nil, statusCodeError{"getting space", rpc.Code_CODE_NOT_FOUND} } return res.StorageSpaces[0], nil @@ -83,8 +93,8 @@ func GetGroupMembers(ctx context.Context, groupID string, gwc gateway.GatewayAPI return nil, err } - if r.GetStatus().GetCode() != rpc.Code_CODE_OK { - return nil, fmt.Errorf("unexpected status code from gateway client: %d", r.GetStatus().GetCode()) + if err := checkStatusCode("getting group", r.GetStatus().GetCode()); err != nil { + return nil, err } users := make([]string, 0, len(r.GetGroup().GetMembers())) @@ -147,13 +157,30 @@ func GetResource(ctx context.Context, ref *storageprovider.Reference, gwc gatewa return nil, err } - if res.GetStatus().GetCode() != rpc.Code_CODE_OK { - return nil, fmt.Errorf("unexpected status code while getting space: %v", res.GetStatus().GetCode()) + if err := checkStatusCode("getting resource", res.GetStatus().GetCode()); err != nil { + return nil, err } return res.GetInfo(), nil } +// IsStatusCodeError returns true if `err` was caused because of status code `code` +func IsStatusCodeError(err error, code rpc.Code) bool { + sce, ok := err.(statusCodeError) + if !ok { + return false + } + + return sce.code == code +} + +func checkStatusCode(reason string, code rpc.Code) error { + if code == rpc.Code_CODE_OK { + return nil + } + return statusCodeError{reason, code} +} + func gatherProjectSpaceMembers(ctx context.Context, space *storageprovider.StorageSpace, gwc gateway.GatewayAPIClient, role SpaceRole) ([]string, error) { var permissionsMap map[string]*storageprovider.ResourcePermissions if err := ReadJSONFromOpaque(space.GetOpaque(), "grants", &permissionsMap); err != nil { @@ -215,3 +242,14 @@ func listStorageSpaceRequest(spaceID string) *storageprovider.ListStorageSpacesR }, } } + +// statusCodeError is a helper struct to return errors +type statusCodeError struct { + reason string + code rpc.Code +} + +// Error implements error interface +func (sce statusCodeError) Error() string { + return fmt.Sprintf(_errStatusCodeTmpl, sce.reason, sce.code) +}