mirror of
https://github.com/marcusDenslow/terminalShop.git
synced 2026-10-25 02:52:20 +02:00
various error checks and formatting
This commit is contained in:
@@ -76,7 +76,7 @@ func (h *AddressHandler) CreateAddress(w http.ResponseWriter, r *http.Request) {
|
||||
switch req.Country {
|
||||
case "US":
|
||||
if h.shippoKey == "" {
|
||||
utils.RespondError(w, http.StatusBadRequest, "CONFIG_ERROR", "shippo not configured for US address validation", nil)
|
||||
utils.RespondError(w, http.StatusInternalServerError, "CONFIG_ERROR", "shippo not configured for US address validation", nil)
|
||||
return
|
||||
}
|
||||
client := shippo.NewClient(h.shippoKey)
|
||||
@@ -166,12 +166,14 @@ func (h *AddressHandler) DeleteAddress(w http.ResponseWriter, r *http.Request) {
|
||||
var address models.Address
|
||||
|
||||
if err := db.Where("id = ? AND user_id = ?", id, userID).First(&address).Error; err != nil {
|
||||
utils.RespondError(w, http.StatusNotFound, "ADDRESS NOT FOUND", "address not found", nil)
|
||||
utils.RespondError(w, http.StatusNotFound, "ADDRESS_NOT_FOUND", "address not found", nil)
|
||||
return
|
||||
}
|
||||
|
||||
// ownership is guaranteed by the WHERE clause above
|
||||
db.Delete(&address)
|
||||
if err := db.Delete(&address).Error; err != nil {
|
||||
utils.RespondError(w, http.StatusInternalServerError, "INTERNAL_ERROR", "failed to delete address", nil)
|
||||
return
|
||||
}
|
||||
|
||||
utils.RespondSuccess(w, http.StatusOK, map[string]interface{}{
|
||||
"message": "address successfully deleted",
|
||||
@@ -197,10 +199,16 @@ func (h *AddressHandler) SetDefaultAddress(w http.ResponseWriter, r *http.Reques
|
||||
return
|
||||
}
|
||||
|
||||
db.Model(&models.Address{}).Where("user_id = ?", userID).Update("is_default", false)
|
||||
if err := db.Model(&models.Address{}).Where("user_id = ?", userID).Update("is_default", false).Error; err != nil {
|
||||
utils.RespondError(w, http.StatusInternalServerError, "INTERNAL_ERROR", "failed to update address", nil)
|
||||
return
|
||||
}
|
||||
|
||||
address.IsDefault = true
|
||||
db.Save(&address)
|
||||
if err := db.Save(&address).Error; err != nil {
|
||||
utils.RespondError(w, http.StatusInternalServerError, "INTERNAL_ERROR", "failed to save address", nil)
|
||||
return
|
||||
}
|
||||
|
||||
utils.RespondSuccess(w, http.StatusOK, map[string]interface{}{
|
||||
"address": address,
|
||||
|
||||
@@ -158,4 +158,3 @@ func TestGetAddressesWithData(t *testing.T) {
|
||||
t.Errorf("expected 2 addresses, got: %d", len(resp.Data.Addresses))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ func (h *AuthHandler) GetToken(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
} else if err != nil {
|
||||
utils.RespondError(w, http.StatusInternalServerError, "DATABASE_ERROR", "database error", nil)
|
||||
utils.RespondError(w, http.StatusInternalServerError, "DATABASE_ERROR", "failed to look up user", nil)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -89,7 +89,13 @@ func (h *AuthHandler) GetToken(w http.ResponseWriter, r *http.Request) {
|
||||
Fingerprint: req.Fingerprint,
|
||||
PublicKey: req.SSHPublicKey,
|
||||
}
|
||||
db.Where(models.SSHKey{Fingerprint: req.Fingerprint}).FirstOrCreate(&sshKey)
|
||||
if err := db.Where(models.SSHKey{Fingerprint: req.Fingerprint}).FirstOrCreate(&sshKey).Error; err != nil {
|
||||
// we specifically want to block users whos ssh key failed to save. this is to prevent downstream errors which i dont want to deal with now
|
||||
// !TODO add a way to just log the errror and app continue without trying to save carts, cards and addresses. this way the users wouldnt
|
||||
// just be kicked, they would shop normally but on their next login they would need to add all their data again.
|
||||
utils.RespondError(w, http.StatusInternalServerError, "DATABASE_ERROR", "failed to save ssh key", nil)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
token, err := h.jwtManager.GenerateToken(user.ID, user.Email, user.Name)
|
||||
|
||||
@@ -119,10 +119,16 @@ func (h *CardHandler) SetDefaultCard(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
db.Model(&models.Card{}).Where("user_id = ?", userID).Update("is_default", false)
|
||||
if err := db.Model(&models.Card{}).Where("user_id = ?", userID).Update("is_default", false).Error; err != nil {
|
||||
utils.RespondError(w, http.StatusInternalServerError, "INTERNAL_ERROR", "failed to update card", nil)
|
||||
return
|
||||
}
|
||||
|
||||
card.IsDefault = true
|
||||
db.Save(&card)
|
||||
if err := db.Save(&card).Error; err != nil {
|
||||
utils.RespondError(w, http.StatusInternalServerError, "INTERNAL_ERROR", "failed to save card", nil)
|
||||
return
|
||||
}
|
||||
|
||||
utils.RespondSuccess(w, http.StatusOK, map[string]interface{}{
|
||||
"card": card,
|
||||
@@ -285,7 +291,10 @@ func (h *CardHandler) DeleteCard(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// Clear the card from any cart that references it.
|
||||
cardID := uint(id)
|
||||
db.Model(&models.Cart{}).Where("card_id = ? AND user_id = ?", cardID, userID).Update("card_id", nil)
|
||||
if err := db.Model(&models.Cart{}).Where("card_id = ? AND user_id = ?", cardID, userID).Update("card_id", nil).Error; err != nil {
|
||||
utils.RespondError(w, http.StatusInternalServerError, "INTERNAL_ERROR", "failed to clear card from cart", nil)
|
||||
return
|
||||
}
|
||||
|
||||
// Detach from Stripe (best-effort; don't block deletion on Stripe errors).
|
||||
if len(card.StripePaymentID) >= 3 && card.StripePaymentID[:3] == "pm_" {
|
||||
@@ -294,7 +303,10 @@ func (h *CardHandler) DeleteCard(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// Soft-delete the local record.
|
||||
db.Delete(&card)
|
||||
if err := db.Delete(&card).Error; err != nil {
|
||||
utils.RespondError(w, http.StatusInternalServerError, "INTERNAL_ERROR", "failed to delete card", nil)
|
||||
return
|
||||
}
|
||||
|
||||
audit.CardDeleted(userID, card.ID)
|
||||
|
||||
@@ -325,6 +337,8 @@ func ensureStripeCustomer(gdb *gorm.DB, user *models.User) error {
|
||||
return err
|
||||
}
|
||||
user.StripeCustomerID = cust.ID
|
||||
gdb.Save(user)
|
||||
if err := gdb.Save(user).Error; err != nil {
|
||||
return fmt.Errorf("Failed to save stripe customer: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -5,10 +5,10 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"gorm.io/gorm"
|
||||
"github.com/stripe/stripe-go/v78"
|
||||
"github.com/stripe/stripe-go/v78/paymentintent"
|
||||
"github.com/stripe/stripe-go/v78/paymentmethod"
|
||||
"gorm.io/gorm"
|
||||
|
||||
"terminalShop/api/middleware"
|
||||
"terminalShop/pkg/audit"
|
||||
@@ -117,7 +117,10 @@ func (h *CartHandler) SetItem(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
if req.Quantity <= 0 {
|
||||
db.Where("cart_id = ? AND coffee_id = ?", cart.ID, req.CoffeeID).Delete(&models.CartItem{})
|
||||
if err := db.Where("cart_id = ? AND coffee_id = ?", cart.ID, req.CoffeeID).Delete(&models.CartItem{}).Error; err != nil {
|
||||
utils.RespondError(w, http.StatusInternalServerError, "INTERNAL_ERROR", "failed to delete cart item", nil)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
var item models.CartItem
|
||||
result := db.Where("cart_id = ? AND coffee_id = ?", cart.ID, req.CoffeeID).First(&item)
|
||||
@@ -127,9 +130,15 @@ func (h *CartHandler) SetItem(w http.ResponseWriter, r *http.Request) {
|
||||
CoffeeID: req.CoffeeID,
|
||||
Quantity: req.Quantity,
|
||||
}
|
||||
db.Create(&item)
|
||||
if err := db.Create(&item).Error; err != nil {
|
||||
utils.RespondError(w, http.StatusInternalServerError, "INTERNAL_ERROR", "failed to create item", nil)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
db.Model(&item).Update("quantity", req.Quantity)
|
||||
if err := db.Model(&item).Update("quantity", req.Quantity).Error; err != nil {
|
||||
utils.RespondError(w, http.StatusInternalServerError, "INTERNAL_ERROR", "failed to update quantity", nil)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,7 +173,10 @@ func (h *CartHandler) SetAddress(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
db.Model(cart).Update("address_id", req.AddressID)
|
||||
if err := db.Model(cart).Update("address_id", req.AddressID).Error; err != nil {
|
||||
utils.RespondError(w, http.StatusInternalServerError, "INTERNAL_ERROR", "failed to set address", nil)
|
||||
return
|
||||
}
|
||||
|
||||
utils.RespondSuccess(w, http.StatusOK, map[string]interface{}{
|
||||
"message": "address set",
|
||||
@@ -197,7 +209,10 @@ func (h *CartHandler) SetCard(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
db.Model(cart).Update("card_id", req.CardID)
|
||||
if err := db.Model(cart).Update("card_id", req.CardID).Error; err != nil {
|
||||
utils.RespondError(w, http.StatusInternalServerError, "INTERNAL_ERROR", "failed to set card", nil)
|
||||
return
|
||||
}
|
||||
|
||||
utils.RespondSuccess(w, http.StatusOK, map[string]interface{}{
|
||||
"message": "card set",
|
||||
@@ -214,7 +229,10 @@ func (h *CartHandler) ClearCart(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
db.Where("cart_id = ?", cart.ID).Delete(&models.CartItem{})
|
||||
if err := db.Where("cart_id = ?", cart.ID).Delete(&models.CartItem{}).Error; err != nil {
|
||||
utils.RespondError(w, http.StatusInternalServerError, "INTERNAL_ERROR", "failed to delete cart item", nil)
|
||||
return
|
||||
}
|
||||
|
||||
utils.RespondSuccess(w, http.StatusOK, map[string]interface{}{
|
||||
"message": "cart cleared",
|
||||
@@ -297,7 +315,10 @@ func (h *CartHandler) ConvertCart(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
paymentMethodID = pm.ID
|
||||
card.StripePaymentID = pm.ID
|
||||
db.Save(&card)
|
||||
if err := db.Save(&card).Error; err != nil {
|
||||
utils.RespondError(w, http.StatusInternalServerError, "INTERNAL_ERROR", "failed to save card", nil)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
var subtotal int
|
||||
@@ -427,10 +448,12 @@ func (h *CartHandler) ConvertCart(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
audit.OrderPaid(userID, order.ID, total, pi.ID)
|
||||
|
||||
db.Preload("Items").First(&order, order.ID)
|
||||
if err := db.Preload("Items").First(&order, order.ID).Error; err != nil {
|
||||
utils.RespondError(w, http.StatusInternalServerError, "INTERNAL_ERROR", "failed to preload items", nil)
|
||||
return
|
||||
}
|
||||
|
||||
utils.RespondSuccess(w, http.StatusOK, map[string]interface{}{
|
||||
"order": order,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -57,4 +57,3 @@ func (h *ProductHandler) GetProduct(w http.ResponseWriter, r *http.Request) {
|
||||
"product": product,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -23,10 +23,7 @@ func (h *SSHKeyHandler) GetSSHKeys(w http.ResponseWriter, r *http.Request) {
|
||||
userID := middleware.UserIDFromContext(r.Context())
|
||||
|
||||
var keys []models.SSHKey
|
||||
if err := db.Where("user_id = ?", userID).Order("created_at ASC").Find(&keys).Error; err != nil {
|
||||
utils.RespondError(w, http.StatusInternalServerError, "DATABASE_ERROR", "failed to fetch ssh keys", nil)
|
||||
return
|
||||
}
|
||||
db.Where("user_id = ?", userID).Order("created_at ASC").Find(&keys)
|
||||
|
||||
utils.RespondSuccess(w, http.StatusOK, map[string]interface{}{
|
||||
"ssh_keys": keys,
|
||||
@@ -36,7 +33,7 @@ func (h *SSHKeyHandler) GetSSHKeys(w http.ResponseWriter, r *http.Request) {
|
||||
// DeleteSSHKeys removes one of the users ssh keys by ID
|
||||
func (h *SSHKeyHandler) DeleteSSHKeys(w http.ResponseWriter, r *http.Request) {
|
||||
db := database.GetDB()
|
||||
userId := middleware.UserIDFromContext(r.Context())
|
||||
userID := middleware.UserIDFromContext(r.Context())
|
||||
|
||||
idStr := chi.URLParam(r, "id")
|
||||
id, err := strconv.ParseUint(idStr, 10, 32)
|
||||
@@ -46,11 +43,14 @@ func (h *SSHKeyHandler) DeleteSSHKeys(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
var key models.SSHKey
|
||||
if err := db.Where("id = ? AND user_id = ?", id, userId).First(&key).Error; err != nil {
|
||||
if err := db.Where("id = ? AND user_id = ?", id, userID).First(&key).Error; err != nil {
|
||||
utils.RespondError(w, http.StatusNotFound, "SSH_KEY_NOT_FOUND", "ssh key not found", nil)
|
||||
return
|
||||
}
|
||||
db.Delete(&key)
|
||||
if err := db.Delete(&key).Error; err != nil {
|
||||
utils.RespondError(w, http.StatusInternalServerError, "INTERNAL_ERROR", "failed to delete ssh key", nil)
|
||||
return
|
||||
}
|
||||
|
||||
utils.RespondSuccess(w, http.StatusOK, map[string]interface{}{
|
||||
"message": "ssh key deleted",
|
||||
|
||||
@@ -2,6 +2,7 @@ package handlers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
@@ -128,7 +129,9 @@ func (h *WebhookHandler) handlePaymentIntentSucceeded(event stripe.Event) {
|
||||
if err := tx.Where("user_id = ?", order.UserID).First(&cart).Error; err != nil {
|
||||
return nil // Cart already gone.
|
||||
}
|
||||
tx.Where("cart_id = ?", cart.ID).Delete(&models.CartItem{})
|
||||
if err := tx.Where("cart_id = ?", cart.ID).Delete(&models.CartItem{}).Error; err != nil {
|
||||
return fmt.Errorf("failed to delete cart item: %w", err)
|
||||
}
|
||||
return tx.Model(&cart).Updates(map[string]interface{}{
|
||||
"address_id": nil,
|
||||
"card_id": nil,
|
||||
@@ -156,8 +159,10 @@ func (h *WebhookHandler) handlePaymentIntentFailed(event stripe.Event) {
|
||||
}
|
||||
|
||||
db := database.GetDB()
|
||||
db.Model(&models.Order{}).Where("id = ? AND status = ?", orderIDStr, models.OrderStatusPending).
|
||||
Update("status", models.OrderStatusFailed)
|
||||
if err := db.Model(&models.Order{}).Where("id = ? AND status = ?", orderIDStr, models.OrderStatusPending).
|
||||
Update("status", models.OrderStatusFailed).Error; err != nil {
|
||||
log.Printf("[webhook] failed to mark order %s as failed: %v", orderIDStr, err)
|
||||
}
|
||||
|
||||
errMsg := "unknown"
|
||||
if pi.LastPaymentError != nil {
|
||||
|
||||
@@ -117,7 +117,7 @@ func SetupRoutes(
|
||||
})
|
||||
|
||||
// SSH Keys
|
||||
r.Route("/ssh-keys", func(r chi.Router){
|
||||
r.Route("/ssh-keys", func(r chi.Router) {
|
||||
// GET doesnt need id because it gets every ssh key
|
||||
r.Get("/", sshKeyHandler.GetSSHKeys)
|
||||
// Delete needs an id to delete only one key
|
||||
|
||||
Reference in New Issue
Block a user