From 1f012ac9b5fc60c0796ec61495a3d3f45a39df92 Mon Sep 17 00:00:00 2001 From: Florian Schade Date: Thu, 13 Jun 2024 15:21:33 +0200 Subject: [PATCH] enhancement: bump reva and remove unnecessary explicit automount mount point naming --- changelog/unreleased/bump-reva.md | 1 + go.mod | 2 +- go.sum | 4 +- services/frontend/pkg/command/events.go | 103 +--------- .../usershareprovider/usershareprovider.go | 185 +++++++++++++++--- .../handlers/apps/sharing/shares/pending.go | 111 +++-------- .../storage/fs/posix/blobstore/blobstore.go | 3 +- vendor/modules.txt | 2 +- 8 files changed, 203 insertions(+), 208 deletions(-) diff --git a/changelog/unreleased/bump-reva.md b/changelog/unreleased/bump-reva.md index bbae000324..ee203b6bdd 100644 --- a/changelog/unreleased/bump-reva.md +++ b/changelog/unreleased/bump-reva.md @@ -2,6 +2,7 @@ Enhancement: Bump Reva bumps reva version +https://github.com/owncloud/ocis/pull/9377 https://github.com/owncloud/ocis/pull/9330 https://github.com/owncloud/ocis/pull/9318 https://github.com/owncloud/ocis/pull/9269 diff --git a/go.mod b/go.mod index 5b896ef28a..4b0048bab5 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( github.com/cenkalti/backoff v2.2.1+incompatible github.com/coreos/go-oidc/v3 v3.10.0 github.com/cs3org/go-cs3apis v0.0.0-20231023073225-7748710e0781 - github.com/cs3org/reva/v2 v2.19.2-0.20240607120909-0a9c7b8bef6a + github.com/cs3org/reva/v2 v2.19.2-0.20240613123928-7fb5f11a24cf github.com/dhowden/tag v0.0.0-20230630033851-978a0926ee25 github.com/dutchcoders/go-clamd v0.0.0-20170520113014-b970184f4d9e github.com/egirna/icap-client v0.1.1 diff --git a/go.sum b/go.sum index 70964522b4..314807368e 100644 --- a/go.sum +++ b/go.sum @@ -1025,8 +1025,8 @@ github.com/crewjam/saml v0.4.14 h1:g9FBNx62osKusnFzs3QTN5L9CVA/Egfgm+stJShzw/c= github.com/crewjam/saml v0.4.14/go.mod h1:UVSZCf18jJkk6GpWNVqcyQJMD5HsRugBPf4I1nl2mME= github.com/cs3org/go-cs3apis v0.0.0-20231023073225-7748710e0781 h1:BUdwkIlf8IS2FasrrPg8gGPHQPOrQ18MS1Oew2tmGtY= github.com/cs3org/go-cs3apis v0.0.0-20231023073225-7748710e0781/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY= -github.com/cs3org/reva/v2 v2.19.2-0.20240607120909-0a9c7b8bef6a h1:D1Pg9i+pZhzn/h5397/ukX0XYYPBaUVLh6Zhe83vKUg= -github.com/cs3org/reva/v2 v2.19.2-0.20240607120909-0a9c7b8bef6a/go.mod h1:lKqw0VuP1NcZbhj0e6tGoAGq3tgWO/pLafVJyDK0yVI= +github.com/cs3org/reva/v2 v2.19.2-0.20240613123928-7fb5f11a24cf h1:AQLf+bZfcEn4zKQiH5vLtBpOx7onvbCQ4Z9X4i6SKNM= +github.com/cs3org/reva/v2 v2.19.2-0.20240613123928-7fb5f11a24cf/go.mod h1:Rb2XnhpGKnH7k6WBFZlMygbyBxW6ma09Z4Uk+ro0v+A= github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= diff --git a/services/frontend/pkg/command/events.go b/services/frontend/pkg/command/events.go index b7cb4b6217..430b90dd15 100644 --- a/services/frontend/pkg/command/events.go +++ b/services/frontend/pkg/command/events.go @@ -4,16 +4,14 @@ import ( "context" "errors" "fmt" - "path" - "path/filepath" - "slices" - "strconv" - "strings" "github.com/cs3org/reva/v2/pkg/events" "github.com/cs3org/reva/v2/pkg/events/stream" "github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool" "github.com/cs3org/reva/v2/pkg/utils" + "go-micro.dev/v4/metadata" + "google.golang.org/protobuf/types/known/fieldmaskpb" + "github.com/owncloud/ocis/v2/ocis-pkg/log" "github.com/owncloud/ocis/v2/ocis-pkg/middleware" "github.com/owncloud/ocis/v2/ocis-pkg/registry" @@ -21,15 +19,13 @@ import ( "github.com/owncloud/ocis/v2/ocis-pkg/tracing" "github.com/owncloud/ocis/v2/services/frontend/pkg/config" "github.com/owncloud/ocis/v2/services/settings/pkg/store/defaults" - "go-micro.dev/v4/metadata" - "google.golang.org/protobuf/types/known/fieldmaskpb" gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1" group "github.com/cs3org/go-cs3apis/cs3/identity/group/v1beta1" user "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" 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" + settingssvc "github.com/owncloud/ocis/v2/protogen/gen/ocis/services/settings/v0" ) @@ -116,41 +112,23 @@ func AutoAcceptShares(ev events.ShareCreated, autoAcceptDefault bool, l log.Logg return } - uids, err := getUserIDs(ctx, gatewaySelector, ev.GranteeUserID, ev.GranteeGroupID) + userIDs, err := getUserIDs(ctx, gatewaySelector, ev.GranteeUserID, ev.GranteeGroupID) if err != nil { l.Error().Err(err).Msg("cannot get grantees") return } - gwc, err = gatewaySelector.Next() - if err != nil { - l.Error().Err(err).Msg("cannot get gateway client") - return - } - info, err := utils.GetResourceByID(ctx, ev.ItemID, gwc) - if err != nil { - l.Error().Err(err).Msg("error getting resource") - return - } - - for _, uid := range uids { + for _, uid := range userIDs { if !autoAcceptShares(ctx, uid, autoAcceptDefault, vs) { continue } - mp, err := getMountPoint(ctx, l, ev.ItemID, uid, gatewaySelector, info) - if err != nil { - l.Error().Err(err).Msg("error getting mount point") - continue - - } - gwc, err := gatewaySelector.Next() if err != nil { l.Error().Err(err).Msg("cannot get gateway client") continue } - resp, err := gwc.UpdateReceivedShare(ctx, updateShareRequest(ev.ShareID, uid, mp)) + resp, err := gwc.UpdateReceivedShare(ctx, updateShareRequest(ev.ShareID, uid)) if err != nil { l.Error().Err(err).Msg("error sending grpc request") continue @@ -163,66 +141,6 @@ func AutoAcceptShares(ev events.ShareCreated, autoAcceptDefault bool, l log.Logg } -func getMountPoint(ctx context.Context, l log.Logger, itemid *provider.ResourceId, uid *user.UserId, gatewaySelector pool.Selectable[gateway.GatewayAPIClient], info *provider.ResourceInfo) (string, error) { - lrs, err := getSharesList(ctx, gatewaySelector, uid) - if err != nil { - return "", err - } - - // we need to sort the received shares by mount point in order to make things easier to evaluate. - base := path.Base(info.GetPath()) - mount := base - mounts := make([]string, 0, len(lrs.Shares)) - var exists bool - - for _, s := range lrs.Shares { - if s.State != collaboration.ShareState_SHARE_STATE_ACCEPTED { - // we don't care about unaccepted shares - continue - } - - if utils.ResourceIDEqual(s.GetShare().GetResourceId(), itemid) { - // a share to the same resource already exists and is mounted - return s.GetMountPoint().GetPath(), nil - } - - if s.GetMountPoint().GetPath() == mount { - // does the shared resource still exist? - gwc, err := gatewaySelector.Next() - if err != nil { - l.Error().Err(err).Msg("cannot get gateway client") - continue - } - _, err = utils.GetResourceByID(ctx, s.GetShare().GetResourceId(), gwc) - if err == nil { - exists = true - } - // TODO we could delete shares here if the stat returns code NOT FOUND ... but listening for file deletes would be better - } - // collect all mount points - mounts = append(mounts, s.GetMountPoint().GetPath()) - } - - // If the mount point really already exists, we need to insert a number into the filename - if exists { - // now we have a list of shares, we want to iterate over all of them and check for name collisions agents a mount points list - for i := 1; i <= len(mounts)+1; i++ { - ext := filepath.Ext(base) - name := strings.TrimSuffix(base, ext) - // be smart about .tar.(gz|bz) files - if strings.HasSuffix(name, ".tar") { - name = strings.TrimSuffix(name, ".tar") - ext = ".tar" + ext - } - mount = name + " (" + strconv.Itoa(i) + ")" + ext - if !slices.Contains(mounts, mount) { - return mount, nil - } - } - } - return mount, nil -} - func getUserIDs(ctx context.Context, gatewaySelector pool.Selectable[gateway.GatewayAPIClient], uid *user.UserId, gid *group.GroupId) ([]*user.UserId, error) { if uid != nil { return []*user.UserId{uid}, nil @@ -257,19 +175,16 @@ func autoAcceptShares(ctx context.Context, uid *user.UserId, defaultValue bool, return defaultValue } -func updateShareRequest(shareID *collaboration.ShareId, uid *user.UserId, path string) *collaboration.UpdateReceivedShareRequest { +func updateShareRequest(shareID *collaboration.ShareId, uid *user.UserId) *collaboration.UpdateReceivedShareRequest { return &collaboration.UpdateReceivedShareRequest{ Opaque: utils.AppendJSONToOpaque(nil, "userid", uid), Share: &collaboration.ReceivedShare{ Share: &collaboration.Share{ Id: shareID, }, - MountPoint: &provider.Reference{ - Path: path, - }, State: collaboration.ShareState_SHARE_STATE_ACCEPTED, }, - UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"state", "mount_point"}}, + UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"state"}}, } } diff --git a/vendor/github.com/cs3org/reva/v2/internal/grpc/services/usershareprovider/usershareprovider.go b/vendor/github.com/cs3org/reva/v2/internal/grpc/services/usershareprovider/usershareprovider.go index 779409faac..178c6f78d3 100644 --- a/vendor/github.com/cs3org/reva/v2/internal/grpc/services/usershareprovider/usershareprovider.go +++ b/vendor/github.com/cs3org/reva/v2/internal/grpc/services/usershareprovider/usershareprovider.go @@ -20,8 +20,11 @@ package usershareprovider import ( "context" + "path/filepath" "regexp" "slices" + "strconv" + "strings" gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1" userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" @@ -46,6 +49,12 @@ import ( "github.com/cs3org/reva/v2/pkg/utils" ) +const ( + _fieldMaskPathMountPoint = "mount_point" + _fieldMaskPathPermissions = "permissions" + _fieldMaskPathState = "state" +) + func init() { rgrpc.Register("usershareprovider", NewDefault) } @@ -407,7 +416,7 @@ func (s *service) UpdateShare(ctx context.Context, req *collaboration.UpdateShar // If this is a permissions update, check if user's permissions on the resource are sufficient to set the desired permissions var newPermissions *provider.ResourcePermissions - if slices.Contains(req.GetUpdateMask().GetPaths(), "permissions") { + if slices.Contains(req.GetUpdateMask().GetPaths(), _fieldMaskPathPermissions) { newPermissions = req.GetShare().GetPermissions().GetPermissions() } else { newPermissions = req.GetField().GetPermissions().GetPermissions() @@ -497,40 +506,170 @@ func (s *service) GetReceivedShare(ctx context.Context, req *collaboration.GetRe } func (s *service) UpdateReceivedShare(ctx context.Context, req *collaboration.UpdateReceivedShareRequest) (*collaboration.UpdateReceivedShareResponse, error) { - - if req.Share == nil { - return &collaboration.UpdateReceivedShareResponse{ - Status: status.NewInvalid(ctx, "updating requires a received share object"), - }, nil - } - if req.Share.Share == nil { - return &collaboration.UpdateReceivedShareResponse{ - Status: status.NewInvalid(ctx, "share missing"), - }, nil - } - if req.Share.Share.Id == nil { - return &collaboration.UpdateReceivedShareResponse{ - Status: status.NewInvalid(ctx, "share id missing"), - }, nil - } - if req.Share.Share.Id.OpaqueId == "" { + if req.GetShare().GetShare().GetId().GetOpaqueId() == "" { return &collaboration.UpdateReceivedShareResponse{ Status: status.NewInvalid(ctx, "share id empty"), }, nil } + isStateTransitionShareAccepted := slices.Contains(req.GetUpdateMask().GetPaths(), _fieldMaskPathState) && req.GetShare().GetState() == collaboration.ShareState_SHARE_STATE_ACCEPTED + isMountPointSet := slices.Contains(req.GetUpdateMask().GetPaths(), _fieldMaskPathMountPoint) && req.GetShare().GetMountPoint().GetPath() != "" + // we calculate a valid mountpoint only if the share should be accepted and the mount point is not set explicitly + if isStateTransitionShareAccepted && !isMountPointSet { + gatewayClient, err := s.gatewaySelector.Next() + if err != nil { + return nil, err + } + + s, err := setReceivedShareMountPoint(ctx, gatewayClient, req) + switch { + case err != nil: + fallthrough + case s.GetCode() != rpc.Code_CODE_OK: + return &collaboration.UpdateReceivedShareResponse{ + Status: s, + }, err + } + } + var uid userpb.UserId _ = utils.ReadJSONFromOpaque(req.Opaque, "userid", &uid) - share, err := s.sm.UpdateReceivedShare(ctx, req.Share, req.UpdateMask, &uid) + updatedShare, err := s.sm.UpdateReceivedShare(ctx, req.Share, req.UpdateMask, &uid) if err != nil { return &collaboration.UpdateReceivedShareResponse{ Status: status.NewInternal(ctx, "error updating received share"), }, nil } - res := &collaboration.UpdateReceivedShareResponse{ + return &collaboration.UpdateReceivedShareResponse{ Status: status.NewOK(ctx), - Share: share, - } - return res, nil + Share: updatedShare, + }, nil +} + +// GetAvailableMountpoint returns a new or existing mountpoint +func GetAvailableMountpoint(ctx context.Context, gwc gateway.GatewayAPIClient, id *provider.ResourceId, name string, userId *userpb.UserId) (string, error) { + listReceivedSharesReq := &collaboration.ListReceivedSharesRequest{} + if userId != nil { + listReceivedSharesReq.Opaque = utils.AppendJSONToOpaque(nil, "userid", userId) + } + + listReceivedSharesRes, err := gwc.ListReceivedShares(ctx, listReceivedSharesReq) + if err != nil { + return "", errtypes.InternalError("grpc list received shares request failed") + } + + if err := errtypes.NewErrtypeFromStatus(listReceivedSharesRes.GetStatus()); err != nil { + return "", err + } + + base := filepath.Clean(name) + mount := base + existingMountpoint := "" + mountedShares := make([]string, 0, len(listReceivedSharesRes.GetShares())) + var pathExists bool + + for _, s := range listReceivedSharesRes.GetShares() { + resourceIDEqual := utils.ResourceIDEqual(s.GetShare().GetResourceId(), id) + + if resourceIDEqual && s.State == collaboration.ShareState_SHARE_STATE_ACCEPTED { + // a share to the resource already exists and is mounted, remembers the mount point + _, err := utils.GetResourceByID(ctx, s.GetShare().GetResourceId(), gwc) + if err == nil { + existingMountpoint = s.GetMountPoint().GetPath() + } + } + + if s.State == collaboration.ShareState_SHARE_STATE_ACCEPTED { + // collect all accepted mount points + mountedShares = append(mountedShares, s.GetMountPoint().GetPath()) + if s.GetMountPoint().GetPath() == mount { + // does the shared resource still exist? + _, err := utils.GetResourceByID(ctx, s.GetShare().GetResourceId(), gwc) + if err == nil { + pathExists = true + } + // TODO we could delete shares here if the stat returns code NOT FOUND ... but listening for file deletes would be better + } + } + } + + if existingMountpoint != "" { + // we want to reuse the same mountpoint for all unmounted shares to the same resource + return existingMountpoint, nil + } + + // If the mount point really already exists, we need to insert a number into the filename + if pathExists { + // now we have a list of shares, we want to iterate over all of them and check for name collisions agents a mount points list + for i := 1; i <= len(mountedShares)+1; i++ { + ext := filepath.Ext(base) + name := strings.TrimSuffix(base, ext) + + mount = name + " (" + strconv.Itoa(i) + ")" + ext + if !slices.Contains(mountedShares, mount) { + return mount, nil + } + } + } + + return mount, nil +} + +func setReceivedShareMountPoint(ctx context.Context, gwc gateway.GatewayAPIClient, req *collaboration.UpdateReceivedShareRequest) (*rpc.Status, error) { + receivedShare, err := gwc.GetReceivedShare(ctx, &collaboration.GetReceivedShareRequest{ + Ref: &collaboration.ShareReference{ + Spec: &collaboration.ShareReference_Id{ + Id: req.GetShare().GetShare().GetId(), + }, + }, + }) + switch { + case err != nil: + fallthrough + case receivedShare.GetStatus().GetCode() != rpc.Code_CODE_OK: + return receivedShare.GetStatus(), err + } + + if receivedShare.GetShare().GetMountPoint().GetPath() != "" { + return status.NewOK(ctx), nil + } + + resourceStat, err := gwc.Stat(ctx, &provider.StatRequest{ + Ref: &provider.Reference{ + ResourceId: receivedShare.GetShare().GetShare().GetResourceId(), + }, + }) + switch { + case err != nil: + fallthrough + case resourceStat.GetStatus().GetCode() != rpc.Code_CODE_OK: + return resourceStat.GetStatus(), err + } + + // handle mount point related updates + { + var userID *userpb.UserId + _ = utils.ReadJSONFromOpaque(req.Opaque, "userid", &userID) + + // check if the requested mount point is available and if not, find a suitable one + availableMountpoint, err := GetAvailableMountpoint(ctx, gwc, + resourceStat.GetInfo().GetId(), + resourceStat.GetInfo().GetName(), + userID, + ) + if err != nil { + return status.NewInternal(ctx, err.Error()), nil + } + + if !slices.Contains(req.GetUpdateMask().GetPaths(), _fieldMaskPathMountPoint) { + req.GetUpdateMask().Paths = append(req.GetUpdateMask().GetPaths(), _fieldMaskPathMountPoint) + } + + req.GetShare().MountPoint = &provider.Reference{ + Path: availableMountpoint, + } + } + + return status.NewOK(ctx), nil } diff --git a/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/pending.go b/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/pending.go index 5ab1c1782c..5bfd78cd29 100644 --- a/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/pending.go +++ b/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/pending.go @@ -23,24 +23,22 @@ import ( "fmt" "net/http" "path" - "path/filepath" - "slices" "strconv" - "strings" gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1" rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" collaboration "github.com/cs3org/go-cs3apis/cs3/sharing/collaboration/v1beta1" ocmv1beta1 "github.com/cs3org/go-cs3apis/cs3/sharing/ocm/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" + "github.com/go-chi/chi/v5" + "github.com/pkg/errors" + "google.golang.org/protobuf/types/known/fieldmaskpb" + "github.com/cs3org/reva/v2/internal/http/services/owncloud/ocs/response" "github.com/cs3org/reva/v2/pkg/appctx" "github.com/cs3org/reva/v2/pkg/conversions" "github.com/cs3org/reva/v2/pkg/errtypes" "github.com/cs3org/reva/v2/pkg/utils" - "github.com/go-chi/chi/v5" - "github.com/pkg/errors" - "google.golang.org/protobuf/types/known/fieldmaskpb" ) const ( @@ -76,7 +74,7 @@ func (h *Handler) AcceptReceivedShare(w http.ResponseWriter, r *http.Request) { return } - mount, unmountedShares, err := GetMountpointAndUnmountedShares(ctx, client, sharedResource.Info) + unmountedShares, err := getUnmountedShares(ctx, client, sharedResource.GetInfo().GetId()) if err != nil { response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "could not determine mountpoint", err) return @@ -84,12 +82,8 @@ func (h *Handler) AcceptReceivedShare(w http.ResponseWriter, r *http.Request) { // first update the requested share receivedShare.State = collaboration.ShareState_SHARE_STATE_ACCEPTED - // we need to add a path to the share - receivedShare.MountPoint = &provider.Reference{ - Path: mount, - } - updateMask := &fieldmaskpb.FieldMask{Paths: []string{"state", "mount_point"}} + updateMask := &fieldmaskpb.FieldMask{Paths: []string{"state"}} data, meta, err := h.updateReceivedShare(r.Context(), receivedShare, updateMask) if err != nil { // we log an error for affected shares, for the actual share we return an error @@ -106,10 +100,6 @@ func (h *Handler) AcceptReceivedShare(w http.ResponseWriter, r *http.Request) { } rs.State = collaboration.ShareState_SHARE_STATE_ACCEPTED - // set the same mountpoint as for the requested received share - rs.MountPoint = &provider.Reference{ - Path: mount, - } _, _, err := h.updateReceivedShare(r.Context(), rs, updateMask) if err != nil { @@ -119,76 +109,6 @@ func (h *Handler) AcceptReceivedShare(w http.ResponseWriter, r *http.Request) { } } -// GetMountpointAndUnmountedShares returns a new or existing mountpoint for the given info and produces a list of unmounted received shares for the same resource -func GetMountpointAndUnmountedShares(ctx context.Context, gwc gateway.GatewayAPIClient, info *provider.ResourceInfo) (string, []*collaboration.ReceivedShare, error) { - unmountedShares := []*collaboration.ReceivedShare{} - receivedShares, err := listReceivedShares(ctx, gwc) - if err != nil { - return "", unmountedShares, err - } - - // we need to sort the received shares by mount point in order to make things easier to evaluate. - base := filepath.Clean(info.Name) - mount := base - existingMountpoint := "" - mountedShares := make([]string, 0, len(receivedShares)) - var pathExists bool - - for _, s := range receivedShares { - resourceIDEqual := utils.ResourceIDEqual(s.GetShare().GetResourceId(), info.GetId()) - - if resourceIDEqual && s.State == collaboration.ShareState_SHARE_STATE_ACCEPTED { - // a share to the resource already exists and is mounted, remember the mount point - _, err := utils.GetResourceByID(ctx, s.GetShare().GetResourceId(), gwc) - if err == nil { - existingMountpoint = s.GetMountPoint().GetPath() - } - } - - if resourceIDEqual && s.State != collaboration.ShareState_SHARE_STATE_ACCEPTED { - // a share to the resource already exists but is not mounted, collect the unmounted share - unmountedShares = append(unmountedShares, s) - } - - if s.State == collaboration.ShareState_SHARE_STATE_ACCEPTED { - // collect all accepted mount points - mountedShares = append(mountedShares, s.GetMountPoint().GetPath()) - if s.GetMountPoint().GetPath() == mount { - // does the shared resource still exist? - _, err := utils.GetResourceByID(ctx, s.GetShare().GetResourceId(), gwc) - if err == nil { - pathExists = true - } - // TODO we could delete shares here if the stat returns code NOT FOUND ... but listening for file deletes would be better - } - } - } - - if existingMountpoint != "" { - // we want to reuse the same mountpoint for all unmounted shares to the same resource - return existingMountpoint, unmountedShares, nil - } - - // If the mount point really already exists, we need to insert a number into the filename - if pathExists { - // now we have a list of shares, we want to iterate over all of them and check for name collisions agents a mount points list - for i := 1; i <= len(mountedShares)+1; i++ { - ext := filepath.Ext(base) - name := strings.TrimSuffix(base, ext) - // be smart about .tar.(gz|bz) files - if strings.HasSuffix(name, ".tar") { - name = strings.TrimSuffix(name, ".tar") - ext = ".tar" + ext - } - mount = name + " (" + strconv.Itoa(i) + ")" + ext - if !slices.Contains(mountedShares, mount) { - return mount, unmountedShares, nil - } - } - } - return mount, unmountedShares, nil -} - // RejectReceivedShare handles DELETE Requests on /apps/files_sharing/api/v1/shares/{shareid} func (h *Handler) RejectReceivedShare(w http.ResponseWriter, r *http.Request) { shareID := chi.URLParam(r, "shareid") @@ -394,6 +314,25 @@ func getReceivedShareFromID(ctx context.Context, client gateway.GatewayAPIClient return s.Share, nil } +func getUnmountedShares(ctx context.Context, gwc gateway.GatewayAPIClient, id *provider.ResourceId) ([]*collaboration.ReceivedShare, error) { + var unmountedShares []*collaboration.ReceivedShare + receivedShares, err := listReceivedShares(ctx, gwc) + if err != nil { + return unmountedShares, err + } + + for _, s := range receivedShares { + resourceIDEqual := utils.ResourceIDEqual(s.GetShare().GetResourceId(), id) + + if resourceIDEqual && s.State != collaboration.ShareState_SHARE_STATE_ACCEPTED { + // a share to the resource already exists but is not mounted, collect the unmounted share + unmountedShares = append(unmountedShares, s) + } + } + + return unmountedShares, err +} + // getSharedResource attempts to get a shared resource from the storage from the resource reference. func getSharedResource(ctx context.Context, client gateway.GatewayAPIClient, resID *provider.ResourceId) (*provider.StatResponse, *response.Response) { res, err := client.Stat(ctx, &provider.StatRequest{ diff --git a/vendor/github.com/cs3org/reva/v2/pkg/storage/fs/posix/blobstore/blobstore.go b/vendor/github.com/cs3org/reva/v2/pkg/storage/fs/posix/blobstore/blobstore.go index eee4a3f8c4..bdbeb4536d 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/storage/fs/posix/blobstore/blobstore.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/storage/fs/posix/blobstore/blobstore.go @@ -47,10 +47,11 @@ func (bs *Blobstore) Upload(node *node.Node, source string) error { } defer file.Close() - f, err := os.OpenFile(node.InternalPath(), os.O_CREATE|os.O_WRONLY, 0700) + f, err := os.OpenFile(node.InternalPath(), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0700) if err != nil { return errors.Wrapf(err, "could not open blob '%s' for writing", node.InternalPath()) } + defer f.Close() w := bufio.NewWriter(f) _, err = w.ReadFrom(file) diff --git a/vendor/modules.txt b/vendor/modules.txt index 98db04bb72..7a844eef35 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -366,7 +366,7 @@ github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1 github.com/cs3org/go-cs3apis/cs3/storage/registry/v1beta1 github.com/cs3org/go-cs3apis/cs3/tx/v1beta1 github.com/cs3org/go-cs3apis/cs3/types/v1beta1 -# github.com/cs3org/reva/v2 v2.19.2-0.20240607120909-0a9c7b8bef6a +# github.com/cs3org/reva/v2 v2.19.2-0.20240613123928-7fb5f11a24cf ## explicit; go 1.21 github.com/cs3org/reva/v2/cmd/revad/internal/grace github.com/cs3org/reva/v2/cmd/revad/runtime