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