WIP ACLTree tests
This commit is contained in:
parent
8372abb4e1
commit
b07a137fb9
@ -1,231 +0,0 @@
|
|||||||
package acltree
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/account"
|
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/aclchanges/pb"
|
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/testutils/threadbuilder"
|
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/thread"
|
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/keys"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
|
||||||
|
|
||||||
type ACLContext struct {
|
|
||||||
Tree *Tree
|
|
||||||
ACLState *ACLState
|
|
||||||
}
|
|
||||||
|
|
||||||
func createTreeFromThread(t thread.Thread, fromStart bool) (*Tree, error) {
|
|
||||||
treeBuilder := newTreeBuilder(t, keys.NewEd25519Decoder())
|
|
||||||
treeBuilder.Init()
|
|
||||||
return treeBuilder.Build(fromStart)
|
|
||||||
}
|
|
||||||
|
|
||||||
func createACLStateFromThread(
|
|
||||||
t thread.Thread,
|
|
||||||
identity string,
|
|
||||||
key keys.EncryptionPrivKey,
|
|
||||||
decoder keys.SigningPubKeyDecoder,
|
|
||||||
fromStart bool) (*ACLContext, error) {
|
|
||||||
tree, err := createTreeFromThread(t, fromStart)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
accountData := &account.AccountData{
|
|
||||||
Identity: identity,
|
|
||||||
EncKey: key,
|
|
||||||
}
|
|
||||||
|
|
||||||
aclTreeBuilder := newACLTreeBuilder(t, decoder)
|
|
||||||
aclTreeBuilder.Init()
|
|
||||||
aclTree, err := aclTreeBuilder.Build()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if !fromStart {
|
|
||||||
snapshotValidator := newSnapshotValidator(decoder, accountData)
|
|
||||||
snapshotValidator.Init(aclTree)
|
|
||||||
valid, err := snapshotValidator.ValidateSnapshot(tree.root)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if !valid {
|
|
||||||
// TODO: think about what to do if the snapshot is invalid - should we rebuild the Tree without it
|
|
||||||
return createACLStateFromThread(t, identity, key, decoder, true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
aclBuilder := newACLStateBuilder(decoder, accountData)
|
|
||||||
err = aclBuilder.Init(tree)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
aclState, err := aclBuilder.Build()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &ACLContext{
|
|
||||||
Tree: tree,
|
|
||||||
ACLState: aclState,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestACLStateBuilder_UserJoinBuild(t *testing.T) {
|
|
||||||
thread, err := threadbuilder.NewThreadBuilderFromFile("threadbuilder/userjoinexample.yml")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
keychain := thread.GetKeychain()
|
|
||||||
ctx, err := createACLStateFromThread(
|
|
||||||
thread,
|
|
||||||
keychain.GetIdentity("A"),
|
|
||||||
keychain.EncryptionKeys["A"],
|
|
||||||
keys.NewEd25519Decoder(),
|
|
||||||
false)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("should Build acl ACLState without err: %v", err)
|
|
||||||
}
|
|
||||||
aclState := ctx.ACLState
|
|
||||||
//fmt.Println(ctx.Tree.Graph())
|
|
||||||
aId := keychain.GeneratedIdentities["A"]
|
|
||||||
bId := keychain.GeneratedIdentities["B"]
|
|
||||||
cId := keychain.GeneratedIdentities["C"]
|
|
||||||
|
|
||||||
assert.Equal(t, aclState.identity, aId)
|
|
||||||
assert.Equal(t, aclState.userStates[aId].Permissions, pb.ACLChange_Admin)
|
|
||||||
assert.Equal(t, aclState.userStates[bId].Permissions, pb.ACLChange_Writer)
|
|
||||||
assert.Equal(t, aclState.userStates[cId].Permissions, pb.ACLChange_Reader)
|
|
||||||
|
|
||||||
var changeIds []string
|
|
||||||
ctx.Tree.Iterate(ctx.Tree.root.Id, func(c *Change) (isContinue bool) {
|
|
||||||
changeIds = append(changeIds, c.Id)
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
assert.Equal(t, changeIds, []string{"A.1.1", "A.1.2", "B.1.1", "B.1.2"})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestACLStateBuilder_UserRemoveBuild(t *testing.T) {
|
|
||||||
thread, err := threadbuilder.NewThreadBuilderFromFile("threadbuilder/userremoveexample.yml")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
keychain := thread.GetKeychain()
|
|
||||||
ctx, err := createACLStateFromThread(
|
|
||||||
thread,
|
|
||||||
keychain.GetIdentity("A"),
|
|
||||||
keychain.EncryptionKeys["A"],
|
|
||||||
keys.NewEd25519Decoder(),
|
|
||||||
false)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("should Build acl ACLState without err: %v", err)
|
|
||||||
}
|
|
||||||
aclState := ctx.ACLState
|
|
||||||
//fmt.Println(ctx.Tree.Graph())
|
|
||||||
aId := keychain.GeneratedIdentities["A"]
|
|
||||||
|
|
||||||
assert.Equal(t, aclState.identity, aId)
|
|
||||||
assert.Equal(t, aclState.userStates[aId].Permissions, pb.ACLChange_Admin)
|
|
||||||
|
|
||||||
var changeIds []string
|
|
||||||
ctx.Tree.Iterate(ctx.Tree.root.Id, func(c *Change) (isContinue bool) {
|
|
||||||
changeIds = append(changeIds, c.Id)
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
assert.Equal(t, changeIds, []string{"A.1.1", "A.1.2", "B.1.1", "A.1.3", "A.1.4"})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestACLStateBuilder_UserRemoveBeforeBuild(t *testing.T) {
|
|
||||||
thread, err := threadbuilder.NewThreadBuilderFromFile("threadbuilder/userremovebeforeexample.yml")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
keychain := thread.GetKeychain()
|
|
||||||
ctx, err := createACLStateFromThread(
|
|
||||||
thread,
|
|
||||||
keychain.GetIdentity("A"),
|
|
||||||
keychain.EncryptionKeys["A"],
|
|
||||||
keys.NewEd25519Decoder(),
|
|
||||||
false)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("should Build acl ACLState without err: %v", err)
|
|
||||||
}
|
|
||||||
aclState := ctx.ACLState
|
|
||||||
//fmt.Println(ctx.Tree.Graph())
|
|
||||||
for _, s := range []string{"A", "C", "E"} {
|
|
||||||
assert.Equal(t, aclState.userStates[keychain.GetIdentity(s)].Permissions, pb.ACLChange_Admin)
|
|
||||||
}
|
|
||||||
assert.Equal(t, aclState.identity, keychain.GetIdentity("A"))
|
|
||||||
assert.Nil(t, aclState.userStates[keychain.GetIdentity("B")])
|
|
||||||
|
|
||||||
var changeIds []string
|
|
||||||
ctx.Tree.Iterate(ctx.Tree.root.Id, func(c *Change) (isContinue bool) {
|
|
||||||
changeIds = append(changeIds, c.Id)
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
assert.Equal(t, changeIds, []string{"A.1.1", "B.1.1", "A.1.2", "A.1.3"})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestACLStateBuilder_InvalidSnapshotBuild(t *testing.T) {
|
|
||||||
thread, err := threadbuilder.NewThreadBuilderFromFile("threadbuilder/invalidsnapshotexample.yml")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
keychain := thread.GetKeychain()
|
|
||||||
ctx, err := createACLStateFromThread(
|
|
||||||
thread,
|
|
||||||
keychain.GetIdentity("A"),
|
|
||||||
keychain.EncryptionKeys["A"],
|
|
||||||
keys.NewEd25519Decoder(),
|
|
||||||
false)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("should Build acl ACLState without err: %v", err)
|
|
||||||
}
|
|
||||||
aclState := ctx.ACLState
|
|
||||||
//fmt.Println(ctx.Tree.Graph())
|
|
||||||
for _, s := range []string{"A", "B", "C", "D", "E", "F"} {
|
|
||||||
assert.Equal(t, aclState.userStates[keychain.GetIdentity(s)].Permissions, pb.ACLChange_Admin)
|
|
||||||
}
|
|
||||||
assert.Equal(t, aclState.identity, keychain.GetIdentity("A"))
|
|
||||||
|
|
||||||
var changeIds []string
|
|
||||||
ctx.Tree.Iterate(ctx.Tree.root.Id, func(c *Change) (isContinue bool) {
|
|
||||||
changeIds = append(changeIds, c.Id)
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
assert.Equal(t, []string{"A.1.1", "B.1.1", "A.1.2", "A.1.3", "B.1.2"}, changeIds)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestACLStateBuilder_ValidSnapshotBuild(t *testing.T) {
|
|
||||||
thread, err := threadbuilder.NewThreadBuilderFromFile("threadbuilder/validsnapshotexample.yml")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
keychain := thread.GetKeychain()
|
|
||||||
ctx, err := createACLStateFromThread(
|
|
||||||
thread,
|
|
||||||
keychain.GetIdentity("A"),
|
|
||||||
keychain.EncryptionKeys["A"],
|
|
||||||
keys.NewEd25519Decoder(),
|
|
||||||
false)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("should Build acl ACLState without err: %v", err)
|
|
||||||
}
|
|
||||||
aclState := ctx.ACLState
|
|
||||||
//fmt.Println(ctx.Tree.Graph())
|
|
||||||
for _, s := range []string{"A", "B", "C", "D", "E", "F"} {
|
|
||||||
assert.Equal(t, aclState.userStates[keychain.GetIdentity(s)].Permissions, pb.ACLChange_Admin)
|
|
||||||
}
|
|
||||||
assert.Equal(t, aclState.identity, keychain.GetIdentity("A"))
|
|
||||||
|
|
||||||
var changeIds []string
|
|
||||||
ctx.Tree.Iterate(ctx.Tree.root.Id, func(c *Change) (isContinue bool) {
|
|
||||||
changeIds = append(changeIds, c.Id)
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
assert.Equal(t, []string{"A.1.2", "A.1.3", "B.1.2"}, changeIds)
|
|
||||||
}
|
|
||||||
166
acltree/acltree_test.go
Normal file
166
acltree/acltree_test.go
Normal file
@ -0,0 +1,166 @@
|
|||||||
|
package acltree
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/account"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/aclchanges/pb"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/testutils/threadbuilder"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestACLTree_UserJoinBuild(t *testing.T) {
|
||||||
|
thr, err := threadbuilder.NewThreadBuilderFromFile("threadbuilder/userjoinexample.yml")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
keychain := thr.GetKeychain()
|
||||||
|
accountData := &account.AccountData{
|
||||||
|
Identity: keychain.GetIdentity("A"),
|
||||||
|
SignKey: keychain.SigningKeys["A"],
|
||||||
|
EncKey: keychain.EncryptionKeys["A"],
|
||||||
|
}
|
||||||
|
tree, err := BuildACLTree(thr, accountData)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("should Build acl ACLState without err: %v", err)
|
||||||
|
}
|
||||||
|
aclState := tree.ACLState()
|
||||||
|
//fmt.Println(ctx.Tree.Graph())
|
||||||
|
aId := keychain.GeneratedIdentities["A"]
|
||||||
|
bId := keychain.GeneratedIdentities["B"]
|
||||||
|
cId := keychain.GeneratedIdentities["C"]
|
||||||
|
|
||||||
|
assert.Equal(t, aclState.identity, aId)
|
||||||
|
assert.Equal(t, aclState.userStates[aId].Permissions, pb.ACLChange_Admin)
|
||||||
|
assert.Equal(t, aclState.userStates[bId].Permissions, pb.ACLChange_Writer)
|
||||||
|
assert.Equal(t, aclState.userStates[cId].Permissions, pb.ACLChange_Reader)
|
||||||
|
|
||||||
|
var changeIds []string
|
||||||
|
tree.Iterate(func(c *Change) (isContinue bool) {
|
||||||
|
changeIds = append(changeIds, c.Id)
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
assert.Equal(t, changeIds, []string{"A.1.1", "A.1.2", "B.1.1", "B.1.2"})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestACLTree_UserRemoveBuild(t *testing.T) {
|
||||||
|
thr, err := threadbuilder.NewThreadBuilderFromFile("threadbuilder/userremoveexample.yml")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
keychain := thr.GetKeychain()
|
||||||
|
accountData := &account.AccountData{
|
||||||
|
Identity: keychain.GetIdentity("A"),
|
||||||
|
SignKey: keychain.SigningKeys["A"],
|
||||||
|
EncKey: keychain.EncryptionKeys["A"],
|
||||||
|
}
|
||||||
|
tree, err := BuildACLTree(thr, accountData)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("should Build acl ACLState without err: %v", err)
|
||||||
|
}
|
||||||
|
aclState := tree.ACLState()
|
||||||
|
//fmt.Println(ctx.Tree.Graph())
|
||||||
|
aId := keychain.GeneratedIdentities["A"]
|
||||||
|
|
||||||
|
assert.Equal(t, aclState.identity, aId)
|
||||||
|
assert.Equal(t, aclState.userStates[aId].Permissions, pb.ACLChange_Admin)
|
||||||
|
|
||||||
|
var changeIds []string
|
||||||
|
tree.Iterate(func(c *Change) (isContinue bool) {
|
||||||
|
changeIds = append(changeIds, c.Id)
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
assert.Equal(t, changeIds, []string{"A.1.1", "A.1.2", "B.1.1", "A.1.3", "A.1.4"})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestACLTree_UserRemoveBeforeBuild(t *testing.T) {
|
||||||
|
thr, err := threadbuilder.NewThreadBuilderFromFile("threadbuilder/userremovebeforeexample.yml")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
keychain := thr.GetKeychain()
|
||||||
|
accountData := &account.AccountData{
|
||||||
|
Identity: keychain.GetIdentity("A"),
|
||||||
|
SignKey: keychain.SigningKeys["A"],
|
||||||
|
EncKey: keychain.EncryptionKeys["A"],
|
||||||
|
}
|
||||||
|
tree, err := BuildACLTree(thr, accountData)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("should Build acl ACLState without err: %v", err)
|
||||||
|
}
|
||||||
|
aclState := tree.ACLState()
|
||||||
|
//fmt.Println(ctx.Tree.Graph())
|
||||||
|
for _, s := range []string{"A", "C", "E"} {
|
||||||
|
assert.Equal(t, aclState.userStates[keychain.GetIdentity(s)].Permissions, pb.ACLChange_Admin)
|
||||||
|
}
|
||||||
|
assert.Equal(t, aclState.identity, keychain.GetIdentity("A"))
|
||||||
|
assert.Nil(t, aclState.userStates[keychain.GetIdentity("B")])
|
||||||
|
|
||||||
|
var changeIds []string
|
||||||
|
tree.Iterate(func(c *Change) (isContinue bool) {
|
||||||
|
changeIds = append(changeIds, c.Id)
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
assert.Equal(t, changeIds, []string{"A.1.1", "B.1.1", "A.1.2", "A.1.3"})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestACLTree_InvalidSnapshotBuild(t *testing.T) {
|
||||||
|
thr, err := threadbuilder.NewThreadBuilderFromFile("threadbuilder/invalidsnapshotexample.yml")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
keychain := thr.GetKeychain()
|
||||||
|
accountData := &account.AccountData{
|
||||||
|
Identity: keychain.GetIdentity("A"),
|
||||||
|
SignKey: keychain.SigningKeys["A"],
|
||||||
|
EncKey: keychain.EncryptionKeys["A"],
|
||||||
|
}
|
||||||
|
tree, err := BuildACLTree(thr, accountData)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("should Build acl ACLState without err: %v", err)
|
||||||
|
}
|
||||||
|
aclState := tree.ACLState()
|
||||||
|
//fmt.Println(ctx.Tree.Graph())
|
||||||
|
for _, s := range []string{"A", "B", "C", "D", "E", "F"} {
|
||||||
|
assert.Equal(t, aclState.userStates[keychain.GetIdentity(s)].Permissions, pb.ACLChange_Admin)
|
||||||
|
}
|
||||||
|
assert.Equal(t, aclState.identity, keychain.GetIdentity("A"))
|
||||||
|
|
||||||
|
var changeIds []string
|
||||||
|
tree.Iterate(func(c *Change) (isContinue bool) {
|
||||||
|
changeIds = append(changeIds, c.Id)
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
assert.Equal(t, []string{"A.1.1", "B.1.1", "A.1.2", "A.1.3", "B.1.2"}, changeIds)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestACLTree_ValidSnapshotBuild(t *testing.T) {
|
||||||
|
thr, err := threadbuilder.NewThreadBuilderFromFile("threadbuilder/validsnapshotexample.yml")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
keychain := thr.GetKeychain()
|
||||||
|
accountData := &account.AccountData{
|
||||||
|
Identity: keychain.GetIdentity("A"),
|
||||||
|
SignKey: keychain.SigningKeys["A"],
|
||||||
|
EncKey: keychain.EncryptionKeys["A"],
|
||||||
|
}
|
||||||
|
tree, err := BuildACLTree(thr, accountData)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("should Build acl ACLState without err: %v", err)
|
||||||
|
}
|
||||||
|
aclState := tree.ACLState()
|
||||||
|
//fmt.Println(ctx.Tree.Graph())
|
||||||
|
for _, s := range []string{"A", "B", "C", "D", "E", "F"} {
|
||||||
|
assert.Equal(t, aclState.userStates[keychain.GetIdentity(s)].Permissions, pb.ACLChange_Admin)
|
||||||
|
}
|
||||||
|
assert.Equal(t, aclState.identity, keychain.GetIdentity("A"))
|
||||||
|
|
||||||
|
var changeIds []string
|
||||||
|
tree.Iterate(func(c *Change) (isContinue bool) {
|
||||||
|
changeIds = append(changeIds, c.Id)
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
assert.Equal(t, []string{"A.1.2", "A.1.3", "B.1.2"}, changeIds)
|
||||||
|
}
|
||||||
@ -1,5 +1,11 @@
|
|||||||
package acltree
|
package acltree
|
||||||
|
|
||||||
|
//func createTreeFromThread(t thread.Thread, fromStart bool) (*Tree, error) {
|
||||||
|
// treeBuilder := newTreeBuilder(t, keys.NewEd25519Decoder())
|
||||||
|
// treeBuilder.Init()
|
||||||
|
// return treeBuilder.Build(fromStart)
|
||||||
|
//}
|
||||||
|
//
|
||||||
//func TestACLTreeBuilder_UserJoinCorrectHeadsAndLen(t *testing.T) {
|
//func TestACLTreeBuilder_UserJoinCorrectHeadsAndLen(t *testing.T) {
|
||||||
// thread, err := threadbuilder.NewThreadBuilderFromFile("threadbuilder/userjoinexample.yml")
|
// thread, err := threadbuilder.NewThreadBuilderFromFile("threadbuilder/userjoinexample.yml")
|
||||||
// if err != nil {
|
// if err != nil {
|
||||||
|
|||||||
@ -117,7 +117,7 @@ graph:
|
|||||||
baseSnapshot: A.1.2
|
baseSnapshot: A.1.2
|
||||||
aclHeads: [A.1.2]
|
aclHeads: [A.1.2]
|
||||||
treeHeads: [A.1.2]
|
treeHeads: [A.1.2]
|
||||||
maybeHeads:
|
orphans:
|
||||||
- A.1.3
|
- A.1.3
|
||||||
- B.1.2
|
- B.1.2
|
||||||
|
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/anytypeio/go-anytype-infrastructure-experiments/aclchanges"
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/aclchanges"
|
||||||
|
"github.com/anytypeio/go-anytype-infrastructure-experiments/util/slice"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
|
||||||
"github.com/gogo/protobuf/proto"
|
"github.com/gogo/protobuf/proto"
|
||||||
@ -31,7 +32,7 @@ type ThreadBuilder struct {
|
|||||||
allChanges map[string]*threadChange
|
allChanges map[string]*threadChange
|
||||||
updatedChanges map[string]*threadChange
|
updatedChanges map[string]*threadChange
|
||||||
heads []string
|
heads []string
|
||||||
maybeHeads []string
|
orphans []string
|
||||||
keychain *Keychain
|
keychain *Keychain
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,8 +110,8 @@ func (t *ThreadBuilder) AddRawChange(change *thread.RawChange) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *ThreadBuilder) AddOrphans(head string) {
|
func (t *ThreadBuilder) AddOrphans(orphans ...string) {
|
||||||
t.maybeHeads = append(t.maybeHeads, head)
|
t.orphans = append(t.orphans, orphans...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *ThreadBuilder) AddChange(change aclchanges.Change) error {
|
func (t *ThreadBuilder) AddChange(change aclchanges.Change) error {
|
||||||
@ -141,12 +142,7 @@ func (t *ThreadBuilder) AddChange(change aclchanges.Change) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *ThreadBuilder) Orphans() []string {
|
func (t *ThreadBuilder) Orphans() []string {
|
||||||
return t.maybeHeads
|
return t.orphans
|
||||||
}
|
|
||||||
|
|
||||||
func (t *ThreadBuilder) SetPossibleHeads(heads []string) {
|
|
||||||
// we should copy here instead of just setting the value
|
|
||||||
t.maybeHeads = heads
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *ThreadBuilder) SetHeads(heads []string) {
|
func (t *ThreadBuilder) SetHeads(heads []string) {
|
||||||
@ -154,6 +150,10 @@ func (t *ThreadBuilder) SetHeads(heads []string) {
|
|||||||
t.heads = heads
|
t.heads = heads
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *ThreadBuilder) RemoveOrphans(orphans ...string) {
|
||||||
|
t.orphans = slice.Difference(t.orphans, orphans)
|
||||||
|
}
|
||||||
|
|
||||||
func (t *ThreadBuilder) GetChange(ctx context.Context, recordID string) (*thread.RawChange, error) {
|
func (t *ThreadBuilder) GetChange(ctx context.Context, recordID string) (*thread.RawChange, error) {
|
||||||
return t.getChange(recordID, t.allChanges), nil
|
return t.getChange(recordID, t.allChanges), nil
|
||||||
}
|
}
|
||||||
@ -214,7 +214,7 @@ func (t *ThreadBuilder) Parse(thread *YMLThread) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
t.parseGraph(thread)
|
t.parseGraph(thread)
|
||||||
t.parseHeads(thread)
|
t.parseOrphans(thread)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *ThreadBuilder) parseChange(ch *Change) *threadChange {
|
func (t *ThreadBuilder) parseChange(ch *Change) *threadChange {
|
||||||
@ -469,8 +469,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.maybeHeads), 10)
|
stack := make([]string, len(t.orphans), 10)
|
||||||
copy(stack, t.maybeHeads)
|
copy(stack, t.orphans)
|
||||||
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]
|
||||||
@ -507,7 +507,6 @@ func (t *ThreadBuilder) parseGraph(thread *YMLThread) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *ThreadBuilder) parseHeads(thread *YMLThread) {
|
func (t *ThreadBuilder) parseOrphans(thread *YMLThread) {
|
||||||
t.heads = thread.Heads
|
t.orphans = thread.Orphans
|
||||||
t.maybeHeads = thread.MaybeHeads
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -99,7 +99,7 @@ graph:
|
|||||||
baseSnapshot: A.1.1
|
baseSnapshot: A.1.1
|
||||||
aclHeads: [B.1.1]
|
aclHeads: [B.1.1]
|
||||||
treeHeads: [B.1.1]
|
treeHeads: [B.1.1]
|
||||||
maybeHeads:
|
orphans:
|
||||||
- "A.1.3"
|
- "A.1.3"
|
||||||
updatedChanges:
|
updatedChanges:
|
||||||
- id: B.1.3
|
- id: B.1.3
|
||||||
|
|||||||
@ -101,7 +101,7 @@ graph:
|
|||||||
baseSnapshot: A.1.1
|
baseSnapshot: A.1.1
|
||||||
aclHeads: [B.1.1]
|
aclHeads: [B.1.1]
|
||||||
treeHeads: [B.1.1]
|
treeHeads: [B.1.1]
|
||||||
maybeHeads:
|
orphans:
|
||||||
- "A.1.3"
|
- "A.1.3"
|
||||||
updatedChanges:
|
updatedChanges:
|
||||||
- id: B.1.3
|
- id: B.1.3
|
||||||
|
|||||||
@ -101,6 +101,6 @@ graph:
|
|||||||
baseSnapshot: A.1.1
|
baseSnapshot: A.1.1
|
||||||
aclHeads: [A.1.2]
|
aclHeads: [A.1.2]
|
||||||
treeHeads: [A.1.2]
|
treeHeads: [A.1.2]
|
||||||
maybeHeads:
|
orphans:
|
||||||
- "A.1.3"
|
- "A.1.3"
|
||||||
- "B.1.2"
|
- "B.1.2"
|
||||||
|
|||||||
@ -101,6 +101,6 @@ graph:
|
|||||||
aclSnapshot: A.1.1
|
aclSnapshot: A.1.1
|
||||||
aclHeads: [A.1.3]
|
aclHeads: [A.1.3]
|
||||||
treeHeads: [A.1.3]
|
treeHeads: [A.1.3]
|
||||||
maybeHeads:
|
orphans:
|
||||||
- "A.1.4"
|
- "A.1.4"
|
||||||
- "B.1.2"
|
- "B.1.2"
|
||||||
|
|||||||
@ -124,7 +124,7 @@ graph:
|
|||||||
baseSnapshot: A.1.2
|
baseSnapshot: A.1.2
|
||||||
aclHeads: [A.1.2]
|
aclHeads: [A.1.2]
|
||||||
treeHeads: [A.1.2]
|
treeHeads: [A.1.2]
|
||||||
maybeHeads:
|
orphans:
|
||||||
- "A.1.3"
|
- "A.1.3"
|
||||||
- "B.1.2"
|
- "B.1.2"
|
||||||
|
|
||||||
|
|||||||
@ -100,6 +100,6 @@ type YMLThread struct {
|
|||||||
Graph []*GraphNode `yaml:"graph"`
|
Graph []*GraphNode `yaml:"graph"`
|
||||||
UpdatedGraph []*GraphNode `yaml:"updatedGraph"`
|
UpdatedGraph []*GraphNode `yaml:"updatedGraph"`
|
||||||
|
|
||||||
Heads []string `yaml:"heads"`
|
Heads []string `yaml:"heads"`
|
||||||
MaybeHeads []string `yaml:"maybeHeads"`
|
Orphans []string `yaml:"orphans"`
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user