website/pkg/middleware/geo_gate.go

89 lines
2.4 KiB
Go

package middleware
import (
"net"
"net/http"
"code.nonshy.com/nonshy/website/pkg/config"
"code.nonshy.com/nonshy/website/pkg/controller/index"
"code.nonshy.com/nonshy/website/pkg/session"
"code.nonshy.com/nonshy/website/pkg/utility"
"github.com/oschwald/geoip2-golang"
)
// GeoGate: block access to the site based on the user's location (due to local laws or regulations).
func GeoGate(handler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if !config.GeoGateEnabled {
handler.ServeHTTP(w, r)
return
}
// Flash errors to admins.
onError := func(err error) {
session.FlashError(w, r, "GeoIP: %s", err)
handler.ServeHTTP(w, r)
}
// See where they're coming from.
db, err := geoip2.Open(config.GeoIPPath)
if err != nil {
onError(err)
return
}
defer db.Close()
// If you are using strings that may be invalid, check that ip is not nil
addr := utility.IPAddress(r)
ip := net.ParseIP(addr)
if ip != nil {
record, err := db.City(ip)
if err != nil {
onError(err)
return
}
// Blocked by US states
if record.Country.IsoCode == "US" {
for _, sub := range record.Subdivisions {
if _, ok := config.BlockUSStates[sub.IsoCode]; ok {
session.LogoutUser(w, r)
page := index.StaticTemplate("errors/geo_gate.html")()
page(w, r)
return
}
}
}
// Blocked by country code
if _, ok := config.BlockCountries[record.Country.IsoCode]; ok {
session.LogoutUser(w, r)
page := index.StaticTemplate("errors/geo_gate.html")()
page(w, r)
return
}
// Debug info
/*
fmt.Printf("Portuguese (BR) city name: %v\n", record.City.Names["pt-BR"])
if len(record.Subdivisions) > 0 {
fmt.Printf("English subdivision name: %v\n", record.Subdivisions[0].Names["en"])
}
fmt.Printf("Russian country name: %v\n", record.Country.Names["ru"])
fmt.Printf("ISO country code: %v\n", record.Country.IsoCode)
fmt.Printf("Time zone: %v\n", record.Location.TimeZone)
fmt.Printf("Coordinates: %v, %v\n", record.Location.Latitude, record.Location.Longitude)
// Output:
// Portuguese (BR) city name: Londres
// English subdivision name: England
// Russian country name: Великобритания
// ISO country code: GB
// Time zone: Europe/London
// Coordinates: 51.5142, -0.0931
*/
}
handler.ServeHTTP(w, r)
})
}