enhancement: add get share service method

This commit is contained in:
Florian Schade
2024-04-23 18:00:13 +02:00
committed by Ralf Haferkamp
parent 9b17c3fa30
commit 4841240bff
3 changed files with 207 additions and 61 deletions

View File

@@ -27,29 +27,29 @@ func (_m *DrivesDriveItemProvider) EXPECT() *DrivesDriveItemProvider_Expecter {
return &DrivesDriveItemProvider_Expecter{mock: &_m.Mock}
}
// GetShareAndSiblings provides a mock function with given fields: ctx, shareID, filters
func (_m *DrivesDriveItemProvider) GetShareAndSiblings(ctx context.Context, shareID *collaborationv1beta1.ShareId, filters []*collaborationv1beta1.Filter) ([]*collaborationv1beta1.ReceivedShare, error) {
ret := _m.Called(ctx, shareID, filters)
// GetShare provides a mock function with given fields: ctx, shareID
func (_m *DrivesDriveItemProvider) GetShare(ctx context.Context, shareID *collaborationv1beta1.ShareId) (*collaborationv1beta1.ReceivedShare, error) {
ret := _m.Called(ctx, shareID)
if len(ret) == 0 {
panic("no return value specified for GetShareAndSiblings")
panic("no return value specified for GetShare")
}
var r0 []*collaborationv1beta1.ReceivedShare
var r0 *collaborationv1beta1.ReceivedShare
var r1 error
if rf, ok := ret.Get(0).(func(context.Context, *collaborationv1beta1.ShareId, []*collaborationv1beta1.Filter) ([]*collaborationv1beta1.ReceivedShare, error)); ok {
return rf(ctx, shareID, filters)
if rf, ok := ret.Get(0).(func(context.Context, *collaborationv1beta1.ShareId) (*collaborationv1beta1.ReceivedShare, error)); ok {
return rf(ctx, shareID)
}
if rf, ok := ret.Get(0).(func(context.Context, *collaborationv1beta1.ShareId, []*collaborationv1beta1.Filter) []*collaborationv1beta1.ReceivedShare); ok {
r0 = rf(ctx, shareID, filters)
if rf, ok := ret.Get(0).(func(context.Context, *collaborationv1beta1.ShareId) *collaborationv1beta1.ReceivedShare); ok {
r0 = rf(ctx, shareID)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]*collaborationv1beta1.ReceivedShare)
r0 = ret.Get(0).(*collaborationv1beta1.ReceivedShare)
}
}
if rf, ok := ret.Get(1).(func(context.Context, *collaborationv1beta1.ShareId, []*collaborationv1beta1.Filter) error); ok {
r1 = rf(ctx, shareID, filters)
if rf, ok := ret.Get(1).(func(context.Context, *collaborationv1beta1.ShareId) error); ok {
r1 = rf(ctx, shareID)
} else {
r1 = ret.Error(1)
}
@@ -57,32 +57,91 @@ func (_m *DrivesDriveItemProvider) GetShareAndSiblings(ctx context.Context, shar
return r0, r1
}
// DrivesDriveItemProvider_GetShareAndSiblings_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetShareAndSiblings'
type DrivesDriveItemProvider_GetShareAndSiblings_Call struct {
// DrivesDriveItemProvider_GetShare_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetShare'
type DrivesDriveItemProvider_GetShare_Call struct {
*mock.Call
}
// GetShareAndSiblings is a helper method to define mock.On call
// GetShare is a helper method to define mock.On call
// - ctx context.Context
// - shareID *collaborationv1beta1.ShareId
// - filters []*collaborationv1beta1.Filter
func (_e *DrivesDriveItemProvider_Expecter) GetShareAndSiblings(ctx interface{}, shareID interface{}, filters interface{}) *DrivesDriveItemProvider_GetShareAndSiblings_Call {
return &DrivesDriveItemProvider_GetShareAndSiblings_Call{Call: _e.mock.On("GetShareAndSiblings", ctx, shareID, filters)}
func (_e *DrivesDriveItemProvider_Expecter) GetShare(ctx interface{}, shareID interface{}) *DrivesDriveItemProvider_GetShare_Call {
return &DrivesDriveItemProvider_GetShare_Call{Call: _e.mock.On("GetShare", ctx, shareID)}
}
func (_c *DrivesDriveItemProvider_GetShareAndSiblings_Call) Run(run func(ctx context.Context, shareID *collaborationv1beta1.ShareId, filters []*collaborationv1beta1.Filter)) *DrivesDriveItemProvider_GetShareAndSiblings_Call {
func (_c *DrivesDriveItemProvider_GetShare_Call) Run(run func(ctx context.Context, shareID *collaborationv1beta1.ShareId)) *DrivesDriveItemProvider_GetShare_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(context.Context), args[1].(*collaborationv1beta1.ShareId), args[2].([]*collaborationv1beta1.Filter))
run(args[0].(context.Context), args[1].(*collaborationv1beta1.ShareId))
})
return _c
}
func (_c *DrivesDriveItemProvider_GetShareAndSiblings_Call) Return(_a0 []*collaborationv1beta1.ReceivedShare, _a1 error) *DrivesDriveItemProvider_GetShareAndSiblings_Call {
func (_c *DrivesDriveItemProvider_GetShare_Call) Return(_a0 *collaborationv1beta1.ReceivedShare, _a1 error) *DrivesDriveItemProvider_GetShare_Call {
_c.Call.Return(_a0, _a1)
return _c
}
func (_c *DrivesDriveItemProvider_GetShareAndSiblings_Call) RunAndReturn(run func(context.Context, *collaborationv1beta1.ShareId, []*collaborationv1beta1.Filter) ([]*collaborationv1beta1.ReceivedShare, error)) *DrivesDriveItemProvider_GetShareAndSiblings_Call {
func (_c *DrivesDriveItemProvider_GetShare_Call) RunAndReturn(run func(context.Context, *collaborationv1beta1.ShareId) (*collaborationv1beta1.ReceivedShare, error)) *DrivesDriveItemProvider_GetShare_Call {
_c.Call.Return(run)
return _c
}
// GetShares provides a mock function with given fields: ctx, resourceID, filters
func (_m *DrivesDriveItemProvider) GetShares(ctx context.Context, resourceID *providerv1beta1.ResourceId, filters []*collaborationv1beta1.Filter) ([]*collaborationv1beta1.ReceivedShare, error) {
ret := _m.Called(ctx, resourceID, filters)
if len(ret) == 0 {
panic("no return value specified for GetShares")
}
var r0 []*collaborationv1beta1.ReceivedShare
var r1 error
if rf, ok := ret.Get(0).(func(context.Context, *providerv1beta1.ResourceId, []*collaborationv1beta1.Filter) ([]*collaborationv1beta1.ReceivedShare, error)); ok {
return rf(ctx, resourceID, filters)
}
if rf, ok := ret.Get(0).(func(context.Context, *providerv1beta1.ResourceId, []*collaborationv1beta1.Filter) []*collaborationv1beta1.ReceivedShare); ok {
r0 = rf(ctx, resourceID, filters)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]*collaborationv1beta1.ReceivedShare)
}
}
if rf, ok := ret.Get(1).(func(context.Context, *providerv1beta1.ResourceId, []*collaborationv1beta1.Filter) error); ok {
r1 = rf(ctx, resourceID, filters)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// DrivesDriveItemProvider_GetShares_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetShares'
type DrivesDriveItemProvider_GetShares_Call struct {
*mock.Call
}
// GetShares is a helper method to define mock.On call
// - ctx context.Context
// - resourceID *providerv1beta1.ResourceId
// - filters []*collaborationv1beta1.Filter
func (_e *DrivesDriveItemProvider_Expecter) GetShares(ctx interface{}, resourceID interface{}, filters interface{}) *DrivesDriveItemProvider_GetShares_Call {
return &DrivesDriveItemProvider_GetShares_Call{Call: _e.mock.On("GetShares", ctx, resourceID, filters)}
}
func (_c *DrivesDriveItemProvider_GetShares_Call) Run(run func(ctx context.Context, resourceID *providerv1beta1.ResourceId, filters []*collaborationv1beta1.Filter)) *DrivesDriveItemProvider_GetShares_Call {
_c.Call.Run(func(args mock.Arguments) {
run(args[0].(context.Context), args[1].(*providerv1beta1.ResourceId), args[2].([]*collaborationv1beta1.Filter))
})
return _c
}
func (_c *DrivesDriveItemProvider_GetShares_Call) Return(_a0 []*collaborationv1beta1.ReceivedShare, _a1 error) *DrivesDriveItemProvider_GetShares_Call {
_c.Call.Return(_a0, _a1)
return _c
}
func (_c *DrivesDriveItemProvider_GetShares_Call) RunAndReturn(run func(context.Context, *providerv1beta1.ResourceId, []*collaborationv1beta1.Filter) ([]*collaborationv1beta1.ReceivedShare, error)) *DrivesDriveItemProvider_GetShares_Call {
_c.Call.Return(run)
return _c
}

View File

@@ -36,6 +36,9 @@ var (
// ErrNoShares is returned when no shares are found
ErrNoShares = errors.New("no shares found")
// ErrNoShare is returned when no share is found
ErrNoShare = errors.New("no shares found")
// ErrAbsoluteNamePath is returned when the name is an absolute path
ErrAbsoluteNamePath = errors.New("name cannot be an absolute path")
@@ -82,8 +85,11 @@ type (
// UpdateShares updates multiple shares
UpdateShares(ctx context.Context, shares []*collaboration.ReceivedShare, updater UpdateShareClosure) ([]*collaboration.ReceivedShare, error)
// GetShareAndSiblings returns the share and all its siblings
GetShareAndSiblings(ctx context.Context, shareID *collaboration.ShareId, filters []*collaboration.Filter) ([]*collaboration.ReceivedShare, error)
// GetShare returns the share
GetShare(ctx context.Context, shareID *collaboration.ShareId) (*collaboration.ReceivedShare, error)
// GetShares returns all shares for a given resourceID
GetShares(ctx context.Context, resourceID *storageprovider.ResourceId, filters []*collaboration.Filter) ([]*collaboration.ReceivedShare, error)
}
)
@@ -101,8 +107,7 @@ func NewDrivesDriveItemService(logger log.Logger, gatewaySelector pool.Selectabl
}, nil
}
// GetShareAndSiblings returns the share and all its siblings
func (s DrivesDriveItemService) GetShareAndSiblings(ctx context.Context, shareID *collaboration.ShareId, filters []*collaboration.Filter) ([]*collaboration.ReceivedShare, error) {
func (s DrivesDriveItemService) GetShare(ctx context.Context, shareID *collaboration.ShareId) (*collaboration.ReceivedShare, error) {
gatewayClient, err := s.gatewaySelector.Next()
if err != nil {
return nil, err
@@ -118,15 +123,12 @@ func (s DrivesDriveItemService) GetShareAndSiblings(ctx context.Context, shareID
},
},
)
if err := errorcode.FromCS3Status(getReceivedShareResponse.GetStatus(), err); err != nil {
return nil, err
}
return s.GetSharesByResourceID(ctx, getReceivedShareResponse.GetShare().GetShare().GetResourceId(), filters)
return getReceivedShareResponse.GetShare(), errorcode.FromCS3Status(getReceivedShareResponse.GetStatus(), err)
}
// GetSharesByResourceID returns all shares for a given resourceID
func (s DrivesDriveItemService) GetSharesByResourceID(ctx context.Context, resourceID *storageprovider.ResourceId, filters []*collaboration.Filter) ([]*collaboration.ReceivedShare, error) {
// GetShares returns all shares for a given resourceID
func (s DrivesDriveItemService) GetShares(ctx context.Context, resourceID *storageprovider.ResourceId, filters []*collaboration.Filter) ([]*collaboration.ReceivedShare, error) {
// Find all accepted shares for this resource
gatewayClient, err := s.gatewaySelector.Next()
if err != nil {
@@ -211,7 +213,12 @@ func (s DrivesDriveItemService) UpdateShare(ctx context.Context, share *collabor
// UnmountShare unmounts a share
func (s DrivesDriveItemService) UnmountShare(ctx context.Context, shareID *collaboration.ShareId) error {
availableShares, err := s.GetShareAndSiblings(ctx, shareID, []*collaboration.Filter{
share, err := s.GetShare(ctx, shareID)
if err != nil {
return err
}
availableShares, err := s.GetShares(ctx, share.GetShare().GetResourceId(), []*collaboration.Filter{
{
Type: collaboration.Filter_TYPE_STATE,
Term: &collaboration.Filter_State{
@@ -243,7 +250,7 @@ func (s DrivesDriveItemService) MountShare(ctx context.Context, resourceID *stor
name = filepath.Clean(name)
}
availableShares, err := s.GetSharesByResourceID(ctx, resourceID, []*collaboration.Filter{
availableShares, err := s.GetShares(ctx, resourceID, []*collaboration.Filter{
{
Type: collaboration.Filter_TYPE_STATE,
Term: &collaboration.Filter_State{
@@ -357,7 +364,14 @@ func (api DrivesDriveItemApi) UpdateDriveItem(w http.ResponseWriter, r *http.Req
return
}
availableShares, err := api.drivesDriveItemService.GetShareAndSiblings(r.Context(), shareID, nil)
share, err := api.drivesDriveItemService.GetShare(r.Context(), shareID)
if err != nil {
api.logger.Debug().Err(err).Msg(ErrNoShare.Error())
errorcode.InvalidRequest.Render(w, r, http.StatusFailedDependency, ErrNoShare.Error())
return
}
availableShares, err := api.drivesDriveItemService.GetShares(r.Context(), share.GetShare().GetResourceId(), nil)
if err != nil {
api.logger.Debug().Err(err).Msg(ErrGetShareAndSiblings.Error())
errorcode.InvalidRequest.Render(w, r, http.StatusFailedDependency, ErrGetShareAndSiblings.Error())

View File

@@ -41,14 +41,28 @@ var _ = Describe("DrivesDriveItemService", func() {
gatewayClient = cs3mocks.NewGatewayAPIClient(GinkgoT())
gatewaySelector = mocks.NewSelectable[gateway.GatewayAPIClient](GinkgoT())
gatewaySelector.On("Next").Return(gatewayClient, nil)
gatewaySelector.EXPECT().Next().Return(gatewayClient, nil)
service, err := svc.NewDrivesDriveItemService(logger, gatewaySelector)
Expect(err).ToNot(HaveOccurred())
drivesDriveItemService = service
})
var _ = Describe("GetSharesByResourceID", func() {
failOnFailingGatewayClientRotation := func(f func() error) {
It("fails if obtaining the next gateway client fails", func() {
someErr := errors.New("some error")
gatewaySelector.EXPECT().Next().Unset()
gatewaySelector.EXPECT().Next().Return(gatewayClient, someErr).Times(1)
Expect(f()).To(MatchError(someErr))
})
}
var _ = Describe("GetShares", func() {
failOnFailingGatewayClientRotation(func() error {
_, err := drivesDriveItemService.GetShares(context.Background(), nil, nil)
return err
})
It("uses the correct filters to list received shares", func() {
resourceID := &storageprovider.ResourceId{
StorageId: "1",
@@ -68,7 +82,7 @@ var _ = Describe("DrivesDriveItemService", func() {
}).
Once()
_, _ = drivesDriveItemService.GetSharesByResourceID(context.Background(), resourceID, []*collaborationv1beta1.Filter{
_, _ = drivesDriveItemService.GetShares(context.Background(), resourceID, []*collaborationv1beta1.Filter{
{
Type: collaborationv1beta1.Filter_TYPE_STATE,
Term: &collaborationv1beta1.Filter_State{
@@ -86,7 +100,7 @@ var _ = Describe("DrivesDriveItemService", func() {
Return(nil, someErr).
Once()
_, err := drivesDriveItemService.GetSharesByResourceID(context.Background(), &storageprovider.ResourceId{}, []*collaborationv1beta1.Filter{})
_, err := drivesDriveItemService.GetShares(context.Background(), &storageprovider.ResourceId{}, []*collaborationv1beta1.Filter{})
Expect(err).To(MatchError(someErr))
})
@@ -97,7 +111,7 @@ var _ = Describe("DrivesDriveItemService", func() {
Return(nil, nil).
Once()
_, err := drivesDriveItemService.GetSharesByResourceID(context.Background(), &storageprovider.ResourceId{}, []*collaborationv1beta1.Filter{})
_, err := drivesDriveItemService.GetShares(context.Background(), &storageprovider.ResourceId{}, []*collaborationv1beta1.Filter{})
Expect(err).To(MatchError(svc.ErrNoShares))
})
@@ -116,13 +130,18 @@ var _ = Describe("DrivesDriveItemService", func() {
}, nil).
Once()
shares, err := drivesDriveItemService.GetSharesByResourceID(context.Background(), &storageprovider.ResourceId{}, []*collaborationv1beta1.Filter{})
shares, err := drivesDriveItemService.GetShares(context.Background(), &storageprovider.ResourceId{}, []*collaborationv1beta1.Filter{})
Expect(err).To(BeNil())
Expect(shares).To(Equal(givenShares))
})
})
var _ = Describe("GetShareAndSiblings", func() {
var _ = Describe("GetShare", func() {
failOnFailingGatewayClientRotation(func() error {
_, err := drivesDriveItemService.GetShare(context.Background(), nil)
return err
})
It("fails if share lookup reports an error", func() {
someErr := errors.New("some error")
gatewayClient.
@@ -131,7 +150,7 @@ var _ = Describe("DrivesDriveItemService", func() {
Return(nil, someErr).
Once()
_, err := drivesDriveItemService.GetShareAndSiblings(context.Background(), &collaborationv1beta1.ShareId{}, nil)
_, err := drivesDriveItemService.GetShare(context.Background(), &collaborationv1beta1.ShareId{})
Expect(err).To(MatchError(errorcode.New(errorcode.GeneralException, someErr.Error())))
})
@@ -145,35 +164,38 @@ var _ = Describe("DrivesDriveItemService", func() {
}, nil).
Once()
_, err := drivesDriveItemService.GetShareAndSiblings(context.Background(), &collaborationv1beta1.ShareId{}, nil)
_, err := drivesDriveItemService.GetShare(context.Background(), &collaborationv1beta1.ShareId{})
Expect(err).To(MatchError(errorcode.New(errorcode.ItemNotFound, someErr.Error())))
})
It("successfully returns shares", func() {
It("successfully returns a share", func() {
gatewayClient.
EXPECT().
GetReceivedShare(context.Background(), mock.Anything, mock.Anything).
Return(&collaborationv1beta1.GetReceivedShareResponse{
Status: status.NewOK(context.Background()),
Share: &collaborationv1beta1.ReceivedShare{
Share: &collaborationv1beta1.Share{
Id: &collaborationv1beta1.ShareId{
OpaqueId: "123",
},
},
},
}, nil).
Once()
gatewayClient.
EXPECT().
ListReceivedShares(context.Background(), mock.Anything, mock.Anything, mock.Anything).
Return(&collaborationv1beta1.ListReceivedSharesResponse{
Status: status.NewOK(context.Background()),
Shares: make([]*collaborationv1beta1.ReceivedShare, 3),
}, nil).
Once()
shares, err := drivesDriveItemService.GetShareAndSiblings(context.Background(), &collaborationv1beta1.ShareId{}, nil)
share, err := drivesDriveItemService.GetShare(context.Background(), &collaborationv1beta1.ShareId{})
Expect(err).To(BeNil())
Expect(shares).To(HaveLen(3))
Expect(share.GetShare().GetId().GetOpaqueId()).To(Equal("123"))
})
})
var _ = Describe("UpdateShare", func() {
failOnFailingGatewayClientRotation(func() error {
_, err := drivesDriveItemService.UpdateShare(context.Background(), nil, nil)
return err
})
It("fails without an updater", func() {
_, err := drivesDriveItemService.UpdateShare(context.Background(), &collaborationv1beta1.ReceivedShare{}, nil)
Expect(err).To(MatchError(svc.ErrNoUpdater))
@@ -544,7 +566,7 @@ var _ = Describe("DrivesDriveItemApi", func() {
failOninvalidDriveItemBody(drivesDriveItemApi.UpdateDriveItem)
It("fails if retrieving the share ans siblings fails", func() {
It("fails if retrieving the share fails", func() {
rCTX.URLParams.Add("driveID", "a0ca6a90-a365-4782-871e-d44447bbc668$a0ca6a90-a365-4782-871e-d44447bbc668")
rCTX.URLParams.Add("itemID", "a0ca6a90-a365-4782-871e-d44447bbc668$a0ca6a90-a365-4782-871e-d44447bbc668!1")
@@ -560,7 +582,40 @@ var _ = Describe("DrivesDriveItemApi", func() {
drivesDriveItemProvider.
EXPECT().
GetShareAndSiblings(mock.Anything, mock.Anything, mock.Anything).
GetShare(mock.Anything, mock.Anything).
Return(nil, errors.New("some error")).
Once()
drivesDriveItemApi.UpdateDriveItem(w, r)
Expect(w.Code).To(Equal(http.StatusFailedDependency))
jsonData := gjson.Get(w.Body.String(), "error")
Expect(jsonData.Get("message").String()).To(Equal(svc.ErrNoShare.Error()))
})
It("fails if retrieving the shares fail", func() {
rCTX.URLParams.Add("driveID", "a0ca6a90-a365-4782-871e-d44447bbc668$a0ca6a90-a365-4782-871e-d44447bbc668")
rCTX.URLParams.Add("itemID", "a0ca6a90-a365-4782-871e-d44447bbc668$a0ca6a90-a365-4782-871e-d44447bbc668!1")
w := httptest.NewRecorder()
driveItemJson, err := json.Marshal(libregraph.DriveItem{})
Expect(err).ToNot(HaveOccurred())
r := httptest.NewRequest(http.MethodPost, "/", bytes.NewBuffer(driveItemJson)).
WithContext(
context.WithValue(context.Background(), chi.RouteCtxKey, rCTX),
)
drivesDriveItemProvider.
EXPECT().
GetShare(mock.Anything, mock.Anything).
Return(nil, nil).
Once()
drivesDriveItemProvider.
EXPECT().
GetShares(mock.Anything, mock.Anything, mock.Anything).
Return(nil, errors.New("some error")).
Once()
@@ -587,7 +642,13 @@ var _ = Describe("DrivesDriveItemApi", func() {
drivesDriveItemProvider.
EXPECT().
GetShareAndSiblings(mock.Anything, mock.Anything, mock.Anything).
GetShare(mock.Anything, mock.Anything).
Return(nil, nil).
Once()
drivesDriveItemProvider.
EXPECT().
GetShares(mock.Anything, mock.Anything, mock.Anything).
Return(nil, nil).
Once()
@@ -622,7 +683,13 @@ var _ = Describe("DrivesDriveItemApi", func() {
drivesDriveItemProvider.
EXPECT().
GetShareAndSiblings(mock.Anything, mock.Anything, mock.Anything).
GetShare(mock.Anything, mock.Anything).
Return(nil, nil).
Once()
drivesDriveItemProvider.
EXPECT().
GetShares(mock.Anything, mock.Anything, mock.Anything).
Return([]*collaborationv1beta1.ReceivedShare{}, nil).
Once()
@@ -663,7 +730,13 @@ var _ = Describe("DrivesDriveItemApi", func() {
drivesDriveItemProvider.
EXPECT().
GetShareAndSiblings(mock.Anything, mock.Anything, mock.Anything).
GetShare(mock.Anything, mock.Anything).
Return(nil, nil).
Once()
drivesDriveItemProvider.
EXPECT().
GetShares(mock.Anything, mock.Anything, mock.Anything).
Return([]*collaborationv1beta1.ReceivedShare{share}, nil).
Once()