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.CommonAPI
17 alias Pleroma.Web.MediaProxy
18 import Pleroma.Factory
21 Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
26 describe "DELETE /api/pleroma/admin/users" do
28 admin = insert(:user, info: %{is_admin: true})
33 |> assign(:user, admin)
34 |> put_req_header("accept", "application/json")
35 |> delete("/api/pleroma/admin/users?nickname=#{user.nickname}")
37 log_entry = Repo.one(ModerationLog)
39 assert ModerationLog.get_log_entry_message(log_entry) ==
40 "@#{admin.nickname} deleted users: @#{user.nickname}"
42 assert json_response(conn, 200) == user.nickname
45 test "multiple users" do
46 admin = insert(:user, info: %{is_admin: true})
47 user_one = insert(:user)
48 user_two = insert(:user)
52 |> assign(:user, admin)
53 |> put_req_header("accept", "application/json")
54 |> delete("/api/pleroma/admin/users", %{
55 nicknames: [user_one.nickname, user_two.nickname]
58 log_entry = Repo.one(ModerationLog)
60 assert ModerationLog.get_log_entry_message(log_entry) ==
61 "@#{admin.nickname} deleted users: @#{user_one.nickname}, @#{user_two.nickname}"
63 response = json_response(conn, 200)
64 assert response -- [user_one.nickname, user_two.nickname] == []
68 describe "/api/pleroma/admin/users" do
70 admin = insert(:user, info: %{is_admin: true})
74 |> assign(:user, admin)
75 |> put_req_header("accept", "application/json")
76 |> post("/api/pleroma/admin/users", %{
80 "email" => "lain@example.org",
84 "nickname" => "lain2",
85 "email" => "lain2@example.org",
91 response = json_response(conn, 200) |> Enum.map(&Map.get(&1, "type"))
92 assert response == ["success", "success"]
94 log_entry = Repo.one(ModerationLog)
96 assert ["lain", "lain2"] -- Enum.map(log_entry.data["subjects"], & &1["nickname"]) == []
99 test "Cannot create user with exisiting email" do
100 admin = insert(:user, info: %{is_admin: true})
105 |> assign(:user, admin)
106 |> put_req_header("accept", "application/json")
107 |> post("/api/pleroma/admin/users", %{
110 "nickname" => "lain",
111 "email" => user.email,
117 assert json_response(conn, 409) == [
121 "email" => user.email,
124 "error" => "email has already been taken",
130 test "Cannot create user with exisiting nickname" do
131 admin = insert(:user, info: %{is_admin: true})
136 |> assign(:user, admin)
137 |> put_req_header("accept", "application/json")
138 |> post("/api/pleroma/admin/users", %{
141 "nickname" => user.nickname,
142 "email" => "someuser@plerama.social",
148 assert json_response(conn, 409) == [
152 "email" => "someuser@plerama.social",
153 "nickname" => user.nickname
155 "error" => "nickname has already been taken",
161 test "Multiple user creation works in transaction" do
162 admin = insert(:user, info: %{is_admin: true})
167 |> assign(:user, admin)
168 |> put_req_header("accept", "application/json")
169 |> post("/api/pleroma/admin/users", %{
172 "nickname" => "newuser",
173 "email" => "newuser@pleroma.social",
177 "nickname" => "lain",
178 "email" => user.email,
184 assert json_response(conn, 409) == [
188 "email" => user.email,
191 "error" => "email has already been taken",
197 "email" => "newuser@pleroma.social",
198 "nickname" => "newuser"
205 assert User.get_by_nickname("newuser") === nil
209 describe "/api/pleroma/admin/users/:nickname" do
210 test "Show", %{conn: conn} do
211 admin = insert(:user, info: %{is_admin: true})
216 |> assign(:user, admin)
217 |> get("/api/pleroma/admin/users/#{user.nickname}")
220 "deactivated" => false,
221 "id" => to_string(user.id),
223 "nickname" => user.nickname,
224 "roles" => %{"admin" => false, "moderator" => false},
226 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
227 "display_name" => HTML.strip_tags(user.name || user.nickname)
230 assert expected == json_response(conn, 200)
233 test "when the user doesn't exist", %{conn: conn} do
234 admin = insert(:user, info: %{is_admin: true})
239 |> assign(:user, admin)
240 |> get("/api/pleroma/admin/users/#{user.nickname}")
242 assert "Not found" == json_response(conn, 404)
246 describe "/api/pleroma/admin/users/follow" do
247 test "allows to force-follow another user" do
248 admin = insert(:user, info: %{is_admin: true})
250 follower = insert(:user)
253 |> assign(:user, admin)
254 |> put_req_header("accept", "application/json")
255 |> post("/api/pleroma/admin/users/follow", %{
256 "follower" => follower.nickname,
257 "followed" => user.nickname
260 user = User.get_cached_by_id(user.id)
261 follower = User.get_cached_by_id(follower.id)
263 assert User.following?(follower, user)
265 log_entry = Repo.one(ModerationLog)
267 assert ModerationLog.get_log_entry_message(log_entry) ==
268 "@#{admin.nickname} made @#{follower.nickname} follow @#{user.nickname}"
272 describe "/api/pleroma/admin/users/unfollow" do
273 test "allows to force-unfollow another user" do
274 admin = insert(:user, info: %{is_admin: true})
276 follower = insert(:user)
278 User.follow(follower, user)
281 |> assign(:user, admin)
282 |> put_req_header("accept", "application/json")
283 |> post("/api/pleroma/admin/users/unfollow", %{
284 "follower" => follower.nickname,
285 "followed" => user.nickname
288 user = User.get_cached_by_id(user.id)
289 follower = User.get_cached_by_id(follower.id)
291 refute User.following?(follower, user)
293 log_entry = Repo.one(ModerationLog)
295 assert ModerationLog.get_log_entry_message(log_entry) ==
296 "@#{admin.nickname} made @#{follower.nickname} unfollow @#{user.nickname}"
300 describe "PUT /api/pleroma/admin/users/tag" do
302 admin = insert(:user, info: %{is_admin: true})
303 user1 = insert(:user, %{tags: ["x"]})
304 user2 = insert(:user, %{tags: ["y"]})
305 user3 = insert(:user, %{tags: ["unchanged"]})
309 |> assign(:user, admin)
310 |> put_req_header("accept", "application/json")
312 "/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=#{
314 }&tags[]=foo&tags[]=bar"
317 %{conn: conn, admin: admin, user1: user1, user2: user2, user3: user3}
320 test "it appends specified tags to users with specified nicknames", %{
326 assert json_response(conn, :no_content)
327 assert User.get_cached_by_id(user1.id).tags == ["x", "foo", "bar"]
328 assert User.get_cached_by_id(user2.id).tags == ["y", "foo", "bar"]
330 log_entry = Repo.one(ModerationLog)
333 [user1.nickname, user2.nickname]
334 |> Enum.map(&"@#{&1}")
337 tags = ["foo", "bar"] |> Enum.join(", ")
339 assert ModerationLog.get_log_entry_message(log_entry) ==
340 "@#{admin.nickname} added tags: #{tags} to users: #{users}"
343 test "it does not modify tags of not specified users", %{conn: conn, user3: user3} do
344 assert json_response(conn, :no_content)
345 assert User.get_cached_by_id(user3.id).tags == ["unchanged"]
349 describe "DELETE /api/pleroma/admin/users/tag" do
351 admin = insert(:user, info: %{is_admin: true})
352 user1 = insert(:user, %{tags: ["x"]})
353 user2 = insert(:user, %{tags: ["y", "z"]})
354 user3 = insert(:user, %{tags: ["unchanged"]})
358 |> assign(:user, admin)
359 |> put_req_header("accept", "application/json")
361 "/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=#{
366 %{conn: conn, admin: admin, user1: user1, user2: user2, user3: user3}
369 test "it removes specified tags from users with specified nicknames", %{
375 assert json_response(conn, :no_content)
376 assert User.get_cached_by_id(user1.id).tags == []
377 assert User.get_cached_by_id(user2.id).tags == ["y"]
379 log_entry = Repo.one(ModerationLog)
382 [user1.nickname, user2.nickname]
383 |> Enum.map(&"@#{&1}")
386 tags = ["x", "z"] |> Enum.join(", ")
388 assert ModerationLog.get_log_entry_message(log_entry) ==
389 "@#{admin.nickname} removed tags: #{tags} from users: #{users}"
392 test "it does not modify tags of not specified users", %{conn: conn, user3: user3} do
393 assert json_response(conn, :no_content)
394 assert User.get_cached_by_id(user3.id).tags == ["unchanged"]
398 describe "/api/pleroma/admin/users/:nickname/permission_group" do
399 test "GET is giving user_info" do
400 admin = insert(:user, info: %{is_admin: true})
404 |> assign(:user, admin)
405 |> put_req_header("accept", "application/json")
406 |> get("/api/pleroma/admin/users/#{admin.nickname}/permission_group/")
408 assert json_response(conn, 200) == %{
410 "is_moderator" => false
414 test "/:right POST, can add to a permission group" do
415 admin = insert(:user, info: %{is_admin: true})
420 |> assign(:user, admin)
421 |> put_req_header("accept", "application/json")
422 |> post("/api/pleroma/admin/users/#{user.nickname}/permission_group/admin")
424 assert json_response(conn, 200) == %{
428 log_entry = Repo.one(ModerationLog)
430 assert ModerationLog.get_log_entry_message(log_entry) ==
431 "@#{admin.nickname} made @#{user.nickname} admin"
434 test "/:right POST, can add to a permission group (multiple)" do
435 admin = insert(:user, info: %{is_admin: true})
436 user_one = insert(:user)
437 user_two = insert(:user)
441 |> assign(:user, admin)
442 |> put_req_header("accept", "application/json")
443 |> post("/api/pleroma/admin/users/permission_group/admin", %{
444 nicknames: [user_one.nickname, user_two.nickname]
447 assert json_response(conn, 200) == %{
451 log_entry = Repo.one(ModerationLog)
453 assert ModerationLog.get_log_entry_message(log_entry) ==
454 "@#{admin.nickname} made @#{user_one.nickname}, @#{user_two.nickname} admin"
457 test "/:right DELETE, can remove from a permission group" do
458 admin = insert(:user, info: %{is_admin: true})
459 user = insert(:user, info: %{is_admin: true})
463 |> assign(:user, admin)
464 |> put_req_header("accept", "application/json")
465 |> delete("/api/pleroma/admin/users/#{user.nickname}/permission_group/admin")
467 assert json_response(conn, 200) == %{
471 log_entry = Repo.one(ModerationLog)
473 assert ModerationLog.get_log_entry_message(log_entry) ==
474 "@#{admin.nickname} revoked admin role from @#{user.nickname}"
477 test "/:right DELETE, can remove from a permission group (multiple)" do
478 admin = insert(:user, info: %{is_admin: true})
479 user_one = insert(:user, info: %{is_admin: true})
480 user_two = insert(:user, info: %{is_admin: true})
484 |> assign(:user, admin)
485 |> put_req_header("accept", "application/json")
486 |> delete("/api/pleroma/admin/users/permission_group/admin", %{
487 nicknames: [user_one.nickname, user_two.nickname]
490 assert json_response(conn, 200) == %{
494 log_entry = Repo.one(ModerationLog)
496 assert ModerationLog.get_log_entry_message(log_entry) ==
497 "@#{admin.nickname} revoked admin role from @#{user_one.nickname}, @#{
503 describe "POST /api/pleroma/admin/email_invite, with valid config" do
505 [user: insert(:user, info: %{is_admin: true})]
508 clear_config([:instance, :registrations_open]) do
509 Pleroma.Config.put([:instance, :registrations_open], false)
512 clear_config([:instance, :invites_enabled]) do
513 Pleroma.Config.put([:instance, :invites_enabled], true)
516 test "sends invitation and returns 204", %{conn: conn, user: user} do
517 recipient_email = "foo@bar.com"
518 recipient_name = "J. D."
522 |> assign(:user, user)
524 "/api/pleroma/admin/users/email_invite?email=#{recipient_email}&name=#{recipient_name}"
527 assert json_response(conn, :no_content)
529 token_record = List.last(Pleroma.Repo.all(Pleroma.UserInviteToken))
531 refute token_record.used
533 notify_email = Pleroma.Config.get([:instance, :notify_email])
534 instance_name = Pleroma.Config.get([:instance, :name])
537 Pleroma.Emails.UserEmail.user_invitation_email(
544 Swoosh.TestAssertions.assert_email_sent(
545 from: {instance_name, notify_email},
546 to: {recipient_name, recipient_email},
547 html_body: email.html_body
551 test "it returns 403 if requested by a non-admin", %{conn: conn} do
552 non_admin_user = insert(:user)
556 |> assign(:user, non_admin_user)
557 |> post("/api/pleroma/admin/users/email_invite?email=foo@bar.com&name=JD")
559 assert json_response(conn, :forbidden)
563 describe "POST /api/pleroma/admin/users/email_invite, with invalid config" do
565 [user: insert(:user, info: %{is_admin: true})]
568 clear_config([:instance, :registrations_open])
569 clear_config([:instance, :invites_enabled])
571 test "it returns 500 if `invites_enabled` is not enabled", %{conn: conn, user: user} do
572 Pleroma.Config.put([:instance, :registrations_open], false)
573 Pleroma.Config.put([:instance, :invites_enabled], false)
577 |> assign(:user, user)
578 |> post("/api/pleroma/admin/users/email_invite?email=foo@bar.com&name=JD")
580 assert json_response(conn, :internal_server_error)
583 test "it returns 500 if `registrations_open` is enabled", %{conn: conn, user: user} do
584 Pleroma.Config.put([:instance, :registrations_open], true)
585 Pleroma.Config.put([:instance, :invites_enabled], true)
589 |> assign(:user, user)
590 |> post("/api/pleroma/admin/users/email_invite?email=foo@bar.com&name=JD")
592 assert json_response(conn, :internal_server_error)
596 test "/api/pleroma/admin/users/:nickname/password_reset" do
597 admin = insert(:user, info: %{is_admin: true})
602 |> assign(:user, admin)
603 |> put_req_header("accept", "application/json")
604 |> get("/api/pleroma/admin/users/#{user.nickname}/password_reset")
606 resp = json_response(conn, 200)
608 assert Regex.match?(~r/(http:\/\/|https:\/\/)/, resp["link"])
611 describe "GET /api/pleroma/admin/users" do
613 admin = insert(:user, info: %{is_admin: true})
617 |> assign(:user, admin)
619 {:ok, conn: conn, admin: admin}
622 test "renders users array for the first page", %{conn: conn, admin: admin} do
623 user = insert(:user, local: false, tags: ["foo", "bar"])
624 conn = get(conn, "/api/pleroma/admin/users?page=1")
629 "deactivated" => admin.info.deactivated,
631 "nickname" => admin.nickname,
632 "roles" => %{"admin" => true, "moderator" => false},
635 "avatar" => User.avatar_url(admin) |> MediaProxy.url(),
636 "display_name" => HTML.strip_tags(admin.name || admin.nickname)
639 "deactivated" => user.info.deactivated,
641 "nickname" => user.nickname,
642 "roles" => %{"admin" => false, "moderator" => false},
644 "tags" => ["foo", "bar"],
645 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
646 "display_name" => HTML.strip_tags(user.name || user.nickname)
649 |> Enum.sort_by(& &1["nickname"])
651 assert json_response(conn, 200) == %{
658 test "renders empty array for the second page", %{conn: conn} do
661 conn = get(conn, "/api/pleroma/admin/users?page=2")
663 assert json_response(conn, 200) == %{
670 test "regular search", %{conn: conn} do
671 user = insert(:user, nickname: "bob")
673 conn = get(conn, "/api/pleroma/admin/users?query=bo")
675 assert json_response(conn, 200) == %{
680 "deactivated" => user.info.deactivated,
682 "nickname" => user.nickname,
683 "roles" => %{"admin" => false, "moderator" => false},
686 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
687 "display_name" => HTML.strip_tags(user.name || user.nickname)
693 test "search by domain", %{conn: conn} do
694 user = insert(:user, nickname: "nickname@domain.com")
697 conn = get(conn, "/api/pleroma/admin/users?query=domain.com")
699 assert json_response(conn, 200) == %{
704 "deactivated" => user.info.deactivated,
706 "nickname" => user.nickname,
707 "roles" => %{"admin" => false, "moderator" => false},
710 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
711 "display_name" => HTML.strip_tags(user.name || user.nickname)
717 test "search by full nickname", %{conn: conn} do
718 user = insert(:user, nickname: "nickname@domain.com")
721 conn = get(conn, "/api/pleroma/admin/users?query=nickname@domain.com")
723 assert json_response(conn, 200) == %{
728 "deactivated" => user.info.deactivated,
730 "nickname" => user.nickname,
731 "roles" => %{"admin" => false, "moderator" => false},
734 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
735 "display_name" => HTML.strip_tags(user.name || user.nickname)
741 test "search by display name", %{conn: conn} do
742 user = insert(:user, name: "Display name")
745 conn = get(conn, "/api/pleroma/admin/users?name=display")
747 assert json_response(conn, 200) == %{
752 "deactivated" => user.info.deactivated,
754 "nickname" => user.nickname,
755 "roles" => %{"admin" => false, "moderator" => false},
758 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
759 "display_name" => HTML.strip_tags(user.name || user.nickname)
765 test "search by email", %{conn: conn} do
766 user = insert(:user, email: "email@example.com")
769 conn = get(conn, "/api/pleroma/admin/users?email=email@example.com")
771 assert json_response(conn, 200) == %{
776 "deactivated" => user.info.deactivated,
778 "nickname" => user.nickname,
779 "roles" => %{"admin" => false, "moderator" => false},
782 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
783 "display_name" => HTML.strip_tags(user.name || user.nickname)
789 test "regular search with page size", %{conn: conn} do
790 user = insert(:user, nickname: "aalice")
791 user2 = insert(:user, nickname: "alice")
793 conn1 = get(conn, "/api/pleroma/admin/users?query=a&page_size=1&page=1")
795 assert json_response(conn1, 200) == %{
800 "deactivated" => user.info.deactivated,
802 "nickname" => user.nickname,
803 "roles" => %{"admin" => false, "moderator" => false},
806 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
807 "display_name" => HTML.strip_tags(user.name || user.nickname)
812 conn2 = get(conn, "/api/pleroma/admin/users?query=a&page_size=1&page=2")
814 assert json_response(conn2, 200) == %{
819 "deactivated" => user2.info.deactivated,
821 "nickname" => user2.nickname,
822 "roles" => %{"admin" => false, "moderator" => false},
825 "avatar" => User.avatar_url(user2) |> MediaProxy.url(),
826 "display_name" => HTML.strip_tags(user2.name || user2.nickname)
832 test "only local users" do
833 admin = insert(:user, info: %{is_admin: true}, nickname: "john")
834 user = insert(:user, nickname: "bob")
836 insert(:user, nickname: "bobb", local: false)
840 |> assign(:user, admin)
841 |> get("/api/pleroma/admin/users?query=bo&filters=local")
843 assert json_response(conn, 200) == %{
848 "deactivated" => user.info.deactivated,
850 "nickname" => user.nickname,
851 "roles" => %{"admin" => false, "moderator" => false},
854 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
855 "display_name" => HTML.strip_tags(user.name || user.nickname)
861 test "only local users with no query", %{admin: old_admin} do
862 admin = insert(:user, info: %{is_admin: true}, nickname: "john")
863 user = insert(:user, nickname: "bob")
865 insert(:user, nickname: "bobb", local: false)
869 |> assign(:user, admin)
870 |> get("/api/pleroma/admin/users?filters=local")
875 "deactivated" => user.info.deactivated,
877 "nickname" => user.nickname,
878 "roles" => %{"admin" => false, "moderator" => false},
881 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
882 "display_name" => HTML.strip_tags(user.name || user.nickname)
885 "deactivated" => admin.info.deactivated,
887 "nickname" => admin.nickname,
888 "roles" => %{"admin" => true, "moderator" => false},
891 "avatar" => User.avatar_url(admin) |> MediaProxy.url(),
892 "display_name" => HTML.strip_tags(admin.name || admin.nickname)
895 "deactivated" => false,
896 "id" => old_admin.id,
898 "nickname" => old_admin.nickname,
899 "roles" => %{"admin" => true, "moderator" => false},
901 "avatar" => User.avatar_url(old_admin) |> MediaProxy.url(),
902 "display_name" => HTML.strip_tags(old_admin.name || old_admin.nickname)
905 |> Enum.sort_by(& &1["nickname"])
907 assert json_response(conn, 200) == %{
914 test "load only admins", %{conn: conn, admin: admin} do
915 second_admin = insert(:user, info: %{is_admin: true})
919 conn = get(conn, "/api/pleroma/admin/users?filters=is_admin")
924 "deactivated" => false,
926 "nickname" => admin.nickname,
927 "roles" => %{"admin" => true, "moderator" => false},
928 "local" => admin.local,
930 "avatar" => User.avatar_url(admin) |> MediaProxy.url(),
931 "display_name" => HTML.strip_tags(admin.name || admin.nickname)
934 "deactivated" => false,
935 "id" => second_admin.id,
936 "nickname" => second_admin.nickname,
937 "roles" => %{"admin" => true, "moderator" => false},
938 "local" => second_admin.local,
940 "avatar" => User.avatar_url(second_admin) |> MediaProxy.url(),
941 "display_name" => HTML.strip_tags(second_admin.name || second_admin.nickname)
944 |> Enum.sort_by(& &1["nickname"])
946 assert json_response(conn, 200) == %{
953 test "load only moderators", %{conn: conn} do
954 moderator = insert(:user, info: %{is_moderator: true})
958 conn = get(conn, "/api/pleroma/admin/users?filters=is_moderator")
960 assert json_response(conn, 200) == %{
965 "deactivated" => false,
966 "id" => moderator.id,
967 "nickname" => moderator.nickname,
968 "roles" => %{"admin" => false, "moderator" => true},
969 "local" => moderator.local,
971 "avatar" => User.avatar_url(moderator) |> MediaProxy.url(),
972 "display_name" => HTML.strip_tags(moderator.name || moderator.nickname)
978 test "load users with tags list", %{conn: conn} do
979 user1 = insert(:user, tags: ["first"])
980 user2 = insert(:user, tags: ["second"])
984 conn = get(conn, "/api/pleroma/admin/users?tags[]=first&tags[]=second")
989 "deactivated" => false,
991 "nickname" => user1.nickname,
992 "roles" => %{"admin" => false, "moderator" => false},
993 "local" => user1.local,
995 "avatar" => User.avatar_url(user1) |> MediaProxy.url(),
996 "display_name" => HTML.strip_tags(user1.name || user1.nickname)
999 "deactivated" => false,
1001 "nickname" => user2.nickname,
1002 "roles" => %{"admin" => false, "moderator" => false},
1003 "local" => user2.local,
1004 "tags" => ["second"],
1005 "avatar" => User.avatar_url(user2) |> MediaProxy.url(),
1006 "display_name" => HTML.strip_tags(user2.name || user2.nickname)
1009 |> Enum.sort_by(& &1["nickname"])
1011 assert json_response(conn, 200) == %{
1018 test "it works with multiple filters" do
1019 admin = insert(:user, nickname: "john", info: %{is_admin: true})
1020 user = insert(:user, nickname: "bob", local: false, info: %{deactivated: true})
1022 insert(:user, nickname: "ken", local: true, info: %{deactivated: true})
1023 insert(:user, nickname: "bobb", local: false, info: %{deactivated: false})
1027 |> assign(:user, admin)
1028 |> get("/api/pleroma/admin/users?filters=deactivated,external")
1030 assert json_response(conn, 200) == %{
1035 "deactivated" => user.info.deactivated,
1037 "nickname" => user.nickname,
1038 "roles" => %{"admin" => false, "moderator" => false},
1039 "local" => user.local,
1041 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
1042 "display_name" => HTML.strip_tags(user.name || user.nickname)
1049 test "PATCH /api/pleroma/admin/users/activate" do
1050 admin = insert(:user, info: %{is_admin: true})
1051 user_one = insert(:user, info: %{deactivated: true})
1052 user_two = insert(:user, info: %{deactivated: true})
1056 |> assign(:user, admin)
1058 "/api/pleroma/admin/users/activate",
1059 %{nicknames: [user_one.nickname, user_two.nickname]}
1062 response = json_response(conn, 200)
1063 assert Enum.map(response["users"], & &1["deactivated"]) == [false, false]
1065 log_entry = Repo.one(ModerationLog)
1067 assert ModerationLog.get_log_entry_message(log_entry) ==
1068 "@#{admin.nickname} activated users: @#{user_one.nickname}, @#{user_two.nickname}"
1071 test "PATCH /api/pleroma/admin/users/deactivate" do
1072 admin = insert(:user, info: %{is_admin: true})
1073 user_one = insert(:user, info: %{deactivated: false})
1074 user_two = insert(:user, info: %{deactivated: false})
1078 |> assign(:user, admin)
1080 "/api/pleroma/admin/users/deactivate",
1081 %{nicknames: [user_one.nickname, user_two.nickname]}
1084 response = json_response(conn, 200)
1085 assert Enum.map(response["users"], & &1["deactivated"]) == [true, true]
1087 log_entry = Repo.one(ModerationLog)
1089 assert ModerationLog.get_log_entry_message(log_entry) ==
1090 "@#{admin.nickname} deactivated users: @#{user_one.nickname}, @#{user_two.nickname}"
1093 test "PATCH /api/pleroma/admin/users/:nickname/toggle_activation" do
1094 admin = insert(:user, info: %{is_admin: true})
1095 user = insert(:user)
1099 |> assign(:user, admin)
1100 |> patch("/api/pleroma/admin/users/#{user.nickname}/toggle_activation")
1102 assert json_response(conn, 200) ==
1104 "deactivated" => !user.info.deactivated,
1106 "nickname" => user.nickname,
1107 "roles" => %{"admin" => false, "moderator" => false},
1110 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
1111 "display_name" => HTML.strip_tags(user.name || user.nickname)
1114 log_entry = Repo.one(ModerationLog)
1116 assert ModerationLog.get_log_entry_message(log_entry) ==
1117 "@#{admin.nickname} deactivated users: @#{user.nickname}"
1120 describe "POST /api/pleroma/admin/users/invite_token" do
1122 admin = insert(:user, info: %{is_admin: true})
1126 |> assign(:user, admin)
1131 test "without options", %{conn: conn} do
1132 conn = post(conn, "/api/pleroma/admin/users/invite_token")
1134 invite_json = json_response(conn, 200)
1135 invite = UserInviteToken.find_by_token!(invite_json["token"])
1137 refute invite.expires_at
1138 refute invite.max_use
1139 assert invite.invite_type == "one_time"
1142 test "with expires_at", %{conn: conn} do
1144 post(conn, "/api/pleroma/admin/users/invite_token", %{
1145 "expires_at" => Date.to_string(Date.utc_today())
1148 invite_json = json_response(conn, 200)
1149 invite = UserInviteToken.find_by_token!(invite_json["token"])
1152 assert invite.expires_at == Date.utc_today()
1153 refute invite.max_use
1154 assert invite.invite_type == "date_limited"
1157 test "with max_use", %{conn: conn} do
1158 conn = post(conn, "/api/pleroma/admin/users/invite_token", %{"max_use" => 150})
1160 invite_json = json_response(conn, 200)
1161 invite = UserInviteToken.find_by_token!(invite_json["token"])
1163 refute invite.expires_at
1164 assert invite.max_use == 150
1165 assert invite.invite_type == "reusable"
1168 test "with max use and expires_at", %{conn: conn} do
1170 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"])
1178 assert invite.expires_at == Date.utc_today()
1179 assert invite.max_use == 150
1180 assert invite.invite_type == "reusable_date_limited"
1184 describe "GET /api/pleroma/admin/users/invites" do
1186 admin = insert(:user, info: %{is_admin: true})
1190 |> assign(:user, admin)
1195 test "no invites", %{conn: conn} do
1196 conn = get(conn, "/api/pleroma/admin/users/invites")
1198 assert json_response(conn, 200) == %{"invites" => []}
1201 test "with invite", %{conn: conn} do
1202 {:ok, invite} = UserInviteToken.create_invite()
1204 conn = get(conn, "/api/pleroma/admin/users/invites")
1206 assert json_response(conn, 200) == %{
1209 "expires_at" => nil,
1211 "invite_type" => "one_time",
1213 "token" => invite.token,
1222 describe "POST /api/pleroma/admin/users/revoke_invite" do
1223 test "with token" do
1224 admin = insert(:user, info: %{is_admin: true})
1225 {:ok, invite} = UserInviteToken.create_invite()
1229 |> assign(:user, admin)
1230 |> post("/api/pleroma/admin/users/revoke_invite", %{"token" => invite.token})
1232 assert json_response(conn, 200) == %{
1233 "expires_at" => nil,
1235 "invite_type" => "one_time",
1237 "token" => invite.token,
1243 test "with invalid token" do
1244 admin = insert(:user, info: %{is_admin: true})
1248 |> assign(:user, admin)
1249 |> post("/api/pleroma/admin/users/revoke_invite", %{"token" => "foo"})
1251 assert json_response(conn, :not_found) == "Not found"
1255 describe "GET /api/pleroma/admin/reports/:id" do
1256 setup %{conn: conn} do
1257 admin = insert(:user, info: %{is_admin: true})
1259 %{conn: assign(conn, :user, admin)}
1262 test "returns report by its id", %{conn: conn} do
1263 [reporter, target_user] = insert_pair(:user)
1264 activity = insert(:note_activity, user: target_user)
1266 {:ok, %{id: report_id}} =
1267 CommonAPI.report(reporter, %{
1268 "account_id" => target_user.id,
1269 "comment" => "I feel offended",
1270 "status_ids" => [activity.id]
1275 |> get("/api/pleroma/admin/reports/#{report_id}")
1276 |> json_response(:ok)
1278 assert response["id"] == report_id
1281 test "returns 404 when report id is invalid", %{conn: conn} do
1282 conn = get(conn, "/api/pleroma/admin/reports/test")
1284 assert json_response(conn, :not_found) == "Not found"
1288 describe "PUT /api/pleroma/admin/reports/:id" do
1289 setup %{conn: conn} do
1290 admin = insert(:user, info: %{is_admin: true})
1291 [reporter, target_user] = insert_pair(:user)
1292 activity = insert(:note_activity, user: target_user)
1294 {:ok, %{id: report_id}} =
1295 CommonAPI.report(reporter, %{
1296 "account_id" => target_user.id,
1297 "comment" => "I feel offended",
1298 "status_ids" => [activity.id]
1301 %{conn: assign(conn, :user, admin), id: report_id, admin: admin}
1304 test "mark report as resolved", %{conn: conn, id: id, admin: admin} do
1307 |> put("/api/pleroma/admin/reports/#{id}", %{"state" => "resolved"})
1308 |> json_response(:ok)
1310 assert response["state"] == "resolved"
1312 log_entry = Repo.one(ModerationLog)
1314 assert ModerationLog.get_log_entry_message(log_entry) ==
1315 "@#{admin.nickname} updated report ##{id} with 'resolved' state"
1318 test "closes report", %{conn: conn, id: id, admin: admin} do
1321 |> put("/api/pleroma/admin/reports/#{id}", %{"state" => "closed"})
1322 |> json_response(:ok)
1324 assert response["state"] == "closed"
1326 log_entry = Repo.one(ModerationLog)
1328 assert ModerationLog.get_log_entry_message(log_entry) ==
1329 "@#{admin.nickname} updated report ##{id} with 'closed' state"
1332 test "returns 400 when state is unknown", %{conn: conn, id: id} do
1335 |> put("/api/pleroma/admin/reports/#{id}", %{"state" => "test"})
1337 assert json_response(conn, :bad_request) == "Unsupported state"
1340 test "returns 404 when report is not exist", %{conn: conn} do
1343 |> put("/api/pleroma/admin/reports/test", %{"state" => "closed"})
1345 assert json_response(conn, :not_found) == "Not found"
1349 describe "GET /api/pleroma/admin/reports" do
1350 setup %{conn: conn} do
1351 admin = insert(:user, info: %{is_admin: true})
1353 %{conn: assign(conn, :user, admin)}
1356 test "returns empty response when no reports created", %{conn: conn} do
1359 |> get("/api/pleroma/admin/reports")
1360 |> json_response(:ok)
1362 assert Enum.empty?(response["reports"])
1363 assert response["total"] == 0
1366 test "returns reports", %{conn: conn} do
1367 [reporter, target_user] = insert_pair(:user)
1368 activity = insert(:note_activity, user: target_user)
1370 {:ok, %{id: report_id}} =
1371 CommonAPI.report(reporter, %{
1372 "account_id" => target_user.id,
1373 "comment" => "I feel offended",
1374 "status_ids" => [activity.id]
1379 |> get("/api/pleroma/admin/reports")
1380 |> json_response(:ok)
1382 [report] = response["reports"]
1384 assert length(response["reports"]) == 1
1385 assert report["id"] == report_id
1387 assert response["total"] == 1
1390 test "returns reports with specified state", %{conn: conn} do
1391 [reporter, target_user] = insert_pair(:user)
1392 activity = insert(:note_activity, user: target_user)
1394 {:ok, %{id: first_report_id}} =
1395 CommonAPI.report(reporter, %{
1396 "account_id" => target_user.id,
1397 "comment" => "I feel offended",
1398 "status_ids" => [activity.id]
1401 {:ok, %{id: second_report_id}} =
1402 CommonAPI.report(reporter, %{
1403 "account_id" => target_user.id,
1404 "comment" => "I don't like this user"
1407 CommonAPI.update_report_state(second_report_id, "closed")
1411 |> get("/api/pleroma/admin/reports", %{
1414 |> json_response(:ok)
1416 [open_report] = response["reports"]
1418 assert length(response["reports"]) == 1
1419 assert open_report["id"] == first_report_id
1421 assert response["total"] == 1
1425 |> get("/api/pleroma/admin/reports", %{
1428 |> json_response(:ok)
1430 [closed_report] = response["reports"]
1432 assert length(response["reports"]) == 1
1433 assert closed_report["id"] == second_report_id
1435 assert response["total"] == 1
1439 |> get("/api/pleroma/admin/reports", %{
1440 "state" => "resolved"
1442 |> json_response(:ok)
1444 assert Enum.empty?(response["reports"])
1445 assert response["total"] == 0
1448 test "returns 403 when requested by a non-admin" do
1449 user = insert(:user)
1453 |> assign(:user, user)
1454 |> get("/api/pleroma/admin/reports")
1456 assert json_response(conn, :forbidden) == %{"error" => "User is not admin."}
1459 test "returns 403 when requested by anonymous" do
1462 |> get("/api/pleroma/admin/reports")
1464 assert json_response(conn, :forbidden) == %{"error" => "Invalid credentials."}
1469 describe "POST /api/pleroma/admin/reports/:id/respond" do
1470 setup %{conn: conn} do
1471 admin = insert(:user, info: %{is_admin: true})
1473 %{conn: assign(conn, :user, admin), admin: admin}
1476 test "returns created dm", %{conn: conn, admin: admin} do
1477 [reporter, target_user] = insert_pair(:user)
1478 activity = insert(:note_activity, user: target_user)
1480 {:ok, %{id: report_id}} =
1481 CommonAPI.report(reporter, %{
1482 "account_id" => target_user.id,
1483 "comment" => "I feel offended",
1484 "status_ids" => [activity.id]
1489 |> post("/api/pleroma/admin/reports/#{report_id}/respond", %{
1490 "status" => "I will check it out"
1492 |> json_response(:ok)
1494 recipients = Enum.map(response["mentions"], & &1["username"])
1496 assert reporter.nickname in recipients
1497 assert response["content"] == "I will check it out"
1498 assert response["visibility"] == "direct"
1500 log_entry = Repo.one(ModerationLog)
1502 assert ModerationLog.get_log_entry_message(log_entry) ==
1503 "@#{admin.nickname} responded with 'I will check it out' to report ##{
1508 test "returns 400 when status is missing", %{conn: conn} do
1509 conn = post(conn, "/api/pleroma/admin/reports/test/respond")
1511 assert json_response(conn, :bad_request) == "Invalid parameters"
1514 test "returns 404 when report id is invalid", %{conn: conn} do
1516 post(conn, "/api/pleroma/admin/reports/test/respond", %{
1520 assert json_response(conn, :not_found) == "Not found"
1524 describe "PUT /api/pleroma/admin/statuses/:id" do
1525 setup %{conn: conn} do
1526 admin = insert(:user, info: %{is_admin: true})
1527 activity = insert(:note_activity)
1529 %{conn: assign(conn, :user, admin), id: activity.id, admin: admin}
1532 test "toggle sensitive flag", %{conn: conn, id: id, admin: admin} do
1535 |> put("/api/pleroma/admin/statuses/#{id}", %{"sensitive" => "true"})
1536 |> json_response(:ok)
1538 assert response["sensitive"]
1540 log_entry = Repo.one(ModerationLog)
1542 assert ModerationLog.get_log_entry_message(log_entry) ==
1543 "@#{admin.nickname} updated status ##{id}, set sensitive: 'true'"
1547 |> put("/api/pleroma/admin/statuses/#{id}", %{"sensitive" => "false"})
1548 |> json_response(:ok)
1550 refute response["sensitive"]
1553 test "change visibility flag", %{conn: conn, id: id, admin: admin} do
1556 |> put("/api/pleroma/admin/statuses/#{id}", %{"visibility" => "public"})
1557 |> json_response(:ok)
1559 assert response["visibility"] == "public"
1561 log_entry = Repo.one(ModerationLog)
1563 assert ModerationLog.get_log_entry_message(log_entry) ==
1564 "@#{admin.nickname} updated status ##{id}, set visibility: 'public'"
1568 |> put("/api/pleroma/admin/statuses/#{id}", %{"visibility" => "private"})
1569 |> json_response(:ok)
1571 assert response["visibility"] == "private"
1575 |> put("/api/pleroma/admin/statuses/#{id}", %{"visibility" => "unlisted"})
1576 |> json_response(:ok)
1578 assert response["visibility"] == "unlisted"
1581 test "returns 400 when visibility is unknown", %{conn: conn, id: id} do
1584 |> put("/api/pleroma/admin/statuses/#{id}", %{"visibility" => "test"})
1586 assert json_response(conn, :bad_request) == "Unsupported visibility"
1590 describe "DELETE /api/pleroma/admin/statuses/:id" do
1591 setup %{conn: conn} do
1592 admin = insert(:user, info: %{is_admin: true})
1593 activity = insert(:note_activity)
1595 %{conn: assign(conn, :user, admin), id: activity.id, admin: admin}
1598 test "deletes status", %{conn: conn, id: id, admin: admin} do
1600 |> delete("/api/pleroma/admin/statuses/#{id}")
1601 |> json_response(:ok)
1603 refute Activity.get_by_id(id)
1605 log_entry = Repo.one(ModerationLog)
1607 assert ModerationLog.get_log_entry_message(log_entry) ==
1608 "@#{admin.nickname} deleted status ##{id}"
1611 test "returns error when status is not exist", %{conn: conn} do
1614 |> delete("/api/pleroma/admin/statuses/test")
1616 assert json_response(conn, :bad_request) == "Could not delete"
1620 describe "GET /api/pleroma/admin/config" do
1621 setup %{conn: conn} do
1622 admin = insert(:user, info: %{is_admin: true})
1624 %{conn: assign(conn, :user, admin)}
1627 test "without any settings in db", %{conn: conn} do
1628 conn = get(conn, "/api/pleroma/admin/config")
1630 assert json_response(conn, 200) == %{"configs" => []}
1633 test "with settings in db", %{conn: conn} do
1634 config1 = insert(:config)
1635 config2 = insert(:config)
1637 conn = get(conn, "/api/pleroma/admin/config")
1650 } = json_response(conn, 200)
1652 assert key1 == config1.key
1653 assert key2 == config2.key
1657 describe "POST /api/pleroma/admin/config" do
1658 setup %{conn: conn} do
1659 admin = insert(:user, info: %{is_admin: true})
1661 temp_file = "config/test.exported_from_db.secret.exs"
1664 Application.delete_env(:pleroma, :key1)
1665 Application.delete_env(:pleroma, :key2)
1666 Application.delete_env(:pleroma, :key3)
1667 Application.delete_env(:pleroma, :key4)
1668 Application.delete_env(:pleroma, :keyaa1)
1669 Application.delete_env(:pleroma, :keyaa2)
1670 Application.delete_env(:pleroma, Pleroma.Web.Endpoint.NotReal)
1671 Application.delete_env(:pleroma, Pleroma.Captcha.NotReal)
1672 :ok = File.rm(temp_file)
1675 %{conn: assign(conn, :user, admin)}
1678 clear_config([:instance, :dynamic_configuration]) do
1679 Pleroma.Config.put([:instance, :dynamic_configuration], true)
1682 test "create new config setting in db", %{conn: conn} do
1684 post(conn, "/api/pleroma/admin/config", %{
1686 %{group: "pleroma", key: "key1", value: "value1"},
1689 key: "Ueberauth.Strategy.Twitter.OAuth",
1690 value: [%{"tuple" => [":consumer_secret", "aaaa"]}]
1696 ":nested_1" => "nested_value1",
1698 %{":nested_22" => "nested_value222"},
1699 %{":nested_33" => %{":nested_44" => "nested_444"}}
1707 %{"nested_3" => ":nested_3", "nested_33" => "nested_33"},
1708 %{"nested_4" => true}
1714 value: %{":nested_5" => ":upload", "endpoint" => "https://example.com"}
1719 value: %{"tuple" => ["string", "Pleroma.Captcha.NotReal", []]}
1724 assert json_response(conn, 200) == %{
1727 "group" => "pleroma",
1732 "group" => "ueberauth",
1733 "key" => "Ueberauth.Strategy.Twitter.OAuth",
1734 "value" => [%{"tuple" => [":consumer_secret", "aaaa"]}]
1737 "group" => "pleroma",
1740 ":nested_1" => "nested_value1",
1742 %{":nested_22" => "nested_value222"},
1743 %{":nested_33" => %{":nested_44" => "nested_444"}}
1748 "group" => "pleroma",
1751 %{"nested_3" => ":nested_3", "nested_33" => "nested_33"},
1752 %{"nested_4" => true}
1756 "group" => "pleroma",
1758 "value" => %{"endpoint" => "https://example.com", ":nested_5" => ":upload"}
1763 "value" => %{"tuple" => ["string", "Pleroma.Captcha.NotReal", []]}
1768 assert Application.get_env(:pleroma, :key1) == "value1"
1770 assert Application.get_env(:pleroma, :key2) == %{
1771 nested_1: "nested_value1",
1773 %{nested_22: "nested_value222"},
1774 %{nested_33: %{nested_44: "nested_444"}}
1778 assert Application.get_env(:pleroma, :key3) == [
1779 %{"nested_3" => :nested_3, "nested_33" => "nested_33"},
1780 %{"nested_4" => true}
1783 assert Application.get_env(:pleroma, :key4) == %{
1784 "endpoint" => "https://example.com",
1788 assert Application.get_env(:idna, :key5) == {"string", Pleroma.Captcha.NotReal, []}
1791 test "update config setting & delete", %{conn: conn} do
1792 config1 = insert(:config, key: "keyaa1")
1793 config2 = insert(:config, key: "keyaa2")
1797 key: "Ueberauth.Strategy.Microsoft.OAuth",
1798 value: :erlang.term_to_binary([])
1802 post(conn, "/api/pleroma/admin/config", %{
1804 %{group: config1.group, key: config1.key, value: "another_value"},
1805 %{group: config2.group, key: config2.key, delete: "true"},
1808 key: "Ueberauth.Strategy.Microsoft.OAuth",
1814 assert json_response(conn, 200) == %{
1817 "group" => "pleroma",
1818 "key" => config1.key,
1819 "value" => "another_value"
1824 assert Application.get_env(:pleroma, :keyaa1) == "another_value"
1825 refute Application.get_env(:pleroma, :keyaa2)
1828 test "common config example", %{conn: conn} do
1830 post(conn, "/api/pleroma/admin/config", %{
1833 "group" => "pleroma",
1834 "key" => "Pleroma.Captcha.NotReal",
1836 %{"tuple" => [":enabled", false]},
1837 %{"tuple" => [":method", "Pleroma.Captcha.Kocaptcha"]},
1838 %{"tuple" => [":seconds_valid", 60]},
1839 %{"tuple" => [":path", ""]},
1840 %{"tuple" => [":key1", nil]},
1841 %{"tuple" => [":partial_chain", "&:hackney_connect.partial_chain/1"]},
1842 %{"tuple" => [":regex1", "~r/https:\/\/example.com/"]},
1843 %{"tuple" => [":regex2", "~r/https:\/\/example.com/u"]},
1844 %{"tuple" => [":regex3", "~r/https:\/\/example.com/i"]},
1845 %{"tuple" => [":regex4", "~r/https:\/\/example.com/s"]}
1851 assert json_response(conn, 200) == %{
1854 "group" => "pleroma",
1855 "key" => "Pleroma.Captcha.NotReal",
1857 %{"tuple" => [":enabled", false]},
1858 %{"tuple" => [":method", "Pleroma.Captcha.Kocaptcha"]},
1859 %{"tuple" => [":seconds_valid", 60]},
1860 %{"tuple" => [":path", ""]},
1861 %{"tuple" => [":key1", nil]},
1862 %{"tuple" => [":partial_chain", "&:hackney_connect.partial_chain/1"]},
1863 %{"tuple" => [":regex1", "~r/https:\\/\\/example.com/"]},
1864 %{"tuple" => [":regex2", "~r/https:\\/\\/example.com/u"]},
1865 %{"tuple" => [":regex3", "~r/https:\\/\\/example.com/i"]},
1866 %{"tuple" => [":regex4", "~r/https:\\/\\/example.com/s"]}
1873 test "tuples with more than two values", %{conn: conn} do
1875 post(conn, "/api/pleroma/admin/config", %{
1878 "group" => "pleroma",
1879 "key" => "Pleroma.Web.Endpoint.NotReal",
1895 "/api/v1/streaming",
1896 "Pleroma.Web.MastodonAPI.WebsocketHandler",
1903 "Phoenix.Endpoint.CowboyWebSocket",
1906 "Phoenix.Transports.WebSocket",
1909 "Pleroma.Web.Endpoint",
1910 "Pleroma.Web.UserSocket",
1921 "Phoenix.Endpoint.Cowboy2Handler",
1922 %{"tuple" => ["Pleroma.Web.Endpoint", []]}
1939 assert json_response(conn, 200) == %{
1942 "group" => "pleroma",
1943 "key" => "Pleroma.Web.Endpoint.NotReal",
1959 "/api/v1/streaming",
1960 "Pleroma.Web.MastodonAPI.WebsocketHandler",
1967 "Phoenix.Endpoint.CowboyWebSocket",
1970 "Phoenix.Transports.WebSocket",
1973 "Pleroma.Web.Endpoint",
1974 "Pleroma.Web.UserSocket",
1985 "Phoenix.Endpoint.Cowboy2Handler",
1986 %{"tuple" => ["Pleroma.Web.Endpoint", []]}
2004 test "settings with nesting map", %{conn: conn} do
2006 post(conn, "/api/pleroma/admin/config", %{
2009 "group" => "pleroma",
2012 %{"tuple" => [":key2", "some_val"]},
2017 ":max_options" => 20,
2018 ":max_option_chars" => 200,
2019 ":min_expiration" => 0,
2020 ":max_expiration" => 31_536_000,
2022 ":max_options" => 20,
2023 ":max_option_chars" => 200,
2024 ":min_expiration" => 0,
2025 ":max_expiration" => 31_536_000
2035 assert json_response(conn, 200) ==
2039 "group" => "pleroma",
2042 %{"tuple" => [":key2", "some_val"]},
2047 ":max_expiration" => 31_536_000,
2048 ":max_option_chars" => 200,
2049 ":max_options" => 20,
2050 ":min_expiration" => 0,
2052 ":max_expiration" => 31_536_000,
2053 ":max_option_chars" => 200,
2054 ":max_options" => 20,
2055 ":min_expiration" => 0
2066 test "value as map", %{conn: conn} do
2068 post(conn, "/api/pleroma/admin/config", %{
2071 "group" => "pleroma",
2073 "value" => %{"key" => "some_val"}
2078 assert json_response(conn, 200) ==
2082 "group" => "pleroma",
2084 "value" => %{"key" => "some_val"}
2090 test "dispatch setting", %{conn: conn} do
2092 post(conn, "/api/pleroma/admin/config", %{
2095 "group" => "pleroma",
2096 "key" => "Pleroma.Web.Endpoint.NotReal",
2102 %{"tuple" => [":ip", %{"tuple" => [127, 0, 0, 1]}]},
2103 %{"tuple" => [":dispatch", ["{:_,
2105 {\"/api/v1/streaming\", Pleroma.Web.MastodonAPI.WebsocketHandler, []},
2106 {\"/websocket\", Phoenix.Endpoint.CowboyWebSocket,
2107 {Phoenix.Transports.WebSocket,
2108 {Pleroma.Web.Endpoint, Pleroma.Web.UserSocket, [path: \"/websocket\"]}}},
2109 {:_, Phoenix.Endpoint.Cowboy2Handler, {Pleroma.Web.Endpoint, []}}
2120 "{:_, [{\"/api/v1/streaming\", Pleroma.Web.MastodonAPI.WebsocketHandler, []}, " <>
2121 "{\"/websocket\", Phoenix.Endpoint.CowboyWebSocket, {Phoenix.Transports.WebSocket, " <>
2122 "{Pleroma.Web.Endpoint, Pleroma.Web.UserSocket, [path: \"/websocket\"]}}}, " <>
2123 "{:_, Phoenix.Endpoint.Cowboy2Handler, {Pleroma.Web.Endpoint, []}}]}"
2125 assert json_response(conn, 200) == %{
2128 "group" => "pleroma",
2129 "key" => "Pleroma.Web.Endpoint.NotReal",
2135 %{"tuple" => [":ip", %{"tuple" => [127, 0, 0, 1]}]},
2153 test "queues key as atom", %{conn: conn} do
2155 post(conn, "/api/pleroma/admin/config", %{
2161 %{"tuple" => [":federator_incoming", 50]},
2162 %{"tuple" => [":federator_outgoing", 50]},
2163 %{"tuple" => [":web_push", 50]},
2164 %{"tuple" => [":mailer", 10]},
2165 %{"tuple" => [":transmogrifier", 20]},
2166 %{"tuple" => [":scheduled_activities", 10]},
2167 %{"tuple" => [":background", 5]}
2173 assert json_response(conn, 200) == %{
2179 %{"tuple" => [":federator_incoming", 50]},
2180 %{"tuple" => [":federator_outgoing", 50]},
2181 %{"tuple" => [":web_push", 50]},
2182 %{"tuple" => [":mailer", 10]},
2183 %{"tuple" => [":transmogrifier", 20]},
2184 %{"tuple" => [":scheduled_activities", 10]},
2185 %{"tuple" => [":background", 5]}
2192 test "delete part of settings by atom subkeys", %{conn: conn} do
2196 value: :erlang.term_to_binary(subkey1: "val1", subkey2: "val2", subkey3: "val3")
2200 post(conn, "/api/pleroma/admin/config", %{
2203 group: config.group,
2205 subkeys: [":subkey1", ":subkey3"],
2212 json_response(conn, 200) == %{
2215 "group" => "pleroma",
2217 "value" => [%{"tuple" => [":subkey2", "val2"]}]
2225 describe "config mix tasks run" do
2226 setup %{conn: conn} do
2227 admin = insert(:user, info: %{is_admin: true})
2229 temp_file = "config/test.exported_from_db.secret.exs"
2231 Mix.shell(Mix.Shell.Quiet)
2234 Mix.shell(Mix.Shell.IO)
2235 :ok = File.rm(temp_file)
2238 %{conn: assign(conn, :user, admin), admin: admin}
2241 clear_config([:instance, :dynamic_configuration]) do
2242 Pleroma.Config.put([:instance, :dynamic_configuration], true)
2245 test "transfer settings to DB and to file", %{conn: conn, admin: admin} do
2246 assert Pleroma.Repo.all(Pleroma.Web.AdminAPI.Config) == []
2247 conn = get(conn, "/api/pleroma/admin/config/migrate_to_db")
2248 assert json_response(conn, 200) == %{}
2249 assert Pleroma.Repo.all(Pleroma.Web.AdminAPI.Config) > 0
2253 |> assign(:user, admin)
2254 |> get("/api/pleroma/admin/config/migrate_from_db")
2256 assert json_response(conn, 200) == %{}
2257 assert Pleroma.Repo.all(Pleroma.Web.AdminAPI.Config) == []
2261 describe "GET /api/pleroma/admin/users/:nickname/statuses" do
2263 admin = insert(:user, info: %{is_admin: true})
2264 user = insert(:user)
2266 date1 = (DateTime.to_unix(DateTime.utc_now()) + 2000) |> DateTime.from_unix!()
2267 date2 = (DateTime.to_unix(DateTime.utc_now()) + 1000) |> DateTime.from_unix!()
2268 date3 = (DateTime.to_unix(DateTime.utc_now()) + 3000) |> DateTime.from_unix!()
2270 insert(:note_activity, user: user, published: date1)
2271 insert(:note_activity, user: user, published: date2)
2272 insert(:note_activity, user: user, published: date3)
2276 |> assign(:user, admin)
2278 {:ok, conn: conn, user: user}
2281 test "renders user's statuses", %{conn: conn, user: user} do
2282 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses")
2284 assert json_response(conn, 200) |> length() == 3
2287 test "renders user's statuses with a limit", %{conn: conn, user: user} do
2288 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses?page_size=2")
2290 assert json_response(conn, 200) |> length() == 2
2293 test "doesn't return private statuses by default", %{conn: conn, user: user} do
2294 {:ok, _private_status} =
2295 CommonAPI.post(user, %{"status" => "private", "visibility" => "private"})
2297 {:ok, _public_status} =
2298 CommonAPI.post(user, %{"status" => "public", "visibility" => "public"})
2300 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses")
2302 assert json_response(conn, 200) |> length() == 4
2305 test "returns private statuses with godmode on", %{conn: conn, user: user} do
2306 {:ok, _private_status} =
2307 CommonAPI.post(user, %{"status" => "private", "visibility" => "private"})
2309 {:ok, _public_status} =
2310 CommonAPI.post(user, %{"status" => "public", "visibility" => "public"})
2312 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses?godmode=true")
2314 assert json_response(conn, 200) |> length() == 5
2318 describe "GET /api/pleroma/admin/moderation_log" do
2319 setup %{conn: conn} do
2320 admin = insert(:user, info: %{is_admin: true})
2321 moderator = insert(:user, info: %{is_moderator: true})
2323 %{conn: assign(conn, :user, admin), admin: admin, moderator: moderator}
2326 test "returns the log", %{conn: conn, admin: admin} do
2327 Repo.insert(%ModerationLog{
2331 "nickname" => admin.nickname,
2334 action: "relay_follow",
2335 target: "https://example.org/relay"
2337 inserted_at: NaiveDateTime.truncate(~N[2017-08-15 15:47:06.597036], :second)
2340 Repo.insert(%ModerationLog{
2344 "nickname" => admin.nickname,
2347 action: "relay_unfollow",
2348 target: "https://example.org/relay"
2350 inserted_at: NaiveDateTime.truncate(~N[2017-08-16 15:47:06.597036], :second)
2353 conn = get(conn, "/api/pleroma/admin/moderation_log")
2355 response = json_response(conn, 200)
2356 [first_entry, second_entry] = response["items"]
2358 assert response["total"] == 2
2359 assert first_entry["data"]["action"] == "relay_unfollow"
2361 assert first_entry["message"] ==
2362 "@#{admin.nickname} unfollowed relay: https://example.org/relay"
2364 assert second_entry["data"]["action"] == "relay_follow"
2366 assert second_entry["message"] ==
2367 "@#{admin.nickname} followed relay: https://example.org/relay"
2370 test "returns the log with pagination", %{conn: conn, admin: admin} do
2371 Repo.insert(%ModerationLog{
2375 "nickname" => admin.nickname,
2378 action: "relay_follow",
2379 target: "https://example.org/relay"
2381 inserted_at: NaiveDateTime.truncate(~N[2017-08-15 15:47:06.597036], :second)
2384 Repo.insert(%ModerationLog{
2388 "nickname" => admin.nickname,
2391 action: "relay_unfollow",
2392 target: "https://example.org/relay"
2394 inserted_at: NaiveDateTime.truncate(~N[2017-08-16 15:47:06.597036], :second)
2397 conn1 = get(conn, "/api/pleroma/admin/moderation_log?page_size=1&page=1")
2399 response1 = json_response(conn1, 200)
2400 [first_entry] = response1["items"]
2402 assert response1["total"] == 2
2403 assert response1["items"] |> length() == 1
2404 assert first_entry["data"]["action"] == "relay_unfollow"
2406 assert first_entry["message"] ==
2407 "@#{admin.nickname} unfollowed relay: https://example.org/relay"
2409 conn2 = get(conn, "/api/pleroma/admin/moderation_log?page_size=1&page=2")
2411 response2 = json_response(conn2, 200)
2412 [second_entry] = response2["items"]
2414 assert response2["total"] == 2
2415 assert response2["items"] |> length() == 1
2416 assert second_entry["data"]["action"] == "relay_follow"
2418 assert second_entry["message"] ==
2419 "@#{admin.nickname} followed relay: https://example.org/relay"
2422 test "filters log by date", %{conn: conn, admin: admin} do
2423 first_date = "2017-08-15T15:47:06Z"
2424 second_date = "2017-08-20T15:47:06Z"
2426 Repo.insert(%ModerationLog{
2430 "nickname" => admin.nickname,
2433 action: "relay_follow",
2434 target: "https://example.org/relay"
2436 inserted_at: NaiveDateTime.from_iso8601!(first_date)
2439 Repo.insert(%ModerationLog{
2443 "nickname" => admin.nickname,
2446 action: "relay_unfollow",
2447 target: "https://example.org/relay"
2449 inserted_at: NaiveDateTime.from_iso8601!(second_date)
2455 "/api/pleroma/admin/moderation_log?start_date=#{second_date}"
2458 response1 = json_response(conn1, 200)
2459 [first_entry] = response1["items"]
2461 assert response1["total"] == 1
2462 assert first_entry["data"]["action"] == "relay_unfollow"
2464 assert first_entry["message"] ==
2465 "@#{admin.nickname} unfollowed relay: https://example.org/relay"
2468 test "returns log filtered by user", %{conn: conn, admin: admin, moderator: moderator} do
2469 Repo.insert(%ModerationLog{
2473 "nickname" => admin.nickname,
2476 action: "relay_follow",
2477 target: "https://example.org/relay"
2481 Repo.insert(%ModerationLog{
2484 "id" => moderator.id,
2485 "nickname" => moderator.nickname,
2488 action: "relay_unfollow",
2489 target: "https://example.org/relay"
2493 conn1 = get(conn, "/api/pleroma/admin/moderation_log?user_id=#{moderator.id}")
2495 response1 = json_response(conn1, 200)
2496 [first_entry] = response1["items"]
2498 assert response1["total"] == 1
2499 assert get_in(first_entry, ["data", "actor", "id"]) == moderator.id
2502 test "returns log filtered by search", %{conn: conn, moderator: moderator} do
2503 ModerationLog.insert_log(%{
2505 action: "relay_follow",
2506 target: "https://example.org/relay"
2509 ModerationLog.insert_log(%{
2511 action: "relay_unfollow",
2512 target: "https://example.org/relay"
2515 conn1 = get(conn, "/api/pleroma/admin/moderation_log?search=unfo")
2517 response1 = json_response(conn1, 200)
2518 [first_entry] = response1["items"]
2520 assert response1["total"] == 1
2522 assert get_in(first_entry, ["data", "message"]) ==
2523 "@#{moderator.nickname} unfollowed relay: https://example.org/relay"
2527 describe "PATCH /users/:nickname/force_password_reset" do
2528 setup %{conn: conn} do
2529 admin = insert(:user, info: %{is_admin: true})
2530 user = insert(:user)
2532 %{conn: assign(conn, :user, admin), admin: admin, user: user}
2535 test "sets password_reset_pending to true", %{admin: admin, user: user} do
2536 assert user.info.password_reset_pending == false
2540 |> assign(:user, admin)
2541 |> patch("/api/pleroma/admin/users/#{user.nickname}/force_password_reset")
2543 assert json_response(conn, 204) == ""
2545 ObanHelpers.perform_all()
2547 assert User.get_by_id(user.id).info.password_reset_pending == true
2551 describe "relays" do
2552 setup %{conn: conn} do
2553 admin = insert(:user, info: %{is_admin: true})
2555 %{conn: assign(conn, :user, admin), admin: admin}
2558 test "POST /relay", %{admin: admin} do
2561 |> assign(:user, admin)
2562 |> post("/api/pleroma/admin/relay", %{
2563 relay_url: "http://mastodon.example.org/users/admin"
2566 assert json_response(conn, 200) == "http://mastodon.example.org/users/admin"
2568 log_entry = Repo.one(ModerationLog)
2570 assert ModerationLog.get_log_entry_message(log_entry) ==
2571 "@#{admin.nickname} followed relay: http://mastodon.example.org/users/admin"
2574 test "GET /relay", %{admin: admin} do
2575 Pleroma.Web.ActivityPub.Relay.get_actor()
2576 |> Ecto.Changeset.change(
2578 "http://test-app.com/user/test1",
2579 "http://test-app.com/user/test1",
2580 "http://test-app-42.com/user/test1"
2583 |> Pleroma.User.update_and_set_cache()
2587 |> assign(:user, admin)
2588 |> get("/api/pleroma/admin/relay")
2590 assert json_response(conn, 200)["relays"] -- ["test-app.com", "test-app-42.com"] == []
2593 test "DELETE /relay", %{admin: admin} do
2595 |> assign(:user, admin)
2596 |> post("/api/pleroma/admin/relay", %{
2597 relay_url: "http://mastodon.example.org/users/admin"
2602 |> assign(:user, admin)
2603 |> delete("/api/pleroma/admin/relay", %{
2604 relay_url: "http://mastodon.example.org/users/admin"
2607 assert json_response(conn, 200) == "http://mastodon.example.org/users/admin"
2609 [log_entry_one, log_entry_two] = Repo.all(ModerationLog)
2611 assert ModerationLog.get_log_entry_message(log_entry_one) ==
2612 "@#{admin.nickname} followed relay: http://mastodon.example.org/users/admin"
2614 assert ModerationLog.get_log_entry_message(log_entry_two) ==
2615 "@#{admin.nickname} unfollowed relay: http://mastodon.example.org/users/admin"
2620 # Needed for testing
2621 defmodule Pleroma.Web.Endpoint.NotReal do
2624 defmodule Pleroma.Captcha.NotReal do