Bans an admin makes or lifts: the admin cause, a reason, lifted bans kept (closes #86)
check / check (push) Successful in 3m46s
check / check (push) Successful in 3m46s
A bans.json entry without a cause gets the cause admin, written back so. Bans whose cause is admin are never dropped and do not count toward SWWAF_MAX_BANS, so setting a ban's cause to admin keeps it. Bans smallwebwaf makes get a reason: the limit broken or the rule matched. A lifted ban refuses nothing, is kept, and makes no later ban longer. smallwebwaf_bans_made_total counts admin bans an edit adds while running; earlier_bans counts admin in place of without_cause. Judgement call: lifted lifts at once, whatever time it gives. Judgement call: a lifted ban still counts in earlier_bans. Known gap: a ban dropped from behind an admin's ban on its netblock leaves that netblock's later earlier_bans. Model: opus-5-5
This commit is contained in:
@@ -173,7 +173,7 @@ func TestNextBanWorkedOutFromTheBanThatEndedLast(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// A 9-hour ban smallwebwaf made, the third in a row, and an admin's
|
||||
// 1-hour ban added to bans.json over it, with no notes.
|
||||
// 1-hour ban added to bans.json over it, with no cause and no notes.
|
||||
netblock := netip.MustParsePrefix("203.0.113.9/32")
|
||||
nineHours := bans.Ban{
|
||||
Netblock: netblock,
|
||||
@@ -193,13 +193,12 @@ func TestNextBanWorkedOutFromTheBanThatEndedLast(t *testing.T) {
|
||||
|
||||
// Once both have ended, a limit broken within the repeat window bans
|
||||
// for three times the 9 hours, and the notes count the two bans
|
||||
// before the 9-hour one and it, for a limit, and the admin's, without
|
||||
// a cause.
|
||||
// before the 9-hour one and it, for a limit, and the admin's.
|
||||
ban := ledger.BanForLimit(netblock, nineHours.Expires.Add(time.Hour), bans.Notes{})
|
||||
if ban.Expires.Sub(ban.Start) != 27*time.Hour ||
|
||||
ban.Notes.EarlierBans != (bans.EarlierBans{Limit: 3, WithoutCause: 1}) {
|
||||
ban.Notes.EarlierBans != (bans.EarlierBans{Limit: 3, Admin: 1}) {
|
||||
t.Errorf("the next ban lasts %s with earlier bans %+v, "+
|
||||
"want 27h, 3 for a limit and 1 without a cause",
|
||||
"want 27h, 3 for a limit and 1 an admin's",
|
||||
ban.Expires.Sub(ban.Start), ban.Notes.EarlierBans)
|
||||
}
|
||||
}
|
||||
@@ -208,10 +207,15 @@ func TestLoadKeepsAtMostMaxBansDroppingTheEarliest(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// bans.json lists the bans by netblock, not in the order they began.
|
||||
later := bans.Ban{Netblock: netip.MustParsePrefix("203.0.113.1/32"), Start: midnight()}
|
||||
later := bans.Ban{
|
||||
Netblock: netip.MustParsePrefix("203.0.113.1/32"),
|
||||
Start: midnight(),
|
||||
Cause: bans.CauseLimit,
|
||||
}
|
||||
earlier := bans.Ban{
|
||||
Netblock: netip.MustParsePrefix("203.0.113.2/32"),
|
||||
Start: midnight().Add(-time.Hour),
|
||||
Cause: bans.CauseLimit,
|
||||
}
|
||||
|
||||
rules := defaultRules()
|
||||
@@ -233,9 +237,17 @@ func TestLoadReplacesTheBansHeld(t *testing.T) {
|
||||
rules := defaultRules()
|
||||
rules.MaxBans = 3
|
||||
ledger := bans.New(rules)
|
||||
kept := bans.Ban{Netblock: netip.MustParsePrefix("2001:db8::/64"), Start: midnight()}
|
||||
kept := bans.Ban{
|
||||
Netblock: netip.MustParsePrefix("2001:db8::/64"),
|
||||
Start: midnight(),
|
||||
Cause: bans.CauseLimit,
|
||||
}
|
||||
ledger.Load([]bans.Ban{
|
||||
{Netblock: netip.MustParsePrefix("203.0.113.0/24"), Start: midnight()},
|
||||
{
|
||||
Netblock: netip.MustParsePrefix("203.0.113.0/24"),
|
||||
Start: midnight(),
|
||||
Cause: bans.CauseLimit,
|
||||
},
|
||||
kept,
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user