From 0d4aceb9b0c6d742b481c08b88ba50d67c65c091 Mon Sep 17 00:00:00 2001 From: Sean King Date: Tue, 5 Jul 2022 20:36:47 -0600 Subject: [PATCH 1/4] Make checking blacklisted domains and restricted nicknames case-insenstive --- lib/pleroma/user.ex | 17 +++++++++++++++-- test/pleroma/user_test.exs | 23 +++++++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 747a83e8d..47c51469e 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -758,13 +758,26 @@ def register_changeset(struct, params \\ %{}, opts \\ []) do valid? = Config.get([User, :email_blacklist]) |> Enum.all?(fn blacklisted_domain -> - !String.ends_with?(email, ["@" <> blacklisted_domain, "." <> blacklisted_domain]) + blacklisted_domain_downcase = String.downcase(blacklisted_domain) + + !String.ends_with?(String.downcase(email), [ + "@" <> blacklisted_domain_downcase, + "." <> blacklisted_domain_downcase + ]) end) if valid?, do: [], else: [email: "Invalid email"] end) |> unique_constraint(:nickname) - |> validate_exclusion(:nickname, Config.get([User, :restricted_nicknames])) + |> validate_change(:nickname, fn :nickname, nickname -> + valid? = + Config.get([User, :restricted_nicknames]) + |> Enum.all?(fn restricted_nickname -> + String.downcase(nickname) != String.downcase(restricted_nickname) + end) + + if valid?, do: [], else: [nickname: "Invalid nickname"] + end) |> validate_format(:nickname, local_nickname_regex()) |> validate_length(:bio, max: bio_limit) |> validate_length(:name, min: 1, max: name_limit) diff --git a/test/pleroma/user_test.exs b/test/pleroma/user_test.exs index 884b846ae..5b513f01b 100644 --- a/test/pleroma/user_test.exs +++ b/test/pleroma/user_test.exs @@ -618,6 +618,7 @@ test "it requires an name, nickname and password, bio and email are optional whe end test "it restricts certain nicknames" do + clear_config([User, :restricted_nicknames], ["about"]) [restricted_name | _] = Pleroma.Config.get([User, :restricted_nicknames]) assert is_bitstring(restricted_name) @@ -631,6 +632,23 @@ test "it restricts certain nicknames" do refute changeset.valid? end + test "it is case-insensitive when restricting nicknames" do + clear_config([User, :restricted_nicknames], ["about"]) + [restricted_name | _] = Pleroma.Config.get([User, :restricted_nicknames]) + + assert is_bitstring(restricted_name) + + restricted_upcase_name = String.upcase(restricted_name) + + params = + @full_user_data + |> Map.put(:nickname, restricted_upcase_name) + + changeset = User.register_changeset(%User{}, params) + + refute changeset.valid? + end + test "it blocks blacklisted email domains" do clear_config([User, :email_blacklist], ["trolling.world"]) @@ -639,6 +657,11 @@ test "it blocks blacklisted email domains" do changeset = User.register_changeset(%User{}, params) refute changeset.valid? + # Block with case-insensitive match + params = Map.put(@full_user_data, :email, "troll@TrOlLing.wOrld") + changeset = User.register_changeset(%User{}, params) + refute changeset.valid? + # Block with subdomain match params = Map.put(@full_user_data, :email, "troll@gnomes.trolling.world") changeset = User.register_changeset(%User{}, params) From 6e7b919637ff220a3abf17feff5c25149f3a23a1 Mon Sep 17 00:00:00 2001 From: Sean King Date: Wed, 6 Jul 2022 20:15:49 -0600 Subject: [PATCH 2/4] Make validation functions for restricted nicknames and blacklisted domains; do restricted nickname validation in LDAP account registration --- lib/pleroma/user.ex | 56 ++++++++++++++++++++++++++------------------- 1 file changed, 32 insertions(+), 24 deletions(-) diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 47c51469e..d05fbe5a2 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -706,7 +706,7 @@ def register_changeset_ldap(struct, params = %{password: password}) ]) |> validate_required([:name, :nickname]) |> unique_constraint(:nickname) - |> validate_exclusion(:nickname, Config.get([User, :restricted_nicknames])) + |> validate_not_restricted_nickname(:nickname) |> validate_format(:nickname, local_nickname_regex()) |> put_ap_id() |> unique_constraint(:ap_id) @@ -754,30 +754,9 @@ def register_changeset(struct, params \\ %{}, opts \\ []) do |> validate_confirmation(:password) |> unique_constraint(:email) |> validate_format(:email, @email_regex) - |> validate_change(:email, fn :email, email -> - valid? = - Config.get([User, :email_blacklist]) - |> Enum.all?(fn blacklisted_domain -> - blacklisted_domain_downcase = String.downcase(blacklisted_domain) - - !String.ends_with?(String.downcase(email), [ - "@" <> blacklisted_domain_downcase, - "." <> blacklisted_domain_downcase - ]) - end) - - if valid?, do: [], else: [email: "Invalid email"] - end) + |> validate_email_not_in_blacklisted_domain(:email) |> unique_constraint(:nickname) - |> validate_change(:nickname, fn :nickname, nickname -> - valid? = - Config.get([User, :restricted_nicknames]) - |> Enum.all?(fn restricted_nickname -> - String.downcase(nickname) != String.downcase(restricted_nickname) - end) - - if valid?, do: [], else: [nickname: "Invalid nickname"] - end) + |> validate_not_restricted_nickname(:nickname) |> validate_format(:nickname, local_nickname_regex()) |> validate_length(:bio, max: bio_limit) |> validate_length(:name, min: 1, max: name_limit) @@ -791,6 +770,35 @@ def register_changeset(struct, params \\ %{}, opts \\ []) do |> put_following_and_follower_and_featured_address() end + def validate_not_restricted_nickname(changeset, field) do + validate_change changeset, field, fn _, value -> + valid? = + Config.get([User, :restricted_nicknames]) + |> Enum.all?(fn restricted_nickname -> + String.downcase(value) != String.downcase(restricted_nickname) + end) + + if valid?, do: [], else: [nickname: "Invalid nickname"] + end + end + + def validate_email_not_in_blacklisted_domain(changeset, field) do + validate_change changeset, field, fn _, value -> + valid? = + Config.get([User, :email_blacklist]) + |> Enum.all?(fn blacklisted_domain -> + blacklisted_domain_downcase = String.downcase(blacklisted_domain) + + !String.ends_with?(String.downcase(value), [ + "@" <> blacklisted_domain_downcase, + "." <> blacklisted_domain_downcase + ]) + end) + + if valid?, do: [], else: [email: "Invalid email"] + end + end + def maybe_validate_required_email(changeset, true), do: changeset def maybe_validate_required_email(changeset, _) do From 3cf6c2b7ea20c9c87c63e382c36231b1b9be3d7f Mon Sep 17 00:00:00 2001 From: Sean King Date: Sat, 9 Jul 2022 23:39:35 -0600 Subject: [PATCH 3/4] Use is_binary instead of is_bitstring for restricted nicknames tests --- test/pleroma/user_test.exs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/pleroma/user_test.exs b/test/pleroma/user_test.exs index 5b513f01b..408389c3a 100644 --- a/test/pleroma/user_test.exs +++ b/test/pleroma/user_test.exs @@ -621,7 +621,7 @@ test "it restricts certain nicknames" do clear_config([User, :restricted_nicknames], ["about"]) [restricted_name | _] = Pleroma.Config.get([User, :restricted_nicknames]) - assert is_bitstring(restricted_name) + assert is_binary(restricted_name) params = @full_user_data @@ -636,7 +636,7 @@ test "it is case-insensitive when restricting nicknames" do clear_config([User, :restricted_nicknames], ["about"]) [restricted_name | _] = Pleroma.Config.get([User, :restricted_nicknames]) - assert is_bitstring(restricted_name) + assert is_binary(restricted_name) restricted_upcase_name = String.upcase(restricted_name) From 8bb2e52d2ee569dc0343ec8bca1f1196bba9386f Mon Sep 17 00:00:00 2001 From: Tusooa Zhu Date: Sun, 10 Jul 2022 23:43:49 -0400 Subject: [PATCH 4/4] Make lint happy --- lib/pleroma/user.ex | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index d05fbe5a2..712d3b1d9 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -771,19 +771,19 @@ def register_changeset(struct, params \\ %{}, opts \\ []) do end def validate_not_restricted_nickname(changeset, field) do - validate_change changeset, field, fn _, value -> + validate_change(changeset, field, fn _, value -> valid? = Config.get([User, :restricted_nicknames]) |> Enum.all?(fn restricted_nickname -> - String.downcase(value) != String.downcase(restricted_nickname) - end) + String.downcase(value) != String.downcase(restricted_nickname) + end) if valid?, do: [], else: [nickname: "Invalid nickname"] - end + end) end def validate_email_not_in_blacklisted_domain(changeset, field) do - validate_change changeset, field, fn _, value -> + validate_change(changeset, field, fn _, value -> valid? = Config.get([User, :email_blacklist]) |> Enum.all?(fn blacklisted_domain -> @@ -794,9 +794,9 @@ def validate_email_not_in_blacklisted_domain(changeset, field) do "." <> blacklisted_domain_downcase ]) end) - + if valid?, do: [], else: [email: "Invalid email"] - end + end) end def maybe_validate_required_email(changeset, true), do: changeset