audit 4: log paging at its edges, NaN refused, a red rate limit, recalculation asks, reload writes all
test / test (push) Canceled after 0s
test / test (push) Canceled after 0s
Step 4 of stage 4 (L10, L11, L13, L18, L19 and a row of
review-2026-08-followups):
- The Outbound log counts first and clamps the page to the last; a number
too large for an int (strconv's ErrRange with the largest int) is the
last page on both logs. Tested at the edges: first, last, past the last
however far, nonsense, an empty log asked for page 5.
- checkAutoMultiplier is "not within", so NaN and the infinities are out.
- rate-limited is red (components.go; the mockup first, 643892a).
- data-unsaved on both recalculate buttons: panel.js asks on submit
(ev.submitter) when a field of the page differs from what it was drawn
with; testdata/unsaved_test.js under TestPanelJS.
- HandleReload writes what a restore's first start writes - the filter
lists and the DMARC maps too - and a failed step is an error flash on
Health that names it, not plain text; the success flash says what was
written.
Tested on the test server: go vet + go test of 25 packages, make e2e (all
pass, 695 s) on this tree.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -380,21 +380,22 @@ func (h *Handlers) outLogPage(r *http.Request) (*view.OutLog, error) {
|
||||
}
|
||||
}
|
||||
|
||||
page := parsePage(q.Get("p"))
|
||||
|
||||
total, err := h.store.CountSendLog(filter)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rows, err := h.store.QuerySendLog(filter, sendLogPageSize, (page-1)*sendLogPageSize)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
lastPage := 1
|
||||
if total > 0 {
|
||||
lastPage = int((total + sendLogPageSize - 1) / sendLogPageSize)
|
||||
}
|
||||
// A page past the end is the last one, as on the Inbound log: a link
|
||||
// kept while the log was pruned, or a number typed, shows rows, not an
|
||||
// empty table under "Page 9 of 2" (audit 2026-10-12, L10).
|
||||
page := min(parsePage(q.Get("p")), lastPage)
|
||||
rows, err := h.store.QuerySendLog(filter, sendLogPageSize, (page-1)*sendLogPageSize)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out := view.NewOutLog(h.shellMeta(r), h.sendLogRetentionDays(), p.IsGlobal(), domainNames, logins, filter.Domain, filter.AppLogin)
|
||||
table := make([]view.OutLogRow, len(rows))
|
||||
for i, row := range rows {
|
||||
@@ -409,8 +410,16 @@ func (h *Handlers) outLogPage(r *http.Request) (*view.OutLog, error) {
|
||||
|
||||
// parsePage clamps the "p" query parameter to a valid page number, defaulting
|
||||
// to 1 for anything missing or malformed rather than rejecting the request.
|
||||
//
|
||||
// A number too large for an int is past every last page, and is taken as
|
||||
// that: strconv returns it as the largest int with ErrRange (Go 1.26,
|
||||
// strconv.ParseInt: "the maximum magnitude integer of the appropriate
|
||||
// bitSize and sign"), and the caller clamps it to the last page.
|
||||
func parsePage(v string) int {
|
||||
n, err := strconv.Atoi(v)
|
||||
if errors.Is(err, strconv.ErrRange) && n > 0 {
|
||||
return n
|
||||
}
|
||||
if err != nil || n < 1 {
|
||||
return 1
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user