mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-10-31 02:02:25 -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) | ||||
| } | ||||
| 
 | ||||
| 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) { | ||||
| 	suite.Run(t, &InboxPostTestSuite{}) | ||||
| } | ||||
|  |  | |||
|  | @ -20,10 +20,14 @@ package bundb_test | |||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"crypto/rand" | ||||
| 	"crypto/rsa" | ||||
| 	"testing" | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/stretchr/testify/suite" | ||||
| 	"github.com/superseriousbusiness/gotosocial/internal/ap" | ||||
| 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | ||||
| ) | ||||
| 
 | ||||
| type AccountTestSuite struct { | ||||
|  | @ -56,6 +60,34 @@ func (suite *AccountTestSuite) TestUpdateAccount() { | |||
| 	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) { | ||||
| 	suite.Run(t, new(AccountTestSuite)) | ||||
| } | ||||
|  |  | |||
|  | @ -98,8 +98,7 @@ func (f *federatingDB) Update(ctx context.Context, asType vocab.Type) error { | |||
| 		typeName == ap.ActorService { | ||||
| 		// it's an UPDATE to some kind of account | ||||
| 		var accountable ap.Accountable | ||||
| 
 | ||||
| 		switch asType.GetTypeName() { | ||||
| 		switch typeName { | ||||
| 		case ap.ActorApplication: | ||||
| 			l.Debug("got update for APPLICATION") | ||||
| 			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) | ||||
| 		} | ||||
| 
 | ||||
| 		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) | ||||
| 		if err != nil { | ||||
| 			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{ | ||||
| 			APObjectType:     ap.ObjectProfile, | ||||
| 			APActivityType:   ap.ActivityUpdate, | ||||
| 			GTSModel:         updatedAcct, | ||||
| 			ReceivingAccount: targetAcct, | ||||
| 		} | ||||
| 
 | ||||
| 	} | ||||
| 
 | ||||
| 	return nil | ||||
|  |  | |||
|  | @ -22,7 +22,6 @@ import ( | |||
| 	"context" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"net/url" | ||||
| 
 | ||||
| 	"github.com/sirupsen/logrus" | ||||
| 	"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") | ||||
| 			} | ||||
| 
 | ||||
| 			incomingAccountURI, err := url.Parse(incomingAccount.URI) | ||||
| 			if err != nil { | ||||
| 				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) | ||||
| 			if _, err := p.federator.EnrichRemoteAccount(ctx, federatorMsg.ReceivingAccount.Username, incomingAccount); err != nil { | ||||
| 				return fmt.Errorf("error enriching updated account from federator: %s", err) | ||||
| 			} | ||||
| 		} | ||||
| 	case ap.ActivityDelete: | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue