mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-10-30 23:32:25 -05:00 
			
		
		
		
	start work on AP inbox post
This commit is contained in:
		
					parent
					
						
							
								742f985d5b
							
						
					
				
			
			
				commit
				
					
						d09a8a1f05
					
				
			
		
					 12 changed files with 207 additions and 22 deletions
				
			
		
							
								
								
									
										2
									
								
								go.mod
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								go.mod
									
										
									
									
									
								
							|  | @ -7,7 +7,7 @@ require ( | |||
| 	github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect | ||||
| 	github.com/gin-contrib/sessions v0.0.3 | ||||
| 	github.com/gin-gonic/gin v1.6.3 | ||||
| 	github.com/go-fed/activity v1.0.0 | ||||
| 	github.com/go-fed/activity v1.0.1-0.20210426194615-e0de0863dcc1 | ||||
| 	github.com/go-fed/httpsig v0.1.1-0.20190914113940-c2de3672e5b5 | ||||
| 	github.com/go-pg/pg/extra/pgdebug v0.2.0 | ||||
| 	github.com/go-pg/pg/v10 v10.8.0 | ||||
|  |  | |||
							
								
								
									
										4
									
								
								go.sum
									
										
									
									
									
								
							
							
						
						
									
										4
									
								
								go.sum
									
										
									
									
									
								
							|  | @ -59,8 +59,8 @@ github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0 | |||
| github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= | ||||
| github.com/go-errors/errors v1.0.2 h1:xMxH9j2fNg/L4hLn/4y3M0IUsn0M6Wbu/Uh9QlOfBh4= | ||||
| github.com/go-errors/errors v1.0.2/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs= | ||||
| github.com/go-fed/activity v1.0.0 h1:j7w3auHZnVCjUcgA1mE+UqSOjFBhvW2Z2res3vNol+o= | ||||
| github.com/go-fed/activity v1.0.0/go.mod h1:v4QoPaAzjWZ8zN2VFVGL5ep9C02mst0hQYHUpQwso4Q= | ||||
| github.com/go-fed/activity v1.0.1-0.20210426194615-e0de0863dcc1 h1:go9MogQW0eTLwdOs/ZfNCGpwUkVcr7IMUbI3u8wYQxw= | ||||
| github.com/go-fed/activity v1.0.1-0.20210426194615-e0de0863dcc1/go.mod h1:v4QoPaAzjWZ8zN2VFVGL5ep9C02mst0hQYHUpQwso4Q= | ||||
| github.com/go-fed/httpsig v0.1.1-0.20190914113940-c2de3672e5b5 h1:WLvFZqoXnuVTBKA6U/1FnEHNQ0Rq0QM0rGhY8Tx6R1g= | ||||
| github.com/go-fed/httpsig v0.1.1-0.20190914113940-c2de3672e5b5/go.mod h1:T56HUNYZUQ1AGUzhAYPugZfp36sKApVnGBgKlIY+aIE= | ||||
| github.com/go-pg/pg/extra/pgdebug v0.2.0 h1:t62UhMiV6KYAxSWojwIJiyX06TdepkzCeIzdeb00184= | ||||
|  |  | |||
							
								
								
									
										56
									
								
								internal/api/s2s/user/inboxpost.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								internal/api/s2s/user/inboxpost.go
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,56 @@ | |||
| /* | ||||
|    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 user | ||||
| 
 | ||||
| import ( | ||||
| 	"net/http" | ||||
| 
 | ||||
| 	"github.com/gin-gonic/gin" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| 	"github.com/superseriousbusiness/gotosocial/internal/message" | ||||
| ) | ||||
| 
 | ||||
| func (m *Module) InboxPOSTHandler(c *gin.Context) { | ||||
| 	l := m.log.WithFields(logrus.Fields{ | ||||
| 		"func": "InboxPOSTHandler", | ||||
| 		"url":  c.Request.RequestURI, | ||||
| 	}) | ||||
| 
 | ||||
| 	requestedUsername := c.Param(UsernameKey) | ||||
| 	if requestedUsername == "" { | ||||
| 		c.JSON(http.StatusBadRequest, gin.H{"error": "no username specified in request"}) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	posted, err := m.processor.InboxPost(c.Request.Context(), c.Writer, c.Request) | ||||
| 	if err != nil { | ||||
| 		if withCode, ok := err.(message.ErrorWithCode); ok { | ||||
| 			l.Debug(withCode.Error()) | ||||
| 			c.JSON(withCode.Code(), withCode.Safe()) | ||||
| 			return | ||||
| 		} | ||||
| 		l.Debug(err) | ||||
| 		c.JSON(http.StatusBadRequest, gin.H{"error": "unable to process request"}) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	if !posted { | ||||
| 		c.JSON(http.StatusBadRequest, gin.H{"error": "unable to process request"}) | ||||
| 	} | ||||
| } | ||||
|  | @ -38,6 +38,7 @@ const ( | |||
| 	// Use this anywhere you need to know the username of the user being queried. | ||||
| 	// Eg https://example.org/users/:username | ||||
| 	UsersBasePathWithUsername = UsersBasePath + "/:" + UsernameKey | ||||
| 	UsersInboxPath            = UsersBasePathWithUsername + "/" + util.InboxPath | ||||
| ) | ||||
| 
 | ||||
| // ActivityPubAcceptHeaders represents the Accept headers mentioned here: | ||||
|  | @ -66,5 +67,6 @@ func New(config *config.Config, processor message.Processor, log *logrus.Logger) | |||
| // Route satisfies the RESTAPIModule interface | ||||
| func (m *Module) Route(s router.Router) error { | ||||
| 	s.AttachHandler(http.MethodGet, UsersBasePathWithUsername, m.UsersGETHandler) | ||||
| 	s.AttachHandler(http.MethodPost, UsersInboxPath, m.InboxPOSTHandler) | ||||
| 	return nil | ||||
| } | ||||
|  |  | |||
|  | @ -104,6 +104,13 @@ func (f *federatingDB) Unlock(c context.Context, id *url.URL) error { | |||
| // | ||||
| // The library makes this call only after acquiring a lock first. | ||||
| func (f *federatingDB) InboxContains(c context.Context, inbox, id *url.URL) (contains bool, err error) { | ||||
| 	l := f.log.WithFields( | ||||
| 		logrus.Fields{ | ||||
| 			"func": "InboxContains", | ||||
| 			"id": id.String(), | ||||
| 		}, | ||||
| 	) | ||||
| 	l.Debug("entering INBOXCONTAINS function") | ||||
| 
 | ||||
| 	if !util.IsInboxPath(inbox) { | ||||
| 		return false, fmt.Errorf("%s is not an inbox URI", inbox.String()) | ||||
|  | @ -151,6 +158,14 @@ func (f *federatingDB) SetInbox(c context.Context, inbox vocab.ActivityStreamsOr | |||
| // the database has an entry for the IRI. | ||||
| // The library makes this call only after acquiring a lock first. | ||||
| func (f *federatingDB) Owns(c context.Context, id *url.URL) (bool, error) { | ||||
| 	l := f.log.WithFields( | ||||
| 		logrus.Fields{ | ||||
| 			"func": "Owns", | ||||
| 			"id": id.String(), | ||||
| 		}, | ||||
| 	) | ||||
| 	l.Debug("entering OWNS function") | ||||
| 
 | ||||
| 	// if the id host isn't this instance host, we don't own this IRI | ||||
| 	if id.Host != f.config.Host { | ||||
| 		return false, nil | ||||
|  | @ -199,6 +214,14 @@ func (f *federatingDB) Owns(c context.Context, id *url.URL) (bool, error) { | |||
| // | ||||
| // The library makes this call only after acquiring a lock first. | ||||
| func (f *federatingDB) ActorForOutbox(c context.Context, outboxIRI *url.URL) (actorIRI *url.URL, err error) { | ||||
| 	l := f.log.WithFields( | ||||
| 		logrus.Fields{ | ||||
| 			"func": "ActorForOutbox", | ||||
| 			"inboxIRI": outboxIRI.String(), | ||||
| 		}, | ||||
| 	) | ||||
| 	l.Debug("entering ACTORFOROUTBOX function") | ||||
| 
 | ||||
| 	if !util.IsOutboxPath(outboxIRI) { | ||||
| 		return nil, fmt.Errorf("%s is not an outbox URI", outboxIRI.String()) | ||||
| 	} | ||||
|  | @ -216,6 +239,14 @@ func (f *federatingDB) ActorForOutbox(c context.Context, outboxIRI *url.URL) (ac | |||
| // | ||||
| // The library makes this call only after acquiring a lock first. | ||||
| func (f *federatingDB) ActorForInbox(c context.Context, inboxIRI *url.URL) (actorIRI *url.URL, err error) { | ||||
| 	l := f.log.WithFields( | ||||
| 		logrus.Fields{ | ||||
| 			"func": "ActorForInbox", | ||||
| 			"inboxIRI": inboxIRI.String(), | ||||
| 		}, | ||||
| 	) | ||||
| 	l.Debug("entering ACTORFORINBOX function") | ||||
| 
 | ||||
| 	if !util.IsInboxPath(inboxIRI) { | ||||
| 		return nil, fmt.Errorf("%s is not an inbox URI", inboxIRI.String()) | ||||
| 	} | ||||
|  | @ -234,6 +265,14 @@ func (f *federatingDB) ActorForInbox(c context.Context, inboxIRI *url.URL) (acto | |||
| // | ||||
| // The library makes this call only after acquiring a lock first. | ||||
| func (f *federatingDB) OutboxForInbox(c context.Context, inboxIRI *url.URL) (outboxIRI *url.URL, err error) { | ||||
| 	l := f.log.WithFields( | ||||
| 		logrus.Fields{ | ||||
| 			"func": "OutboxForInbox", | ||||
| 			"inboxIRI": inboxIRI.String(), | ||||
| 		}, | ||||
| 	) | ||||
| 	l.Debug("entering OUTBOXFORINBOX function") | ||||
| 
 | ||||
| 	if !util.IsInboxPath(inboxIRI) { | ||||
| 		return nil, fmt.Errorf("%s is not an inbox URI", inboxIRI.String()) | ||||
| 	} | ||||
|  | @ -252,6 +291,14 @@ func (f *federatingDB) OutboxForInbox(c context.Context, inboxIRI *url.URL) (out | |||
| // | ||||
| // The library makes this call only after acquiring a lock first. | ||||
| func (f *federatingDB) Exists(c context.Context, id *url.URL) (exists bool, err error) { | ||||
| 	l := f.log.WithFields( | ||||
| 		logrus.Fields{ | ||||
| 			"func": "Exists", | ||||
| 			"id": id.String(), | ||||
| 		}, | ||||
| 	) | ||||
| 	l.Debug("entering EXISTS function") | ||||
| 
 | ||||
| 	return false, nil | ||||
| } | ||||
| 
 | ||||
|  | @ -259,6 +306,13 @@ func (f *federatingDB) Exists(c context.Context, id *url.URL) (exists bool, err | |||
| // | ||||
| // The library makes this call only after acquiring a lock first. | ||||
| func (f *federatingDB) Get(c context.Context, id *url.URL) (value vocab.Type, err error) { | ||||
| 	l := f.log.WithFields( | ||||
| 		logrus.Fields{ | ||||
| 			"func": "Get", | ||||
| 			"id": id.String(), | ||||
| 		}, | ||||
| 	) | ||||
| 	l.Debug("entering GET function") | ||||
| 	return nil, nil | ||||
| } | ||||
| 
 | ||||
|  | @ -275,6 +329,13 @@ func (f *federatingDB) Get(c context.Context, id *url.URL) (value vocab.Type, er | |||
| // Under certain conditions and network activities, Create may be called | ||||
| // multiple times for the same ActivityStreams object. | ||||
| func (f *federatingDB) Create(c context.Context, asType vocab.Type) error { | ||||
| 	l := f.log.WithFields( | ||||
| 		logrus.Fields{ | ||||
| 			"func": "Create", | ||||
| 			"asType": asType.GetTypeName(), | ||||
| 		}, | ||||
| 	) | ||||
| 	l.Debugf("received CREATE asType %+v", asType) | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
|  | @ -288,6 +349,13 @@ func (f *federatingDB) Create(c context.Context, asType vocab.Type) error { | |||
| // | ||||
| // The library makes this call only after acquiring a lock first. | ||||
| func (f *federatingDB) Update(c context.Context, asType vocab.Type) error { | ||||
| 	l := f.log.WithFields( | ||||
| 		logrus.Fields{ | ||||
| 			"func": "Update", | ||||
| 			"asType": asType.GetTypeName(), | ||||
| 		}, | ||||
| 	) | ||||
| 	l.Debugf("received UPDATE asType %+v", asType) | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
|  | @ -298,6 +366,13 @@ func (f *federatingDB) Update(c context.Context, asType vocab.Type) error { | |||
| // | ||||
| // The library makes this call only after acquiring a lock first. | ||||
| func (f *federatingDB) Delete(c context.Context, id *url.URL) error { | ||||
| 	l := f.log.WithFields( | ||||
| 		logrus.Fields{ | ||||
| 			"func": "Delete", | ||||
| 			"id": id.String(), | ||||
| 		}, | ||||
| 	) | ||||
| 	l.Debugf("received DELETE id %s", id.String()) | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
|  | @ -325,6 +400,14 @@ func (f *federatingDB) SetOutbox(c context.Context, outbox vocab.ActivityStreams | |||
| // The go-fed library will handle setting the 'id' property on the | ||||
| // activity or object provided with the value returned. | ||||
| func (f *federatingDB) NewID(c context.Context, t vocab.Type) (id *url.URL, err error) { | ||||
| 
 | ||||
| 	l := f.log.WithFields( | ||||
| 		logrus.Fields{ | ||||
| 			"func": "NewID", | ||||
| 			"asType": t.GetTypeName(), | ||||
| 		}, | ||||
| 	) | ||||
| 	l.Debugf("received NEWID request for asType %+v", t) | ||||
| 	return nil, nil | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -57,7 +57,7 @@ import ( | |||
| // authenticated must be true and error nil. The request will continue | ||||
| // to be processed. | ||||
| func (f *federator) AuthenticateGetInbox(ctx context.Context, w http.ResponseWriter, r *http.Request) (context.Context, bool, error) { | ||||
| 	// IMPLEMENTATION NOTE: For GoToSocial, we serve outboxes and inboxes through | ||||
| 	// IMPLEMENTATION NOTE: For GoToSocial, we serve GETS to outboxes and inboxes through | ||||
| 	// the CLIENT API, not through the federation API, so we just do nothing here. | ||||
| 	return nil, false, nil | ||||
| } | ||||
|  | @ -82,7 +82,7 @@ func (f *federator) AuthenticateGetInbox(ctx context.Context, w http.ResponseWri | |||
| // authenticated must be true and error nil. The request will continue | ||||
| // to be processed. | ||||
| func (f *federator) AuthenticateGetOutbox(ctx context.Context, w http.ResponseWriter, r *http.Request) (context.Context, bool, error) { | ||||
| 	// IMPLEMENTATION NOTE: For GoToSocial, we serve outboxes and inboxes through | ||||
| 	// IMPLEMENTATION NOTE: For GoToSocial, we serve GETS to outboxes and inboxes through | ||||
| 	// the CLIENT API, not through the federation API, so we just do nothing here. | ||||
| 	return nil, false, nil | ||||
| } | ||||
|  | @ -96,7 +96,7 @@ func (f *federator) AuthenticateGetOutbox(ctx context.Context, w http.ResponseWr | |||
| // Always called, regardless whether the Federated Protocol or Social | ||||
| // API is enabled. | ||||
| func (f *federator) GetOutbox(ctx context.Context, r *http.Request) (vocab.ActivityStreamsOrderedCollectionPage, error) { | ||||
| 	// IMPLEMENTATION NOTE: For GoToSocial, we serve outboxes and inboxes through | ||||
| 	// IMPLEMENTATION NOTE: For GoToSocial, we serve GETS to outboxes and inboxes through | ||||
| 	// the CLIENT API, not through the federation API, so we just do nothing here. | ||||
| 	return nil, nil | ||||
| } | ||||
|  |  | |||
|  | @ -77,6 +77,13 @@ func (f *federatingActor) PostInbox(c context.Context, w http.ResponseWriter, r | |||
| 	return f.actor.PostInbox(c, w, r) | ||||
| } | ||||
| 
 | ||||
| // PostInboxScheme is similar to PostInbox, except clients are able to | ||||
| // specify which protocol scheme to handle the incoming request and the | ||||
| // data stored within the application (HTTP, HTTPS, etc). | ||||
| func (f *federatingActor) PostInboxScheme(c context.Context, w http.ResponseWriter, r *http.Request, scheme string) (bool, error) { | ||||
| 	return f.actor.PostInboxScheme(c, w, r, scheme) | ||||
| } | ||||
| 
 | ||||
| // GetInbox returns true if the request was handled as an ActivityPub | ||||
| // GET to an actor's inbox. If false, the request was not an ActivityPub | ||||
| // request and may still be handled by the caller in another way, such | ||||
|  | @ -118,6 +125,13 @@ func (f *federatingActor) PostOutbox(c context.Context, w http.ResponseWriter, r | |||
| 	return f.actor.PostOutbox(c, w, r) | ||||
| } | ||||
| 
 | ||||
| // PostOutboxScheme is similar to PostOutbox, except clients are able to | ||||
| // specify which protocol scheme to handle the incoming request and the | ||||
| // data stored within the application (HTTP, HTTPS, etc). | ||||
| func (f *federatingActor) PostOutboxScheme(c context.Context, w http.ResponseWriter, r *http.Request, scheme string) (bool, error) { | ||||
| 	return f.actor.PostOutboxScheme(c, w, r, scheme) | ||||
| } | ||||
| 
 | ||||
| // GetOutbox returns true if the request was handled as an ActivityPub | ||||
| // GET to an actor's outbox. If false, the request was not an | ||||
| // ActivityPub request. | ||||
|  |  | |||
|  | @ -72,6 +72,7 @@ func (f *federator) PostInboxRequestBodyHook(ctx context.Context, r *http.Reques | |||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 
 | ||||
| 	ctxWithActivity := context.WithValue(ctx, util.APActivity, activity) | ||||
| 	return ctxWithActivity, nil | ||||
| } | ||||
|  | @ -100,14 +101,22 @@ func (f *federator) AuthenticatePostInbox(ctx context.Context, w http.ResponseWr | |||
| 	}) | ||||
| 	l.Trace("received request to authenticate") | ||||
| 
 | ||||
| 	requestedAccountI := ctx.Value(util.APAccount) | ||||
| 	if requestedAccountI == nil { | ||||
| 		return ctx, false, errors.New("requested account not set in context") | ||||
| 	if !util.IsInboxPath(r.URL) { | ||||
| 		return nil, false, fmt.Errorf("path %s was not an inbox path", r.URL.String()) | ||||
| 	} | ||||
| 
 | ||||
| 	requestedAccount, ok := requestedAccountI.(*gtsmodel.Account) | ||||
| 	if !ok || requestedAccount == nil { | ||||
| 		return ctx, false, errors.New("requested account not parsebale from context") | ||||
| 	username, err := util.ParseInboxPath(r.URL) | ||||
| 	if err != nil { | ||||
| 		return nil, false, fmt.Errorf("could not parse path %s: %s", r.URL.String(), err) | ||||
| 	} | ||||
| 
 | ||||
| 	if username == "" { | ||||
| 		return nil, false, errors.New("username was empty") | ||||
| 	} | ||||
| 
 | ||||
| 	requestedAccount := >smodel.Account{} | ||||
| 	if err := f.db.GetLocalAccountByUsername(username, requestedAccount); err != nil { | ||||
| 		return nil, false, fmt.Errorf("could not fetch requested account with username %s: %s", username, err) | ||||
| 	} | ||||
| 
 | ||||
| 	publicKeyOwnerURI, err := f.AuthenticateFederatedRequest(requestedAccount.Username, r) | ||||
|  | @ -124,7 +133,6 @@ func (f *federator) AuthenticatePostInbox(ctx context.Context, w http.ResponseWr | |||
| 		} | ||||
| 
 | ||||
| 		// we don't know this account (yet) so let's dereference it right now | ||||
| 		// TODO: slow-fed | ||||
| 		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) | ||||
|  | @ -138,7 +146,6 @@ func (f *federator) AuthenticatePostInbox(ctx context.Context, w http.ResponseWr | |||
| 	} | ||||
| 
 | ||||
| 	contextWithRequestingAccount := context.WithValue(ctx, util.APRequestingAccount, requestingAccount) | ||||
| 
 | ||||
| 	return contextWithRequestingAccount, true, nil | ||||
| } | ||||
| 
 | ||||
|  | @ -180,9 +187,9 @@ func (f *federator) Blocked(ctx context.Context, actorIRIs []*url.URL) (bool, er | |||
| // | ||||
| // Applications are not expected to handle every single ActivityStreams | ||||
| // type and extension. The unhandled ones are passed to DefaultCallback. | ||||
| func (f *federator) FederatingCallbacks(ctx context.Context) (pub.FederatingWrappedCallbacks, []interface{}, error) { | ||||
| 	// TODO | ||||
| 	return pub.FederatingWrappedCallbacks{}, nil, nil | ||||
| func (f *federator) FederatingCallbacks(ctx context.Context) (wrapped pub.FederatingWrappedCallbacks, other []interface{}, err error) { | ||||
| 
 | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| // DefaultCallback is called for types that go-fed can deserialize but | ||||
|  | @ -207,7 +214,7 @@ func (f *federator) DefaultCallback(ctx context.Context, activity pub.Activity) | |||
| // Zero or negative numbers indicate infinite recursion. | ||||
| func (f *federator) MaxInboxForwardingRecursionDepth(ctx context.Context) int { | ||||
| 	// TODO | ||||
| 	return 0 | ||||
| 	return 4 | ||||
| } | ||||
| 
 | ||||
| // MaxDeliveryRecursionDepth determines how deep to search within | ||||
|  | @ -217,7 +224,7 @@ func (f *federator) MaxInboxForwardingRecursionDepth(ctx context.Context) int { | |||
| // Zero or negative numbers indicate infinite recursion. | ||||
| func (f *federator) MaxDeliveryRecursionDepth(ctx context.Context) int { | ||||
| 	// TODO | ||||
| 	return 0 | ||||
| 	return 4 | ||||
| } | ||||
| 
 | ||||
| // FilterForwarding allows the implementation to apply business logic | ||||
|  | @ -241,7 +248,7 @@ func (f *federator) FilterForwarding(ctx context.Context, potentialRecipients [] | |||
| // Always called, regardless whether the Federated Protocol or Social | ||||
| // API is enabled. | ||||
| func (f *federator) GetInbox(ctx context.Context, r *http.Request) (vocab.ActivityStreamsOrderedCollectionPage, error) { | ||||
| 	// IMPLEMENTATION NOTE: For GoToSocial, we serve outboxes and inboxes through | ||||
| 	// IMPLEMENTATION NOTE: For GoToSocial, we serve GETS to outboxes and inboxes through | ||||
| 	// the CLIENT API, not through the federation API, so we just do nothing here. | ||||
| 	return nil, nil | ||||
| } | ||||
|  |  | |||
|  | @ -1,6 +1,7 @@ | |||
| package message | ||||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"fmt" | ||||
| 	"net/http" | ||||
| 
 | ||||
|  | @ -8,6 +9,7 @@ import ( | |||
| 	apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model" | ||||
| 	"github.com/superseriousbusiness/gotosocial/internal/db" | ||||
| 	"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" | ||||
| 	"github.com/superseriousbusiness/gotosocial/internal/util" | ||||
| ) | ||||
| 
 | ||||
| // authenticateAndDereferenceFediRequest authenticates the HTTP signature of an incoming federation request, using the given | ||||
|  | @ -130,3 +132,9 @@ func (p *processor) GetWebfingerAccount(requestedUsername string, request *http. | |||
| 		}, | ||||
| 	}, nil | ||||
| } | ||||
| 
 | ||||
| func (p *processor) InboxPost(ctx context.Context, w http.ResponseWriter, r *http.Request) (bool, error) { | ||||
| 	contextWithChannel := context.WithValue(ctx, util.APFromFederatorChanKey, p.fromFederator) | ||||
| 	posted, err := p.federator.FederatingActor().PostInbox(contextWithChannel, w, r) | ||||
| 	return posted, err | ||||
| } | ||||
|  |  | |||
|  | @ -19,6 +19,7 @@ | |||
| package message | ||||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 	"net/http" | ||||
| 
 | ||||
| 	"github.com/sirupsen/logrus" | ||||
|  | @ -116,6 +117,18 @@ type Processor interface { | |||
| 
 | ||||
| 	// GetWebfingerAccount handles the GET for a webfinger resource. Most commonly, it will be used for returning account lookups. | ||||
| 	GetWebfingerAccount(requestedUsername string, request *http.Request) (*apimodel.WebfingerAccountResponse, ErrorWithCode) | ||||
| 
 | ||||
| 	// InboxPost handles POST requests to a user's inbox for new activitypub messages. | ||||
| 	// | ||||
| 	// InboxPost returns true if the request was handled as an ActivityPub POST to an actor's inbox. | ||||
| 	// If false, the request was not an ActivityPub request and may still be handled by the caller in another way, such as serving a web page. | ||||
| 	// | ||||
| 	// If the error is nil, then the ResponseWriter's headers and response has already been written. If a non-nil error is returned, then no response has been written. | ||||
| 	// | ||||
| 	// If the Actor was constructed with the Federated Protocol enabled, side effects will occur. | ||||
| 	// | ||||
| 	// If the Federated Protocol is not enabled, writes the http.StatusMethodNotAllowed status code in the response. No side effects occur. | ||||
| 	InboxPost(ctx context.Context, w http.ResponseWriter, r *http.Request) (bool, error) | ||||
| } | ||||
| 
 | ||||
| // processor just implements the Processor interface | ||||
|  |  | |||
|  | @ -54,8 +54,8 @@ func NewController(config *config.Config, clock pub.Clock, client pub.HttpClient | |||
| func (c *controller) NewTransport(pubKeyID string, privkey crypto.PrivateKey) (pub.Transport, error) { | ||||
| 	prefs := []httpsig.Algorithm{httpsig.RSA_SHA256, httpsig.RSA_SHA512} | ||||
| 	digestAlgo := httpsig.DigestSha256 | ||||
| 	getHeaders := []string{"(request-target)", "date", "accept"} | ||||
| 	postHeaders := []string{"(request-target)", "date", "accept", "digest"} | ||||
| 	getHeaders := []string{"(request-target)", "host", "date"} | ||||
| 	postHeaders := []string{"(request-target)", "host", "date", "digest"} | ||||
| 
 | ||||
| 	getSigner, _, err := httpsig.NewSigner(prefs, digestAlgo, getHeaders, httpsig.Signature) | ||||
| 	if err != nil { | ||||
|  |  | |||
|  | @ -61,6 +61,8 @@ const ( | |||
| 	APRequestingAccount APContextKey = "requestingAccount" | ||||
| 	// 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. | ||||
| 	APFromFederatorChanKey APContextKey = "fromFederatorChan" | ||||
| ) | ||||
| 
 | ||||
| type ginContextKey struct{} | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue