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(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
165 |> json(%{error: "No such permission_group"})
168 def right_get(conn, %{"nickname" => nickname}) do
169 user = User.get_cached_by_nickname(nickname)
173 is_moderator: user.info.is_moderator,
174 is_admin: user.info.is_admin
179 %{assigns: %{user: %User{:nickname => admin_nickname}}} = conn,
181 "permission_group" => permission_group,
182 "nickname" => nickname
185 when permission_group in ["moderator", "admin"] do
186 if admin_nickname == nickname do
189 |> json(%{error: "You can't revoke your own admin status."})
191 user = User.get_cached_by_nickname(nickname)
195 |> Map.put("is_" <> permission_group, false)
197 info_cng = User.Info.admin_api_update(user.info, info)
200 Ecto.Changeset.change(user)
201 |> Ecto.Changeset.put_embed(:info, info_cng)
203 {:ok, _user} = User.update_and_set_cache(cng)
209 def right_delete(conn, _) do
212 |> json(%{error: "No such permission_group"})
215 def set_activation_status(conn, %{"nickname" => nickname, "status" => status}) do
216 with {:ok, status} <- Ecto.Type.cast(:boolean, status),
217 %User{} = user <- User.get_cached_by_nickname(nickname),
218 {:ok, _} <- User.deactivate(user, !status),
219 do: json_response(conn, :no_content, "")
222 def relay_follow(conn, %{"relay_url" => target}) do
223 with {:ok, _message} <- Relay.follow(target) do
233 def relay_unfollow(conn, %{"relay_url" => target}) do
234 with {:ok, _message} <- Relay.unfollow(target) do
244 @doc "Sends registration invite via email"
245 def email_invite(%{assigns: %{user: user}} = conn, %{"email" => email} = params) do
247 Pleroma.Config.get([:instance, :invites_enabled]) &&
248 !Pleroma.Config.get([:instance, :registrations_open]),
249 {:ok, invite_token} <- UserInviteToken.create_invite(),
251 Pleroma.Emails.UserEmail.user_invitation_email(
257 {:ok, _} <- Pleroma.Emails.Mailer.deliver(email) do
258 json_response(conn, :no_content, "")
262 @doc "Get a account registeration invite token (base64 string)"
263 def get_invite_token(conn, params) do
264 options = params["invite"] || %{}
265 {:ok, invite} = UserInviteToken.create_invite(options)
268 |> json(invite.token)
271 @doc "Get list of created invites"
272 def invites(conn, _params) do
273 invites = UserInviteToken.list_invites()
276 |> json(AccountView.render("invites.json", %{invites: invites}))
279 @doc "Revokes invite by token"
280 def revoke_invite(conn, %{"token" => token}) do
281 invite = UserInviteToken.find_by_token!(token)
282 {:ok, updated_invite} = UserInviteToken.update_invite(invite, %{used: true})
285 |> json(AccountView.render("invite.json", %{invite: updated_invite}))
288 @doc "Get a password reset token (base64 string) for given nickname"
289 def get_password_reset(conn, %{"nickname" => nickname}) do
290 (%User{local: true} = user) = User.get_cached_by_nickname(nickname)
291 {:ok, token} = Pleroma.PasswordResetToken.create_token(user)
297 def list_reports(conn, params) do
300 |> Map.put("type", "Flag")
301 |> Map.put("skip_preload", true)
305 |> ActivityPub.fetch_activities(params)
309 |> put_view(ReportView)
310 |> render("index.json", %{reports: reports})
313 def report_show(conn, %{"id" => id}) do
314 with %Activity{} = report <- Activity.get_by_id(id) do
316 |> put_view(ReportView)
317 |> render("show.json", %{report: report})
319 _ -> {:error, :not_found}
323 def report_update_state(conn, %{"id" => id, "state" => state}) do
324 with {:ok, report} <- CommonAPI.update_report_state(id, state) do
326 |> put_view(ReportView)
327 |> render("show.json", %{report: report})
331 def report_respond(%{assigns: %{user: user}} = conn, %{"id" => id} = params) do
332 with false <- is_nil(params["status"]),
333 %Activity{} <- Activity.get_by_id(id) do
336 |> Map.put("in_reply_to_status_id", id)
337 |> Map.put("visibility", "direct")
339 {:ok, activity} = CommonAPI.post(user, params)
342 |> put_view(StatusView)
343 |> render("status.json", %{activity: activity})
353 def status_update(conn, %{"id" => id} = params) do
354 with {:ok, activity} <- CommonAPI.update_activity_scope(id, params) do
356 |> put_view(StatusView)
357 |> render("status.json", %{activity: activity})
361 def status_delete(%{assigns: %{user: user}} = conn, %{"id" => id}) do
362 with {:ok, %Activity{}} <- CommonAPI.delete(id, user) do
367 def config_show(conn, _params) do
368 configs = Pleroma.Repo.all(Config)
371 |> put_view(ConfigView)
372 |> render("index.json", %{configs: configs})
375 def config_update(conn, %{"configs" => configs}) do
377 if Pleroma.Config.get([:instance, :dynamic_configuration]) do
380 %{"group" => group, "key" => key, "value" => value} ->
381 {:ok, config} = Config.update_or_create(%{group: group, key: key, value: value})
384 %{"group" => group, "key" => key, "delete" => "true"} ->
385 {:ok, _} = Config.delete(%{group: group, key: key})
388 |> Enum.reject(&is_nil(&1))
390 Pleroma.Config.TransferTask.load_and_update_env()
391 Mix.Tasks.Pleroma.Config.run(["migrate_from_db", Pleroma.Config.get(:env)])
398 |> put_view(ConfigView)
399 |> render("index.json", %{configs: updated})
402 def errors(conn, {:error, :not_found}) do
408 def errors(conn, {:error, reason}) do
414 def errors(conn, {:param_cast, _}) do
417 |> json("Invalid parameters")
420 def errors(conn, _) do
423 |> json("Something went wrong")
426 defp page_params(params) do
427 {get_page(params["page"]), get_page_size(params["page_size"])}
430 defp get_page(page_string) when is_nil(page_string), do: 1
432 defp get_page(page_string) do
433 case Integer.parse(page_string) do
439 defp get_page_size(page_size_string) when is_nil(page_size_string), do: @users_page_size
441 defp get_page_size(page_size_string) do
442 case Integer.parse(page_size_string) do
443 {page_size, _} -> page_size
444 :error -> @users_page_size