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