Merge branch 'openapi/admin/reports' into 'develop'
[akkoma] / lib / pleroma / web / admin_api / controllers / admin_api_controller.ex
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Web.AdminAPI.AdminAPIController do
6 use Pleroma.Web, :controller
7
8 import Pleroma.Web.ControllerHelper, only: [json_response: 3]
9
10 alias Pleroma.Config
11 alias Pleroma.ConfigDB
12 alias Pleroma.MFA
13 alias Pleroma.ModerationLog
14 alias Pleroma.Plugs.OAuthScopesPlug
15 alias Pleroma.Stats
16 alias Pleroma.User
17 alias Pleroma.Web.ActivityPub.ActivityPub
18 alias Pleroma.Web.ActivityPub.Builder
19 alias Pleroma.Web.ActivityPub.Pipeline
20 alias Pleroma.Web.ActivityPub.Relay
21 alias Pleroma.Web.AdminAPI
22 alias Pleroma.Web.AdminAPI.AccountView
23 alias Pleroma.Web.AdminAPI.ConfigView
24 alias Pleroma.Web.AdminAPI.ModerationLogView
25 alias Pleroma.Web.AdminAPI.Search
26 alias Pleroma.Web.Endpoint
27 alias Pleroma.Web.Router
28
29 require Logger
30
31 @descriptions Pleroma.Docs.JSON.compile()
32 @users_page_size 50
33
34 plug(
35 OAuthScopesPlug,
36 %{scopes: ["read:accounts"], admin: true}
37 when action in [:list_users, :user_show, :right_get, :show_user_credentials]
38 )
39
40 plug(
41 OAuthScopesPlug,
42 %{scopes: ["write:accounts"], admin: true}
43 when action in [
44 :get_password_reset,
45 :force_password_reset,
46 :user_delete,
47 :users_create,
48 :user_toggle_activation,
49 :user_activate,
50 :user_deactivate,
51 :tag_users,
52 :untag_users,
53 :right_add,
54 :right_add_multiple,
55 :right_delete,
56 :disable_mfa,
57 :right_delete_multiple,
58 :update_user_credentials
59 ]
60 )
61
62 plug(
63 OAuthScopesPlug,
64 %{scopes: ["write:follows"], admin: true}
65 when action in [:user_follow, :user_unfollow, :relay_follow, :relay_unfollow]
66 )
67
68 plug(
69 OAuthScopesPlug,
70 %{scopes: ["read:statuses"], admin: true}
71 when action in [:list_user_statuses, :list_instance_statuses]
72 )
73
74 plug(
75 OAuthScopesPlug,
76 %{scopes: ["read"], admin: true}
77 when action in [
78 :config_show,
79 :list_log,
80 :stats,
81 :relay_list,
82 :config_descriptions,
83 :need_reboot
84 ]
85 )
86
87 plug(
88 OAuthScopesPlug,
89 %{scopes: ["write"], admin: true}
90 when action in [
91 :restart,
92 :config_update,
93 :resend_confirmation_email,
94 :confirm_email,
95 :reload_emoji
96 ]
97 )
98
99 action_fallback(AdminAPI.FallbackController)
100
101 def user_delete(conn, %{"nickname" => nickname}) do
102 user_delete(conn, %{"nicknames" => [nickname]})
103 end
104
105 def user_delete(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do
106 users =
107 nicknames
108 |> Enum.map(&User.get_cached_by_nickname/1)
109
110 users
111 |> Enum.each(fn user ->
112 {:ok, delete_data, _} = Builder.delete(admin, user.ap_id)
113 Pipeline.common_pipeline(delete_data, local: true)
114 end)
115
116 ModerationLog.insert_log(%{
117 actor: admin,
118 subject: users,
119 action: "delete"
120 })
121
122 conn
123 |> json(nicknames)
124 end
125
126 def user_follow(%{assigns: %{user: admin}} = conn, %{
127 "follower" => follower_nick,
128 "followed" => followed_nick
129 }) do
130 with %User{} = follower <- User.get_cached_by_nickname(follower_nick),
131 %User{} = followed <- User.get_cached_by_nickname(followed_nick) do
132 User.follow(follower, followed)
133
134 ModerationLog.insert_log(%{
135 actor: admin,
136 followed: followed,
137 follower: follower,
138 action: "follow"
139 })
140 end
141
142 conn
143 |> json("ok")
144 end
145
146 def user_unfollow(%{assigns: %{user: admin}} = conn, %{
147 "follower" => follower_nick,
148 "followed" => followed_nick
149 }) do
150 with %User{} = follower <- User.get_cached_by_nickname(follower_nick),
151 %User{} = followed <- User.get_cached_by_nickname(followed_nick) do
152 User.unfollow(follower, followed)
153
154 ModerationLog.insert_log(%{
155 actor: admin,
156 followed: followed,
157 follower: follower,
158 action: "unfollow"
159 })
160 end
161
162 conn
163 |> json("ok")
164 end
165
166 def users_create(%{assigns: %{user: admin}} = conn, %{"users" => users}) do
167 changesets =
168 Enum.map(users, fn %{"nickname" => nickname, "email" => email, "password" => password} ->
169 user_data = %{
170 nickname: nickname,
171 name: nickname,
172 email: email,
173 password: password,
174 password_confirmation: password,
175 bio: "."
176 }
177
178 User.register_changeset(%User{}, user_data, need_confirmation: false)
179 end)
180 |> Enum.reduce(Ecto.Multi.new(), fn changeset, multi ->
181 Ecto.Multi.insert(multi, Ecto.UUID.generate(), changeset)
182 end)
183
184 case Pleroma.Repo.transaction(changesets) do
185 {:ok, users} ->
186 res =
187 users
188 |> Map.values()
189 |> Enum.map(fn user ->
190 {:ok, user} = User.post_register_action(user)
191
192 user
193 end)
194 |> Enum.map(&AccountView.render("created.json", %{user: &1}))
195
196 ModerationLog.insert_log(%{
197 actor: admin,
198 subjects: Map.values(users),
199 action: "create"
200 })
201
202 conn
203 |> json(res)
204
205 {:error, id, changeset, _} ->
206 res =
207 Enum.map(changesets.operations, fn
208 {current_id, {:changeset, _current_changeset, _}} when current_id == id ->
209 AccountView.render("create-error.json", %{changeset: changeset})
210
211 {_, {:changeset, current_changeset, _}} ->
212 AccountView.render("create-error.json", %{changeset: current_changeset})
213 end)
214
215 conn
216 |> put_status(:conflict)
217 |> json(res)
218 end
219 end
220
221 def user_show(conn, %{"nickname" => nickname}) do
222 with %User{} = user <- User.get_cached_by_nickname_or_id(nickname) do
223 conn
224 |> put_view(AccountView)
225 |> render("show.json", %{user: user})
226 else
227 _ -> {:error, :not_found}
228 end
229 end
230
231 def list_instance_statuses(conn, %{"instance" => instance} = params) do
232 with_reblogs = params["with_reblogs"] == "true" || params["with_reblogs"] == true
233 {page, page_size} = page_params(params)
234
235 activities =
236 ActivityPub.fetch_statuses(nil, %{
237 "instance" => instance,
238 "limit" => page_size,
239 "offset" => (page - 1) * page_size,
240 "exclude_reblogs" => !with_reblogs && "true"
241 })
242
243 conn
244 |> put_view(AdminAPI.StatusView)
245 |> render("index.json", %{activities: activities, as: :activity})
246 end
247
248 def list_user_statuses(conn, %{"nickname" => nickname} = params) do
249 with_reblogs = params["with_reblogs"] == "true" || params["with_reblogs"] == true
250 godmode = params["godmode"] == "true" || params["godmode"] == true
251
252 with %User{} = user <- User.get_cached_by_nickname_or_id(nickname) do
253 {_, page_size} = page_params(params)
254
255 activities =
256 ActivityPub.fetch_user_activities(user, nil, %{
257 "limit" => page_size,
258 "godmode" => godmode,
259 "exclude_reblogs" => !with_reblogs && "true"
260 })
261
262 conn
263 |> put_view(AdminAPI.StatusView)
264 |> render("index.json", %{activities: activities, as: :activity})
265 else
266 _ -> {:error, :not_found}
267 end
268 end
269
270 def user_toggle_activation(%{assigns: %{user: admin}} = conn, %{"nickname" => nickname}) do
271 user = User.get_cached_by_nickname(nickname)
272
273 {:ok, updated_user} = User.deactivate(user, !user.deactivated)
274
275 action = if user.deactivated, do: "activate", else: "deactivate"
276
277 ModerationLog.insert_log(%{
278 actor: admin,
279 subject: [user],
280 action: action
281 })
282
283 conn
284 |> put_view(AccountView)
285 |> render("show.json", %{user: updated_user})
286 end
287
288 def user_activate(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do
289 users = Enum.map(nicknames, &User.get_cached_by_nickname/1)
290 {:ok, updated_users} = User.deactivate(users, false)
291
292 ModerationLog.insert_log(%{
293 actor: admin,
294 subject: users,
295 action: "activate"
296 })
297
298 conn
299 |> put_view(AccountView)
300 |> render("index.json", %{users: Keyword.values(updated_users)})
301 end
302
303 def user_deactivate(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do
304 users = Enum.map(nicknames, &User.get_cached_by_nickname/1)
305 {:ok, updated_users} = User.deactivate(users, true)
306
307 ModerationLog.insert_log(%{
308 actor: admin,
309 subject: users,
310 action: "deactivate"
311 })
312
313 conn
314 |> put_view(AccountView)
315 |> render("index.json", %{users: Keyword.values(updated_users)})
316 end
317
318 def tag_users(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames, "tags" => tags}) do
319 with {:ok, _} <- User.tag(nicknames, tags) do
320 ModerationLog.insert_log(%{
321 actor: admin,
322 nicknames: nicknames,
323 tags: tags,
324 action: "tag"
325 })
326
327 json_response(conn, :no_content, "")
328 end
329 end
330
331 def untag_users(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames, "tags" => tags}) do
332 with {:ok, _} <- User.untag(nicknames, tags) do
333 ModerationLog.insert_log(%{
334 actor: admin,
335 nicknames: nicknames,
336 tags: tags,
337 action: "untag"
338 })
339
340 json_response(conn, :no_content, "")
341 end
342 end
343
344 def list_users(conn, params) do
345 {page, page_size} = page_params(params)
346 filters = maybe_parse_filters(params["filters"])
347
348 search_params = %{
349 query: params["query"],
350 page: page,
351 page_size: page_size,
352 tags: params["tags"],
353 name: params["name"],
354 email: params["email"]
355 }
356
357 with {:ok, users, count} <- Search.user(Map.merge(search_params, filters)) do
358 json(
359 conn,
360 AccountView.render("index.json", users: users, count: count, page_size: page_size)
361 )
362 end
363 end
364
365 @filters ~w(local external active deactivated is_admin is_moderator)
366
367 @spec maybe_parse_filters(String.t()) :: %{required(String.t()) => true} | %{}
368 defp maybe_parse_filters(filters) when is_nil(filters) or filters == "", do: %{}
369
370 defp maybe_parse_filters(filters) do
371 filters
372 |> String.split(",")
373 |> Enum.filter(&Enum.member?(@filters, &1))
374 |> Enum.map(&String.to_atom(&1))
375 |> Enum.into(%{}, &{&1, true})
376 end
377
378 def right_add_multiple(%{assigns: %{user: admin}} = conn, %{
379 "permission_group" => permission_group,
380 "nicknames" => nicknames
381 })
382 when permission_group in ["moderator", "admin"] do
383 update = %{:"is_#{permission_group}" => true}
384
385 users = nicknames |> Enum.map(&User.get_cached_by_nickname/1)
386
387 for u <- users, do: User.admin_api_update(u, update)
388
389 ModerationLog.insert_log(%{
390 action: "grant",
391 actor: admin,
392 subject: users,
393 permission: permission_group
394 })
395
396 json(conn, update)
397 end
398
399 def right_add_multiple(conn, _) do
400 render_error(conn, :not_found, "No such permission_group")
401 end
402
403 def right_add(%{assigns: %{user: admin}} = conn, %{
404 "permission_group" => permission_group,
405 "nickname" => nickname
406 })
407 when permission_group in ["moderator", "admin"] do
408 fields = %{:"is_#{permission_group}" => true}
409
410 {:ok, user} =
411 nickname
412 |> User.get_cached_by_nickname()
413 |> User.admin_api_update(fields)
414
415 ModerationLog.insert_log(%{
416 action: "grant",
417 actor: admin,
418 subject: [user],
419 permission: permission_group
420 })
421
422 json(conn, fields)
423 end
424
425 def right_add(conn, _) do
426 render_error(conn, :not_found, "No such permission_group")
427 end
428
429 def right_get(conn, %{"nickname" => nickname}) do
430 user = User.get_cached_by_nickname(nickname)
431
432 conn
433 |> json(%{
434 is_moderator: user.is_moderator,
435 is_admin: user.is_admin
436 })
437 end
438
439 def right_delete_multiple(
440 %{assigns: %{user: %{nickname: admin_nickname} = admin}} = conn,
441 %{
442 "permission_group" => permission_group,
443 "nicknames" => nicknames
444 }
445 )
446 when permission_group in ["moderator", "admin"] do
447 with false <- Enum.member?(nicknames, admin_nickname) do
448 update = %{:"is_#{permission_group}" => false}
449
450 users = nicknames |> Enum.map(&User.get_cached_by_nickname/1)
451
452 for u <- users, do: User.admin_api_update(u, update)
453
454 ModerationLog.insert_log(%{
455 action: "revoke",
456 actor: admin,
457 subject: users,
458 permission: permission_group
459 })
460
461 json(conn, update)
462 else
463 _ -> render_error(conn, :forbidden, "You can't revoke your own admin/moderator status.")
464 end
465 end
466
467 def right_delete_multiple(conn, _) do
468 render_error(conn, :not_found, "No such permission_group")
469 end
470
471 def right_delete(
472 %{assigns: %{user: admin}} = conn,
473 %{
474 "permission_group" => permission_group,
475 "nickname" => nickname
476 }
477 )
478 when permission_group in ["moderator", "admin"] do
479 fields = %{:"is_#{permission_group}" => false}
480
481 {:ok, user} =
482 nickname
483 |> User.get_cached_by_nickname()
484 |> User.admin_api_update(fields)
485
486 ModerationLog.insert_log(%{
487 action: "revoke",
488 actor: admin,
489 subject: [user],
490 permission: permission_group
491 })
492
493 json(conn, fields)
494 end
495
496 def right_delete(%{assigns: %{user: %{nickname: nickname}}} = conn, %{"nickname" => nickname}) do
497 render_error(conn, :forbidden, "You can't revoke your own admin status.")
498 end
499
500 def relay_list(conn, _params) do
501 with {:ok, list} <- Relay.list() do
502 json(conn, %{relays: list})
503 else
504 _ ->
505 conn
506 |> put_status(500)
507 end
508 end
509
510 def relay_follow(%{assigns: %{user: admin}} = conn, %{"relay_url" => target}) do
511 with {:ok, _message} <- Relay.follow(target) do
512 ModerationLog.insert_log(%{
513 action: "relay_follow",
514 actor: admin,
515 target: target
516 })
517
518 json(conn, target)
519 else
520 _ ->
521 conn
522 |> put_status(500)
523 |> json(target)
524 end
525 end
526
527 def relay_unfollow(%{assigns: %{user: admin}} = conn, %{"relay_url" => target}) do
528 with {:ok, _message} <- Relay.unfollow(target) do
529 ModerationLog.insert_log(%{
530 action: "relay_unfollow",
531 actor: admin,
532 target: target
533 })
534
535 json(conn, target)
536 else
537 _ ->
538 conn
539 |> put_status(500)
540 |> json(target)
541 end
542 end
543
544 @doc "Get a password reset token (base64 string) for given nickname"
545 def get_password_reset(conn, %{"nickname" => nickname}) do
546 (%User{local: true} = user) = User.get_cached_by_nickname(nickname)
547 {:ok, token} = Pleroma.PasswordResetToken.create_token(user)
548
549 conn
550 |> json(%{
551 token: token.token,
552 link: Router.Helpers.reset_password_url(Endpoint, :reset, token.token)
553 })
554 end
555
556 @doc "Force password reset for a given user"
557 def force_password_reset(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do
558 users = nicknames |> Enum.map(&User.get_cached_by_nickname/1)
559
560 Enum.each(users, &User.force_password_reset_async/1)
561
562 ModerationLog.insert_log(%{
563 actor: admin,
564 subject: users,
565 action: "force_password_reset"
566 })
567
568 json_response(conn, :no_content, "")
569 end
570
571 @doc "Disable mfa for user's account."
572 def disable_mfa(conn, %{"nickname" => nickname}) do
573 case User.get_by_nickname(nickname) do
574 %User{} = user ->
575 MFA.disable(user)
576 json(conn, nickname)
577
578 _ ->
579 {:error, :not_found}
580 end
581 end
582
583 @doc "Show a given user's credentials"
584 def show_user_credentials(%{assigns: %{user: admin}} = conn, %{"nickname" => nickname}) do
585 with %User{} = user <- User.get_cached_by_nickname_or_id(nickname) do
586 conn
587 |> put_view(AccountView)
588 |> render("credentials.json", %{user: user, for: admin})
589 else
590 _ -> {:error, :not_found}
591 end
592 end
593
594 @doc "Updates a given user"
595 def update_user_credentials(
596 %{assigns: %{user: admin}} = conn,
597 %{"nickname" => nickname} = params
598 ) do
599 with {_, %User{} = user} <- {:user, User.get_cached_by_nickname(nickname)},
600 {:ok, _user} <-
601 User.update_as_admin(user, params) do
602 ModerationLog.insert_log(%{
603 actor: admin,
604 subject: [user],
605 action: "updated_users"
606 })
607
608 if params["password"] do
609 User.force_password_reset_async(user)
610 end
611
612 ModerationLog.insert_log(%{
613 actor: admin,
614 subject: [user],
615 action: "force_password_reset"
616 })
617
618 json(conn, %{status: "success"})
619 else
620 {:error, changeset} ->
621 errors = Map.new(changeset.errors, fn {key, {error, _}} -> {key, error} end)
622
623 json(conn, %{errors: errors})
624
625 _ ->
626 json(conn, %{error: "Unable to update user."})
627 end
628 end
629
630 def list_log(conn, params) do
631 {page, page_size} = page_params(params)
632
633 log =
634 ModerationLog.get_all(%{
635 page: page,
636 page_size: page_size,
637 start_date: params["start_date"],
638 end_date: params["end_date"],
639 user_id: params["user_id"],
640 search: params["search"]
641 })
642
643 conn
644 |> put_view(ModerationLogView)
645 |> render("index.json", %{log: log})
646 end
647
648 def config_descriptions(conn, _params) do
649 descriptions = Enum.filter(@descriptions, &whitelisted_config?/1)
650
651 json(conn, descriptions)
652 end
653
654 def config_show(conn, %{"only_db" => true}) do
655 with :ok <- configurable_from_database() do
656 configs = Pleroma.Repo.all(ConfigDB)
657
658 conn
659 |> put_view(ConfigView)
660 |> render("index.json", %{configs: configs})
661 end
662 end
663
664 def config_show(conn, _params) do
665 with :ok <- configurable_from_database() do
666 configs = ConfigDB.get_all_as_keyword()
667
668 merged =
669 Config.Holder.default_config()
670 |> ConfigDB.merge(configs)
671 |> Enum.map(fn {group, values} ->
672 Enum.map(values, fn {key, value} ->
673 db =
674 if configs[group][key] do
675 ConfigDB.get_db_keys(configs[group][key], key)
676 end
677
678 db_value = configs[group][key]
679
680 merged_value =
681 if !is_nil(db_value) and Keyword.keyword?(db_value) and
682 ConfigDB.sub_key_full_update?(group, key, Keyword.keys(db_value)) do
683 ConfigDB.merge_group(group, key, value, db_value)
684 else
685 value
686 end
687
688 setting = %{
689 group: ConfigDB.convert(group),
690 key: ConfigDB.convert(key),
691 value: ConfigDB.convert(merged_value)
692 }
693
694 if db, do: Map.put(setting, :db, db), else: setting
695 end)
696 end)
697 |> List.flatten()
698
699 json(conn, %{configs: merged, need_reboot: Restarter.Pleroma.need_reboot?()})
700 end
701 end
702
703 def config_update(conn, %{"configs" => configs}) do
704 with :ok <- configurable_from_database() do
705 {_errors, results} =
706 configs
707 |> Enum.filter(&whitelisted_config?/1)
708 |> Enum.map(fn
709 %{"group" => group, "key" => key, "delete" => true} = params ->
710 ConfigDB.delete(%{group: group, key: key, subkeys: params["subkeys"]})
711
712 %{"group" => group, "key" => key, "value" => value} ->
713 ConfigDB.update_or_create(%{group: group, key: key, value: value})
714 end)
715 |> Enum.split_with(fn result -> elem(result, 0) == :error end)
716
717 {deleted, updated} =
718 results
719 |> Enum.map(fn {:ok, config} ->
720 Map.put(config, :db, ConfigDB.get_db_keys(config))
721 end)
722 |> Enum.split_with(fn config ->
723 Ecto.get_meta(config, :state) == :deleted
724 end)
725
726 Config.TransferTask.load_and_update_env(deleted, false)
727
728 if !Restarter.Pleroma.need_reboot?() do
729 changed_reboot_settings? =
730 (updated ++ deleted)
731 |> Enum.any?(fn config ->
732 group = ConfigDB.from_string(config.group)
733 key = ConfigDB.from_string(config.key)
734 value = ConfigDB.from_binary(config.value)
735 Config.TransferTask.pleroma_need_restart?(group, key, value)
736 end)
737
738 if changed_reboot_settings?, do: Restarter.Pleroma.need_reboot()
739 end
740
741 conn
742 |> put_view(ConfigView)
743 |> render("index.json", %{configs: updated, need_reboot: Restarter.Pleroma.need_reboot?()})
744 end
745 end
746
747 def restart(conn, _params) do
748 with :ok <- configurable_from_database() do
749 Restarter.Pleroma.restart(Config.get(:env), 50)
750
751 json(conn, %{})
752 end
753 end
754
755 def need_reboot(conn, _params) do
756 json(conn, %{need_reboot: Restarter.Pleroma.need_reboot?()})
757 end
758
759 defp configurable_from_database do
760 if Config.get(:configurable_from_database) do
761 :ok
762 else
763 {:error, "To use this endpoint you need to enable configuration from database."}
764 end
765 end
766
767 defp whitelisted_config?(group, key) do
768 if whitelisted_configs = Config.get(:database_config_whitelist) do
769 Enum.any?(whitelisted_configs, fn
770 {whitelisted_group} ->
771 group == inspect(whitelisted_group)
772
773 {whitelisted_group, whitelisted_key} ->
774 group == inspect(whitelisted_group) && key == inspect(whitelisted_key)
775 end)
776 else
777 true
778 end
779 end
780
781 defp whitelisted_config?(%{"group" => group, "key" => key}) do
782 whitelisted_config?(group, key)
783 end
784
785 defp whitelisted_config?(%{:group => group} = config) do
786 whitelisted_config?(group, config[:key])
787 end
788
789 def reload_emoji(conn, _params) do
790 Pleroma.Emoji.reload()
791
792 conn |> json("ok")
793 end
794
795 def confirm_email(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do
796 users = nicknames |> Enum.map(&User.get_cached_by_nickname/1)
797
798 User.toggle_confirmation(users)
799
800 ModerationLog.insert_log(%{
801 actor: admin,
802 subject: users,
803 action: "confirm_email"
804 })
805
806 conn |> json("")
807 end
808
809 def resend_confirmation_email(%{assigns: %{user: admin}} = conn, %{"nicknames" => nicknames}) do
810 users = nicknames |> Enum.map(&User.get_cached_by_nickname/1)
811
812 User.try_send_confirmation_email(users)
813
814 ModerationLog.insert_log(%{
815 actor: admin,
816 subject: users,
817 action: "resend_confirmation_email"
818 })
819
820 conn |> json("")
821 end
822
823 def stats(conn, _) do
824 count = Stats.get_status_visibility_count()
825
826 conn
827 |> json(%{"status_visibility" => count})
828 end
829
830 defp page_params(params) do
831 {get_page(params["page"]), get_page_size(params["page_size"])}
832 end
833
834 defp get_page(page_string) when is_nil(page_string), do: 1
835
836 defp get_page(page_string) do
837 case Integer.parse(page_string) do
838 {page, _} -> page
839 :error -> 1
840 end
841 end
842
843 defp get_page_size(page_size_string) when is_nil(page_size_string), do: @users_page_size
844
845 defp get_page_size(page_size_string) do
846 case Integer.parse(page_size_string) do
847 {page_size, _} -> page_size
848 :error -> @users_page_size
849 end
850 end
851 end