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