From 698dd2b2a3fbf6d08a4896bb63c28f57c84bdf59 Mon Sep 17 00:00:00 2001 From: David Christofas Date: Fri, 13 Aug 2021 14:35:08 +0200 Subject: [PATCH] first draft for removing references of declined shares --- .../grpc/services/gateway/storageprovider.go | 11 ++++-- .../services/gateway/usershareprovider.go | 16 +++++++- .../storageprovider/storageprovider.go | 37 ++++++++++++++++--- .../handlers/apps/sharing/shares/pending.go | 1 + pkg/storage/fs/owncloud/owncloud.go | 4 ++ pkg/storage/fs/owncloudsql/owncloudsql.go | 4 ++ pkg/storage/fs/s3/s3.go | 4 ++ pkg/storage/storage.go | 1 + .../utils/decomposedfs/decomposedfs.go | 28 ++++++++++++++ pkg/storage/utils/eosfs/eosfs.go | 4 ++ pkg/storage/utils/localfs/localfs.go | 4 ++ 11 files changed, 102 insertions(+), 12 deletions(-) diff --git a/internal/grpc/services/gateway/storageprovider.go b/internal/grpc/services/gateway/storageprovider.go index 1464954fe66..8f8d7a73673 100644 --- a/internal/grpc/services/gateway/storageprovider.go +++ b/internal/grpc/services/gateway/storageprovider.go @@ -920,13 +920,16 @@ func (s *svc) Delete(ctx context.Context, req *provider.DeleteRequest) (*provide if err != nil { return nil, err } + + return &provider.DeleteResponse{ + Status: status.NewOK(ctx), + }, nil } } - ref := &provider.Reference{Path: p} - - req.Ref = ref - return s.delete(ctx, req) + return &provider.DeleteResponse{ + Status: status.NewNotFound(ctx, "could not find share"), + }, nil } if s.isShareChild(ctx, p) { diff --git a/internal/grpc/services/gateway/usershareprovider.go b/internal/grpc/services/gateway/usershareprovider.go index a1bc98ad0e7..50ba7d0b27b 100644 --- a/internal/grpc/services/gateway/usershareprovider.go +++ b/internal/grpc/services/gateway/usershareprovider.go @@ -26,6 +26,7 @@ import ( rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" collaboration "github.com/cs3org/go-cs3apis/cs3/sharing/collaboration/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" + typesv1beta1 "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" "github.com/cs3org/reva/pkg/appctx" "github.com/cs3org/reva/pkg/errtypes" "github.com/cs3org/reva/pkg/rgrpc/status" @@ -127,6 +128,8 @@ func (s *svc) RemoveShare(ctx context.Context, req *collaboration.RemoveShareReq return nil, errors.Wrap(err, "gateway: error calling RemoveShare") } + s.createReference(ctx, share.ResourceId, "true") + // if we don't need to commit we return earlier if !s.c.CommitShareToStorageGrant && !s.c.CommitShareToStorageRef { return res, nil @@ -316,7 +319,7 @@ func (s *svc) UpdateReceivedShare(ctx context.Context, req *collaboration.Update if share == nil { panic("gateway: error updating a received share: the share is nil") } - createRefStatus := s.createReference(ctx, share.Share.ResourceId) + createRefStatus := s.createReference(ctx, share.Share.ResourceId, "false") rsp := &collaboration.UpdateReceivedShareResponse{Status: createRefStatus} if createRefStatus.Code == rpc.Code_CODE_OK { @@ -325,6 +328,7 @@ func (s *svc) UpdateReceivedShare(ctx context.Context, req *collaboration.Update return rsp, nil } else if req.Field.GetState() == collaboration.ShareState_SHARE_STATE_REJECTED { // Nothing more to do, return the original result + s.createReference(ctx, res.Share.Share.ResourceId, "true") return res, nil } } @@ -336,7 +340,7 @@ func (s *svc) UpdateReceivedShare(ctx context.Context, req *collaboration.Update }, nil } -func (s *svc) createReference(ctx context.Context, resourceID *provider.ResourceId) *rpc.Status { +func (s *svc) createReference(ctx context.Context, resourceID *provider.ResourceId, delete string) *rpc.Status { ref := &provider.Reference{ ResourceId: resourceID, } @@ -386,6 +390,14 @@ func (s *svc) createReference(ctx context.Context, resourceID *provider.Resource log.Info().Msg("mount path will be:" + refPath) createRefReq := &provider.CreateReferenceRequest{ + Opaque: &typesv1beta1.Opaque{ + Map: map[string]*typesv1beta1.OpaqueEntry{ + "delete": { + Decoder: "plain", + Value: []byte(delete), + }, + }, + }, Ref: &provider.Reference{Path: refPath}, // cs3 is the Scheme and %s/%s is the Opaque parts of a net.URL. TargetUri: fmt.Sprintf("cs3:%s/%s", resourceID.GetStorageId(), resourceID.GetOpaqueId()), diff --git a/internal/grpc/services/storageprovider/storageprovider.go b/internal/grpc/services/storageprovider/storageprovider.go index 87d280a07a3..d1980901753 100644 --- a/internal/grpc/services/storageprovider/storageprovider.go +++ b/internal/grpc/services/storageprovider/storageprovider.go @@ -1130,19 +1130,44 @@ func (s *service) RemoveGrant(ctx context.Context, req *provider.RemoveGrantRequ func (s *service) CreateReference(ctx context.Context, req *provider.CreateReferenceRequest) (*provider.CreateReferenceResponse, error) { log := appctx.GetLogger(ctx) - // parse uri is valid - u, err := url.Parse(req.TargetUri) + newRef, err := s.unwrap(ctx, req.Ref) if err != nil { - log.Err(err).Msg("invalid target uri") return &provider.CreateReferenceResponse{ - Status: status.NewInvalidArg(ctx, "target uri is invalid: "+err.Error()), + Status: status.NewInternal(ctx, err, "error unwrapping path"), }, nil } - newRef, err := s.unwrap(ctx, req.Ref) + if req.Opaque != nil { + opaque := req.Opaque + if entry, ok := opaque.Map["delete"]; ok { + if string(entry.Value) == "true" { + if err := s.storage.RemoveReference(ctx, newRef.Path); err != nil { + var st *rpc.Status + switch err.(type) { + case errtypes.IsNotFound: + st = status.NewNotFound(ctx, "path not found when creating reference") + case errtypes.PermissionDenied: + st = status.NewPermissionDenied(ctx, err, "permission denied") + default: + st = status.NewInternal(ctx, err, "error creating reference") + } + return &provider.CreateReferenceResponse{ + Status: st, + }, nil + } + return &provider.CreateReferenceResponse{ + Status: status.NewOK(ctx), + }, nil + } + } + } + + // parse uri is valid + u, err := url.Parse(req.TargetUri) if err != nil { + log.Err(err).Msg("invalid target uri") return &provider.CreateReferenceResponse{ - Status: status.NewInternal(ctx, err, "error unwrapping path"), + Status: status.NewInvalidArg(ctx, "target uri is invalid: "+err.Error()), }, nil } diff --git a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/pending.go b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/pending.go index 33636f32271..2bbc02b1e1b 100644 --- a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/pending.go +++ b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/pending.go @@ -103,6 +103,7 @@ func (h *Handler) updateReceivedShare(w http.ResponseWriter, r *http.Request, sh // Needed because received shares can be jailed in a folder in the users home data.FileTarget = path.Join(h.sharePrefix, path.Base(info.Path)) data.Path = path.Join(h.sharePrefix, path.Base(info.Path)) + data.StorageID = "shared::" + data.Path } response.WriteOCSSuccess(w, r, []*conversions.ShareData{data}) diff --git a/pkg/storage/fs/owncloud/owncloud.go b/pkg/storage/fs/owncloud/owncloud.go index 8eba17ca410..a861dfe79b8 100644 --- a/pkg/storage/fs/owncloud/owncloud.go +++ b/pkg/storage/fs/owncloud/owncloud.go @@ -1214,6 +1214,10 @@ func (fs *ocfs) CreateReference(ctx context.Context, sp string, targetURI *url.U return nil } +func (fs *ocfs) RemoveReference(ctx context.Context, path string) error { + return nil +} + func (fs *ocfs) setMtime(ctx context.Context, ip string, mtime string) error { log := appctx.GetLogger(ctx) if mt, err := parseMTime(mtime); err == nil { diff --git a/pkg/storage/fs/owncloudsql/owncloudsql.go b/pkg/storage/fs/owncloudsql/owncloudsql.go index e2a8539c639..7a6347ffbbe 100644 --- a/pkg/storage/fs/owncloudsql/owncloudsql.go +++ b/pkg/storage/fs/owncloudsql/owncloudsql.go @@ -764,6 +764,10 @@ func (fs *owncloudsqlfs) CreateReference(ctx context.Context, sp string, targetU return errtypes.NotSupported("owncloudsql: operation not supported") } +func (fs *owncloudsqlfs) RemoveReference(ctx context.Context, path string) error { + return nil +} + func (fs *owncloudsqlfs) setMtime(ctx context.Context, ip string, mtime string) error { log := appctx.GetLogger(ctx) if mt, err := parseMTime(mtime); err == nil { diff --git a/pkg/storage/fs/s3/s3.go b/pkg/storage/fs/s3/s3.go index eaf717562aa..0679735c167 100644 --- a/pkg/storage/fs/s3/s3.go +++ b/pkg/storage/fs/s3/s3.go @@ -285,6 +285,10 @@ func (fs *s3FS) CreateReference(ctx context.Context, path string, targetURI *url return errtypes.NotSupported("s3: operation not supported") } +func (fs *s3FS) RemoveReference(ctx context.Context, path string) error { + return nil +} + func (fs *s3FS) GetHome(ctx context.Context) (string, error) { return "", errtypes.NotSupported("eos: not supported") } diff --git a/pkg/storage/storage.go b/pkg/storage/storage.go index 1b65c30fddb..bacb3ee0113 100644 --- a/pkg/storage/storage.go +++ b/pkg/storage/storage.go @@ -54,6 +54,7 @@ type FS interface { ListGrants(ctx context.Context, ref *provider.Reference) ([]*provider.Grant, error) GetQuota(ctx context.Context) (uint64, uint64, error) CreateReference(ctx context.Context, path string, targetURI *url.URL) error + RemoveReference(ctx context.Context, path string) error Shutdown(ctx context.Context) error SetArbitraryMetadata(ctx context.Context, ref *provider.Reference, md *provider.ArbitraryMetadata) error UnsetArbitraryMetadata(ctx context.Context, ref *provider.Reference, keys []string) error diff --git a/pkg/storage/utils/decomposedfs/decomposedfs.go b/pkg/storage/utils/decomposedfs/decomposedfs.go index d851323f859..95175a0aca2 100644 --- a/pkg/storage/utils/decomposedfs/decomposedfs.go +++ b/pkg/storage/utils/decomposedfs/decomposedfs.go @@ -371,6 +371,34 @@ func (fs *Decomposedfs) CreateReference(ctx context.Context, p string, targetURI return nil } +// RemoveReference removes a reference from the users home +func (fs *Decomposedfs) RemoveReference(ctx context.Context, path string) (err error) { + path = strings.Trim(path, "/") + parts := strings.Split(path, "/") + + if len(parts) != 2 { + return errtypes.PermissionDenied("Decomposedfs: references must be a child of the share folder: share_folder=" + fs.o.ShareFolder + " path=" + path) + } else if parts[0] != strings.Trim(fs.o.ShareFolder, "/") { + return errtypes.PermissionDenied("Decomposedfs: cannot create references outside the share folder: share_folder=" + fs.o.ShareFolder + " path=" + path) + } + + var n *node.Node + if n, err = fs.lu.NodeFromPath(ctx, fs.o.ShareFolder); err != nil { + return errtypes.InternalError(err.Error()) + } else if !n.Exists { + return nil + } + + if n, err = n.Child(ctx, parts[1]); err != nil { + return errtypes.InternalError(err.Error()) + } else if !n.Exists { + // TODO append increasing number to mountpoint name + return errtypes.NotFound(path) + } + + return fs.tp.Delete(ctx, n) +} + // Move moves a resource from one reference to another func (fs *Decomposedfs) Move(ctx context.Context, oldRef, newRef *provider.Reference) (err error) { var oldNode, newNode *node.Node diff --git a/pkg/storage/utils/eosfs/eosfs.go b/pkg/storage/utils/eosfs/eosfs.go index 73b66c9b71e..e0af59e5069 100644 --- a/pkg/storage/utils/eosfs/eosfs.go +++ b/pkg/storage/utils/eosfs/eosfs.go @@ -1232,6 +1232,10 @@ func (fs *eosfs) CreateReference(ctx context.Context, p string, targetURI *url.U return nil } +func (fs *eosfs) RemoveReference(ctx context.Context, path string) (err error) { + return nil +} + func (fs *eosfs) Delete(ctx context.Context, ref *provider.Reference) error { p, err := fs.resolve(ctx, ref) if err != nil { diff --git a/pkg/storage/utils/localfs/localfs.go b/pkg/storage/utils/localfs/localfs.go index 2af306dde08..b8205a4d0ca 100644 --- a/pkg/storage/utils/localfs/localfs.go +++ b/pkg/storage/utils/localfs/localfs.go @@ -564,6 +564,10 @@ func (fs *localfs) CreateReference(ctx context.Context, path string, targetURI * return fs.propagate(ctx, fn) } +func (fs *localfs) RemoveReference(ctx context.Context, path string) error { + return nil +} + func (fs *localfs) SetArbitraryMetadata(ctx context.Context, ref *provider.Reference, md *provider.ArbitraryMetadata) error { np, err := fs.resolve(ctx, ref)