[feature] serdes for moved/also_known_as (#2600)

* [feature] serdes for moved/also_known_as

* document `alsoKnownAs` and `movedTo` properties

* only implicitly populate AKA uris from DB for local accounts

* don't let remotes store more than 20 AKA uris to avoid shenanigans
This commit is contained in:
tobi
2024-02-06 10:45:46 +01:00
committed by GitHub
parent 3cc51d5072
commit aa396c78d3
11 changed files with 392 additions and 22 deletions

View File

@@ -198,7 +198,25 @@ func (c *Converter) ASRepresentationToAccount(ctx context.Context, accountable a
// TODO: FeaturedTagsURI
// TODO: alsoKnownAs
// Moved and AlsoKnownAsURIs,
// needed for account migrations.
movedToURI := ap.GetMovedTo(accountable)
if movedToURI != nil {
acct.MovedToURI = movedToURI.String()
}
alsoKnownAsURIs := ap.GetAlsoKnownAs(accountable)
for i, uri := range alsoKnownAsURIs {
// Don't store more than
// 20 AKA URIs for remotes,
// to prevent people playing
// silly buggers.
if i >= 20 {
break
}
acct.AlsoKnownAsURIs = append(acct.AlsoKnownAsURIs, uri.String())
}
// Extract account public key and verify ownership to account.
pkey, pkeyURL, pkeyOwnerID, err := ap.ExtractPublicKey(accountable)

View File

@@ -146,6 +146,7 @@ func (suite *ASToInternalTestSuite) TestParseGargron() {
acct, err := suite.typeconverter.ASRepresentationToAccount(context.Background(), rep, "")
suite.NoError(err)
suite.Equal("https://mastodon.social/inbox", *acct.SharedInboxURI)
suite.Equal([]string{"https://tooting.ai/users/Gargron"}, acct.AlsoKnownAsURIs)
suite.Equal(int64(1458086400), acct.CreatedAt.Unix())
}

View File

@@ -171,7 +171,30 @@ func (c *Converter) AccountToAS(ctx context.Context, a *gtsmodel.Account) (vocab
// alsoKnownAs
// Required for Move activity.
// TODO: NOT IMPLEMENTED **YET** -- this needs to be added as an activitypub extension to https://github.com/go-fed/activity, see https://github.com/go-fed/activity/tree/master/astool
if l := len(a.AlsoKnownAsURIs); l != 0 {
alsoKnownAsURIs := make([]*url.URL, l)
for i, rawURL := range a.AlsoKnownAsURIs {
uri, err := url.Parse(rawURL)
if err != nil {
return nil, err
}
alsoKnownAsURIs[i] = uri
}
ap.SetAlsoKnownAs(person, alsoKnownAsURIs)
}
// movedTo
// Required for Move activity.
if a.MovedToURI != "" {
movedTo, err := url.Parse(a.MovedToURI)
if err != nil {
return nil, err
}
ap.SetMovedTo(person, movedTo)
}
// publicKey
// Required for signatures.

View File

@@ -138,6 +138,72 @@ func (suite *InternalToASTestSuite) TestAccountToASWithFields() {
}`, trimmed)
}
func (suite *InternalToASTestSuite) TestAccountToASAliasedAndMoved() {
testAccount := &gtsmodel.Account{}
*testAccount = *suite.testAccounts["local_account_1"] // take zork for this test
ctx := context.Background()
// Suppose zork has moved account to turtle.
testAccount.AlsoKnownAsURIs = []string{"http://localhost:8080/users/1happyturtle"}
testAccount.MovedToURI = "http://localhost:8080/users/1happyturtle"
if err := suite.state.DB.UpdateAccount(ctx,
testAccount,
"also_known_as_uris",
"moved_to_uri",
); err != nil {
suite.FailNow(err.Error())
}
asPerson, err := suite.typeconverter.AccountToAS(context.Background(), testAccount)
suite.NoError(err)
ser, err := ap.Serialize(asPerson)
suite.NoError(err)
bytes, err := json.MarshalIndent(ser, "", " ")
suite.NoError(err)
// trim off everything up to 'alsoKnownAs';
// this is necessary because the order of multiple 'context' entries is not determinate
trimmed := strings.Split(string(bytes), "\"alsoKnownAs\"")[1]
suite.Equal(`: [
"http://localhost:8080/users/1happyturtle"
],
"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,
"movedTo": "http://localhost:8080/users/1happyturtle",
"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",
"tag": [],
"type": "Person",
"url": "http://localhost:8080/@the_mighty_zork"
}`, trimmed)
}
func (suite *InternalToASTestSuite) TestAccountToASWithOneField() {
testAccount := &gtsmodel.Account{}
*testAccount = *suite.testAccounts["local_account_2"]