mirror of
https://github.com/plausible/analytics.git
synced 2024-12-23 09:33:19 +03:00
Use only root domain in user id generation
This commit is contained in:
parent
9f92cf779f
commit
7cb148a4f1
@ -195,12 +195,18 @@ defmodule PlausibleWeb.Api.ExternalController do
|
|||||||
defp generate_user_id(conn, domain, hostname, salt) do
|
defp generate_user_id(conn, domain, hostname, salt) do
|
||||||
user_agent = List.first(Plug.Conn.get_req_header(conn, "user-agent")) || ""
|
user_agent = List.first(Plug.Conn.get_req_header(conn, "user-agent")) || ""
|
||||||
ip_address = PlausibleWeb.RemoteIp.get(conn)
|
ip_address = PlausibleWeb.RemoteIp.get(conn)
|
||||||
|
root_domain = get_root_domain(hostname)
|
||||||
|
|
||||||
if domain && hostname do
|
if domain && root_domain do
|
||||||
SipHash.hash!(salt, user_agent <> ip_address <> domain <> hostname)
|
SipHash.hash!(salt, user_agent <> ip_address <> domain <> root_domain)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp get_root_domain(hostname) when is_binary(hostname) do
|
||||||
|
PublicSuffix.registrable_domain(hostname)
|
||||||
|
end
|
||||||
|
defp get_root_domain(hostname), do: hostname
|
||||||
|
|
||||||
defp calculate_screen_size(nil), do: nil
|
defp calculate_screen_size(nil), do: nil
|
||||||
defp calculate_screen_size(width) when width < 576, do: "Mobile"
|
defp calculate_screen_size(width) when width < 576, do: "Mobile"
|
||||||
defp calculate_screen_size(width) when width < 992, do: "Tablet"
|
defp calculate_screen_size(width) when width < 992, do: "Tablet"
|
||||||
|
3
mix.exs
3
mix.exs
@ -96,7 +96,8 @@ defmodule Plausible.MixProject do
|
|||||||
{:kaffy, "~> 0.9.0"},
|
{:kaffy, "~> 0.9.0"},
|
||||||
{:envy, "~> 1.1.1"},
|
{:envy, "~> 1.1.1"},
|
||||||
{:phoenix_pagination, "~> 0.7.0"},
|
{:phoenix_pagination, "~> 0.7.0"},
|
||||||
{:hammer, "~> 6.0"}
|
{:hammer, "~> 6.0"},
|
||||||
|
{:public_suffix, git: "https://github.com/axelson/publicsuffix-elixir"}
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
1
mix.lock
1
mix.lock
@ -76,6 +76,7 @@
|
|||||||
"poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], [], "hexpm", "fec8660eb7733ee4117b85f55799fd3833eb769a6df71ccf8903e8dc5447cfce"},
|
"poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], [], "hexpm", "fec8660eb7733ee4117b85f55799fd3833eb769a6df71ccf8903e8dc5447cfce"},
|
||||||
"poolboy": {:hex, :poolboy, "1.5.2", "392b007a1693a64540cead79830443abf5762f5d30cf50bc95cb2c1aaafa006b", [:rebar3], [], "hexpm", "dad79704ce5440f3d5a3681c8590b9dc25d1a561e8f5a9c995281012860901e3"},
|
"poolboy": {:hex, :poolboy, "1.5.2", "392b007a1693a64540cead79830443abf5762f5d30cf50bc95cb2c1aaafa006b", [:rebar3], [], "hexpm", "dad79704ce5440f3d5a3681c8590b9dc25d1a561e8f5a9c995281012860901e3"},
|
||||||
"postgrex": {:hex, :postgrex, "0.15.9", "46f8fe6f25711aeb861c4d0ae09780facfdf3adbd2fb5594ead61504dd489bda", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "610719103e4cb2223d4ab78f9f0f3e720320eeca6011415ab4137ddef730adee"},
|
"postgrex": {:hex, :postgrex, "0.15.9", "46f8fe6f25711aeb861c4d0ae09780facfdf3adbd2fb5594ead61504dd489bda", [:mix], [{:connection, "~> 1.0", [hex: :connection, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "610719103e4cb2223d4ab78f9f0f3e720320eeca6011415ab4137ddef730adee"},
|
||||||
|
"public_suffix": {:git, "https://github.com/axelson/publicsuffix-elixir", "89372422ab8b433de508519ef474e39699fd11ca", []},
|
||||||
"ranch": {:hex, :ranch, "1.7.1", "6b1fab51b49196860b733a49c07604465a47bdb78aa10c1c16a3d199f7f8c881", [:rebar3], [], "hexpm", "451d8527787df716d99dc36162fca05934915db0b6141bbdac2ea8d3c7afc7d7"},
|
"ranch": {:hex, :ranch, "1.7.1", "6b1fab51b49196860b733a49c07604465a47bdb78aa10c1c16a3d199f7f8c881", [:rebar3], [], "hexpm", "451d8527787df716d99dc36162fca05934915db0b6141bbdac2ea8d3c7afc7d7"},
|
||||||
"ref_inspector": {:hex, :ref_inspector, "1.3.1", "bb0489a4c4299dcd633f2b7a60c41a01f5590789d0b28225a60be484e1fbe777", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}, {:yamerl, "~> 0.7", [hex: :yamerl, repo: "hexpm", optional: false]}], "hexpm", "3172eb1b08e5c69966f796e3fe0e691257546fa143a5eb0ecc18a6e39b233854"},
|
"ref_inspector": {:hex, :ref_inspector, "1.3.1", "bb0489a4c4299dcd633f2b7a60c41a01f5590789d0b28225a60be484e1fbe777", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}, {:yamerl, "~> 0.7", [hex: :yamerl, repo: "hexpm", optional: false]}], "hexpm", "3172eb1b08e5c69966f796e3fe0e691257546fa143a5eb0ecc18a6e39b233854"},
|
||||||
"sentry": {:hex, :sentry, "8.0.5", "5ca922b9238a50c7258b52f47364b2d545beda5e436c7a43965b34577f1ef61f", [:mix], [{:hackney, "~> 1.8", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:plug, "~> 1.6", [hex: :plug, repo: "hexpm", optional: true]}, {:plug_cowboy, "~> 2.3", [hex: :plug_cowboy, repo: "hexpm", optional: true]}], "hexpm", "4972839fdbf52e886d7b3e694c8adf421f764f2fa79036b88fb4742049bd4b7c"},
|
"sentry": {:hex, :sentry, "8.0.5", "5ca922b9238a50c7258b52f47364b2d545beda5e436c7a43965b34577f1ef61f", [:mix], [{:hackney, "~> 1.8", [hex: :hackney, repo: "hexpm", optional: true]}, {:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: true]}, {:plug, "~> 1.6", [hex: :plug, repo: "hexpm", optional: true]}, {:plug_cowboy, "~> 2.3", [hex: :plug_cowboy, repo: "hexpm", optional: true]}], "hexpm", "4972839fdbf52e886d7b3e694c8adf421f764f2fa79036b88fb4742049bd4b7c"},
|
||||||
|
@ -12,6 +12,16 @@ defmodule PlausibleWeb.Api.ExternalControllerTest do
|
|||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp get_events(domain) do
|
||||||
|
Plausible.Event.WriteBuffer.flush()
|
||||||
|
|
||||||
|
ClickhouseRepo.all(
|
||||||
|
from e in Plausible.ClickhouseEvent,
|
||||||
|
where: e.domain == ^domain,
|
||||||
|
order_by: [desc: e.timestamp]
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
@user_agent "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36"
|
@user_agent "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36"
|
||||||
|
|
||||||
describe "POST /api/event" do
|
describe "POST /api/event" do
|
||||||
@ -357,340 +367,475 @@ defmodule PlausibleWeb.Api.ExternalControllerTest do
|
|||||||
assert response(conn, 202) == ""
|
assert response(conn, 202) == ""
|
||||||
assert pageview.referrer_source == ""
|
assert pageview.referrer_source == ""
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
test "screen size is calculated from screen_width", %{conn: conn} do
|
test "screen size is calculated from screen_width", %{conn: conn} do
|
||||||
params = %{
|
params = %{
|
||||||
name: "pageview",
|
name: "pageview",
|
||||||
url: "http://gigride.live/",
|
url: "http://gigride.live/",
|
||||||
screen_width: 480,
|
screen_width: 480,
|
||||||
domain: "external-controller-test-16.com"
|
domain: "external-controller-test-16.com"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> put_req_header("user-agent", @user_agent)
|
||||||
|
|> post("/api/event", params)
|
||||||
|
|
||||||
|
pageview = get_event("external-controller-test-16.com")
|
||||||
|
|
||||||
|
assert response(conn, 202) == ""
|
||||||
|
assert pageview.screen_size == "Mobile"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "screen size is nil if screen_width is missing", %{conn: conn} do
|
||||||
|
params = %{
|
||||||
|
name: "pageview",
|
||||||
|
url: "http://gigride.live/",
|
||||||
|
domain: "external-controller-test-17.com"
|
||||||
|
}
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> put_req_header("user-agent", @user_agent)
|
||||||
|
|> post("/api/event", params)
|
||||||
|
|
||||||
|
pageview = get_event("external-controller-test-17.com")
|
||||||
|
|
||||||
|
assert response(conn, 202) == ""
|
||||||
|
assert pageview.screen_size == ""
|
||||||
|
end
|
||||||
|
|
||||||
|
test "can trigger a custom event", %{conn: conn} do
|
||||||
|
params = %{
|
||||||
|
name: "custom event",
|
||||||
|
url: "http://gigride.live/",
|
||||||
|
domain: "external-controller-test-18.com"
|
||||||
|
}
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> put_req_header("user-agent", @user_agent)
|
||||||
|
|> post("/api/event", params)
|
||||||
|
|
||||||
|
event = get_event("external-controller-test-18.com")
|
||||||
|
|
||||||
|
assert response(conn, 202) == ""
|
||||||
|
assert event.name == "custom event"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "casts custom props to string", %{conn: conn} do
|
||||||
|
params = %{
|
||||||
|
name: "Signup",
|
||||||
|
url: "http://gigride.live/",
|
||||||
|
domain: "custom-prop-test.com",
|
||||||
|
props:
|
||||||
|
Jason.encode!(%{
|
||||||
|
bool_test: true,
|
||||||
|
number_test: 12
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
conn =
|
|
||||||
conn
|
conn
|
||||||
|> put_req_header("user-agent", @user_agent)
|
|
||||||
|> post("/api/event", params)
|
|> post("/api/event", params)
|
||||||
|
|
||||||
pageview = get_event("external-controller-test-16.com")
|
event = get_event("custom-prop-test.com")
|
||||||
|
|
||||||
assert response(conn, 202) == ""
|
assert Map.get(event, :"meta.key") == ["bool_test", "number_test"]
|
||||||
assert pageview.screen_size == "Mobile"
|
assert Map.get(event, :"meta.value") == ["true", "12"]
|
||||||
end
|
end
|
||||||
|
|
||||||
test "screen size is nil if screen_width is missing", %{conn: conn} do
|
test "ignores malformed custom props", %{conn: conn} do
|
||||||
params = %{
|
params = %{
|
||||||
name: "pageview",
|
name: "Signup",
|
||||||
url: "http://gigride.live/",
|
url: "http://gigride.live/",
|
||||||
domain: "external-controller-test-17.com"
|
domain: "custom-prop-test-2.com",
|
||||||
}
|
props: "\"show-more:button\""
|
||||||
|
}
|
||||||
|
|
||||||
conn =
|
|
||||||
conn
|
conn
|
||||||
|> put_req_header("user-agent", @user_agent)
|
|
||||||
|> post("/api/event", params)
|
|> post("/api/event", params)
|
||||||
|
|
||||||
pageview = get_event("external-controller-test-17.com")
|
event = get_event("custom-prop-test-2.com")
|
||||||
|
|
||||||
assert response(conn, 202) == ""
|
assert Map.get(event, :"meta.key") == []
|
||||||
assert pageview.screen_size == ""
|
assert Map.get(event, :"meta.value") == []
|
||||||
end
|
end
|
||||||
|
|
||||||
test "can trigger a custom event", %{conn: conn} do
|
test "ignores a malformed referrer URL", %{conn: conn} do
|
||||||
params = %{
|
params = %{
|
||||||
name: "custom event",
|
name: "pageview",
|
||||||
url: "http://gigride.live/",
|
url: "http://gigride.live/",
|
||||||
domain: "external-controller-test-18.com"
|
referrer: "https:://twitter.com",
|
||||||
}
|
domain: "external-controller-test-19.com"
|
||||||
|
}
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> put_req_header("user-agent", @user_agent)
|
||||||
|
|> post("/api/event", params)
|
||||||
|
|
||||||
|
event = get_event("external-controller-test-19.com")
|
||||||
|
|
||||||
|
assert response(conn, 202) == ""
|
||||||
|
assert event.referrer == ""
|
||||||
|
end
|
||||||
|
|
||||||
|
# Fake data is set up in config/test.exs
|
||||||
|
test "looks up the country from the ip address", %{conn: conn} do
|
||||||
|
params = %{
|
||||||
|
name: "pageview",
|
||||||
|
domain: "external-controller-test-20.com",
|
||||||
|
url: "http://gigride.live/"
|
||||||
|
}
|
||||||
|
|
||||||
conn =
|
|
||||||
conn
|
conn
|
||||||
|> put_req_header("user-agent", @user_agent)
|
|> put_req_header("x-forwarded-for", "1.1.1.1")
|
||||||
|> post("/api/event", params)
|
|> post("/api/event", params)
|
||||||
|
|
||||||
event = get_event("external-controller-test-18.com")
|
pageview = get_event("external-controller-test-20.com")
|
||||||
|
|
||||||
assert response(conn, 202) == ""
|
assert pageview.country_code == "US"
|
||||||
assert event.name == "custom event"
|
end
|
||||||
end
|
|
||||||
|
|
||||||
test "casts custom props to string", %{conn: conn} do
|
test "scrubs port from x-forwarded-for", %{conn: conn} do
|
||||||
params = %{
|
params = %{
|
||||||
name: "Signup",
|
name: "pageview",
|
||||||
url: "http://gigride.live/",
|
domain: "external-controller-test-x-forwarded-for-port.com",
|
||||||
domain: "custom-prop-test.com",
|
url: "http://gigride.live/"
|
||||||
props:
|
}
|
||||||
Jason.encode!(%{
|
|
||||||
bool_test: true,
|
|
||||||
number_test: 12
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
conn
|
|
||||||
|> post("/api/event", params)
|
|
||||||
|
|
||||||
event = get_event("custom-prop-test.com")
|
|
||||||
|
|
||||||
assert Map.get(event, :"meta.key") == ["bool_test", "number_test"]
|
|
||||||
assert Map.get(event, :"meta.value") == ["true", "12"]
|
|
||||||
end
|
|
||||||
|
|
||||||
test "ignores malformed custom props", %{conn: conn} do
|
|
||||||
params = %{
|
|
||||||
name: "Signup",
|
|
||||||
url: "http://gigride.live/",
|
|
||||||
domain: "custom-prop-test-2.com",
|
|
||||||
props: "\"show-more:button\""
|
|
||||||
}
|
|
||||||
|
|
||||||
conn
|
|
||||||
|> post("/api/event", params)
|
|
||||||
|
|
||||||
event = get_event("custom-prop-test-2.com")
|
|
||||||
|
|
||||||
assert Map.get(event, :"meta.key") == []
|
|
||||||
assert Map.get(event, :"meta.value") == []
|
|
||||||
end
|
|
||||||
|
|
||||||
test "ignores a malformed referrer URL", %{conn: conn} do
|
|
||||||
params = %{
|
|
||||||
name: "pageview",
|
|
||||||
url: "http://gigride.live/",
|
|
||||||
referrer: "https:://twitter.com",
|
|
||||||
domain: "external-controller-test-19.com"
|
|
||||||
}
|
|
||||||
|
|
||||||
conn =
|
|
||||||
conn
|
conn
|
||||||
|> put_req_header("user-agent", @user_agent)
|
|> put_req_header("x-forwarded-for", "1.1.1.1:123")
|
||||||
|> post("/api/event", params)
|
|> post("/api/event", params)
|
||||||
|
|
||||||
event = get_event("external-controller-test-19.com")
|
pageview = get_event("external-controller-test-x-forwarded-for-port.com")
|
||||||
|
|
||||||
assert response(conn, 202) == ""
|
assert pageview.country_code == "US"
|
||||||
assert event.referrer == ""
|
end
|
||||||
end
|
|
||||||
|
|
||||||
# Fake data is set up in config/test.exs
|
test "works with ipv6 without port in x-forwarded-for", %{conn: conn} do
|
||||||
test "looks up the country from the ip address", %{conn: conn} do
|
params = %{
|
||||||
params = %{
|
name: "pageview",
|
||||||
name: "pageview",
|
domain: "external-controller-test-x-forwarded-for-ipv6.com",
|
||||||
domain: "external-controller-test-20.com",
|
url: "http://gigride.live/"
|
||||||
url: "http://gigride.live/"
|
}
|
||||||
}
|
|
||||||
|
|
||||||
conn
|
|
||||||
|> put_req_header("x-forwarded-for", "1.1.1.1")
|
|
||||||
|> post("/api/event", params)
|
|
||||||
|
|
||||||
pageview = get_event("external-controller-test-20.com")
|
|
||||||
|
|
||||||
assert pageview.country_code == "US"
|
|
||||||
end
|
|
||||||
|
|
||||||
test "scrubs port from x-forwarded-for", %{conn: conn} do
|
|
||||||
params = %{
|
|
||||||
name: "pageview",
|
|
||||||
domain: "external-controller-test-x-forwarded-for-port.com",
|
|
||||||
url: "http://gigride.live/"
|
|
||||||
}
|
|
||||||
|
|
||||||
conn
|
|
||||||
|> put_req_header("x-forwarded-for", "1.1.1.1:123")
|
|
||||||
|> post("/api/event", params)
|
|
||||||
|
|
||||||
pageview = get_event("external-controller-test-x-forwarded-for-port.com")
|
|
||||||
|
|
||||||
assert pageview.country_code == "US"
|
|
||||||
end
|
|
||||||
|
|
||||||
test "works with ipv6 without port in x-forwarded-for", %{conn: conn} do
|
|
||||||
params = %{
|
|
||||||
name: "pageview",
|
|
||||||
domain: "external-controller-test-x-forwarded-for-ipv6.com",
|
|
||||||
url: "http://gigride.live/"
|
|
||||||
}
|
|
||||||
|
|
||||||
conn
|
|
||||||
|> put_req_header("x-forwarded-for", "1:1: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"
|
|
||||||
end
|
|
||||||
|
|
||||||
test "works with ipv6 with a port number in x-forwarded-for", %{conn: conn} do
|
|
||||||
params = %{
|
|
||||||
name: "pageview",
|
|
||||||
domain: "external-controller-test-x-forwarded-for-ipv6-port.com",
|
|
||||||
url: "http://gigride.live/"
|
|
||||||
}
|
|
||||||
|
|
||||||
conn
|
|
||||||
|> put_req_header("x-forwarded-for", "[1:1: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"
|
|
||||||
end
|
|
||||||
|
|
||||||
test "uses cloudflare's special header for client IP address if present", %{conn: conn} do
|
|
||||||
params = %{
|
|
||||||
name: "pageview",
|
|
||||||
domain: "external-controller-test-cloudflare.com",
|
|
||||||
url: "http://gigride.live/"
|
|
||||||
}
|
|
||||||
|
|
||||||
conn
|
|
||||||
|> put_req_header("x-forwarded-for", "0.0.0.0")
|
|
||||||
|> put_req_header("cf-connecting-ip", "1.1.1.1")
|
|
||||||
|> post("/api/event", params)
|
|
||||||
|
|
||||||
pageview = get_event("external-controller-test-cloudflare.com")
|
|
||||||
|
|
||||||
assert pageview.country_code == "US"
|
|
||||||
end
|
|
||||||
|
|
||||||
test "Uses the Forwarded header when cf-connecting-ip and x-forwarded-for are missing", %{
|
|
||||||
conn: conn
|
|
||||||
} do
|
|
||||||
params = %{
|
|
||||||
name: "pageview",
|
|
||||||
domain: "external-controller-test-forwarded.com",
|
|
||||||
url: "http://gigride.live/"
|
|
||||||
}
|
|
||||||
|
|
||||||
conn
|
|
||||||
|> put_req_header("forwarded", "by=0.0.0.0;for=1.1.1.1;host=somehost.com;proto=https")
|
|
||||||
|> post("/api/event", params)
|
|
||||||
|
|
||||||
pageview = get_event("external-controller-test-forwarded.com")
|
|
||||||
|
|
||||||
assert pageview.country_code == "US"
|
|
||||||
end
|
|
||||||
|
|
||||||
test "Forwarded header can parse ipv6", %{conn: conn} do
|
|
||||||
params = %{
|
|
||||||
name: "pageview",
|
|
||||||
domain: "external-controller-test-forwarded-ipv6.com",
|
|
||||||
url: "http://gigride.live/"
|
|
||||||
}
|
|
||||||
|
|
||||||
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"
|
|
||||||
)
|
|
||||||
|> post("/api/event", params)
|
|
||||||
|
|
||||||
pageview = get_event("external-controller-test-forwarded-ipv6.com")
|
|
||||||
|
|
||||||
assert pageview.country_code == "US"
|
|
||||||
end
|
|
||||||
|
|
||||||
test "URL is decoded", %{conn: conn} do
|
|
||||||
params = %{
|
|
||||||
name: "pageview",
|
|
||||||
url:
|
|
||||||
"http://www.example.com/opportunity/category/%D8%AC%D9%88%D8%A7%D8%A6%D8%B2-%D9%88%D9%85%D8%B3%D8%A7%D8%A8%D9%82%D8%A7%D8%AA",
|
|
||||||
domain: "external-controller-test-21.com"
|
|
||||||
}
|
|
||||||
|
|
||||||
conn
|
|
||||||
|> post("/api/event", params)
|
|
||||||
|
|
||||||
pageview = get_event("external-controller-test-21.com")
|
|
||||||
|
|
||||||
assert pageview.pathname == "/opportunity/category/جوائز-ومسابقات"
|
|
||||||
end
|
|
||||||
|
|
||||||
test "accepts shorthand map keys", %{conn: conn} do
|
|
||||||
params = %{
|
|
||||||
n: "pageview",
|
|
||||||
u: "http://www.example.com/opportunity",
|
|
||||||
d: "external-controller-test-22.com",
|
|
||||||
r: "https://facebook.com/page",
|
|
||||||
w: 300
|
|
||||||
}
|
|
||||||
|
|
||||||
conn
|
|
||||||
|> post("/api/event", params)
|
|
||||||
|
|
||||||
pageview = get_event("external-controller-test-22.com")
|
|
||||||
|
|
||||||
assert pageview.pathname == "/opportunity"
|
|
||||||
assert pageview.referrer_source == "Facebook"
|
|
||||||
assert pageview.referrer == "facebook.com/page"
|
|
||||||
assert pageview.screen_size == "Mobile"
|
|
||||||
end
|
|
||||||
|
|
||||||
test "records hash when in hash mode", %{conn: conn} do
|
|
||||||
params = %{
|
|
||||||
n: "pageview",
|
|
||||||
u: "http://www.example.com/#page-a",
|
|
||||||
d: "external-controller-test-23.com",
|
|
||||||
h: 1
|
|
||||||
}
|
|
||||||
|
|
||||||
conn
|
|
||||||
|> post("/api/event", params)
|
|
||||||
|
|
||||||
pageview = get_event("external-controller-test-23.com")
|
|
||||||
|
|
||||||
assert pageview.pathname == "/#page-a"
|
|
||||||
end
|
|
||||||
|
|
||||||
test "decodes URL pathname, fragment and search", %{conn: conn} do
|
|
||||||
params = %{
|
|
||||||
n: "pageview",
|
|
||||||
u:
|
|
||||||
"https://test.com/%EF%BA%9D%EF%BB%AD%EF%BA%8E%EF%BA%8B%EF%BA%AF-%EF%BB%AE%EF%BB%A4%EF%BA%B3%EF%BA%8E%EF%BA%92%EF%BB%97%EF%BA%8E%EF%BA%97?utm_source=%25balle%25",
|
|
||||||
d: "url-decode-test.com",
|
|
||||||
h: 1
|
|
||||||
}
|
|
||||||
|
|
||||||
conn
|
|
||||||
|> post("/api/event", params)
|
|
||||||
|
|
||||||
pageview = get_event("url-decode-test.com")
|
|
||||||
|
|
||||||
assert pageview.hostname == "test.com"
|
|
||||||
assert pageview.pathname == "/ﺝﻭﺎﺋﺯ-ﻮﻤﺳﺎﺒﻗﺎﺗ"
|
|
||||||
assert pageview.utm_source == "%balle%"
|
|
||||||
end
|
|
||||||
|
|
||||||
test "can use double quotes in query params", %{conn: conn} do
|
|
||||||
q = URI.encode_query(%{"utm_source" => "Something \"quoted\""})
|
|
||||||
|
|
||||||
params = %{
|
|
||||||
n: "pageview",
|
|
||||||
u: "https://test.com/?" <> q,
|
|
||||||
d: "quote-encode-test.com",
|
|
||||||
h: 1
|
|
||||||
}
|
|
||||||
|
|
||||||
conn
|
|
||||||
|> post("/api/event", params)
|
|
||||||
|
|
||||||
pageview = get_event("quote-encode-test.com")
|
|
||||||
|
|
||||||
assert pageview.utm_source == "Something \"quoted\""
|
|
||||||
end
|
|
||||||
|
|
||||||
test "responds 400 when required fields are missing", %{conn: conn} do
|
|
||||||
params = %{
|
|
||||||
domain: "some-domain.com",
|
|
||||||
name: "pageview"
|
|
||||||
}
|
|
||||||
|
|
||||||
conn =
|
|
||||||
conn
|
conn
|
||||||
|> put_req_header("user-agent", @user_agent)
|
|> put_req_header("x-forwarded-for", "1:1:1:1:1:1:1:1")
|
||||||
|> post("/api/event", params)
|
|> post("/api/event", params)
|
||||||
|
|
||||||
assert response(conn, 400) == ""
|
pageview = get_event("external-controller-test-x-forwarded-for-ipv6.com")
|
||||||
|
|
||||||
|
assert pageview.country_code == "US"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "works with ipv6 with a port number in x-forwarded-for", %{conn: conn} do
|
||||||
|
params = %{
|
||||||
|
name: "pageview",
|
||||||
|
domain: "external-controller-test-x-forwarded-for-ipv6-port.com",
|
||||||
|
url: "http://gigride.live/"
|
||||||
|
}
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> put_req_header("x-forwarded-for", "[1:1: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"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "uses cloudflare's special header for client IP address if present", %{conn: conn} do
|
||||||
|
params = %{
|
||||||
|
name: "pageview",
|
||||||
|
domain: "external-controller-test-cloudflare.com",
|
||||||
|
url: "http://gigride.live/"
|
||||||
|
}
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> put_req_header("x-forwarded-for", "0.0.0.0")
|
||||||
|
|> put_req_header("cf-connecting-ip", "1.1.1.1")
|
||||||
|
|> post("/api/event", params)
|
||||||
|
|
||||||
|
pageview = get_event("external-controller-test-cloudflare.com")
|
||||||
|
|
||||||
|
assert pageview.country_code == "US"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "Uses the Forwarded header when cf-connecting-ip and x-forwarded-for are missing", %{
|
||||||
|
conn: conn
|
||||||
|
} do
|
||||||
|
params = %{
|
||||||
|
name: "pageview",
|
||||||
|
domain: "external-controller-test-forwarded.com",
|
||||||
|
url: "http://gigride.live/"
|
||||||
|
}
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> put_req_header("forwarded", "by=0.0.0.0;for=1.1.1.1;host=somehost.com;proto=https")
|
||||||
|
|> post("/api/event", params)
|
||||||
|
|
||||||
|
pageview = get_event("external-controller-test-forwarded.com")
|
||||||
|
|
||||||
|
assert pageview.country_code == "US"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "Forwarded header can parse ipv6", %{conn: conn} do
|
||||||
|
params = %{
|
||||||
|
name: "pageview",
|
||||||
|
domain: "external-controller-test-forwarded-ipv6.com",
|
||||||
|
url: "http://gigride.live/"
|
||||||
|
}
|
||||||
|
|
||||||
|
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"
|
||||||
|
)
|
||||||
|
|> post("/api/event", params)
|
||||||
|
|
||||||
|
pageview = get_event("external-controller-test-forwarded-ipv6.com")
|
||||||
|
|
||||||
|
assert pageview.country_code == "US"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "URL is decoded", %{conn: conn} do
|
||||||
|
params = %{
|
||||||
|
name: "pageview",
|
||||||
|
url:
|
||||||
|
"http://www.example.com/opportunity/category/%D8%AC%D9%88%D8%A7%D8%A6%D8%B2-%D9%88%D9%85%D8%B3%D8%A7%D8%A8%D9%82%D8%A7%D8%AA",
|
||||||
|
domain: "external-controller-test-21.com"
|
||||||
|
}
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> post("/api/event", params)
|
||||||
|
|
||||||
|
pageview = get_event("external-controller-test-21.com")
|
||||||
|
|
||||||
|
assert pageview.pathname == "/opportunity/category/جوائز-ومسابقات"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "accepts shorthand map keys", %{conn: conn} do
|
||||||
|
params = %{
|
||||||
|
n: "pageview",
|
||||||
|
u: "http://www.example.com/opportunity",
|
||||||
|
d: "external-controller-test-22.com",
|
||||||
|
r: "https://facebook.com/page",
|
||||||
|
w: 300
|
||||||
|
}
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> post("/api/event", params)
|
||||||
|
|
||||||
|
pageview = get_event("external-controller-test-22.com")
|
||||||
|
|
||||||
|
assert pageview.pathname == "/opportunity"
|
||||||
|
assert pageview.referrer_source == "Facebook"
|
||||||
|
assert pageview.referrer == "facebook.com/page"
|
||||||
|
assert pageview.screen_size == "Mobile"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "records hash when in hash mode", %{conn: conn} do
|
||||||
|
params = %{
|
||||||
|
n: "pageview",
|
||||||
|
u: "http://www.example.com/#page-a",
|
||||||
|
d: "external-controller-test-23.com",
|
||||||
|
h: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> post("/api/event", params)
|
||||||
|
|
||||||
|
pageview = get_event("external-controller-test-23.com")
|
||||||
|
|
||||||
|
assert pageview.pathname == "/#page-a"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "decodes URL pathname, fragment and search", %{conn: conn} do
|
||||||
|
params = %{
|
||||||
|
n: "pageview",
|
||||||
|
u:
|
||||||
|
"https://test.com/%EF%BA%9D%EF%BB%AD%EF%BA%8E%EF%BA%8B%EF%BA%AF-%EF%BB%AE%EF%BB%A4%EF%BA%B3%EF%BA%8E%EF%BA%92%EF%BB%97%EF%BA%8E%EF%BA%97?utm_source=%25balle%25",
|
||||||
|
d: "url-decode-test.com",
|
||||||
|
h: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> post("/api/event", params)
|
||||||
|
|
||||||
|
pageview = get_event("url-decode-test.com")
|
||||||
|
|
||||||
|
assert pageview.hostname == "test.com"
|
||||||
|
assert pageview.pathname == "/ﺝﻭﺎﺋﺯ-ﻮﻤﺳﺎﺒﻗﺎﺗ"
|
||||||
|
assert pageview.utm_source == "%balle%"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "can use double quotes in query params", %{conn: conn} do
|
||||||
|
q = URI.encode_query(%{"utm_source" => "Something \"quoted\""})
|
||||||
|
|
||||||
|
params = %{
|
||||||
|
n: "pageview",
|
||||||
|
u: "https://test.com/?" <> q,
|
||||||
|
d: "quote-encode-test.com",
|
||||||
|
h: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> post("/api/event", params)
|
||||||
|
|
||||||
|
pageview = get_event("quote-encode-test.com")
|
||||||
|
|
||||||
|
assert pageview.utm_source == "Something \"quoted\""
|
||||||
|
end
|
||||||
|
|
||||||
|
test "responds 400 when required fields are missing", %{conn: conn} do
|
||||||
|
params = %{
|
||||||
|
domain: "some-domain.com",
|
||||||
|
name: "pageview"
|
||||||
|
}
|
||||||
|
|
||||||
|
conn =
|
||||||
|
conn
|
||||||
|
|> put_req_header("user-agent", @user_agent)
|
||||||
|
|> post("/api/event", params)
|
||||||
|
|
||||||
|
assert response(conn, 400) == ""
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "user_id generation" do
|
||||||
|
test "with same IP address and user agent, the same user ID is generated", %{conn: conn} do
|
||||||
|
params = %{
|
||||||
|
url: "https://user-id-test-domain.com/",
|
||||||
|
domain: "user-id-test-domain.com",
|
||||||
|
name: "pageview"
|
||||||
|
}
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> put_req_header("user-agent", @user_agent)
|
||||||
|
|> put_req_header("x-forwarded-for", "127.0.0.1")
|
||||||
|
|> post("/api/event", params)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> put_req_header("user-agent", @user_agent)
|
||||||
|
|> put_req_header("x-forwarded-for", "127.0.0.1")
|
||||||
|
|> post("/api/event", params)
|
||||||
|
|
||||||
|
[one, two] = get_events("user-id-test-domain.com")
|
||||||
|
|
||||||
|
assert one.user_id == two.user_id
|
||||||
|
end
|
||||||
|
|
||||||
|
test "different IP address results in different user ID", %{conn: conn} do
|
||||||
|
params = %{
|
||||||
|
url: "https://user-id-test-domain.com/",
|
||||||
|
domain: "user-id-test-domain-2.com",
|
||||||
|
name: "pageview"
|
||||||
|
}
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> put_req_header("user-agent", @user_agent)
|
||||||
|
|> put_req_header("x-forwarded-for", "127.0.0.1")
|
||||||
|
|> post("/api/event", params)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> put_req_header("user-agent", @user_agent)
|
||||||
|
|> put_req_header("x-forwarded-for", "127.0.0.2")
|
||||||
|
|> post("/api/event", params)
|
||||||
|
|
||||||
|
[one, two] = get_events("user-id-test-domain-2.com")
|
||||||
|
|
||||||
|
assert one.user_id != two.user_id
|
||||||
|
end
|
||||||
|
|
||||||
|
test "different user agent results in different user ID", %{conn: conn} do
|
||||||
|
params = %{
|
||||||
|
url: "https://user-id-test-domain.com/",
|
||||||
|
domain: "user-id-test-domain-3.com",
|
||||||
|
name: "pageview"
|
||||||
|
}
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> put_req_header("user-agent", @user_agent)
|
||||||
|
|> put_req_header("x-forwarded-for", "127.0.0.1")
|
||||||
|
|> post("/api/event", params)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> put_req_header("user-agent", @user_agent <> "!!")
|
||||||
|
|> put_req_header("x-forwarded-for", "127.0.0.1")
|
||||||
|
|> post("/api/event", params)
|
||||||
|
|
||||||
|
[one, two] = get_events("user-id-test-domain-3.com")
|
||||||
|
|
||||||
|
assert one.user_id != two.user_id
|
||||||
|
end
|
||||||
|
|
||||||
|
test "different domain value results in different user ID", %{conn: conn} do
|
||||||
|
params = %{
|
||||||
|
url: "https://user-id-test-domain.com/",
|
||||||
|
domain: "user-id-test-domain-4.com",
|
||||||
|
name: "pageview"
|
||||||
|
}
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> put_req_header("user-agent", @user_agent)
|
||||||
|
|> put_req_header("x-forwarded-for", "127.0.0.1")
|
||||||
|
|> post("/api/event", params)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> put_req_header("user-agent", @user_agent)
|
||||||
|
|> put_req_header("x-forwarded-for", "127.0.0.1")
|
||||||
|
|> post("/api/event", Map.put(params, :domain, "other-domain.com"))
|
||||||
|
|
||||||
|
one = get_event("user-id-test-domain-4.com")
|
||||||
|
two = get_event("other-domain.com")
|
||||||
|
|
||||||
|
assert one.user_id != two.user_id
|
||||||
|
end
|
||||||
|
|
||||||
|
test "different hostname results in different user ID", %{conn: conn} do
|
||||||
|
params = %{
|
||||||
|
url: "https://user-id-test-domain.com/",
|
||||||
|
domain: "user-id-test-domain-5.com",
|
||||||
|
name: "pageview"
|
||||||
|
}
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> put_req_header("user-agent", @user_agent)
|
||||||
|
|> put_req_header("x-forwarded-for", "127.0.0.1")
|
||||||
|
|> post("/api/event", params)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> put_req_header("user-agent", @user_agent)
|
||||||
|
|> put_req_header("x-forwarded-for", "127.0.0.1")
|
||||||
|
|> post("/api/event", Map.put(params, :url, "https://other-domain.com/"))
|
||||||
|
|
||||||
|
[one, two] = get_events("user-id-test-domain-5.com")
|
||||||
|
|
||||||
|
assert one.user_id != two.user_id
|
||||||
|
end
|
||||||
|
|
||||||
|
test "different hostname results in the same user ID when the root domain in the same", %{conn: conn} do
|
||||||
|
params = %{
|
||||||
|
url: "https://user-id-test-domain.com/",
|
||||||
|
domain: "user-id-test-domain-6.com",
|
||||||
|
name: "pageview"
|
||||||
|
}
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> put_req_header("user-agent", @user_agent)
|
||||||
|
|> put_req_header("x-forwarded-for", "127.0.0.1")
|
||||||
|
|> post("/api/event", params)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> put_req_header("user-agent", @user_agent)
|
||||||
|
|> put_req_header("x-forwarded-for", "127.0.0.1")
|
||||||
|
|> post("/api/event", Map.put(params, :url, "https://app.user-id-test-domain.com/"))
|
||||||
|
|
||||||
|
[one, two] = get_events("user-id-test-domain-6.com")
|
||||||
|
|
||||||
|
assert one.user_id == two.user_id
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "GET /api/health" do
|
describe "GET /api/health" do
|
||||||
|
Loading…
Reference in New Issue
Block a user