Merge branch 'feat/allow_alt_text_search_config' into 'develop'
[akkoma] / test / pleroma / web / admin_api / controllers / admin_api_controller_test.exs
1 # Pleroma: A lightweight social networking server
2 # Copyright © 2017-2021 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 Pleroma.Factory
11 import Swoosh.TestAssertions
12
13 alias Pleroma.Activity
14 alias Pleroma.MFA
15 alias Pleroma.ModerationLog
16 alias Pleroma.Repo
17 alias Pleroma.Tests.ObanHelpers
18 alias Pleroma.User
19 alias Pleroma.Web.CommonAPI
20
21 setup_all do
22 Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
23
24 :ok
25 end
26
27 setup do
28 admin = insert(:user, is_admin: true)
29 token = insert(:oauth_admin_token, user: admin)
30
31 conn =
32 build_conn()
33 |> assign(:user, admin)
34 |> assign(:token, token)
35
36 {:ok, %{admin: admin, token: token, conn: conn}}
37 end
38
39 test "with valid `admin_token` query parameter, skips OAuth scopes check" do
40 clear_config([:admin_token], "password123")
41
42 user = insert(:user)
43
44 conn = get(build_conn(), "/api/pleroma/admin/users/#{user.nickname}?admin_token=password123")
45
46 assert json_response(conn, 200)
47 end
48
49 describe "with [:auth, :enforce_oauth_admin_scope_usage]," do
50 setup do: clear_config([:auth, :enforce_oauth_admin_scope_usage], true)
51
52 test "GET /api/pleroma/admin/users/:nickname requires admin:read:accounts or broader scope",
53 %{admin: admin} do
54 user = insert(:user)
55 url = "/api/pleroma/admin/users/#{user.nickname}"
56
57 good_token1 = insert(:oauth_token, user: admin, scopes: ["admin"])
58 good_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read"])
59 good_token3 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts"])
60
61 bad_token1 = insert(:oauth_token, user: admin, scopes: ["read:accounts"])
62 bad_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts:partial"])
63 bad_token3 = nil
64
65 for good_token <- [good_token1, good_token2, good_token3] do
66 conn =
67 build_conn()
68 |> assign(:user, admin)
69 |> assign(:token, good_token)
70 |> get(url)
71
72 assert json_response(conn, 200)
73 end
74
75 for good_token <- [good_token1, good_token2, good_token3] do
76 conn =
77 build_conn()
78 |> assign(:user, nil)
79 |> assign(:token, good_token)
80 |> get(url)
81
82 assert json_response(conn, :forbidden)
83 end
84
85 for bad_token <- [bad_token1, bad_token2, bad_token3] do
86 conn =
87 build_conn()
88 |> assign(:user, admin)
89 |> assign(:token, bad_token)
90 |> get(url)
91
92 assert json_response(conn, :forbidden)
93 end
94 end
95 end
96
97 describe "unless [:auth, :enforce_oauth_admin_scope_usage]," do
98 setup do: clear_config([:auth, :enforce_oauth_admin_scope_usage], false)
99
100 test "GET /api/pleroma/admin/users/:nickname requires " <>
101 "read:accounts or admin:read:accounts or broader scope",
102 %{admin: admin} do
103 user = insert(:user)
104 url = "/api/pleroma/admin/users/#{user.nickname}"
105
106 good_token1 = insert(:oauth_token, user: admin, scopes: ["admin"])
107 good_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read"])
108 good_token3 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts"])
109 good_token4 = insert(:oauth_token, user: admin, scopes: ["read:accounts"])
110 good_token5 = insert(:oauth_token, user: admin, scopes: ["read"])
111
112 good_tokens = [good_token1, good_token2, good_token3, good_token4, good_token5]
113
114 bad_token1 = insert(:oauth_token, user: admin, scopes: ["read:accounts:partial"])
115 bad_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts:partial"])
116 bad_token3 = nil
117
118 for good_token <- good_tokens do
119 conn =
120 build_conn()
121 |> assign(:user, admin)
122 |> assign(:token, good_token)
123 |> get(url)
124
125 assert json_response(conn, 200)
126 end
127
128 for good_token <- good_tokens do
129 conn =
130 build_conn()
131 |> assign(:user, nil)
132 |> assign(:token, good_token)
133 |> get(url)
134
135 assert json_response(conn, :forbidden)
136 end
137
138 for bad_token <- [bad_token1, bad_token2, bad_token3] do
139 conn =
140 build_conn()
141 |> assign(:user, admin)
142 |> assign(:token, bad_token)
143 |> get(url)
144
145 assert json_response(conn, :forbidden)
146 end
147 end
148 end
149
150 describe "PUT /api/pleroma/admin/users/tag" do
151 setup %{conn: conn} do
152 user1 = insert(:user, %{tags: ["x"]})
153 user2 = insert(:user, %{tags: ["y"]})
154 user3 = insert(:user, %{tags: ["unchanged"]})
155
156 conn =
157 conn
158 |> put_req_header("accept", "application/json")
159 |> put(
160 "/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=" <>
161 "#{user2.nickname}&tags[]=foo&tags[]=bar"
162 )
163
164 %{conn: conn, user1: user1, user2: user2, user3: user3}
165 end
166
167 test "it appends specified tags to users with specified nicknames", %{
168 conn: conn,
169 admin: admin,
170 user1: user1,
171 user2: user2
172 } do
173 assert empty_json_response(conn)
174 assert User.get_cached_by_id(user1.id).tags == ["x", "foo", "bar"]
175 assert User.get_cached_by_id(user2.id).tags == ["y", "foo", "bar"]
176
177 log_entry = Repo.one(ModerationLog)
178
179 users =
180 [user1.nickname, user2.nickname]
181 |> Enum.map(&"@#{&1}")
182 |> Enum.join(", ")
183
184 tags = ["foo", "bar"] |> Enum.join(", ")
185
186 assert ModerationLog.get_log_entry_message(log_entry) ==
187 "@#{admin.nickname} added tags: #{tags} to users: #{users}"
188 end
189
190 test "it does not modify tags of not specified users", %{conn: conn, user3: user3} do
191 assert empty_json_response(conn)
192 assert User.get_cached_by_id(user3.id).tags == ["unchanged"]
193 end
194 end
195
196 describe "DELETE /api/pleroma/admin/users/tag" do
197 setup %{conn: conn} do
198 user1 = insert(:user, %{tags: ["x"]})
199 user2 = insert(:user, %{tags: ["y", "z"]})
200 user3 = insert(:user, %{tags: ["unchanged"]})
201
202 conn =
203 conn
204 |> put_req_header("accept", "application/json")
205 |> delete(
206 "/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=" <>
207 "#{user2.nickname}&tags[]=x&tags[]=z"
208 )
209
210 %{conn: conn, user1: user1, user2: user2, user3: user3}
211 end
212
213 test "it removes specified tags from users with specified nicknames", %{
214 conn: conn,
215 admin: admin,
216 user1: user1,
217 user2: user2
218 } do
219 assert empty_json_response(conn)
220 assert User.get_cached_by_id(user1.id).tags == []
221 assert User.get_cached_by_id(user2.id).tags == ["y"]
222
223 log_entry = Repo.one(ModerationLog)
224
225 users =
226 [user1.nickname, user2.nickname]
227 |> Enum.map(&"@#{&1}")
228 |> Enum.join(", ")
229
230 tags = ["x", "z"] |> Enum.join(", ")
231
232 assert ModerationLog.get_log_entry_message(log_entry) ==
233 "@#{admin.nickname} removed tags: #{tags} from users: #{users}"
234 end
235
236 test "it does not modify tags of not specified users", %{conn: conn, user3: user3} do
237 assert empty_json_response(conn)
238 assert User.get_cached_by_id(user3.id).tags == ["unchanged"]
239 end
240 end
241
242 describe "/api/pleroma/admin/users/:nickname/permission_group" do
243 test "GET is giving user_info", %{admin: admin, conn: conn} do
244 conn =
245 conn
246 |> put_req_header("accept", "application/json")
247 |> get("/api/pleroma/admin/users/#{admin.nickname}/permission_group/")
248
249 assert json_response(conn, 200) == %{
250 "is_admin" => true,
251 "is_moderator" => false
252 }
253 end
254
255 test "/:right POST, can add to a permission group", %{admin: admin, conn: conn} do
256 user = insert(:user)
257
258 conn =
259 conn
260 |> put_req_header("accept", "application/json")
261 |> post("/api/pleroma/admin/users/#{user.nickname}/permission_group/admin")
262
263 assert json_response(conn, 200) == %{
264 "is_admin" => true
265 }
266
267 log_entry = Repo.one(ModerationLog)
268
269 assert ModerationLog.get_log_entry_message(log_entry) ==
270 "@#{admin.nickname} made @#{user.nickname} admin"
271 end
272
273 test "/:right POST, can add to a permission group (multiple)", %{admin: admin, conn: conn} do
274 user_one = insert(:user)
275 user_two = insert(:user)
276
277 conn =
278 conn
279 |> put_req_header("accept", "application/json")
280 |> post("/api/pleroma/admin/users/permission_group/admin", %{
281 nicknames: [user_one.nickname, user_two.nickname]
282 })
283
284 assert json_response(conn, 200) == %{"is_admin" => true}
285
286 log_entry = Repo.one(ModerationLog)
287
288 assert ModerationLog.get_log_entry_message(log_entry) ==
289 "@#{admin.nickname} made @#{user_one.nickname}, @#{user_two.nickname} admin"
290 end
291
292 test "/:right DELETE, can remove from a permission group", %{admin: admin, conn: conn} do
293 user = insert(:user, is_admin: true)
294
295 conn =
296 conn
297 |> put_req_header("accept", "application/json")
298 |> delete("/api/pleroma/admin/users/#{user.nickname}/permission_group/admin")
299
300 assert json_response(conn, 200) == %{"is_admin" => false}
301
302 log_entry = Repo.one(ModerationLog)
303
304 assert ModerationLog.get_log_entry_message(log_entry) ==
305 "@#{admin.nickname} revoked admin role from @#{user.nickname}"
306 end
307
308 test "/:right DELETE, can remove from a permission group (multiple)", %{
309 admin: admin,
310 conn: conn
311 } do
312 user_one = insert(:user, is_admin: true)
313 user_two = insert(:user, is_admin: true)
314
315 conn =
316 conn
317 |> put_req_header("accept", "application/json")
318 |> delete("/api/pleroma/admin/users/permission_group/admin", %{
319 nicknames: [user_one.nickname, user_two.nickname]
320 })
321
322 assert json_response(conn, 200) == %{"is_admin" => false}
323
324 log_entry = Repo.one(ModerationLog)
325
326 assert ModerationLog.get_log_entry_message(log_entry) ==
327 "@#{admin.nickname} revoked admin role from @#{user_one.nickname}, @#{
328 user_two.nickname
329 }"
330 end
331 end
332
333 test "/api/pleroma/admin/users/:nickname/password_reset", %{conn: conn} do
334 user = insert(:user)
335
336 conn =
337 conn
338 |> put_req_header("accept", "application/json")
339 |> get("/api/pleroma/admin/users/#{user.nickname}/password_reset")
340
341 resp = json_response(conn, 200)
342
343 assert Regex.match?(~r/(http:\/\/|https:\/\/)/, resp["link"])
344 end
345
346 describe "PUT disable_mfa" do
347 test "returns 200 and disable 2fa", %{conn: conn} do
348 user =
349 insert(:user,
350 multi_factor_authentication_settings: %MFA.Settings{
351 enabled: true,
352 totp: %MFA.Settings.TOTP{secret: "otp_secret", confirmed: true}
353 }
354 )
355
356 response =
357 conn
358 |> put("/api/pleroma/admin/users/disable_mfa", %{nickname: user.nickname})
359 |> json_response(200)
360
361 assert response == user.nickname
362 mfa_settings = refresh_record(user).multi_factor_authentication_settings
363
364 refute mfa_settings.enabled
365 refute mfa_settings.totp.confirmed
366 end
367
368 test "returns 404 if user not found", %{conn: conn} do
369 response =
370 conn
371 |> put("/api/pleroma/admin/users/disable_mfa", %{nickname: "nickname"})
372 |> json_response(404)
373
374 assert response == %{"error" => "Not found"}
375 end
376 end
377
378 describe "GET /api/pleroma/admin/restart" do
379 setup do: clear_config(:configurable_from_database, true)
380
381 test "pleroma restarts", %{conn: conn} do
382 capture_log(fn ->
383 assert conn |> get("/api/pleroma/admin/restart") |> json_response(200) == %{}
384 end) =~ "pleroma restarted"
385
386 refute Restarter.Pleroma.need_reboot?()
387 end
388 end
389
390 test "need_reboot flag", %{conn: conn} do
391 assert conn
392 |> get("/api/pleroma/admin/need_reboot")
393 |> json_response(200) == %{"need_reboot" => false}
394
395 Restarter.Pleroma.need_reboot()
396
397 assert conn
398 |> get("/api/pleroma/admin/need_reboot")
399 |> json_response(200) == %{"need_reboot" => true}
400
401 on_exit(fn -> Restarter.Pleroma.refresh() end)
402 end
403
404 describe "GET /api/pleroma/admin/users/:nickname/statuses" do
405 setup do
406 user = insert(:user)
407
408 insert(:note_activity, user: user)
409 insert(:note_activity, user: user)
410 insert(:note_activity, user: user)
411
412 %{user: user}
413 end
414
415 test "renders user's statuses", %{conn: conn, user: user} do
416 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses")
417
418 assert %{"total" => 3, "activities" => activities} = json_response(conn, 200)
419 assert length(activities) == 3
420 end
421
422 test "renders user's statuses with pagination", %{conn: conn, user: user} do
423 %{"total" => 3, "activities" => [activity1]} =
424 conn
425 |> get("/api/pleroma/admin/users/#{user.nickname}/statuses?page_size=1&page=1")
426 |> json_response(200)
427
428 %{"total" => 3, "activities" => [activity2]} =
429 conn
430 |> get("/api/pleroma/admin/users/#{user.nickname}/statuses?page_size=1&page=2")
431 |> json_response(200)
432
433 refute activity1 == activity2
434 end
435
436 test "doesn't return private statuses by default", %{conn: conn, user: user} do
437 {:ok, _private_status} = CommonAPI.post(user, %{status: "private", visibility: "private"})
438
439 {:ok, _public_status} = CommonAPI.post(user, %{status: "public", visibility: "public"})
440
441 %{"total" => 4, "activities" => activities} =
442 conn
443 |> get("/api/pleroma/admin/users/#{user.nickname}/statuses")
444 |> json_response(200)
445
446 assert length(activities) == 4
447 end
448
449 test "returns private statuses with godmode on", %{conn: conn, user: user} do
450 {:ok, _private_status} = CommonAPI.post(user, %{status: "private", visibility: "private"})
451
452 {:ok, _public_status} = CommonAPI.post(user, %{status: "public", visibility: "public"})
453
454 %{"total" => 5, "activities" => activities} =
455 conn
456 |> get("/api/pleroma/admin/users/#{user.nickname}/statuses?godmode=true")
457 |> json_response(200)
458
459 assert length(activities) == 5
460 end
461
462 test "excludes reblogs by default", %{conn: conn, user: user} do
463 other_user = insert(:user)
464 {:ok, activity} = CommonAPI.post(user, %{status: "."})
465 {:ok, %Activity{}} = CommonAPI.repeat(activity.id, other_user)
466
467 assert %{"total" => 0, "activities" => []} ==
468 conn
469 |> get("/api/pleroma/admin/users/#{other_user.nickname}/statuses")
470 |> json_response(200)
471
472 assert %{"total" => 1, "activities" => [_]} =
473 conn
474 |> get(
475 "/api/pleroma/admin/users/#{other_user.nickname}/statuses?with_reblogs=true"
476 )
477 |> json_response(200)
478 end
479 end
480
481 describe "GET /api/pleroma/admin/users/:nickname/chats" do
482 setup do
483 user = insert(:user)
484 recipients = insert_list(3, :user)
485
486 Enum.each(recipients, fn recipient ->
487 CommonAPI.post_chat_message(user, recipient, "yo")
488 end)
489
490 %{user: user}
491 end
492
493 test "renders user's chats", %{conn: conn, user: user} do
494 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/chats")
495
496 assert json_response(conn, 200) |> length() == 3
497 end
498 end
499
500 describe "GET /api/pleroma/admin/users/:nickname/chats unauthorized" do
501 setup do
502 user = insert(:user)
503 recipient = insert(:user)
504 CommonAPI.post_chat_message(user, recipient, "yo")
505 %{conn: conn} = oauth_access(["read:chats"])
506 %{conn: conn, user: user}
507 end
508
509 test "returns 403", %{conn: conn, user: user} do
510 conn
511 |> get("/api/pleroma/admin/users/#{user.nickname}/chats")
512 |> json_response(403)
513 end
514 end
515
516 describe "GET /api/pleroma/admin/users/:nickname/chats unauthenticated" do
517 setup do
518 user = insert(:user)
519 recipient = insert(:user)
520 CommonAPI.post_chat_message(user, recipient, "yo")
521 %{conn: build_conn(), user: user}
522 end
523
524 test "returns 403", %{conn: conn, user: user} do
525 conn
526 |> get("/api/pleroma/admin/users/#{user.nickname}/chats")
527 |> json_response(403)
528 end
529 end
530
531 describe "GET /api/pleroma/admin/moderation_log" do
532 setup do
533 moderator = insert(:user, is_moderator: true)
534
535 %{moderator: moderator}
536 end
537
538 test "returns the log", %{conn: conn, admin: admin} do
539 Repo.insert(%ModerationLog{
540 data: %{
541 actor: %{
542 "id" => admin.id,
543 "nickname" => admin.nickname,
544 "type" => "user"
545 },
546 action: "relay_follow",
547 target: "https://example.org/relay"
548 },
549 inserted_at: NaiveDateTime.truncate(~N[2017-08-15 15:47:06.597036], :second)
550 })
551
552 Repo.insert(%ModerationLog{
553 data: %{
554 actor: %{
555 "id" => admin.id,
556 "nickname" => admin.nickname,
557 "type" => "user"
558 },
559 action: "relay_unfollow",
560 target: "https://example.org/relay"
561 },
562 inserted_at: NaiveDateTime.truncate(~N[2017-08-16 15:47:06.597036], :second)
563 })
564
565 conn = get(conn, "/api/pleroma/admin/moderation_log")
566
567 response = json_response(conn, 200)
568 [first_entry, second_entry] = response["items"]
569
570 assert response["total"] == 2
571 assert first_entry["data"]["action"] == "relay_unfollow"
572
573 assert first_entry["message"] ==
574 "@#{admin.nickname} unfollowed relay: https://example.org/relay"
575
576 assert second_entry["data"]["action"] == "relay_follow"
577
578 assert second_entry["message"] ==
579 "@#{admin.nickname} followed relay: https://example.org/relay"
580 end
581
582 test "returns the log with pagination", %{conn: conn, admin: admin} do
583 Repo.insert(%ModerationLog{
584 data: %{
585 actor: %{
586 "id" => admin.id,
587 "nickname" => admin.nickname,
588 "type" => "user"
589 },
590 action: "relay_follow",
591 target: "https://example.org/relay"
592 },
593 inserted_at: NaiveDateTime.truncate(~N[2017-08-15 15:47:06.597036], :second)
594 })
595
596 Repo.insert(%ModerationLog{
597 data: %{
598 actor: %{
599 "id" => admin.id,
600 "nickname" => admin.nickname,
601 "type" => "user"
602 },
603 action: "relay_unfollow",
604 target: "https://example.org/relay"
605 },
606 inserted_at: NaiveDateTime.truncate(~N[2017-08-16 15:47:06.597036], :second)
607 })
608
609 conn1 = get(conn, "/api/pleroma/admin/moderation_log?page_size=1&page=1")
610
611 response1 = json_response(conn1, 200)
612 [first_entry] = response1["items"]
613
614 assert response1["total"] == 2
615 assert response1["items"] |> length() == 1
616 assert first_entry["data"]["action"] == "relay_unfollow"
617
618 assert first_entry["message"] ==
619 "@#{admin.nickname} unfollowed relay: https://example.org/relay"
620
621 conn2 = get(conn, "/api/pleroma/admin/moderation_log?page_size=1&page=2")
622
623 response2 = json_response(conn2, 200)
624 [second_entry] = response2["items"]
625
626 assert response2["total"] == 2
627 assert response2["items"] |> length() == 1
628 assert second_entry["data"]["action"] == "relay_follow"
629
630 assert second_entry["message"] ==
631 "@#{admin.nickname} followed relay: https://example.org/relay"
632 end
633
634 test "filters log by date", %{conn: conn, admin: admin} do
635 first_date = "2017-08-15T15:47:06Z"
636 second_date = "2017-08-20T15:47:06Z"
637
638 Repo.insert(%ModerationLog{
639 data: %{
640 actor: %{
641 "id" => admin.id,
642 "nickname" => admin.nickname,
643 "type" => "user"
644 },
645 action: "relay_follow",
646 target: "https://example.org/relay"
647 },
648 inserted_at: NaiveDateTime.from_iso8601!(first_date)
649 })
650
651 Repo.insert(%ModerationLog{
652 data: %{
653 actor: %{
654 "id" => admin.id,
655 "nickname" => admin.nickname,
656 "type" => "user"
657 },
658 action: "relay_unfollow",
659 target: "https://example.org/relay"
660 },
661 inserted_at: NaiveDateTime.from_iso8601!(second_date)
662 })
663
664 conn1 =
665 get(
666 conn,
667 "/api/pleroma/admin/moderation_log?start_date=#{second_date}"
668 )
669
670 response1 = json_response(conn1, 200)
671 [first_entry] = response1["items"]
672
673 assert response1["total"] == 1
674 assert first_entry["data"]["action"] == "relay_unfollow"
675
676 assert first_entry["message"] ==
677 "@#{admin.nickname} unfollowed relay: https://example.org/relay"
678 end
679
680 test "returns log filtered by user", %{conn: conn, admin: admin, moderator: moderator} do
681 Repo.insert(%ModerationLog{
682 data: %{
683 actor: %{
684 "id" => admin.id,
685 "nickname" => admin.nickname,
686 "type" => "user"
687 },
688 action: "relay_follow",
689 target: "https://example.org/relay"
690 }
691 })
692
693 Repo.insert(%ModerationLog{
694 data: %{
695 actor: %{
696 "id" => moderator.id,
697 "nickname" => moderator.nickname,
698 "type" => "user"
699 },
700 action: "relay_unfollow",
701 target: "https://example.org/relay"
702 }
703 })
704
705 conn1 = get(conn, "/api/pleroma/admin/moderation_log?user_id=#{moderator.id}")
706
707 response1 = json_response(conn1, 200)
708 [first_entry] = response1["items"]
709
710 assert response1["total"] == 1
711 assert get_in(first_entry, ["data", "actor", "id"]) == moderator.id
712 end
713
714 test "returns log filtered by search", %{conn: conn, moderator: moderator} do
715 ModerationLog.insert_log(%{
716 actor: moderator,
717 action: "relay_follow",
718 target: "https://example.org/relay"
719 })
720
721 ModerationLog.insert_log(%{
722 actor: moderator,
723 action: "relay_unfollow",
724 target: "https://example.org/relay"
725 })
726
727 conn1 = get(conn, "/api/pleroma/admin/moderation_log?search=unfo")
728
729 response1 = json_response(conn1, 200)
730 [first_entry] = response1["items"]
731
732 assert response1["total"] == 1
733
734 assert get_in(first_entry, ["data", "message"]) ==
735 "@#{moderator.nickname} unfollowed relay: https://example.org/relay"
736 end
737 end
738
739 test "gets a remote users when [:instance, :limit_to_local_content] is set to :unauthenticated",
740 %{conn: conn} do
741 clear_config(Pleroma.Config.get([:instance, :limit_to_local_content]), :unauthenticated)
742 user = insert(:user, %{local: false, nickname: "u@peer1.com"})
743 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/credentials")
744
745 assert json_response(conn, 200)
746 end
747
748 describe "GET /users/:nickname/credentials" do
749 test "gets the user credentials", %{conn: conn} do
750 user = insert(:user)
751 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/credentials")
752
753 response = assert json_response(conn, 200)
754 assert response["email"] == user.email
755 end
756
757 test "returns 403 if requested by a non-admin" do
758 user = insert(:user)
759
760 conn =
761 build_conn()
762 |> assign(:user, user)
763 |> get("/api/pleroma/admin/users/#{user.nickname}/credentials")
764
765 assert json_response(conn, :forbidden)
766 end
767 end
768
769 describe "PATCH /users/:nickname/credentials" do
770 setup do
771 user = insert(:user)
772 [user: user]
773 end
774
775 test "changes password and email", %{conn: conn, admin: admin, user: user} do
776 assert user.password_reset_pending == false
777
778 conn =
779 patch(conn, "/api/pleroma/admin/users/#{user.nickname}/credentials", %{
780 "password" => "new_password",
781 "email" => "new_email@example.com",
782 "name" => "new_name"
783 })
784
785 assert json_response(conn, 200) == %{"status" => "success"}
786
787 ObanHelpers.perform_all()
788
789 updated_user = User.get_by_id(user.id)
790
791 assert updated_user.email == "new_email@example.com"
792 assert updated_user.name == "new_name"
793 assert updated_user.password_hash != user.password_hash
794 assert updated_user.password_reset_pending == true
795
796 [log_entry2, log_entry1] = ModerationLog |> Repo.all() |> Enum.sort()
797
798 assert ModerationLog.get_log_entry_message(log_entry1) ==
799 "@#{admin.nickname} updated users: @#{user.nickname}"
800
801 assert ModerationLog.get_log_entry_message(log_entry2) ==
802 "@#{admin.nickname} forced password reset for users: @#{user.nickname}"
803 end
804
805 test "returns 403 if requested by a non-admin", %{user: user} do
806 conn =
807 build_conn()
808 |> assign(:user, user)
809 |> patch("/api/pleroma/admin/users/#{user.nickname}/credentials", %{
810 "password" => "new_password",
811 "email" => "new_email@example.com",
812 "name" => "new_name"
813 })
814
815 assert json_response(conn, :forbidden)
816 end
817
818 test "changes actor type from permitted list", %{conn: conn, user: user} do
819 assert user.actor_type == "Person"
820
821 assert patch(conn, "/api/pleroma/admin/users/#{user.nickname}/credentials", %{
822 "actor_type" => "Service"
823 })
824 |> json_response(200) == %{"status" => "success"}
825
826 updated_user = User.get_by_id(user.id)
827
828 assert updated_user.actor_type == "Service"
829
830 assert patch(conn, "/api/pleroma/admin/users/#{user.nickname}/credentials", %{
831 "actor_type" => "Application"
832 })
833 |> json_response(400) == %{"errors" => %{"actor_type" => "is invalid"}}
834 end
835
836 test "update non existing user", %{conn: conn} do
837 assert patch(conn, "/api/pleroma/admin/users/non-existing/credentials", %{
838 "password" => "new_password"
839 })
840 |> json_response(404) == %{"error" => "Not found"}
841 end
842 end
843
844 describe "PATCH /users/:nickname/force_password_reset" do
845 test "sets password_reset_pending to true", %{conn: conn} do
846 user = insert(:user)
847 assert user.password_reset_pending == false
848
849 conn =
850 patch(conn, "/api/pleroma/admin/users/force_password_reset", %{nicknames: [user.nickname]})
851
852 assert empty_json_response(conn) == ""
853
854 ObanHelpers.perform_all()
855
856 assert User.get_by_id(user.id).password_reset_pending == true
857 end
858 end
859
860 describe "instances" do
861 test "GET /instances/:instance/statuses", %{conn: conn} do
862 user = insert(:user, local: false, ap_id: "https://archae.me/users/archaeme")
863 user2 = insert(:user, local: false, ap_id: "https://test.com/users/test")
864 insert_pair(:note_activity, user: user)
865 activity = insert(:note_activity, user: user2)
866
867 %{"total" => 2, "activities" => activities} =
868 conn |> get("/api/pleroma/admin/instances/archae.me/statuses") |> json_response(200)
869
870 assert length(activities) == 2
871
872 %{"total" => 1, "activities" => [_]} =
873 conn |> get("/api/pleroma/admin/instances/test.com/statuses") |> json_response(200)
874
875 %{"total" => 0, "activities" => []} =
876 conn |> get("/api/pleroma/admin/instances/nonexistent.com/statuses") |> json_response(200)
877
878 CommonAPI.repeat(activity.id, user)
879
880 %{"total" => 2, "activities" => activities} =
881 conn |> get("/api/pleroma/admin/instances/archae.me/statuses") |> json_response(200)
882
883 assert length(activities) == 2
884
885 %{"total" => 3, "activities" => activities} =
886 conn
887 |> get("/api/pleroma/admin/instances/archae.me/statuses?with_reblogs=true")
888 |> json_response(200)
889
890 assert length(activities) == 3
891 end
892 end
893
894 describe "PATCH /confirm_email" do
895 test "it confirms emails of two users", %{conn: conn, admin: admin} do
896 [first_user, second_user] = insert_pair(:user, is_confirmed: false)
897
898 refute first_user.is_confirmed
899 refute second_user.is_confirmed
900
901 ret_conn =
902 patch(conn, "/api/pleroma/admin/users/confirm_email", %{
903 nicknames: [
904 first_user.nickname,
905 second_user.nickname
906 ]
907 })
908
909 assert ret_conn.status == 200
910
911 first_user = User.get_by_id(first_user.id)
912 second_user = User.get_by_id(second_user.id)
913
914 assert first_user.is_confirmed
915 assert second_user.is_confirmed
916
917 log_entry = Repo.one(ModerationLog)
918
919 assert ModerationLog.get_log_entry_message(log_entry) ==
920 "@#{admin.nickname} confirmed email for users: @#{first_user.nickname}, @#{
921 second_user.nickname
922 }"
923 end
924 end
925
926 describe "PATCH /resend_confirmation_email" do
927 test "it resend emails for two users", %{conn: conn, admin: admin} do
928 [first_user, second_user] = insert_pair(:user, is_confirmed: false)
929
930 ret_conn =
931 patch(conn, "/api/pleroma/admin/users/resend_confirmation_email", %{
932 nicknames: [
933 first_user.nickname,
934 second_user.nickname
935 ]
936 })
937
938 assert ret_conn.status == 200
939
940 log_entry = Repo.one(ModerationLog)
941
942 assert ModerationLog.get_log_entry_message(log_entry) ==
943 "@#{admin.nickname} re-sent confirmation email for users: @#{first_user.nickname}, @#{
944 second_user.nickname
945 }"
946
947 ObanHelpers.perform_all()
948
949 Pleroma.Emails.UserEmail.account_confirmation_email(first_user)
950 # temporary hackney fix until hackney max_connections bug is fixed
951 # https://git.pleroma.social/pleroma/pleroma/-/issues/2101
952 |> Swoosh.Email.put_private(:hackney_options, ssl_options: [versions: [:"tlsv1.2"]])
953 |> assert_email_sent()
954 end
955 end
956
957 describe "/api/pleroma/admin/stats" do
958 test "status visibility count", %{conn: conn} do
959 user = insert(:user)
960 CommonAPI.post(user, %{visibility: "public", status: "hey"})
961 CommonAPI.post(user, %{visibility: "unlisted", status: "hey"})
962 CommonAPI.post(user, %{visibility: "unlisted", status: "hey"})
963
964 response =
965 conn
966 |> get("/api/pleroma/admin/stats")
967 |> json_response(200)
968
969 assert %{"direct" => 0, "private" => 0, "public" => 1, "unlisted" => 2} =
970 response["status_visibility"]
971 end
972
973 test "by instance", %{conn: conn} do
974 user1 = insert(:user)
975 instance2 = "instance2.tld"
976 user2 = insert(:user, %{ap_id: "https://#{instance2}/@actor"})
977
978 CommonAPI.post(user1, %{visibility: "public", status: "hey"})
979 CommonAPI.post(user2, %{visibility: "unlisted", status: "hey"})
980 CommonAPI.post(user2, %{visibility: "private", status: "hey"})
981
982 response =
983 conn
984 |> get("/api/pleroma/admin/stats", instance: instance2)
985 |> json_response(200)
986
987 assert %{"direct" => 0, "private" => 1, "public" => 0, "unlisted" => 1} =
988 response["status_visibility"]
989 end
990 end
991
992 describe "/api/pleroma/backups" do
993 test "it creates a backup", %{conn: conn} do
994 admin = %{id: admin_id, nickname: admin_nickname} = insert(:user, is_admin: true)
995 token = insert(:oauth_admin_token, user: admin)
996 user = %{id: user_id, nickname: user_nickname} = insert(:user)
997
998 assert "" ==
999 conn
1000 |> assign(:user, admin)
1001 |> assign(:token, token)
1002 |> post("/api/pleroma/admin/backups", %{nickname: user.nickname})
1003 |> json_response(200)
1004
1005 assert [backup] = Repo.all(Pleroma.User.Backup)
1006
1007 ObanHelpers.perform_all()
1008
1009 email = Pleroma.Emails.UserEmail.backup_is_ready_email(backup, admin.id)
1010
1011 assert String.contains?(email.html_body, "Admin @#{admin.nickname} requested a full backup")
1012 assert_email_sent(to: {user.name, user.email}, html_body: email.html_body)
1013
1014 log_message = "@#{admin_nickname} requested account backup for @#{user_nickname}"
1015
1016 assert [
1017 %{
1018 data: %{
1019 "action" => "create_backup",
1020 "actor" => %{
1021 "id" => ^admin_id,
1022 "nickname" => ^admin_nickname
1023 },
1024 "message" => ^log_message,
1025 "subject" => %{
1026 "id" => ^user_id,
1027 "nickname" => ^user_nickname
1028 }
1029 }
1030 }
1031 ] = Pleroma.ModerationLog |> Repo.all()
1032 end
1033
1034 test "it doesn't limit admins", %{conn: conn} do
1035 admin = insert(:user, is_admin: true)
1036 token = insert(:oauth_admin_token, user: admin)
1037 user = insert(:user)
1038
1039 assert "" ==
1040 conn
1041 |> assign(:user, admin)
1042 |> assign(:token, token)
1043 |> post("/api/pleroma/admin/backups", %{nickname: user.nickname})
1044 |> json_response(200)
1045
1046 assert [_backup] = Repo.all(Pleroma.User.Backup)
1047
1048 assert "" ==
1049 conn
1050 |> assign(:user, admin)
1051 |> assign(:token, token)
1052 |> post("/api/pleroma/admin/backups", %{nickname: user.nickname})
1053 |> json_response(200)
1054
1055 assert Repo.aggregate(Pleroma.User.Backup, :count) == 2
1056 end
1057 end
1058 end
1059
1060 # Needed for testing
1061 defmodule Pleroma.Web.Endpoint.NotReal do
1062 end
1063
1064 defmodule Pleroma.Captcha.NotReal do
1065 end