1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
5 defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
6 use Pleroma.Web.ConnCase
7 use Oban.Testing, repo: Pleroma.Repo
11 alias Pleroma.ModerationLog
13 alias Pleroma.Tests.ObanHelpers
15 alias Pleroma.UserInviteToken
16 alias Pleroma.Web.ActivityPub.Relay
17 alias Pleroma.Web.CommonAPI
18 alias Pleroma.Web.MastodonAPI.StatusView
19 alias Pleroma.Web.MediaProxy
20 import Pleroma.Factory
23 Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
28 describe "DELETE /api/pleroma/admin/users" do
30 admin = insert(:user, is_admin: true)
35 |> assign(:user, admin)
36 |> put_req_header("accept", "application/json")
37 |> delete("/api/pleroma/admin/users?nickname=#{user.nickname}")
39 log_entry = Repo.one(ModerationLog)
41 assert ModerationLog.get_log_entry_message(log_entry) ==
42 "@#{admin.nickname} deleted users: @#{user.nickname}"
44 assert json_response(conn, 200) == user.nickname
47 test "multiple users" do
48 admin = insert(:user, is_admin: true)
49 user_one = insert(:user)
50 user_two = insert(:user)
54 |> assign(:user, admin)
55 |> put_req_header("accept", "application/json")
56 |> delete("/api/pleroma/admin/users", %{
57 nicknames: [user_one.nickname, user_two.nickname]
60 log_entry = Repo.one(ModerationLog)
62 assert ModerationLog.get_log_entry_message(log_entry) ==
63 "@#{admin.nickname} deleted users: @#{user_one.nickname}, @#{user_two.nickname}"
65 response = json_response(conn, 200)
66 assert response -- [user_one.nickname, user_two.nickname] == []
70 describe "/api/pleroma/admin/users" do
72 admin = insert(:user, is_admin: true)
76 |> assign(:user, admin)
77 |> put_req_header("accept", "application/json")
78 |> post("/api/pleroma/admin/users", %{
82 "email" => "lain@example.org",
86 "nickname" => "lain2",
87 "email" => "lain2@example.org",
93 response = json_response(conn, 200) |> Enum.map(&Map.get(&1, "type"))
94 assert response == ["success", "success"]
96 log_entry = Repo.one(ModerationLog)
98 assert ["lain", "lain2"] -- Enum.map(log_entry.data["subjects"], & &1["nickname"]) == []
101 test "Cannot create user with exisiting email" do
102 admin = insert(:user, is_admin: true)
107 |> assign(:user, admin)
108 |> put_req_header("accept", "application/json")
109 |> post("/api/pleroma/admin/users", %{
112 "nickname" => "lain",
113 "email" => user.email,
119 assert json_response(conn, 409) == [
123 "email" => user.email,
126 "error" => "email has already been taken",
132 test "Cannot create user with exisiting nickname" do
133 admin = insert(:user, is_admin: true)
138 |> assign(:user, admin)
139 |> put_req_header("accept", "application/json")
140 |> post("/api/pleroma/admin/users", %{
143 "nickname" => user.nickname,
144 "email" => "someuser@plerama.social",
150 assert json_response(conn, 409) == [
154 "email" => "someuser@plerama.social",
155 "nickname" => user.nickname
157 "error" => "nickname has already been taken",
163 test "Multiple user creation works in transaction" do
164 admin = insert(:user, is_admin: true)
169 |> assign(:user, admin)
170 |> put_req_header("accept", "application/json")
171 |> post("/api/pleroma/admin/users", %{
174 "nickname" => "newuser",
175 "email" => "newuser@pleroma.social",
179 "nickname" => "lain",
180 "email" => user.email,
186 assert json_response(conn, 409) == [
190 "email" => user.email,
193 "error" => "email has already been taken",
199 "email" => "newuser@pleroma.social",
200 "nickname" => "newuser"
207 assert User.get_by_nickname("newuser") === nil
211 describe "/api/pleroma/admin/users/:nickname" do
212 test "Show", %{conn: conn} do
213 admin = insert(:user, is_admin: true)
218 |> assign(:user, admin)
219 |> get("/api/pleroma/admin/users/#{user.nickname}")
222 "deactivated" => false,
223 "id" => to_string(user.id),
225 "nickname" => user.nickname,
226 "roles" => %{"admin" => false, "moderator" => false},
228 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
229 "display_name" => HTML.strip_tags(user.name || user.nickname),
230 "confirmation_pending" => false
233 assert expected == json_response(conn, 200)
236 test "when the user doesn't exist", %{conn: conn} do
237 admin = insert(:user, is_admin: true)
242 |> assign(:user, admin)
243 |> get("/api/pleroma/admin/users/#{user.nickname}")
245 assert "Not found" == json_response(conn, 404)
249 describe "/api/pleroma/admin/users/follow" do
250 test "allows to force-follow another user" do
251 admin = insert(:user, is_admin: true)
253 follower = insert(:user)
256 |> assign(:user, admin)
257 |> put_req_header("accept", "application/json")
258 |> post("/api/pleroma/admin/users/follow", %{
259 "follower" => follower.nickname,
260 "followed" => user.nickname
263 user = User.get_cached_by_id(user.id)
264 follower = User.get_cached_by_id(follower.id)
266 assert User.following?(follower, user)
268 log_entry = Repo.one(ModerationLog)
270 assert ModerationLog.get_log_entry_message(log_entry) ==
271 "@#{admin.nickname} made @#{follower.nickname} follow @#{user.nickname}"
275 describe "/api/pleroma/admin/users/unfollow" do
276 test "allows to force-unfollow another user" do
277 admin = insert(:user, is_admin: true)
279 follower = insert(:user)
281 User.follow(follower, user)
284 |> assign(:user, admin)
285 |> put_req_header("accept", "application/json")
286 |> post("/api/pleroma/admin/users/unfollow", %{
287 "follower" => follower.nickname,
288 "followed" => user.nickname
291 user = User.get_cached_by_id(user.id)
292 follower = User.get_cached_by_id(follower.id)
294 refute User.following?(follower, user)
296 log_entry = Repo.one(ModerationLog)
298 assert ModerationLog.get_log_entry_message(log_entry) ==
299 "@#{admin.nickname} made @#{follower.nickname} unfollow @#{user.nickname}"
303 describe "PUT /api/pleroma/admin/users/tag" do
305 admin = insert(:user, is_admin: true)
306 user1 = insert(:user, %{tags: ["x"]})
307 user2 = insert(:user, %{tags: ["y"]})
308 user3 = insert(:user, %{tags: ["unchanged"]})
312 |> assign(:user, admin)
313 |> put_req_header("accept", "application/json")
315 "/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=#{
317 }&tags[]=foo&tags[]=bar"
320 %{conn: conn, admin: admin, user1: user1, user2: user2, user3: user3}
323 test "it appends specified tags to users with specified nicknames", %{
329 assert json_response(conn, :no_content)
330 assert User.get_cached_by_id(user1.id).tags == ["x", "foo", "bar"]
331 assert User.get_cached_by_id(user2.id).tags == ["y", "foo", "bar"]
333 log_entry = Repo.one(ModerationLog)
336 [user1.nickname, user2.nickname]
337 |> Enum.map(&"@#{&1}")
340 tags = ["foo", "bar"] |> Enum.join(", ")
342 assert ModerationLog.get_log_entry_message(log_entry) ==
343 "@#{admin.nickname} added tags: #{tags} to users: #{users}"
346 test "it does not modify tags of not specified users", %{conn: conn, user3: user3} do
347 assert json_response(conn, :no_content)
348 assert User.get_cached_by_id(user3.id).tags == ["unchanged"]
352 describe "DELETE /api/pleroma/admin/users/tag" do
354 admin = insert(:user, is_admin: true)
355 user1 = insert(:user, %{tags: ["x"]})
356 user2 = insert(:user, %{tags: ["y", "z"]})
357 user3 = insert(:user, %{tags: ["unchanged"]})
361 |> assign(:user, admin)
362 |> put_req_header("accept", "application/json")
364 "/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=#{
369 %{conn: conn, admin: admin, user1: user1, user2: user2, user3: user3}
372 test "it removes specified tags from users with specified nicknames", %{
378 assert json_response(conn, :no_content)
379 assert User.get_cached_by_id(user1.id).tags == []
380 assert User.get_cached_by_id(user2.id).tags == ["y"]
382 log_entry = Repo.one(ModerationLog)
385 [user1.nickname, user2.nickname]
386 |> Enum.map(&"@#{&1}")
389 tags = ["x", "z"] |> Enum.join(", ")
391 assert ModerationLog.get_log_entry_message(log_entry) ==
392 "@#{admin.nickname} removed tags: #{tags} from users: #{users}"
395 test "it does not modify tags of not specified users", %{conn: conn, user3: user3} do
396 assert json_response(conn, :no_content)
397 assert User.get_cached_by_id(user3.id).tags == ["unchanged"]
401 describe "/api/pleroma/admin/users/:nickname/permission_group" do
402 test "GET is giving user_info" do
403 admin = insert(:user, is_admin: true)
407 |> assign(:user, admin)
408 |> put_req_header("accept", "application/json")
409 |> get("/api/pleroma/admin/users/#{admin.nickname}/permission_group/")
411 assert json_response(conn, 200) == %{
413 "is_moderator" => false
417 test "/:right POST, can add to a permission group" do
418 admin = insert(:user, is_admin: true)
423 |> assign(:user, admin)
424 |> put_req_header("accept", "application/json")
425 |> post("/api/pleroma/admin/users/#{user.nickname}/permission_group/admin")
427 assert json_response(conn, 200) == %{
431 log_entry = Repo.one(ModerationLog)
433 assert ModerationLog.get_log_entry_message(log_entry) ==
434 "@#{admin.nickname} made @#{user.nickname} admin"
437 test "/:right POST, can add to a permission group (multiple)" do
438 admin = insert(:user, is_admin: true)
439 user_one = insert(:user)
440 user_two = insert(:user)
444 |> assign(:user, admin)
445 |> put_req_header("accept", "application/json")
446 |> post("/api/pleroma/admin/users/permission_group/admin", %{
447 nicknames: [user_one.nickname, user_two.nickname]
450 assert json_response(conn, 200) == %{
454 log_entry = Repo.one(ModerationLog)
456 assert ModerationLog.get_log_entry_message(log_entry) ==
457 "@#{admin.nickname} made @#{user_one.nickname}, @#{user_two.nickname} admin"
460 test "/:right DELETE, can remove from a permission group" do
461 admin = insert(:user, is_admin: true)
462 user = insert(:user, is_admin: true)
466 |> assign(:user, admin)
467 |> put_req_header("accept", "application/json")
468 |> delete("/api/pleroma/admin/users/#{user.nickname}/permission_group/admin")
470 assert json_response(conn, 200) == %{
474 log_entry = Repo.one(ModerationLog)
476 assert ModerationLog.get_log_entry_message(log_entry) ==
477 "@#{admin.nickname} revoked admin role from @#{user.nickname}"
480 test "/:right DELETE, can remove from a permission group (multiple)" do
481 admin = insert(:user, is_admin: true)
482 user_one = insert(:user, is_admin: true)
483 user_two = insert(:user, is_admin: true)
487 |> assign(:user, admin)
488 |> put_req_header("accept", "application/json")
489 |> delete("/api/pleroma/admin/users/permission_group/admin", %{
490 nicknames: [user_one.nickname, user_two.nickname]
493 assert json_response(conn, 200) == %{
497 log_entry = Repo.one(ModerationLog)
499 assert ModerationLog.get_log_entry_message(log_entry) ==
500 "@#{admin.nickname} revoked admin role from @#{user_one.nickname}, @#{
506 describe "POST /api/pleroma/admin/email_invite, with valid config" do
508 [user: insert(:user, is_admin: true)]
511 clear_config([:instance, :registrations_open]) do
512 Pleroma.Config.put([:instance, :registrations_open], false)
515 clear_config([:instance, :invites_enabled]) do
516 Pleroma.Config.put([:instance, :invites_enabled], true)
519 test "sends invitation and returns 204", %{conn: conn, user: user} do
520 recipient_email = "foo@bar.com"
521 recipient_name = "J. D."
525 |> assign(:user, user)
527 "/api/pleroma/admin/users/email_invite?email=#{recipient_email}&name=#{recipient_name}"
530 assert json_response(conn, :no_content)
532 token_record = List.last(Pleroma.Repo.all(Pleroma.UserInviteToken))
534 refute token_record.used
536 notify_email = Pleroma.Config.get([:instance, :notify_email])
537 instance_name = Pleroma.Config.get([:instance, :name])
540 Pleroma.Emails.UserEmail.user_invitation_email(
547 Swoosh.TestAssertions.assert_email_sent(
548 from: {instance_name, notify_email},
549 to: {recipient_name, recipient_email},
550 html_body: email.html_body
554 test "it returns 403 if requested by a non-admin", %{conn: conn} do
555 non_admin_user = insert(:user)
559 |> assign(:user, non_admin_user)
560 |> post("/api/pleroma/admin/users/email_invite?email=foo@bar.com&name=JD")
562 assert json_response(conn, :forbidden)
566 describe "POST /api/pleroma/admin/users/email_invite, with invalid config" do
568 [user: insert(:user, is_admin: true)]
571 clear_config([:instance, :registrations_open])
572 clear_config([:instance, :invites_enabled])
574 test "it returns 500 if `invites_enabled` is not enabled", %{conn: conn, user: user} do
575 Pleroma.Config.put([:instance, :registrations_open], false)
576 Pleroma.Config.put([:instance, :invites_enabled], false)
580 |> assign(:user, user)
581 |> post("/api/pleroma/admin/users/email_invite?email=foo@bar.com&name=JD")
583 assert json_response(conn, :internal_server_error)
586 test "it returns 500 if `registrations_open` is enabled", %{conn: conn, user: user} do
587 Pleroma.Config.put([:instance, :registrations_open], true)
588 Pleroma.Config.put([:instance, :invites_enabled], true)
592 |> assign(:user, user)
593 |> post("/api/pleroma/admin/users/email_invite?email=foo@bar.com&name=JD")
595 assert json_response(conn, :internal_server_error)
599 test "/api/pleroma/admin/users/:nickname/password_reset" do
600 admin = insert(:user, is_admin: true)
605 |> assign(:user, admin)
606 |> put_req_header("accept", "application/json")
607 |> get("/api/pleroma/admin/users/#{user.nickname}/password_reset")
609 resp = json_response(conn, 200)
611 assert Regex.match?(~r/(http:\/\/|https:\/\/)/, resp["link"])
614 describe "GET /api/pleroma/admin/users" do
616 admin = insert(:user, is_admin: true)
620 |> assign(:user, admin)
622 {:ok, conn: conn, admin: admin}
625 test "renders users array for the first page", %{conn: conn, admin: admin} do
626 user = insert(:user, local: false, tags: ["foo", "bar"])
627 conn = get(conn, "/api/pleroma/admin/users?page=1")
632 "deactivated" => admin.deactivated,
634 "nickname" => admin.nickname,
635 "roles" => %{"admin" => true, "moderator" => false},
638 "avatar" => User.avatar_url(admin) |> MediaProxy.url(),
639 "display_name" => HTML.strip_tags(admin.name || admin.nickname),
640 "confirmation_pending" => false
643 "deactivated" => user.deactivated,
645 "nickname" => user.nickname,
646 "roles" => %{"admin" => false, "moderator" => false},
648 "tags" => ["foo", "bar"],
649 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
650 "display_name" => HTML.strip_tags(user.name || user.nickname),
651 "confirmation_pending" => false
654 |> Enum.sort_by(& &1["nickname"])
656 assert json_response(conn, 200) == %{
663 test "renders empty array for the second page", %{conn: conn} do
666 conn = get(conn, "/api/pleroma/admin/users?page=2")
668 assert json_response(conn, 200) == %{
675 test "regular search", %{conn: conn} do
676 user = insert(:user, nickname: "bob")
678 conn = get(conn, "/api/pleroma/admin/users?query=bo")
680 assert json_response(conn, 200) == %{
685 "deactivated" => user.deactivated,
687 "nickname" => user.nickname,
688 "roles" => %{"admin" => false, "moderator" => false},
691 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
692 "display_name" => HTML.strip_tags(user.name || user.nickname),
693 "confirmation_pending" => false
699 test "search by domain", %{conn: conn} do
700 user = insert(:user, nickname: "nickname@domain.com")
703 conn = get(conn, "/api/pleroma/admin/users?query=domain.com")
705 assert json_response(conn, 200) == %{
710 "deactivated" => user.deactivated,
712 "nickname" => user.nickname,
713 "roles" => %{"admin" => false, "moderator" => false},
716 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
717 "display_name" => HTML.strip_tags(user.name || user.nickname),
718 "confirmation_pending" => false
724 test "search by full nickname", %{conn: conn} do
725 user = insert(:user, nickname: "nickname@domain.com")
728 conn = get(conn, "/api/pleroma/admin/users?query=nickname@domain.com")
730 assert json_response(conn, 200) == %{
735 "deactivated" => user.deactivated,
737 "nickname" => user.nickname,
738 "roles" => %{"admin" => false, "moderator" => false},
741 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
742 "display_name" => HTML.strip_tags(user.name || user.nickname),
743 "confirmation_pending" => false
749 test "search by display name", %{conn: conn} do
750 user = insert(:user, name: "Display name")
753 conn = get(conn, "/api/pleroma/admin/users?name=display")
755 assert json_response(conn, 200) == %{
760 "deactivated" => user.deactivated,
762 "nickname" => user.nickname,
763 "roles" => %{"admin" => false, "moderator" => false},
766 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
767 "display_name" => HTML.strip_tags(user.name || user.nickname),
768 "confirmation_pending" => false
774 test "search by email", %{conn: conn} do
775 user = insert(:user, email: "email@example.com")
778 conn = get(conn, "/api/pleroma/admin/users?email=email@example.com")
780 assert json_response(conn, 200) == %{
785 "deactivated" => user.deactivated,
787 "nickname" => user.nickname,
788 "roles" => %{"admin" => false, "moderator" => false},
791 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
792 "display_name" => HTML.strip_tags(user.name || user.nickname),
793 "confirmation_pending" => false
799 test "regular search with page size", %{conn: conn} do
800 user = insert(:user, nickname: "aalice")
801 user2 = insert(:user, nickname: "alice")
803 conn1 = get(conn, "/api/pleroma/admin/users?query=a&page_size=1&page=1")
805 assert json_response(conn1, 200) == %{
810 "deactivated" => user.deactivated,
812 "nickname" => user.nickname,
813 "roles" => %{"admin" => false, "moderator" => false},
816 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
817 "display_name" => HTML.strip_tags(user.name || user.nickname),
818 "confirmation_pending" => false
823 conn2 = get(conn, "/api/pleroma/admin/users?query=a&page_size=1&page=2")
825 assert json_response(conn2, 200) == %{
830 "deactivated" => user2.deactivated,
832 "nickname" => user2.nickname,
833 "roles" => %{"admin" => false, "moderator" => false},
836 "avatar" => User.avatar_url(user2) |> MediaProxy.url(),
837 "display_name" => HTML.strip_tags(user2.name || user2.nickname),
838 "confirmation_pending" => false
844 test "only local users" do
845 admin = insert(:user, is_admin: true, nickname: "john")
846 user = insert(:user, nickname: "bob")
848 insert(:user, nickname: "bobb", local: false)
852 |> assign(:user, admin)
853 |> get("/api/pleroma/admin/users?query=bo&filters=local")
855 assert json_response(conn, 200) == %{
860 "deactivated" => user.deactivated,
862 "nickname" => user.nickname,
863 "roles" => %{"admin" => false, "moderator" => false},
866 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
867 "display_name" => HTML.strip_tags(user.name || user.nickname),
868 "confirmation_pending" => false
874 test "only local users with no query", %{admin: old_admin} do
875 admin = insert(:user, is_admin: true, nickname: "john")
876 user = insert(:user, nickname: "bob")
878 insert(:user, nickname: "bobb", local: false)
882 |> assign(:user, admin)
883 |> get("/api/pleroma/admin/users?filters=local")
888 "deactivated" => user.deactivated,
890 "nickname" => user.nickname,
891 "roles" => %{"admin" => false, "moderator" => false},
894 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
895 "display_name" => HTML.strip_tags(user.name || user.nickname),
896 "confirmation_pending" => false
899 "deactivated" => admin.deactivated,
901 "nickname" => admin.nickname,
902 "roles" => %{"admin" => true, "moderator" => false},
905 "avatar" => User.avatar_url(admin) |> MediaProxy.url(),
906 "display_name" => HTML.strip_tags(admin.name || admin.nickname),
907 "confirmation_pending" => false
910 "deactivated" => false,
911 "id" => old_admin.id,
913 "nickname" => old_admin.nickname,
914 "roles" => %{"admin" => true, "moderator" => false},
916 "avatar" => User.avatar_url(old_admin) |> MediaProxy.url(),
917 "display_name" => HTML.strip_tags(old_admin.name || old_admin.nickname),
918 "confirmation_pending" => false
921 |> Enum.sort_by(& &1["nickname"])
923 assert json_response(conn, 200) == %{
930 test "load only admins", %{conn: conn, admin: admin} do
931 second_admin = insert(:user, is_admin: true)
935 conn = get(conn, "/api/pleroma/admin/users?filters=is_admin")
940 "deactivated" => false,
942 "nickname" => admin.nickname,
943 "roles" => %{"admin" => true, "moderator" => false},
944 "local" => admin.local,
946 "avatar" => User.avatar_url(admin) |> MediaProxy.url(),
947 "display_name" => HTML.strip_tags(admin.name || admin.nickname),
948 "confirmation_pending" => false
951 "deactivated" => false,
952 "id" => second_admin.id,
953 "nickname" => second_admin.nickname,
954 "roles" => %{"admin" => true, "moderator" => false},
955 "local" => second_admin.local,
957 "avatar" => User.avatar_url(second_admin) |> MediaProxy.url(),
958 "display_name" => HTML.strip_tags(second_admin.name || second_admin.nickname),
959 "confirmation_pending" => false
962 |> Enum.sort_by(& &1["nickname"])
964 assert json_response(conn, 200) == %{
971 test "load only moderators", %{conn: conn} do
972 moderator = insert(:user, is_moderator: true)
976 conn = get(conn, "/api/pleroma/admin/users?filters=is_moderator")
978 assert json_response(conn, 200) == %{
983 "deactivated" => false,
984 "id" => moderator.id,
985 "nickname" => moderator.nickname,
986 "roles" => %{"admin" => false, "moderator" => true},
987 "local" => moderator.local,
989 "avatar" => User.avatar_url(moderator) |> MediaProxy.url(),
990 "display_name" => HTML.strip_tags(moderator.name || moderator.nickname),
991 "confirmation_pending" => false
997 test "load users with tags list", %{conn: conn} do
998 user1 = insert(:user, tags: ["first"])
999 user2 = insert(:user, tags: ["second"])
1003 conn = get(conn, "/api/pleroma/admin/users?tags[]=first&tags[]=second")
1008 "deactivated" => false,
1010 "nickname" => user1.nickname,
1011 "roles" => %{"admin" => false, "moderator" => false},
1012 "local" => user1.local,
1013 "tags" => ["first"],
1014 "avatar" => User.avatar_url(user1) |> MediaProxy.url(),
1015 "display_name" => HTML.strip_tags(user1.name || user1.nickname),
1016 "confirmation_pending" => false
1019 "deactivated" => false,
1021 "nickname" => user2.nickname,
1022 "roles" => %{"admin" => false, "moderator" => false},
1023 "local" => user2.local,
1024 "tags" => ["second"],
1025 "avatar" => User.avatar_url(user2) |> MediaProxy.url(),
1026 "display_name" => HTML.strip_tags(user2.name || user2.nickname),
1027 "confirmation_pending" => false
1030 |> Enum.sort_by(& &1["nickname"])
1032 assert json_response(conn, 200) == %{
1039 test "it works with multiple filters" do
1040 admin = insert(:user, nickname: "john", is_admin: true)
1041 user = insert(:user, nickname: "bob", local: false, deactivated: true)
1043 insert(:user, nickname: "ken", local: true, deactivated: true)
1044 insert(:user, nickname: "bobb", local: false, deactivated: false)
1048 |> assign(:user, admin)
1049 |> get("/api/pleroma/admin/users?filters=deactivated,external")
1051 assert json_response(conn, 200) == %{
1056 "deactivated" => user.deactivated,
1058 "nickname" => user.nickname,
1059 "roles" => %{"admin" => false, "moderator" => false},
1060 "local" => user.local,
1062 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
1063 "display_name" => HTML.strip_tags(user.name || user.nickname),
1064 "confirmation_pending" => false
1070 test "it omits relay user", %{admin: admin} do
1071 assert %User{} = Relay.get_actor()
1075 |> assign(:user, admin)
1076 |> get("/api/pleroma/admin/users")
1078 assert json_response(conn, 200) == %{
1083 "deactivated" => admin.deactivated,
1085 "nickname" => admin.nickname,
1086 "roles" => %{"admin" => true, "moderator" => false},
1089 "avatar" => User.avatar_url(admin) |> MediaProxy.url(),
1090 "display_name" => HTML.strip_tags(admin.name || admin.nickname),
1091 "confirmation_pending" => false
1098 test "PATCH /api/pleroma/admin/users/activate" do
1099 admin = insert(:user, is_admin: true)
1100 user_one = insert(:user, deactivated: true)
1101 user_two = insert(:user, deactivated: true)
1105 |> assign(:user, admin)
1107 "/api/pleroma/admin/users/activate",
1108 %{nicknames: [user_one.nickname, user_two.nickname]}
1111 response = json_response(conn, 200)
1112 assert Enum.map(response["users"], & &1["deactivated"]) == [false, false]
1114 log_entry = Repo.one(ModerationLog)
1116 assert ModerationLog.get_log_entry_message(log_entry) ==
1117 "@#{admin.nickname} activated users: @#{user_one.nickname}, @#{user_two.nickname}"
1120 test "PATCH /api/pleroma/admin/users/deactivate" do
1121 admin = insert(:user, is_admin: true)
1122 user_one = insert(:user, deactivated: false)
1123 user_two = insert(:user, deactivated: false)
1127 |> assign(:user, admin)
1129 "/api/pleroma/admin/users/deactivate",
1130 %{nicknames: [user_one.nickname, user_two.nickname]}
1133 response = json_response(conn, 200)
1134 assert Enum.map(response["users"], & &1["deactivated"]) == [true, true]
1136 log_entry = Repo.one(ModerationLog)
1138 assert ModerationLog.get_log_entry_message(log_entry) ==
1139 "@#{admin.nickname} deactivated users: @#{user_one.nickname}, @#{user_two.nickname}"
1142 test "PATCH /api/pleroma/admin/users/:nickname/toggle_activation" do
1143 admin = insert(:user, is_admin: true)
1144 user = insert(:user)
1148 |> assign(:user, admin)
1149 |> patch("/api/pleroma/admin/users/#{user.nickname}/toggle_activation")
1151 assert json_response(conn, 200) ==
1153 "deactivated" => !user.deactivated,
1155 "nickname" => user.nickname,
1156 "roles" => %{"admin" => false, "moderator" => false},
1159 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
1160 "display_name" => HTML.strip_tags(user.name || user.nickname),
1161 "confirmation_pending" => false
1164 log_entry = Repo.one(ModerationLog)
1166 assert ModerationLog.get_log_entry_message(log_entry) ==
1167 "@#{admin.nickname} deactivated users: @#{user.nickname}"
1170 describe "POST /api/pleroma/admin/users/invite_token" do
1172 admin = insert(:user, is_admin: true)
1176 |> assign(:user, admin)
1181 test "without options", %{conn: conn} do
1182 conn = post(conn, "/api/pleroma/admin/users/invite_token")
1184 invite_json = json_response(conn, 200)
1185 invite = UserInviteToken.find_by_token!(invite_json["token"])
1187 refute invite.expires_at
1188 refute invite.max_use
1189 assert invite.invite_type == "one_time"
1192 test "with expires_at", %{conn: conn} do
1194 post(conn, "/api/pleroma/admin/users/invite_token", %{
1195 "expires_at" => Date.to_string(Date.utc_today())
1198 invite_json = json_response(conn, 200)
1199 invite = UserInviteToken.find_by_token!(invite_json["token"])
1202 assert invite.expires_at == Date.utc_today()
1203 refute invite.max_use
1204 assert invite.invite_type == "date_limited"
1207 test "with max_use", %{conn: conn} do
1208 conn = post(conn, "/api/pleroma/admin/users/invite_token", %{"max_use" => 150})
1210 invite_json = json_response(conn, 200)
1211 invite = UserInviteToken.find_by_token!(invite_json["token"])
1213 refute invite.expires_at
1214 assert invite.max_use == 150
1215 assert invite.invite_type == "reusable"
1218 test "with max use and expires_at", %{conn: conn} do
1220 post(conn, "/api/pleroma/admin/users/invite_token", %{
1222 "expires_at" => Date.to_string(Date.utc_today())
1225 invite_json = json_response(conn, 200)
1226 invite = UserInviteToken.find_by_token!(invite_json["token"])
1228 assert invite.expires_at == Date.utc_today()
1229 assert invite.max_use == 150
1230 assert invite.invite_type == "reusable_date_limited"
1234 describe "GET /api/pleroma/admin/users/invites" do
1236 admin = insert(:user, is_admin: true)
1240 |> assign(:user, admin)
1245 test "no invites", %{conn: conn} do
1246 conn = get(conn, "/api/pleroma/admin/users/invites")
1248 assert json_response(conn, 200) == %{"invites" => []}
1251 test "with invite", %{conn: conn} do
1252 {:ok, invite} = UserInviteToken.create_invite()
1254 conn = get(conn, "/api/pleroma/admin/users/invites")
1256 assert json_response(conn, 200) == %{
1259 "expires_at" => nil,
1261 "invite_type" => "one_time",
1263 "token" => invite.token,
1272 describe "POST /api/pleroma/admin/users/revoke_invite" do
1273 test "with token" do
1274 admin = insert(:user, is_admin: true)
1275 {:ok, invite} = UserInviteToken.create_invite()
1279 |> assign(:user, admin)
1280 |> post("/api/pleroma/admin/users/revoke_invite", %{"token" => invite.token})
1282 assert json_response(conn, 200) == %{
1283 "expires_at" => nil,
1285 "invite_type" => "one_time",
1287 "token" => invite.token,
1293 test "with invalid token" do
1294 admin = insert(:user, is_admin: true)
1298 |> assign(:user, admin)
1299 |> post("/api/pleroma/admin/users/revoke_invite", %{"token" => "foo"})
1301 assert json_response(conn, :not_found) == "Not found"
1305 describe "GET /api/pleroma/admin/reports/:id" do
1306 setup %{conn: conn} do
1307 admin = insert(:user, is_admin: true)
1309 %{conn: assign(conn, :user, admin)}
1312 test "returns report by its id", %{conn: conn} do
1313 [reporter, target_user] = insert_pair(:user)
1314 activity = insert(:note_activity, user: target_user)
1316 {:ok, %{id: report_id}} =
1317 CommonAPI.report(reporter, %{
1318 "account_id" => target_user.id,
1319 "comment" => "I feel offended",
1320 "status_ids" => [activity.id]
1325 |> get("/api/pleroma/admin/reports/#{report_id}")
1326 |> json_response(:ok)
1328 assert response["id"] == report_id
1331 test "returns 404 when report id is invalid", %{conn: conn} do
1332 conn = get(conn, "/api/pleroma/admin/reports/test")
1334 assert json_response(conn, :not_found) == "Not found"
1338 describe "PATCH /api/pleroma/admin/reports" do
1339 setup %{conn: conn} do
1340 admin = insert(:user, is_admin: true)
1341 [reporter, target_user] = insert_pair(:user)
1342 activity = insert(:note_activity, user: target_user)
1344 {:ok, %{id: report_id}} =
1345 CommonAPI.report(reporter, %{
1346 "account_id" => target_user.id,
1347 "comment" => "I feel offended",
1348 "status_ids" => [activity.id]
1351 {:ok, %{id: second_report_id}} =
1352 CommonAPI.report(reporter, %{
1353 "account_id" => target_user.id,
1354 "comment" => "I feel very offended",
1355 "status_ids" => [activity.id]
1359 conn: assign(conn, :user, admin),
1362 second_report_id: second_report_id
1366 test "mark report as resolved", %{conn: conn, id: id, admin: admin} do
1368 |> patch("/api/pleroma/admin/reports", %{
1370 %{"state" => "resolved", "id" => id}
1373 |> json_response(:no_content)
1375 activity = Activity.get_by_id(id)
1376 assert activity.data["state"] == "resolved"
1378 log_entry = Repo.one(ModerationLog)
1380 assert ModerationLog.get_log_entry_message(log_entry) ==
1381 "@#{admin.nickname} updated report ##{id} with 'resolved' state"
1384 test "closes report", %{conn: conn, id: id, admin: admin} do
1386 |> patch("/api/pleroma/admin/reports", %{
1388 %{"state" => "closed", "id" => id}
1391 |> json_response(:no_content)
1393 activity = Activity.get_by_id(id)
1394 assert activity.data["state"] == "closed"
1396 log_entry = Repo.one(ModerationLog)
1398 assert ModerationLog.get_log_entry_message(log_entry) ==
1399 "@#{admin.nickname} updated report ##{id} with 'closed' state"
1402 test "returns 400 when state is unknown", %{conn: conn, id: id} do
1405 |> patch("/api/pleroma/admin/reports", %{
1407 %{"state" => "test", "id" => id}
1411 assert hd(json_response(conn, :bad_request))["error"] == "Unsupported state"
1414 test "returns 404 when report is not exist", %{conn: conn} do
1417 |> patch("/api/pleroma/admin/reports", %{
1419 %{"state" => "closed", "id" => "test"}
1423 assert hd(json_response(conn, :bad_request))["error"] == "not_found"
1426 test "updates state of multiple reports", %{
1430 second_report_id: second_report_id
1433 |> patch("/api/pleroma/admin/reports", %{
1435 %{"state" => "resolved", "id" => id},
1436 %{"state" => "closed", "id" => second_report_id}
1439 |> json_response(:no_content)
1441 activity = Activity.get_by_id(id)
1442 second_activity = Activity.get_by_id(second_report_id)
1443 assert activity.data["state"] == "resolved"
1444 assert second_activity.data["state"] == "closed"
1446 [first_log_entry, second_log_entry] = Repo.all(ModerationLog)
1448 assert ModerationLog.get_log_entry_message(first_log_entry) ==
1449 "@#{admin.nickname} updated report ##{id} with 'resolved' state"
1451 assert ModerationLog.get_log_entry_message(second_log_entry) ==
1452 "@#{admin.nickname} updated report ##{second_report_id} with 'closed' state"
1456 describe "GET /api/pleroma/admin/reports" do
1457 setup %{conn: conn} do
1458 admin = insert(:user, is_admin: true)
1460 %{conn: assign(conn, :user, admin)}
1463 test "returns empty response when no reports created", %{conn: conn} do
1466 |> get("/api/pleroma/admin/reports")
1467 |> json_response(:ok)
1469 assert Enum.empty?(response["reports"])
1470 assert response["total"] == 0
1473 test "returns reports", %{conn: conn} do
1474 [reporter, target_user] = insert_pair(:user)
1475 activity = insert(:note_activity, user: target_user)
1477 {:ok, %{id: report_id}} =
1478 CommonAPI.report(reporter, %{
1479 "account_id" => target_user.id,
1480 "comment" => "I feel offended",
1481 "status_ids" => [activity.id]
1486 |> get("/api/pleroma/admin/reports")
1487 |> json_response(:ok)
1489 [report] = response["reports"]
1491 assert length(response["reports"]) == 1
1492 assert report["id"] == report_id
1494 assert response["total"] == 1
1497 test "returns reports with specified state", %{conn: conn} do
1498 [reporter, target_user] = insert_pair(:user)
1499 activity = insert(:note_activity, user: target_user)
1501 {:ok, %{id: first_report_id}} =
1502 CommonAPI.report(reporter, %{
1503 "account_id" => target_user.id,
1504 "comment" => "I feel offended",
1505 "status_ids" => [activity.id]
1508 {:ok, %{id: second_report_id}} =
1509 CommonAPI.report(reporter, %{
1510 "account_id" => target_user.id,
1511 "comment" => "I don't like this user"
1514 CommonAPI.update_report_state(second_report_id, "closed")
1518 |> get("/api/pleroma/admin/reports", %{
1521 |> json_response(:ok)
1523 [open_report] = response["reports"]
1525 assert length(response["reports"]) == 1
1526 assert open_report["id"] == first_report_id
1528 assert response["total"] == 1
1532 |> get("/api/pleroma/admin/reports", %{
1535 |> json_response(:ok)
1537 [closed_report] = response["reports"]
1539 assert length(response["reports"]) == 1
1540 assert closed_report["id"] == second_report_id
1542 assert response["total"] == 1
1546 |> get("/api/pleroma/admin/reports", %{
1547 "state" => "resolved"
1549 |> json_response(:ok)
1551 assert Enum.empty?(response["reports"])
1552 assert response["total"] == 0
1555 test "returns 403 when requested by a non-admin" do
1556 user = insert(:user)
1560 |> assign(:user, user)
1561 |> get("/api/pleroma/admin/reports")
1563 assert json_response(conn, :forbidden) == %{"error" => "User is not admin."}
1566 test "returns 403 when requested by anonymous" do
1569 |> get("/api/pleroma/admin/reports")
1571 assert json_response(conn, :forbidden) == %{"error" => "Invalid credentials."}
1575 describe "GET /api/pleroma/admin/grouped_reports" do
1576 setup %{conn: conn} do
1577 admin = insert(:user, is_admin: true)
1578 [reporter, target_user] = insert_pair(:user)
1580 date1 = (DateTime.to_unix(DateTime.utc_now()) + 1000) |> DateTime.from_unix!()
1581 date2 = (DateTime.to_unix(DateTime.utc_now()) + 2000) |> DateTime.from_unix!()
1582 date3 = (DateTime.to_unix(DateTime.utc_now()) + 3000) |> DateTime.from_unix!()
1585 insert(:note_activity, user: target_user, data_attrs: %{"published" => date1})
1588 insert(:note_activity, user: target_user, data_attrs: %{"published" => date2})
1591 insert(:note_activity, user: target_user, data_attrs: %{"published" => date3})
1593 {:ok, first_report} =
1594 CommonAPI.report(reporter, %{
1595 "account_id" => target_user.id,
1596 "status_ids" => [first_status.id, second_status.id, third_status.id]
1599 {:ok, second_report} =
1600 CommonAPI.report(reporter, %{
1601 "account_id" => target_user.id,
1602 "status_ids" => [first_status.id, second_status.id]
1605 {:ok, third_report} =
1606 CommonAPI.report(reporter, %{
1607 "account_id" => target_user.id,
1608 "status_ids" => [first_status.id]
1612 conn: assign(conn, :user, admin),
1613 first_status: Activity.get_by_ap_id_with_object(first_status.data["id"]),
1614 second_status: Activity.get_by_ap_id_with_object(second_status.data["id"]),
1615 third_status: Activity.get_by_ap_id_with_object(third_status.data["id"]),
1616 first_report: first_report,
1617 first_status_reports: [first_report, second_report, third_report],
1618 second_status_reports: [first_report, second_report],
1619 third_status_reports: [first_report],
1620 target_user: target_user,
1625 test "returns reports grouped by status", %{
1627 first_status: first_status,
1628 second_status: second_status,
1629 third_status: third_status,
1630 first_status_reports: first_status_reports,
1631 second_status_reports: second_status_reports,
1632 third_status_reports: third_status_reports,
1633 target_user: target_user,
1638 |> get("/api/pleroma/admin/grouped_reports")
1639 |> json_response(:ok)
1641 assert length(response["reports"]) == 3
1643 first_group = Enum.find(response["reports"], &(&1["status"]["id"] == first_status.id))
1645 second_group = Enum.find(response["reports"], &(&1["status"]["id"] == second_status.id))
1647 third_group = Enum.find(response["reports"], &(&1["status"]["id"] == third_status.id))
1649 assert length(first_group["reports"]) == 3
1650 assert length(second_group["reports"]) == 2
1651 assert length(third_group["reports"]) == 1
1653 assert first_group["date"] ==
1654 Enum.max_by(first_status_reports, fn act ->
1655 NaiveDateTime.from_iso8601!(act.data["published"])
1656 end).data["published"]
1658 assert first_group["status"] ==
1660 stringify_keys(StatusView.render("show.json", %{activity: first_status})),
1665 assert(first_group["account"]["id"] == target_user.id)
1667 assert length(first_group["actors"]) == 1
1668 assert hd(first_group["actors"])["id"] == reporter.id
1670 assert Enum.map(first_group["reports"], & &1["id"]) --
1671 Enum.map(first_status_reports, & &1.id) == []
1673 assert second_group["date"] ==
1674 Enum.max_by(second_status_reports, fn act ->
1675 NaiveDateTime.from_iso8601!(act.data["published"])
1676 end).data["published"]
1678 assert second_group["status"] ==
1680 stringify_keys(StatusView.render("show.json", %{activity: second_status})),
1685 assert second_group["account"]["id"] == target_user.id
1687 assert length(second_group["actors"]) == 1
1688 assert hd(second_group["actors"])["id"] == reporter.id
1690 assert Enum.map(second_group["reports"], & &1["id"]) --
1691 Enum.map(second_status_reports, & &1.id) == []
1693 assert third_group["date"] ==
1694 Enum.max_by(third_status_reports, fn act ->
1695 NaiveDateTime.from_iso8601!(act.data["published"])
1696 end).data["published"]
1698 assert third_group["status"] ==
1700 stringify_keys(StatusView.render("show.json", %{activity: third_status})),
1705 assert third_group["account"]["id"] == target_user.id
1707 assert length(third_group["actors"]) == 1
1708 assert hd(third_group["actors"])["id"] == reporter.id
1710 assert Enum.map(third_group["reports"], & &1["id"]) --
1711 Enum.map(third_status_reports, & &1.id) == []
1714 test "reopened report renders status data", %{
1716 first_report: first_report,
1717 first_status: first_status
1719 {:ok, _} = CommonAPI.update_report_state(first_report.id, "resolved")
1723 |> get("/api/pleroma/admin/grouped_reports")
1724 |> json_response(:ok)
1726 first_group = Enum.find(response["reports"], &(&1["status"]["id"] == first_status.id))
1728 assert first_group["status"] ==
1730 stringify_keys(StatusView.render("show.json", %{activity: first_status})),
1736 test "reopened report does not render status data if status has been deleted", %{
1738 first_report: first_report,
1739 first_status: first_status,
1740 target_user: target_user
1742 {:ok, _} = CommonAPI.update_report_state(first_report.id, "resolved")
1743 {:ok, _} = CommonAPI.delete(first_status.id, target_user)
1745 refute Activity.get_by_ap_id(first_status.id)
1749 |> get("/api/pleroma/admin/grouped_reports")
1750 |> json_response(:ok)
1752 assert Enum.find(response["reports"], &(&1["status"]["deleted"] == true))["status"][
1756 assert length(Enum.filter(response["reports"], &(&1["status"]["deleted"] == false))) == 2
1759 test "account not empty if status was deleted", %{
1761 first_report: first_report,
1762 first_status: first_status,
1763 target_user: target_user
1765 {:ok, _} = CommonAPI.update_report_state(first_report.id, "resolved")
1766 {:ok, _} = CommonAPI.delete(first_status.id, target_user)
1768 refute Activity.get_by_ap_id(first_status.id)
1772 |> get("/api/pleroma/admin/grouped_reports")
1773 |> json_response(:ok)
1775 assert Enum.find(response["reports"], &(&1["status"]["deleted"] == true))["account"]
1779 describe "POST /api/pleroma/admin/reports/:id/respond" do
1780 setup %{conn: conn} do
1781 admin = insert(:user, is_admin: true)
1783 %{conn: assign(conn, :user, admin), admin: admin}
1786 test "returns created dm", %{conn: conn, admin: admin} do
1787 [reporter, target_user] = insert_pair(:user)
1788 activity = insert(:note_activity, user: target_user)
1790 {:ok, %{id: report_id}} =
1791 CommonAPI.report(reporter, %{
1792 "account_id" => target_user.id,
1793 "comment" => "I feel offended",
1794 "status_ids" => [activity.id]
1799 |> post("/api/pleroma/admin/reports/#{report_id}/respond", %{
1800 "status" => "I will check it out"
1802 |> json_response(:ok)
1804 recipients = Enum.map(response["mentions"], & &1["username"])
1806 assert reporter.nickname in recipients
1807 assert response["content"] == "I will check it out"
1808 assert response["visibility"] == "direct"
1810 log_entry = Repo.one(ModerationLog)
1812 assert ModerationLog.get_log_entry_message(log_entry) ==
1813 "@#{admin.nickname} responded with 'I will check it out' to report ##{
1818 test "returns 400 when status is missing", %{conn: conn} do
1819 conn = post(conn, "/api/pleroma/admin/reports/test/respond")
1821 assert json_response(conn, :bad_request) == "Invalid parameters"
1824 test "returns 404 when report id is invalid", %{conn: conn} do
1826 post(conn, "/api/pleroma/admin/reports/test/respond", %{
1830 assert json_response(conn, :not_found) == "Not found"
1834 describe "PUT /api/pleroma/admin/statuses/:id" do
1835 setup %{conn: conn} do
1836 admin = insert(:user, is_admin: true)
1837 activity = insert(:note_activity)
1839 %{conn: assign(conn, :user, admin), id: activity.id, admin: admin}
1842 test "toggle sensitive flag", %{conn: conn, id: id, admin: admin} do
1845 |> put("/api/pleroma/admin/statuses/#{id}", %{"sensitive" => "true"})
1846 |> json_response(:ok)
1848 assert response["sensitive"]
1850 log_entry = Repo.one(ModerationLog)
1852 assert ModerationLog.get_log_entry_message(log_entry) ==
1853 "@#{admin.nickname} updated status ##{id}, set sensitive: 'true'"
1857 |> put("/api/pleroma/admin/statuses/#{id}", %{"sensitive" => "false"})
1858 |> json_response(:ok)
1860 refute response["sensitive"]
1863 test "change visibility flag", %{conn: conn, id: id, admin: admin} do
1866 |> put("/api/pleroma/admin/statuses/#{id}", %{"visibility" => "public"})
1867 |> json_response(:ok)
1869 assert response["visibility"] == "public"
1871 log_entry = Repo.one(ModerationLog)
1873 assert ModerationLog.get_log_entry_message(log_entry) ==
1874 "@#{admin.nickname} updated status ##{id}, set visibility: 'public'"
1878 |> put("/api/pleroma/admin/statuses/#{id}", %{"visibility" => "private"})
1879 |> json_response(:ok)
1881 assert response["visibility"] == "private"
1885 |> put("/api/pleroma/admin/statuses/#{id}", %{"visibility" => "unlisted"})
1886 |> json_response(:ok)
1888 assert response["visibility"] == "unlisted"
1891 test "returns 400 when visibility is unknown", %{conn: conn, id: id} do
1894 |> put("/api/pleroma/admin/statuses/#{id}", %{"visibility" => "test"})
1896 assert json_response(conn, :bad_request) == "Unsupported visibility"
1900 describe "DELETE /api/pleroma/admin/statuses/:id" do
1901 setup %{conn: conn} do
1902 admin = insert(:user, is_admin: true)
1903 activity = insert(:note_activity)
1905 %{conn: assign(conn, :user, admin), id: activity.id, admin: admin}
1908 test "deletes status", %{conn: conn, id: id, admin: admin} do
1910 |> delete("/api/pleroma/admin/statuses/#{id}")
1911 |> json_response(:ok)
1913 refute Activity.get_by_id(id)
1915 log_entry = Repo.one(ModerationLog)
1917 assert ModerationLog.get_log_entry_message(log_entry) ==
1918 "@#{admin.nickname} deleted status ##{id}"
1921 test "returns error when status is not exist", %{conn: conn} do
1924 |> delete("/api/pleroma/admin/statuses/test")
1926 assert json_response(conn, :bad_request) == "Could not delete"
1930 describe "GET /api/pleroma/admin/config" do
1931 setup %{conn: conn} do
1932 admin = insert(:user, is_admin: true)
1934 %{conn: assign(conn, :user, admin)}
1937 test "without any settings in db", %{conn: conn} do
1938 conn = get(conn, "/api/pleroma/admin/config")
1940 assert json_response(conn, 200) == %{"configs" => []}
1943 test "with settings in db", %{conn: conn} do
1944 config1 = insert(:config)
1945 config2 = insert(:config)
1947 conn = get(conn, "/api/pleroma/admin/config")
1960 } = json_response(conn, 200)
1962 assert key1 == config1.key
1963 assert key2 == config2.key
1967 describe "POST /api/pleroma/admin/config" do
1968 setup %{conn: conn} do
1969 admin = insert(:user, is_admin: true)
1971 temp_file = "config/test.exported_from_db.secret.exs"
1974 Application.delete_env(:pleroma, :key1)
1975 Application.delete_env(:pleroma, :key2)
1976 Application.delete_env(:pleroma, :key3)
1977 Application.delete_env(:pleroma, :key4)
1978 Application.delete_env(:pleroma, :keyaa1)
1979 Application.delete_env(:pleroma, :keyaa2)
1980 Application.delete_env(:pleroma, Pleroma.Web.Endpoint.NotReal)
1981 Application.delete_env(:pleroma, Pleroma.Captcha.NotReal)
1982 :ok = File.rm(temp_file)
1985 %{conn: assign(conn, :user, admin)}
1988 clear_config([:instance, :dynamic_configuration]) do
1989 Pleroma.Config.put([:instance, :dynamic_configuration], true)
1992 @tag capture_log: true
1993 test "create new config setting in db", %{conn: conn} do
1995 post(conn, "/api/pleroma/admin/config", %{
1997 %{group: "pleroma", key: "key1", value: "value1"},
2000 key: "Ueberauth.Strategy.Twitter.OAuth",
2001 value: [%{"tuple" => [":consumer_secret", "aaaa"]}]
2007 ":nested_1" => "nested_value1",
2009 %{":nested_22" => "nested_value222"},
2010 %{":nested_33" => %{":nested_44" => "nested_444"}}
2018 %{"nested_3" => ":nested_3", "nested_33" => "nested_33"},
2019 %{"nested_4" => true}
2025 value: %{":nested_5" => ":upload", "endpoint" => "https://example.com"}
2030 value: %{"tuple" => ["string", "Pleroma.Captcha.NotReal", []]}
2035 assert json_response(conn, 200) == %{
2038 "group" => "pleroma",
2043 "group" => "ueberauth",
2044 "key" => "Ueberauth.Strategy.Twitter.OAuth",
2045 "value" => [%{"tuple" => [":consumer_secret", "aaaa"]}]
2048 "group" => "pleroma",
2051 ":nested_1" => "nested_value1",
2053 %{":nested_22" => "nested_value222"},
2054 %{":nested_33" => %{":nested_44" => "nested_444"}}
2059 "group" => "pleroma",
2062 %{"nested_3" => ":nested_3", "nested_33" => "nested_33"},
2063 %{"nested_4" => true}
2067 "group" => "pleroma",
2069 "value" => %{"endpoint" => "https://example.com", ":nested_5" => ":upload"}
2074 "value" => %{"tuple" => ["string", "Pleroma.Captcha.NotReal", []]}
2079 assert Application.get_env(:pleroma, :key1) == "value1"
2081 assert Application.get_env(:pleroma, :key2) == %{
2082 nested_1: "nested_value1",
2084 %{nested_22: "nested_value222"},
2085 %{nested_33: %{nested_44: "nested_444"}}
2089 assert Application.get_env(:pleroma, :key3) == [
2090 %{"nested_3" => :nested_3, "nested_33" => "nested_33"},
2091 %{"nested_4" => true}
2094 assert Application.get_env(:pleroma, :key4) == %{
2095 "endpoint" => "https://example.com",
2099 assert Application.get_env(:idna, :key5) == {"string", Pleroma.Captcha.NotReal, []}
2102 test "update config setting & delete", %{conn: conn} do
2103 config1 = insert(:config, key: "keyaa1")
2104 config2 = insert(:config, key: "keyaa2")
2108 key: "Ueberauth.Strategy.Microsoft.OAuth",
2109 value: :erlang.term_to_binary([])
2113 post(conn, "/api/pleroma/admin/config", %{
2115 %{group: config1.group, key: config1.key, value: "another_value"},
2116 %{group: config2.group, key: config2.key, delete: "true"},
2119 key: "Ueberauth.Strategy.Microsoft.OAuth",
2125 assert json_response(conn, 200) == %{
2128 "group" => "pleroma",
2129 "key" => config1.key,
2130 "value" => "another_value"
2135 assert Application.get_env(:pleroma, :keyaa1) == "another_value"
2136 refute Application.get_env(:pleroma, :keyaa2)
2139 test "common config example", %{conn: conn} do
2141 post(conn, "/api/pleroma/admin/config", %{
2144 "group" => "pleroma",
2145 "key" => "Pleroma.Captcha.NotReal",
2147 %{"tuple" => [":enabled", false]},
2148 %{"tuple" => [":method", "Pleroma.Captcha.Kocaptcha"]},
2149 %{"tuple" => [":seconds_valid", 60]},
2150 %{"tuple" => [":path", ""]},
2151 %{"tuple" => [":key1", nil]},
2152 %{"tuple" => [":partial_chain", "&:hackney_connect.partial_chain/1"]},
2153 %{"tuple" => [":regex1", "~r/https:\/\/example.com/"]},
2154 %{"tuple" => [":regex2", "~r/https:\/\/example.com/u"]},
2155 %{"tuple" => [":regex3", "~r/https:\/\/example.com/i"]},
2156 %{"tuple" => [":regex4", "~r/https:\/\/example.com/s"]}
2162 assert json_response(conn, 200) == %{
2165 "group" => "pleroma",
2166 "key" => "Pleroma.Captcha.NotReal",
2168 %{"tuple" => [":enabled", false]},
2169 %{"tuple" => [":method", "Pleroma.Captcha.Kocaptcha"]},
2170 %{"tuple" => [":seconds_valid", 60]},
2171 %{"tuple" => [":path", ""]},
2172 %{"tuple" => [":key1", nil]},
2173 %{"tuple" => [":partial_chain", "&:hackney_connect.partial_chain/1"]},
2174 %{"tuple" => [":regex1", "~r/https:\\/\\/example.com/"]},
2175 %{"tuple" => [":regex2", "~r/https:\\/\\/example.com/u"]},
2176 %{"tuple" => [":regex3", "~r/https:\\/\\/example.com/i"]},
2177 %{"tuple" => [":regex4", "~r/https:\\/\\/example.com/s"]}
2184 test "tuples with more than two values", %{conn: conn} do
2186 post(conn, "/api/pleroma/admin/config", %{
2189 "group" => "pleroma",
2190 "key" => "Pleroma.Web.Endpoint.NotReal",
2206 "/api/v1/streaming",
2207 "Pleroma.Web.MastodonAPI.WebsocketHandler",
2214 "Phoenix.Endpoint.CowboyWebSocket",
2217 "Phoenix.Transports.WebSocket",
2220 "Pleroma.Web.Endpoint",
2221 "Pleroma.Web.UserSocket",
2232 "Phoenix.Endpoint.Cowboy2Handler",
2233 %{"tuple" => ["Pleroma.Web.Endpoint", []]}
2250 assert json_response(conn, 200) == %{
2253 "group" => "pleroma",
2254 "key" => "Pleroma.Web.Endpoint.NotReal",
2270 "/api/v1/streaming",
2271 "Pleroma.Web.MastodonAPI.WebsocketHandler",
2278 "Phoenix.Endpoint.CowboyWebSocket",
2281 "Phoenix.Transports.WebSocket",
2284 "Pleroma.Web.Endpoint",
2285 "Pleroma.Web.UserSocket",
2296 "Phoenix.Endpoint.Cowboy2Handler",
2297 %{"tuple" => ["Pleroma.Web.Endpoint", []]}
2315 test "settings with nesting map", %{conn: conn} do
2317 post(conn, "/api/pleroma/admin/config", %{
2320 "group" => "pleroma",
2323 %{"tuple" => [":key2", "some_val"]},
2328 ":max_options" => 20,
2329 ":max_option_chars" => 200,
2330 ":min_expiration" => 0,
2331 ":max_expiration" => 31_536_000,
2333 ":max_options" => 20,
2334 ":max_option_chars" => 200,
2335 ":min_expiration" => 0,
2336 ":max_expiration" => 31_536_000
2346 assert json_response(conn, 200) ==
2350 "group" => "pleroma",
2353 %{"tuple" => [":key2", "some_val"]},
2358 ":max_expiration" => 31_536_000,
2359 ":max_option_chars" => 200,
2360 ":max_options" => 20,
2361 ":min_expiration" => 0,
2363 ":max_expiration" => 31_536_000,
2364 ":max_option_chars" => 200,
2365 ":max_options" => 20,
2366 ":min_expiration" => 0
2377 test "value as map", %{conn: conn} do
2379 post(conn, "/api/pleroma/admin/config", %{
2382 "group" => "pleroma",
2384 "value" => %{"key" => "some_val"}
2389 assert json_response(conn, 200) ==
2393 "group" => "pleroma",
2395 "value" => %{"key" => "some_val"}
2401 test "dispatch setting", %{conn: conn} do
2403 post(conn, "/api/pleroma/admin/config", %{
2406 "group" => "pleroma",
2407 "key" => "Pleroma.Web.Endpoint.NotReal",
2413 %{"tuple" => [":ip", %{"tuple" => [127, 0, 0, 1]}]},
2414 %{"tuple" => [":dispatch", ["{:_,
2416 {\"/api/v1/streaming\", Pleroma.Web.MastodonAPI.WebsocketHandler, []},
2417 {\"/websocket\", Phoenix.Endpoint.CowboyWebSocket,
2418 {Phoenix.Transports.WebSocket,
2419 {Pleroma.Web.Endpoint, Pleroma.Web.UserSocket, [path: \"/websocket\"]}}},
2420 {:_, Phoenix.Endpoint.Cowboy2Handler, {Pleroma.Web.Endpoint, []}}
2431 "{:_, [{\"/api/v1/streaming\", Pleroma.Web.MastodonAPI.WebsocketHandler, []}, " <>
2432 "{\"/websocket\", Phoenix.Endpoint.CowboyWebSocket, {Phoenix.Transports.WebSocket, " <>
2433 "{Pleroma.Web.Endpoint, Pleroma.Web.UserSocket, [path: \"/websocket\"]}}}, " <>
2434 "{:_, Phoenix.Endpoint.Cowboy2Handler, {Pleroma.Web.Endpoint, []}}]}"
2436 assert json_response(conn, 200) == %{
2439 "group" => "pleroma",
2440 "key" => "Pleroma.Web.Endpoint.NotReal",
2446 %{"tuple" => [":ip", %{"tuple" => [127, 0, 0, 1]}]},
2464 test "queues key as atom", %{conn: conn} do
2466 post(conn, "/api/pleroma/admin/config", %{
2472 %{"tuple" => [":federator_incoming", 50]},
2473 %{"tuple" => [":federator_outgoing", 50]},
2474 %{"tuple" => [":web_push", 50]},
2475 %{"tuple" => [":mailer", 10]},
2476 %{"tuple" => [":transmogrifier", 20]},
2477 %{"tuple" => [":scheduled_activities", 10]},
2478 %{"tuple" => [":background", 5]}
2484 assert json_response(conn, 200) == %{
2490 %{"tuple" => [":federator_incoming", 50]},
2491 %{"tuple" => [":federator_outgoing", 50]},
2492 %{"tuple" => [":web_push", 50]},
2493 %{"tuple" => [":mailer", 10]},
2494 %{"tuple" => [":transmogrifier", 20]},
2495 %{"tuple" => [":scheduled_activities", 10]},
2496 %{"tuple" => [":background", 5]}
2503 test "delete part of settings by atom subkeys", %{conn: conn} do
2507 value: :erlang.term_to_binary(subkey1: "val1", subkey2: "val2", subkey3: "val3")
2511 post(conn, "/api/pleroma/admin/config", %{
2514 group: config.group,
2516 subkeys: [":subkey1", ":subkey3"],
2523 json_response(conn, 200) == %{
2526 "group" => "pleroma",
2528 "value" => [%{"tuple" => [":subkey2", "val2"]}]
2536 describe "config mix tasks run" do
2537 setup %{conn: conn} do
2538 admin = insert(:user, is_admin: true)
2540 temp_file = "config/test.exported_from_db.secret.exs"
2542 Mix.shell(Mix.Shell.Quiet)
2545 Mix.shell(Mix.Shell.IO)
2546 :ok = File.rm(temp_file)
2549 %{conn: assign(conn, :user, admin), admin: admin}
2552 clear_config([:instance, :dynamic_configuration]) do
2553 Pleroma.Config.put([:instance, :dynamic_configuration], true)
2556 clear_config([:feed, :post_title]) do
2557 Pleroma.Config.put([:feed, :post_title], %{max_length: 100, omission: "…"})
2560 test "transfer settings to DB and to file", %{conn: conn, admin: admin} do
2561 assert Pleroma.Repo.all(Pleroma.Web.AdminAPI.Config) == []
2562 conn = get(conn, "/api/pleroma/admin/config/migrate_to_db")
2563 assert json_response(conn, 200) == %{}
2564 assert Pleroma.Repo.all(Pleroma.Web.AdminAPI.Config) > 0
2568 |> assign(:user, admin)
2569 |> get("/api/pleroma/admin/config/migrate_from_db")
2571 assert json_response(conn, 200) == %{}
2572 assert Pleroma.Repo.all(Pleroma.Web.AdminAPI.Config) == []
2576 describe "GET /api/pleroma/admin/users/:nickname/statuses" do
2578 admin = insert(:user, is_admin: true)
2579 user = insert(:user)
2581 date1 = (DateTime.to_unix(DateTime.utc_now()) + 2000) |> DateTime.from_unix!()
2582 date2 = (DateTime.to_unix(DateTime.utc_now()) + 1000) |> DateTime.from_unix!()
2583 date3 = (DateTime.to_unix(DateTime.utc_now()) + 3000) |> DateTime.from_unix!()
2585 insert(:note_activity, user: user, published: date1)
2586 insert(:note_activity, user: user, published: date2)
2587 insert(:note_activity, user: user, published: date3)
2591 |> assign(:user, admin)
2593 {:ok, conn: conn, user: user}
2596 test "renders user's statuses", %{conn: conn, user: user} do
2597 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses")
2599 assert json_response(conn, 200) |> length() == 3
2602 test "renders user's statuses with a limit", %{conn: conn, user: user} do
2603 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses?page_size=2")
2605 assert json_response(conn, 200) |> length() == 2
2608 test "doesn't return private statuses by default", %{conn: conn, user: user} do
2609 {:ok, _private_status} =
2610 CommonAPI.post(user, %{"status" => "private", "visibility" => "private"})
2612 {:ok, _public_status} =
2613 CommonAPI.post(user, %{"status" => "public", "visibility" => "public"})
2615 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses")
2617 assert json_response(conn, 200) |> length() == 4
2620 test "returns private statuses with godmode on", %{conn: conn, user: user} do
2621 {:ok, _private_status} =
2622 CommonAPI.post(user, %{"status" => "private", "visibility" => "private"})
2624 {:ok, _public_status} =
2625 CommonAPI.post(user, %{"status" => "public", "visibility" => "public"})
2627 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses?godmode=true")
2629 assert json_response(conn, 200) |> length() == 5
2633 describe "GET /api/pleroma/admin/moderation_log" do
2634 setup %{conn: conn} do
2635 admin = insert(:user, is_admin: true)
2636 moderator = insert(:user, is_moderator: true)
2638 %{conn: assign(conn, :user, admin), admin: admin, moderator: moderator}
2641 test "returns the log", %{conn: conn, admin: admin} do
2642 Repo.insert(%ModerationLog{
2646 "nickname" => admin.nickname,
2649 action: "relay_follow",
2650 target: "https://example.org/relay"
2652 inserted_at: NaiveDateTime.truncate(~N[2017-08-15 15:47:06.597036], :second)
2655 Repo.insert(%ModerationLog{
2659 "nickname" => admin.nickname,
2662 action: "relay_unfollow",
2663 target: "https://example.org/relay"
2665 inserted_at: NaiveDateTime.truncate(~N[2017-08-16 15:47:06.597036], :second)
2668 conn = get(conn, "/api/pleroma/admin/moderation_log")
2670 response = json_response(conn, 200)
2671 [first_entry, second_entry] = response["items"]
2673 assert response["total"] == 2
2674 assert first_entry["data"]["action"] == "relay_unfollow"
2676 assert first_entry["message"] ==
2677 "@#{admin.nickname} unfollowed relay: https://example.org/relay"
2679 assert second_entry["data"]["action"] == "relay_follow"
2681 assert second_entry["message"] ==
2682 "@#{admin.nickname} followed relay: https://example.org/relay"
2685 test "returns the log with pagination", %{conn: conn, admin: admin} do
2686 Repo.insert(%ModerationLog{
2690 "nickname" => admin.nickname,
2693 action: "relay_follow",
2694 target: "https://example.org/relay"
2696 inserted_at: NaiveDateTime.truncate(~N[2017-08-15 15:47:06.597036], :second)
2699 Repo.insert(%ModerationLog{
2703 "nickname" => admin.nickname,
2706 action: "relay_unfollow",
2707 target: "https://example.org/relay"
2709 inserted_at: NaiveDateTime.truncate(~N[2017-08-16 15:47:06.597036], :second)
2712 conn1 = get(conn, "/api/pleroma/admin/moderation_log?page_size=1&page=1")
2714 response1 = json_response(conn1, 200)
2715 [first_entry] = response1["items"]
2717 assert response1["total"] == 2
2718 assert response1["items"] |> length() == 1
2719 assert first_entry["data"]["action"] == "relay_unfollow"
2721 assert first_entry["message"] ==
2722 "@#{admin.nickname} unfollowed relay: https://example.org/relay"
2724 conn2 = get(conn, "/api/pleroma/admin/moderation_log?page_size=1&page=2")
2726 response2 = json_response(conn2, 200)
2727 [second_entry] = response2["items"]
2729 assert response2["total"] == 2
2730 assert response2["items"] |> length() == 1
2731 assert second_entry["data"]["action"] == "relay_follow"
2733 assert second_entry["message"] ==
2734 "@#{admin.nickname} followed relay: https://example.org/relay"
2737 test "filters log by date", %{conn: conn, admin: admin} do
2738 first_date = "2017-08-15T15:47:06Z"
2739 second_date = "2017-08-20T15:47:06Z"
2741 Repo.insert(%ModerationLog{
2745 "nickname" => admin.nickname,
2748 action: "relay_follow",
2749 target: "https://example.org/relay"
2751 inserted_at: NaiveDateTime.from_iso8601!(first_date)
2754 Repo.insert(%ModerationLog{
2758 "nickname" => admin.nickname,
2761 action: "relay_unfollow",
2762 target: "https://example.org/relay"
2764 inserted_at: NaiveDateTime.from_iso8601!(second_date)
2770 "/api/pleroma/admin/moderation_log?start_date=#{second_date}"
2773 response1 = json_response(conn1, 200)
2774 [first_entry] = response1["items"]
2776 assert response1["total"] == 1
2777 assert first_entry["data"]["action"] == "relay_unfollow"
2779 assert first_entry["message"] ==
2780 "@#{admin.nickname} unfollowed relay: https://example.org/relay"
2783 test "returns log filtered by user", %{conn: conn, admin: admin, moderator: moderator} do
2784 Repo.insert(%ModerationLog{
2788 "nickname" => admin.nickname,
2791 action: "relay_follow",
2792 target: "https://example.org/relay"
2796 Repo.insert(%ModerationLog{
2799 "id" => moderator.id,
2800 "nickname" => moderator.nickname,
2803 action: "relay_unfollow",
2804 target: "https://example.org/relay"
2808 conn1 = get(conn, "/api/pleroma/admin/moderation_log?user_id=#{moderator.id}")
2810 response1 = json_response(conn1, 200)
2811 [first_entry] = response1["items"]
2813 assert response1["total"] == 1
2814 assert get_in(first_entry, ["data", "actor", "id"]) == moderator.id
2817 test "returns log filtered by search", %{conn: conn, moderator: moderator} do
2818 ModerationLog.insert_log(%{
2820 action: "relay_follow",
2821 target: "https://example.org/relay"
2824 ModerationLog.insert_log(%{
2826 action: "relay_unfollow",
2827 target: "https://example.org/relay"
2830 conn1 = get(conn, "/api/pleroma/admin/moderation_log?search=unfo")
2832 response1 = json_response(conn1, 200)
2833 [first_entry] = response1["items"]
2835 assert response1["total"] == 1
2837 assert get_in(first_entry, ["data", "message"]) ==
2838 "@#{moderator.nickname} unfollowed relay: https://example.org/relay"
2842 describe "PATCH /users/:nickname/force_password_reset" do
2843 setup %{conn: conn} do
2844 admin = insert(:user, is_admin: true)
2845 user = insert(:user)
2847 %{conn: assign(conn, :user, admin), admin: admin, user: user}
2850 test "sets password_reset_pending to true", %{admin: admin, user: user} do
2851 assert user.password_reset_pending == false
2855 |> assign(:user, admin)
2856 |> patch("/api/pleroma/admin/users/force_password_reset", %{nicknames: [user.nickname]})
2858 assert json_response(conn, 204) == ""
2860 ObanHelpers.perform_all()
2862 assert User.get_by_id(user.id).password_reset_pending == true
2866 describe "relays" do
2867 setup %{conn: conn} do
2868 admin = insert(:user, is_admin: true)
2870 %{conn: assign(conn, :user, admin), admin: admin}
2873 test "POST /relay", %{admin: admin} do
2876 |> assign(:user, admin)
2877 |> post("/api/pleroma/admin/relay", %{
2878 relay_url: "http://mastodon.example.org/users/admin"
2881 assert json_response(conn, 200) == "http://mastodon.example.org/users/admin"
2883 log_entry = Repo.one(ModerationLog)
2885 assert ModerationLog.get_log_entry_message(log_entry) ==
2886 "@#{admin.nickname} followed relay: http://mastodon.example.org/users/admin"
2889 test "GET /relay", %{admin: admin} do
2890 relay_user = Pleroma.Web.ActivityPub.Relay.get_actor()
2892 ["http://mastodon.example.org/users/admin", "https://mstdn.io/users/mayuutann"]
2893 |> Enum.each(fn ap_id ->
2894 {:ok, user} = User.get_or_fetch_by_ap_id(ap_id)
2895 User.follow(relay_user, user)
2900 |> assign(:user, admin)
2901 |> get("/api/pleroma/admin/relay")
2903 assert json_response(conn, 200)["relays"] -- ["mastodon.example.org", "mstdn.io"] == []
2906 test "DELETE /relay", %{admin: admin} do
2908 |> assign(:user, admin)
2909 |> post("/api/pleroma/admin/relay", %{
2910 relay_url: "http://mastodon.example.org/users/admin"
2915 |> assign(:user, admin)
2916 |> delete("/api/pleroma/admin/relay", %{
2917 relay_url: "http://mastodon.example.org/users/admin"
2920 assert json_response(conn, 200) == "http://mastodon.example.org/users/admin"
2922 [log_entry_one, log_entry_two] = Repo.all(ModerationLog)
2924 assert ModerationLog.get_log_entry_message(log_entry_one) ==
2925 "@#{admin.nickname} followed relay: http://mastodon.example.org/users/admin"
2927 assert ModerationLog.get_log_entry_message(log_entry_two) ==
2928 "@#{admin.nickname} unfollowed relay: http://mastodon.example.org/users/admin"
2932 describe "instances" do
2933 test "GET /instances/:instance/statuses" do
2934 admin = insert(:user, is_admin: true)
2935 user = insert(:user, local: false, nickname: "archaeme@archae.me")
2936 user2 = insert(:user, local: false, nickname: "test@test.com")
2937 insert_pair(:note_activity, user: user)
2938 insert(:note_activity, user: user2)
2942 |> assign(:user, admin)
2943 |> get("/api/pleroma/admin/instances/archae.me/statuses")
2945 response = json_response(conn, 200)
2947 assert length(response) == 2
2951 |> assign(:user, admin)
2952 |> get("/api/pleroma/admin/instances/test.com/statuses")
2954 response = json_response(conn, 200)
2956 assert length(response) == 1
2960 |> assign(:user, admin)
2961 |> get("/api/pleroma/admin/instances/nonexistent.com/statuses")
2963 response = json_response(conn, 200)
2965 assert length(response) == 0
2969 describe "PATCH /confirm_email" do
2970 setup %{conn: conn} do
2971 admin = insert(:user, is_admin: true)
2973 %{conn: assign(conn, :user, admin), admin: admin}
2976 test "it confirms emails of two users", %{admin: admin} do
2977 [first_user, second_user] = insert_pair(:user, confirmation_pending: true)
2979 assert first_user.confirmation_pending == true
2980 assert second_user.confirmation_pending == true
2983 |> assign(:user, admin)
2984 |> patch("/api/pleroma/admin/users/confirm_email", %{
2986 first_user.nickname,
2987 second_user.nickname
2991 assert first_user.confirmation_pending == true
2992 assert second_user.confirmation_pending == true
2994 log_entry = Repo.one(ModerationLog)
2996 assert ModerationLog.get_log_entry_message(log_entry) ==
2997 "@#{admin.nickname} confirmed email for users: @#{first_user.nickname}, @#{
2998 second_user.nickname
3003 describe "PATCH /resend_confirmation_email" do
3004 setup %{conn: conn} do
3005 admin = insert(:user, is_admin: true)
3007 %{conn: assign(conn, :user, admin), admin: admin}
3010 test "it resend emails for two users", %{admin: admin} do
3011 [first_user, second_user] = insert_pair(:user, confirmation_pending: true)
3014 |> assign(:user, admin)
3015 |> patch("/api/pleroma/admin/users/resend_confirmation_email", %{
3017 first_user.nickname,
3018 second_user.nickname
3022 log_entry = Repo.one(ModerationLog)
3024 assert ModerationLog.get_log_entry_message(log_entry) ==
3025 "@#{admin.nickname} re-sent confirmation email for users: @#{first_user.nickname}, @#{
3026 second_user.nickname
3032 # Needed for testing
3033 defmodule Pleroma.Web.Endpoint.NotReal do
3036 defmodule Pleroma.Captcha.NotReal do