logo

pleroma

My custom branche(s) on git.pleroma.social/pleroma/pleroma git clone https://hacktivis.me/git/pleroma.git

user_controller.ex (9439B)


  1. # Pleroma: A lightweight social networking server
  2. # Copyright © 2017-2022 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, replace_params: false)
  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. :suggest,
  33. :unsuggest
  34. ]
  35. )
  36. plug(
  37. OAuthScopesPlug,
  38. %{scopes: ["admin:write:follows"]}
  39. when action in [:follow, :unfollow]
  40. )
  41. action_fallback(AdminAPI.FallbackController)
  42. defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.Admin.UserOperation
  43. def delete(%{private: %{open_api_spex: %{params: %{nickname: nickname}}}} = conn, _) do
  44. conn
  45. |> do_deletes([nickname])
  46. end
  47. def delete(
  48. %{
  49. private: %{open_api_spex: %{body_params: %{nicknames: nicknames}}}
  50. } = conn,
  51. _
  52. ) do
  53. conn
  54. |> do_deletes(nicknames)
  55. end
  56. defp do_deletes(%{assigns: %{user: admin}} = conn, nicknames) when is_list(nicknames) do
  57. users = Enum.map(nicknames, &User.get_cached_by_nickname/1)
  58. Enum.each(users, fn user ->
  59. {:ok, delete_data, _} = Builder.delete(admin, user.ap_id)
  60. Pipeline.common_pipeline(delete_data, local: true)
  61. end)
  62. ModerationLog.insert_log(%{
  63. actor: admin,
  64. subject: users,
  65. action: "delete"
  66. })
  67. json(conn, nicknames)
  68. end
  69. def follow(
  70. %{
  71. assigns: %{user: admin},
  72. private: %{
  73. open_api_spex: %{
  74. body_params: %{
  75. follower: follower_nick,
  76. followed: followed_nick
  77. }
  78. }
  79. }
  80. } = conn,
  81. _
  82. ) do
  83. with %User{} = follower <- User.get_cached_by_nickname(follower_nick),
  84. %User{} = followed <- User.get_cached_by_nickname(followed_nick) do
  85. User.follow(follower, followed)
  86. ModerationLog.insert_log(%{
  87. actor: admin,
  88. followed: followed,
  89. follower: follower,
  90. action: "follow"
  91. })
  92. end
  93. json(conn, "ok")
  94. end
  95. def unfollow(
  96. %{
  97. assigns: %{user: admin},
  98. private: %{
  99. open_api_spex: %{
  100. body_params: %{
  101. follower: follower_nick,
  102. followed: followed_nick
  103. }
  104. }
  105. }
  106. } = conn,
  107. _
  108. ) do
  109. with %User{} = follower <- User.get_cached_by_nickname(follower_nick),
  110. %User{} = followed <- User.get_cached_by_nickname(followed_nick) do
  111. User.unfollow(follower, followed)
  112. ModerationLog.insert_log(%{
  113. actor: admin,
  114. followed: followed,
  115. follower: follower,
  116. action: "unfollow"
  117. })
  118. end
  119. json(conn, "ok")
  120. end
  121. def create(
  122. %{
  123. assigns: %{user: admin},
  124. private: %{open_api_spex: %{body_params: %{users: users}}}
  125. } = conn,
  126. _
  127. ) do
  128. changesets =
  129. users
  130. |> Enum.map(fn %{nickname: nickname, email: email, password: password} ->
  131. user_data = %{
  132. nickname: nickname,
  133. name: nickname,
  134. email: email,
  135. password: password,
  136. password_confirmation: password,
  137. bio: "."
  138. }
  139. User.register_changeset(%User{}, user_data, need_confirmation: false)
  140. end)
  141. |> Enum.reduce(Ecto.Multi.new(), fn changeset, multi ->
  142. Ecto.Multi.insert(multi, Ecto.UUID.generate(), changeset)
  143. end)
  144. case Pleroma.Repo.transaction(changesets) do
  145. {:ok, users_map} ->
  146. users =
  147. users_map
  148. |> Map.values()
  149. |> Enum.map(fn user ->
  150. {:ok, user} = User.post_register_action(user)
  151. user
  152. end)
  153. ModerationLog.insert_log(%{
  154. actor: admin,
  155. subjects: users,
  156. action: "create"
  157. })
  158. render(conn, "created_many.json", users: users)
  159. {:error, id, changeset, _} ->
  160. changesets =
  161. Enum.map(changesets.operations, fn
  162. {^id, {:changeset, _current_changeset, _}} ->
  163. changeset
  164. {_, {:changeset, current_changeset, _}} ->
  165. current_changeset
  166. end)
  167. conn
  168. |> put_status(:conflict)
  169. |> render("create_errors.json", changesets: changesets)
  170. end
  171. end
  172. def show(
  173. %{
  174. assigns: %{user: admin},
  175. private: %{open_api_spex: %{params: %{nickname: nickname}}}
  176. } = conn,
  177. _
  178. ) do
  179. with %User{} = user <- User.get_cached_by_nickname_or_id(nickname, for: admin) do
  180. render(conn, "show.json", %{user: user})
  181. else
  182. _ -> {:error, :not_found}
  183. end
  184. end
  185. def toggle_activation(
  186. %{assigns: %{user: admin}, private: %{open_api_spex: %{params: %{nickname: nickname}}}} =
  187. conn,
  188. _
  189. ) do
  190. user = User.get_cached_by_nickname(nickname)
  191. {:ok, updated_user} = User.set_activation(user, !user.is_active)
  192. action = if !user.is_active, do: "activate", else: "deactivate"
  193. ModerationLog.insert_log(%{
  194. actor: admin,
  195. subject: [user],
  196. action: action
  197. })
  198. render(conn, "show.json", user: updated_user)
  199. end
  200. def activate(
  201. %{
  202. assigns: %{user: admin},
  203. private: %{open_api_spex: %{body_params: %{nicknames: nicknames}}}
  204. } = conn,
  205. _
  206. ) do
  207. users = Enum.map(nicknames, &User.get_cached_by_nickname/1)
  208. {:ok, updated_users} = User.set_activation(users, true)
  209. ModerationLog.insert_log(%{
  210. actor: admin,
  211. subject: users,
  212. action: "activate"
  213. })
  214. render(conn, "index.json", users: updated_users)
  215. end
  216. def deactivate(
  217. %{
  218. assigns: %{user: admin},
  219. private: %{open_api_spex: %{body_params: %{nicknames: nicknames}}}
  220. } = conn,
  221. _
  222. ) do
  223. users = Enum.map(nicknames, &User.get_cached_by_nickname/1)
  224. {:ok, updated_users} = User.set_activation(users, false)
  225. ModerationLog.insert_log(%{
  226. actor: admin,
  227. subject: users,
  228. action: "deactivate"
  229. })
  230. render(conn, "index.json", users: updated_users)
  231. end
  232. def approve(
  233. %{
  234. assigns: %{user: admin},
  235. private: %{open_api_spex: %{body_params: %{nicknames: nicknames}}}
  236. } = conn,
  237. _
  238. ) do
  239. users = Enum.map(nicknames, &User.get_cached_by_nickname/1)
  240. {:ok, updated_users} = User.approve(users)
  241. ModerationLog.insert_log(%{
  242. actor: admin,
  243. subject: users,
  244. action: "approve"
  245. })
  246. render(conn, "index.json", users: updated_users)
  247. end
  248. def suggest(
  249. %{
  250. assigns: %{user: admin},
  251. private: %{open_api_spex: %{body_params: %{nicknames: nicknames}}}
  252. } = conn,
  253. _
  254. ) do
  255. users = Enum.map(nicknames, &User.get_cached_by_nickname/1)
  256. {:ok, updated_users} = User.set_suggestion(users, true)
  257. ModerationLog.insert_log(%{
  258. actor: admin,
  259. subject: users,
  260. action: "add_suggestion"
  261. })
  262. render(conn, "index.json", users: updated_users)
  263. end
  264. def unsuggest(
  265. %{
  266. assigns: %{user: admin},
  267. private: %{open_api_spex: %{body_params: %{nicknames: nicknames}}}
  268. } = conn,
  269. _
  270. ) do
  271. users = Enum.map(nicknames, &User.get_cached_by_nickname/1)
  272. {:ok, updated_users} = User.set_suggestion(users, false)
  273. ModerationLog.insert_log(%{
  274. actor: admin,
  275. subject: users,
  276. action: "remove_suggestion"
  277. })
  278. render(conn, "index.json", users: updated_users)
  279. end
  280. def index(%{private: %{open_api_spex: %{params: params}}} = conn, _) do
  281. {page, page_size} = page_params(params)
  282. filters = maybe_parse_filters(params[:filters])
  283. search_params =
  284. %{
  285. query: params[:query],
  286. page: page,
  287. page_size: page_size,
  288. tags: params[:tags],
  289. name: params[:name],
  290. email: params[:email],
  291. actor_types: params[:actor_types]
  292. }
  293. |> Map.merge(filters)
  294. with {:ok, users, count} <- Search.user(search_params) do
  295. render(conn, "index.json", users: users, count: count, page_size: page_size)
  296. end
  297. end
  298. @filters ~w(local external active deactivated need_approval unconfirmed is_admin is_moderator)
  299. @spec maybe_parse_filters(String.t()) :: %{required(String.t()) => true} | %{}
  300. defp maybe_parse_filters(filters) when is_nil(filters) or filters == "", do: %{}
  301. defp maybe_parse_filters(filters) do
  302. filters
  303. |> String.split(",")
  304. |> Enum.filter(&Enum.member?(@filters, &1))
  305. |> Map.new(&{String.to_existing_atom(&1), true})
  306. end
  307. defp page_params(params) do
  308. {
  309. fetch_integer_param(params, :page, 1),
  310. fetch_integer_param(params, :page_size, @users_page_size)
  311. }
  312. end
  313. end