diff options
Diffstat (limited to 'internal/federation')
-rw-r--r-- | internal/federation/dereferencing/account.go | 42 | ||||
-rw-r--r-- | internal/federation/dereferencing/account_test.go | 18 | ||||
-rw-r--r-- | internal/federation/federatingactor_test.go | 2 | ||||
-rw-r--r-- | internal/federation/federatingdb/inbox.go | 20 | ||||
-rw-r--r-- | internal/federation/federatingdb/inbox_test.go | 21 |
5 files changed, 96 insertions, 7 deletions
diff --git a/internal/federation/dereferencing/account.go b/internal/federation/dereferencing/account.go index 0fda96bf4..6a633a54a 100644 --- a/internal/federation/dereferencing/account.go +++ b/internal/federation/dereferencing/account.go @@ -29,6 +29,7 @@ import ( "sync" "time" + "github.com/miekg/dns" "github.com/superseriousbusiness/activity/streams" "github.com/superseriousbusiness/activity/streams/vocab" "github.com/superseriousbusiness/gotosocial/internal/ap" @@ -197,10 +198,12 @@ func (d *deref) GetRemoteAccount(ctx context.Context, params GetRemoteAccountPar accountDomain = params.RemoteAccountHost } - // to save on remote calls: only webfinger if we don't have a remoteAccount yet, or if we haven't - // fingered the remote account for at least 2 days; don't finger instance accounts + // to save on remote calls, only webfinger if: + // - we don't know the remote account ActivityPub ID yet OR + // - we haven't found the account yet in some other way OR + // - we haven't webfingered the account for two days AND the account isn't an instance account var fingered time.Time - if foundAccount == nil || (foundAccount.LastWebfingeredAt.Before(time.Now().Add(webfingerInterval)) && !instanceAccount(foundAccount)) { + if params.RemoteAccountID == nil || foundAccount == nil || (foundAccount.LastWebfingeredAt.Before(time.Now().Add(webfingerInterval)) && !instanceAccount(foundAccount)) { accountDomain, params.RemoteAccountID, err = d.fingerRemoteAccount(ctx, params.RequestingUsername, params.RemoteAccountUsername, params.RemoteAccountHost) if err != nil { err = fmt.Errorf("GetRemoteAccount: error while fingering: %s", err) @@ -279,6 +282,37 @@ func (d *deref) GetRemoteAccount(ctx context.Context, params GetRemoteAccountPar } } + // if SharedInboxURI is nil, that means we don't know yet if this account has + // a shared inbox available for it, so we need to check this here + var sharedInboxChanged bool + if foundAccount.SharedInboxURI == nil { + // we need the accountable for this, so get it if we don't have it yet + if accountable == nil { + accountable, err = d.dereferenceAccountable(ctx, params.RequestingUsername, params.RemoteAccountID) + if err != nil { + err = fmt.Errorf("GetRemoteAccount: error dereferencing accountable: %s", err) + return + } + } + + // This can be: + // - an empty string (we know it doesn't have a shared inbox) OR + // - a string URL (we know it does a shared inbox). + // Set it either way! + var sharedInbox string + + if sharedInboxURI := ap.ExtractSharedInbox(accountable); sharedInboxURI != nil { + // only trust shared inbox if it has at least two domains, + // from the right, in common with the domain of the account + if dns.CompareDomainName(foundAccount.Domain, sharedInboxURI.Host) >= 2 { + sharedInbox = sharedInboxURI.String() + } + } + + sharedInboxChanged = true + foundAccount.SharedInboxURI = &sharedInbox + } + // make sure the account fields are populated before returning: // the caller might want to block until everything is loaded var fieldsChanged bool @@ -293,7 +327,7 @@ func (d *deref) GetRemoteAccount(ctx context.Context, params GetRemoteAccountPar foundAccount.LastWebfingeredAt = fingered } - if fieldsChanged || fingeredChanged { + if fieldsChanged || fingeredChanged || sharedInboxChanged { foundAccount.UpdatedAt = time.Now() foundAccount, err = d.db.UpdateAccount(ctx, foundAccount) if err != nil { diff --git a/internal/federation/dereferencing/account_test.go b/internal/federation/dereferencing/account_test.go index 77ebb7cac..4f1a83a96 100644 --- a/internal/federation/dereferencing/account_test.go +++ b/internal/federation/dereferencing/account_test.go @@ -101,6 +101,24 @@ func (suite *AccountTestSuite) TestDereferenceLocalAccountAsRemoteURL() { suite.Empty(fetchedAccount.Domain) } +func (suite *AccountTestSuite) TestDereferenceLocalAccountAsRemoteURLNoSharedInboxYet() { + fetchingAccount := suite.testAccounts["local_account_1"] + targetAccount := suite.testAccounts["local_account_2"] + + targetAccount.SharedInboxURI = nil + if _, err := suite.db.UpdateAccount(context.Background(), targetAccount); err != nil { + suite.FailNow(err.Error()) + } + + fetchedAccount, err := suite.dereferencer.GetRemoteAccount(context.Background(), dereferencing.GetRemoteAccountParams{ + RequestingUsername: fetchingAccount.Username, + RemoteAccountID: testrig.URLMustParse(targetAccount.URI), + }) + suite.NoError(err) + suite.NotNil(fetchedAccount) + suite.Empty(fetchedAccount.Domain) +} + func (suite *AccountTestSuite) TestDereferenceLocalAccountAsUsername() { fetchingAccount := suite.testAccounts["local_account_1"] targetAccount := suite.testAccounts["local_account_2"] diff --git a/internal/federation/federatingactor_test.go b/internal/federation/federatingactor_test.go index bab38abe2..46a392d70 100644 --- a/internal/federation/federatingactor_test.go +++ b/internal/federation/federatingactor_test.go @@ -117,7 +117,7 @@ func (suite *FederatingActorTestSuite) TestSendRemoteFollower() { // because we added 1 remote follower for zork, there should be a url in sentMessage var sent [][]byte if !testrig.WaitFor(func() bool { - sentI, ok := httpClient.SentMessages.Load(testRemoteAccount.InboxURI) + sentI, ok := httpClient.SentMessages.Load(*testRemoteAccount.SharedInboxURI) if ok { sent, ok = sentI.([][]byte) if !ok { diff --git a/internal/federation/federatingdb/inbox.go b/internal/federation/federatingdb/inbox.go index b3b935bff..18f620bce 100644 --- a/internal/federation/federatingdb/inbox.go +++ b/internal/federation/federatingdb/inbox.go @@ -108,7 +108,15 @@ func (f *federatingDB) InboxesForIRI(c context.Context, iri *url.URL) (inboxIRIs follow.Account = followingAccount } - inboxIRI, err := url.Parse(follow.Account.InboxURI) + // deliver to a shared inbox if we have that option + var inbox string + if config.GetInstanceDeliverToSharedInboxes() && follow.Account.SharedInboxURI != nil && *follow.Account.SharedInboxURI != "" { + inbox = *follow.Account.SharedInboxURI + } else { + inbox = follow.Account.InboxURI + } + + inboxIRI, err := url.Parse(inbox) if err != nil { return nil, fmt.Errorf("error parsing inbox uri of following account %s: %s", follow.Account.InboxURI, err) } @@ -119,7 +127,15 @@ func (f *federatingDB) InboxesForIRI(c context.Context, iri *url.URL) (inboxIRIs // check if this is just an account IRI... if account, err := f.db.GetAccountByURI(c, iri.String()); err == nil { - inboxIRI, err := url.Parse(account.InboxURI) + // deliver to a shared inbox if we have that option + var inbox string + if config.GetInstanceDeliverToSharedInboxes() && account.SharedInboxURI != nil && *account.SharedInboxURI != "" { + inbox = *account.SharedInboxURI + } else { + inbox = account.InboxURI + } + + inboxIRI, err := url.Parse(inbox) if err != nil { return nil, fmt.Errorf("error parsing account inbox uri %s: %s", account.InboxURI, account.InboxURI) } diff --git a/internal/federation/federatingdb/inbox_test.go b/internal/federation/federatingdb/inbox_test.go index fb3b96944..dbf9d3c53 100644 --- a/internal/federation/federatingdb/inbox_test.go +++ b/internal/federation/federatingdb/inbox_test.go @@ -63,6 +63,27 @@ func (suite *InboxTestSuite) TestInboxesForAccountIRI() { suite.Contains(asStrings, suite.testAccounts["local_account_1"].InboxURI) } +func (suite *InboxTestSuite) TestInboxesForAccountIRIWithSharedInbox() { + ctx := context.Background() + testAccount := suite.testAccounts["local_account_1"] + sharedInbox := "http://some-inbox-iri/weeeeeeeeeeeee" + testAccount.SharedInboxURI = &sharedInbox + if _, err := suite.db.UpdateAccount(ctx, testAccount); err != nil { + suite.FailNow("error updating account") + } + + inboxIRIs, err := suite.federatingDB.InboxesForIRI(ctx, testrig.URLMustParse(testAccount.URI)) + suite.NoError(err) + + asStrings := []string{} + for _, i := range inboxIRIs { + asStrings = append(asStrings, i.String()) + } + + suite.Len(asStrings, 1) + suite.Contains(asStrings, "http://some-inbox-iri/weeeeeeeeeeeee") +} + func TestInboxTestSuite(t *testing.T) { suite.Run(t, &InboxTestSuite{}) } |