forked from TrueCloudLab/frostfs-sdk-go
[#53] session: move package from neofs-api-go
Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
This commit is contained in:
parent
1feafcbcbf
commit
ee47683848
6 changed files with 825 additions and 0 deletions
139
session/container.go
Normal file
139
session/container.go
Normal file
|
@ -0,0 +1,139 @@
|
|||
package session
|
||||
|
||||
import (
|
||||
"github.com/nspcc-dev/neofs-api-go/v2/session"
|
||||
cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
|
||||
)
|
||||
|
||||
// ContainerContext represents NeoFS API v2-compatible
|
||||
// context of the container session.
|
||||
//
|
||||
// It is a wrapper over session.ContainerSessionContext
|
||||
// which allows to abstract from details of the message
|
||||
// structure.
|
||||
type ContainerContext session.ContainerSessionContext
|
||||
|
||||
// NewContainerContext creates and returns blank ContainerSessionContext.
|
||||
//
|
||||
// Defaults:
|
||||
// - not bound to any operation;
|
||||
// - applied to all containers.
|
||||
func NewContainerContext() *ContainerContext {
|
||||
v2 := new(session.ContainerSessionContext)
|
||||
v2.SetWildcard(true)
|
||||
|
||||
return ContainerContextFromV2(v2)
|
||||
}
|
||||
|
||||
// ContainerContextFromV2 wraps session.ContainerSessionContext
|
||||
// into ContainerContext.
|
||||
func ContainerContextFromV2(v *session.ContainerSessionContext) *ContainerContext {
|
||||
return (*ContainerContext)(v)
|
||||
}
|
||||
|
||||
// ToV2 converts ContainerContext to session.ContainerSessionContext
|
||||
// message structure.
|
||||
func (x *ContainerContext) ToV2() *session.ContainerSessionContext {
|
||||
return (*session.ContainerSessionContext)(x)
|
||||
}
|
||||
|
||||
// ApplyTo specifies which container the ContainerContext applies to.
|
||||
//
|
||||
// If id is nil, ContainerContext is applied to all containers.
|
||||
func (x *ContainerContext) ApplyTo(id *cid.ID) {
|
||||
v2 := (*session.ContainerSessionContext)(x)
|
||||
|
||||
v2.SetWildcard(id == nil)
|
||||
v2.SetContainerID(id.ToV2())
|
||||
}
|
||||
|
||||
// ActOnAllContainers is a helper function that conveniently
|
||||
// applies ContainerContext to all containers.
|
||||
func ApplyToAllContainers(c *ContainerContext) {
|
||||
c.ApplyTo(nil)
|
||||
}
|
||||
|
||||
// Container returns identifier of the container
|
||||
// to which the ContainerContext applies.
|
||||
//
|
||||
// Returns nil if ContainerContext is applied to
|
||||
// all containers.
|
||||
func (x *ContainerContext) Container() *cid.ID {
|
||||
v2 := (*session.ContainerSessionContext)(x)
|
||||
|
||||
if v2.Wildcard() {
|
||||
return nil
|
||||
}
|
||||
|
||||
return cid.NewFromV2(v2.ContainerID())
|
||||
}
|
||||
|
||||
func (x *ContainerContext) forVerb(v session.ContainerSessionVerb) {
|
||||
(*session.ContainerSessionContext)(x).
|
||||
SetVerb(v)
|
||||
}
|
||||
|
||||
func (x *ContainerContext) isForVerb(v session.ContainerSessionVerb) bool {
|
||||
return (*session.ContainerSessionContext)(x).
|
||||
Verb() == v
|
||||
}
|
||||
|
||||
// ForPut binds the ContainerContext to
|
||||
// PUT operation.
|
||||
func (x *ContainerContext) ForPut() {
|
||||
x.forVerb(session.ContainerVerbPut)
|
||||
}
|
||||
|
||||
// IsForPut checks if ContainerContext is bound to
|
||||
// PUT operation.
|
||||
func (x *ContainerContext) IsForPut() bool {
|
||||
return x.isForVerb(session.ContainerVerbPut)
|
||||
}
|
||||
|
||||
// ForDelete binds the ContainerContext to
|
||||
// DELETE operation.
|
||||
func (x *ContainerContext) ForDelete() {
|
||||
x.forVerb(session.ContainerVerbDelete)
|
||||
}
|
||||
|
||||
// IsForDelete checks if ContainerContext is bound to
|
||||
// DELETE operation.
|
||||
func (x *ContainerContext) IsForDelete() bool {
|
||||
return x.isForVerb(session.ContainerVerbDelete)
|
||||
}
|
||||
|
||||
// ForSetEACL binds the ContainerContext to
|
||||
// SETEACL operation.
|
||||
func (x *ContainerContext) ForSetEACL() {
|
||||
x.forVerb(session.ContainerVerbSetEACL)
|
||||
}
|
||||
|
||||
// IsForSetEACL checks if ContainerContext is bound to
|
||||
// SETEACL operation.
|
||||
func (x *ContainerContext) IsForSetEACL() bool {
|
||||
return x.isForVerb(session.ContainerVerbSetEACL)
|
||||
}
|
||||
|
||||
// Marshal marshals ContainerContext into a protobuf binary form.
|
||||
func (x *ContainerContext) Marshal(bs ...[]byte) ([]byte, error) {
|
||||
var buf []byte
|
||||
if len(bs) > 0 {
|
||||
buf = bs[0]
|
||||
}
|
||||
return x.ToV2().StableMarshal(buf)
|
||||
}
|
||||
|
||||
// Unmarshal unmarshals protobuf binary representation of ContainerContext.
|
||||
func (x *ContainerContext) Unmarshal(data []byte) error {
|
||||
return x.ToV2().Unmarshal(data)
|
||||
}
|
||||
|
||||
// MarshalJSON encodes ContainerContext to protobuf JSON format.
|
||||
func (x *ContainerContext) MarshalJSON() ([]byte, error) {
|
||||
return x.ToV2().MarshalJSON()
|
||||
}
|
||||
|
||||
// UnmarshalJSON decodes ContainerContext from protobuf JSON format.
|
||||
func (x *ContainerContext) UnmarshalJSON(data []byte) error {
|
||||
return x.ToV2().UnmarshalJSON(data)
|
||||
}
|
112
session/container_test.go
Normal file
112
session/container_test.go
Normal file
|
@ -0,0 +1,112 @@
|
|||
package session_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
v2session "github.com/nspcc-dev/neofs-api-go/v2/session"
|
||||
cidtest "github.com/nspcc-dev/neofs-sdk-go/container/id/test"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/session"
|
||||
sessiontest "github.com/nspcc-dev/neofs-sdk-go/session/test"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestContainerContextVerbs(t *testing.T) {
|
||||
c := session.NewContainerContext()
|
||||
|
||||
assert := func(setter func(), getter func() bool, verb v2session.ContainerSessionVerb) {
|
||||
setter()
|
||||
|
||||
require.True(t, getter())
|
||||
|
||||
require.Equal(t, verb, c.ToV2().Verb())
|
||||
}
|
||||
|
||||
t.Run("PUT", func(t *testing.T) {
|
||||
assert(c.ForPut, c.IsForPut, v2session.ContainerVerbPut)
|
||||
})
|
||||
|
||||
t.Run("DELETE", func(t *testing.T) {
|
||||
assert(c.ForDelete, c.IsForDelete, v2session.ContainerVerbDelete)
|
||||
})
|
||||
|
||||
t.Run("SETEACL", func(t *testing.T) {
|
||||
assert(c.ForSetEACL, c.IsForSetEACL, v2session.ContainerVerbSetEACL)
|
||||
})
|
||||
}
|
||||
|
||||
func TestContainerContext_ApplyTo(t *testing.T) {
|
||||
c := session.NewContainerContext()
|
||||
id := cidtest.GenerateID()
|
||||
|
||||
t.Run("method", func(t *testing.T) {
|
||||
c.ApplyTo(id)
|
||||
|
||||
require.Equal(t, id, c.Container())
|
||||
|
||||
c.ApplyTo(nil)
|
||||
|
||||
require.Nil(t, c.Container())
|
||||
})
|
||||
|
||||
t.Run("helper functions", func(t *testing.T) {
|
||||
c.ApplyTo(id)
|
||||
|
||||
session.ApplyToAllContainers(c)
|
||||
|
||||
require.Nil(t, c.Container())
|
||||
})
|
||||
}
|
||||
|
||||
func TestFilter_ToV2(t *testing.T) {
|
||||
t.Run("nil", func(t *testing.T) {
|
||||
var x *session.ContainerContext
|
||||
|
||||
require.Nil(t, x.ToV2())
|
||||
})
|
||||
|
||||
t.Run("default values", func(t *testing.T) {
|
||||
c := session.NewContainerContext()
|
||||
|
||||
// check initial values
|
||||
require.Nil(t, c.Container())
|
||||
|
||||
for _, op := range []func() bool{
|
||||
c.IsForPut,
|
||||
c.IsForDelete,
|
||||
c.IsForSetEACL,
|
||||
} {
|
||||
require.False(t, op())
|
||||
}
|
||||
|
||||
// convert to v2 message
|
||||
cV2 := c.ToV2()
|
||||
|
||||
require.Equal(t, v2session.ContainerVerbUnknown, cV2.Verb())
|
||||
require.True(t, cV2.Wildcard())
|
||||
require.Nil(t, cV2.ContainerID())
|
||||
})
|
||||
}
|
||||
|
||||
func TestContainerContextEncoding(t *testing.T) {
|
||||
c := sessiontest.ContainerContext()
|
||||
|
||||
t.Run("binary", func(t *testing.T) {
|
||||
data, err := c.Marshal()
|
||||
require.NoError(t, err)
|
||||
|
||||
c2 := session.NewContainerContext()
|
||||
require.NoError(t, c2.Unmarshal(data))
|
||||
|
||||
require.Equal(t, c, c2)
|
||||
})
|
||||
|
||||
t.Run("json", func(t *testing.T) {
|
||||
data, err := c.MarshalJSON()
|
||||
require.NoError(t, err)
|
||||
|
||||
c2 := session.NewContainerContext()
|
||||
require.NoError(t, c2.UnmarshalJSON(data))
|
||||
|
||||
require.Equal(t, c, c2)
|
||||
})
|
||||
}
|
282
session/session.go
Normal file
282
session/session.go
Normal file
|
@ -0,0 +1,282 @@
|
|||
package session
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
|
||||
"github.com/nspcc-dev/neofs-api-go/v2/refs"
|
||||
"github.com/nspcc-dev/neofs-api-go/v2/session"
|
||||
v2signature "github.com/nspcc-dev/neofs-api-go/v2/signature"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/owner"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/signature"
|
||||
sigutil "github.com/nspcc-dev/neofs-sdk-go/util/signature"
|
||||
)
|
||||
|
||||
// Token represents NeoFS API v2-compatible
|
||||
// session token.
|
||||
type Token session.SessionToken
|
||||
|
||||
// NewTokenFromV2 wraps session.SessionToken message structure
|
||||
// into Token.
|
||||
//
|
||||
// Nil session.SessionToken converts to nil.
|
||||
func NewTokenFromV2(tV2 *session.SessionToken) *Token {
|
||||
return (*Token)(tV2)
|
||||
}
|
||||
|
||||
// NewToken creates and returns blank Token.
|
||||
//
|
||||
// Defaults:
|
||||
// - body: nil;
|
||||
// - id: nil;
|
||||
// - ownerId: nil;
|
||||
// - sessionKey: nil;
|
||||
// - exp: 0;
|
||||
// - iat: 0;
|
||||
// - nbf: 0;
|
||||
func NewToken() *Token {
|
||||
return NewTokenFromV2(new(session.SessionToken))
|
||||
}
|
||||
|
||||
// ToV2 converts Token to session.SessionToken message structure.
|
||||
//
|
||||
// Nil Token converts to nil.
|
||||
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)
|
||||
})
|
||||
}
|
||||
|
||||
func (t *Token) setLifetimeField(f func(*session.TokenLifetime)) {
|
||||
t.setBodyField(func(body *session.SessionTokenBody) {
|
||||
lt := body.GetLifetime()
|
||||
if lt == nil {
|
||||
lt = new(session.TokenLifetime)
|
||||
body.SetLifetime(lt)
|
||||
}
|
||||
|
||||
f(lt)
|
||||
})
|
||||
}
|
||||
|
||||
// Exp returns epoch number of the token expiration.
|
||||
func (t *Token) Exp() uint64 {
|
||||
return (*session.SessionToken)(t).
|
||||
GetBody().
|
||||
GetLifetime().
|
||||
GetExp()
|
||||
}
|
||||
|
||||
// SetExp sets epoch number of the token expiration.
|
||||
func (t *Token) SetExp(exp uint64) {
|
||||
t.setLifetimeField(func(lt *session.TokenLifetime) {
|
||||
lt.SetExp(exp)
|
||||
})
|
||||
}
|
||||
|
||||
// Nbf returns starting epoch number of the token.
|
||||
func (t *Token) Nbf() uint64 {
|
||||
return (*session.SessionToken)(t).
|
||||
GetBody().
|
||||
GetLifetime().
|
||||
GetNbf()
|
||||
}
|
||||
|
||||
// SetNbf sets starting epoch number of the token.
|
||||
func (t *Token) SetNbf(nbf uint64) {
|
||||
t.setLifetimeField(func(lt *session.TokenLifetime) {
|
||||
lt.SetNbf(nbf)
|
||||
})
|
||||
}
|
||||
|
||||
// Iat returns starting epoch number of the token.
|
||||
func (t *Token) Iat() uint64 {
|
||||
return (*session.SessionToken)(t).
|
||||
GetBody().
|
||||
GetLifetime().
|
||||
GetIat()
|
||||
}
|
||||
|
||||
// SetIat sets the number of the epoch in which the token was issued.
|
||||
func (t *Token) SetIat(iat uint64) {
|
||||
t.setLifetimeField(func(lt *session.TokenLifetime) {
|
||||
lt.SetIat(iat)
|
||||
})
|
||||
}
|
||||
|
||||
// Sign calculates and writes signature of the Token data.
|
||||
//
|
||||
// Returns signature calculation errors.
|
||||
func (t *Token) Sign(key *ecdsa.PrivateKey) error {
|
||||
tV2 := (*session.SessionToken)(t)
|
||||
|
||||
signedData := v2signature.StableMarshalerWrapper{
|
||||
SM: tV2.GetBody(),
|
||||
}
|
||||
|
||||
return sigutil.SignDataWithHandler(key, signedData, func(key, sig []byte) {
|
||||
tSig := tV2.GetSignature()
|
||||
if tSig == nil {
|
||||
tSig = new(refs.Signature)
|
||||
}
|
||||
|
||||
tSig.SetKey(key)
|
||||
tSig.SetSign(sig)
|
||||
|
||||
tV2.SetSignature(tSig)
|
||||
})
|
||||
}
|
||||
|
||||
// VerifySignature checks if token signature is
|
||||
// presented and valid.
|
||||
func (t *Token) VerifySignature() bool {
|
||||
tV2 := (*session.SessionToken)(t)
|
||||
|
||||
signedData := v2signature.StableMarshalerWrapper{
|
||||
SM: tV2.GetBody(),
|
||||
}
|
||||
|
||||
return sigutil.VerifyDataWithSource(signedData, func() (key, sig []byte) {
|
||||
tSig := tV2.GetSignature()
|
||||
return tSig.GetKey(), tSig.GetSign()
|
||||
}) == nil
|
||||
}
|
||||
|
||||
// Signature returns Token signature.
|
||||
func (t *Token) Signature() *signature.Signature {
|
||||
return signature.NewFromV2(
|
||||
(*session.SessionToken)(t).
|
||||
GetSignature(),
|
||||
)
|
||||
}
|
||||
|
||||
// SetContext sets context of the Token.
|
||||
//
|
||||
// Supported contexts:
|
||||
// - *ContainerContext.
|
||||
//
|
||||
// Resets context if it is not supported.
|
||||
func (t *Token) SetContext(v interface{}) {
|
||||
var cV2 session.SessionTokenContext
|
||||
|
||||
switch c := v.(type) {
|
||||
case *ContainerContext:
|
||||
cV2 = c.ToV2()
|
||||
}
|
||||
|
||||
t.setBodyField(func(body *session.SessionTokenBody) {
|
||||
body.SetContext(cV2)
|
||||
})
|
||||
}
|
||||
|
||||
// Context returns context of the Token.
|
||||
//
|
||||
// Supports same contexts as SetContext.
|
||||
//
|
||||
// Returns nil if context is not supported.
|
||||
func (t *Token) Context() interface{} {
|
||||
switch v := (*session.SessionToken)(t).
|
||||
GetBody().
|
||||
GetContext(); c := v.(type) {
|
||||
default:
|
||||
return nil
|
||||
case *session.ContainerSessionContext:
|
||||
return ContainerContextFromV2(c)
|
||||
}
|
||||
}
|
||||
|
||||
// GetContainerContext is a helper function that casts
|
||||
// Token context to ContainerContext.
|
||||
//
|
||||
// Returns nil if context is not a ContainerContext.
|
||||
func GetContainerContext(t *Token) *ContainerContext {
|
||||
c, _ := t.Context().(*ContainerContext)
|
||||
return c
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
202
session/session_test.go
Normal file
202
session/session_test.go
Normal file
|
@ -0,0 +1,202 @@
|
|||
package session_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
sessionv2 "github.com/nspcc-dev/neofs-api-go/v2/session"
|
||||
ownertest "github.com/nspcc-dev/neofs-sdk-go/owner/test"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/session"
|
||||
sessiontest "github.com/nspcc-dev/neofs-sdk-go/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()
|
||||
|
||||
ownerID := ownertest.GenerateID()
|
||||
|
||||
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)
|
||||
})
|
||||
}
|
||||
|
||||
func TestToken_VerifySignature(t *testing.T) {
|
||||
t.Run("nil", func(t *testing.T) {
|
||||
var tok *session.Token
|
||||
|
||||
require.False(t, tok.VerifySignature())
|
||||
})
|
||||
|
||||
t.Run("unsigned", func(t *testing.T) {
|
||||
tok := sessiontest.Generate()
|
||||
|
||||
require.False(t, tok.VerifySignature())
|
||||
})
|
||||
|
||||
t.Run("signed", func(t *testing.T) {
|
||||
tok := sessiontest.GenerateSigned()
|
||||
|
||||
require.True(t, tok.VerifySignature())
|
||||
})
|
||||
}
|
||||
|
||||
var unsupportedContexts = []interface{}{
|
||||
123,
|
||||
true,
|
||||
session.NewToken(),
|
||||
}
|
||||
|
||||
var nonContainerContexts = unsupportedContexts
|
||||
|
||||
func TestToken_Context(t *testing.T) {
|
||||
tok := session.NewToken()
|
||||
|
||||
for _, item := range []struct {
|
||||
ctx interface{}
|
||||
v2assert func(interface{})
|
||||
}{
|
||||
{
|
||||
ctx: sessiontest.ContainerContext(),
|
||||
v2assert: func(c interface{}) {
|
||||
require.Equal(t, c.(*session.ContainerContext).ToV2(), tok.ToV2().GetBody().GetContext())
|
||||
},
|
||||
},
|
||||
} {
|
||||
tok.SetContext(item.ctx)
|
||||
|
||||
require.Equal(t, item.ctx, tok.Context())
|
||||
|
||||
item.v2assert(item.ctx)
|
||||
}
|
||||
|
||||
for _, c := range unsupportedContexts {
|
||||
tok.SetContext(c)
|
||||
|
||||
require.Nil(t, tok.Context())
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetContainerContext(t *testing.T) {
|
||||
tok := session.NewToken()
|
||||
|
||||
c := sessiontest.ContainerContext()
|
||||
|
||||
tok.SetContext(c)
|
||||
|
||||
require.Equal(t, c, session.GetContainerContext(tok))
|
||||
|
||||
for _, c := range nonContainerContexts {
|
||||
tok.SetContext(c)
|
||||
|
||||
require.Nil(t, session.GetContainerContext(tok))
|
||||
}
|
||||
}
|
||||
|
||||
func TestToken_Exp(t *testing.T) {
|
||||
tok := session.NewToken()
|
||||
|
||||
const exp = 11
|
||||
|
||||
tok.SetExp(exp)
|
||||
|
||||
require.EqualValues(t, exp, tok.Exp())
|
||||
}
|
||||
|
||||
func TestToken_Nbf(t *testing.T) {
|
||||
tok := session.NewToken()
|
||||
|
||||
const nbf = 22
|
||||
|
||||
tok.SetNbf(nbf)
|
||||
|
||||
require.EqualValues(t, nbf, tok.Nbf())
|
||||
}
|
||||
|
||||
func TestToken_Iat(t *testing.T) {
|
||||
tok := session.NewToken()
|
||||
|
||||
const iat = 33
|
||||
|
||||
tok.SetIat(iat)
|
||||
|
||||
require.EqualValues(t, iat, tok.Iat())
|
||||
}
|
||||
|
||||
func TestNewTokenFromV2(t *testing.T) {
|
||||
t.Run("from nil", func(t *testing.T) {
|
||||
var x *sessionv2.SessionToken
|
||||
|
||||
require.Nil(t, session.NewTokenFromV2(x))
|
||||
})
|
||||
}
|
||||
|
||||
func TestToken_ToV2(t *testing.T) {
|
||||
t.Run("nil", func(t *testing.T) {
|
||||
var x *session.Token
|
||||
|
||||
require.Nil(t, x.ToV2())
|
||||
})
|
||||
}
|
||||
|
||||
func TestNewToken(t *testing.T) {
|
||||
t.Run("default values", func(t *testing.T) {
|
||||
token := session.NewToken()
|
||||
|
||||
// check initial values
|
||||
require.Nil(t, token.Signature())
|
||||
require.Nil(t, token.OwnerID())
|
||||
require.Nil(t, token.SessionKey())
|
||||
require.Nil(t, token.ID())
|
||||
require.Zero(t, token.Exp())
|
||||
require.Zero(t, token.Iat())
|
||||
require.Zero(t, token.Nbf())
|
||||
|
||||
// convert to v2 message
|
||||
tokenV2 := token.ToV2()
|
||||
|
||||
require.Nil(t, tokenV2.GetSignature())
|
||||
require.Nil(t, tokenV2.GetBody())
|
||||
})
|
||||
}
|
26
session/test/container.go
Normal file
26
session/test/container.go
Normal file
|
@ -0,0 +1,26 @@
|
|||
package sessiontest
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
|
||||
cidtest "github.com/nspcc-dev/neofs-sdk-go/container/id/test"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/session"
|
||||
)
|
||||
|
||||
// ContainerContext returns session.ContainerContext
|
||||
// which applies to random operation on a random container.
|
||||
func ContainerContext() *session.ContainerContext {
|
||||
c := session.NewContainerContext()
|
||||
|
||||
setters := []func(){
|
||||
c.ForPut,
|
||||
c.ForDelete,
|
||||
c.ForSetEACL,
|
||||
}
|
||||
|
||||
setters[rand.Uint32()%uint32(len(setters))]()
|
||||
|
||||
c.ApplyTo(cidtest.GenerateID())
|
||||
|
||||
return c
|
||||
}
|
64
session/test/token.go
Normal file
64
session/test/token.go
Normal file
|
@ -0,0 +1,64 @@
|
|||
package sessiontest
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/owner"
|
||||
"github.com/nspcc-dev/neofs-sdk-go/session"
|
||||
)
|
||||
|
||||
var p *keys.PrivateKey
|
||||
|
||||
func init() {
|
||||
var err error
|
||||
|
||||
p, err = keys.NewPrivateKey()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Generate returns random session.Token.
|
||||
//
|
||||
// Resulting token is unsigned.
|
||||
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 := p.PublicKey().Bytes()
|
||||
|
||||
tok.SetID(uid)
|
||||
tok.SetOwnerID(ownerID)
|
||||
tok.SetSessionKey(keyBin)
|
||||
tok.SetExp(11)
|
||||
tok.SetNbf(22)
|
||||
tok.SetIat(33)
|
||||
|
||||
return tok
|
||||
}
|
||||
|
||||
// GenerateSigned returns signed random session.Token.
|
||||
//
|
||||
// Panics if token could not be signed (actually unexpected).
|
||||
func GenerateSigned() *session.Token {
|
||||
tok := Generate()
|
||||
|
||||
err := tok.Sign(&p.PrivateKey)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return tok
|
||||
}
|
Loading…
Reference in a new issue