From 9417306aa3a1218777acf14daaf292d5d2890d94 Mon Sep 17 00:00:00 2001 From: Cory Slep Date: Sun, 24 Feb 2019 13:05:00 +0100 Subject: [PATCH] Outline the needed federating side effects tests. --- pub/federating_wrapped_callbacks.go | 47 +++- pub/federating_wrapped_callbacks_test.go | 297 +++++++++++++++++++++++ pub/pub_test.go | 22 +- pub/util.go | 4 + 4 files changed, 353 insertions(+), 17 deletions(-) create mode 100644 pub/federating_wrapped_callbacks_test.go diff --git a/pub/federating_wrapped_callbacks.go b/pub/federating_wrapped_callbacks.go index e1c66d9..3af8e56 100644 --- a/pub/federating_wrapped_callbacks.go +++ b/pub/federating_wrapped_callbacks.go @@ -488,6 +488,8 @@ func (w FederatingWrappedCallbacks) accept(c context.Context, a vocab.ActivitySt // Unlock must be called by now and every branch above. // // Determine if we are in a follow on the 'object' property. + // + // TODO: Handle Accept multiple Follow. var maybeMyFollowIRI *url.URL for iter := op.Begin(); iter != op.End(); iter = iter.Next() { t := iter.GetType() @@ -546,6 +548,13 @@ func (w FederatingWrappedCallbacks) accept(c context.Context, a vocab.ActivitySt if maybeMyFollowIRI != nil { // Verify our Follow request exists and the peer didn't // fabricate it. + actors := a.GetActivityStreamsActor() + if actors == nil || actors.Len() == 0 { + return fmt.Errorf("an Accept with a Follow has no actors") + } + // This may be a duplicate check if we dereferenced the + // Follow above. TODO: Separate this logic to avoid + // redundancy. // // Use an anonymous function to properly scope the // database lock, immediately call it. @@ -566,6 +575,7 @@ func (w FederatingWrappedCallbacks) accept(c context.Context, a vocab.ActivitySt return fmt.Errorf("a Follow in an Accept does not satisfy the Activity interface") } // Ensure that we are one of the actors on the Follow. + ok = false actors := follow.GetActivityStreamsActor() for iter := actors.Begin(); iter != actors.End(); iter = iter.Next() { id, err := ToId(iter) @@ -573,19 +583,44 @@ func (w FederatingWrappedCallbacks) accept(c context.Context, a vocab.ActivitySt return err } if id.String() == actorIRI.String() { - return nil + ok = true + break } } - return fmt.Errorf("peer gave an Accept wrapping a Follow but we are not the actor on that Follow") + if !ok { + return fmt.Errorf("peer gave an Accept wrapping a Follow but we are not the actor on that Follow") + } + // Build map of original Accept actors + acceptActors := make(map[string]bool) + for iter := actors.Begin(); iter != actors.End(); iter = iter.Next() { + id, err := ToId(iter) + if err != nil { + return err + } + acceptActors[id.String()] = false + } + // Verify all actor(s) were on the original Follow. + followObj := follow.GetActivityStreamsObject() + for iter := followObj.Begin(); iter != followObj.End(); iter = iter.Next() { + id, err := ToId(iter) + if err != nil { + return err + } + if _, ok := acceptActors[id.String()]; ok { + acceptActors[id.String()] = true + } + } + for _, found := range acceptActors { + if !found { + return fmt.Errorf("peer gave an Accept wrapping a Follow but was not an object in the original Follow") + } + } + return nil }() if err != nil { return err } // Add the peer to our following collection. - actors := a.GetActivityStreamsActor() - if actors == nil || actors.Len() == 0 { - return fmt.Errorf("an Accept with a Follow has no actors") - } if err := w.db.Lock(c, actorIRI); err != nil { return err } diff --git a/pub/federating_wrapped_callbacks_test.go b/pub/federating_wrapped_callbacks_test.go new file mode 100644 index 0000000..f09731d --- /dev/null +++ b/pub/federating_wrapped_callbacks_test.go @@ -0,0 +1,297 @@ +package pub + +import ( + "testing" +) + +// TestFederatedCallbacks tests the overriding functionality. +func TestFederatedCallbacks(t *testing.T) { + t.Run("ReturnsOtherCallback", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("OverridesCreate", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("OverridesUpdate", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("OverridesDelete", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("OverridesFollow", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("OverridesAccept", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("OverridesReject", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("OverridesAdd", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("OverridesRemove", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("OverridesLike", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("OverridesAnnounce", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("OverridesUndo", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("OverridesBlock", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) +} + +func TestFederatedCreate(t *testing.T) { + t.Run("ErrorIfNoObject", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("ErrorIfObjectLengthZero", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("CreatesFederatedObject", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("CreatesAllFederatedObjects", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("DereferencesIRIObject", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("CallsCustomCallback", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) +} + +func TestFederatedUpdate(t *testing.T) { + t.Run("ErrorIfNoObject", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("ErrorIfObjectLengthZero", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("ErrorIfOriginMismatchesObject", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("UpdatesFederatedObject", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("UpdatesAllFederatedObjects", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("ErrorIfObjectIsIRI", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("CallsCustomCallback", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) +} + +func TestFederatedDelete(t *testing.T) { + t.Run("ErrorIfNoObject", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("ErrorIfObjectLengthZero", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("ErrorIfOriginMismatchesObject", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("DeletesFederatedObject", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("DeletesAllFederatedObjects", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("CallsCustomCallback", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) +} + +func TestFederatedFollow(t *testing.T) { + t.Run("ErrorIfNoObject", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("ErrorIfObjectLengthZero", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("OnFollowNothingDoesNothing", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("OnFollowAutomaticallyAcceptUpdatesFollowers", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("OnFollowAutomaticallyAcceptDelivers", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("OnFollowAutomaticallyRejectDelivers", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("OnFollowNothingCallsCustomCallback", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("OnFollowAutomaticallyAcceptCallsCustomCallback", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("OnFollowAutomaticallyRejectCallsCustomCallback", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) +} + +func TestFederatedAccept(t *testing.T) { + t.Run("DoesNothingIfNoObjects", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("DereferencesObjectIRI", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("IgnoresNonFollowObjects", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("IgnoresFollowObjectsNotContainingMe", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("VerifiesFollowExistsAndIsWellFormatted", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("UpdatesFollowingCollection", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("CallsCustomCallback", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) +} + +func TestFederatedReject(t *testing.T) { + t.Run("CallsCustomCallback", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) +} + +func TestFederatedAdd(t *testing.T) { + t.Run("ErrorIfNoObject", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("ErrorIfObjectLengthZero", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("ErrorIfNoTarget", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("ErrorIfTargetLengthZero", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("AddsAllObjectIdsToCollection", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("AddsAllObjectIdsToOrderedCollection", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("ReturnsErrorIfTargetIsNotCollection", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("CallsCustomCallback", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) +} + +func TestFederatedRemove(t *testing.T) { + t.Run("ErrorIfNoObject", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("ErrorIfObjectLengthZero", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("ErrorIfNoTarget", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("ErrorIfTargetLengthZero", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("RemovesAllObjectIdsFromCollection", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("RemovesAllObjectIdsFromOrderedCollection", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("ReturnsErrorIfTargetIsNotCollection", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("CallsCustomCallback", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) +} + +func TestFederatedLike(t *testing.T) { + t.Run("ErrorIfNoObject", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("ErrorIfObjectLengthZero", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("SkipsUnownedObjects", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("AddsToNewLikesCollection", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("AddsToExistingLikesCollection", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("AddsToExistingLikesOrderedCollection", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("CallsCustomCallback", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) +} + +func TestFederatedAnnounce(t *testing.T) { + t.Run("SkipsUnownedObjects", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("AddsToNewSharesCollection", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("AddsToExistingSharesCollection", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("AddsToExistingSharesOrderedCollection", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("CallsCustomCallback", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) +} + +func TestFederatedUndo(t *testing.T) { + t.Run("ErrorIfNoObject", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("ErrorIfObjectLengthZero", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("ErrorIfActorMismatch", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("CallsCustomCallback", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) +} + +func TestFederatedBlock(t *testing.T) { + t.Run("ErrorIfNoObject", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("ErrorIfObjectLengthZero", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) + t.Run("CallsCustomCallback", func(t *testing.T) { + t.Errorf("Not yet implemented.") + }) +} diff --git a/pub/pub_test.go b/pub/pub_test.go index 387596c..9227104 100644 --- a/pub/pub_test.go +++ b/pub/pub_test.go @@ -25,14 +25,14 @@ const ( testNoteId1 = "https://example.com/note/1" testNoteId2 = "https://example.com/note/2" testNewActivityIRI = "https://example.com/new/1" - testToIRI = "https://maybe.example.com/to/1" - testToIRI2 = "https://maybe.example.com/to/2" - testCcIRI = "https://maybe.example.com/cc/1" - testCcIRI2 = "https://maybe.example.com/cc/2" - testAudienceIRI = "https://maybe.example.com/audience/1" - testAudienceIRI2 = "https://maybe.example.com/audience/2" - testPersonIRI = "https://maybe.example.com/person" - testServiceIRI = "https://maybe.example.com/service" + testToIRI = "https://maybe.example.com/to/1" + testToIRI2 = "https://maybe.example.com/to/2" + testCcIRI = "https://maybe.example.com/cc/1" + testCcIRI2 = "https://maybe.example.com/cc/2" + testAudienceIRI = "https://maybe.example.com/audience/1" + testAudienceIRI2 = "https://maybe.example.com/audience/2" + testPersonIRI = "https://maybe.example.com/person" + testServiceIRI = "https://maybe.example.com/service" ) // mustParse parses a URL or panics. @@ -230,19 +230,19 @@ func setupData() { testOrderedCollectionWithBothFederatedIds.SetActivityStreamsOrderedItems(oi) }() // testPerson - func () { + func() { testPerson = streams.NewActivityStreamsPerson() id := streams.NewActivityStreamsIdProperty() id.Set(mustParse(testPersonIRI)) testPerson.SetActivityStreamsId(id) }() // testService - func () { + func() { testService = streams.NewActivityStreamsService() id := streams.NewActivityStreamsIdProperty() id.Set(mustParse(testServiceIRI)) testService.SetActivityStreamsId(id) - } () + }() } // wrappedInCreate returns a Create activity wrapping the given type. diff --git a/pub/util.go b/pub/util.go index 2cbef20..97d5a65 100644 --- a/pub/util.go +++ b/pub/util.go @@ -896,6 +896,8 @@ func add(c context.Context, for _, objId := range opIds { iProp.AppendIRI(objId) } + } else { + return fmt.Errorf("target in Add is neither a Collection nor an OrderedCollection") } err = db.Update(c, tp) if err != nil { @@ -987,6 +989,8 @@ func remove(c context.Context, } } } + } else { + return fmt.Errorf("target in Remove is neither a Collection nor an OrderedCollection") } err = db.Update(c, tp) if err != nil {