refactor: move e2e tests into src/e2e directory
This commit is contained in:
177
src/e2e/e2e_permissions_test.go
Normal file
177
src/e2e/e2e_permissions_test.go
Normal file
@@ -0,0 +1,177 @@
|
||||
package e2e_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestPermissions(t *testing.T) {
|
||||
alice := newTestEnv(t, "alice")
|
||||
bob := alice.withUser("bob")
|
||||
|
||||
// Alice creates a node (gets has_ownership automatically).
|
||||
aliceNode := alice.parseNode(alice.mustAx("add", "Alice's secret", "--json"))
|
||||
aliceNodeID := aliceNode.ID
|
||||
|
||||
// Resolve alice's user node ID.
|
||||
var aliceUserID string
|
||||
for _, u := range alice.parseNodes(alice.mustAx("list", "--type", "user", "--json")) {
|
||||
if u.Title == "alice" {
|
||||
aliceUserID = u.ID
|
||||
}
|
||||
}
|
||||
if aliceUserID == "" {
|
||||
t.Fatal("could not resolve alice's user node ID")
|
||||
}
|
||||
|
||||
t.Run("NoAccess_CannotShow", func(t *testing.T) {
|
||||
_, err := bob.ax("show", aliceNodeID)
|
||||
if err == nil {
|
||||
t.Error("bob should not be able to show alice's node without access")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("NoAccess_NotInList", func(t *testing.T) {
|
||||
bob.mustAx("add", "Bob's scratch", "--json")
|
||||
|
||||
nodes := bob.parseNodes(bob.mustAx("list", "--json"))
|
||||
if _, ok := bob.findInList(nodes, aliceNodeID); ok {
|
||||
t.Error("alice's node should not appear in bob's list without access")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("NoAccess_CannotUpdate", func(t *testing.T) {
|
||||
_, err := bob.ax("update", aliceNodeID, "--title", "hacked")
|
||||
if err == nil {
|
||||
t.Error("bob should not be able to update alice's node without access")
|
||||
}
|
||||
})
|
||||
|
||||
// Resolve bob's user node ID. User nodes are globally readable.
|
||||
var bobUserID string
|
||||
for _, u := range alice.parseNodes(alice.mustAx("list", "--type", "user", "--json")) {
|
||||
if u.Title == "bob" {
|
||||
bobUserID = u.ID
|
||||
}
|
||||
}
|
||||
if bobUserID == "" {
|
||||
t.Fatal("could not resolve bob's user node ID")
|
||||
}
|
||||
|
||||
t.Run("SelfEscalation_Denied", func(t *testing.T) {
|
||||
_, err := bob.ax("update", bobUserID, "--rel", "can_write:"+aliceNodeID)
|
||||
if err == nil {
|
||||
t.Error("bob should not be able to grant himself write access to alice's node")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("ReadAccess_Grant", func(t *testing.T) {
|
||||
alice.mustAx("update", bobUserID, "--rel", "can_read:"+aliceNodeID)
|
||||
|
||||
if _, err := bob.ax("show", aliceNodeID); err != nil {
|
||||
t.Error("bob should be able to show alice's node after read access granted")
|
||||
}
|
||||
nodes := bob.parseNodes(bob.mustAx("list", "--json"))
|
||||
if _, ok := bob.findInList(nodes, aliceNodeID); !ok {
|
||||
t.Error("alice's node should appear in bob's list after read access granted")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("ReadAccess_CannotUpdate", func(t *testing.T) {
|
||||
_, err := bob.ax("update", aliceNodeID, "--title", "hacked with read access")
|
||||
if err == nil {
|
||||
t.Error("bob should not be able to update alice's node with only read access")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("ReadAccess_CannotAddRelationToNode", func(t *testing.T) {
|
||||
bobLinkedID := bob.parseNode(bob.mustAx("add", "Bob's linked node", "--json")).ID
|
||||
_, err := bob.ax("update", bobLinkedID, "--rel", "related:"+aliceNodeID)
|
||||
if err == nil {
|
||||
t.Error("bob should not be able to create a relation to alice's node with only read access")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("WriteAccess_Grant", func(t *testing.T) {
|
||||
alice.mustAx("update", bobUserID, "--rel", "can_write:"+aliceNodeID)
|
||||
|
||||
out := bob.mustAx("update", aliceNodeID, "--title", "Bob modified this", "--json")
|
||||
n := bob.parseNode(out)
|
||||
if n.Title != "Bob modified this" {
|
||||
t.Errorf("expected 'Bob modified this', got %q", n.Title)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("WriteAccess_CanAddRelationToNode", func(t *testing.T) {
|
||||
bobNode2 := bob.parseNode(bob.mustAx("add", "Bob's related node", "--json"))
|
||||
bob.mustAx("update", bobNode2.ID, "--rel", "related:"+aliceNodeID)
|
||||
out := bob.mustAx("show", bobNode2.ID, "--json")
|
||||
n := bob.parseNode(out)
|
||||
if !n.HasRelation("related", aliceNodeID) {
|
||||
t.Error("expected related relation after write access granted")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Ownership_DefaultOnCreate", func(t *testing.T) {
|
||||
userOut := alice.mustAx("show", aliceUserID, "--json")
|
||||
userNode := alice.parseNode(userOut)
|
||||
if !userNode.HasRelation("has_ownership", aliceUserID) {
|
||||
t.Errorf("expected user node to have self-ownership, got relations: %v", userNode.Relations)
|
||||
}
|
||||
if !userNode.HasRelation("has_ownership", aliceNodeID) {
|
||||
t.Errorf("expected alice to own her node, got relations: %v", userNode.Relations)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Ownership_CascadeDelete", func(t *testing.T) {
|
||||
throwaway := alice.withUser("throwaway")
|
||||
child := throwaway.parseNode(throwaway.mustAx("add", "Child node", "--json"))
|
||||
|
||||
var throwawayUserID string
|
||||
for _, u := range throwaway.parseNodes(throwaway.mustAx("list", "--type", "user", "--json")) {
|
||||
if u.Title == "throwaway" {
|
||||
throwawayUserID = u.ID
|
||||
}
|
||||
}
|
||||
if throwawayUserID == "" {
|
||||
t.Fatal("could not find throwaway user node")
|
||||
}
|
||||
|
||||
throwaway.mustAx("del", throwawayUserID, "--force")
|
||||
|
||||
_, err := throwaway.ax("show", child.ID)
|
||||
if err == nil {
|
||||
t.Error("child node should have been cascade-deleted when its owner was deleted")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestNamespaceExplicitCreate(t *testing.T) {
|
||||
env := newTestEnv(t, "testuser")
|
||||
|
||||
nsNode := env.parseNode(env.mustAx("add", "myworkspace", "--type", "namespace", "--json"))
|
||||
|
||||
if !nsNode.HasRelation("in_namespace", nsNode.ID) {
|
||||
t.Errorf("expected namespace to have in_namespace pointing to itself, got relations: %v", nsNode.Relations)
|
||||
}
|
||||
|
||||
users := env.parseNodes(env.mustAx("list", "--type", "user", "--json"))
|
||||
var userNode *NodeResponse
|
||||
for i := range users {
|
||||
if users[i].Title == "testuser" {
|
||||
userNode = &users[i]
|
||||
break
|
||||
}
|
||||
}
|
||||
if userNode == nil {
|
||||
t.Fatal("could not find testuser node")
|
||||
}
|
||||
if !userNode.HasRelation("has_ownership", nsNode.ID) {
|
||||
t.Errorf("expected creator to have has_ownership on new namespace, got relations: %v", userNode.Relations)
|
||||
}
|
||||
|
||||
env.mustAx("add", "task in workspace", "--namespace", "myworkspace", "--json")
|
||||
listed := env.parseNodes(env.mustAx("list", "--namespace", "myworkspace", "--json"))
|
||||
if len(listed) == 0 {
|
||||
t.Error("expected to list nodes in newly created namespace")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user