aboutsummaryrefslogtreecommitdiff
path: root/lib/pleroma/web/admin_api
diff options
context:
space:
mode:
Diffstat (limited to 'lib/pleroma/web/admin_api')
-rw-r--r--lib/pleroma/web/admin_api/controllers/admin_api_controller.ex329
-rw-r--r--lib/pleroma/web/admin_api/controllers/chat_controller.ex85
-rw-r--r--lib/pleroma/web/admin_api/controllers/config_controller.ex10
-rw-r--r--lib/pleroma/web/admin_api/controllers/fallback_controller.ex2
-rw-r--r--lib/pleroma/web/admin_api/controllers/frontend_controller.ex46
-rw-r--r--lib/pleroma/web/admin_api/controllers/instance_controller.ex63
-rw-r--r--lib/pleroma/web/admin_api/controllers/instance_document_controller.ex41
-rw-r--r--lib/pleroma/web/admin_api/controllers/invite_controller.ex8
-rw-r--r--lib/pleroma/web/admin_api/controllers/media_proxy_cache_controller.ex12
-rw-r--r--lib/pleroma/web/admin_api/controllers/o_auth_app_controller.ex (renamed from lib/pleroma/web/admin_api/controllers/oauth_app_controller.ex)7
-rw-r--r--lib/pleroma/web/admin_api/controllers/relay_controller.ex24
-rw-r--r--lib/pleroma/web/admin_api/controllers/report_controller.ex27
-rw-r--r--lib/pleroma/web/admin_api/controllers/status_controller.ex8
-rw-r--r--lib/pleroma/web/admin_api/controllers/user_controller.ex309
-rw-r--r--lib/pleroma/web/admin_api/report.ex6
-rw-r--r--lib/pleroma/web/admin_api/search.ex10
-rw-r--r--lib/pleroma/web/admin_api/views/account_view.ex37
-rw-r--r--lib/pleroma/web/admin_api/views/chat_view.ex30
-rw-r--r--lib/pleroma/web/admin_api/views/config_view.ex2
-rw-r--r--lib/pleroma/web/admin_api/views/frontend_view.ex21
-rw-r--r--lib/pleroma/web/admin_api/views/invite_view.ex2
-rw-r--r--lib/pleroma/web/admin_api/views/media_proxy_cache_view.ex2
-rw-r--r--lib/pleroma/web/admin_api/views/moderation_log_view.ex3
-rw-r--r--lib/pleroma/web/admin_api/views/o_auth_app_view.ex10
-rw-r--r--lib/pleroma/web/admin_api/views/report_view.ex7
-rw-r--r--lib/pleroma/web/admin_api/views/status_view.ex9
-rw-r--r--lib/pleroma/web/admin_api/views/user_view.ex10
27 files changed, 756 insertions, 364 deletions
diff --git a/lib/pleroma/web/admin_api/controllers/admin_api_controller.ex b/lib/pleroma/web/admin_api/controllers/admin_api_controller.ex
index aa2af1ab5..50aa294f0 100644
--- a/lib/pleroma/web/admin_api/controllers/admin_api_controller.ex
+++ b/lib/pleroma/web/admin_api/controllers/admin_api_controller.ex
@@ -1,50 +1,40 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.AdminAPI.AdminAPIController do
use Pleroma.Web, :controller
- import Pleroma.Web.ControllerHelper, only: [json_response: 3]
+ import Pleroma.Web.ControllerHelper,
+ only: [json_response: 3, fetch_integer_param: 3]
alias Pleroma.Config
alias Pleroma.MFA
alias Pleroma.ModerationLog
- alias Pleroma.Plugs.OAuthScopesPlug
alias Pleroma.Stats
alias Pleroma.User
alias Pleroma.Web.ActivityPub.ActivityPub
- alias Pleroma.Web.ActivityPub.Builder
- alias Pleroma.Web.ActivityPub.Pipeline
alias Pleroma.Web.AdminAPI
alias Pleroma.Web.AdminAPI.AccountView
alias Pleroma.Web.AdminAPI.ModerationLogView
- alias Pleroma.Web.AdminAPI.Search
alias Pleroma.Web.Endpoint
+ alias Pleroma.Web.Plugs.OAuthScopesPlug
alias Pleroma.Web.Router
- require Logger
-
@users_page_size 50
plug(
OAuthScopesPlug,
- %{scopes: ["read:accounts"], admin: true}
- when action in [:list_users, :user_show, :right_get, :show_user_credentials]
+ %{scopes: ["admin:read:accounts"]}
+ when action in [:right_get, :show_user_credentials, :create_backup]
)
plug(
OAuthScopesPlug,
- %{scopes: ["write:accounts"], admin: true}
+ %{scopes: ["admin:write:accounts"]}
when action in [
:get_password_reset,
:force_password_reset,
- :user_delete,
- :users_create,
- :user_toggle_activation,
- :user_activate,
- :user_deactivate,
- :user_approve,
:tag_users,
:untag_users,
:right_add,
@@ -58,19 +48,19 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
plug(
OAuthScopesPlug,
- %{scopes: ["write:follows"], admin: true}
- when action in [:user_follow, :user_unfollow]
+ %{scopes: ["admin:read:statuses"]}
+ when action in [:list_user_statuses]
)
plug(
OAuthScopesPlug,
- %{scopes: ["read:statuses"], admin: true}
- when action in [:list_user_statuses, :list_instance_statuses]
+ %{scopes: ["admin:read:chats"]}
+ when action in [:list_user_chats]
)
plug(
OAuthScopesPlug,
- %{scopes: ["read"], admin: true}
+ %{scopes: ["admin:read"]}
when action in [
:list_log,
:stats,
@@ -80,7 +70,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
plug(
OAuthScopesPlug,
- %{scopes: ["write"], admin: true}
+ %{scopes: ["admin:write"]}
when action in [
:restart,
:resend_confirmation_email,
@@ -91,232 +81,43 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
action_fallback(AdminAPI.FallbackController)
- def user_delete(conn, %{"nickname" => nickname}) do
- user_delete(conn, %{"nicknames" => [nickname]})
- end
-
- def user_delete(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do
- users =
- nicknames
- |> Enum.map(&User.get_cached_by_nickname/1)
-
- users
- |> Enum.each(fn user ->
- {:ok, delete_data, _} = Builder.delete(admin, user.ap_id)
- Pipeline.common_pipeline(delete_data, local: true)
- end)
-
- ModerationLog.insert_log(%{
- actor: admin,
- subject: users,
- action: "delete"
- })
-
- json(conn, nicknames)
- end
-
- def user_follow(%{assigns: %{user: admin}} = conn, %{
- "follower" => follower_nick,
- "followed" => followed_nick
- }) do
- with %User{} = follower <- User.get_cached_by_nickname(follower_nick),
- %User{} = followed <- User.get_cached_by_nickname(followed_nick) do
- User.follow(follower, followed)
-
- ModerationLog.insert_log(%{
- actor: admin,
- followed: followed,
- follower: follower,
- action: "follow"
- })
- end
-
- json(conn, "ok")
- end
-
- def user_unfollow(%{assigns: %{user: admin}} = conn, %{
- "follower" => follower_nick,
- "followed" => followed_nick
- }) do
- with %User{} = follower <- User.get_cached_by_nickname(follower_nick),
- %User{} = followed <- User.get_cached_by_nickname(followed_nick) do
- User.unfollow(follower, followed)
-
- ModerationLog.insert_log(%{
- actor: admin,
- followed: followed,
- follower: follower,
- action: "unfollow"
- })
- end
-
- json(conn, "ok")
- end
-
- def users_create(%{assigns: %{user: admin}} = conn, %{"users" => users}) do
- changesets =
- Enum.map(users, fn %{"nickname" => nickname, "email" => email, "password" => password} ->
- user_data = %{
- nickname: nickname,
- name: nickname,
- email: email,
- password: password,
- password_confirmation: password,
- bio: "."
- }
-
- User.register_changeset(%User{}, user_data, need_confirmation: false)
- end)
- |> Enum.reduce(Ecto.Multi.new(), fn changeset, multi ->
- Ecto.Multi.insert(multi, Ecto.UUID.generate(), changeset)
- end)
-
- case Pleroma.Repo.transaction(changesets) do
- {:ok, users} ->
- res =
- users
- |> Map.values()
- |> Enum.map(fn user ->
- {:ok, user} = User.post_register_action(user)
-
- user
- end)
- |> Enum.map(&AccountView.render("created.json", %{user: &1}))
-
- ModerationLog.insert_log(%{
- actor: admin,
- subjects: Map.values(users),
- action: "create"
- })
-
- json(conn, res)
-
- {:error, id, changeset, _} ->
- res =
- Enum.map(changesets.operations, fn
- {current_id, {:changeset, _current_changeset, _}} when current_id == id ->
- AccountView.render("create-error.json", %{changeset: changeset})
-
- {_, {:changeset, current_changeset, _}} ->
- AccountView.render("create-error.json", %{changeset: current_changeset})
- end)
-
- conn
- |> put_status(:conflict)
- |> json(res)
- end
- end
-
- def user_show(%{assigns: %{user: admin}} = conn, %{"nickname" => nickname}) do
- with %User{} = user <- User.get_cached_by_nickname_or_id(nickname, for: admin) do
- conn
- |> put_view(AccountView)
- |> render("show.json", %{user: user})
- else
- _ -> {:error, :not_found}
- end
- end
-
- def list_instance_statuses(conn, %{"instance" => instance} = params) do
- with_reblogs = params["with_reblogs"] == "true" || params["with_reblogs"] == true
- {page, page_size} = page_params(params)
-
- activities =
- ActivityPub.fetch_statuses(nil, %{
- instance: instance,
- limit: page_size,
- offset: (page - 1) * page_size,
- exclude_reblogs: not with_reblogs
- })
-
- conn
- |> put_view(AdminAPI.StatusView)
- |> render("index.json", %{activities: activities, as: :activity})
- end
-
def list_user_statuses(%{assigns: %{user: admin}} = conn, %{"nickname" => nickname} = params) do
with_reblogs = params["with_reblogs"] == "true" || params["with_reblogs"] == true
godmode = params["godmode"] == "true" || params["godmode"] == true
with %User{} = user <- User.get_cached_by_nickname_or_id(nickname, for: admin) do
- {_, page_size} = page_params(params)
+ {page, page_size} = page_params(params)
- activities =
+ result =
ActivityPub.fetch_user_activities(user, nil, %{
limit: page_size,
+ offset: (page - 1) * page_size,
godmode: godmode,
- exclude_reblogs: not with_reblogs
+ exclude_reblogs: not with_reblogs,
+ pagination_type: :offset,
+ total: true
})
conn
|> put_view(AdminAPI.StatusView)
- |> render("index.json", %{activities: activities, as: :activity})
+ |> render("index.json", %{total: result[:total], activities: result[:items], as: :activity})
else
_ -> {:error, :not_found}
end
end
- def user_toggle_activation(%{assigns: %{user: admin}} = conn, %{"nickname" => nickname}) do
- user = User.get_cached_by_nickname(nickname)
+ def list_user_chats(%{assigns: %{user: admin}} = conn, %{"nickname" => nickname} = _params) do
+ with %User{id: user_id} <- User.get_cached_by_nickname_or_id(nickname, for: admin) do
+ chats =
+ Pleroma.Chat.for_user_query(user_id)
+ |> Pleroma.Repo.all()
- {:ok, updated_user} = User.deactivate(user, !user.deactivated)
-
- action = if user.deactivated, do: "activate", else: "deactivate"
-
- ModerationLog.insert_log(%{
- actor: admin,
- subject: [user],
- action: action
- })
-
- conn
- |> put_view(AccountView)
- |> render("show.json", %{user: updated_user})
- end
-
- def user_activate(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do
- users = Enum.map(nicknames, &User.get_cached_by_nickname/1)
- {:ok, updated_users} = User.deactivate(users, false)
-
- ModerationLog.insert_log(%{
- actor: admin,
- subject: users,
- action: "activate"
- })
-
- conn
- |> put_view(AccountView)
- |> render("index.json", %{users: Keyword.values(updated_users)})
- end
-
- def user_deactivate(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do
- users = Enum.map(nicknames, &User.get_cached_by_nickname/1)
- {:ok, updated_users} = User.deactivate(users, true)
-
- ModerationLog.insert_log(%{
- actor: admin,
- subject: users,
- action: "deactivate"
- })
-
- conn
- |> put_view(AccountView)
- |> render("index.json", %{users: Keyword.values(updated_users)})
- end
-
- def user_approve(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do
- users = Enum.map(nicknames, &User.get_cached_by_nickname/1)
- {:ok, updated_users} = User.approve(users)
-
- ModerationLog.insert_log(%{
- actor: admin,
- subject: users,
- action: "approve"
- })
-
- conn
- |> put_view(AccountView)
- |> render("index.json", %{users: updated_users})
+ conn
+ |> put_view(AdminAPI.ChatView)
+ |> render("index.json", chats: chats)
+ else
+ _ -> {:error, :not_found}
+ end
end
def tag_users(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames, "tags" => tags}) do
@@ -345,44 +146,6 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
end
end
- def list_users(conn, params) do
- {page, page_size} = page_params(params)
- filters = maybe_parse_filters(params["filters"])
-
- search_params = %{
- query: params["query"],
- page: page,
- page_size: page_size,
- tags: params["tags"],
- name: params["name"],
- email: params["email"]
- }
-
- with {:ok, users, count} <- Search.user(Map.merge(search_params, filters)) do
- json(
- conn,
- AccountView.render("index.json",
- users: users,
- count: count,
- page_size: page_size
- )
- )
- end
- end
-
- @filters ~w(local external active deactivated need_approval is_admin is_moderator)
-
- @spec maybe_parse_filters(String.t()) :: %{required(String.t()) => true} | %{}
- defp maybe_parse_filters(filters) when is_nil(filters) or filters == "", do: %{}
-
- defp maybe_parse_filters(filters) do
- filters
- |> String.split(",")
- |> Enum.filter(&Enum.member?(@filters, &1))
- |> Enum.map(&String.to_atom/1)
- |> Map.new(&{&1, true})
- end
-
def right_add_multiple(%{assigns: %{user: admin}} = conn, %{
"permission_group" => permission_group,
"nicknames" => nicknames
@@ -625,7 +388,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
if Config.get(:configurable_from_database) do
:ok
else
- {:error, "To use this endpoint you need to enable configuration from database."}
+ {:error, "You must enable configurable_from_database in your config file."}
end
end
@@ -638,7 +401,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
def confirm_email(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do
users = Enum.map(nicknames, &User.get_cached_by_nickname/1)
- User.toggle_confirmation(users)
+ User.confirm(users)
ModerationLog.insert_log(%{actor: admin, subject: users, action: "confirm_email"})
@@ -664,25 +427,19 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
json(conn, %{"status_visibility" => counters})
end
- defp page_params(params) do
- {get_page(params["page"]), get_page_size(params["page_size"])}
- end
+ def create_backup(%{assigns: %{user: admin}} = conn, %{"nickname" => nickname}) do
+ with %User{} = user <- User.get_by_nickname(nickname),
+ {:ok, _} <- Pleroma.User.Backup.create(user, admin.id) do
+ ModerationLog.insert_log(%{actor: admin, subject: user, action: "create_backup"})
- defp get_page(page_string) when is_nil(page_string), do: 1
-
- defp get_page(page_string) do
- case Integer.parse(page_string) do
- {page, _} -> page
- :error -> 1
+ json(conn, "")
end
end
- defp get_page_size(page_size_string) when is_nil(page_size_string), do: @users_page_size
-
- defp get_page_size(page_size_string) do
- case Integer.parse(page_size_string) do
- {page_size, _} -> page_size
- :error -> @users_page_size
- end
+ defp page_params(params) do
+ {
+ fetch_integer_param(params, "page", 1),
+ fetch_integer_param(params, "page_size", @users_page_size)
+ }
end
end
diff --git a/lib/pleroma/web/admin_api/controllers/chat_controller.ex b/lib/pleroma/web/admin_api/controllers/chat_controller.ex
new file mode 100644
index 000000000..ff20c8604
--- /dev/null
+++ b/lib/pleroma/web/admin_api/controllers/chat_controller.ex
@@ -0,0 +1,85 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.AdminAPI.ChatController do
+ use Pleroma.Web, :controller
+
+ alias Pleroma.Activity
+ alias Pleroma.Chat
+ alias Pleroma.Chat.MessageReference
+ alias Pleroma.ModerationLog
+ alias Pleroma.Pagination
+ alias Pleroma.Web.AdminAPI
+ alias Pleroma.Web.CommonAPI
+ alias Pleroma.Web.PleromaAPI.Chat.MessageReferenceView
+ alias Pleroma.Web.Plugs.OAuthScopesPlug
+
+ require Logger
+
+ plug(Pleroma.Web.ApiSpec.CastAndValidate)
+
+ plug(
+ OAuthScopesPlug,
+ %{scopes: ["admin:read:chats"]} when action in [:show, :messages]
+ )
+
+ plug(
+ OAuthScopesPlug,
+ %{scopes: ["admin:write:chats"]} when action in [:delete_message]
+ )
+
+ action_fallback(Pleroma.Web.AdminAPI.FallbackController)
+
+ defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.Admin.ChatOperation
+
+ def delete_message(%{assigns: %{user: user}} = conn, %{
+ message_id: message_id,
+ id: chat_id
+ }) do
+ with %MessageReference{object: %{data: %{"id" => object_ap_id}}} = cm_ref <-
+ MessageReference.get_by_id(message_id),
+ ^chat_id <- to_string(cm_ref.chat_id),
+ %Activity{id: activity_id} <- Activity.get_create_by_object_ap_id(object_ap_id),
+ {:ok, _} <- CommonAPI.delete(activity_id, user) do
+ ModerationLog.insert_log(%{
+ action: "chat_message_delete",
+ actor: user,
+ subject_id: message_id
+ })
+
+ conn
+ |> put_view(MessageReferenceView)
+ |> render("show.json", chat_message_reference: cm_ref)
+ else
+ _e ->
+ {:error, :could_not_delete}
+ end
+ end
+
+ def messages(conn, %{id: id} = params) do
+ with %Chat{} = chat <- Chat.get_by_id(id) do
+ cm_refs =
+ chat
+ |> MessageReference.for_chat_query()
+ |> Pagination.fetch_paginated(params)
+
+ conn
+ |> put_view(MessageReferenceView)
+ |> render("index.json", chat_message_references: cm_refs)
+ else
+ _ ->
+ conn
+ |> put_status(:not_found)
+ |> json(%{error: "not found"})
+ end
+ end
+
+ def show(conn, %{id: id}) do
+ with %Chat{} = chat <- Chat.get_by_id(id) do
+ conn
+ |> put_view(AdminAPI.ChatView)
+ |> render("show.json", chat: chat)
+ end
+ end
+end
diff --git a/lib/pleroma/web/admin_api/controllers/config_controller.ex b/lib/pleroma/web/admin_api/controllers/config_controller.ex
index 0df13007f..a718d7b8d 100644
--- a/lib/pleroma/web/admin_api/controllers/config_controller.ex
+++ b/lib/pleroma/web/admin_api/controllers/config_controller.ex
@@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.AdminAPI.ConfigController do
@@ -7,14 +7,14 @@ defmodule Pleroma.Web.AdminAPI.ConfigController do
alias Pleroma.Config
alias Pleroma.ConfigDB
- alias Pleroma.Plugs.OAuthScopesPlug
+ alias Pleroma.Web.Plugs.OAuthScopesPlug
plug(Pleroma.Web.ApiSpec.CastAndValidate)
- plug(OAuthScopesPlug, %{scopes: ["write"], admin: true} when action == :update)
+ plug(OAuthScopesPlug, %{scopes: ["admin:write"]} when action == :update)
plug(
OAuthScopesPlug,
- %{scopes: ["read"], admin: true}
+ %{scopes: ["admin:read"]}
when action in [:show, :descriptions]
)
@@ -122,7 +122,7 @@ defmodule Pleroma.Web.AdminAPI.ConfigController do
if Config.get(:configurable_from_database) do
:ok
else
- {:error, "To use this endpoint you need to enable configuration from database."}
+ {:error, "You must enable configurable_from_database in your config file."}
end
end
diff --git a/lib/pleroma/web/admin_api/controllers/fallback_controller.ex b/lib/pleroma/web/admin_api/controllers/fallback_controller.ex
index 34d90db07..45d8815b5 100644
--- a/lib/pleroma/web/admin_api/controllers/fallback_controller.ex
+++ b/lib/pleroma/web/admin_api/controllers/fallback_controller.ex
@@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.AdminAPI.FallbackController do
diff --git a/lib/pleroma/web/admin_api/controllers/frontend_controller.ex b/lib/pleroma/web/admin_api/controllers/frontend_controller.ex
new file mode 100644
index 000000000..442e6a5a0
--- /dev/null
+++ b/lib/pleroma/web/admin_api/controllers/frontend_controller.ex
@@ -0,0 +1,46 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.AdminAPI.FrontendController do
+ use Pleroma.Web, :controller
+
+ alias Pleroma.Config
+ alias Pleroma.Web.Plugs.OAuthScopesPlug
+
+ plug(Pleroma.Web.ApiSpec.CastAndValidate)
+ plug(OAuthScopesPlug, %{scopes: ["admin:write"]} when action == :install)
+ plug(OAuthScopesPlug, %{scopes: ["admin:read"]} when action == :index)
+ action_fallback(Pleroma.Web.AdminAPI.FallbackController)
+
+ defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.Admin.FrontendOperation
+
+ def index(conn, _params) do
+ installed = installed()
+
+ frontends =
+ [:frontends, :available]
+ |> Config.get([])
+ |> Enum.map(fn {name, desc} ->
+ Map.put(desc, "installed", name in installed)
+ end)
+
+ render(conn, "index.json", frontends: frontends)
+ end
+
+ def install(%{body_params: params} = conn, _params) do
+ with :ok <- Pleroma.Frontend.install(params.name, Map.delete(params, :name)) do
+ index(conn, %{})
+ end
+ end
+
+ defp installed do
+ frontend_directory = Pleroma.Frontend.dir()
+
+ if File.exists?(frontend_directory) do
+ File.ls!(frontend_directory)
+ else
+ []
+ end
+ end
+end
diff --git a/lib/pleroma/web/admin_api/controllers/instance_controller.ex b/lib/pleroma/web/admin_api/controllers/instance_controller.ex
new file mode 100644
index 000000000..00857983f
--- /dev/null
+++ b/lib/pleroma/web/admin_api/controllers/instance_controller.ex
@@ -0,0 +1,63 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.AdminAPI.InstanceController do
+ use Pleroma.Web, :controller
+
+ import Pleroma.Web.ControllerHelper, only: [fetch_integer_param: 3]
+
+ alias Pleroma.Instances.Instance
+ alias Pleroma.Web.ActivityPub.ActivityPub
+ alias Pleroma.Web.AdminAPI
+ alias Pleroma.Web.Plugs.OAuthScopesPlug
+
+ require Logger
+
+ @default_page_size 50
+
+ plug(
+ OAuthScopesPlug,
+ %{scopes: ["admin:read:statuses"]}
+ when action in [:list_statuses]
+ )
+
+ plug(
+ OAuthScopesPlug,
+ %{scopes: ["admin:write:accounts", "admin:write:statuses"]}
+ when action in [:delete]
+ )
+
+ action_fallback(AdminAPI.FallbackController)
+
+ def list_statuses(conn, %{"instance" => instance} = params) do
+ with_reblogs = params["with_reblogs"] == "true" || params["with_reblogs"] == true
+ {page, page_size} = page_params(params)
+
+ result =
+ ActivityPub.fetch_statuses(nil, %{
+ instance: instance,
+ limit: page_size,
+ offset: (page - 1) * page_size,
+ exclude_reblogs: not with_reblogs,
+ total: true
+ })
+
+ conn
+ |> put_view(AdminAPI.StatusView)
+ |> render("index.json", %{total: result[:total], activities: result[:items], as: :activity})
+ end
+
+ def delete(conn, %{"instance" => instance}) do
+ with {:ok, _job} <- Instance.delete_users_and_activities(instance) do
+ json(conn, instance)
+ end
+ end
+
+ defp page_params(params) do
+ {
+ fetch_integer_param(params, "page", 1),
+ fetch_integer_param(params, "page_size", @default_page_size)
+ }
+ end
+end
diff --git a/lib/pleroma/web/admin_api/controllers/instance_document_controller.ex b/lib/pleroma/web/admin_api/controllers/instance_document_controller.ex
new file mode 100644
index 000000000..a55857a0e
--- /dev/null
+++ b/lib/pleroma/web/admin_api/controllers/instance_document_controller.ex
@@ -0,0 +1,41 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.AdminAPI.InstanceDocumentController do
+ use Pleroma.Web, :controller
+
+ alias Pleroma.Web.InstanceDocument
+ alias Pleroma.Web.Plugs.InstanceStatic
+ alias Pleroma.Web.Plugs.OAuthScopesPlug
+
+ plug(Pleroma.Web.ApiSpec.CastAndValidate)
+
+ action_fallback(Pleroma.Web.AdminAPI.FallbackController)
+
+ defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.Admin.InstanceDocumentOperation
+
+ plug(OAuthScopesPlug, %{scopes: ["admin:read"]} when action == :show)
+ plug(OAuthScopesPlug, %{scopes: ["admin:write"]} when action in [:update, :delete])
+
+ def show(conn, %{name: document_name}) do
+ with {:ok, url} <- InstanceDocument.get(document_name),
+ {:ok, content} <- File.read(InstanceStatic.file_path(url)) do
+ conn
+ |> put_resp_content_type("text/html")
+ |> send_resp(200, content)
+ end
+ end
+
+ def update(%{body_params: %{file: file}} = conn, %{name: document_name}) do
+ with {:ok, url} <- InstanceDocument.put(document_name, file.path) do
+ json(conn, %{"url" => url})
+ end
+ end
+
+ def delete(conn, %{name: document_name}) do
+ with :ok <- InstanceDocument.delete(document_name) do
+ json(conn, %{})
+ end
+ end
+end
diff --git a/lib/pleroma/web/admin_api/controllers/invite_controller.ex b/lib/pleroma/web/admin_api/controllers/invite_controller.ex
index 7d169b8d2..727ebd846 100644
--- a/lib/pleroma/web/admin_api/controllers/invite_controller.ex
+++ b/lib/pleroma/web/admin_api/controllers/invite_controller.ex
@@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.AdminAPI.InviteController do
@@ -8,17 +8,17 @@ defmodule Pleroma.Web.AdminAPI.InviteController do
import Pleroma.Web.ControllerHelper, only: [json_response: 3]
alias Pleroma.Config
- alias Pleroma.Plugs.OAuthScopesPlug
alias Pleroma.UserInviteToken
+ alias Pleroma.Web.Plugs.OAuthScopesPlug
require Logger
plug(Pleroma.Web.ApiSpec.CastAndValidate)
- plug(OAuthScopesPlug, %{scopes: ["read:invites"], admin: true} when action == :index)
+ plug(OAuthScopesPlug, %{scopes: ["admin:read:invites"]} when action == :index)
plug(
OAuthScopesPlug,
- %{scopes: ["write:invites"], admin: true} when action in [:create, :revoke, :email]
+ %{scopes: ["admin:write:invites"]} when action in [:create, :revoke, :email]
)
action_fallback(Pleroma.Web.AdminAPI.FallbackController)
diff --git a/lib/pleroma/web/admin_api/controllers/media_proxy_cache_controller.ex b/lib/pleroma/web/admin_api/controllers/media_proxy_cache_controller.ex
index 131e22d78..a6d7aaf54 100644
--- a/lib/pleroma/web/admin_api/controllers/media_proxy_cache_controller.ex
+++ b/lib/pleroma/web/admin_api/controllers/media_proxy_cache_controller.ex
@@ -1,24 +1,26 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.AdminAPI.MediaProxyCacheController do
use Pleroma.Web, :controller
- alias Pleroma.Plugs.OAuthScopesPlug
alias Pleroma.Web.ApiSpec.Admin, as: Spec
alias Pleroma.Web.MediaProxy
+ alias Pleroma.Web.Plugs.OAuthScopesPlug
+
+ @cachex Pleroma.Config.get([:cachex, :provider], Cachex)
plug(Pleroma.Web.ApiSpec.CastAndValidate)
plug(
OAuthScopesPlug,
- %{scopes: ["read:media_proxy_caches"], admin: true} when action in [:index]
+ %{scopes: ["admin:read:media_proxy_caches"]} when action in [:index]
)
plug(
OAuthScopesPlug,
- %{scopes: ["write:media_proxy_caches"], admin: true} when action in [:purge, :delete]
+ %{scopes: ["admin:write:media_proxy_caches"]} when action in [:purge, :delete]
)
action_fallback(Pleroma.Web.AdminAPI.FallbackController)
@@ -38,7 +40,7 @@ defmodule Pleroma.Web.AdminAPI.MediaProxyCacheController do
defp fetch_entries(params) do
MediaProxy.cache_table()
- |> Cachex.stream!(Cachex.Query.create(true, :key))
+ |> @cachex.stream!(Cachex.Query.create(true, :key))
|> filter_entries(params[:query])
end
diff --git a/lib/pleroma/web/admin_api/controllers/oauth_app_controller.ex b/lib/pleroma/web/admin_api/controllers/o_auth_app_controller.ex
index dca23ea73..51b17d392 100644
--- a/lib/pleroma/web/admin_api/controllers/oauth_app_controller.ex
+++ b/lib/pleroma/web/admin_api/controllers/o_auth_app_controller.ex
@@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.AdminAPI.OAuthAppController do
@@ -7,17 +7,16 @@ defmodule Pleroma.Web.AdminAPI.OAuthAppController do
import Pleroma.Web.ControllerHelper, only: [json_response: 3]
- alias Pleroma.Plugs.OAuthScopesPlug
alias Pleroma.Web.OAuth.App
+ alias Pleroma.Web.Plugs.OAuthScopesPlug
require Logger
plug(Pleroma.Web.ApiSpec.CastAndValidate)
- plug(:put_view, Pleroma.Web.MastodonAPI.AppView)
plug(
OAuthScopesPlug,
- %{scopes: ["write"], admin: true}
+ %{scopes: ["admin:write"]}
when action in [:create, :index, :update, :delete]
)
diff --git a/lib/pleroma/web/admin_api/controllers/relay_controller.ex b/lib/pleroma/web/admin_api/controllers/relay_controller.ex
index 95d06dde7..c6bd43fea 100644
--- a/lib/pleroma/web/admin_api/controllers/relay_controller.ex
+++ b/lib/pleroma/web/admin_api/controllers/relay_controller.ex
@@ -1,13 +1,13 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.AdminAPI.RelayController do
use Pleroma.Web, :controller
alias Pleroma.ModerationLog
- alias Pleroma.Plugs.OAuthScopesPlug
alias Pleroma.Web.ActivityPub.Relay
+ alias Pleroma.Web.Plugs.OAuthScopesPlug
require Logger
@@ -15,11 +15,11 @@ defmodule Pleroma.Web.AdminAPI.RelayController do
plug(
OAuthScopesPlug,
- %{scopes: ["write:follows"], admin: true}
+ %{scopes: ["admin:write:follows"]}
when action in [:follow, :unfollow]
)
- plug(OAuthScopesPlug, %{scopes: ["read"], admin: true} when action == :index)
+ plug(OAuthScopesPlug, %{scopes: ["admin:read"]} when action == :index)
action_fallback(Pleroma.Web.AdminAPI.FallbackController)
@@ -33,11 +33,7 @@ defmodule Pleroma.Web.AdminAPI.RelayController do
def follow(%{assigns: %{user: admin}, body_params: %{relay_url: target}} = conn, _) do
with {:ok, _message} <- Relay.follow(target) do
- ModerationLog.insert_log(%{
- action: "relay_follow",
- actor: admin,
- target: target
- })
+ ModerationLog.insert_log(%{action: "relay_follow", actor: admin, target: target})
json(conn, %{actor: target, followed_back: target in Relay.following()})
else
@@ -48,13 +44,9 @@ defmodule Pleroma.Web.AdminAPI.RelayController do
end
end
- def unfollow(%{assigns: %{user: admin}, body_params: %{relay_url: target}} = conn, _) do
- with {:ok, _message} <- Relay.unfollow(target) do
- ModerationLog.insert_log(%{
- action: "relay_unfollow",
- actor: admin,
- target: target
- })
+ def unfollow(%{assigns: %{user: admin}, body_params: %{relay_url: target} = params} = conn, _) do
+ with {:ok, _message} <- Relay.unfollow(target, %{force: params[:force]}) do
+ ModerationLog.insert_log(%{action: "relay_unfollow", actor: admin, target: target})
json(conn, target)
else
diff --git a/lib/pleroma/web/admin_api/controllers/report_controller.ex b/lib/pleroma/web/admin_api/controllers/report_controller.ex
index 4c011e174..d4a4935ee 100644
--- a/lib/pleroma/web/admin_api/controllers/report_controller.ex
+++ b/lib/pleroma/web/admin_api/controllers/report_controller.ex
@@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.AdminAPI.ReportController do
@@ -9,21 +9,21 @@ defmodule Pleroma.Web.AdminAPI.ReportController do
alias Pleroma.Activity
alias Pleroma.ModerationLog
- alias Pleroma.Plugs.OAuthScopesPlug
alias Pleroma.ReportNote
alias Pleroma.Web.ActivityPub.Utils
alias Pleroma.Web.AdminAPI
alias Pleroma.Web.AdminAPI.Report
alias Pleroma.Web.CommonAPI
+ alias Pleroma.Web.Plugs.OAuthScopesPlug
require Logger
plug(Pleroma.Web.ApiSpec.CastAndValidate)
- plug(OAuthScopesPlug, %{scopes: ["read:reports"], admin: true} when action in [:index, :show])
+ plug(OAuthScopesPlug, %{scopes: ["admin:read:reports"]} when action in [:index, :show])
plug(
OAuthScopesPlug,
- %{scopes: ["write:reports"], admin: true}
+ %{scopes: ["admin:write:reports"]}
when action in [:update, :notes_create, :notes_delete]
)
@@ -38,7 +38,7 @@ defmodule Pleroma.Web.AdminAPI.ReportController do
end
def show(conn, %{id: id}) do
- with %Activity{} = report <- Activity.get_by_id(id) do
+ with %Activity{} = report <- Activity.get_report(id) do
render(conn, "show.json", Report.extract_report_info(report))
else
_ -> {:error, :not_found}
@@ -50,10 +50,13 @@ defmodule Pleroma.Web.AdminAPI.ReportController do
Enum.map(reports, fn report ->
case CommonAPI.update_report_state(report.id, report.state) do
{:ok, activity} ->
+ report = Activity.get_by_id_with_user_actor(activity.id)
+
ModerationLog.insert_log(%{
action: "report_update",
actor: admin,
- subject: activity
+ subject: activity,
+ subject_actor: report.user_actor
})
activity
@@ -73,11 +76,13 @@ defmodule Pleroma.Web.AdminAPI.ReportController do
def notes_create(%{assigns: %{user: user}, body_params: %{content: content}} = conn, %{
id: report_id
}) do
- with {:ok, _} <- ReportNote.create(user.id, report_id, content) do
+ with {:ok, _} <- ReportNote.create(user.id, report_id, content),
+ report <- Activity.get_by_id_with_user_actor(report_id) do
ModerationLog.insert_log(%{
action: "report_note",
actor: user,
- subject: Activity.get_by_id(report_id),
+ subject: report,
+ subject_actor: report.user_actor,
text: content
})
@@ -91,11 +96,13 @@ defmodule Pleroma.Web.AdminAPI.ReportController do
id: note_id,
report_id: report_id
}) do
- with {:ok, note} <- ReportNote.destroy(note_id) do
+ with {:ok, note} <- ReportNote.destroy(note_id),
+ report <- Activity.get_by_id_with_user_actor(report_id) do
ModerationLog.insert_log(%{
action: "report_note_delete",
actor: user,
- subject: Activity.get_by_id(report_id),
+ subject: report,
+ subject_actor: report.user_actor,
text: note.content
})
diff --git a/lib/pleroma/web/admin_api/controllers/status_controller.ex b/lib/pleroma/web/admin_api/controllers/status_controller.ex
index bc48cc527..7058def82 100644
--- a/lib/pleroma/web/admin_api/controllers/status_controller.ex
+++ b/lib/pleroma/web/admin_api/controllers/status_controller.ex
@@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.AdminAPI.StatusController do
@@ -7,19 +7,19 @@ defmodule Pleroma.Web.AdminAPI.StatusController do
alias Pleroma.Activity
alias Pleroma.ModerationLog
- alias Pleroma.Plugs.OAuthScopesPlug
alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.CommonAPI
alias Pleroma.Web.MastodonAPI
+ alias Pleroma.Web.Plugs.OAuthScopesPlug
require Logger
plug(Pleroma.Web.ApiSpec.CastAndValidate)
- plug(OAuthScopesPlug, %{scopes: ["read:statuses"], admin: true} when action in [:index, :show])
+ plug(OAuthScopesPlug, %{scopes: ["admin:read:statuses"]} when action in [:index, :show])
plug(
OAuthScopesPlug,
- %{scopes: ["write:statuses"], admin: true} when action in [:update, :delete]
+ %{scopes: ["admin:write:statuses"]} when action in [:update, :delete]
)
action_fallback(Pleroma.Web.AdminAPI.FallbackController)
diff --git a/lib/pleroma/web/admin_api/controllers/user_controller.ex b/lib/pleroma/web/admin_api/controllers/user_controller.ex
new file mode 100644
index 000000000..50208a8b7
--- /dev/null
+++ b/lib/pleroma/web/admin_api/controllers/user_controller.ex
@@ -0,0 +1,309 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.AdminAPI.UserController do
+ use Pleroma.Web, :controller
+
+ import Pleroma.Web.ControllerHelper,
+ only: [fetch_integer_param: 3]
+
+ alias Pleroma.ModerationLog
+ alias Pleroma.User
+ alias Pleroma.Web.ActivityPub.Builder
+ alias Pleroma.Web.ActivityPub.Pipeline
+ alias Pleroma.Web.AdminAPI
+ alias Pleroma.Web.AdminAPI.Search
+ alias Pleroma.Web.Plugs.OAuthScopesPlug
+
+ @users_page_size 50
+
+ plug(Pleroma.Web.ApiSpec.CastAndValidate)
+
+ plug(
+ OAuthScopesPlug,
+ %{scopes: ["admin:read:accounts"]}
+ when action in [:index, :show]
+ )
+
+ plug(
+ OAuthScopesPlug,
+ %{scopes: ["admin:write:accounts"]}
+ when action in [
+ :delete,
+ :create,
+ :toggle_activation,
+ :activate,
+ :deactivate,
+ :approve,
+ :suggest,
+ :unsuggest
+ ]
+ )
+
+ plug(
+ OAuthScopesPlug,
+ %{scopes: ["admin:write:follows"]}
+ when action in [:follow, :unfollow]
+ )
+
+ action_fallback(AdminAPI.FallbackController)
+
+ defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.Admin.UserOperation
+
+ def delete(conn, %{nickname: nickname}) do
+ conn
+ |> Map.put(:body_params, %{nicknames: [nickname]})
+ |> delete(%{})
+ end
+
+ def delete(%{assigns: %{user: admin}, body_params: %{nicknames: nicknames}} = conn, _) do
+ users = Enum.map(nicknames, &User.get_cached_by_nickname/1)
+
+ Enum.each(users, fn user ->
+ {:ok, delete_data, _} = Builder.delete(admin, user.ap_id)
+ Pipeline.common_pipeline(delete_data, local: true)
+ end)
+
+ ModerationLog.insert_log(%{
+ actor: admin,
+ subject: users,
+ action: "delete"
+ })
+
+ json(conn, nicknames)
+ end
+
+ def follow(
+ %{
+ assigns: %{user: admin},
+ body_params: %{
+ follower: follower_nick,
+ followed: followed_nick
+ }
+ } = conn,
+ _
+ ) do
+ with %User{} = follower <- User.get_cached_by_nickname(follower_nick),
+ %User{} = followed <- User.get_cached_by_nickname(followed_nick) do
+ User.follow(follower, followed)
+
+ ModerationLog.insert_log(%{
+ actor: admin,
+ followed: followed,
+ follower: follower,
+ action: "follow"
+ })
+ end
+
+ json(conn, "ok")
+ end
+
+ def unfollow(
+ %{
+ assigns: %{user: admin},
+ body_params: %{
+ follower: follower_nick,
+ followed: followed_nick
+ }
+ } = conn,
+ _
+ ) do
+ with %User{} = follower <- User.get_cached_by_nickname(follower_nick),
+ %User{} = followed <- User.get_cached_by_nickname(followed_nick) do
+ User.unfollow(follower, followed)
+
+ ModerationLog.insert_log(%{
+ actor: admin,
+ followed: followed,
+ follower: follower,
+ action: "unfollow"
+ })
+ end
+
+ json(conn, "ok")
+ end
+
+ def create(%{assigns: %{user: admin}, body_params: %{users: users}} = conn, _) do
+ changesets =
+ users
+ |> Enum.map(fn %{nickname: nickname, email: email, password: password} ->
+ user_data = %{
+ nickname: nickname,
+ name: nickname,
+ email: email,
+ password: password,
+ password_confirmation: password,
+ bio: "."
+ }
+
+ User.register_changeset(%User{}, user_data, need_confirmation: false)
+ end)
+ |> Enum.reduce(Ecto.Multi.new(), fn changeset, multi ->
+ Ecto.Multi.insert(multi, Ecto.UUID.generate(), changeset)
+ end)
+
+ case Pleroma.Repo.transaction(changesets) do
+ {:ok, users_map} ->
+ users =
+ users_map
+ |> Map.values()
+ |> Enum.map(fn user ->
+ {:ok, user} = User.post_register_action(user)
+
+ user
+ end)
+
+ ModerationLog.insert_log(%{
+ actor: admin,
+ subjects: users,
+ action: "create"
+ })
+
+ render(conn, "created_many.json", users: users)
+
+ {:error, id, changeset, _} ->
+ changesets =
+ Enum.map(changesets.operations, fn
+ {^id, {:changeset, _current_changeset, _}} ->
+ changeset
+
+ {_, {:changeset, current_changeset, _}} ->
+ current_changeset
+ end)
+
+ conn
+ |> put_status(:conflict)
+ |> render("create_errors.json", changesets: changesets)
+ end
+ end
+
+ def show(%{assigns: %{user: admin}} = conn, %{nickname: nickname}) do
+ with %User{} = user <- User.get_cached_by_nickname_or_id(nickname, for: admin) do
+ render(conn, "show.json", %{user: user})
+ else
+ _ -> {:error, :not_found}
+ end
+ end
+
+ def toggle_activation(%{assigns: %{user: admin}} = conn, %{nickname: nickname}) do
+ user = User.get_cached_by_nickname(nickname)
+
+ {:ok, updated_user} = User.set_activation(user, !user.is_active)
+
+ action = if !user.is_active, do: "activate", else: "deactivate"
+
+ ModerationLog.insert_log(%{
+ actor: admin,
+ subject: [user],
+ action: action
+ })
+
+ render(conn, "show.json", user: updated_user)
+ end
+
+ def activate(%{assigns: %{user: admin}, body_params: %{nicknames: nicknames}} = conn, _) do
+ users = Enum.map(nicknames, &User.get_cached_by_nickname/1)
+ {:ok, updated_users} = User.set_activation(users, true)
+
+ ModerationLog.insert_log(%{
+ actor: admin,
+ subject: users,
+ action: "activate"
+ })
+
+ render(conn, "index.json", users: Keyword.values(updated_users))
+ end
+
+ def deactivate(%{assigns: %{user: admin}, body_params: %{nicknames: nicknames}} = conn, _) do
+ users = Enum.map(nicknames, &User.get_cached_by_nickname/1)
+ {:ok, updated_users} = User.set_activation(users, false)
+
+ ModerationLog.insert_log(%{
+ actor: admin,
+ subject: users,
+ action: "deactivate"
+ })
+
+ render(conn, "index.json", users: Keyword.values(updated_users))
+ end
+
+ def approve(%{assigns: %{user: admin}, body_params: %{nicknames: nicknames}} = conn, _) do
+ users = Enum.map(nicknames, &User.get_cached_by_nickname/1)
+ {:ok, updated_users} = User.approve(users)
+
+ ModerationLog.insert_log(%{
+ actor: admin,
+ subject: users,
+ action: "approve"
+ })
+
+ render(conn, "index.json", users: updated_users)
+ end
+
+ def suggest(%{assigns: %{user: admin}, body_params: %{nicknames: nicknames}} = conn, _) do
+ users = Enum.map(nicknames, &User.get_cached_by_nickname/1)
+ {:ok, updated_users} = User.set_suggestion(users, true)
+
+ ModerationLog.insert_log(%{
+ actor: admin,
+ subject: users,
+ action: "add_suggestion"
+ })
+
+ render(conn, "index.json", users: updated_users)
+ end
+
+ def unsuggest(%{assigns: %{user: admin}, body_params: %{nicknames: nicknames}} = conn, _) do
+ users = Enum.map(nicknames, &User.get_cached_by_nickname/1)
+ {:ok, updated_users} = User.set_suggestion(users, false)
+
+ ModerationLog.insert_log(%{
+ actor: admin,
+ subject: users,
+ action: "remove_suggestion"
+ })
+
+ render(conn, "index.json", users: updated_users)
+ end
+
+ def index(conn, params) do
+ {page, page_size} = page_params(params)
+ filters = maybe_parse_filters(params[:filters])
+
+ search_params =
+ %{
+ query: params[:query],
+ page: page,
+ page_size: page_size,
+ tags: params[:tags],
+ name: params[:name],
+ email: params[:email],
+ actor_types: params[:actor_types]
+ }
+ |> Map.merge(filters)
+
+ with {:ok, users, count} <- Search.user(search_params) do
+ render(conn, "index.json", users: users, count: count, page_size: page_size)
+ end
+ end
+
+ @filters ~w(local external active deactivated need_approval unconfirmed is_admin is_moderator)
+
+ @spec maybe_parse_filters(String.t()) :: %{required(String.t()) => true} | %{}
+ defp maybe_parse_filters(filters) when is_nil(filters) or filters == "", do: %{}
+
+ defp maybe_parse_filters(filters) do
+ filters
+ |> String.split(",")
+ |> Enum.filter(&Enum.member?(@filters, &1))
+ |> Map.new(&{String.to_existing_atom(&1), true})
+ end
+
+ defp page_params(params) do
+ {
+ fetch_integer_param(params, :page, 1),
+ fetch_integer_param(params, :page_size, @users_page_size)
+ }
+ end
+end
diff --git a/lib/pleroma/web/admin_api/report.ex b/lib/pleroma/web/admin_api/report.ex
index 8660d6520..345bc1e87 100644
--- a/lib/pleroma/web/admin_api/report.ex
+++ b/lib/pleroma/web/admin_api/report.ex
@@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.AdminAPI.Report do
@@ -13,7 +13,9 @@ defmodule Pleroma.Web.AdminAPI.Report do
account = User.get_cached_by_ap_id(account_ap_id)
statuses =
- Enum.map(status_ap_ids, fn
+ status_ap_ids
+ |> Enum.reject(&is_nil(&1))
+ |> Enum.map(fn
act when is_map(act) -> Activity.get_by_ap_id_with_object(act["id"])
act when is_binary(act) -> Activity.get_by_ap_id_with_object(act)
end)
diff --git a/lib/pleroma/web/admin_api/search.ex b/lib/pleroma/web/admin_api/search.ex
index 0bfb8f022..da38fab56 100644
--- a/lib/pleroma/web/admin_api/search.ex
+++ b/lib/pleroma/web/admin_api/search.ex
@@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.AdminAPI.Search do
@@ -10,12 +10,6 @@ defmodule Pleroma.Web.AdminAPI.Search do
@page_size 50
- defmacro not_empty_string(string) do
- quote do
- is_binary(unquote(string)) and unquote(string) != ""
- end
- end
-
@spec user(map()) :: {:ok, [User.t()], pos_integer()}
def user(params \\ %{}) do
query =
@@ -23,7 +17,7 @@ defmodule Pleroma.Web.AdminAPI.Search do
|> Map.drop([:page, :page_size])
|> Map.put(:invisible, false)
|> User.Query.build()
- |> order_by([u], u.nickname)
+ |> order_by(desc: :id)
paginated_query =
User.Query.paginate(query, params[:page] || 1, params[:page_size] || @page_size)
diff --git a/lib/pleroma/web/admin_api/views/account_view.ex b/lib/pleroma/web/admin_api/views/account_view.ex
index 9c477feab..2f1f7e627 100644
--- a/lib/pleroma/web/admin_api/views/account_view.ex
+++ b/lib/pleroma/web/admin_api/views/account_view.ex
@@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.AdminAPI.AccountView do
@@ -8,6 +8,7 @@ defmodule Pleroma.Web.AdminAPI.AccountView do
alias Pleroma.User
alias Pleroma.Web.AdminAPI
alias Pleroma.Web.AdminAPI.AccountView
+ alias Pleroma.Web.CommonAPI
alias Pleroma.Web.MastodonAPI
alias Pleroma.Web.MediaProxy
@@ -39,7 +40,7 @@ defmodule Pleroma.Web.AdminAPI.AccountView do
:fields,
:name,
:nickname,
- :locked,
+ :is_locked,
:no_rich_text,
:default_scope,
:hide_follows,
@@ -52,7 +53,7 @@ defmodule Pleroma.Web.AdminAPI.AccountView do
:skip_thread_containment,
:pleroma_settings_store,
:raw_fields,
- :discoverable,
+ :is_discoverable,
:actor_type
])
|> Map.merge(%{
@@ -69,21 +70,28 @@ defmodule Pleroma.Web.AdminAPI.AccountView do
%{
"id" => user.id,
+ "email" => user.email,
"avatar" => avatar,
"nickname" => user.nickname,
"display_name" => display_name,
- "deactivated" => user.deactivated,
+ "is_active" => user.is_active,
"local" => user.local,
- "roles" => User.roles(user),
+ "roles" => roles(user),
"tags" => user.tags || [],
- "confirmation_pending" => user.confirmation_pending,
- "approval_pending" => user.approval_pending,
+ "is_confirmed" => user.is_confirmed,
+ "is_approved" => user.is_approved,
+ "is_suggested" => user.is_suggested,
"url" => user.uri || user.ap_id,
"registration_reason" => user.registration_reason,
- "actor_type" => user.actor_type
+ "actor_type" => user.actor_type,
+ "created_at" => CommonAPI.Utils.to_masto_date(user.inserted_at)
}
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
%{
type: "success",
@@ -95,7 +103,11 @@ defmodule Pleroma.Web.AdminAPI.AccountView do
}
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",
code: 409,
@@ -139,4 +151,11 @@ defmodule Pleroma.Web.AdminAPI.AccountView do
defp image_url(%{"url" => [%{"href" => href} | _]}), do: href
defp image_url(_), do: nil
+
+ defp roles(%{is_moderator: is_moderator, is_admin: is_admin}) do
+ %{
+ admin: is_admin,
+ moderator: is_moderator
+ }
+ end
end
diff --git a/lib/pleroma/web/admin_api/views/chat_view.ex b/lib/pleroma/web/admin_api/views/chat_view.ex
new file mode 100644
index 000000000..2a2015ad1
--- /dev/null
+++ b/lib/pleroma/web/admin_api/views/chat_view.ex
@@ -0,0 +1,30 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.AdminAPI.ChatView do
+ use Pleroma.Web, :view
+
+ alias Pleroma.Chat
+ alias Pleroma.User
+ alias Pleroma.Web.MastodonAPI
+ alias Pleroma.Web.PleromaAPI
+
+ def render("index.json", %{chats: chats} = opts) do
+ render_many(chats, __MODULE__, "show.json", Map.delete(opts, :chats))
+ end
+
+ def render("show.json", %{chat: %Chat{user_id: user_id}} = opts) do
+ user = User.get_by_id(user_id)
+ sender = MastodonAPI.AccountView.render("show.json", user: user, skip_visibility_check: true)
+
+ serialized_chat = PleromaAPI.ChatView.render("show.json", opts)
+
+ serialized_chat
+ |> Map.put(:sender, sender)
+ |> Map.put(:receiver, serialized_chat[:account])
+ |> Map.delete(:account)
+ end
+
+ def render(view, opts), do: PleromaAPI.ChatView.render(view, opts)
+end
diff --git a/lib/pleroma/web/admin_api/views/config_view.ex b/lib/pleroma/web/admin_api/views/config_view.ex
index d2d8b5907..d29b4963d 100644
--- a/lib/pleroma/web/admin_api/views/config_view.ex
+++ b/lib/pleroma/web/admin_api/views/config_view.ex
@@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.AdminAPI.ConfigView do
diff --git a/lib/pleroma/web/admin_api/views/frontend_view.ex b/lib/pleroma/web/admin_api/views/frontend_view.ex
new file mode 100644
index 000000000..a3933a57d
--- /dev/null
+++ b/lib/pleroma/web/admin_api/views/frontend_view.ex
@@ -0,0 +1,21 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.AdminAPI.FrontendView do
+ use Pleroma.Web, :view
+
+ def render("index.json", %{frontends: frontends}) do
+ render_many(frontends, __MODULE__, "show.json")
+ end
+
+ def render("show.json", %{frontend: frontend}) do
+ %{
+ name: frontend["name"],
+ git: frontend["git"],
+ build_url: frontend["build_url"],
+ ref: frontend["ref"],
+ installed: frontend["installed"]
+ }
+ end
+end
diff --git a/lib/pleroma/web/admin_api/views/invite_view.ex b/lib/pleroma/web/admin_api/views/invite_view.ex
index f93cb6916..c7e307bda 100644
--- a/lib/pleroma/web/admin_api/views/invite_view.ex
+++ b/lib/pleroma/web/admin_api/views/invite_view.ex
@@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.AdminAPI.InviteView do
diff --git a/lib/pleroma/web/admin_api/views/media_proxy_cache_view.ex b/lib/pleroma/web/admin_api/views/media_proxy_cache_view.ex
index a803bda0b..1ec123048 100644
--- a/lib/pleroma/web/admin_api/views/media_proxy_cache_view.ex
+++ b/lib/pleroma/web/admin_api/views/media_proxy_cache_view.ex
@@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.AdminAPI.MediaProxyCacheView do
diff --git a/lib/pleroma/web/admin_api/views/moderation_log_view.ex b/lib/pleroma/web/admin_api/views/moderation_log_view.ex
index 112f9e0e1..b3a9efff3 100644
--- a/lib/pleroma/web/admin_api/views/moderation_log_view.ex
+++ b/lib/pleroma/web/admin_api/views/moderation_log_view.ex
@@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.AdminAPI.ModerationLogView do
@@ -21,6 +21,7 @@ defmodule Pleroma.Web.AdminAPI.ModerationLogView do
|> DateTime.to_unix()
%{
+ id: log_entry.id,
data: log_entry.data,
time: time,
message: ModerationLog.get_log_entry_message(log_entry)
diff --git a/lib/pleroma/web/admin_api/views/o_auth_app_view.ex b/lib/pleroma/web/admin_api/views/o_auth_app_view.ex
new file mode 100644
index 000000000..af046f343
--- /dev/null
+++ b/lib/pleroma/web/admin_api/views/o_auth_app_view.ex
@@ -0,0 +1,10 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.AdminAPI.OAuthAppView do
+ use Pleroma.Web, :view
+ alias Pleroma.Web.MastodonAPI
+
+ def render(view, opts), do: MastodonAPI.AppView.render(view, opts)
+end
diff --git a/lib/pleroma/web/admin_api/views/report_view.ex b/lib/pleroma/web/admin_api/views/report_view.ex
index 773f798fe..1c67b2458 100644
--- a/lib/pleroma/web/admin_api/views/report_view.ex
+++ b/lib/pleroma/web/admin_api/views/report_view.ex
@@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.AdminAPI.ReportView do
@@ -19,8 +19,7 @@ defmodule Pleroma.Web.AdminAPI.ReportView do
reports:
reports[:items]
|> Enum.map(&Report.extract_report_info/1)
- |> Enum.map(&render(__MODULE__, "show.json", &1))
- |> Enum.reverse(),
+ |> Enum.map(&render(__MODULE__, "show.json", &1)),
total: reports[:total]
}
end
@@ -52,7 +51,7 @@ defmodule Pleroma.Web.AdminAPI.ReportView do
end
def render("index_notes.json", %{notes: notes}) when is_list(notes) do
- Enum.map(notes, &render(__MODULE__, "show_note.json", &1))
+ Enum.map(notes, &render(__MODULE__, "show_note.json", Map.from_struct(&1)))
end
def render("index_notes.json", _), do: []
diff --git a/lib/pleroma/web/admin_api/views/status_view.ex b/lib/pleroma/web/admin_api/views/status_view.ex
index 500800be2..48d639b41 100644
--- a/lib/pleroma/web/admin_api/views/status_view.ex
+++ b/lib/pleroma/web/admin_api/views/status_view.ex
@@ -1,5 +1,5 @@
# Pleroma: A lightweight social networking server
-# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.Web.AdminAPI.StatusView do
@@ -8,16 +8,21 @@ defmodule Pleroma.Web.AdminAPI.StatusView do
require Pleroma.Constants
alias Pleroma.Web.AdminAPI
+ alias Pleroma.Web.CommonAPI
alias Pleroma.Web.MastodonAPI
defdelegate merge_account_views(user), to: AdminAPI.AccountView
+ def render("index.json", %{total: total} = opts) do
+ %{total: total, activities: safe_render_many(opts.activities, __MODULE__, "show.json", opts)}
+ end
+
def render("index.json", opts) do
safe_render_many(opts.activities, __MODULE__, "show.json", opts)
end
def render("show.json", %{activity: %{data: %{"object" => _object}} = activity} = opts) do
- user = MastodonAPI.StatusView.get_user(activity.data["actor"])
+ user = CommonAPI.get_user(activity.data["actor"])
MastodonAPI.StatusView.render("show.json", opts)
|> Map.merge(%{account: merge_account_views(user)})
diff --git a/lib/pleroma/web/admin_api/views/user_view.ex b/lib/pleroma/web/admin_api/views/user_view.ex
new file mode 100644
index 000000000..e91265ffe
--- /dev/null
+++ b/lib/pleroma/web/admin_api/views/user_view.ex
@@ -0,0 +1,10 @@
+# Pleroma: A lightweight social networking server
+# Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
+# SPDX-License-Identifier: AGPL-3.0-only
+
+defmodule Pleroma.Web.AdminAPI.UserView do
+ use Pleroma.Web, :view
+ alias Pleroma.Web.AdminAPI
+
+ def render(view, opts), do: AdminAPI.AccountView.render(view, opts)
+end