From d3f664b2df3259ada2dcb6dc2a4205d0fc0fae73 Mon Sep 17 00:00:00 2001 From: Gianmaria Del Monte Date: Mon, 13 Nov 2023 12:03:22 +0100 Subject: [PATCH] handle spaces relative paths in webdav responses --- .../services/spacesregistry/spacesregistry.go | 7 ++++ internal/http/services/owncloud/ocdav/dav.go | 34 +++++++++++++++++-- .../http/services/owncloud/ocdav/ocdav.go | 4 +++ .../http/services/owncloud/ocdav/propfind.go | 22 +++++++++++- .../http/services/owncloud/ocgraph/drives.go | 6 ++-- 5 files changed, 66 insertions(+), 7 deletions(-) diff --git a/internal/grpc/services/spacesregistry/spacesregistry.go b/internal/grpc/services/spacesregistry/spacesregistry.go index ed1edd6b17..f4082bf52b 100644 --- a/internal/grpc/services/spacesregistry/spacesregistry.go +++ b/internal/grpc/services/spacesregistry/spacesregistry.go @@ -20,6 +20,7 @@ package spacesregistry import ( "context" + "encoding/base64" "errors" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" @@ -93,6 +94,12 @@ func (s *service) ListStorageSpaces(ctx context.Context, req *provider.ListStora Status: status.NewInternal(ctx, err, "error listing storage spaces"), }, nil } + + for _, s := range spaces { + s.Id = &provider.StorageSpaceId{ + OpaqueId: base64.StdEncoding.EncodeToString([]byte(s.RootInfo.Path)), + } + } return &provider.ListStorageSpacesResponse{ Status: status.NewOK(ctx), StorageSpaces: spaces, diff --git a/internal/http/services/owncloud/ocdav/dav.go b/internal/http/services/owncloud/ocdav/dav.go index a4ff90430b..71955fde29 100644 --- a/internal/http/services/owncloud/ocdav/dav.go +++ b/internal/http/services/owncloud/ocdav/dav.go @@ -20,6 +20,7 @@ package ocdav import ( "context" + "encoding/base64" "net/http" "path" "path/filepath" @@ -45,7 +46,7 @@ type DavHandler struct { FilesHomeHandler *WebDavHandler MetaHandler *MetaHandler TrashbinHandler *TrashbinHandler - SpacesHandler *SpacesHandler + SpacesHandler *WebDavHandler PublicFolderHandler *WebDavHandler PublicFileHandler *PublicFileHandler OCMSharesHandler *WebDavHandler @@ -70,8 +71,8 @@ func (h *DavHandler) init(c *Config) error { } h.TrashbinHandler = new(TrashbinHandler) - h.SpacesHandler = new(SpacesHandler) - if err := h.SpacesHandler.init(c); err != nil { + h.SpacesHandler = new(WebDavHandler) + if err := h.SpacesHandler.init("", false); err != nil { return err } @@ -176,6 +177,25 @@ func (h *DavHandler) Handler(s *svc) http.Handler { case "spaces": base := path.Join(ctx.Value(ctxKeyBaseURI).(string), "spaces") ctx := context.WithValue(ctx, ctxKeyBaseURI, base) + + // path is of type: space_id/relative/path/from/space + // the space_id is the base64 encode of the path where + // the space is located + spaceID, relativeSpacePath := router.ShiftPath(r.URL.Path) + + spacePath, err := getSpacePath(spaceID) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + return + } + + fullPath := filepath.Join(spacePath, relativeSpacePath) + r.URL.Path = fullPath + + ctx = context.WithValue(ctx, ctxSpaceID, spaceID) + ctx = context.WithValue(ctx, ctxSpaceFullPath, fullPath) + ctx = context.WithValue(ctx, ctxSpacePath, spacePath) + ctx = context.WithValue(ctx, ctxSpaceRelativePath, relativeSpacePath) r = r.WithContext(ctx) h.SpacesHandler.Handler(s).ServeHTTP(w, r) case "ocm": @@ -323,6 +343,14 @@ func (h *DavHandler) Handler(s *svc) http.Handler { }) } +func getSpacePath(spaceID string) (string, error) { + decoded, err := base64.StdEncoding.DecodeString(spaceID) + if err != nil { + return "", err + } + return string(decoded), nil +} + func getTokenStatInfo(ctx context.Context, client gatewayv1beta1.GatewayAPIClient, token string) (*provider.StatResponse, error) { return client.Stat(ctx, &provider.StatRequest{Ref: &provider.Reference{Path: path.Join("/public", token)}}) } diff --git a/internal/http/services/owncloud/ocdav/ocdav.go b/internal/http/services/owncloud/ocdav/ocdav.go index 6606be76f5..662bbc7136 100644 --- a/internal/http/services/owncloud/ocdav/ocdav.go +++ b/internal/http/services/owncloud/ocdav/ocdav.go @@ -52,6 +52,10 @@ type ctxKey int const ( ctxKeyBaseURI ctxKey = iota ctxOCM10 + ctxSpaceID + ctxSpacePath + ctxSpaceFullPath + ctxSpaceRelativePath ) var ( diff --git a/internal/http/services/owncloud/ocdav/propfind.go b/internal/http/services/owncloud/ocdav/propfind.go index ab6e341623..14435a8c5a 100644 --- a/internal/http/services/owncloud/ocdav/propfind.go +++ b/internal/http/services/owncloud/ocdav/propfind.go @@ -514,6 +514,20 @@ func supportLegacyOCMAccess(ctx context.Context, md *provider.ResourceInfo) { } } +func spaceHref(ctx context.Context, baseURI, fullPath string) string { + // in the context of spaces, the final URL will be baseURI + //relative/path/to/space + spacePath, ok := ctx.Value(ctxSpacePath).(string) + if !ok { + panic("space path expected to be in the context") + } + relativePath := strings.TrimPrefix(fullPath, spacePath) + spaceID, ok := ctx.Value(ctxSpaceID).(string) + if !ok { + panic("space id expected to be in the context") + } + return path.Join(baseURI, spaceID, relativePath) +} + // mdToPropResponse converts the CS3 metadata into a webdav PropResponse // ns is the CS3 namespace that needs to be removed from the CS3 path before // prefixing it with the baseURI. @@ -524,7 +538,13 @@ func (s *svc) mdToPropResponse(ctx context.Context, pf *propfindXML, md *provide baseURI := ctx.Value(ctxKeyBaseURI).(string) supportLegacyOCMAccess(ctx, md) - ref := path.Join(baseURI, md.Path) + + var ref string + if _, ok := ctx.Value(ctxSpaceID).(string); ok { + ref = spaceHref(ctx, baseURI, md.Path) + } else { + ref = path.Join(baseURI, md.Path) + } if md.Type == provider.ResourceType_RESOURCE_TYPE_CONTAINER { ref += "/" } diff --git a/internal/http/services/owncloud/ocgraph/drives.go b/internal/http/services/owncloud/ocgraph/drives.go index 25e76ba3e7..4c30db8cba 100644 --- a/internal/http/services/owncloud/ocgraph/drives.go +++ b/internal/http/services/owncloud/ocgraph/drives.go @@ -113,12 +113,12 @@ func generateCs3Filters(request *godata.GoDataRequest) ([]*providerpb.ListStorag func (s *svc) cs3StorageSpaceToDrive(user *userpb.User, space *providerpb.StorageSpace) *libregraph.Drive { drive := &libregraph.Drive{ - DriveAlias: libregraph.PtrString(space.RootInfo.Path[1:]), - Id: libregraph.PtrString(space.RootInfo.Path), + DriveAlias: libregraph.PtrString(space.RootInfo.Path), + Id: libregraph.PtrString(space.Id.OpaqueId), Name: space.Name, DriveType: libregraph.PtrString(space.SpaceType), Root: &libregraph.DriveItem{ - Id: libregraph.PtrString(space.RootInfo.Path), + Id: libregraph.PtrString(space.Id.OpaqueId), Permissions: cs3PermissionsToLibreGraph(user, space.RootInfo.PermissionSet), }, }