taler-mailbox

Service for asynchronous wallet-to-wallet payment messages
Log | Files | Refs | Submodules | README | LICENSE

commit 73098709dc206cf812610c846d039bbf49cb7d5c
parent 1b46dc08ebce5ea8fbe6bfeaa17a7348517d986e
Author: Martin Schanzenbach <schanzen@gnunet.org>
Date:   Fri, 25 Apr 2025 15:35:37 +0200

refactoring and code cleanup

Diffstat:
Mcmd/mailbox-server/main_test.go | 326++++++++++++++++++++++++++++++++++++++++----------------------------------------
Mpkg/rest/mailbox.go | 352+++++++++++++++++++++++++++++++++++++++++--------------------------------------
2 files changed, 348 insertions(+), 330 deletions(-)

diff --git a/cmd/mailbox-server/main_test.go b/cmd/mailbox-server/main_test.go @@ -54,195 +54,195 @@ const merchantConfigResponse = `{ }` func executeRequest(req *http.Request) *httptest.ResponseRecorder { - rr := httptest.NewRecorder() - a.Router.ServeHTTP(rr, req) - return rr + rr := httptest.NewRecorder() + a.Router.ServeHTTP(rr, req) + return rr } func checkResponseCode(t *testing.T, expected, actual int) { - if expected != actual { - t.Errorf("Expected response code %d, Got %d\n", expected, actual) - } + if expected != actual { + t.Errorf("Expected response code %d, Got %d\n", expected, actual) + } } func TestMain(m *testing.M) { - a.Initialize("test-mailbox.conf") - testWalletAlice, testWalletAlicePriv, _ = ed25519.GenerateKey(nil) - h := sha512.New() - h.Write(testWalletAlice) - testWalletAliceString = gnunetutil.EncodeBinaryToString(h.Sum(nil)) - - merchServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - var orderResp merchant.PostOrderRequest - if r.URL.Path == "/config" { - w.WriteHeader(http.StatusOK) - w.Write([]byte(merchantConfigResponse)) - return - } - if !strings.HasPrefix(r.URL.Path, "/private/orders") { - fmt.Printf("Expected to request '/private/orders', got: %s\n", r.URL.Path) - return - } - if r.Method == http.MethodPost { - err := json.NewDecoder(r.Body).Decode(&orderResp) - if err != nil { - fmt.Printf("Error %s\n", err) - } - jsonResp := fmt.Sprintf("{\"order_id\":\"%s\"}", orderResp.Order.OrderId) - w.WriteHeader(http.StatusOK) - w.Write([]byte(jsonResp)) - } else { - if r.Header.Get("PaidIndicator") == "yes" { - jsonResp := "{\"order_status\":\"paid\"}" - w.WriteHeader(http.StatusOK) - w.Write([]byte(jsonResp)) - } else { - jsonResp := "{\"order_status\":\"unpaid\", \"taler_pay_uri\": \"somepaytouri\"}" - w.WriteHeader(http.StatusOK) - w.Write([]byte(jsonResp)) - } - } - })) - defer merchServer.Close() - a.Merchant = merchant.NewMerchant(merchServer.URL, "") - - code := m.Run() - // Purge DB - a.Db.Where("1 = 1").Delete(&mailbox.InboxEntry{}) - os.Exit(code) + a.Initialize("test-mailbox.conf") + testWalletAlice, testWalletAlicePriv, _ = ed25519.GenerateKey(nil) + h := sha512.New() + h.Write(testWalletAlice) + testWalletAliceString = gnunetutil.EncodeBinaryToString(h.Sum(nil)) + + merchServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + var orderResp merchant.PostOrderRequest + if r.URL.Path == "/config" { + w.WriteHeader(http.StatusOK) + w.Write([]byte(merchantConfigResponse)) + return + } + if !strings.HasPrefix(r.URL.Path, "/private/orders") { + fmt.Printf("Expected to request '/private/orders', got: %s\n", r.URL.Path) + return + } + if r.Method == http.MethodPost { + err := json.NewDecoder(r.Body).Decode(&orderResp) + if err != nil { + fmt.Printf("Error %s\n", err) + } + jsonResp := fmt.Sprintf("{\"order_id\":\"%s\"}", orderResp.Order.OrderId) + w.WriteHeader(http.StatusOK) + w.Write([]byte(jsonResp)) + } else { + if r.Header.Get("PaidIndicator") == "yes" { + jsonResp := "{\"order_status\":\"paid\"}" + w.WriteHeader(http.StatusOK) + w.Write([]byte(jsonResp)) + } else { + jsonResp := "{\"order_status\":\"unpaid\", \"taler_pay_uri\": \"somepaytouri\"}" + w.WriteHeader(http.StatusOK) + w.Write([]byte(jsonResp)) + } + } + })) + defer merchServer.Close() + a.Merchant = merchant.NewMerchant(merchServer.URL, "") + + code := m.Run() + // Purge DB + a.Db.Where("1 = 1").Delete(&mailbox.InboxEntry{}) + os.Exit(code) } func TestEmptyMailbox(t *testing.T) { - a.Db.Where("1 = 1").Delete(&mailbox.InboxEntry{}) - req, _ := http.NewRequest("GET", "/" + testWalletAliceString, nil) - response := executeRequest(req) + a.Db.Where("1 = 1").Delete(&mailbox.InboxEntry{}) + req, _ := http.NewRequest("GET", "/"+testWalletAliceString, nil) + response := executeRequest(req) - checkResponseCode(t, http.StatusNoContent, response.Code) + checkResponseCode(t, http.StatusNoContent, response.Code) - body := response.Body.String() - if body != "" { - t.Errorf("Expected empty response, Got %s", body) - } + body := response.Body.String() + if body != "" { + t.Errorf("Expected empty response, Got %s", body) + } } func TestPostMessage(t *testing.T) { - testMessage := make([]byte, 256) - a.Db.Where("1 = 1").Delete(&mailbox.InboxEntry{}) - req, _ := http.NewRequest("POST", "/" + testWalletAliceString, bytes.NewReader(testMessage)) - response := executeRequest(req) + testMessage := make([]byte, 256) + a.Db.Where("1 = 1").Delete(&mailbox.InboxEntry{}) + req, _ := http.NewRequest("POST", "/"+testWalletAliceString, bytes.NewReader(testMessage)) + response := executeRequest(req) - checkResponseCode(t, http.StatusNoContent, response.Code) + checkResponseCode(t, http.StatusNoContent, response.Code) - body := response.Body.String() - if body != "" { - t.Errorf("Expected empty response, Got %s", body) - } + body := response.Body.String() + if body != "" { + t.Errorf("Expected empty response, Got %s", body) + } } func TestPostMessagePaid(t *testing.T) { - testMessage := make([]byte, 256) + testMessage := make([]byte, 256) - // Make paid - fee,err := util.ParseAmount("KUDOS:1") - if err != nil { - t.Errorf("%v", err) - } - a.MessageFee = fee - a.Db.Where("1 = 1").Delete(&mailbox.InboxEntry{}) - req, _ := http.NewRequest("POST", "/" + testWalletAliceString, bytes.NewReader(testMessage)) - response := executeRequest(req) + // Make paid + fee, err := util.ParseAmount("KUDOS:1") + if err != nil { + t.Errorf("%v", err) + } + a.MessageFee = fee + a.Db.Where("1 = 1").Delete(&mailbox.InboxEntry{}) + req, _ := http.NewRequest("POST", "/"+testWalletAliceString, bytes.NewReader(testMessage)) + response := executeRequest(req) - checkResponseCode(t, http.StatusPaymentRequired, response.Code) + checkResponseCode(t, http.StatusPaymentRequired, response.Code) - // TODO check QR / payto response + // TODO check QR / payto response - req, _ = http.NewRequest("POST", "/" + testWalletAliceString, bytes.NewReader(testMessage)) - req.Header.Add("PaidIndicator", "yes") - response = executeRequest(req) + req, _ = http.NewRequest("POST", "/"+testWalletAliceString, bytes.NewReader(testMessage)) + req.Header.Add("PaidIndicator", "yes") + response = executeRequest(req) - checkResponseCode(t, http.StatusPaymentRequired, response.Code) + checkResponseCode(t, http.StatusPaymentRequired, response.Code) - body := response.Body.String() - if body != "" { - t.Errorf("Expected empty response, Got %s", body) - } - a.MessageFee,_ = util.ParseAmount("KUDOS:0") + body := response.Body.String() + if body != "" { + t.Errorf("Expected empty response, Got %s", body) + } + a.MessageFee, _ = util.ParseAmount("KUDOS:0") } func TestPostThenDeleteMessage(t *testing.T) { - // testMessage := make([]byte, 256) - var deletionReq mailbox.MessageDeletionRequest - testMessages := make([]byte, 25600) - _, _ = rand.Read(testMessages) - a.Db.Where("1 = 1").Delete(&mailbox.InboxEntry{}) - - for i := 0; i < 100; i++ { - testMessage := testMessages[i*256:(i+1)*256] - req, _ := http.NewRequest("POST", "/" + testWalletAliceString, bytes.NewReader(testMessage)) - response := executeRequest(req) - - checkResponseCode(t, http.StatusNoContent, response.Code) - - body := response.Body.String() - if body != "" { - t.Errorf("Expected empty response, Got %s", body) - } - } - - req, _ := http.NewRequest("GET", "/" + testWalletAliceString, nil) - response := executeRequest(req) - - checkResponseCode(t, http.StatusOK, response.Code) - - if response.Body.Len() != 25600 { - t.Errorf("Expected response of 25600 bytes, Got %d", response.Body.Len()) - } - - etag := response.Result().Header.Get("ETag") - - if etag == "" { - t.Errorf("ETag missing!\n") - } - - // Now delete 10 messages - h := sha512.New() - for i := 0; i < 10; i++ { - h.Write(testMessages[i*256:(i+1)*256]) - } - var signed_msg [64+4+4]byte - size := signed_msg[0:4] - binary.BigEndian.PutUint32(size, 64+4+4) - purp := signed_msg[4:8] - binary.BigEndian.PutUint32(purp, gana.TALER_SIGNATURE_PURPOSE_MAILBOX_MESSAGES_DELETE) - checksum := h.Sum(nil) - copy(signed_msg[8:], checksum) - sig := ed25519.Sign(testWalletAlicePriv, signed_msg[0:]) - if !ed25519.Verify(testWalletAlice, signed_msg[0:], sig) { - t.Errorf("Signature invalid!") - } - deletionReq.WalletSig = gnunetutil.EncodeBinaryToString(sig) - deletionReq.Count = 10 - deletionReq.Checksum = gnunetutil.EncodeBinaryToString(checksum) - reqJson, _ := json.Marshal(deletionReq) - - hAddress := gnunetutil.EncodeBinaryToString(testWalletAlice) - req, _ = http.NewRequest("DELETE", "/" + hAddress, bytes.NewBuffer(reqJson)) - req.Header.Add("If-Match", etag) - response = executeRequest(req) - - checkResponseCode(t, http.StatusNoContent, response.Code) - - body := response.Body.String() - if body != "" { - t.Errorf("Expected empty response, Got %s", body) - } - - req, _ = http.NewRequest("GET", "/" + testWalletAliceString, nil) - response = executeRequest(req) - - checkResponseCode(t, http.StatusOK, response.Code) - - if response.Body.Len() != 25600 - 2560 { - t.Errorf("Expected response of 25600 - 2560 bytes, Got %d", response.Body.Len()) - } + // testMessage := make([]byte, 256) + var deletionReq mailbox.MessageDeletionRequest + testMessages := make([]byte, 25600) + _, _ = rand.Read(testMessages) + a.Db.Where("1 = 1").Delete(&mailbox.InboxEntry{}) + + for i := 0; i < 100; i++ { + testMessage := testMessages[i*256 : (i+1)*256] + req, _ := http.NewRequest("POST", "/"+testWalletAliceString, bytes.NewReader(testMessage)) + response := executeRequest(req) + + checkResponseCode(t, http.StatusNoContent, response.Code) + + body := response.Body.String() + if body != "" { + t.Errorf("Expected empty response, Got %s", body) + } + } + + req, _ := http.NewRequest("GET", "/"+testWalletAliceString, nil) + response := executeRequest(req) + + checkResponseCode(t, http.StatusOK, response.Code) + + if response.Body.Len() != 25600 { + t.Errorf("Expected response of 25600 bytes, Got %d", response.Body.Len()) + } + + etag := response.Result().Header.Get("ETag") + + if etag == "" { + t.Errorf("ETag missing!\n") + } + + // Now delete 10 messages + h := sha512.New() + for i := 0; i < 10; i++ { + h.Write(testMessages[i*256 : (i+1)*256]) + } + var signed_msg [64 + 4 + 4]byte + size := signed_msg[0:4] + binary.BigEndian.PutUint32(size, 64+4+4) + purp := signed_msg[4:8] + binary.BigEndian.PutUint32(purp, gana.TALER_SIGNATURE_PURPOSE_MAILBOX_MESSAGES_DELETE) + checksum := h.Sum(nil) + copy(signed_msg[8:], checksum) + sig := ed25519.Sign(testWalletAlicePriv, signed_msg[0:]) + if !ed25519.Verify(testWalletAlice, signed_msg[0:], sig) { + t.Errorf("Signature invalid!") + } + deletionReq.WalletSig = gnunetutil.EncodeBinaryToString(sig) + deletionReq.Count = 10 + deletionReq.Checksum = gnunetutil.EncodeBinaryToString(checksum) + reqJson, _ := json.Marshal(deletionReq) + + hAddress := gnunetutil.EncodeBinaryToString(testWalletAlice) + req, _ = http.NewRequest("DELETE", "/"+hAddress, bytes.NewBuffer(reqJson)) + req.Header.Add("If-Match", etag) + response = executeRequest(req) + + checkResponseCode(t, http.StatusNoContent, response.Code) + + body := response.Body.String() + if body != "" { + t.Errorf("Expected empty response, Got %s", body) + } + + req, _ = http.NewRequest("GET", "/"+testWalletAliceString, nil) + response = executeRequest(req) + + checkResponseCode(t, http.StatusOK, response.Code) + + if response.Body.Len() != 25600-2560 { + t.Errorf("Expected response of 25600 - 2560 bytes, Got %d", response.Body.Len()) + } } diff --git a/pkg/rest/mailbox.go b/pkg/rest/mailbox.go @@ -133,10 +133,6 @@ type InboxEntry struct { // Hash of the inbox for this entry HMailbox string - - // Order ID - OrderID string - } func (m *Mailbox) configResponse(w http.ResponseWriter, r *http.Request) { @@ -202,193 +198,215 @@ func (m *Mailbox) sendMessageResponse(w http.ResponseWriter, r *http.Request) { return } err = m.Db.First(&entry, "h_mailbox = ? AND body = ?", vars["h_mailbox"], body, true).Error - if err != nil { - entry.HMailbox = vars["h_mailbox"] - entry.Body = body + if err == nil { + w.WriteHeader(http.StatusNotModified) + return + } + entry.HMailbox = vars["h_mailbox"] + entry.Body = body + if m.MessageFee.IsZero() { + m.Db.Save(&entry) + w.WriteHeader(http.StatusNoContent) + return + } + + // Check if order exists and was paid already. + h := sha256.New() + h.Sum(body) + orderId := gnunetutil.EncodeBinaryToString(h.Sum(nil)) + httpStatus, paymentStatus, payto, paytoErr := m.Merchant.IsOrderPaid(orderId) + if paytoErr != nil { + fmt.Println(paytoErr) + w.WriteHeader(http.StatusInternalServerError) + return } - if !m.MessageFee.IsZero() { - if len(entry.OrderID) == 0 { - // Add new order for new entry - var order merchant.CommonOrder - order.Amount = m.MessageFee.String() - order.Summary = "Mailbox message dispatch" - order.MerchantBaseUrl = m.BaseUrl - h := sha256.New() - h.Sum(body) - order.OrderId = gnunetutil.EncodeBinaryToString(h.Sum(nil)) - orderID, newOrderErr := m.Merchant.CreateOrder(order) - if newOrderErr != nil { - fmt.Println(newOrderErr) - w.WriteHeader(http.StatusInternalServerError) - return - } - entry.OrderID = orderID + switch httpStatus { + case http.StatusNotFound: + // Not found. Create new order. + var order merchant.CommonOrder + order.OrderId = orderId + order.Amount = m.MessageFee.String() + order.Summary = "Mailbox message dispatch" + order.MerchantBaseUrl = m.BaseUrl + _, newOrderErr := m.Merchant.CreateOrder(order) + if newOrderErr != nil { + fmt.Println(newOrderErr) + w.WriteHeader(http.StatusInternalServerError) + return } - // Check if order paid. - _, paymentStatus, payto, paytoErr := m.Merchant.IsOrderPaid(entry.OrderID) + // Check for oder again to get payto. + _, _, payto, paytoErr = m.Merchant.IsOrderPaid(orderId) if paytoErr != nil { fmt.Println(paytoErr) w.WriteHeader(http.StatusInternalServerError) - log.Println(paytoErr) return } - if paymentStatus != "paid" { - m.Db.Save(&entry) - w.WriteHeader(http.StatusPaymentRequired) - if payto != "" { - w.Header().Set("Taler", payto) - } - return - } - } - // In this case, this order was paid - m.Db.Save(&entry) - w.WriteHeader(http.StatusNoContent) + if payto == "" { + fmt.Println(paytoErr) + w.WriteHeader(http.StatusInternalServerError) + return + } + w.WriteHeader(http.StatusPaymentRequired) + w.Header().Set("Taler", payto) + return + case http.StatusOK: + // Check if it was actually paid. + if paymentStatus == "paid" { + m.Db.Save(&entry) + w.WriteHeader(http.StatusNoContent) + return + } + w.WriteHeader(http.StatusPaymentRequired) + if payto != "" { + w.Header().Set("Taler", payto) + } + return + } } func (m *Mailbox) deleteMessagesResponse(w http.ResponseWriter, r *http.Request) { - vars := mux.Vars(r) - var msg MessageDeletionRequest - var entries []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 - } - etag_hdr := r.Header.Get("If-Match") - if etag_hdr == "" { - http.Error(w, "If-Match header missing", 400) - return - } - if strings.Contains(etag_hdr, ",") { - http.Error(w, "If-Match contains multiple values", 400) - return - } - etag_expected, err := strconv.Atoi(etag_hdr) - if err != nil { - http.Error(w, "If-Match contains malformed etag number", 400) - return - } - pkey, err := gnunetutil.DecodeStringToBinary(vars["mailbox"], 32) - if err != nil { - w.WriteHeader(http.StatusBadRequest) - return - } - checksum, err := gnunetutil.DecodeStringToBinary(msg.Checksum, 64) - if err != nil { - w.WriteHeader(http.StatusBadRequest) - return - } - pk := ed25519.PublicKey(pkey) - sig, err := gnunetutil.DecodeStringToBinary(msg.WalletSig, 64) - if nil != err { - w.WriteHeader(http.StatusBadRequest) - return - } - var signed_msg [72]byte - size := signed_msg[0:4] - binary.BigEndian.PutUint32(size, 64+4+4) - purp := signed_msg[4:8] - binary.BigEndian.PutUint32(purp, gana.TALER_SIGNATURE_PURPOSE_MAILBOX_MESSAGES_DELETE) - copy(signed_msg[8:], checksum) - if !ed25519.Verify(pk, signed_msg[0:], sig) { - w.WriteHeader(http.StatusForbidden) - return - } - h := sha512.New() - h.Write(pkey) - h_mailbox := gnunetutil.EncodeBinaryToString(h.Sum(nil)) - err = m.Db.Where("h_mailbox = ? AND id >= ?", h_mailbox, etag_expected).Limit(msg.Count).Find(&entries).Error - if err != nil { - w.WriteHeader(http.StatusInternalServerError) - return - } - if len(entries) != msg.Count { - w.WriteHeader(http.StatusNotFound) - return - } - if entries[0].ID != uint(etag_expected) { - w.WriteHeader(http.StatusPreconditionFailed) - return - } - h_all := sha512.New() - for _, entry := range entries { - h_all.Write(entry.Body) - } - if !bytes.Equal(h_all.Sum(nil), checksum) { - w.WriteHeader(http.StatusNotFound) - return - } - m.Db.Delete(&entries) - w.WriteHeader(http.StatusNoContent) + vars := mux.Vars(r) + var msg MessageDeletionRequest + var entries []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 + } + etag_hdr := r.Header.Get("If-Match") + if etag_hdr == "" { + http.Error(w, "If-Match header missing", 400) + return + } + if strings.Contains(etag_hdr, ",") { + http.Error(w, "If-Match contains multiple values", 400) + return + } + etag_expected, err := strconv.Atoi(etag_hdr) + if err != nil { + http.Error(w, "If-Match contains malformed etag number", 400) + return + } + pkey, err := gnunetutil.DecodeStringToBinary(vars["mailbox"], 32) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + return + } + checksum, err := gnunetutil.DecodeStringToBinary(msg.Checksum, 64) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + return + } + pk := ed25519.PublicKey(pkey) + sig, err := gnunetutil.DecodeStringToBinary(msg.WalletSig, 64) + if nil != err { + w.WriteHeader(http.StatusBadRequest) + return + } + var signed_msg [72]byte + size := signed_msg[0:4] + binary.BigEndian.PutUint32(size, 64+4+4) + purp := signed_msg[4:8] + binary.BigEndian.PutUint32(purp, gana.TALER_SIGNATURE_PURPOSE_MAILBOX_MESSAGES_DELETE) + copy(signed_msg[8:], checksum) + if !ed25519.Verify(pk, signed_msg[0:], sig) { + w.WriteHeader(http.StatusForbidden) + return + } + h := sha512.New() + h.Write(pkey) + h_mailbox := gnunetutil.EncodeBinaryToString(h.Sum(nil)) + err = m.Db.Where("h_mailbox = ? AND id >= ?", h_mailbox, etag_expected).Limit(msg.Count).Find(&entries).Error + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + if len(entries) != msg.Count { + w.WriteHeader(http.StatusNotFound) + return + } + if entries[0].ID != uint(etag_expected) { + w.WriteHeader(http.StatusPreconditionFailed) + return + } + h_all := sha512.New() + for _, entry := range entries { + h_all.Write(entry.Body) + } + if !bytes.Equal(h_all.Sum(nil), checksum) { + w.WriteHeader(http.StatusNotFound) + return + } + m.Db.Delete(&entries) + w.WriteHeader(http.StatusNoContent) } func (m *Mailbox) termsResponse(w http.ResponseWriter, r *http.Request) { - tos.ServiceTermsResponse(m.Cfg.Section("mailbox"), w, r) + tos.ServiceTermsResponse(m.Cfg.Section("mailbox"), w, r) } func (m *Mailbox) privacyResponse(w http.ResponseWriter, r *http.Request) { - tos.PrivacyPolicyResponse(m.Cfg.Section("mailbox"), w, r) + tos.PrivacyPolicyResponse(m.Cfg.Section("mailbox"), w, r) } func (m *Mailbox) setupHandlers() { - m.Router = mux.NewRouter().StrictSlash(true) + m.Router = mux.NewRouter().StrictSlash(true) - /* ToS API */ - m.Router.HandleFunc("/terms", m.termsResponse).Methods("GET") - m.Router.HandleFunc("/privacy", m.privacyResponse).Methods("GET") + /* ToS API */ + m.Router.HandleFunc("/terms", m.termsResponse).Methods("GET") + m.Router.HandleFunc("/privacy", m.privacyResponse).Methods("GET") - /* Config API */ - m.Router.HandleFunc("/config", m.configResponse).Methods("GET") + /* 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") - m.Router.HandleFunc("/{mailbox}", m.deleteMessagesResponse).Methods("DELETE") + /* Mailbox API */ + m.Router.HandleFunc("/{h_mailbox}", m.sendMessageResponse).Methods("POST") + m.Router.HandleFunc("/{h_mailbox}", m.getMessagesResponse).Methods("GET") + m.Router.HandleFunc("/{mailbox}", m.deleteMessagesResponse).Methods("DELETE") } // Initialize the Mailbox instance with cfgfile func (m *Mailbox) Initialize(cfgfile string) { - _cfg, err := ini.Load(cfgfile) - if err != nil { - fmt.Printf("Failed to read config: %v", err) - os.Exit(1) - } - m.Cfg = _cfg - if m.Cfg.Section("mailbox").Key("production").MustBool(false) { - fmt.Println("Production mode enabled") - } - m.BaseUrl = m.Cfg.Section("mailbox").Key("base_url").MustString("https://example.com") - m.MessageBodyBytes = m.Cfg.Section("mailbox").Key("message_body_bytes").MustInt64(256) - // FIXME actual cost - m.MessageFee, err = talerutil.ParseAmount(m.Cfg.Section("mailbox").Key("message_fee").MustString("KUDOS:1")) - if err != nil { - fmt.Printf("Failed to parse cost: %v", err) - os.Exit(1) - } - psqlconn := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable", - m.Cfg.Section("mailbox-pq").Key("host").MustString("localhost"), - m.Cfg.Section("mailbox-pq").Key("port").MustInt64(5432), - m.Cfg.Section("mailbox-pq").Key("user").MustString("taler-mailbox"), - m.Cfg.Section("mailbox-pq").Key("password").MustString("secret"), - m.Cfg.Section("mailbox-pq").Key("db_name").MustString("taler-mailbox")) - _db, err := gorm.Open(postgres.Open(psqlconn), &gorm.Config{ - Logger: logger.Default.LogMode(logger.Silent), - }) - if err != nil { - panic(err) - } - m.Db = _db - if err := m.Db.AutoMigrate(&InboxEntry{}); err != nil { - panic(err) - } - - merchURL := m.Cfg.Section("mailbox").Key("merchant_baseurl_private").MustString("http://merchant.mailbox/instances/myInstance") - merchToken := m.Cfg.Section("mailbox").Key("merchant_token").MustString("secretAccessToken") - m.Merchant = merchant.NewMerchant(merchURL, merchToken) - m.setupHandlers() + _cfg, err := ini.Load(cfgfile) + if err != nil { + fmt.Printf("Failed to read config: %v", err) + os.Exit(1) + } + m.Cfg = _cfg + if m.Cfg.Section("mailbox").Key("production").MustBool(false) { + fmt.Println("Production mode enabled") + } + m.BaseUrl = m.Cfg.Section("mailbox").Key("base_url").MustString("https://example.com") + m.MessageBodyBytes = m.Cfg.Section("mailbox").Key("message_body_bytes").MustInt64(256) + // FIXME actual cost + m.MessageFee, err = talerutil.ParseAmount(m.Cfg.Section("mailbox").Key("message_fee").MustString("KUDOS:1")) + if err != nil { + fmt.Printf("Failed to parse cost: %v", err) + os.Exit(1) + } + psqlconn := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable", + m.Cfg.Section("mailbox-pq").Key("host").MustString("localhost"), + m.Cfg.Section("mailbox-pq").Key("port").MustInt64(5432), + m.Cfg.Section("mailbox-pq").Key("user").MustString("taler-mailbox"), + m.Cfg.Section("mailbox-pq").Key("password").MustString("secret"), + m.Cfg.Section("mailbox-pq").Key("db_name").MustString("taler-mailbox")) + _db, err := gorm.Open(postgres.Open(psqlconn), &gorm.Config{ + Logger: logger.Default.LogMode(logger.Silent), + }) + if err != nil { + panic(err) + } + m.Db = _db + if err := m.Db.AutoMigrate(&InboxEntry{}); err != nil { + panic(err) + } + + merchURL := m.Cfg.Section("mailbox").Key("merchant_baseurl_private").MustString("http://merchant.mailbox/instances/myInstance") + merchToken := m.Cfg.Section("mailbox").Key("merchant_token").MustString("secretAccessToken") + m.Merchant = merchant.NewMerchant(merchURL, merchToken) + m.setupHandlers() }