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
|
||||
$(eval PKGMAP := $$(P_ACL_CHANGES))
|
||||
$(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:
|
||||
@$(eval FLAGS := $$(shell govvv -flags -pkg github.com/anytypeio/go-anytype-infrastructure-experiments/app))
|
||||
|
||||
@ -1,16 +1,17 @@
|
||||
syntax = "proto3";
|
||||
package anySpace;
|
||||
|
||||
option go_package = "common/commonspace/spacesyncproto";
|
||||
import "pkg/acl/aclchanges/aclpb/protos/aclchanges.proto";
|
||||
|
||||
enum ErrCodes {
|
||||
Unexpected = 0;
|
||||
}
|
||||
|
||||
|
||||
service Space {
|
||||
// HeadSync compares all objects and their hashes in a space
|
||||
rpc HeadSync(HeadSyncRequest) returns (HeadSyncResponse);
|
||||
rpc Stream( stream Msg) returns (stream Msg);
|
||||
rpc Stream(stream ObjectSyncMessage) returns (stream ObjectSyncMessage);
|
||||
}
|
||||
|
||||
// TODO: temporary mock message
|
||||
@ -18,8 +19,6 @@ message Msg {
|
||||
string spaceId = 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// HeadSyncRange presenting a request for one range
|
||||
message HeadSyncRange {
|
||||
uint64 from = 1;
|
||||
@ -50,3 +49,40 @@ message HeadSyncRequest {
|
||||
message HeadSyncResponse {
|
||||
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
|
||||
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
|
||||
EncKey encryptionkey.PrivKey
|
||||
Decoder keys.Decoder
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -2,147 +2,142 @@ syntax = "proto3";
|
||||
package acl;
|
||||
option go_package = "aclpb";
|
||||
|
||||
message RawChange {
|
||||
// ACL protos
|
||||
|
||||
message RawACLRecord {
|
||||
bytes payload = 1;
|
||||
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 {
|
||||
bytes payload = 1;
|
||||
bytes signature = 2;
|
||||
string id = 3;
|
||||
}
|
||||
|
||||
// the element of change tree used to store and internal apply smartBlock history
|
||||
message ACLChange {
|
||||
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 ACLContentValue {
|
||||
oneof value {
|
||||
ACLUserAdd userAdd = 1;
|
||||
ACLUserRemove userRemove = 2;
|
||||
ACLUserPermissionChange userPermissionChange = 3;
|
||||
ACLUserInvite userInvite = 4;
|
||||
ACLUserJoin userJoin = 5;
|
||||
ACLUserConfirm userConfirm = 6;
|
||||
}
|
||||
}
|
||||
|
||||
message Change {
|
||||
repeated string treeHeadIds = 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 ACLData {
|
||||
repeated ACLContentValue aclContent = 1;
|
||||
}
|
||||
|
||||
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 identity = 2;
|
||||
bytes identity = 2;
|
||||
bytes data = 3;
|
||||
uint64 currentReadKeyHash = 4;
|
||||
int64 timestamp = 5;
|
||||
}
|
||||
|
||||
message Header {
|
||||
message ACLHeader {
|
||||
string firstId = 1;
|
||||
string aclListId = 2;
|
||||
string workspaceId = 3;
|
||||
DocType docType = 4;
|
||||
|
||||
enum DocType {
|
||||
ACL = 0;
|
||||
DocTree = 1;
|
||||
}
|
||||
bytes identity = 2; // the identity of the creator
|
||||
}
|
||||
|
||||
// Tree protos
|
||||
|
||||
message RawTreeChange {
|
||||
bytes payload = 1;
|
||||
bytes signature = 2;
|
||||
}
|
||||
|
||||
message RawTreeChangeWithId {
|
||||
bytes rawChange = 1;
|
||||
string id = 2;
|
||||
}
|
||||
|
||||
message TreeChange {
|
||||
repeated string treeHeadIds = 1;
|
||||
string aclHeadId = 2;
|
||||
string snapshotBaseId = 3;
|
||||
bytes changesData = 4;
|
||||
uint64 currentReadKeyHash = 5;
|
||||
int64 timestamp = 6;
|
||||
bytes identity = 7;
|
||||
bool isSnapshot = 8;
|
||||
}
|
||||
|
||||
enum TreeHeaderType {
|
||||
Object = 0;
|
||||
Space = 1;
|
||||
}
|
||||
|
||||
message TreeHeader {
|
||||
string firstId = 1;
|
||||
string aclId = 2;
|
||||
TreeHeaderType treeHeaderType = 3;
|
||||
bytes identity = 4;
|
||||
bytes data = 5; // this should be reserved for the client to add the data it needs
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package list
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/app/logger"
|
||||
@ -29,14 +30,14 @@ var ErrInvalidSignature = errors.New("signature is invalid")
|
||||
|
||||
type UserPermissionPair struct {
|
||||
Identity string
|
||||
Permission aclpb.ACLChangeUserPermissions
|
||||
Permission aclpb.ACLUserPermissions
|
||||
}
|
||||
|
||||
type ACLState struct {
|
||||
currentReadKeyHash uint64
|
||||
userReadKeys map[uint64]*symmetric.Key
|
||||
userStates map[string]*aclpb.ACLChangeUserState
|
||||
userInvites map[string]*aclpb.ACLChangeUserInvite
|
||||
userStates map[string]*aclpb.ACLUserState
|
||||
userInvites map[string]*aclpb.ACLUserInvite
|
||||
|
||||
signingPubKeyDecoder keys.Decoder
|
||||
encryptionKey encryptionkey.PrivKey
|
||||
@ -55,8 +56,8 @@ func newACLStateWithIdentity(
|
||||
identity: identity,
|
||||
encryptionKey: encryptionKey,
|
||||
userReadKeys: make(map[uint64]*symmetric.Key),
|
||||
userStates: make(map[string]*aclpb.ACLChangeUserState),
|
||||
userInvites: make(map[string]*aclpb.ACLChangeUserInvite),
|
||||
userStates: make(map[string]*aclpb.ACLUserState),
|
||||
userInvites: make(map[string]*aclpb.ACLUserInvite),
|
||||
signingPubKeyDecoder: decoder,
|
||||
permissionsAtRecord: make(map[string][]UserPermissionPair),
|
||||
keychain: common.NewKeychain(),
|
||||
@ -67,8 +68,8 @@ func newACLState(decoder keys.Decoder) *ACLState {
|
||||
return &ACLState{
|
||||
signingPubKeyDecoder: decoder,
|
||||
userReadKeys: make(map[uint64]*symmetric.Key),
|
||||
userStates: make(map[string]*aclpb.ACLChangeUserState),
|
||||
userInvites: make(map[string]*aclpb.ACLChangeUserInvite),
|
||||
userStates: make(map[string]*aclpb.ACLUserState),
|
||||
userInvites: make(map[string]*aclpb.ACLUserInvite),
|
||||
permissionsAtRecord: make(map[string][]UserPermissionPair),
|
||||
keychain: common.NewKeychain(),
|
||||
}
|
||||
@ -105,8 +106,8 @@ func (st *ACLState) PermissionsAtRecord(id string, identity string) (UserPermiss
|
||||
return UserPermissionPair{}, ErrNoSuchUser
|
||||
}
|
||||
|
||||
func (st *ACLState) applyRecord(record *aclpb.Record) (err error) {
|
||||
aclData := &aclpb.ACLChangeACLData{}
|
||||
func (st *ACLState) applyRecord(record *aclpb.ACLRecord) (err error) {
|
||||
aclData := &aclpb.ACLData{}
|
||||
|
||||
err = proto.Unmarshal(record.Data, aclData)
|
||||
if err != nil {
|
||||
@ -122,14 +123,14 @@ func (st *ACLState) applyRecord(record *aclpb.Record) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (st *ACLState) applyChangeAndUpdate(recordWrapper *Record) (err error) {
|
||||
func (st *ACLState) applyChangeAndUpdate(recordWrapper *ACLRecord) (err error) {
|
||||
var (
|
||||
change = recordWrapper.Content
|
||||
aclData = &aclpb.ACLChangeACLData{}
|
||||
aclData = &aclpb.ACLData{}
|
||||
)
|
||||
|
||||
if recordWrapper.Model != nil {
|
||||
aclData = recordWrapper.Model.(*aclpb.ACLChangeACLData)
|
||||
aclData = recordWrapper.Model.(*aclpb.ACLData)
|
||||
} else {
|
||||
err = proto.Unmarshal(change.Data, aclData)
|
||||
if err != nil {
|
||||
@ -147,7 +148,7 @@ func (st *ACLState) applyChangeAndUpdate(recordWrapper *Record) (err error) {
|
||||
var permissions []UserPermissionPair
|
||||
for _, state := range st.userStates {
|
||||
permission := UserPermissionPair{
|
||||
Identity: state.Identity,
|
||||
Identity: string(state.Identity),
|
||||
Permission: state.Permissions,
|
||||
}
|
||||
permissions = append(permissions, permission)
|
||||
@ -157,7 +158,7 @@ func (st *ACLState) applyChangeAndUpdate(recordWrapper *Record) (err error) {
|
||||
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() {
|
||||
if err != nil {
|
||||
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))
|
||||
if !skipIdentityCheck {
|
||||
// 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
|
||||
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)
|
||||
return
|
||||
}
|
||||
@ -191,7 +192,7 @@ func (st *ACLState) applyChangeData(changeData *aclpb.ACLChangeACLData, hash uin
|
||||
return nil
|
||||
}
|
||||
|
||||
func (st *ACLState) applyChangeContent(ch *aclpb.ACLChangeACLContentValue) error {
|
||||
func (st *ACLState) applyChangeContent(ch *aclpb.ACLContentValue) error {
|
||||
switch {
|
||||
case ch.GetUserPermissionChange() != nil:
|
||||
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 {
|
||||
if _, exists := st.userStates[ch.Identity]; !exists {
|
||||
func (st *ACLState) applyUserPermissionChange(ch *aclpb.ACLUserPermissionChange) error {
|
||||
chIdentity := string(ch.Identity)
|
||||
if _, exists := st.userStates[chIdentity]; !exists {
|
||||
return ErrNoSuchUser
|
||||
}
|
||||
|
||||
st.userStates[ch.Identity].Permissions = ch.Permissions
|
||||
st.userStates[chIdentity].Permissions = ch.Permissions
|
||||
return nil
|
||||
}
|
||||
|
||||
func (st *ACLState) applyUserInvite(ch *aclpb.ACLChangeUserInvite) error {
|
||||
func (st *ACLState) applyUserInvite(ch *aclpb.ACLUserInvite) error {
|
||||
st.userInvites[ch.InviteId] = ch
|
||||
return nil
|
||||
}
|
||||
|
||||
func (st *ACLState) applyUserJoin(ch *aclpb.ACLChangeUserJoin) error {
|
||||
func (st *ACLState) applyUserJoin(ch *aclpb.ACLUserJoin) error {
|
||||
invite, exists := st.userInvites[ch.UserInviteId]
|
||||
if !exists {
|
||||
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
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
rawSignedId, err := st.signingPubKeyDecoder.DecodeFromStringIntoBytes(ch.Identity)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to decode signing identity as bytes")
|
||||
}
|
||||
|
||||
res, err := verificationKey.(signingkey.PubKey).Verify(rawSignedId, signature)
|
||||
res, err := verificationKey.(signingkey.PubKey).Verify(ch.Identity, signature)
|
||||
if err != nil {
|
||||
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 st.identity == ch.Identity {
|
||||
if st.identity == chIdentity {
|
||||
for _, key := range ch.EncryptedReadKeys {
|
||||
key, hash, err := st.decryptReadKeyAndHash(key)
|
||||
if err != nil {
|
||||
@ -267,30 +265,31 @@ func (st *ACLState) applyUserJoin(ch *aclpb.ACLChangeUserJoin) error {
|
||||
}
|
||||
|
||||
// adding user to the list
|
||||
userState := &aclpb.ACLChangeUserState{
|
||||
userState := &aclpb.ACLUserState{
|
||||
Identity: ch.Identity,
|
||||
EncryptionKey: ch.EncryptionKey,
|
||||
EncryptedReadKeys: ch.EncryptedReadKeys,
|
||||
Permissions: invite.Permissions,
|
||||
IsConfirmed: true,
|
||||
}
|
||||
st.userStates[ch.Identity] = userState
|
||||
st.userStates[chIdentity] = userState
|
||||
return nil
|
||||
}
|
||||
|
||||
func (st *ACLState) applyUserAdd(ch *aclpb.ACLChangeUserAdd) error {
|
||||
if _, exists := st.userStates[ch.Identity]; exists {
|
||||
func (st *ACLState) applyUserAdd(ch *aclpb.ACLUserAdd) error {
|
||||
chIdentity := string(ch.Identity)
|
||||
if _, exists := st.userStates[chIdentity]; exists {
|
||||
return ErrUserAlreadyExists
|
||||
}
|
||||
|
||||
st.userStates[ch.Identity] = &aclpb.ACLChangeUserState{
|
||||
st.userStates[chIdentity] = &aclpb.ACLUserState{
|
||||
Identity: ch.Identity,
|
||||
EncryptionKey: ch.EncryptionKey,
|
||||
Permissions: ch.Permissions,
|
||||
EncryptedReadKeys: ch.EncryptedReadKeys,
|
||||
}
|
||||
|
||||
if ch.Identity == st.identity {
|
||||
if chIdentity == st.identity {
|
||||
for _, key := range ch.EncryptedReadKeys {
|
||||
key, hash, err := st.decryptReadKeyAndHash(key)
|
||||
if err != nil {
|
||||
@ -304,26 +303,28 @@ func (st *ACLState) applyUserAdd(ch *aclpb.ACLChangeUserAdd) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (st *ACLState) applyUserRemove(ch *aclpb.ACLChangeUserRemove) error {
|
||||
if ch.Identity == st.identity {
|
||||
func (st *ACLState) applyUserRemove(ch *aclpb.ACLUserRemove) error {
|
||||
chIdentity := string(ch.Identity)
|
||||
if chIdentity == st.identity {
|
||||
return ErrDocumentForbidden
|
||||
}
|
||||
|
||||
if _, exists := st.userStates[ch.Identity]; !exists {
|
||||
if _, exists := st.userStates[chIdentity]; !exists {
|
||||
return ErrNoSuchUser
|
||||
}
|
||||
|
||||
delete(st.userStates, ch.Identity)
|
||||
delete(st.userStates, chIdentity)
|
||||
|
||||
for _, replace := range ch.ReadKeyReplaces {
|
||||
userState, exists := st.userStates[replace.Identity]
|
||||
repIdentity := string(replace.Identity)
|
||||
userState, exists := st.userStates[repIdentity]
|
||||
if !exists {
|
||||
continue
|
||||
}
|
||||
|
||||
userState.EncryptedReadKeys = append(userState.EncryptedReadKeys, replace.EncryptedReadKey)
|
||||
// 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)
|
||||
if err != nil {
|
||||
return ErrFailedToDecrypt
|
||||
@ -336,12 +337,13 @@ func (st *ACLState) applyUserRemove(ch *aclpb.ACLChangeUserRemove) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (st *ACLState) applyUserConfirm(ch *aclpb.ACLChangeUserConfirm) error {
|
||||
if _, exists := st.userStates[ch.Identity]; !exists {
|
||||
func (st *ACLState) applyUserConfirm(ch *aclpb.ACLUserConfirm) error {
|
||||
chIdentity := string(ch.Identity)
|
||||
if _, exists := st.userStates[chIdentity]; !exists {
|
||||
return ErrNoSuchUser
|
||||
}
|
||||
|
||||
userState := st.userStates[ch.Identity]
|
||||
userState := st.userStates[chIdentity]
|
||||
userState.IsConfirmed = true
|
||||
return nil
|
||||
}
|
||||
@ -362,8 +364,8 @@ func (st *ACLState) decryptReadKeyAndHash(msg []byte) (*symmetric.Key, uint64, e
|
||||
return key, hasher.Sum64(), nil
|
||||
}
|
||||
|
||||
func (st *ACLState) hasPermission(identity string, permission aclpb.ACLChangeUserPermissions) bool {
|
||||
state, exists := st.userStates[identity]
|
||||
func (st *ACLState) hasPermission(identity []byte, permission aclpb.ACLUserPermissions) bool {
|
||||
state, exists := st.userStates[string(identity)]
|
||||
if !exists {
|
||||
return false
|
||||
}
|
||||
@ -371,17 +373,17 @@ func (st *ACLState) hasPermission(identity string, permission aclpb.ACLChangeUse
|
||||
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
|
||||
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
|
||||
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
|
||||
}
|
||||
|
||||
@ -15,7 +15,7 @@ type aclStateBuilder struct {
|
||||
func newACLStateBuilderWithIdentity(decoder keys.Decoder, accountData *account.AccountData) *aclStateBuilder {
|
||||
return &aclStateBuilder{
|
||||
decoder: decoder,
|
||||
identity: accountData.Identity,
|
||||
identity: string(accountData.Identity),
|
||||
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 (
|
||||
err error
|
||||
state *ACLState
|
||||
|
||||
@ -14,7 +14,7 @@ import (
|
||||
type MarshalledChange = []byte
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
@ -23,7 +23,7 @@ type aclChangeBuilder struct {
|
||||
list ACLList
|
||||
acc *account.AccountData
|
||||
|
||||
aclData *aclpb.ACLChangeACLData
|
||||
aclData *aclpb.ACLData
|
||||
id string
|
||||
readKey *symmetric.Key
|
||||
readKeyHash uint64
|
||||
@ -38,7 +38,7 @@ func (c *aclChangeBuilder) Init(state *ACLState, list ACLList, acc *account.Acco
|
||||
c.list = list
|
||||
c.acc = acc
|
||||
|
||||
c.aclData = &aclpb.ACLChangeACLData{}
|
||||
c.aclData = &aclpb.ACLData{}
|
||||
// setting read key for further encryption etc
|
||||
if state.currentReadKeyHash == 0 {
|
||||
c.readKey, _ = symmetric.NewRandom()
|
||||
@ -56,7 +56,7 @@ func (c *aclChangeBuilder) AddId(id string) {
|
||||
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
|
||||
if c.aclState.currentReadKeyHash != 0 {
|
||||
for _, key := range c.aclState.userReadKeys {
|
||||
@ -79,10 +79,10 @@ func (c *aclChangeBuilder) UserAdd(identity string, encryptionKey encryptionkey.
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ch := &aclpb.ACLChangeACLContentValue{
|
||||
Value: &aclpb.ACLChangeACLContentValueValueOfUserAdd{
|
||||
UserAdd: &aclpb.ACLChangeUserAdd{
|
||||
Identity: identity,
|
||||
ch := &aclpb.ACLContentValue{
|
||||
Value: &aclpb.ACLContentValue_UserAdd{
|
||||
UserAdd: &aclpb.ACLUserAdd{
|
||||
Identity: []byte(identity),
|
||||
EncryptionKey: rawKey,
|
||||
EncryptedReadKeys: encryptedKeys,
|
||||
Permissions: permissions,
|
||||
@ -93,8 +93,8 @@ func (c *aclChangeBuilder) UserAdd(identity string, encryptionKey encryptionkey.
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *aclChangeBuilder) BuildAndApply() (*Record, []byte, error) {
|
||||
aclRecord := &aclpb.Record{
|
||||
func (c *aclChangeBuilder) BuildAndApply() (*ACLRecord, []byte, error) {
|
||||
aclRecord := &aclpb.ACLRecord{
|
||||
PrevId: c.list.Head().Id,
|
||||
CurrentReadKeyHash: c.readKeyHash,
|
||||
Timestamp: int64(time.Now().Nanosecond()),
|
||||
|
||||
@ -13,7 +13,7 @@ import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
type IterFunc = func(record *Record) (IsContinue bool)
|
||||
type IterFunc = func(record *ACLRecord) (IsContinue bool)
|
||||
|
||||
var ErrIncorrectCID = errors.New("incorrect CID")
|
||||
|
||||
@ -26,20 +26,20 @@ type RWLocker interface {
|
||||
type ACLList interface {
|
||||
RWLocker
|
||||
ID() string
|
||||
Header() *aclpb.Header
|
||||
Records() []*Record
|
||||
Header() *aclpb.ACLHeader
|
||||
Records() []*ACLRecord
|
||||
ACLState() *ACLState
|
||||
IsAfter(first string, second string) (bool, error)
|
||||
Head() *Record
|
||||
Get(id string) (*Record, error)
|
||||
Head() *ACLRecord
|
||||
Get(id string) (*ACLRecord, error)
|
||||
Iterate(iterFunc IterFunc)
|
||||
IterateFrom(startId string, iterFunc IterFunc)
|
||||
Close() (err error)
|
||||
}
|
||||
|
||||
type aclList struct {
|
||||
header *aclpb.Header
|
||||
records []*Record
|
||||
header *aclpb.ACLHeader
|
||||
records []*ACLRecord
|
||||
indexes map[string]int
|
||||
id string
|
||||
|
||||
@ -84,7 +84,7 @@ func buildWithACLStateBuilder(builder *aclStateBuilder, storage storage.ListStor
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
records := []*Record{record}
|
||||
records := []*ACLRecord{record}
|
||||
|
||||
for record.Content.PrevId != "" {
|
||||
rawRecord, err = storage.GetRawRecord(context.Background(), record.Content.PrevId)
|
||||
@ -131,7 +131,7 @@ func buildWithACLStateBuilder(builder *aclStateBuilder, storage storage.ListStor
|
||||
return
|
||||
}
|
||||
|
||||
func (a *aclList) Records() []*Record {
|
||||
func (a *aclList) Records() []*ACLRecord {
|
||||
return a.records
|
||||
}
|
||||
|
||||
@ -139,7 +139,7 @@ func (a *aclList) ID() string {
|
||||
return a.id
|
||||
}
|
||||
|
||||
func (a *aclList) Header() *aclpb.Header {
|
||||
func (a *aclList) Header() *aclpb.ACLHeader {
|
||||
return a.header
|
||||
}
|
||||
|
||||
@ -156,11 +156,11 @@ func (a *aclList) IsAfter(first string, second string) (bool, error) {
|
||||
return firstRec >= secondRec, nil
|
||||
}
|
||||
|
||||
func (a *aclList) Head() *Record {
|
||||
func (a *aclList) Head() *ACLRecord {
|
||||
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]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("no such record")
|
||||
@ -192,8 +192,8 @@ func (a *aclList) Close() (err error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
func verifyRecord(keychain *common.Keychain, rawRecord *aclpb.RawRecord, record *Record) (err error) {
|
||||
identityKey, err := keychain.GetOrAdd(record.Content.Identity)
|
||||
func verifyRecord(keychain *common.Keychain, rawRecord *aclpb.RawACLRecord, record *ACLRecord) (err error) {
|
||||
identityKey, err := keychain.GetOrAdd(record.Identity)
|
||||
if err != nil {
|
||||
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, aclList.Head().Content.CurrentReadKeyHash, aclList.ACLState().CurrentReadKeyHash())
|
||||
|
||||
var records []*Record
|
||||
aclList.Iterate(func(record *Record) (IsContinue bool) {
|
||||
var records []*ACLRecord
|
||||
aclList.Iterate(func(record *ACLRecord) (IsContinue bool) {
|
||||
records = append(records, record)
|
||||
return true
|
||||
})
|
||||
@ -69,8 +69,8 @@ func TestAclList_ACLState_UserJoinAndRemove(t *testing.T) {
|
||||
_, exists := aclList.ACLState().GetUserStates()[idB]
|
||||
assert.Equal(t, false, exists)
|
||||
|
||||
var records []*Record
|
||||
aclList.Iterate(func(record *Record) (IsContinue bool) {
|
||||
var records []*ACLRecord
|
||||
aclList.Iterate(func(record *ACLRecord) (IsContinue bool) {
|
||||
records = append(records, record)
|
||||
return true
|
||||
})
|
||||
|
||||
@ -5,30 +5,33 @@ import (
|
||||
"github.com/gogo/protobuf/proto"
|
||||
)
|
||||
|
||||
type Record struct {
|
||||
Id string
|
||||
Content *aclpb.Record
|
||||
Model interface{}
|
||||
Sign []byte
|
||||
type ACLRecord struct {
|
||||
Id string
|
||||
Content *aclpb.ACLRecord
|
||||
Identity string
|
||||
Model interface{}
|
||||
Sign []byte
|
||||
}
|
||||
|
||||
func NewRecord(id string, aclRecord *aclpb.Record) *Record {
|
||||
return &Record{
|
||||
Id: id,
|
||||
Content: aclRecord,
|
||||
func NewRecord(id string, aclRecord *aclpb.ACLRecord) *ACLRecord {
|
||||
return &ACLRecord{
|
||||
Id: id,
|
||||
Content: aclRecord,
|
||||
Identity: string(aclRecord.Identity),
|
||||
}
|
||||
}
|
||||
|
||||
func NewFromRawRecord(rawRec *aclpb.RawRecord) (*Record, error) {
|
||||
aclRec := &aclpb.Record{}
|
||||
func NewFromRawRecord(rawRec *aclpb.RawACLRecord) (*ACLRecord, error) {
|
||||
aclRec := &aclpb.ACLRecord{}
|
||||
err := proto.Unmarshal(rawRec.Payload, aclRec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Record{
|
||||
Id: rawRec.Id,
|
||||
Content: aclRec,
|
||||
Sign: rawRec.Signature,
|
||||
return &ACLRecord{
|
||||
Id: rawRec.Id,
|
||||
Content: aclRec,
|
||||
Sign: rawRec.Signature,
|
||||
Identity: string(aclRec.Identity),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -8,8 +8,8 @@ import (
|
||||
)
|
||||
|
||||
type inMemoryACLListStorage struct {
|
||||
header *aclpb.Header
|
||||
records []*aclpb.RawRecord
|
||||
header *aclpb.ACLHeader
|
||||
records []*aclpb.RawACLRecord
|
||||
|
||||
id string
|
||||
|
||||
@ -18,8 +18,8 @@ type inMemoryACLListStorage struct {
|
||||
|
||||
func NewInMemoryACLListStorage(
|
||||
id string,
|
||||
header *aclpb.Header,
|
||||
records []*aclpb.RawRecord) (ListStorage, error) {
|
||||
header *aclpb.ACLHeader,
|
||||
records []*aclpb.RawACLRecord) (ListStorage, error) {
|
||||
return &inMemoryACLListStorage{
|
||||
id: id,
|
||||
header: header,
|
||||
@ -28,19 +28,19 @@ func NewInMemoryACLListStorage(
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (i *inMemoryACLListStorage) Header() (*aclpb.Header, error) {
|
||||
func (i *inMemoryACLListStorage) Header() (*aclpb.ACLHeader, error) {
|
||||
i.RLock()
|
||||
defer i.RUnlock()
|
||||
return i.header, nil
|
||||
}
|
||||
|
||||
func (i *inMemoryACLListStorage) Head() (*aclpb.RawRecord, error) {
|
||||
func (i *inMemoryACLListStorage) Head() (*aclpb.RawACLRecord, error) {
|
||||
i.RLock()
|
||||
defer i.RUnlock()
|
||||
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()
|
||||
defer i.RUnlock()
|
||||
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")
|
||||
}
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
@ -63,19 +63,19 @@ func (i *inMemoryACLListStorage) ID() (string, error) {
|
||||
|
||||
type inMemoryTreeStorage struct {
|
||||
id string
|
||||
header *aclpb.Header
|
||||
header *aclpb.TreeHeader
|
||||
heads []string
|
||||
changes map[string]*aclpb.RawChange
|
||||
changes map[string]*aclpb.RawTreeChangeWithId
|
||||
|
||||
sync.RWMutex
|
||||
}
|
||||
|
||||
func NewInMemoryTreeStorage(
|
||||
treeId string,
|
||||
header *aclpb.Header,
|
||||
header *aclpb.TreeHeader,
|
||||
heads []string,
|
||||
changes []*aclpb.RawChange) (TreeStorage, error) {
|
||||
allChanges := make(map[string]*aclpb.RawChange)
|
||||
changes []*aclpb.RawTreeChangeWithId) (TreeStorage, error) {
|
||||
allChanges := make(map[string]*aclpb.RawTreeChangeWithId)
|
||||
for _, ch := range changes {
|
||||
allChanges[ch.Id] = ch
|
||||
}
|
||||
@ -95,7 +95,7 @@ func (t *inMemoryTreeStorage) ID() (string, error) {
|
||||
return t.id, nil
|
||||
}
|
||||
|
||||
func (t *inMemoryTreeStorage) Header() (*aclpb.Header, error) {
|
||||
func (t *inMemoryTreeStorage) Header() (*aclpb.TreeHeader, error) {
|
||||
t.RLock()
|
||||
defer t.RUnlock()
|
||||
return t.header, nil
|
||||
@ -118,7 +118,7 @@ func (t *inMemoryTreeStorage) SetHeads(heads []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *inMemoryTreeStorage) AddRawChange(change *aclpb.RawChange) error {
|
||||
func (t *inMemoryTreeStorage) AddRawChange(change *aclpb.RawTreeChangeWithId) error {
|
||||
t.Lock()
|
||||
defer t.Unlock()
|
||||
// TODO: better to do deep copy
|
||||
@ -126,7 +126,7 @@ func (t *inMemoryTreeStorage) AddRawChange(change *aclpb.RawChange) error {
|
||||
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()
|
||||
defer t.RUnlock()
|
||||
if res, exists := t.changes[changeId]; exists {
|
||||
|
||||
@ -7,8 +7,8 @@ import (
|
||||
|
||||
type ListStorage interface {
|
||||
Storage
|
||||
Head() (*aclpb.RawRecord, error)
|
||||
Head() (*aclpb.RawACLRecord, error)
|
||||
|
||||
GetRawRecord(ctx context.Context, id string) (*aclpb.RawRecord, error)
|
||||
AddRawRecord(ctx context.Context, rec *aclpb.RawRecord) error
|
||||
GetRawRecord(ctx context.Context, id string) (*aclpb.RawACLRecord, error)
|
||||
AddRawRecord(ctx context.Context, rec *aclpb.RawACLRecord) error
|
||||
}
|
||||
|
||||
@ -9,15 +9,15 @@ var ErrUnknownTreeId = errors.New("tree does not exist")
|
||||
|
||||
type TreeStorageCreatePayload struct {
|
||||
TreeId string
|
||||
Header *aclpb.Header
|
||||
Changes []*aclpb.RawChange
|
||||
Header *aclpb.TreeHeader
|
||||
Changes []*aclpb.RawTreeChangeWithId
|
||||
Heads []string
|
||||
}
|
||||
|
||||
type ACLListStorageCreatePayload struct {
|
||||
ListId string
|
||||
Header *aclpb.Header
|
||||
Records []*aclpb.RawRecord
|
||||
Header *aclpb.ACLHeader
|
||||
Records []*aclpb.RawACLRecord
|
||||
}
|
||||
|
||||
type Provider interface {
|
||||
|
||||
@ -10,8 +10,8 @@ type TreeStorage interface {
|
||||
Heads() ([]string, error)
|
||||
SetHeads(heads []string) error
|
||||
|
||||
AddRawChange(change *aclpb.RawChange) error
|
||||
GetRawChange(ctx context.Context, recordID string) (*aclpb.RawChange, error)
|
||||
AddRawChange(change *aclpb.RawTreeChangeWithId) error
|
||||
GetRawChange(ctx context.Context, recordID string) (*aclpb.RawTreeChangeWithId, error)
|
||||
}
|
||||
|
||||
type TreeStorageCreatorFunc = func(payload TreeStorageCreatePayload) (TreeStorage, error)
|
||||
|
||||
@ -19,8 +19,8 @@ import (
|
||||
|
||||
type ACLListStorageBuilder struct {
|
||||
aclList string
|
||||
records []*aclpb.Record
|
||||
rawRecords []*aclpb.RawRecord
|
||||
records []*aclpb.ACLRecord
|
||||
rawRecords []*aclpb.RawACLRecord
|
||||
indexes map[string]int
|
||||
keychain *Keychain
|
||||
header *aclpb.Header
|
||||
@ -29,7 +29,7 @@ type ACLListStorageBuilder struct {
|
||||
|
||||
func NewACLListStorageBuilder(keychain *Keychain) *ACLListStorageBuilder {
|
||||
return &ACLListStorageBuilder{
|
||||
records: make([]*aclpb.Record, 0),
|
||||
records: make([]*aclpb.ACLRecord, 0),
|
||||
indexes: make(map[string]int),
|
||||
keychain: keychain,
|
||||
}
|
||||
@ -58,7 +58,7 @@ func NewACLListStorageBuilderFromFile(file string) (*ACLListStorageBuilder, erro
|
||||
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)
|
||||
if err != nil {
|
||||
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)
|
||||
|
||||
return &aclpb.RawRecord{
|
||||
return &aclpb.RawACLRecord{
|
||||
Payload: aclMarshaled,
|
||||
Signature: signature,
|
||||
Id: id,
|
||||
}
|
||||
}
|
||||
|
||||
func (t *ACLListStorageBuilder) getRecord(idx int) *aclpb.RawRecord {
|
||||
func (t *ACLListStorageBuilder) getRecord(idx int) *aclpb.RawACLRecord {
|
||||
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
|
||||
}
|
||||
|
||||
@ -90,7 +90,7 @@ func (t *ACLListStorageBuilder) Header() (*aclpb.Header, error) {
|
||||
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]
|
||||
if !ok {
|
||||
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
|
||||
}
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
@ -106,7 +106,7 @@ func (t *ACLListStorageBuilder) ID() (string, error) {
|
||||
return t.id, nil
|
||||
}
|
||||
|
||||
func (t *ACLListStorageBuilder) GetRawRecords() []*aclpb.RawRecord {
|
||||
func (t *ACLListStorageBuilder) GetRawRecords() []*aclpb.RawACLRecord {
|
||||
return t.rawRecords
|
||||
}
|
||||
|
||||
@ -132,7 +132,7 @@ func (t *ACLListStorageBuilder) Parse(tree *YMLList) {
|
||||
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)
|
||||
var aclChangeContents []*aclpb.ACLChangeACLContentValue
|
||||
for _, ch := range rec.AclChanges {
|
||||
@ -144,7 +144,7 @@ func (t *ACLListStorageBuilder) parseRecord(rec *Record, prevId string) *aclpb.R
|
||||
}
|
||||
bytes, _ := data.Marshal()
|
||||
|
||||
return &aclpb.Record{
|
||||
return &aclpb.ACLRecord{
|
||||
PrevId: prevId,
|
||||
Identity: t.keychain.GetIdentity(rec.Identity),
|
||||
Data: bytes,
|
||||
@ -163,7 +163,7 @@ func (t *ACLListStorageBuilder) parseACLChange(ch *ACLChange) (convCh *aclpb.ACL
|
||||
|
||||
convCh = &aclpb.ACLChangeACLContentValue{
|
||||
Value: &aclpb.ACLChangeACLContentValueValueOfUserAdd{
|
||||
UserAdd: &aclpb.ACLChangeUserAdd{
|
||||
UserAdd: &aclpb.ACLUserPermissionsAdd{
|
||||
Identity: t.keychain.GetIdentity(add.Identity),
|
||||
EncryptionKey: rawKey,
|
||||
EncryptedReadKeys: t.encryptReadKeys(add.EncryptedReadKeys, encKey),
|
||||
@ -187,7 +187,7 @@ func (t *ACLListStorageBuilder) parseACLChange(ch *ACLChange) (convCh *aclpb.ACL
|
||||
|
||||
convCh = &aclpb.ACLChangeACLContentValue{
|
||||
Value: &aclpb.ACLChangeACLContentValueValueOfUserJoin{
|
||||
UserJoin: &aclpb.ACLChangeUserJoin{
|
||||
UserJoin: &aclpb.ACLUserPermissionsJoin{
|
||||
Identity: t.keychain.GetIdentity(join.Identity),
|
||||
EncryptionKey: rawKey,
|
||||
AcceptSignature: signature,
|
||||
@ -205,7 +205,7 @@ func (t *ACLListStorageBuilder) parseACLChange(ch *ACLChange) (convCh *aclpb.ACL
|
||||
|
||||
convCh = &aclpb.ACLChangeACLContentValue{
|
||||
Value: &aclpb.ACLChangeACLContentValueValueOfUserInvite{
|
||||
UserInvite: &aclpb.ACLChangeUserInvite{
|
||||
UserInvite: &aclpb.ACLUserPermissionsInvite{
|
||||
AcceptPublicKey: rawAcceptKey,
|
||||
EncryptPublicKey: rawEncKey,
|
||||
EncryptedReadKeys: t.encryptReadKeys(invite.EncryptedReadKeys, encKey),
|
||||
@ -219,7 +219,7 @@ func (t *ACLListStorageBuilder) parseACLChange(ch *ACLChange) (convCh *aclpb.ACL
|
||||
|
||||
convCh = &aclpb.ACLChangeACLContentValue{
|
||||
Value: &aclpb.ACLChangeACLContentValueValueOfUserConfirm{
|
||||
UserConfirm: &aclpb.ACLChangeUserConfirm{
|
||||
UserConfirm: &aclpb.ACLUserPermissionsConfirm{
|
||||
Identity: t.keychain.GetIdentity(confirm.Identity),
|
||||
UserAddId: confirm.UserAddId,
|
||||
},
|
||||
@ -230,7 +230,7 @@ func (t *ACLListStorageBuilder) parseACLChange(ch *ACLChange) (convCh *aclpb.ACL
|
||||
|
||||
convCh = &aclpb.ACLChangeACLContentValue{
|
||||
Value: &aclpb.ACLChangeACLContentValueValueOfUserPermissionChange{
|
||||
UserPermissionChange: &aclpb.ACLChangeUserPermissionChange{
|
||||
UserPermissionChange: &aclpb.ACLUserPermissionsPermissionChange{
|
||||
Identity: t.keychain.GetIdentity(permissionChange.Identity),
|
||||
Permissions: t.convertPermission(permissionChange.Permission),
|
||||
},
|
||||
@ -259,7 +259,7 @@ func (t *ACLListStorageBuilder) parseACLChange(ch *ACLChange) (convCh *aclpb.ACL
|
||||
|
||||
convCh = &aclpb.ACLChangeACLContentValue{
|
||||
Value: &aclpb.ACLChangeACLContentValueValueOfUserRemove{
|
||||
UserRemove: &aclpb.ACLChangeUserRemove{
|
||||
UserRemove: &aclpb.ACLUserPermissionsRemove{
|
||||
Identity: t.keychain.GetIdentity(remove.RemovedIdentity),
|
||||
ReadKeyReplaces: replaces,
|
||||
},
|
||||
@ -286,7 +286,7 @@ func (t *ACLListStorageBuilder) encryptReadKeys(keys []string, encKey encryption
|
||||
return
|
||||
}
|
||||
|
||||
func (t *ACLListStorageBuilder) convertPermission(perm string) aclpb.ACLChangeUserPermissions {
|
||||
func (t *ACLListStorageBuilder) convertPermission(perm string) aclpb.ACLUserPermissions {
|
||||
switch perm {
|
||||
case "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-- {
|
||||
err = f(t.records[i], t.rawRecords[i].Id)
|
||||
if err != nil {
|
||||
|
||||
@ -33,7 +33,7 @@ func (t *ACLListStorageBuilder) Graph() (string, error) {
|
||||
graph.SetDir(true)
|
||||
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"
|
||||
|
||||
var chSymbs []string
|
||||
@ -92,7 +92,7 @@ func (t *ACLListStorageBuilder) Graph() (string, error) {
|
||||
return nil
|
||||
}
|
||||
|
||||
var addLinks = func(r *aclpb.Record, id string) error {
|
||||
var addLinks = func(r *aclpb.ACLRecord, id string) error {
|
||||
if r.PrevId == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -58,24 +58,24 @@ func (m *PlainTextChange) XXX_DiscardUnknown() {
|
||||
|
||||
var xxx_messageInfo_PlainTextChange proto.InternalMessageInfo
|
||||
|
||||
type PlainTextChangeContent struct {
|
||||
type PlainTextChange_Content struct {
|
||||
// Types that are valid to be assigned to Value:
|
||||
// *PlainTextChangeContentValueOfTextAppend
|
||||
Value IsPlainTextChangeContentValue `protobuf_oneof:"value"`
|
||||
// *PlainTextChange_Content_TextAppend
|
||||
Value isPlainTextChange_Content_Value `protobuf_oneof:"value"`
|
||||
}
|
||||
|
||||
func (m *PlainTextChangeContent) Reset() { *m = PlainTextChangeContent{} }
|
||||
func (m *PlainTextChangeContent) String() string { return proto.CompactTextString(m) }
|
||||
func (*PlainTextChangeContent) ProtoMessage() {}
|
||||
func (*PlainTextChangeContent) Descriptor() ([]byte, []int) {
|
||||
func (m *PlainTextChange_Content) Reset() { *m = PlainTextChange_Content{} }
|
||||
func (m *PlainTextChange_Content) String() string { return proto.CompactTextString(m) }
|
||||
func (*PlainTextChange_Content) ProtoMessage() {}
|
||||
func (*PlainTextChange_Content) Descriptor() ([]byte, []int) {
|
||||
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)
|
||||
}
|
||||
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 {
|
||||
return xxx_messageInfo_PlainTextChangeContent.Marshal(b, m, deterministic)
|
||||
return xxx_messageInfo_PlainTextChange_Content.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalToSizedBuffer(b)
|
||||
@ -85,67 +85,67 @@ func (m *PlainTextChangeContent) XXX_Marshal(b []byte, deterministic bool) ([]by
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *PlainTextChangeContent) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_PlainTextChangeContent.Merge(m, src)
|
||||
func (m *PlainTextChange_Content) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_PlainTextChange_Content.Merge(m, src)
|
||||
}
|
||||
func (m *PlainTextChangeContent) XXX_Size() int {
|
||||
func (m *PlainTextChange_Content) XXX_Size() int {
|
||||
return m.Size()
|
||||
}
|
||||
func (m *PlainTextChangeContent) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_PlainTextChangeContent.DiscardUnknown(m)
|
||||
func (m *PlainTextChange_Content) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_PlainTextChange_Content.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_PlainTextChangeContent proto.InternalMessageInfo
|
||||
var xxx_messageInfo_PlainTextChange_Content proto.InternalMessageInfo
|
||||
|
||||
type IsPlainTextChangeContentValue interface {
|
||||
IsPlainTextChangeContentValue()
|
||||
type isPlainTextChange_Content_Value interface {
|
||||
isPlainTextChange_Content_Value()
|
||||
MarshalTo([]byte) (int, error)
|
||||
Size() int
|
||||
}
|
||||
|
||||
type PlainTextChangeContentValueOfTextAppend struct {
|
||||
TextAppend *PlainTextChangeTextAppend `protobuf:"bytes,1,opt,name=textAppend,proto3,oneof" json:"textAppend,omitempty"`
|
||||
type PlainTextChange_Content_TextAppend struct {
|
||||
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 {
|
||||
return m.Value
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *PlainTextChangeContent) GetTextAppend() *PlainTextChangeTextAppend {
|
||||
if x, ok := m.GetValue().(*PlainTextChangeContentValueOfTextAppend); ok {
|
||||
func (m *PlainTextChange_Content) GetTextAppend() *PlainTextChange_TextAppend {
|
||||
if x, ok := m.GetValue().(*PlainTextChange_Content_TextAppend); ok {
|
||||
return x.TextAppend
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// XXX_OneofWrappers is for the internal use of the proto package.
|
||||
func (*PlainTextChangeContent) XXX_OneofWrappers() []interface{} {
|
||||
func (*PlainTextChange_Content) XXX_OneofWrappers() []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"`
|
||||
}
|
||||
|
||||
func (m *PlainTextChangeTextAppend) Reset() { *m = PlainTextChangeTextAppend{} }
|
||||
func (m *PlainTextChangeTextAppend) String() string { return proto.CompactTextString(m) }
|
||||
func (*PlainTextChangeTextAppend) ProtoMessage() {}
|
||||
func (*PlainTextChangeTextAppend) Descriptor() ([]byte, []int) {
|
||||
func (m *PlainTextChange_TextAppend) Reset() { *m = PlainTextChange_TextAppend{} }
|
||||
func (m *PlainTextChange_TextAppend) String() string { return proto.CompactTextString(m) }
|
||||
func (*PlainTextChange_TextAppend) ProtoMessage() {}
|
||||
func (*PlainTextChange_TextAppend) Descriptor() ([]byte, []int) {
|
||||
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)
|
||||
}
|
||||
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 {
|
||||
return xxx_messageInfo_PlainTextChangeTextAppend.Marshal(b, m, deterministic)
|
||||
return xxx_messageInfo_PlainTextChange_TextAppend.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalToSizedBuffer(b)
|
||||
@ -155,41 +155,41 @@ func (m *PlainTextChangeTextAppend) XXX_Marshal(b []byte, deterministic bool) ([
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *PlainTextChangeTextAppend) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_PlainTextChangeTextAppend.Merge(m, src)
|
||||
func (m *PlainTextChange_TextAppend) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_PlainTextChange_TextAppend.Merge(m, src)
|
||||
}
|
||||
func (m *PlainTextChangeTextAppend) XXX_Size() int {
|
||||
func (m *PlainTextChange_TextAppend) XXX_Size() int {
|
||||
return m.Size()
|
||||
}
|
||||
func (m *PlainTextChangeTextAppend) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_PlainTextChangeTextAppend.DiscardUnknown(m)
|
||||
func (m *PlainTextChange_TextAppend) XXX_DiscardUnknown() {
|
||||
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 {
|
||||
return m.Text
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type PlainTextChangeSnapshot struct {
|
||||
type PlainTextChange_Snapshot struct {
|
||||
Text string `protobuf:"bytes,1,opt,name=text,proto3" json:"text,omitempty"`
|
||||
}
|
||||
|
||||
func (m *PlainTextChangeSnapshot) Reset() { *m = PlainTextChangeSnapshot{} }
|
||||
func (m *PlainTextChangeSnapshot) String() string { return proto.CompactTextString(m) }
|
||||
func (*PlainTextChangeSnapshot) ProtoMessage() {}
|
||||
func (*PlainTextChangeSnapshot) Descriptor() ([]byte, []int) {
|
||||
func (m *PlainTextChange_Snapshot) Reset() { *m = PlainTextChange_Snapshot{} }
|
||||
func (m *PlainTextChange_Snapshot) String() string { return proto.CompactTextString(m) }
|
||||
func (*PlainTextChange_Snapshot) ProtoMessage() {}
|
||||
func (*PlainTextChange_Snapshot) Descriptor() ([]byte, []int) {
|
||||
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)
|
||||
}
|
||||
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 {
|
||||
return xxx_messageInfo_PlainTextChangeSnapshot.Marshal(b, m, deterministic)
|
||||
return xxx_messageInfo_PlainTextChange_Snapshot.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalToSizedBuffer(b)
|
||||
@ -199,42 +199,42 @@ func (m *PlainTextChangeSnapshot) XXX_Marshal(b []byte, deterministic bool) ([]b
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *PlainTextChangeSnapshot) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_PlainTextChangeSnapshot.Merge(m, src)
|
||||
func (m *PlainTextChange_Snapshot) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_PlainTextChange_Snapshot.Merge(m, src)
|
||||
}
|
||||
func (m *PlainTextChangeSnapshot) XXX_Size() int {
|
||||
func (m *PlainTextChange_Snapshot) XXX_Size() int {
|
||||
return m.Size()
|
||||
}
|
||||
func (m *PlainTextChangeSnapshot) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_PlainTextChangeSnapshot.DiscardUnknown(m)
|
||||
func (m *PlainTextChange_Snapshot) XXX_DiscardUnknown() {
|
||||
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 {
|
||||
return m.Text
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type PlainTextChangeData struct {
|
||||
Content []*PlainTextChangeContent `protobuf:"bytes,1,rep,name=content,proto3" json:"content,omitempty"`
|
||||
Snapshot *PlainTextChangeSnapshot `protobuf:"bytes,2,opt,name=snapshot,proto3" json:"snapshot,omitempty"`
|
||||
type PlainTextChange_Data struct {
|
||||
Content []*PlainTextChange_Content `protobuf:"bytes,1,rep,name=content,proto3" json:"content,omitempty"`
|
||||
Snapshot *PlainTextChange_Snapshot `protobuf:"bytes,2,opt,name=snapshot,proto3" json:"snapshot,omitempty"`
|
||||
}
|
||||
|
||||
func (m *PlainTextChangeData) Reset() { *m = PlainTextChangeData{} }
|
||||
func (m *PlainTextChangeData) String() string { return proto.CompactTextString(m) }
|
||||
func (*PlainTextChangeData) ProtoMessage() {}
|
||||
func (*PlainTextChangeData) Descriptor() ([]byte, []int) {
|
||||
func (m *PlainTextChange_Data) Reset() { *m = PlainTextChange_Data{} }
|
||||
func (m *PlainTextChange_Data) String() string { return proto.CompactTextString(m) }
|
||||
func (*PlainTextChange_Data) ProtoMessage() {}
|
||||
func (*PlainTextChange_Data) Descriptor() ([]byte, []int) {
|
||||
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)
|
||||
}
|
||||
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 {
|
||||
return xxx_messageInfo_PlainTextChangeData.Marshal(b, m, deterministic)
|
||||
return xxx_messageInfo_PlainTextChange_Data.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalToSizedBuffer(b)
|
||||
@ -244,26 +244,26 @@ func (m *PlainTextChangeData) XXX_Marshal(b []byte, deterministic bool) ([]byte,
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *PlainTextChangeData) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_PlainTextChangeData.Merge(m, src)
|
||||
func (m *PlainTextChange_Data) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_PlainTextChange_Data.Merge(m, src)
|
||||
}
|
||||
func (m *PlainTextChangeData) XXX_Size() int {
|
||||
func (m *PlainTextChange_Data) XXX_Size() int {
|
||||
return m.Size()
|
||||
}
|
||||
func (m *PlainTextChangeData) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_PlainTextChangeData.DiscardUnknown(m)
|
||||
func (m *PlainTextChange_Data) XXX_DiscardUnknown() {
|
||||
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 {
|
||||
return m.Content
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *PlainTextChangeData) GetSnapshot() *PlainTextChangeSnapshot {
|
||||
func (m *PlainTextChange_Data) GetSnapshot() *PlainTextChange_Snapshot {
|
||||
if m != nil {
|
||||
return m.Snapshot
|
||||
}
|
||||
@ -272,10 +272,10 @@ func (m *PlainTextChangeData) GetSnapshot() *PlainTextChangeSnapshot {
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*PlainTextChange)(nil), "anytype.PlainTextChange")
|
||||
proto.RegisterType((*PlainTextChangeContent)(nil), "anytype.PlainTextChange.Content")
|
||||
proto.RegisterType((*PlainTextChangeTextAppend)(nil), "anytype.PlainTextChange.TextAppend")
|
||||
proto.RegisterType((*PlainTextChangeSnapshot)(nil), "anytype.PlainTextChange.Snapshot")
|
||||
proto.RegisterType((*PlainTextChangeData)(nil), "anytype.PlainTextChange.Data")
|
||||
proto.RegisterType((*PlainTextChange_Content)(nil), "anytype.PlainTextChange.Content")
|
||||
proto.RegisterType((*PlainTextChange_TextAppend)(nil), "anytype.PlainTextChange.TextAppend")
|
||||
proto.RegisterType((*PlainTextChange_Snapshot)(nil), "anytype.PlainTextChange.Snapshot")
|
||||
proto.RegisterType((*PlainTextChange_Data)(nil), "anytype.PlainTextChange.Data")
|
||||
}
|
||||
|
||||
func init() {
|
||||
@ -326,7 +326,7 @@ func (m *PlainTextChange) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
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()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||
@ -336,12 +336,12 @@ func (m *PlainTextChangeContent) Marshal() (dAtA []byte, err error) {
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *PlainTextChangeContent) MarshalTo(dAtA []byte) (int, error) {
|
||||
func (m *PlainTextChange_Content) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.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
|
||||
var l int
|
||||
@ -358,12 +358,12 @@ func (m *PlainTextChangeContent) MarshalToSizedBuffer(dAtA []byte) (int, error)
|
||||
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()
|
||||
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)
|
||||
if m.TextAppend != nil {
|
||||
{
|
||||
@ -379,7 +379,7 @@ func (m *PlainTextChangeContentValueOfTextAppend) MarshalToSizedBuffer(dAtA []by
|
||||
}
|
||||
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()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||
@ -389,12 +389,12 @@ func (m *PlainTextChangeTextAppend) Marshal() (dAtA []byte, err error) {
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *PlainTextChangeTextAppend) MarshalTo(dAtA []byte) (int, error) {
|
||||
func (m *PlainTextChange_TextAppend) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.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
|
||||
var l int
|
||||
@ -409,7 +409,7 @@ func (m *PlainTextChangeTextAppend) MarshalToSizedBuffer(dAtA []byte) (int, erro
|
||||
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()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||
@ -419,12 +419,12 @@ func (m *PlainTextChangeSnapshot) Marshal() (dAtA []byte, err error) {
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *PlainTextChangeSnapshot) MarshalTo(dAtA []byte) (int, error) {
|
||||
func (m *PlainTextChange_Snapshot) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.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
|
||||
var l int
|
||||
@ -439,7 +439,7 @@ func (m *PlainTextChangeSnapshot) MarshalToSizedBuffer(dAtA []byte) (int, error)
|
||||
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()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||
@ -449,12 +449,12 @@ func (m *PlainTextChangeData) Marshal() (dAtA []byte, err error) {
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *PlainTextChangeData) MarshalTo(dAtA []byte) (int, error) {
|
||||
func (m *PlainTextChange_Data) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.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
|
||||
var l int
|
||||
@ -508,7 +508,7 @@ func (m *PlainTextChange) Size() (n int) {
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *PlainTextChangeContent) Size() (n int) {
|
||||
func (m *PlainTextChange_Content) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
@ -520,7 +520,7 @@ func (m *PlainTextChangeContent) Size() (n int) {
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *PlainTextChangeContentValueOfTextAppend) Size() (n int) {
|
||||
func (m *PlainTextChange_Content_TextAppend) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
@ -532,7 +532,7 @@ func (m *PlainTextChangeContentValueOfTextAppend) Size() (n int) {
|
||||
}
|
||||
return n
|
||||
}
|
||||
func (m *PlainTextChangeTextAppend) Size() (n int) {
|
||||
func (m *PlainTextChange_TextAppend) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
@ -545,7 +545,7 @@ func (m *PlainTextChangeTextAppend) Size() (n int) {
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *PlainTextChangeSnapshot) Size() (n int) {
|
||||
func (m *PlainTextChange_Snapshot) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
@ -558,7 +558,7 @@ func (m *PlainTextChangeSnapshot) Size() (n int) {
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *PlainTextChangeData) Size() (n int) {
|
||||
func (m *PlainTextChange_Data) Size() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
@ -633,7 +633,7 @@ func (m *PlainTextChange) Unmarshal(dAtA []byte) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *PlainTextChangeContent) Unmarshal(dAtA []byte) error {
|
||||
func (m *PlainTextChange_Content) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
@ -691,11 +691,11 @@ func (m *PlainTextChangeContent) Unmarshal(dAtA []byte) error {
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
v := &PlainTextChangeTextAppend{}
|
||||
v := &PlainTextChange_TextAppend{}
|
||||
if err := v.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
m.Value = &PlainTextChangeContentValueOfTextAppend{v}
|
||||
m.Value = &PlainTextChange_Content_TextAppend{v}
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
@ -718,7 +718,7 @@ func (m *PlainTextChangeContent) Unmarshal(dAtA []byte) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *PlainTextChangeTextAppend) Unmarshal(dAtA []byte) error {
|
||||
func (m *PlainTextChange_TextAppend) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
@ -800,7 +800,7 @@ func (m *PlainTextChangeTextAppend) Unmarshal(dAtA []byte) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *PlainTextChangeSnapshot) Unmarshal(dAtA []byte) error {
|
||||
func (m *PlainTextChange_Snapshot) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
@ -882,7 +882,7 @@ func (m *PlainTextChangeSnapshot) Unmarshal(dAtA []byte) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *PlainTextChangeData) Unmarshal(dAtA []byte) error {
|
||||
func (m *PlainTextChange_Data) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
@ -940,7 +940,7 @@ func (m *PlainTextChangeData) Unmarshal(dAtA []byte) error {
|
||||
if postIndex > l {
|
||||
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 {
|
||||
return err
|
||||
}
|
||||
@ -975,7 +975,7 @@ func (m *PlainTextChangeData) Unmarshal(dAtA []byte) error {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if m.Snapshot == nil {
|
||||
m.Snapshot = &PlainTextChangeSnapshot{}
|
||||
m.Snapshot = &PlainTextChange_Snapshot{}
|
||||
}
|
||||
if err := m.Snapshot.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
|
||||
@ -16,7 +16,7 @@ var (
|
||||
|
||||
type ChangeContent struct {
|
||||
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
|
||||
}
|
||||
|
||||
@ -34,8 +34,9 @@ type Change struct {
|
||||
visited bool
|
||||
branchesFinished bool
|
||||
|
||||
Content *aclpb.Change
|
||||
Sign []byte
|
||||
Content *aclpb.TreeChange
|
||||
Identity string
|
||||
Sign []byte
|
||||
}
|
||||
|
||||
func (ch *Change) ProtoChange() proto.Marshaler {
|
||||
@ -56,7 +57,7 @@ func (ch *Change) DecryptContents(key *symmetric.Key) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewChange(id string, ch *aclpb.Change, signature []byte) *Change {
|
||||
func NewChange(id string, ch *aclpb.TreeChange, signature []byte) *Change {
|
||||
return &Change{
|
||||
Next: nil,
|
||||
PreviousIds: ch.TreeHeadIds,
|
||||
@ -64,6 +65,7 @@ func NewChange(id string, ch *aclpb.Change, signature []byte) *Change {
|
||||
Content: ch,
|
||||
SnapshotId: ch.SnapshotBaseId,
|
||||
IsSnapshot: ch.IsSnapshot,
|
||||
Identity: string(ch.Identity),
|
||||
Sign: signature,
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package tree
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/aclchanges/aclpb"
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/pkg/acl/common"
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/cid"
|
||||
@ -10,25 +11,24 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
const componentBuilder = "tree.changebuilder"
|
||||
var ErrEmptyChange = errors.New("change payload should not be empty")
|
||||
|
||||
type BuilderContent struct {
|
||||
treeHeadIds []string
|
||||
aclHeadId string
|
||||
snapshotBaseId string
|
||||
currentReadKeyHash uint64
|
||||
identity string
|
||||
identity []byte
|
||||
isSnapshot bool
|
||||
signingKey signingkey.PrivKey
|
||||
readKey *symmetric.Key
|
||||
content proto.Marshaler
|
||||
content []byte
|
||||
}
|
||||
|
||||
type ChangeBuilder interface {
|
||||
ConvertFromRaw(rawChange *aclpb.RawChange) (ch *Change, err error)
|
||||
ConvertFromRawAndVerify(rawChange *aclpb.RawChange) (ch *Change, err error)
|
||||
BuildContent(payload BuilderContent) (ch *Change, raw *aclpb.RawChange, err error)
|
||||
BuildRaw(ch *Change) (*aclpb.RawChange, error)
|
||||
ConvertFromRaw(rawIdChange *aclpb.RawTreeChangeWithId, verify bool) (ch *Change, err error)
|
||||
BuildContent(payload BuilderContent) (ch *Change, raw *aclpb.RawTreeChangeWithId, err error)
|
||||
BuildRaw(ch *Change) (*aclpb.RawTreeChangeWithId, error)
|
||||
}
|
||||
|
||||
type changeBuilder struct {
|
||||
@ -39,49 +39,55 @@ func newChangeBuilder(keys *common.Keychain) ChangeBuilder {
|
||||
return &changeBuilder{keys: keys}
|
||||
}
|
||||
|
||||
func (c *changeBuilder) ConvertFromRaw(rawChange *aclpb.RawChange) (ch *Change, err error) {
|
||||
unmarshalled := &aclpb.Change{}
|
||||
err = proto.Unmarshal(rawChange.Payload, unmarshalled)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
func (c *changeBuilder) ConvertFromRaw(rawIdChange *aclpb.RawTreeChangeWithId, verify bool) (ch *Change, err error) {
|
||||
if rawIdChange.GetRawChange() == nil {
|
||||
err = ErrEmptyChange
|
||||
return
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
func (c *changeBuilder) ConvertFromRawAndVerify(rawChange *aclpb.RawChange) (ch *Change, err error) {
|
||||
unmarshalled := &aclpb.Change{}
|
||||
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{
|
||||
func (c *changeBuilder) BuildContent(payload BuilderContent) (ch *Change, rawIdChange *aclpb.RawTreeChangeWithId, err error) {
|
||||
change := &aclpb.TreeChange{
|
||||
TreeHeadIds: payload.treeHeadIds,
|
||||
AclHeadId: payload.aclHeadId,
|
||||
SnapshotBaseId: payload.snapshotBaseId,
|
||||
@ -90,53 +96,65 @@ func (c *changeBuilder) BuildContent(payload BuilderContent) (ch *Change, raw *a
|
||||
Identity: payload.identity,
|
||||
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 {
|
||||
return
|
||||
}
|
||||
|
||||
encrypted, err := payload.readKey.Encrypt(marshalledData)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
aclChange.ChangesData = encrypted
|
||||
|
||||
fullMarshalledChange, err := proto.Marshal(aclChange)
|
||||
signature, err := payload.signingKey.Sign(marshalledChange)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
signature, err := payload.signingKey.Sign(fullMarshalledChange)
|
||||
raw := &aclpb.RawTreeChange{
|
||||
Payload: marshalledChange,
|
||||
Signature: signature,
|
||||
}
|
||||
|
||||
marshalledRawChange, err := proto.Marshal(raw)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
id, err := cid.NewCIDFromBytes(fullMarshalledChange)
|
||||
id, err := cid.NewCIDFromBytes(marshalledRawChange)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
ch = NewChange(id, aclChange, signature)
|
||||
ch = NewChange(id, change, signature)
|
||||
ch.ParsedModel = payload.content
|
||||
|
||||
raw = &aclpb.RawChange{
|
||||
Payload: fullMarshalledChange,
|
||||
Signature: signature,
|
||||
rawIdChange = &aclpb.RawTreeChangeWithId{
|
||||
RawChange: marshalledRawChange,
|
||||
Id: id,
|
||||
}
|
||||
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
|
||||
marshalled, err = ch.Content.Marshal()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
raw = &aclpb.RawChange{
|
||||
marshalledRawChange, err := proto.Marshal(&aclpb.RawTreeChange{
|
||||
Payload: marshalled,
|
||||
Signature: ch.Signature(),
|
||||
Signature: ch.Sign,
|
||||
})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
raw = &aclpb.RawTreeChangeWithId{
|
||||
RawChange: marshalledRawChange,
|
||||
Id: ch.Id,
|
||||
}
|
||||
return
|
||||
|
||||
@ -48,7 +48,7 @@ func (v *objectTreeValidator) validateChange(tree *Tree, aclList list.ACLList, c
|
||||
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
|
||||
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/storage"
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/symmetric"
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/slice"
|
||||
"go.uber.org/zap"
|
||||
"sync"
|
||||
)
|
||||
|
||||
@ -34,7 +32,7 @@ type AddResultSummary int
|
||||
type AddResult struct {
|
||||
OldHeads []string
|
||||
Heads []string
|
||||
Added []*aclpb.RawChange
|
||||
Added []*aclpb.RawTreeChangeWithId
|
||||
|
||||
Mode Mode
|
||||
}
|
||||
@ -46,7 +44,7 @@ type ObjectTree interface {
|
||||
RWLocker
|
||||
|
||||
ID() string
|
||||
Header() *aclpb.Header
|
||||
Header() *aclpb.TreeHeader
|
||||
Heads() []string
|
||||
Root() *Change
|
||||
HasChange(string) bool
|
||||
@ -55,13 +53,13 @@ type ObjectTree interface {
|
||||
IterateFrom(id string, convert ChangeConvertFunc, iterate ChangeIterateFunc) error
|
||||
|
||||
SnapshotPath() []string
|
||||
ChangesAfterCommonSnapshot(snapshotPath, heads []string) ([]*aclpb.RawChange, error)
|
||||
ChangesAfterCommonSnapshot(snapshotPath, heads []string) ([]*aclpb.RawTreeChangeWithId, error)
|
||||
|
||||
Storage() storage.TreeStorage
|
||||
DebugDump() (string, error)
|
||||
|
||||
AddContent(ctx context.Context, content SignableChangeContent) (*aclpb.RawChange, error)
|
||||
AddRawChanges(ctx context.Context, changes ...*aclpb.RawChange) (AddResult, error)
|
||||
AddContent(ctx context.Context, content SignableChangeContent) (*aclpb.RawTreeChangeWithId, error)
|
||||
AddRawChanges(ctx context.Context, changes ...*aclpb.RawTreeChangeWithId) (AddResult, error)
|
||||
|
||||
Close() error
|
||||
}
|
||||
@ -76,13 +74,13 @@ type objectTree struct {
|
||||
aclList list.ACLList
|
||||
|
||||
id string
|
||||
header *aclpb.Header
|
||||
header *aclpb.TreeHeader
|
||||
tree *Tree
|
||||
|
||||
keys map[uint64]*symmetric.Key
|
||||
|
||||
// buffers
|
||||
difSnapshotBuf []*aclpb.RawChange
|
||||
difSnapshotBuf []*aclpb.RawTreeChangeWithId
|
||||
tmpChangesBuf []*Change
|
||||
newSnapshotsBuf []*Change
|
||||
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) {
|
||||
ot.treeBuilder.Reset()
|
||||
|
||||
@ -201,7 +140,7 @@ func (ot *objectTree) ID() string {
|
||||
return ot.id
|
||||
}
|
||||
|
||||
func (ot *objectTree) Header() *aclpb.Header {
|
||||
func (ot *objectTree) Header() *aclpb.TreeHeader {
|
||||
return ot.header
|
||||
}
|
||||
|
||||
@ -209,7 +148,7 @@ func (ot *objectTree) Storage() storage.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() {
|
||||
if err == nil && ot.updateListener != nil {
|
||||
ot.updateListener.Update(ot)
|
||||
@ -258,12 +197,12 @@ func (ot *objectTree) prepareBuilderContent(content SignableChangeContent) (cnt
|
||||
isSnapshot: content.IsSnapshot,
|
||||
signingKey: content.Key,
|
||||
readKey: readKey,
|
||||
content: content.Proto,
|
||||
content: content.Data,
|
||||
}
|
||||
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
|
||||
mode, addResult, err = ot.addRawChanges(ctx, rawChanges...)
|
||||
if err != nil {
|
||||
@ -302,7 +241,7 @@ func (ot *objectTree) AddRawChanges(ctx context.Context, rawChanges ...*aclpb.Ra
|
||||
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
|
||||
ot.tmpChangesBuf = ot.tmpChangesBuf[:0]
|
||||
ot.notSeenIdxBuf = ot.notSeenIdxBuf[:0]
|
||||
@ -329,7 +268,7 @@ func (ot *objectTree) addRawChanges(ctx context.Context, rawChanges ...*aclpb.Ra
|
||||
}
|
||||
|
||||
var change *Change
|
||||
change, err = ot.changeBuilder.ConvertFromRawAndVerify(ch)
|
||||
change, err = ot.changeBuilder.ConvertFromRaw(ch, true)
|
||||
if err != nil {
|
||||
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
|
||||
// they can include not only the changes that were added now,
|
||||
// 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{})
|
||||
|
||||
// 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 {
|
||||
// if we got some changes that we need to convert to raw
|
||||
if _, exists := alreadyConverted[ch]; !exists {
|
||||
var raw *aclpb.RawChange
|
||||
var raw *aclpb.RawTreeChangeWithId
|
||||
raw, err = ot.changeBuilder.BuildRaw(ch)
|
||||
if err != nil {
|
||||
return
|
||||
@ -421,7 +360,7 @@ func (ot *objectTree) addRawChanges(ctx context.Context, rawChanges ...*aclpb.Ra
|
||||
ot.rebuildFromStorage(nil)
|
||||
return
|
||||
}
|
||||
var added []*aclpb.RawChange
|
||||
var added []*aclpb.RawTreeChangeWithId
|
||||
added, err = getAddedChanges(nil)
|
||||
// we shouldn't get any error in this case
|
||||
if err != nil {
|
||||
@ -457,7 +396,7 @@ func (ot *objectTree) addRawChanges(ctx context.Context, rawChanges ...*aclpb.Ra
|
||||
err = ErrHasInvalidChanges
|
||||
return
|
||||
}
|
||||
var added []*aclpb.RawChange
|
||||
var added []*aclpb.RawTreeChangeWithId
|
||||
added, err = getAddedChanges(treeChangesAdded)
|
||||
if err != nil {
|
||||
// that means that some unattached changes were somehow corrupted in memory
|
||||
@ -553,7 +492,7 @@ func (ot *objectTree) SnapshotPath() []string {
|
||||
return path
|
||||
}
|
||||
|
||||
func (ot *objectTree) ChangesAfterCommonSnapshot(theirPath, theirHeads []string) ([]*aclpb.RawChange, error) {
|
||||
func (ot *objectTree) ChangesAfterCommonSnapshot(theirPath, theirHeads []string) ([]*aclpb.RawTreeChangeWithId, error) {
|
||||
var (
|
||||
needFullDocument = len(theirPath) == 0
|
||||
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)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
|
||||
@ -15,7 +15,7 @@ import (
|
||||
type mockChangeCreator struct{}
|
||||
|
||||
func (c *mockChangeCreator) createRaw(id, aclId, snapshotId string, isSnapshot bool, prevIds ...string) *aclpb.RawChange {
|
||||
aclChange := &aclpb.Change{
|
||||
aclChange := &aclpb.TreeChange{
|
||||
TreeHeadIds: prevIds,
|
||||
AclHeadId: aclId,
|
||||
SnapshotBaseId: snapshotId,
|
||||
@ -23,22 +23,27 @@ func (c *mockChangeCreator) createRaw(id, aclId, snapshotId string, isSnapshot b
|
||||
IsSnapshot: isSnapshot,
|
||||
}
|
||||
res, _ := aclChange.Marshal()
|
||||
return &aclpb.RawChange{
|
||||
|
||||
raw := &aclpb.RawTreeChange{
|
||||
Payload: res,
|
||||
Signature: nil,
|
||||
}
|
||||
rawMarshalled, _ := raw.Marshal()
|
||||
|
||||
return &aclpb.RawTreeChangeWithId{
|
||||
RawChange: rawMarshalled,
|
||||
Id: id,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *mockChangeCreator) createNewTreeStorage(treeId, aclListId, aclHeadId, firstChangeId string) storage.TreeStorage {
|
||||
firstChange := c.createRaw(firstChangeId, aclHeadId, "", true)
|
||||
header := &aclpb.Header{
|
||||
FirstId: firstChangeId,
|
||||
AclListId: aclListId,
|
||||
WorkspaceId: "",
|
||||
DocType: aclpb.Header_DocTree,
|
||||
header := &aclpb.TreeHeader{
|
||||
FirstId: firstChangeId,
|
||||
AclId: aclListId,
|
||||
TreeHeaderType: aclpb.TreeHeaderType_Object,
|
||||
}
|
||||
treeStorage, _ := storage.NewInMemoryTreeStorage(treeId, header, []string{firstChangeId}, []*aclpb.RawChange{firstChange})
|
||||
treeStorage, _ := storage.NewInMemoryTreeStorage(treeId, header, []string{firstChangeId}, []*aclpb.RawTreeChangeWithId{firstChange})
|
||||
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 {
|
||||
change *Change
|
||||
rawChange *aclpb.RawChange
|
||||
rawChange *aclpb.RawTreeChangeWithId
|
||||
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
|
||||
for _, h := range t.headIds {
|
||||
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 {
|
||||
var raw *aclpb.RawChange
|
||||
var raw *aclpb.RawTreeChangeWithId
|
||||
raw, err = r.changeBuilder.BuildRaw(ch)
|
||||
if err != nil {
|
||||
return
|
||||
@ -95,7 +95,7 @@ func (r *rawChangeLoader) LoadFromTree(t *Tree, breakpoints []string) ([]*aclpb.
|
||||
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
|
||||
r.cache = make(map[string]rawCacheEntry)
|
||||
defer func() {
|
||||
@ -162,7 +162,7 @@ func (r *rawChangeLoader) LoadFromStorage(commonSnapshot string, heads, breakpoi
|
||||
|
||||
// preparing first pass
|
||||
r.idStack = append(r.idStack, heads...)
|
||||
var buffer []*aclpb.RawChange
|
||||
var buffer []*aclpb.RawTreeChangeWithId
|
||||
|
||||
rootVisited := dfs(commonSnapshot, heads, 0,
|
||||
func(counter int, mapExists bool) bool {
|
||||
@ -203,7 +203,7 @@ func (r *rawChangeLoader) LoadFromStorage(commonSnapshot string, heads, breakpoi
|
||||
})
|
||||
|
||||
// discarding visited
|
||||
buffer = discardFromSlice(buffer, func(change *aclpb.RawChange) bool {
|
||||
buffer = discardFromSlice(buffer, func(change *aclpb.RawTreeChangeWithId) bool {
|
||||
return change == nil
|
||||
})
|
||||
|
||||
@ -219,7 +219,7 @@ func (r *rawChangeLoader) loadEntry(id string) (entry rawCacheEntry, err error)
|
||||
return
|
||||
}
|
||||
|
||||
change, err := r.changeBuilder.ConvertFromRaw(rawChange)
|
||||
change, err := r.changeBuilder.ConvertFromRaw(rawChange, false)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@ -2,12 +2,11 @@ package tree
|
||||
|
||||
import (
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys/asymmetric/signingkey"
|
||||
"github.com/gogo/protobuf/proto"
|
||||
)
|
||||
|
||||
type SignableChangeContent struct {
|
||||
Proto proto.Marshaler
|
||||
Data []byte
|
||||
Key signingkey.PrivKey
|
||||
Identity string
|
||||
Identity []byte
|
||||
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
|
||||
}
|
||||
|
||||
ch, err = tb.builder.ConvertFromRawAndVerify(change)
|
||||
ch, err = tb.builder.ConvertFromRaw(change, true)
|
||||
if err != nil {
|
||||
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 {
|
||||
Id string
|
||||
Header *aclpb.Header
|
||||
Records []*aclpb.RawRecord
|
||||
Records []*aclpb.RawACLRecord
|
||||
}
|
||||
|
||||
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