From 6c29afababf19141ff9c166f58247c208948680a Mon Sep 17 00:00:00 2001 From: elraphty Date: Tue, 22 Oct 2024 15:01:11 +0100 Subject: [PATCH 1/6] fixed payment history failed payments --- db/workspaces.go | 11 ----------- handlers/bounty.go | 4 +++- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/db/workspaces.go b/db/workspaces.go index 4b352a1a7..5b322d6d9 100644 --- a/db/workspaces.go +++ b/db/workspaces.go @@ -440,17 +440,6 @@ func (db database) WithdrawBudget(sender_pubkey string, workspace_uuid string, a func (db database) AddPaymentHistory(payment NewPaymentHistory) NewPaymentHistory { db.db.Create(&payment) - // get Workspace budget and subtract payment from total budget - WorkspaceBudget := db.GetWorkspaceBudget(payment.WorkspaceUuid) - totalBudget := WorkspaceBudget.TotalBudget - - // deduct amount if it's a bounty payment - if payment.PaymentType == "payment" { - WorkspaceBudget.TotalBudget = totalBudget - payment.Amount - } - - db.UpdateWorkspaceBudget(WorkspaceBudget) - return payment } diff --git a/handlers/bounty.go b/handlers/bounty.go index 4216a61d5..fc6aa0430 100644 --- a/handlers/bounty.go +++ b/handlers/bounty.go @@ -637,7 +637,7 @@ func (h *bountyHandler) MakeBountyPayment(w http.ResponseWriter, r *http.Request BountyId: id, Created: &now, Updated: &now, - Status: true, + Status: false, PaymentType: "payment", Tag: v2KeysendRes.Tag, PaymentStatus: v2KeysendRes.Status, @@ -649,6 +649,7 @@ func (h *bountyHandler) MakeBountyPayment(w http.ResponseWriter, r *http.Request bounty.PaidDate = &now bounty.Completed = true bounty.CompletionDate = &now + paymentHistory.Status = true h.db.ProcessBountyPayment(paymentHistory, bounty) @@ -662,6 +663,7 @@ func (h *bountyHandler) MakeBountyPayment(w http.ResponseWriter, r *http.Request } else { // Send payment status log.Printf("[bounty] V2 Status Was not completed: %s", v2KeysendRes.Status) + paymentHistory.Status = false h.db.AddPaymentHistory(paymentHistory) From c5b4577c6938e99db9aa1508bfb59fa2d57d3eea Mon Sep 17 00:00:00 2001 From: elraphty Date: Tue, 22 Oct 2024 16:18:22 +0100 Subject: [PATCH 2/6] added payment pending flag --- db/structs.go | 2 ++ handlers/bounty.go | 20 +++++++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/db/structs.go b/db/structs.go index 4491fbd88..ff45c4e3e 100644 --- a/db/structs.go +++ b/db/structs.go @@ -390,6 +390,7 @@ type Bounty struct { CodingLanguages pq.StringArray `gorm:"type:text[];not null default:'[]'" json:"coding_languages"` PhaseUuid *string `json:"phase_uuid"` PhasePriority *int `json:"phase_priority"` + PaymentPending bool `gorm:"default:false" json:"payment_pending"` } // Todo: Change back to Bounty @@ -427,6 +428,7 @@ type NewBounty struct { CodingLanguages pq.StringArray `gorm:"type:text[];not null default:'[]'" json:"coding_languages"` PhaseUuid string `json:"phase_uuid"` PhasePriority int `json:"phase_priority"` + PaymentPending bool `gorm:"default:false" json:"payment_pending"` } type BountyOwners struct { diff --git a/handlers/bounty.go b/handlers/bounty.go index fc6aa0430..15b7ad509 100644 --- a/handlers/bounty.go +++ b/handlers/bounty.go @@ -656,6 +656,25 @@ func (h *bountyHandler) MakeBountyPayment(w http.ResponseWriter, r *http.Request msg["msg"] = "keysend_success" msg["invoice"] = "" + socket, err := h.getSocketConnections(request.Websocket_token) + if err == nil { + socket.Conn.WriteJSON(msg) + } + } else if v2KeysendRes.Status == db.PaymentPending { + // Send payment status + log.Printf("[bounty] V2 Status is pending: %s", v2KeysendRes.Status) + bounty.Paid = false + bounty.PaymentPending = true + bounty.PaidDate = &now + bounty.Completed = true + bounty.CompletionDate = &now + paymentHistory.Status = true + + h.db.ProcessBountyPayment(paymentHistory, bounty) + + msg["msg"] = "keysend_pending" + msg["invoice"] = "" + socket, err := h.getSocketConnections(request.Websocket_token) if err == nil { socket.Conn.WriteJSON(msg) @@ -663,7 +682,6 @@ func (h *bountyHandler) MakeBountyPayment(w http.ResponseWriter, r *http.Request } else { // Send payment status log.Printf("[bounty] V2 Status Was not completed: %s", v2KeysendRes.Status) - paymentHistory.Status = false h.db.AddPaymentHistory(paymentHistory) From c060a551d398b3577e1162849c175203fd279a3c Mon Sep 17 00:00:00 2001 From: elraphty Date: Tue, 22 Oct 2024 20:38:18 +0100 Subject: [PATCH 3/6] added Payment failed column --- db/structs.go | 4 ++++ db/structsv2.go | 1 + handlers/bounty.go | 27 ++++++++++++++++++++++++++- routes/bounty.go | 1 - 4 files changed, 31 insertions(+), 2 deletions(-) diff --git a/db/structs.go b/db/structs.go index ff45c4e3e..4e37fc974 100644 --- a/db/structs.go +++ b/db/structs.go @@ -391,6 +391,7 @@ type Bounty struct { PhaseUuid *string `json:"phase_uuid"` PhasePriority *int `json:"phase_priority"` PaymentPending bool `gorm:"default:false" json:"payment_pending"` + PaymentFailed bool `gorm:"default:false" json:"payment_failed"` } // Todo: Change back to Bounty @@ -429,6 +430,7 @@ type NewBounty struct { PhaseUuid string `json:"phase_uuid"` PhasePriority int `json:"phase_priority"` PaymentPending bool `gorm:"default:false" json:"payment_pending"` + PaymentFailed bool `gorm:"default:false" json:"payment_failed"` } type BountyOwners struct { @@ -720,6 +722,7 @@ type PaymentHistory struct { ReceiverPubKey string `json:"receiver_pubkey"` Tag string `json:"tag,omitempty"` PaymentStatus string `json:"payment_status,omitempty"` + Error string `json:"error,omitempty"` Created *time.Time `json:"created"` Updated *time.Time `json:"updated"` Status bool `json:"status"` @@ -736,6 +739,7 @@ type NewPaymentHistory struct { ReceiverPubKey string `json:"receiver_pubkey"` Tag string `json:"tag,omitempty"` PaymentStatus string `json:"payment_status,omitempty"` + Error string `json:"error,omitempty"` Created *time.Time `json:"created"` Updated *time.Time `json:"updated"` Status bool `json:"status"` diff --git a/db/structsv2.go b/db/structsv2.go index f6df64bba..c0ba2f0e5 100644 --- a/db/structsv2.go +++ b/db/structsv2.go @@ -29,6 +29,7 @@ type V2SendOnionRes struct { Tag string `json:"tag"` Preimage string `json:"preimage"` PaymentHash string `json:"payment_hash"` + Message string `json:"message,omitempty"` } type V2PayInvoiceBody struct { diff --git a/handlers/bounty.go b/handlers/bounty.go index 15b7ad509..7207e73d7 100644 --- a/handlers/bounty.go +++ b/handlers/bounty.go @@ -256,13 +256,22 @@ func (h *bountyHandler) CreateOrEditBounty(w http.ResponseWriter, r *http.Reques // get bounty from DB dbBounty := h.db.GetBounty(bounty.ID) + // check if the bounty has a pending payment + if dbBounty.PaymentPending { + msg := "You cannot update a bounty with a pending payment" + fmt.Println("[bounty]", msg) + w.WriteHeader(http.StatusBadRequest) + json.NewEncoder(w).Encode(msg) + return + } + // trying to update // check if bounty belongs to user if pubKeyFromAuth != dbBounty.OwnerID { if bounty.WorkspaceUuid != "" { hasBountyRoles := h.userHasManageBountyRoles(pubKeyFromAuth, bounty.WorkspaceUuid) if !hasBountyRoles { - msg := "You don't have a=the right permission ton update bounty" + msg := "You don't have the right permission ton update bounty" fmt.Println("[bounty]", msg) w.WriteHeader(http.StatusBadRequest) json.NewEncoder(w).Encode(msg) @@ -369,6 +378,7 @@ func UpdatePaymentStatus(w http.ResponseWriter, r *http.Request) { bounty.Completed = true bounty.CompletionDate = &now bounty.MarkAsPaidDate = &now + if bounty.PaidDate == nil { bounty.PaidDate = &now } @@ -531,6 +541,13 @@ func (h *bountyHandler) MakeBountyPayment(w http.ResponseWriter, r *http.Request return } + if bounty.PaymentPending { + w.WriteHeader(http.StatusBadRequest) + json.NewEncoder(w).Encode("Bounty payemnt is pending, cannot retry payment") + h.m.Unlock() + return + } + // check if user is the admin of the workspace // or has a pay bounty role hasRole := h.userHasAccess(pubKeyFromAuth, bounty.WorkspaceUuid, db.PayBounty) @@ -683,6 +700,13 @@ func (h *bountyHandler) MakeBountyPayment(w http.ResponseWriter, r *http.Request // Send payment status log.Printf("[bounty] V2 Status Was not completed: %s", v2KeysendRes.Status) + bounty.Paid = false + bounty.PaymentPending = false + bounty.PaymentFailed = true + + // set the error message + paymentHistory.Error = v2KeysendRes.Message + h.db.AddPaymentHistory(paymentHistory) log.Println("Keysend payment not completed ===") @@ -898,6 +922,7 @@ func (h *bountyHandler) UpdateBountyPaymentStatus(w http.ResponseWriter, r *http now := time.Now() bounty.Paid = true + bounty.PaymentPending = false bounty.PaidDate = &now bounty.Completed = true bounty.CompletionDate = &now diff --git a/routes/bounty.go b/routes/bounty.go index d6d83d2e0..74f969d52 100644 --- a/routes/bounty.go +++ b/routes/bounty.go @@ -38,7 +38,6 @@ func BountyRoutes() chi.Router { r.Post("/pay/{id}", bountyHandler.MakeBountyPayment) r.Get("/payment/status/{id}", bountyHandler.GetBountyPaymentStatus) r.Put("/payment/status/{id}", bountyHandler.UpdateBountyPaymentStatus) - r.Get("/payment/status/{id}", bountyHandler.GetBountyPaymentStatus) r.Post("/", bountyHandler.CreateOrEditBounty) r.Delete("/assignee", handlers.DeleteBountyAssignee) From c6c1c8c123b7f22ce8b129923db5e95f9a20defa Mon Sep 17 00:00:00 2001 From: elraphty Date: Tue, 22 Oct 2024 20:43:55 +0100 Subject: [PATCH 4/6] added Payemnt Pending, and Failed to Generate Bounty Response --- handlers/bounty.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/handlers/bounty.go b/handlers/bounty.go index 7207e73d7..9d5806061 100644 --- a/handlers/bounty.go +++ b/handlers/bounty.go @@ -446,6 +446,8 @@ func (h *bountyHandler) GenerateBountyResponse(bounties []db.NewBounty) []db.Bou Updated: bounty.Updated, CodingLanguages: bounty.CodingLanguages, Completed: bounty.Completed, + PaymentPending: bounty.PaymentPending, + PaymentFailed: bounty.PaymentFailed, }, Assignee: db.Person{ ID: assignee.ID, From 9cffbae122ff6dae85509d6a379fc1b624573ff6 Mon Sep 17 00:00:00 2001 From: elraphty Date: Tue, 22 Oct 2024 22:36:26 +0100 Subject: [PATCH 5/6] added pending check for other bounty updates --- handlers/bounty.go | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/handlers/bounty.go b/handlers/bounty.go index 9d5806061..09ef19331 100644 --- a/handlers/bounty.go +++ b/handlers/bounty.go @@ -369,6 +369,12 @@ func UpdatePaymentStatus(w http.ResponseWriter, r *http.Request) { created, _ := strconv.ParseUint(createdParam, 10, 32) bounty, _ := db.DB.GetBountyByCreated(uint(created)) + if bounty.PaymentPending { + w.WriteHeader(http.StatusBadGateway) + json.NewEncoder(w).Encode("Cannot update a bounty with a pending payment") + return + } + if bounty.ID != 0 && bounty.Created == int64(created) { bounty.Paid = !bounty.Paid now := time.Now() @@ -392,8 +398,14 @@ func UpdatePaymentStatus(w http.ResponseWriter, r *http.Request) { func UpdateCompletedStatus(w http.ResponseWriter, r *http.Request) { createdParam := chi.URLParam(r, "created") created, _ := strconv.ParseUint(createdParam, 10, 32) - bounty, _ := db.DB.GetBountyByCreated(uint(created)) + + if bounty.PaymentPending { + w.WriteHeader(http.StatusBadGateway) + json.NewEncoder(w).Encode("Cannot update a bounty with a pending payment") + return + } + if bounty.ID != 0 && bounty.Created == int64(created) { now := time.Now() // set bounty as completed From f03c576fa6213059c6bbd4e32cfa6d967a5e00b7 Mon Sep 17 00:00:00 2001 From: elraphty Date: Tue, 22 Oct 2024 22:49:16 +0100 Subject: [PATCH 6/6] added return and unlock to payment status conditionals --- handlers/bounty.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/handlers/bounty.go b/handlers/bounty.go index 09ef19331..422aaefec 100644 --- a/handlers/bounty.go +++ b/handlers/bounty.go @@ -691,6 +691,9 @@ func (h *bountyHandler) MakeBountyPayment(w http.ResponseWriter, r *http.Request if err == nil { socket.Conn.WriteJSON(msg) } + + h.m.Unlock() + return } else if v2KeysendRes.Status == db.PaymentPending { // Send payment status log.Printf("[bounty] V2 Status is pending: %s", v2KeysendRes.Status) @@ -710,6 +713,9 @@ func (h *bountyHandler) MakeBountyPayment(w http.ResponseWriter, r *http.Request if err == nil { socket.Conn.WriteJSON(msg) } + + h.m.Unlock() + return } else { // Send payment status log.Printf("[bounty] V2 Status Was not completed: %s", v2KeysendRes.Status) @@ -833,8 +839,6 @@ func (h *bountyHandler) MakeBountyPayment(w http.ResponseWriter, r *http.Request return } } - - h.m.Unlock() } func (h *bountyHandler) GetBountyPaymentStatus(w http.ResponseWriter, r *http.Request) {