refactor(formmailer): use geoip instead of iploc for country check

Swap github.com/phuslu/iploc for the shared net/geoip package,
matching the pattern established by check-ip. AllowedCountries now
reads CountryISO off fm.Geo.Value().Lookup(ipStr) instead of
iploc.IPCountry, so the same GeoLite2 databases serve both callers
and refresh on the same cadence.

New field: Geo *dataset.View[geoip.Databases]. Required when
AllowedCountries is set; if Value() is nil (pre-load), the check is
skipped (unknown = allow), matching the prior iploc behavior on
unknown IPs.
This commit is contained in:
AJ ONeal 2026-04-20 20:35:18 -06:00
parent ee67cf05bc
commit 0d4bce8a38
No known key found for this signature in database
2 changed files with 15 additions and 8 deletions

View File

@ -8,7 +8,8 @@
//
// Typical setup:
//
// blacklist := dataset.Add(set, func() (*ipcohort.Cohort, error) { ... })
// blacklist := dataset.Add(set, func(ctx context.Context) (*ipcohort.Cohort, error) { ... })
// geo := dataset.Add(geoSet, func(ctx context.Context) (*geoip.Databases, error) { ... })
//
// fm := &formmailer.FormMailer{
// SMTPHost: "smtp.example.com:587",
@ -49,9 +50,9 @@ import (
"sync"
"time"
"github.com/phuslu/iploc"
"golang.org/x/time/rate"
"github.com/therootcompany/golib/net/geoip"
"github.com/therootcompany/golib/net/ipcohort"
"github.com/therootcompany/golib/sync/dataset"
)
@ -145,8 +146,12 @@ type FormMailer struct {
// Blacklist — if set, matching IPs are rejected before any other processing.
Blacklist *dataset.View[ipcohort.Cohort]
// Geo — required when AllowedCountries is set. Provides the GeoLite2
// City/ASN databases used for country lookup.
Geo *dataset.View[geoip.Databases]
// AllowedCountries — if non-nil, only requests from listed ISO codes are
// accepted. Unknown country ("") is always allowed.
// accepted. Unknown country ("") is always allowed. Requires Geo to be set.
AllowedCountries []string
// Fields declares the form inputs in display order. Exactly one entry
@ -229,12 +234,14 @@ func (fm *FormMailer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
}
if fm.AllowedCountries != nil {
country := string(iploc.IPCountry(ip))
if geo := fm.Geo.Value(); geo != nil {
country := geo.Lookup(ipStr).CountryISO
if country != "" && !slices.Contains(fm.AllowedCountries, country) {
fm.writeError(w, fmt.Errorf("submissions from your region are not accepted; please email us directly"), true)
return
}
}
}
if !fm.allow(ipStr) {
http.Error(w, "rate limit exceeded — please try again later", http.StatusTooManyRequests)

View File

@ -3,7 +3,7 @@ module github.com/therootcompany/golib/net/formmailer
go 1.26.0
require (
github.com/phuslu/iploc v1.0.20260415
github.com/therootcompany/golib/net/geoip v0.0.0
github.com/therootcompany/golib/net/ipcohort v0.0.0
github.com/therootcompany/golib/sync/dataset v0.0.0
golang.org/x/time v0.15.0