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
13 alias Pleroma.ModerationLog
14 alias Pleroma.Plugs.OAuthScopesPlug
15 alias Pleroma.ReportNote
18 alias Pleroma.UserInviteToken
19 alias Pleroma.Web.ActivityPub.ActivityPub
20 alias Pleroma.Web.ActivityPub.Builder
21 alias Pleroma.Web.ActivityPub.Pipeline
22 alias Pleroma.Web.ActivityPub.Relay
23 alias Pleroma.Web.ActivityPub.Utils
24 alias Pleroma.Web.AdminAPI.AccountView
25 alias Pleroma.Web.AdminAPI.ConfigView
26 alias Pleroma.Web.AdminAPI.ModerationLogView
27 alias Pleroma.Web.AdminAPI.Report
28 alias Pleroma.Web.AdminAPI.ReportView
29 alias Pleroma.Web.AdminAPI.Search
30 alias Pleroma.Web.CommonAPI
31 alias Pleroma.Web.Endpoint
32 alias Pleroma.Web.MastodonAPI.AppView
33 alias Pleroma.Web.MastodonAPI.StatusView
34 alias Pleroma.Web.OAuth.App
35 alias Pleroma.Web.Router
39 @descriptions_json Pleroma.Docs.JSON.compile()
44 %{scopes: ["read:accounts"], admin: true}
45 when action in [:list_users, :user_show, :right_get, :show_user_credentials]
50 %{scopes: ["write:accounts"], admin: true}
53 :force_password_reset,
56 :user_toggle_activation,
64 :right_delete_multiple,
65 :update_user_credentials
69 plug(OAuthScopesPlug, %{scopes: ["read:invites"], admin: true} when action == :invites)
73 %{scopes: ["write:invites"], admin: true}
74 when action in [:create_invite_token, :revoke_invite, :email_invite]
79 %{scopes: ["write:follows"], admin: true}
80 when action in [:user_follow, :user_unfollow, :relay_follow, :relay_unfollow]
85 %{scopes: ["read:reports"], admin: true}
86 when action in [:list_reports, :report_show]
91 %{scopes: ["write:reports"], admin: true}
92 when action in [:reports_update, :report_notes_create, :report_notes_delete]
97 %{scopes: ["read:statuses"], admin: true}
98 when action in [:list_statuses, :list_user_statuses, :list_instance_statuses]
103 %{scopes: ["write:statuses"], admin: true}
104 when action in [:status_update, :status_delete]
109 %{scopes: ["read"], admin: true}
115 :config_descriptions,
122 %{scopes: ["write"], admin: true}
126 :resend_confirmation_email,
136 action_fallback(:errors)
138 def user_delete(conn, %{"nickname" => nickname}) do
139 user_delete(conn, %{"nicknames" => [nickname]})
142 def user_delete(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do
145 |> Enum.map(&User.get_cached_by_nickname/1)
148 |> Enum.each(fn user ->
149 {:ok, delete_data, _} = Builder.delete(admin, user.ap_id)
150 Pipeline.common_pipeline(delete_data, local: true)
153 ModerationLog.insert_log(%{
163 def user_follow(%{assigns: %{user: admin}} = conn, %{
164 "follower" => follower_nick,
165 "followed" => followed_nick
167 with %User{} = follower <- User.get_cached_by_nickname(follower_nick),
168 %User{} = followed <- User.get_cached_by_nickname(followed_nick) do
169 User.follow(follower, followed)
171 ModerationLog.insert_log(%{
183 def user_unfollow(%{assigns: %{user: admin}} = conn, %{
184 "follower" => follower_nick,
185 "followed" => followed_nick
187 with %User{} = follower <- User.get_cached_by_nickname(follower_nick),
188 %User{} = followed <- User.get_cached_by_nickname(followed_nick) do
189 User.unfollow(follower, followed)
191 ModerationLog.insert_log(%{
203 def users_create(%{assigns: %{user: admin}} = conn, %{"users" => users}) do
205 Enum.map(users, fn %{"nickname" => nickname, "email" => email, "password" => password} ->
211 password_confirmation: password,
215 User.register_changeset(%User{}, user_data, need_confirmation: false)
217 |> Enum.reduce(Ecto.Multi.new(), fn changeset, multi ->
218 Ecto.Multi.insert(multi, Ecto.UUID.generate(), changeset)
221 case Pleroma.Repo.transaction(changesets) do
226 |> Enum.map(fn user ->
227 {:ok, user} = User.post_register_action(user)
231 |> Enum.map(&AccountView.render("created.json", %{user: &1}))
233 ModerationLog.insert_log(%{
235 subjects: Map.values(users),
242 {:error, id, changeset, _} ->
244 Enum.map(changesets.operations, fn
245 {current_id, {:changeset, _current_changeset, _}} when current_id == id ->
246 AccountView.render("create-error.json", %{changeset: changeset})
248 {_, {:changeset, current_changeset, _}} ->
249 AccountView.render("create-error.json", %{changeset: current_changeset})
253 |> put_status(:conflict)
258 def user_show(conn, %{"nickname" => nickname}) do
259 with %User{} = user <- User.get_cached_by_nickname_or_id(nickname) do
261 |> put_view(AccountView)
262 |> render("show.json", %{user: user})
264 _ -> {:error, :not_found}
268 def list_instance_statuses(conn, %{"instance" => instance} = params) do
269 with_reblogs = params["with_reblogs"] == "true" || params["with_reblogs"] == true
270 {page, page_size} = page_params(params)
273 ActivityPub.fetch_statuses(nil, %{
274 "instance" => instance,
275 "limit" => page_size,
276 "offset" => (page - 1) * page_size,
277 "exclude_reblogs" => !with_reblogs && "true"
281 |> put_view(Pleroma.Web.AdminAPI.StatusView)
282 |> render("index.json", %{activities: activities, as: :activity, skip_relationships: false})
285 def list_user_statuses(conn, %{"nickname" => nickname} = params) do
286 with_reblogs = params["with_reblogs"] == "true" || params["with_reblogs"] == true
287 godmode = params["godmode"] == "true" || params["godmode"] == true
289 with %User{} = user <- User.get_cached_by_nickname_or_id(nickname) do
290 {_, page_size} = page_params(params)
293 ActivityPub.fetch_user_activities(user, nil, %{
294 "limit" => page_size,
295 "godmode" => godmode,
296 "exclude_reblogs" => !with_reblogs && "true"
300 |> put_view(StatusView)
301 |> render("index.json", %{activities: activities, as: :activity, skip_relationships: false})
303 _ -> {:error, :not_found}
307 def user_toggle_activation(%{assigns: %{user: admin}} = conn, %{"nickname" => nickname}) do
308 user = User.get_cached_by_nickname(nickname)
310 {:ok, updated_user} = User.deactivate(user, !user.deactivated)
312 action = if user.deactivated, do: "activate", else: "deactivate"
314 ModerationLog.insert_log(%{
321 |> put_view(AccountView)
322 |> render("show.json", %{user: updated_user})
325 def user_activate(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do
326 users = Enum.map(nicknames, &User.get_cached_by_nickname/1)
327 {:ok, updated_users} = User.deactivate(users, false)
329 ModerationLog.insert_log(%{
336 |> put_view(AccountView)
337 |> render("index.json", %{users: Keyword.values(updated_users)})
340 def user_deactivate(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do
341 users = Enum.map(nicknames, &User.get_cached_by_nickname/1)
342 {:ok, updated_users} = User.deactivate(users, true)
344 ModerationLog.insert_log(%{
351 |> put_view(AccountView)
352 |> render("index.json", %{users: Keyword.values(updated_users)})
355 def tag_users(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames, "tags" => tags}) do
356 with {:ok, _} <- User.tag(nicknames, tags) do
357 ModerationLog.insert_log(%{
359 nicknames: nicknames,
364 json_response(conn, :no_content, "")
368 def untag_users(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames, "tags" => tags}) do
369 with {:ok, _} <- User.untag(nicknames, tags) do
370 ModerationLog.insert_log(%{
372 nicknames: nicknames,
377 json_response(conn, :no_content, "")
381 def list_users(conn, params) do
382 {page, page_size} = page_params(params)
383 filters = maybe_parse_filters(params["filters"])
386 query: params["query"],
388 page_size: page_size,
389 tags: params["tags"],
390 name: params["name"],
391 email: params["email"]
394 with {:ok, users, count} <- Search.user(Map.merge(search_params, filters)),
395 {:ok, users, count} <- filter_service_users(users, count),
399 AccountView.render("index.json",
407 defp filter_service_users(users, count) do
408 filtered_users = Enum.reject(users, &service_user?/1)
409 count = if Enum.any?(users, &service_user?/1), do: length(filtered_users), else: count
411 {:ok, filtered_users, count}
414 defp service_user?(user) do
415 String.match?(user.ap_id, ~r/.*\/relay$/) or
416 String.match?(user.ap_id, ~r/.*\/internal\/fetch$/)
419 @filters ~w(local external active deactivated is_admin is_moderator)
421 @spec maybe_parse_filters(String.t()) :: %{required(String.t()) => true} | %{}
422 defp maybe_parse_filters(filters) when is_nil(filters) or filters == "", do: %{}
424 defp maybe_parse_filters(filters) do
427 |> Enum.filter(&Enum.member?(@filters, &1))
428 |> Enum.map(&String.to_atom(&1))
429 |> Enum.into(%{}, &{&1, true})
432 def right_add_multiple(%{assigns: %{user: admin}} = conn, %{
433 "permission_group" => permission_group,
434 "nicknames" => nicknames
436 when permission_group in ["moderator", "admin"] do
437 update = %{:"is_#{permission_group}" => true}
439 users = nicknames |> Enum.map(&User.get_cached_by_nickname/1)
441 for u <- users, do: User.admin_api_update(u, update)
443 ModerationLog.insert_log(%{
447 permission: permission_group
453 def right_add_multiple(conn, _) do
454 render_error(conn, :not_found, "No such permission_group")
457 def right_add(%{assigns: %{user: admin}} = conn, %{
458 "permission_group" => permission_group,
459 "nickname" => nickname
461 when permission_group in ["moderator", "admin"] do
462 fields = %{:"is_#{permission_group}" => true}
466 |> User.get_cached_by_nickname()
467 |> User.admin_api_update(fields)
469 ModerationLog.insert_log(%{
473 permission: permission_group
479 def right_add(conn, _) do
480 render_error(conn, :not_found, "No such permission_group")
483 def right_get(conn, %{"nickname" => nickname}) do
484 user = User.get_cached_by_nickname(nickname)
488 is_moderator: user.is_moderator,
489 is_admin: user.is_admin
493 def right_delete_multiple(
494 %{assigns: %{user: %{nickname: admin_nickname} = admin}} = conn,
496 "permission_group" => permission_group,
497 "nicknames" => nicknames
500 when permission_group in ["moderator", "admin"] do
501 with false <- Enum.member?(nicknames, admin_nickname) do
502 update = %{:"is_#{permission_group}" => false}
504 users = nicknames |> Enum.map(&User.get_cached_by_nickname/1)
506 for u <- users, do: User.admin_api_update(u, update)
508 ModerationLog.insert_log(%{
512 permission: permission_group
517 _ -> render_error(conn, :forbidden, "You can't revoke your own admin/moderator status.")
521 def right_delete_multiple(conn, _) do
522 render_error(conn, :not_found, "No such permission_group")
526 %{assigns: %{user: admin}} = conn,
528 "permission_group" => permission_group,
529 "nickname" => nickname
532 when permission_group in ["moderator", "admin"] do
533 fields = %{:"is_#{permission_group}" => false}
537 |> User.get_cached_by_nickname()
538 |> User.admin_api_update(fields)
540 ModerationLog.insert_log(%{
544 permission: permission_group
550 def right_delete(%{assigns: %{user: %{nickname: nickname}}} = conn, %{"nickname" => nickname}) do
551 render_error(conn, :forbidden, "You can't revoke your own admin status.")
554 def relay_list(conn, _params) do
555 with {:ok, list} <- Relay.list() do
556 json(conn, %{relays: list})
564 def relay_follow(%{assigns: %{user: admin}} = conn, %{"relay_url" => target}) do
565 with {:ok, _message} <- Relay.follow(target) do
566 ModerationLog.insert_log(%{
567 action: "relay_follow",
581 def relay_unfollow(%{assigns: %{user: admin}} = conn, %{"relay_url" => target}) do
582 with {:ok, _message} <- Relay.unfollow(target) do
583 ModerationLog.insert_log(%{
584 action: "relay_unfollow",
598 @doc "Sends registration invite via email"
599 def email_invite(%{assigns: %{user: user}} = conn, %{"email" => email} = params) do
600 with {_, false} <- {:registrations_open, Config.get([:instance, :registrations_open])},
601 {_, true} <- {:invites_enabled, Config.get([:instance, :invites_enabled])},
602 {:ok, invite_token} <- UserInviteToken.create_invite(),
604 Pleroma.Emails.UserEmail.user_invitation_email(
610 {:ok, _} <- Pleroma.Emails.Mailer.deliver(email) do
611 json_response(conn, :no_content, "")
613 {:registrations_open, _} ->
616 {:error, "To send invites you need to set the `registrations_open` option to false."}
619 {:invites_enabled, _} ->
622 {:error, "To send invites you need to set the `invites_enabled` option to true."}
627 @doc "Create an account registration invite token"
628 def create_invite_token(conn, params) do
632 if params["max_use"],
633 do: Map.put(opts, :max_use, params["max_use"]),
637 if params["expires_at"],
638 do: Map.put(opts, :expires_at, params["expires_at"]),
641 {:ok, invite} = UserInviteToken.create_invite(opts)
643 json(conn, AccountView.render("invite.json", %{invite: invite}))
646 @doc "Get list of created invites"
647 def invites(conn, _params) do
648 invites = UserInviteToken.list_invites()
651 |> put_view(AccountView)
652 |> render("invites.json", %{invites: invites})
655 @doc "Revokes invite by token"
656 def revoke_invite(conn, %{"token" => token}) do
657 with {:ok, invite} <- UserInviteToken.find_by_token(token),
658 {:ok, updated_invite} = UserInviteToken.update_invite(invite, %{used: true}) do
660 |> put_view(AccountView)
661 |> render("invite.json", %{invite: updated_invite})
663 nil -> {:error, :not_found}
667 @doc "Get a password reset token (base64 string) for given nickname"
668 def get_password_reset(conn, %{"nickname" => nickname}) do
669 (%User{local: true} = user) = User.get_cached_by_nickname(nickname)
670 {:ok, token} = Pleroma.PasswordResetToken.create_token(user)
675 link: Router.Helpers.reset_password_url(Endpoint, :reset, token.token)
679 @doc "Force password reset for a given user"
680 def force_password_reset(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do
681 users = nicknames |> Enum.map(&User.get_cached_by_nickname/1)
683 Enum.each(users, &User.force_password_reset_async/1)
685 ModerationLog.insert_log(%{
688 action: "force_password_reset"
691 json_response(conn, :no_content, "")
694 @doc "Show a given user's credentials"
695 def show_user_credentials(%{assigns: %{user: admin}} = conn, %{"nickname" => nickname}) do
696 with %User{} = user <- User.get_cached_by_nickname_or_id(nickname) do
698 |> put_view(AccountView)
699 |> render("credentials.json", %{user: user, for: admin})
701 _ -> {:error, :not_found}
705 @doc "Updates a given user"
706 def update_user_credentials(
707 %{assigns: %{user: admin}} = conn,
708 %{"nickname" => nickname} = params
710 with {_, user} <- {:user, User.get_cached_by_nickname(nickname)},
712 User.update_as_admin(user, params) do
713 ModerationLog.insert_log(%{
716 action: "updated_users"
719 if params["password"] do
720 User.force_password_reset_async(user)
723 ModerationLog.insert_log(%{
726 action: "force_password_reset"
729 json(conn, %{status: "success"})
731 {:error, changeset} ->
732 {_, {error, _}} = Enum.at(changeset.errors, 0)
733 json(conn, %{error: "New password #{error}."})
736 json(conn, %{error: "Unable to change password."})
740 def list_reports(conn, params) do
741 {page, page_size} = page_params(params)
743 reports = Utils.get_reports(params, page, page_size)
746 |> put_view(ReportView)
747 |> render("index.json", %{reports: reports})
750 def report_show(conn, %{"id" => id}) do
751 with %Activity{} = report <- Activity.get_by_id(id) do
753 |> put_view(ReportView)
754 |> render("show.json", Report.extract_report_info(report))
756 _ -> {:error, :not_found}
760 def reports_update(%{assigns: %{user: admin}} = conn, %{"reports" => reports}) do
763 |> Enum.map(fn report ->
764 with {:ok, activity} <- CommonAPI.update_report_state(report["id"], report["state"]) do
765 ModerationLog.insert_log(%{
766 action: "report_update",
773 {:error, message} -> %{id: report["id"], error: message}
777 case Enum.any?(result, &Map.has_key?(&1, :error)) do
778 true -> json_response(conn, :bad_request, result)
779 false -> json_response(conn, :no_content, "")
783 def report_notes_create(%{assigns: %{user: user}} = conn, %{
787 with {:ok, _} <- ReportNote.create(user.id, report_id, content) do
788 ModerationLog.insert_log(%{
789 action: "report_note",
791 subject: Activity.get_by_id(report_id),
795 json_response(conn, :no_content, "")
797 _ -> json_response(conn, :bad_request, "")
801 def report_notes_delete(%{assigns: %{user: user}} = conn, %{
803 "report_id" => report_id
805 with {:ok, note} <- ReportNote.destroy(note_id) do
806 ModerationLog.insert_log(%{
807 action: "report_note_delete",
809 subject: Activity.get_by_id(report_id),
813 json_response(conn, :no_content, "")
815 _ -> json_response(conn, :bad_request, "")
819 def list_statuses(%{assigns: %{user: _admin}} = conn, params) do
820 godmode = params["godmode"] == "true" || params["godmode"] == true
821 local_only = params["local_only"] == "true" || params["local_only"] == true
822 with_reblogs = params["with_reblogs"] == "true" || params["with_reblogs"] == true
823 {page, page_size} = page_params(params)
826 ActivityPub.fetch_statuses(nil, %{
827 "godmode" => godmode,
828 "local_only" => local_only,
829 "limit" => page_size,
830 "offset" => (page - 1) * page_size,
831 "exclude_reblogs" => !with_reblogs && "true"
835 |> put_view(Pleroma.Web.AdminAPI.StatusView)
836 |> render("index.json", %{activities: activities, as: :activity, skip_relationships: false})
839 def status_update(%{assigns: %{user: admin}} = conn, %{"id" => id} = params) do
840 with {:ok, activity} <- CommonAPI.update_activity_scope(id, params) do
841 {:ok, sensitive} = Ecto.Type.cast(:boolean, params["sensitive"])
843 ModerationLog.insert_log(%{
844 action: "status_update",
847 sensitive: sensitive,
848 visibility: params["visibility"]
852 |> put_view(StatusView)
853 |> render("show.json", %{activity: activity})
857 def status_delete(%{assigns: %{user: user}} = conn, %{"id" => id}) do
858 with {:ok, %Activity{}} <- CommonAPI.delete(id, user) do
859 ModerationLog.insert_log(%{
860 action: "status_delete",
869 def list_log(conn, params) do
870 {page, page_size} = page_params(params)
873 ModerationLog.get_all(%{
875 page_size: page_size,
876 start_date: params["start_date"],
877 end_date: params["end_date"],
878 user_id: params["user_id"],
879 search: params["search"]
883 |> put_view(ModerationLogView)
884 |> render("index.json", %{log: log})
887 def config_descriptions(conn, _params) do
889 |> Plug.Conn.put_resp_content_type("application/json")
890 |> Plug.Conn.send_resp(200, @descriptions_json)
893 def config_show(conn, %{"only_db" => true}) do
894 with :ok <- configurable_from_database(conn) do
895 configs = Pleroma.Repo.all(ConfigDB)
898 |> put_view(ConfigView)
899 |> render("index.json", %{configs: configs})
903 def config_show(conn, _params) do
904 with :ok <- configurable_from_database(conn) do
905 configs = ConfigDB.get_all_as_keyword()
908 Config.Holder.default_config()
909 |> ConfigDB.merge(configs)
910 |> Enum.map(fn {group, values} ->
911 Enum.map(values, fn {key, value} ->
913 if configs[group][key] do
914 ConfigDB.get_db_keys(configs[group][key], key)
917 db_value = configs[group][key]
920 if !is_nil(db_value) and Keyword.keyword?(db_value) and
921 ConfigDB.sub_key_full_update?(group, key, Keyword.keys(db_value)) do
922 ConfigDB.merge_group(group, key, value, db_value)
928 group: ConfigDB.convert(group),
929 key: ConfigDB.convert(key),
930 value: ConfigDB.convert(merged_value)
933 if db, do: Map.put(setting, :db, db), else: setting
938 json(conn, %{configs: merged, need_reboot: Restarter.Pleroma.need_reboot?()})
942 def config_update(conn, %{"configs" => configs}) do
943 with :ok <- configurable_from_database(conn) do
946 %{"group" => group, "key" => key, "delete" => true} = params ->
947 ConfigDB.delete(%{group: group, key: key, subkeys: params["subkeys"]})
949 %{"group" => group, "key" => key, "value" => value} ->
950 ConfigDB.update_or_create(%{group: group, key: key, value: value})
952 |> Enum.split_with(fn result -> elem(result, 0) == :error end)
956 |> Enum.map(fn {:ok, config} ->
957 Map.put(config, :db, ConfigDB.get_db_keys(config))
959 |> Enum.split_with(fn config ->
960 Ecto.get_meta(config, :state) == :deleted
963 Config.TransferTask.load_and_update_env(deleted, false)
965 if !Restarter.Pleroma.need_reboot?() do
966 changed_reboot_settings? =
968 |> Enum.any?(fn config ->
969 group = ConfigDB.from_string(config.group)
970 key = ConfigDB.from_string(config.key)
971 value = ConfigDB.from_binary(config.value)
972 Config.TransferTask.pleroma_need_restart?(group, key, value)
975 if changed_reboot_settings?, do: Restarter.Pleroma.need_reboot()
979 |> put_view(ConfigView)
980 |> render("index.json", %{configs: updated, need_reboot: Restarter.Pleroma.need_reboot?()})
984 def restart(conn, _params) do
985 with :ok <- configurable_from_database(conn) do
986 Restarter.Pleroma.restart(Config.get(:env), 50)
992 def need_reboot(conn, _params) do
993 json(conn, %{need_reboot: Restarter.Pleroma.need_reboot?()})
996 defp configurable_from_database(conn) do
997 if Config.get(:configurable_from_database) do
1002 {:error, "To use this endpoint you need to enable configuration from database."}
1007 def reload_emoji(conn, _params) do
1008 Pleroma.Emoji.reload()
1013 def confirm_email(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do
1014 users = nicknames |> Enum.map(&User.get_cached_by_nickname/1)
1016 User.toggle_confirmation(users)
1018 ModerationLog.insert_log(%{
1021 action: "confirm_email"
1027 def resend_confirmation_email(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do
1028 users = nicknames |> Enum.map(&User.get_cached_by_nickname/1)
1030 User.try_send_confirmation_email(users)
1032 ModerationLog.insert_log(%{
1035 action: "resend_confirmation_email"
1041 def oauth_app_create(conn, params) do
1043 if params["name"] do
1044 Map.put(params, "client_name", params["name"])
1050 case App.create(params) do
1052 AppView.render("show.json", %{app: app, admin: true})
1054 {:error, changeset} ->
1055 App.errors(changeset)
1061 def oauth_app_update(conn, params) do
1063 if params["name"] do
1064 Map.put(params, "client_name", params["name"])
1069 with {:ok, app} <- App.update(params) do
1070 json(conn, AppView.render("show.json", %{app: app, admin: true}))
1072 {:error, changeset} ->
1073 json(conn, App.errors(changeset))
1076 json_response(conn, :bad_request, "")
1080 def oauth_app_list(conn, params) do
1081 {page, page_size} = page_params(params)
1084 client_name: params["name"],
1085 client_id: params["client_id"],
1087 page_size: page_size
1091 if Map.has_key?(params, "trusted") do
1092 Map.put(search_params, :trusted, params["trusted"])
1097 with {:ok, apps, count} <- App.search(search_params) do
1100 AppView.render("index.json",
1103 page_size: page_size,
1110 def oauth_app_delete(conn, params) do
1111 with {:ok, _app} <- App.destroy(params["id"]) do
1112 json_response(conn, :no_content, "")
1114 _ -> json_response(conn, :bad_request, "")
1118 def stats(conn, _) do
1119 count = Stats.get_status_visibility_count()
1122 |> json(%{"status_visibility" => count})
1125 defp errors(conn, {:error, :not_found}) do
1127 |> put_status(:not_found)
1128 |> json(dgettext("errors", "Not found"))
1131 defp errors(conn, {:error, reason}) do
1133 |> put_status(:bad_request)
1137 defp errors(conn, {:param_cast, _}) do
1139 |> put_status(:bad_request)
1140 |> json(dgettext("errors", "Invalid parameters"))
1143 defp errors(conn, _) do
1145 |> put_status(:internal_server_error)
1146 |> json(dgettext("errors", "Something went wrong"))
1149 defp page_params(params) do
1150 {get_page(params["page"]), get_page_size(params["page_size"])}
1153 defp get_page(page_string) when is_nil(page_string), do: 1
1155 defp get_page(page_string) do
1156 case Integer.parse(page_string) do
1162 defp get_page_size(page_size_string) when is_nil(page_size_string), do: @users_page_size
1164 defp get_page_size(page_size_string) do
1165 case Integer.parse(page_size_string) do
1166 {page_size, _} -> page_size
1167 :error -> @users_page_size