Add extra integration tests.
These generally include improving the handling of OrderedCollections and IRIs. Note that improvement to setting IRI'd fetches from the implementing application were made. Improve the handing of AutoAccept and AutoReject follows. If there are no owned objects in the Activity, we prevent sending the automatic reply in case the implemented application is not checking for ownership of the object of the original Follow activity.
このコミットが含まれているのは:
コミット
4bad90902e
76
pub/fed.go
76
pub/fed.go
@ -695,27 +695,27 @@ func (f *federator) handleClientLike(ctx context.Context, deliverable *bool) fun
|
||||
if s.LenObject() == 0 {
|
||||
return ErrObjectRequired
|
||||
}
|
||||
getter := func(actor vocab.ObjectType, lc *vocab.CollectionType, loc *vocab.OrderedCollectionType) error {
|
||||
getter := func(actor vocab.ObjectType, lc *vocab.CollectionType, loc *vocab.OrderedCollectionType) (bool, error) {
|
||||
if actor.IsLikedAnyURI() {
|
||||
pObj, err := f.App.Get(ctx, actor.GetLikedAnyURI())
|
||||
if err != nil {
|
||||
return err
|
||||
return true, err
|
||||
}
|
||||
ok := false
|
||||
if *lc, ok = pObj.(vocab.CollectionType); !ok {
|
||||
if *loc, ok = pObj.(vocab.OrderedCollectionType); !ok {
|
||||
return fmt.Errorf("actors liked collection not CollectionType nor OrderedCollectionType")
|
||||
return true, fmt.Errorf("actors liked collection not CollectionType nor OrderedCollectionType")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
return true, nil
|
||||
} else if actor.IsLikedCollection() {
|
||||
*lc = actor.GetLikedCollection()
|
||||
return nil
|
||||
return false, nil
|
||||
} else if actor.IsLikedOrderedCollection() {
|
||||
*loc = actor.GetLikedOrderedCollection()
|
||||
return nil
|
||||
return false, nil
|
||||
}
|
||||
return fmt.Errorf("cannot determine type of actor liked")
|
||||
return false, fmt.Errorf("cannot determine type of actor liked")
|
||||
}
|
||||
if err := f.addAllObjectsToActorCollection(ctx, getter, s.Raw()); err != nil {
|
||||
return err
|
||||
@ -863,34 +863,44 @@ func (f *federator) handleFollow(c context.Context) func(s *streams.Follow) erro
|
||||
activity.AddToIRI(raw.GetActorIRI(i))
|
||||
}
|
||||
}
|
||||
if err := f.deliver(activity); err != nil {
|
||||
return err
|
||||
}
|
||||
ownsAny := false
|
||||
if todo == AutomaticAccept {
|
||||
getter := func(object vocab.ObjectType, lc *vocab.CollectionType, loc *vocab.OrderedCollectionType) error {
|
||||
getter := func(object vocab.ObjectType, lc *vocab.CollectionType, loc *vocab.OrderedCollectionType) (bool, error) {
|
||||
if object.IsFollowersAnyURI() {
|
||||
pObj, err := f.App.Get(c, object.GetFollowersAnyURI())
|
||||
if err != nil {
|
||||
return err
|
||||
return true, err
|
||||
}
|
||||
ok := false
|
||||
if *lc, ok = pObj.(vocab.CollectionType); !ok {
|
||||
if *loc, ok = pObj.(vocab.OrderedCollectionType); !ok {
|
||||
return fmt.Errorf("object followers collection not CollectionType nor OrderedCollectionType")
|
||||
return true, fmt.Errorf("object followers collection not CollectionType nor OrderedCollectionType")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
return true, nil
|
||||
} else if object.IsFollowersCollection() {
|
||||
*lc = object.GetFollowersCollection()
|
||||
return nil
|
||||
return false, nil
|
||||
} else if object.IsFollowersOrderedCollection() {
|
||||
*loc = object.GetFollowersOrderedCollection()
|
||||
return nil
|
||||
return false, nil
|
||||
}
|
||||
return fmt.Errorf("cannot determine type of object followers")
|
||||
return false, fmt.Errorf("cannot determine type of object followers")
|
||||
}
|
||||
// TODO: Deduplication detection.
|
||||
if err := f.addAllActorsToObjectCollection(c, getter, raw); err != nil {
|
||||
var err error
|
||||
if ownsAny, err = f.addAllActorsToObjectCollection(c, getter, raw); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if todo == AutomaticReject {
|
||||
var err error
|
||||
ownsAny, err = f.ownsAnyObjects(c, raw)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if ownsAny {
|
||||
if err := f.deliver(activity); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -912,27 +922,27 @@ func (f *federator) handleAccept(c context.Context) func(s *streams.Accept) erro
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
getter := func(actor vocab.ObjectType, lc *vocab.CollectionType, loc *vocab.OrderedCollectionType) error {
|
||||
getter := func(actor vocab.ObjectType, lc *vocab.CollectionType, loc *vocab.OrderedCollectionType) (bool, error) {
|
||||
if actor.IsFollowingAnyURI() {
|
||||
pObj, err := f.App.Get(c, actor.GetFollowingAnyURI())
|
||||
if err != nil {
|
||||
return err
|
||||
return true, err
|
||||
}
|
||||
ok := false
|
||||
if *lc, ok = pObj.(vocab.CollectionType); !ok {
|
||||
if *loc, ok = pObj.(vocab.OrderedCollectionType); !ok {
|
||||
return fmt.Errorf("actors following collection not CollectionType nor OrderedCollectionType")
|
||||
return true, fmt.Errorf("actors following collection not CollectionType nor OrderedCollectionType")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
return true, nil
|
||||
} else if actor.IsFollowingCollection() {
|
||||
*lc = actor.GetFollowingCollection()
|
||||
return nil
|
||||
return false, nil
|
||||
} else if actor.IsFollowingOrderedCollection() {
|
||||
*loc = actor.GetFollowingOrderedCollection()
|
||||
return nil
|
||||
return false, nil
|
||||
}
|
||||
return fmt.Errorf("cannot determine type of actor following")
|
||||
return false, fmt.Errorf("cannot determine type of actor following")
|
||||
}
|
||||
// TODO: Deduplication detection.
|
||||
if err := f.addAllObjectsToActorCollection(c, getter, follow); err != nil {
|
||||
@ -1087,29 +1097,29 @@ func (f *federator) handleLike(c context.Context) func(s *streams.Like) error {
|
||||
if s.LenObject() == 0 {
|
||||
return ErrObjectRequired
|
||||
}
|
||||
getter := func(object vocab.ObjectType, lc *vocab.CollectionType, loc *vocab.OrderedCollectionType) error {
|
||||
getter := func(object vocab.ObjectType, lc *vocab.CollectionType, loc *vocab.OrderedCollectionType) (bool, error) {
|
||||
if object.IsLikesAnyURI() {
|
||||
pObj, err := f.App.Get(c, object.GetLikesAnyURI())
|
||||
if err != nil {
|
||||
return err
|
||||
return true, err
|
||||
}
|
||||
ok := false
|
||||
if *lc, ok = pObj.(vocab.CollectionType); !ok {
|
||||
if *loc, ok = pObj.(vocab.OrderedCollectionType); !ok {
|
||||
return fmt.Errorf("object likes collection not CollectionType nor OrderedCollectionType")
|
||||
return true, fmt.Errorf("object likes collection not CollectionType nor OrderedCollectionType")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
return true, nil
|
||||
} else if object.IsLikesCollection() {
|
||||
*lc = object.GetLikesCollection()
|
||||
return nil
|
||||
return false, nil
|
||||
} else if object.IsLikesOrderedCollection() {
|
||||
*loc = object.GetLikesOrderedCollection()
|
||||
return nil
|
||||
return false, nil
|
||||
}
|
||||
return fmt.Errorf("cannot determine type of object likes")
|
||||
return false, fmt.Errorf("cannot determine type of object likes")
|
||||
}
|
||||
if err := f.addAllActorsToObjectCollection(c, getter, s.Raw()); err != nil {
|
||||
if _, err := f.addAllActorsToObjectCollection(c, getter, s.Raw()); err != nil {
|
||||
return err
|
||||
}
|
||||
return f.ServerCallbacker.Like(c, s)
|
||||
|
437
pub/fed_test.go
437
pub/fed_test.go
@ -17,20 +17,21 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
iriString = "https://example.com/something"
|
||||
noteURIString = "https://example.com/note/123"
|
||||
updateURIString = "https://example.com/note/update/123"
|
||||
noteActivityURIString = "https://example.com/activity/987"
|
||||
testAgent = "test agent string"
|
||||
testInboxURI = "https://example.com/sally/inbox"
|
||||
testOutboxURI = "https://example.com/sally/outbox"
|
||||
testNewIRIString = "https://example.com/test/new/iri"
|
||||
sallyIRIString = "https://example.com/sally"
|
||||
samIRIString = "https://example.com/sam"
|
||||
samIRIInboxString = "https://example.com/sam/inbox"
|
||||
samIRIFollowersString = "https://example.com/sam/followers"
|
||||
sallyIRIInboxString = "https://example.com/sally/inbox"
|
||||
noteName = "A Note"
|
||||
iriString = "https://example.com/something"
|
||||
noteURIString = "https://example.com/note/123"
|
||||
updateURIString = "https://example.com/note/update/123"
|
||||
noteActivityURIString = "https://example.com/activity/987"
|
||||
testAgent = "test agent string"
|
||||
testInboxURI = "https://example.com/sally/inbox"
|
||||
testOutboxURI = "https://example.com/sally/outbox"
|
||||
testNewIRIString = "https://example.com/test/new/iri"
|
||||
sallyIRIString = "https://example.com/sally"
|
||||
sallyFollowingIRIString = "https://example.com/sally/following"
|
||||
samIRIString = "https://example.com/sam"
|
||||
samIRIInboxString = "https://example.com/sam/inbox"
|
||||
samIRIFollowersString = "https://example.com/sam/followers"
|
||||
sallyIRIInboxString = "https://example.com/sally/inbox"
|
||||
noteName = "A Note"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -41,6 +42,7 @@ var (
|
||||
testNewIRI *url.URL
|
||||
sallyIRI *url.URL
|
||||
sallyIRIInbox *url.URL
|
||||
sallyFollowingIRI *url.URL
|
||||
sallyActor *vocab.Person
|
||||
sallyActorJSON []byte
|
||||
samIRI *url.URL
|
||||
@ -111,6 +113,10 @@ func init() {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
sallyFollowingIRI, err = url.Parse(sallyFollowingIRIString)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
samIRI, err = url.Parse(samIRIString)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@ -1979,6 +1985,13 @@ func TestPostInbox_Follow_AutoReject(t *testing.T) {
|
||||
fedCb.follow = func(c context.Context, s *streams.Follow) error {
|
||||
return nil
|
||||
}
|
||||
gotOwns := 0
|
||||
var ownsIRI url.URL
|
||||
app.owns = func(c context.Context, id url.URL) bool {
|
||||
gotOwns++
|
||||
ownsIRI = id
|
||||
return true
|
||||
}
|
||||
gotHttpDo := 0
|
||||
var httpActorRequest *http.Request
|
||||
var httpDeliveryRequest *http.Request
|
||||
@ -2028,6 +2041,10 @@ func TestPostInbox_Follow_AutoReject(t *testing.T) {
|
||||
t.Fatalf("expected %s, got %s", sallyIRIString, s)
|
||||
} else if s := httpDeliveryRequest.URL.String(); s != sallyIRIInboxString {
|
||||
t.Fatalf("expected %s, got %s", sallyIRIInboxString, s)
|
||||
} else if gotOwns != 1 {
|
||||
t.Fatalf("expected %d, got %d", 1, gotOwns)
|
||||
} else if ownsIRI.String() != samIRIString {
|
||||
t.Fatalf("expected %s, got %s", samIRIString, ownsIRI.String())
|
||||
} else if gotDoDelivery != 1 {
|
||||
t.Fatalf("expected %d, got %d", 1, gotDoDelivery)
|
||||
} else if doDeliveryURL.String() != sallyIRIInboxString {
|
||||
@ -2037,8 +2054,6 @@ func TestPostInbox_Follow_AutoReject(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Test follower OrderedCollection & IRI.
|
||||
// TODO: Test does not own one of the objects.
|
||||
func TestPostInbox_Follow_AutoAccept(t *testing.T) {
|
||||
app, socialApp, fedApp, socialCb, fedCb, d, httpClient, p := NewPubberTest(t)
|
||||
PreparePostInboxTest(t, app, socialApp, fedApp, socialCb, fedCb, d, httpClient, p)
|
||||
@ -2155,6 +2170,190 @@ func TestPostInbox_Follow_AutoAccept(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestPostInbox_Follow_AutoAcceptFollowersIsOrderedCollection(t *testing.T) {
|
||||
app, socialApp, fedApp, socialCb, fedCb, d, httpClient, p := NewPubberTest(t)
|
||||
PreparePostInboxTest(t, app, socialApp, fedApp, socialCb, fedCb, d, httpClient, p)
|
||||
resp := httptest.NewRecorder()
|
||||
req := ActivityPubRequest(httptest.NewRequest("POST", testInboxURI, bytes.NewBuffer(MustSerialize(testFollow))))
|
||||
fedApp.onFollow = func(c context.Context, s *streams.Follow) FollowResponse {
|
||||
return AutomaticAccept
|
||||
}
|
||||
fedCb.follow = func(c context.Context, s *streams.Follow) error {
|
||||
return nil
|
||||
}
|
||||
gotHttpDo := 0
|
||||
httpClient.do = func(req *http.Request) (*http.Response, error) {
|
||||
gotHttpDo++
|
||||
if gotHttpDo == 1 {
|
||||
actorResp := &http.Response{
|
||||
StatusCode: http.StatusOK,
|
||||
Body: ioutil.NopCloser(bytes.NewBuffer(sallyActorJSON)),
|
||||
}
|
||||
return actorResp, nil
|
||||
} else if gotHttpDo == 2 {
|
||||
okResp := &http.Response{
|
||||
StatusCode: http.StatusOK,
|
||||
Body: ioutil.NopCloser(bytes.NewBuffer([]byte{})),
|
||||
}
|
||||
return okResp, nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
d.do = func(b []byte, u url.URL, toDo func(b []byte, u url.URL) error) {
|
||||
if err := toDo(b, u); err != nil {
|
||||
t.Fatalf("Unexpected error in MockDeliverer.Do: %s", err)
|
||||
}
|
||||
}
|
||||
app.owns = func(c context.Context, id url.URL) bool {
|
||||
return true
|
||||
}
|
||||
app.get = func(c context.Context, id url.URL) (PubObject, error) {
|
||||
samActor := &vocab.Person{}
|
||||
samActor.SetInboxAnyURI(*samIRIInbox)
|
||||
samActor.SetId(*samIRI)
|
||||
samActor.SetFollowersOrderedCollection(&vocab.OrderedCollection{})
|
||||
return samActor, nil
|
||||
}
|
||||
gotSet := 0
|
||||
var setObject PubObject
|
||||
app.set = func(c context.Context, o PubObject) error {
|
||||
gotSet++
|
||||
if gotSet == 1 {
|
||||
setObject = o
|
||||
}
|
||||
return nil
|
||||
}
|
||||
handled, err := p.PostInbox(context.Background(), resp, req)
|
||||
expectedFollowers := &vocab.OrderedCollection{}
|
||||
expectedFollowers.AddOrderedItemsObject(sallyActor)
|
||||
expectedActor := &vocab.Person{}
|
||||
expectedActor.SetInboxAnyURI(*samIRIInbox)
|
||||
expectedActor.SetId(*samIRI)
|
||||
expectedActor.SetFollowersOrderedCollection(expectedFollowers)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
} else if !handled {
|
||||
t.Fatalf("expected handled, got !handled")
|
||||
} else if err := PubObjectEquals(setObject, expectedActor); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPostInbox_Follow_AutoAcceptFollowersIsIRI(t *testing.T) {
|
||||
app, socialApp, fedApp, socialCb, fedCb, d, httpClient, p := NewPubberTest(t)
|
||||
PreparePostInboxTest(t, app, socialApp, fedApp, socialCb, fedCb, d, httpClient, p)
|
||||
resp := httptest.NewRecorder()
|
||||
req := ActivityPubRequest(httptest.NewRequest("POST", testInboxURI, bytes.NewBuffer(MustSerialize(testFollow))))
|
||||
fedApp.onFollow = func(c context.Context, s *streams.Follow) FollowResponse {
|
||||
return AutomaticAccept
|
||||
}
|
||||
fedCb.follow = func(c context.Context, s *streams.Follow) error {
|
||||
return nil
|
||||
}
|
||||
gotHttpDo := 0
|
||||
httpClient.do = func(req *http.Request) (*http.Response, error) {
|
||||
gotHttpDo++
|
||||
if gotHttpDo == 1 {
|
||||
actorResp := &http.Response{
|
||||
StatusCode: http.StatusOK,
|
||||
Body: ioutil.NopCloser(bytes.NewBuffer(sallyActorJSON)),
|
||||
}
|
||||
return actorResp, nil
|
||||
} else if gotHttpDo == 2 {
|
||||
okResp := &http.Response{
|
||||
StatusCode: http.StatusOK,
|
||||
Body: ioutil.NopCloser(bytes.NewBuffer([]byte{})),
|
||||
}
|
||||
return okResp, nil
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
d.do = func(b []byte, u url.URL, toDo func(b []byte, u url.URL) error) {
|
||||
if err := toDo(b, u); err != nil {
|
||||
t.Fatalf("Unexpected error in MockDeliverer.Do: %s", err)
|
||||
}
|
||||
}
|
||||
app.owns = func(c context.Context, id url.URL) bool {
|
||||
return true
|
||||
}
|
||||
app.get = func(c context.Context, id url.URL) (PubObject, error) {
|
||||
if id == *samIRI {
|
||||
samActor := &vocab.Person{}
|
||||
samActor.SetInboxAnyURI(*samIRIInbox)
|
||||
samActor.SetId(*samIRI)
|
||||
samActor.SetFollowersAnyURI(*testNewIRI)
|
||||
return samActor, nil
|
||||
} else if id == *testNewIRI {
|
||||
return &vocab.Collection{}, nil
|
||||
}
|
||||
t.Fatalf("unexpected get(%s)", &id)
|
||||
return nil, nil
|
||||
}
|
||||
gotSet := 0
|
||||
var setObject PubObject
|
||||
app.set = func(c context.Context, o PubObject) error {
|
||||
gotSet++
|
||||
if gotSet == 1 {
|
||||
setObject = o
|
||||
}
|
||||
return nil
|
||||
}
|
||||
handled, err := p.PostInbox(context.Background(), resp, req)
|
||||
expectedFollowers := &vocab.Collection{}
|
||||
expectedFollowers.AddItemsObject(sallyActor)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
} else if !handled {
|
||||
t.Fatalf("expected handled, got !handled")
|
||||
} else if err := PubObjectEquals(setObject, expectedFollowers); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPostInbox_Follow_DoesNotAutoAcceptIfNotOwned(t *testing.T) {
|
||||
app, socialApp, fedApp, socialCb, fedCb, d, httpClient, p := NewPubberTest(t)
|
||||
PreparePostInboxTest(t, app, socialApp, fedApp, socialCb, fedCb, d, httpClient, p)
|
||||
resp := httptest.NewRecorder()
|
||||
req := ActivityPubRequest(httptest.NewRequest("POST", testInboxURI, bytes.NewBuffer(MustSerialize(testFollow))))
|
||||
fedApp.onFollow = func(c context.Context, s *streams.Follow) FollowResponse {
|
||||
return AutomaticAccept
|
||||
}
|
||||
fedCb.follow = func(c context.Context, s *streams.Follow) error {
|
||||
return nil
|
||||
}
|
||||
app.owns = func(c context.Context, id url.URL) bool {
|
||||
return false
|
||||
}
|
||||
handled, err := p.PostInbox(context.Background(), resp, req)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
} else if !handled {
|
||||
t.Fatalf("expected handled, got !handled")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPostInbox_Follow_DoesNotAutoRejectIfNotOwned(t *testing.T) {
|
||||
app, socialApp, fedApp, socialCb, fedCb, d, httpClient, p := NewPubberTest(t)
|
||||
PreparePostInboxTest(t, app, socialApp, fedApp, socialCb, fedCb, d, httpClient, p)
|
||||
resp := httptest.NewRecorder()
|
||||
req := ActivityPubRequest(httptest.NewRequest("POST", testInboxURI, bytes.NewBuffer(MustSerialize(testFollow))))
|
||||
fedApp.onFollow = func(c context.Context, s *streams.Follow) FollowResponse {
|
||||
return AutomaticReject
|
||||
}
|
||||
fedCb.follow = func(c context.Context, s *streams.Follow) error {
|
||||
return nil
|
||||
}
|
||||
app.owns = func(c context.Context, id url.URL) bool {
|
||||
return false
|
||||
}
|
||||
handled, err := p.PostInbox(context.Background(), resp, req)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
} else if !handled {
|
||||
t.Fatalf("expected handled, got !handled")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPostInbox_Follow_CallsCallback(t *testing.T) {
|
||||
app, socialApp, fedApp, socialCb, fedCb, d, httpClient, p := NewPubberTest(t)
|
||||
PreparePostInboxTest(t, app, socialApp, fedApp, socialCb, fedCb, d, httpClient, p)
|
||||
@ -2198,7 +2397,6 @@ func TestPostInbox_Accept_DoesNothingIfNotAcceptingFollow(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Test follower OrderedCollection & IRI.
|
||||
func TestPostInbox_Accept_AcceptFollowAddsToFollowersIfOwned(t *testing.T) {
|
||||
app, socialApp, fedApp, socialCb, fedCb, d, httpClient, p := NewPubberTest(t)
|
||||
PreparePostInboxTest(t, app, socialApp, fedApp, socialCb, fedCb, d, httpClient, p)
|
||||
@ -2260,6 +2458,94 @@ func TestPostInbox_Accept_AcceptFollowAddsToFollowersIfOwned(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestPostInbox_Accept_AcceptFollowAddsToFollowersOrderedCollection(t *testing.T) {
|
||||
app, socialApp, fedApp, socialCb, fedCb, d, httpClient, p := NewPubberTest(t)
|
||||
PreparePostInboxTest(t, app, socialApp, fedApp, socialCb, fedCb, d, httpClient, p)
|
||||
resp := httptest.NewRecorder()
|
||||
req := ActivityPubRequest(httptest.NewRequest("POST", testInboxURI, bytes.NewBuffer(MustSerialize(testAcceptFollow))))
|
||||
app.owns = func(c context.Context, id url.URL) bool {
|
||||
return true
|
||||
}
|
||||
app.get = func(c context.Context, id url.URL) (PubObject, error) {
|
||||
sallyActor := &vocab.Person{}
|
||||
sallyActor.SetInboxAnyURI(*sallyIRIInbox)
|
||||
sallyActor.SetId(*sallyIRI)
|
||||
sallyActor.SetFollowingOrderedCollection(&vocab.OrderedCollection{})
|
||||
return sallyActor, nil
|
||||
}
|
||||
gotSet := 0
|
||||
var setObject PubObject
|
||||
app.set = func(c context.Context, o PubObject) error {
|
||||
gotSet++
|
||||
if gotSet == 1 {
|
||||
setObject = o
|
||||
}
|
||||
return nil
|
||||
}
|
||||
fedCb.accept = func(c context.Context, s *streams.Accept) error {
|
||||
return nil
|
||||
}
|
||||
expectedFollowing := &vocab.OrderedCollection{}
|
||||
expectedFollowing.AddOrderedItemsObject(samActor)
|
||||
expectedActor := &vocab.Person{}
|
||||
expectedActor.SetInboxAnyURI(*sallyIRIInbox)
|
||||
expectedActor.SetId(*sallyIRI)
|
||||
expectedActor.SetFollowingOrderedCollection(expectedFollowing)
|
||||
handled, err := p.PostInbox(context.Background(), resp, req)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
} else if !handled {
|
||||
t.Fatalf("expected handled, got !handled")
|
||||
} else if err := PubObjectEquals(setObject, expectedActor); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPostInbox_Accept_AcceptFollowAddsToFollowersIRI(t *testing.T) {
|
||||
app, socialApp, fedApp, socialCb, fedCb, d, httpClient, p := NewPubberTest(t)
|
||||
PreparePostInboxTest(t, app, socialApp, fedApp, socialCb, fedCb, d, httpClient, p)
|
||||
resp := httptest.NewRecorder()
|
||||
req := ActivityPubRequest(httptest.NewRequest("POST", testInboxURI, bytes.NewBuffer(MustSerialize(testAcceptFollow))))
|
||||
app.owns = func(c context.Context, id url.URL) bool {
|
||||
return true
|
||||
}
|
||||
app.get = func(c context.Context, id url.URL) (PubObject, error) {
|
||||
if id == *sallyIRI {
|
||||
sallyActor := &vocab.Person{}
|
||||
sallyActor.SetInboxAnyURI(*sallyIRIInbox)
|
||||
sallyActor.SetId(*sallyIRI)
|
||||
sallyActor.SetFollowingAnyURI(*sallyFollowingIRI)
|
||||
return sallyActor, nil
|
||||
} else if id == *sallyFollowingIRI {
|
||||
return &vocab.OrderedCollection{}, nil
|
||||
}
|
||||
t.Fatalf("Unexpected get(%s)", (&id).String())
|
||||
return nil, nil
|
||||
}
|
||||
gotSet := 0
|
||||
var setObject PubObject
|
||||
app.set = func(c context.Context, o PubObject) error {
|
||||
gotSet++
|
||||
if gotSet == 1 {
|
||||
setObject = o
|
||||
}
|
||||
return nil
|
||||
}
|
||||
fedCb.accept = func(c context.Context, s *streams.Accept) error {
|
||||
return nil
|
||||
}
|
||||
expectedFollowing := &vocab.OrderedCollection{}
|
||||
expectedFollowing.AddOrderedItemsObject(samActor)
|
||||
handled, err := p.PostInbox(context.Background(), resp, req)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
} else if !handled {
|
||||
t.Fatalf("expected handled, got !handled")
|
||||
} else if err := PubObjectEquals(setObject, expectedFollowing); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPostInbox_Accept_DoesNothingIfNotOwned(t *testing.T) {
|
||||
app, socialApp, fedApp, socialCb, fedCb, d, httpClient, p := NewPubberTest(t)
|
||||
PreparePostInboxTest(t, app, socialApp, fedApp, socialCb, fedCb, d, httpClient, p)
|
||||
@ -2717,7 +3003,6 @@ func TestPostInbox_Remove_CallsCallback(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Test likes OrderedCollection & IRI.
|
||||
func TestPostInbox_Like_AddsToLikeCollection(t *testing.T) {
|
||||
app, socialApp, fedApp, socialCb, fedCb, d, httpClient, p := NewPubberTest(t)
|
||||
PreparePostInboxTest(t, app, socialApp, fedApp, socialCb, fedCb, d, httpClient, p)
|
||||
@ -2781,6 +3066,97 @@ func TestPostInbox_Like_AddsToLikeCollection(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestPostInbox_Like_AddsToLikeOrderedCollection(t *testing.T) {
|
||||
app, socialApp, fedApp, socialCb, fedCb, d, httpClient, p := NewPubberTest(t)
|
||||
PreparePostInboxTest(t, app, socialApp, fedApp, socialCb, fedCb, d, httpClient, p)
|
||||
resp := httptest.NewRecorder()
|
||||
req := ActivityPubRequest(httptest.NewRequest("POST", testInboxURI, bytes.NewBuffer(MustSerialize(testLikeNote))))
|
||||
app.owns = func(c context.Context, id url.URL) bool {
|
||||
return true
|
||||
}
|
||||
app.get = func(c context.Context, id url.URL) (PubObject, error) {
|
||||
v := &vocab.Note{}
|
||||
v.SetId(*noteIRI)
|
||||
v.AddNameString(noteName)
|
||||
v.AddContentString("This is a simple note")
|
||||
v.SetLikesOrderedCollection(&vocab.OrderedCollection{})
|
||||
return v, nil
|
||||
}
|
||||
gotSet := 0
|
||||
var gotSetObject PubObject
|
||||
app.set = func(c context.Context, target PubObject) error {
|
||||
gotSet++
|
||||
if gotSet == 1 {
|
||||
gotSetObject = target
|
||||
}
|
||||
return nil
|
||||
}
|
||||
fedCb.like = func(c context.Context, s *streams.Like) error {
|
||||
return nil
|
||||
}
|
||||
handled, err := p.PostInbox(context.Background(), resp, req)
|
||||
expected := &vocab.OrderedCollection{}
|
||||
expected.AddOrderedItemsObject(sallyActor)
|
||||
expectedNote := &vocab.Note{}
|
||||
expectedNote.SetId(*noteIRI)
|
||||
expectedNote.AddNameString(noteName)
|
||||
expectedNote.AddContentString("This is a simple note")
|
||||
expectedNote.SetLikesOrderedCollection(expected)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
} else if !handled {
|
||||
t.Fatalf("expected handled, got !handled")
|
||||
} else if err := PubObjectEquals(gotSetObject, expectedNote); err != nil {
|
||||
t.Fatalf("unexpected callback object: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPostInbox_Like_AddsToLikeIRI(t *testing.T) {
|
||||
app, socialApp, fedApp, socialCb, fedCb, d, httpClient, p := NewPubberTest(t)
|
||||
PreparePostInboxTest(t, app, socialApp, fedApp, socialCb, fedCb, d, httpClient, p)
|
||||
resp := httptest.NewRecorder()
|
||||
req := ActivityPubRequest(httptest.NewRequest("POST", testInboxURI, bytes.NewBuffer(MustSerialize(testLikeNote))))
|
||||
app.owns = func(c context.Context, id url.URL) bool {
|
||||
return true
|
||||
}
|
||||
app.get = func(c context.Context, id url.URL) (PubObject, error) {
|
||||
if id == *noteIRI {
|
||||
v := &vocab.Note{}
|
||||
v.SetId(*noteIRI)
|
||||
v.AddNameString(noteName)
|
||||
v.AddContentString("This is a simple note")
|
||||
v.SetLikesAnyURI(*testNewIRI)
|
||||
return v, nil
|
||||
} else if id == *testNewIRI {
|
||||
return &vocab.OrderedCollection{}, nil
|
||||
}
|
||||
t.Fatalf("unexpected get(%s)", &id)
|
||||
return nil, nil
|
||||
}
|
||||
gotSet := 0
|
||||
var gotSetObject PubObject
|
||||
app.set = func(c context.Context, target PubObject) error {
|
||||
gotSet++
|
||||
if gotSet == 1 {
|
||||
gotSetObject = target
|
||||
}
|
||||
return nil
|
||||
}
|
||||
fedCb.like = func(c context.Context, s *streams.Like) error {
|
||||
return nil
|
||||
}
|
||||
handled, err := p.PostInbox(context.Background(), resp, req)
|
||||
expected := &vocab.OrderedCollection{}
|
||||
expected.AddOrderedItemsObject(sallyActor)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
} else if !handled {
|
||||
t.Fatalf("expected handled, got !handled")
|
||||
} else if err := PubObjectEquals(gotSetObject, expected); err != nil {
|
||||
t.Fatalf("unexpected callback object: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPostInbox_Like_CallsCallback(t *testing.T) {
|
||||
app, socialApp, fedApp, socialCb, fedCb, d, httpClient, p := NewPubberTest(t)
|
||||
PreparePostInboxTest(t, app, socialApp, fedApp, socialCb, fedCb, d, httpClient, p)
|
||||
@ -4718,12 +5094,26 @@ func TestPostOutbox_Block_IsNotDelivered(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestPostOutbox_DoesNotDeliverNondeliverable(t *testing.T) {
|
||||
// TODO: Implement
|
||||
}
|
||||
|
||||
func TestPostOutbox_SetsLocationHeader(t *testing.T) {
|
||||
// TODO: Implement
|
||||
app, socialApp, fedApp, socialCb, fedCb, d, httpClient, p := NewPubberTest(t)
|
||||
PreparePostOutboxTest(t, app, socialApp, fedApp, socialCb, fedCb, d, httpClient, p)
|
||||
resp := httptest.NewRecorder()
|
||||
req := ActivityPubRequest(httptest.NewRequest("POST", testOutboxURI, bytes.NewBuffer(MustSerialize(testCreateNote))))
|
||||
socialCb.create = func(c context.Context, s *streams.Create) error {
|
||||
return nil
|
||||
}
|
||||
handled, err := p.PostOutbox(context.Background(), resp, req)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
} else if !handled {
|
||||
t.Fatalf("expected handled, got !handled")
|
||||
} else if loc, ok := resp.HeaderMap["Location"]; !ok {
|
||||
t.Fatalf("expected Location header, got none")
|
||||
} else if len(loc) != 1 {
|
||||
t.Fatalf("expected Location header to have length 1, got %d", len(loc))
|
||||
} else if loc[0] != testNewIRIString {
|
||||
t.Fatalf("expected %s, got %s", testNewIRIString, loc[0])
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetOutbox_RejectNonActivityPub(t *testing.T) {
|
||||
@ -4739,7 +5129,6 @@ func TestGetOutbox_RejectNonActivityPub(t *testing.T) {
|
||||
} else if handled {
|
||||
t.Fatalf("expected !handled, got handled")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestGetOutbox_SetsContentTypeHeader(t *testing.T) {
|
||||
|
@ -88,8 +88,9 @@ type FederateApp interface {
|
||||
// the given target collection.
|
||||
CanRemove(c context.Context, obj vocab.ObjectType, target vocab.ObjectType) bool
|
||||
// OnFollow determines whether to take any automatic reactions in
|
||||
// response to this follow. Note that this method must check ownership
|
||||
// to automatically Accept the Follow.
|
||||
// response to this follow. Note that if this application does not own
|
||||
// an object on the activity, then the 'AutomaticAccept' and
|
||||
// 'AutomaticReject' results will behave as if they were 'DoNothing'.
|
||||
OnFollow(c context.Context, s *streams.Follow) FollowResponse
|
||||
// Unblocked should return an error if the provided actor ids are not
|
||||
// able to interact with this particular end user due to being blocked
|
||||
|
@ -1187,7 +1187,9 @@ func toTombstone(obj vocab.ObjectType, id url.URL, now time.Time) vocab.Tombston
|
||||
return tomb
|
||||
}
|
||||
|
||||
func (f *federator) addAllObjectsToActorCollection(ctx context.Context, getter func(actor vocab.ObjectType, lc *vocab.CollectionType, loc *vocab.OrderedCollectionType) error, c vocab.ActivityType) error {
|
||||
type getActorCollectionFn func(actor vocab.ObjectType, lc *vocab.CollectionType, loc *vocab.OrderedCollectionType) (isIRI bool, e error)
|
||||
|
||||
func (f *federator) addAllObjectsToActorCollection(ctx context.Context, getter getActorCollectionFn, c vocab.ActivityType) error {
|
||||
for i := 0; i < c.ActorLen(); i++ {
|
||||
var iri url.URL
|
||||
if c.IsActorObject(i) {
|
||||
@ -1221,7 +1223,8 @@ func (f *federator) addAllObjectsToActorCollection(ctx context.Context, getter f
|
||||
}
|
||||
var lc vocab.CollectionType
|
||||
var loc vocab.OrderedCollectionType
|
||||
if err := getter(actor, &lc, &loc); err != nil {
|
||||
isIRI := false
|
||||
if isIRI, err = getter(actor, &lc, &loc); err != nil {
|
||||
return err
|
||||
}
|
||||
for i := 0; i < c.ObjectLen(); i++ {
|
||||
@ -1239,20 +1242,32 @@ func (f *federator) addAllObjectsToActorCollection(ctx context.Context, getter f
|
||||
}
|
||||
}
|
||||
}
|
||||
if err := f.App.Set(ctx, actor); err != nil {
|
||||
if isIRI {
|
||||
if lc != nil {
|
||||
err = f.App.Set(ctx, lc)
|
||||
} else if loc != nil {
|
||||
err = f.App.Set(ctx, loc)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else if err := f.App.Set(ctx, actor); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *federator) addAllActorsToObjectCollection(ctx context.Context, getter func(object vocab.ObjectType, lc *vocab.CollectionType, loc *vocab.OrderedCollectionType) error, c vocab.ActivityType) error {
|
||||
type getObjectCollectionFn func(object vocab.ObjectType, lc *vocab.CollectionType, loc *vocab.OrderedCollectionType) (isIRI bool, e error)
|
||||
|
||||
func (f *federator) addAllActorsToObjectCollection(ctx context.Context, getter getObjectCollectionFn, c vocab.ActivityType) (bool, error) {
|
||||
ownsAny := false
|
||||
for i := 0; i < c.ObjectLen(); i++ {
|
||||
var iri url.URL
|
||||
if c.IsObject(i) {
|
||||
obj := c.GetObject(i)
|
||||
if !obj.HasId() {
|
||||
return fmt.Errorf("object does not have id")
|
||||
return ownsAny, fmt.Errorf("object does not have id")
|
||||
}
|
||||
iri = obj.GetId()
|
||||
} else if c.IsObjectIRI(i) {
|
||||
@ -1261,21 +1276,23 @@ func (f *federator) addAllActorsToObjectCollection(ctx context.Context, getter f
|
||||
if !f.App.Owns(ctx, iri) {
|
||||
continue
|
||||
}
|
||||
ownsAny = true
|
||||
var object vocab.ObjectType
|
||||
pObj, err := f.App.Get(ctx, iri)
|
||||
if err != nil {
|
||||
return err
|
||||
return ownsAny, err
|
||||
}
|
||||
ok := false
|
||||
object, ok = pObj.(vocab.ObjectType)
|
||||
if !ok {
|
||||
// TODO: Handle links, too
|
||||
return fmt.Errorf("object is not vocab.ObjectType")
|
||||
return ownsAny, fmt.Errorf("object is not vocab.ObjectType")
|
||||
}
|
||||
var lc vocab.CollectionType
|
||||
var loc vocab.OrderedCollectionType
|
||||
if err := getter(object, &lc, &loc); err != nil {
|
||||
return err
|
||||
isIRI := false
|
||||
if isIRI, err = getter(object, &lc, &loc); err != nil {
|
||||
return ownsAny, err
|
||||
}
|
||||
for i := 0; i < c.ActorLen(); i++ {
|
||||
if c.IsActorIRI(i) {
|
||||
@ -1298,11 +1315,36 @@ func (f *federator) addAllActorsToObjectCollection(ctx context.Context, getter f
|
||||
}
|
||||
}
|
||||
}
|
||||
if err := f.App.Set(ctx, object); err != nil {
|
||||
return err
|
||||
if isIRI {
|
||||
if lc != nil {
|
||||
err = f.App.Set(ctx, lc)
|
||||
} else if loc != nil {
|
||||
err = f.App.Set(ctx, loc)
|
||||
}
|
||||
if err != nil {
|
||||
return ownsAny, err
|
||||
}
|
||||
} else if err := f.App.Set(ctx, object); err != nil {
|
||||
return ownsAny, err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
return ownsAny, nil
|
||||
}
|
||||
|
||||
func (f *federator) ownsAnyObjects(c context.Context, a vocab.ActivityType) (bool, error) {
|
||||
var iris []url.URL
|
||||
for i := 0; i < a.ObjectLen(); i++ {
|
||||
if a.IsObject(i) {
|
||||
obj := a.GetObject(i)
|
||||
if !obj.HasId() {
|
||||
return false, fmt.Errorf("object missing id")
|
||||
}
|
||||
iris = append(iris, obj.GetId())
|
||||
} else if a.IsObjectIRI(i) {
|
||||
iris = append(iris, a.GetObjectIRI(i))
|
||||
}
|
||||
}
|
||||
return f.ownsAnyIRIs(c, iris), nil
|
||||
}
|
||||
|
||||
func (f *federator) addToOutbox(c context.Context, r *http.Request, m map[string]interface{}) error {
|
||||
|
読み込み中…
新しいイシューから参照
ユーザーをブロックする