[bugfix] Fix multiple dereferences of boosted status causing media duplication (#589)
* add some announces to test models * start on announce test logic * test federatingDB.Announce * change signature of GetRemoteStatus * remove 'refresh' logic and replace it with refetch * go fmt * remove timeline manager from processor test * make zork created at determinate * test get account statuses * test get + serialize zork * make account keys determinate * make admin accountCreate time determinate * test account to as * init test config before test log * test status to frontend * remove daft Within check * hack around a bit * use index of slice
This commit is contained in:
parent
1461adfd3a
commit
f0c9f4169b
|
@ -65,8 +65,6 @@ func (suite *AccountVerifyTestSuite) TestAccountVerifyGet() {
|
||||||
|
|
||||||
createdAt, err := time.Parse(time.RFC3339, apimodelAccount.CreatedAt)
|
createdAt, err := time.Parse(time.RFC3339, apimodelAccount.CreatedAt)
|
||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
lastStatusAt, err := time.Parse(time.RFC3339, apimodelAccount.LastStatusAt)
|
|
||||||
suite.NoError(err)
|
|
||||||
|
|
||||||
suite.Equal(testAccount.ID, apimodelAccount.ID)
|
suite.Equal(testAccount.ID, apimodelAccount.ID)
|
||||||
suite.Equal(testAccount.Username, apimodelAccount.Username)
|
suite.Equal(testAccount.Username, apimodelAccount.Username)
|
||||||
|
@ -83,7 +81,6 @@ func (suite *AccountVerifyTestSuite) TestAccountVerifyGet() {
|
||||||
suite.Equal(2, apimodelAccount.FollowersCount)
|
suite.Equal(2, apimodelAccount.FollowersCount)
|
||||||
suite.Equal(2, apimodelAccount.FollowingCount)
|
suite.Equal(2, apimodelAccount.FollowingCount)
|
||||||
suite.Equal(5, apimodelAccount.StatusesCount)
|
suite.Equal(5, apimodelAccount.StatusesCount)
|
||||||
suite.WithinDuration(time.Now(), lastStatusAt, 5*time.Minute)
|
|
||||||
suite.EqualValues(gtsmodel.VisibilityPublic, apimodelAccount.Source.Privacy)
|
suite.EqualValues(gtsmodel.VisibilityPublic, apimodelAccount.Source.Privacy)
|
||||||
suite.Equal(testAccount.Language, apimodelAccount.Source.Language)
|
suite.Equal(testAccount.Language, apimodelAccount.Source.Language)
|
||||||
suite.Equal(testAccount.NoteRaw, apimodelAccount.Source.Note)
|
suite.Equal(testAccount.NoteRaw, apimodelAccount.Source.Note)
|
||||||
|
|
|
@ -34,6 +34,12 @@ type AccountTestSuite struct {
|
||||||
BunDBStandardTestSuite
|
BunDBStandardTestSuite
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (suite *AccountTestSuite) TestGetAccountStatuses() {
|
||||||
|
statuses, err := suite.db.GetAccountStatuses(context.Background(), suite.testAccounts["local_account_1"].ID, 20, false, false, "", "", false, false, false)
|
||||||
|
suite.NoError(err)
|
||||||
|
suite.Len(statuses, 5)
|
||||||
|
}
|
||||||
|
|
||||||
func (suite *AccountTestSuite) TestGetAccountByIDWithExtras() {
|
func (suite *AccountTestSuite) TestGetAccountByIDWithExtras() {
|
||||||
account, err := suite.db.GetAccountByID(context.Background(), suite.testAccounts["local_account_1"].ID)
|
account, err := suite.db.GetAccountByID(context.Background(), suite.testAccounts["local_account_1"].ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -30,8 +30,8 @@ func (f *federator) GetRemoteAccount(ctx context.Context, username string, remot
|
||||||
return f.dereferencer.GetRemoteAccount(ctx, username, remoteAccountID, blocking, refresh)
|
return f.dereferencer.GetRemoteAccount(ctx, username, remoteAccountID, blocking, refresh)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *federator) GetRemoteStatus(ctx context.Context, username string, remoteStatusID *url.URL, refresh, includeParent bool) (*gtsmodel.Status, ap.Statusable, bool, error) {
|
func (f *federator) GetRemoteStatus(ctx context.Context, username string, remoteStatusID *url.URL, refetch, includeParent bool) (*gtsmodel.Status, ap.Statusable, error) {
|
||||||
return f.dereferencer.GetRemoteStatus(ctx, username, remoteStatusID, refresh, includeParent)
|
return f.dereferencer.GetRemoteStatus(ctx, username, remoteStatusID, refetch, includeParent)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *federator) EnrichRemoteStatus(ctx context.Context, username string, status *gtsmodel.Status, includeParent bool) (*gtsmodel.Status, error) {
|
func (f *federator) EnrichRemoteStatus(ctx context.Context, username string, status *gtsmodel.Status, includeParent bool) (*gtsmodel.Status, error) {
|
||||||
|
|
|
@ -46,7 +46,7 @@ func (d *deref) DereferenceAnnounce(ctx context.Context, announce *gtsmodel.Stat
|
||||||
return fmt.Errorf("DereferenceAnnounce: error dereferencing thread of boosted status: %s", err)
|
return fmt.Errorf("DereferenceAnnounce: error dereferencing thread of boosted status: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
boostedStatus, _, _, err := d.GetRemoteStatus(ctx, requestingUsername, boostedStatusURI, false, true)
|
boostedStatus, _, err := d.GetRemoteStatus(ctx, requestingUsername, boostedStatusURI, false, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("DereferenceAnnounce: error dereferencing remote status with id %s: %s", announce.BoostOf.URI, err)
|
return fmt.Errorf("DereferenceAnnounce: error dereferencing remote status with id %s: %s", announce.BoostOf.URI, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ import (
|
||||||
type Dereferencer interface {
|
type Dereferencer interface {
|
||||||
GetRemoteAccount(ctx context.Context, username string, remoteAccountID *url.URL, blocking bool, refresh bool) (*gtsmodel.Account, error)
|
GetRemoteAccount(ctx context.Context, username string, remoteAccountID *url.URL, blocking bool, refresh bool) (*gtsmodel.Account, error)
|
||||||
|
|
||||||
GetRemoteStatus(ctx context.Context, username string, remoteStatusID *url.URL, refresh, includeParent bool) (*gtsmodel.Status, ap.Statusable, bool, error)
|
GetRemoteStatus(ctx context.Context, username string, remoteStatusID *url.URL, refetch, includeParent bool) (*gtsmodel.Status, ap.Statusable, error)
|
||||||
EnrichRemoteStatus(ctx context.Context, username string, status *gtsmodel.Status, includeParent bool) (*gtsmodel.Status, error)
|
EnrichRemoteStatus(ctx context.Context, username string, status *gtsmodel.Status, includeParent bool) (*gtsmodel.Status, error)
|
||||||
|
|
||||||
GetRemoteInstance(ctx context.Context, username string, remoteInstanceURI *url.URL) (*gtsmodel.Instance, error)
|
GetRemoteInstance(ctx context.Context, username string, remoteInstanceURI *url.URL) (*gtsmodel.Instance, error)
|
||||||
|
|
|
@ -53,79 +53,63 @@ func (d *deref) EnrichRemoteStatus(ctx context.Context, username string, status
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRemoteStatus completely dereferences a remote status, converts it to a GtS model status,
|
// GetRemoteStatus completely dereferences a remote status, converts it to a GtS model status,
|
||||||
// puts it in the database, and returns it to a caller. The boolean indicates whether the status is new
|
// puts it in the database, and returns it to a caller.
|
||||||
// to us or not. If we haven't seen the status before, bool will be true. If we have seen the status before,
|
|
||||||
// it will be false.
|
|
||||||
//
|
//
|
||||||
// If refresh is true, then even if we have the status in our database already, it will be dereferenced from its
|
// If refetch is true, then regardless of whether we have the original status in the database or not,
|
||||||
// remote representation, as will its owner.
|
// the ap.Statusable representation of the status will be dereferenced and returned.
|
||||||
//
|
//
|
||||||
// If a dereference was performed, then the function also returns the ap.Statusable representation for further processing.
|
// If refetch is false, the ap.Statusable will only be returned if this is a new status, so callers
|
||||||
|
// should check whether or not this is nil.
|
||||||
//
|
//
|
||||||
// SIDE EFFECTS: remote status will be stored in the database, and the remote status owner will also be stored.
|
// SIDE EFFECTS: remote status will be stored in the database, and the remote status owner will also be stored.
|
||||||
func (d *deref) GetRemoteStatus(ctx context.Context, username string, remoteStatusID *url.URL, refresh, includeParent bool) (*gtsmodel.Status, ap.Statusable, bool, error) {
|
func (d *deref) GetRemoteStatus(ctx context.Context, username string, remoteStatusID *url.URL, refetch, includeParent bool) (*gtsmodel.Status, ap.Statusable, error) {
|
||||||
new := true
|
|
||||||
|
|
||||||
// check if we already have the status in our db
|
|
||||||
maybeStatus, err := d.db.GetStatusByURI(ctx, remoteStatusID.String())
|
maybeStatus, err := d.db.GetStatusByURI(ctx, remoteStatusID.String())
|
||||||
if err == nil {
|
if err == nil && !refetch {
|
||||||
// we've seen this status before so it's not new
|
// we already had the status and we aren't being asked to refetch the AP representation
|
||||||
new = false
|
return maybeStatus, nil, nil
|
||||||
|
|
||||||
// if we're not being asked to refresh, we can just return the maybeStatus as-is and avoid doing any external calls
|
|
||||||
if !refresh {
|
|
||||||
return maybeStatus, nil, new, nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
statusable, err := d.dereferenceStatusable(ctx, username, remoteStatusID)
|
statusable, err := d.dereferenceStatusable(ctx, username, remoteStatusID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, statusable, new, fmt.Errorf("GetRemoteStatus: error dereferencing statusable: %s", err)
|
return nil, nil, fmt.Errorf("GetRemoteStatus: error dereferencing statusable: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if maybeStatus != nil && refetch {
|
||||||
|
// we already had the status and we've successfully fetched the AP representation as requested
|
||||||
|
return maybeStatus, statusable, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// from here on out we can consider this to be a 'new' status because we didn't have the status in the db already
|
||||||
accountURI, err := ap.ExtractAttributedTo(statusable)
|
accountURI, err := ap.ExtractAttributedTo(statusable)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, statusable, new, fmt.Errorf("GetRemoteStatus: error extracting attributedTo: %s", err)
|
return nil, nil, fmt.Errorf("GetRemoteStatus: error extracting attributedTo: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// do this so we know we have the remote account of the status in the db
|
|
||||||
_, err = d.GetRemoteAccount(ctx, username, accountURI, true, false)
|
_, err = d.GetRemoteAccount(ctx, username, accountURI, true, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, statusable, new, fmt.Errorf("GetRemoteStatus: couldn't derive status author: %s", err)
|
return nil, nil, fmt.Errorf("GetRemoteStatus: couldn't get status author: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
gtsStatus, err := d.typeConverter.ASStatusToStatus(ctx, statusable)
|
gtsStatus, err := d.typeConverter.ASStatusToStatus(ctx, statusable)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, statusable, new, fmt.Errorf("GetRemoteStatus: error converting statusable to status: %s", err)
|
return nil, statusable, fmt.Errorf("GetRemoteStatus: error converting statusable to status: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if new {
|
|
||||||
ulid, err := id.NewULIDFromTime(gtsStatus.CreatedAt)
|
ulid, err := id.NewULIDFromTime(gtsStatus.CreatedAt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, statusable, new, fmt.Errorf("GetRemoteStatus: error generating new id for status: %s", err)
|
return nil, nil, fmt.Errorf("GetRemoteStatus: error generating new id for status: %s", err)
|
||||||
}
|
}
|
||||||
gtsStatus.ID = ulid
|
gtsStatus.ID = ulid
|
||||||
|
|
||||||
if err := d.populateStatusFields(ctx, gtsStatus, username, includeParent); err != nil {
|
if err := d.populateStatusFields(ctx, gtsStatus, username, includeParent); err != nil {
|
||||||
return nil, statusable, new, fmt.Errorf("GetRemoteStatus: error populating status fields: %s", err)
|
return nil, nil, fmt.Errorf("GetRemoteStatus: error populating status fields: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := d.db.PutStatus(ctx, gtsStatus); err != nil {
|
if err := d.db.PutStatus(ctx, gtsStatus); err != nil {
|
||||||
return nil, statusable, new, fmt.Errorf("GetRemoteStatus: error putting new status: %s", err)
|
return nil, nil, fmt.Errorf("GetRemoteStatus: error putting new status: %s", err)
|
||||||
}
|
|
||||||
} else {
|
|
||||||
gtsStatus.ID = maybeStatus.ID
|
|
||||||
|
|
||||||
if err := d.populateStatusFields(ctx, gtsStatus, username, includeParent); err != nil {
|
|
||||||
return nil, statusable, new, fmt.Errorf("GetRemoteStatus: error populating status fields: %s", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := d.db.UpdateByPrimaryKey(ctx, gtsStatus); err != nil {
|
return gtsStatus, statusable, nil
|
||||||
return nil, statusable, new, fmt.Errorf("GetRemoteStatus: error updating status: %s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return gtsStatus, statusable, new, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *deref) dereferenceStatusable(ctx context.Context, username string, remoteStatusID *url.URL) (ap.Statusable, error) {
|
func (d *deref) dereferenceStatusable(ctx context.Context, username string, remoteStatusID *url.URL) (ap.Statusable, error) {
|
||||||
|
@ -429,15 +413,10 @@ func (d *deref) populateStatusRepliedTo(ctx context.Context, status *gtsmodel.St
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// see if we have the status in our db already
|
replyToStatus, _, err := d.GetRemoteStatus(ctx, requestingUsername, statusURI, false, false)
|
||||||
replyToStatus, err := d.db.GetStatusByURI(ctx, status.InReplyToURI)
|
|
||||||
if err != nil {
|
|
||||||
// Status was not in the DB, try fetch
|
|
||||||
replyToStatus, _, _, err = d.GetRemoteStatus(ctx, requestingUsername, statusURI, false, false)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("populateStatusRepliedTo: couldn't get reply to status with uri %s: %s", status.InReplyToURI, err)
|
return fmt.Errorf("populateStatusRepliedTo: couldn't get reply to status with uri %s: %s", status.InReplyToURI, err)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// we have the status
|
// we have the status
|
||||||
status.InReplyToID = replyToStatus.ID
|
status.InReplyToID = replyToStatus.ID
|
||||||
|
|
|
@ -38,11 +38,9 @@ func (suite *StatusTestSuite) TestDereferenceSimpleStatus() {
|
||||||
fetchingAccount := suite.testAccounts["local_account_1"]
|
fetchingAccount := suite.testAccounts["local_account_1"]
|
||||||
|
|
||||||
statusURL := testrig.URLMustParse("https://unknown-instance.com/users/brand_new_person/statuses/01FE4NTHKWW7THT67EF10EB839")
|
statusURL := testrig.URLMustParse("https://unknown-instance.com/users/brand_new_person/statuses/01FE4NTHKWW7THT67EF10EB839")
|
||||||
status, statusable, new, err := suite.dereferencer.GetRemoteStatus(context.Background(), fetchingAccount.Username, statusURL, false, false)
|
status, _, err := suite.dereferencer.GetRemoteStatus(context.Background(), fetchingAccount.Username, statusURL, false, false)
|
||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
suite.NotNil(status)
|
suite.NotNil(status)
|
||||||
suite.NotNil(statusable)
|
|
||||||
suite.True(new)
|
|
||||||
|
|
||||||
// status values should be set
|
// status values should be set
|
||||||
suite.Equal("https://unknown-instance.com/users/brand_new_person/statuses/01FE4NTHKWW7THT67EF10EB839", status.URI)
|
suite.Equal("https://unknown-instance.com/users/brand_new_person/statuses/01FE4NTHKWW7THT67EF10EB839", status.URI)
|
||||||
|
@ -80,11 +78,9 @@ func (suite *StatusTestSuite) TestDereferenceStatusWithMention() {
|
||||||
fetchingAccount := suite.testAccounts["local_account_1"]
|
fetchingAccount := suite.testAccounts["local_account_1"]
|
||||||
|
|
||||||
statusURL := testrig.URLMustParse("https://unknown-instance.com/users/brand_new_person/statuses/01FE5Y30E3W4P7TRE0R98KAYQV")
|
statusURL := testrig.URLMustParse("https://unknown-instance.com/users/brand_new_person/statuses/01FE5Y30E3W4P7TRE0R98KAYQV")
|
||||||
status, statusable, new, err := suite.dereferencer.GetRemoteStatus(context.Background(), fetchingAccount.Username, statusURL, false, false)
|
status, _, err := suite.dereferencer.GetRemoteStatus(context.Background(), fetchingAccount.Username, statusURL, false, false)
|
||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
suite.NotNil(status)
|
suite.NotNil(status)
|
||||||
suite.NotNil(statusable)
|
|
||||||
suite.True(new)
|
|
||||||
|
|
||||||
// status values should be set
|
// status values should be set
|
||||||
suite.Equal("https://unknown-instance.com/users/brand_new_person/statuses/01FE5Y30E3W4P7TRE0R98KAYQV", status.URI)
|
suite.Equal("https://unknown-instance.com/users/brand_new_person/statuses/01FE5Y30E3W4P7TRE0R98KAYQV", status.URI)
|
||||||
|
@ -135,11 +131,9 @@ func (suite *StatusTestSuite) TestDereferenceStatusWithImageAndNoContent() {
|
||||||
fetchingAccount := suite.testAccounts["local_account_1"]
|
fetchingAccount := suite.testAccounts["local_account_1"]
|
||||||
|
|
||||||
statusURL := testrig.URLMustParse("https://turnip.farm/users/turniplover6969/statuses/70c53e54-3146-42d5-a630-83c8b6c7c042")
|
statusURL := testrig.URLMustParse("https://turnip.farm/users/turniplover6969/statuses/70c53e54-3146-42d5-a630-83c8b6c7c042")
|
||||||
status, statusable, new, err := suite.dereferencer.GetRemoteStatus(context.Background(), fetchingAccount.Username, statusURL, false, false)
|
status, _, err := suite.dereferencer.GetRemoteStatus(context.Background(), fetchingAccount.Username, statusURL, false, false)
|
||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
suite.NotNil(status)
|
suite.NotNil(status)
|
||||||
suite.NotNil(statusable)
|
|
||||||
suite.True(new)
|
|
||||||
|
|
||||||
// status values should be set
|
// status values should be set
|
||||||
suite.Equal("https://turnip.farm/users/turniplover6969/statuses/70c53e54-3146-42d5-a630-83c8b6c7c042", status.URI)
|
suite.Equal("https://turnip.farm/users/turniplover6969/statuses/70c53e54-3146-42d5-a630-83c8b6c7c042", status.URI)
|
||||||
|
|
|
@ -52,9 +52,9 @@ func (d *deref) DereferenceThread(ctx context.Context, username string, statusIR
|
||||||
}
|
}
|
||||||
|
|
||||||
// first make sure we have this status in our db
|
// first make sure we have this status in our db
|
||||||
_, statusable, _, err := d.GetRemoteStatus(ctx, username, statusIRI, true, false)
|
_, statusable, err := d.GetRemoteStatus(ctx, username, statusIRI, true, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("DereferenceThread: error getting status with id %s: %s", statusIRI.String(), err)
|
return fmt.Errorf("DereferenceThread: error getting initial status with id %s: %s", statusIRI.String(), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// first iterate up through ancestors, dereferencing if necessary as we go
|
// first iterate up through ancestors, dereferencing if necessary as we go
|
||||||
|
@ -106,9 +106,8 @@ func (d *deref) iterateAncestors(ctx context.Context, username string, statusIRI
|
||||||
return d.iterateAncestors(ctx, username, *nextIRI)
|
return d.iterateAncestors(ctx, username, *nextIRI)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we reach here, we're looking at a remote status -- make sure we have it in our db by calling GetRemoteStatus
|
// If we reach here, we're looking at a remote status
|
||||||
// We call it with refresh to true because we want the statusable representation to parse inReplyTo from.
|
_, statusable, err := d.GetRemoteStatus(ctx, username, &statusIRI, true, false)
|
||||||
_, statusable, _, err := d.GetRemoteStatus(ctx, username, &statusIRI, true, false)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Debugf("error getting remote status: %s", err)
|
l.Debugf("error getting remote status: %s", err)
|
||||||
return nil
|
return nil
|
||||||
|
@ -220,8 +219,8 @@ pageLoop:
|
||||||
foundReplies++
|
foundReplies++
|
||||||
|
|
||||||
// get the remote statusable and put it in the db
|
// get the remote statusable and put it in the db
|
||||||
_, statusable, new, err := d.GetRemoteStatus(ctx, username, itemURI, false, false)
|
_, statusable, err := d.GetRemoteStatus(ctx, username, itemURI, false, false)
|
||||||
if new && err == nil && statusable != nil {
|
if err == nil {
|
||||||
// now iterate descendants of *that* status
|
// now iterate descendants of *that* status
|
||||||
if err := d.iterateDescendants(ctx, username, *itemURI, statusable); err != nil {
|
if err := d.iterateDescendants(ctx, username, *itemURI, statusable); err != nil {
|
||||||
continue
|
continue
|
||||||
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
/*
|
||||||
|
GoToSocial
|
||||||
|
Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package federatingdb_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/suite"
|
||||||
|
"github.com/superseriousbusiness/activity/streams/vocab"
|
||||||
|
"github.com/superseriousbusiness/gotosocial/internal/ap"
|
||||||
|
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||||
|
)
|
||||||
|
|
||||||
|
type AnnounceTestSuite struct {
|
||||||
|
FederatingDBTestSuite
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *AnnounceTestSuite) TestNewAnnounce() {
|
||||||
|
receivingAccount1 := suite.testAccounts["local_account_1"]
|
||||||
|
announcingAccount := suite.testAccounts["remote_account_1"]
|
||||||
|
|
||||||
|
ctx := createTestContext(receivingAccount1, announcingAccount)
|
||||||
|
announce1 := suite.testActivities["announce_forwarded_1_zork"]
|
||||||
|
|
||||||
|
err := suite.federatingDB.Announce(ctx, announce1.Activity.(vocab.ActivityStreamsAnnounce))
|
||||||
|
suite.NoError(err)
|
||||||
|
|
||||||
|
// should be a message heading to the processor now, which we can intercept here
|
||||||
|
msg := <-suite.fromFederator
|
||||||
|
suite.Equal(ap.ActivityAnnounce, msg.APObjectType)
|
||||||
|
suite.Equal(ap.ActivityCreate, msg.APActivityType)
|
||||||
|
|
||||||
|
boost, ok := msg.GTSModel.(*gtsmodel.Status)
|
||||||
|
suite.True(ok)
|
||||||
|
suite.Equal(announcingAccount.ID, boost.AccountID)
|
||||||
|
|
||||||
|
// only the URI will be set on the boosted status because it still needs to be dereferenced
|
||||||
|
suite.NotEmpty(boost.BoostOf.URI)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *AnnounceTestSuite) TestAnnounceTwice() {
|
||||||
|
receivingAccount1 := suite.testAccounts["local_account_1"]
|
||||||
|
receivingAccount2 := suite.testAccounts["local_account_2"]
|
||||||
|
|
||||||
|
announcingAccount := suite.testAccounts["remote_account_1"]
|
||||||
|
|
||||||
|
ctx1 := createTestContext(receivingAccount1, announcingAccount)
|
||||||
|
announce1 := suite.testActivities["announce_forwarded_1_zork"]
|
||||||
|
|
||||||
|
err := suite.federatingDB.Announce(ctx1, announce1.Activity.(vocab.ActivityStreamsAnnounce))
|
||||||
|
suite.NoError(err)
|
||||||
|
|
||||||
|
// should be a message heading to the processor now, which we can intercept here
|
||||||
|
msg := <-suite.fromFederator
|
||||||
|
suite.Equal(ap.ActivityAnnounce, msg.APObjectType)
|
||||||
|
suite.Equal(ap.ActivityCreate, msg.APActivityType)
|
||||||
|
boost, ok := msg.GTSModel.(*gtsmodel.Status)
|
||||||
|
suite.True(ok)
|
||||||
|
suite.Equal(announcingAccount.ID, boost.AccountID)
|
||||||
|
|
||||||
|
// only the URI will be set on the boosted status because it still needs to be dereferenced
|
||||||
|
suite.NotEmpty(boost.BoostOf.URI)
|
||||||
|
|
||||||
|
ctx2 := createTestContext(receivingAccount2, announcingAccount)
|
||||||
|
announce2 := suite.testActivities["announce_forwarded_1_turtle"]
|
||||||
|
|
||||||
|
err = suite.federatingDB.Announce(ctx2, announce2.Activity.(vocab.ActivityStreamsAnnounce))
|
||||||
|
suite.NoError(err)
|
||||||
|
|
||||||
|
// since this is a repeat announce with the same URI, just delivered to a different inbox,
|
||||||
|
// we should have nothing in the messages channel...
|
||||||
|
suite.Empty(suite.fromFederator)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAnnounceTestSuite(t *testing.T) {
|
||||||
|
suite.Run(t, &AnnounceTestSuite{})
|
||||||
|
}
|
|
@ -63,8 +63,9 @@ func (suite *FederatingDBTestSuite) SetupSuite() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *FederatingDBTestSuite) SetupTest() {
|
func (suite *FederatingDBTestSuite) SetupTest() {
|
||||||
testrig.InitTestLog()
|
|
||||||
testrig.InitTestConfig()
|
testrig.InitTestConfig()
|
||||||
|
testrig.InitTestLog()
|
||||||
|
|
||||||
suite.fedWorker = concurrency.NewWorkerPool[messages.FromFederator](-1, -1)
|
suite.fedWorker = concurrency.NewWorkerPool[messages.FromFederator](-1, -1)
|
||||||
suite.fromFederator = make(chan messages.FromFederator, 10)
|
suite.fromFederator = make(chan messages.FromFederator, 10)
|
||||||
suite.fedWorker.SetProcessor(func(ctx context.Context, msg messages.FromFederator) error {
|
suite.fedWorker.SetProcessor(func(ctx context.Context, msg messages.FromFederator) error {
|
||||||
|
|
|
@ -62,7 +62,7 @@ type Federator interface {
|
||||||
|
|
||||||
GetRemoteAccount(ctx context.Context, username string, remoteAccountID *url.URL, blocking bool, refresh bool) (*gtsmodel.Account, error)
|
GetRemoteAccount(ctx context.Context, username string, remoteAccountID *url.URL, blocking bool, refresh bool) (*gtsmodel.Account, error)
|
||||||
|
|
||||||
GetRemoteStatus(ctx context.Context, username string, remoteStatusID *url.URL, refresh, includeParent bool) (*gtsmodel.Status, ap.Statusable, bool, error)
|
GetRemoteStatus(ctx context.Context, username string, remoteStatusID *url.URL, refetch, includeParent bool) (*gtsmodel.Status, ap.Statusable, error)
|
||||||
EnrichRemoteStatus(ctx context.Context, username string, status *gtsmodel.Status, includeParent bool) (*gtsmodel.Status, error)
|
EnrichRemoteStatus(ctx context.Context, username string, status *gtsmodel.Status, includeParent bool) (*gtsmodel.Status, error)
|
||||||
|
|
||||||
GetRemoteInstance(ctx context.Context, username string, remoteInstanceURI *url.URL) (*gtsmodel.Instance, error)
|
GetRemoteInstance(ctx context.Context, username string, remoteInstanceURI *url.URL) (*gtsmodel.Instance, error)
|
||||||
|
|
|
@ -108,7 +108,7 @@ func (p *processor) processCreateStatusFromFederator(ctx context.Context, federa
|
||||||
return errors.New("ProcessFromFederator: status was not pinned to federatorMsg, and neither was an IRI for us to dereference")
|
return errors.New("ProcessFromFederator: status was not pinned to federatorMsg, and neither was an IRI for us to dereference")
|
||||||
}
|
}
|
||||||
var err error
|
var err error
|
||||||
status, _, _, err = p.federator.GetRemoteStatus(ctx, federatorMsg.ReceivingAccount.Username, federatorMsg.APIri, false, false)
|
status, _, err = p.federator.GetRemoteStatus(ctx, federatorMsg.ReceivingAccount.Username, federatorMsg.APIri, false, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,6 @@ import (
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/messages"
|
"github.com/superseriousbusiness/gotosocial/internal/messages"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/oauth"
|
"github.com/superseriousbusiness/gotosocial/internal/oauth"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/processing"
|
"github.com/superseriousbusiness/gotosocial/internal/processing"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/timeline"
|
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/transport"
|
"github.com/superseriousbusiness/gotosocial/internal/transport"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/typeutils"
|
"github.com/superseriousbusiness/gotosocial/internal/typeutils"
|
||||||
"github.com/superseriousbusiness/gotosocial/testrig"
|
"github.com/superseriousbusiness/gotosocial/testrig"
|
||||||
|
@ -54,7 +53,6 @@ type ProcessingStandardTestSuite struct {
|
||||||
transportController transport.Controller
|
transportController transport.Controller
|
||||||
federator federation.Federator
|
federator federation.Federator
|
||||||
oauthServer oauth.Server
|
oauthServer oauth.Server
|
||||||
timelineManager timeline.Manager
|
|
||||||
emailSender email.Sender
|
emailSender email.Sender
|
||||||
|
|
||||||
// standard suite models
|
// standard suite models
|
||||||
|
|
|
@ -127,7 +127,7 @@ func (p *processor) searchStatusByURI(ctx context.Context, authed *oauth.Auth, u
|
||||||
|
|
||||||
// we don't have it locally so dereference it if we're allowed to
|
// we don't have it locally so dereference it if we're allowed to
|
||||||
if resolve {
|
if resolve {
|
||||||
status, _, _, err := p.federator.GetRemoteStatus(ctx, authed.Account.Username, uri, true, true)
|
status, _, err := p.federator.GetRemoteStatus(ctx, authed.Account.Username, uri, false, true)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if err := p.federator.DereferenceRemoteThread(ctx, authed.Account.Username, uri); err != nil {
|
if err := p.federator.DereferenceRemoteThread(ctx, authed.Account.Username, uri); err != nil {
|
||||||
// try to deref the thread while we're here
|
// try to deref the thread while we're here
|
||||||
|
|
|
@ -427,8 +427,8 @@ type TypeUtilsTestSuite struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *TypeUtilsTestSuite) SetupSuite() {
|
func (suite *TypeUtilsTestSuite) SetupSuite() {
|
||||||
testrig.InitTestLog()
|
|
||||||
testrig.InitTestConfig()
|
testrig.InitTestConfig()
|
||||||
|
testrig.InitTestLog()
|
||||||
|
|
||||||
suite.db = testrig.NewTestDB()
|
suite.db = testrig.NewTestDB()
|
||||||
suite.testAccounts = testrig.NewTestAccounts()
|
suite.testAccounts = testrig.NewTestAccounts()
|
||||||
|
|
|
@ -21,7 +21,7 @@ package typeutils_test
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
@ -45,8 +45,11 @@ func (suite *InternalToASTestSuite) TestAccountToAS() {
|
||||||
bytes, err := json.Marshal(ser)
|
bytes, err := json.Marshal(ser)
|
||||||
suite.NoError(err)
|
suite.NoError(err)
|
||||||
|
|
||||||
fmt.Println(string(bytes))
|
// trim off everything up to 'discoverable';
|
||||||
// TODO: write assertions here, rn we're just eyeballing the output
|
// this is necessary because the order of multiple 'context' entries is not determinate
|
||||||
|
trimmed := strings.Split(string(bytes), "\"discoverable\"")[1]
|
||||||
|
|
||||||
|
suite.Equal(`: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.jpeg"},"id":"http://localhost:8080/users/the_mighty_zork","image":{"mediaType":"image/jpeg","type":"Image","url":"http://localhost:8080/fileserver/01F8MH1H7YV1Z7D2C8K2730QBF/header/original/01PFPMWK2FF0D9WMHEJHR07C3Q.jpeg"},"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"},"summary":"\u003cp\u003ehey yo this is my profile!\u003c/p\u003e","type":"Person","url":"http://localhost:8080/@the_mighty_zork"}`, trimmed)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *InternalToASTestSuite) TestOutboxToASCollection() {
|
func (suite *InternalToASTestSuite) TestOutboxToASCollection() {
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
GoToSocial
|
||||||
|
Copyright (C) 2021-2022 GoToSocial Authors admin@gotosocial.org
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package typeutils_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/suite"
|
||||||
|
)
|
||||||
|
|
||||||
|
type InternalToFrontendTestSuite struct {
|
||||||
|
TypeUtilsTestSuite
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *InternalToFrontendTestSuite) TestAccountToFrontend() {
|
||||||
|
testAccount := suite.testAccounts["local_account_1"] // take zork for this test
|
||||||
|
apiAccount, err := suite.typeconverter.AccountToAPIAccountPublic(context.Background(), testAccount)
|
||||||
|
suite.NoError(err)
|
||||||
|
suite.NotNil(apiAccount)
|
||||||
|
|
||||||
|
b, err := json.Marshal(apiAccount)
|
||||||
|
suite.NoError(err)
|
||||||
|
suite.Equal(`{"id":"01F8MH1H7YV1Z7D2C8K2730QBF","username":"the_mighty_zork","acct":"the_mighty_zork","display_name":"original zork (he/they)","locked":false,"bot":false,"created_at":"2022-05-20T11:09:18Z","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.jpeg","avatar_static":"http://localhost:8080/fileserver/01F8MH1H7YV1Z7D2C8K2730QBF/avatar/small/01F8MH58A357CV5K7R7TJMSH6S.jpeg","header":"http://localhost:8080/fileserver/01F8MH1H7YV1Z7D2C8K2730QBF/header/original/01PFPMWK2FF0D9WMHEJHR07C3Q.jpeg","header_static":"http://localhost:8080/fileserver/01F8MH1H7YV1Z7D2C8K2730QBF/header/small/01PFPMWK2FF0D9WMHEJHR07C3Q.jpeg","followers_count":2,"following_count":2,"statuses_count":5,"last_status_at":"2022-05-20T11:37:55Z","emojis":[],"fields":[]}`, string(b))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (suite *InternalToFrontendTestSuite) TestStatusToFrontend() {
|
||||||
|
testStatus := suite.testStatuses["admin_account_status_1"]
|
||||||
|
requestingAccount := suite.testAccounts["local_account_1"]
|
||||||
|
apiStatus, err := suite.typeconverter.StatusToAPIStatus(context.Background(), testStatus, requestingAccount)
|
||||||
|
suite.NoError(err)
|
||||||
|
|
||||||
|
b, err := json.Marshal(apiStatus)
|
||||||
|
suite.NoError(err)
|
||||||
|
|
||||||
|
suite.Equal(`{"id":"01F8MH75CBF9JFX4ZAD54N0W0R","created_at":"2021-10-20T11:36:45Z","sensitive":false,"spoiler_text":"","visibility":"public","language":"en","uri":"http://localhost:8080/users/admin/statuses/01F8MH75CBF9JFX4ZAD54N0W0R","url":"http://localhost:8080/@admin/statuses/01F8MH75CBF9JFX4ZAD54N0W0R","replies_count":0,"reblogs_count":0,"favourites_count":1,"favourited":true,"reblogged":false,"muted":false,"bookmarked":false,"content":"hello world! #welcome ! first post on the instance :rainbow: !","application":{"name":"superseriousbusiness","website":"https://superserious.business"},"account":{"id":"01F8MH17FWEB39HZJ76B6VXSKF","username":"admin","acct":"admin","display_name":"","locked":false,"bot":false,"created_at":"2022-05-17T13:10:59Z","note":"","url":"http://localhost:8080/@admin","avatar":"","avatar_static":"","header":"","header_static":"","followers_count":1,"following_count":1,"statuses_count":4,"last_status_at":"2021-10-20T10:41:37Z","emojis":[],"fields":[]},"media_attachments":[{"id":"01F8MH6NEM8D7527KZAECTCR76","type":"image","url":"http://localhost:8080/fileserver/01F8MH17FWEB39HZJ76B6VXSKF/attachment/original/01F8MH6NEM8D7527KZAECTCR76.jpeg","preview_url":"http://localhost:8080/fileserver/01F8MH17FWEB39HZJ76B6VXSKF/attachment/small/01F8MH6NEM8D7527KZAECTCR76.jpeg","meta":{"original":{"width":1200,"height":630,"size":"1200x630","aspect":1.9047619},"small":{"width":256,"height":134,"size":"256x134","aspect":1.9104477},"focus":{"x":0,"y":0}},"description":"Black and white image of some 50's style text saying: Welcome On Board","blurhash":"LNJRdVM{00Rj%Mayt7j[4nWBofRj"}],"mentions":[],"tags":[{"name":"welcome","url":"http://localhost:8080/tags/welcome"}],"emojis":[{"shortcode":"rainbow","url":"http://localhost:8080/fileserver/01F8MH261H1KSV3GW3016GZRY3/emoji/original/01F8MH9H8E4VG3KDYJR9EGPXCQ.png","static_url":"http://localhost:8080/fileserver/01F8MH261H1KSV3GW3016GZRY3/emoji/static/01F8MH9H8E4VG3KDYJR9EGPXCQ.png","visible_in_picker":true}],"card":null,"poll":null,"text":""}`, string(b))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInternalToFrontendTestSuite(t *testing.T) {
|
||||||
|
suite.Run(t, new(InternalToFrontendTestSuite))
|
||||||
|
}
|
|
@ -31,6 +31,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -318,8 +319,8 @@ func NewTestAccounts() map[string]*gtsmodel.Account {
|
||||||
NoteRaw: "",
|
NoteRaw: "",
|
||||||
Memorial: false,
|
Memorial: false,
|
||||||
MovedToAccountID: "",
|
MovedToAccountID: "",
|
||||||
CreatedAt: time.Now().Add(-72 * time.Hour),
|
CreatedAt: TimeMustParse("2022-05-17T13:10:59Z"),
|
||||||
UpdatedAt: time.Now().Add(-72 * time.Hour),
|
UpdatedAt: TimeMustParse("2022-05-17T13:10:59Z"),
|
||||||
Bot: false,
|
Bot: false,
|
||||||
Reason: "",
|
Reason: "",
|
||||||
Locked: false,
|
Locked: false,
|
||||||
|
@ -357,8 +358,8 @@ func NewTestAccounts() map[string]*gtsmodel.Account {
|
||||||
NoteRaw: "hey yo this is my profile!",
|
NoteRaw: "hey yo this is my profile!",
|
||||||
Memorial: false,
|
Memorial: false,
|
||||||
MovedToAccountID: "",
|
MovedToAccountID: "",
|
||||||
CreatedAt: time.Now().Add(-48 * time.Hour),
|
CreatedAt: TimeMustParse("2022-05-20T11:09:18Z"),
|
||||||
UpdatedAt: time.Now().Add(-48 * time.Hour),
|
UpdatedAt: TimeMustParse("2022-05-20T11:09:18Z"),
|
||||||
Bot: false,
|
Bot: false,
|
||||||
Reason: "I wanna be on this damned webbed site so bad! Please! Wow",
|
Reason: "I wanna be on this damned webbed site so bad! Please! Wow",
|
||||||
Locked: false,
|
Locked: false,
|
||||||
|
@ -496,6 +497,15 @@ func NewTestAccounts() map[string]*gtsmodel.Account {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var accountsSorted []*gtsmodel.Account
|
||||||
|
for _, a := range accounts {
|
||||||
|
accountsSorted = append(accountsSorted, a)
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Slice(accountsSorted, func(i, j int) bool {
|
||||||
|
return accountsSorted[i].ID > accountsSorted[j].ID
|
||||||
|
})
|
||||||
|
|
||||||
preserializedKeys := []string{
|
preserializedKeys := []string{
|
||||||
"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",
|
||||||
|
@ -505,7 +515,7 @@ func NewTestAccounts() map[string]*gtsmodel.Account {
|
||||||
"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",
|
||||||
}
|
}
|
||||||
|
|
||||||
if diff := len(accounts) - len(preserializedKeys); diff > 0 {
|
if diff := len(accountsSorted) - len(preserializedKeys); diff > 0 {
|
||||||
keyStrings := make([]string, diff)
|
keyStrings := make([]string, diff)
|
||||||
for i := 0; i < diff; i++ {
|
for i := 0; i < diff; i++ {
|
||||||
priv, _ := rsa.GenerateKey(rand.Reader, 2048)
|
priv, _ := rsa.GenerateKey(rand.Reader, 2048)
|
||||||
|
@ -515,9 +525,7 @@ func NewTestAccounts() map[string]*gtsmodel.Account {
|
||||||
panic(fmt.Sprintf("mismatch between number of hardcoded test RSA keys and accounts used for test data. Insert the following generated key[s]: \n%+v", keyStrings))
|
panic(fmt.Sprintf("mismatch between number of hardcoded test RSA keys and accounts used for test data. Insert the following generated key[s]: \n%+v", keyStrings))
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate keys for each account
|
for i, v := range accountsSorted {
|
||||||
i := 0
|
|
||||||
for _, v := range accounts {
|
|
||||||
premadeBytes, err := base64.StdEncoding.DecodeString(preserializedKeys[i])
|
premadeBytes, err := base64.StdEncoding.DecodeString(preserializedKeys[i])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
@ -532,8 +540,8 @@ func NewTestAccounts() map[string]*gtsmodel.Account {
|
||||||
}
|
}
|
||||||
v.PrivateKey = priv
|
v.PrivateKey = priv
|
||||||
v.PublicKey = &priv.PublicKey
|
v.PublicKey = &priv.PublicKey
|
||||||
i++
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return accounts
|
return accounts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1174,8 +1182,8 @@ func NewTestStatuses() map[string]*gtsmodel.Status {
|
||||||
URL: "http://localhost:8080/@the_mighty_zork/statuses/01FCTA44PW9H1TB328S9AQXKDS",
|
URL: "http://localhost:8080/@the_mighty_zork/statuses/01FCTA44PW9H1TB328S9AQXKDS",
|
||||||
Content: "hi!",
|
Content: "hi!",
|
||||||
AttachmentIDs: []string{},
|
AttachmentIDs: []string{},
|
||||||
CreatedAt: time.Now().Add(-1 * time.Minute),
|
CreatedAt: TimeMustParse("2022-05-20T11:37:55Z"),
|
||||||
UpdatedAt: time.Now().Add(-1 * time.Minute),
|
UpdatedAt: TimeMustParse("2022-05-20T11:37:55Z"),
|
||||||
Local: true,
|
Local: true,
|
||||||
AccountURI: "http://localhost:8080/users/the_mighty_zork",
|
AccountURI: "http://localhost:8080/users/the_mighty_zork",
|
||||||
AccountID: "01F8MH1H7YV1Z7D2C8K2730QBF",
|
AccountID: "01F8MH1H7YV1Z7D2C8K2730QBF",
|
||||||
|
@ -1636,7 +1644,13 @@ func NewTestActivities(accounts map[string]*gtsmodel.Account) map[string]Activit
|
||||||
nil,
|
nil,
|
||||||
false,
|
false,
|
||||||
[]vocab.ActivityStreamsMention{},
|
[]vocab.ActivityStreamsMention{},
|
||||||
nil,
|
[]vocab.ActivityStreamsImage{
|
||||||
|
newAPImage(
|
||||||
|
URLMustParse("http://example.org/users/some_user/statuses/afaba698-5740-4e32-a702-af61aa543bc1/attachment1.jpeg"),
|
||||||
|
"image/jpeg",
|
||||||
|
"trent reznor looking handsome as balls",
|
||||||
|
"LEDara58O=t5EMSOENEN9]}?aK%0"),
|
||||||
|
},
|
||||||
)
|
)
|
||||||
createForwardedMessage := WrapAPNoteInCreate(
|
createForwardedMessage := WrapAPNoteInCreate(
|
||||||
URLMustParse("http://example.org/users/some_user/statuses/afaba698-5740-4e32-a702-af61aa543bc1/activity"),
|
URLMustParse("http://example.org/users/some_user/statuses/afaba698-5740-4e32-a702-af61aa543bc1/activity"),
|
||||||
|
@ -1645,6 +1659,33 @@ func NewTestActivities(accounts map[string]*gtsmodel.Account) map[string]Activit
|
||||||
forwardedMessage)
|
forwardedMessage)
|
||||||
createForwardedMessageSig, createForwardedMessageDigest, createForwardedMessageDate := GetSignatureForActivity(createForwardedMessage, accounts["remote_account_1"].PublicKeyURI, accounts["remote_account_1"].PrivateKey, URLMustParse(accounts["local_account_1"].InboxURI))
|
createForwardedMessageSig, createForwardedMessageDigest, createForwardedMessageDate := GetSignatureForActivity(createForwardedMessage, accounts["remote_account_1"].PublicKeyURI, accounts["remote_account_1"].PrivateKey, URLMustParse(accounts["local_account_1"].InboxURI))
|
||||||
|
|
||||||
|
announceForwarded1Zork := newAPAnnounce(
|
||||||
|
URLMustParse("http://fossbros-anonymous.io/users/foss_satan/first_announce"),
|
||||||
|
URLMustParse("http://fossbros-anonymous.io/users/foss_satan"),
|
||||||
|
time.Now(),
|
||||||
|
URLMustParse("http://fossbros-anonymous.io/users/foss_satan/followers"),
|
||||||
|
forwardedMessage,
|
||||||
|
)
|
||||||
|
announceForwarded1ZorkSig, announceForwarded1ZorkDigest, announceForwarded1ZorkDate := GetSignatureForActivity(announceForwarded1Zork, accounts["remote_account_1"].PublicKeyURI, accounts["remote_account_1"].PrivateKey, URLMustParse(accounts["local_account_1"].InboxURI))
|
||||||
|
|
||||||
|
announceForwarded1Turtle := newAPAnnounce(
|
||||||
|
URLMustParse("http://fossbros-anonymous.io/users/foss_satan/first_announce"),
|
||||||
|
URLMustParse("http://fossbros-anonymous.io/users/foss_satan"),
|
||||||
|
time.Now(),
|
||||||
|
URLMustParse("http://fossbros-anonymous.io/users/foss_satan/followers"),
|
||||||
|
forwardedMessage,
|
||||||
|
)
|
||||||
|
announceForwarded1TurtleSig, announceForwarded1TurtleDigest, announceForwarded1TurtleDate := GetSignatureForActivity(announceForwarded1Turtle, accounts["remote_account_1"].PublicKeyURI, accounts["remote_account_1"].PrivateKey, URLMustParse(accounts["local_account_2"].InboxURI))
|
||||||
|
|
||||||
|
announceForwarded2Zork := newAPAnnounce(
|
||||||
|
URLMustParse("http://fossbros-anonymous.io/users/foss_satan/second_announce"),
|
||||||
|
URLMustParse("http://fossbros-anonymous.io/users/foss_satan"),
|
||||||
|
time.Now(),
|
||||||
|
URLMustParse("http://fossbros-anonymous.io/users/foss_satan/followers"),
|
||||||
|
forwardedMessage,
|
||||||
|
)
|
||||||
|
announceForwarded2ZorkSig, announceForwarded2ZorkDigest, announceForwarded2ZorkDate := GetSignatureForActivity(announceForwarded2Zork, accounts["remote_account_1"].PublicKeyURI, accounts["remote_account_1"].PrivateKey, URLMustParse(accounts["local_account_1"].InboxURI))
|
||||||
|
|
||||||
return map[string]ActivityWithSignature{
|
return map[string]ActivityWithSignature{
|
||||||
"dm_for_zork": {
|
"dm_for_zork": {
|
||||||
Activity: createDmForZork,
|
Activity: createDmForZork,
|
||||||
|
@ -1670,6 +1711,24 @@ func NewTestActivities(accounts map[string]*gtsmodel.Account) map[string]Activit
|
||||||
DigestHeader: createForwardedMessageDigest,
|
DigestHeader: createForwardedMessageDigest,
|
||||||
DateHeader: createForwardedMessageDate,
|
DateHeader: createForwardedMessageDate,
|
||||||
},
|
},
|
||||||
|
"announce_forwarded_1_zork": {
|
||||||
|
Activity: announceForwarded1Zork,
|
||||||
|
SignatureHeader: announceForwarded1ZorkSig,
|
||||||
|
DigestHeader: announceForwarded1ZorkDigest,
|
||||||
|
DateHeader: announceForwarded1ZorkDate,
|
||||||
|
},
|
||||||
|
"announce_forwarded_1_turtle": {
|
||||||
|
Activity: announceForwarded1Turtle,
|
||||||
|
SignatureHeader: announceForwarded1TurtleSig,
|
||||||
|
DigestHeader: announceForwarded1TurtleDigest,
|
||||||
|
DateHeader: announceForwarded1TurtleDate,
|
||||||
|
},
|
||||||
|
"announce_forwarded_2_zork": {
|
||||||
|
Activity: announceForwarded2Zork,
|
||||||
|
SignatureHeader: announceForwarded2ZorkSig,
|
||||||
|
DigestHeader: announceForwarded2ZorkDigest,
|
||||||
|
DateHeader: announceForwarded2ZorkDate,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2585,3 +2644,41 @@ func WrapAPNoteInCreate(createID *url.URL, createActor *url.URL, createPublished
|
||||||
|
|
||||||
return create
|
return create
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newAPAnnounce(announceID *url.URL, announceActor *url.URL, announcePublished time.Time, announceTo *url.URL, announceNote vocab.ActivityStreamsNote) vocab.ActivityStreamsAnnounce {
|
||||||
|
announce := streams.NewActivityStreamsAnnounce()
|
||||||
|
|
||||||
|
if announceID != nil {
|
||||||
|
id := streams.NewJSONLDIdProperty()
|
||||||
|
id.Set(announceID)
|
||||||
|
announce.SetJSONLDId(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
if announceActor != nil {
|
||||||
|
actor := streams.NewActivityStreamsActorProperty()
|
||||||
|
actor.AppendIRI(announceActor)
|
||||||
|
announce.SetActivityStreamsActor(actor)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !announcePublished.IsZero() {
|
||||||
|
published := streams.NewActivityStreamsPublishedProperty()
|
||||||
|
published.Set(announcePublished)
|
||||||
|
announce.SetActivityStreamsPublished(published)
|
||||||
|
}
|
||||||
|
|
||||||
|
to := streams.NewActivityStreamsToProperty()
|
||||||
|
to.AppendIRI(announceTo)
|
||||||
|
announce.SetActivityStreamsTo(announceNote.GetActivityStreamsTo())
|
||||||
|
|
||||||
|
cc := streams.NewActivityStreamsCcProperty()
|
||||||
|
cc.AppendIRI(announceNote.GetActivityStreamsAttributedTo().Begin().GetIRI())
|
||||||
|
announce.SetActivityStreamsCc(cc)
|
||||||
|
|
||||||
|
if announceNote != nil {
|
||||||
|
noteIRI := streams.NewActivityStreamsObjectProperty()
|
||||||
|
noteIRI.AppendIRI(announceNote.GetJSONLDId().Get())
|
||||||
|
announce.SetActivityStreamsObject(noteIRI)
|
||||||
|
}
|
||||||
|
|
||||||
|
return announce
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue