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