fix - carto now requires api keys
All checks were successful
Release / tag (push) Successful in 2s
Release / build-and-release (push) Successful in 13s

This commit is contained in:
mr0xb 2026-08-26 22:41:52 -04:00
commit 3a3307e190
9 changed files with 100 additions and 6 deletions

View file

@ -5,6 +5,7 @@ import (
"encoding/json"
"fmt"
"html/template"
"net/url"
"path/filepath"
"sort"
"strings"
@ -66,6 +67,10 @@ type ReportData struct {
// Theme selects the visual theme (see themes.go). Empty or unrecognized
// falls back to DefaultTheme.
Theme string
// MapAPIKey is the basemap provider API key. When non-empty it is appended
// to the theme's tile URL as a "key" query parameter (CARTO's format).
MapAPIKey string
}
// DaySummary is one row in the index page's daily breakdown table.
@ -338,6 +343,20 @@ type reportRenderData struct {
MarkerColor string
}
// tileURLWithKey appends the basemap provider API key to tileURL as a "key"
// query parameter, e.g. ".../{z}/{x}/{y}.png?key=XYZ". The URL is returned
// unchanged when no key is set.
func tileURLWithKey(tileURL, key string) string {
if key == "" || tileURL == "" {
return tileURL
}
sep := "?"
if strings.Contains(tileURL, "?") {
sep = "&"
}
return tileURL + sep + "key=" + url.QueryEscape(key)
}
// GenerateHTML renders the full HTML report from data.
func GenerateHTML(data ReportData) (string, error) {
th := themeFor(data.Theme)
@ -354,7 +373,7 @@ func GenerateHTML(data ReportData) (string, error) {
Chart3: th.Chart3,
ChartWarn: th.ChartWarn,
ChartErr: th.ChartErr,
MapTileURL: th.MapTileURL,
MapTileURL: tileURLWithKey(th.MapTileURL, data.MapAPIKey),
MapAttribution: th.MapAttribution,
MarkerColor: th.MarkerColor,
}

View file

@ -624,3 +624,56 @@ func TestGenerateHTML_DayTitleInHeader(t *testing.T) {
t.Error("expected DayTitle in report HTML")
}
}
// ── map API key ────────────────────────────────────────────────────────────
func TestTileURLWithKey(t *testing.T) {
cases := []struct{ url, key, want string }{
{"https://basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}.png", "XYZ",
"https://basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}.png?key=XYZ"},
{"https://tiles.example/{z}/{x}/{y}.png?style=dark", "XYZ",
"https://tiles.example/{z}/{x}/{y}.png?style=dark&key=XYZ"},
{"https://tiles.example/{z}/{x}/{y}.png", "a b&c",
"https://tiles.example/{z}/{x}/{y}.png?key=a+b%26c"},
{"https://tiles.example/{z}/{x}/{y}.png", "",
"https://tiles.example/{z}/{x}/{y}.png"},
}
for _, c := range cases {
if got := tileURLWithKey(c.url, c.key); got != c.want {
t.Errorf("tileURLWithKey(%q, %q) = %q, want %q", c.url, c.key, got, c.want)
}
}
}
func TestGenerateHTML_MapAPIKeyInTileURL(t *testing.T) {
data := makeTestData()
ComputeStats(&data)
data.GeoLocations = []GeoPoint{
{IP: "1.1.1.1", Lat: 37.751, Lon: -97.822, Country: "United States", CountryCode: "US", Count: 2},
}
data.MapAPIKey = "secret-key"
html, err := GenerateHTML(data)
if err != nil {
t.Fatalf("GenerateHTML error: %v", err)
}
if !strings.Contains(html, "?key=secret-key") {
t.Error("expected map API key appended to the tile URL")
}
}
func TestGenerateHTML_NoMapAPIKeyLeavesTileURL(t *testing.T) {
data := makeTestData()
ComputeStats(&data)
data.GeoLocations = []GeoPoint{
{IP: "1.1.1.1", Lat: 37.751, Lon: -97.822, Country: "United States", CountryCode: "US", Count: 2},
}
html, err := GenerateHTML(data)
if err != nil {
t.Fatalf("GenerateHTML error: %v", err)
}
if strings.Contains(html, "key=") {
t.Error("did not expect a key query parameter when MapAPIKey is empty")
}
}

View file

@ -241,7 +241,7 @@ var cactusTheme = themeAssets{
Chart3: "#e0956b",
ChartWarn: "#d99a3d",
ChartErr: "#c96a5b",
MapTileURL: "https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png",
MapTileURL: "https://basemaps.cartocdn.com/rastertiles/light_all/{z}/{x}/{y}{r}.png",
MapAttribution: `&copy; <a href="https://carto.com/">CARTO</a>`,
MarkerColor: "#e0956b",
}

View file

@ -258,7 +258,7 @@ var cyberpunkTheme = themeAssets{
Chart3: "#ff00c8",
ChartWarn: "#ffcc00",
ChartErr: "#ff4444",
MapTileURL: "https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png",
MapTileURL: "https://basemaps.cartocdn.com/rastertiles/dark_all/{z}/{x}/{y}{r}.png",
MapAttribution: `&copy; <a href="https://carto.com/">CARTO</a>`,
MarkerColor: "#ff00c8",
}

View file

@ -243,7 +243,7 @@ var purplerainTheme = themeAssets{
Chart3: "#e879f9",
ChartWarn: "#fbbf24",
ChartErr: "#fb7185",
MapTileURL: "https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png",
MapTileURL: "https://basemaps.cartocdn.com/rastertiles/dark_all/{z}/{x}/{y}{r}.png",
MapAttribution: `&copy; <a href="https://carto.com/">CARTO</a>`,
MarkerColor: "#a78bfa",
}