Consider the mountpoint share when searching grants

This commit is contained in:
André Duffeck
2022-05-06 09:32:25 +02:00
parent 7e6187a812
commit 2c604bacbb
2 changed files with 65 additions and 13 deletions
@@ -14,6 +14,7 @@ import (
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
ctxpkg "github.com/cs3org/reva/v2/pkg/ctx" ctxpkg "github.com/cs3org/reva/v2/pkg/ctx"
"github.com/cs3org/reva/v2/pkg/errtypes" "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/storage/utils/walker"
"github.com/cs3org/reva/v2/pkg/storagespace" "github.com/cs3org/reva/v2/pkg/storagespace"
"github.com/cs3org/reva/v2/pkg/utils" "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 == "" { if req.Query == "" {
return nil, errtypes.PreconditionFailed("empty query provided") 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{ listSpacesRes, err := p.gwClient.ListStorageSpaces(ctx, &provider.ListStorageSpacesRequest{
Filters: []*provider.ListStorageSpacesRequest_Filter{ Filters: []*provider.ListStorageSpacesRequest_Filter{
@@ -67,13 +69,36 @@ func (p *Provider) Search(ctx context.Context, req *searchsvc.SearchRequest) (*s
}, },
}) })
if err != nil { if err != nil {
p.logger.Error().Err(err).Msg("failed to list the user's storage spaces")
return nil, err 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{} matches := []*searchmsg.Match{}
for _, space := range listSpacesRes.StorageSpaces { for _, space := range listSpacesRes.StorageSpaces {
pathPrefix := "" var mountpointRootId *searchmsg.ResourceID
if space.SpaceType == "grant" { 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{ gpRes, err := p.gwClient.GetPath(ctx, &provider.GetPathRequest{
ResourceId: space.Root, 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 { if gpRes.Status.Code != rpcv1beta1.Code_CODE_OK {
return nil, errtypes.NewErrtypeFromStatus(gpRes.Status) 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) _, rootStorageID := storagespace.SplitStorageID(space.Root.StorageId)
res, err := p.indexClient.Search(ctx, &searchsvc.SearchIndexRequest{ res, err := p.indexClient.Search(ctx, &searchsvc.SearchIndexRequest{
Query: req.Query, Query: req.Query,
Ref: &searchmsg.Reference{ Ref: &searchmsg.Reference{
@@ -95,16 +128,21 @@ func (p *Provider) Search(ctx context.Context, req *searchsvc.SearchRequest) (*s
StorageId: space.Root.StorageId, StorageId: space.Root.StorageId,
OpaqueId: rootStorageID, OpaqueId: rootStorageID,
}, },
Path: pathPrefix, Path: mountpointPrefix,
}, },
}) })
if err != nil { if err != nil {
p.logger.Error().Err(err).Str("space", space.Id.OpaqueId).Msg("failed to search the index")
return nil, err 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 { for _, match := range res.Matches {
if pathPrefix != "" { if mountpointPrefix != "" {
match.Entity.Ref.Path = utils.MakeRelativePath(strings.TrimPrefix(match.Entity.Ref.Path, pathPrefix)) 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) matches = append(matches, match)
} }
@@ -267,7 +267,8 @@ var _ = Describe("Searchprovider", func() {
Context("with received shares", func() { Context("with received shares", func() {
var ( var (
grantSpace *sprovider.StorageSpace grantSpace *sprovider.StorageSpace
mountpointSpace *sprovider.StorageSpace
) )
BeforeEach(func() { BeforeEach(func() {
@@ -275,19 +276,32 @@ var _ = Describe("Searchprovider", func() {
SpaceType: "grant", SpaceType: "grant",
Owner: otherUser, Owner: otherUser,
Id: &sprovider.StorageSpaceId{OpaqueId: "otherspaceroot!otherspacegrant"}, Id: &sprovider.StorageSpaceId{OpaqueId: "otherspaceroot!otherspacegrant"},
Root: &sprovider.ResourceId{StorageId: "otherspaceroot", OpaqueId: "otherspaceroot"}, Root: &sprovider.ResourceId{StorageId: "otherspaceroot", OpaqueId: "otherspacegrant"},
Name: "grantspace", 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{ gwClient.On("GetPath", mock.Anything, mock.Anything).Return(&sprovider.GetPathResponse{
Status: status.NewOK(ctx), Status: status.NewOK(ctx),
Path: "/grant/path", Path: "/grant/path",
}, nil) }, nil)
}) })
It("searches the received spaces (grants)", func() { It("searches the received spaces", func() {
gwClient.On("ListStorageSpaces", mock.Anything, mock.Anything).Return(&sprovider.ListStorageSpacesResponse{ gwClient.On("ListStorageSpaces", mock.Anything, mock.Anything).Return(&sprovider.ListStorageSpacesResponse{
Status: status.NewOK(ctx), Status: status.NewOK(ctx),
StorageSpaces: []*sprovider.StorageSpace{grantSpace}, StorageSpaces: []*sprovider.StorageSpace{grantSpace, mountpointSpace},
}, nil) }, nil)
indexClient.On("Search", mock.Anything, mock.Anything).Return(&searchsvc.SearchIndexResponse{ indexClient.On("Search", mock.Anything, mock.Anything).Return(&searchsvc.SearchIndexResponse{
Matches: []*searchmsg.Match{ Matches: []*searchmsg.Match{
@@ -319,7 +333,7 @@ var _ = Describe("Searchprovider", func() {
match := res.Matches[0] match := res.Matches[0]
Expect(match.Entity.Id.OpaqueId).To(Equal("grant-shared-id")) Expect(match.Entity.Id.OpaqueId).To(Equal("grant-shared-id"))
Expect(match.Entity.Name).To(Equal("Shared.pdf")) 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")) Expect(match.Entity.Ref.Path).To(Equal("./to/Shared.pdf"))
indexClient.AssertCalled(GinkgoT(), "Search", mock.Anything, mock.MatchedBy(func(req *searchsvc.SearchIndexRequest) bool { 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() { It("finds matches in both the personal space AND the grant", func() {
gwClient.On("ListStorageSpaces", mock.Anything, mock.Anything).Return(&sprovider.ListStorageSpacesResponse{ gwClient.On("ListStorageSpaces", mock.Anything, mock.Anything).Return(&sprovider.ListStorageSpacesResponse{
Status: status.NewOK(ctx), Status: status.NewOK(ctx),
StorageSpaces: []*sprovider.StorageSpace{personalSpace, grantSpace}, StorageSpaces: []*sprovider.StorageSpace{personalSpace, grantSpace, mountpointSpace},
}, nil) }, nil)
indexClient.On("Search", mock.Anything, mock.MatchedBy(func(req *searchsvc.SearchIndexRequest) bool { indexClient.On("Search", mock.Anything, mock.MatchedBy(func(req *searchsvc.SearchIndexRequest) bool {
return req.Ref.ResourceId.StorageId == grantSpace.Root.StorageId return req.Ref.ResourceId.StorageId == grantSpace.Root.StorageId