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