Allow internal prop keys in queries (#3231)

* Remove `Plausible.Sites.set_allowed_event_props/2` function

This commit removes the `Plausible.Sites.set_allowed_event_props/2`
function in favor of `Plausible.Props.allow/2`.

* Allow internal prop keys in queries

This commit allows internal prop keys by default in queries. I decided
not to include internal keys in the database, because they might change
and we'd need to migrate it again.

* remove redundant 'props.' from behaviours/index.js

---------

Co-authored-by: Robert Joonas <robertjoonas16@gmail.com>
This commit is contained in:
Vini Brasil 2023-08-05 11:13:16 -03:00 committed by GitHub
parent 1fedaf18c3
commit 8c3b541971
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 40 additions and 30 deletions

View File

@ -167,7 +167,7 @@ export default function Behaviours(props) {
function renderProps() {
if (site.hasProps) {
return <Properties site={site} query={props.query} />
return <Properties site={site} query={query} />
} else if (adminAccess) {
return (
<FeatureSetupNotice

View File

@ -81,10 +81,16 @@ defmodule Plausible.Props do
allow(site, props_to_allow)
end
# List of props to be ignored from suggestions. For example, `url` is used both
# for file downloads and outbound links, and it doesn't make sense to suggest
# users to allow this prop key.
@internal_props ~w(url path)
@internal_keys ~w(url path)
@doc """
Lists prop keys used internally.
These props should be allowed by default, and should not be displayed in the
props settings page. For example, `url` is a special prop key used for file
downloads and outbound links. It doesn't make sense to remove this prop key
from the allow list, or to suggest users to add this prop key.
"""
def internal_keys, do: @internal_keys
@spec suggest_keys_to_allow(Plausible.Site.t(), non_neg_integer()) :: [String.t()]
@doc """
@ -104,7 +110,7 @@ defmodule Plausible.Props do
Plausible.ClickhouseRepo.all(
from uk in subquery(unnested_keys),
where: uk.key not in ^allowed_event_props,
where: uk.key not in ^@internal_props,
where: uk.key not in ^@internal_keys,
group_by: uk.key,
select: uk.key,
order_by: {:desc, count(uk.key)},

View File

@ -85,7 +85,7 @@ defmodule Plausible.SiteAdmin do
props -> String.split(props, ~r/\s*,\s*/)
end
Plausible.Sites.set_allowed_event_props!(site, props_list)
{:ok, _site} = Plausible.Props.allow(site, props_list)
:ok
end

View File

@ -177,9 +177,4 @@ defmodule Plausible.Sites do
where: sm.role == :owner
)
end
def set_allowed_event_props!(site, props) do
Ecto.Changeset.change(site, allowed_event_props: props)
|> Repo.update!()
end
end

View File

@ -51,7 +51,8 @@ defmodule Plausible.Stats.CustomProps do
end
def maybe_allowed_props_only(q, allowed_props) when is_list(allowed_props) do
from [..., m] in q, where: m.key in ^allowed_props
props = allowed_props ++ Plausible.Props.internal_keys()
from [..., m] in q, where: m.key in ^props
end
def maybe_allowed_props_only(q, nil), do: q

View File

@ -448,14 +448,8 @@ defmodule PlausibleWeb.Api.StatsController.ConversionsTest do
assert [%{"prop_names" => []}] = json_response(conn, 200)
end
test "filters out garbage prop_names",
%{
conn: conn,
site: site
} do
site =
site
|> Plausible.Sites.set_allowed_event_props!(["author"])
test "filters out garbage prop_names", %{conn: conn, site: site} do
{:ok, site} = Plausible.Props.allow(site, ["author"])
populate_stats(site, [
build(:event,
@ -488,9 +482,7 @@ defmodule PlausibleWeb.Api.StatsController.ConversionsTest do
conn: conn,
site: site
} do
site =
site
|> Plausible.Sites.set_allowed_event_props!(["author", "logged_in"])
{:ok, site} = Plausible.Props.allow(site, ["author", "logged_in"])
populate_stats(site, [
build(:event,
@ -549,6 +541,24 @@ defmodule PlausibleWeb.Api.StatsController.ConversionsTest do
assert "OnlyGarbage" in prop_names
end
test "does not filter out special prop keys", %{conn: conn, site: site} do
{:ok, site} = Plausible.Props.allow(site, ["author"])
populate_stats(site, [
build(:event,
name: "Outbound Link: Click",
"meta.key": ["url", "path", "first_time_customer"],
"meta.value": ["http://link.test", "/abc", "true"]
)
])
insert(:goal, %{site: site, event_name: "Outbound Link: Click"})
filters = Jason.encode!(%{goal: "Outbound Link: Click"})
conn = get(conn, "/api/stats/#{site.domain}/conversions?period=day&filters=#{filters}")
assert [%{"prop_names" => ["url", "path"]}] = json_response(conn, 200)
end
test "can filter by multiple mixed goals", %{conn: conn, site: site} do
populate_stats(site, [
build(:pageview, pathname: "/"),

View File

@ -282,9 +282,7 @@ defmodule PlausibleWeb.Api.StatsController.SuggestionsTest do
conn: conn,
site: site
} do
site =
site
|> Plausible.Sites.set_allowed_event_props!(["author"])
{:ok, site} = Plausible.Props.allow(site, ["author"])
populate_stats(site, [
build(:pageview,

View File

@ -171,7 +171,7 @@ defmodule PlausibleWeb.StatsControllerTest do
end
test "exports allowed event props", %{conn: conn, site: site} do
site = Plausible.Sites.set_allowed_event_props!(site, ["author", "logged_in"])
{:ok, site} = Plausible.Props.allow(site, ["author", "logged_in"])
populate_stats(site, [
build(:pageview, "meta.key": ["author"], "meta.value": ["uku"]),
@ -277,7 +277,7 @@ defmodule PlausibleWeb.StatsControllerTest do
conn: conn,
site: site
} do
site = Plausible.Sites.set_allowed_event_props!(site, ["author", "logged_in"])
{:ok, site} = Plausible.Props.allow(site, ["author", "logged_in"])
populate_stats(site, [
build(:pageview, "meta.key": ["author"], "meta.value": ["uku"]),
@ -395,7 +395,7 @@ defmodule PlausibleWeb.StatsControllerTest do
conn: conn,
site: site
} do
site = Plausible.Sites.set_allowed_event_props!(site, ["author", "logged_in"])
{:ok, site} = Plausible.Props.allow(site, ["author", "logged_in"])
populate_stats(site, [
build(:event, name: "Newsletter Signup", "meta.key": ["author"], "meta.value": ["uku"]),