From a8dfb10f8995476463b4c5452420256f182280c2 Mon Sep 17 00:00:00 2001 From: Michiel de Jong Date: Wed, 13 Oct 2021 09:51:21 +0200 Subject: [PATCH] Nextcloud edits (#2135) --- .../unreleased/nextcloud-test-improvements.md | 3 + pkg/auth/manager/nextcloud/nextcloud.go | 44 +- pkg/auth/manager/nextcloud/nextcloud_test.go | 46 ++- pkg/share/manager/nextcloud/nextcloud.go | 78 ++-- .../nextcloud/nextcloud_server_mock.go | 2 +- pkg/share/manager/nextcloud/nextcloud_test.go | 134 +++--- pkg/storage/fs/nextcloud/nextcloud.go | 24 +- .../fs/nextcloud/nextcloud_server_mock.go | 31 +- pkg/storage/fs/nextcloud/nextcloud_test.go | 381 +++++------------- pkg/user/manager/nextcloud/nextcloud.go | 56 ++- pkg/user/manager/nextcloud/nextcloud_test.go | 78 ++-- 11 files changed, 409 insertions(+), 468 deletions(-) create mode 100644 changelog/unreleased/nextcloud-test-improvements.md diff --git a/changelog/unreleased/nextcloud-test-improvements.md b/changelog/unreleased/nextcloud-test-improvements.md new file mode 100644 index 0000000000..4f5c1042cb --- /dev/null +++ b/changelog/unreleased/nextcloud-test-improvements.md @@ -0,0 +1,3 @@ +Enhancement: Nextcloud test improvements + +https://github.com/cs3org/reva/pull/2135 diff --git a/pkg/auth/manager/nextcloud/nextcloud.go b/pkg/auth/manager/nextcloud/nextcloud.go index c355f4a5a8..7992f36e59 100644 --- a/pkg/auth/manager/nextcloud/nextcloud.go +++ b/pkg/auth/manager/nextcloud/nextcloud.go @@ -39,7 +39,9 @@ func init() { registry.Register("nextcloud", New) } -type mgr struct { +// Manager is the Nextcloud-based implementation of the auth.Manager interface +// see https://github.com/cs3org/reva/blob/v1.13.0/pkg/auth/auth.go#L32-L35 +type Manager struct { client *http.Client endPoint string } @@ -47,6 +49,7 @@ type mgr struct { // AuthManagerConfig contains config for a Nextcloud-based AuthManager type AuthManagerConfig struct { EndPoint string `mapstructure:"endpoint" docs:";The Nextcloud backend endpoint for user check"` + MockHTTP bool `mapstructure:"mock_http"` } // Action describes a REST request to forward to the Nextcloud backend @@ -76,29 +79,42 @@ func New(m map[string]interface{}) (auth.Manager, error) { } c.init() - return NewAuthManager(c, &http.Client{}) + return NewAuthManager(c) } // NewAuthManager returns a new Nextcloud-based AuthManager -func NewAuthManager(c *AuthManagerConfig, hc *http.Client) (auth.Manager, error) { - return &mgr{ +func NewAuthManager(c *AuthManagerConfig) (*Manager, error) { + var client *http.Client + if c.MockHTTP { + // called := make([]string, 0) + // nextcloudServerMock := GetNextcloudServerMock(&called) + // client, _ = TestingHTTPClient(nextcloudServerMock) + + // Wait for SetHTTPClient to be called later + client = nil + } else { + client = &http.Client{} + } + + return &Manager{ endPoint: c.EndPoint, // e.g. "http://nc/apps/sciencemesh/" - client: hc, + client: client, }, nil } -func (am *mgr) Configure(ml map[string]interface{}) error { +// Configure method as defined in https://github.com/cs3org/reva/blob/v1.13.0/pkg/auth/auth.go#L32-L35 +func (am *Manager) Configure(ml map[string]interface{}) error { return nil } -func (am *mgr) do(ctx context.Context, a Action) (int, []byte, error) { +// SetHTTPClient sets the HTTP client +func (am *Manager) SetHTTPClient(c *http.Client) { + am.client = c +} + +func (am *Manager) do(ctx context.Context, a Action) (int, []byte, error) { log := appctx.GetLogger(ctx) - // user, err := getUser(ctx) - // if err != nil { - // return 0, nil, err - // } - // url := am.endPoint + "~" + a.username + "/api/" + a.verb - url := "http://localhost/apps/sciencemesh/~" + a.username + "/api/auth/" + a.verb + url := am.endPoint + "~" + a.username + "/api/auth/" + a.verb log.Info().Msgf("am.do %s %s", url, a.argS) req, err := http.NewRequest(http.MethodPost, url, strings.NewReader(a.argS)) if err != nil { @@ -122,7 +138,7 @@ func (am *mgr) do(ctx context.Context, a Action) (int, []byte, error) { } // Authenticate method as defined in https://github.com/cs3org/reva/blob/28500a8/pkg/auth/auth.go#L31-L33 -func (am *mgr) Authenticate(ctx context.Context, clientID, clientSecret string) (*user.User, map[string]*authpb.Scope, error) { +func (am *Manager) Authenticate(ctx context.Context, clientID, clientSecret string) (*user.User, map[string]*authpb.Scope, error) { type paramsObj struct { ClientID string `json:"clientID"` ClientSecret string `json:"clientSecret"` diff --git a/pkg/auth/manager/nextcloud/nextcloud_test.go b/pkg/auth/manager/nextcloud/nextcloud_test.go index b774b6e7ca..dd14b8a1e8 100644 --- a/pkg/auth/manager/nextcloud/nextcloud_test.go +++ b/pkg/auth/manager/nextcloud/nextcloud_test.go @@ -20,6 +20,7 @@ package nextcloud_test import ( "context" + "fmt" "os" "google.golang.org/grpc/metadata" @@ -38,6 +39,39 @@ import ( . "github.com/onsi/gomega" ) +func setUpNextcloudServer() (*nextcloud.Manager, *[]string, func()) { + var conf *nextcloud.AuthManagerConfig + + ncHost := os.Getenv("NEXTCLOUD") + fmt.Printf(`NEXTCLOUD env var: "%s"`, ncHost) + if len(ncHost) == 0 { + conf = &nextcloud.AuthManagerConfig{ + EndPoint: "http://mock.com/apps/sciencemesh/", + MockHTTP: true, + } + nc, _ := nextcloud.NewAuthManager(conf) + called := make([]string, 0) + h := nextcloud.GetNextcloudServerMock(&called) + mock, teardown := nextcloud.TestingHTTPClient(h) + nc.SetHTTPClient(mock) + return nc, &called, teardown + } + conf = &nextcloud.AuthManagerConfig{ + EndPoint: ncHost + "/apps/sciencemesh/", + MockHTTP: false, + } + nc, _ := nextcloud.NewAuthManager(conf) + return nc, nil, func() {} +} + +func checkCalled(called *[]string, expected string) { + if called == nil { + return + } + Expect(len(*called)).To(Equal(1)) + Expect((*called)[0]).To(Equal(expected)) +} + var _ = Describe("Nextcloud", func() { var ( ctx context.Context @@ -94,14 +128,9 @@ var _ = Describe("Nextcloud", func() { // Authenticate(ctx context.Context, clientID, clientSecret string) (*user.User, map[string]*authpb.Scope, error) Describe("Authenticate", func() { It("calls the GetHome endpoint", func() { - called := make([]string, 0) - - h := nextcloud.GetNextcloudServerMock(&called) - mock, teardown := nextcloud.TestingHTTPClient(h) + am, called, teardown := setUpNextcloudServer() defer teardown() - am, _ := nextcloud.NewAuthManager(&nextcloud.AuthManagerConfig{ - EndPoint: "http://mock.com/apps/sciencemesh/", - }, mock) + user, scope, err := am.Authenticate(ctx, "einstein", "relativity") Expect(err).ToNot(HaveOccurred()) Expect(user).To(Equal(&userpb.User{ @@ -128,8 +157,7 @@ var _ = Describe("Nextcloud", func() { Role: 1, }, })) - Expect(len(called)).To(Equal(1)) - Expect(called[0]).To(Equal(`POST /apps/sciencemesh/~einstein/api/auth/Authenticate {"clientID":"einstein","clientSecret":"relativity"}`)) + checkCalled(called, `POST /apps/sciencemesh/~einstein/api/auth/Authenticate {"clientID":"einstein","clientSecret":"relativity"}`) }) }) diff --git a/pkg/share/manager/nextcloud/nextcloud.go b/pkg/share/manager/nextcloud/nextcloud.go index c4ffdb94e8..69d5e41cf3 100644 --- a/pkg/share/manager/nextcloud/nextcloud.go +++ b/pkg/share/manager/nextcloud/nextcloud.go @@ -46,7 +46,9 @@ func init() { registry.Register("nextcloud", New) } -type mgr struct { +// Manager is the Nextcloud-based implementation of the share.Manager interface +// see https://github.com/cs3org/reva/blob/v1.13.0/pkg/share/share.go#L29-L54 +type Manager struct { client *http.Client endPoint string } @@ -54,6 +56,7 @@ type mgr struct { // ShareManagerConfig contains config for a Nextcloud-based ShareManager type ShareManagerConfig struct { EndPoint string `mapstructure:"endpoint" docs:";The Nextcloud backend endpoint for user check"` + MockHTTP bool `mapstructure:"mock_http"` } // Action describes a REST request to forward to the Nextcloud backend @@ -108,7 +111,7 @@ func getUser(ctx context.Context) (*userpb.User, error) { return u, nil } -// New returns an share manager implementation that verifies against a Nextcloud backend. +// New returns a share manager implementation that verifies against a Nextcloud backend. func New(m map[string]interface{}) (share.Manager, error) { c, err := parseConfig(m) if err != nil { @@ -116,25 +119,44 @@ func New(m map[string]interface{}) (share.Manager, error) { } c.init() - return NewShareManager(c, &http.Client{}) + return NewShareManager(c) } // NewShareManager returns a new Nextcloud-based ShareManager -func NewShareManager(c *ShareManagerConfig, hc *http.Client) (share.Manager, error) { - return &mgr{ +func NewShareManager(c *ShareManagerConfig) (*Manager, error) { + var client *http.Client + if c.MockHTTP { + // called := make([]string, 0) + // nextcloudServerMock := GetNextcloudServerMock(&called) + // client, _ = TestingHTTPClient(nextcloudServerMock) + + // Wait for SetHTTPClient to be called later + client = nil + } else { + client = &http.Client{} + } + + return &Manager{ endPoint: c.EndPoint, // e.g. "http://nc/apps/sciencemesh/" - client: hc, + client: client, }, nil } -func (sm *mgr) do(ctx context.Context, a Action) (int, []byte, error) { +// SetHTTPClient sets the HTTP client +func (sm *Manager) SetHTTPClient(c *http.Client) { + sm.client = c +} + +func (sm *Manager) do(ctx context.Context, a Action) (int, []byte, error) { log := appctx.GetLogger(ctx) user, err := getUser(ctx) if err != nil { return 0, nil, err } // url := am.endPoint + "~" + a.username + "/api/" + a.verb - url := "http://localhost/apps/sciencemesh/~" + user.Username + "/api/share/" + a.verb + // url := "http://localhost/apps/sciencemesh/~" + user.Username + "/api/share/" + a.verb + url := sm.endPoint + "~" + user.Username + "/api/share/" + a.verb + log.Info().Msgf("am.do %s %s", url, a.argS) req, err := http.NewRequest(http.MethodPost, url, strings.NewReader(a.argS)) if err != nil { @@ -157,7 +179,9 @@ func (sm *mgr) do(ctx context.Context, a Action) (int, []byte, error) { return resp.StatusCode, body, nil } -func (sm *mgr) Share(ctx context.Context, md *provider.ResourceInfo, g *collaboration.ShareGrant) (*collaboration.Share, error) { +// Share as defined in the share.Manager interface +// https://github.com/cs3org/reva/blob/v1.13.0/pkg/share/share.go#L29-L54 +func (sm *Manager) Share(ctx context.Context, md *provider.ResourceInfo, g *collaboration.ShareGrant) (*collaboration.Share, error) { type paramsObj struct { Md *provider.ResourceInfo `json:"md"` G *collaboration.ShareGrant `json:"g"` @@ -196,8 +220,9 @@ func (sm *mgr) Share(ctx context.Context, md *provider.ResourceInfo, g *collabor }, err } -// GetShare gets the information for a share by the given ref. -func (sm *mgr) GetShare(ctx context.Context, ref *collaboration.ShareReference) (*collaboration.Share, error) { +// GetShare as defined in the share.Manager interface +// https://github.com/cs3org/reva/blob/v1.13.0/pkg/share/share.go#L29-L54 +func (sm *Manager) GetShare(ctx context.Context, ref *collaboration.ShareReference) (*collaboration.Share, error) { bodyStr, err := json.Marshal(ref) if err != nil { return nil, err @@ -226,8 +251,9 @@ func (sm *mgr) GetShare(ctx context.Context, ref *collaboration.ShareReference) }, err } -// Unshare deletes the share pointed by ref. -func (sm *mgr) Unshare(ctx context.Context, ref *collaboration.ShareReference) error { +// Unshare as defined in the share.Manager interface +// https://github.com/cs3org/reva/blob/v1.13.0/pkg/share/share.go#L29-L54 +func (sm *Manager) Unshare(ctx context.Context, ref *collaboration.ShareReference) error { bodyStr, err := json.Marshal(ref) if err != nil { return err @@ -237,8 +263,9 @@ func (sm *mgr) Unshare(ctx context.Context, ref *collaboration.ShareReference) e return err } -// UpdateShare updates the mode of the given share. -func (sm *mgr) UpdateShare(ctx context.Context, ref *collaboration.ShareReference, p *collaboration.SharePermissions) (*collaboration.Share, error) { +// UpdateShare as defined in the share.Manager interface +// https://github.com/cs3org/reva/blob/v1.13.0/pkg/share/share.go#L29-L54 +func (sm *Manager) UpdateShare(ctx context.Context, ref *collaboration.ShareReference, p *collaboration.SharePermissions) (*collaboration.Share, error) { type paramsObj struct { Ref *collaboration.ShareReference `json:"ref"` P *collaboration.SharePermissions `json:"p"` @@ -277,9 +304,9 @@ func (sm *mgr) UpdateShare(ctx context.Context, ref *collaboration.ShareReferenc }, err } -// ListShares returns the shares created by the user. If md is provided is not nil, -// it returns only shares attached to the given resource. -func (sm *mgr) ListShares(ctx context.Context, filters []*collaboration.Filter) ([]*collaboration.Share, error) { +// ListShares as defined in the share.Manager interface +// https://github.com/cs3org/reva/blob/v1.13.0/pkg/share/share.go#L29-L54 +func (sm *Manager) ListShares(ctx context.Context, filters []*collaboration.Filter) ([]*collaboration.Share, error) { bodyStr, err := json.Marshal(filters) if err != nil { return nil, err @@ -315,8 +342,9 @@ func (sm *mgr) ListShares(ctx context.Context, filters []*collaboration.Filter) return pointers, err } -// ListReceivedShares returns the list of shares the user has access. -func (sm *mgr) ListReceivedShares(ctx context.Context, filters []*collaboration.Filter) ([]*collaboration.ReceivedShare, error) { +// ListReceivedShares as defined in the share.Manager interface +// https://github.com/cs3org/reva/blob/v1.13.0/pkg/share/share.go#L29-L54 +func (sm *Manager) ListReceivedShares(ctx context.Context, filters []*collaboration.Filter) ([]*collaboration.ReceivedShare, error) { bodyStr, err := json.Marshal(filters) if err != nil { return nil, err @@ -362,8 +390,9 @@ func (sm *mgr) ListReceivedShares(ctx context.Context, filters []*collaboration. } -// GetReceivedShare returns the information for a received share the user has access. -func (sm *mgr) GetReceivedShare(ctx context.Context, ref *collaboration.ShareReference) (*collaboration.ReceivedShare, error) { +// GetReceivedShare as defined in the share.Manager interface +// https://github.com/cs3org/reva/blob/v1.13.0/pkg/share/share.go#L29-L54 +func (sm *Manager) GetReceivedShare(ctx context.Context, ref *collaboration.ShareReference) (*collaboration.ReceivedShare, error) { bodyStr, err := json.Marshal(ref) if err != nil { return nil, err @@ -403,8 +432,9 @@ func (sm *mgr) GetReceivedShare(ctx context.Context, ref *collaboration.ShareRef }, err } -// UpdateReceivedShare updates the received share with share state. -func (sm *mgr) UpdateReceivedShare(ctx context.Context, receivedShare *collaboration.ReceivedShare, fieldMask *field_mask.FieldMask) (*collaboration.ReceivedShare, error) { +// UpdateReceivedShare as defined in the share.Manager interface +// https://github.com/cs3org/reva/blob/v1.13.0/pkg/share/share.go#L29-L54 +func (sm Manager) UpdateReceivedShare(ctx context.Context, receivedShare *collaboration.ReceivedShare, fieldMask *field_mask.FieldMask) (*collaboration.ReceivedShare, error) { type paramsObj struct { ReceivedShare *collaboration.ReceivedShare `json:"received_share"` FieldMask *field_mask.FieldMask `json:"field_mask"` diff --git a/pkg/share/manager/nextcloud/nextcloud_server_mock.go b/pkg/share/manager/nextcloud/nextcloud_server_mock.go index 1a865b9bf8..023da07293 100644 --- a/pkg/share/manager/nextcloud/nextcloud_server_mock.go +++ b/pkg/share/manager/nextcloud/nextcloud_server_mock.go @@ -43,7 +43,7 @@ const serverStateHome = "HOME" var serverState = serverStateEmpty var responses = map[string]Response{ - `POST /apps/sciencemesh/~tester/api/share/Share {"md":{"opaque":{},"type":1,"id":{"opaque_id":"fileid-/some/path"},"checksum":{},"etag":"deadbeef","mime_type":"text/plain","mtime":{"seconds":1234567890},"path":"/some/path","permission_set":{},"size":12345,"canonical_metadata":{},"arbitrary_metadata":{"metadata":{"da":"ta","some":"arbi","trary":"meta"}}},"g":{"grantee":{"Id":null},"permissions":{"permissions":{}}}}`: {200, `{"id":{},"resource_id":{},"permissions":{"permissions":{"add_grant":true,"create_container":true,"delete":true,"get_path":true,"get_quota":true,"initiate_file_download":true,"initiate_file_upload":true,"list_grants":true,"list_container":true,"list_file_versions":true,"list_recycle":true,"move":true,"remove_grant":true,"purge_recycle":true,"restore_file_version":true,"restore_recycle_item":true,"stat":true,"update_grant":true,"deny_grant":true}},"grantee":{"Id":{"UserId":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1}}},"owner":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1},"creator":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1},"ctime":{"seconds":1234567890},"mtime":{"seconds":1234567890}}`, serverStateHome}, + `POST /apps/sciencemesh/~tester/api/share/Share {"md":{"opaque":{},"type":1,"id":{"opaque_id":"fileid-/some/path"},"checksum":{},"etag":"deadbeef","mime_type":"text/plain","mtime":{"seconds":1234567890},"path":"/some/path","permission_set":{},"size":12345,"canonical_metadata":{},"arbitrary_metadata":{"metadata":{"da":"ta","some":"arbi","trary":"meta"}}},"g":{"grantee":{"Id":{"UserId":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1}}},"permissions":{"permissions":{}}}}`: {200, `{"id":{},"resource_id":{},"permissions":{"permissions":{"add_grant":true,"create_container":true,"delete":true,"get_path":true,"get_quota":true,"initiate_file_download":true,"initiate_file_upload":true,"list_grants":true,"list_container":true,"list_file_versions":true,"list_recycle":true,"move":true,"remove_grant":true,"purge_recycle":true,"restore_file_version":true,"restore_recycle_item":true,"stat":true,"update_grant":true,"deny_grant":true}},"grantee":{"Id":{"UserId":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1}}},"owner":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1},"creator":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1},"ctime":{"seconds":1234567890},"mtime":{"seconds":1234567890}}`, serverStateHome}, `POST /apps/sciencemesh/~tester/api/share/GetShare {"Spec":{"Id":{"opaque_id":"some-share-id"}}}`: {200, `{"id":{},"resource_id":{},"permissions":{"permissions":{"add_grant":true,"create_container":true,"delete":true,"get_path":true,"get_quota":true,"initiate_file_download":true,"initiate_file_upload":true,"list_grants":true,"list_container":true,"list_file_versions":true,"list_recycle":true,"move":true,"remove_grant":true,"purge_recycle":true,"restore_file_version":true,"restore_recycle_item":true,"stat":true,"update_grant":true,"deny_grant":true}},"grantee":{"Id":{"UserId":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1}}},"owner":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1},"creator":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1},"ctime":{"seconds":1234567890},"mtime":{"seconds":1234567890}}`, serverStateHome}, `POST /apps/sciencemesh/~tester/api/share/Unshare {"Spec":{"Id":{"opaque_id":"some-share-id"}}}`: {200, ``, serverStateHome}, `POST /apps/sciencemesh/~tester/api/share/UpdateShare {"ref":{"Spec":{"Id":{"opaque_id":"some-share-id"}}},"p":{"permissions":{"add_grant":true,"create_container":true,"delete":true,"get_path":true,"get_quota":true,"initiate_file_download":true,"initiate_file_upload":true,"list_grants":true,"list_container":true,"list_file_versions":true,"list_recycle":true,"move":true,"remove_grant":true,"purge_recycle":true,"restore_file_version":true,"restore_recycle_item":true,"stat":true,"update_grant":true,"deny_grant":true}}}`: {200, `{"id":{},"resource_id":{},"permissions":{"permissions":{"add_grant":true,"create_container":true,"delete":true,"get_path":true,"get_quota":true,"initiate_file_download":true,"initiate_file_upload":true,"list_grants":true,"list_container":true,"list_file_versions":true,"list_recycle":true,"move":true,"remove_grant":true,"purge_recycle":true,"restore_file_version":true,"restore_recycle_item":true,"stat":true,"update_grant":true,"deny_grant":true}},"grantee":{"Id":{"UserId":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1}}},"owner":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1},"creator":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1},"ctime":{"seconds":1234567890},"mtime":{"seconds":1234567890}}`, serverStateHome}, diff --git a/pkg/share/manager/nextcloud/nextcloud_test.go b/pkg/share/manager/nextcloud/nextcloud_test.go index f6f86b3857..2284560035 100644 --- a/pkg/share/manager/nextcloud/nextcloud_test.go +++ b/pkg/share/manager/nextcloud/nextcloud_test.go @@ -20,6 +20,7 @@ package nextcloud_test import ( "context" + "fmt" "os" "google.golang.org/genproto/protobuf/field_mask" @@ -32,6 +33,7 @@ import ( "github.com/cs3org/reva/pkg/auth/scope" ctxpkg "github.com/cs3org/reva/pkg/ctx" + "github.com/cs3org/reva/pkg/share/manager/nextcloud" jwt "github.com/cs3org/reva/pkg/token/manager/jwt" "github.com/cs3org/reva/tests/helpers" @@ -40,6 +42,39 @@ import ( . "github.com/onsi/gomega" ) +func setUpNextcloudServer() (*nextcloud.Manager, *[]string, func()) { + var conf *nextcloud.ShareManagerConfig + + ncHost := os.Getenv("NEXTCLOUD") + fmt.Printf(`NEXTCLOUD env var: "%s"`, ncHost) + if len(ncHost) == 0 { + conf = &nextcloud.ShareManagerConfig{ + EndPoint: "http://mock.com/apps/sciencemesh/", + MockHTTP: true, + } + nc, _ := nextcloud.NewShareManager(conf) + called := make([]string, 0) + h := nextcloud.GetNextcloudServerMock(&called) + mock, teardown := nextcloud.TestingHTTPClient(h) + nc.SetHTTPClient(mock) + return nc, &called, teardown + } + conf = &nextcloud.ShareManagerConfig{ + EndPoint: ncHost + "/apps/sciencemesh/", + MockHTTP: false, + } + nc, _ := nextcloud.NewShareManager(conf) + return nc, nil, func() {} +} + +func checkCalled(called *[]string, expected string) { + if called == nil { + return + } + Expect(len(*called)).To(Equal(1)) + Expect((*called)[0]).To(Equal(expected)) +} + var _ = Describe("Nextcloud", func() { var ( ctx context.Context @@ -96,14 +131,10 @@ var _ = Describe("Nextcloud", func() { // Share(ctx context.Context, md *provider.ResourceInfo, g *collaboration.ShareGrant) (*collaboration.Share, error) Describe("Share", func() { It("calls the Share endpoint", func() { - called := make([]string, 0) - - h := nextcloud.GetNextcloudServerMock(&called) - mock, teardown := nextcloud.TestingHTTPClient(h) + fmt.Println("Calling setUpNextCloudServer!") + am, called, teardown := setUpNextcloudServer() defer teardown() - am, _ := nextcloud.NewShareManager(&nextcloud.ShareManagerConfig{ - EndPoint: "http://mock.com/apps/sciencemesh/", - }, mock) + share, err := am.Share(ctx, &provider.ResourceInfo{ Opaque: &types.Opaque{ Map: nil, @@ -179,7 +210,15 @@ var _ = Describe("Nextcloud", func() { XXX_unrecognized: nil, XXX_sizecache: 0, }, &collaboration.ShareGrant{ - Grantee: &provider.Grantee{}, + Grantee: &provider.Grantee{ + Id: &provider.Grantee_UserId{ + UserId: &userpb.UserId{ + Idp: "0.0.0.0:19000", + OpaqueId: "f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c", + Type: userpb.UserType_USER_TYPE_PRIMARY, + }, + }, + }, Permissions: &collaboration.SharePermissions{ Permissions: &provider.ResourcePermissions{}, }, @@ -245,21 +284,16 @@ var _ = Describe("Nextcloud", func() { XXX_sizecache: 0, }, })) - Expect(called[0]).To(Equal(`POST /apps/sciencemesh/~tester/api/share/Share {"md":{"opaque":{},"type":1,"id":{"opaque_id":"fileid-/some/path"},"checksum":{},"etag":"deadbeef","mime_type":"text/plain","mtime":{"seconds":1234567890},"path":"/some/path","permission_set":{},"size":12345,"canonical_metadata":{},"arbitrary_metadata":{"metadata":{"da":"ta","some":"arbi","trary":"meta"}}},"g":{"grantee":{"Id":null},"permissions":{"permissions":{}}}}`)) + checkCalled(called, `POST /apps/sciencemesh/~tester/api/share/Share {"md":{"opaque":{},"type":1,"id":{"opaque_id":"fileid-/some/path"},"checksum":{},"etag":"deadbeef","mime_type":"text/plain","mtime":{"seconds":1234567890},"path":"/some/path","permission_set":{},"size":12345,"canonical_metadata":{},"arbitrary_metadata":{"metadata":{"da":"ta","some":"arbi","trary":"meta"}}},"g":{"grantee":{"Id":{"UserId":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1}}},"permissions":{"permissions":{}}}}`) }) }) // GetShare(ctx context.Context, ref *collaboration.ShareReference) (*collaboration.Share, error) Describe("GetShare", func() { It("calls the GetShare endpoint", func() { - called := make([]string, 0) - - h := nextcloud.GetNextcloudServerMock(&called) - mock, teardown := nextcloud.TestingHTTPClient(h) + am, called, teardown := setUpNextcloudServer() defer teardown() - am, _ := nextcloud.NewShareManager(&nextcloud.ShareManagerConfig{ - EndPoint: "http://mock.com/apps/sciencemesh/", - }, mock) + share, err := am.GetShare(ctx, &collaboration.ShareReference{ Spec: &collaboration.ShareReference_Id{ Id: &collaboration.ShareId{ @@ -328,21 +362,16 @@ var _ = Describe("Nextcloud", func() { XXX_sizecache: 0, }, })) - Expect(called[0]).To(Equal(`POST /apps/sciencemesh/~tester/api/share/GetShare {"Spec":{"Id":{"opaque_id":"some-share-id"}}}`)) + checkCalled(called, `POST /apps/sciencemesh/~tester/api/share/GetShare {"Spec":{"Id":{"opaque_id":"some-share-id"}}}`) }) }) // Unshare(ctx context.Context, ref *collaboration.ShareReference) error Describe("Unshare", func() { It("calls the Unshare endpoint", func() { - called := make([]string, 0) - - h := nextcloud.GetNextcloudServerMock(&called) - mock, teardown := nextcloud.TestingHTTPClient(h) + am, called, teardown := setUpNextcloudServer() defer teardown() - am, _ := nextcloud.NewShareManager(&nextcloud.ShareManagerConfig{ - EndPoint: "http://mock.com/apps/sciencemesh/", - }, mock) + err := am.Unshare(ctx, &collaboration.ShareReference{ Spec: &collaboration.ShareReference_Id{ Id: &collaboration.ShareId{ @@ -351,21 +380,16 @@ var _ = Describe("Nextcloud", func() { }, }) Expect(err).ToNot(HaveOccurred()) - Expect(called[0]).To(Equal(`POST /apps/sciencemesh/~tester/api/share/Unshare {"Spec":{"Id":{"opaque_id":"some-share-id"}}}`)) + checkCalled(called, `POST /apps/sciencemesh/~tester/api/share/Unshare {"Spec":{"Id":{"opaque_id":"some-share-id"}}}`) }) }) // UpdateShare(ctx context.Context, ref *collaboration.ShareReference, p *collaboration.SharePermissions) (*collaboration.Share, error) Describe("UpdateShare", func() { It("calls the UpdateShare endpoint", func() { - called := make([]string, 0) - - h := nextcloud.GetNextcloudServerMock(&called) - mock, teardown := nextcloud.TestingHTTPClient(h) + am, called, teardown := setUpNextcloudServer() defer teardown() - am, _ := nextcloud.NewShareManager(&nextcloud.ShareManagerConfig{ - EndPoint: "http://mock.com/apps/sciencemesh/", - }, mock) + share, err := am.UpdateShare(ctx, &collaboration.ShareReference{ Spec: &collaboration.ShareReference_Id{ Id: &collaboration.ShareId{ @@ -457,21 +481,16 @@ var _ = Describe("Nextcloud", func() { XXX_sizecache: 0, }, })) - Expect(called[0]).To(Equal(`POST /apps/sciencemesh/~tester/api/share/UpdateShare {"ref":{"Spec":{"Id":{"opaque_id":"some-share-id"}}},"p":{"permissions":{"add_grant":true,"create_container":true,"delete":true,"get_path":true,"get_quota":true,"initiate_file_download":true,"initiate_file_upload":true,"list_grants":true,"list_container":true,"list_file_versions":true,"list_recycle":true,"move":true,"remove_grant":true,"purge_recycle":true,"restore_file_version":true,"restore_recycle_item":true,"stat":true,"update_grant":true,"deny_grant":true}}}`)) + checkCalled(called, `POST /apps/sciencemesh/~tester/api/share/UpdateShare {"ref":{"Spec":{"Id":{"opaque_id":"some-share-id"}}},"p":{"permissions":{"add_grant":true,"create_container":true,"delete":true,"get_path":true,"get_quota":true,"initiate_file_download":true,"initiate_file_upload":true,"list_grants":true,"list_container":true,"list_file_versions":true,"list_recycle":true,"move":true,"remove_grant":true,"purge_recycle":true,"restore_file_version":true,"restore_recycle_item":true,"stat":true,"update_grant":true,"deny_grant":true}}}`) }) }) // ListShares(ctx context.Context, filters []*collaboration.Filter) ([]*collaboration.Share, error) Describe("ListShares", func() { It("calls the ListShares endpoint", func() { - called := make([]string, 0) - - h := nextcloud.GetNextcloudServerMock(&called) - mock, teardown := nextcloud.TestingHTTPClient(h) + am, called, teardown := setUpNextcloudServer() defer teardown() - am, _ := nextcloud.NewShareManager(&nextcloud.ShareManagerConfig{ - EndPoint: "http://mock.com/apps/sciencemesh/", - }, mock) + shares, err := am.ListShares(ctx, []*collaboration.Filter{ { Type: collaboration.Filter_TYPE_CREATOR, @@ -546,21 +565,16 @@ var _ = Describe("Nextcloud", func() { XXX_sizecache: 0, }, })) - Expect(called[0]).To(Equal(`POST /apps/sciencemesh/~tester/api/share/ListShares [{"type":4,"Term":{"Creator":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1}}}]`)) + checkCalled(called, `POST /apps/sciencemesh/~tester/api/share/ListShares [{"type":4,"Term":{"Creator":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1}}}]`) }) }) // ListReceivedShares(ctx context.Context, filters []*collaboration.Filter) ([]*collaboration.ReceivedShare, error) Describe("ListReceivedShares", func() { It("calls the ListReceivedShares endpoint", func() { - called := make([]string, 0) - - h := nextcloud.GetNextcloudServerMock(&called) - mock, teardown := nextcloud.TestingHTTPClient(h) + am, called, teardown := setUpNextcloudServer() defer teardown() - am, _ := nextcloud.NewShareManager(&nextcloud.ShareManagerConfig{ - EndPoint: "http://mock.com/apps/sciencemesh/", - }, mock) + receivedShares, err := am.ListReceivedShares(ctx, []*collaboration.Filter{ { Type: collaboration.Filter_TYPE_CREATOR, @@ -638,21 +652,16 @@ var _ = Describe("Nextcloud", func() { }, State: collaboration.ShareState_SHARE_STATE_ACCEPTED, })) - Expect(called[0]).To(Equal(`POST /apps/sciencemesh/~tester/api/share/ListReceivedShares [{"type":4,"Term":{"Creator":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1}}}]`)) + checkCalled(called, `POST /apps/sciencemesh/~tester/api/share/ListReceivedShares [{"type":4,"Term":{"Creator":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1}}}]`) }) }) // GetReceivedShare(ctx context.Context, ref *collaboration.ShareReference) (*collaboration.ReceivedShare, error) Describe("GetReceivedShare", func() { It("calls the GetReceivedShare endpoint", func() { - called := make([]string, 0) - - h := nextcloud.GetNextcloudServerMock(&called) - mock, teardown := nextcloud.TestingHTTPClient(h) + am, called, teardown := setUpNextcloudServer() defer teardown() - am, _ := nextcloud.NewShareManager(&nextcloud.ShareManagerConfig{ - EndPoint: "http://mock.com/apps/sciencemesh/", - }, mock) + receivedShare, err := am.GetReceivedShare(ctx, &collaboration.ShareReference{ Spec: &collaboration.ShareReference_Id{ Id: &collaboration.ShareId{ @@ -724,21 +733,16 @@ var _ = Describe("Nextcloud", func() { }, State: collaboration.ShareState_SHARE_STATE_ACCEPTED, })) - Expect(called[0]).To(Equal(`POST /apps/sciencemesh/~tester/api/share/GetReceivedShare {"Spec":{"Id":{"opaque_id":"some-share-id"}}}`)) + checkCalled(called, `POST /apps/sciencemesh/~tester/api/share/GetReceivedShare {"Spec":{"Id":{"opaque_id":"some-share-id"}}}`) }) }) // UpdateReceivedShare(ctx context.Context, receivedShare *collaboration.ReceivedShare, fieldMask *field_mask.FieldMask) (*collaboration.ReceivedShare, error) Describe("UpdateReceivedShare", func() { It("calls the UpdateReceivedShare endpoint", func() { - called := make([]string, 0) - - h := nextcloud.GetNextcloudServerMock(&called) - mock, teardown := nextcloud.TestingHTTPClient(h) + am, called, teardown := setUpNextcloudServer() defer teardown() - am, _ := nextcloud.NewShareManager(&nextcloud.ShareManagerConfig{ - EndPoint: "http://mock.com/apps/sciencemesh/", - }, mock) + receivedShare, err := am.UpdateReceivedShare(ctx, &collaboration.ReceivedShare{ Share: &collaboration.Share{ @@ -870,7 +874,7 @@ var _ = Describe("Nextcloud", func() { }, State: collaboration.ShareState_SHARE_STATE_ACCEPTED, })) - Expect(called[0]).To(Equal(`POST /apps/sciencemesh/~tester/api/share/UpdateReceivedShare {"received_share":{"share":{"id":{},"resource_id":{},"permissions":{"permissions":{"add_grant":true,"create_container":true,"delete":true,"get_path":true,"get_quota":true,"initiate_file_download":true,"initiate_file_upload":true,"list_grants":true,"list_container":true,"list_file_versions":true,"list_recycle":true,"move":true,"remove_grant":true,"purge_recycle":true,"restore_file_version":true,"restore_recycle_item":true,"stat":true,"update_grant":true,"deny_grant":true}},"grantee":{"Id":{"UserId":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1}}},"owner":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1},"creator":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1},"ctime":{"seconds":1234567890},"mtime":{"seconds":1234567890}},"state":2},"field_mask":{"paths":["state"]}}`)) + checkCalled(called, `POST /apps/sciencemesh/~tester/api/share/UpdateReceivedShare {"received_share":{"share":{"id":{},"resource_id":{},"permissions":{"permissions":{"add_grant":true,"create_container":true,"delete":true,"get_path":true,"get_quota":true,"initiate_file_download":true,"initiate_file_upload":true,"list_grants":true,"list_container":true,"list_file_versions":true,"list_recycle":true,"move":true,"remove_grant":true,"purge_recycle":true,"restore_file_version":true,"restore_recycle_item":true,"stat":true,"update_grant":true,"deny_grant":true}},"grantee":{"Id":{"UserId":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1}}},"owner":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1},"creator":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1},"ctime":{"seconds":1234567890},"mtime":{"seconds":1234567890}},"state":2},"field_mask":{"paths":["state"]}}`) }) }) diff --git a/pkg/storage/fs/nextcloud/nextcloud.go b/pkg/storage/fs/nextcloud/nextcloud.go index e53a793a25..43ac7f1fac 100644 --- a/pkg/storage/fs/nextcloud/nextcloud.go +++ b/pkg/storage/fs/nextcloud/nextcloud.go @@ -79,9 +79,16 @@ func New(m map[string]interface{}) (storage.FS, error) { func NewStorageDriver(c *StorageDriverConfig) (*StorageDriver, error) { var client *http.Client if c.MockHTTP { + // called := make([]string, 0) + // nextcloudServerMock := GetNextcloudServerMock(&called) + // client, _ = TestingHTTPClient(nextcloudServerMock) + + // This is only used by the integration tests: + // (unit tests will call SetHTTPClient later): called := make([]string, 0) - nextcloudServerMock := GetNextcloudServerMock(&called) - client, _ = TestingHTTPClient(nextcloudServerMock) + h := GetNextcloudServerMock(&called) + client, _ = TestingHTTPClient(h) + // FIXME: defer teardown() } else { client = &http.Client{} } @@ -192,7 +199,7 @@ func (nc *StorageDriver) do(ctx context.Context, a Action) (int, []byte, error) return 0, nil, err } url := nc.endPoint + "~" + user.Username + "/api/storage/" + a.verb - log.Info().Msgf("nc.do %s", url) + log.Info().Msgf("nc.do req %s %s", url, a.argS) req, err := http.NewRequest(http.MethodPost, url, strings.NewReader(a.argS)) if err != nil { return 0, nil, err @@ -206,11 +213,12 @@ func (nc *StorageDriver) do(ctx context.Context, a Action) (int, []byte, error) defer resp.Body.Close() body, err := io.ReadAll(resp.Body) + if err != nil { return 0, nil, err } + log.Info().Msgf("nc.do res %s %s", url, string(body)) - // fmt.Printf("nc.do response %d %s\n", resp.StatusCode, body) return resp.StatusCode, body, nil } @@ -318,11 +326,14 @@ func (nc *StorageDriver) ListFolder(ctx context.Context, ref *provider.Reference } bodyStr, err := json.Marshal(bodyObj) log := appctx.GetLogger(ctx) - log.Info().Msgf("LisfFolder %s", bodyStr) + log.Info().Msgf("ListFolder %s", bodyStr) if err != nil { return nil, err } + fmt.Println("calling!") + fmt.Println(string(bodyStr)) status, body, err := nc.do(ctx, Action{"ListFolder", string(bodyStr)}) + fmt.Println(string(body)) if err != nil { return nil, err } @@ -387,7 +398,6 @@ func (nc *StorageDriver) ListRevisions(ctx context.Context, ref *provider.Refere log.Info().Msgf("ListRevisions %s", bodyStr) _, respBody, err := nc.do(ctx, Action{"ListRevisions", string(bodyStr)}) - // fmt.Printf("ListRevisions respBody %s", respBody) if err != nil { return nil, err @@ -464,7 +474,6 @@ func (nc *StorageDriver) ListRecycle(ctx context.Context, key string, path strin // RestoreRecycleItem as defined in the storage.FS interface func (nc *StorageDriver) RestoreRecycleItem(ctx context.Context, key string, path string, restoreRef *provider.Reference) error { - // fmt.Printf("RestoreRecycleItem! %s %s\n\n", key, path) type paramsObj struct { Key string `json:"key"` Path string `json:"path"` @@ -777,7 +786,6 @@ func (nc *StorageDriver) CreateStorageSpace(ctx context.Context, req *provider.C return nil, err } var respObj provider.CreateStorageSpaceResponse - fmt.Println(string(respBody)) err = json.Unmarshal(respBody, &respObj) if err != nil { return nil, err diff --git a/pkg/storage/fs/nextcloud/nextcloud_server_mock.go b/pkg/storage/fs/nextcloud/nextcloud_server_mock.go index fc8fd8f2e2..9fca788a9b 100644 --- a/pkg/storage/fs/nextcloud/nextcloud_server_mock.go +++ b/pkg/storage/fs/nextcloud/nextcloud_server_mock.go @@ -143,18 +143,19 @@ var responses = map[string]Response{ `POST /apps/sciencemesh/~tester/api/storage/Delete {"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"/some/path"}`: {200, ``, serverStateEmpty}, `POST /apps/sciencemesh/~tester/api/storage/Move {"oldRef":{"resource_id":{"storage_id":"storage-id-1","opaque_id":"opaque-id-1"},"path":"/some/old/path"},"newRef":{"resource_id":{"storage_id":"storage-id-2","opaque_id":"opaque-id-2"},"path":"/some/new/path"}}`: {200, ``, serverStateEmpty}, `POST /apps/sciencemesh/~tester/api/storage/GetMD {"ref":{"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"/some/path"},"mdKeys":["val1","val2","val3"]}`: {200, `{"opaque":{},"type":1,"id":{"opaque_id":"fileid-/some/path"},"checksum":{},"etag":"deadbeef","mime_type":"text/plain","mtime":{"seconds":1234567890},"path":"/some/path","permission_set":{},"size":12345,"canonical_metadata":{},"arbitrary_metadata":{"metadata":{"da":"ta","some":"arbi","trary":"meta"}}}`, serverStateEmpty}, - `POST /apps/sciencemesh/~tester/api/storage/ListFolder {"ref":{"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"/some/path"},"mdKeys":["val1","val2","val3"]}`: {200, `[{"opaque":{},"type":1,"id":{"opaque_id":"fileid-/some/path"},"checksum":{},"etag":"deadbeef","mime_type":"text/plain","mtime":{"seconds":1234567890},"path":"/some/path","permission_set":{},"size":12345,"canonical_metadata":{},"arbitrary_metadata":{"metadata":{"da":"ta","some":"arbi","trary":"meta"}}}]`, serverStateEmpty}, - `POST /apps/sciencemesh/~tester/api/storage/InitiateUpload {"ref":{"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"/some/path"},"uploadLength":12345,"metadata":{"key1":"val1","key2":"val2","key3":"val3"}}`: {200, `{ "not":"sure", "what": "should be", "returned": "here" }`, serverStateEmpty}, - `PUT /apps/sciencemesh/~tester/api/storage/Upload/some/file/path.txt shiny!`: {200, ``, serverStateEmpty}, - `GET /apps/sciencemesh/~tester/api/storage/Download/some/file/path.txt `: {200, `the contents of the file`, serverStateEmpty}, - `POST /apps/sciencemesh/~tester/api/storage/ListRevisions {"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"/some/path"}`: {200, `[{"opaque":{"map":{"some":{"value":"ZGF0YQ=="}}},"key":"version-12","size":12345,"mtime":1234567890,"etag":"deadb00f"},{"opaque":{"map":{"different":{"value":"c3R1ZmY="}}},"key":"asdf","size":12345,"mtime":1234567890,"etag":"deadbeef"}]`, serverStateEmpty}, - `GET /apps/sciencemesh/~tester/api/storage/DownloadRevision/some%2Frevision/some/file/path.txt `: {200, `the contents of that revision`, serverStateEmpty}, - `POST /apps/sciencemesh/~tester/api/storage/RestoreRevision {"ref":{"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"some/file/path.txt"},"key":"asdf"}`: {200, ``, serverStateEmpty}, - `POST /apps/sciencemesh/~tester/api/storage/ListRecycle {"key":"asdf","path":"/some/file.txt"}`: {200, `[{"opaque":{},"key":"some-deleted-version","ref":{"resource_id":{},"path":"/some/file.txt"},"size":12345,"deletion_time":{"seconds":1234567890}}]`, serverStateEmpty}, - `POST /apps/sciencemesh/~tester/api/storage/RestoreRecycleItem {"key":"asdf","path":"original/location/when/deleted.txt","restoreRef":{"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"some/file/path.txt"}}`: {200, ``, serverStateEmpty}, - `POST /apps/sciencemesh/~tester/api/storage/PurgeRecycleItem {"key":"asdf","path":"original/location/when/deleted.txt"}`: {200, ``, serverStateEmpty}, - `POST /apps/sciencemesh/~tester/api/storage/EmptyRecycle `: {200, ``, serverStateEmpty}, - `POST /apps/sciencemesh/~tester/api/storage/GetPathByID {"storage_id":"storage-id","opaque_id":"opaque-id"}`: {200, `the/path/for/that/id.txt`, serverStateEmpty}, + `POST /apps/sciencemesh/~tester/api/storage/ListFolder {"ref":{"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"/some"},"mdKeys":["val1","val2","val3"]}`: {200, `[{"opaque":{},"type":1,"id":{"opaque_id":"fileid-/some/path"},"checksum":{},"etag":"deadbeef","mime_type":"text/plain","mtime":{"seconds":1234567890},"path":"/some/path","permission_set":{},"size":12345,"canonical_metadata":{},"arbitrary_metadata":{"metadata":{"da":"ta","some":"arbi","trary":"meta"}}}]`, serverStateEmpty}, + // `POST /apps/sciencemesh/~tester/api/storage/ListFolder {"ref":{"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"/some"},"mdKeys":["val1","val2","val3"]}`: {200, `[{"opaque":{},"type":1,"id":{"opaque_id":"fileid-/path"},"checksum":{},"etag":"deadbeef","mime_type":"text/plain","mtime":{"seconds":1234567890},"path":"/path","permission_set":{},"size":12345,"canonical_metadata":{},"arbitrary_metadata":{"metadata":{"da":"ta","some":"arbi","trary":"meta"}}}]`, serverStateEmpty}, + `POST /apps/sciencemesh/~tester/api/storage/InitiateUpload {"ref":{"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"/some/path"},"uploadLength":12345,"metadata":{"key1":"val1","key2":"val2","key3":"val3"}}`: {200, `{ "not":"sure", "what": "should be", "returned": "here" }`, serverStateEmpty}, + `PUT /apps/sciencemesh/~tester/api/storage/Upload/some/file/path.txt shiny!`: {200, ``, serverStateEmpty}, + `GET /apps/sciencemesh/~tester/api/storage/Download/some/file/path.txt `: {200, `the contents of the file`, serverStateEmpty}, + `POST /apps/sciencemesh/~tester/api/storage/ListRevisions {"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"/some/path"}`: {200, `[{"opaque":{"map":{"some":{"value":"ZGF0YQ=="}}},"key":"version-12","size":12345,"mtime":1234567890,"etag":"deadb00f"},{"opaque":{"map":{"different":{"value":"c3R1ZmY="}}},"key":"asdf","size":12345,"mtime":1234567890,"etag":"deadbeef"}]`, serverStateEmpty}, + `GET /apps/sciencemesh/~tester/api/storage/DownloadRevision/some%2Frevision/some/file/path.txt `: {200, `the contents of that revision`, serverStateEmpty}, + `POST /apps/sciencemesh/~tester/api/storage/RestoreRevision {"ref":{"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"some/file/path.txt"},"key":"asdf"}`: {200, ``, serverStateEmpty}, + `POST /apps/sciencemesh/~tester/api/storage/ListRecycle {"key":"asdf","path":"/some/file.txt"}`: {200, `[{"opaque":{},"key":"some-deleted-version","ref":{"resource_id":{},"path":"/some/file.txt"},"size":12345,"deletion_time":{"seconds":1234567890}}]`, serverStateEmpty}, + `POST /apps/sciencemesh/~tester/api/storage/RestoreRecycleItem {"key":"asdf","path":"original/location/when/deleted.txt","restoreRef":{"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"some/file/path.txt"}}`: {200, ``, serverStateEmpty}, + `POST /apps/sciencemesh/~tester/api/storage/PurgeRecycleItem {"key":"asdf","path":"original/location/when/deleted.txt"}`: {200, ``, serverStateEmpty}, + `POST /apps/sciencemesh/~tester/api/storage/EmptyRecycle `: {200, ``, serverStateEmpty}, + `POST /apps/sciencemesh/~tester/api/storage/GetPathByID {"storage_id":"storage-id","opaque_id":"opaque-id"}`: {200, `the/path/for/that/id.txt`, serverStateEmpty}, `POST /apps/sciencemesh/~tester/api/storage/AddGrant {"ref":{"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"some/file/path.txt"},"g":{"grantee":{"Id":{"UserId":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1}}},"permissions":{"add_grant":true,"create_container":true,"delete":true,"get_path":true,"get_quota":true,"initiate_file_download":true,"initiate_file_upload":true,"list_grants":true,"list_container":true,"list_file_versions":true,"list_recycle":true,"move":true,"remove_grant":true,"purge_recycle":true,"restore_file_version":true,"restore_recycle_item":true,"stat":true,"update_grant":true,"deny_grant":true}}}`: {200, ``, serverStateEmpty}, `POST /apps/sciencemesh/~tester/api/storage/DenyGrant {"ref":{"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"some/file/path.txt"},"g":{"Id":{"UserId":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1}}}}`: {200, ``, serverStateEmpty}, `POST /apps/sciencemesh/~tester/api/storage/RemoveGrant {"ref":{"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"some/file/path.txt"},"g":{"grantee":{"Id":{"UserId":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1}}},"permissions":{"add_grant":true,"create_container":true,"delete":true,"get_path":true,"get_quota":true,"initiate_file_download":true,"initiate_file_upload":true,"list_grants":true,"list_container":true,"list_file_versions":true,"list_recycle":true,"move":true,"remove_grant":true,"purge_recycle":true,"restore_file_version":true,"restore_recycle_item":true,"stat":true,"update_grant":true,"deny_grant":true}}}`: {200, ``, serverStateEmpty}, @@ -178,13 +179,13 @@ func GetNextcloudServerMock(called *[]string) http.Handler { panic("Error reading response into buffer") } var key = fmt.Sprintf("%s %s %s", r.Method, r.URL, buf.String()) - fmt.Printf("Nextcloud Server Mock key components %s %d %s %d %s %d\n", r.Method, len(r.Method), r.URL.String(), len(r.URL.String()), buf.String(), len(buf.String())) - fmt.Printf("Nextcloud Server Mock key %s\n", key) + // fmt.Printf("Nextcloud Server Mock key components %s %d %s %d %s %d\n", r.Method, len(r.Method), r.URL.String(), len(r.URL.String()), buf.String(), len(buf.String())) + // fmt.Printf("Nextcloud Server Mock key %s\n", key) *called = append(*called, key) response := responses[key] if (response == Response{}) { key = fmt.Sprintf("%s %s %s %s", r.Method, r.URL, buf.String(), serverState) - fmt.Printf("Nextcloud Server Mock key with State %s\n", key) + // fmt.Printf("Nextcloud Server Mock key with State %s\n", key) // *called = append(*called, key) response = responses[key] } diff --git a/pkg/storage/fs/nextcloud/nextcloud_test.go b/pkg/storage/fs/nextcloud/nextcloud_test.go index 8f660bf669..6925a12c46 100644 --- a/pkg/storage/fs/nextcloud/nextcloud_test.go +++ b/pkg/storage/fs/nextcloud/nextcloud_test.go @@ -20,6 +20,9 @@ package nextcloud_test import ( "context" + "fmt" + + // "fmt" "io" "net/url" "os" @@ -40,6 +43,39 @@ import ( . "github.com/onsi/gomega" ) +func setUpNextcloudServer() (*nextcloud.StorageDriver, *[]string, func()) { + var conf *nextcloud.StorageDriverConfig + + ncHost := os.Getenv("NEXTCLOUD") + fmt.Printf(`NEXTCLOUD env var: "%s"`, ncHost) + if len(ncHost) == 0 { + conf = &nextcloud.StorageDriverConfig{ + EndPoint: "http://mock.com/apps/sciencemesh/", + MockHTTP: true, + } + nc, _ := nextcloud.NewStorageDriver(conf) + called := make([]string, 0) + h := nextcloud.GetNextcloudServerMock(&called) + mock, teardown := nextcloud.TestingHTTPClient(h) + nc.SetHTTPClient(mock) + return nc, &called, teardown + } + conf = &nextcloud.StorageDriverConfig{ + EndPoint: ncHost + "/apps/sciencemesh/", + MockHTTP: false, + } + nc, _ := nextcloud.NewStorageDriver(conf) + return nc, nil, func() {} +} + +func checkCalled(called *[]string, expected string) { + if called == nil { + return + } + Expect(len(*called)).To(Equal(1)) + Expect((*called)[0]).To(Equal(expected)) +} + var _ = Describe("Nextcloud", func() { var ( ctx context.Context @@ -96,55 +132,31 @@ var _ = Describe("Nextcloud", func() { // GetHome(ctx context.Context) (string, error) Describe("GetHome", func() { It("calls the GetHome endpoint", func() { - nc, _ := nextcloud.NewStorageDriver(&nextcloud.StorageDriverConfig{ - EndPoint: "http://mock.com/apps/sciencemesh/", - MockHTTP: true, - }) - called := make([]string, 0) - - h := nextcloud.GetNextcloudServerMock(&called) - mock, teardown := nextcloud.TestingHTTPClient(h) + nc, called, teardown := setUpNextcloudServer() defer teardown() - nc.SetHTTPClient(mock) home, err := nc.GetHome(ctx) Expect(home).To(Equal("yes we are")) Expect(err).ToNot(HaveOccurred()) - Expect(len(called)).To(Equal(1)) - Expect(called[0]).To(Equal(`POST /apps/sciencemesh/~tester/api/storage/GetHome `)) + checkCalled(called, `POST /apps/sciencemesh/~tester/api/storage/GetHome `) }) }) // CreateHome(ctx context.Context) error Describe("CreateHome", func() { It("calls the CreateHome endpoint", func() { - nc, _ := nextcloud.NewStorageDriver(&nextcloud.StorageDriverConfig{ - EndPoint: "http://mock.com/apps/sciencemesh/", - MockHTTP: true, - }) - called := make([]string, 0) - h := nextcloud.GetNextcloudServerMock(&called) - mock, teardown := nextcloud.TestingHTTPClient(h) + nc, called, teardown := setUpNextcloudServer() defer teardown() - nc.SetHTTPClient(mock) err := nc.CreateHome(ctx) Expect(err).ToNot(HaveOccurred()) - Expect(len(called)).To(Equal(1)) - Expect(called[0]).To(Equal(`POST /apps/sciencemesh/~tester/api/storage/CreateHome `)) + checkCalled(called, `POST /apps/sciencemesh/~tester/api/storage/CreateHome `) }) }) // CreateDir(ctx context.Context, ref *provider.Reference) error Describe("CreateDir", func() { It("calls the CreateDir endpoint", func() { - nc, _ := nextcloud.NewStorageDriver(&nextcloud.StorageDriverConfig{ - EndPoint: "http://mock.com/apps/sciencemesh/", - MockHTTP: true, - }) - called := make([]string, 0) - h := nextcloud.GetNextcloudServerMock(&called) - mock, teardown := nextcloud.TestingHTTPClient(h) + nc, called, teardown := setUpNextcloudServer() defer teardown() - nc.SetHTTPClient(mock) // https://github.com/cs3org/go-cs3apis/blob/970eec3/cs3/storage/provider/v1beta1/resources.pb.go#L550-L561 ref := &provider.Reference{ ResourceId: &provider.ResourceId{ @@ -155,23 +167,15 @@ var _ = Describe("Nextcloud", func() { } err := nc.CreateDir(ctx, ref) Expect(err).ToNot(HaveOccurred()) - Expect(len(called)).To(Equal(1)) - Expect(called[0]).To(Equal(`POST /apps/sciencemesh/~tester/api/storage/CreateDir {"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"/some/path"}`)) + checkCalled(called, `POST /apps/sciencemesh/~tester/api/storage/CreateDir {"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"/some/path"}`) }) }) // Delete(ctx context.Context, ref *provider.Reference) error Describe("Delete", func() { It("calls the Delete endpoint", func() { - nc, _ := nextcloud.NewStorageDriver(&nextcloud.StorageDriverConfig{ - EndPoint: "http://mock.com/apps/sciencemesh/", - MockHTTP: true, - }) - called := make([]string, 0) - h := nextcloud.GetNextcloudServerMock(&called) - mock, teardown := nextcloud.TestingHTTPClient(h) + nc, called, teardown := setUpNextcloudServer() defer teardown() - nc.SetHTTPClient(mock) // https://github.com/cs3org/go-cs3apis/blob/970eec3/cs3/storage/provider/v1beta1/resources.pb.go#L550-L561 ref := &provider.Reference{ ResourceId: &provider.ResourceId{ @@ -182,23 +186,15 @@ var _ = Describe("Nextcloud", func() { } err := nc.Delete(ctx, ref) Expect(err).ToNot(HaveOccurred()) - Expect(len(called)).To(Equal(1)) - Expect(called[0]).To(Equal(`POST /apps/sciencemesh/~tester/api/storage/Delete {"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"/some/path"}`)) + checkCalled(called, `POST /apps/sciencemesh/~tester/api/storage/Delete {"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"/some/path"}`) }) }) // Move(ctx context.Context, oldRef, newRef *provider.Reference) error Describe("Move", func() { It("calls the Move endpoint", func() { - nc, _ := nextcloud.NewStorageDriver(&nextcloud.StorageDriverConfig{ - EndPoint: "http://mock.com/apps/sciencemesh/", - MockHTTP: true, - }) - called := make([]string, 0) - h := nextcloud.GetNextcloudServerMock(&called) - mock, teardown := nextcloud.TestingHTTPClient(h) + nc, called, teardown := setUpNextcloudServer() defer teardown() - nc.SetHTTPClient(mock) // https://github.com/cs3org/go-cs3apis/blob/970eec3/cs3/storage/provider/v1beta1/resources.pb.go#L550-L561 ref1 := &provider.Reference{ ResourceId: &provider.ResourceId{ @@ -216,23 +212,15 @@ var _ = Describe("Nextcloud", func() { } err := nc.Move(ctx, ref1, ref2) Expect(err).ToNot(HaveOccurred()) - Expect(len(called)).To(Equal(1)) - Expect(called[0]).To(Equal(`POST /apps/sciencemesh/~tester/api/storage/Move {"oldRef":{"resource_id":{"storage_id":"storage-id-1","opaque_id":"opaque-id-1"},"path":"/some/old/path"},"newRef":{"resource_id":{"storage_id":"storage-id-2","opaque_id":"opaque-id-2"},"path":"/some/new/path"}}`)) + checkCalled(called, `POST /apps/sciencemesh/~tester/api/storage/Move {"oldRef":{"resource_id":{"storage_id":"storage-id-1","opaque_id":"opaque-id-1"},"path":"/some/old/path"},"newRef":{"resource_id":{"storage_id":"storage-id-2","opaque_id":"opaque-id-2"},"path":"/some/new/path"}}`) }) }) // GetMD(ctx context.Context, ref *provider.Reference, mdKeys []string) (*provider.ResourceInfo, error) Describe("GetMD", func() { It("calls the GetMD endpoint", func() { - nc, _ := nextcloud.NewStorageDriver(&nextcloud.StorageDriverConfig{ - EndPoint: "http://mock.com/apps/sciencemesh/", - MockHTTP: true, - }) - called := make([]string, 0) - h := nextcloud.GetNextcloudServerMock(&called) - mock, teardown := nextcloud.TestingHTTPClient(h) + nc, called, teardown := setUpNextcloudServer() defer teardown() - nc.SetHTTPClient(mock) // https://github.com/cs3org/go-cs3apis/blob/970eec3/cs3/storage/provider/v1beta1/resources.pb.go#L550-L561 ref := &provider.Reference{ ResourceId: &provider.ResourceId{ @@ -319,30 +307,22 @@ var _ = Describe("Nextcloud", func() { XXX_unrecognized: nil, XXX_sizecache: 0, })) - Expect(len(called)).To(Equal(1)) - Expect(called[0]).To(Equal(`POST /apps/sciencemesh/~tester/api/storage/GetMD {"ref":{"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"/some/path"},"mdKeys":["val1","val2","val3"]}`)) + checkCalled(called, `POST /apps/sciencemesh/~tester/api/storage/GetMD {"ref":{"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"/some/path"},"mdKeys":["val1","val2","val3"]}`) }) }) // ListFolder(ctx context.Context, ref *provider.Reference, mdKeys []string) ([]*provider.ResourceInfo, error) Describe("ListFolder", func() { It("calls the ListFolder endpoint", func() { - nc, _ := nextcloud.NewStorageDriver(&nextcloud.StorageDriverConfig{ - EndPoint: "http://mock.com/apps/sciencemesh/", - MockHTTP: true, - }) - called := make([]string, 0) - h := nextcloud.GetNextcloudServerMock(&called) - mock, teardown := nextcloud.TestingHTTPClient(h) + nc, called, teardown := setUpNextcloudServer() defer teardown() - nc.SetHTTPClient(mock) // https://github.com/cs3org/go-cs3apis/blob/970eec3/cs3/storage/provider/v1beta1/resources.pb.go#L550-L561 ref := &provider.Reference{ ResourceId: &provider.ResourceId{ StorageId: "storage-id", OpaqueId: "opaque-id", }, - Path: "/some/path", + Path: "/some", } mdKeys := []string{"val1", "val2", "val3"} results, err := nc.ListFolder(ctx, ref, mdKeys) @@ -423,26 +403,16 @@ var _ = Describe("Nextcloud", func() { XXX_unrecognized: nil, XXX_sizecache: 0, })) - // Expect(results[0].Etag).To(Equal("in-json-etag")) - // Expect(results[0].MimeType).To(Equal("in-json-mimetype")) - // Expect(err).ToNot(HaveOccurred()) - // Expect(len(called)).To(Equal(1)) - Expect(called[0]).To(Equal(`POST /apps/sciencemesh/~tester/api/storage/ListFolder {"ref":{"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"/some/path"},"mdKeys":["val1","val2","val3"]}`)) + Expect(err).ToNot(HaveOccurred()) + checkCalled(called, `POST /apps/sciencemesh/~tester/api/storage/ListFolder {"ref":{"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"/some"},"mdKeys":["val1","val2","val3"]}`) }) }) // InitiateUpload(ctx context.Context, ref *provider.Reference, uploadLength int64, metadata map[string]string) (map[string]string, error) Describe("InitiateUpload", func() { It("calls the InitiateUpload endpoint", func() { - nc, _ := nextcloud.NewStorageDriver(&nextcloud.StorageDriverConfig{ - EndPoint: "http://mock.com/apps/sciencemesh/", - MockHTTP: true, - }) - called := make([]string, 0) - h := nextcloud.GetNextcloudServerMock(&called) - mock, teardown := nextcloud.TestingHTTPClient(h) + nc, called, teardown := setUpNextcloudServer() defer teardown() - nc.SetHTTPClient(mock) // https://github.com/cs3org/go-cs3apis/blob/970eec3/cs3/storage/provider/v1beta1/resources.pb.go#L550-L561 ref := &provider.Reference{ ResourceId: &provider.ResourceId{ @@ -464,22 +434,15 @@ var _ = Describe("Nextcloud", func() { "what": "should be", "returned": "here", })) - Expect(called[0]).To(Equal(`POST /apps/sciencemesh/~tester/api/storage/InitiateUpload {"ref":{"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"/some/path"},"uploadLength":12345,"metadata":{"key1":"val1","key2":"val2","key3":"val3"}}`)) + checkCalled(called, `POST /apps/sciencemesh/~tester/api/storage/InitiateUpload {"ref":{"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"/some/path"},"uploadLength":12345,"metadata":{"key1":"val1","key2":"val2","key3":"val3"}}`) }) }) // Upload(ctx context.Context, ref *provider.Reference, r io.ReadCloser) error Describe("Upload", func() { It("calls the Upload endpoint", func() { - nc, _ := nextcloud.NewStorageDriver(&nextcloud.StorageDriverConfig{ - EndPoint: "http://mock.com/apps/sciencemesh/", - MockHTTP: true, - }) - called := make([]string, 0) - h := nextcloud.GetNextcloudServerMock(&called) - mock, teardown := nextcloud.TestingHTTPClient(h) + nc, called, teardown := setUpNextcloudServer() defer teardown() - nc.SetHTTPClient(mock) // https://github.com/cs3org/go-cs3apis/blob/970eec3/cs3/storage/provider/v1beta1/resources.pb.go#L550-L561 ref := &provider.Reference{ ResourceId: &provider.ResourceId{ @@ -492,21 +455,14 @@ var _ = Describe("Nextcloud", func() { stringReadCloser := io.NopCloser(stringReader) err := nc.Upload(ctx, ref, stringReadCloser) Expect(err).ToNot(HaveOccurred()) - Expect(called[0]).To(Equal(`PUT /apps/sciencemesh/~tester/api/storage/Upload/some/file/path.txt shiny!`)) + checkCalled(called, `PUT /apps/sciencemesh/~tester/api/storage/Upload/some/file/path.txt shiny!`) }) }) // Download(ctx context.Context, ref *provider.Reference) (io.ReadCloser, error) Describe("Download", func() { It("calls the Download endpoint with GET", func() { - nc, _ := nextcloud.NewStorageDriver(&nextcloud.StorageDriverConfig{ - EndPoint: "http://mock.com/apps/sciencemesh/", - MockHTTP: true, - }) - called := make([]string, 0) - h := nextcloud.GetNextcloudServerMock(&called) - mock, teardown := nextcloud.TestingHTTPClient(h) + nc, called, teardown := setUpNextcloudServer() defer teardown() - nc.SetHTTPClient(mock) // https://github.com/cs3org/go-cs3apis/blob/970eec3/cs3/storage/provider/v1beta1/resources.pb.go#L550-L561 ref := &provider.Reference{ ResourceId: &provider.ResourceId{ @@ -517,7 +473,7 @@ var _ = Describe("Nextcloud", func() { } reader, err := nc.Download(ctx, ref) Expect(err).ToNot(HaveOccurred()) - Expect(called[0]).To(Equal(`GET /apps/sciencemesh/~tester/api/storage/Download/some/file/path.txt `)) + checkCalled(called, `GET /apps/sciencemesh/~tester/api/storage/Download/some/file/path.txt `) defer reader.Close() body, err := io.ReadAll(reader) Expect(err).ToNot(HaveOccurred()) @@ -528,15 +484,8 @@ var _ = Describe("Nextcloud", func() { // ListRevisions(ctx context.Context, ref *provider.Reference) ([]*provider.FileVersion, error) Describe("ListRevisions", func() { It("calls the ListRevisions endpoint", func() { - nc, _ := nextcloud.NewStorageDriver(&nextcloud.StorageDriverConfig{ - EndPoint: "http://mock.com/apps/sciencemesh/", - MockHTTP: true, - }) - called := make([]string, 0) - h := nextcloud.GetNextcloudServerMock(&called) - mock, teardown := nextcloud.TestingHTTPClient(h) + nc, called, teardown := setUpNextcloudServer() defer teardown() - nc.SetHTTPClient(mock) // https://github.com/cs3org/go-cs3apis/blob/970eec3/cs3/storage/provider/v1beta1/resources.pb.go#L550-L561 ref := &provider.Reference{ ResourceId: &provider.ResourceId{ @@ -581,22 +530,15 @@ var _ = Describe("Nextcloud", func() { XXX_unrecognized: nil, XXX_sizecache: 0, })) - Expect(called[0]).To(Equal(`POST /apps/sciencemesh/~tester/api/storage/ListRevisions {"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"/some/path"}`)) + checkCalled(called, `POST /apps/sciencemesh/~tester/api/storage/ListRevisions {"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"/some/path"}`) }) }) // DownloadRevision(ctx context.Context, ref *provider.Reference, key string) (io.ReadCloser, error) Describe("DownloadRevision", func() { It("calls the DownloadRevision endpoint with GET", func() { - nc, _ := nextcloud.NewStorageDriver(&nextcloud.StorageDriverConfig{ - EndPoint: "http://mock.com/apps/sciencemesh/", - MockHTTP: true, - }) - called := make([]string, 0) - h := nextcloud.GetNextcloudServerMock(&called) - mock, teardown := nextcloud.TestingHTTPClient(h) + nc, called, teardown := setUpNextcloudServer() defer teardown() - nc.SetHTTPClient(mock) // https://github.com/cs3org/go-cs3apis/blob/970eec3/cs3/storage/provider/v1beta1/resources.pb.go#L550-L561 ref := &provider.Reference{ ResourceId: &provider.ResourceId{ @@ -608,7 +550,7 @@ var _ = Describe("Nextcloud", func() { key := "some/revision" reader, err := nc.DownloadRevision(ctx, ref, key) Expect(err).ToNot(HaveOccurred()) - Expect(called[0]).To(Equal(`GET /apps/sciencemesh/~tester/api/storage/DownloadRevision/some%2Frevision/some/file/path.txt `)) + checkCalled(called, `GET /apps/sciencemesh/~tester/api/storage/DownloadRevision/some%2Frevision/some/file/path.txt `) defer reader.Close() body, err := io.ReadAll(reader) Expect(err).ToNot(HaveOccurred()) @@ -619,15 +561,8 @@ var _ = Describe("Nextcloud", func() { // RestoreRevision(ctx context.Context, ref *provider.Reference, key string) error Describe("RestoreRevision", func() { It("calls the RestoreRevision endpoint", func() { - nc, _ := nextcloud.NewStorageDriver(&nextcloud.StorageDriverConfig{ - EndPoint: "http://mock.com/apps/sciencemesh/", - MockHTTP: true, - }) - called := make([]string, 0) - h := nextcloud.GetNextcloudServerMock(&called) - mock, teardown := nextcloud.TestingHTTPClient(h) + nc, called, teardown := setUpNextcloudServer() defer teardown() - nc.SetHTTPClient(mock) // https://github.com/cs3org/go-cs3apis/blob/970eec3/cs3/storage/provider/v1beta1/resources.pb.go#L550-L561 ref := &provider.Reference{ ResourceId: &provider.ResourceId{ @@ -639,22 +574,15 @@ var _ = Describe("Nextcloud", func() { key := "asdf" err := nc.RestoreRevision(ctx, ref, key) Expect(err).ToNot(HaveOccurred()) - Expect(called[0]).To(Equal(`POST /apps/sciencemesh/~tester/api/storage/RestoreRevision {"ref":{"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"some/file/path.txt"},"key":"asdf"}`)) + checkCalled(called, `POST /apps/sciencemesh/~tester/api/storage/RestoreRevision {"ref":{"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"some/file/path.txt"},"key":"asdf"}`) }) }) // ListRecycle(ctx context.Context, key, path string) ([]*provider.RecycleItem, error) Describe("ListRecycle", func() { It("calls the ListRecycle endpoint", func() { - nc, _ := nextcloud.NewStorageDriver(&nextcloud.StorageDriverConfig{ - EndPoint: "http://mock.com/apps/sciencemesh/", - MockHTTP: true, - }) - called := make([]string, 0) - h := nextcloud.GetNextcloudServerMock(&called) - mock, teardown := nextcloud.TestingHTTPClient(h) + nc, called, teardown := setUpNextcloudServer() defer teardown() - nc.SetHTTPClient(mock) results, err := nc.ListRecycle(ctx, "asdf", "/some/file.txt") Expect(err).ToNot(HaveOccurred()) @@ -676,22 +604,15 @@ var _ = Describe("Nextcloud", func() { XXX_unrecognized: nil, XXX_sizecache: 0, })) - Expect(called[0]).To(Equal(`POST /apps/sciencemesh/~tester/api/storage/ListRecycle {"key":"asdf","path":"/some/file.txt"}`)) + checkCalled(called, `POST /apps/sciencemesh/~tester/api/storage/ListRecycle {"key":"asdf","path":"/some/file.txt"}`) }) }) // RestoreRecycleItem(ctx context.Context, key, path string, restoreRef *provider.Reference) error Describe("RestoreRecycleItem", func() { It("calls the RestoreRecycleItem endpoint", func() { - nc, _ := nextcloud.NewStorageDriver(&nextcloud.StorageDriverConfig{ - EndPoint: "http://mock.com/apps/sciencemesh/", - MockHTTP: true, - }) - called := make([]string, 0) - h := nextcloud.GetNextcloudServerMock(&called) - mock, teardown := nextcloud.TestingHTTPClient(h) + nc, called, teardown := setUpNextcloudServer() defer teardown() - nc.SetHTTPClient(mock) // https://github.com/cs3org/go-cs3apis/blob/970eec3/cs3/storage/provider/v1beta1/resources.pb.go#L550-L561 restoreRef := &provider.Reference{ ResourceId: &provider.ResourceId{ @@ -704,59 +625,38 @@ var _ = Describe("Nextcloud", func() { key := "asdf" err := nc.RestoreRecycleItem(ctx, key, path, restoreRef) Expect(err).ToNot(HaveOccurred()) - Expect(called[0]).To(Equal(`POST /apps/sciencemesh/~tester/api/storage/RestoreRecycleItem {"key":"asdf","path":"original/location/when/deleted.txt","restoreRef":{"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"some/file/path.txt"}}`)) + checkCalled(called, `POST /apps/sciencemesh/~tester/api/storage/RestoreRecycleItem {"key":"asdf","path":"original/location/when/deleted.txt","restoreRef":{"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"some/file/path.txt"}}`) }) }) // PurgeRecycleItem(ctx context.Context, key, path string) error Describe("PurgeRecycleItem", func() { It("calls the PurgeRecycleItem endpoint", func() { - nc, _ := nextcloud.NewStorageDriver(&nextcloud.StorageDriverConfig{ - EndPoint: "http://mock.com/apps/sciencemesh/", - MockHTTP: true, - }) - called := make([]string, 0) - h := nextcloud.GetNextcloudServerMock(&called) - mock, teardown := nextcloud.TestingHTTPClient(h) + nc, called, teardown := setUpNextcloudServer() defer teardown() - nc.SetHTTPClient(mock) path := "original/location/when/deleted.txt" key := "asdf" err := nc.PurgeRecycleItem(ctx, key, path) Expect(err).ToNot(HaveOccurred()) - Expect(called[0]).To(Equal(`POST /apps/sciencemesh/~tester/api/storage/PurgeRecycleItem {"key":"asdf","path":"original/location/when/deleted.txt"}`)) + checkCalled(called, `POST /apps/sciencemesh/~tester/api/storage/PurgeRecycleItem {"key":"asdf","path":"original/location/when/deleted.txt"}`) }) }) // EmptyRecycle(ctx context.Context) error Describe("EmpytRecycle", func() { It("calls the EmpytRecycle endpoint", func() { - nc, _ := nextcloud.NewStorageDriver(&nextcloud.StorageDriverConfig{ - EndPoint: "http://mock.com/apps/sciencemesh/", - MockHTTP: true, - }) - called := make([]string, 0) - h := nextcloud.GetNextcloudServerMock(&called) - mock, teardown := nextcloud.TestingHTTPClient(h) + nc, called, teardown := setUpNextcloudServer() defer teardown() - nc.SetHTTPClient(mock) err := nc.EmptyRecycle(ctx) Expect(err).ToNot(HaveOccurred()) - Expect(called[0]).To(Equal(`POST /apps/sciencemesh/~tester/api/storage/EmptyRecycle `)) + checkCalled(called, `POST /apps/sciencemesh/~tester/api/storage/EmptyRecycle `) }) }) // GetPathByID(ctx context.Context, id *provider.ResourceId) (string, error) Describe("GetPathByID", func() { It("calls the GetPathByID endpoint", func() { - nc, _ := nextcloud.NewStorageDriver(&nextcloud.StorageDriverConfig{ - EndPoint: "http://mock.com/apps/sciencemesh/", - MockHTTP: true, - }) - called := make([]string, 0) - h := nextcloud.GetNextcloudServerMock(&called) - mock, teardown := nextcloud.TestingHTTPClient(h) + nc, called, teardown := setUpNextcloudServer() defer teardown() - nc.SetHTTPClient(mock) // https://github.com/cs3org/go-cs3apis/blob/970eec3/cs3/storage/provider/v1beta1/resources.pb.go#L602-L618 id := &provider.ResourceId{ StorageId: "storage-id", @@ -764,7 +664,7 @@ var _ = Describe("Nextcloud", func() { } path, err := nc.GetPathByID(ctx, id) Expect(err).ToNot(HaveOccurred()) - Expect(called[0]).To(Equal(`POST /apps/sciencemesh/~tester/api/storage/GetPathByID {"storage_id":"storage-id","opaque_id":"opaque-id"}`)) + checkCalled(called, `POST /apps/sciencemesh/~tester/api/storage/GetPathByID {"storage_id":"storage-id","opaque_id":"opaque-id"}`) Expect(path).To(Equal("the/path/for/that/id.txt")) }) }) @@ -772,15 +672,8 @@ var _ = Describe("Nextcloud", func() { // AddGrant(ctx context.Context, ref *provider.Reference, g *provider.Grant) error Describe("AddGrant", func() { It("calls the AddGrant endpoint", func() { - nc, _ := nextcloud.NewStorageDriver(&nextcloud.StorageDriverConfig{ - EndPoint: "http://mock.com/apps/sciencemesh/", - MockHTTP: true, - }) - called := make([]string, 0) - h := nextcloud.GetNextcloudServerMock(&called) - mock, teardown := nextcloud.TestingHTTPClient(h) + nc, called, teardown := setUpNextcloudServer() defer teardown() - nc.SetHTTPClient(mock) ref := &provider.Reference{ ResourceId: &provider.ResourceId{ StorageId: "storage-id", @@ -825,22 +718,15 @@ var _ = Describe("Nextcloud", func() { } err := nc.AddGrant(ctx, ref, grant) Expect(err).ToNot(HaveOccurred()) - Expect(called[0]).To(Equal(`POST /apps/sciencemesh/~tester/api/storage/AddGrant {"ref":{"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"some/file/path.txt"},"g":{"grantee":{"Id":{"UserId":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1}}},"permissions":{"add_grant":true,"create_container":true,"delete":true,"get_path":true,"get_quota":true,"initiate_file_download":true,"initiate_file_upload":true,"list_grants":true,"list_container":true,"list_file_versions":true,"list_recycle":true,"move":true,"remove_grant":true,"purge_recycle":true,"restore_file_version":true,"restore_recycle_item":true,"stat":true,"update_grant":true,"deny_grant":true}}}`)) + checkCalled(called, `POST /apps/sciencemesh/~tester/api/storage/AddGrant {"ref":{"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"some/file/path.txt"},"g":{"grantee":{"Id":{"UserId":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1}}},"permissions":{"add_grant":true,"create_container":true,"delete":true,"get_path":true,"get_quota":true,"initiate_file_download":true,"initiate_file_upload":true,"list_grants":true,"list_container":true,"list_file_versions":true,"list_recycle":true,"move":true,"remove_grant":true,"purge_recycle":true,"restore_file_version":true,"restore_recycle_item":true,"stat":true,"update_grant":true,"deny_grant":true}}}`) }) }) // DenyGrant(ctx context.Context, ref *provider.Reference, g *provider.Grantee) error Describe("DenyGrant", func() { It("calls the DenyGrant endpoint", func() { - nc, _ := nextcloud.NewStorageDriver(&nextcloud.StorageDriverConfig{ - EndPoint: "http://mock.com/apps/sciencemesh/", - MockHTTP: true, - }) - called := make([]string, 0) - h := nextcloud.GetNextcloudServerMock(&called) - mock, teardown := nextcloud.TestingHTTPClient(h) + nc, called, teardown := setUpNextcloudServer() defer teardown() - nc.SetHTTPClient(mock) ref := &provider.Reference{ ResourceId: &provider.ResourceId{ StorageId: "storage-id", @@ -860,22 +746,15 @@ var _ = Describe("Nextcloud", func() { } err := nc.DenyGrant(ctx, ref, grantee) Expect(err).ToNot(HaveOccurred()) - Expect(called[0]).To(Equal(`POST /apps/sciencemesh/~tester/api/storage/DenyGrant {"ref":{"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"some/file/path.txt"},"g":{"Id":{"UserId":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1}}}}`)) + checkCalled(called, `POST /apps/sciencemesh/~tester/api/storage/DenyGrant {"ref":{"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"some/file/path.txt"},"g":{"Id":{"UserId":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1}}}}`) }) }) // RemoveGrant(ctx context.Context, ref *provider.Reference, g *provider.Grant) error Describe("RemoveGrant", func() { It("calls the RemoveGrant endpoint", func() { - nc, _ := nextcloud.NewStorageDriver(&nextcloud.StorageDriverConfig{ - EndPoint: "http://mock.com/apps/sciencemesh/", - MockHTTP: true, - }) - called := make([]string, 0) - h := nextcloud.GetNextcloudServerMock(&called) - mock, teardown := nextcloud.TestingHTTPClient(h) + nc, called, teardown := setUpNextcloudServer() defer teardown() - nc.SetHTTPClient(mock) ref := &provider.Reference{ ResourceId: &provider.ResourceId{ StorageId: "storage-id", @@ -920,22 +799,15 @@ var _ = Describe("Nextcloud", func() { } err := nc.RemoveGrant(ctx, ref, grant) Expect(err).ToNot(HaveOccurred()) - Expect(called[0]).To(Equal(`POST /apps/sciencemesh/~tester/api/storage/RemoveGrant {"ref":{"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"some/file/path.txt"},"g":{"grantee":{"Id":{"UserId":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1}}},"permissions":{"add_grant":true,"create_container":true,"delete":true,"get_path":true,"get_quota":true,"initiate_file_download":true,"initiate_file_upload":true,"list_grants":true,"list_container":true,"list_file_versions":true,"list_recycle":true,"move":true,"remove_grant":true,"purge_recycle":true,"restore_file_version":true,"restore_recycle_item":true,"stat":true,"update_grant":true,"deny_grant":true}}}`)) + checkCalled(called, `POST /apps/sciencemesh/~tester/api/storage/RemoveGrant {"ref":{"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"some/file/path.txt"},"g":{"grantee":{"Id":{"UserId":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1}}},"permissions":{"add_grant":true,"create_container":true,"delete":true,"get_path":true,"get_quota":true,"initiate_file_download":true,"initiate_file_upload":true,"list_grants":true,"list_container":true,"list_file_versions":true,"list_recycle":true,"move":true,"remove_grant":true,"purge_recycle":true,"restore_file_version":true,"restore_recycle_item":true,"stat":true,"update_grant":true,"deny_grant":true}}}`) }) }) // UpdateGrant(ctx context.Context, ref *provider.Reference, g *provider.Grant) error Describe("UpdateGrant", func() { It("calls the UpdateGrant endpoint", func() { - nc, _ := nextcloud.NewStorageDriver(&nextcloud.StorageDriverConfig{ - EndPoint: "http://mock.com/apps/sciencemesh/", - MockHTTP: true, - }) - called := make([]string, 0) - h := nextcloud.GetNextcloudServerMock(&called) - mock, teardown := nextcloud.TestingHTTPClient(h) + nc, called, teardown := setUpNextcloudServer() defer teardown() - nc.SetHTTPClient(mock) ref := &provider.Reference{ ResourceId: &provider.ResourceId{ StorageId: "storage-id", @@ -980,22 +852,15 @@ var _ = Describe("Nextcloud", func() { } err := nc.UpdateGrant(ctx, ref, grant) Expect(err).ToNot(HaveOccurred()) - Expect(called[0]).To(Equal(`POST /apps/sciencemesh/~tester/api/storage/UpdateGrant {"ref":{"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"some/file/path.txt"},"g":{"grantee":{"Id":{"UserId":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1}}},"permissions":{"add_grant":true,"create_container":true,"delete":true,"get_path":true,"get_quota":true,"initiate_file_download":true,"initiate_file_upload":true,"list_grants":true,"list_container":true,"list_file_versions":true,"list_recycle":true,"move":true,"remove_grant":true,"purge_recycle":true,"restore_file_version":true,"restore_recycle_item":true,"stat":true,"update_grant":true,"deny_grant":true}}}`)) + checkCalled(called, `POST /apps/sciencemesh/~tester/api/storage/UpdateGrant {"ref":{"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"some/file/path.txt"},"g":{"grantee":{"Id":{"UserId":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1}}},"permissions":{"add_grant":true,"create_container":true,"delete":true,"get_path":true,"get_quota":true,"initiate_file_download":true,"initiate_file_upload":true,"list_grants":true,"list_container":true,"list_file_versions":true,"list_recycle":true,"move":true,"remove_grant":true,"purge_recycle":true,"restore_file_version":true,"restore_recycle_item":true,"stat":true,"update_grant":true,"deny_grant":true}}}`) }) }) // ListGrants(ctx context.Context, ref *provider.Reference) ([]*provider.Grant, error) Describe("ListGrants", func() { It("calls the ListGrants endpoint", func() { - nc, _ := nextcloud.NewStorageDriver(&nextcloud.StorageDriverConfig{ - EndPoint: "http://mock.com/apps/sciencemesh/", - MockHTTP: true, - }) - called := make([]string, 0) - h := nextcloud.GetNextcloudServerMock(&called) - mock, teardown := nextcloud.TestingHTTPClient(h) + nc, called, teardown := setUpNextcloudServer() defer teardown() - nc.SetHTTPClient(mock) ref := &provider.Reference{ ResourceId: &provider.ResourceId{ StorageId: "storage-id", @@ -1007,81 +872,53 @@ var _ = Describe("Nextcloud", func() { Expect(err).ToNot(HaveOccurred()) Expect(len(grants)).To(Equal(1)) - Expect(called[0]).To(Equal(`POST /apps/sciencemesh/~tester/api/storage/ListGrants {"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"some/file/path.txt"}`)) + checkCalled(called, `POST /apps/sciencemesh/~tester/api/storage/ListGrants {"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"some/file/path.txt"}`) }) }) // GetQuota(ctx context.Context) (uint64, uint64, error) Describe("GetQuota", func() { It("calls the GetQuota endpoint", func() { - nc, _ := nextcloud.NewStorageDriver(&nextcloud.StorageDriverConfig{ - EndPoint: "http://mock.com/apps/sciencemesh/", - MockHTTP: true, - }) - called := make([]string, 0) - h := nextcloud.GetNextcloudServerMock(&called) - mock, teardown := nextcloud.TestingHTTPClient(h) + nc, called, teardown := setUpNextcloudServer() defer teardown() - nc.SetHTTPClient(mock) maxBytes, maxFiles, err := nc.GetQuota(ctx) Expect(err).ToNot(HaveOccurred()) Expect(maxBytes).To(Equal(uint64(456))) Expect(maxFiles).To(Equal(uint64(123))) - Expect(called[0]).To(Equal(`POST /apps/sciencemesh/~tester/api/storage/GetQuota `)) + checkCalled(called, `POST /apps/sciencemesh/~tester/api/storage/GetQuota `) }) }) // CreateReference(ctx context.Context, path string, targetURI *url.URL) error Describe("CreateReference", func() { It("calls the CreateReference endpoint", func() { - nc, _ := nextcloud.NewStorageDriver(&nextcloud.StorageDriverConfig{ - EndPoint: "http://mock.com/apps/sciencemesh/", - MockHTTP: true, - }) - called := make([]string, 0) - h := nextcloud.GetNextcloudServerMock(&called) - mock, teardown := nextcloud.TestingHTTPClient(h) + nc, called, teardown := setUpNextcloudServer() defer teardown() - nc.SetHTTPClient(mock) path := "some/file/path.txt" targetURI, err := url.Parse("http://bing.com/search?q=dotnet") Expect(err).ToNot(HaveOccurred()) err = nc.CreateReference(ctx, path, targetURI) Expect(err).ToNot(HaveOccurred()) - Expect(called[0]).To(Equal(`POST /apps/sciencemesh/~tester/api/storage/CreateReference {"path":"some/file/path.txt","url":"http://bing.com/search?q=dotnet"}`)) + checkCalled(called, `POST /apps/sciencemesh/~tester/api/storage/CreateReference {"path":"some/file/path.txt","url":"http://bing.com/search?q=dotnet"}`) }) }) // Shutdown(ctx context.Context) error Describe("Shutdown", func() { It("calls the Shutdown endpoint", func() { - nc, _ := nextcloud.NewStorageDriver(&nextcloud.StorageDriverConfig{ - EndPoint: "http://mock.com/apps/sciencemesh/", - MockHTTP: true, - }) - called := make([]string, 0) - h := nextcloud.GetNextcloudServerMock(&called) - mock, teardown := nextcloud.TestingHTTPClient(h) + nc, called, teardown := setUpNextcloudServer() defer teardown() - nc.SetHTTPClient(mock) err := nc.Shutdown(ctx) Expect(err).ToNot(HaveOccurred()) - Expect(called[0]).To(Equal(`POST /apps/sciencemesh/~tester/api/storage/Shutdown `)) + checkCalled(called, `POST /apps/sciencemesh/~tester/api/storage/Shutdown `) }) }) // SetArbitraryMetadata(ctx context.Context, ref *provider.Reference, md *provider.ArbitraryMetadata) error Describe("SetArbitraryMetadata", func() { It("calls the SetArbitraryMetadata endpoint", func() { - nc, _ := nextcloud.NewStorageDriver(&nextcloud.StorageDriverConfig{ - EndPoint: "http://mock.com/apps/sciencemesh/", - MockHTTP: true, - }) - called := make([]string, 0) - h := nextcloud.GetNextcloudServerMock(&called) - mock, teardown := nextcloud.TestingHTTPClient(h) + nc, called, teardown := setUpNextcloudServer() defer teardown() - nc.SetHTTPClient(mock) ref := &provider.Reference{ ResourceId: &provider.ResourceId{ StorageId: "storage-id", @@ -1097,22 +934,15 @@ var _ = Describe("Nextcloud", func() { } err := nc.SetArbitraryMetadata(ctx, ref, md) Expect(err).ToNot(HaveOccurred()) - Expect(called[0]).To(Equal(`POST /apps/sciencemesh/~tester/api/storage/SetArbitraryMetadata {"ref":{"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"some/file/path.txt"},"md":{"metadata":{"arbi":"trary","meta":"data"}}}`)) + checkCalled(called, `POST /apps/sciencemesh/~tester/api/storage/SetArbitraryMetadata {"ref":{"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"some/file/path.txt"},"md":{"metadata":{"arbi":"trary","meta":"data"}}}`) }) }) // UnsetArbitraryMetadata(ctx context.Context, ref *provider.Reference, keys []string) error Describe("UnsetArbitraryMetadata", func() { It("calls the UnsetArbitraryMetadata endpoint", func() { - nc, _ := nextcloud.NewStorageDriver(&nextcloud.StorageDriverConfig{ - EndPoint: "http://mock.com/apps/sciencemesh/", - MockHTTP: true, - }) - called := make([]string, 0) - h := nextcloud.GetNextcloudServerMock(&called) - mock, teardown := nextcloud.TestingHTTPClient(h) + nc, called, teardown := setUpNextcloudServer() defer teardown() - nc.SetHTTPClient(mock) ref := &provider.Reference{ ResourceId: &provider.ResourceId{ StorageId: "storage-id", @@ -1123,22 +953,15 @@ var _ = Describe("Nextcloud", func() { keys := []string{"arbi"} err := nc.UnsetArbitraryMetadata(ctx, ref, keys) Expect(err).ToNot(HaveOccurred()) - Expect(called[0]).To(Equal(`POST /apps/sciencemesh/~tester/api/storage/UnsetArbitraryMetadata {"ref":{"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"some/file/path.txt"},"keys":["arbi"]}`)) + checkCalled(called, `POST /apps/sciencemesh/~tester/api/storage/UnsetArbitraryMetadata {"ref":{"resource_id":{"storage_id":"storage-id","opaque_id":"opaque-id"},"path":"some/file/path.txt"},"keys":["arbi"]}`) }) }) // ListStorageSpaces(ctx context.Context, filter []*provider.ListStorageSpacesRequest_Filter) ([]*provider.StorageSpace, error) Describe("ListStorageSpaces", func() { It("calls the ListStorageSpaces endpoint", func() { - nc, _ := nextcloud.NewStorageDriver(&nextcloud.StorageDriverConfig{ - EndPoint: "http://mock.com/apps/sciencemesh/", - MockHTTP: true, - }) - called := make([]string, 0) - h := nextcloud.GetNextcloudServerMock(&called) - mock, teardown := nextcloud.TestingHTTPClient(h) + nc, called, teardown := setUpNextcloudServer() defer teardown() - nc.SetHTTPClient(mock) filter1 := &provider.ListStorageSpacesRequest_Filter{ Type: provider.ListStorageSpacesRequest_Filter_TYPE_OWNER, Term: &provider.ListStorageSpacesRequest_Filter_Owner{ @@ -1197,22 +1020,15 @@ var _ = Describe("Nextcloud", func() { Seconds: uint64(1234567890), }, })) - Expect(called[0]).To(Equal(`POST /apps/sciencemesh/~tester/api/storage/ListStorageSpaces [{"type":3,"Term":{"Owner":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1}}},{"type":2,"Term":{"Id":{"opaque_id":"opaque-id"}}},{"type":4,"Term":{"SpaceType":"home"}}]`)) + checkCalled(called, `POST /apps/sciencemesh/~tester/api/storage/ListStorageSpaces [{"type":3,"Term":{"Owner":{"idp":"0.0.0.0:19000","opaque_id":"f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c","type":1}}},{"type":2,"Term":{"Id":{"opaque_id":"opaque-id"}}},{"type":4,"Term":{"SpaceType":"home"}}]`) }) }) // CreateStorageSpace(ctx context.Context, req *provider.CreateStorageSpaceRequest) (*provider.CreateStorageSpaceResponse, error) Describe("CreateStorageSpace", func() { It("calls the CreateStorageSpace endpoint", func() { - nc, _ := nextcloud.NewStorageDriver(&nextcloud.StorageDriverConfig{ - EndPoint: "http://mock.com/apps/sciencemesh/", - MockHTTP: true, - }) - called := make([]string, 0) - h := nextcloud.GetNextcloudServerMock(&called) - mock, teardown := nextcloud.TestingHTTPClient(h) + nc, called, teardown := setUpNextcloudServer() defer teardown() - nc.SetHTTPClient(mock) // https://github.com/cs3org/go-cs3apis/blob/03e4a408c1f3b2882916cf3fad4c71081a20711d/cs3/storage/provider/v1beta1/provider_api.pb.go#L3176-L3192 result, err := nc.CreateStorageSpace(ctx, &provider.CreateStorageSpaceRequest{ Opaque: &types.Opaque{ @@ -1269,8 +1085,7 @@ var _ = Describe("Nextcloud", func() { }, }, })) - Expect(len(called)).To(Equal(1)) - Expect(called[0]).To(Equal(`POST /apps/sciencemesh/~tester/api/storage/CreateStorageSpace {"opaque":{"map":{"bar":{"value":"c2FtYQ=="},"foo":{"value":"c2FtYQ=="}}},"owner":{"id":{"idp":"some-idp","opaque_id":"some-opaque-user-id","type":1}},"type":"home","name":"My Storage Space","quota":{"quota_max_bytes":456,"quota_max_files":123}}`)) + checkCalled(called, `POST /apps/sciencemesh/~tester/api/storage/CreateStorageSpace {"opaque":{"map":{"bar":{"value":"c2FtYQ=="},"foo":{"value":"c2FtYQ=="}}},"owner":{"id":{"idp":"some-idp","opaque_id":"some-opaque-user-id","type":1}},"type":"home","name":"My Storage Space","quota":{"quota_max_bytes":456,"quota_max_files":123}}`) }) }) diff --git a/pkg/user/manager/nextcloud/nextcloud.go b/pkg/user/manager/nextcloud/nextcloud.go index db002871d1..87a15c0165 100644 --- a/pkg/user/manager/nextcloud/nextcloud.go +++ b/pkg/user/manager/nextcloud/nextcloud.go @@ -41,7 +41,9 @@ func init() { registry.Register("nextcloud", New) } -type manager struct { +// Manager is the Nextcloud-based implementation of the share.Manager interface +// see https://github.com/cs3org/reva/blob/v1.13.0/pkg/user/user.go#L29-L35 +type Manager struct { client *http.Client endPoint string } @@ -49,6 +51,7 @@ type manager struct { // UserManagerConfig contains config for a Nextcloud-based UserManager type UserManagerConfig struct { EndPoint string `mapstructure:"endpoint" docs:";The Nextcloud backend endpoint for user management"` + MockHTTP bool `mapstructure:"mock_http"` } func (c *UserManagerConfig) init() { @@ -79,18 +82,32 @@ func New(m map[string]interface{}) (user.Manager, error) { if err != nil { return nil, err } + c.init() - return NewUserManager(c, &http.Client{}) + return NewUserManager(c) } // NewUserManager returns a new Nextcloud-based UserManager -func NewUserManager(c *UserManagerConfig, hc *http.Client) (user.Manager, error) { - return &manager{ +func NewUserManager(c *UserManagerConfig) (*Manager, error) { + var client *http.Client + if c.MockHTTP { + // Wait for SetHTTPClient to be called later + client = nil + } else { + client = &http.Client{} + } + + return &Manager{ endPoint: c.EndPoint, // e.g. "http://nc/apps/sciencemesh/" - client: hc, + client: client, }, nil } +// SetHTTPClient sets the HTTP client +func (um *Manager) SetHTTPClient(c *http.Client) { + um.client = c +} + func getUser(ctx context.Context) (*userpb.User, error) { u, ok := ctxpkg.ContextGetUser(ctx) if !ok { @@ -100,19 +117,19 @@ func getUser(ctx context.Context) (*userpb.User, error) { return u, nil } -func (m *manager) do(ctx context.Context, a Action) (int, []byte, error) { +func (um *Manager) do(ctx context.Context, a Action) (int, []byte, error) { user, err := getUser(ctx) if err != nil { return 0, nil, err } - url := m.endPoint + "~" + user.Username + "/api/user/" + a.verb + url := um.endPoint + "~" + user.Username + "/api/user/" + a.verb req, err := http.NewRequest(http.MethodPost, url, strings.NewReader(a.argS)) if err != nil { panic(err) } req.Header.Set("Content-Type", "application/json") - resp, err := m.client.Do(req) + resp, err := um.client.Do(req) if err != nil { panic(err) } @@ -122,16 +139,18 @@ func (m *manager) do(ctx context.Context, a Action) (int, []byte, error) { return resp.StatusCode, body, err } -func (m *manager) Configure(ml map[string]interface{}) error { +// Configure method as defined in https://github.com/cs3org/reva/blob/v1.13.0/pkg/user/user.go#L29-L35 +func (um *Manager) Configure(ml map[string]interface{}) error { return nil } -func (m *manager) GetUser(ctx context.Context, uid *userpb.UserId) (*userpb.User, error) { +// GetUser method as defined in https://github.com/cs3org/reva/blob/v1.13.0/pkg/user/user.go#L29-L35 +func (um *Manager) GetUser(ctx context.Context, uid *userpb.UserId) (*userpb.User, error) { bodyStr, err := json.Marshal(uid) if err != nil { return nil, err } - _, respBody, err := m.do(ctx, Action{"GetUser", string(bodyStr)}) + _, respBody, err := um.do(ctx, Action{"GetUser", string(bodyStr)}) if err != nil { return nil, err } @@ -144,7 +163,8 @@ func (m *manager) GetUser(ctx context.Context, uid *userpb.UserId) (*userpb.User return result, err } -func (m *manager) GetUserByClaim(ctx context.Context, claim, value string) (*userpb.User, error) { +// GetUserByClaim method as defined in https://github.com/cs3org/reva/blob/v1.13.0/pkg/user/user.go#L29-L35 +func (um *Manager) GetUserByClaim(ctx context.Context, claim, value string) (*userpb.User, error) { type paramsObj struct { Claim string `json:"claim"` Value string `json:"value"` @@ -154,7 +174,7 @@ func (m *manager) GetUserByClaim(ctx context.Context, claim, value string) (*use Value: value, } bodyStr, _ := json.Marshal(bodyObj) - _, respBody, err := m.do(ctx, Action{"GetUserByClaim", string(bodyStr)}) + _, respBody, err := um.do(ctx, Action{"GetUserByClaim", string(bodyStr)}) if err != nil { return nil, err } @@ -166,12 +186,13 @@ func (m *manager) GetUserByClaim(ctx context.Context, claim, value string) (*use return result, err } -func (m *manager) GetUserGroups(ctx context.Context, uid *userpb.UserId) ([]string, error) { +// GetUserGroups method as defined in https://github.com/cs3org/reva/blob/v1.13.0/pkg/user/user.go#L29-L35 +func (um *Manager) GetUserGroups(ctx context.Context, uid *userpb.UserId) ([]string, error) { bodyStr, err := json.Marshal(uid) if err != nil { return nil, err } - _, respBody, err := m.do(ctx, Action{"GetUserGroups", string(bodyStr)}) + _, respBody, err := um.do(ctx, Action{"GetUserGroups", string(bodyStr)}) if err != nil { return nil, err } @@ -183,8 +204,9 @@ func (m *manager) GetUserGroups(ctx context.Context, uid *userpb.UserId) ([]stri return gs, err } -func (m *manager) FindUsers(ctx context.Context, query string) ([]*userpb.User, error) { - _, respBody, err := m.do(ctx, Action{"FindUsers", query}) +// FindUsers method as defined in https://github.com/cs3org/reva/blob/v1.13.0/pkg/user/user.go#L29-L35 +func (um *Manager) FindUsers(ctx context.Context, query string) ([]*userpb.User, error) { + _, respBody, err := um.do(ctx, Action{"FindUsers", query}) if err != nil { return nil, err } diff --git a/pkg/user/manager/nextcloud/nextcloud_test.go b/pkg/user/manager/nextcloud/nextcloud_test.go index a150f5e731..d043038925 100644 --- a/pkg/user/manager/nextcloud/nextcloud_test.go +++ b/pkg/user/manager/nextcloud/nextcloud_test.go @@ -20,6 +20,7 @@ package nextcloud_test import ( "context" + "fmt" "os" "google.golang.org/grpc/metadata" @@ -36,6 +37,39 @@ import ( . "github.com/onsi/gomega" ) +func setUpNextcloudServer() (*nextcloud.Manager, *[]string, func()) { + var conf *nextcloud.UserManagerConfig + + ncHost := os.Getenv("NEXTCLOUD") + fmt.Printf(`NEXTCLOUD env var: "%s"`, ncHost) + if len(ncHost) == 0 { + conf = &nextcloud.UserManagerConfig{ + EndPoint: "http://mock.com/apps/sciencemesh/", + MockHTTP: true, + } + nc, _ := nextcloud.NewUserManager(conf) + called := make([]string, 0) + h := nextcloud.GetNextcloudServerMock(&called) + mock, teardown := nextcloud.TestingHTTPClient(h) + nc.SetHTTPClient(mock) + return nc, &called, teardown + } + conf = &nextcloud.UserManagerConfig{ + EndPoint: ncHost + "/apps/sciencemesh/", + MockHTTP: false, + } + nc, _ := nextcloud.NewUserManager(conf) + return nc, nil, func() {} +} + +func checkCalled(called *[]string, expected string) { + if called == nil { + return + } + Expect(len(*called)).To(Equal(1)) + Expect((*called)[0]).To(Equal(expected)) +} + var _ = Describe("Nextcloud", func() { var ( ctx context.Context @@ -92,14 +126,9 @@ var _ = Describe("Nextcloud", func() { // GetUser(ctx context.Context, uid *userpb.UserId) (*userpb.User, error) Describe("GetUser", func() { It("calls the GetUser endpoint", func() { - called := make([]string, 0) - - h := nextcloud.GetNextcloudServerMock(&called) - mock, teardown := nextcloud.TestingHTTPClient(h) + um, called, teardown := setUpNextcloudServer() defer teardown() - um, _ := nextcloud.NewUserManager(&nextcloud.UserManagerConfig{ - EndPoint: "http://mock.com/apps/sciencemesh/", - }, mock) + user, err := um.GetUser(ctx, &userpb.UserId{ Idp: "some-idp", OpaqueId: "some-opaque-user-id", @@ -121,21 +150,16 @@ var _ = Describe("Nextcloud", func() { UidNumber: 0, GidNumber: 0, })) - Expect(called[0]).To(Equal(`POST /apps/sciencemesh/~tester/api/user/GetUser {"idp":"some-idp","opaque_id":"some-opaque-user-id","type":1}`)) + checkCalled(called, `POST /apps/sciencemesh/~tester/api/user/GetUser {"idp":"some-idp","opaque_id":"some-opaque-user-id","type":1}`) }) }) // GetUserByClaim(ctx context.Context, claim, value string) (*userpb.User, error) Describe("GetUserByClaim", func() { It("calls the GetUserByClaim endpoint", func() { - called := make([]string, 0) - - h := nextcloud.GetNextcloudServerMock(&called) - mock, teardown := nextcloud.TestingHTTPClient(h) + um, called, teardown := setUpNextcloudServer() defer teardown() - um, _ := nextcloud.NewUserManager(&nextcloud.UserManagerConfig{ - EndPoint: "http://mock.com/apps/sciencemesh/", - }, mock) + user, err := um.GetUserByClaim(ctx, "claim-string", "value-string") Expect(err).ToNot(HaveOccurred()) Expect(user).To(Equal(&userpb.User{ @@ -153,21 +177,16 @@ var _ = Describe("Nextcloud", func() { UidNumber: 0, GidNumber: 0, })) - Expect(called[0]).To(Equal(`POST /apps/sciencemesh/~tester/api/user/GetUserByClaim {"claim":"claim-string","value":"value-string"}`)) + checkCalled(called, `POST /apps/sciencemesh/~tester/api/user/GetUserByClaim {"claim":"claim-string","value":"value-string"}`) }) }) // GetUserGroups(ctx context.Context, uid *userpb.UserId) ([]string, error) Describe("GetUserGroups", func() { It("calls the GetUserGroups endpoint", func() { - called := make([]string, 0) - - h := nextcloud.GetNextcloudServerMock(&called) - mock, teardown := nextcloud.TestingHTTPClient(h) + um, called, teardown := setUpNextcloudServer() defer teardown() - um, _ := nextcloud.NewUserManager(&nextcloud.UserManagerConfig{ - EndPoint: "http://mock.com/apps/sciencemesh/", - }, mock) + groups, err := um.GetUserGroups(ctx, &userpb.UserId{ Idp: "some-idp", OpaqueId: "some-opaque-user-id", @@ -175,21 +194,16 @@ var _ = Describe("Nextcloud", func() { }) Expect(err).ToNot(HaveOccurred()) Expect(groups).To(Equal([]string{"wine-lovers"})) - Expect(called[0]).To(Equal(`POST /apps/sciencemesh/~tester/api/user/GetUserGroups {"idp":"some-idp","opaque_id":"some-opaque-user-id","type":1}`)) + checkCalled(called, `POST /apps/sciencemesh/~tester/api/user/GetUserGroups {"idp":"some-idp","opaque_id":"some-opaque-user-id","type":1}`) }) }) // FindUsers(ctx context.Context, query string) ([]*userpb.User, error) Describe("FindUsers", func() { It("calls the FindUsers endpoint", func() { - called := make([]string, 0) - - h := nextcloud.GetNextcloudServerMock(&called) - mock, teardown := nextcloud.TestingHTTPClient(h) + um, called, teardown := setUpNextcloudServer() defer teardown() - um, _ := nextcloud.NewUserManager(&nextcloud.UserManagerConfig{ - EndPoint: "http://mock.com/apps/sciencemesh/", - }, mock) + users, err := um.FindUsers(ctx, "some-query") Expect(err).ToNot(HaveOccurred()) Expect(len(users)).To(Equal(1)) @@ -208,7 +222,7 @@ var _ = Describe("Nextcloud", func() { UidNumber: 0, GidNumber: 0, })) - Expect(called[0]).To(Equal(`POST /apps/sciencemesh/~tester/api/user/FindUsers some-query`)) + checkCalled(called, `POST /apps/sciencemesh/~tester/api/user/FindUsers some-query`) }) }) })