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