diff options
| author | 2021-05-28 22:47:18 +0200 | |
|---|---|---|
| committer | 2021-05-28 22:47:18 +0200 | |
| commit | cb54324430e7c4640a7aa5aac24932b5e91b71c4 (patch) | |
| tree | a5193ee09656d808f589de20f77a5a455a5a6683 /internal | |
| parent | Announce/boost (#35) (diff) | |
| download | gotosocial-cb54324430e7c4640a7aa5aac24932b5e91b71c4.tar.xz | |
federate account updates
Diffstat (limited to 'internal')
| -rw-r--r-- | internal/federation/federatingdb/update.go | 6 | ||||
| -rw-r--r-- | internal/federation/federatingdb/util.go | 13 | ||||
| -rw-r--r-- | internal/message/accountprocess.go | 7 | ||||
| -rw-r--r-- | internal/message/fromclientapiprocess.go | 32 | ||||
| -rw-r--r-- | internal/typeutils/converter.go | 7 | ||||
| -rw-r--r-- | internal/typeutils/wrap.go | 61 | ||||
| -rw-r--r-- | internal/util/uri.go | 12 | 
7 files changed, 135 insertions, 3 deletions
| diff --git a/internal/federation/federatingdb/update.go b/internal/federation/federatingdb/update.go index 3ac5f265a..1a148056b 100644 --- a/internal/federation/federatingdb/update.go +++ b/internal/federation/federatingdb/update.go @@ -120,6 +120,12 @@ func (f *federatingDB) Update(ctx context.Context, asType vocab.Type) error {  			return fmt.Errorf("error converting to account: %s", err)  		} +		if updatedAcct.Domain == f.config.Host { +			// no need to update local accounts +			// in fact, if we do this will break the shit out of things so do NOT +			return nil +		} +  		if requestingAcct.URI != updatedAcct.URI {  			return fmt.Errorf("update for account %s was requested by account %s, this is not valid", updatedAcct.URI, requestingAcct.URI)  		} diff --git a/internal/federation/federatingdb/util.go b/internal/federation/federatingdb/util.go index 53fe194a7..ff6ae50a6 100644 --- a/internal/federation/federatingdb/util.go +++ b/internal/federation/federatingdb/util.go @@ -143,6 +143,19 @@ func (f *federatingDB) NewID(c context.Context, t vocab.Type) (id *url.URL, err  				return idProp.GetIRI(), nil  			}  		} +	case gtsmodel.ActivityStreamsUpdate: +		// UPDATE +		// ID might already be set on an update we've created, so check it here and return it if it is +		update, ok := t.(vocab.ActivityStreamsUpdate) +		if !ok { +			return nil, errors.New("newid: fave couldn't be parsed into vocab.ActivityStreamsUpdate") +		} +		idProp := update.GetJSONLDId() +		if idProp != nil { +			if idProp.IsIRI() { +				return idProp.GetIRI(), nil +			} +		}  	}  	// fallback default behavior: just return a random UUID after our protocol and host diff --git a/internal/message/accountprocess.go b/internal/message/accountprocess.go index 8847e5789..ea03ab0ff 100644 --- a/internal/message/accountprocess.go +++ b/internal/message/accountprocess.go @@ -188,6 +188,13 @@ func (p *processor) AccountUpdate(authed *oauth.Auth, form *apimodel.UpdateCrede  		return nil, fmt.Errorf("could not fetch updated account %s: %s", authed.Account.ID, err)  	} +	p.fromClientAPI <- gtsmodel.FromClientAPI{ +		APObjectType:   gtsmodel.ActivityStreamsProfile, +		APActivityType: gtsmodel.ActivityStreamsUpdate, +		GTSModel:       updatedAccount, +		OriginAccount:  updatedAccount, +	} +  	acctSensitive, err := p.tc.AccountToMastoSensitive(updatedAccount)  	if err != nil {  		return nil, fmt.Errorf("could not convert account into mastosensitive account: %s", err) diff --git a/internal/message/fromclientapiprocess.go b/internal/message/fromclientapiprocess.go index 1d30b526c..40a2981a8 100644 --- a/internal/message/fromclientapiprocess.go +++ b/internal/message/fromclientapiprocess.go @@ -88,6 +88,16 @@ func (p *processor) processFromClientAPI(clientMsg gtsmodel.FromClientAPI) error  		}  	case gtsmodel.ActivityStreamsUpdate:  		// UPDATE +		switch clientMsg.APObjectType { +		case gtsmodel.ActivityStreamsProfile, gtsmodel.ActivityStreamsPerson: +			// UPDATE ACCOUNT/PROFILE +			account, ok := clientMsg.GTSModel.(*gtsmodel.Account) +			if !ok { +				return errors.New("account was not parseable as *gtsmodel.Account") +			} + +			return p.federateAccountUpdate(account, clientMsg.OriginAccount) +		}  	case gtsmodel.ActivityStreamsAccept:  		// ACCEPT  		switch clientMsg.APObjectType { @@ -277,7 +287,27 @@ func (p *processor) federateAnnounce(boostWrapperStatus *gtsmodel.Status, boosti  	if err != nil {  		return fmt.Errorf("federateAnnounce: error parsing outboxURI %s: %s", boostingAccount.OutboxURI, err)  	} -	 +  	_, err = p.federator.FederatingActor().Send(context.Background(), outboxIRI, announce)  	return err  } + +func (p *processor) federateAccountUpdate(updatedAccount *gtsmodel.Account, originAccount *gtsmodel.Account) error { +	person, err := p.tc.AccountToAS(updatedAccount) +	if err != nil { +		return fmt.Errorf("federateAccountUpdate: error converting account to person: %s", err) +	} + +	update, err := p.tc.WrapPersonInUpdate(person, originAccount) +	if err != nil { +		return fmt.Errorf("federateAccountUpdate: error wrapping person in update: %s", err) +	} + +	outboxIRI, err := url.Parse(originAccount.OutboxURI) +	if err != nil { +		return fmt.Errorf("federateAnnounce: error parsing outboxURI %s: %s", originAccount.OutboxURI, err) +	} + +	_, err = p.federator.FederatingActor().Send(context.Background(), outboxIRI, update) +	return err +} diff --git a/internal/typeutils/converter.go b/internal/typeutils/converter.go index 93ac6bd84..9cd7ad9b4 100644 --- a/internal/typeutils/converter.go +++ b/internal/typeutils/converter.go @@ -141,6 +141,13 @@ type TypeConverter interface {  	FollowRequestToFollow(f *gtsmodel.FollowRequest) *gtsmodel.Follow  	// StatusToBoost wraps the given status into a boosting status.  	StatusToBoost(s *gtsmodel.Status, boostingAccount *gtsmodel.Account) (*gtsmodel.Status, error) + +	/* +		WRAPPER CONVENIENCE FUNCTIONS +	*/ +	 +	// WrapPersonInUpdate +	WrapPersonInUpdate(person vocab.ActivityStreamsPerson, originAccount *gtsmodel.Account) (vocab.ActivityStreamsUpdate, error)  }  type converter struct { diff --git a/internal/typeutils/wrap.go b/internal/typeutils/wrap.go new file mode 100644 index 000000000..fde6fda79 --- /dev/null +++ b/internal/typeutils/wrap.go @@ -0,0 +1,61 @@ +package typeutils + +import ( +	"fmt" +	"net/url" + +	"github.com/go-fed/activity/streams" +	"github.com/go-fed/activity/streams/vocab" +	"github.com/google/uuid" +	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" +	"github.com/superseriousbusiness/gotosocial/internal/util" +) + +func (c *converter) WrapPersonInUpdate(person vocab.ActivityStreamsPerson, originAccount *gtsmodel.Account) (vocab.ActivityStreamsUpdate, error) { + +	update := streams.NewActivityStreamsUpdate() + +	// set the actor +	actorURI, err := url.Parse(originAccount.URI) +	if err != nil { +		return nil, fmt.Errorf("WrapPersonInUpdate: error parsing url %s: %s", originAccount.URI, err) +	} +	actorProp := streams.NewActivityStreamsActorProperty() +	actorProp.AppendIRI(actorURI) +	update.SetActivityStreamsActor(actorProp) + +	// set the ID +	idString := util.GenerateURIForUpdate(originAccount.Username, c.config.Protocol, c.config.Host, uuid.NewString()) +	idURI, err := url.Parse(idString) +	if err != nil { +		return nil, fmt.Errorf("WrapPersonInUpdate: error parsing url %s: %s", idString, err) +	} +	idProp := streams.NewJSONLDIdProperty() +	idProp.SetIRI(idURI) +	update.SetJSONLDId(idProp) + +	// set the person as the object here +	objectProp := streams.NewActivityStreamsObjectProperty() +	objectProp.AppendActivityStreamsPerson(person) +	update.SetActivityStreamsObject(objectProp) + +	// to should be public +	toURI, err := url.Parse(asPublicURI) +	if err != nil { +		return nil, fmt.Errorf("WrapPersonInUpdate: error parsing url %s: %s", asPublicURI, err) +	} +	toProp := streams.NewActivityStreamsToProperty() +	toProp.AppendIRI(toURI) +	update.SetActivityStreamsTo(toProp) + +	// bcc followers +	followersURI, err := url.Parse(originAccount.FollowersURI) +	if err != nil { +		return nil, fmt.Errorf("WrapPersonInUpdate: error parsing url %s: %s", originAccount.FollowersURI, err) +	} +	bccProp := streams.NewActivityStreamsBccProperty() +	bccProp.AppendIRI(followersURI) +	update.SetActivityStreamsBcc(bccProp) + +	return update, nil +} diff --git a/internal/util/uri.go b/internal/util/uri.go index 8d64bdd8e..d8dce803b 100644 --- a/internal/util/uri.go +++ b/internal/util/uri.go @@ -49,6 +49,8 @@ const (  	PublicKeyPath = "main-key"  	// FollowPath used to generate the URI for an individual follow or follow request  	FollowPath = "follow" +	// UpdatePath is used to generate the URI for an account update +	UpdatePath = "updates"  )  // APContextKey is a type used specifically for settings values on contexts within go-fed AP request chains @@ -108,13 +110,19 @@ type UserURIs struct {  // GenerateURIForFollow returns the AP URI for a new follow -- something like:  // https://example.org/users/whatever_user/follow/41c7f33f-1060-48d9-84df-38dcb13cf0d8  func GenerateURIForFollow(username string, protocol string, host string, thisFollowID string) string { -	return fmt.Sprintf("%s://%s/%s/%s/%s", protocol, host, UsersPath, FollowPath, thisFollowID) +	return fmt.Sprintf("%s://%s/%s/%s/%s/%s", protocol, host, UsersPath, username, FollowPath, thisFollowID)  }  // GenerateURIForFollow returns the AP URI for a new like/fave -- something like:  // https://example.org/users/whatever_user/liked/41c7f33f-1060-48d9-84df-38dcb13cf0d8  func GenerateURIForLike(username string, protocol string, host string, thisFavedID string) string { -	return fmt.Sprintf("%s://%s/%s/%s/%s", protocol, host, UsersPath, LikedPath, thisFavedID) +	return fmt.Sprintf("%s://%s/%s/%s/%s/%s", protocol, host, UsersPath, username, LikedPath, thisFavedID) +} + +// GenerateURIForUpdate returns the AP URI for a new update activity -- something like: +// https://example.org/users/whatever_user#updates/41c7f33f-1060-48d9-84df-38dcb13cf0d8 +func GenerateURIForUpdate(username string, protocol string, host string, thisUpdateID string) string { +	return fmt.Sprintf("%s://%s/%s/%s#%s/%s", protocol, host, UsersPath, username, UpdatePath, thisUpdateID)  }  // GenerateURIsForAccount throws together a bunch of URIs for the given username, with the given protocol and host. | 
