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