Merge branch 'develop' into issue/1411
[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 "POST /api/pleroma/admin/reports/:id/respond" do
1714 setup %{conn: conn} do
1715 admin = insert(:user, is_admin: true)
1716
1717 %{conn: assign(conn, :user, admin), admin: admin}
1718 end
1719
1720 test "returns created dm", %{conn: conn, admin: admin} do
1721 [reporter, target_user] = insert_pair(:user)
1722 activity = insert(:note_activity, user: target_user)
1723
1724 {:ok, %{id: report_id}} =
1725 CommonAPI.report(reporter, %{
1726 "account_id" => target_user.id,
1727 "comment" => "I feel offended",
1728 "status_ids" => [activity.id]
1729 })
1730
1731 response =
1732 conn
1733 |> post("/api/pleroma/admin/reports/#{report_id}/respond", %{
1734 "status" => "I will check it out"
1735 })
1736 |> json_response(:ok)
1737
1738 recipients = Enum.map(response["mentions"], & &1["username"])
1739
1740 assert reporter.nickname in recipients
1741 assert response["content"] == "I will check it out"
1742 assert response["visibility"] == "direct"
1743
1744 log_entry = Repo.one(ModerationLog)
1745
1746 assert ModerationLog.get_log_entry_message(log_entry) ==
1747 "@#{admin.nickname} responded with 'I will check it out' to report ##{
1748 response["id"]
1749 }"
1750 end
1751
1752 test "returns 400 when status is missing", %{conn: conn} do
1753 conn = post(conn, "/api/pleroma/admin/reports/test/respond")
1754
1755 assert json_response(conn, :bad_request) == "Invalid parameters"
1756 end
1757
1758 test "returns 404 when report id is invalid", %{conn: conn} do
1759 conn =
1760 post(conn, "/api/pleroma/admin/reports/test/respond", %{
1761 "status" => "foo"
1762 })
1763
1764 assert json_response(conn, :not_found) == "Not found"
1765 end
1766 end
1767
1768 describe "PUT /api/pleroma/admin/statuses/:id" do
1769 setup %{conn: conn} do
1770 admin = insert(:user, is_admin: true)
1771 activity = insert(:note_activity)
1772
1773 %{conn: assign(conn, :user, admin), id: activity.id, admin: admin}
1774 end
1775
1776 test "toggle sensitive flag", %{conn: conn, id: id, admin: admin} do
1777 response =
1778 conn
1779 |> put("/api/pleroma/admin/statuses/#{id}", %{"sensitive" => "true"})
1780 |> json_response(:ok)
1781
1782 assert response["sensitive"]
1783
1784 log_entry = Repo.one(ModerationLog)
1785
1786 assert ModerationLog.get_log_entry_message(log_entry) ==
1787 "@#{admin.nickname} updated status ##{id}, set sensitive: 'true'"
1788
1789 response =
1790 conn
1791 |> put("/api/pleroma/admin/statuses/#{id}", %{"sensitive" => "false"})
1792 |> json_response(:ok)
1793
1794 refute response["sensitive"]
1795 end
1796
1797 test "change visibility flag", %{conn: conn, id: id, admin: admin} do
1798 response =
1799 conn
1800 |> put("/api/pleroma/admin/statuses/#{id}", %{"visibility" => "public"})
1801 |> json_response(:ok)
1802
1803 assert response["visibility"] == "public"
1804
1805 log_entry = Repo.one(ModerationLog)
1806
1807 assert ModerationLog.get_log_entry_message(log_entry) ==
1808 "@#{admin.nickname} updated status ##{id}, set visibility: 'public'"
1809
1810 response =
1811 conn
1812 |> put("/api/pleroma/admin/statuses/#{id}", %{"visibility" => "private"})
1813 |> json_response(:ok)
1814
1815 assert response["visibility"] == "private"
1816
1817 response =
1818 conn
1819 |> put("/api/pleroma/admin/statuses/#{id}", %{"visibility" => "unlisted"})
1820 |> json_response(:ok)
1821
1822 assert response["visibility"] == "unlisted"
1823 end
1824
1825 test "returns 400 when visibility is unknown", %{conn: conn, id: id} do
1826 conn =
1827 conn
1828 |> put("/api/pleroma/admin/statuses/#{id}", %{"visibility" => "test"})
1829
1830 assert json_response(conn, :bad_request) == "Unsupported visibility"
1831 end
1832 end
1833
1834 describe "DELETE /api/pleroma/admin/statuses/:id" do
1835 setup %{conn: conn} do
1836 admin = insert(:user, is_admin: true)
1837 activity = insert(:note_activity)
1838
1839 %{conn: assign(conn, :user, admin), id: activity.id, admin: admin}
1840 end
1841
1842 test "deletes status", %{conn: conn, id: id, admin: admin} do
1843 conn
1844 |> delete("/api/pleroma/admin/statuses/#{id}")
1845 |> json_response(:ok)
1846
1847 refute Activity.get_by_id(id)
1848
1849 log_entry = Repo.one(ModerationLog)
1850
1851 assert ModerationLog.get_log_entry_message(log_entry) ==
1852 "@#{admin.nickname} deleted status ##{id}"
1853 end
1854
1855 test "returns error when status is not exist", %{conn: conn} do
1856 conn =
1857 conn
1858 |> delete("/api/pleroma/admin/statuses/test")
1859
1860 assert json_response(conn, :bad_request) == "Could not delete"
1861 end
1862 end
1863
1864 describe "GET /api/pleroma/admin/config" do
1865 setup %{conn: conn} do
1866 admin = insert(:user, is_admin: true)
1867
1868 %{conn: assign(conn, :user, admin)}
1869 end
1870
1871 test "without any settings in db", %{conn: conn} do
1872 conn = get(conn, "/api/pleroma/admin/config")
1873
1874 assert json_response(conn, 200) == %{"configs" => []}
1875 end
1876
1877 test "with settings in db", %{conn: conn} do
1878 config1 = insert(:config)
1879 config2 = insert(:config)
1880
1881 conn = get(conn, "/api/pleroma/admin/config")
1882
1883 %{
1884 "configs" => [
1885 %{
1886 "key" => key1,
1887 "value" => _
1888 },
1889 %{
1890 "key" => key2,
1891 "value" => _
1892 }
1893 ]
1894 } = json_response(conn, 200)
1895
1896 assert key1 == config1.key
1897 assert key2 == config2.key
1898 end
1899 end
1900
1901 describe "POST /api/pleroma/admin/config" do
1902 setup %{conn: conn} do
1903 admin = insert(:user, is_admin: true)
1904
1905 temp_file = "config/test.exported_from_db.secret.exs"
1906
1907 on_exit(fn ->
1908 Application.delete_env(:pleroma, :key1)
1909 Application.delete_env(:pleroma, :key2)
1910 Application.delete_env(:pleroma, :key3)
1911 Application.delete_env(:pleroma, :key4)
1912 Application.delete_env(:pleroma, :keyaa1)
1913 Application.delete_env(:pleroma, :keyaa2)
1914 Application.delete_env(:pleroma, Pleroma.Web.Endpoint.NotReal)
1915 Application.delete_env(:pleroma, Pleroma.Captcha.NotReal)
1916 :ok = File.rm(temp_file)
1917 end)
1918
1919 %{conn: assign(conn, :user, admin)}
1920 end
1921
1922 clear_config([:instance, :dynamic_configuration]) do
1923 Pleroma.Config.put([:instance, :dynamic_configuration], true)
1924 end
1925
1926 @tag capture_log: true
1927 test "create new config setting in db", %{conn: conn} do
1928 conn =
1929 post(conn, "/api/pleroma/admin/config", %{
1930 configs: [
1931 %{group: "pleroma", key: "key1", value: "value1"},
1932 %{
1933 group: "ueberauth",
1934 key: "Ueberauth.Strategy.Twitter.OAuth",
1935 value: [%{"tuple" => [":consumer_secret", "aaaa"]}]
1936 },
1937 %{
1938 group: "pleroma",
1939 key: "key2",
1940 value: %{
1941 ":nested_1" => "nested_value1",
1942 ":nested_2" => [
1943 %{":nested_22" => "nested_value222"},
1944 %{":nested_33" => %{":nested_44" => "nested_444"}}
1945 ]
1946 }
1947 },
1948 %{
1949 group: "pleroma",
1950 key: "key3",
1951 value: [
1952 %{"nested_3" => ":nested_3", "nested_33" => "nested_33"},
1953 %{"nested_4" => true}
1954 ]
1955 },
1956 %{
1957 group: "pleroma",
1958 key: "key4",
1959 value: %{":nested_5" => ":upload", "endpoint" => "https://example.com"}
1960 },
1961 %{
1962 group: "idna",
1963 key: "key5",
1964 value: %{"tuple" => ["string", "Pleroma.Captcha.NotReal", []]}
1965 }
1966 ]
1967 })
1968
1969 assert json_response(conn, 200) == %{
1970 "configs" => [
1971 %{
1972 "group" => "pleroma",
1973 "key" => "key1",
1974 "value" => "value1"
1975 },
1976 %{
1977 "group" => "ueberauth",
1978 "key" => "Ueberauth.Strategy.Twitter.OAuth",
1979 "value" => [%{"tuple" => [":consumer_secret", "aaaa"]}]
1980 },
1981 %{
1982 "group" => "pleroma",
1983 "key" => "key2",
1984 "value" => %{
1985 ":nested_1" => "nested_value1",
1986 ":nested_2" => [
1987 %{":nested_22" => "nested_value222"},
1988 %{":nested_33" => %{":nested_44" => "nested_444"}}
1989 ]
1990 }
1991 },
1992 %{
1993 "group" => "pleroma",
1994 "key" => "key3",
1995 "value" => [
1996 %{"nested_3" => ":nested_3", "nested_33" => "nested_33"},
1997 %{"nested_4" => true}
1998 ]
1999 },
2000 %{
2001 "group" => "pleroma",
2002 "key" => "key4",
2003 "value" => %{"endpoint" => "https://example.com", ":nested_5" => ":upload"}
2004 },
2005 %{
2006 "group" => "idna",
2007 "key" => "key5",
2008 "value" => %{"tuple" => ["string", "Pleroma.Captcha.NotReal", []]}
2009 }
2010 ]
2011 }
2012
2013 assert Application.get_env(:pleroma, :key1) == "value1"
2014
2015 assert Application.get_env(:pleroma, :key2) == %{
2016 nested_1: "nested_value1",
2017 nested_2: [
2018 %{nested_22: "nested_value222"},
2019 %{nested_33: %{nested_44: "nested_444"}}
2020 ]
2021 }
2022
2023 assert Application.get_env(:pleroma, :key3) == [
2024 %{"nested_3" => :nested_3, "nested_33" => "nested_33"},
2025 %{"nested_4" => true}
2026 ]
2027
2028 assert Application.get_env(:pleroma, :key4) == %{
2029 "endpoint" => "https://example.com",
2030 nested_5: :upload
2031 }
2032
2033 assert Application.get_env(:idna, :key5) == {"string", Pleroma.Captcha.NotReal, []}
2034 end
2035
2036 test "update config setting & delete", %{conn: conn} do
2037 config1 = insert(:config, key: "keyaa1")
2038 config2 = insert(:config, key: "keyaa2")
2039
2040 insert(:config,
2041 group: "ueberauth",
2042 key: "Ueberauth.Strategy.Microsoft.OAuth",
2043 value: :erlang.term_to_binary([])
2044 )
2045
2046 conn =
2047 post(conn, "/api/pleroma/admin/config", %{
2048 configs: [
2049 %{group: config1.group, key: config1.key, value: "another_value"},
2050 %{group: config2.group, key: config2.key, delete: "true"},
2051 %{
2052 group: "ueberauth",
2053 key: "Ueberauth.Strategy.Microsoft.OAuth",
2054 delete: "true"
2055 }
2056 ]
2057 })
2058
2059 assert json_response(conn, 200) == %{
2060 "configs" => [
2061 %{
2062 "group" => "pleroma",
2063 "key" => config1.key,
2064 "value" => "another_value"
2065 }
2066 ]
2067 }
2068
2069 assert Application.get_env(:pleroma, :keyaa1) == "another_value"
2070 refute Application.get_env(:pleroma, :keyaa2)
2071 end
2072
2073 test "common config example", %{conn: conn} do
2074 conn =
2075 post(conn, "/api/pleroma/admin/config", %{
2076 configs: [
2077 %{
2078 "group" => "pleroma",
2079 "key" => "Pleroma.Captcha.NotReal",
2080 "value" => [
2081 %{"tuple" => [":enabled", false]},
2082 %{"tuple" => [":method", "Pleroma.Captcha.Kocaptcha"]},
2083 %{"tuple" => [":seconds_valid", 60]},
2084 %{"tuple" => [":path", ""]},
2085 %{"tuple" => [":key1", nil]},
2086 %{"tuple" => [":partial_chain", "&:hackney_connect.partial_chain/1"]},
2087 %{"tuple" => [":regex1", "~r/https:\/\/example.com/"]},
2088 %{"tuple" => [":regex2", "~r/https:\/\/example.com/u"]},
2089 %{"tuple" => [":regex3", "~r/https:\/\/example.com/i"]},
2090 %{"tuple" => [":regex4", "~r/https:\/\/example.com/s"]}
2091 ]
2092 }
2093 ]
2094 })
2095
2096 assert json_response(conn, 200) == %{
2097 "configs" => [
2098 %{
2099 "group" => "pleroma",
2100 "key" => "Pleroma.Captcha.NotReal",
2101 "value" => [
2102 %{"tuple" => [":enabled", false]},
2103 %{"tuple" => [":method", "Pleroma.Captcha.Kocaptcha"]},
2104 %{"tuple" => [":seconds_valid", 60]},
2105 %{"tuple" => [":path", ""]},
2106 %{"tuple" => [":key1", nil]},
2107 %{"tuple" => [":partial_chain", "&:hackney_connect.partial_chain/1"]},
2108 %{"tuple" => [":regex1", "~r/https:\\/\\/example.com/"]},
2109 %{"tuple" => [":regex2", "~r/https:\\/\\/example.com/u"]},
2110 %{"tuple" => [":regex3", "~r/https:\\/\\/example.com/i"]},
2111 %{"tuple" => [":regex4", "~r/https:\\/\\/example.com/s"]}
2112 ]
2113 }
2114 ]
2115 }
2116 end
2117
2118 test "tuples with more than two values", %{conn: conn} do
2119 conn =
2120 post(conn, "/api/pleroma/admin/config", %{
2121 configs: [
2122 %{
2123 "group" => "pleroma",
2124 "key" => "Pleroma.Web.Endpoint.NotReal",
2125 "value" => [
2126 %{
2127 "tuple" => [
2128 ":http",
2129 [
2130 %{
2131 "tuple" => [
2132 ":key2",
2133 [
2134 %{
2135 "tuple" => [
2136 ":_",
2137 [
2138 %{
2139 "tuple" => [
2140 "/api/v1/streaming",
2141 "Pleroma.Web.MastodonAPI.WebsocketHandler",
2142 []
2143 ]
2144 },
2145 %{
2146 "tuple" => [
2147 "/websocket",
2148 "Phoenix.Endpoint.CowboyWebSocket",
2149 %{
2150 "tuple" => [
2151 "Phoenix.Transports.WebSocket",
2152 %{
2153 "tuple" => [
2154 "Pleroma.Web.Endpoint",
2155 "Pleroma.Web.UserSocket",
2156 []
2157 ]
2158 }
2159 ]
2160 }
2161 ]
2162 },
2163 %{
2164 "tuple" => [
2165 ":_",
2166 "Phoenix.Endpoint.Cowboy2Handler",
2167 %{"tuple" => ["Pleroma.Web.Endpoint", []]}
2168 ]
2169 }
2170 ]
2171 ]
2172 }
2173 ]
2174 ]
2175 }
2176 ]
2177 ]
2178 }
2179 ]
2180 }
2181 ]
2182 })
2183
2184 assert json_response(conn, 200) == %{
2185 "configs" => [
2186 %{
2187 "group" => "pleroma",
2188 "key" => "Pleroma.Web.Endpoint.NotReal",
2189 "value" => [
2190 %{
2191 "tuple" => [
2192 ":http",
2193 [
2194 %{
2195 "tuple" => [
2196 ":key2",
2197 [
2198 %{
2199 "tuple" => [
2200 ":_",
2201 [
2202 %{
2203 "tuple" => [
2204 "/api/v1/streaming",
2205 "Pleroma.Web.MastodonAPI.WebsocketHandler",
2206 []
2207 ]
2208 },
2209 %{
2210 "tuple" => [
2211 "/websocket",
2212 "Phoenix.Endpoint.CowboyWebSocket",
2213 %{
2214 "tuple" => [
2215 "Phoenix.Transports.WebSocket",
2216 %{
2217 "tuple" => [
2218 "Pleroma.Web.Endpoint",
2219 "Pleroma.Web.UserSocket",
2220 []
2221 ]
2222 }
2223 ]
2224 }
2225 ]
2226 },
2227 %{
2228 "tuple" => [
2229 ":_",
2230 "Phoenix.Endpoint.Cowboy2Handler",
2231 %{"tuple" => ["Pleroma.Web.Endpoint", []]}
2232 ]
2233 }
2234 ]
2235 ]
2236 }
2237 ]
2238 ]
2239 }
2240 ]
2241 ]
2242 }
2243 ]
2244 }
2245 ]
2246 }
2247 end
2248
2249 test "settings with nesting map", %{conn: conn} do
2250 conn =
2251 post(conn, "/api/pleroma/admin/config", %{
2252 configs: [
2253 %{
2254 "group" => "pleroma",
2255 "key" => ":key1",
2256 "value" => [
2257 %{"tuple" => [":key2", "some_val"]},
2258 %{
2259 "tuple" => [
2260 ":key3",
2261 %{
2262 ":max_options" => 20,
2263 ":max_option_chars" => 200,
2264 ":min_expiration" => 0,
2265 ":max_expiration" => 31_536_000,
2266 "nested" => %{
2267 ":max_options" => 20,
2268 ":max_option_chars" => 200,
2269 ":min_expiration" => 0,
2270 ":max_expiration" => 31_536_000
2271 }
2272 }
2273 ]
2274 }
2275 ]
2276 }
2277 ]
2278 })
2279
2280 assert json_response(conn, 200) ==
2281 %{
2282 "configs" => [
2283 %{
2284 "group" => "pleroma",
2285 "key" => ":key1",
2286 "value" => [
2287 %{"tuple" => [":key2", "some_val"]},
2288 %{
2289 "tuple" => [
2290 ":key3",
2291 %{
2292 ":max_expiration" => 31_536_000,
2293 ":max_option_chars" => 200,
2294 ":max_options" => 20,
2295 ":min_expiration" => 0,
2296 "nested" => %{
2297 ":max_expiration" => 31_536_000,
2298 ":max_option_chars" => 200,
2299 ":max_options" => 20,
2300 ":min_expiration" => 0
2301 }
2302 }
2303 ]
2304 }
2305 ]
2306 }
2307 ]
2308 }
2309 end
2310
2311 test "value as map", %{conn: conn} do
2312 conn =
2313 post(conn, "/api/pleroma/admin/config", %{
2314 configs: [
2315 %{
2316 "group" => "pleroma",
2317 "key" => ":key1",
2318 "value" => %{"key" => "some_val"}
2319 }
2320 ]
2321 })
2322
2323 assert json_response(conn, 200) ==
2324 %{
2325 "configs" => [
2326 %{
2327 "group" => "pleroma",
2328 "key" => ":key1",
2329 "value" => %{"key" => "some_val"}
2330 }
2331 ]
2332 }
2333 end
2334
2335 test "dispatch setting", %{conn: conn} do
2336 conn =
2337 post(conn, "/api/pleroma/admin/config", %{
2338 configs: [
2339 %{
2340 "group" => "pleroma",
2341 "key" => "Pleroma.Web.Endpoint.NotReal",
2342 "value" => [
2343 %{
2344 "tuple" => [
2345 ":http",
2346 [
2347 %{"tuple" => [":ip", %{"tuple" => [127, 0, 0, 1]}]},
2348 %{"tuple" => [":dispatch", ["{:_,
2349 [
2350 {\"/api/v1/streaming\", Pleroma.Web.MastodonAPI.WebsocketHandler, []},
2351 {\"/websocket\", Phoenix.Endpoint.CowboyWebSocket,
2352 {Phoenix.Transports.WebSocket,
2353 {Pleroma.Web.Endpoint, Pleroma.Web.UserSocket, [path: \"/websocket\"]}}},
2354 {:_, Phoenix.Endpoint.Cowboy2Handler, {Pleroma.Web.Endpoint, []}}
2355 ]}"]]}
2356 ]
2357 ]
2358 }
2359 ]
2360 }
2361 ]
2362 })
2363
2364 dispatch_string =
2365 "{:_, [{\"/api/v1/streaming\", Pleroma.Web.MastodonAPI.WebsocketHandler, []}, " <>
2366 "{\"/websocket\", Phoenix.Endpoint.CowboyWebSocket, {Phoenix.Transports.WebSocket, " <>
2367 "{Pleroma.Web.Endpoint, Pleroma.Web.UserSocket, [path: \"/websocket\"]}}}, " <>
2368 "{:_, Phoenix.Endpoint.Cowboy2Handler, {Pleroma.Web.Endpoint, []}}]}"
2369
2370 assert json_response(conn, 200) == %{
2371 "configs" => [
2372 %{
2373 "group" => "pleroma",
2374 "key" => "Pleroma.Web.Endpoint.NotReal",
2375 "value" => [
2376 %{
2377 "tuple" => [
2378 ":http",
2379 [
2380 %{"tuple" => [":ip", %{"tuple" => [127, 0, 0, 1]}]},
2381 %{
2382 "tuple" => [
2383 ":dispatch",
2384 [
2385 dispatch_string
2386 ]
2387 ]
2388 }
2389 ]
2390 ]
2391 }
2392 ]
2393 }
2394 ]
2395 }
2396 end
2397
2398 test "queues key as atom", %{conn: conn} do
2399 conn =
2400 post(conn, "/api/pleroma/admin/config", %{
2401 configs: [
2402 %{
2403 "group" => "oban",
2404 "key" => ":queues",
2405 "value" => [
2406 %{"tuple" => [":federator_incoming", 50]},
2407 %{"tuple" => [":federator_outgoing", 50]},
2408 %{"tuple" => [":web_push", 50]},
2409 %{"tuple" => [":mailer", 10]},
2410 %{"tuple" => [":transmogrifier", 20]},
2411 %{"tuple" => [":scheduled_activities", 10]},
2412 %{"tuple" => [":background", 5]}
2413 ]
2414 }
2415 ]
2416 })
2417
2418 assert json_response(conn, 200) == %{
2419 "configs" => [
2420 %{
2421 "group" => "oban",
2422 "key" => ":queues",
2423 "value" => [
2424 %{"tuple" => [":federator_incoming", 50]},
2425 %{"tuple" => [":federator_outgoing", 50]},
2426 %{"tuple" => [":web_push", 50]},
2427 %{"tuple" => [":mailer", 10]},
2428 %{"tuple" => [":transmogrifier", 20]},
2429 %{"tuple" => [":scheduled_activities", 10]},
2430 %{"tuple" => [":background", 5]}
2431 ]
2432 }
2433 ]
2434 }
2435 end
2436
2437 test "delete part of settings by atom subkeys", %{conn: conn} do
2438 config =
2439 insert(:config,
2440 key: "keyaa1",
2441 value: :erlang.term_to_binary(subkey1: "val1", subkey2: "val2", subkey3: "val3")
2442 )
2443
2444 conn =
2445 post(conn, "/api/pleroma/admin/config", %{
2446 configs: [
2447 %{
2448 group: config.group,
2449 key: config.key,
2450 subkeys: [":subkey1", ":subkey3"],
2451 delete: "true"
2452 }
2453 ]
2454 })
2455
2456 assert(
2457 json_response(conn, 200) == %{
2458 "configs" => [
2459 %{
2460 "group" => "pleroma",
2461 "key" => "keyaa1",
2462 "value" => [%{"tuple" => [":subkey2", "val2"]}]
2463 }
2464 ]
2465 }
2466 )
2467 end
2468 end
2469
2470 describe "config mix tasks run" do
2471 setup %{conn: conn} do
2472 admin = insert(:user, is_admin: true)
2473
2474 temp_file = "config/test.exported_from_db.secret.exs"
2475
2476 Mix.shell(Mix.Shell.Quiet)
2477
2478 on_exit(fn ->
2479 Mix.shell(Mix.Shell.IO)
2480 :ok = File.rm(temp_file)
2481 end)
2482
2483 %{conn: assign(conn, :user, admin), admin: admin}
2484 end
2485
2486 clear_config([:instance, :dynamic_configuration]) do
2487 Pleroma.Config.put([:instance, :dynamic_configuration], true)
2488 end
2489
2490 clear_config([:feed, :post_title]) do
2491 Pleroma.Config.put([:feed, :post_title], %{max_length: 100, omission: "…"})
2492 end
2493
2494 test "transfer settings to DB and to file", %{conn: conn, admin: admin} do
2495 assert Pleroma.Repo.all(Pleroma.Web.AdminAPI.Config) == []
2496 conn = get(conn, "/api/pleroma/admin/config/migrate_to_db")
2497 assert json_response(conn, 200) == %{}
2498 assert Pleroma.Repo.all(Pleroma.Web.AdminAPI.Config) > 0
2499
2500 conn =
2501 build_conn()
2502 |> assign(:user, admin)
2503 |> get("/api/pleroma/admin/config/migrate_from_db")
2504
2505 assert json_response(conn, 200) == %{}
2506 assert Pleroma.Repo.all(Pleroma.Web.AdminAPI.Config) == []
2507 end
2508 end
2509
2510 describe "GET /api/pleroma/admin/users/:nickname/statuses" do
2511 setup do
2512 admin = insert(:user, is_admin: true)
2513 user = insert(:user)
2514
2515 date1 = (DateTime.to_unix(DateTime.utc_now()) + 2000) |> DateTime.from_unix!()
2516 date2 = (DateTime.to_unix(DateTime.utc_now()) + 1000) |> DateTime.from_unix!()
2517 date3 = (DateTime.to_unix(DateTime.utc_now()) + 3000) |> DateTime.from_unix!()
2518
2519 insert(:note_activity, user: user, published: date1)
2520 insert(:note_activity, user: user, published: date2)
2521 insert(:note_activity, user: user, published: date3)
2522
2523 conn =
2524 build_conn()
2525 |> assign(:user, admin)
2526
2527 {:ok, conn: conn, user: user}
2528 end
2529
2530 test "renders user's statuses", %{conn: conn, user: user} do
2531 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses")
2532
2533 assert json_response(conn, 200) |> length() == 3
2534 end
2535
2536 test "renders user's statuses with a limit", %{conn: conn, user: user} do
2537 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses?page_size=2")
2538
2539 assert json_response(conn, 200) |> length() == 2
2540 end
2541
2542 test "doesn't return private statuses by default", %{conn: conn, user: user} do
2543 {:ok, _private_status} =
2544 CommonAPI.post(user, %{"status" => "private", "visibility" => "private"})
2545
2546 {:ok, _public_status} =
2547 CommonAPI.post(user, %{"status" => "public", "visibility" => "public"})
2548
2549 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses")
2550
2551 assert json_response(conn, 200) |> length() == 4
2552 end
2553
2554 test "returns private statuses with godmode on", %{conn: conn, user: user} do
2555 {:ok, _private_status} =
2556 CommonAPI.post(user, %{"status" => "private", "visibility" => "private"})
2557
2558 {:ok, _public_status} =
2559 CommonAPI.post(user, %{"status" => "public", "visibility" => "public"})
2560
2561 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses?godmode=true")
2562
2563 assert json_response(conn, 200) |> length() == 5
2564 end
2565 end
2566
2567 describe "GET /api/pleroma/admin/moderation_log" do
2568 setup %{conn: conn} do
2569 admin = insert(:user, is_admin: true)
2570 moderator = insert(:user, is_moderator: true)
2571
2572 %{conn: assign(conn, :user, admin), admin: admin, moderator: moderator}
2573 end
2574
2575 test "returns the log", %{conn: conn, admin: admin} do
2576 Repo.insert(%ModerationLog{
2577 data: %{
2578 actor: %{
2579 "id" => admin.id,
2580 "nickname" => admin.nickname,
2581 "type" => "user"
2582 },
2583 action: "relay_follow",
2584 target: "https://example.org/relay"
2585 },
2586 inserted_at: NaiveDateTime.truncate(~N[2017-08-15 15:47:06.597036], :second)
2587 })
2588
2589 Repo.insert(%ModerationLog{
2590 data: %{
2591 actor: %{
2592 "id" => admin.id,
2593 "nickname" => admin.nickname,
2594 "type" => "user"
2595 },
2596 action: "relay_unfollow",
2597 target: "https://example.org/relay"
2598 },
2599 inserted_at: NaiveDateTime.truncate(~N[2017-08-16 15:47:06.597036], :second)
2600 })
2601
2602 conn = get(conn, "/api/pleroma/admin/moderation_log")
2603
2604 response = json_response(conn, 200)
2605 [first_entry, second_entry] = response["items"]
2606
2607 assert response["total"] == 2
2608 assert first_entry["data"]["action"] == "relay_unfollow"
2609
2610 assert first_entry["message"] ==
2611 "@#{admin.nickname} unfollowed relay: https://example.org/relay"
2612
2613 assert second_entry["data"]["action"] == "relay_follow"
2614
2615 assert second_entry["message"] ==
2616 "@#{admin.nickname} followed relay: https://example.org/relay"
2617 end
2618
2619 test "returns the log with pagination", %{conn: conn, admin: admin} do
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.truncate(~N[2017-08-15 15:47:06.597036], :second)
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.truncate(~N[2017-08-16 15:47:06.597036], :second)
2644 })
2645
2646 conn1 = get(conn, "/api/pleroma/admin/moderation_log?page_size=1&page=1")
2647
2648 response1 = json_response(conn1, 200)
2649 [first_entry] = response1["items"]
2650
2651 assert response1["total"] == 2
2652 assert response1["items"] |> length() == 1
2653 assert first_entry["data"]["action"] == "relay_unfollow"
2654
2655 assert first_entry["message"] ==
2656 "@#{admin.nickname} unfollowed relay: https://example.org/relay"
2657
2658 conn2 = get(conn, "/api/pleroma/admin/moderation_log?page_size=1&page=2")
2659
2660 response2 = json_response(conn2, 200)
2661 [second_entry] = response2["items"]
2662
2663 assert response2["total"] == 2
2664 assert response2["items"] |> length() == 1
2665 assert second_entry["data"]["action"] == "relay_follow"
2666
2667 assert second_entry["message"] ==
2668 "@#{admin.nickname} followed relay: https://example.org/relay"
2669 end
2670
2671 test "filters log by date", %{conn: conn, admin: admin} do
2672 first_date = "2017-08-15T15:47:06Z"
2673 second_date = "2017-08-20T15:47:06Z"
2674
2675 Repo.insert(%ModerationLog{
2676 data: %{
2677 actor: %{
2678 "id" => admin.id,
2679 "nickname" => admin.nickname,
2680 "type" => "user"
2681 },
2682 action: "relay_follow",
2683 target: "https://example.org/relay"
2684 },
2685 inserted_at: NaiveDateTime.from_iso8601!(first_date)
2686 })
2687
2688 Repo.insert(%ModerationLog{
2689 data: %{
2690 actor: %{
2691 "id" => admin.id,
2692 "nickname" => admin.nickname,
2693 "type" => "user"
2694 },
2695 action: "relay_unfollow",
2696 target: "https://example.org/relay"
2697 },
2698 inserted_at: NaiveDateTime.from_iso8601!(second_date)
2699 })
2700
2701 conn1 =
2702 get(
2703 conn,
2704 "/api/pleroma/admin/moderation_log?start_date=#{second_date}"
2705 )
2706
2707 response1 = json_response(conn1, 200)
2708 [first_entry] = response1["items"]
2709
2710 assert response1["total"] == 1
2711 assert first_entry["data"]["action"] == "relay_unfollow"
2712
2713 assert first_entry["message"] ==
2714 "@#{admin.nickname} unfollowed relay: https://example.org/relay"
2715 end
2716
2717 test "returns log filtered by user", %{conn: conn, admin: admin, moderator: moderator} do
2718 Repo.insert(%ModerationLog{
2719 data: %{
2720 actor: %{
2721 "id" => admin.id,
2722 "nickname" => admin.nickname,
2723 "type" => "user"
2724 },
2725 action: "relay_follow",
2726 target: "https://example.org/relay"
2727 }
2728 })
2729
2730 Repo.insert(%ModerationLog{
2731 data: %{
2732 actor: %{
2733 "id" => moderator.id,
2734 "nickname" => moderator.nickname,
2735 "type" => "user"
2736 },
2737 action: "relay_unfollow",
2738 target: "https://example.org/relay"
2739 }
2740 })
2741
2742 conn1 = get(conn, "/api/pleroma/admin/moderation_log?user_id=#{moderator.id}")
2743
2744 response1 = json_response(conn1, 200)
2745 [first_entry] = response1["items"]
2746
2747 assert response1["total"] == 1
2748 assert get_in(first_entry, ["data", "actor", "id"]) == moderator.id
2749 end
2750
2751 test "returns log filtered by search", %{conn: conn, moderator: moderator} do
2752 ModerationLog.insert_log(%{
2753 actor: moderator,
2754 action: "relay_follow",
2755 target: "https://example.org/relay"
2756 })
2757
2758 ModerationLog.insert_log(%{
2759 actor: moderator,
2760 action: "relay_unfollow",
2761 target: "https://example.org/relay"
2762 })
2763
2764 conn1 = get(conn, "/api/pleroma/admin/moderation_log?search=unfo")
2765
2766 response1 = json_response(conn1, 200)
2767 [first_entry] = response1["items"]
2768
2769 assert response1["total"] == 1
2770
2771 assert get_in(first_entry, ["data", "message"]) ==
2772 "@#{moderator.nickname} unfollowed relay: https://example.org/relay"
2773 end
2774 end
2775
2776 describe "PATCH /users/:nickname/force_password_reset" do
2777 setup %{conn: conn} do
2778 admin = insert(:user, is_admin: true)
2779 user = insert(:user)
2780
2781 %{conn: assign(conn, :user, admin), admin: admin, user: user}
2782 end
2783
2784 test "sets password_reset_pending to true", %{admin: admin, user: user} do
2785 assert user.password_reset_pending == false
2786
2787 conn =
2788 build_conn()
2789 |> assign(:user, admin)
2790 |> patch("/api/pleroma/admin/users/force_password_reset", %{nicknames: [user.nickname]})
2791
2792 assert json_response(conn, 204) == ""
2793
2794 ObanHelpers.perform_all()
2795
2796 assert User.get_by_id(user.id).password_reset_pending == true
2797 end
2798 end
2799
2800 describe "relays" do
2801 setup %{conn: conn} do
2802 admin = insert(:user, is_admin: true)
2803
2804 %{conn: assign(conn, :user, admin), admin: admin}
2805 end
2806
2807 test "POST /relay", %{admin: admin} do
2808 conn =
2809 build_conn()
2810 |> assign(:user, admin)
2811 |> post("/api/pleroma/admin/relay", %{
2812 relay_url: "http://mastodon.example.org/users/admin"
2813 })
2814
2815 assert json_response(conn, 200) == "http://mastodon.example.org/users/admin"
2816
2817 log_entry = Repo.one(ModerationLog)
2818
2819 assert ModerationLog.get_log_entry_message(log_entry) ==
2820 "@#{admin.nickname} followed relay: http://mastodon.example.org/users/admin"
2821 end
2822
2823 test "GET /relay", %{admin: admin} do
2824 relay_user = Pleroma.Web.ActivityPub.Relay.get_actor()
2825
2826 ["http://mastodon.example.org/users/admin", "https://mstdn.io/users/mayuutann"]
2827 |> Enum.each(fn ap_id ->
2828 {:ok, user} = User.get_or_fetch_by_ap_id(ap_id)
2829 User.follow(relay_user, user)
2830 end)
2831
2832 conn =
2833 build_conn()
2834 |> assign(:user, admin)
2835 |> get("/api/pleroma/admin/relay")
2836
2837 assert json_response(conn, 200)["relays"] -- ["mastodon.example.org", "mstdn.io"] == []
2838 end
2839
2840 test "DELETE /relay", %{admin: admin} do
2841 build_conn()
2842 |> assign(:user, admin)
2843 |> post("/api/pleroma/admin/relay", %{
2844 relay_url: "http://mastodon.example.org/users/admin"
2845 })
2846
2847 conn =
2848 build_conn()
2849 |> assign(:user, admin)
2850 |> delete("/api/pleroma/admin/relay", %{
2851 relay_url: "http://mastodon.example.org/users/admin"
2852 })
2853
2854 assert json_response(conn, 200) == "http://mastodon.example.org/users/admin"
2855
2856 [log_entry_one, log_entry_two] = Repo.all(ModerationLog)
2857
2858 assert ModerationLog.get_log_entry_message(log_entry_one) ==
2859 "@#{admin.nickname} followed relay: http://mastodon.example.org/users/admin"
2860
2861 assert ModerationLog.get_log_entry_message(log_entry_two) ==
2862 "@#{admin.nickname} unfollowed relay: http://mastodon.example.org/users/admin"
2863 end
2864 end
2865
2866 describe "instances" do
2867 test "GET /instances/:instance/statuses" do
2868 admin = insert(:user, is_admin: true)
2869 user = insert(:user, local: false, nickname: "archaeme@archae.me")
2870 user2 = insert(:user, local: false, nickname: "test@test.com")
2871 insert_pair(:note_activity, user: user)
2872 insert(:note_activity, user: user2)
2873
2874 conn =
2875 build_conn()
2876 |> assign(:user, admin)
2877 |> get("/api/pleroma/admin/instances/archae.me/statuses")
2878
2879 response = json_response(conn, 200)
2880
2881 assert length(response) == 2
2882
2883 conn =
2884 build_conn()
2885 |> assign(:user, admin)
2886 |> get("/api/pleroma/admin/instances/test.com/statuses")
2887
2888 response = json_response(conn, 200)
2889
2890 assert length(response) == 1
2891
2892 conn =
2893 build_conn()
2894 |> assign(:user, admin)
2895 |> get("/api/pleroma/admin/instances/nonexistent.com/statuses")
2896
2897 response = json_response(conn, 200)
2898
2899 assert length(response) == 0
2900 end
2901 end
2902
2903 describe "PATCH /confirm_email" do
2904 setup %{conn: conn} do
2905 admin = insert(:user, is_admin: true)
2906
2907 %{conn: assign(conn, :user, admin), admin: admin}
2908 end
2909
2910 test "it confirms emails of two users", %{admin: admin} do
2911 [first_user, second_user] = insert_pair(:user, confirmation_pending: true)
2912
2913 assert first_user.confirmation_pending == true
2914 assert second_user.confirmation_pending == true
2915
2916 build_conn()
2917 |> assign(:user, admin)
2918 |> patch("/api/pleroma/admin/users/confirm_email", %{
2919 nicknames: [
2920 first_user.nickname,
2921 second_user.nickname
2922 ]
2923 })
2924
2925 assert first_user.confirmation_pending == true
2926 assert second_user.confirmation_pending == true
2927
2928 log_entry = Repo.one(ModerationLog)
2929
2930 assert ModerationLog.get_log_entry_message(log_entry) ==
2931 "@#{admin.nickname} confirmed email for users: @#{first_user.nickname}, @#{
2932 second_user.nickname
2933 }"
2934 end
2935 end
2936
2937 describe "PATCH /resend_confirmation_email" do
2938 setup %{conn: conn} do
2939 admin = insert(:user, is_admin: true)
2940
2941 %{conn: assign(conn, :user, admin), admin: admin}
2942 end
2943
2944 test "it resend emails for two users", %{admin: admin} do
2945 [first_user, second_user] = insert_pair(:user, confirmation_pending: true)
2946
2947 build_conn()
2948 |> assign(:user, admin)
2949 |> patch("/api/pleroma/admin/users/resend_confirmation_email", %{
2950 nicknames: [
2951 first_user.nickname,
2952 second_user.nickname
2953 ]
2954 })
2955
2956 log_entry = Repo.one(ModerationLog)
2957
2958 assert ModerationLog.get_log_entry_message(log_entry) ==
2959 "@#{admin.nickname} re-sent confirmation email for users: @#{first_user.nickname}, @#{
2960 second_user.nickname
2961 }"
2962 end
2963 end
2964 end
2965
2966 # Needed for testing
2967 defmodule Pleroma.Web.Endpoint.NotReal do
2968 end
2969
2970 defmodule Pleroma.Captcha.NotReal do
2971 end