summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Schanzenbach <schanzen@gnunet.org>2022-07-19 18:57:10 +0200
committerMartin Schanzenbach <schanzen@gnunet.org>2022-07-19 18:57:10 +0200
commit485861ffce6d8b1983e5573c0c60a43d7cbc0e07 (patch)
tree316ab88269f57230f1acd53c2199f10f1b2a2ad8
parentce8a3d30783476d4d3bb6a54c0c0116c13d49112 (diff)
downloadtaler-mailbox-485861ffce6d8b1983e5573c0c60a43d7cbc0e07.tar.gz
taler-mailbox-485861ffce6d8b1983e5573c0c60a43d7cbc0e07.tar.bz2
taler-mailbox-485861ffce6d8b1983e5573c0c60a43d7cbc0e07.zip
more API
-rw-r--r--go.mod4
-rw-r--r--go.sum13
-rw-r--r--pkg/rest/mailbox.go123
3 files changed, 138 insertions, 2 deletions
diff --git a/go.mod b/go.mod
index c941a77..919271c 100644
--- a/go.mod
+++ b/go.mod
@@ -3,6 +3,7 @@ module taler.net/taler-mailbox
go 1.18
require (
+ git.gnunet.org/gnunet-go.git v0.1.28-0.20220717050634-369422be2512
github.com/gorilla/mux v1.8.0
gopkg.in/ini.v1 v1.66.6
gorm.io/driver/postgres v1.3.8
@@ -11,6 +12,8 @@ require (
)
require (
+ github.com/bfix/gospel v1.2.15 // indirect
+ github.com/go-sql-driver/mysql v1.6.0 // indirect
github.com/jackc/chunkreader/v2 v2.0.1 // indirect
github.com/jackc/pgconn v1.12.1 // indirect
github.com/jackc/pgio v1.0.0 // indirect
@@ -21,6 +24,7 @@ require (
github.com/jackc/pgx/v4 v4.16.1 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.4 // indirect
+ github.com/mattn/go-sqlite3 v1.14.14 // indirect
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect
golang.org/x/text v0.3.7 // indirect
)
diff --git a/go.sum b/go.sum
index 8815945..fc28f7a 100644
--- a/go.sum
+++ b/go.sum
@@ -1,6 +1,10 @@
+git.gnunet.org/gnunet-go.git v0.1.28-0.20220717050634-369422be2512 h1:RHHLRqEzdblfKOx/isc6E/0/6bJfWLgwWVAXNX5dI7A=
+git.gnunet.org/gnunet-go.git v0.1.28-0.20220717050634-369422be2512/go.mod h1:dfSzJbX7Hc7tywZT498/WgTEzoXWZnuvKH6JSFjbyME=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc=
github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
+github.com/bfix/gospel v1.2.15 h1:f0t8dvihSXWvhnXDI2q7FCtG7LHg5qImjEWdzIN/luY=
+github.com/bfix/gospel v1.2.15/go.mod h1:cdu63bA9ZdfeDoqZ+vnWOcbY9Puwdzmf5DMxMGMznRI=
github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I=
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
@@ -11,12 +15,16 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
+github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
+github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw=
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
+github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc=
+github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o=
github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo=
github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk=
github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8=
@@ -85,6 +93,8 @@ github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
+github.com/mattn/go-sqlite3 v1.14.14 h1:qZgc/Rwetq+MtyE18WhzjokPD93dNqLGNT3QJuLvBGw=
+github.com/mattn/go-sqlite3 v1.14.14/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@@ -127,6 +137,7 @@ golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
+golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg=
@@ -134,6 +145,7 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
+golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@@ -158,6 +170,7 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
diff --git a/pkg/rest/mailbox.go b/pkg/rest/mailbox.go
index 874ecaa..eb47b89 100644
--- a/pkg/rest/mailbox.go
+++ b/pkg/rest/mailbox.go
@@ -26,6 +26,7 @@ import (
"os"
"time"
+ gnunetutil "git.gnunet.org/gnunet-go.git/pkg/util"
"github.com/gorilla/mux"
"gopkg.in/ini.v1"
"gorm.io/driver/postgres"
@@ -33,6 +34,7 @@ import (
"gorm.io/gorm/logger"
"taler.net/taler-go.git/pkg/merchant"
tos "taler.net/taler-go.git/pkg/rest"
+ talerutil "taler.net/taler-go.git/pkg/util"
)
// Mailbox is the primary object of the Mailbox service
@@ -51,6 +53,18 @@ type Mailbox struct {
Merchant merchant.Merchant
}
+type identityMessage struct {
+ // Public DH key used to encrypt the body. Must be fresh
+ // and only used once (ephemeral).
+ EphemeralKey string `json:"ephemeral_key"`
+
+ // Encrypted message. Must be exactly 256-32 bytes long.
+ Body string
+
+ // Order ID, if the client recently paid for this message.
+ //order_id?: string;
+}
+
// VersionResponse is the JSON response of the /config enpoint
type VersionResponse struct {
// libtool-style representation of the Merchant protocol version, see
@@ -82,9 +96,21 @@ type MailboxRateLimitedResponse struct {
Hint string `json:"hint"`
}
-type message struct {
+type inboxEntry struct {
// ORM
gorm.Model `json:"-"`
+
+ // and only used once (ephemeral).
+ EphemeralKey string `json:"ephemeral_key"`
+
+ // Encrypted message. Must be exactly 256-32 bytes long.
+ Body string
+
+ // Hash of the inbox for this entry
+ HMailbox string
+
+ // Order ID
+ OrderID string
}
func (m *Mailbox) configResponse(w http.ResponseWriter, r *http.Request) {
@@ -105,6 +131,96 @@ func (m *Mailbox) configResponse(w http.ResponseWriter, r *http.Request) {
w.Write(response)
}
+func (m *Mailbox) getMessagesResponse(w http.ResponseWriter, r *http.Request) {
+ vars := mux.Vars(r)
+ //to, toSet := vars["timeout_ms"]
+ var entries []inboxEntry
+ // FIXME rate limit
+ // FIXME timeout
+ // FIXME possibly limit results here
+ err := m.Db.Where("h_mailbox = ? AND read = ?", vars["h_mailbox"], false).Find(&entries).Error
+ if err != nil {
+ w.WriteHeader(http.StatusInternalServerError)
+ return
+ }
+ if len(entries) == 0 {
+ w.WriteHeader(http.StatusNoContent)
+ return
+ }
+ for _, entry := range entries {
+ eph, err := gnunetutil.DecodeStringToBinary(entry.EphemeralKey, 32)
+ if err != nil {
+ w.WriteHeader(http.StatusInternalServerError)
+ return
+ }
+ body, err := gnunetutil.DecodeStringToBinary(entry.Body, 256-32)
+ if err != nil {
+ w.WriteHeader(http.StatusInternalServerError)
+ return
+ }
+ w.Write(eph)
+ w.Write(body)
+ }
+ w.WriteHeader(http.StatusOK)
+}
+
+func (m *Mailbox) sendMessageResponse(w http.ResponseWriter, r *http.Request) {
+ vars := mux.Vars(r)
+ var msg identityMessage
+ var entry inboxEntry
+ if r.Body == nil {
+ http.Error(w, "No request body", 400)
+ return
+ }
+ err := json.NewDecoder(r.Body).Decode(&msg)
+ if err != nil {
+ w.WriteHeader(http.StatusInternalServerError)
+ return
+ }
+ tx := m.Db.Where("h_mailbox = ?", vars["h_mailbox"])
+ // FIXME max messages from config
+ // FIXME unclear if this is how the API is defined
+ if tx.RowsAffected > 10 {
+ w.WriteHeader(http.StatusTooManyRequests)
+ return
+ }
+ err = m.Db.First(&entry, "h_mailbox = ? AND ephemeral_key = ? AND body = ?", vars["h_mailbox"], msg.EphemeralKey, msg.Body).Error
+ // FIXME
+ cost, _ := talerutil.ParseAmount("KUDOS:1")
+ if err != nil {
+ entry.HMailbox = vars["h_mailbox"]
+ entry.EphemeralKey = msg.EphemeralKey
+ entry.Body = msg.Body
+ }
+ if len(entry.OrderID) == 0 {
+ // Add new order for new entry
+ orderID, newOrderErr := m.Merchant.AddNewOrder(*cost)
+ if newOrderErr != nil {
+ fmt.Println(newOrderErr)
+ w.WriteHeader(http.StatusInternalServerError)
+ return
+ }
+ entry.OrderID = orderID
+ }
+ // Check if order paid.
+ payto, paytoErr := m.Merchant.IsOrderPaid(entry.OrderID)
+ if paytoErr != nil {
+ fmt.Println(paytoErr)
+ w.WriteHeader(http.StatusInternalServerError)
+ log.Println(paytoErr)
+ return
+ }
+ if len(payto) != 0 {
+ m.Db.Save(&entry)
+ w.WriteHeader(http.StatusPaymentRequired)
+ w.Header().Set("Taler", payto)
+ return
+ }
+ // In this case, this order was paid
+ m.Db.Save(&entry)
+ w.WriteHeader(http.StatusNoContent)
+}
+
func (m *Mailbox) termsResponse(w http.ResponseWriter, r *http.Request) {
tos.ServiceTermsResponse(m.Cfg.Section("mailbox"), w, r)
}
@@ -123,6 +239,9 @@ func (m *Mailbox) setupHandlers() {
/* Config API */
m.Router.HandleFunc("/config", m.configResponse).Methods("GET")
+ /* Mailbox API */
+ m.Router.HandleFunc("/{h_mailbox}", m.sendMessageResponse).Methods("POST")
+ m.Router.HandleFunc("/{h_mailbox}", m.getMessagesResponse).Methods("GET")
}
// Initialize the Mailbox instance with cfgfile
@@ -150,7 +269,7 @@ func (m *Mailbox) Initialize(cfgfile string) {
panic(err)
}
m.Db = _db
- if err := m.Db.AutoMigrate(&message{}); err != nil {
+ if err := m.Db.AutoMigrate(&inboxEntry{}); err != nil {
panic(err)
}