Add test for thread utility

This commit is contained in:
mcrakhman 2022-07-12 21:27:27 +02:00 committed by Mikhail Iudin
parent dbfb8cbabc
commit acc2699b0e
No known key found for this signature in database
GPG Key ID: FAAAA8BAABDFF1C0
4 changed files with 88 additions and 17 deletions

View File

@ -110,8 +110,11 @@ func (st *ACLState) applyChange(change *pb.ACLChange) (err error) {
}
st.currentReadKeyHash = change.CurrentReadKeyHash
}()
// we can't check this for the user which is joining, because it will not be in our list
if !st.isUserJoin(change) {
// the same is for the first change to be added
skipIdentityCheck := st.isUserJoin(change) || (st.currentReadKeyHash == 0 && st.isUserAdd(change))
if !skipIdentityCheck {
// we check signature when we add this to the Tree, so no need to do it here
if _, exists := st.userStates[change.Identity]; !exists {
err = ErrNoSuchUser
@ -320,6 +323,12 @@ func (st *ACLState) isUserJoin(ch *pb.ACLChange) bool {
return ch.AclData.GetAclContent() != nil && ch.AclData.GetAclContent()[0].GetUserJoin() != nil
}
func (st *ACLState) isUserAdd(ch *pb.ACLChange) bool {
// if we have a UserAdd, then it should always be the first one applied
userAdd := ch.AclData.GetAclContent()[0].GetUserAdd()
return ch.AclData.GetAclContent() != nil && userAdd != nil && userAdd.GetIdentity() == ch.Identity
}
func (st *ACLState) getPermissionDecreasedUsers(ch *pb.ACLChange) (identities []*pb.ACLChangeUserPermissionChange) {
// this should be called after general checks are completed
if ch.GetAclData().GetAclContent() == nil {

View File

@ -8,6 +8,7 @@ import (
"github.com/gogo/protobuf/proto"
"github.com/textileio/go-threads/crypto/symmetric"
"hash/fnv"
"time"
)
type MarshalledChange = []byte
@ -105,28 +106,16 @@ func (c *changeBuilder) UserAdd(identity string, encryptionKey keys.EncryptionPu
}
func (c *changeBuilder) BuildAndApply() (*Change, []byte, error) {
marshalled, err := c.changeContent.Marshal()
if err != nil {
return nil, nil, err
}
encrypted, err := c.aclState.userReadKeys[c.aclState.currentReadKeyHash].
Encrypt(marshalled)
if err != nil {
return nil, nil, err
}
aclChange := &pb.ACLChange{
TreeHeadIds: c.tree.Heads(),
AclHeadIds: c.tree.ACLHeads(),
SnapshotBaseId: c.tree.RootId(),
AclData: c.aclData,
ChangesData: encrypted,
CurrentReadKeyHash: c.aclState.currentReadKeyHash,
Timestamp: 0,
CurrentReadKeyHash: c.readKeyHash,
Timestamp: int64(time.Now().Nanosecond()),
Identity: c.acc.Identity,
}
err = c.aclState.applyChange(aclChange)
err := c.aclState.applyChange(aclChange)
if err != nil {
return nil, nil, err
}
@ -135,6 +124,21 @@ func (c *changeBuilder) BuildAndApply() (*Change, []byte, error) {
c.aclData.AclSnapshot = c.aclState.makeSnapshot()
}
var marshalled []byte
if c.changeContent != nil {
marshalled, err = c.changeContent.Marshal()
if err != nil {
return nil, nil, err
}
encrypted, err := c.aclState.userReadKeys[c.aclState.currentReadKeyHash].
Encrypt(marshalled)
if err != nil {
return nil, nil, err
}
aclChange.ChangesData = encrypted
}
fullMarshalledChange, err := proto.Marshal(aclChange)
if err != nil {
return nil, nil, err

View File

@ -31,5 +31,12 @@ func BuildThreadWithACL(
Signature: change.Signature(),
Id: change.CID(),
}
return create(rawChange)
thr, err := create(rawChange)
if err != nil {
return nil, err
}
thr.SetHeads([]string{change.CID()})
return thr, nil
}

View File

@ -0,0 +1,51 @@
package acltree
import (
"context"
"github.com/anytypeio/go-anytype-infrastructure-experiments/account"
"github.com/anytypeio/go-anytype-infrastructure-experiments/aclchanges/pb"
"github.com/anytypeio/go-anytype-infrastructure-experiments/testutils/threadbuilder"
"github.com/anytypeio/go-anytype-infrastructure-experiments/thread"
"github.com/stretchr/testify/assert"
"testing"
)
func TestBuildThreadWithACL(t *testing.T) {
keychain := threadbuilder.NewKeychain()
keychain.AddSigningKey("A")
keychain.AddEncryptionKey("A")
data := &account.AccountData{
Identity: keychain.GetIdentity("A"),
SignKey: keychain.SigningKeys["A"],
EncKey: keychain.EncryptionKeys["A"],
}
thr, err := BuildThreadWithACL(
data,
func(builder ChangeBuilder) error {
return builder.UserAdd(
keychain.GetIdentity("A"),
keychain.EncryptionKeys["A"].GetPublic(),
pb.ACLChange_Admin)
},
thread.NewInMemoryThread)
if err != nil {
t.Fatalf("build should not return error")
}
if len(thr.Heads()) == 0 {
t.Fatalf("thread should have non-empty heads")
}
if thr.Header() == nil {
t.Fatalf("thread should have non-empty header")
}
assert.Equal(t, thr.Heads()[0], thr.Header().FirstChangeId)
assert.NotEmpty(t, thr.ID())
ch, err := thr.GetChange(context.Background(), thr.Header().FirstChangeId)
if err != nil {
t.Fatalf("get change should not return error: %v", err)
}
_, err = NewFromRawChange(ch)
if err != nil {
t.Fatalf("we should be able to unmarshall change: %v", err)
}
}