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