Add updated changes to thread builder
This commit is contained in:
parent
f15c806415
commit
475904a266
@ -24,17 +24,19 @@ type threadChange struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ThreadBuilder struct {
|
type ThreadBuilder struct {
|
||||||
threadId string
|
threadId string
|
||||||
allChanges map[string]*threadChange
|
allChanges map[string]*threadChange
|
||||||
heads []string
|
updatedChanges map[string]*threadChange
|
||||||
maybeHeads []string
|
heads []string
|
||||||
keychain *Keychain
|
maybeHeads []string
|
||||||
|
keychain *Keychain
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewThreadBuilder(keychain *Keychain) *ThreadBuilder {
|
func NewThreadBuilder(keychain *Keychain) *ThreadBuilder {
|
||||||
return &ThreadBuilder{
|
return &ThreadBuilder{
|
||||||
allChanges: make(map[string]*threadChange),
|
allChanges: make(map[string]*threadChange),
|
||||||
keychain: keychain,
|
updatedChanges: make(map[string]*threadChange),
|
||||||
|
keychain: keychain,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,7 +123,20 @@ func (t *ThreadBuilder) SetHeads(heads []string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *ThreadBuilder) GetChange(ctx context.Context, recordID string) (*threadmodels.RawChange, error) {
|
func (t *ThreadBuilder) GetChange(ctx context.Context, recordID string) (*threadmodels.RawChange, error) {
|
||||||
rec := t.allChanges[recordID]
|
return t.getChange(recordID, t.allChanges), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *ThreadBuilder) GetUpdatedChanges() []*threadmodels.RawChange {
|
||||||
|
var res []*threadmodels.RawChange
|
||||||
|
for _, ch := range t.updatedChanges {
|
||||||
|
rawCh := t.getChange(ch.id, t.updatedChanges)
|
||||||
|
res = append(res, rawCh)
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *ThreadBuilder) getChange(changeId string, m map[string]*threadChange) *threadmodels.RawChange {
|
||||||
|
rec := m[changeId]
|
||||||
|
|
||||||
if rec.changesDataDecrypted != nil {
|
if rec.changesDataDecrypted != nil {
|
||||||
encrypted, err := rec.readKey.Key.Encrypt(rec.changesDataDecrypted)
|
encrypted, err := rec.readKey.Key.Encrypt(rec.changesDataDecrypted)
|
||||||
@ -145,13 +160,9 @@ func (t *ThreadBuilder) GetChange(ctx context.Context, recordID string) (*thread
|
|||||||
transformedRec := &threadmodels.RawChange{
|
transformedRec := &threadmodels.RawChange{
|
||||||
Payload: aclMarshaled,
|
Payload: aclMarshaled,
|
||||||
Signature: signature,
|
Signature: signature,
|
||||||
Id: recordID,
|
Id: changeId,
|
||||||
}
|
}
|
||||||
return transformedRec, nil
|
return transformedRec
|
||||||
}
|
|
||||||
|
|
||||||
func (t *ThreadBuilder) PushChange(payload proto.Marshaler) (id string, err error) {
|
|
||||||
panic("implement me")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *ThreadBuilder) Parse(thread *YMLThread) {
|
func (t *ThreadBuilder) Parse(thread *YMLThread) {
|
||||||
@ -161,55 +172,66 @@ func (t *ThreadBuilder) Parse(thread *YMLThread) {
|
|||||||
t.keychain.ParseKeys(&thread.Keys)
|
t.keychain.ParseKeys(&thread.Keys)
|
||||||
t.threadId = t.parseThreadId(thread.Description)
|
t.threadId = t.parseThreadId(thread.Description)
|
||||||
for _, ch := range thread.Changes {
|
for _, ch := range thread.Changes {
|
||||||
newChange := &threadChange{
|
newChange := t.parseChange(ch)
|
||||||
id: ch.Id,
|
|
||||||
}
|
|
||||||
k := t.keychain.GetKey(ch.ReadKey).(*SymKey)
|
|
||||||
newChange.readKey = k
|
|
||||||
newChange.signKey = t.keychain.SigningKeys[ch.Identity]
|
|
||||||
aclChange := &pb.ACLChange{}
|
|
||||||
aclChange.Identity = t.keychain.GetIdentity(ch.Identity)
|
|
||||||
if len(ch.AclChanges) > 0 || ch.AclSnapshot != nil {
|
|
||||||
aclChange.AclData = &pb.ACLChangeACLData{}
|
|
||||||
if ch.AclSnapshot != nil {
|
|
||||||
aclChange.AclData.AclSnapshot = t.parseACLSnapshot(ch.AclSnapshot)
|
|
||||||
}
|
|
||||||
if ch.AclChanges != nil {
|
|
||||||
var aclChangeContents []*pb.ACLChangeACLContentValue
|
|
||||||
for _, ch := range ch.AclChanges {
|
|
||||||
aclChangeContent := t.parseACLChange(ch)
|
|
||||||
aclChangeContents = append(aclChangeContents, aclChangeContent)
|
|
||||||
}
|
|
||||||
aclChange.AclData.AclContent = aclChangeContents
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(ch.Changes) > 0 || ch.Snapshot != nil {
|
|
||||||
changesData := &pb.PlainTextChangeData{}
|
|
||||||
if ch.Snapshot != nil {
|
|
||||||
changesData.Snapshot = t.parseChangeSnapshot(ch.Snapshot)
|
|
||||||
}
|
|
||||||
if len(ch.Changes) > 0 {
|
|
||||||
var changeContents []*pb.PlainTextChangeContent
|
|
||||||
for _, ch := range ch.Changes {
|
|
||||||
aclChangeContent := t.parseDocumentChange(ch)
|
|
||||||
changeContents = append(changeContents, aclChangeContent)
|
|
||||||
}
|
|
||||||
changesData.Content = changeContents
|
|
||||||
}
|
|
||||||
m, err := proto.Marshal(changesData)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
newChange.changesDataDecrypted = m
|
|
||||||
}
|
|
||||||
aclChange.CurrentReadKeyHash = k.Hash
|
|
||||||
newChange.ACLChange = aclChange
|
|
||||||
t.allChanges[newChange.id] = newChange
|
t.allChanges[newChange.id] = newChange
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, ch := range thread.UpdatedChanges {
|
||||||
|
newChange := t.parseChange(ch)
|
||||||
|
t.updatedChanges[newChange.id] = newChange
|
||||||
|
}
|
||||||
|
|
||||||
t.parseGraph(thread)
|
t.parseGraph(thread)
|
||||||
t.parseHeads(thread)
|
t.parseHeads(thread)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *ThreadBuilder) parseChange(ch *Change) *threadChange {
|
||||||
|
newChange := &threadChange{
|
||||||
|
id: ch.Id,
|
||||||
|
}
|
||||||
|
k := t.keychain.GetKey(ch.ReadKey).(*SymKey)
|
||||||
|
newChange.readKey = k
|
||||||
|
newChange.signKey = t.keychain.SigningKeys[ch.Identity]
|
||||||
|
aclChange := &pb.ACLChange{}
|
||||||
|
aclChange.Identity = t.keychain.GetIdentity(ch.Identity)
|
||||||
|
if len(ch.AclChanges) > 0 || ch.AclSnapshot != nil {
|
||||||
|
aclChange.AclData = &pb.ACLChangeACLData{}
|
||||||
|
if ch.AclSnapshot != nil {
|
||||||
|
aclChange.AclData.AclSnapshot = t.parseACLSnapshot(ch.AclSnapshot)
|
||||||
|
}
|
||||||
|
if ch.AclChanges != nil {
|
||||||
|
var aclChangeContents []*pb.ACLChangeACLContentValue
|
||||||
|
for _, ch := range ch.AclChanges {
|
||||||
|
aclChangeContent := t.parseACLChange(ch)
|
||||||
|
aclChangeContents = append(aclChangeContents, aclChangeContent)
|
||||||
|
}
|
||||||
|
aclChange.AclData.AclContent = aclChangeContents
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(ch.Changes) > 0 || ch.Snapshot != nil {
|
||||||
|
changesData := &pb.PlainTextChangeData{}
|
||||||
|
if ch.Snapshot != nil {
|
||||||
|
changesData.Snapshot = t.parseChangeSnapshot(ch.Snapshot)
|
||||||
|
}
|
||||||
|
if len(ch.Changes) > 0 {
|
||||||
|
var changeContents []*pb.PlainTextChangeContent
|
||||||
|
for _, ch := range ch.Changes {
|
||||||
|
aclChangeContent := t.parseDocumentChange(ch)
|
||||||
|
changeContents = append(changeContents, aclChangeContent)
|
||||||
|
}
|
||||||
|
changesData.Content = changeContents
|
||||||
|
}
|
||||||
|
m, err := proto.Marshal(changesData)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
newChange.changesDataDecrypted = m
|
||||||
|
}
|
||||||
|
aclChange.CurrentReadKeyHash = k.Hash
|
||||||
|
newChange.ACLChange = aclChange
|
||||||
|
return newChange
|
||||||
|
}
|
||||||
|
|
||||||
func (t *ThreadBuilder) parseThreadId(description *ThreadDescription) string {
|
func (t *ThreadBuilder) parseThreadId(description *ThreadDescription) string {
|
||||||
if description == nil {
|
if description == nil {
|
||||||
panic("no author in thread")
|
panic("no author in thread")
|
||||||
@ -415,8 +437,8 @@ func (t *ThreadBuilder) convertPermission(perm string) pb.ACLChangeUserPermissio
|
|||||||
|
|
||||||
func (t *ThreadBuilder) traverseFromHeads(f func(t *threadChange) error) error {
|
func (t *ThreadBuilder) traverseFromHeads(f func(t *threadChange) error) error {
|
||||||
uniqMap := map[string]struct{}{}
|
uniqMap := map[string]struct{}{}
|
||||||
stack := make([]string, len(t.heads), 10)
|
stack := make([]string, len(t.maybeHeads), 10)
|
||||||
copy(stack, t.heads)
|
copy(stack, t.maybeHeads)
|
||||||
for len(stack) > 0 {
|
for len(stack) > 0 {
|
||||||
id := stack[len(stack)-1]
|
id := stack[len(stack)-1]
|
||||||
stack = stack[:len(stack)-1]
|
stack = stack[:len(stack)-1]
|
||||||
@ -444,6 +466,13 @@ func (t *ThreadBuilder) parseGraph(thread *YMLThread) {
|
|||||||
rec.TreeHeadIds = node.TreeHeads
|
rec.TreeHeadIds = node.TreeHeads
|
||||||
rec.SnapshotBaseId = node.BaseSnapshot
|
rec.SnapshotBaseId = node.BaseSnapshot
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, node := range thread.UpdatedGraph {
|
||||||
|
rec := t.updatedChanges[node.Id]
|
||||||
|
rec.AclHeadIds = node.ACLHeads
|
||||||
|
rec.TreeHeadIds = node.TreeHeads
|
||||||
|
rec.SnapshotBaseId = node.BaseSnapshot
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *ThreadBuilder) parseHeads(thread *YMLThread) {
|
func (t *ThreadBuilder) parseHeads(thread *YMLThread) {
|
||||||
|
|||||||
@ -101,3 +101,15 @@ graph:
|
|||||||
treeHeads: [B.1.1]
|
treeHeads: [B.1.1]
|
||||||
maybeHeads:
|
maybeHeads:
|
||||||
- "A.1.3"
|
- "A.1.3"
|
||||||
|
updatedChanges:
|
||||||
|
- id: B.1.3
|
||||||
|
identity: B
|
||||||
|
changes:
|
||||||
|
- textAppend:
|
||||||
|
text: "first"
|
||||||
|
readKey: key.Read.1
|
||||||
|
updatedGraph:
|
||||||
|
- id: B.1.3
|
||||||
|
baseSnapshot: A.1.1
|
||||||
|
aclHeads: [ B.1.1 ]
|
||||||
|
treeHeads: [ B.1.2 ]
|
||||||
|
|||||||
@ -70,29 +70,35 @@ type PlainTextChange struct {
|
|||||||
} `yaml:"textAppend"`
|
} `yaml:"textAppend"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type GraphNode struct {
|
||||||
|
Id string `yaml:"id"`
|
||||||
|
BaseSnapshot string `yaml:"baseSnapshot"`
|
||||||
|
AclSnapshot string `yaml:"aclSnapshot"`
|
||||||
|
ACLHeads []string `yaml:"aclHeads"`
|
||||||
|
TreeHeads []string `yaml:"treeHeads"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Change struct {
|
||||||
|
Id string `yaml:"id"`
|
||||||
|
Identity string `yaml:"identity"`
|
||||||
|
|
||||||
|
AclSnapshot *ACLSnapshot `yaml:"aclSnapshot"`
|
||||||
|
Snapshot *PlainTextSnapshot `yaml:"snapshot"`
|
||||||
|
AclChanges []*ACLChange `yaml:"aclChanges"`
|
||||||
|
Changes []*PlainTextChange `yaml:"changes"`
|
||||||
|
|
||||||
|
ReadKey string `yaml:"readKey"`
|
||||||
|
}
|
||||||
|
|
||||||
type YMLThread struct {
|
type YMLThread struct {
|
||||||
Description *ThreadDescription `yaml:"thread"`
|
Description *ThreadDescription `yaml:"thread"`
|
||||||
Changes []struct {
|
Changes []*Change `yaml:"changes"`
|
||||||
Id string `yaml:"id"`
|
UpdatedChanges []*Change `yaml:"updatedChanges"`
|
||||||
Identity string `yaml:"identity"`
|
|
||||||
|
|
||||||
AclSnapshot *ACLSnapshot `yaml:"aclSnapshot"`
|
|
||||||
Snapshot *PlainTextSnapshot `yaml:"snapshot"`
|
|
||||||
AclChanges []*ACLChange `yaml:"aclChanges"`
|
|
||||||
Changes []*PlainTextChange `yaml:"changes"`
|
|
||||||
|
|
||||||
ReadKey string `yaml:"readKey"`
|
|
||||||
} `yaml:"changes"`
|
|
||||||
|
|
||||||
Keys Keys `yaml:"keys"`
|
Keys Keys `yaml:"keys"`
|
||||||
|
|
||||||
Graph []struct {
|
Graph []*GraphNode `yaml:"graph"`
|
||||||
Id string `yaml:"id"`
|
UpdatedGraph []*GraphNode `yaml:"updatedGraph"`
|
||||||
BaseSnapshot string `yaml:"baseSnapshot"`
|
|
||||||
AclSnapshot string `yaml:"aclSnapshot"`
|
|
||||||
ACLHeads []string `yaml:"aclHeads"`
|
|
||||||
TreeHeads []string `yaml:"treeHeads"`
|
|
||||||
} `yaml:"graph"`
|
|
||||||
|
|
||||||
Heads []string `yaml:"heads"`
|
Heads []string `yaml:"heads"`
|
||||||
MaybeHeads []string `yaml:"maybeHeads"`
|
MaybeHeads []string `yaml:"maybeHeads"`
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user