[#199] owner: Rename to user, refactor and doc

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
This commit is contained in:
Leonard Lyubich 2022-04-11 09:30:22 +03:00 committed by LeL
parent d20999113a
commit 1ed426b8a6
36 changed files with 546 additions and 557 deletions

View file

@ -12,7 +12,7 @@ import (
neofscrypto "github.com/nspcc-dev/neofs-sdk-go/crypto" neofscrypto "github.com/nspcc-dev/neofs-sdk-go/crypto"
neofsecdsa "github.com/nspcc-dev/neofs-sdk-go/crypto/ecdsa" neofsecdsa "github.com/nspcc-dev/neofs-sdk-go/crypto/ecdsa"
"github.com/nspcc-dev/neofs-sdk-go/eacl" "github.com/nspcc-dev/neofs-sdk-go/eacl"
"github.com/nspcc-dev/neofs-sdk-go/owner" "github.com/nspcc-dev/neofs-sdk-go/user"
) )
var ( var (
@ -175,11 +175,11 @@ func (b Token) EACLTable() eacl.Table {
return *eacl.NewTableFromV2(v2.GetBody().GetEACL()) return *eacl.NewTableFromV2(v2.GetBody().GetEACL())
} }
// SetOwnerID sets owner.ID value of the user who can attach bearer token to // SetOwnerID sets user.ID value of the user who can attach bearer token to
// its requests. // its requests.
// //
// See also OwnerID. // See also OwnerID.
func (b *Token) SetOwnerID(id owner.ID) { func (b *Token) SetOwnerID(id user.ID) {
v2 := (*acl.BearerToken)(b) v2 := (*acl.BearerToken)(b)
body := v2.GetBody() body := v2.GetBody()
@ -187,17 +187,28 @@ func (b *Token) SetOwnerID(id owner.ID) {
body = new(acl.BearerTokenBody) body = new(acl.BearerTokenBody)
} }
body.SetOwnerID(id.ToV2()) var idV2 refs.OwnerID
id.WriteToV2(&idV2)
body.SetOwnerID(&idV2)
v2.SetBody(body) v2.SetBody(body)
} }
// OwnerID returns owner.ID value of the user who can attach bearer token to // OwnerID returns user.ID value of the user who can attach bearer token to
// its requests. // its requests.
// //
// See also SetOwnerID. // See also SetOwnerID.
func (b Token) OwnerID() owner.ID { func (b Token) OwnerID() user.ID {
v2 := (acl.BearerToken)(b) v2 := (acl.BearerToken)(b)
return *owner.NewIDFromV2(v2.GetBody().GetOwnerID())
var id user.ID
idV2 := v2.GetBody().GetOwnerID()
if idV2 != nil {
_ = id.ReadFromV2(*idV2)
}
return id
} }
// Sign signs bearer token. This method should be invoked with the private // Sign signs bearer token. This method should be invoked with the private
@ -261,21 +272,23 @@ func (b Token) VerifySignature() error {
return nil return nil
} }
// Issuer returns owner.ID associated with the key that signed bearer token. // Issuer returns user.ID associated with the key that signed bearer token.
// To pass node validation it should be owner of requested container. // To pass node validation it should be owner of requested container.
// //
// If token is not signed, Issuer returns empty owner ID and false `ok` flag. // If token is not signed, Issuer returns empty owner ID and false `ok` flag.
// //
// See also Sign. // See also Sign.
func (b Token) Issuer() (id owner.ID, ok bool) { func (b Token) Issuer() (id user.ID, ok bool) {
v2 := (acl.BearerToken)(b) v2 := (acl.BearerToken)(b)
pub, _ := keys.NewPublicKeyFromBytes(v2.GetSignature().GetKey(), elliptic.P256()) pub, _ := keys.NewPublicKeyFromBytes(v2.GetSignature().GetKey(), elliptic.P256())
if pub == nil {
return id, false ok = pub != nil
if ok {
user.IDFromKey(&id, (ecdsa.PublicKey)(*pub))
} }
return *owner.NewIDFromPublicKey((*ecdsa.PublicKey)(pub)), true return
} }
// sanityCheck if bearer token is ready to be issued. // sanityCheck if bearer token is ready to be issued.

View file

@ -1,14 +1,13 @@
package bearer_test package bearer_test
import ( import (
"crypto/ecdsa"
"testing" "testing"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neofs-sdk-go/bearer" "github.com/nspcc-dev/neofs-sdk-go/bearer"
tokentest "github.com/nspcc-dev/neofs-sdk-go/bearer/test" tokentest "github.com/nspcc-dev/neofs-sdk-go/bearer/test"
"github.com/nspcc-dev/neofs-sdk-go/eacl" "github.com/nspcc-dev/neofs-sdk-go/eacl"
"github.com/nspcc-dev/neofs-sdk-go/owner" "github.com/nspcc-dev/neofs-sdk-go/user"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@ -24,13 +23,14 @@ func TestBearerToken_Issuer(t *testing.T) {
p, err := keys.NewPrivateKey() p, err := keys.NewPrivateKey()
require.NoError(t, err) require.NoError(t, err)
ownerID := owner.NewIDFromPublicKey((*ecdsa.PublicKey)(p.PublicKey())) var id user.ID
user.IDFromKey(&id, p.PrivateKey.PublicKey)
bearerToken.SetEACLTable(*eacl.NewTable()) bearerToken.SetEACLTable(*eacl.NewTable())
require.NoError(t, bearerToken.Sign(p.PrivateKey)) require.NoError(t, bearerToken.Sign(p.PrivateKey))
issuer, ok := bearerToken.Issuer() issuer, ok := bearerToken.Issuer()
require.True(t, ok) require.True(t, ok)
require.True(t, ownerID.Equal(&issuer)) require.True(t, id.Equals(issuer))
}) })
} }

View file

@ -3,7 +3,7 @@ package bearertest
import ( import (
"github.com/nspcc-dev/neofs-sdk-go/bearer" "github.com/nspcc-dev/neofs-sdk-go/bearer"
eacltest "github.com/nspcc-dev/neofs-sdk-go/eacl/test" eacltest "github.com/nspcc-dev/neofs-sdk-go/eacl/test"
ownertest "github.com/nspcc-dev/neofs-sdk-go/owner/test" usertest "github.com/nspcc-dev/neofs-sdk-go/user/test"
) )
// Token returns random bearer.Token. // Token returns random bearer.Token.
@ -13,7 +13,7 @@ func Token() (t bearer.Token) {
t.SetExpiration(3) t.SetExpiration(3)
t.SetNotBefore(2) t.SetNotBefore(2)
t.SetIssuedAt(1) t.SetIssuedAt(1)
t.SetOwnerID(*ownertest.ID()) t.SetOwnerID(*usertest.ID())
t.SetEACLTable(*eacltest.Table()) t.SetEACLTable(*eacltest.Table())
return t return t

View file

@ -4,25 +4,26 @@ import (
"context" "context"
v2accounting "github.com/nspcc-dev/neofs-api-go/v2/accounting" v2accounting "github.com/nspcc-dev/neofs-api-go/v2/accounting"
"github.com/nspcc-dev/neofs-api-go/v2/refs"
rpcapi "github.com/nspcc-dev/neofs-api-go/v2/rpc" rpcapi "github.com/nspcc-dev/neofs-api-go/v2/rpc"
"github.com/nspcc-dev/neofs-api-go/v2/rpc/client" "github.com/nspcc-dev/neofs-api-go/v2/rpc/client"
"github.com/nspcc-dev/neofs-sdk-go/accounting" "github.com/nspcc-dev/neofs-sdk-go/accounting"
"github.com/nspcc-dev/neofs-sdk-go/owner" "github.com/nspcc-dev/neofs-sdk-go/user"
) )
// PrmBalanceGet groups parameters of BalanceGet operation. // PrmBalanceGet groups parameters of BalanceGet operation.
type PrmBalanceGet struct { type PrmBalanceGet struct {
prmCommonMeta prmCommonMeta
ownerSet bool accountSet bool
ownerID owner.ID account user.ID
} }
// SetAccount sets identifier of the NeoFS account for which the balance is requested. // SetAccount sets identifier of the NeoFS account for which the balance is requested.
// Required parameter. Must be a valid ID according to NeoFS API protocol. // Required parameter.
func (x *PrmBalanceGet) SetAccount(id owner.ID) { func (x *PrmBalanceGet) SetAccount(id user.ID) {
x.ownerID = id x.account = id
x.ownerSet = true x.accountSet = true
} }
// ResBalanceGet groups resulting values of BalanceGet operation. // ResBalanceGet groups resulting values of BalanceGet operation.
@ -60,16 +61,16 @@ func (c *Client) BalanceGet(ctx context.Context, prm PrmBalanceGet) (*ResBalance
switch { switch {
case ctx == nil: case ctx == nil:
panic(panicMsgMissingContext) panic(panicMsgMissingContext)
case !prm.ownerSet: case !prm.accountSet:
panic("account not set") panic("account not set")
case !prm.ownerID.Valid():
panic("invalid account ID")
} }
// form request body // form request body
var body v2accounting.BalanceRequestBody var accountV2 refs.OwnerID
prm.account.WriteToV2(&accountV2)
body.SetOwnerID(prm.ownerID.ToV2()) var body v2accounting.BalanceRequestBody
body.SetOwnerID(&accountV2)
// form request // form request
var req v2accounting.BalanceRequest var req v2accounting.BalanceRequest

View file

@ -14,8 +14,8 @@ import (
neofscrypto "github.com/nspcc-dev/neofs-sdk-go/crypto" neofscrypto "github.com/nspcc-dev/neofs-sdk-go/crypto"
neofsecdsa "github.com/nspcc-dev/neofs-sdk-go/crypto/ecdsa" neofsecdsa "github.com/nspcc-dev/neofs-sdk-go/crypto/ecdsa"
"github.com/nspcc-dev/neofs-sdk-go/eacl" "github.com/nspcc-dev/neofs-sdk-go/eacl"
"github.com/nspcc-dev/neofs-sdk-go/owner"
"github.com/nspcc-dev/neofs-sdk-go/session" "github.com/nspcc-dev/neofs-sdk-go/session"
"github.com/nspcc-dev/neofs-sdk-go/user"
) )
// PrmContainerPut groups parameters of ContainerPut operation. // PrmContainerPut groups parameters of ContainerPut operation.
@ -269,12 +269,12 @@ type PrmContainerList struct {
prmCommonMeta prmCommonMeta
ownerSet bool ownerSet bool
ownerID owner.ID ownerID user.ID
} }
// SetAccount sets identifier of the NeoFS account to list the containers. // SetAccount sets identifier of the NeoFS account to list the containers.
// Required parameter. Must be a valid ID according to NeoFS API protocol. // Required parameter.
func (x *PrmContainerList) SetAccount(id owner.ID) { func (x *PrmContainerList) SetAccount(id user.ID) {
x.ownerID = id x.ownerID = id
x.ownerSet = true x.ownerSet = true
} }
@ -317,13 +317,14 @@ func (c *Client) ContainerList(ctx context.Context, prm PrmContainerList) (*ResC
panic(panicMsgMissingContext) panic(panicMsgMissingContext)
case !prm.ownerSet: case !prm.ownerSet:
panic("account not set") panic("account not set")
case !prm.ownerID.Valid():
panic("invalid account")
} }
// form request body // form request body
var ownerV2 refs.OwnerID
prm.ownerID.WriteToV2(&ownerV2)
reqBody := new(v2container.ListRequestBody) reqBody := new(v2container.ListRequestBody)
reqBody.SetOwnerID(prm.ownerID.ToV2()) reqBody.SetOwnerID(&ownerV2)
// form request // form request
var req v2container.ListRequest var req v2container.ListRequest

View file

@ -3,10 +3,11 @@ package client
import ( import (
"context" "context"
"github.com/nspcc-dev/neofs-api-go/v2/refs"
rpcapi "github.com/nspcc-dev/neofs-api-go/v2/rpc" rpcapi "github.com/nspcc-dev/neofs-api-go/v2/rpc"
"github.com/nspcc-dev/neofs-api-go/v2/rpc/client" "github.com/nspcc-dev/neofs-api-go/v2/rpc/client"
v2session "github.com/nspcc-dev/neofs-api-go/v2/session" v2session "github.com/nspcc-dev/neofs-api-go/v2/session"
"github.com/nspcc-dev/neofs-sdk-go/owner" "github.com/nspcc-dev/neofs-sdk-go/user"
) )
// PrmSessionCreate groups parameters of SessionCreate operation. // PrmSessionCreate groups parameters of SessionCreate operation.
@ -71,11 +72,15 @@ func (c *Client) SessionCreate(ctx context.Context, prm PrmSessionCreate) (*ResS
panic(panicMsgMissingContext) panic(panicMsgMissingContext)
} }
ownerID := owner.NewIDFromPublicKey(&c.prm.key.PublicKey) var ownerID user.ID
user.IDFromKey(&ownerID, c.prm.key.PublicKey)
var ownerIDV2 refs.OwnerID
ownerID.WriteToV2(&ownerIDV2)
// form request body // form request body
reqBody := new(v2session.CreateRequestBody) reqBody := new(v2session.CreateRequestBody)
reqBody.SetOwnerID(ownerID.ToV2()) reqBody.SetOwnerID(&ownerIDV2)
reqBody.SetExpiration(prm.exp) reqBody.SetExpiration(prm.exp)
// for request // for request

View file

@ -10,8 +10,8 @@ import (
cid "github.com/nspcc-dev/neofs-sdk-go/container/id" cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
neofscrypto "github.com/nspcc-dev/neofs-sdk-go/crypto" neofscrypto "github.com/nspcc-dev/neofs-sdk-go/crypto"
"github.com/nspcc-dev/neofs-sdk-go/netmap" "github.com/nspcc-dev/neofs-sdk-go/netmap"
"github.com/nspcc-dev/neofs-sdk-go/owner"
"github.com/nspcc-dev/neofs-sdk-go/session" "github.com/nspcc-dev/neofs-sdk-go/session"
"github.com/nspcc-dev/neofs-sdk-go/user"
"github.com/nspcc-dev/neofs-sdk-go/version" "github.com/nspcc-dev/neofs-sdk-go/version"
) )
@ -113,12 +113,24 @@ func (c *Container) SetVersion(v *version.Version) {
c.v2.SetVersion(&verV2) c.v2.SetVersion(&verV2)
} }
func (c *Container) OwnerID() *owner.ID { func (c *Container) OwnerID() *user.ID {
return owner.NewIDFromV2(c.v2.GetOwnerID()) m := c.v2.GetOwnerID()
if m == nil {
return nil
}
var id user.ID
_ = id.ReadFromV2(*m)
return &id
} }
func (c *Container) SetOwnerID(v *owner.ID) { func (c *Container) SetOwnerID(v *user.ID) {
c.v2.SetOwnerID(v.ToV2()) var m refs.OwnerID
v.WriteToV2(&m)
c.v2.SetOwnerID(&m)
} }
// Returns container nonce in UUID format. // Returns container nonce in UUID format.

View file

@ -9,8 +9,8 @@ import (
"github.com/nspcc-dev/neofs-sdk-go/container" "github.com/nspcc-dev/neofs-sdk-go/container"
containertest "github.com/nspcc-dev/neofs-sdk-go/container/test" containertest "github.com/nspcc-dev/neofs-sdk-go/container/test"
netmaptest "github.com/nspcc-dev/neofs-sdk-go/netmap/test" netmaptest "github.com/nspcc-dev/neofs-sdk-go/netmap/test"
ownertest "github.com/nspcc-dev/neofs-sdk-go/owner/test"
sessiontest "github.com/nspcc-dev/neofs-sdk-go/session/test" sessiontest "github.com/nspcc-dev/neofs-sdk-go/session/test"
usertest "github.com/nspcc-dev/neofs-sdk-go/user/test"
"github.com/nspcc-dev/neofs-sdk-go/version" "github.com/nspcc-dev/neofs-sdk-go/version"
versiontest "github.com/nspcc-dev/neofs-sdk-go/version/test" versiontest "github.com/nspcc-dev/neofs-sdk-go/version/test"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -21,7 +21,7 @@ func TestNewContainer(t *testing.T) {
nonce := uuid.New() nonce := uuid.New()
ownerID := ownertest.ID() ownerID := usertest.ID()
policy := netmaptest.PlacementPolicy() policy := netmaptest.PlacementPolicy()
c.SetBasicACL(acl.PublicBasicRule) c.SetBasicACL(acl.PublicBasicRule)

View file

@ -6,7 +6,7 @@ import (
"github.com/google/uuid" "github.com/google/uuid"
"github.com/nspcc-dev/neofs-sdk-go/acl" "github.com/nspcc-dev/neofs-sdk-go/acl"
"github.com/nspcc-dev/neofs-sdk-go/netmap" "github.com/nspcc-dev/neofs-sdk-go/netmap"
"github.com/nspcc-dev/neofs-sdk-go/owner" "github.com/nspcc-dev/neofs-sdk-go/user"
) )
type ( type (
@ -16,7 +16,7 @@ type (
acl acl.BasicACL acl acl.BasicACL
policy *netmap.PlacementPolicy policy *netmap.PlacementPolicy
attributes Attributes attributes Attributes
owner *owner.ID owner *user.ID
nonce uuid.UUID nonce uuid.UUID
} }
) )
@ -57,7 +57,7 @@ func WithNonce(nonce uuid.UUID) Option {
} }
} }
func WithOwnerID(id *owner.ID) Option { func WithOwnerID(id *user.ID) Option {
return func(option *containerOptions) { return func(option *containerOptions) {
option.owner = id option.owner = id
} }
@ -66,10 +66,10 @@ func WithOwnerID(id *owner.ID) Option {
func WithOwnerPublicKey(pub *ecdsa.PublicKey) Option { func WithOwnerPublicKey(pub *ecdsa.PublicKey) Option {
return func(option *containerOptions) { return func(option *containerOptions) {
if option.owner == nil { if option.owner == nil {
option.owner = new(owner.ID) option.owner = new(user.ID)
} }
option.owner.SetPublicKey(pub) user.IDFromKey(option.owner, *pub)
} }
} }

View file

@ -4,7 +4,7 @@ import (
"github.com/nspcc-dev/neofs-sdk-go/container" "github.com/nspcc-dev/neofs-sdk-go/container"
cidtest "github.com/nspcc-dev/neofs-sdk-go/container/id/test" cidtest "github.com/nspcc-dev/neofs-sdk-go/container/id/test"
netmaptest "github.com/nspcc-dev/neofs-sdk-go/netmap/test" netmaptest "github.com/nspcc-dev/neofs-sdk-go/netmap/test"
ownertest "github.com/nspcc-dev/neofs-sdk-go/owner/test" usertest "github.com/nspcc-dev/neofs-sdk-go/user/test"
versiontest "github.com/nspcc-dev/neofs-sdk-go/version/test" versiontest "github.com/nspcc-dev/neofs-sdk-go/version/test"
) )
@ -30,7 +30,7 @@ func Container() *container.Container {
x.SetVersion(&ver) x.SetVersion(&ver)
x.SetAttributes(Attributes()) x.SetAttributes(Attributes())
x.SetOwnerID(ownertest.ID()) x.SetOwnerID(usertest.ID())
x.SetBasicACL(123) x.SetBasicACL(123)
x.SetPlacementPolicy(netmaptest.PlacementPolicy()) x.SetPlacementPolicy(netmaptest.PlacementPolicy())

View file

@ -9,7 +9,7 @@ import (
cid "github.com/nspcc-dev/neofs-sdk-go/container/id" cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
"github.com/nspcc-dev/neofs-sdk-go/object" "github.com/nspcc-dev/neofs-sdk-go/object"
oid "github.com/nspcc-dev/neofs-sdk-go/object/id" oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
"github.com/nspcc-dev/neofs-sdk-go/owner" "github.com/nspcc-dev/neofs-sdk-go/user"
"github.com/nspcc-dev/neofs-sdk-go/version" "github.com/nspcc-dev/neofs-sdk-go/version"
) )
@ -122,7 +122,7 @@ func (r *Record) AddObjectContainerIDFilter(m Match, id cid.ID) {
} }
// AddObjectOwnerIDFilter adds filter by object owner ID. // AddObjectOwnerIDFilter adds filter by object owner ID.
func (r *Record) AddObjectOwnerIDFilter(m Match, id *owner.ID) { func (r *Record) AddObjectOwnerIDFilter(m Match, id *user.ID) {
r.addObjectReservedFilter(m, fKeyObjOwnerID, id) r.addObjectReservedFilter(m, fKeyObjOwnerID, id)
} }

View file

@ -11,7 +11,7 @@ import (
cidtest "github.com/nspcc-dev/neofs-sdk-go/container/id/test" cidtest "github.com/nspcc-dev/neofs-sdk-go/container/id/test"
"github.com/nspcc-dev/neofs-sdk-go/object" "github.com/nspcc-dev/neofs-sdk-go/object"
oidtest "github.com/nspcc-dev/neofs-sdk-go/object/id/test" oidtest "github.com/nspcc-dev/neofs-sdk-go/object/id/test"
ownertest "github.com/nspcc-dev/neofs-sdk-go/owner/test" usertest "github.com/nspcc-dev/neofs-sdk-go/user/test"
versiontest "github.com/nspcc-dev/neofs-sdk-go/version/test" versiontest "github.com/nspcc-dev/neofs-sdk-go/version/test"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@ -154,7 +154,7 @@ func TestReservedRecords(t *testing.T) {
v = versiontest.Version() v = versiontest.Version()
oid = oidtest.ID() oid = oidtest.ID()
cid = cidtest.ID() cid = cidtest.ID()
ownerid = ownertest.ID() ownerid = usertest.ID()
h = checksumtest.Checksum() h = checksumtest.Checksum()
typ = new(object.Type) typ = new(object.Type)
) )

View file

@ -3,7 +3,7 @@ package eacltest
import ( import (
cidtest "github.com/nspcc-dev/neofs-sdk-go/container/id/test" cidtest "github.com/nspcc-dev/neofs-sdk-go/container/id/test"
"github.com/nspcc-dev/neofs-sdk-go/eacl" "github.com/nspcc-dev/neofs-sdk-go/eacl"
ownertest "github.com/nspcc-dev/neofs-sdk-go/owner/test" usertest "github.com/nspcc-dev/neofs-sdk-go/user/test"
versiontest "github.com/nspcc-dev/neofs-sdk-go/version/test" versiontest "github.com/nspcc-dev/neofs-sdk-go/version/test"
) )
@ -28,7 +28,7 @@ func Record() *eacl.Record {
x.SetOperation(eacl.OperationRangeHash) x.SetOperation(eacl.OperationRangeHash)
x.SetTargets(*Target(), *Target()) x.SetTargets(*Target(), *Target())
x.AddObjectContainerIDFilter(eacl.MatchStringEqual, cidtest.ID()) x.AddObjectContainerIDFilter(eacl.MatchStringEqual, cidtest.ID())
x.AddObjectOwnerIDFilter(eacl.MatchStringNotEqual, ownertest.ID()) x.AddObjectOwnerIDFilter(eacl.MatchStringNotEqual, usertest.ID())
return x return x
} }

View file

@ -10,8 +10,8 @@ import (
cid "github.com/nspcc-dev/neofs-sdk-go/container/id" cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
neofscrypto "github.com/nspcc-dev/neofs-sdk-go/crypto" neofscrypto "github.com/nspcc-dev/neofs-sdk-go/crypto"
oid "github.com/nspcc-dev/neofs-sdk-go/object/id" oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
"github.com/nspcc-dev/neofs-sdk-go/owner"
"github.com/nspcc-dev/neofs-sdk-go/session" "github.com/nspcc-dev/neofs-sdk-go/session"
"github.com/nspcc-dev/neofs-sdk-go/user"
"github.com/nspcc-dev/neofs-sdk-go/version" "github.com/nspcc-dev/neofs-sdk-go/version"
) )
@ -30,8 +30,8 @@ type RequiredFields struct {
// Identifier of the NeoFS container associated with the object. // Identifier of the NeoFS container associated with the object.
Container cid.ID Container cid.ID
// Object owner ID in the NeoFS system. // Object owner's user ID in the NeoFS system.
Owner owner.ID Owner user.ID
} }
// InitCreation initializes the object instance with minimum set of required fields. // InitCreation initializes the object instance with minimum set of required fields.
@ -201,18 +201,24 @@ func (o *Object) SetContainerID(v cid.ID) {
} }
// OwnerID returns identifier of the object owner. // OwnerID returns identifier of the object owner.
func (o *Object) OwnerID() *owner.ID { func (o *Object) OwnerID() *user.ID {
return owner.NewIDFromV2( var id user.ID
(*object.Object)(o).
GetHeader(). m := (*object.Object)(o).GetHeader().GetOwnerID()
GetOwnerID(), if m != nil {
) _ = id.ReadFromV2(*m)
}
return &id
} }
// SetOwnerID sets identifier of the object owner. // SetOwnerID sets identifier of the object owner.
func (o *Object) SetOwnerID(v *owner.ID) { func (o *Object) SetOwnerID(v *user.ID) {
o.setHeaderField(func(h *object.Header) { o.setHeaderField(func(h *object.Header) {
h.SetOwnerID(v.ToV2()) var m refs.OwnerID
v.WriteToV2(&m)
h.SetOwnerID(&m)
}) })
} }

View file

@ -5,14 +5,14 @@ import (
cidtest "github.com/nspcc-dev/neofs-sdk-go/container/id/test" cidtest "github.com/nspcc-dev/neofs-sdk-go/container/id/test"
"github.com/nspcc-dev/neofs-sdk-go/object" "github.com/nspcc-dev/neofs-sdk-go/object"
ownertest "github.com/nspcc-dev/neofs-sdk-go/owner/test" usertest "github.com/nspcc-dev/neofs-sdk-go/user/test"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
func TestInitCreation(t *testing.T) { func TestInitCreation(t *testing.T) {
var o object.Object var o object.Object
cnr := cidtest.ID() cnr := cidtest.ID()
own := *ownertest.ID() own := *usertest.ID()
object.InitCreation(&o, object.RequiredFields{ object.InitCreation(&o, object.RequiredFields{
Container: cnr, Container: cnr,

View file

@ -9,8 +9,8 @@ import (
"github.com/nspcc-dev/neofs-sdk-go/checksum" "github.com/nspcc-dev/neofs-sdk-go/checksum"
cidtest "github.com/nspcc-dev/neofs-sdk-go/container/id/test" cidtest "github.com/nspcc-dev/neofs-sdk-go/container/id/test"
oid "github.com/nspcc-dev/neofs-sdk-go/object/id" oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
ownertest "github.com/nspcc-dev/neofs-sdk-go/owner/test"
sessiontest "github.com/nspcc-dev/neofs-sdk-go/session/test" sessiontest "github.com/nspcc-dev/neofs-sdk-go/session/test"
usertest "github.com/nspcc-dev/neofs-sdk-go/user/test"
"github.com/nspcc-dev/neofs-sdk-go/version" "github.com/nspcc-dev/neofs-sdk-go/version"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@ -95,7 +95,7 @@ func TestObject_SetContainerID(t *testing.T) {
func TestObject_SetOwnerID(t *testing.T) { func TestObject_SetOwnerID(t *testing.T) {
obj := New() obj := New()
ownerID := ownertest.ID() ownerID := usertest.ID()
obj.SetOwnerID(ownerID) obj.SetOwnerID(ownerID)

View file

@ -8,7 +8,7 @@ import (
v2object "github.com/nspcc-dev/neofs-api-go/v2/object" v2object "github.com/nspcc-dev/neofs-api-go/v2/object"
cid "github.com/nspcc-dev/neofs-sdk-go/container/id" cid "github.com/nspcc-dev/neofs-sdk-go/container/id"
oid "github.com/nspcc-dev/neofs-sdk-go/object/id" oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
"github.com/nspcc-dev/neofs-sdk-go/owner" "github.com/nspcc-dev/neofs-sdk-go/user"
"github.com/nspcc-dev/neofs-sdk-go/version" "github.com/nspcc-dev/neofs-sdk-go/version"
) )
@ -224,7 +224,7 @@ func (f *SearchFilters) AddObjectContainerIDFilter(m SearchMatchType, id cid.ID)
f.addReservedFilter(m, fKeyContainerID, id) f.addReservedFilter(m, fKeyContainerID, id)
} }
func (f *SearchFilters) AddObjectOwnerIDFilter(m SearchMatchType, id *owner.ID) { func (f *SearchFilters) AddObjectOwnerIDFilter(m SearchMatchType, id *user.ID) {
f.addReservedFilter(m, fKeyOwnerID, id) f.addReservedFilter(m, fKeyOwnerID, id)
} }

View file

@ -7,8 +7,8 @@ import (
"github.com/nspcc-dev/neofs-sdk-go/object" "github.com/nspcc-dev/neofs-sdk-go/object"
oid "github.com/nspcc-dev/neofs-sdk-go/object/id" oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
oidtest "github.com/nspcc-dev/neofs-sdk-go/object/id/test" oidtest "github.com/nspcc-dev/neofs-sdk-go/object/id/test"
ownertest "github.com/nspcc-dev/neofs-sdk-go/owner/test"
sessiontest "github.com/nspcc-dev/neofs-sdk-go/session/test" sessiontest "github.com/nspcc-dev/neofs-sdk-go/session/test"
usertest "github.com/nspcc-dev/neofs-sdk-go/user/test"
"github.com/nspcc-dev/neofs-sdk-go/version" "github.com/nspcc-dev/neofs-sdk-go/version"
) )
@ -48,7 +48,7 @@ func generate(withParent bool) *object.Object {
x.SetID(oidtest.ID()) x.SetID(oidtest.ID())
x.SetSessionToken(sessiontest.Token()) x.SetSessionToken(sessiontest.Token())
x.SetPayload([]byte{1, 2, 3}) x.SetPayload([]byte{1, 2, 3})
x.SetOwnerID(ownertest.ID()) x.SetOwnerID(usertest.ID())
x.SetContainerID(cidtest.ID()) x.SetContainerID(cidtest.ID())
x.SetType(object.TypeTombstone) x.SetType(object.TypeTombstone)
x.SetVersion(&ver) x.SetVersion(&ver)

View file

@ -1,46 +0,0 @@
package owner
import (
"crypto/ecdsa"
"crypto/elliptic"
"encoding/hex"
"testing"
"github.com/mr-tron/base58"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/stretchr/testify/require"
)
func TestNEO3WalletFromPublicKey(t *testing.T) {
rawPub, _ := hex.DecodeString("0369b7b6c49fb937f3de52af189b91069767679c2739798d85f2ed69c079940680")
x, y := elliptic.UnmarshalCompressed(elliptic.P256(), rawPub)
require.True(t, x != nil && y != nil)
expected := "35ee628f21922d7308f1bd71f03a0d8ba89c4e7372fca1442c"
actual := PublicKeyToIDBytes(&ecdsa.PublicKey{Curve: elliptic.P256(), X: x, Y: y})
require.Equal(t, expected, hex.EncodeToString(actual))
}
func TestPublicKeyToBytes(t *testing.T) {
p, err := keys.NewPrivateKey()
require.NoError(t, err)
expected, err := base58.Decode(p.PublicKey().Address())
require.NoError(t, err)
actual := PublicKeyToIDBytes((*ecdsa.PublicKey)(p.PublicKey()))
require.Equal(t, expected, actual)
require.Equal(t, NEO3WalletSize, len(actual))
}
func TestScriptHashToIDBytes(t *testing.T) {
p, err := keys.NewPrivateKey()
require.NoError(t, err)
expected, err := base58.Decode(p.PublicKey().Address())
require.NoError(t, err)
actual := ScriptHashToIDBytes(p.GetScriptHash())
require.Equal(t, expected, actual)
require.Equal(t, NEO3WalletSize, len(actual))
}

View file

@ -1,163 +0,0 @@
package owner
import (
"bytes"
"crypto/ecdsa"
"errors"
"fmt"
"github.com/mr-tron/base58"
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/wallet"
"github.com/nspcc-dev/neofs-api-go/v2/refs"
)
// ID represents v2-compatible owner identifier.
type ID refs.OwnerID
var errInvalidIDString = errors.New("incorrect format of the string owner ID")
// ErrEmptyPublicKey when public key passed to Verify method is nil.
var ErrEmptyPublicKey = errors.New("empty public key")
// NEO3WalletSize contains size of neo3 wallet.
const NEO3WalletSize = 25
// NewIDFromV2 wraps v2 OwnerID message to ID.
//
// Nil refs.OwnerID converts to nil.
func NewIDFromV2(idV2 *refs.OwnerID) *ID {
return (*ID)(idV2)
}
// NewID creates and initializes blank ID.
//
// Works similar as NewIDFromV2(new(OwnerID)).
//
// Defaults:
// - value: nil.
func NewID() *ID {
return NewIDFromV2(new(refs.OwnerID))
}
// SetPublicKey sets owner identifier value to the provided NEO3 public key.
func (id *ID) SetPublicKey(pub *ecdsa.PublicKey) {
(*refs.OwnerID)(id).SetValue(PublicKeyToIDBytes(pub))
}
// SetScriptHash sets owner identifier value to the provided NEO3 script hash.
func (id *ID) SetScriptHash(u util.Uint160) {
(*refs.OwnerID)(id).SetValue(ScriptHashToIDBytes(u))
}
// ToV2 returns the v2 owner ID message.
//
// Nil ID converts to nil.
func (id *ID) ToV2() *refs.OwnerID {
return (*refs.OwnerID)(id)
}
// String implements fmt.Stringer.
func (id *ID) String() string {
return base58.Encode((*refs.OwnerID)(id).GetValue())
}
// Equal defines a comparison relation on ID's.
//
// ID's are equal if they have the same binary representation.
func (id *ID) Equal(id2 *ID) bool {
return bytes.Equal(
(*refs.ObjectID)(id).GetValue(),
(*refs.ObjectID)(id2).GetValue(),
)
}
// NewIDFromPublicKey creates new owner identity from ECDSA public key.
func NewIDFromPublicKey(pub *ecdsa.PublicKey) *ID {
id := NewID()
id.SetPublicKey(pub)
return id
}
// NewIDFromN3Account creates new owner identity from N3 wallet account.
func NewIDFromN3Account(acc *wallet.Account) *ID {
return NewIDFromPublicKey(
(*ecdsa.PublicKey)(acc.PrivateKey().PublicKey()))
}
// Parse converts base58 string representation into ID.
func (id *ID) Parse(s string) error {
data, err := base58.Decode(s)
if err != nil {
return fmt.Errorf("could not parse owner.ID from string: %w", err)
} else if !valid(data) {
return errInvalidIDString
}
(*refs.OwnerID)(id).SetValue(data)
return nil
}
// Valid returns true if id is a valid owner id.
// The rules for v2 are the following:
// 1. Must be 25 bytes in length.
// 2. Must have N3 address prefix-byte.
// 3. Last 4 bytes must contain the address checksum.
func (id *ID) Valid() bool {
rawID := id.ToV2().GetValue()
return valid(rawID)
}
func valid(rawID []byte) bool {
if len(rawID) != NEO3WalletSize {
return false
}
if rawID[0] != address.NEO3Prefix {
return false
}
const boundIndex = NEO3WalletSize - 4
return bytes.Equal(rawID[boundIndex:], hash.Checksum(rawID[:boundIndex]))
}
// Marshal marshals ID into a protobuf binary form.
func (id *ID) Marshal() ([]byte, error) {
return (*refs.OwnerID)(id).StableMarshal(nil)
}
// Unmarshal unmarshals protobuf binary representation of ID.
func (id *ID) Unmarshal(data []byte) error {
return (*refs.OwnerID)(id).Unmarshal(data)
}
// MarshalJSON encodes ID to protobuf JSON format.
func (id *ID) MarshalJSON() ([]byte, error) {
return (*refs.OwnerID)(id).MarshalJSON()
}
// UnmarshalJSON decodes ID from protobuf JSON format.
func (id *ID) UnmarshalJSON(data []byte) error {
return (*refs.OwnerID)(id).UnmarshalJSON(data)
}
// PublicKeyToIDBytes converts public key to a byte slice of NEO3WalletSize length.
// It is similar to decoding a NEO3 address but is inlined to skip base58 encoding-decoding step
// make it clear that no errors can occur.
func PublicKeyToIDBytes(pub *ecdsa.PublicKey) []byte {
sh := (*keys.PublicKey)(pub).GetScriptHash()
return ScriptHashToIDBytes(sh)
}
// ScriptHashToIDBytes converts NEO3 script hash to a byte slice of NEO3WalletSize length.
func ScriptHashToIDBytes(sh util.Uint160) []byte {
b := make([]byte, NEO3WalletSize)
b[0] = address.Prefix
copy(b[1:], sh.BytesBE())
copy(b[21:], hash.Checksum(b[:21]))
return b
}

View file

@ -1,174 +0,0 @@
package owner_test
import (
"crypto/ecdsa"
"testing"
"github.com/mr-tron/base58"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/util/slice"
"github.com/nspcc-dev/neo-go/pkg/wallet"
"github.com/nspcc-dev/neofs-api-go/v2/refs"
. "github.com/nspcc-dev/neofs-sdk-go/owner"
ownertest "github.com/nspcc-dev/neofs-sdk-go/owner/test"
"github.com/stretchr/testify/require"
)
func TestIDV2(t *testing.T) {
id := ownertest.ID()
idV2 := id.ToV2()
require.Equal(t, id, NewIDFromV2(idV2))
}
func TestID_Valid(t *testing.T) {
id := ownertest.ID()
require.True(t, id.Valid())
val := id.ToV2().GetValue()
t.Run("invalid prefix", func(t *testing.T) {
val := slice.Copy(val)
val[0] ^= 0xFF
id := ownertest.IDFromBytes(val)
require.False(t, id.Valid())
})
t.Run("invalid size", func(t *testing.T) {
val := val[:NEO3WalletSize-1]
id := ownertest.IDFromBytes(val)
require.False(t, id.Valid())
})
t.Run("invalid checksum", func(t *testing.T) {
val := slice.Copy(val)
val[NEO3WalletSize-1] ^= 0xFF
id := ownertest.IDFromBytes(val)
require.False(t, id.Valid())
})
}
func TestNewIDFromN3Account(t *testing.T) {
acc, err := wallet.NewAccount()
require.NoError(t, err)
id := NewIDFromN3Account(acc)
require.Equal(t, id.String(), acc.Address)
}
func TestNewIDFromPublicKey(t *testing.T) {
p, err := keys.NewPrivateKey()
require.NoError(t, err)
id := NewIDFromPublicKey((*ecdsa.PublicKey)(p.PublicKey()))
require.Equal(t, id.String(), p.Address())
}
func TestID_Parse(t *testing.T) {
t.Run("should parse successful", func(t *testing.T) {
acc, err := wallet.NewAccount()
require.NoError(t, err)
eid := NewIDFromN3Account(acc)
aid := NewID()
require.NoError(t, aid.Parse(eid.String()))
require.Equal(t, eid, aid)
})
t.Run("should failure on parse", func(t *testing.T) {
cs := []byte{1, 2, 3, 4, 5, 6}
str := base58.Encode(cs)
cid := NewID()
require.Error(t, cid.Parse(str))
})
}
func TestIDEncoding(t *testing.T) {
id := ownertest.ID()
t.Run("binary", func(t *testing.T) {
data, err := id.Marshal()
require.NoError(t, err)
id2 := NewID()
require.NoError(t, id2.Unmarshal(data))
require.Equal(t, id, id2)
})
t.Run("json", func(t *testing.T) {
data, err := id.MarshalJSON()
require.NoError(t, err)
a2 := NewID()
require.NoError(t, a2.UnmarshalJSON(data))
require.Equal(t, id, a2)
})
}
func TestID_Equal(t *testing.T) {
var (
data1 = []byte{1, 2, 3}
data2 = data1
data3 = append(data1, 255)
)
id1 := ownertest.IDFromBytes(data1)
require.True(t, id1.Equal(
ownertest.IDFromBytes(data2),
))
require.False(t, id1.Equal(
ownertest.IDFromBytes(data3),
))
}
func TestNewIDFromV2(t *testing.T) {
t.Run("from nil", func(t *testing.T) {
var x *refs.OwnerID
require.Nil(t, NewIDFromV2(x))
})
}
func TestID_ToV2(t *testing.T) {
t.Run("nil", func(t *testing.T) {
var x *ID
require.Nil(t, x.ToV2())
})
}
func TestID_String(t *testing.T) {
t.Run("nil", func(t *testing.T) {
id := NewID()
require.Empty(t, id.String())
})
}
func TestNewID(t *testing.T) {
t.Run("default values", func(t *testing.T) {
id := NewID()
// convert to v2 message
idV2 := id.ToV2()
require.Nil(t, idV2.GetValue())
})
}
func TestID_SetScriptHash(t *testing.T) {
p, err := keys.NewPrivateKey()
require.NoError(t, err)
id := NewID()
id.SetScriptHash(p.GetScriptHash())
require.Equal(t, p.Address(), id.String())
}

View file

@ -1,34 +0,0 @@
package ownertest
import (
"math/rand"
"github.com/mr-tron/base58"
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neofs-api-go/v2/refs"
"github.com/nspcc-dev/neofs-sdk-go/owner"
)
// ID returns owner.ID calculated
// from a random owner.NEO3Wallet.
func ID() *owner.ID {
u := util.Uint160{}
rand.Read(u[:])
addr := address.Uint160ToString(u)
data, err := base58.Decode(addr)
if err != nil {
panic(err)
}
return IDFromBytes(data)
}
// IDFromBytes returns owner.ID generated
// from a passed byte slice.
func IDFromBytes(val []byte) *owner.ID {
idV2 := new(refs.OwnerID)
idV2.SetValue(val)
return owner.NewIDFromV2(idV2)
}

View file

@ -26,8 +26,8 @@ import (
"github.com/nspcc-dev/neofs-sdk-go/object" "github.com/nspcc-dev/neofs-sdk-go/object"
"github.com/nspcc-dev/neofs-sdk-go/object/address" "github.com/nspcc-dev/neofs-sdk-go/object/address"
oid "github.com/nspcc-dev/neofs-sdk-go/object/id" oid "github.com/nspcc-dev/neofs-sdk-go/object/id"
"github.com/nspcc-dev/neofs-sdk-go/owner"
"github.com/nspcc-dev/neofs-sdk-go/session" "github.com/nspcc-dev/neofs-sdk-go/session"
"github.com/nspcc-dev/neofs-sdk-go/user"
"go.uber.org/zap" "go.uber.org/zap"
) )
@ -104,7 +104,7 @@ func newWrapper(prm wrapperPrm) (*clientWrapper, error) {
func (c *clientWrapper) balanceGet(ctx context.Context, prm PrmBalanceGet) (*accounting.Decimal, error) { func (c *clientWrapper) balanceGet(ctx context.Context, prm PrmBalanceGet) (*accounting.Decimal, error) {
var cliPrm sdkClient.PrmBalanceGet var cliPrm sdkClient.PrmBalanceGet
cliPrm.SetAccount(prm.ownerID) cliPrm.SetAccount(prm.account)
res, err := c.client.BalanceGet(ctx, cliPrm) res, err := c.client.BalanceGet(ctx, cliPrm)
if err != nil { if err != nil {
@ -775,11 +775,11 @@ func (x *PrmContainerGet) SetContainerID(cnrID cid.ID) {
// PrmContainerList groups parameters of ListContainers operation. // PrmContainerList groups parameters of ListContainers operation.
type PrmContainerList struct { type PrmContainerList struct {
ownerID owner.ID ownerID user.ID
} }
// SetOwnerID specifies identifier of the NeoFS account to list the containers. // SetOwnerID specifies identifier of the NeoFS account to list the containers.
func (x *PrmContainerList) SetOwnerID(ownerID owner.ID) { func (x *PrmContainerList) SetOwnerID(ownerID user.ID) {
x.ownerID = ownerID x.ownerID = ownerID
} }
@ -848,12 +848,12 @@ func (x *PrmContainerSetEACL) SetWaitParams(waitParams WaitParams) {
// PrmBalanceGet groups parameters of Balance operation. // PrmBalanceGet groups parameters of Balance operation.
type PrmBalanceGet struct { type PrmBalanceGet struct {
ownerID owner.ID account user.ID
} }
// SetOwnerID specifies identifier of the NeoFS account for which the balance is requested. // SetAccount specifies identifier of the NeoFS account for which the balance is requested.
func (x *PrmBalanceGet) SetOwnerID(ownerID owner.ID) { func (x *PrmBalanceGet) SetAccount(id user.ID) {
x.ownerID = ownerID x.account = id
} }
// prmEndpointInfo groups parameters of sessionCreate operation. // prmEndpointInfo groups parameters of sessionCreate operation.
@ -903,7 +903,7 @@ type resCreateSession struct {
type Pool struct { type Pool struct {
innerPools []*innerPool innerPools []*innerPool
key *ecdsa.PrivateKey key *ecdsa.PrivateKey
owner *owner.ID sessionOwner user.ID
cancel context.CancelFunc cancel context.CancelFunc
closedCh chan struct{} closedCh chan struct{}
cache *sessionCache cache *sessionCache
@ -946,7 +946,6 @@ func NewPool(options InitParameters) (*Pool, error) {
pool := &Pool{ pool := &Pool{
key: options.key, key: options.key,
owner: owner.NewIDFromPublicKey(&options.key.PublicKey),
cache: cache, cache: cache,
logger: options.logger, logger: options.logger,
stokenDuration: options.sessionExpirationDuration, stokenDuration: options.sessionExpirationDuration,
@ -959,6 +958,8 @@ func NewPool(options InitParameters) (*Pool, error) {
clientBuilder: options.clientBuilder, clientBuilder: options.clientBuilder,
} }
user.IDFromKey(&pool.sessionOwner, options.key.PublicKey)
return pool, nil return pool, nil
} }
@ -982,7 +983,7 @@ func (p *Pool) Dial(ctx context.Context) error {
return err return err
} }
var healthy bool var healthy bool
st, err := createSessionTokenForDuration(ctx, c, p.owner, p.rebalanceParams.sessionExpirationDuration) st, err := createSessionTokenForDuration(ctx, c, p.sessionOwner, p.rebalanceParams.sessionExpirationDuration)
if err != nil && p.logger != nil { if err != nil && p.logger != nil {
p.logger.Warn("failed to create neofs session token for client", p.logger.Warn("failed to create neofs session token for client",
zap.String("Address", addr), zap.String("Address", addr),
@ -1205,8 +1206,8 @@ func (p *innerPool) connection() (*clientPack, error) {
return nil, errors.New("no healthy client") return nil, errors.New("no healthy client")
} }
func (p *Pool) OwnerID() *owner.ID { func (p *Pool) OwnerID() *user.ID {
return p.owner return &p.sessionOwner
} }
func formCacheKey(address string, key *ecdsa.PrivateKey) string { func formCacheKey(address string, key *ecdsa.PrivateKey) string {
@ -1228,7 +1229,7 @@ func (p *Pool) checkSessionTokenErr(err error, address string) bool {
return false return false
} }
func createSessionTokenForDuration(ctx context.Context, c client, ownerID *owner.ID, dur uint64) (*session.Token, error) { func createSessionTokenForDuration(ctx context.Context, c client, ownerID user.ID, dur uint64) (*session.Token, error) {
ni, err := c.networkInfo(ctx, prmNetworkInfo{}) ni, err := c.networkInfo(ctx, prmNetworkInfo{})
if err != nil { if err != nil {
return nil, err return nil, err
@ -1309,8 +1310,12 @@ func (p *Pool) openDefaultSession(ctx *callContext) error {
tok := p.cache.Get(cacheKey) tok := p.cache.Get(cacheKey)
if tok == nil { if tok == nil {
var err error var err error
var sessionOwner user.ID
user.IDFromKey(&sessionOwner, ctx.key.PublicKey)
// open new session // open new session
tok, err = createSessionTokenForDuration(ctx, ctx.client, owner.NewIDFromPublicKey(&ctx.key.PublicKey), p.stokenDuration) tok, err = createSessionTokenForDuration(ctx, ctx.client, sessionOwner, p.stokenDuration)
if err != nil { if err != nil {
return fmt.Errorf("session API client: %w", err) return fmt.Errorf("session API client: %w", err)
} }
@ -1784,9 +1789,9 @@ func (p *Pool) Close() {
} }
// creates new session token with specified owner from SessionCreate call result. // creates new session token with specified owner from SessionCreate call result.
func sessionTokenForOwner(id *owner.ID, cliRes *resCreateSession, exp uint64) *session.Token { func sessionTokenForOwner(id user.ID, cliRes *resCreateSession, exp uint64) *session.Token {
st := session.NewToken() st := session.NewToken()
st.SetOwnerID(id) st.SetOwnerID(&id)
st.SetID(cliRes.id) st.SetID(cliRes.id)
st.SetSessionKey(cliRes.sessionKey) st.SetSessionKey(cliRes.sessionKey)
st.SetExp(exp) st.SetExp(exp)
@ -1815,15 +1820,7 @@ func copySessionTokenWithoutSignatureAndContext(from session.Token) (to session.
copy(sessionTokenKey, from.SessionKey()) copy(sessionTokenKey, from.SessionKey())
to.SetSessionKey(sessionTokenKey) to.SetSessionKey(sessionTokenKey)
var sessionTokenOwner owner.ID sessionTokenOwner := *from.OwnerID()
buf, err := from.OwnerID().Marshal()
if err != nil {
panic(err) // should never happen
}
err = sessionTokenOwner.Unmarshal(buf)
if err != nil {
panic(err) // should never happen
}
to.SetOwnerID(&sessionTokenOwner) to.SetOwnerID(&sessionTokenOwner)
return to return to

View file

@ -17,9 +17,9 @@ import (
"github.com/nspcc-dev/neofs-sdk-go/netmap" "github.com/nspcc-dev/neofs-sdk-go/netmap"
"github.com/nspcc-dev/neofs-sdk-go/object" "github.com/nspcc-dev/neofs-sdk-go/object"
"github.com/nspcc-dev/neofs-sdk-go/object/address" "github.com/nspcc-dev/neofs-sdk-go/object/address"
"github.com/nspcc-dev/neofs-sdk-go/owner"
"github.com/nspcc-dev/neofs-sdk-go/session" "github.com/nspcc-dev/neofs-sdk-go/session"
sessiontest "github.com/nspcc-dev/neofs-sdk-go/session/test" sessiontest "github.com/nspcc-dev/neofs-sdk-go/session/test"
"github.com/nspcc-dev/neofs-sdk-go/user"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"go.uber.org/zap" "go.uber.org/zap"
) )
@ -594,7 +594,9 @@ func TestSessionTokenOwner(t *testing.T) {
t.Cleanup(p.Close) t.Cleanup(p.Close)
anonKey := newPrivateKey(t) anonKey := newPrivateKey(t)
anonOwner := owner.NewIDFromPublicKey(&anonKey.PublicKey)
var anonOwner user.ID
user.IDFromKey(&anonOwner, anonKey.PublicKey)
var prm prmCommon var prm prmCommon
prm.UseKey(anonKey) prm.UseKey(anonKey)
@ -611,7 +613,7 @@ func TestSessionTokenOwner(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
tkn := p.cache.Get(formCacheKey("peer0", anonKey)) tkn := p.cache.Get(formCacheKey("peer0", anonKey))
require.True(t, anonOwner.Equal(tkn.OwnerID())) require.True(t, anonOwner.Equals(*tkn.OwnerID()))
} }
func TestWaitPresence(t *testing.T) { func TestWaitPresence(t *testing.T) {

View file

@ -9,7 +9,7 @@ import (
"github.com/nspcc-dev/neofs-api-go/v2/session" "github.com/nspcc-dev/neofs-api-go/v2/session"
neofscrypto "github.com/nspcc-dev/neofs-sdk-go/crypto" neofscrypto "github.com/nspcc-dev/neofs-sdk-go/crypto"
neofsecdsa "github.com/nspcc-dev/neofs-sdk-go/crypto/ecdsa" neofsecdsa "github.com/nspcc-dev/neofs-sdk-go/crypto/ecdsa"
"github.com/nspcc-dev/neofs-sdk-go/owner" "github.com/nspcc-dev/neofs-sdk-go/user"
) )
// Token represents NeoFS API v2-compatible // Token represents NeoFS API v2-compatible
@ -72,18 +72,27 @@ func (t *Token) SetID(v []byte) {
} }
// OwnerID returns Token's owner identifier. // OwnerID returns Token's owner identifier.
func (t *Token) OwnerID() *owner.ID { func (t *Token) OwnerID() *user.ID {
return owner.NewIDFromV2( m := (*session.Token)(t).GetBody().GetOwnerID()
(*session.Token)(t). if m == nil {
GetBody(). return nil
GetOwnerID(), }
)
var res user.ID
_ = res.ReadFromV2(*m)
return &res
} }
// SetOwnerID sets Token's owner identifier. // SetOwnerID sets Token's owner identifier.
func (t *Token) SetOwnerID(v *owner.ID) { func (t *Token) SetOwnerID(v *user.ID) {
t.setBodyField(func(body *session.TokenBody) { t.setBodyField(func(body *session.TokenBody) {
body.SetOwnerID(v.ToV2()) var m refs.OwnerID
v.WriteToV2(&m)
body.SetOwnerID(&m)
}) })
} }

View file

@ -4,9 +4,9 @@ import (
"testing" "testing"
sessionv2 "github.com/nspcc-dev/neofs-api-go/v2/session" 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" "github.com/nspcc-dev/neofs-sdk-go/session"
sessiontest "github.com/nspcc-dev/neofs-sdk-go/session/test" sessiontest "github.com/nspcc-dev/neofs-sdk-go/session/test"
usertest "github.com/nspcc-dev/neofs-sdk-go/user/test"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@ -22,7 +22,7 @@ func TestSessionToken_SetID(t *testing.T) {
func TestSessionToken_SetOwnerID(t *testing.T) { func TestSessionToken_SetOwnerID(t *testing.T) {
token := session.NewToken() token := session.NewToken()
ownerID := ownertest.ID() ownerID := usertest.ID()
token.SetOwnerID(ownerID) token.SetOwnerID(ownerID)

View file

@ -7,8 +7,8 @@ import (
"github.com/google/uuid" "github.com/google/uuid"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys" "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" "github.com/nspcc-dev/neofs-sdk-go/session"
"github.com/nspcc-dev/neofs-sdk-go/user"
) )
var p *keys.PrivateKey var p *keys.PrivateKey
@ -38,13 +38,14 @@ func Token() *session.Token {
panic(err) panic(err)
} }
ownerID := owner.NewID() var ownerID user.ID
ownerID.SetPublicKey(&priv.PublicKey)
user.IDFromKey(&ownerID, priv.PublicKey)
keyBin := p.PublicKey().Bytes() keyBin := p.PublicKey().Bytes()
tok.SetID(uid) tok.SetID(uid)
tok.SetOwnerID(ownerID) tok.SetOwnerID(&ownerID)
tok.SetSessionKey(keyBin) tok.SetSessionKey(keyBin)
tok.SetExp(11) tok.SetExp(11)
tok.SetNbf(22) tok.SetNbf(22)

View file

@ -3,8 +3,8 @@ package subnet
import ( import (
"github.com/nspcc-dev/neofs-api-go/v2/refs" "github.com/nspcc-dev/neofs-api-go/v2/refs"
"github.com/nspcc-dev/neofs-api-go/v2/subnet" "github.com/nspcc-dev/neofs-api-go/v2/subnet"
"github.com/nspcc-dev/neofs-sdk-go/owner"
subnetid "github.com/nspcc-dev/neofs-sdk-go/subnet/id" subnetid "github.com/nspcc-dev/neofs-sdk-go/subnet/id"
"github.com/nspcc-dev/neofs-sdk-go/user"
) )
// Info represents information about NeoFS subnet. // Info represents information about NeoFS subnet.
@ -63,7 +63,7 @@ func (x Info) ReadID(id *subnetid.ID) {
} }
// SetOwner sets subnet owner ID. // SetOwner sets subnet owner ID.
func (x *Info) SetOwner(id owner.ID) { func (x *Info) SetOwner(id user.ID) {
infov2 := (*subnet.Info)(x) infov2 := (*subnet.Info)(x)
idv2 := infov2.Owner() idv2 := infov2.Owner()
@ -72,33 +72,32 @@ func (x *Info) SetOwner(id owner.ID) {
infov2.SetOwner(idv2) infov2.SetOwner(idv2)
} }
// FIXME: we need to implement and use owner.ID.WriteToV2() method id.WriteToV2(idv2)
*idv2 = *id.ToV2()
} }
// ReadOwner reads the identifier of the subnet that Info describes. // ReadOwner reads the identifier of the subnet that Info describes.
// Must be called only if owner is set (see HasOwner). Arg must not be nil. // Must be called only if owner is set (see HasOwner). Arg must not be nil.
func (x Info) ReadOwner(id *owner.ID) { func (x Info) ReadOwner(id *user.ID) {
infov2 := (subnet.Info)(x) infov2 := (subnet.Info)(x)
id2 := infov2.Owner() id2 := infov2.Owner()
if id2 == nil { if id2 == nil {
// TODO: implement owner.ID.Reset *id = user.ID{}
*id = owner.ID{}
return return
} }
// TODO: we need to implement and use owner.ID.FromV2 method if ownerV2 := infov2.Owner(); ownerV2 != nil {
*id = *owner.NewIDFromV2(infov2.Owner()) _ = id.ReadFromV2(*ownerV2)
}
} }
// IsOwner checks subnet ownership. // IsOwner checks subnet ownership.
func IsOwner(info Info, id owner.ID) bool { func IsOwner(info Info, id user.ID) bool {
id2 := new(owner.ID) var id2 user.ID
info.ReadOwner(id2) info.ReadOwner(&id2)
return id.Equal(id2) return id.Equals(id2)
} }
// IDEquals checks if ID refers to subnet that Info describes. // IDEquals checks if ID refers to subnet that Info describes.

View file

@ -5,10 +5,10 @@ import (
subnetv2 "github.com/nspcc-dev/neofs-api-go/v2/subnet" subnetv2 "github.com/nspcc-dev/neofs-api-go/v2/subnet"
subnettest "github.com/nspcc-dev/neofs-api-go/v2/subnet/test" subnettest "github.com/nspcc-dev/neofs-api-go/v2/subnet/test"
"github.com/nspcc-dev/neofs-sdk-go/owner"
ownertest "github.com/nspcc-dev/neofs-sdk-go/owner/test"
. "github.com/nspcc-dev/neofs-sdk-go/subnet" . "github.com/nspcc-dev/neofs-sdk-go/subnet"
subnetid "github.com/nspcc-dev/neofs-sdk-go/subnet/id" subnetid "github.com/nspcc-dev/neofs-sdk-go/subnet/id"
"github.com/nspcc-dev/neofs-sdk-go/user"
usertest "github.com/nspcc-dev/neofs-sdk-go/user/test"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@ -36,11 +36,11 @@ func TestInfo_SetID(t *testing.T) {
func TestInfo_SetOwner(t *testing.T) { func TestInfo_SetOwner(t *testing.T) {
var ( var (
id owner.ID id user.ID
info Info info Info
) )
id = *ownertest.ID() id = *usertest.ID()
require.False(t, IsOwner(info, id)) require.False(t, IsOwner(info, id))

55
user/doc.go Normal file
View file

@ -0,0 +1,55 @@
/*
Package user provides functionality related to NeoFS users.
User identity is reflected in ID type. Each user has its own unique identifier
within the same network.
NeoFS user identification is compatible with Neo accounts:
import "github.com/nspcc-dev/neo-go/pkg/crypto/keys"
import "github.com/nspcc-dev/neo-go/pkg/crypto/hash"
var id user.ID
var scriptHash util.Uint160 // user account in NeoFS
id.SetScriptHash(scriptHash)
var key keys.PublicKey // user's public key
user.IDFromKey(&id, k.PrivateKey.PublicKey)
ID is compatible with the NeoFS Smart Contract API:
var id user.ID
// ...
wallet := id.WalletBytes()
// use wallet in call
Encoding/decoding mechanisms are used to transfer identifiers:
var id user.ID
// ...
s := id.EncodeToString() // on transmitter
err = id.DecodeString(s) // on receiver
Instances can be also used to process NeoFS API protocol messages
(see neo.fs.v2.refs package in https://github.com/nspcc-dev/neofs-api).
On client side:
import "github.com/nspcc-dev/neofs-api-go/v2/refs"
var msg refs.OwnerID
id.WriteToV2(&msg)
// send msg
On server side:
// recv msg
var id user.ID
err := id.ReadFromV2(msg)
// ...
// process id
*/
package user

116
user/id.go Normal file
View file

@ -0,0 +1,116 @@
package user
import (
"bytes"
"errors"
"fmt"
"github.com/mr-tron/base58"
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neofs-api-go/v2/refs"
)
// ID identifies users of the NeoFS system.
//
// ID is mutually compatible with github.com/nspcc-dev/neofs-api-go/v2/refs.OwnerID
// message. See ReadFromV2 / WriteToV2 methods.
//
// Instances can be created using built-in var declaration. Zero ID is not valid,
// so it MUST be initialized using some modifying function (e.g. SetScriptHash,
// IDFromKey, etc.).
type ID struct {
w []byte
}
// ReadFromV2 reads ID from the refs.OwnerID message. Returns an error if
// the message is malformed according to the NeoFS API V2 protocol.
//
// See also WriteToV2.
func (x *ID) ReadFromV2(m refs.OwnerID) error {
w := m.GetValue()
if len(w) != 25 {
return fmt.Errorf("invalid length %d, expected 25", len(w))
}
if w[0] != address.NEO3Prefix {
return fmt.Errorf("invalid prefix byte 0x%X, expected 0x%X", w[0], address.NEO3Prefix)
}
if !bytes.Equal(w[21:], hash.Checksum(w[:21])) {
return errors.New("checksum mismatch")
}
x.w = w
return nil
}
// WriteToV2 writes ID to the refs.OwnerID message.
// The message must not be nil.
//
// See also ReadFromV2.
func (x ID) WriteToV2(m *refs.OwnerID) {
m.SetValue(x.w)
}
// SetScriptHash forms user ID from wallet address scripthash.
func (x *ID) SetScriptHash(scriptHash util.Uint160) {
if cap(x.w) < 25 {
x.w = make([]byte, 25)
} else if len(x.w) < 25 {
x.w = x.w[:25]
}
x.w[0] = address.Prefix
copy(x.w[1:], scriptHash.BytesBE())
copy(x.w[21:], hash.Checksum(x.w[:21]))
}
// WalletBytes returns NeoFS user ID as Neo3 wallet address in a binary format.
//
// Return value MUST NOT be mutated: to do this, first make a copy.
//
// See also Neo3 wallet docs.
func (x ID) WalletBytes() []byte {
return x.w
}
// EncodeToString encodes ID into NeoFS API V2 protocol string.
//
// See also DecodeString.
func (x ID) EncodeToString() string {
return base58.Encode(x.w)
}
// DecodeString decodes NeoFS API V2 protocol string. Returns an error
// if s is malformed.
//
// DecodeString always changes the ID.
//
// See also EncodeToString.
func (x *ID) DecodeString(s string) error {
var err error
x.w, err = base58.Decode(s)
if err != nil {
return fmt.Errorf("decode base58: %w", err)
}
return nil
}
// String implements fmt.Stringer.
//
// String is designed to be human-readable, and its format MAY differ between
// SDK versions. String MAY return same result as EncodeToString. String MUST NOT
// be used to encode ID into NeoFS protocol string.
func (x ID) String() string {
return x.EncodeToString()
}
// Equals defines a comparison relation between two ID instances.
func (x ID) Equals(x2 ID) bool {
return bytes.Equal(x.w, x2.w)
}

121
user/id_test.go Normal file
View file

@ -0,0 +1,121 @@
package user_test
import (
"math/rand"
"testing"
"github.com/mr-tron/base58"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/util/slice"
"github.com/nspcc-dev/neofs-api-go/v2/refs"
. "github.com/nspcc-dev/neofs-sdk-go/user"
usertest "github.com/nspcc-dev/neofs-sdk-go/user/test"
"github.com/stretchr/testify/require"
)
func TestID_WalletBytes(t *testing.T) {
var scriptHash util.Uint160
rand.Read(scriptHash[:])
var id ID
id.SetScriptHash(scriptHash)
w := id.WalletBytes()
var m refs.OwnerID
m.SetValue(w)
err := id.ReadFromV2(m)
require.NoError(t, err)
}
func TestID_SetScriptHash(t *testing.T) {
var scriptHash util.Uint160
rand.Read(scriptHash[:])
var id ID
id.SetScriptHash(scriptHash)
var m refs.OwnerID
id.WriteToV2(&m)
var id2 ID
err := id2.ReadFromV2(m)
require.NoError(t, err)
require.True(t, id2.Equals(id))
}
func TestV2_ID(t *testing.T) {
id := *usertest.ID()
var m refs.OwnerID
var id2 ID
t.Run("OK", func(t *testing.T) {
id.WriteToV2(&m)
err := id2.ReadFromV2(m)
require.NoError(t, err)
require.True(t, id2.Equals(id))
})
val := m.GetValue()
t.Run("invalid size", func(t *testing.T) {
m.SetValue(val[:24])
err := id2.ReadFromV2(m)
require.Error(t, err)
})
t.Run("invalid prefix", func(t *testing.T) {
val := slice.Copy(val)
val[0]++
m.SetValue(val)
err := id2.ReadFromV2(m)
require.Error(t, err)
})
t.Run("invalid checksum", func(t *testing.T) {
val := slice.Copy(val)
val[21]++
m.SetValue(val)
err := id2.ReadFromV2(m)
require.Error(t, err)
})
}
func TestID_EncodeToString(t *testing.T) {
id := *usertest.ID()
s := id.EncodeToString()
_, err := base58.Decode(s)
require.NoError(t, err)
var id2 ID
err = id2.DecodeString(s)
require.NoError(t, err)
require.Equal(t, id, id2)
err = id2.DecodeString("_") // any invalid bas58 string
require.Error(t, err)
}
func TestID_Equal(t *testing.T) {
id1 := *usertest.ID()
id2 := *usertest.ID()
id3 := id1
require.True(t, id1.Equals(id1)) // self-equality
require.True(t, id1.Equals(id3))
require.True(t, id3.Equals(id1)) // commutativity
require.False(t, id1.Equals(id2))
}

13
user/test/doc.go Normal file
View file

@ -0,0 +1,13 @@
/*
Package usertest provides functions for convenient testing of user package API.
Note that importing the package into source files is highly discouraged.
Random instance generation functions can be useful when testing expects any value, e.g.:
import usertest "github.com/nspcc-dev/neofs-sdk-go/user/test"
id := usertest.ID()
// test the value
*/
package usertest

19
user/test/id.go Normal file
View file

@ -0,0 +1,19 @@
package usertest
import (
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neofs-sdk-go/user"
)
// ID returns random user.ID.
func ID() *user.ID {
key, err := keys.NewPrivateKey()
if err != nil {
panic(err)
}
var x user.ID
user.IDFromKey(&x, key.PrivateKey.PublicKey)
return &x
}

12
user/util.go Normal file
View file

@ -0,0 +1,12 @@
package user
import (
"crypto/ecdsa"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
)
// IDFromKey forms the ID using script hash calculated for the given key.
func IDFromKey(id *ID, key ecdsa.PublicKey) {
id.SetScriptHash((*keys.PublicKey)(&key).GetScriptHash())
}

24
user/util_test.go Normal file
View file

@ -0,0 +1,24 @@
package user_test
import (
"crypto/ecdsa"
"crypto/elliptic"
"encoding/hex"
"testing"
"github.com/nspcc-dev/neofs-sdk-go/user"
"github.com/stretchr/testify/require"
)
func TestIDFromKey(t *testing.T) {
// examples are taken from https://docs.neo.org/docs/en-us/basic/concept/wallets.html
rawPub, _ := hex.DecodeString("03cdb067d930fd5adaa6c68545016044aaddec64ba39e548250eaea551172e535c")
x, y := elliptic.UnmarshalCompressed(elliptic.P256(), rawPub)
require.True(t, x != nil && y != nil)
var id user.ID
user.IDFromKey(&id, ecdsa.PublicKey{Curve: elliptic.P256(), X: x, Y: y})
require.Equal(t, "NNLi44dJNXtDNSBkofB48aTVYtb1zZrNEs", id.EncodeToString())
}