fix(bookings): add request struct validation and fix patch test notice logic
Add validators.Validate.Struct() calls across booking handlers. Fix patch test notice period check to compare against booking start time (not current time) and fix expiry check similarly. Update test to match new error message. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -912,6 +912,10 @@ func UpdateBookingServicesHandler(w http.ResponseWriter, r *http.Request) {
|
||||
http.Error(w, "Invalid request", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if err := validators.Validate.Struct(&req); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if len(req.ServiceIDs) == 0 {
|
||||
http.Error(w, "At least one service is required", http.StatusBadRequest)
|
||||
@@ -1216,6 +1220,10 @@ func SearchAdminBookingsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
http.Error(w, "Search query 'q' is required", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if len(query) > 200 {
|
||||
http.Error(w, "search query too long", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
page, perPage := 1, 10
|
||||
if pageStr := r.URL.Query().Get("page"); pageStr != "" {
|
||||
@@ -1492,6 +1500,11 @@ func CreateBookingHandler(w http.ResponseWriter, r *http.Request) {
|
||||
isGuest = true
|
||||
}
|
||||
|
||||
if err := validators.Validate.Struct(&req); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if req.StartTime.IsZero() {
|
||||
http.Error(w, "Start time is required", http.StatusBadRequest)
|
||||
return
|
||||
@@ -1566,15 +1579,16 @@ func CreateBookingHandler(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
eligibleFrom := testedAt.Add(time.Duration(noticeHours) * time.Hour)
|
||||
if time.Now().Before(eligibleFrom) {
|
||||
hoursLeft := time.Until(eligibleFrom).Hours()
|
||||
http.Error(w, fmt.Sprintf("You must wait %.0f hours after your patch test before booking this service.", hoursLeft), http.StatusBadRequest)
|
||||
if req.StartTime.Before(eligibleFrom) {
|
||||
hoursLeft := eligibleFrom.Sub(req.StartTime).Hours()
|
||||
http.Error(w, fmt.Sprintf("Booking time is before the %.0f hour notice period after patch test. Earliest booking: %s", hoursLeft, eligibleFrom.Format("2006-01-02 15:04")), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
var expiryMonths int
|
||||
if err := db.DB.QueryRow(r.Context(), `SELECT expiry_months FROM patch_tests WHERE id = $1`, patchTestID).Scan(&expiryMonths); err == nil {
|
||||
if time.Now().After(testedAt.AddDate(0, expiryMonths, 0)) {
|
||||
expiresAt := testedAt.AddDate(0, expiryMonths, 0)
|
||||
if req.StartTime.After(expiresAt) {
|
||||
http.Error(w, "Your patch test has expired. Please complete a new patch test.", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
@@ -1777,6 +1791,10 @@ func EditBookingHandler(w http.ResponseWriter, r *http.Request) {
|
||||
http.Error(w, "Invalid request", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if err := validators.Validate.Struct(&req); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if req.StartTime.IsZero() {
|
||||
http.Error(w, "Start time is required", http.StatusBadRequest)
|
||||
@@ -2220,6 +2238,10 @@ func ConfirmBookingHandler(w http.ResponseWriter, r *http.Request) {
|
||||
http.Error(w, "Invalid request", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if err := validators.Validate.Struct(&req); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
for _, override := range req.ServiceOverrides {
|
||||
if override.OverridePrice != nil && *override.OverridePrice < 0 {
|
||||
@@ -2434,6 +2456,10 @@ func DeleteBookingHandler(w http.ResponseWriter, r *http.Request) {
|
||||
http.Error(w, "Invalid request", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if err := validators.Validate.Struct(&req); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
allowed := map[string]bool{
|
||||
"client_cancelled": true, "we_cancelled": true, "re-schedule": true, "no_show": true,
|
||||
}
|
||||
@@ -3291,6 +3317,10 @@ func AdminRescheduleBookingHandler(w http.ResponseWriter, r *http.Request) {
|
||||
http.Error(w, "Invalid request", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if err := validators.Validate.Struct(&req); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if req.StartTime.IsZero() {
|
||||
http.Error(w, "Start time is required", http.StatusBadRequest)
|
||||
|
||||
Reference in New Issue
Block a user