mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-10-31 08:12:26 -05:00 
			
		
		
		
	Account update issue (#250)
* start poking around * tests * notes and fiddling
This commit is contained in:
		
					parent
					
						
							
								b3fd9c39a3
							
						
					
				
			
			
				commit
				
					
						b5a7e1ba32
					
				
			
		
					 5 changed files with 172 additions and 12 deletions
				
			
		|  | @ -223,6 +223,136 @@ func (suite *InboxPostTestSuite) TestPostUnblock() { | ||||||
| 	suite.Nil(block) | 	suite.Nil(block) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (suite *InboxPostTestSuite) TestPostUpdate() { | ||||||
|  | 	updatedAccount := *suite.testAccounts["remote_account_1"] | ||||||
|  | 	updatedAccount.DisplayName = "updated display name!" | ||||||
|  | 
 | ||||||
|  | 	asAccount, err := suite.tc.AccountToAS(context.Background(), &updatedAccount) | ||||||
|  | 	suite.NoError(err) | ||||||
|  | 
 | ||||||
|  | 	receivingAccount := suite.testAccounts["local_account_1"] | ||||||
|  | 
 | ||||||
|  | 	// create an update | ||||||
|  | 	update := streams.NewActivityStreamsUpdate() | ||||||
|  | 
 | ||||||
|  | 	// set the appropriate actor on it | ||||||
|  | 	updateActor := streams.NewActivityStreamsActorProperty() | ||||||
|  | 	updateActor.AppendIRI(testrig.URLMustParse(updatedAccount.URI)) | ||||||
|  | 	update.SetActivityStreamsActor(updateActor) | ||||||
|  | 
 | ||||||
|  | 	// Set the account as the 'object' property. | ||||||
|  | 	updateObject := streams.NewActivityStreamsObjectProperty() | ||||||
|  | 	updateObject.AppendActivityStreamsPerson(asAccount) | ||||||
|  | 	update.SetActivityStreamsObject(updateObject) | ||||||
|  | 
 | ||||||
|  | 	// Set the To of the update as public | ||||||
|  | 	updateTo := streams.NewActivityStreamsToProperty() | ||||||
|  | 	updateTo.AppendIRI(testrig.URLMustParse("https://www.w3.org/ns/activitystreams#Public")) | ||||||
|  | 	update.SetActivityStreamsTo(updateTo) | ||||||
|  | 
 | ||||||
|  | 	// set the cc of the update to the receivingAccount | ||||||
|  | 	updateCC := streams.NewActivityStreamsCcProperty() | ||||||
|  | 	updateCC.AppendIRI(testrig.URLMustParse(receivingAccount.URI)) | ||||||
|  | 	update.SetActivityStreamsCc(updateCC) | ||||||
|  | 
 | ||||||
|  | 	// set some random-ass ID for the activity | ||||||
|  | 	undoID := streams.NewJSONLDIdProperty() | ||||||
|  | 	undoID.SetIRI(testrig.URLMustParse("http://fossbros-anonymous.io/d360613a-dc8d-4563-8f0b-b6161caf0f2b")) | ||||||
|  | 	update.SetJSONLDId(undoID) | ||||||
|  | 
 | ||||||
|  | 	targetURI := testrig.URLMustParse(receivingAccount.InboxURI) | ||||||
|  | 
 | ||||||
|  | 	signature, digestHeader, dateHeader := testrig.GetSignatureForActivity(update, updatedAccount.PublicKeyURI, updatedAccount.PrivateKey, targetURI) | ||||||
|  | 	bodyI, err := streams.Serialize(update) | ||||||
|  | 	suite.NoError(err) | ||||||
|  | 
 | ||||||
|  | 	bodyJson, err := json.Marshal(bodyI) | ||||||
|  | 	suite.NoError(err) | ||||||
|  | 	body := bytes.NewReader(bodyJson) | ||||||
|  | 
 | ||||||
|  | 	tc := testrig.NewTestTransportController(testrig.NewMockHTTPClient(nil), suite.db) | ||||||
|  | 	federator := testrig.NewTestFederator(suite.db, tc, suite.storage) | ||||||
|  | 	processor := testrig.NewTestProcessor(suite.db, suite.storage, federator) | ||||||
|  | 	userModule := user.New(suite.config, processor, suite.log).(*user.Module) | ||||||
|  | 
 | ||||||
|  | 	// setup request | ||||||
|  | 	recorder := httptest.NewRecorder() | ||||||
|  | 	ctx, _ := gin.CreateTestContext(recorder) | ||||||
|  | 	ctx.Request = httptest.NewRequest(http.MethodPost, targetURI.String(), body) // the endpoint we're hitting | ||||||
|  | 	ctx.Request.Header.Set("Signature", signature) | ||||||
|  | 	ctx.Request.Header.Set("Date", dateHeader) | ||||||
|  | 	ctx.Request.Header.Set("Digest", digestHeader) | ||||||
|  | 	ctx.Request.Header.Set("Content-Type", "application/activity+json") | ||||||
|  | 
 | ||||||
|  | 	// we need to pass the context through signature check first to set appropriate values on it | ||||||
|  | 	suite.securityModule.SignatureCheck(ctx) | ||||||
|  | 
 | ||||||
|  | 	// normally the router would populate these params from the path values, | ||||||
|  | 	// but because we're calling the function directly, we need to set them manually. | ||||||
|  | 	ctx.Params = gin.Params{ | ||||||
|  | 		gin.Param{ | ||||||
|  | 			Key:   user.UsernameKey, | ||||||
|  | 			Value: receivingAccount.Username, | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// trigger the function being tested | ||||||
|  | 	userModule.InboxPOSTHandler(ctx) | ||||||
|  | 
 | ||||||
|  | 	result := recorder.Result() | ||||||
|  | 	defer result.Body.Close() | ||||||
|  | 	b, err := ioutil.ReadAll(result.Body) | ||||||
|  | 	suite.NoError(err) | ||||||
|  | 	suite.Empty(b) | ||||||
|  | 	suite.Equal(http.StatusOK, result.StatusCode) | ||||||
|  | 
 | ||||||
|  | 	// account should be changed in the database now | ||||||
|  | 	dbUpdatedAccount, err := suite.db.GetAccountByID(context.Background(), updatedAccount.ID) | ||||||
|  | 	suite.NoError(err) | ||||||
|  | 
 | ||||||
|  | 	// displayName should be updated | ||||||
|  | 	suite.Equal("updated display name!", dbUpdatedAccount.DisplayName) | ||||||
|  | 
 | ||||||
|  | 	// everything else should be the same as it was before | ||||||
|  | 	suite.EqualValues(updatedAccount.Username, dbUpdatedAccount.Username) | ||||||
|  | 	suite.EqualValues(updatedAccount.Domain, dbUpdatedAccount.Domain) | ||||||
|  | 	suite.EqualValues(updatedAccount.AvatarMediaAttachmentID, dbUpdatedAccount.AvatarMediaAttachmentID) | ||||||
|  | 	suite.EqualValues(updatedAccount.AvatarMediaAttachment, dbUpdatedAccount.AvatarMediaAttachment) | ||||||
|  | 	suite.EqualValues(updatedAccount.AvatarRemoteURL, dbUpdatedAccount.AvatarRemoteURL) | ||||||
|  | 	suite.EqualValues(updatedAccount.HeaderMediaAttachmentID, dbUpdatedAccount.HeaderMediaAttachmentID) | ||||||
|  | 	suite.EqualValues(updatedAccount.HeaderMediaAttachment, dbUpdatedAccount.HeaderMediaAttachment) | ||||||
|  | 	suite.EqualValues(updatedAccount.HeaderRemoteURL, dbUpdatedAccount.HeaderRemoteURL) | ||||||
|  | 	// suite.EqualValues(updatedAccount.Fields, dbUpdatedAccount.Fields) | ||||||
|  | 	suite.EqualValues(updatedAccount.Note, dbUpdatedAccount.Note) | ||||||
|  | 	suite.EqualValues(updatedAccount.Memorial, dbUpdatedAccount.Memorial) | ||||||
|  | 	suite.EqualValues(updatedAccount.AlsoKnownAs, dbUpdatedAccount.AlsoKnownAs) | ||||||
|  | 	suite.EqualValues(updatedAccount.MovedToAccountID, dbUpdatedAccount.MovedToAccountID) | ||||||
|  | 	suite.EqualValues(updatedAccount.Bot, dbUpdatedAccount.Bot) | ||||||
|  | 	suite.EqualValues(updatedAccount.Reason, dbUpdatedAccount.Reason) | ||||||
|  | 	suite.EqualValues(updatedAccount.Locked, dbUpdatedAccount.Locked) | ||||||
|  | 	suite.EqualValues(updatedAccount.Discoverable, dbUpdatedAccount.Discoverable) | ||||||
|  | 	suite.EqualValues(updatedAccount.Privacy, dbUpdatedAccount.Privacy) | ||||||
|  | 	suite.EqualValues(updatedAccount.Sensitive, dbUpdatedAccount.Sensitive) | ||||||
|  | 	suite.EqualValues(updatedAccount.Language, dbUpdatedAccount.Language) | ||||||
|  | 	suite.EqualValues(updatedAccount.URI, dbUpdatedAccount.URI) | ||||||
|  | 	suite.EqualValues(updatedAccount.URL, dbUpdatedAccount.URL) | ||||||
|  | 	suite.EqualValues(updatedAccount.LastWebfingeredAt, dbUpdatedAccount.LastWebfingeredAt) | ||||||
|  | 	suite.EqualValues(updatedAccount.InboxURI, dbUpdatedAccount.InboxURI) | ||||||
|  | 	suite.EqualValues(updatedAccount.OutboxURI, dbUpdatedAccount.OutboxURI) | ||||||
|  | 	suite.EqualValues(updatedAccount.FollowingURI, dbUpdatedAccount.FollowingURI) | ||||||
|  | 	suite.EqualValues(updatedAccount.FollowersURI, dbUpdatedAccount.FollowersURI) | ||||||
|  | 	suite.EqualValues(updatedAccount.FeaturedCollectionURI, dbUpdatedAccount.FeaturedCollectionURI) | ||||||
|  | 	suite.EqualValues(updatedAccount.ActorType, dbUpdatedAccount.ActorType) | ||||||
|  | 	// suite.EqualValues(updatedAccount.PrivateKey, dbUpdatedAccount.PrivateKey) | ||||||
|  | 	suite.EqualValues(updatedAccount.PublicKey, dbUpdatedAccount.PublicKey) | ||||||
|  | 	suite.EqualValues(updatedAccount.PublicKeyURI, dbUpdatedAccount.PublicKeyURI) | ||||||
|  | 	suite.EqualValues(updatedAccount.SensitizedAt, dbUpdatedAccount.SensitizedAt) | ||||||
|  | 	suite.EqualValues(updatedAccount.SilencedAt, dbUpdatedAccount.SilencedAt) | ||||||
|  | 	suite.EqualValues(updatedAccount.SuspendedAt, dbUpdatedAccount.SuspendedAt) | ||||||
|  | 	suite.EqualValues(updatedAccount.HideCollections, dbUpdatedAccount.HideCollections) | ||||||
|  | 	suite.EqualValues(updatedAccount.SuspensionOrigin, dbUpdatedAccount.SuspensionOrigin) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func TestInboxPostTestSuite(t *testing.T) { | func TestInboxPostTestSuite(t *testing.T) { | ||||||
| 	suite.Run(t, &InboxPostTestSuite{}) | 	suite.Run(t, &InboxPostTestSuite{}) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -20,10 +20,14 @@ package bundb_test | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"context" | 	"context" | ||||||
|  | 	"crypto/rand" | ||||||
|  | 	"crypto/rsa" | ||||||
| 	"testing" | 	"testing" | ||||||
| 	"time" | 	"time" | ||||||
| 
 | 
 | ||||||
| 	"github.com/stretchr/testify/suite" | 	"github.com/stretchr/testify/suite" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/ap" | ||||||
|  | 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| type AccountTestSuite struct { | type AccountTestSuite struct { | ||||||
|  | @ -56,6 +60,34 @@ func (suite *AccountTestSuite) TestUpdateAccount() { | ||||||
| 	suite.WithinDuration(time.Now(), updated.UpdatedAt, 5*time.Second) | 	suite.WithinDuration(time.Now(), updated.UpdatedAt, 5*time.Second) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (suite *AccountTestSuite) TestInsertAccountWithDefaults() { | ||||||
|  | 	key, err := rsa.GenerateKey(rand.Reader, 2048) | ||||||
|  | 	suite.NoError(err) | ||||||
|  | 
 | ||||||
|  | 	newAccount := >smodel.Account{ | ||||||
|  | 		ID:           "01FGP5P4VJ9SPFB0T3E36Q60DW", | ||||||
|  | 		Username:     "test_service", | ||||||
|  | 		Domain:       "example.org", | ||||||
|  | 		URI:          "https://example.org/users/test_service", | ||||||
|  | 		URL:          "https://example.org/@test_service", | ||||||
|  | 		ActorType:    ap.ActorService, | ||||||
|  | 		PublicKey:    &key.PublicKey, | ||||||
|  | 		PublicKeyURI: "https://example.org/users/test_service#main-key", | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	err = suite.db.Put(context.Background(), newAccount) | ||||||
|  | 	suite.NoError(err) | ||||||
|  | 
 | ||||||
|  | 	suite.Equal("en", newAccount.Language) | ||||||
|  | 	suite.WithinDuration(time.Now(), newAccount.CreatedAt, 30*time.Second) | ||||||
|  | 	suite.WithinDuration(time.Now(), newAccount.UpdatedAt, 30*time.Second) | ||||||
|  | 	suite.False(newAccount.Memorial) | ||||||
|  | 	suite.False(newAccount.Bot) | ||||||
|  | 	suite.False(newAccount.Discoverable) | ||||||
|  | 	suite.False(newAccount.Sensitive) | ||||||
|  | 	suite.False(newAccount.HideCollections) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func TestAccountTestSuite(t *testing.T) { | func TestAccountTestSuite(t *testing.T) { | ||||||
| 	suite.Run(t, new(AccountTestSuite)) | 	suite.Run(t, new(AccountTestSuite)) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -98,8 +98,7 @@ func (f *federatingDB) Update(ctx context.Context, asType vocab.Type) error { | ||||||
| 		typeName == ap.ActorService { | 		typeName == ap.ActorService { | ||||||
| 		// it's an UPDATE to some kind of account | 		// it's an UPDATE to some kind of account | ||||||
| 		var accountable ap.Accountable | 		var accountable ap.Accountable | ||||||
| 
 | 		switch typeName { | ||||||
| 		switch asType.GetTypeName() { |  | ||||||
| 		case ap.ActorApplication: | 		case ap.ActorApplication: | ||||||
| 			l.Debug("got update for APPLICATION") | 			l.Debug("got update for APPLICATION") | ||||||
| 			i, ok := asType.(vocab.ActivityStreamsApplication) | 			i, ok := asType.(vocab.ActivityStreamsApplication) | ||||||
|  | @ -152,19 +151,24 @@ func (f *federatingDB) Update(ctx context.Context, asType vocab.Type) error { | ||||||
| 			return fmt.Errorf("UPDATE: update for account %s was requested by account %s, this is not valid", updatedAcct.URI, requestingAcct.URI) | 			return fmt.Errorf("UPDATE: update for account %s was requested by account %s, this is not valid", updatedAcct.URI, requestingAcct.URI) | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		updatedAcct.ID = requestingAcct.ID // set this here so the db will update properly instead of trying to PUT this and getting constraint issues | 		// set some fields here on the updatedAccount representation so we don't run into db issues | ||||||
|  | 		updatedAcct.CreatedAt = requestingAcct.CreatedAt | ||||||
|  | 		updatedAcct.ID = requestingAcct.ID | ||||||
|  | 		updatedAcct.Language = requestingAcct.Language | ||||||
|  | 
 | ||||||
|  | 		// do the update | ||||||
| 		updatedAcct, err = f.db.UpdateAccount(ctx, updatedAcct) | 		updatedAcct, err = f.db.UpdateAccount(ctx, updatedAcct) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return fmt.Errorf("UPDATE: database error inserting updated account: %s", err) | 			return fmt.Errorf("UPDATE: database error inserting updated account: %s", err) | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | 		// pass to the processor for further processing of eg., avatar/header | ||||||
| 		fromFederatorChan <- messages.FromFederator{ | 		fromFederatorChan <- messages.FromFederator{ | ||||||
| 			APObjectType:     ap.ObjectProfile, | 			APObjectType:     ap.ObjectProfile, | ||||||
| 			APActivityType:   ap.ActivityUpdate, | 			APActivityType:   ap.ActivityUpdate, | ||||||
| 			GTSModel:         updatedAcct, | 			GTSModel:         updatedAcct, | ||||||
| 			ReceivingAccount: targetAcct, | 			ReceivingAccount: targetAcct, | ||||||
| 		} | 		} | ||||||
| 
 |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return nil | 	return nil | ||||||
|  |  | ||||||
|  | @ -22,7 +22,6 @@ import ( | ||||||
| 	"context" | 	"context" | ||||||
| 	"errors" | 	"errors" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"net/url" |  | ||||||
| 
 | 
 | ||||||
| 	"github.com/sirupsen/logrus" | 	"github.com/sirupsen/logrus" | ||||||
| 	"github.com/superseriousbusiness/gotosocial/internal/ap" | 	"github.com/superseriousbusiness/gotosocial/internal/ap" | ||||||
|  | @ -141,13 +140,8 @@ func (p *processor) ProcessFromFederator(ctx context.Context, federatorMsg messa | ||||||
| 				return errors.New("profile was not parseable as *gtsmodel.Account") | 				return errors.New("profile was not parseable as *gtsmodel.Account") | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			incomingAccountURI, err := url.Parse(incomingAccount.URI) | 			if _, err := p.federator.EnrichRemoteAccount(ctx, federatorMsg.ReceivingAccount.Username, incomingAccount); err != nil { | ||||||
| 			if err != nil { | 				return fmt.Errorf("error enriching updated account from federator: %s", err) | ||||||
| 				return err |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			if _, _, err := p.federator.GetRemoteAccount(ctx, federatorMsg.ReceivingAccount.Username, incomingAccountURI, true); err != nil { |  | ||||||
| 				return fmt.Errorf("error dereferencing account from federator: %s", err) |  | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	case ap.ActivityDelete: | 	case ap.ActivityDelete: | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue