diff --git a/acltree/acltree.go b/acltree/acltree.go index 276a4054..2a671d53 100644 --- a/acltree/acltree.go +++ b/acltree/acltree.go @@ -148,6 +148,10 @@ func (a *aclTree) rebuildFromThread(fromStart bool) error { return a.rebuildFromThread(true) } } + // TODO: there is a question how we can validate not only that the full tree is built correctly + // but also that the ACL prev ids are not messed up. I think we should probably compare the resulting + // acl state with the acl state which is built in aclTreeFromStart + err = a.aclStateBuilder.Init(a.fullTree) if err != nil { return err diff --git a/acltree/change.go b/acltree/change.go index 40a168d0..5f3121b3 100644 --- a/acltree/change.go +++ b/acltree/change.go @@ -2,6 +2,7 @@ package acltree import ( "fmt" + "github.com/anytypeio/go-anytype-infrastructure-experiments/thread" "github.com/gogo/protobuf/proto" "github.com/anytypeio/go-anytype-infrastructure-experiments/aclchanges/pb" @@ -46,6 +47,18 @@ func (ch *Change) IsACLChange() bool { return ch.Content.GetAclData() != nil } +func NewFromRawChange(rawChange *thread.RawChange) (*Change, error) { + unmarshalled := &pb.ACLChange{} + err := proto.Unmarshal(rawChange.Payload, unmarshalled) + if err != nil { + return nil, err + } + + ch := NewChange(rawChange.Id, unmarshalled) + ch.Sign = rawChange.Signature + return ch, nil +} + func NewChange(id string, ch *pb.ACLChange) *Change { return &Change{ Next: nil, diff --git a/testutils/threadbuilder/threadbuilder.go b/testutils/threadbuilder/threadbuilder.go index 8258adbf..313f209c 100644 --- a/testutils/threadbuilder/threadbuilder.go +++ b/testutils/threadbuilder/threadbuilder.go @@ -30,21 +30,25 @@ type threadChange struct { changesDataDecrypted []byte } +type updateUseCase struct { + changes map[string]*threadChange +} + type ThreadBuilder struct { - threadId string - allChanges map[string]*threadChange - updatedChanges map[string]*threadChange - heads []string - orphans []string - keychain *Keychain - header *threadpb.ThreadHeader + threadId string + allChanges map[string]*threadChange + updates map[string]*updateUseCase + heads []string + orphans []string + keychain *Keychain + header *threadpb.ThreadHeader } func NewThreadBuilder(keychain *Keychain) *ThreadBuilder { return &ThreadBuilder{ - allChanges: make(map[string]*threadChange), - updatedChanges: make(map[string]*threadChange), - keychain: keychain, + allChanges: make(map[string]*threadChange), + updates: make(map[string]*updateUseCase), + keychain: keychain, } } @@ -162,10 +166,11 @@ func (t *ThreadBuilder) GetChange(ctx context.Context, recordID string) (*thread return t.getChange(recordID, t.allChanges), nil } -func (t *ThreadBuilder) GetUpdatedChanges() []*thread.RawChange { +func (t *ThreadBuilder) GetUpdates(useCase string) []*thread.RawChange { var res []*thread.RawChange - for _, ch := range t.updatedChanges { - rawCh := t.getChange(ch.id, t.updatedChanges) + update := t.updates[useCase] + for _, ch := range update.changes { + rawCh := t.getChange(ch.id, update.changes) res = append(res, rawCh) } return res @@ -216,14 +221,10 @@ func (t *ThreadBuilder) Parse(thread *YMLThread) { t.allChanges[newChange.id] = newChange } - for _, ch := range thread.UpdatedChanges { - newChange := t.parseChange(ch) - t.updatedChanges[newChange.id] = newChange - } - t.parseGraph(thread) t.parseOrphans(thread) t.parseHeader(thread) + t.parseUpdates(thread.Updates) } func (t *ThreadBuilder) parseChange(ch *Change) *threadChange { @@ -500,6 +501,26 @@ func (t *ThreadBuilder) traverseFromHeads(f func(t *threadChange) error) error { return nil } +func (t *ThreadBuilder) parseUpdates(updates []*Update) { + for _, update := range updates { + useCase := &updateUseCase{ + changes: map[string]*threadChange{}, + } + for _, ch := range update.Changes { + newChange := t.parseChange(ch) + useCase.changes[newChange.id] = newChange + } + for _, node := range update.Graph { + rec := useCase.changes[node.Id] + rec.AclHeadIds = node.ACLHeads + rec.TreeHeadIds = node.TreeHeads + rec.SnapshotBaseId = node.BaseSnapshot + } + + t.updates[update.UseCase] = useCase + } +} + func (t *ThreadBuilder) parseGraph(thread *YMLThread) { for _, node := range thread.Graph { rec := t.allChanges[node.Id] @@ -507,13 +528,6 @@ func (t *ThreadBuilder) parseGraph(thread *YMLThread) { rec.TreeHeadIds = node.TreeHeads rec.SnapshotBaseId = node.BaseSnapshot } - - for _, node := range thread.UpdatedGraph { - rec := t.updatedChanges[node.Id] - rec.AclHeadIds = node.ACLHeads - rec.TreeHeadIds = node.TreeHeads - rec.SnapshotBaseId = node.BaseSnapshot - } } func (t *ThreadBuilder) parseOrphans(thread *YMLThread) { diff --git a/testutils/threadbuilder/ymlentities.go b/testutils/threadbuilder/ymlentities.go index c488ce0e..37e983b7 100644 --- a/testutils/threadbuilder/ymlentities.go +++ b/testutils/threadbuilder/ymlentities.go @@ -95,15 +95,20 @@ type Header struct { IsWorkspace bool `yaml:"isWorkspace"` } +type Update struct { + UseCase string `yaml:"useCase"` + Changes []*Change `yaml:"changes"` + Graph []*GraphNode `yaml:"graph"` +} + type YMLThread struct { - Description *ThreadDescription `yaml:"thread"` - Changes []*Change `yaml:"changes"` - UpdatedChanges []*Change `yaml:"updatedChanges"` + Description *ThreadDescription `yaml:"thread"` + Changes []*Change `yaml:"changes"` + Updates []*Update `yaml:"updates"` Keys Keys `yaml:"keys"` - Graph []*GraphNode `yaml:"graph"` - UpdatedGraph []*GraphNode `yaml:"updatedGraph"` + Graph []*GraphNode `yaml:"graph"` Heads []string `yaml:"heads"` Orphans []string `yaml:"orphans"` diff --git a/testutils/threadbuilder/ymlentities_test.go b/testutils/threadbuilder/ymlentities_test.go index 30c8f453..a702152b 100644 --- a/testutils/threadbuilder/ymlentities_test.go +++ b/testutils/threadbuilder/ymlentities_test.go @@ -6,7 +6,7 @@ import ( ) func Test_YamlParse(t *testing.T) { - tb, _ := NewThreadBuilderWithTestName("userjoinexample.yml") + tb, _ := NewThreadBuilderWithTestName("userjoinexampleupdate.yml") gr, _ := tb.Graph() fmt.Println(gr) } diff --git a/testutils/yamltests/userjoinexample.yml b/testutils/yamltests/userjoinexample.yml index 88f9ed92..60080ccc 100644 --- a/testutils/yamltests/userjoinexample.yml +++ b/testutils/yamltests/userjoinexample.yml @@ -104,15 +104,3 @@ header: isWorkspace: false orphans: - "A.1.3" -updatedChanges: - - id: B.1.3 - identity: B - changes: - - textAppend: - text: "second" - readKey: key.Read.1 -updatedGraph: - - id: B.1.3 - baseSnapshot: A.1.1 - aclHeads: [ B.1.1 ] - treeHeads: [ B.1.2 ] diff --git a/testutils/yamltests/userjoinexampleupdate.yml b/testutils/yamltests/userjoinexampleupdate.yml index 8e489521..cebfaf4a 100644 --- a/testutils/yamltests/userjoinexampleupdate.yml +++ b/testutils/yamltests/userjoinexampleupdate.yml @@ -106,31 +106,33 @@ header: isWorkspace: false orphans: - "A.1.3" -updatedChanges: - - id: B.1.3 - identity: B +updates: + - useCase: append changes: - - textAppend: - text: "second" - readKey: key.Read.1 - - id: A.1.4 - identity: A - aclChanges: - - userAdd: - identity: D - permission: writer - encryptionKey: key.Enc.D - encryptedReadKeys: [ key.Read.1 ] - changes: - - textAppend: - text: "second" - readKey: key.Read.1 -updatedGraph: - - id: B.1.3 - baseSnapshot: A.1.1 - aclHeads: [ B.1.1 ] - treeHeads: [ B.1.2 ] - - id: A.1.4 - baseSnapshot: A.1.1 - aclHeads: [ B.1.1 ] - treeHeads: [ B.1.3 ] + - id: B.1.3 + identity: B + changes: + - textAppend: + text: "second" + readKey: key.Read.1 + - id: A.1.4 + identity: A + aclChanges: + - userAdd: + identity: D + permission: writer + encryptionKey: key.Enc.D + encryptedReadKeys: [ key.Read.1 ] + changes: + - textAppend: + text: "second" + readKey: key.Read.1 + graph: + - id: B.1.3 + baseSnapshot: A.1.1 + aclHeads: [ B.1.1 ] + treeHeads: [ B.1.2 ] + - id: A.1.4 + baseSnapshot: A.1.1 + aclHeads: [ B.1.1 ] + treeHeads: [ B.1.3 ]