Skip to content

Commit

Permalink
fix restore for nested spaces
Browse files Browse the repository at this point in the history
There can be nested spaces e.g. the 'Shares Jail' inside a users space
  • Loading branch information
David Christofas committed Mar 14, 2022
1 parent d192df5 commit c66d9ce
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 20 deletions.
1 change: 0 additions & 1 deletion internal/http/services/owncloud/ocdav/net/net.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,6 @@ func ParseDepth(s string) (Depth, error) {
// ParseOverwrite parses the overwrite header value defined in https://datatracker.ietf.org/doc/html/rfc4918#section-10.6
// Valid values are "T" and "F". An empty string will be parse to true.
func ParseOverwrite(s string) (bool, error) {
s = strings.ToUpper(s)
if s == "" {
s = "T"
}
Expand Down
8 changes: 6 additions & 2 deletions internal/http/services/owncloud/ocdav/spaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -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/utils"
)

// SpacesHandler handles trashbin requests
Expand Down Expand Up @@ -184,9 +185,12 @@ func (h *SpacesHandler) handleSpacesTrashbin(w http.ResponseWriter, r *http.Requ
w.WriteHeader(http.StatusBadRequest)
return
}

log.Debug().Str("key", key).Str("path", r.URL.Path).Str("dst", dst).Msg("spaces restore")
trashbinHandler.restore(w, r, s, ref, dst, key, r.URL.Path)

dstRef := ref
dstRef.Path = utils.MakeRelativePath(dst)

trashbinHandler.restore(w, r, s, ref, dstRef, key, r.URL.Path)
case http.MethodDelete:
trashbinHandler.delete(w, r, s, ref, key, r.URL.Path)
default:
Expand Down
39 changes: 22 additions & 17 deletions internal/http/services/owncloud/ocdav/trashbin.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,22 @@ func (h *TrashbinHandler) Handler(s *svc) http.Handler {
return
}

p := path.Join(ns, dst)
// The destination can be in another space. E.g. the 'Shares Jail'.
space, rpcstatus, err := spacelookup.LookUpStorageSpaceForPath(ctx, client, p)
if err != nil {
log.Error().Err(err).Str("path", p).Msg("failed to look up destination storage space")
w.WriteHeader(http.StatusInternalServerError)
return
}
if rpcstatus.Code != rpc.Code_CODE_OK {
errors.HandleErrorStatus(log, w, rpcstatus)
return
}
dstRef := spacelookup.MakeRelativeReference(space, p, false)

log.Debug().Str("key", key).Str("dst", dst).Msg("restore")
h.restore(w, r, s, ref, dst, key, r.URL.Path)
h.restore(w, r, s, ref, dstRef, key, r.URL.Path)
case http.MethodDelete:
h.delete(w, r, s, ref, key, r.URL.Path)
default:
Expand Down Expand Up @@ -261,11 +275,6 @@ func (h *TrashbinHandler) listTrashbin(w http.ResponseWriter, r *http.Request, s
}
}

// TODO when using space based requests we should be able to get rid of this path unprefixing
// for i := range items {
// items[i].Ref.Path = strings.TrimPrefix(items[i].Ref.Path, basePath)
// }

propRes, err := h.formatTrashPropfind(ctx, s, refBase, &pf, items)
if err != nil {
sublog.Error().Err(err).Msg("error formatting propfind")
Expand Down Expand Up @@ -438,7 +447,7 @@ func (h *TrashbinHandler) itemToPropResponse(ctx context.Context, s *svc, refBas
return &response, nil
}

func (h *TrashbinHandler) restore(w http.ResponseWriter, r *http.Request, s *svc, ref *provider.Reference, dst, key, itemPath string) {
func (h *TrashbinHandler) restore(w http.ResponseWriter, r *http.Request, s *svc, ref, dst *provider.Reference, key, itemPath string) {
ctx, span := rtrace.Provider.Tracer("trash-bin").Start(r.Context(), "restore")
defer span.End()

Expand All @@ -459,10 +468,7 @@ func (h *TrashbinHandler) restore(w http.ResponseWriter, r *http.Request, s *svc
return
}

dstRef := ref
dstRef.Path = utils.MakeRelativePath(dst)

dstStatReq := &provider.StatRequest{Ref: dstRef}
dstStatReq := &provider.StatRequest{Ref: dst}
dstStatRes, err := client.Stat(ctx, dstStatReq)
if err != nil {
sublog.Error().Err(err).Msg("error sending grpc stat request")
Expand All @@ -477,9 +483,8 @@ func (h *TrashbinHandler) restore(w http.ResponseWriter, r *http.Request, s *svc

// Restoring to a non-existent location is not supported by the WebDAV spec. The following block ensures the target
// restore location exists, and if it doesn't returns a conflict error code.
if dstStatRes.Status.Code == rpc.Code_CODE_NOT_FOUND && isNested(dst) {
parentRef := ref
parentRef.Path = utils.MakeRelativePath(path.Dir(dst))
if dstStatRes.Status.Code == rpc.Code_CODE_NOT_FOUND && isNested(dst.Path) {
parentRef := &provider.Reference{ResourceId: dst.ResourceId, Path: utils.MakeRelativePath(path.Dir(dst.Path))}
parentStatReq := &provider.StatRequest{Ref: parentRef}

parentStatResponse, err := client.Stat(ctx, parentStatReq)
Expand Down Expand Up @@ -512,7 +517,7 @@ func (h *TrashbinHandler) restore(w http.ResponseWriter, r *http.Request, s *svc
return
}
// delete existing tree
delReq := &provider.DeleteRequest{Ref: dstRef}
delReq := &provider.DeleteRequest{Ref: dst}
delRes, err := client.Delete(ctx, delReq)
if err != nil {
sublog.Error().Err(err).Msg("error sending grpc delete request")
Expand All @@ -529,7 +534,7 @@ func (h *TrashbinHandler) restore(w http.ResponseWriter, r *http.Request, s *svc
req := &provider.RestoreRecycleItemRequest{
Ref: ref,
Key: path.Join(key, itemPath),
RestoreRef: dstRef,
RestoreRef: dst,
}

res, err := client.RestoreRecycleItem(ctx, req)
Expand Down Expand Up @@ -621,5 +626,5 @@ func (h *TrashbinHandler) delete(w http.ResponseWriter, r *http.Request, s *svc,

func isNested(p string) bool {
dir, _ := path.Split(p)
return dir != "/"
return dir != "/" && dir != "./"
}

0 comments on commit c66d9ce

Please sign in to comment.