Implement report notes destruction
[akkoma] / test / web / admin_api / admin_api_controller_test.exs
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
3 # SPDX-License-Identifier: AGPL-3.0-only
4
5 defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
6 use Pleroma.Web.ConnCase
7 use Oban.Testing, repo: Pleroma.Repo
8
9 alias Pleroma.Activity
10 alias Pleroma.HTML
11 alias Pleroma.ModerationLog
12 alias Pleroma.Repo
13 alias Pleroma.ReportNote
14 alias Pleroma.Tests.ObanHelpers
15 alias Pleroma.User
16 alias Pleroma.UserInviteToken
17 alias Pleroma.Web.ActivityPub.Relay
18 alias Pleroma.Web.CommonAPI
19 alias Pleroma.Web.MediaProxy
20 import Pleroma.Factory
21
22 setup_all do
23 Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
24
25 :ok
26 end
27
28 describe "DELETE /api/pleroma/admin/users" do
29 test "single user" do
30 admin = insert(:user, is_admin: true)
31 user = insert(:user)
32
33 conn =
34 build_conn()
35 |> assign(:user, admin)
36 |> put_req_header("accept", "application/json")
37 |> delete("/api/pleroma/admin/users?nickname=#{user.nickname}")
38
39 log_entry = Repo.one(ModerationLog)
40
41 assert ModerationLog.get_log_entry_message(log_entry) ==
42 "@#{admin.nickname} deleted users: @#{user.nickname}"
43
44 assert json_response(conn, 200) == user.nickname
45 end
46
47 test "multiple users" do
48 admin = insert(:user, is_admin: true)
49 user_one = insert(:user)
50 user_two = insert(:user)
51
52 conn =
53 build_conn()
54 |> assign(:user, admin)
55 |> put_req_header("accept", "application/json")
56 |> delete("/api/pleroma/admin/users", %{
57 nicknames: [user_one.nickname, user_two.nickname]
58 })
59
60 log_entry = Repo.one(ModerationLog)
61
62 assert ModerationLog.get_log_entry_message(log_entry) ==
63 "@#{admin.nickname} deleted users: @#{user_one.nickname}, @#{user_two.nickname}"
64
65 response = json_response(conn, 200)
66 assert response -- [user_one.nickname, user_two.nickname] == []
67 end
68 end
69
70 describe "/api/pleroma/admin/users" do
71 test "Create" do
72 admin = insert(:user, is_admin: true)
73
74 conn =
75 build_conn()
76 |> assign(:user, admin)
77 |> put_req_header("accept", "application/json")
78 |> post("/api/pleroma/admin/users", %{
79 "users" => [
80 %{
81 "nickname" => "lain",
82 "email" => "lain@example.org",
83 "password" => "test"
84 },
85 %{
86 "nickname" => "lain2",
87 "email" => "lain2@example.org",
88 "password" => "test"
89 }
90 ]
91 })
92
93 response = json_response(conn, 200) |> Enum.map(&Map.get(&1, "type"))
94 assert response == ["success", "success"]
95
96 log_entry = Repo.one(ModerationLog)
97
98 assert ["lain", "lain2"] -- Enum.map(log_entry.data["subjects"], & &1["nickname"]) == []
99 end
100
101 test "Cannot create user with exisiting email" do
102 admin = insert(:user, is_admin: true)
103 user = insert(:user)
104
105 conn =
106 build_conn()
107 |> assign(:user, admin)
108 |> put_req_header("accept", "application/json")
109 |> post("/api/pleroma/admin/users", %{
110 "users" => [
111 %{
112 "nickname" => "lain",
113 "email" => user.email,
114 "password" => "test"
115 }
116 ]
117 })
118
119 assert json_response(conn, 409) == [
120 %{
121 "code" => 409,
122 "data" => %{
123 "email" => user.email,
124 "nickname" => "lain"
125 },
126 "error" => "email has already been taken",
127 "type" => "error"
128 }
129 ]
130 end
131
132 test "Cannot create user with exisiting nickname" do
133 admin = insert(:user, is_admin: true)
134 user = insert(:user)
135
136 conn =
137 build_conn()
138 |> assign(:user, admin)
139 |> put_req_header("accept", "application/json")
140 |> post("/api/pleroma/admin/users", %{
141 "users" => [
142 %{
143 "nickname" => user.nickname,
144 "email" => "someuser@plerama.social",
145 "password" => "test"
146 }
147 ]
148 })
149
150 assert json_response(conn, 409) == [
151 %{
152 "code" => 409,
153 "data" => %{
154 "email" => "someuser@plerama.social",
155 "nickname" => user.nickname
156 },
157 "error" => "nickname has already been taken",
158 "type" => "error"
159 }
160 ]
161 end
162
163 test "Multiple user creation works in transaction" do
164 admin = insert(:user, is_admin: true)
165 user = insert(:user)
166
167 conn =
168 build_conn()
169 |> assign(:user, admin)
170 |> put_req_header("accept", "application/json")
171 |> post("/api/pleroma/admin/users", %{
172 "users" => [
173 %{
174 "nickname" => "newuser",
175 "email" => "newuser@pleroma.social",
176 "password" => "test"
177 },
178 %{
179 "nickname" => "lain",
180 "email" => user.email,
181 "password" => "test"
182 }
183 ]
184 })
185
186 assert json_response(conn, 409) == [
187 %{
188 "code" => 409,
189 "data" => %{
190 "email" => user.email,
191 "nickname" => "lain"
192 },
193 "error" => "email has already been taken",
194 "type" => "error"
195 },
196 %{
197 "code" => 409,
198 "data" => %{
199 "email" => "newuser@pleroma.social",
200 "nickname" => "newuser"
201 },
202 "error" => "",
203 "type" => "error"
204 }
205 ]
206
207 assert User.get_by_nickname("newuser") === nil
208 end
209 end
210
211 describe "/api/pleroma/admin/users/:nickname" do
212 test "Show", %{conn: conn} do
213 admin = insert(:user, is_admin: true)
214 user = insert(:user)
215
216 conn =
217 conn
218 |> assign(:user, admin)
219 |> get("/api/pleroma/admin/users/#{user.nickname}")
220
221 expected = %{
222 "deactivated" => false,
223 "id" => to_string(user.id),
224 "local" => true,
225 "nickname" => user.nickname,
226 "roles" => %{"admin" => false, "moderator" => false},
227 "tags" => [],
228 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
229 "display_name" => HTML.strip_tags(user.name || user.nickname),
230 "confirmation_pending" => false
231 }
232
233 assert expected == json_response(conn, 200)
234 end
235
236 test "when the user doesn't exist", %{conn: conn} do
237 admin = insert(:user, is_admin: true)
238 user = build(:user)
239
240 conn =
241 conn
242 |> assign(:user, admin)
243 |> get("/api/pleroma/admin/users/#{user.nickname}")
244
245 assert "Not found" == json_response(conn, 404)
246 end
247 end
248
249 describe "/api/pleroma/admin/users/follow" do
250 test "allows to force-follow another user" do
251 admin = insert(:user, is_admin: true)
252 user = insert(:user)
253 follower = insert(:user)
254
255 build_conn()
256 |> assign(:user, admin)
257 |> put_req_header("accept", "application/json")
258 |> post("/api/pleroma/admin/users/follow", %{
259 "follower" => follower.nickname,
260 "followed" => user.nickname
261 })
262
263 user = User.get_cached_by_id(user.id)
264 follower = User.get_cached_by_id(follower.id)
265
266 assert User.following?(follower, user)
267
268 log_entry = Repo.one(ModerationLog)
269
270 assert ModerationLog.get_log_entry_message(log_entry) ==
271 "@#{admin.nickname} made @#{follower.nickname} follow @#{user.nickname}"
272 end
273 end
274
275 describe "/api/pleroma/admin/users/unfollow" do
276 test "allows to force-unfollow another user" do
277 admin = insert(:user, is_admin: true)
278 user = insert(:user)
279 follower = insert(:user)
280
281 User.follow(follower, user)
282
283 build_conn()
284 |> assign(:user, admin)
285 |> put_req_header("accept", "application/json")
286 |> post("/api/pleroma/admin/users/unfollow", %{
287 "follower" => follower.nickname,
288 "followed" => user.nickname
289 })
290
291 user = User.get_cached_by_id(user.id)
292 follower = User.get_cached_by_id(follower.id)
293
294 refute User.following?(follower, user)
295
296 log_entry = Repo.one(ModerationLog)
297
298 assert ModerationLog.get_log_entry_message(log_entry) ==
299 "@#{admin.nickname} made @#{follower.nickname} unfollow @#{user.nickname}"
300 end
301 end
302
303 describe "PUT /api/pleroma/admin/users/tag" do
304 setup do
305 admin = insert(:user, is_admin: true)
306 user1 = insert(:user, %{tags: ["x"]})
307 user2 = insert(:user, %{tags: ["y"]})
308 user3 = insert(:user, %{tags: ["unchanged"]})
309
310 conn =
311 build_conn()
312 |> assign(:user, admin)
313 |> put_req_header("accept", "application/json")
314 |> put(
315 "/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=#{
316 user2.nickname
317 }&tags[]=foo&tags[]=bar"
318 )
319
320 %{conn: conn, admin: admin, user1: user1, user2: user2, user3: user3}
321 end
322
323 test "it appends specified tags to users with specified nicknames", %{
324 conn: conn,
325 admin: admin,
326 user1: user1,
327 user2: user2
328 } do
329 assert json_response(conn, :no_content)
330 assert User.get_cached_by_id(user1.id).tags == ["x", "foo", "bar"]
331 assert User.get_cached_by_id(user2.id).tags == ["y", "foo", "bar"]
332
333 log_entry = Repo.one(ModerationLog)
334
335 users =
336 [user1.nickname, user2.nickname]
337 |> Enum.map(&"@#{&1}")
338 |> Enum.join(", ")
339
340 tags = ["foo", "bar"] |> Enum.join(", ")
341
342 assert ModerationLog.get_log_entry_message(log_entry) ==
343 "@#{admin.nickname} added tags: #{tags} to users: #{users}"
344 end
345
346 test "it does not modify tags of not specified users", %{conn: conn, user3: user3} do
347 assert json_response(conn, :no_content)
348 assert User.get_cached_by_id(user3.id).tags == ["unchanged"]
349 end
350 end
351
352 describe "DELETE /api/pleroma/admin/users/tag" do
353 setup do
354 admin = insert(:user, is_admin: true)
355 user1 = insert(:user, %{tags: ["x"]})
356 user2 = insert(:user, %{tags: ["y", "z"]})
357 user3 = insert(:user, %{tags: ["unchanged"]})
358
359 conn =
360 build_conn()
361 |> assign(:user, admin)
362 |> put_req_header("accept", "application/json")
363 |> delete(
364 "/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=#{
365 user2.nickname
366 }&tags[]=x&tags[]=z"
367 )
368
369 %{conn: conn, admin: admin, user1: user1, user2: user2, user3: user3}
370 end
371
372 test "it removes specified tags from users with specified nicknames", %{
373 conn: conn,
374 admin: admin,
375 user1: user1,
376 user2: user2
377 } do
378 assert json_response(conn, :no_content)
379 assert User.get_cached_by_id(user1.id).tags == []
380 assert User.get_cached_by_id(user2.id).tags == ["y"]
381
382 log_entry = Repo.one(ModerationLog)
383
384 users =
385 [user1.nickname, user2.nickname]
386 |> Enum.map(&"@#{&1}")
387 |> Enum.join(", ")
388
389 tags = ["x", "z"] |> Enum.join(", ")
390
391 assert ModerationLog.get_log_entry_message(log_entry) ==
392 "@#{admin.nickname} removed tags: #{tags} from users: #{users}"
393 end
394
395 test "it does not modify tags of not specified users", %{conn: conn, user3: user3} do
396 assert json_response(conn, :no_content)
397 assert User.get_cached_by_id(user3.id).tags == ["unchanged"]
398 end
399 end
400
401 describe "/api/pleroma/admin/users/:nickname/permission_group" do
402 test "GET is giving user_info" do
403 admin = insert(:user, is_admin: true)
404
405 conn =
406 build_conn()
407 |> assign(:user, admin)
408 |> put_req_header("accept", "application/json")
409 |> get("/api/pleroma/admin/users/#{admin.nickname}/permission_group/")
410
411 assert json_response(conn, 200) == %{
412 "is_admin" => true,
413 "is_moderator" => false
414 }
415 end
416
417 test "/:right POST, can add to a permission group" do
418 admin = insert(:user, is_admin: true)
419 user = insert(:user)
420
421 conn =
422 build_conn()
423 |> assign(:user, admin)
424 |> put_req_header("accept", "application/json")
425 |> post("/api/pleroma/admin/users/#{user.nickname}/permission_group/admin")
426
427 assert json_response(conn, 200) == %{
428 "is_admin" => true
429 }
430
431 log_entry = Repo.one(ModerationLog)
432
433 assert ModerationLog.get_log_entry_message(log_entry) ==
434 "@#{admin.nickname} made @#{user.nickname} admin"
435 end
436
437 test "/:right POST, can add to a permission group (multiple)" do
438 admin = insert(:user, is_admin: true)
439 user_one = insert(:user)
440 user_two = insert(:user)
441
442 conn =
443 build_conn()
444 |> assign(:user, admin)
445 |> put_req_header("accept", "application/json")
446 |> post("/api/pleroma/admin/users/permission_group/admin", %{
447 nicknames: [user_one.nickname, user_two.nickname]
448 })
449
450 assert json_response(conn, 200) == %{
451 "is_admin" => true
452 }
453
454 log_entry = Repo.one(ModerationLog)
455
456 assert ModerationLog.get_log_entry_message(log_entry) ==
457 "@#{admin.nickname} made @#{user_one.nickname}, @#{user_two.nickname} admin"
458 end
459
460 test "/:right DELETE, can remove from a permission group" do
461 admin = insert(:user, is_admin: true)
462 user = insert(:user, is_admin: true)
463
464 conn =
465 build_conn()
466 |> assign(:user, admin)
467 |> put_req_header("accept", "application/json")
468 |> delete("/api/pleroma/admin/users/#{user.nickname}/permission_group/admin")
469
470 assert json_response(conn, 200) == %{
471 "is_admin" => false
472 }
473
474 log_entry = Repo.one(ModerationLog)
475
476 assert ModerationLog.get_log_entry_message(log_entry) ==
477 "@#{admin.nickname} revoked admin role from @#{user.nickname}"
478 end
479
480 test "/:right DELETE, can remove from a permission group (multiple)" do
481 admin = insert(:user, is_admin: true)
482 user_one = insert(:user, is_admin: true)
483 user_two = insert(:user, is_admin: true)
484
485 conn =
486 build_conn()
487 |> assign(:user, admin)
488 |> put_req_header("accept", "application/json")
489 |> delete("/api/pleroma/admin/users/permission_group/admin", %{
490 nicknames: [user_one.nickname, user_two.nickname]
491 })
492
493 assert json_response(conn, 200) == %{
494 "is_admin" => false
495 }
496
497 log_entry = Repo.one(ModerationLog)
498
499 assert ModerationLog.get_log_entry_message(log_entry) ==
500 "@#{admin.nickname} revoked admin role from @#{user_one.nickname}, @#{
501 user_two.nickname
502 }"
503 end
504 end
505
506 describe "POST /api/pleroma/admin/email_invite, with valid config" do
507 setup do
508 [user: insert(:user, is_admin: true)]
509 end
510
511 clear_config([:instance, :registrations_open]) do
512 Pleroma.Config.put([:instance, :registrations_open], false)
513 end
514
515 clear_config([:instance, :invites_enabled]) do
516 Pleroma.Config.put([:instance, :invites_enabled], true)
517 end
518
519 test "sends invitation and returns 204", %{conn: conn, user: user} do
520 recipient_email = "foo@bar.com"
521 recipient_name = "J. D."
522
523 conn =
524 conn
525 |> assign(:user, user)
526 |> post(
527 "/api/pleroma/admin/users/email_invite?email=#{recipient_email}&name=#{recipient_name}"
528 )
529
530 assert json_response(conn, :no_content)
531
532 token_record = List.last(Pleroma.Repo.all(Pleroma.UserInviteToken))
533 assert token_record
534 refute token_record.used
535
536 notify_email = Pleroma.Config.get([:instance, :notify_email])
537 instance_name = Pleroma.Config.get([:instance, :name])
538
539 email =
540 Pleroma.Emails.UserEmail.user_invitation_email(
541 user,
542 token_record,
543 recipient_email,
544 recipient_name
545 )
546
547 Swoosh.TestAssertions.assert_email_sent(
548 from: {instance_name, notify_email},
549 to: {recipient_name, recipient_email},
550 html_body: email.html_body
551 )
552 end
553
554 test "it returns 403 if requested by a non-admin", %{conn: conn} do
555 non_admin_user = insert(:user)
556
557 conn =
558 conn
559 |> assign(:user, non_admin_user)
560 |> post("/api/pleroma/admin/users/email_invite?email=foo@bar.com&name=JD")
561
562 assert json_response(conn, :forbidden)
563 end
564 end
565
566 describe "POST /api/pleroma/admin/users/email_invite, with invalid config" do
567 setup do
568 [user: insert(:user, is_admin: true)]
569 end
570
571 clear_config([:instance, :registrations_open])
572 clear_config([:instance, :invites_enabled])
573
574 test "it returns 500 if `invites_enabled` is not enabled", %{conn: conn, user: user} do
575 Pleroma.Config.put([:instance, :registrations_open], false)
576 Pleroma.Config.put([:instance, :invites_enabled], false)
577
578 conn =
579 conn
580 |> assign(:user, user)
581 |> post("/api/pleroma/admin/users/email_invite?email=foo@bar.com&name=JD")
582
583 assert json_response(conn, :internal_server_error)
584 end
585
586 test "it returns 500 if `registrations_open` is enabled", %{conn: conn, user: user} do
587 Pleroma.Config.put([:instance, :registrations_open], true)
588 Pleroma.Config.put([:instance, :invites_enabled], true)
589
590 conn =
591 conn
592 |> assign(:user, user)
593 |> post("/api/pleroma/admin/users/email_invite?email=foo@bar.com&name=JD")
594
595 assert json_response(conn, :internal_server_error)
596 end
597 end
598
599 test "/api/pleroma/admin/users/:nickname/password_reset" do
600 admin = insert(:user, is_admin: true)
601 user = insert(:user)
602
603 conn =
604 build_conn()
605 |> assign(:user, admin)
606 |> put_req_header("accept", "application/json")
607 |> get("/api/pleroma/admin/users/#{user.nickname}/password_reset")
608
609 resp = json_response(conn, 200)
610
611 assert Regex.match?(~r/(http:\/\/|https:\/\/)/, resp["link"])
612 end
613
614 describe "GET /api/pleroma/admin/users" do
615 setup do
616 admin = insert(:user, is_admin: true)
617
618 conn =
619 build_conn()
620 |> assign(:user, admin)
621
622 {:ok, conn: conn, admin: admin}
623 end
624
625 test "renders users array for the first page", %{conn: conn, admin: admin} do
626 user = insert(:user, local: false, tags: ["foo", "bar"])
627 conn = get(conn, "/api/pleroma/admin/users?page=1")
628
629 users =
630 [
631 %{
632 "deactivated" => admin.deactivated,
633 "id" => admin.id,
634 "nickname" => admin.nickname,
635 "roles" => %{"admin" => true, "moderator" => false},
636 "local" => true,
637 "tags" => [],
638 "avatar" => User.avatar_url(admin) |> MediaProxy.url(),
639 "display_name" => HTML.strip_tags(admin.name || admin.nickname),
640 "confirmation_pending" => false
641 },
642 %{
643 "deactivated" => user.deactivated,
644 "id" => user.id,
645 "nickname" => user.nickname,
646 "roles" => %{"admin" => false, "moderator" => false},
647 "local" => false,
648 "tags" => ["foo", "bar"],
649 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
650 "display_name" => HTML.strip_tags(user.name || user.nickname),
651 "confirmation_pending" => false
652 }
653 ]
654 |> Enum.sort_by(& &1["nickname"])
655
656 assert json_response(conn, 200) == %{
657 "count" => 2,
658 "page_size" => 50,
659 "users" => users
660 }
661 end
662
663 test "renders empty array for the second page", %{conn: conn} do
664 insert(:user)
665
666 conn = get(conn, "/api/pleroma/admin/users?page=2")
667
668 assert json_response(conn, 200) == %{
669 "count" => 2,
670 "page_size" => 50,
671 "users" => []
672 }
673 end
674
675 test "regular search", %{conn: conn} do
676 user = insert(:user, nickname: "bob")
677
678 conn = get(conn, "/api/pleroma/admin/users?query=bo")
679
680 assert json_response(conn, 200) == %{
681 "count" => 1,
682 "page_size" => 50,
683 "users" => [
684 %{
685 "deactivated" => user.deactivated,
686 "id" => user.id,
687 "nickname" => user.nickname,
688 "roles" => %{"admin" => false, "moderator" => false},
689 "local" => true,
690 "tags" => [],
691 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
692 "display_name" => HTML.strip_tags(user.name || user.nickname),
693 "confirmation_pending" => false
694 }
695 ]
696 }
697 end
698
699 test "search by domain", %{conn: conn} do
700 user = insert(:user, nickname: "nickname@domain.com")
701 insert(:user)
702
703 conn = get(conn, "/api/pleroma/admin/users?query=domain.com")
704
705 assert json_response(conn, 200) == %{
706 "count" => 1,
707 "page_size" => 50,
708 "users" => [
709 %{
710 "deactivated" => user.deactivated,
711 "id" => user.id,
712 "nickname" => user.nickname,
713 "roles" => %{"admin" => false, "moderator" => false},
714 "local" => true,
715 "tags" => [],
716 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
717 "display_name" => HTML.strip_tags(user.name || user.nickname),
718 "confirmation_pending" => false
719 }
720 ]
721 }
722 end
723
724 test "search by full nickname", %{conn: conn} do
725 user = insert(:user, nickname: "nickname@domain.com")
726 insert(:user)
727
728 conn = get(conn, "/api/pleroma/admin/users?query=nickname@domain.com")
729
730 assert json_response(conn, 200) == %{
731 "count" => 1,
732 "page_size" => 50,
733 "users" => [
734 %{
735 "deactivated" => user.deactivated,
736 "id" => user.id,
737 "nickname" => user.nickname,
738 "roles" => %{"admin" => false, "moderator" => false},
739 "local" => true,
740 "tags" => [],
741 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
742 "display_name" => HTML.strip_tags(user.name || user.nickname),
743 "confirmation_pending" => false
744 }
745 ]
746 }
747 end
748
749 test "search by display name", %{conn: conn} do
750 user = insert(:user, name: "Display name")
751 insert(:user)
752
753 conn = get(conn, "/api/pleroma/admin/users?name=display")
754
755 assert json_response(conn, 200) == %{
756 "count" => 1,
757 "page_size" => 50,
758 "users" => [
759 %{
760 "deactivated" => user.deactivated,
761 "id" => user.id,
762 "nickname" => user.nickname,
763 "roles" => %{"admin" => false, "moderator" => false},
764 "local" => true,
765 "tags" => [],
766 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
767 "display_name" => HTML.strip_tags(user.name || user.nickname),
768 "confirmation_pending" => false
769 }
770 ]
771 }
772 end
773
774 test "search by email", %{conn: conn} do
775 user = insert(:user, email: "email@example.com")
776 insert(:user)
777
778 conn = get(conn, "/api/pleroma/admin/users?email=email@example.com")
779
780 assert json_response(conn, 200) == %{
781 "count" => 1,
782 "page_size" => 50,
783 "users" => [
784 %{
785 "deactivated" => user.deactivated,
786 "id" => user.id,
787 "nickname" => user.nickname,
788 "roles" => %{"admin" => false, "moderator" => false},
789 "local" => true,
790 "tags" => [],
791 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
792 "display_name" => HTML.strip_tags(user.name || user.nickname),
793 "confirmation_pending" => false
794 }
795 ]
796 }
797 end
798
799 test "regular search with page size", %{conn: conn} do
800 user = insert(:user, nickname: "aalice")
801 user2 = insert(:user, nickname: "alice")
802
803 conn1 = get(conn, "/api/pleroma/admin/users?query=a&page_size=1&page=1")
804
805 assert json_response(conn1, 200) == %{
806 "count" => 2,
807 "page_size" => 1,
808 "users" => [
809 %{
810 "deactivated" => user.deactivated,
811 "id" => user.id,
812 "nickname" => user.nickname,
813 "roles" => %{"admin" => false, "moderator" => false},
814 "local" => true,
815 "tags" => [],
816 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
817 "display_name" => HTML.strip_tags(user.name || user.nickname),
818 "confirmation_pending" => false
819 }
820 ]
821 }
822
823 conn2 = get(conn, "/api/pleroma/admin/users?query=a&page_size=1&page=2")
824
825 assert json_response(conn2, 200) == %{
826 "count" => 2,
827 "page_size" => 1,
828 "users" => [
829 %{
830 "deactivated" => user2.deactivated,
831 "id" => user2.id,
832 "nickname" => user2.nickname,
833 "roles" => %{"admin" => false, "moderator" => false},
834 "local" => true,
835 "tags" => [],
836 "avatar" => User.avatar_url(user2) |> MediaProxy.url(),
837 "display_name" => HTML.strip_tags(user2.name || user2.nickname),
838 "confirmation_pending" => false
839 }
840 ]
841 }
842 end
843
844 test "only local users" do
845 admin = insert(:user, is_admin: true, nickname: "john")
846 user = insert(:user, nickname: "bob")
847
848 insert(:user, nickname: "bobb", local: false)
849
850 conn =
851 build_conn()
852 |> assign(:user, admin)
853 |> get("/api/pleroma/admin/users?query=bo&filters=local")
854
855 assert json_response(conn, 200) == %{
856 "count" => 1,
857 "page_size" => 50,
858 "users" => [
859 %{
860 "deactivated" => user.deactivated,
861 "id" => user.id,
862 "nickname" => user.nickname,
863 "roles" => %{"admin" => false, "moderator" => false},
864 "local" => true,
865 "tags" => [],
866 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
867 "display_name" => HTML.strip_tags(user.name || user.nickname),
868 "confirmation_pending" => false
869 }
870 ]
871 }
872 end
873
874 test "only local users with no query", %{admin: old_admin} do
875 admin = insert(:user, is_admin: true, nickname: "john")
876 user = insert(:user, nickname: "bob")
877
878 insert(:user, nickname: "bobb", local: false)
879
880 conn =
881 build_conn()
882 |> assign(:user, admin)
883 |> get("/api/pleroma/admin/users?filters=local")
884
885 users =
886 [
887 %{
888 "deactivated" => user.deactivated,
889 "id" => user.id,
890 "nickname" => user.nickname,
891 "roles" => %{"admin" => false, "moderator" => false},
892 "local" => true,
893 "tags" => [],
894 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
895 "display_name" => HTML.strip_tags(user.name || user.nickname),
896 "confirmation_pending" => false
897 },
898 %{
899 "deactivated" => admin.deactivated,
900 "id" => admin.id,
901 "nickname" => admin.nickname,
902 "roles" => %{"admin" => true, "moderator" => false},
903 "local" => true,
904 "tags" => [],
905 "avatar" => User.avatar_url(admin) |> MediaProxy.url(),
906 "display_name" => HTML.strip_tags(admin.name || admin.nickname),
907 "confirmation_pending" => false
908 },
909 %{
910 "deactivated" => false,
911 "id" => old_admin.id,
912 "local" => true,
913 "nickname" => old_admin.nickname,
914 "roles" => %{"admin" => true, "moderator" => false},
915 "tags" => [],
916 "avatar" => User.avatar_url(old_admin) |> MediaProxy.url(),
917 "display_name" => HTML.strip_tags(old_admin.name || old_admin.nickname),
918 "confirmation_pending" => false
919 }
920 ]
921 |> Enum.sort_by(& &1["nickname"])
922
923 assert json_response(conn, 200) == %{
924 "count" => 3,
925 "page_size" => 50,
926 "users" => users
927 }
928 end
929
930 test "load only admins", %{conn: conn, admin: admin} do
931 second_admin = insert(:user, is_admin: true)
932 insert(:user)
933 insert(:user)
934
935 conn = get(conn, "/api/pleroma/admin/users?filters=is_admin")
936
937 users =
938 [
939 %{
940 "deactivated" => false,
941 "id" => admin.id,
942 "nickname" => admin.nickname,
943 "roles" => %{"admin" => true, "moderator" => false},
944 "local" => admin.local,
945 "tags" => [],
946 "avatar" => User.avatar_url(admin) |> MediaProxy.url(),
947 "display_name" => HTML.strip_tags(admin.name || admin.nickname),
948 "confirmation_pending" => false
949 },
950 %{
951 "deactivated" => false,
952 "id" => second_admin.id,
953 "nickname" => second_admin.nickname,
954 "roles" => %{"admin" => true, "moderator" => false},
955 "local" => second_admin.local,
956 "tags" => [],
957 "avatar" => User.avatar_url(second_admin) |> MediaProxy.url(),
958 "display_name" => HTML.strip_tags(second_admin.name || second_admin.nickname),
959 "confirmation_pending" => false
960 }
961 ]
962 |> Enum.sort_by(& &1["nickname"])
963
964 assert json_response(conn, 200) == %{
965 "count" => 2,
966 "page_size" => 50,
967 "users" => users
968 }
969 end
970
971 test "load only moderators", %{conn: conn} do
972 moderator = insert(:user, is_moderator: true)
973 insert(:user)
974 insert(:user)
975
976 conn = get(conn, "/api/pleroma/admin/users?filters=is_moderator")
977
978 assert json_response(conn, 200) == %{
979 "count" => 1,
980 "page_size" => 50,
981 "users" => [
982 %{
983 "deactivated" => false,
984 "id" => moderator.id,
985 "nickname" => moderator.nickname,
986 "roles" => %{"admin" => false, "moderator" => true},
987 "local" => moderator.local,
988 "tags" => [],
989 "avatar" => User.avatar_url(moderator) |> MediaProxy.url(),
990 "display_name" => HTML.strip_tags(moderator.name || moderator.nickname),
991 "confirmation_pending" => false
992 }
993 ]
994 }
995 end
996
997 test "load users with tags list", %{conn: conn} do
998 user1 = insert(:user, tags: ["first"])
999 user2 = insert(:user, tags: ["second"])
1000 insert(:user)
1001 insert(:user)
1002
1003 conn = get(conn, "/api/pleroma/admin/users?tags[]=first&tags[]=second")
1004
1005 users =
1006 [
1007 %{
1008 "deactivated" => false,
1009 "id" => user1.id,
1010 "nickname" => user1.nickname,
1011 "roles" => %{"admin" => false, "moderator" => false},
1012 "local" => user1.local,
1013 "tags" => ["first"],
1014 "avatar" => User.avatar_url(user1) |> MediaProxy.url(),
1015 "display_name" => HTML.strip_tags(user1.name || user1.nickname),
1016 "confirmation_pending" => false
1017 },
1018 %{
1019 "deactivated" => false,
1020 "id" => user2.id,
1021 "nickname" => user2.nickname,
1022 "roles" => %{"admin" => false, "moderator" => false},
1023 "local" => user2.local,
1024 "tags" => ["second"],
1025 "avatar" => User.avatar_url(user2) |> MediaProxy.url(),
1026 "display_name" => HTML.strip_tags(user2.name || user2.nickname),
1027 "confirmation_pending" => false
1028 }
1029 ]
1030 |> Enum.sort_by(& &1["nickname"])
1031
1032 assert json_response(conn, 200) == %{
1033 "count" => 2,
1034 "page_size" => 50,
1035 "users" => users
1036 }
1037 end
1038
1039 test "it works with multiple filters" do
1040 admin = insert(:user, nickname: "john", is_admin: true)
1041 user = insert(:user, nickname: "bob", local: false, deactivated: true)
1042
1043 insert(:user, nickname: "ken", local: true, deactivated: true)
1044 insert(:user, nickname: "bobb", local: false, deactivated: false)
1045
1046 conn =
1047 build_conn()
1048 |> assign(:user, admin)
1049 |> get("/api/pleroma/admin/users?filters=deactivated,external")
1050
1051 assert json_response(conn, 200) == %{
1052 "count" => 1,
1053 "page_size" => 50,
1054 "users" => [
1055 %{
1056 "deactivated" => user.deactivated,
1057 "id" => user.id,
1058 "nickname" => user.nickname,
1059 "roles" => %{"admin" => false, "moderator" => false},
1060 "local" => user.local,
1061 "tags" => [],
1062 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
1063 "display_name" => HTML.strip_tags(user.name || user.nickname),
1064 "confirmation_pending" => false
1065 }
1066 ]
1067 }
1068 end
1069
1070 test "it omits relay user", %{admin: admin} do
1071 assert %User{} = Relay.get_actor()
1072
1073 conn =
1074 build_conn()
1075 |> assign(:user, admin)
1076 |> get("/api/pleroma/admin/users")
1077
1078 assert json_response(conn, 200) == %{
1079 "count" => 1,
1080 "page_size" => 50,
1081 "users" => [
1082 %{
1083 "deactivated" => admin.deactivated,
1084 "id" => admin.id,
1085 "nickname" => admin.nickname,
1086 "roles" => %{"admin" => true, "moderator" => false},
1087 "local" => true,
1088 "tags" => [],
1089 "avatar" => User.avatar_url(admin) |> MediaProxy.url(),
1090 "display_name" => HTML.strip_tags(admin.name || admin.nickname),
1091 "confirmation_pending" => false
1092 }
1093 ]
1094 }
1095 end
1096 end
1097
1098 test "PATCH /api/pleroma/admin/users/activate" do
1099 admin = insert(:user, is_admin: true)
1100 user_one = insert(:user, deactivated: true)
1101 user_two = insert(:user, deactivated: true)
1102
1103 conn =
1104 build_conn()
1105 |> assign(:user, admin)
1106 |> patch(
1107 "/api/pleroma/admin/users/activate",
1108 %{nicknames: [user_one.nickname, user_two.nickname]}
1109 )
1110
1111 response = json_response(conn, 200)
1112 assert Enum.map(response["users"], & &1["deactivated"]) == [false, false]
1113
1114 log_entry = Repo.one(ModerationLog)
1115
1116 assert ModerationLog.get_log_entry_message(log_entry) ==
1117 "@#{admin.nickname} activated users: @#{user_one.nickname}, @#{user_two.nickname}"
1118 end
1119
1120 test "PATCH /api/pleroma/admin/users/deactivate" do
1121 admin = insert(:user, is_admin: true)
1122 user_one = insert(:user, deactivated: false)
1123 user_two = insert(:user, deactivated: false)
1124
1125 conn =
1126 build_conn()
1127 |> assign(:user, admin)
1128 |> patch(
1129 "/api/pleroma/admin/users/deactivate",
1130 %{nicknames: [user_one.nickname, user_two.nickname]}
1131 )
1132
1133 response = json_response(conn, 200)
1134 assert Enum.map(response["users"], & &1["deactivated"]) == [true, true]
1135
1136 log_entry = Repo.one(ModerationLog)
1137
1138 assert ModerationLog.get_log_entry_message(log_entry) ==
1139 "@#{admin.nickname} deactivated users: @#{user_one.nickname}, @#{user_two.nickname}"
1140 end
1141
1142 test "PATCH /api/pleroma/admin/users/:nickname/toggle_activation" do
1143 admin = insert(:user, is_admin: true)
1144 user = insert(:user)
1145
1146 conn =
1147 build_conn()
1148 |> assign(:user, admin)
1149 |> patch("/api/pleroma/admin/users/#{user.nickname}/toggle_activation")
1150
1151 assert json_response(conn, 200) ==
1152 %{
1153 "deactivated" => !user.deactivated,
1154 "id" => user.id,
1155 "nickname" => user.nickname,
1156 "roles" => %{"admin" => false, "moderator" => false},
1157 "local" => true,
1158 "tags" => [],
1159 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
1160 "display_name" => HTML.strip_tags(user.name || user.nickname),
1161 "confirmation_pending" => false
1162 }
1163
1164 log_entry = Repo.one(ModerationLog)
1165
1166 assert ModerationLog.get_log_entry_message(log_entry) ==
1167 "@#{admin.nickname} deactivated users: @#{user.nickname}"
1168 end
1169
1170 describe "POST /api/pleroma/admin/users/invite_token" do
1171 setup do
1172 admin = insert(:user, is_admin: true)
1173
1174 conn =
1175 build_conn()
1176 |> assign(:user, admin)
1177
1178 {:ok, conn: conn}
1179 end
1180
1181 test "without options", %{conn: conn} do
1182 conn = post(conn, "/api/pleroma/admin/users/invite_token")
1183
1184 invite_json = json_response(conn, 200)
1185 invite = UserInviteToken.find_by_token!(invite_json["token"])
1186 refute invite.used
1187 refute invite.expires_at
1188 refute invite.max_use
1189 assert invite.invite_type == "one_time"
1190 end
1191
1192 test "with expires_at", %{conn: conn} do
1193 conn =
1194 post(conn, "/api/pleroma/admin/users/invite_token", %{
1195 "expires_at" => Date.to_string(Date.utc_today())
1196 })
1197
1198 invite_json = json_response(conn, 200)
1199 invite = UserInviteToken.find_by_token!(invite_json["token"])
1200
1201 refute invite.used
1202 assert invite.expires_at == Date.utc_today()
1203 refute invite.max_use
1204 assert invite.invite_type == "date_limited"
1205 end
1206
1207 test "with max_use", %{conn: conn} do
1208 conn = post(conn, "/api/pleroma/admin/users/invite_token", %{"max_use" => 150})
1209
1210 invite_json = json_response(conn, 200)
1211 invite = UserInviteToken.find_by_token!(invite_json["token"])
1212 refute invite.used
1213 refute invite.expires_at
1214 assert invite.max_use == 150
1215 assert invite.invite_type == "reusable"
1216 end
1217
1218 test "with max use and expires_at", %{conn: conn} do
1219 conn =
1220 post(conn, "/api/pleroma/admin/users/invite_token", %{
1221 "max_use" => 150,
1222 "expires_at" => Date.to_string(Date.utc_today())
1223 })
1224
1225 invite_json = json_response(conn, 200)
1226 invite = UserInviteToken.find_by_token!(invite_json["token"])
1227 refute invite.used
1228 assert invite.expires_at == Date.utc_today()
1229 assert invite.max_use == 150
1230 assert invite.invite_type == "reusable_date_limited"
1231 end
1232 end
1233
1234 describe "GET /api/pleroma/admin/users/invites" do
1235 setup do
1236 admin = insert(:user, is_admin: true)
1237
1238 conn =
1239 build_conn()
1240 |> assign(:user, admin)
1241
1242 {:ok, conn: conn}
1243 end
1244
1245 test "no invites", %{conn: conn} do
1246 conn = get(conn, "/api/pleroma/admin/users/invites")
1247
1248 assert json_response(conn, 200) == %{"invites" => []}
1249 end
1250
1251 test "with invite", %{conn: conn} do
1252 {:ok, invite} = UserInviteToken.create_invite()
1253
1254 conn = get(conn, "/api/pleroma/admin/users/invites")
1255
1256 assert json_response(conn, 200) == %{
1257 "invites" => [
1258 %{
1259 "expires_at" => nil,
1260 "id" => invite.id,
1261 "invite_type" => "one_time",
1262 "max_use" => nil,
1263 "token" => invite.token,
1264 "used" => false,
1265 "uses" => 0
1266 }
1267 ]
1268 }
1269 end
1270 end
1271
1272 describe "POST /api/pleroma/admin/users/revoke_invite" do
1273 test "with token" do
1274 admin = insert(:user, is_admin: true)
1275 {:ok, invite} = UserInviteToken.create_invite()
1276
1277 conn =
1278 build_conn()
1279 |> assign(:user, admin)
1280 |> post("/api/pleroma/admin/users/revoke_invite", %{"token" => invite.token})
1281
1282 assert json_response(conn, 200) == %{
1283 "expires_at" => nil,
1284 "id" => invite.id,
1285 "invite_type" => "one_time",
1286 "max_use" => nil,
1287 "token" => invite.token,
1288 "used" => true,
1289 "uses" => 0
1290 }
1291 end
1292
1293 test "with invalid token" do
1294 admin = insert(:user, is_admin: true)
1295
1296 conn =
1297 build_conn()
1298 |> assign(:user, admin)
1299 |> post("/api/pleroma/admin/users/revoke_invite", %{"token" => "foo"})
1300
1301 assert json_response(conn, :not_found) == "Not found"
1302 end
1303 end
1304
1305 describe "GET /api/pleroma/admin/reports/:id" do
1306 setup %{conn: conn} do
1307 admin = insert(:user, is_admin: true)
1308
1309 %{conn: assign(conn, :user, admin)}
1310 end
1311
1312 test "returns report by its id", %{conn: conn} do
1313 [reporter, target_user] = insert_pair(:user)
1314 activity = insert(:note_activity, user: target_user)
1315
1316 {:ok, %{id: report_id}} =
1317 CommonAPI.report(reporter, %{
1318 "account_id" => target_user.id,
1319 "comment" => "I feel offended",
1320 "status_ids" => [activity.id]
1321 })
1322
1323 response =
1324 conn
1325 |> get("/api/pleroma/admin/reports/#{report_id}")
1326 |> json_response(:ok)
1327
1328 assert response["id"] == report_id
1329 end
1330
1331 test "returns 404 when report id is invalid", %{conn: conn} do
1332 conn = get(conn, "/api/pleroma/admin/reports/test")
1333
1334 assert json_response(conn, :not_found) == "Not found"
1335 end
1336 end
1337
1338 describe "PATCH /api/pleroma/admin/reports" do
1339 setup %{conn: conn} do
1340 admin = insert(:user, is_admin: true)
1341 [reporter, target_user] = insert_pair(:user)
1342 activity = insert(:note_activity, user: target_user)
1343
1344 {:ok, %{id: report_id}} =
1345 CommonAPI.report(reporter, %{
1346 "account_id" => target_user.id,
1347 "comment" => "I feel offended",
1348 "status_ids" => [activity.id]
1349 })
1350
1351 {:ok, %{id: second_report_id}} =
1352 CommonAPI.report(reporter, %{
1353 "account_id" => target_user.id,
1354 "comment" => "I feel very offended",
1355 "status_ids" => [activity.id]
1356 })
1357
1358 %{
1359 conn: assign(conn, :user, admin),
1360 id: report_id,
1361 admin: admin,
1362 second_report_id: second_report_id
1363 }
1364 end
1365
1366 test "mark report as resolved", %{conn: conn, id: id, admin: admin} do
1367 conn
1368 |> patch("/api/pleroma/admin/reports", %{
1369 "reports" => [
1370 %{"state" => "resolved", "id" => id}
1371 ]
1372 })
1373 |> json_response(:no_content)
1374
1375 activity = Activity.get_by_id(id)
1376 assert activity.data["state"] == "resolved"
1377
1378 log_entry = Repo.one(ModerationLog)
1379
1380 assert ModerationLog.get_log_entry_message(log_entry) ==
1381 "@#{admin.nickname} updated report ##{id} with 'resolved' state"
1382 end
1383
1384 test "closes report", %{conn: conn, id: id, admin: admin} do
1385 conn
1386 |> patch("/api/pleroma/admin/reports", %{
1387 "reports" => [
1388 %{"state" => "closed", "id" => id}
1389 ]
1390 })
1391 |> json_response(:no_content)
1392
1393 activity = Activity.get_by_id(id)
1394 assert activity.data["state"] == "closed"
1395
1396 log_entry = Repo.one(ModerationLog)
1397
1398 assert ModerationLog.get_log_entry_message(log_entry) ==
1399 "@#{admin.nickname} updated report ##{id} with 'closed' state"
1400 end
1401
1402 test "returns 400 when state is unknown", %{conn: conn, id: id} do
1403 conn =
1404 conn
1405 |> patch("/api/pleroma/admin/reports", %{
1406 "reports" => [
1407 %{"state" => "test", "id" => id}
1408 ]
1409 })
1410
1411 assert hd(json_response(conn, :bad_request))["error"] == "Unsupported state"
1412 end
1413
1414 test "returns 404 when report is not exist", %{conn: conn} do
1415 conn =
1416 conn
1417 |> patch("/api/pleroma/admin/reports", %{
1418 "reports" => [
1419 %{"state" => "closed", "id" => "test"}
1420 ]
1421 })
1422
1423 assert hd(json_response(conn, :bad_request))["error"] == "not_found"
1424 end
1425
1426 test "updates state of multiple reports", %{
1427 conn: conn,
1428 id: id,
1429 admin: admin,
1430 second_report_id: second_report_id
1431 } do
1432 conn
1433 |> patch("/api/pleroma/admin/reports", %{
1434 "reports" => [
1435 %{"state" => "resolved", "id" => id},
1436 %{"state" => "closed", "id" => second_report_id}
1437 ]
1438 })
1439 |> json_response(:no_content)
1440
1441 activity = Activity.get_by_id(id)
1442 second_activity = Activity.get_by_id(second_report_id)
1443 assert activity.data["state"] == "resolved"
1444 assert second_activity.data["state"] == "closed"
1445
1446 [first_log_entry, second_log_entry] = Repo.all(ModerationLog)
1447
1448 assert ModerationLog.get_log_entry_message(first_log_entry) ==
1449 "@#{admin.nickname} updated report ##{id} with 'resolved' state"
1450
1451 assert ModerationLog.get_log_entry_message(second_log_entry) ==
1452 "@#{admin.nickname} updated report ##{second_report_id} with 'closed' state"
1453 end
1454 end
1455
1456 describe "GET /api/pleroma/admin/reports" do
1457 setup %{conn: conn} do
1458 admin = insert(:user, is_admin: true)
1459
1460 %{conn: assign(conn, :user, admin)}
1461 end
1462
1463 test "returns empty response when no reports created", %{conn: conn} do
1464 response =
1465 conn
1466 |> get("/api/pleroma/admin/reports")
1467 |> json_response(:ok)
1468
1469 assert Enum.empty?(response["reports"])
1470 assert response["total"] == 0
1471 end
1472
1473 test "returns reports", %{conn: conn} do
1474 [reporter, target_user] = insert_pair(:user)
1475 activity = insert(:note_activity, user: target_user)
1476
1477 {:ok, %{id: report_id}} =
1478 CommonAPI.report(reporter, %{
1479 "account_id" => target_user.id,
1480 "comment" => "I feel offended",
1481 "status_ids" => [activity.id]
1482 })
1483
1484 response =
1485 conn
1486 |> get("/api/pleroma/admin/reports")
1487 |> json_response(:ok)
1488
1489 [report] = response["reports"]
1490
1491 assert length(response["reports"]) == 1
1492 assert report["id"] == report_id
1493
1494 assert response["total"] == 1
1495 end
1496
1497 test "returns reports with specified state", %{conn: conn} do
1498 [reporter, target_user] = insert_pair(:user)
1499 activity = insert(:note_activity, user: target_user)
1500
1501 {:ok, %{id: first_report_id}} =
1502 CommonAPI.report(reporter, %{
1503 "account_id" => target_user.id,
1504 "comment" => "I feel offended",
1505 "status_ids" => [activity.id]
1506 })
1507
1508 {:ok, %{id: second_report_id}} =
1509 CommonAPI.report(reporter, %{
1510 "account_id" => target_user.id,
1511 "comment" => "I don't like this user"
1512 })
1513
1514 CommonAPI.update_report_state(second_report_id, "closed")
1515
1516 response =
1517 conn
1518 |> get("/api/pleroma/admin/reports", %{
1519 "state" => "open"
1520 })
1521 |> json_response(:ok)
1522
1523 [open_report] = response["reports"]
1524
1525 assert length(response["reports"]) == 1
1526 assert open_report["id"] == first_report_id
1527
1528 assert response["total"] == 1
1529
1530 response =
1531 conn
1532 |> get("/api/pleroma/admin/reports", %{
1533 "state" => "closed"
1534 })
1535 |> json_response(:ok)
1536
1537 [closed_report] = response["reports"]
1538
1539 assert length(response["reports"]) == 1
1540 assert closed_report["id"] == second_report_id
1541
1542 assert response["total"] == 1
1543
1544 response =
1545 conn
1546 |> get("/api/pleroma/admin/reports", %{
1547 "state" => "resolved"
1548 })
1549 |> json_response(:ok)
1550
1551 assert Enum.empty?(response["reports"])
1552 assert response["total"] == 0
1553 end
1554
1555 test "returns 403 when requested by a non-admin" do
1556 user = insert(:user)
1557
1558 conn =
1559 build_conn()
1560 |> assign(:user, user)
1561 |> get("/api/pleroma/admin/reports")
1562
1563 assert json_response(conn, :forbidden) == %{"error" => "User is not admin."}
1564 end
1565
1566 test "returns 403 when requested by anonymous" do
1567 conn =
1568 build_conn()
1569 |> get("/api/pleroma/admin/reports")
1570
1571 assert json_response(conn, :forbidden) == %{"error" => "Invalid credentials."}
1572 end
1573 end
1574
1575 describe "GET /api/pleroma/admin/grouped_reports" do
1576 setup %{conn: conn} do
1577 admin = insert(:user, is_admin: true)
1578 [reporter, target_user] = insert_pair(:user)
1579
1580 date1 = (DateTime.to_unix(DateTime.utc_now()) + 1000) |> DateTime.from_unix!()
1581 date2 = (DateTime.to_unix(DateTime.utc_now()) + 2000) |> DateTime.from_unix!()
1582 date3 = (DateTime.to_unix(DateTime.utc_now()) + 3000) |> DateTime.from_unix!()
1583
1584 first_status =
1585 insert(:note_activity, user: target_user, data_attrs: %{"published" => date1})
1586
1587 second_status =
1588 insert(:note_activity, user: target_user, data_attrs: %{"published" => date2})
1589
1590 third_status =
1591 insert(:note_activity, user: target_user, data_attrs: %{"published" => date3})
1592
1593 {:ok, first_report} =
1594 CommonAPI.report(reporter, %{
1595 "account_id" => target_user.id,
1596 "status_ids" => [first_status.id, second_status.id, third_status.id]
1597 })
1598
1599 {:ok, second_report} =
1600 CommonAPI.report(reporter, %{
1601 "account_id" => target_user.id,
1602 "status_ids" => [first_status.id, second_status.id]
1603 })
1604
1605 {:ok, third_report} =
1606 CommonAPI.report(reporter, %{
1607 "account_id" => target_user.id,
1608 "status_ids" => [first_status.id]
1609 })
1610
1611 %{
1612 conn: assign(conn, :user, admin),
1613 first_status: Activity.get_by_ap_id_with_object(first_status.data["id"]),
1614 second_status: Activity.get_by_ap_id_with_object(second_status.data["id"]),
1615 third_status: Activity.get_by_ap_id_with_object(third_status.data["id"]),
1616 first_status_reports: [first_report, second_report, third_report],
1617 second_status_reports: [first_report, second_report],
1618 third_status_reports: [first_report],
1619 target_user: target_user,
1620 reporter: reporter
1621 }
1622 end
1623
1624 test "returns reports grouped by status", %{
1625 conn: conn,
1626 first_status: first_status,
1627 second_status: second_status,
1628 third_status: third_status,
1629 first_status_reports: first_status_reports,
1630 second_status_reports: second_status_reports,
1631 third_status_reports: third_status_reports,
1632 target_user: target_user,
1633 reporter: reporter
1634 } do
1635 response =
1636 conn
1637 |> get("/api/pleroma/admin/grouped_reports")
1638 |> json_response(:ok)
1639
1640 assert length(response["reports"]) == 3
1641
1642 first_group =
1643 Enum.find(response["reports"], &(&1["status"]["id"] == first_status.data["id"]))
1644
1645 second_group =
1646 Enum.find(response["reports"], &(&1["status"]["id"] == second_status.data["id"]))
1647
1648 third_group =
1649 Enum.find(response["reports"], &(&1["status"]["id"] == third_status.data["id"]))
1650
1651 assert length(first_group["reports"]) == 3
1652 assert length(second_group["reports"]) == 2
1653 assert length(third_group["reports"]) == 1
1654
1655 assert first_group["date"] ==
1656 Enum.max_by(first_status_reports, fn act ->
1657 NaiveDateTime.from_iso8601!(act.data["published"])
1658 end).data["published"]
1659
1660 assert first_group["status"] == %{
1661 "id" => first_status.data["id"],
1662 "content" => first_status.object.data["content"],
1663 "published" => first_status.object.data["published"]
1664 }
1665
1666 assert first_group["account"]["id"] == target_user.id
1667
1668 assert length(first_group["actors"]) == 1
1669 assert hd(first_group["actors"])["id"] == reporter.id
1670
1671 assert Enum.map(first_group["reports"], & &1["id"]) --
1672 Enum.map(first_status_reports, & &1.id) == []
1673
1674 assert second_group["date"] ==
1675 Enum.max_by(second_status_reports, fn act ->
1676 NaiveDateTime.from_iso8601!(act.data["published"])
1677 end).data["published"]
1678
1679 assert second_group["status"] == %{
1680 "id" => second_status.data["id"],
1681 "content" => second_status.object.data["content"],
1682 "published" => second_status.object.data["published"]
1683 }
1684
1685 assert second_group["account"]["id"] == target_user.id
1686
1687 assert length(second_group["actors"]) == 1
1688 assert hd(second_group["actors"])["id"] == reporter.id
1689
1690 assert Enum.map(second_group["reports"], & &1["id"]) --
1691 Enum.map(second_status_reports, & &1.id) == []
1692
1693 assert third_group["date"] ==
1694 Enum.max_by(third_status_reports, fn act ->
1695 NaiveDateTime.from_iso8601!(act.data["published"])
1696 end).data["published"]
1697
1698 assert third_group["status"] == %{
1699 "id" => third_status.data["id"],
1700 "content" => third_status.object.data["content"],
1701 "published" => third_status.object.data["published"]
1702 }
1703
1704 assert third_group["account"]["id"] == target_user.id
1705
1706 assert length(third_group["actors"]) == 1
1707 assert hd(third_group["actors"])["id"] == reporter.id
1708
1709 assert Enum.map(third_group["reports"], & &1["id"]) --
1710 Enum.map(third_status_reports, & &1.id) == []
1711 end
1712 end
1713
1714 describe "PUT /api/pleroma/admin/statuses/:id" do
1715 setup %{conn: conn} do
1716 admin = insert(:user, is_admin: true)
1717 activity = insert(:note_activity)
1718
1719 %{conn: assign(conn, :user, admin), id: activity.id, admin: admin}
1720 end
1721
1722 test "toggle sensitive flag", %{conn: conn, id: id, admin: admin} do
1723 response =
1724 conn
1725 |> put("/api/pleroma/admin/statuses/#{id}", %{"sensitive" => "true"})
1726 |> json_response(:ok)
1727
1728 assert response["sensitive"]
1729
1730 log_entry = Repo.one(ModerationLog)
1731
1732 assert ModerationLog.get_log_entry_message(log_entry) ==
1733 "@#{admin.nickname} updated status ##{id}, set sensitive: 'true'"
1734
1735 response =
1736 conn
1737 |> put("/api/pleroma/admin/statuses/#{id}", %{"sensitive" => "false"})
1738 |> json_response(:ok)
1739
1740 refute response["sensitive"]
1741 end
1742
1743 test "change visibility flag", %{conn: conn, id: id, admin: admin} do
1744 response =
1745 conn
1746 |> put("/api/pleroma/admin/statuses/#{id}", %{"visibility" => "public"})
1747 |> json_response(:ok)
1748
1749 assert response["visibility"] == "public"
1750
1751 log_entry = Repo.one(ModerationLog)
1752
1753 assert ModerationLog.get_log_entry_message(log_entry) ==
1754 "@#{admin.nickname} updated status ##{id}, set visibility: 'public'"
1755
1756 response =
1757 conn
1758 |> put("/api/pleroma/admin/statuses/#{id}", %{"visibility" => "private"})
1759 |> json_response(:ok)
1760
1761 assert response["visibility"] == "private"
1762
1763 response =
1764 conn
1765 |> put("/api/pleroma/admin/statuses/#{id}", %{"visibility" => "unlisted"})
1766 |> json_response(:ok)
1767
1768 assert response["visibility"] == "unlisted"
1769 end
1770
1771 test "returns 400 when visibility is unknown", %{conn: conn, id: id} do
1772 conn =
1773 conn
1774 |> put("/api/pleroma/admin/statuses/#{id}", %{"visibility" => "test"})
1775
1776 assert json_response(conn, :bad_request) == "Unsupported visibility"
1777 end
1778 end
1779
1780 describe "DELETE /api/pleroma/admin/statuses/:id" do
1781 setup %{conn: conn} do
1782 admin = insert(:user, is_admin: true)
1783 activity = insert(:note_activity)
1784
1785 %{conn: assign(conn, :user, admin), id: activity.id, admin: admin}
1786 end
1787
1788 test "deletes status", %{conn: conn, id: id, admin: admin} do
1789 conn
1790 |> delete("/api/pleroma/admin/statuses/#{id}")
1791 |> json_response(:ok)
1792
1793 refute Activity.get_by_id(id)
1794
1795 log_entry = Repo.one(ModerationLog)
1796
1797 assert ModerationLog.get_log_entry_message(log_entry) ==
1798 "@#{admin.nickname} deleted status ##{id}"
1799 end
1800
1801 test "returns error when status is not exist", %{conn: conn} do
1802 conn =
1803 conn
1804 |> delete("/api/pleroma/admin/statuses/test")
1805
1806 assert json_response(conn, :bad_request) == "Could not delete"
1807 end
1808 end
1809
1810 describe "GET /api/pleroma/admin/config" do
1811 setup %{conn: conn} do
1812 admin = insert(:user, is_admin: true)
1813
1814 %{conn: assign(conn, :user, admin)}
1815 end
1816
1817 test "without any settings in db", %{conn: conn} do
1818 conn = get(conn, "/api/pleroma/admin/config")
1819
1820 assert json_response(conn, 200) == %{"configs" => []}
1821 end
1822
1823 test "with settings in db", %{conn: conn} do
1824 config1 = insert(:config)
1825 config2 = insert(:config)
1826
1827 conn = get(conn, "/api/pleroma/admin/config")
1828
1829 %{
1830 "configs" => [
1831 %{
1832 "key" => key1,
1833 "value" => _
1834 },
1835 %{
1836 "key" => key2,
1837 "value" => _
1838 }
1839 ]
1840 } = json_response(conn, 200)
1841
1842 assert key1 == config1.key
1843 assert key2 == config2.key
1844 end
1845 end
1846
1847 describe "POST /api/pleroma/admin/config" do
1848 setup %{conn: conn} do
1849 admin = insert(:user, is_admin: true)
1850
1851 temp_file = "config/test.exported_from_db.secret.exs"
1852
1853 on_exit(fn ->
1854 Application.delete_env(:pleroma, :key1)
1855 Application.delete_env(:pleroma, :key2)
1856 Application.delete_env(:pleroma, :key3)
1857 Application.delete_env(:pleroma, :key4)
1858 Application.delete_env(:pleroma, :keyaa1)
1859 Application.delete_env(:pleroma, :keyaa2)
1860 Application.delete_env(:pleroma, Pleroma.Web.Endpoint.NotReal)
1861 Application.delete_env(:pleroma, Pleroma.Captcha.NotReal)
1862 :ok = File.rm(temp_file)
1863 end)
1864
1865 %{conn: assign(conn, :user, admin)}
1866 end
1867
1868 clear_config([:instance, :dynamic_configuration]) do
1869 Pleroma.Config.put([:instance, :dynamic_configuration], true)
1870 end
1871
1872 @tag capture_log: true
1873 test "create new config setting in db", %{conn: conn} do
1874 conn =
1875 post(conn, "/api/pleroma/admin/config", %{
1876 configs: [
1877 %{group: "pleroma", key: "key1", value: "value1"},
1878 %{
1879 group: "ueberauth",
1880 key: "Ueberauth.Strategy.Twitter.OAuth",
1881 value: [%{"tuple" => [":consumer_secret", "aaaa"]}]
1882 },
1883 %{
1884 group: "pleroma",
1885 key: "key2",
1886 value: %{
1887 ":nested_1" => "nested_value1",
1888 ":nested_2" => [
1889 %{":nested_22" => "nested_value222"},
1890 %{":nested_33" => %{":nested_44" => "nested_444"}}
1891 ]
1892 }
1893 },
1894 %{
1895 group: "pleroma",
1896 key: "key3",
1897 value: [
1898 %{"nested_3" => ":nested_3", "nested_33" => "nested_33"},
1899 %{"nested_4" => true}
1900 ]
1901 },
1902 %{
1903 group: "pleroma",
1904 key: "key4",
1905 value: %{":nested_5" => ":upload", "endpoint" => "https://example.com"}
1906 },
1907 %{
1908 group: "idna",
1909 key: "key5",
1910 value: %{"tuple" => ["string", "Pleroma.Captcha.NotReal", []]}
1911 }
1912 ]
1913 })
1914
1915 assert json_response(conn, 200) == %{
1916 "configs" => [
1917 %{
1918 "group" => "pleroma",
1919 "key" => "key1",
1920 "value" => "value1"
1921 },
1922 %{
1923 "group" => "ueberauth",
1924 "key" => "Ueberauth.Strategy.Twitter.OAuth",
1925 "value" => [%{"tuple" => [":consumer_secret", "aaaa"]}]
1926 },
1927 %{
1928 "group" => "pleroma",
1929 "key" => "key2",
1930 "value" => %{
1931 ":nested_1" => "nested_value1",
1932 ":nested_2" => [
1933 %{":nested_22" => "nested_value222"},
1934 %{":nested_33" => %{":nested_44" => "nested_444"}}
1935 ]
1936 }
1937 },
1938 %{
1939 "group" => "pleroma",
1940 "key" => "key3",
1941 "value" => [
1942 %{"nested_3" => ":nested_3", "nested_33" => "nested_33"},
1943 %{"nested_4" => true}
1944 ]
1945 },
1946 %{
1947 "group" => "pleroma",
1948 "key" => "key4",
1949 "value" => %{"endpoint" => "https://example.com", ":nested_5" => ":upload"}
1950 },
1951 %{
1952 "group" => "idna",
1953 "key" => "key5",
1954 "value" => %{"tuple" => ["string", "Pleroma.Captcha.NotReal", []]}
1955 }
1956 ]
1957 }
1958
1959 assert Application.get_env(:pleroma, :key1) == "value1"
1960
1961 assert Application.get_env(:pleroma, :key2) == %{
1962 nested_1: "nested_value1",
1963 nested_2: [
1964 %{nested_22: "nested_value222"},
1965 %{nested_33: %{nested_44: "nested_444"}}
1966 ]
1967 }
1968
1969 assert Application.get_env(:pleroma, :key3) == [
1970 %{"nested_3" => :nested_3, "nested_33" => "nested_33"},
1971 %{"nested_4" => true}
1972 ]
1973
1974 assert Application.get_env(:pleroma, :key4) == %{
1975 "endpoint" => "https://example.com",
1976 nested_5: :upload
1977 }
1978
1979 assert Application.get_env(:idna, :key5) == {"string", Pleroma.Captcha.NotReal, []}
1980 end
1981
1982 test "update config setting & delete", %{conn: conn} do
1983 config1 = insert(:config, key: "keyaa1")
1984 config2 = insert(:config, key: "keyaa2")
1985
1986 insert(:config,
1987 group: "ueberauth",
1988 key: "Ueberauth.Strategy.Microsoft.OAuth",
1989 value: :erlang.term_to_binary([])
1990 )
1991
1992 conn =
1993 post(conn, "/api/pleroma/admin/config", %{
1994 configs: [
1995 %{group: config1.group, key: config1.key, value: "another_value"},
1996 %{group: config2.group, key: config2.key, delete: "true"},
1997 %{
1998 group: "ueberauth",
1999 key: "Ueberauth.Strategy.Microsoft.OAuth",
2000 delete: "true"
2001 }
2002 ]
2003 })
2004
2005 assert json_response(conn, 200) == %{
2006 "configs" => [
2007 %{
2008 "group" => "pleroma",
2009 "key" => config1.key,
2010 "value" => "another_value"
2011 }
2012 ]
2013 }
2014
2015 assert Application.get_env(:pleroma, :keyaa1) == "another_value"
2016 refute Application.get_env(:pleroma, :keyaa2)
2017 end
2018
2019 test "common config example", %{conn: conn} do
2020 conn =
2021 post(conn, "/api/pleroma/admin/config", %{
2022 configs: [
2023 %{
2024 "group" => "pleroma",
2025 "key" => "Pleroma.Captcha.NotReal",
2026 "value" => [
2027 %{"tuple" => [":enabled", false]},
2028 %{"tuple" => [":method", "Pleroma.Captcha.Kocaptcha"]},
2029 %{"tuple" => [":seconds_valid", 60]},
2030 %{"tuple" => [":path", ""]},
2031 %{"tuple" => [":key1", nil]},
2032 %{"tuple" => [":partial_chain", "&:hackney_connect.partial_chain/1"]},
2033 %{"tuple" => [":regex1", "~r/https:\/\/example.com/"]},
2034 %{"tuple" => [":regex2", "~r/https:\/\/example.com/u"]},
2035 %{"tuple" => [":regex3", "~r/https:\/\/example.com/i"]},
2036 %{"tuple" => [":regex4", "~r/https:\/\/example.com/s"]}
2037 ]
2038 }
2039 ]
2040 })
2041
2042 assert json_response(conn, 200) == %{
2043 "configs" => [
2044 %{
2045 "group" => "pleroma",
2046 "key" => "Pleroma.Captcha.NotReal",
2047 "value" => [
2048 %{"tuple" => [":enabled", false]},
2049 %{"tuple" => [":method", "Pleroma.Captcha.Kocaptcha"]},
2050 %{"tuple" => [":seconds_valid", 60]},
2051 %{"tuple" => [":path", ""]},
2052 %{"tuple" => [":key1", nil]},
2053 %{"tuple" => [":partial_chain", "&:hackney_connect.partial_chain/1"]},
2054 %{"tuple" => [":regex1", "~r/https:\\/\\/example.com/"]},
2055 %{"tuple" => [":regex2", "~r/https:\\/\\/example.com/u"]},
2056 %{"tuple" => [":regex3", "~r/https:\\/\\/example.com/i"]},
2057 %{"tuple" => [":regex4", "~r/https:\\/\\/example.com/s"]}
2058 ]
2059 }
2060 ]
2061 }
2062 end
2063
2064 test "tuples with more than two values", %{conn: conn} do
2065 conn =
2066 post(conn, "/api/pleroma/admin/config", %{
2067 configs: [
2068 %{
2069 "group" => "pleroma",
2070 "key" => "Pleroma.Web.Endpoint.NotReal",
2071 "value" => [
2072 %{
2073 "tuple" => [
2074 ":http",
2075 [
2076 %{
2077 "tuple" => [
2078 ":key2",
2079 [
2080 %{
2081 "tuple" => [
2082 ":_",
2083 [
2084 %{
2085 "tuple" => [
2086 "/api/v1/streaming",
2087 "Pleroma.Web.MastodonAPI.WebsocketHandler",
2088 []
2089 ]
2090 },
2091 %{
2092 "tuple" => [
2093 "/websocket",
2094 "Phoenix.Endpoint.CowboyWebSocket",
2095 %{
2096 "tuple" => [
2097 "Phoenix.Transports.WebSocket",
2098 %{
2099 "tuple" => [
2100 "Pleroma.Web.Endpoint",
2101 "Pleroma.Web.UserSocket",
2102 []
2103 ]
2104 }
2105 ]
2106 }
2107 ]
2108 },
2109 %{
2110 "tuple" => [
2111 ":_",
2112 "Phoenix.Endpoint.Cowboy2Handler",
2113 %{"tuple" => ["Pleroma.Web.Endpoint", []]}
2114 ]
2115 }
2116 ]
2117 ]
2118 }
2119 ]
2120 ]
2121 }
2122 ]
2123 ]
2124 }
2125 ]
2126 }
2127 ]
2128 })
2129
2130 assert json_response(conn, 200) == %{
2131 "configs" => [
2132 %{
2133 "group" => "pleroma",
2134 "key" => "Pleroma.Web.Endpoint.NotReal",
2135 "value" => [
2136 %{
2137 "tuple" => [
2138 ":http",
2139 [
2140 %{
2141 "tuple" => [
2142 ":key2",
2143 [
2144 %{
2145 "tuple" => [
2146 ":_",
2147 [
2148 %{
2149 "tuple" => [
2150 "/api/v1/streaming",
2151 "Pleroma.Web.MastodonAPI.WebsocketHandler",
2152 []
2153 ]
2154 },
2155 %{
2156 "tuple" => [
2157 "/websocket",
2158 "Phoenix.Endpoint.CowboyWebSocket",
2159 %{
2160 "tuple" => [
2161 "Phoenix.Transports.WebSocket",
2162 %{
2163 "tuple" => [
2164 "Pleroma.Web.Endpoint",
2165 "Pleroma.Web.UserSocket",
2166 []
2167 ]
2168 }
2169 ]
2170 }
2171 ]
2172 },
2173 %{
2174 "tuple" => [
2175 ":_",
2176 "Phoenix.Endpoint.Cowboy2Handler",
2177 %{"tuple" => ["Pleroma.Web.Endpoint", []]}
2178 ]
2179 }
2180 ]
2181 ]
2182 }
2183 ]
2184 ]
2185 }
2186 ]
2187 ]
2188 }
2189 ]
2190 }
2191 ]
2192 }
2193 end
2194
2195 test "settings with nesting map", %{conn: conn} do
2196 conn =
2197 post(conn, "/api/pleroma/admin/config", %{
2198 configs: [
2199 %{
2200 "group" => "pleroma",
2201 "key" => ":key1",
2202 "value" => [
2203 %{"tuple" => [":key2", "some_val"]},
2204 %{
2205 "tuple" => [
2206 ":key3",
2207 %{
2208 ":max_options" => 20,
2209 ":max_option_chars" => 200,
2210 ":min_expiration" => 0,
2211 ":max_expiration" => 31_536_000,
2212 "nested" => %{
2213 ":max_options" => 20,
2214 ":max_option_chars" => 200,
2215 ":min_expiration" => 0,
2216 ":max_expiration" => 31_536_000
2217 }
2218 }
2219 ]
2220 }
2221 ]
2222 }
2223 ]
2224 })
2225
2226 assert json_response(conn, 200) ==
2227 %{
2228 "configs" => [
2229 %{
2230 "group" => "pleroma",
2231 "key" => ":key1",
2232 "value" => [
2233 %{"tuple" => [":key2", "some_val"]},
2234 %{
2235 "tuple" => [
2236 ":key3",
2237 %{
2238 ":max_expiration" => 31_536_000,
2239 ":max_option_chars" => 200,
2240 ":max_options" => 20,
2241 ":min_expiration" => 0,
2242 "nested" => %{
2243 ":max_expiration" => 31_536_000,
2244 ":max_option_chars" => 200,
2245 ":max_options" => 20,
2246 ":min_expiration" => 0
2247 }
2248 }
2249 ]
2250 }
2251 ]
2252 }
2253 ]
2254 }
2255 end
2256
2257 test "value as map", %{conn: conn} do
2258 conn =
2259 post(conn, "/api/pleroma/admin/config", %{
2260 configs: [
2261 %{
2262 "group" => "pleroma",
2263 "key" => ":key1",
2264 "value" => %{"key" => "some_val"}
2265 }
2266 ]
2267 })
2268
2269 assert json_response(conn, 200) ==
2270 %{
2271 "configs" => [
2272 %{
2273 "group" => "pleroma",
2274 "key" => ":key1",
2275 "value" => %{"key" => "some_val"}
2276 }
2277 ]
2278 }
2279 end
2280
2281 test "dispatch setting", %{conn: conn} do
2282 conn =
2283 post(conn, "/api/pleroma/admin/config", %{
2284 configs: [
2285 %{
2286 "group" => "pleroma",
2287 "key" => "Pleroma.Web.Endpoint.NotReal",
2288 "value" => [
2289 %{
2290 "tuple" => [
2291 ":http",
2292 [
2293 %{"tuple" => [":ip", %{"tuple" => [127, 0, 0, 1]}]},
2294 %{"tuple" => [":dispatch", ["{:_,
2295 [
2296 {\"/api/v1/streaming\", Pleroma.Web.MastodonAPI.WebsocketHandler, []},
2297 {\"/websocket\", Phoenix.Endpoint.CowboyWebSocket,
2298 {Phoenix.Transports.WebSocket,
2299 {Pleroma.Web.Endpoint, Pleroma.Web.UserSocket, [path: \"/websocket\"]}}},
2300 {:_, Phoenix.Endpoint.Cowboy2Handler, {Pleroma.Web.Endpoint, []}}
2301 ]}"]]}
2302 ]
2303 ]
2304 }
2305 ]
2306 }
2307 ]
2308 })
2309
2310 dispatch_string =
2311 "{:_, [{\"/api/v1/streaming\", Pleroma.Web.MastodonAPI.WebsocketHandler, []}, " <>
2312 "{\"/websocket\", Phoenix.Endpoint.CowboyWebSocket, {Phoenix.Transports.WebSocket, " <>
2313 "{Pleroma.Web.Endpoint, Pleroma.Web.UserSocket, [path: \"/websocket\"]}}}, " <>
2314 "{:_, Phoenix.Endpoint.Cowboy2Handler, {Pleroma.Web.Endpoint, []}}]}"
2315
2316 assert json_response(conn, 200) == %{
2317 "configs" => [
2318 %{
2319 "group" => "pleroma",
2320 "key" => "Pleroma.Web.Endpoint.NotReal",
2321 "value" => [
2322 %{
2323 "tuple" => [
2324 ":http",
2325 [
2326 %{"tuple" => [":ip", %{"tuple" => [127, 0, 0, 1]}]},
2327 %{
2328 "tuple" => [
2329 ":dispatch",
2330 [
2331 dispatch_string
2332 ]
2333 ]
2334 }
2335 ]
2336 ]
2337 }
2338 ]
2339 }
2340 ]
2341 }
2342 end
2343
2344 test "queues key as atom", %{conn: conn} do
2345 conn =
2346 post(conn, "/api/pleroma/admin/config", %{
2347 configs: [
2348 %{
2349 "group" => "oban",
2350 "key" => ":queues",
2351 "value" => [
2352 %{"tuple" => [":federator_incoming", 50]},
2353 %{"tuple" => [":federator_outgoing", 50]},
2354 %{"tuple" => [":web_push", 50]},
2355 %{"tuple" => [":mailer", 10]},
2356 %{"tuple" => [":transmogrifier", 20]},
2357 %{"tuple" => [":scheduled_activities", 10]},
2358 %{"tuple" => [":background", 5]}
2359 ]
2360 }
2361 ]
2362 })
2363
2364 assert json_response(conn, 200) == %{
2365 "configs" => [
2366 %{
2367 "group" => "oban",
2368 "key" => ":queues",
2369 "value" => [
2370 %{"tuple" => [":federator_incoming", 50]},
2371 %{"tuple" => [":federator_outgoing", 50]},
2372 %{"tuple" => [":web_push", 50]},
2373 %{"tuple" => [":mailer", 10]},
2374 %{"tuple" => [":transmogrifier", 20]},
2375 %{"tuple" => [":scheduled_activities", 10]},
2376 %{"tuple" => [":background", 5]}
2377 ]
2378 }
2379 ]
2380 }
2381 end
2382
2383 test "delete part of settings by atom subkeys", %{conn: conn} do
2384 config =
2385 insert(:config,
2386 key: "keyaa1",
2387 value: :erlang.term_to_binary(subkey1: "val1", subkey2: "val2", subkey3: "val3")
2388 )
2389
2390 conn =
2391 post(conn, "/api/pleroma/admin/config", %{
2392 configs: [
2393 %{
2394 group: config.group,
2395 key: config.key,
2396 subkeys: [":subkey1", ":subkey3"],
2397 delete: "true"
2398 }
2399 ]
2400 })
2401
2402 assert(
2403 json_response(conn, 200) == %{
2404 "configs" => [
2405 %{
2406 "group" => "pleroma",
2407 "key" => "keyaa1",
2408 "value" => [%{"tuple" => [":subkey2", "val2"]}]
2409 }
2410 ]
2411 }
2412 )
2413 end
2414 end
2415
2416 describe "config mix tasks run" do
2417 setup %{conn: conn} do
2418 admin = insert(:user, is_admin: true)
2419
2420 temp_file = "config/test.exported_from_db.secret.exs"
2421
2422 Mix.shell(Mix.Shell.Quiet)
2423
2424 on_exit(fn ->
2425 Mix.shell(Mix.Shell.IO)
2426 :ok = File.rm(temp_file)
2427 end)
2428
2429 %{conn: assign(conn, :user, admin), admin: admin}
2430 end
2431
2432 clear_config([:instance, :dynamic_configuration]) do
2433 Pleroma.Config.put([:instance, :dynamic_configuration], true)
2434 end
2435
2436 clear_config([:feed, :post_title]) do
2437 Pleroma.Config.put([:feed, :post_title], %{max_length: 100, omission: "…"})
2438 end
2439
2440 test "transfer settings to DB and to file", %{conn: conn, admin: admin} do
2441 assert Pleroma.Repo.all(Pleroma.Web.AdminAPI.Config) == []
2442 conn = get(conn, "/api/pleroma/admin/config/migrate_to_db")
2443 assert json_response(conn, 200) == %{}
2444 assert Pleroma.Repo.all(Pleroma.Web.AdminAPI.Config) > 0
2445
2446 conn =
2447 build_conn()
2448 |> assign(:user, admin)
2449 |> get("/api/pleroma/admin/config/migrate_from_db")
2450
2451 assert json_response(conn, 200) == %{}
2452 assert Pleroma.Repo.all(Pleroma.Web.AdminAPI.Config) == []
2453 end
2454 end
2455
2456 describe "GET /api/pleroma/admin/users/:nickname/statuses" do
2457 setup do
2458 admin = insert(:user, is_admin: true)
2459 user = insert(:user)
2460
2461 date1 = (DateTime.to_unix(DateTime.utc_now()) + 2000) |> DateTime.from_unix!()
2462 date2 = (DateTime.to_unix(DateTime.utc_now()) + 1000) |> DateTime.from_unix!()
2463 date3 = (DateTime.to_unix(DateTime.utc_now()) + 3000) |> DateTime.from_unix!()
2464
2465 insert(:note_activity, user: user, published: date1)
2466 insert(:note_activity, user: user, published: date2)
2467 insert(:note_activity, user: user, published: date3)
2468
2469 conn =
2470 build_conn()
2471 |> assign(:user, admin)
2472
2473 {:ok, conn: conn, user: user}
2474 end
2475
2476 test "renders user's statuses", %{conn: conn, user: user} do
2477 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses")
2478
2479 assert json_response(conn, 200) |> length() == 3
2480 end
2481
2482 test "renders user's statuses with a limit", %{conn: conn, user: user} do
2483 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses?page_size=2")
2484
2485 assert json_response(conn, 200) |> length() == 2
2486 end
2487
2488 test "doesn't return private statuses by default", %{conn: conn, user: user} do
2489 {:ok, _private_status} =
2490 CommonAPI.post(user, %{"status" => "private", "visibility" => "private"})
2491
2492 {:ok, _public_status} =
2493 CommonAPI.post(user, %{"status" => "public", "visibility" => "public"})
2494
2495 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses")
2496
2497 assert json_response(conn, 200) |> length() == 4
2498 end
2499
2500 test "returns private statuses with godmode on", %{conn: conn, user: user} do
2501 {:ok, _private_status} =
2502 CommonAPI.post(user, %{"status" => "private", "visibility" => "private"})
2503
2504 {:ok, _public_status} =
2505 CommonAPI.post(user, %{"status" => "public", "visibility" => "public"})
2506
2507 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses?godmode=true")
2508
2509 assert json_response(conn, 200) |> length() == 5
2510 end
2511 end
2512
2513 describe "GET /api/pleroma/admin/moderation_log" do
2514 setup %{conn: conn} do
2515 admin = insert(:user, is_admin: true)
2516 moderator = insert(:user, is_moderator: true)
2517
2518 %{conn: assign(conn, :user, admin), admin: admin, moderator: moderator}
2519 end
2520
2521 test "returns the log", %{conn: conn, admin: admin} do
2522 Repo.insert(%ModerationLog{
2523 data: %{
2524 actor: %{
2525 "id" => admin.id,
2526 "nickname" => admin.nickname,
2527 "type" => "user"
2528 },
2529 action: "relay_follow",
2530 target: "https://example.org/relay"
2531 },
2532 inserted_at: NaiveDateTime.truncate(~N[2017-08-15 15:47:06.597036], :second)
2533 })
2534
2535 Repo.insert(%ModerationLog{
2536 data: %{
2537 actor: %{
2538 "id" => admin.id,
2539 "nickname" => admin.nickname,
2540 "type" => "user"
2541 },
2542 action: "relay_unfollow",
2543 target: "https://example.org/relay"
2544 },
2545 inserted_at: NaiveDateTime.truncate(~N[2017-08-16 15:47:06.597036], :second)
2546 })
2547
2548 conn = get(conn, "/api/pleroma/admin/moderation_log")
2549
2550 response = json_response(conn, 200)
2551 [first_entry, second_entry] = response["items"]
2552
2553 assert response["total"] == 2
2554 assert first_entry["data"]["action"] == "relay_unfollow"
2555
2556 assert first_entry["message"] ==
2557 "@#{admin.nickname} unfollowed relay: https://example.org/relay"
2558
2559 assert second_entry["data"]["action"] == "relay_follow"
2560
2561 assert second_entry["message"] ==
2562 "@#{admin.nickname} followed relay: https://example.org/relay"
2563 end
2564
2565 test "returns the log with pagination", %{conn: conn, admin: admin} do
2566 Repo.insert(%ModerationLog{
2567 data: %{
2568 actor: %{
2569 "id" => admin.id,
2570 "nickname" => admin.nickname,
2571 "type" => "user"
2572 },
2573 action: "relay_follow",
2574 target: "https://example.org/relay"
2575 },
2576 inserted_at: NaiveDateTime.truncate(~N[2017-08-15 15:47:06.597036], :second)
2577 })
2578
2579 Repo.insert(%ModerationLog{
2580 data: %{
2581 actor: %{
2582 "id" => admin.id,
2583 "nickname" => admin.nickname,
2584 "type" => "user"
2585 },
2586 action: "relay_unfollow",
2587 target: "https://example.org/relay"
2588 },
2589 inserted_at: NaiveDateTime.truncate(~N[2017-08-16 15:47:06.597036], :second)
2590 })
2591
2592 conn1 = get(conn, "/api/pleroma/admin/moderation_log?page_size=1&page=1")
2593
2594 response1 = json_response(conn1, 200)
2595 [first_entry] = response1["items"]
2596
2597 assert response1["total"] == 2
2598 assert response1["items"] |> length() == 1
2599 assert first_entry["data"]["action"] == "relay_unfollow"
2600
2601 assert first_entry["message"] ==
2602 "@#{admin.nickname} unfollowed relay: https://example.org/relay"
2603
2604 conn2 = get(conn, "/api/pleroma/admin/moderation_log?page_size=1&page=2")
2605
2606 response2 = json_response(conn2, 200)
2607 [second_entry] = response2["items"]
2608
2609 assert response2["total"] == 2
2610 assert response2["items"] |> length() == 1
2611 assert second_entry["data"]["action"] == "relay_follow"
2612
2613 assert second_entry["message"] ==
2614 "@#{admin.nickname} followed relay: https://example.org/relay"
2615 end
2616
2617 test "filters log by date", %{conn: conn, admin: admin} do
2618 first_date = "2017-08-15T15:47:06Z"
2619 second_date = "2017-08-20T15:47:06Z"
2620
2621 Repo.insert(%ModerationLog{
2622 data: %{
2623 actor: %{
2624 "id" => admin.id,
2625 "nickname" => admin.nickname,
2626 "type" => "user"
2627 },
2628 action: "relay_follow",
2629 target: "https://example.org/relay"
2630 },
2631 inserted_at: NaiveDateTime.from_iso8601!(first_date)
2632 })
2633
2634 Repo.insert(%ModerationLog{
2635 data: %{
2636 actor: %{
2637 "id" => admin.id,
2638 "nickname" => admin.nickname,
2639 "type" => "user"
2640 },
2641 action: "relay_unfollow",
2642 target: "https://example.org/relay"
2643 },
2644 inserted_at: NaiveDateTime.from_iso8601!(second_date)
2645 })
2646
2647 conn1 =
2648 get(
2649 conn,
2650 "/api/pleroma/admin/moderation_log?start_date=#{second_date}"
2651 )
2652
2653 response1 = json_response(conn1, 200)
2654 [first_entry] = response1["items"]
2655
2656 assert response1["total"] == 1
2657 assert first_entry["data"]["action"] == "relay_unfollow"
2658
2659 assert first_entry["message"] ==
2660 "@#{admin.nickname} unfollowed relay: https://example.org/relay"
2661 end
2662
2663 test "returns log filtered by user", %{conn: conn, admin: admin, moderator: moderator} do
2664 Repo.insert(%ModerationLog{
2665 data: %{
2666 actor: %{
2667 "id" => admin.id,
2668 "nickname" => admin.nickname,
2669 "type" => "user"
2670 },
2671 action: "relay_follow",
2672 target: "https://example.org/relay"
2673 }
2674 })
2675
2676 Repo.insert(%ModerationLog{
2677 data: %{
2678 actor: %{
2679 "id" => moderator.id,
2680 "nickname" => moderator.nickname,
2681 "type" => "user"
2682 },
2683 action: "relay_unfollow",
2684 target: "https://example.org/relay"
2685 }
2686 })
2687
2688 conn1 = get(conn, "/api/pleroma/admin/moderation_log?user_id=#{moderator.id}")
2689
2690 response1 = json_response(conn1, 200)
2691 [first_entry] = response1["items"]
2692
2693 assert response1["total"] == 1
2694 assert get_in(first_entry, ["data", "actor", "id"]) == moderator.id
2695 end
2696
2697 test "returns log filtered by search", %{conn: conn, moderator: moderator} do
2698 ModerationLog.insert_log(%{
2699 actor: moderator,
2700 action: "relay_follow",
2701 target: "https://example.org/relay"
2702 })
2703
2704 ModerationLog.insert_log(%{
2705 actor: moderator,
2706 action: "relay_unfollow",
2707 target: "https://example.org/relay"
2708 })
2709
2710 conn1 = get(conn, "/api/pleroma/admin/moderation_log?search=unfo")
2711
2712 response1 = json_response(conn1, 200)
2713 [first_entry] = response1["items"]
2714
2715 assert response1["total"] == 1
2716
2717 assert get_in(first_entry, ["data", "message"]) ==
2718 "@#{moderator.nickname} unfollowed relay: https://example.org/relay"
2719 end
2720 end
2721
2722 describe "PATCH /users/:nickname/force_password_reset" do
2723 setup %{conn: conn} do
2724 admin = insert(:user, is_admin: true)
2725 user = insert(:user)
2726
2727 %{conn: assign(conn, :user, admin), admin: admin, user: user}
2728 end
2729
2730 test "sets password_reset_pending to true", %{admin: admin, user: user} do
2731 assert user.password_reset_pending == false
2732
2733 conn =
2734 build_conn()
2735 |> assign(:user, admin)
2736 |> patch("/api/pleroma/admin/users/force_password_reset", %{nicknames: [user.nickname]})
2737
2738 assert json_response(conn, 204) == ""
2739
2740 ObanHelpers.perform_all()
2741
2742 assert User.get_by_id(user.id).password_reset_pending == true
2743 end
2744 end
2745
2746 describe "relays" do
2747 setup %{conn: conn} do
2748 admin = insert(:user, is_admin: true)
2749
2750 %{conn: assign(conn, :user, admin), admin: admin}
2751 end
2752
2753 test "POST /relay", %{admin: admin} do
2754 conn =
2755 build_conn()
2756 |> assign(:user, admin)
2757 |> post("/api/pleroma/admin/relay", %{
2758 relay_url: "http://mastodon.example.org/users/admin"
2759 })
2760
2761 assert json_response(conn, 200) == "http://mastodon.example.org/users/admin"
2762
2763 log_entry = Repo.one(ModerationLog)
2764
2765 assert ModerationLog.get_log_entry_message(log_entry) ==
2766 "@#{admin.nickname} followed relay: http://mastodon.example.org/users/admin"
2767 end
2768
2769 test "GET /relay", %{admin: admin} do
2770 relay_user = Pleroma.Web.ActivityPub.Relay.get_actor()
2771
2772 ["http://mastodon.example.org/users/admin", "https://mstdn.io/users/mayuutann"]
2773 |> Enum.each(fn ap_id ->
2774 {:ok, user} = User.get_or_fetch_by_ap_id(ap_id)
2775 User.follow(relay_user, user)
2776 end)
2777
2778 conn =
2779 build_conn()
2780 |> assign(:user, admin)
2781 |> get("/api/pleroma/admin/relay")
2782
2783 assert json_response(conn, 200)["relays"] -- ["mastodon.example.org", "mstdn.io"] == []
2784 end
2785
2786 test "DELETE /relay", %{admin: admin} do
2787 build_conn()
2788 |> assign(:user, admin)
2789 |> post("/api/pleroma/admin/relay", %{
2790 relay_url: "http://mastodon.example.org/users/admin"
2791 })
2792
2793 conn =
2794 build_conn()
2795 |> assign(:user, admin)
2796 |> delete("/api/pleroma/admin/relay", %{
2797 relay_url: "http://mastodon.example.org/users/admin"
2798 })
2799
2800 assert json_response(conn, 200) == "http://mastodon.example.org/users/admin"
2801
2802 [log_entry_one, log_entry_two] = Repo.all(ModerationLog)
2803
2804 assert ModerationLog.get_log_entry_message(log_entry_one) ==
2805 "@#{admin.nickname} followed relay: http://mastodon.example.org/users/admin"
2806
2807 assert ModerationLog.get_log_entry_message(log_entry_two) ==
2808 "@#{admin.nickname} unfollowed relay: http://mastodon.example.org/users/admin"
2809 end
2810 end
2811
2812 describe "instances" do
2813 test "GET /instances/:instance/statuses" do
2814 admin = insert(:user, is_admin: true)
2815 user = insert(:user, local: false, nickname: "archaeme@archae.me")
2816 user2 = insert(:user, local: false, nickname: "test@test.com")
2817 insert_pair(:note_activity, user: user)
2818 insert(:note_activity, user: user2)
2819
2820 conn =
2821 build_conn()
2822 |> assign(:user, admin)
2823 |> get("/api/pleroma/admin/instances/archae.me/statuses")
2824
2825 response = json_response(conn, 200)
2826
2827 assert length(response) == 2
2828
2829 conn =
2830 build_conn()
2831 |> assign(:user, admin)
2832 |> get("/api/pleroma/admin/instances/test.com/statuses")
2833
2834 response = json_response(conn, 200)
2835
2836 assert length(response) == 1
2837
2838 conn =
2839 build_conn()
2840 |> assign(:user, admin)
2841 |> get("/api/pleroma/admin/instances/nonexistent.com/statuses")
2842
2843 response = json_response(conn, 200)
2844
2845 assert length(response) == 0
2846 end
2847 end
2848
2849 describe "PATCH /confirm_email" do
2850 setup %{conn: conn} do
2851 admin = insert(:user, is_admin: true)
2852
2853 %{conn: assign(conn, :user, admin), admin: admin}
2854 end
2855
2856 test "it confirms emails of two users", %{admin: admin} do
2857 [first_user, second_user] = insert_pair(:user, confirmation_pending: true)
2858
2859 assert first_user.confirmation_pending == true
2860 assert second_user.confirmation_pending == true
2861
2862 build_conn()
2863 |> assign(:user, admin)
2864 |> patch("/api/pleroma/admin/users/confirm_email", %{
2865 nicknames: [
2866 first_user.nickname,
2867 second_user.nickname
2868 ]
2869 })
2870
2871 assert first_user.confirmation_pending == true
2872 assert second_user.confirmation_pending == true
2873
2874 log_entry = Repo.one(ModerationLog)
2875
2876 assert ModerationLog.get_log_entry_message(log_entry) ==
2877 "@#{admin.nickname} confirmed email for users: @#{first_user.nickname}, @#{
2878 second_user.nickname
2879 }"
2880 end
2881 end
2882
2883 describe "PATCH /resend_confirmation_email" do
2884 setup %{conn: conn} do
2885 admin = insert(:user, is_admin: true)
2886
2887 %{conn: assign(conn, :user, admin), admin: admin}
2888 end
2889
2890 test "it resend emails for two users", %{admin: admin} do
2891 [first_user, second_user] = insert_pair(:user, confirmation_pending: true)
2892
2893 build_conn()
2894 |> assign(:user, admin)
2895 |> patch("/api/pleroma/admin/users/resend_confirmation_email", %{
2896 nicknames: [
2897 first_user.nickname,
2898 second_user.nickname
2899 ]
2900 })
2901
2902 log_entry = Repo.one(ModerationLog)
2903
2904 assert ModerationLog.get_log_entry_message(log_entry) ==
2905 "@#{admin.nickname} re-sent confirmation email for users: @#{first_user.nickname}, @#{
2906 second_user.nickname
2907 }"
2908 end
2909 end
2910
2911 describe "POST /reports/:id/notes" do
2912 setup do
2913 admin = insert(:user, is_admin: true)
2914 [reporter, target_user] = insert_pair(:user)
2915 activity = insert(:note_activity, user: target_user)
2916
2917 {:ok, %{id: report_id}} =
2918 CommonAPI.report(reporter, %{
2919 "account_id" => target_user.id,
2920 "comment" => "I feel offended",
2921 "status_ids" => [activity.id]
2922 })
2923
2924 build_conn()
2925 |> assign(:user, admin)
2926 |> post("/api/pleroma/admin/reports/#{report_id}/notes", %{
2927 content: "this is disgusting!"
2928 })
2929
2930 build_conn()
2931 |> assign(:user, admin)
2932 |> post("/api/pleroma/admin/reports/#{report_id}/notes", %{
2933 content: "this is disgusting2!"
2934 })
2935
2936 %{
2937 admin_id: admin.id,
2938 report_id: report_id,
2939 admin: admin
2940 }
2941 end
2942
2943 test "it creates report note", %{admin_id: admin_id, report_id: report_id} do
2944 [note, _] = Repo.all(ReportNote)
2945
2946 assert %{
2947 activity_id: ^report_id,
2948 content: "this is disgusting!",
2949 user_id: ^admin_id
2950 } = note
2951 end
2952
2953 test "it returns reports with notes", %{admin: admin} do
2954 conn =
2955 build_conn()
2956 |> assign(:user, admin)
2957 |> get("/api/pleroma/admin/reports")
2958
2959 response = json_response(conn, 200)
2960 notes = hd(response["reports"])["notes"]
2961 [note, _] = notes
2962
2963 assert note["user"]["nickname"] == admin.nickname
2964 assert note["content"] == "this is disgusting!"
2965 assert note["created_at"]
2966 assert response["total"] == 1
2967 end
2968
2969 test "it deletes the note", %{admin: admin, report_id: report_id} do
2970 assert ReportNote |> Repo.all() |> length() == 2
2971
2972 [note, _] = Repo.all(ReportNote)
2973
2974 build_conn()
2975 |> assign(:user, admin)
2976 |> delete("/api/pleroma/admin/reports/#{report_id}/notes/#{note.id}")
2977
2978 assert ReportNote |> Repo.all() |> length() == 1
2979 end
2980 end
2981 end
2982
2983 # Needed for testing
2984 defmodule Pleroma.Web.Endpoint.NotReal do
2985 end
2986
2987 defmodule Pleroma.Captcha.NotReal do
2988 end