1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
5 defmodule Pleroma.Web.AdminAPI.AdminAPIController do
6 use Pleroma.Web, :controller
9 alias Pleroma.UserInviteToken
10 alias Pleroma.Web.ActivityPub.ActivityPub
11 alias Pleroma.Web.ActivityPub.Relay
12 alias Pleroma.Web.AdminAPI.AccountView
13 alias Pleroma.Web.AdminAPI.Config
14 alias Pleroma.Web.AdminAPI.ConfigView
15 alias Pleroma.Web.AdminAPI.ReportView
16 alias Pleroma.Web.AdminAPI.Search
17 alias Pleroma.Web.CommonAPI
18 alias Pleroma.Web.MastodonAPI.StatusView
20 import Pleroma.Web.ControllerHelper, only: [json_response: 3]
26 action_fallback(:errors)
28 def user_delete(conn, %{"nickname" => nickname}) do
29 User.get_cached_by_nickname(nickname)
36 def user_follow(conn, %{"follower" => follower_nick, "followed" => followed_nick}) do
37 with %User{} = follower <- User.get_cached_by_nickname(follower_nick),
38 %User{} = followed <- User.get_cached_by_nickname(followed_nick) do
39 User.follow(follower, followed)
46 def user_unfollow(conn, %{"follower" => follower_nick, "followed" => followed_nick}) do
47 with %User{} = follower <- User.get_cached_by_nickname(follower_nick),
48 %User{} = followed <- User.get_cached_by_nickname(followed_nick) do
49 User.unfollow(follower, followed)
58 %{"nickname" => nickname, "email" => email, "password" => password}
65 password_confirmation: password,
69 changeset = User.register_changeset(%User{}, user_data, need_confirmation: false)
70 {:ok, user} = User.register(changeset)
73 |> json(user.nickname)
76 def user_show(conn, %{"nickname" => nickname}) do
77 with %User{} = user <- User.get_cached_by_nickname_or_id(nickname) do
79 |> json(AccountView.render("show.json", %{user: user}))
81 _ -> {:error, :not_found}
85 def user_toggle_activation(conn, %{"nickname" => nickname}) do
86 user = User.get_cached_by_nickname(nickname)
88 {:ok, updated_user} = User.deactivate(user, !user.info.deactivated)
91 |> json(AccountView.render("show.json", %{user: updated_user}))
94 def tag_users(conn, %{"nicknames" => nicknames, "tags" => tags}) do
95 with {:ok, _} <- User.tag(nicknames, tags),
96 do: json_response(conn, :no_content, "")
99 def untag_users(conn, %{"nicknames" => nicknames, "tags" => tags}) do
100 with {:ok, _} <- User.untag(nicknames, tags),
101 do: json_response(conn, :no_content, "")
104 def list_users(conn, params) do
105 {page, page_size} = page_params(params)
106 filters = maybe_parse_filters(params["filters"])
109 query: params["query"],
111 page_size: page_size,
112 tags: params["tags"],
113 name: params["name"],
114 email: params["email"]
117 with {:ok, users, count} <- Search.user(Map.merge(search_params, filters)),
121 AccountView.render("index.json",
129 @filters ~w(local external active deactivated is_admin is_moderator)
131 @spec maybe_parse_filters(String.t()) :: %{required(String.t()) => true} | %{}
132 defp maybe_parse_filters(filters) when is_nil(filters) or filters == "", do: %{}
134 defp maybe_parse_filters(filters) do
137 |> Enum.filter(&Enum.member?(@filters, &1))
138 |> Enum.map(&String.to_atom(&1))
139 |> Enum.into(%{}, &{&1, true})
142 def right_add(conn, %{"permission_group" => permission_group, "nickname" => nickname})
143 when permission_group in ["moderator", "admin"] do
144 user = User.get_cached_by_nickname(nickname)
148 |> Map.put("is_" <> permission_group, true)
150 info_cng = User.Info.admin_api_update(user.info, info)
154 |> Ecto.Changeset.change()
155 |> Ecto.Changeset.put_embed(:info, info_cng)
157 {:ok, _user} = User.update_and_set_cache(cng)
162 def right_add(conn, _) do
163 render_error(conn, :not_found, "No such permission_group")
166 def right_get(conn, %{"nickname" => nickname}) do
167 user = User.get_cached_by_nickname(nickname)
171 is_moderator: user.info.is_moderator,
172 is_admin: user.info.is_admin
177 %{assigns: %{user: %User{:nickname => admin_nickname}}} = conn,
179 "permission_group" => permission_group,
180 "nickname" => nickname
183 when permission_group in ["moderator", "admin"] do
184 if admin_nickname == nickname do
185 render_error(conn, :forbidden, "You can't revoke your own admin status.")
187 user = User.get_cached_by_nickname(nickname)
191 |> Map.put("is_" <> permission_group, false)
193 info_cng = User.Info.admin_api_update(user.info, info)
196 Ecto.Changeset.change(user)
197 |> Ecto.Changeset.put_embed(:info, info_cng)
199 {:ok, _user} = User.update_and_set_cache(cng)
205 def right_delete(conn, _) do
206 render_error(conn, :not_found, "No such permission_group")
209 def set_activation_status(conn, %{"nickname" => nickname, "status" => status}) do
210 with {:ok, status} <- Ecto.Type.cast(:boolean, status),
211 %User{} = user <- User.get_cached_by_nickname(nickname),
212 {:ok, _} <- User.deactivate(user, !status),
213 do: json_response(conn, :no_content, "")
216 def relay_follow(conn, %{"relay_url" => target}) do
217 with {:ok, _message} <- Relay.follow(target) do
227 def relay_unfollow(conn, %{"relay_url" => target}) do
228 with {:ok, _message} <- Relay.unfollow(target) do
238 @doc "Sends registration invite via email"
239 def email_invite(%{assigns: %{user: user}} = conn, %{"email" => email} = params) do
241 Pleroma.Config.get([:instance, :invites_enabled]) &&
242 !Pleroma.Config.get([:instance, :registrations_open]),
243 {:ok, invite_token} <- UserInviteToken.create_invite(),
245 Pleroma.Emails.UserEmail.user_invitation_email(
251 {:ok, _} <- Pleroma.Emails.Mailer.deliver(email) do
252 json_response(conn, :no_content, "")
256 @doc "Get a account registeration invite token (base64 string)"
257 def get_invite_token(conn, params) do
258 options = params["invite"] || %{}
259 {:ok, invite} = UserInviteToken.create_invite(options)
262 |> json(invite.token)
265 @doc "Get list of created invites"
266 def invites(conn, _params) do
267 invites = UserInviteToken.list_invites()
270 |> json(AccountView.render("invites.json", %{invites: invites}))
273 @doc "Revokes invite by token"
274 def revoke_invite(conn, %{"token" => token}) do
275 invite = UserInviteToken.find_by_token!(token)
276 {:ok, updated_invite} = UserInviteToken.update_invite(invite, %{used: true})
279 |> json(AccountView.render("invite.json", %{invite: updated_invite}))
282 @doc "Get a password reset token (base64 string) for given nickname"
283 def get_password_reset(conn, %{"nickname" => nickname}) do
284 (%User{local: true} = user) = User.get_cached_by_nickname(nickname)
285 {:ok, token} = Pleroma.PasswordResetToken.create_token(user)
291 def list_reports(conn, params) do
294 |> Map.put("type", "Flag")
295 |> Map.put("skip_preload", true)
299 |> ActivityPub.fetch_activities(params)
303 |> put_view(ReportView)
304 |> render("index.json", %{reports: reports})
307 def report_show(conn, %{"id" => id}) do
308 with %Activity{} = report <- Activity.get_by_id(id) do
310 |> put_view(ReportView)
311 |> render("show.json", %{report: report})
313 _ -> {:error, :not_found}
317 def report_update_state(conn, %{"id" => id, "state" => state}) do
318 with {:ok, report} <- CommonAPI.update_report_state(id, state) do
320 |> put_view(ReportView)
321 |> render("show.json", %{report: report})
325 def report_respond(%{assigns: %{user: user}} = conn, %{"id" => id} = params) do
326 with false <- is_nil(params["status"]),
327 %Activity{} <- Activity.get_by_id(id) do
330 |> Map.put("in_reply_to_status_id", id)
331 |> Map.put("visibility", "direct")
333 {:ok, activity} = CommonAPI.post(user, params)
336 |> put_view(StatusView)
337 |> render("status.json", %{activity: activity})
347 def status_update(conn, %{"id" => id} = params) do
348 with {:ok, activity} <- CommonAPI.update_activity_scope(id, params) do
350 |> put_view(StatusView)
351 |> render("status.json", %{activity: activity})
355 def status_delete(%{assigns: %{user: user}} = conn, %{"id" => id}) do
356 with {:ok, %Activity{}} <- CommonAPI.delete(id, user) do
361 def config_show(conn, _params) do
362 configs = Pleroma.Repo.all(Config)
365 |> put_view(ConfigView)
366 |> render("index.json", %{configs: configs})
369 def config_update(conn, %{"configs" => configs}) do
371 if Pleroma.Config.get([:instance, :dynamic_configuration]) do
374 %{"group" => group, "key" => key, "delete" => "true"} ->
375 {:ok, _} = Config.delete(%{group: group, key: key})
378 %{"group" => group, "key" => key, "value" => value} ->
379 {:ok, config} = Config.update_or_create(%{group: group, key: key, value: value})
382 |> Enum.reject(&is_nil(&1))
384 Pleroma.Config.TransferTask.load_and_update_env()
385 Mix.Tasks.Pleroma.Config.run(["migrate_from_db", Pleroma.Config.get(:env), "false"])
392 |> put_view(ConfigView)
393 |> render("index.json", %{configs: updated})
396 def errors(conn, {:error, :not_found}) do
398 |> put_status(:not_found)
399 |> json(dgettext("errors", "Not found"))
402 def errors(conn, {:error, reason}) do
404 |> put_status(:bad_request)
408 def errors(conn, {:param_cast, _}) do
410 |> put_status(:bad_request)
411 |> json(dgettext("errors", "Invalid parameters"))
414 def errors(conn, _) do
416 |> put_status(:internal_server_error)
417 |> json(dgettext("errors", "Something went wrong"))
420 defp page_params(params) do
421 {get_page(params["page"]), get_page_size(params["page_size"])}
424 defp get_page(page_string) when is_nil(page_string), do: 1
426 defp get_page(page_string) do
427 case Integer.parse(page_string) do
433 defp get_page_size(page_size_string) when is_nil(page_size_string), do: @users_page_size
435 defp get_page_size(page_size_string) do
436 case Integer.parse(page_size_string) do
437 {page_size, _} -> page_size
438 :error -> @users_page_size