You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
fix(plans): add server-side past-date guard in createPlannedPurchases #1275
PR #1258 (QA 5.6) added a browser-level `min` attribute to the Add Purchases start-date picker to block past dates on the client. The backend handler `parseCreatePurchasesRequest` in `internal/api/handler_plans.go` only validates the date format (`YYYY-MM-DD`), not that the date is >= today.
A caller that bypasses the browser (e.g., `curl`) can submit any past date, causing purchase executions to be scheduled in the past -- which the scheduler will execute immediately in bulk or skip depending on its catch-up behaviour, potentially making unintended purchases.
Root cause
`internal/api/handler_plans.go`, function `parseCreatePurchasesRequest` (~line 337):
today:=time.Now().UTC().Truncate(24*time.Hour)
ifstartDate.UTC().Before(today) {
returnnil, time.Time{}, NewClientError(400, "start_date must be today or a future date")
}
Use UTC truncation to align with ISO-8601 dates which are timezone-neutral; this matches how the frontend sends `YYYY-MM-DD` strings derived from `new Date().toISOString()`.
Test
Add a unit test in the handler plans test file that calls `parseCreatePurchasesRequest` with yesterday's date and expects a 400 `ClientError`.
Activity
cristim commentedon Sep 2, 2026
Duplicate of LeanerCloud/cloud-commitments-platform#50: both ask for the same past-date rejection in parseCreatePurchasesRequest (internal/api/handler_plans.go:483), and LeanerCloud/cloud-commitments-platform#50 additionally specifies the client-side check and the timezone decision, so the work is tracked there.