From 59d93de47b768f5843b4ac32b9a4292f297004d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A1lint=20Ujv=C3=A1ri?= Date: Wed, 29 May 2024 16:30:11 +0200 Subject: [PATCH] test(act): controller add, revoke and get with history + fix typos --- openapi/SwarmCommon.yaml | 2 +- pkg/api/dynamicaccess.go | 8 ++--- pkg/dynamicaccess/controller.go | 16 ++++------ pkg/dynamicaccess/controller_test.go | 44 ++++++++++++++++++++++++++-- pkg/dynamicaccess/mock/controller.go | 28 +++++++++--------- pkg/kvs/kvs.go | 10 +++---- 6 files changed, 71 insertions(+), 37 deletions(-) diff --git a/openapi/SwarmCommon.yaml b/openapi/SwarmCommon.yaml index 85b7b2d6f62..620f3ed8aff 100644 --- a/openapi/SwarmCommon.yaml +++ b/openapi/SwarmCommon.yaml @@ -883,7 +883,7 @@ components: reserveSize: type: integer reserveSizeWithinRadius: - type: interger + type: integer pullsyncRate: type: number storageRadius: diff --git a/pkg/api/dynamicaccess.go b/pkg/api/dynamicaccess.go index aad9a69d56a..f83f0cca435 100644 --- a/pkg/api/dynamicaccess.go +++ b/pkg/api/dynamicaccess.go @@ -281,23 +281,23 @@ func (s *Service) actGrantRevokeHandler(w http.ResponseWriter, r *http.Request) } grantees := GranteesPatch{} - paresAddlist, err := parseKeys(gpr.Addlist) + parsedAddlist, err := parseKeys(gpr.Addlist) if err != nil { logger.Debug("add list key parse failed", "error", err) logger.Error(nil, "add list key parse failed") jsonhttp.InternalServerError(w, "error add list key parsing") return } - grantees.Addlist = append(grantees.Addlist, paresAddlist...) + grantees.Addlist = append(grantees.Addlist, parsedAddlist...) - paresRevokelist, err := parseKeys(gpr.Revokelist) + parsedRevokelist, err := parseKeys(gpr.Revokelist) if err != nil { logger.Debug("revoke list key parse failed", "error", err) logger.Error(nil, "revoke list key parse failed") jsonhttp.InternalServerError(w, "error revoke list key parsing") return } - grantees.Revokelist = append(grantees.Revokelist, paresRevokelist...) + grantees.Revokelist = append(grantees.Revokelist, parsedRevokelist...) ctx := r.Context() putter, err := s.newStamperPutter(ctx, putterOptions{ diff --git a/pkg/dynamicaccess/controller.go b/pkg/dynamicaccess/controller.go index 48e771cddc5..dffe4bbdf64 100644 --- a/pkg/dynamicaccess/controller.go +++ b/pkg/dynamicaccess/controller.go @@ -86,6 +86,8 @@ func (c *ControllerStruct) UploadHandler( return actRef, newHistoryRef, encryptedRef, err } +// Limitation: If an upadate is called again within a second from the latest upload/update then mantaray save fails with ErrInvalidInput, +// because the key (timestamp) is already present, hence a new fork is not created func (c *ControllerStruct) UpdateHandler( ctx context.Context, ls file.LoadSaver, @@ -180,12 +182,8 @@ func (c *ControllerStruct) newActWithPublisher(ctx context.Context, ls file.Load return act, nil } -func (c *ControllerStruct) getHistoryAndAct(ctx context.Context, ls file.LoadSaver, historyRef swarm.Address, publisher *ecdsa.PublicKey, timestamp int64) (History, kvs.KeyValueStore, error) { - var ( - history History - act kvs.KeyValueStore - err error - ) + +func (c *ControllerStruct) getHistoryAndAct(ctx context.Context, ls file.LoadSaver, historyRef swarm.Address, publisher *ecdsa.PublicKey, timestamp int64) (history History, act kvs.KeyValueStore, err error) { if historyRef.IsZero() { history, err = NewHistory(ls) if err != nil { @@ -230,11 +228,7 @@ func (c *ControllerStruct) saveHistoryAndAct(ctx context.Context, history Histor return historyRef, actRef, nil } -func (c *ControllerStruct) getGranteeList(ctx context.Context, ls file.LoadSaver, encryptedglRef swarm.Address, publisher *ecdsa.PublicKey) (GranteeList, error) { - var ( - gl GranteeList - err error - ) +func (c *ControllerStruct) getGranteeList(ctx context.Context, ls file.LoadSaver, encryptedglRef swarm.Address, publisher *ecdsa.PublicKey) (gl GranteeList, err error) { if encryptedglRef.IsZero() { gl, err = NewGranteeList(ls) if err != nil { diff --git a/pkg/dynamicaccess/controller_test.go b/pkg/dynamicaccess/controller_test.go index 7118368afa8..c25d8079bfa 100644 --- a/pkg/dynamicaccess/controller_test.go +++ b/pkg/dynamicaccess/controller_test.go @@ -19,6 +19,7 @@ import ( "github.com/ethersphere/bee/v2/pkg/kvs" "github.com/ethersphere/bee/v2/pkg/swarm" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "golang.org/x/crypto/sha3" ) @@ -206,13 +207,52 @@ func TestController_UpdateHandler(t *testing.T) { assert.NoError(t, err) assert.Len(t, gl.Get(), 2) }) + t.Run("add and revoke then get from history", func(t *testing.T) { + addRevokeList := []*ecdsa.PublicKey{&grantee.PublicKey} + ref := swarm.RandAddress(t) + _, hRef, encRef, err := c.UploadHandler(ctx, ls, ref, &publisher.PublicKey, swarm.ZeroAddress) + require.NoError(t, err) + + // Need to wait a second before each update call so that a new history mantaray fork is created for the new key(timestamp) entry + time.Sleep(1 * time.Second) + beforeRevokeTS := time.Now().Unix() + _, egranteeRef, hrefUpdate1, _, err := c.UpdateHandler(ctx, ls, gls, swarm.ZeroAddress, hRef, &publisher.PublicKey, addRevokeList, nil) + require.NoError(t, err) + + time.Sleep(1 * time.Second) + granteeRef, _, hrefUpdate2, _, err := c.UpdateHandler(ctx, ls, gls, egranteeRef, hrefUpdate1, &publisher.PublicKey, nil, addRevokeList) + require.NoError(t, err) + gl, err := dynamicaccess.NewGranteeListReference(ctx, ls, granteeRef) + require.NoError(t, err) + assert.Empty(t, gl.Get()) + // expect history reference to be different after grantee list update + assert.NotEqual(t, hrefUpdate1, hrefUpdate2) + + granteeDH := dynamicaccess.NewDefaultSession(grantee) + granteeAl := dynamicaccess.NewLogic(granteeDH) + granteeCtrl := dynamicaccess.NewController(granteeAl) + // download with grantee shall still work with the timestamp before the revoke + decRef, err := granteeCtrl.DownloadHandler(ctx, ls, encRef, &publisher.PublicKey, hrefUpdate2, beforeRevokeTS) + require.NoError(t, err) + assert.Equal(t, ref, decRef) + + // download with grantee shall NOT work with the latest timestamp + decRef, err = granteeCtrl.DownloadHandler(ctx, ls, encRef, &publisher.PublicKey, hrefUpdate2, time.Now().Unix()) + require.Error(t, err) + assert.Equal(t, swarm.ZeroAddress, decRef) + + // publisher shall still be able to download with the timestamp before the revoke + decRef, err = c.DownloadHandler(ctx, ls, encRef, &publisher.PublicKey, hrefUpdate2, beforeRevokeTS) + require.NoError(t, err) + assert.Equal(t, ref, decRef) + }) t.Run("add twice", func(t *testing.T) { addList := []*ecdsa.PublicKey{&grantee.PublicKey, &grantee.PublicKey} //nolint:ineffassign,staticcheck,wastedassign granteeRef, eglref, _, _, err := c.UpdateHandler(ctx, ls, gls, swarm.ZeroAddress, href, &publisher.PublicKey, addList, nil) granteeRef, _, _, _, _ = c.UpdateHandler(ctx, ls, ls, eglref, href, &publisher.PublicKey, addList, nil) - gl, err := dynamicaccess.NewGranteeListReference(ctx, createLs(), granteeRef) + gl, err := dynamicaccess.NewGranteeListReference(ctx, ls, granteeRef) assert.NoError(t, err) assert.Len(t, gl.Get(), 1) @@ -220,7 +260,7 @@ func TestController_UpdateHandler(t *testing.T) { t.Run("revoke non-existing", func(t *testing.T) { addList := []*ecdsa.PublicKey{&grantee.PublicKey} granteeRef, _, _, _, _ := c.UpdateHandler(ctx, ls, ls, swarm.ZeroAddress, href, &publisher.PublicKey, addList, nil) - gl, err := dynamicaccess.NewGranteeListReference(ctx, createLs(), granteeRef) + gl, err := dynamicaccess.NewGranteeListReference(ctx, ls, granteeRef) assert.NoError(t, err) assert.Len(t, gl.Get(), 1) diff --git a/pkg/dynamicaccess/mock/controller.go b/pkg/dynamicaccess/mock/controller.go index 3db86c88020..30f617bfccb 100644 --- a/pkg/dynamicaccess/mock/controller.go +++ b/pkg/dynamicaccess/mock/controller.go @@ -25,7 +25,7 @@ import ( "golang.org/x/crypto/sha3" ) -type mockDacService struct { +type mockController struct { historyMap map[string]dynamicaccess.History refMap map[string]swarm.Address acceptAll bool @@ -34,19 +34,19 @@ type mockDacService struct { ls file.LoadSaver } -type optionFunc func(*mockDacService) +type optionFunc func(*mockController) // Option is an option passed to a mock dynamicaccess Service. type Option interface { - apply(*mockDacService) + apply(*mockController) } -func (f optionFunc) apply(r *mockDacService) { f(r) } +func (f optionFunc) apply(r *mockController) { f(r) } // New creates a new mock dynamicaccess service. func New(o ...Option) dynamicaccess.Controller { storer := mockstorer.New() - m := &mockDacService{ + m := &mockController{ historyMap: make(map[string]dynamicaccess.History), refMap: make(map[string]swarm.Address), publisher: "", @@ -62,23 +62,23 @@ func New(o ...Option) dynamicaccess.Controller { // WithAcceptAll sets the mock to return fixed references on every call to DownloadHandler. func WithAcceptAll() Option { - return optionFunc(func(m *mockDacService) { m.acceptAll = true }) + return optionFunc(func(m *mockController) { m.acceptAll = true }) } func WithHistory(h dynamicaccess.History, ref string) Option { - return optionFunc(func(m *mockDacService) { + return optionFunc(func(m *mockController) { m.historyMap = map[string]dynamicaccess.History{ref: h} }) } func WithPublisher(ref string) Option { - return optionFunc(func(m *mockDacService) { + return optionFunc(func(m *mockController) { m.publisher = ref m.encrypter = encryption.New(encryption.Key(ref), 0, uint32(0), sha3.NewLegacyKeccak256) }) } -func (m *mockDacService) DownloadHandler(ctx context.Context, ls file.LoadSaver, encryptedRef swarm.Address, publisher *ecdsa.PublicKey, historyRootHash swarm.Address, timestamp int64) (swarm.Address, error) { +func (m *mockController) DownloadHandler(ctx context.Context, ls file.LoadSaver, encryptedRef swarm.Address, publisher *ecdsa.PublicKey, historyRootHash swarm.Address, timestamp int64) (swarm.Address, error) { if m.acceptAll { return swarm.ParseHexAddress("36e6c1bbdfee6ac21485d5f970479fd1df458d36df9ef4e8179708ed46da557f") } @@ -101,7 +101,7 @@ func (m *mockDacService) DownloadHandler(ctx context.Context, ls file.LoadSaver, return m.refMap[encryptedRef.String()], nil } -func (m *mockDacService) UploadHandler(ctx context.Context, ls file.LoadSaver, reference swarm.Address, publisher *ecdsa.PublicKey, historyRootHash swarm.Address) (swarm.Address, swarm.Address, swarm.Address, error) { +func (m *mockController) UploadHandler(ctx context.Context, ls file.LoadSaver, reference swarm.Address, publisher *ecdsa.PublicKey, historyRootHash swarm.Address) (swarm.Address, swarm.Address, swarm.Address, error) { historyRef, _ := swarm.ParseHexAddress("67bdf80a9bbea8eca9c8480e43fdceb485d2d74d5708e45144b8c4adacd13d9c") kvsRef, _ := swarm.ParseHexAddress("3339613565613837623134316665343461613630396333333237656364383934") if m.acceptAll { @@ -136,11 +136,11 @@ func (m *mockDacService) UploadHandler(ctx context.Context, ls file.LoadSaver, r return kvsRef, historyRef, swarm.NewAddress(encryptedRef), nil } -func (m *mockDacService) Close() error { +func (m *mockController) Close() error { return nil } -func (m *mockDacService) UpdateHandler(_ context.Context, ls file.LoadSaver, gls file.LoadSaver, encryptedglref swarm.Address, historyref swarm.Address, publisher *ecdsa.PublicKey, addList []*ecdsa.PublicKey, removeList []*ecdsa.PublicKey) (swarm.Address, swarm.Address, swarm.Address, swarm.Address, error) { +func (m *mockController) UpdateHandler(_ context.Context, ls file.LoadSaver, gls file.LoadSaver, encryptedglref swarm.Address, historyref swarm.Address, publisher *ecdsa.PublicKey, addList []*ecdsa.PublicKey, removeList []*ecdsa.PublicKey) (swarm.Address, swarm.Address, swarm.Address, swarm.Address, error) { historyRef, _ := swarm.ParseHexAddress("67bdf80a9bbea8eca9c8480e43fdceb485d2d74d5708e45144b8c4adacd13d9c") glRef, _ := swarm.ParseHexAddress("3339613565613837623134316665343461613630396333333237656364383934") eglRef, _ := swarm.ParseHexAddress("fc4e9fe978991257b897d987bc4ff13058b66ef45a53189a0b4fe84bb3346396") @@ -148,7 +148,7 @@ func (m *mockDacService) UpdateHandler(_ context.Context, ls file.LoadSaver, gls return glRef, eglRef, historyRef, actref, nil } -func (m *mockDacService) Get(ctx context.Context, ls file.LoadSaver, publisher *ecdsa.PublicKey, encryptedglref swarm.Address) ([]*ecdsa.PublicKey, error) { +func (m *mockController) Get(ctx context.Context, ls file.LoadSaver, publisher *ecdsa.PublicKey, encryptedglref swarm.Address) ([]*ecdsa.PublicKey, error) { if m.publisher == "" { return nil, fmt.Errorf("granteelist not found") } @@ -180,4 +180,4 @@ func requestPipelineFactory(ctx context.Context, s storage.Putter, encrypt bool, } } -var _ dynamicaccess.Controller = (*mockDacService)(nil) +var _ dynamicaccess.Controller = (*mockController)(nil) diff --git a/pkg/kvs/kvs.go b/pkg/kvs/kvs.go index 5f2381a8b24..0c7eae48c08 100644 --- a/pkg/kvs/kvs.go +++ b/pkg/kvs/kvs.go @@ -58,23 +58,23 @@ func (s *keyValueStore) Save(ctx context.Context) (swarm.Address, error) { } func New(ls file.LoadSaver) (KeyValueStore, error) { - manif, err := manifest.NewSimpleManifest(ls) + m, err := manifest.NewSimpleManifest(ls) if err != nil { return nil, err } return &keyValueStore{ - manifest: manif, + manifest: m, }, nil } -func NewReference(ls file.LoadSaver, rootHash swarm.Address) (KeyValueStore, error) { - manif, err := manifest.NewSimpleManifestReference(rootHash, ls) +func NewReference(ls file.LoadSaver, ref swarm.Address) (KeyValueStore, error) { + m, err := manifest.NewSimpleManifestReference(ref, ls) if err != nil { return nil, err } return &keyValueStore{ - manifest: manif, + manifest: m, }, nil }