summaryrefslogtreecommitdiff
path: root/internal/federation/federatingdb
diff options
context:
space:
mode:
authorLibravatar tobi <31960611+tsmethurst@users.noreply.github.com>2021-10-10 12:39:25 +0200
committerLibravatar GitHub <noreply@github.com>2021-10-10 12:39:25 +0200
commit367bdca25093ee76b36506d8a5e6733b0aa2e2bb (patch)
tree37b1b82ae6e9fad7e6d95b8abbb58bdb42049707 /internal/federation/federatingdb
parentDerive visibility fixes (#271) (diff)
downloadgotosocial-367bdca25093ee76b36506d8a5e6733b0aa2e2bb.tar.xz
Handle forwarded messages (#273)
* correct path of foss_satan * add APIri and notes * test create forward note * rename target => receiving account * split up create into separate funcs * update extractFromCtx * tidy up from federator processing * foss satan => http not https * check if status in db * mock dereference of status from IRI * add forward message deref test * update test with activities * add remote_account_2 to test rig
Diffstat (limited to 'internal/federation/federatingdb')
-rw-r--r--internal/federation/federatingdb/accept.go17
-rw-r--r--internal/federation/federatingdb/announce.go13
-rw-r--r--internal/federation/federatingdb/create.go337
-rw-r--r--internal/federation/federatingdb/create_test.go91
-rw-r--r--internal/federation/federatingdb/delete.go13
-rw-r--r--internal/federation/federatingdb/federatingdb_test.go14
-rw-r--r--internal/federation/federatingdb/undo.go13
-rw-r--r--internal/federation/federatingdb/update.go11
-rw-r--r--internal/federation/federatingdb/util.go29
9 files changed, 372 insertions, 166 deletions
diff --git a/internal/federation/federatingdb/accept.go b/internal/federation/federatingdb/accept.go
index 7ecf41ee4..0d2d3a270 100644
--- a/internal/federation/federatingdb/accept.go
+++ b/internal/federation/federatingdb/accept.go
@@ -48,12 +48,9 @@ func (f *federatingDB) Accept(ctx context.Context, accept vocab.ActivityStreamsA
l.Debug("entering Accept")
}
- targetAcct, fromFederatorChan, err := extractFromCtx(ctx)
- if err != nil {
- return err
- }
- if targetAcct == nil || fromFederatorChan == nil {
- // If the target account or federator channel wasn't set on the context, that means this request didn't pass
+ receivingAccount, _, fromFederatorChan := extractFromCtx(ctx)
+ if receivingAccount == nil || fromFederatorChan == nil {
+ // If the receiving account or federator channel wasn't set on the context, that means this request didn't pass
// through the API, but came from inside GtS as the result of another activity on this instance. That being so,
// we can safely just ignore this activity, since we know we've already processed it elsewhere.
return nil
@@ -77,7 +74,7 @@ func (f *federatingDB) Accept(ctx context.Context, accept vocab.ActivityStreamsA
}
// make sure the addressee of the original follow is the same as whatever inbox this landed in
- if gtsFollowRequest.AccountID != targetAcct.ID {
+ if gtsFollowRequest.AccountID != receivingAccount.ID {
return errors.New("ACCEPT: follow object account and inbox account were not the same")
}
follow, err := f.db.AcceptFollowRequest(ctx, gtsFollowRequest.AccountID, gtsFollowRequest.TargetAccountID)
@@ -89,7 +86,7 @@ func (f *federatingDB) Accept(ctx context.Context, accept vocab.ActivityStreamsA
APObjectType: ap.ActivityFollow,
APActivityType: ap.ActivityAccept,
GTSModel: follow,
- ReceivingAccount: targetAcct,
+ ReceivingAccount: receivingAccount,
}
return nil
@@ -114,7 +111,7 @@ func (f *federatingDB) Accept(ctx context.Context, accept vocab.ActivityStreamsA
return fmt.Errorf("ACCEPT: error converting asfollow to gtsfollow: %s", err)
}
// make sure the addressee of the original follow is the same as whatever inbox this landed in
- if gtsFollow.AccountID != targetAcct.ID {
+ if gtsFollow.AccountID != receivingAccount.ID {
return errors.New("ACCEPT: follow object account and inbox account were not the same")
}
follow, err := f.db.AcceptFollowRequest(ctx, gtsFollow.AccountID, gtsFollow.TargetAccountID)
@@ -126,7 +123,7 @@ func (f *federatingDB) Accept(ctx context.Context, accept vocab.ActivityStreamsA
APObjectType: ap.ActivityFollow,
APActivityType: ap.ActivityAccept,
GTSModel: follow,
- ReceivingAccount: targetAcct,
+ ReceivingAccount: receivingAccount,
}
return nil
diff --git a/internal/federation/federatingdb/announce.go b/internal/federation/federatingdb/announce.go
index 9a03ede92..49ec84509 100644
--- a/internal/federation/federatingdb/announce.go
+++ b/internal/federation/federatingdb/announce.go
@@ -44,12 +44,9 @@ func (f *federatingDB) Announce(ctx context.Context, announce vocab.ActivityStre
l.Debug("entering Announce")
}
- targetAcct, fromFederatorChan, err := extractFromCtx(ctx)
- if err != nil {
- return err
- }
- if targetAcct == nil || fromFederatorChan == nil {
- // If the target account or federator channel wasn't set on the context, that means this request didn't pass
+ receivingAccount, _, fromFederatorChan := extractFromCtx(ctx)
+ if receivingAccount == nil || fromFederatorChan == nil {
+ // If the receiving account or federator channel wasn't set on the context, that means this request didn't pass
// through the API, but came from inside GtS as the result of another activity on this instance. That being so,
// we can safely just ignore this activity, since we know we've already processed it elsewhere.
return nil
@@ -57,7 +54,7 @@ func (f *federatingDB) Announce(ctx context.Context, announce vocab.ActivityStre
boost, isNew, err := f.typeConverter.ASAnnounceToStatus(ctx, announce)
if err != nil {
- return fmt.Errorf("ANNOUNCE: error converting announce to boost: %s", err)
+ return fmt.Errorf("Announce: error converting announce to boost: %s", err)
}
if !isNew {
@@ -70,7 +67,7 @@ func (f *federatingDB) Announce(ctx context.Context, announce vocab.ActivityStre
APObjectType: ap.ActivityAnnounce,
APActivityType: ap.ActivityCreate,
GTSModel: boost,
- ReceivingAccount: targetAcct,
+ ReceivingAccount: receivingAccount,
}
return nil
diff --git a/internal/federation/federatingdb/create.go b/internal/federation/federatingdb/create.go
index 2a31108f2..4262dfcb4 100644
--- a/internal/federation/federatingdb/create.go
+++ b/internal/federation/federatingdb/create.go
@@ -22,11 +22,13 @@ import (
"context"
"errors"
"fmt"
+ "strings"
"github.com/go-fed/activity/streams/vocab"
"github.com/sirupsen/logrus"
"github.com/superseriousbusiness/gotosocial/internal/ap"
"github.com/superseriousbusiness/gotosocial/internal/db"
+ "github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
"github.com/superseriousbusiness/gotosocial/internal/id"
"github.com/superseriousbusiness/gotosocial/internal/messages"
)
@@ -59,144 +61,261 @@ func (f *federatingDB) Create(ctx context.Context, asType vocab.Type) error {
l.Debug("entering Create")
}
- targetAcct, fromFederatorChan, err := extractFromCtx(ctx)
- if err != nil {
- return err
- }
- if targetAcct == nil || fromFederatorChan == nil {
- // If the target account or federator channel wasn't set on the context, that means this request didn't pass
+ receivingAccount, requestingAccount, fromFederatorChan := extractFromCtx(ctx)
+ if receivingAccount == nil || fromFederatorChan == nil {
+ // If the receiving account or federator channel wasn't set on the context, that means this request didn't pass
// through the API, but came from inside GtS as the result of another activity on this instance. That being so,
// we can safely just ignore this activity, since we know we've already processed it elsewhere.
return nil
}
switch asType.GetTypeName() {
+ case ap.ActivityBlock:
+ // BLOCK SOMETHING
+ return f.activityBlock(ctx, asType, receivingAccount, requestingAccount, fromFederatorChan)
case ap.ActivityCreate:
// CREATE SOMETHING
- create, ok := asType.(vocab.ActivityStreamsCreate)
- if !ok {
- return errors.New("CREATE: could not convert type to create")
- }
- object := create.GetActivityStreamsObject()
- for objectIter := object.Begin(); objectIter != object.End(); objectIter = objectIter.Next() {
- switch objectIter.GetType().GetTypeName() {
- case ap.ObjectNote:
- // CREATE A NOTE
- note := objectIter.GetActivityStreamsNote()
- status, err := f.typeConverter.ASStatusToStatus(ctx, note)
- if err != nil {
- return fmt.Errorf("CREATE: error converting note to status: %s", err)
- }
-
- // id the status based on the time it was created
- statusID, err := id.NewULIDFromTime(status.CreatedAt)
- if err != nil {
- return err
- }
- status.ID = statusID
-
- if err := f.db.PutStatus(ctx, status); err != nil {
- if err == db.ErrAlreadyExists {
- // the status already exists in the database, which means we've already handled everything else,
- // so we can just return nil here and be done with it.
- return nil
- }
- // an actual error has happened
- return fmt.Errorf("CREATE: database error inserting status: %s", err)
- }
-
- fromFederatorChan <- messages.FromFederator{
- APObjectType: ap.ObjectNote,
- APActivityType: ap.ActivityCreate,
- GTSModel: status,
- ReceivingAccount: targetAcct,
- }
- }
- }
+ return f.activityCreate(ctx, asType, receivingAccount, requestingAccount, fromFederatorChan)
case ap.ActivityFollow:
// FOLLOW SOMETHING
- follow, ok := asType.(vocab.ActivityStreamsFollow)
- if !ok {
- return errors.New("CREATE: could not convert type to follow")
- }
+ return f.activityFollow(ctx, asType, receivingAccount, requestingAccount, fromFederatorChan)
+ case ap.ActivityLike:
+ // LIKE SOMETHING
+ return f.activityLike(ctx, asType, receivingAccount, requestingAccount, fromFederatorChan)
+ }
+ return nil
+}
- followRequest, err := f.typeConverter.ASFollowToFollowRequest(ctx, follow)
- if err != nil {
- return fmt.Errorf("CREATE: could not convert Follow to follow request: %s", err)
- }
+/*
+ BLOCK HANDLERS
+*/
- newID, err := id.NewULID()
- if err != nil {
- return err
- }
- followRequest.ID = newID
+func (f *federatingDB) activityBlock(ctx context.Context, asType vocab.Type, receiving *gtsmodel.Account, requestingAccount *gtsmodel.Account, fromFederatorChan chan messages.FromFederator) error {
+ blockable, ok := asType.(vocab.ActivityStreamsBlock)
+ if !ok {
+ return errors.New("activityBlock: could not convert type to block")
+ }
- if err := f.db.Put(ctx, followRequest); err != nil {
- return fmt.Errorf("CREATE: database error inserting follow request: %s", err)
- }
+ block, err := f.typeConverter.ASBlockToBlock(ctx, blockable)
+ if err != nil {
+ return fmt.Errorf("activityBlock: could not convert Block to gts model block")
+ }
- fromFederatorChan <- messages.FromFederator{
- APObjectType: ap.ActivityFollow,
- APActivityType: ap.ActivityCreate,
- GTSModel: followRequest,
- ReceivingAccount: targetAcct,
- }
- case ap.ActivityLike:
- // LIKE SOMETHING
- like, ok := asType.(vocab.ActivityStreamsLike)
- if !ok {
- return errors.New("CREATE: could not convert type to like")
- }
+ newID, err := id.NewULID()
+ if err != nil {
+ return err
+ }
+ block.ID = newID
- fave, err := f.typeConverter.ASLikeToFave(ctx, like)
- if err != nil {
- return fmt.Errorf("CREATE: could not convert Like to fave: %s", err)
+ if err := f.db.Put(ctx, block); err != nil {
+ return fmt.Errorf("activityBlock: database error inserting block: %s", err)
+ }
+
+ fromFederatorChan <- messages.FromFederator{
+ APObjectType: ap.ActivityBlock,
+ APActivityType: ap.ActivityCreate,
+ GTSModel: block,
+ ReceivingAccount: receiving,
+ }
+ return nil
+}
+
+/*
+ CREATE HANDLERS
+*/
+
+func (f *federatingDB) activityCreate(ctx context.Context, asType vocab.Type, receivingAccount *gtsmodel.Account, requestingAccount *gtsmodel.Account, fromFederatorChan chan messages.FromFederator) error {
+ create, ok := asType.(vocab.ActivityStreamsCreate)
+ if !ok {
+ return errors.New("activityCreate: could not convert type to create")
+ }
+
+ // create should have an object
+ object := create.GetActivityStreamsObject()
+ if object == nil {
+ return errors.New("Create had no Object")
+ }
+
+ errs := []string{}
+ // iterate through the object(s) to see what we're meant to be creating
+ for objectIter := object.Begin(); objectIter != object.End(); objectIter = objectIter.Next() {
+ asObjectType := objectIter.GetType()
+ if asObjectType == nil {
+ // currently we can't do anything with just a Create of something that's not an Object with a type
+ // TODO: process a Create with an Object that's just a URI or something
+ errs = append(errs, "object of Create was not a Type")
+ continue
}
- newID, err := id.NewULID()
- if err != nil {
- return err
+ // we have a type -- what is it?
+ asObjectTypeName := asObjectType.GetTypeName()
+ switch asObjectTypeName {
+ case ap.ObjectNote:
+ // CREATE A NOTE
+ if err := f.createNote(ctx, objectIter.GetActivityStreamsNote(), receivingAccount, requestingAccount, fromFederatorChan); err != nil {
+ errs = append(errs, err.Error())
+ }
+ default:
+ errs = append(errs, fmt.Sprintf("received an object on a Create that we couldn't handle: %s", asObjectType.GetTypeName()))
}
- fave.ID = newID
+ }
+
+ if len(errs) != 0 {
+ return fmt.Errorf("activityCreate: one or more errors while processing activity: %s", strings.Join(errs, "; "))
+ }
- if err := f.db.Put(ctx, fave); err != nil {
- return fmt.Errorf("CREATE: database error inserting fave: %s", err)
+ return nil
+}
+
+// createNote handles a Create activity with a Note type.
+func (f *federatingDB) createNote(ctx context.Context, note vocab.ActivityStreamsNote, receivingAccount *gtsmodel.Account, requestingAccount *gtsmodel.Account, fromFederatorChan chan messages.FromFederator) error {
+ l := f.log.WithFields(logrus.Fields{
+ "func": "createNote",
+ "receivingAccount": receivingAccount.URI,
+ "requestingAccount": requestingAccount.URI,
+ })
+
+ // Check if we have a forward.
+ // In other words, was the note posted to our inbox by at least one actor who actually created the note, or are they just forwarding it?
+ forward := true
+
+ // note should have an attributedTo
+ noteAttributedTo := note.GetActivityStreamsAttributedTo()
+ if noteAttributedTo == nil {
+ return errors.New("createNote: note had no attributedTo")
+ }
+
+ // compare the attributedTo(s) with the actor who posted this to our inbox
+ for attributedToIter := noteAttributedTo.Begin(); attributedToIter != noteAttributedTo.End(); attributedToIter = attributedToIter.Next() {
+ if !attributedToIter.IsIRI() {
+ continue
+ }
+ iri := attributedToIter.GetIRI()
+ if requestingAccount.URI == iri.String() {
+ // at least one creator of the note, and the actor who posted the note to our inbox, are the same, so it's not a forward
+ forward = false
}
+ }
+ // If we do have a forward, we should ignore the content for now and just dereference based on the URL/ID of the note instead, to get the note straight from the horse's mouth
+ if forward {
+ l.Trace("note is a forward")
+ id := note.GetJSONLDId()
+ if !id.IsIRI() {
+ // if the note id isn't an IRI, there's nothing we can do here
+ return nil
+ }
+ // pass the note iri into the processor and have it do the dereferencing instead of doing it here
fromFederatorChan <- messages.FromFederator{
- APObjectType: ap.ActivityLike,
+ APObjectType: ap.ObjectNote,
APActivityType: ap.ActivityCreate,
- GTSModel: fave,
- ReceivingAccount: targetAcct,
- }
- case ap.ActivityBlock:
- // BLOCK SOMETHING
- blockable, ok := asType.(vocab.ActivityStreamsBlock)
- if !ok {
- return errors.New("CREATE: could not convert type to block")
+ APIri: id.GetIRI(),
+ GTSModel: nil,
+ ReceivingAccount: receivingAccount,
}
+ return nil
+ }
- block, err := f.typeConverter.ASBlockToBlock(ctx, blockable)
- if err != nil {
- return fmt.Errorf("CREATE: could not convert Block to gts model block")
- }
+ // if we reach this point, we know it's not a forwarded status, so proceed with processing it as normal
- newID, err := id.NewULID()
- if err != nil {
- return err
- }
- block.ID = newID
+ status, err := f.typeConverter.ASStatusToStatus(ctx, note)
+ if err != nil {
+ return fmt.Errorf("createNote: error converting note to status: %s", err)
+ }
- if err := f.db.Put(ctx, block); err != nil {
- return fmt.Errorf("CREATE: database error inserting block: %s", err)
- }
+ // id the status based on the time it was created
+ statusID, err := id.NewULIDFromTime(status.CreatedAt)
+ if err != nil {
+ return err
+ }
+ status.ID = statusID
- fromFederatorChan <- messages.FromFederator{
- APObjectType: ap.ActivityBlock,
- APActivityType: ap.ActivityCreate,
- GTSModel: block,
- ReceivingAccount: targetAcct,
+ if err := f.db.PutStatus(ctx, status); err != nil {
+ if err == db.ErrAlreadyExists {
+ // the status already exists in the database, which means we've already handled everything else,
+ // so we can just return nil here and be done with it.
+ return nil
}
+ // an actual error has happened
+ return fmt.Errorf("createNote: database error inserting status: %s", err)
}
+
+ fromFederatorChan <- messages.FromFederator{
+ APObjectType: ap.ObjectNote,
+ APActivityType: ap.ActivityCreate,
+ GTSModel: status,
+ ReceivingAccount: receivingAccount,
+ }
+
+ return nil
+}
+
+/*
+ FOLLOW HANDLERS
+*/
+
+func (f *federatingDB) activityFollow(ctx context.Context, asType vocab.Type, receivingAccount *gtsmodel.Account, requestingAccount *gtsmodel.Account, fromFederatorChan chan messages.FromFederator) error {
+ follow, ok := asType.(vocab.ActivityStreamsFollow)
+ if !ok {
+ return errors.New("activityFollow: could not convert type to follow")
+ }
+
+ followRequest, err := f.typeConverter.ASFollowToFollowRequest(ctx, follow)
+ if err != nil {
+ return fmt.Errorf("activityFollow: could not convert Follow to follow request: %s", err)
+ }
+
+ newID, err := id.NewULID()
+ if err != nil {
+ return err
+ }
+ followRequest.ID = newID
+
+ if err := f.db.Put(ctx, followRequest); err != nil {
+ return fmt.Errorf("activityFollow: database error inserting follow request: %s", err)
+ }
+
+ fromFederatorChan <- messages.FromFederator{
+ APObjectType: ap.ActivityFollow,
+ APActivityType: ap.ActivityCreate,
+ GTSModel: followRequest,
+ ReceivingAccount: receivingAccount,
+ }
+
+ return nil
+}
+
+/*
+ LIKE HANDLERS
+*/
+
+func (f *federatingDB) activityLike(ctx context.Context, asType vocab.Type, receivingAccount *gtsmodel.Account, requestingAccount *gtsmodel.Account, fromFederatorChan chan messages.FromFederator) error {
+ like, ok := asType.(vocab.ActivityStreamsLike)
+ if !ok {
+ return errors.New("activityLike: could not convert type to like")
+ }
+
+ fave, err := f.typeConverter.ASLikeToFave(ctx, like)
+ if err != nil {
+ return fmt.Errorf("activityLike: could not convert Like to fave: %s", err)
+ }
+
+ newID, err := id.NewULID()
+ if err != nil {
+ return err
+ }
+ fave.ID = newID
+
+ if err := f.db.Put(ctx, fave); err != nil {
+ return fmt.Errorf("activityLike: database error inserting fave: %s", err)
+ }
+
+ fromFederatorChan <- messages.FromFederator{
+ APObjectType: ap.ActivityLike,
+ APActivityType: ap.ActivityCreate,
+ GTSModel: fave,
+ ReceivingAccount: receivingAccount,
+ }
+
return nil
}
diff --git a/internal/federation/federatingdb/create_test.go b/internal/federation/federatingdb/create_test.go
new file mode 100644
index 000000000..ee2194f9e
--- /dev/null
+++ b/internal/federation/federatingdb/create_test.go
@@ -0,0 +1,91 @@
+/*
+ GoToSocial
+ Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+package federatingdb_test
+
+import (
+ "context"
+ "testing"
+
+ "github.com/stretchr/testify/suite"
+ "github.com/superseriousbusiness/gotosocial/internal/ap"
+ "github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
+ "github.com/superseriousbusiness/gotosocial/internal/messages"
+)
+
+type CreateTestSuite struct {
+ FederatingDBTestSuite
+}
+
+func (suite *CreateTestSuite) TestCreateNote() {
+ receivingAccount := suite.testAccounts["local_account_1"]
+ requestingAccount := suite.testAccounts["remote_account_1"]
+ fromFederatorChan := make(chan messages.FromFederator, 10)
+
+ ctx := createTestContext(receivingAccount, requestingAccount, fromFederatorChan)
+
+ create := suite.testActivities["dm_for_zork"].Activity
+
+ err := suite.federatingDB.Create(ctx, create)
+ suite.NoError(err)
+
+ // should be a message heading to the processor now, which we can intercept here
+ msg := <-fromFederatorChan
+ suite.Equal(ap.ObjectNote, msg.APObjectType)
+ suite.Equal(ap.ActivityCreate, msg.APActivityType)
+
+ // shiny new status should be defined on the message
+ suite.NotNil(msg.GTSModel)
+ status := msg.GTSModel.(*gtsmodel.Status)
+
+ // status should have some expected values
+ suite.Equal(requestingAccount.ID, status.AccountID)
+ suite.Equal("hey zork here's a new private note for you", status.Content)
+
+ // status should be in the database
+ _, err = suite.db.GetStatusByID(context.Background(), status.ID)
+ suite.NoError(err)
+}
+
+func (suite *CreateTestSuite) TestCreateNoteForward() {
+ receivingAccount := suite.testAccounts["local_account_1"]
+ requestingAccount := suite.testAccounts["remote_account_1"]
+ fromFederatorChan := make(chan messages.FromFederator, 10)
+
+ ctx := createTestContext(receivingAccount, requestingAccount, fromFederatorChan)
+
+ create := suite.testActivities["forwarded_message"].Activity
+
+ err := suite.federatingDB.Create(ctx, create)
+ suite.NoError(err)
+
+ // should be a message heading to the processor now, which we can intercept here
+ msg := <-fromFederatorChan
+ suite.Equal(ap.ObjectNote, msg.APObjectType)
+ suite.Equal(ap.ActivityCreate, msg.APActivityType)
+
+ // nothing should be set as the model since this is a forward
+ suite.Nil(msg.GTSModel)
+
+ // but we should have a uri set
+ suite.Equal("http://example.org/users/some_user/statuses/afaba698-5740-4e32-a702-af61aa543bc1", msg.APIri.String())
+}
+
+func TestCreateTestSuite(t *testing.T) {
+ suite.Run(t, &CreateTestSuite{})
+}
diff --git a/internal/federation/federatingdb/delete.go b/internal/federation/federatingdb/delete.go
index fc77f8025..77c3f502b 100644
--- a/internal/federation/federatingdb/delete.go
+++ b/internal/federation/federatingdb/delete.go
@@ -44,12 +44,9 @@ func (f *federatingDB) Delete(ctx context.Context, id *url.URL) error {
)
l.Debug("entering Delete")
- targetAcct, fromFederatorChan, err := extractFromCtx(ctx)
- if err != nil {
- return err
- }
- if targetAcct == nil || fromFederatorChan == nil {
- // If the target account or federator channel wasn't set on the context, that means this request didn't pass
+ receivingAccount, _, fromFederatorChan := extractFromCtx(ctx)
+ if receivingAccount == nil || fromFederatorChan == nil {
+ // If the receiving account or federator channel wasn't set on the context, that means this request didn't pass
// through the API, but came from inside GtS as the result of another activity on this instance. That being so,
// we can safely just ignore this activity, since we know we've already processed it elsewhere.
return nil
@@ -68,7 +65,7 @@ func (f *federatingDB) Delete(ctx context.Context, id *url.URL) error {
APObjectType: ap.ObjectNote,
APActivityType: ap.ActivityDelete,
GTSModel: s,
- ReceivingAccount: targetAcct,
+ ReceivingAccount: receivingAccount,
}
}
@@ -80,7 +77,7 @@ func (f *federatingDB) Delete(ctx context.Context, id *url.URL) error {
APObjectType: ap.ObjectProfile,
APActivityType: ap.ActivityDelete,
GTSModel: a,
- ReceivingAccount: targetAcct,
+ ReceivingAccount: receivingAccount,
}
}
diff --git a/internal/federation/federatingdb/federatingdb_test.go b/internal/federation/federatingdb/federatingdb_test.go
index fc78540f2..3c22480f7 100644
--- a/internal/federation/federatingdb/federatingdb_test.go
+++ b/internal/federation/federatingdb/federatingdb_test.go
@@ -19,13 +19,17 @@
package federatingdb_test
import (
+ "context"
+
"github.com/sirupsen/logrus"
"github.com/stretchr/testify/suite"
"github.com/superseriousbusiness/gotosocial/internal/config"
"github.com/superseriousbusiness/gotosocial/internal/db"
"github.com/superseriousbusiness/gotosocial/internal/federation/federatingdb"
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
+ "github.com/superseriousbusiness/gotosocial/internal/messages"
"github.com/superseriousbusiness/gotosocial/internal/typeutils"
+ "github.com/superseriousbusiness/gotosocial/internal/util"
"github.com/superseriousbusiness/gotosocial/testrig"
)
@@ -45,6 +49,7 @@ type FederatingDBTestSuite struct {
testAttachments map[string]*gtsmodel.MediaAttachment
testStatuses map[string]*gtsmodel.Status
testBlocks map[string]*gtsmodel.Block
+ testActivities map[string]testrig.ActivityWithSignature
}
func (suite *FederatingDBTestSuite) SetupSuite() {
@@ -56,6 +61,7 @@ func (suite *FederatingDBTestSuite) SetupSuite() {
suite.testAttachments = testrig.NewTestAttachments()
suite.testStatuses = testrig.NewTestStatuses()
suite.testBlocks = testrig.NewTestBlocks()
+ suite.testActivities = testrig.NewTestActivities(suite.testAccounts)
}
func (suite *FederatingDBTestSuite) SetupTest() {
@@ -70,3 +76,11 @@ func (suite *FederatingDBTestSuite) SetupTest() {
func (suite *FederatingDBTestSuite) TearDownTest() {
testrig.StandardDBTeardown(suite.db)
}
+
+func createTestContext(receivingAccount *gtsmodel.Account, requestingAccount *gtsmodel.Account, fromFederatorChan chan messages.FromFederator) context.Context {
+ ctx := context.Background()
+ ctx = context.WithValue(ctx, util.APReceivingAccount, receivingAccount)
+ ctx = context.WithValue(ctx, util.APRequestingAccount, requestingAccount)
+ ctx = context.WithValue(ctx, util.APFromFederatorChanKey, fromFederatorChan)
+ return ctx
+}
diff --git a/internal/federation/federatingdb/undo.go b/internal/federation/federatingdb/undo.go
index 082d76e60..3d4cb1d53 100644
--- a/internal/federation/federatingdb/undo.go
+++ b/internal/federation/federatingdb/undo.go
@@ -46,12 +46,9 @@ func (f *federatingDB) Undo(ctx context.Context, undo vocab.ActivityStreamsUndo)
l.Debug("entering Undo")
}
- targetAcct, fromFederatorChan, err := extractFromCtx(ctx)
- if err != nil {
- return err
- }
- if targetAcct == nil || fromFederatorChan == nil {
- // If the target account or federator channel wasn't set on the context, that means this request didn't pass
+ receivingAccount, _, fromFederatorChan := extractFromCtx(ctx)
+ if receivingAccount == nil || fromFederatorChan == nil {
+ // If the receiving account or federator channel wasn't set on the context, that means this request didn't pass
// through the API, but came from inside GtS as the result of another activity on this instance. That being so,
// we can safely just ignore this activity, since we know we've already processed it elsewhere.
return nil
@@ -83,7 +80,7 @@ func (f *federatingDB) Undo(ctx context.Context, undo vocab.ActivityStreamsUndo)
return fmt.Errorf("UNDO: error converting asfollow to gtsfollow: %s", err)
}
// make sure the addressee of the original follow is the same as whatever inbox this landed in
- if gtsFollow.TargetAccountID != targetAcct.ID {
+ if gtsFollow.TargetAccountID != receivingAccount.ID {
return errors.New("UNDO: follow object account and inbox account were not the same")
}
// delete any existing FOLLOW
@@ -116,7 +113,7 @@ func (f *federatingDB) Undo(ctx context.Context, undo vocab.ActivityStreamsUndo)
return fmt.Errorf("UNDO: error converting asblock to gtsblock: %s", err)
}
// make sure the addressee of the original block is the same as whatever inbox this landed in
- if gtsBlock.TargetAccountID != targetAcct.ID {
+ if gtsBlock.TargetAccountID != receivingAccount.ID {
return errors.New("UNDO: block object account and inbox account were not the same")
}
// delete any existing BLOCK
diff --git a/internal/federation/federatingdb/update.go b/internal/federation/federatingdb/update.go
index 6ce08ccb6..b3a27b462 100644
--- a/internal/federation/federatingdb/update.go
+++ b/internal/federation/federatingdb/update.go
@@ -56,12 +56,9 @@ func (f *federatingDB) Update(ctx context.Context, asType vocab.Type) error {
l.Debug("entering Update")
}
- targetAcct, fromFederatorChan, err := extractFromCtx(ctx)
- if err != nil {
- return err
- }
- if targetAcct == nil || fromFederatorChan == nil {
- // If the target account or federator channel wasn't set on the context, that means this request didn't pass
+ receivingAccount, _, fromFederatorChan := extractFromCtx(ctx)
+ if receivingAccount == nil || fromFederatorChan == nil {
+ // If the receiving account or federator channel wasn't set on the context, that means this request didn't pass
// through the API, but came from inside GtS as the result of another activity on this instance. That being so,
// we can safely just ignore this activity, since we know we've already processed it elsewhere.
return nil
@@ -153,7 +150,7 @@ func (f *federatingDB) Update(ctx context.Context, asType vocab.Type) error {
APObjectType: ap.ObjectProfile,
APActivityType: ap.ActivityUpdate,
GTSModel: updatedAcct,
- ReceivingAccount: targetAcct,
+ ReceivingAccount: receivingAccount,
}
}
diff --git a/internal/federation/federatingdb/util.go b/internal/federation/federatingdb/util.go
index dfc998abb..49a95a449 100644
--- a/internal/federation/federatingdb/util.go
+++ b/internal/federation/federatingdb/util.go
@@ -289,29 +289,26 @@ func (f *federatingDB) collectIRIs(ctx context.Context, iris []*url.URL) (vocab.
// extractFromCtx extracts some useful values from a context passed into the federatingDB via the API:
// - The target account that owns the inbox or URI being interacted with.
+// - The requesting account that posted to the inbox.
// - A channel that messages for the processor can be placed into.
-func extractFromCtx(ctx context.Context) (*gtsmodel.Account, chan messages.FromFederator, error) {
- var targetAcct *gtsmodel.Account
- targetAcctI := ctx.Value(util.APAccount)
- if targetAcctI != nil {
- var ok bool
- targetAcct, ok = targetAcctI.(*gtsmodel.Account)
- if !ok {
- return nil, nil, errors.New("extractFromCtx: account value in context not parseable")
- }
+// If a value is not present, nil will be returned for it. It's up to the caller to check this and respond appropriately.
+func extractFromCtx(ctx context.Context) (receivingAccount, requestingAccount *gtsmodel.Account, fromFederatorChan chan messages.FromFederator) {
+ receivingAccountI := ctx.Value(util.APReceivingAccount)
+ if receivingAccountI != nil {
+ receivingAccount = receivingAccountI.(*gtsmodel.Account)
+ }
+
+ requestingAcctI := ctx.Value(util.APRequestingAccount)
+ if requestingAcctI != nil {
+ requestingAccount = requestingAcctI.(*gtsmodel.Account)
}
- var fromFederatorChan chan messages.FromFederator
fromFederatorChanI := ctx.Value(util.APFromFederatorChanKey)
if fromFederatorChanI != nil {
- var ok bool
- fromFederatorChan, ok = fromFederatorChanI.(chan messages.FromFederator)
- if !ok {
- return nil, nil, errors.New("extractFromCtx: fromFederatorChan value in context not parseable")
- }
+ fromFederatorChan = fromFederatorChanI.(chan messages.FromFederator)
}
- return targetAcct, fromFederatorChan, nil
+ return
}
func marshalItem(item vocab.Type) (string, error) {