From 7174e0e08146952344d5915a7f27c87092c06fbf Mon Sep 17 00:00:00 2001 From: mcrakhman Date: Sun, 22 Jan 2023 22:16:14 +0100 Subject: [PATCH 1/9] Add exporter/viewer interfaces and empty methods, refactoring --- commonspace/object/acl/list/aclstate.go | 64 ++++++++--------- .../object/acl/liststorage/liststorage.go | 4 ++ .../object/tree/exporter/treeexporter.go | 26 +++++++ .../object/tree/exporter/treeviewer.go | 11 +++ .../object/tree/objecttree/changebuilder.go | 37 +++++++--- .../object/tree/objecttree/objecttree.go | 34 +-------- .../object/tree/objecttree/objecttree_test.go | 48 ++----------- .../object/tree/objecttree/rawloader.go | 4 +- .../tree/objecttree/rawtreevalidator.go | 16 ----- .../object/tree/objecttree/treebuilder.go | 2 +- .../object/tree/objecttree/treefactory.go | 72 ++++++++++++++++--- .../{changevalidator.go => treevalidator.go} | 21 ++++++ .../object/tree/treestorage/treestorage.go | 4 ++ commonspace/payloads.go | 4 +- 14 files changed, 203 insertions(+), 144 deletions(-) create mode 100644 commonspace/object/tree/exporter/treeexporter.go create mode 100644 commonspace/object/tree/exporter/treeviewer.go delete mode 100644 commonspace/object/tree/objecttree/rawtreevalidator.go rename commonspace/object/tree/objecttree/{changevalidator.go => treevalidator.go} (77%) diff --git a/commonspace/object/acl/list/aclstate.go b/commonspace/object/acl/list/aclstate.go index 54bf3f0d..9808dddf 100644 --- a/commonspace/object/acl/list/aclstate.go +++ b/commonspace/object/acl/list/aclstate.go @@ -5,7 +5,7 @@ import ( "errors" "fmt" "github.com/anytypeio/any-sync/app/logger" - aclrecordproto2 "github.com/anytypeio/any-sync/commonspace/object/acl/aclrecordproto" + aclrecordproto "github.com/anytypeio/any-sync/commonspace/object/acl/aclrecordproto" "github.com/anytypeio/any-sync/commonspace/object/keychain" "github.com/anytypeio/any-sync/util/keys" "github.com/anytypeio/any-sync/util/keys/asymmetric/encryptionkey" @@ -36,15 +36,15 @@ var ( type UserPermissionPair struct { Identity string - Permission aclrecordproto2.AclUserPermissions + Permission aclrecordproto.AclUserPermissions } type AclState struct { id string currentReadKeyHash uint64 userReadKeys map[uint64]*symmetric.Key - userStates map[string]*aclrecordproto2.AclUserState - userInvites map[string]*aclrecordproto2.AclUserInvite + userStates map[string]*aclrecordproto.AclUserState + userInvites map[string]*aclrecordproto.AclUserInvite encryptionKey encryptionkey.PrivKey signingKey signingkey.PrivKey totalReadKeys int @@ -70,8 +70,8 @@ func newAclStateWithKeys( signingKey: signingKey, encryptionKey: encryptionKey, userReadKeys: make(map[uint64]*symmetric.Key), - userStates: make(map[string]*aclrecordproto2.AclUserState), - userInvites: make(map[string]*aclrecordproto2.AclUserInvite), + userStates: make(map[string]*aclrecordproto.AclUserState), + userInvites: make(map[string]*aclrecordproto.AclUserInvite), permissionsAtRecord: make(map[string][]UserPermissionPair), }, nil } @@ -80,8 +80,8 @@ func newAclState(id string) *AclState { return &AclState{ id: id, userReadKeys: make(map[uint64]*symmetric.Key), - userStates: make(map[string]*aclrecordproto2.AclUserState), - userInvites: make(map[string]*aclrecordproto2.AclUserInvite), + userStates: make(map[string]*aclrecordproto.AclUserState), + userInvites: make(map[string]*aclrecordproto.AclUserInvite), permissionsAtRecord: make(map[string][]UserPermissionPair), } } @@ -128,7 +128,7 @@ func (st *AclState) applyRecord(record *AclRecord) (err error) { return } if record.Id == st.id { - root, ok := record.Model.(*aclrecordproto2.AclRoot) + root, ok := record.Model.(*aclrecordproto.AclRoot) if !ok { return ErrIncorrectRoot } @@ -137,14 +137,14 @@ func (st *AclState) applyRecord(record *AclRecord) (err error) { return } st.permissionsAtRecord[record.Id] = []UserPermissionPair{ - {Identity: string(root.Identity), Permission: aclrecordproto2.AclUserPermissions_Admin}, + {Identity: string(root.Identity), Permission: aclrecordproto.AclUserPermissions_Admin}, } return } - aclData := &aclrecordproto2.AclData{} + aclData := &aclrecordproto.AclData{} if record.Model != nil { - aclData = record.Model.(*aclrecordproto2.AclData) + aclData = record.Model.(*aclrecordproto.AclData) } else { err = proto.Unmarshal(record.Data, aclData) if err != nil { @@ -172,7 +172,7 @@ func (st *AclState) applyRecord(record *AclRecord) (err error) { return } -func (st *AclState) applyRoot(root *aclrecordproto2.AclRoot) (err error) { +func (st *AclState) applyRoot(root *aclrecordproto.AclRoot) (err error) { if st.signingKey != nil && st.encryptionKey != nil && st.identity == string(root.Identity) { err = st.saveReadKeyFromRoot(root) if err != nil { @@ -181,10 +181,10 @@ func (st *AclState) applyRoot(root *aclrecordproto2.AclRoot) (err error) { } // adding user to the list - userState := &aclrecordproto2.AclUserState{ + userState := &aclrecordproto.AclUserState{ Identity: root.Identity, EncryptionKey: root.EncryptionKey, - Permissions: aclrecordproto2.AclUserPermissions_Admin, + Permissions: aclrecordproto.AclUserPermissions_Admin, } st.currentReadKeyHash = root.CurrentReadKeyHash st.userStates[string(root.Identity)] = userState @@ -192,7 +192,7 @@ func (st *AclState) applyRoot(root *aclrecordproto2.AclRoot) (err error) { return } -func (st *AclState) saveReadKeyFromRoot(root *aclrecordproto2.AclRoot) (err error) { +func (st *AclState) saveReadKeyFromRoot(root *aclrecordproto.AclRoot) (err error) { var readKey *symmetric.Key if len(root.GetDerivationScheme()) != 0 { var encPrivKey []byte @@ -206,7 +206,7 @@ func (st *AclState) saveReadKeyFromRoot(root *aclrecordproto2.AclRoot) (err erro return } - readKey, err = aclrecordproto2.AclReadKeyDerive(signPrivKey, encPrivKey) + readKey, err = aclrecordproto.AclReadKeyDerive(signPrivKey, encPrivKey) if err != nil { return } @@ -230,7 +230,7 @@ func (st *AclState) saveReadKeyFromRoot(root *aclrecordproto2.AclRoot) (err erro return } -func (st *AclState) applyChangeData(changeData *aclrecordproto2.AclData, hash uint64, identity []byte) (err error) { +func (st *AclState) applyChangeData(changeData *aclrecordproto.AclData, hash uint64, identity []byte) (err error) { defer func() { if err != nil { return @@ -248,7 +248,7 @@ func (st *AclState) applyChangeData(changeData *aclrecordproto2.AclData, hash ui return } - if !st.HasPermission(identity, aclrecordproto2.AclUserPermissions_Admin) { + if !st.HasPermission(identity, aclrecordproto.AclUserPermissions_Admin) { err = fmt.Errorf("user %s must have admin permissions", identity) return } @@ -264,7 +264,7 @@ func (st *AclState) applyChangeData(changeData *aclrecordproto2.AclData, hash ui return nil } -func (st *AclState) applyChangeContent(ch *aclrecordproto2.AclContentValue) error { +func (st *AclState) applyChangeContent(ch *aclrecordproto.AclContentValue) error { switch { case ch.GetUserPermissionChange() != nil: return st.applyUserPermissionChange(ch.GetUserPermissionChange()) @@ -281,7 +281,7 @@ func (st *AclState) applyChangeContent(ch *aclrecordproto2.AclContentValue) erro } } -func (st *AclState) applyUserPermissionChange(ch *aclrecordproto2.AclUserPermissionChange) error { +func (st *AclState) applyUserPermissionChange(ch *aclrecordproto.AclUserPermissionChange) error { chIdentity := string(ch.Identity) state, exists := st.userStates[chIdentity] if !exists { @@ -292,12 +292,12 @@ func (st *AclState) applyUserPermissionChange(ch *aclrecordproto2.AclUserPermiss return nil } -func (st *AclState) applyUserInvite(ch *aclrecordproto2.AclUserInvite) error { +func (st *AclState) applyUserInvite(ch *aclrecordproto.AclUserInvite) error { st.userInvites[string(ch.AcceptPublicKey)] = ch return nil } -func (st *AclState) applyUserJoin(ch *aclrecordproto2.AclUserJoin) error { +func (st *AclState) applyUserJoin(ch *aclrecordproto.AclUserJoin) error { invite, exists := st.userInvites[string(ch.AcceptPubKey)] if !exists { return fmt.Errorf("no such invite with such public key %s", keys.EncodeBytesToString(ch.AcceptPubKey)) @@ -336,7 +336,7 @@ func (st *AclState) applyUserJoin(ch *aclrecordproto2.AclUserJoin) error { } // adding user to the list - userState := &aclrecordproto2.AclUserState{ + userState := &aclrecordproto.AclUserState{ Identity: ch.Identity, EncryptionKey: ch.EncryptionKey, Permissions: invite.Permissions, @@ -345,13 +345,13 @@ func (st *AclState) applyUserJoin(ch *aclrecordproto2.AclUserJoin) error { return nil } -func (st *AclState) applyUserAdd(ch *aclrecordproto2.AclUserAdd) error { +func (st *AclState) applyUserAdd(ch *aclrecordproto.AclUserAdd) error { chIdentity := string(ch.Identity) if _, exists := st.userStates[chIdentity]; exists { return ErrUserAlreadyExists } - st.userStates[chIdentity] = &aclrecordproto2.AclUserState{ + st.userStates[chIdentity] = &aclrecordproto.AclUserState{ Identity: ch.Identity, EncryptionKey: ch.EncryptionKey, Permissions: ch.Permissions, @@ -371,7 +371,7 @@ func (st *AclState) applyUserAdd(ch *aclrecordproto2.AclUserAdd) error { return nil } -func (st *AclState) applyUserRemove(ch *aclrecordproto2.AclUserRemove) error { +func (st *AclState) applyUserRemove(ch *aclrecordproto.AclUserRemove) error { chIdentity := string(ch.Identity) if chIdentity == st.identity { return ErrDocumentForbidden @@ -415,7 +415,7 @@ func (st *AclState) decryptReadKeyAndHash(msg []byte) (*symmetric.Key, uint64, e return key, hasher.Sum64(), nil } -func (st *AclState) HasPermission(identity []byte, permission aclrecordproto2.AclUserPermissions) bool { +func (st *AclState) HasPermission(identity []byte, permission aclrecordproto.AclUserPermissions) bool { state, exists := st.userStates[string(identity)] if !exists { return false @@ -424,22 +424,22 @@ func (st *AclState) HasPermission(identity []byte, permission aclrecordproto2.Ac return state.Permissions == permission } -func (st *AclState) isUserJoin(data *aclrecordproto2.AclData) bool { +func (st *AclState) isUserJoin(data *aclrecordproto.AclData) bool { // if we have a UserJoin, then it should always be the first one applied return data.GetAclContent() != nil && data.GetAclContent()[0].GetUserJoin() != nil } -func (st *AclState) isUserAdd(data *aclrecordproto2.AclData, identity []byte) bool { +func (st *AclState) isUserAdd(data *aclrecordproto.AclData, identity []byte) bool { // if we have a UserAdd, then it should always be the first one applied userAdd := data.GetAclContent()[0].GetUserAdd() return data.GetAclContent() != nil && userAdd != nil && bytes.Compare(userAdd.GetIdentity(), identity) == 0 } -func (st *AclState) UserStates() map[string]*aclrecordproto2.AclUserState { +func (st *AclState) UserStates() map[string]*aclrecordproto.AclUserState { return st.userStates } -func (st *AclState) Invite(acceptPubKey []byte) (invite *aclrecordproto2.AclUserInvite, err error) { +func (st *AclState) Invite(acceptPubKey []byte) (invite *aclrecordproto.AclUserInvite, err error) { invite, exists := st.userInvites[string(acceptPubKey)] if !exists { err = ErrNoSuchInvite diff --git a/commonspace/object/acl/liststorage/liststorage.go b/commonspace/object/acl/liststorage/liststorage.go index 673c31d5..1991ac0d 100644 --- a/commonspace/object/acl/liststorage/liststorage.go +++ b/commonspace/object/acl/liststorage/liststorage.go @@ -13,6 +13,10 @@ var ( ErrUnknownRecord = errors.New("record doesn't exist") ) +type Exporter interface { + ListStorage(root *aclrecordproto.RawAclRecordWithId) (ListStorage, error) +} + type ListStorage interface { Id() string Root() (*aclrecordproto.RawAclRecordWithId, error) diff --git a/commonspace/object/tree/exporter/treeexporter.go b/commonspace/object/tree/exporter/treeexporter.go new file mode 100644 index 00000000..8b70fd62 --- /dev/null +++ b/commonspace/object/tree/exporter/treeexporter.go @@ -0,0 +1,26 @@ +package exporter + +import ( + "github.com/anytypeio/any-sync/commonspace/object/acl/liststorage" + "github.com/anytypeio/any-sync/commonspace/object/tree/objecttree" + "github.com/anytypeio/any-sync/commonspace/object/tree/treestorage" +) + +type DataConverter interface { + Unmarshall(decrypted []byte) (any, error) + Convert(model any) (any, error) +} + +type TreeExporterParams struct { + ListStorageExporter liststorage.Exporter + TreeStorageExporter treestorage.Exporter + DataConverter DataConverter +} + +type TreeExporter interface { + ExportUnencrypted(tree objecttree.ReadableObjectTree) (err error) +} + +func NewTreeExporter(params TreeExporterParams) TreeExporter { + return nil +} diff --git a/commonspace/object/tree/exporter/treeviewer.go b/commonspace/object/tree/exporter/treeviewer.go new file mode 100644 index 00000000..510e458f --- /dev/null +++ b/commonspace/object/tree/exporter/treeviewer.go @@ -0,0 +1,11 @@ +package exporter + +import ( + "github.com/anytypeio/any-sync/commonspace/object/acl/liststorage" + "github.com/anytypeio/any-sync/commonspace/object/tree/objecttree" + "github.com/anytypeio/any-sync/commonspace/object/tree/treestorage" +) + +func ViewObjectTree(listStorage liststorage.ListStorage, treeStorage treestorage.TreeStorage) (objecttree.ReadableObjectTree, error) { + return nil, nil +} diff --git a/commonspace/object/tree/objecttree/changebuilder.go b/commonspace/object/tree/objecttree/changebuilder.go index 03f84b4a..f23648b0 100644 --- a/commonspace/object/tree/objecttree/changebuilder.go +++ b/commonspace/object/tree/objecttree/changebuilder.go @@ -35,12 +35,31 @@ type InitialContent struct { Timestamp int64 } +type nonVerifiableChangeBuilder struct { + ChangeBuilder +} + +func (c *nonVerifiableChangeBuilder) BuildRoot(payload InitialContent) (ch *Change, raw *treechangeproto.RawTreeChangeWithId, err error) { + return c.ChangeBuilder.BuildRoot(payload) +} + +func (c *nonVerifiableChangeBuilder) Unmarshall(rawChange *treechangeproto.RawTreeChangeWithId, verify bool) (ch *Change, err error) { + return c.ChangeBuilder.Unmarshall(rawChange, false) +} + +func (c *nonVerifiableChangeBuilder) Build(payload BuilderContent) (ch *Change, raw *treechangeproto.RawTreeChangeWithId, err error) { + return c.ChangeBuilder.Build(payload) +} + +func (c *nonVerifiableChangeBuilder) Marshall(ch *Change) (raw *treechangeproto.RawTreeChangeWithId, err error) { + return c.ChangeBuilder.Marshall(ch) +} + type ChangeBuilder interface { - ConvertFromRaw(rawIdChange *treechangeproto.RawTreeChangeWithId, verify bool) (ch *Change, err error) - BuildContent(payload BuilderContent) (ch *Change, raw *treechangeproto.RawTreeChangeWithId, err error) - BuildInitialContent(payload InitialContent) (ch *Change, raw *treechangeproto.RawTreeChangeWithId, err error) - BuildRaw(ch *Change) (*treechangeproto.RawTreeChangeWithId, error) - SetRootRawChange(rawIdChange *treechangeproto.RawTreeChangeWithId) + Unmarshall(rawIdChange *treechangeproto.RawTreeChangeWithId, verify bool) (ch *Change, err error) + Build(payload BuilderContent) (ch *Change, raw *treechangeproto.RawTreeChangeWithId, err error) + BuildRoot(payload InitialContent) (ch *Change, raw *treechangeproto.RawTreeChangeWithId, err error) + Marshall(ch *Change) (*treechangeproto.RawTreeChangeWithId, error) } type changeBuilder struct { @@ -52,7 +71,7 @@ func NewChangeBuilder(keys *keychain.Keychain, rootChange *treechangeproto.RawTr return &changeBuilder{keys: keys, rootChange: rootChange} } -func (c *changeBuilder) ConvertFromRaw(rawIdChange *treechangeproto.RawTreeChangeWithId, verify bool) (ch *Change, err error) { +func (c *changeBuilder) Unmarshall(rawIdChange *treechangeproto.RawTreeChangeWithId, verify bool) (ch *Change, err error) { if rawIdChange.GetRawChange() == nil { err = ErrEmptyChange return @@ -101,7 +120,7 @@ func (c *changeBuilder) SetRootRawChange(rawIdChange *treechangeproto.RawTreeCha c.rootChange = rawIdChange } -func (c *changeBuilder) BuildInitialContent(payload InitialContent) (ch *Change, rawIdChange *treechangeproto.RawTreeChangeWithId, err error) { +func (c *changeBuilder) BuildRoot(payload InitialContent) (ch *Change, rawIdChange *treechangeproto.RawTreeChangeWithId, err error) { change := &treechangeproto.RootChange{ AclHeadId: payload.AclHeadId, Timestamp: payload.Timestamp, @@ -145,7 +164,7 @@ func (c *changeBuilder) BuildInitialContent(payload InitialContent) (ch *Change, return } -func (c *changeBuilder) BuildContent(payload BuilderContent) (ch *Change, rawIdChange *treechangeproto.RawTreeChangeWithId, err error) { +func (c *changeBuilder) Build(payload BuilderContent) (ch *Change, rawIdChange *treechangeproto.RawTreeChangeWithId, err error) { change := &treechangeproto.TreeChange{ TreeHeadIds: payload.TreeHeadIds, AclHeadId: payload.AclHeadId, @@ -200,7 +219,7 @@ func (c *changeBuilder) BuildContent(payload BuilderContent) (ch *Change, rawIdC return } -func (c *changeBuilder) BuildRaw(ch *Change) (raw *treechangeproto.RawTreeChangeWithId, err error) { +func (c *changeBuilder) Marshall(ch *Change) (raw *treechangeproto.RawTreeChangeWithId, err error) { if ch.Id == c.rootChange.Id { return c.rootChange, nil } diff --git a/commonspace/object/tree/objecttree/objecttree.go b/commonspace/object/tree/objecttree/objecttree.go index 9e5141b0..ee513be1 100644 --- a/commonspace/object/tree/objecttree/objecttree.go +++ b/commonspace/object/tree/objecttree/objecttree.go @@ -6,7 +6,6 @@ import ( "errors" "github.com/anytypeio/any-sync/commonspace/object/acl/aclrecordproto" list "github.com/anytypeio/any-sync/commonspace/object/acl/list" - "github.com/anytypeio/any-sync/commonspace/object/keychain" "github.com/anytypeio/any-sync/commonspace/object/tree/treechangeproto" "github.com/anytypeio/any-sync/commonspace/object/tree/treestorage" "github.com/anytypeio/any-sync/util/keys/symmetric" @@ -102,33 +101,6 @@ type objectTree struct { sync.RWMutex } -type objectTreeDeps struct { - changeBuilder ChangeBuilder - treeBuilder *treeBuilder - treeStorage treestorage.TreeStorage - validator ObjectTreeValidator - rawChangeLoader *rawChangeLoader - aclList list.AclList -} - -func defaultObjectTreeDeps( - rootChange *treechangeproto.RawTreeChangeWithId, - treeStorage treestorage.TreeStorage, - aclList list.AclList) objectTreeDeps { - - keychain := keychain.NewKeychain() - changeBuilder := NewChangeBuilder(keychain, rootChange) - treeBuilder := newTreeBuilder(treeStorage, changeBuilder) - return objectTreeDeps{ - changeBuilder: changeBuilder, - treeBuilder: treeBuilder, - treeStorage: treeStorage, - validator: newTreeValidator(), - rawChangeLoader: newRawChangeLoader(treeStorage, changeBuilder), - aclList: aclList, - } -} - func (ot *objectTree) rebuildFromStorage(theirHeads []string, newChanges []*Change) (err error) { ot.treeBuilder.Reset() @@ -179,7 +151,7 @@ func (ot *objectTree) AddContent(ctx context.Context, content SignableChangeCont oldHeads := make([]string, 0, len(ot.tree.Heads())) oldHeads = append(oldHeads, ot.tree.Heads()...) - objChange, rawChange, err := ot.changeBuilder.BuildContent(payload) + objChange, rawChange, err := ot.changeBuilder.Build(payload) if content.IsSnapshot { // clearing tree, because we already saved everything in the last snapshot ot.tree = &Tree{} @@ -293,7 +265,7 @@ func (ot *objectTree) addRawChanges(ctx context.Context, changesPayload RawChang if unAttached, exists := ot.tree.unAttached[ch.Id]; exists { change = unAttached } else { - change, err = ot.changeBuilder.ConvertFromRaw(ch, true) + change, err = ot.changeBuilder.Unmarshall(ch, true) if err != nil { return } @@ -444,7 +416,7 @@ func (ot *objectTree) createAddResult(oldHeads []string, mode Mode, treeChangesA // if we got some changes that we need to convert to raw if _, exists := alreadyConverted[ch]; !exists { var raw *treechangeproto.RawTreeChangeWithId - raw, err = ot.changeBuilder.BuildRaw(ch) + raw, err = ot.changeBuilder.Marshall(ch) if err != nil { return } diff --git a/commonspace/object/tree/objecttree/objecttree_test.go b/commonspace/object/tree/objecttree/objecttree_test.go index 24506bf0..ee8989e9 100644 --- a/commonspace/object/tree/objecttree/objecttree_test.go +++ b/commonspace/object/tree/objecttree/objecttree_test.go @@ -59,44 +59,10 @@ func (c *mockChangeCreator) createNewTreeStorage(treeId, aclHeadId string) trees return treeStorage } -type mockChangeBuilder struct { - originalBuilder ChangeBuilder -} - -func (c *mockChangeBuilder) BuildInitialContent(payload InitialContent) (ch *Change, raw *treechangeproto.RawTreeChangeWithId, err error) { - panic("implement me") -} - -func (c *mockChangeBuilder) SetRootRawChange(rawIdChange *treechangeproto.RawTreeChangeWithId) { - c.originalBuilder.SetRootRawChange(rawIdChange) -} - -func (c *mockChangeBuilder) ConvertFromRaw(rawChange *treechangeproto.RawTreeChangeWithId, verify bool) (ch *Change, err error) { - return c.originalBuilder.ConvertFromRaw(rawChange, false) -} - -func (c *mockChangeBuilder) BuildContent(payload BuilderContent) (ch *Change, raw *treechangeproto.RawTreeChangeWithId, err error) { - panic("implement me") -} - -func (c *mockChangeBuilder) BuildRaw(ch *Change) (raw *treechangeproto.RawTreeChangeWithId, err error) { - return c.originalBuilder.BuildRaw(ch) -} - -type mockChangeValidator struct{} - -func (m *mockChangeValidator) ValidateNewChanges(tree *Tree, aclList list.AclList, newChanges []*Change) error { - return nil -} - -func (m *mockChangeValidator) ValidateFullTree(tree *Tree, aclList list.AclList) error { - return nil -} - type testTreeContext struct { aclList list.AclList treeStorage treestorage.TreeStorage - changeBuilder *mockChangeBuilder + changeBuilder ChangeBuilder changeCreator *mockChangeCreator objTree ObjectTree } @@ -115,15 +81,15 @@ func prepareTreeDeps(aclList list.AclList) (*mockChangeCreator, objectTreeDeps) changeCreator := &mockChangeCreator{} treeStorage := changeCreator.createNewTreeStorage("0", aclList.Head().Id) root, _ := treeStorage.Root() - changeBuilder := &mockChangeBuilder{ - originalBuilder: NewChangeBuilder(nil, root), + changeBuilder := &nonVerifiableChangeBuilder{ + ChangeBuilder: NewChangeBuilder(nil, root), } deps := objectTreeDeps{ changeBuilder: changeBuilder, treeBuilder: newTreeBuilder(treeStorage, changeBuilder), treeStorage: treeStorage, rawChangeLoader: newRawChangeLoader(treeStorage, changeBuilder), - validator: &mockChangeValidator{}, + validator: &noOpTreeValidator{}, aclList: aclList, } return changeCreator, deps @@ -133,15 +99,15 @@ func prepareTreeContext(t *testing.T, aclList list.AclList) testTreeContext { changeCreator := &mockChangeCreator{} treeStorage := changeCreator.createNewTreeStorage("0", aclList.Head().Id) root, _ := treeStorage.Root() - changeBuilder := &mockChangeBuilder{ - originalBuilder: NewChangeBuilder(nil, root), + changeBuilder := &nonVerifiableChangeBuilder{ + ChangeBuilder: NewChangeBuilder(nil, root), } deps := objectTreeDeps{ changeBuilder: changeBuilder, treeBuilder: newTreeBuilder(treeStorage, changeBuilder), treeStorage: treeStorage, rawChangeLoader: newRawChangeLoader(treeStorage, changeBuilder), - validator: &mockChangeValidator{}, + validator: &noOpTreeValidator{}, aclList: aclList, } diff --git a/commonspace/object/tree/objecttree/rawloader.go b/commonspace/object/tree/objecttree/rawloader.go index 970f03a5..cae32cb3 100644 --- a/commonspace/object/tree/objecttree/rawloader.go +++ b/commonspace/object/tree/objecttree/rawloader.go @@ -39,7 +39,7 @@ func (r *rawChangeLoader) LoadFromTree(t *Tree, breakpoints []string) ([]*treech convert := func(chs []*Change) (rawChanges []*treechangeproto.RawTreeChangeWithId, err error) { for _, ch := range chs { var raw *treechangeproto.RawTreeChangeWithId - raw, err = r.changeBuilder.BuildRaw(ch) + raw, err = r.changeBuilder.Marshall(ch) if err != nil { return } @@ -226,7 +226,7 @@ func (r *rawChangeLoader) loadEntry(id string) (entry rawCacheEntry, err error) return } - change, err := r.changeBuilder.ConvertFromRaw(rawChange, false) + change, err := r.changeBuilder.Unmarshall(rawChange, false) if err != nil { return } diff --git a/commonspace/object/tree/objecttree/rawtreevalidator.go b/commonspace/object/tree/objecttree/rawtreevalidator.go deleted file mode 100644 index 72673e10..00000000 --- a/commonspace/object/tree/objecttree/rawtreevalidator.go +++ /dev/null @@ -1,16 +0,0 @@ -package objecttree - -import ( - "github.com/anytypeio/any-sync/commonspace/object/acl/list" - "github.com/anytypeio/any-sync/commonspace/object/tree/treestorage" -) - -func ValidateRawTree(payload treestorage.TreeStorageCreatePayload, aclList list.AclList) (err error) { - treeStorage, err := treestorage.NewInMemoryTreeStorage(payload.RootRawChange, payload.Heads, payload.Changes) - if err != nil { - return - } - - _, err = BuildObjectTree(treeStorage, aclList) - return -} diff --git a/commonspace/object/tree/objecttree/treebuilder.go b/commonspace/object/tree/objecttree/treebuilder.go index ab5592c7..5ec64b9a 100644 --- a/commonspace/object/tree/objecttree/treebuilder.go +++ b/commonspace/object/tree/objecttree/treebuilder.go @@ -154,7 +154,7 @@ func (tb *treeBuilder) loadChange(id string) (ch *Change, err error) { return nil, err } - ch, err = tb.builder.ConvertFromRaw(change, true) + ch, err = tb.builder.Unmarshall(change, true) if err != nil { return nil, err } diff --git a/commonspace/object/tree/objecttree/treefactory.go b/commonspace/object/tree/objecttree/treefactory.go index 0f8a337d..2dd0d9e0 100644 --- a/commonspace/object/tree/objecttree/treefactory.go +++ b/commonspace/object/tree/objecttree/treefactory.go @@ -19,6 +19,56 @@ type ObjectTreeCreatePayload struct { IsEncrypted bool } +type HistoryTreeParams struct { + TreeStorage treestorage.TreeStorage + AclList list.AclList + BeforeId string + IncludeBeforeId bool +} + +type objectTreeDeps struct { + changeBuilder ChangeBuilder + treeBuilder *treeBuilder + treeStorage treestorage.TreeStorage + validator ObjectTreeValidator + rawChangeLoader *rawChangeLoader + aclList list.AclList +} + +func defaultObjectTreeDeps( + rootChange *treechangeproto.RawTreeChangeWithId, + treeStorage treestorage.TreeStorage, + aclList list.AclList) objectTreeDeps { + + keychain := keychain.NewKeychain() + changeBuilder := NewChangeBuilder(keychain, rootChange) + treeBuilder := newTreeBuilder(treeStorage, changeBuilder) + return objectTreeDeps{ + changeBuilder: changeBuilder, + treeBuilder: treeBuilder, + treeStorage: treeStorage, + validator: newTreeValidator(), + rawChangeLoader: newRawChangeLoader(treeStorage, changeBuilder), + aclList: aclList, + } +} + +func nonVerifiableTreeDeps( + rootChange *treechangeproto.RawTreeChangeWithId, + treeStorage treestorage.TreeStorage, + aclList list.AclList) objectTreeDeps { + changeBuilder := &nonVerifiableChangeBuilder{NewChangeBuilder(nil, rootChange)} + treeBuilder := newTreeBuilder(treeStorage, changeBuilder) + return objectTreeDeps{ + changeBuilder: changeBuilder, + treeBuilder: treeBuilder, + treeStorage: treeStorage, + validator: &noOpTreeValidator{}, + rawChangeLoader: newRawChangeLoader(treeStorage, changeBuilder), + aclList: aclList, + } +} + func CreateObjectTreeRoot(payload ObjectTreeCreatePayload, aclList list.AclList) (root *treechangeproto.RawTreeChangeWithId, err error) { bytes := make([]byte, 32) _, err = rand.Read(bytes) @@ -41,6 +91,15 @@ func BuildObjectTree(treeStorage treestorage.TreeStorage, aclList list.AclList) return buildObjectTree(deps) } +func BuildNonVerifiableTree(treeStorage treestorage.TreeStorage, aclList list.AclList) (ObjectTree, error) { + rootChange, err := treeStorage.Root() + if err != nil { + return nil, err + } + deps := nonVerifiableTreeDeps(rootChange, treeStorage, aclList) + return buildObjectTree(deps) +} + func BuildHistoryTree(params HistoryTreeParams) (HistoryTree, error) { rootChange, err := params.TreeStorage.Root() if err != nil { @@ -115,7 +174,7 @@ func createObjectTreeRoot( Seed: seed, } - _, root, err = NewChangeBuilder(keychain.NewKeychain(), nil).BuildInitialContent(cnt) + _, root, err = NewChangeBuilder(keychain.NewKeychain(), nil).BuildRoot(cnt) return } @@ -146,7 +205,7 @@ func buildObjectTree(deps objectTreeDeps) (ObjectTree, error) { } // verifying root - header, err := objTree.changeBuilder.ConvertFromRaw(objTree.rawRoot, true) + header, err := objTree.changeBuilder.Unmarshall(objTree.rawRoot, true) if err != nil { return nil, err } @@ -155,13 +214,6 @@ func buildObjectTree(deps objectTreeDeps) (ObjectTree, error) { return objTree, nil } -type HistoryTreeParams struct { - TreeStorage treestorage.TreeStorage - AclList list.AclList - BeforeId string - IncludeBeforeId bool -} - func buildHistoryTree(deps objectTreeDeps, params HistoryTreeParams) (ht HistoryTree, err error) { objTree := &objectTree{ treeStorage: deps.treeStorage, @@ -188,7 +240,7 @@ func buildHistoryTree(deps objectTreeDeps, params HistoryTreeParams) (ht History return nil, err } - header, err := objTree.changeBuilder.ConvertFromRaw(objTree.rawRoot, false) + header, err := objTree.changeBuilder.Unmarshall(objTree.rawRoot, false) if err != nil { return nil, err } diff --git a/commonspace/object/tree/objecttree/changevalidator.go b/commonspace/object/tree/objecttree/treevalidator.go similarity index 77% rename from commonspace/object/tree/objecttree/changevalidator.go rename to commonspace/object/tree/objecttree/treevalidator.go index 12a0f4a4..55adc6a7 100644 --- a/commonspace/object/tree/objecttree/changevalidator.go +++ b/commonspace/object/tree/objecttree/treevalidator.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/anytypeio/any-sync/commonspace/object/acl/aclrecordproto" "github.com/anytypeio/any-sync/commonspace/object/acl/list" + "github.com/anytypeio/any-sync/commonspace/object/tree/treestorage" ) type ObjectTreeValidator interface { @@ -13,6 +14,16 @@ type ObjectTreeValidator interface { ValidateNewChanges(tree *Tree, aclList list.AclList, newChanges []*Change) error } +type noOpTreeValidator struct{} + +func (n *noOpTreeValidator) ValidateFullTree(tree *Tree, aclList list.AclList) error { + return nil +} + +func (n *noOpTreeValidator) ValidateNewChanges(tree *Tree, aclList list.AclList, newChanges []*Change) error { + return nil +} + type objectTreeValidator struct{} func newTreeValidator() ObjectTreeValidator { @@ -75,3 +86,13 @@ func (v *objectTreeValidator) validateChange(tree *Tree, aclList list.AclList, c } return } + +func ValidateRawTree(payload treestorage.TreeStorageCreatePayload, aclList list.AclList) (err error) { + treeStorage, err := treestorage.NewInMemoryTreeStorage(payload.RootRawChange, payload.Heads, payload.Changes) + if err != nil { + return + } + + _, err = BuildObjectTree(treeStorage, aclList) + return +} diff --git a/commonspace/object/tree/treestorage/treestorage.go b/commonspace/object/tree/treestorage/treestorage.go index b0051d76..14fbad78 100644 --- a/commonspace/object/tree/treestorage/treestorage.go +++ b/commonspace/object/tree/treestorage/treestorage.go @@ -19,6 +19,10 @@ type TreeStorageCreatePayload struct { Heads []string } +type Exporter interface { + TreeStorage(root *treechangeproto.RawTreeChangeWithId) (TreeStorage, error) +} + type TreeStorageCreatorFunc = func(payload TreeStorageCreatePayload) (TreeStorage, error) type TreeStorage interface { diff --git a/commonspace/payloads.go b/commonspace/payloads.go index 29e9568e..c6d25503 100644 --- a/commonspace/payloads.go +++ b/commonspace/payloads.go @@ -95,7 +95,7 @@ func storagePayloadForSpaceCreate(payload SpaceCreatePayload) (storagePayload sp return } - _, settingsRoot, err := builder.BuildInitialContent(objecttree.InitialContent{ + _, settingsRoot, err := builder.BuildRoot(objecttree.InitialContent{ AclHeadId: rawWithId.Id, Identity: aclRoot.Identity, SigningKey: payload.SigningKey, @@ -196,7 +196,7 @@ func storagePayloadForSpaceDerive(payload SpaceDerivePayload) (storagePayload sp } builder := objecttree.NewChangeBuilder(keychain.NewKeychain(), nil) - _, settingsRoot, err := builder.BuildInitialContent(objecttree.InitialContent{ + _, settingsRoot, err := builder.BuildRoot(objecttree.InitialContent{ AclHeadId: rawWithId.Id, Identity: aclRoot.Identity, SigningKey: payload.SigningKey, From ed615379c45d1ddbbaf625491c3359b5bd6728cd Mon Sep 17 00:00:00 2001 From: mcrakhman Date: Tue, 24 Jan 2023 17:04:38 +0100 Subject: [PATCH 2/9] Change dataconverter interface --- commonspace/object/tree/exporter/treeexporter.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/commonspace/object/tree/exporter/treeexporter.go b/commonspace/object/tree/exporter/treeexporter.go index 8b70fd62..3f21ff28 100644 --- a/commonspace/object/tree/exporter/treeexporter.go +++ b/commonspace/object/tree/exporter/treeexporter.go @@ -8,7 +8,7 @@ import ( type DataConverter interface { Unmarshall(decrypted []byte) (any, error) - Convert(model any) (any, error) + Marshall(model any) ([]byte, error) } type TreeExporterParams struct { From 60b2c996600e3e2580a689b96804f60f11513037 Mon Sep 17 00:00:00 2001 From: mcrakhman Date: Wed, 25 Jan 2023 10:13:01 +0100 Subject: [PATCH 3/9] Change interfaces for import tree --- .../tree/exporter/{treeviewer.go => treeimport.go} | 9 ++++++++- commonspace/object/tree/objecttree/treefactory.go | 8 ++++---- 2 files changed, 12 insertions(+), 5 deletions(-) rename commonspace/object/tree/exporter/{treeviewer.go => treeimport.go} (50%) diff --git a/commonspace/object/tree/exporter/treeviewer.go b/commonspace/object/tree/exporter/treeimport.go similarity index 50% rename from commonspace/object/tree/exporter/treeviewer.go rename to commonspace/object/tree/exporter/treeimport.go index 510e458f..69384b6a 100644 --- a/commonspace/object/tree/exporter/treeviewer.go +++ b/commonspace/object/tree/exporter/treeimport.go @@ -6,6 +6,13 @@ import ( "github.com/anytypeio/any-sync/commonspace/object/tree/treestorage" ) -func ViewObjectTree(listStorage liststorage.ListStorage, treeStorage treestorage.TreeStorage) (objecttree.ReadableObjectTree, error) { +type TreeImportParams struct { + ListStorage liststorage.ListStorage + TreeStorage treestorage.TreeStorage + BeforeId string + IncludeBeforeId bool +} + +func ImportHistoryTree(params TreeImportParams) (objecttree.ReadableObjectTree, error) { return nil, nil } diff --git a/commonspace/object/tree/objecttree/treefactory.go b/commonspace/object/tree/objecttree/treefactory.go index 2dd0d9e0..8eb5b466 100644 --- a/commonspace/object/tree/objecttree/treefactory.go +++ b/commonspace/object/tree/objecttree/treefactory.go @@ -91,13 +91,13 @@ func BuildObjectTree(treeStorage treestorage.TreeStorage, aclList list.AclList) return buildObjectTree(deps) } -func BuildNonVerifiableTree(treeStorage treestorage.TreeStorage, aclList list.AclList) (ObjectTree, error) { - rootChange, err := treeStorage.Root() +func BuildNonVerifiableHistoryTree(params HistoryTreeParams) (HistoryTree, error) { + rootChange, err := params.TreeStorage.Root() if err != nil { return nil, err } - deps := nonVerifiableTreeDeps(rootChange, treeStorage, aclList) - return buildObjectTree(deps) + deps := nonVerifiableTreeDeps(rootChange, params.TreeStorage, params.AclList) + return buildHistoryTree(deps, params) } func BuildHistoryTree(params HistoryTreeParams) (HistoryTree, error) { From 348b94a55492536fe57fc8b2f7438deabddf7b26 Mon Sep 17 00:00:00 2001 From: mcrakhman Date: Wed, 25 Jan 2023 11:26:37 +0100 Subject: [PATCH 4/9] Change debug api for tree --- .../mock_objecttree/mock_objecttree.go | 14 +++++------ .../object/tree/objecttree/objecttree.go | 6 ++--- .../object/tree/objecttree/objecttreedebug.go | 25 +++++++++++++++++++ .../{treefactory.go => objecttreefactory.go} | 0 ...reevalidator.go => objecttreevalidator.go} | 0 .../synctree/mock_synctree/mock_synctree.go | 14 +++++------ 6 files changed, 42 insertions(+), 17 deletions(-) create mode 100644 commonspace/object/tree/objecttree/objecttreedebug.go rename commonspace/object/tree/objecttree/{treefactory.go => objecttreefactory.go} (100%) rename commonspace/object/tree/objecttree/{treevalidator.go => objecttreevalidator.go} (100%) diff --git a/commonspace/object/tree/objecttree/mock_objecttree/mock_objecttree.go b/commonspace/object/tree/objecttree/mock_objecttree/mock_objecttree.go index 1198794c..c8dc3841 100644 --- a/commonspace/object/tree/objecttree/mock_objecttree/mock_objecttree.go +++ b/commonspace/object/tree/objecttree/mock_objecttree/mock_objecttree.go @@ -96,19 +96,19 @@ func (mr *MockObjectTreeMockRecorder) Close() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockObjectTree)(nil).Close)) } -// DebugDump mocks base method. -func (m *MockObjectTree) DebugDump(arg0 objecttree.DescriptionParser) (string, error) { +// Debug mocks base method. +func (m *MockObjectTree) Debug(arg0 objecttree.DescriptionParser) (objecttree.DebugInfo, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DebugDump", arg0) - ret0, _ := ret[0].(string) + ret := m.ctrl.Call(m, "Debug", arg0) + ret0, _ := ret[0].(objecttree.DebugInfo) ret1, _ := ret[1].(error) return ret0, ret1 } -// DebugDump indicates an expected call of DebugDump. -func (mr *MockObjectTreeMockRecorder) DebugDump(arg0 interface{}) *gomock.Call { +// Debug indicates an expected call of Debug. +func (mr *MockObjectTreeMockRecorder) Debug(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DebugDump", reflect.TypeOf((*MockObjectTree)(nil).DebugDump), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Debug", reflect.TypeOf((*MockObjectTree)(nil).Debug), arg0) } // Delete mocks base method. diff --git a/commonspace/object/tree/objecttree/objecttree.go b/commonspace/object/tree/objecttree/objecttree.go index ee513be1..bc806522 100644 --- a/commonspace/object/tree/objecttree/objecttree.go +++ b/commonspace/object/tree/objecttree/objecttree.go @@ -55,7 +55,7 @@ type ReadableObjectTree interface { HasChanges(...string) bool GetChange(string) (*Change, error) - DebugDump(parser DescriptionParser) (string, error) + Debug(parser DescriptionParser) (DebugInfo, error) IterateRoot(convert ChangeConvertFunc, iterate ChangeIterateFunc) error IterateFrom(id string, convert ChangeConvertFunc, iterate ChangeIterateFunc) error } @@ -609,6 +609,6 @@ func (ot *objectTree) validateTree(newChanges []*Change) error { return ot.validator.ValidateNewChanges(ot.tree, ot.aclList, newChanges) } -func (ot *objectTree) DebugDump(parser DescriptionParser) (string, error) { - return ot.tree.Graph(parser) +func (ot *objectTree) Debug(parser DescriptionParser) (DebugInfo, error) { + return objectTreeDebug{}.debugInfo(ot, parser) } diff --git a/commonspace/object/tree/objecttree/objecttreedebug.go b/commonspace/object/tree/objecttree/objecttreedebug.go new file mode 100644 index 00000000..ea59c2e8 --- /dev/null +++ b/commonspace/object/tree/objecttree/objecttreedebug.go @@ -0,0 +1,25 @@ +package objecttree + +type objectTreeDebug struct { +} + +type DebugInfo struct { + TreeLen int + TreeString string + Graphviz string + Heads []string + SnapshotPath []string +} + +func (o objectTreeDebug) debugInfo(ot *objectTree, parser DescriptionParser) (di DebugInfo, err error) { + di = DebugInfo{} + di.Graphviz, err = ot.tree.Graph(parser) + if err != nil { + return + } + di.TreeString = ot.tree.String() + di.TreeLen = ot.tree.Len() + di.Heads = ot.Heads() + di.SnapshotPath = ot.SnapshotPath() + return +} diff --git a/commonspace/object/tree/objecttree/treefactory.go b/commonspace/object/tree/objecttree/objecttreefactory.go similarity index 100% rename from commonspace/object/tree/objecttree/treefactory.go rename to commonspace/object/tree/objecttree/objecttreefactory.go diff --git a/commonspace/object/tree/objecttree/treevalidator.go b/commonspace/object/tree/objecttree/objecttreevalidator.go similarity index 100% rename from commonspace/object/tree/objecttree/treevalidator.go rename to commonspace/object/tree/objecttree/objecttreevalidator.go diff --git a/commonspace/object/tree/synctree/mock_synctree/mock_synctree.go b/commonspace/object/tree/synctree/mock_synctree/mock_synctree.go index c5b05925..73335d45 100644 --- a/commonspace/object/tree/synctree/mock_synctree/mock_synctree.go +++ b/commonspace/object/tree/synctree/mock_synctree/mock_synctree.go @@ -221,19 +221,19 @@ func (mr *MockSyncTreeMockRecorder) Close() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockSyncTree)(nil).Close)) } -// DebugDump mocks base method. -func (m *MockSyncTree) DebugDump(arg0 objecttree.DescriptionParser) (string, error) { +// Debug mocks base method. +func (m *MockSyncTree) Debug(arg0 objecttree.DescriptionParser) (objecttree.DebugInfo, error) { m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DebugDump", arg0) - ret0, _ := ret[0].(string) + ret := m.ctrl.Call(m, "Debug", arg0) + ret0, _ := ret[0].(objecttree.DebugInfo) ret1, _ := ret[1].(error) return ret0, ret1 } -// DebugDump indicates an expected call of DebugDump. -func (mr *MockSyncTreeMockRecorder) DebugDump(arg0 interface{}) *gomock.Call { +// Debug indicates an expected call of Debug. +func (mr *MockSyncTreeMockRecorder) Debug(arg0 interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DebugDump", reflect.TypeOf((*MockSyncTree)(nil).DebugDump), arg0) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Debug", reflect.TypeOf((*MockSyncTree)(nil).Debug), arg0) } // Delete mocks base method. From dffb418e600a0ded91ae1b891886a9bde8375122 Mon Sep 17 00:00:00 2001 From: mcrakhman Date: Wed, 25 Jan 2023 21:20:23 +0100 Subject: [PATCH 5/9] Add tree exporter --- .../object/tree/exporter/treeexporter.go | 55 ++++++++++++++++++- .../object/tree/exporter/treeimport.go | 14 ++++- .../mock_objecttree/mock_objecttree.go | 15 +++++ .../object/tree/objecttree/objecttree.go | 6 ++ .../synctree/mock_synctree/mock_synctree.go | 15 +++++ 5 files changed, 101 insertions(+), 4 deletions(-) diff --git a/commonspace/object/tree/exporter/treeexporter.go b/commonspace/object/tree/exporter/treeexporter.go index 3f21ff28..01d41f96 100644 --- a/commonspace/object/tree/exporter/treeexporter.go +++ b/commonspace/object/tree/exporter/treeexporter.go @@ -2,7 +2,9 @@ package exporter import ( "github.com/anytypeio/any-sync/commonspace/object/acl/liststorage" + "github.com/anytypeio/any-sync/commonspace/object/keychain" "github.com/anytypeio/any-sync/commonspace/object/tree/objecttree" + "github.com/anytypeio/any-sync/commonspace/object/tree/treechangeproto" "github.com/anytypeio/any-sync/commonspace/object/tree/treestorage" ) @@ -21,6 +23,55 @@ type TreeExporter interface { ExportUnencrypted(tree objecttree.ReadableObjectTree) (err error) } -func NewTreeExporter(params TreeExporterParams) TreeExporter { - return nil +type treeExporter struct { + listExporter liststorage.Exporter + treeExporter treestorage.Exporter + converter DataConverter +} + +func NewTreeExporter(params TreeExporterParams) TreeExporter { + return &treeExporter{ + listExporter: params.ListStorageExporter, + treeExporter: params.TreeStorageExporter, + converter: params.DataConverter, + } +} + +func (t *treeExporter) ExportUnencrypted(tree objecttree.ReadableObjectTree) (err error) { + lst := tree.AclList() + // this exports root which should be enough before we implement acls + _, err = t.listExporter.ListStorage(lst.Root()) + if err != nil { + return + } + treeStorage, err := t.treeExporter.TreeStorage(tree.Header()) + if err != nil { + return + } + changeBuilder := objecttree.NewChangeBuilder(keychain.NewKeychain(), tree.Header()) + putStorage := func(change *objecttree.Change) (err error) { + var raw *treechangeproto.RawTreeChangeWithId + raw, err = changeBuilder.Marshall(change) + if err != nil { + return + } + return treeStorage.AddRawChange(raw) + } + err = tree.IterateRoot(t.converter.Unmarshall, func(change *objecttree.Change) bool { + if change.Id == tree.Id() { + err = putStorage(change) + return err == nil + } + var data []byte + data, err = t.converter.Marshall(change.Model) + if err != nil { + return false + } + // that means that change is unencrypted + change.ReadKeyHash = 0 + change.Data = data + err = putStorage(change) + return err == nil + }) + return err } diff --git a/commonspace/object/tree/exporter/treeimport.go b/commonspace/object/tree/exporter/treeimport.go index 69384b6a..f0ac9a82 100644 --- a/commonspace/object/tree/exporter/treeimport.go +++ b/commonspace/object/tree/exporter/treeimport.go @@ -1,6 +1,7 @@ package exporter import ( + "github.com/anytypeio/any-sync/commonspace/object/acl/list" "github.com/anytypeio/any-sync/commonspace/object/acl/liststorage" "github.com/anytypeio/any-sync/commonspace/object/tree/objecttree" "github.com/anytypeio/any-sync/commonspace/object/tree/treestorage" @@ -13,6 +14,15 @@ type TreeImportParams struct { IncludeBeforeId bool } -func ImportHistoryTree(params TreeImportParams) (objecttree.ReadableObjectTree, error) { - return nil, nil +func ImportHistoryTree(params TreeImportParams) (tree objecttree.ReadableObjectTree, err error) { + aclList, err := list.BuildAclList(params.ListStorage) + if err != nil { + return + } + return objecttree.BuildNonVerifiableHistoryTree(objecttree.HistoryTreeParams{ + TreeStorage: params.TreeStorage, + AclList: aclList, + BeforeId: params.BeforeId, + IncludeBeforeId: params.IncludeBeforeId, + }) } diff --git a/commonspace/object/tree/objecttree/mock_objecttree/mock_objecttree.go b/commonspace/object/tree/objecttree/mock_objecttree/mock_objecttree.go index c8dc3841..6915f927 100644 --- a/commonspace/object/tree/objecttree/mock_objecttree/mock_objecttree.go +++ b/commonspace/object/tree/objecttree/mock_objecttree/mock_objecttree.go @@ -8,6 +8,7 @@ import ( context "context" reflect "reflect" + list "github.com/anytypeio/any-sync/commonspace/object/acl/list" objecttree "github.com/anytypeio/any-sync/commonspace/object/tree/objecttree" treechangeproto "github.com/anytypeio/any-sync/commonspace/object/tree/treechangeproto" treestorage "github.com/anytypeio/any-sync/commonspace/object/tree/treestorage" @@ -37,6 +38,20 @@ func (m *MockObjectTree) EXPECT() *MockObjectTreeMockRecorder { return m.recorder } +// AclList mocks base method. +func (m *MockObjectTree) AclList() list.AclList { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "AclList") + ret0, _ := ret[0].(list.AclList) + return ret0 +} + +// AclList indicates an expected call of AclList. +func (mr *MockObjectTreeMockRecorder) AclList() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AclList", reflect.TypeOf((*MockObjectTree)(nil).AclList)) +} + // AddContent mocks base method. func (m *MockObjectTree) AddContent(arg0 context.Context, arg1 objecttree.SignableChangeContent) (objecttree.AddResult, error) { m.ctrl.T.Helper() diff --git a/commonspace/object/tree/objecttree/objecttree.go b/commonspace/object/tree/objecttree/objecttree.go index bc806522..58c254da 100644 --- a/commonspace/object/tree/objecttree/objecttree.go +++ b/commonspace/object/tree/objecttree/objecttree.go @@ -52,6 +52,8 @@ type ReadableObjectTree interface { Heads() []string Root() *Change + AclList() list.AclList + HasChanges(...string) bool GetChange(string) (*Change, error) @@ -122,6 +124,10 @@ func (ot *objectTree) Id() string { return ot.id } +func (ot *objectTree) AclList() list.AclList { + return ot.aclList +} + func (ot *objectTree) Header() *treechangeproto.RawTreeChangeWithId { return ot.rawRoot } diff --git a/commonspace/object/tree/synctree/mock_synctree/mock_synctree.go b/commonspace/object/tree/synctree/mock_synctree/mock_synctree.go index 73335d45..6fad9dd5 100644 --- a/commonspace/object/tree/synctree/mock_synctree/mock_synctree.go +++ b/commonspace/object/tree/synctree/mock_synctree/mock_synctree.go @@ -8,6 +8,7 @@ import ( context "context" reflect "reflect" + list "github.com/anytypeio/any-sync/commonspace/object/acl/list" objecttree "github.com/anytypeio/any-sync/commonspace/object/tree/objecttree" updatelistener "github.com/anytypeio/any-sync/commonspace/object/tree/synctree/updatelistener" treechangeproto "github.com/anytypeio/any-sync/commonspace/object/tree/treechangeproto" @@ -162,6 +163,20 @@ func (m *MockSyncTree) EXPECT() *MockSyncTreeMockRecorder { return m.recorder } +// AclList mocks base method. +func (m *MockSyncTree) AclList() list.AclList { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "AclList") + ret0, _ := ret[0].(list.AclList) + return ret0 +} + +// AclList indicates an expected call of AclList. +func (mr *MockSyncTreeMockRecorder) AclList() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AclList", reflect.TypeOf((*MockSyncTree)(nil).AclList)) +} + // AddContent mocks base method. func (m *MockSyncTree) AddContent(arg0 context.Context, arg1 objecttree.SignableChangeContent) (objecttree.AddResult, error) { m.ctrl.T.Helper() From 82b398ff7fd2d341d7b489d01b6251392b74f25c Mon Sep 17 00:00:00 2001 From: mcrakhman Date: Thu, 26 Jan 2023 10:06:06 +0100 Subject: [PATCH 6/9] Set object tree id at the start --- commonspace/object/tree/objecttree/objecttreefactory.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/commonspace/object/tree/objecttree/objecttreefactory.go b/commonspace/object/tree/objecttree/objecttreefactory.go index 8eb5b466..eb0ec8e2 100644 --- a/commonspace/object/tree/objecttree/objecttreefactory.go +++ b/commonspace/object/tree/objecttree/objecttreefactory.go @@ -180,6 +180,7 @@ func createObjectTreeRoot( func buildObjectTree(deps objectTreeDeps) (ObjectTree, error) { objTree := &objectTree{ + id: deps.treeStorage.Id(), treeStorage: deps.treeStorage, treeBuilder: deps.treeBuilder, validator: deps.validator, @@ -198,7 +199,6 @@ func buildObjectTree(deps objectTreeDeps) (ObjectTree, error) { return nil, err } - objTree.id = objTree.treeStorage.Id() objTree.rawRoot, err = objTree.treeStorage.Root() if err != nil { return nil, err @@ -216,6 +216,7 @@ func buildObjectTree(deps objectTreeDeps) (ObjectTree, error) { func buildHistoryTree(deps objectTreeDeps, params HistoryTreeParams) (ht HistoryTree, err error) { objTree := &objectTree{ + id: deps.treeStorage.Id(), treeStorage: deps.treeStorage, treeBuilder: deps.treeBuilder, validator: deps.validator, From bf56f338f21c03c66e836b120d99d0b6b90a9949 Mon Sep 17 00:00:00 2001 From: mcrakhman Date: Thu, 26 Jan 2023 12:55:34 +0100 Subject: [PATCH 7/9] Set heads in tree storage --- commonspace/object/tree/exporter/treeexporter.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/commonspace/object/tree/exporter/treeexporter.go b/commonspace/object/tree/exporter/treeexporter.go index 01d41f96..3dabd605 100644 --- a/commonspace/object/tree/exporter/treeexporter.go +++ b/commonspace/object/tree/exporter/treeexporter.go @@ -73,5 +73,8 @@ func (t *treeExporter) ExportUnencrypted(tree objecttree.ReadableObjectTree) (er err = putStorage(change) return err == nil }) - return err + if err != nil { + return + } + return treeStorage.SetHeads(tree.Heads()) } From 06bb0f7496819e9a843b634348237d36b1339061 Mon Sep 17 00:00:00 2001 From: mcrakhman Date: Sat, 28 Jan 2023 23:58:47 +0100 Subject: [PATCH 8/9] Add dialer to inner pool --- net/pool/poolservice.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/pool/poolservice.go b/net/pool/poolservice.go index c28fcf6b..dea7c0b6 100644 --- a/net/pool/poolservice.go +++ b/net/pool/poolservice.go @@ -35,8 +35,8 @@ type poolService struct { } func (p *poolService) Init(a *app.App) (err error) { - p.pool = &pool{} p.dialer = a.MustComponent(dialer.CName).(dialer.Dialer) + p.pool = &pool{dialer: p.dialer} if m := a.Component(metric.CName); m != nil { p.metricReg = m.(metric.Metric).Registry() } From 8ff7cc9e16a2331bc0ce8e5abf99904bd48b244e Mon Sep 17 00:00:00 2001 From: Sergey Cherepanov Date: Tue, 31 Jan 2023 19:34:23 +0300 Subject: [PATCH 9/9] fix the test blinking --- commonspace/settings/deletionstate/deletionstate_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/commonspace/settings/deletionstate/deletionstate_test.go b/commonspace/settings/deletionstate/deletionstate_test.go index 6c91daac..82c68122 100644 --- a/commonspace/settings/deletionstate/deletionstate_test.go +++ b/commonspace/settings/deletionstate/deletionstate_test.go @@ -5,6 +5,7 @@ import ( "github.com/anytypeio/any-sync/commonspace/spacestorage/mock_spacestorage" "github.com/golang/mock/gomock" "github.com/stretchr/testify/require" + "sort" "testing" ) @@ -70,6 +71,7 @@ func TestDeletionState_GetQueued(t *testing.T) { fx.delState.queued["id2"] = struct{}{} queued := fx.delState.GetQueued() + sort.Strings(queued) require.Equal(t, []string{"id1", "id2"}, queued) }