diff --git a/changelog/unreleased/centralize-space-id-functions.md b/changelog/unreleased/centralize-space-id-functions.md new file mode 100644 index 0000000000..0401d645e2 --- /dev/null +++ b/changelog/unreleased/centralize-space-id-functions.md @@ -0,0 +1,5 @@ +Change: Merge the utility functions for space ids/references into one package + +Merged the utility functions regarding space ids or references into one package. Also updated the functions to support the newly added provider id in the spaces id. + +https://github.com/cs3org/reva/pull/2816 diff --git a/internal/grpc/interceptors/auth/scope.go b/internal/grpc/interceptors/auth/scope.go index 0097680ea1..67730fd3dd 100644 --- a/internal/grpc/interceptors/auth/scope.go +++ b/internal/grpc/interceptors/auth/scope.go @@ -40,9 +40,9 @@ import ( "github.com/cs3org/reva/v2/pkg/errtypes" statuspkg "github.com/cs3org/reva/v2/pkg/rgrpc/status" "github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool" + "github.com/cs3org/reva/v2/pkg/storagespace" "github.com/cs3org/reva/v2/pkg/token" "github.com/cs3org/reva/v2/pkg/utils" - "github.com/cs3org/reva/v2/pkg/utils/resourceid" "google.golang.org/grpc/metadata" ) @@ -137,7 +137,7 @@ func resolveLightweightScope(ctx context.Context, ref *provider.Reference, scope } for _, share := range shares.Shares { - shareKey := "lw:" + user.Id.OpaqueId + scopeDelimiter + resourceid.OwnCloudResourceIDWrap(share.Share.ResourceId) + shareKey := "lw:" + user.Id.OpaqueId + scopeDelimiter + storagespace.FormatResourceID(*share.Share.ResourceId) _ = scopeExpansionCache.SetWithExpire(shareKey, nil, scopeCacheExpiration*time.Second) if ref.ResourceId != nil && utils.ResourceIDEqual(share.Share.ResourceId, ref.ResourceId) { @@ -174,7 +174,7 @@ func resolveUserShare(ctx context.Context, ref *provider.Reference, scope *authp func checkCacheForNestedResource(ctx context.Context, ref *provider.Reference, resource *provider.ResourceId, client gateway.GatewayAPIClient, mgr token.Manager) error { // Check if this ref is cached - key := resourceid.OwnCloudResourceIDWrap(resource) + scopeDelimiter + getRefKey(ref) + key := storagespace.FormatResourceID(*resource) + scopeDelimiter + getRefKey(ref) if _, err := scopeExpansionCache.Get(key); err == nil { return nil } @@ -397,5 +397,5 @@ func getRefKey(ref *provider.Reference) string { if ref.Path != "" { return ref.Path } - return resourceid.OwnCloudResourceIDWrap(ref.ResourceId) + return storagespace.FormatResourceID(*ref.ResourceId) } diff --git a/internal/grpc/services/gateway/storageprovider.go b/internal/grpc/services/gateway/storageprovider.go index e076185c81..756bc61aa9 100644 --- a/internal/grpc/services/gateway/storageprovider.go +++ b/internal/grpc/services/gateway/storageprovider.go @@ -45,6 +45,7 @@ import ( "github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool" sdk "github.com/cs3org/reva/v2/pkg/sdk/common" "github.com/cs3org/reva/v2/pkg/share" + "github.com/cs3org/reva/v2/pkg/storagespace" "github.com/cs3org/reva/v2/pkg/utils" "github.com/golang-jwt/jwt" "github.com/pkg/errors" @@ -221,7 +222,7 @@ func (s *svc) ListStorageSpaces(ctx context.Context, req *provider.ListStorageSp for _, f := range req.Filters { switch f.Type { case provider.ListStorageSpacesRequest_Filter_TYPE_ID: - sid, oid, err := utils.SplitStorageSpaceID(f.GetId().OpaqueId) + sid, oid, err := storagespace.SplitID(f.GetId().OpaqueId) if err != nil { continue } @@ -308,7 +309,7 @@ func (s *svc) DeleteStorageSpace(ctx context.Context, req *provider.DeleteStorag _, purge = opaque.Map["purge"] } - storageid, opaqeid, err := utils.SplitStorageSpaceID(req.Id.OpaqueId) + storageid, opaqeid, err := storagespace.SplitID(req.Id.OpaqueId) if err != nil { return &provider.DeleteStorageSpaceResponse{ Status: status.NewStatusFromErrType(ctx, fmt.Sprintf("gateway could not split space id %s", req.GetId().GetOpaqueId()), err), diff --git a/internal/grpc/services/gateway/usershareprovider.go b/internal/grpc/services/gateway/usershareprovider.go index 85e1d2519d..e1ee3ebf34 100644 --- a/internal/grpc/services/gateway/usershareprovider.go +++ b/internal/grpc/services/gateway/usershareprovider.go @@ -34,8 +34,8 @@ import ( "github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool" "github.com/cs3org/reva/v2/pkg/share" "github.com/cs3org/reva/v2/pkg/storage/utils/grants" + "github.com/cs3org/reva/v2/pkg/storagespace" rtrace "github.com/cs3org/reva/v2/pkg/trace" - "github.com/cs3org/reva/v2/pkg/utils/resourceid" "github.com/pkg/errors" ) @@ -779,7 +779,7 @@ func refIsSpaceRoot(ref *provider.ResourceId) bool { if ref.StorageId == "" || ref.OpaqueId == "" { return false } - sid, _ := resourceid.StorageIDUnwrap(ref.GetStorageId()) + _, sid := storagespace.SplitStorageID(ref.GetStorageId()) return sid == ref.OpaqueId } diff --git a/internal/grpc/services/publicstorageprovider/publicstorageprovider.go b/internal/grpc/services/publicstorageprovider/publicstorageprovider.go index c7b1596e57..f959398596 100644 --- a/internal/grpc/services/publicstorageprovider/publicstorageprovider.go +++ b/internal/grpc/services/publicstorageprovider/publicstorageprovider.go @@ -37,9 +37,9 @@ import ( "github.com/cs3org/reva/v2/pkg/rgrpc" "github.com/cs3org/reva/v2/pkg/rgrpc/status" "github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool" + "github.com/cs3org/reva/v2/pkg/storagespace" rtrace "github.com/cs3org/reva/v2/pkg/trace" "github.com/cs3org/reva/v2/pkg/utils" - "github.com/cs3org/reva/v2/pkg/utils/resourceid" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" "go.opentelemetry.io/otel/attribute" @@ -104,7 +104,7 @@ func New(m map[string]interface{}, ss *grpc.Server) (rgrpc.Service, error) { func (s *service) SetArbitraryMetadata(ctx context.Context, req *provider.SetArbitraryMetadataRequest) (*provider.SetArbitraryMetadataResponse, error) { if req.Ref.GetResourceId() != nil { - req.Ref.ResourceId.StorageId, _ = resourceid.StorageIDUnwrap(req.Ref.ResourceId.StorageId) + _, req.Ref.ResourceId.StorageId = storagespace.SplitStorageID(req.Ref.ResourceId.StorageId) } ref, _, _, st, err := s.translatePublicRefToCS3Ref(ctx, req.Ref) @@ -126,7 +126,7 @@ func (s *service) UnsetArbitraryMetadata(ctx context.Context, req *provider.Unse // SetLock puts a lock on the given reference func (s *service) SetLock(ctx context.Context, req *provider.SetLockRequest) (*provider.SetLockResponse, error) { if req.Ref.GetResourceId() != nil { - req.Ref.ResourceId.StorageId, _ = resourceid.StorageIDUnwrap(req.Ref.ResourceId.StorageId) + _, req.Ref.ResourceId.StorageId = storagespace.SplitStorageID(req.Ref.ResourceId.StorageId) } ref, _, _, st, err := s.translatePublicRefToCS3Ref(ctx, req.Ref) @@ -144,7 +144,7 @@ func (s *service) SetLock(ctx context.Context, req *provider.SetLockRequest) (*p // GetLock returns an existing lock on the given reference func (s *service) GetLock(ctx context.Context, req *provider.GetLockRequest) (*provider.GetLockResponse, error) { if req.Ref.GetResourceId() != nil { - req.Ref.ResourceId.StorageId, _ = resourceid.StorageIDUnwrap(req.Ref.ResourceId.StorageId) + _, req.Ref.ResourceId.StorageId = storagespace.SplitStorageID(req.Ref.ResourceId.StorageId) } ref, _, _, st, err := s.translatePublicRefToCS3Ref(ctx, req.Ref) @@ -162,7 +162,7 @@ func (s *service) GetLock(ctx context.Context, req *provider.GetLockRequest) (*p // RefreshLock refreshes an existing lock on the given reference func (s *service) RefreshLock(ctx context.Context, req *provider.RefreshLockRequest) (*provider.RefreshLockResponse, error) { if req.Ref.GetResourceId() != nil { - req.Ref.ResourceId.StorageId, _ = resourceid.StorageIDUnwrap(req.Ref.ResourceId.StorageId) + _, req.Ref.ResourceId.StorageId = storagespace.SplitStorageID(req.Ref.ResourceId.StorageId) } ref, _, _, st, err := s.translatePublicRefToCS3Ref(ctx, req.Ref) @@ -180,7 +180,7 @@ func (s *service) RefreshLock(ctx context.Context, req *provider.RefreshLockRequ // Unlock removes an existing lock from the given reference func (s *service) Unlock(ctx context.Context, req *provider.UnlockRequest) (*provider.UnlockResponse, error) { if req.Ref.GetResourceId() != nil { - req.Ref.ResourceId.StorageId, _ = resourceid.StorageIDUnwrap(req.Ref.ResourceId.StorageId) + _, req.Ref.ResourceId.StorageId = storagespace.SplitStorageID(req.Ref.ResourceId.StorageId) } ref, _, _, st, err := s.translatePublicRefToCS3Ref(ctx, req.Ref) @@ -197,7 +197,7 @@ func (s *service) Unlock(ctx context.Context, req *provider.UnlockRequest) (*pro func (s *service) InitiateFileDownload(ctx context.Context, req *provider.InitiateFileDownloadRequest) (*provider.InitiateFileDownloadResponse, error) { if req.Ref.GetResourceId() != nil { - req.Ref.ResourceId.StorageId, _ = resourceid.StorageIDUnwrap(req.Ref.ResourceId.StorageId) + _, req.Ref.ResourceId.StorageId = storagespace.SplitStorageID(req.Ref.ResourceId.StorageId) } statReq := &provider.StatRequest{Ref: req.Ref} @@ -323,7 +323,7 @@ func (s *service) initiateFileDownload(ctx context.Context, req *provider.Initia func (s *service) InitiateFileUpload(ctx context.Context, req *provider.InitiateFileUploadRequest) (*provider.InitiateFileUploadResponse, error) { if req.Ref.GetResourceId() != nil { - req.Ref.ResourceId.StorageId, _ = resourceid.StorageIDUnwrap(req.Ref.ResourceId.StorageId) + _, req.Ref.ResourceId.StorageId = storagespace.SplitStorageID(req.Ref.ResourceId.StorageId) } cs3Ref, _, ls, st, err := s.translatePublicRefToCS3Ref(ctx, req.Ref) @@ -411,7 +411,7 @@ func (s *service) CreateStorageSpace(ctx context.Context, req *provider.CreateSt func (s *service) ListStorageSpaces(ctx context.Context, req *provider.ListStorageSpacesRequest) (*provider.ListStorageSpacesResponse, error) { for i, f := range req.Filters { if f.Type == provider.ListStorageSpacesRequest_Filter_TYPE_ID { - id, _ := resourceid.StorageIDUnwrap(f.GetId().GetOpaqueId()) + _, id := storagespace.SplitStorageID(f.GetId().GetOpaqueId()) req.Filters[i].Term = &provider.ListStorageSpacesRequest_Filter_Id{Id: &provider.StorageSpaceId{OpaqueId: id}} break } @@ -431,7 +431,7 @@ func (s *service) ListStorageSpaces(ctx context.Context, req *provider.ListStora } spaceTypes[spaceType] = exists case provider.ListStorageSpacesRequest_Filter_TYPE_ID: - spaceid, shareid, err := utils.SplitStorageSpaceID(f.GetId().OpaqueId) + spaceid, shareid, err := storagespace.SplitID(f.GetId().OpaqueId) if err != nil { continue } @@ -549,7 +549,7 @@ func (s *service) DeleteStorageSpace(ctx context.Context, req *provider.DeleteSt func (s *service) CreateContainer(ctx context.Context, req *provider.CreateContainerRequest) (*provider.CreateContainerResponse, error) { if req.Ref.GetResourceId() != nil { - req.Ref.ResourceId.StorageId, _ = resourceid.StorageIDUnwrap(req.Ref.ResourceId.StorageId) + _, req.Ref.ResourceId.StorageId = storagespace.SplitStorageID(req.Ref.ResourceId.StorageId) } ctx, span := rtrace.Provider.Tracer("publicstorageprovider").Start(ctx, "CreateContainer") @@ -593,7 +593,7 @@ func (s *service) CreateContainer(ctx context.Context, req *provider.CreateConta func (s *service) TouchFile(ctx context.Context, req *provider.TouchFileRequest) (*provider.TouchFileResponse, error) { if req.Ref.GetResourceId() != nil { - req.Ref.ResourceId.StorageId, _ = resourceid.StorageIDUnwrap(req.Ref.ResourceId.StorageId) + _, req.Ref.ResourceId.StorageId = storagespace.SplitStorageID(req.Ref.ResourceId.StorageId) } ref, _, _, st, err := s.translatePublicRefToCS3Ref(ctx, req.Ref) @@ -610,7 +610,7 @@ func (s *service) TouchFile(ctx context.Context, req *provider.TouchFileRequest) func (s *service) Delete(ctx context.Context, req *provider.DeleteRequest) (*provider.DeleteResponse, error) { if req.Ref.GetResourceId() != nil { - req.Ref.ResourceId.StorageId, _ = resourceid.StorageIDUnwrap(req.Ref.ResourceId.StorageId) + _, req.Ref.ResourceId.StorageId = storagespace.SplitStorageID(req.Ref.ResourceId.StorageId) } ctx, span := rtrace.Provider.Tracer("publicstorageprovider").Start(ctx, "Delete") @@ -654,10 +654,10 @@ func (s *service) Delete(ctx context.Context, req *provider.DeleteRequest) (*pro func (s *service) Move(ctx context.Context, req *provider.MoveRequest) (*provider.MoveResponse, error) { if req.Source.GetResourceId() != nil { - req.Source.ResourceId.StorageId, _ = resourceid.StorageIDUnwrap(req.Source.ResourceId.StorageId) + _, req.Source.ResourceId.StorageId = storagespace.SplitStorageID(req.Source.ResourceId.StorageId) } if req.Destination.GetResourceId() != nil { - req.Destination.ResourceId.StorageId, _ = resourceid.StorageIDUnwrap(req.Destination.ResourceId.StorageId) + _, req.Destination.ResourceId.StorageId = storagespace.SplitStorageID(req.Destination.ResourceId.StorageId) } ctx, span := rtrace.Provider.Tracer("publicstorageprovider").Start(ctx, "Move") @@ -724,7 +724,7 @@ func (s *service) Move(ctx context.Context, req *provider.MoveRequest) (*provide func (s *service) Stat(ctx context.Context, req *provider.StatRequest) (*provider.StatResponse, error) { if req.Ref.GetResourceId() != nil { - req.Ref.ResourceId.StorageId, _ = resourceid.StorageIDUnwrap(req.Ref.ResourceId.StorageId) + _, req.Ref.ResourceId.StorageId = storagespace.SplitStorageID(req.Ref.ResourceId.StorageId) } ctx, span := rtrace.Provider.Tracer("publicstorageprovider").Start(ctx, "Stat") @@ -825,7 +825,7 @@ func (s *service) ListContainerStream(req *provider.ListContainerStreamRequest, func (s *service) ListContainer(ctx context.Context, req *provider.ListContainerRequest) (*provider.ListContainerResponse, error) { if req.Ref.GetResourceId() != nil { - req.Ref.ResourceId.StorageId, _ = resourceid.StorageIDUnwrap(req.Ref.ResourceId.StorageId) + _, req.Ref.ResourceId.StorageId = storagespace.SplitStorageID(req.Ref.ResourceId.StorageId) } share, ok := extractLinkFromScope(ctx) diff --git a/internal/grpc/services/sharesstorageprovider/sharesstorageprovider.go b/internal/grpc/services/sharesstorageprovider/sharesstorageprovider.go index 18323a344c..ec8f2f63b8 100644 --- a/internal/grpc/services/sharesstorageprovider/sharesstorageprovider.go +++ b/internal/grpc/services/sharesstorageprovider/sharesstorageprovider.go @@ -26,7 +26,7 @@ import ( "strings" "github.com/cs3org/reva/v2/pkg/share" - "github.com/cs3org/reva/v2/pkg/utils/resourceid" + "github.com/cs3org/reva/v2/pkg/storagespace" "google.golang.org/grpc" codes "google.golang.org/grpc/codes" gstatus "google.golang.org/grpc/status" @@ -107,7 +107,7 @@ func New(gateway gateway.GatewayAPIClient, c collaboration.CollaborationAPIClien func (s *service) SetArbitraryMetadata(ctx context.Context, req *provider.SetArbitraryMetadataRequest) (*provider.SetArbitraryMetadataResponse, error) { if req.Ref.GetResourceId() != nil { - req.Ref.ResourceId.StorageId, _ = resourceid.StorageIDUnwrap(req.Ref.ResourceId.StorageId) + _, req.Ref.ResourceId.StorageId = storagespace.SplitStorageID(req.Ref.ResourceId.StorageId) } receivedShare, rpcStatus, err := s.resolveReference(ctx, req.Ref) @@ -135,7 +135,7 @@ func (s *service) SetArbitraryMetadata(ctx context.Context, req *provider.SetArb func (s *service) UnsetArbitraryMetadata(ctx context.Context, req *provider.UnsetArbitraryMetadataRequest) (*provider.UnsetArbitraryMetadataResponse, error) { if req.Ref.GetResourceId() != nil { - req.Ref.ResourceId.StorageId, _ = resourceid.StorageIDUnwrap(req.Ref.ResourceId.StorageId) + _, req.Ref.ResourceId.StorageId = storagespace.SplitStorageID(req.Ref.ResourceId.StorageId) } receivedShare, rpcStatus, err := s.resolveReference(ctx, req.Ref) @@ -163,7 +163,7 @@ func (s *service) UnsetArbitraryMetadata(ctx context.Context, req *provider.Unse func (s *service) InitiateFileDownload(ctx context.Context, req *provider.InitiateFileDownloadRequest) (*provider.InitiateFileDownloadResponse, error) { if req.Ref.GetResourceId() != nil { - req.Ref.ResourceId.StorageId, _ = resourceid.StorageIDUnwrap(req.Ref.ResourceId.StorageId) + _, req.Ref.ResourceId.StorageId = storagespace.SplitStorageID(req.Ref.ResourceId.StorageId) } receivedShare, rpcStatus, err := s.resolveReference(ctx, req.Ref) @@ -219,7 +219,7 @@ func (s *service) InitiateFileDownload(ctx context.Context, req *provider.Initia func (s *service) InitiateFileUpload(ctx context.Context, req *provider.InitiateFileUploadRequest) (*provider.InitiateFileUploadResponse, error) { if req.Ref.GetResourceId() != nil { - req.Ref.ResourceId.StorageId, _ = resourceid.StorageIDUnwrap(req.Ref.ResourceId.StorageId) + _, req.Ref.ResourceId.StorageId = storagespace.SplitStorageID(req.Ref.ResourceId.StorageId) } receivedShare, rpcStatus, err := s.resolveReference(ctx, req.Ref) @@ -308,7 +308,7 @@ func (s *service) CreateStorageSpace(ctx context.Context, req *provider.CreateSt func (s *service) ListStorageSpaces(ctx context.Context, req *provider.ListStorageSpacesRequest) (*provider.ListStorageSpacesResponse, error) { for i, f := range req.Filters { if f.Type == provider.ListStorageSpacesRequest_Filter_TYPE_ID { - id, _ := resourceid.StorageIDUnwrap(f.GetId().GetOpaqueId()) + _, id := storagespace.SplitStorageID(f.GetId().GetOpaqueId()) req.Filters[i].Term = &provider.ListStorageSpacesRequest_Filter_Id{Id: &provider.StorageSpaceId{OpaqueId: id}} break } @@ -334,7 +334,7 @@ func (s *service) ListStorageSpaces(ctx context.Context, req *provider.ListStora } spaceTypes[spaceType] = exists case provider.ListStorageSpacesRequest_Filter_TYPE_ID: - spaceid, shareid, err := utils.SplitStorageSpaceID(f.GetId().OpaqueId) + spaceid, shareid, err := storagespace.SplitID(f.GetId().OpaqueId) if err != nil { continue } @@ -499,7 +499,7 @@ func (s *service) DeleteStorageSpace(ctx context.Context, req *provider.DeleteSt func (s *service) CreateContainer(ctx context.Context, req *provider.CreateContainerRequest) (*provider.CreateContainerResponse, error) { if req.Ref.GetResourceId() != nil { - req.Ref.ResourceId.StorageId, _ = resourceid.StorageIDUnwrap(req.Ref.ResourceId.StorageId) + _, req.Ref.ResourceId.StorageId = storagespace.SplitStorageID(req.Ref.ResourceId.StorageId) } receivedShare, rpcStatus, err := s.resolveReference(ctx, req.Ref) @@ -526,7 +526,7 @@ func (s *service) CreateContainer(ctx context.Context, req *provider.CreateConta func (s *service) Delete(ctx context.Context, req *provider.DeleteRequest) (*provider.DeleteResponse, error) { if req.Ref.GetResourceId() != nil { - req.Ref.ResourceId.StorageId, _ = resourceid.StorageIDUnwrap(req.Ref.ResourceId.StorageId) + _, req.Ref.ResourceId.StorageId = storagespace.SplitStorageID(req.Ref.ResourceId.StorageId) } receivedShare, rpcStatus, err := s.resolveReference(ctx, req.Ref) @@ -567,10 +567,10 @@ func (s *service) Delete(ctx context.Context, req *provider.DeleteRequest) (*pro func (s *service) Move(ctx context.Context, req *provider.MoveRequest) (*provider.MoveResponse, error) { if req.Source.GetResourceId() != nil { - req.Source.ResourceId.StorageId, _ = resourceid.StorageIDUnwrap(req.Source.ResourceId.StorageId) + _, req.Source.ResourceId.StorageId = storagespace.SplitStorageID(req.Source.ResourceId.StorageId) } if req.Destination.GetResourceId() != nil { - req.Destination.ResourceId.StorageId, _ = resourceid.StorageIDUnwrap(req.Destination.ResourceId.StorageId) + _, req.Destination.ResourceId.StorageId = storagespace.SplitStorageID(req.Destination.ResourceId.StorageId) } appctx.GetLogger(ctx).Debug(). @@ -671,7 +671,7 @@ func (s *service) Unlock(ctx context.Context, req *provider.UnlockRequest) (*pro func (s *service) Stat(ctx context.Context, req *provider.StatRequest) (*provider.StatResponse, error) { if req.Ref.GetResourceId() != nil { - req.Ref.ResourceId.StorageId, _ = resourceid.StorageIDUnwrap(req.Ref.ResourceId.StorageId) + _, req.Ref.ResourceId.StorageId = storagespace.SplitStorageID(req.Ref.ResourceId.StorageId) } if isVirtualRoot(req.Ref.ResourceId) && (req.Ref.Path == "" || req.Ref.Path == ".") { @@ -756,7 +756,7 @@ func isVirtualRoot(id *provider.ResourceId) bool { } func (s *service) ListContainer(ctx context.Context, req *provider.ListContainerRequest) (*provider.ListContainerResponse, error) { if req.Ref.GetResourceId() != nil { - req.Ref.ResourceId.StorageId, _ = resourceid.StorageIDUnwrap(req.Ref.ResourceId.StorageId) + _, req.Ref.ResourceId.StorageId = storagespace.SplitStorageID(req.Ref.ResourceId.StorageId) } if isVirtualRoot(req.Ref.ResourceId) { @@ -792,7 +792,7 @@ func (s *service) ListContainer(ctx context.Context, req *provider.ListContainer } func (s *service) ListFileVersions(ctx context.Context, req *provider.ListFileVersionsRequest) (*provider.ListFileVersionsResponse, error) { if req.Ref.GetResourceId() != nil { - req.Ref.ResourceId.StorageId, _ = resourceid.StorageIDUnwrap(req.Ref.ResourceId.StorageId) + _, req.Ref.ResourceId.StorageId = storagespace.SplitStorageID(req.Ref.ResourceId.StorageId) } receivedShare, rpcStatus, err := s.resolveReference(ctx, req.Ref) @@ -820,7 +820,7 @@ func (s *service) ListFileVersions(ctx context.Context, req *provider.ListFileVe func (s *service) RestoreFileVersion(ctx context.Context, req *provider.RestoreFileVersionRequest) (*provider.RestoreFileVersionResponse, error) { if req.Ref.GetResourceId() != nil { - req.Ref.ResourceId.StorageId, _ = resourceid.StorageIDUnwrap(req.Ref.ResourceId.StorageId) + _, req.Ref.ResourceId.StorageId = storagespace.SplitStorageID(req.Ref.ResourceId.StorageId) } receivedShare, rpcStatus, err := s.resolveReference(ctx, req.Ref) @@ -897,7 +897,7 @@ func (s *service) TouchFile(ctx context.Context, req *provider.TouchFileRequest) // GetQuota returns 0 free quota. It is virtual ... the shares may have a different quota ... func (s *service) GetQuota(ctx context.Context, req *provider.GetQuotaRequest) (*provider.GetQuotaResponse, error) { if req.Ref.GetResourceId() != nil { - req.Ref.ResourceId.StorageId, _ = resourceid.StorageIDUnwrap(req.Ref.ResourceId.StorageId) + _, req.Ref.ResourceId.StorageId = storagespace.SplitStorageID(req.Ref.ResourceId.StorageId) } // FIXME use req.Ref to get real quota diff --git a/internal/grpc/services/storageprovider/storageprovider.go b/internal/grpc/services/storageprovider/storageprovider.go index cfdd2bec16..c21b56e21d 100644 --- a/internal/grpc/services/storageprovider/storageprovider.go +++ b/internal/grpc/services/storageprovider/storageprovider.go @@ -41,9 +41,9 @@ import ( "github.com/cs3org/reva/v2/pkg/rhttp/router" "github.com/cs3org/reva/v2/pkg/storage" "github.com/cs3org/reva/v2/pkg/storage/fs/registry" + "github.com/cs3org/reva/v2/pkg/storagespace" rtrace "github.com/cs3org/reva/v2/pkg/trace" "github.com/cs3org/reva/v2/pkg/utils" - "github.com/cs3org/reva/v2/pkg/utils/resourceid" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" "go.opentelemetry.io/otel/attribute" @@ -497,15 +497,15 @@ func (s *service) CreateStorageSpace(ctx context.Context, req *provider.CreateSt }, nil } - resp.StorageSpace.Id.OpaqueId = resourceid.StorageIDWrap(resp.StorageSpace.Id.GetOpaqueId(), s.conf.MountID) - resp.StorageSpace.Root.StorageId = resourceid.StorageIDWrap(resp.StorageSpace.Root.GetStorageId(), s.conf.MountID) + resp.StorageSpace.Id.OpaqueId = storagespace.FormatStorageID(s.conf.MountID, resp.StorageSpace.Id.GetOpaqueId()) + resp.StorageSpace.Root.StorageId = storagespace.FormatStorageID(s.conf.MountID, resp.StorageSpace.Root.GetStorageId()) return resp, nil } func (s *service) ListStorageSpaces(ctx context.Context, req *provider.ListStorageSpacesRequest) (*provider.ListStorageSpacesResponse, error) { for i, f := range req.Filters { if f.Type == provider.ListStorageSpacesRequest_Filter_TYPE_ID { - id, _ := resourceid.StorageIDUnwrap(f.GetId().GetOpaqueId()) + _, id := storagespace.SplitStorageID(f.GetId().GetOpaqueId()) req.Filters[i].Term = &provider.ListStorageSpacesRequest_Filter_Id{Id: &provider.StorageSpaceId{OpaqueId: id}} break } @@ -549,8 +549,8 @@ func (s *service) ListStorageSpaces(ctx context.Context, req *provider.ListStora log.Error().Str("service", "storageprovider").Str("driver", s.conf.Driver).Interface("space", sp).Msg("space is missing space id and root id") continue } - sp.Id.OpaqueId = resourceid.StorageIDWrap(sp.Id.GetOpaqueId(), s.conf.MountID) - sp.Root.StorageId = resourceid.StorageIDWrap(sp.Root.GetStorageId(), s.conf.MountID) + sp.Id.OpaqueId = storagespace.FormatStorageID(s.conf.MountID, sp.Id.GetOpaqueId()) + sp.Root.StorageId = storagespace.FormatStorageID(s.conf.MountID, sp.Root.GetStorageId()) } return &provider.ListStorageSpacesResponse{ @@ -561,8 +561,8 @@ func (s *service) ListStorageSpaces(ctx context.Context, req *provider.ListStora func (s *service) UpdateStorageSpace(ctx context.Context, req *provider.UpdateStorageSpaceRequest) (*provider.UpdateStorageSpaceResponse, error) { if req.GetStorageSpace().GetId() != nil { - req.StorageSpace.Id.OpaqueId, _ = resourceid.StorageIDUnwrap(req.StorageSpace.Id.OpaqueId) - req.StorageSpace.Root.StorageId, _ = resourceid.StorageIDUnwrap(req.StorageSpace.Root.StorageId) + _, req.StorageSpace.Id.OpaqueId = storagespace.SplitStorageID(req.StorageSpace.Id.OpaqueId) + _, req.StorageSpace.Root.StorageId = storagespace.SplitStorageID(req.StorageSpace.Root.StorageId) } res, err := s.storage.UpdateStorageSpace(ctx, req) @@ -574,14 +574,14 @@ func (s *service) UpdateStorageSpace(ctx context.Context, req *provider.UpdateSt Msg("failed to update storage space") return nil, err } - res.StorageSpace.Id.OpaqueId = resourceid.StorageIDWrap(res.StorageSpace.Id.GetOpaqueId(), s.conf.MountID) - res.StorageSpace.Root.StorageId = resourceid.StorageIDWrap(res.StorageSpace.Root.GetStorageId(), s.conf.MountID) + res.StorageSpace.Id.OpaqueId = storagespace.FormatStorageID(s.conf.MountID, res.StorageSpace.Id.GetOpaqueId()) + res.StorageSpace.Root.StorageId = storagespace.FormatStorageID(s.conf.MountID, res.StorageSpace.Root.GetStorageId()) return res, nil } func (s *service) DeleteStorageSpace(ctx context.Context, req *provider.DeleteStorageSpaceRequest) (*provider.DeleteStorageSpaceResponse, error) { if req.GetId() != nil { - req.Id.OpaqueId, _ = resourceid.StorageIDUnwrap(req.Id.OpaqueId) + _, req.Id.OpaqueId = storagespace.SplitStorageID(req.Id.OpaqueId) } if err := s.storage.DeleteStorageSpace(ctx, req); err != nil { @@ -726,7 +726,7 @@ func (s *service) Stat(ctx context.Context, req *provider.StatRequest) (*provide if providerID == "" { providerID = s.conf.MountID } - md.Id.StorageId = resourceid.StorageIDWrap(md.Id.GetStorageId(), providerID) + md.Id.StorageId = storagespace.FormatStorageID(providerID, md.Id.GetStorageId()) return &provider.StatResponse{ Status: status.NewOK(ctx), Info: md, @@ -794,7 +794,7 @@ func (s *service) ListContainer(ctx context.Context, req *provider.ListContainer } for _, i := range res.Infos { - i.Id.StorageId = resourceid.StorageIDWrap(i.Id.GetStorageId(), s.conf.MountID) + i.Id.StorageId = storagespace.FormatStorageID(s.conf.MountID, i.Id.GetStorageId()) } return res, nil } @@ -905,7 +905,7 @@ func (s *service) ListRecycle(ctx context.Context, req *provider.ListRecycleRequ for _, i := range items { if i.Ref != nil && i.Ref.ResourceId != nil { - i.Ref.ResourceId.StorageId = resourceid.StorageIDWrap(i.Ref.GetResourceId().GetStorageId(), s.conf.MountID) + i.Ref.ResourceId.StorageId = storagespace.FormatStorageID(s.conf.MountID, i.Ref.GetResourceId().GetStorageId()) } } res := &provider.ListRecycleResponse{ @@ -1244,13 +1244,13 @@ func (v descendingMtime) Swap(i, j int) { func unwrapProviderID(id *provider.ResourceId) string { var spid string if id != nil { - id.StorageId, spid = resourceid.StorageIDUnwrap(id.StorageId) + spid, id.StorageId = storagespace.SplitStorageID(id.StorageId) } return spid } func rewrapProviderID(id *provider.ResourceId, spid string) { if id != nil { - id.StorageId = resourceid.StorageIDWrap(id.StorageId, spid) + id.StorageId = storagespace.FormatStorageID(spid, id.StorageId) } } diff --git a/internal/http/services/appprovider/appprovider.go b/internal/http/services/appprovider/appprovider.go index e73cfdaf72..06cda3b13c 100644 --- a/internal/http/services/appprovider/appprovider.go +++ b/internal/http/services/appprovider/appprovider.go @@ -34,8 +34,8 @@ import ( "github.com/cs3org/reva/v2/pkg/rhttp" "github.com/cs3org/reva/v2/pkg/rhttp/global" "github.com/cs3org/reva/v2/pkg/sharedconf" + "github.com/cs3org/reva/v2/pkg/storagespace" "github.com/cs3org/reva/v2/pkg/utils" - "github.com/cs3org/reva/v2/pkg/utils/resourceid" "github.com/go-chi/chi" ua "github.com/mileusna/useragent" "github.com/mitchellh/mapstructure" @@ -135,8 +135,8 @@ func (s *svc) handleNew(w http.ResponseWriter, r *http.Request) { return } - parentContainerRef := resourceid.OwnCloudResourceIDUnwrap(parentContainerID) - if parentContainerRef == nil { + parentContainerRef, err := storagespace.ParseID(parentContainerID) + if err != nil { writeError(w, r, appErrorInvalidParameter, "invalid parent container ID", nil) return } @@ -155,7 +155,7 @@ func (s *svc) handleNew(w http.ResponseWriter, r *http.Request) { statParentContainerReq := &provider.StatRequest{ Ref: &provider.Reference{ - ResourceId: parentContainerRef, + ResourceId: &parentContainerRef, }, } parentContainer, err := client.Stat(ctx, statParentContainerReq) @@ -271,7 +271,7 @@ func (s *svc) handleNew(w http.ResponseWriter, r *http.Request) { js, err := json.Marshal( map[string]interface{}{ - "file_id": resourceid.OwnCloudResourceIDWrap(statRes.Info.Id), + "file_id": storagespace.FormatResourceID(*statRes.Info.Id), }, ) if err != nil { @@ -334,14 +334,14 @@ func (s *svc) handleOpen(w http.ResponseWriter, r *http.Request) { return } - resourceID := resourceid.OwnCloudResourceIDUnwrap(fileID) - if resourceID == nil { + resourceID, err := storagespace.ParseID(fileID) + if err != nil { writeError(w, r, appErrorInvalidParameter, "invalid file ID", nil) return } fileRef := &provider.Reference{ - ResourceId: resourceID, + ResourceId: &resourceID, Path: ".", } diff --git a/internal/http/services/archiver/handler.go b/internal/http/services/archiver/handler.go index c56eae581c..8726a9e6be 100644 --- a/internal/http/services/archiver/handler.go +++ b/internal/http/services/archiver/handler.go @@ -39,7 +39,7 @@ import ( "github.com/cs3org/reva/v2/pkg/sharedconf" "github.com/cs3org/reva/v2/pkg/storage/utils/downloader" "github.com/cs3org/reva/v2/pkg/storage/utils/walker" - "github.com/cs3org/reva/v2/pkg/utils/resourceid" + "github.com/cs3org/reva/v2/pkg/storagespace" "github.com/gdexlab/go-render/render" ua "github.com/mileusna/useragent" "github.com/mitchellh/mapstructure" @@ -129,12 +129,12 @@ func (s *svc) getResources(ctx context.Context, paths, ids []string) ([]*provide for _, id := range ids { // id is base64 encoded and after decoding has the form : - decodedID := resourceid.OwnCloudResourceIDUnwrap(id) - if decodedID == nil { + decodedID, err := storagespace.ParseID(id) + if err != nil { return nil, errors.New("could not unwrap given file id") } - resources = append(resources, decodedID) + resources = append(resources, &decodedID) } diff --git a/internal/http/services/owncloud/ocdav/get.go b/internal/http/services/owncloud/ocdav/get.go index 6b1413ac68..4022532407 100644 --- a/internal/http/services/owncloud/ocdav/get.go +++ b/internal/http/services/owncloud/ocdav/get.go @@ -37,9 +37,9 @@ import ( "github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/spacelookup" "github.com/cs3org/reva/v2/pkg/appctx" "github.com/cs3org/reva/v2/pkg/rhttp" + "github.com/cs3org/reva/v2/pkg/storagespace" rtrace "github.com/cs3org/reva/v2/pkg/trace" "github.com/cs3org/reva/v2/pkg/utils" - "github.com/cs3org/reva/v2/pkg/utils/resourceid" "github.com/rs/zerolog" ) @@ -146,7 +146,7 @@ func (s *svc) handleGet(ctx context.Context, w http.ResponseWriter, r *http.Requ w.Header().Set(net.HeaderContentDisposistion, "attachment; filename*=UTF-8''"+ path.Base(r.URL.Path)+"; filename=\""+path.Base(r.URL.Path)+"\"") w.Header().Set(net.HeaderETag, info.Etag) - w.Header().Set(net.HeaderOCFileID, resourceid.OwnCloudResourceIDWrap(info.Id)) + w.Header().Set(net.HeaderOCFileID, storagespace.FormatResourceID(*info.Id)) w.Header().Set(net.HeaderOCETag, info.Etag) t := utils.TSToTime(info.Mtime).UTC() lastModifiedString := t.Format(time.RFC1123Z) diff --git a/internal/http/services/owncloud/ocdav/head.go b/internal/http/services/owncloud/ocdav/head.go index 1882d52a20..d5dd7c7447 100644 --- a/internal/http/services/owncloud/ocdav/head.go +++ b/internal/http/services/owncloud/ocdav/head.go @@ -27,8 +27,8 @@ import ( "strings" "time" + "github.com/cs3org/reva/v2/pkg/storagespace" rtrace "github.com/cs3org/reva/v2/pkg/trace" - "github.com/cs3org/reva/v2/pkg/utils/resourceid" rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" @@ -93,7 +93,7 @@ func (s *svc) handleHead(ctx context.Context, w http.ResponseWriter, r *http.Req info := res.Info w.Header().Set(net.HeaderContentType, info.MimeType) w.Header().Set(net.HeaderETag, info.Etag) - w.Header().Set(net.HeaderOCFileID, resourceid.OwnCloudResourceIDWrap(info.Id)) + w.Header().Set(net.HeaderOCFileID, storagespace.FormatResourceID(*info.Id)) w.Header().Set(net.HeaderOCETag, info.Etag) if info.Checksum != nil { w.Header().Set(net.HeaderOCChecksum, fmt.Sprintf("%s:%s", strings.ToUpper(string(storageprovider.GRPC2PKGXS(info.Checksum.Type))), info.Checksum.Sum)) diff --git a/internal/http/services/owncloud/ocdav/meta.go b/internal/http/services/owncloud/ocdav/meta.go index 820d808a60..f6bb481b23 100644 --- a/internal/http/services/owncloud/ocdav/meta.go +++ b/internal/http/services/owncloud/ocdav/meta.go @@ -32,8 +32,8 @@ import ( "github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/propfind" "github.com/cs3org/reva/v2/pkg/appctx" "github.com/cs3org/reva/v2/pkg/rhttp/router" + "github.com/cs3org/reva/v2/pkg/storagespace" rtrace "github.com/cs3org/reva/v2/pkg/trace" - "github.com/cs3org/reva/v2/pkg/utils/resourceid" ) // MetaHandler handles meta requests @@ -57,8 +57,8 @@ func (h *MetaHandler) Handler(s *svc) http.Handler { return } - did := resourceid.OwnCloudResourceIDUnwrap(id) - if did == nil { + did, err := storagespace.ParseID(id) + if err != nil { logger := appctx.GetLogger(r.Context()) logger.Debug().Str("prop", net.PropOcMetaPathForUser).Msg("invalid resource id") w.WriteHeader(http.StatusBadRequest) @@ -76,9 +76,9 @@ func (h *MetaHandler) Handler(s *svc) http.Handler { w.WriteHeader(http.StatusBadRequest) return } - h.handlePathForUser(w, r, s, did) + h.handlePathForUser(w, r, s, &did) case "v": - h.VersionsHandler.Handler(s, did).ServeHTTP(w, r) + h.VersionsHandler.Handler(s, &did).ServeHTTP(w, r) default: w.WriteHeader(http.StatusNotFound) } @@ -90,7 +90,7 @@ func (h *MetaHandler) handlePathForUser(w http.ResponseWriter, r *http.Request, ctx, span := rtrace.Provider.Tracer("ocdav").Start(r.Context(), "meta_propfind") defer span.End() - id := resourceid.OwnCloudResourceIDWrap(rid) + id := storagespace.FormatResourceID(*rid) sublog := appctx.GetLogger(ctx).With().Str("path", r.URL.Path).Str("resourceid", id).Logger() client, err := s.getClient() if err != nil { diff --git a/internal/http/services/owncloud/ocdav/move.go b/internal/http/services/owncloud/ocdav/move.go index 0146cd5fa8..84a2cfae32 100644 --- a/internal/http/services/owncloud/ocdav/move.go +++ b/internal/http/services/owncloud/ocdav/move.go @@ -31,9 +31,9 @@ import ( "github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/spacelookup" "github.com/cs3org/reva/v2/pkg/appctx" "github.com/cs3org/reva/v2/pkg/rhttp/router" + "github.com/cs3org/reva/v2/pkg/storagespace" rtrace "github.com/cs3org/reva/v2/pkg/trace" "github.com/cs3org/reva/v2/pkg/utils" - "github.com/cs3org/reva/v2/pkg/utils/resourceid" "github.com/rs/zerolog" ) @@ -278,7 +278,7 @@ func (s *svc) handleMove(ctx context.Context, w http.ResponseWriter, r *http.Req info := dstStatRes.Info w.Header().Set(net.HeaderContentType, info.MimeType) w.Header().Set(net.HeaderETag, info.Etag) - w.Header().Set(net.HeaderOCFileID, resourceid.OwnCloudResourceIDWrap(info.Id)) + w.Header().Set(net.HeaderOCFileID, storagespace.FormatResourceID(*info.Id)) w.Header().Set(net.HeaderOCETag, info.Etag) w.WriteHeader(successCode) } diff --git a/internal/http/services/owncloud/ocdav/ocdav_test.go b/internal/http/services/owncloud/ocdav/ocdav_test.go index 13f47f4cc3..e6108d4423 100644 --- a/internal/http/services/owncloud/ocdav/ocdav_test.go +++ b/internal/http/services/owncloud/ocdav/ocdav_test.go @@ -21,12 +21,12 @@ import ( "testing" providerv1beta1 "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" - "github.com/cs3org/reva/v2/pkg/utils/resourceid" + "github.com/cs3org/reva/v2/pkg/storagespace" ) func TestWrapResourceID(t *testing.T) { expected := "storageid" + "!" + "opaqueid" - wrapped := resourceid.OwnCloudResourceIDWrap(&providerv1beta1.ResourceId{StorageId: "storageid", OpaqueId: "opaqueid"}) + wrapped := storagespace.FormatResourceID(providerv1beta1.ResourceId{StorageId: "storageid", OpaqueId: "opaqueid"}) if wrapped != expected { t.Errorf("wrapped id doesn't have the expected format: got %s expected %s", wrapped, expected) diff --git a/internal/http/services/owncloud/ocdav/propfind/propfind.go b/internal/http/services/owncloud/ocdav/propfind/propfind.go index b9206bd9a8..4c82a895e5 100644 --- a/internal/http/services/owncloud/ocdav/propfind/propfind.go +++ b/internal/http/services/owncloud/ocdav/propfind/propfind.go @@ -46,9 +46,9 @@ import ( ctxpkg "github.com/cs3org/reva/v2/pkg/ctx" "github.com/cs3org/reva/v2/pkg/publicshare" "github.com/cs3org/reva/v2/pkg/rhttp/router" + "github.com/cs3org/reva/v2/pkg/storagespace" rtrace "github.com/cs3org/reva/v2/pkg/trace" "github.com/cs3org/reva/v2/pkg/utils" - "github.com/cs3org/reva/v2/pkg/utils/resourceid" "github.com/rs/zerolog" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/codes" @@ -736,7 +736,7 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p // return all known properties if md.Id != nil { - id := resourceid.OwnCloudResourceIDWrap(md.Id) + id := storagespace.FormatResourceID(*md.Id) propstatOK.Prop = append(propstatOK.Prop, prop.Escaped("oc:id", id), prop.Escaped("oc:fileid", id), @@ -840,13 +840,13 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p // I tested the desktop client and phoenix to annotate which properties are requestted, see below cases case "fileid": // phoenix only if md.Id != nil { - propstatOK.Prop = append(propstatOK.Prop, prop.Escaped("oc:fileid", resourceid.OwnCloudResourceIDWrap(md.Id))) + propstatOK.Prop = append(propstatOK.Prop, prop.Escaped("oc:fileid", storagespace.FormatResourceID(*md.Id))) } else { propstatNotFound.Prop = append(propstatNotFound.Prop, prop.NotFound("oc:fileid")) } case "id": // desktop client only if md.Id != nil { - propstatOK.Prop = append(propstatOK.Prop, prop.Escaped("oc:id", resourceid.OwnCloudResourceIDWrap(md.Id))) + propstatOK.Prop = append(propstatOK.Prop, prop.Escaped("oc:id", storagespace.FormatResourceID(*md.Id))) } else { propstatNotFound.Prop = append(propstatNotFound.Prop, prop.NotFound("oc:id")) } diff --git a/internal/http/services/owncloud/ocdav/put.go b/internal/http/services/owncloud/ocdav/put.go index 2bd34dbd67..d62229523d 100644 --- a/internal/http/services/owncloud/ocdav/put.go +++ b/internal/http/services/owncloud/ocdav/put.go @@ -37,9 +37,9 @@ import ( "github.com/cs3org/reva/v2/pkg/errtypes" "github.com/cs3org/reva/v2/pkg/rhttp" "github.com/cs3org/reva/v2/pkg/storage/utils/chunking" + "github.com/cs3org/reva/v2/pkg/storagespace" rtrace "github.com/cs3org/reva/v2/pkg/trace" "github.com/cs3org/reva/v2/pkg/utils" - "github.com/cs3org/reva/v2/pkg/utils/resourceid" "github.com/rs/zerolog" ) @@ -327,7 +327,7 @@ func (s *svc) handlePut(ctx context.Context, w http.ResponseWriter, r *http.Requ w.Header().Add(net.HeaderContentType, newInfo.MimeType) w.Header().Set(net.HeaderETag, newInfo.Etag) - w.Header().Set(net.HeaderOCFileID, resourceid.OwnCloudResourceIDWrap(newInfo.Id)) + w.Header().Set(net.HeaderOCFileID, storagespace.FormatResourceID(*newInfo.Id)) w.Header().Set(net.HeaderOCETag, newInfo.Etag) t := utils.TSToTime(newInfo.Mtime).UTC() lastModifiedString := t.Format(time.RFC1123Z) diff --git a/internal/http/services/owncloud/ocdav/spaces.go b/internal/http/services/owncloud/ocdav/spaces.go index 384ceba3e1..06694d82c0 100644 --- a/internal/http/services/owncloud/ocdav/spaces.go +++ b/internal/http/services/owncloud/ocdav/spaces.go @@ -29,6 +29,7 @@ import ( "github.com/cs3org/reva/v2/pkg/appctx" "github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool" "github.com/cs3org/reva/v2/pkg/rhttp/router" + "github.com/cs3org/reva/v2/pkg/storagespace" "github.com/cs3org/reva/v2/pkg/utils" ) @@ -157,7 +158,7 @@ func (h *SpacesHandler) handleSpacesTrashbin(w http.ResponseWriter, r *http.Requ return } - ref, err := utils.ParseStorageSpaceReference(spaceID) + ref, err := storagespace.ParseReference(spaceID) if err != nil { w.WriteHeader(http.StatusBadRequest) return diff --git a/internal/http/services/owncloud/ocdav/trashbin.go b/internal/http/services/owncloud/ocdav/trashbin.go index 158acfe6ec..6042ebbdb0 100644 --- a/internal/http/services/owncloud/ocdav/trashbin.go +++ b/internal/http/services/owncloud/ocdav/trashbin.go @@ -34,8 +34,8 @@ import ( "github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/prop" "github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/propfind" "github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/spacelookup" + "github.com/cs3org/reva/v2/pkg/storagespace" rtrace "github.com/cs3org/reva/v2/pkg/trace" - "github.com/cs3org/reva/v2/pkg/utils/resourceid" rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" @@ -571,7 +571,7 @@ func (h *TrashbinHandler) restore(w http.ResponseWriter, r *http.Request, s *svc info := dstStatRes.Info w.Header().Set(net.HeaderContentType, info.MimeType) w.Header().Set(net.HeaderETag, info.Etag) - w.Header().Set(net.HeaderOCFileID, resourceid.OwnCloudResourceIDWrap(info.Id)) + w.Header().Set(net.HeaderOCFileID, storagespace.FormatResourceID(*info.Id)) w.Header().Set(net.HeaderOCETag, info.Etag) w.WriteHeader(successCode) diff --git a/internal/http/services/owncloud/ocdav/tus.go b/internal/http/services/owncloud/ocdav/tus.go index 1506f82f25..de8affc826 100644 --- a/internal/http/services/owncloud/ocdav/tus.go +++ b/internal/http/services/owncloud/ocdav/tus.go @@ -37,9 +37,9 @@ import ( "github.com/cs3org/reva/v2/internal/http/services/owncloud/ocs/conversions" "github.com/cs3org/reva/v2/pkg/appctx" "github.com/cs3org/reva/v2/pkg/rhttp" + "github.com/cs3org/reva/v2/pkg/storagespace" rtrace "github.com/cs3org/reva/v2/pkg/trace" "github.com/cs3org/reva/v2/pkg/utils" - "github.com/cs3org/reva/v2/pkg/utils/resourceid" "github.com/rs/zerolog" tusd "github.com/tus/tusd/pkg/handler" ) @@ -326,7 +326,7 @@ func (s *svc) handleTusPost(ctx context.Context, w http.ResponseWriter, r *http. ) w.Header().Set(net.HeaderContentType, info.MimeType) - w.Header().Set(net.HeaderOCFileID, resourceid.OwnCloudResourceIDWrap(info.Id)) + w.Header().Set(net.HeaderOCFileID, storagespace.FormatResourceID(*info.Id)) w.Header().Set(net.HeaderOCETag, info.Etag) w.Header().Set(net.HeaderETag, info.Etag) w.Header().Set(net.HeaderOCPermissions, permissions) diff --git a/internal/http/services/owncloud/ocdav/versions.go b/internal/http/services/owncloud/ocdav/versions.go index 9ebbab4c5a..90d2a751f9 100644 --- a/internal/http/services/owncloud/ocdav/versions.go +++ b/internal/http/services/owncloud/ocdav/versions.go @@ -26,8 +26,8 @@ import ( "github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/errors" "github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/net" "github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/propfind" + "github.com/cs3org/reva/v2/pkg/storagespace" rtrace "github.com/cs3org/reva/v2/pkg/trace" - "github.com/cs3org/reva/v2/pkg/utils/resourceid" rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" @@ -57,7 +57,7 @@ func (h *VersionsHandler) Handler(s *svc, rid *provider.ResourceId) http.Handler } // baseURI is encoded as part of the response payload in href field - baseURI := path.Join(ctx.Value(net.CtxKeyBaseURI).(string), resourceid.OwnCloudResourceIDWrap(rid)) + baseURI := path.Join(ctx.Value(net.CtxKeyBaseURI).(string), storagespace.FormatResourceID(*rid)) ctx = context.WithValue(ctx, net.CtxKeyBaseURI, baseURI) r = r.WithContext(ctx) diff --git a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go index bbfd776133..aee0119793 100644 --- a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go +++ b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go @@ -56,8 +56,8 @@ import ( cachereg "github.com/cs3org/reva/v2/pkg/share/cache/registry" warmupreg "github.com/cs3org/reva/v2/pkg/share/cache/warmup/registry" "github.com/cs3org/reva/v2/pkg/storage/utils/templates" + "github.com/cs3org/reva/v2/pkg/storagespace" "github.com/cs3org/reva/v2/pkg/utils" - "github.com/cs3org/reva/v2/pkg/utils/resourceid" "github.com/pkg/errors" ) @@ -157,7 +157,7 @@ func (h *Handler) startCacheWarmup(c cache.Warmup) { return } for _, r := range infos { - key := resourceid.OwnCloudResourceIDWrap(r.Id) + key := storagespace.FormatResourceID(*r.Id) _ = h.resourceInfoCache.SetWithExpire(key, r, h.resourceInfoCacheTTL) } } @@ -172,7 +172,7 @@ func (h *Handler) extractReference(r *http.Request) (provider.Reference, error) } } else if spaceRef := r.FormValue("space_ref"); spaceRef != "" { var err error - ref, err = utils.ParseStorageSpaceReference(spaceRef) + ref, err = storagespace.ParseReference(spaceRef) if err != nil { return provider.Reference{}, err } @@ -1030,7 +1030,7 @@ func (h *Handler) addFileInfo(ctx context.Context, s *conversions.ShareData, inf s.MimeType = parsedMt // TODO STime: &types.Timestamp{Seconds: info.Mtime.Seconds, Nanos: info.Mtime.Nanos}, // TODO Storage: int - s.ItemSource = resourceid.OwnCloudResourceIDWrap(info.Id) + s.ItemSource = storagespace.FormatResourceID(*info.Id) s.FileSource = s.ItemSource switch { case h.sharePrefix == "/": @@ -1233,7 +1233,7 @@ func (h *Handler) getResourceInfoByReference(ctx context.Context, client gateway key = ref.Path } else { var err error - key, err = utils.FormatStorageSpaceReference(ref) + key, err = storagespace.FormatReference(ref) if err != nil { return nil, nil, err } @@ -1242,7 +1242,7 @@ func (h *Handler) getResourceInfoByReference(ctx context.Context, client gateway } func (h *Handler) getResourceInfoByID(ctx context.Context, client gateway.GatewayAPIClient, id *provider.ResourceId) (*provider.ResourceInfo, *rpc.Status, error) { - return h.getResourceInfo(ctx, client, resourceid.OwnCloudResourceIDWrap(id), &provider.Reference{ResourceId: id, Path: "."}) + return h.getResourceInfo(ctx, client, storagespace.FormatResourceID(*id), &provider.Reference{ResourceId: id, Path: "."}) } // getResourceInfo retrieves the resource info to a target. diff --git a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/spaces.go b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/spaces.go index d91a9e1b4b..8d3184f5e3 100644 --- a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/spaces.go +++ b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/spaces.go @@ -37,7 +37,7 @@ import ( "github.com/cs3org/reva/v2/pkg/rgrpc/status" "github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool" sdk "github.com/cs3org/reva/v2/pkg/sdk/common" - "github.com/cs3org/reva/v2/pkg/utils" + "github.com/cs3org/reva/v2/pkg/storagespace" "github.com/pkg/errors" ) @@ -132,7 +132,7 @@ func (h *Handler) removeSpaceMember(w http.ResponseWriter, r *http.Request, spac return } - ref, err := utils.ParseStorageSpaceReference(spaceID) + ref, err := storagespace.ParseReference(spaceID) if err != nil { response.WriteOCSError(w, r, response.MetaBadRequest.StatusCode, "could not parse space id", err) return diff --git a/pkg/rhttp/datatx/manager/spaces/spaces.go b/pkg/rhttp/datatx/manager/spaces/spaces.go index 1ff0788b02..c2373f9a6e 100644 --- a/pkg/rhttp/datatx/manager/spaces/spaces.go +++ b/pkg/rhttp/datatx/manager/spaces/spaces.go @@ -31,7 +31,7 @@ import ( "github.com/cs3org/reva/v2/pkg/rhttp/datatx/utils/download" "github.com/cs3org/reva/v2/pkg/rhttp/router" "github.com/cs3org/reva/v2/pkg/storage" - "github.com/cs3org/reva/v2/pkg/utils" + "github.com/cs3org/reva/v2/pkg/storagespace" "github.com/mitchellh/mapstructure" "github.com/pkg/errors" ) @@ -81,7 +81,7 @@ func (m *manager) Handler(fs storage.FS) (http.Handler, error) { fn := path.Clean(strings.TrimLeft(r.URL.Path, "/")) defer r.Body.Close() - storageid, opaqeid, _ := utils.SplitStorageSpaceID(spaceID) + storageid, opaqeid, _ := storagespace.SplitID(spaceID) ref := &provider.Reference{ ResourceId: &provider.ResourceId{StorageId: storageid, OpaqueId: opaqeid}, Path: fn, diff --git a/pkg/rhttp/datatx/utils/download/download.go b/pkg/rhttp/datatx/utils/download/download.go index bb8bffde7a..356545bab9 100644 --- a/pkg/rhttp/datatx/utils/download/download.go +++ b/pkg/rhttp/datatx/utils/download/download.go @@ -31,6 +31,7 @@ import ( "github.com/cs3org/reva/v2/pkg/appctx" "github.com/cs3org/reva/v2/pkg/errtypes" "github.com/cs3org/reva/v2/pkg/storage" + "github.com/cs3org/reva/v2/pkg/storagespace" "github.com/cs3org/reva/v2/pkg/utils" "github.com/rs/zerolog" ) @@ -54,7 +55,7 @@ func GetOrHeadFile(w http.ResponseWriter, r *http.Request, fs storage.FS, spaceI ref = &provider.Reference{Path: path.Join("/", fn)} } else { // build a storage space reference - storageid, opaqeid, _ := utils.SplitStorageSpaceID(spaceID) + storageid, opaqeid, _ := storagespace.SplitID(spaceID) ref = &provider.Reference{ ResourceId: &provider.ResourceId{StorageId: storageid, OpaqueId: opaqeid}, // ensure the relative path starts with '.' diff --git a/pkg/storage/fs/owncloudsql/spaces.go b/pkg/storage/fs/owncloudsql/spaces.go index 5b264a780c..c19e779d92 100644 --- a/pkg/storage/fs/owncloudsql/spaces.go +++ b/pkg/storage/fs/owncloudsql/spaces.go @@ -30,7 +30,7 @@ import ( ctxpkg "github.com/cs3org/reva/v2/pkg/ctx" "github.com/cs3org/reva/v2/pkg/errtypes" "github.com/cs3org/reva/v2/pkg/storage/fs/owncloudsql/filecache" - "github.com/cs3org/reva/v2/pkg/utils" + "github.com/cs3org/reva/v2/pkg/storagespace" ) // ListStorageSpaces lists storage spaces according to the provided filters @@ -47,7 +47,7 @@ func (fs *owncloudsqlfs) ListStorageSpaces(ctx context.Context, filter []*provid t := filter[i].GetSpaceType() filteringUnsupportedSpaceTypes = (t != "personal" && !strings.HasPrefix(t, "+")) case provider.ListStorageSpacesRequest_Filter_TYPE_ID: - spaceID, _, _ = utils.SplitStorageSpaceID(filter[i].GetId().OpaqueId) + spaceID, _, _ = storagespace.SplitID(filter[i].GetId().OpaqueId) } } if filteringUnsupportedSpaceTypes { diff --git a/pkg/storage/utils/decomposedfs/spaces.go b/pkg/storage/utils/decomposedfs/spaces.go index cdfec53783..d50f47cd2f 100644 --- a/pkg/storage/utils/decomposedfs/spaces.go +++ b/pkg/storage/utils/decomposedfs/spaces.go @@ -43,8 +43,8 @@ import ( "github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/node" "github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/xattrs" "github.com/cs3org/reva/v2/pkg/storage/utils/templates" + "github.com/cs3org/reva/v2/pkg/storagespace" "github.com/cs3org/reva/v2/pkg/utils" - "github.com/cs3org/reva/v2/pkg/utils/resourceid" "github.com/google/uuid" "github.com/pkg/errors" ) @@ -265,7 +265,7 @@ func (fs *Decomposedfs) ListStorageSpaces(ctx context.Context, filter []*provide spaceTypes = append(spaceTypes, filter[i].GetSpaceType()) } case provider.ListStorageSpacesRequest_Filter_TYPE_ID: - spaceID, nodeID, _ = utils.SplitStorageSpaceID(filter[i].GetId().OpaqueId) + spaceID, nodeID, _ = storagespace.SplitID(filter[i].GetId().OpaqueId) if strings.Contains(nodeID, "/") { return []*provider.StorageSpace{}, nil } @@ -402,7 +402,7 @@ func (fs *Decomposedfs) UpdateStorageSpace(ctx context.Context, req *provider.Up } space := req.StorageSpace - spaceID, _, _ := utils.SplitStorageSpaceID(space.Id.OpaqueId) + spaceID, _, _ := storagespace.SplitID(space.Id.OpaqueId) node, err := node.ReadNode(ctx, fs.lu, spaceID, spaceID) if err != nil { @@ -441,8 +441,8 @@ func (fs *Decomposedfs) UpdateStorageSpace(ctx context.Context, req *provider.Up metadata[xattrs.SpaceAliasAttr] = alias } if image := utils.ReadPlainFromOpaque(space.Opaque, "image"); image != "" { - imageID := resourceid.OwnCloudResourceIDUnwrap(image) - if imageID == nil { + imageID, err := storagespace.ParseID(image) + if err != nil { return &provider.UpdateStorageSpaceResponse{ Status: &v1beta11.Status{Code: v1beta11.Code_CODE_NOT_FOUND, Message: "decomposedFS: space image resource not found"}, }, nil @@ -450,8 +450,8 @@ func (fs *Decomposedfs) UpdateStorageSpace(ctx context.Context, req *provider.Up metadata[xattrs.SpaceImageAttr] = imageID.OpaqueId } if readme := utils.ReadPlainFromOpaque(space.Opaque, "readme"); readme != "" { - readmeID := resourceid.OwnCloudResourceIDUnwrap(readme) - if readmeID == nil { + readmeID, err := storagespace.ParseID(readme) + if err != nil { return &provider.UpdateStorageSpaceResponse{ Status: &v1beta11.Status{Code: v1beta11.Code_CODE_NOT_FOUND, Message: "decomposedFS: space readme resource not found"}, }, nil @@ -708,8 +708,8 @@ func (fs *Decomposedfs) storageSpaceFromNode(ctx context.Context, n *node.Node, } spaceImage, ok := spaceAttributes[xattrs.SpaceImageAttr] if ok { - space.Opaque = utils.AppendPlainToOpaque(space.Opaque, "image", resourceid.OwnCloudResourceIDWrap( - &provider.ResourceId{StorageId: space.Root.StorageId, OpaqueId: spaceImage}, + space.Opaque = utils.AppendPlainToOpaque(space.Opaque, "image", storagespace.FormatResourceID( + provider.ResourceId{StorageId: space.Root.StorageId, OpaqueId: spaceImage}, )) } spaceDescription, ok := spaceAttributes[xattrs.SpaceDescriptionAttr] @@ -718,8 +718,8 @@ func (fs *Decomposedfs) storageSpaceFromNode(ctx context.Context, n *node.Node, } spaceReadme, ok := spaceAttributes[xattrs.SpaceReadmeAttr] if ok { - space.Opaque = utils.AppendPlainToOpaque(space.Opaque, "readme", resourceid.OwnCloudResourceIDWrap( - &provider.ResourceId{StorageId: space.Root.StorageId, OpaqueId: spaceReadme}, + space.Opaque = utils.AppendPlainToOpaque(space.Opaque, "readme", storagespace.FormatResourceID( + provider.ResourceId{StorageId: space.Root.StorageId, OpaqueId: spaceReadme}, )) } spaceAlias, ok := spaceAttributes[xattrs.SpaceAliasAttr] diff --git a/pkg/storagespace/storagespace.go b/pkg/storagespace/storagespace.go new file mode 100644 index 0000000000..24454b3bed --- /dev/null +++ b/pkg/storagespace/storagespace.go @@ -0,0 +1,151 @@ +// Copyright 2018-2021 CERN +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +package storagespace + +import ( + "path" + "strings" + + provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" + "github.com/cs3org/reva/v2/pkg/utils" + "github.com/pkg/errors" +) + +const ( + _idDelimiter string = "!" + _storageIDDelimiter string = "$" +) + +var ( + // ErrInvalidSpaceReference signals that the space reference is invalid. + ErrInvalidSpaceReference = errors.New("invalid storage space reference") + // ErrInvalidSpaceID signals that the space ID is invalid. + ErrInvalidSpaceID = errors.New("invalid storage space id") +) + +// SplitID splits a storage space ID into a provider ID and a node ID. +// The accepted formats results of the storage space ID and respective results +// are: +// $! -> $, +// $ -> $, +// -> , +func SplitID(ssid string) (storageid, nodeid string, err error) { + if ssid == "" { + return "", "", errors.Wrap(ErrInvalidSpaceID, "can't split empty storage space ID") + } + parts := strings.SplitN(ssid, _idDelimiter, 2) + if len(parts) == 1 || parts[1] == "" { + _, sid := SplitStorageID(parts[0]) + return parts[0], sid, nil + } + return parts[0], parts[1], nil +} + +// SplitStorageID splits a storage ID into the provider ID and the spaceID. +// The accepted formats are: +// $ -> , +// -> "", +func SplitStorageID(sid string) (providerID, spaceID string) { + parts := strings.SplitN(sid, _storageIDDelimiter, 2) + if len(parts) == 2 { + return parts[0], parts[1] + } + return "", parts[0] +} + +// FormatResourceID converts a ResourceId into the string format. +// The result format will look like: +// ! +func FormatResourceID(sid provider.ResourceId) string { + return strings.Join([]string{sid.StorageId, sid.OpaqueId}, _idDelimiter) +} + +// FormatStorageID converts the provider ID and space ID into the string format. +// The result format will look like: +// $ or +// in case the provider ID is empty. +func FormatStorageID(providerID, spaceID string) string { + if providerID == "" { + return spaceID + } + return strings.Join([]string{providerID, spaceID}, _storageIDDelimiter) +} + +// ParseID parses a storage space ID and returns a storageprovider ResourceId. +// The accepted formats are: +// $! -> $, +// $ -> $, +// -> , +func ParseID(ssid string) (provider.ResourceId, error) { + sid, nid, err := SplitID(ssid) + return provider.ResourceId{ + StorageId: sid, + OpaqueId: nid, + }, err +} + +// ParseReference parses a string into a spaces reference. +// The expected format is `$!/`. +func ParseReference(sRef string) (provider.Reference, error) { + parts := strings.SplitN(sRef, "/", 2) + + rid, err := ParseID(parts[0]) + if err != nil { + return provider.Reference{}, err + } + + var path string + if len(parts) == 2 { + path = parts[1] + } + + return provider.Reference{ + ResourceId: &rid, + Path: utils.MakeRelativePath(path), + }, nil +} + +// FormatReference will format a storage space reference into a string representation. +// If ref or ref.ResourceId are nil an error will be returned. +// The function doesn't check if all values are set. +// The resulting format can be: +// +// "storage_id!opaque_id" +// "storage_id!opaque_id/path" +// "storage_id/path" +// "storage_id" +func FormatReference(ref *provider.Reference) (string, error) { + if ref == nil || ref.ResourceId == nil || ref.ResourceId.StorageId == "" { + return "", ErrInvalidSpaceReference + } + var ssid string + if ref.ResourceId.OpaqueId == "" { + + ssid = ref.ResourceId.StorageId + } else { + var sb strings.Builder + // ssid == storage_id!opaque_id + sb.Grow(len(ref.ResourceId.StorageId) + len(ref.ResourceId.OpaqueId) + 1) + sb.WriteString(ref.ResourceId.StorageId) + sb.WriteString(_idDelimiter) + sb.WriteString(ref.ResourceId.OpaqueId) + ssid = sb.String() + } + return path.Join(ssid, ref.Path), nil +} diff --git a/pkg/storagespace/storagespace_test.go b/pkg/storagespace/storagespace_test.go new file mode 100644 index 0000000000..d07d8737be --- /dev/null +++ b/pkg/storagespace/storagespace_test.go @@ -0,0 +1,267 @@ +// Copyright 2018-2021 CERN +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +package storagespace + +import ( + "errors" + "testing" + + provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" + "github.com/cs3org/reva/v2/pkg/utils" +) + +func TestSplitStorageID(t *testing.T) { + tests := []struct { + input string + expected []string + }{ + { + "providerid" + _storageIDDelimiter + "storageid", + []string{"storageid", "providerid"}, + }, + { + "", + nil, + }, + { + "storageid", + []string{"storageid", ""}, + }, + } + + for _, tt := range tests { + storageID, spaceID := SplitStorageID(tt.input) + switch { + case tt.expected == nil: + if spaceID != "" || storageID != "" { + t.Errorf("Expected unwrap to return nil, got '%s' '%s'", spaceID, storageID) + } + case len(tt.expected) != 2: + t.Error("testcase won't work with len(expected) != 2. Avoiding panic") + case spaceID != tt.expected[0]: + t.Errorf("StorageID doesn't match, expected '%s' got '%s'", tt.expected[0], spaceID) + case storageID != tt.expected[1]: + t.Errorf("ProviderID doesn't match, expected '%s' got '%s'", tt.expected[1], storageID) + } + } + +} + +func TestParseID(t *testing.T) { + tests := []struct { + input string + expected provider.ResourceId + expectedErr error + }{ + { + "spaceid" + _idDelimiter + "opaqueid", + provider.ResourceId{StorageId: "spaceid", OpaqueId: "opaqueid"}, + nil, + }, + { + "providerid" + _storageIDDelimiter + "spaceid" + _idDelimiter + "opaqueid", + provider.ResourceId{StorageId: "providerid$spaceid", OpaqueId: "opaqueid"}, + nil, + }, + { + "", + provider.ResourceId{}, + ErrInvalidSpaceID, + }, + { + "spaceid", + provider.ResourceId{StorageId: "spaceid", OpaqueId: "spaceid"}, + nil, + }, + } + + for _, tt := range tests { + rid, err := ParseID(tt.input) + switch { + case tt.expectedErr != nil: + if !errors.Is(err, tt.expectedErr) { + t.Errorf("Expected ParseID to return error %s, got %s", tt.expectedErr, err) + } + case rid.StorageId != tt.expected.StorageId: + t.Errorf("StorageIDs don't match. Expected %v, got %v", tt.expected, rid) + case rid.OpaqueId != tt.expected.OpaqueId: + t.Errorf("StorageIDs don't match. Expected %v, got %v", tt.expected, rid) + } + } + +} + +func TestFormatResourceID(t *testing.T) { + expected := "storageid" + _idDelimiter + "opaqueid" + wrapped := FormatResourceID(provider.ResourceId{StorageId: "storageid", OpaqueId: "opaqueid"}) + + if wrapped != expected { + t.Errorf("wrapped id doesn't have the expected format: got %s expected %s", wrapped, expected) + } +} + +func TestFormatStorageID(t *testing.T) { + expected := "providerid" + _storageIDDelimiter + "spaceid" + wrapped := FormatStorageID("providerid", "spaceid") + + if wrapped != expected { + t.Errorf("wrapped id doesn't have the expected format: got %s expected %s", wrapped, expected) + } +} + +func TestParseStorageSpaceReference(t *testing.T) { + tests := []struct { + sRef string + storageID string + nodeID string + relPath string + }{ + { + "1234!abcd/f1/f2", + "1234", + "abcd", + "./f1/f2", + }, + { + "1234!abcd", + "1234", + "abcd", + ".", + }, + { + "01234$56789!abcd", + "01234$56789", + "abcd", + ".", + }, + } + for _, tt := range tests { + ref, _ := ParseReference(tt.sRef) + + if ref.ResourceId.StorageId != tt.storageID { + t.Errorf("Expected storageId %s got %s", tt.storageID, ref.ResourceId.StorageId) + } + if ref.ResourceId.OpaqueId != tt.nodeID { + t.Errorf("Expected OpaqueId %s got %s", tt.nodeID, ref.ResourceId.OpaqueId) + } + if ref.Path != tt.relPath { + t.Errorf("Expected path %s got %s", tt.relPath, ref.Path) + } + } +} + +func TestFormatStorageSpaceReference(t *testing.T) { + tests := []struct { + ref *provider.Reference + expected string + expectedErr error + }{ + { + ref: &provider.Reference{}, + expected: "", + expectedErr: ErrInvalidSpaceReference, + }, + { + ref: &provider.Reference{ResourceId: &provider.ResourceId{}}, + expected: "!", + expectedErr: ErrInvalidSpaceReference, + }, + { + ref: &provider.Reference{ResourceId: &provider.ResourceId{OpaqueId: "opaqueid"}, Path: "path"}, + expectedErr: ErrInvalidSpaceReference, + }, + { + ref: &provider.Reference{ResourceId: &provider.ResourceId{StorageId: "storageid"}, Path: "path"}, + expected: "storageid/path", + }, + { + ref: &provider.Reference{ResourceId: &provider.ResourceId{StorageId: "storageid", OpaqueId: "opaqueid"}, Path: "path"}, + expected: "storageid!opaqueid/path", + }, + { + ref: &provider.Reference{ResourceId: &provider.ResourceId{StorageId: "storageid", OpaqueId: "opaqueid"}, Path: "."}, + expected: "storageid!opaqueid", + }, + { + ref: &provider.Reference{ResourceId: &provider.ResourceId{StorageId: "storageid"}, Path: "."}, + expected: "storageid", + }, + { + ref: &provider.Reference{ResourceId: &provider.ResourceId{StorageId: "storageid"}}, + expected: "storageid", + }, + } + + for _, tt := range tests { + result, err := FormatReference(tt.ref) + if err != nil && !errors.Is(err, tt.expectedErr) { + t.Errorf("FormateStorageSpaceRefence returned unexpected error: %v", err) + } + if err == nil && result != tt.expected { + t.Errorf("Reference %v got formatted to %s, expected %s", tt.ref, result, tt.expected) + } + } +} + +func TestFormatAndParseReference(t *testing.T) { + tests := []struct { + orig *provider.Reference + expected *provider.Reference + }{ + { + orig: &provider.Reference{ResourceId: &provider.ResourceId{StorageId: "storageid"}, Path: "./path"}, + expected: &provider.Reference{ResourceId: &provider.ResourceId{StorageId: "storageid", OpaqueId: "storageid"}, Path: "./path"}, + }, + { + orig: &provider.Reference{ResourceId: &provider.ResourceId{StorageId: "storageid$spaceid"}, Path: "./path"}, + expected: &provider.Reference{ResourceId: &provider.ResourceId{StorageId: "storageid$spaceid", OpaqueId: "spaceid"}, Path: "./path"}, + }, + { + orig: &provider.Reference{ResourceId: &provider.ResourceId{StorageId: "storageid", OpaqueId: "opaqueid"}, Path: "./path"}, + expected: &provider.Reference{ResourceId: &provider.ResourceId{StorageId: "storageid", OpaqueId: "opaqueid"}, Path: "./path"}, + }, + { + orig: &provider.Reference{ResourceId: &provider.ResourceId{StorageId: "storageid$spaceid", OpaqueId: "opaqueid"}, Path: "./path"}, + expected: &provider.Reference{ResourceId: &provider.ResourceId{StorageId: "storageid$spaceid", OpaqueId: "opaqueid"}, Path: "./path"}, + }, + { + orig: &provider.Reference{ResourceId: &provider.ResourceId{StorageId: "storageid", OpaqueId: "opaqueid"}, Path: "."}, + expected: &provider.Reference{ResourceId: &provider.ResourceId{StorageId: "storageid", OpaqueId: "opaqueid"}, Path: "."}, + }, + { + orig: &provider.Reference{ResourceId: &provider.ResourceId{StorageId: "storageid"}, Path: "."}, + expected: &provider.Reference{ResourceId: &provider.ResourceId{StorageId: "storageid", OpaqueId: "storageid"}, Path: "."}, + }, + { + orig: &provider.Reference{ResourceId: &provider.ResourceId{StorageId: "storageid"}}, + expected: &provider.Reference{ResourceId: &provider.ResourceId{StorageId: "storageid", OpaqueId: "storageid"}, Path: "."}, + }, + } + + for _, tt := range tests { + formatted, _ := FormatReference(tt.orig) + parsed, err := ParseReference(formatted) + if err != nil { + t.Errorf("failed to parse space reference: %s error: %s", formatted, err) + } + if !(utils.ResourceIDEqual(parsed.ResourceId, tt.expected.ResourceId) && parsed.Path == tt.expected.Path) { + t.Errorf("Formatted then parsed references don't match the original got: %v expected %v", parsed, tt.expected) + } + } +} diff --git a/pkg/utils/resourceid/owncloud.go b/pkg/utils/resourceid/owncloud.go deleted file mode 100644 index d566f1c8b3..0000000000 --- a/pkg/utils/resourceid/owncloud.go +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright 2018-2021 CERN -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// In applying this license, CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. - -package resourceid - -import ( - "errors" - "strings" - "unicode/utf8" - - provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" -) - -const ( - _idDelimiter string = "!" - _providerDelimiter string = "$" -) - -// StorageIDUnwrap unwraps the 'encoded' into the storageID and the storageProviderID -func StorageIDUnwrap(s string) (sid string, spid string) { - spid, sid, err := unwrap(s, _providerDelimiter) - if err != nil { - // assume it's only a storageid - return s, "" - } - return sid, spid -} - -// OwnCloudResourceIDUnwrap returns the wrapped resource id -// by OwnCloudResourceIDWrap and returns nil if not possible -func OwnCloudResourceIDUnwrap(rid string) *provider.ResourceId { - sid, oid, err := unwrap(rid, _idDelimiter) - if err != nil { - return nil - } - return &provider.ResourceId{ - StorageId: sid, - OpaqueId: oid, - } -} - -func unwrap(rid string, delimiter string) (string, string, error) { - parts := strings.SplitN(rid, delimiter, 2) - if len(parts) != 2 { - return "", "", errors.New("could not find two parts with given delimiter") - } - - if !utf8.ValidString(parts[0]) || !utf8.ValidString(parts[1]) { - return "", "", errors.New("invalid utf8 string found") - } - - return parts[0], parts[1], nil -} - -// OwnCloudResourceIDWrap wraps a resource id into a xml safe string -// which can then be passed to the outside world -func OwnCloudResourceIDWrap(r *provider.ResourceId) string { - return wrap(r.StorageId, r.OpaqueId, _idDelimiter) -} - -// StorageIDWrap wraps a storageid and storageproviderid into a xml safe string -// which can then be passed to the outside world -func StorageIDWrap(sid string, spid string) string { - return wrap(spid, sid, _providerDelimiter) -} - -// returns second argument in case the first is empty (without adding the delimiter) -// the delimiter should be Url safe (we use a reserved character) -func wrap(first string, second string, delimiter string) string { - if first == "" { - return second - } - return first + delimiter + second -} diff --git a/pkg/utils/resourceid/owncloud_test.go b/pkg/utils/resourceid/owncloud_test.go deleted file mode 100644 index 775ccd314c..0000000000 --- a/pkg/utils/resourceid/owncloud_test.go +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright 2021 CERN -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// -// In applying this license, CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. -package resourceid - -import ( - "testing" - - providerv1beta1 "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" -) - -func BenchmarkWrap(b *testing.B) { - for i := 0; i < b.N; i++ { - _ = wrap("storageid", "opaqueid", "!") - } -} - -func TestWrap(t *testing.T) { - expected := "storageid!opaqueid" - wrapped := wrap("storageid", "opaqueid", "!") - - if wrapped != expected { - t.Errorf("wrapped id doesn't have the expected format: got %s expected %s", wrapped, expected) - } -} - -func TestWrapResourceID(t *testing.T) { - expected := "storageid" + _idDelimiter + "opaqueid" - wrapped := OwnCloudResourceIDWrap(&providerv1beta1.ResourceId{StorageId: "storageid", OpaqueId: "opaqueid"}) - - if wrapped != expected { - t.Errorf("wrapped id doesn't have the expected format: got %s expected %s", wrapped, expected) - } -} - -func TestWrapStorageID(t *testing.T) { - expected := "providerid" + _providerDelimiter + "storageid" - wrapped := StorageIDWrap("storageid", "providerid") - - if wrapped != expected { - t.Errorf("wrapped id doesn't have the expected format: got %s expected %s", wrapped, expected) - } -} - -func TestUnwrap(t *testing.T) { - expected := []string{"storageid", "opaqueid"} - sid, oid, err := unwrap("storageid!opaqueid", "!") - if err != nil { - t.Errorf("unwrap returned an error: %v", err) - } - - if sid != expected[0] || oid != expected[1] { - t.Errorf("wrapped id doesn't have the expected format: got (%s, %s) expected %s", sid, oid, expected) - } -} - -func BenchmarkUnwrap(b *testing.B) { - delimiter := "!" - for i := 0; i < b.N; i++ { - _, _, _ = unwrap("storageid"+delimiter+"opaqueid", delimiter) - } -} - -func TestUnwrapResourceID(t *testing.T) { - tests := []struct { - input string - expected *providerv1beta1.ResourceId - }{ - { - "storageid" + _idDelimiter + "opaqueid", - &providerv1beta1.ResourceId{StorageId: "storageid", OpaqueId: "opaqueid"}, - }, - { - "providerid" + _providerDelimiter + "storageid" + _idDelimiter + "opaqueid", - &providerv1beta1.ResourceId{StorageId: "providerid$storageid", OpaqueId: "opaqueid"}, - }, - { - "", - nil, - }, - { - "c", - nil, - }, - } - - for _, tt := range tests { - rid := OwnCloudResourceIDUnwrap(tt.input) - switch { - case tt.expected == nil: - if rid != nil { - t.Errorf("Expected unwrap to return nil, got %v", rid) - } - case rid == nil: - t.Errorf("ResourceID should not be nil. Expected %v", tt.expected) - case rid.StorageId != tt.expected.StorageId: - t.Errorf("StorageIDs don't match. Expected %v, got %v", tt.expected, rid) - case rid.OpaqueId != tt.expected.OpaqueId: - t.Errorf("StorageIDs don't match. Expected %v, got %v", tt.expected, rid) - } - } - -} - -func TestUnwrapStorageID(t *testing.T) { - tests := []struct { - input string - expected []string - }{ - { - "providerid" + _providerDelimiter + "storageid", - []string{"storageid", "providerid"}, - }, - { - "", - nil, - }, - { - "storageid", - []string{"storageid", ""}, - }, - } - - for _, tt := range tests { - sid, spid := StorageIDUnwrap(tt.input) - switch { - case tt.expected == nil: - if sid != "" || spid != "" { - t.Errorf("Expected unwrap to return nil, got '%s' '%s'", sid, spid) - } - case len(tt.expected) != 2: - t.Error("testcase won't work with len(expected) != 2. Avoiding panic") - case sid != tt.expected[0]: - t.Errorf("StorageID doesn't match, expected '%s' got '%s'", tt.expected[0], sid) - case spid != tt.expected[1]: - t.Errorf("ProviderID doesn't match, expected '%s' got '%s'", tt.expected[1], spid) - } - } - -} diff --git a/pkg/utils/utils.go b/pkg/utils/utils.go index 1a8266ed99..9b3c7ffb29 100644 --- a/pkg/utils/utils.go +++ b/pkg/utils/utils.go @@ -19,7 +19,6 @@ package utils import ( - "errors" "math/rand" "net" "net/http" @@ -38,15 +37,10 @@ import ( types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" "github.com/cs3org/reva/v2/pkg/registry" "github.com/cs3org/reva/v2/pkg/registry/memory" - "github.com/cs3org/reva/v2/pkg/utils/resourceid" "github.com/golang/protobuf/proto" "google.golang.org/protobuf/encoding/protojson" ) -const ( - spaceIDDelimiter = "!" -) - var ( matchFirstCap = regexp.MustCompile("(.)([A-Z][a-z]+)") matchAllCap = regexp.MustCompile("([a-z0-9])([A-Z])") @@ -63,8 +57,6 @@ var ( // SpaceGrant is used to signal the storageprovider that the grant is on a space SpaceGrant struct{} - - errInvalidSpaceReference = errors.New("invalid storage space reference") ) // Skip evaluates whether a source endpoint contains any of the prefixes. @@ -327,73 +319,6 @@ func UserTypeToString(accountType userpb.UserType) string { return t } -// SplitStorageSpaceID can be used to split `storagespaceid` into `storageid` and `nodeid`. -// If no specific node is appended with a `!` separator the spaceid is used as nodeid, identifying the root of the space. -func SplitStorageSpaceID(ssid string) (storageid, nodeid string, err error) { - if ssid == "" { - return "", "", errors.New("can't split empty StorageSpaceID") - } - parts := strings.SplitN(ssid, spaceIDDelimiter, 2) - if len(parts) == 1 { - p, _ := resourceid.StorageIDUnwrap(parts[0]) - return parts[0], p, nil - } - return parts[0], parts[1], nil -} - -// ParseStorageSpaceReference parses a string into a spaces reference. -// The expected format is `!/`. -func ParseStorageSpaceReference(sRef string) (provider.Reference, error) { - parts := strings.SplitN(sRef, "/", 2) - - storageid, nodeid, err := SplitStorageSpaceID(parts[0]) - if err != nil { - return provider.Reference{}, err - } - - var relPath string - if len(parts) == 2 { - relPath = parts[1] - } - - return provider.Reference{ - ResourceId: &provider.ResourceId{ - StorageId: storageid, - OpaqueId: nodeid, - }, - Path: MakeRelativePath(relPath), - }, nil -} - -// FormatStorageSpaceReference will format a storage space reference into a string representation. -// If ref or ref.ResourceId are nil an error will be returned. -// The function doesn't check if all values are set. -// The resulting format can be: -// -// "storage_id!opaque_id" -// "storage_id!opaque_id/path" -// "storage_id/path" -// "storage_id" -func FormatStorageSpaceReference(ref *provider.Reference) (string, error) { - if ref == nil || ref.ResourceId == nil || ref.ResourceId.StorageId == "" { - return "", errInvalidSpaceReference - } - var ssid string - if ref.ResourceId.OpaqueId == "" { - - ssid = ref.ResourceId.StorageId - } else { - var sb strings.Builder - // ssid == storage_id!opaque_id - sb.Grow(len(ref.ResourceId.StorageId) + len(ref.ResourceId.OpaqueId) + 1) - sb.WriteString(ref.ResourceId.StorageId) - sb.WriteString(spaceIDDelimiter) - sb.WriteString(ref.ResourceId.OpaqueId) - ssid = sb.String() - } - return path.Join(ssid, ref.Path), nil -} - // GetViewMode converts a human-readable string to a view mode for opening a resource in an app. func GetViewMode(viewMode string) gateway.OpenInAppRequest_ViewMode { switch viewMode { diff --git a/pkg/utils/utils_test.go b/pkg/utils/utils_test.go index d8caa7dedc..6d5a7ff335 100644 --- a/pkg/utils/utils_test.go +++ b/pkg/utils/utils_test.go @@ -19,7 +19,6 @@ package utils import ( - "errors" "testing" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" @@ -173,130 +172,3 @@ func TestMakeRelativePath(t *testing.T) { } } } - -func TestParseStorageSpaceReference(t *testing.T) { - tests := []struct { - sRef string - storageID string - nodeID string - relPath string - }{ - { - "1234!abcd/f1/f2", - "1234", - "abcd", - "./f1/f2", - }, - { - "1234!abcd", - "1234", - "abcd", - ".", - }, - } - for _, tt := range tests { - ref, _ := ParseStorageSpaceReference(tt.sRef) - - if ref.ResourceId.StorageId != tt.storageID { - t.Errorf("Expected storageId %s got %s", tt.storageID, ref.ResourceId.StorageId) - } - if ref.ResourceId.OpaqueId != tt.nodeID { - t.Errorf("Expected OpaqueId %s got %s", tt.nodeID, ref.ResourceId.OpaqueId) - } - if ref.Path != tt.relPath { - t.Errorf("Expected path %s got %s", tt.relPath, ref.Path) - } - } -} - -func TestFormatStorageSpaceReference(t *testing.T) { - tests := []struct { - ref *provider.Reference - expected string - expectedErr error - }{ - { - ref: &provider.Reference{}, - expected: "", - expectedErr: errInvalidSpaceReference, - }, - { - ref: &provider.Reference{ResourceId: &provider.ResourceId{}}, - expected: "!", - expectedErr: errInvalidSpaceReference, - }, - { - ref: &provider.Reference{ResourceId: &provider.ResourceId{OpaqueId: "opaqueid"}, Path: "path"}, - expectedErr: errInvalidSpaceReference, - }, - { - ref: &provider.Reference{ResourceId: &provider.ResourceId{StorageId: "storageid"}, Path: "path"}, - expected: "storageid/path", - }, - { - ref: &provider.Reference{ResourceId: &provider.ResourceId{StorageId: "storageid", OpaqueId: "opaqueid"}, Path: "path"}, - expected: "storageid!opaqueid/path", - }, - { - ref: &provider.Reference{ResourceId: &provider.ResourceId{StorageId: "storageid", OpaqueId: "opaqueid"}, Path: "."}, - expected: "storageid!opaqueid", - }, - { - ref: &provider.Reference{ResourceId: &provider.ResourceId{StorageId: "storageid"}, Path: "."}, - expected: "storageid", - }, - { - ref: &provider.Reference{ResourceId: &provider.ResourceId{StorageId: "storageid"}}, - expected: "storageid", - }, - } - - for _, tt := range tests { - result, err := FormatStorageSpaceReference(tt.ref) - if err != nil && !errors.Is(err, tt.expectedErr) { - t.Errorf("FormateStorageSpaceRefence returned unexpected error: %v", err) - } - if err == nil && result != tt.expected { - t.Errorf("Reference %v got formatted to %s, expected %s", tt.ref, result, tt.expected) - } - } -} - -func TestFormatAndParseReference(t *testing.T) { - tests := []struct { - orig *provider.Reference - expected *provider.Reference - }{ - { - orig: &provider.Reference{ResourceId: &provider.ResourceId{StorageId: "storageid"}, Path: "./path"}, - expected: &provider.Reference{ResourceId: &provider.ResourceId{StorageId: "storageid", OpaqueId: "storageid"}, Path: "./path"}, - }, - { - orig: &provider.Reference{ResourceId: &provider.ResourceId{StorageId: "storageid", OpaqueId: "opaqueid"}, Path: "./path"}, - expected: &provider.Reference{ResourceId: &provider.ResourceId{StorageId: "storageid", OpaqueId: "opaqueid"}, Path: "./path"}, - }, - { - orig: &provider.Reference{ResourceId: &provider.ResourceId{StorageId: "storageid", OpaqueId: "opaqueid"}, Path: "."}, - expected: &provider.Reference{ResourceId: &provider.ResourceId{StorageId: "storageid", OpaqueId: "opaqueid"}, Path: "."}, - }, - { - orig: &provider.Reference{ResourceId: &provider.ResourceId{StorageId: "storageid"}, Path: "."}, - expected: &provider.Reference{ResourceId: &provider.ResourceId{StorageId: "storageid", OpaqueId: "storageid"}, Path: "."}, - }, - { - orig: &provider.Reference{ResourceId: &provider.ResourceId{StorageId: "storageid"}}, - expected: &provider.Reference{ResourceId: &provider.ResourceId{StorageId: "storageid", OpaqueId: "storageid"}, Path: "."}, - }, - } - - for _, tt := range tests { - formatted, _ := FormatStorageSpaceReference(tt.orig) - parsed, err := ParseStorageSpaceReference(formatted) - if err != nil { - t.Errorf("failed to parse space reference: %s error: %s", formatted, err) - } - if !(ResourceIDEqual(parsed.ResourceId, tt.expected.ResourceId) && parsed.Path == tt.expected.Path) { - t.Errorf("Formatted then parsed references don't match the original got: %v expected %v", parsed, tt.expected) - } - } -}