diff options
author | 2023-05-09 12:16:10 +0200 | |
---|---|---|
committer | 2023-05-09 11:16:10 +0100 | |
commit | 0e29f1f5bb68a48d9b837d7f4e0a16370734955b (patch) | |
tree | f08d203ec8ca8aeea728e5251b1dc3956524b4f4 /internal/federation/dereferencing/account.go | |
parent | [chore/performance] Make sender multiplier configurable (#1750) (diff) | |
download | gotosocial-0e29f1f5bb68a48d9b837d7f4e0a16370734955b.tar.xz |
[feature] Enable federation in/out of profile PropertyValue fields (#1722)
Co-authored-by: kim <grufwub@gmail.com>
Co-authored-by: kim <89579420+NyaaaWhatsUpDoc@users.noreply.github.com>
Diffstat (limited to 'internal/federation/dereferencing/account.go')
-rw-r--r-- | internal/federation/dereferencing/account.go | 99 |
1 files changed, 73 insertions, 26 deletions
diff --git a/internal/federation/dereferencing/account.go b/internal/federation/dereferencing/account.go index 4795db733..b33f1d6fa 100644 --- a/internal/federation/dereferencing/account.go +++ b/internal/federation/dereferencing/account.go @@ -38,7 +38,7 @@ import ( "github.com/superseriousbusiness/gotosocial/internal/transport" ) -func (d *deref) GetAccountByURI(ctx context.Context, requestUser string, uri *url.URL, block bool) (*gtsmodel.Account, error) { +func (d *deref) GetAccountByURI(ctx context.Context, requestUser string, uri *url.URL) (*gtsmodel.Account, error) { var ( account *gtsmodel.Account uriStr = uri.String() @@ -70,11 +70,11 @@ func (d *deref) GetAccountByURI(ctx context.Context, requestUser string, uri *ur ID: id.NewULID(), Domain: uri.Host, URI: uriStr, - }, false, true) + }, d.defaultFetchLatest, false) } // Try to update existing account model - enriched, err := d.enrichAccount(ctx, requestUser, uri, account, false, block) + enriched, err := d.enrichAccount(ctx, requestUser, uri, account, d.defaultFetchLatest, false) if err != nil { log.Errorf(ctx, "error enriching remote account: %v", err) return account, nil // fall back to returning existing @@ -83,7 +83,7 @@ func (d *deref) GetAccountByURI(ctx context.Context, requestUser string, uri *ur return enriched, nil } -func (d *deref) GetAccountByUsernameDomain(ctx context.Context, requestUser string, username string, domain string, block bool) (*gtsmodel.Account, error) { +func (d *deref) GetAccountByUsernameDomain(ctx context.Context, requestUser string, username string, domain string) (*gtsmodel.Account, error) { if domain == config.GetHost() || domain == config.GetAccountDomain() { // We do local lookups using an empty domain, // else it will fail the db search below. @@ -99,19 +99,24 @@ func (d *deref) GetAccountByUsernameDomain(ctx context.Context, requestUser stri if account == nil { // Check for failed local lookup. if domain == "" { - return nil, NewErrNotRetrievable(err) // will be db.ErrNoEntries + return nil, NewErrNotRetrievable(err) // wrapped err will be db.ErrNoEntries } // Create and pass-through a new bare-bones model for dereferencing. - return d.enrichAccount(ctx, requestUser, nil, >smodel.Account{ + account = >smodel.Account{ ID: id.NewULID(), Username: username, Domain: domain, - }, false, true) + } + + // There's no known account to fall back on, + // so return error if we can't enrich account. + return d.enrichAccount(ctx, requestUser, nil, account, d.defaultFetchLatest, false) } - // Try to update existing account model - enriched, err := d.enrichAccount(ctx, requestUser, nil, account, false, block) + // We knew about this account already; + // try to update existing account model. + enriched, err := d.enrichAccount(ctx, requestUser, nil, account, d.defaultFetchLatest, false) if err != nil { log.Errorf(ctx, "error enriching account from remote: %v", err) return account, nil // fall back to returning unchanged existing account model @@ -120,12 +125,62 @@ func (d *deref) GetAccountByUsernameDomain(ctx context.Context, requestUser stri return enriched, nil } -func (d *deref) UpdateAccount(ctx context.Context, requestUser string, account *gtsmodel.Account, force bool) (*gtsmodel.Account, error) { - return d.enrichAccount(ctx, requestUser, nil, account, force, false) +func (d *deref) RefreshAccount(ctx context.Context, requestUser string, accountable ap.Accountable, account *gtsmodel.Account) (*gtsmodel.Account, error) { + // To avoid unnecessarily refetching multiple times from remote, + // we can just pass in the Accountable object that we received, + // if it was defined. If not, fall back to default fetch func. + var f fetchLatest + if accountable != nil { + f = func( + _ context.Context, + _ transport.Transport, + _ *url.URL, + _ string, + ) (ap.Accountable, *gtsmodel.Account, error) { + return accountable, account, nil + } + } else { + f = d.defaultFetchLatest + } + + // Set 'force' to 'true' to always fetch latest media etc. + return d.enrichAccount(ctx, requestUser, nil, account, f, true) +} + +// fetchLatest defines a function for using a transport and uri to fetch the fetchLatest +// version of an account (and its AP representation) from a remote instance. +type fetchLatest func(ctx context.Context, transport transport.Transport, uri *url.URL, accountDomain string) (ap.Accountable, *gtsmodel.Account, error) + +// defaultFetchLatest deduplicates latest fetching code that is used in several +// different functions. It simply calls the remote uri using the given transport, +// parses a returned AP representation into an account, and then returns both. +func (d *deref) defaultFetchLatest(ctx context.Context, transport transport.Transport, uri *url.URL, accountDomain string) (ap.Accountable, *gtsmodel.Account, error) { + // Dereference this account to get the latest available. + apubAcc, err := d.dereferenceAccountable(ctx, transport, uri) + if err != nil { + return nil, nil, fmt.Errorf("error dereferencing account %s: %w", uri, err) + } + + // Convert the dereferenced AP account object to our GTS model. + latestAcc, err := d.typeConverter.ASRepresentationToAccount( + ctx, apubAcc, accountDomain, + ) + if err != nil { + return nil, nil, fmt.Errorf("error converting accountable to gts model for account %s: %w", uri, err) + } + + return apubAcc, latestAcc, nil } // enrichAccount will ensure the given account is the most up-to-date model of the account, re-webfingering and re-dereferencing if necessary. -func (d *deref) enrichAccount(ctx context.Context, requestUser string, uri *url.URL, account *gtsmodel.Account, force, block bool) (*gtsmodel.Account, error) { +func (d *deref) enrichAccount( + ctx context.Context, + requestUser string, + uri *url.URL, + account *gtsmodel.Account, + f fetchLatest, + force bool, +) (*gtsmodel.Account, error) { if account.IsLocal() { // Can't update local accounts. return account, nil @@ -205,18 +260,10 @@ func (d *deref) enrichAccount(ctx context.Context, requestUser string, uri *url. d.startHandshake(requestUser, uri) defer d.stopHandshake(requestUser, uri) - // Dereference this account to get the latest available. - apubAcc, err := d.dereferenceAccountable(ctx, transport, uri) - if err != nil { - return nil, fmt.Errorf("enrichAccount: error dereferencing account %s: %w", uri, err) - } - - // Convert the dereferenced AP account object to our GTS model. - latestAcc, err := d.typeConverter.ASRepresentationToAccount( - ctx, apubAcc, account.Domain, - ) + // Fetch latest version of the account, dereferencing if necessary. + apubAcc, latestAcc, err := f(ctx, transport, uri, account.Domain) if err != nil { - return nil, fmt.Errorf("enrichAccount: error converting accountable to gts model for account %s: %w", uri, err) + return nil, fmt.Errorf("enrichAccount: error calling fetchLatest function: %w", err) } if account.Username == "" { @@ -256,11 +303,11 @@ func (d *deref) enrichAccount(ctx context.Context, requestUser string, uri *url. latestAcc.ID = account.ID latestAcc.FetchedAt = time.Now() - // Use the existing account media attachments by default. + // Reuse the existing account media attachments by default. latestAcc.AvatarMediaAttachmentID = account.AvatarMediaAttachmentID latestAcc.HeaderMediaAttachmentID = account.HeaderMediaAttachmentID - if latestAcc.AvatarRemoteURL != account.AvatarRemoteURL { + if force || (latestAcc.AvatarRemoteURL != account.AvatarRemoteURL) { // Reset the avatar media ID (handles removed). latestAcc.AvatarMediaAttachmentID = "" @@ -281,7 +328,7 @@ func (d *deref) enrichAccount(ctx context.Context, requestUser string, uri *url. } } - if latestAcc.HeaderRemoteURL != account.HeaderRemoteURL { + if force || (latestAcc.HeaderRemoteURL != account.HeaderRemoteURL) { // Reset the header media ID (handles removed). latestAcc.HeaderMediaAttachmentID = "" |