Add account remove test

This commit is contained in:
mcrakhman 2023-06-28 15:43:35 +02:00
parent 39f41c52d1
commit 3f08fcb555
No known key found for this signature in database
GPG Key ID: DED12CFEF5B8396B
7 changed files with 86 additions and 44 deletions

View File

@ -63,14 +63,16 @@ type aclRecordBuilder struct {
id string
keyStorage crypto.KeyStorage
accountKeys *accountdata.AccountKeys
verifier AcceptorVerifier
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{
id: id,
keyStorage: keyStorage,
accountKeys: keys,
verifier: verifier,
}
}
@ -420,6 +422,10 @@ func (a *aclRecordBuilder) UnmarshallWithId(rawIdRecord *aclrecordproto.RawAclRe
Model: aclRoot,
}
} else {
err = a.verifier.VerifyAcceptor(rawRec)
if err != nil {
return
}
aclRecord := &aclrecordproto.AclRecord{}
err = proto.Unmarshal(rawRec.Payload, aclRecord)
if err != nil {

View File

@ -25,6 +25,7 @@ var (
ErrInsufficientPermissions = errors.New("insufficient permissions")
ErrIsOwner = errors.New("can't be made by owner")
ErrIncorrectNumberOfAccounts = errors.New("incorrect number of accounts")
ErrDuplicateAccounts = errors.New("duplicate accounts")
ErrNoReadKey = errors.New("acl state doesn't have a read key")
ErrIncorrectReadKey = errors.New("incorrect read key")
ErrInvalidSignature = errors.New("signature is invalid")

View File

@ -85,10 +85,11 @@ type internalDeps struct {
func BuildAclListWithIdentity(acc *accountdata.AccountKeys, storage liststorage.ListStorage, verifier AcceptorVerifier) (AclList, error) {
keyStorage := crypto.NewKeyStorage()
deps := internalDeps{
storage: storage,
keyStorage: keyStorage,
stateBuilder: newAclStateBuilderWithIdentity(acc),
recordBuilder: NewAclRecordBuilder(storage.Id(), keyStorage, acc),
storage: storage,
keyStorage: keyStorage,
stateBuilder: newAclStateBuilderWithIdentity(acc),
recordBuilder: NewAclRecordBuilder(storage.Id(), keyStorage, acc, verifier),
acceptorVerifier: verifier,
}
return build(deps)
}
@ -96,10 +97,11 @@ func BuildAclListWithIdentity(acc *accountdata.AccountKeys, storage liststorage.
func BuildAclList(storage liststorage.ListStorage, verifier AcceptorVerifier) (AclList, error) {
keyStorage := crypto.NewKeyStorage()
deps := internalDeps{
storage: storage,
keyStorage: keyStorage,
stateBuilder: newAclStateBuilder(),
recordBuilder: NewAclRecordBuilder(storage.Id(), keyStorage, nil),
storage: storage,
keyStorage: keyStorage,
stateBuilder: newAclStateBuilder(),
recordBuilder: NewAclRecordBuilder(storage.Id(), keyStorage, nil, verifier),
acceptorVerifier: verifier,
}
return build(deps)
}
@ -215,15 +217,6 @@ func (a *aclList) AddRawRecord(rawRec *aclrecordproto.RawAclRecordWithId) (err e
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 {
return a.id
}

View File

@ -7,6 +7,7 @@ import (
"github.com/anyproto/any-sync/commonspace/object/accountdata"
"github.com/anyproto/any-sync/commonspace/object/acl/aclrecordproto"
"github.com/anyproto/any-sync/util/cidutil"
"github.com/anyproto/any-sync/util/crypto"
"github.com/stretchr/testify/require"
)
@ -52,16 +53,14 @@ func newFixture(t *testing.T) *aclFixture {
}
}
func TestAclList_BuildRoot(t *testing.T) {
randomKeys, err := accountdata.NewRandom()
func (fx *aclFixture) addRec(t *testing.T, rec *aclrecordproto.RawAclRecordWithId) {
err := fx.ownerAcl.AddRawRecord(rec)
require.NoError(t, err)
randomAcl, err := NewTestDerivedAcl("spaceId", randomKeys)
err = fx.accountAcl.AddRawRecord(rec)
require.NoError(t, err)
fmt.Println(randomAcl.Id())
}
func TestAclList_InvitePipeline(t *testing.T) {
fx := newFixture(t)
func (fx *aclFixture) inviteAccount(t *testing.T, perms AclPermissions) {
var (
ownerAcl = fx.ownerAcl
ownerState = fx.ownerAcl.aclState
@ -72,10 +71,7 @@ func TestAclList_InvitePipeline(t *testing.T) {
inv, err := ownerAcl.RecordBuilder().BuildInvite()
require.NoError(t, err)
inviteRec := wrapRecord(inv.InviteRec)
err = ownerAcl.AddRawRecord(inviteRec)
require.NoError(t, err)
err = accountAcl.AddRawRecord(inviteRec)
require.NoError(t, err)
fx.addRec(t, inviteRec)
// building request join
requestJoin, err := accountAcl.RecordBuilder().BuildRequestJoin(RequestJoinPayload{
@ -84,22 +80,16 @@ func TestAclList_InvitePipeline(t *testing.T) {
})
require.NoError(t, err)
requestJoinRec := wrapRecord(requestJoin)
err = ownerAcl.AddRawRecord(requestJoinRec)
require.NoError(t, err)
err = accountAcl.AddRawRecord(requestJoinRec)
require.NoError(t, err)
fx.addRec(t, requestJoinRec)
// building request accept
requestAccept, err := ownerAcl.RecordBuilder().BuildRequestAccept(RequestAcceptPayload{
RequestRecordId: requestJoinRec.Id,
Permissions: AclPermissions(aclrecordproto.AclUserPermissions_Writer),
Permissions: perms,
})
require.NoError(t, err)
requestAcceptRec := wrapRecord(requestAccept)
err = ownerAcl.AddRawRecord(requestAcceptRec)
require.NoError(t, err)
err = accountAcl.AddRawRecord(requestAcceptRec)
require.NoError(t, err)
fx.addRec(t, requestAcceptRec)
// checking acl state
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(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()])
}

View File

@ -8,7 +8,7 @@ import (
)
func NewTestDerivedAcl(spaceId string, keys *accountdata.AccountKeys) (AclList, error) {
builder := NewAclRecordBuilder("", crypto.NewKeyStorage(), keys)
builder := NewAclRecordBuilder("", crypto.NewKeyStorage(), keys, NoOpAcceptorVerifier{})
masterKey, _, err := crypto.GenerateRandomEd25519KeyPair()
if err != nil {
return nil, err

View File

@ -161,11 +161,15 @@ func (c *contentValidator) ValidateAccountRemove(ch *aclrecordproto.AclAccountRe
if !c.aclState.Permissions(authorIdentity).CanManageAccounts() {
return ErrInsufficientPermissions
}
seenIdentities := map[string]struct{}{}
for _, rawIdentity := range ch.Identities {
identity, err := c.keyStore.PubKeyFromProto(rawIdentity)
if err != nil {
return err
}
if identity.Equals(authorIdentity) {
return ErrInsufficientPermissions
}
permissions := c.aclState.Permissions(identity)
if permissions.NoPermissions() {
return ErrNoSuchAccount
@ -173,8 +177,13 @@ func (c *contentValidator) ValidateAccountRemove(ch *aclrecordproto.AclAccountRe
if permissions.IsOwner() {
return ErrInsufficientPermissions
}
idKey := mapKeyFromPubKey(identity)
if _, exists := seenIdentities[idKey]; exists {
return ErrDuplicateAccounts
}
seenIdentities[mapKeyFromPubKey(identity)] = struct{}{}
}
return c.validateAccountReadKeys(ch.AccountKeys)
return c.validateAccountReadKeys(ch.AccountKeys, len(c.aclState.userStates)-len(ch.Identities))
}
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) {
return c.validateAccountReadKeys(ch.AccountKeys)
return c.validateAccountReadKeys(ch.AccountKeys, len(c.aclState.userStates))
}
func (c *contentValidator) validateAccountReadKeys(accountKeys []*aclrecordproto.AclEncryptedReadKey) (err error) {
if len(accountKeys) != len(c.aclState.userStates) {
func (c *contentValidator) validateAccountReadKeys(accountKeys []*aclrecordproto.AclEncryptedReadKey, usersNum int) (err error) {
if len(accountKeys) != usersNum {
return ErrIncorrectNumberOfAccounts
}
for _, encKeys := range accountKeys {

View File

@ -72,7 +72,7 @@ func storagePayloadForSpaceCreate(payload SpaceCreatePayload) (storagePayload sp
// building acl root
keyStorage := crypto.NewKeyStorage()
aclBuilder := list.NewAclRecordBuilder("", keyStorage, nil)
aclBuilder := list.NewAclRecordBuilder("", keyStorage, nil, list.NoOpAcceptorVerifier{})
aclRoot, err := aclBuilder.BuildRoot(list.RootContent{
PrivKey: payload.SigningKey,
MasterKey: payload.MasterKey,
@ -159,7 +159,7 @@ func storagePayloadForSpaceDerive(payload SpaceDerivePayload) (storagePayload sp
// building acl root
keyStorage := crypto.NewKeyStorage()
aclBuilder := list.NewAclRecordBuilder("", keyStorage, nil)
aclBuilder := list.NewAclRecordBuilder("", keyStorage, nil, list.NoOpAcceptorVerifier{})
aclRoot, err := aclBuilder.BuildRoot(list.RootContent{
PrivKey: payload.SigningKey,
MasterKey: payload.MasterKey,