diff --git a/acltree/acltree_test.go b/acltree/acltree_test.go index ebf3e4c2..8f5665ac 100644 --- a/acltree/acltree_test.go +++ b/acltree/acltree_test.go @@ -10,6 +10,12 @@ import ( "github.com/anytypeio/go-anytype-infrastructure-experiments/testutils/threadbuilder" ) +type mockListener struct{} + +func (m *mockListener) Update(tree ACLTree) {} + +func (m *mockListener) Rebuild(tree ACLTree) {} + func TestACLTree_UserJoinBuild(t *testing.T) { thr, err := threadbuilder.NewThreadBuilderFromFile("threadbuilder/userjoinexample.yml") if err != nil { @@ -21,7 +27,8 @@ func TestACLTree_UserJoinBuild(t *testing.T) { SignKey: keychain.SigningKeys["A"], EncKey: keychain.EncryptionKeys["A"], } - tree, err := BuildACLTree(thr, accountData) + listener := &mockListener{} + tree, err := BuildACLTree(thr, accountData, listener) if err != nil { t.Fatalf("should Build acl ACLState without err: %v", err) } @@ -55,7 +62,8 @@ func TestACLTree_UserRemoveBuild(t *testing.T) { SignKey: keychain.SigningKeys["A"], EncKey: keychain.EncryptionKeys["A"], } - tree, err := BuildACLTree(thr, accountData) + listener := &mockListener{} + tree, err := BuildACLTree(thr, accountData, listener) if err != nil { t.Fatalf("should Build acl ACLState without err: %v", err) } @@ -85,7 +93,8 @@ func TestACLTree_UserRemoveBeforeBuild(t *testing.T) { SignKey: keychain.SigningKeys["A"], EncKey: keychain.EncryptionKeys["A"], } - tree, err := BuildACLTree(thr, accountData) + listener := &mockListener{} + tree, err := BuildACLTree(thr, accountData, listener) if err != nil { t.Fatalf("should Build acl ACLState without err: %v", err) } @@ -116,7 +125,8 @@ func TestACLTree_InvalidSnapshotBuild(t *testing.T) { SignKey: keychain.SigningKeys["A"], EncKey: keychain.EncryptionKeys["A"], } - tree, err := BuildACLTree(thr, accountData) + listener := &mockListener{} + tree, err := BuildACLTree(thr, accountData, listener) if err != nil { t.Fatalf("should Build acl ACLState without err: %v", err) } @@ -146,7 +156,8 @@ func TestACLTree_ValidSnapshotBuild(t *testing.T) { SignKey: keychain.SigningKeys["A"], EncKey: keychain.EncryptionKeys["A"], } - tree, err := BuildACLTree(thr, accountData) + listener := &mockListener{} + tree, err := BuildACLTree(thr, accountData, listener) if err != nil { t.Fatalf("should Build acl ACLState without err: %v", err) } diff --git a/acltree/acltreebuilder.go b/acltree/acltreebuilder.go index 7c552407..dfb855fe 100644 --- a/acltree/acltreebuilder.go +++ b/acltree/acltreebuilder.go @@ -6,7 +6,6 @@ import ( "github.com/anytypeio/go-anytype-infrastructure-experiments/thread" "github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys" "github.com/anytypeio/go-anytype-infrastructure-experiments/util/slice" - gothread "github.com/textileio/go-threads/core/thread" ) type aclTreeBuilder struct { @@ -56,11 +55,7 @@ func (tb *aclTreeBuilder) Build() (*Tree, error) { } func (tb *aclTreeBuilder) buildTreeFromStart(heads []string) (err error) { - changes, possibleRoots, err := tb.dfsFromStart(heads) - if len(possibleRoots) == 0 { - return fmt.Errorf("cannot have Tree without root") - } - root, err := tb.getRoot(possibleRoots) + changes, root, err := tb.dfsFromStart(heads) if err != nil { return err } @@ -70,7 +65,8 @@ func (tb *aclTreeBuilder) buildTreeFromStart(heads []string) (err error) { return } -func (tb *aclTreeBuilder) dfsFromStart(heads []string) (buf []*Change, possibleRoots []*Change, err error) { +func (tb *aclTreeBuilder) dfsFromStart(heads []string) (buf []*Change, root *Change, err error) { + var possibleRoots []*Change stack := make([]string, len(heads), len(heads)*2) copy(stack, heads) @@ -98,32 +94,14 @@ func (tb *aclTreeBuilder) dfsFromStart(heads []string) (buf []*Change, possibleR possibleRoots = append(possibleRoots, ch) } } - return buf, possibleRoots, nil -} - -func (tb *aclTreeBuilder) getRoot(possibleRoots []*Change) (*Change, error) { - threadId, err := gothread.Decode(tb.thread.ID()) - if err != nil { - return nil, err - } - + header := tb.thread.Header() for _, r := range possibleRoots { - id := r.Content.Identity - sk, err := tb.signingPubKeyDecoder.DecodeFromString(id) - if err != nil { - continue - } - - res, err := thread.VerifyACLThreadID(sk, threadId) - if err != nil { - continue - } - - if res { - return r, nil + if r.Id == header.FirstChangeId { + return buf, r, nil } } - return nil, fmt.Errorf("could not find any root") + + return nil, nil, fmt.Errorf("could not find root change") } func (tb *aclTreeBuilder) getACLHeads(heads []string) (aclTreeHeads []string, err error) { diff --git a/acltree/treebuilder.go b/acltree/treebuilder.go index 0e3bc79d..944a44e1 100644 --- a/acltree/treebuilder.go +++ b/acltree/treebuilder.go @@ -9,7 +9,6 @@ import ( //"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/lib/logging" "github.com/anytypeio/go-anytype-infrastructure-experiments/util/slice" "github.com/prometheus/common/log" - gothread "github.com/textileio/go-threads/core/thread" ) var ( @@ -71,11 +70,7 @@ func (tb *treeBuilder) Build(fromStart bool) (*Tree, error) { } func (tb *treeBuilder) buildTreeFromStart(heads []string) (err error) { - changes, possibleRoots, err := tb.dfsFromStart(heads) - if len(possibleRoots) == 0 { - return fmt.Errorf("cannot have Tree without root") - } - root, err := tb.getRoot(possibleRoots) + changes, root, err := tb.dfsFromStart(heads) if err != nil { return err } @@ -85,7 +80,8 @@ func (tb *treeBuilder) buildTreeFromStart(heads []string) (err error) { return } -func (tb *treeBuilder) dfsFromStart(heads []string) (buf []*Change, possibleRoots []*Change, err error) { +func (tb *treeBuilder) dfsFromStart(heads []string) (buf []*Change, root *Change, err error) { + var possibleRoots []*Change stack := make([]string, len(heads), len(heads)*2) copy(stack, heads) @@ -113,7 +109,14 @@ func (tb *treeBuilder) dfsFromStart(heads []string) (buf []*Change, possibleRoot possibleRoots = append(possibleRoots, ch) } } - return buf, possibleRoots, nil + header := tb.thread.Header() + for _, r := range possibleRoots { + if r.Id == header.FirstChangeId { + return buf, r, nil + } + } + + return nil, nil, fmt.Errorf("could not find root change") } func (tb *treeBuilder) buildTree(heads []string, breakpoint string) (err error) { @@ -287,28 +290,3 @@ func (tb *treeBuilder) findCommonForTwoSnapshots(s1, s2 string) (s string, err e return s2, nil } - -func (tb *treeBuilder) getRoot(possibleRoots []*Change) (*Change, error) { - threadId, err := gothread.Decode(tb.thread.ID()) - if err != nil { - return nil, err - } - - for _, r := range possibleRoots { - id := r.Content.Identity - sk, err := tb.signingPubKeyDecoder.DecodeFromString(id) - if err != nil { - continue - } - - res, err := thread.VerifyACLThreadID(sk, threadId) - if err != nil { - continue - } - - if res { - return r, nil - } - } - return nil, fmt.Errorf("could not find any root") -} diff --git a/testutils/threadbuilder/invalidsnapshotexample.yml b/testutils/threadbuilder/invalidsnapshotexample.yml index e3877b47..e592f7d6 100644 --- a/testutils/threadbuilder/invalidsnapshotexample.yml +++ b/testutils/threadbuilder/invalidsnapshotexample.yml @@ -117,6 +117,9 @@ graph: baseSnapshot: A.1.2 aclHeads: [A.1.2] treeHeads: [A.1.2] +header: + firstChangeId: A.1.1 + isWorkspace: false orphans: - A.1.3 - B.1.2 diff --git a/testutils/threadbuilder/threadbuilder.go b/testutils/threadbuilder/threadbuilder.go index 72784452..9cfd25f8 100644 --- a/testutils/threadbuilder/threadbuilder.go +++ b/testutils/threadbuilder/threadbuilder.go @@ -13,6 +13,7 @@ import ( "github.com/anytypeio/go-anytype-infrastructure-experiments/aclchanges/pb" testpb "github.com/anytypeio/go-anytype-infrastructure-experiments/testutils/testchanges/pb" "github.com/anytypeio/go-anytype-infrastructure-experiments/thread" + threadpb "github.com/anytypeio/go-anytype-infrastructure-experiments/thread/pb" "github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys" ) @@ -34,6 +35,7 @@ type ThreadBuilder struct { heads []string orphans []string keychain *Keychain + header *threadpb.ThreadHeader } func NewThreadBuilder(keychain *Keychain) *ThreadBuilder { @@ -167,6 +169,10 @@ func (t *ThreadBuilder) GetUpdatedChanges() []*thread.RawChange { return res } +func (t *ThreadBuilder) Header() *threadpb.ThreadHeader { + return t.header +} + func (t *ThreadBuilder) getChange(changeId string, m map[string]*threadChange) *thread.RawChange { rec := m[changeId] @@ -510,3 +516,10 @@ func (t *ThreadBuilder) parseGraph(thread *YMLThread) { func (t *ThreadBuilder) parseOrphans(thread *YMLThread) { t.orphans = thread.Orphans } + +func (t *ThreadBuilder) parseHeader(thread *YMLThread) { + t.header = &threadpb.ThreadHeader{ + FirstChangeId: thread.Header.FirstChangeId, + IsWorkspace: thread.Header.IsWorkspace, + } +} diff --git a/testutils/threadbuilder/userjoinexample.yml b/testutils/threadbuilder/userjoinexample.yml index c2a0b11b..88f9ed92 100644 --- a/testutils/threadbuilder/userjoinexample.yml +++ b/testutils/threadbuilder/userjoinexample.yml @@ -99,6 +99,9 @@ graph: baseSnapshot: A.1.1 aclHeads: [B.1.1] treeHeads: [B.1.1] +header: + firstChangeId: A.1.1 + isWorkspace: false orphans: - "A.1.3" updatedChanges: diff --git a/testutils/threadbuilder/userjoinexampleupdate.yml b/testutils/threadbuilder/userjoinexampleupdate.yml index daf5d550..8e489521 100644 --- a/testutils/threadbuilder/userjoinexampleupdate.yml +++ b/testutils/threadbuilder/userjoinexampleupdate.yml @@ -101,6 +101,9 @@ graph: baseSnapshot: A.1.1 aclHeads: [B.1.1] treeHeads: [B.1.1] +header: + firstChangeId: A.1.1 + isWorkspace: false orphans: - "A.1.3" updatedChanges: diff --git a/testutils/threadbuilder/userremovebeforeexample.yml b/testutils/threadbuilder/userremovebeforeexample.yml index 7569ec04..c19ccaa6 100644 --- a/testutils/threadbuilder/userremovebeforeexample.yml +++ b/testutils/threadbuilder/userremovebeforeexample.yml @@ -104,3 +104,6 @@ graph: orphans: - "A.1.3" - "B.1.2" +header: + firstChangeId: A.1.1 + isWorkspace: false diff --git a/testutils/threadbuilder/userremoveexample.yml b/testutils/threadbuilder/userremoveexample.yml index 36a4a191..614a0687 100644 --- a/testutils/threadbuilder/userremoveexample.yml +++ b/testutils/threadbuilder/userremoveexample.yml @@ -104,3 +104,6 @@ graph: orphans: - "A.1.4" - "B.1.2" +header: + firstChangeId: A.1.1 + isWorkspace: false diff --git a/testutils/threadbuilder/validsnapshotexample.yml b/testutils/threadbuilder/validsnapshotexample.yml index 1fef3c35..9d5821ec 100644 --- a/testutils/threadbuilder/validsnapshotexample.yml +++ b/testutils/threadbuilder/validsnapshotexample.yml @@ -127,4 +127,7 @@ graph: orphans: - "A.1.3" - "B.1.2" +header: + firstChangeId: A.1.1 + isWorkspace: false diff --git a/testutils/threadbuilder/ymlentities.go b/testutils/threadbuilder/ymlentities.go index 68c7f3ac..c488ce0e 100644 --- a/testutils/threadbuilder/ymlentities.go +++ b/testutils/threadbuilder/ymlentities.go @@ -90,6 +90,11 @@ type Change struct { ReadKey string `yaml:"readKey"` } +type Header struct { + FirstChangeId string `yaml:"firstChangeId"` + IsWorkspace bool `yaml:"isWorkspace"` +} + type YMLThread struct { Description *ThreadDescription `yaml:"thread"` Changes []*Change `yaml:"changes"` @@ -102,4 +107,5 @@ type YMLThread struct { Heads []string `yaml:"heads"` Orphans []string `yaml:"orphans"` + Header *Header `yaml:"header"` }