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
847 with {:ok, activity} <- CommonAPI.update_activity_scope(id, params) do
848 {:ok, sensitive} = Ecto.Type.cast(:boolean, params["sensitive"])
850 ModerationLog.insert_log(%{
851 action: "status_update",
854 sensitive: sensitive,
855 visibility: params["visibility"]
859 |> put_view(StatusView)
860 |> render("show.json", %{activity: activity})
864 def status_delete(%{assigns: %{user: user}} = conn, %{"id" => id}) do
865 with {:ok, %Activity{}} <- CommonAPI.delete(id, user) do
866 ModerationLog.insert_log(%{
867 action: "status_delete",
876 def list_log(conn, params) do
877 {page, page_size} = page_params(params)
880 ModerationLog.get_all(%{
882 page_size: page_size,
883 start_date: params["start_date"],
884 end_date: params["end_date"],
885 user_id: params["user_id"],
886 search: params["search"]
890 |> put_view(ModerationLogView)
891 |> render("index.json", %{log: log})
894 def config_descriptions(conn, _params) do
895 descriptions = Enum.filter(@descriptions, &whitelisted_config?/1)
897 json(conn, descriptions)
900 def config_show(conn, %{"only_db" => true}) do
901 with :ok <- configurable_from_database(conn) do
902 configs = Pleroma.Repo.all(ConfigDB)
905 |> put_view(ConfigView)
906 |> render("index.json", %{configs: configs})
910 def config_show(conn, _params) do
911 with :ok <- configurable_from_database(conn) do
912 configs = ConfigDB.get_all_as_keyword()
915 Config.Holder.default_config()
916 |> ConfigDB.merge(configs)
917 |> Enum.map(fn {group, values} ->
918 Enum.map(values, fn {key, value} ->
920 if configs[group][key] do
921 ConfigDB.get_db_keys(configs[group][key], key)
924 db_value = configs[group][key]
927 if !is_nil(db_value) and Keyword.keyword?(db_value) and
928 ConfigDB.sub_key_full_update?(group, key, Keyword.keys(db_value)) do
929 ConfigDB.merge_group(group, key, value, db_value)
935 group: ConfigDB.convert(group),
936 key: ConfigDB.convert(key),
937 value: ConfigDB.convert(merged_value)
940 if db, do: Map.put(setting, :db, db), else: setting
945 json(conn, %{configs: merged, need_reboot: Restarter.Pleroma.need_reboot?()})
949 def config_update(conn, %{"configs" => configs}) do
950 with :ok <- configurable_from_database(conn) do
953 |> Enum.filter(&whitelisted_config?/1)
955 %{"group" => group, "key" => key, "delete" => true} = params ->
956 ConfigDB.delete(%{group: group, key: key, subkeys: params["subkeys"]})
958 %{"group" => group, "key" => key, "value" => value} ->
959 ConfigDB.update_or_create(%{group: group, key: key, value: value})
961 |> Enum.split_with(fn result -> elem(result, 0) == :error end)
965 |> Enum.map(fn {:ok, config} ->
966 Map.put(config, :db, ConfigDB.get_db_keys(config))
968 |> Enum.split_with(fn config ->
969 Ecto.get_meta(config, :state) == :deleted
972 Config.TransferTask.load_and_update_env(deleted, false)
974 if !Restarter.Pleroma.need_reboot?() do
975 changed_reboot_settings? =
977 |> Enum.any?(fn config ->
978 group = ConfigDB.from_string(config.group)
979 key = ConfigDB.from_string(config.key)
980 value = ConfigDB.from_binary(config.value)
981 Config.TransferTask.pleroma_need_restart?(group, key, value)
984 if changed_reboot_settings?, do: Restarter.Pleroma.need_reboot()
988 |> put_view(ConfigView)
989 |> render("index.json", %{configs: updated, need_reboot: Restarter.Pleroma.need_reboot?()})
993 def restart(conn, _params) do
994 with :ok <- configurable_from_database(conn) do
995 Restarter.Pleroma.restart(Config.get(:env), 50)
1001 def need_reboot(conn, _params) do
1002 json(conn, %{need_reboot: Restarter.Pleroma.need_reboot?()})
1005 defp configurable_from_database(conn) do
1006 if Config.get(:configurable_from_database) do
1011 {:error, "To use this endpoint you need to enable configuration from database."}
1016 defp whitelisted_config?(group, key) do
1017 if whitelisted_configs = Config.get(:database_config_whitelist) do
1018 Enum.any?(whitelisted_configs, fn
1019 {whitelisted_group} ->
1020 group == inspect(whitelisted_group)
1022 {whitelisted_group, whitelisted_key} ->
1023 group == inspect(whitelisted_group) && key == inspect(whitelisted_key)
1030 defp whitelisted_config?(%{"group" => group, "key" => key}) do
1031 whitelisted_config?(group, key)
1034 defp whitelisted_config?(%{:group => group} = config) do
1035 whitelisted_config?(group, config[:key])
1038 def reload_emoji(conn, _params) do
1039 Pleroma.Emoji.reload()
1044 def confirm_email(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do
1045 users = nicknames |> Enum.map(&User.get_cached_by_nickname/1)
1047 User.toggle_confirmation(users)
1049 ModerationLog.insert_log(%{
1052 action: "confirm_email"
1058 def resend_confirmation_email(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do
1059 users = nicknames |> Enum.map(&User.get_cached_by_nickname/1)
1061 User.try_send_confirmation_email(users)
1063 ModerationLog.insert_log(%{
1066 action: "resend_confirmation_email"
1072 def oauth_app_create(conn, params) do
1074 if params["name"] do
1075 Map.put(params, "client_name", params["name"])
1081 case App.create(params) do
1083 AppView.render("show.json", %{app: app, admin: true})
1085 {:error, changeset} ->
1086 App.errors(changeset)
1092 def oauth_app_update(conn, params) do
1094 if params["name"] do
1095 Map.put(params, "client_name", params["name"])
1100 with {:ok, app} <- App.update(params) do
1101 json(conn, AppView.render("show.json", %{app: app, admin: true}))
1103 {:error, changeset} ->
1104 json(conn, App.errors(changeset))
1107 json_response(conn, :bad_request, "")
1111 def oauth_app_list(conn, params) do
1112 {page, page_size} = page_params(params)
1115 client_name: params["name"],
1116 client_id: params["client_id"],
1118 page_size: page_size
1122 if Map.has_key?(params, "trusted") do
1123 Map.put(search_params, :trusted, params["trusted"])
1128 with {:ok, apps, count} <- App.search(search_params) do
1131 AppView.render("index.json",
1134 page_size: page_size,
1141 def oauth_app_delete(conn, params) do
1142 with {:ok, _app} <- App.destroy(params["id"]) do
1143 json_response(conn, :no_content, "")
1145 _ -> json_response(conn, :bad_request, "")
1149 def stats(conn, _) do
1150 count = Stats.get_status_visibility_count()
1153 |> json(%{"status_visibility" => count})
1156 defp errors(conn, {:error, :not_found}) do
1158 |> put_status(:not_found)
1159 |> json(dgettext("errors", "Not found"))
1162 defp errors(conn, {:error, reason}) do
1164 |> put_status(:bad_request)
1168 defp errors(conn, {:param_cast, _}) do
1170 |> put_status(:bad_request)
1171 |> json(dgettext("errors", "Invalid parameters"))
1174 defp errors(conn, _) do
1176 |> put_status(:internal_server_error)
1177 |> json(dgettext("errors", "Something went wrong"))
1180 defp page_params(params) do
1181 {get_page(params["page"]), get_page_size(params["page_size"])}
1184 defp get_page(page_string) when is_nil(page_string), do: 1
1186 defp get_page(page_string) do
1187 case Integer.parse(page_string) do
1193 defp get_page_size(page_size_string) when is_nil(page_size_string), do: @users_page_size
1195 defp get_page_size(page_size_string) do
1196 case Integer.parse(page_size_string) do
1197 {page_size, _} -> page_size
1198 :error -> @users_page_size