diff options
55 files changed, 151 insertions, 199 deletions
| diff --git a/internal/api/activitypub/emoji/emojiget_test.go b/internal/api/activitypub/emoji/emojiget_test.go index ea9bbc752..993149784 100644 --- a/internal/api/activitypub/emoji/emojiget_test.go +++ b/internal/api/activitypub/emoji/emojiget_test.go @@ -45,7 +45,7 @@ type EmojiGetTestSuite struct {  	db           db.DB  	tc           *typeutils.Converter  	mediaManager *media.Manager -	federator    federation.Federator +	federator    *federation.Federator  	emailSender  email.Sender  	processor    *processing.Processor  	storage      *storage.Driver diff --git a/internal/api/activitypub/users/user_test.go b/internal/api/activitypub/users/user_test.go index 0689e7de8..611b9033a 100644 --- a/internal/api/activitypub/users/user_test.go +++ b/internal/api/activitypub/users/user_test.go @@ -41,7 +41,7 @@ type UserStandardTestSuite struct {  	db           db.DB  	tc           *typeutils.Converter  	mediaManager *media.Manager -	federator    federation.Federator +	federator    *federation.Federator  	emailSender  email.Sender  	processor    *processing.Processor  	storage      *storage.Driver diff --git a/internal/api/auth/auth_test.go b/internal/api/auth/auth_test.go index 5c397ae57..a8d029795 100644 --- a/internal/api/auth/auth_test.go +++ b/internal/api/auth/auth_test.go @@ -47,7 +47,7 @@ type AuthStandardTestSuite struct {  	storage      *storage.Driver  	state        state.State  	mediaManager *media.Manager -	federator    federation.Federator +	federator    *federation.Federator  	processor    *processing.Processor  	emailSender  email.Sender  	idp          oidc.IDP diff --git a/internal/api/client/accounts/account_test.go b/internal/api/client/accounts/account_test.go index 6984f2563..ed4d48027 100644 --- a/internal/api/client/accounts/account_test.go +++ b/internal/api/client/accounts/account_test.go @@ -47,7 +47,7 @@ type AccountStandardTestSuite struct {  	db           db.DB  	storage      *storage.Driver  	mediaManager *media.Manager -	federator    federation.Federator +	federator    *federation.Federator  	processor    *processing.Processor  	emailSender  email.Sender  	sentEmails   map[string]string diff --git a/internal/api/client/admin/admin_test.go b/internal/api/client/admin/admin_test.go index bb403c2d6..53b7b3552 100644 --- a/internal/api/client/admin/admin_test.go +++ b/internal/api/client/admin/admin_test.go @@ -47,7 +47,7 @@ type AdminStandardTestSuite struct {  	db           db.DB  	storage      *storage.Driver  	mediaManager *media.Manager -	federator    federation.Federator +	federator    *federation.Federator  	processor    *processing.Processor  	emailSender  email.Sender  	sentEmails   map[string]string diff --git a/internal/api/client/bookmarks/bookmarks_test.go b/internal/api/client/bookmarks/bookmarks_test.go index 6a6fc6108..b10cf914c 100644 --- a/internal/api/client/bookmarks/bookmarks_test.go +++ b/internal/api/client/bookmarks/bookmarks_test.go @@ -52,7 +52,7 @@ type BookmarkTestSuite struct {  	db           db.DB  	tc           *typeutils.Converter  	mediaManager *media.Manager -	federator    federation.Federator +	federator    *federation.Federator  	emailSender  email.Sender  	processor    *processing.Processor  	storage      *storage.Driver diff --git a/internal/api/client/favourites/favourites_test.go b/internal/api/client/favourites/favourites_test.go index 7033a8d39..c9776225f 100644 --- a/internal/api/client/favourites/favourites_test.go +++ b/internal/api/client/favourites/favourites_test.go @@ -39,7 +39,7 @@ type FavouritesStandardTestSuite struct {  	db           db.DB  	tc           *typeutils.Converter  	mediaManager *media.Manager -	federator    federation.Federator +	federator    *federation.Federator  	emailSender  email.Sender  	processor    *processing.Processor  	storage      *storage.Driver diff --git a/internal/api/client/followrequests/followrequest_test.go b/internal/api/client/followrequests/followrequest_test.go index 113950049..5268d259e 100644 --- a/internal/api/client/followrequests/followrequest_test.go +++ b/internal/api/client/followrequests/followrequest_test.go @@ -45,7 +45,7 @@ type FollowRequestStandardTestSuite struct {  	db           db.DB  	storage      *storage.Driver  	mediaManager *media.Manager -	federator    federation.Federator +	federator    *federation.Federator  	processor    *processing.Processor  	emailSender  email.Sender  	state        state.State diff --git a/internal/api/client/instance/instance_test.go b/internal/api/client/instance/instance_test.go index 116f4d4b4..0189d87bf 100644 --- a/internal/api/client/instance/instance_test.go +++ b/internal/api/client/instance/instance_test.go @@ -46,7 +46,7 @@ type InstanceStandardTestSuite struct {  	db           db.DB  	storage      *storage.Driver  	mediaManager *media.Manager -	federator    federation.Federator +	federator    *federation.Federator  	processor    *processing.Processor  	emailSender  email.Sender  	sentEmails   map[string]string diff --git a/internal/api/client/lists/lists_test.go b/internal/api/client/lists/lists_test.go index 353306e1e..ac6f79f11 100644 --- a/internal/api/client/lists/lists_test.go +++ b/internal/api/client/lists/lists_test.go @@ -39,7 +39,7 @@ type ListsStandardTestSuite struct {  	db           db.DB  	storage      *storage.Driver  	mediaManager *media.Manager -	federator    federation.Federator +	federator    *federation.Federator  	processor    *processing.Processor  	emailSender  email.Sender  	state        state.State diff --git a/internal/api/client/media/mediacreate_test.go b/internal/api/client/media/mediacreate_test.go index 23445607e..8fcaaa06e 100644 --- a/internal/api/client/media/mediacreate_test.go +++ b/internal/api/client/media/mediacreate_test.go @@ -55,7 +55,7 @@ type MediaCreateTestSuite struct {  	db           db.DB  	storage      *storage.Driver  	mediaManager *media.Manager -	federator    federation.Federator +	federator    *federation.Federator  	tc           *typeutils.Converter  	oauthServer  oauth.Server  	emailSender  email.Sender diff --git a/internal/api/client/media/mediaupdate_test.go b/internal/api/client/media/mediaupdate_test.go index eb8266082..423178ee7 100644 --- a/internal/api/client/media/mediaupdate_test.go +++ b/internal/api/client/media/mediaupdate_test.go @@ -51,7 +51,7 @@ type MediaUpdateTestSuite struct {  	suite.Suite  	db           db.DB  	storage      *storage.Driver -	federator    federation.Federator +	federator    *federation.Federator  	tc           *typeutils.Converter  	mediaManager *media.Manager  	oauthServer  oauth.Server diff --git a/internal/api/client/reports/reports_test.go b/internal/api/client/reports/reports_test.go index c1986cf1f..95833da20 100644 --- a/internal/api/client/reports/reports_test.go +++ b/internal/api/client/reports/reports_test.go @@ -38,7 +38,7 @@ type ReportsStandardTestSuite struct {  	db           db.DB  	storage      *storage.Driver  	mediaManager *media.Manager -	federator    federation.Federator +	federator    *federation.Federator  	processor    *processing.Processor  	emailSender  email.Sender  	sentEmails   map[string]string diff --git a/internal/api/client/search/search_test.go b/internal/api/client/search/search_test.go index b8d0dab6c..7b9155a83 100644 --- a/internal/api/client/search/search_test.go +++ b/internal/api/client/search/search_test.go @@ -46,7 +46,7 @@ type SearchStandardTestSuite struct {  	db           db.DB  	storage      *storage.Driver  	mediaManager *media.Manager -	federator    federation.Federator +	federator    *federation.Federator  	processor    *processing.Processor  	emailSender  email.Sender  	sentEmails   map[string]string diff --git a/internal/api/client/statuses/status_test.go b/internal/api/client/statuses/status_test.go index 4946bb9d3..96f7a633d 100644 --- a/internal/api/client/statuses/status_test.go +++ b/internal/api/client/statuses/status_test.go @@ -39,7 +39,7 @@ type StatusStandardTestSuite struct {  	db           db.DB  	tc           *typeutils.Converter  	mediaManager *media.Manager -	federator    federation.Federator +	federator    *federation.Federator  	emailSender  email.Sender  	processor    *processing.Processor  	storage      *storage.Driver diff --git a/internal/api/client/streaming/streaming_test.go b/internal/api/client/streaming/streaming_test.go index 87c07d8f1..1bd0bea78 100644 --- a/internal/api/client/streaming/streaming_test.go +++ b/internal/api/client/streaming/streaming_test.go @@ -51,7 +51,7 @@ type StreamingTestSuite struct {  	db           db.DB  	tc           *typeutils.Converter  	mediaManager *media.Manager -	federator    federation.Federator +	federator    *federation.Federator  	emailSender  email.Sender  	processor    *processing.Processor  	storage      *storage.Driver diff --git a/internal/api/client/user/user_test.go b/internal/api/client/user/user_test.go index db7adfd6d..ccf538ac2 100644 --- a/internal/api/client/user/user_test.go +++ b/internal/api/client/user/user_test.go @@ -38,7 +38,7 @@ type UserStandardTestSuite struct {  	db           db.DB  	tc           *typeutils.Converter  	mediaManager *media.Manager -	federator    federation.Federator +	federator    *federation.Federator  	emailSender  email.Sender  	processor    *processing.Processor  	storage      *storage.Driver diff --git a/internal/api/fileserver/fileserver_test.go b/internal/api/fileserver/fileserver_test.go index 6f46fbe74..9f6cb578f 100644 --- a/internal/api/fileserver/fileserver_test.go +++ b/internal/api/fileserver/fileserver_test.go @@ -41,7 +41,7 @@ type FileserverTestSuite struct {  	db           db.DB  	storage      *storage.Driver  	state        state.State -	federator    federation.Federator +	federator    *federation.Federator  	tc           *typeutils.Converter  	processor    *processing.Processor  	mediaManager *media.Manager diff --git a/internal/api/wellknown/webfinger/webfinger_test.go b/internal/api/wellknown/webfinger/webfinger_test.go index 3cec7fcde..e0da90db4 100644 --- a/internal/api/wellknown/webfinger/webfinger_test.go +++ b/internal/api/wellknown/webfinger/webfinger_test.go @@ -41,7 +41,7 @@ type WebfingerStandardTestSuite struct {  	state        state.State  	tc           *typeutils.Converter  	mediaManager *media.Manager -	federator    federation.Federator +	federator    *federation.Federator  	emailSender  email.Sender  	processor    *processing.Processor  	storage      *storage.Driver diff --git a/internal/federation/authenticate.go b/internal/federation/authenticate.go index 12d6f459a..a42633b8f 100644 --- a/internal/federation/authenticate.go +++ b/internal/federation/authenticate.go @@ -109,7 +109,7 @@ type PubKeyAuth struct {  // Also note that this function *does not* dereference the remote account that  // the signature key is associated with. Other functions should use the returned  // URL to dereference the remote account, if required. -func (f *federator) AuthenticateFederatedRequest(ctx context.Context, requestedUsername string) (*PubKeyAuth, gtserror.WithCode) { +func (f *Federator) AuthenticateFederatedRequest(ctx context.Context, requestedUsername string) (*PubKeyAuth, gtserror.WithCode) {  	// Thanks to the signature check middleware,  	// we should already have an http signature  	// verifier set on the context. If we don't, @@ -215,7 +215,7 @@ func (f *federator) AuthenticateFederatedRequest(ctx context.Context, requestedU  //  // In case an entry for the pubKey owner just doesn't  // exist in the db (yet), will return nil, nil. -func (f *federator) derefPubKeyDBOnly( +func (f *Federator) derefPubKeyDBOnly(  	ctx context.Context,  	pubKeyIDStr string,  ) (*PubKeyAuth, gtserror.WithCode) { @@ -248,7 +248,7 @@ func (f *federator) derefPubKeyDBOnly(  // checking in the database, and then (if no entry found, or entry  // found but pubKey expired) calling the remote pub key URI and  // extracting the key. -func (f *federator) derefPubKey( +func (f *Federator) derefPubKey(  	ctx context.Context,  	requestedUsername string,  	pubKeyIDStr string, @@ -363,7 +363,7 @@ func (f *federator) derefPubKey(  // callForPubKey handles the nitty gritty of actually  // making a request for the given pubKeyID with a  // transport created on behalf of requestedUsername. -func (f *federator) callForPubKey( +func (f *Federator) callForPubKey(  	ctx context.Context,  	requestedUsername string,  	pubKeyID *url.URL, diff --git a/internal/federation/commonbehavior.go b/internal/federation/commonbehavior.go index 4fbbe4b14..5ca704db7 100644 --- a/internal/federation/commonbehavior.go +++ b/internal/federation/commonbehavior.go @@ -51,7 +51,7 @@ import (  // Finally, if the authentication and authorization succeeds, then  // authenticated must be true and error nil. The request will continue  // to be processed. -func (f *federator) AuthenticateGetInbox(ctx context.Context, w http.ResponseWriter, r *http.Request) (context.Context, bool, error) { +func (f *Federator) AuthenticateGetInbox(ctx context.Context, w http.ResponseWriter, r *http.Request) (context.Context, bool, error) {  	// IMPLEMENTATION NOTE: For GoToSocial, we serve GETS to outboxes and inboxes through  	// the CLIENT API, not through the federation API, so we just do nothing here.  	return ctx, false, nil @@ -76,7 +76,7 @@ func (f *federator) AuthenticateGetInbox(ctx context.Context, w http.ResponseWri  // Finally, if the authentication and authorization succeeds, then  // authenticated must be true and error nil. The request will continue  // to be processed. -func (f *federator) AuthenticateGetOutbox(ctx context.Context, w http.ResponseWriter, r *http.Request) (context.Context, bool, error) { +func (f *Federator) AuthenticateGetOutbox(ctx context.Context, w http.ResponseWriter, r *http.Request) (context.Context, bool, error) {  	// IMPLEMENTATION NOTE: For GoToSocial, we serve GETS to outboxes and inboxes through  	// the CLIENT API, not through the federation API, so we just do nothing here.  	return ctx, false, nil @@ -90,7 +90,7 @@ func (f *federator) AuthenticateGetOutbox(ctx context.Context, w http.ResponseWr  //  // Always called, regardless whether the Federated Protocol or Social  // API is enabled. -func (f *federator) GetOutbox(ctx context.Context, r *http.Request) (vocab.ActivityStreamsOrderedCollectionPage, error) { +func (f *Federator) GetOutbox(ctx context.Context, r *http.Request) (vocab.ActivityStreamsOrderedCollectionPage, error) {  	// IMPLEMENTATION NOTE: For GoToSocial, we serve GETS to outboxes and inboxes through  	// the CLIENT API, not through the federation API, so we just do nothing here.  	return streams.NewActivityStreamsOrderedCollectionPage(), nil diff --git a/internal/federation/dereferencing/account.go b/internal/federation/dereferencing/account.go index 04efc464f..f94dbaffa 100644 --- a/internal/federation/dereferencing/account.go +++ b/internal/federation/dereferencing/account.go @@ -60,8 +60,10 @@ func accountUpToDate(account *gtsmodel.Account) bool {  	return false  } -// GetAccountByURI: implements Dereferencer{}.GetAccountByURI. -func (d *deref) GetAccountByURI(ctx context.Context, requestUser string, uri *url.URL) (*gtsmodel.Account, ap.Accountable, error) { +// GetAccountByURI will attempt to fetch an accounts by its URI, first checking the database. In the case of a newly-met remote model, or a remote model +// whose last_fetched date is beyond a certain interval, the account will be dereferenced. In the case of dereferencing, some low-priority account information +// may be enqueued for asynchronous fetching, e.g. featured account statuses (pins). An ActivityPub object indicates the account was dereferenced. +func (d *Dereferencer) GetAccountByURI(ctx context.Context, requestUser string, uri *url.URL) (*gtsmodel.Account, ap.Accountable, error) {  	// Fetch and dereference account if necessary.  	account, apubAcc, err := d.getAccountByURI(ctx,  		requestUser, @@ -84,7 +86,7 @@ func (d *deref) GetAccountByURI(ctx context.Context, requestUser string, uri *ur  }  // getAccountByURI is a package internal form of .GetAccountByURI() that doesn't bother dereferencing featured posts on update. -func (d *deref) getAccountByURI(ctx context.Context, requestUser string, uri *url.URL) (*gtsmodel.Account, ap.Accountable, error) { +func (d *Dereferencer) getAccountByURI(ctx context.Context, requestUser string, uri *url.URL) (*gtsmodel.Account, ap.Accountable, error) {  	var (  		account *gtsmodel.Account  		uriStr  = uri.String() @@ -157,8 +159,10 @@ func (d *deref) getAccountByURI(ctx context.Context, requestUser string, uri *ur  	return latest, apubAcc, nil  } -// GetAccountByUsernameDomain: implements Dereferencer{}.GetAccountByUsernameDomain. -func (d *deref) GetAccountByUsernameDomain(ctx context.Context, requestUser string, username string, domain string) (*gtsmodel.Account, ap.Accountable, error) { +// GetAccountByUsernameDomain will attempt to fetch an accounts by its username@domain, first checking the database. In the case of a newly-met remote model, +// or a remote model whose last_fetched date is beyond a certain interval, the account will be dereferenced. In the case of dereferencing, some low-priority +// account information may be enqueued for asynchronous fetching, e.g. featured account statuses (pins). An ActivityPub object indicates the account was dereferenced. +func (d *Dereferencer) GetAccountByUsernameDomain(ctx context.Context, requestUser string, username string, domain string) (*gtsmodel.Account, ap.Accountable, error) {  	if domain == config.GetHost() || domain == config.GetAccountDomain() {  		// We do local lookups using an empty domain,  		// else it will fail the db search below. @@ -224,8 +228,10 @@ func (d *deref) GetAccountByUsernameDomain(ctx context.Context, requestUser stri  	return latest, apubAcc, nil  } -// RefreshAccount: implements Dereferencer{}.RefreshAccount. -func (d *deref) RefreshAccount(ctx context.Context, requestUser string, account *gtsmodel.Account, apubAcc ap.Accountable, force bool) (*gtsmodel.Account, ap.Accountable, error) { +// RefreshAccount updates the given account if remote and last_fetched is beyond fetch interval, or if force is set. An updated account model is returned, +// but in the case of dereferencing, some low-priority account information may be enqueued for asynchronous fetching, e.g. featured account statuses (pins). +// An ActivityPub object indicates the account was dereferenced (i.e. updated). +func (d *Dereferencer) RefreshAccount(ctx context.Context, requestUser string, account *gtsmodel.Account, apubAcc ap.Accountable, force bool) (*gtsmodel.Account, ap.Accountable, error) {  	// Check whether needs update (and not forced).  	if accountUpToDate(account) && !force {  		return account, nil, nil @@ -264,8 +270,9 @@ func (d *deref) RefreshAccount(ctx context.Context, requestUser string, account  	return latest, apubAcc, nil  } -// RefreshAccountAsync: implements Dereferencer{}.RefreshAccountAsync. -func (d *deref) RefreshAccountAsync(ctx context.Context, requestUser string, account *gtsmodel.Account, apubAcc ap.Accountable, force bool) { +// RefreshAccountAsync enqueues the given account for an asychronous update fetching, if last_fetched is beyond fetch interval, or if forcc is set. +// This is a more optimized form of manually enqueueing .UpdateAccount() to the federation worker, since it only enqueues update if necessary. +func (d *Dereferencer) RefreshAccountAsync(ctx context.Context, requestUser string, account *gtsmodel.Account, apubAcc ap.Accountable, force bool) {  	// Check whether needs update (and not forced).  	if accountUpToDate(account) && !force {  		return @@ -294,7 +301,7 @@ func (d *deref) RefreshAccountAsync(ctx context.Context, requestUser string, acc  }  // enrichAccount will enrich the given account, whether a new barebones model, or existing model from the database. It handles necessary dereferencing, webfingering etc. -func (d *deref) enrichAccount(ctx context.Context, requestUser string, uri *url.URL, account *gtsmodel.Account, apubAcc ap.Accountable) (*gtsmodel.Account, ap.Accountable, error) { +func (d *Dereferencer) enrichAccount(ctx context.Context, requestUser string, uri *url.URL, account *gtsmodel.Account, apubAcc ap.Accountable) (*gtsmodel.Account, ap.Accountable, error) {  	// Pre-fetch a transport for requesting username, used by later deref procedures.  	tsport, err := d.transportController.NewTransportForUsername(ctx, requestUser)  	if err != nil { @@ -472,7 +479,7 @@ func (d *deref) enrichAccount(ctx context.Context, requestUser string, uri *url.  	return latestAcc, apubAcc, nil  } -func (d *deref) fetchRemoteAccountAvatar(ctx context.Context, tsport transport.Transport, existing, latestAcc *gtsmodel.Account) error { +func (d *Dereferencer) fetchRemoteAccountAvatar(ctx context.Context, tsport transport.Transport, existing, latestAcc *gtsmodel.Account) error {  	if latestAcc.AvatarRemoteURL == "" {  		// No avatar set on newest model, leave  		// latest avatar attachment ID empty. @@ -562,7 +569,7 @@ func (d *deref) fetchRemoteAccountAvatar(ctx context.Context, tsport transport.T  	return nil  } -func (d *deref) fetchRemoteAccountHeader(ctx context.Context, tsport transport.Transport, existing, latestAcc *gtsmodel.Account) error { +func (d *Dereferencer) fetchRemoteAccountHeader(ctx context.Context, tsport transport.Transport, existing, latestAcc *gtsmodel.Account) error {  	if latestAcc.HeaderRemoteURL == "" {  		// No header set on newest model, leave  		// latest header attachment ID empty. @@ -652,7 +659,7 @@ func (d *deref) fetchRemoteAccountHeader(ctx context.Context, tsport transport.T  	return nil  } -func (d *deref) fetchRemoteAccountEmojis(ctx context.Context, targetAccount *gtsmodel.Account, requestingUsername string) (bool, error) { +func (d *Dereferencer) fetchRemoteAccountEmojis(ctx context.Context, targetAccount *gtsmodel.Account, requestingUsername string) (bool, error) {  	maybeEmojis := targetAccount.Emojis  	maybeEmojiIDs := targetAccount.EmojiIDs @@ -766,7 +773,7 @@ func (d *deref) fetchRemoteAccountEmojis(ctx context.Context, targetAccount *gts  // dereferenceAccountFeatured dereferences an account's featuredCollectionURI (if not empty). For each discovered status, this status will  // be dereferenced (if necessary) and marked as pinned (if necessary). Then, old pins will be removed if they're not included in new pins. -func (d *deref) dereferenceAccountFeatured(ctx context.Context, requestUser string, account *gtsmodel.Account) error { +func (d *Dereferencer) dereferenceAccountFeatured(ctx context.Context, requestUser string, account *gtsmodel.Account) error {  	uri, err := url.Parse(account.FeaturedCollectionURI)  	if err != nil {  		return err diff --git a/internal/federation/dereferencing/announce.go b/internal/federation/dereferencing/announce.go index e479e41b1..22c33685a 100644 --- a/internal/federation/dereferencing/announce.go +++ b/internal/federation/dereferencing/announce.go @@ -27,7 +27,7 @@ import (  	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"  ) -func (d *deref) DereferenceAnnounce(ctx context.Context, announce *gtsmodel.Status, requestingUsername string) error { +func (d *Dereferencer) DereferenceAnnounce(ctx context.Context, announce *gtsmodel.Status, requestingUsername string) error {  	if announce.BoostOf == nil {  		// we can't do anything unfortunately  		return errors.New("DereferenceAnnounce: no URI to dereference") diff --git a/internal/federation/dereferencing/collectionpage.go b/internal/federation/dereferencing/collectionpage.go index dc4ac7b4b..dc5c68273 100644 --- a/internal/federation/dereferencing/collectionpage.go +++ b/internal/federation/dereferencing/collectionpage.go @@ -30,7 +30,7 @@ import (  )  // dereferenceCollectionPage returns the activitystreams CollectionPage at the specified IRI, or an error if something goes wrong. -func (d *deref) dereferenceCollectionPage(ctx context.Context, username string, pageIRI *url.URL) (ap.CollectionPageIterator, error) { +func (d *Dereferencer) dereferenceCollectionPage(ctx context.Context, username string, pageIRI *url.URL) (ap.CollectionPageIterator, error) {  	if blocked, err := d.state.DB.IsDomainBlocked(ctx, pageIRI.Host); blocked || err != nil {  		return nil, gtserror.Newf("domain %s is blocked", pageIRI.Host)  	} diff --git a/internal/federation/dereferencing/dereferencer.go b/internal/federation/dereferencing/dereferencer.go index 6248aa2c1..a5c68bd80 100644 --- a/internal/federation/dereferencing/dereferencer.go +++ b/internal/federation/dereferencing/dereferencer.go @@ -18,72 +18,19 @@  package dereferencing  import ( -	"context"  	"net/url"  	"sync"  	"codeberg.org/gruf/go-mutexes" -	"github.com/superseriousbusiness/gotosocial/internal/ap" -	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"  	"github.com/superseriousbusiness/gotosocial/internal/media"  	"github.com/superseriousbusiness/gotosocial/internal/state"  	"github.com/superseriousbusiness/gotosocial/internal/transport"  	"github.com/superseriousbusiness/gotosocial/internal/typeutils"  ) -// Dereferencer wraps logic and functionality for doing dereferencing of remote accounts, statuses, etc, from federated instances. -type Dereferencer interface { -	// GetAccountByURI will attempt to fetch an accounts by its URI, first checking the database. In the case of a newly-met remote model, or a remote model -	// whose last_fetched date is beyond a certain interval, the account will be dereferenced. In the case of dereferencing, some low-priority account information -	// may be enqueued for asynchronous fetching, e.g. featured account statuses (pins). An ActivityPub object indicates the account was dereferenced. -	GetAccountByURI(ctx context.Context, requestUser string, uri *url.URL) (*gtsmodel.Account, ap.Accountable, error) - -	// GetAccountByUsernameDomain will attempt to fetch an accounts by its username@domain, first checking the database. In the case of a newly-met remote model, -	// or a remote model whose last_fetched date is beyond a certain interval, the account will be dereferenced. In the case of dereferencing, some low-priority -	// account information may be enqueued for asynchronous fetching, e.g. featured account statuses (pins). An ActivityPub object indicates the account was dereferenced. -	GetAccountByUsernameDomain(ctx context.Context, requestUser string, username string, domain string) (*gtsmodel.Account, ap.Accountable, error) - -	// RefreshAccount updates the given account if remote and last_fetched is beyond fetch interval, or if force is set. An updated account model is returned, -	// but in the case of dereferencing, some low-priority account information may be enqueued for asynchronous fetching, e.g. featured account statuses (pins). -	// An ActivityPub object indicates the account was dereferenced (i.e. updated). -	RefreshAccount(ctx context.Context, requestUser string, account *gtsmodel.Account, apubAcc ap.Accountable, force bool) (*gtsmodel.Account, ap.Accountable, error) - -	// RefreshAccountAsync enqueues the given account for an asychronous update fetching, if last_fetched is beyond fetch interval, or if forcc is set. -	// This is a more optimized form of manually enqueueing .UpdateAccount() to the federation worker, since it only enqueues update if necessary. -	RefreshAccountAsync(ctx context.Context, requestUser string, account *gtsmodel.Account, apubAcc ap.Accountable, force bool) - -	// GetStatusByURI will attempt to fetch a status by its URI, first checking the database. In the case of a newly-met remote model, or a remote model -	// whose last_fetched date is beyond a certain interval, the status will be dereferenced. In the case of dereferencing, some low-priority status information -	// may be enqueued for asynchronous fetching, e.g. dereferencing the remainder of the status thread. An ActivityPub object indicates the status was dereferenced. -	GetStatusByURI(ctx context.Context, requestUser string, uri *url.URL) (*gtsmodel.Status, ap.Statusable, error) - -	// RefreshStatus updates the given status if remote and last_fetched is beyond fetch interval, or if force is set. An updated status model is returned, -	// but in the case of dereferencing, some low-priority status information may be enqueued for asynchronous fetching, e.g. dereferencing the remainder of the -	// status thread. An ActivityPub object indicates the status was dereferenced (i.e. updated). -	RefreshStatus(ctx context.Context, requestUser string, status *gtsmodel.Status, apubStatus ap.Statusable, force bool) (*gtsmodel.Status, ap.Statusable, error) - -	// RefreshStatusAsync enqueues the given status for an asychronous update fetching, if last_fetched is beyond fetch interval, or if force is set. -	// This is a more optimized form of manually enqueueing .UpdateStatus() to the federation worker, since it only enqueues update if necessary. -	RefreshStatusAsync(ctx context.Context, requestUser string, status *gtsmodel.Status, apubStatus ap.Statusable, force bool) - -	// DereferenceStatusAncestors iterates upwards from the given status, using InReplyToURI, to ensure that as many parent statuses as possible are dereferenced. -	DereferenceStatusAncestors(ctx context.Context, requestUser string, status *gtsmodel.Status) error - -	// DereferenceStatusDescendents iterates downwards from the given status, using its replies, to ensure that as many children statuses as possible are dereferenced. -	DereferenceStatusDescendants(ctx context.Context, requestUser string, statusIRI *url.URL, parent ap.Statusable) error - -	GetRemoteInstance(ctx context.Context, username string, remoteInstanceURI *url.URL) (*gtsmodel.Instance, error) - -	DereferenceAnnounce(ctx context.Context, announce *gtsmodel.Status, requestingUsername string) error - -	GetRemoteMedia(ctx context.Context, requestingUsername string, accountID string, remoteURL string, ai *media.AdditionalMediaInfo) (*media.ProcessingMedia, error) - -	GetRemoteEmoji(ctx context.Context, requestingUsername string, remoteURL string, shortcode string, domain string, id string, emojiURI string, ai *media.AdditionalEmojiInfo, refresh bool) (*media.ProcessingEmoji, error) - -	Handshaking(username string, remoteAccountID *url.URL) bool -} - -type deref struct { +// Dereferencer wraps logic and functionality for doing dereferencing +// of remote accounts, statuses, etc, from federated instances. +type Dereferencer struct {  	state               *state.State  	converter           *typeutils.Converter  	transportController transport.Controller @@ -99,8 +46,13 @@ type deref struct {  }  // NewDereferencer returns a Dereferencer initialized with the given parameters. -func NewDereferencer(state *state.State, converter *typeutils.Converter, transportController transport.Controller, mediaManager *media.Manager) Dereferencer { -	return &deref{ +func NewDereferencer( +	state *state.State, +	converter *typeutils.Converter, +	transportController transport.Controller, +	mediaManager *media.Manager, +) Dereferencer { +	return Dereferencer{  		state:               state,  		converter:           converter,  		transportController: transportController, diff --git a/internal/federation/dereferencing/emoji.go b/internal/federation/dereferencing/emoji.go index 3ce3c7f10..2d86da663 100644 --- a/internal/federation/dereferencing/emoji.go +++ b/internal/federation/dereferencing/emoji.go @@ -30,7 +30,7 @@ import (  	"github.com/superseriousbusiness/gotosocial/internal/media"  ) -func (d *deref) GetRemoteEmoji(ctx context.Context, requestingUsername string, remoteURL string, shortcode string, domain string, id string, emojiURI string, ai *media.AdditionalEmojiInfo, refresh bool) (*media.ProcessingEmoji, error) { +func (d *Dereferencer) GetRemoteEmoji(ctx context.Context, requestingUsername string, remoteURL string, shortcode string, domain string, id string, emojiURI string, ai *media.AdditionalEmojiInfo, refresh bool) (*media.ProcessingEmoji, error) {  	var (  		shortcodeDomain = shortcode + "@" + domain  		processingEmoji *media.ProcessingEmoji @@ -88,7 +88,7 @@ func (d *deref) GetRemoteEmoji(ctx context.Context, requestingUsername string, r  	return processingEmoji, nil  } -func (d *deref) populateEmojis(ctx context.Context, rawEmojis []*gtsmodel.Emoji, requestingUsername string) ([]*gtsmodel.Emoji, error) { +func (d *Dereferencer) populateEmojis(ctx context.Context, rawEmojis []*gtsmodel.Emoji, requestingUsername string) ([]*gtsmodel.Emoji, error) {  	// At this point we should know:  	// * the AP uri of the emoji  	// * the domain of the emoji diff --git a/internal/federation/dereferencing/finger.go b/internal/federation/dereferencing/finger.go index fff079327..a81afa5ea 100644 --- a/internal/federation/dereferencing/finger.go +++ b/internal/federation/dereferencing/finger.go @@ -30,7 +30,7 @@ import (  	"github.com/superseriousbusiness/gotosocial/internal/util"  ) -func (d *deref) fingerRemoteAccount(ctx context.Context, transport transport.Transport, targetUsername string, targetHost string) (accountDomain string, accountURI *url.URL, err error) { +func (d *Dereferencer) fingerRemoteAccount(ctx context.Context, transport transport.Transport, targetUsername string, targetHost string) (accountDomain string, accountURI *url.URL, err error) {  	b, err := transport.Finger(ctx, targetUsername, targetHost)  	if err != nil {  		err = fmt.Errorf("fingerRemoteAccount: error fingering @%s@%s: %s", targetUsername, targetHost, err) diff --git a/internal/federation/dereferencing/handshake.go b/internal/federation/dereferencing/handshake.go index 96d8d349f..1180ff140 100644 --- a/internal/federation/dereferencing/handshake.go +++ b/internal/federation/dereferencing/handshake.go @@ -21,7 +21,7 @@ import (  	"net/url"  ) -func (d *deref) Handshaking(username string, remoteAccountID *url.URL) bool { +func (d *Dereferencer) Handshaking(username string, remoteAccountID *url.URL) bool {  	d.handshakesMu.Lock()  	defer d.handshakesMu.Unlock() @@ -51,7 +51,7 @@ func (d *deref) Handshaking(username string, remoteAccountID *url.URL) bool {  	return false  } -func (d *deref) startHandshake(username string, remoteAccountID *url.URL) { +func (d *Dereferencer) startHandshake(username string, remoteAccountID *url.URL) {  	d.handshakesMu.Lock()  	defer d.handshakesMu.Unlock() @@ -68,7 +68,7 @@ func (d *deref) startHandshake(username string, remoteAccountID *url.URL) {  	d.handshakes[username] = remoteIDs  } -func (d *deref) stopHandshake(username string, remoteAccountID *url.URL) { +func (d *Dereferencer) stopHandshake(username string, remoteAccountID *url.URL) {  	d.handshakesMu.Lock()  	defer d.handshakesMu.Unlock() diff --git a/internal/federation/dereferencing/instance.go b/internal/federation/dereferencing/instance.go index 742239637..90ce074cd 100644 --- a/internal/federation/dereferencing/instance.go +++ b/internal/federation/dereferencing/instance.go @@ -25,7 +25,7 @@ import (  	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"  ) -func (d *deref) GetRemoteInstance(ctx context.Context, username string, remoteInstanceURI *url.URL) (*gtsmodel.Instance, error) { +func (d *Dereferencer) GetRemoteInstance(ctx context.Context, username string, remoteInstanceURI *url.URL) (*gtsmodel.Instance, error) {  	if blocked, err := d.state.DB.IsDomainBlocked(ctx, remoteInstanceURI.Host); blocked || err != nil {  		return nil, fmt.Errorf("GetRemoteInstance: domain %s is blocked", remoteInstanceURI.Host)  	} diff --git a/internal/federation/dereferencing/media.go b/internal/federation/dereferencing/media.go index 315da1c39..15aa4bb08 100644 --- a/internal/federation/dereferencing/media.go +++ b/internal/federation/dereferencing/media.go @@ -26,7 +26,7 @@ import (  	"github.com/superseriousbusiness/gotosocial/internal/media"  ) -func (d *deref) GetRemoteMedia(ctx context.Context, requestingUsername string, accountID string, remoteURL string, ai *media.AdditionalMediaInfo) (*media.ProcessingMedia, error) { +func (d *Dereferencer) GetRemoteMedia(ctx context.Context, requestingUsername string, accountID string, remoteURL string, ai *media.AdditionalMediaInfo) (*media.ProcessingMedia, error) {  	if accountID == "" {  		return nil, fmt.Errorf("GetRemoteMedia: account ID was empty")  	} diff --git a/internal/federation/dereferencing/status.go b/internal/federation/dereferencing/status.go index 84316f3a9..bb6a8002c 100644 --- a/internal/federation/dereferencing/status.go +++ b/internal/federation/dereferencing/status.go @@ -52,8 +52,10 @@ func statusUpToDate(status *gtsmodel.Status) bool {  	return false  } -// GetStatus: implements Dereferencer{}.GetStatus(). -func (d *deref) GetStatusByURI(ctx context.Context, requestUser string, uri *url.URL) (*gtsmodel.Status, ap.Statusable, error) { +// GetStatusByURI will attempt to fetch a status by its URI, first checking the database. In the case of a newly-met remote model, or a remote model +// whose last_fetched date is beyond a certain interval, the status will be dereferenced. In the case of dereferencing, some low-priority status information +// may be enqueued for asynchronous fetching, e.g. dereferencing the remainder of the status thread. An ActivityPub object indicates the status was dereferenced. +func (d *Dereferencer) GetStatusByURI(ctx context.Context, requestUser string, uri *url.URL) (*gtsmodel.Status, ap.Statusable, error) {  	// Fetch and dereference status if necessary.  	status, apubStatus, err := d.getStatusByURI(ctx,  		requestUser, @@ -74,7 +76,7 @@ func (d *deref) GetStatusByURI(ctx context.Context, requestUser string, uri *url  }  // getStatusByURI is a package internal form of .GetStatusByURI() that doesn't bother dereferencing the whole thread on update. -func (d *deref) getStatusByURI(ctx context.Context, requestUser string, uri *url.URL) (*gtsmodel.Status, ap.Statusable, error) { +func (d *Dereferencer) getStatusByURI(ctx context.Context, requestUser string, uri *url.URL) (*gtsmodel.Status, ap.Statusable, error) {  	var (  		status *gtsmodel.Status  		uriStr = uri.String() @@ -146,8 +148,10 @@ func (d *deref) getStatusByURI(ctx context.Context, requestUser string, uri *url  	return latest, apubStatus, nil  } -// RefreshStatus: implements Dereferencer{}.RefreshStatus(). -func (d *deref) RefreshStatus(ctx context.Context, requestUser string, status *gtsmodel.Status, apubStatus ap.Statusable, force bool) (*gtsmodel.Status, ap.Statusable, error) { +// RefreshStatus updates the given status if remote and last_fetched is beyond fetch interval, or if force is set. An updated status model is returned, +// but in the case of dereferencing, some low-priority status information may be enqueued for asynchronous fetching, e.g. dereferencing the remainder of the +// status thread. An ActivityPub object indicates the status was dereferenced (i.e. updated). +func (d *Dereferencer) RefreshStatus(ctx context.Context, requestUser string, status *gtsmodel.Status, apubStatus ap.Statusable, force bool) (*gtsmodel.Status, ap.Statusable, error) {  	// Check whether needs update.  	if !force && statusUpToDate(status) {  		return status, nil, nil @@ -178,8 +182,9 @@ func (d *deref) RefreshStatus(ctx context.Context, requestUser string, status *g  	return latest, apubStatus, nil  } -// RefreshStatusAsync: implements Dereferencer{}.RefreshStatusAsync(). -func (d *deref) RefreshStatusAsync(ctx context.Context, requestUser string, status *gtsmodel.Status, apubStatus ap.Statusable, force bool) { +// RefreshStatusAsync enqueues the given status for an asychronous update fetching, if last_fetched is beyond fetch interval, or if force is set. +// This is a more optimized form of manually enqueueing .UpdateStatus() to the federation worker, since it only enqueues update if necessary. +func (d *Dereferencer) RefreshStatusAsync(ctx context.Context, requestUser string, status *gtsmodel.Status, apubStatus ap.Statusable, force bool) {  	// Check whether needs update.  	if statusUpToDate(status) {  		return @@ -208,7 +213,7 @@ func (d *deref) RefreshStatusAsync(ctx context.Context, requestUser string, stat  // enrichStatus will enrich the given status, whether a new  // barebones model, or existing model from the database.  // It handles necessary dereferencing, database updates, etc. -func (d *deref) enrichStatus( +func (d *Dereferencer) enrichStatus(  	ctx context.Context,  	requestUser string,  	uri *url.URL, @@ -329,7 +334,7 @@ func (d *deref) enrichStatus(  	return latestStatus, apubStatus, nil  } -func (d *deref) fetchStatusMentions(ctx context.Context, requestUser string, existing, status *gtsmodel.Status) error { +func (d *Dereferencer) fetchStatusMentions(ctx context.Context, requestUser string, existing, status *gtsmodel.Status) error {  	// Allocate new slice to take the yet-to-be created mention IDs.  	status.MentionIDs = make([]string, len(status.Mentions)) @@ -405,7 +410,7 @@ func (d *deref) fetchStatusMentions(ctx context.Context, requestUser string, exi  	return nil  } -func (d *deref) fetchStatusTags(ctx context.Context, status *gtsmodel.Status) error { +func (d *Dereferencer) fetchStatusTags(ctx context.Context, status *gtsmodel.Status) error {  	// Allocate new slice to take the yet-to-be determined tag IDs.  	status.TagIDs = make([]string, len(status.Tags)) @@ -455,7 +460,7 @@ func (d *deref) fetchStatusTags(ctx context.Context, status *gtsmodel.Status) er  	return nil  } -func (d *deref) fetchStatusAttachments(ctx context.Context, tsport transport.Transport, existing, status *gtsmodel.Status) error { +func (d *Dereferencer) fetchStatusAttachments(ctx context.Context, tsport transport.Transport, existing, status *gtsmodel.Status) error {  	// Allocate new slice to take the yet-to-be fetched attachment IDs.  	status.AttachmentIDs = make([]string, len(status.Attachments)) @@ -519,7 +524,7 @@ func (d *deref) fetchStatusAttachments(ctx context.Context, tsport transport.Tra  	return nil  } -func (d *deref) fetchStatusEmojis(ctx context.Context, requestUser string, status *gtsmodel.Status) error { +func (d *Dereferencer) fetchStatusEmojis(ctx context.Context, requestUser string, status *gtsmodel.Status) error {  	// Fetch the full-fleshed-out emoji objects for our status.  	emojis, err := d.populateEmojis(ctx, status.Emojis, requestUser)  	if err != nil { diff --git a/internal/federation/dereferencing/thread.go b/internal/federation/dereferencing/thread.go index 6d8c913c7..5753ce4dd 100644 --- a/internal/federation/dereferencing/thread.go +++ b/internal/federation/dereferencing/thread.go @@ -38,7 +38,7 @@ import (  // ancesters we are willing to follow before returning error.  const maxIter = 1000 -func (d *deref) dereferenceThread(ctx context.Context, username string, statusIRI *url.URL, status *gtsmodel.Status, statusable ap.Statusable) { +func (d *Dereferencer) dereferenceThread(ctx context.Context, username string, statusIRI *url.URL, status *gtsmodel.Status, statusable ap.Statusable) {  	// Ensure that ancestors have been fully dereferenced  	if err := d.DereferenceStatusAncestors(ctx, username, status); err != nil {  		log.Error(ctx, err) @@ -50,11 +50,8 @@ func (d *deref) dereferenceThread(ctx context.Context, username string, statusIR  	}  } -func (d *deref) DereferenceStatusAncestors( -	ctx context.Context, -	username string, -	status *gtsmodel.Status, -) error { +// DereferenceStatusAncestors iterates upwards from the given status, using InReplyToURI, to ensure that as many parent statuses as possible are dereferenced. +func (d *Dereferencer) DereferenceStatusAncestors(ctx context.Context, username string, status *gtsmodel.Status) error {  	// Start log entry with fields  	l := log.WithContext(ctx).  		WithFields(kv.Fields{ @@ -220,7 +217,8 @@ func (d *deref) DereferenceStatusAncestors(  	return gtserror.Newf("reached %d ancestor iterations for %q", maxIter, status.URI)  } -func (d *deref) DereferenceStatusDescendants(ctx context.Context, username string, statusIRI *url.URL, parent ap.Statusable) error { +// DereferenceStatusDescendents iterates downwards from the given status, using its replies, to ensure that as many children statuses as possible are dereferenced. +func (d *Dereferencer) DereferenceStatusDescendants(ctx context.Context, username string, statusIRI *url.URL, parent ap.Statusable) error {  	statusIRIStr := statusIRI.String()  	// Start log entry with fields diff --git a/internal/federation/federatingprotocol.go b/internal/federation/federatingprotocol.go index ea19eb651..28dc145af 100644 --- a/internal/federation/federatingprotocol.go +++ b/internal/federation/federatingprotocol.go @@ -93,7 +93,7 @@ func newErrOtherIRIBlocked(  // In this case, the DelegateActor implementation must not write a response  // to the ResponseWriter as is expected that the caller to PostInbox will  // do so when handling the error. -func (f *federator) PostInboxRequestBodyHook(ctx context.Context, r *http.Request, activity pub.Activity) (context.Context, error) { +func (f *Federator) PostInboxRequestBodyHook(ctx context.Context, r *http.Request, activity pub.Activity) (context.Context, error) {  	// Extract any other IRIs involved in this activity.  	otherIRIs := []*url.URL{} @@ -186,7 +186,7 @@ func (f *federator) PostInboxRequestBodyHook(ctx context.Context, r *http.Reques  // Finally, if the authentication and authorization succeeds, then  // authenticated must be true and error nil. The request will continue  // to be processed. -func (f *federator) AuthenticatePostInbox(ctx context.Context, w http.ResponseWriter, r *http.Request) (context.Context, bool, error) { +func (f *Federator) AuthenticatePostInbox(ctx context.Context, w http.ResponseWriter, r *http.Request) (context.Context, bool, error) {  	log.Tracef(ctx, "received request to authenticate inbox %s", r.URL.String())  	// Ensure this is an inbox path, and fetch the inbox owner @@ -298,7 +298,7 @@ func (f *federator) AuthenticatePostInbox(ctx context.Context, w http.ResponseWr  // Blocked should determine whether to permit a set of actors given by  // their ids are able to interact with this particular end user due to  // being blocked or other application-specific logic. -func (f *federator) Blocked(ctx context.Context, actorIRIs []*url.URL) (bool, error) { +func (f *Federator) Blocked(ctx context.Context, actorIRIs []*url.URL) (bool, error) {  	// Fetch relevant items from request context.  	// These should have been set further up the flow.  	receivingAccount := gtscontext.ReceivingAccount(ctx) @@ -498,7 +498,7 @@ func (f *federator) Blocked(ctx context.Context, actorIRIs []*url.URL) (bool, er  //  // Applications are not expected to handle every single ActivityStreams  // type and extension. The unhandled ones are passed to DefaultCallback. -func (f *federator) FederatingCallbacks(ctx context.Context) (wrapped pub.FederatingWrappedCallbacks, other []interface{}, err error) { +func (f *Federator) FederatingCallbacks(ctx context.Context) (wrapped pub.FederatingWrappedCallbacks, other []interface{}, err error) {  	wrapped = pub.FederatingWrappedCallbacks{  		// OnFollow determines what action to take for this  		// particular callback if a Follow Activity is handled. @@ -537,7 +537,7 @@ func (f *federator) FederatingCallbacks(ctx context.Context) (wrapped pub.Federa  // Applications are not expected to handle every single ActivityStreams  // type and extension, so the unhandled ones are passed to  // DefaultCallback. -func (f *federator) DefaultCallback(ctx context.Context, activity pub.Activity) error { +func (f *Federator) DefaultCallback(ctx context.Context, activity pub.Activity) error {  	log.Debugf(ctx, "received unhandle-able activity type (%s) so ignoring it", activity.GetTypeName())  	return nil  } @@ -546,7 +546,7 @@ func (f *federator) DefaultCallback(ctx context.Context, activity pub.Activity)  // an activity to determine if inbox forwarding needs to occur.  //  // Zero or negative numbers indicate infinite recursion. -func (f *federator) MaxInboxForwardingRecursionDepth(ctx context.Context) int { +func (f *Federator) MaxInboxForwardingRecursionDepth(ctx context.Context) int {  	// TODO  	return 4  } @@ -556,7 +556,7 @@ func (f *federator) MaxInboxForwardingRecursionDepth(ctx context.Context) int {  // delivery.  //  // Zero or negative numbers indicate infinite recursion. -func (f *federator) MaxDeliveryRecursionDepth(ctx context.Context) int { +func (f *Federator) MaxDeliveryRecursionDepth(ctx context.Context) int {  	// TODO  	return 4  } @@ -568,7 +568,7 @@ func (f *federator) MaxDeliveryRecursionDepth(ctx context.Context) int {  //  // The activity is provided as a reference for more intelligent  // logic to be used, but the implementation must not modify it. -func (f *federator) FilterForwarding(ctx context.Context, potentialRecipients []*url.URL, a pub.Activity) ([]*url.URL, error) { +func (f *Federator) FilterForwarding(ctx context.Context, potentialRecipients []*url.URL, a pub.Activity) ([]*url.URL, error) {  	// TODO  	return []*url.URL{}, nil  } @@ -581,7 +581,7 @@ func (f *federator) FilterForwarding(ctx context.Context, potentialRecipients []  //  // Always called, regardless whether the Federated Protocol or Social  // API is enabled. -func (f *federator) GetInbox(ctx context.Context, r *http.Request) (vocab.ActivityStreamsOrderedCollectionPage, error) { +func (f *Federator) GetInbox(ctx context.Context, r *http.Request) (vocab.ActivityStreamsOrderedCollectionPage, error) {  	// IMPLEMENTATION NOTE: For GoToSocial, we serve GETS to outboxes and inboxes through  	// the CLIENT API, not through the federation API, so we just do nothing here.  	return streams.NewActivityStreamsOrderedCollectionPage(), nil diff --git a/internal/federation/federator.go b/internal/federation/federator.go index 1d1df4714..8377546a1 100644 --- a/internal/federation/federator.go +++ b/internal/federation/federator.go @@ -18,44 +18,22 @@  package federation  import ( -	"context" -  	"github.com/superseriousbusiness/activity/pub"  	"github.com/superseriousbusiness/gotosocial/internal/db"  	"github.com/superseriousbusiness/gotosocial/internal/federation/dereferencing"  	"github.com/superseriousbusiness/gotosocial/internal/federation/federatingdb" -	"github.com/superseriousbusiness/gotosocial/internal/gtserror"  	"github.com/superseriousbusiness/gotosocial/internal/media"  	"github.com/superseriousbusiness/gotosocial/internal/state"  	"github.com/superseriousbusiness/gotosocial/internal/transport"  	"github.com/superseriousbusiness/gotosocial/internal/typeutils"  ) -// Federator wraps various interfaces and functions to manage activitypub federation from gotosocial -type Federator interface { -	// FederatingActor returns the underlying pub.FederatingActor, which can be used to send activities, and serve actors at inboxes/outboxes. -	FederatingActor() pub.FederatingActor -	// FederatingDB returns the underlying FederatingDB interface. -	FederatingDB() federatingdb.DB -	// TransportController returns the underlying transport controller. -	TransportController() transport.Controller - -	// AuthenticateFederatedRequest can be used to check the authenticity of incoming http-signed requests for federating resources. -	// The given username will be used to create a transport for making outgoing requests. See the implementation for more detailed comments. -	// -	// If the request is valid and passes authentication, the URL of the key owner ID will be returned, as well as true, and nil. -	// -	// If the request does not pass authentication, or there's a domain block, nil, false, nil will be returned. -	// -	// If something goes wrong during authentication, nil, false, and an error will be returned. -	AuthenticateFederatedRequest(ctx context.Context, username string) (*PubKeyAuth, gtserror.WithCode) - +var _ interface {  	pub.CommonBehavior  	pub.FederatingProtocol -	dereferencing.Dereferencer -} +} = &Federator{} -type federator struct { +type Federator struct {  	db                  db.DB  	federatingDB        federatingdb.DB  	clock               pub.Clock @@ -66,33 +44,40 @@ type federator struct {  	dereferencing.Dereferencer  } -// NewFederator returns a new federator -func NewFederator(state *state.State, federatingDB federatingdb.DB, transportController transport.Controller, converter *typeutils.Converter, mediaManager *media.Manager) Federator { -	dereferencer := dereferencing.NewDereferencer(state, converter, transportController, mediaManager) - +// NewFederator returns a new federator instance. +func NewFederator( +	state *state.State, +	federatingDB federatingdb.DB, +	transportController transport.Controller, +	converter *typeutils.Converter, +	mediaManager *media.Manager, +) *Federator {  	clock := &Clock{} -	f := &federator{ +	f := &Federator{  		db:                  state.DB,  		federatingDB:        federatingDB, -		clock:               &Clock{}, +		clock:               clock,  		converter:           converter,  		transportController: transportController,  		mediaManager:        mediaManager, -		Dereferencer:        dereferencer, +		Dereferencer:        dereferencing.NewDereferencer(state, converter, transportController, mediaManager),  	}  	actor := newFederatingActor(f, f, federatingDB, clock)  	f.actor = actor  	return f  } -func (f *federator) FederatingActor() pub.FederatingActor { +// FederatingActor returns the underlying pub.FederatingActor, which can be used to send activities, and serve actors at inboxes/outboxes. +func (f *Federator) FederatingActor() pub.FederatingActor {  	return f.actor  } -func (f *federator) FederatingDB() federatingdb.DB { +// FederatingDB returns the underlying FederatingDB interface. +func (f *Federator) FederatingDB() federatingdb.DB {  	return f.federatingDB  } -func (f *federator) TransportController() transport.Controller { +// TransportController returns the underlying transport controller. +func (f *Federator) TransportController() transport.Controller {  	return f.transportController  } diff --git a/internal/federation/federator_test.go b/internal/federation/federator_test.go index 7c57dfff1..bfc25fc74 100644 --- a/internal/federation/federator_test.go +++ b/internal/federation/federator_test.go @@ -39,7 +39,7 @@ type FederatorStandardTestSuite struct {  	typeconverter       *typeutils.Converter  	transportController transport.Controller  	httpClient          *testrig.MockHTTPClient -	federator           federation.Federator +	federator           *federation.Federator  	testAccounts   map[string]*gtsmodel.Account  	testStatuses   map[string]*gtsmodel.Status diff --git a/internal/federation/gone.go b/internal/federation/gone.go index 7f0c34532..e0278765c 100644 --- a/internal/federation/gone.go +++ b/internal/federation/gone.go @@ -26,12 +26,12 @@ import (  )  // CheckGone checks if a tombstone exists in the database for AP Actor or Object with the given uri. -func (f *federator) CheckGone(ctx context.Context, uri *url.URL) (bool, error) { +func (f *Federator) CheckGone(ctx context.Context, uri *url.URL) (bool, error) {  	return f.db.TombstoneExistsWithURI(ctx, uri.String())  }  // HandleGone puts a tombstone in the database, which marks an AP Actor or Object with the given uri as gone. -func (f *federator) HandleGone(ctx context.Context, uri *url.URL) error { +func (f *Federator) HandleGone(ctx context.Context, uri *url.URL) error {  	tombstone := >smodel.Tombstone{  		ID:     id.NewULID(),  		Domain: uri.Host, diff --git a/internal/federation/transport.go b/internal/federation/transport.go index 0116db4cb..b6f7a46c8 100644 --- a/internal/federation/transport.go +++ b/internal/federation/transport.go @@ -49,7 +49,7 @@ import (  // Note that the library will not maintain a long-lived pointer to the  // returned Transport so that any private credentials are able to be  // garbage collected. -func (f *federator) NewTransport(ctx context.Context, actorBoxIRI *url.URL, gofedAgent string) (pub.Transport, error) { +func (f *Federator) NewTransport(ctx context.Context, actorBoxIRI *url.URL, gofedAgent string) (pub.Transport, error) {  	var username string  	var err error diff --git a/internal/gotosocial/gotosocial.go b/internal/gotosocial/gotosocial.go index 6a66602f0..89d11c579 100644 --- a/internal/gotosocial/gotosocial.go +++ b/internal/gotosocial/gotosocial.go @@ -41,7 +41,12 @@ type Server interface {  // NewServer returns a new gotosocial server, initialized with the given configuration.  // An error will be returned the caller if something goes wrong during initialization  // eg., no db or storage connection, port for router already in use, etc. -func NewServer(db db.DB, apiRouter router.Router, federator federation.Federator, mediaManager *media.Manager) (Server, error) { +func NewServer( +	db db.DB, +	apiRouter router.Router, +	federator *federation.Federator, +	mediaManager *media.Manager, +) (Server, error) {  	return &gotosocial{  		db:           db,  		apiRouter:    apiRouter, @@ -54,7 +59,7 @@ func NewServer(db db.DB, apiRouter router.Router, federator federation.Federator  type gotosocial struct {  	db           db.DB  	apiRouter    router.Router -	federator    federation.Federator +	federator    *federation.Federator  	mediaManager *media.Manager  } diff --git a/internal/processing/account/account.go b/internal/processing/account/account.go index 06caffaec..ea6882271 100644 --- a/internal/processing/account/account.go +++ b/internal/processing/account/account.go @@ -42,7 +42,7 @@ type Processor struct {  	oauthServer  oauth.Server  	filter       *visibility.Filter  	formatter    *text.Formatter -	federator    federation.Federator +	federator    *federation.Federator  	parseMention gtsmodel.ParseMentionFunc  } @@ -53,7 +53,7 @@ func New(  	converter *typeutils.Converter,  	mediaManager *media.Manager,  	oauthServer oauth.Server, -	federator federation.Federator, +	federator *federation.Federator,  	filter *visibility.Filter,  	parseMention gtsmodel.ParseMentionFunc,  ) Processor { diff --git a/internal/processing/account/account_test.go b/internal/processing/account/account_test.go index a23d324f8..7f259815a 100644 --- a/internal/processing/account/account_test.go +++ b/internal/processing/account/account_test.go @@ -50,7 +50,7 @@ type AccountStandardTestSuite struct {  	oauthServer         oauth.Server  	fromClientAPIChan   chan messages.FromClientAPI  	transportController transport.Controller -	federator           federation.Federator +	federator           *federation.Federator  	emailSender         email.Sender  	sentEmails          map[string]string diff --git a/internal/processing/admin/admin_test.go b/internal/processing/admin/admin_test.go index 689f33f46..a5a790763 100644 --- a/internal/processing/admin/admin_test.go +++ b/internal/processing/admin/admin_test.go @@ -47,7 +47,7 @@ type AdminStandardTestSuite struct {  	oauthServer         oauth.Server  	fromClientAPIChan   chan messages.FromClientAPI  	transportController transport.Controller -	federator           federation.Federator +	federator           *federation.Federator  	emailSender         email.Sender  	sentEmails          map[string]string  	processor           *processing.Processor diff --git a/internal/processing/common/common.go b/internal/processing/common/common.go index 28fadc2a6..5abf50674 100644 --- a/internal/processing/common/common.go +++ b/internal/processing/common/common.go @@ -30,7 +30,7 @@ import (  type Processor struct {  	state     *state.State  	converter *typeutils.Converter -	federator federation.Federator +	federator *federation.Federator  	filter    *visibility.Filter  } @@ -38,7 +38,7 @@ type Processor struct {  func New(  	state *state.State,  	converter *typeutils.Converter, -	federator federation.Federator, +	federator *federation.Federator,  	filter *visibility.Filter,  ) Processor {  	return Processor{ diff --git a/internal/processing/fedi/fedi.go b/internal/processing/fedi/fedi.go index 9fbcebefc..11be26a3e 100644 --- a/internal/processing/fedi/fedi.go +++ b/internal/processing/fedi/fedi.go @@ -26,13 +26,13 @@ import (  type Processor struct {  	state     *state.State -	federator federation.Federator +	federator *federation.Federator  	converter *typeutils.Converter  	filter    *visibility.Filter  }  // New returns a new fedi processor. -func New(state *state.State, converter *typeutils.Converter, federator federation.Federator, filter *visibility.Filter) Processor { +func New(state *state.State, converter *typeutils.Converter, federator *federation.Federator, filter *visibility.Filter) Processor {  	return Processor{  		state:     state,  		federator: federator, diff --git a/internal/processing/processor.go b/internal/processing/processor.go index 92c7974c7..a24683e69 100644 --- a/internal/processing/processor.go +++ b/internal/processing/processor.go @@ -127,7 +127,7 @@ func (p *Processor) Workers() *workers.Processor {  // NewProcessor returns a new Processor.  func NewProcessor(  	converter *typeutils.Converter, -	federator federation.Federator, +	federator *federation.Federator,  	oauthServer oauth.Server,  	mediaManager *mm.Manager,  	state *state.State, diff --git a/internal/processing/processor_test.go b/internal/processing/processor_test.go index 15d943e86..63d2c31fe 100644 --- a/internal/processing/processor_test.go +++ b/internal/processing/processor_test.go @@ -47,7 +47,7 @@ type ProcessingStandardTestSuite struct {  	typeconverter       *typeutils.Converter  	httpClient          *testrig.MockHTTPClient  	transportController transport.Controller -	federator           federation.Federator +	federator           *federation.Federator  	oauthServer         oauth.Server  	emailSender         email.Sender diff --git a/internal/processing/search/search.go b/internal/processing/search/search.go index a7b1d4ad3..5321cb89d 100644 --- a/internal/processing/search/search.go +++ b/internal/processing/search/search.go @@ -26,13 +26,13 @@ import (  type Processor struct {  	state     *state.State -	federator federation.Federator +	federator *federation.Federator  	converter *typeutils.Converter  	filter    *visibility.Filter  }  // New returns a new status processor. -func New(state *state.State, federator federation.Federator, converter *typeutils.Converter, filter *visibility.Filter) Processor { +func New(state *state.State, federator *federation.Federator, converter *typeutils.Converter, filter *visibility.Filter) Processor {  	return Processor{  		state:     state,  		federator: federator, diff --git a/internal/processing/status/status.go b/internal/processing/status/status.go index 432f945fc..28ea64542 100644 --- a/internal/processing/status/status.go +++ b/internal/processing/status/status.go @@ -28,7 +28,7 @@ import (  type Processor struct {  	state        *state.State -	federator    federation.Federator +	federator    *federation.Federator  	converter    *typeutils.Converter  	filter       *visibility.Filter  	formatter    *text.Formatter @@ -36,7 +36,7 @@ type Processor struct {  }  // New returns a new status processor. -func New(state *state.State, federator federation.Federator, converter *typeutils.Converter, filter *visibility.Filter, parseMention gtsmodel.ParseMentionFunc) Processor { +func New(state *state.State, federator *federation.Federator, converter *typeutils.Converter, filter *visibility.Filter, parseMention gtsmodel.ParseMentionFunc) Processor {  	return Processor{  		state:        state,  		federator:    federator, diff --git a/internal/processing/status/status_test.go b/internal/processing/status/status_test.go index 1f73530cb..0507df484 100644 --- a/internal/processing/status/status_test.go +++ b/internal/processing/status/status_test.go @@ -41,7 +41,7 @@ type StatusStandardTestSuite struct {  	storage       *storage.Driver  	state         state.State  	mediaManager  *media.Manager -	federator     federation.Federator +	federator     *federation.Federator  	// standard suite models  	testTokens       map[string]*gtsmodel.Token diff --git a/internal/processing/util.go b/internal/processing/util.go index 7aefe64fc..1ce67c616 100644 --- a/internal/processing/util.go +++ b/internal/processing/util.go @@ -30,7 +30,7 @@ import (  	"github.com/superseriousbusiness/gotosocial/internal/util"  ) -func GetParseMentionFunc(dbConn db.DB, federator federation.Federator) gtsmodel.ParseMentionFunc { +func GetParseMentionFunc(dbConn db.DB, federator *federation.Federator) gtsmodel.ParseMentionFunc {  	return func(ctx context.Context, targetAccount string, originAccountID string, statusID string) (*gtsmodel.Mention, error) {  		// get the origin account first since we'll need it to create the mention  		originAccount, err := dbConn.GetAccountByID(ctx, originAccountID) diff --git a/internal/processing/workers/federate.go b/internal/processing/workers/federate.go index a87a89fd2..80b01ca40 100644 --- a/internal/processing/workers/federate.go +++ b/internal/processing/workers/federate.go @@ -36,7 +36,7 @@ import (  type federate struct {  	// Embed federator to give access  	// to send and retrieve functions. -	federation.Federator +	*federation.Federator  	state     *state.State  	converter *typeutils.Converter  } diff --git a/internal/processing/workers/workers.go b/internal/processing/workers/workers.go index e512a36bf..02e2f3f5b 100644 --- a/internal/processing/workers/workers.go +++ b/internal/processing/workers/workers.go @@ -37,7 +37,7 @@ type Processor struct {  func New(  	state *state.State, -	federator federation.Federator, +	federator *federation.Federator,  	converter *typeutils.Converter,  	filter *visibility.Filter,  	emailSender email.Sender, diff --git a/internal/processing/workers/workers_test.go b/internal/processing/workers/workers_test.go index 5a7e645d6..5712180f5 100644 --- a/internal/processing/workers/workers_test.go +++ b/internal/processing/workers/workers_test.go @@ -47,7 +47,7 @@ type WorkersTestSuite struct {  	typeconverter       *typeutils.Converter  	httpClient          *testrig.MockHTTPClient  	transportController transport.Controller -	federator           federation.Federator +	federator           *federation.Federator  	oauthServer         oauth.Server  	emailSender         email.Sender diff --git a/internal/transport/transport_test.go b/internal/transport/transport_test.go index 9f4b13cce..c58c2a055 100644 --- a/internal/transport/transport_test.go +++ b/internal/transport/transport_test.go @@ -41,7 +41,7 @@ type TransportTestSuite struct {  	db           db.DB  	storage      *storage.Driver  	mediaManager *media.Manager -	federator    federation.Federator +	federator    *federation.Federator  	processor    *processing.Processor  	emailSender  email.Sender  	sentEmails   map[string]string diff --git a/testrig/federator.go b/testrig/federator.go index 4d3d111cc..8519d724c 100644 --- a/testrig/federator.go +++ b/testrig/federator.go @@ -26,6 +26,6 @@ import (  )  // NewTestFederator returns a federator with the given database and (mock!!) transport controller. -func NewTestFederator(state *state.State, tc transport.Controller, mediaManager *media.Manager) federation.Federator { +func NewTestFederator(state *state.State, tc transport.Controller, mediaManager *media.Manager) *federation.Federator {  	return federation.NewFederator(state, NewTestFederatingDB(state), tc, typeutils.NewConverter(state), mediaManager)  } diff --git a/testrig/processor.go b/testrig/processor.go index a30d183ed..4d4ba3d53 100644 --- a/testrig/processor.go +++ b/testrig/processor.go @@ -27,7 +27,7 @@ import (  )  // NewTestProcessor returns a Processor suitable for testing purposes -func NewTestProcessor(state *state.State, federator federation.Federator, emailSender email.Sender, mediaManager *media.Manager) *processing.Processor { +func NewTestProcessor(state *state.State, federator *federation.Federator, emailSender email.Sender, mediaManager *media.Manager) *processing.Processor {  	p := processing.NewProcessor(typeutils.NewConverter(state), federator, NewTestOauthServer(state.DB), mediaManager, state, emailSender)  	state.Workers.EnqueueClientAPI = p.Workers().EnqueueClientAPI  	state.Workers.EnqueueFediAPI = p.Workers().EnqueueFediAPI | 
