fix(admin): replace string(rune) with strconv.Itoa and validate status param

Fix query parameter construction by using strconv.Itoa instead of string(rune('0'+argNum)). Add status filter validation against allowed values.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
2026-05-31 18:49:02 +01:00
co-authored by Sisyphus
parent 253d8785a4
commit 304a54c283
+20 -12
View File
@@ -8,6 +8,7 @@ import (
"encoding/json" "encoding/json"
"log" "log"
"net/http" "net/http"
"strconv"
"time" "time"
"github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5"
@@ -76,6 +77,13 @@ type CampaignStats struct {
// Optional query param ?status=active to filter by status // Optional query param ?status=active to filter by status
func GetDiscountCampaigns(w http.ResponseWriter, r *http.Request) { func GetDiscountCampaigns(w http.ResponseWriter, r *http.Request) {
statusFilter := r.URL.Query().Get("status") statusFilter := r.URL.Query().Get("status")
if statusFilter != "" {
validStatuses := map[string]bool{"active": true, "paused": true, "cancelled": true, "expired": true}
if !validStatuses[statusFilter] {
http.Error(w, "invalid status filter", http.StatusBadRequest)
return
}
}
var query string var query string
var rows pgx.Rows var rows pgx.Rows
@@ -407,12 +415,12 @@ func UpdateDiscountCampaign(w http.ResponseWriter, r *http.Request) {
argNum := 1 argNum := 1
if req.Name != nil { if req.Name != nil {
query += ", name = $" + string(rune('0'+argNum)) query += ", name = $" + strconv.Itoa(argNum)
args = append(args, *req.Name) args = append(args, *req.Name)
argNum++ argNum++
} }
if req.Description != nil { if req.Description != nil {
query += ", description = $" + string(rune('0'+argNum)) query += ", description = $" + strconv.Itoa(argNum)
args = append(args, *req.Description) args = append(args, *req.Description)
argNum++ argNum++
} }
@@ -421,12 +429,12 @@ func UpdateDiscountCampaign(w http.ResponseWriter, r *http.Request) {
http.Error(w, "Discount percent must be greater than 0 and less than or equal to 100", http.StatusBadRequest) http.Error(w, "Discount percent must be greater than 0 and less than or equal to 100", http.StatusBadRequest)
return return
} }
query += ", discount_percent = $" + string(rune('0'+argNum)) query += ", discount_percent = $" + strconv.Itoa(argNum)
args = append(args, *req.DiscountPercent) args = append(args, *req.DiscountPercent)
argNum++ argNum++
} }
if req.Scope != nil { if req.Scope != nil {
query += ", scope = $" + string(rune('0'+argNum)) query += ", scope = $" + strconv.Itoa(argNum)
args = append(args, *req.Scope) args = append(args, *req.Scope)
argNum++ argNum++
} }
@@ -436,7 +444,7 @@ func UpdateDiscountCampaign(w http.ResponseWriter, r *http.Request) {
http.Error(w, "Invalid start date format. Use ISO 8601 format", http.StatusBadRequest) http.Error(w, "Invalid start date format. Use ISO 8601 format", http.StatusBadRequest)
return return
} }
query += ", start_date = $" + string(rune('0'+argNum)) query += ", start_date = $" + strconv.Itoa(argNum)
args = append(args, startTime) args = append(args, startTime)
argNum++ argNum++
} }
@@ -446,12 +454,12 @@ func UpdateDiscountCampaign(w http.ResponseWriter, r *http.Request) {
http.Error(w, "Invalid end date format. Use ISO 8601 format", http.StatusBadRequest) http.Error(w, "Invalid end date format. Use ISO 8601 format", http.StatusBadRequest)
return return
} }
query += ", end_date = $" + string(rune('0'+argNum)) query += ", end_date = $" + strconv.Itoa(argNum)
args = append(args, endTime) args = append(args, endTime)
argNum++ argNum++
} }
if req.MilestoneType != nil { if req.MilestoneType != nil {
query += ", milestone_type = $" + string(rune('0'+argNum)) query += ", milestone_type = $" + strconv.Itoa(argNum)
args = append(args, *req.MilestoneType) args = append(args, *req.MilestoneType)
argNum++ argNum++
} }
@@ -460,12 +468,12 @@ func UpdateDiscountCampaign(w http.ResponseWriter, r *http.Request) {
http.Error(w, "Milestone value must be greater than 0", http.StatusBadRequest) http.Error(w, "Milestone value must be greater than 0", http.StatusBadRequest)
return return
} }
query += ", milestone_value = $" + string(rune('0'+argNum)) query += ", milestone_value = $" + strconv.Itoa(argNum)
args = append(args, *req.MilestoneValue) args = append(args, *req.MilestoneValue)
argNum++ argNum++
} }
if req.MilestoneUnit != nil { if req.MilestoneUnit != nil {
query += ", milestone_unit = $" + string(rune('0'+argNum)) query += ", milestone_unit = $" + strconv.Itoa(argNum)
args = append(args, *req.MilestoneUnit) args = append(args, *req.MilestoneUnit)
argNum++ argNum++
} }
@@ -474,17 +482,17 @@ func UpdateDiscountCampaign(w http.ResponseWriter, r *http.Request) {
http.Error(w, "Status must be 'active', 'cancelled', or 'completed'", http.StatusBadRequest) http.Error(w, "Status must be 'active', 'cancelled', or 'completed'", http.StatusBadRequest)
return return
} }
query += ", status = $" + string(rune('0'+argNum)) query += ", status = $" + strconv.Itoa(argNum)
args = append(args, *req.Status) args = append(args, *req.Status)
argNum++ argNum++
} }
if req.MaxRedemptions != nil { if req.MaxRedemptions != nil {
query += ", max_redemptions = $" + string(rune('0'+argNum)) query += ", max_redemptions = $" + strconv.Itoa(argNum)
args = append(args, *req.MaxRedemptions) args = append(args, *req.MaxRedemptions)
argNum++ argNum++
} }
query += " WHERE id = $" + string(rune('0'+argNum)) query += " WHERE id = $" + strconv.Itoa(argNum)
args = append(args, campaignID) args = append(args, campaignID)
_, err = db.DB.Exec(r.Context(), query, args...) _, err = db.DB.Exec(r.Context(), query, args...)