From 2453957a6e334105a5df893f7d8f1dcd3eca409a Mon Sep 17 00:00:00 2001 From: tsmethurst Date: Fri, 14 May 2021 13:07:17 +0200 Subject: [PATCH] bleep bloop --- internal/federation/federating_db.go | 10 ++-- internal/federation/federatingprotocol.go | 50 +++++++++++++++- internal/typeutils/asextractionutil.go | 6 -- internal/typeutils/astointernal.go | 71 ++++++++++++++++++++--- internal/util/uri.go | 4 ++ 5 files changed, 122 insertions(+), 19 deletions(-) diff --git a/internal/federation/federating_db.go b/internal/federation/federating_db.go index eb5b82f30..40c12ecb3 100644 --- a/internal/federation/federating_db.go +++ b/internal/federation/federating_db.go @@ -359,16 +359,12 @@ func (f *federatingDB) Create(c context.Context, asType vocab.Type) error { ) l.Debugf("received CREATE asType %+v", asType) - - - switch gtsmodel.ActivityStreamsActivity(asType.GetTypeName()) { case gtsmodel.ActivityStreamsCreate: create, ok := asType.(vocab.ActivityStreamsCreate) if !ok { return errors.New("could not convert type to create") } - object := create.GetActivityStreamsObject() for objectIter := object.Begin(); objectIter != object.End(); objectIter = objectIter.Next() { switch gtsmodel.ActivityStreamsObject(objectIter.GetType().GetTypeName()) { @@ -383,6 +379,12 @@ func (f *federatingDB) Create(c context.Context, asType vocab.Type) error { } } } + case gtsmodel.ActivityStreamsFollow: + follow, ok := asType.(vocab.ActivityStreamsFollow) + if !ok { + return errors.New("could not convert type to follow") + } + } return nil } diff --git a/internal/federation/federatingprotocol.go b/internal/federation/federatingprotocol.go index d549a157a..45fca5f01 100644 --- a/internal/federation/federatingprotocol.go +++ b/internal/federation/federatingprotocol.go @@ -72,8 +72,49 @@ func (f *federator) PostInboxRequestBodyHook(ctx context.Context, r *http.Reques return nil, err } - ctxWithActivity := context.WithValue(ctx, util.APActivity, activity) - return ctxWithActivity, nil + // derefence the actor of the activity already + // var requestingActorIRI *url.URL + // actorProp := activity.GetActivityStreamsActor() + // if actorProp != nil { + // for i := actorProp.Begin(); i != actorProp.End(); i = i.Next() { + // if i.IsIRI() { + // requestingActorIRI = i.GetIRI() + // break + // } + // } + // } + // if requestingActorIRI != nil { + + // requestedAccountI := ctx.Value(util.APAccount) + // requestedAccount, ok := requestedAccountI.(*gtsmodel.Account) + // if !ok { + // return nil, errors.New("requested account was not set on request context") + // } + + // requestingActor := >smodel.Account{} + // if err := f.db.GetWhere("uri", requestingActorIRI.String(), requestingActor); err != nil { + // // there's been a proper error so return it + // if _, ok := err.(db.ErrNoEntries); !ok { + // return nil, fmt.Errorf("error getting requesting actor with id %s: %s", requestingActorIRI.String(), err) + // } + + // // we don't know this account (yet) so let's dereference it right now + // person, err := f.DereferenceRemoteAccount(requestedAccount.Username, publicKeyOwnerURI) + // if err != nil { + // return ctx, false, fmt.Errorf("error dereferencing account with public key id %s: %s", publicKeyOwnerURI.String(), err) + // } + + // a, err := f.typeConverter.ASRepresentationToAccount(person) + // if err != nil { + // return ctx, false, fmt.Errorf("error converting person with public key id %s to account: %s", publicKeyOwnerURI.String(), err) + // } + // requestingAccount = a + // } + // } + + // set the activity on the context for use later on + + return context.WithValue(ctx, util.APActivity, activity), nil } // AuthenticatePostInbox delegates the authentication of a POST to an @@ -141,6 +182,11 @@ func (f *federator) AuthenticatePostInbox(ctx context.Context, w http.ResponseWr if err != nil { return ctx, false, fmt.Errorf("error converting person with public key id %s to account: %s", publicKeyOwnerURI.String(), err) } + + if err := f.db.Put(a); err != nil { + l.Errorf("error inserting dereferenced remote account: %s", err) + } + requestingAccount = a } diff --git a/internal/typeutils/asextractionutil.go b/internal/typeutils/asextractionutil.go index f3d2b1c4f..b5ce2d02a 100644 --- a/internal/typeutils/asextractionutil.go +++ b/internal/typeutils/asextractionutil.go @@ -82,9 +82,6 @@ func extractTos(i withTo) ([]*url.URL, error) { } } } - if len(to) == 0 { - return nil, errors.New("found no to entries") - } return to, nil } @@ -98,9 +95,6 @@ func extractCCs(i withCC) ([]*url.URL, error) { } } } - if len(cc) == 0 { - return nil, errors.New("found no cc entries") - } return cc, nil } diff --git a/internal/typeutils/astointernal.go b/internal/typeutils/astointernal.go index e2017f9b8..f8b76ffe5 100644 --- a/internal/typeutils/astointernal.go +++ b/internal/typeutils/astointernal.go @@ -21,6 +21,8 @@ package typeutils import ( "errors" "fmt" + "net/url" + "strings" "github.com/superseriousbusiness/gotosocial/internal/db" "github.com/superseriousbusiness/gotosocial/internal/gtsmodel" @@ -218,10 +220,11 @@ func (c *converter) ASStatusToStatus(statusable Statusable) (*gtsmodel.Status, e status.APStatusOwnerURI = attributedTo.String() statusOwner := >smodel.Account{} - if err := c.db.GetWhere("uri", attributedTo.String(), statusOwner); err == nil { - status.AccountID = statusOwner.ID - status.GTSAccount = statusOwner + if err := c.db.GetWhere("uri", attributedTo.String(), statusOwner); err != nil { + return nil, fmt.Errorf("couldn't get status owner from db: %s", err) } + status.AccountID = statusOwner.ID + status.GTSAccount = statusOwner // check if there's a post that this is a reply to inReplyToURI, err := extractInReplyToURI(statusable) @@ -248,10 +251,45 @@ func (c *converter) ASStatusToStatus(statusable Statusable) (*gtsmodel.Status, e } // visibility entry for this status - // TODO: if it's just got followers in TO and it's not CC'ed to public, it's followers only - // TODO: if it's CC'ed to public, it's public or unlocked - // TODO: if it's a DM then it's addressed to SPECIFIC ACCOUNTS and not followers or public - // TODO: mentioned SPECIFIC ACCOUNTS also get added to CC'es if it's not a direct message + var visibility gtsmodel.Visibility + + to, err := extractTos(statusable) + if err != nil { + return nil, fmt.Errorf("error extracting TO values: %s", err) + } + + cc, err := extractCCs(statusable) + if err != nil { + return nil, fmt.Errorf("error extracting CC values: %s", err) + } + + if len(to) == 0 && len(cc) == 0 { + return nil, errors.New("message wasn't TO or CC anyone") + } + + // for visibility derivation, we start by assuming most restrictive, and work our way to least restrictive + + // if it's a DM then it's addressed to SPECIFIC ACCOUNTS and not followers or public + if len(to) != 0 && len(cc) == 0 { + visibility = gtsmodel.VisibilityDirect + } + + // if it's just got followers in TO and it's not also CC'ed to public, it's followers only + if isFollowers(to, statusOwner.FollowersURI) { + visibility = gtsmodel.VisibilityFollowersOnly + } + + // if it's CC'ed to public, it's public or unlocked + // mentioned SPECIFIC ACCOUNTS also get added to CC'es if it's not a direct message + if isPublic(to) { + visibility = gtsmodel.VisibilityPublic + } + + // we should have a visibility by now + if visibility == "" { + return nil, errors.New("couldn't derive visibility") + } + status.Visibility = visibility // advanced visibility for this status // TODO: a lot of work to be done here -- a new type needs to be created for this in go-fed/activity using ASTOOL @@ -262,7 +300,26 @@ func (c *converter) ASStatusToStatus(statusable Statusable) (*gtsmodel.Status, e // language // we might be able to extract this from the contentMap field + // ActivityStreamsType status.ActivityStreamsType = gtsmodel.ActivityStreamsObject(statusable.GetTypeName()) return status, nil } + +func isPublic(tos []*url.URL) bool { + for _, entry := range tos { + if strings.EqualFold(entry.String(), "https://www.w3.org/ns/activitystreams#Public") { + return true + } + } + return false +} + +func isFollowers(ccs []*url.URL, followersURI string) bool { + for _, entry := range ccs { + if strings.EqualFold(entry.String(), followersURI) { + return true + } + } + return false +} diff --git a/internal/util/uri.go b/internal/util/uri.go index 2b0020b4e..edcfc5c02 100644 --- a/internal/util/uri.go +++ b/internal/util/uri.go @@ -58,7 +58,11 @@ const ( // APAccount can be used the set and retrieve the account being interacted with APAccount APContextKey = "account" // APRequestingAccount can be used to set and retrieve the account of an incoming federation request. + // This will often be the actor of the instance that's posting the request. APRequestingAccount APContextKey = "requestingAccount" + // APRequestingActorIRI can be used to set and retrieve the actor of an incoming federation request. + // This will usually be the owner of whatever activity is being posted. + APRequestingActorIRI APContextKey = "requestingActorIRI" // APRequestingPublicKeyID can be used to set and retrieve the public key ID of an incoming federation request. APRequestingPublicKeyID APContextKey = "requestingPublicKeyID" // APFromFederatorChanKey can be used to pass a pointer to the fromFederator channel into the federator for use in callbacks.