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