diff --git a/tests/integration/acp.go b/tests/integration/acp.go index 9242a266fc..6604f4602c 100644 --- a/tests/integration/acp.go +++ b/tests/integration/acp.go @@ -119,6 +119,121 @@ func addPolicyACP( } } +// AddDocActorRelationship will attempt to create a new relationship for a document with an actor. +type AddDocActorRelationship struct { + // NodeID may hold the ID (index) of the node we want to add doc actor relationship on. + // + // If a value is not provided the relationship will be added in all nodes, unless testing with + // sourcehub ACP, in which case the relationship will only be defined once. + NodeID immutable.Option[int] + + // The collection in which this document we want to add a relationship for exists. + // + // This is a required field. To test the invalid usage of not having this arg, use -1 index. + CollectionID int + + // The index-identifier of the document within the collection. This is based on + // the order in which it was created, not the ordering of the document within the + // database. + // + // This is a required field. To test the invalid usage of not having this arg, use -1 index. + DocID int + + // The name of the relation to set between document and target actor (should be defined in the policy). + // + // This is a required field. + Relation string + + // The target public identity, i.e. the identity of the actor to tie the document's relation with. + // + // This is a required field. To test the invalid usage of not having this arg, use -1 index. + TargetIdentity int + + // The requestor identity, i.e. identity of the actor creating the relationship. + // Note: This identity must either own or have managing access defined in the policy. + // + // This is a required field. To test the invalid usage of not having this arg, use -1 index. + RequestorIdentity int + + // Result returns true if it was a no-op due to existing before, and false if a new relationship was made. + ExpectedExistence bool + + // Any error expected from the action. Optional. + // + // String can be a partial, and the test will pass if an error is returned that + // contains this string. + ExpectedError string +} + +func addDocActorRelationshipACP( + s *state, + action AddDocActorRelationship, +) { + for i, node := range getNodes(action.NodeID, s.nodes) { + var collectionName string + if action.CollectionID == -1 { + collectionName = "" + } else { + collection := s.collections[i][action.CollectionID] + if !collection.Description().Name.HasValue() { + require.Fail(s.t, "Expected non-empty collection name, but it was empty.", s.testCase.Description) + } + collectionName = collection.Description().Name.Value() + } + + var docID string + if action.DocID == -1 { + docID = "" + } else { + docID = s.docIDs[action.CollectionID][action.DocID].String() + } + + var targetIdentity string + if action.TargetIdentity == -1 { + targetIdentity = "" + } else { + optionalTargetIdentity := getIdentity(s, i, immutable.Some(action.TargetIdentity)) + if !optionalTargetIdentity.HasValue() { + require.Fail(s.t, "Expected non-empty target identity, but it was empty.", s.testCase.Description) + } + targetIdentity = optionalTargetIdentity.Value().DID + } + + var requestorIdentity immutable.Option[acpIdentity.Identity] + if action.RequestorIdentity == -1 { + requestorIdentity = acpIdentity.None + } else { + requestorIdentity = getIdentity(s, i, immutable.Some(action.RequestorIdentity)) + if !requestorIdentity.HasValue() { + require.Fail(s.t, "Expected non-empty requestor identity, but it was empty.", s.testCase.Description) + } + } + ctx := db.SetContextIdentity(s.ctx, requestorIdentity) + + exists, err := node.AddDocActorRelationship( + ctx, + collectionName, + docID, + action.Relation, + targetIdentity, + ) + + if err == nil { + require.Equal(s.t, action.ExpectedError, "") + require.Equal(s.t, action.ExpectedExistence, exists) + } + + expectedErrorRaised := AssertError(s.t, s.testCase.Description, err, action.ExpectedError) + assertExpectedErrorRaised(s.t, s.testCase.Description, action.ExpectedError, expectedErrorRaised) + + // The relationship should only be added to a SourceHub chain once - there is no need to loop through + // the nodes. + if acpType == SourceHubACPType { + break + } + } +} + func setupSourceHub(s *state) ([]node.ACPOpt, error) { var isACPTest bool for _, a := range s.testCase.Actions { diff --git a/tests/integration/utils.go b/tests/integration/utils.go index 2576f30762..a6c70b5ab6 100644 --- a/tests/integration/utils.go +++ b/tests/integration/utils.go @@ -299,6 +299,9 @@ func performAction( case AddPolicy: addPolicyACP(s, action) + case AddDocActorRelationship: + addDocActorRelationshipACP(s, action) + case CreateDoc: createDoc(s, action)