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.MediaProxy
19 import Pleroma.Factory
22 Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
27 describe "DELETE /api/pleroma/admin/users" do
29 admin = insert(:user, is_admin: true)
34 |> assign(:user, admin)
35 |> put_req_header("accept", "application/json")
36 |> delete("/api/pleroma/admin/users?nickname=#{user.nickname}")
38 log_entry = Repo.one(ModerationLog)
40 assert ModerationLog.get_log_entry_message(log_entry) ==
41 "@#{admin.nickname} deleted users: @#{user.nickname}"
43 assert json_response(conn, 200) == user.nickname
46 test "multiple users" do
47 admin = insert(:user, is_admin: true)
48 user_one = insert(:user)
49 user_two = insert(:user)
53 |> assign(:user, admin)
54 |> put_req_header("accept", "application/json")
55 |> delete("/api/pleroma/admin/users", %{
56 nicknames: [user_one.nickname, user_two.nickname]
59 log_entry = Repo.one(ModerationLog)
61 assert ModerationLog.get_log_entry_message(log_entry) ==
62 "@#{admin.nickname} deleted users: @#{user_one.nickname}, @#{user_two.nickname}"
64 response = json_response(conn, 200)
65 assert response -- [user_one.nickname, user_two.nickname] == []
69 describe "/api/pleroma/admin/users" do
71 admin = insert(:user, is_admin: true)
75 |> assign(:user, admin)
76 |> put_req_header("accept", "application/json")
77 |> post("/api/pleroma/admin/users", %{
81 "email" => "lain@example.org",
85 "nickname" => "lain2",
86 "email" => "lain2@example.org",
92 response = json_response(conn, 200) |> Enum.map(&Map.get(&1, "type"))
93 assert response == ["success", "success"]
95 log_entry = Repo.one(ModerationLog)
97 assert ["lain", "lain2"] -- Enum.map(log_entry.data["subjects"], & &1["nickname"]) == []
100 test "Cannot create user with exisiting email" do
101 admin = insert(:user, is_admin: true)
106 |> assign(:user, admin)
107 |> put_req_header("accept", "application/json")
108 |> post("/api/pleroma/admin/users", %{
111 "nickname" => "lain",
112 "email" => user.email,
118 assert json_response(conn, 409) == [
122 "email" => user.email,
125 "error" => "email has already been taken",
131 test "Cannot create user with exisiting nickname" do
132 admin = insert(:user, is_admin: true)
137 |> assign(:user, admin)
138 |> put_req_header("accept", "application/json")
139 |> post("/api/pleroma/admin/users", %{
142 "nickname" => user.nickname,
143 "email" => "someuser@plerama.social",
149 assert json_response(conn, 409) == [
153 "email" => "someuser@plerama.social",
154 "nickname" => user.nickname
156 "error" => "nickname has already been taken",
162 test "Multiple user creation works in transaction" do
163 admin = insert(:user, is_admin: true)
168 |> assign(:user, admin)
169 |> put_req_header("accept", "application/json")
170 |> post("/api/pleroma/admin/users", %{
173 "nickname" => "newuser",
174 "email" => "newuser@pleroma.social",
178 "nickname" => "lain",
179 "email" => user.email,
185 assert json_response(conn, 409) == [
189 "email" => user.email,
192 "error" => "email has already been taken",
198 "email" => "newuser@pleroma.social",
199 "nickname" => "newuser"
206 assert User.get_by_nickname("newuser") === nil
210 describe "/api/pleroma/admin/users/:nickname" do
211 test "Show", %{conn: conn} do
212 admin = insert(:user, is_admin: true)
217 |> assign(:user, admin)
218 |> get("/api/pleroma/admin/users/#{user.nickname}")
221 "deactivated" => false,
222 "id" => to_string(user.id),
224 "nickname" => user.nickname,
225 "roles" => %{"admin" => false, "moderator" => false},
227 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
228 "display_name" => HTML.strip_tags(user.name || user.nickname)
231 assert expected == json_response(conn, 200)
234 test "when the user doesn't exist", %{conn: conn} do
235 admin = insert(:user, is_admin: true)
240 |> assign(:user, admin)
241 |> get("/api/pleroma/admin/users/#{user.nickname}")
243 assert "Not found" == json_response(conn, 404)
247 describe "/api/pleroma/admin/users/follow" do
248 test "allows to force-follow another user" do
249 admin = insert(:user, is_admin: true)
251 follower = insert(:user)
254 |> assign(:user, admin)
255 |> put_req_header("accept", "application/json")
256 |> post("/api/pleroma/admin/users/follow", %{
257 "follower" => follower.nickname,
258 "followed" => user.nickname
261 user = User.get_cached_by_id(user.id)
262 follower = User.get_cached_by_id(follower.id)
264 assert User.following?(follower, user)
266 log_entry = Repo.one(ModerationLog)
268 assert ModerationLog.get_log_entry_message(log_entry) ==
269 "@#{admin.nickname} made @#{follower.nickname} follow @#{user.nickname}"
273 describe "/api/pleroma/admin/users/unfollow" do
274 test "allows to force-unfollow another user" do
275 admin = insert(:user, is_admin: true)
277 follower = insert(:user)
279 User.follow(follower, user)
282 |> assign(:user, admin)
283 |> put_req_header("accept", "application/json")
284 |> post("/api/pleroma/admin/users/unfollow", %{
285 "follower" => follower.nickname,
286 "followed" => user.nickname
289 user = User.get_cached_by_id(user.id)
290 follower = User.get_cached_by_id(follower.id)
292 refute User.following?(follower, user)
294 log_entry = Repo.one(ModerationLog)
296 assert ModerationLog.get_log_entry_message(log_entry) ==
297 "@#{admin.nickname} made @#{follower.nickname} unfollow @#{user.nickname}"
301 describe "PUT /api/pleroma/admin/users/tag" do
303 admin = insert(:user, is_admin: true)
304 user1 = insert(:user, %{tags: ["x"]})
305 user2 = insert(:user, %{tags: ["y"]})
306 user3 = insert(:user, %{tags: ["unchanged"]})
310 |> assign(:user, admin)
311 |> put_req_header("accept", "application/json")
313 "/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=#{
315 }&tags[]=foo&tags[]=bar"
318 %{conn: conn, admin: admin, user1: user1, user2: user2, user3: user3}
321 test "it appends specified tags to users with specified nicknames", %{
327 assert json_response(conn, :no_content)
328 assert User.get_cached_by_id(user1.id).tags == ["x", "foo", "bar"]
329 assert User.get_cached_by_id(user2.id).tags == ["y", "foo", "bar"]
331 log_entry = Repo.one(ModerationLog)
334 [user1.nickname, user2.nickname]
335 |> Enum.map(&"@#{&1}")
338 tags = ["foo", "bar"] |> Enum.join(", ")
340 assert ModerationLog.get_log_entry_message(log_entry) ==
341 "@#{admin.nickname} added tags: #{tags} to users: #{users}"
344 test "it does not modify tags of not specified users", %{conn: conn, user3: user3} do
345 assert json_response(conn, :no_content)
346 assert User.get_cached_by_id(user3.id).tags == ["unchanged"]
350 describe "DELETE /api/pleroma/admin/users/tag" do
352 admin = insert(:user, is_admin: true)
353 user1 = insert(:user, %{tags: ["x"]})
354 user2 = insert(:user, %{tags: ["y", "z"]})
355 user3 = insert(:user, %{tags: ["unchanged"]})
359 |> assign(:user, admin)
360 |> put_req_header("accept", "application/json")
362 "/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=#{
367 %{conn: conn, admin: admin, user1: user1, user2: user2, user3: user3}
370 test "it removes specified tags from users with specified nicknames", %{
376 assert json_response(conn, :no_content)
377 assert User.get_cached_by_id(user1.id).tags == []
378 assert User.get_cached_by_id(user2.id).tags == ["y"]
380 log_entry = Repo.one(ModerationLog)
383 [user1.nickname, user2.nickname]
384 |> Enum.map(&"@#{&1}")
387 tags = ["x", "z"] |> Enum.join(", ")
389 assert ModerationLog.get_log_entry_message(log_entry) ==
390 "@#{admin.nickname} removed tags: #{tags} from users: #{users}"
393 test "it does not modify tags of not specified users", %{conn: conn, user3: user3} do
394 assert json_response(conn, :no_content)
395 assert User.get_cached_by_id(user3.id).tags == ["unchanged"]
399 describe "/api/pleroma/admin/users/:nickname/permission_group" do
400 test "GET is giving user_info" do
401 admin = insert(:user, is_admin: true)
405 |> assign(:user, admin)
406 |> put_req_header("accept", "application/json")
407 |> get("/api/pleroma/admin/users/#{admin.nickname}/permission_group/")
409 assert json_response(conn, 200) == %{
411 "is_moderator" => false
415 test "/:right POST, can add to a permission group" do
416 admin = insert(:user, is_admin: true)
421 |> assign(:user, admin)
422 |> put_req_header("accept", "application/json")
423 |> post("/api/pleroma/admin/users/#{user.nickname}/permission_group/admin")
425 assert json_response(conn, 200) == %{
429 log_entry = Repo.one(ModerationLog)
431 assert ModerationLog.get_log_entry_message(log_entry) ==
432 "@#{admin.nickname} made @#{user.nickname} admin"
435 test "/:right POST, can add to a permission group (multiple)" do
436 admin = insert(:user, is_admin: true)
437 user_one = insert(:user)
438 user_two = insert(:user)
442 |> assign(:user, admin)
443 |> put_req_header("accept", "application/json")
444 |> post("/api/pleroma/admin/users/permission_group/admin", %{
445 nicknames: [user_one.nickname, user_two.nickname]
448 assert json_response(conn, 200) == %{
452 log_entry = Repo.one(ModerationLog)
454 assert ModerationLog.get_log_entry_message(log_entry) ==
455 "@#{admin.nickname} made @#{user_one.nickname}, @#{user_two.nickname} admin"
458 test "/:right DELETE, can remove from a permission group" do
459 admin = insert(:user, is_admin: true)
460 user = insert(:user, is_admin: true)
464 |> assign(:user, admin)
465 |> put_req_header("accept", "application/json")
466 |> delete("/api/pleroma/admin/users/#{user.nickname}/permission_group/admin")
468 assert json_response(conn, 200) == %{
472 log_entry = Repo.one(ModerationLog)
474 assert ModerationLog.get_log_entry_message(log_entry) ==
475 "@#{admin.nickname} revoked admin role from @#{user.nickname}"
478 test "/:right DELETE, can remove from a permission group (multiple)" do
479 admin = insert(:user, is_admin: true)
480 user_one = insert(:user, is_admin: true)
481 user_two = insert(:user, is_admin: true)
485 |> assign(:user, admin)
486 |> put_req_header("accept", "application/json")
487 |> delete("/api/pleroma/admin/users/permission_group/admin", %{
488 nicknames: [user_one.nickname, user_two.nickname]
491 assert json_response(conn, 200) == %{
495 log_entry = Repo.one(ModerationLog)
497 assert ModerationLog.get_log_entry_message(log_entry) ==
498 "@#{admin.nickname} revoked admin role from @#{user_one.nickname}, @#{
504 describe "POST /api/pleroma/admin/email_invite, with valid config" do
506 [user: insert(:user, is_admin: true)]
509 clear_config([:instance, :registrations_open]) do
510 Pleroma.Config.put([:instance, :registrations_open], false)
513 clear_config([:instance, :invites_enabled]) do
514 Pleroma.Config.put([:instance, :invites_enabled], true)
517 test "sends invitation and returns 204", %{conn: conn, user: user} do
518 recipient_email = "foo@bar.com"
519 recipient_name = "J. D."
523 |> assign(:user, user)
525 "/api/pleroma/admin/users/email_invite?email=#{recipient_email}&name=#{recipient_name}"
528 assert json_response(conn, :no_content)
530 token_record = List.last(Pleroma.Repo.all(Pleroma.UserInviteToken))
532 refute token_record.used
534 notify_email = Pleroma.Config.get([:instance, :notify_email])
535 instance_name = Pleroma.Config.get([:instance, :name])
538 Pleroma.Emails.UserEmail.user_invitation_email(
545 Swoosh.TestAssertions.assert_email_sent(
546 from: {instance_name, notify_email},
547 to: {recipient_name, recipient_email},
548 html_body: email.html_body
552 test "it returns 403 if requested by a non-admin", %{conn: conn} do
553 non_admin_user = insert(:user)
557 |> assign(:user, non_admin_user)
558 |> post("/api/pleroma/admin/users/email_invite?email=foo@bar.com&name=JD")
560 assert json_response(conn, :forbidden)
564 describe "POST /api/pleroma/admin/users/email_invite, with invalid config" do
566 [user: insert(:user, is_admin: true)]
569 clear_config([:instance, :registrations_open])
570 clear_config([:instance, :invites_enabled])
572 test "it returns 500 if `invites_enabled` is not enabled", %{conn: conn, user: user} do
573 Pleroma.Config.put([:instance, :registrations_open], false)
574 Pleroma.Config.put([:instance, :invites_enabled], false)
578 |> assign(:user, user)
579 |> post("/api/pleroma/admin/users/email_invite?email=foo@bar.com&name=JD")
581 assert json_response(conn, :internal_server_error)
584 test "it returns 500 if `registrations_open` is enabled", %{conn: conn, user: user} do
585 Pleroma.Config.put([:instance, :registrations_open], true)
586 Pleroma.Config.put([:instance, :invites_enabled], true)
590 |> assign(:user, user)
591 |> post("/api/pleroma/admin/users/email_invite?email=foo@bar.com&name=JD")
593 assert json_response(conn, :internal_server_error)
597 test "/api/pleroma/admin/users/:nickname/password_reset" do
598 admin = insert(:user, is_admin: true)
603 |> assign(:user, admin)
604 |> put_req_header("accept", "application/json")
605 |> get("/api/pleroma/admin/users/#{user.nickname}/password_reset")
607 resp = json_response(conn, 200)
609 assert Regex.match?(~r/(http:\/\/|https:\/\/)/, resp["link"])
612 describe "GET /api/pleroma/admin/users" do
614 admin = insert(:user, is_admin: true)
618 |> assign(:user, admin)
620 {:ok, conn: conn, admin: admin}
623 test "renders users array for the first page", %{conn: conn, admin: admin} do
624 user = insert(:user, local: false, tags: ["foo", "bar"])
625 conn = get(conn, "/api/pleroma/admin/users?page=1")
630 "deactivated" => admin.deactivated,
632 "nickname" => admin.nickname,
633 "roles" => %{"admin" => true, "moderator" => false},
636 "avatar" => User.avatar_url(admin) |> MediaProxy.url(),
637 "display_name" => HTML.strip_tags(admin.name || admin.nickname)
640 "deactivated" => user.deactivated,
642 "nickname" => user.nickname,
643 "roles" => %{"admin" => false, "moderator" => false},
645 "tags" => ["foo", "bar"],
646 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
647 "display_name" => HTML.strip_tags(user.name || user.nickname)
650 |> Enum.sort_by(& &1["nickname"])
652 assert json_response(conn, 200) == %{
659 test "renders empty array for the second page", %{conn: conn} do
662 conn = get(conn, "/api/pleroma/admin/users?page=2")
664 assert json_response(conn, 200) == %{
671 test "regular search", %{conn: conn} do
672 user = insert(:user, nickname: "bob")
674 conn = get(conn, "/api/pleroma/admin/users?query=bo")
676 assert json_response(conn, 200) == %{
681 "deactivated" => user.deactivated,
683 "nickname" => user.nickname,
684 "roles" => %{"admin" => false, "moderator" => false},
687 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
688 "display_name" => HTML.strip_tags(user.name || user.nickname)
694 test "search by domain", %{conn: conn} do
695 user = insert(:user, nickname: "nickname@domain.com")
698 conn = get(conn, "/api/pleroma/admin/users?query=domain.com")
700 assert json_response(conn, 200) == %{
705 "deactivated" => user.deactivated,
707 "nickname" => user.nickname,
708 "roles" => %{"admin" => false, "moderator" => false},
711 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
712 "display_name" => HTML.strip_tags(user.name || user.nickname)
718 test "search by full nickname", %{conn: conn} do
719 user = insert(:user, nickname: "nickname@domain.com")
722 conn = get(conn, "/api/pleroma/admin/users?query=nickname@domain.com")
724 assert json_response(conn, 200) == %{
729 "deactivated" => user.deactivated,
731 "nickname" => user.nickname,
732 "roles" => %{"admin" => false, "moderator" => false},
735 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
736 "display_name" => HTML.strip_tags(user.name || user.nickname)
742 test "search by display name", %{conn: conn} do
743 user = insert(:user, name: "Display name")
746 conn = get(conn, "/api/pleroma/admin/users?name=display")
748 assert json_response(conn, 200) == %{
753 "deactivated" => user.deactivated,
755 "nickname" => user.nickname,
756 "roles" => %{"admin" => false, "moderator" => false},
759 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
760 "display_name" => HTML.strip_tags(user.name || user.nickname)
766 test "search by email", %{conn: conn} do
767 user = insert(:user, email: "email@example.com")
770 conn = get(conn, "/api/pleroma/admin/users?email=email@example.com")
772 assert json_response(conn, 200) == %{
777 "deactivated" => user.deactivated,
779 "nickname" => user.nickname,
780 "roles" => %{"admin" => false, "moderator" => false},
783 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
784 "display_name" => HTML.strip_tags(user.name || user.nickname)
790 test "regular search with page size", %{conn: conn} do
791 user = insert(:user, nickname: "aalice")
792 user2 = insert(:user, nickname: "alice")
794 conn1 = get(conn, "/api/pleroma/admin/users?query=a&page_size=1&page=1")
796 assert json_response(conn1, 200) == %{
801 "deactivated" => user.deactivated,
803 "nickname" => user.nickname,
804 "roles" => %{"admin" => false, "moderator" => false},
807 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
808 "display_name" => HTML.strip_tags(user.name || user.nickname)
813 conn2 = get(conn, "/api/pleroma/admin/users?query=a&page_size=1&page=2")
815 assert json_response(conn2, 200) == %{
820 "deactivated" => user2.deactivated,
822 "nickname" => user2.nickname,
823 "roles" => %{"admin" => false, "moderator" => false},
826 "avatar" => User.avatar_url(user2) |> MediaProxy.url(),
827 "display_name" => HTML.strip_tags(user2.name || user2.nickname)
833 test "only local users" do
834 admin = insert(:user, is_admin: true, nickname: "john")
835 user = insert(:user, nickname: "bob")
837 insert(:user, nickname: "bobb", local: false)
841 |> assign(:user, admin)
842 |> get("/api/pleroma/admin/users?query=bo&filters=local")
844 assert json_response(conn, 200) == %{
849 "deactivated" => user.deactivated,
851 "nickname" => user.nickname,
852 "roles" => %{"admin" => false, "moderator" => false},
855 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
856 "display_name" => HTML.strip_tags(user.name || user.nickname)
862 test "only local users with no query", %{admin: old_admin} do
863 admin = insert(:user, is_admin: true, nickname: "john")
864 user = insert(:user, nickname: "bob")
866 insert(:user, nickname: "bobb", local: false)
870 |> assign(:user, admin)
871 |> get("/api/pleroma/admin/users?filters=local")
876 "deactivated" => user.deactivated,
878 "nickname" => user.nickname,
879 "roles" => %{"admin" => false, "moderator" => false},
882 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
883 "display_name" => HTML.strip_tags(user.name || user.nickname)
886 "deactivated" => admin.deactivated,
888 "nickname" => admin.nickname,
889 "roles" => %{"admin" => true, "moderator" => false},
892 "avatar" => User.avatar_url(admin) |> MediaProxy.url(),
893 "display_name" => HTML.strip_tags(admin.name || admin.nickname)
896 "deactivated" => false,
897 "id" => old_admin.id,
899 "nickname" => old_admin.nickname,
900 "roles" => %{"admin" => true, "moderator" => false},
902 "avatar" => User.avatar_url(old_admin) |> MediaProxy.url(),
903 "display_name" => HTML.strip_tags(old_admin.name || old_admin.nickname)
906 |> Enum.sort_by(& &1["nickname"])
908 assert json_response(conn, 200) == %{
915 test "load only admins", %{conn: conn, admin: admin} do
916 second_admin = insert(:user, is_admin: true)
920 conn = get(conn, "/api/pleroma/admin/users?filters=is_admin")
925 "deactivated" => false,
927 "nickname" => admin.nickname,
928 "roles" => %{"admin" => true, "moderator" => false},
929 "local" => admin.local,
931 "avatar" => User.avatar_url(admin) |> MediaProxy.url(),
932 "display_name" => HTML.strip_tags(admin.name || admin.nickname)
935 "deactivated" => false,
936 "id" => second_admin.id,
937 "nickname" => second_admin.nickname,
938 "roles" => %{"admin" => true, "moderator" => false},
939 "local" => second_admin.local,
941 "avatar" => User.avatar_url(second_admin) |> MediaProxy.url(),
942 "display_name" => HTML.strip_tags(second_admin.name || second_admin.nickname)
945 |> Enum.sort_by(& &1["nickname"])
947 assert json_response(conn, 200) == %{
954 test "load only moderators", %{conn: conn} do
955 moderator = insert(:user, is_moderator: true)
959 conn = get(conn, "/api/pleroma/admin/users?filters=is_moderator")
961 assert json_response(conn, 200) == %{
966 "deactivated" => false,
967 "id" => moderator.id,
968 "nickname" => moderator.nickname,
969 "roles" => %{"admin" => false, "moderator" => true},
970 "local" => moderator.local,
972 "avatar" => User.avatar_url(moderator) |> MediaProxy.url(),
973 "display_name" => HTML.strip_tags(moderator.name || moderator.nickname)
979 test "load users with tags list", %{conn: conn} do
980 user1 = insert(:user, tags: ["first"])
981 user2 = insert(:user, tags: ["second"])
985 conn = get(conn, "/api/pleroma/admin/users?tags[]=first&tags[]=second")
990 "deactivated" => false,
992 "nickname" => user1.nickname,
993 "roles" => %{"admin" => false, "moderator" => false},
994 "local" => user1.local,
996 "avatar" => User.avatar_url(user1) |> MediaProxy.url(),
997 "display_name" => HTML.strip_tags(user1.name || user1.nickname)
1000 "deactivated" => false,
1002 "nickname" => user2.nickname,
1003 "roles" => %{"admin" => false, "moderator" => false},
1004 "local" => user2.local,
1005 "tags" => ["second"],
1006 "avatar" => User.avatar_url(user2) |> MediaProxy.url(),
1007 "display_name" => HTML.strip_tags(user2.name || user2.nickname)
1010 |> Enum.sort_by(& &1["nickname"])
1012 assert json_response(conn, 200) == %{
1019 test "it works with multiple filters" do
1020 admin = insert(:user, nickname: "john", is_admin: true)
1021 user = insert(:user, nickname: "bob", local: false, deactivated: true)
1023 insert(:user, nickname: "ken", local: true, deactivated: true)
1024 insert(:user, nickname: "bobb", local: false, deactivated: false)
1028 |> assign(:user, admin)
1029 |> get("/api/pleroma/admin/users?filters=deactivated,external")
1031 assert json_response(conn, 200) == %{
1036 "deactivated" => user.deactivated,
1038 "nickname" => user.nickname,
1039 "roles" => %{"admin" => false, "moderator" => false},
1040 "local" => user.local,
1042 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
1043 "display_name" => HTML.strip_tags(user.name || user.nickname)
1049 test "it omits relay user", %{admin: admin} do
1050 assert %User{} = Relay.get_actor()
1054 |> assign(:user, admin)
1055 |> get("/api/pleroma/admin/users")
1057 assert json_response(conn, 200) == %{
1062 "deactivated" => admin.deactivated,
1064 "nickname" => admin.nickname,
1065 "roles" => %{"admin" => true, "moderator" => false},
1068 "avatar" => User.avatar_url(admin) |> MediaProxy.url(),
1069 "display_name" => HTML.strip_tags(admin.name || admin.nickname)
1076 test "PATCH /api/pleroma/admin/users/activate" do
1077 admin = insert(:user, is_admin: true)
1078 user_one = insert(:user, deactivated: true)
1079 user_two = insert(:user, deactivated: true)
1083 |> assign(:user, admin)
1085 "/api/pleroma/admin/users/activate",
1086 %{nicknames: [user_one.nickname, user_two.nickname]}
1089 response = json_response(conn, 200)
1090 assert Enum.map(response["users"], & &1["deactivated"]) == [false, false]
1092 log_entry = Repo.one(ModerationLog)
1094 assert ModerationLog.get_log_entry_message(log_entry) ==
1095 "@#{admin.nickname} activated users: @#{user_one.nickname}, @#{user_two.nickname}"
1098 test "PATCH /api/pleroma/admin/users/deactivate" do
1099 admin = insert(:user, is_admin: true)
1100 user_one = insert(:user, deactivated: false)
1101 user_two = insert(:user, deactivated: false)
1105 |> assign(:user, admin)
1107 "/api/pleroma/admin/users/deactivate",
1108 %{nicknames: [user_one.nickname, user_two.nickname]}
1111 response = json_response(conn, 200)
1112 assert Enum.map(response["users"], & &1["deactivated"]) == [true, true]
1114 log_entry = Repo.one(ModerationLog)
1116 assert ModerationLog.get_log_entry_message(log_entry) ==
1117 "@#{admin.nickname} deactivated users: @#{user_one.nickname}, @#{user_two.nickname}"
1120 test "PATCH /api/pleroma/admin/users/:nickname/toggle_activation" do
1121 admin = insert(:user, is_admin: true)
1122 user = insert(:user)
1126 |> assign(:user, admin)
1127 |> patch("/api/pleroma/admin/users/#{user.nickname}/toggle_activation")
1129 assert json_response(conn, 200) ==
1131 "deactivated" => !user.deactivated,
1133 "nickname" => user.nickname,
1134 "roles" => %{"admin" => false, "moderator" => false},
1137 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
1138 "display_name" => HTML.strip_tags(user.name || user.nickname)
1141 log_entry = Repo.one(ModerationLog)
1143 assert ModerationLog.get_log_entry_message(log_entry) ==
1144 "@#{admin.nickname} deactivated users: @#{user.nickname}"
1147 describe "POST /api/pleroma/admin/users/invite_token" do
1149 admin = insert(:user, is_admin: true)
1153 |> assign(:user, admin)
1158 test "without options", %{conn: conn} do
1159 conn = post(conn, "/api/pleroma/admin/users/invite_token")
1161 invite_json = json_response(conn, 200)
1162 invite = UserInviteToken.find_by_token!(invite_json["token"])
1164 refute invite.expires_at
1165 refute invite.max_use
1166 assert invite.invite_type == "one_time"
1169 test "with expires_at", %{conn: conn} do
1171 post(conn, "/api/pleroma/admin/users/invite_token", %{
1172 "expires_at" => Date.to_string(Date.utc_today())
1175 invite_json = json_response(conn, 200)
1176 invite = UserInviteToken.find_by_token!(invite_json["token"])
1179 assert invite.expires_at == Date.utc_today()
1180 refute invite.max_use
1181 assert invite.invite_type == "date_limited"
1184 test "with max_use", %{conn: conn} do
1185 conn = post(conn, "/api/pleroma/admin/users/invite_token", %{"max_use" => 150})
1187 invite_json = json_response(conn, 200)
1188 invite = UserInviteToken.find_by_token!(invite_json["token"])
1190 refute invite.expires_at
1191 assert invite.max_use == 150
1192 assert invite.invite_type == "reusable"
1195 test "with max use and expires_at", %{conn: conn} do
1197 post(conn, "/api/pleroma/admin/users/invite_token", %{
1199 "expires_at" => Date.to_string(Date.utc_today())
1202 invite_json = json_response(conn, 200)
1203 invite = UserInviteToken.find_by_token!(invite_json["token"])
1205 assert invite.expires_at == Date.utc_today()
1206 assert invite.max_use == 150
1207 assert invite.invite_type == "reusable_date_limited"
1211 describe "GET /api/pleroma/admin/users/invites" do
1213 admin = insert(:user, is_admin: true)
1217 |> assign(:user, admin)
1222 test "no invites", %{conn: conn} do
1223 conn = get(conn, "/api/pleroma/admin/users/invites")
1225 assert json_response(conn, 200) == %{"invites" => []}
1228 test "with invite", %{conn: conn} do
1229 {:ok, invite} = UserInviteToken.create_invite()
1231 conn = get(conn, "/api/pleroma/admin/users/invites")
1233 assert json_response(conn, 200) == %{
1236 "expires_at" => nil,
1238 "invite_type" => "one_time",
1240 "token" => invite.token,
1249 describe "POST /api/pleroma/admin/users/revoke_invite" do
1250 test "with token" do
1251 admin = insert(:user, is_admin: true)
1252 {:ok, invite} = UserInviteToken.create_invite()
1256 |> assign(:user, admin)
1257 |> post("/api/pleroma/admin/users/revoke_invite", %{"token" => invite.token})
1259 assert json_response(conn, 200) == %{
1260 "expires_at" => nil,
1262 "invite_type" => "one_time",
1264 "token" => invite.token,
1270 test "with invalid token" do
1271 admin = insert(:user, is_admin: true)
1275 |> assign(:user, admin)
1276 |> post("/api/pleroma/admin/users/revoke_invite", %{"token" => "foo"})
1278 assert json_response(conn, :not_found) == "Not found"
1282 describe "GET /api/pleroma/admin/reports/:id" do
1283 setup %{conn: conn} do
1284 admin = insert(:user, is_admin: true)
1286 %{conn: assign(conn, :user, admin)}
1289 test "returns report by its id", %{conn: conn} do
1290 [reporter, target_user] = insert_pair(:user)
1291 activity = insert(:note_activity, user: target_user)
1293 {:ok, %{id: report_id}} =
1294 CommonAPI.report(reporter, %{
1295 "account_id" => target_user.id,
1296 "comment" => "I feel offended",
1297 "status_ids" => [activity.id]
1302 |> get("/api/pleroma/admin/reports/#{report_id}")
1303 |> json_response(:ok)
1305 assert response["id"] == report_id
1308 test "returns 404 when report id is invalid", %{conn: conn} do
1309 conn = get(conn, "/api/pleroma/admin/reports/test")
1311 assert json_response(conn, :not_found) == "Not found"
1315 describe "PUT /api/pleroma/admin/reports/:id" do
1316 setup %{conn: conn} do
1317 admin = insert(:user, is_admin: true)
1318 [reporter, target_user] = insert_pair(:user)
1319 activity = insert(:note_activity, user: target_user)
1321 {:ok, %{id: report_id}} =
1322 CommonAPI.report(reporter, %{
1323 "account_id" => target_user.id,
1324 "comment" => "I feel offended",
1325 "status_ids" => [activity.id]
1328 %{conn: assign(conn, :user, admin), id: report_id, admin: admin}
1331 test "mark report as resolved", %{conn: conn, id: id, admin: admin} do
1334 |> put("/api/pleroma/admin/reports/#{id}", %{"state" => "resolved"})
1335 |> json_response(:ok)
1337 assert response["state"] == "resolved"
1339 log_entry = Repo.one(ModerationLog)
1341 assert ModerationLog.get_log_entry_message(log_entry) ==
1342 "@#{admin.nickname} updated report ##{id} with 'resolved' state"
1345 test "closes report", %{conn: conn, id: id, admin: admin} do
1348 |> put("/api/pleroma/admin/reports/#{id}", %{"state" => "closed"})
1349 |> json_response(:ok)
1351 assert response["state"] == "closed"
1353 log_entry = Repo.one(ModerationLog)
1355 assert ModerationLog.get_log_entry_message(log_entry) ==
1356 "@#{admin.nickname} updated report ##{id} with 'closed' state"
1359 test "returns 400 when state is unknown", %{conn: conn, id: id} do
1362 |> put("/api/pleroma/admin/reports/#{id}", %{"state" => "test"})
1364 assert json_response(conn, :bad_request) == "Unsupported state"
1367 test "returns 404 when report is not exist", %{conn: conn} do
1370 |> put("/api/pleroma/admin/reports/test", %{"state" => "closed"})
1372 assert json_response(conn, :not_found) == "Not found"
1376 describe "GET /api/pleroma/admin/reports" do
1377 setup %{conn: conn} do
1378 admin = insert(:user, is_admin: true)
1380 %{conn: assign(conn, :user, admin)}
1383 test "returns empty response when no reports created", %{conn: conn} do
1386 |> get("/api/pleroma/admin/reports")
1387 |> json_response(:ok)
1389 assert Enum.empty?(response["reports"])
1390 assert response["total"] == 0
1393 test "returns reports", %{conn: conn} do
1394 [reporter, target_user] = insert_pair(:user)
1395 activity = insert(:note_activity, user: target_user)
1397 {:ok, %{id: report_id}} =
1398 CommonAPI.report(reporter, %{
1399 "account_id" => target_user.id,
1400 "comment" => "I feel offended",
1401 "status_ids" => [activity.id]
1406 |> get("/api/pleroma/admin/reports")
1407 |> json_response(:ok)
1409 [report] = response["reports"]
1411 assert length(response["reports"]) == 1
1412 assert report["id"] == report_id
1414 assert response["total"] == 1
1417 test "returns reports with specified state", %{conn: conn} do
1418 [reporter, target_user] = insert_pair(:user)
1419 activity = insert(:note_activity, user: target_user)
1421 {:ok, %{id: first_report_id}} =
1422 CommonAPI.report(reporter, %{
1423 "account_id" => target_user.id,
1424 "comment" => "I feel offended",
1425 "status_ids" => [activity.id]
1428 {:ok, %{id: second_report_id}} =
1429 CommonAPI.report(reporter, %{
1430 "account_id" => target_user.id,
1431 "comment" => "I don't like this user"
1434 CommonAPI.update_report_state(second_report_id, "closed")
1438 |> get("/api/pleroma/admin/reports", %{
1441 |> json_response(:ok)
1443 [open_report] = response["reports"]
1445 assert length(response["reports"]) == 1
1446 assert open_report["id"] == first_report_id
1448 assert response["total"] == 1
1452 |> get("/api/pleroma/admin/reports", %{
1455 |> json_response(:ok)
1457 [closed_report] = response["reports"]
1459 assert length(response["reports"]) == 1
1460 assert closed_report["id"] == second_report_id
1462 assert response["total"] == 1
1466 |> get("/api/pleroma/admin/reports", %{
1467 "state" => "resolved"
1469 |> json_response(:ok)
1471 assert Enum.empty?(response["reports"])
1472 assert response["total"] == 0
1475 test "returns 403 when requested by a non-admin" do
1476 user = insert(:user)
1480 |> assign(:user, user)
1481 |> get("/api/pleroma/admin/reports")
1483 assert json_response(conn, :forbidden) == %{"error" => "User is not admin."}
1486 test "returns 403 when requested by anonymous" do
1489 |> get("/api/pleroma/admin/reports")
1491 assert json_response(conn, :forbidden) == %{"error" => "Invalid credentials."}
1496 describe "POST /api/pleroma/admin/reports/:id/respond" do
1497 setup %{conn: conn} do
1498 admin = insert(:user, is_admin: true)
1500 %{conn: assign(conn, :user, admin), admin: admin}
1503 test "returns created dm", %{conn: conn, admin: admin} do
1504 [reporter, target_user] = insert_pair(:user)
1505 activity = insert(:note_activity, user: target_user)
1507 {:ok, %{id: report_id}} =
1508 CommonAPI.report(reporter, %{
1509 "account_id" => target_user.id,
1510 "comment" => "I feel offended",
1511 "status_ids" => [activity.id]
1516 |> post("/api/pleroma/admin/reports/#{report_id}/respond", %{
1517 "status" => "I will check it out"
1519 |> json_response(:ok)
1521 recipients = Enum.map(response["mentions"], & &1["username"])
1523 assert reporter.nickname in recipients
1524 assert response["content"] == "I will check it out"
1525 assert response["visibility"] == "direct"
1527 log_entry = Repo.one(ModerationLog)
1529 assert ModerationLog.get_log_entry_message(log_entry) ==
1530 "@#{admin.nickname} responded with 'I will check it out' to report ##{
1535 test "returns 400 when status is missing", %{conn: conn} do
1536 conn = post(conn, "/api/pleroma/admin/reports/test/respond")
1538 assert json_response(conn, :bad_request) == "Invalid parameters"
1541 test "returns 404 when report id is invalid", %{conn: conn} do
1543 post(conn, "/api/pleroma/admin/reports/test/respond", %{
1547 assert json_response(conn, :not_found) == "Not found"
1551 describe "PUT /api/pleroma/admin/statuses/:id" do
1552 setup %{conn: conn} do
1553 admin = insert(:user, is_admin: true)
1554 activity = insert(:note_activity)
1556 %{conn: assign(conn, :user, admin), id: activity.id, admin: admin}
1559 test "toggle sensitive flag", %{conn: conn, id: id, admin: admin} do
1562 |> put("/api/pleroma/admin/statuses/#{id}", %{"sensitive" => "true"})
1563 |> json_response(:ok)
1565 assert response["sensitive"]
1567 log_entry = Repo.one(ModerationLog)
1569 assert ModerationLog.get_log_entry_message(log_entry) ==
1570 "@#{admin.nickname} updated status ##{id}, set sensitive: 'true'"
1574 |> put("/api/pleroma/admin/statuses/#{id}", %{"sensitive" => "false"})
1575 |> json_response(:ok)
1577 refute response["sensitive"]
1580 test "change visibility flag", %{conn: conn, id: id, admin: admin} do
1583 |> put("/api/pleroma/admin/statuses/#{id}", %{"visibility" => "public"})
1584 |> json_response(:ok)
1586 assert response["visibility"] == "public"
1588 log_entry = Repo.one(ModerationLog)
1590 assert ModerationLog.get_log_entry_message(log_entry) ==
1591 "@#{admin.nickname} updated status ##{id}, set visibility: 'public'"
1595 |> put("/api/pleroma/admin/statuses/#{id}", %{"visibility" => "private"})
1596 |> json_response(:ok)
1598 assert response["visibility"] == "private"
1602 |> put("/api/pleroma/admin/statuses/#{id}", %{"visibility" => "unlisted"})
1603 |> json_response(:ok)
1605 assert response["visibility"] == "unlisted"
1608 test "returns 400 when visibility is unknown", %{conn: conn, id: id} do
1611 |> put("/api/pleroma/admin/statuses/#{id}", %{"visibility" => "test"})
1613 assert json_response(conn, :bad_request) == "Unsupported visibility"
1617 describe "DELETE /api/pleroma/admin/statuses/:id" do
1618 setup %{conn: conn} do
1619 admin = insert(:user, is_admin: true)
1620 activity = insert(:note_activity)
1622 %{conn: assign(conn, :user, admin), id: activity.id, admin: admin}
1625 test "deletes status", %{conn: conn, id: id, admin: admin} do
1627 |> delete("/api/pleroma/admin/statuses/#{id}")
1628 |> json_response(:ok)
1630 refute Activity.get_by_id(id)
1632 log_entry = Repo.one(ModerationLog)
1634 assert ModerationLog.get_log_entry_message(log_entry) ==
1635 "@#{admin.nickname} deleted status ##{id}"
1638 test "returns error when status is not exist", %{conn: conn} do
1641 |> delete("/api/pleroma/admin/statuses/test")
1643 assert json_response(conn, :bad_request) == "Could not delete"
1647 describe "GET /api/pleroma/admin/config" do
1648 setup %{conn: conn} do
1649 admin = insert(:user, is_admin: true)
1651 %{conn: assign(conn, :user, admin)}
1654 test "without any settings in db", %{conn: conn} do
1655 conn = get(conn, "/api/pleroma/admin/config")
1657 assert json_response(conn, 200) == %{"configs" => []}
1660 test "with settings in db", %{conn: conn} do
1661 config1 = insert(:config)
1662 config2 = insert(:config)
1664 conn = get(conn, "/api/pleroma/admin/config")
1677 } = json_response(conn, 200)
1679 assert key1 == config1.key
1680 assert key2 == config2.key
1684 describe "POST /api/pleroma/admin/config" do
1685 setup %{conn: conn} do
1686 admin = insert(:user, is_admin: true)
1688 temp_file = "config/test.exported_from_db.secret.exs"
1691 Application.delete_env(:pleroma, :key1)
1692 Application.delete_env(:pleroma, :key2)
1693 Application.delete_env(:pleroma, :key3)
1694 Application.delete_env(:pleroma, :key4)
1695 Application.delete_env(:pleroma, :keyaa1)
1696 Application.delete_env(:pleroma, :keyaa2)
1697 Application.delete_env(:pleroma, Pleroma.Web.Endpoint.NotReal)
1698 Application.delete_env(:pleroma, Pleroma.Captcha.NotReal)
1699 :ok = File.rm(temp_file)
1702 %{conn: assign(conn, :user, admin)}
1705 clear_config([:instance, :dynamic_configuration]) do
1706 Pleroma.Config.put([:instance, :dynamic_configuration], true)
1709 test "create new config setting in db", %{conn: conn} do
1711 post(conn, "/api/pleroma/admin/config", %{
1713 %{group: "pleroma", key: "key1", value: "value1"},
1716 key: "Ueberauth.Strategy.Twitter.OAuth",
1717 value: [%{"tuple" => [":consumer_secret", "aaaa"]}]
1723 ":nested_1" => "nested_value1",
1725 %{":nested_22" => "nested_value222"},
1726 %{":nested_33" => %{":nested_44" => "nested_444"}}
1734 %{"nested_3" => ":nested_3", "nested_33" => "nested_33"},
1735 %{"nested_4" => true}
1741 value: %{":nested_5" => ":upload", "endpoint" => "https://example.com"}
1746 value: %{"tuple" => ["string", "Pleroma.Captcha.NotReal", []]}
1751 assert json_response(conn, 200) == %{
1754 "group" => "pleroma",
1759 "group" => "ueberauth",
1760 "key" => "Ueberauth.Strategy.Twitter.OAuth",
1761 "value" => [%{"tuple" => [":consumer_secret", "aaaa"]}]
1764 "group" => "pleroma",
1767 ":nested_1" => "nested_value1",
1769 %{":nested_22" => "nested_value222"},
1770 %{":nested_33" => %{":nested_44" => "nested_444"}}
1775 "group" => "pleroma",
1778 %{"nested_3" => ":nested_3", "nested_33" => "nested_33"},
1779 %{"nested_4" => true}
1783 "group" => "pleroma",
1785 "value" => %{"endpoint" => "https://example.com", ":nested_5" => ":upload"}
1790 "value" => %{"tuple" => ["string", "Pleroma.Captcha.NotReal", []]}
1795 assert Application.get_env(:pleroma, :key1) == "value1"
1797 assert Application.get_env(:pleroma, :key2) == %{
1798 nested_1: "nested_value1",
1800 %{nested_22: "nested_value222"},
1801 %{nested_33: %{nested_44: "nested_444"}}
1805 assert Application.get_env(:pleroma, :key3) == [
1806 %{"nested_3" => :nested_3, "nested_33" => "nested_33"},
1807 %{"nested_4" => true}
1810 assert Application.get_env(:pleroma, :key4) == %{
1811 "endpoint" => "https://example.com",
1815 assert Application.get_env(:idna, :key5) == {"string", Pleroma.Captcha.NotReal, []}
1818 test "update config setting & delete", %{conn: conn} do
1819 config1 = insert(:config, key: "keyaa1")
1820 config2 = insert(:config, key: "keyaa2")
1824 key: "Ueberauth.Strategy.Microsoft.OAuth",
1825 value: :erlang.term_to_binary([])
1829 post(conn, "/api/pleroma/admin/config", %{
1831 %{group: config1.group, key: config1.key, value: "another_value"},
1832 %{group: config2.group, key: config2.key, delete: "true"},
1835 key: "Ueberauth.Strategy.Microsoft.OAuth",
1841 assert json_response(conn, 200) == %{
1844 "group" => "pleroma",
1845 "key" => config1.key,
1846 "value" => "another_value"
1851 assert Application.get_env(:pleroma, :keyaa1) == "another_value"
1852 refute Application.get_env(:pleroma, :keyaa2)
1855 test "common config example", %{conn: conn} do
1857 post(conn, "/api/pleroma/admin/config", %{
1860 "group" => "pleroma",
1861 "key" => "Pleroma.Captcha.NotReal",
1863 %{"tuple" => [":enabled", false]},
1864 %{"tuple" => [":method", "Pleroma.Captcha.Kocaptcha"]},
1865 %{"tuple" => [":seconds_valid", 60]},
1866 %{"tuple" => [":path", ""]},
1867 %{"tuple" => [":key1", nil]},
1868 %{"tuple" => [":partial_chain", "&:hackney_connect.partial_chain/1"]},
1869 %{"tuple" => [":regex1", "~r/https:\/\/example.com/"]},
1870 %{"tuple" => [":regex2", "~r/https:\/\/example.com/u"]},
1871 %{"tuple" => [":regex3", "~r/https:\/\/example.com/i"]},
1872 %{"tuple" => [":regex4", "~r/https:\/\/example.com/s"]}
1878 assert json_response(conn, 200) == %{
1881 "group" => "pleroma",
1882 "key" => "Pleroma.Captcha.NotReal",
1884 %{"tuple" => [":enabled", false]},
1885 %{"tuple" => [":method", "Pleroma.Captcha.Kocaptcha"]},
1886 %{"tuple" => [":seconds_valid", 60]},
1887 %{"tuple" => [":path", ""]},
1888 %{"tuple" => [":key1", nil]},
1889 %{"tuple" => [":partial_chain", "&:hackney_connect.partial_chain/1"]},
1890 %{"tuple" => [":regex1", "~r/https:\\/\\/example.com/"]},
1891 %{"tuple" => [":regex2", "~r/https:\\/\\/example.com/u"]},
1892 %{"tuple" => [":regex3", "~r/https:\\/\\/example.com/i"]},
1893 %{"tuple" => [":regex4", "~r/https:\\/\\/example.com/s"]}
1900 test "tuples with more than two values", %{conn: conn} do
1902 post(conn, "/api/pleroma/admin/config", %{
1905 "group" => "pleroma",
1906 "key" => "Pleroma.Web.Endpoint.NotReal",
1922 "/api/v1/streaming",
1923 "Pleroma.Web.MastodonAPI.WebsocketHandler",
1930 "Phoenix.Endpoint.CowboyWebSocket",
1933 "Phoenix.Transports.WebSocket",
1936 "Pleroma.Web.Endpoint",
1937 "Pleroma.Web.UserSocket",
1948 "Phoenix.Endpoint.Cowboy2Handler",
1949 %{"tuple" => ["Pleroma.Web.Endpoint", []]}
1966 assert json_response(conn, 200) == %{
1969 "group" => "pleroma",
1970 "key" => "Pleroma.Web.Endpoint.NotReal",
1986 "/api/v1/streaming",
1987 "Pleroma.Web.MastodonAPI.WebsocketHandler",
1994 "Phoenix.Endpoint.CowboyWebSocket",
1997 "Phoenix.Transports.WebSocket",
2000 "Pleroma.Web.Endpoint",
2001 "Pleroma.Web.UserSocket",
2012 "Phoenix.Endpoint.Cowboy2Handler",
2013 %{"tuple" => ["Pleroma.Web.Endpoint", []]}
2031 test "settings with nesting map", %{conn: conn} do
2033 post(conn, "/api/pleroma/admin/config", %{
2036 "group" => "pleroma",
2039 %{"tuple" => [":key2", "some_val"]},
2044 ":max_options" => 20,
2045 ":max_option_chars" => 200,
2046 ":min_expiration" => 0,
2047 ":max_expiration" => 31_536_000,
2049 ":max_options" => 20,
2050 ":max_option_chars" => 200,
2051 ":min_expiration" => 0,
2052 ":max_expiration" => 31_536_000
2062 assert json_response(conn, 200) ==
2066 "group" => "pleroma",
2069 %{"tuple" => [":key2", "some_val"]},
2074 ":max_expiration" => 31_536_000,
2075 ":max_option_chars" => 200,
2076 ":max_options" => 20,
2077 ":min_expiration" => 0,
2079 ":max_expiration" => 31_536_000,
2080 ":max_option_chars" => 200,
2081 ":max_options" => 20,
2082 ":min_expiration" => 0
2093 test "value as map", %{conn: conn} do
2095 post(conn, "/api/pleroma/admin/config", %{
2098 "group" => "pleroma",
2100 "value" => %{"key" => "some_val"}
2105 assert json_response(conn, 200) ==
2109 "group" => "pleroma",
2111 "value" => %{"key" => "some_val"}
2117 test "dispatch setting", %{conn: conn} do
2119 post(conn, "/api/pleroma/admin/config", %{
2122 "group" => "pleroma",
2123 "key" => "Pleroma.Web.Endpoint.NotReal",
2129 %{"tuple" => [":ip", %{"tuple" => [127, 0, 0, 1]}]},
2130 %{"tuple" => [":dispatch", ["{:_,
2132 {\"/api/v1/streaming\", Pleroma.Web.MastodonAPI.WebsocketHandler, []},
2133 {\"/websocket\", Phoenix.Endpoint.CowboyWebSocket,
2134 {Phoenix.Transports.WebSocket,
2135 {Pleroma.Web.Endpoint, Pleroma.Web.UserSocket, [path: \"/websocket\"]}}},
2136 {:_, Phoenix.Endpoint.Cowboy2Handler, {Pleroma.Web.Endpoint, []}}
2147 "{:_, [{\"/api/v1/streaming\", Pleroma.Web.MastodonAPI.WebsocketHandler, []}, " <>
2148 "{\"/websocket\", Phoenix.Endpoint.CowboyWebSocket, {Phoenix.Transports.WebSocket, " <>
2149 "{Pleroma.Web.Endpoint, Pleroma.Web.UserSocket, [path: \"/websocket\"]}}}, " <>
2150 "{:_, Phoenix.Endpoint.Cowboy2Handler, {Pleroma.Web.Endpoint, []}}]}"
2152 assert json_response(conn, 200) == %{
2155 "group" => "pleroma",
2156 "key" => "Pleroma.Web.Endpoint.NotReal",
2162 %{"tuple" => [":ip", %{"tuple" => [127, 0, 0, 1]}]},
2180 test "queues key as atom", %{conn: conn} do
2182 post(conn, "/api/pleroma/admin/config", %{
2188 %{"tuple" => [":federator_incoming", 50]},
2189 %{"tuple" => [":federator_outgoing", 50]},
2190 %{"tuple" => [":web_push", 50]},
2191 %{"tuple" => [":mailer", 10]},
2192 %{"tuple" => [":transmogrifier", 20]},
2193 %{"tuple" => [":scheduled_activities", 10]},
2194 %{"tuple" => [":background", 5]}
2200 assert json_response(conn, 200) == %{
2206 %{"tuple" => [":federator_incoming", 50]},
2207 %{"tuple" => [":federator_outgoing", 50]},
2208 %{"tuple" => [":web_push", 50]},
2209 %{"tuple" => [":mailer", 10]},
2210 %{"tuple" => [":transmogrifier", 20]},
2211 %{"tuple" => [":scheduled_activities", 10]},
2212 %{"tuple" => [":background", 5]}
2219 test "delete part of settings by atom subkeys", %{conn: conn} do
2223 value: :erlang.term_to_binary(subkey1: "val1", subkey2: "val2", subkey3: "val3")
2227 post(conn, "/api/pleroma/admin/config", %{
2230 group: config.group,
2232 subkeys: [":subkey1", ":subkey3"],
2239 json_response(conn, 200) == %{
2242 "group" => "pleroma",
2244 "value" => [%{"tuple" => [":subkey2", "val2"]}]
2252 describe "config mix tasks run" do
2253 setup %{conn: conn} do
2254 admin = insert(:user, is_admin: true)
2256 temp_file = "config/test.exported_from_db.secret.exs"
2258 Mix.shell(Mix.Shell.Quiet)
2261 Mix.shell(Mix.Shell.IO)
2262 :ok = File.rm(temp_file)
2265 %{conn: assign(conn, :user, admin), admin: admin}
2268 clear_config([:instance, :dynamic_configuration]) do
2269 Pleroma.Config.put([:instance, :dynamic_configuration], true)
2272 test "transfer settings to DB and to file", %{conn: conn, admin: admin} do
2273 assert Pleroma.Repo.all(Pleroma.Web.AdminAPI.Config) == []
2274 conn = get(conn, "/api/pleroma/admin/config/migrate_to_db")
2275 assert json_response(conn, 200) == %{}
2276 assert Pleroma.Repo.all(Pleroma.Web.AdminAPI.Config) > 0
2280 |> assign(:user, admin)
2281 |> get("/api/pleroma/admin/config/migrate_from_db")
2283 assert json_response(conn, 200) == %{}
2284 assert Pleroma.Repo.all(Pleroma.Web.AdminAPI.Config) == []
2288 describe "GET /api/pleroma/admin/users/:nickname/statuses" do
2290 admin = insert(:user, is_admin: true)
2291 user = insert(:user)
2293 date1 = (DateTime.to_unix(DateTime.utc_now()) + 2000) |> DateTime.from_unix!()
2294 date2 = (DateTime.to_unix(DateTime.utc_now()) + 1000) |> DateTime.from_unix!()
2295 date3 = (DateTime.to_unix(DateTime.utc_now()) + 3000) |> DateTime.from_unix!()
2297 insert(:note_activity, user: user, published: date1)
2298 insert(:note_activity, user: user, published: date2)
2299 insert(:note_activity, user: user, published: date3)
2303 |> assign(:user, admin)
2305 {:ok, conn: conn, user: user}
2308 test "renders user's statuses", %{conn: conn, user: user} do
2309 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses")
2311 assert json_response(conn, 200) |> length() == 3
2314 test "renders user's statuses with a limit", %{conn: conn, user: user} do
2315 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses?page_size=2")
2317 assert json_response(conn, 200) |> length() == 2
2320 test "doesn't return private statuses by default", %{conn: conn, user: user} do
2321 {:ok, _private_status} =
2322 CommonAPI.post(user, %{"status" => "private", "visibility" => "private"})
2324 {:ok, _public_status} =
2325 CommonAPI.post(user, %{"status" => "public", "visibility" => "public"})
2327 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses")
2329 assert json_response(conn, 200) |> length() == 4
2332 test "returns private statuses with godmode on", %{conn: conn, user: user} do
2333 {:ok, _private_status} =
2334 CommonAPI.post(user, %{"status" => "private", "visibility" => "private"})
2336 {:ok, _public_status} =
2337 CommonAPI.post(user, %{"status" => "public", "visibility" => "public"})
2339 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses?godmode=true")
2341 assert json_response(conn, 200) |> length() == 5
2345 describe "GET /api/pleroma/admin/moderation_log" do
2346 setup %{conn: conn} do
2347 admin = insert(:user, is_admin: true)
2348 moderator = insert(:user, is_moderator: true)
2350 %{conn: assign(conn, :user, admin), admin: admin, moderator: moderator}
2353 test "returns the log", %{conn: conn, admin: admin} do
2354 Repo.insert(%ModerationLog{
2358 "nickname" => admin.nickname,
2361 action: "relay_follow",
2362 target: "https://example.org/relay"
2364 inserted_at: NaiveDateTime.truncate(~N[2017-08-15 15:47:06.597036], :second)
2367 Repo.insert(%ModerationLog{
2371 "nickname" => admin.nickname,
2374 action: "relay_unfollow",
2375 target: "https://example.org/relay"
2377 inserted_at: NaiveDateTime.truncate(~N[2017-08-16 15:47:06.597036], :second)
2380 conn = get(conn, "/api/pleroma/admin/moderation_log")
2382 response = json_response(conn, 200)
2383 [first_entry, second_entry] = response["items"]
2385 assert response["total"] == 2
2386 assert first_entry["data"]["action"] == "relay_unfollow"
2388 assert first_entry["message"] ==
2389 "@#{admin.nickname} unfollowed relay: https://example.org/relay"
2391 assert second_entry["data"]["action"] == "relay_follow"
2393 assert second_entry["message"] ==
2394 "@#{admin.nickname} followed relay: https://example.org/relay"
2397 test "returns the log with pagination", %{conn: conn, admin: admin} do
2398 Repo.insert(%ModerationLog{
2402 "nickname" => admin.nickname,
2405 action: "relay_follow",
2406 target: "https://example.org/relay"
2408 inserted_at: NaiveDateTime.truncate(~N[2017-08-15 15:47:06.597036], :second)
2411 Repo.insert(%ModerationLog{
2415 "nickname" => admin.nickname,
2418 action: "relay_unfollow",
2419 target: "https://example.org/relay"
2421 inserted_at: NaiveDateTime.truncate(~N[2017-08-16 15:47:06.597036], :second)
2424 conn1 = get(conn, "/api/pleroma/admin/moderation_log?page_size=1&page=1")
2426 response1 = json_response(conn1, 200)
2427 [first_entry] = response1["items"]
2429 assert response1["total"] == 2
2430 assert response1["items"] |> length() == 1
2431 assert first_entry["data"]["action"] == "relay_unfollow"
2433 assert first_entry["message"] ==
2434 "@#{admin.nickname} unfollowed relay: https://example.org/relay"
2436 conn2 = get(conn, "/api/pleroma/admin/moderation_log?page_size=1&page=2")
2438 response2 = json_response(conn2, 200)
2439 [second_entry] = response2["items"]
2441 assert response2["total"] == 2
2442 assert response2["items"] |> length() == 1
2443 assert second_entry["data"]["action"] == "relay_follow"
2445 assert second_entry["message"] ==
2446 "@#{admin.nickname} followed relay: https://example.org/relay"
2449 test "filters log by date", %{conn: conn, admin: admin} do
2450 first_date = "2017-08-15T15:47:06Z"
2451 second_date = "2017-08-20T15:47:06Z"
2453 Repo.insert(%ModerationLog{
2457 "nickname" => admin.nickname,
2460 action: "relay_follow",
2461 target: "https://example.org/relay"
2463 inserted_at: NaiveDateTime.from_iso8601!(first_date)
2466 Repo.insert(%ModerationLog{
2470 "nickname" => admin.nickname,
2473 action: "relay_unfollow",
2474 target: "https://example.org/relay"
2476 inserted_at: NaiveDateTime.from_iso8601!(second_date)
2482 "/api/pleroma/admin/moderation_log?start_date=#{second_date}"
2485 response1 = json_response(conn1, 200)
2486 [first_entry] = response1["items"]
2488 assert response1["total"] == 1
2489 assert first_entry["data"]["action"] == "relay_unfollow"
2491 assert first_entry["message"] ==
2492 "@#{admin.nickname} unfollowed relay: https://example.org/relay"
2495 test "returns log filtered by user", %{conn: conn, admin: admin, moderator: moderator} do
2496 Repo.insert(%ModerationLog{
2500 "nickname" => admin.nickname,
2503 action: "relay_follow",
2504 target: "https://example.org/relay"
2508 Repo.insert(%ModerationLog{
2511 "id" => moderator.id,
2512 "nickname" => moderator.nickname,
2515 action: "relay_unfollow",
2516 target: "https://example.org/relay"
2520 conn1 = get(conn, "/api/pleroma/admin/moderation_log?user_id=#{moderator.id}")
2522 response1 = json_response(conn1, 200)
2523 [first_entry] = response1["items"]
2525 assert response1["total"] == 1
2526 assert get_in(first_entry, ["data", "actor", "id"]) == moderator.id
2529 test "returns log filtered by search", %{conn: conn, moderator: moderator} do
2530 ModerationLog.insert_log(%{
2532 action: "relay_follow",
2533 target: "https://example.org/relay"
2536 ModerationLog.insert_log(%{
2538 action: "relay_unfollow",
2539 target: "https://example.org/relay"
2542 conn1 = get(conn, "/api/pleroma/admin/moderation_log?search=unfo")
2544 response1 = json_response(conn1, 200)
2545 [first_entry] = response1["items"]
2547 assert response1["total"] == 1
2549 assert get_in(first_entry, ["data", "message"]) ==
2550 "@#{moderator.nickname} unfollowed relay: https://example.org/relay"
2554 describe "PATCH /users/:nickname/force_password_reset" do
2555 setup %{conn: conn} do
2556 admin = insert(:user, is_admin: true)
2557 user = insert(:user)
2559 %{conn: assign(conn, :user, admin), admin: admin, user: user}
2562 test "sets password_reset_pending to true", %{admin: admin, user: user} do
2563 assert user.password_reset_pending == false
2567 |> assign(:user, admin)
2568 |> patch("/api/pleroma/admin/users/force_password_reset", %{nicknames: [user.nickname]})
2570 assert json_response(conn, 204) == ""
2572 ObanHelpers.perform_all()
2574 assert User.get_by_id(user.id).password_reset_pending == true
2578 describe "relays" do
2579 setup %{conn: conn} do
2580 admin = insert(:user, is_admin: true)
2582 %{conn: assign(conn, :user, admin), admin: admin}
2585 test "POST /relay", %{admin: admin} do
2588 |> assign(:user, admin)
2589 |> post("/api/pleroma/admin/relay", %{
2590 relay_url: "http://mastodon.example.org/users/admin"
2593 assert json_response(conn, 200) == "http://mastodon.example.org/users/admin"
2595 log_entry = Repo.one(ModerationLog)
2597 assert ModerationLog.get_log_entry_message(log_entry) ==
2598 "@#{admin.nickname} followed relay: http://mastodon.example.org/users/admin"
2601 test "GET /relay", %{admin: admin} do
2602 relay_user = Pleroma.Web.ActivityPub.Relay.get_actor()
2604 ["http://mastodon.example.org/users/admin", "https://mstdn.io/users/mayuutann"]
2605 |> Enum.each(fn ap_id ->
2606 {:ok, user} = User.get_or_fetch_by_ap_id(ap_id)
2607 User.follow(relay_user, user)
2612 |> assign(:user, admin)
2613 |> get("/api/pleroma/admin/relay")
2615 assert json_response(conn, 200)["relays"] -- ["mastodon.example.org", "mstdn.io"] == []
2618 test "DELETE /relay", %{admin: admin} do
2620 |> assign(:user, admin)
2621 |> post("/api/pleroma/admin/relay", %{
2622 relay_url: "http://mastodon.example.org/users/admin"
2627 |> assign(:user, admin)
2628 |> delete("/api/pleroma/admin/relay", %{
2629 relay_url: "http://mastodon.example.org/users/admin"
2632 assert json_response(conn, 200) == "http://mastodon.example.org/users/admin"
2634 [log_entry_one, log_entry_two] = Repo.all(ModerationLog)
2636 assert ModerationLog.get_log_entry_message(log_entry_one) ==
2637 "@#{admin.nickname} followed relay: http://mastodon.example.org/users/admin"
2639 assert ModerationLog.get_log_entry_message(log_entry_two) ==
2640 "@#{admin.nickname} unfollowed relay: http://mastodon.example.org/users/admin"
2644 describe "instances" do
2645 test "GET /instances/:instance/statuses" do
2646 admin = insert(:user, is_admin: true)
2647 user = insert(:user, local: false, nickname: "archaeme@archae.me")
2648 user2 = insert(:user, local: false, nickname: "test@test.com")
2649 insert_pair(:note_activity, user: user)
2650 insert(:note_activity, user: user2)
2654 |> assign(:user, admin)
2655 |> get("/api/pleroma/admin/instances/archae.me/statuses")
2657 response = json_response(conn, 200)
2659 assert length(response) == 2
2663 |> assign(:user, admin)
2664 |> get("/api/pleroma/admin/instances/test.com/statuses")
2666 response = json_response(conn, 200)
2668 assert length(response) == 1
2672 |> assign(:user, admin)
2673 |> get("/api/pleroma/admin/instances/nonexistent.com/statuses")
2675 response = json_response(conn, 200)
2677 assert length(response) == 0
2682 # Needed for testing
2683 defmodule Pleroma.Web.Endpoint.NotReal do
2686 defmodule Pleroma.Captcha.NotReal do