WIP ACLTree
This commit is contained in:
parent
ed06aadd21
commit
8570c4e318
@ -2,8 +2,11 @@ package acltree
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/account"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/account"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/aclchanges/pb"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/thread"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/thread"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/slice"
|
||||||
|
"github.com/gogo/protobuf/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
type AddResultSummary int
|
type AddResultSummary int
|
||||||
@ -37,6 +40,7 @@ type aclTree struct {
|
|||||||
accountData *account.AccountData
|
accountData *account.AccountData
|
||||||
|
|
||||||
fullTree *Tree
|
fullTree *Tree
|
||||||
|
aclTree *Tree // this tree is built from start of the document
|
||||||
aclState *ACLState
|
aclState *ACLState
|
||||||
|
|
||||||
treeBuilder *treeBuilder
|
treeBuilder *treeBuilder
|
||||||
@ -70,9 +74,36 @@ func BuildACLTree(t thread.Thread, acc *account.AccountData) (ACLTree, error) {
|
|||||||
return aclTree, nil
|
return aclTree, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *aclTree) rebuildFromThread(fromStart bool) error {
|
func (a *aclTree) rebuildFromTree(validateSnapshot bool) (err error) {
|
||||||
var aclTree *Tree
|
if validateSnapshot {
|
||||||
|
err = a.snapshotValidator.init(a.aclTree)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
valid, err := a.snapshotValidator.validateSnapshot(a.fullTree.root)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !valid {
|
||||||
|
return a.rebuildFromThread(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = a.aclStateBuilder.init(a.fullTree)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
a.aclState, err = a.aclStateBuilder.build()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *aclTree) rebuildFromThread(fromStart bool) error {
|
||||||
a.treeBuilder.init()
|
a.treeBuilder.init()
|
||||||
a.aclTreeBuilder.init()
|
a.aclTreeBuilder.init()
|
||||||
|
|
||||||
@ -83,13 +114,13 @@ func (a *aclTree) rebuildFromThread(fromStart bool) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: remove this from context as this is used only to validate snapshot
|
// TODO: remove this from context as this is used only to validate snapshot
|
||||||
aclTree, err = a.aclTreeBuilder.build()
|
a.aclTree, err = a.aclTreeBuilder.build()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if !fromStart {
|
if !fromStart {
|
||||||
err = a.snapshotValidator.init(aclTree)
|
err = a.snapshotValidator.init(a.aclTree)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -115,19 +146,120 @@ func (a *aclTree) rebuildFromThread(fromStart bool) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: this should not be the responsibility of ACLTree, move it somewhere else after testing
|
||||||
|
func (a *aclTree) getACLHeads() []string {
|
||||||
|
var aclTreeHeads []string
|
||||||
|
for _, head := range a.fullTree.Heads() {
|
||||||
|
if slice.FindPos(aclTreeHeads, head) != -1 { // do not scan known heads
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
precedingHeads := a.getPrecedingACLHeads(head)
|
||||||
|
|
||||||
|
for _, aclHead := range precedingHeads {
|
||||||
|
if slice.FindPos(aclTreeHeads, aclHead) != -1 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
aclTreeHeads = append(aclTreeHeads, aclHead)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return aclTreeHeads
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *aclTree) getPrecedingACLHeads(head string) []string {
|
||||||
|
headChange := a.fullTree.attached[head]
|
||||||
|
|
||||||
|
if headChange.Content.GetAclData() != nil {
|
||||||
|
return []string{head}
|
||||||
|
} else {
|
||||||
|
return headChange.Content.AclHeadIds
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (a *aclTree) ACLState() *ACLState {
|
func (a *aclTree) ACLState() *ACLState {
|
||||||
//TODO implement me
|
return a.aclState
|
||||||
panic("implement me")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *aclTree) AddContent(changeContent *ChangeContent) (*Change, error) {
|
func (a *aclTree) AddContent(changeContent *ChangeContent) (*Change, error) {
|
||||||
//TODO implement me
|
// TODO: add snapshot creation logic
|
||||||
panic("implement me")
|
marshalled, err := changeContent.ChangesData.Marshal()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
encrypted, err := a.aclState.userReadKeys[a.aclState.currentReadKeyHash].
|
||||||
|
Encrypt(marshalled)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
aclChange := &pb.ACLChange{
|
||||||
|
TreeHeadIds: a.fullTree.Heads(),
|
||||||
|
AclHeadIds: a.getACLHeads(),
|
||||||
|
SnapshotBaseId: a.fullTree.RootId(),
|
||||||
|
AclData: changeContent.ACLData,
|
||||||
|
ChangesData: encrypted,
|
||||||
|
CurrentReadKeyHash: a.aclState.currentReadKeyHash,
|
||||||
|
Timestamp: 0,
|
||||||
|
Identity: a.accountData.Identity,
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: add CID creation logic based on content
|
||||||
|
ch := NewChange(changeContent.Id, aclChange)
|
||||||
|
ch.DecryptedDocumentChange = marshalled
|
||||||
|
|
||||||
|
fullMarshalledChange, err := proto.Marshal(aclChange)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
signature, err := a.accountData.SignKey.Sign(fullMarshalledChange)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if aclChange.AclData != nil {
|
||||||
|
// we can apply change right away without going through builder, because
|
||||||
|
err = a.aclState.applyChange(changeContent.Id, aclChange)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
a.fullTree.AddFast(ch)
|
||||||
|
|
||||||
|
err = a.thread.AddChange(&thread.RawChange{
|
||||||
|
Payload: marshalled,
|
||||||
|
Signature: signature,
|
||||||
|
Id: changeContent.Id,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
a.thread.SetHeads([]string{ch.Id})
|
||||||
|
return a.fullTree.attached[changeContent.Id], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *aclTree) AddChanges(changes ...*Change) (AddResult, error) {
|
func (a *aclTree) AddChanges(changes ...*Change) (AddResult, error) {
|
||||||
//TODO implement me
|
var aclChanges []*Change
|
||||||
panic("implement me")
|
for _, ch := range changes {
|
||||||
|
if ch.IsACLChange() {
|
||||||
|
aclChanges = append(aclChanges, ch)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: understand the common snapshot problem
|
||||||
|
prevHeads := a.fullTree.Heads()
|
||||||
|
prevRoot := a.
|
||||||
|
mode := a.fullTree.Add(changes...)
|
||||||
|
switch mode {
|
||||||
|
case acltree.Nothing:
|
||||||
|
return d.docContext.docState, UpdateResultNoAction, nil
|
||||||
|
case acltree.Rebuild:
|
||||||
|
res, err := d.Build()
|
||||||
|
return res, UpdateResultRebuild, err
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *aclTree) Heads() []string {
|
func (a *aclTree) Heads() []string {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user