fix(admin-api): reject explicit empty passwords

This commit is contained in:
Lain Soykaf 2026-07-24 22:52:23 +04:00
commit 836f4a2d69
No known key found for this signature in database
4 changed files with 25 additions and 11 deletions

View file

@ -80,7 +80,7 @@ The `/api/v1/pleroma/admin/*` path is backwards compatible with `/api/pleroma/ad
{
`nickname`,
`email`,
`password` (optional)
`password` (optional; when provided, must not be empty)
}
]
- Response: Array of user objects. When a user is created without a `password`, `data`

View file

@ -153,7 +153,7 @@ defmodule Pleroma.Web.AdminAPI.UserController do
_
) do
conn =
if Enum.any?(users, fn user -> Map.get(user, :password) in ["", nil] end) do
if Enum.any?(users, fn user -> not Map.has_key?(user, :password) end) do
put_private(conn, :skip_idempotency_cache, true)
else
conn
@ -162,15 +162,13 @@ defmodule Pleroma.Web.AdminAPI.UserController do
multi =
users
|> Enum.map(fn %{nickname: nickname, email: email} = attrs ->
passwordless? = Map.get(attrs, :password) in ["", nil]
{password, passwordless?} =
case Map.fetch(attrs, :password) do
{:ok, password} ->
{password, false}
password =
case Map.get(attrs, :password) do
password when is_binary(password) and password != "" ->
password
_ ->
:crypto.strong_rand_bytes(16) |> Base.encode64()
:error ->
{:crypto.strong_rand_bytes(16) |> Base.encode64(), true}
end
user_data = %{

View file

@ -86,7 +86,8 @@ defmodule Pleroma.Web.ApiSpec.Admin.UserOperation do
type: :string,
description:
"Optional. When omitted, a `password_reset_link` is returned, " <>
"allowing the user to set their own password."
"allowing the user to set their own password. When provided, " <>
"it must not be empty."
}
},
required: [:nickname, :email]

View file

@ -208,6 +208,21 @@ defmodule Pleroma.Web.AdminAPI.UserControllerTest do
refute Map.has_key?(account2["data"], "password_reset_link")
end
test "Explicit empty passwords return a conflict", %{conn: conn} do
conn =
conn
|> put_req_header("accept", "application/json")
|> put_req_header("content-type", "application/json")
|> post("/api/pleroma/admin/users", %{
"users" => [
%{"nickname" => "lain", "email" => "lain@example.org", "password" => ""}
]
})
assert [%{"error" => "password can't be blank"}] = json_response(conn, 409)
refute User.get_by_nickname("lain")
end
test "Password reset token failures roll back the user batch", %{conn: conn} do
with_mock Pleroma.PasswordResetToken, [:passthrough],
create_token: fn user ->