mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2025-12-30 01:56:15 -06:00
Merge branch 'main' into xvello/import-mutes
This commit is contained in:
commit
f30ab4bae4
328 changed files with 31571 additions and 115701 deletions
|
|
@ -540,8 +540,9 @@ func (suite *TypeUtilsTestSuite) GetProcessor() *processing.Processor {
|
|||
mediaManager := testrig.NewTestMediaManager(&suite.state)
|
||||
federator := testrig.NewTestFederator(&suite.state, transportController, mediaManager)
|
||||
emailSender := testrig.NewEmailSender("../../web/template/", nil)
|
||||
webPushSender := testrig.NewNoopWebPushSender()
|
||||
|
||||
processor := testrig.NewTestProcessor(&suite.state, federator, emailSender, mediaManager)
|
||||
processor := testrig.NewTestProcessor(&suite.state, federator, emailSender, webPushSender, mediaManager)
|
||||
testrig.StartWorkers(&suite.state, processor.Workers())
|
||||
|
||||
return processor
|
||||
|
|
|
|||
|
|
@ -36,12 +36,24 @@ import (
|
|||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/log"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/uris"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/util"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/util/xslices"
|
||||
)
|
||||
|
||||
// AccountToAS converts a gts model account into an activity streams person, suitable for federation
|
||||
func (c *Converter) AccountToAS(ctx context.Context, a *gtsmodel.Account) (vocab.ActivityStreamsPerson, error) {
|
||||
person := streams.NewActivityStreamsPerson()
|
||||
// AccountToAS converts a gts model account
|
||||
// into an activity streams person or service.
|
||||
func (c *Converter) AccountToAS(
|
||||
ctx context.Context,
|
||||
a *gtsmodel.Account,
|
||||
) (ap.Accountable, error) {
|
||||
// accountable is a service if this
|
||||
// is a bot account, otherwise a person.
|
||||
var accountable ap.Accountable
|
||||
if util.PtrOrZero(a.Bot) {
|
||||
accountable = streams.NewActivityStreamsService()
|
||||
} else {
|
||||
accountable = streams.NewActivityStreamsPerson()
|
||||
}
|
||||
|
||||
// id should be the activitypub URI of this user
|
||||
// something like https://example.org/users/example_user
|
||||
|
|
@ -51,7 +63,13 @@ func (c *Converter) AccountToAS(ctx context.Context, a *gtsmodel.Account) (vocab
|
|||
}
|
||||
idProp := streams.NewJSONLDIdProperty()
|
||||
idProp.SetIRI(profileIDURI)
|
||||
person.SetJSONLDId(idProp)
|
||||
accountable.SetJSONLDId(idProp)
|
||||
|
||||
// published
|
||||
// The moment when the account was created.
|
||||
publishedProp := streams.NewActivityStreamsPublishedProperty()
|
||||
publishedProp.Set(a.CreatedAt)
|
||||
accountable.SetActivityStreamsPublished(publishedProp)
|
||||
|
||||
// following
|
||||
// The URI for retrieving a list of accounts this user is following
|
||||
|
|
@ -61,7 +79,7 @@ func (c *Converter) AccountToAS(ctx context.Context, a *gtsmodel.Account) (vocab
|
|||
}
|
||||
followingProp := streams.NewActivityStreamsFollowingProperty()
|
||||
followingProp.SetIRI(followingURI)
|
||||
person.SetActivityStreamsFollowing(followingProp)
|
||||
accountable.SetActivityStreamsFollowing(followingProp)
|
||||
|
||||
// followers
|
||||
// The URI for retrieving a list of this user's followers
|
||||
|
|
@ -71,7 +89,7 @@ func (c *Converter) AccountToAS(ctx context.Context, a *gtsmodel.Account) (vocab
|
|||
}
|
||||
followersProp := streams.NewActivityStreamsFollowersProperty()
|
||||
followersProp.SetIRI(followersURI)
|
||||
person.SetActivityStreamsFollowers(followersProp)
|
||||
accountable.SetActivityStreamsFollowers(followersProp)
|
||||
|
||||
// inbox
|
||||
// the activitypub inbox of this user for accepting messages
|
||||
|
|
@ -81,7 +99,7 @@ func (c *Converter) AccountToAS(ctx context.Context, a *gtsmodel.Account) (vocab
|
|||
}
|
||||
inboxProp := streams.NewActivityStreamsInboxProperty()
|
||||
inboxProp.SetIRI(inboxURI)
|
||||
person.SetActivityStreamsInbox(inboxProp)
|
||||
accountable.SetActivityStreamsInbox(inboxProp)
|
||||
|
||||
// shared inbox -- only add this if we know for sure it has one
|
||||
if a.SharedInboxURI != nil && *a.SharedInboxURI != "" {
|
||||
|
|
@ -95,7 +113,7 @@ func (c *Converter) AccountToAS(ctx context.Context, a *gtsmodel.Account) (vocab
|
|||
sharedInboxProp.SetIRI(sharedInboxURI)
|
||||
endpoints.SetActivityStreamsSharedInbox(sharedInboxProp)
|
||||
endpointsProp.AppendActivityStreamsEndpoints(endpoints)
|
||||
person.SetActivityStreamsEndpoints(endpointsProp)
|
||||
accountable.SetActivityStreamsEndpoints(endpointsProp)
|
||||
}
|
||||
|
||||
// outbox
|
||||
|
|
@ -106,7 +124,7 @@ func (c *Converter) AccountToAS(ctx context.Context, a *gtsmodel.Account) (vocab
|
|||
}
|
||||
outboxProp := streams.NewActivityStreamsOutboxProperty()
|
||||
outboxProp.SetIRI(outboxURI)
|
||||
person.SetActivityStreamsOutbox(outboxProp)
|
||||
accountable.SetActivityStreamsOutbox(outboxProp)
|
||||
|
||||
// featured posts
|
||||
// Pinned posts.
|
||||
|
|
@ -116,7 +134,7 @@ func (c *Converter) AccountToAS(ctx context.Context, a *gtsmodel.Account) (vocab
|
|||
}
|
||||
featuredProp := streams.NewTootFeaturedProperty()
|
||||
featuredProp.SetIRI(featuredURI)
|
||||
person.SetTootFeatured(featuredProp)
|
||||
accountable.SetTootFeatured(featuredProp)
|
||||
|
||||
// featuredTags
|
||||
// NOT IMPLEMENTED
|
||||
|
|
@ -125,7 +143,7 @@ func (c *Converter) AccountToAS(ctx context.Context, a *gtsmodel.Account) (vocab
|
|||
// Used for Webfinger lookup. Must be unique on the domain, and must correspond to a Webfinger acct: URI.
|
||||
preferredUsernameProp := streams.NewActivityStreamsPreferredUsernameProperty()
|
||||
preferredUsernameProp.SetXMLSchemaString(a.Username)
|
||||
person.SetActivityStreamsPreferredUsername(preferredUsernameProp)
|
||||
accountable.SetActivityStreamsPreferredUsername(preferredUsernameProp)
|
||||
|
||||
// name
|
||||
// Used as profile display name.
|
||||
|
|
@ -135,14 +153,14 @@ func (c *Converter) AccountToAS(ctx context.Context, a *gtsmodel.Account) (vocab
|
|||
} else {
|
||||
nameProp.AppendXMLSchemaString(a.Username)
|
||||
}
|
||||
person.SetActivityStreamsName(nameProp)
|
||||
accountable.SetActivityStreamsName(nameProp)
|
||||
|
||||
// summary
|
||||
// Used as profile bio.
|
||||
if a.Note != "" {
|
||||
summaryProp := streams.NewActivityStreamsSummaryProperty()
|
||||
summaryProp.AppendXMLSchemaString(a.Note)
|
||||
person.SetActivityStreamsSummary(summaryProp)
|
||||
accountable.SetActivityStreamsSummary(summaryProp)
|
||||
}
|
||||
|
||||
// url
|
||||
|
|
@ -153,19 +171,19 @@ func (c *Converter) AccountToAS(ctx context.Context, a *gtsmodel.Account) (vocab
|
|||
}
|
||||
urlProp := streams.NewActivityStreamsUrlProperty()
|
||||
urlProp.AppendIRI(profileURL)
|
||||
person.SetActivityStreamsUrl(urlProp)
|
||||
accountable.SetActivityStreamsUrl(urlProp)
|
||||
|
||||
// manuallyApprovesFollowers
|
||||
// Will be shown as a locked account.
|
||||
manuallyApprovesFollowersProp := streams.NewActivityStreamsManuallyApprovesFollowersProperty()
|
||||
manuallyApprovesFollowersProp.Set(*a.Locked)
|
||||
person.SetActivityStreamsManuallyApprovesFollowers(manuallyApprovesFollowersProp)
|
||||
accountable.SetActivityStreamsManuallyApprovesFollowers(manuallyApprovesFollowersProp)
|
||||
|
||||
// discoverable
|
||||
// Will be shown in the profile directory.
|
||||
discoverableProp := streams.NewTootDiscoverableProperty()
|
||||
discoverableProp.Set(*a.Discoverable)
|
||||
person.SetTootDiscoverable(discoverableProp)
|
||||
accountable.SetTootDiscoverable(discoverableProp)
|
||||
|
||||
// devices
|
||||
// NOT IMPLEMENTED, probably won't implement
|
||||
|
|
@ -183,7 +201,7 @@ func (c *Converter) AccountToAS(ctx context.Context, a *gtsmodel.Account) (vocab
|
|||
alsoKnownAsURIs[i] = uri
|
||||
}
|
||||
|
||||
ap.SetAlsoKnownAs(person, alsoKnownAsURIs)
|
||||
ap.SetAlsoKnownAs(accountable, alsoKnownAsURIs)
|
||||
}
|
||||
|
||||
// movedTo
|
||||
|
|
@ -194,7 +212,7 @@ func (c *Converter) AccountToAS(ctx context.Context, a *gtsmodel.Account) (vocab
|
|||
return nil, err
|
||||
}
|
||||
|
||||
ap.SetMovedTo(person, movedTo)
|
||||
ap.SetMovedTo(accountable, movedTo)
|
||||
}
|
||||
|
||||
// publicKey
|
||||
|
|
@ -235,7 +253,7 @@ func (c *Converter) AccountToAS(ctx context.Context, a *gtsmodel.Account) (vocab
|
|||
publicKeyProp.AppendW3IDSecurityV1PublicKey(publicKey)
|
||||
|
||||
// set the public key property on the Person
|
||||
person.SetW3IDSecurityV1PublicKey(publicKeyProp)
|
||||
accountable.SetW3IDSecurityV1PublicKey(publicKeyProp)
|
||||
|
||||
// tags
|
||||
tagProp := streams.NewActivityStreamsTagProperty()
|
||||
|
|
@ -263,7 +281,7 @@ func (c *Converter) AccountToAS(ctx context.Context, a *gtsmodel.Account) (vocab
|
|||
// tag -- hashtags
|
||||
// TODO
|
||||
|
||||
person.SetActivityStreamsTag(tagProp)
|
||||
accountable.SetActivityStreamsTag(tagProp)
|
||||
|
||||
// attachment
|
||||
// Used for profile fields.
|
||||
|
|
@ -284,7 +302,7 @@ func (c *Converter) AccountToAS(ctx context.Context, a *gtsmodel.Account) (vocab
|
|||
attachmentProp.AppendSchemaPropertyValue(propertyValue)
|
||||
}
|
||||
|
||||
person.SetActivityStreamsAttachment(attachmentProp)
|
||||
accountable.SetActivityStreamsAttachment(attachmentProp)
|
||||
}
|
||||
|
||||
// endpoints
|
||||
|
|
@ -320,7 +338,7 @@ func (c *Converter) AccountToAS(ctx context.Context, a *gtsmodel.Account) (vocab
|
|||
iconImage.SetActivityStreamsUrl(avatarURLProperty)
|
||||
|
||||
iconProperty.AppendActivityStreamsImage(iconImage)
|
||||
person.SetActivityStreamsIcon(iconProperty)
|
||||
accountable.SetActivityStreamsIcon(iconProperty)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -354,20 +372,32 @@ func (c *Converter) AccountToAS(ctx context.Context, a *gtsmodel.Account) (vocab
|
|||
headerImage.SetActivityStreamsUrl(headerURLProperty)
|
||||
|
||||
headerProperty.AppendActivityStreamsImage(headerImage)
|
||||
person.SetActivityStreamsImage(headerProperty)
|
||||
accountable.SetActivityStreamsImage(headerProperty)
|
||||
}
|
||||
}
|
||||
|
||||
return person, nil
|
||||
return accountable, nil
|
||||
}
|
||||
|
||||
// AccountToASMinimal converts a gts model account into an activity streams person, suitable for federation.
|
||||
// AccountToASMinimal converts a gts model account
|
||||
// into an activity streams person or service.
|
||||
//
|
||||
// The returned account will just have the Type, Username, PublicKey, and ID properties set. This is
|
||||
// suitable for serving to requesters to whom we want to give as little information as possible because
|
||||
// we don't trust them (yet).
|
||||
func (c *Converter) AccountToASMinimal(ctx context.Context, a *gtsmodel.Account) (vocab.ActivityStreamsPerson, error) {
|
||||
person := streams.NewActivityStreamsPerson()
|
||||
// The returned account will just have the Type, Username,
|
||||
// PublicKey, and ID properties set. This is suitable for
|
||||
// serving to requesters to whom we want to give as little
|
||||
// information as possible because we don't trust them (yet).
|
||||
func (c *Converter) AccountToASMinimal(
|
||||
ctx context.Context,
|
||||
a *gtsmodel.Account,
|
||||
) (ap.Accountable, error) {
|
||||
// accountable is a service if this
|
||||
// is a bot account, otherwise a person.
|
||||
var accountable ap.Accountable
|
||||
if util.PtrOrZero(a.Bot) {
|
||||
accountable = streams.NewActivityStreamsService()
|
||||
} else {
|
||||
accountable = streams.NewActivityStreamsPerson()
|
||||
}
|
||||
|
||||
// id should be the activitypub URI of this user
|
||||
// something like https://example.org/users/example_user
|
||||
|
|
@ -377,13 +407,13 @@ func (c *Converter) AccountToASMinimal(ctx context.Context, a *gtsmodel.Account)
|
|||
}
|
||||
idProp := streams.NewJSONLDIdProperty()
|
||||
idProp.SetIRI(profileIDURI)
|
||||
person.SetJSONLDId(idProp)
|
||||
accountable.SetJSONLDId(idProp)
|
||||
|
||||
// preferredUsername
|
||||
// Used for Webfinger lookup. Must be unique on the domain, and must correspond to a Webfinger acct: URI.
|
||||
preferredUsernameProp := streams.NewActivityStreamsPreferredUsernameProperty()
|
||||
preferredUsernameProp.SetXMLSchemaString(a.Username)
|
||||
person.SetActivityStreamsPreferredUsername(preferredUsernameProp)
|
||||
accountable.SetActivityStreamsPreferredUsername(preferredUsernameProp)
|
||||
|
||||
// publicKey
|
||||
// Required for signatures.
|
||||
|
|
@ -423,9 +453,9 @@ func (c *Converter) AccountToASMinimal(ctx context.Context, a *gtsmodel.Account)
|
|||
publicKeyProp.AppendW3IDSecurityV1PublicKey(publicKey)
|
||||
|
||||
// set the public key property on the Person
|
||||
person.SetW3IDSecurityV1PublicKey(publicKeyProp)
|
||||
accountable.SetW3IDSecurityV1PublicKey(publicKeyProp)
|
||||
|
||||
return person, nil
|
||||
return accountable, nil
|
||||
}
|
||||
|
||||
// StatusToAS converts a gts model status into an ActivityStreams Statusable implementation, suitable for federation
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import (
|
|||
"github.com/superseriousbusiness/gotosocial/internal/ap"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/db"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/util"
|
||||
"github.com/superseriousbusiness/gotosocial/testrig"
|
||||
)
|
||||
|
||||
|
|
@ -38,10 +39,10 @@ func (suite *InternalToASTestSuite) TestAccountToAS() {
|
|||
testAccount := >smodel.Account{}
|
||||
*testAccount = *suite.testAccounts["local_account_1"] // take zork for this test
|
||||
|
||||
asPerson, err := suite.typeconverter.AccountToAS(context.Background(), testAccount)
|
||||
accountable, err := suite.typeconverter.AccountToAS(context.Background(), testAccount)
|
||||
suite.NoError(err)
|
||||
|
||||
ser, err := ap.Serialize(asPerson)
|
||||
ser, err := ap.Serialize(accountable)
|
||||
suite.NoError(err)
|
||||
|
||||
bytes, err := json.MarshalIndent(ser, "", " ")
|
||||
|
|
@ -86,6 +87,7 @@ func (suite *InternalToASTestSuite) TestAccountToAS() {
|
|||
"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"
|
||||
},
|
||||
"published": "2022-05-20T11:09:18Z",
|
||||
"summary": "\u003cp\u003ehey yo this is my profile!\u003c/p\u003e",
|
||||
"tag": [],
|
||||
"type": "Person",
|
||||
|
|
@ -93,14 +95,80 @@ func (suite *InternalToASTestSuite) TestAccountToAS() {
|
|||
}`, string(bytes))
|
||||
}
|
||||
|
||||
func (suite *InternalToASTestSuite) TestAccountToASBot() {
|
||||
testAccount := >smodel.Account{}
|
||||
*testAccount = *suite.testAccounts["local_account_1"] // take zork for this test
|
||||
|
||||
// Update zork to be a bot.
|
||||
testAccount.Bot = util.Ptr(true)
|
||||
if err := suite.state.DB.UpdateAccount(context.Background(), testAccount); err != nil {
|
||||
suite.FailNow(err.Error())
|
||||
}
|
||||
|
||||
accountable, err := suite.typeconverter.AccountToAS(context.Background(), testAccount)
|
||||
suite.NoError(err)
|
||||
|
||||
ser, err := ap.Serialize(accountable)
|
||||
suite.NoError(err)
|
||||
|
||||
bytes, err := json.MarshalIndent(ser, "", " ")
|
||||
suite.NoError(err)
|
||||
|
||||
suite.Equal(`{
|
||||
"@context": [
|
||||
"https://w3id.org/security/v1",
|
||||
"https://www.w3.org/ns/activitystreams",
|
||||
{
|
||||
"discoverable": "toot:discoverable",
|
||||
"featured": {
|
||||
"@id": "toot:featured",
|
||||
"@type": "@id"
|
||||
},
|
||||
"manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
|
||||
"toot": "http://joinmastodon.org/ns#"
|
||||
}
|
||||
],
|
||||
"discoverable": 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.jpg"
|
||||
},
|
||||
"id": "http://localhost:8080/users/the_mighty_zork",
|
||||
"image": {
|
||||
"mediaType": "image/jpeg",
|
||||
"type": "Image",
|
||||
"url": "http://localhost:8080/fileserver/01F8MH1H7YV1Z7D2C8K2730QBF/header/original/01PFPMWK2FF0D9WMHEJHR07C3Q.jpg"
|
||||
},
|
||||
"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"
|
||||
},
|
||||
"published": "2022-05-20T11:09:18Z",
|
||||
"summary": "\u003cp\u003ehey yo this is my profile!\u003c/p\u003e",
|
||||
"tag": [],
|
||||
"type": "Service",
|
||||
"url": "http://localhost:8080/@the_mighty_zork"
|
||||
}`, string(bytes))
|
||||
}
|
||||
|
||||
func (suite *InternalToASTestSuite) TestAccountToASWithFields() {
|
||||
testAccount := >smodel.Account{}
|
||||
*testAccount = *suite.testAccounts["local_account_2"]
|
||||
|
||||
asPerson, err := suite.typeconverter.AccountToAS(context.Background(), testAccount)
|
||||
accountable, err := suite.typeconverter.AccountToAS(context.Background(), testAccount)
|
||||
suite.NoError(err)
|
||||
|
||||
ser, err := ap.Serialize(asPerson)
|
||||
ser, err := ap.Serialize(accountable)
|
||||
suite.NoError(err)
|
||||
|
||||
bytes, err := json.MarshalIndent(ser, "", " ")
|
||||
|
|
@ -150,6 +218,7 @@ func (suite *InternalToASTestSuite) TestAccountToASWithFields() {
|
|||
"owner": "http://localhost:8080/users/1happyturtle",
|
||||
"publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtTc6Jpg6LrRPhVQG4KLz\n2+YqEUUtZPd4YR+TKXuCnwEG9ZNGhgP046xa9h3EWzrZXaOhXvkUQgJuRqPrAcfN\nvc8jBHV2xrUeD8pu/MWKEabAsA/tgCv3nUC47HQ3/c12aHfYoPz3ufWsGGnrkhci\nv8PaveJ3LohO5vjCn1yZ00v6osMJMViEZvZQaazyE9A8FwraIexXabDpoy7tkHRg\nA1fvSkg4FeSG1XMcIz2NN7xyUuFACD+XkuOk7UqzRd4cjPUPLxiDwIsTlcgGOd3E\nUFMWVlPxSGjY2hIKa3lEHytaYK9IMYdSuyCsJshd3/yYC9LqxZY2KdlKJ80VOVyh\nyQIDAQAB\n-----END PUBLIC KEY-----\n"
|
||||
},
|
||||
"published": "2022-06-04T13:12:00Z",
|
||||
"summary": "\u003cp\u003ei post about things that concern me\u003c/p\u003e",
|
||||
"tag": [],
|
||||
"type": "Person",
|
||||
|
|
@ -174,10 +243,10 @@ func (suite *InternalToASTestSuite) TestAccountToASAliasedAndMoved() {
|
|||
suite.FailNow(err.Error())
|
||||
}
|
||||
|
||||
asPerson, err := suite.typeconverter.AccountToAS(context.Background(), testAccount)
|
||||
accountable, err := suite.typeconverter.AccountToAS(context.Background(), testAccount)
|
||||
suite.NoError(err)
|
||||
|
||||
ser, err := ap.Serialize(asPerson)
|
||||
ser, err := ap.Serialize(accountable)
|
||||
suite.NoError(err)
|
||||
|
||||
bytes, err := json.MarshalIndent(ser, "", " ")
|
||||
|
|
@ -231,6 +300,7 @@ func (suite *InternalToASTestSuite) TestAccountToASAliasedAndMoved() {
|
|||
"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"
|
||||
},
|
||||
"published": "2022-05-20T11:09:18Z",
|
||||
"summary": "\u003cp\u003ehey yo this is my profile!\u003c/p\u003e",
|
||||
"tag": [],
|
||||
"type": "Person",
|
||||
|
|
@ -243,10 +313,10 @@ func (suite *InternalToASTestSuite) TestAccountToASWithOneField() {
|
|||
*testAccount = *suite.testAccounts["local_account_2"]
|
||||
testAccount.Fields = testAccount.Fields[0:1] // Take only one field.
|
||||
|
||||
asPerson, err := suite.typeconverter.AccountToAS(context.Background(), testAccount)
|
||||
accountable, err := suite.typeconverter.AccountToAS(context.Background(), testAccount)
|
||||
suite.NoError(err)
|
||||
|
||||
ser, err := ap.Serialize(asPerson)
|
||||
ser, err := ap.Serialize(accountable)
|
||||
suite.NoError(err)
|
||||
|
||||
bytes, err := json.MarshalIndent(ser, "", " ")
|
||||
|
|
@ -292,6 +362,7 @@ func (suite *InternalToASTestSuite) TestAccountToASWithOneField() {
|
|||
"owner": "http://localhost:8080/users/1happyturtle",
|
||||
"publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtTc6Jpg6LrRPhVQG4KLz\n2+YqEUUtZPd4YR+TKXuCnwEG9ZNGhgP046xa9h3EWzrZXaOhXvkUQgJuRqPrAcfN\nvc8jBHV2xrUeD8pu/MWKEabAsA/tgCv3nUC47HQ3/c12aHfYoPz3ufWsGGnrkhci\nv8PaveJ3LohO5vjCn1yZ00v6osMJMViEZvZQaazyE9A8FwraIexXabDpoy7tkHRg\nA1fvSkg4FeSG1XMcIz2NN7xyUuFACD+XkuOk7UqzRd4cjPUPLxiDwIsTlcgGOd3E\nUFMWVlPxSGjY2hIKa3lEHytaYK9IMYdSuyCsJshd3/yYC9LqxZY2KdlKJ80VOVyh\nyQIDAQAB\n-----END PUBLIC KEY-----\n"
|
||||
},
|
||||
"published": "2022-06-04T13:12:00Z",
|
||||
"summary": "\u003cp\u003ei post about things that concern me\u003c/p\u003e",
|
||||
"tag": [],
|
||||
"type": "Person",
|
||||
|
|
@ -304,10 +375,10 @@ func (suite *InternalToASTestSuite) TestAccountToASWithEmoji() {
|
|||
*testAccount = *suite.testAccounts["local_account_1"] // take zork for this test
|
||||
testAccount.Emojis = []*gtsmodel.Emoji{suite.testEmojis["rainbow"]}
|
||||
|
||||
asPerson, err := suite.typeconverter.AccountToAS(context.Background(), testAccount)
|
||||
accountable, err := suite.typeconverter.AccountToAS(context.Background(), testAccount)
|
||||
suite.NoError(err)
|
||||
|
||||
ser, err := ap.Serialize(asPerson)
|
||||
ser, err := ap.Serialize(accountable)
|
||||
suite.NoError(err)
|
||||
|
||||
bytes, err := json.MarshalIndent(ser, "", " ")
|
||||
|
|
@ -353,6 +424,7 @@ func (suite *InternalToASTestSuite) TestAccountToASWithEmoji() {
|
|||
"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"
|
||||
},
|
||||
"published": "2022-05-20T11:09:18Z",
|
||||
"summary": "\u003cp\u003ehey yo this is my profile!\u003c/p\u003e",
|
||||
"tag": {
|
||||
"icon": {
|
||||
|
|
@ -376,10 +448,10 @@ func (suite *InternalToASTestSuite) TestAccountToASWithSharedInbox() {
|
|||
sharedInbox := "http://localhost:8080/sharedInbox"
|
||||
testAccount.SharedInboxURI = &sharedInbox
|
||||
|
||||
asPerson, err := suite.typeconverter.AccountToAS(context.Background(), testAccount)
|
||||
accountable, err := suite.typeconverter.AccountToAS(context.Background(), testAccount)
|
||||
suite.NoError(err)
|
||||
|
||||
ser, err := ap.Serialize(asPerson)
|
||||
ser, err := ap.Serialize(accountable)
|
||||
suite.NoError(err)
|
||||
|
||||
bytes, err := json.MarshalIndent(ser, "", " ")
|
||||
|
|
@ -427,6 +499,7 @@ func (suite *InternalToASTestSuite) TestAccountToASWithSharedInbox() {
|
|||
"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"
|
||||
},
|
||||
"published": "2022-05-20T11:09:18Z",
|
||||
"summary": "\u003cp\u003ehey yo this is my profile!\u003c/p\u003e",
|
||||
"tag": [],
|
||||
"type": "Person",
|
||||
|
|
|
|||
|
|
@ -616,6 +616,11 @@ func (c *Converter) AccountToAdminAPIAccount(ctx context.Context, a *gtsmodel.Ac
|
|||
}
|
||||
|
||||
func (c *Converter) AppToAPIAppSensitive(ctx context.Context, a *gtsmodel.Application) (*apimodel.Application, error) {
|
||||
vapidKeyPair, err := c.state.DB.GetVAPIDKeyPair(ctx)
|
||||
if err != nil {
|
||||
return nil, gtserror.Newf("error getting VAPID public key: %w", err)
|
||||
}
|
||||
|
||||
return &apimodel.Application{
|
||||
ID: a.ID,
|
||||
Name: a.Name,
|
||||
|
|
@ -623,6 +628,7 @@ func (c *Converter) AppToAPIAppSensitive(ctx context.Context, a *gtsmodel.Applic
|
|||
RedirectURI: a.RedirectURI,
|
||||
ClientID: a.ClientID,
|
||||
ClientSecret: a.ClientSecret,
|
||||
VapidKey: vapidKeyPair.Public,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
|
@ -1878,6 +1884,12 @@ func (c *Converter) InstanceToAPIV2Instance(ctx context.Context, i *gtsmodel.Ins
|
|||
instance.Configuration.Emojis.EmojiSizeLimit = int(config.GetMediaEmojiLocalMaxSize()) // #nosec G115 -- Already validated.
|
||||
instance.Configuration.OIDCEnabled = config.GetOIDCEnabled()
|
||||
|
||||
vapidKeyPair, err := c.state.DB.GetVAPIDKeyPair(ctx)
|
||||
if err != nil {
|
||||
return nil, gtserror.Newf("error getting VAPID public key: %w", err)
|
||||
}
|
||||
instance.Configuration.VAPID.PublicKey = vapidKeyPair.Public
|
||||
|
||||
// registrations
|
||||
instance.Registrations.Enabled = config.GetAccountsRegistrationOpen()
|
||||
instance.Registrations.ApprovalRequired = true // always required
|
||||
|
|
@ -2985,3 +2997,36 @@ func (c *Converter) InteractionReqToAPIInteractionReq(
|
|||
URI: req.URI,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *Converter) WebPushSubscriptionToAPIWebPushSubscription(
|
||||
ctx context.Context,
|
||||
subscription *gtsmodel.WebPushSubscription,
|
||||
) (*apimodel.WebPushSubscription, error) {
|
||||
vapidKeyPair, err := c.state.DB.GetVAPIDKeyPair(ctx)
|
||||
if err != nil {
|
||||
return nil, gtserror.Newf("error getting VAPID key pair: %w", err)
|
||||
}
|
||||
|
||||
return &apimodel.WebPushSubscription{
|
||||
ID: subscription.ID,
|
||||
Endpoint: subscription.Endpoint,
|
||||
ServerKey: vapidKeyPair.Public,
|
||||
Alerts: apimodel.WebPushSubscriptionAlerts{
|
||||
Follow: subscription.NotificationFlags.Get(gtsmodel.NotificationFollow),
|
||||
FollowRequest: subscription.NotificationFlags.Get(gtsmodel.NotificationFollowRequest),
|
||||
Favourite: subscription.NotificationFlags.Get(gtsmodel.NotificationFavourite),
|
||||
Mention: subscription.NotificationFlags.Get(gtsmodel.NotificationMention),
|
||||
Reblog: subscription.NotificationFlags.Get(gtsmodel.NotificationReblog),
|
||||
Poll: subscription.NotificationFlags.Get(gtsmodel.NotificationPoll),
|
||||
Status: subscription.NotificationFlags.Get(gtsmodel.NotificationStatus),
|
||||
Update: subscription.NotificationFlags.Get(gtsmodel.NotificationUpdate),
|
||||
AdminSignup: subscription.NotificationFlags.Get(gtsmodel.NotificationAdminSignup),
|
||||
AdminReport: subscription.NotificationFlags.Get(gtsmodel.NotificationAdminReport),
|
||||
PendingFavourite: subscription.NotificationFlags.Get(gtsmodel.NotificationPendingFave),
|
||||
PendingReply: subscription.NotificationFlags.Get(gtsmodel.NotificationPendingReply),
|
||||
PendingReblog: subscription.NotificationFlags.Get(gtsmodel.NotificationPendingReblog),
|
||||
},
|
||||
Policy: apimodel.WebPushNotificationPolicyAll,
|
||||
Standard: true,
|
||||
}, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import (
|
|||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
|
@ -2061,6 +2062,13 @@ func (suite *InternalToFrontendTestSuite) TestInstanceV2ToFrontend() {
|
|||
b, err := json.MarshalIndent(instance, "", " ")
|
||||
suite.NoError(err)
|
||||
|
||||
// The VAPID public key changes from run to run.
|
||||
vapidKeyPair, err := suite.db.GetVAPIDKeyPair(ctx)
|
||||
if err != nil {
|
||||
suite.FailNow(err.Error())
|
||||
}
|
||||
s := strings.Replace(string(b), vapidKeyPair.Public, "VAPID_PUBLIC_KEY_PLACEHOLDER", 1)
|
||||
|
||||
suite.Equal(`{
|
||||
"domain": "localhost:8080",
|
||||
"account_domain": "localhost:8080",
|
||||
|
|
@ -2140,6 +2148,9 @@ func (suite *InternalToFrontendTestSuite) TestInstanceV2ToFrontend() {
|
|||
},
|
||||
"emojis": {
|
||||
"emoji_size_limit": 51200
|
||||
},
|
||||
"vapid": {
|
||||
"public_key": "VAPID_PUBLIC_KEY_PLACEHOLDER"
|
||||
}
|
||||
},
|
||||
"registrations": {
|
||||
|
|
@ -2184,7 +2195,7 @@ func (suite *InternalToFrontendTestSuite) TestInstanceV2ToFrontend() {
|
|||
"rules": [],
|
||||
"terms": "\u003cp\u003eThis is where a list of terms and conditions might go.\u003c/p\u003e\u003cp\u003eFor example:\u003c/p\u003e\u003cp\u003eIf you want to sign up on this instance, you oughta know that we:\u003c/p\u003e\u003col\u003e\u003cli\u003eWill sell your data to whoever offers.\u003c/li\u003e\u003cli\u003eSecure the server with password \u003ccode\u003epassword\u003c/code\u003e wherever possible.\u003c/li\u003e\u003c/ol\u003e",
|
||||
"terms_text": "This is where a list of terms and conditions might go.\n\nFor example:\n\nIf you want to sign up on this instance, you oughta know that we:\n\n1. Will sell your data to whoever offers.\n2. Secure the server with password `+"`"+`password`+"`"+` wherever possible."
|
||||
}`, string(b))
|
||||
}`, s)
|
||||
}
|
||||
|
||||
func (suite *InternalToFrontendTestSuite) TestEmojiToFrontend() {
|
||||
|
|
|
|||
|
|
@ -18,68 +18,45 @@
|
|||
package typeutils
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
|
||||
"github.com/superseriousbusiness/activity/pub"
|
||||
"github.com/superseriousbusiness/activity/streams"
|
||||
"github.com/superseriousbusiness/activity/streams/vocab"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/ap"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/id"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/log"
|
||||
"github.com/superseriousbusiness/gotosocial/internal/uris"
|
||||
)
|
||||
|
||||
// WrapPersonInUpdate ...
|
||||
func (c *Converter) WrapPersonInUpdate(person vocab.ActivityStreamsPerson, originAccount *gtsmodel.Account) (vocab.ActivityStreamsUpdate, error) {
|
||||
// WrapAccountableInUpdate wraps the given accountable
|
||||
// in an Update activity with the accountable as the object.
|
||||
//
|
||||
// The Update will be addressed to Public and bcc followers.
|
||||
func (c *Converter) WrapAccountableInUpdate(accountable ap.Accountable) (vocab.ActivityStreamsUpdate, error) {
|
||||
update := streams.NewActivityStreamsUpdate()
|
||||
|
||||
// set the actor
|
||||
actorURI, err := url.Parse(originAccount.URI)
|
||||
if err != nil {
|
||||
return nil, gtserror.Newf("error parsing url %s: %w", originAccount.URI, err)
|
||||
}
|
||||
actorProp := streams.NewActivityStreamsActorProperty()
|
||||
actorProp.AppendIRI(actorURI)
|
||||
update.SetActivityStreamsActor(actorProp)
|
||||
// Set actor IRI to this accountable's IRI.
|
||||
ap.AppendActorIRIs(update, ap.GetJSONLDId(accountable))
|
||||
|
||||
// set the ID
|
||||
newID, err := id.NewRandomULID()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Set the update ID
|
||||
updateURI := uris.GenerateURIForUpdate(ap.ExtractPreferredUsername(accountable), id.NewULID())
|
||||
ap.MustSet(ap.SetJSONLDIdStr, ap.WithJSONLDId(update), updateURI)
|
||||
|
||||
idString := uris.GenerateURIForUpdate(originAccount.Username, newID)
|
||||
idURI, err := url.Parse(idString)
|
||||
if err != nil {
|
||||
return nil, gtserror.Newf("error parsing url %s: %w", idString, err)
|
||||
}
|
||||
idProp := streams.NewJSONLDIdProperty()
|
||||
idProp.SetIRI(idURI)
|
||||
update.SetJSONLDId(idProp)
|
||||
|
||||
// set the person as the object here
|
||||
// Set the accountable as the object of the update.
|
||||
objectProp := streams.NewActivityStreamsObjectProperty()
|
||||
objectProp.AppendActivityStreamsPerson(person)
|
||||
switch t := accountable.(type) {
|
||||
case vocab.ActivityStreamsPerson:
|
||||
objectProp.AppendActivityStreamsPerson(t)
|
||||
case vocab.ActivityStreamsService:
|
||||
objectProp.AppendActivityStreamsService(t)
|
||||
default:
|
||||
log.Panicf(nil, "%T was neither person nor service", t)
|
||||
}
|
||||
update.SetActivityStreamsObject(objectProp)
|
||||
|
||||
// to should be public
|
||||
toURI, err := url.Parse(pub.PublicActivityPubIRI)
|
||||
if err != nil {
|
||||
return nil, gtserror.Newf("error parsing url %s: %w", pub.PublicActivityPubIRI, err)
|
||||
}
|
||||
toProp := streams.NewActivityStreamsToProperty()
|
||||
toProp.AppendIRI(toURI)
|
||||
update.SetActivityStreamsTo(toProp)
|
||||
// to should be public.
|
||||
ap.AppendTo(update, ap.PublicURI())
|
||||
|
||||
// bcc followers
|
||||
followersURI, err := url.Parse(originAccount.FollowersURI)
|
||||
if err != nil {
|
||||
return nil, gtserror.Newf("error parsing url %s: %w", originAccount.FollowersURI, err)
|
||||
}
|
||||
bccProp := streams.NewActivityStreamsBccProperty()
|
||||
bccProp.AppendIRI(followersURI)
|
||||
update.SetActivityStreamsBcc(bccProp)
|
||||
// bcc should be followers.
|
||||
ap.AppendBcc(update, ap.GetFollowers(accountable))
|
||||
|
||||
return update, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -139,6 +139,86 @@ func (suite *WrapTestSuite) TestWrapNoteInCreate() {
|
|||
}`, string(bytes))
|
||||
}
|
||||
|
||||
func (suite *WrapTestSuite) TestWrapAccountableInUpdate() {
|
||||
testAccount := suite.testAccounts["local_account_1"]
|
||||
|
||||
accountable, err := suite.typeconverter.AccountToAS(context.Background(), testAccount)
|
||||
if err != nil {
|
||||
suite.FailNow(err.Error())
|
||||
}
|
||||
|
||||
create, err := suite.typeconverter.WrapAccountableInUpdate(accountable)
|
||||
if err != nil {
|
||||
suite.FailNow(err.Error())
|
||||
}
|
||||
|
||||
createI, err := ap.Serialize(create)
|
||||
if err != nil {
|
||||
suite.FailNow(err.Error())
|
||||
}
|
||||
|
||||
// Get the ID as it's not determinate.
|
||||
createID := ap.GetJSONLDId(create)
|
||||
|
||||
bytes, err := json.MarshalIndent(createI, "", " ")
|
||||
if err != nil {
|
||||
suite.FailNow(err.Error())
|
||||
}
|
||||
|
||||
suite.Equal(`{
|
||||
"@context": [
|
||||
"https://w3id.org/security/v1",
|
||||
"https://www.w3.org/ns/activitystreams",
|
||||
{
|
||||
"discoverable": "toot:discoverable",
|
||||
"featured": {
|
||||
"@id": "toot:featured",
|
||||
"@type": "@id"
|
||||
},
|
||||
"manuallyApprovesFollowers": "as:manuallyApprovesFollowers",
|
||||
"toot": "http://joinmastodon.org/ns#"
|
||||
}
|
||||
],
|
||||
"actor": "http://localhost:8080/users/the_mighty_zork",
|
||||
"bcc": "http://localhost:8080/users/the_mighty_zork/followers",
|
||||
"id": "`+createID.String()+`",
|
||||
"object": {
|
||||
"discoverable": 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.jpg"
|
||||
},
|
||||
"id": "http://localhost:8080/users/the_mighty_zork",
|
||||
"image": {
|
||||
"mediaType": "image/jpeg",
|
||||
"type": "Image",
|
||||
"url": "http://localhost:8080/fileserver/01F8MH1H7YV1Z7D2C8K2730QBF/header/original/01PFPMWK2FF0D9WMHEJHR07C3Q.jpg"
|
||||
},
|
||||
"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"
|
||||
},
|
||||
"published": "2022-05-20T11:09:18Z",
|
||||
"summary": "\u003cp\u003ehey yo this is my profile!\u003c/p\u003e",
|
||||
"tag": [],
|
||||
"type": "Person",
|
||||
"url": "http://localhost:8080/@the_mighty_zork"
|
||||
},
|
||||
"to": "https://www.w3.org/ns/activitystreams#Public",
|
||||
"type": "Update"
|
||||
}`, string(bytes))
|
||||
}
|
||||
|
||||
func TestWrapTestSuite(t *testing.T) {
|
||||
suite.Run(t, new(WrapTestSuite))
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue