mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2026-01-08 08:03:15 -06:00
[feature] Allow delivery to sharedInboxes where possible (#847)
* update Activity * add instance-deliver-to-shared-inboxes setting * update activity version again * add SharedInboxURI field to accounts * serdes for endpoints/sharedInbox * deliver to sharedInbox if one is available * update tests * only assign shared inbox if shared domain * look for shared inbox if currently nil * go fmt * finger to get params.RemoteAccountID if necessary * make comments clearer * compare dns more consistently
This commit is contained in:
parent
eb1bb8b1b3
commit
69a193dae5
69 changed files with 2212 additions and 32 deletions
|
|
@ -23,6 +23,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/miekg/dns"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/ap"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/db"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
|
|
@ -156,6 +157,19 @@ func (c *converter) ASRepresentationToAccount(ctx context.Context, accountable a
|
|||
acct.InboxURI = accountable.GetActivityStreamsInbox().GetIRI().String()
|
||||
}
|
||||
|
||||
// SharedInboxURI
|
||||
if sharedInboxURI := ap.ExtractSharedInbox(accountable); sharedInboxURI != nil {
|
||||
var sharedInbox string
|
||||
|
||||
// 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(acct.Domain, sharedInboxURI.Host) >= 2 {
|
||||
sharedInbox = sharedInboxURI.String()
|
||||
}
|
||||
|
||||
acct.SharedInboxURI = &sharedInbox
|
||||
}
|
||||
|
||||
// OutboxURI
|
||||
if accountable.GetActivityStreamsOutbox() != nil && accountable.GetActivityStreamsOutbox().GetIRI() != nil {
|
||||
acct.OutboxURI = accountable.GetActivityStreamsOutbox().GetIRI().String()
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ func (suite *ASToInternalTestSuite) TestParsePerson() {
|
|||
suite.Equal("https://unknown-instance.com/users/brand_new_person/following", acct.FollowingURI)
|
||||
suite.Equal("https://unknown-instance.com/users/brand_new_person/followers", acct.FollowersURI)
|
||||
suite.Equal("https://unknown-instance.com/users/brand_new_person/inbox", acct.InboxURI)
|
||||
suite.Nil(acct.SharedInboxURI)
|
||||
suite.Equal("https://unknown-instance.com/users/brand_new_person/outbox", acct.OutboxURI)
|
||||
suite.Equal("https://unknown-instance.com/users/brand_new_person/collections/featured", acct.FeaturedCollectionURI)
|
||||
suite.Equal("brand_new_person", acct.Username)
|
||||
|
|
@ -56,6 +57,28 @@ func (suite *ASToInternalTestSuite) TestParsePerson() {
|
|||
suite.False(*acct.Locked)
|
||||
}
|
||||
|
||||
func (suite *ASToInternalTestSuite) TestParsePersonWithSharedInbox() {
|
||||
testPerson := suite.testPeople["https://turnip.farm/users/turniplover6969"]
|
||||
|
||||
acct, err := suite.typeconverter.ASRepresentationToAccount(context.Background(), testPerson, "", false)
|
||||
suite.NoError(err)
|
||||
|
||||
suite.Equal("https://turnip.farm/users/turniplover6969", acct.URI)
|
||||
suite.Equal("https://turnip.farm/users/turniplover6969/following", acct.FollowingURI)
|
||||
suite.Equal("https://turnip.farm/users/turniplover6969/followers", acct.FollowersURI)
|
||||
suite.Equal("https://turnip.farm/users/turniplover6969/inbox", acct.InboxURI)
|
||||
suite.Equal("https://turnip.farm/sharedInbox", *acct.SharedInboxURI)
|
||||
suite.Equal("https://turnip.farm/users/turniplover6969/outbox", acct.OutboxURI)
|
||||
suite.Equal("https://turnip.farm/users/turniplover6969/collections/featured", acct.FeaturedCollectionURI)
|
||||
suite.Equal("turniplover6969", acct.Username)
|
||||
suite.Equal("Turnip Lover 6969", acct.DisplayName)
|
||||
suite.Equal("I just think they're neat", acct.Note)
|
||||
suite.Equal("https://turnip.farm/@turniplover6969", acct.URL)
|
||||
suite.True(*acct.Discoverable)
|
||||
suite.Equal("https://turnip.farm/users/turniplover6969#main-key", acct.PublicKeyURI)
|
||||
suite.False(*acct.Locked)
|
||||
}
|
||||
|
||||
func (suite *ASToInternalTestSuite) TestParsePublicStatus() {
|
||||
m := make(map[string]interface{})
|
||||
err := json.Unmarshal([]byte(publicStatusActivityJson), &m)
|
||||
|
|
@ -109,6 +132,8 @@ func (suite *ASToInternalTestSuite) TestParseGargron() {
|
|||
acct, err := suite.typeconverter.ASRepresentationToAccount(context.Background(), rep, "", false)
|
||||
suite.NoError(err)
|
||||
|
||||
suite.Equal("https://mastodon.social/inbox", *acct.SharedInboxURI)
|
||||
|
||||
fmt.Printf("%+v", acct)
|
||||
// TODO: write assertions here, rn we're just eyeballing the output
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,6 +85,21 @@ func (c *converter) AccountToAS(ctx context.Context, a *gtsmodel.Account) (vocab
|
|||
inboxProp.SetIRI(inboxURI)
|
||||
person.SetActivityStreamsInbox(inboxProp)
|
||||
|
||||
// shared inbox -- only add this if we know for sure it has one
|
||||
if a.SharedInboxURI != nil && *a.SharedInboxURI != "" {
|
||||
sharedInboxURI, err := url.Parse(*a.SharedInboxURI)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
endpointsProp := streams.NewActivityStreamsEndpointsProperty()
|
||||
endpoints := streams.NewActivityStreamsEndpoints()
|
||||
sharedInboxProp := streams.NewActivityStreamsSharedInboxProperty()
|
||||
sharedInboxProp.SetIRI(sharedInboxURI)
|
||||
endpoints.SetActivityStreamsSharedInbox(sharedInboxProp)
|
||||
endpointsProp.AppendActivityStreamsEndpoints(endpoints)
|
||||
person.SetActivityStreamsEndpoints(endpointsProp)
|
||||
}
|
||||
|
||||
// outbox
|
||||
// the activitypub outbox of this user for serving messages
|
||||
outboxURI, err := url.Parse(a.OutboxURI)
|
||||
|
|
|
|||
|
|
@ -52,6 +52,27 @@ func (suite *InternalToASTestSuite) TestAccountToAS() {
|
|||
suite.Equal(`:true,"featured":"http://localhost:8080/users/the_mighty_zork/collections/featured","followers":"http://localhost:8080/users/the_mighty_zork/followers","following":"http://localhost:8080/users/the_mighty_zork/following","icon":{"mediaType":"image/jpeg","type":"Image","url":"http://localhost:8080/fileserver/01F8MH1H7YV1Z7D2C8K2730QBF/avatar/original/01F8MH58A357CV5K7R7TJMSH6S.jpeg"},"id":"http://localhost:8080/users/the_mighty_zork","image":{"mediaType":"image/jpeg","type":"Image","url":"http://localhost:8080/fileserver/01F8MH1H7YV1Z7D2C8K2730QBF/header/original/01PFPMWK2FF0D9WMHEJHR07C3Q.jpeg"},"inbox":"http://localhost:8080/users/the_mighty_zork/inbox","manuallyApprovesFollowers":false,"name":"original zork (he/they)","outbox":"http://localhost:8080/users/the_mighty_zork/outbox","preferredUsername":"the_mighty_zork","publicKey":{"id":"http://localhost:8080/users/the_mighty_zork/main-key","owner":"http://localhost:8080/users/the_mighty_zork","publicKeyPem":"-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwXTcOAvM1Jiw5Ffpk0qn\nr0cwbNvFe/5zQ+Tp7tumK/ZnT37o7X0FUEXrxNi+dkhmeJ0gsaiN+JQGNUewvpSk\nPIAXKvi908aSfCGjs7bGlJCJCuDuL5d6m7hZnP9rt9fJc70GElPpG0jc9fXwlz7T\nlsPb2ecatmG05Y4jPwdC+oN4MNCv9yQzEvCVMzl76EJaM602kIHC1CISn0rDFmYd\n9rSN7XPlNJw1F6PbpJ/BWQ+pXHKw3OEwNTETAUNYiVGnZU+B7a7bZC9f6/aPbJuV\nt8Qmg+UnDvW1Y8gmfHnxaWG2f5TDBvCHmcYtucIZPLQD4trAozC4ryqlmCWQNKbt\n0wIDAQAB\n-----END PUBLIC KEY-----\n"},"summary":"\u003cp\u003ehey yo this is my profile!\u003c/p\u003e","type":"Person","url":"http://localhost:8080/@the_mighty_zork"}`, trimmed)
|
||||
}
|
||||
|
||||
func (suite *InternalToASTestSuite) TestAccountToASWithSharedInbox() {
|
||||
testAccount := suite.testAccounts["local_account_1"] // take zork for this test
|
||||
sharedInbox := "http://localhost:8080/sharedInbox"
|
||||
testAccount.SharedInboxURI = &sharedInbox
|
||||
|
||||
asPerson, err := suite.typeconverter.AccountToAS(context.Background(), testAccount)
|
||||
suite.NoError(err)
|
||||
|
||||
ser, err := streams.Serialize(asPerson)
|
||||
suite.NoError(err)
|
||||
|
||||
bytes, err := json.Marshal(ser)
|
||||
suite.NoError(err)
|
||||
|
||||
// trim off everything up to 'discoverable';
|
||||
// this is necessary because the order of multiple 'context' entries is not determinate
|
||||
trimmed := strings.Split(string(bytes), "\"discoverable\"")[1]
|
||||
|
||||
suite.Equal(`:true,"endpoints":{"sharedInbox":"http://localhost:8080/sharedInbox"},"featured":"http://localhost:8080/users/the_mighty_zork/collections/featured","followers":"http://localhost:8080/users/the_mighty_zork/followers","following":"http://localhost:8080/users/the_mighty_zork/following","icon":{"mediaType":"image/jpeg","type":"Image","url":"http://localhost:8080/fileserver/01F8MH1H7YV1Z7D2C8K2730QBF/avatar/original/01F8MH58A357CV5K7R7TJMSH6S.jpeg"},"id":"http://localhost:8080/users/the_mighty_zork","image":{"mediaType":"image/jpeg","type":"Image","url":"http://localhost:8080/fileserver/01F8MH1H7YV1Z7D2C8K2730QBF/header/original/01PFPMWK2FF0D9WMHEJHR07C3Q.jpeg"},"inbox":"http://localhost:8080/users/the_mighty_zork/inbox","manuallyApprovesFollowers":false,"name":"original zork (he/they)","outbox":"http://localhost:8080/users/the_mighty_zork/outbox","preferredUsername":"the_mighty_zork","publicKey":{"id":"http://localhost:8080/users/the_mighty_zork/main-key","owner":"http://localhost:8080/users/the_mighty_zork","publicKeyPem":"-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwXTcOAvM1Jiw5Ffpk0qn\nr0cwbNvFe/5zQ+Tp7tumK/ZnT37o7X0FUEXrxNi+dkhmeJ0gsaiN+JQGNUewvpSk\nPIAXKvi908aSfCGjs7bGlJCJCuDuL5d6m7hZnP9rt9fJc70GElPpG0jc9fXwlz7T\nlsPb2ecatmG05Y4jPwdC+oN4MNCv9yQzEvCVMzl76EJaM602kIHC1CISn0rDFmYd\n9rSN7XPlNJw1F6PbpJ/BWQ+pXHKw3OEwNTETAUNYiVGnZU+B7a7bZC9f6/aPbJuV\nt8Qmg+UnDvW1Y8gmfHnxaWG2f5TDBvCHmcYtucIZPLQD4trAozC4ryqlmCWQNKbt\n0wIDAQAB\n-----END PUBLIC KEY-----\n"},"summary":"\u003cp\u003ehey yo this is my profile!\u003c/p\u003e","type":"Person","url":"http://localhost:8080/@the_mighty_zork"}`, trimmed)
|
||||
}
|
||||
|
||||
func (suite *InternalToASTestSuite) TestOutboxToASCollection() {
|
||||
testAccount := suite.testAccounts["admin_account"]
|
||||
ctx := context.Background()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue