X-Git-Url: http://git.squeep.com/?a=blobdiff_plain;f=test%2Fweb%2Fadmin_api%2Fadmin_api_controller_test.exs;h=045c87e952bef70158c0ddd5aca0c68607042f80;hb=390bf9b097cab96b9d3a0214f974044667524442;hp=5f36d42e4e22c88f9648dd485a0d92f0dc464e7d;hpb=25b43656565b0044d79d7e969d98a0f8283279fc;p=akkoma diff --git a/test/web/admin_api/admin_api_controller_test.exs b/test/web/admin_api/admin_api_controller_test.exs index 5f36d42e4..c8f8ba310 100644 --- a/test/web/admin_api/admin_api_controller_test.exs +++ b/test/web/admin_api/admin_api_controller_test.exs @@ -1,48 +1,190 @@ # Pleroma: A lightweight social networking server -# Copyright © 2017-2018 Pleroma Authors +# Copyright © 2017-2019 Pleroma Authors # SPDX-License-Identifier: AGPL-3.0-only defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do use Pleroma.Web.ConnCase + use Oban.Testing, repo: Pleroma.Repo alias Pleroma.Activity alias Pleroma.HTML alias Pleroma.ModerationLog alias Pleroma.Repo + alias Pleroma.ReportNote + alias Pleroma.Tests.ObanHelpers alias Pleroma.User alias Pleroma.UserInviteToken + alias Pleroma.Web.ActivityPub.Relay alias Pleroma.Web.CommonAPI + alias Pleroma.Web.MastodonAPI.StatusView alias Pleroma.Web.MediaProxy import Pleroma.Factory - describe "/api/pleroma/admin/users" do - test "Delete" do - admin = insert(:user, info: %{is_admin: true}) + setup_all do + Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end) + + :ok + end + + setup do + admin = insert(:user, is_admin: true) + token = insert(:oauth_admin_token, user: admin) + + conn = + build_conn() + |> assign(:user, admin) + |> assign(:token, token) + + {:ok, %{admin: admin, token: token, conn: conn}} + end + + describe "with [:auth, :enforce_oauth_admin_scope_usage]," do + clear_config([:auth, :enforce_oauth_admin_scope_usage]) do + Pleroma.Config.put([:auth, :enforce_oauth_admin_scope_usage], true) + end + + test "GET /api/pleroma/admin/users/:nickname requires admin:read:accounts or broader scope", + %{admin: admin} do + user = insert(:user) + url = "/api/pleroma/admin/users/#{user.nickname}" + + good_token1 = insert(:oauth_token, user: admin, scopes: ["admin"]) + good_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read"]) + good_token3 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts"]) + + bad_token1 = insert(:oauth_token, user: admin, scopes: ["read:accounts"]) + bad_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts:partial"]) + bad_token3 = nil + + for good_token <- [good_token1, good_token2, good_token3] do + conn = + build_conn() + |> assign(:user, admin) + |> assign(:token, good_token) + |> get(url) + + assert json_response(conn, 200) + end + + for good_token <- [good_token1, good_token2, good_token3] do + conn = + build_conn() + |> assign(:user, nil) + |> assign(:token, good_token) + |> get(url) + + assert json_response(conn, :forbidden) + end + + for bad_token <- [bad_token1, bad_token2, bad_token3] do + conn = + build_conn() + |> assign(:user, admin) + |> assign(:token, bad_token) + |> get(url) + + assert json_response(conn, :forbidden) + end + end + end + + describe "unless [:auth, :enforce_oauth_admin_scope_usage]," do + clear_config([:auth, :enforce_oauth_admin_scope_usage]) do + Pleroma.Config.put([:auth, :enforce_oauth_admin_scope_usage], false) + end + + test "GET /api/pleroma/admin/users/:nickname requires " <> + "read:accounts or admin:read:accounts or broader scope", + %{admin: admin} do + user = insert(:user) + url = "/api/pleroma/admin/users/#{user.nickname}" + + good_token1 = insert(:oauth_token, user: admin, scopes: ["admin"]) + good_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read"]) + good_token3 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts"]) + good_token4 = insert(:oauth_token, user: admin, scopes: ["read:accounts"]) + good_token5 = insert(:oauth_token, user: admin, scopes: ["read"]) + + good_tokens = [good_token1, good_token2, good_token3, good_token4, good_token5] + + bad_token1 = insert(:oauth_token, user: admin, scopes: ["read:accounts:partial"]) + bad_token2 = insert(:oauth_token, user: admin, scopes: ["admin:read:accounts:partial"]) + bad_token3 = nil + + for good_token <- good_tokens do + conn = + build_conn() + |> assign(:user, admin) + |> assign(:token, good_token) + |> get(url) + + assert json_response(conn, 200) + end + + for good_token <- good_tokens do + conn = + build_conn() + |> assign(:user, nil) + |> assign(:token, good_token) + |> get(url) + + assert json_response(conn, :forbidden) + end + + for bad_token <- [bad_token1, bad_token2, bad_token3] do + conn = + build_conn() + |> assign(:user, admin) + |> assign(:token, bad_token) + |> get(url) + + assert json_response(conn, :forbidden) + end + end + end + + describe "DELETE /api/pleroma/admin/users" do + test "single user", %{admin: admin, conn: conn} do user = insert(:user) conn = - build_conn() - |> assign(:user, admin) + conn |> put_req_header("accept", "application/json") |> delete("/api/pleroma/admin/users?nickname=#{user.nickname}") log_entry = Repo.one(ModerationLog) - assert log_entry.data["subject"]["nickname"] == user.nickname - assert log_entry.data["action"] == "delete" - assert ModerationLog.get_log_entry_message(log_entry) == - "@#{admin.nickname} deleted user @#{user.nickname}" + "@#{admin.nickname} deleted users: @#{user.nickname}" assert json_response(conn, 200) == user.nickname end - test "Create" do - admin = insert(:user, info: %{is_admin: true}) + test "multiple users", %{admin: admin, conn: conn} do + user_one = insert(:user) + user_two = insert(:user) conn = - build_conn() - |> assign(:user, admin) + conn + |> put_req_header("accept", "application/json") + |> delete("/api/pleroma/admin/users", %{ + nicknames: [user_one.nickname, user_two.nickname] + }) + + log_entry = Repo.one(ModerationLog) + + assert ModerationLog.get_log_entry_message(log_entry) == + "@#{admin.nickname} deleted users: @#{user_one.nickname}, @#{user_two.nickname}" + + response = json_response(conn, 200) + assert response -- [user_one.nickname, user_two.nickname] == [] + end + end + + describe "/api/pleroma/admin/users" do + test "Create", %{conn: conn} do + conn = + conn |> put_req_header("accept", "application/json") |> post("/api/pleroma/admin/users", %{ "users" => [ @@ -67,13 +209,11 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do assert ["lain", "lain2"] -- Enum.map(log_entry.data["subjects"], & &1["nickname"]) == [] end - test "Cannot create user with exisiting email" do - admin = insert(:user, info: %{is_admin: true}) + test "Cannot create user with existing email", %{conn: conn} do user = insert(:user) conn = - build_conn() - |> assign(:user, admin) + conn |> put_req_header("accept", "application/json") |> post("/api/pleroma/admin/users", %{ "users" => [ @@ -98,13 +238,11 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do ] end - test "Cannot create user with exisiting nickname" do - admin = insert(:user, info: %{is_admin: true}) + test "Cannot create user with existing nickname", %{conn: conn} do user = insert(:user) conn = - build_conn() - |> assign(:user, admin) + conn |> put_req_header("accept", "application/json") |> post("/api/pleroma/admin/users", %{ "users" => [ @@ -129,13 +267,11 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do ] end - test "Multiple user creation works in transaction" do - admin = insert(:user, info: %{is_admin: true}) + test "Multiple user creation works in transaction", %{conn: conn} do user = insert(:user) conn = - build_conn() - |> assign(:user, admin) + conn |> put_req_header("accept", "application/json") |> post("/api/pleroma/admin/users", %{ "users" => [ @@ -179,13 +315,9 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do describe "/api/pleroma/admin/users/:nickname" do test "Show", %{conn: conn} do - admin = insert(:user, info: %{is_admin: true}) user = insert(:user) - conn = - conn - |> assign(:user, admin) - |> get("/api/pleroma/admin/users/#{user.nickname}") + conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}") expected = %{ "deactivated" => false, @@ -195,33 +327,28 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do "roles" => %{"admin" => false, "moderator" => false}, "tags" => [], "avatar" => User.avatar_url(user) |> MediaProxy.url(), - "display_name" => HTML.strip_tags(user.name || user.nickname) + "display_name" => HTML.strip_tags(user.name || user.nickname), + "confirmation_pending" => false } assert expected == json_response(conn, 200) end test "when the user doesn't exist", %{conn: conn} do - admin = insert(:user, info: %{is_admin: true}) user = build(:user) - conn = - conn - |> assign(:user, admin) - |> get("/api/pleroma/admin/users/#{user.nickname}") + conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}") assert "Not found" == json_response(conn, 404) end end describe "/api/pleroma/admin/users/follow" do - test "allows to force-follow another user" do - admin = insert(:user, info: %{is_admin: true}) + test "allows to force-follow another user", %{admin: admin, conn: conn} do user = insert(:user) follower = insert(:user) - build_conn() - |> assign(:user, admin) + conn |> put_req_header("accept", "application/json") |> post("/api/pleroma/admin/users/follow", %{ "follower" => follower.nickname, @@ -241,15 +368,13 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do end describe "/api/pleroma/admin/users/unfollow" do - test "allows to force-unfollow another user" do - admin = insert(:user, info: %{is_admin: true}) + test "allows to force-unfollow another user", %{admin: admin, conn: conn} do user = insert(:user) follower = insert(:user) User.follow(follower, user) - build_conn() - |> assign(:user, admin) + conn |> put_req_header("accept", "application/json") |> post("/api/pleroma/admin/users/unfollow", %{ "follower" => follower.nickname, @@ -269,23 +394,20 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do end describe "PUT /api/pleroma/admin/users/tag" do - setup do - admin = insert(:user, info: %{is_admin: true}) + setup %{conn: conn} do user1 = insert(:user, %{tags: ["x"]}) user2 = insert(:user, %{tags: ["y"]}) user3 = insert(:user, %{tags: ["unchanged"]}) conn = - build_conn() - |> assign(:user, admin) + conn |> put_req_header("accept", "application/json") |> put( - "/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=#{ - user2.nickname - }&tags[]=foo&tags[]=bar" + "/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=" <> + "#{user2.nickname}&tags[]=foo&tags[]=bar" ) - %{conn: conn, admin: admin, user1: user1, user2: user2, user3: user3} + %{conn: conn, user1: user1, user2: user2, user3: user3} end test "it appends specified tags to users with specified nicknames", %{ @@ -318,23 +440,20 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do end describe "DELETE /api/pleroma/admin/users/tag" do - setup do - admin = insert(:user, info: %{is_admin: true}) + setup %{conn: conn} do user1 = insert(:user, %{tags: ["x"]}) user2 = insert(:user, %{tags: ["y", "z"]}) user3 = insert(:user, %{tags: ["unchanged"]}) conn = - build_conn() - |> assign(:user, admin) + conn |> put_req_header("accept", "application/json") |> delete( - "/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=#{ - user2.nickname - }&tags[]=x&tags[]=z" + "/api/pleroma/admin/users/tag?nicknames[]=#{user1.nickname}&nicknames[]=" <> + "#{user2.nickname}&tags[]=x&tags[]=z" ) - %{conn: conn, admin: admin, user1: user1, user2: user2, user3: user3} + %{conn: conn, user1: user1, user2: user2, user3: user3} end test "it removes specified tags from users with specified nicknames", %{ @@ -367,12 +486,9 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do end describe "/api/pleroma/admin/users/:nickname/permission_group" do - test "GET is giving user_info" do - admin = insert(:user, info: %{is_admin: true}) - + test "GET is giving user_info", %{admin: admin, conn: conn} do conn = - build_conn() - |> assign(:user, admin) + conn |> put_req_header("accept", "application/json") |> get("/api/pleroma/admin/users/#{admin.nickname}/permission_group/") @@ -382,13 +498,11 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do } end - test "/:right POST, can add to a permission group" do - admin = insert(:user, info: %{is_admin: true}) + test "/:right POST, can add to a permission group", %{admin: admin, conn: conn} do user = insert(:user) conn = - build_conn() - |> assign(:user, admin) + conn |> put_req_header("accept", "application/json") |> post("/api/pleroma/admin/users/#{user.nickname}/permission_group/admin") @@ -402,90 +516,67 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do "@#{admin.nickname} made @#{user.nickname} admin" end - test "/:right DELETE, can remove from a permission group" do - admin = insert(:user, info: %{is_admin: true}) - user = insert(:user, info: %{is_admin: true}) + test "/:right POST, can add to a permission group (multiple)", %{admin: admin, conn: conn} do + user_one = insert(:user) + user_two = insert(:user) conn = - build_conn() - |> assign(:user, admin) + conn |> put_req_header("accept", "application/json") - |> delete("/api/pleroma/admin/users/#{user.nickname}/permission_group/admin") + |> post("/api/pleroma/admin/users/permission_group/admin", %{ + nicknames: [user_one.nickname, user_two.nickname] + }) - assert json_response(conn, 200) == %{ - "is_admin" => false - } + assert json_response(conn, 200) == %{"is_admin" => true} log_entry = Repo.one(ModerationLog) assert ModerationLog.get_log_entry_message(log_entry) == - "@#{admin.nickname} revoked admin role from @#{user.nickname}" + "@#{admin.nickname} made @#{user_one.nickname}, @#{user_two.nickname} admin" end - end - describe "PUT /api/pleroma/admin/users/:nickname/activation_status" do - setup %{conn: conn} do - admin = insert(:user, info: %{is_admin: true}) + test "/:right DELETE, can remove from a permission group", %{admin: admin, conn: conn} do + user = insert(:user, is_admin: true) conn = conn - |> assign(:user, admin) |> put_req_header("accept", "application/json") + |> delete("/api/pleroma/admin/users/#{user.nickname}/permission_group/admin") - %{conn: conn, admin: admin} - end - - test "deactivates the user", %{conn: conn, admin: admin} do - user = insert(:user) - - conn = - conn - |> put("/api/pleroma/admin/users/#{user.nickname}/activation_status", %{status: false}) - - user = User.get_cached_by_id(user.id) - assert user.info.deactivated == true - assert json_response(conn, :no_content) + assert json_response(conn, 200) == %{"is_admin" => false} log_entry = Repo.one(ModerationLog) assert ModerationLog.get_log_entry_message(log_entry) == - "@#{admin.nickname} deactivated user @#{user.nickname}" + "@#{admin.nickname} revoked admin role from @#{user.nickname}" end - test "activates the user", %{conn: conn, admin: admin} do - user = insert(:user, info: %{deactivated: true}) + test "/:right DELETE, can remove from a permission group (multiple)", %{ + admin: admin, + conn: conn + } do + user_one = insert(:user, is_admin: true) + user_two = insert(:user, is_admin: true) conn = conn - |> put("/api/pleroma/admin/users/#{user.nickname}/activation_status", %{status: true}) + |> put_req_header("accept", "application/json") + |> delete("/api/pleroma/admin/users/permission_group/admin", %{ + nicknames: [user_one.nickname, user_two.nickname] + }) - user = User.get_cached_by_id(user.id) - assert user.info.deactivated == false - assert json_response(conn, :no_content) + assert json_response(conn, 200) == %{"is_admin" => false} log_entry = Repo.one(ModerationLog) assert ModerationLog.get_log_entry_message(log_entry) == - "@#{admin.nickname} activated user @#{user.nickname}" - end - - test "returns 403 when requested by a non-admin", %{conn: conn} do - user = insert(:user) - - conn = - conn - |> assign(:user, user) - |> put("/api/pleroma/admin/users/#{user.nickname}/activation_status", %{status: false}) - - assert json_response(conn, :forbidden) + "@#{admin.nickname} revoked admin role from @#{user_one.nickname}, @#{ + user_two.nickname + }" end end describe "POST /api/pleroma/admin/email_invite, with valid config" do - setup do - [user: insert(:user, info: %{is_admin: true})] - end - clear_config([:instance, :registrations_open]) do Pleroma.Config.put([:instance, :registrations_open], false) end @@ -494,14 +585,13 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do Pleroma.Config.put([:instance, :invites_enabled], true) end - test "sends invitation and returns 204", %{conn: conn, user: user} do + test "sends invitation and returns 204", %{admin: admin, conn: conn} do recipient_email = "foo@bar.com" recipient_name = "J. D." conn = - conn - |> assign(:user, user) - |> post( + post( + conn, "/api/pleroma/admin/users/email_invite?email=#{recipient_email}&name=#{recipient_name}" ) @@ -516,7 +606,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do email = Pleroma.Emails.UserEmail.user_invitation_email( - user, + admin, token_record, recipient_email, recipient_name @@ -529,12 +619,14 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do ) end - test "it returns 403 if requested by a non-admin", %{conn: conn} do + test "it returns 403 if requested by a non-admin" do non_admin_user = insert(:user) + token = insert(:oauth_token, user: non_admin_user) conn = - conn + build_conn() |> assign(:user, non_admin_user) + |> assign(:token, token) |> post("/api/pleroma/admin/users/email_invite?email=foo@bar.com&name=JD") assert json_response(conn, :forbidden) @@ -542,62 +634,42 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do end describe "POST /api/pleroma/admin/users/email_invite, with invalid config" do - setup do - [user: insert(:user, info: %{is_admin: true})] - end - clear_config([:instance, :registrations_open]) clear_config([:instance, :invites_enabled]) - test "it returns 500 if `invites_enabled` is not enabled", %{conn: conn, user: user} do + test "it returns 500 if `invites_enabled` is not enabled", %{conn: conn} do Pleroma.Config.put([:instance, :registrations_open], false) Pleroma.Config.put([:instance, :invites_enabled], false) - conn = - conn - |> assign(:user, user) - |> post("/api/pleroma/admin/users/email_invite?email=foo@bar.com&name=JD") + conn = post(conn, "/api/pleroma/admin/users/email_invite?email=foo@bar.com&name=JD") assert json_response(conn, :internal_server_error) end - test "it returns 500 if `registrations_open` is enabled", %{conn: conn, user: user} do + test "it returns 500 if `registrations_open` is enabled", %{conn: conn} do Pleroma.Config.put([:instance, :registrations_open], true) Pleroma.Config.put([:instance, :invites_enabled], true) - conn = - conn - |> assign(:user, user) - |> post("/api/pleroma/admin/users/email_invite?email=foo@bar.com&name=JD") + conn = post(conn, "/api/pleroma/admin/users/email_invite?email=foo@bar.com&name=JD") assert json_response(conn, :internal_server_error) end end - test "/api/pleroma/admin/users/:nickname/password_reset" do - admin = insert(:user, info: %{is_admin: true}) + test "/api/pleroma/admin/users/:nickname/password_reset", %{conn: conn} do user = insert(:user) conn = - build_conn() - |> assign(:user, admin) + conn |> put_req_header("accept", "application/json") |> get("/api/pleroma/admin/users/#{user.nickname}/password_reset") - assert conn.status == 200 + resp = json_response(conn, 200) + + assert Regex.match?(~r/(http:\/\/|https:\/\/)/, resp["link"]) end describe "GET /api/pleroma/admin/users" do - setup do - admin = insert(:user, info: %{is_admin: true}) - - conn = - build_conn() - |> assign(:user, admin) - - {:ok, conn: conn, admin: admin} - end - test "renders users array for the first page", %{conn: conn, admin: admin} do user = insert(:user, local: false, tags: ["foo", "bar"]) conn = get(conn, "/api/pleroma/admin/users?page=1") @@ -605,24 +677,26 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do users = [ %{ - "deactivated" => admin.info.deactivated, + "deactivated" => admin.deactivated, "id" => admin.id, "nickname" => admin.nickname, "roles" => %{"admin" => true, "moderator" => false}, "local" => true, "tags" => [], "avatar" => User.avatar_url(admin) |> MediaProxy.url(), - "display_name" => HTML.strip_tags(admin.name || admin.nickname) + "display_name" => HTML.strip_tags(admin.name || admin.nickname), + "confirmation_pending" => false }, %{ - "deactivated" => user.info.deactivated, + "deactivated" => user.deactivated, "id" => user.id, "nickname" => user.nickname, "roles" => %{"admin" => false, "moderator" => false}, "local" => false, "tags" => ["foo", "bar"], "avatar" => User.avatar_url(user) |> MediaProxy.url(), - "display_name" => HTML.strip_tags(user.name || user.nickname) + "display_name" => HTML.strip_tags(user.name || user.nickname), + "confirmation_pending" => false } ] |> Enum.sort_by(& &1["nickname"]) @@ -656,14 +730,15 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do "page_size" => 50, "users" => [ %{ - "deactivated" => user.info.deactivated, + "deactivated" => user.deactivated, "id" => user.id, "nickname" => user.nickname, "roles" => %{"admin" => false, "moderator" => false}, "local" => true, "tags" => [], "avatar" => User.avatar_url(user) |> MediaProxy.url(), - "display_name" => HTML.strip_tags(user.name || user.nickname) + "display_name" => HTML.strip_tags(user.name || user.nickname), + "confirmation_pending" => false } ] } @@ -680,14 +755,15 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do "page_size" => 50, "users" => [ %{ - "deactivated" => user.info.deactivated, + "deactivated" => user.deactivated, "id" => user.id, "nickname" => user.nickname, "roles" => %{"admin" => false, "moderator" => false}, "local" => true, "tags" => [], "avatar" => User.avatar_url(user) |> MediaProxy.url(), - "display_name" => HTML.strip_tags(user.name || user.nickname) + "display_name" => HTML.strip_tags(user.name || user.nickname), + "confirmation_pending" => false } ] } @@ -704,14 +780,15 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do "page_size" => 50, "users" => [ %{ - "deactivated" => user.info.deactivated, + "deactivated" => user.deactivated, "id" => user.id, "nickname" => user.nickname, "roles" => %{"admin" => false, "moderator" => false}, "local" => true, "tags" => [], "avatar" => User.avatar_url(user) |> MediaProxy.url(), - "display_name" => HTML.strip_tags(user.name || user.nickname) + "display_name" => HTML.strip_tags(user.name || user.nickname), + "confirmation_pending" => false } ] } @@ -728,14 +805,15 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do "page_size" => 50, "users" => [ %{ - "deactivated" => user.info.deactivated, + "deactivated" => user.deactivated, "id" => user.id, "nickname" => user.nickname, "roles" => %{"admin" => false, "moderator" => false}, "local" => true, "tags" => [], "avatar" => User.avatar_url(user) |> MediaProxy.url(), - "display_name" => HTML.strip_tags(user.name || user.nickname) + "display_name" => HTML.strip_tags(user.name || user.nickname), + "confirmation_pending" => false } ] } @@ -752,14 +830,15 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do "page_size" => 50, "users" => [ %{ - "deactivated" => user.info.deactivated, + "deactivated" => user.deactivated, "id" => user.id, "nickname" => user.nickname, "roles" => %{"admin" => false, "moderator" => false}, "local" => true, "tags" => [], "avatar" => User.avatar_url(user) |> MediaProxy.url(), - "display_name" => HTML.strip_tags(user.name || user.nickname) + "display_name" => HTML.strip_tags(user.name || user.nickname), + "confirmation_pending" => false } ] } @@ -776,14 +855,15 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do "page_size" => 1, "users" => [ %{ - "deactivated" => user.info.deactivated, + "deactivated" => user.deactivated, "id" => user.id, "nickname" => user.nickname, "roles" => %{"admin" => false, "moderator" => false}, "local" => true, "tags" => [], "avatar" => User.avatar_url(user) |> MediaProxy.url(), - "display_name" => HTML.strip_tags(user.name || user.nickname) + "display_name" => HTML.strip_tags(user.name || user.nickname), + "confirmation_pending" => false } ] } @@ -795,21 +875,23 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do "page_size" => 1, "users" => [ %{ - "deactivated" => user2.info.deactivated, + "deactivated" => user2.deactivated, "id" => user2.id, "nickname" => user2.nickname, "roles" => %{"admin" => false, "moderator" => false}, "local" => true, "tags" => [], "avatar" => User.avatar_url(user2) |> MediaProxy.url(), - "display_name" => HTML.strip_tags(user2.name || user2.nickname) + "display_name" => HTML.strip_tags(user2.name || user2.nickname), + "confirmation_pending" => false } ] } end test "only local users" do - admin = insert(:user, info: %{is_admin: true}, nickname: "john") + admin = insert(:user, is_admin: true, nickname: "john") + token = insert(:oauth_admin_token, user: admin) user = insert(:user, nickname: "bob") insert(:user, nickname: "bobb", local: false) @@ -817,6 +899,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do conn = build_conn() |> assign(:user, admin) + |> assign(:token, token) |> get("/api/pleroma/admin/users?query=bo&filters=local") assert json_response(conn, 200) == %{ @@ -824,51 +907,51 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do "page_size" => 50, "users" => [ %{ - "deactivated" => user.info.deactivated, + "deactivated" => user.deactivated, "id" => user.id, "nickname" => user.nickname, "roles" => %{"admin" => false, "moderator" => false}, "local" => true, "tags" => [], "avatar" => User.avatar_url(user) |> MediaProxy.url(), - "display_name" => HTML.strip_tags(user.name || user.nickname) + "display_name" => HTML.strip_tags(user.name || user.nickname), + "confirmation_pending" => false } ] } end - test "only local users with no query", %{admin: old_admin} do - admin = insert(:user, info: %{is_admin: true}, nickname: "john") + test "only local users with no query", %{conn: conn, admin: old_admin} do + admin = insert(:user, is_admin: true, nickname: "john") user = insert(:user, nickname: "bob") insert(:user, nickname: "bobb", local: false) - conn = - build_conn() - |> assign(:user, admin) - |> get("/api/pleroma/admin/users?filters=local") + conn = get(conn, "/api/pleroma/admin/users?filters=local") users = [ %{ - "deactivated" => user.info.deactivated, + "deactivated" => user.deactivated, "id" => user.id, "nickname" => user.nickname, "roles" => %{"admin" => false, "moderator" => false}, "local" => true, "tags" => [], "avatar" => User.avatar_url(user) |> MediaProxy.url(), - "display_name" => HTML.strip_tags(user.name || user.nickname) + "display_name" => HTML.strip_tags(user.name || user.nickname), + "confirmation_pending" => false }, %{ - "deactivated" => admin.info.deactivated, + "deactivated" => admin.deactivated, "id" => admin.id, "nickname" => admin.nickname, "roles" => %{"admin" => true, "moderator" => false}, "local" => true, "tags" => [], "avatar" => User.avatar_url(admin) |> MediaProxy.url(), - "display_name" => HTML.strip_tags(admin.name || admin.nickname) + "display_name" => HTML.strip_tags(admin.name || admin.nickname), + "confirmation_pending" => false }, %{ "deactivated" => false, @@ -878,7 +961,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do "roles" => %{"admin" => true, "moderator" => false}, "tags" => [], "avatar" => User.avatar_url(old_admin) |> MediaProxy.url(), - "display_name" => HTML.strip_tags(old_admin.name || old_admin.nickname) + "display_name" => HTML.strip_tags(old_admin.name || old_admin.nickname), + "confirmation_pending" => false } ] |> Enum.sort_by(& &1["nickname"]) @@ -891,7 +975,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do end test "load only admins", %{conn: conn, admin: admin} do - second_admin = insert(:user, info: %{is_admin: true}) + second_admin = insert(:user, is_admin: true) insert(:user) insert(:user) @@ -907,7 +991,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do "local" => admin.local, "tags" => [], "avatar" => User.avatar_url(admin) |> MediaProxy.url(), - "display_name" => HTML.strip_tags(admin.name || admin.nickname) + "display_name" => HTML.strip_tags(admin.name || admin.nickname), + "confirmation_pending" => false }, %{ "deactivated" => false, @@ -917,7 +1002,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do "local" => second_admin.local, "tags" => [], "avatar" => User.avatar_url(second_admin) |> MediaProxy.url(), - "display_name" => HTML.strip_tags(second_admin.name || second_admin.nickname) + "display_name" => HTML.strip_tags(second_admin.name || second_admin.nickname), + "confirmation_pending" => false } ] |> Enum.sort_by(& &1["nickname"]) @@ -930,7 +1016,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do end test "load only moderators", %{conn: conn} do - moderator = insert(:user, info: %{is_moderator: true}) + moderator = insert(:user, is_moderator: true) insert(:user) insert(:user) @@ -948,7 +1034,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do "local" => moderator.local, "tags" => [], "avatar" => User.avatar_url(moderator) |> MediaProxy.url(), - "display_name" => HTML.strip_tags(moderator.name || moderator.nickname) + "display_name" => HTML.strip_tags(moderator.name || moderator.nickname), + "confirmation_pending" => false } ] } @@ -972,7 +1059,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do "local" => user1.local, "tags" => ["first"], "avatar" => User.avatar_url(user1) |> MediaProxy.url(), - "display_name" => HTML.strip_tags(user1.name || user1.nickname) + "display_name" => HTML.strip_tags(user1.name || user1.nickname), + "confirmation_pending" => false }, %{ "deactivated" => false, @@ -982,7 +1070,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do "local" => user2.local, "tags" => ["second"], "avatar" => User.avatar_url(user2) |> MediaProxy.url(), - "display_name" => HTML.strip_tags(user2.name || user2.nickname) + "display_name" => HTML.strip_tags(user2.name || user2.nickname), + "confirmation_pending" => false } ] |> Enum.sort_by(& &1["nickname"]) @@ -995,15 +1084,17 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do end test "it works with multiple filters" do - admin = insert(:user, nickname: "john", info: %{is_admin: true}) - user = insert(:user, nickname: "bob", local: false, info: %{deactivated: true}) + admin = insert(:user, nickname: "john", is_admin: true) + token = insert(:oauth_admin_token, user: admin) + user = insert(:user, nickname: "bob", local: false, deactivated: true) - insert(:user, nickname: "ken", local: true, info: %{deactivated: true}) - insert(:user, nickname: "bobb", local: false, info: %{deactivated: false}) + insert(:user, nickname: "ken", local: true, deactivated: true) + insert(:user, nickname: "bobb", local: false, deactivated: false) conn = build_conn() |> assign(:user, admin) + |> assign(:token, token) |> get("/api/pleroma/admin/users?filters=deactivated,external") assert json_response(conn, 200) == %{ @@ -1011,58 +1102,110 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do "page_size" => 50, "users" => [ %{ - "deactivated" => user.info.deactivated, + "deactivated" => user.deactivated, "id" => user.id, "nickname" => user.nickname, "roles" => %{"admin" => false, "moderator" => false}, "local" => user.local, "tags" => [], "avatar" => User.avatar_url(user) |> MediaProxy.url(), - "display_name" => HTML.strip_tags(user.name || user.nickname) + "display_name" => HTML.strip_tags(user.name || user.nickname), + "confirmation_pending" => false + } + ] + } + end + + test "it omits relay user", %{admin: admin, conn: conn} do + assert %User{} = Relay.get_actor() + + conn = get(conn, "/api/pleroma/admin/users") + + assert json_response(conn, 200) == %{ + "count" => 1, + "page_size" => 50, + "users" => [ + %{ + "deactivated" => admin.deactivated, + "id" => admin.id, + "nickname" => admin.nickname, + "roles" => %{"admin" => true, "moderator" => false}, + "local" => true, + "tags" => [], + "avatar" => User.avatar_url(admin) |> MediaProxy.url(), + "display_name" => HTML.strip_tags(admin.name || admin.nickname), + "confirmation_pending" => false } ] } end end - test "PATCH /api/pleroma/admin/users/:nickname/toggle_activation" do - admin = insert(:user, info: %{is_admin: true}) - user = insert(:user) + test "PATCH /api/pleroma/admin/users/activate", %{admin: admin, conn: conn} do + user_one = insert(:user, deactivated: true) + user_two = insert(:user, deactivated: true) conn = - build_conn() - |> assign(:user, admin) - |> patch("/api/pleroma/admin/users/#{user.nickname}/toggle_activation") + patch( + conn, + "/api/pleroma/admin/users/activate", + %{nicknames: [user_one.nickname, user_two.nickname]} + ) + + response = json_response(conn, 200) + assert Enum.map(response["users"], & &1["deactivated"]) == [false, false] + + log_entry = Repo.one(ModerationLog) + + assert ModerationLog.get_log_entry_message(log_entry) == + "@#{admin.nickname} activated users: @#{user_one.nickname}, @#{user_two.nickname}" + end + + test "PATCH /api/pleroma/admin/users/deactivate", %{admin: admin, conn: conn} do + user_one = insert(:user, deactivated: false) + user_two = insert(:user, deactivated: false) + + conn = + patch( + conn, + "/api/pleroma/admin/users/deactivate", + %{nicknames: [user_one.nickname, user_two.nickname]} + ) + + response = json_response(conn, 200) + assert Enum.map(response["users"], & &1["deactivated"]) == [true, true] + + log_entry = Repo.one(ModerationLog) + + assert ModerationLog.get_log_entry_message(log_entry) == + "@#{admin.nickname} deactivated users: @#{user_one.nickname}, @#{user_two.nickname}" + end + + test "PATCH /api/pleroma/admin/users/:nickname/toggle_activation", %{admin: admin, conn: conn} do + user = insert(:user) + + conn = patch(conn, "/api/pleroma/admin/users/#{user.nickname}/toggle_activation") assert json_response(conn, 200) == %{ - "deactivated" => !user.info.deactivated, + "deactivated" => !user.deactivated, "id" => user.id, "nickname" => user.nickname, "roles" => %{"admin" => false, "moderator" => false}, "local" => true, "tags" => [], "avatar" => User.avatar_url(user) |> MediaProxy.url(), - "display_name" => HTML.strip_tags(user.name || user.nickname) + "display_name" => HTML.strip_tags(user.name || user.nickname), + "confirmation_pending" => false } log_entry = Repo.one(ModerationLog) assert ModerationLog.get_log_entry_message(log_entry) == - "@#{admin.nickname} deactivated user @#{user.nickname}" + "@#{admin.nickname} deactivated users: @#{user.nickname}" end describe "POST /api/pleroma/admin/users/invite_token" do - setup do - admin = insert(:user, info: %{is_admin: true}) - - conn = - build_conn() - |> assign(:user, admin) - - {:ok, conn: conn} - end - test "without options", %{conn: conn} do conn = post(conn, "/api/pleroma/admin/users/invite_token") @@ -1117,16 +1260,6 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do end describe "GET /api/pleroma/admin/users/invites" do - setup do - admin = insert(:user, info: %{is_admin: true}) - - conn = - build_conn() - |> assign(:user, admin) - - {:ok, conn: conn} - end - test "no invites", %{conn: conn} do conn = get(conn, "/api/pleroma/admin/users/invites") @@ -1155,14 +1288,10 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do end describe "POST /api/pleroma/admin/users/revoke_invite" do - test "with token" do - admin = insert(:user, info: %{is_admin: true}) + test "with token", %{conn: conn} do {:ok, invite} = UserInviteToken.create_invite() - conn = - build_conn() - |> assign(:user, admin) - |> post("/api/pleroma/admin/users/revoke_invite", %{"token" => invite.token}) + conn = post(conn, "/api/pleroma/admin/users/revoke_invite", %{"token" => invite.token}) assert json_response(conn, 200) == %{ "expires_at" => nil, @@ -1175,25 +1304,14 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do } end - test "with invalid token" do - admin = insert(:user, info: %{is_admin: true}) - - conn = - build_conn() - |> assign(:user, admin) - |> post("/api/pleroma/admin/users/revoke_invite", %{"token" => "foo"}) + test "with invalid token", %{conn: conn} do + conn = post(conn, "/api/pleroma/admin/users/revoke_invite", %{"token" => "foo"}) assert json_response(conn, :not_found) == "Not found" end end describe "GET /api/pleroma/admin/reports/:id" do - setup %{conn: conn} do - admin = insert(:user, info: %{is_admin: true}) - - %{conn: assign(conn, :user, admin)} - end - test "returns report by its id", %{conn: conn} do [reporter, target_user] = insert_pair(:user) activity = insert(:note_activity, user: target_user) @@ -1220,9 +1338,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do end end - describe "PUT /api/pleroma/admin/reports/:id" do - setup %{conn: conn} do - admin = insert(:user, info: %{is_admin: true}) + describe "PATCH /api/pleroma/admin/reports" do + setup do [reporter, target_user] = insert_pair(:user) activity = insert(:note_activity, user: target_user) @@ -1233,16 +1350,54 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do "status_ids" => [activity.id] }) - %{conn: assign(conn, :user, admin), id: report_id, admin: admin} + {:ok, %{id: second_report_id}} = + CommonAPI.report(reporter, %{ + "account_id" => target_user.id, + "comment" => "I feel very offended", + "status_ids" => [activity.id] + }) + + %{ + id: report_id, + second_report_id: second_report_id + } end - test "mark report as resolved", %{conn: conn, id: id, admin: admin} do + test "requires admin:write:reports scope", %{conn: conn, id: id, admin: admin} do + read_token = insert(:oauth_token, user: admin, scopes: ["admin:read"]) + write_token = insert(:oauth_token, user: admin, scopes: ["admin:write:reports"]) + response = conn - |> put("/api/pleroma/admin/reports/#{id}", %{"state" => "resolved"}) - |> json_response(:ok) + |> assign(:token, read_token) + |> patch("/api/pleroma/admin/reports", %{ + "reports" => [%{"state" => "resolved", "id" => id}] + }) + |> json_response(403) + + assert response == %{ + "error" => "Insufficient permissions: admin:write:reports." + } + + conn + |> assign(:token, write_token) + |> patch("/api/pleroma/admin/reports", %{ + "reports" => [%{"state" => "resolved", "id" => id}] + }) + |> json_response(:no_content) + end + + test "mark report as resolved", %{conn: conn, id: id, admin: admin} do + conn + |> patch("/api/pleroma/admin/reports", %{ + "reports" => [ + %{"state" => "resolved", "id" => id} + ] + }) + |> json_response(:no_content) - assert response["state"] == "resolved" + activity = Activity.get_by_id(id) + assert activity.data["state"] == "resolved" log_entry = Repo.one(ModerationLog) @@ -1251,12 +1406,16 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do end test "closes report", %{conn: conn, id: id, admin: admin} do - response = - conn - |> put("/api/pleroma/admin/reports/#{id}", %{"state" => "closed"}) - |> json_response(:ok) + conn + |> patch("/api/pleroma/admin/reports", %{ + "reports" => [ + %{"state" => "closed", "id" => id} + ] + }) + |> json_response(:no_content) - assert response["state"] == "closed" + activity = Activity.get_by_id(id) + assert activity.data["state"] == "closed" log_entry = Repo.one(ModerationLog) @@ -1267,27 +1426,58 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do test "returns 400 when state is unknown", %{conn: conn, id: id} do conn = conn - |> put("/api/pleroma/admin/reports/#{id}", %{"state" => "test"}) + |> patch("/api/pleroma/admin/reports", %{ + "reports" => [ + %{"state" => "test", "id" => id} + ] + }) - assert json_response(conn, :bad_request) == "Unsupported state" + assert hd(json_response(conn, :bad_request))["error"] == "Unsupported state" end test "returns 404 when report is not exist", %{conn: conn} do conn = conn - |> put("/api/pleroma/admin/reports/test", %{"state" => "closed"}) + |> patch("/api/pleroma/admin/reports", %{ + "reports" => [ + %{"state" => "closed", "id" => "test"} + ] + }) - assert json_response(conn, :not_found) == "Not found" + assert hd(json_response(conn, :bad_request))["error"] == "not_found" end - end - describe "GET /api/pleroma/admin/reports" do - setup %{conn: conn} do - admin = insert(:user, info: %{is_admin: true}) + test "updates state of multiple reports", %{ + conn: conn, + id: id, + admin: admin, + second_report_id: second_report_id + } do + conn + |> patch("/api/pleroma/admin/reports", %{ + "reports" => [ + %{"state" => "resolved", "id" => id}, + %{"state" => "closed", "id" => second_report_id} + ] + }) + |> json_response(:no_content) + + activity = Activity.get_by_id(id) + second_activity = Activity.get_by_id(second_report_id) + assert activity.data["state"] == "resolved" + assert second_activity.data["state"] == "closed" + + [first_log_entry, second_log_entry] = Repo.all(ModerationLog) + + assert ModerationLog.get_log_entry_message(first_log_entry) == + "@#{admin.nickname} updated report ##{id} with 'resolved' state" - %{conn: assign(conn, :user, admin)} + assert ModerationLog.get_log_entry_message(second_log_entry) == + "@#{admin.nickname} updated report ##{second_report_id} with 'closed' state" end + end + describe "GET /api/pleroma/admin/reports" do test "returns empty response when no reports created", %{conn: conn} do response = conn @@ -1382,86 +1572,232 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do test "returns 403 when requested by a non-admin" do user = insert(:user) + token = insert(:oauth_token, user: user) conn = build_conn() |> assign(:user, user) + |> assign(:token, token) |> get("/api/pleroma/admin/reports") - assert json_response(conn, :forbidden) == %{"error" => "User is not admin."} + assert json_response(conn, :forbidden) == + %{"error" => "User is not an admin or OAuth admin scope is not granted."} end test "returns 403 when requested by anonymous" do - conn = - build_conn() - |> get("/api/pleroma/admin/reports") + conn = get(build_conn(), "/api/pleroma/admin/reports") assert json_response(conn, :forbidden) == %{"error" => "Invalid credentials."} end end - # - describe "POST /api/pleroma/admin/reports/:id/respond" do - setup %{conn: conn} do - admin = insert(:user, info: %{is_admin: true}) + describe "GET /api/pleroma/admin/grouped_reports" do + setup do + [reporter, target_user] = insert_pair(:user) - %{conn: assign(conn, :user, admin), admin: admin} - end + date1 = (DateTime.to_unix(DateTime.utc_now()) + 1000) |> DateTime.from_unix!() + date2 = (DateTime.to_unix(DateTime.utc_now()) + 2000) |> DateTime.from_unix!() + date3 = (DateTime.to_unix(DateTime.utc_now()) + 3000) |> DateTime.from_unix!() - test "returns created dm", %{conn: conn, admin: admin} do - [reporter, target_user] = insert_pair(:user) - activity = insert(:note_activity, user: target_user) + first_status = + insert(:note_activity, user: target_user, data_attrs: %{"published" => date1}) - {:ok, %{id: report_id}} = + second_status = + insert(:note_activity, user: target_user, data_attrs: %{"published" => date2}) + + third_status = + insert(:note_activity, user: target_user, data_attrs: %{"published" => date3}) + + {:ok, first_report} = CommonAPI.report(reporter, %{ "account_id" => target_user.id, - "comment" => "I feel offended", - "status_ids" => [activity.id] + "status_ids" => [first_status.id, second_status.id, third_status.id] }) + {:ok, second_report} = + CommonAPI.report(reporter, %{ + "account_id" => target_user.id, + "status_ids" => [first_status.id, second_status.id] + }) + + {:ok, third_report} = + CommonAPI.report(reporter, %{ + "account_id" => target_user.id, + "status_ids" => [first_status.id] + }) + + %{ + first_status: Activity.get_by_ap_id_with_object(first_status.data["id"]), + second_status: Activity.get_by_ap_id_with_object(second_status.data["id"]), + third_status: Activity.get_by_ap_id_with_object(third_status.data["id"]), + first_report: first_report, + first_status_reports: [first_report, second_report, third_report], + second_status_reports: [first_report, second_report], + third_status_reports: [first_report], + target_user: target_user, + reporter: reporter + } + end + + test "returns reports grouped by status", %{ + conn: conn, + first_status: first_status, + second_status: second_status, + third_status: third_status, + first_status_reports: first_status_reports, + second_status_reports: second_status_reports, + third_status_reports: third_status_reports, + target_user: target_user, + reporter: reporter + } do response = conn - |> post("/api/pleroma/admin/reports/#{report_id}/respond", %{ - "status" => "I will check it out" - }) + |> get("/api/pleroma/admin/grouped_reports") |> json_response(:ok) - recipients = Enum.map(response["mentions"], & &1["username"]) + assert length(response["reports"]) == 3 - assert reporter.nickname in recipients - assert response["content"] == "I will check it out" - assert response["visibility"] == "direct" + first_group = Enum.find(response["reports"], &(&1["status"]["id"] == first_status.id)) - log_entry = Repo.one(ModerationLog) + second_group = Enum.find(response["reports"], &(&1["status"]["id"] == second_status.id)) - assert ModerationLog.get_log_entry_message(log_entry) == - "@#{admin.nickname} responded with 'I will check it out' to report ##{ - response["id"] - }" + third_group = Enum.find(response["reports"], &(&1["status"]["id"] == third_status.id)) + + assert length(first_group["reports"]) == 3 + assert length(second_group["reports"]) == 2 + assert length(third_group["reports"]) == 1 + + assert first_group["date"] == + Enum.max_by(first_status_reports, fn act -> + NaiveDateTime.from_iso8601!(act.data["published"]) + end).data["published"] + + assert first_group["status"] == + Map.put( + stringify_keys(StatusView.render("show.json", %{activity: first_status})), + "deleted", + false + ) + + assert(first_group["account"]["id"] == target_user.id) + + assert length(first_group["actors"]) == 1 + assert hd(first_group["actors"])["id"] == reporter.id + + assert Enum.map(first_group["reports"], & &1["id"]) -- + Enum.map(first_status_reports, & &1.id) == [] + + assert second_group["date"] == + Enum.max_by(second_status_reports, fn act -> + NaiveDateTime.from_iso8601!(act.data["published"]) + end).data["published"] + + assert second_group["status"] == + Map.put( + stringify_keys(StatusView.render("show.json", %{activity: second_status})), + "deleted", + false + ) + + assert second_group["account"]["id"] == target_user.id + + assert length(second_group["actors"]) == 1 + assert hd(second_group["actors"])["id"] == reporter.id + + assert Enum.map(second_group["reports"], & &1["id"]) -- + Enum.map(second_status_reports, & &1.id) == [] + + assert third_group["date"] == + Enum.max_by(third_status_reports, fn act -> + NaiveDateTime.from_iso8601!(act.data["published"]) + end).data["published"] + + assert third_group["status"] == + Map.put( + stringify_keys(StatusView.render("show.json", %{activity: third_status})), + "deleted", + false + ) + + assert third_group["account"]["id"] == target_user.id + + assert length(third_group["actors"]) == 1 + assert hd(third_group["actors"])["id"] == reporter.id + + assert Enum.map(third_group["reports"], & &1["id"]) -- + Enum.map(third_status_reports, & &1.id) == [] end - test "returns 400 when status is missing", %{conn: conn} do - conn = post(conn, "/api/pleroma/admin/reports/test/respond") + test "reopened report renders status data", %{ + conn: conn, + first_report: first_report, + first_status: first_status + } do + {:ok, _} = CommonAPI.update_report_state(first_report.id, "resolved") + + response = + conn + |> get("/api/pleroma/admin/grouped_reports") + |> json_response(:ok) + + first_group = Enum.find(response["reports"], &(&1["status"]["id"] == first_status.id)) - assert json_response(conn, :bad_request) == "Invalid parameters" + assert first_group["status"] == + Map.put( + stringify_keys(StatusView.render("show.json", %{activity: first_status})), + "deleted", + false + ) end - test "returns 404 when report id is invalid", %{conn: conn} do - conn = - post(conn, "/api/pleroma/admin/reports/test/respond", %{ - "status" => "foo" - }) + test "reopened report does not render status data if status has been deleted", %{ + conn: conn, + first_report: first_report, + first_status: first_status, + target_user: target_user + } do + {:ok, _} = CommonAPI.update_report_state(first_report.id, "resolved") + {:ok, _} = CommonAPI.delete(first_status.id, target_user) - assert json_response(conn, :not_found) == "Not found" + refute Activity.get_by_ap_id(first_status.id) + + response = + conn + |> get("/api/pleroma/admin/grouped_reports") + |> json_response(:ok) + + assert Enum.find(response["reports"], &(&1["status"]["deleted"] == true))["status"][ + "deleted" + ] == true + + assert length(Enum.filter(response["reports"], &(&1["status"]["deleted"] == false))) == 2 + end + + test "account not empty if status was deleted", %{ + conn: conn, + first_report: first_report, + first_status: first_status, + target_user: target_user + } do + {:ok, _} = CommonAPI.update_report_state(first_report.id, "resolved") + {:ok, _} = CommonAPI.delete(first_status.id, target_user) + + refute Activity.get_by_ap_id(first_status.id) + + response = + conn + |> get("/api/pleroma/admin/grouped_reports") + |> json_response(:ok) + + assert Enum.find(response["reports"], &(&1["status"]["deleted"] == true))["account"] end end describe "PUT /api/pleroma/admin/statuses/:id" do - setup %{conn: conn} do - admin = insert(:user, info: %{is_admin: true}) + setup do activity = insert(:note_activity) - %{conn: assign(conn, :user, admin), id: activity.id, admin: admin} + %{id: activity.id} end test "toggle sensitive flag", %{conn: conn, id: id, admin: admin} do @@ -1514,20 +1850,17 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do end test "returns 400 when visibility is unknown", %{conn: conn, id: id} do - conn = - conn - |> put("/api/pleroma/admin/statuses/#{id}", %{"visibility" => "test"}) + conn = put(conn, "/api/pleroma/admin/statuses/#{id}", %{"visibility" => "test"}) assert json_response(conn, :bad_request) == "Unsupported visibility" end end describe "DELETE /api/pleroma/admin/statuses/:id" do - setup %{conn: conn} do - admin = insert(:user, info: %{is_admin: true}) + setup do activity = insert(:note_activity) - %{conn: assign(conn, :user, admin), id: activity.id, admin: admin} + %{id: activity.id} end test "deletes status", %{conn: conn, id: id, admin: admin} do @@ -1544,21 +1877,13 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do end test "returns error when status is not exist", %{conn: conn} do - conn = - conn - |> delete("/api/pleroma/admin/statuses/test") + conn = delete(conn, "/api/pleroma/admin/statuses/test") assert json_response(conn, :bad_request) == "Could not delete" end end describe "GET /api/pleroma/admin/config" do - setup %{conn: conn} do - admin = insert(:user, info: %{is_admin: true}) - - %{conn: assign(conn, :user, admin)} - end - test "without any settings in db", %{conn: conn} do conn = get(conn, "/api/pleroma/admin/config") @@ -1590,9 +1915,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do end describe "POST /api/pleroma/admin/config" do - setup %{conn: conn} do - admin = insert(:user, info: %{is_admin: true}) - + setup do temp_file = "config/test.exported_from_db.secret.exs" on_exit(fn -> @@ -1606,14 +1929,13 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do Application.delete_env(:pleroma, Pleroma.Captcha.NotReal) :ok = File.rm(temp_file) end) - - %{conn: assign(conn, :user, admin)} end clear_config([:instance, :dynamic_configuration]) do Pleroma.Config.put([:instance, :dynamic_configuration], true) end + @tag capture_log: true test "create new config setting in db", %{conn: conn} do conn = post(conn, "/api/pleroma/admin/config", %{ @@ -2158,9 +2480,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do end describe "config mix tasks run" do - setup %{conn: conn} do - admin = insert(:user, info: %{is_admin: true}) - + setup do temp_file = "config/test.exported_from_db.secret.exs" Mix.shell(Mix.Shell.Quiet) @@ -2170,32 +2490,32 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do :ok = File.rm(temp_file) end) - %{conn: assign(conn, :user, admin), admin: admin} + :ok end clear_config([:instance, :dynamic_configuration]) do Pleroma.Config.put([:instance, :dynamic_configuration], true) end - test "transfer settings to DB and to file", %{conn: conn, admin: admin} do + clear_config([:feed, :post_title]) do + Pleroma.Config.put([:feed, :post_title], %{max_length: 100, omission: "…"}) + end + + test "transfer settings to DB and to file", %{conn: conn} do assert Pleroma.Repo.all(Pleroma.Web.AdminAPI.Config) == [] - conn = get(conn, "/api/pleroma/admin/config/migrate_to_db") - assert json_response(conn, 200) == %{} + ret_conn = get(conn, "/api/pleroma/admin/config/migrate_to_db") + assert json_response(ret_conn, 200) == %{} assert Pleroma.Repo.all(Pleroma.Web.AdminAPI.Config) > 0 - conn = - build_conn() - |> assign(:user, admin) - |> get("/api/pleroma/admin/config/migrate_from_db") + ret_conn = get(conn, "/api/pleroma/admin/config/migrate_from_db") - assert json_response(conn, 200) == %{} + assert json_response(ret_conn, 200) == %{} assert Pleroma.Repo.all(Pleroma.Web.AdminAPI.Config) == [] end end describe "GET /api/pleroma/admin/users/:nickname/statuses" do setup do - admin = insert(:user, info: %{is_admin: true}) user = insert(:user) date1 = (DateTime.to_unix(DateTime.utc_now()) + 2000) |> DateTime.from_unix!() @@ -2206,11 +2526,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do insert(:note_activity, user: user, published: date2) insert(:note_activity, user: user, published: date3) - conn = - build_conn() - |> assign(:user, admin) - - {:ok, conn: conn, user: user} + %{user: user} end test "renders user's statuses", %{conn: conn, user: user} do @@ -2251,10 +2567,10 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do end describe "GET /api/pleroma/admin/moderation_log" do - setup %{conn: conn} do - admin = insert(:user, info: %{is_admin: true}) + setup do + moderator = insert(:user, is_moderator: true) - %{conn: assign(conn, :user, admin), admin: admin} + %{moderator: moderator} end test "returns the log", %{conn: conn, admin: admin} do @@ -2287,9 +2603,9 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do conn = get(conn, "/api/pleroma/admin/moderation_log") response = json_response(conn, 200) - [first_entry, second_entry] = response + [first_entry, second_entry] = response["items"] - assert response |> length() == 2 + assert response["total"] == 2 assert first_entry["data"]["action"] == "relay_unfollow" assert first_entry["message"] == @@ -2331,9 +2647,10 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do conn1 = get(conn, "/api/pleroma/admin/moderation_log?page_size=1&page=1") response1 = json_response(conn1, 200) - [first_entry] = response1 + [first_entry] = response1["items"] - assert response1 |> length() == 1 + assert response1["total"] == 2 + assert response1["items"] |> length() == 1 assert first_entry["data"]["action"] == "relay_unfollow" assert first_entry["message"] == @@ -2342,14 +2659,325 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do conn2 = get(conn, "/api/pleroma/admin/moderation_log?page_size=1&page=2") response2 = json_response(conn2, 200) - [second_entry] = response2 + [second_entry] = response2["items"] - assert response2 |> length() == 1 + assert response2["total"] == 2 + assert response2["items"] |> length() == 1 assert second_entry["data"]["action"] == "relay_follow" assert second_entry["message"] == "@#{admin.nickname} followed relay: https://example.org/relay" end + + test "filters log by date", %{conn: conn, admin: admin} do + first_date = "2017-08-15T15:47:06Z" + second_date = "2017-08-20T15:47:06Z" + + Repo.insert(%ModerationLog{ + data: %{ + actor: %{ + "id" => admin.id, + "nickname" => admin.nickname, + "type" => "user" + }, + action: "relay_follow", + target: "https://example.org/relay" + }, + inserted_at: NaiveDateTime.from_iso8601!(first_date) + }) + + Repo.insert(%ModerationLog{ + data: %{ + actor: %{ + "id" => admin.id, + "nickname" => admin.nickname, + "type" => "user" + }, + action: "relay_unfollow", + target: "https://example.org/relay" + }, + inserted_at: NaiveDateTime.from_iso8601!(second_date) + }) + + conn1 = + get( + conn, + "/api/pleroma/admin/moderation_log?start_date=#{second_date}" + ) + + response1 = json_response(conn1, 200) + [first_entry] = response1["items"] + + assert response1["total"] == 1 + assert first_entry["data"]["action"] == "relay_unfollow" + + assert first_entry["message"] == + "@#{admin.nickname} unfollowed relay: https://example.org/relay" + end + + test "returns log filtered by user", %{conn: conn, admin: admin, moderator: moderator} do + Repo.insert(%ModerationLog{ + data: %{ + actor: %{ + "id" => admin.id, + "nickname" => admin.nickname, + "type" => "user" + }, + action: "relay_follow", + target: "https://example.org/relay" + } + }) + + Repo.insert(%ModerationLog{ + data: %{ + actor: %{ + "id" => moderator.id, + "nickname" => moderator.nickname, + "type" => "user" + }, + action: "relay_unfollow", + target: "https://example.org/relay" + } + }) + + conn1 = get(conn, "/api/pleroma/admin/moderation_log?user_id=#{moderator.id}") + + response1 = json_response(conn1, 200) + [first_entry] = response1["items"] + + assert response1["total"] == 1 + assert get_in(first_entry, ["data", "actor", "id"]) == moderator.id + end + + test "returns log filtered by search", %{conn: conn, moderator: moderator} do + ModerationLog.insert_log(%{ + actor: moderator, + action: "relay_follow", + target: "https://example.org/relay" + }) + + ModerationLog.insert_log(%{ + actor: moderator, + action: "relay_unfollow", + target: "https://example.org/relay" + }) + + conn1 = get(conn, "/api/pleroma/admin/moderation_log?search=unfo") + + response1 = json_response(conn1, 200) + [first_entry] = response1["items"] + + assert response1["total"] == 1 + + assert get_in(first_entry, ["data", "message"]) == + "@#{moderator.nickname} unfollowed relay: https://example.org/relay" + end + end + + describe "PATCH /users/:nickname/force_password_reset" do + test "sets password_reset_pending to true", %{conn: conn} do + user = insert(:user) + assert user.password_reset_pending == false + + conn = + patch(conn, "/api/pleroma/admin/users/force_password_reset", %{nicknames: [user.nickname]}) + + assert json_response(conn, 204) == "" + + ObanHelpers.perform_all() + + assert User.get_by_id(user.id).password_reset_pending == true + end + end + + describe "relays" do + test "POST /relay", %{conn: conn, admin: admin} do + conn = + post(conn, "/api/pleroma/admin/relay", %{ + relay_url: "http://mastodon.example.org/users/admin" + }) + + assert json_response(conn, 200) == "http://mastodon.example.org/users/admin" + + log_entry = Repo.one(ModerationLog) + + assert ModerationLog.get_log_entry_message(log_entry) == + "@#{admin.nickname} followed relay: http://mastodon.example.org/users/admin" + end + + test "GET /relay", %{conn: conn} do + relay_user = Pleroma.Web.ActivityPub.Relay.get_actor() + + ["http://mastodon.example.org/users/admin", "https://mstdn.io/users/mayuutann"] + |> Enum.each(fn ap_id -> + {:ok, user} = User.get_or_fetch_by_ap_id(ap_id) + User.follow(relay_user, user) + end) + + conn = get(conn, "/api/pleroma/admin/relay") + + assert json_response(conn, 200)["relays"] -- ["mastodon.example.org", "mstdn.io"] == [] + end + + test "DELETE /relay", %{conn: conn, admin: admin} do + post(conn, "/api/pleroma/admin/relay", %{ + relay_url: "http://mastodon.example.org/users/admin" + }) + + conn = + delete(conn, "/api/pleroma/admin/relay", %{ + relay_url: "http://mastodon.example.org/users/admin" + }) + + assert json_response(conn, 200) == "http://mastodon.example.org/users/admin" + + [log_entry_one, log_entry_two] = Repo.all(ModerationLog) + + assert ModerationLog.get_log_entry_message(log_entry_one) == + "@#{admin.nickname} followed relay: http://mastodon.example.org/users/admin" + + assert ModerationLog.get_log_entry_message(log_entry_two) == + "@#{admin.nickname} unfollowed relay: http://mastodon.example.org/users/admin" + end + end + + describe "instances" do + test "GET /instances/:instance/statuses", %{conn: conn} do + user = insert(:user, local: false, nickname: "archaeme@archae.me") + user2 = insert(:user, local: false, nickname: "test@test.com") + insert_pair(:note_activity, user: user) + insert(:note_activity, user: user2) + + ret_conn = get(conn, "/api/pleroma/admin/instances/archae.me/statuses") + + response = json_response(ret_conn, 200) + + assert length(response) == 2 + + ret_conn = get(conn, "/api/pleroma/admin/instances/test.com/statuses") + + response = json_response(ret_conn, 200) + + assert length(response) == 1 + + ret_conn = get(conn, "/api/pleroma/admin/instances/nonexistent.com/statuses") + + response = json_response(ret_conn, 200) + + assert Enum.empty?(response) + end + end + + describe "PATCH /confirm_email" do + test "it confirms emails of two users", %{conn: conn, admin: admin} do + [first_user, second_user] = insert_pair(:user, confirmation_pending: true) + + assert first_user.confirmation_pending == true + assert second_user.confirmation_pending == true + + ret_conn = + patch(conn, "/api/pleroma/admin/users/confirm_email", %{ + nicknames: [ + first_user.nickname, + second_user.nickname + ] + }) + + assert ret_conn.status == 200 + + assert first_user.confirmation_pending == true + assert second_user.confirmation_pending == true + + log_entry = Repo.one(ModerationLog) + + assert ModerationLog.get_log_entry_message(log_entry) == + "@#{admin.nickname} confirmed email for users: @#{first_user.nickname}, @#{ + second_user.nickname + }" + end + end + + describe "PATCH /resend_confirmation_email" do + test "it resend emails for two users", %{conn: conn, admin: admin} do + [first_user, second_user] = insert_pair(:user, confirmation_pending: true) + + ret_conn = + patch(conn, "/api/pleroma/admin/users/resend_confirmation_email", %{ + nicknames: [ + first_user.nickname, + second_user.nickname + ] + }) + + assert ret_conn.status == 200 + + log_entry = Repo.one(ModerationLog) + + assert ModerationLog.get_log_entry_message(log_entry) == + "@#{admin.nickname} re-sent confirmation email for users: @#{first_user.nickname}, @#{ + second_user.nickname + }" + end + end + + describe "POST /reports/:id/notes" do + setup %{conn: conn, admin: admin} do + [reporter, target_user] = insert_pair(:user) + activity = insert(:note_activity, user: target_user) + + {:ok, %{id: report_id}} = + CommonAPI.report(reporter, %{ + "account_id" => target_user.id, + "comment" => "I feel offended", + "status_ids" => [activity.id] + }) + + post(conn, "/api/pleroma/admin/reports/#{report_id}/notes", %{ + content: "this is disgusting!" + }) + + post(conn, "/api/pleroma/admin/reports/#{report_id}/notes", %{ + content: "this is disgusting2!" + }) + + %{ + admin_id: admin.id, + report_id: report_id + } + end + + test "it creates report note", %{admin_id: admin_id, report_id: report_id} do + [note, _] = Repo.all(ReportNote) + + assert %{ + activity_id: ^report_id, + content: "this is disgusting!", + user_id: ^admin_id + } = note + end + + test "it returns reports with notes", %{conn: conn, admin: admin} do + conn = get(conn, "/api/pleroma/admin/reports") + + response = json_response(conn, 200) + notes = hd(response["reports"])["notes"] + [note, _] = notes + + assert note["user"]["nickname"] == admin.nickname + assert note["content"] == "this is disgusting!" + assert note["created_at"] + assert response["total"] == 1 + end + + test "it deletes the note", %{conn: conn, report_id: report_id} do + assert ReportNote |> Repo.all() |> length() == 2 + + [note, _] = Repo.all(ReportNote) + + delete(conn, "/api/pleroma/admin/reports/#{report_id}/notes/#{note.id}") + + assert ReportNote |> Repo.all() |> length() == 1 + end end end