Merge remote-tracking branch 'origin/acl-sync' into acl-invite

# Conflicts:
#	common/commonspace/service.go
#	common/pkg/acl/aclrecordproto/aclrecord.pb.go
#	common/pkg/acl/aclrecordproto/protos/aclrecord.proto
#	common/pkg/acl/list/list.go
#	common/pkg/acl/storage/inmemory.go
#	common/pkg/acl/testutils/acllistbuilder/liststoragebuilder.go
#	node/nodespace/rpchandler.go
#	node/nodespace/service.go
This commit is contained in:
mcrakhman 2022-11-07 12:36:48 +01:00
commit 354ee3b6c7
No known key found for this signature in database
GPG Key ID: DED12CFEF5B8396B
39 changed files with 1707 additions and 242 deletions

View File

@ -42,7 +42,7 @@ func (s *service) Init(a *app.App) (err error) {
s.spaceStorageProvider = a.MustComponent(storage.CName).(storage.SpaceStorageProvider) s.spaceStorageProvider = a.MustComponent(storage.CName).(storage.SpaceStorageProvider)
s.spaceCache = ocache.New( s.spaceCache = ocache.New(
func(ctx context.Context, id string) (value ocache.Object, err error) { func(ctx context.Context, id string) (value ocache.Object, err error) {
return s.commonSpace.GetSpace(ctx, id) return s.commonSpace.NewSpace(ctx, id)
}, },
ocache.WithLogger(log.Sugar()), ocache.WithLogger(log.Sugar()),
ocache.WithGCPeriod(time.Minute), ocache.WithGCPeriod(time.Minute),

View File

@ -77,7 +77,7 @@ func createListStorage(spaceId string, db *badger.DB, txn *badger.Txn, root *acl
return return
} }
func (l *listStorage) ID() string { func (l *listStorage) Id() string {
return l.id return l.id
} }

View File

@ -10,7 +10,7 @@ import (
) )
func testList(t *testing.T, store storage.ListStorage, root *aclrecordproto.RawACLRecordWithId, head string) { func testList(t *testing.T, store storage.ListStorage, root *aclrecordproto.RawACLRecordWithId, head string) {
require.Equal(t, store.ID(), root.Id) require.Equal(t, store.Id(), root.Id)
aclRoot, err := store.Root() aclRoot, err := store.Root()
require.NoError(t, err) require.NoError(t, err)

View File

@ -3,7 +3,7 @@ package storage
import ( import (
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto"
spacestorage "github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/storage" spacestorage "github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/storage"
storage2 "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/storage" storage "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/storage"
"github.com/dgraph-io/badger/v3" "github.com/dgraph-io/badger/v3"
"sync" "sync"
) )
@ -12,7 +12,7 @@ type spaceStorage struct {
spaceId string spaceId string
objDb *badger.DB objDb *badger.DB
keys spaceKeys keys spaceKeys
aclStorage storage2.ListStorage aclStorage storage.ListStorage
header *spacesyncproto.RawSpaceHeaderWithId header *spacesyncproto.RawSpaceHeaderWithId
mx sync.Mutex mx sync.Mutex
} }
@ -77,15 +77,15 @@ func createSpaceStorage(db *badger.DB, payload spacestorage.SpaceStorageCreatePa
return return
} }
func (s *spaceStorage) ID() string { func (s *spaceStorage) Id() string {
return s.spaceId return s.spaceId
} }
func (s *spaceStorage) TreeStorage(id string) (storage2.TreeStorage, error) { func (s *spaceStorage) TreeStorage(id string) (storage.TreeStorage, error) {
return newTreeStorage(s.objDb, s.spaceId, id) return newTreeStorage(s.objDb, s.spaceId, id)
} }
func (s *spaceStorage) CreateTreeStorage(payload storage2.TreeStorageCreatePayload) (ts storage2.TreeStorage, err error) { func (s *spaceStorage) CreateTreeStorage(payload storage.TreeStorageCreatePayload) (ts storage.TreeStorage, err error) {
// we have mutex here, so we prevent overwriting the heads of a tree on concurrent creation // we have mutex here, so we prevent overwriting the heads of a tree on concurrent creation
s.mx.Lock() s.mx.Lock()
defer s.mx.Unlock() defer s.mx.Unlock()
@ -93,7 +93,7 @@ func (s *spaceStorage) CreateTreeStorage(payload storage2.TreeStorageCreatePaylo
return createTreeStorage(s.objDb, s.spaceId, payload) return createTreeStorage(s.objDb, s.spaceId, payload)
} }
func (s *spaceStorage) ACLStorage() (storage2.ListStorage, error) { func (s *spaceStorage) ACLStorage() (storage.ListStorage, error) {
return s.aclStorage, nil return s.aclStorage, nil
} }

View File

@ -2,7 +2,7 @@ package storage
import ( import (
"context" "context"
storage "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/storage" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/storage"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/treechangeproto" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/treechangeproto"
"github.com/dgraph-io/badger/v3" "github.com/dgraph-io/badger/v3"
) )
@ -88,7 +88,7 @@ func createTreeStorage(db *badger.DB, spaceId string, payload storage.TreeStorag
return return
} }
func (t *treeStorage) ID() string { func (t *treeStorage) Id() string {
return t.id return t.id
} }

View File

@ -27,7 +27,7 @@ type fixture struct {
} }
func testTreePayload(t *testing.T, store storage.TreeStorage, payload storage.TreeStorageCreatePayload) { func testTreePayload(t *testing.T, store storage.TreeStorage, payload storage.TreeStorageCreatePayload) {
require.Equal(t, payload.RootRawChange.Id, store.ID()) require.Equal(t, payload.RootRawChange.Id, store.Id())
root, err := store.Root() root, err := store.Root()
require.NoError(t, err) require.NoError(t, err)

View File

@ -10,7 +10,7 @@ import (
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/storage" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/storage"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/syncservice" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/syncservice"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/treegetter" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/treegetter"
config2 "github.com/anytypeio/go-anytype-infrastructure-experiments/common/config" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/config"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/net/peer" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/net/peer"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/net/pool" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/net/pool"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/nodeconf" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/nodeconf"
@ -28,13 +28,13 @@ func New() Service {
type Service interface { type Service interface {
DeriveSpace(ctx context.Context, payload SpaceDerivePayload) (string, error) DeriveSpace(ctx context.Context, payload SpaceDerivePayload) (string, error)
CreateSpace(ctx context.Context, payload SpaceCreatePayload) (string, error) CreateSpace(ctx context.Context, payload SpaceCreatePayload) (string, error)
GetSpace(ctx context.Context, id string) (sp Space, err error) NewSpace(ctx context.Context, id string) (sp Space, err error)
AddSpace(ctx context.Context, spaceDescription SpaceDescription) (err error) AddSpace(ctx context.Context, spaceDescription SpaceDescription) (err error)
app.Component app.Component
} }
type service struct { type service struct {
config config2.Space config config.Space
account account.Service account account.Service
configurationService nodeconf.Service configurationService nodeconf.Service
storageProvider storage.SpaceStorageProvider storageProvider storage.SpaceStorageProvider
@ -43,7 +43,7 @@ type service struct {
} }
func (s *service) Init(a *app.App) (err error) { func (s *service) Init(a *app.App) (err error) {
s.config = a.MustComponent(config2.CName).(*config2.Config).Space s.config = a.MustComponent(config.CName).(*config.Config).Space
s.account = a.MustComponent(account.CName).(account.Service) s.account = a.MustComponent(account.CName).(account.Service)
s.storageProvider = a.MustComponent(storage.CName).(storage.SpaceStorageProvider) s.storageProvider = a.MustComponent(storage.CName).(storage.SpaceStorageProvider)
s.configurationService = a.MustComponent(nodeconf.CName).(nodeconf.Service) s.configurationService = a.MustComponent(nodeconf.CName).(nodeconf.Service)
@ -56,9 +56,7 @@ func (s *service) Name() (name string) {
return CName return CName
} }
func (s *service) CreateSpace( func (s *service) CreateSpace(ctx context.Context, payload SpaceCreatePayload) (id string, err error) {
ctx context.Context,
payload SpaceCreatePayload) (id string, err error) {
storageCreate, err := storagePayloadForSpaceCreate(payload) storageCreate, err := storagePayloadForSpaceCreate(payload)
if err != nil { if err != nil {
return return
@ -68,12 +66,10 @@ func (s *service) CreateSpace(
return return
} }
return store.ID(), nil return store.Id(), nil
} }
func (s *service) DeriveSpace( func (s *service) DeriveSpace(ctx context.Context, payload SpaceDerivePayload) (id string, err error) {
ctx context.Context,
payload SpaceDerivePayload) (id string, err error) {
storageCreate, err := storagePayloadForSpaceDerive(payload) storageCreate, err := storagePayloadForSpaceDerive(payload)
if err != nil { if err != nil {
return return
@ -83,7 +79,7 @@ func (s *service) DeriveSpace(
return return
} }
return store.ID(), nil return store.Id(), nil
} }
func (s *service) AddSpace(ctx context.Context, spaceDescription SpaceDescription) (err error) { func (s *service) AddSpace(ctx context.Context, spaceDescription SpaceDescription) (err error) {
@ -116,7 +112,7 @@ func (s *service) AddSpace(ctx context.Context, spaceDescription SpaceDescriptio
return return
} }
func (s *service) GetSpace(ctx context.Context, id string) (Space, error) { func (s *service) NewSpace(ctx context.Context, id string) (Space, error) {
st, err := s.storageProvider.SpaceStorage(id) st, err := s.storageProvider.SpaceStorage(id)
if err != nil { if err != nil {
if err != spacesyncproto.ErrSpaceMissing { if err != spacesyncproto.ErrSpaceMissing {
@ -143,32 +139,23 @@ func (s *service) GetSpace(ctx context.Context, id string) (Space, error) {
configuration: lastConfiguration, configuration: lastConfiguration,
storage: st, storage: st,
} }
if err := sp.Init(ctx); err != nil {
return nil, err
}
return sp, nil return sp, nil
} }
func (s *service) getSpaceStorageFromRemote(ctx context.Context, id string) (st storage.SpaceStorage, err error) { func (s *service) getSpaceStorageFromRemote(ctx context.Context, id string) (st storage.SpaceStorage, err error) {
var p peer.Peer var p peer.Peer
peerId, err := syncservice.GetPeerIdFromStreamContext(ctx) lastConfiguration := s.configurationService.GetLast()
if err == nil { // for nodes we always get remote space only if we have id in the context
p, err = s.pool.Dial(ctx, peerId) if lastConfiguration.IsResponsible(id) {
if err != nil { err = spacesyncproto.ErrSpaceMissing
return return
}
} else {
lastConfiguration := s.configurationService.GetLast()
// for nodes we always get remote space only if we have id in the context
if lastConfiguration.IsResponsible(id) {
err = spacesyncproto.ErrSpaceMissing
return
}
p, err = s.pool.DialOneOf(ctx, lastConfiguration.NodeIds(id))
if err != nil {
return
}
} }
p, err = s.pool.DialOneOf(ctx, lastConfiguration.NodeIds(id))
if err != nil {
return
}
cl := spacesyncproto.NewDRPCSpaceClient(p) cl := spacesyncproto.NewDRPCSpaceClient(p)
res, err := cl.PullSpace(ctx, &spacesyncproto.PullSpaceRequest{Id: id}) res, err := cl.PullSpace(ctx, &spacesyncproto.PullSpaceRequest{Id: id})
if err != nil { if err != nil {

View File

@ -15,9 +15,10 @@ import (
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/treegetter" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/treegetter"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/nodeconf" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/nodeconf"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/list" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/list"
tree "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/tree" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/tree"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/keys/asymmetric/encryptionkey" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/keys/asymmetric/encryptionkey"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/keys/asymmetric/signingkey" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/keys/asymmetric/signingkey"
"github.com/zeebo/errs"
"go.uber.org/zap" "go.uber.org/zap"
"sync" "sync"
"sync/atomic" "sync/atomic"
@ -58,6 +59,8 @@ func NewSpaceId(id string, repKey uint64) string {
type Space interface { type Space interface {
Id() string Id() string
Init(ctx context.Context) error
StoredIds() []string StoredIds() []string
Description() SpaceDescription Description() SpaceDescription
@ -206,7 +209,18 @@ func (s *space) Close() error {
s.isClosed.Store(true) s.isClosed.Store(true)
log.With(zap.String("id", s.id)).Debug("space closed") log.With(zap.String("id", s.id)).Debug("space closed")
}() }()
s.diffService.Close() var mError errs.Group
s.syncService.Close() if err := s.diffService.Close(); err != nil {
return s.storage.Close() mError.Add(err)
}
if err := s.syncService.Close(); err != nil {
mError.Add(err)
}
if err := s.aclList.Close(); err != nil {
mError.Add(err)
}
if err := s.storage.Close(); err != nil {
mError.Add(err)
}
return mError.Err()
} }

View File

@ -162,18 +162,18 @@ func (mr *MockSpaceStorageMockRecorder) CreateTreeStorage(arg0 interface{}) *gom
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateTreeStorage", reflect.TypeOf((*MockSpaceStorage)(nil).CreateTreeStorage), arg0) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateTreeStorage", reflect.TypeOf((*MockSpaceStorage)(nil).CreateTreeStorage), arg0)
} }
// ID mocks base method. // Id mocks base method.
func (m *MockSpaceStorage) ID() string { func (m *MockSpaceStorage) Id() string {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ID") ret := m.ctrl.Call(m, "Id")
ret0, _ := ret[0].(string) ret0, _ := ret[0].(string)
return ret0 return ret0
} }
// ID indicates an expected call of ID. // Id indicates an expected call of Id.
func (mr *MockSpaceStorageMockRecorder) ID() *gomock.Call { func (mr *MockSpaceStorageMockRecorder) Id() *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ID", reflect.TypeOf((*MockSpaceStorage)(nil).ID)) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Id", reflect.TypeOf((*MockSpaceStorage)(nil).Id))
} }
// SpaceHeader mocks base method. // SpaceHeader mocks base method.

View File

@ -6,7 +6,7 @@ import (
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/app" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/app"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/aclrecordproto" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/aclrecordproto"
storage "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/storage" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/storage"
) )
const CName = "commonspace.storage" const CName = "commonspace.storage"
@ -16,7 +16,7 @@ var ErrSpaceStorageMissing = errors.New("space storage missing")
type SpaceStorage interface { type SpaceStorage interface {
storage.Provider storage.Provider
ID() string Id() string
ACLStorage() (storage.ListStorage, error) ACLStorage() (storage.ListStorage, error)
SpaceHeader() (*spacesyncproto.RawSpaceHeaderWithId, error) SpaceHeader() (*spacesyncproto.RawSpaceHeaderWithId, error)
StoredIds() ([]string, error) StoredIds() ([]string, error)

View File

@ -0,0 +1,31 @@
package syncacl
import (
"context"
"fmt"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/aclrecordproto"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/list"
)
type syncAclHandler struct {
acl list.ACLList
}
func (s *syncAclHandler) HandleMessage(ctx context.Context, senderId string, req *spacesyncproto.ObjectSyncMessage) (err error) {
aclMsg := &aclrecordproto.ACLSyncMessage{}
if err = aclMsg.Unmarshal(req.Payload); err != nil {
return
}
content := aclMsg.GetContent()
switch {
case content.GetAddRecords() != nil:
return s.handleAddRecords(ctx, senderId, content.GetAddRecords())
default:
return fmt.Errorf("unexpected aclSync message: %T", content.Value)
}
}
func (s *syncAclHandler) handleAddRecords(ctx context.Context, senderId string, addRecord *aclrecordproto.ACLAddRecords) (err error) {
return
}

View File

@ -51,8 +51,10 @@ func (ACLUserPermissions) EnumDescriptor() ([]byte, []int) {
} }
type RawACLRecord struct { type RawACLRecord struct {
Payload []byte `protobuf:"bytes,1,opt,name=payload,proto3" json:"payload,omitempty"` Payload []byte `protobuf:"bytes,1,opt,name=payload,proto3" json:"payload,omitempty"`
Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"`
AcceptorIdentity []byte `protobuf:"bytes,3,opt,name=acceptorIdentity,proto3" json:"acceptorIdentity,omitempty"`
AcceptorSignature []byte `protobuf:"bytes,4,opt,name=acceptorSignature,proto3" json:"acceptorSignature,omitempty"`
} }
func (m *RawACLRecord) Reset() { *m = RawACLRecord{} } func (m *RawACLRecord) Reset() { *m = RawACLRecord{} }
@ -102,6 +104,20 @@ func (m *RawACLRecord) GetSignature() []byte {
return nil return nil
} }
func (m *RawACLRecord) GetAcceptorIdentity() []byte {
if m != nil {
return m.AcceptorIdentity
}
return nil
}
func (m *RawACLRecord) GetAcceptorSignature() []byte {
if m != nil {
return m.AcceptorSignature
}
return nil
}
type RawACLRecordWithId struct { type RawACLRecordWithId struct {
Payload []byte `protobuf:"bytes,1,opt,name=payload,proto3" json:"payload,omitempty"` Payload []byte `protobuf:"bytes,1,opt,name=payload,proto3" json:"payload,omitempty"`
Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"` Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"`
@ -987,6 +1003,168 @@ func (m *ACLUserPermissionChange) GetPermissions() ACLUserPermissions {
return ACLUserPermissions_Admin return ACLUserPermissions_Admin
} }
type ACLSyncMessage struct {
Content *ACLSyncContentValue `protobuf:"bytes,2,opt,name=content,proto3" json:"content,omitempty"`
}
func (m *ACLSyncMessage) Reset() { *m = ACLSyncMessage{} }
func (m *ACLSyncMessage) String() string { return proto.CompactTextString(m) }
func (*ACLSyncMessage) ProtoMessage() {}
func (*ACLSyncMessage) Descriptor() ([]byte, []int) {
return fileDescriptor_14abe0d1b4206d54, []int{14}
}
func (m *ACLSyncMessage) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *ACLSyncMessage) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_ACLSyncMessage.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *ACLSyncMessage) XXX_Merge(src proto.Message) {
xxx_messageInfo_ACLSyncMessage.Merge(m, src)
}
func (m *ACLSyncMessage) XXX_Size() int {
return m.Size()
}
func (m *ACLSyncMessage) XXX_DiscardUnknown() {
xxx_messageInfo_ACLSyncMessage.DiscardUnknown(m)
}
var xxx_messageInfo_ACLSyncMessage proto.InternalMessageInfo
func (m *ACLSyncMessage) GetContent() *ACLSyncContentValue {
if m != nil {
return m.Content
}
return nil
}
// ACLSyncContentValue provides different types for acl sync
type ACLSyncContentValue struct {
// Types that are valid to be assigned to Value:
//
// *ACLSyncContentValue_AddRecords
Value isACLSyncContentValue_Value `protobuf_oneof:"value"`
}
func (m *ACLSyncContentValue) Reset() { *m = ACLSyncContentValue{} }
func (m *ACLSyncContentValue) String() string { return proto.CompactTextString(m) }
func (*ACLSyncContentValue) ProtoMessage() {}
func (*ACLSyncContentValue) Descriptor() ([]byte, []int) {
return fileDescriptor_14abe0d1b4206d54, []int{15}
}
func (m *ACLSyncContentValue) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *ACLSyncContentValue) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_ACLSyncContentValue.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *ACLSyncContentValue) XXX_Merge(src proto.Message) {
xxx_messageInfo_ACLSyncContentValue.Merge(m, src)
}
func (m *ACLSyncContentValue) XXX_Size() int {
return m.Size()
}
func (m *ACLSyncContentValue) XXX_DiscardUnknown() {
xxx_messageInfo_ACLSyncContentValue.DiscardUnknown(m)
}
var xxx_messageInfo_ACLSyncContentValue proto.InternalMessageInfo
type isACLSyncContentValue_Value interface {
isACLSyncContentValue_Value()
MarshalTo([]byte) (int, error)
Size() int
}
type ACLSyncContentValue_AddRecords struct {
AddRecords *ACLAddRecords `protobuf:"bytes,1,opt,name=addRecords,proto3,oneof" json:"addRecords,omitempty"`
}
func (*ACLSyncContentValue_AddRecords) isACLSyncContentValue_Value() {}
func (m *ACLSyncContentValue) GetValue() isACLSyncContentValue_Value {
if m != nil {
return m.Value
}
return nil
}
func (m *ACLSyncContentValue) GetAddRecords() *ACLAddRecords {
if x, ok := m.GetValue().(*ACLSyncContentValue_AddRecords); ok {
return x.AddRecords
}
return nil
}
// XXX_OneofWrappers is for the internal use of the proto package.
func (*ACLSyncContentValue) XXX_OneofWrappers() []interface{} {
return []interface{}{
(*ACLSyncContentValue_AddRecords)(nil),
}
}
type ACLAddRecords struct {
Records []*RawACLRecordWithId `protobuf:"bytes,1,rep,name=records,proto3" json:"records,omitempty"`
}
func (m *ACLAddRecords) Reset() { *m = ACLAddRecords{} }
func (m *ACLAddRecords) String() string { return proto.CompactTextString(m) }
func (*ACLAddRecords) ProtoMessage() {}
func (*ACLAddRecords) Descriptor() ([]byte, []int) {
return fileDescriptor_14abe0d1b4206d54, []int{16}
}
func (m *ACLAddRecords) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *ACLAddRecords) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_ACLAddRecords.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *ACLAddRecords) XXX_Merge(src proto.Message) {
xxx_messageInfo_ACLAddRecords.Merge(m, src)
}
func (m *ACLAddRecords) XXX_Size() int {
return m.Size()
}
func (m *ACLAddRecords) XXX_DiscardUnknown() {
xxx_messageInfo_ACLAddRecords.DiscardUnknown(m)
}
var xxx_messageInfo_ACLAddRecords proto.InternalMessageInfo
func (m *ACLAddRecords) GetRecords() []*RawACLRecordWithId {
if m != nil {
return m.Records
}
return nil
}
func init() { func init() {
proto.RegisterEnum("aclrecord.ACLUserPermissions", ACLUserPermissions_name, ACLUserPermissions_value) proto.RegisterEnum("aclrecord.ACLUserPermissions", ACLUserPermissions_name, ACLUserPermissions_value)
proto.RegisterType((*RawACLRecord)(nil), "aclrecord.RawACLRecord") proto.RegisterType((*RawACLRecord)(nil), "aclrecord.RawACLRecord")
@ -1004,6 +1182,9 @@ func init() {
proto.RegisterType((*ACLUserRemove)(nil), "aclrecord.ACLUserRemove") proto.RegisterType((*ACLUserRemove)(nil), "aclrecord.ACLUserRemove")
proto.RegisterType((*ACLReadKeyReplace)(nil), "aclrecord.ACLReadKeyReplace") proto.RegisterType((*ACLReadKeyReplace)(nil), "aclrecord.ACLReadKeyReplace")
proto.RegisterType((*ACLUserPermissionChange)(nil), "aclrecord.ACLUserPermissionChange") proto.RegisterType((*ACLUserPermissionChange)(nil), "aclrecord.ACLUserPermissionChange")
proto.RegisterType((*ACLSyncMessage)(nil), "aclrecord.ACLSyncMessage")
proto.RegisterType((*ACLSyncContentValue)(nil), "aclrecord.ACLSyncContentValue")
proto.RegisterType((*ACLAddRecords)(nil), "aclrecord.ACLAddRecords")
} }
func init() { func init() {
@ -1011,61 +1192,67 @@ func init() {
} }
var fileDescriptor_14abe0d1b4206d54 = []byte{ var fileDescriptor_14abe0d1b4206d54 = []byte{
// 854 bytes of a gzipped FileDescriptorProto // 954 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x56, 0x4f, 0x6f, 0x1b, 0x45, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x56, 0x4f, 0x6f, 0x1b, 0x45,
0x14, 0xdf, 0x59, 0x3b, 0x71, 0xf6, 0xd9, 0x6d, 0xdc, 0x11, 0xa4, 0xab, 0xa8, 0x58, 0xd6, 0x8a, 0x14, 0xf7, 0xac, 0x9d, 0x38, 0x7e, 0x76, 0x13, 0x67, 0x80, 0x74, 0x15, 0x15, 0x2b, 0x5a, 0x71,
0x83, 0x55, 0x81, 0x0b, 0x06, 0xa9, 0x28, 0x07, 0x90, 0x6b, 0x5a, 0x39, 0x24, 0x87, 0x6a, 0x02, 0x88, 0xaa, 0xe2, 0x82, 0x41, 0x4a, 0x95, 0x03, 0xc8, 0x35, 0x45, 0x76, 0x13, 0xa4, 0x6a, 0x02,
0x14, 0x71, 0x9b, 0xee, 0x8e, 0xe2, 0x51, 0xed, 0xdd, 0xd5, 0xec, 0xd8, 0xc8, 0x47, 0xce, 0x5c, 0x14, 0xf5, 0x36, 0xdd, 0x1d, 0x25, 0xab, 0xda, 0xbb, 0xab, 0x99, 0xb1, 0xd1, 0x1e, 0x39, 0x73,
0xe0, 0x23, 0xf0, 0x41, 0xb8, 0x23, 0x71, 0xe9, 0x05, 0xc4, 0x11, 0x25, 0x1f, 0x83, 0x0b, 0x9a, 0x81, 0x6f, 0x00, 0x1f, 0x84, 0x3b, 0x12, 0x97, 0x5e, 0x40, 0x1c, 0x51, 0xf2, 0x31, 0xb8, 0xa0,
0xd9, 0xff, 0xbb, 0xb6, 0x45, 0x25, 0xab, 0x87, 0xc4, 0xf3, 0xde, 0xfb, 0xbd, 0xe7, 0xdf, 0xfc, 0x99, 0xd9, 0xff, 0xeb, 0x44, 0x54, 0x8a, 0x7a, 0x48, 0x32, 0xf3, 0xde, 0xef, 0x4d, 0x7e, 0xef,
0xe6, 0xcd, 0x1b, 0xc3, 0x87, 0xe1, 0xab, 0xeb, 0x47, 0xd4, 0x9d, 0xab, 0x3f, 0xc1, 0xdc, 0x40, 0xf7, 0xde, 0xbc, 0x59, 0xf8, 0x30, 0x7a, 0x75, 0xfe, 0x90, 0xba, 0x73, 0xf5, 0xc3, 0x99, 0x1b,
0x78, 0xa1, 0x08, 0x64, 0xf0, 0x48, 0xff, 0x8f, 0x72, 0xef, 0x50, 0x3b, 0xb0, 0x95, 0x39, 0x9c, 0x72, 0x2f, 0xe2, 0xa1, 0x0c, 0x1f, 0xea, 0xdf, 0x22, 0xb7, 0x0e, 0xb5, 0x01, 0x77, 0x32, 0x83,
0x67, 0xd0, 0x21, 0xf4, 0x87, 0xf1, 0xe4, 0x92, 0x68, 0x1b, 0xdb, 0xd0, 0x0a, 0xe9, 0x7a, 0x1e, 0xf3, 0x0b, 0x82, 0x1e, 0xa1, 0xdf, 0x8f, 0x27, 0xa7, 0x44, 0x1b, 0xb0, 0x0d, 0xed, 0x88, 0xc6,
0x50, 0xcf, 0x46, 0x7d, 0x34, 0xe8, 0x90, 0xd4, 0xc4, 0x0f, 0xc0, 0x8a, 0xf8, 0xb5, 0x4f, 0xe5, 0xf3, 0x90, 0x7a, 0x36, 0x3a, 0x40, 0x87, 0x3d, 0x92, 0x6e, 0xf1, 0x3d, 0xe8, 0x08, 0xff, 0x3c,
0x52, 0x30, 0xdb, 0xd4, 0xb1, 0xdc, 0xe1, 0x7c, 0x0e, 0xb8, 0x58, 0xe7, 0x05, 0x97, 0xb3, 0xf3, 0xa0, 0x72, 0xc9, 0x99, 0x6d, 0x69, 0x5f, 0x6e, 0xc0, 0xf7, 0xa1, 0x4f, 0x5d, 0x97, 0x45, 0x32,
0x5d, 0xd5, 0xee, 0x82, 0xc9, 0x3d, 0x5d, 0xc6, 0x22, 0x26, 0xf7, 0x9c, 0x5f, 0x11, 0x58, 0x39, 0xe4, 0x33, 0x8f, 0x05, 0xd2, 0x97, 0xb1, 0xdd, 0xd4, 0xa0, 0x9a, 0x1d, 0x3f, 0x80, 0xdd, 0xd4,
0x8b, 0x13, 0x38, 0x0c, 0x05, 0x5b, 0x9d, 0xc7, 0x69, 0x16, 0x49, 0x2c, 0x7c, 0x0a, 0x47, 0xdc, 0x76, 0x96, 0x9d, 0xd8, 0xd2, 0xe0, 0xba, 0xc3, 0xf9, 0x0c, 0x70, 0x91, 0xe1, 0x73, 0x5f, 0x5e,
0x63, 0xbe, 0xe4, 0x72, 0x9d, 0x50, 0xc8, 0x6c, 0x8c, 0xa1, 0xe9, 0x51, 0x49, 0xed, 0x86, 0xf6, 0xcc, 0x6e, 0xe2, 0xb9, 0x0d, 0x96, 0xef, 0x69, 0x82, 0x1d, 0x62, 0xf9, 0x9e, 0xf3, 0x2b, 0x82,
0xeb, 0x35, 0x1e, 0x02, 0x76, 0x97, 0x42, 0x30, 0x5f, 0x12, 0x46, 0xbd, 0x0b, 0xb6, 0x9e, 0xd2, 0x4e, 0x9e, 0xdf, 0x1e, 0x6c, 0x46, 0x9c, 0xad, 0x66, 0x26, 0xac, 0x43, 0x92, 0x1d, 0xde, 0x87,
0x68, 0x66, 0x37, 0xfb, 0x68, 0xd0, 0x24, 0x1b, 0x22, 0x6a, 0x8f, 0x92, 0x2f, 0x58, 0x24, 0xe9, 0x2d, 0x3f, 0xe5, 0x6d, 0x92, 0xcb, 0xf6, 0x18, 0x43, 0xcb, 0xa3, 0x92, 0x26, 0xf9, 0xe8, 0x35,
0x22, 0xb4, 0x0f, 0xfa, 0x68, 0xd0, 0x20, 0xb9, 0xc3, 0xf9, 0xc9, 0x84, 0x96, 0xe2, 0x18, 0x04, 0x1e, 0x02, 0x76, 0x97, 0x9c, 0xb3, 0x40, 0x12, 0x46, 0xbd, 0x13, 0x16, 0x4f, 0xa9, 0xb8, 0xd0,
0xb2, 0xc4, 0x04, 0x55, 0x98, 0xbc, 0x0f, 0x77, 0x98, 0xef, 0x8a, 0x75, 0x28, 0x79, 0xe0, 0x5f, 0x49, 0xb4, 0xc8, 0x1a, 0x8f, 0x52, 0x4f, 0xfa, 0x0b, 0x26, 0x24, 0x5d, 0x44, 0xf6, 0xc6, 0x01,
0xb0, 0x94, 0x6a, 0xd9, 0xa9, 0xb4, 0x89, 0x42, 0xea, 0xb2, 0x73, 0x4f, 0x53, 0xb6, 0x48, 0x6a, 0x3a, 0x6c, 0x92, 0xdc, 0xe0, 0xfc, 0x68, 0x41, 0x5b, 0x71, 0x0c, 0x43, 0x59, 0x62, 0x82, 0x2a,
0xe2, 0x87, 0xd0, 0x4d, 0xa0, 0xcc, 0x4b, 0xd8, 0x69, 0xce, 0x1d, 0x52, 0xf3, 0x2b, 0xac, 0xc7, 0x4c, 0x3e, 0x80, 0x3b, 0x2c, 0x70, 0x79, 0x1c, 0x49, 0x3f, 0x0c, 0x4e, 0x58, 0x4a, 0xb5, 0x6c,
0x04, 0x5f, 0x51, 0x55, 0xf6, 0xca, 0x9d, 0xb1, 0x05, 0xd3, 0xc4, 0x2d, 0x52, 0xf3, 0x6f, 0x51, 0x54, 0xda, 0x88, 0x88, 0xba, 0x6c, 0xe6, 0x69, 0xca, 0x1d, 0x92, 0x6e, 0x55, 0x95, 0x12, 0x28,
0xe3, 0xf0, 0xff, 0xa9, 0xd1, 0xaa, 0xaa, 0xf1, 0xa7, 0x09, 0xc7, 0xe3, 0xc9, 0xe5, 0x24, 0xf0, 0xf3, 0x12, 0x76, 0x89, 0xf0, 0x35, 0xbb, 0xc2, 0x7a, 0x8c, 0xfb, 0x2b, 0xaa, 0x8e, 0x3d, 0x73,
0x25, 0xf3, 0xe5, 0xb7, 0x74, 0xbe, 0x64, 0xf8, 0x63, 0x68, 0x2d, 0x23, 0x26, 0xc6, 0x5e, 0x7c, 0x2f, 0xd8, 0x82, 0x69, 0xe2, 0x1d, 0x52, 0xb3, 0x5f, 0xa3, 0xc6, 0xe6, 0xff, 0x53, 0xa3, 0x5d,
0x70, 0xed, 0xd1, 0xbb, 0xc3, 0xbc, 0xf7, 0xc6, 0x93, 0xcb, 0x6f, 0xe2, 0xe0, 0xd4, 0x20, 0x29, 0x55, 0xe3, 0x4f, 0x0b, 0x76, 0xc6, 0x93, 0xd3, 0x49, 0x18, 0x48, 0x16, 0xc8, 0x6f, 0xe9, 0x7c,
0x0e, 0x9f, 0x01, 0xa8, 0x25, 0x61, 0x8b, 0x60, 0x15, 0xf7, 0x55, 0x7b, 0x64, 0xd7, 0xb3, 0xe2, 0xc9, 0xf0, 0xc7, 0xd0, 0x5e, 0x0a, 0xc6, 0xc7, 0x9e, 0x29, 0x5c, 0x77, 0xf4, 0xde, 0x30, 0x6f,
0xf8, 0xd4, 0x20, 0x05, 0x34, 0xfe, 0x0e, 0xde, 0x51, 0xd6, 0x73, 0x26, 0x16, 0x3c, 0x8a, 0x78, 0xeb, 0xf1, 0xe4, 0xf4, 0x1b, 0xe3, 0x9c, 0x36, 0x48, 0x8a, 0xc3, 0xc7, 0x00, 0x6a, 0x49, 0xd8,
0xe0, 0x4f, 0x66, 0xd4, 0xbf, 0x66, 0x5a, 0xcf, 0xf6, 0xc8, 0xa9, 0x57, 0xa9, 0x22, 0xa7, 0x06, 0x22, 0x5c, 0x99, 0x8e, 0xed, 0x8e, 0xec, 0x7a, 0x94, 0xf1, 0x4f, 0x1b, 0xa4, 0x80, 0xc6, 0xdf,
0xd9, 0x58, 0x21, 0x65, 0x75, 0xee, 0xaf, 0xb8, 0x64, 0x5a, 0xfc, 0x8d, 0xac, 0xe2, 0x78, 0xca, 0xc1, 0xbb, 0x6a, 0xf7, 0x8c, 0xf1, 0x85, 0x2f, 0x84, 0x1f, 0x06, 0x93, 0x0b, 0x1a, 0x9c, 0x33,
0x2a, 0xb6, 0xf0, 0xa7, 0x70, 0xa4, 0xac, 0xaf, 0x02, 0xee, 0xeb, 0xa3, 0x68, 0x8f, 0x4e, 0xea, 0xad, 0x67, 0x77, 0xe4, 0xd4, 0x4f, 0xa9, 0x22, 0xa7, 0x0d, 0xb2, 0xf6, 0x84, 0x94, 0xd5, 0x2c,
0x99, 0x2a, 0x3a, 0x35, 0x48, 0x86, 0x7c, 0xd2, 0x82, 0x83, 0x95, 0xd2, 0xd0, 0x79, 0xaa, 0x9b, 0x58, 0xf9, 0xd2, 0x74, 0xfd, 0x5a, 0x56, 0xc6, 0x9f, 0xb2, 0x32, 0x3b, 0xfc, 0x29, 0x6c, 0xa9,
0xec, 0x4b, 0xd5, 0xbe, 0x67, 0x00, 0xd4, 0x9d, 0x27, 0x0a, 0xdb, 0xa8, 0xdf, 0x18, 0xb4, 0x47, 0xdd, 0xd3, 0xd0, 0x0f, 0x74, 0x29, 0xba, 0xa3, 0xbd, 0x7a, 0xa4, 0xf2, 0x4e, 0x1b, 0x24, 0x43,
0xa7, 0xe5, 0x5a, 0x45, 0xf9, 0x49, 0x01, 0xed, 0xfc, 0x8b, 0xe0, 0x68, 0x3c, 0xb9, 0xbc, 0x92, 0x3e, 0x6e, 0xc3, 0xc6, 0x4a, 0x69, 0xe8, 0x3c, 0xd1, 0x4d, 0xf6, 0x85, 0x6a, 0xdf, 0x63, 0x00,
0x54, 0x32, 0xd5, 0x91, 0x22, 0x3f, 0x58, 0x16, 0xe9, 0x5a, 0x4d, 0x52, 0x76, 0xe2, 0xc7, 0xf1, 0xea, 0xce, 0x13, 0x85, 0x6d, 0x74, 0xd0, 0x3c, 0xec, 0x8e, 0xf6, 0xcb, 0x67, 0x15, 0xe5, 0x27,
0xa6, 0x75, 0x4a, 0x64, 0x9b, 0xfa, 0xeb, 0xee, 0xd7, 0xa9, 0xeb, 0x38, 0x29, 0x40, 0xf1, 0x19, 0x05, 0xb4, 0xf3, 0x2f, 0x82, 0xad, 0xf1, 0xe4, 0xf4, 0x4c, 0x52, 0xc9, 0x54, 0x47, 0xf2, 0xbc,
0xb4, 0xb8, 0xde, 0x7b, 0x64, 0x37, 0x74, 0x56, 0xbf, 0x9c, 0xa5, 0x61, 0xc3, 0x58, 0x9e, 0xe8, 0xb0, 0x4c, 0xe8, 0xb3, 0x5a, 0xa4, 0x6c, 0xc4, 0x47, 0x26, 0x69, 0x1d, 0x22, 0x6c, 0x4b, 0xff,
0xa9, 0x2f, 0xc5, 0x9a, 0xa4, 0x09, 0xa7, 0x5f, 0x43, 0xa7, 0x18, 0xc0, 0x5d, 0x68, 0xbc, 0x62, 0xbb, 0xbb, 0x75, 0xea, 0xda, 0x4f, 0x0a, 0x50, 0x7c, 0x0c, 0x6d, 0x5f, 0xe7, 0x2e, 0xec, 0xa6,
0xeb, 0xe4, 0xde, 0xab, 0x25, 0x1e, 0x26, 0xca, 0x6c, 0x6f, 0x8e, 0xb8, 0x00, 0x89, 0x61, 0x67, 0x8e, 0x3a, 0x28, 0x47, 0x69, 0xd8, 0xd0, 0xc8, 0x23, 0x9e, 0x04, 0x92, 0xc7, 0x24, 0x0d, 0xd8,
0xe6, 0x67, 0xc8, 0xf9, 0x05, 0x41, 0xa7, 0x48, 0x77, 0x0f, 0xf7, 0xf5, 0x0b, 0x68, 0x87, 0x59, 0xff, 0x1a, 0x7a, 0x45, 0x07, 0xee, 0x43, 0xf3, 0x15, 0x8b, 0x93, 0x7b, 0xaf, 0x96, 0x78, 0x98,
0x9b, 0x44, 0xba, 0xc7, 0xee, 0x8e, 0xde, 0xdb, 0xd5, 0x63, 0x11, 0x29, 0x66, 0x38, 0xbf, 0x21, 0x28, 0x73, 0x7d, 0x73, 0x98, 0x03, 0x88, 0x81, 0x1d, 0x5b, 0x8f, 0x90, 0xf3, 0x33, 0x82, 0x5e,
0x80, 0xfc, 0x0e, 0xec, 0x81, 0xd1, 0x07, 0x70, 0xaf, 0x3a, 0x0f, 0xe2, 0x03, 0xe8, 0x90, 0x7a, 0x91, 0xee, 0x2d, 0xdc, 0xd7, 0xcf, 0xa1, 0x1b, 0x65, 0x6d, 0x22, 0x74, 0x8f, 0x6d, 0x8f, 0xde,
0xa0, 0xca, 0xbf, 0xf9, 0xc6, 0xfc, 0xff, 0x42, 0x70, 0xa7, 0x24, 0x38, 0x1e, 0xc0, 0x31, 0x75, 0xbf, 0xa9, 0xc7, 0x04, 0x29, 0x46, 0x38, 0xbf, 0x21, 0x80, 0xfc, 0x0e, 0xdc, 0x02, 0xa3, 0x07,
0x5d, 0x16, 0xca, 0xe7, 0xcb, 0x97, 0x73, 0xee, 0x5e, 0xb0, 0x74, 0x27, 0x55, 0x77, 0x81, 0xea, 0xb0, 0x5b, 0x9d, 0x07, 0xa6, 0x00, 0x3d, 0x52, 0x77, 0x54, 0xf9, 0xb7, 0xde, 0x98, 0xff, 0x5f,
0xd5, 0x7a, 0x91, 0x4e, 0x1e, 0x53, 0x4f, 0x9e, 0x7a, 0xe0, 0x6d, 0x6f, 0xec, 0x0f, 0x04, 0xed, 0x08, 0xee, 0x94, 0x04, 0xc7, 0x87, 0xb0, 0x63, 0x5e, 0x82, 0x67, 0xcb, 0x97, 0x73, 0xdf, 0x3d,
0xc2, 0xb5, 0xdc, 0xc3, 0xc9, 0x64, 0xc2, 0x5c, 0x65, 0x2f, 0x66, 0xa3, 0x28, 0x4c, 0xe6, 0xc6, 0x61, 0x69, 0x26, 0x55, 0x73, 0x81, 0xea, 0x59, 0xbc, 0x48, 0x27, 0x8f, 0xa5, 0x27, 0x4f, 0xdd,
0x0e, 0x74, 0x32, 0xad, 0xf2, 0x39, 0x5f, 0xf2, 0x6d, 0x96, 0xe3, 0x60, 0x8b, 0x1c, 0x4e, 0x94, 0xf1, 0xb6, 0x13, 0xfb, 0x03, 0x41, 0xb7, 0x70, 0x2d, 0x6f, 0xa1, 0x32, 0x99, 0x30, 0xf9, 0xcb,
0x9d, 0x52, 0x32, 0x25, 0x77, 0x6d, 0xe7, 0x19, 0x1c, 0x27, 0x33, 0x80, 0xb0, 0x70, 0x4e, 0xdd, 0xd9, 0x2c, 0x0a, 0x93, 0x99, 0xb1, 0x03, 0xbd, 0x4c, 0xab, 0x7c, 0xce, 0x97, 0x6c, 0xeb, 0xe5,
0xec, 0xde, 0x3f, 0x28, 0xeb, 0x47, 0x4a, 0x20, 0x52, 0x4d, 0x72, 0x7e, 0x44, 0x70, 0xaf, 0x06, 0xd8, 0xb8, 0x46, 0x0e, 0x47, 0x64, 0x55, 0x4a, 0xa6, 0xe4, 0x4d, 0xe9, 0x7c, 0x09, 0x3b, 0xc9,
0xdb, 0x83, 0x90, 0x9b, 0x9e, 0xc2, 0xc6, 0xe6, 0xa7, 0xd0, 0x59, 0xc1, 0xfd, 0x2d, 0x63, 0x7e, 0x0c, 0x20, 0x2c, 0x9a, 0x53, 0x37, 0xbb, 0xf7, 0xf7, 0xca, 0xfa, 0x91, 0x12, 0x88, 0x54, 0x83,
0x27, 0x91, 0x4a, 0xfb, 0x98, 0x6f, 0xda, 0x3e, 0x0f, 0x1f, 0x03, 0xae, 0x43, 0xb0, 0x05, 0x07, 0x9c, 0x1f, 0x10, 0xec, 0xd6, 0x60, 0xb7, 0x20, 0xe4, 0xba, 0xa7, 0xb0, 0xb9, 0xfe, 0x29, 0x74,
0x63, 0x6f, 0xc1, 0xfd, 0xae, 0x81, 0x01, 0x0e, 0x5f, 0x08, 0x2e, 0x99, 0xe8, 0x22, 0xb5, 0x56, 0x56, 0x70, 0xf7, 0x9a, 0x31, 0x7f, 0x23, 0x91, 0x4a, 0xfb, 0x58, 0x6f, 0xdc, 0x3e, 0x4f, 0x61,
0x7c, 0x99, 0xe8, 0x9a, 0x4f, 0x3e, 0xfa, 0xfd, 0xa6, 0x87, 0x5e, 0xdf, 0xf4, 0xd0, 0x3f, 0x37, 0x5b, 0xcd, 0xb8, 0x38, 0x70, 0xbf, 0x62, 0x42, 0xd0, 0x73, 0x86, 0x1f, 0x41, 0xdb, 0x4d, 0x86,
0x3d, 0xf4, 0xf3, 0x6d, 0xcf, 0x78, 0x7d, 0xdb, 0x33, 0xfe, 0xbe, 0xed, 0x19, 0xdf, 0x9f, 0x6c, 0xb6, 0x99, 0x59, 0x83, 0xca, 0x3c, 0x8c, 0x03, 0xb7, 0x34, 0xb8, 0x53, 0xb8, 0xf3, 0x02, 0xde,
0xfe, 0x3d, 0xf7, 0xf2, 0x50, 0x7f, 0x7c, 0xf2, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x80, 0xdf, 0x59, 0xe3, 0xd7, 0x0f, 0x81, 0xe7, 0x99, 0x8f, 0x23, 0x91, 0x3c, 0xad, 0x95, 0x39, 0x38, 0xce,
0xf6, 0x6c, 0xf0, 0x09, 0x00, 0x00, 0xfc, 0xea, 0x39, 0xca, 0xd1, 0xf9, 0xc3, 0x32, 0xd5, 0x8d, 0x91, 0xe3, 0xf0, 0x11, 0xb4, 0x79,
0x76, 0xa4, 0x2a, 0x7a, 0x31, 0xeb, 0xfa, 0xd7, 0x1c, 0x49, 0xd1, 0xf7, 0x8f, 0x00, 0xd7, 0x45,
0xc1, 0x1d, 0xd8, 0x18, 0x7b, 0x0b, 0x3f, 0xe8, 0x37, 0x30, 0xc0, 0xe6, 0x73, 0xee, 0x4b, 0xc6,
0xfb, 0x48, 0xad, 0x55, 0x85, 0x18, 0xef, 0x5b, 0x8f, 0x3f, 0xfa, 0xfd, 0x72, 0x80, 0x5e, 0x5f,
0x0e, 0xd0, 0x3f, 0x97, 0x03, 0xf4, 0xd3, 0xd5, 0xa0, 0xf1, 0xfa, 0x6a, 0xd0, 0xf8, 0xfb, 0x6a,
0xd0, 0x78, 0xb1, 0xb7, 0xfe, 0xe3, 0xf8, 0xe5, 0xa6, 0xfe, 0xf3, 0xc9, 0x7f, 0x01, 0x00, 0x00,
0xff, 0xff, 0xa9, 0xbd, 0x7e, 0xe0, 0x3d, 0x0b, 0x00, 0x00,
} }
func (m *RawACLRecord) Marshal() (dAtA []byte, err error) { func (m *RawACLRecord) Marshal() (dAtA []byte, err error) {
@ -1088,6 +1275,20 @@ func (m *RawACLRecord) MarshalToSizedBuffer(dAtA []byte) (int, error) {
_ = i _ = i
var l int var l int
_ = l _ = l
if len(m.AcceptorSignature) > 0 {
i -= len(m.AcceptorSignature)
copy(dAtA[i:], m.AcceptorSignature)
i = encodeVarintAclrecord(dAtA, i, uint64(len(m.AcceptorSignature)))
i--
dAtA[i] = 0x22
}
if len(m.AcceptorIdentity) > 0 {
i -= len(m.AcceptorIdentity)
copy(dAtA[i:], m.AcceptorIdentity)
i = encodeVarintAclrecord(dAtA, i, uint64(len(m.AcceptorIdentity)))
i--
dAtA[i] = 0x1a
}
if len(m.Signature) > 0 { if len(m.Signature) > 0 {
i -= len(m.Signature) i -= len(m.Signature)
copy(dAtA[i:], m.Signature) copy(dAtA[i:], m.Signature)
@ -1844,6 +2045,131 @@ func (m *ACLUserPermissionChange) MarshalToSizedBuffer(dAtA []byte) (int, error)
return len(dAtA) - i, nil return len(dAtA) - i, nil
} }
func (m *ACLSyncMessage) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *ACLSyncMessage) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *ACLSyncMessage) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if m.Content != nil {
{
size, err := m.Content.MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintAclrecord(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0x12
}
return len(dAtA) - i, nil
}
func (m *ACLSyncContentValue) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *ACLSyncContentValue) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *ACLSyncContentValue) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if m.Value != nil {
{
size := m.Value.Size()
i -= size
if _, err := m.Value.MarshalTo(dAtA[i:]); err != nil {
return 0, err
}
}
}
return len(dAtA) - i, nil
}
func (m *ACLSyncContentValue_AddRecords) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *ACLSyncContentValue_AddRecords) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
if m.AddRecords != nil {
{
size, err := m.AddRecords.MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintAclrecord(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0xa
}
return len(dAtA) - i, nil
}
func (m *ACLAddRecords) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *ACLAddRecords) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *ACLAddRecords) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if len(m.Records) > 0 {
for iNdEx := len(m.Records) - 1; iNdEx >= 0; iNdEx-- {
{
size, err := m.Records[iNdEx].MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintAclrecord(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0xa
}
}
return len(dAtA) - i, nil
}
func encodeVarintAclrecord(dAtA []byte, offset int, v uint64) int { func encodeVarintAclrecord(dAtA []byte, offset int, v uint64) int {
offset -= sovAclrecord(v) offset -= sovAclrecord(v)
base := offset base := offset
@ -1869,6 +2195,14 @@ func (m *RawACLRecord) Size() (n int) {
if l > 0 { if l > 0 {
n += 1 + l + sovAclrecord(uint64(l)) n += 1 + l + sovAclrecord(uint64(l))
} }
l = len(m.AcceptorIdentity)
if l > 0 {
n += 1 + l + sovAclrecord(uint64(l))
}
l = len(m.AcceptorSignature)
if l > 0 {
n += 1 + l + sovAclrecord(uint64(l))
}
return n return n
} }
@ -2231,6 +2565,58 @@ func (m *ACLUserPermissionChange) Size() (n int) {
return n return n
} }
func (m *ACLSyncMessage) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
if m.Content != nil {
l = m.Content.Size()
n += 1 + l + sovAclrecord(uint64(l))
}
return n
}
func (m *ACLSyncContentValue) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
if m.Value != nil {
n += m.Value.Size()
}
return n
}
func (m *ACLSyncContentValue_AddRecords) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
if m.AddRecords != nil {
l = m.AddRecords.Size()
n += 1 + l + sovAclrecord(uint64(l))
}
return n
}
func (m *ACLAddRecords) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
if len(m.Records) > 0 {
for _, e := range m.Records {
l = e.Size()
n += 1 + l + sovAclrecord(uint64(l))
}
}
return n
}
func sovAclrecord(x uint64) (n int) { func sovAclrecord(x uint64) (n int) {
return (math_bits.Len64(x|1) + 6) / 7 return (math_bits.Len64(x|1) + 6) / 7
} }
@ -2334,6 +2720,74 @@ func (m *RawACLRecord) Unmarshal(dAtA []byte) error {
m.Signature = []byte{} m.Signature = []byte{}
} }
iNdEx = postIndex iNdEx = postIndex
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field AcceptorIdentity", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowAclrecord
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return ErrInvalidLengthAclrecord
}
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthAclrecord
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.AcceptorIdentity = append(m.AcceptorIdentity[:0], dAtA[iNdEx:postIndex]...)
if m.AcceptorIdentity == nil {
m.AcceptorIdentity = []byte{}
}
iNdEx = postIndex
case 4:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field AcceptorSignature", wireType)
}
var byteLen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowAclrecord
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
byteLen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if byteLen < 0 {
return ErrInvalidLengthAclrecord
}
postIndex := iNdEx + byteLen
if postIndex < 0 {
return ErrInvalidLengthAclrecord
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.AcceptorSignature = append(m.AcceptorSignature[:0], dAtA[iNdEx:postIndex]...)
if m.AcceptorSignature == nil {
m.AcceptorSignature = []byte{}
}
iNdEx = postIndex
default: default:
iNdEx = preIndex iNdEx = preIndex
skippy, err := skipAclrecord(dAtA[iNdEx:]) skippy, err := skipAclrecord(dAtA[iNdEx:])
@ -4562,6 +5016,261 @@ func (m *ACLUserPermissionChange) Unmarshal(dAtA []byte) error {
} }
return nil return nil
} }
func (m *ACLSyncMessage) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowAclrecord
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: ACLSyncMessage: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: ACLSyncMessage: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Content", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowAclrecord
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthAclrecord
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthAclrecord
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
if m.Content == nil {
m.Content = &ACLSyncContentValue{}
}
if err := m.Content.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipAclrecord(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthAclrecord
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *ACLSyncContentValue) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowAclrecord
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: ACLSyncContentValue: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: ACLSyncContentValue: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field AddRecords", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowAclrecord
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthAclrecord
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthAclrecord
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
v := &ACLAddRecords{}
if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
m.Value = &ACLSyncContentValue_AddRecords{v}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipAclrecord(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthAclrecord
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *ACLAddRecords) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowAclrecord
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: ACLAddRecords: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: ACLAddRecords: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Records", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowAclrecord
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthAclrecord
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthAclrecord
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Records = append(m.Records, &RawACLRecordWithId{})
if err := m.Records[len(m.Records)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipAclrecord(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthAclrecord
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipAclrecord(dAtA []byte) (n int, err error) { func skipAclrecord(dAtA []byte) (n int, err error) {
l := len(dAtA) l := len(dAtA)
iNdEx := 0 iNdEx := 0

View File

@ -3,64 +3,66 @@ package aclrecord;
option go_package = "pkg/acl/aclrecordproto"; option go_package = "pkg/acl/aclrecordproto";
message RawACLRecord { message RawACLRecord {
bytes payload = 1; bytes payload = 1;
bytes signature = 2; bytes signature = 2;
bytes acceptorIdentity = 3;
bytes acceptorSignature = 4;
} }
message RawACLRecordWithId { message RawACLRecordWithId {
bytes payload = 1; bytes payload = 1;
string id = 2; string id = 2;
} }
message ACLRecord { message ACLRecord {
string prevId = 1; string prevId = 1;
bytes identity = 2; bytes identity = 2;
bytes data = 3; bytes data = 3;
uint64 currentReadKeyHash = 4; uint64 currentReadKeyHash = 4;
int64 timestamp = 5; int64 timestamp = 5;
} }
message ACLRoot { message ACLRoot {
bytes identity = 1; bytes identity = 1;
bytes encryptionKey = 2; bytes encryptionKey = 2;
string spaceId = 3; string spaceId = 3;
bytes encryptedReadKey = 4; bytes encryptedReadKey = 4;
string derivationScheme = 5; string derivationScheme = 5;
uint64 currentReadKeyHash = 6; uint64 currentReadKeyHash = 6;
int64 timestamp = 7; int64 timestamp = 7;
} }
message ACLContentValue { message ACLContentValue {
oneof value { oneof value {
ACLUserAdd userAdd = 1; ACLUserAdd userAdd = 1;
ACLUserRemove userRemove = 2; ACLUserRemove userRemove = 2;
ACLUserPermissionChange userPermissionChange = 3; ACLUserPermissionChange userPermissionChange = 3;
ACLUserInvite userInvite = 4; ACLUserInvite userInvite = 4;
ACLUserJoin userJoin = 5; ACLUserJoin userJoin = 5;
} }
} }
message ACLData { message ACLData {
repeated ACLContentValue aclContent = 1; repeated ACLContentValue aclContent = 1;
} }
message ACLState { message ACLState {
repeated uint64 readKeyHashes = 1; repeated uint64 readKeyHashes = 1;
repeated ACLUserState userStates = 2; repeated ACLUserState userStates = 2;
map<string, ACLUserInvite> invites = 3; map<string, ACLUserInvite> invites = 3;
} }
message ACLUserState { message ACLUserState {
bytes identity = 1; bytes identity = 1;
bytes encryptionKey = 2; bytes encryptionKey = 2;
ACLUserPermissions permissions = 3; ACLUserPermissions permissions = 3;
} }
message ACLUserAdd { message ACLUserAdd {
bytes identity = 1; bytes identity = 1;
bytes encryptionKey = 2; bytes encryptionKey = 2;
repeated bytes encryptedReadKeys = 3; repeated bytes encryptedReadKeys = 3;
ACLUserPermissions permissions = 4; ACLUserPermissions permissions = 4;
} }
message ACLUserInvite { message ACLUserInvite {
@ -84,18 +86,33 @@ message ACLUserRemove {
} }
message ACLReadKeyReplace { message ACLReadKeyReplace {
bytes identity = 1; bytes identity = 1;
bytes encryptionKey = 2; bytes encryptionKey = 2;
bytes encryptedReadKey = 3; bytes encryptedReadKey = 3;
} }
message ACLUserPermissionChange { message ACLUserPermissionChange {
bytes identity = 1; bytes identity = 1;
ACLUserPermissions permissions = 2; ACLUserPermissions permissions = 2;
} }
enum ACLUserPermissions { enum ACLUserPermissions {
Admin = 0; Admin = 0;
Writer = 1; Writer = 1;
Reader = 2; Reader = 2;
} }
message ACLSyncMessage {
ACLSyncContentValue content = 2;
}
// ACLSyncContentValue provides different types for acl sync
message ACLSyncContentValue {
oneof value {
ACLAddRecords addRecords = 1;
}
}
message ACLAddRecords {
repeated RawACLRecordWithId records = 1;
}

View File

@ -10,6 +10,7 @@ import (
"time" "time"
) )
// remove interface
type ACLRecordBuilder interface { type ACLRecordBuilder interface {
ConvertFromRaw(rawIdRecord *aclrecordproto.RawACLRecordWithId) (rec *ACLRecord, err error) ConvertFromRaw(rawIdRecord *aclrecordproto.RawACLRecordWithId) (rec *ACLRecord, err error)
BuildUserJoin(acceptPrivKeyBytes []byte, encSymKeyBytes []byte, state *ACLState) (rec *aclrecordproto.RawACLRecord, err error) BuildUserJoin(acceptPrivKeyBytes []byte, encSymKeyBytes []byte, state *ACLState) (rec *aclrecordproto.RawACLRecord, err error)

View File

@ -29,11 +29,13 @@ type ACLList interface {
Records() []*ACLRecord Records() []*ACLRecord
ACLState() *ACLState ACLState() *ACLState
IsAfter(first string, second string) (bool, error) IsAfter(first string, second string) (bool, error)
AddRawRecords(ctx context.Context, rec []*aclrecordproto.RawACLRecordWithId) (err error)
Head() *ACLRecord Head() *ACLRecord
Get(id string) (*ACLRecord, error) Get(id string) (*ACLRecord, error)
Iterate(iterFunc IterFunc) Iterate(iterFunc IterFunc)
IterateFrom(startId string, iterFunc IterFunc) IterateFrom(startId string, iterFunc IterFunc)
AddRawRecord(rawRec *aclrecordproto.RawACLRecordWithId) (added bool, err error)
Close() (err error) Close() (err error)
} }
@ -53,14 +55,12 @@ type aclList struct {
} }
func BuildACLListWithIdentity(acc *account.AccountData, storage storage.ListStorage) (ACLList, error) { func BuildACLListWithIdentity(acc *account.AccountData, storage storage.ListStorage) (ACLList, error) {
id := storage.ID()
builder := newACLStateBuilderWithIdentity(acc) builder := newACLStateBuilderWithIdentity(acc)
return build(id, builder, newACLRecordBuilder(id, common.NewKeychain()), storage) return build(storage.Id(), builder, newACLRecordBuilder(storage.Id(), common.NewKeychain()), storage)
} }
func BuildACLList(storage storage.ListStorage) (ACLList, error) { func BuildACLList(storage storage.ListStorage) (ACLList, error) {
id := storage.ID() return build(storage.Id(), newACLStateBuilder(), newACLRecordBuilder(storage.Id(), common.NewKeychain()), storage)
return build(id, newACLStateBuilder(), newACLRecordBuilder(id, common.NewKeychain()), storage)
} }
func build(id string, stateBuilder *aclStateBuilder, recBuilder ACLRecordBuilder, storage storage.ListStorage) (list ACLList, err error) { func build(id string, stateBuilder *aclStateBuilder, recBuilder ACLRecordBuilder, storage storage.ListStorage) (list ACLList, err error) {
@ -110,6 +110,7 @@ func build(id string, stateBuilder *aclStateBuilder, recBuilder ACLRecordBuilder
return return
} }
// TODO: check if this is correct (raw model instead of unmarshalled)
rootWithId, err := storage.Root() rootWithId, err := storage.Root()
if err != nil { if err != nil {
return return
@ -124,7 +125,6 @@ func build(id string, stateBuilder *aclStateBuilder, recBuilder ACLRecordBuilder
aclState: state, aclState: state,
storage: storage, storage: storage,
id: id, id: id,
RWMutex: sync.RWMutex{},
} }
return return
} }
@ -133,6 +133,37 @@ func (a *aclList) Records() []*ACLRecord {
return a.records return a.records
} }
func (a *aclList) AddRawRecord(rawRec *aclrecordproto.RawACLRecordWithId) (added bool, err error) {
if _, ok := a.indexes[rawRec.Id]; ok {
return
}
record, err := a.recordBuilder.ConvertFromRaw(rawRec)
if err != nil {
return
}
if err = a.aclState.applyRecord(record); err != nil {
return
}
a.records = append(a.records, record)
a.indexes[record.Id] = len(a.records) - 1
if err = a.storage.AddRawRecord(context.Background(), rawRec); err != nil {
return
}
if err = a.storage.SetHead(rawRec.Id); err != nil {
return
}
return true, nil
}
func (a *aclList) IsValidNext(rawRec *aclrecordproto.RawACLRecordWithId) (err error) {
_, err = a.recordBuilder.ConvertFromRaw(rawRec)
if err != nil {
return
}
// TODO: change state and add "check" method for records
return
}
func (a *aclList) ID() string { func (a *aclList) ID() string {
return a.id return a.id
} }
@ -141,40 +172,6 @@ func (a *aclList) Root() *aclrecordproto.RawACLRecordWithId {
return a.root return a.root
} }
func (a *aclList) AddRawRecords(ctx context.Context, records []*aclrecordproto.RawACLRecordWithId) (err error) {
if len(records) == 0 {
return
}
// converting and verifying
var aclRecords []*ACLRecord
for _, rec := range records {
var record *ACLRecord
record, err = a.recordBuilder.ConvertFromRaw(rec)
if err != nil {
return
}
aclRecords = append(aclRecords, record)
}
// trying to append them to state
err = a.stateBuilder.Append(a.aclState, aclRecords)
if err != nil {
return
}
// saving to storage
for _, rec := range records {
err = a.storage.AddRawRecord(ctx, rec)
if err != nil {
return
}
}
// setting new head
err = a.storage.SetHead(records[len(records)-1].Id)
return
}
func (a *aclList) ACLState() *ACLState { func (a *aclList) ACLState() *ACLState {
return a.aclState return a.aclState
} }

View File

@ -89,3 +89,7 @@ func TestAclList_ACLState_UserJoinAndRemove(t *testing.T) {
_, err = aclList.ACLState().PermissionsAtRecord(records[3].Id, idB) _, err = aclList.ACLState().PermissionsAtRecord(records[3].Id, idB)
assert.Error(t, err, "B should have no permissions at record 3, because user should be removed") assert.Error(t, err, "B should have no permissions at record 3, because user should be removed")
} }
func TestAclList_AddRawRecord(t *testing.T) {
}

View File

@ -33,11 +33,10 @@ func NewInMemoryACLListStorage(
root: root, root: root,
head: head.Id, head: head.Id,
records: allRecords, records: allRecords,
RWMutex: sync.RWMutex{},
}, nil }, nil
} }
func (t *inMemoryACLListStorage) ID() string { func (t *inMemoryACLListStorage) Id() string {
t.RLock() t.RLock()
defer t.RUnlock() defer t.RUnlock()
return t.id return t.id
@ -112,7 +111,7 @@ func (t *inMemoryTreeStorage) HasChange(ctx context.Context, id string) (bool, e
return exists, nil return exists, nil
} }
func (t *inMemoryTreeStorage) ID() string { func (t *inMemoryTreeStorage) Id() string {
t.RLock() t.RLock()
defer t.RUnlock() defer t.RUnlock()
return t.id return t.id

View File

@ -12,7 +12,7 @@ var ErrACLExists = errors.New("acl already exists")
var ErrUnknownRecord = errors.New("record doesn't exist") var ErrUnknownRecord = errors.New("record doesn't exist")
type ListStorage interface { type ListStorage interface {
ID() string Id() string
Root() (*aclrecordproto.RawACLRecordWithId, error) Root() (*aclrecordproto.RawACLRecordWithId, error)
Head() (string, error) Head() (string, error)
SetHead(headId string) error SetHead(headId string) error

View File

@ -80,18 +80,18 @@ func (mr *MockListStorageMockRecorder) Head() *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Head", reflect.TypeOf((*MockListStorage)(nil).Head)) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Head", reflect.TypeOf((*MockListStorage)(nil).Head))
} }
// ID mocks base method. // Id mocks base method.
func (m *MockListStorage) ID() string { func (m *MockListStorage) Id() string {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ID") ret := m.ctrl.Call(m, "Id")
ret0, _ := ret[0].(string) ret0, _ := ret[0].(string)
return ret0 return ret0
} }
// ID indicates an expected call of ID. // Id indicates an expected call of Id.
func (mr *MockListStorageMockRecorder) ID() *gomock.Call { func (mr *MockListStorageMockRecorder) Id() *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ID", reflect.TypeOf((*MockListStorage)(nil).ID)) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Id", reflect.TypeOf((*MockListStorage)(nil).Id))
} }
// Root mocks base method. // Root mocks base method.
@ -205,18 +205,18 @@ func (mr *MockTreeStorageMockRecorder) Heads() *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Heads", reflect.TypeOf((*MockTreeStorage)(nil).Heads)) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Heads", reflect.TypeOf((*MockTreeStorage)(nil).Heads))
} }
// ID mocks base method. // Id mocks base method.
func (m *MockTreeStorage) ID() string { func (m *MockTreeStorage) Id() string {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ID") ret := m.ctrl.Call(m, "Id")
ret0, _ := ret[0].(string) ret0, _ := ret[0].(string)
return ret0 return ret0
} }
// ID indicates an expected call of ID. // Id indicates an expected call of Id.
func (mr *MockTreeStorageMockRecorder) ID() *gomock.Call { func (mr *MockTreeStorageMockRecorder) Id() *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ID", reflect.TypeOf((*MockTreeStorage)(nil).ID)) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Id", reflect.TypeOf((*MockTreeStorage)(nil).Id))
} }
// Root mocks base method. // Root mocks base method.

View File

@ -6,7 +6,7 @@ import (
) )
type TreeStorage interface { type TreeStorage interface {
ID() string Id() string
Root() (*treechangeproto.RawTreeChangeWithId, error) Root() (*treechangeproto.RawTreeChangeWithId, error)
Heads() ([]string, error) Heads() ([]string, error)
SetHeads(heads []string) error SetHeads(heads []string) error

View File

@ -3,14 +3,14 @@ package tree
import ( import (
"fmt" "fmt"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/aclrecordproto" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/aclrecordproto"
list2 "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/list" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/list"
) )
type ObjectTreeValidator interface { type ObjectTreeValidator interface {
// ValidateFullTree should always be entered while holding a read lock on ACLList // ValidateFullTree should always be entered while holding a read lock on ACLList
ValidateFullTree(tree *Tree, aclList list2.ACLList) error ValidateFullTree(tree *Tree, aclList list.ACLList) error
// ValidateNewChanges should always be entered while holding a read lock on ACLList // ValidateNewChanges should always be entered while holding a read lock on ACLList
ValidateNewChanges(tree *Tree, aclList list2.ACLList, newChanges []*Change) error ValidateNewChanges(tree *Tree, aclList list.ACLList, newChanges []*Change) error
} }
type objectTreeValidator struct{} type objectTreeValidator struct{}
@ -19,7 +19,7 @@ func newTreeValidator() ObjectTreeValidator {
return &objectTreeValidator{} return &objectTreeValidator{}
} }
func (v *objectTreeValidator) ValidateFullTree(tree *Tree, aclList list2.ACLList) (err error) { func (v *objectTreeValidator) ValidateFullTree(tree *Tree, aclList list.ACLList) (err error) {
tree.Iterate(tree.RootId(), func(c *Change) (isContinue bool) { tree.Iterate(tree.RootId(), func(c *Change) (isContinue bool) {
err = v.validateChange(tree, aclList, c) err = v.validateChange(tree, aclList, c)
return err == nil return err == nil
@ -27,7 +27,7 @@ func (v *objectTreeValidator) ValidateFullTree(tree *Tree, aclList list2.ACLList
return err return err
} }
func (v *objectTreeValidator) ValidateNewChanges(tree *Tree, aclList list2.ACLList, newChanges []*Change) (err error) { func (v *objectTreeValidator) ValidateNewChanges(tree *Tree, aclList list.ACLList, newChanges []*Change) (err error) {
for _, c := range newChanges { for _, c := range newChanges {
err = v.validateChange(tree, aclList, c) err = v.validateChange(tree, aclList, c)
if err != nil { if err != nil {
@ -37,9 +37,9 @@ func (v *objectTreeValidator) ValidateNewChanges(tree *Tree, aclList list2.ACLLi
return return
} }
func (v *objectTreeValidator) validateChange(tree *Tree, aclList list2.ACLList, c *Change) (err error) { func (v *objectTreeValidator) validateChange(tree *Tree, aclList list.ACLList, c *Change) (err error) {
var ( var (
perm list2.UserPermissionPair perm list.UserPermissionPair
state = aclList.ACLState() state = aclList.ACLState()
) )
// checking if the user could write // checking if the user could write
@ -49,7 +49,7 @@ func (v *objectTreeValidator) validateChange(tree *Tree, aclList list2.ACLList,
} }
if perm.Permission != aclrecordproto.ACLUserPermissions_Writer && perm.Permission != aclrecordproto.ACLUserPermissions_Admin { if perm.Permission != aclrecordproto.ACLUserPermissions_Writer && perm.Permission != aclrecordproto.ACLUserPermissions_Admin {
err = list2.ErrInsufficientPermissions err = list.ErrInsufficientPermissions
return return
} }

View File

@ -126,7 +126,9 @@ func buildObjectTree(deps objectTreeDeps) (ObjectTree, error) {
} }
} }
objTree.id = objTree.treeStorage.ID() objTree.id = objTree.treeStorage.Id()
objTree.id = objTree.treeStorage.Id()
objTree.root, err = objTree.treeStorage.Root() objTree.root, err = objTree.treeStorage.Root()
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -0,0 +1,44 @@
package testaccount
import (
accountService "github.com/anytypeio/go-anytype-infrastructure-experiments/common/account"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/app"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/account"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/keys/asymmetric/encryptionkey"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/keys/asymmetric/signingkey"
)
// AccountTestService provides service for test purposes, generates new random account every Init
type AccountTestService struct {
acc *account.AccountData
}
func (s *AccountTestService) Init(a *app.App) (err error) {
encKey, _, err := encryptionkey.GenerateRandomRSAKeyPair(2048)
if err != nil {
return
}
signKey, _, err := signingkey.GenerateRandomEd25519KeyPair()
if err != nil {
return
}
ident, err := signKey.GetPublic().Raw()
if err != nil {
return
}
s.acc = &account.AccountData{
Identity: ident,
SignKey: signKey,
EncKey: encKey,
}
return nil
}
func (s *AccountTestService) Name() (name string) {
return accountService.CName
}
func (s *AccountTestService) Account() *account.AccountData {
return s.acc
}

View File

@ -1,3 +1,4 @@
//go:generate mockgen -destination mock_consensusclient/mock_consensusclient.go github.com/anytypeio/go-anytype-infrastructure-experiments/consensus/consensusclient Service
package consensusclient package consensusclient
import ( import (

View File

@ -13,6 +13,7 @@ import (
"github.com/golang/mock/gomock" "github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"sync"
"testing" "testing"
"time" "time"
) )
@ -22,7 +23,7 @@ func TestService_Watch(t *testing.T) {
fx := newFixture(t).run(t) fx := newFixture(t).run(t)
defer fx.Finish() defer fx.Finish()
var logId = []byte{'1'} var logId = []byte{'1'}
w := &testWatcher{} w := &testWatcher{ready: make(chan struct{})}
require.NoError(t, fx.Watch(logId, w)) require.NoError(t, fx.Watch(logId, w))
st := fx.testServer.waitStream(t) st := fx.testServer.waitStream(t)
req, err := st.Recv() req, err := st.Recv()
@ -34,6 +35,7 @@ func TestService_Watch(t *testing.T) {
Error: consensusproto.ErrCodes_ErrorOffset + consensusproto.ErrCodes_LogNotFound, Error: consensusproto.ErrCodes_ErrorOffset + consensusproto.ErrCodes_LogNotFound,
}, },
})) }))
<-w.ready
assert.Equal(t, consensuserr.ErrLogNotFound, w.err) assert.Equal(t, consensuserr.ErrLogNotFound, w.err)
fx.testServer.releaseStream <- nil fx.testServer.releaseStream <- nil
}) })
@ -188,7 +190,6 @@ func (t *testServer) AddRecord(ctx context.Context, req *consensusproto.AddRecor
} }
func (t *testServer) WatchLog(stream consensusproto.DRPCConsensus_WatchLogStream) error { func (t *testServer) WatchLog(stream consensusproto.DRPCConsensus_WatchLogStream) error {
fmt.Println("watchLog", t.watchErrOnce)
if t.watchErrOnce { if t.watchErrOnce {
t.watchErrOnce = false t.watchErrOnce = false
return fmt.Errorf("error") return fmt.Errorf("error")
@ -208,14 +209,22 @@ func (t *testServer) waitStream(test *testing.T) consensusproto.DRPCConsensus_Wa
} }
type testWatcher struct { type testWatcher struct {
recs [][]*consensusproto.Record recs [][]*consensusproto.Record
err error err error
ready chan struct{}
once sync.Once
} }
func (t *testWatcher) AddConsensusRecords(recs []*consensusproto.Record) { func (t *testWatcher) AddConsensusRecords(recs []*consensusproto.Record) {
t.recs = append(t.recs, recs) t.recs = append(t.recs, recs)
t.once.Do(func() {
close(t.ready)
})
} }
func (t *testWatcher) AddConsensusError(err error) { func (t *testWatcher) AddConsensusError(err error) {
t.err = err t.err = err
t.once.Do(func() {
close(t.ready)
})
} }

View File

@ -0,0 +1,150 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/anytypeio/go-anytype-infrastructure-experiments/consensus/consensusclient (interfaces: Service)
// Package mock_consensusclient is a generated GoMock package.
package mock_consensusclient
import (
context "context"
reflect "reflect"
app "github.com/anytypeio/go-anytype-infrastructure-experiments/common/app"
consensusclient "github.com/anytypeio/go-anytype-infrastructure-experiments/consensus/consensusclient"
consensusproto "github.com/anytypeio/go-anytype-infrastructure-experiments/consensus/consensusproto"
gomock "github.com/golang/mock/gomock"
)
// MockService is a mock of Service interface.
type MockService struct {
ctrl *gomock.Controller
recorder *MockServiceMockRecorder
}
// MockServiceMockRecorder is the mock recorder for MockService.
type MockServiceMockRecorder struct {
mock *MockService
}
// NewMockService creates a new mock instance.
func NewMockService(ctrl *gomock.Controller) *MockService {
mock := &MockService{ctrl: ctrl}
mock.recorder = &MockServiceMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockService) EXPECT() *MockServiceMockRecorder {
return m.recorder
}
// AddLog mocks base method.
func (m *MockService) AddLog(arg0 context.Context, arg1 *consensusproto.Log) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "AddLog", arg0, arg1)
ret0, _ := ret[0].(error)
return ret0
}
// AddLog indicates an expected call of AddLog.
func (mr *MockServiceMockRecorder) AddLog(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddLog", reflect.TypeOf((*MockService)(nil).AddLog), arg0, arg1)
}
// AddRecord mocks base method.
func (m *MockService) AddRecord(arg0 context.Context, arg1 []byte, arg2 *consensusproto.Record) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "AddRecord", arg0, arg1, arg2)
ret0, _ := ret[0].(error)
return ret0
}
// AddRecord indicates an expected call of AddRecord.
func (mr *MockServiceMockRecorder) AddRecord(arg0, arg1, arg2 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddRecord", reflect.TypeOf((*MockService)(nil).AddRecord), arg0, arg1, arg2)
}
// Close mocks base method.
func (m *MockService) Close(arg0 context.Context) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Close", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// Close indicates an expected call of Close.
func (mr *MockServiceMockRecorder) Close(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Close", reflect.TypeOf((*MockService)(nil).Close), arg0)
}
// Init mocks base method.
func (m *MockService) Init(arg0 *app.App) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Init", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// Init indicates an expected call of Init.
func (mr *MockServiceMockRecorder) Init(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Init", reflect.TypeOf((*MockService)(nil).Init), arg0)
}
// Name mocks base method.
func (m *MockService) Name() string {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Name")
ret0, _ := ret[0].(string)
return ret0
}
// Name indicates an expected call of Name.
func (mr *MockServiceMockRecorder) Name() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Name", reflect.TypeOf((*MockService)(nil).Name))
}
// Run mocks base method.
func (m *MockService) Run(arg0 context.Context) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Run", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// Run indicates an expected call of Run.
func (mr *MockServiceMockRecorder) Run(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Run", reflect.TypeOf((*MockService)(nil).Run), arg0)
}
// UnWatch mocks base method.
func (m *MockService) UnWatch(arg0 []byte) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "UnWatch", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// UnWatch indicates an expected call of UnWatch.
func (mr *MockServiceMockRecorder) UnWatch(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UnWatch", reflect.TypeOf((*MockService)(nil).UnWatch), arg0)
}
// Watch mocks base method.
func (m *MockService) Watch(arg0 []byte, arg1 consensusclient.Watcher) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Watch", arg0, arg1)
ret0, _ := ret[0].(error)
return ret0
}
// Watch indicates an expected call of Watch.
func (mr *MockServiceMockRecorder) Watch(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Watch", reflect.TypeOf((*MockService)(nil).Watch), arg0, arg1)
}

View File

@ -3,6 +3,7 @@ package consensusclient
import ( import (
"github.com/anytypeio/go-anytype-infrastructure-experiments/consensus/consensusproto" "github.com/anytypeio/go-anytype-infrastructure-experiments/consensus/consensusproto"
"github.com/cheggaaa/mb/v2" "github.com/cheggaaa/mb/v2"
"sync"
) )
func runStream(rpcStream consensusproto.DRPCConsensus_WatchLogClient) *stream { func runStream(rpcStream consensusproto.DRPCConsensus_WatchLogClient) *stream {
@ -17,6 +18,7 @@ func runStream(rpcStream consensusproto.DRPCConsensus_WatchLogClient) *stream {
type stream struct { type stream struct {
rpcStream consensusproto.DRPCConsensus_WatchLogClient rpcStream consensusproto.DRPCConsensus_WatchLogClient
mb *mb.MB[*consensusproto.WatchLogEvent] mb *mb.MB[*consensusproto.WatchLogEvent]
mu sync.Mutex
err error err error
} }
@ -37,6 +39,8 @@ func (s *stream) WaitLogs() []*consensusproto.WatchLogEvent {
} }
func (s *stream) Err() error { func (s *stream) Err() error {
s.mu.Lock()
defer s.mu.Unlock()
return s.err return s.err
} }
@ -45,7 +49,9 @@ func (s *stream) readStream() {
for { for {
event, err := s.rpcStream.Recv() event, err := s.rpcStream.Recv()
if err != nil { if err != nil {
s.mu.Lock()
s.err = err s.err = err
s.mu.Unlock()
return return
} }
if err = s.mb.Add(event); err != nil { if err = s.mb.Add(event); err != nil {

134
node/acl/service.go Normal file
View File

@ -0,0 +1,134 @@
package acl
import (
"context"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/account"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/app"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/app/logger"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/syncservice/synchandler"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/aclrecordproto"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/cid"
"github.com/anytypeio/go-anytype-infrastructure-experiments/consensus/consensusclient"
"github.com/anytypeio/go-anytype-infrastructure-experiments/consensus/consensusproto"
"time"
)
const CName = "node.acl"
var log = logger.NewNamed(CName)
func New() Service {
return &service{}
}
type Service interface {
CreateLog(ctx context.Context, aclId string, rawRec *aclrecordproto.RawACLRecord) (firstRecId string, err error)
AddRecord(ctx context.Context, aclId string, rawRec *aclrecordproto.RawACLRecord) (id string, err error)
Watch(ctx context.Context, spaceId, aclId string, h synchandler.SyncHandler) (err error)
UnWatch(aclId string) (err error)
app.Component
}
type service struct {
consService consensusclient.Service
account account.Service
}
func (s *service) Init(a *app.App) (err error) {
s.consService = a.MustComponent(consensusclient.CName).(consensusclient.Service)
s.account = a.MustComponent(account.CName).(account.Service)
return
}
func (s *service) Name() (name string) {
return CName
}
func (s *service) CreateLog(ctx context.Context, aclId string, rawRec *aclrecordproto.RawACLRecord) (firstRecId string, err error) {
logId, err := cidToByte(aclId)
if err != nil {
return
}
recId, _, payload, err := s.signAndMarshal(rawRec)
if err != nil {
return
}
if err = s.consService.AddLog(ctx, &consensusproto.Log{
Id: logId,
Records: []*consensusproto.Record{
{
Id: recId,
Payload: payload,
CreatedUnix: uint64(time.Now().Unix()),
},
},
}); err != nil {
return
}
return cidToString(recId)
}
func (s *service) AddRecord(ctx context.Context, aclId string, rawRec *aclrecordproto.RawACLRecord) (id string, err error) {
logId, err := cidToByte(aclId)
if err != nil {
return
}
recId, prevId, payload, err := s.signAndMarshal(rawRec)
if err != nil {
return
}
if err = s.consService.AddRecord(ctx, logId, &consensusproto.Record{
Id: recId,
PrevId: prevId,
Payload: payload,
CreatedUnix: uint64(time.Now().Unix()),
}); err != nil {
return
}
return cidToString(recId)
}
func (s *service) Watch(ctx context.Context, spaceId, aclId string, h synchandler.SyncHandler) (err error) {
w, err := newWatcher(spaceId, aclId, h)
if err != nil {
return
}
if err = s.consService.Watch(w.logId, w); err != nil {
return err
}
return w.Ready(ctx)
}
func (s *service) UnWatch(aclId string) (err error) {
logId, err := cidToByte(aclId)
if err != nil {
return
}
return s.consService.UnWatch(logId)
}
func (s *service) signAndMarshal(rawRec *aclrecordproto.RawACLRecord) (recId, prevId, payload []byte, err error) {
var rec = &aclrecordproto.ACLRecord{}
if err = rec.Unmarshal(rawRec.Payload); err != nil {
return
}
if rec.PrevId != "" {
if prevId, err = cidToByte(rec.PrevId); err != nil {
return
}
}
rawRec.AcceptorIdentity = s.account.Account().Identity
if rawRec.AcceptorSignature, err = s.account.Account().SignKey.Sign(rawRec.Payload); err != nil {
return
}
if payload, err = rawRec.Marshal(); err != nil {
return
}
recCid, err := cid.NewCIDFromBytes(payload)
if err != nil {
return
}
recId, err = cidToByte(recCid)
return
}

195
node/acl/service_test.go Normal file
View File

@ -0,0 +1,195 @@
package acl
import (
"context"
"fmt"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/app"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/aclrecordproto"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/testutil/testaccount"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/cid"
"github.com/anytypeio/go-anytype-infrastructure-experiments/consensus/consensusclient"
"github.com/anytypeio/go-anytype-infrastructure-experiments/consensus/consensusclient/mock_consensusclient"
"github.com/anytypeio/go-anytype-infrastructure-experiments/consensus/consensusproto"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"testing"
"time"
)
var ctx = context.Background()
func TestService_CreateLog(t *testing.T) {
fx := newFixture(t)
defer fx.Finish(t)
var clog *consensusproto.Log
fx.mockClient.EXPECT().AddLog(ctx, gomock.Any()).Do(func(ctx context.Context, l *consensusproto.Log) {
clog = l
})
aclId, _ := cid.NewCIDFromBytes([]byte("aclId"))
rec := &aclrecordproto.ACLRecord{
PrevId: "",
Identity: fx.account.Account().Identity,
Data: []byte{'1', '2', '3'},
Timestamp: time.Now().Unix(),
}
pl, _ := rec.Marshal()
firstRecId, err := fx.CreateLog(ctx, aclId, &aclrecordproto.RawACLRecord{
Payload: pl,
})
require.NoError(t, err)
aclIdBytes, _ := cidToByte(aclId)
firstRecIdBytes, _ := cidToByte(firstRecId)
assert.Equal(t, aclIdBytes, clog.Id)
assert.NotEmpty(t, firstRecIdBytes)
require.Len(t, clog.Records, 1)
var resultRawAcl = &aclrecordproto.RawACLRecord{}
require.NoError(t, resultRawAcl.Unmarshal(clog.Records[0].Payload))
valid, err := fx.account.Account().SignKey.GetPublic().Verify(resultRawAcl.Payload, resultRawAcl.AcceptorSignature)
require.NoError(t, err)
require.True(t, valid)
}
func TestService_AddRecord(t *testing.T) {
fx := newFixture(t)
defer fx.Finish(t)
var clog *consensusproto.Log
fx.mockClient.EXPECT().AddLog(ctx, gomock.Any()).Do(func(ctx context.Context, l *consensusproto.Log) {
clog = l
})
aclId, _ := cid.NewCIDFromBytes([]byte("aclId"))
rec := &aclrecordproto.ACLRecord{
PrevId: "",
Identity: fx.account.Account().Identity,
Data: []byte{'1', '2', '3'},
Timestamp: time.Now().Unix(),
}
pl, _ := rec.Marshal()
firstRecId, err := fx.CreateLog(ctx, aclId, &aclrecordproto.RawACLRecord{
Payload: pl,
})
require.NoError(t, err)
aclIdBytes, _ := cidToByte(aclId)
firstRecIdBytes, _ := cidToByte(firstRecId)
assert.Equal(t, aclIdBytes, clog.Id)
assert.NotEmpty(t, firstRecIdBytes)
var addRec *consensusproto.Record
fx.mockClient.EXPECT().AddRecord(ctx, aclIdBytes, gomock.Any()).Do(func(ctx context.Context, logId []byte, rec *consensusproto.Record) {
addRec = rec
})
rec = &aclrecordproto.ACLRecord{
PrevId: firstRecId,
Identity: fx.account.Account().Identity,
Data: []byte{'1', '2', '3', '4'},
Timestamp: time.Now().Unix(),
}
pl, _ = rec.Marshal()
newRecId, err := fx.AddRecord(ctx, aclId, &aclrecordproto.RawACLRecord{
Payload: pl,
})
require.NoError(t, err)
assert.NotEmpty(t, newRecId)
assert.Equal(t, firstRecIdBytes, addRec.PrevId)
}
func TestService_Watch(t *testing.T) {
t.Run("remote error", func(t *testing.T) {
fx := newFixture(t)
defer fx.Finish(t)
var expErr = fmt.Errorf("error")
aclId, _ := cid.NewCIDFromBytes([]byte("aclId"))
aclIdBytes, _ := cidToByte(aclId)
fx.mockClient.EXPECT().Watch(aclIdBytes, gomock.Any()).Do(func(aid []byte, w consensusclient.Watcher) {
assert.Equal(t, aclIdBytes, aid)
go func() {
time.Sleep(time.Millisecond * 10)
w.AddConsensusError(expErr)
}()
})
th := &testHandler{}
err := fx.Watch(ctx, "123", aclId, th)
assert.Equal(t, expErr, err)
})
t.Run("success", func(t *testing.T) {
fx := newFixture(t)
defer fx.Finish(t)
aclId, _ := cid.NewCIDFromBytes([]byte("aclId"))
aclIdBytes, _ := cidToByte(aclId)
fx.mockClient.EXPECT().Watch(aclIdBytes, gomock.Any()).Do(func(aid []byte, w consensusclient.Watcher) {
assert.Equal(t, aclIdBytes, aid)
go func() {
time.Sleep(time.Millisecond * 10)
r1cid, _ := cid.NewCIDFromBytes([]byte("r1"))
r2cid, _ := cid.NewCIDFromBytes([]byte("r2"))
r1cidB, _ := cidToByte(r1cid)
r2cidB, _ := cidToByte(r2cid)
w.AddConsensusRecords([]*consensusproto.Record{
{
Id: r2cidB,
PrevId: r1cidB,
Payload: []byte("p1"),
},
{
Id: r1cidB,
Payload: []byte("p1"),
},
})
}()
})
th := &testHandler{}
err := fx.Watch(ctx, "123", aclId, th)
require.NoError(t, err)
})
}
func newFixture(t *testing.T) *fixture {
fx := &fixture{
a: new(app.App),
ctrl: gomock.NewController(t),
account: &testaccount.AccountTestService{},
}
fx.mockClient = mock_consensusclient.NewMockService(fx.ctrl)
fx.mockClient.EXPECT().Name().Return(consensusclient.CName).AnyTimes()
fx.mockClient.EXPECT().Init(gomock.Any()).AnyTimes()
fx.mockClient.EXPECT().Run(gomock.Any()).AnyTimes()
fx.mockClient.EXPECT().Close(gomock.Any()).AnyTimes()
fx.Service = New()
fx.a.Register(fx.account).Register(fx.mockClient).Register(fx.Service)
require.NoError(t, fx.a.Start(ctx))
return fx
}
type fixture struct {
Service
mockClient *mock_consensusclient.MockService
ctrl *gomock.Controller
a *app.App
account *testaccount.AccountTestService
}
func (fx *fixture) Finish(t *testing.T) {
require.NoError(t, fx.a.Close(ctx))
fx.ctrl.Finish()
}
type testHandler struct {
req *spacesyncproto.ObjectSyncMessage
}
func (t *testHandler) HandleMessage(ctx context.Context, senderId string, request *spacesyncproto.ObjectSyncMessage) (err error) {
t.req = request
return
}

19
node/acl/util.go Normal file
View File

@ -0,0 +1,19 @@
package acl
import "github.com/ipfs/go-cid"
func cidToString(b []byte) (s string, err error) {
rcid, err := cid.Cast(b)
if err != nil {
return
}
return rcid.String(), nil
}
func cidToByte(s string) (b []byte, err error) {
rcid, err := cid.Decode(s)
if err != nil {
return
}
return rcid.Bytes(), nil
}

16
node/acl/util_test.go Normal file
View File

@ -0,0 +1,16 @@
package acl
import (
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/util/cid"
"github.com/stretchr/testify/assert"
"testing"
)
func TestCIDLen(t *testing.T) {
s, _ := cid.NewCIDFromBytes([]byte("some data"))
t.Log(s, len(s))
b, _ := cidToByte(s)
t.Log(b, len(b))
s2, _ := cidToString(b)
assert.Equal(t, s, s2)
}

93
node/acl/watcher.go Normal file
View File

@ -0,0 +1,93 @@
package acl
import (
"context"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/syncservice/synchandler"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/aclrecordproto"
"github.com/anytypeio/go-anytype-infrastructure-experiments/consensus/consensusproto"
"go.uber.org/zap"
"sync"
)
func newWatcher(spaceId, aclId string, h synchandler.SyncHandler) (w *watcher, err error) {
w = &watcher{
aclId: aclId,
spaceId: spaceId,
handler: h,
ready: make(chan struct{}),
}
if w.logId, err = cidToByte(aclId); err != nil {
return nil, err
}
return
}
type watcher struct {
spaceId string
aclId string
logId []byte
handler synchandler.SyncHandler
ready chan struct{}
isReady sync.Once
err error
}
func (w *watcher) AddConsensusRecords(recs []*consensusproto.Record) {
w.isReady.Do(func() {
close(w.ready)
})
records := make([]*aclrecordproto.RawACLRecordWithId, 0, len(recs))
for _, rec := range recs {
recId, err := cidToString(rec.Id)
if err != nil {
log.Error("received invalid id from consensus node", zap.Error(err))
continue
}
records = append(records, &aclrecordproto.RawACLRecordWithId{
Payload: rec.Payload,
Id: recId,
})
}
aclReq := &aclrecordproto.ACLSyncMessage{
Content: &aclrecordproto.ACLSyncContentValue{
Value: &aclrecordproto.ACLSyncContentValue_AddRecords{
AddRecords: &aclrecordproto.ACLAddRecords{
Records: records,
},
},
},
}
payload, err := aclReq.Marshal()
if err != nil {
log.Error("acl payload marshal error", zap.Error(err))
return
}
req := &spacesyncproto.ObjectSyncMessage{
SpaceId: w.spaceId,
Payload: payload,
ObjectId: w.aclId,
}
if err = w.handler.HandleMessage(context.TODO(), "", req); err != nil {
log.Warn("handle message error", zap.Error(err))
}
}
func (w *watcher) AddConsensusError(err error) {
w.isReady.Do(func() {
w.err = err
close(w.ready)
})
}
func (w *watcher) Ready(ctx context.Context) (err error) {
select {
case <-w.ready:
return w.err
case <-ctx.Done():
return ctx.Err()
}
}

View File

@ -7,7 +7,7 @@ import (
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/storage" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/storage"
config2 "github.com/anytypeio/go-anytype-infrastructure-experiments/common/config" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/config"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/net/rpc/server" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/net/rpc/server"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/ocache" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/ocache"
"time" "time"
@ -28,20 +28,18 @@ type Service interface {
} }
type service struct { type service struct {
conf config2.Space conf config.Space
spaceCache ocache.OCache spaceCache ocache.OCache
commonSpace commonspace.Service commonSpace commonspace.Service
spaceStorageProvider storage.SpaceStorageProvider spaceStorageProvider storage.SpaceStorageProvider
} }
func (s *service) Init(a *app.App) (err error) { func (s *service) Init(a *app.App) (err error) {
s.conf = a.MustComponent(config2.CName).(*config2.Config).Space s.conf = a.MustComponent(config.CName).(*config.Config).Space
s.commonSpace = a.MustComponent(commonspace.CName).(commonspace.Service) s.commonSpace = a.MustComponent(commonspace.CName).(commonspace.Service)
s.spaceStorageProvider = a.MustComponent(storage.CName).(storage.SpaceStorageProvider) s.spaceStorageProvider = a.MustComponent(storage.CName).(storage.SpaceStorageProvider)
s.spaceCache = ocache.New( s.spaceCache = ocache.New(
func(ctx context.Context, id string) (value ocache.Object, err error) { s.loadSpace,
return s.commonSpace.GetSpace(ctx, id)
},
ocache.WithLogger(log.Sugar()), ocache.WithLogger(log.Sugar()),
ocache.WithGCPeriod(time.Minute), ocache.WithGCPeriod(time.Minute),
ocache.WithTTL(time.Duration(s.conf.GCTTL)*time.Second), ocache.WithTTL(time.Duration(s.conf.GCTTL)*time.Second),
@ -69,6 +67,21 @@ func (s *service) AddSpace(ctx context.Context, description commonspace.SpaceDes
return s.commonSpace.AddSpace(ctx, description) return s.commonSpace.AddSpace(ctx, description)
} }
func (s *service) loadSpace(ctx context.Context, id string) (value ocache.Object, err error) {
cc, err := s.commonSpace.NewSpace(ctx, id)
if err != nil {
return
}
ns, err := newNodeSpace(cc)
if err != nil {
return
}
if err = ns.Init(ctx); err != nil {
return
}
return ns, nil
}
func (s *service) Close(ctx context.Context) (err error) { func (s *service) Close(ctx context.Context) (err error) {
return s.spaceCache.Close() return s.spaceCache.Close()
} }

24
node/nodespace/space.go Normal file
View File

@ -0,0 +1,24 @@
package nodespace
import (
"context"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace"
)
func newNodeSpace(cc commonspace.Space) (commonspace.Space, error) {
return &nodeSpace{cc}, nil
}
type nodeSpace struct {
commonspace.Space
}
func (s *nodeSpace) Init(ctx context.Context) (err error) {
// try to push acl to consensus node
//
return s.Space.Init(ctx)
}
func (s *nodeSpace) Close() (err error) {
return s.Space.Close()
}

View File

@ -82,7 +82,7 @@ func createListStorage(db *pogreb.DB, root *aclrecordproto.RawACLRecordWithId) (
return return
} }
func (l *listStorage) ID() string { func (l *listStorage) Id() string {
return l.id return l.id
} }

View File

@ -9,7 +9,7 @@ import (
) )
func testList(t *testing.T, store storage.ListStorage, root *aclrecordproto.RawACLRecordWithId, head string) { func testList(t *testing.T, store storage.ListStorage, root *aclrecordproto.RawACLRecordWithId, head string) {
require.Equal(t, store.ID(), root.Id) require.Equal(t, store.Id(), root.Id)
aclRoot, err := store.Root() aclRoot, err := store.Root()
require.NoError(t, err) require.NoError(t, err)

View File

@ -5,7 +5,7 @@ import (
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/app/logger" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/app/logger"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/spacesyncproto"
spacestorage "github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/storage" spacestorage "github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/storage"
storage2 "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/storage" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/storage"
"go.uber.org/zap" "go.uber.org/zap"
"path" "path"
"sync" "sync"
@ -22,7 +22,7 @@ type spaceStorage struct {
spaceId string spaceId string
objDb *pogreb.DB objDb *pogreb.DB
keys spaceKeys keys spaceKeys
aclStorage storage2.ListStorage aclStorage storage.ListStorage
header *spacesyncproto.RawSpaceHeaderWithId header *spacesyncproto.RawSpaceHeaderWithId
mx sync.Mutex mx sync.Mutex
} }
@ -129,15 +129,15 @@ func createSpaceStorage(rootPath string, payload spacestorage.SpaceStorageCreate
return return
} }
func (s *spaceStorage) ID() string { func (s *spaceStorage) Id() string {
return s.spaceId return s.spaceId
} }
func (s *spaceStorage) TreeStorage(id string) (storage2.TreeStorage, error) { func (s *spaceStorage) TreeStorage(id string) (storage.TreeStorage, error) {
return newTreeStorage(s.objDb, id) return newTreeStorage(s.objDb, id)
} }
func (s *spaceStorage) CreateTreeStorage(payload storage2.TreeStorageCreatePayload) (ts storage2.TreeStorage, err error) { func (s *spaceStorage) CreateTreeStorage(payload storage.TreeStorageCreatePayload) (ts storage.TreeStorage, err error) {
// we have mutex here, so we prevent overwriting the heads of a tree on concurrent creation // we have mutex here, so we prevent overwriting the heads of a tree on concurrent creation
s.mx.Lock() s.mx.Lock()
defer s.mx.Unlock() defer s.mx.Unlock()
@ -145,7 +145,7 @@ func (s *spaceStorage) CreateTreeStorage(payload storage2.TreeStorageCreatePaylo
return createTreeStorage(s.objDb, payload) return createTreeStorage(s.objDb, payload)
} }
func (s *spaceStorage) ACLStorage() (storage2.ListStorage, error) { func (s *spaceStorage) ACLStorage() (storage.ListStorage, error) {
return s.aclStorage, nil return s.aclStorage, nil
} }

View File

@ -3,7 +3,7 @@ package storage
import ( import (
"context" "context"
"github.com/akrylysov/pogreb" "github.com/akrylysov/pogreb"
storage "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/storage" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/storage"
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/treechangeproto" "github.com/anytypeio/go-anytype-infrastructure-experiments/common/pkg/acl/treechangeproto"
) )
@ -86,7 +86,7 @@ func createTreeStorage(db *pogreb.DB, payload storage.TreeStorageCreatePayload)
return return
} }
func (t *treeStorage) ID() string { func (t *treeStorage) Id() string {
return t.id return t.id
} }

View File

@ -43,7 +43,7 @@ func (fx *fixture) stop(t *testing.T) {
} }
func testTreePayload(t *testing.T, store storage.TreeStorage, payload storage.TreeStorageCreatePayload) { func testTreePayload(t *testing.T, store storage.TreeStorage, payload storage.TreeStorageCreatePayload) {
require.Equal(t, payload.RootRawChange.Id, store.ID()) require.Equal(t, payload.RootRawChange.Id, store.Id())
root, err := store.Root() root, err := store.Root()
require.NoError(t, err) require.NoError(t, err)