<%= link("← Back to Sites",
diff --git a/lib/plausible_web/templates/site/settings_people.html.heex b/lib/plausible_web/templates/site/settings_people.html.heex
index 74f2b569643e..496852f14289 100644
--- a/lib/plausible_web/templates/site/settings_people.html.heex
+++ b/lib/plausible_web/templates/site/settings_people.html.heex
@@ -1,5 +1,5 @@
<.settings_tiles>
- <.tile docs="user-roles">
+ <.tile docs="users-roles">
<:title>People
<:subtitle>Invite your friends or coworkers
diff --git a/mix.exs b/mix.exs
index ee9adbf52447..bff10a52e8a9 100644
--- a/mix.exs
+++ b/mix.exs
@@ -63,13 +63,12 @@ defmodule Plausible.MixProject do
defp deps do
[
{:bamboo, "~> 2.3", override: true},
- {:bamboo_phoenix, "~> 1.0.0"},
{:bamboo_postmark, git: "https://github.com/plausible/bamboo_postmark.git", branch: "main"},
{:bamboo_smtp, "~> 4.1"},
{:bamboo_mua, "~> 0.2.0"},
{:bcrypt_elixir, "~> 3.0"},
{:bypass, "~> 2.1", only: [:dev, :test, :ce_test]},
- {:ecto_ch, "~> 0.3.9"},
+ {:ecto_ch, "~> 0.5.0"},
{:cloak, "~> 1.1"},
{:cloak_ecto, "~> 1.2"},
{:combination, "~> 0.0.3"},
diff --git a/mix.lock b/mix.lock
index bc915b942b49..59456e4ff966 100644
--- a/mix.lock
+++ b/mix.lock
@@ -2,15 +2,14 @@
"acceptor_pool": {:hex, :acceptor_pool, "1.0.0", "43c20d2acae35f0c2bcd64f9d2bde267e459f0f3fd23dab26485bf518c281b21", [:rebar3], [], "hexpm", "0cbcd83fdc8b9ad2eee2067ef8b91a14858a5883cb7cd800e6fcd5803e158788"},
"bamboo": {:hex, :bamboo, "2.3.0", "d2392a2cabe91edf488553d3c70638b532e8db7b76b84b0a39e3dfe492ffd6fc", [:mix], [{:hackney, ">= 1.15.2", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:mime, "~> 1.4 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "dd0037e68e108fd04d0e8773921512c940e35d981e097b5793543e3b2f9cd3f6"},
"bamboo_mua": {:hex, :bamboo_mua, "0.2.2", "c50cd41ef684155669e2d99d428fbb87e13797a80829a162b47d3c0a7f7e7ecd", [:mix], [{:bamboo, "~> 2.0", [hex: :bamboo, repo: "hexpm", optional: false]}, {:mail, "~> 0.3.0", [hex: :mail, repo: "hexpm", optional: false]}, {:mua, "~> 0.2.3", [hex: :mua, repo: "hexpm", optional: false]}], "hexpm", "5fe6e3676640578c6fe8f040b34dda8991ebef8566c0601a984eb4771b85b11f"},
- "bamboo_phoenix": {:hex, :bamboo_phoenix, "1.0.0", "f3cc591ffb163ed0bf935d256f1f4645cd870cf436545601215745fb9cc9953f", [:mix], [{:bamboo, ">= 2.0.0", [hex: :bamboo, repo: "hexpm", optional: false]}, {:phoenix, ">= 1.3.0", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "6db88fbb26019c84a47994bb2bd879c0887c29ce6c559bc6385fd54eb8b37dee"},
"bamboo_postmark": {:git, "https://github.com/plausible/bamboo_postmark.git", "5eac6dfdffacd273bd9aacdd3e494a600bb0b170", [branch: "main"]},
"bamboo_smtp": {:hex, :bamboo_smtp, "4.2.2", "e9f57a2300df9cb496c48751bd7668a86a2b89aa2e79ccaa34e0c46a5f64c3ae", [:mix], [{:bamboo, "~> 2.2.0", [hex: :bamboo, repo: "hexpm", optional: false]}, {:gen_smtp, "~> 1.2.0", [hex: :gen_smtp, repo: "hexpm", optional: false]}], "hexpm", "28cac2ec8adaae02aed663bf68163992891a3b44cfd7ada0bebe3e09bed7207f"},
"bcrypt_elixir": {:hex, :bcrypt_elixir, "3.1.0", "0b110a9a6c619b19a7f73fa3004aa11d6e719a67e672d1633dc36b6b2290a0f7", [:make, :mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "2ad2acb5a8bc049e8d5aa267802631912bb80d5f4110a178ae7999e69dca1bf7"},
"bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"},
"bypass": {:hex, :bypass, "2.1.0", "909782781bf8e20ee86a9cabde36b259d44af8b9f38756173e8f5e2e1fabb9b1", [:mix], [{:plug, "~> 1.7", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.0", [hex: :plug_cowboy, repo: "hexpm", optional: false]}, {:ranch, "~> 1.3", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "d9b5df8fa5b7a6efa08384e9bbecfe4ce61c77d28a4282f79e02f1ef78d96b80"},
- "castore": {:hex, :castore, "1.0.8", "dedcf20ea746694647f883590b82d9e96014057aff1d44d03ec90f36a5c0dc6e", [:mix], [], "hexpm", "0b2b66d2ee742cb1d9cb8c8be3b43c3a70ee8651f37b75a8b982e036752983f1"},
+ "castore": {:hex, :castore, "1.0.9", "5cc77474afadf02c7c017823f460a17daa7908e991b0cc917febc90e466a375c", [:mix], [], "hexpm", "5ea956504f1ba6f2b4eb707061d8e17870de2bee95fb59d512872c2ef06925e7"},
"certifi": {:hex, :certifi, "2.12.0", "2d1cca2ec95f59643862af91f001478c9863c2ac9cb6e2f89780bfd8de987329", [:rebar3], [], "hexpm", "ee68d85df22e554040cdb4be100f33873ac6051387baf6a8f6ce82272340ff1c"},
- "ch": {:hex, :ch, "0.2.7", "29565d4ee8b0ae11df03f308f1cf4dfc04dbebe169a3d565d7c9283c18384af2", [:mix], [{:db_connection, "~> 2.0", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:ecto, "~> 3.12", [hex: :ecto, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: false]}], "hexpm", "3a906077411b0f39fb6d19f599b91f746d6a55674333f83272c6bed12055efa5"},
+ "ch": {:hex, :ch, "0.2.9", "8273e27b741f2a31410c0c6291700abfbd262d0d9bd70b51c0deef624d6079b8", [:mix], [{:db_connection, "~> 2.0", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:ecto, "~> 3.12", [hex: :ecto, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mint, "~> 1.0", [hex: :mint, repo: "hexpm", optional: false]}], "hexpm", "889a12ad2dae69a6136b7109cbc73ba4f0d719f48d1a4c567ad3f95ad752a9c9"},
"chatterbox": {:hex, :ts_chatterbox, "0.15.1", "5cac4d15dd7ad61fc3c4415ce4826fc563d4643dee897a558ec4ea0b1c835c9c", [:rebar3], [{:hpack, "~> 0.3.0", [hex: :hpack_erl, repo: "hexpm", optional: false]}], "hexpm", "4f75b91451338bc0da5f52f3480fa6ef6e3a2aeecfc33686d6b3d0a0948f31aa"},
"cldr_utils": {:hex, :cldr_utils, "2.27.0", "a75d5cdaaf6b7432eb10f547e6abe635c94746985c5b78e35bbbd08b16473b6c", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:certifi, "~> 2.5", [hex: :certifi, repo: "hexpm", optional: true]}, {:decimal, "~> 1.9 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}], "hexpm", "516f601e28da10b8f1f3af565321c4e3da3b898a0b50a5e5be425eff76d587e1"},
"cloak": {:hex, :cloak, "1.1.2", "7e0006c2b0b98d976d4f559080fabefd81f0e0a50a3c4b621f85ceeb563e80bb", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "940d5ac4fcd51b252930fd112e319ea5ae6ab540b722f3ca60a85666759b9585"},
@@ -31,10 +30,10 @@
"digital_token": {:hex, :digital_token, "0.6.0", "13e6de581f0b1f6c686f7c7d12ab11a84a7b22fa79adeb4b50eec1a2d278d258", [:mix], [{:cldr_utils, "~> 2.17", [hex: :cldr_utils, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}], "hexpm", "2455d626e7c61a128b02a4a8caddb092548c3eb613ac6f6a85e4cbb6caddc4d1"},
"double": {:hex, :double, "0.8.2", "8e1cfcccdaef76c18846bc08e555555a2a699b806fa207b6468572a60513cc6a", [:mix], [], "hexpm", "90287642b2ec86125e0457aaba2ab0e80f7d7050cc80a0cef733e59bd70aa67c"},
"earmark_parser": {:hex, :earmark_parser, "1.4.39", "424642f8335b05bb9eb611aa1564c148a8ee35c9c8a8bba6e129d51a3e3c6769", [:mix], [], "hexpm", "06553a88d1f1846da9ef066b87b57c6f605552cfbe40d20bd8d59cc6bde41944"},
- "ecto": {:hex, :ecto, "3.12.2", "bae2094f038e9664ce5f089e5f3b6132a535d8b018bd280a485c2f33df5c0ce1", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "492e67c70f3a71c6afe80d946d3ced52ecc57c53c9829791bfff1830ff5a1f0c"},
- "ecto_ch": {:hex, :ecto_ch, "0.3.9", "220ef4452aaccbc2bcb80f02a31ac24ef4febf095d672f17fcd22ec0c626b63e", [:mix], [{:ch, "~> 0.2.7", [hex: :ch, repo: "hexpm", optional: false]}, {:ecto_sql, "~> 3.12", [hex: :ecto_sql, repo: "hexpm", optional: false]}], "hexpm", "7ab1909d06462e20eb5fbff9564042942ee72589983bc3789d354e88a2fa6b7c"},
+ "ecto": {:hex, :ecto, "3.12.4", "267c94d9f2969e6acc4dd5e3e3af5b05cdae89a4d549925f3008b2b7eb0b93c3", [:mix], [{:decimal, "~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "ef04e4101688a67d061e1b10d7bc1fbf00d1d13c17eef08b71d070ff9188f747"},
+ "ecto_ch": {:hex, :ecto_ch, "0.5.0", "f65dcc3b7b0c85726259471a91c34045852ce8b8817ea29becb3afdb28b3e987", [:mix], [{:ch, "~> 0.2.7", [hex: :ch, repo: "hexpm", optional: false]}, {:ecto_sql, "~> 3.12", [hex: :ecto_sql, repo: "hexpm", optional: false]}], "hexpm", "c8bb1c75e20983f16b285d7df21825ce2e3ba15d690bab930ea4133568ae2136"},
"ecto_network": {:hex, :ecto_network, "1.5.0", "a930c910975e7a91237b858ebf0f4ad7b2aae32fa846275aa203cb858459ec73", [:mix], [{:ecto_sql, ">= 3.0.0", [hex: :ecto_sql, repo: "hexpm", optional: false]}, {:phoenix_html, ">= 0.0.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:postgrex, ">= 0.14.0", [hex: :postgrex, repo: "hexpm", optional: false]}], "hexpm", "4d614434ae3e6d373a2f693d56aafaa3f3349714668ffd6d24e760caf578aa2f"},
- "ecto_sql": {:hex, :ecto_sql, "3.12.0", "73cea17edfa54bde76ee8561b30d29ea08f630959685006d9c6e7d1e59113b7d", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.12", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.7", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.19 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "dc9e4d206f274f3947e96142a8fdc5f69a2a6a9abb4649ef5c882323b6d512f0"},
+ "ecto_sql": {:hex, :ecto_sql, "3.12.1", "c0d0d60e85d9ff4631f12bafa454bc392ce8b9ec83531a412c12a0d415a3a4d0", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.12", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.7", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.19 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "aff5b958a899762c5f09028c847569f7dfb9cc9d63bdb8133bff8a5546de6bf5"},
"elixir_make": {:hex, :elixir_make, "0.7.7", "7128c60c2476019ed978210c245badf08b03dbec4f24d05790ef791da11aa17c", [:mix], [{:castore, "~> 0.1 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}], "hexpm", "5bc19fff950fad52bbe5f211b12db9ec82c6b34a9647da0c2224b8b8464c7e6c"},
"envy": {:hex, :envy, "1.1.1", "0bc9bd654dec24fcdf203f7c5aa1b8f30620f12cfb28c589d5e9c38fe1b07475", [:mix], [], "hexpm", "7061eb1a47415fd757145d8dec10dc0b1e48344960265cb108f194c4252c3a89"},
"eqrcode": {:hex, :eqrcode, "0.1.10", "6294fece9d68ad64eef1c3c92cf111cfd6469f4fbf230a2d4cc905a682178f3f", [:mix], [], "hexpm", "da30e373c36a0fd37ab6f58664b16029919896d6c45a68a95cc4d713e81076f1"},
@@ -86,7 +85,7 @@
"mjml": {:hex, :mjml, "3.1.0", "549e985bc03be1af563c62a34c8e62bdb8d0baaa6b31af705a5bdf67e20f22b7", [:mix], [{:rustler, ">= 0.0.0", [hex: :rustler, repo: "hexpm", optional: true]}, {:rustler_precompiled, "~> 0.7.0", [hex: :rustler_precompiled, repo: "hexpm", optional: false]}], "hexpm", "987674d296b14b628e5e5d2d8b910e6501cdfafa0239527d8b633880dc595344"},
"mjml_eex": {:hex, :mjml_eex, "0.11.0", "f0845730f4caccddea7c98ab5ad1485831446b7c09896fa5ed54b3fa0c431e72", [:mix], [{:erlexec, "~> 2.0", [hex: :erlexec, repo: "hexpm", optional: true]}, {:mjml, "~> 1.0 or ~> 2.0 or ~> 3.0", [hex: :mjml, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.2 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "0c60732fe766336ec504a94cad4ebf30405f05fa8920a544ff0ef936252438ac"},
"mox": {:hex, :mox, "1.1.0", "0f5e399649ce9ab7602f72e718305c0f9cdc351190f72844599545e4996af73c", [:mix], [], "hexpm", "d44474c50be02d5b72131070281a5d3895c0e7a95c780e90bc0cfe712f633a13"},
- "mua": {:hex, :mua, "0.2.3", "46b29b7b2bb14105c0b7be9526f7c452df17a7841b30b69871c024a822ff551c", [:mix], [{:castore, "~> 0.1.0 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}], "hexpm", "7fe861a87fcc06a980d3941bbcb2634e5f0f30fd6ad15ef6c0423ff9dc7e46de"},
+ "mua": {:hex, :mua, "0.2.4", "a9172ab0a1ac8732cf2699d739ceac3febcb9b4ffc540260ad2e32c0b6632af9", [:mix], [{:castore, "~> 0.1.0 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}], "hexpm", "e7e4dacd5ad65f13e3542772e74a159c00bd2d5579e729e9bb72d2c73a266fb7"},
"nanoid": {:hex, :nanoid, "2.1.0", "d192a5bf1d774258bc49762b480fca0e3128178fa6d35a464af2a738526607fd", [:mix], [], "hexpm", "ebc7a342d02d213534a7f93a091d569b9fea7f26fcd3a638dc655060fc1f76ac"},
"nimble_csv": {:hex, :nimble_csv, "1.2.0", "4e26385d260c61eba9d4412c71cea34421f296d5353f914afe3f2e71cce97722", [:mix], [], "hexpm", "d0628117fcc2148178b034044c55359b26966c6eaa8e2ce15777be3bbc91b12a"},
"nimble_options": {:hex, :nimble_options, "1.1.1", "e3a492d54d85fc3fd7c5baf411d9d2852922f66e69476317787a7b2bb000a61b", [:mix], [], "hexpm", "821b2470ca9442c4b6984882fe9bb0389371b8ddec4d45a9504f00a66f650b44"},
@@ -124,7 +123,7 @@
"plug": {:hex, :plug, "1.16.1", "40c74619c12f82736d2214557dedec2e9762029b2438d6d175c5074c933edc9d", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a13ff6b9006b03d7e33874945b2755253841b238c34071ed85b0e86057f8cddc"},
"plug_cowboy": {:hex, :plug_cowboy, "2.7.2", "fdadb973799ae691bf9ecad99125b16625b1c6039999da5fe544d99218e662e4", [:mix], [{:cowboy, "~> 2.7", [hex: :cowboy, repo: "hexpm", optional: false]}, {:cowboy_telemetry, "~> 0.3", [hex: :cowboy_telemetry, repo: "hexpm", optional: false]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "245d8a11ee2306094840c000e8816f0cbed69a23fc0ac2bcf8d7835ae019bb2f"},
"plug_crypto": {:hex, :plug_crypto, "1.2.5", "918772575e48e81e455818229bf719d4ab4181fcbf7f85b68a35620f78d89ced", [:mix], [], "hexpm", "26549a1d6345e2172eb1c233866756ae44a9609bd33ee6f99147ab3fd87fd842"},
- "postgrex": {:hex, :postgrex, "0.19.1", "73b498508b69aded53907fe48a1fee811be34cc720e69ef4ccd568c8715495ea", [:mix], [{: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]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "8bac7885a18f381e091ec6caf41bda7bb8c77912bb0e9285212829afe5d8a8f8"},
+ "postgrex": {:hex, :postgrex, "0.19.2", "34d6884a332c7bf1e367fc8b9a849d23b43f7da5c6e263def92784d03f9da468", [:mix], [{: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]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "618988886ab7ae8561ebed9a3c7469034bf6a88b8995785a3378746a4b9835ec"},
"prom_ex": {:hex, :prom_ex, "1.9.0", "63e6dda6c05cdeec1f26c48443dcc38ffd2118b3665ae8d2bd0e5b79f2aea03e", [:mix], [{:absinthe, ">= 1.6.0", [hex: :absinthe, repo: "hexpm", optional: true]}, {:broadway, ">= 1.0.2", [hex: :broadway, repo: "hexpm", optional: true]}, {:ecto, ">= 3.5.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:finch, "~> 0.15", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.2", [hex: :jason, repo: "hexpm", optional: false]}, {:oban, ">= 2.4.0", [hex: :oban, repo: "hexpm", optional: true]}, {:octo_fetch, "~> 0.3", [hex: :octo_fetch, repo: "hexpm", optional: false]}, {:phoenix, ">= 1.5.0", [hex: :phoenix, repo: "hexpm", optional: true]}, {:phoenix_live_view, ">= 0.14.0", [hex: :phoenix_live_view, repo: "hexpm", optional: true]}, {:plug, ">= 1.12.1", [hex: :plug, repo: "hexpm", optional: true]}, {:plug_cowboy, "~> 2.5", [hex: :plug_cowboy, repo: "hexpm", optional: false]}, {:telemetry, ">= 1.0.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}, {:telemetry_metrics_prometheus_core, "~> 1.0", [hex: :telemetry_metrics_prometheus_core, repo: "hexpm", optional: false]}, {:telemetry_poller, "~> 1.0", [hex: :telemetry_poller, repo: "hexpm", optional: false]}], "hexpm", "01f3d4f69ec93068219e686cc65e58a29c42bea5429a8ff4e2121f19db178ee6"},
"public_suffix": {:git, "https://github.com/axelson/publicsuffix-elixir", "fa40c243d4b5d8598b90cff268bc4e33f3bb63f1", []},
"ranch": {:hex, :ranch, "1.8.0", "8c7a100a139fd57f17327b6413e4167ac559fbc04ca7448e9be9057311597a1d", [:make, :rebar3], [], "hexpm", "49fbcfd3682fab1f5d109351b61257676da1a2fdbe295904176d5e521a2ddfe5"},
diff --git a/test/plausible/config_test.exs b/test/plausible/config_test.exs
index 07ae08c1c1a2..46eaa2c8d185 100644
--- a/test/plausible/config_test.exs
+++ b/test/plausible/config_test.exs
@@ -1,5 +1,45 @@
defmodule Plausible.ConfigTest do
use ExUnit.Case
+ import Plausible.ConfigHelpers
+
+ describe "get_bool_from_path_or_env/3" do
+ test "parses truthy vars" do
+ truthy = ["1", "t", "true", "y", "yes", "on"]
+
+ for var <- truthy do
+ env = [{"ENABLE_EMAIL_VERIFICATION", var}]
+ config = runtime_config(env)
+ assert get_in(config, [:plausible, :selfhost, :enable_email_verification]) == true
+ end
+ end
+
+ test "parses false vars" do
+ falsy = ["0", "f", "false", "n", "no", "off"]
+
+ for var <- falsy do
+ env = [{"ENABLE_EMAIL_VERIFICATION", var}]
+ config = runtime_config(env)
+ assert get_in(config, [:plausible, :selfhost, :enable_email_verification]) == false
+ end
+ end
+
+ test "supports defaults" do
+ put_system_env_undo([{"ENABLE_EMAIL_VERIFICATION", nil}])
+ config_dir = "/run/secrets"
+
+ assert get_bool_from_path_or_env(config_dir, "ENABLE_EMAIL_VERIFICATION") == nil
+ assert get_bool_from_path_or_env(config_dir, "ENABLE_EMAIL_VERIFICATION", true) == true
+ assert get_bool_from_path_or_env(config_dir, "ENABLE_EMAIL_VERIFICATION", false) == false
+ end
+
+ test "raises on invalid var" do
+ env = [{"ENABLE_EMAIL_VERIFICATION", "YOLO"}]
+
+ assert_raise ArgumentError,
+ "Invalid boolean value: \"YOLO\". Expected one of: 1, 0, t, f, true, false, y, n, yes, no, on, off",
+ fn -> runtime_config(env) end
+ end
+ end
describe "mailer" do
test "mailer email default" do
@@ -132,9 +172,9 @@ defmodule Plausible.ConfigTest do
{:password, "one"},
{:tls, :if_available},
{:allowed_tls_versions, [:tlsv1, :"tlsv1.1", :"tlsv1.2"]},
- {:ssl, "true"},
+ {:ssl, true},
{:retries, "3"},
- {:no_mx_lookups, "true"}
+ {:no_mx_lookups, true}
]
end
diff --git a/test/plausible/imported/csv_importer_test.exs b/test/plausible/imported/csv_importer_test.exs
index 3bb6f8ca08a2..2153e85b204c 100644
--- a/test/plausible/imported/csv_importer_test.exs
+++ b/test/plausible/imported/csv_importer_test.exs
@@ -541,6 +541,9 @@ defmodule Plausible.Imported.CSVImporterTest do
assert email.html_body =~
~s[Please click
here to start the download process.]
+ assert email.text_body =~
+ ~r[Please click here \(http://localhost:8000/#{URI.encode_www_form(exported_site.domain)}/download/export\) to start the download process.]
+
# download archive
on_ee do
ExAws.request!(
diff --git a/test/plausible_web/controllers/site_controller_test.exs b/test/plausible_web/controllers/site_controller_test.exs
index 277d2a295c9a..ec5dee748279 100644
--- a/test/plausible_web/controllers/site_controller_test.exs
+++ b/test/plausible_web/controllers/site_controller_test.exs
@@ -416,6 +416,12 @@ defmodule PlausibleWeb.SiteControllerTest do
assert html_response(conn, 200) =~
"This domain cannot be registered. Perhaps one of your colleagues registered it?"
+
+ if Plausible.ee?() do
+ assert html_response(conn, 200) =~ "support@plausible.io"
+ else
+ refute html_response(conn, 200) =~ "support@plausible.io"
+ end
end
test "renders form again when domain was changed from elsewhere", %{conn: conn} do
@@ -433,6 +439,12 @@ defmodule PlausibleWeb.SiteControllerTest do
assert html_response(conn, 200) =~
"This domain cannot be registered. Perhaps one of your colleagues registered it?"
+
+ if Plausible.ee?() do
+ assert html_response(conn, 200) =~ "support@plausible.io"
+ else
+ refute html_response(conn, 200) =~ "support@plausible.io"
+ end
end
test "allows creating the site if domain was changed by the owner", %{
diff --git a/test/plausible_web/email_test.exs b/test/plausible_web/email_test.exs
index e161d2a99a01..0de0455c52ad 100644
--- a/test/plausible_web/email_test.exs
+++ b/test/plausible_web/email_test.exs
@@ -13,6 +13,7 @@ defmodule PlausibleWeb.EmailTest do
})
assert email.html_body =~ "Hey John,"
+ assert email.text_body =~ "Hey John,"
end
test "greets impersonally when user not in template assigns" do
@@ -21,6 +22,7 @@ defmodule PlausibleWeb.EmailTest do
|> Email.render("welcome_email.html")
assert email.html_body =~ "Hey,"
+ assert email.text_body =~ "Hey,"
end
test "renders plausible link" do
@@ -29,6 +31,7 @@ defmodule PlausibleWeb.EmailTest do
|> Email.render("welcome_email.html")
assert email.html_body =~ plausible_link()
+ assert email.text_body =~ plausible_url()
end
@tag :ee_only
@@ -49,11 +52,15 @@ defmodule PlausibleWeb.EmailTest do
refute email.html_body =~ "Hey John,"
refute email.html_body =~ plausible_link()
+
+ refute email.text_body =~ "Hey John,"
+ refute email.text_body =~ plausible_url()
end
end
describe "priority email layout" do
- test "uses the `priority` message stream in Postmark" do
+ @tag :ee_only
+ test "uses the `priority` message stream in Postmark in EE" do
email =
Email.priority_email()
|> Email.render("activation_email.html", %{
@@ -64,6 +71,18 @@ defmodule PlausibleWeb.EmailTest do
assert %{"MessageStream" => "priority"} = email.private[:message_params]
end
+ @tag :ce_build_only
+ test "doesn't use the `priority` message stream in Postmark in CE" do
+ email =
+ Email.priority_email()
+ |> Email.render("activation_email.html", %{
+ user: build(:user, name: "John Doe"),
+ code: "123"
+ })
+
+ refute email.private[:message_params]["MessageStream"]
+ end
+
test "greets user by first name if user in template assigns" do
email =
Email.priority_email()
@@ -73,6 +92,7 @@ defmodule PlausibleWeb.EmailTest do
})
assert email.html_body =~ "Hey John,"
+ assert email.text_body =~ "Hey John,"
end
test "greets impersonally when user not in template assigns" do
@@ -83,6 +103,7 @@ defmodule PlausibleWeb.EmailTest do
})
assert email.html_body =~ "Hey,"
+ assert email.text_body =~ "Hey,"
end
test "renders plausible link" do
@@ -93,6 +114,7 @@ defmodule PlausibleWeb.EmailTest do
})
assert email.html_body =~ plausible_link()
+ assert email.text_body =~ plausible_url()
end
test "does not render unsubscribe placeholder" do
@@ -114,6 +136,9 @@ defmodule PlausibleWeb.EmailTest do
refute email.html_body =~ "Hey John,"
refute email.html_body =~ plausible_link()
+
+ refute email.text_body =~ "Hey John,"
+ refute email.text_body =~ plausible_url()
end
end
@@ -275,7 +300,7 @@ defmodule PlausibleWeb.EmailTest do
end
end
- describe "site_setup_success" do
+ describe "site setup emails" do
setup do
trial_user =
build(:user,
@@ -285,31 +310,122 @@ defmodule PlausibleWeb.EmailTest do
)
site = build(:site, members: [trial_user])
- email = PlausibleWeb.Email.site_setup_success(trial_user, site)
- {:ok, email: email}
+
+ emails = [
+ PlausibleWeb.Email.create_site_email(trial_user),
+ PlausibleWeb.Email.site_setup_help(trial_user, site),
+ PlausibleWeb.Email.site_setup_success(trial_user, site)
+ ]
+
+ {:ok, emails: emails}
end
+ @trial_message "trial"
+ @reply_message "reply back"
+
@tag :ee_only
- test "renders 'trial' and 'reply' blocks", %{email: email} do
- assert email.html_body =~
- "You're on a 30-day free trial with no obligations so do take your time to explore Plausible."
+ test "has 'trial' and 'reply' blocks, correct product name", %{emails: emails} do
+ for email <- emails do
+ assert email.html_body =~ @trial_message
+ assert email.html_body =~ @reply_message
+ refute email.html_body =~ "Plausible CE"
+ end
+
+ assert Enum.any?(emails, fn email -> email.html_body =~ "Plausible Analytics" end)
+ end
+
+ @tag :ce_build_only
+ test "no 'trial' or 'reply' blocks, correct product name", %{emails: emails} do
+ for email <- emails do
+ refute email.html_body =~ @trial_message
+ refute email.html_body =~ @reply_message
+ refute email.html_body =~ "Plausible Analytics"
+ end
+
+ assert Enum.any?(emails, fn email -> email.html_body =~ "Plausible CE" end)
+ end
+ end
+
+ describe "text_body" do
+ @tag :ee_only
+ test "welcome_email (EE)" do
+ email =
+ Email.base_email()
+ |> Email.render("welcome_email.html", %{
+ user: build(:user, name: "John Doe"),
+ code: "123"
+ })
+
+ assert email.text_body == """
+ Hey John,
+
+ We are building Plausible to provide a simple and ethical approach to tracking website visitors. We're super excited to have you on board!
+
+ Here's how to get the most out of your Plausible experience:
+
+ * Enable email reports (https://plausible.io/docs/email-reports) and notifications for traffic spikes (https://plausible.io/docs/traffic-spikes)
+ * Integrate with Search Console (https://plausible.io/docs/google-search-console-integration) to get keyword phrases people find your site with
+ * Invite team members and other collaborators (https://plausible.io/docs/users-roles)
+ * Set up easy goals including 404 error pages (https://plausible.io/docs/error-pages-tracking-404), file downloads (https://plausible.io/docs/file-downloads-tracking) and outbound link clicks (https://plausible.io/docs/outbound-link-click-tracking)
+ * Opt out from counting your own visits (https://plausible.io/docs/excluding)
+ * If you're concerned about adblockers, set up a proxy to bypass them (https://plausible.io/docs/proxy/introduction)
+
- assert email.html_body =~
- "Do reply back to this email if you have any questions. We're here to help."
+ Then you're ready to start exploring your fast loading, ethical and actionable Plausible dashboard (https://plausible.io/sites).
+
+ Have a question, feedback or need some guidance? Do reply back to this email.
+
+ Regards,
+ The Plausible Team 💌
+
+ --
+
+ http://localhost:8000
+ {{{ pm:unsubscribe }}}\
+ """
end
@tag :ce_build_only
- test "does not render 'trial' and 'reply' blocks", %{email: email} do
- refute email.html_body =~
- "You're on a 30-day free trial with no obligations so do take your time to explore Plausible."
+ test "welcome_email (CE)" do
+ email =
+ Email.base_email()
+ |> Email.render("welcome_email.html", %{
+ user: build(:user, name: "John Doe"),
+ code: "123"
+ })
+
+ assert email.text_body == """
+ Hey John,
+
+ We are building Plausible to provide a simple and ethical approach to tracking website visitors. We're super excited to have you on board!
+
+ Here's how to get the most out of your Plausible experience:
+
+ * Enable email reports (https://plausible.io/docs/email-reports) and notifications for traffic spikes (https://plausible.io/docs/traffic-spikes)
+ * Integrate with Search Console (https://plausible.io/docs/google-search-console-integration) to get keyword phrases people find your site with
+ * Invite team members and other collaborators (https://plausible.io/docs/users-roles)
+ * Set up easy goals including 404 error pages (https://plausible.io/docs/error-pages-tracking-404), file downloads (https://plausible.io/docs/file-downloads-tracking) and outbound link clicks (https://plausible.io/docs/outbound-link-click-tracking)
+ * Opt out from counting your own visits (https://plausible.io/docs/excluding)
+ * If you're concerned about adblockers, set up a proxy to bypass them (https://plausible.io/docs/proxy/introduction)
- refute email.html_body =~
- "Do reply back to this email if you have any questions. We're here to help."
+
+ Then you're ready to start exploring your fast loading, ethical and actionable Plausible dashboard (https://plausible.io/sites).
+
+ Have a question, feedback or need some guidance? Do reply back to this email.
+
+ --
+
+ http://localhost:8000
+ """
end
end
+ def plausible_url do
+ PlausibleWeb.EmailView.plausible_url()
+ end
+
def plausible_link() do
- plausible_url = PlausibleWeb.EmailView.plausible_url()
+ plausible_url = plausible_url()
"
#{plausible_url}"
end
end
diff --git a/test/workers/notify_exported_analytics_test.exs b/test/workers/notify_exported_analytics_test.exs
index b3caecbe075d..c869c909cd9c 100644
--- a/test/workers/notify_exported_analytics_test.exs
+++ b/test/workers/notify_exported_analytics_test.exs
@@ -27,6 +27,7 @@ defmodule Plausible.Workers.NotifyExportedAnalyticsTest do
assert_receive {:delivered_email, email}
assert email.html_body =~ "was unsuccessful."
+ assert email.text_body =~ "was unsuccessful."
end
end
end