diff --git a/changelog/unreleased/fix-mount-points-naming.md b/changelog/unreleased/fix-mount-points-naming.md new file mode 100644 index 000000000..f188aeb72 --- /dev/null +++ b/changelog/unreleased/fix-mount-points-naming.md @@ -0,0 +1,6 @@ +Bugfix: Fix the mount points naming + +We fixed a bug that caused inconsistent naming when multiple users share the resource with same name to another user. + +https://github.com/owncloud/ocis/pull/8543 +https://github.com/owncloud/ocis/issues/8471 diff --git a/go.mod b/go.mod index 859e7cb34..d068ec8b8 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/cenkalti/backoff v2.2.1+incompatible github.com/coreos/go-oidc/v3 v3.9.0 github.com/cs3org/go-cs3apis v0.0.0-20231023073225-7748710e0781 - github.com/cs3org/reva/v2 v2.19.2-0.20240312150024-04c0a3136ac9 + github.com/cs3org/reva/v2 v2.19.2-0.20240313154849-352a246529ff github.com/dhowden/tag v0.0.0-20230630033851-978a0926ee25 github.com/disintegration/imaging v1.6.2 github.com/dutchcoders/go-clamd v0.0.0-20170520113014-b970184f4d9e diff --git a/go.sum b/go.sum index d465ca97e..38deb30ad 100644 --- a/go.sum +++ b/go.sum @@ -1018,8 +1018,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.20240312150024-04c0a3136ac9 h1:7DdURTnE38PoSLxsYjZ8ZXyknc53PgD4M1KQT24eX88= -github.com/cs3org/reva/v2 v2.19.2-0.20240312150024-04c0a3136ac9/go.mod h1:GRUrOp5HbFVwZTgR9bVrMZ/MvVy+Jhxw1PdMmhhKP9E= +github.com/cs3org/reva/v2 v2.19.2-0.20240313154849-352a246529ff h1:XW1j4lf3EWfB9/fKN3D8Q1mehNvrlmGuXdVVzWLtFDs= +github.com/cs3org/reva/v2 v2.19.2-0.20240313154849-352a246529ff/go.mod h1:GRUrOp5HbFVwZTgR9bVrMZ/MvVy+Jhxw1PdMmhhKP9E= 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 248843115..b3d39331c 100644 --- a/services/frontend/pkg/command/events.go +++ b/services/frontend/pkg/command/events.go @@ -6,7 +6,7 @@ import ( "fmt" "path" "path/filepath" - "sort" + "slices" "strconv" "strings" @@ -171,49 +171,53 @@ func getMountpoint(ctx context.Context, l log.Logger, itemid *provider.ResourceI // 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 - mountedShares := make([]*collaboration.ReceivedShare, 0, len(lrs.Shares)) + 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.Share.ResourceId, itemid) { + if utils.ResourceIDEqual(s.GetShare().GetResourceId(), itemid) { // a share to the same resource already exists and is mounted - return s.MountPoint.Path, nil + return s.GetMountPoint().GetPath(), nil } - mountedShares = append(mountedShares, s) - } - - sort.Slice(mountedShares, func(i, j int) bool { - return mountedShares[i].MountPoint.Path > mountedShares[j].MountPoint.Path - }) - - // now we have a list of shares, we want to iterate over all of them and check for name collisions - for i, ms := range mountedShares { - if ms.MountPoint.Path == mount { + 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, ms.Share.ResourceId, gwc) + _, err = utils.GetResourceByID(ctx, s.GetShare().GetResourceId(), gwc) if err == nil { - // The mount point really already exists, we need to insert a number into the filename - 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 = fmt.Sprintf("%s (%s)%s", name, strconv.Itoa(i+1), ext) + 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 } 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 ca6c28df5..5ab1c1782 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 @@ -24,7 +24,7 @@ import ( "net/http" "path" "path/filepath" - "sort" + "slices" "strconv" "strings" @@ -128,55 +128,62 @@ func GetMountpointAndUnmountedShares(ctx context.Context, gwc gateway.GatewayAPI } // we need to sort the received shares by mount point in order to make things easier to evaluate. - mount := filepath.Clean(info.Name) + base := filepath.Clean(info.Name) + mount := base existingMountpoint := "" - mountedShares := make([]*collaboration.ReceivedShare, 0, len(receivedShares)) + mountedShares := make([]string, 0, len(receivedShares)) + var pathExists bool + for _, s := range receivedShares { - if utils.ResourceIDEqual(s.Share.ResourceId, info.GetId()) { - if 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.Share.ResourceId, gwc) - if err == nil { - existingMountpoint = s.MountPoint.Path - } - } else { - // a share to the resource already exists but is not mounted, collect the unmounted share - unmountedShares = append(unmountedShares, s) + 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 { - mountedShares = append(mountedShares, s) + // 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 + } } } - sort.Slice(mountedShares, func(i, j int) bool { - return mountedShares[i].MountPoint.Path > mountedShares[j].MountPoint.Path - }) - if existingMountpoint != "" { // we want to reuse the same mountpoint for all unmounted shares to the same resource return existingMountpoint, unmountedShares, nil } - // we have a list of shares, we want to iterate over all of them and check for name collisions - for i, ms := range mountedShares { - if ms.MountPoint.Path == mount { - // does the shared resource still exist? - _, err := utils.GetResourceByID(ctx, ms.Share.ResourceId, gwc) - if err == nil { - // The mount point really already exists, we need to insert a number into the filename - ext := filepath.Ext(mount) - name := strings.TrimSuffix(mount, ext) - // be smart about .tar.(gz|bz) files - if strings.HasSuffix(name, ".tar") { - name = strings.TrimSuffix(name, ".tar") - ext = ".tar" + ext - } - - mount = fmt.Sprintf("%s (%s)%s", name, strconv.Itoa(i+1), ext) + // 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 } - // TODO we could delete shares here if the stat returns code NOT FOUND ... but listening for file deletes would be better } } return mount, unmountedShares, nil diff --git a/vendor/modules.txt b/vendor/modules.txt index 17a5b2455..31c0df215 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -359,7 +359,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.20240312150024-04c0a3136ac9 +# github.com/cs3org/reva/v2 v2.19.2-0.20240313154849-352a246529ff ## explicit; go 1.21 github.com/cs3org/reva/v2/cmd/revad/internal/grace github.com/cs3org/reva/v2/cmd/revad/runtime