mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2025-04-16 22:34:05 +00:00
fiddle with it! (that's what she said)
This commit is contained in:
parent
39339dc832
commit
1bfc1aa7d1
10 changed files with 218 additions and 199 deletions
|
@ -46,22 +46,48 @@ type accountDB struct {
|
|||
state *state.State
|
||||
}
|
||||
|
||||
func (a *accountDB) getAccountsBy(
|
||||
ctx context.Context,
|
||||
index string,
|
||||
keys []string,
|
||||
load func([]string) ([]*gtsmodel.Account, error),
|
||||
getKey func(*gtsmodel.Account) string,
|
||||
) ([]*gtsmodel.Account, error) {
|
||||
// Load all input account keys via cache loader callback.
|
||||
accounts, err := a.state.Caches.DB.Account.LoadIDs(index, keys, load)
|
||||
func (a *accountDB) GetAccountByID(ctx context.Context, id string) (*gtsmodel.Account, error) {
|
||||
return a.getAccount(
|
||||
ctx,
|
||||
"ID",
|
||||
func(account *gtsmodel.Account) error {
|
||||
return a.db.NewSelect().
|
||||
Model(account).
|
||||
Where("? = ?", bun.Ident("account.id"), id).
|
||||
Scan(ctx)
|
||||
},
|
||||
id,
|
||||
)
|
||||
}
|
||||
|
||||
func (a *accountDB) GetAccountsByIDs(ctx context.Context, ids []string) ([]*gtsmodel.Account, error) {
|
||||
// Load all input account IDs via cache loader callback.
|
||||
accounts, err := a.state.Caches.DB.Account.LoadIDs("ID",
|
||||
ids,
|
||||
func(uncached []string) ([]*gtsmodel.Account, error) {
|
||||
// Preallocate expected length of uncached accounts.
|
||||
accounts := make([]*gtsmodel.Account, 0, len(uncached))
|
||||
|
||||
// Perform database query scanning
|
||||
// the remaining (uncached) account IDs.
|
||||
if err := a.db.NewSelect().
|
||||
Model(&accounts).
|
||||
Where("? IN (?)", bun.Ident("id"), bun.In(uncached)).
|
||||
Scan(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return accounts, nil
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Reorder the statuses by their
|
||||
// keys to ensure in correct order.
|
||||
xslices.OrderBy(accounts, keys, getKey)
|
||||
// IDs to ensure in correct order.
|
||||
getID := func(a *gtsmodel.Account) string { return a.ID }
|
||||
xslices.OrderBy(accounts, ids, getID)
|
||||
|
||||
if gtscontext.Barebones(ctx) {
|
||||
// no need to fully populate.
|
||||
|
@ -81,75 +107,6 @@ func (a *accountDB) getAccountsBy(
|
|||
return accounts, nil
|
||||
}
|
||||
|
||||
func (a *accountDB) getOneAccountBy(
|
||||
ctx context.Context,
|
||||
index string,
|
||||
key string,
|
||||
load func([]string) ([]*gtsmodel.Account, error),
|
||||
) (*gtsmodel.Account, error) {
|
||||
// Get all accounts with the given key.
|
||||
accounts, err := a.getAccountsBy(
|
||||
ctx,
|
||||
index,
|
||||
[]string{key},
|
||||
load,
|
||||
func(a *gtsmodel.Account) string { return key },
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Ensure we have one
|
||||
// and only one account.
|
||||
l := len(accounts)
|
||||
if l == 0 {
|
||||
return nil, db.ErrNoEntries
|
||||
}
|
||||
if l > 1 {
|
||||
return nil, db.ErrMultipleEntries
|
||||
}
|
||||
|
||||
return accounts[0], nil
|
||||
}
|
||||
|
||||
func (a *accountDB) GetAccountByID(ctx context.Context, id string) (*gtsmodel.Account, error) {
|
||||
return a.getAccount(
|
||||
ctx,
|
||||
"ID",
|
||||
func(account *gtsmodel.Account) error {
|
||||
return a.db.NewSelect().
|
||||
Model(account).
|
||||
Where("? = ?", bun.Ident("account.id"), id).
|
||||
Scan(ctx)
|
||||
},
|
||||
id,
|
||||
)
|
||||
}
|
||||
|
||||
func (a *accountDB) GetAccountsByIDs(ctx context.Context, ids []string) ([]*gtsmodel.Account, error) {
|
||||
return a.getAccountsBy(
|
||||
ctx,
|
||||
"ID",
|
||||
ids,
|
||||
func(uncached []string) ([]*gtsmodel.Account, error) {
|
||||
// Preallocate expected length of uncached accounts.
|
||||
accounts := make([]*gtsmodel.Account, 0, len(uncached))
|
||||
|
||||
// Perform database query scanning
|
||||
// the remaining (uncached) accounts.
|
||||
if err := a.db.NewSelect().
|
||||
Model(&accounts).
|
||||
Where("? IN (?)", bun.Ident("account.id"), bun.In(uncached)).
|
||||
Scan(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return accounts, nil
|
||||
},
|
||||
func(a *gtsmodel.Account) string { return a.ID },
|
||||
)
|
||||
}
|
||||
|
||||
func (a *accountDB) GetAccountByURI(ctx context.Context, uri string) (*gtsmodel.Account, error) {
|
||||
return a.getAccount(
|
||||
ctx,
|
||||
|
@ -165,51 +122,45 @@ func (a *accountDB) GetAccountByURI(ctx context.Context, uri string) (*gtsmodel.
|
|||
}
|
||||
|
||||
func (a *accountDB) GetOneAccountByURL(ctx context.Context, url string) (*gtsmodel.Account, error) {
|
||||
return a.getOneAccountBy(
|
||||
ctx,
|
||||
"URL",
|
||||
url,
|
||||
func(uncached []string) ([]*gtsmodel.Account, error) {
|
||||
// Preallocate expected length of uncached accounts.
|
||||
accounts := make([]*gtsmodel.Account, 0, len(uncached))
|
||||
// Select IDs of all
|
||||
// accounts with this url.
|
||||
var ids []string
|
||||
if err := a.db.NewSelect().
|
||||
TableExpr("? AS ?", bun.Ident("accounts"), bun.Ident("account")).
|
||||
Column("account.id").
|
||||
Where("? = ?", bun.Ident("account.url"), url).
|
||||
Scan(ctx, &ids); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Perform database query scanning
|
||||
// the remaining (uncached) accounts.
|
||||
if err := a.db.NewSelect().
|
||||
Model(&accounts).
|
||||
Where("? IN (?)", bun.Ident("account.url"), bun.In(uncached)).
|
||||
Scan(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Ensure exactly one account.
|
||||
if len(ids) == 0 {
|
||||
return nil, db.ErrNoEntries
|
||||
}
|
||||
if len(ids) > 1 {
|
||||
return nil, db.ErrMultipleEntries
|
||||
}
|
||||
|
||||
return accounts, nil
|
||||
},
|
||||
)
|
||||
return a.GetAccountByID(ctx, ids[0])
|
||||
}
|
||||
|
||||
func (a *accountDB) GetAccountsByURL(ctx context.Context, url string) ([]*gtsmodel.Account, error) {
|
||||
// Get all accounts with the given URL.
|
||||
return a.getAccountsBy(
|
||||
ctx,
|
||||
"ID",
|
||||
[]string{url},
|
||||
func(uncached []string) ([]*gtsmodel.Account, error) {
|
||||
// Preallocate expected length of uncached accounts.
|
||||
accounts := make([]*gtsmodel.Account, 0, len(uncached))
|
||||
// Select IDs of all
|
||||
// accounts with this url.
|
||||
var ids []string
|
||||
if err := a.db.NewSelect().
|
||||
TableExpr("? AS ?", bun.Ident("accounts"), bun.Ident("account")).
|
||||
Column("account.id").
|
||||
Where("? = ?", bun.Ident("account.url"), url).
|
||||
Scan(ctx, &ids); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Perform database query scanning
|
||||
// the remaining (uncached) accounts.
|
||||
if err := a.db.NewSelect().
|
||||
Model(&accounts).
|
||||
Where("? IN (?)", bun.Ident("account.url"), bun.In(uncached)).
|
||||
Scan(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(ids) == 0 {
|
||||
return nil, db.ErrNoEntries
|
||||
}
|
||||
|
||||
return accounts, nil
|
||||
},
|
||||
func(a *gtsmodel.Account) string { return a.URL },
|
||||
)
|
||||
return a.GetAccountsByIDs(ctx, ids)
|
||||
}
|
||||
|
||||
func (a *accountDB) GetAccountByUsernameDomain(ctx context.Context, username string, domain string) (*gtsmodel.Account, error) {
|
||||
|
@ -261,50 +212,50 @@ func (a *accountDB) GetAccountByPubkeyID(ctx context.Context, id string) (*gtsmo
|
|||
)
|
||||
}
|
||||
|
||||
func (a *accountDB) GetOneAccountByInboxURI(ctx context.Context, uri string) (*gtsmodel.Account, error) {
|
||||
return a.getOneAccountBy(
|
||||
ctx,
|
||||
"InboxURI",
|
||||
uri,
|
||||
func(uncached []string) ([]*gtsmodel.Account, error) {
|
||||
// Preallocate expected length of uncached accounts.
|
||||
accounts := make([]*gtsmodel.Account, 0, len(uncached))
|
||||
func (a *accountDB) GetOneAccountByInboxURI(ctx context.Context, inboxURI string) (*gtsmodel.Account, error) {
|
||||
// Select IDs of all accounts
|
||||
// with this inbox_uri.
|
||||
var ids []string
|
||||
if err := a.db.NewSelect().
|
||||
TableExpr("? AS ?", bun.Ident("accounts"), bun.Ident("account")).
|
||||
Column("account.id").
|
||||
Where("? = ?", bun.Ident("account.inbox_uri"), inboxURI).
|
||||
Scan(ctx, &ids); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Perform database query scanning
|
||||
// the remaining (uncached) accounts.
|
||||
if err := a.db.NewSelect().
|
||||
Model(&accounts).
|
||||
Where("? IN (?)", bun.Ident("account.inbox_uri"), bun.In(uncached)).
|
||||
Scan(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Ensure exactly one account.
|
||||
if len(ids) == 0 {
|
||||
return nil, db.ErrNoEntries
|
||||
}
|
||||
if len(ids) > 1 {
|
||||
return nil, db.ErrMultipleEntries
|
||||
}
|
||||
|
||||
return accounts, nil
|
||||
},
|
||||
)
|
||||
return a.GetAccountByID(ctx, ids[0])
|
||||
}
|
||||
|
||||
func (a *accountDB) GetOneAccountByOutboxURI(ctx context.Context, uri string) (*gtsmodel.Account, error) {
|
||||
return a.getOneAccountBy(
|
||||
ctx,
|
||||
"OutboxURI",
|
||||
uri,
|
||||
func(uncached []string) ([]*gtsmodel.Account, error) {
|
||||
// Preallocate expected length of uncached accounts.
|
||||
accounts := make([]*gtsmodel.Account, 0, len(uncached))
|
||||
func (a *accountDB) GetOneAccountByOutboxURI(ctx context.Context, outboxURI string) (*gtsmodel.Account, error) {
|
||||
// Select IDs of all accounts
|
||||
// with this outbox_uri.
|
||||
var ids []string
|
||||
if err := a.db.NewSelect().
|
||||
TableExpr("? AS ?", bun.Ident("accounts"), bun.Ident("account")).
|
||||
Column("account.id").
|
||||
Where("? = ?", bun.Ident("account.outbox_uri"), outboxURI).
|
||||
Scan(ctx, &ids); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Perform database query scanning
|
||||
// the remaining (uncached) accounts.
|
||||
if err := a.db.NewSelect().
|
||||
Model(&accounts).
|
||||
Where("? IN (?)", bun.Ident("account.outbox_uri"), bun.In(uncached)).
|
||||
Scan(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Ensure exactly one account.
|
||||
if len(ids) == 0 {
|
||||
return nil, db.ErrNoEntries
|
||||
}
|
||||
if len(ids) > 1 {
|
||||
return nil, db.ErrMultipleEntries
|
||||
}
|
||||
|
||||
return accounts, nil
|
||||
},
|
||||
)
|
||||
return a.GetAccountByID(ctx, ids[0])
|
||||
}
|
||||
|
||||
func (a *accountDB) GetInstanceAccount(ctx context.Context, domain string) (*gtsmodel.Account, error) {
|
||||
|
|
|
@ -199,9 +199,11 @@ func (f *Federator) AuthenticateFederatedRequest(ctx context.Context, requestedU
|
|||
}
|
||||
|
||||
// Dereference the account located at owner URI.
|
||||
// Use exact URI match, not URL match.
|
||||
pubKeyAuth.Owner, _, err = f.GetAccountByURI(ctx,
|
||||
requestedUsername,
|
||||
pubKeyAuth.OwnerURI,
|
||||
false,
|
||||
)
|
||||
if err != nil {
|
||||
if gtserror.StatusCode(err) == http.StatusGone {
|
||||
|
|
|
@ -89,14 +89,30 @@ func accountFresh(
|
|||
return !time.Now().After(staleAt)
|
||||
}
|
||||
|
||||
// GetAccountByURI will attempt to fetch an accounts by its URI, first checking the database. In the case of a newly-met remote model, or a remote model
|
||||
// whose last_fetched date is beyond a certain interval, the account will be dereferenced. In the case of dereferencing, some low-priority account information
|
||||
// may be enqueued for asynchronous fetching, e.g. featured account statuses (pins). An ActivityPub object indicates the account was dereferenced.
|
||||
func (d *Dereferencer) GetAccountByURI(ctx context.Context, requestUser string, uri *url.URL) (*gtsmodel.Account, ap.Accountable, error) {
|
||||
// GetAccountByURI will attempt to fetch an accounts by its
|
||||
// URI, first checking the database. In the case of a newly-met
|
||||
// remote model, or a remote model whose last_fetched date is
|
||||
// beyond a certain interval, the account will be dereferenced.
|
||||
// In the case of dereferencing, some low-priority account info
|
||||
// may be enqueued for asynchronous fetching, e.g. pinned statuses.
|
||||
// An ActivityPub object indicates the account was dereferenced.
|
||||
//
|
||||
// if tryURL is true, then the database will also check for a *single*
|
||||
// account where uri == account.url, not just uri == account.uri.
|
||||
// Because url does not guarantee uniqueness, you should only set
|
||||
// tryURL to true when doing searches set in motion by a user,
|
||||
// ie., when it's not important that an exact account is returned.
|
||||
func (d *Dereferencer) GetAccountByURI(
|
||||
ctx context.Context,
|
||||
requestUser string,
|
||||
uri *url.URL,
|
||||
tryURL bool,
|
||||
) (*gtsmodel.Account, ap.Accountable, error) {
|
||||
// Fetch and dereference account if necessary.
|
||||
account, accountable, err := d.getAccountByURI(ctx,
|
||||
requestUser,
|
||||
uri,
|
||||
tryURL,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
@ -118,8 +134,15 @@ func (d *Dereferencer) GetAccountByURI(ctx context.Context, requestUser string,
|
|||
return account, accountable, nil
|
||||
}
|
||||
|
||||
// getAccountByURI is a package internal form of .GetAccountByURI() that doesn't bother dereferencing featured posts on update.
|
||||
func (d *Dereferencer) getAccountByURI(ctx context.Context, requestUser string, uri *url.URL) (*gtsmodel.Account, ap.Accountable, error) {
|
||||
// getAccountByURI is a package internal form of
|
||||
// .GetAccountByURI() that doesn't bother dereferencing
|
||||
// featured posts on update.
|
||||
func (d *Dereferencer) getAccountByURI(
|
||||
ctx context.Context,
|
||||
requestUser string,
|
||||
uri *url.URL,
|
||||
tryURL bool,
|
||||
) (*gtsmodel.Account, ap.Accountable, error) {
|
||||
var (
|
||||
account *gtsmodel.Account
|
||||
uriStr = uri.String()
|
||||
|
@ -127,9 +150,8 @@ func (d *Dereferencer) getAccountByURI(ctx context.Context, requestUser string,
|
|||
)
|
||||
|
||||
// Search the database for existing account with URI.
|
||||
// URI is unique so if we get a hit it's that account for sure.
|
||||
account, err = d.state.DB.GetAccountByURI(
|
||||
// request a barebones object, it may be in the
|
||||
// db but with related models not yet dereferenced.
|
||||
gtscontext.SetBarebones(ctx),
|
||||
uriStr,
|
||||
)
|
||||
|
@ -137,9 +159,11 @@ func (d *Dereferencer) getAccountByURI(ctx context.Context, requestUser string,
|
|||
return nil, nil, gtserror.Newf("error checking database for account %s by uri: %w", uriStr, err)
|
||||
}
|
||||
|
||||
if account == nil {
|
||||
// Else, search the database for one account with URL.
|
||||
// Can return multiple hits so check for ErrMultipleEntries.
|
||||
if account == nil && tryURL {
|
||||
// Else if we're permitted, search the database for *ONE*
|
||||
// account with this URL. This can return multiple hits
|
||||
// so check for ErrMultipleEntries. If we get exactly one
|
||||
// hit it's *probably* the account we're looking for.
|
||||
account, err = d.state.DB.GetOneAccountByURL(
|
||||
gtscontext.SetBarebones(ctx),
|
||||
uriStr,
|
||||
|
|
|
@ -54,6 +54,7 @@ func (suite *AccountTestSuite) TestDereferenceGroup() {
|
|||
context.Background(),
|
||||
fetchingAccount.Username,
|
||||
groupURL,
|
||||
false,
|
||||
)
|
||||
suite.NoError(err)
|
||||
suite.NotNil(group)
|
||||
|
@ -78,6 +79,7 @@ func (suite *AccountTestSuite) TestDereferenceService() {
|
|||
context.Background(),
|
||||
fetchingAccount.Username,
|
||||
serviceURL,
|
||||
false,
|
||||
)
|
||||
suite.NoError(err)
|
||||
suite.NotNil(service)
|
||||
|
@ -110,6 +112,7 @@ func (suite *AccountTestSuite) TestDereferenceLocalAccountAsRemoteURL() {
|
|||
context.Background(),
|
||||
fetchingAccount.Username,
|
||||
testrig.URLMustParse(targetAccount.URI),
|
||||
false,
|
||||
)
|
||||
suite.NoError(err)
|
||||
suite.NotNil(fetchedAccount)
|
||||
|
@ -129,6 +132,7 @@ func (suite *AccountTestSuite) TestDereferenceLocalAccountAsRemoteURLNoSharedInb
|
|||
context.Background(),
|
||||
fetchingAccount.Username,
|
||||
testrig.URLMustParse(targetAccount.URI),
|
||||
false,
|
||||
)
|
||||
suite.NoError(err)
|
||||
suite.NotNil(fetchedAccount)
|
||||
|
@ -143,6 +147,7 @@ func (suite *AccountTestSuite) TestDereferenceLocalAccountAsUsername() {
|
|||
context.Background(),
|
||||
fetchingAccount.Username,
|
||||
testrig.URLMustParse(targetAccount.URI),
|
||||
false,
|
||||
)
|
||||
suite.NoError(err)
|
||||
suite.NotNil(fetchedAccount)
|
||||
|
@ -157,6 +162,7 @@ func (suite *AccountTestSuite) TestDereferenceLocalAccountAsUsernameDomain() {
|
|||
context.Background(),
|
||||
fetchingAccount.Username,
|
||||
testrig.URLMustParse(targetAccount.URI),
|
||||
false,
|
||||
)
|
||||
suite.NoError(err)
|
||||
suite.NotNil(fetchedAccount)
|
||||
|
@ -213,6 +219,7 @@ func (suite *AccountTestSuite) TestDereferenceLocalAccountWithUnknownUserURI() {
|
|||
context.Background(),
|
||||
fetchingAccount.Username,
|
||||
testrig.URLMustParse("http://localhost:8080/users/thisaccountdoesnotexist"),
|
||||
false,
|
||||
)
|
||||
suite.True(gtserror.IsUnretrievable(err))
|
||||
suite.EqualError(err, db.ErrNoEntries.Error())
|
||||
|
@ -265,7 +272,7 @@ func (suite *AccountTestSuite) TestDereferenceLocalAccountByRedirect() {
|
|||
uri := testrig.URLMustParse("https://this-will-be-redirected.butts/")
|
||||
|
||||
// Try dereference the test URI, since it correctly redirects to us it should return our account.
|
||||
account, accountable, err := suite.dereferencer.GetAccountByURI(ctx, fetchingAccount.Username, uri)
|
||||
account, accountable, err := suite.dereferencer.GetAccountByURI(ctx, fetchingAccount.Username, uri, false)
|
||||
suite.NoError(err)
|
||||
suite.Nil(accountable)
|
||||
suite.NotNil(account)
|
||||
|
@ -318,7 +325,7 @@ func (suite *AccountTestSuite) TestDereferenceMasqueradingLocalAccount() {
|
|||
)
|
||||
|
||||
// Try dereference the test URI, since it correctly redirects to us it should return our account.
|
||||
account, accountable, err := suite.dereferencer.GetAccountByURI(ctx, fetchingAccount.Username, uri)
|
||||
account, accountable, err := suite.dereferencer.GetAccountByURI(ctx, fetchingAccount.Username, uri, false)
|
||||
suite.NotNil(err)
|
||||
suite.Nil(account)
|
||||
suite.Nil(accountable)
|
||||
|
@ -341,6 +348,7 @@ func (suite *AccountTestSuite) TestDereferenceRemoteAccountWithNonMatchingURI()
|
|||
context.Background(),
|
||||
fetchingAccount.Username,
|
||||
testrig.URLMustParse(remoteAltURI),
|
||||
false,
|
||||
)
|
||||
suite.Equal(err.Error(), fmt.Sprintf("enrichAccount: account uri %s does not match %s", remoteURI, remoteAltURI))
|
||||
suite.Nil(fetchedAccount)
|
||||
|
@ -357,6 +365,7 @@ func (suite *AccountTestSuite) TestDereferenceRemoteAccountWithUnexpectedKeyChan
|
|||
remoteAcc, _, err := suite.dereferencer.GetAccountByURI(ctx,
|
||||
fetchingAcc.Username,
|
||||
testrig.URLMustParse(remoteURI),
|
||||
false,
|
||||
)
|
||||
suite.NoError(err)
|
||||
suite.NotNil(remoteAcc)
|
||||
|
@ -395,6 +404,7 @@ func (suite *AccountTestSuite) TestDereferenceRemoteAccountWithExpectedKeyChange
|
|||
remoteAcc, _, err := suite.dereferencer.GetAccountByURI(ctx,
|
||||
fetchingAcc.Username,
|
||||
testrig.URLMustParse(remoteURI),
|
||||
false,
|
||||
)
|
||||
suite.NoError(err)
|
||||
suite.NotNil(remoteAcc)
|
||||
|
@ -436,6 +446,7 @@ func (suite *AccountTestSuite) TestRefreshFederatedRemoteAccountWithKeyChange()
|
|||
remoteAcc, _, err := suite.dereferencer.GetAccountByURI(ctx,
|
||||
fetchingAcc.Username,
|
||||
testrig.URLMustParse(remoteURI),
|
||||
false,
|
||||
)
|
||||
suite.NoError(err)
|
||||
suite.NotNil(remoteAcc)
|
||||
|
|
|
@ -454,7 +454,8 @@ func (d *Dereferencer) enrichStatus(
|
|||
|
||||
// Ensure we have the author account of the status dereferenced (+ up-to-date). If this is a new status
|
||||
// (i.e. status.AccountID == "") then any error here is irrecoverable. status.AccountID must ALWAYS be set.
|
||||
if _, _, err := d.getAccountByURI(ctx, requestUser, attributedTo); err != nil && status.AccountID == "" {
|
||||
// We want the exact URI match here as well, not the imprecise URL match.
|
||||
if _, _, err := d.getAccountByURI(ctx, requestUser, attributedTo, false); err != nil && status.AccountID == "" {
|
||||
|
||||
// Note that we specifically DO NOT wrap the error, instead collapsing it as string.
|
||||
// Errors fetching an account do not necessarily relate to dereferencing the status.
|
||||
|
@ -1312,35 +1313,17 @@ func (d *Dereferencer) getPopulatedMention(
|
|||
bool, // True if mention already exists in the DB.
|
||||
error,
|
||||
) {
|
||||
// Mentions can be created using Name or Href.
|
||||
// Prefer Href (TargetAccountURI), fall back to Name.
|
||||
if mention.TargetAccountURI != "" {
|
||||
// Mentions can be created using `name` or `href`,
|
||||
// and when mention was extracted, we ensured that
|
||||
// one of either `name` or `href` was set.
|
||||
//
|
||||
// Prefer to deref the mention target using `name`,
|
||||
// which should always be exact. and fall back to `href`,
|
||||
// which *should* be the target's URI, but may be the URL
|
||||
// depending on implementation.
|
||||
if mention.NameString != "" {
|
||||
|
||||
// Look for existing mention with target account's URI, if so use this.
|
||||
existingMention, ok := existing.GetMentionByTargetURI(mention.TargetAccountURI)
|
||||
if ok && existingMention.ID != "" {
|
||||
return existingMention, true, nil
|
||||
}
|
||||
|
||||
// Ensure that mention account URI is parseable.
|
||||
accountURI, err := url.Parse(mention.TargetAccountURI)
|
||||
if err != nil {
|
||||
err := gtserror.Newf("invalid account uri %q: %w", mention.TargetAccountURI, err)
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
// Ensure we have account of the mention target dereferenced.
|
||||
mention.TargetAccount, _, err = d.getAccountByURI(ctx,
|
||||
requestUser,
|
||||
accountURI,
|
||||
)
|
||||
if err != nil {
|
||||
err := gtserror.Newf("failed to dereference account %s: %w", accountURI, err)
|
||||
return nil, false, err
|
||||
}
|
||||
} else {
|
||||
|
||||
// Href wasn't set, extract the username and domain parts from namestring.
|
||||
// Extract the username and domain parts from namestring.
|
||||
username, domain, err := util.ExtractNamestringParts(mention.NameString)
|
||||
if err != nil {
|
||||
err := gtserror.Newf("failed to parse namestring %s: %w", mention.NameString, err)
|
||||
|
@ -1369,6 +1352,34 @@ func (d *Dereferencer) getPopulatedMention(
|
|||
if ok && existingMention.ID != "" {
|
||||
return existingMention, true, nil
|
||||
}
|
||||
} else {
|
||||
|
||||
// Name wasn't set.
|
||||
//
|
||||
// Look for existing mention with target account's URI, if so use this.
|
||||
existingMention, ok := existing.GetMentionByTargetURI(mention.TargetAccountURI)
|
||||
if ok && existingMention.ID != "" {
|
||||
return existingMention, true, nil
|
||||
}
|
||||
|
||||
// Ensure that mention account URI is parseable.
|
||||
accountURI, err := url.Parse(mention.TargetAccountURI)
|
||||
if err != nil {
|
||||
err := gtserror.Newf("invalid account uri %q: %w", mention.TargetAccountURI, err)
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
// Ensure we have account of the mention target dereferenced.
|
||||
// Don't allow imprecise URL here, we want the exact acct.
|
||||
mention.TargetAccount, _, err = d.getAccountByURI(ctx,
|
||||
requestUser,
|
||||
accountURI,
|
||||
false,
|
||||
)
|
||||
if err != nil {
|
||||
err := gtserror.Newf("failed to dereference account %s: %w", accountURI, err)
|
||||
return nil, false, err
|
||||
}
|
||||
}
|
||||
|
||||
// At this point, mention.TargetAccountURI
|
||||
|
|
|
@ -107,9 +107,14 @@ func (p *Processor) Alias(
|
|||
}
|
||||
|
||||
// Ensure we have account dereferenced.
|
||||
//
|
||||
// As this comes from user input, allow checking
|
||||
// by URL to make things easier, not just to an
|
||||
// exact AP URI (which a user might not even know).
|
||||
targetAccount, _, err := p.federator.GetAccountByURI(ctx,
|
||||
account.Username,
|
||||
newAKA.uri,
|
||||
true,
|
||||
)
|
||||
if err != nil {
|
||||
err := fmt.Errorf(
|
||||
|
|
|
@ -66,10 +66,13 @@ func (p *Processor) Get(ctx context.Context, requestingAccount *gtsmodel.Account
|
|||
|
||||
// Perform a last-minute fetch of target account to
|
||||
// ensure remote account header / avatar is cached.
|
||||
//
|
||||
// Match by URI only.
|
||||
latest, _, err := p.federator.GetAccountByURI(
|
||||
gtscontext.SetFastFail(ctx),
|
||||
requestingAccount.Username,
|
||||
targetAccountURI,
|
||||
false,
|
||||
)
|
||||
if err != nil {
|
||||
log.Errorf(ctx, "error fetching latest target account: %v", err)
|
||||
|
|
|
@ -119,11 +119,15 @@ func (p *Processor) MoveSelf(
|
|||
unlock := p.state.ProcessingLocks.Lock(lockKey)
|
||||
defer unlock()
|
||||
|
||||
// Ensure we have a valid, up-to-date representation of the target account.
|
||||
// Ensure we have a valid, up-to-date
|
||||
// representation of the target account.
|
||||
//
|
||||
// Match by uri only.
|
||||
targetAcct, targetAcctable, err = p.federator.GetAccountByURI(
|
||||
ctx,
|
||||
originAcct.Username,
|
||||
targetAcctURI,
|
||||
false,
|
||||
)
|
||||
if err != nil {
|
||||
const text = "error dereferencing moved_to_uri"
|
||||
|
|
|
@ -564,10 +564,15 @@ func (p *Processor) accountsByURI(
|
|||
if resolve {
|
||||
// We're allowed to resolve, leave the
|
||||
// rest up to the dereferencer functions.
|
||||
//
|
||||
// Allow dereferencing by URL and not just URI;
|
||||
// there are many cases where someone might
|
||||
// paste a URL into the search bar.
|
||||
account, _, err := p.federator.GetAccountByURI(
|
||||
gtscontext.SetFastFail(ctx),
|
||||
requestingAccount.Username,
|
||||
uri,
|
||||
true,
|
||||
)
|
||||
|
||||
return []*gtsmodel.Account{account}, err
|
||||
|
|
|
@ -303,10 +303,13 @@ func (p *fediAPI) MoveAccount(ctx context.Context, fMsg *messages.FromFediAPI) e
|
|||
}
|
||||
|
||||
// Account to which the Move is taking place.
|
||||
//
|
||||
// Match by uri only.
|
||||
targetAcct, targetAcctable, err := p.federate.GetAccountByURI(
|
||||
ctx,
|
||||
fMsg.Receiving.Username,
|
||||
targetAcctURI,
|
||||
false,
|
||||
)
|
||||
if err != nil {
|
||||
return gtserror.Newf(
|
||||
|
|
Loading…
Reference in a new issue