Implement outbox

This commit is contained in:
Anthony Wang 2022-04-13 21:49:27 -05:00
parent 95fdec2739
commit 2b243acf71
Signed by: a
GPG key ID: BC96B00AEC5F2D76
7 changed files with 140 additions and 28 deletions

View file

@ -24,7 +24,7 @@ import (
const (
// ActivityStreamsContentType const
ActivityStreamsContentType = `application/ld+json; profile="https://www.w3.org/ns/activitystreams"`
httpsigExpirationTime = 60
httpsigExpirationTime = 60
)
func containsRequiredHTTPHeaders(method string, headers []string) error {

View file

@ -0,0 +1,23 @@
// Copyright 2022 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package activitypub
import (
user_model "code.gitea.io/gitea/models/user"
"github.com/go-fed/activity/streams/vocab"
)
func databaseAddToInbox(activity vocab.ActivityStreamsActivity) {
}
func databaseAddToOutbox(activity vocab.ActivityStreamsActivity) {
}
func GetInbox(user user_model.User) {
}
func GetOutbox(user user_model.User) {
}

View file

@ -0,0 +1,38 @@
// Copyright 2022 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package activitypub
import (
"fmt"
"io"
"net/http"
"net/url"
"time"
"code.gitea.io/gitea/modules/httplib"
)
func Fetch(iri *url.URL) (b []byte, err error) {
req := httplib.NewRequest(iri.String(), http.MethodGet)
req.Header("Accept", ActivityStreamsContentType)
req.Header("Accept-Charset", "utf-8")
clock, err := NewClock()
if err != nil {
return
}
req.Header("Date", fmt.Sprintf("%s GMT", clock.Now().UTC().Format(time.RFC1123)))
resp, err := req.Response()
if err != nil {
return
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
err = fmt.Errorf("url IRI fetch [%s] failed with status (%d): %s", iri, resp.StatusCode, resp.Status)
return
}
b, err = io.ReadAll(resp.Body)
return
}

View file

@ -0,0 +1,12 @@
// Copyright 2022 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package activitypub
import (
"github.com/go-fed/activity/streams/vocab"
)
func follow(activity vocab.ActivityStreamsActivity) {
}

View file

@ -0,0 +1,19 @@
// Copyright 2022 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package activitypub
import (
"github.com/go-fed/activity/streams/vocab"
)
// Add an activity to a user's inbox
func AddToInbox(activity vocab.ActivityStreamsActivity) {
databaseAddToInbox(activity)
// Probably should use callbacks here
if activity.GetJSONLDType().Name() == "Follow" {
follow(activity)
}
}

View file

@ -0,0 +1,46 @@
// Copyright 2022 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package activitypub
import (
"context"
"strings"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/json"
"github.com/go-fed/activity/streams"
"github.com/go-fed/activity/streams/vocab"
)
// Add an activity to a user's outbox
func AddToOutbox(activity vocab.ActivityStreamsActivity) {
databaseAddToOutbox(activity)
actorIRI := activity.GetActivityStreamsActor().Begin().GetIRI()
s := strings.Split(actorIRI.String(), ",")
user, _ := user_model.GetUserByName(s[len(s)-1])
to := activity.GetActivityStreamsTo().Begin().GetIRI()
fetched, _ := Fetch(to)
var m map[string]interface{}
json.Unmarshal(fetched, &m)
var person vocab.ActivityStreamsPerson
resolver, _ := streams.NewJSONResolver(func(c context.Context, p vocab.ActivityStreamsPerson) error {
person = p
return nil
})
ctx := context.Background()
_ = resolver.Resolve(ctx, m)
inboxIRI := person.GetActivityStreamsInbox().GetIRI().String()
client, _ := NewClient(user, actorIRI.String()+"#main-key")
jsonmap, _ := streams.Serialize(activity)
body, _ := json.Marshal(jsonmap)
client.Post(body, inboxIRI)
}

View file

@ -10,14 +10,11 @@ import (
"crypto/x509"
"encoding/pem"
"fmt"
"io"
"net/http"
"net/url"
"time"
"code.gitea.io/gitea/modules/activitypub"
gitea_context "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/httplib"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/setting"
@ -88,29 +85,6 @@ func getPublicKeyFromResponse(ctx context.Context, b []byte, keyID *url.URL) (p
return
}
func fetch(iri *url.URL) (b []byte, err error) {
req := httplib.NewRequest(iri.String(), http.MethodGet)
req.Header("Accept", activitypub.ActivityStreamsContentType)
req.Header("Accept-Charset", "utf-8")
clock, err := activitypub.NewClock()
if err != nil {
return
}
req.Header("Date", fmt.Sprintf("%s GMT", clock.Now().UTC().Format(time.RFC1123)))
resp, err := req.Response()
if err != nil {
return
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
err = fmt.Errorf("url IRI fetch [%s] failed with status (%d): %s", iri, resp.StatusCode, resp.Status)
return
}
b, err = io.ReadAll(resp.Body)
return
}
func verifyHTTPSignatures(ctx *gitea_context.APIContext) (authenticated bool, err error) {
r := ctx.Req
@ -125,7 +99,7 @@ func verifyHTTPSignatures(ctx *gitea_context.APIContext) (authenticated bool, er
return
}
// 2. Fetch the public key of the other actor
b, err := fetch(idIRI)
b, err := activitypub.Fetch(idIRI)
if err != nil {
return
}