WIP root change refactoring
This commit is contained in:
parent
41709d7dd3
commit
d41045aa63
17
Makefile
17
Makefile
@ -12,26 +12,25 @@ endif
|
|||||||
|
|
||||||
export PATH=$(GOPATH)/bin:$(shell echo $$PATH)
|
export PATH=$(GOPATH)/bin:$(shell echo $$PATH)
|
||||||
|
|
||||||
# TODO: folders were changed, so we should update Makefile and protos generation
|
|
||||||
proto:
|
proto:
|
||||||
@echo 'Generating protobuf packages (Go)...'
|
@echo 'Generating protobuf packages (Go)...'
|
||||||
# Uncomment if needed
|
# Uncomment if needed
|
||||||
@$(eval ROOT_PKG := pkg)
|
@$(eval ROOT_PKG := pkg)
|
||||||
@$(eval GOGO_START := GOGO_NO_UNDERSCORE=1 GOGO_EXPORT_ONEOF_INTERFACE=1)
|
@$(eval GOGO_START := GOGO_NO_UNDERSCORE=1 GOGO_EXPORT_ONEOF_INTERFACE=1)
|
||||||
@$(eval P_ACL_CHANGES_PATH_PB := $(ROOT_PKG)/acl/aclchanges/aclpb)
|
@$(eval P_ACL_RECORDS_PATH_PB := $(ROOT_PKG)/acl/aclrecordproto)
|
||||||
|
@$(eval P_TREE_CHANGES_PATH_PB := $(ROOT_PKG)/acl/treechangeproto)
|
||||||
@$(eval P_SYNC_CHANGES_PATH_PB := syncproto)
|
@$(eval P_SYNC_CHANGES_PATH_PB := syncproto)
|
||||||
@$(eval P_TEST_CHANGES_PATH_PB := $(ROOT_PKG)/acl/testutils/testchanges)
|
@$(eval P_TEST_CHANGES_PATH_PB := $(ROOT_PKG)/acl/testutils/testchanges)
|
||||||
@$(eval P_TIMESTAMP := Mgoogle/protobuf/timestamp.proto=github.com/gogo/protobuf/types)
|
@$(eval P_ACL_RECORDS := M$(P_ACL_RECORDS_PATH_PB)/protos/aclrecord.proto=github.com/anytypeio/go-anytype-infrastructure-experiments/$(P_ACL_RECORDS_PATH_PB))
|
||||||
@$(eval P_STRUCT := Mgoogle/protobuf/struct.proto=github.com/gogo/protobuf/types)
|
@$(eval P_TREE_CHANGES := M$(P_TREE_CHANGES_PATH_PB)/protos/treechange.proto=github.com/anytypeio/go-anytype-infrastructure-experiments/$(P_TREE_CHANGES_PATH_PB))
|
||||||
@$(eval P_ACL_CHANGES := M$(P_ACL_CHANGES_PATH_PB)/protos/aclchanges.proto=github.com/anytypeio/go-anytype-infrastructure-experiments/$(P_ACL_CHANGES_PATH_PB))
|
|
||||||
|
|
||||||
# use if needed $(eval PKGMAP := $$(P_TIMESTAMP),$$(P_STRUCT))
|
$(GOGO_START) protoc --gogofaster_out=:. $(P_ACL_RECORDS_PATH_PB)/protos/*.proto
|
||||||
$(GOGO_START) protoc --gogofaster_out=:. $(P_ACL_CHANGES_PATH_PB)/protos/*.proto
|
$(GOGO_START) protoc --gogofaster_out=:. $(P_TREE_CHANGES_PATH_PB)/protos/*.proto
|
||||||
$(GOGO_START) protoc --gogofaster_out=:. $(P_TEST_CHANGES_PATH_PB)/proto/*.proto
|
$(GOGO_START) protoc --gogofaster_out=:. $(P_TEST_CHANGES_PATH_PB)/proto/*.proto
|
||||||
$(eval PKGMAP := $$(P_ACL_CHANGES))
|
$(eval PKGMAP := $$(P_TREE_CHANGES))
|
||||||
$(GOGO_START) protoc --gogofaster_out=$(PKGMAP):. $(P_SYNC_CHANGES_PATH_PB)/proto/*.proto
|
|
||||||
$(GOGO_START) protoc --gogofaster_out=$(PKGMAP):. --go-drpc_out=protolib=github.com/gogo/protobuf:. common/commonspace/spacesyncproto/protos/*.proto
|
$(GOGO_START) protoc --gogofaster_out=$(PKGMAP):. --go-drpc_out=protolib=github.com/gogo/protobuf:. common/commonspace/spacesyncproto/protos/*.proto
|
||||||
|
|
||||||
|
|
||||||
build:
|
build:
|
||||||
@$(eval FLAGS := $$(shell govvv -flags -pkg github.com/anytypeio/go-anytype-infrastructure-experiments/app))
|
@$(eval FLAGS := $$(shell govvv -flags -pkg github.com/anytypeio/go-anytype-infrastructure-experiments/app))
|
||||||
go build -v -o bin/anytype-node -ldflags "$(FLAGS)" cmd/node/node.go
|
go build -v -o bin/anytype-node -ldflags "$(FLAGS)" cmd/node/node.go
|
||||||
@ -2,7 +2,7 @@ syntax = "proto3";
|
|||||||
package anySpace;
|
package anySpace;
|
||||||
|
|
||||||
option go_package = "common/commonspace/spacesyncproto";
|
option go_package = "common/commonspace/spacesyncproto";
|
||||||
import "pkg/acl/aclchanges/aclpb/protos/aclchanges.proto";
|
import "pkg/acl/treechangeproto/protos/treechange.proto";
|
||||||
|
|
||||||
enum ErrCodes {
|
enum ErrCodes {
|
||||||
Unexpected = 0;
|
Unexpected = 0;
|
||||||
@ -49,7 +49,7 @@ message HeadSyncResponse {
|
|||||||
message ObjectSyncMessage {
|
message ObjectSyncMessage {
|
||||||
string spaceId = 1;
|
string spaceId = 1;
|
||||||
ObjectSyncContentValue content = 2;
|
ObjectSyncContentValue content = 2;
|
||||||
acl.TreeHeader treeHeader = 3;
|
treechange.RootChange treeHeader = 3;
|
||||||
string treeId = 4;
|
string treeId = 4;
|
||||||
string trackingId = 5;
|
string trackingId = 5;
|
||||||
//
|
//
|
||||||
@ -70,24 +70,32 @@ message ObjectSyncContentValue {
|
|||||||
// ObjectHeadUpdate is a message sent on document head update
|
// ObjectHeadUpdate is a message sent on document head update
|
||||||
message ObjectHeadUpdate {
|
message ObjectHeadUpdate {
|
||||||
repeated string heads = 1;
|
repeated string heads = 1;
|
||||||
repeated acl.RawTreeChangeWithId changes = 2;
|
repeated treechange.RawTreeChangeWithId changes = 2;
|
||||||
repeated string snapshotPath = 3;
|
repeated string snapshotPath = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ObjectHeadUpdate is a message sent when document needs full sync
|
// ObjectHeadUpdate is a message sent when document needs full sync
|
||||||
message ObjectFullSyncRequest {
|
message ObjectFullSyncRequest {
|
||||||
repeated string heads = 1;
|
repeated string heads = 1;
|
||||||
repeated acl.RawTreeChangeWithId changes = 2;
|
repeated treechange.RawTreeChangeWithId changes = 2;
|
||||||
repeated string snapshotPath = 3;
|
repeated string snapshotPath = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ObjectFullSyncResponse is a message sent as a response for a specific full sync
|
// ObjectFullSyncResponse is a message sent as a response for a specific full sync
|
||||||
message ObjectFullSyncResponse {
|
message ObjectFullSyncResponse {
|
||||||
repeated string heads = 1;
|
repeated string heads = 1;
|
||||||
repeated acl.RawTreeChangeWithId changes = 2;
|
repeated treechange.RawTreeChangeWithId changes = 2;
|
||||||
repeated string snapshotPath = 3;
|
repeated string snapshotPath = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message ObjectErrorResponse {
|
message ObjectErrorResponse {
|
||||||
string error = 1;
|
string error = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message SpaceHeader {
|
||||||
|
bytes identity = 1;
|
||||||
|
int64 timestamp = 2;
|
||||||
|
string spaceType = 3;
|
||||||
|
uint64 replicationKey = 4;
|
||||||
|
bytes seed = 5;
|
||||||
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
package spacesyncproto
|
package spacesyncproto
|
||||||
|
|
||||||
import "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb"
|
import "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclrecordproto/aclpb"
|
||||||
|
|
||||||
type SpaceStream = DRPCSpace_StreamStream
|
type SpaceStream = DRPCSpace_StreamStream
|
||||||
|
|
||||||
|
|||||||
@ -5,7 +5,7 @@ package spacesyncproto
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
fmt "fmt"
|
fmt "fmt"
|
||||||
aclpb "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb"
|
treechangeproto "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treechangeproto"
|
||||||
proto "github.com/gogo/protobuf/proto"
|
proto "github.com/gogo/protobuf/proto"
|
||||||
io "io"
|
io "io"
|
||||||
math "math"
|
math "math"
|
||||||
@ -322,7 +322,7 @@ func (m *HeadSyncResponse) GetResults() []*HeadSyncResult {
|
|||||||
type ObjectSyncMessage struct {
|
type ObjectSyncMessage struct {
|
||||||
SpaceId string `protobuf:"bytes,1,opt,name=spaceId,proto3" json:"spaceId,omitempty"`
|
SpaceId string `protobuf:"bytes,1,opt,name=spaceId,proto3" json:"spaceId,omitempty"`
|
||||||
Content *ObjectSyncContentValue `protobuf:"bytes,2,opt,name=content,proto3" json:"content,omitempty"`
|
Content *ObjectSyncContentValue `protobuf:"bytes,2,opt,name=content,proto3" json:"content,omitempty"`
|
||||||
TreeHeader *aclpb.TreeHeader `protobuf:"bytes,3,opt,name=treeHeader,proto3" json:"treeHeader,omitempty"`
|
TreeHeader *treechangeproto.RootChange `protobuf:"bytes,3,opt,name=treeHeader,proto3" json:"treeHeader,omitempty"`
|
||||||
TreeId string `protobuf:"bytes,4,opt,name=treeId,proto3" json:"treeId,omitempty"`
|
TreeId string `protobuf:"bytes,4,opt,name=treeId,proto3" json:"treeId,omitempty"`
|
||||||
TrackingId string `protobuf:"bytes,5,opt,name=trackingId,proto3" json:"trackingId,omitempty"`
|
TrackingId string `protobuf:"bytes,5,opt,name=trackingId,proto3" json:"trackingId,omitempty"`
|
||||||
}
|
}
|
||||||
@ -374,7 +374,7 @@ func (m *ObjectSyncMessage) GetContent() *ObjectSyncContentValue {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *ObjectSyncMessage) GetTreeHeader() *aclpb.TreeHeader {
|
func (m *ObjectSyncMessage) GetTreeHeader() *treechangeproto.RootChange {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
return m.TreeHeader
|
return m.TreeHeader
|
||||||
}
|
}
|
||||||
@ -510,7 +510,7 @@ func (*ObjectSyncContentValue) XXX_OneofWrappers() []interface{} {
|
|||||||
// ObjectHeadUpdate is a message sent on document head update
|
// ObjectHeadUpdate is a message sent on document head update
|
||||||
type ObjectHeadUpdate struct {
|
type ObjectHeadUpdate struct {
|
||||||
Heads []string `protobuf:"bytes,1,rep,name=heads,proto3" json:"heads,omitempty"`
|
Heads []string `protobuf:"bytes,1,rep,name=heads,proto3" json:"heads,omitempty"`
|
||||||
Changes []*aclpb.RawTreeChangeWithId `protobuf:"bytes,2,rep,name=changes,proto3" json:"changes,omitempty"`
|
Changes []*treechangeproto.RawTreeChangeWithId `protobuf:"bytes,2,rep,name=changes,proto3" json:"changes,omitempty"`
|
||||||
SnapshotPath []string `protobuf:"bytes,3,rep,name=snapshotPath,proto3" json:"snapshotPath,omitempty"`
|
SnapshotPath []string `protobuf:"bytes,3,rep,name=snapshotPath,proto3" json:"snapshotPath,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -554,7 +554,7 @@ func (m *ObjectHeadUpdate) GetHeads() []string {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *ObjectHeadUpdate) GetChanges() []*aclpb.RawTreeChangeWithId {
|
func (m *ObjectHeadUpdate) GetChanges() []*treechangeproto.RawTreeChangeWithId {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
return m.Changes
|
return m.Changes
|
||||||
}
|
}
|
||||||
@ -571,7 +571,7 @@ func (m *ObjectHeadUpdate) GetSnapshotPath() []string {
|
|||||||
// ObjectHeadUpdate is a message sent when document needs full sync
|
// ObjectHeadUpdate is a message sent when document needs full sync
|
||||||
type ObjectFullSyncRequest struct {
|
type ObjectFullSyncRequest struct {
|
||||||
Heads []string `protobuf:"bytes,1,rep,name=heads,proto3" json:"heads,omitempty"`
|
Heads []string `protobuf:"bytes,1,rep,name=heads,proto3" json:"heads,omitempty"`
|
||||||
Changes []*aclpb.RawTreeChangeWithId `protobuf:"bytes,2,rep,name=changes,proto3" json:"changes,omitempty"`
|
Changes []*treechangeproto.RawTreeChangeWithId `protobuf:"bytes,2,rep,name=changes,proto3" json:"changes,omitempty"`
|
||||||
SnapshotPath []string `protobuf:"bytes,3,rep,name=snapshotPath,proto3" json:"snapshotPath,omitempty"`
|
SnapshotPath []string `protobuf:"bytes,3,rep,name=snapshotPath,proto3" json:"snapshotPath,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -615,7 +615,7 @@ func (m *ObjectFullSyncRequest) GetHeads() []string {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *ObjectFullSyncRequest) GetChanges() []*aclpb.RawTreeChangeWithId {
|
func (m *ObjectFullSyncRequest) GetChanges() []*treechangeproto.RawTreeChangeWithId {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
return m.Changes
|
return m.Changes
|
||||||
}
|
}
|
||||||
@ -632,7 +632,7 @@ func (m *ObjectFullSyncRequest) GetSnapshotPath() []string {
|
|||||||
// ObjectFullSyncResponse is a message sent as a response for a specific full sync
|
// ObjectFullSyncResponse is a message sent as a response for a specific full sync
|
||||||
type ObjectFullSyncResponse struct {
|
type ObjectFullSyncResponse struct {
|
||||||
Heads []string `protobuf:"bytes,1,rep,name=heads,proto3" json:"heads,omitempty"`
|
Heads []string `protobuf:"bytes,1,rep,name=heads,proto3" json:"heads,omitempty"`
|
||||||
Changes []*aclpb.RawTreeChangeWithId `protobuf:"bytes,2,rep,name=changes,proto3" json:"changes,omitempty"`
|
Changes []*treechangeproto.RawTreeChangeWithId `protobuf:"bytes,2,rep,name=changes,proto3" json:"changes,omitempty"`
|
||||||
SnapshotPath []string `protobuf:"bytes,3,rep,name=snapshotPath,proto3" json:"snapshotPath,omitempty"`
|
SnapshotPath []string `protobuf:"bytes,3,rep,name=snapshotPath,proto3" json:"snapshotPath,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -676,7 +676,7 @@ func (m *ObjectFullSyncResponse) GetHeads() []string {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *ObjectFullSyncResponse) GetChanges() []*aclpb.RawTreeChangeWithId {
|
func (m *ObjectFullSyncResponse) GetChanges() []*treechangeproto.RawTreeChangeWithId {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
return m.Changes
|
return m.Changes
|
||||||
}
|
}
|
||||||
@ -734,6 +734,82 @@ func (m *ObjectErrorResponse) GetError() string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SpaceHeader struct {
|
||||||
|
Identity []byte `protobuf:"bytes,1,opt,name=identity,proto3" json:"identity,omitempty"`
|
||||||
|
Timestamp int64 `protobuf:"varint,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
|
||||||
|
SpaceType string `protobuf:"bytes,3,opt,name=spaceType,proto3" json:"spaceType,omitempty"`
|
||||||
|
ReplicationKey uint64 `protobuf:"varint,4,opt,name=replicationKey,proto3" json:"replicationKey,omitempty"`
|
||||||
|
Seed []byte `protobuf:"bytes,5,opt,name=seed,proto3" json:"seed,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *SpaceHeader) Reset() { *m = SpaceHeader{} }
|
||||||
|
func (m *SpaceHeader) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*SpaceHeader) ProtoMessage() {}
|
||||||
|
func (*SpaceHeader) Descriptor() ([]byte, []int) {
|
||||||
|
return fileDescriptor_5855f4ef9cf24cdb, []int{11}
|
||||||
|
}
|
||||||
|
func (m *SpaceHeader) XXX_Unmarshal(b []byte) error {
|
||||||
|
return m.Unmarshal(b)
|
||||||
|
}
|
||||||
|
func (m *SpaceHeader) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
|
if deterministic {
|
||||||
|
return xxx_messageInfo_SpaceHeader.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 *SpaceHeader) XXX_Merge(src proto.Message) {
|
||||||
|
xxx_messageInfo_SpaceHeader.Merge(m, src)
|
||||||
|
}
|
||||||
|
func (m *SpaceHeader) XXX_Size() int {
|
||||||
|
return m.Size()
|
||||||
|
}
|
||||||
|
func (m *SpaceHeader) XXX_DiscardUnknown() {
|
||||||
|
xxx_messageInfo_SpaceHeader.DiscardUnknown(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
var xxx_messageInfo_SpaceHeader proto.InternalMessageInfo
|
||||||
|
|
||||||
|
func (m *SpaceHeader) GetIdentity() []byte {
|
||||||
|
if m != nil {
|
||||||
|
return m.Identity
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *SpaceHeader) GetTimestamp() int64 {
|
||||||
|
if m != nil {
|
||||||
|
return m.Timestamp
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *SpaceHeader) GetSpaceType() string {
|
||||||
|
if m != nil {
|
||||||
|
return m.SpaceType
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *SpaceHeader) GetReplicationKey() uint64 {
|
||||||
|
if m != nil {
|
||||||
|
return m.ReplicationKey
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *SpaceHeader) GetSeed() []byte {
|
||||||
|
if m != nil {
|
||||||
|
return m.Seed
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
proto.RegisterEnum("anySpace.ErrCodes", ErrCodes_name, ErrCodes_value)
|
proto.RegisterEnum("anySpace.ErrCodes", ErrCodes_name, ErrCodes_value)
|
||||||
proto.RegisterType((*HeadSyncRange)(nil), "anySpace.HeadSyncRange")
|
proto.RegisterType((*HeadSyncRange)(nil), "anySpace.HeadSyncRange")
|
||||||
@ -747,6 +823,7 @@ func init() {
|
|||||||
proto.RegisterType((*ObjectFullSyncRequest)(nil), "anySpace.ObjectFullSyncRequest")
|
proto.RegisterType((*ObjectFullSyncRequest)(nil), "anySpace.ObjectFullSyncRequest")
|
||||||
proto.RegisterType((*ObjectFullSyncResponse)(nil), "anySpace.ObjectFullSyncResponse")
|
proto.RegisterType((*ObjectFullSyncResponse)(nil), "anySpace.ObjectFullSyncResponse")
|
||||||
proto.RegisterType((*ObjectErrorResponse)(nil), "anySpace.ObjectErrorResponse")
|
proto.RegisterType((*ObjectErrorResponse)(nil), "anySpace.ObjectErrorResponse")
|
||||||
|
proto.RegisterType((*SpaceHeader)(nil), "anySpace.SpaceHeader")
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -754,52 +831,57 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var fileDescriptor_5855f4ef9cf24cdb = []byte{
|
var fileDescriptor_5855f4ef9cf24cdb = []byte{
|
||||||
// 712 bytes of a gzipped FileDescriptorProto
|
// 797 bytes of a gzipped FileDescriptorProto
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x55, 0x4b, 0x6f, 0xd3, 0x40,
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x55, 0xcd, 0x8e, 0xe3, 0x44,
|
||||||
0x10, 0xf6, 0xa6, 0x79, 0x75, 0xd2, 0x47, 0x58, 0x68, 0x31, 0x41, 0xa4, 0xc1, 0xa7, 0x08, 0xa4,
|
0x10, 0xb6, 0x33, 0x99, 0x49, 0x52, 0x99, 0x99, 0x0d, 0x0d, 0x3b, 0x98, 0x00, 0xd9, 0xe0, 0x03,
|
||||||
0xa4, 0x0a, 0x17, 0x44, 0xb9, 0xd0, 0x2a, 0x55, 0x22, 0xc4, 0x43, 0x5b, 0x0a, 0x12, 0xe2, 0xb2,
|
0x8a, 0x40, 0x4a, 0x50, 0x90, 0x10, 0x30, 0x5c, 0xd8, 0x51, 0x46, 0x89, 0x56, 0xfc, 0xa8, 0x67,
|
||||||
0xb5, 0xb7, 0x49, 0xa8, 0x63, 0x1b, 0xef, 0x86, 0xd2, 0x1b, 0x17, 0x38, 0x23, 0xfe, 0x12, 0x17,
|
0x17, 0x24, 0xc4, 0xa5, 0xd7, 0xae, 0x4d, 0xcc, 0xda, 0x6e, 0xe3, 0xee, 0xb0, 0xe4, 0x09, 0xb8,
|
||||||
0x8e, 0x15, 0x27, 0x8e, 0xa8, 0xfd, 0x23, 0x68, 0xc7, 0x76, 0x5e, 0xb8, 0xe5, 0xd6, 0x43, 0xec,
|
0x80, 0x84, 0x78, 0x03, 0x9e, 0x85, 0x0b, 0xc7, 0x3d, 0xc2, 0x0d, 0xcd, 0xbc, 0x08, 0xea, 0xb2,
|
||||||
0x9d, 0xd9, 0xf9, 0xbe, 0xfd, 0xf6, 0x9b, 0xf5, 0x06, 0x1e, 0xda, 0xfe, 0x70, 0xe8, 0x7b, 0xcd,
|
0x1d, 0x3b, 0xc1, 0xbb, 0x1c, 0xf7, 0x12, 0x77, 0x7d, 0x5d, 0xf5, 0xf5, 0xd7, 0x55, 0xd5, 0x15,
|
||||||
0xe8, 0x25, 0x03, 0x6e, 0x8b, 0x26, 0x3e, 0xe5, 0x89, 0x67, 0x07, 0xa1, 0xaf, 0xfc, 0x26, 0x3e,
|
0xf8, 0xd0, 0x93, 0x51, 0x24, 0xe3, 0x49, 0xf6, 0x51, 0x89, 0xf0, 0x70, 0x42, 0xbf, 0x6a, 0x13,
|
||||||
0xe5, 0x24, 0xdb, 0xc0, 0x04, 0x2d, 0x72, 0xef, 0x64, 0x4f, 0xe7, 0x2a, 0x9b, 0xc1, 0x51, 0xaf,
|
0x7b, 0x49, 0x2a, 0xb5, 0x9c, 0xd0, 0xaf, 0x2a, 0xd1, 0x31, 0x01, 0xac, 0x2d, 0xe2, 0xcd, 0x95,
|
||||||
0xc9, 0x6d, 0x57, 0xff, 0xec, 0x3e, 0xf7, 0x7a, 0x42, 0xea, 0x61, 0x70, 0x90, 0x40, 0x27, 0xf9,
|
0xc1, 0xfa, 0x93, 0xe4, 0xf1, 0x72, 0x22, 0xbc, 0x70, 0xa2, 0x53, 0x44, 0x6f, 0x25, 0xe2, 0x25,
|
||||||
0x08, 0x6b, 0x75, 0x61, 0xb9, 0x23, 0xb8, 0xb3, 0x77, 0xe2, 0xd9, 0x4c, 0xe7, 0x29, 0x85, 0xec,
|
0xee, 0x44, 0x96, 0x70, 0x16, 0xea, 0x2e, 0xe0, 0x64, 0x8e, 0xc2, 0xbf, 0xda, 0xc4, 0x1e, 0x37,
|
||||||
0x61, 0xe8, 0x0f, 0x4d, 0x52, 0x23, 0xf5, 0x2c, 0xc3, 0x31, 0x5d, 0x81, 0x8c, 0xf2, 0xcd, 0x0c,
|
0x30, 0x63, 0xd0, 0x7c, 0x94, 0xca, 0xc8, 0xb1, 0x87, 0xf6, 0xa8, 0xc9, 0x69, 0xcd, 0x4e, 0xa1,
|
||||||
0x66, 0x32, 0xca, 0xa7, 0x37, 0x20, 0xe7, 0x0e, 0x86, 0x03, 0x65, 0x2e, 0xd4, 0x48, 0x7d, 0x99,
|
0xa1, 0xa5, 0xd3, 0x20, 0xa4, 0xa1, 0x25, 0x7b, 0x05, 0x0e, 0xc3, 0x20, 0x0a, 0xb4, 0x73, 0x30,
|
||||||
0x45, 0x81, 0x75, 0x0c, 0x2b, 0x63, 0x2a, 0x21, 0x47, 0xae, 0xd2, 0x5c, 0x7d, 0x2e, 0xfb, 0xc8,
|
0xb4, 0x47, 0x27, 0x3c, 0x33, 0xdc, 0x27, 0x70, 0xba, 0xa5, 0x42, 0xb5, 0x0e, 0xb5, 0xe1, 0x5a,
|
||||||
0xb5, 0xc4, 0x70, 0x4c, 0xb7, 0xa0, 0x28, 0x5c, 0x31, 0x14, 0x9e, 0x92, 0x66, 0xa6, 0xb6, 0x50,
|
0x09, 0xb5, 0x22, 0xae, 0x63, 0x4e, 0x6b, 0x76, 0x0e, 0x6d, 0x0c, 0x31, 0xc2, 0x58, 0x2b, 0xa7,
|
||||||
0x2f, 0xb5, 0x36, 0x1a, 0x89, 0xfe, 0xc6, 0x2c, 0xbe, 0x1d, 0xd5, 0xb1, 0x31, 0x40, 0x2f, 0x6c,
|
0x31, 0x3c, 0x18, 0x75, 0xa7, 0x77, 0xc6, 0x85, 0xfc, 0xf1, 0x6e, 0xfc, 0x2c, 0xf3, 0xe3, 0xdb,
|
||||||
0xfb, 0x23, 0x6f, 0xbc, 0x30, 0x06, 0xd6, 0x16, 0xac, 0xa5, 0x02, 0xb5, 0xee, 0x81, 0x83, 0xab,
|
0x00, 0x73, 0xb0, 0x27, 0xd7, 0xf1, 0xf6, 0x60, 0x32, 0xdc, 0x73, 0xb8, 0x5d, 0x1b, 0x68, 0x74,
|
||||||
0x2f, 0xb2, 0xcc, 0xc0, 0x41, 0x3d, 0x82, 0x3b, 0xb8, 0x93, 0x45, 0x86, 0x63, 0xeb, 0x1d, 0xac,
|
0x07, 0x3e, 0x9d, 0xde, 0xe1, 0x8d, 0xc0, 0x27, 0x3d, 0x28, 0x7c, 0xba, 0x49, 0x87, 0xd3, 0xda,
|
||||||
0x4e, 0xc0, 0x1f, 0x46, 0x42, 0x2a, 0x6a, 0x42, 0x01, 0x2d, 0xee, 0x26, 0xd8, 0x24, 0xa4, 0x4d,
|
0xfd, 0x16, 0x6e, 0x95, 0xc1, 0xdf, 0xaf, 0x51, 0x69, 0xe6, 0x40, 0x8b, 0x32, 0xbc, 0x28, 0x62,
|
||||||
0xc8, 0x87, 0xe8, 0x5e, 0x2c, 0xfd, 0x66, 0x8a, 0x74, 0x3d, 0xcf, 0xe2, 0x32, 0x6b, 0x17, 0xca,
|
0x0b, 0x93, 0x4d, 0xe0, 0x28, 0x35, 0x59, 0x2a, 0xa4, 0xbf, 0x5a, 0x23, 0xdd, 0xec, 0xf3, 0xdc,
|
||||||
0x53, 0xd2, 0x02, 0xdf, 0x93, 0x82, 0xb6, 0xa0, 0x10, 0xa2, 0x4c, 0x69, 0x12, 0x64, 0x31, 0x2f,
|
0xcd, 0xbd, 0x84, 0x5e, 0x45, 0x5a, 0x22, 0x63, 0x85, 0x6c, 0x0a, 0xad, 0x94, 0x64, 0x2a, 0xc7,
|
||||||
0x32, 0x80, 0x25, 0x85, 0xd6, 0x2f, 0x02, 0xd7, 0x5e, 0x1c, 0xbc, 0x17, 0xb6, 0xd2, 0xb3, 0xcf,
|
0x26, 0x16, 0xe7, 0x59, 0x09, 0xe0, 0x85, 0xa3, 0xfb, 0xb7, 0x0d, 0x2f, 0x7d, 0xf1, 0xf0, 0x3b,
|
||||||
0x84, 0x94, 0xbc, 0x27, 0x2e, 0x11, 0xfa, 0x08, 0x0a, 0xb6, 0xef, 0x29, 0xe1, 0x29, 0xdc, 0x6c,
|
0xf4, 0xb4, 0xd9, 0xfd, 0x0c, 0x95, 0x12, 0x4b, 0x7c, 0x8e, 0xd0, 0x8f, 0xa1, 0xe5, 0xc9, 0x58,
|
||||||
0xa9, 0x55, 0x9b, 0xac, 0x31, 0xe1, 0xd9, 0x89, 0x4a, 0x5e, 0x73, 0x77, 0x24, 0x58, 0x02, 0xa0,
|
0x63, 0xac, 0xe9, 0xb2, 0xdd, 0xe9, 0xb0, 0x3c, 0xa3, 0xe4, 0xb9, 0xc8, 0x5c, 0xbe, 0x12, 0xe1,
|
||||||
0x4d, 0x00, 0x15, 0x0a, 0xa1, 0xa5, 0x88, 0x10, 0x9d, 0x2e, 0xb5, 0x56, 0x1b, 0xdc, 0x76, 0x1b,
|
0x1a, 0x79, 0x11, 0xc0, 0x3e, 0x00, 0x30, 0x6d, 0x62, 0xa4, 0x60, 0x4a, 0x99, 0xee, 0x4e, 0xcf,
|
||||||
0xaf, 0xc6, 0x69, 0x36, 0x55, 0x42, 0xd7, 0x21, 0xaf, 0xa3, 0xae, 0x63, 0x66, 0x51, 0x45, 0x1c,
|
0xc6, 0x95, 0xce, 0xe1, 0x52, 0xea, 0x0b, 0x5a, 0xf2, 0x8a, 0x27, 0x3b, 0x83, 0x23, 0x63, 0x2d,
|
||||||
0xd1, 0xaa, 0x26, 0xe2, 0xf6, 0xd1, 0xc0, 0xeb, 0x75, 0x1d, 0x33, 0x87, 0x73, 0x53, 0x19, 0xeb,
|
0x7c, 0xa7, 0x49, 0x62, 0x72, 0x8b, 0x0d, 0x0c, 0x9f, 0xf0, 0x1e, 0x07, 0xf1, 0x72, 0xe1, 0x3b,
|
||||||
0x47, 0x06, 0xd6, 0xd3, 0xc5, 0xd0, 0xc7, 0x00, 0xba, 0x3b, 0xfb, 0x81, 0xc3, 0x95, 0xc0, 0xcd,
|
0x87, 0xb4, 0x57, 0x41, 0xdc, 0x3f, 0x1a, 0x70, 0x56, 0xaf, 0x89, 0x7d, 0x02, 0x60, 0x8a, 0xf4,
|
||||||
0x95, 0x5a, 0x95, 0xf9, 0x2d, 0x74, 0xc6, 0x15, 0x1d, 0x83, 0x4d, 0xd5, 0xd3, 0xa7, 0xb0, 0x7a,
|
0x20, 0xf1, 0x85, 0x46, 0xba, 0x63, 0x77, 0xda, 0xdf, 0xbf, 0xc9, 0x7c, 0xeb, 0x31, 0xb7, 0x78,
|
||||||
0x38, 0x72, 0xdd, 0xa9, 0x9e, 0xc6, 0x2e, 0x6c, 0xcc, 0x53, 0xec, 0xce, 0x96, 0x75, 0x0c, 0x36,
|
0xc5, 0x9f, 0xdd, 0x83, 0x5b, 0x8f, 0xd6, 0x61, 0x58, 0x29, 0x6d, 0x9e, 0x8c, 0x3b, 0xfb, 0x14,
|
||||||
0x8f, 0xa4, 0xcf, 0xa1, 0x3c, 0x49, 0x45, 0x2d, 0x8c, 0x4d, 0xa9, 0x5d, 0xcc, 0x16, 0xd5, 0x75,
|
0x97, 0xbb, 0x6e, 0x73, 0x8b, 0xef, 0x47, 0xb2, 0xcf, 0xa1, 0x57, 0x42, 0x59, 0x25, 0xf3, 0xdc,
|
||||||
0x0c, 0xf6, 0x0f, 0x96, 0xb6, 0x61, 0x59, 0x84, 0xa1, 0x1f, 0x8e, 0xc9, 0xb2, 0x48, 0x76, 0x67,
|
0x0c, 0x9f, 0xcd, 0x96, 0xf9, 0xcd, 0x2d, 0xfe, 0x9f, 0x58, 0x36, 0x83, 0x13, 0x4c, 0x53, 0x99,
|
||||||
0x9e, 0xac, 0x3d, 0x5d, 0xd4, 0x31, 0xd8, 0x2c, 0x6a, 0xbb, 0x00, 0xb9, 0x8f, 0xda, 0x2a, 0xeb,
|
0x6e, 0xc9, 0x9a, 0x44, 0xf6, 0xe6, 0x3e, 0xd9, 0xac, 0xea, 0x34, 0xb7, 0xf8, 0x6e, 0xd4, 0xdd,
|
||||||
0x33, 0x81, 0xf2, 0xbc, 0x1f, 0xfa, 0x43, 0xd1, 0x7e, 0x44, 0x27, 0x6c, 0x91, 0x45, 0x81, 0x3e,
|
0x16, 0x1c, 0xfe, 0x60, 0x52, 0xe5, 0xfe, 0x64, 0x43, 0x6f, 0x3f, 0x1f, 0xe6, 0xbd, 0x98, 0x7c,
|
||||||
0x79, 0xf1, 0xd7, 0x1f, 0x9f, 0x5f, 0x13, 0xdb, 0xca, 0xf8, 0xb1, 0xee, 0xec, 0x0e, 0x4e, 0xbd,
|
0x64, 0x8d, 0xd6, 0xe1, 0x99, 0xc1, 0x3e, 0x82, 0x56, 0x56, 0xc9, 0xf2, 0x05, 0x56, 0xab, 0x2b,
|
||||||
0x19, 0xa8, 0x7e, 0xd7, 0x61, 0x49, 0x21, 0xb5, 0x60, 0x49, 0x7a, 0x3c, 0x90, 0x7d, 0x5f, 0xbd,
|
0x9e, 0xdc, 0x4f, 0x11, 0xb3, 0x02, 0x7f, 0x1d, 0xe8, 0xd5, 0xc2, 0xe7, 0x85, 0x3f, 0x73, 0xe1,
|
||||||
0xe4, 0xaa, 0x6f, 0x2e, 0x20, 0xe1, 0x4c, 0xce, 0xfa, 0x42, 0x60, 0x2d, 0xd5, 0xcf, 0x2b, 0xd6,
|
0x58, 0xc5, 0x22, 0x51, 0x2b, 0xa9, 0xbf, 0x14, 0x7a, 0xe5, 0x1c, 0x10, 0xef, 0x0e, 0xe6, 0xfe,
|
||||||
0xf1, 0x95, 0x24, 0x07, 0x6a, 0xbe, 0x13, 0x57, 0x2c, 0xe4, 0x3e, 0x5c, 0x4f, 0x69, 0xa2, 0x16,
|
0x6c, 0xc3, 0xed, 0xda, 0xb4, 0xbe, 0x18, 0x39, 0xbf, 0xd8, 0x45, 0x7b, 0xed, 0xd7, 0xe5, 0xc5,
|
||||||
0x81, 0x4d, 0x8c, 0xbf, 0xd6, 0x28, 0xb8, 0x57, 0x81, 0x62, 0x3b, 0x0c, 0x77, 0x7c, 0x47, 0x48,
|
0xe8, 0x79, 0x17, 0x5e, 0xae, 0xa9, 0xac, 0xd1, 0x42, 0x95, 0xcd, 0x5f, 0x72, 0x66, 0xb8, 0xbf,
|
||||||
0xba, 0x02, 0xb0, 0xef, 0x89, 0x4f, 0x81, 0xb0, 0x95, 0x70, 0xca, 0x46, 0xeb, 0x3b, 0x81, 0x1c,
|
0xdb, 0xd0, 0xa5, 0x6e, 0xc8, 0xdf, 0x58, 0x1f, 0xda, 0x81, 0x8f, 0xb1, 0x0e, 0xf4, 0x26, 0x9f,
|
||||||
0x1e, 0x0a, 0xfa, 0x04, 0x8a, 0xc9, 0xe5, 0x40, 0x6f, 0xa5, 0x5d, 0x18, 0x68, 0x78, 0xa5, 0x92,
|
0xaa, 0x5b, 0x9b, 0xbd, 0x01, 0x1d, 0x1d, 0x44, 0xa8, 0xb4, 0x88, 0x12, 0x6a, 0xf4, 0x03, 0x5e,
|
||||||
0x7a, 0x97, 0x44, 0xcb, 0xef, 0x42, 0x7e, 0x4f, 0x85, 0x82, 0x0f, 0xe9, 0xed, 0xb4, 0xdb, 0x20,
|
0x02, 0x66, 0x97, 0x86, 0xc3, 0xfd, 0x4d, 0x92, 0x35, 0x6e, 0x87, 0x97, 0x00, 0x7b, 0x1b, 0x4e,
|
||||||
0xbe, 0x55, 0x2a, 0x97, 0x4d, 0xd6, 0xc9, 0x26, 0xd9, 0xde, 0xfa, 0x79, 0x56, 0x25, 0xa7, 0x67,
|
0x53, 0x4c, 0xc2, 0xc0, 0x13, 0x3a, 0x90, 0xf1, 0x3d, 0xdc, 0x50, 0x3b, 0x36, 0xf9, 0x1e, 0x6a,
|
||||||
0x55, 0xf2, 0xe7, 0xac, 0x4a, 0xbe, 0x9d, 0x57, 0x8d, 0xd3, 0xf3, 0xaa, 0xf1, 0xfb, 0xbc, 0x6a,
|
0x26, 0xa8, 0x42, 0xcc, 0x5e, 0xf1, 0x31, 0xa7, 0xf5, 0x3b, 0x7d, 0x68, 0xcf, 0xd2, 0xf4, 0x42,
|
||||||
0xbc, 0xbd, 0xfb, 0xdf, 0xff, 0xb0, 0x83, 0x3c, 0xbe, 0x1e, 0xfc, 0x0d, 0x00, 0x00, 0xff, 0xff,
|
0xfa, 0xa8, 0xd8, 0x29, 0xc0, 0x83, 0x18, 0x7f, 0x4c, 0xd0, 0xd3, 0xe8, 0xf7, 0xac, 0xe9, 0x6f,
|
||||||
0x93, 0x27, 0x56, 0x41, 0xef, 0x06, 0x00, 0x00,
|
0x36, 0x1c, 0x92, 0x7e, 0xf6, 0x29, 0xb4, 0x8b, 0xe1, 0xc6, 0x5e, 0xab, 0x1b, 0x78, 0xd4, 0x22,
|
||||||
|
0xfd, 0x7e, 0xed, 0x2c, 0xcc, 0x52, 0x74, 0x09, 0x47, 0x57, 0x3a, 0x45, 0x11, 0xb1, 0xd7, 0xeb,
|
||||||
|
0xa6, 0x59, 0x3e, 0x15, 0xfb, 0xcf, 0xdb, 0x1c, 0xd9, 0xef, 0xd9, 0x77, 0xcf, 0xff, 0xbc, 0x1e,
|
||||||
|
0xd8, 0x4f, 0xaf, 0x07, 0xf6, 0x3f, 0xd7, 0x03, 0xfb, 0xd7, 0x9b, 0x81, 0xf5, 0xf4, 0x66, 0x60,
|
||||||
|
0xfd, 0x75, 0x33, 0xb0, 0xbe, 0x79, 0xeb, 0x7f, 0xff, 0x82, 0x1f, 0x1e, 0xd1, 0xe7, 0xfd, 0x7f,
|
||||||
|
0x03, 0x00, 0x00, 0xff, 0xff, 0x7b, 0x1f, 0x02, 0x55, 0xae, 0x07, 0x00, 0x00,
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *HeadSyncRange) Marshal() (dAtA []byte, err error) {
|
func (m *HeadSyncRange) Marshal() (dAtA []byte, err error) {
|
||||||
@ -1386,6 +1468,60 @@ func (m *ObjectErrorResponse) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
|||||||
return len(dAtA) - i, nil
|
return len(dAtA) - i, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *SpaceHeader) 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 *SpaceHeader) MarshalTo(dAtA []byte) (int, error) {
|
||||||
|
size := m.Size()
|
||||||
|
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *SpaceHeader) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||||
|
i := len(dAtA)
|
||||||
|
_ = i
|
||||||
|
var l int
|
||||||
|
_ = l
|
||||||
|
if len(m.Seed) > 0 {
|
||||||
|
i -= len(m.Seed)
|
||||||
|
copy(dAtA[i:], m.Seed)
|
||||||
|
i = encodeVarintSpacesync(dAtA, i, uint64(len(m.Seed)))
|
||||||
|
i--
|
||||||
|
dAtA[i] = 0x2a
|
||||||
|
}
|
||||||
|
if m.ReplicationKey != 0 {
|
||||||
|
i = encodeVarintSpacesync(dAtA, i, uint64(m.ReplicationKey))
|
||||||
|
i--
|
||||||
|
dAtA[i] = 0x20
|
||||||
|
}
|
||||||
|
if len(m.SpaceType) > 0 {
|
||||||
|
i -= len(m.SpaceType)
|
||||||
|
copy(dAtA[i:], m.SpaceType)
|
||||||
|
i = encodeVarintSpacesync(dAtA, i, uint64(len(m.SpaceType)))
|
||||||
|
i--
|
||||||
|
dAtA[i] = 0x1a
|
||||||
|
}
|
||||||
|
if m.Timestamp != 0 {
|
||||||
|
i = encodeVarintSpacesync(dAtA, i, uint64(m.Timestamp))
|
||||||
|
i--
|
||||||
|
dAtA[i] = 0x10
|
||||||
|
}
|
||||||
|
if len(m.Identity) > 0 {
|
||||||
|
i -= len(m.Identity)
|
||||||
|
copy(dAtA[i:], m.Identity)
|
||||||
|
i = encodeVarintSpacesync(dAtA, i, uint64(len(m.Identity)))
|
||||||
|
i--
|
||||||
|
dAtA[i] = 0xa
|
||||||
|
}
|
||||||
|
return len(dAtA) - i, nil
|
||||||
|
}
|
||||||
|
|
||||||
func encodeVarintSpacesync(dAtA []byte, offset int, v uint64) int {
|
func encodeVarintSpacesync(dAtA []byte, offset int, v uint64) int {
|
||||||
offset -= sovSpacesync(v)
|
offset -= sovSpacesync(v)
|
||||||
base := offset
|
base := offset
|
||||||
@ -1671,6 +1807,33 @@ func (m *ObjectErrorResponse) Size() (n int) {
|
|||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *SpaceHeader) Size() (n int) {
|
||||||
|
if m == nil {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
var l int
|
||||||
|
_ = l
|
||||||
|
l = len(m.Identity)
|
||||||
|
if l > 0 {
|
||||||
|
n += 1 + l + sovSpacesync(uint64(l))
|
||||||
|
}
|
||||||
|
if m.Timestamp != 0 {
|
||||||
|
n += 1 + sovSpacesync(uint64(m.Timestamp))
|
||||||
|
}
|
||||||
|
l = len(m.SpaceType)
|
||||||
|
if l > 0 {
|
||||||
|
n += 1 + l + sovSpacesync(uint64(l))
|
||||||
|
}
|
||||||
|
if m.ReplicationKey != 0 {
|
||||||
|
n += 1 + sovSpacesync(uint64(m.ReplicationKey))
|
||||||
|
}
|
||||||
|
l = len(m.Seed)
|
||||||
|
if l > 0 {
|
||||||
|
n += 1 + l + sovSpacesync(uint64(l))
|
||||||
|
}
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
func sovSpacesync(x uint64) (n int) {
|
func sovSpacesync(x uint64) (n int) {
|
||||||
return (math_bits.Len64(x|1) + 6) / 7
|
return (math_bits.Len64(x|1) + 6) / 7
|
||||||
}
|
}
|
||||||
@ -2362,7 +2525,7 @@ func (m *ObjectSyncMessage) Unmarshal(dAtA []byte) error {
|
|||||||
return io.ErrUnexpectedEOF
|
return io.ErrUnexpectedEOF
|
||||||
}
|
}
|
||||||
if m.TreeHeader == nil {
|
if m.TreeHeader == nil {
|
||||||
m.TreeHeader = &aclpb.TreeHeader{}
|
m.TreeHeader = &treechangeproto.RootChange{}
|
||||||
}
|
}
|
||||||
if err := m.TreeHeader.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
if err := m.TreeHeader.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -2733,7 +2896,7 @@ func (m *ObjectHeadUpdate) Unmarshal(dAtA []byte) error {
|
|||||||
if postIndex > l {
|
if postIndex > l {
|
||||||
return io.ErrUnexpectedEOF
|
return io.ErrUnexpectedEOF
|
||||||
}
|
}
|
||||||
m.Changes = append(m.Changes, &aclpb.RawTreeChangeWithId{})
|
m.Changes = append(m.Changes, &treechangeproto.RawTreeChangeWithId{})
|
||||||
if err := m.Changes[len(m.Changes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
if err := m.Changes[len(m.Changes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -2881,7 +3044,7 @@ func (m *ObjectFullSyncRequest) Unmarshal(dAtA []byte) error {
|
|||||||
if postIndex > l {
|
if postIndex > l {
|
||||||
return io.ErrUnexpectedEOF
|
return io.ErrUnexpectedEOF
|
||||||
}
|
}
|
||||||
m.Changes = append(m.Changes, &aclpb.RawTreeChangeWithId{})
|
m.Changes = append(m.Changes, &treechangeproto.RawTreeChangeWithId{})
|
||||||
if err := m.Changes[len(m.Changes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
if err := m.Changes[len(m.Changes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -3029,7 +3192,7 @@ func (m *ObjectFullSyncResponse) Unmarshal(dAtA []byte) error {
|
|||||||
if postIndex > l {
|
if postIndex > l {
|
||||||
return io.ErrUnexpectedEOF
|
return io.ErrUnexpectedEOF
|
||||||
}
|
}
|
||||||
m.Changes = append(m.Changes, &aclpb.RawTreeChangeWithId{})
|
m.Changes = append(m.Changes, &treechangeproto.RawTreeChangeWithId{})
|
||||||
if err := m.Changes[len(m.Changes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
if err := m.Changes[len(m.Changes)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -3169,6 +3332,194 @@ func (m *ObjectErrorResponse) Unmarshal(dAtA []byte) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
func (m *SpaceHeader) 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 ErrIntOverflowSpacesync
|
||||||
|
}
|
||||||
|
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: SpaceHeader: wiretype end group for non-group")
|
||||||
|
}
|
||||||
|
if fieldNum <= 0 {
|
||||||
|
return fmt.Errorf("proto: SpaceHeader: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||||
|
}
|
||||||
|
switch fieldNum {
|
||||||
|
case 1:
|
||||||
|
if wireType != 2 {
|
||||||
|
return fmt.Errorf("proto: wrong wireType = %d for field Identity", wireType)
|
||||||
|
}
|
||||||
|
var byteLen int
|
||||||
|
for shift := uint(0); ; shift += 7 {
|
||||||
|
if shift >= 64 {
|
||||||
|
return ErrIntOverflowSpacesync
|
||||||
|
}
|
||||||
|
if iNdEx >= l {
|
||||||
|
return io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
b := dAtA[iNdEx]
|
||||||
|
iNdEx++
|
||||||
|
byteLen |= int(b&0x7F) << shift
|
||||||
|
if b < 0x80 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if byteLen < 0 {
|
||||||
|
return ErrInvalidLengthSpacesync
|
||||||
|
}
|
||||||
|
postIndex := iNdEx + byteLen
|
||||||
|
if postIndex < 0 {
|
||||||
|
return ErrInvalidLengthSpacesync
|
||||||
|
}
|
||||||
|
if postIndex > l {
|
||||||
|
return io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
m.Identity = append(m.Identity[:0], dAtA[iNdEx:postIndex]...)
|
||||||
|
if m.Identity == nil {
|
||||||
|
m.Identity = []byte{}
|
||||||
|
}
|
||||||
|
iNdEx = postIndex
|
||||||
|
case 2:
|
||||||
|
if wireType != 0 {
|
||||||
|
return fmt.Errorf("proto: wrong wireType = %d for field Timestamp", wireType)
|
||||||
|
}
|
||||||
|
m.Timestamp = 0
|
||||||
|
for shift := uint(0); ; shift += 7 {
|
||||||
|
if shift >= 64 {
|
||||||
|
return ErrIntOverflowSpacesync
|
||||||
|
}
|
||||||
|
if iNdEx >= l {
|
||||||
|
return io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
b := dAtA[iNdEx]
|
||||||
|
iNdEx++
|
||||||
|
m.Timestamp |= int64(b&0x7F) << shift
|
||||||
|
if b < 0x80 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 3:
|
||||||
|
if wireType != 2 {
|
||||||
|
return fmt.Errorf("proto: wrong wireType = %d for field SpaceType", wireType)
|
||||||
|
}
|
||||||
|
var stringLen uint64
|
||||||
|
for shift := uint(0); ; shift += 7 {
|
||||||
|
if shift >= 64 {
|
||||||
|
return ErrIntOverflowSpacesync
|
||||||
|
}
|
||||||
|
if iNdEx >= l {
|
||||||
|
return io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
b := dAtA[iNdEx]
|
||||||
|
iNdEx++
|
||||||
|
stringLen |= uint64(b&0x7F) << shift
|
||||||
|
if b < 0x80 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
intStringLen := int(stringLen)
|
||||||
|
if intStringLen < 0 {
|
||||||
|
return ErrInvalidLengthSpacesync
|
||||||
|
}
|
||||||
|
postIndex := iNdEx + intStringLen
|
||||||
|
if postIndex < 0 {
|
||||||
|
return ErrInvalidLengthSpacesync
|
||||||
|
}
|
||||||
|
if postIndex > l {
|
||||||
|
return io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
m.SpaceType = string(dAtA[iNdEx:postIndex])
|
||||||
|
iNdEx = postIndex
|
||||||
|
case 4:
|
||||||
|
if wireType != 0 {
|
||||||
|
return fmt.Errorf("proto: wrong wireType = %d for field ReplicationKey", wireType)
|
||||||
|
}
|
||||||
|
m.ReplicationKey = 0
|
||||||
|
for shift := uint(0); ; shift += 7 {
|
||||||
|
if shift >= 64 {
|
||||||
|
return ErrIntOverflowSpacesync
|
||||||
|
}
|
||||||
|
if iNdEx >= l {
|
||||||
|
return io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
b := dAtA[iNdEx]
|
||||||
|
iNdEx++
|
||||||
|
m.ReplicationKey |= uint64(b&0x7F) << shift
|
||||||
|
if b < 0x80 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 5:
|
||||||
|
if wireType != 2 {
|
||||||
|
return fmt.Errorf("proto: wrong wireType = %d for field Seed", wireType)
|
||||||
|
}
|
||||||
|
var byteLen int
|
||||||
|
for shift := uint(0); ; shift += 7 {
|
||||||
|
if shift >= 64 {
|
||||||
|
return ErrIntOverflowSpacesync
|
||||||
|
}
|
||||||
|
if iNdEx >= l {
|
||||||
|
return io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
b := dAtA[iNdEx]
|
||||||
|
iNdEx++
|
||||||
|
byteLen |= int(b&0x7F) << shift
|
||||||
|
if b < 0x80 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if byteLen < 0 {
|
||||||
|
return ErrInvalidLengthSpacesync
|
||||||
|
}
|
||||||
|
postIndex := iNdEx + byteLen
|
||||||
|
if postIndex < 0 {
|
||||||
|
return ErrInvalidLengthSpacesync
|
||||||
|
}
|
||||||
|
if postIndex > l {
|
||||||
|
return io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
m.Seed = append(m.Seed[:0], dAtA[iNdEx:postIndex]...)
|
||||||
|
if m.Seed == nil {
|
||||||
|
m.Seed = []byte{}
|
||||||
|
}
|
||||||
|
iNdEx = postIndex
|
||||||
|
default:
|
||||||
|
iNdEx = preIndex
|
||||||
|
skippy, err := skipSpacesync(dAtA[iNdEx:])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||||
|
return ErrInvalidLengthSpacesync
|
||||||
|
}
|
||||||
|
if (iNdEx + skippy) > l {
|
||||||
|
return io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
iNdEx += skippy
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if iNdEx > l {
|
||||||
|
return io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
func skipSpacesync(dAtA []byte) (n int, err error) {
|
func skipSpacesync(dAtA []byte) (n int, err error) {
|
||||||
l := len(dAtA)
|
l := len(dAtA)
|
||||||
iNdEx := 0
|
iNdEx := 0
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/cache"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/cache"
|
||||||
"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/pkg/acl/aclchanges/aclpb"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclrecordproto/aclpb"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/tree"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/tree"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/slice"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/slice"
|
||||||
)
|
)
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import (
|
|||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/cache"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/cache"
|
||||||
"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/nodeconf"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/nodeconf"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclrecordproto/aclpb"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"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/syncservice"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/commonspace/syncservice"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclrecordproto/aclpb"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/list"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/list"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/storage"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/storage"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/tree"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/tree"
|
||||||
|
|||||||
6
go.mod
6
go.mod
@ -3,6 +3,7 @@ module github.com/anytypeio/go-anytype-infrastructure-experiments
|
|||||||
go 1.18
|
go 1.18
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/anytypeio/go-chash v0.0.0-20220629194632-4ad1154fe232
|
||||||
github.com/awalterschulze/gographviz v0.0.0-20190522210029-fa59802746ab
|
github.com/awalterschulze/gographviz v0.0.0-20190522210029-fa59802746ab
|
||||||
github.com/cespare/xxhash v1.1.0
|
github.com/cespare/xxhash v1.1.0
|
||||||
github.com/goccy/go-graphviz v0.0.9
|
github.com/goccy/go-graphviz v0.0.9
|
||||||
@ -16,6 +17,7 @@ require (
|
|||||||
github.com/multiformats/go-multihash v0.1.0
|
github.com/multiformats/go-multihash v0.1.0
|
||||||
github.com/stretchr/testify v1.8.0
|
github.com/stretchr/testify v1.8.0
|
||||||
github.com/zeebo/blake3 v0.2.3
|
github.com/zeebo/blake3 v0.2.3
|
||||||
|
github.com/zeebo/errs v1.3.0
|
||||||
go.uber.org/zap v1.21.0
|
go.uber.org/zap v1.21.0
|
||||||
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22
|
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
@ -24,7 +26,6 @@ require (
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/OneOfOne/xxhash v1.2.8 // indirect
|
github.com/OneOfOne/xxhash v1.2.8 // indirect
|
||||||
github.com/anytypeio/go-chash v0.0.0-20220629194632-4ad1154fe232 // indirect
|
|
||||||
github.com/btcsuite/btcd v0.22.1 // indirect
|
github.com/btcsuite/btcd v0.22.1 // indirect
|
||||||
github.com/btcsuite/btcd/btcec/v2 v2.1.3 // indirect
|
github.com/btcsuite/btcd/btcec/v2 v2.1.3 // indirect
|
||||||
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 // indirect
|
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 // indirect
|
||||||
@ -32,7 +33,6 @@ require (
|
|||||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
|
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
|
||||||
github.com/fogleman/gg v1.3.0 // indirect
|
github.com/fogleman/gg v1.3.0 // indirect
|
||||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
|
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
|
||||||
github.com/golang/protobuf v1.5.2 // indirect
|
|
||||||
github.com/klauspost/cpuid/v2 v2.0.12 // indirect
|
github.com/klauspost/cpuid/v2 v2.0.12 // indirect
|
||||||
github.com/libp2p/go-buffer-pool v0.0.2 // indirect
|
github.com/libp2p/go-buffer-pool v0.0.2 // indirect
|
||||||
github.com/libp2p/go-openssl v0.0.7 // indirect
|
github.com/libp2p/go-openssl v0.0.7 // indirect
|
||||||
@ -47,13 +47,11 @@ require (
|
|||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 // indirect
|
github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 // indirect
|
||||||
github.com/spaolacci/murmur3 v1.1.0 // indirect
|
github.com/spaolacci/murmur3 v1.1.0 // indirect
|
||||||
github.com/zeebo/errs v1.3.0 // indirect
|
|
||||||
go.uber.org/atomic v1.9.0 // indirect
|
go.uber.org/atomic v1.9.0 // indirect
|
||||||
go.uber.org/multierr v1.8.0 // indirect
|
go.uber.org/multierr v1.8.0 // indirect
|
||||||
golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 // indirect
|
golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 // indirect
|
||||||
golang.org/x/image v0.0.0-20200119044424-58c23975cae1 // indirect
|
golang.org/x/image v0.0.0-20200119044424-58c23975cae1 // indirect
|
||||||
golang.org/x/sys v0.0.0-20220422013727-9388b58f7150 // indirect
|
golang.org/x/sys v0.0.0-20220422013727-9388b58f7150 // indirect
|
||||||
google.golang.org/protobuf v1.28.1 // indirect
|
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
lukechampine.com/blake3 v1.1.6 // indirect
|
lukechampine.com/blake3 v1.1.6 // indirect
|
||||||
|
|||||||
10
go.sum
10
go.sum
@ -32,10 +32,6 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
|||||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
|
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
|
||||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
||||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
|
||||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
|
||||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/huandu/go-assert v1.1.5 h1:fjemmA7sSfYHJD7CUqs9qTwwfdNAx7/j2/ZlHXzNB3c=
|
github.com/huandu/go-assert v1.1.5 h1:fjemmA7sSfYHJD7CUqs9qTwwfdNAx7/j2/ZlHXzNB3c=
|
||||||
github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0JrPVhn/06U=
|
github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0JrPVhn/06U=
|
||||||
github.com/huandu/skiplist v1.2.0 h1:gox56QD77HzSC0w+Ws3MH3iie755GBJU1OER3h5VsYw=
|
github.com/huandu/skiplist v1.2.0 h1:gox56QD77HzSC0w+Ws3MH3iie755GBJU1OER3h5VsYw=
|
||||||
@ -117,8 +113,6 @@ github.com/zeebo/assert v1.1.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN
|
|||||||
github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ=
|
github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ=
|
||||||
github.com/zeebo/blake3 v0.2.3 h1:TFoLXsjeXqRNFxSbk35Dk4YtszE/MQQGK10BH4ptoTg=
|
github.com/zeebo/blake3 v0.2.3 h1:TFoLXsjeXqRNFxSbk35Dk4YtszE/MQQGK10BH4ptoTg=
|
||||||
github.com/zeebo/blake3 v0.2.3/go.mod h1:mjJjZpnsyIVtVgTOSpJ9vmRE4wgDeyt2HU3qXvvKCaQ=
|
github.com/zeebo/blake3 v0.2.3/go.mod h1:mjJjZpnsyIVtVgTOSpJ9vmRE4wgDeyt2HU3qXvvKCaQ=
|
||||||
github.com/zeebo/errs v1.2.2 h1:5NFypMTuSdoySVTqlNs1dEoU21QVamMQJxW/Fii5O7g=
|
|
||||||
github.com/zeebo/errs v1.2.2/go.mod h1:sgbWHsvVuTPHcqJJGQ1WhI5KbWlHYz+2+2C/LSEtCw4=
|
|
||||||
github.com/zeebo/errs v1.3.0 h1:hmiaKqgYZzcVgRL1Vkc1Mn2914BbzB0IBxs+ebeutGs=
|
github.com/zeebo/errs v1.3.0 h1:hmiaKqgYZzcVgRL1Vkc1Mn2914BbzB0IBxs+ebeutGs=
|
||||||
github.com/zeebo/errs v1.3.0/go.mod h1:sgbWHsvVuTPHcqJJGQ1WhI5KbWlHYz+2+2C/LSEtCw4=
|
github.com/zeebo/errs v1.3.0/go.mod h1:sgbWHsvVuTPHcqJJGQ1WhI5KbWlHYz+2+2C/LSEtCw4=
|
||||||
github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo=
|
github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo=
|
||||||
@ -184,10 +178,6 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
|
|||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
|
||||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
|
||||||
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
|
|
||||||
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||||
|
|||||||
@ -1,143 +0,0 @@
|
|||||||
syntax = "proto3";
|
|
||||||
package acl;
|
|
||||||
option go_package = "pkg/acl/aclchanges/aclpb";
|
|
||||||
|
|
||||||
// ACL protos
|
|
||||||
|
|
||||||
message RawACLRecord {
|
|
||||||
bytes payload = 1;
|
|
||||||
bytes signature = 2;
|
|
||||||
string id = 3; // this field is only used on user side for convenience, it should be empty when saving to db
|
|
||||||
}
|
|
||||||
|
|
||||||
message ACLContentValue {
|
|
||||||
oneof value {
|
|
||||||
ACLUserAdd userAdd = 1;
|
|
||||||
ACLUserRemove userRemove = 2;
|
|
||||||
ACLUserPermissionChange userPermissionChange = 3;
|
|
||||||
ACLUserInvite userInvite = 4;
|
|
||||||
ACLUserJoin userJoin = 5;
|
|
||||||
ACLUserConfirm userConfirm = 6;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
message ACLData {
|
|
||||||
repeated ACLContentValue aclContent = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
message ACLState {
|
|
||||||
repeated uint64 readKeyHashes = 1;
|
|
||||||
repeated ACLUserState userStates = 2;
|
|
||||||
map<string, ACLUserInvite> invites = 3; // TODO: later
|
|
||||||
// repeated string unconfirmedUsers = 4; // TODO: later
|
|
||||||
}
|
|
||||||
|
|
||||||
message ACLUserState {
|
|
||||||
bytes identity = 1;
|
|
||||||
bytes encryptionKey = 2;
|
|
||||||
repeated bytes encryptedReadKeys = 3; // all read keys that we know
|
|
||||||
ACLUserPermissions permissions = 4;
|
|
||||||
bool isConfirmed = 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
// we already know identity and encryptionKey
|
|
||||||
message ACLUserAdd {
|
|
||||||
bytes identity = 1; // public signing key
|
|
||||||
bytes encryptionKey = 2; // public encryption key
|
|
||||||
repeated bytes encryptedReadKeys = 3; // all read keys that we know for the user
|
|
||||||
ACLUserPermissions permissions = 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: this is not used as of now
|
|
||||||
message ACLUserConfirm { // not needed for read permissions
|
|
||||||
bytes identity = 1; // not needed
|
|
||||||
string userAddId = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
message ACLUserInvite {
|
|
||||||
bytes acceptPublicKey = 1;
|
|
||||||
bytes encryptPublicKey = 2;
|
|
||||||
repeated bytes encryptedReadKeys = 3; // all read keys that we know for the user
|
|
||||||
ACLUserPermissions permissions = 4;
|
|
||||||
string inviteId = 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
message ACLUserJoin {
|
|
||||||
bytes identity = 1;
|
|
||||||
bytes encryptionKey = 2;
|
|
||||||
bytes acceptSignature = 3; // sign acceptPublicKey
|
|
||||||
string userInviteId = 4;
|
|
||||||
repeated bytes encryptedReadKeys = 5; // the idea is that user should itself reencrypt the keys with the pub key
|
|
||||||
}
|
|
||||||
|
|
||||||
message ACLUserRemove {
|
|
||||||
bytes identity = 1;
|
|
||||||
repeated ACLReadKeyReplace readKeyReplaces = 3; // new read key encrypted for all users
|
|
||||||
}
|
|
||||||
|
|
||||||
message ACLReadKeyReplace {
|
|
||||||
bytes identity = 1;
|
|
||||||
bytes encryptionKey = 2;
|
|
||||||
bytes encryptedReadKey = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
message ACLUserPermissionChange {
|
|
||||||
bytes identity = 1;
|
|
||||||
ACLUserPermissions permissions = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum ACLUserPermissions {
|
|
||||||
Admin = 0;
|
|
||||||
Writer = 1;
|
|
||||||
Reader = 2;
|
|
||||||
Removed = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
message ACLRecord {
|
|
||||||
string prevId = 1;
|
|
||||||
bytes identity = 2;
|
|
||||||
bytes data = 3;
|
|
||||||
uint64 currentReadKeyHash = 4;
|
|
||||||
int64 timestamp = 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
message ACLHeader {
|
|
||||||
string firstId = 1;
|
|
||||||
bytes identity = 2; // the identity of the creator
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tree protos
|
|
||||||
|
|
||||||
message RawTreeChange {
|
|
||||||
bytes payload = 1;
|
|
||||||
bytes signature = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
message RawTreeChangeWithId {
|
|
||||||
bytes rawChange = 1;
|
|
||||||
string id = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
message TreeChange {
|
|
||||||
repeated string treeHeadIds = 1;
|
|
||||||
string aclHeadId = 2;
|
|
||||||
string snapshotBaseId = 3;
|
|
||||||
bytes changesData = 4;
|
|
||||||
uint64 currentReadKeyHash = 5;
|
|
||||||
int64 timestamp = 6;
|
|
||||||
bytes identity = 7;
|
|
||||||
bool isSnapshot = 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum TreeHeaderType {
|
|
||||||
Object = 0;
|
|
||||||
Space = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
message TreeHeader {
|
|
||||||
string firstId = 1;
|
|
||||||
string aclId = 2;
|
|
||||||
TreeHeaderType treeHeaderType = 3;
|
|
||||||
bytes identity = 4;
|
|
||||||
bytes data = 5; // this should be reserved for the client to add the data it needs
|
|
||||||
}
|
|
||||||
@ -1,12 +0,0 @@
|
|||||||
package aclchanges
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/gogo/protobuf/proto"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Change interface {
|
|
||||||
ProtoChange() proto.Marshaler
|
|
||||||
DecryptedChangeContent() []byte
|
|
||||||
Signature() []byte
|
|
||||||
CID() string
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
102
pkg/acl/aclrecordproto/protos/aclrecord.proto
Normal file
102
pkg/acl/aclrecordproto/protos/aclrecord.proto
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
package aclrecord;
|
||||||
|
option go_package = "pkg/acl/aclrecordproto";
|
||||||
|
|
||||||
|
message RawACLRecord {
|
||||||
|
bytes payload = 1;
|
||||||
|
bytes signature = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message RawACLRecordWithId {
|
||||||
|
bytes payload = 1;
|
||||||
|
string id = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ACLRecord {
|
||||||
|
string prevId = 1;
|
||||||
|
bytes identity = 2;
|
||||||
|
bytes data = 3;
|
||||||
|
uint64 currentReadKeyHash = 4;
|
||||||
|
int64 timestamp = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ACLRoot {
|
||||||
|
bytes identity = 1;
|
||||||
|
bytes encryptionKey = 2;
|
||||||
|
string spaceId = 3;
|
||||||
|
bytes encryptedReadKey = 4;
|
||||||
|
string derivationScheme = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ACLContentValue {
|
||||||
|
oneof value {
|
||||||
|
ACLUserAdd userAdd = 1;
|
||||||
|
ACLUserRemove userRemove = 2;
|
||||||
|
ACLUserPermissionChange userPermissionChange = 3;
|
||||||
|
ACLUserInvite userInvite = 4;
|
||||||
|
ACLUserJoin userJoin = 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
message ACLData {
|
||||||
|
repeated ACLContentValue aclContent = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ACLState {
|
||||||
|
repeated uint64 readKeyHashes = 1;
|
||||||
|
repeated ACLUserState userStates = 2;
|
||||||
|
map<string, ACLUserInvite> invites = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ACLUserState {
|
||||||
|
bytes identity = 1;
|
||||||
|
bytes encryptionKey = 2;
|
||||||
|
repeated bytes encryptedReadKeys = 3;
|
||||||
|
ACLUserPermissions permissions = 4;
|
||||||
|
bool isConfirmed = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ACLUserAdd {
|
||||||
|
bytes identity = 1;
|
||||||
|
bytes encryptionKey = 2;
|
||||||
|
repeated bytes encryptedReadKeys = 3;
|
||||||
|
ACLUserPermissions permissions = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ACLUserInvite {
|
||||||
|
bytes acceptPublicKey = 1;
|
||||||
|
bytes encryptPublicKey = 2;
|
||||||
|
repeated bytes encryptedReadKeys = 3;
|
||||||
|
ACLUserPermissions permissions = 4;
|
||||||
|
string inviteId = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ACLUserJoin {
|
||||||
|
bytes identity = 1;
|
||||||
|
bytes encryptionKey = 2;
|
||||||
|
bytes acceptSignature = 3;
|
||||||
|
string inviteId = 4;
|
||||||
|
repeated bytes encryptedReadKeys = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ACLUserRemove {
|
||||||
|
bytes identity = 1;
|
||||||
|
repeated ACLReadKeyReplace readKeyReplaces = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ACLReadKeyReplace {
|
||||||
|
bytes identity = 1;
|
||||||
|
bytes encryptionKey = 2;
|
||||||
|
bytes encryptedReadKey = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ACLUserPermissionChange {
|
||||||
|
bytes identity = 1;
|
||||||
|
ACLUserPermissions permissions = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ACLUserPermissions {
|
||||||
|
Admin = 0;
|
||||||
|
Writer = 1;
|
||||||
|
Reader = 2;
|
||||||
|
}
|
||||||
@ -5,7 +5,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/app/logger"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/app/logger"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclrecordproto"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/common"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/common"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/asymmetric/encryptionkey"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/asymmetric/encryptionkey"
|
||||||
@ -30,14 +30,14 @@ var ErrInvalidSignature = errors.New("signature is invalid")
|
|||||||
|
|
||||||
type UserPermissionPair struct {
|
type UserPermissionPair struct {
|
||||||
Identity string
|
Identity string
|
||||||
Permission aclpb.ACLUserPermissions
|
Permission aclrecordproto.ACLUserPermissions
|
||||||
}
|
}
|
||||||
|
|
||||||
type ACLState struct {
|
type ACLState struct {
|
||||||
currentReadKeyHash uint64
|
currentReadKeyHash uint64
|
||||||
userReadKeys map[uint64]*symmetric.Key
|
userReadKeys map[uint64]*symmetric.Key
|
||||||
userStates map[string]*aclpb.ACLUserState
|
userStates map[string]*aclrecordproto.ACLUserState
|
||||||
userInvites map[string]*aclpb.ACLUserInvite
|
userInvites map[string]*aclrecordproto.ACLUserInvite
|
||||||
|
|
||||||
signingPubKeyDecoder keys.Decoder
|
signingPubKeyDecoder keys.Decoder
|
||||||
encryptionKey encryptionkey.PrivKey
|
encryptionKey encryptionkey.PrivKey
|
||||||
@ -56,8 +56,8 @@ func newACLStateWithIdentity(
|
|||||||
identity: identity,
|
identity: identity,
|
||||||
encryptionKey: encryptionKey,
|
encryptionKey: encryptionKey,
|
||||||
userReadKeys: make(map[uint64]*symmetric.Key),
|
userReadKeys: make(map[uint64]*symmetric.Key),
|
||||||
userStates: make(map[string]*aclpb.ACLUserState),
|
userStates: make(map[string]*aclrecordproto.ACLUserState),
|
||||||
userInvites: make(map[string]*aclpb.ACLUserInvite),
|
userInvites: make(map[string]*aclrecordproto.ACLUserInvite),
|
||||||
signingPubKeyDecoder: decoder,
|
signingPubKeyDecoder: decoder,
|
||||||
permissionsAtRecord: make(map[string][]UserPermissionPair),
|
permissionsAtRecord: make(map[string][]UserPermissionPair),
|
||||||
keychain: common.NewKeychain(),
|
keychain: common.NewKeychain(),
|
||||||
@ -68,8 +68,8 @@ func newACLState(decoder keys.Decoder) *ACLState {
|
|||||||
return &ACLState{
|
return &ACLState{
|
||||||
signingPubKeyDecoder: decoder,
|
signingPubKeyDecoder: decoder,
|
||||||
userReadKeys: make(map[uint64]*symmetric.Key),
|
userReadKeys: make(map[uint64]*symmetric.Key),
|
||||||
userStates: make(map[string]*aclpb.ACLUserState),
|
userStates: make(map[string]*aclrecordproto.ACLUserState),
|
||||||
userInvites: make(map[string]*aclpb.ACLUserInvite),
|
userInvites: make(map[string]*aclrecordproto.ACLUserInvite),
|
||||||
permissionsAtRecord: make(map[string][]UserPermissionPair),
|
permissionsAtRecord: make(map[string][]UserPermissionPair),
|
||||||
keychain: common.NewKeychain(),
|
keychain: common.NewKeychain(),
|
||||||
}
|
}
|
||||||
@ -106,8 +106,8 @@ func (st *ACLState) PermissionsAtRecord(id string, identity string) (UserPermiss
|
|||||||
return UserPermissionPair{}, ErrNoSuchUser
|
return UserPermissionPair{}, ErrNoSuchUser
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *ACLState) applyRecord(record *aclpb.ACLRecord) (err error) {
|
func (st *ACLState) applyRecord(record *aclrecordproto.ACLRecord) (err error) {
|
||||||
aclData := &aclpb.ACLData{}
|
aclData := &aclrecordproto.ACLData{}
|
||||||
|
|
||||||
err = proto.Unmarshal(record.Data, aclData)
|
err = proto.Unmarshal(record.Data, aclData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -126,11 +126,11 @@ func (st *ACLState) applyRecord(record *aclpb.ACLRecord) (err error) {
|
|||||||
func (st *ACLState) applyChangeAndUpdate(recordWrapper *ACLRecord) (err error) {
|
func (st *ACLState) applyChangeAndUpdate(recordWrapper *ACLRecord) (err error) {
|
||||||
var (
|
var (
|
||||||
change = recordWrapper.Content
|
change = recordWrapper.Content
|
||||||
aclData = &aclpb.ACLData{}
|
aclData = &aclrecordproto.ACLData{}
|
||||||
)
|
)
|
||||||
|
|
||||||
if recordWrapper.Model != nil {
|
if recordWrapper.Model != nil {
|
||||||
aclData = recordWrapper.Model.(*aclpb.ACLData)
|
aclData = recordWrapper.Model.(*aclrecordproto.ACLData)
|
||||||
} else {
|
} else {
|
||||||
err = proto.Unmarshal(change.Data, aclData)
|
err = proto.Unmarshal(change.Data, aclData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -158,7 +158,7 @@ func (st *ACLState) applyChangeAndUpdate(recordWrapper *ACLRecord) (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *ACLState) applyChangeData(changeData *aclpb.ACLData, hash uint64, identity []byte) (err error) {
|
func (st *ACLState) applyChangeData(changeData *aclrecordproto.ACLData, hash uint64, identity []byte) (err error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@ -176,7 +176,7 @@ func (st *ACLState) applyChangeData(changeData *aclpb.ACLData, hash uint64, iden
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !st.hasPermission(identity, aclpb.ACLUserPermissions_Admin) {
|
if !st.hasPermission(identity, aclrecordproto.ACLUserPermissions_Admin) {
|
||||||
err = fmt.Errorf("user %s must have admin permissions", identity)
|
err = fmt.Errorf("user %s must have admin permissions", identity)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -192,7 +192,7 @@ func (st *ACLState) applyChangeData(changeData *aclpb.ACLData, hash uint64, iden
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *ACLState) applyChangeContent(ch *aclpb.ACLContentValue) error {
|
func (st *ACLState) applyChangeContent(ch *aclrecordproto.ACLContentValue) error {
|
||||||
switch {
|
switch {
|
||||||
case ch.GetUserPermissionChange() != nil:
|
case ch.GetUserPermissionChange() != nil:
|
||||||
return st.applyUserPermissionChange(ch.GetUserPermissionChange())
|
return st.applyUserPermissionChange(ch.GetUserPermissionChange())
|
||||||
@ -211,7 +211,7 @@ func (st *ACLState) applyChangeContent(ch *aclpb.ACLContentValue) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *ACLState) applyUserPermissionChange(ch *aclpb.ACLUserPermissionChange) error {
|
func (st *ACLState) applyUserPermissionChange(ch *aclrecordproto.ACLUserPermissionChange) error {
|
||||||
chIdentity := string(ch.Identity)
|
chIdentity := string(ch.Identity)
|
||||||
state, exists := st.userStates[chIdentity]
|
state, exists := st.userStates[chIdentity]
|
||||||
if !exists {
|
if !exists {
|
||||||
@ -222,12 +222,12 @@ func (st *ACLState) applyUserPermissionChange(ch *aclpb.ACLUserPermissionChange)
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *ACLState) applyUserInvite(ch *aclpb.ACLUserInvite) error {
|
func (st *ACLState) applyUserInvite(ch *aclrecordproto.ACLUserInvite) error {
|
||||||
st.userInvites[ch.InviteId] = ch
|
st.userInvites[ch.InviteId] = ch
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *ACLState) applyUserJoin(ch *aclpb.ACLUserJoin) error {
|
func (st *ACLState) applyUserJoin(ch *aclrecordproto.ACLUserJoin) error {
|
||||||
invite, exists := st.userInvites[ch.UserInviteId]
|
invite, exists := st.userInvites[ch.UserInviteId]
|
||||||
if !exists {
|
if !exists {
|
||||||
return fmt.Errorf("no such invite with id %s", ch.UserInviteId)
|
return fmt.Errorf("no such invite with id %s", ch.UserInviteId)
|
||||||
@ -266,7 +266,7 @@ func (st *ACLState) applyUserJoin(ch *aclpb.ACLUserJoin) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// adding user to the list
|
// adding user to the list
|
||||||
userState := &aclpb.ACLUserState{
|
userState := &aclrecordproto.ACLUserState{
|
||||||
Identity: ch.Identity,
|
Identity: ch.Identity,
|
||||||
EncryptionKey: ch.EncryptionKey,
|
EncryptionKey: ch.EncryptionKey,
|
||||||
EncryptedReadKeys: ch.EncryptedReadKeys,
|
EncryptedReadKeys: ch.EncryptedReadKeys,
|
||||||
@ -277,13 +277,13 @@ func (st *ACLState) applyUserJoin(ch *aclpb.ACLUserJoin) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *ACLState) applyUserAdd(ch *aclpb.ACLUserAdd) error {
|
func (st *ACLState) applyUserAdd(ch *aclrecordproto.ACLUserAdd) error {
|
||||||
chIdentity := string(ch.Identity)
|
chIdentity := string(ch.Identity)
|
||||||
if _, exists := st.userStates[chIdentity]; exists {
|
if _, exists := st.userStates[chIdentity]; exists {
|
||||||
return ErrUserAlreadyExists
|
return ErrUserAlreadyExists
|
||||||
}
|
}
|
||||||
|
|
||||||
st.userStates[chIdentity] = &aclpb.ACLUserState{
|
st.userStates[chIdentity] = &aclrecordproto.ACLUserState{
|
||||||
Identity: ch.Identity,
|
Identity: ch.Identity,
|
||||||
EncryptionKey: ch.EncryptionKey,
|
EncryptionKey: ch.EncryptionKey,
|
||||||
Permissions: ch.Permissions,
|
Permissions: ch.Permissions,
|
||||||
@ -304,7 +304,7 @@ func (st *ACLState) applyUserAdd(ch *aclpb.ACLUserAdd) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *ACLState) applyUserRemove(ch *aclpb.ACLUserRemove) error {
|
func (st *ACLState) applyUserRemove(ch *aclrecordproto.ACLUserRemove) error {
|
||||||
chIdentity := string(ch.Identity)
|
chIdentity := string(ch.Identity)
|
||||||
if chIdentity == st.identity {
|
if chIdentity == st.identity {
|
||||||
return ErrDocumentForbidden
|
return ErrDocumentForbidden
|
||||||
@ -338,7 +338,7 @@ func (st *ACLState) applyUserRemove(ch *aclpb.ACLUserRemove) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *ACLState) applyUserConfirm(ch *aclpb.ACLUserConfirm) error {
|
func (st *ACLState) applyUserConfirm(ch *aclrecordproto.ACLUserConfirm) error {
|
||||||
chIdentity := string(ch.Identity)
|
chIdentity := string(ch.Identity)
|
||||||
state, exists := st.userStates[chIdentity]
|
state, exists := st.userStates[chIdentity]
|
||||||
if !exists {
|
if !exists {
|
||||||
@ -365,7 +365,7 @@ func (st *ACLState) decryptReadKeyAndHash(msg []byte) (*symmetric.Key, uint64, e
|
|||||||
return key, hasher.Sum64(), nil
|
return key, hasher.Sum64(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *ACLState) hasPermission(identity []byte, permission aclpb.ACLUserPermissions) bool {
|
func (st *ACLState) hasPermission(identity []byte, permission aclrecordproto.ACLUserPermissions) bool {
|
||||||
state, exists := st.userStates[string(identity)]
|
state, exists := st.userStates[string(identity)]
|
||||||
if !exists {
|
if !exists {
|
||||||
return false
|
return false
|
||||||
@ -374,17 +374,17 @@ func (st *ACLState) hasPermission(identity []byte, permission aclpb.ACLUserPermi
|
|||||||
return state.Permissions == permission
|
return state.Permissions == permission
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *ACLState) isUserJoin(data *aclpb.ACLData) bool {
|
func (st *ACLState) isUserJoin(data *aclrecordproto.ACLData) bool {
|
||||||
// if we have a UserJoin, then it should always be the first one applied
|
// if we have a UserJoin, then it should always be the first one applied
|
||||||
return data.GetAclContent() != nil && data.GetAclContent()[0].GetUserJoin() != nil
|
return data.GetAclContent() != nil && data.GetAclContent()[0].GetUserJoin() != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *ACLState) isUserAdd(data *aclpb.ACLData, identity []byte) bool {
|
func (st *ACLState) isUserAdd(data *aclrecordproto.ACLData, identity []byte) bool {
|
||||||
// if we have a UserAdd, then it should always be the first one applied
|
// if we have a UserAdd, then it should always be the first one applied
|
||||||
userAdd := data.GetAclContent()[0].GetUserAdd()
|
userAdd := data.GetAclContent()[0].GetUserAdd()
|
||||||
return data.GetAclContent() != nil && userAdd != nil && bytes.Compare(userAdd.GetIdentity(), identity) == 0
|
return data.GetAclContent() != nil && userAdd != nil && bytes.Compare(userAdd.GetIdentity(), identity) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *ACLState) GetUserStates() map[string]*aclpb.ACLUserState {
|
func (st *ACLState) GetUserStates() map[string]*aclrecordproto.ACLUserState {
|
||||||
return st.userStates
|
return st.userStates
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,7 @@ package list
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/account"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/account"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclrecordproto/aclpb"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/cid"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/cid"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/asymmetric/encryptionkey"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/asymmetric/encryptionkey"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/symmetric"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/symmetric"
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/account"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/account"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclrecordproto/aclpb"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/common"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/common"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/storage"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/storage"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/cid"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/cid"
|
||||||
@ -60,7 +60,7 @@ func BuildACLList(decoder keys.Decoder, storage storage.ListStorage) (ACLList, e
|
|||||||
}
|
}
|
||||||
|
|
||||||
func buildWithACLStateBuilder(builder *aclStateBuilder, storage storage.ListStorage) (list ACLList, err error) {
|
func buildWithACLStateBuilder(builder *aclStateBuilder, storage storage.ListStorage) (list ACLList, err error) {
|
||||||
header, err := storage.Header()
|
header, err := storage.Root()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
package list
|
package list
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclrecordproto/aclpb"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/testutils/acllistbuilder"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/testutils/acllistbuilder"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/asymmetric/signingkey"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/asymmetric/signingkey"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|||||||
@ -1,19 +1,19 @@
|
|||||||
package list
|
package list
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclrecordproto"
|
||||||
"github.com/gogo/protobuf/proto"
|
"github.com/gogo/protobuf/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ACLRecord struct {
|
type ACLRecord struct {
|
||||||
Id string
|
Id string
|
||||||
Content *aclpb.ACLRecord
|
Content *aclrecordproto.ACLRecord
|
||||||
Identity string
|
Identity string
|
||||||
Model interface{}
|
Model interface{}
|
||||||
Sign []byte
|
Sign []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRecord(id string, aclRecord *aclpb.ACLRecord) *ACLRecord {
|
func NewRecord(id string, aclRecord *aclrecordproto.ACLRecord) *ACLRecord {
|
||||||
return &ACLRecord{
|
return &ACLRecord{
|
||||||
Id: id,
|
Id: id,
|
||||||
Content: aclRecord,
|
Content: aclRecord,
|
||||||
@ -21,17 +21,45 @@ func NewRecord(id string, aclRecord *aclpb.ACLRecord) *ACLRecord {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewFromRawRecord(rawRec *aclpb.RawACLRecord) (*ACLRecord, error) {
|
func NewFromRawRecord(rawRecWithId *aclrecordproto.RawACLRecordWithId) (aclRec *ACLRecord, err error) {
|
||||||
aclRec := &aclpb.ACLRecord{}
|
rawRec := &aclrecordproto.RawACLRecord{}
|
||||||
err := proto.Unmarshal(rawRec.Payload, aclRec)
|
err = proto.Unmarshal(rawRecWithId.Payload, rawRec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
protoAclRec := &aclrecordproto.ACLRecord{}
|
||||||
|
err = proto.Unmarshal(rawRec.Payload, protoAclRec)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
return &ACLRecord{
|
return &ACLRecord{
|
||||||
Id: rawRec.Id,
|
Id: rawRecWithId.Id,
|
||||||
Content: aclRec,
|
Content: protoAclRec,
|
||||||
Sign: rawRec.Signature,
|
Sign: rawRec.Signature,
|
||||||
Identity: string(aclRec.Identity),
|
Identity: string(protoAclRec.Identity),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewFromRawRoot(rawRecWithId *aclrecordproto.RawACLRecordWithId) (aclRec *ACLRecord, err error) {
|
||||||
|
rawRec := &aclrecordproto.RawACLRecord{}
|
||||||
|
err = proto.Unmarshal(rawRecWithId.Payload, rawRec)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
protoAclRec := &aclrecordproto.ACLRecord{}
|
||||||
|
err = proto.Unmarshal(rawRec.Payload, protoAclRec)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return &ACLRecord{
|
||||||
|
Id: rawRecWithId.Id,
|
||||||
|
Content: protoAclRec,
|
||||||
|
Sign: rawRec.Signature,
|
||||||
|
Identity: string(protoAclRec.Identity),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@ -3,14 +3,13 @@ package storage
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclrecordproto"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treechangeproto"
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
type inMemoryACLListStorage struct {
|
type inMemoryACLListStorage struct {
|
||||||
header *aclpb.ACLHeader
|
records []*aclrecordproto.RawACLRecordWithId
|
||||||
records []*aclpb.RawACLRecord
|
|
||||||
|
|
||||||
id string
|
id string
|
||||||
|
|
||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
@ -18,29 +17,27 @@ type inMemoryACLListStorage struct {
|
|||||||
|
|
||||||
func NewInMemoryACLListStorage(
|
func NewInMemoryACLListStorage(
|
||||||
id string,
|
id string,
|
||||||
header *aclpb.ACLHeader,
|
records []*aclrecordproto.RawACLRecordWithId) (ListStorage, error) {
|
||||||
records []*aclpb.RawACLRecord) (ListStorage, error) {
|
|
||||||
return &inMemoryACLListStorage{
|
return &inMemoryACLListStorage{
|
||||||
id: id,
|
id: id,
|
||||||
header: header,
|
|
||||||
records: records,
|
records: records,
|
||||||
RWMutex: sync.RWMutex{},
|
RWMutex: sync.RWMutex{},
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *inMemoryACLListStorage) Header() (*aclpb.ACLHeader, error) {
|
func (i *inMemoryACLListStorage) Root() (*aclrecordproto.RawACLRecordWithId, error) {
|
||||||
i.RLock()
|
i.RLock()
|
||||||
defer i.RUnlock()
|
defer i.RUnlock()
|
||||||
return i.header, nil
|
return i.records[0], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *inMemoryACLListStorage) Head() (*aclpb.RawACLRecord, error) {
|
func (i *inMemoryACLListStorage) Head() (*aclrecordproto.RawACLRecordWithId, error) {
|
||||||
i.RLock()
|
i.RLock()
|
||||||
defer i.RUnlock()
|
defer i.RUnlock()
|
||||||
return i.records[len(i.records)-1], nil
|
return i.records[len(i.records)-1], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *inMemoryACLListStorage) GetRawRecord(ctx context.Context, id string) (*aclpb.RawACLRecord, error) {
|
func (i *inMemoryACLListStorage) GetRawRecord(ctx context.Context, id string) (*aclrecordproto.RawACLRecordWithId, error) {
|
||||||
i.RLock()
|
i.RLock()
|
||||||
defer i.RUnlock()
|
defer i.RUnlock()
|
||||||
for _, rec := range i.records {
|
for _, rec := range i.records {
|
||||||
@ -51,7 +48,7 @@ func (i *inMemoryACLListStorage) GetRawRecord(ctx context.Context, id string) (*
|
|||||||
return nil, fmt.Errorf("no such record")
|
return nil, fmt.Errorf("no such record")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *inMemoryACLListStorage) AddRawRecord(ctx context.Context, rec *aclpb.RawACLRecord) error {
|
func (i *inMemoryACLListStorage) AddRawRecord(ctx context.Context, rec *aclrecordproto.RawACLRecordWithId) error {
|
||||||
panic("implement me")
|
panic("implement me")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,26 +60,27 @@ func (i *inMemoryACLListStorage) ID() (string, error) {
|
|||||||
|
|
||||||
type inMemoryTreeStorage struct {
|
type inMemoryTreeStorage struct {
|
||||||
id string
|
id string
|
||||||
header *aclpb.TreeHeader
|
root *treechangeproto.RawTreeChangeWithId
|
||||||
heads []string
|
heads []string
|
||||||
changes map[string]*aclpb.RawTreeChangeWithId
|
changes map[string]*treechangeproto.RawTreeChangeWithId
|
||||||
|
|
||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewInMemoryTreeStorage(
|
func NewInMemoryTreeStorage(
|
||||||
treeId string,
|
treeId string,
|
||||||
header *aclpb.TreeHeader,
|
root *treechangeproto.RawTreeChangeWithId,
|
||||||
heads []string,
|
heads []string,
|
||||||
changes []*aclpb.RawTreeChangeWithId) (TreeStorage, error) {
|
changes []*treechangeproto.RawTreeChangeWithId) (TreeStorage, error) {
|
||||||
allChanges := make(map[string]*aclpb.RawTreeChangeWithId)
|
allChanges := make(map[string]*treechangeproto.RawTreeChangeWithId)
|
||||||
for _, ch := range changes {
|
for _, ch := range changes {
|
||||||
allChanges[ch.Id] = ch
|
allChanges[ch.Id] = ch
|
||||||
}
|
}
|
||||||
|
allChanges[treeId] = root
|
||||||
|
|
||||||
return &inMemoryTreeStorage{
|
return &inMemoryTreeStorage{
|
||||||
id: treeId,
|
id: treeId,
|
||||||
header: header,
|
root: root,
|
||||||
heads: heads,
|
heads: heads,
|
||||||
changes: allChanges,
|
changes: allChanges,
|
||||||
RWMutex: sync.RWMutex{},
|
RWMutex: sync.RWMutex{},
|
||||||
@ -95,10 +93,10 @@ func (t *inMemoryTreeStorage) ID() (string, error) {
|
|||||||
return t.id, nil
|
return t.id, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *inMemoryTreeStorage) Header() (*aclpb.TreeHeader, error) {
|
func (t *inMemoryTreeStorage) Root() (*treechangeproto.RawTreeChangeWithId, error) {
|
||||||
t.RLock()
|
t.RLock()
|
||||||
defer t.RUnlock()
|
defer t.RUnlock()
|
||||||
return t.header, nil
|
return t.root, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *inMemoryTreeStorage) Heads() ([]string, error) {
|
func (t *inMemoryTreeStorage) Heads() ([]string, error) {
|
||||||
@ -118,7 +116,7 @@ func (t *inMemoryTreeStorage) SetHeads(heads []string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *inMemoryTreeStorage) AddRawChange(change *aclpb.RawTreeChangeWithId) error {
|
func (t *inMemoryTreeStorage) AddRawChange(change *treechangeproto.RawTreeChangeWithId) error {
|
||||||
t.Lock()
|
t.Lock()
|
||||||
defer t.Unlock()
|
defer t.Unlock()
|
||||||
// TODO: better to do deep copy
|
// TODO: better to do deep copy
|
||||||
@ -126,7 +124,7 @@ func (t *inMemoryTreeStorage) AddRawChange(change *aclpb.RawTreeChangeWithId) er
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *inMemoryTreeStorage) GetRawChange(ctx context.Context, changeId string) (*aclpb.RawTreeChangeWithId, error) {
|
func (t *inMemoryTreeStorage) GetRawChange(ctx context.Context, changeId string) (*treechangeproto.RawTreeChangeWithId, error) {
|
||||||
t.RLock()
|
t.RLock()
|
||||||
defer t.RUnlock()
|
defer t.RUnlock()
|
||||||
if res, exists := t.changes[changeId]; exists {
|
if res, exists := t.changes[changeId]; exists {
|
||||||
@ -163,7 +161,7 @@ func (i *inMemoryStorageProvider) Storage(id string) (Storage, error) {
|
|||||||
func (i *inMemoryStorageProvider) CreateTreeStorage(payload TreeStorageCreatePayload) (TreeStorage, error) {
|
func (i *inMemoryStorageProvider) CreateTreeStorage(payload TreeStorageCreatePayload) (TreeStorage, error) {
|
||||||
i.Lock()
|
i.Lock()
|
||||||
defer i.Unlock()
|
defer i.Unlock()
|
||||||
res, err := NewInMemoryTreeStorage(payload.TreeId, payload.Header, payload.Heads, payload.Changes)
|
res, err := NewInMemoryTreeStorage(payload.TreeId, payload.RootRawChange, payload.Heads, payload.Changes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -175,7 +173,7 @@ func (i *inMemoryStorageProvider) CreateTreeStorage(payload TreeStorageCreatePay
|
|||||||
func (i *inMemoryStorageProvider) CreateACLListStorage(payload ACLListStorageCreatePayload) (ListStorage, error) {
|
func (i *inMemoryStorageProvider) CreateACLListStorage(payload ACLListStorageCreatePayload) (ListStorage, error) {
|
||||||
i.Lock()
|
i.Lock()
|
||||||
defer i.Unlock()
|
defer i.Unlock()
|
||||||
res, err := NewInMemoryACLListStorage(payload.ListId, payload.Header, payload.Records)
|
res, err := NewInMemoryACLListStorage(payload.ListId, payload.Records)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,14 +2,14 @@ package storage
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclrecordproto"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ListStorage interface {
|
type ListStorage interface {
|
||||||
Storage
|
Storage
|
||||||
Header() (*aclpb.ACLHeader, error)
|
Root() (*aclrecordproto.RawACLRecordWithId, error)
|
||||||
Head() (*aclpb.RawACLRecord, error)
|
Head() (*aclrecordproto.RawACLRecordWithId, error)
|
||||||
|
|
||||||
GetRawRecord(ctx context.Context, id string) (*aclpb.RawACLRecord, error)
|
GetRawRecord(ctx context.Context, id string) (*aclrecordproto.RawACLRecordWithId, error)
|
||||||
AddRawRecord(ctx context.Context, rec *aclpb.RawACLRecord) error
|
AddRawRecord(ctx context.Context, rec *aclrecordproto.RawACLRecordWithId) error
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,27 +2,26 @@ package storage
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclrecordproto"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treechangeproto"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ErrUnknownTreeId = errors.New("tree does not exist")
|
var ErrUnknownTreeId = errors.New("tree does not exist")
|
||||||
|
|
||||||
type TreeStorageCreatePayload struct {
|
type TreeStorageCreatePayload struct {
|
||||||
TreeId string
|
TreeId string
|
||||||
Header *aclpb.TreeHeader
|
RootRawChange *treechangeproto.RawTreeChangeWithId
|
||||||
Changes []*aclpb.RawTreeChangeWithId
|
Changes []*treechangeproto.RawTreeChangeWithId
|
||||||
Heads []string
|
Heads []string
|
||||||
}
|
}
|
||||||
|
|
||||||
type ACLListStorageCreatePayload struct {
|
type ACLListStorageCreatePayload struct {
|
||||||
ListId string
|
ListId string
|
||||||
Header *aclpb.ACLHeader
|
Records []*aclrecordproto.RawACLRecordWithId
|
||||||
Records []*aclpb.RawACLRecord
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Provider interface {
|
type Provider interface {
|
||||||
Storage(id string) (Storage, error)
|
Storage(id string) (Storage, error)
|
||||||
AddStorage(id string, st Storage) error
|
|
||||||
CreateTreeStorage(payload TreeStorageCreatePayload) (TreeStorage, error)
|
CreateTreeStorage(payload TreeStorageCreatePayload) (TreeStorage, error)
|
||||||
CreateACLListStorage(payload ACLListStorageCreatePayload) (ListStorage, error)
|
CreateACLListStorage(payload ACLListStorageCreatePayload) (ListStorage, error)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,17 +2,17 @@ package storage
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treechangeproto"
|
||||||
)
|
)
|
||||||
|
|
||||||
type TreeStorage interface {
|
type TreeStorage interface {
|
||||||
Storage
|
Storage
|
||||||
Header() (*aclpb.TreeHeader, error)
|
Root() (*treechangeproto.RawTreeChangeWithId, error)
|
||||||
Heads() ([]string, error)
|
Heads() ([]string, error)
|
||||||
SetHeads(heads []string) error
|
SetHeads(heads []string) error
|
||||||
|
|
||||||
AddRawChange(change *aclpb.RawTreeChangeWithId) error
|
AddRawChange(change *treechangeproto.RawTreeChangeWithId) error
|
||||||
GetRawChange(ctx context.Context, recordID string) (*aclpb.RawTreeChangeWithId, error)
|
GetRawChange(ctx context.Context, id string) (*treechangeproto.RawTreeChangeWithId, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type TreeStorageCreatorFunc = func(payload TreeStorageCreatePayload) (TreeStorage, error)
|
type TreeStorageCreatorFunc = func(payload TreeStorageCreatePayload) (TreeStorage, error)
|
||||||
|
|||||||
@ -2,11 +2,7 @@ package tree
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treechangeproto"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb"
|
|
||||||
"github.com/gogo/protobuf/proto"
|
|
||||||
|
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/symmetric"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -14,68 +10,52 @@ var (
|
|||||||
ErrIncorrectCID = errors.New("change has incorrect CID")
|
ErrIncorrectCID = errors.New("change has incorrect CID")
|
||||||
)
|
)
|
||||||
|
|
||||||
type ChangeContent struct {
|
|
||||||
ChangesData proto.Marshaler
|
|
||||||
ACLData *aclpb.ACLData
|
|
||||||
Id string // TODO: this is just for testing, because id should be created automatically from content
|
|
||||||
}
|
|
||||||
|
|
||||||
// Change is an abstract type for all types of changes
|
// Change is an abstract type for all types of changes
|
||||||
type Change struct {
|
type Change struct {
|
||||||
Next []*Change
|
Next []*Change
|
||||||
PreviousIds []string
|
PreviousIds []string
|
||||||
|
AclHeadId string
|
||||||
Id string
|
Id string
|
||||||
SnapshotId string
|
SnapshotId string
|
||||||
IsSnapshot bool
|
IsSnapshot bool
|
||||||
DecryptedChange []byte // TODO: check if we need it
|
Timestamp int64
|
||||||
ParsedModel interface{} // TODO: check if we need it
|
ReadKeyHash uint64
|
||||||
|
Identity string
|
||||||
|
Data []byte
|
||||||
|
Model interface{}
|
||||||
|
|
||||||
// iterator helpers
|
// iterator helpers
|
||||||
visited bool
|
visited bool
|
||||||
branchesFinished bool
|
branchesFinished bool
|
||||||
|
|
||||||
Content *aclpb.TreeChange
|
Signature []byte
|
||||||
Identity string
|
|
||||||
Sign []byte
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ch *Change) ProtoChange() proto.Marshaler {
|
func NewChange(id string, ch *treechangeproto.TreeChange, signature []byte) *Change {
|
||||||
return ch.Content
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ch *Change) DecryptContents(key *symmetric.Key) error {
|
|
||||||
// if the document is already decrypted
|
|
||||||
if ch.Content.CurrentReadKeyHash == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
decrypted, err := key.Decrypt(ch.Content.ChangesData)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to decrypt changes data: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
ch.DecryptedChange = decrypted
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewChange(id string, ch *aclpb.TreeChange, signature []byte) *Change {
|
|
||||||
return &Change{
|
return &Change{
|
||||||
Next: nil,
|
Next: nil,
|
||||||
PreviousIds: ch.TreeHeadIds,
|
PreviousIds: ch.TreeHeadIds,
|
||||||
|
AclHeadId: ch.AclHeadId,
|
||||||
|
Timestamp: ch.Timestamp,
|
||||||
|
ReadKeyHash: ch.CurrentReadKeyHash,
|
||||||
Id: id,
|
Id: id,
|
||||||
Content: ch,
|
Data: ch.ChangesData,
|
||||||
SnapshotId: ch.SnapshotBaseId,
|
SnapshotId: ch.SnapshotBaseId,
|
||||||
IsSnapshot: ch.IsSnapshot,
|
IsSnapshot: ch.IsSnapshot,
|
||||||
Identity: string(ch.Identity),
|
Identity: string(ch.Identity),
|
||||||
Sign: signature,
|
Signature: signature,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ch *Change) DecryptedChangeContent() []byte {
|
func NewChangeFromRoot(id string, ch *treechangeproto.RootChange, signature []byte) *Change {
|
||||||
return ch.DecryptedChange
|
return &Change{
|
||||||
|
Next: nil,
|
||||||
|
AclHeadId: ch.AclHeadId,
|
||||||
|
Id: id,
|
||||||
|
IsSnapshot: true,
|
||||||
|
Identity: string(ch.Identity),
|
||||||
|
Signature: signature,
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ch *Change) Signature() []byte {
|
|
||||||
return ch.Sign
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ch *Change) CID() string {
|
func (ch *Change) CID() string {
|
||||||
|
|||||||
@ -2,8 +2,8 @@ package tree
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb"
|
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/common"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/common"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treechangeproto"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/cid"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/cid"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/asymmetric/signingkey"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/asymmetric/signingkey"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/symmetric"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/symmetric"
|
||||||
@ -14,32 +14,44 @@ import (
|
|||||||
var ErrEmptyChange = errors.New("change payload should not be empty")
|
var ErrEmptyChange = errors.New("change payload should not be empty")
|
||||||
|
|
||||||
type BuilderContent struct {
|
type BuilderContent struct {
|
||||||
treeHeadIds []string
|
TreeHeadIds []string
|
||||||
aclHeadId string
|
AclHeadId string
|
||||||
snapshotBaseId string
|
SnapshotBaseId string
|
||||||
currentReadKeyHash uint64
|
CurrentReadKeyHash uint64
|
||||||
identity []byte
|
Identity []byte
|
||||||
isSnapshot bool
|
IsSnapshot bool
|
||||||
signingKey signingkey.PrivKey
|
SigningKey signingkey.PrivKey
|
||||||
readKey *symmetric.Key
|
ReadKey *symmetric.Key
|
||||||
content []byte
|
Content []byte
|
||||||
|
}
|
||||||
|
|
||||||
|
type InitialContent struct {
|
||||||
|
AclHeadId string
|
||||||
|
Identity []byte
|
||||||
|
SigningKey signingkey.PrivKey
|
||||||
|
SpaceId string
|
||||||
|
Seed []byte
|
||||||
|
ChangeType string
|
||||||
}
|
}
|
||||||
|
|
||||||
type ChangeBuilder interface {
|
type ChangeBuilder interface {
|
||||||
ConvertFromRaw(rawIdChange *aclpb.RawTreeChangeWithId, verify bool) (ch *Change, err error)
|
ConvertFromRaw(rawIdChange *treechangeproto.RawTreeChangeWithId, verify bool) (ch *Change, err error)
|
||||||
BuildContent(payload BuilderContent) (ch *Change, raw *aclpb.RawTreeChangeWithId, err error)
|
BuildContent(payload BuilderContent) (ch *Change, raw *treechangeproto.RawTreeChangeWithId, err error)
|
||||||
BuildRaw(ch *Change) (*aclpb.RawTreeChangeWithId, error)
|
BuildInitialContent(payload InitialContent) (ch *Change, raw *treechangeproto.RawTreeChangeWithId, err error)
|
||||||
|
BuildRaw(ch *Change) (*treechangeproto.RawTreeChangeWithId, error)
|
||||||
|
SetRootRawChange(rawIdChange *treechangeproto.RawTreeChangeWithId)
|
||||||
}
|
}
|
||||||
|
|
||||||
type changeBuilder struct {
|
type changeBuilder struct {
|
||||||
|
rootChange *treechangeproto.RawTreeChangeWithId
|
||||||
keys *common.Keychain
|
keys *common.Keychain
|
||||||
}
|
}
|
||||||
|
|
||||||
func newChangeBuilder(keys *common.Keychain) ChangeBuilder {
|
func newChangeBuilder(keys *common.Keychain, rootChange *treechangeproto.RawTreeChangeWithId) ChangeBuilder {
|
||||||
return &changeBuilder{keys: keys}
|
return &changeBuilder{keys: keys, rootChange: rootChange}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *changeBuilder) ConvertFromRaw(rawIdChange *aclpb.RawTreeChangeWithId, verify bool) (ch *Change, err error) {
|
func (c *changeBuilder) ConvertFromRaw(rawIdChange *treechangeproto.RawTreeChangeWithId, verify bool) (ch *Change, err error) {
|
||||||
if rawIdChange.GetRawChange() == nil {
|
if rawIdChange.GetRawChange() == nil {
|
||||||
err = ErrEmptyChange
|
err = ErrEmptyChange
|
||||||
return
|
return
|
||||||
@ -53,7 +65,7 @@ func (c *changeBuilder) ConvertFromRaw(rawIdChange *aclpb.RawTreeChangeWithId, v
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
raw := &aclpb.RawTreeChange{} // TODO: sync pool
|
raw := &treechangeproto.RawTreeChange{} // TODO: sync pool
|
||||||
err = proto.Unmarshal(rawIdChange.GetRawChange(), raw)
|
err = proto.Unmarshal(rawIdChange.GetRawChange(), raw)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@ -78,28 +90,69 @@ func (c *changeBuilder) ConvertFromRaw(rawIdChange *aclpb.RawTreeChangeWithId, v
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unmarshalled := &aclpb.TreeChange{}
|
return c.unmarshallRawChange(raw, rawIdChange.Id)
|
||||||
err = proto.Unmarshal(raw.Payload, unmarshalled)
|
}
|
||||||
|
|
||||||
|
func (c *changeBuilder) SetRootRawChange(rawIdChange *treechangeproto.RawTreeChangeWithId) {
|
||||||
|
c.rootChange = rawIdChange
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *changeBuilder) BuildInitialContent(payload InitialContent) (ch *Change, rawIdChange *treechangeproto.RawTreeChangeWithId, err error) {
|
||||||
|
change := &treechangeproto.RootChange{
|
||||||
|
AclHeadId: payload.AclHeadId,
|
||||||
|
Timestamp: int64(time.Now().Nanosecond()),
|
||||||
|
Identity: payload.Identity,
|
||||||
|
ChangeType: payload.ChangeType,
|
||||||
|
SpaceId: payload.SpaceId,
|
||||||
|
Seed: payload.Seed,
|
||||||
|
}
|
||||||
|
|
||||||
|
marshalledChange, err := proto.Marshal(change)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ch = NewChange(rawIdChange.Id, unmarshalled, raw.Signature)
|
signature, err := payload.SigningKey.Sign(marshalledChange)
|
||||||
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *changeBuilder) BuildContent(payload BuilderContent) (ch *Change, rawIdChange *aclpb.RawTreeChangeWithId, err error) {
|
raw := &treechangeproto.RawTreeChange{
|
||||||
change := &aclpb.TreeChange{
|
Payload: marshalledChange,
|
||||||
TreeHeadIds: payload.treeHeadIds,
|
Signature: signature,
|
||||||
AclHeadId: payload.aclHeadId,
|
|
||||||
SnapshotBaseId: payload.snapshotBaseId,
|
|
||||||
CurrentReadKeyHash: payload.currentReadKeyHash,
|
|
||||||
Timestamp: int64(time.Now().Nanosecond()),
|
|
||||||
Identity: payload.identity,
|
|
||||||
IsSnapshot: payload.isSnapshot,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
encrypted, err := payload.readKey.Encrypt(payload.content)
|
marshalledRawChange, err := proto.Marshal(raw)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
id, err := cid.NewCIDFromBytes(marshalledRawChange)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ch = NewChangeFromRoot(id, change, signature)
|
||||||
|
|
||||||
|
rawIdChange = &treechangeproto.RawTreeChangeWithId{
|
||||||
|
RawChange: marshalledRawChange,
|
||||||
|
Id: id,
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *changeBuilder) BuildContent(payload BuilderContent) (ch *Change, rawIdChange *treechangeproto.RawTreeChangeWithId, err error) {
|
||||||
|
change := &treechangeproto.TreeChange{
|
||||||
|
TreeHeadIds: payload.TreeHeadIds,
|
||||||
|
AclHeadId: payload.AclHeadId,
|
||||||
|
SnapshotBaseId: payload.SnapshotBaseId,
|
||||||
|
CurrentReadKeyHash: payload.CurrentReadKeyHash,
|
||||||
|
Timestamp: int64(time.Now().Nanosecond()),
|
||||||
|
Identity: payload.Identity,
|
||||||
|
IsSnapshot: payload.IsSnapshot,
|
||||||
|
}
|
||||||
|
|
||||||
|
encrypted, err := payload.ReadKey.Encrypt(payload.Content)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -110,12 +163,12 @@ func (c *changeBuilder) BuildContent(payload BuilderContent) (ch *Change, rawIdC
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
signature, err := payload.signingKey.Sign(marshalledChange)
|
signature, err := payload.SigningKey.Sign(marshalledChange)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
raw := &aclpb.RawTreeChange{
|
raw := &treechangeproto.RawTreeChange{
|
||||||
Payload: marshalledChange,
|
Payload: marshalledChange,
|
||||||
Signature: signature,
|
Signature: signature,
|
||||||
}
|
}
|
||||||
@ -131,33 +184,67 @@ func (c *changeBuilder) BuildContent(payload BuilderContent) (ch *Change, rawIdC
|
|||||||
}
|
}
|
||||||
|
|
||||||
ch = NewChange(id, change, signature)
|
ch = NewChange(id, change, signature)
|
||||||
ch.ParsedModel = payload.content
|
ch.Model = payload.Content
|
||||||
|
|
||||||
rawIdChange = &aclpb.RawTreeChangeWithId{
|
rawIdChange = &treechangeproto.RawTreeChangeWithId{
|
||||||
RawChange: marshalledRawChange,
|
RawChange: marshalledRawChange,
|
||||||
Id: id,
|
Id: id,
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *changeBuilder) BuildRaw(ch *Change) (raw *aclpb.RawTreeChangeWithId, err error) {
|
func (c *changeBuilder) BuildRaw(ch *Change) (raw *treechangeproto.RawTreeChangeWithId, err error) {
|
||||||
|
if ch.Id == c.rootChange.Id {
|
||||||
|
return c.rootChange, nil
|
||||||
|
}
|
||||||
|
treeChange := &treechangeproto.TreeChange{
|
||||||
|
TreeHeadIds: ch.PreviousIds,
|
||||||
|
AclHeadId: ch.AclHeadId,
|
||||||
|
SnapshotBaseId: ch.SnapshotId,
|
||||||
|
ChangesData: ch.Data,
|
||||||
|
CurrentReadKeyHash: ch.ReadKeyHash,
|
||||||
|
Timestamp: ch.Timestamp,
|
||||||
|
Identity: []byte(ch.Identity),
|
||||||
|
IsSnapshot: ch.IsSnapshot,
|
||||||
|
}
|
||||||
var marshalled []byte
|
var marshalled []byte
|
||||||
marshalled, err = ch.Content.Marshal()
|
marshalled, err = treeChange.Marshal()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
marshalledRawChange, err := proto.Marshal(&aclpb.RawTreeChange{
|
marshalledRawChange, err := proto.Marshal(&treechangeproto.RawTreeChange{
|
||||||
Payload: marshalled,
|
Payload: marshalled,
|
||||||
Signature: ch.Sign,
|
Signature: ch.Signature,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
raw = &aclpb.RawTreeChangeWithId{
|
raw = &treechangeproto.RawTreeChangeWithId{
|
||||||
RawChange: marshalledRawChange,
|
RawChange: marshalledRawChange,
|
||||||
Id: ch.Id,
|
Id: ch.Id,
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *changeBuilder) unmarshallRawChange(raw *treechangeproto.RawTreeChange, id string) (ch *Change, err error) {
|
||||||
|
if c.rootChange.Id == id {
|
||||||
|
unmarshalled := &treechangeproto.RootChange{}
|
||||||
|
err = proto.Unmarshal(raw.Payload, unmarshalled)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ch = NewChangeFromRoot(id, unmarshalled, raw.Signature)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
unmarshalled := &treechangeproto.TreeChange{}
|
||||||
|
err = proto.Unmarshal(raw.Payload, unmarshalled)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ch = NewChange(id, unmarshalled, raw.Signature)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|||||||
@ -2,7 +2,7 @@ package tree
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclrecordproto"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/list"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/list"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -43,12 +43,12 @@ func (v *objectTreeValidator) validateChange(tree *Tree, aclList list.ACLList, c
|
|||||||
state = aclList.ACLState()
|
state = aclList.ACLState()
|
||||||
)
|
)
|
||||||
// checking if the user could write
|
// checking if the user could write
|
||||||
perm, err = state.PermissionsAtRecord(c.Content.AclHeadId, c.Identity)
|
perm, err = state.PermissionsAtRecord(c.AclHeadId, c.Identity)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if perm.Permission != aclpb.ACLUserPermissions_Writer && perm.Permission != aclpb.ACLUserPermissions_Admin {
|
if perm.Permission != aclrecordproto.ACLUserPermissions_Writer && perm.Permission != aclrecordproto.ACLUserPermissions_Admin {
|
||||||
err = list.ErrInsufficientPermissions
|
err = list.ErrInsufficientPermissions
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -56,16 +56,16 @@ func (v *objectTreeValidator) validateChange(tree *Tree, aclList list.ACLList, c
|
|||||||
// checking if the change refers to later acl heads than its previous ids
|
// checking if the change refers to later acl heads than its previous ids
|
||||||
for _, id := range c.PreviousIds {
|
for _, id := range c.PreviousIds {
|
||||||
prevChange := tree.attached[id]
|
prevChange := tree.attached[id]
|
||||||
if prevChange.Content.AclHeadId == c.Content.AclHeadId {
|
if prevChange.AclHeadId == c.AclHeadId {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
var after bool
|
var after bool
|
||||||
after, err = aclList.IsAfter(c.Content.AclHeadId, prevChange.Content.AclHeadId)
|
after, err = aclList.IsAfter(c.AclHeadId, prevChange.AclHeadId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !after {
|
if !after {
|
||||||
err = fmt.Errorf("current acl head id (%s) should be after each of the previous ones (%s)", c.Content.AclHeadId, prevChange.Content.AclHeadId)
|
err = fmt.Errorf("current acl head id (%s) should be after each of the previous ones (%s)", c.AclHeadId, prevChange.AclHeadId)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,10 +3,10 @@ package tree
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb"
|
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/common"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/common"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/list"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/list"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/storage"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/storage"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treechangeproto"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/symmetric"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/symmetric"
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
@ -27,7 +27,7 @@ type AddResultSummary int
|
|||||||
type AddResult struct {
|
type AddResult struct {
|
||||||
OldHeads []string
|
OldHeads []string
|
||||||
Heads []string
|
Heads []string
|
||||||
Added []*aclpb.RawTreeChangeWithId
|
Added []*treechangeproto.RawTreeChangeWithId
|
||||||
|
|
||||||
Mode Mode
|
Mode Mode
|
||||||
}
|
}
|
||||||
@ -39,7 +39,7 @@ type ObjectTree interface {
|
|||||||
RWLocker
|
RWLocker
|
||||||
|
|
||||||
ID() string
|
ID() string
|
||||||
Header() *aclpb.TreeHeader
|
Header() *treechangeproto.RootChange
|
||||||
Heads() []string
|
Heads() []string
|
||||||
Root() *Change
|
Root() *Change
|
||||||
HasChange(string) bool
|
HasChange(string) bool
|
||||||
@ -49,12 +49,12 @@ type ObjectTree interface {
|
|||||||
IterateFrom(id string, convert ChangeConvertFunc, iterate ChangeIterateFunc) error
|
IterateFrom(id string, convert ChangeConvertFunc, iterate ChangeIterateFunc) error
|
||||||
|
|
||||||
SnapshotPath() []string
|
SnapshotPath() []string
|
||||||
ChangesAfterCommonSnapshot(snapshotPath, heads []string) ([]*aclpb.RawTreeChangeWithId, error)
|
ChangesAfterCommonSnapshot(snapshotPath, heads []string) ([]*treechangeproto.RawTreeChangeWithId, error)
|
||||||
|
|
||||||
Storage() storage.TreeStorage
|
Storage() storage.TreeStorage
|
||||||
|
|
||||||
AddContent(ctx context.Context, content SignableChangeContent) (AddResult, error)
|
AddContent(ctx context.Context, content SignableChangeContent) (AddResult, error)
|
||||||
AddRawChanges(ctx context.Context, changes ...*aclpb.RawTreeChangeWithId) (AddResult, error)
|
AddRawChanges(ctx context.Context, changes ...*treechangeproto.RawTreeChangeWithId) (AddResult, error)
|
||||||
|
|
||||||
Close() error
|
Close() error
|
||||||
}
|
}
|
||||||
@ -68,13 +68,13 @@ type objectTree struct {
|
|||||||
aclList list.ACLList
|
aclList list.ACLList
|
||||||
|
|
||||||
id string
|
id string
|
||||||
header *aclpb.TreeHeader
|
root *treechangeproto.RootChange
|
||||||
tree *Tree
|
tree *Tree
|
||||||
|
|
||||||
keys map[uint64]*symmetric.Key
|
keys map[uint64]*symmetric.Key
|
||||||
|
|
||||||
// buffers
|
// buffers
|
||||||
difSnapshotBuf []*aclpb.RawTreeChangeWithId
|
difSnapshotBuf []*treechangeproto.RawTreeChangeWithId
|
||||||
tmpChangesBuf []*Change
|
tmpChangesBuf []*Change
|
||||||
newSnapshotsBuf []*Change
|
newSnapshotsBuf []*Change
|
||||||
notSeenIdxBuf []int
|
notSeenIdxBuf []int
|
||||||
@ -94,11 +94,12 @@ type objectTreeDeps struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func defaultObjectTreeDeps(
|
func defaultObjectTreeDeps(
|
||||||
|
rootChange *treechangeproto.RawTreeChangeWithId,
|
||||||
treeStorage storage.TreeStorage,
|
treeStorage storage.TreeStorage,
|
||||||
aclList list.ACLList) objectTreeDeps {
|
aclList list.ACLList) objectTreeDeps {
|
||||||
|
|
||||||
keychain := common.NewKeychain()
|
keychain := common.NewKeychain()
|
||||||
changeBuilder := newChangeBuilder(keychain)
|
changeBuilder := newChangeBuilder(keychain, rootChange)
|
||||||
treeBuilder := newTreeBuilder(treeStorage, changeBuilder)
|
treeBuilder := newTreeBuilder(treeStorage, changeBuilder)
|
||||||
return objectTreeDeps{
|
return objectTreeDeps{
|
||||||
changeBuilder: changeBuilder,
|
changeBuilder: changeBuilder,
|
||||||
@ -131,8 +132,8 @@ func (ot *objectTree) ID() string {
|
|||||||
return ot.id
|
return ot.id
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ot *objectTree) Header() *aclpb.TreeHeader {
|
func (ot *objectTree) Header() *treechangeproto.RootChange {
|
||||||
return ot.header
|
return ot.root
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ot *objectTree) Storage() storage.TreeStorage {
|
func (ot *objectTree) Storage() storage.TreeStorage {
|
||||||
@ -172,7 +173,7 @@ func (ot *objectTree) AddContent(ctx context.Context, content SignableChangeCont
|
|||||||
res = AddResult{
|
res = AddResult{
|
||||||
OldHeads: oldHeads,
|
OldHeads: oldHeads,
|
||||||
Heads: []string{objChange.Id},
|
Heads: []string{objChange.Id},
|
||||||
Added: []*aclpb.RawTreeChangeWithId{rawChange},
|
Added: []*treechangeproto.RawTreeChangeWithId{rawChange},
|
||||||
Mode: Append,
|
Mode: Append,
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
@ -188,20 +189,20 @@ func (ot *objectTree) prepareBuilderContent(content SignableChangeContent) (cnt
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
cnt = BuilderContent{
|
cnt = BuilderContent{
|
||||||
treeHeadIds: ot.tree.Heads(),
|
TreeHeadIds: ot.tree.Heads(),
|
||||||
aclHeadId: ot.aclList.Head().Id,
|
AclHeadId: ot.aclList.Head().Id,
|
||||||
snapshotBaseId: ot.tree.RootId(),
|
SnapshotBaseId: ot.tree.RootId(),
|
||||||
currentReadKeyHash: state.CurrentReadKeyHash(),
|
CurrentReadKeyHash: state.CurrentReadKeyHash(),
|
||||||
identity: content.Identity,
|
Identity: content.Identity,
|
||||||
isSnapshot: content.IsSnapshot,
|
IsSnapshot: content.IsSnapshot,
|
||||||
signingKey: content.Key,
|
SigningKey: content.Key,
|
||||||
readKey: readKey,
|
ReadKey: readKey,
|
||||||
content: content.Data,
|
Content: content.Data,
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ot *objectTree) AddRawChanges(ctx context.Context, rawChanges ...*aclpb.RawTreeChangeWithId) (addResult AddResult, err error) {
|
func (ot *objectTree) AddRawChanges(ctx context.Context, rawChanges ...*treechangeproto.RawTreeChangeWithId) (addResult AddResult, err error) {
|
||||||
addResult, err = ot.addRawChanges(ctx, rawChanges...)
|
addResult, err = ot.addRawChanges(ctx, rawChanges...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@ -223,7 +224,7 @@ func (ot *objectTree) AddRawChanges(ctx context.Context, rawChanges ...*aclpb.Ra
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ot *objectTree) addRawChanges(ctx context.Context, rawChanges ...*aclpb.RawTreeChangeWithId) (addResult AddResult, err error) {
|
func (ot *objectTree) addRawChanges(ctx context.Context, rawChanges ...*treechangeproto.RawTreeChangeWithId) (addResult AddResult, err error) {
|
||||||
// resetting buffers
|
// resetting buffers
|
||||||
ot.tmpChangesBuf = ot.tmpChangesBuf[:0]
|
ot.tmpChangesBuf = ot.tmpChangesBuf[:0]
|
||||||
ot.notSeenIdxBuf = ot.notSeenIdxBuf[:0]
|
ot.notSeenIdxBuf = ot.notSeenIdxBuf[:0]
|
||||||
@ -275,7 +276,7 @@ func (ot *objectTree) addRawChanges(ctx context.Context, rawChanges ...*aclpb.Ra
|
|||||||
// returns changes that we added to the tree as attached this round
|
// returns changes that we added to the tree as attached this round
|
||||||
// they can include not only the changes that were added now,
|
// they can include not only the changes that were added now,
|
||||||
// but also the changes that were previously in the tree
|
// but also the changes that were previously in the tree
|
||||||
getAddedChanges := func(toConvert []*Change) (added []*aclpb.RawTreeChangeWithId, err error) {
|
getAddedChanges := func(toConvert []*Change) (added []*treechangeproto.RawTreeChangeWithId, err error) {
|
||||||
alreadyConverted := make(map[*Change]struct{})
|
alreadyConverted := make(map[*Change]struct{})
|
||||||
|
|
||||||
// first we see if we have already unmarshalled those changes
|
// first we see if we have already unmarshalled those changes
|
||||||
@ -300,7 +301,7 @@ func (ot *objectTree) addRawChanges(ctx context.Context, rawChanges ...*aclpb.Ra
|
|||||||
for _, ch := range toConvert {
|
for _, ch := range toConvert {
|
||||||
// if we got some changes that we need to convert to raw
|
// if we got some changes that we need to convert to raw
|
||||||
if _, exists := alreadyConverted[ch]; !exists {
|
if _, exists := alreadyConverted[ch]; !exists {
|
||||||
var raw *aclpb.RawTreeChangeWithId
|
var raw *treechangeproto.RawTreeChangeWithId
|
||||||
raw, err = ot.changeBuilder.BuildRaw(ch)
|
raw, err = ot.changeBuilder.BuildRaw(ch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@ -342,7 +343,7 @@ func (ot *objectTree) addRawChanges(ctx context.Context, rawChanges ...*aclpb.Ra
|
|||||||
ot.rebuildFromStorage(nil)
|
ot.rebuildFromStorage(nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var added []*aclpb.RawTreeChangeWithId
|
var added []*treechangeproto.RawTreeChangeWithId
|
||||||
added, err = getAddedChanges(nil)
|
added, err = getAddedChanges(nil)
|
||||||
// we shouldn't get any error in this case
|
// we shouldn't get any error in this case
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -378,7 +379,7 @@ func (ot *objectTree) addRawChanges(ctx context.Context, rawChanges ...*aclpb.Ra
|
|||||||
err = ErrHasInvalidChanges
|
err = ErrHasInvalidChanges
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var added []*aclpb.RawTreeChangeWithId
|
var added []*treechangeproto.RawTreeChangeWithId
|
||||||
added, err = getAddedChanges(treeChangesAdded)
|
added, err = getAddedChanges(treeChangesAdded)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// that means that some unattached changes were somehow corrupted in memory
|
// that means that some unattached changes were somehow corrupted in memory
|
||||||
@ -409,17 +410,21 @@ func (ot *objectTree) IterateFrom(id string, convert ChangeConvertFunc, iterate
|
|||||||
|
|
||||||
ot.tree.Iterate(ot.tree.RootId(), func(c *Change) (isContinue bool) {
|
ot.tree.Iterate(ot.tree.RootId(), func(c *Change) (isContinue bool) {
|
||||||
var model any
|
var model any
|
||||||
if c.ParsedModel != nil {
|
if c.Model != nil {
|
||||||
return iterate(c)
|
return iterate(c)
|
||||||
}
|
}
|
||||||
readKey, exists := ot.keys[c.Content.CurrentReadKeyHash]
|
// if this is a root change
|
||||||
|
if c.Id == ot.id {
|
||||||
|
return iterate(c)
|
||||||
|
}
|
||||||
|
readKey, exists := ot.keys[c.ReadKeyHash]
|
||||||
if !exists {
|
if !exists {
|
||||||
err = list.ErrNoReadKey
|
err = list.ErrNoReadKey
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
var decrypted []byte
|
var decrypted []byte
|
||||||
decrypted, err = readKey.Decrypt(c.Content.GetChangesData())
|
decrypted, err = readKey.Decrypt(c.Data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -429,7 +434,7 @@ func (ot *objectTree) IterateFrom(id string, convert ChangeConvertFunc, iterate
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
c.ParsedModel = model
|
c.Model = model
|
||||||
return iterate(c)
|
return iterate(c)
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
@ -474,7 +479,7 @@ func (ot *objectTree) SnapshotPath() []string {
|
|||||||
return path
|
return path
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ot *objectTree) ChangesAfterCommonSnapshot(theirPath, theirHeads []string) ([]*aclpb.RawTreeChangeWithId, error) {
|
func (ot *objectTree) ChangesAfterCommonSnapshot(theirPath, theirHeads []string) ([]*treechangeproto.RawTreeChangeWithId, error) {
|
||||||
var (
|
var (
|
||||||
needFullDocument = len(theirPath) == 0
|
needFullDocument = len(theirPath) == 0
|
||||||
ourPath = ot.SnapshotPath()
|
ourPath = ot.SnapshotPath()
|
||||||
@ -498,11 +503,11 @@ func (ot *objectTree) ChangesAfterCommonSnapshot(theirPath, theirHeads []string)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ot *objectTree) getChangesFromTree(theirHeads []string) (rawChanges []*aclpb.RawTreeChangeWithId, err error) {
|
func (ot *objectTree) getChangesFromTree(theirHeads []string) (rawChanges []*treechangeproto.RawTreeChangeWithId, err error) {
|
||||||
return ot.rawChangeLoader.LoadFromTree(ot.tree, theirHeads)
|
return ot.rawChangeLoader.LoadFromTree(ot.tree, theirHeads)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ot *objectTree) getChangesFromDB(commonSnapshot string, theirHeads []string) (rawChanges []*aclpb.RawTreeChangeWithId, err error) {
|
func (ot *objectTree) getChangesFromDB(commonSnapshot string, theirHeads []string) (rawChanges []*treechangeproto.RawTreeChangeWithId, err error) {
|
||||||
return ot.rawChangeLoader.LoadFromStorage(commonSnapshot, ot.tree.headIds, theirHeads)
|
return ot.rawChangeLoader.LoadFromStorage(commonSnapshot, ot.tree.headIds, theirHeads)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2,10 +2,12 @@ package tree
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb"
|
"crypto/rand"
|
||||||
|
"encoding/hex"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/list"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/list"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/storage"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/storage"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/testutils/acllistbuilder"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/testutils/acllistbuilder"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treechangeproto"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/asymmetric/signingkey"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/asymmetric/signingkey"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
@ -14,8 +16,26 @@ import (
|
|||||||
|
|
||||||
type mockChangeCreator struct{}
|
type mockChangeCreator struct{}
|
||||||
|
|
||||||
func (c *mockChangeCreator) createRaw(id, aclId, snapshotId string, isSnapshot bool, prevIds ...string) *aclpb.RawTreeChangeWithId {
|
func (c *mockChangeCreator) createRoot(id, aclId string) *treechangeproto.RawTreeChangeWithId {
|
||||||
aclChange := &aclpb.TreeChange{
|
aclChange := &treechangeproto.RootChange{
|
||||||
|
AclHeadId: aclId,
|
||||||
|
}
|
||||||
|
res, _ := aclChange.Marshal()
|
||||||
|
|
||||||
|
raw := &treechangeproto.RawTreeChange{
|
||||||
|
Payload: res,
|
||||||
|
Signature: nil,
|
||||||
|
}
|
||||||
|
rawMarshalled, _ := raw.Marshal()
|
||||||
|
|
||||||
|
return &treechangeproto.RawTreeChangeWithId{
|
||||||
|
RawChange: rawMarshalled,
|
||||||
|
Id: id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *mockChangeCreator) createRaw(id, aclId, snapshotId string, isSnapshot bool, prevIds ...string) *treechangeproto.RawTreeChangeWithId {
|
||||||
|
aclChange := &treechangeproto.TreeChange{
|
||||||
TreeHeadIds: prevIds,
|
TreeHeadIds: prevIds,
|
||||||
AclHeadId: aclId,
|
AclHeadId: aclId,
|
||||||
SnapshotBaseId: snapshotId,
|
SnapshotBaseId: snapshotId,
|
||||||
@ -24,26 +44,21 @@ func (c *mockChangeCreator) createRaw(id, aclId, snapshotId string, isSnapshot b
|
|||||||
}
|
}
|
||||||
res, _ := aclChange.Marshal()
|
res, _ := aclChange.Marshal()
|
||||||
|
|
||||||
raw := &aclpb.RawTreeChange{
|
raw := &treechangeproto.RawTreeChange{
|
||||||
Payload: res,
|
Payload: res,
|
||||||
Signature: nil,
|
Signature: nil,
|
||||||
}
|
}
|
||||||
rawMarshalled, _ := raw.Marshal()
|
rawMarshalled, _ := raw.Marshal()
|
||||||
|
|
||||||
return &aclpb.RawTreeChangeWithId{
|
return &treechangeproto.RawTreeChangeWithId{
|
||||||
RawChange: rawMarshalled,
|
RawChange: rawMarshalled,
|
||||||
Id: id,
|
Id: id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *mockChangeCreator) createNewTreeStorage(treeId, aclListId, aclHeadId, firstChangeId string) storage.TreeStorage {
|
func (c *mockChangeCreator) createNewTreeStorage(treeId, aclHeadId string) storage.TreeStorage {
|
||||||
firstChange := c.createRaw(firstChangeId, aclHeadId, "", true)
|
root := c.createRoot(treeId, aclHeadId)
|
||||||
header := &aclpb.TreeHeader{
|
treeStorage, _ := storage.NewInMemoryTreeStorage(treeId, root, []string{root.Id}, []*treechangeproto.RawTreeChangeWithId{root})
|
||||||
FirstId: firstChangeId,
|
|
||||||
AclId: aclListId,
|
|
||||||
TreeHeaderType: aclpb.TreeHeaderType_Object,
|
|
||||||
}
|
|
||||||
treeStorage, _ := storage.NewInMemoryTreeStorage(treeId, header, []string{firstChangeId}, []*aclpb.RawTreeChangeWithId{firstChange})
|
|
||||||
return treeStorage
|
return treeStorage
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,15 +66,23 @@ type mockChangeBuilder struct {
|
|||||||
originalBuilder ChangeBuilder
|
originalBuilder ChangeBuilder
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *mockChangeBuilder) ConvertFromRaw(rawChange *aclpb.RawTreeChangeWithId, verify bool) (ch *Change, err error) {
|
func (c *mockChangeBuilder) BuildInitialContent(payload InitialContent) (ch *Change, raw *treechangeproto.RawTreeChangeWithId, err error) {
|
||||||
return c.originalBuilder.ConvertFromRaw(rawChange, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *mockChangeBuilder) BuildContent(payload BuilderContent) (ch *Change, raw *aclpb.RawTreeChangeWithId, err error) {
|
|
||||||
panic("implement me")
|
panic("implement me")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *mockChangeBuilder) BuildRaw(ch *Change) (raw *aclpb.RawTreeChangeWithId, err error) {
|
func (c *mockChangeBuilder) SetRootRawChange(rawIdChange *treechangeproto.RawTreeChangeWithId) {
|
||||||
|
c.originalBuilder.SetRootRawChange(rawIdChange)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *mockChangeBuilder) ConvertFromRaw(rawChange *treechangeproto.RawTreeChangeWithId, verify bool) (ch *Change, err error) {
|
||||||
|
return c.originalBuilder.ConvertFromRaw(rawChange, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *mockChangeBuilder) BuildContent(payload BuilderContent) (ch *Change, raw *treechangeproto.RawTreeChangeWithId, err error) {
|
||||||
|
panic("implement me")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *mockChangeBuilder) BuildRaw(ch *Change) (raw *treechangeproto.RawTreeChangeWithId, err error) {
|
||||||
return c.originalBuilder.BuildRaw(ch)
|
return c.originalBuilder.BuildRaw(ch)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,15 +116,15 @@ func prepareACLList(t *testing.T) list.ACLList {
|
|||||||
|
|
||||||
func prepareTreeContext(t *testing.T, aclList list.ACLList) testTreeContext {
|
func prepareTreeContext(t *testing.T, aclList list.ACLList) testTreeContext {
|
||||||
changeCreator := &mockChangeCreator{}
|
changeCreator := &mockChangeCreator{}
|
||||||
treeStorage := changeCreator.createNewTreeStorage("treeId", aclList.ID(), aclList.Head().Id, "0")
|
treeStorage := changeCreator.createNewTreeStorage("0", aclList.Head().Id)
|
||||||
|
root, _ := treeStorage.Root()
|
||||||
changeBuilder := &mockChangeBuilder{
|
changeBuilder := &mockChangeBuilder{
|
||||||
originalBuilder: newChangeBuilder(nil),
|
originalBuilder: newChangeBuilder(nil, root),
|
||||||
}
|
}
|
||||||
deps := objectTreeDeps{
|
deps := objectTreeDeps{
|
||||||
changeBuilder: changeBuilder,
|
changeBuilder: changeBuilder,
|
||||||
treeBuilder: newTreeBuilder(treeStorage, changeBuilder),
|
treeBuilder: newTreeBuilder(treeStorage, changeBuilder),
|
||||||
treeStorage: treeStorage,
|
treeStorage: treeStorage,
|
||||||
updateListener: nil,
|
|
||||||
rawChangeLoader: newRawChangeLoader(treeStorage, changeBuilder),
|
rawChangeLoader: newRawChangeLoader(treeStorage, changeBuilder),
|
||||||
validator: &mockChangeValidator{},
|
validator: &mockChangeValidator{},
|
||||||
aclList: aclList,
|
aclList: aclList,
|
||||||
@ -128,6 +151,18 @@ func prepareTreeContext(t *testing.T, aclList list.ACLList) testTreeContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSameSignature(t *testing.T) {
|
||||||
|
privKey, _, err := signingkey.GenerateEd25519Key(rand.Reader)
|
||||||
|
require.NoError(t, err)
|
||||||
|
bytes := []byte("asefhiosahjfoiesjgioesajgihs")
|
||||||
|
for i := 0; i < 5; i++ {
|
||||||
|
signed, err := privKey.Sign(bytes)
|
||||||
|
require.NoError(t, err)
|
||||||
|
t.Log(hex.EncodeToString(signed))
|
||||||
|
}
|
||||||
|
// kitten step voyage hand cover funny timber auction differ mushroom update pulp
|
||||||
|
}
|
||||||
|
|
||||||
func TestObjectTree(t *testing.T) {
|
func TestObjectTree(t *testing.T) {
|
||||||
aclList := prepareACLList(t)
|
aclList := prepareACLList(t)
|
||||||
|
|
||||||
@ -137,7 +172,7 @@ func TestObjectTree(t *testing.T) {
|
|||||||
changeCreator := ctx.changeCreator
|
changeCreator := ctx.changeCreator
|
||||||
objTree := ctx.objTree
|
objTree := ctx.objTree
|
||||||
|
|
||||||
rawChanges := []*aclpb.RawTreeChangeWithId{
|
rawChanges := []*treechangeproto.RawTreeChangeWithId{
|
||||||
changeCreator.createRaw("1", aclList.Head().Id, "0", false, "0"),
|
changeCreator.createRaw("1", aclList.Head().Id, "0", false, "0"),
|
||||||
changeCreator.createRaw("2", aclList.Head().Id, "0", false, "1"),
|
changeCreator.createRaw("2", aclList.Head().Id, "0", false, "1"),
|
||||||
}
|
}
|
||||||
@ -178,7 +213,7 @@ func TestObjectTree(t *testing.T) {
|
|||||||
changeCreator := ctx.changeCreator
|
changeCreator := ctx.changeCreator
|
||||||
objTree := ctx.objTree
|
objTree := ctx.objTree
|
||||||
|
|
||||||
rawChanges := []*aclpb.RawTreeChangeWithId{
|
rawChanges := []*treechangeproto.RawTreeChangeWithId{
|
||||||
changeCreator.createRaw("0", aclList.Head().Id, "", true, ""),
|
changeCreator.createRaw("0", aclList.Head().Id, "", true, ""),
|
||||||
}
|
}
|
||||||
res, err := objTree.AddRawChanges(context.Background(), rawChanges...)
|
res, err := objTree.AddRawChanges(context.Background(), rawChanges...)
|
||||||
@ -198,7 +233,7 @@ func TestObjectTree(t *testing.T) {
|
|||||||
changeCreator := ctx.changeCreator
|
changeCreator := ctx.changeCreator
|
||||||
objTree := ctx.objTree
|
objTree := ctx.objTree
|
||||||
|
|
||||||
rawChanges := []*aclpb.RawTreeChangeWithId{
|
rawChanges := []*treechangeproto.RawTreeChangeWithId{
|
||||||
changeCreator.createRaw("2", aclList.Head().Id, "0", false, "1"),
|
changeCreator.createRaw("2", aclList.Head().Id, "0", false, "1"),
|
||||||
}
|
}
|
||||||
res, err := objTree.AddRawChanges(context.Background(), rawChanges...)
|
res, err := objTree.AddRawChanges(context.Background(), rawChanges...)
|
||||||
@ -220,7 +255,7 @@ func TestObjectTree(t *testing.T) {
|
|||||||
changeCreator := ctx.changeCreator
|
changeCreator := ctx.changeCreator
|
||||||
objTree := ctx.objTree
|
objTree := ctx.objTree
|
||||||
|
|
||||||
rawChanges := []*aclpb.RawTreeChangeWithId{
|
rawChanges := []*treechangeproto.RawTreeChangeWithId{
|
||||||
changeCreator.createRaw("1", aclList.Head().Id, "0", false, "0"),
|
changeCreator.createRaw("1", aclList.Head().Id, "0", false, "0"),
|
||||||
changeCreator.createRaw("2", aclList.Head().Id, "0", false, "1"),
|
changeCreator.createRaw("2", aclList.Head().Id, "0", false, "1"),
|
||||||
changeCreator.createRaw("3", aclList.Head().Id, "0", true, "2"),
|
changeCreator.createRaw("3", aclList.Head().Id, "0", true, "2"),
|
||||||
@ -264,7 +299,7 @@ func TestObjectTree(t *testing.T) {
|
|||||||
changeCreator := ctx.changeCreator
|
changeCreator := ctx.changeCreator
|
||||||
objTree := ctx.objTree
|
objTree := ctx.objTree
|
||||||
|
|
||||||
rawChanges := []*aclpb.RawTreeChangeWithId{
|
rawChanges := []*treechangeproto.RawTreeChangeWithId{
|
||||||
changeCreator.createRaw("1", aclList.Head().Id, "0", false, "0"),
|
changeCreator.createRaw("1", aclList.Head().Id, "0", false, "0"),
|
||||||
changeCreator.createRaw("2", aclList.Head().Id, "0", false, "1"),
|
changeCreator.createRaw("2", aclList.Head().Id, "0", false, "1"),
|
||||||
changeCreator.createRaw("3", aclList.Head().Id, "0", true, "2"),
|
changeCreator.createRaw("3", aclList.Head().Id, "0", true, "2"),
|
||||||
@ -283,7 +318,7 @@ func TestObjectTree(t *testing.T) {
|
|||||||
changeCreator := ctx.changeCreator
|
changeCreator := ctx.changeCreator
|
||||||
objTree := ctx.objTree
|
objTree := ctx.objTree
|
||||||
|
|
||||||
rawChanges := []*aclpb.RawTreeChangeWithId{
|
rawChanges := []*treechangeproto.RawTreeChangeWithId{
|
||||||
changeCreator.createRaw("1", aclList.Head().Id, "0", false, "0"),
|
changeCreator.createRaw("1", aclList.Head().Id, "0", false, "0"),
|
||||||
changeCreator.createRaw("2", aclList.Head().Id, "0", false, "1"),
|
changeCreator.createRaw("2", aclList.Head().Id, "0", false, "1"),
|
||||||
changeCreator.createRaw("3", aclList.Head().Id, "0", true, "2"),
|
changeCreator.createRaw("3", aclList.Head().Id, "0", true, "2"),
|
||||||
@ -357,7 +392,7 @@ func TestObjectTree(t *testing.T) {
|
|||||||
changeCreator := ctx.changeCreator
|
changeCreator := ctx.changeCreator
|
||||||
objTree := ctx.objTree
|
objTree := ctx.objTree
|
||||||
|
|
||||||
rawChanges := []*aclpb.RawTreeChangeWithId{
|
rawChanges := []*treechangeproto.RawTreeChangeWithId{
|
||||||
changeCreator.createRaw("1", aclList.Head().Id, "0", false, "0"),
|
changeCreator.createRaw("1", aclList.Head().Id, "0", false, "0"),
|
||||||
changeCreator.createRaw("2", aclList.Head().Id, "0", false, "1"),
|
changeCreator.createRaw("2", aclList.Head().Id, "0", false, "1"),
|
||||||
changeCreator.createRaw("3", aclList.Head().Id, "0", true, "2"),
|
changeCreator.createRaw("3", aclList.Head().Id, "0", true, "2"),
|
||||||
@ -433,7 +468,7 @@ func TestObjectTree(t *testing.T) {
|
|||||||
changeCreator := ctx.changeCreator
|
changeCreator := ctx.changeCreator
|
||||||
objTree := ctx.objTree
|
objTree := ctx.objTree
|
||||||
|
|
||||||
rawChanges := []*aclpb.RawTreeChangeWithId{
|
rawChanges := []*treechangeproto.RawTreeChangeWithId{
|
||||||
changeCreator.createRaw("1", aclList.Head().Id, "0", false, "0"),
|
changeCreator.createRaw("1", aclList.Head().Id, "0", false, "0"),
|
||||||
changeCreator.createRaw("2", aclList.Head().Id, "0", false, "1"),
|
changeCreator.createRaw("2", aclList.Head().Id, "0", false, "1"),
|
||||||
changeCreator.createRaw("3", aclList.Head().Id, "0", true, "2"),
|
changeCreator.createRaw("3", aclList.Head().Id, "0", true, "2"),
|
||||||
@ -442,7 +477,7 @@ func TestObjectTree(t *testing.T) {
|
|||||||
require.NoError(t, err, "adding changes should be without error")
|
require.NoError(t, err, "adding changes should be without error")
|
||||||
require.Equal(t, "3", objTree.Root().Id)
|
require.Equal(t, "3", objTree.Root().Id)
|
||||||
|
|
||||||
rawChanges = []*aclpb.RawTreeChangeWithId{
|
rawChanges = []*treechangeproto.RawTreeChangeWithId{
|
||||||
changeCreator.createRaw("4", aclList.Head().Id, "0", false, "2"),
|
changeCreator.createRaw("4", aclList.Head().Id, "0", false, "2"),
|
||||||
changeCreator.createRaw("5", aclList.Head().Id, "0", false, "1"),
|
changeCreator.createRaw("5", aclList.Head().Id, "0", false, "1"),
|
||||||
changeCreator.createRaw("6", aclList.Head().Id, "0", false, "3", "4", "5"),
|
changeCreator.createRaw("6", aclList.Head().Id, "0", false, "3", "4", "5"),
|
||||||
|
|||||||
@ -1,11 +1,10 @@
|
|||||||
package tree
|
package tree
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/account"
|
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb"
|
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/list"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/list"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/storage"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/storage"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/cid"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treechangeproto"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/asymmetric/signingkey"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/symmetric"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/symmetric"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/slice"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/slice"
|
||||||
"github.com/gogo/protobuf/proto"
|
"github.com/gogo/protobuf/proto"
|
||||||
@ -13,14 +12,19 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type ObjectTreeCreatePayload struct {
|
type ObjectTreeCreatePayload struct {
|
||||||
AccountData *account.AccountData
|
SignKey signingkey.PrivKey
|
||||||
HeaderData []byte
|
ChangeType string
|
||||||
ChangeData []byte
|
Seed []byte
|
||||||
TreeType aclpb.TreeHeaderType
|
SpaceId string
|
||||||
|
Identity []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func BuildObjectTree(treeStorage storage.TreeStorage, aclList list.ACLList) (ObjectTree, error) {
|
func BuildObjectTree(treeStorage storage.TreeStorage, aclList list.ACLList) (ObjectTree, error) {
|
||||||
deps := defaultObjectTreeDeps(treeStorage, aclList)
|
rootChange, err := treeStorage.Root()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
deps := defaultObjectTreeDeps(rootChange, treeStorage, aclList)
|
||||||
return buildObjectTree(deps)
|
return buildObjectTree(deps)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,53 +34,34 @@ func CreateObjectTree(
|
|||||||
createStorage storage.TreeStorageCreatorFunc) (objTree ObjectTree, err error) {
|
createStorage storage.TreeStorageCreatorFunc) (objTree ObjectTree, err error) {
|
||||||
aclList.RLock()
|
aclList.RLock()
|
||||||
var (
|
var (
|
||||||
deps = defaultObjectTreeDeps(nil, aclList)
|
deps = defaultObjectTreeDeps(nil, nil, aclList)
|
||||||
state = aclList.ACLState()
|
|
||||||
aclId = aclList.ID()
|
|
||||||
aclHeadId = aclList.Head().Id
|
aclHeadId = aclList.Head().Id
|
||||||
readKeyHash = state.CurrentReadKeyHash()
|
|
||||||
)
|
)
|
||||||
readKey, err := state.CurrentReadKey()
|
|
||||||
aclList.RUnlock()
|
aclList.RUnlock()
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
cnt := InitialContent{
|
||||||
// create first change
|
AclHeadId: aclHeadId,
|
||||||
cnt := BuilderContent{
|
Identity: payload.Identity,
|
||||||
treeHeadIds: nil,
|
SigningKey: payload.SignKey,
|
||||||
aclHeadId: aclHeadId,
|
SpaceId: payload.SpaceId,
|
||||||
snapshotBaseId: "",
|
Seed: payload.Seed,
|
||||||
currentReadKeyHash: readKeyHash,
|
ChangeType: payload.ChangeType,
|
||||||
isSnapshot: true,
|
|
||||||
readKey: readKey,
|
|
||||||
identity: payload.AccountData.Identity,
|
|
||||||
signingKey: payload.AccountData.SignKey,
|
|
||||||
content: payload.ChangeData,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_, raw, err := deps.changeBuilder.BuildContent(cnt)
|
_, raw, err := deps.changeBuilder.BuildInitialContent(cnt)
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// create header
|
|
||||||
header, id, err := createTreeHeaderAndId(
|
|
||||||
raw,
|
|
||||||
payload.TreeType,
|
|
||||||
aclId,
|
|
||||||
payload.AccountData.Identity,
|
|
||||||
payload.HeaderData)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
deps.changeBuilder.SetRootRawChange(raw)
|
||||||
|
|
||||||
// create storage
|
// create storage
|
||||||
st, err := createStorage(storage.TreeStorageCreatePayload{
|
st, err := createStorage(storage.TreeStorageCreatePayload{
|
||||||
TreeId: id,
|
TreeId: raw.Id,
|
||||||
Header: header,
|
RootRawChange: raw,
|
||||||
Changes: []*aclpb.RawTreeChangeWithId{raw},
|
Changes: []*treechangeproto.RawTreeChangeWithId{raw},
|
||||||
Heads: []string{raw.Id},
|
Heads: []string{raw.Id},
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -98,7 +83,7 @@ func buildObjectTree(deps objectTreeDeps) (ObjectTree, error) {
|
|||||||
tree: nil,
|
tree: nil,
|
||||||
keys: make(map[uint64]*symmetric.Key),
|
keys: make(map[uint64]*symmetric.Key),
|
||||||
tmpChangesBuf: make([]*Change, 0, 10),
|
tmpChangesBuf: make([]*Change, 0, 10),
|
||||||
difSnapshotBuf: make([]*aclpb.RawTreeChangeWithId, 0, 10),
|
difSnapshotBuf: make([]*treechangeproto.RawTreeChangeWithId, 0, 10),
|
||||||
notSeenIdxBuf: make([]int, 0, 10),
|
notSeenIdxBuf: make([]int, 0, 10),
|
||||||
newSnapshotsBuf: make([]*Change, 0, 10),
|
newSnapshotsBuf: make([]*Change, 0, 10),
|
||||||
}
|
}
|
||||||
@ -128,32 +113,23 @@ func buildObjectTree(deps objectTreeDeps) (ObjectTree, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
objTree.header, err = objTree.treeStorage.Header()
|
|
||||||
|
rawRootWithId, err := objTree.treeStorage.Root()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
rawRoot := &treechangeproto.RawTreeChange{}
|
||||||
|
err = proto.Unmarshal(rawRootWithId.RawChange, rawRoot)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
objTree.root = &treechangeproto.RootChange{}
|
||||||
|
err = proto.Unmarshal(rawRoot.Payload, objTree.root)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return objTree, nil
|
return objTree, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func createTreeHeaderAndId(
|
|
||||||
raw *aclpb.RawTreeChangeWithId,
|
|
||||||
treeType aclpb.TreeHeaderType,
|
|
||||||
aclId string,
|
|
||||||
identity []byte,
|
|
||||||
headerData []byte) (header *aclpb.TreeHeader, treeId string, err error) {
|
|
||||||
header = &aclpb.TreeHeader{
|
|
||||||
FirstId: raw.Id,
|
|
||||||
TreeHeaderType: treeType,
|
|
||||||
AclId: aclId,
|
|
||||||
Identity: identity,
|
|
||||||
Data: headerData,
|
|
||||||
}
|
|
||||||
marshalledHeader, err := proto.Marshal(header)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
treeId, err = cid.NewCIDFromBytes(marshalledHeader)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|||||||
@ -2,8 +2,8 @@ package tree
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb"
|
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/storage"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/storage"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treechangeproto"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -18,7 +18,7 @@ type rawChangeLoader struct {
|
|||||||
|
|
||||||
type rawCacheEntry struct {
|
type rawCacheEntry struct {
|
||||||
change *Change
|
change *Change
|
||||||
rawChange *aclpb.RawTreeChangeWithId
|
rawChange *treechangeproto.RawTreeChangeWithId
|
||||||
position int
|
position int
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,15 +29,15 @@ func newRawChangeLoader(treeStorage storage.TreeStorage, changeBuilder ChangeBui
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *rawChangeLoader) LoadFromTree(t *Tree, breakpoints []string) ([]*aclpb.RawTreeChangeWithId, error) {
|
func (r *rawChangeLoader) LoadFromTree(t *Tree, breakpoints []string) ([]*treechangeproto.RawTreeChangeWithId, error) {
|
||||||
var stack []*Change
|
var stack []*Change
|
||||||
for _, h := range t.headIds {
|
for _, h := range t.headIds {
|
||||||
stack = append(stack, t.attached[h])
|
stack = append(stack, t.attached[h])
|
||||||
}
|
}
|
||||||
|
|
||||||
convert := func(chs []*Change) (rawChanges []*aclpb.RawTreeChangeWithId, err error) {
|
convert := func(chs []*Change) (rawChanges []*treechangeproto.RawTreeChangeWithId, err error) {
|
||||||
for _, ch := range chs {
|
for _, ch := range chs {
|
||||||
var raw *aclpb.RawTreeChangeWithId
|
var raw *treechangeproto.RawTreeChangeWithId
|
||||||
raw, err = r.changeBuilder.BuildRaw(ch)
|
raw, err = r.changeBuilder.BuildRaw(ch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@ -95,7 +95,7 @@ func (r *rawChangeLoader) LoadFromTree(t *Tree, breakpoints []string) ([]*aclpb.
|
|||||||
return convert(results)
|
return convert(results)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *rawChangeLoader) LoadFromStorage(commonSnapshot string, heads, breakpoints []string) ([]*aclpb.RawTreeChangeWithId, error) {
|
func (r *rawChangeLoader) LoadFromStorage(commonSnapshot string, heads, breakpoints []string) ([]*treechangeproto.RawTreeChangeWithId, error) {
|
||||||
// resetting cache
|
// resetting cache
|
||||||
r.cache = make(map[string]rawCacheEntry)
|
r.cache = make(map[string]rawCacheEntry)
|
||||||
defer func() {
|
defer func() {
|
||||||
@ -162,7 +162,7 @@ func (r *rawChangeLoader) LoadFromStorage(commonSnapshot string, heads, breakpoi
|
|||||||
|
|
||||||
// preparing first pass
|
// preparing first pass
|
||||||
r.idStack = append(r.idStack, heads...)
|
r.idStack = append(r.idStack, heads...)
|
||||||
var buffer []*aclpb.RawTreeChangeWithId
|
var buffer []*treechangeproto.RawTreeChangeWithId
|
||||||
|
|
||||||
rootVisited := dfs(commonSnapshot, heads, 0,
|
rootVisited := dfs(commonSnapshot, heads, 0,
|
||||||
func(counter int, mapExists bool) bool {
|
func(counter int, mapExists bool) bool {
|
||||||
@ -203,7 +203,7 @@ func (r *rawChangeLoader) LoadFromStorage(commonSnapshot string, heads, breakpoi
|
|||||||
})
|
})
|
||||||
|
|
||||||
// discarding visited
|
// discarding visited
|
||||||
buffer = discardFromSlice(buffer, func(change *aclpb.RawTreeChangeWithId) bool {
|
buffer = discardFromSlice(buffer, func(change *treechangeproto.RawTreeChangeWithId) bool {
|
||||||
return change == nil
|
return change == nil
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@ -90,7 +90,7 @@ func (t *Tree) Graph() (data string, err error) {
|
|||||||
label := fmt.Sprintf("Id: %s\nOrd: %s\nTime: %s\nChanges: %s\n",
|
label := fmt.Sprintf("Id: %s\nOrd: %s\nTime: %s\nChanges: %s\n",
|
||||||
shortId,
|
shortId,
|
||||||
ord,
|
ord,
|
||||||
time.Unix(c.Content.Timestamp, 0).Format("02.01.06 15:04:05"),
|
time.Unix(c.Timestamp, 0).Format("02.01.06 15:04:05"),
|
||||||
strings.Join(chSymbs, ","),
|
strings.Join(chSymbs, ","),
|
||||||
)
|
)
|
||||||
n.SetLabel(label)
|
n.SetLabel(label)
|
||||||
|
|||||||
55
pkg/acl/treechangeproto/protos/treechange.proto
Normal file
55
pkg/acl/treechangeproto/protos/treechange.proto
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
package treechange;
|
||||||
|
option go_package = "pkg/acl/treechangeproto";
|
||||||
|
|
||||||
|
// RootChange is a root of a tree
|
||||||
|
message RootChange {
|
||||||
|
// AclHeadId is a cid of latest acl record at the time of tree creation
|
||||||
|
string aclHeadId = 1;
|
||||||
|
// SpaceId is an id of space where the document is placed
|
||||||
|
string spaceId = 2;
|
||||||
|
// ChangeType is a type of tree which this RootChange is a root of
|
||||||
|
string changeType = 3;
|
||||||
|
// Timestamp is this change creation timestamp
|
||||||
|
int64 timestamp = 4;
|
||||||
|
// Seed is a random bytes to make root change unique
|
||||||
|
bytes seed = 5;
|
||||||
|
// Identity is a public key of the tree's creator
|
||||||
|
bytes identity = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TreeChange is a change of a tree
|
||||||
|
message TreeChange {
|
||||||
|
// TreeHeadIds are previous ids for this TreeChange
|
||||||
|
repeated string treeHeadIds = 1;
|
||||||
|
// AclHeadId is a cid of latest acl record at the time of this change
|
||||||
|
string aclHeadId = 2;
|
||||||
|
// SnapshotBaseId is a snapshot (root) of the tree where this change is added
|
||||||
|
string snapshotBaseId = 3;
|
||||||
|
// ChangesData is an arbitrary payload to be read by the client
|
||||||
|
bytes changesData = 4;
|
||||||
|
// CurrentReadKeyHash is the hash of the read key which is used to encrypt this change
|
||||||
|
uint64 currentReadKeyHash = 5;
|
||||||
|
// Timestamp is this change creation timestamp
|
||||||
|
int64 timestamp = 6;
|
||||||
|
// Identity is a public key with which the raw payload of this change is signed
|
||||||
|
bytes identity = 7;
|
||||||
|
// IsSnapshot indicates whether this change contains a snapshot of state
|
||||||
|
bool isSnapshot = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
// RawTreeChange is a marshalled TreeChange (or RootChange) payload and a signature of this payload
|
||||||
|
message RawTreeChange {
|
||||||
|
// Payload is a byte payload containing TreeChange
|
||||||
|
bytes payload = 1;
|
||||||
|
// Signature is a signature made by identity indicated in the TreeChange payload
|
||||||
|
bytes signature = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// RawTreeChangeWithId is a marshalled RawTreeChange with CID
|
||||||
|
message RawTreeChangeWithId {
|
||||||
|
// RawChange is a byte payload of RawTreeChange
|
||||||
|
bytes rawChange = 1;
|
||||||
|
// Id is a cid made from rawChange payload
|
||||||
|
string id = 2;
|
||||||
|
}
|
||||||
1537
pkg/acl/treechangeproto/treechange.pb.go
Normal file
1537
pkg/acl/treechangeproto/treechange.pb.go
Normal file
File diff suppressed because it is too large
Load Diff
@ -2,14 +2,16 @@ package document
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/app"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/app"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/app/logger"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/app/logger"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/account"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/account"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclrecordproto/aclpb"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/acltree"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/list"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/testutils/testchanges/testchangepb"
|
testchanges "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/testutils/testchanges/proto"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treestorage/treepb"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/tree"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/node"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/node"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/storage"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/sync/message"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/sync/message"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/treecache"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/treecache"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/syncproto"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/syncproto"
|
||||||
@ -25,13 +27,14 @@ type service struct {
|
|||||||
messageService message.Service
|
messageService message.Service
|
||||||
treeCache treecache.Service
|
treeCache treecache.Service
|
||||||
account account.Service
|
account account.Service
|
||||||
|
storage storage.Service
|
||||||
// to create new documents we need to know all nodes
|
// to create new documents we need to know all nodes
|
||||||
nodes []*node.Node
|
nodes []*node.Node
|
||||||
}
|
}
|
||||||
|
|
||||||
type Service interface {
|
type Service interface {
|
||||||
UpdateDocument(ctx context.Context, id, text string) error
|
UpdateDocumentTree(ctx context.Context, id, text string) error
|
||||||
CreateDocument(ctx context.Context, text string) (string, error)
|
CreateDocumentTree(ctx context.Context, aclTreeId string, text string) (id string, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func New() app.Component {
|
func New() app.Component {
|
||||||
@ -42,6 +45,7 @@ func (s *service) Init(a *app.App) (err error) {
|
|||||||
s.account = a.MustComponent(account.CName).(account.Service)
|
s.account = a.MustComponent(account.CName).(account.Service)
|
||||||
s.messageService = a.MustComponent(message.CName).(message.Service)
|
s.messageService = a.MustComponent(message.CName).(message.Service)
|
||||||
s.treeCache = a.MustComponent(treecache.CName).(treecache.Service)
|
s.treeCache = a.MustComponent(treecache.CName).(treecache.Service)
|
||||||
|
s.storage = a.MustComponent(storage.CName).(storage.Service)
|
||||||
|
|
||||||
nodesService := a.MustComponent(node.CName).(node.Service)
|
nodesService := a.MustComponent(node.CName).(node.Service)
|
||||||
s.nodes = nodesService.Nodes()
|
s.nodes = nodesService.Nodes()
|
||||||
@ -54,41 +58,65 @@ func (s *service) Name() (name string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *service) Run(ctx context.Context) (err error) {
|
func (s *service) Run(ctx context.Context) (err error) {
|
||||||
return nil
|
syncData := s.storage.ImportedACLSyncData()
|
||||||
|
|
||||||
|
// we could have added a timeout or some additional logic,
|
||||||
|
// but let's just use the ACL id of the latest started node :-)
|
||||||
|
return s.messageService.SendToSpaceAsync("", syncproto.WrapACLList(
|
||||||
|
&syncproto.SyncACLList{Records: syncData.Records},
|
||||||
|
syncData.Header,
|
||||||
|
syncData.Id,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *service) Close(ctx context.Context) (err error) {
|
func (s *service) Close(ctx context.Context) (err error) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *service) UpdateDocument(ctx context.Context, id, text string) (err error) {
|
func (s *service) UpdateDocumentTree(ctx context.Context, id, text string) (err error) {
|
||||||
var (
|
var (
|
||||||
ch *aclpb.RawChange
|
ch *aclpb.RawChange
|
||||||
header *treepb.TreeHeader
|
header *aclpb.Header
|
||||||
snapshotPath []string
|
snapshotPath []string
|
||||||
heads []string
|
heads []string
|
||||||
)
|
)
|
||||||
log.With(zap.String("id", id), zap.String("text", text)).
|
log.With(zap.String("id", id), zap.String("text", text)).
|
||||||
Debug("updating document")
|
Debug("updating document")
|
||||||
|
|
||||||
err = s.treeCache.Do(ctx, id, func(tree acltree.ACLTree) error {
|
err = s.treeCache.Do(ctx, id, func(obj interface{}) error {
|
||||||
ch, err = tree.AddContent(ctx, func(builder acltree.ChangeBuilder) error {
|
docTree, ok := obj.(tree.ObjectTree)
|
||||||
builder.AddChangeContent(
|
if !ok {
|
||||||
&testchangepb.PlainTextChange_Data{
|
return fmt.Errorf("can't update acl trees with text")
|
||||||
Content: []*testchangepb.PlainTextChange_Content{
|
}
|
||||||
createAppendTextChangeContent(text),
|
|
||||||
},
|
docTree.Lock()
|
||||||
})
|
defer docTree.Unlock()
|
||||||
|
err = s.treeCache.Do(ctx, docTree.Header().AclListId, func(obj interface{}) error {
|
||||||
|
aclTree := obj.(list.ACLList)
|
||||||
|
aclTree.RLock()
|
||||||
|
defer aclTree.RUnlock()
|
||||||
|
|
||||||
|
content := createAppendTextChange(text)
|
||||||
|
signable := tree.SignableChangeContent{
|
||||||
|
Proto: content,
|
||||||
|
Key: s.account.Account().SignKey,
|
||||||
|
Identity: s.account.Account().Identity,
|
||||||
|
IsSnapshot: false,
|
||||||
|
}
|
||||||
|
ch, err = docTree.AddContent(ctx, signable)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
id = tree.ID()
|
id = docTree.ID()
|
||||||
heads = tree.Heads()
|
heads = docTree.Heads()
|
||||||
header = tree.Header()
|
header = docTree.Header()
|
||||||
snapshotPath = tree.SnapshotPath()
|
snapshotPath = docTree.SnapshotPath()
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -100,87 +128,90 @@ func (s *service) UpdateDocument(ctx context.Context, id, text string) (err erro
|
|||||||
zap.String("header", header.String())).
|
zap.String("header", header.String())).
|
||||||
Debug("document updated in the database")
|
Debug("document updated in the database")
|
||||||
|
|
||||||
return s.messageService.SendToSpaceAsync("", syncproto.WrapHeadUpdate(&syncproto.Sync_HeadUpdate{
|
return s.messageService.SendToSpaceAsync("", syncproto.WrapHeadUpdate(&syncproto.SyncHeadUpdate{
|
||||||
Heads: heads,
|
Heads: heads,
|
||||||
Changes: []*aclpb.RawChange{ch},
|
Changes: []*aclpb.RawChange{ch},
|
||||||
TreeId: id,
|
|
||||||
SnapshotPath: snapshotPath,
|
SnapshotPath: snapshotPath,
|
||||||
TreeHeader: header,
|
}, header, id))
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *service) CreateDocument(ctx context.Context, text string) (id string, err error) {
|
func (s *service) CreateDocumentTree(ctx context.Context, aclListId string, text string) (id string, err error) {
|
||||||
acc := s.account.Account()
|
acc := s.account.Account()
|
||||||
var (
|
var (
|
||||||
ch *aclpb.RawChange
|
ch *aclpb.RawChange
|
||||||
header *treepb.TreeHeader
|
header *aclpb.Header
|
||||||
snapshotPath []string
|
snapshotPath []string
|
||||||
heads []string
|
heads []string
|
||||||
)
|
)
|
||||||
|
err = s.treeCache.Do(ctx, aclListId, func(obj interface{}) error {
|
||||||
|
t := obj.(list.ACLList)
|
||||||
|
t.RLock()
|
||||||
|
defer t.RUnlock()
|
||||||
|
|
||||||
err = s.treeCache.Create(ctx, func(builder acltree.ChangeBuilder) error {
|
content := createInitialTextChange(text)
|
||||||
err := builder.UserAdd(acc.Identity, acc.EncKey.GetPublic(), aclpb.ACLChange_Admin)
|
doc, err := tree.CreateNewTreeStorage(acc, t, content, s.storage.CreateTreeStorage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// adding all predefined nodes to the document as admins
|
|
||||||
for _, n := range s.nodes {
|
|
||||||
err = builder.UserAdd(n.SigningKeyString, n.EncryptionKey, aclpb.ACLChange_Admin)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.AddChangeContent(createInitialChangeContent(text))
|
id, err = doc.ID()
|
||||||
return nil
|
|
||||||
}, func(tree acltree.ACLTree) error {
|
|
||||||
id = tree.ID()
|
|
||||||
heads = tree.Heads()
|
|
||||||
header = tree.Header()
|
|
||||||
snapshotPath = tree.SnapshotPath()
|
|
||||||
ch, err = tree.Storage().GetChange(ctx, heads[0])
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
log.With(
|
|
||||||
zap.String("id", id),
|
header, err = doc.Header()
|
||||||
zap.Strings("heads", heads),
|
if err != nil {
|
||||||
zap.String("header", header.String())).
|
return err
|
||||||
Debug("document created in the database")
|
}
|
||||||
|
|
||||||
|
heads = []string{header.FirstId}
|
||||||
|
snapshotPath = []string{header.FirstId}
|
||||||
|
ch, err = doc.GetRawChange(ctx, header.FirstId)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.With(zap.String("id", id), zap.String("text", text)).
|
log.With(zap.String("id", id), zap.String("text", text)).
|
||||||
Debug("creating document")
|
Debug("creating document")
|
||||||
|
|
||||||
err = s.messageService.SendToSpaceAsync("", syncproto.WrapHeadUpdate(&syncproto.Sync_HeadUpdate{
|
err = s.messageService.SendToSpaceAsync("", syncproto.WrapHeadUpdate(&syncproto.SyncHeadUpdate{
|
||||||
Heads: heads,
|
Heads: heads,
|
||||||
Changes: []*aclpb.RawChange{ch},
|
Changes: []*aclpb.RawChange{ch},
|
||||||
TreeId: id,
|
|
||||||
SnapshotPath: snapshotPath,
|
SnapshotPath: snapshotPath,
|
||||||
TreeHeader: header,
|
}, header, id))
|
||||||
}))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
return id, err
|
return id, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func createInitialChangeContent(text string) proto.Marshaler {
|
func createInitialTextChange(text string) proto.Marshaler {
|
||||||
return &testchangepb.PlainTextChange_Data{
|
return &testchanges.PlainTextChangeData{
|
||||||
Content: []*testchangepb.PlainTextChange_Content{
|
Content: []*testchanges.PlainTextChangeContent{
|
||||||
createAppendTextChangeContent(text),
|
createAppendTextChangeContent(text),
|
||||||
},
|
},
|
||||||
Snapshot: &testchangepb.PlainTextChange_Snapshot{Text: text},
|
Snapshot: &testchanges.PlainTextChangeSnapshot{Text: text},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func createAppendTextChangeContent(text string) *testchangepb.PlainTextChange_Content {
|
func createAppendTextChange(text string) proto.Marshaler {
|
||||||
return &testchangepb.PlainTextChange_Content{
|
return &testchanges.PlainTextChangeData{
|
||||||
Value: &testchangepb.PlainTextChange_Content_TextAppend{
|
Content: []*testchanges.PlainTextChangeContent{
|
||||||
TextAppend: &testchangepb.PlainTextChange_TextAppend{
|
createAppendTextChangeContent(text),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func createAppendTextChangeContent(text string) *testchanges.PlainTextChangeContent {
|
||||||
|
return &testchanges.PlainTextChangeContent{
|
||||||
|
Value: &testchanges.PlainTextChangeContentValueOfTextAppend{
|
||||||
|
TextAppend: &testchanges.PlainTextChangeTextAppend{
|
||||||
Text: text,
|
Text: text,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@ -2,16 +2,10 @@ package storage
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/app"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/app"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/app/logger"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/app/logger"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/etc"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclrecordproto/aclpb"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb"
|
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/list"
|
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/storage"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/storage"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/testutils/acllistbuilder"
|
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/account"
|
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/node"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var CName = "storage"
|
var CName = "storage"
|
||||||
@ -38,10 +32,10 @@ type service struct {
|
|||||||
importedACLSyncData ImportedACLSyncData
|
importedACLSyncData ImportedACLSyncData
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *service) Init(ctx context.Context, a *app.App) (err error) {
|
func (s *service) Init(a *app.App) (err error) {
|
||||||
s.storageProvider = storage.NewInMemoryTreeStorageProvider()
|
s.storageProvider = storage.NewInMemoryTreeStorageProvider()
|
||||||
// importing hardcoded acl list, check that the keys there are correct
|
// importing hardcoded acl list, check that the keys there are correct
|
||||||
return s.importACLList(a)
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *service) Storage(treeId string) (storage.Storage, error) {
|
func (s *service) Storage(treeId string) (storage.Storage, error) {
|
||||||
@ -52,12 +46,12 @@ func (s *service) AddStorage(id string, st storage.Storage) error {
|
|||||||
return s.storageProvider.AddStorage(id, st)
|
return s.storageProvider.AddStorage(id, st)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *service) CreateTreeStorage(treeId string, header *aclpb.Header, changes []*aclpb.RawChange) (storage.TreeStorage, error) {
|
func (s *service) CreateTreeStorage(payload storage.TreeStorageCreatePayload) (storage.TreeStorage, error) {
|
||||||
return s.storageProvider.CreateTreeStorage(treeId, header, changes)
|
return s.storageProvider.CreateTreeStorage(payload)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *service) CreateACLListStorage(id string, header *aclpb.Header, records []*aclpb.RawRecord) (storage.ListStorage, error) {
|
func (s *service) CreateACLListStorage(payload storage.ACLListStorageCreatePayload) (storage.ListStorage, error) {
|
||||||
return s.storageProvider.CreateACLListStorage(id, header, records)
|
return s.storageProvider.CreateACLListStorage(payload)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *service) Name() (name string) {
|
func (s *service) Name() (name string) {
|
||||||
@ -75,62 +69,3 @@ func (s *service) Run(ctx context.Context) (err error) {
|
|||||||
func (s service) Close(ctx context.Context) (err error) {
|
func (s service) Close(ctx context.Context) (err error) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *service) importACLList(a *app.App) (err error) {
|
|
||||||
path := fmt.Sprintf("%s/%s", etc.Path(), "acl.yml")
|
|
||||||
st, err := acllistbuilder.NewACLListStorageBuilderFromFile(path)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
id, err := st.ID()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
header, err := st.Header()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// checking that acl list contains all the needed permissions for all our nodes
|
|
||||||
err = s.checkActualNodesPermissions(st, a)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
s.importedACLSyncData = ImportedACLSyncData{
|
|
||||||
Id: id,
|
|
||||||
Header: header,
|
|
||||||
Records: st.GetRawRecords(),
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Infof("imported ACLList with id %s", id)
|
|
||||||
return s.storageProvider.AddStorage(id, st)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *service) checkActualNodesPermissions(st *acllistbuilder.ACLListStorageBuilder, a *app.App) error {
|
|
||||||
nodes := a.MustComponent(node.CName).(node.Service)
|
|
||||||
acc := a.MustComponent(account.CName).(account.Service)
|
|
||||||
|
|
||||||
aclList, err := list.BuildACLListWithIdentity(acc.Account(), st)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
state := aclList.ACLState()
|
|
||||||
|
|
||||||
// checking own state
|
|
||||||
if state.GetUserStates()[acc.Account().Identity].Permissions != aclpb.ACLChange_Admin {
|
|
||||||
return fmt.Errorf("own node with signing key %s should be admin", acc.Account().Identity)
|
|
||||||
}
|
|
||||||
|
|
||||||
// checking other nodes' states
|
|
||||||
for _, n := range nodes.Nodes() {
|
|
||||||
if state.GetUserStates()[n.SigningKeyString].Permissions != aclpb.ACLChange_Admin {
|
|
||||||
return fmt.Errorf("other node with signing key %s should be admin", n.SigningKeyString)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|||||||
@ -2,33 +2,32 @@ package treecache
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/app"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/app"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/app/logger"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/app/logger"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/account"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/common/account"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclrecordproto/aclpb"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/acltree"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/list"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treestorage"
|
aclstorage "github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/storage"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/treestorage/treepb"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/tree"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/ocache"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/ocache"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/service/storage"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
const CName = "treecache"
|
const CName = "treecache"
|
||||||
|
|
||||||
// TODO: add context
|
type ObjFunc = func(obj interface{}) error
|
||||||
type ACLTreeFunc = func(tree acltree.ACLTree) error
|
|
||||||
type ChangeBuildFunc = func(builder acltree.ChangeBuilder) error
|
|
||||||
|
|
||||||
var log = logger.NewNamed("treecache")
|
var log = logger.NewNamed("treecache")
|
||||||
|
|
||||||
type Service interface {
|
type Service interface {
|
||||||
Do(ctx context.Context, treeId string, f ACLTreeFunc) error
|
Do(ctx context.Context, id string, f ObjFunc) error
|
||||||
Add(ctx context.Context, treeId string, header *treepb.TreeHeader, changes []*aclpb.RawChange, f ACLTreeFunc) error
|
Add(ctx context.Context, id string, payload any) error
|
||||||
Create(ctx context.Context, build ChangeBuildFunc, f ACLTreeFunc) error
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type service struct {
|
type service struct {
|
||||||
treeProvider treestorage.Provider
|
storage storage.Service
|
||||||
account account.Service
|
account account.Service
|
||||||
cache ocache.OCache
|
cache ocache.OCache
|
||||||
}
|
}
|
||||||
@ -37,53 +36,48 @@ func New() app.ComponentRunnable {
|
|||||||
return &service{}
|
return &service{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *service) Create(ctx context.Context, build ChangeBuildFunc, f ACLTreeFunc) error {
|
func (s *service) Do(ctx context.Context, treeId string, f ObjFunc) error {
|
||||||
acc := s.account.Account()
|
|
||||||
st, err := acltree.CreateNewTreeStorageWithACL(acc, build, s.treeProvider.CreateTreeStorage)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
id, err := st.TreeID()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return s.Do(ctx, id, f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *service) Do(ctx context.Context, treeId string, f ACLTreeFunc) error {
|
|
||||||
log.
|
log.
|
||||||
With(zap.String("treeId", treeId)).
|
With(zap.String("treeId", treeId)).
|
||||||
Debug("requesting tree from cache to perform operation")
|
Debug("requesting tree from cache to perform operation")
|
||||||
|
|
||||||
tree, err := s.cache.Get(ctx, treeId)
|
t, err := s.cache.Get(ctx, treeId)
|
||||||
defer s.cache.Release(treeId)
|
defer s.cache.Release(treeId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
aclTree := tree.(acltree.ACLTree)
|
return f(t)
|
||||||
aclTree.Lock()
|
|
||||||
defer aclTree.Unlock()
|
|
||||||
return f(tree.(acltree.ACLTree))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *service) Add(ctx context.Context, treeId string, header *treepb.TreeHeader, changes []*aclpb.RawChange, f ACLTreeFunc) error {
|
func (s *service) Add(ctx context.Context, treeId string, payload any) error {
|
||||||
|
switch pl := payload.(type) {
|
||||||
|
case aclstorage.TreeStorageCreatePayload:
|
||||||
log.
|
log.
|
||||||
With(zap.String("treeId", treeId), zap.Int("len(changes)", len(changes))).
|
With(zap.String("treeId", treeId), zap.Int("len(changes)", len(pl.Changes))).
|
||||||
Debug("adding tree with changes")
|
Debug("adding Tree with changes")
|
||||||
|
|
||||||
_, err := s.treeProvider.CreateTreeStorage(treeId, header, changes)
|
_, err := s.storage.CreateTreeStorage(payload.(aclstorage.TreeStorageCreatePayload))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return s.Do(ctx, treeId, f)
|
case aclstorage.ACLListStorageCreatePayload:
|
||||||
|
log.
|
||||||
|
With(zap.String("treeId", treeId), zap.Int("len(changes)", len(pl.Records))).
|
||||||
|
Debug("adding ACLList with records")
|
||||||
|
|
||||||
|
_, err := s.storage.CreateACLListStorage(payload.(aclstorage.ACLListStorageCreatePayload))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *service) Init(a *app.App) (err error) {
|
func (s *service) Init(a *app.App) (err error) {
|
||||||
s.cache = ocache.New(s.loadTree)
|
s.cache = ocache.New(s.loadTree)
|
||||||
s.account = a.MustComponent(account.CName).(account.Service)
|
s.account = a.MustComponent(account.CName).(account.Service)
|
||||||
s.treeProvider = treestorage.NewInMemoryTreeStorageProvider()
|
s.storage = a.MustComponent(storage.CName).(storage.Service)
|
||||||
// TODO: for test we should load some predefined keys
|
// TODO: for test we should load some predefined keys
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -101,11 +95,33 @@ func (s *service) Close(ctx context.Context) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *service) loadTree(ctx context.Context, id string) (ocache.Object, error) {
|
func (s *service) loadTree(ctx context.Context, id string) (ocache.Object, error) {
|
||||||
tree, err := s.treeProvider.TreeStorage(id)
|
t, err := s.storage.Storage(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// TODO: should probably accept nil listeners
|
header, err := t.Header()
|
||||||
aclTree, err := acltree.BuildACLTree(tree, s.account.Account(), acltree.NoOpListener{})
|
if err != nil {
|
||||||
return aclTree, err
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch header.DocType { // handler
|
||||||
|
case aclpb.Header_ACL:
|
||||||
|
return list.BuildACLListWithIdentity(s.account.Account(), t.(aclstorage.ListStorage))
|
||||||
|
case aclpb.Header_DocTree:
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("incorrect type")
|
||||||
|
}
|
||||||
|
log.Info("got header", zap.String("header", header.String()))
|
||||||
|
var objTree tree.ObjectTree
|
||||||
|
err = s.Do(ctx, header.AclListId, func(obj interface{}) error {
|
||||||
|
aclList := obj.(list.ACLList)
|
||||||
|
objTree, err = tree.BuildObjectTree(t.(aclstorage.TreeStorage), nil, aclList)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
return objTree, err
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,7 @@ syntax = "proto3";
|
|||||||
package anytype;
|
package anytype;
|
||||||
option go_package = "/syncproto";
|
option go_package = "/syncproto";
|
||||||
|
|
||||||
import "pkg/acl/aclchanges/aclpb/protos/aclchanges.proto";
|
import "pkg/acl/aclrecordproto/aclpb/protos/aclrecordproto.proto";
|
||||||
|
|
||||||
message Message {
|
message Message {
|
||||||
Header header = 1;
|
Header header = 1;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user