Fork of Pleroma with site-specific changes and feature branches https://git.pleroma.social/pleroma/pleroma
Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

284 řádky
7.4KB

  1. # Pleroma: A lightweight social networking server
  2. # Copyright © 2017-2021 Pleroma Authors <https://pleroma.social/>
  3. # SPDX-License-Identifier: AGPL-3.0-only
  4. defmodule Pleroma.Web.AdminAPI.UserController do
  5. use Pleroma.Web, :controller
  6. import Pleroma.Web.ControllerHelper,
  7. only: [fetch_integer_param: 3]
  8. alias Pleroma.ModerationLog
  9. alias Pleroma.User
  10. alias Pleroma.Web.ActivityPub.Builder
  11. alias Pleroma.Web.ActivityPub.Pipeline
  12. alias Pleroma.Web.AdminAPI
  13. alias Pleroma.Web.AdminAPI.Search
  14. alias Pleroma.Web.Plugs.OAuthScopesPlug
  15. @users_page_size 50
  16. plug(Pleroma.Web.ApiSpec.CastAndValidate)
  17. plug(
  18. OAuthScopesPlug,
  19. %{scopes: ["admin:read:accounts"]}
  20. when action in [:index, :show]
  21. )
  22. plug(
  23. OAuthScopesPlug,
  24. %{scopes: ["admin:write:accounts"]}
  25. when action in [
  26. :delete,
  27. :create,
  28. :toggle_activation,
  29. :activate,
  30. :deactivate,
  31. :approve
  32. ]
  33. )
  34. plug(
  35. OAuthScopesPlug,
  36. %{scopes: ["admin:write:follows"]}
  37. when action in [:follow, :unfollow]
  38. )
  39. plug(:put_view, Pleroma.Web.AdminAPI.AccountView)
  40. action_fallback(AdminAPI.FallbackController)
  41. defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.Admin.UserOperation
  42. def delete(conn, %{nickname: nickname}) do
  43. conn
  44. |> Map.put(:body_params, %{nicknames: [nickname]})
  45. |> delete(%{})
  46. end
  47. def delete(%{assigns: %{user: admin}, body_params: %{nicknames: nicknames}} = conn, _) do
  48. users = Enum.map(nicknames, &User.get_cached_by_nickname/1)
  49. Enum.each(users, fn user ->
  50. {:ok, delete_data, _} = Builder.delete(admin, user.ap_id)
  51. Pipeline.common_pipeline(delete_data, local: true)
  52. end)
  53. ModerationLog.insert_log(%{
  54. actor: admin,
  55. subject: users,
  56. action: "delete"
  57. })
  58. json(conn, nicknames)
  59. end
  60. def follow(
  61. %{
  62. assigns: %{user: admin},
  63. body_params: %{
  64. follower: follower_nick,
  65. followed: followed_nick
  66. }
  67. } = conn,
  68. _
  69. ) do
  70. with %User{} = follower <- User.get_cached_by_nickname(follower_nick),
  71. %User{} = followed <- User.get_cached_by_nickname(followed_nick) do
  72. User.follow(follower, followed)
  73. ModerationLog.insert_log(%{
  74. actor: admin,
  75. followed: followed,
  76. follower: follower,
  77. action: "follow"
  78. })
  79. end
  80. json(conn, "ok")
  81. end
  82. def unfollow(
  83. %{
  84. assigns: %{user: admin},
  85. body_params: %{
  86. follower: follower_nick,
  87. followed: followed_nick
  88. }
  89. } = conn,
  90. _
  91. ) do
  92. with %User{} = follower <- User.get_cached_by_nickname(follower_nick),
  93. %User{} = followed <- User.get_cached_by_nickname(followed_nick) do
  94. User.unfollow(follower, followed)
  95. ModerationLog.insert_log(%{
  96. actor: admin,
  97. followed: followed,
  98. follower: follower,
  99. action: "unfollow"
  100. })
  101. end
  102. json(conn, "ok")
  103. end
  104. def create(%{assigns: %{user: admin}, body_params: %{users: users}} = conn, _) do
  105. changesets =
  106. users
  107. |> Enum.map(fn %{nickname: nickname, email: email, password: password} ->
  108. user_data = %{
  109. nickname: nickname,
  110. name: nickname,
  111. email: email,
  112. password: password,
  113. password_confirmation: password,
  114. bio: "."
  115. }
  116. User.register_changeset(%User{}, user_data, need_confirmation: false)
  117. end)
  118. |> Enum.reduce(Ecto.Multi.new(), fn changeset, multi ->
  119. Ecto.Multi.insert(multi, Ecto.UUID.generate(), changeset)
  120. end)
  121. case Pleroma.Repo.transaction(changesets) do
  122. {:ok, users_map} ->
  123. users =
  124. users_map
  125. |> Map.values()
  126. |> Enum.map(fn user ->
  127. {:ok, user} = User.post_register_action(user)
  128. user
  129. end)
  130. ModerationLog.insert_log(%{
  131. actor: admin,
  132. subjects: users,
  133. action: "create"
  134. })
  135. render(conn, "created_many.json", users: users)
  136. {:error, id, changeset, _} ->
  137. changesets =
  138. Enum.map(changesets.operations, fn
  139. {^id, {:changeset, _current_changeset, _}} ->
  140. changeset
  141. {_, {:changeset, current_changeset, _}} ->
  142. current_changeset
  143. end)
  144. conn
  145. |> put_status(:conflict)
  146. |> render("create_errors.json", changesets: changesets)
  147. end
  148. end
  149. def show(%{assigns: %{user: admin}} = conn, %{nickname: nickname}) do
  150. with %User{} = user <- User.get_cached_by_nickname_or_id(nickname, for: admin) do
  151. render(conn, "show.json", %{user: user})
  152. else
  153. _ -> {:error, :not_found}
  154. end
  155. end
  156. def toggle_activation(%{assigns: %{user: admin}} = conn, %{nickname: nickname}) do
  157. user = User.get_cached_by_nickname(nickname)
  158. {:ok, updated_user} = User.set_activation(user, !user.is_active)
  159. action = if !user.is_active, do: "activate", else: "deactivate"
  160. ModerationLog.insert_log(%{
  161. actor: admin,
  162. subject: [user],
  163. action: action
  164. })
  165. render(conn, "show.json", user: updated_user)
  166. end
  167. def activate(%{assigns: %{user: admin}, body_params: %{nicknames: nicknames}} = conn, _) do
  168. users = Enum.map(nicknames, &User.get_cached_by_nickname/1)
  169. {:ok, updated_users} = User.set_activation(users, true)
  170. ModerationLog.insert_log(%{
  171. actor: admin,
  172. subject: users,
  173. action: "activate"
  174. })
  175. render(conn, "index.json", users: Keyword.values(updated_users))
  176. end
  177. def deactivate(%{assigns: %{user: admin}, body_params: %{nicknames: nicknames}} = conn, _) do
  178. users = Enum.map(nicknames, &User.get_cached_by_nickname/1)
  179. {:ok, updated_users} = User.set_activation(users, false)
  180. ModerationLog.insert_log(%{
  181. actor: admin,
  182. subject: users,
  183. action: "deactivate"
  184. })
  185. render(conn, "index.json", users: Keyword.values(updated_users))
  186. end
  187. def approve(%{assigns: %{user: admin}, body_params: %{nicknames: nicknames}} = conn, _) do
  188. users = Enum.map(nicknames, &User.get_cached_by_nickname/1)
  189. {:ok, updated_users} = User.approve(users)
  190. ModerationLog.insert_log(%{
  191. actor: admin,
  192. subject: users,
  193. action: "approve"
  194. })
  195. render(conn, "index.json", users: updated_users)
  196. end
  197. def index(conn, params) do
  198. {page, page_size} = page_params(params)
  199. filters = maybe_parse_filters(params[:filters])
  200. search_params =
  201. %{
  202. query: params[:query],
  203. page: page,
  204. page_size: page_size,
  205. tags: params[:tags],
  206. name: params[:name],
  207. email: params[:email],
  208. actor_types: params[:actor_types]
  209. }
  210. |> Map.merge(filters)
  211. with {:ok, users, count} <- Search.user(search_params) do
  212. render(conn, "index.json", users: users, count: count, page_size: page_size)
  213. end
  214. end
  215. @filters ~w(local external active deactivated need_approval unconfirmed is_admin is_moderator)
  216. @spec maybe_parse_filters(String.t()) :: %{required(String.t()) => true} | %{}
  217. defp maybe_parse_filters(filters) when is_nil(filters) or filters == "", do: %{}
  218. defp maybe_parse_filters(filters) do
  219. filters
  220. |> String.split(",")
  221. |> Enum.filter(&Enum.member?(@filters, &1))
  222. |> Map.new(&{String.to_existing_atom(&1), true})
  223. end
  224. defp page_params(params) do
  225. {
  226. fetch_integer_param(params, :page, 1),
  227. fetch_integer_param(params, :page_size, @users_page_size)
  228. }
  229. end
  230. end