aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--go.mod1
-rw-r--r--go.sum2
-rw-r--r--http/router.go39
-rw-r--r--main.go7
-rw-r--r--models/keypair.go74
-rw-r--r--registry/registry.go35
-rwxr-xr-xsample-cgi-handler.sh2
-rw-r--r--sample-config.toml22
-rw-r--r--views/outbox.go2
9 files changed, 153 insertions, 31 deletions
diff --git a/go.mod b/go.mod
index c8e5410..a6b76bb 100644
--- a/go.mod
+++ b/go.mod
@@ -16,6 +16,7 @@ require (
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/gin-gonic/gin v1.8.1 // indirect
github.com/go-fed/activity v1.0.0 // indirect
+ github.com/go-fed/httpsig v1.1.0 // indirect
github.com/go-playground/locales v0.14.0 // indirect
github.com/go-playground/universal-translator v0.18.0 // indirect
github.com/go-playground/validator/v10 v10.11.1 // indirect
diff --git a/go.sum b/go.sum
index faf8240..b80dceb 100644
--- a/go.sum
+++ b/go.sum
@@ -48,6 +48,8 @@ github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR
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/httpsig v0.1.1-0.20190914113940-c2de3672e5b5/go.mod h1:T56HUNYZUQ1AGUzhAYPugZfp36sKApVnGBgKlIY+aIE=
+github.com/go-fed/httpsig v1.1.0 h1:9M+hb0jkEICD8/cAiNqEB66R87tTINszBRTjwjQzWcI=
+github.com/go-fed/httpsig v1.1.0/go.mod h1:RCMrTZvN1bJYtofsG4rd5NaO5obxQ5xBkdiS7xsT7bM=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU=
github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
diff --git a/http/router.go b/http/router.go
index a34ff7c..be2a128 100644
--- a/http/router.go
+++ b/http/router.go
@@ -1,19 +1,22 @@
package http
import (
+ "bytes"
"io"
"net/http"
"git.capotej.com/capotej/communique/registry"
"github.com/gin-gonic/gin"
+ "go.uber.org/zap"
)
type Router struct {
registry *registry.Registry
+ log *zap.SugaredLogger
}
-func NewRouter(registry *registry.Registry) *Router {
- return &Router{registry: registry}
+func NewRouter(registry *registry.Registry, log *zap.SugaredLogger) *Router {
+ return &Router{registry: registry, log: log}
}
func render(c *gin.Context, resource map[string]interface{}, err error) {
@@ -68,17 +71,27 @@ func (s *Router) Start(zapWriter io.Writer) {
render(c, resource, err)
})
- // // Inbox
- // router.POST("/actors/:actor/inbox", func(c *gin.Context) {
- // actorParam := c.Param("actor")
- // resource := s.registry.Inbox(actorParam)
- // if resource != nil {
- // c.JSON(http.StatusOK, resource)
- // } else {
- // c.JSON(http.StatusNotFound, nil)
- // }
-
- // })
+ // Inbox
+ router.POST("/actors/:actor/inbox", func(c *gin.Context) {
+ log := s.log.With("type", "inbox")
+ buf := new(bytes.Buffer)
+ buf.ReadFrom(c.Request.Body)
+ payload := buf.String()
+ log.With(
+ "payload",
+ c.GetHeader("Signature"),
+ ).With(
+ "content-type",
+ c.GetHeader("Content-Type"),
+ ).With(
+ "payload",
+ payload,
+ ).Debug("received item")
+ actorParam := c.Param("actor")
+ err := s.registry.Inbox(actorParam, c.Request)
+ resource := map[string]interface{}{}
+ render(c, resource, err)
+ })
// Actor Outbox
router.GET("/actors/:actor/outbox", func(c *gin.Context) {
diff --git a/main.go b/main.go
index e65a600..453a4e3 100644
--- a/main.go
+++ b/main.go
@@ -51,7 +51,10 @@ func main() {
persister := models.NewPersister(log, db)
// Registry
- registry := registry.NewRegistry(cfg, persister)
+ registry, err := registry.NewRegistry(cfg, persister)
+ if err != nil {
+ log.Fatal(err)
+ }
// Servers
var mainWg sync.WaitGroup
@@ -64,7 +67,7 @@ func main() {
// // External Http Server
writer := &zapio.Writer{Log: logger, Level: zap.DebugLevel}
defer writer.Close()
- router := http.NewRouter(registry)
+ router := http.NewRouter(registry, log)
mainWg.Add(1)
go router.Start(writer)
diff --git a/models/keypair.go b/models/keypair.go
new file mode 100644
index 0000000..bff60cd
--- /dev/null
+++ b/models/keypair.go
@@ -0,0 +1,74 @@
+package models
+
+import (
+ "bytes"
+ "crypto/rand"
+ "crypto/rsa"
+ "encoding/gob"
+ "fmt"
+ "time"
+
+ "git.capotej.com/capotej/communique/config"
+ "github.com/dgraph-io/badger/v3"
+)
+
+type Keypair struct {
+ Handler config.Handler
+ PrivateKey rsa.PrivateKey
+ CreatedAt time.Time
+}
+
+// used for lookup purposes (count, collect, find)
+func NewKeypair(h config.Handler) *Keypair {
+ aso := &Keypair{Handler: h}
+ return aso
+}
+
+func CreateKeypair(h config.Handler) (*Keypair, error) {
+ key, err := rsa.GenerateKey(rand.Reader, 2048)
+ if err != nil {
+ return nil, fmt.Errorf("could not generate private key for %s: %w", h.Name, err)
+ }
+ aso := &Keypair{
+ PrivateKey: *key,
+ Handler: h,
+ }
+ return aso, nil
+}
+
+func (a *Keypair) Name() string {
+ return "Keypair"
+}
+
+func (a *Keypair) Key() string {
+ keyBase := fmt.Sprintf("keypairs:%s", a.Handler.Name)
+ return keyBase
+}
+
+func (a *Keypair) DedupKey() string {
+ return a.Key()
+}
+
+func (a *Keypair) Keybase() string {
+ return a.Key()
+}
+
+func (a *Keypair) SaveDedup(txn *badger.Txn) error {
+ txn.Discard() // nothing to do here
+ return nil
+}
+
+func (a *Keypair) Save(txn *badger.Txn) error {
+ if a.PrivateKey.D == nil {
+ return fmt.Errorf("private key not set")
+ }
+
+ var network bytes.Buffer
+ enc := gob.NewEncoder(&network)
+ err := enc.Encode(a)
+ if err != nil {
+ return fmt.Errorf("could not encode keypair: %w", err)
+ }
+ e := badger.NewEntry([]byte(a.Key()), network.Bytes())
+ return txn.SetEntry(e)
+}
diff --git a/registry/registry.go b/registry/registry.go
index 16ae828..bbe3f1c 100644
--- a/registry/registry.go
+++ b/registry/registry.go
@@ -3,6 +3,7 @@ package registry
import (
"bytes"
"encoding/gob"
+ "net/http"
"net/url"
"strings"
@@ -23,13 +24,29 @@ type Registry struct {
handlerMap map[string]Handler
}
-func NewRegistry(cfg config.Config, persister *models.Persister) *Registry {
+func NewRegistry(cfg config.Config, persister *models.Persister) (*Registry, error) {
reg := Registry{cfg: cfg, persister: persister}
reg.handlerMap = make(map[string]Handler)
for _, v := range cfg.Handlers {
reg.handlerMap[v.Name] = Handler{handlerCfg: v}
+ err := generateKeypairIfNeeded(v, persister)
+ if err != nil {
+ return nil, err
+ }
}
- return &reg
+ return &reg, nil
+}
+
+func generateKeypairIfNeeded(v config.Handler, p *models.Persister) error {
+ kp, err := models.CreateKeypair(v)
+ if err != nil {
+ return err
+ }
+ err = p.Store(kp)
+ if err != nil {
+ return err
+ }
+ return nil
}
func (r *Registry) Actor(name string) (map[string]interface{}, error) {
@@ -51,7 +68,7 @@ func (r *Registry) OutboxCollection(name string) (map[string]interface{}, error)
return nil, err
}
var outboxItems []models.OutboxItem
- for _, v := range page[0:20] { //TODO pagination
+ for _, v := range page { //TODO pagination
buf := bytes.NewBuffer(v)
dec := gob.NewDecoder(buf)
var outboxItem models.OutboxItem
@@ -109,6 +126,18 @@ func (r *Registry) Followers(name string) (map[string]interface{}, error) {
return result, nil
}
+func (r *Registry) Inbox(name string, req *http.Request) error {
+ handler := r.findByName(name)
+ if handler == nil {
+ return nil
+ }
+ // verifier, err := httpsig.NewVerifier(req)
+ // if err != nil {
+ // return err
+ // }
+ return nil
+}
+
func (r *Registry) ActivityOrNote(activityOrNote, name, id string) (map[string]interface{}, error) {
handler := r.findByName(name)
if handler == nil {
diff --git a/sample-cgi-handler.sh b/sample-cgi-handler.sh
index bc82dc4..11bae71 100755
--- a/sample-cgi-handler.sh
+++ b/sample-cgi-handler.sh
@@ -3,7 +3,7 @@ echo "Content-type: application/atom+xml"
echo ""
echo '<feed xmlns="http://www.w3.org/2005/Atom">
<entry>
- <content>alkfjlasjf</content>
+ <content>alkfjaiasdfaslasjf</content>
</entry>
</feed>'
exit 0
diff --git a/sample-config.toml b/sample-config.toml
index 293a525..f659e60 100644
--- a/sample-config.toml
+++ b/sample-config.toml
@@ -1,19 +1,19 @@
domain = "http://localhost:8080"
dbPath = "bub.db"
-# [[handlers]]
-# name = "sample"
-# rpc = "cgi" # rename to protocol?
-# exec = "sample-cgi-handler.sh"
-# interval = "5s"
-# dedupWindow = "1m"
-
[[handlers]]
-name = "autosport"
+name = "sample"
rpc = "cgi" # rename to protocol?
-exec = "autosport-handler.sh"
-interval = "10m"
-dedupWindow = "900h"
+exec = "sample-cgi-handler.sh"
+interval = "5s"
+dedupWindow = "1m"
+
+# [[handlers]]
+# name = "autosport"
+# rpc = "cgi" # rename to protocol?
+# exec = "autosport-handler.sh"
+# interval = "10m"
+# dedupWindow = "900h"
# [[handlers]]
# name = "another"
diff --git a/views/outbox.go b/views/outbox.go
index 6132072..37afed1 100644
--- a/views/outbox.go
+++ b/views/outbox.go
@@ -55,7 +55,7 @@ func RenderOutboxCollection(name, domain string, page []models.OutboxItem) (map[
itemsProp.AppendActivityStreamsCreate(crea)
}
totalProp := streams.NewActivityStreamsTotalItemsProperty()
- totalProp.Set(20)
+ totalProp.Set(len(page))
oc.SetActivityStreamsTotalItems(totalProp)
oc.SetActivityStreamsOrderedItems(itemsProp)
return streams.Serialize(oc)