WIP change creation logic
This commit is contained in:
parent
eea64a3014
commit
2f66bd3e9c
@ -33,8 +33,7 @@ func (sb *ACLStateBuilder) Build() (*ACLState, error) {
|
||||
return state, err
|
||||
}
|
||||
|
||||
func (sb *ACLStateBuilder) Init(
|
||||
tree *Tree) error {
|
||||
func (sb *ACLStateBuilder) Init(tree *Tree) error {
|
||||
root := tree.Root()
|
||||
if !root.IsSnapshot {
|
||||
return fmt.Errorf("root should always be a snapshot")
|
||||
|
||||
@ -128,7 +128,7 @@ func (tb *ACLTreeBuilder) getACLHeads(heads []string) (aclTreeHeads []string, er
|
||||
}
|
||||
precedingHeads, err := tb.getPrecedingACLHeads(head)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
continue
|
||||
}
|
||||
|
||||
for _, aclHead := range precedingHeads {
|
||||
|
||||
@ -2,11 +2,15 @@ package data
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/data/pb"
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/data/threadmodels"
|
||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/slice"
|
||||
"github.com/gogo/protobuf/proto"
|
||||
)
|
||||
|
||||
type AccountData struct {
|
||||
Identity string
|
||||
SignKey threadmodels.SigningPrivKey
|
||||
EncKey threadmodels.EncryptionPrivKey
|
||||
}
|
||||
|
||||
@ -33,6 +37,12 @@ const (
|
||||
UpdateResultRebuild
|
||||
)
|
||||
|
||||
type CreateChangePayload struct {
|
||||
ChangesData proto.Marshaler
|
||||
ACLData *pb.ACLChangeACLData
|
||||
Id string // TODO: this is just for testing, because id should be created automatically from content
|
||||
}
|
||||
|
||||
func NewDocument(
|
||||
thread threadmodels.Thread,
|
||||
stateProvider InitialStateProvider,
|
||||
@ -53,6 +63,59 @@ func NewDocument(
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Document) Create(payload *CreateChangePayload) error {
|
||||
// TODO: add snapshot creation logic
|
||||
marshalled, err := payload.ChangesData.Marshal()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
encrypted, err := d.docContext.aclState.userReadKeys[d.docContext.aclState.currentReadKeyHash].
|
||||
Encrypt(marshalled)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
aclChange := &pb.ACLChange{
|
||||
TreeHeadIds: d.docContext.fullTree.Heads(),
|
||||
AclHeadIds: d.getACLHeads(),
|
||||
SnapshotBaseId: d.docContext.fullTree.RootId(),
|
||||
AclData: payload.ACLData,
|
||||
ChangesData: encrypted,
|
||||
CurrentReadKeyHash: d.docContext.aclState.currentReadKeyHash,
|
||||
Timestamp: 0,
|
||||
Identity: d.accountData.Identity,
|
||||
}
|
||||
|
||||
// TODO: add CID creation logic based on content
|
||||
ch := NewChange(payload.Id, aclChange)
|
||||
ch.DecryptedDocumentChange = marshalled
|
||||
|
||||
fullMarshalledChange, err := proto.Marshal(aclChange)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
signature, err := d.accountData.SignKey.Sign(fullMarshalledChange)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
d.docContext.fullTree.AddFast(ch)
|
||||
|
||||
err = d.thread.AddChange(&threadmodels.RawChange{
|
||||
Payload: marshalled,
|
||||
Signature: signature,
|
||||
Id: payload.Id,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
d.thread.SetHeads([]string{ch.Id})
|
||||
d.thread.SetMaybeHeads([]string{ch.Id})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Document) Update(changes ...*threadmodels.RawChange) (DocumentState, UpdateResult, error) {
|
||||
var treeChanges []*Change
|
||||
|
||||
@ -133,6 +196,35 @@ func (d *Document) Build() (DocumentState, error) {
|
||||
return d.build(false)
|
||||
}
|
||||
|
||||
// TODO: this should not be the responsibility of Document, move it somewhere else after testing
|
||||
func (d *Document) getACLHeads() []string {
|
||||
var aclTreeHeads []string
|
||||
for _, head := range d.docContext.fullTree.Heads() {
|
||||
if slice.FindPos(aclTreeHeads, head) != -1 { // do not scan known heads
|
||||
continue
|
||||
}
|
||||
precedingHeads := d.getPrecedingACLHeads(head)
|
||||
|
||||
for _, aclHead := range precedingHeads {
|
||||
if slice.FindPos(aclTreeHeads, aclHead) != -1 {
|
||||
continue
|
||||
}
|
||||
aclTreeHeads = append(aclTreeHeads, aclHead)
|
||||
}
|
||||
}
|
||||
return aclTreeHeads
|
||||
}
|
||||
|
||||
func (d *Document) getPrecedingACLHeads(head string) []string {
|
||||
headChange := d.docContext.fullTree.attached[head]
|
||||
|
||||
if headChange.Content.GetAclData() != nil {
|
||||
return []string{head}
|
||||
} else {
|
||||
return headChange.Content.AclHeadIds
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Document) build(fromStart bool) (DocumentState, error) {
|
||||
d.treeBuilder.Init()
|
||||
d.aclTreeBuilder.Init()
|
||||
@ -143,6 +235,7 @@ func (d *Document) build(fromStart bool) (DocumentState, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// TODO: remove this from context as this is used only to validate snapshot
|
||||
d.docContext.aclTree, err = d.aclTreeBuilder.Build()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@ -64,6 +64,7 @@ func (d *documentStateBuilder) build() (s DocumentState, err error) {
|
||||
}
|
||||
|
||||
func (d *documentStateBuilder) appendFrom(fromId string, init DocumentState) (s DocumentState, err error) {
|
||||
// TODO: we should do something like state copy probably
|
||||
s = init
|
||||
d.tree.Iterate(fromId, func(c *Change) (isContinue bool) {
|
||||
if c.Id == fromId {
|
||||
|
||||
133
data/threadbuilder/userjoinexampleupdate.yml
Normal file
133
data/threadbuilder/userjoinexampleupdate.yml
Normal file
@ -0,0 +1,133 @@
|
||||
thread:
|
||||
author: A
|
||||
changes:
|
||||
- id: A.1.1
|
||||
identity: A
|
||||
aclSnapshot:
|
||||
userStates:
|
||||
- identity: A
|
||||
encryptionKey: key.Enc.A
|
||||
encryptedReadKeys: [key.Read.1]
|
||||
permission: admin
|
||||
snapshot:
|
||||
text: "some text"
|
||||
aclChanges:
|
||||
- userAdd:
|
||||
identity: A
|
||||
permission: admin
|
||||
encryptionKey: key.Enc.A
|
||||
encryptedReadKeys: [key.Read.1]
|
||||
changes:
|
||||
- textAppend:
|
||||
text: "some text"
|
||||
readKey: key.Read.1
|
||||
- id: A.1.2
|
||||
identity: A
|
||||
aclChanges:
|
||||
- userInvite:
|
||||
acceptKey: key.Sign.Onetime1
|
||||
encryptionKey: key.Enc.Onetime1
|
||||
encryptedReadKeys: [key.Read.1]
|
||||
permissions: writer
|
||||
- userAdd:
|
||||
identity: C
|
||||
permission: reader
|
||||
encryptionKey: key.Enc.C
|
||||
encryptedReadKeys: [ key.Read.1 ]
|
||||
readKey: key.Read.1
|
||||
- id: A.1.3
|
||||
identity: A
|
||||
changes:
|
||||
- textAppend:
|
||||
text: "second"
|
||||
readKey: key.Read.1
|
||||
- id: B.1.1
|
||||
identity: B
|
||||
aclChanges:
|
||||
- userJoin:
|
||||
identity: B
|
||||
encryptionKey: key.Enc.B
|
||||
acceptSignature: key.Sign.Onetime1
|
||||
inviteId: A.1.2
|
||||
encryptedReadKeys: [key.Read.1]
|
||||
readKey: key.Read.1
|
||||
- id: B.1.2
|
||||
identity: B
|
||||
changes:
|
||||
- textAppend:
|
||||
text: "first"
|
||||
readKey: key.Read.1
|
||||
- id: C.1.1
|
||||
identity: C
|
||||
changes:
|
||||
- textAppend:
|
||||
text: "third"
|
||||
readKey: key.Read.1
|
||||
keys:
|
||||
Enc:
|
||||
- A
|
||||
- B
|
||||
- C
|
||||
- D
|
||||
- Onetime1
|
||||
Sign:
|
||||
- A
|
||||
- B
|
||||
- C
|
||||
- D
|
||||
- Onetime1
|
||||
Read:
|
||||
- 1
|
||||
graph:
|
||||
- id: A.1.1
|
||||
baseSnapshot: A.1.1
|
||||
- id: A.1.2
|
||||
baseSnapshot: A.1.1
|
||||
aclHeads: [A.1.1]
|
||||
treeHeads: [A.1.1]
|
||||
- id: B.1.1
|
||||
baseSnapshot: A.1.1
|
||||
aclHeads: [A.1.2]
|
||||
treeHeads: [A.1.2]
|
||||
- id: B.1.2
|
||||
baseSnapshot: A.1.1
|
||||
aclHeads: [B.1.1]
|
||||
treeHeads: [B.1.1]
|
||||
- id: A.1.3 # this should be invalid, because it is based on one of the invalid changes
|
||||
baseSnapshot: A.1.1
|
||||
aclHeads: [B.1.1]
|
||||
treeHeads: [B.1.2, C.1.1]
|
||||
- id: C.1.1 # this should be invalid, because C is a reader
|
||||
baseSnapshot: A.1.1
|
||||
aclHeads: [B.1.1]
|
||||
treeHeads: [B.1.1]
|
||||
maybeHeads:
|
||||
- "A.1.3"
|
||||
updatedChanges:
|
||||
- id: B.1.3
|
||||
identity: B
|
||||
changes:
|
||||
- textAppend:
|
||||
text: "second"
|
||||
readKey: key.Read.1
|
||||
- id: A.1.4
|
||||
identity: A
|
||||
aclChanges:
|
||||
- userAdd:
|
||||
identity: D
|
||||
permission: writer
|
||||
encryptionKey: key.Enc.D
|
||||
encryptedReadKeys: [ key.Read.1 ]
|
||||
changes:
|
||||
- textAppend:
|
||||
text: "second"
|
||||
readKey: key.Read.1
|
||||
updatedGraph:
|
||||
- id: B.1.3
|
||||
baseSnapshot: A.1.1
|
||||
aclHeads: [ B.1.1 ]
|
||||
treeHeads: [ B.1.2 ]
|
||||
- id: A.1.4
|
||||
baseSnapshot: A.1.1
|
||||
aclHeads: [ B.1.1 ]
|
||||
treeHeads: [ B.1.3 ]
|
||||
Loading…
x
Reference in New Issue
Block a user