ea1b4c48cc098344fe273e4a097062997847f156
[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 }
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 },
640 %{
641 "deactivated" => user.deactivated,
642 "id" => user.id,
643 "nickname" => user.nickname,
644 "roles" => %{"admin" => false, "moderator" => false},
645 "local" => false,
646 "tags" => ["foo", "bar"],
647 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
648 "display_name" => HTML.strip_tags(user.name || user.nickname)
649 }
650 ]
651 |> Enum.sort_by(& &1["nickname"])
652
653 assert json_response(conn, 200) == %{
654 "count" => 2,
655 "page_size" => 50,
656 "users" => users
657 }
658 end
659
660 test "renders empty array for the second page", %{conn: conn} do
661 insert(:user)
662
663 conn = get(conn, "/api/pleroma/admin/users?page=2")
664
665 assert json_response(conn, 200) == %{
666 "count" => 2,
667 "page_size" => 50,
668 "users" => []
669 }
670 end
671
672 test "regular search", %{conn: conn} do
673 user = insert(:user, nickname: "bob")
674
675 conn = get(conn, "/api/pleroma/admin/users?query=bo")
676
677 assert json_response(conn, 200) == %{
678 "count" => 1,
679 "page_size" => 50,
680 "users" => [
681 %{
682 "deactivated" => user.deactivated,
683 "id" => user.id,
684 "nickname" => user.nickname,
685 "roles" => %{"admin" => false, "moderator" => false},
686 "local" => true,
687 "tags" => [],
688 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
689 "display_name" => HTML.strip_tags(user.name || user.nickname)
690 }
691 ]
692 }
693 end
694
695 test "search by domain", %{conn: conn} do
696 user = insert(:user, nickname: "nickname@domain.com")
697 insert(:user)
698
699 conn = get(conn, "/api/pleroma/admin/users?query=domain.com")
700
701 assert json_response(conn, 200) == %{
702 "count" => 1,
703 "page_size" => 50,
704 "users" => [
705 %{
706 "deactivated" => user.deactivated,
707 "id" => user.id,
708 "nickname" => user.nickname,
709 "roles" => %{"admin" => false, "moderator" => false},
710 "local" => true,
711 "tags" => [],
712 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
713 "display_name" => HTML.strip_tags(user.name || user.nickname)
714 }
715 ]
716 }
717 end
718
719 test "search by full nickname", %{conn: conn} do
720 user = insert(:user, nickname: "nickname@domain.com")
721 insert(:user)
722
723 conn = get(conn, "/api/pleroma/admin/users?query=nickname@domain.com")
724
725 assert json_response(conn, 200) == %{
726 "count" => 1,
727 "page_size" => 50,
728 "users" => [
729 %{
730 "deactivated" => user.deactivated,
731 "id" => user.id,
732 "nickname" => user.nickname,
733 "roles" => %{"admin" => false, "moderator" => false},
734 "local" => true,
735 "tags" => [],
736 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
737 "display_name" => HTML.strip_tags(user.name || user.nickname)
738 }
739 ]
740 }
741 end
742
743 test "search by display name", %{conn: conn} do
744 user = insert(:user, name: "Display name")
745 insert(:user)
746
747 conn = get(conn, "/api/pleroma/admin/users?name=display")
748
749 assert json_response(conn, 200) == %{
750 "count" => 1,
751 "page_size" => 50,
752 "users" => [
753 %{
754 "deactivated" => user.deactivated,
755 "id" => user.id,
756 "nickname" => user.nickname,
757 "roles" => %{"admin" => false, "moderator" => false},
758 "local" => true,
759 "tags" => [],
760 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
761 "display_name" => HTML.strip_tags(user.name || user.nickname)
762 }
763 ]
764 }
765 end
766
767 test "search by email", %{conn: conn} do
768 user = insert(:user, email: "email@example.com")
769 insert(:user)
770
771 conn = get(conn, "/api/pleroma/admin/users?email=email@example.com")
772
773 assert json_response(conn, 200) == %{
774 "count" => 1,
775 "page_size" => 50,
776 "users" => [
777 %{
778 "deactivated" => user.deactivated,
779 "id" => user.id,
780 "nickname" => user.nickname,
781 "roles" => %{"admin" => false, "moderator" => false},
782 "local" => true,
783 "tags" => [],
784 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
785 "display_name" => HTML.strip_tags(user.name || user.nickname)
786 }
787 ]
788 }
789 end
790
791 test "regular search with page size", %{conn: conn} do
792 user = insert(:user, nickname: "aalice")
793 user2 = insert(:user, nickname: "alice")
794
795 conn1 = get(conn, "/api/pleroma/admin/users?query=a&page_size=1&page=1")
796
797 assert json_response(conn1, 200) == %{
798 "count" => 2,
799 "page_size" => 1,
800 "users" => [
801 %{
802 "deactivated" => user.deactivated,
803 "id" => user.id,
804 "nickname" => user.nickname,
805 "roles" => %{"admin" => false, "moderator" => false},
806 "local" => true,
807 "tags" => [],
808 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
809 "display_name" => HTML.strip_tags(user.name || user.nickname)
810 }
811 ]
812 }
813
814 conn2 = get(conn, "/api/pleroma/admin/users?query=a&page_size=1&page=2")
815
816 assert json_response(conn2, 200) == %{
817 "count" => 2,
818 "page_size" => 1,
819 "users" => [
820 %{
821 "deactivated" => user2.deactivated,
822 "id" => user2.id,
823 "nickname" => user2.nickname,
824 "roles" => %{"admin" => false, "moderator" => false},
825 "local" => true,
826 "tags" => [],
827 "avatar" => User.avatar_url(user2) |> MediaProxy.url(),
828 "display_name" => HTML.strip_tags(user2.name || user2.nickname)
829 }
830 ]
831 }
832 end
833
834 test "only local users" do
835 admin = insert(:user, is_admin: true, nickname: "john")
836 user = insert(:user, nickname: "bob")
837
838 insert(:user, nickname: "bobb", local: false)
839
840 conn =
841 build_conn()
842 |> assign(:user, admin)
843 |> get("/api/pleroma/admin/users?query=bo&filters=local")
844
845 assert json_response(conn, 200) == %{
846 "count" => 1,
847 "page_size" => 50,
848 "users" => [
849 %{
850 "deactivated" => user.deactivated,
851 "id" => user.id,
852 "nickname" => user.nickname,
853 "roles" => %{"admin" => false, "moderator" => false},
854 "local" => true,
855 "tags" => [],
856 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
857 "display_name" => HTML.strip_tags(user.name || user.nickname)
858 }
859 ]
860 }
861 end
862
863 test "only local users with no query", %{admin: old_admin} do
864 admin = insert(:user, is_admin: true, nickname: "john")
865 user = insert(:user, nickname: "bob")
866
867 insert(:user, nickname: "bobb", local: false)
868
869 conn =
870 build_conn()
871 |> assign(:user, admin)
872 |> get("/api/pleroma/admin/users?filters=local")
873
874 users =
875 [
876 %{
877 "deactivated" => user.deactivated,
878 "id" => user.id,
879 "nickname" => user.nickname,
880 "roles" => %{"admin" => false, "moderator" => false},
881 "local" => true,
882 "tags" => [],
883 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
884 "display_name" => HTML.strip_tags(user.name || user.nickname)
885 },
886 %{
887 "deactivated" => admin.deactivated,
888 "id" => admin.id,
889 "nickname" => admin.nickname,
890 "roles" => %{"admin" => true, "moderator" => false},
891 "local" => true,
892 "tags" => [],
893 "avatar" => User.avatar_url(admin) |> MediaProxy.url(),
894 "display_name" => HTML.strip_tags(admin.name || admin.nickname)
895 },
896 %{
897 "deactivated" => false,
898 "id" => old_admin.id,
899 "local" => true,
900 "nickname" => old_admin.nickname,
901 "roles" => %{"admin" => true, "moderator" => false},
902 "tags" => [],
903 "avatar" => User.avatar_url(old_admin) |> MediaProxy.url(),
904 "display_name" => HTML.strip_tags(old_admin.name || old_admin.nickname)
905 }
906 ]
907 |> Enum.sort_by(& &1["nickname"])
908
909 assert json_response(conn, 200) == %{
910 "count" => 3,
911 "page_size" => 50,
912 "users" => users
913 }
914 end
915
916 test "load only admins", %{conn: conn, admin: admin} do
917 second_admin = insert(:user, is_admin: true)
918 insert(:user)
919 insert(:user)
920
921 conn = get(conn, "/api/pleroma/admin/users?filters=is_admin")
922
923 users =
924 [
925 %{
926 "deactivated" => false,
927 "id" => admin.id,
928 "nickname" => admin.nickname,
929 "roles" => %{"admin" => true, "moderator" => false},
930 "local" => admin.local,
931 "tags" => [],
932 "avatar" => User.avatar_url(admin) |> MediaProxy.url(),
933 "display_name" => HTML.strip_tags(admin.name || admin.nickname)
934 },
935 %{
936 "deactivated" => false,
937 "id" => second_admin.id,
938 "nickname" => second_admin.nickname,
939 "roles" => %{"admin" => true, "moderator" => false},
940 "local" => second_admin.local,
941 "tags" => [],
942 "avatar" => User.avatar_url(second_admin) |> MediaProxy.url(),
943 "display_name" => HTML.strip_tags(second_admin.name || second_admin.nickname)
944 }
945 ]
946 |> Enum.sort_by(& &1["nickname"])
947
948 assert json_response(conn, 200) == %{
949 "count" => 2,
950 "page_size" => 50,
951 "users" => users
952 }
953 end
954
955 test "load only moderators", %{conn: conn} do
956 moderator = insert(:user, is_moderator: true)
957 insert(:user)
958 insert(:user)
959
960 conn = get(conn, "/api/pleroma/admin/users?filters=is_moderator")
961
962 assert json_response(conn, 200) == %{
963 "count" => 1,
964 "page_size" => 50,
965 "users" => [
966 %{
967 "deactivated" => false,
968 "id" => moderator.id,
969 "nickname" => moderator.nickname,
970 "roles" => %{"admin" => false, "moderator" => true},
971 "local" => moderator.local,
972 "tags" => [],
973 "avatar" => User.avatar_url(moderator) |> MediaProxy.url(),
974 "display_name" => HTML.strip_tags(moderator.name || moderator.nickname)
975 }
976 ]
977 }
978 end
979
980 test "load users with tags list", %{conn: conn} do
981 user1 = insert(:user, tags: ["first"])
982 user2 = insert(:user, tags: ["second"])
983 insert(:user)
984 insert(:user)
985
986 conn = get(conn, "/api/pleroma/admin/users?tags[]=first&tags[]=second")
987
988 users =
989 [
990 %{
991 "deactivated" => false,
992 "id" => user1.id,
993 "nickname" => user1.nickname,
994 "roles" => %{"admin" => false, "moderator" => false},
995 "local" => user1.local,
996 "tags" => ["first"],
997 "avatar" => User.avatar_url(user1) |> MediaProxy.url(),
998 "display_name" => HTML.strip_tags(user1.name || user1.nickname)
999 },
1000 %{
1001 "deactivated" => false,
1002 "id" => user2.id,
1003 "nickname" => user2.nickname,
1004 "roles" => %{"admin" => false, "moderator" => false},
1005 "local" => user2.local,
1006 "tags" => ["second"],
1007 "avatar" => User.avatar_url(user2) |> MediaProxy.url(),
1008 "display_name" => HTML.strip_tags(user2.name || user2.nickname)
1009 }
1010 ]
1011 |> Enum.sort_by(& &1["nickname"])
1012
1013 assert json_response(conn, 200) == %{
1014 "count" => 2,
1015 "page_size" => 50,
1016 "users" => users
1017 }
1018 end
1019
1020 test "it works with multiple filters" do
1021 admin = insert(:user, nickname: "john", is_admin: true)
1022 user = insert(:user, nickname: "bob", local: false, deactivated: true)
1023
1024 insert(:user, nickname: "ken", local: true, deactivated: true)
1025 insert(:user, nickname: "bobb", local: false, deactivated: false)
1026
1027 conn =
1028 build_conn()
1029 |> assign(:user, admin)
1030 |> get("/api/pleroma/admin/users?filters=deactivated,external")
1031
1032 assert json_response(conn, 200) == %{
1033 "count" => 1,
1034 "page_size" => 50,
1035 "users" => [
1036 %{
1037 "deactivated" => user.deactivated,
1038 "id" => user.id,
1039 "nickname" => user.nickname,
1040 "roles" => %{"admin" => false, "moderator" => false},
1041 "local" => user.local,
1042 "tags" => [],
1043 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
1044 "display_name" => HTML.strip_tags(user.name || user.nickname)
1045 }
1046 ]
1047 }
1048 end
1049
1050 test "it omits relay user", %{admin: admin} do
1051 assert %User{} = Relay.get_actor()
1052
1053 conn =
1054 build_conn()
1055 |> assign(:user, admin)
1056 |> get("/api/pleroma/admin/users")
1057
1058 assert json_response(conn, 200) == %{
1059 "count" => 1,
1060 "page_size" => 50,
1061 "users" => [
1062 %{
1063 "deactivated" => admin.deactivated,
1064 "id" => admin.id,
1065 "nickname" => admin.nickname,
1066 "roles" => %{"admin" => true, "moderator" => false},
1067 "local" => true,
1068 "tags" => [],
1069 "avatar" => User.avatar_url(admin) |> MediaProxy.url(),
1070 "display_name" => HTML.strip_tags(admin.name || admin.nickname)
1071 }
1072 ]
1073 }
1074 end
1075 end
1076
1077 test "PATCH /api/pleroma/admin/users/activate" do
1078 admin = insert(:user, is_admin: true)
1079 user_one = insert(:user, deactivated: true)
1080 user_two = insert(:user, deactivated: true)
1081
1082 conn =
1083 build_conn()
1084 |> assign(:user, admin)
1085 |> patch(
1086 "/api/pleroma/admin/users/activate",
1087 %{nicknames: [user_one.nickname, user_two.nickname]}
1088 )
1089
1090 response = json_response(conn, 200)
1091 assert Enum.map(response["users"], & &1["deactivated"]) == [false, false]
1092
1093 log_entry = Repo.one(ModerationLog)
1094
1095 assert ModerationLog.get_log_entry_message(log_entry) ==
1096 "@#{admin.nickname} activated users: @#{user_one.nickname}, @#{user_two.nickname}"
1097 end
1098
1099 test "PATCH /api/pleroma/admin/users/deactivate" do
1100 admin = insert(:user, is_admin: true)
1101 user_one = insert(:user, deactivated: false)
1102 user_two = insert(:user, deactivated: false)
1103
1104 conn =
1105 build_conn()
1106 |> assign(:user, admin)
1107 |> patch(
1108 "/api/pleroma/admin/users/deactivate",
1109 %{nicknames: [user_one.nickname, user_two.nickname]}
1110 )
1111
1112 response = json_response(conn, 200)
1113 assert Enum.map(response["users"], & &1["deactivated"]) == [true, true]
1114
1115 log_entry = Repo.one(ModerationLog)
1116
1117 assert ModerationLog.get_log_entry_message(log_entry) ==
1118 "@#{admin.nickname} deactivated users: @#{user_one.nickname}, @#{user_two.nickname}"
1119 end
1120
1121 test "PATCH /api/pleroma/admin/users/:nickname/toggle_activation" do
1122 admin = insert(:user, is_admin: true)
1123 user = insert(:user)
1124
1125 conn =
1126 build_conn()
1127 |> assign(:user, admin)
1128 |> patch("/api/pleroma/admin/users/#{user.nickname}/toggle_activation")
1129
1130 assert json_response(conn, 200) ==
1131 %{
1132 "deactivated" => !user.deactivated,
1133 "id" => user.id,
1134 "nickname" => user.nickname,
1135 "roles" => %{"admin" => false, "moderator" => false},
1136 "local" => true,
1137 "tags" => [],
1138 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
1139 "display_name" => HTML.strip_tags(user.name || user.nickname)
1140 }
1141
1142 log_entry = Repo.one(ModerationLog)
1143
1144 assert ModerationLog.get_log_entry_message(log_entry) ==
1145 "@#{admin.nickname} deactivated users: @#{user.nickname}"
1146 end
1147
1148 describe "POST /api/pleroma/admin/users/invite_token" do
1149 setup do
1150 admin = insert(:user, is_admin: true)
1151
1152 conn =
1153 build_conn()
1154 |> assign(:user, admin)
1155
1156 {:ok, conn: conn}
1157 end
1158
1159 test "without options", %{conn: conn} do
1160 conn = post(conn, "/api/pleroma/admin/users/invite_token")
1161
1162 invite_json = json_response(conn, 200)
1163 invite = UserInviteToken.find_by_token!(invite_json["token"])
1164 refute invite.used
1165 refute invite.expires_at
1166 refute invite.max_use
1167 assert invite.invite_type == "one_time"
1168 end
1169
1170 test "with expires_at", %{conn: conn} do
1171 conn =
1172 post(conn, "/api/pleroma/admin/users/invite_token", %{
1173 "expires_at" => Date.to_string(Date.utc_today())
1174 })
1175
1176 invite_json = json_response(conn, 200)
1177 invite = UserInviteToken.find_by_token!(invite_json["token"])
1178
1179 refute invite.used
1180 assert invite.expires_at == Date.utc_today()
1181 refute invite.max_use
1182 assert invite.invite_type == "date_limited"
1183 end
1184
1185 test "with max_use", %{conn: conn} do
1186 conn = post(conn, "/api/pleroma/admin/users/invite_token", %{"max_use" => 150})
1187
1188 invite_json = json_response(conn, 200)
1189 invite = UserInviteToken.find_by_token!(invite_json["token"])
1190 refute invite.used
1191 refute invite.expires_at
1192 assert invite.max_use == 150
1193 assert invite.invite_type == "reusable"
1194 end
1195
1196 test "with max use and expires_at", %{conn: conn} do
1197 conn =
1198 post(conn, "/api/pleroma/admin/users/invite_token", %{
1199 "max_use" => 150,
1200 "expires_at" => Date.to_string(Date.utc_today())
1201 })
1202
1203 invite_json = json_response(conn, 200)
1204 invite = UserInviteToken.find_by_token!(invite_json["token"])
1205 refute invite.used
1206 assert invite.expires_at == Date.utc_today()
1207 assert invite.max_use == 150
1208 assert invite.invite_type == "reusable_date_limited"
1209 end
1210 end
1211
1212 describe "GET /api/pleroma/admin/users/invites" do
1213 setup do
1214 admin = insert(:user, is_admin: true)
1215
1216 conn =
1217 build_conn()
1218 |> assign(:user, admin)
1219
1220 {:ok, conn: conn}
1221 end
1222
1223 test "no invites", %{conn: conn} do
1224 conn = get(conn, "/api/pleroma/admin/users/invites")
1225
1226 assert json_response(conn, 200) == %{"invites" => []}
1227 end
1228
1229 test "with invite", %{conn: conn} do
1230 {:ok, invite} = UserInviteToken.create_invite()
1231
1232 conn = get(conn, "/api/pleroma/admin/users/invites")
1233
1234 assert json_response(conn, 200) == %{
1235 "invites" => [
1236 %{
1237 "expires_at" => nil,
1238 "id" => invite.id,
1239 "invite_type" => "one_time",
1240 "max_use" => nil,
1241 "token" => invite.token,
1242 "used" => false,
1243 "uses" => 0
1244 }
1245 ]
1246 }
1247 end
1248 end
1249
1250 describe "POST /api/pleroma/admin/users/revoke_invite" do
1251 test "with token" do
1252 admin = insert(:user, is_admin: true)
1253 {:ok, invite} = UserInviteToken.create_invite()
1254
1255 conn =
1256 build_conn()
1257 |> assign(:user, admin)
1258 |> post("/api/pleroma/admin/users/revoke_invite", %{"token" => invite.token})
1259
1260 assert json_response(conn, 200) == %{
1261 "expires_at" => nil,
1262 "id" => invite.id,
1263 "invite_type" => "one_time",
1264 "max_use" => nil,
1265 "token" => invite.token,
1266 "used" => true,
1267 "uses" => 0
1268 }
1269 end
1270
1271 test "with invalid token" do
1272 admin = insert(:user, is_admin: true)
1273
1274 conn =
1275 build_conn()
1276 |> assign(:user, admin)
1277 |> post("/api/pleroma/admin/users/revoke_invite", %{"token" => "foo"})
1278
1279 assert json_response(conn, :not_found) == "Not found"
1280 end
1281 end
1282
1283 describe "GET /api/pleroma/admin/reports/:id" do
1284 setup %{conn: conn} do
1285 admin = insert(:user, is_admin: true)
1286
1287 %{conn: assign(conn, :user, admin)}
1288 end
1289
1290 test "returns report by its id", %{conn: conn} do
1291 [reporter, target_user] = insert_pair(:user)
1292 activity = insert(:note_activity, user: target_user)
1293
1294 {:ok, %{id: report_id}} =
1295 CommonAPI.report(reporter, %{
1296 "account_id" => target_user.id,
1297 "comment" => "I feel offended",
1298 "status_ids" => [activity.id]
1299 })
1300
1301 response =
1302 conn
1303 |> get("/api/pleroma/admin/reports/#{report_id}")
1304 |> json_response(:ok)
1305
1306 assert response["id"] == report_id
1307 end
1308
1309 test "returns 404 when report id is invalid", %{conn: conn} do
1310 conn = get(conn, "/api/pleroma/admin/reports/test")
1311
1312 assert json_response(conn, :not_found) == "Not found"
1313 end
1314 end
1315
1316 describe "PATCH /api/pleroma/admin/reports" do
1317 setup %{conn: conn} do
1318 admin = insert(:user, is_admin: true)
1319 [reporter, target_user] = insert_pair(:user)
1320 activity = insert(:note_activity, user: target_user)
1321
1322 {:ok, %{id: report_id}} =
1323 CommonAPI.report(reporter, %{
1324 "account_id" => target_user.id,
1325 "comment" => "I feel offended",
1326 "status_ids" => [activity.id]
1327 })
1328
1329 {:ok, %{id: second_report_id}} =
1330 CommonAPI.report(reporter, %{
1331 "account_id" => target_user.id,
1332 "comment" => "I feel very offended",
1333 "status_ids" => [activity.id]
1334 })
1335
1336 %{
1337 conn: assign(conn, :user, admin),
1338 id: report_id,
1339 admin: admin,
1340 second_report_id: second_report_id
1341 }
1342 end
1343
1344 test "mark report as resolved", %{conn: conn, id: id, admin: admin} do
1345 conn
1346 |> patch("/api/pleroma/admin/reports", %{
1347 "reports" => [
1348 %{"state" => "resolved", "id" => id}
1349 ]
1350 })
1351 |> json_response(:no_content)
1352
1353 activity = Activity.get_by_id(id)
1354 assert activity.data["state"] == "resolved"
1355
1356 log_entry = Repo.one(ModerationLog)
1357
1358 assert ModerationLog.get_log_entry_message(log_entry) ==
1359 "@#{admin.nickname} updated report ##{id} with 'resolved' state"
1360 end
1361
1362 test "closes report", %{conn: conn, id: id, admin: admin} do
1363 conn
1364 |> patch("/api/pleroma/admin/reports", %{
1365 "reports" => [
1366 %{"state" => "closed", "id" => id}
1367 ]
1368 })
1369 |> json_response(:no_content)
1370
1371 activity = Activity.get_by_id(id)
1372 assert activity.data["state"] == "closed"
1373
1374 log_entry = Repo.one(ModerationLog)
1375
1376 assert ModerationLog.get_log_entry_message(log_entry) ==
1377 "@#{admin.nickname} updated report ##{id} with 'closed' state"
1378 end
1379
1380 test "returns 400 when state is unknown", %{conn: conn, id: id} do
1381 conn =
1382 conn
1383 |> patch("/api/pleroma/admin/reports", %{
1384 "reports" => [
1385 %{"state" => "test", "id" => id}
1386 ]
1387 })
1388
1389 assert hd(json_response(conn, :bad_request))["error"] == "Unsupported state"
1390 end
1391
1392 test "returns 404 when report is not exist", %{conn: conn} do
1393 conn =
1394 conn
1395 |> patch("/api/pleroma/admin/reports", %{
1396 "reports" => [
1397 %{"state" => "closed", "id" => "test"}
1398 ]
1399 })
1400
1401 assert hd(json_response(conn, :bad_request))["error"] == "not_found"
1402 end
1403
1404 test "updates state of multiple reports", %{
1405 conn: conn,
1406 id: id,
1407 admin: admin,
1408 second_report_id: second_report_id
1409 } do
1410 conn
1411 |> patch("/api/pleroma/admin/reports", %{
1412 "reports" => [
1413 %{"state" => "resolved", "id" => id},
1414 %{"state" => "closed", "id" => second_report_id}
1415 ]
1416 })
1417 |> json_response(:no_content)
1418
1419 activity = Activity.get_by_id(id)
1420 second_activity = Activity.get_by_id(second_report_id)
1421 assert activity.data["state"] == "resolved"
1422 assert second_activity.data["state"] == "closed"
1423
1424 [first_log_entry, second_log_entry] = Repo.all(ModerationLog)
1425
1426 assert ModerationLog.get_log_entry_message(first_log_entry) ==
1427 "@#{admin.nickname} updated report ##{id} with 'resolved' state"
1428
1429 assert ModerationLog.get_log_entry_message(second_log_entry) ==
1430 "@#{admin.nickname} updated report ##{second_report_id} with 'closed' state"
1431 end
1432 end
1433
1434 describe "GET /api/pleroma/admin/reports" do
1435 setup %{conn: conn} do
1436 admin = insert(:user, is_admin: true)
1437
1438 %{conn: assign(conn, :user, admin)}
1439 end
1440
1441 test "returns empty response when no reports created", %{conn: conn} do
1442 response =
1443 conn
1444 |> get("/api/pleroma/admin/reports")
1445 |> json_response(:ok)
1446
1447 assert Enum.empty?(response["reports"])
1448 assert response["total"] == 0
1449 end
1450
1451 test "returns reports", %{conn: conn} do
1452 [reporter, target_user] = insert_pair(:user)
1453 activity = insert(:note_activity, user: target_user)
1454
1455 {:ok, %{id: report_id}} =
1456 CommonAPI.report(reporter, %{
1457 "account_id" => target_user.id,
1458 "comment" => "I feel offended",
1459 "status_ids" => [activity.id]
1460 })
1461
1462 response =
1463 conn
1464 |> get("/api/pleroma/admin/reports")
1465 |> json_response(:ok)
1466
1467 [report] = response["reports"]
1468
1469 assert length(response["reports"]) == 1
1470 assert report["id"] == report_id
1471
1472 assert response["total"] == 1
1473 end
1474
1475 test "returns reports with specified state", %{conn: conn} do
1476 [reporter, target_user] = insert_pair(:user)
1477 activity = insert(:note_activity, user: target_user)
1478
1479 {:ok, %{id: first_report_id}} =
1480 CommonAPI.report(reporter, %{
1481 "account_id" => target_user.id,
1482 "comment" => "I feel offended",
1483 "status_ids" => [activity.id]
1484 })
1485
1486 {:ok, %{id: second_report_id}} =
1487 CommonAPI.report(reporter, %{
1488 "account_id" => target_user.id,
1489 "comment" => "I don't like this user"
1490 })
1491
1492 CommonAPI.update_report_state(second_report_id, "closed")
1493
1494 response =
1495 conn
1496 |> get("/api/pleroma/admin/reports", %{
1497 "state" => "open"
1498 })
1499 |> json_response(:ok)
1500
1501 [open_report] = response["reports"]
1502
1503 assert length(response["reports"]) == 1
1504 assert open_report["id"] == first_report_id
1505
1506 assert response["total"] == 1
1507
1508 response =
1509 conn
1510 |> get("/api/pleroma/admin/reports", %{
1511 "state" => "closed"
1512 })
1513 |> json_response(:ok)
1514
1515 [closed_report] = response["reports"]
1516
1517 assert length(response["reports"]) == 1
1518 assert closed_report["id"] == second_report_id
1519
1520 assert response["total"] == 1
1521
1522 response =
1523 conn
1524 |> get("/api/pleroma/admin/reports", %{
1525 "state" => "resolved"
1526 })
1527 |> json_response(:ok)
1528
1529 assert Enum.empty?(response["reports"])
1530 assert response["total"] == 0
1531 end
1532
1533 test "returns 403 when requested by a non-admin" do
1534 user = insert(:user)
1535
1536 conn =
1537 build_conn()
1538 |> assign(:user, user)
1539 |> get("/api/pleroma/admin/reports")
1540
1541 assert json_response(conn, :forbidden) == %{"error" => "User is not admin."}
1542 end
1543
1544 test "returns 403 when requested by anonymous" do
1545 conn =
1546 build_conn()
1547 |> get("/api/pleroma/admin/reports")
1548
1549 assert json_response(conn, :forbidden) == %{"error" => "Invalid credentials."}
1550 end
1551 end
1552
1553 describe "GET /api/pleroma/admin/grouped_reports" do
1554 setup %{conn: conn} do
1555 admin = insert(:user, is_admin: true)
1556 [reporter, target_user] = insert_pair(:user)
1557
1558 date1 = (DateTime.to_unix(DateTime.utc_now()) + 1000) |> DateTime.from_unix!()
1559 date2 = (DateTime.to_unix(DateTime.utc_now()) + 2000) |> DateTime.from_unix!()
1560 date3 = (DateTime.to_unix(DateTime.utc_now()) + 3000) |> DateTime.from_unix!()
1561
1562 first_status =
1563 insert(:note_activity, user: target_user, data_attrs: %{"published" => date1})
1564
1565 second_status =
1566 insert(:note_activity, user: target_user, data_attrs: %{"published" => date2})
1567
1568 third_status =
1569 insert(:note_activity, user: target_user, data_attrs: %{"published" => date3})
1570
1571 {:ok, first_report} =
1572 CommonAPI.report(reporter, %{
1573 "account_id" => target_user.id,
1574 "status_ids" => [first_status.id, second_status.id, third_status.id]
1575 })
1576
1577 {:ok, second_report} =
1578 CommonAPI.report(reporter, %{
1579 "account_id" => target_user.id,
1580 "status_ids" => [first_status.id, second_status.id]
1581 })
1582
1583 {:ok, third_report} =
1584 CommonAPI.report(reporter, %{
1585 "account_id" => target_user.id,
1586 "status_ids" => [first_status.id]
1587 })
1588
1589 %{
1590 conn: assign(conn, :user, admin),
1591 first_status: Activity.get_by_ap_id_with_object(first_status.data["id"]),
1592 second_status: Activity.get_by_ap_id_with_object(second_status.data["id"]),
1593 third_status: Activity.get_by_ap_id_with_object(third_status.data["id"]),
1594 first_status_reports: [first_report, second_report, third_report],
1595 second_status_reports: [first_report, second_report],
1596 third_status_reports: [first_report],
1597 target_user: target_user,
1598 reporter: reporter
1599 }
1600 end
1601
1602 test "returns reports grouped by status", %{
1603 conn: conn,
1604 first_status: first_status,
1605 second_status: second_status,
1606 third_status: third_status,
1607 first_status_reports: first_status_reports,
1608 second_status_reports: second_status_reports,
1609 third_status_reports: third_status_reports,
1610 target_user: target_user,
1611 reporter: reporter
1612 } do
1613 response =
1614 conn
1615 |> get("/api/pleroma/admin/grouped_reports")
1616 |> json_response(:ok)
1617
1618 assert length(response["reports"]) == 3
1619
1620 first_group = Enum.find(response["reports"], &(&1["status"]["id"] == first_status.id))
1621
1622 second_group = Enum.find(response["reports"], &(&1["status"]["id"] == second_status.id))
1623
1624 third_group = Enum.find(response["reports"], &(&1["status"]["id"] == third_status.id))
1625
1626 assert length(first_group["reports"]) == 3
1627 assert length(second_group["reports"]) == 2
1628 assert length(third_group["reports"]) == 1
1629
1630 assert first_group["date"] ==
1631 Enum.max_by(first_status_reports, fn act ->
1632 NaiveDateTime.from_iso8601!(act.data["published"])
1633 end).data["published"]
1634
1635 assert first_group["status"] == StatusView.render("show.json", %{activity: first_status})
1636
1637 assert first_group["account"]["id"] == target_user.id
1638
1639 assert length(first_group["actors"]) == 1
1640 assert hd(first_group["actors"])["id"] == reporter.id
1641
1642 assert Enum.map(first_group["reports"], & &1["id"]) --
1643 Enum.map(first_status_reports, & &1.id) == []
1644
1645 assert second_group["date"] ==
1646 Enum.max_by(second_status_reports, fn act ->
1647 NaiveDateTime.from_iso8601!(act.data["published"])
1648 end).data["published"]
1649
1650 assert second_group["status"] == %{
1651 "id" => second_status.data["id"],
1652 "content" => second_status.object.data["content"],
1653 "published" => second_status.object.data["published"]
1654 }
1655
1656 assert second_group["account"]["id"] == target_user.id
1657
1658 assert length(second_group["actors"]) == 1
1659 assert hd(second_group["actors"])["id"] == reporter.id
1660
1661 assert Enum.map(second_group["reports"], & &1["id"]) --
1662 Enum.map(second_status_reports, & &1.id) == []
1663
1664 assert third_group["date"] ==
1665 Enum.max_by(third_status_reports, fn act ->
1666 NaiveDateTime.from_iso8601!(act.data["published"])
1667 end).data["published"]
1668
1669 assert third_group["status"] == %{
1670 "id" => third_status.data["id"],
1671 "content" => third_status.object.data["content"],
1672 "published" => third_status.object.data["published"]
1673 }
1674
1675 assert third_group["account"]["id"] == target_user.id
1676
1677 assert length(third_group["actors"]) == 1
1678 assert hd(third_group["actors"])["id"] == reporter.id
1679
1680 assert Enum.map(third_group["reports"], & &1["id"]) --
1681 Enum.map(third_status_reports, & &1.id) == []
1682 end
1683 end
1684
1685 describe "POST /api/pleroma/admin/reports/:id/respond" do
1686 setup %{conn: conn} do
1687 admin = insert(:user, is_admin: true)
1688
1689 %{conn: assign(conn, :user, admin), admin: admin}
1690 end
1691
1692 test "returns created dm", %{conn: conn, admin: admin} do
1693 [reporter, target_user] = insert_pair(:user)
1694 activity = insert(:note_activity, user: target_user)
1695
1696 {:ok, %{id: report_id}} =
1697 CommonAPI.report(reporter, %{
1698 "account_id" => target_user.id,
1699 "comment" => "I feel offended",
1700 "status_ids" => [activity.id]
1701 })
1702
1703 response =
1704 conn
1705 |> post("/api/pleroma/admin/reports/#{report_id}/respond", %{
1706 "status" => "I will check it out"
1707 })
1708 |> json_response(:ok)
1709
1710 recipients = Enum.map(response["mentions"], & &1["username"])
1711
1712 assert reporter.nickname in recipients
1713 assert response["content"] == "I will check it out"
1714 assert response["visibility"] == "direct"
1715
1716 log_entry = Repo.one(ModerationLog)
1717
1718 assert ModerationLog.get_log_entry_message(log_entry) ==
1719 "@#{admin.nickname} responded with 'I will check it out' to report ##{
1720 response["id"]
1721 }"
1722 end
1723
1724 test "returns 400 when status is missing", %{conn: conn} do
1725 conn = post(conn, "/api/pleroma/admin/reports/test/respond")
1726
1727 assert json_response(conn, :bad_request) == "Invalid parameters"
1728 end
1729
1730 test "returns 404 when report id is invalid", %{conn: conn} do
1731 conn =
1732 post(conn, "/api/pleroma/admin/reports/test/respond", %{
1733 "status" => "foo"
1734 })
1735
1736 assert json_response(conn, :not_found) == "Not found"
1737 end
1738 end
1739
1740 describe "PUT /api/pleroma/admin/statuses/:id" do
1741 setup %{conn: conn} do
1742 admin = insert(:user, is_admin: true)
1743 activity = insert(:note_activity)
1744
1745 %{conn: assign(conn, :user, admin), id: activity.id, admin: admin}
1746 end
1747
1748 test "toggle sensitive flag", %{conn: conn, id: id, admin: admin} do
1749 response =
1750 conn
1751 |> put("/api/pleroma/admin/statuses/#{id}", %{"sensitive" => "true"})
1752 |> json_response(:ok)
1753
1754 assert response["sensitive"]
1755
1756 log_entry = Repo.one(ModerationLog)
1757
1758 assert ModerationLog.get_log_entry_message(log_entry) ==
1759 "@#{admin.nickname} updated status ##{id}, set sensitive: 'true'"
1760
1761 response =
1762 conn
1763 |> put("/api/pleroma/admin/statuses/#{id}", %{"sensitive" => "false"})
1764 |> json_response(:ok)
1765
1766 refute response["sensitive"]
1767 end
1768
1769 test "change visibility flag", %{conn: conn, id: id, admin: admin} do
1770 response =
1771 conn
1772 |> put("/api/pleroma/admin/statuses/#{id}", %{"visibility" => "public"})
1773 |> json_response(:ok)
1774
1775 assert response["visibility"] == "public"
1776
1777 log_entry = Repo.one(ModerationLog)
1778
1779 assert ModerationLog.get_log_entry_message(log_entry) ==
1780 "@#{admin.nickname} updated status ##{id}, set visibility: 'public'"
1781
1782 response =
1783 conn
1784 |> put("/api/pleroma/admin/statuses/#{id}", %{"visibility" => "private"})
1785 |> json_response(:ok)
1786
1787 assert response["visibility"] == "private"
1788
1789 response =
1790 conn
1791 |> put("/api/pleroma/admin/statuses/#{id}", %{"visibility" => "unlisted"})
1792 |> json_response(:ok)
1793
1794 assert response["visibility"] == "unlisted"
1795 end
1796
1797 test "returns 400 when visibility is unknown", %{conn: conn, id: id} do
1798 conn =
1799 conn
1800 |> put("/api/pleroma/admin/statuses/#{id}", %{"visibility" => "test"})
1801
1802 assert json_response(conn, :bad_request) == "Unsupported visibility"
1803 end
1804 end
1805
1806 describe "DELETE /api/pleroma/admin/statuses/:id" do
1807 setup %{conn: conn} do
1808 admin = insert(:user, is_admin: true)
1809 activity = insert(:note_activity)
1810
1811 %{conn: assign(conn, :user, admin), id: activity.id, admin: admin}
1812 end
1813
1814 test "deletes status", %{conn: conn, id: id, admin: admin} do
1815 conn
1816 |> delete("/api/pleroma/admin/statuses/#{id}")
1817 |> json_response(:ok)
1818
1819 refute Activity.get_by_id(id)
1820
1821 log_entry = Repo.one(ModerationLog)
1822
1823 assert ModerationLog.get_log_entry_message(log_entry) ==
1824 "@#{admin.nickname} deleted status ##{id}"
1825 end
1826
1827 test "returns error when status is not exist", %{conn: conn} do
1828 conn =
1829 conn
1830 |> delete("/api/pleroma/admin/statuses/test")
1831
1832 assert json_response(conn, :bad_request) == "Could not delete"
1833 end
1834 end
1835
1836 describe "GET /api/pleroma/admin/config" do
1837 setup %{conn: conn} do
1838 admin = insert(:user, is_admin: true)
1839
1840 %{conn: assign(conn, :user, admin)}
1841 end
1842
1843 test "without any settings in db", %{conn: conn} do
1844 conn = get(conn, "/api/pleroma/admin/config")
1845
1846 assert json_response(conn, 200) == %{"configs" => []}
1847 end
1848
1849 test "with settings in db", %{conn: conn} do
1850 config1 = insert(:config)
1851 config2 = insert(:config)
1852
1853 conn = get(conn, "/api/pleroma/admin/config")
1854
1855 %{
1856 "configs" => [
1857 %{
1858 "key" => key1,
1859 "value" => _
1860 },
1861 %{
1862 "key" => key2,
1863 "value" => _
1864 }
1865 ]
1866 } = json_response(conn, 200)
1867
1868 assert key1 == config1.key
1869 assert key2 == config2.key
1870 end
1871 end
1872
1873 describe "POST /api/pleroma/admin/config" do
1874 setup %{conn: conn} do
1875 admin = insert(:user, is_admin: true)
1876
1877 temp_file = "config/test.exported_from_db.secret.exs"
1878
1879 on_exit(fn ->
1880 Application.delete_env(:pleroma, :key1)
1881 Application.delete_env(:pleroma, :key2)
1882 Application.delete_env(:pleroma, :key3)
1883 Application.delete_env(:pleroma, :key4)
1884 Application.delete_env(:pleroma, :keyaa1)
1885 Application.delete_env(:pleroma, :keyaa2)
1886 Application.delete_env(:pleroma, Pleroma.Web.Endpoint.NotReal)
1887 Application.delete_env(:pleroma, Pleroma.Captcha.NotReal)
1888 :ok = File.rm(temp_file)
1889 end)
1890
1891 %{conn: assign(conn, :user, admin)}
1892 end
1893
1894 clear_config([:instance, :dynamic_configuration]) do
1895 Pleroma.Config.put([:instance, :dynamic_configuration], true)
1896 end
1897
1898 test "create new config setting in db", %{conn: conn} do
1899 conn =
1900 post(conn, "/api/pleroma/admin/config", %{
1901 configs: [
1902 %{group: "pleroma", key: "key1", value: "value1"},
1903 %{
1904 group: "ueberauth",
1905 key: "Ueberauth.Strategy.Twitter.OAuth",
1906 value: [%{"tuple" => [":consumer_secret", "aaaa"]}]
1907 },
1908 %{
1909 group: "pleroma",
1910 key: "key2",
1911 value: %{
1912 ":nested_1" => "nested_value1",
1913 ":nested_2" => [
1914 %{":nested_22" => "nested_value222"},
1915 %{":nested_33" => %{":nested_44" => "nested_444"}}
1916 ]
1917 }
1918 },
1919 %{
1920 group: "pleroma",
1921 key: "key3",
1922 value: [
1923 %{"nested_3" => ":nested_3", "nested_33" => "nested_33"},
1924 %{"nested_4" => true}
1925 ]
1926 },
1927 %{
1928 group: "pleroma",
1929 key: "key4",
1930 value: %{":nested_5" => ":upload", "endpoint" => "https://example.com"}
1931 },
1932 %{
1933 group: "idna",
1934 key: "key5",
1935 value: %{"tuple" => ["string", "Pleroma.Captcha.NotReal", []]}
1936 }
1937 ]
1938 })
1939
1940 assert json_response(conn, 200) == %{
1941 "configs" => [
1942 %{
1943 "group" => "pleroma",
1944 "key" => "key1",
1945 "value" => "value1"
1946 },
1947 %{
1948 "group" => "ueberauth",
1949 "key" => "Ueberauth.Strategy.Twitter.OAuth",
1950 "value" => [%{"tuple" => [":consumer_secret", "aaaa"]}]
1951 },
1952 %{
1953 "group" => "pleroma",
1954 "key" => "key2",
1955 "value" => %{
1956 ":nested_1" => "nested_value1",
1957 ":nested_2" => [
1958 %{":nested_22" => "nested_value222"},
1959 %{":nested_33" => %{":nested_44" => "nested_444"}}
1960 ]
1961 }
1962 },
1963 %{
1964 "group" => "pleroma",
1965 "key" => "key3",
1966 "value" => [
1967 %{"nested_3" => ":nested_3", "nested_33" => "nested_33"},
1968 %{"nested_4" => true}
1969 ]
1970 },
1971 %{
1972 "group" => "pleroma",
1973 "key" => "key4",
1974 "value" => %{"endpoint" => "https://example.com", ":nested_5" => ":upload"}
1975 },
1976 %{
1977 "group" => "idna",
1978 "key" => "key5",
1979 "value" => %{"tuple" => ["string", "Pleroma.Captcha.NotReal", []]}
1980 }
1981 ]
1982 }
1983
1984 assert Application.get_env(:pleroma, :key1) == "value1"
1985
1986 assert Application.get_env(:pleroma, :key2) == %{
1987 nested_1: "nested_value1",
1988 nested_2: [
1989 %{nested_22: "nested_value222"},
1990 %{nested_33: %{nested_44: "nested_444"}}
1991 ]
1992 }
1993
1994 assert Application.get_env(:pleroma, :key3) == [
1995 %{"nested_3" => :nested_3, "nested_33" => "nested_33"},
1996 %{"nested_4" => true}
1997 ]
1998
1999 assert Application.get_env(:pleroma, :key4) == %{
2000 "endpoint" => "https://example.com",
2001 nested_5: :upload
2002 }
2003
2004 assert Application.get_env(:idna, :key5) == {"string", Pleroma.Captcha.NotReal, []}
2005 end
2006
2007 test "update config setting & delete", %{conn: conn} do
2008 config1 = insert(:config, key: "keyaa1")
2009 config2 = insert(:config, key: "keyaa2")
2010
2011 insert(:config,
2012 group: "ueberauth",
2013 key: "Ueberauth.Strategy.Microsoft.OAuth",
2014 value: :erlang.term_to_binary([])
2015 )
2016
2017 conn =
2018 post(conn, "/api/pleroma/admin/config", %{
2019 configs: [
2020 %{group: config1.group, key: config1.key, value: "another_value"},
2021 %{group: config2.group, key: config2.key, delete: "true"},
2022 %{
2023 group: "ueberauth",
2024 key: "Ueberauth.Strategy.Microsoft.OAuth",
2025 delete: "true"
2026 }
2027 ]
2028 })
2029
2030 assert json_response(conn, 200) == %{
2031 "configs" => [
2032 %{
2033 "group" => "pleroma",
2034 "key" => config1.key,
2035 "value" => "another_value"
2036 }
2037 ]
2038 }
2039
2040 assert Application.get_env(:pleroma, :keyaa1) == "another_value"
2041 refute Application.get_env(:pleroma, :keyaa2)
2042 end
2043
2044 test "common config example", %{conn: conn} do
2045 conn =
2046 post(conn, "/api/pleroma/admin/config", %{
2047 configs: [
2048 %{
2049 "group" => "pleroma",
2050 "key" => "Pleroma.Captcha.NotReal",
2051 "value" => [
2052 %{"tuple" => [":enabled", false]},
2053 %{"tuple" => [":method", "Pleroma.Captcha.Kocaptcha"]},
2054 %{"tuple" => [":seconds_valid", 60]},
2055 %{"tuple" => [":path", ""]},
2056 %{"tuple" => [":key1", nil]},
2057 %{"tuple" => [":partial_chain", "&:hackney_connect.partial_chain/1"]},
2058 %{"tuple" => [":regex1", "~r/https:\/\/example.com/"]},
2059 %{"tuple" => [":regex2", "~r/https:\/\/example.com/u"]},
2060 %{"tuple" => [":regex3", "~r/https:\/\/example.com/i"]},
2061 %{"tuple" => [":regex4", "~r/https:\/\/example.com/s"]}
2062 ]
2063 }
2064 ]
2065 })
2066
2067 assert json_response(conn, 200) == %{
2068 "configs" => [
2069 %{
2070 "group" => "pleroma",
2071 "key" => "Pleroma.Captcha.NotReal",
2072 "value" => [
2073 %{"tuple" => [":enabled", false]},
2074 %{"tuple" => [":method", "Pleroma.Captcha.Kocaptcha"]},
2075 %{"tuple" => [":seconds_valid", 60]},
2076 %{"tuple" => [":path", ""]},
2077 %{"tuple" => [":key1", nil]},
2078 %{"tuple" => [":partial_chain", "&:hackney_connect.partial_chain/1"]},
2079 %{"tuple" => [":regex1", "~r/https:\\/\\/example.com/"]},
2080 %{"tuple" => [":regex2", "~r/https:\\/\\/example.com/u"]},
2081 %{"tuple" => [":regex3", "~r/https:\\/\\/example.com/i"]},
2082 %{"tuple" => [":regex4", "~r/https:\\/\\/example.com/s"]}
2083 ]
2084 }
2085 ]
2086 }
2087 end
2088
2089 test "tuples with more than two values", %{conn: conn} do
2090 conn =
2091 post(conn, "/api/pleroma/admin/config", %{
2092 configs: [
2093 %{
2094 "group" => "pleroma",
2095 "key" => "Pleroma.Web.Endpoint.NotReal",
2096 "value" => [
2097 %{
2098 "tuple" => [
2099 ":http",
2100 [
2101 %{
2102 "tuple" => [
2103 ":key2",
2104 [
2105 %{
2106 "tuple" => [
2107 ":_",
2108 [
2109 %{
2110 "tuple" => [
2111 "/api/v1/streaming",
2112 "Pleroma.Web.MastodonAPI.WebsocketHandler",
2113 []
2114 ]
2115 },
2116 %{
2117 "tuple" => [
2118 "/websocket",
2119 "Phoenix.Endpoint.CowboyWebSocket",
2120 %{
2121 "tuple" => [
2122 "Phoenix.Transports.WebSocket",
2123 %{
2124 "tuple" => [
2125 "Pleroma.Web.Endpoint",
2126 "Pleroma.Web.UserSocket",
2127 []
2128 ]
2129 }
2130 ]
2131 }
2132 ]
2133 },
2134 %{
2135 "tuple" => [
2136 ":_",
2137 "Phoenix.Endpoint.Cowboy2Handler",
2138 %{"tuple" => ["Pleroma.Web.Endpoint", []]}
2139 ]
2140 }
2141 ]
2142 ]
2143 }
2144 ]
2145 ]
2146 }
2147 ]
2148 ]
2149 }
2150 ]
2151 }
2152 ]
2153 })
2154
2155 assert json_response(conn, 200) == %{
2156 "configs" => [
2157 %{
2158 "group" => "pleroma",
2159 "key" => "Pleroma.Web.Endpoint.NotReal",
2160 "value" => [
2161 %{
2162 "tuple" => [
2163 ":http",
2164 [
2165 %{
2166 "tuple" => [
2167 ":key2",
2168 [
2169 %{
2170 "tuple" => [
2171 ":_",
2172 [
2173 %{
2174 "tuple" => [
2175 "/api/v1/streaming",
2176 "Pleroma.Web.MastodonAPI.WebsocketHandler",
2177 []
2178 ]
2179 },
2180 %{
2181 "tuple" => [
2182 "/websocket",
2183 "Phoenix.Endpoint.CowboyWebSocket",
2184 %{
2185 "tuple" => [
2186 "Phoenix.Transports.WebSocket",
2187 %{
2188 "tuple" => [
2189 "Pleroma.Web.Endpoint",
2190 "Pleroma.Web.UserSocket",
2191 []
2192 ]
2193 }
2194 ]
2195 }
2196 ]
2197 },
2198 %{
2199 "tuple" => [
2200 ":_",
2201 "Phoenix.Endpoint.Cowboy2Handler",
2202 %{"tuple" => ["Pleroma.Web.Endpoint", []]}
2203 ]
2204 }
2205 ]
2206 ]
2207 }
2208 ]
2209 ]
2210 }
2211 ]
2212 ]
2213 }
2214 ]
2215 }
2216 ]
2217 }
2218 end
2219
2220 test "settings with nesting map", %{conn: conn} do
2221 conn =
2222 post(conn, "/api/pleroma/admin/config", %{
2223 configs: [
2224 %{
2225 "group" => "pleroma",
2226 "key" => ":key1",
2227 "value" => [
2228 %{"tuple" => [":key2", "some_val"]},
2229 %{
2230 "tuple" => [
2231 ":key3",
2232 %{
2233 ":max_options" => 20,
2234 ":max_option_chars" => 200,
2235 ":min_expiration" => 0,
2236 ":max_expiration" => 31_536_000,
2237 "nested" => %{
2238 ":max_options" => 20,
2239 ":max_option_chars" => 200,
2240 ":min_expiration" => 0,
2241 ":max_expiration" => 31_536_000
2242 }
2243 }
2244 ]
2245 }
2246 ]
2247 }
2248 ]
2249 })
2250
2251 assert json_response(conn, 200) ==
2252 %{
2253 "configs" => [
2254 %{
2255 "group" => "pleroma",
2256 "key" => ":key1",
2257 "value" => [
2258 %{"tuple" => [":key2", "some_val"]},
2259 %{
2260 "tuple" => [
2261 ":key3",
2262 %{
2263 ":max_expiration" => 31_536_000,
2264 ":max_option_chars" => 200,
2265 ":max_options" => 20,
2266 ":min_expiration" => 0,
2267 "nested" => %{
2268 ":max_expiration" => 31_536_000,
2269 ":max_option_chars" => 200,
2270 ":max_options" => 20,
2271 ":min_expiration" => 0
2272 }
2273 }
2274 ]
2275 }
2276 ]
2277 }
2278 ]
2279 }
2280 end
2281
2282 test "value as map", %{conn: conn} do
2283 conn =
2284 post(conn, "/api/pleroma/admin/config", %{
2285 configs: [
2286 %{
2287 "group" => "pleroma",
2288 "key" => ":key1",
2289 "value" => %{"key" => "some_val"}
2290 }
2291 ]
2292 })
2293
2294 assert json_response(conn, 200) ==
2295 %{
2296 "configs" => [
2297 %{
2298 "group" => "pleroma",
2299 "key" => ":key1",
2300 "value" => %{"key" => "some_val"}
2301 }
2302 ]
2303 }
2304 end
2305
2306 test "dispatch setting", %{conn: conn} do
2307 conn =
2308 post(conn, "/api/pleroma/admin/config", %{
2309 configs: [
2310 %{
2311 "group" => "pleroma",
2312 "key" => "Pleroma.Web.Endpoint.NotReal",
2313 "value" => [
2314 %{
2315 "tuple" => [
2316 ":http",
2317 [
2318 %{"tuple" => [":ip", %{"tuple" => [127, 0, 0, 1]}]},
2319 %{"tuple" => [":dispatch", ["{:_,
2320 [
2321 {\"/api/v1/streaming\", Pleroma.Web.MastodonAPI.WebsocketHandler, []},
2322 {\"/websocket\", Phoenix.Endpoint.CowboyWebSocket,
2323 {Phoenix.Transports.WebSocket,
2324 {Pleroma.Web.Endpoint, Pleroma.Web.UserSocket, [path: \"/websocket\"]}}},
2325 {:_, Phoenix.Endpoint.Cowboy2Handler, {Pleroma.Web.Endpoint, []}}
2326 ]}"]]}
2327 ]
2328 ]
2329 }
2330 ]
2331 }
2332 ]
2333 })
2334
2335 dispatch_string =
2336 "{:_, [{\"/api/v1/streaming\", Pleroma.Web.MastodonAPI.WebsocketHandler, []}, " <>
2337 "{\"/websocket\", Phoenix.Endpoint.CowboyWebSocket, {Phoenix.Transports.WebSocket, " <>
2338 "{Pleroma.Web.Endpoint, Pleroma.Web.UserSocket, [path: \"/websocket\"]}}}, " <>
2339 "{:_, Phoenix.Endpoint.Cowboy2Handler, {Pleroma.Web.Endpoint, []}}]}"
2340
2341 assert json_response(conn, 200) == %{
2342 "configs" => [
2343 %{
2344 "group" => "pleroma",
2345 "key" => "Pleroma.Web.Endpoint.NotReal",
2346 "value" => [
2347 %{
2348 "tuple" => [
2349 ":http",
2350 [
2351 %{"tuple" => [":ip", %{"tuple" => [127, 0, 0, 1]}]},
2352 %{
2353 "tuple" => [
2354 ":dispatch",
2355 [
2356 dispatch_string
2357 ]
2358 ]
2359 }
2360 ]
2361 ]
2362 }
2363 ]
2364 }
2365 ]
2366 }
2367 end
2368
2369 test "queues key as atom", %{conn: conn} do
2370 conn =
2371 post(conn, "/api/pleroma/admin/config", %{
2372 configs: [
2373 %{
2374 "group" => "oban",
2375 "key" => ":queues",
2376 "value" => [
2377 %{"tuple" => [":federator_incoming", 50]},
2378 %{"tuple" => [":federator_outgoing", 50]},
2379 %{"tuple" => [":web_push", 50]},
2380 %{"tuple" => [":mailer", 10]},
2381 %{"tuple" => [":transmogrifier", 20]},
2382 %{"tuple" => [":scheduled_activities", 10]},
2383 %{"tuple" => [":background", 5]}
2384 ]
2385 }
2386 ]
2387 })
2388
2389 assert json_response(conn, 200) == %{
2390 "configs" => [
2391 %{
2392 "group" => "oban",
2393 "key" => ":queues",
2394 "value" => [
2395 %{"tuple" => [":federator_incoming", 50]},
2396 %{"tuple" => [":federator_outgoing", 50]},
2397 %{"tuple" => [":web_push", 50]},
2398 %{"tuple" => [":mailer", 10]},
2399 %{"tuple" => [":transmogrifier", 20]},
2400 %{"tuple" => [":scheduled_activities", 10]},
2401 %{"tuple" => [":background", 5]}
2402 ]
2403 }
2404 ]
2405 }
2406 end
2407
2408 test "delete part of settings by atom subkeys", %{conn: conn} do
2409 config =
2410 insert(:config,
2411 key: "keyaa1",
2412 value: :erlang.term_to_binary(subkey1: "val1", subkey2: "val2", subkey3: "val3")
2413 )
2414
2415 conn =
2416 post(conn, "/api/pleroma/admin/config", %{
2417 configs: [
2418 %{
2419 group: config.group,
2420 key: config.key,
2421 subkeys: [":subkey1", ":subkey3"],
2422 delete: "true"
2423 }
2424 ]
2425 })
2426
2427 assert(
2428 json_response(conn, 200) == %{
2429 "configs" => [
2430 %{
2431 "group" => "pleroma",
2432 "key" => "keyaa1",
2433 "value" => [%{"tuple" => [":subkey2", "val2"]}]
2434 }
2435 ]
2436 }
2437 )
2438 end
2439 end
2440
2441 describe "config mix tasks run" do
2442 setup %{conn: conn} do
2443 admin = insert(:user, is_admin: true)
2444
2445 temp_file = "config/test.exported_from_db.secret.exs"
2446
2447 Mix.shell(Mix.Shell.Quiet)
2448
2449 on_exit(fn ->
2450 Mix.shell(Mix.Shell.IO)
2451 :ok = File.rm(temp_file)
2452 end)
2453
2454 %{conn: assign(conn, :user, admin), admin: admin}
2455 end
2456
2457 clear_config([:instance, :dynamic_configuration]) do
2458 Pleroma.Config.put([:instance, :dynamic_configuration], true)
2459 end
2460
2461 clear_config([:feed, :post_title]) do
2462 Pleroma.Config.put([:feed, :post_title], %{max_length: 100, omission: "…"})
2463 end
2464
2465 test "transfer settings to DB and to file", %{conn: conn, admin: admin} do
2466 assert Pleroma.Repo.all(Pleroma.Web.AdminAPI.Config) == []
2467 conn = get(conn, "/api/pleroma/admin/config/migrate_to_db")
2468 assert json_response(conn, 200) == %{}
2469 assert Pleroma.Repo.all(Pleroma.Web.AdminAPI.Config) > 0
2470
2471 conn =
2472 build_conn()
2473 |> assign(:user, admin)
2474 |> get("/api/pleroma/admin/config/migrate_from_db")
2475
2476 assert json_response(conn, 200) == %{}
2477 assert Pleroma.Repo.all(Pleroma.Web.AdminAPI.Config) == []
2478 end
2479 end
2480
2481 describe "GET /api/pleroma/admin/users/:nickname/statuses" do
2482 setup do
2483 admin = insert(:user, is_admin: true)
2484 user = insert(:user)
2485
2486 date1 = (DateTime.to_unix(DateTime.utc_now()) + 2000) |> DateTime.from_unix!()
2487 date2 = (DateTime.to_unix(DateTime.utc_now()) + 1000) |> DateTime.from_unix!()
2488 date3 = (DateTime.to_unix(DateTime.utc_now()) + 3000) |> DateTime.from_unix!()
2489
2490 insert(:note_activity, user: user, published: date1)
2491 insert(:note_activity, user: user, published: date2)
2492 insert(:note_activity, user: user, published: date3)
2493
2494 conn =
2495 build_conn()
2496 |> assign(:user, admin)
2497
2498 {:ok, conn: conn, user: user}
2499 end
2500
2501 test "renders user's statuses", %{conn: conn, user: user} do
2502 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses")
2503
2504 assert json_response(conn, 200) |> length() == 3
2505 end
2506
2507 test "renders user's statuses with a limit", %{conn: conn, user: user} do
2508 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses?page_size=2")
2509
2510 assert json_response(conn, 200) |> length() == 2
2511 end
2512
2513 test "doesn't return private statuses by default", %{conn: conn, user: user} do
2514 {:ok, _private_status} =
2515 CommonAPI.post(user, %{"status" => "private", "visibility" => "private"})
2516
2517 {:ok, _public_status} =
2518 CommonAPI.post(user, %{"status" => "public", "visibility" => "public"})
2519
2520 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses")
2521
2522 assert json_response(conn, 200) |> length() == 4
2523 end
2524
2525 test "returns private statuses with godmode on", %{conn: conn, user: user} do
2526 {:ok, _private_status} =
2527 CommonAPI.post(user, %{"status" => "private", "visibility" => "private"})
2528
2529 {:ok, _public_status} =
2530 CommonAPI.post(user, %{"status" => "public", "visibility" => "public"})
2531
2532 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses?godmode=true")
2533
2534 assert json_response(conn, 200) |> length() == 5
2535 end
2536 end
2537
2538 describe "GET /api/pleroma/admin/moderation_log" do
2539 setup %{conn: conn} do
2540 admin = insert(:user, is_admin: true)
2541 moderator = insert(:user, is_moderator: true)
2542
2543 %{conn: assign(conn, :user, admin), admin: admin, moderator: moderator}
2544 end
2545
2546 test "returns the log", %{conn: conn, admin: admin} do
2547 Repo.insert(%ModerationLog{
2548 data: %{
2549 actor: %{
2550 "id" => admin.id,
2551 "nickname" => admin.nickname,
2552 "type" => "user"
2553 },
2554 action: "relay_follow",
2555 target: "https://example.org/relay"
2556 },
2557 inserted_at: NaiveDateTime.truncate(~N[2017-08-15 15:47:06.597036], :second)
2558 })
2559
2560 Repo.insert(%ModerationLog{
2561 data: %{
2562 actor: %{
2563 "id" => admin.id,
2564 "nickname" => admin.nickname,
2565 "type" => "user"
2566 },
2567 action: "relay_unfollow",
2568 target: "https://example.org/relay"
2569 },
2570 inserted_at: NaiveDateTime.truncate(~N[2017-08-16 15:47:06.597036], :second)
2571 })
2572
2573 conn = get(conn, "/api/pleroma/admin/moderation_log")
2574
2575 response = json_response(conn, 200)
2576 [first_entry, second_entry] = response["items"]
2577
2578 assert response["total"] == 2
2579 assert first_entry["data"]["action"] == "relay_unfollow"
2580
2581 assert first_entry["message"] ==
2582 "@#{admin.nickname} unfollowed relay: https://example.org/relay"
2583
2584 assert second_entry["data"]["action"] == "relay_follow"
2585
2586 assert second_entry["message"] ==
2587 "@#{admin.nickname} followed relay: https://example.org/relay"
2588 end
2589
2590 test "returns the log with pagination", %{conn: conn, admin: admin} do
2591 Repo.insert(%ModerationLog{
2592 data: %{
2593 actor: %{
2594 "id" => admin.id,
2595 "nickname" => admin.nickname,
2596 "type" => "user"
2597 },
2598 action: "relay_follow",
2599 target: "https://example.org/relay"
2600 },
2601 inserted_at: NaiveDateTime.truncate(~N[2017-08-15 15:47:06.597036], :second)
2602 })
2603
2604 Repo.insert(%ModerationLog{
2605 data: %{
2606 actor: %{
2607 "id" => admin.id,
2608 "nickname" => admin.nickname,
2609 "type" => "user"
2610 },
2611 action: "relay_unfollow",
2612 target: "https://example.org/relay"
2613 },
2614 inserted_at: NaiveDateTime.truncate(~N[2017-08-16 15:47:06.597036], :second)
2615 })
2616
2617 conn1 = get(conn, "/api/pleroma/admin/moderation_log?page_size=1&page=1")
2618
2619 response1 = json_response(conn1, 200)
2620 [first_entry] = response1["items"]
2621
2622 assert response1["total"] == 2
2623 assert response1["items"] |> length() == 1
2624 assert first_entry["data"]["action"] == "relay_unfollow"
2625
2626 assert first_entry["message"] ==
2627 "@#{admin.nickname} unfollowed relay: https://example.org/relay"
2628
2629 conn2 = get(conn, "/api/pleroma/admin/moderation_log?page_size=1&page=2")
2630
2631 response2 = json_response(conn2, 200)
2632 [second_entry] = response2["items"]
2633
2634 assert response2["total"] == 2
2635 assert response2["items"] |> length() == 1
2636 assert second_entry["data"]["action"] == "relay_follow"
2637
2638 assert second_entry["message"] ==
2639 "@#{admin.nickname} followed relay: https://example.org/relay"
2640 end
2641
2642 test "filters log by date", %{conn: conn, admin: admin} do
2643 first_date = "2017-08-15T15:47:06Z"
2644 second_date = "2017-08-20T15:47:06Z"
2645
2646 Repo.insert(%ModerationLog{
2647 data: %{
2648 actor: %{
2649 "id" => admin.id,
2650 "nickname" => admin.nickname,
2651 "type" => "user"
2652 },
2653 action: "relay_follow",
2654 target: "https://example.org/relay"
2655 },
2656 inserted_at: NaiveDateTime.from_iso8601!(first_date)
2657 })
2658
2659 Repo.insert(%ModerationLog{
2660 data: %{
2661 actor: %{
2662 "id" => admin.id,
2663 "nickname" => admin.nickname,
2664 "type" => "user"
2665 },
2666 action: "relay_unfollow",
2667 target: "https://example.org/relay"
2668 },
2669 inserted_at: NaiveDateTime.from_iso8601!(second_date)
2670 })
2671
2672 conn1 =
2673 get(
2674 conn,
2675 "/api/pleroma/admin/moderation_log?start_date=#{second_date}"
2676 )
2677
2678 response1 = json_response(conn1, 200)
2679 [first_entry] = response1["items"]
2680
2681 assert response1["total"] == 1
2682 assert first_entry["data"]["action"] == "relay_unfollow"
2683
2684 assert first_entry["message"] ==
2685 "@#{admin.nickname} unfollowed relay: https://example.org/relay"
2686 end
2687
2688 test "returns log filtered by user", %{conn: conn, admin: admin, moderator: moderator} do
2689 Repo.insert(%ModerationLog{
2690 data: %{
2691 actor: %{
2692 "id" => admin.id,
2693 "nickname" => admin.nickname,
2694 "type" => "user"
2695 },
2696 action: "relay_follow",
2697 target: "https://example.org/relay"
2698 }
2699 })
2700
2701 Repo.insert(%ModerationLog{
2702 data: %{
2703 actor: %{
2704 "id" => moderator.id,
2705 "nickname" => moderator.nickname,
2706 "type" => "user"
2707 },
2708 action: "relay_unfollow",
2709 target: "https://example.org/relay"
2710 }
2711 })
2712
2713 conn1 = get(conn, "/api/pleroma/admin/moderation_log?user_id=#{moderator.id}")
2714
2715 response1 = json_response(conn1, 200)
2716 [first_entry] = response1["items"]
2717
2718 assert response1["total"] == 1
2719 assert get_in(first_entry, ["data", "actor", "id"]) == moderator.id
2720 end
2721
2722 test "returns log filtered by search", %{conn: conn, moderator: moderator} do
2723 ModerationLog.insert_log(%{
2724 actor: moderator,
2725 action: "relay_follow",
2726 target: "https://example.org/relay"
2727 })
2728
2729 ModerationLog.insert_log(%{
2730 actor: moderator,
2731 action: "relay_unfollow",
2732 target: "https://example.org/relay"
2733 })
2734
2735 conn1 = get(conn, "/api/pleroma/admin/moderation_log?search=unfo")
2736
2737 response1 = json_response(conn1, 200)
2738 [first_entry] = response1["items"]
2739
2740 assert response1["total"] == 1
2741
2742 assert get_in(first_entry, ["data", "message"]) ==
2743 "@#{moderator.nickname} unfollowed relay: https://example.org/relay"
2744 end
2745 end
2746
2747 describe "PATCH /users/:nickname/force_password_reset" do
2748 setup %{conn: conn} do
2749 admin = insert(:user, is_admin: true)
2750 user = insert(:user)
2751
2752 %{conn: assign(conn, :user, admin), admin: admin, user: user}
2753 end
2754
2755 test "sets password_reset_pending to true", %{admin: admin, user: user} do
2756 assert user.password_reset_pending == false
2757
2758 conn =
2759 build_conn()
2760 |> assign(:user, admin)
2761 |> patch("/api/pleroma/admin/users/force_password_reset", %{nicknames: [user.nickname]})
2762
2763 assert json_response(conn, 204) == ""
2764
2765 ObanHelpers.perform_all()
2766
2767 assert User.get_by_id(user.id).password_reset_pending == true
2768 end
2769 end
2770
2771 describe "relays" do
2772 setup %{conn: conn} do
2773 admin = insert(:user, is_admin: true)
2774
2775 %{conn: assign(conn, :user, admin), admin: admin}
2776 end
2777
2778 test "POST /relay", %{admin: admin} do
2779 conn =
2780 build_conn()
2781 |> assign(:user, admin)
2782 |> post("/api/pleroma/admin/relay", %{
2783 relay_url: "http://mastodon.example.org/users/admin"
2784 })
2785
2786 assert json_response(conn, 200) == "http://mastodon.example.org/users/admin"
2787
2788 log_entry = Repo.one(ModerationLog)
2789
2790 assert ModerationLog.get_log_entry_message(log_entry) ==
2791 "@#{admin.nickname} followed relay: http://mastodon.example.org/users/admin"
2792 end
2793
2794 test "GET /relay", %{admin: admin} do
2795 relay_user = Pleroma.Web.ActivityPub.Relay.get_actor()
2796
2797 ["http://mastodon.example.org/users/admin", "https://mstdn.io/users/mayuutann"]
2798 |> Enum.each(fn ap_id ->
2799 {:ok, user} = User.get_or_fetch_by_ap_id(ap_id)
2800 User.follow(relay_user, user)
2801 end)
2802
2803 conn =
2804 build_conn()
2805 |> assign(:user, admin)
2806 |> get("/api/pleroma/admin/relay")
2807
2808 assert json_response(conn, 200)["relays"] -- ["mastodon.example.org", "mstdn.io"] == []
2809 end
2810
2811 test "DELETE /relay", %{admin: admin} do
2812 build_conn()
2813 |> assign(:user, admin)
2814 |> post("/api/pleroma/admin/relay", %{
2815 relay_url: "http://mastodon.example.org/users/admin"
2816 })
2817
2818 conn =
2819 build_conn()
2820 |> assign(:user, admin)
2821 |> delete("/api/pleroma/admin/relay", %{
2822 relay_url: "http://mastodon.example.org/users/admin"
2823 })
2824
2825 assert json_response(conn, 200) == "http://mastodon.example.org/users/admin"
2826
2827 [log_entry_one, log_entry_two] = Repo.all(ModerationLog)
2828
2829 assert ModerationLog.get_log_entry_message(log_entry_one) ==
2830 "@#{admin.nickname} followed relay: http://mastodon.example.org/users/admin"
2831
2832 assert ModerationLog.get_log_entry_message(log_entry_two) ==
2833 "@#{admin.nickname} unfollowed relay: http://mastodon.example.org/users/admin"
2834 end
2835 end
2836 end
2837
2838 # Needed for testing
2839 defmodule Pleroma.Web.Endpoint.NotReal do
2840 end
2841
2842 defmodule Pleroma.Captcha.NotReal do
2843 end