WIP proto refactoring
This commit is contained in:
parent
018406d25c
commit
9976a84d42
2
Makefile
2
Makefile
@ -30,7 +30,7 @@ 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_ACL_CHANGES))
|
||||||
$(GOGO_START) protoc --gogofaster_out=$(PKGMAP):. $(P_SYNC_CHANGES_PATH_PB)/proto/*.proto
|
$(GOGO_START) protoc --gogofaster_out=$(PKGMAP):. $(P_SYNC_CHANGES_PATH_PB)/proto/*.proto
|
||||||
$(GOGO_START) protoc --gogofaster_out=$(PKGMAP):. service/space/spacesync/protos/*.proto
|
$(GOGO_START) protoc --gogofaster_out=$(PKGMAP):. 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))
|
||||||
|
|||||||
@ -1,16 +1,17 @@
|
|||||||
syntax = "proto3";
|
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";
|
||||||
|
|
||||||
enum ErrCodes {
|
enum ErrCodes {
|
||||||
Unexpected = 0;
|
Unexpected = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
service Space {
|
service Space {
|
||||||
// HeadSync compares all objects and their hashes in a space
|
// HeadSync compares all objects and their hashes in a space
|
||||||
rpc HeadSync(HeadSyncRequest) returns (HeadSyncResponse);
|
rpc HeadSync(HeadSyncRequest) returns (HeadSyncResponse);
|
||||||
rpc Stream( stream Msg) returns (stream Msg);
|
rpc Stream(stream ObjectSyncMessage) returns (stream ObjectSyncMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: temporary mock message
|
// TODO: temporary mock message
|
||||||
@ -18,8 +19,6 @@ message Msg {
|
|||||||
string spaceId = 1;
|
string spaceId = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// HeadSyncRange presenting a request for one range
|
// HeadSyncRange presenting a request for one range
|
||||||
message HeadSyncRange {
|
message HeadSyncRange {
|
||||||
uint64 from = 1;
|
uint64 from = 1;
|
||||||
@ -50,3 +49,40 @@ message HeadSyncRequest {
|
|||||||
message HeadSyncResponse {
|
message HeadSyncResponse {
|
||||||
repeated HeadSyncResult results = 1;
|
repeated HeadSyncResult results = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ObjectSyncMessage is a message sent on object sync
|
||||||
|
message ObjectSyncMessage {
|
||||||
|
string spaceId = 1;
|
||||||
|
ObjectSyncContentValue content = 2;
|
||||||
|
acl.TreeHeader treeHeader = 3;
|
||||||
|
string treeId = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ObjectSyncContentValue provides different types for object sync
|
||||||
|
message ObjectSyncContentValue {
|
||||||
|
oneof value {
|
||||||
|
ObjectHeadUpdate headUpdate = 1;
|
||||||
|
ObjectFullSyncRequest fullSyncRequest = 2;
|
||||||
|
ObjectFullSyncResponse fullSyncResponse = 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ObjectHeadUpdate is a message sent on document head update
|
||||||
|
message ObjectHeadUpdate {
|
||||||
|
repeated string heads = 1;
|
||||||
|
repeated acl.RawTreeChangeWithId changes = 2;
|
||||||
|
repeated string snapshotPath = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ObjectHeadUpdate is a message sent when document needs full sync
|
||||||
|
message ObjectFullSyncRequest {
|
||||||
|
repeated string heads = 1;
|
||||||
|
repeated string snapshotPath = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ObjectFullSyncResponse is a message sent as a response for a specific full sync
|
||||||
|
message ObjectFullSyncResponse {
|
||||||
|
repeated string heads = 1;
|
||||||
|
repeated acl.RawTreeChangeWithId changes = 2;
|
||||||
|
repeated string snapshotPath = 3;
|
||||||
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -7,7 +7,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type AccountData struct { // TODO: create a convenient constructor for this
|
type AccountData struct { // TODO: create a convenient constructor for this
|
||||||
Identity string // TODO: this is essentially the same as sign key
|
Identity []byte // TODO: this is essentially the same as sign key
|
||||||
SignKey signingkey.PrivKey
|
SignKey signingkey.PrivKey
|
||||||
EncKey encryptionkey.PrivKey
|
EncKey encryptionkey.PrivKey
|
||||||
Decoder keys.Decoder
|
Decoder keys.Decoder
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -2,147 +2,142 @@ syntax = "proto3";
|
|||||||
package acl;
|
package acl;
|
||||||
option go_package = "aclpb";
|
option go_package = "aclpb";
|
||||||
|
|
||||||
message RawChange {
|
// ACL protos
|
||||||
|
|
||||||
|
message RawACLRecord {
|
||||||
bytes payload = 1;
|
bytes payload = 1;
|
||||||
bytes signature = 2;
|
bytes signature = 2;
|
||||||
string id = 3;
|
string id = 3; // this field is only used on user side for convenience, it should be empty when saving to db
|
||||||
}
|
}
|
||||||
|
|
||||||
message RawRecord {
|
message ACLContentValue {
|
||||||
bytes payload = 1;
|
oneof value {
|
||||||
bytes signature = 2;
|
ACLUserAdd userAdd = 1;
|
||||||
string id = 3;
|
ACLUserRemove userRemove = 2;
|
||||||
}
|
ACLUserPermissionChange userPermissionChange = 3;
|
||||||
|
ACLUserInvite userInvite = 4;
|
||||||
// the element of change tree used to store and internal apply smartBlock history
|
ACLUserJoin userJoin = 5;
|
||||||
message ACLChange {
|
ACLUserConfirm userConfirm = 6;
|
||||||
repeated string treeHeadIds = 1;
|
|
||||||
repeated string aclHeadIds = 2;
|
|
||||||
string snapshotBaseId = 3; // we will only have one base snapshot for both
|
|
||||||
ACLData aclData = 4;
|
|
||||||
// the data is encoded with read key and should be read in ChangesData format
|
|
||||||
bytes changesData = 5;
|
|
||||||
uint64 currentReadKeyHash = 6;
|
|
||||||
int64 timestamp = 7;
|
|
||||||
string identity = 8;
|
|
||||||
|
|
||||||
message ACLContentValue {
|
|
||||||
oneof value {
|
|
||||||
UserAdd userAdd = 1;
|
|
||||||
UserRemove userRemove = 2;
|
|
||||||
UserPermissionChange userPermissionChange = 3;
|
|
||||||
UserInvite userInvite = 4;
|
|
||||||
UserJoin userJoin = 5;
|
|
||||||
UserConfirm userConfirm = 6;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
message ACLData {
|
|
||||||
ACLSnapshot aclSnapshot = 1;
|
|
||||||
repeated ACLContentValue aclContent = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
message ACLSnapshot {
|
|
||||||
// We don't need ACLState as a separate message now, because we simplified the snapshot model
|
|
||||||
ACLState aclState = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
message ACLState {
|
|
||||||
repeated uint64 readKeyHashes = 1;
|
|
||||||
repeated UserState userStates = 2;
|
|
||||||
map<string, UserInvite> invites = 3; // TODO: later
|
|
||||||
// repeated string unconfirmedUsers = 4; // TODO: later
|
|
||||||
}
|
|
||||||
|
|
||||||
message UserState {
|
|
||||||
string identity = 1;
|
|
||||||
bytes encryptionKey = 2;
|
|
||||||
repeated bytes encryptedReadKeys = 3; // all read keys that we know
|
|
||||||
UserPermissions permissions = 4;
|
|
||||||
bool IsConfirmed = 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
// we already know identity and encryptionKey
|
|
||||||
message UserAdd {
|
|
||||||
string identity = 1; // public signing key
|
|
||||||
bytes encryptionKey = 2; // public encryption key
|
|
||||||
repeated bytes encryptedReadKeys = 3; // all read keys that we know for the user
|
|
||||||
UserPermissions permissions = 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: this is not used as of now
|
|
||||||
message UserConfirm { // not needed for read permissions
|
|
||||||
string identity = 1; // not needed
|
|
||||||
string userAddId = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
message UserInvite {
|
|
||||||
bytes acceptPublicKey = 1;
|
|
||||||
bytes encryptPublicKey = 2;
|
|
||||||
repeated bytes encryptedReadKeys = 3; // all read keys that we know for the user
|
|
||||||
UserPermissions permissions = 4;
|
|
||||||
string InviteId = 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
message UserJoin {
|
|
||||||
string 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 UserRemove {
|
|
||||||
string identity = 1;
|
|
||||||
repeated ReadKeyReplace readKeyReplaces = 3; // new read key encrypted for all users
|
|
||||||
}
|
|
||||||
|
|
||||||
message ReadKeyReplace {
|
|
||||||
string identity = 1;
|
|
||||||
bytes encryptionKey = 2;
|
|
||||||
bytes encryptedReadKey = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
message UserPermissionChange {
|
|
||||||
string identity = 1;
|
|
||||||
UserPermissions permissions = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum UserPermissions {
|
|
||||||
Admin = 0;
|
|
||||||
Writer = 1;
|
|
||||||
Reader = 2;
|
|
||||||
Removed = 3;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
message Change {
|
message ACLData {
|
||||||
repeated string treeHeadIds = 1;
|
repeated ACLContentValue aclContent = 1;
|
||||||
string aclHeadId = 2;
|
|
||||||
string snapshotBaseId = 3; // we will only have one base snapshot for both
|
|
||||||
bytes changesData = 4;
|
|
||||||
uint64 currentReadKeyHash = 5;
|
|
||||||
int64 timestamp = 6;
|
|
||||||
string identity = 7;
|
|
||||||
bool isSnapshot = 8;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message Record {
|
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;
|
string prevId = 1;
|
||||||
string identity = 2;
|
bytes identity = 2;
|
||||||
bytes data = 3;
|
bytes data = 3;
|
||||||
uint64 currentReadKeyHash = 4;
|
uint64 currentReadKeyHash = 4;
|
||||||
int64 timestamp = 5;
|
int64 timestamp = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
message Header {
|
message ACLHeader {
|
||||||
string firstId = 1;
|
string firstId = 1;
|
||||||
string aclListId = 2;
|
bytes identity = 2; // the identity of the creator
|
||||||
string workspaceId = 3;
|
}
|
||||||
DocType docType = 4;
|
|
||||||
|
// Tree protos
|
||||||
enum DocType {
|
|
||||||
ACL = 0;
|
message RawTreeChange {
|
||||||
DocTree = 1;
|
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,6 +1,7 @@
|
|||||||
package list
|
package list
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/app/logger"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/app/logger"
|
||||||
@ -29,14 +30,14 @@ var ErrInvalidSignature = errors.New("signature is invalid")
|
|||||||
|
|
||||||
type UserPermissionPair struct {
|
type UserPermissionPair struct {
|
||||||
Identity string
|
Identity string
|
||||||
Permission aclpb.ACLChangeUserPermissions
|
Permission aclpb.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.ACLChangeUserState
|
userStates map[string]*aclpb.ACLUserState
|
||||||
userInvites map[string]*aclpb.ACLChangeUserInvite
|
userInvites map[string]*aclpb.ACLUserInvite
|
||||||
|
|
||||||
signingPubKeyDecoder keys.Decoder
|
signingPubKeyDecoder keys.Decoder
|
||||||
encryptionKey encryptionkey.PrivKey
|
encryptionKey encryptionkey.PrivKey
|
||||||
@ -55,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.ACLChangeUserState),
|
userStates: make(map[string]*aclpb.ACLUserState),
|
||||||
userInvites: make(map[string]*aclpb.ACLChangeUserInvite),
|
userInvites: make(map[string]*aclpb.ACLUserInvite),
|
||||||
signingPubKeyDecoder: decoder,
|
signingPubKeyDecoder: decoder,
|
||||||
permissionsAtRecord: make(map[string][]UserPermissionPair),
|
permissionsAtRecord: make(map[string][]UserPermissionPair),
|
||||||
keychain: common.NewKeychain(),
|
keychain: common.NewKeychain(),
|
||||||
@ -67,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.ACLChangeUserState),
|
userStates: make(map[string]*aclpb.ACLUserState),
|
||||||
userInvites: make(map[string]*aclpb.ACLChangeUserInvite),
|
userInvites: make(map[string]*aclpb.ACLUserInvite),
|
||||||
permissionsAtRecord: make(map[string][]UserPermissionPair),
|
permissionsAtRecord: make(map[string][]UserPermissionPair),
|
||||||
keychain: common.NewKeychain(),
|
keychain: common.NewKeychain(),
|
||||||
}
|
}
|
||||||
@ -105,8 +106,8 @@ func (st *ACLState) PermissionsAtRecord(id string, identity string) (UserPermiss
|
|||||||
return UserPermissionPair{}, ErrNoSuchUser
|
return UserPermissionPair{}, ErrNoSuchUser
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *ACLState) applyRecord(record *aclpb.Record) (err error) {
|
func (st *ACLState) applyRecord(record *aclpb.ACLRecord) (err error) {
|
||||||
aclData := &aclpb.ACLChangeACLData{}
|
aclData := &aclpb.ACLData{}
|
||||||
|
|
||||||
err = proto.Unmarshal(record.Data, aclData)
|
err = proto.Unmarshal(record.Data, aclData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -122,14 +123,14 @@ func (st *ACLState) applyRecord(record *aclpb.Record) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *ACLState) applyChangeAndUpdate(recordWrapper *Record) (err error) {
|
func (st *ACLState) applyChangeAndUpdate(recordWrapper *ACLRecord) (err error) {
|
||||||
var (
|
var (
|
||||||
change = recordWrapper.Content
|
change = recordWrapper.Content
|
||||||
aclData = &aclpb.ACLChangeACLData{}
|
aclData = &aclpb.ACLData{}
|
||||||
)
|
)
|
||||||
|
|
||||||
if recordWrapper.Model != nil {
|
if recordWrapper.Model != nil {
|
||||||
aclData = recordWrapper.Model.(*aclpb.ACLChangeACLData)
|
aclData = recordWrapper.Model.(*aclpb.ACLData)
|
||||||
} else {
|
} else {
|
||||||
err = proto.Unmarshal(change.Data, aclData)
|
err = proto.Unmarshal(change.Data, aclData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -147,7 +148,7 @@ func (st *ACLState) applyChangeAndUpdate(recordWrapper *Record) (err error) {
|
|||||||
var permissions []UserPermissionPair
|
var permissions []UserPermissionPair
|
||||||
for _, state := range st.userStates {
|
for _, state := range st.userStates {
|
||||||
permission := UserPermissionPair{
|
permission := UserPermissionPair{
|
||||||
Identity: state.Identity,
|
Identity: string(state.Identity),
|
||||||
Permission: state.Permissions,
|
Permission: state.Permissions,
|
||||||
}
|
}
|
||||||
permissions = append(permissions, permission)
|
permissions = append(permissions, permission)
|
||||||
@ -157,7 +158,7 @@ func (st *ACLState) applyChangeAndUpdate(recordWrapper *Record) (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *ACLState) applyChangeData(changeData *aclpb.ACLChangeACLData, hash uint64, identity string) (err error) {
|
func (st *ACLState) applyChangeData(changeData *aclpb.ACLData, hash uint64, identity []byte) (err error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@ -170,12 +171,12 @@ func (st *ACLState) applyChangeData(changeData *aclpb.ACLChangeACLData, hash uin
|
|||||||
skipIdentityCheck := st.isUserJoin(changeData) || (st.currentReadKeyHash == 0 && st.isUserAdd(changeData, identity))
|
skipIdentityCheck := st.isUserJoin(changeData) || (st.currentReadKeyHash == 0 && st.isUserAdd(changeData, identity))
|
||||||
if !skipIdentityCheck {
|
if !skipIdentityCheck {
|
||||||
// we check signature when we add this to the Tree, so no need to do it here
|
// we check signature when we add this to the Tree, so no need to do it here
|
||||||
if _, exists := st.userStates[identity]; !exists {
|
if _, exists := st.userStates[string(identity)]; !exists {
|
||||||
err = ErrNoSuchUser
|
err = ErrNoSuchUser
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !st.hasPermission(identity, aclpb.ACLChange_Admin) {
|
if !st.hasPermission(identity, aclpb.ACLUserPermissions_Admin) {
|
||||||
err = fmt.Errorf("user %s must have admin permissions", identity)
|
err = fmt.Errorf("user %s must have admin permissions", identity)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -191,7 +192,7 @@ func (st *ACLState) applyChangeData(changeData *aclpb.ACLChangeACLData, hash uin
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *ACLState) applyChangeContent(ch *aclpb.ACLChangeACLContentValue) error {
|
func (st *ACLState) applyChangeContent(ch *aclpb.ACLContentValue) error {
|
||||||
switch {
|
switch {
|
||||||
case ch.GetUserPermissionChange() != nil:
|
case ch.GetUserPermissionChange() != nil:
|
||||||
return st.applyUserPermissionChange(ch.GetUserPermissionChange())
|
return st.applyUserPermissionChange(ch.GetUserPermissionChange())
|
||||||
@ -210,27 +211,29 @@ func (st *ACLState) applyChangeContent(ch *aclpb.ACLChangeACLContentValue) error
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *ACLState) applyUserPermissionChange(ch *aclpb.ACLChangeUserPermissionChange) error {
|
func (st *ACLState) applyUserPermissionChange(ch *aclpb.ACLUserPermissionChange) error {
|
||||||
if _, exists := st.userStates[ch.Identity]; !exists {
|
chIdentity := string(ch.Identity)
|
||||||
|
if _, exists := st.userStates[chIdentity]; !exists {
|
||||||
return ErrNoSuchUser
|
return ErrNoSuchUser
|
||||||
}
|
}
|
||||||
|
|
||||||
st.userStates[ch.Identity].Permissions = ch.Permissions
|
st.userStates[chIdentity].Permissions = ch.Permissions
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *ACLState) applyUserInvite(ch *aclpb.ACLChangeUserInvite) error {
|
func (st *ACLState) applyUserInvite(ch *aclpb.ACLUserInvite) error {
|
||||||
st.userInvites[ch.InviteId] = ch
|
st.userInvites[ch.InviteId] = ch
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *ACLState) applyUserJoin(ch *aclpb.ACLChangeUserJoin) error {
|
func (st *ACLState) applyUserJoin(ch *aclpb.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)
|
||||||
}
|
}
|
||||||
|
chIdentity := string(ch.Identity)
|
||||||
|
|
||||||
if _, exists = st.userStates[ch.Identity]; exists {
|
if _, exists = st.userStates[chIdentity]; exists {
|
||||||
return ErrUserAlreadyExists
|
return ErrUserAlreadyExists
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -241,12 +244,7 @@ func (st *ACLState) applyUserJoin(ch *aclpb.ACLChangeUserJoin) error {
|
|||||||
return fmt.Errorf("public key verifying invite accepts is given in incorrect format: %v", err)
|
return fmt.Errorf("public key verifying invite accepts is given in incorrect format: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
rawSignedId, err := st.signingPubKeyDecoder.DecodeFromStringIntoBytes(ch.Identity)
|
res, err := verificationKey.(signingkey.PubKey).Verify(ch.Identity, signature)
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("failed to decode signing identity as bytes")
|
|
||||||
}
|
|
||||||
|
|
||||||
res, err := verificationKey.(signingkey.PubKey).Verify(rawSignedId, signature)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("verification returned error: %w", err)
|
return fmt.Errorf("verification returned error: %w", err)
|
||||||
}
|
}
|
||||||
@ -255,7 +253,7 @@ func (st *ACLState) applyUserJoin(ch *aclpb.ACLChangeUserJoin) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if ourselves -> we need to decrypt the read keys
|
// if ourselves -> we need to decrypt the read keys
|
||||||
if st.identity == ch.Identity {
|
if st.identity == chIdentity {
|
||||||
for _, key := range ch.EncryptedReadKeys {
|
for _, key := range ch.EncryptedReadKeys {
|
||||||
key, hash, err := st.decryptReadKeyAndHash(key)
|
key, hash, err := st.decryptReadKeyAndHash(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -267,30 +265,31 @@ func (st *ACLState) applyUserJoin(ch *aclpb.ACLChangeUserJoin) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// adding user to the list
|
// adding user to the list
|
||||||
userState := &aclpb.ACLChangeUserState{
|
userState := &aclpb.ACLUserState{
|
||||||
Identity: ch.Identity,
|
Identity: ch.Identity,
|
||||||
EncryptionKey: ch.EncryptionKey,
|
EncryptionKey: ch.EncryptionKey,
|
||||||
EncryptedReadKeys: ch.EncryptedReadKeys,
|
EncryptedReadKeys: ch.EncryptedReadKeys,
|
||||||
Permissions: invite.Permissions,
|
Permissions: invite.Permissions,
|
||||||
IsConfirmed: true,
|
IsConfirmed: true,
|
||||||
}
|
}
|
||||||
st.userStates[ch.Identity] = userState
|
st.userStates[chIdentity] = userState
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *ACLState) applyUserAdd(ch *aclpb.ACLChangeUserAdd) error {
|
func (st *ACLState) applyUserAdd(ch *aclpb.ACLUserAdd) error {
|
||||||
if _, exists := st.userStates[ch.Identity]; exists {
|
chIdentity := string(ch.Identity)
|
||||||
|
if _, exists := st.userStates[chIdentity]; exists {
|
||||||
return ErrUserAlreadyExists
|
return ErrUserAlreadyExists
|
||||||
}
|
}
|
||||||
|
|
||||||
st.userStates[ch.Identity] = &aclpb.ACLChangeUserState{
|
st.userStates[chIdentity] = &aclpb.ACLUserState{
|
||||||
Identity: ch.Identity,
|
Identity: ch.Identity,
|
||||||
EncryptionKey: ch.EncryptionKey,
|
EncryptionKey: ch.EncryptionKey,
|
||||||
Permissions: ch.Permissions,
|
Permissions: ch.Permissions,
|
||||||
EncryptedReadKeys: ch.EncryptedReadKeys,
|
EncryptedReadKeys: ch.EncryptedReadKeys,
|
||||||
}
|
}
|
||||||
|
|
||||||
if ch.Identity == st.identity {
|
if chIdentity == st.identity {
|
||||||
for _, key := range ch.EncryptedReadKeys {
|
for _, key := range ch.EncryptedReadKeys {
|
||||||
key, hash, err := st.decryptReadKeyAndHash(key)
|
key, hash, err := st.decryptReadKeyAndHash(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -304,26 +303,28 @@ func (st *ACLState) applyUserAdd(ch *aclpb.ACLChangeUserAdd) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *ACLState) applyUserRemove(ch *aclpb.ACLChangeUserRemove) error {
|
func (st *ACLState) applyUserRemove(ch *aclpb.ACLUserRemove) error {
|
||||||
if ch.Identity == st.identity {
|
chIdentity := string(ch.Identity)
|
||||||
|
if chIdentity == st.identity {
|
||||||
return ErrDocumentForbidden
|
return ErrDocumentForbidden
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, exists := st.userStates[ch.Identity]; !exists {
|
if _, exists := st.userStates[chIdentity]; !exists {
|
||||||
return ErrNoSuchUser
|
return ErrNoSuchUser
|
||||||
}
|
}
|
||||||
|
|
||||||
delete(st.userStates, ch.Identity)
|
delete(st.userStates, chIdentity)
|
||||||
|
|
||||||
for _, replace := range ch.ReadKeyReplaces {
|
for _, replace := range ch.ReadKeyReplaces {
|
||||||
userState, exists := st.userStates[replace.Identity]
|
repIdentity := string(replace.Identity)
|
||||||
|
userState, exists := st.userStates[repIdentity]
|
||||||
if !exists {
|
if !exists {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
userState.EncryptedReadKeys = append(userState.EncryptedReadKeys, replace.EncryptedReadKey)
|
userState.EncryptedReadKeys = append(userState.EncryptedReadKeys, replace.EncryptedReadKey)
|
||||||
// if this is our identity then we have to decrypt the key
|
// if this is our identity then we have to decrypt the key
|
||||||
if replace.Identity == st.identity {
|
if repIdentity == st.identity {
|
||||||
key, hash, err := st.decryptReadKeyAndHash(replace.EncryptedReadKey)
|
key, hash, err := st.decryptReadKeyAndHash(replace.EncryptedReadKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ErrFailedToDecrypt
|
return ErrFailedToDecrypt
|
||||||
@ -336,12 +337,13 @@ func (st *ACLState) applyUserRemove(ch *aclpb.ACLChangeUserRemove) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *ACLState) applyUserConfirm(ch *aclpb.ACLChangeUserConfirm) error {
|
func (st *ACLState) applyUserConfirm(ch *aclpb.ACLUserConfirm) error {
|
||||||
if _, exists := st.userStates[ch.Identity]; !exists {
|
chIdentity := string(ch.Identity)
|
||||||
|
if _, exists := st.userStates[chIdentity]; !exists {
|
||||||
return ErrNoSuchUser
|
return ErrNoSuchUser
|
||||||
}
|
}
|
||||||
|
|
||||||
userState := st.userStates[ch.Identity]
|
userState := st.userStates[chIdentity]
|
||||||
userState.IsConfirmed = true
|
userState.IsConfirmed = true
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -362,8 +364,8 @@ 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 string, permission aclpb.ACLChangeUserPermissions) bool {
|
func (st *ACLState) hasPermission(identity []byte, permission aclpb.ACLUserPermissions) bool {
|
||||||
state, exists := st.userStates[identity]
|
state, exists := st.userStates[string(identity)]
|
||||||
if !exists {
|
if !exists {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -371,17 +373,17 @@ func (st *ACLState) hasPermission(identity string, permission aclpb.ACLChangeUse
|
|||||||
return state.Permissions == permission
|
return state.Permissions == permission
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *ACLState) isUserJoin(data *aclpb.ACLChangeACLData) bool {
|
func (st *ACLState) isUserJoin(data *aclpb.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.ACLChangeACLData, identity string) bool {
|
func (st *ACLState) isUserAdd(data *aclpb.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 && userAdd.GetIdentity() == identity
|
return data.GetAclContent() != nil && userAdd != nil && bytes.Compare(userAdd.GetIdentity(), identity) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (st *ACLState) GetUserStates() map[string]*aclpb.ACLChangeUserState {
|
func (st *ACLState) GetUserStates() map[string]*aclpb.ACLUserState {
|
||||||
return st.userStates
|
return st.userStates
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,7 +15,7 @@ type aclStateBuilder struct {
|
|||||||
func newACLStateBuilderWithIdentity(decoder keys.Decoder, accountData *account.AccountData) *aclStateBuilder {
|
func newACLStateBuilderWithIdentity(decoder keys.Decoder, accountData *account.AccountData) *aclStateBuilder {
|
||||||
return &aclStateBuilder{
|
return &aclStateBuilder{
|
||||||
decoder: decoder,
|
decoder: decoder,
|
||||||
identity: accountData.Identity,
|
identity: string(accountData.Identity),
|
||||||
key: accountData.EncKey,
|
key: accountData.EncKey,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -26,7 +26,7 @@ func newACLStateBuilder(decoder keys.Decoder) *aclStateBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sb *aclStateBuilder) Build(records []*Record) (*ACLState, error) {
|
func (sb *aclStateBuilder) Build(records []*ACLRecord) (*ACLState, error) {
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
state *ACLState
|
state *ACLState
|
||||||
|
|||||||
@ -14,7 +14,7 @@ import (
|
|||||||
type MarshalledChange = []byte
|
type MarshalledChange = []byte
|
||||||
|
|
||||||
type ACLChangeBuilder interface {
|
type ACLChangeBuilder interface {
|
||||||
UserAdd(identity string, encryptionKey encryptionkey.PubKey, permissions aclpb.ACLChangeUserPermissions) error
|
UserAdd(identity string, encryptionKey encryptionkey.PubKey, permissions aclpb.ACLUserPermissions) error
|
||||||
AddId(id string) // TODO: this is only for testing
|
AddId(id string) // TODO: this is only for testing
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23,7 +23,7 @@ type aclChangeBuilder struct {
|
|||||||
list ACLList
|
list ACLList
|
||||||
acc *account.AccountData
|
acc *account.AccountData
|
||||||
|
|
||||||
aclData *aclpb.ACLChangeACLData
|
aclData *aclpb.ACLData
|
||||||
id string
|
id string
|
||||||
readKey *symmetric.Key
|
readKey *symmetric.Key
|
||||||
readKeyHash uint64
|
readKeyHash uint64
|
||||||
@ -38,7 +38,7 @@ func (c *aclChangeBuilder) Init(state *ACLState, list ACLList, acc *account.Acco
|
|||||||
c.list = list
|
c.list = list
|
||||||
c.acc = acc
|
c.acc = acc
|
||||||
|
|
||||||
c.aclData = &aclpb.ACLChangeACLData{}
|
c.aclData = &aclpb.ACLData{}
|
||||||
// setting read key for further encryption etc
|
// setting read key for further encryption etc
|
||||||
if state.currentReadKeyHash == 0 {
|
if state.currentReadKeyHash == 0 {
|
||||||
c.readKey, _ = symmetric.NewRandom()
|
c.readKey, _ = symmetric.NewRandom()
|
||||||
@ -56,7 +56,7 @@ func (c *aclChangeBuilder) AddId(id string) {
|
|||||||
c.id = id
|
c.id = id
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *aclChangeBuilder) UserAdd(identity string, encryptionKey encryptionkey.PubKey, permissions aclpb.ACLChangeUserPermissions) error {
|
func (c *aclChangeBuilder) UserAdd(identity string, encryptionKey encryptionkey.PubKey, permissions aclpb.ACLUserPermissions) error {
|
||||||
var allKeys []*symmetric.Key
|
var allKeys []*symmetric.Key
|
||||||
if c.aclState.currentReadKeyHash != 0 {
|
if c.aclState.currentReadKeyHash != 0 {
|
||||||
for _, key := range c.aclState.userReadKeys {
|
for _, key := range c.aclState.userReadKeys {
|
||||||
@ -79,10 +79,10 @@ func (c *aclChangeBuilder) UserAdd(identity string, encryptionKey encryptionkey.
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
ch := &aclpb.ACLChangeACLContentValue{
|
ch := &aclpb.ACLContentValue{
|
||||||
Value: &aclpb.ACLChangeACLContentValueValueOfUserAdd{
|
Value: &aclpb.ACLContentValue_UserAdd{
|
||||||
UserAdd: &aclpb.ACLChangeUserAdd{
|
UserAdd: &aclpb.ACLUserAdd{
|
||||||
Identity: identity,
|
Identity: []byte(identity),
|
||||||
EncryptionKey: rawKey,
|
EncryptionKey: rawKey,
|
||||||
EncryptedReadKeys: encryptedKeys,
|
EncryptedReadKeys: encryptedKeys,
|
||||||
Permissions: permissions,
|
Permissions: permissions,
|
||||||
@ -93,8 +93,8 @@ func (c *aclChangeBuilder) UserAdd(identity string, encryptionKey encryptionkey.
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *aclChangeBuilder) BuildAndApply() (*Record, []byte, error) {
|
func (c *aclChangeBuilder) BuildAndApply() (*ACLRecord, []byte, error) {
|
||||||
aclRecord := &aclpb.Record{
|
aclRecord := &aclpb.ACLRecord{
|
||||||
PrevId: c.list.Head().Id,
|
PrevId: c.list.Head().Id,
|
||||||
CurrentReadKeyHash: c.readKeyHash,
|
CurrentReadKeyHash: c.readKeyHash,
|
||||||
Timestamp: int64(time.Now().Nanosecond()),
|
Timestamp: int64(time.Now().Nanosecond()),
|
||||||
|
|||||||
@ -13,7 +13,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
type IterFunc = func(record *Record) (IsContinue bool)
|
type IterFunc = func(record *ACLRecord) (IsContinue bool)
|
||||||
|
|
||||||
var ErrIncorrectCID = errors.New("incorrect CID")
|
var ErrIncorrectCID = errors.New("incorrect CID")
|
||||||
|
|
||||||
@ -26,20 +26,20 @@ type RWLocker interface {
|
|||||||
type ACLList interface {
|
type ACLList interface {
|
||||||
RWLocker
|
RWLocker
|
||||||
ID() string
|
ID() string
|
||||||
Header() *aclpb.Header
|
Header() *aclpb.ACLHeader
|
||||||
Records() []*Record
|
Records() []*ACLRecord
|
||||||
ACLState() *ACLState
|
ACLState() *ACLState
|
||||||
IsAfter(first string, second string) (bool, error)
|
IsAfter(first string, second string) (bool, error)
|
||||||
Head() *Record
|
Head() *ACLRecord
|
||||||
Get(id string) (*Record, error)
|
Get(id string) (*ACLRecord, error)
|
||||||
Iterate(iterFunc IterFunc)
|
Iterate(iterFunc IterFunc)
|
||||||
IterateFrom(startId string, iterFunc IterFunc)
|
IterateFrom(startId string, iterFunc IterFunc)
|
||||||
Close() (err error)
|
Close() (err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type aclList struct {
|
type aclList struct {
|
||||||
header *aclpb.Header
|
header *aclpb.ACLHeader
|
||||||
records []*Record
|
records []*ACLRecord
|
||||||
indexes map[string]int
|
indexes map[string]int
|
||||||
id string
|
id string
|
||||||
|
|
||||||
@ -84,7 +84,7 @@ func buildWithACLStateBuilder(builder *aclStateBuilder, storage storage.ListStor
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
records := []*Record{record}
|
records := []*ACLRecord{record}
|
||||||
|
|
||||||
for record.Content.PrevId != "" {
|
for record.Content.PrevId != "" {
|
||||||
rawRecord, err = storage.GetRawRecord(context.Background(), record.Content.PrevId)
|
rawRecord, err = storage.GetRawRecord(context.Background(), record.Content.PrevId)
|
||||||
@ -131,7 +131,7 @@ func buildWithACLStateBuilder(builder *aclStateBuilder, storage storage.ListStor
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *aclList) Records() []*Record {
|
func (a *aclList) Records() []*ACLRecord {
|
||||||
return a.records
|
return a.records
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,7 +139,7 @@ func (a *aclList) ID() string {
|
|||||||
return a.id
|
return a.id
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *aclList) Header() *aclpb.Header {
|
func (a *aclList) Header() *aclpb.ACLHeader {
|
||||||
return a.header
|
return a.header
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,11 +156,11 @@ func (a *aclList) IsAfter(first string, second string) (bool, error) {
|
|||||||
return firstRec >= secondRec, nil
|
return firstRec >= secondRec, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *aclList) Head() *Record {
|
func (a *aclList) Head() *ACLRecord {
|
||||||
return a.records[len(a.records)-1]
|
return a.records[len(a.records)-1]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *aclList) Get(id string) (*Record, error) {
|
func (a *aclList) Get(id string) (*ACLRecord, error) {
|
||||||
recIdx, ok := a.indexes[id]
|
recIdx, ok := a.indexes[id]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("no such record")
|
return nil, fmt.Errorf("no such record")
|
||||||
@ -192,8 +192,8 @@ func (a *aclList) Close() (err error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func verifyRecord(keychain *common.Keychain, rawRecord *aclpb.RawRecord, record *Record) (err error) {
|
func verifyRecord(keychain *common.Keychain, rawRecord *aclpb.RawACLRecord, record *ACLRecord) (err error) {
|
||||||
identityKey, err := keychain.GetOrAdd(record.Content.Identity)
|
identityKey, err := keychain.GetOrAdd(record.Identity)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -28,8 +28,8 @@ func TestAclList_ACLState_UserInviteAndJoin(t *testing.T) {
|
|||||||
assert.Equal(t, aclpb.ACLChange_Reader, aclList.ACLState().GetUserStates()[idC].Permissions)
|
assert.Equal(t, aclpb.ACLChange_Reader, aclList.ACLState().GetUserStates()[idC].Permissions)
|
||||||
assert.Equal(t, aclList.Head().Content.CurrentReadKeyHash, aclList.ACLState().CurrentReadKeyHash())
|
assert.Equal(t, aclList.Head().Content.CurrentReadKeyHash, aclList.ACLState().CurrentReadKeyHash())
|
||||||
|
|
||||||
var records []*Record
|
var records []*ACLRecord
|
||||||
aclList.Iterate(func(record *Record) (IsContinue bool) {
|
aclList.Iterate(func(record *ACLRecord) (IsContinue bool) {
|
||||||
records = append(records, record)
|
records = append(records, record)
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
@ -69,8 +69,8 @@ func TestAclList_ACLState_UserJoinAndRemove(t *testing.T) {
|
|||||||
_, exists := aclList.ACLState().GetUserStates()[idB]
|
_, exists := aclList.ACLState().GetUserStates()[idB]
|
||||||
assert.Equal(t, false, exists)
|
assert.Equal(t, false, exists)
|
||||||
|
|
||||||
var records []*Record
|
var records []*ACLRecord
|
||||||
aclList.Iterate(func(record *Record) (IsContinue bool) {
|
aclList.Iterate(func(record *ACLRecord) (IsContinue bool) {
|
||||||
records = append(records, record)
|
records = append(records, record)
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
|
|||||||
@ -5,30 +5,33 @@ import (
|
|||||||
"github.com/gogo/protobuf/proto"
|
"github.com/gogo/protobuf/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Record struct {
|
type ACLRecord struct {
|
||||||
Id string
|
Id string
|
||||||
Content *aclpb.Record
|
Content *aclpb.ACLRecord
|
||||||
Model interface{}
|
Identity string
|
||||||
Sign []byte
|
Model interface{}
|
||||||
|
Sign []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRecord(id string, aclRecord *aclpb.Record) *Record {
|
func NewRecord(id string, aclRecord *aclpb.ACLRecord) *ACLRecord {
|
||||||
return &Record{
|
return &ACLRecord{
|
||||||
Id: id,
|
Id: id,
|
||||||
Content: aclRecord,
|
Content: aclRecord,
|
||||||
|
Identity: string(aclRecord.Identity),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewFromRawRecord(rawRec *aclpb.RawRecord) (*Record, error) {
|
func NewFromRawRecord(rawRec *aclpb.RawACLRecord) (*ACLRecord, error) {
|
||||||
aclRec := &aclpb.Record{}
|
aclRec := &aclpb.ACLRecord{}
|
||||||
err := proto.Unmarshal(rawRec.Payload, aclRec)
|
err := proto.Unmarshal(rawRec.Payload, aclRec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &Record{
|
return &ACLRecord{
|
||||||
Id: rawRec.Id,
|
Id: rawRec.Id,
|
||||||
Content: aclRec,
|
Content: aclRec,
|
||||||
Sign: rawRec.Signature,
|
Sign: rawRec.Signature,
|
||||||
|
Identity: string(aclRec.Identity),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,8 +8,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type inMemoryACLListStorage struct {
|
type inMemoryACLListStorage struct {
|
||||||
header *aclpb.Header
|
header *aclpb.ACLHeader
|
||||||
records []*aclpb.RawRecord
|
records []*aclpb.RawACLRecord
|
||||||
|
|
||||||
id string
|
id string
|
||||||
|
|
||||||
@ -18,8 +18,8 @@ type inMemoryACLListStorage struct {
|
|||||||
|
|
||||||
func NewInMemoryACLListStorage(
|
func NewInMemoryACLListStorage(
|
||||||
id string,
|
id string,
|
||||||
header *aclpb.Header,
|
header *aclpb.ACLHeader,
|
||||||
records []*aclpb.RawRecord) (ListStorage, error) {
|
records []*aclpb.RawACLRecord) (ListStorage, error) {
|
||||||
return &inMemoryACLListStorage{
|
return &inMemoryACLListStorage{
|
||||||
id: id,
|
id: id,
|
||||||
header: header,
|
header: header,
|
||||||
@ -28,19 +28,19 @@ func NewInMemoryACLListStorage(
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *inMemoryACLListStorage) Header() (*aclpb.Header, error) {
|
func (i *inMemoryACLListStorage) Header() (*aclpb.ACLHeader, error) {
|
||||||
i.RLock()
|
i.RLock()
|
||||||
defer i.RUnlock()
|
defer i.RUnlock()
|
||||||
return i.header, nil
|
return i.header, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *inMemoryACLListStorage) Head() (*aclpb.RawRecord, error) {
|
func (i *inMemoryACLListStorage) Head() (*aclpb.RawACLRecord, 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.RawRecord, error) {
|
func (i *inMemoryACLListStorage) GetRawRecord(ctx context.Context, id string) (*aclpb.RawACLRecord, error) {
|
||||||
i.RLock()
|
i.RLock()
|
||||||
defer i.RUnlock()
|
defer i.RUnlock()
|
||||||
for _, rec := range i.records {
|
for _, rec := range i.records {
|
||||||
@ -51,7 +51,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.RawRecord) error {
|
func (i *inMemoryACLListStorage) AddRawRecord(ctx context.Context, rec *aclpb.RawACLRecord) error {
|
||||||
panic("implement me")
|
panic("implement me")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,19 +63,19 @@ func (i *inMemoryACLListStorage) ID() (string, error) {
|
|||||||
|
|
||||||
type inMemoryTreeStorage struct {
|
type inMemoryTreeStorage struct {
|
||||||
id string
|
id string
|
||||||
header *aclpb.Header
|
header *aclpb.TreeHeader
|
||||||
heads []string
|
heads []string
|
||||||
changes map[string]*aclpb.RawChange
|
changes map[string]*aclpb.RawTreeChangeWithId
|
||||||
|
|
||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewInMemoryTreeStorage(
|
func NewInMemoryTreeStorage(
|
||||||
treeId string,
|
treeId string,
|
||||||
header *aclpb.Header,
|
header *aclpb.TreeHeader,
|
||||||
heads []string,
|
heads []string,
|
||||||
changes []*aclpb.RawChange) (TreeStorage, error) {
|
changes []*aclpb.RawTreeChangeWithId) (TreeStorage, error) {
|
||||||
allChanges := make(map[string]*aclpb.RawChange)
|
allChanges := make(map[string]*aclpb.RawTreeChangeWithId)
|
||||||
for _, ch := range changes {
|
for _, ch := range changes {
|
||||||
allChanges[ch.Id] = ch
|
allChanges[ch.Id] = ch
|
||||||
}
|
}
|
||||||
@ -95,7 +95,7 @@ func (t *inMemoryTreeStorage) ID() (string, error) {
|
|||||||
return t.id, nil
|
return t.id, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *inMemoryTreeStorage) Header() (*aclpb.Header, error) {
|
func (t *inMemoryTreeStorage) Header() (*aclpb.TreeHeader, error) {
|
||||||
t.RLock()
|
t.RLock()
|
||||||
defer t.RUnlock()
|
defer t.RUnlock()
|
||||||
return t.header, nil
|
return t.header, nil
|
||||||
@ -118,7 +118,7 @@ func (t *inMemoryTreeStorage) SetHeads(heads []string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *inMemoryTreeStorage) AddRawChange(change *aclpb.RawChange) error {
|
func (t *inMemoryTreeStorage) AddRawChange(change *aclpb.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 +126,7 @@ func (t *inMemoryTreeStorage) AddRawChange(change *aclpb.RawChange) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *inMemoryTreeStorage) GetRawChange(ctx context.Context, changeId string) (*aclpb.RawChange, error) {
|
func (t *inMemoryTreeStorage) GetRawChange(ctx context.Context, changeId string) (*aclpb.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 {
|
||||||
|
|||||||
@ -7,8 +7,8 @@ import (
|
|||||||
|
|
||||||
type ListStorage interface {
|
type ListStorage interface {
|
||||||
Storage
|
Storage
|
||||||
Head() (*aclpb.RawRecord, error)
|
Head() (*aclpb.RawACLRecord, error)
|
||||||
|
|
||||||
GetRawRecord(ctx context.Context, id string) (*aclpb.RawRecord, error)
|
GetRawRecord(ctx context.Context, id string) (*aclpb.RawACLRecord, error)
|
||||||
AddRawRecord(ctx context.Context, rec *aclpb.RawRecord) error
|
AddRawRecord(ctx context.Context, rec *aclpb.RawACLRecord) error
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,15 +9,15 @@ var ErrUnknownTreeId = errors.New("tree does not exist")
|
|||||||
|
|
||||||
type TreeStorageCreatePayload struct {
|
type TreeStorageCreatePayload struct {
|
||||||
TreeId string
|
TreeId string
|
||||||
Header *aclpb.Header
|
Header *aclpb.TreeHeader
|
||||||
Changes []*aclpb.RawChange
|
Changes []*aclpb.RawTreeChangeWithId
|
||||||
Heads []string
|
Heads []string
|
||||||
}
|
}
|
||||||
|
|
||||||
type ACLListStorageCreatePayload struct {
|
type ACLListStorageCreatePayload struct {
|
||||||
ListId string
|
ListId string
|
||||||
Header *aclpb.Header
|
Header *aclpb.ACLHeader
|
||||||
Records []*aclpb.RawRecord
|
Records []*aclpb.RawACLRecord
|
||||||
}
|
}
|
||||||
|
|
||||||
type Provider interface {
|
type Provider interface {
|
||||||
|
|||||||
@ -10,8 +10,8 @@ type TreeStorage interface {
|
|||||||
Heads() ([]string, error)
|
Heads() ([]string, error)
|
||||||
SetHeads(heads []string) error
|
SetHeads(heads []string) error
|
||||||
|
|
||||||
AddRawChange(change *aclpb.RawChange) error
|
AddRawChange(change *aclpb.RawTreeChangeWithId) error
|
||||||
GetRawChange(ctx context.Context, recordID string) (*aclpb.RawChange, error)
|
GetRawChange(ctx context.Context, recordID string) (*aclpb.RawTreeChangeWithId, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type TreeStorageCreatorFunc = func(payload TreeStorageCreatePayload) (TreeStorage, error)
|
type TreeStorageCreatorFunc = func(payload TreeStorageCreatePayload) (TreeStorage, error)
|
||||||
|
|||||||
@ -19,8 +19,8 @@ import (
|
|||||||
|
|
||||||
type ACLListStorageBuilder struct {
|
type ACLListStorageBuilder struct {
|
||||||
aclList string
|
aclList string
|
||||||
records []*aclpb.Record
|
records []*aclpb.ACLRecord
|
||||||
rawRecords []*aclpb.RawRecord
|
rawRecords []*aclpb.RawACLRecord
|
||||||
indexes map[string]int
|
indexes map[string]int
|
||||||
keychain *Keychain
|
keychain *Keychain
|
||||||
header *aclpb.Header
|
header *aclpb.Header
|
||||||
@ -29,7 +29,7 @@ type ACLListStorageBuilder struct {
|
|||||||
|
|
||||||
func NewACLListStorageBuilder(keychain *Keychain) *ACLListStorageBuilder {
|
func NewACLListStorageBuilder(keychain *Keychain) *ACLListStorageBuilder {
|
||||||
return &ACLListStorageBuilder{
|
return &ACLListStorageBuilder{
|
||||||
records: make([]*aclpb.Record, 0),
|
records: make([]*aclpb.ACLRecord, 0),
|
||||||
indexes: make(map[string]int),
|
indexes: make(map[string]int),
|
||||||
keychain: keychain,
|
keychain: keychain,
|
||||||
}
|
}
|
||||||
@ -58,7 +58,7 @@ func NewACLListStorageBuilderFromFile(file string) (*ACLListStorageBuilder, erro
|
|||||||
return tb, nil
|
return tb, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *ACLListStorageBuilder) createRaw(rec *aclpb.Record) *aclpb.RawRecord {
|
func (t *ACLListStorageBuilder) createRaw(rec *aclpb.ACLRecord) *aclpb.RawACLRecord {
|
||||||
aclMarshaled, err := proto.Marshal(rec)
|
aclMarshaled, err := proto.Marshal(rec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("should be able to marshal final acl message!")
|
panic("should be able to marshal final acl message!")
|
||||||
@ -71,18 +71,18 @@ func (t *ACLListStorageBuilder) createRaw(rec *aclpb.Record) *aclpb.RawRecord {
|
|||||||
|
|
||||||
id, _ := cid.NewCIDFromBytes(aclMarshaled)
|
id, _ := cid.NewCIDFromBytes(aclMarshaled)
|
||||||
|
|
||||||
return &aclpb.RawRecord{
|
return &aclpb.RawACLRecord{
|
||||||
Payload: aclMarshaled,
|
Payload: aclMarshaled,
|
||||||
Signature: signature,
|
Signature: signature,
|
||||||
Id: id,
|
Id: id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *ACLListStorageBuilder) getRecord(idx int) *aclpb.RawRecord {
|
func (t *ACLListStorageBuilder) getRecord(idx int) *aclpb.RawACLRecord {
|
||||||
return t.rawRecords[idx]
|
return t.rawRecords[idx]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *ACLListStorageBuilder) Head() (*aclpb.RawRecord, error) {
|
func (t *ACLListStorageBuilder) Head() (*aclpb.RawACLRecord, error) {
|
||||||
return t.getRecord(len(t.records) - 1), nil
|
return t.getRecord(len(t.records) - 1), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,7 +90,7 @@ func (t *ACLListStorageBuilder) Header() (*aclpb.Header, error) {
|
|||||||
return t.header, nil
|
return t.header, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *ACLListStorageBuilder) GetRawRecord(ctx context.Context, id string) (*aclpb.RawRecord, error) {
|
func (t *ACLListStorageBuilder) GetRawRecord(ctx context.Context, id string) (*aclpb.RawACLRecord, error) {
|
||||||
recIdx, ok := t.indexes[id]
|
recIdx, ok := t.indexes[id]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("no such record")
|
return nil, fmt.Errorf("no such record")
|
||||||
@ -98,7 +98,7 @@ func (t *ACLListStorageBuilder) GetRawRecord(ctx context.Context, id string) (*a
|
|||||||
return t.getRecord(recIdx), nil
|
return t.getRecord(recIdx), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *ACLListStorageBuilder) AddRawRecord(ctx context.Context, rec *aclpb.RawRecord) error {
|
func (t *ACLListStorageBuilder) AddRawRecord(ctx context.Context, rec *aclpb.RawACLRecord) error {
|
||||||
panic("implement me")
|
panic("implement me")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,7 +106,7 @@ func (t *ACLListStorageBuilder) ID() (string, error) {
|
|||||||
return t.id, nil
|
return t.id, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *ACLListStorageBuilder) GetRawRecords() []*aclpb.RawRecord {
|
func (t *ACLListStorageBuilder) GetRawRecords() []*aclpb.RawACLRecord {
|
||||||
return t.rawRecords
|
return t.rawRecords
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,7 +132,7 @@ func (t *ACLListStorageBuilder) Parse(tree *YMLList) {
|
|||||||
t.createHeaderAndId()
|
t.createHeaderAndId()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *ACLListStorageBuilder) parseRecord(rec *Record, prevId string) *aclpb.Record {
|
func (t *ACLListStorageBuilder) parseRecord(rec *Record, prevId string) *aclpb.ACLRecord {
|
||||||
k := t.keychain.GetKey(rec.ReadKey).(*SymKey)
|
k := t.keychain.GetKey(rec.ReadKey).(*SymKey)
|
||||||
var aclChangeContents []*aclpb.ACLChangeACLContentValue
|
var aclChangeContents []*aclpb.ACLChangeACLContentValue
|
||||||
for _, ch := range rec.AclChanges {
|
for _, ch := range rec.AclChanges {
|
||||||
@ -144,7 +144,7 @@ func (t *ACLListStorageBuilder) parseRecord(rec *Record, prevId string) *aclpb.R
|
|||||||
}
|
}
|
||||||
bytes, _ := data.Marshal()
|
bytes, _ := data.Marshal()
|
||||||
|
|
||||||
return &aclpb.Record{
|
return &aclpb.ACLRecord{
|
||||||
PrevId: prevId,
|
PrevId: prevId,
|
||||||
Identity: t.keychain.GetIdentity(rec.Identity),
|
Identity: t.keychain.GetIdentity(rec.Identity),
|
||||||
Data: bytes,
|
Data: bytes,
|
||||||
@ -163,7 +163,7 @@ func (t *ACLListStorageBuilder) parseACLChange(ch *ACLChange) (convCh *aclpb.ACL
|
|||||||
|
|
||||||
convCh = &aclpb.ACLChangeACLContentValue{
|
convCh = &aclpb.ACLChangeACLContentValue{
|
||||||
Value: &aclpb.ACLChangeACLContentValueValueOfUserAdd{
|
Value: &aclpb.ACLChangeACLContentValueValueOfUserAdd{
|
||||||
UserAdd: &aclpb.ACLChangeUserAdd{
|
UserAdd: &aclpb.ACLUserPermissionsAdd{
|
||||||
Identity: t.keychain.GetIdentity(add.Identity),
|
Identity: t.keychain.GetIdentity(add.Identity),
|
||||||
EncryptionKey: rawKey,
|
EncryptionKey: rawKey,
|
||||||
EncryptedReadKeys: t.encryptReadKeys(add.EncryptedReadKeys, encKey),
|
EncryptedReadKeys: t.encryptReadKeys(add.EncryptedReadKeys, encKey),
|
||||||
@ -187,7 +187,7 @@ func (t *ACLListStorageBuilder) parseACLChange(ch *ACLChange) (convCh *aclpb.ACL
|
|||||||
|
|
||||||
convCh = &aclpb.ACLChangeACLContentValue{
|
convCh = &aclpb.ACLChangeACLContentValue{
|
||||||
Value: &aclpb.ACLChangeACLContentValueValueOfUserJoin{
|
Value: &aclpb.ACLChangeACLContentValueValueOfUserJoin{
|
||||||
UserJoin: &aclpb.ACLChangeUserJoin{
|
UserJoin: &aclpb.ACLUserPermissionsJoin{
|
||||||
Identity: t.keychain.GetIdentity(join.Identity),
|
Identity: t.keychain.GetIdentity(join.Identity),
|
||||||
EncryptionKey: rawKey,
|
EncryptionKey: rawKey,
|
||||||
AcceptSignature: signature,
|
AcceptSignature: signature,
|
||||||
@ -205,7 +205,7 @@ func (t *ACLListStorageBuilder) parseACLChange(ch *ACLChange) (convCh *aclpb.ACL
|
|||||||
|
|
||||||
convCh = &aclpb.ACLChangeACLContentValue{
|
convCh = &aclpb.ACLChangeACLContentValue{
|
||||||
Value: &aclpb.ACLChangeACLContentValueValueOfUserInvite{
|
Value: &aclpb.ACLChangeACLContentValueValueOfUserInvite{
|
||||||
UserInvite: &aclpb.ACLChangeUserInvite{
|
UserInvite: &aclpb.ACLUserPermissionsInvite{
|
||||||
AcceptPublicKey: rawAcceptKey,
|
AcceptPublicKey: rawAcceptKey,
|
||||||
EncryptPublicKey: rawEncKey,
|
EncryptPublicKey: rawEncKey,
|
||||||
EncryptedReadKeys: t.encryptReadKeys(invite.EncryptedReadKeys, encKey),
|
EncryptedReadKeys: t.encryptReadKeys(invite.EncryptedReadKeys, encKey),
|
||||||
@ -219,7 +219,7 @@ func (t *ACLListStorageBuilder) parseACLChange(ch *ACLChange) (convCh *aclpb.ACL
|
|||||||
|
|
||||||
convCh = &aclpb.ACLChangeACLContentValue{
|
convCh = &aclpb.ACLChangeACLContentValue{
|
||||||
Value: &aclpb.ACLChangeACLContentValueValueOfUserConfirm{
|
Value: &aclpb.ACLChangeACLContentValueValueOfUserConfirm{
|
||||||
UserConfirm: &aclpb.ACLChangeUserConfirm{
|
UserConfirm: &aclpb.ACLUserPermissionsConfirm{
|
||||||
Identity: t.keychain.GetIdentity(confirm.Identity),
|
Identity: t.keychain.GetIdentity(confirm.Identity),
|
||||||
UserAddId: confirm.UserAddId,
|
UserAddId: confirm.UserAddId,
|
||||||
},
|
},
|
||||||
@ -230,7 +230,7 @@ func (t *ACLListStorageBuilder) parseACLChange(ch *ACLChange) (convCh *aclpb.ACL
|
|||||||
|
|
||||||
convCh = &aclpb.ACLChangeACLContentValue{
|
convCh = &aclpb.ACLChangeACLContentValue{
|
||||||
Value: &aclpb.ACLChangeACLContentValueValueOfUserPermissionChange{
|
Value: &aclpb.ACLChangeACLContentValueValueOfUserPermissionChange{
|
||||||
UserPermissionChange: &aclpb.ACLChangeUserPermissionChange{
|
UserPermissionChange: &aclpb.ACLUserPermissionsPermissionChange{
|
||||||
Identity: t.keychain.GetIdentity(permissionChange.Identity),
|
Identity: t.keychain.GetIdentity(permissionChange.Identity),
|
||||||
Permissions: t.convertPermission(permissionChange.Permission),
|
Permissions: t.convertPermission(permissionChange.Permission),
|
||||||
},
|
},
|
||||||
@ -259,7 +259,7 @@ func (t *ACLListStorageBuilder) parseACLChange(ch *ACLChange) (convCh *aclpb.ACL
|
|||||||
|
|
||||||
convCh = &aclpb.ACLChangeACLContentValue{
|
convCh = &aclpb.ACLChangeACLContentValue{
|
||||||
Value: &aclpb.ACLChangeACLContentValueValueOfUserRemove{
|
Value: &aclpb.ACLChangeACLContentValueValueOfUserRemove{
|
||||||
UserRemove: &aclpb.ACLChangeUserRemove{
|
UserRemove: &aclpb.ACLUserPermissionsRemove{
|
||||||
Identity: t.keychain.GetIdentity(remove.RemovedIdentity),
|
Identity: t.keychain.GetIdentity(remove.RemovedIdentity),
|
||||||
ReadKeyReplaces: replaces,
|
ReadKeyReplaces: replaces,
|
||||||
},
|
},
|
||||||
@ -286,7 +286,7 @@ func (t *ACLListStorageBuilder) encryptReadKeys(keys []string, encKey encryption
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *ACLListStorageBuilder) convertPermission(perm string) aclpb.ACLChangeUserPermissions {
|
func (t *ACLListStorageBuilder) convertPermission(perm string) aclpb.ACLUserPermissions {
|
||||||
switch perm {
|
switch perm {
|
||||||
case "admin":
|
case "admin":
|
||||||
return aclpb.ACLChange_Admin
|
return aclpb.ACLChange_Admin
|
||||||
@ -299,7 +299,7 @@ func (t *ACLListStorageBuilder) convertPermission(perm string) aclpb.ACLChangeUs
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *ACLListStorageBuilder) traverseFromHead(f func(rec *aclpb.Record, id string) error) (err error) {
|
func (t *ACLListStorageBuilder) traverseFromHead(f func(rec *aclpb.ACLRecord, id string) error) (err error) {
|
||||||
for i := len(t.records) - 1; i >= 0; i-- {
|
for i := len(t.records) - 1; i >= 0; i-- {
|
||||||
err = f(t.records[i], t.rawRecords[i].Id)
|
err = f(t.records[i], t.rawRecords[i].Id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@ -33,7 +33,7 @@ func (t *ACLListStorageBuilder) Graph() (string, error) {
|
|||||||
graph.SetDir(true)
|
graph.SetDir(true)
|
||||||
var nodes = make(map[string]struct{})
|
var nodes = make(map[string]struct{})
|
||||||
|
|
||||||
var addNodes = func(r *aclpb.Record, id string) error {
|
var addNodes = func(r *aclpb.ACLRecord, id string) error {
|
||||||
style := "solid"
|
style := "solid"
|
||||||
|
|
||||||
var chSymbs []string
|
var chSymbs []string
|
||||||
@ -92,7 +92,7 @@ func (t *ACLListStorageBuilder) Graph() (string, error) {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var addLinks = func(r *aclpb.Record, id string) error {
|
var addLinks = func(r *aclpb.ACLRecord, id string) error {
|
||||||
if r.PrevId == "" {
|
if r.PrevId == "" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -58,24 +58,24 @@ func (m *PlainTextChange) XXX_DiscardUnknown() {
|
|||||||
|
|
||||||
var xxx_messageInfo_PlainTextChange proto.InternalMessageInfo
|
var xxx_messageInfo_PlainTextChange proto.InternalMessageInfo
|
||||||
|
|
||||||
type PlainTextChangeContent struct {
|
type PlainTextChange_Content struct {
|
||||||
// Types that are valid to be assigned to Value:
|
// Types that are valid to be assigned to Value:
|
||||||
// *PlainTextChangeContentValueOfTextAppend
|
// *PlainTextChange_Content_TextAppend
|
||||||
Value IsPlainTextChangeContentValue `protobuf_oneof:"value"`
|
Value isPlainTextChange_Content_Value `protobuf_oneof:"value"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PlainTextChangeContent) Reset() { *m = PlainTextChangeContent{} }
|
func (m *PlainTextChange_Content) Reset() { *m = PlainTextChange_Content{} }
|
||||||
func (m *PlainTextChangeContent) String() string { return proto.CompactTextString(m) }
|
func (m *PlainTextChange_Content) String() string { return proto.CompactTextString(m) }
|
||||||
func (*PlainTextChangeContent) ProtoMessage() {}
|
func (*PlainTextChange_Content) ProtoMessage() {}
|
||||||
func (*PlainTextChangeContent) Descriptor() ([]byte, []int) {
|
func (*PlainTextChange_Content) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor_37f33c266ada4318, []int{0, 0}
|
return fileDescriptor_37f33c266ada4318, []int{0, 0}
|
||||||
}
|
}
|
||||||
func (m *PlainTextChangeContent) XXX_Unmarshal(b []byte) error {
|
func (m *PlainTextChange_Content) XXX_Unmarshal(b []byte) error {
|
||||||
return m.Unmarshal(b)
|
return m.Unmarshal(b)
|
||||||
}
|
}
|
||||||
func (m *PlainTextChangeContent) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
func (m *PlainTextChange_Content) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
if deterministic {
|
if deterministic {
|
||||||
return xxx_messageInfo_PlainTextChangeContent.Marshal(b, m, deterministic)
|
return xxx_messageInfo_PlainTextChange_Content.Marshal(b, m, deterministic)
|
||||||
} else {
|
} else {
|
||||||
b = b[:cap(b)]
|
b = b[:cap(b)]
|
||||||
n, err := m.MarshalToSizedBuffer(b)
|
n, err := m.MarshalToSizedBuffer(b)
|
||||||
@ -85,67 +85,67 @@ func (m *PlainTextChangeContent) XXX_Marshal(b []byte, deterministic bool) ([]by
|
|||||||
return b[:n], nil
|
return b[:n], nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func (m *PlainTextChangeContent) XXX_Merge(src proto.Message) {
|
func (m *PlainTextChange_Content) XXX_Merge(src proto.Message) {
|
||||||
xxx_messageInfo_PlainTextChangeContent.Merge(m, src)
|
xxx_messageInfo_PlainTextChange_Content.Merge(m, src)
|
||||||
}
|
}
|
||||||
func (m *PlainTextChangeContent) XXX_Size() int {
|
func (m *PlainTextChange_Content) XXX_Size() int {
|
||||||
return m.Size()
|
return m.Size()
|
||||||
}
|
}
|
||||||
func (m *PlainTextChangeContent) XXX_DiscardUnknown() {
|
func (m *PlainTextChange_Content) XXX_DiscardUnknown() {
|
||||||
xxx_messageInfo_PlainTextChangeContent.DiscardUnknown(m)
|
xxx_messageInfo_PlainTextChange_Content.DiscardUnknown(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
var xxx_messageInfo_PlainTextChangeContent proto.InternalMessageInfo
|
var xxx_messageInfo_PlainTextChange_Content proto.InternalMessageInfo
|
||||||
|
|
||||||
type IsPlainTextChangeContentValue interface {
|
type isPlainTextChange_Content_Value interface {
|
||||||
IsPlainTextChangeContentValue()
|
isPlainTextChange_Content_Value()
|
||||||
MarshalTo([]byte) (int, error)
|
MarshalTo([]byte) (int, error)
|
||||||
Size() int
|
Size() int
|
||||||
}
|
}
|
||||||
|
|
||||||
type PlainTextChangeContentValueOfTextAppend struct {
|
type PlainTextChange_Content_TextAppend struct {
|
||||||
TextAppend *PlainTextChangeTextAppend `protobuf:"bytes,1,opt,name=textAppend,proto3,oneof" json:"textAppend,omitempty"`
|
TextAppend *PlainTextChange_TextAppend `protobuf:"bytes,1,opt,name=textAppend,proto3,oneof" json:"textAppend,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*PlainTextChangeContentValueOfTextAppend) IsPlainTextChangeContentValue() {}
|
func (*PlainTextChange_Content_TextAppend) isPlainTextChange_Content_Value() {}
|
||||||
|
|
||||||
func (m *PlainTextChangeContent) GetValue() IsPlainTextChangeContentValue {
|
func (m *PlainTextChange_Content) GetValue() isPlainTextChange_Content_Value {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
return m.Value
|
return m.Value
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PlainTextChangeContent) GetTextAppend() *PlainTextChangeTextAppend {
|
func (m *PlainTextChange_Content) GetTextAppend() *PlainTextChange_TextAppend {
|
||||||
if x, ok := m.GetValue().(*PlainTextChangeContentValueOfTextAppend); ok {
|
if x, ok := m.GetValue().(*PlainTextChange_Content_TextAppend); ok {
|
||||||
return x.TextAppend
|
return x.TextAppend
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX_OneofWrappers is for the internal use of the proto package.
|
// XXX_OneofWrappers is for the internal use of the proto package.
|
||||||
func (*PlainTextChangeContent) XXX_OneofWrappers() []interface{} {
|
func (*PlainTextChange_Content) XXX_OneofWrappers() []interface{} {
|
||||||
return []interface{}{
|
return []interface{}{
|
||||||
(*PlainTextChangeContentValueOfTextAppend)(nil),
|
(*PlainTextChange_Content_TextAppend)(nil),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type PlainTextChangeTextAppend struct {
|
type PlainTextChange_TextAppend struct {
|
||||||
Text string `protobuf:"bytes,1,opt,name=text,proto3" json:"text,omitempty"`
|
Text string `protobuf:"bytes,1,opt,name=text,proto3" json:"text,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PlainTextChangeTextAppend) Reset() { *m = PlainTextChangeTextAppend{} }
|
func (m *PlainTextChange_TextAppend) Reset() { *m = PlainTextChange_TextAppend{} }
|
||||||
func (m *PlainTextChangeTextAppend) String() string { return proto.CompactTextString(m) }
|
func (m *PlainTextChange_TextAppend) String() string { return proto.CompactTextString(m) }
|
||||||
func (*PlainTextChangeTextAppend) ProtoMessage() {}
|
func (*PlainTextChange_TextAppend) ProtoMessage() {}
|
||||||
func (*PlainTextChangeTextAppend) Descriptor() ([]byte, []int) {
|
func (*PlainTextChange_TextAppend) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor_37f33c266ada4318, []int{0, 1}
|
return fileDescriptor_37f33c266ada4318, []int{0, 1}
|
||||||
}
|
}
|
||||||
func (m *PlainTextChangeTextAppend) XXX_Unmarshal(b []byte) error {
|
func (m *PlainTextChange_TextAppend) XXX_Unmarshal(b []byte) error {
|
||||||
return m.Unmarshal(b)
|
return m.Unmarshal(b)
|
||||||
}
|
}
|
||||||
func (m *PlainTextChangeTextAppend) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
func (m *PlainTextChange_TextAppend) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
if deterministic {
|
if deterministic {
|
||||||
return xxx_messageInfo_PlainTextChangeTextAppend.Marshal(b, m, deterministic)
|
return xxx_messageInfo_PlainTextChange_TextAppend.Marshal(b, m, deterministic)
|
||||||
} else {
|
} else {
|
||||||
b = b[:cap(b)]
|
b = b[:cap(b)]
|
||||||
n, err := m.MarshalToSizedBuffer(b)
|
n, err := m.MarshalToSizedBuffer(b)
|
||||||
@ -155,41 +155,41 @@ func (m *PlainTextChangeTextAppend) XXX_Marshal(b []byte, deterministic bool) ([
|
|||||||
return b[:n], nil
|
return b[:n], nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func (m *PlainTextChangeTextAppend) XXX_Merge(src proto.Message) {
|
func (m *PlainTextChange_TextAppend) XXX_Merge(src proto.Message) {
|
||||||
xxx_messageInfo_PlainTextChangeTextAppend.Merge(m, src)
|
xxx_messageInfo_PlainTextChange_TextAppend.Merge(m, src)
|
||||||
}
|
}
|
||||||
func (m *PlainTextChangeTextAppend) XXX_Size() int {
|
func (m *PlainTextChange_TextAppend) XXX_Size() int {
|
||||||
return m.Size()
|
return m.Size()
|
||||||
}
|
}
|
||||||
func (m *PlainTextChangeTextAppend) XXX_DiscardUnknown() {
|
func (m *PlainTextChange_TextAppend) XXX_DiscardUnknown() {
|
||||||
xxx_messageInfo_PlainTextChangeTextAppend.DiscardUnknown(m)
|
xxx_messageInfo_PlainTextChange_TextAppend.DiscardUnknown(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
var xxx_messageInfo_PlainTextChangeTextAppend proto.InternalMessageInfo
|
var xxx_messageInfo_PlainTextChange_TextAppend proto.InternalMessageInfo
|
||||||
|
|
||||||
func (m *PlainTextChangeTextAppend) GetText() string {
|
func (m *PlainTextChange_TextAppend) GetText() string {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
return m.Text
|
return m.Text
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
type PlainTextChangeSnapshot struct {
|
type PlainTextChange_Snapshot struct {
|
||||||
Text string `protobuf:"bytes,1,opt,name=text,proto3" json:"text,omitempty"`
|
Text string `protobuf:"bytes,1,opt,name=text,proto3" json:"text,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PlainTextChangeSnapshot) Reset() { *m = PlainTextChangeSnapshot{} }
|
func (m *PlainTextChange_Snapshot) Reset() { *m = PlainTextChange_Snapshot{} }
|
||||||
func (m *PlainTextChangeSnapshot) String() string { return proto.CompactTextString(m) }
|
func (m *PlainTextChange_Snapshot) String() string { return proto.CompactTextString(m) }
|
||||||
func (*PlainTextChangeSnapshot) ProtoMessage() {}
|
func (*PlainTextChange_Snapshot) ProtoMessage() {}
|
||||||
func (*PlainTextChangeSnapshot) Descriptor() ([]byte, []int) {
|
func (*PlainTextChange_Snapshot) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor_37f33c266ada4318, []int{0, 2}
|
return fileDescriptor_37f33c266ada4318, []int{0, 2}
|
||||||
}
|
}
|
||||||
func (m *PlainTextChangeSnapshot) XXX_Unmarshal(b []byte) error {
|
func (m *PlainTextChange_Snapshot) XXX_Unmarshal(b []byte) error {
|
||||||
return m.Unmarshal(b)
|
return m.Unmarshal(b)
|
||||||
}
|
}
|
||||||
func (m *PlainTextChangeSnapshot) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
func (m *PlainTextChange_Snapshot) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
if deterministic {
|
if deterministic {
|
||||||
return xxx_messageInfo_PlainTextChangeSnapshot.Marshal(b, m, deterministic)
|
return xxx_messageInfo_PlainTextChange_Snapshot.Marshal(b, m, deterministic)
|
||||||
} else {
|
} else {
|
||||||
b = b[:cap(b)]
|
b = b[:cap(b)]
|
||||||
n, err := m.MarshalToSizedBuffer(b)
|
n, err := m.MarshalToSizedBuffer(b)
|
||||||
@ -199,42 +199,42 @@ func (m *PlainTextChangeSnapshot) XXX_Marshal(b []byte, deterministic bool) ([]b
|
|||||||
return b[:n], nil
|
return b[:n], nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func (m *PlainTextChangeSnapshot) XXX_Merge(src proto.Message) {
|
func (m *PlainTextChange_Snapshot) XXX_Merge(src proto.Message) {
|
||||||
xxx_messageInfo_PlainTextChangeSnapshot.Merge(m, src)
|
xxx_messageInfo_PlainTextChange_Snapshot.Merge(m, src)
|
||||||
}
|
}
|
||||||
func (m *PlainTextChangeSnapshot) XXX_Size() int {
|
func (m *PlainTextChange_Snapshot) XXX_Size() int {
|
||||||
return m.Size()
|
return m.Size()
|
||||||
}
|
}
|
||||||
func (m *PlainTextChangeSnapshot) XXX_DiscardUnknown() {
|
func (m *PlainTextChange_Snapshot) XXX_DiscardUnknown() {
|
||||||
xxx_messageInfo_PlainTextChangeSnapshot.DiscardUnknown(m)
|
xxx_messageInfo_PlainTextChange_Snapshot.DiscardUnknown(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
var xxx_messageInfo_PlainTextChangeSnapshot proto.InternalMessageInfo
|
var xxx_messageInfo_PlainTextChange_Snapshot proto.InternalMessageInfo
|
||||||
|
|
||||||
func (m *PlainTextChangeSnapshot) GetText() string {
|
func (m *PlainTextChange_Snapshot) GetText() string {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
return m.Text
|
return m.Text
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
type PlainTextChangeData struct {
|
type PlainTextChange_Data struct {
|
||||||
Content []*PlainTextChangeContent `protobuf:"bytes,1,rep,name=content,proto3" json:"content,omitempty"`
|
Content []*PlainTextChange_Content `protobuf:"bytes,1,rep,name=content,proto3" json:"content,omitempty"`
|
||||||
Snapshot *PlainTextChangeSnapshot `protobuf:"bytes,2,opt,name=snapshot,proto3" json:"snapshot,omitempty"`
|
Snapshot *PlainTextChange_Snapshot `protobuf:"bytes,2,opt,name=snapshot,proto3" json:"snapshot,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PlainTextChangeData) Reset() { *m = PlainTextChangeData{} }
|
func (m *PlainTextChange_Data) Reset() { *m = PlainTextChange_Data{} }
|
||||||
func (m *PlainTextChangeData) String() string { return proto.CompactTextString(m) }
|
func (m *PlainTextChange_Data) String() string { return proto.CompactTextString(m) }
|
||||||
func (*PlainTextChangeData) ProtoMessage() {}
|
func (*PlainTextChange_Data) ProtoMessage() {}
|
||||||
func (*PlainTextChangeData) Descriptor() ([]byte, []int) {
|
func (*PlainTextChange_Data) Descriptor() ([]byte, []int) {
|
||||||
return fileDescriptor_37f33c266ada4318, []int{0, 3}
|
return fileDescriptor_37f33c266ada4318, []int{0, 3}
|
||||||
}
|
}
|
||||||
func (m *PlainTextChangeData) XXX_Unmarshal(b []byte) error {
|
func (m *PlainTextChange_Data) XXX_Unmarshal(b []byte) error {
|
||||||
return m.Unmarshal(b)
|
return m.Unmarshal(b)
|
||||||
}
|
}
|
||||||
func (m *PlainTextChangeData) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
func (m *PlainTextChange_Data) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
if deterministic {
|
if deterministic {
|
||||||
return xxx_messageInfo_PlainTextChangeData.Marshal(b, m, deterministic)
|
return xxx_messageInfo_PlainTextChange_Data.Marshal(b, m, deterministic)
|
||||||
} else {
|
} else {
|
||||||
b = b[:cap(b)]
|
b = b[:cap(b)]
|
||||||
n, err := m.MarshalToSizedBuffer(b)
|
n, err := m.MarshalToSizedBuffer(b)
|
||||||
@ -244,26 +244,26 @@ func (m *PlainTextChangeData) XXX_Marshal(b []byte, deterministic bool) ([]byte,
|
|||||||
return b[:n], nil
|
return b[:n], nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func (m *PlainTextChangeData) XXX_Merge(src proto.Message) {
|
func (m *PlainTextChange_Data) XXX_Merge(src proto.Message) {
|
||||||
xxx_messageInfo_PlainTextChangeData.Merge(m, src)
|
xxx_messageInfo_PlainTextChange_Data.Merge(m, src)
|
||||||
}
|
}
|
||||||
func (m *PlainTextChangeData) XXX_Size() int {
|
func (m *PlainTextChange_Data) XXX_Size() int {
|
||||||
return m.Size()
|
return m.Size()
|
||||||
}
|
}
|
||||||
func (m *PlainTextChangeData) XXX_DiscardUnknown() {
|
func (m *PlainTextChange_Data) XXX_DiscardUnknown() {
|
||||||
xxx_messageInfo_PlainTextChangeData.DiscardUnknown(m)
|
xxx_messageInfo_PlainTextChange_Data.DiscardUnknown(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
var xxx_messageInfo_PlainTextChangeData proto.InternalMessageInfo
|
var xxx_messageInfo_PlainTextChange_Data proto.InternalMessageInfo
|
||||||
|
|
||||||
func (m *PlainTextChangeData) GetContent() []*PlainTextChangeContent {
|
func (m *PlainTextChange_Data) GetContent() []*PlainTextChange_Content {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
return m.Content
|
return m.Content
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PlainTextChangeData) GetSnapshot() *PlainTextChangeSnapshot {
|
func (m *PlainTextChange_Data) GetSnapshot() *PlainTextChange_Snapshot {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
return m.Snapshot
|
return m.Snapshot
|
||||||
}
|
}
|
||||||
@ -272,10 +272,10 @@ func (m *PlainTextChangeData) GetSnapshot() *PlainTextChangeSnapshot {
|
|||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
proto.RegisterType((*PlainTextChange)(nil), "anytype.PlainTextChange")
|
proto.RegisterType((*PlainTextChange)(nil), "anytype.PlainTextChange")
|
||||||
proto.RegisterType((*PlainTextChangeContent)(nil), "anytype.PlainTextChange.Content")
|
proto.RegisterType((*PlainTextChange_Content)(nil), "anytype.PlainTextChange.Content")
|
||||||
proto.RegisterType((*PlainTextChangeTextAppend)(nil), "anytype.PlainTextChange.TextAppend")
|
proto.RegisterType((*PlainTextChange_TextAppend)(nil), "anytype.PlainTextChange.TextAppend")
|
||||||
proto.RegisterType((*PlainTextChangeSnapshot)(nil), "anytype.PlainTextChange.Snapshot")
|
proto.RegisterType((*PlainTextChange_Snapshot)(nil), "anytype.PlainTextChange.Snapshot")
|
||||||
proto.RegisterType((*PlainTextChangeData)(nil), "anytype.PlainTextChange.Data")
|
proto.RegisterType((*PlainTextChange_Data)(nil), "anytype.PlainTextChange.Data")
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -326,7 +326,7 @@ func (m *PlainTextChange) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
|||||||
return len(dAtA) - i, nil
|
return len(dAtA) - i, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PlainTextChangeContent) Marshal() (dAtA []byte, err error) {
|
func (m *PlainTextChange_Content) Marshal() (dAtA []byte, err error) {
|
||||||
size := m.Size()
|
size := m.Size()
|
||||||
dAtA = make([]byte, size)
|
dAtA = make([]byte, size)
|
||||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||||
@ -336,12 +336,12 @@ func (m *PlainTextChangeContent) Marshal() (dAtA []byte, err error) {
|
|||||||
return dAtA[:n], nil
|
return dAtA[:n], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PlainTextChangeContent) MarshalTo(dAtA []byte) (int, error) {
|
func (m *PlainTextChange_Content) MarshalTo(dAtA []byte) (int, error) {
|
||||||
size := m.Size()
|
size := m.Size()
|
||||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PlainTextChangeContent) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
func (m *PlainTextChange_Content) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||||
i := len(dAtA)
|
i := len(dAtA)
|
||||||
_ = i
|
_ = i
|
||||||
var l int
|
var l int
|
||||||
@ -358,12 +358,12 @@ func (m *PlainTextChangeContent) MarshalToSizedBuffer(dAtA []byte) (int, error)
|
|||||||
return len(dAtA) - i, nil
|
return len(dAtA) - i, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PlainTextChangeContentValueOfTextAppend) MarshalTo(dAtA []byte) (int, error) {
|
func (m *PlainTextChange_Content_TextAppend) MarshalTo(dAtA []byte) (int, error) {
|
||||||
size := m.Size()
|
size := m.Size()
|
||||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PlainTextChangeContentValueOfTextAppend) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
func (m *PlainTextChange_Content_TextAppend) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||||
i := len(dAtA)
|
i := len(dAtA)
|
||||||
if m.TextAppend != nil {
|
if m.TextAppend != nil {
|
||||||
{
|
{
|
||||||
@ -379,7 +379,7 @@ func (m *PlainTextChangeContentValueOfTextAppend) MarshalToSizedBuffer(dAtA []by
|
|||||||
}
|
}
|
||||||
return len(dAtA) - i, nil
|
return len(dAtA) - i, nil
|
||||||
}
|
}
|
||||||
func (m *PlainTextChangeTextAppend) Marshal() (dAtA []byte, err error) {
|
func (m *PlainTextChange_TextAppend) Marshal() (dAtA []byte, err error) {
|
||||||
size := m.Size()
|
size := m.Size()
|
||||||
dAtA = make([]byte, size)
|
dAtA = make([]byte, size)
|
||||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||||
@ -389,12 +389,12 @@ func (m *PlainTextChangeTextAppend) Marshal() (dAtA []byte, err error) {
|
|||||||
return dAtA[:n], nil
|
return dAtA[:n], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PlainTextChangeTextAppend) MarshalTo(dAtA []byte) (int, error) {
|
func (m *PlainTextChange_TextAppend) MarshalTo(dAtA []byte) (int, error) {
|
||||||
size := m.Size()
|
size := m.Size()
|
||||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PlainTextChangeTextAppend) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
func (m *PlainTextChange_TextAppend) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||||
i := len(dAtA)
|
i := len(dAtA)
|
||||||
_ = i
|
_ = i
|
||||||
var l int
|
var l int
|
||||||
@ -409,7 +409,7 @@ func (m *PlainTextChangeTextAppend) MarshalToSizedBuffer(dAtA []byte) (int, erro
|
|||||||
return len(dAtA) - i, nil
|
return len(dAtA) - i, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PlainTextChangeSnapshot) Marshal() (dAtA []byte, err error) {
|
func (m *PlainTextChange_Snapshot) Marshal() (dAtA []byte, err error) {
|
||||||
size := m.Size()
|
size := m.Size()
|
||||||
dAtA = make([]byte, size)
|
dAtA = make([]byte, size)
|
||||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||||
@ -419,12 +419,12 @@ func (m *PlainTextChangeSnapshot) Marshal() (dAtA []byte, err error) {
|
|||||||
return dAtA[:n], nil
|
return dAtA[:n], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PlainTextChangeSnapshot) MarshalTo(dAtA []byte) (int, error) {
|
func (m *PlainTextChange_Snapshot) MarshalTo(dAtA []byte) (int, error) {
|
||||||
size := m.Size()
|
size := m.Size()
|
||||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PlainTextChangeSnapshot) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
func (m *PlainTextChange_Snapshot) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||||
i := len(dAtA)
|
i := len(dAtA)
|
||||||
_ = i
|
_ = i
|
||||||
var l int
|
var l int
|
||||||
@ -439,7 +439,7 @@ func (m *PlainTextChangeSnapshot) MarshalToSizedBuffer(dAtA []byte) (int, error)
|
|||||||
return len(dAtA) - i, nil
|
return len(dAtA) - i, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PlainTextChangeData) Marshal() (dAtA []byte, err error) {
|
func (m *PlainTextChange_Data) Marshal() (dAtA []byte, err error) {
|
||||||
size := m.Size()
|
size := m.Size()
|
||||||
dAtA = make([]byte, size)
|
dAtA = make([]byte, size)
|
||||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||||
@ -449,12 +449,12 @@ func (m *PlainTextChangeData) Marshal() (dAtA []byte, err error) {
|
|||||||
return dAtA[:n], nil
|
return dAtA[:n], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PlainTextChangeData) MarshalTo(dAtA []byte) (int, error) {
|
func (m *PlainTextChange_Data) MarshalTo(dAtA []byte) (int, error) {
|
||||||
size := m.Size()
|
size := m.Size()
|
||||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PlainTextChangeData) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
func (m *PlainTextChange_Data) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||||
i := len(dAtA)
|
i := len(dAtA)
|
||||||
_ = i
|
_ = i
|
||||||
var l int
|
var l int
|
||||||
@ -508,7 +508,7 @@ func (m *PlainTextChange) Size() (n int) {
|
|||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PlainTextChangeContent) Size() (n int) {
|
func (m *PlainTextChange_Content) Size() (n int) {
|
||||||
if m == nil {
|
if m == nil {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
@ -520,7 +520,7 @@ func (m *PlainTextChangeContent) Size() (n int) {
|
|||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PlainTextChangeContentValueOfTextAppend) Size() (n int) {
|
func (m *PlainTextChange_Content_TextAppend) Size() (n int) {
|
||||||
if m == nil {
|
if m == nil {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
@ -532,7 +532,7 @@ func (m *PlainTextChangeContentValueOfTextAppend) Size() (n int) {
|
|||||||
}
|
}
|
||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
func (m *PlainTextChangeTextAppend) Size() (n int) {
|
func (m *PlainTextChange_TextAppend) Size() (n int) {
|
||||||
if m == nil {
|
if m == nil {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
@ -545,7 +545,7 @@ func (m *PlainTextChangeTextAppend) Size() (n int) {
|
|||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PlainTextChangeSnapshot) Size() (n int) {
|
func (m *PlainTextChange_Snapshot) Size() (n int) {
|
||||||
if m == nil {
|
if m == nil {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
@ -558,7 +558,7 @@ func (m *PlainTextChangeSnapshot) Size() (n int) {
|
|||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *PlainTextChangeData) Size() (n int) {
|
func (m *PlainTextChange_Data) Size() (n int) {
|
||||||
if m == nil {
|
if m == nil {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
@ -633,7 +633,7 @@ func (m *PlainTextChange) Unmarshal(dAtA []byte) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (m *PlainTextChangeContent) Unmarshal(dAtA []byte) error {
|
func (m *PlainTextChange_Content) Unmarshal(dAtA []byte) error {
|
||||||
l := len(dAtA)
|
l := len(dAtA)
|
||||||
iNdEx := 0
|
iNdEx := 0
|
||||||
for iNdEx < l {
|
for iNdEx < l {
|
||||||
@ -691,11 +691,11 @@ func (m *PlainTextChangeContent) Unmarshal(dAtA []byte) error {
|
|||||||
if postIndex > l {
|
if postIndex > l {
|
||||||
return io.ErrUnexpectedEOF
|
return io.ErrUnexpectedEOF
|
||||||
}
|
}
|
||||||
v := &PlainTextChangeTextAppend{}
|
v := &PlainTextChange_TextAppend{}
|
||||||
if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
m.Value = &PlainTextChangeContentValueOfTextAppend{v}
|
m.Value = &PlainTextChange_Content_TextAppend{v}
|
||||||
iNdEx = postIndex
|
iNdEx = postIndex
|
||||||
default:
|
default:
|
||||||
iNdEx = preIndex
|
iNdEx = preIndex
|
||||||
@ -718,7 +718,7 @@ func (m *PlainTextChangeContent) Unmarshal(dAtA []byte) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (m *PlainTextChangeTextAppend) Unmarshal(dAtA []byte) error {
|
func (m *PlainTextChange_TextAppend) Unmarshal(dAtA []byte) error {
|
||||||
l := len(dAtA)
|
l := len(dAtA)
|
||||||
iNdEx := 0
|
iNdEx := 0
|
||||||
for iNdEx < l {
|
for iNdEx < l {
|
||||||
@ -800,7 +800,7 @@ func (m *PlainTextChangeTextAppend) Unmarshal(dAtA []byte) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (m *PlainTextChangeSnapshot) Unmarshal(dAtA []byte) error {
|
func (m *PlainTextChange_Snapshot) Unmarshal(dAtA []byte) error {
|
||||||
l := len(dAtA)
|
l := len(dAtA)
|
||||||
iNdEx := 0
|
iNdEx := 0
|
||||||
for iNdEx < l {
|
for iNdEx < l {
|
||||||
@ -882,7 +882,7 @@ func (m *PlainTextChangeSnapshot) Unmarshal(dAtA []byte) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (m *PlainTextChangeData) Unmarshal(dAtA []byte) error {
|
func (m *PlainTextChange_Data) Unmarshal(dAtA []byte) error {
|
||||||
l := len(dAtA)
|
l := len(dAtA)
|
||||||
iNdEx := 0
|
iNdEx := 0
|
||||||
for iNdEx < l {
|
for iNdEx < l {
|
||||||
@ -940,7 +940,7 @@ func (m *PlainTextChangeData) Unmarshal(dAtA []byte) error {
|
|||||||
if postIndex > l {
|
if postIndex > l {
|
||||||
return io.ErrUnexpectedEOF
|
return io.ErrUnexpectedEOF
|
||||||
}
|
}
|
||||||
m.Content = append(m.Content, &PlainTextChangeContent{})
|
m.Content = append(m.Content, &PlainTextChange_Content{})
|
||||||
if err := m.Content[len(m.Content)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
if err := m.Content[len(m.Content)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -975,7 +975,7 @@ func (m *PlainTextChangeData) Unmarshal(dAtA []byte) error {
|
|||||||
return io.ErrUnexpectedEOF
|
return io.ErrUnexpectedEOF
|
||||||
}
|
}
|
||||||
if m.Snapshot == nil {
|
if m.Snapshot == nil {
|
||||||
m.Snapshot = &PlainTextChangeSnapshot{}
|
m.Snapshot = &PlainTextChange_Snapshot{}
|
||||||
}
|
}
|
||||||
if err := m.Snapshot.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
if err := m.Snapshot.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@ -16,7 +16,7 @@ var (
|
|||||||
|
|
||||||
type ChangeContent struct {
|
type ChangeContent struct {
|
||||||
ChangesData proto.Marshaler
|
ChangesData proto.Marshaler
|
||||||
ACLData *aclpb.ACLChangeACLData
|
ACLData *aclpb.ACLData
|
||||||
Id string // TODO: this is just for testing, because id should be created automatically from content
|
Id string // TODO: this is just for testing, because id should be created automatically from content
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,8 +34,9 @@ type Change struct {
|
|||||||
visited bool
|
visited bool
|
||||||
branchesFinished bool
|
branchesFinished bool
|
||||||
|
|
||||||
Content *aclpb.Change
|
Content *aclpb.TreeChange
|
||||||
Sign []byte
|
Identity string
|
||||||
|
Sign []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ch *Change) ProtoChange() proto.Marshaler {
|
func (ch *Change) ProtoChange() proto.Marshaler {
|
||||||
@ -56,7 +57,7 @@ func (ch *Change) DecryptContents(key *symmetric.Key) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewChange(id string, ch *aclpb.Change, signature []byte) *Change {
|
func NewChange(id string, ch *aclpb.TreeChange, signature []byte) *Change {
|
||||||
return &Change{
|
return &Change{
|
||||||
Next: nil,
|
Next: nil,
|
||||||
PreviousIds: ch.TreeHeadIds,
|
PreviousIds: ch.TreeHeadIds,
|
||||||
@ -64,6 +65,7 @@ func NewChange(id string, ch *aclpb.Change, signature []byte) *Change {
|
|||||||
Content: ch,
|
Content: ch,
|
||||||
SnapshotId: ch.SnapshotBaseId,
|
SnapshotId: ch.SnapshotBaseId,
|
||||||
IsSnapshot: ch.IsSnapshot,
|
IsSnapshot: ch.IsSnapshot,
|
||||||
|
Identity: string(ch.Identity),
|
||||||
Sign: signature,
|
Sign: signature,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
package tree
|
package tree
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb"
|
"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/util/cid"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/cid"
|
||||||
@ -10,25 +11,24 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const componentBuilder = "tree.changebuilder"
|
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 string
|
identity []byte
|
||||||
isSnapshot bool
|
isSnapshot bool
|
||||||
signingKey signingkey.PrivKey
|
signingKey signingkey.PrivKey
|
||||||
readKey *symmetric.Key
|
readKey *symmetric.Key
|
||||||
content proto.Marshaler
|
content []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
type ChangeBuilder interface {
|
type ChangeBuilder interface {
|
||||||
ConvertFromRaw(rawChange *aclpb.RawChange) (ch *Change, err error)
|
ConvertFromRaw(rawIdChange *aclpb.RawTreeChangeWithId, verify bool) (ch *Change, err error)
|
||||||
ConvertFromRawAndVerify(rawChange *aclpb.RawChange) (ch *Change, err error)
|
BuildContent(payload BuilderContent) (ch *Change, raw *aclpb.RawTreeChangeWithId, err error)
|
||||||
BuildContent(payload BuilderContent) (ch *Change, raw *aclpb.RawChange, err error)
|
BuildRaw(ch *Change) (*aclpb.RawTreeChangeWithId, error)
|
||||||
BuildRaw(ch *Change) (*aclpb.RawChange, error)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type changeBuilder struct {
|
type changeBuilder struct {
|
||||||
@ -39,49 +39,55 @@ func newChangeBuilder(keys *common.Keychain) ChangeBuilder {
|
|||||||
return &changeBuilder{keys: keys}
|
return &changeBuilder{keys: keys}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *changeBuilder) ConvertFromRaw(rawChange *aclpb.RawChange) (ch *Change, err error) {
|
func (c *changeBuilder) ConvertFromRaw(rawIdChange *aclpb.RawTreeChangeWithId, verify bool) (ch *Change, err error) {
|
||||||
unmarshalled := &aclpb.Change{}
|
if rawIdChange.GetRawChange() == nil {
|
||||||
err = proto.Unmarshal(rawChange.Payload, unmarshalled)
|
err = ErrEmptyChange
|
||||||
if err != nil {
|
return
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ch = NewChange(rawChange.Id, unmarshalled, rawChange.Signature)
|
if verify {
|
||||||
|
// verifying ID
|
||||||
|
if !cid.VerifyCID(rawIdChange.RawChange, rawIdChange.Id) {
|
||||||
|
err = ErrIncorrectCID
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
raw := &aclpb.RawTreeChange{}
|
||||||
|
err = proto.Unmarshal(rawIdChange.GetRawChange(), raw)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if verify {
|
||||||
|
identityKey, err := c.keys.GetOrAdd(ch.Identity)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// verifying signature
|
||||||
|
res, err := identityKey.Verify(raw.Payload, raw.Signature)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !res {
|
||||||
|
err = ErrIncorrectSignature
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unmarshalled := &aclpb.TreeChange{}
|
||||||
|
err = proto.Unmarshal(raw.Payload, unmarshalled)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ch = NewChange(rawIdChange.Id, unmarshalled, raw.Signature)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *changeBuilder) ConvertFromRawAndVerify(rawChange *aclpb.RawChange) (ch *Change, err error) {
|
func (c *changeBuilder) BuildContent(payload BuilderContent) (ch *Change, rawIdChange *aclpb.RawTreeChangeWithId, err error) {
|
||||||
unmarshalled := &aclpb.Change{}
|
change := &aclpb.TreeChange{
|
||||||
ch, err = c.ConvertFromRaw(rawChange)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
identityKey, err := c.keys.GetOrAdd(unmarshalled.Identity)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// verifying signature
|
|
||||||
res, err := identityKey.Verify(rawChange.Payload, rawChange.Signature)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !res {
|
|
||||||
err = ErrIncorrectSignature
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// verifying ID
|
|
||||||
if !cid.VerifyCID(rawChange.Payload, rawChange.Id) {
|
|
||||||
err = ErrIncorrectCID
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *changeBuilder) BuildContent(payload BuilderContent) (ch *Change, raw *aclpb.RawChange, err error) {
|
|
||||||
aclChange := &aclpb.Change{
|
|
||||||
TreeHeadIds: payload.treeHeadIds,
|
TreeHeadIds: payload.treeHeadIds,
|
||||||
AclHeadId: payload.aclHeadId,
|
AclHeadId: payload.aclHeadId,
|
||||||
SnapshotBaseId: payload.snapshotBaseId,
|
SnapshotBaseId: payload.snapshotBaseId,
|
||||||
@ -90,53 +96,65 @@ func (c *changeBuilder) BuildContent(payload BuilderContent) (ch *Change, raw *a
|
|||||||
Identity: payload.identity,
|
Identity: payload.identity,
|
||||||
IsSnapshot: payload.isSnapshot,
|
IsSnapshot: payload.isSnapshot,
|
||||||
}
|
}
|
||||||
marshalledData, err := payload.content.Marshal()
|
|
||||||
|
encrypted, err := payload.readKey.Encrypt(payload.content)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
change.ChangesData = encrypted
|
||||||
|
|
||||||
|
marshalledChange, err := proto.Marshal(change)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
encrypted, err := payload.readKey.Encrypt(marshalledData)
|
signature, err := payload.signingKey.Sign(marshalledChange)
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
aclChange.ChangesData = encrypted
|
|
||||||
|
|
||||||
fullMarshalledChange, err := proto.Marshal(aclChange)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
signature, err := payload.signingKey.Sign(fullMarshalledChange)
|
raw := &aclpb.RawTreeChange{
|
||||||
|
Payload: marshalledChange,
|
||||||
|
Signature: signature,
|
||||||
|
}
|
||||||
|
|
||||||
|
marshalledRawChange, err := proto.Marshal(raw)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
id, err := cid.NewCIDFromBytes(fullMarshalledChange)
|
id, err := cid.NewCIDFromBytes(marshalledRawChange)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ch = NewChange(id, aclChange, signature)
|
ch = NewChange(id, change, signature)
|
||||||
ch.ParsedModel = payload.content
|
ch.ParsedModel = payload.content
|
||||||
|
|
||||||
raw = &aclpb.RawChange{
|
rawIdChange = &aclpb.RawTreeChangeWithId{
|
||||||
Payload: fullMarshalledChange,
|
RawChange: marshalledRawChange,
|
||||||
Signature: signature,
|
|
||||||
Id: id,
|
Id: id,
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *changeBuilder) BuildRaw(ch *Change) (raw *aclpb.RawChange, err error) {
|
func (c *changeBuilder) BuildRaw(ch *Change) (raw *aclpb.RawTreeChangeWithId, err error) {
|
||||||
var marshalled []byte
|
var marshalled []byte
|
||||||
marshalled, err = ch.Content.Marshal()
|
marshalled, err = ch.Content.Marshal()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
raw = &aclpb.RawChange{
|
marshalledRawChange, err := proto.Marshal(&aclpb.RawTreeChange{
|
||||||
Payload: marshalled,
|
Payload: marshalled,
|
||||||
Signature: ch.Signature(),
|
Signature: ch.Sign,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
raw = &aclpb.RawTreeChangeWithId{
|
||||||
|
RawChange: marshalledRawChange,
|
||||||
Id: ch.Id,
|
Id: ch.Id,
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
|||||||
@ -48,7 +48,7 @@ func (v *objectTreeValidator) validateChange(tree *Tree, aclList list.ACLList, c
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if perm.Permission != aclpb.ACLChange_Writer && perm.Permission != aclpb.ACLChange_Admin {
|
if perm.Permission != aclpb.ACLUserPermissions_Writer && perm.Permission != aclpb.ACLUserPermissions_Admin {
|
||||||
err = list.ErrInsufficientPermissions
|
err = list.ErrInsufficientPermissions
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,8 +8,6 @@ import (
|
|||||||
"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/keys/symmetric"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/symmetric"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/slice"
|
|
||||||
"go.uber.org/zap"
|
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -34,7 +32,7 @@ type AddResultSummary int
|
|||||||
type AddResult struct {
|
type AddResult struct {
|
||||||
OldHeads []string
|
OldHeads []string
|
||||||
Heads []string
|
Heads []string
|
||||||
Added []*aclpb.RawChange
|
Added []*aclpb.RawTreeChangeWithId
|
||||||
|
|
||||||
Mode Mode
|
Mode Mode
|
||||||
}
|
}
|
||||||
@ -46,7 +44,7 @@ type ObjectTree interface {
|
|||||||
RWLocker
|
RWLocker
|
||||||
|
|
||||||
ID() string
|
ID() string
|
||||||
Header() *aclpb.Header
|
Header() *aclpb.TreeHeader
|
||||||
Heads() []string
|
Heads() []string
|
||||||
Root() *Change
|
Root() *Change
|
||||||
HasChange(string) bool
|
HasChange(string) bool
|
||||||
@ -55,13 +53,13 @@ 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.RawChange, error)
|
ChangesAfterCommonSnapshot(snapshotPath, heads []string) ([]*aclpb.RawTreeChangeWithId, error)
|
||||||
|
|
||||||
Storage() storage.TreeStorage
|
Storage() storage.TreeStorage
|
||||||
DebugDump() (string, error)
|
DebugDump() (string, error)
|
||||||
|
|
||||||
AddContent(ctx context.Context, content SignableChangeContent) (*aclpb.RawChange, error)
|
AddContent(ctx context.Context, content SignableChangeContent) (*aclpb.RawTreeChangeWithId, error)
|
||||||
AddRawChanges(ctx context.Context, changes ...*aclpb.RawChange) (AddResult, error)
|
AddRawChanges(ctx context.Context, changes ...*aclpb.RawTreeChangeWithId) (AddResult, error)
|
||||||
|
|
||||||
Close() error
|
Close() error
|
||||||
}
|
}
|
||||||
@ -76,13 +74,13 @@ type objectTree struct {
|
|||||||
aclList list.ACLList
|
aclList list.ACLList
|
||||||
|
|
||||||
id string
|
id string
|
||||||
header *aclpb.Header
|
header *aclpb.TreeHeader
|
||||||
tree *Tree
|
tree *Tree
|
||||||
|
|
||||||
keys map[uint64]*symmetric.Key
|
keys map[uint64]*symmetric.Key
|
||||||
|
|
||||||
// buffers
|
// buffers
|
||||||
difSnapshotBuf []*aclpb.RawChange
|
difSnapshotBuf []*aclpb.RawTreeChangeWithId
|
||||||
tmpChangesBuf []*Change
|
tmpChangesBuf []*Change
|
||||||
newSnapshotsBuf []*Change
|
newSnapshotsBuf []*Change
|
||||||
notSeenIdxBuf []int
|
notSeenIdxBuf []int
|
||||||
@ -121,65 +119,6 @@ func defaultObjectTreeDeps(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildObjectTree(deps objectTreeDeps) (ObjectTree, error) {
|
|
||||||
objTree := &objectTree{
|
|
||||||
treeStorage: deps.treeStorage,
|
|
||||||
updateListener: deps.updateListener,
|
|
||||||
treeBuilder: deps.treeBuilder,
|
|
||||||
validator: deps.validator,
|
|
||||||
aclList: deps.aclList,
|
|
||||||
changeBuilder: deps.changeBuilder,
|
|
||||||
rawChangeLoader: deps.rawChangeLoader,
|
|
||||||
tree: nil,
|
|
||||||
keys: make(map[uint64]*symmetric.Key),
|
|
||||||
tmpChangesBuf: make([]*Change, 0, 10),
|
|
||||||
difSnapshotBuf: make([]*aclpb.RawChange, 0, 10),
|
|
||||||
notSeenIdxBuf: make([]int, 0, 10),
|
|
||||||
newSnapshotsBuf: make([]*Change, 0, 10),
|
|
||||||
}
|
|
||||||
|
|
||||||
err := objTree.rebuildFromStorage(nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
storageHeads, err := objTree.treeStorage.Heads()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// comparing rebuilt heads with heads in storage
|
|
||||||
// in theory it can happen that we didn't set heads because the process has crashed
|
|
||||||
// therefore we want to set them later
|
|
||||||
if !slice.UnsortedEquals(storageHeads, objTree.tree.Heads()) {
|
|
||||||
log.With(zap.Strings("storage", storageHeads), zap.Strings("rebuilt", objTree.tree.Heads())).
|
|
||||||
Errorf("the heads in storage and objTree are different")
|
|
||||||
err = objTree.treeStorage.SetHeads(objTree.tree.Heads())
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
objTree.id, err = objTree.treeStorage.ID()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
objTree.header, err = objTree.treeStorage.Header()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if objTree.updateListener != nil {
|
|
||||||
objTree.updateListener.Rebuild(objTree)
|
|
||||||
}
|
|
||||||
|
|
||||||
return objTree, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func BuildObjectTree(treeStorage storage.TreeStorage, listener ObjectTreeUpdateListener, aclList list.ACLList) (ObjectTree, error) {
|
|
||||||
deps := defaultObjectTreeDeps(treeStorage, listener, aclList)
|
|
||||||
return buildObjectTree(deps)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ot *objectTree) rebuildFromStorage(newChanges []*Change) (err error) {
|
func (ot *objectTree) rebuildFromStorage(newChanges []*Change) (err error) {
|
||||||
ot.treeBuilder.Reset()
|
ot.treeBuilder.Reset()
|
||||||
|
|
||||||
@ -201,7 +140,7 @@ func (ot *objectTree) ID() string {
|
|||||||
return ot.id
|
return ot.id
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ot *objectTree) Header() *aclpb.Header {
|
func (ot *objectTree) Header() *aclpb.TreeHeader {
|
||||||
return ot.header
|
return ot.header
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -209,7 +148,7 @@ func (ot *objectTree) Storage() storage.TreeStorage {
|
|||||||
return ot.treeStorage
|
return ot.treeStorage
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ot *objectTree) AddContent(ctx context.Context, content SignableChangeContent) (rawChange *aclpb.RawChange, err error) {
|
func (ot *objectTree) AddContent(ctx context.Context, content SignableChangeContent) (rawChange *aclpb.RawTreeChangeWithId, err error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if err == nil && ot.updateListener != nil {
|
if err == nil && ot.updateListener != nil {
|
||||||
ot.updateListener.Update(ot)
|
ot.updateListener.Update(ot)
|
||||||
@ -258,12 +197,12 @@ func (ot *objectTree) prepareBuilderContent(content SignableChangeContent) (cnt
|
|||||||
isSnapshot: content.IsSnapshot,
|
isSnapshot: content.IsSnapshot,
|
||||||
signingKey: content.Key,
|
signingKey: content.Key,
|
||||||
readKey: readKey,
|
readKey: readKey,
|
||||||
content: content.Proto,
|
content: content.Data,
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ot *objectTree) AddRawChanges(ctx context.Context, rawChanges ...*aclpb.RawChange) (addResult AddResult, err error) {
|
func (ot *objectTree) AddRawChanges(ctx context.Context, rawChanges ...*aclpb.RawTreeChangeWithId) (addResult AddResult, err error) {
|
||||||
var mode Mode
|
var mode Mode
|
||||||
mode, addResult, err = ot.addRawChanges(ctx, rawChanges...)
|
mode, addResult, err = ot.addRawChanges(ctx, rawChanges...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -302,7 +241,7 @@ func (ot *objectTree) AddRawChanges(ctx context.Context, rawChanges ...*aclpb.Ra
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ot *objectTree) addRawChanges(ctx context.Context, rawChanges ...*aclpb.RawChange) (mode Mode, addResult AddResult, err error) {
|
func (ot *objectTree) addRawChanges(ctx context.Context, rawChanges ...*aclpb.RawTreeChangeWithId) (mode Mode, 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]
|
||||||
@ -329,7 +268,7 @@ func (ot *objectTree) addRawChanges(ctx context.Context, rawChanges ...*aclpb.Ra
|
|||||||
}
|
}
|
||||||
|
|
||||||
var change *Change
|
var change *Change
|
||||||
change, err = ot.changeBuilder.ConvertFromRawAndVerify(ch)
|
change, err = ot.changeBuilder.ConvertFromRaw(ch, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -354,7 +293,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.RawChange, err error) {
|
getAddedChanges := func(toConvert []*Change) (added []*aclpb.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
|
||||||
@ -379,7 +318,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.RawChange
|
var raw *aclpb.RawTreeChangeWithId
|
||||||
raw, err = ot.changeBuilder.BuildRaw(ch)
|
raw, err = ot.changeBuilder.BuildRaw(ch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@ -421,7 +360,7 @@ func (ot *objectTree) addRawChanges(ctx context.Context, rawChanges ...*aclpb.Ra
|
|||||||
ot.rebuildFromStorage(nil)
|
ot.rebuildFromStorage(nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var added []*aclpb.RawChange
|
var added []*aclpb.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 {
|
||||||
@ -457,7 +396,7 @@ func (ot *objectTree) addRawChanges(ctx context.Context, rawChanges ...*aclpb.Ra
|
|||||||
err = ErrHasInvalidChanges
|
err = ErrHasInvalidChanges
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var added []*aclpb.RawChange
|
var added []*aclpb.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
|
||||||
@ -553,7 +492,7 @@ func (ot *objectTree) SnapshotPath() []string {
|
|||||||
return path
|
return path
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ot *objectTree) ChangesAfterCommonSnapshot(theirPath, theirHeads []string) ([]*aclpb.RawChange, error) {
|
func (ot *objectTree) ChangesAfterCommonSnapshot(theirPath, theirHeads []string) ([]*aclpb.RawTreeChangeWithId, error) {
|
||||||
var (
|
var (
|
||||||
needFullDocument = len(theirPath) == 0
|
needFullDocument = len(theirPath) == 0
|
||||||
ourPath = ot.SnapshotPath()
|
ourPath = ot.SnapshotPath()
|
||||||
@ -577,11 +516,11 @@ func (ot *objectTree) ChangesAfterCommonSnapshot(theirPath, theirHeads []string)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ot *objectTree) getChangesFromTree(theirHeads []string) (rawChanges []*aclpb.RawChange, err error) {
|
func (ot *objectTree) getChangesFromTree(theirHeads []string) (rawChanges []*aclpb.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.RawChange, err error) {
|
func (ot *objectTree) getChangesFromDB(commonSnapshot string, theirHeads []string) (rawChanges []*aclpb.RawTreeChangeWithId, err error) {
|
||||||
return ot.rawChangeLoader.LoadFromStorage(commonSnapshot, ot.tree.headIds, theirHeads)
|
return ot.rawChangeLoader.LoadFromStorage(commonSnapshot, ot.tree.headIds, theirHeads)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -15,7 +15,7 @@ import (
|
|||||||
type mockChangeCreator struct{}
|
type mockChangeCreator struct{}
|
||||||
|
|
||||||
func (c *mockChangeCreator) createRaw(id, aclId, snapshotId string, isSnapshot bool, prevIds ...string) *aclpb.RawChange {
|
func (c *mockChangeCreator) createRaw(id, aclId, snapshotId string, isSnapshot bool, prevIds ...string) *aclpb.RawChange {
|
||||||
aclChange := &aclpb.Change{
|
aclChange := &aclpb.TreeChange{
|
||||||
TreeHeadIds: prevIds,
|
TreeHeadIds: prevIds,
|
||||||
AclHeadId: aclId,
|
AclHeadId: aclId,
|
||||||
SnapshotBaseId: snapshotId,
|
SnapshotBaseId: snapshotId,
|
||||||
@ -23,22 +23,27 @@ func (c *mockChangeCreator) createRaw(id, aclId, snapshotId string, isSnapshot b
|
|||||||
IsSnapshot: isSnapshot,
|
IsSnapshot: isSnapshot,
|
||||||
}
|
}
|
||||||
res, _ := aclChange.Marshal()
|
res, _ := aclChange.Marshal()
|
||||||
return &aclpb.RawChange{
|
|
||||||
|
raw := &aclpb.RawTreeChange{
|
||||||
Payload: res,
|
Payload: res,
|
||||||
Signature: nil,
|
Signature: nil,
|
||||||
|
}
|
||||||
|
rawMarshalled, _ := raw.Marshal()
|
||||||
|
|
||||||
|
return &aclpb.RawTreeChangeWithId{
|
||||||
|
RawChange: rawMarshalled,
|
||||||
Id: id,
|
Id: id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *mockChangeCreator) createNewTreeStorage(treeId, aclListId, aclHeadId, firstChangeId string) storage.TreeStorage {
|
func (c *mockChangeCreator) createNewTreeStorage(treeId, aclListId, aclHeadId, firstChangeId string) storage.TreeStorage {
|
||||||
firstChange := c.createRaw(firstChangeId, aclHeadId, "", true)
|
firstChange := c.createRaw(firstChangeId, aclHeadId, "", true)
|
||||||
header := &aclpb.Header{
|
header := &aclpb.TreeHeader{
|
||||||
FirstId: firstChangeId,
|
FirstId: firstChangeId,
|
||||||
AclListId: aclListId,
|
AclId: aclListId,
|
||||||
WorkspaceId: "",
|
TreeHeaderType: aclpb.TreeHeaderType_Object,
|
||||||
DocType: aclpb.Header_DocTree,
|
|
||||||
}
|
}
|
||||||
treeStorage, _ := storage.NewInMemoryTreeStorage(treeId, header, []string{firstChangeId}, []*aclpb.RawChange{firstChange})
|
treeStorage, _ := storage.NewInMemoryTreeStorage(treeId, header, []string{firstChangeId}, []*aclpb.RawTreeChangeWithId{firstChange})
|
||||||
return treeStorage
|
return treeStorage
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
161
pkg/acl/tree/objecttreefactory.go
Normal file
161
pkg/acl/tree/objecttreefactory.go
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
package tree
|
||||||
|
|
||||||
|
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/storage"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/cid"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/symmetric"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/slice"
|
||||||
|
"github.com/gogo/protobuf/proto"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ObjectTreeCreatePayload struct {
|
||||||
|
AccountData *account.AccountData
|
||||||
|
HeaderData []byte
|
||||||
|
ChangeData []byte
|
||||||
|
TreeType aclpb.TreeHeaderType
|
||||||
|
}
|
||||||
|
|
||||||
|
func BuildObjectTree(treeStorage storage.TreeStorage, listener ObjectTreeUpdateListener, aclList list.ACLList) (ObjectTree, error) {
|
||||||
|
deps := defaultObjectTreeDeps(treeStorage, listener, aclList)
|
||||||
|
return buildObjectTree(deps)
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateObjectTree(
|
||||||
|
payload ObjectTreeCreatePayload,
|
||||||
|
listener ObjectTreeUpdateListener,
|
||||||
|
aclList list.ACLList,
|
||||||
|
createStorage storage.TreeStorageCreatorFunc) (objTree ObjectTree, err error) {
|
||||||
|
aclList.RLock()
|
||||||
|
var (
|
||||||
|
deps = defaultObjectTreeDeps(nil, listener, aclList)
|
||||||
|
state = aclList.ACLState()
|
||||||
|
aclId = aclList.ID()
|
||||||
|
aclHeadId = aclList.Head().Id
|
||||||
|
readKeyHash = state.CurrentReadKeyHash()
|
||||||
|
)
|
||||||
|
readKey, err := state.CurrentReadKey()
|
||||||
|
aclList.RUnlock()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// create first change
|
||||||
|
cnt := BuilderContent{
|
||||||
|
treeHeadIds: nil,
|
||||||
|
aclHeadId: aclHeadId,
|
||||||
|
snapshotBaseId: "",
|
||||||
|
currentReadKeyHash: readKeyHash,
|
||||||
|
isSnapshot: true,
|
||||||
|
readKey: readKey,
|
||||||
|
identity: payload.AccountData.Identity,
|
||||||
|
signingKey: payload.AccountData.SignKey,
|
||||||
|
content: payload.ChangeData,
|
||||||
|
}
|
||||||
|
|
||||||
|
_, raw, err := deps.changeBuilder.BuildContent(cnt)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// create header
|
||||||
|
header, id, err := createTreeHeaderAndId(
|
||||||
|
raw,
|
||||||
|
payload.TreeType,
|
||||||
|
aclId,
|
||||||
|
payload.AccountData.Identity,
|
||||||
|
payload.HeaderData)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// create storage
|
||||||
|
st, err := createStorage(storage.TreeStorageCreatePayload{
|
||||||
|
TreeId: id,
|
||||||
|
Header: header,
|
||||||
|
Changes: []*aclpb.RawTreeChangeWithId{raw},
|
||||||
|
Heads: []string{raw.Id},
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
deps.treeStorage = st
|
||||||
|
return buildObjectTree(deps)
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildObjectTree(deps objectTreeDeps) (ObjectTree, error) {
|
||||||
|
objTree := &objectTree{
|
||||||
|
treeStorage: deps.treeStorage,
|
||||||
|
updateListener: deps.updateListener,
|
||||||
|
treeBuilder: deps.treeBuilder,
|
||||||
|
validator: deps.validator,
|
||||||
|
aclList: deps.aclList,
|
||||||
|
changeBuilder: deps.changeBuilder,
|
||||||
|
rawChangeLoader: deps.rawChangeLoader,
|
||||||
|
tree: nil,
|
||||||
|
keys: make(map[uint64]*symmetric.Key),
|
||||||
|
tmpChangesBuf: make([]*Change, 0, 10),
|
||||||
|
difSnapshotBuf: make([]*aclpb.RawTreeChangeWithId, 0, 10),
|
||||||
|
notSeenIdxBuf: make([]int, 0, 10),
|
||||||
|
newSnapshotsBuf: make([]*Change, 0, 10),
|
||||||
|
}
|
||||||
|
|
||||||
|
err := objTree.rebuildFromStorage(nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
storageHeads, err := objTree.treeStorage.Heads()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// comparing rebuilt heads with heads in storage
|
||||||
|
// in theory it can happen that we didn't set heads because the process has crashed
|
||||||
|
// therefore we want to set them later
|
||||||
|
if !slice.UnsortedEquals(storageHeads, objTree.tree.Heads()) {
|
||||||
|
log.With(zap.Strings("storage", storageHeads), zap.Strings("rebuilt", objTree.tree.Heads())).
|
||||||
|
Errorf("the heads in storage and objTree are different")
|
||||||
|
err = objTree.treeStorage.SetHeads(objTree.tree.Heads())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
objTree.id, err = objTree.treeStorage.ID()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
objTree.header, err = objTree.treeStorage.Header()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
@ -18,7 +18,7 @@ type rawChangeLoader struct {
|
|||||||
|
|
||||||
type rawCacheEntry struct {
|
type rawCacheEntry struct {
|
||||||
change *Change
|
change *Change
|
||||||
rawChange *aclpb.RawChange
|
rawChange *aclpb.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.RawChange, error) {
|
func (r *rawChangeLoader) LoadFromTree(t *Tree, breakpoints []string) ([]*aclpb.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.RawChange, err error) {
|
convert := func(chs []*Change) (rawChanges []*aclpb.RawTreeChangeWithId, err error) {
|
||||||
for _, ch := range chs {
|
for _, ch := range chs {
|
||||||
var raw *aclpb.RawChange
|
var raw *aclpb.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.RawChange, error) {
|
func (r *rawChangeLoader) LoadFromStorage(commonSnapshot string, heads, breakpoints []string) ([]*aclpb.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.RawChange
|
var buffer []*aclpb.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.RawChange) bool {
|
buffer = discardFromSlice(buffer, func(change *aclpb.RawTreeChangeWithId) bool {
|
||||||
return change == nil
|
return change == nil
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -219,7 +219,7 @@ func (r *rawChangeLoader) loadEntry(id string) (entry rawCacheEntry, err error)
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
change, err := r.changeBuilder.ConvertFromRaw(rawChange)
|
change, err := r.changeBuilder.ConvertFromRaw(rawChange, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,12 +2,11 @@ package tree
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/asymmetric/signingkey"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/asymmetric/signingkey"
|
||||||
"github.com/gogo/protobuf/proto"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type SignableChangeContent struct {
|
type SignableChangeContent struct {
|
||||||
Proto proto.Marshaler
|
Data []byte
|
||||||
Key signingkey.PrivKey
|
Key signingkey.PrivKey
|
||||||
Identity string
|
Identity []byte
|
||||||
IsSnapshot bool
|
IsSnapshot bool
|
||||||
}
|
}
|
||||||
|
|||||||
91
pkg/acl/tree/tests/benches_test.go
Normal file
91
pkg/acl/tree/tests/benches_test.go
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
package tests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"math/rand"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func BenchmarkHashes(b *testing.B) {
|
||||||
|
genRandomBytes := func() [][]byte {
|
||||||
|
var res [][]byte
|
||||||
|
s := rand.NewSource(time.Now().Unix())
|
||||||
|
r := rand.New(s)
|
||||||
|
for i := 0; i < 10000; i++ {
|
||||||
|
var newBytes []byte
|
||||||
|
for j := 0; j < 64; j++ {
|
||||||
|
newBytes = append(newBytes, byte(r.Intn(256)))
|
||||||
|
}
|
||||||
|
res = append(res, newBytes)
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
makeStrings := func(input [][]byte) []string {
|
||||||
|
var res []string
|
||||||
|
for _, bytes := range input {
|
||||||
|
res = append(res, string(bytes))
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
res := genRandomBytes()
|
||||||
|
stringRes := makeStrings(res)
|
||||||
|
stringMap := map[string]struct{}{}
|
||||||
|
b.Run("string bytes hash map write", func(b *testing.B) {
|
||||||
|
stringMap = map[string]struct{}{}
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for _, bytes := range res {
|
||||||
|
stringMap[string(bytes)] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Run("hash map read", func(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for _, bytes := range res {
|
||||||
|
_, _ = stringMap[string(bytes)]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
b.Run("compare byte slices as strings", func(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for _, bytes := range res {
|
||||||
|
if string(bytes) == string(bytes) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
b.Run("compare byte slices", func(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for _, bt := range res {
|
||||||
|
if bytes.Compare(bt, bt) == 0 {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
b.Run("compare strings", func(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for _, st := range stringRes {
|
||||||
|
if st == st {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
b.Run("string hash map write", func(b *testing.B) {
|
||||||
|
stringMap = map[string]struct{}{}
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for _, str := range stringRes {
|
||||||
|
stringMap[str] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.Run("hash map read", func(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
for _, str := range stringRes {
|
||||||
|
_, _ = stringMap[str]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
@ -129,7 +129,7 @@ func (tb *treeBuilder) loadChange(id string) (ch *Change, err error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
ch, err = tb.builder.ConvertFromRawAndVerify(change)
|
ch, err = tb.builder.ConvertFromRaw(change, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,91 +0,0 @@
|
|||||||
package tree
|
|
||||||
|
|
||||||
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/storage"
|
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/cid"
|
|
||||||
"github.com/gogo/protobuf/proto"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func CreateNewTreeStorage(
|
|
||||||
acc *account.AccountData,
|
|
||||||
aclList list.ACLList,
|
|
||||||
content proto.Marshaler,
|
|
||||||
create storage.TreeStorageCreatorFunc) (thr storage.TreeStorage, err error) {
|
|
||||||
|
|
||||||
state := aclList.ACLState()
|
|
||||||
change := &aclpb.Change{
|
|
||||||
AclHeadId: aclList.Head().Id,
|
|
||||||
CurrentReadKeyHash: state.CurrentReadKeyHash(),
|
|
||||||
Timestamp: int64(time.Now().Nanosecond()),
|
|
||||||
Identity: acc.Identity,
|
|
||||||
IsSnapshot: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
marshalledData, err := content.Marshal()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
readKey, err := state.CurrentReadKey()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
encrypted, err := readKey.Encrypt(marshalledData)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
change.ChangesData = encrypted
|
|
||||||
|
|
||||||
fullMarshalledChange, err := proto.Marshal(change)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
signature, err := acc.SignKey.Sign(fullMarshalledChange)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
changeId, err := cid.NewCIDFromBytes(fullMarshalledChange)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
rawChange := &aclpb.RawChange{
|
|
||||||
Payload: fullMarshalledChange,
|
|
||||||
Signature: signature,
|
|
||||||
Id: changeId,
|
|
||||||
}
|
|
||||||
header, treeId, err := createTreeHeaderAndId(rawChange, aclpb.Header_DocTree, aclList.ID())
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
return create(storage.TreeStorageCreatePayload{
|
|
||||||
TreeId: treeId,
|
|
||||||
Header: header,
|
|
||||||
Changes: []*aclpb.RawChange{rawChange},
|
|
||||||
Heads: []string{rawChange.Id},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func createTreeHeaderAndId(change *aclpb.RawChange, treeType aclpb.HeaderDocType, aclListId string) (header *aclpb.Header, treeId string, err error) {
|
|
||||||
header = &aclpb.Header{
|
|
||||||
FirstId: change.Id,
|
|
||||||
DocType: treeType,
|
|
||||||
AclListId: aclListId,
|
|
||||||
}
|
|
||||||
marshalledHeader, err := proto.Marshal(header)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
treeId, err = cid.NewCIDFromBytes(marshalledHeader)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
@ -15,7 +15,7 @@ var log = logger.NewNamed("storage").Sugar()
|
|||||||
type ImportedACLSyncData struct {
|
type ImportedACLSyncData struct {
|
||||||
Id string
|
Id string
|
||||||
Header *aclpb.Header
|
Header *aclpb.Header
|
||||||
Records []*aclpb.RawRecord
|
Records []*aclpb.RawACLRecord
|
||||||
}
|
}
|
||||||
|
|
||||||
type Service interface {
|
type Service interface {
|
||||||
|
|||||||
@ -47,44 +47,3 @@ message System {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
message Sync {
|
|
||||||
string spaceId = 1;
|
|
||||||
ContentValue message = 2;
|
|
||||||
acl.Header treeHeader = 3;
|
|
||||||
string treeId = 4;
|
|
||||||
|
|
||||||
message ContentValue {
|
|
||||||
oneof value {
|
|
||||||
HeadUpdate headUpdate = 1;
|
|
||||||
Full.Request fullSyncRequest = 2;
|
|
||||||
Full.Response fullSyncResponse = 3;
|
|
||||||
ACLList aclList = 4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
message ACLList {
|
|
||||||
repeated acl.RawRecord records = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
message HeadUpdate {
|
|
||||||
repeated string heads = 1;
|
|
||||||
repeated acl.RawChange changes = 2;
|
|
||||||
repeated string snapshotPath = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
message Full {
|
|
||||||
// here with send the request with all changes we have (we already know sender's snapshot path)
|
|
||||||
message Request {
|
|
||||||
repeated string heads = 1;
|
|
||||||
repeated acl.RawChange changes = 2;
|
|
||||||
repeated string snapshotPath = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
message Response {
|
|
||||||
repeated string heads = 1;
|
|
||||||
repeated acl.RawChange changes = 2;
|
|
||||||
repeated string snapshotPath = 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
2300
syncproto/sync.pb.go
2300
syncproto/sync.pb.go
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user