Search dav spaces (#4661)

* Add a Ref option to SearchRequest, e.g. for limiting the search to a space

* Enable REPORT requests for /dav/spaces URLs

* Limit the search to the according space in case of /dav/spaces searches

* Add changelog

* Adapt expected failures

* Comment exported functions
This commit is contained in:
Andre Duffeck
2022-09-27 10:38:15 +02:00
committed by GitHub
parent 918bc85879
commit 68b17eb68d
15 changed files with 286 additions and 201 deletions
@@ -41,6 +41,7 @@ func DefaultConfig() *config.Config {
}
}
// EnsureDefaults adds default values to the configuration if they are not set yet
func EnsureDefaults(cfg *config.Config) {
// provide with defaults for shared logging, since we need a valid destination address for "envdecode".
if cfg.Log == nil && cfg.Commons != nil && cfg.Commons.Log != nil {
@@ -78,6 +79,7 @@ func EnsureDefaults(cfg *config.Config) {
}
}
// Sanitize sanitizes the configuration
func Sanitize(cfg *config.Config) {
// no http endpoint to be sanitized
}
@@ -78,93 +78,104 @@ var _ = Describe("Searchprovider", func() {
})
Describe("events", func() {
It("triggers an index update when a file has been uploaded", func() {
called := false
indexClient.On("Add", mock.Anything, mock.MatchedBy(func(riToIndex *sprovider.ResourceInfo) bool {
return riToIndex.Id.OpaqueId == ri.Id.OpaqueId
})).Return(nil).Run(func(args mock.Arguments) {
called = true
Context("with the file being in the original location", func() {
BeforeEach(func() {
gwClient.On("GetPath", mock.Anything, mock.MatchedBy(func(req *sprovider.GetPathRequest) bool {
return req.ResourceId.OpaqueId == ri.Id.OpaqueId
})).Return(&sprovider.GetPathResponse{
Status: status.NewOK(context.Background()),
Path: ri.Path,
}, nil)
})
eventsChan <- events.FileUploaded{
Ref: ref,
Executant: user.Id,
}
Eventually(func() bool {
return called
}, "2s").Should(BeTrue())
})
It("triggers an index update when a file has been uploaded", func() {
called := false
indexClient.On("Add", mock.Anything, mock.MatchedBy(func(riToIndex *sprovider.ResourceInfo) bool {
return riToIndex.Id.OpaqueId == ri.Id.OpaqueId
})).Return(nil).Run(func(args mock.Arguments) {
called = true
})
eventsChan <- events.FileUploaded{
Ref: ref,
Executant: user.Id,
}
It("triggers an index update when a file has been touched", func() {
called := false
indexClient.On("Add", mock.Anything, mock.MatchedBy(func(riToIndex *sprovider.ResourceInfo) bool {
return riToIndex.Id.OpaqueId == ri.Id.OpaqueId
})).Return(nil).Run(func(args mock.Arguments) {
called = true
Eventually(func() bool {
return called
}, "2s").Should(BeTrue())
})
eventsChan <- events.FileTouched{
Ref: ref,
Executant: user.Id,
}
Eventually(func() bool {
return called
}, "2s").Should(BeTrue())
})
It("triggers an index update when a file has been touched", func() {
called := false
indexClient.On("Add", mock.Anything, mock.MatchedBy(func(riToIndex *sprovider.ResourceInfo) bool {
return riToIndex.Id.OpaqueId == ri.Id.OpaqueId
})).Return(nil).Run(func(args mock.Arguments) {
called = true
})
eventsChan <- events.FileTouched{
Ref: ref,
Executant: user.Id,
}
It("removes an entry from the index when the file has been deleted", func() {
called := false
gwClient.On("Stat", mock.Anything, mock.Anything).Return(&sprovider.StatResponse{
Status: status.NewNotFound(context.Background(), ""),
}, nil)
indexClient.On("Delete", mock.MatchedBy(func(id *sprovider.ResourceId) bool {
return id.OpaqueId == ri.Id.OpaqueId
})).Return(nil).Run(func(args mock.Arguments) {
called = true
Eventually(func() bool {
return called
}, "2s").Should(BeTrue())
})
eventsChan <- events.ItemTrashed{
Ref: ref,
ID: ri.Id,
Executant: user.Id,
}
Eventually(func() bool {
return called
}, "2s").Should(BeTrue())
})
It("removes an entry from the index when the file has been deleted", func() {
called := false
gwClient.On("Stat", mock.Anything, mock.Anything).Return(&sprovider.StatResponse{
Status: status.NewNotFound(context.Background(), ""),
}, nil)
indexClient.On("Delete", mock.MatchedBy(func(id *sprovider.ResourceId) bool {
return id.OpaqueId == ri.Id.OpaqueId
})).Return(nil).Run(func(args mock.Arguments) {
called = true
})
eventsChan <- events.ItemTrashed{
Ref: ref,
ID: ri.Id,
Executant: user.Id,
}
It("indexes items when they are being restored", func() {
called := false
indexClient.On("Restore", mock.MatchedBy(func(id *sprovider.ResourceId) bool {
return id.OpaqueId == ri.Id.OpaqueId
})).Return(nil).Run(func(args mock.Arguments) {
called = true
Eventually(func() bool {
return called
}, "2s").Should(BeTrue())
})
eventsChan <- events.ItemRestored{
Ref: ref,
Executant: user.Id,
}
Eventually(func() bool {
return called
}, "2s").Should(BeTrue())
})
It("indexes items when they are being restored", func() {
called := false
indexClient.On("Restore", mock.MatchedBy(func(id *sprovider.ResourceId) bool {
return id.OpaqueId == ri.Id.OpaqueId
})).Return(nil).Run(func(args mock.Arguments) {
called = true
})
eventsChan <- events.ItemRestored{
Ref: ref,
Executant: user.Id,
}
It("indexes items when a version has been restored", func() {
called := false
indexClient.On("Add", mock.Anything, mock.MatchedBy(func(riToIndex *sprovider.ResourceInfo) bool {
return riToIndex.Id.OpaqueId == ri.Id.OpaqueId
})).Return(nil).Run(func(args mock.Arguments) {
called = true
Eventually(func() bool {
return called
}, "2s").Should(BeTrue())
})
eventsChan <- events.FileVersionRestored{
Ref: ref,
Executant: user.Id,
}
Eventually(func() bool {
return called
}, "2s").Should(BeTrue())
It("indexes items when a version has been restored", func() {
called := false
indexClient.On("Add", mock.Anything, mock.MatchedBy(func(riToIndex *sprovider.ResourceInfo) bool {
return riToIndex.Id.OpaqueId == ri.Id.OpaqueId
})).Return(nil).Run(func(args mock.Arguments) {
called = true
})
eventsChan <- events.FileVersionRestored{
Ref: ref,
Executant: user.Id,
}
Eventually(func() bool {
return called
}, "2s").Should(BeTrue())
})
})
It("indexes items when they are being moved", func() {
@@ -138,6 +138,14 @@ func (p *Provider) Search(ctx context.Context, req *searchsvc.SearchRequest) (*s
SpaceId: space.Root.SpaceId,
OpaqueId: space.Root.OpaqueId,
}
if req.Ref != nil &&
(req.Ref.ResourceId.StorageId != searchRootId.StorageId ||
req.Ref.ResourceId.SpaceId != searchRootId.SpaceId ||
req.Ref.ResourceId.OpaqueId != searchRootId.OpaqueId) {
continue
}
var (
mountpointRootID *searchmsg.ResourceID
rootName string
@@ -50,7 +50,7 @@ var _ = Describe("Searchprovider", func() {
},
},
Id: &sprovider.StorageSpaceId{OpaqueId: "storageid$personalspace!personalspace"},
Root: &sprovider.ResourceId{StorageId: "storageid", SpaceId: "personalspace", OpaqueId: "storageid"},
Root: &sprovider.ResourceId{StorageId: "storageid", SpaceId: "personalspace", OpaqueId: "personalspace"},
Name: "personalspace",
}
@@ -80,6 +80,12 @@ var _ = Describe("Searchprovider", func() {
Status: status.NewOK(context.Background()),
Info: ri,
}, nil)
gwClient.On("GetPath", mock.Anything, mock.MatchedBy(func(req *sprovider.GetPathRequest) bool {
return req.ResourceId.OpaqueId == ri.Id.OpaqueId
})).Return(&sprovider.GetPathResponse{
Status: status.NewOK(context.Background()),
Path: ri.Path,
}, nil)
indexClient.On("DocCount").Return(uint64(1), nil)
})
@@ -370,6 +376,23 @@ var _ = Describe("Searchprovider", func() {
}, nil)
})
It("considers the search Ref parameter", func() {
res, err := p.Search(ctx, &searchsvc.SearchRequest{
Query: "foo",
Ref: &searchmsg.Reference{
ResourceId: &searchmsg.ResourceID{
StorageId: "storageid",
SpaceId: "personalspace",
OpaqueId: "personalspace",
},
},
})
Expect(err).ToNot(HaveOccurred())
Expect(res).ToNot(BeNil())
Expect(len(res.Matches)).To(Equal(1))
Expect(res.Matches[0].Entity.Id.OpaqueId).To(Equal("foo-id"))
})
It("finds matches in both the personal space AND the grant", func() {
res, err := p.Search(ctx, &searchsvc.SearchRequest{
Query: "foo",
@@ -96,6 +96,7 @@ func (s Service) Search(ctx context.Context, in *searchsvc.SearchRequest, out *s
res, err := s.provider.Search(ctx, &searchsvc.SearchRequest{
Query: in.Query,
PageSize: in.PageSize,
Ref: in.Ref,
})
if err != nil {
switch err.(type) {