diff --git a/backend/handlers/admin/discount_campaigns.go b/backend/handlers/admin/discount_campaigns.go index 81cf26b..b8f1b17 100644 --- a/backend/handlers/admin/discount_campaigns.go +++ b/backend/handlers/admin/discount_campaigns.go @@ -37,8 +37,8 @@ type DiscountCampaign struct { // CreateCampaignRequest represents the request payload for creating a new campaign type CreateCampaignRequest struct { - Name string `json:"name"` - Description *string `json:"description,omitempty"` + Name string `json:"name" validate:"required,min=1,max=200"` + Description *string `json:"description,omitempty" validate:"omitempty,max=1000"` CampaignType string `json:"campaign_type"` // "time_based" or "milestone" DiscountPercent float64 `json:"discount_percent"` Scope *string `json:"scope,omitempty"` @@ -52,8 +52,8 @@ type CreateCampaignRequest struct { // UpdateCampaignRequest represents the request payload for updating a campaign type UpdateCampaignRequest struct { - Name *string `json:"name,omitempty"` - Description *string `json:"description,omitempty"` + Name *string `json:"name,omitempty" validate:"omitempty,min=1,max=200"` + Description *string `json:"description,omitempty" validate:"omitempty,max=1000"` DiscountPercent *float64 `json:"discount_percent,omitempty"` Scope *string `json:"scope,omitempty"` StartDate *string `json:"start_date,omitempty"` @@ -206,6 +206,11 @@ func CreateDiscountCampaign(w http.ResponseWriter, r *http.Request) { return } + if err := validators.Validate.Struct(&req); err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + // Validate required fields if req.Name == "" { http.Error(w, "Name is required", http.StatusBadRequest) @@ -391,6 +396,11 @@ func UpdateDiscountCampaign(w http.ResponseWriter, r *http.Request) { return } + if err := validators.Validate.Struct(&req); err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + // Build dynamic update query query := "UPDATE discount_campaigns SET updated_at = NOW()" args := []interface{}{} diff --git a/backend/handlers/admin/patch_tests.go b/backend/handlers/admin/patch_tests.go index 65c24e8..342177f 100644 --- a/backend/handlers/admin/patch_tests.go +++ b/backend/handlers/admin/patch_tests.go @@ -23,8 +23,8 @@ type PatchTest struct { // CreatePatchTestRequest represents the request payload type CreatePatchTestRequest struct { - Name string `json:"name"` - Description *string `json:"description,omitempty"` + Name string `json:"name" validate:"required,min=1,max=200"` + Description *string `json:"description,omitempty" validate:"omitempty,max=1000"` NoticeDurationHours int `json:"notice_duration_hours"` ExpiryMonths int `json:"expiry_months"` ServiceIDs []string `json:"service_ids"` @@ -32,8 +32,8 @@ type CreatePatchTestRequest struct { // UpdatePatchTestRequest represents the request payload type UpdatePatchTestRequest struct { - Name *string `json:"name,omitempty"` - Description *string `json:"description,omitempty"` + Name *string `json:"name,omitempty" validate:"omitempty,min=1,max=200"` + Description *string `json:"description,omitempty" validate:"omitempty,max=1000"` NoticeDurationHours *int `json:"notice_duration_hours,omitempty"` ExpiryMonths *int `json:"expiry_months,omitempty"` ServiceIDs []string `json:"service_ids,omitempty"` @@ -81,6 +81,11 @@ func CreatePatchTest(w http.ResponseWriter, r *http.Request) { return } + if err := validators.Validate.Struct(&req); err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + query := ` INSERT INTO patch_tests (name, description, notice_duration_hours, expiry_months, service_ids) VALUES ($1, $2, $3, $4, $5) @@ -112,6 +117,11 @@ func UpdatePatchTest(w http.ResponseWriter, r *http.Request) { return } + if err := validators.Validate.Struct(&req); err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + query := "UPDATE patch_tests SET " args := []interface{}{} i := 1 diff --git a/backend/handlers/scheduling/time-blockers.go b/backend/handlers/scheduling/time-blockers.go index ce516f5..e10b2f8 100644 --- a/backend/handlers/scheduling/time-blockers.go +++ b/backend/handlers/scheduling/time-blockers.go @@ -9,6 +9,7 @@ import ( "time" "crussell/db" + "crussell/internal/validators" "crussell/mw" "github.com/go-chi/chi/v5" @@ -29,10 +30,10 @@ type TimeBlocker struct { } type CreateTimeBlockerRequest struct { - StartTime time.Time `json:"start_time"` - DurationMinutes int `json:"duration_minutes"` - Description string `json:"description,omitempty"` - CronExpression *string `json:"cron_expression,omitempty"` + StartTime time.Time `json:"start_time" validate:"required"` + DurationMinutes int `json:"duration_minutes" validate:"required,gt=0"` + Description string `json:"description,omitempty" validate:"omitempty,max=500"` + CronExpression *string `json:"cron_expression,omitempty" validate:"omitempty,max=500"` } // --- List Time Blockers --- @@ -123,6 +124,11 @@ func CreateTimeBlocker(w http.ResponseWriter, r *http.Request) { return } + if err := validators.Validate.Struct(&req); err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + // Validate required fields if req.StartTime.IsZero() { http.Error(w, "start_time is required", http.StatusBadRequest)