fix(admin): name the configured geo provider in the system snapshot

The admin system snapshot hardcoded "ipwho.is" for the offline-geo-off
state, so an operator who points IP_GEO_LOOKUP_URL at another provider
still read the wrong host. Resolve the actual provider host from the env
and surface it through /api/version, so the snapshot reads
"Online (ip-api.com)" — the host it really queries.
This commit is contained in:
Marc-André Bombeck committed 2026-06-30 18:08:57 +02:00
1 parent 6fe552ffdf
commit 45ca6ff24b
13 files changed
+98 -18

No files matched your search

@@ -5,8 +5,10 @@ vi.mock("@/lib/api-handler", () => ({
}));
const offlineGeoReadyMock = vi.fn(() => false);
const resolveGeoProviderHostMock = vi.fn(() => "ipwho.is");
vi.mock("@/lib/geo", () => ({
offlineGeoReady: () => offlineGeoReadyMock(),
resolveGeoProviderHost: () => resolveGeoProviderHostMock(),
}));
import { GET } from "../route";
@@ -16,6 +18,7 @@ beforeEach(() => {
delete process.env.NEXT_PUBLIC_APP_BUILT_AT;
delete process.env.NEXT_PUBLIC_APP_VERSION;
offlineGeoReadyMock.mockReturnValue(false);
resolveGeoProviderHostMock.mockReturnValue("ipwho.is");
});
interface VersionEnvelope {
@@ -28,6 +31,7 @@ interface VersionEnvelope {
changelog: string;
docs: string;
offlineGeoEnabled: boolean;
geoProviderHost: string;
};
}
@@ -95,4 +99,11 @@ describe("GET /api/version", () => {
const body = (await response.json()) as VersionEnvelope;
expect(body.data.offlineGeoEnabled).toBe(true);
});
it("surfaces the resolved online geo provider host", async () => {
resolveGeoProviderHostMock.mockReturnValue("ip-api.com");
const response = await (GET as unknown as () => Promise<Response>)();
const body = (await response.json()) as VersionEnvelope;
expect(body.data.geoProviderHost).toBe("ip-api.com");
});
});
+8 -4
View File
@@ -1,6 +1,6 @@
import { apiHandler } from "@/lib/api-handler";
import { apiSuccess } from "@/lib/api-response";
import { offlineGeoReady } from "@/lib/geo";
import { offlineGeoReady, resolveGeoProviderHost } from "@/lib/geo";
import packageJson from "../../../../package.json";
// v1.4.27 R5 — `offlineGeoEnabled` reads from the same source the geo
@@ -32,9 +32,11 @@ export const dynamic = "force-dynamic";
*
* `offlineGeoEnabled` is `true` when the GeoLite2-City MMDB is present
* at the configured `GEOLITE2_DIR` and no `.empty` marker is set.
* When `false` the runtime falls back to the online `ipwho.is`
* provider and the resolver emits a one-shot admin notification on
* first use.
* When `false` the runtime falls back to the online provider named by
* `geoProviderHost` (the host of `IP_GEO_LOOKUP_URL`, default
* `ipwho.is`) and the resolver emits a one-shot admin notification on
* first use. `geoProviderHost` lets the admin status surface name the
* real provider instead of assuming the default.
*/
export const GET = apiHandler(async () => {
// v1.4.43 B11 — prefer the build-arg-injected env var so the runtime
@@ -50,6 +52,7 @@ export const GET = apiHandler(async () => {
const buildSha = process.env.NEXT_PUBLIC_APP_BUILD_SHA?.trim() || null;
const builtAt = process.env.NEXT_PUBLIC_APP_BUILT_AT?.trim() || null;
const offlineGeoEnabled = offlineGeoReady();
const geoProviderHost = resolveGeoProviderHost();
return apiSuccess({
version,
@@ -60,5 +63,6 @@ export const GET = apiHandler(async () => {
changelog: "https://github.com/MBombeck/HealthLog/blob/main/CHANGELOG.md",
docs: "https://docs.healthlog.dev",
offlineGeoEnabled,
geoProviderHost,
});
});