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