Add account remove test
This commit is contained in:
parent
39f41c52d1
commit
3f08fcb555
@ -63,14 +63,16 @@ type aclRecordBuilder struct {
|
|||||||
id string
|
id string
|
||||||
keyStorage crypto.KeyStorage
|
keyStorage crypto.KeyStorage
|
||||||
accountKeys *accountdata.AccountKeys
|
accountKeys *accountdata.AccountKeys
|
||||||
|
verifier AcceptorVerifier
|
||||||
state *AclState
|
state *AclState
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAclRecordBuilder(id string, keyStorage crypto.KeyStorage, keys *accountdata.AccountKeys) AclRecordBuilder {
|
func NewAclRecordBuilder(id string, keyStorage crypto.KeyStorage, keys *accountdata.AccountKeys, verifier AcceptorVerifier) AclRecordBuilder {
|
||||||
return &aclRecordBuilder{
|
return &aclRecordBuilder{
|
||||||
id: id,
|
id: id,
|
||||||
keyStorage: keyStorage,
|
keyStorage: keyStorage,
|
||||||
accountKeys: keys,
|
accountKeys: keys,
|
||||||
|
verifier: verifier,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -420,6 +422,10 @@ func (a *aclRecordBuilder) UnmarshallWithId(rawIdRecord *aclrecordproto.RawAclRe
|
|||||||
Model: aclRoot,
|
Model: aclRoot,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
err = a.verifier.VerifyAcceptor(rawRec)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
aclRecord := &aclrecordproto.AclRecord{}
|
aclRecord := &aclrecordproto.AclRecord{}
|
||||||
err = proto.Unmarshal(rawRec.Payload, aclRecord)
|
err = proto.Unmarshal(rawRec.Payload, aclRecord)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@ -25,6 +25,7 @@ var (
|
|||||||
ErrInsufficientPermissions = errors.New("insufficient permissions")
|
ErrInsufficientPermissions = errors.New("insufficient permissions")
|
||||||
ErrIsOwner = errors.New("can't be made by owner")
|
ErrIsOwner = errors.New("can't be made by owner")
|
||||||
ErrIncorrectNumberOfAccounts = errors.New("incorrect number of accounts")
|
ErrIncorrectNumberOfAccounts = errors.New("incorrect number of accounts")
|
||||||
|
ErrDuplicateAccounts = errors.New("duplicate accounts")
|
||||||
ErrNoReadKey = errors.New("acl state doesn't have a read key")
|
ErrNoReadKey = errors.New("acl state doesn't have a read key")
|
||||||
ErrIncorrectReadKey = errors.New("incorrect read key")
|
ErrIncorrectReadKey = errors.New("incorrect read key")
|
||||||
ErrInvalidSignature = errors.New("signature is invalid")
|
ErrInvalidSignature = errors.New("signature is invalid")
|
||||||
|
|||||||
@ -88,7 +88,8 @@ func BuildAclListWithIdentity(acc *accountdata.AccountKeys, storage liststorage.
|
|||||||
storage: storage,
|
storage: storage,
|
||||||
keyStorage: keyStorage,
|
keyStorage: keyStorage,
|
||||||
stateBuilder: newAclStateBuilderWithIdentity(acc),
|
stateBuilder: newAclStateBuilderWithIdentity(acc),
|
||||||
recordBuilder: NewAclRecordBuilder(storage.Id(), keyStorage, acc),
|
recordBuilder: NewAclRecordBuilder(storage.Id(), keyStorage, acc, verifier),
|
||||||
|
acceptorVerifier: verifier,
|
||||||
}
|
}
|
||||||
return build(deps)
|
return build(deps)
|
||||||
}
|
}
|
||||||
@ -99,7 +100,8 @@ func BuildAclList(storage liststorage.ListStorage, verifier AcceptorVerifier) (A
|
|||||||
storage: storage,
|
storage: storage,
|
||||||
keyStorage: keyStorage,
|
keyStorage: keyStorage,
|
||||||
stateBuilder: newAclStateBuilder(),
|
stateBuilder: newAclStateBuilder(),
|
||||||
recordBuilder: NewAclRecordBuilder(storage.Id(), keyStorage, nil),
|
recordBuilder: NewAclRecordBuilder(storage.Id(), keyStorage, nil, verifier),
|
||||||
|
acceptorVerifier: verifier,
|
||||||
}
|
}
|
||||||
return build(deps)
|
return build(deps)
|
||||||
}
|
}
|
||||||
@ -215,15 +217,6 @@ func (a *aclList) AddRawRecord(rawRec *aclrecordproto.RawAclRecordWithId) (err e
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *aclList) IsValidNext(rawRec *aclrecordproto.RawAclRecordWithId) (err error) {
|
|
||||||
_, err = a.recordBuilder.UnmarshallWithId(rawRec)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// TODO: change state and add "check" method for records
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *aclList) Id() string {
|
func (a *aclList) Id() string {
|
||||||
return a.id
|
return a.id
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import (
|
|||||||
"github.com/anyproto/any-sync/commonspace/object/accountdata"
|
"github.com/anyproto/any-sync/commonspace/object/accountdata"
|
||||||
"github.com/anyproto/any-sync/commonspace/object/acl/aclrecordproto"
|
"github.com/anyproto/any-sync/commonspace/object/acl/aclrecordproto"
|
||||||
"github.com/anyproto/any-sync/util/cidutil"
|
"github.com/anyproto/any-sync/util/cidutil"
|
||||||
|
"github.com/anyproto/any-sync/util/crypto"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -52,16 +53,14 @@ func newFixture(t *testing.T) *aclFixture {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAclList_BuildRoot(t *testing.T) {
|
func (fx *aclFixture) addRec(t *testing.T, rec *aclrecordproto.RawAclRecordWithId) {
|
||||||
randomKeys, err := accountdata.NewRandom()
|
err := fx.ownerAcl.AddRawRecord(rec)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
randomAcl, err := NewTestDerivedAcl("spaceId", randomKeys)
|
err = fx.accountAcl.AddRawRecord(rec)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
fmt.Println(randomAcl.Id())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAclList_InvitePipeline(t *testing.T) {
|
func (fx *aclFixture) inviteAccount(t *testing.T, perms AclPermissions) {
|
||||||
fx := newFixture(t)
|
|
||||||
var (
|
var (
|
||||||
ownerAcl = fx.ownerAcl
|
ownerAcl = fx.ownerAcl
|
||||||
ownerState = fx.ownerAcl.aclState
|
ownerState = fx.ownerAcl.aclState
|
||||||
@ -72,10 +71,7 @@ func TestAclList_InvitePipeline(t *testing.T) {
|
|||||||
inv, err := ownerAcl.RecordBuilder().BuildInvite()
|
inv, err := ownerAcl.RecordBuilder().BuildInvite()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
inviteRec := wrapRecord(inv.InviteRec)
|
inviteRec := wrapRecord(inv.InviteRec)
|
||||||
err = ownerAcl.AddRawRecord(inviteRec)
|
fx.addRec(t, inviteRec)
|
||||||
require.NoError(t, err)
|
|
||||||
err = accountAcl.AddRawRecord(inviteRec)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
// building request join
|
// building request join
|
||||||
requestJoin, err := accountAcl.RecordBuilder().BuildRequestJoin(RequestJoinPayload{
|
requestJoin, err := accountAcl.RecordBuilder().BuildRequestJoin(RequestJoinPayload{
|
||||||
@ -84,22 +80,16 @@ func TestAclList_InvitePipeline(t *testing.T) {
|
|||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
requestJoinRec := wrapRecord(requestJoin)
|
requestJoinRec := wrapRecord(requestJoin)
|
||||||
err = ownerAcl.AddRawRecord(requestJoinRec)
|
fx.addRec(t, requestJoinRec)
|
||||||
require.NoError(t, err)
|
|
||||||
err = accountAcl.AddRawRecord(requestJoinRec)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
// building request accept
|
// building request accept
|
||||||
requestAccept, err := ownerAcl.RecordBuilder().BuildRequestAccept(RequestAcceptPayload{
|
requestAccept, err := ownerAcl.RecordBuilder().BuildRequestAccept(RequestAcceptPayload{
|
||||||
RequestRecordId: requestJoinRec.Id,
|
RequestRecordId: requestJoinRec.Id,
|
||||||
Permissions: AclPermissions(aclrecordproto.AclUserPermissions_Writer),
|
Permissions: perms,
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
requestAcceptRec := wrapRecord(requestAccept)
|
requestAcceptRec := wrapRecord(requestAccept)
|
||||||
err = ownerAcl.AddRawRecord(requestAcceptRec)
|
fx.addRec(t, requestAcceptRec)
|
||||||
require.NoError(t, err)
|
|
||||||
err = accountAcl.AddRawRecord(requestAcceptRec)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
// checking acl state
|
// checking acl state
|
||||||
require.True(t, ownerState.Permissions(ownerState.pubKey).IsOwner())
|
require.True(t, ownerState.Permissions(ownerState.pubKey).IsOwner())
|
||||||
@ -109,3 +99,46 @@ func TestAclList_InvitePipeline(t *testing.T) {
|
|||||||
require.True(t, accountState.Permissions(ownerState.pubKey).IsOwner())
|
require.True(t, accountState.Permissions(ownerState.pubKey).IsOwner())
|
||||||
require.True(t, accountState.Permissions(accountState.pubKey).CanWrite())
|
require.True(t, accountState.Permissions(accountState.pubKey).CanWrite())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAclList_BuildRoot(t *testing.T) {
|
||||||
|
randomKeys, err := accountdata.NewRandom()
|
||||||
|
require.NoError(t, err)
|
||||||
|
randomAcl, err := NewTestDerivedAcl("spaceId", randomKeys)
|
||||||
|
require.NoError(t, err)
|
||||||
|
fmt.Println(randomAcl.Id())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAclList_InvitePipeline(t *testing.T) {
|
||||||
|
fx := newFixture(t)
|
||||||
|
fx.inviteAccount(t, AclPermissions(aclrecordproto.AclUserPermissions_Writer))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAclList_Remove(t *testing.T) {
|
||||||
|
fx := newFixture(t)
|
||||||
|
var (
|
||||||
|
ownerState = fx.ownerAcl.aclState
|
||||||
|
accountState = fx.accountAcl.aclState
|
||||||
|
)
|
||||||
|
fx.inviteAccount(t, AclPermissions(aclrecordproto.AclUserPermissions_Writer))
|
||||||
|
|
||||||
|
newReadKey := crypto.NewAES()
|
||||||
|
remove, err := fx.ownerAcl.RecordBuilder().BuildAccountRemove(AccountRemovePayload{
|
||||||
|
Identities: []crypto.PubKey{fx.accountKeys.SignKey.GetPublic()},
|
||||||
|
ReadKey: newReadKey,
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
removeRec := wrapRecord(remove)
|
||||||
|
fx.addRec(t, removeRec)
|
||||||
|
|
||||||
|
// checking acl state
|
||||||
|
require.True(t, ownerState.Permissions(ownerState.pubKey).IsOwner())
|
||||||
|
require.True(t, ownerState.Permissions(accountState.pubKey).NoPermissions())
|
||||||
|
require.True(t, ownerState.userReadKeys[removeRec.Id].Equals(newReadKey))
|
||||||
|
require.NotNil(t, ownerState.userReadKeys[fx.ownerAcl.Id()])
|
||||||
|
require.Equal(t, 0, len(ownerState.pendingRequests))
|
||||||
|
require.Equal(t, 0, len(accountState.pendingRequests))
|
||||||
|
require.True(t, accountState.Permissions(ownerState.pubKey).IsOwner())
|
||||||
|
require.True(t, accountState.Permissions(accountState.pubKey).NoPermissions())
|
||||||
|
require.Nil(t, accountState.userReadKeys[removeRec.Id])
|
||||||
|
require.NotNil(t, accountState.userReadKeys[fx.ownerAcl.Id()])
|
||||||
|
}
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func NewTestDerivedAcl(spaceId string, keys *accountdata.AccountKeys) (AclList, error) {
|
func NewTestDerivedAcl(spaceId string, keys *accountdata.AccountKeys) (AclList, error) {
|
||||||
builder := NewAclRecordBuilder("", crypto.NewKeyStorage(), keys)
|
builder := NewAclRecordBuilder("", crypto.NewKeyStorage(), keys, NoOpAcceptorVerifier{})
|
||||||
masterKey, _, err := crypto.GenerateRandomEd25519KeyPair()
|
masterKey, _, err := crypto.GenerateRandomEd25519KeyPair()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@ -161,11 +161,15 @@ func (c *contentValidator) ValidateAccountRemove(ch *aclrecordproto.AclAccountRe
|
|||||||
if !c.aclState.Permissions(authorIdentity).CanManageAccounts() {
|
if !c.aclState.Permissions(authorIdentity).CanManageAccounts() {
|
||||||
return ErrInsufficientPermissions
|
return ErrInsufficientPermissions
|
||||||
}
|
}
|
||||||
|
seenIdentities := map[string]struct{}{}
|
||||||
for _, rawIdentity := range ch.Identities {
|
for _, rawIdentity := range ch.Identities {
|
||||||
identity, err := c.keyStore.PubKeyFromProto(rawIdentity)
|
identity, err := c.keyStore.PubKeyFromProto(rawIdentity)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if identity.Equals(authorIdentity) {
|
||||||
|
return ErrInsufficientPermissions
|
||||||
|
}
|
||||||
permissions := c.aclState.Permissions(identity)
|
permissions := c.aclState.Permissions(identity)
|
||||||
if permissions.NoPermissions() {
|
if permissions.NoPermissions() {
|
||||||
return ErrNoSuchAccount
|
return ErrNoSuchAccount
|
||||||
@ -173,8 +177,13 @@ func (c *contentValidator) ValidateAccountRemove(ch *aclrecordproto.AclAccountRe
|
|||||||
if permissions.IsOwner() {
|
if permissions.IsOwner() {
|
||||||
return ErrInsufficientPermissions
|
return ErrInsufficientPermissions
|
||||||
}
|
}
|
||||||
|
idKey := mapKeyFromPubKey(identity)
|
||||||
|
if _, exists := seenIdentities[idKey]; exists {
|
||||||
|
return ErrDuplicateAccounts
|
||||||
}
|
}
|
||||||
return c.validateAccountReadKeys(ch.AccountKeys)
|
seenIdentities[mapKeyFromPubKey(identity)] = struct{}{}
|
||||||
|
}
|
||||||
|
return c.validateAccountReadKeys(ch.AccountKeys, len(c.aclState.userStates)-len(ch.Identities))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *contentValidator) ValidateRequestRemove(ch *aclrecordproto.AclAccountRequestRemove, authorIdentity crypto.PubKey) (err error) {
|
func (c *contentValidator) ValidateRequestRemove(ch *aclrecordproto.AclAccountRequestRemove, authorIdentity crypto.PubKey) (err error) {
|
||||||
@ -188,11 +197,11 @@ func (c *contentValidator) ValidateRequestRemove(ch *aclrecordproto.AclAccountRe
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *contentValidator) ValidateReadKeyChange(ch *aclrecordproto.AclReadKeyChange, authorIdentity crypto.PubKey) (err error) {
|
func (c *contentValidator) ValidateReadKeyChange(ch *aclrecordproto.AclReadKeyChange, authorIdentity crypto.PubKey) (err error) {
|
||||||
return c.validateAccountReadKeys(ch.AccountKeys)
|
return c.validateAccountReadKeys(ch.AccountKeys, len(c.aclState.userStates))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *contentValidator) validateAccountReadKeys(accountKeys []*aclrecordproto.AclEncryptedReadKey) (err error) {
|
func (c *contentValidator) validateAccountReadKeys(accountKeys []*aclrecordproto.AclEncryptedReadKey, usersNum int) (err error) {
|
||||||
if len(accountKeys) != len(c.aclState.userStates) {
|
if len(accountKeys) != usersNum {
|
||||||
return ErrIncorrectNumberOfAccounts
|
return ErrIncorrectNumberOfAccounts
|
||||||
}
|
}
|
||||||
for _, encKeys := range accountKeys {
|
for _, encKeys := range accountKeys {
|
||||||
|
|||||||
@ -72,7 +72,7 @@ func storagePayloadForSpaceCreate(payload SpaceCreatePayload) (storagePayload sp
|
|||||||
|
|
||||||
// building acl root
|
// building acl root
|
||||||
keyStorage := crypto.NewKeyStorage()
|
keyStorage := crypto.NewKeyStorage()
|
||||||
aclBuilder := list.NewAclRecordBuilder("", keyStorage, nil)
|
aclBuilder := list.NewAclRecordBuilder("", keyStorage, nil, list.NoOpAcceptorVerifier{})
|
||||||
aclRoot, err := aclBuilder.BuildRoot(list.RootContent{
|
aclRoot, err := aclBuilder.BuildRoot(list.RootContent{
|
||||||
PrivKey: payload.SigningKey,
|
PrivKey: payload.SigningKey,
|
||||||
MasterKey: payload.MasterKey,
|
MasterKey: payload.MasterKey,
|
||||||
@ -159,7 +159,7 @@ func storagePayloadForSpaceDerive(payload SpaceDerivePayload) (storagePayload sp
|
|||||||
|
|
||||||
// building acl root
|
// building acl root
|
||||||
keyStorage := crypto.NewKeyStorage()
|
keyStorage := crypto.NewKeyStorage()
|
||||||
aclBuilder := list.NewAclRecordBuilder("", keyStorage, nil)
|
aclBuilder := list.NewAclRecordBuilder("", keyStorage, nil, list.NoOpAcceptorVerifier{})
|
||||||
aclRoot, err := aclBuilder.BuildRoot(list.RootContent{
|
aclRoot, err := aclBuilder.BuildRoot(list.RootContent{
|
||||||
PrivKey: payload.SigningKey,
|
PrivKey: payload.SigningKey,
|
||||||
MasterKey: payload.MasterKey,
|
MasterKey: payload.MasterKey,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user