diff options
author | Martin Schanzenbach <schanzen@gnunet.org> | 2022-07-19 18:57:10 +0200 |
---|---|---|
committer | Martin Schanzenbach <schanzen@gnunet.org> | 2022-07-19 18:57:10 +0200 |
commit | 485861ffce6d8b1983e5573c0c60a43d7cbc0e07 (patch) | |
tree | 316ab88269f57230f1acd53c2199f10f1b2a2ad8 | |
parent | ce8a3d30783476d4d3bb6a54c0c0116c13d49112 (diff) | |
download | taler-mailbox-485861ffce6d8b1983e5573c0c60a43d7cbc0e07.tar.gz taler-mailbox-485861ffce6d8b1983e5573c0c60a43d7cbc0e07.tar.bz2 taler-mailbox-485861ffce6d8b1983e5573c0c60a43d7cbc0e07.zip |
more API
-rw-r--r-- | go.mod | 4 | ||||
-rw-r--r-- | go.sum | 13 | ||||
-rw-r--r-- | pkg/rest/mailbox.go | 123 |
3 files changed, 138 insertions, 2 deletions
@@ -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 ) @@ -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) } |