Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Accept letters from non-Latin alphabets in domain names
  • Loading branch information
vinibrsl committed Sep 27, 2022
commit fd06d8be0adc95412da5bb9abf4581d8af8646e2
21 changes: 19 additions & 2 deletions lib/plausible/site/schema.ex
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,15 @@ defmodule Plausible.Site do
site
|> cast(attrs, [:domain, :timezone])
|> validate_required([:domain, :timezone])
|> validate_format(:domain, ~r/^[a-zA-Z0-9\-\.\/\:]*$/,
|> clean_domain()
|> validate_format(:domain, ~r/^[-\.\\\/:\p{L}\d]*$/u,
message: "only letters, numbers, slashes and period allowed"
)
|> validate_domain_reserved_characters()
|> unique_constraint(:domain,
message:
"This domain has already been taken. Perhaps one of your team members registered it? If that's not the case, please contact support@plausible.io"
)
|> clean_domain
end

def make_public(site) do
Expand Down Expand Up @@ -114,4 +115,20 @@ defmodule Plausible.Site do
domain: clean_domain
})
end

# https://tools.ietf.org/html/rfc3986#section-2.2
@uri_reserved_chars ~w(: ? # [ ] @ ! $ & ' \( \) * + , ; =)
defp validate_domain_reserved_characters(changeset) do
domain = get_field(changeset, :domain) || ""

if String.contains?(domain, @uri_reserved_chars) do
add_error(
changeset,
:domain,
"must not contain URI reserved characters #{@uri_reserved_chars}"
)
else
changeset
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,24 @@ defmodule PlausibleWeb.Api.ExternalSitesControllerTest do
}
end

test "accepts international domain names", %{conn: conn} do
["müllers-café.test", "音乐.cn", "до.101домен.рф/pages"]
|> Enum.each(fn idn_domain ->
conn = post(conn, "/api/v1/sites", %{"domain" => idn_domain})
assert %{"domain" => ^idn_domain} = json_response(conn, 200)
end)
end

test "validates uri breaking domains", %{conn: conn} do
["quero:café.test", "h&llo.test", "iamnotsur&about?this.com"]
|> Enum.each(fn bad_domain ->
conn = post(conn, "/api/v1/sites", %{"domain" => bad_domain})

assert %{"error" => error} = json_response(conn, 400)
assert error =~ "domain must not contain URI reserved characters"
end)
end

test "does not allow creating more sites than the limit", %{conn: conn, user: user} do
Application.put_env(:plausible, :site_limit, 3)
insert(:site, members: [user])
Expand Down