[#336] session: Support group object sessions

Rename `LimitByObject` method of the `session.Object` type to
`LimitByObjects` and make it to accept variadic parameter.

Signed-off-by: Leonard Lyubich <ctulhurider@gmail.com>
This commit is contained in:
Leonard Lyubich 2022-09-16 18:13:57 +04:00 committed by LeL
parent c6576c8112
commit 1325b4f272
6 changed files with 97 additions and 77 deletions

2
go.mod
View file

@ -9,7 +9,7 @@ require (
github.com/mr-tron/base58 v1.2.0
github.com/nspcc-dev/hrw v1.0.9
github.com/nspcc-dev/neo-go v0.99.2
github.com/nspcc-dev/neofs-api-go/v2 v2.13.2-0.20220919124434-cf868188ef9c
github.com/nspcc-dev/neofs-api-go/v2 v2.13.2-0.20221004142957-5fc2644c680d
github.com/nspcc-dev/neofs-contract v0.15.3
github.com/nspcc-dev/tzhash v1.6.1
github.com/stretchr/testify v1.7.0

BIN
go.sum

Binary file not shown.

View file

@ -1737,7 +1737,7 @@ func (p *Pool) openDefaultSession(ctx *callContext) error {
tok.BindContainer(ctx.sessionCnr)
if ctx.sessionObjSet {
tok.LimitByObject(ctx.sessionObj)
tok.LimitByObjects(ctx.sessionObj)
}
// sign the token

View file

@ -29,8 +29,7 @@ type Object struct {
cnrSet bool
cnr cid.ID
objSet bool
obj oid.ID
objs []oid.ID
}
func (x *Object) readContext(c session.TokenContext, checkFieldPresence bool) error {
@ -39,30 +38,31 @@ func (x *Object) readContext(c session.TokenContext, checkFieldPresence bool) er
return fmt.Errorf("invalid context %T", c)
}
addr := cObj.GetAddress()
if checkFieldPresence && addr == nil {
return errors.New("missing object address")
}
var err error
cnr := addr.GetContainerID()
cnr := cObj.GetContainer()
if x.cnrSet = cnr != nil; x.cnrSet {
err := x.cnr.ReadFromV2(*cnr)
if err != nil {
return fmt.Errorf("invalid container ID: %w", err)
}
} else if checkFieldPresence {
return errors.New("missing container in object address")
return errors.New("missing target container")
}
obj := addr.GetObjectID()
if x.objSet = obj != nil; x.objSet {
err = x.obj.ReadFromV2(*obj)
objs := cObj.GetObjects()
if objs != nil {
x.objs = make([]oid.ID, len(objs))
for i := range objs {
err = x.objs[i].ReadFromV2(objs[i])
if err != nil {
return fmt.Errorf("invalid object ID: %w", err)
return fmt.Errorf("invalid target object: %w", err)
}
}
} else {
x.objs = nil
}
x.verb = ObjectVerb(cObj.GetVerb())
@ -85,24 +85,25 @@ func (x Object) writeContext() session.TokenContext {
var c session.ObjectSessionContext
c.SetVerb(session.ObjectSessionVerb(x.verb))
if x.cnrSet || x.objSet {
var addr refs.Address
if x.cnrSet || len(x.objs) > 0 {
var cnr *refs.ContainerID
if x.cnrSet {
var cnr refs.ContainerID
x.cnr.WriteToV2(&cnr)
addr.SetContainerID(&cnr)
cnr = new(refs.ContainerID)
x.cnr.WriteToV2(cnr)
}
if x.objSet {
var obj refs.ObjectID
x.obj.WriteToV2(&obj)
var objs []refs.ObjectID
addr.SetObjectID(&obj)
if x.objs != nil {
objs = make([]refs.ObjectID, len(x.objs))
for i := range x.objs {
x.objs[i].WriteToV2(&objs[i])
}
}
c.SetAddress(&addr)
c.SetTarget(cnr, objs...)
}
return &c
@ -194,22 +195,33 @@ func (x Object) AssertContainer(cnr cid.ID) bool {
return x.cnr.Equals(cnr)
}
// LimitByObject limits session scope to a given object from the container
// LimitByObjects limits session scope to the given objects from the container
// to which Object session is bound.
//
// Argument MUST NOT be mutated, make a copy first.
//
// See also AssertObject.
func (x *Object) LimitByObject(obj oid.ID) {
x.obj = obj
x.objSet = true
func (x *Object) LimitByObjects(objs ...oid.ID) {
x.objs = objs
}
// AssertObject checks if Object session is applied to a given object.
//
// Zero Object is applied to all objects in the container.
//
// See also LimitByObject.
// See also LimitByObjects.
func (x Object) AssertObject(obj oid.ID) bool {
return !x.objSet || x.obj.Equals(obj)
if len(x.objs) == 0 {
return true
}
for i := range x.objs {
if x.objs[i].Equals(obj) {
return true
}
}
return false
}
// ObjectVerb enumerates object operations.

View file

@ -15,7 +15,6 @@ import (
cidtest "github.com/nspcc-dev/neofs-sdk-go/container/id/test"
neofscrypto "github.com/nspcc-dev/neofs-sdk-go/crypto"
neofsecdsa "github.com/nspcc-dev/neofs-sdk-go/crypto/ecdsa"
oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
oidtest "github.com/nspcc-dev/neofs-sdk-go/object/id/test"
"github.com/nspcc-dev/neofs-sdk-go/session"
sessiontest "github.com/nspcc-dev/neofs-sdk-go/session/test"
@ -84,15 +83,17 @@ func TestObjectProtocolV2(t *testing.T) {
// Context
cnr := cidtest.ID()
obj := oidtest.ID()
var addr oid.Address
addr.SetContainer(cnr)
addr.SetObject(obj)
var addrV2 refs.Address
addr.WriteToV2(&addrV2)
obj1 := oidtest.ID()
obj2 := oidtest.ID()
var cnrV2 refs.ContainerID
cnr.WriteToV2(&cnrV2)
var obj1V2 refs.ObjectID
obj1.WriteToV2(&obj1V2)
var obj2V2 refs.ObjectID
obj2.WriteToV2(&obj2V2)
var cObj v2session.ObjectSessionContext
restoreCtx := func() {
cObj.SetAddress(&addrV2)
cObj.SetTarget(&cnrV2, obj1V2, obj2V2)
body.SetContext(&cObj)
}
restoreCtx()
@ -210,32 +211,29 @@ func TestObjectProtocolV2(t *testing.T) {
body.SetContext(nil)
},
func() {
cObj.SetAddress(new(refs.Address))
cObj.SetTarget(nil)
},
func() {
var brokenCnr refs.ContainerID
brokenCnr.SetValue(append(addrV2.GetContainerID().GetValue(), 1))
var addr refs.Address
addr.SetContainerID(&brokenCnr)
cObj.SetAddress(&addr)
brokenCnr.SetValue(append(cnrV2.GetValue(), 1))
cObj.SetTarget(&brokenCnr)
},
func() {
var brokenObj refs.ObjectID
brokenObj.SetValue(append(addrV2.GetContainerID().GetValue(), 1))
var addr refs.Address
addr.SetObjectID(&brokenObj)
cObj.SetAddress(&addr)
brokenObj.SetValue(append(obj1V2.GetValue(), 1))
cObj.SetTarget(&cnrV2, brokenObj)
},
},
restore: restoreCtx,
assert: func(val session.Object) {
require.True(t, val.AssertContainer(cnr))
require.False(t, val.AssertContainer(cidtest.ID()))
require.True(t, val.AssertObject(obj))
require.True(t, val.AssertObject(obj1))
require.True(t, val.AssertObject(obj2))
require.False(t, val.AssertObject(oidtest.ID()))
},
breakSign: func(m *v2session.Token) {
cnr := m.GetBody().GetContext().(*v2session.ObjectSessionContext).GetAddress().GetContainerID().GetValue()
cnr := m.GetBody().GetContext().(*v2session.ObjectSessionContext).GetContainer().GetValue()
cnr[len(cnr)-1]++
},
},
@ -329,7 +327,8 @@ func TestObject_WriteToV2(t *testing.T) {
assert(func(m v2session.Token) {
cCnr, ok := m.GetBody().GetContext().(*v2session.ObjectSessionContext)
require.True(t, ok)
require.Zero(t, cCnr.GetAddress())
require.Zero(t, cCnr.GetContainer())
require.Zero(t, cCnr.GetObjects())
})
cnr := cidtest.ID()
@ -337,19 +336,22 @@ func TestObject_WriteToV2(t *testing.T) {
var cnrV2 refs.ContainerID
cnr.WriteToV2(&cnrV2)
obj := oidtest.ID()
obj1 := oidtest.ID()
obj2 := oidtest.ID()
var objV2 refs.ObjectID
obj.WriteToV2(&objV2)
var obj1V2 refs.ObjectID
obj1.WriteToV2(&obj1V2)
var obj2V2 refs.ObjectID
obj2.WriteToV2(&obj2V2)
val.BindContainer(cnr)
val.LimitByObject(obj)
val.LimitByObjects(obj1, obj2)
assert(func(m v2session.Token) {
cCnr, ok := m.GetBody().GetContext().(*v2session.ObjectSessionContext)
require.True(t, ok)
require.Equal(t, &cnrV2, cCnr.GetAddress().GetContainerID())
require.Equal(t, &objV2, cCnr.GetAddress().GetObjectID())
require.Equal(t, &cnrV2, cCnr.GetContainer())
require.Equal(t, []refs.ObjectID{obj1V2, obj2V2}, cCnr.GetObjects())
})
}
@ -361,7 +363,8 @@ func TestObject_BindContainer(t *testing.T) {
assertDefaults := func() {
cCnr, ok := m.GetBody().GetContext().(*v2session.ObjectSessionContext)
require.True(t, ok)
require.Zero(t, cCnr.GetAddress())
require.Zero(t, cCnr.GetContainer())
require.Zero(t, cCnr.GetObjects())
}
assertBinary := func(baseAssert func()) {
@ -401,7 +404,7 @@ func TestObject_BindContainer(t *testing.T) {
assertCnr := func() {
cObj, ok := m.GetBody().GetContext().(*v2session.ObjectSessionContext)
require.True(t, ok)
require.Equal(t, &cnrV2, cObj.GetAddress().GetContainerID())
require.Equal(t, &cnrV2, cObj.GetContainer())
}
assertCnr()
@ -421,7 +424,7 @@ func TestObject_AssertContainer(t *testing.T) {
require.True(t, x.AssertContainer(cnr))
}
func TestObject_LimitByObject(t *testing.T) {
func TestObject_LimitByObjects(t *testing.T) {
var val session.Object
var m v2session.Token
filled := sessiontest.Object()
@ -429,7 +432,8 @@ func TestObject_LimitByObject(t *testing.T) {
assertDefaults := func() {
cCnr, ok := m.GetBody().GetContext().(*v2session.ObjectSessionContext)
require.True(t, ok)
require.Zero(t, cCnr.GetAddress())
require.Zero(t, cCnr.GetContainer())
require.Zero(t, cCnr.GetObjects())
}
assertBinary := func(baseAssert func()) {
@ -457,19 +461,22 @@ func TestObject_LimitByObject(t *testing.T) {
// set value
obj := oidtest.ID()
obj1 := oidtest.ID()
obj2 := oidtest.ID()
var objV2 refs.ObjectID
obj.WriteToV2(&objV2)
var obj1V2 refs.ObjectID
obj1.WriteToV2(&obj1V2)
var obj2V2 refs.ObjectID
obj2.WriteToV2(&obj2V2)
val.LimitByObject(obj)
val.LimitByObjects(obj1, obj2)
val.WriteToV2(&m)
assertObj := func() {
cObj, ok := m.GetBody().GetContext().(*v2session.ObjectSessionContext)
require.True(t, ok)
require.Equal(t, &objV2, cObj.GetAddress().GetObjectID())
require.Equal(t, []refs.ObjectID{obj1V2, obj2V2}, cObj.GetObjects())
}
assertObj()
@ -480,16 +487,19 @@ func TestObject_LimitByObject(t *testing.T) {
func TestObject_AssertObject(t *testing.T) {
var x session.Object
obj := oidtest.ID()
obj1 := oidtest.ID()
obj2 := oidtest.ID()
objOther := oidtest.ID()
require.True(t, x.AssertObject(obj))
require.True(t, x.AssertObject(obj1))
require.True(t, x.AssertObject(obj2))
require.True(t, x.AssertObject(objOther))
x.LimitByObject(obj)
x.LimitByObjects(obj1, obj2)
require.True(t, x.AssertObject(obj))
require.False(t, x.AssertObject(obj2))
require.True(t, x.AssertObject(obj1))
require.True(t, x.AssertObject(obj2))
require.False(t, x.AssertObject(objOther))
}
func TestObject_InvalidAt(t *testing.T) {

View file

@ -71,11 +71,9 @@ func Object() *session.Object {
panic(err)
}
addr := oidtest.Address()
tok.ForVerb(session.VerbObjectPut)
tok.BindContainer(addr.Container())
tok.LimitByObject(addr.Object())
tok.BindContainer(cidtest.ID())
tok.LimitByObjects(oidtest.ID(), oidtest.ID())
tok.SetID(uuid.New())
tok.SetAuthKey((*neofsecdsa.PublicKey)(&priv.PublicKey))
tok.SetExp(11)