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