From 039c73cb5dafaaec11323fac42436f1007bbe1cd Mon Sep 17 00:00:00 2001 From: ruslandoga <67764432+ruslandoga@users.noreply.github.com> Date: Fri, 28 Oct 2022 18:35:28 +0700 Subject: [PATCH] test geolocation e2e with a test mmdb --- config/.env.test | 1 + config/config.exs | 2 - config/test.exs | 2 - lib/plausible/geo.ex | 102 +++++++++++------- lib/plausible/geo/adapter.ex | 11 -- lib/plausible/geo/locus.ex | 51 --------- test/plausible/ingestion/event_test.exs | 10 +- .../api/external_controller_test.exs | 32 +++--- test/priv/GeoLite2-City-Test.mmdb | Bin 0 -> 20809 bytes test/priv/README.md | 1 + test/support/geo_stub.ex | 49 --------- 11 files changed, 88 insertions(+), 173 deletions(-) delete mode 100644 lib/plausible/geo/adapter.ex delete mode 100644 lib/plausible/geo/locus.ex create mode 100644 test/priv/GeoLite2-City-Test.mmdb create mode 100644 test/priv/README.md delete mode 100644 test/support/geo_stub.ex diff --git a/config/.env.test b/config/.env.test index 0f1a6f5d270a6..71044ee29bade 100644 --- a/config/.env.test +++ b/config/.env.test @@ -13,3 +13,4 @@ SELFHOST=false SITE_LIMIT=3 HCAPTCHA_SITEKEY=test HCAPTCHA_SECRET=scottiger +IP_GEOLOCATION_DB=test/priv/GeoLite2-City-Test.mmdb diff --git a/config/config.exs b/config/config.exs index 43e3ab4204330..369b11b00b264 100644 --- a/config/config.exs +++ b/config/config.exs @@ -41,6 +41,4 @@ config :plausible, Plausible.Repo, connect_timeout: 300_000, handshake_timeout: 300_000 -config :plausible, Plausible.Geo, adapter: Plausible.Geo.Locus - import_config "#{config_env()}.exs" diff --git a/config/test.exs b/config/test.exs index 8013847fef16a..02f33466f008a 100644 --- a/config/test.exs +++ b/config/test.exs @@ -27,5 +27,3 @@ config :bamboo, :refute_timeout, 10 config :plausible, session_timeout: 0, http_impl: Plausible.HTTPClient.Mock - -config :plausible, Plausible.Geo, adapter: Plausible.Geo.Stub diff --git a/lib/plausible/geo.ex b/lib/plausible/geo.ex index e5762ddfa5bb2..d0afc7b2128a4 100644 --- a/lib/plausible/geo.ex +++ b/lib/plausible/geo.ex @@ -1,6 +1,62 @@ defmodule Plausible.Geo do @moduledoc "Geolocation functions" - @adapter Application.compile_env!(:plausible, [__MODULE__, :adapter]) + @db :geolocation + + @doc """ + Starts the geodatabase loading process. Two options are supported, local file and maxmind key. + + Loading a local file: + + iex> load_db(path: "/etc/plausible/dbip-city.mmdb") + :ok + + Loading a maxmind db: + + # this license key is no longer active + iex> load_db(license_key: "LNpsJCCKPis6XvBP", edition: "GeoLite2-City", async: true) + :ok + + """ + def load_db(opts) do + cond do + license_key = opts[:license_key] -> + edition = opts[:edition] || "GeoLite2-City" + :ok = :locus.start_loader(@db, {:maxmind, edition}, license_key: license_key) + + path = opts[:path] -> + :ok = :locus.start_loader(@db, path) + + true -> + raise "failed to load geolocation db: need :path or :license_key to be provided" + end + + unless opts[:async] do + {:ok, _version} = :locus.await_loader(@db) + end + + :ok + end + + @doc """ + Returns geodatabase type. Used for deciding whether to show the DBIP disclaimer. + + Example: + + # in the case of a dbip db + iex> database_type() + "DBIP-City-Lite" + + # in the case of a maxmind db + iex> database_type() + "GeoLite2-City" + + """ + def database_type do + case :locus.get_info(@db, :metadata) do + {:ok, %{database_type: type}} -> type + _other -> nil + end + end @doc """ Looks up geo info about an ip address. @@ -88,43 +144,15 @@ defmodule Plausible.Geo do """ def lookup(ip_address) do - @adapter.lookup(ip_address) - end - - @doc """ - Starts the geodatabase loading process. Two options are supported, local file and maxmind key. - - Loading a local file: + case :locus.lookup(@db, ip_address) do + {:ok, entry} -> + entry - iex> load_db(path: "/etc/plausible/dbip-city.mmdb") - :ok + :not_found -> + nil - Loading a maxmind db: - - # this license key is no longer active - iex> load_db(license_key: "LNpsJCCKPis6XvBP", edition: "GeoLite2-City", async: true) - :ok - - """ - def load_db(opts \\ []) do - @adapter.load_db(opts) - end - - @doc """ - Returns geodatabase type. Used for deciding whether to show the DBIP disclaimer. - - Example: - - # in the case of a dbip db - iex> database_type() - "DBIP-City-Lite" - - # in the case of a maxmind db - iex> database_type() - "GeoLite2-City" - - """ - def database_type do - @adapter.database_type() + {:error, reason} -> + raise "failed to lookup ip address #{inspect(ip_address)}: " <> inspect(reason) + end end end diff --git a/lib/plausible/geo/adapter.ex b/lib/plausible/geo/adapter.ex deleted file mode 100644 index c1c1f20ac12e1..0000000000000 --- a/lib/plausible/geo/adapter.ex +++ /dev/null @@ -1,11 +0,0 @@ -defmodule Plausible.Geo.Adapter do - @moduledoc "Behaviour to be implemented by geolocation adapters" - - @type entry :: map - @type opts :: Keyword.t() - @type ip_address :: :inet.ip_address() | String.t() - - @callback load_db(opts) :: :ok - @callback database_type :: String.t() | nil - @callback lookup(ip_address) :: entry | nil -end diff --git a/lib/plausible/geo/locus.ex b/lib/plausible/geo/locus.ex deleted file mode 100644 index 6be51cea67ee6..0000000000000 --- a/lib/plausible/geo/locus.ex +++ /dev/null @@ -1,51 +0,0 @@ -defmodule Plausible.Geo.Locus do - @moduledoc false - require Logger - - @behaviour Plausible.Geo.Adapter - @db :geolocation - - @impl true - def load_db(opts) do - cond do - license_key = opts[:license_key] -> - edition = opts[:edition] || "GeoLite2-City" - :ok = :locus.start_loader(@db, {:maxmind, edition}, license_key: license_key) - - path = opts[:path] -> - :ok = :locus.start_loader(@db, path) - - true -> - raise "failed to load geolocation db: need :path or :license_key to be provided" - end - - unless opts[:async] do - {:ok, _version} = :locus.await_loader(@db) - end - - :ok - end - - @impl true - def database_type do - case :locus.get_info(@db, :metadata) do - {:ok, %{database_type: type}} -> type - _other -> nil - end - end - - @impl true - def lookup(ip_address) do - case :locus.lookup(@db, ip_address) do - {:ok, entry} -> - entry - - :not_found -> - nil - - {:error, reason} -> - Logger.error("failed to lookup ip address: " <> inspect(reason)) - nil - end - end -end diff --git a/test/plausible/ingestion/event_test.exs b/test/plausible/ingestion/event_test.exs index e306bba2a171c..ef201367c3462 100644 --- a/test/plausible/ingestion/event_test.exs +++ b/test/plausible/ingestion/event_test.exs @@ -15,7 +15,7 @@ defmodule Plausible.Ingestion.EventTest do end @valid_request %Plausible.Ingestion.Request{ - remote_ip: "2.2.2.2", + remote_ip: "2.125.160.216", user_agent: "Mozilla/5.0 (iPad; U; CPU OS 3_2_1 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Mobile/7B405", event_name: "pageview", @@ -46,8 +46,8 @@ defmodule Plausible.Ingestion.EventTest do domain: "plausible-ingestion-event-basic.test", browser: "Safari", browser_version: "", - city_geoname_id: 2_988_507, - country_code: "FR", + city_geoname_id: 2_655_045, + country_code: "GB", hostname: "skywalker.test", "meta.key": [], "meta.value": [], @@ -58,8 +58,8 @@ defmodule Plausible.Ingestion.EventTest do referrer: "m.facebook.test", referrer_source: "utm_source", screen_size: "Desktop", - subdivision1_code: "FR-IDF", - subdivision2_code: "FR-75", + subdivision1_code: "GB-ENG", + subdivision2_code: "GB-WBK", transferred_from: "", utm_campaign: "utm_campaign", utm_content: "utm_content", diff --git a/test/plausible_web/controllers/api/external_controller_test.exs b/test/plausible_web/controllers/api/external_controller_test.exs index bc7d97d7d75de..ae421fa969547 100644 --- a/test/plausible_web/controllers/api/external_controller_test.exs +++ b/test/plausible_web/controllers/api/external_controller_test.exs @@ -630,7 +630,7 @@ defmodule PlausibleWeb.Api.ExternalControllerTest do assert event.referrer == "" end - # Fake data is set up in config/test.exs + # Fake geo is loaded from test/priv/GeoLite2-City-Test.mmdb test "looks up location data from the ip address", %{conn: conn} do params = %{ name: "pageview", @@ -639,15 +639,15 @@ defmodule PlausibleWeb.Api.ExternalControllerTest do } conn - |> put_req_header("x-forwarded-for", "2.2.2.2") + |> put_req_header("x-forwarded-for", "2.125.160.216") |> post("/api/event", params) pageview = get_event("external-controller-test-20.com") - assert pageview.country_code == "FR" - assert pageview.subdivision1_code == "FR-IDF" - assert pageview.subdivision2_code == "FR-75" - assert pageview.city_geoname_id == 2_988_507 + assert pageview.country_code == "GB" + assert pageview.subdivision1_code == "GB-ENG" + assert pageview.subdivision2_code == "GB-WBK" + assert pageview.city_geoname_id == 2_655_045 end test "ignores unknown country code ZZ", %{conn: conn} do @@ -674,7 +674,7 @@ defmodule PlausibleWeb.Api.ExternalControllerTest do } conn - |> put_req_header("x-forwarded-for", "1.1.1.1:123") + |> put_req_header("x-forwarded-for", "216.160.83.56:123") |> post("/api/event", params) pageview = get_event("external-controller-test-x-forwarded-for-port.com") @@ -690,12 +690,12 @@ defmodule PlausibleWeb.Api.ExternalControllerTest do } conn - |> put_req_header("x-forwarded-for", "1:1:1:1:1:1:1:1") + |> put_req_header("x-forwarded-for", "2001:218:1:1:1:1:1:1") |> post("/api/event", params) pageview = get_event("external-controller-test-x-forwarded-for-ipv6.com") - assert pageview.country_code == "US" + assert pageview.country_code == "JP" end test "works with ipv6 with a port number in x-forwarded-for", %{conn: conn} do @@ -706,12 +706,12 @@ defmodule PlausibleWeb.Api.ExternalControllerTest do } conn - |> put_req_header("x-forwarded-for", "[1:1:1:1:1:1:1:1]:123") + |> put_req_header("x-forwarded-for", "[2001:218:1:1:1:1:1:1]:123") |> post("/api/event", params) pageview = get_event("external-controller-test-x-forwarded-for-ipv6-port.com") - assert pageview.country_code == "US" + assert pageview.country_code == "JP" end test "uses cloudflare's special header for client IP address if present", %{conn: conn} do @@ -723,7 +723,7 @@ defmodule PlausibleWeb.Api.ExternalControllerTest do conn |> put_req_header("x-forwarded-for", "0.0.0.0") - |> put_req_header("cf-connecting-ip", "1.1.1.1") + |> put_req_header("cf-connecting-ip", "216.160.83.56") |> post("/api/event", params) pageview = get_event("external-controller-test-cloudflare.com") @@ -740,7 +740,7 @@ defmodule PlausibleWeb.Api.ExternalControllerTest do conn |> put_req_header("x-forwarded-for", "0.0.0.0") - |> put_req_header("b-forwarded-for", "1.1.1.1,9.9.9.9") + |> put_req_header("b-forwarded-for", "216.160.83.56,9.9.9.9") |> post("/api/event", params) pageview = get_event("external-controller-test-bunny.com") @@ -758,7 +758,7 @@ defmodule PlausibleWeb.Api.ExternalControllerTest do } conn - |> put_req_header("forwarded", "by=0.0.0.0;for=1.1.1.1;host=somehost.com;proto=https") + |> put_req_header("forwarded", "by=0.0.0.0;for=216.160.83.56;host=somehost.com;proto=https") |> post("/api/event", params) pageview = get_event("external-controller-test-forwarded.com") @@ -776,13 +776,13 @@ defmodule PlausibleWeb.Api.ExternalControllerTest do conn |> put_req_header( "forwarded", - "by=0.0.0.0;for=\"[1:1:1:1:1:1:1:1]\",for=0.0.0.0;host=somehost.com;proto=https" + "by=0.0.0.0;for=\"[2001:218:1:1:1:1:1:1]\",for=0.0.0.0;host=somehost.com;proto=https" ) |> post("/api/event", params) pageview = get_event("external-controller-test-forwarded-ipv6.com") - assert pageview.country_code == "US" + assert pageview.country_code == "JP" end test "URL is decoded", %{conn: conn} do diff --git a/test/priv/GeoLite2-City-Test.mmdb b/test/priv/GeoLite2-City-Test.mmdb new file mode 100644 index 0000000000000000000000000000000000000000..ed9adc6547fd91b24329c903ace3cc60cab8a408 GIT binary patch literal 20809 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 literal 0 HcmV?d00001 diff --git a/test/priv/README.md b/test/priv/README.md new file mode 100644 index 0000000000000..eb99937238f82 --- /dev/null +++ b/test/priv/README.md @@ -0,0 +1 @@ +`GeoLite2-City-Test.mmdb` is downloaded from https://github.com/maxmind/MaxMind-DB diff --git a/test/support/geo_stub.ex b/test/support/geo_stub.ex deleted file mode 100644 index 5d81226a719bb..0000000000000 --- a/test/support/geo_stub.ex +++ /dev/null @@ -1,49 +0,0 @@ -defmodule Plausible.Geo.Stub do - @moduledoc false - @behaviour Plausible.Geo.Adapter - - sample_lookup = %{ - "city" => %{"geoname_id" => 2_988_507, "names" => %{"en" => "Paris"}}, - "continent" => %{"code" => "EU", "geoname_id" => 6_255_148, "names" => %{"en" => "Europe"}}, - "country" => %{ - "geoname_id" => 3_017_382, - "is_in_european_union" => true, - "iso_code" => "FR", - "names" => %{"en" => "France"} - }, - "location" => %{ - "latitude" => 48.8566, - "longitude" => 2.35222, - "time_zone" => "Europe/Paris", - "weather_code" => "FRXX0076" - }, - "postal" => %{"code" => "75000"}, - "subdivisions" => [ - %{"geoname_id" => 3_012_874, "iso_code" => "IDF", "names" => %{"en" => "Île-de-France"}}, - %{"geoname_id" => 2_968_815, "iso_code" => "75", "names" => %{"en" => "Paris"}} - ] - } - - @lut %{ - {1, 1, 1, 1} => %{"country" => %{"iso_code" => "US"}}, - {2, 2, 2, 2} => sample_lookup, - {1, 1, 1, 1, 1, 1, 1, 1} => %{"country" => %{"iso_code" => "US"}}, - {0, 0, 0, 0} => %{"country" => %{"iso_code" => "ZZ"}} - } - - @impl true - def lookup(ip_address) when is_tuple(ip_address) do - Map.get(@lut, ip_address) - end - - def lookup(ip_address) when is_binary(ip_address) do - {:ok, ip_address} = :inet.parse_address(to_charlist(ip_address)) - lookup(ip_address) - end - - @impl true - def load_db(_opts), do: :ok - - @impl true - def database_type, do: "DBIP-City-Lite" -end