diff --git a/config/config.md b/config/config.md
index dbbfa9194..e8e2cf6f8 100644
--- a/config/config.md
+++ b/config/config.md
@@ -63,6 +63,8 @@ This filter replaces the filename (not the path) of an upload. For complete obfu
* "masto": Copy verbatim, as in Mastodon.
* "noop": Don't copy the subject.
* `always_show_subject_input`: When set to false, auto-hide the subject field when it's empty.
+* `extended_nickname_format`: Set to `true` to use extended local nicknames format (allows underscore). This will break federation with
+ older software for theses nicknames.
## :fe
This section is used to configure Pleroma-FE, unless ``:managed_config`` in ``:instance`` is set to false.
diff --git a/lib/pleroma/formatter.ex b/lib/pleroma/formatter.ex
index 5b03e9aeb..1fea1c57a 100644
--- a/lib/pleroma/formatter.ex
+++ b/lib/pleroma/formatter.ex
@@ -18,7 +18,7 @@ def parse_tags(text, data \\ %{}) do
def parse_mentions(text) do
# Modified from https://www.w3.org/TR/html5/forms.html#valid-e-mail-address
regex =
- ~r/@[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]*@?[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*/u
+ ~r/@[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]*@?[a-zA-Z0-9_](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*/u
Regex.scan(regex, text)
|> List.flatten()
diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex
index e146b562c..f10cdfbc8 100644
--- a/lib/pleroma/user.ex
+++ b/lib/pleroma/user.ex
@@ -11,6 +11,11 @@ defmodule Pleroma.User do
@type t :: %__MODULE__{}
+ @email_regex ~r/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/
+
+ @strict_local_nickname_regex ~r/^[a-zA-Z\d]+$/
+ @extended_local_nickname_regex ~r/^[a-zA-Z\d_]+$/
+
schema "users" do
field(:bio, :string)
field(:email, :string)
@@ -77,7 +82,6 @@ def user_info(%User{} = user) do
}
end
- @email_regex ~r/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/
def remote_user_creation(params) do
params =
params
@@ -117,7 +121,7 @@ def update_changeset(struct, params \\ %{}) do
struct
|> cast(params, [:bio, :name, :avatar])
|> unique_constraint(:nickname)
- |> validate_format(:nickname, ~r/^[a-zA-Z\d]+$/)
+ |> validate_format(:nickname, local_nickname_regex())
|> validate_length(:bio, max: 5000)
|> validate_length(:name, min: 1, max: 100)
end
@@ -134,7 +138,7 @@ def upgrade_changeset(struct, params \\ %{}) do
struct
|> cast(params, [:bio, :name, :follower_address, :avatar, :last_refreshed_at])
|> unique_constraint(:nickname)
- |> validate_format(:nickname, ~r/^[a-zA-Z\d]+$/)
+ |> validate_format(:nickname, local_nickname_regex())
|> validate_length(:bio, max: 5000)
|> validate_length(:name, max: 100)
|> put_embed(:info, info_cng)
@@ -172,7 +176,7 @@ def register_changeset(struct, params \\ %{}) do
|> validate_confirmation(:password)
|> unique_constraint(:email)
|> unique_constraint(:nickname)
- |> validate_format(:nickname, ~r/^[a-zA-Z\d]+$/)
+ |> validate_format(:nickname, local_nickname_regex())
|> validate_format(:email, @email_regex)
|> validate_length(:bio, max: 1000)
|> validate_length(:name, min: 1, max: 100)
@@ -861,4 +865,12 @@ defp normalize_tags(tags) do
|> List.flatten()
|> Enum.map(&String.downcase(&1))
end
+
+ defp local_nickname_regex() do
+ if Pleroma.Config.get([:instance, :extended_nickname_format]) do
+ @extended_local_nickname_regex
+ else
+ @strict_local_nickname_regex
+ end
+ end
end
diff --git a/test/formatter_test.exs b/test/formatter_test.exs
index abb9d882c..428227d78 100644
--- a/test/formatter_test.exs
+++ b/test/formatter_test.exs
@@ -109,13 +109,13 @@ test "turning urls into links" do
describe "add_user_links" do
test "gives a replacement for user links" do
- text = "@gsimg According to @archaeme, that is @daggsy. Also hello @archaeme@archae.me"
+ text = "@gsimg According to @archa_eme_, that is @daggsy. Also hello @archaeme@archae.me"
gsimg = insert(:user, %{nickname: "gsimg"})
archaeme =
insert(:user, %{
- nickname: "archaeme",
- info: %Pleroma.User.Info{source_data: %{"url" => "https://archeme/@archaeme"}}
+ nickname: "archa_eme_",
+ info: %Pleroma.User.Info{source_data: %{"url" => "https://archeme/@archa_eme_"}}
})
archaeme_remote = insert(:user, %{nickname: "archaeme@archae.me"})
@@ -130,7 +130,7 @@ test "gives a replacement for user links" do
expected_text =
"@gsimg According to @archaeme, that is @daggsy. Also hello @archa_eme_, that is @daggsy. Also hello @archaeme"