From 3b73594726b708cb544f8c0c999f4390c82305a1 Mon Sep 17 00:00:00 2001 From: Ishank Arora Date: Mon, 13 Dec 2021 16:37:53 +0530 Subject: [PATCH 1/2] Return wrapped paths for recycled items in storage provider --- changelog/unreleased/wrap-recycle-paths.md | 3 +++ .../storageprovider/storageprovider.go | 21 +++++++++++++++++++ .../http/services/owncloud/ocdav/trashbin.go | 6 ++---- 3 files changed, 26 insertions(+), 4 deletions(-) create mode 100644 changelog/unreleased/wrap-recycle-paths.md diff --git a/changelog/unreleased/wrap-recycle-paths.md b/changelog/unreleased/wrap-recycle-paths.md new file mode 100644 index 0000000000..6f818149f8 --- /dev/null +++ b/changelog/unreleased/wrap-recycle-paths.md @@ -0,0 +1,3 @@ +Bugfix: Return wrapped paths for recycled items in storage provider + +https://github.com/cs3org/reva/pull/2368 \ No newline at end of file diff --git a/internal/grpc/services/storageprovider/storageprovider.go b/internal/grpc/services/storageprovider/storageprovider.go index 82e09db0bb..fd72dbcb7c 100644 --- a/internal/grpc/services/storageprovider/storageprovider.go +++ b/internal/grpc/services/storageprovider/storageprovider.go @@ -1157,6 +1157,15 @@ func (s *service) ListRecycle(ctx context.Context, req *provider.ListRecycleRequ }, nil } + prefixMountpoint := utils.IsAbsoluteReference(req.Ref) + for _, md := range items { + if err := s.wrapReference(ctx, md.Ref, prefixMountpoint); err != nil { + return &provider.ListRecycleResponse{ + Status: status.NewInternal(ctx, err, "error wrapping path"), + }, nil + } + } + res := &provider.ListRecycleResponse{ Status: status.NewOK(ctx), RecycleItems: items, @@ -1538,6 +1547,18 @@ func (s *service) wrap(ctx context.Context, ri *provider.ResourceInfo, prefixMou return nil } +func (s *service) wrapReference(ctx context.Context, ref *provider.Reference, prefixMountpoint bool) error { + if ref.ResourceId != nil && ref.ResourceId.StorageId == "" { + // For wrapper drivers, the storage ID might already be set. In that case, skip setting it + ref.ResourceId.StorageId = s.mountID + } + if prefixMountpoint { + // TODO move mount path prefixing to the gateway + ref.Path = path.Join(s.mountPath, ref.Path) + } + return nil +} + type descendingMtime []*provider.FileVersion func (v descendingMtime) Len() int { diff --git a/internal/http/services/owncloud/ocdav/trashbin.go b/internal/http/services/owncloud/ocdav/trashbin.go index 7d27aa0964..9529d66580 100644 --- a/internal/http/services/owncloud/ocdav/trashbin.go +++ b/internal/http/services/owncloud/ocdav/trashbin.go @@ -465,9 +465,7 @@ func (h *TrashbinHandler) restore(w http.ResponseWriter, r *http.Request, s *svc return } - dstRef := &provider.Reference{ - Path: path.Join(basePath, dst), - } + dstRef := &provider.Reference{Path: dst} dstStatReq := &provider.StatRequest{ Ref: dstRef, @@ -544,7 +542,7 @@ func (h *TrashbinHandler) restore(w http.ResponseWriter, r *http.Request, s *svc Path: basePath, }, Key: path.Join(key, itemPath), - RestoreRef: &provider.Reference{Path: dst}, + RestoreRef: dstRef, } res, err := client.RestoreRecycleItem(ctx, req) From 9c043bf93c6afe5f1b383b2571b30803de590dc7 Mon Sep 17 00:00:00 2001 From: Ishank Arora Date: Mon, 13 Dec 2021 16:45:52 +0530 Subject: [PATCH 2/2] Trim base path in trashbin propfind response --- .../http/services/owncloud/ocdav/trashbin.go | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/internal/http/services/owncloud/ocdav/trashbin.go b/internal/http/services/owncloud/ocdav/trashbin.go index 9529d66580..4c79752214 100644 --- a/internal/http/services/owncloud/ocdav/trashbin.go +++ b/internal/http/services/owncloud/ocdav/trashbin.go @@ -182,7 +182,7 @@ func (h *TrashbinHandler) listTrashbin(w http.ResponseWriter, r *http.Request, s } if depth == "0" { - propRes, err := h.formatTrashPropfind(ctx, s, u, nil, nil) + propRes, err := h.formatTrashPropfind(ctx, s, u, nil, nil, basePath) if err != nil { sublog.Error().Err(err).Msg("error formatting propfind") w.WriteHeader(http.StatusInternalServerError) @@ -270,7 +270,7 @@ func (h *TrashbinHandler) listTrashbin(w http.ResponseWriter, r *http.Request, s } } - propRes, err := h.formatTrashPropfind(ctx, s, u, &pf, items) + propRes, err := h.formatTrashPropfind(ctx, s, u, &pf, items, basePath) if err != nil { sublog.Error().Err(err).Msg("error formatting propfind") w.WriteHeader(http.StatusInternalServerError) @@ -286,7 +286,7 @@ func (h *TrashbinHandler) listTrashbin(w http.ResponseWriter, r *http.Request, s } } -func (h *TrashbinHandler) formatTrashPropfind(ctx context.Context, s *svc, u *userpb.User, pf *propfindXML, items []*provider.RecycleItem) (string, error) { +func (h *TrashbinHandler) formatTrashPropfind(ctx context.Context, s *svc, u *userpb.User, pf *propfindXML, items []*provider.RecycleItem, basePath string) (string, error) { responses := make([]*responseXML, 0, len(items)+1) // add trashbin dir . entry responses = append(responses, &responseXML{ @@ -311,7 +311,7 @@ func (h *TrashbinHandler) formatTrashPropfind(ctx context.Context, s *svc, u *us }) for i := range items { - res, err := h.itemToPropResponse(ctx, s, u, pf, items[i]) + res, err := h.itemToPropResponse(ctx, s, u, pf, items[i], basePath) if err != nil { return "", err } @@ -331,7 +331,7 @@ func (h *TrashbinHandler) formatTrashPropfind(ctx context.Context, s *svc, u *us // itemToPropResponse needs to create a listing that contains a key and destination // the key is the name of an entry in the trash listing // for now we need to limit trash to the users home, so we can expect all trash keys to have the home storage as the opaque id -func (h *TrashbinHandler) itemToPropResponse(ctx context.Context, s *svc, u *userpb.User, pf *propfindXML, item *provider.RecycleItem) (*responseXML, error) { +func (h *TrashbinHandler) itemToPropResponse(ctx context.Context, s *svc, u *userpb.User, pf *propfindXML, item *provider.RecycleItem, basePath string) (*responseXML, error) { baseURI := ctx.Value(ctxKeyBaseURI).(string) ref := path.Join(baseURI, u.Username, item.Key) @@ -348,6 +348,7 @@ func (h *TrashbinHandler) itemToPropResponse(ctx context.Context, s *svc, u *use t := utils.TSToTime(item.DeletionTime).UTC() dTime := t.Format(time.RFC1123Z) + restorePath := strings.TrimPrefix(strings.TrimPrefix(item.Ref.Path, basePath), "/") // when allprops has been requested if pf.Allprop != nil { @@ -358,7 +359,7 @@ func (h *TrashbinHandler) itemToPropResponse(ctx context.Context, s *svc, u *use }) // yes this is redundant, can be derived from oc:trashbin-original-location which contains the full path, clients should not fetch it response.Propstat[0].Prop = append(response.Propstat[0].Prop, s.newProp("oc:trashbin-original-filename", path.Base(item.Ref.Path))) - response.Propstat[0].Prop = append(response.Propstat[0].Prop, s.newProp("oc:trashbin-original-location", strings.TrimPrefix(item.Ref.Path, "/"))) + response.Propstat[0].Prop = append(response.Propstat[0].Prop, s.newProp("oc:trashbin-original-location", restorePath)) response.Propstat[0].Prop = append(response.Propstat[0].Prop, s.newProp("oc:trashbin-delete-timestamp", strconv.FormatUint(item.DeletionTime.Seconds, 10))) response.Propstat[0].Prop = append(response.Propstat[0].Prop, s.newProp("oc:trashbin-delete-datetime", dTime)) if item.Type == provider.ResourceType_RESOURCE_TYPE_CONTAINER { @@ -397,7 +398,7 @@ func (h *TrashbinHandler) itemToPropResponse(ctx context.Context, s *svc, u *use propstatOK.Prop = append(propstatOK.Prop, s.newProp("oc:trashbin-original-filename", path.Base(item.Ref.Path))) case "trashbin-original-location": // TODO (jfd) double check and clarify the cs3 spec what the Key is about and if Path is only the folder that contains the file or if it includes the filename - propstatOK.Prop = append(propstatOK.Prop, s.newProp("oc:trashbin-original-location", strings.TrimPrefix(item.Ref.Path, "/"))) + propstatOK.Prop = append(propstatOK.Prop, s.newProp("oc:trashbin-original-location", restorePath)) case "trashbin-delete-datetime": propstatOK.Prop = append(propstatOK.Prop, s.newProp("oc:trashbin-delete-datetime", dTime)) case "trashbin-delete-timestamp": @@ -465,7 +466,9 @@ func (h *TrashbinHandler) restore(w http.ResponseWriter, r *http.Request, s *svc return } - dstRef := &provider.Reference{Path: dst} + dstRef := &provider.Reference{ + Path: path.Join(basePath, dst), + } dstStatReq := &provider.StatRequest{ Ref: dstRef, @@ -542,7 +545,7 @@ func (h *TrashbinHandler) restore(w http.ResponseWriter, r *http.Request, s *svc Path: basePath, }, Key: path.Join(key, itemPath), - RestoreRef: dstRef, + RestoreRef: &provider.Reference{Path: dst}, } res, err := client.RestoreRecycleItem(ctx, req)