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