Skip to content

Commit d6c8d89

Browse files
authored
Merge pull request #23 from Recruitee/additional-data-validation
Validate special props
2 parents 22961e9 + 62cba87 commit d6c8d89

4 files changed

Lines changed: 99 additions & 2 deletions

File tree

lib/plausible/event/clickhouse_schema.ex

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
defmodule Plausible.ClickhouseEvent do
22
use Ecto.Schema
3+
34
import Ecto.Changeset
45

6+
alias Plausible.ValueHelpers
7+
58
@primary_key false
69
schema "events" do
710
field :event_id, :integer
@@ -89,5 +92,27 @@ defmodule Plausible.ClickhouseEvent do
8992
empty_values: [nil, ""]
9093
)
9194
|> validate_required([:name, :domain, :hostname, :pathname, :event_id, :user_id, :timestamp])
95+
|> validate_campaign_id()
96+
|> validate_product_id()
97+
end
98+
99+
defp validate_campaign_id(changeset) do
100+
campaign_id = get_field(changeset, :campaign_id)
101+
102+
if ValueHelpers.validate(campaign_id, type: :prefixed_id) do
103+
changeset
104+
else
105+
delete_change(changeset, :campaign_id)
106+
end
107+
end
108+
109+
defp validate_product_id(changeset) do
110+
product_id = get_field(changeset, :product_id)
111+
112+
if ValueHelpers.validate(product_id, type: :prefixed_id) do
113+
changeset
114+
else
115+
delete_change(changeset, :product_id)
116+
end
92117
end
93118
end

lib/plausible/helpers/value.ex

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
defmodule Plausible.ValueHelpers do
2+
@prefix_pattern "[a-zA-Z]+"
3+
@id_pattern "\\d+"
4+
@uuid_pattern "[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}"
5+
6+
@spec validate(any(), keyword()) :: any()
7+
def validate(value, type: :prefixed_id) when is_binary(value) do
8+
pattern = ~r/\A(#{@prefix_pattern})-(#{@id_pattern}|#{@uuid_pattern})\Z/
9+
10+
if Regex.match?(pattern, value), do: value, else: nil
11+
end
12+
13+
def validate(nil, _), do: nil
14+
def validate("", _), do: nil
15+
def validate(value, _), do: value
16+
end

lib/plausible/session/clickhouse_schema.ex

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
defmodule Plausible.ClickhouseSession do
22
use Ecto.Schema
3+
34
import Ecto.Changeset
45

6+
alias Plausible.ValueHelpers
7+
58
@primary_key false
69
schema "sessions" do
710
field :hostname, :string
@@ -80,5 +83,27 @@ defmodule Plausible.ClickhouseSession do
8083
:screen_size
8184
])
8285
|> validate_required([:hostname, :domain, :fingerprint, :is_bounce, :start])
86+
|> validate_campaign_id()
87+
|> validate_product_id()
88+
end
89+
90+
defp validate_campaign_id(changeset) do
91+
campaign_id = get_field(changeset, :campaign_id)
92+
93+
if ValueHelpers.validate(campaign_id, type: :prefixed_id) do
94+
changeset
95+
else
96+
delete_change(changeset, :campaign_id)
97+
end
98+
end
99+
100+
defp validate_product_id(changeset) do
101+
product_id = get_field(changeset, :product_id)
102+
103+
if ValueHelpers.validate(product_id, type: :prefixed_id) do
104+
changeset
105+
else
106+
delete_change(changeset, :product_id)
107+
end
83108
end
84109
end

test/plausible_web/controllers/api/external_controller_test.exs

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,7 @@ defmodule PlausibleWeb.Api.ExternalControllerTest do
502502
company_id: 10,
503503
job_id: 12,
504504
page_id: 15,
505-
product_id: "vendor-11",
505+
product_id: "vendor-6a01cfb6-717a-11ee-b962-0242ac120002",
506506
site_id: 9,
507507
careers_application_form_uuid: "313a26c2-741c-421c-9a6b-f39c02c8d35c"
508508
}
@@ -514,7 +514,7 @@ defmodule PlausibleWeb.Api.ExternalControllerTest do
514514
event = get_event("special-props-test.com")
515515

516516
assert Map.get(event, :campaign_id) == "vendor-8"
517-
assert Map.get(event, :product_id) == "vendor-11"
517+
assert Map.get(event, :product_id) == "vendor-6a01cfb6-717a-11ee-b962-0242ac120002"
518518
assert Map.get(event, :company_id) == 10
519519
assert Map.get(event, :job_id) == 12
520520
assert Map.get(event, :page_id) == 15
@@ -527,6 +527,37 @@ defmodule PlausibleWeb.Api.ExternalControllerTest do
527527
assert Map.get(event, :"meta.value") == []
528528
end
529529

530+
test "casts special props, invalidates specific params", %{conn: conn} do
531+
params = %{
532+
name: "Signup",
533+
url: "http://gigride.live/",
534+
domain: "special-props-validation-test.com",
535+
props: %{
536+
campaign_id: "12345",
537+
company_id: 10,
538+
page_id: 15,
539+
product_id: "incorrect-product-id",
540+
careers_application_form_uuid: "313a26c2-741c-421c-9a6b-f39c02c8d35c"
541+
}
542+
}
543+
544+
conn
545+
|> post("/api/event", params)
546+
547+
event = get_event("special-props-validation-test.com")
548+
549+
assert Map.get(event, :campaign_id) == ""
550+
assert Map.get(event, :product_id) == ""
551+
assert Map.get(event, :company_id) == 10
552+
assert Map.get(event, :page_id) == 15
553+
554+
assert Map.get(event, :careers_application_form_uuid) ==
555+
"313a26c2-741c-421c-9a6b-f39c02c8d35c"
556+
557+
assert Map.get(event, :"meta.key") == []
558+
assert Map.get(event, :"meta.value") == []
559+
end
560+
530561
test "generates event id", %{conn: conn} do
531562
params = %{
532563
name: "Signup",

0 commit comments

Comments
 (0)