Skip to content

Commit

Permalink
add UTs for PollInvoice
Browse files Browse the repository at this point in the history
  • Loading branch information
MuhammadUmer44 committed Mar 7, 2024
1 parent f34449a commit 46e6b64
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 25 deletions.
30 changes: 14 additions & 16 deletions handlers/bounty.go
Original file line number Diff line number Diff line change
Expand Up @@ -606,15 +606,14 @@ func formatPayError(errorMsg string) db.InvoicePayError {
}
}

func GetLightningInvoice(payment_request string) (db.InvoiceResult, db.InvoiceError) {
func (h *bountyHandler) GetLightningInvoice(payment_request string) (db.InvoiceResult, db.InvoiceError) {
url := fmt.Sprintf("%s/invoice?payment_request=%s", config.RelayUrl, payment_request)

client := &http.Client{}
req, err := http.NewRequest(http.MethodGet, url, nil)

req.Header.Set("x-user-token", config.RelayAuthKey)
req.Header.Set("Content-Type", "application/json")
res, _ := client.Do(req)
res, _ := h.httpClient.Do(req)

if err != nil {
log.Printf("Request Failed: %s", err)
Expand Down Expand Up @@ -693,9 +692,9 @@ func (h *bountyHandler) PayLightningInvoice(payment_request string) (db.InvoiceP
}
}

func GetInvoiceData(w http.ResponseWriter, r *http.Request) {
func (h *bountyHandler) GetInvoiceData(w http.ResponseWriter, r *http.Request) {
paymentRequest := chi.URLParam(r, "paymentRequest")
invoiceData, invoiceErr := GetLightningInvoice(paymentRequest)
invoiceData, invoiceErr := h.GetLightningInvoice(paymentRequest)

if invoiceErr.Error != "" {
w.WriteHeader(http.StatusForbidden)
Expand All @@ -707,7 +706,7 @@ func GetInvoiceData(w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(invoiceData)
}

func PollInvoice(w http.ResponseWriter, r *http.Request) {
func (h *bountyHandler) PollInvoice(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
pubKeyFromAuth, _ := ctx.Value(auth.ContextKey).(string)
paymentRequest := chi.URLParam(r, "paymentRequest")
Expand All @@ -719,7 +718,7 @@ func PollInvoice(w http.ResponseWriter, r *http.Request) {
return
}

invoiceRes, invoiceErr := GetLightningInvoice(paymentRequest)
invoiceRes, invoiceErr := h.GetLightningInvoice(paymentRequest)

if invoiceErr.Error != "" {
w.WriteHeader(http.StatusForbidden)
Expand All @@ -729,14 +728,14 @@ func PollInvoice(w http.ResponseWriter, r *http.Request) {

if invoiceRes.Response.Settled {
// Todo if an invoice is settled
invoice := db.DB.GetInvoice(paymentRequest)
invData := db.DB.GetUserInvoiceData(paymentRequest)
dbInvoice := db.DB.GetInvoice(paymentRequest)
invoice := h.db.GetInvoice(paymentRequest)
invData := h.db.GetUserInvoiceData(paymentRequest)
dbInvoice := h.db.GetInvoice(paymentRequest)

// Make any change only if the invoice has not been settled
if !dbInvoice.Status {
if invoice.Type == "BUDGET" {
db.DB.AddAndUpdateBudget(invoice)
h.db.AddAndUpdateBudget(invoice)
} else if invoice.Type == "KEYSEND" {
url := fmt.Sprintf("%s/payment", config.RelayUrl)

Expand All @@ -746,12 +745,11 @@ func PollInvoice(w http.ResponseWriter, r *http.Request) {

jsonBody := []byte(bodyData)

client := &http.Client{}
req, _ := http.NewRequest(http.MethodPost, url, bytes.NewBuffer(jsonBody))

req.Header.Set("x-user-token", config.RelayAuthKey)
req.Header.Set("Content-Type", "application/json")
res, _ := client.Do(req)
res, _ := h.httpClient.Do(req)

if err != nil {
log.Printf("Request Failed: %s", err)
Expand All @@ -767,13 +765,13 @@ func PollInvoice(w http.ResponseWriter, r *http.Request) {
keysendRes := db.KeysendSuccess{}
err = json.Unmarshal(body, &keysendRes)

bounty, err := db.DB.GetBountyByCreated(uint(invData.Created))
bounty, err := h.db.GetBountyByCreated(uint(invData.Created))

if err == nil {
bounty.Paid = true
}

db.DB.UpdateBounty(bounty)
h.db.UpdateBounty(bounty)
} else {
// Unmarshal result
keysendError := db.KeysendError{}
Expand All @@ -782,7 +780,7 @@ func PollInvoice(w http.ResponseWriter, r *http.Request) {
}
}
// Update the invoice status
db.DB.UpdateInvoice(paymentRequest)
h.db.UpdateInvoice(paymentRequest)
}

}
Expand Down
86 changes: 85 additions & 1 deletion handlers/bounty_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"encoding/json"
"errors"
"fmt"
"github.com/stakwork/sphinx-tribes/utils"
"io"
"net/http"
"net/http/httptest"
Expand All @@ -16,6 +15,8 @@ import (
"testing"
"time"

"github.com/stakwork/sphinx-tribes/utils"

"github.com/go-chi/chi"
"github.com/lib/pq"
"github.com/stakwork/sphinx-tribes/auth"
Expand Down Expand Up @@ -1431,3 +1432,86 @@ func TestBountyBudgetWithdraw(t *testing.T) {
mockHttpClient.AssertCalled(t, "Do", mock.AnythingOfType("*http.Request"))
})
}

func TestPollInvoice(t *testing.T) {
ctx := context.Background()
mockDb := &dbMocks.Database{}
mockHttpClient := &mocks.HttpClient{}
bHandler := NewBountyHandler(mockHttpClient, mockDb)

unauthorizedCtx := context.WithValue(ctx, auth.ContextKey, "")
authorizedCtx := context.WithValue(ctx, auth.ContextKey, "valid-key")

t.Run("Should test that a 401 error is returned if a user is unauthorized", func(t *testing.T) {
r := chi.NewRouter()
r.Post("/poll/invoice/{paymentRequest}", bHandler.PollInvoice)

rr := httptest.NewRecorder()
req, err := http.NewRequestWithContext(unauthorizedCtx, http.MethodPost, "/poll/invoice/1", bytes.NewBufferString(`{}`))
if err != nil {
t.Fatal(err)
}

r.ServeHTTP(rr, req)

assert.Equal(t, http.StatusUnauthorized, rr.Code, "Expected 401 error if a user is unauthorized")
})

t.Run("Should test that a 403 error is returned if there is an invoice error", func(t *testing.T) {
expectedUrl := fmt.Sprintf("%s/invoice?payment_request=%s", config.RelayUrl, "1")

r := io.NopCloser(bytes.NewReader([]byte(`{"success": false, "error": "Internel server error"}`)))
mockHttpClient.On("Do", mock.MatchedBy(func(req *http.Request) bool {
return req.Method == http.MethodGet && expectedUrl == req.URL.String() && req.Header.Get("x-user-token") == config.RelayAuthKey
})).Return(&http.Response{
StatusCode: 500,
Body: r,
}, nil).Once()

ro := chi.NewRouter()
ro.Post("/poll/invoice/{paymentRequest}", bHandler.PollInvoice)

rr := httptest.NewRecorder()
req, err := http.NewRequestWithContext(authorizedCtx, http.MethodPost, "/poll/invoice/1", bytes.NewBufferString(`{}`))
if err != nil {
t.Fatal(err)
}

ro.ServeHTTP(rr, req)

assert.Equal(t, http.StatusForbidden, rr.Code, "Expected 403 error if there is an invoice error")
mockHttpClient.AssertExpectations(t)
})

t.Run("If the invoice is settled and the invoice.Type is equal to BUDGET the invoice amount should be added to the organization budget and the payment status of the related invoice should be sent to true on the payment history table", func(t *testing.T) {
expectedUrl := fmt.Sprintf("%s/invoice?payment_request=%s", config.RelayUrl, "1")

r := io.NopCloser(bytes.NewReader([]byte(`{"success": true, "response": { "settled": true, "payment_request": "1", "payment_hash": "payment_hash", "preimage": "preimage", "Amount": "1000"}}`)))
mockHttpClient.On("Do", mock.MatchedBy(func(req *http.Request) bool {
return req.Method == http.MethodGet && expectedUrl == req.URL.String() && req.Header.Get("x-user-token") == config.RelayAuthKey
})).Return(&http.Response{
StatusCode: 200,
Body: r,
}, nil).Once()

mockDb.On("GetInvoice", "1").Return(db.InvoiceList{Type: "BUDGET"})
mockDb.On("GetUserInvoiceData", "1").Return(db.UserInvoiceData{Amount: 1000, UserPubkey: "UserPubkey", RouteHint: "RouteHint", Created: 1234})
mockDb.On("GetInvoice", "1").Return(db.InvoiceList{Status: false})
mockDb.On("AddAndUpdateBudget", mock.Anything).Return(db.PaymentHistory{})
mockDb.On("UpdateInvoice", "1").Return(db.InvoiceList{}).Once()

ro := chi.NewRouter()
ro.Post("/poll/invoice/{paymentRequest}", bHandler.PollInvoice)

rr := httptest.NewRecorder()
req, err := http.NewRequestWithContext(authorizedCtx, http.MethodPost, "/poll/invoice/1", bytes.NewBufferString(`{}`))
if err != nil {
t.Fatal(err)
}

ro.ServeHTTP(rr, req)

assert.Equal(t, http.StatusOK, rr.Code)
mockHttpClient.AssertExpectations(t)
})
}
12 changes: 7 additions & 5 deletions handlers/organizations.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@ import (
type organizationHandler struct {
db db.Database
generateBountyHandler func(bounties []db.Bounty) []db.BountyResponse
getLightningInvoice func(payment_request string) (db.InvoiceResult, db.InvoiceError)
}

func NewOrganizationHandler(db db.Database) *organizationHandler {
bHandler := NewBountyHandler(http.DefaultClient, db)
return &organizationHandler{
db: db,
generateBountyHandler: bHandler.GenerateBountyResponse,
getLightningInvoice: bHandler.GetLightningInvoice,
}
}

Expand Down Expand Up @@ -630,7 +632,7 @@ func GetPaymentHistory(w http.ResponseWriter, r *http.Request) {
json.NewEncoder(w).Encode(paymentHistoryData)
}

func PollBudgetInvoices(w http.ResponseWriter, r *http.Request) {
func (oh *organizationHandler) PollBudgetInvoices(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
pubKeyFromAuth, _ := ctx.Value(auth.ContextKey).(string)
uuid := chi.URLParam(r, "uuid")
Expand All @@ -641,10 +643,10 @@ func PollBudgetInvoices(w http.ResponseWriter, r *http.Request) {
return
}

orgInvoices := db.DB.GetOrganizationInvoices(uuid)
orgInvoices := oh.db.GetOrganizationInvoices(uuid)

for _, inv := range orgInvoices {
invoiceRes, invoiceErr := GetLightningInvoice(inv.PaymentRequest)
invoiceRes, invoiceErr := oh.getLightningInvoice(inv.PaymentRequest)

if invoiceErr.Error != "" {
w.WriteHeader(http.StatusForbidden)
Expand All @@ -654,9 +656,9 @@ func PollBudgetInvoices(w http.ResponseWriter, r *http.Request) {

if invoiceRes.Response.Settled {
if !inv.Status && inv.Type == "BUDGET" {
db.DB.AddAndUpdateBudget(inv)
oh.db.AddAndUpdateBudget(inv)
// Update the invoice status
db.DB.UpdateInvoice(inv.PaymentRequest)
oh.db.UpdateInvoice(inv.PaymentRequest)
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion routes/bounty.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func BountyRoutes() chi.Router {
r.Get("/created/{created}", bountyHandler.GetBountyByCreated)
r.Get("/count/{personKey}/{tabType}", handlers.GetUserBountyCount)
r.Get("/count", handlers.GetBountyCount)
r.Get("/invoice/{paymentRequest}", handlers.GetInvoiceData)
r.Get("/invoice/{paymentRequest}", bountyHandler.GetInvoiceData)
r.Get("/filter/count", handlers.GetFilterCount)

})
Expand Down
3 changes: 2 additions & 1 deletion routes/index.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ func NewRouter() *http.Server {
authHandler := handlers.NewAuthHandler(db.DB)
channelHandler := handlers.NewChannelHandler(db.DB)
botHandler := handlers.NewBotHandler(db.DB)
bHandler := handlers.NewBountyHandler(http.DefaultClient, db.DB)

r.Mount("/tribes", TribeRoutes())
r.Mount("/bots", BotsRoutes())
Expand Down Expand Up @@ -75,7 +76,7 @@ func NewRouter() *http.Server {
r.Post("/badges", handlers.AddOrRemoveBadge)
r.Delete("/channel/{id}", channelHandler.DeleteChannel)
r.Delete("/ticket/{pubKey}/{created}", handlers.DeleteTicketByAdmin)
r.Get("/poll/invoice/{paymentRequest}", handlers.PollInvoice)
r.Get("/poll/invoice/{paymentRequest}", bHandler.PollInvoice)
r.Post("/meme_upload", handlers.MemeImageUpload)
r.Get("/admin/auth", authHandler.GetIsAdmin)
})
Expand Down
2 changes: 1 addition & 1 deletion routes/organizations.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func OrganizationRoutes() chi.Router {
r.Get("/budget/{uuid}", organizationHandlers.GetOrganizationBudget)
r.Get("/budget/history/{uuid}", organizationHandlers.GetOrganizationBudgetHistory)
r.Get("/payments/{uuid}", handlers.GetPaymentHistory)
r.Get("/poll/invoices/{uuid}", handlers.PollBudgetInvoices)
r.Get("/poll/invoices/{uuid}", organizationHandlers.PollBudgetInvoices)
r.Get("/invoices/count/{uuid}", handlers.GetInvoicesCount)
r.Delete("/delete/{uuid}", organizationHandlers.DeleteOrganization)
})
Expand Down

0 comments on commit 46e6b64

Please sign in to comment.