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 "PATCH /api/pleroma/admin/reports" 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 {:ok, %{id: second_report_id}} =
1329 CommonAPI.report(reporter, %{
1330 "account_id" => target_user.id,
1331 "comment" => "I feel very offended",
1332 "status_ids" => [activity.id]
1336 conn: assign(conn, :user, admin),
1339 second_report_id: second_report_id
1343 test "mark report as resolved", %{conn: conn, id: id, admin: admin} do
1345 |> patch("/api/pleroma/admin/reports", %{
1347 %{"state" => "resolved", "id" => id}
1350 |> json_response(:no_content)
1352 activity = Activity.get_by_id(id)
1353 assert activity.data["state"] == "resolved"
1355 log_entry = Repo.one(ModerationLog)
1357 assert ModerationLog.get_log_entry_message(log_entry) ==
1358 "@#{admin.nickname} updated report ##{id} with 'resolved' state"
1361 test "closes report", %{conn: conn, id: id, admin: admin} do
1363 |> patch("/api/pleroma/admin/reports", %{
1365 %{"state" => "closed", "id" => id}
1368 |> json_response(:no_content)
1370 activity = Activity.get_by_id(id)
1371 assert activity.data["state"] == "closed"
1373 log_entry = Repo.one(ModerationLog)
1375 assert ModerationLog.get_log_entry_message(log_entry) ==
1376 "@#{admin.nickname} updated report ##{id} with 'closed' state"
1379 test "returns 400 when state is unknown", %{conn: conn, id: id} do
1382 |> patch("/api/pleroma/admin/reports", %{
1384 %{"state" => "test", "id" => id}
1388 assert hd(json_response(conn, :bad_request))["error"] == "Unsupported state"
1391 test "returns 404 when report is not exist", %{conn: conn} do
1394 |> patch("/api/pleroma/admin/reports", %{
1396 %{"state" => "closed", "id" => "test"}
1400 assert hd(json_response(conn, :bad_request))["error"] == "not_found"
1403 test "updates state of multiple reports", %{
1407 second_report_id: second_report_id
1410 |> patch("/api/pleroma/admin/reports", %{
1412 %{"state" => "resolved", "id" => id},
1413 %{"state" => "closed", "id" => second_report_id}
1416 |> json_response(:no_content)
1418 activity = Activity.get_by_id(id)
1419 second_activity = Activity.get_by_id(second_report_id)
1420 assert activity.data["state"] == "resolved"
1421 assert second_activity.data["state"] == "closed"
1423 [first_log_entry, second_log_entry] = Repo.all(ModerationLog)
1425 assert ModerationLog.get_log_entry_message(first_log_entry) ==
1426 "@#{admin.nickname} updated report ##{id} with 'resolved' state"
1428 assert ModerationLog.get_log_entry_message(second_log_entry) ==
1429 "@#{admin.nickname} updated report ##{second_report_id} with 'closed' state"
1433 describe "GET /api/pleroma/admin/reports" do
1434 setup %{conn: conn} do
1435 admin = insert(:user, is_admin: true)
1437 %{conn: assign(conn, :user, admin)}
1440 test "returns empty response when no reports created", %{conn: conn} do
1443 |> get("/api/pleroma/admin/reports")
1444 |> json_response(:ok)
1446 assert Enum.empty?(response["reports"])
1447 assert response["total"] == 0
1450 test "returns reports", %{conn: conn} do
1451 [reporter, target_user] = insert_pair(:user)
1452 activity = insert(:note_activity, user: target_user)
1454 {:ok, %{id: report_id}} =
1455 CommonAPI.report(reporter, %{
1456 "account_id" => target_user.id,
1457 "comment" => "I feel offended",
1458 "status_ids" => [activity.id]
1463 |> get("/api/pleroma/admin/reports")
1464 |> json_response(:ok)
1466 [report] = response["reports"]
1468 assert length(response["reports"]) == 1
1469 assert report["id"] == report_id
1471 assert response["total"] == 1
1474 test "returns reports with specified state", %{conn: conn} do
1475 [reporter, target_user] = insert_pair(:user)
1476 activity = insert(:note_activity, user: target_user)
1478 {:ok, %{id: first_report_id}} =
1479 CommonAPI.report(reporter, %{
1480 "account_id" => target_user.id,
1481 "comment" => "I feel offended",
1482 "status_ids" => [activity.id]
1485 {:ok, %{id: second_report_id}} =
1486 CommonAPI.report(reporter, %{
1487 "account_id" => target_user.id,
1488 "comment" => "I don't like this user"
1491 CommonAPI.update_report_state(second_report_id, "closed")
1495 |> get("/api/pleroma/admin/reports", %{
1498 |> json_response(:ok)
1500 [open_report] = response["reports"]
1502 assert length(response["reports"]) == 1
1503 assert open_report["id"] == first_report_id
1505 assert response["total"] == 1
1509 |> get("/api/pleroma/admin/reports", %{
1512 |> json_response(:ok)
1514 [closed_report] = response["reports"]
1516 assert length(response["reports"]) == 1
1517 assert closed_report["id"] == second_report_id
1519 assert response["total"] == 1
1523 |> get("/api/pleroma/admin/reports", %{
1524 "state" => "resolved"
1526 |> json_response(:ok)
1528 assert Enum.empty?(response["reports"])
1529 assert response["total"] == 0
1532 test "returns 403 when requested by a non-admin" do
1533 user = insert(:user)
1537 |> assign(:user, user)
1538 |> get("/api/pleroma/admin/reports")
1540 assert json_response(conn, :forbidden) == %{"error" => "User is not admin."}
1543 test "returns 403 when requested by anonymous" do
1546 |> get("/api/pleroma/admin/reports")
1548 assert json_response(conn, :forbidden) == %{"error" => "Invalid credentials."}
1552 describe "GET /api/pleroma/admin/grouped_reports" do
1553 setup %{conn: conn} do
1554 admin = insert(:user, is_admin: true)
1555 [reporter, target_user] = insert_pair(:user)
1557 date1 = (DateTime.to_unix(DateTime.utc_now()) + 1000) |> DateTime.from_unix!()
1558 date2 = (DateTime.to_unix(DateTime.utc_now()) + 2000) |> DateTime.from_unix!()
1559 date3 = (DateTime.to_unix(DateTime.utc_now()) + 3000) |> DateTime.from_unix!()
1562 insert(:note_activity, user: target_user, data_attrs: %{"published" => date1})
1565 insert(:note_activity, user: target_user, data_attrs: %{"published" => date2})
1568 insert(:note_activity, user: target_user, data_attrs: %{"published" => date3})
1570 {:ok, first_report} =
1571 CommonAPI.report(reporter, %{
1572 "account_id" => target_user.id,
1573 "status_ids" => [first_status.id, second_status.id, third_status.id]
1576 {:ok, second_report} =
1577 CommonAPI.report(reporter, %{
1578 "account_id" => target_user.id,
1579 "status_ids" => [first_status.id, second_status.id]
1582 {:ok, third_report} =
1583 CommonAPI.report(reporter, %{
1584 "account_id" => target_user.id,
1585 "status_ids" => [first_status.id]
1589 conn: assign(conn, :user, admin),
1590 first_status: Activity.get_by_ap_id_with_object(first_status.data["id"]),
1591 second_status: Activity.get_by_ap_id_with_object(second_status.data["id"]),
1592 third_status: Activity.get_by_ap_id_with_object(third_status.data["id"]),
1593 first_status_reports: [first_report, second_report, third_report],
1594 second_status_reports: [first_report, second_report],
1595 third_status_reports: [first_report],
1596 target_user: target_user,
1601 test "returns reports grouped by status", %{
1603 first_status: first_status,
1604 second_status: second_status,
1605 third_status: third_status,
1606 first_status_reports: first_status_reports,
1607 second_status_reports: second_status_reports,
1608 third_status_reports: third_status_reports,
1609 target_user: target_user,
1614 |> get("/api/pleroma/admin/grouped_reports")
1615 |> json_response(:ok)
1617 assert length(response["reports"]) == 3
1620 Enum.find(response["reports"], &(&1["status"]["id"] == first_status.data["id"]))
1623 Enum.find(response["reports"], &(&1["status"]["id"] == second_status.data["id"]))
1626 Enum.find(response["reports"], &(&1["status"]["id"] == third_status.data["id"]))
1628 assert length(first_group["reports"]) == 3
1629 assert length(second_group["reports"]) == 2
1630 assert length(third_group["reports"]) == 1
1632 assert first_group["date"] ==
1633 Enum.max_by(first_status_reports, fn act ->
1634 NaiveDateTime.from_iso8601!(act.data["published"])
1635 end).data["published"]
1637 assert first_group["status"] == %{
1638 "id" => first_status.data["id"],
1639 "content" => first_status.object.data["content"],
1640 "published" => first_status.object.data["published"]
1643 assert first_group["account"]["id"] == target_user.id
1645 assert length(first_group["actors"]) == 1
1646 assert hd(first_group["actors"])["id"] == reporter.id
1648 assert Enum.map(first_group["reports"], & &1["id"]) --
1649 Enum.map(first_status_reports, & &1.id) == []
1651 assert second_group["date"] ==
1652 Enum.max_by(second_status_reports, fn act ->
1653 NaiveDateTime.from_iso8601!(act.data["published"])
1654 end).data["published"]
1656 assert second_group["status"] == %{
1657 "id" => second_status.data["id"],
1658 "content" => second_status.object.data["content"],
1659 "published" => second_status.object.data["published"]
1662 assert second_group["account"]["id"] == target_user.id
1664 assert length(second_group["actors"]) == 1
1665 assert hd(second_group["actors"])["id"] == reporter.id
1667 assert Enum.map(second_group["reports"], & &1["id"]) --
1668 Enum.map(second_status_reports, & &1.id) == []
1670 assert third_group["date"] ==
1671 Enum.max_by(third_status_reports, fn act ->
1672 NaiveDateTime.from_iso8601!(act.data["published"])
1673 end).data["published"]
1675 assert third_group["status"] == %{
1676 "id" => third_status.data["id"],
1677 "content" => third_status.object.data["content"],
1678 "published" => third_status.object.data["published"]
1681 assert third_group["account"]["id"] == target_user.id
1683 assert length(third_group["actors"]) == 1
1684 assert hd(third_group["actors"])["id"] == reporter.id
1686 assert Enum.map(third_group["reports"], & &1["id"]) --
1687 Enum.map(third_status_reports, & &1.id) == []
1691 describe "POST /api/pleroma/admin/reports/:id/respond" do
1692 setup %{conn: conn} do
1693 admin = insert(:user, is_admin: true)
1695 %{conn: assign(conn, :user, admin), admin: admin}
1698 test "returns created dm", %{conn: conn, admin: admin} do
1699 [reporter, target_user] = insert_pair(:user)
1700 activity = insert(:note_activity, user: target_user)
1702 {:ok, %{id: report_id}} =
1703 CommonAPI.report(reporter, %{
1704 "account_id" => target_user.id,
1705 "comment" => "I feel offended",
1706 "status_ids" => [activity.id]
1711 |> post("/api/pleroma/admin/reports/#{report_id}/respond", %{
1712 "status" => "I will check it out"
1714 |> json_response(:ok)
1716 recipients = Enum.map(response["mentions"], & &1["username"])
1718 assert reporter.nickname in recipients
1719 assert response["content"] == "I will check it out"
1720 assert response["visibility"] == "direct"
1722 log_entry = Repo.one(ModerationLog)
1724 assert ModerationLog.get_log_entry_message(log_entry) ==
1725 "@#{admin.nickname} responded with 'I will check it out' to report ##{
1730 test "returns 400 when status is missing", %{conn: conn} do
1731 conn = post(conn, "/api/pleroma/admin/reports/test/respond")
1733 assert json_response(conn, :bad_request) == "Invalid parameters"
1736 test "returns 404 when report id is invalid", %{conn: conn} do
1738 post(conn, "/api/pleroma/admin/reports/test/respond", %{
1742 assert json_response(conn, :not_found) == "Not found"
1746 describe "PUT /api/pleroma/admin/statuses/:id" do
1747 setup %{conn: conn} do
1748 admin = insert(:user, is_admin: true)
1749 activity = insert(:note_activity)
1751 %{conn: assign(conn, :user, admin), id: activity.id, admin: admin}
1754 test "toggle sensitive flag", %{conn: conn, id: id, admin: admin} do
1757 |> put("/api/pleroma/admin/statuses/#{id}", %{"sensitive" => "true"})
1758 |> json_response(:ok)
1760 assert response["sensitive"]
1762 log_entry = Repo.one(ModerationLog)
1764 assert ModerationLog.get_log_entry_message(log_entry) ==
1765 "@#{admin.nickname} updated status ##{id}, set sensitive: 'true'"
1769 |> put("/api/pleroma/admin/statuses/#{id}", %{"sensitive" => "false"})
1770 |> json_response(:ok)
1772 refute response["sensitive"]
1775 test "change visibility flag", %{conn: conn, id: id, admin: admin} do
1778 |> put("/api/pleroma/admin/statuses/#{id}", %{"visibility" => "public"})
1779 |> json_response(:ok)
1781 assert response["visibility"] == "public"
1783 log_entry = Repo.one(ModerationLog)
1785 assert ModerationLog.get_log_entry_message(log_entry) ==
1786 "@#{admin.nickname} updated status ##{id}, set visibility: 'public'"
1790 |> put("/api/pleroma/admin/statuses/#{id}", %{"visibility" => "private"})
1791 |> json_response(:ok)
1793 assert response["visibility"] == "private"
1797 |> put("/api/pleroma/admin/statuses/#{id}", %{"visibility" => "unlisted"})
1798 |> json_response(:ok)
1800 assert response["visibility"] == "unlisted"
1803 test "returns 400 when visibility is unknown", %{conn: conn, id: id} do
1806 |> put("/api/pleroma/admin/statuses/#{id}", %{"visibility" => "test"})
1808 assert json_response(conn, :bad_request) == "Unsupported visibility"
1812 describe "DELETE /api/pleroma/admin/statuses/:id" do
1813 setup %{conn: conn} do
1814 admin = insert(:user, is_admin: true)
1815 activity = insert(:note_activity)
1817 %{conn: assign(conn, :user, admin), id: activity.id, admin: admin}
1820 test "deletes status", %{conn: conn, id: id, admin: admin} do
1822 |> delete("/api/pleroma/admin/statuses/#{id}")
1823 |> json_response(:ok)
1825 refute Activity.get_by_id(id)
1827 log_entry = Repo.one(ModerationLog)
1829 assert ModerationLog.get_log_entry_message(log_entry) ==
1830 "@#{admin.nickname} deleted status ##{id}"
1833 test "returns error when status is not exist", %{conn: conn} do
1836 |> delete("/api/pleroma/admin/statuses/test")
1838 assert json_response(conn, :bad_request) == "Could not delete"
1842 describe "GET /api/pleroma/admin/config" do
1843 setup %{conn: conn} do
1844 admin = insert(:user, is_admin: true)
1846 %{conn: assign(conn, :user, admin)}
1849 test "without any settings in db", %{conn: conn} do
1850 conn = get(conn, "/api/pleroma/admin/config")
1852 assert json_response(conn, 200) == %{"configs" => []}
1855 test "with settings in db", %{conn: conn} do
1856 config1 = insert(:config)
1857 config2 = insert(:config)
1859 conn = get(conn, "/api/pleroma/admin/config")
1872 } = json_response(conn, 200)
1874 assert key1 == config1.key
1875 assert key2 == config2.key
1879 describe "POST /api/pleroma/admin/config" do
1880 setup %{conn: conn} do
1881 admin = insert(:user, is_admin: true)
1883 temp_file = "config/test.exported_from_db.secret.exs"
1886 Application.delete_env(:pleroma, :key1)
1887 Application.delete_env(:pleroma, :key2)
1888 Application.delete_env(:pleroma, :key3)
1889 Application.delete_env(:pleroma, :key4)
1890 Application.delete_env(:pleroma, :keyaa1)
1891 Application.delete_env(:pleroma, :keyaa2)
1892 Application.delete_env(:pleroma, Pleroma.Web.Endpoint.NotReal)
1893 Application.delete_env(:pleroma, Pleroma.Captcha.NotReal)
1894 :ok = File.rm(temp_file)
1897 %{conn: assign(conn, :user, admin)}
1900 clear_config([:instance, :dynamic_configuration]) do
1901 Pleroma.Config.put([:instance, :dynamic_configuration], true)
1904 test "create new config setting in db", %{conn: conn} do
1906 post(conn, "/api/pleroma/admin/config", %{
1908 %{group: "pleroma", key: "key1", value: "value1"},
1911 key: "Ueberauth.Strategy.Twitter.OAuth",
1912 value: [%{"tuple" => [":consumer_secret", "aaaa"]}]
1918 ":nested_1" => "nested_value1",
1920 %{":nested_22" => "nested_value222"},
1921 %{":nested_33" => %{":nested_44" => "nested_444"}}
1929 %{"nested_3" => ":nested_3", "nested_33" => "nested_33"},
1930 %{"nested_4" => true}
1936 value: %{":nested_5" => ":upload", "endpoint" => "https://example.com"}
1941 value: %{"tuple" => ["string", "Pleroma.Captcha.NotReal", []]}
1946 assert json_response(conn, 200) == %{
1949 "group" => "pleroma",
1954 "group" => "ueberauth",
1955 "key" => "Ueberauth.Strategy.Twitter.OAuth",
1956 "value" => [%{"tuple" => [":consumer_secret", "aaaa"]}]
1959 "group" => "pleroma",
1962 ":nested_1" => "nested_value1",
1964 %{":nested_22" => "nested_value222"},
1965 %{":nested_33" => %{":nested_44" => "nested_444"}}
1970 "group" => "pleroma",
1973 %{"nested_3" => ":nested_3", "nested_33" => "nested_33"},
1974 %{"nested_4" => true}
1978 "group" => "pleroma",
1980 "value" => %{"endpoint" => "https://example.com", ":nested_5" => ":upload"}
1985 "value" => %{"tuple" => ["string", "Pleroma.Captcha.NotReal", []]}
1990 assert Application.get_env(:pleroma, :key1) == "value1"
1992 assert Application.get_env(:pleroma, :key2) == %{
1993 nested_1: "nested_value1",
1995 %{nested_22: "nested_value222"},
1996 %{nested_33: %{nested_44: "nested_444"}}
2000 assert Application.get_env(:pleroma, :key3) == [
2001 %{"nested_3" => :nested_3, "nested_33" => "nested_33"},
2002 %{"nested_4" => true}
2005 assert Application.get_env(:pleroma, :key4) == %{
2006 "endpoint" => "https://example.com",
2010 assert Application.get_env(:idna, :key5) == {"string", Pleroma.Captcha.NotReal, []}
2013 test "update config setting & delete", %{conn: conn} do
2014 config1 = insert(:config, key: "keyaa1")
2015 config2 = insert(:config, key: "keyaa2")
2019 key: "Ueberauth.Strategy.Microsoft.OAuth",
2020 value: :erlang.term_to_binary([])
2024 post(conn, "/api/pleroma/admin/config", %{
2026 %{group: config1.group, key: config1.key, value: "another_value"},
2027 %{group: config2.group, key: config2.key, delete: "true"},
2030 key: "Ueberauth.Strategy.Microsoft.OAuth",
2036 assert json_response(conn, 200) == %{
2039 "group" => "pleroma",
2040 "key" => config1.key,
2041 "value" => "another_value"
2046 assert Application.get_env(:pleroma, :keyaa1) == "another_value"
2047 refute Application.get_env(:pleroma, :keyaa2)
2050 test "common config example", %{conn: conn} do
2052 post(conn, "/api/pleroma/admin/config", %{
2055 "group" => "pleroma",
2056 "key" => "Pleroma.Captcha.NotReal",
2058 %{"tuple" => [":enabled", false]},
2059 %{"tuple" => [":method", "Pleroma.Captcha.Kocaptcha"]},
2060 %{"tuple" => [":seconds_valid", 60]},
2061 %{"tuple" => [":path", ""]},
2062 %{"tuple" => [":key1", nil]},
2063 %{"tuple" => [":partial_chain", "&:hackney_connect.partial_chain/1"]},
2064 %{"tuple" => [":regex1", "~r/https:\/\/example.com/"]},
2065 %{"tuple" => [":regex2", "~r/https:\/\/example.com/u"]},
2066 %{"tuple" => [":regex3", "~r/https:\/\/example.com/i"]},
2067 %{"tuple" => [":regex4", "~r/https:\/\/example.com/s"]}
2073 assert json_response(conn, 200) == %{
2076 "group" => "pleroma",
2077 "key" => "Pleroma.Captcha.NotReal",
2079 %{"tuple" => [":enabled", false]},
2080 %{"tuple" => [":method", "Pleroma.Captcha.Kocaptcha"]},
2081 %{"tuple" => [":seconds_valid", 60]},
2082 %{"tuple" => [":path", ""]},
2083 %{"tuple" => [":key1", nil]},
2084 %{"tuple" => [":partial_chain", "&:hackney_connect.partial_chain/1"]},
2085 %{"tuple" => [":regex1", "~r/https:\\/\\/example.com/"]},
2086 %{"tuple" => [":regex2", "~r/https:\\/\\/example.com/u"]},
2087 %{"tuple" => [":regex3", "~r/https:\\/\\/example.com/i"]},
2088 %{"tuple" => [":regex4", "~r/https:\\/\\/example.com/s"]}
2095 test "tuples with more than two values", %{conn: conn} do
2097 post(conn, "/api/pleroma/admin/config", %{
2100 "group" => "pleroma",
2101 "key" => "Pleroma.Web.Endpoint.NotReal",
2117 "/api/v1/streaming",
2118 "Pleroma.Web.MastodonAPI.WebsocketHandler",
2125 "Phoenix.Endpoint.CowboyWebSocket",
2128 "Phoenix.Transports.WebSocket",
2131 "Pleroma.Web.Endpoint",
2132 "Pleroma.Web.UserSocket",
2143 "Phoenix.Endpoint.Cowboy2Handler",
2144 %{"tuple" => ["Pleroma.Web.Endpoint", []]}
2161 assert json_response(conn, 200) == %{
2164 "group" => "pleroma",
2165 "key" => "Pleroma.Web.Endpoint.NotReal",
2181 "/api/v1/streaming",
2182 "Pleroma.Web.MastodonAPI.WebsocketHandler",
2189 "Phoenix.Endpoint.CowboyWebSocket",
2192 "Phoenix.Transports.WebSocket",
2195 "Pleroma.Web.Endpoint",
2196 "Pleroma.Web.UserSocket",
2207 "Phoenix.Endpoint.Cowboy2Handler",
2208 %{"tuple" => ["Pleroma.Web.Endpoint", []]}
2226 test "settings with nesting map", %{conn: conn} do
2228 post(conn, "/api/pleroma/admin/config", %{
2231 "group" => "pleroma",
2234 %{"tuple" => [":key2", "some_val"]},
2239 ":max_options" => 20,
2240 ":max_option_chars" => 200,
2241 ":min_expiration" => 0,
2242 ":max_expiration" => 31_536_000,
2244 ":max_options" => 20,
2245 ":max_option_chars" => 200,
2246 ":min_expiration" => 0,
2247 ":max_expiration" => 31_536_000
2257 assert json_response(conn, 200) ==
2261 "group" => "pleroma",
2264 %{"tuple" => [":key2", "some_val"]},
2269 ":max_expiration" => 31_536_000,
2270 ":max_option_chars" => 200,
2271 ":max_options" => 20,
2272 ":min_expiration" => 0,
2274 ":max_expiration" => 31_536_000,
2275 ":max_option_chars" => 200,
2276 ":max_options" => 20,
2277 ":min_expiration" => 0
2288 test "value as map", %{conn: conn} do
2290 post(conn, "/api/pleroma/admin/config", %{
2293 "group" => "pleroma",
2295 "value" => %{"key" => "some_val"}
2300 assert json_response(conn, 200) ==
2304 "group" => "pleroma",
2306 "value" => %{"key" => "some_val"}
2312 test "dispatch setting", %{conn: conn} do
2314 post(conn, "/api/pleroma/admin/config", %{
2317 "group" => "pleroma",
2318 "key" => "Pleroma.Web.Endpoint.NotReal",
2324 %{"tuple" => [":ip", %{"tuple" => [127, 0, 0, 1]}]},
2325 %{"tuple" => [":dispatch", ["{:_,
2327 {\"/api/v1/streaming\", Pleroma.Web.MastodonAPI.WebsocketHandler, []},
2328 {\"/websocket\", Phoenix.Endpoint.CowboyWebSocket,
2329 {Phoenix.Transports.WebSocket,
2330 {Pleroma.Web.Endpoint, Pleroma.Web.UserSocket, [path: \"/websocket\"]}}},
2331 {:_, Phoenix.Endpoint.Cowboy2Handler, {Pleroma.Web.Endpoint, []}}
2342 "{:_, [{\"/api/v1/streaming\", Pleroma.Web.MastodonAPI.WebsocketHandler, []}, " <>
2343 "{\"/websocket\", Phoenix.Endpoint.CowboyWebSocket, {Phoenix.Transports.WebSocket, " <>
2344 "{Pleroma.Web.Endpoint, Pleroma.Web.UserSocket, [path: \"/websocket\"]}}}, " <>
2345 "{:_, Phoenix.Endpoint.Cowboy2Handler, {Pleroma.Web.Endpoint, []}}]}"
2347 assert json_response(conn, 200) == %{
2350 "group" => "pleroma",
2351 "key" => "Pleroma.Web.Endpoint.NotReal",
2357 %{"tuple" => [":ip", %{"tuple" => [127, 0, 0, 1]}]},
2375 test "queues key as atom", %{conn: conn} do
2377 post(conn, "/api/pleroma/admin/config", %{
2383 %{"tuple" => [":federator_incoming", 50]},
2384 %{"tuple" => [":federator_outgoing", 50]},
2385 %{"tuple" => [":web_push", 50]},
2386 %{"tuple" => [":mailer", 10]},
2387 %{"tuple" => [":transmogrifier", 20]},
2388 %{"tuple" => [":scheduled_activities", 10]},
2389 %{"tuple" => [":background", 5]}
2395 assert json_response(conn, 200) == %{
2401 %{"tuple" => [":federator_incoming", 50]},
2402 %{"tuple" => [":federator_outgoing", 50]},
2403 %{"tuple" => [":web_push", 50]},
2404 %{"tuple" => [":mailer", 10]},
2405 %{"tuple" => [":transmogrifier", 20]},
2406 %{"tuple" => [":scheduled_activities", 10]},
2407 %{"tuple" => [":background", 5]}
2414 test "delete part of settings by atom subkeys", %{conn: conn} do
2418 value: :erlang.term_to_binary(subkey1: "val1", subkey2: "val2", subkey3: "val3")
2422 post(conn, "/api/pleroma/admin/config", %{
2425 group: config.group,
2427 subkeys: [":subkey1", ":subkey3"],
2434 json_response(conn, 200) == %{
2437 "group" => "pleroma",
2439 "value" => [%{"tuple" => [":subkey2", "val2"]}]
2447 describe "config mix tasks run" do
2448 setup %{conn: conn} do
2449 admin = insert(:user, is_admin: true)
2451 temp_file = "config/test.exported_from_db.secret.exs"
2453 Mix.shell(Mix.Shell.Quiet)
2456 Mix.shell(Mix.Shell.IO)
2457 :ok = File.rm(temp_file)
2460 %{conn: assign(conn, :user, admin), admin: admin}
2463 clear_config([:instance, :dynamic_configuration]) do
2464 Pleroma.Config.put([:instance, :dynamic_configuration], true)
2467 test "transfer settings to DB and to file", %{conn: conn, admin: admin} do
2468 assert Pleroma.Repo.all(Pleroma.Web.AdminAPI.Config) == []
2469 conn = get(conn, "/api/pleroma/admin/config/migrate_to_db")
2470 assert json_response(conn, 200) == %{}
2471 assert Pleroma.Repo.all(Pleroma.Web.AdminAPI.Config) > 0
2475 |> assign(:user, admin)
2476 |> get("/api/pleroma/admin/config/migrate_from_db")
2478 assert json_response(conn, 200) == %{}
2479 assert Pleroma.Repo.all(Pleroma.Web.AdminAPI.Config) == []
2483 describe "GET /api/pleroma/admin/users/:nickname/statuses" do
2485 admin = insert(:user, is_admin: true)
2486 user = insert(:user)
2488 date1 = (DateTime.to_unix(DateTime.utc_now()) + 2000) |> DateTime.from_unix!()
2489 date2 = (DateTime.to_unix(DateTime.utc_now()) + 1000) |> DateTime.from_unix!()
2490 date3 = (DateTime.to_unix(DateTime.utc_now()) + 3000) |> DateTime.from_unix!()
2492 insert(:note_activity, user: user, published: date1)
2493 insert(:note_activity, user: user, published: date2)
2494 insert(:note_activity, user: user, published: date3)
2498 |> assign(:user, admin)
2500 {:ok, conn: conn, user: user}
2503 test "renders user's statuses", %{conn: conn, user: user} do
2504 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses")
2506 assert json_response(conn, 200) |> length() == 3
2509 test "renders user's statuses with a limit", %{conn: conn, user: user} do
2510 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses?page_size=2")
2512 assert json_response(conn, 200) |> length() == 2
2515 test "doesn't return private statuses by default", %{conn: conn, user: user} do
2516 {:ok, _private_status} =
2517 CommonAPI.post(user, %{"status" => "private", "visibility" => "private"})
2519 {:ok, _public_status} =
2520 CommonAPI.post(user, %{"status" => "public", "visibility" => "public"})
2522 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses")
2524 assert json_response(conn, 200) |> length() == 4
2527 test "returns private statuses with godmode on", %{conn: conn, user: user} do
2528 {:ok, _private_status} =
2529 CommonAPI.post(user, %{"status" => "private", "visibility" => "private"})
2531 {:ok, _public_status} =
2532 CommonAPI.post(user, %{"status" => "public", "visibility" => "public"})
2534 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses?godmode=true")
2536 assert json_response(conn, 200) |> length() == 5
2540 describe "GET /api/pleroma/admin/moderation_log" do
2541 setup %{conn: conn} do
2542 admin = insert(:user, is_admin: true)
2543 moderator = insert(:user, is_moderator: true)
2545 %{conn: assign(conn, :user, admin), admin: admin, moderator: moderator}
2548 test "returns the log", %{conn: conn, admin: admin} do
2549 Repo.insert(%ModerationLog{
2553 "nickname" => admin.nickname,
2556 action: "relay_follow",
2557 target: "https://example.org/relay"
2559 inserted_at: NaiveDateTime.truncate(~N[2017-08-15 15:47:06.597036], :second)
2562 Repo.insert(%ModerationLog{
2566 "nickname" => admin.nickname,
2569 action: "relay_unfollow",
2570 target: "https://example.org/relay"
2572 inserted_at: NaiveDateTime.truncate(~N[2017-08-16 15:47:06.597036], :second)
2575 conn = get(conn, "/api/pleroma/admin/moderation_log")
2577 response = json_response(conn, 200)
2578 [first_entry, second_entry] = response["items"]
2580 assert response["total"] == 2
2581 assert first_entry["data"]["action"] == "relay_unfollow"
2583 assert first_entry["message"] ==
2584 "@#{admin.nickname} unfollowed relay: https://example.org/relay"
2586 assert second_entry["data"]["action"] == "relay_follow"
2588 assert second_entry["message"] ==
2589 "@#{admin.nickname} followed relay: https://example.org/relay"
2592 test "returns the log with pagination", %{conn: conn, admin: admin} do
2593 Repo.insert(%ModerationLog{
2597 "nickname" => admin.nickname,
2600 action: "relay_follow",
2601 target: "https://example.org/relay"
2603 inserted_at: NaiveDateTime.truncate(~N[2017-08-15 15:47:06.597036], :second)
2606 Repo.insert(%ModerationLog{
2610 "nickname" => admin.nickname,
2613 action: "relay_unfollow",
2614 target: "https://example.org/relay"
2616 inserted_at: NaiveDateTime.truncate(~N[2017-08-16 15:47:06.597036], :second)
2619 conn1 = get(conn, "/api/pleroma/admin/moderation_log?page_size=1&page=1")
2621 response1 = json_response(conn1, 200)
2622 [first_entry] = response1["items"]
2624 assert response1["total"] == 2
2625 assert response1["items"] |> length() == 1
2626 assert first_entry["data"]["action"] == "relay_unfollow"
2628 assert first_entry["message"] ==
2629 "@#{admin.nickname} unfollowed relay: https://example.org/relay"
2631 conn2 = get(conn, "/api/pleroma/admin/moderation_log?page_size=1&page=2")
2633 response2 = json_response(conn2, 200)
2634 [second_entry] = response2["items"]
2636 assert response2["total"] == 2
2637 assert response2["items"] |> length() == 1
2638 assert second_entry["data"]["action"] == "relay_follow"
2640 assert second_entry["message"] ==
2641 "@#{admin.nickname} followed relay: https://example.org/relay"
2644 test "filters log by date", %{conn: conn, admin: admin} do
2645 first_date = "2017-08-15T15:47:06Z"
2646 second_date = "2017-08-20T15:47:06Z"
2648 Repo.insert(%ModerationLog{
2652 "nickname" => admin.nickname,
2655 action: "relay_follow",
2656 target: "https://example.org/relay"
2658 inserted_at: NaiveDateTime.from_iso8601!(first_date)
2661 Repo.insert(%ModerationLog{
2665 "nickname" => admin.nickname,
2668 action: "relay_unfollow",
2669 target: "https://example.org/relay"
2671 inserted_at: NaiveDateTime.from_iso8601!(second_date)
2677 "/api/pleroma/admin/moderation_log?start_date=#{second_date}"
2680 response1 = json_response(conn1, 200)
2681 [first_entry] = response1["items"]
2683 assert response1["total"] == 1
2684 assert first_entry["data"]["action"] == "relay_unfollow"
2686 assert first_entry["message"] ==
2687 "@#{admin.nickname} unfollowed relay: https://example.org/relay"
2690 test "returns log filtered by user", %{conn: conn, admin: admin, moderator: moderator} do
2691 Repo.insert(%ModerationLog{
2695 "nickname" => admin.nickname,
2698 action: "relay_follow",
2699 target: "https://example.org/relay"
2703 Repo.insert(%ModerationLog{
2706 "id" => moderator.id,
2707 "nickname" => moderator.nickname,
2710 action: "relay_unfollow",
2711 target: "https://example.org/relay"
2715 conn1 = get(conn, "/api/pleroma/admin/moderation_log?user_id=#{moderator.id}")
2717 response1 = json_response(conn1, 200)
2718 [first_entry] = response1["items"]
2720 assert response1["total"] == 1
2721 assert get_in(first_entry, ["data", "actor", "id"]) == moderator.id
2724 test "returns log filtered by search", %{conn: conn, moderator: moderator} do
2725 ModerationLog.insert_log(%{
2727 action: "relay_follow",
2728 target: "https://example.org/relay"
2731 ModerationLog.insert_log(%{
2733 action: "relay_unfollow",
2734 target: "https://example.org/relay"
2737 conn1 = get(conn, "/api/pleroma/admin/moderation_log?search=unfo")
2739 response1 = json_response(conn1, 200)
2740 [first_entry] = response1["items"]
2742 assert response1["total"] == 1
2744 assert get_in(first_entry, ["data", "message"]) ==
2745 "@#{moderator.nickname} unfollowed relay: https://example.org/relay"
2749 describe "PATCH /users/:nickname/force_password_reset" do
2750 setup %{conn: conn} do
2751 admin = insert(:user, is_admin: true)
2752 user = insert(:user)
2754 %{conn: assign(conn, :user, admin), admin: admin, user: user}
2757 test "sets password_reset_pending to true", %{admin: admin, user: user} do
2758 assert user.password_reset_pending == false
2762 |> assign(:user, admin)
2763 |> patch("/api/pleroma/admin/users/force_password_reset", %{nicknames: [user.nickname]})
2765 assert json_response(conn, 204) == ""
2767 ObanHelpers.perform_all()
2769 assert User.get_by_id(user.id).password_reset_pending == true
2773 describe "relays" do
2774 setup %{conn: conn} do
2775 admin = insert(:user, is_admin: true)
2777 %{conn: assign(conn, :user, admin), admin: admin}
2780 test "POST /relay", %{admin: admin} do
2783 |> assign(:user, admin)
2784 |> post("/api/pleroma/admin/relay", %{
2785 relay_url: "http://mastodon.example.org/users/admin"
2788 assert json_response(conn, 200) == "http://mastodon.example.org/users/admin"
2790 log_entry = Repo.one(ModerationLog)
2792 assert ModerationLog.get_log_entry_message(log_entry) ==
2793 "@#{admin.nickname} followed relay: http://mastodon.example.org/users/admin"
2796 test "GET /relay", %{admin: admin} do
2797 relay_user = Pleroma.Web.ActivityPub.Relay.get_actor()
2799 ["http://mastodon.example.org/users/admin", "https://mstdn.io/users/mayuutann"]
2800 |> Enum.each(fn ap_id ->
2801 {:ok, user} = User.get_or_fetch_by_ap_id(ap_id)
2802 User.follow(relay_user, user)
2807 |> assign(:user, admin)
2808 |> get("/api/pleroma/admin/relay")
2810 assert json_response(conn, 200)["relays"] -- ["mastodon.example.org", "mstdn.io"] == []
2813 test "DELETE /relay", %{admin: admin} do
2815 |> assign(:user, admin)
2816 |> post("/api/pleroma/admin/relay", %{
2817 relay_url: "http://mastodon.example.org/users/admin"
2822 |> assign(:user, admin)
2823 |> delete("/api/pleroma/admin/relay", %{
2824 relay_url: "http://mastodon.example.org/users/admin"
2827 assert json_response(conn, 200) == "http://mastodon.example.org/users/admin"
2829 [log_entry_one, log_entry_two] = Repo.all(ModerationLog)
2831 assert ModerationLog.get_log_entry_message(log_entry_one) ==
2832 "@#{admin.nickname} followed relay: http://mastodon.example.org/users/admin"
2834 assert ModerationLog.get_log_entry_message(log_entry_two) ==
2835 "@#{admin.nickname} unfollowed relay: http://mastodon.example.org/users/admin"
2840 # Needed for testing
2841 defmodule Pleroma.Web.Endpoint.NotReal do
2844 defmodule Pleroma.Captcha.NotReal do