Add new heads logic
This commit is contained in:
parent
0e62047498
commit
2940519b5f
@ -36,7 +36,7 @@ func (tb *ACLTreeBuilder) Init() {
|
||||
}
|
||||
|
||||
func (tb *ACLTreeBuilder) Build() (*Tree, error) {
|
||||
heads := tb.thread.Heads()
|
||||
heads := tb.thread.MaybeHeads()
|
||||
aclHeads, err := tb.getACLHeads(heads)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@ -64,6 +64,8 @@ func (d *Document) Update(changes ...*threadmodels.RawChange) (DocumentState, Up
|
||||
treeChange := d.treeBuilder.changeCreator(ch.Id, aclChange)
|
||||
treeChanges = append(treeChanges, treeChange)
|
||||
|
||||
// this already sets MaybeHeads to include new changes
|
||||
// TODO: change this behaviour as non-obvious, because it is not evident from the interface
|
||||
err = d.thread.AddChange(ch)
|
||||
if err != nil {
|
||||
return nil, UpdateResultNoAction, fmt.Errorf("change with id %s cannot be added: %w", ch.Id, err)
|
||||
@ -99,6 +101,11 @@ func (d *Document) Update(changes ...*threadmodels.RawChange) (DocumentState, Up
|
||||
return res, UpdateResultRebuild, fmt.Errorf("could not add changes to state, rebuilded")
|
||||
}
|
||||
|
||||
// setting all heads
|
||||
d.thread.SetHeads(d.docContext.fullTree.Heads())
|
||||
// this should be the entrypoint when we build the document
|
||||
d.thread.SetMaybeHeads(d.docContext.fullTree.Heads())
|
||||
|
||||
return newState, UpdateResultAppend, nil
|
||||
}
|
||||
|
||||
@ -151,6 +158,11 @@ func (d *Document) build(fromStart bool) (DocumentState, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// setting all heads
|
||||
d.thread.SetHeads(d.docContext.fullTree.Heads())
|
||||
// this should be the entrypoint when we build the document
|
||||
d.thread.SetMaybeHeads(d.docContext.fullTree.Heads())
|
||||
|
||||
return d.docContext.docState, nil
|
||||
}
|
||||
|
||||
|
||||
@ -117,6 +117,6 @@ graph:
|
||||
baseSnapshot: A.1.2
|
||||
aclHeads: [A.1.2]
|
||||
treeHeads: [A.1.2]
|
||||
heads:
|
||||
maybeHeads:
|
||||
- A.1.3
|
||||
- B.1.2
|
||||
|
||||
@ -14,11 +14,13 @@ type SymKey struct {
|
||||
}
|
||||
|
||||
type Keychain struct {
|
||||
SigningKeys map[string]threadmodels.SigningPrivKey
|
||||
EncryptionKeys map[string]threadmodels.EncryptionPrivKey
|
||||
ReadKeys map[string]*SymKey
|
||||
GeneratedIdentities map[string]string
|
||||
coder *threadmodels.Ed25519SigningPubKeyDecoder
|
||||
SigningKeys map[string]threadmodels.SigningPrivKey
|
||||
SigningKeysByIdentity map[string]threadmodels.SigningPrivKey
|
||||
EncryptionKeys map[string]threadmodels.EncryptionPrivKey
|
||||
ReadKeys map[string]*SymKey
|
||||
ReadKeysByHash map[uint64]*SymKey
|
||||
GeneratedIdentities map[string]string
|
||||
coder *threadmodels.Ed25519SigningPubKeyDecoder
|
||||
}
|
||||
|
||||
func NewKeychain() *Keychain {
|
||||
@ -71,6 +73,7 @@ func (k *Keychain) AddSigningKey(name string) {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
k.SigningKeysByIdentity[res] = newPrivKey
|
||||
k.GeneratedIdentities[name] = res
|
||||
}
|
||||
|
||||
@ -87,6 +90,10 @@ func (k *Keychain) AddReadKey(name string) {
|
||||
Hash: hasher.Sum64(),
|
||||
Key: key,
|
||||
}
|
||||
k.ReadKeysByHash[hasher.Sum64()] = &SymKey{
|
||||
Hash: hasher.Sum64(),
|
||||
Key: key,
|
||||
}
|
||||
}
|
||||
|
||||
func (k *Keychain) AddKey(key string) {
|
||||
|
||||
@ -20,36 +20,17 @@ type threadChange struct {
|
||||
readKey *SymKey
|
||||
signKey threadmodels.SigningPrivKey
|
||||
|
||||
changesData *pb.PlainTextChangeData
|
||||
changesDataDecrypted []byte
|
||||
}
|
||||
|
||||
type ThreadBuilder struct {
|
||||
threadId string
|
||||
allChanges map[string]*threadChange
|
||||
heads []string
|
||||
maybeHeads []string
|
||||
keychain *Keychain
|
||||
}
|
||||
|
||||
func (t *ThreadBuilder) AddChange(change *threadmodels.RawChange) error {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *ThreadBuilder) MaybeHeads() []string {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (t *ThreadBuilder) SetMaybeHeads(heads []string) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (t *ThreadBuilder) SetHeads(heads []string) {
|
||||
//TODO implement me
|
||||
}
|
||||
|
||||
func NewThreadBuilder(keychain *Keychain) *ThreadBuilder {
|
||||
return &ThreadBuilder{
|
||||
allChanges: make(map[string]*threadChange),
|
||||
@ -92,17 +73,58 @@ func (t *ThreadBuilder) Heads() []string {
|
||||
return t.heads
|
||||
}
|
||||
|
||||
func (t *ThreadBuilder) AddChange(change *threadmodels.RawChange) error {
|
||||
aclChange := new(pb.ACLChange)
|
||||
var err error
|
||||
|
||||
// TODO: think what should we do with such cases, because this can be used by attacker to break our tree
|
||||
if err = proto.Unmarshal(change.Payload, aclChange); err != nil {
|
||||
return fmt.Errorf("could not unmarshall changes")
|
||||
}
|
||||
var changesData []byte
|
||||
|
||||
// get correct readkey
|
||||
readKey := t.keychain.ReadKeysByHash[aclChange.CurrentReadKeyHash]
|
||||
if aclChange.ChangesData != nil {
|
||||
changesData, err = readKey.Key.Decrypt(aclChange.ChangesData)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to decrypt changes data: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// get correct signing key
|
||||
signKey := t.keychain.SigningKeysByIdentity[aclChange.Identity]
|
||||
t.maybeHeads = append(t.maybeHeads, change.Id)
|
||||
|
||||
t.allChanges[change.Id] = &threadChange{
|
||||
ACLChange: aclChange,
|
||||
id: change.Id,
|
||||
readKey: readKey,
|
||||
signKey: signKey,
|
||||
changesDataDecrypted: changesData,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *ThreadBuilder) MaybeHeads() []string {
|
||||
return t.maybeHeads
|
||||
}
|
||||
|
||||
func (t *ThreadBuilder) SetMaybeHeads(heads []string) {
|
||||
// we should copy here instead of just setting the value
|
||||
t.maybeHeads = heads
|
||||
}
|
||||
|
||||
func (t *ThreadBuilder) SetHeads(heads []string) {
|
||||
// we should copy here instead of just setting the value
|
||||
t.heads = heads
|
||||
}
|
||||
|
||||
func (t *ThreadBuilder) GetChange(ctx context.Context, recordID string) (*threadmodels.RawChange, error) {
|
||||
rec := t.allChanges[recordID]
|
||||
|
||||
var encrypted []byte
|
||||
if rec.changesData != nil {
|
||||
m, err := proto.Marshal(rec.changesData)
|
||||
if err != nil {
|
||||
panic("should be able to marshal data!")
|
||||
}
|
||||
|
||||
encrypted, err = rec.readKey.Key.Encrypt(m)
|
||||
if rec.changesDataDecrypted != nil {
|
||||
encrypted, err := rec.readKey.Key.Encrypt(rec.changesDataDecrypted)
|
||||
if err != nil {
|
||||
panic("should be able to encrypt data with read key!")
|
||||
}
|
||||
@ -162,9 +184,9 @@ func (t *ThreadBuilder) Parse(thread *YMLThread) {
|
||||
}
|
||||
}
|
||||
if len(ch.Changes) > 0 || ch.Snapshot != nil {
|
||||
newChange.changesData = &pb.PlainTextChangeData{}
|
||||
changesData := &pb.PlainTextChangeData{}
|
||||
if ch.Snapshot != nil {
|
||||
newChange.changesData.Snapshot = t.parseChangeSnapshot(ch.Snapshot)
|
||||
changesData.Snapshot = t.parseChangeSnapshot(ch.Snapshot)
|
||||
}
|
||||
if len(ch.Changes) > 0 {
|
||||
var changeContents []*pb.PlainTextChangeContent
|
||||
@ -172,8 +194,13 @@ func (t *ThreadBuilder) Parse(thread *YMLThread) {
|
||||
aclChangeContent := t.parseDocumentChange(ch)
|
||||
changeContents = append(changeContents, aclChangeContent)
|
||||
}
|
||||
newChange.changesData.Content = changeContents
|
||||
changesData.Content = changeContents
|
||||
}
|
||||
m, err := proto.Marshal(changesData)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
newChange.changesDataDecrypted = m
|
||||
}
|
||||
aclChange.CurrentReadKeyHash = k.Hash
|
||||
newChange.ACLChange = aclChange
|
||||
@ -421,4 +448,5 @@ func (t *ThreadBuilder) parseGraph(thread *YMLThread) {
|
||||
|
||||
func (t *ThreadBuilder) parseHeads(thread *YMLThread) {
|
||||
t.heads = thread.Heads
|
||||
t.maybeHeads = thread.MaybeHeads
|
||||
}
|
||||
|
||||
@ -36,13 +36,13 @@ func (t *ThreadBuilder) Graph() (string, error) {
|
||||
style := "solid"
|
||||
if r.GetAclData() != nil {
|
||||
style = "filled"
|
||||
} else if r.changesData != nil {
|
||||
} else if r.changesDataDecrypted != nil {
|
||||
style = "dashed"
|
||||
}
|
||||
|
||||
var chSymbs []string
|
||||
if r.changesData != nil {
|
||||
for _, chc := range r.changesData.Content {
|
||||
if r.changesDataDecrypted != nil {
|
||||
for _, chc := range r.changesDataDecrypted.Content {
|
||||
tp := fmt.Sprintf("%T", chc.Value)
|
||||
tp = strings.Replace(tp, "ChangeContentValueOf", "", 1)
|
||||
res := ""
|
||||
|
||||
@ -99,5 +99,5 @@ graph:
|
||||
baseSnapshot: A.1.1
|
||||
aclHeads: [B.1.1]
|
||||
treeHeads: [B.1.1]
|
||||
heads:
|
||||
maybeHeads:
|
||||
- "A.1.3"
|
||||
|
||||
@ -101,6 +101,6 @@ graph:
|
||||
baseSnapshot: A.1.1
|
||||
aclHeads: [A.1.2]
|
||||
treeHeads: [A.1.2]
|
||||
heads:
|
||||
maybeHeads:
|
||||
- "A.1.3"
|
||||
- "B.1.2"
|
||||
|
||||
@ -101,6 +101,6 @@ graph:
|
||||
aclSnapshot: A.1.1
|
||||
aclHeads: [A.1.3]
|
||||
treeHeads: [A.1.3]
|
||||
heads:
|
||||
maybeHeads:
|
||||
- "A.1.4"
|
||||
- "B.1.2"
|
||||
|
||||
@ -124,7 +124,7 @@ graph:
|
||||
baseSnapshot: A.1.2
|
||||
aclHeads: [A.1.2]
|
||||
treeHeads: [A.1.2]
|
||||
heads:
|
||||
maybeHeads:
|
||||
- "A.1.3"
|
||||
- "B.1.2"
|
||||
|
||||
|
||||
@ -94,5 +94,6 @@ type YMLThread struct {
|
||||
TreeHeads []string `yaml:"treeHeads"`
|
||||
} `yaml:"graph"`
|
||||
|
||||
Heads []string `yaml:"heads"`
|
||||
Heads []string `yaml:"heads"`
|
||||
MaybeHeads []string `yaml:"maybeHeads"`
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user