mirror of
https://github.com/superseriousbusiness/gotosocial
synced 2025-06-05 21:59:39 +02:00
[feature] Account alias / move API + db models (#2518)
* [feature] Account alias / move API + db models * go fmt * fix little cherry-pick issues * update error checking, formatting * add and use new util functions to simplify alias logic
This commit is contained in:
@@ -90,6 +90,7 @@ func (c *Converter) AccountToAPIAccountSensitive(ctx context.Context, a *gtsmode
|
||||
Note: a.NoteRaw,
|
||||
Fields: c.fieldsToAPIFields(a.FieldsRaw),
|
||||
FollowRequestsCount: frc,
|
||||
AlsoKnownAsURIs: a.AlsoKnownAsURIs,
|
||||
}
|
||||
|
||||
return apiAccount, nil
|
||||
@@ -111,27 +112,27 @@ func (c *Converter) AccountToAPIAccountPublic(ctx context.Context, a *gtsmodel.A
|
||||
|
||||
followersCount, err := c.state.DB.CountAccountFollowers(ctx, a.ID)
|
||||
if err != nil && !errors.Is(err, db.ErrNoEntries) {
|
||||
return nil, fmt.Errorf("AccountToAPIAccountPublic: error counting followers: %w", err)
|
||||
return nil, gtserror.Newf("error counting followers: %w", err)
|
||||
}
|
||||
|
||||
followingCount, err := c.state.DB.CountAccountFollows(ctx, a.ID)
|
||||
if err != nil && !errors.Is(err, db.ErrNoEntries) {
|
||||
return nil, fmt.Errorf("AccountToAPIAccountPublic: error counting following: %w", err)
|
||||
return nil, gtserror.Newf("error counting following: %w", err)
|
||||
}
|
||||
|
||||
statusesCount, err := c.state.DB.CountAccountStatuses(ctx, a.ID)
|
||||
if err != nil && !errors.Is(err, db.ErrNoEntries) {
|
||||
return nil, fmt.Errorf("AccountToAPIAccountPublic: error counting statuses: %w", err)
|
||||
return nil, gtserror.Newf("error counting statuses: %w", err)
|
||||
}
|
||||
|
||||
var lastStatusAt *string
|
||||
lastPosted, err := c.state.DB.GetAccountLastPosted(ctx, a.ID, false)
|
||||
if err != nil && !errors.Is(err, db.ErrNoEntries) {
|
||||
return nil, fmt.Errorf("AccountToAPIAccountPublic: error counting statuses: %w", err)
|
||||
return nil, gtserror.Newf("error getting last posted: %w", err)
|
||||
}
|
||||
|
||||
if !lastPosted.IsZero() {
|
||||
lastStatusAt = func() *string { t := util.FormatISO8601(lastPosted); return &t }()
|
||||
lastStatusAt = util.Ptr(util.FormatISO8601(lastPosted))
|
||||
}
|
||||
|
||||
// Profile media + nice extras:
|
||||
@@ -180,7 +181,7 @@ func (c *Converter) AccountToAPIAccountPublic(ctx context.Context, a *gtsmodel.A
|
||||
// de-punify it just in case.
|
||||
d, err := util.DePunify(a.Domain)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("AccountToAPIAccountPublic: error de-punifying domain %s for account id %s: %w", a.Domain, a.ID, err)
|
||||
return nil, gtserror.Newf("error de-punifying domain %s for account id %s: %w", a.Domain, a.ID, err)
|
||||
}
|
||||
|
||||
acct = a.Username + "@" + d
|
||||
@@ -191,7 +192,7 @@ func (c *Converter) AccountToAPIAccountPublic(ctx context.Context, a *gtsmodel.A
|
||||
if !a.IsInstance() {
|
||||
user, err := c.state.DB.GetUserByAccountID(ctx, a.ID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("AccountToAPIAccountPublic: error getting user from database for account id %s: %w", a.ID, err)
|
||||
return nil, gtserror.Newf("error getting user from database for account id %s: %w", a.ID, err)
|
||||
}
|
||||
|
||||
switch {
|
||||
@@ -207,6 +208,15 @@ func (c *Converter) AccountToAPIAccountPublic(ctx context.Context, a *gtsmodel.A
|
||||
acct = a.Username // omit domain
|
||||
}
|
||||
|
||||
// Populate moved.
|
||||
var moved *apimodel.Account
|
||||
if a.MovedTo != nil {
|
||||
moved, err = c.AccountToAPIAccountPublic(ctx, a.MovedTo)
|
||||
if err != nil {
|
||||
log.Errorf(ctx, "error converting account movedTo: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Remaining properties are simple and
|
||||
// can be populated directly below.
|
||||
|
||||
@@ -235,6 +245,7 @@ func (c *Converter) AccountToAPIAccountPublic(ctx context.Context, a *gtsmodel.A
|
||||
CustomCSS: a.CustomCSS,
|
||||
EnableRSS: *a.EnableRSS,
|
||||
Role: role,
|
||||
Moved: moved,
|
||||
}
|
||||
|
||||
// Bodge default avatar + header in,
|
||||
|
@@ -69,6 +69,105 @@ func (suite *InternalToFrontendTestSuite) TestAccountToFrontend() {
|
||||
}`, string(b))
|
||||
}
|
||||
|
||||
func (suite *InternalToFrontendTestSuite) TestAccountToFrontendAliasedAndMoved() {
|
||||
// Take zork for this test.
|
||||
var testAccount = new(gtsmodel.Account)
|
||||
*testAccount = *suite.testAccounts["local_account_1"]
|
||||
|
||||
// Update zork to indicate that he's moved to turtle.
|
||||
// This is a bit weird but it's just for this test.
|
||||
movedTo := suite.testAccounts["local_account_2"]
|
||||
testAccount.MovedToURI = movedTo.URI
|
||||
testAccount.AlsoKnownAsURIs = []string{movedTo.URI}
|
||||
|
||||
if err := suite.state.DB.UpdateAccount(context.Background(), testAccount, "moved_to_uri"); err != nil {
|
||||
suite.FailNow(err.Error())
|
||||
}
|
||||
|
||||
apiAccount, err := suite.typeconverter.AccountToAPIAccountSensitive(context.Background(), testAccount)
|
||||
suite.NoError(err)
|
||||
suite.NotNil(apiAccount)
|
||||
|
||||
// moved and also_known_as_uris
|
||||
// should both be set now.
|
||||
b, err := json.MarshalIndent(apiAccount, "", " ")
|
||||
suite.NoError(err)
|
||||
suite.Equal(`{
|
||||
"id": "01F8MH1H7YV1Z7D2C8K2730QBF",
|
||||
"username": "the_mighty_zork",
|
||||
"acct": "the_mighty_zork",
|
||||
"display_name": "original zork (he/they)",
|
||||
"locked": false,
|
||||
"discoverable": true,
|
||||
"bot": false,
|
||||
"created_at": "2022-05-20T11:09:18.000Z",
|
||||
"note": "\u003cp\u003ehey yo this is my profile!\u003c/p\u003e",
|
||||
"url": "http://localhost:8080/@the_mighty_zork",
|
||||
"avatar": "http://localhost:8080/fileserver/01F8MH1H7YV1Z7D2C8K2730QBF/avatar/original/01F8MH58A357CV5K7R7TJMSH6S.jpg",
|
||||
"avatar_static": "http://localhost:8080/fileserver/01F8MH1H7YV1Z7D2C8K2730QBF/avatar/small/01F8MH58A357CV5K7R7TJMSH6S.jpg",
|
||||
"header": "http://localhost:8080/fileserver/01F8MH1H7YV1Z7D2C8K2730QBF/header/original/01PFPMWK2FF0D9WMHEJHR07C3Q.jpg",
|
||||
"header_static": "http://localhost:8080/fileserver/01F8MH1H7YV1Z7D2C8K2730QBF/header/small/01PFPMWK2FF0D9WMHEJHR07C3Q.jpg",
|
||||
"followers_count": 2,
|
||||
"following_count": 2,
|
||||
"statuses_count": 7,
|
||||
"last_status_at": "2023-12-10T09:24:00.000Z",
|
||||
"emojis": [],
|
||||
"fields": [],
|
||||
"source": {
|
||||
"privacy": "public",
|
||||
"sensitive": false,
|
||||
"language": "en",
|
||||
"status_content_type": "text/plain",
|
||||
"note": "hey yo this is my profile!",
|
||||
"fields": [],
|
||||
"follow_requests_count": 0,
|
||||
"also_known_as_uris": [
|
||||
"http://localhost:8080/users/1happyturtle"
|
||||
]
|
||||
},
|
||||
"enable_rss": true,
|
||||
"role": {
|
||||
"name": "user"
|
||||
},
|
||||
"moved": {
|
||||
"id": "01F8MH5NBDF2MV7CTC4Q5128HF",
|
||||
"username": "1happyturtle",
|
||||
"acct": "1happyturtle",
|
||||
"display_name": "happy little turtle :3",
|
||||
"locked": true,
|
||||
"discoverable": false,
|
||||
"bot": false,
|
||||
"created_at": "2022-06-04T13:12:00.000Z",
|
||||
"note": "\u003cp\u003ei post about things that concern me\u003c/p\u003e",
|
||||
"url": "http://localhost:8080/@1happyturtle",
|
||||
"avatar": "",
|
||||
"avatar_static": "",
|
||||
"header": "http://localhost:8080/assets/default_header.png",
|
||||
"header_static": "http://localhost:8080/assets/default_header.png",
|
||||
"followers_count": 1,
|
||||
"following_count": 1,
|
||||
"statuses_count": 8,
|
||||
"last_status_at": "2021-07-28T08:40:37.000Z",
|
||||
"emojis": [],
|
||||
"fields": [
|
||||
{
|
||||
"name": "should you follow me?",
|
||||
"value": "maybe!",
|
||||
"verified_at": null
|
||||
},
|
||||
{
|
||||
"name": "age",
|
||||
"value": "120",
|
||||
"verified_at": null
|
||||
}
|
||||
],
|
||||
"role": {
|
||||
"name": "user"
|
||||
}
|
||||
}
|
||||
}`, string(b))
|
||||
}
|
||||
|
||||
func (suite *InternalToFrontendTestSuite) TestAccountToFrontendWithEmojiStruct() {
|
||||
testAccount := >smodel.Account{}
|
||||
*testAccount = *suite.testAccounts["local_account_1"] // take zork for this test
|
||||
|
Reference in New Issue
Block a user