Merge pull request 'ensure utf-8 nicknames on nickname GETs and user validator' (#1057) from user-utf8 into develop
Some checks failed
ci/woodpecker/push/publish/4 Pipeline failed
ci/woodpecker/push/docs Pipeline was successful
ci/woodpecker/push/publish/1 Pipeline failed
ci/woodpecker/push/publish/2 Pipeline failed

Reviewed-on: #1057
Reviewed-by: Oneric <oneric@noreply.akkoma>
This commit is contained in:
floatingghost 2026-02-07 19:41:26 +00:00
commit cf8010a33e
3 changed files with 44 additions and 11 deletions

View file

@ -1211,14 +1211,18 @@ defmodule Pleroma.User do
end
def get_cached_by_nickname(nickname) do
key = "nickname:#{nickname}"
if String.valid?(nickname) do
key = "nickname:#{nickname}"
@cachex.fetch!(:user_cache, key, fn _ ->
case get_or_fetch_by_nickname(nickname) do
{:ok, user} -> {:commit, user}
{:error, _error} -> {:ignore, nil}
end
end)
@cachex.fetch!(:user_cache, key, fn _ ->
case get_or_fetch_by_nickname(nickname) do
{:ok, user} -> {:commit, user}
{:error, _error} -> {:ignore, nil}
end
end)
else
nil
end
end
def get_cached_by_nickname_or_id(nickname_or_id, opts \\ []) do
@ -1241,10 +1245,14 @@ defmodule Pleroma.User do
@spec get_by_nickname(String.t()) :: User.t() | nil
def get_by_nickname(nickname) do
Repo.get_by(User, nickname: nickname) ||
if Regex.match?(~r(@#{Pleroma.Web.Endpoint.host()})i, nickname) do
Repo.get_by(User, nickname: local_nickname(nickname))
end
if String.valid?(nickname) do
Repo.get_by(User, nickname: nickname) ||
if Regex.match?(~r(@#{Pleroma.Web.Endpoint.host()})i, nickname) do
Repo.get_by(User, nickname: local_nickname(nickname))
end
else
nil
end
end
def get_by_email(email), do: Repo.get_by(User, email: email)

View file

@ -25,6 +25,7 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.UserValidator do
when type in Pleroma.Constants.actor_types() do
with :ok <- validate_pubkey(data),
:ok <- validate_inbox(data),
:ok <- validate_nickname(data),
:ok <- contain_collection_origin(data) do
{:ok, data, meta}
else
@ -83,4 +84,18 @@ defmodule Pleroma.Web.ActivityPub.ObjectValidators.UserValidator do
_, error -> error
end)
end
defp validate_nickname(%{"preferredUsername" => nick}) when is_binary(nick) do
if String.valid?(nick) do
:ok
else
{:error, "Nickname is not valid UTF-8"}
end
end
defp validate_nickname(%{"preferredUsername" => _nick}) do
{:error, "Nickname is not a valid string"}
end
defp validate_nickname(_), do: :ok
end

View file

@ -177,6 +177,16 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do
|> get("/api/v1/accounts/#{user.id}")
|> json_response_and_validate_schema(:not_found)
end
test "returns 404 when the username is not valid utf8" do
nick = <<0xC0>>
refute String.valid?(nick)
assert %{"error" => "Can't find user"} =
build_conn()
|> get("/api/v1/accounts/#{nick}")
|> json_response_and_validate_schema(404)
end
end
defp local_and_remote_users do