diff --git a/extensions/search/pkg/search/provider/searchprovider.go b/extensions/search/pkg/search/provider/searchprovider.go index 9356af88a8..8914e02738 100644 --- a/extensions/search/pkg/search/provider/searchprovider.go +++ b/extensions/search/pkg/search/provider/searchprovider.go @@ -14,6 +14,7 @@ import ( provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" ctxpkg "github.com/cs3org/reva/v2/pkg/ctx" "github.com/cs3org/reva/v2/pkg/errtypes" + sdk "github.com/cs3org/reva/v2/pkg/sdk/common" "github.com/cs3org/reva/v2/pkg/storage/utils/walker" "github.com/cs3org/reva/v2/pkg/storagespace" "github.com/cs3org/reva/v2/pkg/utils" @@ -57,6 +58,7 @@ func (p *Provider) Search(ctx context.Context, req *searchsvc.SearchRequest) (*s if req.Query == "" { return nil, errtypes.PreconditionFailed("empty query provided") } + p.logger.Debug().Str("query", req.Query).Msg("performing a search") listSpacesRes, err := p.gwClient.ListStorageSpaces(ctx, &provider.ListStorageSpacesRequest{ Filters: []*provider.ListStorageSpacesRequest_Filter{ @@ -67,13 +69,36 @@ func (p *Provider) Search(ctx context.Context, req *searchsvc.SearchRequest) (*s }, }) if err != nil { + p.logger.Error().Err(err).Msg("failed to list the user's storage spaces") return nil, err } + mountpointMap := map[string]string{} + for _, space := range listSpacesRes.StorageSpaces { + if space.SpaceType != "mountpoint" { + continue + } + opaqueMap := sdk.DecodeOpaqueMap(space.Opaque) + grantSpaceId := storagespace.FormatResourceID(provider.ResourceId{ + StorageId: opaqueMap["grantStorageID"], + OpaqueId: opaqueMap["grantOpaqueID"], + }) + mountpointMap[grantSpaceId] = space.Id.OpaqueId + } + matches := []*searchmsg.Match{} for _, space := range listSpacesRes.StorageSpaces { - pathPrefix := "" - if space.SpaceType == "grant" { + var mountpointRootId *searchmsg.ResourceID + mountpointPrefix := "" + switch space.SpaceType { + case "mountpoint": + continue // mountpoint spaces are only "links" to the shared spaces. we have to search the shared "grant" space instead + case "grant": + mountpointId, ok := mountpointMap[space.Id.OpaqueId] + if !ok { + p.logger.Warn().Interface("space", space).Msg("could not find mountpoint space for grant space") + continue + } gpRes, err := p.gwClient.GetPath(ctx, &provider.GetPathRequest{ ResourceId: space.Root, }) @@ -83,11 +108,19 @@ func (p *Provider) Search(ctx context.Context, req *searchsvc.SearchRequest) (*s if gpRes.Status.Code != rpcv1beta1.Code_CODE_OK { return nil, errtypes.NewErrtypeFromStatus(gpRes.Status) } - pathPrefix = utils.MakeRelativePath(gpRes.Path) + mountpointPrefix = utils.MakeRelativePath(gpRes.Path) + sid, oid, err := storagespace.SplitID(mountpointId) + if err != nil { + return nil, err + } + mountpointRootId = &searchmsg.ResourceID{ + StorageId: sid, + OpaqueId: oid, + } + p.logger.Debug().Interface("grantSpace", space).Interface("mountpointRootId", mountpointRootId).Msg("searching a grant") } _, rootStorageID := storagespace.SplitStorageID(space.Root.StorageId) - res, err := p.indexClient.Search(ctx, &searchsvc.SearchIndexRequest{ Query: req.Query, Ref: &searchmsg.Reference{ @@ -95,16 +128,21 @@ func (p *Provider) Search(ctx context.Context, req *searchsvc.SearchRequest) (*s StorageId: space.Root.StorageId, OpaqueId: rootStorageID, }, - Path: pathPrefix, + Path: mountpointPrefix, }, }) if err != nil { + p.logger.Error().Err(err).Str("space", space.Id.OpaqueId).Msg("failed to search the index") return nil, err } + p.logger.Debug().Str("space", space.Id.OpaqueId).Int("hits", len(res.Matches)).Msg("space search done") for _, match := range res.Matches { - if pathPrefix != "" { - match.Entity.Ref.Path = utils.MakeRelativePath(strings.TrimPrefix(match.Entity.Ref.Path, pathPrefix)) + if mountpointPrefix != "" { + match.Entity.Ref.Path = utils.MakeRelativePath(strings.TrimPrefix(match.Entity.Ref.Path, mountpointPrefix)) + } + if mountpointRootId != nil { + match.Entity.Ref.ResourceId = mountpointRootId } matches = append(matches, match) } diff --git a/extensions/search/pkg/search/provider/searchprovider_test.go b/extensions/search/pkg/search/provider/searchprovider_test.go index 956d60df0a..b5403bb489 100644 --- a/extensions/search/pkg/search/provider/searchprovider_test.go +++ b/extensions/search/pkg/search/provider/searchprovider_test.go @@ -267,7 +267,8 @@ var _ = Describe("Searchprovider", func() { Context("with received shares", func() { var ( - grantSpace *sprovider.StorageSpace + grantSpace *sprovider.StorageSpace + mountpointSpace *sprovider.StorageSpace ) BeforeEach(func() { @@ -275,19 +276,32 @@ var _ = Describe("Searchprovider", func() { SpaceType: "grant", Owner: otherUser, Id: &sprovider.StorageSpaceId{OpaqueId: "otherspaceroot!otherspacegrant"}, - Root: &sprovider.ResourceId{StorageId: "otherspaceroot", OpaqueId: "otherspaceroot"}, + Root: &sprovider.ResourceId{StorageId: "otherspaceroot", OpaqueId: "otherspacegrant"}, Name: "grantspace", } + mountpointSpace = &sprovider.StorageSpace{ + SpaceType: "mountpoint", + Owner: otherUser, + Id: &sprovider.StorageSpaceId{OpaqueId: "otherspaceroot!otherspacemountpoint"}, + Root: &sprovider.ResourceId{StorageId: "otherspaceroot", OpaqueId: "otherspacemountpoint"}, + Name: "mountpointspace", + Opaque: &typesv1beta1.Opaque{ + Map: map[string]*typesv1beta1.OpaqueEntry{ + "grantStorageID": {Decoder: "plain", Value: []byte("otherspaceroot")}, + "grantOpaqueID": {Decoder: "plain", Value: []byte("otherspacegrant")}, + }, + }, + } gwClient.On("GetPath", mock.Anything, mock.Anything).Return(&sprovider.GetPathResponse{ Status: status.NewOK(ctx), Path: "/grant/path", }, nil) }) - It("searches the received spaces (grants)", func() { + It("searches the received spaces", func() { gwClient.On("ListStorageSpaces", mock.Anything, mock.Anything).Return(&sprovider.ListStorageSpacesResponse{ Status: status.NewOK(ctx), - StorageSpaces: []*sprovider.StorageSpace{grantSpace}, + StorageSpaces: []*sprovider.StorageSpace{grantSpace, mountpointSpace}, }, nil) indexClient.On("Search", mock.Anything, mock.Anything).Return(&searchsvc.SearchIndexResponse{ Matches: []*searchmsg.Match{ @@ -319,7 +333,7 @@ var _ = Describe("Searchprovider", func() { match := res.Matches[0] Expect(match.Entity.Id.OpaqueId).To(Equal("grant-shared-id")) Expect(match.Entity.Name).To(Equal("Shared.pdf")) - Expect(match.Entity.Ref.ResourceId.OpaqueId).To(Equal(grantSpace.Root.OpaqueId)) + Expect(match.Entity.Ref.ResourceId.OpaqueId).To(Equal(mountpointSpace.Root.OpaqueId)) Expect(match.Entity.Ref.Path).To(Equal("./to/Shared.pdf")) indexClient.AssertCalled(GinkgoT(), "Search", mock.Anything, mock.MatchedBy(func(req *searchsvc.SearchIndexRequest) bool { @@ -330,7 +344,7 @@ var _ = Describe("Searchprovider", func() { It("finds matches in both the personal space AND the grant", func() { gwClient.On("ListStorageSpaces", mock.Anything, mock.Anything).Return(&sprovider.ListStorageSpacesResponse{ Status: status.NewOK(ctx), - StorageSpaces: []*sprovider.StorageSpace{personalSpace, grantSpace}, + StorageSpaces: []*sprovider.StorageSpace{personalSpace, grantSpace, mountpointSpace}, }, nil) indexClient.On("Search", mock.Anything, mock.MatchedBy(func(req *searchsvc.SearchIndexRequest) bool { return req.Ref.ResourceId.StorageId == grantSpace.Root.StorageId