Merge pull request #8 from anytypeio/middleware-compatibility

Middleware compatibility
This commit is contained in:
Sergey Cherepanov 2023-01-31 19:36:52 +03:00 committed by GitHub
commit 38f831ab6b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 357 additions and 163 deletions

View File

@ -5,7 +5,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"github.com/anytypeio/any-sync/app/logger" "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/commonspace/object/keychain"
"github.com/anytypeio/any-sync/util/keys" "github.com/anytypeio/any-sync/util/keys"
"github.com/anytypeio/any-sync/util/keys/asymmetric/encryptionkey" "github.com/anytypeio/any-sync/util/keys/asymmetric/encryptionkey"
@ -36,15 +36,15 @@ var (
type UserPermissionPair struct { type UserPermissionPair struct {
Identity string Identity string
Permission aclrecordproto2.AclUserPermissions Permission aclrecordproto.AclUserPermissions
} }
type AclState struct { type AclState struct {
id string id string
currentReadKeyHash uint64 currentReadKeyHash uint64
userReadKeys map[uint64]*symmetric.Key userReadKeys map[uint64]*symmetric.Key
userStates map[string]*aclrecordproto2.AclUserState userStates map[string]*aclrecordproto.AclUserState
userInvites map[string]*aclrecordproto2.AclUserInvite userInvites map[string]*aclrecordproto.AclUserInvite
encryptionKey encryptionkey.PrivKey encryptionKey encryptionkey.PrivKey
signingKey signingkey.PrivKey signingKey signingkey.PrivKey
totalReadKeys int totalReadKeys int
@ -70,8 +70,8 @@ func newAclStateWithKeys(
signingKey: signingKey, signingKey: signingKey,
encryptionKey: encryptionKey, encryptionKey: encryptionKey,
userReadKeys: make(map[uint64]*symmetric.Key), userReadKeys: make(map[uint64]*symmetric.Key),
userStates: make(map[string]*aclrecordproto2.AclUserState), userStates: make(map[string]*aclrecordproto.AclUserState),
userInvites: make(map[string]*aclrecordproto2.AclUserInvite), userInvites: make(map[string]*aclrecordproto.AclUserInvite),
permissionsAtRecord: make(map[string][]UserPermissionPair), permissionsAtRecord: make(map[string][]UserPermissionPair),
}, nil }, nil
} }
@ -80,8 +80,8 @@ func newAclState(id string) *AclState {
return &AclState{ return &AclState{
id: id, id: id,
userReadKeys: make(map[uint64]*symmetric.Key), userReadKeys: make(map[uint64]*symmetric.Key),
userStates: make(map[string]*aclrecordproto2.AclUserState), userStates: make(map[string]*aclrecordproto.AclUserState),
userInvites: make(map[string]*aclrecordproto2.AclUserInvite), userInvites: make(map[string]*aclrecordproto.AclUserInvite),
permissionsAtRecord: make(map[string][]UserPermissionPair), permissionsAtRecord: make(map[string][]UserPermissionPair),
} }
} }
@ -128,7 +128,7 @@ func (st *AclState) applyRecord(record *AclRecord) (err error) {
return return
} }
if record.Id == st.id { if record.Id == st.id {
root, ok := record.Model.(*aclrecordproto2.AclRoot) root, ok := record.Model.(*aclrecordproto.AclRoot)
if !ok { if !ok {
return ErrIncorrectRoot return ErrIncorrectRoot
} }
@ -137,14 +137,14 @@ func (st *AclState) applyRecord(record *AclRecord) (err error) {
return return
} }
st.permissionsAtRecord[record.Id] = []UserPermissionPair{ st.permissionsAtRecord[record.Id] = []UserPermissionPair{
{Identity: string(root.Identity), Permission: aclrecordproto2.AclUserPermissions_Admin}, {Identity: string(root.Identity), Permission: aclrecordproto.AclUserPermissions_Admin},
} }
return return
} }
aclData := &aclrecordproto2.AclData{} aclData := &aclrecordproto.AclData{}
if record.Model != nil { if record.Model != nil {
aclData = record.Model.(*aclrecordproto2.AclData) aclData = record.Model.(*aclrecordproto.AclData)
} else { } else {
err = proto.Unmarshal(record.Data, aclData) err = proto.Unmarshal(record.Data, aclData)
if err != nil { if err != nil {
@ -172,7 +172,7 @@ func (st *AclState) applyRecord(record *AclRecord) (err error) {
return 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) { if st.signingKey != nil && st.encryptionKey != nil && st.identity == string(root.Identity) {
err = st.saveReadKeyFromRoot(root) err = st.saveReadKeyFromRoot(root)
if err != nil { if err != nil {
@ -181,10 +181,10 @@ func (st *AclState) applyRoot(root *aclrecordproto2.AclRoot) (err error) {
} }
// adding user to the list // adding user to the list
userState := &aclrecordproto2.AclUserState{ userState := &aclrecordproto.AclUserState{
Identity: root.Identity, Identity: root.Identity,
EncryptionKey: root.EncryptionKey, EncryptionKey: root.EncryptionKey,
Permissions: aclrecordproto2.AclUserPermissions_Admin, Permissions: aclrecordproto.AclUserPermissions_Admin,
} }
st.currentReadKeyHash = root.CurrentReadKeyHash st.currentReadKeyHash = root.CurrentReadKeyHash
st.userStates[string(root.Identity)] = userState st.userStates[string(root.Identity)] = userState
@ -192,7 +192,7 @@ func (st *AclState) applyRoot(root *aclrecordproto2.AclRoot) (err error) {
return return
} }
func (st *AclState) saveReadKeyFromRoot(root *aclrecordproto2.AclRoot) (err error) { func (st *AclState) saveReadKeyFromRoot(root *aclrecordproto.AclRoot) (err error) {
var readKey *symmetric.Key var readKey *symmetric.Key
if len(root.GetDerivationScheme()) != 0 { if len(root.GetDerivationScheme()) != 0 {
var encPrivKey []byte var encPrivKey []byte
@ -206,7 +206,7 @@ func (st *AclState) saveReadKeyFromRoot(root *aclrecordproto2.AclRoot) (err erro
return return
} }
readKey, err = aclrecordproto2.AclReadKeyDerive(signPrivKey, encPrivKey) readKey, err = aclrecordproto.AclReadKeyDerive(signPrivKey, encPrivKey)
if err != nil { if err != nil {
return return
} }
@ -230,7 +230,7 @@ func (st *AclState) saveReadKeyFromRoot(root *aclrecordproto2.AclRoot) (err erro
return 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() { defer func() {
if err != nil { if err != nil {
return return
@ -248,7 +248,7 @@ func (st *AclState) applyChangeData(changeData *aclrecordproto2.AclData, hash ui
return 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) err = fmt.Errorf("user %s must have admin permissions", identity)
return return
} }
@ -264,7 +264,7 @@ func (st *AclState) applyChangeData(changeData *aclrecordproto2.AclData, hash ui
return nil return nil
} }
func (st *AclState) applyChangeContent(ch *aclrecordproto2.AclContentValue) error { func (st *AclState) applyChangeContent(ch *aclrecordproto.AclContentValue) error {
switch { switch {
case ch.GetUserPermissionChange() != nil: case ch.GetUserPermissionChange() != nil:
return st.applyUserPermissionChange(ch.GetUserPermissionChange()) 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) chIdentity := string(ch.Identity)
state, exists := st.userStates[chIdentity] state, exists := st.userStates[chIdentity]
if !exists { if !exists {
@ -292,12 +292,12 @@ func (st *AclState) applyUserPermissionChange(ch *aclrecordproto2.AclUserPermiss
return nil return nil
} }
func (st *AclState) applyUserInvite(ch *aclrecordproto2.AclUserInvite) error { func (st *AclState) applyUserInvite(ch *aclrecordproto.AclUserInvite) error {
st.userInvites[string(ch.AcceptPublicKey)] = ch st.userInvites[string(ch.AcceptPublicKey)] = ch
return nil 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)] invite, exists := st.userInvites[string(ch.AcceptPubKey)]
if !exists { if !exists {
return fmt.Errorf("no such invite with such public key %s", keys.EncodeBytesToString(ch.AcceptPubKey)) 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 // adding user to the list
userState := &aclrecordproto2.AclUserState{ userState := &aclrecordproto.AclUserState{
Identity: ch.Identity, Identity: ch.Identity,
EncryptionKey: ch.EncryptionKey, EncryptionKey: ch.EncryptionKey,
Permissions: invite.Permissions, Permissions: invite.Permissions,
@ -345,13 +345,13 @@ func (st *AclState) applyUserJoin(ch *aclrecordproto2.AclUserJoin) error {
return nil return nil
} }
func (st *AclState) applyUserAdd(ch *aclrecordproto2.AclUserAdd) error { func (st *AclState) applyUserAdd(ch *aclrecordproto.AclUserAdd) error {
chIdentity := string(ch.Identity) chIdentity := string(ch.Identity)
if _, exists := st.userStates[chIdentity]; exists { if _, exists := st.userStates[chIdentity]; exists {
return ErrUserAlreadyExists return ErrUserAlreadyExists
} }
st.userStates[chIdentity] = &aclrecordproto2.AclUserState{ st.userStates[chIdentity] = &aclrecordproto.AclUserState{
Identity: ch.Identity, Identity: ch.Identity,
EncryptionKey: ch.EncryptionKey, EncryptionKey: ch.EncryptionKey,
Permissions: ch.Permissions, Permissions: ch.Permissions,
@ -371,7 +371,7 @@ func (st *AclState) applyUserAdd(ch *aclrecordproto2.AclUserAdd) error {
return nil return nil
} }
func (st *AclState) applyUserRemove(ch *aclrecordproto2.AclUserRemove) error { func (st *AclState) applyUserRemove(ch *aclrecordproto.AclUserRemove) error {
chIdentity := string(ch.Identity) chIdentity := string(ch.Identity)
if chIdentity == st.identity { if chIdentity == st.identity {
return ErrDocumentForbidden return ErrDocumentForbidden
@ -415,7 +415,7 @@ func (st *AclState) decryptReadKeyAndHash(msg []byte) (*symmetric.Key, uint64, e
return key, hasher.Sum64(), nil 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)] state, exists := st.userStates[string(identity)]
if !exists { if !exists {
return false return false
@ -424,22 +424,22 @@ func (st *AclState) HasPermission(identity []byte, permission aclrecordproto2.Ac
return state.Permissions == permission 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 // if we have a UserJoin, then it should always be the first one applied
return data.GetAclContent() != nil && data.GetAclContent()[0].GetUserJoin() != nil 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 // if we have a UserAdd, then it should always be the first one applied
userAdd := data.GetAclContent()[0].GetUserAdd() userAdd := data.GetAclContent()[0].GetUserAdd()
return data.GetAclContent() != nil && userAdd != nil && bytes.Compare(userAdd.GetIdentity(), identity) == 0 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 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)] invite, exists := st.userInvites[string(acceptPubKey)]
if !exists { if !exists {
err = ErrNoSuchInvite err = ErrNoSuchInvite

View File

@ -13,6 +13,10 @@ var (
ErrUnknownRecord = errors.New("record doesn't exist") ErrUnknownRecord = errors.New("record doesn't exist")
) )
type Exporter interface {
ListStorage(root *aclrecordproto.RawAclRecordWithId) (ListStorage, error)
}
type ListStorage interface { type ListStorage interface {
Id() string Id() string
Root() (*aclrecordproto.RawAclRecordWithId, error) Root() (*aclrecordproto.RawAclRecordWithId, error)

View File

@ -0,0 +1,80 @@
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"
)
type DataConverter interface {
Unmarshall(decrypted []byte) (any, error)
Marshall(model any) ([]byte, error)
}
type TreeExporterParams struct {
ListStorageExporter liststorage.Exporter
TreeStorageExporter treestorage.Exporter
DataConverter DataConverter
}
type TreeExporter interface {
ExportUnencrypted(tree objecttree.ReadableObjectTree) (err error)
}
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
})
if err != nil {
return
}
return treeStorage.SetHeads(tree.Heads())
}

View File

@ -0,0 +1,28 @@
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"
)
type TreeImportParams struct {
ListStorage liststorage.ListStorage
TreeStorage treestorage.TreeStorage
BeforeId string
IncludeBeforeId bool
}
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,
})
}

View File

@ -35,12 +35,31 @@ type InitialContent struct {
Timestamp int64 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 { type ChangeBuilder interface {
ConvertFromRaw(rawIdChange *treechangeproto.RawTreeChangeWithId, verify bool) (ch *Change, err error) Unmarshall(rawIdChange *treechangeproto.RawTreeChangeWithId, verify bool) (ch *Change, err error)
BuildContent(payload BuilderContent) (ch *Change, raw *treechangeproto.RawTreeChangeWithId, err error) Build(payload BuilderContent) (ch *Change, raw *treechangeproto.RawTreeChangeWithId, err error)
BuildInitialContent(payload InitialContent) (ch *Change, raw *treechangeproto.RawTreeChangeWithId, err error) BuildRoot(payload InitialContent) (ch *Change, raw *treechangeproto.RawTreeChangeWithId, err error)
BuildRaw(ch *Change) (*treechangeproto.RawTreeChangeWithId, error) Marshall(ch *Change) (*treechangeproto.RawTreeChangeWithId, error)
SetRootRawChange(rawIdChange *treechangeproto.RawTreeChangeWithId)
} }
type changeBuilder struct { type changeBuilder struct {
@ -52,7 +71,7 @@ func NewChangeBuilder(keys *keychain.Keychain, rootChange *treechangeproto.RawTr
return &changeBuilder{keys: keys, rootChange: rootChange} 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 { if rawIdChange.GetRawChange() == nil {
err = ErrEmptyChange err = ErrEmptyChange
return return
@ -101,7 +120,7 @@ func (c *changeBuilder) SetRootRawChange(rawIdChange *treechangeproto.RawTreeCha
c.rootChange = rawIdChange 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{ change := &treechangeproto.RootChange{
AclHeadId: payload.AclHeadId, AclHeadId: payload.AclHeadId,
Timestamp: payload.Timestamp, Timestamp: payload.Timestamp,
@ -145,7 +164,7 @@ func (c *changeBuilder) BuildInitialContent(payload InitialContent) (ch *Change,
return 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{ change := &treechangeproto.TreeChange{
TreeHeadIds: payload.TreeHeadIds, TreeHeadIds: payload.TreeHeadIds,
AclHeadId: payload.AclHeadId, AclHeadId: payload.AclHeadId,
@ -200,7 +219,7 @@ func (c *changeBuilder) BuildContent(payload BuilderContent) (ch *Change, rawIdC
return 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 { if ch.Id == c.rootChange.Id {
return c.rootChange, nil return c.rootChange, nil
} }

View File

@ -8,6 +8,7 @@ import (
context "context" context "context"
reflect "reflect" reflect "reflect"
list "github.com/anytypeio/any-sync/commonspace/object/acl/list"
objecttree "github.com/anytypeio/any-sync/commonspace/object/tree/objecttree" objecttree "github.com/anytypeio/any-sync/commonspace/object/tree/objecttree"
treechangeproto "github.com/anytypeio/any-sync/commonspace/object/tree/treechangeproto" treechangeproto "github.com/anytypeio/any-sync/commonspace/object/tree/treechangeproto"
treestorage "github.com/anytypeio/any-sync/commonspace/object/tree/treestorage" treestorage "github.com/anytypeio/any-sync/commonspace/object/tree/treestorage"
@ -37,6 +38,20 @@ func (m *MockObjectTree) EXPECT() *MockObjectTreeMockRecorder {
return m.recorder 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. // AddContent mocks base method.
func (m *MockObjectTree) AddContent(arg0 context.Context, arg1 objecttree.SignableChangeContent) (objecttree.AddResult, error) { func (m *MockObjectTree) AddContent(arg0 context.Context, arg1 objecttree.SignableChangeContent) (objecttree.AddResult, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
@ -96,19 +111,19 @@ func (mr *MockObjectTreeMockRecorder) Close() *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockObjectTree)(nil).Close)) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockObjectTree)(nil).Close))
} }
// DebugDump mocks base method. // Debug mocks base method.
func (m *MockObjectTree) DebugDump(arg0 objecttree.DescriptionParser) (string, error) { func (m *MockObjectTree) Debug(arg0 objecttree.DescriptionParser) (objecttree.DebugInfo, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "DebugDump", arg0) ret := m.ctrl.Call(m, "Debug", arg0)
ret0, _ := ret[0].(string) ret0, _ := ret[0].(objecttree.DebugInfo)
ret1, _ := ret[1].(error) ret1, _ := ret[1].(error)
return ret0, ret1 return ret0, ret1
} }
// DebugDump indicates an expected call of DebugDump. // Debug indicates an expected call of Debug.
func (mr *MockObjectTreeMockRecorder) DebugDump(arg0 interface{}) *gomock.Call { func (mr *MockObjectTreeMockRecorder) Debug(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper() 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. // Delete mocks base method.

View File

@ -6,7 +6,6 @@ import (
"errors" "errors"
"github.com/anytypeio/any-sync/commonspace/object/acl/aclrecordproto" "github.com/anytypeio/any-sync/commonspace/object/acl/aclrecordproto"
list "github.com/anytypeio/any-sync/commonspace/object/acl/list" 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/treechangeproto"
"github.com/anytypeio/any-sync/commonspace/object/tree/treestorage" "github.com/anytypeio/any-sync/commonspace/object/tree/treestorage"
"github.com/anytypeio/any-sync/util/keys/symmetric" "github.com/anytypeio/any-sync/util/keys/symmetric"
@ -53,10 +52,12 @@ type ReadableObjectTree interface {
Heads() []string Heads() []string
Root() *Change Root() *Change
AclList() list.AclList
HasChanges(...string) bool HasChanges(...string) bool
GetChange(string) (*Change, error) GetChange(string) (*Change, error)
DebugDump(parser DescriptionParser) (string, error) Debug(parser DescriptionParser) (DebugInfo, error)
IterateRoot(convert ChangeConvertFunc, iterate ChangeIterateFunc) error IterateRoot(convert ChangeConvertFunc, iterate ChangeIterateFunc) error
IterateFrom(id string, convert ChangeConvertFunc, iterate ChangeIterateFunc) error IterateFrom(id string, convert ChangeConvertFunc, iterate ChangeIterateFunc) error
} }
@ -102,33 +103,6 @@ type objectTree struct {
sync.RWMutex 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) { func (ot *objectTree) rebuildFromStorage(theirHeads []string, newChanges []*Change) (err error) {
ot.treeBuilder.Reset() ot.treeBuilder.Reset()
@ -150,6 +124,10 @@ func (ot *objectTree) Id() string {
return ot.id return ot.id
} }
func (ot *objectTree) AclList() list.AclList {
return ot.aclList
}
func (ot *objectTree) Header() *treechangeproto.RawTreeChangeWithId { func (ot *objectTree) Header() *treechangeproto.RawTreeChangeWithId {
return ot.rawRoot return ot.rawRoot
} }
@ -179,7 +157,7 @@ func (ot *objectTree) AddContent(ctx context.Context, content SignableChangeCont
oldHeads := make([]string, 0, len(ot.tree.Heads())) oldHeads := make([]string, 0, len(ot.tree.Heads()))
oldHeads = append(oldHeads, 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 { if content.IsSnapshot {
// clearing tree, because we already saved everything in the last snapshot // clearing tree, because we already saved everything in the last snapshot
ot.tree = &Tree{} ot.tree = &Tree{}
@ -293,7 +271,7 @@ func (ot *objectTree) addRawChanges(ctx context.Context, changesPayload RawChang
if unAttached, exists := ot.tree.unAttached[ch.Id]; exists { if unAttached, exists := ot.tree.unAttached[ch.Id]; exists {
change = unAttached change = unAttached
} else { } else {
change, err = ot.changeBuilder.ConvertFromRaw(ch, true) change, err = ot.changeBuilder.Unmarshall(ch, true)
if err != nil { if err != nil {
return return
} }
@ -444,7 +422,7 @@ func (ot *objectTree) createAddResult(oldHeads []string, mode Mode, treeChangesA
// if we got some changes that we need to convert to raw // if we got some changes that we need to convert to raw
if _, exists := alreadyConverted[ch]; !exists { if _, exists := alreadyConverted[ch]; !exists {
var raw *treechangeproto.RawTreeChangeWithId var raw *treechangeproto.RawTreeChangeWithId
raw, err = ot.changeBuilder.BuildRaw(ch) raw, err = ot.changeBuilder.Marshall(ch)
if err != nil { if err != nil {
return return
} }
@ -637,6 +615,6 @@ func (ot *objectTree) validateTree(newChanges []*Change) error {
return ot.validator.ValidateNewChanges(ot.tree, ot.aclList, newChanges) return ot.validator.ValidateNewChanges(ot.tree, ot.aclList, newChanges)
} }
func (ot *objectTree) DebugDump(parser DescriptionParser) (string, error) { func (ot *objectTree) Debug(parser DescriptionParser) (DebugInfo, error) {
return ot.tree.Graph(parser) return objectTreeDebug{}.debugInfo(ot, parser)
} }

View File

@ -59,44 +59,10 @@ func (c *mockChangeCreator) createNewTreeStorage(treeId, aclHeadId string) trees
return treeStorage 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 { type testTreeContext struct {
aclList list.AclList aclList list.AclList
treeStorage treestorage.TreeStorage treeStorage treestorage.TreeStorage
changeBuilder *mockChangeBuilder changeBuilder ChangeBuilder
changeCreator *mockChangeCreator changeCreator *mockChangeCreator
objTree ObjectTree objTree ObjectTree
} }
@ -115,15 +81,15 @@ func prepareTreeDeps(aclList list.AclList) (*mockChangeCreator, objectTreeDeps)
changeCreator := &mockChangeCreator{} changeCreator := &mockChangeCreator{}
treeStorage := changeCreator.createNewTreeStorage("0", aclList.Head().Id) treeStorage := changeCreator.createNewTreeStorage("0", aclList.Head().Id)
root, _ := treeStorage.Root() root, _ := treeStorage.Root()
changeBuilder := &mockChangeBuilder{ changeBuilder := &nonVerifiableChangeBuilder{
originalBuilder: NewChangeBuilder(nil, root), ChangeBuilder: NewChangeBuilder(nil, root),
} }
deps := objectTreeDeps{ deps := objectTreeDeps{
changeBuilder: changeBuilder, changeBuilder: changeBuilder,
treeBuilder: newTreeBuilder(treeStorage, changeBuilder), treeBuilder: newTreeBuilder(treeStorage, changeBuilder),
treeStorage: treeStorage, treeStorage: treeStorage,
rawChangeLoader: newRawChangeLoader(treeStorage, changeBuilder), rawChangeLoader: newRawChangeLoader(treeStorage, changeBuilder),
validator: &mockChangeValidator{}, validator: &noOpTreeValidator{},
aclList: aclList, aclList: aclList,
} }
return changeCreator, deps return changeCreator, deps
@ -133,15 +99,15 @@ func prepareTreeContext(t *testing.T, aclList list.AclList) testTreeContext {
changeCreator := &mockChangeCreator{} changeCreator := &mockChangeCreator{}
treeStorage := changeCreator.createNewTreeStorage("0", aclList.Head().Id) treeStorage := changeCreator.createNewTreeStorage("0", aclList.Head().Id)
root, _ := treeStorage.Root() root, _ := treeStorage.Root()
changeBuilder := &mockChangeBuilder{ changeBuilder := &nonVerifiableChangeBuilder{
originalBuilder: NewChangeBuilder(nil, root), ChangeBuilder: NewChangeBuilder(nil, root),
} }
deps := objectTreeDeps{ deps := objectTreeDeps{
changeBuilder: changeBuilder, changeBuilder: changeBuilder,
treeBuilder: newTreeBuilder(treeStorage, changeBuilder), treeBuilder: newTreeBuilder(treeStorage, changeBuilder),
treeStorage: treeStorage, treeStorage: treeStorage,
rawChangeLoader: newRawChangeLoader(treeStorage, changeBuilder), rawChangeLoader: newRawChangeLoader(treeStorage, changeBuilder),
validator: &mockChangeValidator{}, validator: &noOpTreeValidator{},
aclList: aclList, aclList: aclList,
} }

View File

@ -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
}

View File

@ -19,6 +19,56 @@ type ObjectTreeCreatePayload struct {
IsEncrypted bool 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) { func CreateObjectTreeRoot(payload ObjectTreeCreatePayload, aclList list.AclList) (root *treechangeproto.RawTreeChangeWithId, err error) {
bytes := make([]byte, 32) bytes := make([]byte, 32)
_, err = rand.Read(bytes) _, err = rand.Read(bytes)
@ -41,6 +91,15 @@ func BuildObjectTree(treeStorage treestorage.TreeStorage, aclList list.AclList)
return buildObjectTree(deps) return buildObjectTree(deps)
} }
func BuildNonVerifiableHistoryTree(params HistoryTreeParams) (HistoryTree, error) {
rootChange, err := params.TreeStorage.Root()
if err != nil {
return nil, err
}
deps := nonVerifiableTreeDeps(rootChange, params.TreeStorage, params.AclList)
return buildHistoryTree(deps, params)
}
func BuildHistoryTree(params HistoryTreeParams) (HistoryTree, error) { func BuildHistoryTree(params HistoryTreeParams) (HistoryTree, error) {
rootChange, err := params.TreeStorage.Root() rootChange, err := params.TreeStorage.Root()
if err != nil { if err != nil {
@ -115,12 +174,13 @@ func createObjectTreeRoot(
Seed: seed, Seed: seed,
} }
_, root, err = NewChangeBuilder(keychain.NewKeychain(), nil).BuildInitialContent(cnt) _, root, err = NewChangeBuilder(keychain.NewKeychain(), nil).BuildRoot(cnt)
return return
} }
func buildObjectTree(deps objectTreeDeps) (ObjectTree, error) { func buildObjectTree(deps objectTreeDeps) (ObjectTree, error) {
objTree := &objectTree{ objTree := &objectTree{
id: deps.treeStorage.Id(),
treeStorage: deps.treeStorage, treeStorage: deps.treeStorage,
treeBuilder: deps.treeBuilder, treeBuilder: deps.treeBuilder,
validator: deps.validator, validator: deps.validator,
@ -139,14 +199,13 @@ func buildObjectTree(deps objectTreeDeps) (ObjectTree, error) {
return nil, err return nil, err
} }
objTree.id = objTree.treeStorage.Id()
objTree.rawRoot, err = objTree.treeStorage.Root() objTree.rawRoot, err = objTree.treeStorage.Root()
if err != nil { if err != nil {
return nil, err return nil, err
} }
// verifying root // verifying root
header, err := objTree.changeBuilder.ConvertFromRaw(objTree.rawRoot, true) header, err := objTree.changeBuilder.Unmarshall(objTree.rawRoot, true)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -155,15 +214,9 @@ func buildObjectTree(deps objectTreeDeps) (ObjectTree, error) {
return objTree, nil 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) { func buildHistoryTree(deps objectTreeDeps, params HistoryTreeParams) (ht HistoryTree, err error) {
objTree := &objectTree{ objTree := &objectTree{
id: deps.treeStorage.Id(),
treeStorage: deps.treeStorage, treeStorage: deps.treeStorage,
treeBuilder: deps.treeBuilder, treeBuilder: deps.treeBuilder,
validator: deps.validator, validator: deps.validator,
@ -188,7 +241,7 @@ func buildHistoryTree(deps objectTreeDeps, params HistoryTreeParams) (ht History
return nil, err return nil, err
} }
header, err := objTree.changeBuilder.ConvertFromRaw(objTree.rawRoot, false) header, err := objTree.changeBuilder.Unmarshall(objTree.rawRoot, false)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -4,6 +4,7 @@ import (
"fmt" "fmt"
"github.com/anytypeio/any-sync/commonspace/object/acl/aclrecordproto" "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/acl/list"
"github.com/anytypeio/any-sync/commonspace/object/tree/treestorage"
) )
type ObjectTreeValidator interface { type ObjectTreeValidator interface {
@ -13,6 +14,16 @@ type ObjectTreeValidator interface {
ValidateNewChanges(tree *Tree, aclList list.AclList, newChanges []*Change) error 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{} type objectTreeValidator struct{}
func newTreeValidator() ObjectTreeValidator { func newTreeValidator() ObjectTreeValidator {
@ -75,3 +86,13 @@ func (v *objectTreeValidator) validateChange(tree *Tree, aclList list.AclList, c
} }
return 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
}

View File

@ -39,7 +39,7 @@ func (r *rawChangeLoader) LoadFromTree(t *Tree, breakpoints []string) ([]*treech
convert := func(chs []*Change) (rawChanges []*treechangeproto.RawTreeChangeWithId, err error) { convert := func(chs []*Change) (rawChanges []*treechangeproto.RawTreeChangeWithId, err error) {
for _, ch := range chs { for _, ch := range chs {
var raw *treechangeproto.RawTreeChangeWithId var raw *treechangeproto.RawTreeChangeWithId
raw, err = r.changeBuilder.BuildRaw(ch) raw, err = r.changeBuilder.Marshall(ch)
if err != nil { if err != nil {
return return
} }
@ -226,7 +226,7 @@ func (r *rawChangeLoader) loadEntry(id string) (entry rawCacheEntry, err error)
return return
} }
change, err := r.changeBuilder.ConvertFromRaw(rawChange, false) change, err := r.changeBuilder.Unmarshall(rawChange, false)
if err != nil { if err != nil {
return return
} }

View File

@ -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
}

View File

@ -154,7 +154,7 @@ func (tb *treeBuilder) loadChange(id string) (ch *Change, err error) {
return nil, err return nil, err
} }
ch, err = tb.builder.ConvertFromRaw(change, true) ch, err = tb.builder.Unmarshall(change, true)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -8,6 +8,7 @@ import (
context "context" context "context"
reflect "reflect" reflect "reflect"
list "github.com/anytypeio/any-sync/commonspace/object/acl/list"
objecttree "github.com/anytypeio/any-sync/commonspace/object/tree/objecttree" objecttree "github.com/anytypeio/any-sync/commonspace/object/tree/objecttree"
updatelistener "github.com/anytypeio/any-sync/commonspace/object/tree/synctree/updatelistener" updatelistener "github.com/anytypeio/any-sync/commonspace/object/tree/synctree/updatelistener"
treechangeproto "github.com/anytypeio/any-sync/commonspace/object/tree/treechangeproto" treechangeproto "github.com/anytypeio/any-sync/commonspace/object/tree/treechangeproto"
@ -162,6 +163,20 @@ func (m *MockSyncTree) EXPECT() *MockSyncTreeMockRecorder {
return m.recorder 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. // AddContent mocks base method.
func (m *MockSyncTree) AddContent(arg0 context.Context, arg1 objecttree.SignableChangeContent) (objecttree.AddResult, error) { func (m *MockSyncTree) AddContent(arg0 context.Context, arg1 objecttree.SignableChangeContent) (objecttree.AddResult, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
@ -221,19 +236,19 @@ func (mr *MockSyncTreeMockRecorder) Close() *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockSyncTree)(nil).Close)) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockSyncTree)(nil).Close))
} }
// DebugDump mocks base method. // Debug mocks base method.
func (m *MockSyncTree) DebugDump(arg0 objecttree.DescriptionParser) (string, error) { func (m *MockSyncTree) Debug(arg0 objecttree.DescriptionParser) (objecttree.DebugInfo, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "DebugDump", arg0) ret := m.ctrl.Call(m, "Debug", arg0)
ret0, _ := ret[0].(string) ret0, _ := ret[0].(objecttree.DebugInfo)
ret1, _ := ret[1].(error) ret1, _ := ret[1].(error)
return ret0, ret1 return ret0, ret1
} }
// DebugDump indicates an expected call of DebugDump. // Debug indicates an expected call of Debug.
func (mr *MockSyncTreeMockRecorder) DebugDump(arg0 interface{}) *gomock.Call { func (mr *MockSyncTreeMockRecorder) Debug(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper() 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. // Delete mocks base method.

View File

@ -19,6 +19,10 @@ type TreeStorageCreatePayload struct {
Heads []string Heads []string
} }
type Exporter interface {
TreeStorage(root *treechangeproto.RawTreeChangeWithId) (TreeStorage, error)
}
type TreeStorageCreatorFunc = func(payload TreeStorageCreatePayload) (TreeStorage, error) type TreeStorageCreatorFunc = func(payload TreeStorageCreatePayload) (TreeStorage, error)
type TreeStorage interface { type TreeStorage interface {

View File

@ -95,7 +95,7 @@ func storagePayloadForSpaceCreate(payload SpaceCreatePayload) (storagePayload sp
return return
} }
_, settingsRoot, err := builder.BuildInitialContent(objecttree.InitialContent{ _, settingsRoot, err := builder.BuildRoot(objecttree.InitialContent{
AclHeadId: rawWithId.Id, AclHeadId: rawWithId.Id,
Identity: aclRoot.Identity, Identity: aclRoot.Identity,
SigningKey: payload.SigningKey, SigningKey: payload.SigningKey,
@ -196,7 +196,7 @@ func storagePayloadForSpaceDerive(payload SpaceDerivePayload) (storagePayload sp
} }
builder := objecttree.NewChangeBuilder(keychain.NewKeychain(), nil) builder := objecttree.NewChangeBuilder(keychain.NewKeychain(), nil)
_, settingsRoot, err := builder.BuildInitialContent(objecttree.InitialContent{ _, settingsRoot, err := builder.BuildRoot(objecttree.InitialContent{
AclHeadId: rawWithId.Id, AclHeadId: rawWithId.Id,
Identity: aclRoot.Identity, Identity: aclRoot.Identity,
SigningKey: payload.SigningKey, SigningKey: payload.SigningKey,

View File

@ -5,6 +5,7 @@ import (
"github.com/anytypeio/any-sync/commonspace/spacestorage/mock_spacestorage" "github.com/anytypeio/any-sync/commonspace/spacestorage/mock_spacestorage"
"github.com/golang/mock/gomock" "github.com/golang/mock/gomock"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"sort"
"testing" "testing"
) )
@ -70,6 +71,7 @@ func TestDeletionState_GetQueued(t *testing.T) {
fx.delState.queued["id2"] = struct{}{} fx.delState.queued["id2"] = struct{}{}
queued := fx.delState.GetQueued() queued := fx.delState.GetQueued()
sort.Strings(queued)
require.Equal(t, []string{"id1", "id2"}, queued) require.Equal(t, []string{"id1", "id2"}, queued)
} }

View File

@ -35,8 +35,8 @@ type poolService struct {
} }
func (p *poolService) Init(a *app.App) (err error) { func (p *poolService) Init(a *app.App) (err error) {
p.pool = &pool{}
p.dialer = a.MustComponent(dialer.CName).(dialer.Dialer) p.dialer = a.MustComponent(dialer.CName).(dialer.Dialer)
p.pool = &pool{dialer: p.dialer}
if m := a.Component(metric.CName); m != nil { if m := a.Component(metric.CName); m != nil {
p.metricReg = m.(metric.Metric).Registry() p.metricReg = m.(metric.Metric).Registry()
} }