mirror of
https://github.com/Kpa-clawbot/meshcore-analyzer.git
synced 2026-10-23 16:32:22 +00:00
feat: link the foreign/domestic geo_filter boundary to a named area
Adds Config.HomeArea: when set to an existing area's key, that area's geometry becomes the effective geo_filter (getGeoFilter), instead of maintaining a second, independently-drawn boundary that can drift out of sync -- exactly what happened with Germany's box bleeding into southern Denmark earlier this session. Falls back to the standalone GeoFilter field when HomeArea is unset or unresolved, so existing deployments see no behavior change. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
896a21cda7
commit
e8e7b670e6
3 files changed
+73
No files matched your search
@@ -244,6 +244,15 @@ type Config struct {
|
||||
|
||||
Areas map[string]AreaEntry `json:"areas,omitempty"`
|
||||
|
||||
// HomeArea names an entry in Areas whose geometry defines "home" for
|
||||
// the foreign/domestic classification (geo_filter above), instead of
|
||||
// maintaining a second, separately-drawn boundary that can drift out
|
||||
// of sync with the area map (see AreaForPoint/AreaKeysForPoint).
|
||||
// When set and the named area exists, it takes priority over any
|
||||
// standalone GeoFilter value — see (*Server).getGeoFilter. Leave
|
||||
// unset to keep using GeoFilter exactly as before.
|
||||
HomeArea string `json:"homeArea,omitempty"`
|
||||
|
||||
Timestamps *TimestampConfig `json:"timestamps,omitempty"`
|
||||
|
||||
// CORSAllowedOrigins is the list of origins permitted to make cross-origin
|
||||
|
||||
@@ -76,3 +76,49 @@ func TestConfigClientOmitsGeoFilterWhenUnconfigured(t *testing.T) {
|
||||
t.Error("expected geoFilter to be omitted from /api/config/client when unconfigured")
|
||||
}
|
||||
}
|
||||
|
||||
// TestGetGeoFilter_HomeAreaTakesPriority covers the new HomeArea linkage:
|
||||
// when cfg.HomeArea names an existing area, its geometry is the effective
|
||||
// geo_filter -- a single boundary shared with the areas system instead of
|
||||
// a second copy that can drift out of sync (exactly what happened with
|
||||
// Germany's box vs. Denmark's area earlier this session).
|
||||
func TestGetGeoFilter_HomeAreaTakesPriority(t *testing.T) {
|
||||
srv, _ := setupTestServer(t)
|
||||
standaloneLat := 10.0
|
||||
srv.cfg.GeoFilter = &GeoFilterConfig{LatMin: &standaloneLat} // deliberately different from the area
|
||||
f := func(v float64) *float64 { return &v }
|
||||
srv.cfg.Areas = map[string]AreaEntry{
|
||||
"DK": {Label: "Danmark", LatMin: f(54.5), LatMax: f(57.8), LonMin: f(8.0), LonMax: f(15.25)},
|
||||
}
|
||||
srv.cfg.HomeArea = "DK"
|
||||
|
||||
gf := srv.getGeoFilter()
|
||||
if gf == nil || gf.LatMin == nil || *gf.LatMin != 54.5 {
|
||||
t.Fatalf("getGeoFilter() = %+v, want DK area's LatMin=54.5 (HomeArea should win over the standalone GeoFilter)", gf)
|
||||
}
|
||||
}
|
||||
|
||||
// TestGetGeoFilter_FallsBackWhenHomeAreaUnresolved confirms existing
|
||||
// deployments (no HomeArea configured, or one naming a since-removed area)
|
||||
// see no behavior change -- the standalone GeoFilter still applies.
|
||||
func TestGetGeoFilter_FallsBackWhenHomeAreaUnresolved(t *testing.T) {
|
||||
srv, _ := setupTestServer(t)
|
||||
standaloneLat := 10.0
|
||||
srv.cfg.GeoFilter = &GeoFilterConfig{LatMin: &standaloneLat}
|
||||
|
||||
t.Run("HomeArea unset", func(t *testing.T) {
|
||||
srv.cfg.HomeArea = ""
|
||||
gf := srv.getGeoFilter()
|
||||
if gf == nil || gf.LatMin == nil || *gf.LatMin != 10.0 {
|
||||
t.Errorf("getGeoFilter() = %+v, want the standalone GeoFilter (LatMin=10.0)", gf)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("HomeArea names a nonexistent area", func(t *testing.T) {
|
||||
srv.cfg.HomeArea = "NOPE"
|
||||
gf := srv.getGeoFilter()
|
||||
if gf == nil || gf.LatMin == nil || *gf.LatMin != 10.0 {
|
||||
t.Errorf("getGeoFilter() = %+v, want the standalone GeoFilter (LatMin=10.0)", gf)
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/meshcore-analyzer/geofilter"
|
||||
"github.com/meshcore-analyzer/packetpath"
|
||||
"github.com/meshcore-analyzer/prunequeue"
|
||||
regionutil "github.com/meshcore-analyzer/regions"
|
||||
@@ -180,9 +181,26 @@ func (s *Server) isPubkeyHidden(pubkey string) bool {
|
||||
return s.cfg.IsNameHidden(name)
|
||||
}
|
||||
|
||||
// getGeoFilter returns the effective home-boundary geometry. If
|
||||
// cfg.HomeArea names an existing entry in cfg.Areas, that area's geometry
|
||||
// wins — a single boundary shared with the areas system, instead of a
|
||||
// second copy that can silently drift (see cfg.HomeArea doc comment).
|
||||
// Falls back to the standalone GeoFilter field when HomeArea is unset or
|
||||
// doesn't resolve, so existing deployments see no behavior change.
|
||||
func (s *Server) getGeoFilter() *GeoFilterConfig {
|
||||
s.cfgMu.RLock()
|
||||
defer s.cfgMu.RUnlock()
|
||||
if s.cfg != nil && s.cfg.HomeArea != "" {
|
||||
if area, ok := s.cfg.Areas[s.cfg.HomeArea]; ok {
|
||||
return &geofilter.Config{
|
||||
Polygon: area.Polygon,
|
||||
LatMin: area.LatMin,
|
||||
LatMax: area.LatMax,
|
||||
LonMin: area.LonMin,
|
||||
LonMax: area.LonMax,
|
||||
}
|
||||
}
|
||||
}
|
||||
return s.cfg.GeoFilter
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user