Skip to content

Commit

Permalink
passed all unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
elraphty committed Apr 24, 2024
1 parent cf3e62a commit ac293a5
Show file tree
Hide file tree
Showing 9 changed files with 204 additions and 128 deletions.
4 changes: 2 additions & 2 deletions db/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -1249,8 +1249,8 @@ func (db database) UpdateBountyBoolColumn(b NewBounty, column string) NewBounty
return b
}

func (db database) DeleteBounty(pubkey string, created string) (Bounty, error) {
m := Bounty{}
func (db database) DeleteBounty(pubkey string, created string) (NewBounty, error) {
m := NewBounty{}
db.db.Where("owner_id", pubkey).Where("created", created).Delete(&m)
return m, nil
}
Expand Down
2 changes: 1 addition & 1 deletion db/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ type Database interface {
CreateOrEditBounty(b NewBounty) (NewBounty, error)
UpdateBountyNullColumn(b NewBounty, column string) NewBounty
UpdateBountyBoolColumn(b NewBounty, column string) NewBounty
DeleteBounty(pubkey string, created string) (Bounty, error)
DeleteBounty(pubkey string, created string) (NewBounty, error)
GetBountyByCreated(created uint) (NewBounty, error)
GetBounty(id uint) NewBounty
UpdateBounty(b NewBounty) (NewBounty, error)
Expand Down
7 changes: 7 additions & 0 deletions db/structs.go
Original file line number Diff line number Diff line change
Expand Up @@ -736,6 +736,13 @@ type WithdrawBudgetRequest struct {
OrgUuid string `json:"org_uuid"`
}

// change back to WithdrawBudgetReques
type NewWithdrawBudgetRequest struct {
PaymentRequest string `json:"payment_request"`
Websocket_token string `json:"websocket_token,omitempty"`
WorkspaceUuid string `json:"workspace_uuid"`
}

type PaymentDateRange struct {
StartDate string `json:"start_date"`
EndDate string `json:"end_date"`
Expand Down
67 changes: 65 additions & 2 deletions handlers/bounty.go
Original file line number Diff line number Diff line change
Expand Up @@ -600,8 +600,6 @@ func (h *bountyHandler) BountyBudgetWithdraw(w http.ResponseWriter, r *http.Requ
body, err := io.ReadAll(r.Body)
r.Body.Close()

fmt.Println("WithdraW Request ===", request)

err = json.Unmarshal(body, &request)
if err != nil {
w.WriteHeader(http.StatusNotAcceptable)
Expand Down Expand Up @@ -649,6 +647,71 @@ func (h *bountyHandler) BountyBudgetWithdraw(w http.ResponseWriter, r *http.Requ
m.Unlock()
}

// Todo: change back to NewBountyBudgetWithdraw
func (h *bountyHandler) NewBountyBudgetWithdraw(w http.ResponseWriter, r *http.Request) {
var m sync.Mutex
m.Lock()

ctx := r.Context()
pubKeyFromAuth, _ := ctx.Value(auth.ContextKey).(string)

if pubKeyFromAuth == "" {
fmt.Println("no pubkey from auth")
w.WriteHeader(http.StatusUnauthorized)
return
}

request := db.NewWithdrawBudgetRequest{}
body, err := io.ReadAll(r.Body)
r.Body.Close()

err = json.Unmarshal(body, &request)
if err != nil {
w.WriteHeader(http.StatusNotAcceptable)
return
}

// check if user is the admin of the workspace
// or has a withdraw bounty budget role
hasRole := h.userHasAccess(pubKeyFromAuth, request.WorkspaceUuid, db.WithdrawBudget)
if !hasRole {
w.WriteHeader(http.StatusUnauthorized)
errMsg := formatPayError("You don't have appropriate permissions to withdraw bounty budget")
json.NewEncoder(w).Encode(errMsg)
return
}

amount := utils.GetInvoiceAmount(request.PaymentRequest)

if err == nil && amount > 0 {
// check if the workspace bounty balance
// is greater than the amount
orgBudget := h.db.GetWorkspaceBudget(request.WorkspaceUuid)
if amount > orgBudget.TotalBudget {
w.WriteHeader(http.StatusForbidden)
errMsg := formatPayError("Workspace budget is not enough to withdraw the amount")
json.NewEncoder(w).Encode(errMsg)
return
}
paymentSuccess, paymentError := h.PayLightningInvoice(request.PaymentRequest)
if paymentSuccess.Success {
// withdraw amount from workspace budget
h.db.WithdrawBudget(pubKeyFromAuth, request.WorkspaceUuid, amount)
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(paymentSuccess)
} else {
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(paymentError)
}
} else {
w.WriteHeader(http.StatusForbidden)
errMsg := formatPayError("Could not pay lightning invoice")
json.NewEncoder(w).Encode(errMsg)
}

m.Unlock()
}

func formatPayError(errorMsg string) db.InvoicePayError {
return db.InvoicePayError{
Success: false,
Expand Down
56 changes: 30 additions & 26 deletions handlers/bounty_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,7 @@ func TestCreateOrEditBounty(t *testing.T) {
Title: "first bounty",
Description: "first bounty description",
WorkspaceUuid: "work-1",
OrgUuid: "org-1",
OwnerID: "test-key",
}
mockDb.On("UpdateBountyNullColumn", mock.AnythingOfType("db.NewBounty"), "assignee").Return(db.Bounty{Assignee: "test-key"})
Expand Down Expand Up @@ -446,7 +447,7 @@ func TestDeleteBounty(t *testing.T) {
t.Run("should return error if failed to delete from db", func(t *testing.T) {
rr := httptest.NewRecorder()
handler := http.HandlerFunc(bHandler.DeleteBounty)
mockDb.On("DeleteBounty", "pub-key", "1111").Return(db.Bounty{}, errors.New("some-error")).Once()
mockDb.On("DeleteBounty", "pub-key", "1111").Return(db.NewBounty{}, errors.New("some-error")).Once()

rctx := chi.NewRouteContext()
rctx.URLParams.Add("pubkey", "pub-key")
Expand All @@ -464,7 +465,7 @@ func TestDeleteBounty(t *testing.T) {
t.Run("should successfully delete bounty from db", func(t *testing.T) {
rr := httptest.NewRecorder()
handler := http.HandlerFunc(bHandler.DeleteBounty)
existingBounty := db.Bounty{
existingBounty := db.NewBounty{
OwnerID: "pub-key",
Created: 1111,
}
Expand All @@ -479,7 +480,7 @@ func TestDeleteBounty(t *testing.T) {
}
handler.ServeHTTP(rr, req)

var returnedBounty db.Bounty
var returnedBounty db.NewBounty
_ = json.Unmarshal(rr.Body.Bytes(), &returnedBounty)
assert.Equal(t, http.StatusOK, rr.Code)
assert.EqualValues(t, existingBounty, returnedBounty)
Expand Down Expand Up @@ -879,6 +880,7 @@ func TestGetBountyById(t *testing.T) {
Tribe: "development",
Assignee: "user1",
TicketUrl: "http://example.com/issues/1",
OrgUuid: "org-789",
WorkspaceUuid: "work-789",
Description: "This bounty is for fixing a critical bug in the payment system that causes transactions to fail under certain conditions.",
WantedType: "immediate",
Expand All @@ -904,7 +906,7 @@ func TestGetBountyById(t *testing.T) {
mockDb.On("GetBountyById", mock.Anything).Return([]db.NewBounty{bounty}, nil).Once()
mockDb.On("GetPersonByPubkey", "owner123").Return(db.Person{}).Once()
mockDb.On("GetPersonByPubkey", "user1").Return(db.Person{}).Once()
mockDb.On("GetWorkspaceByUuid", "org-789").Return(db.Workspace{}).Once()
mockDb.On("GetWorkspaceByUuid", "work-789").Return(db.Workspace{}).Once()

handler.ServeHTTP(rr, req)

Expand Down Expand Up @@ -1298,7 +1300,7 @@ func TestMakeBountyPayment(t *testing.T) {
Assignee: "assignee-1",
Paid: false,
}, nil)
mockDb.On("GetWorkspaceBudget", "org-1").Return(db.BountyBudget{
mockDb.On("GetWorkspaceBudget", "work-1").Return(db.NewBountyBudget{
TotalBudget: 500,
}, nil)

Expand Down Expand Up @@ -1335,9 +1337,9 @@ func TestMakeBountyPayment(t *testing.T) {
}

mockDb.On("GetBounty", bountyID).Return(bounty, nil)
mockDb.On("GetWorkspaceBudget", bounty.OrgUuid).Return(db.BountyBudget{TotalBudget: 2000}, nil)
mockDb.On("GetWorkspaceBudget", bounty.WorkspaceUuid).Return(db.NewBountyBudget{TotalBudget: 2000}, nil)
mockDb.On("GetPersonByPubkey", bounty.Assignee).Return(db.Person{OwnerPubKey: "assignee-1", OwnerRouteHint: "OwnerRouteHint"}, nil)
mockDb.On("AddPaymentHistory", mock.AnythingOfType("db.PaymentHistory")).Return(db.PaymentHistory{ID: 1})
mockDb.On("AddPaymentHistory", mock.AnythingOfType("db.NewPaymentHistory")).Return(db.NewPaymentHistory{ID: 1})
mockDb.On("UpdateBounty", mock.AnythingOfType("db.NewBounty")).Run(func(args mock.Arguments) {
updatedBounty := args.Get(0).(db.NewBounty)
assert.True(t, updatedBounty.Paid)
Expand Down Expand Up @@ -1384,7 +1386,7 @@ func TestMakeBountyPayment(t *testing.T) {
bHandler2.userHasAccess = mockUserHasAccessTrue

mockDb2.On("GetBounty", bountyID).Return(bounty, nil)
mockDb2.On("GetWorkspaceBudget", bounty.OrgUuid).Return(db.BountyBudget{TotalBudget: 2000}, nil)
mockDb2.On("GetWorkspaceBudget", bounty.WorkspaceUuid).Return(db.NewBountyBudget{TotalBudget: 2000}, nil)
mockDb2.On("GetPersonByPubkey", bounty.Assignee).Return(db.Person{OwnerPubKey: "assignee-1", OwnerRouteHint: "OwnerRouteHint"}, nil)

expectedUrl := fmt.Sprintf("%s/payment", config.RelayUrl)
Expand Down Expand Up @@ -1484,7 +1486,7 @@ func TestBountyBudgetWithdraw(t *testing.T) {
bHandler := NewBountyHandler(mockHttpClient, mockDb)
bHandler.userHasAccess = mockUserHasAccessTrue

mockDb.On("GetWorkspaceBudget", "org-1").Return(db.BountyBudget{
mockDb.On("GetWorkspaceBudget", "org-1").Return(db.NewBountyBudget{
TotalBudget: 500,
}, nil)
invoice := "lnbc15u1p3xnhl2pp5jptserfk3zk4qy42tlucycrfwxhydvlemu9pqr93tuzlv9cc7g3sdqsvfhkcap3xyhx7un8cqzpgxqzjcsp5f8c52y2stc300gl6s4xswtjpc37hrnnr3c9wvtgjfuvqmpm35evq9qyyssqy4lgd8tj637qcjp05rdpxxykjenthxftej7a2zzmwrmrl70fyj9hvj0rewhzj7jfyuwkwcg9g2jpwtk3wkjtwnkdks84hsnu8xps5vsq4gj5hs"
Expand Down Expand Up @@ -1516,7 +1518,7 @@ func TestBountyBudgetWithdraw(t *testing.T) {

paymentAmount := uint(1500)

mockDb.On("GetWorkspaceBudget", "org-1").Return(db.BountyBudget{
mockDb.On("GetWorkspaceBudget", "org-1").Return(db.NewBountyBudget{
TotalBudget: 5000,
}, nil)
mockDb.On("WithdrawBudget", "valid-key", "org-1", paymentAmount).Return(nil)
Expand Down Expand Up @@ -1553,7 +1555,7 @@ func TestBountyBudgetWithdraw(t *testing.T) {
bHandler := NewBountyHandler(mockHttpClient, mockDb)
bHandler.userHasAccess = mockUserHasAccessTrue

mockDb.On("GetWorkspaceBudget", "org-1").Return(db.BountyBudget{
mockDb.On("GetWorkspaceBudget", "org-1").Return(db.NewBountyBudget{
TotalBudget: 5000,
}, nil)
mockHttpClient.On("Do", mock.AnythingOfType("*http.Request")).Return(&http.Response{
Expand Down Expand Up @@ -1602,7 +1604,7 @@ func TestBountyBudgetWithdraw(t *testing.T) {
mockHttpClient.ExpectedCalls = nil
mockHttpClient.Calls = nil

mockDb.On("GetWorkspaceBudget", "org-1").Return(db.BountyBudget{
mockDb.On("GetWorkspaceBudget", "org-1").Return(db.NewBountyBudget{
TotalBudget: expectedFinalBudget,
}, nil)
mockDb.On("WithdrawBudget", "valid-key", "org-1", paymentAmount).Return(nil)
Expand Down Expand Up @@ -1733,16 +1735,18 @@ func TestPollInvoice(t *testing.T) {
}, nil).Once()

bountyID := uint(1)
bounty := db.Bounty{
ID: bountyID,
OrgUuid: "org-1",
Assignee: "assignee-1",
Price: uint(1000),
bounty := db.NewBounty{
ID: bountyID,
WorkspaceUuid: "work-1",
OrgUuid: "org-1",
Assignee: "assignee-1",
Price: uint(1000),
}

now := time.Now()
expectedBounty := db.Bounty{
expectedBounty := db.NewBounty{
ID: bountyID,
WorkspaceUuid: "work-1",
OrgUuid: "org-1",
Assignee: "assignee-1",
Price: uint(1000),
Expand All @@ -1751,15 +1755,15 @@ func TestPollInvoice(t *testing.T) {
CompletionDate: &now,
}

mockDb.On("GetInvoice", "1").Return(db.InvoiceList{Type: "KEYSEND"})
mockDb.On("GetInvoice", "1").Return(db.NewInvoiceList{Type: "KEYSEND"})
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("GetInvoice", "1").Return(db.NewInvoiceList{Status: false})
mockDb.On("GetBountyByCreated", uint(1234)).Return(bounty, nil)
mockDb.On("UpdateBounty", mock.AnythingOfType("db.NewBounty")).Run(func(args mock.Arguments) {
updatedBounty := args.Get(0).(db.Bounty)
updatedBounty := args.Get(0).(db.NewBounty)
assert.True(t, updatedBounty.Paid)
}).Return(expectedBounty, nil).Once()
mockDb.On("UpdateInvoice", "1").Return(db.InvoiceList{}).Once()
mockDb.On("UpdateInvoice", "1").Return(db.NewInvoiceList{}).Once()

expectedPaymentUrl := fmt.Sprintf("%s/payment", config.RelayUrl)
expectedPaymentBody := `{"amount": 1000, "destination_key": "UserPubkey", "route_hint": "RouteHint", "text": "memotext added for notification"}`
Expand Down Expand Up @@ -1804,11 +1808,11 @@ func TestPollInvoice(t *testing.T) {
Body: r,
}, nil).Once()

mockDb.On("GetInvoice", "1").Return(db.InvoiceList{Type: "BUDGET"})
mockDb.On("GetInvoice", "1").Return(db.NewInvoiceList{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()
mockDb.On("GetInvoice", "1").Return(db.NewInvoiceList{Status: false})
mockDb.On("AddAndUpdateBudget", mock.Anything).Return(db.NewPaymentHistory{})
mockDb.On("UpdateInvoice", "1").Return(db.NewInvoiceList{}).Once()

ro := chi.NewRouter()
ro.Post("/poll/invoice/{paymentRequest}", bHandler.PollInvoice)
Expand Down
23 changes: 12 additions & 11 deletions handlers/tribes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@ import (
"bytes"
"context"
"encoding/json"
"github.com/stakwork/sphinx-tribes/config"
"net/http"
"net/http/httptest"
"strings"
"testing"

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

"github.com/go-chi/chi"
"github.com/lib/pq"
"github.com/stakwork/sphinx-tribes/auth"
Expand Down Expand Up @@ -636,8 +637,8 @@ func TestGenerateBudgetInvoice(t *testing.T) {

t.Run("Should mock a call to relay /invoices with the correct body", func(t *testing.T) {

mockDb.On("AddPaymentHistory", mock.AnythingOfType("db.PaymentHistory")).Return(db.PaymentHistory{}, nil)
mockDb.On("AddInvoice", mock.AnythingOfType("db.InvoiceList")).Return(db.InvoiceList{}, nil)
mockDb.On("AddPaymentHistory", mock.AnythingOfType("db.NewPaymentHistory")).Return(db.NewPaymentHistory{}, nil)
mockDb.On("AddInvoice", mock.AnythingOfType("db.NewInvoiceList")).Return(db.NewInvoiceList{}, nil)

ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

Expand Down Expand Up @@ -672,8 +673,8 @@ func TestGenerateBudgetInvoice(t *testing.T) {

userAmount := float64(1000)

mockDb.On("AddPaymentHistory", mock.AnythingOfType("db.PaymentHistory")).Return(db.PaymentHistory{}, nil)
mockDb.On("AddInvoice", mock.AnythingOfType("db.InvoiceList")).Return(db.InvoiceList{}, nil)
mockDb.On("AddPaymentHistory", mock.AnythingOfType("db.NewPaymentHistory")).Return(db.NewPaymentHistory{}, nil)
mockDb.On("AddInvoice", mock.AnythingOfType("db.NewInvoiceList")).Return(db.NewInvoiceList{}, nil)

ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
var body map[string]interface{}
Expand Down Expand Up @@ -703,11 +704,11 @@ func TestGenerateBudgetInvoice(t *testing.T) {
})

t.Run("Should add payments to the payment history and invoice to the invoice list upon successful relay call", func(t *testing.T) {
expectedPaymentHistory := db.PaymentHistory{Amount: userAmount}
expectedInvoice := db.InvoiceList{PaymentRequest: invoiceResponse.Response.Invoice}
expectedPaymentHistory := db.NewPaymentHistory{Amount: userAmount}
expectedInvoice := db.NewInvoiceList{PaymentRequest: invoiceResponse.Response.Invoice}

mockDb.On("AddPaymentHistory", mock.AnythingOfType("db.PaymentHistory")).Return(expectedPaymentHistory, nil)
mockDb.On("AddInvoice", mock.AnythingOfType("db.InvoiceList")).Return(expectedInvoice, nil)
mockDb.On("AddPaymentHistory", mock.AnythingOfType("db.NewPaymentHistory")).Return(expectedPaymentHistory, nil)
mockDb.On("AddInvoice", mock.AnythingOfType("db.NewInvoiceList")).Return(expectedInvoice, nil)

ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
Expand All @@ -734,7 +735,7 @@ func TestGenerateBudgetInvoice(t *testing.T) {
assert.True(t, response.Succcess, "Invoice generation should be successful")
assert.Equal(t, "example_invoice", response.Response.Invoice, "The invoice in the response should match the mock")

mockDb.AssertCalled(t, "AddPaymentHistory", mock.AnythingOfType("db.PaymentHistory"))
mockDb.AssertCalled(t, "AddInvoice", mock.AnythingOfType("db.InvoiceList"))
mockDb.AssertCalled(t, "AddPaymentHistory", mock.AnythingOfType("db.NewPaymentHistory"))
mockDb.AssertCalled(t, "AddInvoice", mock.AnythingOfType("db.NewInvoiceList"))
})
}
Loading

0 comments on commit ac293a5

Please sign in to comment.