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_json 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
896 |> Plug.Conn.put_resp_content_type("application/json")
897 |> Plug.Conn.send_resp(200, @descriptions_json)
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
952 Enum.filter(configs, &whitelisted_config?/1)
954 %{"group" => group, "key" => key, "delete" => true} = params ->
955 ConfigDB.delete(%{group: group, key: key, subkeys: params["subkeys"]})
957 %{"group" => group, "key" => key, "value" => value} ->
958 ConfigDB.update_or_create(%{group: group, key: key, value: value})
960 |> Enum.split_with(fn result -> elem(result, 0) == :error end)
964 |> Enum.map(fn {:ok, config} ->
965 Map.put(config, :db, ConfigDB.get_db_keys(config))
967 |> Enum.split_with(fn config ->
968 Ecto.get_meta(config, :state) == :deleted
971 Config.TransferTask.load_and_update_env(deleted, false)
973 if !Restarter.Pleroma.need_reboot?() do
974 changed_reboot_settings? =
976 |> Enum.any?(fn config ->
977 group = ConfigDB.from_string(config.group)
978 key = ConfigDB.from_string(config.key)
979 value = ConfigDB.from_binary(config.value)
980 Config.TransferTask.pleroma_need_restart?(group, key, value)
983 if changed_reboot_settings?, do: Restarter.Pleroma.need_reboot()
987 |> put_view(ConfigView)
988 |> render("index.json", %{configs: updated, need_reboot: Restarter.Pleroma.need_reboot?()})
992 def restart(conn, _params) do
993 with :ok <- configurable_from_database(conn) do
994 Restarter.Pleroma.restart(Config.get(:env), 50)
1000 def need_reboot(conn, _params) do
1001 json(conn, %{need_reboot: Restarter.Pleroma.need_reboot?()})
1004 defp configurable_from_database(conn) do
1005 if Config.get(:configurable_from_database) do
1010 {:error, "To use this endpoint you need to enable configuration from database."}
1015 defp whitelisted_config?(%{"group" => group, "key" => key}) do
1016 if whitelisted_configs = Config.get(:database_config_whitelist) do
1017 Enum.any?(whitelisted_configs, fn {whitelisted_group, whitelisted_key} ->
1018 group == inspect(whitelisted_group) && key == inspect(whitelisted_key)
1025 def reload_emoji(conn, _params) do
1026 Pleroma.Emoji.reload()
1031 def confirm_email(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do
1032 users = nicknames |> Enum.map(&User.get_cached_by_nickname/1)
1034 User.toggle_confirmation(users)
1036 ModerationLog.insert_log(%{
1039 action: "confirm_email"
1045 def resend_confirmation_email(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do
1046 users = nicknames |> Enum.map(&User.get_cached_by_nickname/1)
1048 User.try_send_confirmation_email(users)
1050 ModerationLog.insert_log(%{
1053 action: "resend_confirmation_email"
1059 def oauth_app_create(conn, params) do
1061 if params["name"] do
1062 Map.put(params, "client_name", params["name"])
1068 case App.create(params) do
1070 AppView.render("show.json", %{app: app, admin: true})
1072 {:error, changeset} ->
1073 App.errors(changeset)
1079 def oauth_app_update(conn, params) do
1081 if params["name"] do
1082 Map.put(params, "client_name", params["name"])
1087 with {:ok, app} <- App.update(params) do
1088 json(conn, AppView.render("show.json", %{app: app, admin: true}))
1090 {:error, changeset} ->
1091 json(conn, App.errors(changeset))
1094 json_response(conn, :bad_request, "")
1098 def oauth_app_list(conn, params) do
1099 {page, page_size} = page_params(params)
1102 client_name: params["name"],
1103 client_id: params["client_id"],
1105 page_size: page_size
1109 if Map.has_key?(params, "trusted") do
1110 Map.put(search_params, :trusted, params["trusted"])
1115 with {:ok, apps, count} <- App.search(search_params) do
1118 AppView.render("index.json",
1121 page_size: page_size,
1128 def oauth_app_delete(conn, params) do
1129 with {:ok, _app} <- App.destroy(params["id"]) do
1130 json_response(conn, :no_content, "")
1132 _ -> json_response(conn, :bad_request, "")
1136 def stats(conn, _) do
1137 count = Stats.get_status_visibility_count()
1140 |> json(%{"status_visibility" => count})
1143 defp errors(conn, {:error, :not_found}) do
1145 |> put_status(:not_found)
1146 |> json(dgettext("errors", "Not found"))
1149 defp errors(conn, {:error, reason}) do
1151 |> put_status(:bad_request)
1155 defp errors(conn, {:param_cast, _}) do
1157 |> put_status(:bad_request)
1158 |> json(dgettext("errors", "Invalid parameters"))
1161 defp errors(conn, _) do
1163 |> put_status(:internal_server_error)
1164 |> json(dgettext("errors", "Something went wrong"))
1167 defp page_params(params) do
1168 {get_page(params["page"]), get_page_size(params["page_size"])}
1171 defp get_page(page_string) when is_nil(page_string), do: 1
1173 defp get_page(page_string) do
1174 case Integer.parse(page_string) do
1180 defp get_page_size(page_size_string) when is_nil(page_size_string), do: @users_page_size
1182 defp get_page_size(page_size_string) do
1183 case Integer.parse(page_size_string) do
1184 {page_size, _} -> page_size
1185 :error -> @users_page_size