ensure utf-8 nicknames on nickname GETs and user validator #1057

Merged
floatingghost merged 4 commits from user-utf8 into develop 2026-02-07 19:41:27 +00:00
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
Oneric marked this conversation as resolved

what will happen if "preferredusername" exists but isn’t a binary?

what will happen if `"preferredusername"` exists but isn’t a binary?

updated to error if we have the preferredUsername key but its type is silly

updated to error if we have the preferredUsername key but its type is silly
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