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