Set sum types in query
[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" => [":regex1", "~r/https:\/\/example.com/"]},
2513 %{"tuple" => [":regex2", "~r/https:\/\/example.com/u"]},
2514 %{"tuple" => [":regex3", "~r/https:\/\/example.com/i"]},
2515 %{"tuple" => [":regex4", "~r/https:\/\/example.com/s"]},
2516 %{"tuple" => [":name", "Pleroma"]}
2517 ]
2518 }
2519 ]
2520 })
2521
2522 assert Config.get([Pleroma.Captcha.NotReal, :name]) == "Pleroma"
2523
2524 assert json_response(conn, 200) == %{
2525 "configs" => [
2526 %{
2527 "group" => ":pleroma",
2528 "key" => "Pleroma.Captcha.NotReal",
2529 "value" => [
2530 %{"tuple" => [":enabled", false]},
2531 %{"tuple" => [":method", "Pleroma.Captcha.Kocaptcha"]},
2532 %{"tuple" => [":seconds_valid", 60]},
2533 %{"tuple" => [":path", ""]},
2534 %{"tuple" => [":key1", nil]},
2535 %{"tuple" => [":regex1", "~r/https:\\/\\/example.com/"]},
2536 %{"tuple" => [":regex2", "~r/https:\\/\\/example.com/u"]},
2537 %{"tuple" => [":regex3", "~r/https:\\/\\/example.com/i"]},
2538 %{"tuple" => [":regex4", "~r/https:\\/\\/example.com/s"]},
2539 %{"tuple" => [":name", "Pleroma"]}
2540 ],
2541 "db" => [
2542 ":enabled",
2543 ":method",
2544 ":seconds_valid",
2545 ":path",
2546 ":key1",
2547 ":regex1",
2548 ":regex2",
2549 ":regex3",
2550 ":regex4",
2551 ":name"
2552 ]
2553 }
2554 ]
2555 }
2556 end
2557
2558 test "tuples with more than two values", %{conn: conn} do
2559 conn =
2560 post(conn, "/api/pleroma/admin/config", %{
2561 configs: [
2562 %{
2563 "group" => ":pleroma",
2564 "key" => "Pleroma.Web.Endpoint.NotReal",
2565 "value" => [
2566 %{
2567 "tuple" => [
2568 ":http",
2569 [
2570 %{
2571 "tuple" => [
2572 ":key2",
2573 [
2574 %{
2575 "tuple" => [
2576 ":_",
2577 [
2578 %{
2579 "tuple" => [
2580 "/api/v1/streaming",
2581 "Pleroma.Web.MastodonAPI.WebsocketHandler",
2582 []
2583 ]
2584 },
2585 %{
2586 "tuple" => [
2587 "/websocket",
2588 "Phoenix.Endpoint.CowboyWebSocket",
2589 %{
2590 "tuple" => [
2591 "Phoenix.Transports.WebSocket",
2592 %{
2593 "tuple" => [
2594 "Pleroma.Web.Endpoint",
2595 "Pleroma.Web.UserSocket",
2596 []
2597 ]
2598 }
2599 ]
2600 }
2601 ]
2602 },
2603 %{
2604 "tuple" => [
2605 ":_",
2606 "Phoenix.Endpoint.Cowboy2Handler",
2607 %{"tuple" => ["Pleroma.Web.Endpoint", []]}
2608 ]
2609 }
2610 ]
2611 ]
2612 }
2613 ]
2614 ]
2615 }
2616 ]
2617 ]
2618 }
2619 ]
2620 }
2621 ]
2622 })
2623
2624 assert json_response(conn, 200) == %{
2625 "configs" => [
2626 %{
2627 "group" => ":pleroma",
2628 "key" => "Pleroma.Web.Endpoint.NotReal",
2629 "value" => [
2630 %{
2631 "tuple" => [
2632 ":http",
2633 [
2634 %{
2635 "tuple" => [
2636 ":key2",
2637 [
2638 %{
2639 "tuple" => [
2640 ":_",
2641 [
2642 %{
2643 "tuple" => [
2644 "/api/v1/streaming",
2645 "Pleroma.Web.MastodonAPI.WebsocketHandler",
2646 []
2647 ]
2648 },
2649 %{
2650 "tuple" => [
2651 "/websocket",
2652 "Phoenix.Endpoint.CowboyWebSocket",
2653 %{
2654 "tuple" => [
2655 "Phoenix.Transports.WebSocket",
2656 %{
2657 "tuple" => [
2658 "Pleroma.Web.Endpoint",
2659 "Pleroma.Web.UserSocket",
2660 []
2661 ]
2662 }
2663 ]
2664 }
2665 ]
2666 },
2667 %{
2668 "tuple" => [
2669 ":_",
2670 "Phoenix.Endpoint.Cowboy2Handler",
2671 %{"tuple" => ["Pleroma.Web.Endpoint", []]}
2672 ]
2673 }
2674 ]
2675 ]
2676 }
2677 ]
2678 ]
2679 }
2680 ]
2681 ]
2682 }
2683 ],
2684 "db" => [":http"]
2685 }
2686 ]
2687 }
2688 end
2689
2690 test "settings with nesting map", %{conn: conn} do
2691 conn =
2692 post(conn, "/api/pleroma/admin/config", %{
2693 configs: [
2694 %{
2695 "group" => ":pleroma",
2696 "key" => ":key1",
2697 "value" => [
2698 %{"tuple" => [":key2", "some_val"]},
2699 %{
2700 "tuple" => [
2701 ":key3",
2702 %{
2703 ":max_options" => 20,
2704 ":max_option_chars" => 200,
2705 ":min_expiration" => 0,
2706 ":max_expiration" => 31_536_000,
2707 "nested" => %{
2708 ":max_options" => 20,
2709 ":max_option_chars" => 200,
2710 ":min_expiration" => 0,
2711 ":max_expiration" => 31_536_000
2712 }
2713 }
2714 ]
2715 }
2716 ]
2717 }
2718 ]
2719 })
2720
2721 assert json_response(conn, 200) ==
2722 %{
2723 "configs" => [
2724 %{
2725 "group" => ":pleroma",
2726 "key" => ":key1",
2727 "value" => [
2728 %{"tuple" => [":key2", "some_val"]},
2729 %{
2730 "tuple" => [
2731 ":key3",
2732 %{
2733 ":max_expiration" => 31_536_000,
2734 ":max_option_chars" => 200,
2735 ":max_options" => 20,
2736 ":min_expiration" => 0,
2737 "nested" => %{
2738 ":max_expiration" => 31_536_000,
2739 ":max_option_chars" => 200,
2740 ":max_options" => 20,
2741 ":min_expiration" => 0
2742 }
2743 }
2744 ]
2745 }
2746 ],
2747 "db" => [":key2", ":key3"]
2748 }
2749 ]
2750 }
2751 end
2752
2753 test "value as map", %{conn: conn} do
2754 conn =
2755 post(conn, "/api/pleroma/admin/config", %{
2756 configs: [
2757 %{
2758 "group" => ":pleroma",
2759 "key" => ":key1",
2760 "value" => %{"key" => "some_val"}
2761 }
2762 ]
2763 })
2764
2765 assert json_response(conn, 200) ==
2766 %{
2767 "configs" => [
2768 %{
2769 "group" => ":pleroma",
2770 "key" => ":key1",
2771 "value" => %{"key" => "some_val"},
2772 "db" => [":key1"]
2773 }
2774 ]
2775 }
2776 end
2777
2778 test "queues key as atom", %{conn: conn} do
2779 conn =
2780 post(conn, "/api/pleroma/admin/config", %{
2781 configs: [
2782 %{
2783 "group" => ":oban",
2784 "key" => ":queues",
2785 "value" => [
2786 %{"tuple" => [":federator_incoming", 50]},
2787 %{"tuple" => [":federator_outgoing", 50]},
2788 %{"tuple" => [":web_push", 50]},
2789 %{"tuple" => [":mailer", 10]},
2790 %{"tuple" => [":transmogrifier", 20]},
2791 %{"tuple" => [":scheduled_activities", 10]},
2792 %{"tuple" => [":background", 5]}
2793 ]
2794 }
2795 ]
2796 })
2797
2798 assert json_response(conn, 200) == %{
2799 "configs" => [
2800 %{
2801 "group" => ":oban",
2802 "key" => ":queues",
2803 "value" => [
2804 %{"tuple" => [":federator_incoming", 50]},
2805 %{"tuple" => [":federator_outgoing", 50]},
2806 %{"tuple" => [":web_push", 50]},
2807 %{"tuple" => [":mailer", 10]},
2808 %{"tuple" => [":transmogrifier", 20]},
2809 %{"tuple" => [":scheduled_activities", 10]},
2810 %{"tuple" => [":background", 5]}
2811 ],
2812 "db" => [
2813 ":federator_incoming",
2814 ":federator_outgoing",
2815 ":web_push",
2816 ":mailer",
2817 ":transmogrifier",
2818 ":scheduled_activities",
2819 ":background"
2820 ]
2821 }
2822 ]
2823 }
2824 end
2825
2826 test "delete part of settings by atom subkeys", %{conn: conn} do
2827 config =
2828 insert(:config,
2829 key: ":keyaa1",
2830 value: :erlang.term_to_binary(subkey1: "val1", subkey2: "val2", subkey3: "val3")
2831 )
2832
2833 conn =
2834 post(conn, "/api/pleroma/admin/config", %{
2835 configs: [
2836 %{
2837 group: config.group,
2838 key: config.key,
2839 subkeys: [":subkey1", ":subkey3"],
2840 delete: true
2841 }
2842 ]
2843 })
2844
2845 assert json_response(conn, 200) == %{
2846 "configs" => [
2847 %{
2848 "group" => ":pleroma",
2849 "key" => ":keyaa1",
2850 "value" => [%{"tuple" => [":subkey2", "val2"]}],
2851 "db" => [":subkey2"]
2852 }
2853 ]
2854 }
2855 end
2856
2857 test "proxy tuple localhost", %{conn: conn} do
2858 conn =
2859 post(conn, "/api/pleroma/admin/config", %{
2860 configs: [
2861 %{
2862 group: ":pleroma",
2863 key: ":http",
2864 value: [
2865 %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "localhost", 1234]}]},
2866 %{"tuple" => [":send_user_agent", false]}
2867 ]
2868 }
2869 ]
2870 })
2871
2872 assert json_response(conn, 200) == %{
2873 "configs" => [
2874 %{
2875 "group" => ":pleroma",
2876 "key" => ":http",
2877 "value" => [
2878 %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "localhost", 1234]}]},
2879 %{"tuple" => [":send_user_agent", false]}
2880 ],
2881 "db" => [":proxy_url", ":send_user_agent"]
2882 }
2883 ]
2884 }
2885 end
2886
2887 test "proxy tuple domain", %{conn: conn} do
2888 conn =
2889 post(conn, "/api/pleroma/admin/config", %{
2890 configs: [
2891 %{
2892 group: ":pleroma",
2893 key: ":http",
2894 value: [
2895 %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "domain.com", 1234]}]},
2896 %{"tuple" => [":send_user_agent", false]}
2897 ]
2898 }
2899 ]
2900 })
2901
2902 assert json_response(conn, 200) == %{
2903 "configs" => [
2904 %{
2905 "group" => ":pleroma",
2906 "key" => ":http",
2907 "value" => [
2908 %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "domain.com", 1234]}]},
2909 %{"tuple" => [":send_user_agent", false]}
2910 ],
2911 "db" => [":proxy_url", ":send_user_agent"]
2912 }
2913 ]
2914 }
2915 end
2916
2917 test "proxy tuple ip", %{conn: conn} do
2918 conn =
2919 post(conn, "/api/pleroma/admin/config", %{
2920 configs: [
2921 %{
2922 group: ":pleroma",
2923 key: ":http",
2924 value: [
2925 %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "127.0.0.1", 1234]}]},
2926 %{"tuple" => [":send_user_agent", false]}
2927 ]
2928 }
2929 ]
2930 })
2931
2932 assert json_response(conn, 200) == %{
2933 "configs" => [
2934 %{
2935 "group" => ":pleroma",
2936 "key" => ":http",
2937 "value" => [
2938 %{"tuple" => [":proxy_url", %{"tuple" => [":socks5", "127.0.0.1", 1234]}]},
2939 %{"tuple" => [":send_user_agent", false]}
2940 ],
2941 "db" => [":proxy_url", ":send_user_agent"]
2942 }
2943 ]
2944 }
2945 end
2946 end
2947
2948 describe "GET /api/pleroma/admin/restart" do
2949 setup do: clear_config(:configurable_from_database, true)
2950
2951 test "pleroma restarts", %{conn: conn} do
2952 capture_log(fn ->
2953 assert conn |> get("/api/pleroma/admin/restart") |> json_response(200) == %{}
2954 end) =~ "pleroma restarted"
2955
2956 refute Restarter.Pleroma.need_reboot?()
2957 end
2958 end
2959
2960 test "need_reboot flag", %{conn: conn} do
2961 assert conn
2962 |> get("/api/pleroma/admin/need_reboot")
2963 |> json_response(200) == %{"need_reboot" => false}
2964
2965 Restarter.Pleroma.need_reboot()
2966
2967 assert conn
2968 |> get("/api/pleroma/admin/need_reboot")
2969 |> json_response(200) == %{"need_reboot" => true}
2970
2971 on_exit(fn -> Restarter.Pleroma.refresh() end)
2972 end
2973
2974 describe "GET /api/pleroma/admin/statuses" do
2975 test "returns all public and unlisted statuses", %{conn: conn, admin: admin} do
2976 blocked = insert(:user)
2977 user = insert(:user)
2978 User.block(admin, blocked)
2979
2980 {:ok, _} =
2981 CommonAPI.post(user, %{"status" => "@#{admin.nickname}", "visibility" => "direct"})
2982
2983 {:ok, _} = CommonAPI.post(user, %{"status" => ".", "visibility" => "unlisted"})
2984 {:ok, _} = CommonAPI.post(user, %{"status" => ".", "visibility" => "private"})
2985 {:ok, _} = CommonAPI.post(user, %{"status" => ".", "visibility" => "public"})
2986 {:ok, _} = CommonAPI.post(blocked, %{"status" => ".", "visibility" => "public"})
2987
2988 response =
2989 conn
2990 |> get("/api/pleroma/admin/statuses")
2991 |> json_response(200)
2992
2993 refute "private" in Enum.map(response, & &1["visibility"])
2994 assert length(response) == 3
2995 end
2996
2997 test "returns only local statuses with local_only on", %{conn: conn} do
2998 user = insert(:user)
2999 remote_user = insert(:user, local: false, nickname: "archaeme@archae.me")
3000 insert(:note_activity, user: user, local: true)
3001 insert(:note_activity, user: remote_user, local: false)
3002
3003 response =
3004 conn
3005 |> get("/api/pleroma/admin/statuses?local_only=true")
3006 |> json_response(200)
3007
3008 assert length(response) == 1
3009 end
3010
3011 test "returns private and direct statuses with godmode on", %{conn: conn, admin: admin} do
3012 user = insert(:user)
3013
3014 {:ok, _} =
3015 CommonAPI.post(user, %{"status" => "@#{admin.nickname}", "visibility" => "direct"})
3016
3017 {:ok, _} = CommonAPI.post(user, %{"status" => ".", "visibility" => "private"})
3018 {:ok, _} = CommonAPI.post(user, %{"status" => ".", "visibility" => "public"})
3019 conn = get(conn, "/api/pleroma/admin/statuses?godmode=true")
3020 assert json_response(conn, 200) |> length() == 3
3021 end
3022 end
3023
3024 describe "GET /api/pleroma/admin/users/:nickname/statuses" do
3025 setup do
3026 user = insert(:user)
3027
3028 date1 = (DateTime.to_unix(DateTime.utc_now()) + 2000) |> DateTime.from_unix!()
3029 date2 = (DateTime.to_unix(DateTime.utc_now()) + 1000) |> DateTime.from_unix!()
3030 date3 = (DateTime.to_unix(DateTime.utc_now()) + 3000) |> DateTime.from_unix!()
3031
3032 insert(:note_activity, user: user, published: date1)
3033 insert(:note_activity, user: user, published: date2)
3034 insert(:note_activity, user: user, published: date3)
3035
3036 %{user: user}
3037 end
3038
3039 test "renders user's statuses", %{conn: conn, user: user} do
3040 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses")
3041
3042 assert json_response(conn, 200) |> length() == 3
3043 end
3044
3045 test "renders user's statuses with a limit", %{conn: conn, user: user} do
3046 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses?page_size=2")
3047
3048 assert json_response(conn, 200) |> length() == 2
3049 end
3050
3051 test "doesn't return private statuses by default", %{conn: conn, user: user} do
3052 {:ok, _private_status} =
3053 CommonAPI.post(user, %{"status" => "private", "visibility" => "private"})
3054
3055 {:ok, _public_status} =
3056 CommonAPI.post(user, %{"status" => "public", "visibility" => "public"})
3057
3058 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses")
3059
3060 assert json_response(conn, 200) |> length() == 4
3061 end
3062
3063 test "returns private statuses with godmode on", %{conn: conn, user: user} do
3064 {:ok, _private_status} =
3065 CommonAPI.post(user, %{"status" => "private", "visibility" => "private"})
3066
3067 {:ok, _public_status} =
3068 CommonAPI.post(user, %{"status" => "public", "visibility" => "public"})
3069
3070 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/statuses?godmode=true")
3071
3072 assert json_response(conn, 200) |> length() == 5
3073 end
3074
3075 test "excludes reblogs by default", %{conn: conn, user: user} do
3076 other_user = insert(:user)
3077 {:ok, activity} = CommonAPI.post(user, %{"status" => "."})
3078 {:ok, %Activity{}, _} = CommonAPI.repeat(activity.id, other_user)
3079
3080 conn_res = get(conn, "/api/pleroma/admin/users/#{other_user.nickname}/statuses")
3081 assert json_response(conn_res, 200) |> length() == 0
3082
3083 conn_res =
3084 get(conn, "/api/pleroma/admin/users/#{other_user.nickname}/statuses?with_reblogs=true")
3085
3086 assert json_response(conn_res, 200) |> length() == 1
3087 end
3088 end
3089
3090 describe "GET /api/pleroma/admin/moderation_log" do
3091 setup do
3092 moderator = insert(:user, is_moderator: true)
3093
3094 %{moderator: moderator}
3095 end
3096
3097 test "returns the log", %{conn: conn, admin: admin} do
3098 Repo.insert(%ModerationLog{
3099 data: %{
3100 actor: %{
3101 "id" => admin.id,
3102 "nickname" => admin.nickname,
3103 "type" => "user"
3104 },
3105 action: "relay_follow",
3106 target: "https://example.org/relay"
3107 },
3108 inserted_at: NaiveDateTime.truncate(~N[2017-08-15 15:47:06.597036], :second)
3109 })
3110
3111 Repo.insert(%ModerationLog{
3112 data: %{
3113 actor: %{
3114 "id" => admin.id,
3115 "nickname" => admin.nickname,
3116 "type" => "user"
3117 },
3118 action: "relay_unfollow",
3119 target: "https://example.org/relay"
3120 },
3121 inserted_at: NaiveDateTime.truncate(~N[2017-08-16 15:47:06.597036], :second)
3122 })
3123
3124 conn = get(conn, "/api/pleroma/admin/moderation_log")
3125
3126 response = json_response(conn, 200)
3127 [first_entry, second_entry] = response["items"]
3128
3129 assert response["total"] == 2
3130 assert first_entry["data"]["action"] == "relay_unfollow"
3131
3132 assert first_entry["message"] ==
3133 "@#{admin.nickname} unfollowed relay: https://example.org/relay"
3134
3135 assert second_entry["data"]["action"] == "relay_follow"
3136
3137 assert second_entry["message"] ==
3138 "@#{admin.nickname} followed relay: https://example.org/relay"
3139 end
3140
3141 test "returns the log with pagination", %{conn: conn, admin: admin} do
3142 Repo.insert(%ModerationLog{
3143 data: %{
3144 actor: %{
3145 "id" => admin.id,
3146 "nickname" => admin.nickname,
3147 "type" => "user"
3148 },
3149 action: "relay_follow",
3150 target: "https://example.org/relay"
3151 },
3152 inserted_at: NaiveDateTime.truncate(~N[2017-08-15 15:47:06.597036], :second)
3153 })
3154
3155 Repo.insert(%ModerationLog{
3156 data: %{
3157 actor: %{
3158 "id" => admin.id,
3159 "nickname" => admin.nickname,
3160 "type" => "user"
3161 },
3162 action: "relay_unfollow",
3163 target: "https://example.org/relay"
3164 },
3165 inserted_at: NaiveDateTime.truncate(~N[2017-08-16 15:47:06.597036], :second)
3166 })
3167
3168 conn1 = get(conn, "/api/pleroma/admin/moderation_log?page_size=1&page=1")
3169
3170 response1 = json_response(conn1, 200)
3171 [first_entry] = response1["items"]
3172
3173 assert response1["total"] == 2
3174 assert response1["items"] |> length() == 1
3175 assert first_entry["data"]["action"] == "relay_unfollow"
3176
3177 assert first_entry["message"] ==
3178 "@#{admin.nickname} unfollowed relay: https://example.org/relay"
3179
3180 conn2 = get(conn, "/api/pleroma/admin/moderation_log?page_size=1&page=2")
3181
3182 response2 = json_response(conn2, 200)
3183 [second_entry] = response2["items"]
3184
3185 assert response2["total"] == 2
3186 assert response2["items"] |> length() == 1
3187 assert second_entry["data"]["action"] == "relay_follow"
3188
3189 assert second_entry["message"] ==
3190 "@#{admin.nickname} followed relay: https://example.org/relay"
3191 end
3192
3193 test "filters log by date", %{conn: conn, admin: admin} do
3194 first_date = "2017-08-15T15:47:06Z"
3195 second_date = "2017-08-20T15:47:06Z"
3196
3197 Repo.insert(%ModerationLog{
3198 data: %{
3199 actor: %{
3200 "id" => admin.id,
3201 "nickname" => admin.nickname,
3202 "type" => "user"
3203 },
3204 action: "relay_follow",
3205 target: "https://example.org/relay"
3206 },
3207 inserted_at: NaiveDateTime.from_iso8601!(first_date)
3208 })
3209
3210 Repo.insert(%ModerationLog{
3211 data: %{
3212 actor: %{
3213 "id" => admin.id,
3214 "nickname" => admin.nickname,
3215 "type" => "user"
3216 },
3217 action: "relay_unfollow",
3218 target: "https://example.org/relay"
3219 },
3220 inserted_at: NaiveDateTime.from_iso8601!(second_date)
3221 })
3222
3223 conn1 =
3224 get(
3225 conn,
3226 "/api/pleroma/admin/moderation_log?start_date=#{second_date}"
3227 )
3228
3229 response1 = json_response(conn1, 200)
3230 [first_entry] = response1["items"]
3231
3232 assert response1["total"] == 1
3233 assert first_entry["data"]["action"] == "relay_unfollow"
3234
3235 assert first_entry["message"] ==
3236 "@#{admin.nickname} unfollowed relay: https://example.org/relay"
3237 end
3238
3239 test "returns log filtered by user", %{conn: conn, admin: admin, moderator: moderator} do
3240 Repo.insert(%ModerationLog{
3241 data: %{
3242 actor: %{
3243 "id" => admin.id,
3244 "nickname" => admin.nickname,
3245 "type" => "user"
3246 },
3247 action: "relay_follow",
3248 target: "https://example.org/relay"
3249 }
3250 })
3251
3252 Repo.insert(%ModerationLog{
3253 data: %{
3254 actor: %{
3255 "id" => moderator.id,
3256 "nickname" => moderator.nickname,
3257 "type" => "user"
3258 },
3259 action: "relay_unfollow",
3260 target: "https://example.org/relay"
3261 }
3262 })
3263
3264 conn1 = get(conn, "/api/pleroma/admin/moderation_log?user_id=#{moderator.id}")
3265
3266 response1 = json_response(conn1, 200)
3267 [first_entry] = response1["items"]
3268
3269 assert response1["total"] == 1
3270 assert get_in(first_entry, ["data", "actor", "id"]) == moderator.id
3271 end
3272
3273 test "returns log filtered by search", %{conn: conn, moderator: moderator} do
3274 ModerationLog.insert_log(%{
3275 actor: moderator,
3276 action: "relay_follow",
3277 target: "https://example.org/relay"
3278 })
3279
3280 ModerationLog.insert_log(%{
3281 actor: moderator,
3282 action: "relay_unfollow",
3283 target: "https://example.org/relay"
3284 })
3285
3286 conn1 = get(conn, "/api/pleroma/admin/moderation_log?search=unfo")
3287
3288 response1 = json_response(conn1, 200)
3289 [first_entry] = response1["items"]
3290
3291 assert response1["total"] == 1
3292
3293 assert get_in(first_entry, ["data", "message"]) ==
3294 "@#{moderator.nickname} unfollowed relay: https://example.org/relay"
3295 end
3296 end
3297
3298 describe "GET /users/:nickname/credentials" do
3299 test "gets the user credentials", %{conn: conn} do
3300 user = insert(:user)
3301 conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}/credentials")
3302
3303 response = assert json_response(conn, 200)
3304 assert response["email"] == user.email
3305 end
3306
3307 test "returns 403 if requested by a non-admin" do
3308 user = insert(:user)
3309
3310 conn =
3311 build_conn()
3312 |> assign(:user, user)
3313 |> get("/api/pleroma/admin/users/#{user.nickname}/credentials")
3314
3315 assert json_response(conn, :forbidden)
3316 end
3317 end
3318
3319 describe "PATCH /users/:nickname/credentials" do
3320 test "changes password and email", %{conn: conn, admin: admin} do
3321 user = insert(:user)
3322 assert user.password_reset_pending == false
3323
3324 conn =
3325 patch(conn, "/api/pleroma/admin/users/#{user.nickname}/credentials", %{
3326 "password" => "new_password",
3327 "email" => "new_email@example.com",
3328 "name" => "new_name"
3329 })
3330
3331 assert json_response(conn, 200) == %{"status" => "success"}
3332
3333 ObanHelpers.perform_all()
3334
3335 updated_user = User.get_by_id(user.id)
3336
3337 assert updated_user.email == "new_email@example.com"
3338 assert updated_user.name == "new_name"
3339 assert updated_user.password_hash != user.password_hash
3340 assert updated_user.password_reset_pending == true
3341
3342 [log_entry2, log_entry1] = ModerationLog |> Repo.all() |> Enum.sort()
3343
3344 assert ModerationLog.get_log_entry_message(log_entry1) ==
3345 "@#{admin.nickname} updated users: @#{user.nickname}"
3346
3347 assert ModerationLog.get_log_entry_message(log_entry2) ==
3348 "@#{admin.nickname} forced password reset for users: @#{user.nickname}"
3349 end
3350
3351 test "returns 403 if requested by a non-admin" do
3352 user = insert(:user)
3353
3354 conn =
3355 build_conn()
3356 |> assign(:user, user)
3357 |> patch("/api/pleroma/admin/users/#{user.nickname}/credentials", %{
3358 "password" => "new_password",
3359 "email" => "new_email@example.com",
3360 "name" => "new_name"
3361 })
3362
3363 assert json_response(conn, :forbidden)
3364 end
3365 end
3366
3367 describe "PATCH /users/:nickname/force_password_reset" do
3368 test "sets password_reset_pending to true", %{conn: conn} do
3369 user = insert(:user)
3370 assert user.password_reset_pending == false
3371
3372 conn =
3373 patch(conn, "/api/pleroma/admin/users/force_password_reset", %{nicknames: [user.nickname]})
3374
3375 assert json_response(conn, 204) == ""
3376
3377 ObanHelpers.perform_all()
3378
3379 assert User.get_by_id(user.id).password_reset_pending == true
3380 end
3381 end
3382
3383 describe "relays" do
3384 test "POST /relay", %{conn: conn, admin: admin} do
3385 conn =
3386 post(conn, "/api/pleroma/admin/relay", %{
3387 relay_url: "http://mastodon.example.org/users/admin"
3388 })
3389
3390 assert json_response(conn, 200) == "http://mastodon.example.org/users/admin"
3391
3392 log_entry = Repo.one(ModerationLog)
3393
3394 assert ModerationLog.get_log_entry_message(log_entry) ==
3395 "@#{admin.nickname} followed relay: http://mastodon.example.org/users/admin"
3396 end
3397
3398 test "GET /relay", %{conn: conn} do
3399 relay_user = Pleroma.Web.ActivityPub.Relay.get_actor()
3400
3401 ["http://mastodon.example.org/users/admin", "https://mstdn.io/users/mayuutann"]
3402 |> Enum.each(fn ap_id ->
3403 {:ok, user} = User.get_or_fetch_by_ap_id(ap_id)
3404 User.follow(relay_user, user)
3405 end)
3406
3407 conn = get(conn, "/api/pleroma/admin/relay")
3408
3409 assert json_response(conn, 200)["relays"] -- ["mastodon.example.org", "mstdn.io"] == []
3410 end
3411
3412 test "DELETE /relay", %{conn: conn, admin: admin} do
3413 post(conn, "/api/pleroma/admin/relay", %{
3414 relay_url: "http://mastodon.example.org/users/admin"
3415 })
3416
3417 conn =
3418 delete(conn, "/api/pleroma/admin/relay", %{
3419 relay_url: "http://mastodon.example.org/users/admin"
3420 })
3421
3422 assert json_response(conn, 200) == "http://mastodon.example.org/users/admin"
3423
3424 [log_entry_one, log_entry_two] = Repo.all(ModerationLog)
3425
3426 assert ModerationLog.get_log_entry_message(log_entry_one) ==
3427 "@#{admin.nickname} followed relay: http://mastodon.example.org/users/admin"
3428
3429 assert ModerationLog.get_log_entry_message(log_entry_two) ==
3430 "@#{admin.nickname} unfollowed relay: http://mastodon.example.org/users/admin"
3431 end
3432 end
3433
3434 describe "instances" do
3435 test "GET /instances/:instance/statuses", %{conn: conn} do
3436 user = insert(:user, local: false, nickname: "archaeme@archae.me")
3437 user2 = insert(:user, local: false, nickname: "test@test.com")
3438 insert_pair(:note_activity, user: user)
3439 activity = insert(:note_activity, user: user2)
3440
3441 ret_conn = get(conn, "/api/pleroma/admin/instances/archae.me/statuses")
3442
3443 response = json_response(ret_conn, 200)
3444
3445 assert length(response) == 2
3446
3447 ret_conn = get(conn, "/api/pleroma/admin/instances/test.com/statuses")
3448
3449 response = json_response(ret_conn, 200)
3450
3451 assert length(response) == 1
3452
3453 ret_conn = get(conn, "/api/pleroma/admin/instances/nonexistent.com/statuses")
3454
3455 response = json_response(ret_conn, 200)
3456
3457 assert Enum.empty?(response)
3458
3459 CommonAPI.repeat(activity.id, user)
3460
3461 ret_conn = get(conn, "/api/pleroma/admin/instances/archae.me/statuses")
3462 response = json_response(ret_conn, 200)
3463 assert length(response) == 2
3464
3465 ret_conn = get(conn, "/api/pleroma/admin/instances/archae.me/statuses?with_reblogs=true")
3466 response = json_response(ret_conn, 200)
3467 assert length(response) == 3
3468 end
3469 end
3470
3471 describe "PATCH /confirm_email" do
3472 test "it confirms emails of two users", %{conn: conn, admin: admin} do
3473 [first_user, second_user] = insert_pair(:user, confirmation_pending: true)
3474
3475 assert first_user.confirmation_pending == true
3476 assert second_user.confirmation_pending == true
3477
3478 ret_conn =
3479 patch(conn, "/api/pleroma/admin/users/confirm_email", %{
3480 nicknames: [
3481 first_user.nickname,
3482 second_user.nickname
3483 ]
3484 })
3485
3486 assert ret_conn.status == 200
3487
3488 assert first_user.confirmation_pending == true
3489 assert second_user.confirmation_pending == true
3490
3491 log_entry = Repo.one(ModerationLog)
3492
3493 assert ModerationLog.get_log_entry_message(log_entry) ==
3494 "@#{admin.nickname} confirmed email for users: @#{first_user.nickname}, @#{
3495 second_user.nickname
3496 }"
3497 end
3498 end
3499
3500 describe "PATCH /resend_confirmation_email" do
3501 test "it resend emails for two users", %{conn: conn, admin: admin} do
3502 [first_user, second_user] = insert_pair(:user, confirmation_pending: true)
3503
3504 ret_conn =
3505 patch(conn, "/api/pleroma/admin/users/resend_confirmation_email", %{
3506 nicknames: [
3507 first_user.nickname,
3508 second_user.nickname
3509 ]
3510 })
3511
3512 assert ret_conn.status == 200
3513
3514 log_entry = Repo.one(ModerationLog)
3515
3516 assert ModerationLog.get_log_entry_message(log_entry) ==
3517 "@#{admin.nickname} re-sent confirmation email for users: @#{first_user.nickname}, @#{
3518 second_user.nickname
3519 }"
3520 end
3521 end
3522
3523 describe "POST /reports/:id/notes" do
3524 setup %{conn: conn, admin: admin} do
3525 [reporter, target_user] = insert_pair(:user)
3526 activity = insert(:note_activity, user: target_user)
3527
3528 {:ok, %{id: report_id}} =
3529 CommonAPI.report(reporter, %{
3530 account_id: target_user.id,
3531 comment: "I feel offended",
3532 status_ids: [activity.id]
3533 })
3534
3535 post(conn, "/api/pleroma/admin/reports/#{report_id}/notes", %{
3536 content: "this is disgusting!"
3537 })
3538
3539 post(conn, "/api/pleroma/admin/reports/#{report_id}/notes", %{
3540 content: "this is disgusting2!"
3541 })
3542
3543 %{
3544 admin_id: admin.id,
3545 report_id: report_id
3546 }
3547 end
3548
3549 test "it creates report note", %{admin_id: admin_id, report_id: report_id} do
3550 [note, _] = Repo.all(ReportNote)
3551
3552 assert %{
3553 activity_id: ^report_id,
3554 content: "this is disgusting!",
3555 user_id: ^admin_id
3556 } = note
3557 end
3558
3559 test "it returns reports with notes", %{conn: conn, admin: admin} do
3560 conn = get(conn, "/api/pleroma/admin/reports")
3561
3562 response = json_response(conn, 200)
3563 notes = hd(response["reports"])["notes"]
3564 [note, _] = notes
3565
3566 assert note["user"]["nickname"] == admin.nickname
3567 assert note["content"] == "this is disgusting!"
3568 assert note["created_at"]
3569 assert response["total"] == 1
3570 end
3571
3572 test "it deletes the note", %{conn: conn, report_id: report_id} do
3573 assert ReportNote |> Repo.all() |> length() == 2
3574
3575 [note, _] = Repo.all(ReportNote)
3576
3577 delete(conn, "/api/pleroma/admin/reports/#{report_id}/notes/#{note.id}")
3578
3579 assert ReportNote |> Repo.all() |> length() == 1
3580 end
3581 end
3582
3583 test "GET /api/pleroma/admin/config/descriptions", %{conn: conn} do
3584 admin = insert(:user, is_admin: true)
3585
3586 conn =
3587 assign(conn, :user, admin)
3588 |> get("/api/pleroma/admin/config/descriptions")
3589
3590 assert [child | _others] = json_response(conn, 200)
3591
3592 assert child["children"]
3593 assert child["key"]
3594 assert String.starts_with?(child["group"], ":")
3595 assert child["description"]
3596 end
3597
3598 describe "/api/pleroma/admin/stats" do
3599 test "status visibility count", %{conn: conn} do
3600 admin = insert(:user, is_admin: true)
3601 user = insert(:user)
3602 CommonAPI.post(user, %{"visibility" => "public", "status" => "hey"})
3603 CommonAPI.post(user, %{"visibility" => "unlisted", "status" => "hey"})
3604 CommonAPI.post(user, %{"visibility" => "unlisted", "status" => "hey"})
3605
3606 response =
3607 conn
3608 |> assign(:user, admin)
3609 |> get("/api/pleroma/admin/stats")
3610 |> json_response(200)
3611
3612 assert %{"direct" => 0, "private" => 0, "public" => 1, "unlisted" => 2} =
3613 response["status_visibility"]
3614 end
3615
3616 test "by instance", %{conn: conn} do
3617 admin = insert(:user, is_admin: true)
3618 user1 = insert(:user)
3619 instance2 = "instance2.tld"
3620 user2 = insert(:user, %{ap_id: "https://#{instance2}/@actor"})
3621
3622 CommonAPI.post(user1, %{"visibility" => "public", "status" => "hey"})
3623 CommonAPI.post(user2, %{"visibility" => "unlisted", "status" => "hey"})
3624 CommonAPI.post(user2, %{"visibility" => "private", "status" => "hey"})
3625
3626 response =
3627 conn
3628 |> assign(:user, admin)
3629 |> get("/api/pleroma/admin/stats", instance: instance2)
3630 |> json_response(200)
3631
3632 assert %{"direct" => 0, "private" => 1, "public" => 0, "unlisted" => 1} =
3633 response["status_visibility"]
3634 end
3635 end
3636
3637 describe "POST /api/pleroma/admin/oauth_app" do
3638 test "errors", %{conn: conn} do
3639 response = conn |> post("/api/pleroma/admin/oauth_app", %{}) |> json_response(200)
3640
3641 assert response == %{"name" => "can't be blank", "redirect_uris" => "can't be blank"}
3642 end
3643
3644 test "success", %{conn: conn} do
3645 base_url = Web.base_url()
3646 app_name = "Trusted app"
3647
3648 response =
3649 conn
3650 |> post("/api/pleroma/admin/oauth_app", %{
3651 name: app_name,
3652 redirect_uris: base_url
3653 })
3654 |> json_response(200)
3655
3656 assert %{
3657 "client_id" => _,
3658 "client_secret" => _,
3659 "name" => ^app_name,
3660 "redirect_uri" => ^base_url,
3661 "trusted" => false
3662 } = response
3663 end
3664
3665 test "with trusted", %{conn: conn} do
3666 base_url = Web.base_url()
3667 app_name = "Trusted app"
3668
3669 response =
3670 conn
3671 |> post("/api/pleroma/admin/oauth_app", %{
3672 name: app_name,
3673 redirect_uris: base_url,
3674 trusted: true
3675 })
3676 |> json_response(200)
3677
3678 assert %{
3679 "client_id" => _,
3680 "client_secret" => _,
3681 "name" => ^app_name,
3682 "redirect_uri" => ^base_url,
3683 "trusted" => true
3684 } = response
3685 end
3686 end
3687
3688 describe "GET /api/pleroma/admin/oauth_app" do
3689 setup do
3690 app = insert(:oauth_app)
3691 {:ok, app: app}
3692 end
3693
3694 test "list", %{conn: conn} do
3695 response =
3696 conn
3697 |> get("/api/pleroma/admin/oauth_app")
3698 |> json_response(200)
3699
3700 assert %{"apps" => apps, "count" => count, "page_size" => _} = response
3701
3702 assert length(apps) == count
3703 end
3704
3705 test "with page size", %{conn: conn} do
3706 insert(:oauth_app)
3707 page_size = 1
3708
3709 response =
3710 conn
3711 |> get("/api/pleroma/admin/oauth_app", %{page_size: to_string(page_size)})
3712 |> json_response(200)
3713
3714 assert %{"apps" => apps, "count" => _, "page_size" => ^page_size} = response
3715
3716 assert length(apps) == page_size
3717 end
3718
3719 test "search by client name", %{conn: conn, app: app} do
3720 response =
3721 conn
3722 |> get("/api/pleroma/admin/oauth_app", %{name: app.client_name})
3723 |> json_response(200)
3724
3725 assert %{"apps" => [returned], "count" => _, "page_size" => _} = response
3726
3727 assert returned["client_id"] == app.client_id
3728 assert returned["name"] == app.client_name
3729 end
3730
3731 test "search by client id", %{conn: conn, app: app} do
3732 response =
3733 conn
3734 |> get("/api/pleroma/admin/oauth_app", %{client_id: app.client_id})
3735 |> json_response(200)
3736
3737 assert %{"apps" => [returned], "count" => _, "page_size" => _} = response
3738
3739 assert returned["client_id"] == app.client_id
3740 assert returned["name"] == app.client_name
3741 end
3742
3743 test "only trusted", %{conn: conn} do
3744 app = insert(:oauth_app, trusted: true)
3745
3746 response =
3747 conn
3748 |> get("/api/pleroma/admin/oauth_app", %{trusted: true})
3749 |> json_response(200)
3750
3751 assert %{"apps" => [returned], "count" => _, "page_size" => _} = response
3752
3753 assert returned["client_id"] == app.client_id
3754 assert returned["name"] == app.client_name
3755 end
3756 end
3757
3758 describe "DELETE /api/pleroma/admin/oauth_app/:id" do
3759 test "with id", %{conn: conn} do
3760 app = insert(:oauth_app)
3761
3762 response =
3763 conn
3764 |> delete("/api/pleroma/admin/oauth_app/" <> to_string(app.id))
3765 |> json_response(:no_content)
3766
3767 assert response == ""
3768 end
3769
3770 test "with non existance id", %{conn: conn} do
3771 response =
3772 conn
3773 |> delete("/api/pleroma/admin/oauth_app/0")
3774 |> json_response(:bad_request)
3775
3776 assert response == ""
3777 end
3778 end
3779
3780 describe "PATCH /api/pleroma/admin/oauth_app/:id" do
3781 test "with id", %{conn: conn} do
3782 app = insert(:oauth_app)
3783
3784 name = "another name"
3785 url = "https://example.com"
3786 scopes = ["admin"]
3787 id = app.id
3788 website = "http://website.com"
3789
3790 response =
3791 conn
3792 |> patch("/api/pleroma/admin/oauth_app/" <> to_string(app.id), %{
3793 name: name,
3794 trusted: true,
3795 redirect_uris: url,
3796 scopes: scopes,
3797 website: website
3798 })
3799 |> json_response(200)
3800
3801 assert %{
3802 "client_id" => _,
3803 "client_secret" => _,
3804 "id" => ^id,
3805 "name" => ^name,
3806 "redirect_uri" => ^url,
3807 "trusted" => true,
3808 "website" => ^website
3809 } = response
3810 end
3811
3812 test "without id", %{conn: conn} do
3813 response =
3814 conn
3815 |> patch("/api/pleroma/admin/oauth_app/0")
3816 |> json_response(:bad_request)
3817
3818 assert response == ""
3819 end
3820 end
3821 end
3822
3823 # Needed for testing
3824 defmodule Pleroma.Web.Endpoint.NotReal do
3825 end
3826
3827 defmodule Pleroma.Captcha.NotReal do
3828 end