Merge remote-tracking branch 'remotes/origin/develop' into feature/object-hashtags-rework
This commit is contained in:
commit
946e0aab49
|
@ -74,6 +74,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
<details>
|
<details>
|
||||||
<summary>API Changes</summary>
|
<summary>API Changes</summary>
|
||||||
- Admin API: (`GET /api/pleroma/admin/users`) filter users by `unconfirmed` status and `actor_type`.
|
- Admin API: (`GET /api/pleroma/admin/users`) filter users by `unconfirmed` status and `actor_type`.
|
||||||
|
- Admin API: OpenAPI spec for the user-related operations
|
||||||
- Pleroma API: `GET /api/v2/pleroma/chats` added. It is exactly like `GET /api/v1/pleroma/chats` except supports pagination.
|
- Pleroma API: `GET /api/v2/pleroma/chats` added. It is exactly like `GET /api/v1/pleroma/chats` except supports pagination.
|
||||||
- Pleroma API: Add `idempotency_key` to the chat message entity that can be used for optimistic message sending.
|
- Pleroma API: Add `idempotency_key` to the chat message entity that can be used for optimistic message sending.
|
||||||
- Pleroma API: (`GET /api/v1/pleroma/federation_status`) Add a way to get a list of unreachable instances.
|
- Pleroma API: (`GET /api/v1/pleroma/federation_status`) Add a way to get a list of unreachable instances.
|
||||||
|
|
|
@ -2255,13 +2255,6 @@ def update_background(user, background) do
|
||||||
|> update_and_set_cache()
|
|> update_and_set_cache()
|
||||||
end
|
end
|
||||||
|
|
||||||
def roles(%{is_moderator: is_moderator, is_admin: is_admin}) do
|
|
||||||
%{
|
|
||||||
admin: is_admin,
|
|
||||||
moderator: is_moderator
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
def validate_fields(changeset, remote? \\ false) do
|
def validate_fields(changeset, remote? \\ false) do
|
||||||
limit_name = if remote?, do: :max_remote_account_fields, else: :max_account_fields
|
limit_name = if remote?, do: :max_remote_account_fields, else: :max_account_fields
|
||||||
limit = Config.get([:instance, limit_name], 0)
|
limit = Config.get([:instance, limit_name], 0)
|
||||||
|
|
|
@ -13,16 +13,17 @@ defmodule Pleroma.Web.AdminAPI.UserController do
|
||||||
alias Pleroma.Web.ActivityPub.Builder
|
alias Pleroma.Web.ActivityPub.Builder
|
||||||
alias Pleroma.Web.ActivityPub.Pipeline
|
alias Pleroma.Web.ActivityPub.Pipeline
|
||||||
alias Pleroma.Web.AdminAPI
|
alias Pleroma.Web.AdminAPI
|
||||||
alias Pleroma.Web.AdminAPI.AccountView
|
|
||||||
alias Pleroma.Web.AdminAPI.Search
|
alias Pleroma.Web.AdminAPI.Search
|
||||||
alias Pleroma.Web.Plugs.OAuthScopesPlug
|
alias Pleroma.Web.Plugs.OAuthScopesPlug
|
||||||
|
|
||||||
@users_page_size 50
|
@users_page_size 50
|
||||||
|
|
||||||
|
plug(Pleroma.Web.ApiSpec.CastAndValidate)
|
||||||
|
|
||||||
plug(
|
plug(
|
||||||
OAuthScopesPlug,
|
OAuthScopesPlug,
|
||||||
%{scopes: ["admin:read:accounts"]}
|
%{scopes: ["admin:read:accounts"]}
|
||||||
when action in [:list, :show]
|
when action in [:index, :show]
|
||||||
)
|
)
|
||||||
|
|
||||||
plug(
|
plug(
|
||||||
|
@ -44,13 +45,19 @@ defmodule Pleroma.Web.AdminAPI.UserController do
|
||||||
when action in [:follow, :unfollow]
|
when action in [:follow, :unfollow]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
plug(:put_view, Pleroma.Web.AdminAPI.AccountView)
|
||||||
|
|
||||||
action_fallback(AdminAPI.FallbackController)
|
action_fallback(AdminAPI.FallbackController)
|
||||||
|
|
||||||
def delete(conn, %{"nickname" => nickname}) do
|
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.Admin.UserOperation
|
||||||
delete(conn, %{"nicknames" => [nickname]})
|
|
||||||
|
def delete(conn, %{nickname: nickname}) do
|
||||||
|
conn
|
||||||
|
|> Map.put(:body_params, %{nicknames: [nickname]})
|
||||||
|
|> delete(%{})
|
||||||
end
|
end
|
||||||
|
|
||||||
def delete(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do
|
def delete(%{assigns: %{user: admin}, body_params: %{nicknames: nicknames}} = conn, _) do
|
||||||
users = Enum.map(nicknames, &User.get_cached_by_nickname/1)
|
users = Enum.map(nicknames, &User.get_cached_by_nickname/1)
|
||||||
|
|
||||||
Enum.each(users, fn user ->
|
Enum.each(users, fn user ->
|
||||||
|
@ -67,10 +74,16 @@ def delete(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do
|
||||||
json(conn, nicknames)
|
json(conn, nicknames)
|
||||||
end
|
end
|
||||||
|
|
||||||
def follow(%{assigns: %{user: admin}} = conn, %{
|
def follow(
|
||||||
"follower" => follower_nick,
|
%{
|
||||||
"followed" => followed_nick
|
assigns: %{user: admin},
|
||||||
}) do
|
body_params: %{
|
||||||
|
follower: follower_nick,
|
||||||
|
followed: followed_nick
|
||||||
|
}
|
||||||
|
} = conn,
|
||||||
|
_
|
||||||
|
) do
|
||||||
with %User{} = follower <- User.get_cached_by_nickname(follower_nick),
|
with %User{} = follower <- User.get_cached_by_nickname(follower_nick),
|
||||||
%User{} = followed <- User.get_cached_by_nickname(followed_nick) do
|
%User{} = followed <- User.get_cached_by_nickname(followed_nick) do
|
||||||
User.follow(follower, followed)
|
User.follow(follower, followed)
|
||||||
|
@ -86,10 +99,16 @@ def follow(%{assigns: %{user: admin}} = conn, %{
|
||||||
json(conn, "ok")
|
json(conn, "ok")
|
||||||
end
|
end
|
||||||
|
|
||||||
def unfollow(%{assigns: %{user: admin}} = conn, %{
|
def unfollow(
|
||||||
"follower" => follower_nick,
|
%{
|
||||||
"followed" => followed_nick
|
assigns: %{user: admin},
|
||||||
}) do
|
body_params: %{
|
||||||
|
follower: follower_nick,
|
||||||
|
followed: followed_nick
|
||||||
|
}
|
||||||
|
} = conn,
|
||||||
|
_
|
||||||
|
) do
|
||||||
with %User{} = follower <- User.get_cached_by_nickname(follower_nick),
|
with %User{} = follower <- User.get_cached_by_nickname(follower_nick),
|
||||||
%User{} = followed <- User.get_cached_by_nickname(followed_nick) do
|
%User{} = followed <- User.get_cached_by_nickname(followed_nick) do
|
||||||
User.unfollow(follower, followed)
|
User.unfollow(follower, followed)
|
||||||
|
@ -105,9 +124,10 @@ def unfollow(%{assigns: %{user: admin}} = conn, %{
|
||||||
json(conn, "ok")
|
json(conn, "ok")
|
||||||
end
|
end
|
||||||
|
|
||||||
def create(%{assigns: %{user: admin}} = conn, %{"users" => users}) do
|
def create(%{assigns: %{user: admin}, body_params: %{users: users}} = conn, _) do
|
||||||
changesets =
|
changesets =
|
||||||
Enum.map(users, fn %{"nickname" => nickname, "email" => email, "password" => password} ->
|
users
|
||||||
|
|> Enum.map(fn %{nickname: nickname, email: email, password: password} ->
|
||||||
user_data = %{
|
user_data = %{
|
||||||
nickname: nickname,
|
nickname: nickname,
|
||||||
name: nickname,
|
name: nickname,
|
||||||
|
@ -124,52 +144,49 @@ def create(%{assigns: %{user: admin}} = conn, %{"users" => users}) do
|
||||||
end)
|
end)
|
||||||
|
|
||||||
case Pleroma.Repo.transaction(changesets) do
|
case Pleroma.Repo.transaction(changesets) do
|
||||||
{:ok, users} ->
|
{:ok, users_map} ->
|
||||||
res =
|
users =
|
||||||
users
|
users_map
|
||||||
|> Map.values()
|
|> Map.values()
|
||||||
|> Enum.map(fn user ->
|
|> Enum.map(fn user ->
|
||||||
{:ok, user} = User.post_register_action(user)
|
{:ok, user} = User.post_register_action(user)
|
||||||
|
|
||||||
user
|
user
|
||||||
end)
|
end)
|
||||||
|> Enum.map(&AccountView.render("created.json", %{user: &1}))
|
|
||||||
|
|
||||||
ModerationLog.insert_log(%{
|
ModerationLog.insert_log(%{
|
||||||
actor: admin,
|
actor: admin,
|
||||||
subjects: Map.values(users),
|
subjects: users,
|
||||||
action: "create"
|
action: "create"
|
||||||
})
|
})
|
||||||
|
|
||||||
json(conn, res)
|
render(conn, "created_many.json", users: users)
|
||||||
|
|
||||||
{:error, id, changeset, _} ->
|
{:error, id, changeset, _} ->
|
||||||
res =
|
changesets =
|
||||||
Enum.map(changesets.operations, fn
|
Enum.map(changesets.operations, fn
|
||||||
{current_id, {:changeset, _current_changeset, _}} when current_id == id ->
|
{^id, {:changeset, _current_changeset, _}} ->
|
||||||
AccountView.render("create-error.json", %{changeset: changeset})
|
changeset
|
||||||
|
|
||||||
{_, {:changeset, current_changeset, _}} ->
|
{_, {:changeset, current_changeset, _}} ->
|
||||||
AccountView.render("create-error.json", %{changeset: current_changeset})
|
current_changeset
|
||||||
end)
|
end)
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|> put_status(:conflict)
|
|> put_status(:conflict)
|
||||||
|> json(res)
|
|> render("create_errors.json", changesets: changesets)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def show(%{assigns: %{user: admin}} = conn, %{"nickname" => nickname}) do
|
def show(%{assigns: %{user: admin}} = conn, %{nickname: nickname}) do
|
||||||
with %User{} = user <- User.get_cached_by_nickname_or_id(nickname, for: admin) do
|
with %User{} = user <- User.get_cached_by_nickname_or_id(nickname, for: admin) do
|
||||||
conn
|
render(conn, "show.json", %{user: user})
|
||||||
|> put_view(AccountView)
|
|
||||||
|> render("show.json", %{user: user})
|
|
||||||
else
|
else
|
||||||
_ -> {:error, :not_found}
|
_ -> {:error, :not_found}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def toggle_activation(%{assigns: %{user: admin}} = conn, %{"nickname" => nickname}) do
|
def toggle_activation(%{assigns: %{user: admin}} = conn, %{nickname: nickname}) do
|
||||||
user = User.get_cached_by_nickname(nickname)
|
user = User.get_cached_by_nickname(nickname)
|
||||||
|
|
||||||
{:ok, updated_user} = User.set_activation(user, !user.is_active)
|
{:ok, updated_user} = User.set_activation(user, !user.is_active)
|
||||||
|
@ -182,12 +199,10 @@ def toggle_activation(%{assigns: %{user: admin}} = conn, %{"nickname" => nicknam
|
||||||
action: action
|
action: action
|
||||||
})
|
})
|
||||||
|
|
||||||
conn
|
render(conn, "show.json", user: updated_user)
|
||||||
|> put_view(AccountView)
|
|
||||||
|> render("show.json", %{user: updated_user})
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def activate(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do
|
def activate(%{assigns: %{user: admin}, body_params: %{nicknames: nicknames}} = conn, _) do
|
||||||
users = Enum.map(nicknames, &User.get_cached_by_nickname/1)
|
users = Enum.map(nicknames, &User.get_cached_by_nickname/1)
|
||||||
{:ok, updated_users} = User.set_activation(users, true)
|
{:ok, updated_users} = User.set_activation(users, true)
|
||||||
|
|
||||||
|
@ -197,12 +212,10 @@ def activate(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do
|
||||||
action: "activate"
|
action: "activate"
|
||||||
})
|
})
|
||||||
|
|
||||||
conn
|
render(conn, "index.json", users: Keyword.values(updated_users))
|
||||||
|> put_view(AccountView)
|
|
||||||
|> render("index.json", %{users: Keyword.values(updated_users)})
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def deactivate(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do
|
def deactivate(%{assigns: %{user: admin}, body_params: %{nicknames: nicknames}} = conn, _) do
|
||||||
users = Enum.map(nicknames, &User.get_cached_by_nickname/1)
|
users = Enum.map(nicknames, &User.get_cached_by_nickname/1)
|
||||||
{:ok, updated_users} = User.set_activation(users, false)
|
{:ok, updated_users} = User.set_activation(users, false)
|
||||||
|
|
||||||
|
@ -212,12 +225,10 @@ def deactivate(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) d
|
||||||
action: "deactivate"
|
action: "deactivate"
|
||||||
})
|
})
|
||||||
|
|
||||||
conn
|
render(conn, "index.json", users: Keyword.values(updated_users))
|
||||||
|> put_view(AccountView)
|
|
||||||
|> render("index.json", %{users: Keyword.values(updated_users)})
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def approve(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do
|
def approve(%{assigns: %{user: admin}, body_params: %{nicknames: nicknames}} = conn, _) do
|
||||||
users = Enum.map(nicknames, &User.get_cached_by_nickname/1)
|
users = Enum.map(nicknames, &User.get_cached_by_nickname/1)
|
||||||
{:ok, updated_users} = User.approve(users)
|
{:ok, updated_users} = User.approve(users)
|
||||||
|
|
||||||
|
@ -227,36 +238,27 @@ def approve(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do
|
||||||
action: "approve"
|
action: "approve"
|
||||||
})
|
})
|
||||||
|
|
||||||
conn
|
render(conn, "index.json", users: updated_users)
|
||||||
|> put_view(AccountView)
|
|
||||||
|> render("index.json", %{users: updated_users})
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def list(conn, params) do
|
def index(conn, params) do
|
||||||
{page, page_size} = page_params(params)
|
{page, page_size} = page_params(params)
|
||||||
filters = maybe_parse_filters(params["filters"])
|
filters = maybe_parse_filters(params[:filters])
|
||||||
|
|
||||||
search_params =
|
search_params =
|
||||||
%{
|
%{
|
||||||
query: params["query"],
|
query: params[:query],
|
||||||
page: page,
|
page: page,
|
||||||
page_size: page_size,
|
page_size: page_size,
|
||||||
tags: params["tags"],
|
tags: params[:tags],
|
||||||
name: params["name"],
|
name: params[:name],
|
||||||
email: params["email"],
|
email: params[:email],
|
||||||
actor_types: params["actor_types"]
|
actor_types: params[:actor_types]
|
||||||
}
|
}
|
||||||
|> Map.merge(filters)
|
|> Map.merge(filters)
|
||||||
|
|
||||||
with {:ok, users, count} <- Search.user(search_params) do
|
with {:ok, users, count} <- Search.user(search_params) do
|
||||||
json(
|
render(conn, "index.json", users: users, count: count, page_size: page_size)
|
||||||
conn,
|
|
||||||
AccountView.render("index.json",
|
|
||||||
users: users,
|
|
||||||
count: count,
|
|
||||||
page_size: page_size
|
|
||||||
)
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -274,8 +276,8 @@ defp maybe_parse_filters(filters) do
|
||||||
|
|
||||||
defp page_params(params) do
|
defp page_params(params) do
|
||||||
{
|
{
|
||||||
fetch_integer_param(params, "page", 1),
|
fetch_integer_param(params, :page, 1),
|
||||||
fetch_integer_param(params, "page_size", @users_page_size)
|
fetch_integer_param(params, :page_size, @users_page_size)
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -75,7 +75,7 @@ def render("show.json", %{user: user}) do
|
||||||
"display_name" => display_name,
|
"display_name" => display_name,
|
||||||
"is_active" => user.is_active,
|
"is_active" => user.is_active,
|
||||||
"local" => user.local,
|
"local" => user.local,
|
||||||
"roles" => User.roles(user),
|
"roles" => roles(user),
|
||||||
"tags" => user.tags || [],
|
"tags" => user.tags || [],
|
||||||
"is_confirmed" => user.is_confirmed,
|
"is_confirmed" => user.is_confirmed,
|
||||||
"is_approved" => user.is_approved,
|
"is_approved" => user.is_approved,
|
||||||
|
@ -85,6 +85,10 @@ def render("show.json", %{user: user}) do
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def render("created_many.json", %{users: users}) do
|
||||||
|
render_many(users, AccountView, "created.json", as: :user)
|
||||||
|
end
|
||||||
|
|
||||||
def render("created.json", %{user: user}) do
|
def render("created.json", %{user: user}) do
|
||||||
%{
|
%{
|
||||||
type: "success",
|
type: "success",
|
||||||
|
@ -96,7 +100,11 @@ def render("created.json", %{user: user}) do
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def render("create-error.json", %{changeset: %Ecto.Changeset{changes: changes, errors: errors}}) do
|
def render("create_errors.json", %{changesets: changesets}) do
|
||||||
|
render_many(changesets, AccountView, "create_error.json", as: :changeset)
|
||||||
|
end
|
||||||
|
|
||||||
|
def render("create_error.json", %{changeset: %Ecto.Changeset{changes: changes, errors: errors}}) do
|
||||||
%{
|
%{
|
||||||
type: "error",
|
type: "error",
|
||||||
code: 409,
|
code: 409,
|
||||||
|
@ -140,4 +148,11 @@ defp parse_error(errors) do
|
||||||
|
|
||||||
defp image_url(%{"url" => [%{"href" => href} | _]}), do: href
|
defp image_url(%{"url" => [%{"href" => href} | _]}), do: href
|
||||||
defp image_url(_), do: nil
|
defp image_url(_), do: nil
|
||||||
|
|
||||||
|
defp roles(%{is_moderator: is_moderator, is_admin: is_admin}) do
|
||||||
|
%{
|
||||||
|
admin: is_admin,
|
||||||
|
moderator: is_moderator
|
||||||
|
}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -92,9 +92,10 @@ def spec(opts \\ []) do
|
||||||
"Invites",
|
"Invites",
|
||||||
"MediaProxy cache",
|
"MediaProxy cache",
|
||||||
"OAuth application managment",
|
"OAuth application managment",
|
||||||
"Report managment",
|
|
||||||
"Relays",
|
"Relays",
|
||||||
"Status administration"
|
"Report managment",
|
||||||
|
"Status administration",
|
||||||
|
"User administration"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
%{"name" => "Applications", "tags" => ["Applications", "Push subscriptions"]},
|
%{"name" => "Applications", "tags" => ["Applications", "Push subscriptions"]},
|
||||||
|
|
|
@ -0,0 +1,389 @@
|
||||||
|
# Pleroma: A lightweight social networking server
|
||||||
|
# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
defmodule Pleroma.Web.ApiSpec.Admin.UserOperation do
|
||||||
|
alias OpenApiSpex.Operation
|
||||||
|
alias OpenApiSpex.Schema
|
||||||
|
alias Pleroma.Web.ApiSpec.Schemas.ActorType
|
||||||
|
alias Pleroma.Web.ApiSpec.Schemas.ApiError
|
||||||
|
|
||||||
|
import Pleroma.Web.ApiSpec.Helpers
|
||||||
|
|
||||||
|
def open_api_operation(action) do
|
||||||
|
operation = String.to_existing_atom("#{action}_operation")
|
||||||
|
apply(__MODULE__, operation, [])
|
||||||
|
end
|
||||||
|
|
||||||
|
def index_operation do
|
||||||
|
%Operation{
|
||||||
|
tags: ["User administration"],
|
||||||
|
summary: "List users",
|
||||||
|
operationId: "AdminAPI.UserController.index",
|
||||||
|
security: [%{"oAuth" => ["admin:read:accounts"]}],
|
||||||
|
parameters: [
|
||||||
|
Operation.parameter(:filters, :query, :string, "Comma separated list of filters"),
|
||||||
|
Operation.parameter(:query, :query, :string, "Search users query"),
|
||||||
|
Operation.parameter(:name, :query, :string, "Search by display name"),
|
||||||
|
Operation.parameter(:email, :query, :string, "Search by email"),
|
||||||
|
Operation.parameter(:page, :query, :integer, "Page Number"),
|
||||||
|
Operation.parameter(:page_size, :query, :integer, "Number of users to return per page"),
|
||||||
|
Operation.parameter(
|
||||||
|
:actor_types,
|
||||||
|
:query,
|
||||||
|
%Schema{type: :array, items: ActorType},
|
||||||
|
"Filter by actor type"
|
||||||
|
),
|
||||||
|
Operation.parameter(
|
||||||
|
:tags,
|
||||||
|
:query,
|
||||||
|
%Schema{type: :array, items: %Schema{type: :string}},
|
||||||
|
"Filter by tags"
|
||||||
|
)
|
||||||
|
| admin_api_params()
|
||||||
|
],
|
||||||
|
responses: %{
|
||||||
|
200 =>
|
||||||
|
Operation.response(
|
||||||
|
"Response",
|
||||||
|
"application/json",
|
||||||
|
%Schema{
|
||||||
|
type: :object,
|
||||||
|
properties: %{
|
||||||
|
users: %Schema{type: :array, items: user()},
|
||||||
|
count: %Schema{type: :integer},
|
||||||
|
page_size: %Schema{type: :integer}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
),
|
||||||
|
403 => Operation.response("Forbidden", "application/json", ApiError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_operation do
|
||||||
|
%Operation{
|
||||||
|
tags: ["User administration"],
|
||||||
|
summary: "Create a single or multiple users",
|
||||||
|
operationId: "AdminAPI.UserController.create",
|
||||||
|
security: [%{"oAuth" => ["admin:write:accounts"]}],
|
||||||
|
parameters: admin_api_params(),
|
||||||
|
requestBody:
|
||||||
|
request_body(
|
||||||
|
"Parameters",
|
||||||
|
%Schema{
|
||||||
|
description: "POST body for creating users",
|
||||||
|
type: :object,
|
||||||
|
properties: %{
|
||||||
|
users: %Schema{
|
||||||
|
type: :array,
|
||||||
|
items: %Schema{
|
||||||
|
type: :object,
|
||||||
|
properties: %{
|
||||||
|
nickname: %Schema{type: :string},
|
||||||
|
email: %Schema{type: :string},
|
||||||
|
password: %Schema{type: :string}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
),
|
||||||
|
responses: %{
|
||||||
|
200 =>
|
||||||
|
Operation.response("Response", "application/json", %Schema{
|
||||||
|
type: :array,
|
||||||
|
items: %Schema{
|
||||||
|
type: :object,
|
||||||
|
properties: %{
|
||||||
|
code: %Schema{type: :integer},
|
||||||
|
type: %Schema{type: :string},
|
||||||
|
data: %Schema{
|
||||||
|
type: :object,
|
||||||
|
properties: %{
|
||||||
|
email: %Schema{type: :string, format: :email},
|
||||||
|
nickname: %Schema{type: :string}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
403 => Operation.response("Forbidden", "application/json", ApiError),
|
||||||
|
409 =>
|
||||||
|
Operation.response("Conflict", "application/json", %Schema{
|
||||||
|
type: :array,
|
||||||
|
items: %Schema{
|
||||||
|
type: :object,
|
||||||
|
properties: %{
|
||||||
|
code: %Schema{type: :integer},
|
||||||
|
error: %Schema{type: :string},
|
||||||
|
type: %Schema{type: :string},
|
||||||
|
data: %Schema{
|
||||||
|
type: :object,
|
||||||
|
properties: %{
|
||||||
|
email: %Schema{type: :string, format: :email},
|
||||||
|
nickname: %Schema{type: :string}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def show_operation do
|
||||||
|
%Operation{
|
||||||
|
tags: ["User administration"],
|
||||||
|
summary: "Show user",
|
||||||
|
operationId: "AdminAPI.UserController.show",
|
||||||
|
security: [%{"oAuth" => ["admin:read:accounts"]}],
|
||||||
|
parameters: [
|
||||||
|
Operation.parameter(
|
||||||
|
:nickname,
|
||||||
|
:path,
|
||||||
|
:string,
|
||||||
|
"User nickname or ID"
|
||||||
|
)
|
||||||
|
| admin_api_params()
|
||||||
|
],
|
||||||
|
responses: %{
|
||||||
|
200 => Operation.response("Response", "application/json", user()),
|
||||||
|
403 => Operation.response("Forbidden", "application/json", ApiError),
|
||||||
|
404 => Operation.response("Not Found", "application/json", ApiError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def follow_operation do
|
||||||
|
%Operation{
|
||||||
|
tags: ["User administration"],
|
||||||
|
summary: "Follow",
|
||||||
|
operationId: "AdminAPI.UserController.follow",
|
||||||
|
security: [%{"oAuth" => ["admin:write:follows"]}],
|
||||||
|
parameters: admin_api_params(),
|
||||||
|
requestBody:
|
||||||
|
request_body(
|
||||||
|
"Parameters",
|
||||||
|
%Schema{
|
||||||
|
type: :object,
|
||||||
|
properties: %{
|
||||||
|
follower: %Schema{type: :string, description: "Follower nickname"},
|
||||||
|
followed: %Schema{type: :string, description: "Followed nickname"}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
),
|
||||||
|
responses: %{
|
||||||
|
200 => Operation.response("Response", "application/json", %Schema{type: :string}),
|
||||||
|
403 => Operation.response("Forbidden", "application/json", ApiError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def unfollow_operation do
|
||||||
|
%Operation{
|
||||||
|
tags: ["User administration"],
|
||||||
|
summary: "Unfollow",
|
||||||
|
operationId: "AdminAPI.UserController.unfollow",
|
||||||
|
security: [%{"oAuth" => ["admin:write:follows"]}],
|
||||||
|
parameters: admin_api_params(),
|
||||||
|
requestBody:
|
||||||
|
request_body(
|
||||||
|
"Parameters",
|
||||||
|
%Schema{
|
||||||
|
type: :object,
|
||||||
|
properties: %{
|
||||||
|
follower: %Schema{type: :string, description: "Follower nickname"},
|
||||||
|
followed: %Schema{type: :string, description: "Followed nickname"}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
),
|
||||||
|
responses: %{
|
||||||
|
200 => Operation.response("Response", "application/json", %Schema{type: :string}),
|
||||||
|
403 => Operation.response("Forbidden", "application/json", ApiError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def approve_operation do
|
||||||
|
%Operation{
|
||||||
|
tags: ["User administration"],
|
||||||
|
summary: "Approve multiple users",
|
||||||
|
operationId: "AdminAPI.UserController.approve",
|
||||||
|
security: [%{"oAuth" => ["admin:write:accounts"]}],
|
||||||
|
parameters: admin_api_params(),
|
||||||
|
requestBody:
|
||||||
|
request_body(
|
||||||
|
"Parameters",
|
||||||
|
%Schema{
|
||||||
|
description: "POST body for deleting multiple users",
|
||||||
|
type: :object,
|
||||||
|
properties: %{
|
||||||
|
nicknames: %Schema{
|
||||||
|
type: :array,
|
||||||
|
items: %Schema{type: :string}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
),
|
||||||
|
responses: %{
|
||||||
|
200 =>
|
||||||
|
Operation.response("Response", "application/json", %Schema{
|
||||||
|
type: :object,
|
||||||
|
properties: %{user: %Schema{type: :array, items: user()}}
|
||||||
|
}),
|
||||||
|
403 => Operation.response("Forbidden", "application/json", ApiError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def toggle_activation_operation do
|
||||||
|
%Operation{
|
||||||
|
tags: ["User administration"],
|
||||||
|
summary: "Toggle user activation",
|
||||||
|
operationId: "AdminAPI.UserController.toggle_activation",
|
||||||
|
security: [%{"oAuth" => ["admin:write:accounts"]}],
|
||||||
|
parameters: [
|
||||||
|
Operation.parameter(:nickname, :path, :string, "User nickname")
|
||||||
|
| admin_api_params()
|
||||||
|
],
|
||||||
|
responses: %{
|
||||||
|
200 => Operation.response("Response", "application/json", user()),
|
||||||
|
403 => Operation.response("Forbidden", "application/json", ApiError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def activate_operation do
|
||||||
|
%Operation{
|
||||||
|
tags: ["User administration"],
|
||||||
|
summary: "Activate multiple users",
|
||||||
|
operationId: "AdminAPI.UserController.activate",
|
||||||
|
security: [%{"oAuth" => ["admin:write:accounts"]}],
|
||||||
|
parameters: admin_api_params(),
|
||||||
|
requestBody:
|
||||||
|
request_body(
|
||||||
|
"Parameters",
|
||||||
|
%Schema{
|
||||||
|
description: "POST body for deleting multiple users",
|
||||||
|
type: :object,
|
||||||
|
properties: %{
|
||||||
|
nicknames: %Schema{
|
||||||
|
type: :array,
|
||||||
|
items: %Schema{type: :string}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
),
|
||||||
|
responses: %{
|
||||||
|
200 =>
|
||||||
|
Operation.response("Response", "application/json", %Schema{
|
||||||
|
type: :object,
|
||||||
|
properties: %{user: %Schema{type: :array, items: user()}}
|
||||||
|
}),
|
||||||
|
403 => Operation.response("Forbidden", "application/json", ApiError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def deactivate_operation do
|
||||||
|
%Operation{
|
||||||
|
tags: ["User administration"],
|
||||||
|
summary: "Deactivates multiple users",
|
||||||
|
operationId: "AdminAPI.UserController.deactivate",
|
||||||
|
security: [%{"oAuth" => ["admin:write:accounts"]}],
|
||||||
|
parameters: admin_api_params(),
|
||||||
|
requestBody:
|
||||||
|
request_body(
|
||||||
|
"Parameters",
|
||||||
|
%Schema{
|
||||||
|
description: "POST body for deleting multiple users",
|
||||||
|
type: :object,
|
||||||
|
properties: %{
|
||||||
|
nicknames: %Schema{
|
||||||
|
type: :array,
|
||||||
|
items: %Schema{type: :string}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
),
|
||||||
|
responses: %{
|
||||||
|
200 =>
|
||||||
|
Operation.response("Response", "application/json", %Schema{
|
||||||
|
type: :object,
|
||||||
|
properties: %{user: %Schema{type: :array, items: user()}}
|
||||||
|
}),
|
||||||
|
403 => Operation.response("Forbidden", "application/json", ApiError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def delete_operation do
|
||||||
|
%Operation{
|
||||||
|
tags: ["User administration"],
|
||||||
|
summary: "Removes a single or multiple users",
|
||||||
|
operationId: "AdminAPI.UserController.delete",
|
||||||
|
security: [%{"oAuth" => ["admin:write:accounts"]}],
|
||||||
|
parameters: [
|
||||||
|
Operation.parameter(
|
||||||
|
:nickname,
|
||||||
|
:query,
|
||||||
|
:string,
|
||||||
|
"User nickname"
|
||||||
|
)
|
||||||
|
| admin_api_params()
|
||||||
|
],
|
||||||
|
requestBody:
|
||||||
|
request_body(
|
||||||
|
"Parameters",
|
||||||
|
%Schema{
|
||||||
|
description: "POST body for deleting multiple users",
|
||||||
|
type: :object,
|
||||||
|
properties: %{
|
||||||
|
nicknames: %Schema{
|
||||||
|
type: :array,
|
||||||
|
items: %Schema{type: :string}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
),
|
||||||
|
responses: %{
|
||||||
|
200 =>
|
||||||
|
Operation.response("Response", "application/json", %Schema{
|
||||||
|
description: "Array of nicknames",
|
||||||
|
type: :array,
|
||||||
|
items: %Schema{type: :string}
|
||||||
|
}),
|
||||||
|
403 => Operation.response("Forbidden", "application/json", ApiError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
defp user do
|
||||||
|
%Schema{
|
||||||
|
type: :object,
|
||||||
|
properties: %{
|
||||||
|
id: %Schema{type: :string},
|
||||||
|
email: %Schema{type: :string, format: :email},
|
||||||
|
avatar: %Schema{type: :string, format: :uri},
|
||||||
|
nickname: %Schema{type: :string},
|
||||||
|
display_name: %Schema{type: :string},
|
||||||
|
is_active: %Schema{type: :boolean},
|
||||||
|
local: %Schema{type: :boolean},
|
||||||
|
roles: %Schema{
|
||||||
|
type: :object,
|
||||||
|
properties: %{
|
||||||
|
admin: %Schema{type: :boolean},
|
||||||
|
moderator: %Schema{type: :boolean}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
tags: %Schema{type: :array, items: %Schema{type: :string}},
|
||||||
|
is_confirmed: %Schema{type: :boolean},
|
||||||
|
is_approved: %Schema{type: :boolean},
|
||||||
|
url: %Schema{type: :string, format: :uri},
|
||||||
|
registration_reason: %Schema{type: :string, nullable: true},
|
||||||
|
actor_type: %Schema{type: :string}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
|
@ -204,7 +204,7 @@ defmodule Pleroma.Web.Router do
|
||||||
get("/users/:nickname/credentials", AdminAPIController, :show_user_credentials)
|
get("/users/:nickname/credentials", AdminAPIController, :show_user_credentials)
|
||||||
patch("/users/:nickname/credentials", AdminAPIController, :update_user_credentials)
|
patch("/users/:nickname/credentials", AdminAPIController, :update_user_credentials)
|
||||||
|
|
||||||
get("/users", UserController, :list)
|
get("/users", UserController, :index)
|
||||||
get("/users/:nickname", UserController, :show)
|
get("/users/:nickname", UserController, :show)
|
||||||
get("/users/:nickname/statuses", AdminAPIController, :list_user_statuses)
|
get("/users/:nickname/statuses", AdminAPIController, :list_user_statuses)
|
||||||
get("/users/:nickname/chats", AdminAPIController, :list_user_chats)
|
get("/users/:nickname/chats", AdminAPIController, :list_user_chats)
|
||||||
|
|
|
@ -44,7 +44,7 @@ test "with valid `admin_token` query parameter, skips OAuth scopes check" do
|
||||||
|
|
||||||
conn = get(build_conn(), "/api/pleroma/admin/users/#{user.nickname}?admin_token=password123")
|
conn = get(build_conn(), "/api/pleroma/admin/users/#{user.nickname}?admin_token=password123")
|
||||||
|
|
||||||
assert json_response(conn, 200)
|
assert json_response_and_validate_schema(conn, 200)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "GET /api/pleroma/admin/users/:nickname requires admin:read:accounts or broader scope",
|
test "GET /api/pleroma/admin/users/:nickname requires admin:read:accounts or broader scope",
|
||||||
|
@ -67,7 +67,7 @@ test "GET /api/pleroma/admin/users/:nickname requires admin:read:accounts or bro
|
||||||
|> assign(:token, good_token)
|
|> assign(:token, good_token)
|
||||||
|> get(url)
|
|> get(url)
|
||||||
|
|
||||||
assert json_response(conn, 200)
|
assert json_response_and_validate_schema(conn, 200)
|
||||||
end
|
end
|
||||||
|
|
||||||
for good_token <- [good_token1, good_token2, good_token3] do
|
for good_token <- [good_token1, good_token2, good_token3] do
|
||||||
|
@ -87,7 +87,7 @@ test "GET /api/pleroma/admin/users/:nickname requires admin:read:accounts or bro
|
||||||
|> assign(:token, bad_token)
|
|> assign(:token, bad_token)
|
||||||
|> get(url)
|
|> get(url)
|
||||||
|
|
||||||
assert json_response(conn, :forbidden)
|
assert json_response_and_validate_schema(conn, :forbidden)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -131,7 +131,7 @@ test "single user", %{admin: admin, conn: conn} do
|
||||||
assert ModerationLog.get_log_entry_message(log_entry) ==
|
assert ModerationLog.get_log_entry_message(log_entry) ==
|
||||||
"@#{admin.nickname} deleted users: @#{user.nickname}"
|
"@#{admin.nickname} deleted users: @#{user.nickname}"
|
||||||
|
|
||||||
assert json_response(conn, 200) == [user.nickname]
|
assert json_response_and_validate_schema(conn, 200) == [user.nickname]
|
||||||
|
|
||||||
user = Repo.get(User, user.id)
|
user = Repo.get(User, user.id)
|
||||||
refute user.is_active
|
refute user.is_active
|
||||||
|
@ -152,28 +152,30 @@ test "multiple users", %{admin: admin, conn: conn} do
|
||||||
user_one = insert(:user)
|
user_one = insert(:user)
|
||||||
user_two = insert(:user)
|
user_two = insert(:user)
|
||||||
|
|
||||||
conn =
|
response =
|
||||||
conn
|
conn
|
||||||
|> put_req_header("accept", "application/json")
|
|> put_req_header("accept", "application/json")
|
||||||
|
|> put_req_header("content-type", "application/json")
|
||||||
|> delete("/api/pleroma/admin/users", %{
|
|> delete("/api/pleroma/admin/users", %{
|
||||||
nicknames: [user_one.nickname, user_two.nickname]
|
nicknames: [user_one.nickname, user_two.nickname]
|
||||||
})
|
})
|
||||||
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
log_entry = Repo.one(ModerationLog)
|
log_entry = Repo.one(ModerationLog)
|
||||||
|
|
||||||
assert ModerationLog.get_log_entry_message(log_entry) ==
|
assert ModerationLog.get_log_entry_message(log_entry) ==
|
||||||
"@#{admin.nickname} deleted users: @#{user_one.nickname}, @#{user_two.nickname}"
|
"@#{admin.nickname} deleted users: @#{user_one.nickname}, @#{user_two.nickname}"
|
||||||
|
|
||||||
response = json_response(conn, 200)
|
|
||||||
assert response -- [user_one.nickname, user_two.nickname] == []
|
assert response -- [user_one.nickname, user_two.nickname] == []
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "/api/pleroma/admin/users" do
|
describe "/api/pleroma/admin/users" do
|
||||||
test "Create", %{conn: conn} do
|
test "Create", %{conn: conn} do
|
||||||
conn =
|
response =
|
||||||
conn
|
conn
|
||||||
|> put_req_header("accept", "application/json")
|
|> put_req_header("accept", "application/json")
|
||||||
|
|> put_req_header("content-type", "application/json")
|
||||||
|> post("/api/pleroma/admin/users", %{
|
|> post("/api/pleroma/admin/users", %{
|
||||||
"users" => [
|
"users" => [
|
||||||
%{
|
%{
|
||||||
|
@ -188,8 +190,9 @@ test "Create", %{conn: conn} do
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|> json_response_and_validate_schema(200)
|
||||||
|
|> Enum.map(&Map.get(&1, "type"))
|
||||||
|
|
||||||
response = json_response(conn, 200) |> Enum.map(&Map.get(&1, "type"))
|
|
||||||
assert response == ["success", "success"]
|
assert response == ["success", "success"]
|
||||||
|
|
||||||
log_entry = Repo.one(ModerationLog)
|
log_entry = Repo.one(ModerationLog)
|
||||||
|
@ -203,6 +206,7 @@ test "Cannot create user with existing email", %{conn: conn} do
|
||||||
conn =
|
conn =
|
||||||
conn
|
conn
|
||||||
|> put_req_header("accept", "application/json")
|
|> put_req_header("accept", "application/json")
|
||||||
|
|> put_req_header("content-type", "application/json")
|
||||||
|> post("/api/pleroma/admin/users", %{
|
|> post("/api/pleroma/admin/users", %{
|
||||||
"users" => [
|
"users" => [
|
||||||
%{
|
%{
|
||||||
|
@ -213,7 +217,7 @@ test "Cannot create user with existing email", %{conn: conn} do
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
assert json_response(conn, 409) == [
|
assert json_response_and_validate_schema(conn, 409) == [
|
||||||
%{
|
%{
|
||||||
"code" => 409,
|
"code" => 409,
|
||||||
"data" => %{
|
"data" => %{
|
||||||
|
@ -232,6 +236,7 @@ test "Cannot create user with existing nickname", %{conn: conn} do
|
||||||
conn =
|
conn =
|
||||||
conn
|
conn
|
||||||
|> put_req_header("accept", "application/json")
|
|> put_req_header("accept", "application/json")
|
||||||
|
|> put_req_header("content-type", "application/json")
|
||||||
|> post("/api/pleroma/admin/users", %{
|
|> post("/api/pleroma/admin/users", %{
|
||||||
"users" => [
|
"users" => [
|
||||||
%{
|
%{
|
||||||
|
@ -242,7 +247,7 @@ test "Cannot create user with existing nickname", %{conn: conn} do
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
assert json_response(conn, 409) == [
|
assert json_response_and_validate_schema(conn, 409) == [
|
||||||
%{
|
%{
|
||||||
"code" => 409,
|
"code" => 409,
|
||||||
"data" => %{
|
"data" => %{
|
||||||
|
@ -261,6 +266,7 @@ test "Multiple user creation works in transaction", %{conn: conn} do
|
||||||
conn =
|
conn =
|
||||||
conn
|
conn
|
||||||
|> put_req_header("accept", "application/json")
|
|> put_req_header("accept", "application/json")
|
||||||
|
|> put_req_header("content-type", "application/json")
|
||||||
|> post("/api/pleroma/admin/users", %{
|
|> post("/api/pleroma/admin/users", %{
|
||||||
"users" => [
|
"users" => [
|
||||||
%{
|
%{
|
||||||
|
@ -276,7 +282,7 @@ test "Multiple user creation works in transaction", %{conn: conn} do
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
assert json_response(conn, 409) == [
|
assert json_response_and_validate_schema(conn, 409) == [
|
||||||
%{
|
%{
|
||||||
"code" => 409,
|
"code" => 409,
|
||||||
"data" => %{
|
"data" => %{
|
||||||
|
@ -307,7 +313,7 @@ test "Show", %{conn: conn} do
|
||||||
|
|
||||||
conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}")
|
conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}")
|
||||||
|
|
||||||
assert user_response(user) == json_response(conn, 200)
|
assert user_response(user) == json_response_and_validate_schema(conn, 200)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "when the user doesn't exist", %{conn: conn} do
|
test "when the user doesn't exist", %{conn: conn} do
|
||||||
|
@ -315,7 +321,7 @@ test "when the user doesn't exist", %{conn: conn} do
|
||||||
|
|
||||||
conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}")
|
conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}")
|
||||||
|
|
||||||
assert %{"error" => "Not found"} == json_response(conn, 404)
|
assert %{"error" => "Not found"} == json_response_and_validate_schema(conn, 404)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -326,6 +332,7 @@ test "allows to force-follow another user", %{admin: admin, conn: conn} do
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|> put_req_header("accept", "application/json")
|
|> put_req_header("accept", "application/json")
|
||||||
|
|> put_req_header("content-type", "application/json")
|
||||||
|> post("/api/pleroma/admin/users/follow", %{
|
|> post("/api/pleroma/admin/users/follow", %{
|
||||||
"follower" => follower.nickname,
|
"follower" => follower.nickname,
|
||||||
"followed" => user.nickname
|
"followed" => user.nickname
|
||||||
|
@ -352,6 +359,7 @@ test "allows to force-unfollow another user", %{admin: admin, conn: conn} do
|
||||||
|
|
||||||
conn
|
conn
|
||||||
|> put_req_header("accept", "application/json")
|
|> put_req_header("accept", "application/json")
|
||||||
|
|> put_req_header("content-type", "application/json")
|
||||||
|> post("/api/pleroma/admin/users/unfollow", %{
|
|> post("/api/pleroma/admin/users/unfollow", %{
|
||||||
"follower" => follower.nickname,
|
"follower" => follower.nickname,
|
||||||
"followed" => user.nickname
|
"followed" => user.nickname
|
||||||
|
@ -395,7 +403,7 @@ test "renders users array for the first page", %{conn: conn, admin: admin} do
|
||||||
]
|
]
|
||||||
|> Enum.sort_by(& &1["nickname"])
|
|> Enum.sort_by(& &1["nickname"])
|
||||||
|
|
||||||
assert json_response(conn, 200) == %{
|
assert json_response_and_validate_schema(conn, 200) == %{
|
||||||
"count" => 3,
|
"count" => 3,
|
||||||
"page_size" => 50,
|
"page_size" => 50,
|
||||||
"users" => users
|
"users" => users
|
||||||
|
@ -410,7 +418,7 @@ test "pagination works correctly with service users", %{conn: conn} do
|
||||||
assert %{"count" => 26, "page_size" => 10, "users" => users1} =
|
assert %{"count" => 26, "page_size" => 10, "users" => users1} =
|
||||||
conn
|
conn
|
||||||
|> get("/api/pleroma/admin/users?page=1&filters=", %{page_size: "10"})
|
|> get("/api/pleroma/admin/users?page=1&filters=", %{page_size: "10"})
|
||||||
|> json_response(200)
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
assert Enum.count(users1) == 10
|
assert Enum.count(users1) == 10
|
||||||
assert service1 not in users1
|
assert service1 not in users1
|
||||||
|
@ -418,7 +426,7 @@ test "pagination works correctly with service users", %{conn: conn} do
|
||||||
assert %{"count" => 26, "page_size" => 10, "users" => users2} =
|
assert %{"count" => 26, "page_size" => 10, "users" => users2} =
|
||||||
conn
|
conn
|
||||||
|> get("/api/pleroma/admin/users?page=2&filters=", %{page_size: "10"})
|
|> get("/api/pleroma/admin/users?page=2&filters=", %{page_size: "10"})
|
||||||
|> json_response(200)
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
assert Enum.count(users2) == 10
|
assert Enum.count(users2) == 10
|
||||||
assert service1 not in users2
|
assert service1 not in users2
|
||||||
|
@ -426,7 +434,7 @@ test "pagination works correctly with service users", %{conn: conn} do
|
||||||
assert %{"count" => 26, "page_size" => 10, "users" => users3} =
|
assert %{"count" => 26, "page_size" => 10, "users" => users3} =
|
||||||
conn
|
conn
|
||||||
|> get("/api/pleroma/admin/users?page=3&filters=", %{page_size: "10"})
|
|> get("/api/pleroma/admin/users?page=3&filters=", %{page_size: "10"})
|
||||||
|> json_response(200)
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
assert Enum.count(users3) == 6
|
assert Enum.count(users3) == 6
|
||||||
assert service1 not in users3
|
assert service1 not in users3
|
||||||
|
@ -437,7 +445,7 @@ test "renders empty array for the second page", %{conn: conn} do
|
||||||
|
|
||||||
conn = get(conn, "/api/pleroma/admin/users?page=2")
|
conn = get(conn, "/api/pleroma/admin/users?page=2")
|
||||||
|
|
||||||
assert json_response(conn, 200) == %{
|
assert json_response_and_validate_schema(conn, 200) == %{
|
||||||
"count" => 2,
|
"count" => 2,
|
||||||
"page_size" => 50,
|
"page_size" => 50,
|
||||||
"users" => []
|
"users" => []
|
||||||
|
@ -449,7 +457,7 @@ test "regular search", %{conn: conn} do
|
||||||
|
|
||||||
conn = get(conn, "/api/pleroma/admin/users?query=bo")
|
conn = get(conn, "/api/pleroma/admin/users?query=bo")
|
||||||
|
|
||||||
assert json_response(conn, 200) == %{
|
assert json_response_and_validate_schema(conn, 200) == %{
|
||||||
"count" => 1,
|
"count" => 1,
|
||||||
"page_size" => 50,
|
"page_size" => 50,
|
||||||
"users" => [user_response(user, %{"local" => true})]
|
"users" => [user_response(user, %{"local" => true})]
|
||||||
|
@ -462,7 +470,7 @@ test "search by domain", %{conn: conn} do
|
||||||
|
|
||||||
conn = get(conn, "/api/pleroma/admin/users?query=domain.com")
|
conn = get(conn, "/api/pleroma/admin/users?query=domain.com")
|
||||||
|
|
||||||
assert json_response(conn, 200) == %{
|
assert json_response_and_validate_schema(conn, 200) == %{
|
||||||
"count" => 1,
|
"count" => 1,
|
||||||
"page_size" => 50,
|
"page_size" => 50,
|
||||||
"users" => [user_response(user)]
|
"users" => [user_response(user)]
|
||||||
|
@ -475,7 +483,7 @@ test "search by full nickname", %{conn: conn} do
|
||||||
|
|
||||||
conn = get(conn, "/api/pleroma/admin/users?query=nickname@domain.com")
|
conn = get(conn, "/api/pleroma/admin/users?query=nickname@domain.com")
|
||||||
|
|
||||||
assert json_response(conn, 200) == %{
|
assert json_response_and_validate_schema(conn, 200) == %{
|
||||||
"count" => 1,
|
"count" => 1,
|
||||||
"page_size" => 50,
|
"page_size" => 50,
|
||||||
"users" => [user_response(user)]
|
"users" => [user_response(user)]
|
||||||
|
@ -488,7 +496,7 @@ test "search by display name", %{conn: conn} do
|
||||||
|
|
||||||
conn = get(conn, "/api/pleroma/admin/users?name=display")
|
conn = get(conn, "/api/pleroma/admin/users?name=display")
|
||||||
|
|
||||||
assert json_response(conn, 200) == %{
|
assert json_response_and_validate_schema(conn, 200) == %{
|
||||||
"count" => 1,
|
"count" => 1,
|
||||||
"page_size" => 50,
|
"page_size" => 50,
|
||||||
"users" => [user_response(user)]
|
"users" => [user_response(user)]
|
||||||
|
@ -501,7 +509,7 @@ test "search by email", %{conn: conn} do
|
||||||
|
|
||||||
conn = get(conn, "/api/pleroma/admin/users?email=email@example.com")
|
conn = get(conn, "/api/pleroma/admin/users?email=email@example.com")
|
||||||
|
|
||||||
assert json_response(conn, 200) == %{
|
assert json_response_and_validate_schema(conn, 200) == %{
|
||||||
"count" => 1,
|
"count" => 1,
|
||||||
"page_size" => 50,
|
"page_size" => 50,
|
||||||
"users" => [user_response(user)]
|
"users" => [user_response(user)]
|
||||||
|
@ -514,7 +522,7 @@ test "regular search with page size", %{conn: conn} do
|
||||||
|
|
||||||
conn1 = get(conn, "/api/pleroma/admin/users?query=a&page_size=1&page=1")
|
conn1 = get(conn, "/api/pleroma/admin/users?query=a&page_size=1&page=1")
|
||||||
|
|
||||||
assert json_response(conn1, 200) == %{
|
assert json_response_and_validate_schema(conn1, 200) == %{
|
||||||
"count" => 2,
|
"count" => 2,
|
||||||
"page_size" => 1,
|
"page_size" => 1,
|
||||||
"users" => [user_response(user)]
|
"users" => [user_response(user)]
|
||||||
|
@ -522,7 +530,7 @@ test "regular search with page size", %{conn: conn} do
|
||||||
|
|
||||||
conn2 = get(conn, "/api/pleroma/admin/users?query=a&page_size=1&page=2")
|
conn2 = get(conn, "/api/pleroma/admin/users?query=a&page_size=1&page=2")
|
||||||
|
|
||||||
assert json_response(conn2, 200) == %{
|
assert json_response_and_validate_schema(conn2, 200) == %{
|
||||||
"count" => 2,
|
"count" => 2,
|
||||||
"page_size" => 1,
|
"page_size" => 1,
|
||||||
"users" => [user_response(user2)]
|
"users" => [user_response(user2)]
|
||||||
|
@ -542,7 +550,7 @@ test "only local users" do
|
||||||
|> assign(:token, token)
|
|> assign(:token, token)
|
||||||
|> get("/api/pleroma/admin/users?query=bo&filters=local")
|
|> get("/api/pleroma/admin/users?query=bo&filters=local")
|
||||||
|
|
||||||
assert json_response(conn, 200) == %{
|
assert json_response_and_validate_schema(conn, 200) == %{
|
||||||
"count" => 1,
|
"count" => 1,
|
||||||
"page_size" => 50,
|
"page_size" => 50,
|
||||||
"users" => [user_response(user)]
|
"users" => [user_response(user)]
|
||||||
|
@ -570,7 +578,7 @@ test "only local users with no query", %{conn: conn, admin: old_admin} do
|
||||||
]
|
]
|
||||||
|> Enum.sort_by(& &1["nickname"])
|
|> Enum.sort_by(& &1["nickname"])
|
||||||
|
|
||||||
assert json_response(conn, 200) == %{
|
assert json_response_and_validate_schema(conn, 200) == %{
|
||||||
"count" => 3,
|
"count" => 3,
|
||||||
"page_size" => 50,
|
"page_size" => 50,
|
||||||
"users" => users
|
"users" => users
|
||||||
|
@ -587,7 +595,7 @@ test "only unconfirmed users", %{conn: conn} do
|
||||||
result =
|
result =
|
||||||
conn
|
conn
|
||||||
|> get("/api/pleroma/admin/users?filters=unconfirmed")
|
|> get("/api/pleroma/admin/users?filters=unconfirmed")
|
||||||
|> json_response(200)
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
users =
|
users =
|
||||||
Enum.map([old_user, sad_user], fn user ->
|
Enum.map([old_user, sad_user], fn user ->
|
||||||
|
@ -620,7 +628,7 @@ test "only unapproved users", %{conn: conn} do
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
assert json_response(conn, 200) == %{
|
assert json_response_and_validate_schema(conn, 200) == %{
|
||||||
"count" => 1,
|
"count" => 1,
|
||||||
"page_size" => 50,
|
"page_size" => 50,
|
||||||
"users" => users
|
"users" => users
|
||||||
|
@ -647,7 +655,7 @@ test "load only admins", %{conn: conn, admin: admin} do
|
||||||
]
|
]
|
||||||
|> Enum.sort_by(& &1["nickname"])
|
|> Enum.sort_by(& &1["nickname"])
|
||||||
|
|
||||||
assert json_response(conn, 200) == %{
|
assert json_response_and_validate_schema(conn, 200) == %{
|
||||||
"count" => 2,
|
"count" => 2,
|
||||||
"page_size" => 50,
|
"page_size" => 50,
|
||||||
"users" => users
|
"users" => users
|
||||||
|
@ -661,7 +669,7 @@ test "load only moderators", %{conn: conn} do
|
||||||
|
|
||||||
conn = get(conn, "/api/pleroma/admin/users?filters=is_moderator")
|
conn = get(conn, "/api/pleroma/admin/users?filters=is_moderator")
|
||||||
|
|
||||||
assert json_response(conn, 200) == %{
|
assert json_response_and_validate_schema(conn, 200) == %{
|
||||||
"count" => 1,
|
"count" => 1,
|
||||||
"page_size" => 50,
|
"page_size" => 50,
|
||||||
"users" => [
|
"users" => [
|
||||||
|
@ -682,8 +690,8 @@ test "load users with actor_type is Person", %{admin: admin, conn: conn} do
|
||||||
|
|
||||||
response =
|
response =
|
||||||
conn
|
conn
|
||||||
|> get(user_path(conn, :list), %{actor_types: ["Person"]})
|
|> get(user_path(conn, :index), %{actor_types: ["Person"]})
|
||||||
|> json_response(200)
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
users =
|
users =
|
||||||
[
|
[
|
||||||
|
@ -705,8 +713,8 @@ test "load users with actor_type is Person and Service", %{admin: admin, conn: c
|
||||||
|
|
||||||
response =
|
response =
|
||||||
conn
|
conn
|
||||||
|> get(user_path(conn, :list), %{actor_types: ["Person", "Service"]})
|
|> get(user_path(conn, :index), %{actor_types: ["Person", "Service"]})
|
||||||
|> json_response(200)
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
users =
|
users =
|
||||||
[
|
[
|
||||||
|
@ -728,8 +736,8 @@ test "load users with actor_type is Service", %{conn: conn} do
|
||||||
|
|
||||||
response =
|
response =
|
||||||
conn
|
conn
|
||||||
|> get(user_path(conn, :list), %{actor_types: ["Service"]})
|
|> get(user_path(conn, :index), %{actor_types: ["Service"]})
|
||||||
|> json_response(200)
|
|> json_response_and_validate_schema(200)
|
||||||
|
|
||||||
users = [user_response(user_service, %{"actor_type" => "Service"})]
|
users = [user_response(user_service, %{"actor_type" => "Service"})]
|
||||||
|
|
||||||
|
@ -751,7 +759,7 @@ test "load users with tags list", %{conn: conn} do
|
||||||
]
|
]
|
||||||
|> Enum.sort_by(& &1["nickname"])
|
|> Enum.sort_by(& &1["nickname"])
|
||||||
|
|
||||||
assert json_response(conn, 200) == %{
|
assert json_response_and_validate_schema(conn, 200) == %{
|
||||||
"count" => 2,
|
"count" => 2,
|
||||||
"page_size" => 50,
|
"page_size" => 50,
|
||||||
"users" => users
|
"users" => users
|
||||||
|
@ -776,7 +784,7 @@ test "`active` filters out users pending approval", %{token: token} do
|
||||||
%{"id" => ^admin_id},
|
%{"id" => ^admin_id},
|
||||||
%{"id" => ^user_id}
|
%{"id" => ^user_id}
|
||||||
]
|
]
|
||||||
} = json_response(conn, 200)
|
} = json_response_and_validate_schema(conn, 200)
|
||||||
end
|
end
|
||||||
|
|
||||||
test "it works with multiple filters" do
|
test "it works with multiple filters" do
|
||||||
|
@ -793,7 +801,7 @@ test "it works with multiple filters" do
|
||||||
|> assign(:token, token)
|
|> assign(:token, token)
|
||||||
|> get("/api/pleroma/admin/users?filters=deactivated,external")
|
|> get("/api/pleroma/admin/users?filters=deactivated,external")
|
||||||
|
|
||||||
assert json_response(conn, 200) == %{
|
assert json_response_and_validate_schema(conn, 200) == %{
|
||||||
"count" => 1,
|
"count" => 1,
|
||||||
"page_size" => 50,
|
"page_size" => 50,
|
||||||
"users" => [user_response(user)]
|
"users" => [user_response(user)]
|
||||||
|
@ -805,7 +813,7 @@ test "it omits relay user", %{admin: admin, conn: conn} do
|
||||||
|
|
||||||
conn = get(conn, "/api/pleroma/admin/users")
|
conn = get(conn, "/api/pleroma/admin/users")
|
||||||
|
|
||||||
assert json_response(conn, 200) == %{
|
assert json_response_and_validate_schema(conn, 200) == %{
|
||||||
"count" => 1,
|
"count" => 1,
|
||||||
"page_size" => 50,
|
"page_size" => 50,
|
||||||
"users" => [
|
"users" => [
|
||||||
|
@ -820,13 +828,14 @@ test "PATCH /api/pleroma/admin/users/activate", %{admin: admin, conn: conn} do
|
||||||
user_two = insert(:user, is_active: false)
|
user_two = insert(:user, is_active: false)
|
||||||
|
|
||||||
conn =
|
conn =
|
||||||
patch(
|
conn
|
||||||
conn,
|
|> put_req_header("content-type", "application/json")
|
||||||
|
|> patch(
|
||||||
"/api/pleroma/admin/users/activate",
|
"/api/pleroma/admin/users/activate",
|
||||||
%{nicknames: [user_one.nickname, user_two.nickname]}
|
%{nicknames: [user_one.nickname, user_two.nickname]}
|
||||||
)
|
)
|
||||||
|
|
||||||
response = json_response(conn, 200)
|
response = json_response_and_validate_schema(conn, 200)
|
||||||
assert Enum.map(response["users"], & &1["is_active"]) == [true, true]
|
assert Enum.map(response["users"], & &1["is_active"]) == [true, true]
|
||||||
|
|
||||||
log_entry = Repo.one(ModerationLog)
|
log_entry = Repo.one(ModerationLog)
|
||||||
|
@ -840,13 +849,14 @@ test "PATCH /api/pleroma/admin/users/deactivate", %{admin: admin, conn: conn} do
|
||||||
user_two = insert(:user, is_active: true)
|
user_two = insert(:user, is_active: true)
|
||||||
|
|
||||||
conn =
|
conn =
|
||||||
patch(
|
conn
|
||||||
conn,
|
|> put_req_header("content-type", "application/json")
|
||||||
|
|> patch(
|
||||||
"/api/pleroma/admin/users/deactivate",
|
"/api/pleroma/admin/users/deactivate",
|
||||||
%{nicknames: [user_one.nickname, user_two.nickname]}
|
%{nicknames: [user_one.nickname, user_two.nickname]}
|
||||||
)
|
)
|
||||||
|
|
||||||
response = json_response(conn, 200)
|
response = json_response_and_validate_schema(conn, 200)
|
||||||
assert Enum.map(response["users"], & &1["is_active"]) == [false, false]
|
assert Enum.map(response["users"], & &1["is_active"]) == [false, false]
|
||||||
|
|
||||||
log_entry = Repo.one(ModerationLog)
|
log_entry = Repo.one(ModerationLog)
|
||||||
|
@ -860,13 +870,14 @@ test "PATCH /api/pleroma/admin/users/approve", %{admin: admin, conn: conn} do
|
||||||
user_two = insert(:user, is_approved: false)
|
user_two = insert(:user, is_approved: false)
|
||||||
|
|
||||||
conn =
|
conn =
|
||||||
patch(
|
conn
|
||||||
conn,
|
|> put_req_header("content-type", "application/json")
|
||||||
|
|> patch(
|
||||||
"/api/pleroma/admin/users/approve",
|
"/api/pleroma/admin/users/approve",
|
||||||
%{nicknames: [user_one.nickname, user_two.nickname]}
|
%{nicknames: [user_one.nickname, user_two.nickname]}
|
||||||
)
|
)
|
||||||
|
|
||||||
response = json_response(conn, 200)
|
response = json_response_and_validate_schema(conn, 200)
|
||||||
assert Enum.map(response["users"], & &1["is_approved"]) == [true, true]
|
assert Enum.map(response["users"], & &1["is_approved"]) == [true, true]
|
||||||
|
|
||||||
log_entry = Repo.one(ModerationLog)
|
log_entry = Repo.one(ModerationLog)
|
||||||
|
@ -878,9 +889,12 @@ test "PATCH /api/pleroma/admin/users/approve", %{admin: admin, conn: conn} do
|
||||||
test "PATCH /api/pleroma/admin/users/:nickname/toggle_activation", %{admin: admin, conn: conn} do
|
test "PATCH /api/pleroma/admin/users/:nickname/toggle_activation", %{admin: admin, conn: conn} do
|
||||||
user = insert(:user)
|
user = insert(:user)
|
||||||
|
|
||||||
conn = patch(conn, "/api/pleroma/admin/users/#{user.nickname}/toggle_activation")
|
conn =
|
||||||
|
conn
|
||||||
|
|> put_req_header("content-type", "application/json")
|
||||||
|
|> patch("/api/pleroma/admin/users/#{user.nickname}/toggle_activation")
|
||||||
|
|
||||||
assert json_response(conn, 200) ==
|
assert json_response_and_validate_schema(conn, 200) ==
|
||||||
user_response(
|
user_response(
|
||||||
user,
|
user,
|
||||||
%{"is_active" => !user.is_active}
|
%{"is_active" => !user.is_active}
|
||||||
|
|
Loading…
Reference in New Issue