From 45a367325dc4a0c9924ae55e63fe3a408811e0a3 Mon Sep 17 00:00:00 2001 From: Michael Barz Date: Tue, 16 Apr 2024 00:09:51 +0200 Subject: [PATCH] tests: add unit tests for public share provider --- .../unreleased/fix-public-share-update.md | 1 + .../publicshareprovider.go | 10 +- .../publicshareprovider_suite_test.go | 13 + .../publicshareprovider_test.go | 358 ++++++++++++++++++ pkg/publicshare/mocks/Manager.go | 201 ++++++++++ 5 files changed, 578 insertions(+), 5 deletions(-) create mode 100644 internal/grpc/services/publicshareprovider/publicshareprovider_suite_test.go create mode 100644 internal/grpc/services/publicshareprovider/publicshareprovider_test.go create mode 100644 pkg/publicshare/mocks/Manager.go diff --git a/changelog/unreleased/fix-public-share-update.md b/changelog/unreleased/fix-public-share-update.md index ce0fb4f490..acf5a1283e 100644 --- a/changelog/unreleased/fix-public-share-update.md +++ b/changelog/unreleased/fix-public-share-update.md @@ -2,4 +2,5 @@ Bugfix: Fix public share update We fixed the permission check for updating public shares. When updating the permissions of a public share while not providing a password, the check must be against the new permissions to take into account that users can opt out only for view permissions. +https://github.com/cs3org/reva/pull/4633 https://github.com/cs3org/reva/pull/4622 \ No newline at end of file diff --git a/internal/grpc/services/publicshareprovider/publicshareprovider.go b/internal/grpc/services/publicshareprovider/publicshareprovider.go index c28e694a34..3c60766906 100644 --- a/internal/grpc/services/publicshareprovider/publicshareprovider.go +++ b/internal/grpc/services/publicshareprovider/publicshareprovider.go @@ -109,7 +109,7 @@ func (s *service) Register(ss *grpc.Server) { link.RegisterLinkAPIServer(ss, s) } -func parseConfig(m map[string]interface{}) (*config, error) { +func ParseConfig(m map[string]interface{}) (*config, error) { c := &config{} if err := mapstructure.Decode(m, c); err != nil { err = errors.Wrap(err, "error decoding config") @@ -118,7 +118,7 @@ func parseConfig(m map[string]interface{}) (*config, error) { return c, nil } -func parsePasswordPolicy(m map[string]interface{}) (*passwordPolicy, error) { +func ParsePasswordPolicy(m map[string]interface{}) (*passwordPolicy, error) { p := &passwordPolicy{} if err := mapstructure.Decode(m, p); err != nil { err = errors.Wrap(err, "error decoding password policy config") @@ -129,11 +129,11 @@ func parsePasswordPolicy(m map[string]interface{}) (*passwordPolicy, error) { // New creates a new public share provider svc initialized from defaults func NewDefault(m map[string]interface{}, ss *grpc.Server) (rgrpc.Service, error) { - c, err := parseConfig(m) + c, err := ParseConfig(m) if err != nil { return nil, err } - p, err := parsePasswordPolicy(c.PasswordPolicy) + p, err := ParsePasswordPolicy(c.PasswordPolicy) if err != nil { return nil, err } @@ -149,7 +149,7 @@ func NewDefault(m map[string]interface{}, ss *grpc.Server) (rgrpc.Service, error if err != nil { return nil, err } - return New(gatewaySelector, sm, c, p), nil + return New(gatewaySelector, sm, c, p) } // New creates a new user share provider svc diff --git a/internal/grpc/services/publicshareprovider/publicshareprovider_suite_test.go b/internal/grpc/services/publicshareprovider/publicshareprovider_suite_test.go new file mode 100644 index 0000000000..a3b911ce8f --- /dev/null +++ b/internal/grpc/services/publicshareprovider/publicshareprovider_suite_test.go @@ -0,0 +1,13 @@ +package publicshareprovider_test + +import ( + "testing" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +func TestPublicShareProvider(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "PublicShareProvider Suite") +} diff --git a/internal/grpc/services/publicshareprovider/publicshareprovider_test.go b/internal/grpc/services/publicshareprovider/publicshareprovider_test.go new file mode 100644 index 0000000000..2a38ea7225 --- /dev/null +++ b/internal/grpc/services/publicshareprovider/publicshareprovider_test.go @@ -0,0 +1,358 @@ +package publicshareprovider_test + +import ( + "context" + + gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1" + userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" + permissions "github.com/cs3org/go-cs3apis/cs3/permissions/v1beta1" + rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" + link "github.com/cs3org/go-cs3apis/cs3/sharing/link/v1beta1" + providerpb "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" + "github.com/cs3org/reva/v2/internal/grpc/services/publicshareprovider" + ctxpkg "github.com/cs3org/reva/v2/pkg/ctx" + "github.com/cs3org/reva/v2/pkg/publicshare" + "github.com/cs3org/reva/v2/pkg/publicshare/manager/registry" + "github.com/cs3org/reva/v2/pkg/publicshare/mocks" + "github.com/cs3org/reva/v2/pkg/rgrpc/status" + "github.com/cs3org/reva/v2/pkg/rgrpc/todo/pool" + cs3mocks "github.com/cs3org/reva/v2/tests/cs3mocks/mocks" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + "github.com/pkg/errors" + "github.com/stretchr/testify/mock" + "google.golang.org/grpc" +) + +var _ = Describe("PublicShareProvider Service", func() { + // create some objects to reduce boilerplate within the individual tests + var ( + ctx context.Context + checkPermissionResponse *permissions.CheckPermissionResponse + statResourceResponse *providerpb.StatResponse + provider link.LinkAPIServer + manager *mocks.Manager + gatewayClient *cs3mocks.GatewayAPIClient + gatewaySelector pool.Selectable[gateway.GatewayAPIClient] + resourcePermissions *providerpb.ResourcePermissions + linkPermissions *providerpb.ResourcePermissions + createdLink *link.PublicShare + revaConfig map[string]interface{} + ) + + BeforeEach(func() { + manager = &mocks.Manager{} + + registry.Register("mockManager", func(m map[string]interface{}) (publicshare.Manager, error) { + return manager, nil + }) + + pool.RemoveSelector("GatewaySelector" + "any") + gatewayClient = &cs3mocks.GatewayAPIClient{} + gatewaySelector = pool.GetSelector[gateway.GatewayAPIClient]( + "GatewaySelector", + "any", + func(cc *grpc.ClientConn) gateway.GatewayAPIClient { + return gatewayClient + }, + ) + + checkPermissionResponse = &permissions.CheckPermissionResponse{ + Status: status.NewOK(ctx), + } + gatewayClient.On("CheckPermission", mock.Anything, mock.Anything). + Return(checkPermissionResponse, nil) + + resourcePermissions = &providerpb.ResourcePermissions{ + // all permissions + AddGrant: true, + CreateContainer: true, + Delete: true, + GetPath: true, + GetQuota: true, + InitiateFileDownload: true, + InitiateFileUpload: true, + ListContainer: true, + ListFileVersions: true, + ListGrants: true, + ListRecycle: true, + Move: true, + PurgeRecycle: true, + RemoveGrant: true, + RestoreFileVersion: true, + RestoreRecycleItem: true, + Stat: true, + UpdateGrant: true, + DenyGrant: true, + } + + statResourceResponse = &providerpb.StatResponse{ + Status: status.NewOK(ctx), + Info: &providerpb.ResourceInfo{ + Type: providerpb.ResourceType_RESOURCE_TYPE_FILE, + Path: "./file.txt", + PermissionSet: resourcePermissions, + }, + } + gatewayClient.On("Stat", mock.Anything, mock.Anything).Return(statResourceResponse, nil) + + linkPermissions = &providerpb.ResourcePermissions{ + Stat: true, + CreateContainer: true, + Delete: true, + GetPath: true, + InitiateFileDownload: true, + InitiateFileUpload: true, + } + + createdLink = &link.PublicShare{ + PasswordProtected: true, + Permissions: &link.PublicSharePermissions{ + Permissions: linkPermissions, + }, + } + + revaConfig = map[string]interface{}{ + "driver": "mockManager", + "drivers": map[string]map[string]interface{}{ + "jsoncs3": { + "provider_addr": "com.owncloud.api.storage-system", + "service_user_idp": "internal", + "enable_expired_shares_cleanup": true, + "gateway_addr": "https://localhost:9200", + }, + }, + "gateway_addr": "https://localhost:9200", + "allowed_paths_for_shares": []string{"/NewFolder"}, + "writeable_share_must_have_password": false, + "public_share_must_have_password": true, + "password_policy": map[string]interface{}{ + "min_digits": 1, + "min_characters": 8, + "min_lowercase_characters": 1, + "min_uppercase_characters": 1, + "min_special_characters": 1, + "banned_passwords_list": map[string]struct{}{ + "SecretPasswrd1!": {}, + }, + }, + } + config, err := publicshareprovider.ParseConfig(revaConfig) + Expect(err).ToNot(HaveOccurred()) + passwordPolicy, err := publicshareprovider.ParsePasswordPolicy(config.PasswordPolicy) + Expect(err).ToNot(HaveOccurred()) + publicshareproviderService, err := publicshareprovider.New(gatewaySelector, manager, config, passwordPolicy) + Expect(err).ToNot(HaveOccurred()) + provider = publicshareproviderService.(link.LinkAPIServer) + Expect(provider).ToNot(BeNil()) + + ctx = ctxpkg.ContextSetUser(context.Background(), &userpb.User{ + Id: &userpb.UserId{ + OpaqueId: "alice", + }, + Username: "alice", + }) + }) + Describe("CreatePublicShare", func() { + It("creates a public share with password", func() { + manager.On("CreatePublicShare", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(createdLink, nil) + + req := &link.CreatePublicShareRequest{ + ResourceInfo: &providerpb.ResourceInfo{ + Owner: &userpb.UserId{ + OpaqueId: "alice", + }, + Path: "./NewFolder/file.txt", + }, + Grant: &link.Grant{ + Permissions: &link.PublicSharePermissions{ + Permissions: linkPermissions, + }, + Password: "SecretPassw0rd!", + }, + Description: "test", + } + + res, err := provider.CreatePublicShare(ctx, req) + Expect(err).ToNot(HaveOccurred()) + Expect(res.Status).To(Equal(status.NewOK(ctx))) + Expect(res.Share).To(Equal(createdLink)) + }) + It("has no user permission to create public share", func() { + gatewayClient.On("CheckPermission", mock.Anything, mock.Anything).Unset() + checkPermissionResponse = &permissions.CheckPermissionResponse{ + Status: status.NewPermissionDenied(ctx, nil, "permission denied"), + } + gatewayClient.On("CheckPermission", mock.Anything, mock.Anything).Return(checkPermissionResponse, nil) + + req := &link.CreatePublicShareRequest{} + + res, err := provider.CreatePublicShare(ctx, req) + Expect(err).ToNot(HaveOccurred()) + Expect(res.Status.Code).To(Equal(rpc.Code_CODE_PERMISSION_DENIED)) + Expect(res.Status.Message).To(Equal("no permission to create public links")) + }) + It("has permission to create internal link", func() { + linkPermissions := &providerpb.ResourcePermissions{} + + manager.On("CreatePublicShare", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(createdLink, nil) + + req := &link.CreatePublicShareRequest{ + ResourceInfo: &providerpb.ResourceInfo{ + Owner: &userpb.UserId{ + OpaqueId: "alice", + }, + Path: "./NewFolder/file.txt", + }, + Grant: &link.Grant{ + Permissions: &link.PublicSharePermissions{ + Permissions: linkPermissions, + }, + }, + Description: "test", + } + + res, err := provider.CreatePublicShare(ctx, req) + Expect(err).ToNot(HaveOccurred()) + Expect(res.Status.Code).To(Equal(rpc.Code_CODE_OK)) + Expect(res.Share).To(Equal(createdLink)) + }) + It("has no share permission on the resource to create internal link", func() { + linkPermissions := &providerpb.ResourcePermissions{} + + resourcePermissions.AddGrant = false + + req := &link.CreatePublicShareRequest{ + ResourceInfo: &providerpb.ResourceInfo{ + Owner: &userpb.UserId{ + OpaqueId: "alice", + }, + Path: "./NewFolder/file.txt", + }, + Grant: &link.Grant{ + Permissions: &link.PublicSharePermissions{ + Permissions: linkPermissions, + }, + }, + Description: "test", + } + + res, err := provider.CreatePublicShare(ctx, req) + Expect(err).ToNot(HaveOccurred()) + Expect(res.Status.Code).To(Equal(rpc.Code_CODE_INVALID_ARGUMENT)) + Expect(res.Status.Message).To(Equal("no share permission")) + }) + It("fails to check create public share user permission", func() { + gatewayClient.On("CheckPermission", mock.Anything, mock.Anything).Unset() + gatewayClient.On("CheckPermission", mock.Anything, mock.Anything).Return(nil, errors.New("transport error")) + + req := &link.CreatePublicShareRequest{} + + res, err := provider.CreatePublicShare(ctx, req) + Expect(err).To(HaveOccurred()) + Expect(res.Status.Code).To(Equal(rpc.Code_CODE_INTERNAL)) + Expect(res.Status.Message).To(Equal("failed check user permission to write public link")) + }) + It("has no share permission on the resource", func() { + req := &link.CreatePublicShareRequest{} + + resourcePermissions.AddGrant = false + + res, err := provider.CreatePublicShare(ctx, req) + Expect(err).ToNot(HaveOccurred()) + Expect(res.Status.Code).To(Equal(rpc.Code_CODE_INVALID_ARGUMENT)) + Expect(res.Status.Message).To(Equal("no share permission")) + }) + It("tries to share with higher permissions than granted on the resource", func() { + resourcePermissions.Delete = false + + req := &link.CreatePublicShareRequest{ + Grant: &link.Grant{ + Permissions: &link.PublicSharePermissions{ + Permissions: linkPermissions, + }, + }, + } + + res, err := provider.CreatePublicShare(ctx, req) + Expect(err).ToNot(HaveOccurred()) + Expect(res.Status.Code).To(Equal(rpc.Code_CODE_INVALID_ARGUMENT)) + Expect(res.Status.Message).To(Equal("insufficient permissions to create that kind of share")) + }) + It("tries to share inside a path which is not allowed", func() { + req := &link.CreatePublicShareRequest{ + ResourceInfo: &providerpb.ResourceInfo{ + Owner: &userpb.UserId{ + OpaqueId: "alice", + }, + Path: "./file.txt", + }, + Grant: &link.Grant{ + Permissions: &link.PublicSharePermissions{ + Permissions: linkPermissions, + }, + }, + } + + res, err := provider.CreatePublicShare(ctx, req) + Expect(err).ToNot(HaveOccurred()) + Expect(res.Status.Code).To(Equal(rpc.Code_CODE_FAILED_PRECONDITION)) + Expect(res.Status.Message).To(Equal("share creation is not allowed for the specified path")) + }) + It("tries to share personal space root", func() { + req := &link.CreatePublicShareRequest{ + ResourceInfo: &providerpb.ResourceInfo{ + Owner: &userpb.UserId{ + OpaqueId: "alice", + }, + Path: "./NewFolder/file.txt", + Id: &providerpb.ResourceId{ + StorageId: "storage-id", + OpaqueId: "admin-id", + SpaceId: "admin-id", + }, + Space: &providerpb.StorageSpace{SpaceType: "personal"}, + }, + Grant: &link.Grant{ + Permissions: &link.PublicSharePermissions{ + Permissions: linkPermissions, + }, + }, + } + + res, err := provider.CreatePublicShare(ctx, req) + Expect(err).ToNot(HaveOccurred()) + Expect(res.Status.Code).To(Equal(rpc.Code_CODE_INVALID_ARGUMENT)) + Expect(res.Status.Message).To(Equal("cannot create link on personal space root")) + }) + It("tries to share a project space root", func() { + manager.On("CreatePublicShare", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(createdLink, nil) + + req := &link.CreatePublicShareRequest{ + ResourceInfo: &providerpb.ResourceInfo{ + Owner: &userpb.UserId{ + OpaqueId: "alice", + }, + Path: "./NewFolder/file.txt", + Id: &providerpb.ResourceId{ + StorageId: "storage-id", + OpaqueId: "project-id", + SpaceId: "project-id", + }, + Space: &providerpb.StorageSpace{SpaceType: "project"}, + }, + Grant: &link.Grant{ + Permissions: &link.PublicSharePermissions{ + Permissions: linkPermissions, + }, + Password: "SecretPassw0rd!", + }, + } + + res, err := provider.CreatePublicShare(ctx, req) + Expect(err).ToNot(HaveOccurred()) + Expect(res.Status).To(Equal(status.NewOK(ctx))) + Expect(res.Share).To(Equal(createdLink)) + }) + }) +}) diff --git a/pkg/publicshare/mocks/Manager.go b/pkg/publicshare/mocks/Manager.go new file mode 100644 index 0000000000..4028905553 --- /dev/null +++ b/pkg/publicshare/mocks/Manager.go @@ -0,0 +1,201 @@ +// Code generated by mockery v2.38.0. DO NOT EDIT. + +package mocks + +import ( + context "context" + + linkv1beta1 "github.com/cs3org/go-cs3apis/cs3/sharing/link/v1beta1" + mock "github.com/stretchr/testify/mock" + + providerv1beta1 "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" + + userv1beta1 "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" +) + +// Manager is an autogenerated mock type for the Manager type +type Manager struct { + mock.Mock +} + +// CreatePublicShare provides a mock function with given fields: ctx, u, md, g +func (_m *Manager) CreatePublicShare(ctx context.Context, u *userv1beta1.User, md *providerv1beta1.ResourceInfo, g *linkv1beta1.Grant) (*linkv1beta1.PublicShare, error) { + ret := _m.Called(ctx, u, md, g) + + if len(ret) == 0 { + panic("no return value specified for CreatePublicShare") + } + + var r0 *linkv1beta1.PublicShare + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *userv1beta1.User, *providerv1beta1.ResourceInfo, *linkv1beta1.Grant) (*linkv1beta1.PublicShare, error)); ok { + return rf(ctx, u, md, g) + } + if rf, ok := ret.Get(0).(func(context.Context, *userv1beta1.User, *providerv1beta1.ResourceInfo, *linkv1beta1.Grant) *linkv1beta1.PublicShare); ok { + r0 = rf(ctx, u, md, g) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*linkv1beta1.PublicShare) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *userv1beta1.User, *providerv1beta1.ResourceInfo, *linkv1beta1.Grant) error); ok { + r1 = rf(ctx, u, md, g) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetPublicShare provides a mock function with given fields: ctx, u, ref, sign +func (_m *Manager) GetPublicShare(ctx context.Context, u *userv1beta1.User, ref *linkv1beta1.PublicShareReference, sign bool) (*linkv1beta1.PublicShare, error) { + ret := _m.Called(ctx, u, ref, sign) + + if len(ret) == 0 { + panic("no return value specified for GetPublicShare") + } + + var r0 *linkv1beta1.PublicShare + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *userv1beta1.User, *linkv1beta1.PublicShareReference, bool) (*linkv1beta1.PublicShare, error)); ok { + return rf(ctx, u, ref, sign) + } + if rf, ok := ret.Get(0).(func(context.Context, *userv1beta1.User, *linkv1beta1.PublicShareReference, bool) *linkv1beta1.PublicShare); ok { + r0 = rf(ctx, u, ref, sign) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*linkv1beta1.PublicShare) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *userv1beta1.User, *linkv1beta1.PublicShareReference, bool) error); ok { + r1 = rf(ctx, u, ref, sign) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetPublicShareByToken provides a mock function with given fields: ctx, token, auth, sign +func (_m *Manager) GetPublicShareByToken(ctx context.Context, token string, auth *linkv1beta1.PublicShareAuthentication, sign bool) (*linkv1beta1.PublicShare, error) { + ret := _m.Called(ctx, token, auth, sign) + + if len(ret) == 0 { + panic("no return value specified for GetPublicShareByToken") + } + + var r0 *linkv1beta1.PublicShare + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, string, *linkv1beta1.PublicShareAuthentication, bool) (*linkv1beta1.PublicShare, error)); ok { + return rf(ctx, token, auth, sign) + } + if rf, ok := ret.Get(0).(func(context.Context, string, *linkv1beta1.PublicShareAuthentication, bool) *linkv1beta1.PublicShare); ok { + r0 = rf(ctx, token, auth, sign) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*linkv1beta1.PublicShare) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, string, *linkv1beta1.PublicShareAuthentication, bool) error); ok { + r1 = rf(ctx, token, auth, sign) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ListPublicShares provides a mock function with given fields: ctx, u, filters, sign +func (_m *Manager) ListPublicShares(ctx context.Context, u *userv1beta1.User, filters []*linkv1beta1.ListPublicSharesRequest_Filter, sign bool) ([]*linkv1beta1.PublicShare, error) { + ret := _m.Called(ctx, u, filters, sign) + + if len(ret) == 0 { + panic("no return value specified for ListPublicShares") + } + + var r0 []*linkv1beta1.PublicShare + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *userv1beta1.User, []*linkv1beta1.ListPublicSharesRequest_Filter, bool) ([]*linkv1beta1.PublicShare, error)); ok { + return rf(ctx, u, filters, sign) + } + if rf, ok := ret.Get(0).(func(context.Context, *userv1beta1.User, []*linkv1beta1.ListPublicSharesRequest_Filter, bool) []*linkv1beta1.PublicShare); ok { + r0 = rf(ctx, u, filters, sign) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*linkv1beta1.PublicShare) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *userv1beta1.User, []*linkv1beta1.ListPublicSharesRequest_Filter, bool) error); ok { + r1 = rf(ctx, u, filters, sign) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// RevokePublicShare provides a mock function with given fields: ctx, u, ref +func (_m *Manager) RevokePublicShare(ctx context.Context, u *userv1beta1.User, ref *linkv1beta1.PublicShareReference) error { + ret := _m.Called(ctx, u, ref) + + if len(ret) == 0 { + panic("no return value specified for RevokePublicShare") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, *userv1beta1.User, *linkv1beta1.PublicShareReference) error); ok { + r0 = rf(ctx, u, ref) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// UpdatePublicShare provides a mock function with given fields: ctx, u, req +func (_m *Manager) UpdatePublicShare(ctx context.Context, u *userv1beta1.User, req *linkv1beta1.UpdatePublicShareRequest) (*linkv1beta1.PublicShare, error) { + ret := _m.Called(ctx, u, req) + + if len(ret) == 0 { + panic("no return value specified for UpdatePublicShare") + } + + var r0 *linkv1beta1.PublicShare + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *userv1beta1.User, *linkv1beta1.UpdatePublicShareRequest) (*linkv1beta1.PublicShare, error)); ok { + return rf(ctx, u, req) + } + if rf, ok := ret.Get(0).(func(context.Context, *userv1beta1.User, *linkv1beta1.UpdatePublicShareRequest) *linkv1beta1.PublicShare); ok { + r0 = rf(ctx, u, req) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*linkv1beta1.PublicShare) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *userv1beta1.User, *linkv1beta1.UpdatePublicShareRequest) error); ok { + r1 = rf(ctx, u, req) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// NewManager creates a new instance of Manager. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewManager(t interface { + mock.TestingT + Cleanup(func()) +}) *Manager { + mock := &Manager{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +}