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.Relay
21 alias Pleroma.Web.ActivityPub.Utils
22 alias Pleroma.Web.AdminAPI.AccountView
23 alias Pleroma.Web.AdminAPI.ConfigView
24 alias Pleroma.Web.AdminAPI.ModerationLogView
25 alias Pleroma.Web.AdminAPI.Report
26 alias Pleroma.Web.AdminAPI.ReportView
27 alias Pleroma.Web.AdminAPI.Search
28 alias Pleroma.Web.CommonAPI
29 alias Pleroma.Web.Endpoint
30 alias Pleroma.Web.MastodonAPI.AppView
31 alias Pleroma.Web.MastodonAPI.StatusView
32 alias Pleroma.Web.OAuth.App
33 alias Pleroma.Web.Router
37 @descriptions_json Pleroma.Docs.JSON.compile()
42 %{scopes: ["read:accounts"], admin: true}
43 when action in [:list_users, :user_show, :right_get, :show_user_credentials]
48 %{scopes: ["write:accounts"], admin: true}
51 :force_password_reset,
54 :user_toggle_activation,
62 :right_delete_multiple,
63 :update_user_credentials
67 plug(OAuthScopesPlug, %{scopes: ["read:invites"], admin: true} when action == :invites)
71 %{scopes: ["write:invites"], admin: true}
72 when action in [:create_invite_token, :revoke_invite, :email_invite]
77 %{scopes: ["write:follows"], admin: true}
78 when action in [:user_follow, :user_unfollow, :relay_follow, :relay_unfollow]
83 %{scopes: ["read:reports"], admin: true}
84 when action in [:list_reports, :report_show]
89 %{scopes: ["write:reports"], admin: true}
90 when action in [:reports_update, :report_notes_create, :report_notes_delete]
95 %{scopes: ["read:statuses"], admin: true}
96 when action in [:list_statuses, :list_user_statuses, :list_instance_statuses]
101 %{scopes: ["write:statuses"], admin: true}
102 when action in [:status_update, :status_delete]
107 %{scopes: ["read"], admin: true}
113 :config_descriptions,
120 %{scopes: ["write"], admin: true}
124 :resend_confirmation_email,
134 action_fallback(:errors)
136 def user_delete(%{assigns: %{user: admin}} = conn, %{"nickname" => nickname}) do
137 user = User.get_cached_by_nickname(nickname)
140 ModerationLog.insert_log(%{
150 def user_delete(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do
151 users = nicknames |> Enum.map(&User.get_cached_by_nickname/1)
154 ModerationLog.insert_log(%{
164 def user_follow(%{assigns: %{user: admin}} = conn, %{
165 "follower" => follower_nick,
166 "followed" => followed_nick
168 with %User{} = follower <- User.get_cached_by_nickname(follower_nick),
169 %User{} = followed <- User.get_cached_by_nickname(followed_nick) do
170 User.follow(follower, followed)
172 ModerationLog.insert_log(%{
184 def user_unfollow(%{assigns: %{user: admin}} = conn, %{
185 "follower" => follower_nick,
186 "followed" => followed_nick
188 with %User{} = follower <- User.get_cached_by_nickname(follower_nick),
189 %User{} = followed <- User.get_cached_by_nickname(followed_nick) do
190 User.unfollow(follower, followed)
192 ModerationLog.insert_log(%{
204 def users_create(%{assigns: %{user: admin}} = conn, %{"users" => users}) do
206 Enum.map(users, fn %{"nickname" => nickname, "email" => email, "password" => password} ->
212 password_confirmation: password,
216 User.register_changeset(%User{}, user_data, need_confirmation: false)
218 |> Enum.reduce(Ecto.Multi.new(), fn changeset, multi ->
219 Ecto.Multi.insert(multi, Ecto.UUID.generate(), changeset)
222 case Pleroma.Repo.transaction(changesets) do
227 |> Enum.map(fn user ->
228 {:ok, user} = User.post_register_action(user)
232 |> Enum.map(&AccountView.render("created.json", %{user: &1}))
234 ModerationLog.insert_log(%{
236 subjects: Map.values(users),
243 {:error, id, changeset, _} ->
245 Enum.map(changesets.operations, fn
246 {current_id, {:changeset, _current_changeset, _}} when current_id == id ->
247 AccountView.render("create-error.json", %{changeset: changeset})
249 {_, {:changeset, current_changeset, _}} ->
250 AccountView.render("create-error.json", %{changeset: current_changeset})
254 |> put_status(:conflict)
259 def user_show(conn, %{"nickname" => nickname}) do
260 with %User{} = user <- User.get_cached_by_nickname_or_id(nickname) do
262 |> put_view(AccountView)
263 |> render("show.json", %{user: user})
265 _ -> {:error, :not_found}
269 def list_instance_statuses(conn, %{"instance" => instance} = params) do
270 with_reblogs = params["with_reblogs"] == "true" || params["with_reblogs"] == true
271 {page, page_size} = page_params(params)
274 ActivityPub.fetch_statuses(nil, %{
275 "instance" => instance,
276 "limit" => page_size,
277 "offset" => (page - 1) * page_size,
278 "exclude_reblogs" => !with_reblogs && "true"
282 |> put_view(Pleroma.Web.AdminAPI.StatusView)
283 |> render("index.json", %{activities: activities, as: :activity, skip_relationships: false})
286 def list_user_statuses(conn, %{"nickname" => nickname} = params) do
287 with_reblogs = params["with_reblogs"] == "true" || params["with_reblogs"] == true
288 godmode = params["godmode"] == "true" || params["godmode"] == true
290 with %User{} = user <- User.get_cached_by_nickname_or_id(nickname) do
291 {_, page_size} = page_params(params)
294 ActivityPub.fetch_user_activities(user, nil, %{
295 "limit" => page_size,
296 "godmode" => godmode,
297 "exclude_reblogs" => !with_reblogs && "true"
301 |> put_view(StatusView)
302 |> render("index.json", %{activities: activities, as: :activity, skip_relationships: false})
304 _ -> {:error, :not_found}
308 def user_toggle_activation(%{assigns: %{user: admin}} = conn, %{"nickname" => nickname}) do
309 user = User.get_cached_by_nickname(nickname)
311 {:ok, updated_user} = User.deactivate(user, !user.deactivated)
313 action = if user.deactivated, do: "activate", else: "deactivate"
315 ModerationLog.insert_log(%{
322 |> put_view(AccountView)
323 |> render("show.json", %{user: updated_user})
326 def user_activate(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do
327 users = Enum.map(nicknames, &User.get_cached_by_nickname/1)
328 {:ok, updated_users} = User.deactivate(users, false)
330 ModerationLog.insert_log(%{
337 |> put_view(AccountView)
338 |> render("index.json", %{users: Keyword.values(updated_users)})
341 def user_deactivate(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do
342 users = Enum.map(nicknames, &User.get_cached_by_nickname/1)
343 {:ok, updated_users} = User.deactivate(users, true)
345 ModerationLog.insert_log(%{
352 |> put_view(AccountView)
353 |> render("index.json", %{users: Keyword.values(updated_users)})
356 def tag_users(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames, "tags" => tags}) do
357 with {:ok, _} <- User.tag(nicknames, tags) do
358 ModerationLog.insert_log(%{
360 nicknames: nicknames,
365 json_response(conn, :no_content, "")
369 def untag_users(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames, "tags" => tags}) do
370 with {:ok, _} <- User.untag(nicknames, tags) do
371 ModerationLog.insert_log(%{
373 nicknames: nicknames,
378 json_response(conn, :no_content, "")
382 def list_users(conn, params) do
383 {page, page_size} = page_params(params)
384 filters = maybe_parse_filters(params["filters"])
387 query: params["query"],
389 page_size: page_size,
390 tags: params["tags"],
391 name: params["name"],
392 email: params["email"]
395 with {:ok, users, count} <- Search.user(Map.merge(search_params, filters)) do
398 AccountView.render("index.json", users: users, count: count, page_size: page_size)
403 @filters ~w(local external active deactivated is_admin is_moderator)
405 @spec maybe_parse_filters(String.t()) :: %{required(String.t()) => true} | %{}
406 defp maybe_parse_filters(filters) when is_nil(filters) or filters == "", do: %{}
408 defp maybe_parse_filters(filters) do
411 |> Enum.filter(&Enum.member?(@filters, &1))
412 |> Enum.map(&String.to_atom(&1))
413 |> Enum.into(%{}, &{&1, true})
416 def right_add_multiple(%{assigns: %{user: admin}} = conn, %{
417 "permission_group" => permission_group,
418 "nicknames" => nicknames
420 when permission_group in ["moderator", "admin"] do
421 update = %{:"is_#{permission_group}" => true}
423 users = nicknames |> Enum.map(&User.get_cached_by_nickname/1)
425 for u <- users, do: User.admin_api_update(u, update)
427 ModerationLog.insert_log(%{
431 permission: permission_group
437 def right_add_multiple(conn, _) do
438 render_error(conn, :not_found, "No such permission_group")
441 def right_add(%{assigns: %{user: admin}} = conn, %{
442 "permission_group" => permission_group,
443 "nickname" => nickname
445 when permission_group in ["moderator", "admin"] do
446 fields = %{:"is_#{permission_group}" => true}
450 |> User.get_cached_by_nickname()
451 |> User.admin_api_update(fields)
453 ModerationLog.insert_log(%{
457 permission: permission_group
463 def right_add(conn, _) do
464 render_error(conn, :not_found, "No such permission_group")
467 def right_get(conn, %{"nickname" => nickname}) do
468 user = User.get_cached_by_nickname(nickname)
472 is_moderator: user.is_moderator,
473 is_admin: user.is_admin
477 def right_delete_multiple(
478 %{assigns: %{user: %{nickname: admin_nickname} = admin}} = conn,
480 "permission_group" => permission_group,
481 "nicknames" => nicknames
484 when permission_group in ["moderator", "admin"] do
485 with false <- Enum.member?(nicknames, admin_nickname) do
486 update = %{:"is_#{permission_group}" => false}
488 users = nicknames |> Enum.map(&User.get_cached_by_nickname/1)
490 for u <- users, do: User.admin_api_update(u, update)
492 ModerationLog.insert_log(%{
496 permission: permission_group
501 _ -> render_error(conn, :forbidden, "You can't revoke your own admin/moderator status.")
505 def right_delete_multiple(conn, _) do
506 render_error(conn, :not_found, "No such permission_group")
510 %{assigns: %{user: admin}} = conn,
512 "permission_group" => permission_group,
513 "nickname" => nickname
516 when permission_group in ["moderator", "admin"] do
517 fields = %{:"is_#{permission_group}" => false}
521 |> User.get_cached_by_nickname()
522 |> User.admin_api_update(fields)
524 ModerationLog.insert_log(%{
528 permission: permission_group
534 def right_delete(%{assigns: %{user: %{nickname: nickname}}} = conn, %{"nickname" => nickname}) do
535 render_error(conn, :forbidden, "You can't revoke your own admin status.")
538 def relay_list(conn, _params) do
539 with {:ok, list} <- Relay.list() do
540 json(conn, %{relays: list})
548 def relay_follow(%{assigns: %{user: admin}} = conn, %{"relay_url" => target}) do
549 with {:ok, _message} <- Relay.follow(target) do
550 ModerationLog.insert_log(%{
551 action: "relay_follow",
565 def relay_unfollow(%{assigns: %{user: admin}} = conn, %{"relay_url" => target}) do
566 with {:ok, _message} <- Relay.unfollow(target) do
567 ModerationLog.insert_log(%{
568 action: "relay_unfollow",
582 @doc "Sends registration invite via email"
583 def email_invite(%{assigns: %{user: user}} = conn, %{"email" => email} = params) do
584 with {_, false} <- {:registrations_open, Config.get([:instance, :registrations_open])},
585 {_, true} <- {:invites_enabled, Config.get([:instance, :invites_enabled])},
586 {:ok, invite_token} <- UserInviteToken.create_invite(),
588 Pleroma.Emails.UserEmail.user_invitation_email(
594 {:ok, _} <- Pleroma.Emails.Mailer.deliver(email) do
595 json_response(conn, :no_content, "")
597 {:registrations_open, _} ->
600 {:error, "To send invites you need to set the `registrations_open` option to false."}
603 {:invites_enabled, _} ->
606 {:error, "To send invites you need to set the `invites_enabled` option to true."}
611 @doc "Create an account registration invite token"
612 def create_invite_token(conn, params) do
616 if params["max_use"],
617 do: Map.put(opts, :max_use, params["max_use"]),
621 if params["expires_at"],
622 do: Map.put(opts, :expires_at, params["expires_at"]),
625 {:ok, invite} = UserInviteToken.create_invite(opts)
627 json(conn, AccountView.render("invite.json", %{invite: invite}))
630 @doc "Get list of created invites"
631 def invites(conn, _params) do
632 invites = UserInviteToken.list_invites()
635 |> put_view(AccountView)
636 |> render("invites.json", %{invites: invites})
639 @doc "Revokes invite by token"
640 def revoke_invite(conn, %{"token" => token}) do
641 with {:ok, invite} <- UserInviteToken.find_by_token(token),
642 {:ok, updated_invite} = UserInviteToken.update_invite(invite, %{used: true}) do
644 |> put_view(AccountView)
645 |> render("invite.json", %{invite: updated_invite})
647 nil -> {:error, :not_found}
651 @doc "Get a password reset token (base64 string) for given nickname"
652 def get_password_reset(conn, %{"nickname" => nickname}) do
653 (%User{local: true} = user) = User.get_cached_by_nickname(nickname)
654 {:ok, token} = Pleroma.PasswordResetToken.create_token(user)
659 link: Router.Helpers.reset_password_url(Endpoint, :reset, token.token)
663 @doc "Force password reset for a given user"
664 def force_password_reset(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do
665 users = nicknames |> Enum.map(&User.get_cached_by_nickname/1)
667 Enum.each(users, &User.force_password_reset_async/1)
669 ModerationLog.insert_log(%{
672 action: "force_password_reset"
675 json_response(conn, :no_content, "")
678 @doc "Show a given user's credentials"
679 def show_user_credentials(%{assigns: %{user: admin}} = conn, %{"nickname" => nickname}) do
680 with %User{} = user <- User.get_cached_by_nickname_or_id(nickname) do
682 |> put_view(AccountView)
683 |> render("credentials.json", %{user: user, for: admin})
685 _ -> {:error, :not_found}
689 @doc "Updates a given user"
690 def update_user_credentials(
691 %{assigns: %{user: admin}} = conn,
692 %{"nickname" => nickname} = params
694 with {_, user} <- {:user, User.get_cached_by_nickname(nickname)},
696 User.update_as_admin(user, params) do
697 ModerationLog.insert_log(%{
700 action: "updated_users"
703 if params["password"] do
704 User.force_password_reset_async(user)
707 ModerationLog.insert_log(%{
710 action: "force_password_reset"
713 json(conn, %{status: "success"})
715 {:error, changeset} ->
716 {_, {error, _}} = Enum.at(changeset.errors, 0)
717 json(conn, %{error: "New password #{error}."})
720 json(conn, %{error: "Unable to change password."})
724 def list_reports(conn, params) do
725 {page, page_size} = page_params(params)
727 reports = Utils.get_reports(params, page, page_size)
730 |> put_view(ReportView)
731 |> render("index.json", %{reports: reports})
734 def report_show(conn, %{"id" => id}) do
735 with %Activity{} = report <- Activity.get_by_id(id) do
737 |> put_view(ReportView)
738 |> render("show.json", Report.extract_report_info(report))
740 _ -> {:error, :not_found}
744 def reports_update(%{assigns: %{user: admin}} = conn, %{"reports" => reports}) do
747 |> Enum.map(fn report ->
748 with {:ok, activity} <- CommonAPI.update_report_state(report["id"], report["state"]) do
749 ModerationLog.insert_log(%{
750 action: "report_update",
757 {:error, message} -> %{id: report["id"], error: message}
761 case Enum.any?(result, &Map.has_key?(&1, :error)) do
762 true -> json_response(conn, :bad_request, result)
763 false -> json_response(conn, :no_content, "")
767 def report_notes_create(%{assigns: %{user: user}} = conn, %{
771 with {:ok, _} <- ReportNote.create(user.id, report_id, content) do
772 ModerationLog.insert_log(%{
773 action: "report_note",
775 subject: Activity.get_by_id(report_id),
779 json_response(conn, :no_content, "")
781 _ -> json_response(conn, :bad_request, "")
785 def report_notes_delete(%{assigns: %{user: user}} = conn, %{
787 "report_id" => report_id
789 with {:ok, note} <- ReportNote.destroy(note_id) do
790 ModerationLog.insert_log(%{
791 action: "report_note_delete",
793 subject: Activity.get_by_id(report_id),
797 json_response(conn, :no_content, "")
799 _ -> json_response(conn, :bad_request, "")
803 def list_statuses(%{assigns: %{user: _admin}} = conn, params) do
804 godmode = params["godmode"] == "true" || params["godmode"] == true
805 local_only = params["local_only"] == "true" || params["local_only"] == true
806 with_reblogs = params["with_reblogs"] == "true" || params["with_reblogs"] == true
807 {page, page_size} = page_params(params)
810 ActivityPub.fetch_statuses(nil, %{
811 "godmode" => godmode,
812 "local_only" => local_only,
813 "limit" => page_size,
814 "offset" => (page - 1) * page_size,
815 "exclude_reblogs" => !with_reblogs && "true"
819 |> put_view(Pleroma.Web.AdminAPI.StatusView)
820 |> render("index.json", %{activities: activities, as: :activity, skip_relationships: false})
823 def status_update(%{assigns: %{user: admin}} = conn, %{"id" => id} = params) do
824 with {:ok, activity} <- CommonAPI.update_activity_scope(id, params) do
825 {:ok, sensitive} = Ecto.Type.cast(:boolean, params["sensitive"])
827 ModerationLog.insert_log(%{
828 action: "status_update",
831 sensitive: sensitive,
832 visibility: params["visibility"]
836 |> put_view(StatusView)
837 |> render("show.json", %{activity: activity})
841 def status_delete(%{assigns: %{user: user}} = conn, %{"id" => id}) do
842 with {:ok, %Activity{}} <- CommonAPI.delete(id, user) do
843 ModerationLog.insert_log(%{
844 action: "status_delete",
853 def list_log(conn, params) do
854 {page, page_size} = page_params(params)
857 ModerationLog.get_all(%{
859 page_size: page_size,
860 start_date: params["start_date"],
861 end_date: params["end_date"],
862 user_id: params["user_id"],
863 search: params["search"]
867 |> put_view(ModerationLogView)
868 |> render("index.json", %{log: log})
871 def config_descriptions(conn, _params) do
873 |> Plug.Conn.put_resp_content_type("application/json")
874 |> Plug.Conn.send_resp(200, @descriptions_json)
877 def config_show(conn, %{"only_db" => true}) do
878 with :ok <- configurable_from_database(conn) do
879 configs = Pleroma.Repo.all(ConfigDB)
882 |> put_view(ConfigView)
883 |> render("index.json", %{configs: configs})
887 def config_show(conn, _params) do
888 with :ok <- configurable_from_database(conn) do
889 configs = ConfigDB.get_all_as_keyword()
892 Config.Holder.default_config()
893 |> ConfigDB.merge(configs)
894 |> Enum.map(fn {group, values} ->
895 Enum.map(values, fn {key, value} ->
897 if configs[group][key] do
898 ConfigDB.get_db_keys(configs[group][key], key)
901 db_value = configs[group][key]
904 if !is_nil(db_value) and Keyword.keyword?(db_value) and
905 ConfigDB.sub_key_full_update?(group, key, Keyword.keys(db_value)) do
906 ConfigDB.merge_group(group, key, value, db_value)
912 group: ConfigDB.convert(group),
913 key: ConfigDB.convert(key),
914 value: ConfigDB.convert(merged_value)
917 if db, do: Map.put(setting, :db, db), else: setting
922 json(conn, %{configs: merged, need_reboot: Restarter.Pleroma.need_reboot?()})
926 def config_update(conn, %{"configs" => configs}) do
927 with :ok <- configurable_from_database(conn) do
930 %{"group" => group, "key" => key, "delete" => true} = params ->
931 ConfigDB.delete(%{group: group, key: key, subkeys: params["subkeys"]})
933 %{"group" => group, "key" => key, "value" => value} ->
934 ConfigDB.update_or_create(%{group: group, key: key, value: value})
936 |> Enum.split_with(fn result -> elem(result, 0) == :error end)
940 |> Enum.map(fn {:ok, config} ->
941 Map.put(config, :db, ConfigDB.get_db_keys(config))
943 |> Enum.split_with(fn config ->
944 Ecto.get_meta(config, :state) == :deleted
947 Config.TransferTask.load_and_update_env(deleted, false)
949 if !Restarter.Pleroma.need_reboot?() do
950 changed_reboot_settings? =
952 |> Enum.any?(fn config ->
953 group = ConfigDB.from_string(config.group)
954 key = ConfigDB.from_string(config.key)
955 value = ConfigDB.from_binary(config.value)
956 Config.TransferTask.pleroma_need_restart?(group, key, value)
959 if changed_reboot_settings?, do: Restarter.Pleroma.need_reboot()
963 |> put_view(ConfigView)
964 |> render("index.json", %{configs: updated, need_reboot: Restarter.Pleroma.need_reboot?()})
968 def restart(conn, _params) do
969 with :ok <- configurable_from_database(conn) do
970 Restarter.Pleroma.restart(Config.get(:env), 50)
976 def need_reboot(conn, _params) do
977 json(conn, %{need_reboot: Restarter.Pleroma.need_reboot?()})
980 defp configurable_from_database(conn) do
981 if Config.get(:configurable_from_database) do
986 {:error, "To use this endpoint you need to enable configuration from database."}
991 def reload_emoji(conn, _params) do
992 Pleroma.Emoji.reload()
997 def confirm_email(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do
998 users = nicknames |> Enum.map(&User.get_cached_by_nickname/1)
1000 User.toggle_confirmation(users)
1002 ModerationLog.insert_log(%{
1005 action: "confirm_email"
1011 def resend_confirmation_email(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do
1012 users = nicknames |> Enum.map(&User.get_cached_by_nickname/1)
1014 User.try_send_confirmation_email(users)
1016 ModerationLog.insert_log(%{
1019 action: "resend_confirmation_email"
1025 def oauth_app_create(conn, params) do
1027 if params["name"] do
1028 Map.put(params, "client_name", params["name"])
1034 case App.create(params) do
1036 AppView.render("show.json", %{app: app, admin: true})
1038 {:error, changeset} ->
1039 App.errors(changeset)
1045 def oauth_app_update(conn, params) do
1047 if params["name"] do
1048 Map.put(params, "client_name", params["name"])
1053 with {:ok, app} <- App.update(params) do
1054 json(conn, AppView.render("show.json", %{app: app, admin: true}))
1056 {:error, changeset} ->
1057 json(conn, App.errors(changeset))
1060 json_response(conn, :bad_request, "")
1064 def oauth_app_list(conn, params) do
1065 {page, page_size} = page_params(params)
1068 client_name: params["name"],
1069 client_id: params["client_id"],
1071 page_size: page_size
1075 if Map.has_key?(params, "trusted") do
1076 Map.put(search_params, :trusted, params["trusted"])
1081 with {:ok, apps, count} <- App.search(search_params) do
1084 AppView.render("index.json",
1087 page_size: page_size,
1094 def oauth_app_delete(conn, params) do
1095 with {:ok, _app} <- App.destroy(params["id"]) do
1096 json_response(conn, :no_content, "")
1098 _ -> json_response(conn, :bad_request, "")
1102 def stats(conn, _) do
1103 count = Stats.get_status_visibility_count()
1106 |> json(%{"status_visibility" => count})
1109 defp errors(conn, {:error, :not_found}) do
1111 |> put_status(:not_found)
1112 |> json(dgettext("errors", "Not found"))
1115 defp errors(conn, {:error, reason}) do
1117 |> put_status(:bad_request)
1121 defp errors(conn, {:param_cast, _}) do
1123 |> put_status(:bad_request)
1124 |> json(dgettext("errors", "Invalid parameters"))
1127 defp errors(conn, _) do
1129 |> put_status(:internal_server_error)
1130 |> json(dgettext("errors", "Something went wrong"))
1133 defp page_params(params) do
1134 {get_page(params["page"]), get_page_size(params["page_size"])}
1137 defp get_page(page_string) when is_nil(page_string), do: 1
1139 defp get_page(page_string) do
1140 case Integer.parse(page_string) do
1146 defp get_page_size(page_size_string) when is_nil(page_size_string), do: @users_page_size
1148 defp get_page_size(page_size_string) do
1149 case Integer.parse(page_size_string) do
1150 {page_size, _} -> page_size
1151 :error -> @users_page_size