forked from mirrors/gotosocial
federate account updates
This commit is contained in:
parent
87177d840b
commit
cb54324430
7 changed files with 135 additions and 3 deletions
|
@ -120,6 +120,12 @@ func (f *federatingDB) Update(ctx context.Context, asType vocab.Type) error {
|
||||||
return fmt.Errorf("error converting to account: %s", err)
|
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 {
|
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)
|
return fmt.Errorf("update for account %s was requested by account %s, this is not valid", updatedAcct.URI, requestingAcct.URI)
|
||||||
}
|
}
|
||||||
|
|
|
@ -143,6 +143,19 @@ func (f *federatingDB) NewID(c context.Context, t vocab.Type) (id *url.URL, err
|
||||||
return idProp.GetIRI(), nil
|
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
|
// fallback default behavior: just return a random UUID after our protocol and host
|
||||||
|
|
|
@ -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)
|
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)
|
acctSensitive, err := p.tc.AccountToMastoSensitive(updatedAccount)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("could not convert account into mastosensitive account: %s", err)
|
return nil, fmt.Errorf("could not convert account into mastosensitive account: %s", err)
|
||||||
|
|
|
@ -88,6 +88,16 @@ func (p *processor) processFromClientAPI(clientMsg gtsmodel.FromClientAPI) error
|
||||||
}
|
}
|
||||||
case gtsmodel.ActivityStreamsUpdate:
|
case gtsmodel.ActivityStreamsUpdate:
|
||||||
// UPDATE
|
// 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:
|
case gtsmodel.ActivityStreamsAccept:
|
||||||
// ACCEPT
|
// ACCEPT
|
||||||
switch clientMsg.APObjectType {
|
switch clientMsg.APObjectType {
|
||||||
|
@ -281,3 +291,23 @@ func (p *processor) federateAnnounce(boostWrapperStatus *gtsmodel.Status, boosti
|
||||||
_, err = p.federator.FederatingActor().Send(context.Background(), outboxIRI, announce)
|
_, err = p.federator.FederatingActor().Send(context.Background(), outboxIRI, announce)
|
||||||
return err
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -141,6 +141,13 @@ type TypeConverter interface {
|
||||||
FollowRequestToFollow(f *gtsmodel.FollowRequest) *gtsmodel.Follow
|
FollowRequestToFollow(f *gtsmodel.FollowRequest) *gtsmodel.Follow
|
||||||
// StatusToBoost wraps the given status into a boosting status.
|
// StatusToBoost wraps the given status into a boosting status.
|
||||||
StatusToBoost(s *gtsmodel.Status, boostingAccount *gtsmodel.Account) (*gtsmodel.Status, error)
|
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 {
|
type converter struct {
|
||||||
|
|
61
internal/typeutils/wrap.go
Normal file
61
internal/typeutils/wrap.go
Normal file
|
@ -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
|
||||||
|
}
|
|
@ -49,6 +49,8 @@ const (
|
||||||
PublicKeyPath = "main-key"
|
PublicKeyPath = "main-key"
|
||||||
// FollowPath used to generate the URI for an individual follow or follow request
|
// FollowPath used to generate the URI for an individual follow or follow request
|
||||||
FollowPath = "follow"
|
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
|
// 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:
|
// GenerateURIForFollow returns the AP URI for a new follow -- something like:
|
||||||
// https://example.org/users/whatever_user/follow/41c7f33f-1060-48d9-84df-38dcb13cf0d8
|
// https://example.org/users/whatever_user/follow/41c7f33f-1060-48d9-84df-38dcb13cf0d8
|
||||||
func GenerateURIForFollow(username string, protocol string, host string, thisFollowID string) string {
|
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:
|
// GenerateURIForFollow returns the AP URI for a new like/fave -- something like:
|
||||||
// https://example.org/users/whatever_user/liked/41c7f33f-1060-48d9-84df-38dcb13cf0d8
|
// https://example.org/users/whatever_user/liked/41c7f33f-1060-48d9-84df-38dcb13cf0d8
|
||||||
func GenerateURIForLike(username string, protocol string, host string, thisFavedID string) string {
|
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.
|
// GenerateURIsForAccount throws together a bunch of URIs for the given username, with the given protocol and host.
|
||||||
|
|
Loading…
Reference in a new issue