fix reset confirmation email in admin section
[akkoma] / test / web / admin_api / controllers / admin_api_controller_test.exs
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2020 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 import ExUnit.CaptureLog
10 import Mock
11 import Pleroma.Factory
12 import Swoosh.TestAssertions
13
14 alias Pleroma.Activity
15 alias Pleroma.Config
16 alias Pleroma.HTML
17 alias Pleroma.MFA
18 alias Pleroma.ModerationLog
19 alias Pleroma.Repo
20 alias Pleroma.Tests.ObanHelpers
21 alias Pleroma.User
22 alias Pleroma.Web
23 alias Pleroma.Web.ActivityPub.Relay
24 alias Pleroma.Web.CommonAPI
25 alias Pleroma.Web.MediaProxy
26
27 setup_all do
28 Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
29
30 :ok
31 end
32
33 setup do
34 admin = insert(:user, is_admin: true)
35 token = insert(:oauth_admin_token, user: admin)
36
37 conn =
38 build_conn()
39 |> assign(:user, admin)
40 |> assign(:token, token)
41
42 {:ok, %{admin: admin, token: token, conn: conn}}
43 end
44
45 describe "with [:auth, :enforce_oauth_admin_scope_usage]," do
46 setup do: clear_config([:auth, :enforce_oauth_admin_scope_usage], true)
47
48 test "GET /api/pleroma/admin/users/:nickname requires admin:read:accounts or broader scope",
49 %{admin: admin} do
50 user = insert(:user)
51 url = "/api/pleroma/admin/users/#{user.nickname}"
52
53 good_token1 = insert(:oauth_token, user: admin, scopes: ["admin"])
54 good_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read"])
55 good_token3 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts"])
56
57 bad_token1 = insert(:oauth_token, user: admin, scopes: ["read:accounts"])
58 bad_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts:partial"])
59 bad_token3 = nil
60
61 for good_token <- [good_token1, good_token2, good_token3] do
62 conn =
63 build_conn()
64 |> assign(:user, admin)
65 |> assign(:token, good_token)
66 |> get(url)
67
68 assert json_response(conn, 200)
69 end
70
71 for good_token <- [good_token1, good_token2, good_token3] do
72 conn =
73 build_conn()
74 |> assign(:user, nil)
75 |> assign(:token, good_token)
76 |> get(url)
77
78 assert json_response(conn, :forbidden)
79 end
80
81 for bad_token <- [bad_token1, bad_token2, bad_token3] do
82 conn =
83 build_conn()
84 |> assign(:user, admin)
85 |> assign(:token, bad_token)
86 |> get(url)
87
88 assert json_response(conn, :forbidden)
89 end
90 end
91 end
92
93 describe "unless [:auth, :enforce_oauth_admin_scope_usage]," do
94 setup do: clear_config([:auth, :enforce_oauth_admin_scope_usage], false)
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 clear_config([:instance, :federating], true)
150
151 with_mock Pleroma.Web.Federator,
152 publish: fn _ -> nil end do
153 conn =
154 conn
155 |> put_req_header("accept", "application/json")
156 |> delete("/api/pleroma/admin/users?nickname=#{user.nickname}")
157
158 ObanHelpers.perform_all()
159
160 assert User.get_by_nickname(user.nickname).deactivated
161
162 log_entry = Repo.one(ModerationLog)
163
164 assert ModerationLog.get_log_entry_message(log_entry) ==
165 "@#{admin.nickname} deleted users: @#{user.nickname}"
166
167 assert json_response(conn, 200) == [user.nickname]
168
169 assert called(Pleroma.Web.Federator.publish(:_))
170 end
171 end
172
173 test "multiple users", %{admin: admin, conn: conn} do
174 user_one = insert(:user)
175 user_two = insert(:user)
176
177 conn =
178 conn
179 |> put_req_header("accept", "application/json")
180 |> delete("/api/pleroma/admin/users", %{
181 nicknames: [user_one.nickname, user_two.nickname]
182 })
183
184 log_entry = Repo.one(ModerationLog)
185
186 assert ModerationLog.get_log_entry_message(log_entry) ==
187 "@#{admin.nickname} deleted users: @#{user_one.nickname}, @#{user_two.nickname}"
188
189 response = json_response(conn, 200)
190 assert response -- [user_one.nickname, user_two.nickname] == []
191 end
192 end
193
194 describe "/api/pleroma/admin/users" do
195 test "Create", %{conn: conn} do
196 conn =
197 conn
198 |> put_req_header("accept", "application/json")
199 |> post("/api/pleroma/admin/users", %{
200 "users" => [
201 %{
202 "nickname" => "lain",
203 "email" => "lain@example.org",
204 "password" => "test"
205 },
206 %{
207 "nickname" => "lain2",
208 "email" => "lain2@example.org",
209 "password" => "test"
210 }
211 ]
212 })
213
214 response = json_response(conn, 200) |> Enum.map(&Map.get(&1, "type"))
215 assert response == ["success", "success"]
216
217 log_entry = Repo.one(ModerationLog)
218
219 assert ["lain", "lain2"] -- Enum.map(log_entry.data["subjects"], & &1["nickname"]) == []
220 end
221
222 test "Cannot create user with existing email", %{conn: conn} do
223 user = insert(:user)
224
225 conn =
226 conn
227 |> put_req_header("accept", "application/json")
228 |> post("/api/pleroma/admin/users", %{
229 "users" => [
230 %{
231 "nickname" => "lain",
232 "email" => user.email,
233 "password" => "test"
234 }
235 ]
236 })
237
238 assert json_response(conn, 409) == [
239 %{
240 "code" => 409,
241 "data" => %{
242 "email" => user.email,
243 "nickname" => "lain"
244 },
245 "error" => "email has already been taken",
246 "type" => "error"
247 }
248 ]
249 end
250
251 test "Cannot create user with existing nickname", %{conn: conn} do
252 user = insert(:user)
253
254 conn =
255 conn
256 |> put_req_header("accept", "application/json")
257 |> post("/api/pleroma/admin/users", %{
258 "users" => [
259 %{
260 "nickname" => user.nickname,
261 "email" => "someuser@plerama.social",
262 "password" => "test"
263 }
264 ]
265 })
266
267 assert json_response(conn, 409) == [
268 %{
269 "code" => 409,
270 "data" => %{
271 "email" => "someuser@plerama.social",
272 "nickname" => user.nickname
273 },
274 "error" => "nickname has already been taken",
275 "type" => "error"
276 }
277 ]
278 end
279
280 test "Multiple user creation works in transaction", %{conn: conn} do
281 user = insert(:user)
282
283 conn =
284 conn
285 |> put_req_header("accept", "application/json")
286 |> post("/api/pleroma/admin/users", %{
287 "users" => [
288 %{
289 "nickname" => "newuser",
290 "email" => "newuser@pleroma.social",
291 "password" => "test"
292 },
293 %{
294 "nickname" => "lain",
295 "email" => user.email,
296 "password" => "test"
297 }
298 ]
299 })
300
301 assert json_response(conn, 409) == [
302 %{
303 "code" => 409,
304 "data" => %{
305 "email" => user.email,
306 "nickname" => "lain"
307 },
308 "error" => "email has already been taken",
309 "type" => "error"
310 },
311 %{
312 "code" => 409,
313 "data" => %{
314 "email" => "newuser@pleroma.social",
315 "nickname" => "newuser"
316 },
317 "error" => "",
318 "type" => "error"
319 }
320 ]
321
322 assert User.get_by_nickname("newuser") === nil
323 end
324 end
325
326 describe "/api/pleroma/admin/users/:nickname" do
327 test "Show", %{conn: conn} do
328 user = insert(:user)
329
330 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}")
331
332 expected = %{
333 "deactivated" => false,
334 "id" => to_string(user.id),
335 "local" => true,
336 "nickname" => user.nickname,
337 "roles" => %{"admin" => false, "moderator" => false},
338 "tags" => [],
339 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
340 "display_name" => HTML.strip_tags(user.name || user.nickname),
341 "confirmation_pending" => false,
342 "url" => user.ap_id
343 }
344
345 assert expected == json_response(conn, 200)
346 end
347
348 test "when the user doesn't exist", %{conn: conn} do
349 user = build(:user)
350
351 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}")
352
353 assert %{"error" => "Not found"} == json_response(conn, 404)
354 end
355 end
356
357 describe "/api/pleroma/admin/users/follow" do
358 test "allows to force-follow another user", %{admin: admin, conn: conn} do
359 user = insert(:user)
360 follower = insert(:user)
361
362 conn
363 |> put_req_header("accept", "application/json")
364 |> post("/api/pleroma/admin/users/follow", %{
365 "follower" => follower.nickname,
366 "followed" => user.nickname
367 })
368
369 user = User.get_cached_by_id(user.id)
370 follower = User.get_cached_by_id(follower.id)
371
372 assert User.following?(follower, user)
373
374 log_entry = Repo.one(ModerationLog)
375
376 assert ModerationLog.get_log_entry_message(log_entry) ==
377 "@#{admin.nickname} made @#{follower.nickname} follow @#{user.nickname}"
378 end
379 end
380
381 describe "/api/pleroma/admin/users/unfollow" do
382 test "allows to force-unfollow another user", %{admin: admin, conn: conn} do
383 user = insert(:user)
384 follower = insert(:user)
385
386 User.follow(follower, user)
387
388 conn
389 |> put_req_header("accept", "application/json")
390 |> post("/api/pleroma/admin/users/unfollow", %{
391 "follower" => follower.nickname,
392 "followed" => user.nickname
393 })
394
395 user = User.get_cached_by_id(user.id)
396 follower = User.get_cached_by_id(follower.id)
397
398 refute User.following?(follower, user)
399
400 log_entry = Repo.one(ModerationLog)
401
402 assert ModerationLog.get_log_entry_message(log_entry) ==
403 "@#{admin.nickname} made @#{follower.nickname} unfollow @#{user.nickname}"
404 end
405 end
406
407 describe "PUT /api/pleroma/admin/users/tag" do
408 setup %{conn: conn} do
409 user1 = insert(:user, %{tags: ["x"]})
410 user2 = insert(:user, %{tags: ["y"]})
411 user3 = insert(:user, %{tags: ["unchanged"]})
412
413 conn =
414 conn
415 |> put_req_header("accept", "application/json")
416 |> put(
417 "/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=" <>
418 "#{user2.nickname}&tags[]=foo&tags[]=bar"
419 )
420
421 %{conn: conn, user1: user1, user2: user2, user3: user3}
422 end
423
424 test "it appends specified tags to users with specified nicknames", %{
425 conn: conn,
426 admin: admin,
427 user1: user1,
428 user2: user2
429 } do
430 assert json_response(conn, :no_content)
431 assert User.get_cached_by_id(user1.id).tags == ["x", "foo", "bar"]
432 assert User.get_cached_by_id(user2.id).tags == ["y", "foo", "bar"]
433
434 log_entry = Repo.one(ModerationLog)
435
436 users =
437 [user1.nickname, user2.nickname]
438 |> Enum.map(&"@#{&1}")
439 |> Enum.join(", ")
440
441 tags = ["foo", "bar"] |> Enum.join(", ")
442
443 assert ModerationLog.get_log_entry_message(log_entry) ==
444 "@#{admin.nickname} added tags: #{tags} to users: #{users}"
445 end
446
447 test "it does not modify tags of not specified users", %{conn: conn, user3: user3} do
448 assert json_response(conn, :no_content)
449 assert User.get_cached_by_id(user3.id).tags == ["unchanged"]
450 end
451 end
452
453 describe "DELETE /api/pleroma/admin/users/tag" do
454 setup %{conn: conn} do
455 user1 = insert(:user, %{tags: ["x"]})
456 user2 = insert(:user, %{tags: ["y", "z"]})
457 user3 = insert(:user, %{tags: ["unchanged"]})
458
459 conn =
460 conn
461 |> put_req_header("accept", "application/json")
462 |> delete(
463 "/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=" <>
464 "#{user2.nickname}&tags[]=x&tags[]=z"
465 )
466
467 %{conn: conn, user1: user1, user2: user2, user3: user3}
468 end
469
470 test "it removes specified tags from users with specified nicknames", %{
471 conn: conn,
472 admin: admin,
473 user1: user1,
474 user2: user2
475 } do
476 assert json_response(conn, :no_content)
477 assert User.get_cached_by_id(user1.id).tags == []
478 assert User.get_cached_by_id(user2.id).tags == ["y"]
479
480 log_entry = Repo.one(ModerationLog)
481
482 users =
483 [user1.nickname, user2.nickname]
484 |> Enum.map(&"@#{&1}")
485 |> Enum.join(", ")
486
487 tags = ["x", "z"] |> Enum.join(", ")
488
489 assert ModerationLog.get_log_entry_message(log_entry) ==
490 "@#{admin.nickname} removed tags: #{tags} from users: #{users}"
491 end
492
493 test "it does not modify tags of not specified users", %{conn: conn, user3: user3} do
494 assert json_response(conn, :no_content)
495 assert User.get_cached_by_id(user3.id).tags == ["unchanged"]
496 end
497 end
498
499 describe "/api/pleroma/admin/users/:nickname/permission_group" do
500 test "GET is giving user_info", %{admin: admin, conn: conn} do
501 conn =
502 conn
503 |> put_req_header("accept", "application/json")
504 |> get("/api/pleroma/admin/users/#{admin.nickname}/permission_group/")
505
506 assert json_response(conn, 200) == %{
507 "is_admin" => true,
508 "is_moderator" => false
509 }
510 end
511
512 test "/:right POST, can add to a permission group", %{admin: admin, conn: conn} do
513 user = insert(:user)
514
515 conn =
516 conn
517 |> put_req_header("accept", "application/json")
518 |> post("/api/pleroma/admin/users/#{user.nickname}/permission_group/admin")
519
520 assert json_response(conn, 200) == %{
521 "is_admin" => true
522 }
523
524 log_entry = Repo.one(ModerationLog)
525
526 assert ModerationLog.get_log_entry_message(log_entry) ==
527 "@#{admin.nickname} made @#{user.nickname} admin"
528 end
529
530 test "/:right POST, can add to a permission group (multiple)", %{admin: admin, conn: conn} do
531 user_one = insert(:user)
532 user_two = insert(:user)
533
534 conn =
535 conn
536 |> put_req_header("accept", "application/json")
537 |> post("/api/pleroma/admin/users/permission_group/admin", %{
538 nicknames: [user_one.nickname, user_two.nickname]
539 })
540
541 assert json_response(conn, 200) == %{"is_admin" => true}
542
543 log_entry = Repo.one(ModerationLog)
544
545 assert ModerationLog.get_log_entry_message(log_entry) ==
546 "@#{admin.nickname} made @#{user_one.nickname}, @#{user_two.nickname} admin"
547 end
548
549 test "/:right DELETE, can remove from a permission group", %{admin: admin, conn: conn} do
550 user = insert(:user, is_admin: true)
551
552 conn =
553 conn
554 |> put_req_header("accept", "application/json")
555 |> delete("/api/pleroma/admin/users/#{user.nickname}/permission_group/admin")
556
557 assert json_response(conn, 200) == %{"is_admin" => false}
558
559 log_entry = Repo.one(ModerationLog)
560
561 assert ModerationLog.get_log_entry_message(log_entry) ==
562 "@#{admin.nickname} revoked admin role from @#{user.nickname}"
563 end
564
565 test "/:right DELETE, can remove from a permission group (multiple)", %{
566 admin: admin,
567 conn: conn
568 } do
569 user_one = insert(:user, is_admin: true)
570 user_two = insert(:user, is_admin: true)
571
572 conn =
573 conn
574 |> put_req_header("accept", "application/json")
575 |> delete("/api/pleroma/admin/users/permission_group/admin", %{
576 nicknames: [user_one.nickname, user_two.nickname]
577 })
578
579 assert json_response(conn, 200) == %{"is_admin" => false}
580
581 log_entry = Repo.one(ModerationLog)
582
583 assert ModerationLog.get_log_entry_message(log_entry) ==
584 "@#{admin.nickname} revoked admin role from @#{user_one.nickname}, @#{
585 user_two.nickname
586 }"
587 end
588 end
589
590 test "/api/pleroma/admin/users/:nickname/password_reset", %{conn: conn} do
591 user = insert(:user)
592
593 conn =
594 conn
595 |> put_req_header("accept", "application/json")
596 |> get("/api/pleroma/admin/users/#{user.nickname}/password_reset")
597
598 resp = json_response(conn, 200)
599
600 assert Regex.match?(~r/(http:\/\/|https:\/\/)/, resp["link"])
601 end
602
603 describe "GET /api/pleroma/admin/users" do
604 test "renders users array for the first page", %{conn: conn, admin: admin} do
605 user = insert(:user, local: false, tags: ["foo", "bar"])
606 conn = get(conn, "/api/pleroma/admin/users?page=1")
607
608 users =
609 [
610 %{
611 "deactivated" => admin.deactivated,
612 "id" => admin.id,
613 "nickname" => admin.nickname,
614 "roles" => %{"admin" => true, "moderator" => false},
615 "local" => true,
616 "tags" => [],
617 "avatar" => User.avatar_url(admin) |> MediaProxy.url(),
618 "display_name" => HTML.strip_tags(admin.name || admin.nickname),
619 "confirmation_pending" => false,
620 "url" => admin.ap_id
621 },
622 %{
623 "deactivated" => user.deactivated,
624 "id" => user.id,
625 "nickname" => user.nickname,
626 "roles" => %{"admin" => false, "moderator" => false},
627 "local" => false,
628 "tags" => ["foo", "bar"],
629 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
630 "display_name" => HTML.strip_tags(user.name || user.nickname),
631 "confirmation_pending" => false,
632 "url" => user.ap_id
633 }
634 ]
635 |> Enum.sort_by(& &1["nickname"])
636
637 assert json_response(conn, 200) == %{
638 "count" => 2,
639 "page_size" => 50,
640 "users" => users
641 }
642 end
643
644 test "pagination works correctly with service users", %{conn: conn} do
645 service1 = User.get_or_create_service_actor_by_ap_id(Web.base_url() <> "/meido", "meido")
646
647 insert_list(25, :user)
648
649 assert %{"count" => 26, "page_size" => 10, "users" => users1} =
650 conn
651 |> get("/api/pleroma/admin/users?page=1&filters=", %{page_size: "10"})
652 |> json_response(200)
653
654 assert Enum.count(users1) == 10
655 assert service1 not in users1
656
657 assert %{"count" => 26, "page_size" => 10, "users" => users2} =
658 conn
659 |> get("/api/pleroma/admin/users?page=2&filters=", %{page_size: "10"})
660 |> json_response(200)
661
662 assert Enum.count(users2) == 10
663 assert service1 not in users2
664
665 assert %{"count" => 26, "page_size" => 10, "users" => users3} =
666 conn
667 |> get("/api/pleroma/admin/users?page=3&filters=", %{page_size: "10"})
668 |> json_response(200)
669
670 assert Enum.count(users3) == 6
671 assert service1 not in users3
672 end
673
674 test "renders empty array for the second page", %{conn: conn} do
675 insert(:user)
676
677 conn = get(conn, "/api/pleroma/admin/users?page=2")
678
679 assert json_response(conn, 200) == %{
680 "count" => 2,
681 "page_size" => 50,
682 "users" => []
683 }
684 end
685
686 test "regular search", %{conn: conn} do
687 user = insert(:user, nickname: "bob")
688
689 conn = get(conn, "/api/pleroma/admin/users?query=bo")
690
691 assert json_response(conn, 200) == %{
692 "count" => 1,
693 "page_size" => 50,
694 "users" => [
695 %{
696 "deactivated" => user.deactivated,
697 "id" => user.id,
698 "nickname" => user.nickname,
699 "roles" => %{"admin" => false, "moderator" => false},
700 "local" => true,
701 "tags" => [],
702 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
703 "display_name" => HTML.strip_tags(user.name || user.nickname),
704 "confirmation_pending" => false,
705 "url" => user.ap_id
706 }
707 ]
708 }
709 end
710
711 test "search by domain", %{conn: conn} do
712 user = insert(:user, nickname: "nickname@domain.com")
713 insert(:user)
714
715 conn = get(conn, "/api/pleroma/admin/users?query=domain.com")
716
717 assert json_response(conn, 200) == %{
718 "count" => 1,
719 "page_size" => 50,
720 "users" => [
721 %{
722 "deactivated" => user.deactivated,
723 "id" => user.id,
724 "nickname" => user.nickname,
725 "roles" => %{"admin" => false, "moderator" => false},
726 "local" => true,
727 "tags" => [],
728 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
729 "display_name" => HTML.strip_tags(user.name || user.nickname),
730 "confirmation_pending" => false,
731 "url" => user.ap_id
732 }
733 ]
734 }
735 end
736
737 test "search by full nickname", %{conn: conn} do
738 user = insert(:user, nickname: "nickname@domain.com")
739 insert(:user)
740
741 conn = get(conn, "/api/pleroma/admin/users?query=nickname@domain.com")
742
743 assert json_response(conn, 200) == %{
744 "count" => 1,
745 "page_size" => 50,
746 "users" => [
747 %{
748 "deactivated" => user.deactivated,
749 "id" => user.id,
750 "nickname" => user.nickname,
751 "roles" => %{"admin" => false, "moderator" => false},
752 "local" => true,
753 "tags" => [],
754 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
755 "display_name" => HTML.strip_tags(user.name || user.nickname),
756 "confirmation_pending" => false,
757 "url" => user.ap_id
758 }
759 ]
760 }
761 end
762
763 test "search by display name", %{conn: conn} do
764 user = insert(:user, name: "Display name")
765 insert(:user)
766
767 conn = get(conn, "/api/pleroma/admin/users?name=display")
768
769 assert json_response(conn, 200) == %{
770 "count" => 1,
771 "page_size" => 50,
772 "users" => [
773 %{
774 "deactivated" => user.deactivated,
775 "id" => user.id,
776 "nickname" => user.nickname,
777 "roles" => %{"admin" => false, "moderator" => false},
778 "local" => true,
779 "tags" => [],
780 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
781 "display_name" => HTML.strip_tags(user.name || user.nickname),
782 "confirmation_pending" => false,
783 "url" => user.ap_id
784 }
785 ]
786 }
787 end
788
789 test "search by email", %{conn: conn} do
790 user = insert(:user, email: "email@example.com")
791 insert(:user)
792
793 conn = get(conn, "/api/pleroma/admin/users?email=email@example.com")
794
795 assert json_response(conn, 200) == %{
796 "count" => 1,
797 "page_size" => 50,
798 "users" => [
799 %{
800 "deactivated" => user.deactivated,
801 "id" => user.id,
802 "nickname" => user.nickname,
803 "roles" => %{"admin" => false, "moderator" => false},
804 "local" => true,
805 "tags" => [],
806 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
807 "display_name" => HTML.strip_tags(user.name || user.nickname),
808 "confirmation_pending" => false,
809 "url" => user.ap_id
810 }
811 ]
812 }
813 end
814
815 test "regular search with page size", %{conn: conn} do
816 user = insert(:user, nickname: "aalice")
817 user2 = insert(:user, nickname: "alice")
818
819 conn1 = get(conn, "/api/pleroma/admin/users?query=a&page_size=1&page=1")
820
821 assert json_response(conn1, 200) == %{
822 "count" => 2,
823 "page_size" => 1,
824 "users" => [
825 %{
826 "deactivated" => user.deactivated,
827 "id" => user.id,
828 "nickname" => user.nickname,
829 "roles" => %{"admin" => false, "moderator" => false},
830 "local" => true,
831 "tags" => [],
832 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
833 "display_name" => HTML.strip_tags(user.name || user.nickname),
834 "confirmation_pending" => false,
835 "url" => user.ap_id
836 }
837 ]
838 }
839
840 conn2 = get(conn, "/api/pleroma/admin/users?query=a&page_size=1&page=2")
841
842 assert json_response(conn2, 200) == %{
843 "count" => 2,
844 "page_size" => 1,
845 "users" => [
846 %{
847 "deactivated" => user2.deactivated,
848 "id" => user2.id,
849 "nickname" => user2.nickname,
850 "roles" => %{"admin" => false, "moderator" => false},
851 "local" => true,
852 "tags" => [],
853 "avatar" => User.avatar_url(user2) |> MediaProxy.url(),
854 "display_name" => HTML.strip_tags(user2.name || user2.nickname),
855 "confirmation_pending" => false,
856 "url" => user2.ap_id
857 }
858 ]
859 }
860 end
861
862 test "only local users" do
863 admin = insert(:user, is_admin: true, nickname: "john")
864 token = insert(:oauth_admin_token, user: admin)
865 user = insert(:user, nickname: "bob")
866
867 insert(:user, nickname: "bobb", local: false)
868
869 conn =
870 build_conn()
871 |> assign(:user, admin)
872 |> assign(:token, token)
873 |> get("/api/pleroma/admin/users?query=bo&filters=local")
874
875 assert json_response(conn, 200) == %{
876 "count" => 1,
877 "page_size" => 50,
878 "users" => [
879 %{
880 "deactivated" => user.deactivated,
881 "id" => user.id,
882 "nickname" => user.nickname,
883 "roles" => %{"admin" => false, "moderator" => false},
884 "local" => true,
885 "tags" => [],
886 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
887 "display_name" => HTML.strip_tags(user.name || user.nickname),
888 "confirmation_pending" => false,
889 "url" => user.ap_id
890 }
891 ]
892 }
893 end
894
895 test "only local users with no query", %{conn: conn, admin: old_admin} do
896 admin = insert(:user, is_admin: true, nickname: "john")
897 user = insert(:user, nickname: "bob")
898
899 insert(:user, nickname: "bobb", local: false)
900
901 conn = get(conn, "/api/pleroma/admin/users?filters=local")
902
903 users =
904 [
905 %{
906 "deactivated" => user.deactivated,
907 "id" => user.id,
908 "nickname" => user.nickname,
909 "roles" => %{"admin" => false, "moderator" => false},
910 "local" => true,
911 "tags" => [],
912 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
913 "display_name" => HTML.strip_tags(user.name || user.nickname),
914 "confirmation_pending" => false,
915 "url" => user.ap_id
916 },
917 %{
918 "deactivated" => admin.deactivated,
919 "id" => admin.id,
920 "nickname" => admin.nickname,
921 "roles" => %{"admin" => true, "moderator" => false},
922 "local" => true,
923 "tags" => [],
924 "avatar" => User.avatar_url(admin) |> MediaProxy.url(),
925 "display_name" => HTML.strip_tags(admin.name || admin.nickname),
926 "confirmation_pending" => false,
927 "url" => admin.ap_id
928 },
929 %{
930 "deactivated" => false,
931 "id" => old_admin.id,
932 "local" => true,
933 "nickname" => old_admin.nickname,
934 "roles" => %{"admin" => true, "moderator" => false},
935 "tags" => [],
936 "avatar" => User.avatar_url(old_admin) |> MediaProxy.url(),
937 "display_name" => HTML.strip_tags(old_admin.name || old_admin.nickname),
938 "confirmation_pending" => false,
939 "url" => old_admin.ap_id
940 }
941 ]
942 |> Enum.sort_by(& &1["nickname"])
943
944 assert json_response(conn, 200) == %{
945 "count" => 3,
946 "page_size" => 50,
947 "users" => users
948 }
949 end
950
951 test "load only admins", %{conn: conn, admin: admin} do
952 second_admin = insert(:user, is_admin: true)
953 insert(:user)
954 insert(:user)
955
956 conn = get(conn, "/api/pleroma/admin/users?filters=is_admin")
957
958 users =
959 [
960 %{
961 "deactivated" => false,
962 "id" => admin.id,
963 "nickname" => admin.nickname,
964 "roles" => %{"admin" => true, "moderator" => false},
965 "local" => admin.local,
966 "tags" => [],
967 "avatar" => User.avatar_url(admin) |> MediaProxy.url(),
968 "display_name" => HTML.strip_tags(admin.name || admin.nickname),
969 "confirmation_pending" => false,
970 "url" => admin.ap_id
971 },
972 %{
973 "deactivated" => false,
974 "id" => second_admin.id,
975 "nickname" => second_admin.nickname,
976 "roles" => %{"admin" => true, "moderator" => false},
977 "local" => second_admin.local,
978 "tags" => [],
979 "avatar" => User.avatar_url(second_admin) |> MediaProxy.url(),
980 "display_name" => HTML.strip_tags(second_admin.name || second_admin.nickname),
981 "confirmation_pending" => false,
982 "url" => second_admin.ap_id
983 }
984 ]
985 |> Enum.sort_by(& &1["nickname"])
986
987 assert json_response(conn, 200) == %{
988 "count" => 2,
989 "page_size" => 50,
990 "users" => users
991 }
992 end
993
994 test "load only moderators", %{conn: conn} do
995 moderator = insert(:user, is_moderator: true)
996 insert(:user)
997 insert(:user)
998
999 conn = get(conn, "/api/pleroma/admin/users?filters=is_moderator")
1000
1001 assert json_response(conn, 200) == %{
1002 "count" => 1,
1003 "page_size" => 50,
1004 "users" => [
1005 %{
1006 "deactivated" => false,
1007 "id" => moderator.id,
1008 "nickname" => moderator.nickname,
1009 "roles" => %{"admin" => false, "moderator" => true},
1010 "local" => moderator.local,
1011 "tags" => [],
1012 "avatar" => User.avatar_url(moderator) |> MediaProxy.url(),
1013 "display_name" => HTML.strip_tags(moderator.name || moderator.nickname),
1014 "confirmation_pending" => false,
1015 "url" => moderator.ap_id
1016 }
1017 ]
1018 }
1019 end
1020
1021 test "load users with tags list", %{conn: conn} do
1022 user1 = insert(:user, tags: ["first"])
1023 user2 = insert(:user, tags: ["second"])
1024 insert(:user)
1025 insert(:user)
1026
1027 conn = get(conn, "/api/pleroma/admin/users?tags[]=first&tags[]=second")
1028
1029 users =
1030 [
1031 %{
1032 "deactivated" => false,
1033 "id" => user1.id,
1034 "nickname" => user1.nickname,
1035 "roles" => %{"admin" => false, "moderator" => false},
1036 "local" => user1.local,
1037 "tags" => ["first"],
1038 "avatar" => User.avatar_url(user1) |> MediaProxy.url(),
1039 "display_name" => HTML.strip_tags(user1.name || user1.nickname),
1040 "confirmation_pending" => false,
1041 "url" => user1.ap_id
1042 },
1043 %{
1044 "deactivated" => false,
1045 "id" => user2.id,
1046 "nickname" => user2.nickname,
1047 "roles" => %{"admin" => false, "moderator" => false},
1048 "local" => user2.local,
1049 "tags" => ["second"],
1050 "avatar" => User.avatar_url(user2) |> MediaProxy.url(),
1051 "display_name" => HTML.strip_tags(user2.name || user2.nickname),
1052 "confirmation_pending" => false,
1053 "url" => user2.ap_id
1054 }
1055 ]
1056 |> Enum.sort_by(& &1["nickname"])
1057
1058 assert json_response(conn, 200) == %{
1059 "count" => 2,
1060 "page_size" => 50,
1061 "users" => users
1062 }
1063 end
1064
1065 test "it works with multiple filters" do
1066 admin = insert(:user, nickname: "john", is_admin: true)
1067 token = insert(:oauth_admin_token, user: admin)
1068 user = insert(:user, nickname: "bob", local: false, deactivated: true)
1069
1070 insert(:user, nickname: "ken", local: true, deactivated: true)
1071 insert(:user, nickname: "bobb", local: false, deactivated: false)
1072
1073 conn =
1074 build_conn()
1075 |> assign(:user, admin)
1076 |> assign(:token, token)
1077 |> get("/api/pleroma/admin/users?filters=deactivated,external")
1078
1079 assert json_response(conn, 200) == %{
1080 "count" => 1,
1081 "page_size" => 50,
1082 "users" => [
1083 %{
1084 "deactivated" => user.deactivated,
1085 "id" => user.id,
1086 "nickname" => user.nickname,
1087 "roles" => %{"admin" => false, "moderator" => false},
1088 "local" => user.local,
1089 "tags" => [],
1090 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
1091 "display_name" => HTML.strip_tags(user.name || user.nickname),
1092 "confirmation_pending" => false,
1093 "url" => user.ap_id
1094 }
1095 ]
1096 }
1097 end
1098
1099 test "it omits relay user", %{admin: admin, conn: conn} do
1100 assert %User{} = Relay.get_actor()
1101
1102 conn = get(conn, "/api/pleroma/admin/users")
1103
1104 assert json_response(conn, 200) == %{
1105 "count" => 1,
1106 "page_size" => 50,
1107 "users" => [
1108 %{
1109 "deactivated" => admin.deactivated,
1110 "id" => admin.id,
1111 "nickname" => admin.nickname,
1112 "roles" => %{"admin" => true, "moderator" => false},
1113 "local" => true,
1114 "tags" => [],
1115 "avatar" => User.avatar_url(admin) |> MediaProxy.url(),
1116 "display_name" => HTML.strip_tags(admin.name || admin.nickname),
1117 "confirmation_pending" => false,
1118 "url" => admin.ap_id
1119 }
1120 ]
1121 }
1122 end
1123 end
1124
1125 test "PATCH /api/pleroma/admin/users/activate", %{admin: admin, conn: conn} do
1126 user_one = insert(:user, deactivated: true)
1127 user_two = insert(:user, deactivated: true)
1128
1129 conn =
1130 patch(
1131 conn,
1132 "/api/pleroma/admin/users/activate",
1133 %{nicknames: [user_one.nickname, user_two.nickname]}
1134 )
1135
1136 response = json_response(conn, 200)
1137 assert Enum.map(response["users"], & &1["deactivated"]) == [false, false]
1138
1139 log_entry = Repo.one(ModerationLog)
1140
1141 assert ModerationLog.get_log_entry_message(log_entry) ==
1142 "@#{admin.nickname} activated users: @#{user_one.nickname}, @#{user_two.nickname}"
1143 end
1144
1145 test "PATCH /api/pleroma/admin/users/deactivate", %{admin: admin, conn: conn} do
1146 user_one = insert(:user, deactivated: false)
1147 user_two = insert(:user, deactivated: false)
1148
1149 conn =
1150 patch(
1151 conn,
1152 "/api/pleroma/admin/users/deactivate",
1153 %{nicknames: [user_one.nickname, user_two.nickname]}
1154 )
1155
1156 response = json_response(conn, 200)
1157 assert Enum.map(response["users"], & &1["deactivated"]) == [true, true]
1158
1159 log_entry = Repo.one(ModerationLog)
1160
1161 assert ModerationLog.get_log_entry_message(log_entry) ==
1162 "@#{admin.nickname} deactivated users: @#{user_one.nickname}, @#{user_two.nickname}"
1163 end
1164
1165 test "PATCH /api/pleroma/admin/users/:nickname/toggle_activation", %{admin: admin, conn: conn} do
1166 user = insert(:user)
1167
1168 conn = patch(conn, "/api/pleroma/admin/users/#{user.nickname}/toggle_activation")
1169
1170 assert json_response(conn, 200) ==
1171 %{
1172 "deactivated" => !user.deactivated,
1173 "id" => user.id,
1174 "nickname" => user.nickname,
1175 "roles" => %{"admin" => false, "moderator" => false},
1176 "local" => true,
1177 "tags" => [],
1178 "avatar" => User.avatar_url(user) |> MediaProxy.url(),
1179 "display_name" => HTML.strip_tags(user.name || user.nickname),
1180 "confirmation_pending" => false,
1181 "url" => user.ap_id
1182 }
1183
1184 log_entry = Repo.one(ModerationLog)
1185
1186 assert ModerationLog.get_log_entry_message(log_entry) ==
1187 "@#{admin.nickname} deactivated users: @#{user.nickname}"
1188 end
1189
1190 describe "PUT disable_mfa" do
1191 test "returns 200 and disable 2fa", %{conn: conn} do
1192 user =
1193 insert(:user,
1194 multi_factor_authentication_settings: %MFA.Settings{
1195 enabled: true,
1196 totp: %MFA.Settings.TOTP{secret: "otp_secret", confirmed: true}
1197 }
1198 )
1199
1200 response =
1201 conn
1202 |> put("/api/pleroma/admin/users/disable_mfa", %{nickname: user.nickname})
1203 |> json_response(200)
1204
1205 assert response == user.nickname
1206 mfa_settings = refresh_record(user).multi_factor_authentication_settings
1207
1208 refute mfa_settings.enabled
1209 refute mfa_settings.totp.confirmed
1210 end
1211
1212 test "returns 404 if user not found", %{conn: conn} do
1213 response =
1214 conn
1215 |> put("/api/pleroma/admin/users/disable_mfa", %{nickname: "nickname"})
1216 |> json_response(404)
1217
1218 assert response == %{"error" => "Not found"}
1219 end
1220 end
1221
1222 describe "GET /api/pleroma/admin/restart" do
1223 setup do: clear_config(:configurable_from_database, true)
1224
1225 test "pleroma restarts", %{conn: conn} do
1226 capture_log(fn ->
1227 assert conn |> get("/api/pleroma/admin/restart") |> json_response(200) == %{}
1228 end) =~ "pleroma restarted"
1229
1230 refute Restarter.Pleroma.need_reboot?()
1231 end
1232 end
1233
1234 test "need_reboot flag", %{conn: conn} do
1235 assert conn
1236 |> get("/api/pleroma/admin/need_reboot")
1237 |> json_response(200) == %{"need_reboot" => false}
1238
1239 Restarter.Pleroma.need_reboot()
1240
1241 assert conn
1242 |> get("/api/pleroma/admin/need_reboot")
1243 |> json_response(200) == %{"need_reboot" => true}
1244
1245 on_exit(fn -> Restarter.Pleroma.refresh() end)
1246 end
1247
1248 describe "GET /api/pleroma/admin/users/:nickname/statuses" do
1249 setup do
1250 user = insert(:user)
1251
1252 date1 = (DateTime.to_unix(DateTime.utc_now()) + 2000) |> DateTime.from_unix!()
1253 date2 = (DateTime.to_unix(DateTime.utc_now()) + 1000) |> DateTime.from_unix!()
1254 date3 = (DateTime.to_unix(DateTime.utc_now()) + 3000) |> DateTime.from_unix!()
1255
1256 insert(:note_activity, user: user, published: date1)
1257 insert(:note_activity, user: user, published: date2)
1258 insert(:note_activity, user: user, published: date3)
1259
1260 %{user: user}
1261 end
1262
1263 test "renders user's statuses", %{conn: conn, user: user} do
1264 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses")
1265
1266 assert json_response(conn, 200) |> length() == 3
1267 end
1268
1269 test "renders user's statuses with a limit", %{conn: conn, user: user} do
1270 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses?page_size=2")
1271
1272 assert json_response(conn, 200) |> length() == 2
1273 end
1274
1275 test "doesn't return private statuses by default", %{conn: conn, user: user} do
1276 {:ok, _private_status} = CommonAPI.post(user, %{status: "private", visibility: "private"})
1277
1278 {:ok, _public_status} = CommonAPI.post(user, %{status: "public", visibility: "public"})
1279
1280 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses")
1281
1282 assert json_response(conn, 200) |> length() == 4
1283 end
1284
1285 test "returns private statuses with godmode on", %{conn: conn, user: user} do
1286 {:ok, _private_status} = CommonAPI.post(user, %{status: "private", visibility: "private"})
1287
1288 {:ok, _public_status} = CommonAPI.post(user, %{status: "public", visibility: "public"})
1289
1290 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses?godmode=true")
1291
1292 assert json_response(conn, 200) |> length() == 5
1293 end
1294
1295 test "excludes reblogs by default", %{conn: conn, user: user} do
1296 other_user = insert(:user)
1297 {:ok, activity} = CommonAPI.post(user, %{status: "."})
1298 {:ok, %Activity{}} = CommonAPI.repeat(activity.id, other_user)
1299
1300 conn_res = get(conn, "/api/pleroma/admin/users/#{other_user.nickname}/statuses")
1301 assert json_response(conn_res, 200) |> length() == 0
1302
1303 conn_res =
1304 get(conn, "/api/pleroma/admin/users/#{other_user.nickname}/statuses?with_reblogs=true")
1305
1306 assert json_response(conn_res, 200) |> length() == 1
1307 end
1308 end
1309
1310 describe "GET /api/pleroma/admin/moderation_log" do
1311 setup do
1312 moderator = insert(:user, is_moderator: true)
1313
1314 %{moderator: moderator}
1315 end
1316
1317 test "returns the log", %{conn: conn, admin: admin} do
1318 Repo.insert(%ModerationLog{
1319 data: %{
1320 actor: %{
1321 "id" => admin.id,
1322 "nickname" => admin.nickname,
1323 "type" => "user"
1324 },
1325 action: "relay_follow",
1326 target: "https://example.org/relay"
1327 },
1328 inserted_at: NaiveDateTime.truncate(~N[2017-08-15 15:47:06.597036], :second)
1329 })
1330
1331 Repo.insert(%ModerationLog{
1332 data: %{
1333 actor: %{
1334 "id" => admin.id,
1335 "nickname" => admin.nickname,
1336 "type" => "user"
1337 },
1338 action: "relay_unfollow",
1339 target: "https://example.org/relay"
1340 },
1341 inserted_at: NaiveDateTime.truncate(~N[2017-08-16 15:47:06.597036], :second)
1342 })
1343
1344 conn = get(conn, "/api/pleroma/admin/moderation_log")
1345
1346 response = json_response(conn, 200)
1347 [first_entry, second_entry] = response["items"]
1348
1349 assert response["total"] == 2
1350 assert first_entry["data"]["action"] == "relay_unfollow"
1351
1352 assert first_entry["message"] ==
1353 "@#{admin.nickname} unfollowed relay: https://example.org/relay"
1354
1355 assert second_entry["data"]["action"] == "relay_follow"
1356
1357 assert second_entry["message"] ==
1358 "@#{admin.nickname} followed relay: https://example.org/relay"
1359 end
1360
1361 test "returns the log with pagination", %{conn: conn, admin: admin} do
1362 Repo.insert(%ModerationLog{
1363 data: %{
1364 actor: %{
1365 "id" => admin.id,
1366 "nickname" => admin.nickname,
1367 "type" => "user"
1368 },
1369 action: "relay_follow",
1370 target: "https://example.org/relay"
1371 },
1372 inserted_at: NaiveDateTime.truncate(~N[2017-08-15 15:47:06.597036], :second)
1373 })
1374
1375 Repo.insert(%ModerationLog{
1376 data: %{
1377 actor: %{
1378 "id" => admin.id,
1379 "nickname" => admin.nickname,
1380 "type" => "user"
1381 },
1382 action: "relay_unfollow",
1383 target: "https://example.org/relay"
1384 },
1385 inserted_at: NaiveDateTime.truncate(~N[2017-08-16 15:47:06.597036], :second)
1386 })
1387
1388 conn1 = get(conn, "/api/pleroma/admin/moderation_log?page_size=1&page=1")
1389
1390 response1 = json_response(conn1, 200)
1391 [first_entry] = response1["items"]
1392
1393 assert response1["total"] == 2
1394 assert response1["items"] |> length() == 1
1395 assert first_entry["data"]["action"] == "relay_unfollow"
1396
1397 assert first_entry["message"] ==
1398 "@#{admin.nickname} unfollowed relay: https://example.org/relay"
1399
1400 conn2 = get(conn, "/api/pleroma/admin/moderation_log?page_size=1&page=2")
1401
1402 response2 = json_response(conn2, 200)
1403 [second_entry] = response2["items"]
1404
1405 assert response2["total"] == 2
1406 assert response2["items"] |> length() == 1
1407 assert second_entry["data"]["action"] == "relay_follow"
1408
1409 assert second_entry["message"] ==
1410 "@#{admin.nickname} followed relay: https://example.org/relay"
1411 end
1412
1413 test "filters log by date", %{conn: conn, admin: admin} do
1414 first_date = "2017-08-15T15:47:06Z"
1415 second_date = "2017-08-20T15:47:06Z"
1416
1417 Repo.insert(%ModerationLog{
1418 data: %{
1419 actor: %{
1420 "id" => admin.id,
1421 "nickname" => admin.nickname,
1422 "type" => "user"
1423 },
1424 action: "relay_follow",
1425 target: "https://example.org/relay"
1426 },
1427 inserted_at: NaiveDateTime.from_iso8601!(first_date)
1428 })
1429
1430 Repo.insert(%ModerationLog{
1431 data: %{
1432 actor: %{
1433 "id" => admin.id,
1434 "nickname" => admin.nickname,
1435 "type" => "user"
1436 },
1437 action: "relay_unfollow",
1438 target: "https://example.org/relay"
1439 },
1440 inserted_at: NaiveDateTime.from_iso8601!(second_date)
1441 })
1442
1443 conn1 =
1444 get(
1445 conn,
1446 "/api/pleroma/admin/moderation_log?start_date=#{second_date}"
1447 )
1448
1449 response1 = json_response(conn1, 200)
1450 [first_entry] = response1["items"]
1451
1452 assert response1["total"] == 1
1453 assert first_entry["data"]["action"] == "relay_unfollow"
1454
1455 assert first_entry["message"] ==
1456 "@#{admin.nickname} unfollowed relay: https://example.org/relay"
1457 end
1458
1459 test "returns log filtered by user", %{conn: conn, admin: admin, moderator: moderator} do
1460 Repo.insert(%ModerationLog{
1461 data: %{
1462 actor: %{
1463 "id" => admin.id,
1464 "nickname" => admin.nickname,
1465 "type" => "user"
1466 },
1467 action: "relay_follow",
1468 target: "https://example.org/relay"
1469 }
1470 })
1471
1472 Repo.insert(%ModerationLog{
1473 data: %{
1474 actor: %{
1475 "id" => moderator.id,
1476 "nickname" => moderator.nickname,
1477 "type" => "user"
1478 },
1479 action: "relay_unfollow",
1480 target: "https://example.org/relay"
1481 }
1482 })
1483
1484 conn1 = get(conn, "/api/pleroma/admin/moderation_log?user_id=#{moderator.id}")
1485
1486 response1 = json_response(conn1, 200)
1487 [first_entry] = response1["items"]
1488
1489 assert response1["total"] == 1
1490 assert get_in(first_entry, ["data", "actor", "id"]) == moderator.id
1491 end
1492
1493 test "returns log filtered by search", %{conn: conn, moderator: moderator} do
1494 ModerationLog.insert_log(%{
1495 actor: moderator,
1496 action: "relay_follow",
1497 target: "https://example.org/relay"
1498 })
1499
1500 ModerationLog.insert_log(%{
1501 actor: moderator,
1502 action: "relay_unfollow",
1503 target: "https://example.org/relay"
1504 })
1505
1506 conn1 = get(conn, "/api/pleroma/admin/moderation_log?search=unfo")
1507
1508 response1 = json_response(conn1, 200)
1509 [first_entry] = response1["items"]
1510
1511 assert response1["total"] == 1
1512
1513 assert get_in(first_entry, ["data", "message"]) ==
1514 "@#{moderator.nickname} unfollowed relay: https://example.org/relay"
1515 end
1516 end
1517
1518 test "gets a remote users when [:instance, :limit_to_local_content] is set to :unauthenticated",
1519 %{conn: conn} do
1520 clear_config(Pleroma.Config.get([:instance, :limit_to_local_content]), :unauthenticated)
1521 user = insert(:user, %{local: false, nickname: "u@peer1.com"})
1522 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/credentials")
1523
1524 assert json_response(conn, 200)
1525 end
1526
1527 describe "GET /users/:nickname/credentials" do
1528 test "gets the user credentials", %{conn: conn} do
1529 user = insert(:user)
1530 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/credentials")
1531
1532 response = assert json_response(conn, 200)
1533 assert response["email"] == user.email
1534 end
1535
1536 test "returns 403 if requested by a non-admin" do
1537 user = insert(:user)
1538
1539 conn =
1540 build_conn()
1541 |> assign(:user, user)
1542 |> get("/api/pleroma/admin/users/#{user.nickname}/credentials")
1543
1544 assert json_response(conn, :forbidden)
1545 end
1546 end
1547
1548 describe "PATCH /users/:nickname/credentials" do
1549 setup do
1550 user = insert(:user)
1551 [user: user]
1552 end
1553
1554 test "changes password and email", %{conn: conn, admin: admin, user: user} do
1555 assert user.password_reset_pending == false
1556
1557 conn =
1558 patch(conn, "/api/pleroma/admin/users/#{user.nickname}/credentials", %{
1559 "password" => "new_password",
1560 "email" => "new_email@example.com",
1561 "name" => "new_name"
1562 })
1563
1564 assert json_response(conn, 200) == %{"status" => "success"}
1565
1566 ObanHelpers.perform_all()
1567
1568 updated_user = User.get_by_id(user.id)
1569
1570 assert updated_user.email == "new_email@example.com"
1571 assert updated_user.name == "new_name"
1572 assert updated_user.password_hash != user.password_hash
1573 assert updated_user.password_reset_pending == true
1574
1575 [log_entry2, log_entry1] = ModerationLog |> Repo.all() |> Enum.sort()
1576
1577 assert ModerationLog.get_log_entry_message(log_entry1) ==
1578 "@#{admin.nickname} updated users: @#{user.nickname}"
1579
1580 assert ModerationLog.get_log_entry_message(log_entry2) ==
1581 "@#{admin.nickname} forced password reset for users: @#{user.nickname}"
1582 end
1583
1584 test "returns 403 if requested by a non-admin", %{user: user} do
1585 conn =
1586 build_conn()
1587 |> assign(:user, user)
1588 |> patch("/api/pleroma/admin/users/#{user.nickname}/credentials", %{
1589 "password" => "new_password",
1590 "email" => "new_email@example.com",
1591 "name" => "new_name"
1592 })
1593
1594 assert json_response(conn, :forbidden)
1595 end
1596
1597 test "changes actor type from permitted list", %{conn: conn, user: user} do
1598 assert user.actor_type == "Person"
1599
1600 assert patch(conn, "/api/pleroma/admin/users/#{user.nickname}/credentials", %{
1601 "actor_type" => "Service"
1602 })
1603 |> json_response(200) == %{"status" => "success"}
1604
1605 updated_user = User.get_by_id(user.id)
1606
1607 assert updated_user.actor_type == "Service"
1608
1609 assert patch(conn, "/api/pleroma/admin/users/#{user.nickname}/credentials", %{
1610 "actor_type" => "Application"
1611 })
1612 |> json_response(400) == %{"errors" => %{"actor_type" => "is invalid"}}
1613 end
1614
1615 test "update non existing user", %{conn: conn} do
1616 assert patch(conn, "/api/pleroma/admin/users/non-existing/credentials", %{
1617 "password" => "new_password"
1618 })
1619 |> json_response(404) == %{"error" => "Not found"}
1620 end
1621 end
1622
1623 describe "PATCH /users/:nickname/force_password_reset" do
1624 test "sets password_reset_pending to true", %{conn: conn} do
1625 user = insert(:user)
1626 assert user.password_reset_pending == false
1627
1628 conn =
1629 patch(conn, "/api/pleroma/admin/users/force_password_reset", %{nicknames: [user.nickname]})
1630
1631 assert json_response(conn, 204) == ""
1632
1633 ObanHelpers.perform_all()
1634
1635 assert User.get_by_id(user.id).password_reset_pending == true
1636 end
1637 end
1638
1639 describe "instances" do
1640 test "GET /instances/:instance/statuses", %{conn: conn} do
1641 user = insert(:user, local: false, nickname: "archaeme@archae.me")
1642 user2 = insert(:user, local: false, nickname: "test@test.com")
1643 insert_pair(:note_activity, user: user)
1644 activity = insert(:note_activity, user: user2)
1645
1646 ret_conn = get(conn, "/api/pleroma/admin/instances/archae.me/statuses")
1647
1648 response = json_response(ret_conn, 200)
1649
1650 assert length(response) == 2
1651
1652 ret_conn = get(conn, "/api/pleroma/admin/instances/test.com/statuses")
1653
1654 response = json_response(ret_conn, 200)
1655
1656 assert length(response) == 1
1657
1658 ret_conn = get(conn, "/api/pleroma/admin/instances/nonexistent.com/statuses")
1659
1660 response = json_response(ret_conn, 200)
1661
1662 assert Enum.empty?(response)
1663
1664 CommonAPI.repeat(activity.id, user)
1665
1666 ret_conn = get(conn, "/api/pleroma/admin/instances/archae.me/statuses")
1667 response = json_response(ret_conn, 200)
1668 assert length(response) == 2
1669
1670 ret_conn = get(conn, "/api/pleroma/admin/instances/archae.me/statuses?with_reblogs=true")
1671 response = json_response(ret_conn, 200)
1672 assert length(response) == 3
1673 end
1674 end
1675
1676 describe "PATCH /confirm_email" do
1677 test "it confirms emails of two users", %{conn: conn, admin: admin} do
1678 [first_user, second_user] = insert_pair(:user, confirmation_pending: true)
1679
1680 assert first_user.confirmation_pending == true
1681 assert second_user.confirmation_pending == true
1682
1683 ret_conn =
1684 patch(conn, "/api/pleroma/admin/users/confirm_email", %{
1685 nicknames: [
1686 first_user.nickname,
1687 second_user.nickname
1688 ]
1689 })
1690
1691 assert ret_conn.status == 200
1692
1693 assert first_user.confirmation_pending == true
1694 assert second_user.confirmation_pending == true
1695
1696 log_entry = Repo.one(ModerationLog)
1697
1698 assert ModerationLog.get_log_entry_message(log_entry) ==
1699 "@#{admin.nickname} confirmed email for users: @#{first_user.nickname}, @#{
1700 second_user.nickname
1701 }"
1702 end
1703 end
1704
1705 describe "PATCH /resend_confirmation_email" do
1706 test "it resend emails for two users", %{conn: conn, admin: admin} do
1707 [first_user, second_user] = insert_pair(:user, confirmation_pending: true)
1708
1709 ret_conn =
1710 patch(conn, "/api/pleroma/admin/users/resend_confirmation_email", %{
1711 nicknames: [
1712 first_user.nickname,
1713 second_user.nickname
1714 ]
1715 })
1716
1717 assert ret_conn.status == 200
1718
1719 log_entry = Repo.one(ModerationLog)
1720
1721 assert ModerationLog.get_log_entry_message(log_entry) ==
1722 "@#{admin.nickname} re-sent confirmation email for users: @#{first_user.nickname}, @#{
1723 second_user.nickname
1724 }"
1725
1726 ObanHelpers.perform_all()
1727 assert_email_sent(Pleroma.Emails.UserEmail.account_confirmation_email(first_user))
1728 end
1729 end
1730
1731 describe "/api/pleroma/admin/stats" do
1732 test "status visibility count", %{conn: conn} do
1733 admin = insert(:user, is_admin: true)
1734 user = insert(:user)
1735 CommonAPI.post(user, %{visibility: "public", status: "hey"})
1736 CommonAPI.post(user, %{visibility: "unlisted", status: "hey"})
1737 CommonAPI.post(user, %{visibility: "unlisted", status: "hey"})
1738
1739 response =
1740 conn
1741 |> assign(:user, admin)
1742 |> get("/api/pleroma/admin/stats")
1743 |> json_response(200)
1744
1745 assert %{"direct" => 0, "private" => 0, "public" => 1, "unlisted" => 2} =
1746 response["status_visibility"]
1747 end
1748
1749 test "by instance", %{conn: conn} do
1750 admin = insert(:user, is_admin: true)
1751 user1 = insert(:user)
1752 instance2 = "instance2.tld"
1753 user2 = insert(:user, %{ap_id: "https://#{instance2}/@actor"})
1754
1755 CommonAPI.post(user1, %{visibility: "public", status: "hey"})
1756 CommonAPI.post(user2, %{visibility: "unlisted", status: "hey"})
1757 CommonAPI.post(user2, %{visibility: "private", status: "hey"})
1758
1759 response =
1760 conn
1761 |> assign(:user, admin)
1762 |> get("/api/pleroma/admin/stats", instance: instance2)
1763 |> json_response(200)
1764
1765 assert %{"direct" => 0, "private" => 1, "public" => 0, "unlisted" => 1} =
1766 response["status_visibility"]
1767 end
1768 end
1769 end
1770
1771 # Needed for testing
1772 defmodule Pleroma.Web.Endpoint.NotReal do
1773 end
1774
1775 defmodule Pleroma.Captcha.NotReal do
1776 end