mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2025-10-30 11:12:26 -05:00
tidy up some federation stuff
This commit is contained in:
parent
621e59fd42
commit
211c43073f
11 changed files with 199 additions and 86 deletions
|
|
@ -32,8 +32,13 @@ import (
|
||||||
type Distributor interface {
|
type Distributor interface {
|
||||||
// FromClientAPI returns a channel for accepting messages that come from the gts client API.
|
// FromClientAPI returns a channel for accepting messages that come from the gts client API.
|
||||||
FromClientAPI() chan FromClientAPI
|
FromClientAPI() chan FromClientAPI
|
||||||
// ClientAPIOut returns a channel for putting in messages that need to go to the gts client API.
|
// ToClientAPI returns a channel for putting in messages that need to go to the gts client API.
|
||||||
ToClientAPI() chan ToClientAPI
|
ToClientAPI() chan ToClientAPI
|
||||||
|
// FromFederator returns a channel for accepting messages that come from the federator (activitypub).
|
||||||
|
FromFederator() chan FromFederator
|
||||||
|
// ToFederator returns a channel for putting in messages that need to go to the federator (activitypub).
|
||||||
|
ToFederator() chan ToFederator
|
||||||
|
|
||||||
// Start starts the Distributor, reading from its channels and passing messages back and forth.
|
// Start starts the Distributor, reading from its channels and passing messages back and forth.
|
||||||
Start() error
|
Start() error
|
||||||
// Stop stops the distributor cleanly, finishing handling any remaining messages before closing down.
|
// Stop stops the distributor cleanly, finishing handling any remaining messages before closing down.
|
||||||
|
|
@ -45,6 +50,8 @@ type distributor struct {
|
||||||
// federator pub.FederatingActor
|
// federator pub.FederatingActor
|
||||||
fromClientAPI chan FromClientAPI
|
fromClientAPI chan FromClientAPI
|
||||||
toClientAPI chan ToClientAPI
|
toClientAPI chan ToClientAPI
|
||||||
|
fromFederator chan FromFederator
|
||||||
|
toFederator chan ToFederator
|
||||||
stop chan interface{}
|
stop chan interface{}
|
||||||
log *logrus.Logger
|
log *logrus.Logger
|
||||||
}
|
}
|
||||||
|
|
@ -55,21 +62,29 @@ func New(log *logrus.Logger) Distributor {
|
||||||
// federator: federator,
|
// federator: federator,
|
||||||
fromClientAPI: make(chan FromClientAPI, 100),
|
fromClientAPI: make(chan FromClientAPI, 100),
|
||||||
toClientAPI: make(chan ToClientAPI, 100),
|
toClientAPI: make(chan ToClientAPI, 100),
|
||||||
|
fromFederator: make(chan FromFederator, 100),
|
||||||
|
toFederator: make(chan ToFederator, 100),
|
||||||
stop: make(chan interface{}),
|
stop: make(chan interface{}),
|
||||||
log: log,
|
log: log,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClientAPIIn returns a channel for accepting messages that come from the gts client API.
|
|
||||||
func (d *distributor) FromClientAPI() chan FromClientAPI {
|
func (d *distributor) FromClientAPI() chan FromClientAPI {
|
||||||
return d.fromClientAPI
|
return d.fromClientAPI
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClientAPIOut returns a channel for putting in messages that need to go to the gts client API.
|
|
||||||
func (d *distributor) ToClientAPI() chan ToClientAPI {
|
func (d *distributor) ToClientAPI() chan ToClientAPI {
|
||||||
return d.toClientAPI
|
return d.toClientAPI
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *distributor) FromFederator() chan FromFederator {
|
||||||
|
return d.fromFederator
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *distributor) ToFederator() chan ToFederator {
|
||||||
|
return d.toFederator
|
||||||
|
}
|
||||||
|
|
||||||
// Start starts the Distributor, reading from its channels and passing messages back and forth.
|
// Start starts the Distributor, reading from its channels and passing messages back and forth.
|
||||||
func (d *distributor) Start() error {
|
func (d *distributor) Start() error {
|
||||||
go func() {
|
go func() {
|
||||||
|
|
@ -80,6 +95,10 @@ func (d *distributor) Start() error {
|
||||||
d.log.Infof("received message FROM client API: %+v", clientMsg)
|
d.log.Infof("received message FROM client API: %+v", clientMsg)
|
||||||
case clientMsg := <-d.toClientAPI:
|
case clientMsg := <-d.toClientAPI:
|
||||||
d.log.Infof("received message TO client API: %+v", clientMsg)
|
d.log.Infof("received message TO client API: %+v", clientMsg)
|
||||||
|
case federatorMsg := <-d.fromFederator:
|
||||||
|
d.log.Infof("received message FROM federator: %+v", federatorMsg)
|
||||||
|
case federatorMsg := <-d.toFederator:
|
||||||
|
d.log.Infof("received message TO federator: %+v", federatorMsg)
|
||||||
case <-d.stop:
|
case <-d.stop:
|
||||||
break DistLoop
|
break DistLoop
|
||||||
}
|
}
|
||||||
|
|
@ -108,3 +127,17 @@ type ToClientAPI struct {
|
||||||
APActivityType gtsmodel.ActivityStreamsActivity
|
APActivityType gtsmodel.ActivityStreamsActivity
|
||||||
Activity interface{}
|
Activity interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FromFederator wraps a message that travels from the federator into the distributor
|
||||||
|
type FromFederator struct {
|
||||||
|
APObjectType gtsmodel.ActivityStreamsObject
|
||||||
|
APActivityType gtsmodel.ActivityStreamsActivity
|
||||||
|
Activity interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ToFederator wraps a message that travels from the distributor into the federator
|
||||||
|
type ToFederator struct {
|
||||||
|
APObjectType gtsmodel.ActivityStreamsObject
|
||||||
|
APActivityType gtsmodel.ActivityStreamsActivity
|
||||||
|
Activity interface{}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,21 +24,14 @@ import (
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/config"
|
"github.com/superseriousbusiness/gotosocial/internal/config"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/db"
|
"github.com/superseriousbusiness/gotosocial/internal/db"
|
||||||
|
"github.com/superseriousbusiness/gotosocial/internal/transport"
|
||||||
)
|
)
|
||||||
|
|
||||||
// New returns a go-fed compatible federating actor
|
// NewFederatingActor returns a go-fed compatible federating actor
|
||||||
func New(db db.DB, config *config.Config, log *logrus.Logger) pub.FederatingActor {
|
func NewFederatingActor(db db.DB, transportController transport.Controller, config *config.Config, log *logrus.Logger) pub.FederatingActor {
|
||||||
|
c := NewCommonBehavior(db, log, config, transportController)
|
||||||
c := &Commoner{
|
f := NewFederatingProtocol(db, log, config, transportController)
|
||||||
db: db,
|
pubDatabase := db.Federation()
|
||||||
log: log,
|
clock := &Clock{}
|
||||||
config: config,
|
return pub.NewFederatingActor(c, f, pubDatabase, clock)
|
||||||
}
|
|
||||||
|
|
||||||
f := &Federator{
|
|
||||||
db: db,
|
|
||||||
log: log,
|
|
||||||
config: config,
|
|
||||||
}
|
|
||||||
return pub.NewFederatingActor(c, f, db.Federation(), &Clock{})
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ package federation
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
|
||||||
|
|
@ -28,13 +29,27 @@ import (
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/config"
|
"github.com/superseriousbusiness/gotosocial/internal/config"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/db"
|
"github.com/superseriousbusiness/gotosocial/internal/db"
|
||||||
|
"github.com/superseriousbusiness/gotosocial/internal/db/gtsmodel"
|
||||||
|
"github.com/superseriousbusiness/gotosocial/internal/transport"
|
||||||
|
"github.com/superseriousbusiness/gotosocial/internal/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Commoner implements the go-fed common behavior interface
|
// commonBehavior implements the go-fed common behavior interface
|
||||||
type Commoner struct {
|
type commonBehavior struct {
|
||||||
db db.DB
|
db db.DB
|
||||||
log *logrus.Logger
|
log *logrus.Logger
|
||||||
config *config.Config
|
config *config.Config
|
||||||
|
transportController transport.Controller
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewCommonBehavior returns an implementation of the pub.CommonBehavior interface that uses the given db, log, config, and transportController
|
||||||
|
func NewCommonBehavior(db db.DB, log *logrus.Logger, config *config.Config, transportController transport.Controller) pub.CommonBehavior {
|
||||||
|
return &commonBehavior{
|
||||||
|
db: db,
|
||||||
|
log: log,
|
||||||
|
config: config,
|
||||||
|
transportController: transportController,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -63,7 +78,7 @@ type Commoner struct {
|
||||||
// Finally, if the authentication and authorization succeeds, then
|
// Finally, if the authentication and authorization succeeds, then
|
||||||
// authenticated must be true and error nil. The request will continue
|
// authenticated must be true and error nil. The request will continue
|
||||||
// to be processed.
|
// to be processed.
|
||||||
func (c *Commoner) AuthenticateGetInbox(ctx context.Context, w http.ResponseWriter, r *http.Request) (context.Context, bool, error) {
|
func (c *commonBehavior) AuthenticateGetInbox(ctx context.Context, w http.ResponseWriter, r *http.Request) (context.Context, bool, error) {
|
||||||
// TODO
|
// TODO
|
||||||
// use context.WithValue() and context.Value() to set and get values through here
|
// use context.WithValue() and context.Value() to set and get values through here
|
||||||
return nil, false, nil
|
return nil, false, nil
|
||||||
|
|
@ -88,7 +103,7 @@ func (c *Commoner) AuthenticateGetInbox(ctx context.Context, w http.ResponseWrit
|
||||||
// Finally, if the authentication and authorization succeeds, then
|
// Finally, if the authentication and authorization succeeds, then
|
||||||
// authenticated must be true and error nil. The request will continue
|
// authenticated must be true and error nil. The request will continue
|
||||||
// to be processed.
|
// to be processed.
|
||||||
func (c *Commoner) AuthenticateGetOutbox(ctx context.Context, w http.ResponseWriter, r *http.Request) (context.Context, bool, error) {
|
func (c *commonBehavior) AuthenticateGetOutbox(ctx context.Context, w http.ResponseWriter, r *http.Request) (context.Context, bool, error) {
|
||||||
// TODO
|
// TODO
|
||||||
return nil, false, nil
|
return nil, false, nil
|
||||||
}
|
}
|
||||||
|
|
@ -101,7 +116,7 @@ func (c *Commoner) AuthenticateGetOutbox(ctx context.Context, w http.ResponseWri
|
||||||
//
|
//
|
||||||
// Always called, regardless whether the Federated Protocol or Social
|
// Always called, regardless whether the Federated Protocol or Social
|
||||||
// API is enabled.
|
// API is enabled.
|
||||||
func (c *Commoner) GetOutbox(ctx context.Context, r *http.Request) (vocab.ActivityStreamsOrderedCollectionPage, error) {
|
func (c *commonBehavior) GetOutbox(ctx context.Context, r *http.Request) (vocab.ActivityStreamsOrderedCollectionPage, error) {
|
||||||
// TODO
|
// TODO
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
@ -129,34 +144,29 @@ func (c *Commoner) GetOutbox(ctx context.Context, r *http.Request) (vocab.Activi
|
||||||
// Note that the library will not maintain a long-lived pointer to the
|
// Note that the library will not maintain a long-lived pointer to the
|
||||||
// returned Transport so that any private credentials are able to be
|
// returned Transport so that any private credentials are able to be
|
||||||
// garbage collected.
|
// garbage collected.
|
||||||
func (c *Commoner) NewTransport(ctx context.Context, actorBoxIRI *url.URL, gofedAgent string) (pub.Transport, error) {
|
func (c *commonBehavior) NewTransport(ctx context.Context, actorBoxIRI *url.URL, gofedAgent string) (pub.Transport, error) {
|
||||||
// TODO
|
|
||||||
// prefs := []httpsig.Algorithm{httpsig.RSA_SHA256}
|
|
||||||
// digestPref := httpsig.DigestSha256
|
|
||||||
// getHeadersToSign := []string{httpsig.RequestTarget, "Date"}
|
|
||||||
// postHeadersToSign := []string{httpsig.RequestTarget, "Date", "Digest"}
|
|
||||||
// // Using github.com/go-fed/httpsig for HTTP Signatures:
|
|
||||||
// getSigner, _, err := httpsig.NewSigner(prefs, digestPref, getHeadersToSign, httpsig.Signature)
|
|
||||||
// if err != nil {
|
|
||||||
// return nil, err
|
|
||||||
// }
|
|
||||||
// postSigner, _, err := httpsig.NewSigner(prefs, digestPref, postHeadersToSign, httpsig.Signature)
|
|
||||||
// if err != nil {
|
|
||||||
// return nil, err
|
|
||||||
// }
|
|
||||||
// pubKeyId, privKey, err := s.getKeysForActorBoxIRI(actorBoxIRI)
|
|
||||||
// client := &http.Client{
|
|
||||||
// Timeout: time.Second * 30,
|
|
||||||
// }
|
|
||||||
// t := pub.NewHttpSigTransport(
|
|
||||||
// client,
|
|
||||||
// f.config.Host,
|
|
||||||
// &Clock{},
|
|
||||||
// getSigner,
|
|
||||||
// postSigner,
|
|
||||||
// pubKeyId,
|
|
||||||
// privKey)
|
|
||||||
|
|
||||||
return nil, nil
|
var username string
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if util.IsInboxPath(actorBoxIRI) {
|
||||||
|
username, err = util.ParseInboxPath(actorBoxIRI)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("couldn't parse path %s as an inbox: %s", actorBoxIRI.String(), err)
|
||||||
|
}
|
||||||
|
} else if util.IsOutboxPath(actorBoxIRI) {
|
||||||
|
username, err = util.ParseOutboxPath(actorBoxIRI)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("couldn't parse path %s as an outbox: %s", actorBoxIRI.String(), err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return nil, fmt.Errorf("id %s was neither an inbox path nor an outbox path", actorBoxIRI.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
account := >smodel.Account{}
|
||||||
|
if err := c.db.GetWhere("username", username, account); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.transportController.NewTransport(account.PublicKeyURI, account.PrivateKey)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
41
internal/federation/federator.go
Normal file
41
internal/federation/federator.go
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
GoToSocial
|
||||||
|
Copyright (C) 2021 GoToSocial Authors admin@gotosocial.org
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package federation
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/go-fed/activity/pub"
|
||||||
|
"github.com/superseriousbusiness/gotosocial/internal/distributor"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Federator wraps everything needed to manage activitypub federation from gotosocial
|
||||||
|
type Federator interface {
|
||||||
|
}
|
||||||
|
|
||||||
|
type federator struct {
|
||||||
|
actor pub.FederatingActor
|
||||||
|
distributor distributor.Distributor
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewFederator returns a new federator that uses the given actor and distributor
|
||||||
|
func NewFederator(actor pub.FederatingActor, distributor distributor.Distributor) Federator {
|
||||||
|
return &federator{
|
||||||
|
actor: actor,
|
||||||
|
distributor: distributor,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -34,17 +34,17 @@ import (
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/util"
|
"github.com/superseriousbusiness/gotosocial/internal/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Federator implements the go-fed federating protocol interface
|
// FederatingProtocol implements the go-fed federating protocol interface
|
||||||
type Federator struct {
|
type FederatingProtocol struct {
|
||||||
db db.DB
|
db db.DB
|
||||||
log *logrus.Logger
|
log *logrus.Logger
|
||||||
config *config.Config
|
config *config.Config
|
||||||
transportController transport.Controller
|
transportController transport.Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewFederator returns the gotosocial implementation of the go-fed FederatingProtocol interface
|
// NewFederatingProtocol returns the gotosocial implementation of the go-fed FederatingProtocol interface
|
||||||
func NewFederator(db db.DB, log *logrus.Logger, config *config.Config, transportController transport.Controller) pub.FederatingProtocol {
|
func NewFederatingProtocol(db db.DB, log *logrus.Logger, config *config.Config, transportController transport.Controller) pub.FederatingProtocol {
|
||||||
return &Federator{
|
return &FederatingProtocol{
|
||||||
db: db,
|
db: db,
|
||||||
log: log,
|
log: log,
|
||||||
config: config,
|
config: config,
|
||||||
|
|
@ -78,7 +78,7 @@ func NewFederator(db db.DB, log *logrus.Logger, config *config.Config, transport
|
||||||
// PostInbox. In this case, the DelegateActor implementation must not
|
// PostInbox. In this case, the DelegateActor implementation must not
|
||||||
// write a response to the ResponseWriter as is expected that the caller
|
// write a response to the ResponseWriter as is expected that the caller
|
||||||
// to PostInbox will do so when handling the error.
|
// to PostInbox will do so when handling the error.
|
||||||
func (f *Federator) PostInboxRequestBodyHook(ctx context.Context, r *http.Request, activity pub.Activity) (context.Context, error) {
|
func (f *FederatingProtocol) PostInboxRequestBodyHook(ctx context.Context, r *http.Request, activity pub.Activity) (context.Context, error) {
|
||||||
l := f.log.WithFields(logrus.Fields{
|
l := f.log.WithFields(logrus.Fields{
|
||||||
"func": "PostInboxRequestBodyHook",
|
"func": "PostInboxRequestBodyHook",
|
||||||
"useragent": r.UserAgent(),
|
"useragent": r.UserAgent(),
|
||||||
|
|
@ -128,7 +128,7 @@ func (f *Federator) PostInboxRequestBodyHook(ctx context.Context, r *http.Reques
|
||||||
// Finally, if the authentication and authorization succeeds, then
|
// Finally, if the authentication and authorization succeeds, then
|
||||||
// authenticated must be true and error nil. The request will continue
|
// authenticated must be true and error nil. The request will continue
|
||||||
// to be processed.
|
// to be processed.
|
||||||
func (f *Federator) AuthenticatePostInbox(ctx context.Context, w http.ResponseWriter, r *http.Request) (context.Context, bool, error) {
|
func (f *FederatingProtocol) AuthenticatePostInbox(ctx context.Context, w http.ResponseWriter, r *http.Request) (context.Context, bool, error) {
|
||||||
l := f.log.WithFields(logrus.Fields{
|
l := f.log.WithFields(logrus.Fields{
|
||||||
"func": "AuthenticatePostInbox",
|
"func": "AuthenticatePostInbox",
|
||||||
"useragent": r.UserAgent(),
|
"useragent": r.UserAgent(),
|
||||||
|
|
@ -167,7 +167,7 @@ func (f *Federator) AuthenticatePostInbox(ctx context.Context, w http.ResponseWr
|
||||||
// Finally, if the authentication and authorization succeeds, then
|
// Finally, if the authentication and authorization succeeds, then
|
||||||
// blocked must be false and error nil. The request will continue
|
// blocked must be false and error nil. The request will continue
|
||||||
// to be processed.
|
// to be processed.
|
||||||
func (f *Federator) Blocked(ctx context.Context, actorIRIs []*url.URL) (bool, error) {
|
func (f *FederatingProtocol) Blocked(ctx context.Context, actorIRIs []*url.URL) (bool, error) {
|
||||||
// TODO
|
// TODO
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
@ -191,7 +191,7 @@ func (f *Federator) Blocked(ctx context.Context, actorIRIs []*url.URL) (bool, er
|
||||||
//
|
//
|
||||||
// Applications are not expected to handle every single ActivityStreams
|
// Applications are not expected to handle every single ActivityStreams
|
||||||
// type and extension. The unhandled ones are passed to DefaultCallback.
|
// type and extension. The unhandled ones are passed to DefaultCallback.
|
||||||
func (f *Federator) FederatingCallbacks(ctx context.Context) (pub.FederatingWrappedCallbacks, []interface{}, error) {
|
func (f *FederatingProtocol) FederatingCallbacks(ctx context.Context) (pub.FederatingWrappedCallbacks, []interface{}, error) {
|
||||||
// TODO
|
// TODO
|
||||||
return pub.FederatingWrappedCallbacks{}, nil, nil
|
return pub.FederatingWrappedCallbacks{}, nil, nil
|
||||||
}
|
}
|
||||||
|
|
@ -203,7 +203,7 @@ func (f *Federator) FederatingCallbacks(ctx context.Context) (pub.FederatingWrap
|
||||||
// Applications are not expected to handle every single ActivityStreams
|
// Applications are not expected to handle every single ActivityStreams
|
||||||
// type and extension, so the unhandled ones are passed to
|
// type and extension, so the unhandled ones are passed to
|
||||||
// DefaultCallback.
|
// DefaultCallback.
|
||||||
func (f *Federator) DefaultCallback(ctx context.Context, activity pub.Activity) error {
|
func (f *FederatingProtocol) DefaultCallback(ctx context.Context, activity pub.Activity) error {
|
||||||
l := f.log.WithFields(logrus.Fields{
|
l := f.log.WithFields(logrus.Fields{
|
||||||
"func": "DefaultCallback",
|
"func": "DefaultCallback",
|
||||||
"aptype": activity.GetTypeName(),
|
"aptype": activity.GetTypeName(),
|
||||||
|
|
@ -216,7 +216,7 @@ func (f *Federator) DefaultCallback(ctx context.Context, activity pub.Activity)
|
||||||
// an activity to determine if inbox forwarding needs to occur.
|
// an activity to determine if inbox forwarding needs to occur.
|
||||||
//
|
//
|
||||||
// Zero or negative numbers indicate infinite recursion.
|
// Zero or negative numbers indicate infinite recursion.
|
||||||
func (f *Federator) MaxInboxForwardingRecursionDepth(ctx context.Context) int {
|
func (f *FederatingProtocol) MaxInboxForwardingRecursionDepth(ctx context.Context) int {
|
||||||
// TODO
|
// TODO
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
@ -226,7 +226,7 @@ func (f *Federator) MaxInboxForwardingRecursionDepth(ctx context.Context) int {
|
||||||
// delivery.
|
// delivery.
|
||||||
//
|
//
|
||||||
// Zero or negative numbers indicate infinite recursion.
|
// Zero or negative numbers indicate infinite recursion.
|
||||||
func (f *Federator) MaxDeliveryRecursionDepth(ctx context.Context) int {
|
func (f *FederatingProtocol) MaxDeliveryRecursionDepth(ctx context.Context) int {
|
||||||
// TODO
|
// TODO
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
@ -238,7 +238,7 @@ func (f *Federator) MaxDeliveryRecursionDepth(ctx context.Context) int {
|
||||||
//
|
//
|
||||||
// The activity is provided as a reference for more intelligent
|
// The activity is provided as a reference for more intelligent
|
||||||
// logic to be used, but the implementation must not modify it.
|
// logic to be used, but the implementation must not modify it.
|
||||||
func (f *Federator) FilterForwarding(ctx context.Context, potentialRecipients []*url.URL, a pub.Activity) ([]*url.URL, error) {
|
func (f *FederatingProtocol) FilterForwarding(ctx context.Context, potentialRecipients []*url.URL, a pub.Activity) ([]*url.URL, error) {
|
||||||
// TODO
|
// TODO
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
@ -251,7 +251,7 @@ func (f *Federator) FilterForwarding(ctx context.Context, potentialRecipients []
|
||||||
//
|
//
|
||||||
// Always called, regardless whether the Federated Protocol or Social
|
// Always called, regardless whether the Federated Protocol or Social
|
||||||
// API is enabled.
|
// API is enabled.
|
||||||
func (f *Federator) GetInbox(ctx context.Context, r *http.Request) (vocab.ActivityStreamsOrderedCollectionPage, error) {
|
func (f *FederatingProtocol) GetInbox(ctx context.Context, r *http.Request) (vocab.ActivityStreamsOrderedCollectionPage, error) {
|
||||||
// TODO
|
// TODO
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,7 @@ func (suite *ProtocolTestSuite) TestPostInboxRequestBodyHook() {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}))
|
}))
|
||||||
// setup module being tested
|
// setup module being tested
|
||||||
federator := federation.NewFederator(suite.db, suite.log, suite.config, tc).(*federation.Federator)
|
federator := federation.NewFederatingProtocol(suite.db, suite.log, suite.config, tc).(*federation.FederatingProtocol)
|
||||||
|
|
||||||
// setup request
|
// setup request
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
@ -156,7 +156,7 @@ func (suite *ProtocolTestSuite) TestAuthenticatePostInbox() {
|
||||||
}))
|
}))
|
||||||
|
|
||||||
// now setup module being tested, with the mock transport controller
|
// now setup module being tested, with the mock transport controller
|
||||||
federator := federation.NewFederator(suite.db, suite.log, suite.config, tc)
|
federator := federation.NewFederatingProtocol(suite.db, suite.log, suite.config, tc)
|
||||||
|
|
||||||
// setup request
|
// setup request
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ package gotosocial
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
@ -45,6 +46,7 @@ import (
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/oauth"
|
"github.com/superseriousbusiness/gotosocial/internal/oauth"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/router"
|
"github.com/superseriousbusiness/gotosocial/internal/router"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/storage"
|
"github.com/superseriousbusiness/gotosocial/internal/storage"
|
||||||
|
"github.com/superseriousbusiness/gotosocial/internal/transport"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/typeutils"
|
"github.com/superseriousbusiness/gotosocial/internal/typeutils"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -72,6 +74,9 @@ var Run action.GTSAction = func(ctx context.Context, c *config.Config, log *logr
|
||||||
if err := distributor.Start(); err != nil {
|
if err := distributor.Start(); err != nil {
|
||||||
return fmt.Errorf("error starting distributor: %s", err)
|
return fmt.Errorf("error starting distributor: %s", err)
|
||||||
}
|
}
|
||||||
|
transportController := transport.NewController(c, &federation.Clock{}, http.DefaultClient, log)
|
||||||
|
federatingActor := federation.NewFederatingActor(dbService, transportController, c, log)
|
||||||
|
federator := federation.NewFederator(federatingActor, distributor)
|
||||||
|
|
||||||
// build converters and util
|
// build converters and util
|
||||||
ic := typeutils.NewConverter(c, dbService)
|
ic := typeutils.NewConverter(c, dbService)
|
||||||
|
|
@ -113,7 +118,7 @@ var Run action.GTSAction = func(ctx context.Context, c *config.Config, log *logr
|
||||||
return fmt.Errorf("error creating instance account: %s", err)
|
return fmt.Errorf("error creating instance account: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
gts, err := New(dbService, &cache.MockCache{}, router, federation.New(dbService, c, log), c)
|
gts, err := New(dbService, &cache.MockCache{}, router, federator, c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error creating gotosocial service: %s", err)
|
return fmt.Errorf("error creating gotosocial service: %s", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,10 +21,10 @@ package gotosocial
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/go-fed/activity/pub"
|
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/cache"
|
"github.com/superseriousbusiness/gotosocial/internal/cache"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/config"
|
"github.com/superseriousbusiness/gotosocial/internal/config"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/db"
|
"github.com/superseriousbusiness/gotosocial/internal/db"
|
||||||
|
"github.com/superseriousbusiness/gotosocial/internal/federation"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/router"
|
"github.com/superseriousbusiness/gotosocial/internal/router"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -38,23 +38,23 @@ type Gotosocial interface {
|
||||||
// New returns a new gotosocial server, initialized with the given configuration.
|
// New returns a new gotosocial server, initialized with the given configuration.
|
||||||
// An error will be returned the caller if something goes wrong during initialization
|
// An error will be returned the caller if something goes wrong during initialization
|
||||||
// eg., no db or storage connection, port for router already in use, etc.
|
// eg., no db or storage connection, port for router already in use, etc.
|
||||||
func New(db db.DB, cache cache.Cache, apiRouter router.Router, federationAPI pub.FederatingActor, config *config.Config) (Gotosocial, error) {
|
func New(db db.DB, cache cache.Cache, apiRouter router.Router, federator federation.Federator, config *config.Config) (Gotosocial, error) {
|
||||||
return &gotosocial{
|
return &gotosocial{
|
||||||
db: db,
|
db: db,
|
||||||
cache: cache,
|
cache: cache,
|
||||||
apiRouter: apiRouter,
|
apiRouter: apiRouter,
|
||||||
federationAPI: federationAPI,
|
federator: federator,
|
||||||
config: config,
|
config: config,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// gotosocial fulfils the gotosocial interface.
|
// gotosocial fulfils the gotosocial interface.
|
||||||
type gotosocial struct {
|
type gotosocial struct {
|
||||||
db db.DB
|
db db.DB
|
||||||
cache cache.Cache
|
cache cache.Cache
|
||||||
apiRouter router.Router
|
apiRouter router.Router
|
||||||
federationAPI pub.FederatingActor
|
federator federation.Federator
|
||||||
config *config.Config
|
config *config.Config
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start starts up the gotosocial server. If something goes wrong
|
// Start starts up the gotosocial server. If something goes wrong
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,10 @@ var (
|
||||||
// inboxPathRegex parses a path that validates and captures the username part from eg /users/example_username/inbox
|
// inboxPathRegex parses a path that validates and captures the username part from eg /users/example_username/inbox
|
||||||
inboxPathRegex = regexp.MustCompile(inboxPathRegexString)
|
inboxPathRegex = regexp.MustCompile(inboxPathRegexString)
|
||||||
|
|
||||||
|
outboxPathRegexString = fmt.Sprintf(`^/?%s/(%s)/%s$`, UsersPath, usernameRegexString, OutboxPath)
|
||||||
|
// outboxPathRegex parses a path that validates and captures the username part from eg /users/example_username/outbox
|
||||||
|
outboxPathRegex = regexp.MustCompile(outboxPathRegexString)
|
||||||
|
|
||||||
actorPathRegexString = fmt.Sprintf(`^?/%s/(%s)$`, ActorsPath, usernameRegexString)
|
actorPathRegexString = fmt.Sprintf(`^?/%s/(%s)$`, ActorsPath, usernameRegexString)
|
||||||
// actorPathRegex parses a path that validates and captures the username part from eg /actors/example_username
|
// actorPathRegex parses a path that validates and captures the username part from eg /actors/example_username
|
||||||
actorPathRegex = regexp.MustCompile(actorPathRegexString)
|
actorPathRegex = regexp.MustCompile(actorPathRegexString)
|
||||||
|
|
|
||||||
|
|
@ -137,6 +137,11 @@ func IsInboxPath(id *url.URL) bool {
|
||||||
return inboxPathRegex.MatchString(strings.ToLower(id.Path))
|
return inboxPathRegex.MatchString(strings.ToLower(id.Path))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsOutboxPath returns true if the given URL path corresponds to eg /users/example_username/outbox
|
||||||
|
func IsOutboxPath(id *url.URL) bool {
|
||||||
|
return outboxPathRegex.MatchString(strings.ToLower(id.Path))
|
||||||
|
}
|
||||||
|
|
||||||
// IsInstanceActorPath returns true if the given URL path corresponds to eg /actors/example_username
|
// IsInstanceActorPath returns true if the given URL path corresponds to eg /actors/example_username
|
||||||
func IsInstanceActorPath(id *url.URL) bool {
|
func IsInstanceActorPath(id *url.URL) bool {
|
||||||
return actorPathRegex.MatchString(strings.ToLower(id.Path))
|
return actorPathRegex.MatchString(strings.ToLower(id.Path))
|
||||||
|
|
@ -195,3 +200,14 @@ func ParseInboxPath(id *url.URL) (username string, err error) {
|
||||||
username = matches[1]
|
username = matches[1]
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParseOutboxPath returns the username from a path such as /users/example_username/outbox
|
||||||
|
func ParseOutboxPath(id *url.URL) (username string, err error) {
|
||||||
|
matches := outboxPathRegex.FindStringSubmatch(id.Path)
|
||||||
|
if len(matches) != 2 {
|
||||||
|
err = fmt.Errorf("expected 2 matches but matches length was %d", len(matches))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
username = matches[1]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,11 @@
|
||||||
package testrig
|
package testrig
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
@ -44,6 +47,7 @@ import (
|
||||||
|
|
||||||
// Run creates and starts a gotosocial testrig server
|
// Run creates and starts a gotosocial testrig server
|
||||||
var Run action.GTSAction = func(ctx context.Context, _ *config.Config, log *logrus.Logger) error {
|
var Run action.GTSAction = func(ctx context.Context, _ *config.Config, log *logrus.Logger) error {
|
||||||
|
c := NewTestConfig()
|
||||||
dbService := NewTestDB()
|
dbService := NewTestDB()
|
||||||
router := NewTestRouter()
|
router := NewTestRouter()
|
||||||
storageBackend := NewTestStorage()
|
storageBackend := NewTestStorage()
|
||||||
|
|
@ -54,8 +58,15 @@ var Run action.GTSAction = func(ctx context.Context, _ *config.Config, log *logr
|
||||||
return fmt.Errorf("error starting distributor: %s", err)
|
return fmt.Errorf("error starting distributor: %s", err)
|
||||||
}
|
}
|
||||||
mastoConverter := NewTestTypeConverter(dbService)
|
mastoConverter := NewTestTypeConverter(dbService)
|
||||||
|
transportController := NewTestTransportController(NewMockHTTPClient(func(req *http.Request) (*http.Response, error) {
|
||||||
c := NewTestConfig()
|
r := ioutil.NopCloser(bytes.NewReader([]byte{}))
|
||||||
|
return &http.Response{
|
||||||
|
StatusCode: 200,
|
||||||
|
Body: r,
|
||||||
|
}, nil
|
||||||
|
}))
|
||||||
|
federatingActor := federation.NewFederatingActor(dbService, transportController, c, log)
|
||||||
|
federator := federation.NewFederator(federatingActor, distributor)
|
||||||
|
|
||||||
StandardDBSetup(dbService)
|
StandardDBSetup(dbService)
|
||||||
StandardStorageSetup(storageBackend, "./testrig/media")
|
StandardStorageSetup(storageBackend, "./testrig/media")
|
||||||
|
|
@ -97,7 +108,7 @@ var Run action.GTSAction = func(ctx context.Context, _ *config.Config, log *logr
|
||||||
// return fmt.Errorf("error creating instance account: %s", err)
|
// return fmt.Errorf("error creating instance account: %s", err)
|
||||||
// }
|
// }
|
||||||
|
|
||||||
gts, err := gotosocial.New(dbService, &cache.MockCache{}, router, federation.New(dbService, c, log), c)
|
gts, err := gotosocial.New(dbService, &cache.MockCache{}, router, federator, c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error creating gotosocial service: %s", err)
|
return fmt.Errorf("error creating gotosocial service: %s", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue