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