1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2020 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
8 import Pleroma.Web.ControllerHelper, only: [json_response: 3]
10 alias Pleroma.Activity
12 alias Pleroma.ConfigDB
14 alias Pleroma.ModerationLog
15 alias Pleroma.Plugs.OAuthScopesPlug
16 alias Pleroma.ReportNote
19 alias Pleroma.UserInviteToken
20 alias Pleroma.Web.ActivityPub.ActivityPub
21 alias Pleroma.Web.ActivityPub.Builder
22 alias Pleroma.Web.ActivityPub.Pipeline
23 alias Pleroma.Web.ActivityPub.Relay
24 alias Pleroma.Web.ActivityPub.Utils
25 alias Pleroma.Web.AdminAPI.AccountView
26 alias Pleroma.Web.AdminAPI.ConfigView
27 alias Pleroma.Web.AdminAPI.ModerationLogView
28 alias Pleroma.Web.AdminAPI.Report
29 alias Pleroma.Web.AdminAPI.ReportView
30 alias Pleroma.Web.AdminAPI.Search
31 alias Pleroma.Web.CommonAPI
32 alias Pleroma.Web.Endpoint
33 alias Pleroma.Web.MastodonAPI.AppView
34 alias Pleroma.Web.MastodonAPI.StatusView
35 alias Pleroma.Web.OAuth.App
36 alias Pleroma.Web.Router
40 @descriptions Pleroma.Docs.JSON.compile()
45 %{scopes: ["read:accounts"], admin: true}
46 when action in [:list_users, :user_show, :right_get, :show_user_credentials]
51 %{scopes: ["write:accounts"], admin: true}
54 :force_password_reset,
57 :user_toggle_activation,
66 :right_delete_multiple,
67 :update_user_credentials
71 plug(OAuthScopesPlug, %{scopes: ["read:invites"], admin: true} when action == :invites)
75 %{scopes: ["write:invites"], admin: true}
76 when action in [:create_invite_token, :revoke_invite, :email_invite]
81 %{scopes: ["write:follows"], admin: true}
82 when action in [:user_follow, :user_unfollow, :relay_follow, :relay_unfollow]
87 %{scopes: ["read:reports"], admin: true}
88 when action in [:list_reports, :report_show]
93 %{scopes: ["write:reports"], admin: true}
94 when action in [:reports_update, :report_notes_create, :report_notes_delete]
99 %{scopes: ["read:statuses"], admin: true}
100 when action in [:list_statuses, :list_user_statuses, :list_instance_statuses, :status_show]
105 %{scopes: ["write:statuses"], admin: true}
106 when action in [:status_update, :status_delete]
111 %{scopes: ["read"], admin: true}
117 :config_descriptions,
124 %{scopes: ["write"], admin: true}
128 :resend_confirmation_email,
138 action_fallback(:errors)
140 def user_delete(conn, %{"nickname" => nickname}) do
141 user_delete(conn, %{"nicknames" => [nickname]})
144 def user_delete(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do
147 |> Enum.map(&User.get_cached_by_nickname/1)
150 |> Enum.each(fn user ->
151 {:ok, delete_data, _} = Builder.delete(admin, user.ap_id)
152 Pipeline.common_pipeline(delete_data, local: true)
155 ModerationLog.insert_log(%{
165 def user_follow(%{assigns: %{user: admin}} = conn, %{
166 "follower" => follower_nick,
167 "followed" => followed_nick
169 with %User{} = follower <- User.get_cached_by_nickname(follower_nick),
170 %User{} = followed <- User.get_cached_by_nickname(followed_nick) do
171 User.follow(follower, followed)
173 ModerationLog.insert_log(%{
185 def user_unfollow(%{assigns: %{user: admin}} = conn, %{
186 "follower" => follower_nick,
187 "followed" => followed_nick
189 with %User{} = follower <- User.get_cached_by_nickname(follower_nick),
190 %User{} = followed <- User.get_cached_by_nickname(followed_nick) do
191 User.unfollow(follower, followed)
193 ModerationLog.insert_log(%{
205 def users_create(%{assigns: %{user: admin}} = conn, %{"users" => users}) do
207 Enum.map(users, fn %{"nickname" => nickname, "email" => email, "password" => password} ->
213 password_confirmation: password,
217 User.register_changeset(%User{}, user_data, need_confirmation: false)
219 |> Enum.reduce(Ecto.Multi.new(), fn changeset, multi ->
220 Ecto.Multi.insert(multi, Ecto.UUID.generate(), changeset)
223 case Pleroma.Repo.transaction(changesets) do
228 |> Enum.map(fn user ->
229 {:ok, user} = User.post_register_action(user)
233 |> Enum.map(&AccountView.render("created.json", %{user: &1}))
235 ModerationLog.insert_log(%{
237 subjects: Map.values(users),
244 {:error, id, changeset, _} ->
246 Enum.map(changesets.operations, fn
247 {current_id, {:changeset, _current_changeset, _}} when current_id == id ->
248 AccountView.render("create-error.json", %{changeset: changeset})
250 {_, {:changeset, current_changeset, _}} ->
251 AccountView.render("create-error.json", %{changeset: current_changeset})
255 |> put_status(:conflict)
260 def user_show(conn, %{"nickname" => nickname}) do
261 with %User{} = user <- User.get_cached_by_nickname_or_id(nickname) do
263 |> put_view(AccountView)
264 |> render("show.json", %{user: user})
266 _ -> {:error, :not_found}
270 def list_instance_statuses(conn, %{"instance" => instance} = params) do
271 with_reblogs = params["with_reblogs"] == "true" || params["with_reblogs"] == true
272 {page, page_size} = page_params(params)
275 ActivityPub.fetch_statuses(nil, %{
276 "instance" => instance,
277 "limit" => page_size,
278 "offset" => (page - 1) * page_size,
279 "exclude_reblogs" => !with_reblogs && "true"
283 |> put_view(Pleroma.Web.AdminAPI.StatusView)
284 |> render("index.json", %{activities: activities, as: :activity, skip_relationships: false})
287 def list_user_statuses(conn, %{"nickname" => nickname} = params) do
288 with_reblogs = params["with_reblogs"] == "true" || params["with_reblogs"] == true
289 godmode = params["godmode"] == "true" || params["godmode"] == true
291 with %User{} = user <- User.get_cached_by_nickname_or_id(nickname) do
292 {_, page_size} = page_params(params)
295 ActivityPub.fetch_user_activities(user, nil, %{
296 "limit" => page_size,
297 "godmode" => godmode,
298 "exclude_reblogs" => !with_reblogs && "true"
302 |> put_view(StatusView)
303 |> render("index.json", %{activities: activities, as: :activity, skip_relationships: false})
305 _ -> {:error, :not_found}
309 def user_toggle_activation(%{assigns: %{user: admin}} = conn, %{"nickname" => nickname}) do
310 user = User.get_cached_by_nickname(nickname)
312 {:ok, updated_user} = User.deactivate(user, !user.deactivated)
314 action = if user.deactivated, do: "activate", else: "deactivate"
316 ModerationLog.insert_log(%{
323 |> put_view(AccountView)
324 |> render("show.json", %{user: updated_user})
327 def user_activate(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do
328 users = Enum.map(nicknames, &User.get_cached_by_nickname/1)
329 {:ok, updated_users} = User.deactivate(users, false)
331 ModerationLog.insert_log(%{
338 |> put_view(AccountView)
339 |> render("index.json", %{users: Keyword.values(updated_users)})
342 def user_deactivate(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do
343 users = Enum.map(nicknames, &User.get_cached_by_nickname/1)
344 {:ok, updated_users} = User.deactivate(users, true)
346 ModerationLog.insert_log(%{
353 |> put_view(AccountView)
354 |> render("index.json", %{users: Keyword.values(updated_users)})
357 def tag_users(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames, "tags" => tags}) do
358 with {:ok, _} <- User.tag(nicknames, tags) do
359 ModerationLog.insert_log(%{
361 nicknames: nicknames,
366 json_response(conn, :no_content, "")
370 def untag_users(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames, "tags" => tags}) do
371 with {:ok, _} <- User.untag(nicknames, tags) do
372 ModerationLog.insert_log(%{
374 nicknames: nicknames,
379 json_response(conn, :no_content, "")
383 def list_users(conn, params) do
384 {page, page_size} = page_params(params)
385 filters = maybe_parse_filters(params["filters"])
388 query: params["query"],
390 page_size: page_size,
391 tags: params["tags"],
392 name: params["name"],
393 email: params["email"]
396 with {:ok, users, count} <- Search.user(Map.merge(search_params, filters)) do
399 AccountView.render("index.json", users: users, count: count, page_size: page_size)
404 @filters ~w(local external active deactivated is_admin is_moderator)
406 @spec maybe_parse_filters(String.t()) :: %{required(String.t()) => true} | %{}
407 defp maybe_parse_filters(filters) when is_nil(filters) or filters == "", do: %{}
409 defp maybe_parse_filters(filters) do
412 |> Enum.filter(&Enum.member?(@filters, &1))
413 |> Enum.map(&String.to_atom(&1))
414 |> Enum.into(%{}, &{&1, true})
417 def right_add_multiple(%{assigns: %{user: admin}} = conn, %{
418 "permission_group" => permission_group,
419 "nicknames" => nicknames
421 when permission_group in ["moderator", "admin"] do
422 update = %{:"is_#{permission_group}" => true}
424 users = nicknames |> Enum.map(&User.get_cached_by_nickname/1)
426 for u <- users, do: User.admin_api_update(u, update)
428 ModerationLog.insert_log(%{
432 permission: permission_group
438 def right_add_multiple(conn, _) do
439 render_error(conn, :not_found, "No such permission_group")
442 def right_add(%{assigns: %{user: admin}} = conn, %{
443 "permission_group" => permission_group,
444 "nickname" => nickname
446 when permission_group in ["moderator", "admin"] do
447 fields = %{:"is_#{permission_group}" => true}
451 |> User.get_cached_by_nickname()
452 |> User.admin_api_update(fields)
454 ModerationLog.insert_log(%{
458 permission: permission_group
464 def right_add(conn, _) do
465 render_error(conn, :not_found, "No such permission_group")
468 def right_get(conn, %{"nickname" => nickname}) do
469 user = User.get_cached_by_nickname(nickname)
473 is_moderator: user.is_moderator,
474 is_admin: user.is_admin
478 def right_delete_multiple(
479 %{assigns: %{user: %{nickname: admin_nickname} = admin}} = conn,
481 "permission_group" => permission_group,
482 "nicknames" => nicknames
485 when permission_group in ["moderator", "admin"] do
486 with false <- Enum.member?(nicknames, admin_nickname) do
487 update = %{:"is_#{permission_group}" => false}
489 users = nicknames |> Enum.map(&User.get_cached_by_nickname/1)
491 for u <- users, do: User.admin_api_update(u, update)
493 ModerationLog.insert_log(%{
497 permission: permission_group
502 _ -> render_error(conn, :forbidden, "You can't revoke your own admin/moderator status.")
506 def right_delete_multiple(conn, _) do
507 render_error(conn, :not_found, "No such permission_group")
511 %{assigns: %{user: admin}} = conn,
513 "permission_group" => permission_group,
514 "nickname" => nickname
517 when permission_group in ["moderator", "admin"] do
518 fields = %{:"is_#{permission_group}" => false}
522 |> User.get_cached_by_nickname()
523 |> User.admin_api_update(fields)
525 ModerationLog.insert_log(%{
529 permission: permission_group
535 def right_delete(%{assigns: %{user: %{nickname: nickname}}} = conn, %{"nickname" => nickname}) do
536 render_error(conn, :forbidden, "You can't revoke your own admin status.")
539 def relay_list(conn, _params) do
540 with {:ok, list} <- Relay.list() do
541 json(conn, %{relays: list})
549 def relay_follow(%{assigns: %{user: admin}} = conn, %{"relay_url" => target}) do
550 with {:ok, _message} <- Relay.follow(target) do
551 ModerationLog.insert_log(%{
552 action: "relay_follow",
566 def relay_unfollow(%{assigns: %{user: admin}} = conn, %{"relay_url" => target}) do
567 with {:ok, _message} <- Relay.unfollow(target) do
568 ModerationLog.insert_log(%{
569 action: "relay_unfollow",
583 @doc "Sends registration invite via email"
584 def email_invite(%{assigns: %{user: user}} = conn, %{"email" => email} = params) do
585 with {_, false} <- {:registrations_open, Config.get([:instance, :registrations_open])},
586 {_, true} <- {:invites_enabled, Config.get([:instance, :invites_enabled])},
587 {:ok, invite_token} <- UserInviteToken.create_invite(),
589 Pleroma.Emails.UserEmail.user_invitation_email(
595 {:ok, _} <- Pleroma.Emails.Mailer.deliver(email) do
596 json_response(conn, :no_content, "")
598 {:registrations_open, _} ->
601 {:error, "To send invites you need to set the `registrations_open` option to false."}
604 {:invites_enabled, _} ->
607 {:error, "To send invites you need to set the `invites_enabled` option to true."}
612 @doc "Create an account registration invite token"
613 def create_invite_token(conn, params) do
617 if params["max_use"],
618 do: Map.put(opts, :max_use, params["max_use"]),
622 if params["expires_at"],
623 do: Map.put(opts, :expires_at, params["expires_at"]),
626 {:ok, invite} = UserInviteToken.create_invite(opts)
628 json(conn, AccountView.render("invite.json", %{invite: invite}))
631 @doc "Get list of created invites"
632 def invites(conn, _params) do
633 invites = UserInviteToken.list_invites()
636 |> put_view(AccountView)
637 |> render("invites.json", %{invites: invites})
640 @doc "Revokes invite by token"
641 def revoke_invite(conn, %{"token" => token}) do
642 with {:ok, invite} <- UserInviteToken.find_by_token(token),
643 {:ok, updated_invite} = UserInviteToken.update_invite(invite, %{used: true}) do
645 |> put_view(AccountView)
646 |> render("invite.json", %{invite: updated_invite})
648 nil -> {:error, :not_found}
652 @doc "Get a password reset token (base64 string) for given nickname"
653 def get_password_reset(conn, %{"nickname" => nickname}) do
654 (%User{local: true} = user) = User.get_cached_by_nickname(nickname)
655 {:ok, token} = Pleroma.PasswordResetToken.create_token(user)
660 link: Router.Helpers.reset_password_url(Endpoint, :reset, token.token)
664 @doc "Force password reset for a given user"
665 def force_password_reset(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do
666 users = nicknames |> Enum.map(&User.get_cached_by_nickname/1)
668 Enum.each(users, &User.force_password_reset_async/1)
670 ModerationLog.insert_log(%{
673 action: "force_password_reset"
676 json_response(conn, :no_content, "")
679 @doc "Disable mfa for user's account."
680 def disable_mfa(conn, %{"nickname" => nickname}) do
681 case User.get_by_nickname(nickname) do
691 @doc "Show a given user's credentials"
692 def show_user_credentials(%{assigns: %{user: admin}} = conn, %{"nickname" => nickname}) do
693 with %User{} = user <- User.get_cached_by_nickname_or_id(nickname) do
695 |> put_view(AccountView)
696 |> render("credentials.json", %{user: user, for: admin})
698 _ -> {:error, :not_found}
702 @doc "Updates a given user"
703 def update_user_credentials(
704 %{assigns: %{user: admin}} = conn,
705 %{"nickname" => nickname} = params
707 with {_, user} <- {:user, User.get_cached_by_nickname(nickname)},
709 User.update_as_admin(user, params) do
710 ModerationLog.insert_log(%{
713 action: "updated_users"
716 if params["password"] do
717 User.force_password_reset_async(user)
720 ModerationLog.insert_log(%{
723 action: "force_password_reset"
726 json(conn, %{status: "success"})
728 {:error, changeset} ->
729 {_, {error, _}} = Enum.at(changeset.errors, 0)
730 json(conn, %{error: "New password #{error}."})
733 json(conn, %{error: "Unable to change password."})
737 def list_reports(conn, params) do
738 {page, page_size} = page_params(params)
740 reports = Utils.get_reports(params, page, page_size)
743 |> put_view(ReportView)
744 |> render("index.json", %{reports: reports})
747 def report_show(conn, %{"id" => id}) do
748 with %Activity{} = report <- Activity.get_by_id(id) do
750 |> put_view(ReportView)
751 |> render("show.json", Report.extract_report_info(report))
753 _ -> {:error, :not_found}
757 def reports_update(%{assigns: %{user: admin}} = conn, %{"reports" => reports}) do
760 |> Enum.map(fn report ->
761 with {:ok, activity} <- CommonAPI.update_report_state(report["id"], report["state"]) do
762 ModerationLog.insert_log(%{
763 action: "report_update",
770 {:error, message} -> %{id: report["id"], error: message}
774 case Enum.any?(result, &Map.has_key?(&1, :error)) do
775 true -> json_response(conn, :bad_request, result)
776 false -> json_response(conn, :no_content, "")
780 def report_notes_create(%{assigns: %{user: user}} = conn, %{
784 with {:ok, _} <- ReportNote.create(user.id, report_id, content) do
785 ModerationLog.insert_log(%{
786 action: "report_note",
788 subject: Activity.get_by_id(report_id),
792 json_response(conn, :no_content, "")
794 _ -> json_response(conn, :bad_request, "")
798 def report_notes_delete(%{assigns: %{user: user}} = conn, %{
800 "report_id" => report_id
802 with {:ok, note} <- ReportNote.destroy(note_id) do
803 ModerationLog.insert_log(%{
804 action: "report_note_delete",
806 subject: Activity.get_by_id(report_id),
810 json_response(conn, :no_content, "")
812 _ -> json_response(conn, :bad_request, "")
816 def list_statuses(%{assigns: %{user: _admin}} = conn, params) do
817 godmode = params["godmode"] == "true" || params["godmode"] == true
818 local_only = params["local_only"] == "true" || params["local_only"] == true
819 with_reblogs = params["with_reblogs"] == "true" || params["with_reblogs"] == true
820 {page, page_size} = page_params(params)
823 ActivityPub.fetch_statuses(nil, %{
824 "godmode" => godmode,
825 "local_only" => local_only,
826 "limit" => page_size,
827 "offset" => (page - 1) * page_size,
828 "exclude_reblogs" => !with_reblogs && "true"
832 |> put_view(Pleroma.Web.AdminAPI.StatusView)
833 |> render("index.json", %{activities: activities, as: :activity, skip_relationships: false})
836 def status_show(conn, %{"id" => id}) do
837 with %Activity{} = activity <- Activity.get_by_id(id) do
839 |> put_view(StatusView)
840 |> render("show.json", %{activity: activity})
842 _ -> errors(conn, {:error, :not_found})
846 def status_update(%{assigns: %{user: admin}} = conn, %{"id" => id} = params) do
849 |> Map.take(["sensitive", "visibility"])
850 |> Map.new(fn {key, value} -> {String.to_existing_atom(key), value} end)
852 with {:ok, activity} <- CommonAPI.update_activity_scope(id, params) do
853 {:ok, sensitive} = Ecto.Type.cast(:boolean, params[:sensitive])
855 ModerationLog.insert_log(%{
856 action: "status_update",
859 sensitive: sensitive,
860 visibility: params[:visibility]
864 |> put_view(StatusView)
865 |> render("show.json", %{activity: activity})
869 def status_delete(%{assigns: %{user: user}} = conn, %{"id" => id}) do
870 with {:ok, %Activity{}} <- CommonAPI.delete(id, user) do
871 ModerationLog.insert_log(%{
872 action: "status_delete",
881 def list_log(conn, params) do
882 {page, page_size} = page_params(params)
885 ModerationLog.get_all(%{
887 page_size: page_size,
888 start_date: params["start_date"],
889 end_date: params["end_date"],
890 user_id: params["user_id"],
891 search: params["search"]
895 |> put_view(ModerationLogView)
896 |> render("index.json", %{log: log})
899 def config_descriptions(conn, _params) do
900 descriptions = Enum.filter(@descriptions, &whitelisted_config?/1)
902 json(conn, descriptions)
905 def config_show(conn, %{"only_db" => true}) do
906 with :ok <- configurable_from_database(conn) do
907 configs = Pleroma.Repo.all(ConfigDB)
910 |> put_view(ConfigView)
911 |> render("index.json", %{configs: configs})
915 def config_show(conn, _params) do
916 with :ok <- configurable_from_database(conn) do
917 configs = ConfigDB.get_all_as_keyword()
920 Config.Holder.default_config()
921 |> ConfigDB.merge(configs)
922 |> Enum.map(fn {group, values} ->
923 Enum.map(values, fn {key, value} ->
925 if configs[group][key] do
926 ConfigDB.get_db_keys(configs[group][key], key)
929 db_value = configs[group][key]
932 if !is_nil(db_value) and Keyword.keyword?(db_value) and
933 ConfigDB.sub_key_full_update?(group, key, Keyword.keys(db_value)) do
934 ConfigDB.merge_group(group, key, value, db_value)
940 group: ConfigDB.convert(group),
941 key: ConfigDB.convert(key),
942 value: ConfigDB.convert(merged_value)
945 if db, do: Map.put(setting, :db, db), else: setting
950 json(conn, %{configs: merged, need_reboot: Restarter.Pleroma.need_reboot?()})
954 def config_update(conn, %{"configs" => configs}) do
955 with :ok <- configurable_from_database(conn) do
958 |> Enum.filter(&whitelisted_config?/1)
960 %{"group" => group, "key" => key, "delete" => true} = params ->
961 ConfigDB.delete(%{group: group, key: key, subkeys: params["subkeys"]})
963 %{"group" => group, "key" => key, "value" => value} ->
964 ConfigDB.update_or_create(%{group: group, key: key, value: value})
966 |> Enum.split_with(fn result -> elem(result, 0) == :error end)
970 |> Enum.map(fn {:ok, config} ->
971 Map.put(config, :db, ConfigDB.get_db_keys(config))
973 |> Enum.split_with(fn config ->
974 Ecto.get_meta(config, :state) == :deleted
977 Config.TransferTask.load_and_update_env(deleted, false)
979 if !Restarter.Pleroma.need_reboot?() do
980 changed_reboot_settings? =
982 |> Enum.any?(fn config ->
983 group = ConfigDB.from_string(config.group)
984 key = ConfigDB.from_string(config.key)
985 value = ConfigDB.from_binary(config.value)
986 Config.TransferTask.pleroma_need_restart?(group, key, value)
989 if changed_reboot_settings?, do: Restarter.Pleroma.need_reboot()
993 |> put_view(ConfigView)
994 |> render("index.json", %{configs: updated, need_reboot: Restarter.Pleroma.need_reboot?()})
998 def restart(conn, _params) do
999 with :ok <- configurable_from_database(conn) do
1000 Restarter.Pleroma.restart(Config.get(:env), 50)
1006 def need_reboot(conn, _params) do
1007 json(conn, %{need_reboot: Restarter.Pleroma.need_reboot?()})
1010 defp configurable_from_database(conn) do
1011 if Config.get(:configurable_from_database) do
1016 {:error, "To use this endpoint you need to enable configuration from database."}
1021 defp whitelisted_config?(group, key) do
1022 if whitelisted_configs = Config.get(:database_config_whitelist) do
1023 Enum.any?(whitelisted_configs, fn
1024 {whitelisted_group} ->
1025 group == inspect(whitelisted_group)
1027 {whitelisted_group, whitelisted_key} ->
1028 group == inspect(whitelisted_group) && key == inspect(whitelisted_key)
1035 defp whitelisted_config?(%{"group" => group, "key" => key}) do
1036 whitelisted_config?(group, key)
1039 defp whitelisted_config?(%{:group => group} = config) do
1040 whitelisted_config?(group, config[:key])
1043 def reload_emoji(conn, _params) do
1044 Pleroma.Emoji.reload()
1049 def confirm_email(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do
1050 users = nicknames |> Enum.map(&User.get_cached_by_nickname/1)
1052 User.toggle_confirmation(users)
1054 ModerationLog.insert_log(%{
1057 action: "confirm_email"
1063 def resend_confirmation_email(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do
1064 users = nicknames |> Enum.map(&User.get_cached_by_nickname/1)
1066 User.try_send_confirmation_email(users)
1068 ModerationLog.insert_log(%{
1071 action: "resend_confirmation_email"
1077 def oauth_app_create(conn, params) do
1079 if params["name"] do
1080 Map.put(params, "client_name", params["name"])
1086 case App.create(params) do
1088 AppView.render("show.json", %{app: app, admin: true})
1090 {:error, changeset} ->
1091 App.errors(changeset)
1097 def oauth_app_update(conn, params) do
1099 if params["name"] do
1100 Map.put(params, "client_name", params["name"])
1105 with {:ok, app} <- App.update(params) do
1106 json(conn, AppView.render("show.json", %{app: app, admin: true}))
1108 {:error, changeset} ->
1109 json(conn, App.errors(changeset))
1112 json_response(conn, :bad_request, "")
1116 def oauth_app_list(conn, params) do
1117 {page, page_size} = page_params(params)
1120 client_name: params["name"],
1121 client_id: params["client_id"],
1123 page_size: page_size
1127 if Map.has_key?(params, "trusted") do
1128 Map.put(search_params, :trusted, params["trusted"])
1133 with {:ok, apps, count} <- App.search(search_params) do
1136 AppView.render("index.json",
1139 page_size: page_size,
1146 def oauth_app_delete(conn, params) do
1147 with {:ok, _app} <- App.destroy(params["id"]) do
1148 json_response(conn, :no_content, "")
1150 _ -> json_response(conn, :bad_request, "")
1154 def stats(conn, _) do
1155 count = Stats.get_status_visibility_count()
1158 |> json(%{"status_visibility" => count})
1161 defp errors(conn, {:error, :not_found}) do
1163 |> put_status(:not_found)
1164 |> json(dgettext("errors", "Not found"))
1167 defp errors(conn, {:error, reason}) do
1169 |> put_status(:bad_request)
1173 defp errors(conn, {:param_cast, _}) do
1175 |> put_status(:bad_request)
1176 |> json(dgettext("errors", "Invalid parameters"))
1179 defp errors(conn, _) do
1181 |> put_status(:internal_server_error)
1182 |> json(dgettext("errors", "Something went wrong"))
1185 defp page_params(params) do
1186 {get_page(params["page"]), get_page_size(params["page_size"])}
1189 defp get_page(page_string) when is_nil(page_string), do: 1
1191 defp get_page(page_string) do
1192 case Integer.parse(page_string) do
1198 defp get_page_size(page_size_string) when is_nil(page_size_string), do: @users_page_size
1200 defp get_page_size(page_size_string) do
1201 case Integer.parse(page_size_string) do
1202 {page_size, _} -> page_size
1203 :error -> @users_page_size