From 37b415347d8ffa597b73b1c850ea7e34168591c3 Mon Sep 17 00:00:00 2001 From: Leonard Lyubich Date: Mon, 24 May 2021 20:34:56 +0300 Subject: [PATCH] [#283] pkg/token: Replace SessionToken into a session package There is a need to add session token to `eacl.Table` structure. To do this, we need to replace `token.SessionToken` type to another package since `eacl` package imports `token` one (potential cross-import). Create `pkg/session` package and replace session token implementation to it. Related API in `container` package is deprecated from now. Additionally implement test generator of random session tokens. Signed-off-by: Leonard Lyubich --- pkg/container/container.go | 8 +-- pkg/session/session.go | 125 +++++++++++++++++++++++++++++++++++ pkg/session/session_test.go | 68 +++++++++++++++++++ pkg/session/test/token.go | 35 ++++++++++ pkg/token/session.go | 128 ++++-------------------------------- 5 files changed, 246 insertions(+), 118 deletions(-) create mode 100644 pkg/session/session.go create mode 100644 pkg/session/session_test.go create mode 100644 pkg/session/test/token.go diff --git a/pkg/container/container.go b/pkg/container/container.go index f758d1c..5b07a55 100644 --- a/pkg/container/container.go +++ b/pkg/container/container.go @@ -7,14 +7,14 @@ import ( "github.com/nspcc-dev/neofs-api-go/pkg" "github.com/nspcc-dev/neofs-api-go/pkg/netmap" "github.com/nspcc-dev/neofs-api-go/pkg/owner" - "github.com/nspcc-dev/neofs-api-go/pkg/token" + "github.com/nspcc-dev/neofs-api-go/pkg/session" "github.com/nspcc-dev/neofs-api-go/v2/container" ) type Container struct { v2 container.Container - token *token.SessionToken + token *session.Token sig *pkg.Signature } @@ -159,13 +159,13 @@ func (c *Container) SetPlacementPolicy(v *netmap.PlacementPolicy) { // SessionToken returns token of the session within // which container was created. -func (c Container) SessionToken() *token.SessionToken { +func (c Container) SessionToken() *session.Token { return c.token } // SetSessionToken sets token of the session within // which container was created. -func (c *Container) SetSessionToken(t *token.SessionToken) { +func (c *Container) SetSessionToken(t *session.Token) { c.token = t } diff --git a/pkg/session/session.go b/pkg/session/session.go new file mode 100644 index 0000000..b11a058 --- /dev/null +++ b/pkg/session/session.go @@ -0,0 +1,125 @@ +package session + +import ( + "github.com/nspcc-dev/neofs-api-go/pkg" + "github.com/nspcc-dev/neofs-api-go/pkg/owner" + "github.com/nspcc-dev/neofs-api-go/v2/session" +) + +// Token represents NeoFS API v2-compatible +// session token. +type Token session.SessionToken + +// NewTokenFromV2 wraps session.SessionToken message structure +// into Token. +func NewTokenFromV2(tV2 *session.SessionToken) *Token { + return (*Token)(tV2) +} + +// NewToken creates and returns blank Token. +func NewToken() *Token { + return NewTokenFromV2(new(session.SessionToken)) +} + +// ToV2 converts Token to session.SessionToken message structure. +func (t *Token) ToV2() *session.SessionToken { + return (*session.SessionToken)(t) +} + +func (t *Token) setBodyField(setter func(*session.SessionTokenBody)) { + token := (*session.SessionToken)(t) + body := token.GetBody() + + if body == nil { + body = new(session.SessionTokenBody) + token.SetBody(body) + } + + setter(body) +} + +// ID returns Token identifier. +func (t *Token) ID() []byte { + return (*session.SessionToken)(t). + GetBody(). + GetID() +} + +// SetID sets Token identifier. +func (t *Token) SetID(v []byte) { + t.setBodyField(func(body *session.SessionTokenBody) { + body.SetID(v) + }) +} + +// OwnerID returns Token's owner identifier. +func (t *Token) OwnerID() *owner.ID { + return owner.NewIDFromV2( + (*session.SessionToken)(t). + GetBody(). + GetOwnerID(), + ) +} + +// SetOwnerID sets Token's owner identifier. +func (t *Token) SetOwnerID(v *owner.ID) { + t.setBodyField(func(body *session.SessionTokenBody) { + body.SetOwnerID(v.ToV2()) + }) +} + +// SessionKey returns public key of the session +// in a binary format. +func (t *Token) SessionKey() []byte { + return (*session.SessionToken)(t). + GetBody(). + GetSessionKey() +} + +// SetSessionKey sets public key of the session +// // in a binary format. +func (t *Token) SetSessionKey(v []byte) { + t.setBodyField(func(body *session.SessionTokenBody) { + body.SetSessionKey(v) + }) +} + +// Signature returns Token signature. +func (t *Token) Signature() *pkg.Signature { + return pkg.NewSignatureFromV2( + (*session.SessionToken)(t). + GetSignature(), + ) +} + +// Marshal marshals Token into a protobuf binary form. +// +// Buffer is allocated when the argument is empty. +// Otherwise, the first buffer is used. +func (t *Token) Marshal(bs ...[]byte) ([]byte, error) { + var buf []byte + if len(bs) > 0 { + buf = bs[0] + } + + return (*session.SessionToken)(t). + StableMarshal(buf) +} + +// Unmarshal unmarshals protobuf binary representation of Token. +func (t *Token) Unmarshal(data []byte) error { + return (*session.SessionToken)(t). + Unmarshal(data) +} + +// MarshalJSON encodes Token to protobuf JSON format. +func (t *Token) MarshalJSON() ([]byte, error) { + return (*session.SessionToken)(t). + MarshalJSON() +} + +// UnmarshalJSON decodes Token from protobuf JSON format. +func (t *Token) UnmarshalJSON(data []byte) error { + return (*session.SessionToken)(t). + UnmarshalJSON(data) +} diff --git a/pkg/session/session_test.go b/pkg/session/session_test.go new file mode 100644 index 0000000..9105869 --- /dev/null +++ b/pkg/session/session_test.go @@ -0,0 +1,68 @@ +package session_test + +import ( + "crypto/rand" + "testing" + + "github.com/nspcc-dev/neofs-api-go/pkg/owner" + "github.com/nspcc-dev/neofs-api-go/pkg/session" + sessiontest "github.com/nspcc-dev/neofs-api-go/pkg/session/test" + "github.com/stretchr/testify/require" +) + +func TestSessionToken_SetID(t *testing.T) { + token := session.NewToken() + + id := []byte{1, 2, 3} + token.SetID(id) + + require.Equal(t, id, token.ID()) +} + +func TestSessionToken_SetOwnerID(t *testing.T) { + token := session.NewToken() + + w := new(owner.NEO3Wallet) + _, err := rand.Read(w.Bytes()) + require.NoError(t, err) + + ownerID := owner.NewID() + ownerID.SetNeo3Wallet(w) + + token.SetOwnerID(ownerID) + + require.Equal(t, ownerID, token.OwnerID()) +} + +func TestSessionToken_SetSessionKey(t *testing.T) { + token := session.NewToken() + + key := []byte{1, 2, 3} + token.SetSessionKey(key) + + require.Equal(t, key, token.SessionKey()) +} + +func TestSessionTokenEncoding(t *testing.T) { + tok := sessiontest.Generate() + + t.Run("binary", func(t *testing.T) { + data, err := tok.Marshal() + require.NoError(t, err) + + tok2 := session.NewToken() + require.NoError(t, tok2.Unmarshal(data)) + + require.Equal(t, tok, tok2) + }) + + t.Run("json", func(t *testing.T) { + data, err := tok.MarshalJSON() + require.NoError(t, err) + + tok2 := session.NewToken() + require.NoError(t, tok2.UnmarshalJSON(data)) + + require.Equal(t, tok, tok2) + }) +} diff --git a/pkg/session/test/token.go b/pkg/session/test/token.go new file mode 100644 index 0000000..3924984 --- /dev/null +++ b/pkg/session/test/token.go @@ -0,0 +1,35 @@ +package sessiontest + +import ( + "math/rand" + + "github.com/google/uuid" + "github.com/nspcc-dev/neofs-api-go/pkg/owner" + "github.com/nspcc-dev/neofs-api-go/pkg/session" + crypto "github.com/nspcc-dev/neofs-crypto" + "github.com/nspcc-dev/neofs-crypto/test" +) + +// Generate returns random session.Token. +func Generate() *session.Token { + tok := session.NewToken() + + uid, err := uuid.New().MarshalBinary() + if err != nil { + panic(err) + } + + w := new(owner.NEO3Wallet) + rand.Read(w.Bytes()) + + ownerID := owner.NewID() + ownerID.SetNeo3Wallet(w) + + keyBin := crypto.MarshalPublicKey(&test.DecodeKey(0).PublicKey) + + tok.SetID(uid) + tok.SetOwnerID(ownerID) + tok.SetSessionKey(keyBin) + + return tok +} diff --git a/pkg/token/session.go b/pkg/token/session.go index 834110b..5c8e8a7 100644 --- a/pkg/token/session.go +++ b/pkg/token/session.go @@ -1,122 +1,22 @@ package token import ( - "github.com/nspcc-dev/neofs-api-go/pkg" - "github.com/nspcc-dev/neofs-api-go/pkg/owner" - "github.com/nspcc-dev/neofs-api-go/v2/session" + "github.com/nspcc-dev/neofs-api-go/pkg/session" ) -type SessionToken session.SessionToken - -func NewSessionTokenFromV2(tV2 *session.SessionToken) *SessionToken { - return (*SessionToken)(tV2) -} - -func NewSessionToken() *SessionToken { - return NewSessionTokenFromV2(new(session.SessionToken)) -} - -func (t *SessionToken) ToV2() *session.SessionToken { - return (*session.SessionToken)(t) -} - -func (t *SessionToken) setBodyField(setter func(*session.SessionTokenBody)) { - token := (*session.SessionToken)(t) - body := token.GetBody() - - if body == nil { - body = new(session.SessionTokenBody) - token.SetBody(body) - } - - setter(body) -} - -func (t *SessionToken) ID() []byte { - return (*session.SessionToken)(t). - GetBody(). - GetID() -} - -func (t *SessionToken) SetID(v []byte) { - t.setBodyField(func(body *session.SessionTokenBody) { - body.SetID(v) - }) -} - -func (t *SessionToken) OwnerID() *owner.ID { - return owner.NewIDFromV2( - (*session.SessionToken)(t). - GetBody(). - GetOwnerID(), - ) -} - -func (t *SessionToken) SetOwnerID(v *owner.ID) { - t.setBodyField(func(body *session.SessionTokenBody) { - body.SetOwnerID(v.ToV2()) - }) -} - -func (t *SessionToken) SessionKey() []byte { - return (*session.SessionToken)(t). - GetBody(). - GetSessionKey() -} - -func (t *SessionToken) SetSessionKey(v []byte) { - t.setBodyField(func(body *session.SessionTokenBody) { - body.SetSessionKey(v) - }) -} - -func (t *SessionToken) Signature() *pkg.Signature { - return pkg.NewSignatureFromV2( - (*session.SessionToken)(t). - GetSignature(), - ) -} - -// Marshal marshals SessionToken into a protobuf binary form. +// SessionToken represents NeoFS API v2-compatible +// session token. // -// Buffer is allocated when the argument is empty. -// Otherwise, the first buffer is used. -func (t *SessionToken) Marshal(bs ...[]byte) ([]byte, error) { - var buf []byte - if len(bs) > 0 { - buf = bs[0] - } +// Deprecated: use session.Token instead +type SessionToken = session.Token - return (*session.SessionToken)(t). - StableMarshal(buf) -} +// NewSessionTokenFromV2 wraps session.SessionToken message structure +// into Token. +// +// Deprecated: use session.NewTokenFromV2 instead. +var NewSessionTokenFromV2 = session.NewTokenFromV2 -// Unmarshal unmarshals protobuf binary representation of SessionToken. -func (t *SessionToken) Unmarshal(data []byte) error { - tV2 := new(session.SessionToken) - if err := tV2.Unmarshal(data); err != nil { - return err - } - - *t = *NewSessionTokenFromV2(tV2) - - return nil -} - -// MarshalJSON encodes SessionToken to protobuf JSON format. -func (t *SessionToken) MarshalJSON() ([]byte, error) { - return (*session.SessionToken)(t). - MarshalJSON() -} - -// UnmarshalJSON decodes SessionToken from protobuf JSON format. -func (t *SessionToken) UnmarshalJSON(data []byte) error { - tV2 := new(session.SessionToken) - if err := tV2.UnmarshalJSON(data); err != nil { - return err - } - - *t = *NewSessionTokenFromV2(tV2) - - return nil -} +// NewSessionToken creates and returns blank session token. +// +// Deprecated: use session.NewToken instead. +var NewSessionToken = session.NewToken