From 50420e14ef4f59dca75af2030a4f9e8996b3e6f8 Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Thu, 6 Aug 2020 16:48:26 +0200 Subject: [PATCH 01/17] ignore stray shares --- .../grpc/services/gateway/storageprovider.go | 69 +++++++++---------- .../handlers/apps/sharing/shares/shares.go | 8 ++- 2 files changed, 40 insertions(+), 37 deletions(-) diff --git a/internal/grpc/services/gateway/storageprovider.go b/internal/grpc/services/gateway/storageprovider.go index fc6f565081..4487043c8c 100644 --- a/internal/grpc/services/gateway/storageprovider.go +++ b/internal/grpc/services/gateway/storageprovider.go @@ -123,10 +123,10 @@ func (s *svc) InitiateFileDownload(ctx context.Context, req *provider.InitiateFi }, nil } - p, err := s.getPath(ctx, req.Ref) + p, st := s.getPath(ctx, req.Ref) if err != nil { return &gateway.InitiateFileDownloadResponse{ - Status: status.NewInternal(ctx, err, "gateway: error gettng path for ref"), + Status: st, }, nil } @@ -140,7 +140,8 @@ func (s *svc) InitiateFileDownload(ctx context.Context, req *provider.InitiateFi err := errtypes.PermissionDenied("gateway: cannot upload to share folder or share name: path=" + p) log.Err(err).Msg("gateway: error downloading") return &gateway.InitiateFileDownloadResponse{ - Status: status.NewInvalidArg(ctx, "path points to share folder or share name"), + // Status: status.NewInvalidArg(ctx, "path points to share folder or share name"), + Status: st, }, nil } @@ -254,10 +255,10 @@ func (s *svc) initiateFileDownload(ctx context.Context, req *provider.InitiateFi } func (s *svc) InitiateFileUpload(ctx context.Context, req *provider.InitiateFileUploadRequest) (*gateway.InitiateFileUploadResponse, error) { - p, err := s.getPath(ctx, req.Ref) - if err != nil { + p, st := s.getPath(ctx, req.Ref) + if st.Code != rpc.Code_CODE_OK { return &gateway.InitiateFileUploadResponse{ - Status: status.NewInternal(ctx, err, "gateway: error gettng path for ref"), + Status: st, }, nil } @@ -422,10 +423,10 @@ func (s *svc) GetPath(ctx context.Context, req *provider.GetPathRequest) (*provi } func (s *svc) CreateContainer(ctx context.Context, req *provider.CreateContainerRequest) (*provider.CreateContainerResponse, error) { - p, err := s.getPath(ctx, req.Ref) - if err != nil { + p, st := s.getPath(ctx, req.Ref) + if st.Code != rpc.Code_CODE_OK { return &provider.CreateContainerResponse{ - Status: status.NewInternal(ctx, err, "gateway: error gettng path for ref"), + Status: st, }, nil } @@ -527,10 +528,10 @@ func (s *svc) inSharedFolder(ctx context.Context, p string) bool { } func (s *svc) Delete(ctx context.Context, req *provider.DeleteRequest) (*provider.DeleteResponse, error) { - p, err := s.getPath(ctx, req.Ref) - if err != nil { + p, st := s.getPath(ctx, req.Ref) + if st.Code != rpc.Code_CODE_OK { return &provider.DeleteResponse{ - Status: status.NewInternal(ctx, err, "gateway: error gettng path for ref"), + Status: st, }, nil } @@ -644,19 +645,19 @@ func (s *svc) delete(ctx context.Context, req *provider.DeleteRequest) (*provide func (s *svc) Move(ctx context.Context, req *provider.MoveRequest) (*provider.MoveResponse, error) { log := appctx.GetLogger(ctx) - p, err := s.getPath(ctx, req.Source) - if err != nil { - log.Err(err).Msg("gateway: error moving") + p, st := s.getPath(ctx, req.Source) + if st.Code != rpc.Code_CODE_OK { + // log.Err(err).Msg("gateway: error moving") return &provider.MoveResponse{ - Status: status.NewInternal(ctx, err, "gateway: error gettng path for ref"), + Status: st, }, nil } dp, err := s.getPath(ctx, req.Destination) if err != nil { - log.Err(err).Msg("gateway: error moving") + // log.Err(err).Msg("gateway: error moving") return &provider.MoveResponse{ - Status: status.NewInternal(ctx, err, "gateway: error gettng path for ref"), + Status: st, }, nil } @@ -844,10 +845,11 @@ func (s *svc) stat(ctx context.Context, req *provider.StatRequest) (*provider.St } func (s *svc) Stat(ctx context.Context, req *provider.StatRequest) (*provider.StatResponse, error) { - p, err := s.getPath(ctx, req.Ref, req.ArbitraryMetadataKeys...) - if err != nil { + p, st := s.getPath(ctx, req.Ref, req.ArbitraryMetadataKeys...) + if st.Code != rpc.Code_CODE_OK { return &provider.StatResponse{ - Status: status.NewInternal(ctx, err, "gateway: error getting path for ref"), + // Status: status.NewInternal(ctx, "", "gateway: error getting path for ref"), + Status: st, }, nil } @@ -1062,10 +1064,11 @@ func (s *svc) listContainer(ctx context.Context, req *provider.ListContainerRequ } func (s *svc) ListContainer(ctx context.Context, req *provider.ListContainerRequest) (*provider.ListContainerResponse, error) { - p, err := s.getPath(ctx, req.Ref, req.ArbitraryMetadataKeys...) - if err != nil { + p, st := s.getPath(ctx, req.Ref, req.ArbitraryMetadataKeys...) + if st.Code != rpc.Code_CODE_OK { return &provider.ListContainerResponse{ - Status: status.NewInternal(ctx, err, "gateway: error getting path for ref"), + // Status: status.NewInternal(ctx, err, "gateway: error getting path for ref"), + Status: st, }, nil } @@ -1250,28 +1253,22 @@ func (s *svc) ListContainer(ctx context.Context, req *provider.ListContainerRequ panic("gateway: stating an unknown path:" + p) } -func (s *svc) getPath(ctx context.Context, ref *provider.Reference, keys ...string) (string, error) { +func (s *svc) getPath(ctx context.Context, ref *provider.Reference, keys ...string) (string, *rpc.Status) { if ref.GetPath() != "" { - return ref.GetPath(), nil + return ref.GetPath(), &rpc.Status{Code: rpc.Code_CODE_OK} } if ref.GetId() != nil && ref.GetId().GetOpaqueId() != "" { req := &provider.StatRequest{Ref: ref, ArbitraryMetadataKeys: keys} res, err := s.stat(ctx, req) - if err != nil { - err = errors.Wrap(err, "gateway: error stating ref:"+ref.String()) - return "", err - } - - if res.Status.Code != rpc.Code_CODE_OK { - err := status.NewErrorFromCode(res.Status.Code, "gateway") - return "", err + if res.Status.Code != rpc.Code_CODE_OK || err != nil { + return "", res.Status } - return res.Info.Path, nil + return res.Info.Path, res.Status } - return "", errors.New("gateway: ref is invalid:" + ref.String()) + return "", &rpc.Status{Code: rpc.Code_CODE_INTERNAL} } // /home/MyShares/ 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 229665c009..236e84f29b 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 @@ -1295,7 +1295,13 @@ func (h *Handler) listUserShares(r *http.Request, filters []*collaboration.ListS } if statResponse.Status.Code != rpc.Code_CODE_OK { - return nil, errors.New("could not stat share target") + if statResponse.Status.Code == rpc.Code_CODE_NOT_FOUND { + // TODO share target was not found, we should not error here. + // return nil, errors.New(fmt.Sprintf("could not stat share target: %v, code: %v", s.ResourceId, statResponse.Status)) + continue + } + + return nil, errors.New(fmt.Sprintf("could not stat share target: %v, code: %v", s.ResourceId, statResponse.Status)) } err = h.addFileInfo(ctx, share, statResponse.Info) From 7650a6d69fc359e495dbf13c6af276a0b5244f55 Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Fri, 7 Aug 2020 13:39:33 +0200 Subject: [PATCH 02/17] stray block --- .../grpc/services/gateway/storageprovider.go | 22 +------------------ 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/internal/grpc/services/gateway/storageprovider.go b/internal/grpc/services/gateway/storageprovider.go index 27b30ead04..00c0ec736e 100644 --- a/internal/grpc/services/gateway/storageprovider.go +++ b/internal/grpc/services/gateway/storageprovider.go @@ -104,25 +104,6 @@ func (s *svc) getHome(ctx context.Context) string { return "/home" } func (s *svc) InitiateFileDownload(ctx context.Context, req *provider.InitiateFileDownloadRequest) (*gateway.InitiateFileDownloadResponse, error) { - statReq := &provider.StatRequest{Ref: req.Ref} - statRes, err := s.stat(ctx, statReq) - if err != nil { - return &gateway.InitiateFileDownloadResponse{ - Status: status.NewInternal(ctx, err, "gateway: error stating ref:"+req.Ref.String()), - }, nil - } - if statRes.Status.Code != rpc.Code_CODE_OK { - if statRes.Status.Code == rpc.Code_CODE_NOT_FOUND { - return &gateway.InitiateFileDownloadResponse{ - Status: status.NewNotFound(ctx, "gateway: file not found"), - }, nil - } - err := status.NewErrorFromCode(statRes.Status.Code, "gateway") - return &gateway.InitiateFileDownloadResponse{ - Status: status.NewInternal(ctx, err, "gateway: error stating ref"), - }, nil - } - p, st := s.getPath(ctx, req.Ref) if st.Code != rpc.Code_CODE_OK { return &gateway.InitiateFileDownloadResponse{ @@ -158,8 +139,7 @@ func (s *svc) InitiateFileDownload(ctx context.Context, req *provider.InitiateFi err := errtypes.PermissionDenied("gateway: cannot download share folder or share name: path=" + p) log.Err(err).Msg("gateway: error downloading") return &gateway.InitiateFileDownloadResponse{ - // Status: status.NewInvalidArg(ctx, "path points to share folder or share name"), - Status: st, + Status: status.NewInvalidArg(ctx, "path points to share folder or share name"), }, nil } From 18ff637d8455eaebb38e5457c5199320f54fa67b Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Fri, 7 Aug 2020 13:57:50 +0200 Subject: [PATCH 03/17] log reason of STAT failure --- .../grpc/services/gateway/storageprovider.go | 35 +++++++++++++------ 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/internal/grpc/services/gateway/storageprovider.go b/internal/grpc/services/gateway/storageprovider.go index 00c0ec736e..dfe8c88c49 100644 --- a/internal/grpc/services/gateway/storageprovider.go +++ b/internal/grpc/services/gateway/storageprovider.go @@ -104,8 +104,11 @@ func (s *svc) getHome(ctx context.Context) string { return "/home" } func (s *svc) InitiateFileDownload(ctx context.Context, req *provider.InitiateFileDownloadRequest) (*gateway.InitiateFileDownloadResponse, error) { + log := appctx.GetLogger(ctx) p, st := s.getPath(ctx, req.Ref) if st.Code != rpc.Code_CODE_OK { + log.Error().Str("rpc_code", st.Code.String()). + Msgf("error initiating file download id: %v", req.Ref.GetId()) return &gateway.InitiateFileDownloadResponse{ Status: st, }, nil @@ -133,7 +136,7 @@ func (s *svc) InitiateFileDownload(ctx context.Context, req *provider.InitiateFi return s.initiateFileDownload(ctx, req) } - log := appctx.GetLogger(ctx) + if s.isSharedFolder(ctx, p) || s.isShareName(ctx, p) { log.Debug().Msgf("path:%s points to shared folder or share name", p) err := errtypes.PermissionDenied("gateway: cannot download share folder or share name: path=" + p) @@ -254,8 +257,11 @@ func (s *svc) initiateFileDownload(ctx context.Context, req *provider.InitiateFi } func (s *svc) InitiateFileUpload(ctx context.Context, req *provider.InitiateFileUploadRequest) (*gateway.InitiateFileUploadResponse, error) { + log := appctx.GetLogger(ctx) p, st := s.getPath(ctx, req.Ref) if st.Code != rpc.Code_CODE_OK { + log.Error().Str("rpc_code", st.Code.String()). + Msgf("error initiating file upload id: %v", req.Ref.GetId()) return &gateway.InitiateFileUploadResponse{ Status: st, }, nil @@ -265,7 +271,6 @@ func (s *svc) InitiateFileUpload(ctx context.Context, req *provider.InitiateFile return s.initiateFileUpload(ctx, req) } - log := appctx.GetLogger(ctx) if s.isSharedFolder(ctx, p) || s.isShareName(ctx, p) { log.Debug().Msgf("path:%s points to shared folder or share name", p) err := errtypes.PermissionDenied("gateway: cannot upload to share folder or share name: path=" + p) @@ -422,8 +427,11 @@ func (s *svc) GetPath(ctx context.Context, req *provider.GetPathRequest) (*provi } func (s *svc) CreateContainer(ctx context.Context, req *provider.CreateContainerRequest) (*provider.CreateContainerResponse, error) { + log := appctx.GetLogger(ctx) p, st := s.getPath(ctx, req.Ref) if st.Code != rpc.Code_CODE_OK { + log.Error().Str("rpc_code", st.Code.String()). + Msgf("error creating container on reference id: %v", req.Ref.GetId()) return &provider.CreateContainerResponse{ Status: st, }, nil @@ -433,7 +441,6 @@ func (s *svc) CreateContainer(ctx context.Context, req *provider.CreateContainer return s.createContainer(ctx, req) } - log := appctx.GetLogger(ctx) if s.isSharedFolder(ctx, p) || s.isShareName(ctx, p) { log.Debug().Msgf("path:%s points to shared folder or share name", p) err := errtypes.PermissionDenied("gateway: cannot create container on share folder or share name: path=" + p) @@ -527,15 +534,20 @@ func (s *svc) inSharedFolder(ctx context.Context, p string) bool { } func (s *svc) Delete(ctx context.Context, req *provider.DeleteRequest) (*provider.DeleteResponse, error) { + log := appctx.GetLogger(ctx) p, st := s.getPath(ctx, req.Ref) if st.Code != rpc.Code_CODE_OK { + log.Error().Str("rpc_code", st.Code.String()). + Msgf("error deleting reference id: %v", req.Ref.GetId()) + return &provider.DeleteResponse{ + Status: st, + }, nil } if !s.inSharedFolder(ctx, p) { return s.delete(ctx, req) } - log := appctx.GetLogger(ctx) if s.isSharedFolder(ctx, p) { // TODO(labkode): deleting share names should be allowed, means unmounting. log.Debug().Msgf("path:%s points to shared folder or share name", p) @@ -640,10 +652,10 @@ func (s *svc) delete(ctx context.Context, req *provider.DeleteRequest) (*provide func (s *svc) Move(ctx context.Context, req *provider.MoveRequest) (*provider.MoveResponse, error) { log := appctx.GetLogger(ctx) - p, st := s.getPath(ctx, req.Source) if st.Code != rpc.Code_CODE_OK { - // log.Err(err).Msg("gateway: error moving") + log.Error().Str("rpc_code", st.Code.String()). + Msgf("error moving reference id: %v to `%v`", req.Source.GetId(), req.Destination.String()) return &provider.MoveResponse{ Status: st, }, nil @@ -841,10 +853,12 @@ func (s *svc) stat(ctx context.Context, req *provider.StatRequest) (*provider.St } func (s *svc) Stat(ctx context.Context, req *provider.StatRequest) (*provider.StatResponse, error) { + log := appctx.GetLogger(ctx) p, st := s.getPath(ctx, req.Ref, req.ArbitraryMetadataKeys...) if st.Code != rpc.Code_CODE_OK { + log.Error().Str("rpc_code", st.Code.String()). + Msgf("error during STAT id: %v", req.Ref.GetId()) return &provider.StatResponse{ - // Status: status.NewInternal(ctx, "", "gateway: error getting path for ref"), Status: st, }, nil } @@ -858,8 +872,6 @@ func (s *svc) Stat(ctx context.Context, req *provider.StatRequest) (*provider.St return s.stat(ctx, req) } - log := appctx.GetLogger(ctx) - // we need to provide the info of the target, not the reference. if s.isShareName(ctx, p) { res, err := s.stat(ctx, req) @@ -1078,10 +1090,12 @@ func (s *svc) listContainer(ctx context.Context, req *provider.ListContainerRequ } func (s *svc) ListContainer(ctx context.Context, req *provider.ListContainerRequest) (*provider.ListContainerResponse, error) { + log := appctx.GetLogger(ctx) p, st := s.getPath(ctx, req.Ref, req.ArbitraryMetadataKeys...) if st.Code != rpc.Code_CODE_OK { + log.Error().Str("rpc_code", st.Code.String()). + Msgf("error listing directory id: %v", req.Ref.GetId()) return &provider.ListContainerResponse{ - // Status: status.NewInternal(ctx, err, "gateway: error getting path for ref"), Status: st, }, nil } @@ -1118,7 +1132,6 @@ func (s *svc) ListContainer(ctx context.Context, req *provider.ListContainerRequ return lcr, nil } - log := appctx.GetLogger(ctx) // we need to provide the info of the target, not the reference. if s.isShareName(ctx, p) { From c433b7d999d8facc78cadba542a8597a0b8395e3 Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Fri, 7 Aug 2020 14:24:32 +0200 Subject: [PATCH 04/17] fix warnings and offenses --- .../grpc/services/gateway/storageprovider.go | 29 +++++++------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/internal/grpc/services/gateway/storageprovider.go b/internal/grpc/services/gateway/storageprovider.go index dfe8c88c49..5d6c3bf5c4 100644 --- a/internal/grpc/services/gateway/storageprovider.go +++ b/internal/grpc/services/gateway/storageprovider.go @@ -44,7 +44,7 @@ type transferClaims struct { Target string `json:"target"` } -func (s *svc) sign(ctx context.Context, target string) (string, error) { +func (s *svc) sign(_ context.Context, target string) (string, error) { ttl := time.Duration(s.c.TransferExpires) * time.Second claims := transferClaims{ StandardClaims: jwt.StandardClaims{ @@ -93,13 +93,13 @@ func (s *svc) CreateHome(ctx context.Context, req *provider.CreateHomeRequest) ( return res, nil } -func (s *svc) GetHome(ctx context.Context, req *provider.GetHomeRequest) (*provider.GetHomeResponse, error) { +func (s *svc) GetHome(ctx context.Context, _ *provider.GetHomeRequest) (*provider.GetHomeResponse, error) { home := s.getHome(ctx) homeRes := &provider.GetHomeResponse{Path: home, Status: status.NewOK(ctx)} return homeRes, nil } -func (s *svc) getHome(ctx context.Context) string { +func (s *svc) getHome(_ context.Context) string { // TODO(labkode): issue #601, /home will be hardcoded. return "/home" } @@ -136,7 +136,6 @@ func (s *svc) InitiateFileDownload(ctx context.Context, req *provider.InitiateFi return s.initiateFileDownload(ctx, req) } - if s.isSharedFolder(ctx, p) || s.isShareName(ctx, p) { log.Debug().Msgf("path:%s points to shared folder or share name", p) err := errtypes.PermissionDenied("gateway: cannot download share folder or share name: path=" + p) @@ -663,7 +662,6 @@ func (s *svc) Move(ctx context.Context, req *provider.MoveRequest) (*provider.Mo dp, err := s.getPath(ctx, req.Destination) if err != nil { - // log.Err(err).Msg("gateway: error moving") return &provider.MoveResponse{ Status: st, }, nil @@ -1058,13 +1056,13 @@ func (s *svc) handleCS3Ref(ctx context.Context, opaque string) (*provider.Resour return res.Info, nil } -func (s *svc) handleWebdavRef(ctx context.Context, ri *provider.ResourceInfo) (*provider.ResourceInfo, error) { +func (s *svc) handleWebdavRef(_ context.Context, ri *provider.ResourceInfo) (*provider.ResourceInfo, error) { // A webdav ref has the following layout: /@webdav_endpoint // TODO: Once file transfer functionalities have been added. return ri, nil } -func (s *svc) ListContainerStream(req *provider.ListContainerStreamRequest, ss gateway.GatewayAPI_ListContainerStreamServer) error { +func (s *svc) ListContainerStream(_ *provider.ListContainerStreamRequest, _ gateway.GatewayAPI_ListContainerStreamServer) error { return errors.New("Unimplemented") } @@ -1115,24 +1113,19 @@ func (s *svc) ListContainer(ctx context.Context, req *provider.ListContainerRequ } for i, ref := range lcr.Infos { - info, err := s.checkRef(ctx, ref) if err != nil { return &provider.ListContainerResponse{ - Status: status.NewInternal(ctx, err, "gateway: error resolving reference:"+info.Path), + Status: status.NewInternal(ctx, err, "gateway: error resolving reference:"+ref.Path), }, nil } - base := path.Base(ref.Path) info.Path = path.Join(p, base) - lcr.Infos[i] = info - } return lcr, nil } - // we need to provide the info of the target, not the reference. if s.isShareName(ctx, p) { ref := &provider.Reference{ @@ -1288,7 +1281,7 @@ func (s *svc) getPath(ctx context.Context, ref *provider.Reference, keys ...stri if ref.GetId() != nil && ref.GetId().GetOpaqueId() != "" { req := &provider.StatRequest{Ref: ref, ArbitraryMetadataKeys: keys} res, err := s.stat(ctx, req) - if res.Status.Code != rpc.Code_CODE_OK || err != nil { + if (res != nil && res.Status.Code != rpc.Code_CODE_OK) || err != nil { return "", res.Status } @@ -1356,7 +1349,7 @@ func (s *svc) splitShare(ctx context.Context, p string) (string, string) { return shareName, shareChild } -func (s *svc) splitPath(ctx context.Context, p string) []string { +func (s *svc) splitPath(_ context.Context, p string) []string { p = strings.Trim(p, "/") return strings.SplitN(p, "/", 4) // ["home", "MyShares", "photos", "Ibiza/beach.png"] } @@ -1409,7 +1402,7 @@ func (s *svc) RestoreFileVersion(ctx context.Context, req *provider.RestoreFileV return res, nil } -func (s *svc) ListRecycleStream(req *gateway.ListRecycleStreamRequest, ss gateway.GatewayAPI_ListRecycleStreamServer) error { +func (s *svc) ListRecycleStream(_ *gateway.ListRecycleStreamRequest, _ gateway.GatewayAPI_ListRecycleStreamServer) error { return errors.New("Unimplemented") } @@ -1484,7 +1477,7 @@ func (s *svc) PurgeRecycle(ctx context.Context, req *gateway.PurgeRecycleRequest return res, nil } -func (s *svc) GetQuota(ctx context.Context, req *gateway.GetQuotaRequest) (*provider.GetQuotaResponse, error) { +func (s *svc) GetQuota(ctx context.Context, _ *gateway.GetQuotaRequest) (*provider.GetQuotaResponse, error) { res := &provider.GetQuotaResponse{ Status: status.NewUnimplemented(ctx, nil, "GetQuota not yet implemented"), } @@ -1517,7 +1510,7 @@ func (s *svc) find(ctx context.Context, ref *provider.Reference) (provider.Provi return s.getStorageProviderClient(ctx, p) } -func (s *svc) getStorageProviderClient(ctx context.Context, p *registry.ProviderInfo) (provider.ProviderAPIClient, error) { +func (s *svc) getStorageProviderClient(_ context.Context, p *registry.ProviderInfo) (provider.ProviderAPIClient, error) { c, err := pool.GetStorageProviderServiceClient(p.Address) if err != nil { err = errors.Wrap(err, "gateway: error getting a storage provider client") From 6bd190ffb9b68ca1ed7c37f1c76cc54b98b630c2 Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Fri, 7 Aug 2020 14:31:32 +0200 Subject: [PATCH 05/17] add changelog --- changelog/unreleased/ensure-stray-shares.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 changelog/unreleased/ensure-stray-shares.md diff --git a/changelog/unreleased/ensure-stray-shares.md b/changelog/unreleased/ensure-stray-shares.md new file mode 100644 index 0000000000..fd4fc42b90 --- /dev/null +++ b/changelog/unreleased/ensure-stray-shares.md @@ -0,0 +1,5 @@ +Bugfix: Ensure stray shares get ignored + +When using the json shares manager, it can be the case we found a share with a resource_id that no longer exists. This PR aims to address his case by changing the contract of getPath and return the result of the STAT call instead of a generic error, so we can check the cause. + +https://github.com/cs3org/reva/pull/1064 \ No newline at end of file From 0ef80b3c25b724d73afc3ee454df42c6aa1509b8 Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Mon, 10 Aug 2020 11:42:49 +0200 Subject: [PATCH 06/17] fix move1 --- internal/grpc/services/gateway/storageprovider.go | 4 ++-- internal/http/services/owncloud/ocdav/move.go | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/internal/grpc/services/gateway/storageprovider.go b/internal/grpc/services/gateway/storageprovider.go index 5d6c3bf5c4..d83b75ca05 100644 --- a/internal/grpc/services/gateway/storageprovider.go +++ b/internal/grpc/services/gateway/storageprovider.go @@ -660,8 +660,8 @@ func (s *svc) Move(ctx context.Context, req *provider.MoveRequest) (*provider.Mo }, nil } - dp, err := s.getPath(ctx, req.Destination) - if err != nil { + dp, st2 := s.getPath(ctx, req.Destination) + if st2.Code != rpc.Code_CODE_OK { return &provider.MoveResponse{ Status: st, }, nil diff --git a/internal/http/services/owncloud/ocdav/move.go b/internal/http/services/owncloud/ocdav/move.go index bc28c9a2a6..fd919e050b 100644 --- a/internal/http/services/owncloud/ocdav/move.go +++ b/internal/http/services/owncloud/ocdav/move.go @@ -139,6 +139,7 @@ func (s *svc) handleMove(w http.ResponseWriter, r *http.Request, ns string) { // TODO return a forbidden status if read only? if delRes.Status.Code != rpc.Code_CODE_OK { + log.Error().Err(err).Str("move_request", delRes.Status.Code.String()).Msg("error handling delete request") w.WriteHeader(http.StatusInternalServerError) return } @@ -179,9 +180,11 @@ func (s *svc) handleMove(w http.ResponseWriter, r *http.Request, ns string) { } if mRes.Status.Code != rpc.Code_CODE_OK { + log.Error().Err(err).Str("move_request", mRes.Status.Code.String()).Msg("error handling move request") w.WriteHeader(http.StatusInternalServerError) return } + log.Info().Str("move", mRes.Status.Code.String()).Msg("move request status") dstStatRes, err = client.Stat(ctx, dstStatReq) if err != nil { @@ -191,6 +194,7 @@ func (s *svc) handleMove(w http.ResponseWriter, r *http.Request, ns string) { } if dstStatRes.Status.Code != rpc.Code_CODE_OK { + log.Error().Err(err).Str("status", dstStatRes.Status.Code.String()).Msg("error doing stat") w.WriteHeader(http.StatusInternalServerError) return } From 79c6a59cb4e08b85d0aa797907504169048acb2d Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Mon, 10 Aug 2020 13:20:28 +0200 Subject: [PATCH 07/17] test using testFixOCISPR409 --- .drone.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.drone.yml b/.drone.yml index 16a4274c5d..5cfcb3b876 100644 --- a/.drone.yml +++ b/.drone.yml @@ -341,9 +341,8 @@ steps: image: owncloudci/php:7.2 commands: - git clone -b master --depth=1 https://github.com/owncloud/testing.git /drone/src/tmp/testing - - git clone -b master --single-branch --no-tags https://github.com/owncloud/core.git /drone/src/tmp/testrunner + - git clone -b testFixOCISPR409 --single-branch --no-tags https://github.com/owncloud/core.git /drone/src/tmp/testrunner - cd /drone/src/tmp/testrunner - - git checkout 9ebf886779b98fc3f78e11cf138246f80d5cab39 - make test-acceptance-api environment: TEST_SERVER_URL: 'http://revad-services:20080' From d6f059f0fee107fcf0773205dfb4d2c21cb6c316 Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Mon, 10 Aug 2020 15:21:22 +0200 Subject: [PATCH 08/17] use reva-tests branch --- .drone.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.drone.yml b/.drone.yml index 2923dbbddf..088cc9c6bd 100644 --- a/.drone.yml +++ b/.drone.yml @@ -342,7 +342,7 @@ steps: image: owncloudci/php:7.2 commands: - git clone -b master --depth=1 https://github.com/owncloud/testing.git /drone/src/tmp/testing - - git clone -b testFixOCISPR409 --single-branch --no-tags https://github.com/owncloud/core.git /drone/src/tmp/testrunner + - git clone -b reva-tests --single-branch --no-tags https://github.com/owncloud/core.git /drone/src/tmp/testrunner - cd /drone/src/tmp/testrunner - make test-acceptance-api environment: From 26576d1a241cfa622f94f289e9609907302a066d Mon Sep 17 00:00:00 2001 From: Alex Unger Date: Tue, 11 Aug 2020 13:43:30 +0200 Subject: [PATCH 09/17] make getPath deal with out of sync cached values --- pkg/storage/fs/owncloud/owncloud.go | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/pkg/storage/fs/owncloud/owncloud.go b/pkg/storage/fs/owncloud/owncloud.go index a44f46263c..b229a3ff72 100644 --- a/pkg/storage/fs/owncloud/owncloud.go +++ b/pkg/storage/fs/owncloud/owncloud.go @@ -688,14 +688,32 @@ func readOrCreateID(ctx context.Context, np string, conn redis.Conn) string { } func (fs *ocfs) getPath(ctx context.Context, id *provider.ResourceId) (string, error) { + log := appctx.GetLogger(ctx) c := fs.pool.Get() defer c.Close() fs.scanFiles(ctx, c) np, err := redis.String(c.Do("GET", id.OpaqueId)) if err != nil { - appctx.GetLogger(ctx).Error().Err(err).Interface("id", id).Msg("error looking up fileid") - return "", err + return "", errtypes.NotFound(id.OpaqueId) + } + + idFromXattr, err := xattr.Get(np, idAttribute) + if err != nil { + return "", errtypes.NotFound(id.OpaqueId) + } + + uid, err := uuid.FromBytes(idFromXattr) + if err != nil { + log.Error().Err(err).Msg("error parsing uuid") + } + + if uid.String() != id.OpaqueId { + if _, err := c.Do("DEL", id.OpaqueId); err != nil { + return "", err + } + return "", errtypes.NotFound(id.OpaqueId) } + return np, nil } @@ -1490,6 +1508,9 @@ func (fs *ocfs) Move(ctx context.Context, oldRef, newRef *provider.Reference) (e func (fs *ocfs) GetMD(ctx context.Context, ref *provider.Reference, mdKeys []string) (*provider.ResourceInfo, error) { np, err := fs.resolve(ctx, ref) if err != nil { + if _, ok := err.(errtypes.IsNotFound); ok { + return nil, err + } return nil, errors.Wrap(err, "ocfs: error resolving reference") } p := fs.unwrap(ctx, np) From 391ad658358f552da32d041362472b09170d7c86 Mon Sep 17 00:00:00 2001 From: Alex Unger Date: Tue, 11 Aug 2020 16:19:45 +0200 Subject: [PATCH 10/17] add changelog Signed-off-by: A.Unger --- changelog/unreleased/ignore-stray-shares.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 changelog/unreleased/ignore-stray-shares.md diff --git a/changelog/unreleased/ignore-stray-shares.md b/changelog/unreleased/ignore-stray-shares.md new file mode 100644 index 0000000000..c7172283d0 --- /dev/null +++ b/changelog/unreleased/ignore-stray-shares.md @@ -0,0 +1,5 @@ +Bugfix: Ensure ignoring stray shares + +When using the json shares manager, it can be the case we found a share with a resource_id that no longer exists. This PR aims to address his case by changing the contract of getPath and return the result of the STAT call instead of a generic error, so we can check the cause. + +https://github.com/cs3org/reva/pull/1064 \ No newline at end of file From 8dc7c9088044028ba53e2f641d389c0c1b22c754 Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Wed, 12 Aug 2020 10:20:39 +0200 Subject: [PATCH 11/17] update drone commit --- .drone.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.drone.yml b/.drone.yml index 1ff1b33d8c..79a033b1c6 100644 --- a/.drone.yml +++ b/.drone.yml @@ -344,7 +344,7 @@ steps: - git clone -b master --depth=1 https://github.com/owncloud/testing.git /drone/src/tmp/testing - git clone -b master --single-branch --no-tags https://github.com/owncloud/core.git /drone/src/tmp/testrunner - cd /drone/src/tmp/testrunner - - git checkout 5d8d76600f451b985662024f730cee1a40444c7f + - git checkout ee50968dbf7dee50737cd3f4e67a527a1e2fbc94 - name: localAPIAcceptanceTestsOcStorage image: owncloudci/php:7.2 From 7dc3bd505d0dbae573f3f3fdeee51a01005655f3 Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Wed, 12 Aug 2020 10:26:24 +0200 Subject: [PATCH 12/17] Revert "update drone commit" This reverts commit 8dc7c9088044028ba53e2f641d389c0c1b22c754. --- .drone.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.drone.yml b/.drone.yml index 79a033b1c6..1ff1b33d8c 100644 --- a/.drone.yml +++ b/.drone.yml @@ -344,7 +344,7 @@ steps: - git clone -b master --depth=1 https://github.com/owncloud/testing.git /drone/src/tmp/testing - git clone -b master --single-branch --no-tags https://github.com/owncloud/core.git /drone/src/tmp/testrunner - cd /drone/src/tmp/testrunner - - git checkout ee50968dbf7dee50737cd3f4e67a527a1e2fbc94 + - git checkout 5d8d76600f451b985662024f730cee1a40444c7f - name: localAPIAcceptanceTestsOcStorage image: owncloudci/php:7.2 From 1b1b91000ceb982d30c4a279b1017a07e096a28c Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Wed, 12 Aug 2020 15:05:20 +0200 Subject: [PATCH 13/17] copy feature over from core --- ...piShareManagementBasic-createShare.feature | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/tests/acceptance/features/apiOcisSpecific/apiShareManagementBasic-createShare.feature b/tests/acceptance/features/apiOcisSpecific/apiShareManagementBasic-createShare.feature index a4b6a73e74..08465b86f4 100644 --- a/tests/acceptance/features/apiOcisSpecific/apiShareManagementBasic-createShare.feature +++ b/tests/acceptance/features/apiOcisSpecific/apiShareManagementBasic-createShare.feature @@ -84,7 +84,6 @@ Feature: sharing | 2 | 200 | @issue-ocis-reva-372 @issue-ocis-reva-243 - # after fixing all issues delete this Scenario and use the one from oC10 core Scenario Outline: sharing subfolder of already shared folder, GET result is correct Given using OCS API version "" And these users have been created with default attributes and without skeleton files: @@ -101,17 +100,15 @@ Feature: sharing And user "Alice" has shared folder "/folder1/folder2" with user "Emily" When user "Alice" sends HTTP method "GET" to OCS API endpoint "/apps/files_sharing/api/v1/shares" Then the OCS status code should be "" - And the HTTP status code should be "" - # On OCIS and reva the response is currently not there -# And the response should contain 4 entries -# And folder "/folder1" should be included as path in the response -# And folder "/folder1/folder2" should be included as path in the response + And the HTTP status code should be "200" + And the response should contain 4 entries + And folder "/folder1" should be included as path in the response + And folder "/folder1/folder2" should be included as path in the response And user "Alice" sends HTTP method "GET" to OCS API endpoint "/apps/files_sharing/api/v1/shares?path=/folder1/folder2" And the response should contain 2 entries And folder "/folder1" should not be included as path in the response - And folder "/folder2" should be included as path in the response -# And folder "/folder1/folder2" should be included as path in the response + And folder "/folder1/folder2" should be included as path in the response Examples: - | ocs_api_version | http_status_code | ocs_status_code | - | 1 | 200 | 996 | - | 2 | 500 | 996 | + | ocs_api_version | ocs_status_code | + | 1 | 100 | + | 2 | 200 | \ No newline at end of file From 2489aad9b7ea0e0eef9c0691c47373cf13d0836b Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Wed, 12 Aug 2020 15:16:55 +0200 Subject: [PATCH 14/17] adapt assert --- .../apiShareManagementBasic-createShare.feature | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/acceptance/features/apiOcisSpecific/apiShareManagementBasic-createShare.feature b/tests/acceptance/features/apiOcisSpecific/apiShareManagementBasic-createShare.feature index 08465b86f4..e2c35653c5 100644 --- a/tests/acceptance/features/apiOcisSpecific/apiShareManagementBasic-createShare.feature +++ b/tests/acceptance/features/apiOcisSpecific/apiShareManagementBasic-createShare.feature @@ -103,11 +103,13 @@ Feature: sharing And the HTTP status code should be "200" And the response should contain 4 entries And folder "/folder1" should be included as path in the response - And folder "/folder1/folder2" should be included as path in the response + # And folder "/folder1/folder2" should be included as path in the response + And folder "/folder2" should be included as path in the response And user "Alice" sends HTTP method "GET" to OCS API endpoint "/apps/files_sharing/api/v1/shares?path=/folder1/folder2" And the response should contain 2 entries And folder "/folder1" should not be included as path in the response - And folder "/folder1/folder2" should be included as path in the response + # And folder "/folder1/folder2" should be included as path in the response + And folder "/folder2" should be included as path in the response Examples: | ocs_api_version | ocs_status_code | | 1 | 100 | From 5a104dfb48ec2a83b4f1d55e248b0411d7b0d10c Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Wed, 12 Aug 2020 16:02:50 +0200 Subject: [PATCH 15/17] add expected failures on owncloud/core to the list of expected failures --- changelog/unreleased/ensure-stray-shares.md | 5 ----- tests/acceptance/expected-failures.txt | 6 +++++- 2 files changed, 5 insertions(+), 6 deletions(-) delete mode 100644 changelog/unreleased/ensure-stray-shares.md diff --git a/changelog/unreleased/ensure-stray-shares.md b/changelog/unreleased/ensure-stray-shares.md deleted file mode 100644 index fd4fc42b90..0000000000 --- a/changelog/unreleased/ensure-stray-shares.md +++ /dev/null @@ -1,5 +0,0 @@ -Bugfix: Ensure stray shares get ignored - -When using the json shares manager, it can be the case we found a share with a resource_id that no longer exists. This PR aims to address his case by changing the contract of getPath and return the result of the STAT call instead of a generic error, so we can check the cause. - -https://github.com/cs3org/reva/pull/1064 \ No newline at end of file diff --git a/tests/acceptance/expected-failures.txt b/tests/acceptance/expected-failures.txt index 5b9dedd4bb..d59dc18172 100644 --- a/tests/acceptance/expected-failures.txt +++ b/tests/acceptance/expected-failures.txt @@ -900,7 +900,7 @@ apiWebdavUpload2/uploadFileUsingNewChunking.feature:137 apiWebdavUpload2/uploadFileUsingNewChunking.feature:157 apiWebdavUpload2/uploadFileUsingNewChunking.feature:158 # -# https://github.com/owncloud/ocis-reva/issues/17 uploading with old-chunking does not work +# https://github.com/owncloud/ocis-reva/issues/17 uploading with old-chunking does not work apiWebdavUpload2/uploadFileUsingOldChunking.feature:13 apiWebdavUpload2/uploadFileUsingOldChunking.feature:26 apiWebdavUpload2/uploadFileUsingOldChunking.feature:35 @@ -912,3 +912,7 @@ apiWebdavUpload2/uploadFileUsingOldChunking.feature:98 apiWebdavUpload2/uploadFileUsingOldChunking.feature:99 apiWebdavUpload2/uploadFileUsingOldChunking.feature:100 apiWebdavUpload2/uploadFileUsingOldChunking.feature:101 +# +# https://github.com/owncloud/ocis-reva/issues/372 Listing shares via ocs API does not show path for parent folders +apiShareManagementBasic/createShare.feature:269 +apiShareManagementBasic/createShare.feature:270 \ No newline at end of file From ee3bf316ac79ecee4d26fdf2719d022da296445d Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Wed, 12 Aug 2020 16:20:29 +0200 Subject: [PATCH 16/17] re-add missing comment --- .../apiOcisSpecific/apiShareManagementBasic-createShare.feature | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/acceptance/features/apiOcisSpecific/apiShareManagementBasic-createShare.feature b/tests/acceptance/features/apiOcisSpecific/apiShareManagementBasic-createShare.feature index e2c35653c5..998e370762 100644 --- a/tests/acceptance/features/apiOcisSpecific/apiShareManagementBasic-createShare.feature +++ b/tests/acceptance/features/apiOcisSpecific/apiShareManagementBasic-createShare.feature @@ -84,6 +84,7 @@ Feature: sharing | 2 | 200 | @issue-ocis-reva-372 @issue-ocis-reva-243 + # after fixing all issues delete this Scenario and use the one from oC10 core Scenario Outline: sharing subfolder of already shared folder, GET result is correct Given using OCS API version "" And these users have been created with default attributes and without skeleton files: From b00e51f216381bbf51227445b054fcb298a2b7f4 Mon Sep 17 00:00:00 2001 From: "A.Unger" Date: Wed, 12 Aug 2020 16:30:45 +0200 Subject: [PATCH 17/17] =?UTF-8?q?get=20rid=20of=20expected=20failures=20(?= =?UTF-8?q?=E2=95=AF=C2=B0=E2=96=A1=C2=B0=EF=BC=89=E2=95=AF=EF=B8=B5=20?= =?UTF-8?q?=E2=94=BB=E2=94=81=E2=94=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tests/acceptance/expected-failures.txt | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/tests/acceptance/expected-failures.txt b/tests/acceptance/expected-failures.txt index d59dc18172..02d7f75f55 100644 --- a/tests/acceptance/expected-failures.txt +++ b/tests/acceptance/expected-failures.txt @@ -911,8 +911,4 @@ apiWebdavUpload2/uploadFileUsingOldChunking.feature:97 apiWebdavUpload2/uploadFileUsingOldChunking.feature:98 apiWebdavUpload2/uploadFileUsingOldChunking.feature:99 apiWebdavUpload2/uploadFileUsingOldChunking.feature:100 -apiWebdavUpload2/uploadFileUsingOldChunking.feature:101 -# -# https://github.com/owncloud/ocis-reva/issues/372 Listing shares via ocs API does not show path for parent folders -apiShareManagementBasic/createShare.feature:269 -apiShareManagementBasic/createShare.feature:270 \ No newline at end of file +apiWebdavUpload2/uploadFileUsingOldChunking.feature:101 \ No newline at end of file