diff options
Diffstat (limited to 'test')
34 files changed, 1753 insertions, 1193 deletions
diff --git a/test/fixtures/mewmew_no_name.json b/test/fixtures/mewmew_no_name.json new file mode 100644 index 000000000..532d4cf70 --- /dev/null +++ b/test/fixtures/mewmew_no_name.json @@ -0,0 +1,46 @@ +{ + "@context" : [ + "https://www.w3.org/ns/activitystreams", + "https://princess.cat/schemas/litepub-0.1.jsonld", + { + "@language" : "und" + } + ], + "attachment" : [], + "capabilities" : { + "acceptsChatMessages" : true + }, + "discoverable" : false, + "endpoints" : { + "oauthAuthorizationEndpoint" : "https://princess.cat/oauth/authorize", + "oauthRegistrationEndpoint" : "https://princess.cat/api/v1/apps", + "oauthTokenEndpoint" : "https://princess.cat/oauth/token", + "sharedInbox" : "https://princess.cat/inbox", + "uploadMedia" : "https://princess.cat/api/ap/upload_media" + }, + "followers" : "https://princess.cat/users/mewmew/followers", + "following" : "https://princess.cat/users/mewmew/following", + "icon" : { + "type" : "Image", + "url" : "https://princess.cat/media/12794fb50e86911e65be97f69196814049dcb398a2f8b58b99bb6591576e648c.png?name=blobcatpresentpink.png" + }, + "id" : "https://princess.cat/users/mewmew", + "image" : { + "type" : "Image", + "url" : "https://princess.cat/media/05d8bf3953ab6028fc920494ffc643fbee9dcef40d7bdd06f107e19acbfbd7f9.png" + }, + "inbox" : "https://princess.cat/users/mewmew/inbox", + "manuallyApprovesFollowers" : true, + "name" : " ", + "outbox" : "https://princess.cat/users/mewmew/outbox", + "preferredUsername" : "mewmew", + "publicKey" : { + "id" : "https://princess.cat/users/mewmew#main-key", + "owner" : "https://princess.cat/users/mewmew", + "publicKeyPem" : "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAru7VpygVef4zrFwnj0Mh\nrbO/2z2EdKN3rERtNrT8zWsLXNLQ50lfpRPnGDrd+xq7Rva4EIu0d5KJJ9n4vtY0\nuxK3On9vA2oyjLlR9O0lI3XTrHJborG3P7IPXrmNUMFpHiFHNqHp5tugUrs1gUFq\n7tmOmM92IP4Wjk8qNHFcsfnUbaPTX7sNIhteQKdi5HrTb/6lrEIe4G/FlMKRqxo3\nRNHuv6SNFQuiUKvFzjzazvjkjvBSm+aFROgdHa2tKl88StpLr7xmuY8qNFCRT6W0\nLacRp6c8ah5f03Kd+xCBVhCKvKaF1K0ERnQTBiitUh85md+Mtx/CoDoLnmpnngR3\nvQIDAQAB\n-----END PUBLIC KEY-----\n\n" + }, + "summary" : "please reply to my posts as direct messages if you have many followers", + "tag" : [], + "type" : "Person", + "url" : "https://princess.cat/users/mewmew" +} diff --git a/test/pleroma/conversation/participation_test.exs b/test/pleroma/conversation/participation_test.exs index 59a1b6492..5a603dcc1 100644 --- a/test/pleroma/conversation/participation_test.exs +++ b/test/pleroma/conversation/participation_test.exs @@ -37,9 +37,8 @@ defmodule Pleroma.Conversation.ParticipationTest do [%{read: true}] = Participation.for_user(user) [%{read: false} = participation] = Participation.for_user(other_user) - - assert User.get_cached_by_id(user.id).unread_conversation_count == 0 - assert User.get_cached_by_id(other_user.id).unread_conversation_count == 1 + assert Participation.unread_count(user) == 0 + assert Participation.unread_count(other_user) == 1 {:ok, _} = CommonAPI.post(other_user, %{ @@ -54,8 +53,8 @@ defmodule Pleroma.Conversation.ParticipationTest do [%{read: false}] = Participation.for_user(user) [%{read: true}] = Participation.for_user(other_user) - assert User.get_cached_by_id(user.id).unread_conversation_count == 1 - assert User.get_cached_by_id(other_user.id).unread_conversation_count == 0 + assert Participation.unread_count(user) == 1 + assert Participation.unread_count(other_user) == 0 end test "for a new conversation, it sets the recipents of the participation" do @@ -264,7 +263,7 @@ defmodule Pleroma.Conversation.ParticipationTest do assert [%{read: false}, %{read: false}, %{read: false}, %{read: false}] = Participation.for_user(blocker) - assert User.get_cached_by_id(blocker.id).unread_conversation_count == 4 + assert Participation.unread_count(blocker) == 4 {:ok, _user_relationship} = User.block(blocker, blocked) @@ -272,15 +271,15 @@ defmodule Pleroma.Conversation.ParticipationTest do assert [%{read: true}, %{read: true}, %{read: true}, %{read: false}] = Participation.for_user(blocker) - assert User.get_cached_by_id(blocker.id).unread_conversation_count == 1 + assert Participation.unread_count(blocker) == 1 # The conversation is not marked as read for the blocked user assert [_, _, %{read: false}] = Participation.for_user(blocked) - assert User.get_cached_by_id(blocked.id).unread_conversation_count == 1 + assert Participation.unread_count(blocker) == 1 # The conversation is not marked as read for the third user assert [%{read: false}, _, _] = Participation.for_user(third_user) - assert User.get_cached_by_id(third_user.id).unread_conversation_count == 1 + assert Participation.unread_count(third_user) == 1 end test "the new conversation with the blocked user is not marked as unread " do @@ -298,7 +297,7 @@ defmodule Pleroma.Conversation.ParticipationTest do }) assert [%{read: true}] = Participation.for_user(blocker) - assert User.get_cached_by_id(blocker.id).unread_conversation_count == 0 + assert Participation.unread_count(blocker) == 0 # When the blocked user is a recipient {:ok, _direct2} = @@ -308,10 +307,10 @@ defmodule Pleroma.Conversation.ParticipationTest do }) assert [%{read: true}, %{read: true}] = Participation.for_user(blocker) - assert User.get_cached_by_id(blocker.id).unread_conversation_count == 0 + assert Participation.unread_count(blocker) == 0 assert [%{read: false}, _] = Participation.for_user(blocked) - assert User.get_cached_by_id(blocked.id).unread_conversation_count == 1 + assert Participation.unread_count(blocked) == 1 end test "the conversation with the blocked user is not marked as unread on a reply" do @@ -327,8 +326,8 @@ defmodule Pleroma.Conversation.ParticipationTest do {:ok, _user_relationship} = User.block(blocker, blocked) assert [%{read: true}] = Participation.for_user(blocker) - assert User.get_cached_by_id(blocker.id).unread_conversation_count == 0 + assert Participation.unread_count(blocker) == 0 assert [blocked_participation] = Participation.for_user(blocked) # When it's a reply from the blocked user @@ -340,8 +339,8 @@ defmodule Pleroma.Conversation.ParticipationTest do }) assert [%{read: true}] = Participation.for_user(blocker) - assert User.get_cached_by_id(blocker.id).unread_conversation_count == 0 + assert Participation.unread_count(blocker) == 0 assert [third_user_participation] = Participation.for_user(third_user) # When it's a reply from the third user @@ -353,11 +352,12 @@ defmodule Pleroma.Conversation.ParticipationTest do }) assert [%{read: true}] = Participation.for_user(blocker) - assert User.get_cached_by_id(blocker.id).unread_conversation_count == 0 + assert Participation.unread_count(blocker) == 0 # Marked as unread for the blocked user assert [%{read: false}] = Participation.for_user(blocked) - assert User.get_cached_by_id(blocked.id).unread_conversation_count == 1 + + assert Participation.unread_count(blocked) == 1 end end end diff --git a/test/pleroma/user/backup_test.exs b/test/pleroma/user/backup_test.exs new file mode 100644 index 000000000..f68e4a029 --- /dev/null +++ b/test/pleroma/user/backup_test.exs @@ -0,0 +1,244 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.User.BackupTest do + use Oban.Testing, repo: Pleroma.Repo + use Pleroma.DataCase + + import Mock + import Pleroma.Factory + import Swoosh.TestAssertions + + alias Pleroma.Bookmark + alias Pleroma.Tests.ObanHelpers + alias Pleroma.User.Backup + alias Pleroma.Web.CommonAPI + alias Pleroma.Workers.BackupWorker + + setup do + clear_config([Pleroma.Upload, :uploader]) + clear_config([Backup, :limit_days]) + clear_config([Pleroma.Emails.Mailer, :enabled], true) + end + + test "it requries enabled email" do + Pleroma.Config.put([Pleroma.Emails.Mailer, :enabled], false) + user = insert(:user) + assert {:error, "Backups require enabled email"} == Backup.create(user) + end + + test "it requries user's email" do + user = insert(:user, %{email: nil}) + assert {:error, "Email is required"} == Backup.create(user) + end + + test "it creates a backup record and an Oban job" do + %{id: user_id} = user = insert(:user) + assert {:ok, %Oban.Job{args: args}} = Backup.create(user) + assert_enqueued(worker: BackupWorker, args: args) + + backup = Backup.get(args["backup_id"]) + assert %Backup{user_id: ^user_id, processed: false, file_size: 0} = backup + end + + test "it return an error if the export limit is over" do + %{id: user_id} = user = insert(:user) + limit_days = Pleroma.Config.get([Backup, :limit_days]) + assert {:ok, %Oban.Job{args: args}} = Backup.create(user) + backup = Backup.get(args["backup_id"]) + assert %Backup{user_id: ^user_id, processed: false, file_size: 0} = backup + + assert Backup.create(user) == {:error, "Last export was less than #{limit_days} days ago"} + end + + test "it process a backup record" do + Pleroma.Config.put([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local) + %{id: user_id} = user = insert(:user) + + assert {:ok, %Oban.Job{args: %{"backup_id" => backup_id} = args}} = Backup.create(user) + assert {:ok, backup} = perform_job(BackupWorker, args) + assert backup.file_size > 0 + assert %Backup{id: ^backup_id, processed: true, user_id: ^user_id} = backup + + delete_job_args = %{"op" => "delete", "backup_id" => backup_id} + + assert_enqueued(worker: BackupWorker, args: delete_job_args) + assert {:ok, backup} = perform_job(BackupWorker, delete_job_args) + refute Backup.get(backup_id) + + email = Pleroma.Emails.UserEmail.backup_is_ready_email(backup) + + assert_email_sent( + to: {user.name, user.email}, + html_body: email.html_body + ) + end + + test "it removes outdated backups after creating a fresh one" do + Pleroma.Config.put([Backup, :limit_days], -1) + Pleroma.Config.put([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local) + user = insert(:user) + + assert {:ok, job1} = Backup.create(user) + + assert {:ok, %Backup{}} = ObanHelpers.perform(job1) + assert {:ok, job2} = Backup.create(user) + assert Pleroma.Repo.aggregate(Backup, :count) == 2 + assert {:ok, backup2} = ObanHelpers.perform(job2) + + ObanHelpers.perform_all() + + assert [^backup2] = Pleroma.Repo.all(Backup) + end + + test "it creates a zip archive with user data" do + user = insert(:user, %{nickname: "cofe", name: "Cofe", ap_id: "http://cofe.io/users/cofe"}) + + {:ok, %{object: %{data: %{"id" => id1}}} = status1} = + CommonAPI.post(user, %{status: "status1"}) + + {:ok, %{object: %{data: %{"id" => id2}}} = status2} = + CommonAPI.post(user, %{status: "status2"}) + + {:ok, %{object: %{data: %{"id" => id3}}} = status3} = + CommonAPI.post(user, %{status: "status3"}) + + CommonAPI.favorite(user, status1.id) + CommonAPI.favorite(user, status2.id) + + Bookmark.create(user.id, status2.id) + Bookmark.create(user.id, status3.id) + + assert {:ok, backup} = user |> Backup.new() |> Repo.insert() + assert {:ok, path} = Backup.export(backup) + assert {:ok, zipfile} = :zip.zip_open(String.to_charlist(path), [:memory]) + assert {:ok, {'actor.json', json}} = :zip.zip_get('actor.json', zipfile) + + assert %{ + "@context" => [ + "https://www.w3.org/ns/activitystreams", + "http://localhost:4001/schemas/litepub-0.1.jsonld", + %{"@language" => "und"} + ], + "bookmarks" => "bookmarks.json", + "followers" => "http://cofe.io/users/cofe/followers", + "following" => "http://cofe.io/users/cofe/following", + "id" => "http://cofe.io/users/cofe", + "inbox" => "http://cofe.io/users/cofe/inbox", + "likes" => "likes.json", + "name" => "Cofe", + "outbox" => "http://cofe.io/users/cofe/outbox", + "preferredUsername" => "cofe", + "publicKey" => %{ + "id" => "http://cofe.io/users/cofe#main-key", + "owner" => "http://cofe.io/users/cofe" + }, + "type" => "Person", + "url" => "http://cofe.io/users/cofe" + } = Jason.decode!(json) + + assert {:ok, {'outbox.json', json}} = :zip.zip_get('outbox.json', zipfile) + + assert %{ + "@context" => "https://www.w3.org/ns/activitystreams", + "id" => "outbox.json", + "orderedItems" => [ + %{ + "object" => %{ + "actor" => "http://cofe.io/users/cofe", + "content" => "status1", + "type" => "Note" + }, + "type" => "Create" + }, + %{ + "object" => %{ + "actor" => "http://cofe.io/users/cofe", + "content" => "status2" + } + }, + %{ + "actor" => "http://cofe.io/users/cofe", + "object" => %{ + "content" => "status3" + } + } + ], + "totalItems" => 3, + "type" => "OrderedCollection" + } = Jason.decode!(json) + + assert {:ok, {'likes.json', json}} = :zip.zip_get('likes.json', zipfile) + + assert %{ + "@context" => "https://www.w3.org/ns/activitystreams", + "id" => "likes.json", + "orderedItems" => [^id1, ^id2], + "totalItems" => 2, + "type" => "OrderedCollection" + } = Jason.decode!(json) + + assert {:ok, {'bookmarks.json', json}} = :zip.zip_get('bookmarks.json', zipfile) + + assert %{ + "@context" => "https://www.w3.org/ns/activitystreams", + "id" => "bookmarks.json", + "orderedItems" => [^id2, ^id3], + "totalItems" => 2, + "type" => "OrderedCollection" + } = Jason.decode!(json) + + :zip.zip_close(zipfile) + File.rm!(path) + end + + describe "it uploads and deletes a backup archive" do + setup do + clear_config(Pleroma.Uploaders.S3, + bucket: "test_bucket", + public_endpoint: "https://s3.amazonaws.com" + ) + + clear_config([Pleroma.Upload, :uploader]) + + user = insert(:user, %{nickname: "cofe", name: "Cofe", ap_id: "http://cofe.io/users/cofe"}) + + {:ok, status1} = CommonAPI.post(user, %{status: "status1"}) + {:ok, status2} = CommonAPI.post(user, %{status: "status2"}) + {:ok, status3} = CommonAPI.post(user, %{status: "status3"}) + CommonAPI.favorite(user, status1.id) + CommonAPI.favorite(user, status2.id) + Bookmark.create(user.id, status2.id) + Bookmark.create(user.id, status3.id) + + assert {:ok, backup} = user |> Backup.new() |> Repo.insert() + assert {:ok, path} = Backup.export(backup) + + [path: path, backup: backup] + end + + test "S3", %{path: path, backup: backup} do + Pleroma.Config.put([Pleroma.Upload, :uploader], Pleroma.Uploaders.S3) + + with_mock ExAws, + request: fn + %{http_method: :put} -> {:ok, :ok} + %{http_method: :delete} -> {:ok, %{status_code: 204}} + end do + assert {:ok, %Pleroma.Upload{}} = Backup.upload(backup, path) + assert {:ok, _backup} = Backup.delete(backup) + end + + with_mock ExAws, request: fn %{http_method: :delete} -> {:ok, %{status_code: 204}} end do + end + end + + test "Local", %{path: path, backup: backup} do + Pleroma.Config.put([Pleroma.Upload, :uploader], Pleroma.Uploaders.Local) + + assert {:ok, %Pleroma.Upload{}} = Backup.upload(backup, path) + assert {:ok, _backup} = Backup.delete(backup) + end + end +end diff --git a/test/pleroma/user_test.exs b/test/pleroma/user_test.exs index 7220ce846..9ae52d594 100644 --- a/test/pleroma/user_test.exs +++ b/test/pleroma/user_test.exs @@ -388,6 +388,7 @@ defmodule Pleroma.UserTest do } setup do: clear_config([:instance, :autofollowed_nicknames]) + setup do: clear_config([:instance, :autofollowing_nicknames]) setup do: clear_config([:welcome]) setup do: clear_config([:instance, :account_activation_required]) @@ -408,6 +409,23 @@ defmodule Pleroma.UserTest do refute User.following?(registered_user, remote_user) end + test "it adds automatic followers for new registered accounts" do + user1 = insert(:user) + user2 = insert(:user) + + Pleroma.Config.put([:instance, :autofollowing_nicknames], [ + user1.nickname, + user2.nickname + ]) + + cng = User.register_changeset(%User{}, @full_user_data) + + {:ok, registered_user} = User.register(cng) + + assert User.following?(user1, registered_user) + assert User.following?(user2, registered_user) + end + test "it sends a welcome message if it is set" do welcome_user = insert(:user) Pleroma.Config.put([:welcome, :direct_message, :enabled], true) diff --git a/test/pleroma/web/activity_pub/activity_pub_controller_test.exs b/test/pleroma/web/activity_pub/activity_pub_controller_test.exs index b11e2f961..b696a24f4 100644 --- a/test/pleroma/web/activity_pub/activity_pub_controller_test.exs +++ b/test/pleroma/web/activity_pub/activity_pub_controller_test.exs @@ -156,21 +156,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do assert response == "Not found" end - - test "it requires authentication if instance is NOT federating", %{ - conn: conn - } do - user = insert(:user) - - conn = - put_req_header( - conn, - "accept", - "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"" - ) - - ensure_federating_or_authenticated(conn, "/users/#{user.nickname}.json", user) - end end describe "mastodon compatibility routes" do @@ -338,18 +323,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do assert "Not found" == json_response(conn2, :not_found) end - - test "it requires authentication if instance is NOT federating", %{ - conn: conn - } do - user = insert(:user) - note = insert(:note) - uuid = String.split(note.data["id"], "/") |> List.last() - - conn = put_req_header(conn, "accept", "application/activity+json") - - ensure_federating_or_authenticated(conn, "/objects/#{uuid}", user) - end end describe "/activities/:uuid" do @@ -421,18 +394,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do assert "Not found" == json_response(conn2, :not_found) end - - test "it requires authentication if instance is NOT federating", %{ - conn: conn - } do - user = insert(:user) - activity = insert(:note_activity) - uuid = String.split(activity.data["id"], "/") |> List.last() - - conn = put_req_header(conn, "accept", "application/activity+json") - - ensure_federating_or_authenticated(conn, "/activities/#{uuid}", user) - end end describe "/inbox" do @@ -893,15 +854,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do assert response(conn, 200) =~ announce_activity.data["object"] end - - test "it requires authentication if instance is NOT federating", %{ - conn: conn - } do - user = insert(:user) - conn = put_req_header(conn, "accept", "application/activity+json") - - ensure_federating_or_authenticated(conn, "/users/#{user.nickname}/outbox", user) - end end describe "POST /users/:nickname/outbox (C2S)" do diff --git a/test/pleroma/web/activity_pub/activity_pub_test.exs b/test/pleroma/web/activity_pub/activity_pub_test.exs index 6ac883b23..43bd14ee6 100644 --- a/test/pleroma/web/activity_pub/activity_pub_test.exs +++ b/test/pleroma/web/activity_pub/activity_pub_test.exs @@ -2273,4 +2273,15 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do assert length(activities) == 2 end end + + test "allow fetching of accounts with an empty string name field" do + Tesla.Mock.mock(fn + %{method: :get, url: "https://princess.cat/users/mewmew"} -> + file = File.read!("test/fixtures/mewmew_no_name.json") + %Tesla.Env{status: 200, body: file} + end) + + {:ok, user} = ActivityPub.make_user_from_ap_id("https://princess.cat/users/mewmew") + assert user.name == " " + end end diff --git a/test/pleroma/web/admin_api/controllers/admin_api_controller_test.exs b/test/pleroma/web/admin_api/controllers/admin_api_controller_test.exs index cba6b43d3..74140b7bc 100644 --- a/test/pleroma/web/admin_api/controllers/admin_api_controller_test.exs +++ b/test/pleroma/web/admin_api/controllers/admin_api_controller_test.exs @@ -7,22 +7,16 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do use Oban.Testing, repo: Pleroma.Repo import ExUnit.CaptureLog - import Mock import Pleroma.Factory import Swoosh.TestAssertions alias Pleroma.Activity - alias Pleroma.Config - alias Pleroma.HTML alias Pleroma.MFA alias Pleroma.ModerationLog alias Pleroma.Repo alias Pleroma.Tests.ObanHelpers alias Pleroma.User - alias Pleroma.Web - alias Pleroma.Web.ActivityPub.Relay alias Pleroma.Web.CommonAPI - alias Pleroma.Web.MediaProxy setup_all do Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end) @@ -153,300 +147,6 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do end end - describe "DELETE /api/pleroma/admin/users" do - test "single user", %{admin: admin, conn: conn} do - clear_config([:instance, :federating], true) - - user = - insert(:user, - avatar: %{"url" => [%{"href" => "https://someurl"}]}, - banner: %{"url" => [%{"href" => "https://somebanner"}]}, - bio: "Hello world!", - name: "A guy" - ) - - # Create some activities to check they got deleted later - follower = insert(:user) - {:ok, _} = CommonAPI.post(user, %{status: "test"}) - {:ok, _, _, _} = CommonAPI.follow(user, follower) - {:ok, _, _, _} = CommonAPI.follow(follower, user) - user = Repo.get(User, user.id) - assert user.note_count == 1 - assert user.follower_count == 1 - assert user.following_count == 1 - refute user.deactivated - - with_mock Pleroma.Web.Federator, - publish: fn _ -> nil end, - perform: fn _, _ -> nil end do - conn = - conn - |> put_req_header("accept", "application/json") - |> delete("/api/pleroma/admin/users?nickname=#{user.nickname}") - - ObanHelpers.perform_all() - - assert User.get_by_nickname(user.nickname).deactivated - - log_entry = Repo.one(ModerationLog) - - assert ModerationLog.get_log_entry_message(log_entry) == - "@#{admin.nickname} deleted users: @#{user.nickname}" - - assert json_response(conn, 200) == [user.nickname] - - user = Repo.get(User, user.id) - assert user.deactivated - - assert user.avatar == %{} - assert user.banner == %{} - assert user.note_count == 0 - assert user.follower_count == 0 - assert user.following_count == 0 - assert user.bio == "" - assert user.name == nil - - assert called(Pleroma.Web.Federator.publish(:_)) - end - end - - test "multiple users", %{admin: admin, conn: conn} do - user_one = insert(:user) - user_two = insert(:user) - - conn = - 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" => [ - %{ - "nickname" => "lain", - "email" => "lain@example.org", - "password" => "test" - }, - %{ - "nickname" => "lain2", - "email" => "lain2@example.org", - "password" => "test" - } - ] - }) - - response = json_response(conn, 200) |> Enum.map(&Map.get(&1, "type")) - assert response == ["success", "success"] - - log_entry = Repo.one(ModerationLog) - - assert ["lain", "lain2"] -- Enum.map(log_entry.data["subjects"], & &1["nickname"]) == [] - end - - test "Cannot create user with existing email", %{conn: conn} do - user = insert(:user) - - conn = - conn - |> put_req_header("accept", "application/json") - |> post("/api/pleroma/admin/users", %{ - "users" => [ - %{ - "nickname" => "lain", - "email" => user.email, - "password" => "test" - } - ] - }) - - assert json_response(conn, 409) == [ - %{ - "code" => 409, - "data" => %{ - "email" => user.email, - "nickname" => "lain" - }, - "error" => "email has already been taken", - "type" => "error" - } - ] - end - - test "Cannot create user with existing nickname", %{conn: conn} do - user = insert(:user) - - conn = - conn - |> put_req_header("accept", "application/json") - |> post("/api/pleroma/admin/users", %{ - "users" => [ - %{ - "nickname" => user.nickname, - "email" => "someuser@plerama.social", - "password" => "test" - } - ] - }) - - assert json_response(conn, 409) == [ - %{ - "code" => 409, - "data" => %{ - "email" => "someuser@plerama.social", - "nickname" => user.nickname - }, - "error" => "nickname has already been taken", - "type" => "error" - } - ] - end - - test "Multiple user creation works in transaction", %{conn: conn} do - user = insert(:user) - - conn = - conn - |> put_req_header("accept", "application/json") - |> post("/api/pleroma/admin/users", %{ - "users" => [ - %{ - "nickname" => "newuser", - "email" => "newuser@pleroma.social", - "password" => "test" - }, - %{ - "nickname" => "lain", - "email" => user.email, - "password" => "test" - } - ] - }) - - assert json_response(conn, 409) == [ - %{ - "code" => 409, - "data" => %{ - "email" => user.email, - "nickname" => "lain" - }, - "error" => "email has already been taken", - "type" => "error" - }, - %{ - "code" => 409, - "data" => %{ - "email" => "newuser@pleroma.social", - "nickname" => "newuser" - }, - "error" => "", - "type" => "error" - } - ] - - assert User.get_by_nickname("newuser") === nil - end - end - - describe "/api/pleroma/admin/users/:nickname" do - test "Show", %{conn: conn} do - user = insert(:user) - - conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}") - - expected = %{ - "deactivated" => false, - "id" => to_string(user.id), - "local" => true, - "nickname" => user.nickname, - "roles" => %{"admin" => false, "moderator" => false}, - "tags" => [], - "avatar" => User.avatar_url(user) |> MediaProxy.url(), - "display_name" => HTML.strip_tags(user.name || user.nickname), - "confirmation_pending" => false, - "approval_pending" => false, - "url" => user.ap_id, - "registration_reason" => nil, - "actor_type" => "Person" - } - - assert expected == json_response(conn, 200) - end - - test "when the user doesn't exist", %{conn: conn} do - user = build(:user) - - conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}") - - assert %{"error" => "Not found"} == json_response(conn, 404) - end - end - - describe "/api/pleroma/admin/users/follow" do - test "allows to force-follow another user", %{admin: admin, conn: conn} do - user = insert(:user) - follower = insert(:user) - - conn - |> put_req_header("accept", "application/json") - |> post("/api/pleroma/admin/users/follow", %{ - "follower" => follower.nickname, - "followed" => user.nickname - }) - - user = User.get_cached_by_id(user.id) - follower = User.get_cached_by_id(follower.id) - - assert User.following?(follower, user) - - log_entry = Repo.one(ModerationLog) - - assert ModerationLog.get_log_entry_message(log_entry) == - "@#{admin.nickname} made @#{follower.nickname} follow @#{user.nickname}" - end - end - - describe "/api/pleroma/admin/users/unfollow" do - test "allows to force-unfollow another user", %{admin: admin, conn: conn} do - user = insert(:user) - follower = insert(:user) - - User.follow(follower, user) - - conn - |> put_req_header("accept", "application/json") - |> post("/api/pleroma/admin/users/unfollow", %{ - "follower" => follower.nickname, - "followed" => user.nickname - }) - - user = User.get_cached_by_id(user.id) - follower = User.get_cached_by_id(follower.id) - - refute User.following?(follower, user) - - log_entry = Repo.one(ModerationLog) - - assert ModerationLog.get_log_entry_message(log_entry) == - "@#{admin.nickname} made @#{follower.nickname} unfollow @#{user.nickname}" - end - end - describe "PUT /api/pleroma/admin/users/tag" do setup %{conn: conn} do user1 = insert(:user, %{tags: ["x"]}) @@ -643,753 +343,6 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do assert Regex.match?(~r/(http:\/\/|https:\/\/)/, resp["link"]) end - describe "GET /api/pleroma/admin/users" do - test "renders users array for the first page", %{conn: conn, admin: admin} do - user = insert(:user, local: false, tags: ["foo", "bar"]) - user2 = insert(:user, approval_pending: true, registration_reason: "I'm a chill dude") - - conn = get(conn, "/api/pleroma/admin/users?page=1") - - 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, - "approval_pending" => false, - "url" => admin.ap_id, - "registration_reason" => nil, - "actor_type" => "Person" - }, - %{ - "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), - "confirmation_pending" => false, - "approval_pending" => false, - "url" => user.ap_id, - "registration_reason" => nil, - "actor_type" => "Person" - }, - %{ - "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), - "confirmation_pending" => false, - "approval_pending" => true, - "url" => user2.ap_id, - "registration_reason" => "I'm a chill dude", - "actor_type" => "Person" - } - ] - |> Enum.sort_by(& &1["nickname"]) - - assert json_response(conn, 200) == %{ - "count" => 3, - "page_size" => 50, - "users" => users - } - end - - test "pagination works correctly with service users", %{conn: conn} do - service1 = User.get_or_create_service_actor_by_ap_id(Web.base_url() <> "/meido", "meido") - - insert_list(25, :user) - - assert %{"count" => 26, "page_size" => 10, "users" => users1} = - conn - |> get("/api/pleroma/admin/users?page=1&filters=", %{page_size: "10"}) - |> json_response(200) - - assert Enum.count(users1) == 10 - assert service1 not in users1 - - assert %{"count" => 26, "page_size" => 10, "users" => users2} = - conn - |> get("/api/pleroma/admin/users?page=2&filters=", %{page_size: "10"}) - |> json_response(200) - - assert Enum.count(users2) == 10 - assert service1 not in users2 - - assert %{"count" => 26, "page_size" => 10, "users" => users3} = - conn - |> get("/api/pleroma/admin/users?page=3&filters=", %{page_size: "10"}) - |> json_response(200) - - assert Enum.count(users3) == 6 - assert service1 not in users3 - end - - test "renders empty array for the second page", %{conn: conn} do - insert(:user) - - conn = get(conn, "/api/pleroma/admin/users?page=2") - - assert json_response(conn, 200) == %{ - "count" => 2, - "page_size" => 50, - "users" => [] - } - end - - test "regular search", %{conn: conn} do - user = insert(:user, nickname: "bob") - - conn = get(conn, "/api/pleroma/admin/users?query=bo") - - assert json_response(conn, 200) == %{ - "count" => 1, - "page_size" => 50, - "users" => [ - %{ - "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), - "confirmation_pending" => false, - "approval_pending" => false, - "url" => user.ap_id, - "registration_reason" => nil, - "actor_type" => "Person" - } - ] - } - end - - test "search by domain", %{conn: conn} do - user = insert(:user, nickname: "nickname@domain.com") - insert(:user) - - conn = get(conn, "/api/pleroma/admin/users?query=domain.com") - - assert json_response(conn, 200) == %{ - "count" => 1, - "page_size" => 50, - "users" => [ - %{ - "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), - "confirmation_pending" => false, - "approval_pending" => false, - "url" => user.ap_id, - "registration_reason" => nil, - "actor_type" => "Person" - } - ] - } - end - - test "search by full nickname", %{conn: conn} do - user = insert(:user, nickname: "nickname@domain.com") - insert(:user) - - conn = get(conn, "/api/pleroma/admin/users?query=nickname@domain.com") - - assert json_response(conn, 200) == %{ - "count" => 1, - "page_size" => 50, - "users" => [ - %{ - "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), - "confirmation_pending" => false, - "approval_pending" => false, - "url" => user.ap_id, - "registration_reason" => nil, - "actor_type" => "Person" - } - ] - } - end - - test "search by display name", %{conn: conn} do - user = insert(:user, name: "Display name") - insert(:user) - - conn = get(conn, "/api/pleroma/admin/users?name=display") - - assert json_response(conn, 200) == %{ - "count" => 1, - "page_size" => 50, - "users" => [ - %{ - "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), - "confirmation_pending" => false, - "approval_pending" => false, - "url" => user.ap_id, - "registration_reason" => nil, - "actor_type" => "Person" - } - ] - } - end - - test "search by email", %{conn: conn} do - user = insert(:user, email: "email@example.com") - insert(:user) - - conn = get(conn, "/api/pleroma/admin/users?email=email@example.com") - - assert json_response(conn, 200) == %{ - "count" => 1, - "page_size" => 50, - "users" => [ - %{ - "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), - "confirmation_pending" => false, - "approval_pending" => false, - "url" => user.ap_id, - "registration_reason" => nil, - "actor_type" => "Person" - } - ] - } - end - - test "regular search with page size", %{conn: conn} do - user = insert(:user, nickname: "aalice") - user2 = insert(:user, nickname: "alice") - - conn1 = get(conn, "/api/pleroma/admin/users?query=a&page_size=1&page=1") - - assert json_response(conn1, 200) == %{ - "count" => 2, - "page_size" => 1, - "users" => [ - %{ - "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), - "confirmation_pending" => false, - "approval_pending" => false, - "url" => user.ap_id, - "registration_reason" => nil, - "actor_type" => "Person" - } - ] - } - - conn2 = get(conn, "/api/pleroma/admin/users?query=a&page_size=1&page=2") - - assert json_response(conn2, 200) == %{ - "count" => 2, - "page_size" => 1, - "users" => [ - %{ - "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), - "confirmation_pending" => false, - "approval_pending" => false, - "url" => user2.ap_id, - "registration_reason" => nil, - "actor_type" => "Person" - } - ] - } - end - - test "only local users" do - 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) - - conn = - build_conn() - |> assign(:user, admin) - |> assign(:token, token) - |> get("/api/pleroma/admin/users?query=bo&filters=local") - - assert json_response(conn, 200) == %{ - "count" => 1, - "page_size" => 50, - "users" => [ - %{ - "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), - "confirmation_pending" => false, - "approval_pending" => false, - "url" => user.ap_id, - "registration_reason" => nil, - "actor_type" => "Person" - } - ] - } - end - - 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 = get(conn, "/api/pleroma/admin/users?filters=local") - - users = - [ - %{ - "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), - "confirmation_pending" => false, - "approval_pending" => false, - "url" => user.ap_id, - "registration_reason" => nil, - "actor_type" => "Person" - }, - %{ - "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, - "approval_pending" => false, - "url" => admin.ap_id, - "registration_reason" => nil, - "actor_type" => "Person" - }, - %{ - "deactivated" => false, - "id" => old_admin.id, - "local" => true, - "nickname" => old_admin.nickname, - "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), - "confirmation_pending" => false, - "approval_pending" => false, - "url" => old_admin.ap_id, - "registration_reason" => nil, - "actor_type" => "Person" - } - ] - |> Enum.sort_by(& &1["nickname"]) - - assert json_response(conn, 200) == %{ - "count" => 3, - "page_size" => 50, - "users" => users - } - end - - test "only unapproved users", %{conn: conn} do - user = - insert(:user, - nickname: "sadboy", - approval_pending: true, - registration_reason: "Plz let me in!" - ) - - insert(:user, nickname: "happyboy", approval_pending: false) - - conn = get(conn, "/api/pleroma/admin/users?filters=need_approval") - - users = - [ - %{ - "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), - "confirmation_pending" => false, - "approval_pending" => true, - "url" => user.ap_id, - "registration_reason" => "Plz let me in!", - "actor_type" => "Person" - } - ] - |> Enum.sort_by(& &1["nickname"]) - - assert json_response(conn, 200) == %{ - "count" => 1, - "page_size" => 50, - "users" => users - } - end - - test "load only admins", %{conn: conn, admin: admin} do - second_admin = insert(:user, is_admin: true) - insert(:user) - insert(:user) - - conn = get(conn, "/api/pleroma/admin/users?filters=is_admin") - - users = - [ - %{ - "deactivated" => false, - "id" => admin.id, - "nickname" => admin.nickname, - "roles" => %{"admin" => true, "moderator" => false}, - "local" => admin.local, - "tags" => [], - "avatar" => User.avatar_url(admin) |> MediaProxy.url(), - "display_name" => HTML.strip_tags(admin.name || admin.nickname), - "confirmation_pending" => false, - "approval_pending" => false, - "url" => admin.ap_id, - "registration_reason" => nil, - "actor_type" => "Person" - }, - %{ - "deactivated" => false, - "id" => second_admin.id, - "nickname" => second_admin.nickname, - "roles" => %{"admin" => true, "moderator" => false}, - "local" => second_admin.local, - "tags" => [], - "avatar" => User.avatar_url(second_admin) |> MediaProxy.url(), - "display_name" => HTML.strip_tags(second_admin.name || second_admin.nickname), - "confirmation_pending" => false, - "approval_pending" => false, - "url" => second_admin.ap_id, - "registration_reason" => nil, - "actor_type" => "Person" - } - ] - |> Enum.sort_by(& &1["nickname"]) - - assert json_response(conn, 200) == %{ - "count" => 2, - "page_size" => 50, - "users" => users - } - end - - test "load only moderators", %{conn: conn} do - moderator = insert(:user, is_moderator: true) - insert(:user) - insert(:user) - - conn = get(conn, "/api/pleroma/admin/users?filters=is_moderator") - - assert json_response(conn, 200) == %{ - "count" => 1, - "page_size" => 50, - "users" => [ - %{ - "deactivated" => false, - "id" => moderator.id, - "nickname" => moderator.nickname, - "roles" => %{"admin" => false, "moderator" => true}, - "local" => moderator.local, - "tags" => [], - "avatar" => User.avatar_url(moderator) |> MediaProxy.url(), - "display_name" => HTML.strip_tags(moderator.name || moderator.nickname), - "confirmation_pending" => false, - "approval_pending" => false, - "url" => moderator.ap_id, - "registration_reason" => nil, - "actor_type" => "Person" - } - ] - } - end - - test "load users with tags list", %{conn: conn} do - user1 = insert(:user, tags: ["first"]) - user2 = insert(:user, tags: ["second"]) - insert(:user) - insert(:user) - - conn = get(conn, "/api/pleroma/admin/users?tags[]=first&tags[]=second") - - users = - [ - %{ - "deactivated" => false, - "id" => user1.id, - "nickname" => user1.nickname, - "roles" => %{"admin" => false, "moderator" => false}, - "local" => user1.local, - "tags" => ["first"], - "avatar" => User.avatar_url(user1) |> MediaProxy.url(), - "display_name" => HTML.strip_tags(user1.name || user1.nickname), - "confirmation_pending" => false, - "approval_pending" => false, - "url" => user1.ap_id, - "registration_reason" => nil, - "actor_type" => "Person" - }, - %{ - "deactivated" => false, - "id" => user2.id, - "nickname" => user2.nickname, - "roles" => %{"admin" => false, "moderator" => false}, - "local" => user2.local, - "tags" => ["second"], - "avatar" => User.avatar_url(user2) |> MediaProxy.url(), - "display_name" => HTML.strip_tags(user2.name || user2.nickname), - "confirmation_pending" => false, - "approval_pending" => false, - "url" => user2.ap_id, - "registration_reason" => nil, - "actor_type" => "Person" - } - ] - |> Enum.sort_by(& &1["nickname"]) - - assert json_response(conn, 200) == %{ - "count" => 2, - "page_size" => 50, - "users" => users - } - end - - test "`active` filters out users pending approval", %{token: token} do - insert(:user, approval_pending: true) - %{id: user_id} = insert(:user, approval_pending: false) - %{id: admin_id} = token.user - - conn = - build_conn() - |> assign(:user, token.user) - |> assign(:token, token) - |> get("/api/pleroma/admin/users?filters=active") - - assert %{ - "count" => 2, - "page_size" => 50, - "users" => [ - %{"id" => ^admin_id}, - %{"id" => ^user_id} - ] - } = json_response(conn, 200) - end - - test "it works with multiple filters" do - 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, 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) == %{ - "count" => 1, - "page_size" => 50, - "users" => [ - %{ - "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), - "confirmation_pending" => false, - "approval_pending" => false, - "url" => user.ap_id, - "registration_reason" => nil, - "actor_type" => "Person" - } - ] - } - 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, - "approval_pending" => false, - "url" => admin.ap_id, - "registration_reason" => nil, - "actor_type" => "Person" - } - ] - } - end - end - - 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 = - 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/approve", %{admin: admin, conn: conn} do - user_one = insert(:user, approval_pending: true) - user_two = insert(:user, approval_pending: true) - - conn = - patch( - conn, - "/api/pleroma/admin/users/approve", - %{nicknames: [user_one.nickname, user_two.nickname]} - ) - - response = json_response(conn, 200) - assert Enum.map(response["users"], & &1["approval_pending"]) == [false, false] - - log_entry = Repo.one(ModerationLog) - - assert ModerationLog.get_log_entry_message(log_entry) == - "@#{admin.nickname} approved 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.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), - "confirmation_pending" => false, - "approval_pending" => false, - "url" => user.ap_id, - "registration_reason" => nil, - "actor_type" => "Person" - } - - log_entry = Repo.one(ModerationLog) - - assert ModerationLog.get_log_entry_message(log_entry) == - "@#{admin.nickname} deactivated users: @#{user.nickname}" - end - describe "PUT disable_mfa" do test "returns 200 and disable 2fa", %{conn: conn} do user = @@ -2024,6 +977,73 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do response["status_visibility"] end end + + describe "/api/pleroma/backups" do + test "it creates a backup", %{conn: conn} do + admin = %{id: admin_id, nickname: admin_nickname} = insert(:user, is_admin: true) + token = insert(:oauth_admin_token, user: admin) + user = %{id: user_id, nickname: user_nickname} = insert(:user) + + assert "" == + conn + |> assign(:user, admin) + |> assign(:token, token) + |> post("/api/pleroma/admin/backups", %{nickname: user.nickname}) + |> json_response(200) + + assert [backup] = Repo.all(Pleroma.User.Backup) + + ObanHelpers.perform_all() + + email = Pleroma.Emails.UserEmail.backup_is_ready_email(backup, admin.id) + + assert String.contains?(email.html_body, "Admin @#{admin.nickname} requested a full backup") + assert_email_sent(to: {user.name, user.email}, html_body: email.html_body) + + log_message = "@#{admin_nickname} requested account backup for @#{user_nickname}" + + assert [ + %{ + data: %{ + "action" => "create_backup", + "actor" => %{ + "id" => ^admin_id, + "nickname" => ^admin_nickname + }, + "message" => ^log_message, + "subject" => %{ + "id" => ^user_id, + "nickname" => ^user_nickname + } + } + } + ] = Pleroma.ModerationLog |> Repo.all() + end + + test "it doesn't limit admins", %{conn: conn} do + admin = insert(:user, is_admin: true) + token = insert(:oauth_admin_token, user: admin) + user = insert(:user) + + assert "" == + conn + |> assign(:user, admin) + |> assign(:token, token) + |> post("/api/pleroma/admin/backups", %{nickname: user.nickname}) + |> json_response(200) + + assert [_backup] = Repo.all(Pleroma.User.Backup) + + assert "" == + conn + |> assign(:user, admin) + |> assign(:token, token) + |> post("/api/pleroma/admin/backups", %{nickname: user.nickname}) + |> json_response(200) + + assert Repo.aggregate(Pleroma.User.Backup, :count) == 2 + end + end end # Needed for testing diff --git a/test/pleroma/web/admin_api/controllers/chat_controller_test.exs b/test/pleroma/web/admin_api/controllers/chat_controller_test.exs index bd4c9c9d1..5aefa1e60 100644 --- a/test/pleroma/web/admin_api/controllers/chat_controller_test.exs +++ b/test/pleroma/web/admin_api/controllers/chat_controller_test.exs @@ -9,7 +9,6 @@ defmodule Pleroma.Web.AdminAPI.ChatControllerTest do alias Pleroma.Chat alias Pleroma.Chat.MessageReference - alias Pleroma.Config alias Pleroma.ModerationLog alias Pleroma.Object alias Pleroma.Repo diff --git a/test/pleroma/web/admin_api/controllers/instance_document_controller_test.exs b/test/pleroma/web/admin_api/controllers/instance_document_controller_test.exs index 5f7b042f6..ce867dd0e 100644 --- a/test/pleroma/web/admin_api/controllers/instance_document_controller_test.exs +++ b/test/pleroma/web/admin_api/controllers/instance_document_controller_test.exs @@ -5,7 +5,6 @@ defmodule Pleroma.Web.AdminAPI.InstanceDocumentControllerTest do use Pleroma.Web.ConnCase, async: true import Pleroma.Factory - alias Pleroma.Config @dir "test/tmp/instance_static" @default_instance_panel ~s(<p>Welcome to <a href="https://pleroma.social" target="_blank">Pleroma!</a></p>) diff --git a/test/pleroma/web/admin_api/controllers/o_auth_app_controller_test.exs b/test/pleroma/web/admin_api/controllers/o_auth_app_controller_test.exs index ed7c4172c..f388375d1 100644 --- a/test/pleroma/web/admin_api/controllers/o_auth_app_controller_test.exs +++ b/test/pleroma/web/admin_api/controllers/o_auth_app_controller_test.exs @@ -8,7 +8,6 @@ defmodule Pleroma.Web.AdminAPI.OAuthAppControllerTest do import Pleroma.Factory - alias Pleroma.Config alias Pleroma.Web setup do diff --git a/test/pleroma/web/admin_api/controllers/relay_controller_test.exs b/test/pleroma/web/admin_api/controllers/relay_controller_test.exs index adadf2b5c..b4c5e7567 100644 --- a/test/pleroma/web/admin_api/controllers/relay_controller_test.exs +++ b/test/pleroma/web/admin_api/controllers/relay_controller_test.exs @@ -7,7 +7,6 @@ defmodule Pleroma.Web.AdminAPI.RelayControllerTest do import Pleroma.Factory - alias Pleroma.Config alias Pleroma.ModerationLog alias Pleroma.Repo alias Pleroma.User diff --git a/test/pleroma/web/admin_api/controllers/report_controller_test.exs b/test/pleroma/web/admin_api/controllers/report_controller_test.exs index 57946e6bb..fa746d6ea 100644 --- a/test/pleroma/web/admin_api/controllers/report_controller_test.exs +++ b/test/pleroma/web/admin_api/controllers/report_controller_test.exs @@ -8,7 +8,6 @@ defmodule Pleroma.Web.AdminAPI.ReportControllerTest do import Pleroma.Factory alias Pleroma.Activity - alias Pleroma.Config alias Pleroma.ModerationLog alias Pleroma.Repo alias Pleroma.ReportNote diff --git a/test/pleroma/web/admin_api/controllers/status_controller_test.exs b/test/pleroma/web/admin_api/controllers/status_controller_test.exs index eff78fb0a..a18ef9e4b 100644 --- a/test/pleroma/web/admin_api/controllers/status_controller_test.exs +++ b/test/pleroma/web/admin_api/controllers/status_controller_test.exs @@ -8,7 +8,6 @@ defmodule Pleroma.Web.AdminAPI.StatusControllerTest do import Pleroma.Factory alias Pleroma.Activity - alias Pleroma.Config alias Pleroma.ModerationLog alias Pleroma.Repo alias Pleroma.User diff --git a/test/pleroma/web/admin_api/controllers/user_controller_test.exs b/test/pleroma/web/admin_api/controllers/user_controller_test.exs new file mode 100644 index 000000000..5705306c7 --- /dev/null +++ b/test/pleroma/web/admin_api/controllers/user_controller_test.exs @@ -0,0 +1,970 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.AdminAPI.UserControllerTest do + use Pleroma.Web.ConnCase + use Oban.Testing, repo: Pleroma.Repo + + import Mock + import Pleroma.Factory + + alias Pleroma.HTML + alias Pleroma.ModerationLog + alias Pleroma.Repo + alias Pleroma.Tests.ObanHelpers + alias Pleroma.User + alias Pleroma.Web + alias Pleroma.Web.ActivityPub.Relay + alias Pleroma.Web.CommonAPI + alias Pleroma.Web.MediaProxy + + 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 + + test "with valid `admin_token` query parameter, skips OAuth scopes check" do + clear_config([:admin_token], "password123") + + user = insert(:user) + + conn = get(build_conn(), "/api/pleroma/admin/users/#{user.nickname}?admin_token=password123") + + assert json_response(conn, 200) + end + + describe "with [:auth, :enforce_oauth_admin_scope_usage]," do + setup do: clear_config([:auth, :enforce_oauth_admin_scope_usage], true) + + 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 + setup do: clear_config([:auth, :enforce_oauth_admin_scope_usage], false) + + 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 + clear_config([:instance, :federating], true) + + user = + insert(:user, + avatar: %{"url" => [%{"href" => "https://someurl"}]}, + banner: %{"url" => [%{"href" => "https://somebanner"}]}, + bio: "Hello world!", + name: "A guy" + ) + + # Create some activities to check they got deleted later + follower = insert(:user) + {:ok, _} = CommonAPI.post(user, %{status: "test"}) + {:ok, _, _, _} = CommonAPI.follow(user, follower) + {:ok, _, _, _} = CommonAPI.follow(follower, user) + user = Repo.get(User, user.id) + assert user.note_count == 1 + assert user.follower_count == 1 + assert user.following_count == 1 + refute user.deactivated + + with_mock Pleroma.Web.Federator, + publish: fn _ -> nil end, + perform: fn _, _ -> nil end do + conn = + conn + |> put_req_header("accept", "application/json") + |> delete("/api/pleroma/admin/users?nickname=#{user.nickname}") + + ObanHelpers.perform_all() + + assert User.get_by_nickname(user.nickname).deactivated + + log_entry = Repo.one(ModerationLog) + + assert ModerationLog.get_log_entry_message(log_entry) == + "@#{admin.nickname} deleted users: @#{user.nickname}" + + assert json_response(conn, 200) == [user.nickname] + + user = Repo.get(User, user.id) + assert user.deactivated + + assert user.avatar == %{} + assert user.banner == %{} + assert user.note_count == 0 + assert user.follower_count == 0 + assert user.following_count == 0 + assert user.bio == "" + assert user.name == nil + + assert called(Pleroma.Web.Federator.publish(:_)) + end + end + + test "multiple users", %{admin: admin, conn: conn} do + user_one = insert(:user) + user_two = insert(:user) + + conn = + 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" => [ + %{ + "nickname" => "lain", + "email" => "lain@example.org", + "password" => "test" + }, + %{ + "nickname" => "lain2", + "email" => "lain2@example.org", + "password" => "test" + } + ] + }) + + response = json_response(conn, 200) |> Enum.map(&Map.get(&1, "type")) + assert response == ["success", "success"] + + log_entry = Repo.one(ModerationLog) + + assert ["lain", "lain2"] -- Enum.map(log_entry.data["subjects"], & &1["nickname"]) == [] + end + + test "Cannot create user with existing email", %{conn: conn} do + user = insert(:user) + + conn = + conn + |> put_req_header("accept", "application/json") + |> post("/api/pleroma/admin/users", %{ + "users" => [ + %{ + "nickname" => "lain", + "email" => user.email, + "password" => "test" + } + ] + }) + + assert json_response(conn, 409) == [ + %{ + "code" => 409, + "data" => %{ + "email" => user.email, + "nickname" => "lain" + }, + "error" => "email has already been taken", + "type" => "error" + } + ] + end + + test "Cannot create user with existing nickname", %{conn: conn} do + user = insert(:user) + + conn = + conn + |> put_req_header("accept", "application/json") + |> post("/api/pleroma/admin/users", %{ + "users" => [ + %{ + "nickname" => user.nickname, + "email" => "someuser@plerama.social", + "password" => "test" + } + ] + }) + + assert json_response(conn, 409) == [ + %{ + "code" => 409, + "data" => %{ + "email" => "someuser@plerama.social", + "nickname" => user.nickname + }, + "error" => "nickname has already been taken", + "type" => "error" + } + ] + end + + test "Multiple user creation works in transaction", %{conn: conn} do + user = insert(:user) + + conn = + conn + |> put_req_header("accept", "application/json") + |> post("/api/pleroma/admin/users", %{ + "users" => [ + %{ + "nickname" => "newuser", + "email" => "newuser@pleroma.social", + "password" => "test" + }, + %{ + "nickname" => "lain", + "email" => user.email, + "password" => "test" + } + ] + }) + + assert json_response(conn, 409) == [ + %{ + "code" => 409, + "data" => %{ + "email" => user.email, + "nickname" => "lain" + }, + "error" => "email has already been taken", + "type" => "error" + }, + %{ + "code" => 409, + "data" => %{ + "email" => "newuser@pleroma.social", + "nickname" => "newuser" + }, + "error" => "", + "type" => "error" + } + ] + + assert User.get_by_nickname("newuser") === nil + end + end + + describe "/api/pleroma/admin/users/:nickname" do + test "Show", %{conn: conn} do + user = insert(:user) + + conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}") + + assert user_response(user) == json_response(conn, 200) + end + + test "when the user doesn't exist", %{conn: conn} do + user = build(:user) + + conn = get(conn, "/api/pleroma/admin/users/#{user.nickname}") + + assert %{"error" => "Not found"} == json_response(conn, 404) + end + end + + describe "/api/pleroma/admin/users/follow" do + test "allows to force-follow another user", %{admin: admin, conn: conn} do + user = insert(:user) + follower = insert(:user) + + conn + |> put_req_header("accept", "application/json") + |> post("/api/pleroma/admin/users/follow", %{ + "follower" => follower.nickname, + "followed" => user.nickname + }) + + user = User.get_cached_by_id(user.id) + follower = User.get_cached_by_id(follower.id) + + assert User.following?(follower, user) + + log_entry = Repo.one(ModerationLog) + + assert ModerationLog.get_log_entry_message(log_entry) == + "@#{admin.nickname} made @#{follower.nickname} follow @#{user.nickname}" + end + end + + describe "/api/pleroma/admin/users/unfollow" do + test "allows to force-unfollow another user", %{admin: admin, conn: conn} do + user = insert(:user) + follower = insert(:user) + + User.follow(follower, user) + + conn + |> put_req_header("accept", "application/json") + |> post("/api/pleroma/admin/users/unfollow", %{ + "follower" => follower.nickname, + "followed" => user.nickname + }) + + user = User.get_cached_by_id(user.id) + follower = User.get_cached_by_id(follower.id) + + refute User.following?(follower, user) + + log_entry = Repo.one(ModerationLog) + + assert ModerationLog.get_log_entry_message(log_entry) == + "@#{admin.nickname} made @#{follower.nickname} unfollow @#{user.nickname}" + end + end + + describe "GET /api/pleroma/admin/users" do + test "renders users array for the first page", %{conn: conn, admin: admin} do + user = insert(:user, local: false, tags: ["foo", "bar"]) + user2 = insert(:user, approval_pending: true, registration_reason: "I'm a chill dude") + + conn = get(conn, "/api/pleroma/admin/users?page=1") + + users = + [ + user_response( + admin, + %{"roles" => %{"admin" => true, "moderator" => false}} + ), + user_response(user, %{"local" => false, "tags" => ["foo", "bar"]}), + user_response( + user2, + %{ + "local" => true, + "approval_pending" => true, + "registration_reason" => "I'm a chill dude", + "actor_type" => "Person" + } + ) + ] + |> Enum.sort_by(& &1["nickname"]) + + assert json_response(conn, 200) == %{ + "count" => 3, + "page_size" => 50, + "users" => users + } + end + + test "pagination works correctly with service users", %{conn: conn} do + service1 = User.get_or_create_service_actor_by_ap_id(Web.base_url() <> "/meido", "meido") + + insert_list(25, :user) + + assert %{"count" => 26, "page_size" => 10, "users" => users1} = + conn + |> get("/api/pleroma/admin/users?page=1&filters=", %{page_size: "10"}) + |> json_response(200) + + assert Enum.count(users1) == 10 + assert service1 not in users1 + + assert %{"count" => 26, "page_size" => 10, "users" => users2} = + conn + |> get("/api/pleroma/admin/users?page=2&filters=", %{page_size: "10"}) + |> json_response(200) + + assert Enum.count(users2) == 10 + assert service1 not in users2 + + assert %{"count" => 26, "page_size" => 10, "users" => users3} = + conn + |> get("/api/pleroma/admin/users?page=3&filters=", %{page_size: "10"}) + |> json_response(200) + + assert Enum.count(users3) == 6 + assert service1 not in users3 + end + + test "renders empty array for the second page", %{conn: conn} do + insert(:user) + + conn = get(conn, "/api/pleroma/admin/users?page=2") + + assert json_response(conn, 200) == %{ + "count" => 2, + "page_size" => 50, + "users" => [] + } + end + + test "regular search", %{conn: conn} do + user = insert(:user, nickname: "bob") + + conn = get(conn, "/api/pleroma/admin/users?query=bo") + + assert json_response(conn, 200) == %{ + "count" => 1, + "page_size" => 50, + "users" => [user_response(user, %{"local" => true})] + } + end + + test "search by domain", %{conn: conn} do + user = insert(:user, nickname: "nickname@domain.com") + insert(:user) + + conn = get(conn, "/api/pleroma/admin/users?query=domain.com") + + assert json_response(conn, 200) == %{ + "count" => 1, + "page_size" => 50, + "users" => [user_response(user)] + } + end + + test "search by full nickname", %{conn: conn} do + user = insert(:user, nickname: "nickname@domain.com") + insert(:user) + + conn = get(conn, "/api/pleroma/admin/users?query=nickname@domain.com") + + assert json_response(conn, 200) == %{ + "count" => 1, + "page_size" => 50, + "users" => [user_response(user)] + } + end + + test "search by display name", %{conn: conn} do + user = insert(:user, name: "Display name") + insert(:user) + + conn = get(conn, "/api/pleroma/admin/users?name=display") + + assert json_response(conn, 200) == %{ + "count" => 1, + "page_size" => 50, + "users" => [user_response(user)] + } + end + + test "search by email", %{conn: conn} do + user = insert(:user, email: "email@example.com") + insert(:user) + + conn = get(conn, "/api/pleroma/admin/users?email=email@example.com") + + assert json_response(conn, 200) == %{ + "count" => 1, + "page_size" => 50, + "users" => [user_response(user)] + } + end + + test "regular search with page size", %{conn: conn} do + user = insert(:user, nickname: "aalice") + user2 = insert(:user, nickname: "alice") + + conn1 = get(conn, "/api/pleroma/admin/users?query=a&page_size=1&page=1") + + assert json_response(conn1, 200) == %{ + "count" => 2, + "page_size" => 1, + "users" => [user_response(user)] + } + + conn2 = get(conn, "/api/pleroma/admin/users?query=a&page_size=1&page=2") + + assert json_response(conn2, 200) == %{ + "count" => 2, + "page_size" => 1, + "users" => [user_response(user2)] + } + end + + test "only local users" do + 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) + + conn = + build_conn() + |> assign(:user, admin) + |> assign(:token, token) + |> get("/api/pleroma/admin/users?query=bo&filters=local") + + assert json_response(conn, 200) == %{ + "count" => 1, + "page_size" => 50, + "users" => [user_response(user)] + } + end + + 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 = get(conn, "/api/pleroma/admin/users?filters=local") + + users = + [ + user_response(user), + user_response(admin, %{ + "roles" => %{"admin" => true, "moderator" => false} + }), + user_response(old_admin, %{ + "deactivated" => false, + "roles" => %{"admin" => true, "moderator" => false} + }) + ] + |> Enum.sort_by(& &1["nickname"]) + + assert json_response(conn, 200) == %{ + "count" => 3, + "page_size" => 50, + "users" => users + } + end + + test "only unconfirmed users", %{conn: conn} do + sad_user = insert(:user, nickname: "sadboy", confirmation_pending: true) + old_user = insert(:user, nickname: "oldboy", confirmation_pending: true) + + insert(:user, nickname: "happyboy", approval_pending: false) + insert(:user, confirmation_pending: false) + + result = + conn + |> get("/api/pleroma/admin/users?filters=unconfirmed") + |> json_response(200) + + users = + Enum.map([old_user, sad_user], fn user -> + user_response(user, %{ + "confirmation_pending" => true, + "approval_pending" => false + }) + end) + |> Enum.sort_by(& &1["nickname"]) + + assert result == %{"count" => 2, "page_size" => 50, "users" => users} + end + + test "only unapproved users", %{conn: conn} do + user = + insert(:user, + nickname: "sadboy", + approval_pending: true, + registration_reason: "Plz let me in!" + ) + + insert(:user, nickname: "happyboy", approval_pending: false) + + conn = get(conn, "/api/pleroma/admin/users?filters=need_approval") + + users = [ + user_response( + user, + %{"approval_pending" => true, "registration_reason" => "Plz let me in!"} + ) + ] + + assert json_response(conn, 200) == %{ + "count" => 1, + "page_size" => 50, + "users" => users + } + end + + test "load only admins", %{conn: conn, admin: admin} do + second_admin = insert(:user, is_admin: true) + insert(:user) + insert(:user) + + conn = get(conn, "/api/pleroma/admin/users?filters=is_admin") + + users = + [ + user_response(admin, %{ + "deactivated" => false, + "roles" => %{"admin" => true, "moderator" => false} + }), + user_response(second_admin, %{ + "deactivated" => false, + "roles" => %{"admin" => true, "moderator" => false} + }) + ] + |> Enum.sort_by(& &1["nickname"]) + + assert json_response(conn, 200) == %{ + "count" => 2, + "page_size" => 50, + "users" => users + } + end + + test "load only moderators", %{conn: conn} do + moderator = insert(:user, is_moderator: true) + insert(:user) + insert(:user) + + conn = get(conn, "/api/pleroma/admin/users?filters=is_moderator") + + assert json_response(conn, 200) == %{ + "count" => 1, + "page_size" => 50, + "users" => [ + user_response(moderator, %{ + "deactivated" => false, + "roles" => %{"admin" => false, "moderator" => true} + }) + ] + } + end + + test "load users with actor_type is Person", %{admin: admin, conn: conn} do + insert(:user, actor_type: "Service") + insert(:user, actor_type: "Application") + + user1 = insert(:user) + user2 = insert(:user) + + response = + conn + |> get(user_path(conn, :list), %{actor_types: ["Person"]}) + |> json_response(200) + + users = + [ + user_response(admin, %{"roles" => %{"admin" => true, "moderator" => false}}), + user_response(user1), + user_response(user2) + ] + |> Enum.sort_by(& &1["nickname"]) + + assert response == %{"count" => 3, "page_size" => 50, "users" => users} + end + + test "load users with actor_type is Person and Service", %{admin: admin, conn: conn} do + user_service = insert(:user, actor_type: "Service") + insert(:user, actor_type: "Application") + + user1 = insert(:user) + user2 = insert(:user) + + response = + conn + |> get(user_path(conn, :list), %{actor_types: ["Person", "Service"]}) + |> json_response(200) + + users = + [ + user_response(admin, %{"roles" => %{"admin" => true, "moderator" => false}}), + user_response(user1), + user_response(user2), + user_response(user_service, %{"actor_type" => "Service"}) + ] + |> Enum.sort_by(& &1["nickname"]) + + assert response == %{"count" => 4, "page_size" => 50, "users" => users} + end + + test "load users with actor_type is Service", %{conn: conn} do + user_service = insert(:user, actor_type: "Service") + insert(:user, actor_type: "Application") + insert(:user) + insert(:user) + + response = + conn + |> get(user_path(conn, :list), %{actor_types: ["Service"]}) + |> json_response(200) + + users = [user_response(user_service, %{"actor_type" => "Service"})] + + assert response == %{"count" => 1, "page_size" => 50, "users" => users} + end + + test "load users with tags list", %{conn: conn} do + user1 = insert(:user, tags: ["first"]) + user2 = insert(:user, tags: ["second"]) + insert(:user) + insert(:user) + + conn = get(conn, "/api/pleroma/admin/users?tags[]=first&tags[]=second") + + users = + [ + user_response(user1, %{"tags" => ["first"]}), + user_response(user2, %{"tags" => ["second"]}) + ] + |> Enum.sort_by(& &1["nickname"]) + + assert json_response(conn, 200) == %{ + "count" => 2, + "page_size" => 50, + "users" => users + } + end + + test "`active` filters out users pending approval", %{token: token} do + insert(:user, approval_pending: true) + %{id: user_id} = insert(:user, approval_pending: false) + %{id: admin_id} = token.user + + conn = + build_conn() + |> assign(:user, token.user) + |> assign(:token, token) + |> get("/api/pleroma/admin/users?filters=active") + + assert %{ + "count" => 2, + "page_size" => 50, + "users" => [ + %{"id" => ^admin_id}, + %{"id" => ^user_id} + ] + } = json_response(conn, 200) + end + + test "it works with multiple filters" do + 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, 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) == %{ + "count" => 1, + "page_size" => 50, + "users" => [user_response(user)] + } + 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" => [ + user_response(admin, %{"roles" => %{"admin" => true, "moderator" => false}}) + ] + } + end + end + + 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 = + 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/approve", %{admin: admin, conn: conn} do + user_one = insert(:user, approval_pending: true) + user_two = insert(:user, approval_pending: true) + + conn = + patch( + conn, + "/api/pleroma/admin/users/approve", + %{nicknames: [user_one.nickname, user_two.nickname]} + ) + + response = json_response(conn, 200) + assert Enum.map(response["users"], & &1["approval_pending"]) == [false, false] + + log_entry = Repo.one(ModerationLog) + + assert ModerationLog.get_log_entry_message(log_entry) == + "@#{admin.nickname} approved 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) == + user_response( + user, + %{"deactivated" => !user.deactivated} + ) + + log_entry = Repo.one(ModerationLog) + + assert ModerationLog.get_log_entry_message(log_entry) == + "@#{admin.nickname} deactivated users: @#{user.nickname}" + end + + defp user_response(user, attrs \\ %{}) do + %{ + "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), + "confirmation_pending" => false, + "approval_pending" => false, + "url" => user.ap_id, + "registration_reason" => nil, + "actor_type" => "Person" + } + |> Map.merge(attrs) + end +end diff --git a/test/pleroma/web/admin_api/search_test.exs b/test/pleroma/web/admin_api/search_test.exs index ceec64f1e..92a116c65 100644 --- a/test/pleroma/web/admin_api/search_test.exs +++ b/test/pleroma/web/admin_api/search_test.exs @@ -143,6 +143,20 @@ defmodule Pleroma.Web.AdminAPI.SearchTest do assert user2 in users end + test "it returns users by actor_types" do + user_service = insert(:user, actor_type: "Service") + user_application = insert(:user, actor_type: "Application") + user1 = insert(:user) + user2 = insert(:user) + + {:ok, [^user_service], 1} = Search.user(%{actor_types: ["Service"]}) + {:ok, [^user_application], 1} = Search.user(%{actor_types: ["Application"]}) + {:ok, [^user1, ^user2], 2} = Search.user(%{actor_types: ["Person"]}) + + {:ok, [^user_service, ^user1, ^user2], 3} = + Search.user(%{actor_types: ["Person", "Service"]}) + end + test "it returns user by display name" do user = insert(:user, name: "Display name") insert(:user) @@ -178,6 +192,17 @@ defmodule Pleroma.Web.AdminAPI.SearchTest do assert count == 1 end + test "it returns unconfirmed user" do + unconfirmed = insert(:user, confirmation_pending: true) + insert(:user) + insert(:user) + + {:ok, _results, total} = Search.user() + {:ok, [^unconfirmed], count} = Search.user(%{unconfirmed: true}) + assert total == 3 + assert count == 1 + end + test "it returns non-discoverable users" do insert(:user) insert(:user, is_discoverable: false) diff --git a/test/pleroma/web/endpoint/metrics_exporter_test.exs b/test/pleroma/web/endpoint/metrics_exporter_test.exs new file mode 100644 index 000000000..875addc96 --- /dev/null +++ b/test/pleroma/web/endpoint/metrics_exporter_test.exs @@ -0,0 +1,68 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.Endpoint.MetricsExporterTest do + use Pleroma.Web.ConnCase + + alias Pleroma.Web.Endpoint.MetricsExporter + + defp config do + Application.get_env(:prometheus, MetricsExporter) + end + + describe "with default config" do + test "does NOT expose app metrics", %{conn: conn} do + conn + |> get(config()[:path]) + |> json_response(404) + end + end + + describe "when enabled" do + setup do + initial_config = config() + on_exit(fn -> Application.put_env(:prometheus, MetricsExporter, initial_config) end) + + Application.put_env( + :prometheus, + MetricsExporter, + Keyword.put(initial_config, :enabled, true) + ) + end + + test "serves app metrics", %{conn: conn} do + conn = get(conn, config()[:path]) + assert response = response(conn, 200) + + for metric <- [ + "http_requests_total", + "http_request_duration_microseconds", + "phoenix_controller_call_duration", + "telemetry_scrape_duration", + "erlang_vm_memory_atom_bytes_total" + ] do + assert response =~ ~r/#{metric}/ + end + end + + test "when IP whitelist configured, " <> + "serves app metrics only if client IP is whitelisted", + %{conn: conn} do + Application.put_env( + :prometheus, + MetricsExporter, + Keyword.put(config(), :ip_whitelist, ["127.127.127.127", {1, 1, 1, 1}, '255.255.255.255']) + ) + + conn + |> get(config()[:path]) + |> json_response(404) + + conn + |> Map.put(:remote_ip, {127, 127, 127, 127}) + |> get(config()[:path]) + |> response(200) + end + end +end diff --git a/test/pleroma/web/feed/tag_controller_test.exs b/test/pleroma/web/feed/tag_controller_test.exs index 868e40965..e4084b0e5 100644 --- a/test/pleroma/web/feed/tag_controller_test.exs +++ b/test/pleroma/web/feed/tag_controller_test.exs @@ -8,6 +8,7 @@ defmodule Pleroma.Web.Feed.TagControllerTest do import Pleroma.Factory import SweetXml + alias Pleroma.Config alias Pleroma.Object alias Pleroma.Web.CommonAPI alias Pleroma.Web.Feed.FeedView @@ -15,7 +16,7 @@ defmodule Pleroma.Web.Feed.TagControllerTest do setup do: clear_config([:feed]) test "gets a feed (ATOM)", %{conn: conn} do - Pleroma.Config.put( + Config.put( [:feed, :post_title], %{max_length: 25, omission: "..."} ) @@ -82,7 +83,7 @@ defmodule Pleroma.Web.Feed.TagControllerTest do end test "gets a feed (RSS)", %{conn: conn} do - Pleroma.Config.put( + Config.put( [:feed, :post_title], %{max_length: 25, omission: "..."} ) @@ -157,7 +158,7 @@ defmodule Pleroma.Web.Feed.TagControllerTest do response = conn |> put_req_header("accept", "application/rss+xml") - |> get(tag_feed_path(conn, :feed, "pleromaart")) + |> get(tag_feed_path(conn, :feed, "pleromaart.rss")) |> response(200) xml = parse(response) @@ -183,14 +184,12 @@ defmodule Pleroma.Web.Feed.TagControllerTest do end describe "private instance" do - setup do: clear_config([:instance, :public]) + setup do: clear_config([:instance, :public], false) test "returns 404 for tags feed", %{conn: conn} do - Config.put([:instance, :public], false) - conn |> put_req_header("accept", "application/rss+xml") - |> get(tag_feed_path(conn, :feed, "pleromaart")) + |> get(tag_feed_path(conn, :feed, "pleromaart.rss")) |> response(404) end end diff --git a/test/pleroma/web/feed/user_controller_test.exs b/test/pleroma/web/feed/user_controller_test.exs index a5dc0894b..eabfe3a63 100644 --- a/test/pleroma/web/feed/user_controller_test.exs +++ b/test/pleroma/web/feed/user_controller_test.exs @@ -13,7 +13,7 @@ defmodule Pleroma.Web.Feed.UserControllerTest do alias Pleroma.User alias Pleroma.Web.CommonAPI - setup do: clear_config([:instance, :federating], true) + setup do: clear_config([:static_fe, :enabled], false) describe "feed" do setup do: clear_config([:feed]) @@ -192,6 +192,16 @@ defmodule Pleroma.Web.Feed.UserControllerTest do |> get(user_feed_path(conn, :feed, user.nickname)) |> response(404) end + + test "does not require authentication on non-federating instances", %{conn: conn} do + clear_config([:instance, :federating], false) + user = insert(:user) + + conn + |> put_req_header("accept", "application/rss+xml") + |> get("/users/#{user.nickname}/feed.rss") + |> response(200) + end end # Note: see ActivityPubControllerTest for JSON format tests diff --git a/test/pleroma/web/mastodon_api/controllers/account_controller_test.exs b/test/pleroma/web/mastodon_api/controllers/account_controller_test.exs index dcc0c81ec..58ce76ab8 100644 --- a/test/pleroma/web/mastodon_api/controllers/account_controller_test.exs +++ b/test/pleroma/web/mastodon_api/controllers/account_controller_test.exs @@ -1509,28 +1509,103 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do test "getting a list of mutes" do %{user: user, conn: conn} = oauth_access(["read:mutes"]) - other_user = insert(:user) + %{id: id1} = other_user1 = insert(:user) + %{id: id2} = other_user2 = insert(:user) + %{id: id3} = other_user3 = insert(:user) + + {:ok, _user_relationships} = User.mute(user, other_user1) + {:ok, _user_relationships} = User.mute(user, other_user2) + {:ok, _user_relationships} = User.mute(user, other_user3) + + result = + conn + |> assign(:user, user) + |> get("/api/v1/mutes") + |> json_response_and_validate_schema(200) + + assert [id1, id2, id3] == Enum.map(result, & &1["id"]) + + result = + conn + |> assign(:user, user) + |> get("/api/v1/mutes?limit=1") + |> json_response_and_validate_schema(200) - {:ok, _user_relationships} = User.mute(user, other_user) + assert [%{"id" => ^id1}] = result - conn = get(conn, "/api/v1/mutes") + result = + conn + |> assign(:user, user) + |> get("/api/v1/mutes?since_id=#{id1}") + |> json_response_and_validate_schema(200) + + assert [%{"id" => ^id2}, %{"id" => ^id3}] = result + + result = + conn + |> assign(:user, user) + |> get("/api/v1/mutes?since_id=#{id1}&max_id=#{id3}") + |> json_response_and_validate_schema(200) + + assert [%{"id" => ^id2}] = result + + result = + conn + |> assign(:user, user) + |> get("/api/v1/mutes?since_id=#{id1}&limit=1") + |> json_response_and_validate_schema(200) - other_user_id = to_string(other_user.id) - assert [%{"id" => ^other_user_id}] = json_response_and_validate_schema(conn, 200) + assert [%{"id" => ^id2}] = result end test "getting a list of blocks" do %{user: user, conn: conn} = oauth_access(["read:blocks"]) - other_user = insert(:user) + %{id: id1} = other_user1 = insert(:user) + %{id: id2} = other_user2 = insert(:user) + %{id: id3} = other_user3 = insert(:user) - {:ok, _user_relationship} = User.block(user, other_user) + {:ok, _user_relationship} = User.block(user, other_user1) + {:ok, _user_relationship} = User.block(user, other_user3) + {:ok, _user_relationship} = User.block(user, other_user2) - conn = + result = conn |> assign(:user, user) |> get("/api/v1/blocks") + |> json_response_and_validate_schema(200) + + assert [id1, id2, id3] == Enum.map(result, & &1["id"]) + + result = + conn + |> assign(:user, user) + |> get("/api/v1/blocks?limit=1") + |> json_response_and_validate_schema(200) + + assert [%{"id" => ^id1}] = result + + result = + conn + |> assign(:user, user) + |> get("/api/v1/blocks?since_id=#{id1}") + |> json_response_and_validate_schema(200) + + assert [%{"id" => ^id2}, %{"id" => ^id3}] = result + + result = + conn + |> assign(:user, user) + |> get("/api/v1/blocks?since_id=#{id1}&max_id=#{id3}") + |> json_response_and_validate_schema(200) + + assert [%{"id" => ^id2}] = result + + result = + conn + |> assign(:user, user) + |> get("/api/v1/blocks?since_id=#{id1}&limit=1") + |> json_response_and_validate_schema(200) - other_user_id = to_string(other_user.id) - assert [%{"id" => ^other_user_id}] = json_response_and_validate_schema(conn, 200) + assert [%{"id" => ^id2}] = result end end diff --git a/test/pleroma/web/mastodon_api/controllers/conversation_controller_test.exs b/test/pleroma/web/mastodon_api/controllers/conversation_controller_test.exs index 3e21e6bf1..b23b22752 100644 --- a/test/pleroma/web/mastodon_api/controllers/conversation_controller_test.exs +++ b/test/pleroma/web/mastodon_api/controllers/conversation_controller_test.exs @@ -5,6 +5,7 @@ defmodule Pleroma.Web.MastodonAPI.ConversationControllerTest do use Pleroma.Web.ConnCase + alias Pleroma.Conversation.Participation alias Pleroma.User alias Pleroma.Web.CommonAPI @@ -28,10 +29,10 @@ defmodule Pleroma.Web.MastodonAPI.ConversationControllerTest do user_three: user_three, conn: conn } do - assert User.get_cached_by_id(user_two.id).unread_conversation_count == 0 + assert Participation.unread_count(user_two) == 0 {:ok, direct} = create_direct_message(user_one, [user_two, user_three]) - assert User.get_cached_by_id(user_two.id).unread_conversation_count == 1 + assert Participation.unread_count(user_two) == 1 {:ok, _follower_only} = CommonAPI.post(user_one, %{ @@ -59,7 +60,7 @@ defmodule Pleroma.Web.MastodonAPI.ConversationControllerTest do assert is_binary(res_id) assert unread == false assert res_last_status["id"] == direct.id - assert User.get_cached_by_id(user_one.id).unread_conversation_count == 0 + assert Participation.unread_count(user_one) == 0 end test "observes limit params", %{ @@ -134,8 +135,8 @@ defmodule Pleroma.Web.MastodonAPI.ConversationControllerTest do user_two = insert(:user) {:ok, direct} = create_direct_message(user_one, [user_two]) - assert User.get_cached_by_id(user_one.id).unread_conversation_count == 0 - assert User.get_cached_by_id(user_two.id).unread_conversation_count == 1 + assert Participation.unread_count(user_one) == 0 + assert Participation.unread_count(user_two) == 1 user_two_conn = build_conn() @@ -155,8 +156,8 @@ defmodule Pleroma.Web.MastodonAPI.ConversationControllerTest do |> post("/api/v1/conversations/#{direct_conversation_id}/read") |> json_response_and_validate_schema(200) - assert User.get_cached_by_id(user_one.id).unread_conversation_count == 0 - assert User.get_cached_by_id(user_two.id).unread_conversation_count == 0 + assert Participation.unread_count(user_one) == 0 + assert Participation.unread_count(user_two) == 0 # The conversation is marked as unread on reply {:ok, _} = @@ -171,8 +172,8 @@ defmodule Pleroma.Web.MastodonAPI.ConversationControllerTest do |> get("/api/v1/conversations") |> json_response_and_validate_schema(200) - assert User.get_cached_by_id(user_one.id).unread_conversation_count == 1 - assert User.get_cached_by_id(user_two.id).unread_conversation_count == 0 + assert Participation.unread_count(user_one) == 1 + assert Participation.unread_count(user_two) == 0 # A reply doesn't increment the user's unread_conversation_count if the conversation is unread {:ok, _} = @@ -182,8 +183,8 @@ defmodule Pleroma.Web.MastodonAPI.ConversationControllerTest do in_reply_to_status_id: direct.id }) - assert User.get_cached_by_id(user_one.id).unread_conversation_count == 1 - assert User.get_cached_by_id(user_two.id).unread_conversation_count == 0 + assert Participation.unread_count(user_one) == 1 + assert Participation.unread_count(user_two) == 0 end test "(vanilla) Mastodon frontend behaviour", %{user: user_one, conn: conn} do diff --git a/test/pleroma/web/mastodon_api/controllers/timeline_controller_test.exs b/test/pleroma/web/mastodon_api/controllers/timeline_controller_test.exs index c6e0268fd..9f1ee0424 100644 --- a/test/pleroma/web/mastodon_api/controllers/timeline_controller_test.exs +++ b/test/pleroma/web/mastodon_api/controllers/timeline_controller_test.exs @@ -8,7 +8,6 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do import Pleroma.Factory import Tesla.Mock - alias Pleroma.Config alias Pleroma.User alias Pleroma.Web.CommonAPI diff --git a/test/pleroma/web/o_status/o_status_controller_test.exs b/test/pleroma/web/o_status/o_status_controller_test.exs index ee498f4b5..65b2c22db 100644 --- a/test/pleroma/web/o_status/o_status_controller_test.exs +++ b/test/pleroma/web/o_status/o_status_controller_test.exs @@ -7,7 +7,6 @@ defmodule Pleroma.Web.OStatus.OStatusControllerTest do import Pleroma.Factory - alias Pleroma.Config alias Pleroma.Object alias Pleroma.User alias Pleroma.Web.ActivityPub.ActivityPub @@ -21,7 +20,7 @@ defmodule Pleroma.Web.OStatus.OStatusControllerTest do :ok end - setup do: clear_config([:instance, :federating], true) + setup do: clear_config([:static_fe, :enabled], false) describe "Mastodon compatibility routes" do setup %{conn: conn} do @@ -215,15 +214,16 @@ defmodule Pleroma.Web.OStatus.OStatusControllerTest do assert response(conn, 404) end - test "it requires authentication if instance is NOT federating", %{ + test "does not require authentication on non-federating instances", %{ conn: conn } do - user = insert(:user) + clear_config([:instance, :federating], false) note_activity = insert(:note_activity) - conn = put_req_header(conn, "accept", "text/html") - - ensure_federating_or_authenticated(conn, "/notice/#{note_activity.id}", user) + conn + |> put_req_header("accept", "text/html") + |> get("/notice/#{note_activity.id}") + |> response(200) end end @@ -325,14 +325,16 @@ defmodule Pleroma.Web.OStatus.OStatusControllerTest do |> response(404) end - test "it requires authentication if instance is NOT federating", %{ + test "does not require authentication on non-federating instances", %{ conn: conn, note_activity: note_activity } do - user = insert(:user) - conn = put_req_header(conn, "accept", "text/html") + clear_config([:instance, :federating], false) - ensure_federating_or_authenticated(conn, "/notice/#{note_activity.id}/embed_player", user) + conn + |> put_req_header("accept", "text/html") + |> get("/notice/#{note_activity.id}/embed_player") + |> response(200) end end end diff --git a/test/pleroma/web/pleroma_api/controllers/backup_controller_test.exs b/test/pleroma/web/pleroma_api/controllers/backup_controller_test.exs new file mode 100644 index 000000000..f1941f6dd --- /dev/null +++ b/test/pleroma/web/pleroma_api/controllers/backup_controller_test.exs @@ -0,0 +1,85 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/> +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.PleromaAPI.BackupControllerTest do + use Pleroma.Web.ConnCase + + alias Pleroma.User.Backup + alias Pleroma.Web.PleromaAPI.BackupView + + setup do + clear_config([Pleroma.Upload, :uploader]) + clear_config([Backup, :limit_days]) + oauth_access(["read:accounts"]) + end + + test "GET /api/v1/pleroma/backups", %{user: user, conn: conn} do + assert {:ok, %Oban.Job{args: %{"backup_id" => backup_id}}} = Backup.create(user) + + backup = Backup.get(backup_id) + + response = + conn + |> get("/api/v1/pleroma/backups") + |> json_response_and_validate_schema(:ok) + + assert [ + %{ + "content_type" => "application/zip", + "url" => url, + "file_size" => 0, + "processed" => false, + "inserted_at" => _ + } + ] = response + + assert url == BackupView.download_url(backup) + + Pleroma.Tests.ObanHelpers.perform_all() + + assert [ + %{ + "url" => ^url, + "processed" => true + } + ] = + conn + |> get("/api/v1/pleroma/backups") + |> json_response_and_validate_schema(:ok) + end + + test "POST /api/v1/pleroma/backups", %{user: _user, conn: conn} do + assert [ + %{ + "content_type" => "application/zip", + "url" => url, + "file_size" => 0, + "processed" => false, + "inserted_at" => _ + } + ] = + conn + |> post("/api/v1/pleroma/backups") + |> json_response_and_validate_schema(:ok) + + Pleroma.Tests.ObanHelpers.perform_all() + + assert [ + %{ + "url" => ^url, + "processed" => true + } + ] = + conn + |> get("/api/v1/pleroma/backups") + |> json_response_and_validate_schema(:ok) + + days = Pleroma.Config.get([Backup, :limit_days]) + + assert %{"error" => "Last export was less than #{days} days ago"} == + conn + |> post("/api/v1/pleroma/backups") + |> json_response_and_validate_schema(400) + end +end diff --git a/test/pleroma/web/pleroma_api/controllers/chat_controller_test.exs b/test/pleroma/web/pleroma_api/controllers/chat_controller_test.exs index 6381f9757..fa6b9db65 100644 --- a/test/pleroma/web/pleroma_api/controllers/chat_controller_test.exs +++ b/test/pleroma/web/pleroma_api/controllers/chat_controller_test.exs @@ -82,11 +82,13 @@ defmodule Pleroma.Web.PleromaAPI.ChatControllerTest do result = conn |> put_req_header("content-type", "application/json") + |> put_req_header("idempotency-key", "123") |> post("/api/v1/pleroma/chats/#{chat.id}/messages", %{"content" => "Hallo!!"}) |> json_response_and_validate_schema(200) assert result["content"] == "Hallo!!" assert result["chat_id"] == chat.id |> to_string() + assert result["idempotency_key"] == "123" end test "it fails if there is no content", %{conn: conn, user: user} do diff --git a/test/pleroma/web/pleroma_api/controllers/conversation_controller_test.exs b/test/pleroma/web/pleroma_api/controllers/conversation_controller_test.exs index e6d0b3e37..f2feeaaef 100644 --- a/test/pleroma/web/pleroma_api/controllers/conversation_controller_test.exs +++ b/test/pleroma/web/pleroma_api/controllers/conversation_controller_test.exs @@ -121,7 +121,7 @@ defmodule Pleroma.Web.PleromaAPI.ConversationControllerTest do [participation2, participation1] = Participation.for_user(other_user) assert Participation.get(participation2.id).read == false assert Participation.get(participation1.id).read == false - assert User.get_cached_by_id(other_user.id).unread_conversation_count == 2 + assert Participation.unread_count(other_user) == 2 [%{"unread" => false}, %{"unread" => false}] = conn @@ -131,6 +131,6 @@ defmodule Pleroma.Web.PleromaAPI.ConversationControllerTest do [participation2, participation1] = Participation.for_user(other_user) assert Participation.get(participation2.id).read == true assert Participation.get(participation1.id).read == true - assert User.get_cached_by_id(other_user.id).unread_conversation_count == 0 + assert Participation.unread_count(other_user) == 0 end end diff --git a/test/pleroma/web/pleroma_api/controllers/user_import_controller_test.exs b/test/pleroma/web/pleroma_api/controllers/user_import_controller_test.exs index 433c97e81..68723de71 100644 --- a/test/pleroma/web/pleroma_api/controllers/user_import_controller_test.exs +++ b/test/pleroma/web/pleroma_api/controllers/user_import_controller_test.exs @@ -6,7 +6,6 @@ defmodule Pleroma.Web.PleromaAPI.UserImportControllerTest do use Pleroma.Web.ConnCase use Oban.Testing, repo: Pleroma.Repo - alias Pleroma.Config alias Pleroma.Tests.ObanHelpers import Pleroma.Factory diff --git a/test/pleroma/web/pleroma_api/views/chat_message_reference_view_test.exs b/test/pleroma/web/pleroma_api/views/chat_message_reference_view_test.exs index f171a1e55..ae8257870 100644 --- a/test/pleroma/web/pleroma_api/views/chat_message_reference_view_test.exs +++ b/test/pleroma/web/pleroma_api/views/chat_message_reference_view_test.exs @@ -25,7 +25,9 @@ defmodule Pleroma.Web.PleromaAPI.ChatMessageReferenceViewTest do } {:ok, upload} = ActivityPub.upload(file, actor: user.ap_id) - {:ok, activity} = CommonAPI.post_chat_message(user, recipient, "kippis :firefox:") + + {:ok, activity} = + CommonAPI.post_chat_message(user, recipient, "kippis :firefox:", idempotency_key: "123") chat = Chat.get(user.id, recipient.ap_id) @@ -42,6 +44,7 @@ defmodule Pleroma.Web.PleromaAPI.ChatMessageReferenceViewTest do assert chat_message[:created_at] assert chat_message[:unread] == false assert match?([%{shortcode: "firefox"}], chat_message[:emojis]) + assert chat_message[:idempotency_key] == "123" clear_config([:rich_media, :enabled], true) diff --git a/test/pleroma/web/plugs/frontend_static_plug_test.exs b/test/pleroma/web/plugs/frontend_static_plug_test.exs index f6f7d7bdb..8b7b022fc 100644 --- a/test/pleroma/web/plugs/frontend_static_plug_test.exs +++ b/test/pleroma/web/plugs/frontend_static_plug_test.exs @@ -4,6 +4,7 @@ defmodule Pleroma.Web.Plugs.FrontendStaticPlugTest do use Pleroma.Web.ConnCase + import Mock @dir "test/tmp/instance_static" @@ -53,4 +54,24 @@ defmodule Pleroma.Web.Plugs.FrontendStaticPlugTest do index = get(conn, "/pleroma/admin/") assert html_response(index, 200) == "from frontend plug" end + + test "exclude invalid path", %{conn: conn} do + name = "pleroma-fe" + ref = "dist" + clear_config([:media_proxy, :enabled], true) + clear_config([Pleroma.Web.Endpoint, :secret_key_base], "00000000000") + clear_config([:frontends, :primary], %{"name" => name, "ref" => ref}) + path = "#{@dir}/frontends/#{name}/#{ref}" + + File.mkdir_p!("#{path}/proxy/rr/ss") + File.write!("#{path}/proxy/rr/ss/Ek7w8WPVcAApOvN.jpg:large", "FB image") + + url = + Pleroma.Web.MediaProxy.encode_url("https://pbs.twimg.com/media/Ek7w8WPVcAApOvN.jpg:large") + + with_mock Pleroma.ReverseProxy, + call: fn _conn, _url, _opts -> %Plug.Conn{status: :success} end do + assert %Plug.Conn{status: :success} = get(conn, url) + end + end end diff --git a/test/pleroma/web/plugs/http_security_plug_test.exs b/test/pleroma/web/plugs/http_security_plug_test.exs index 2297e3dac..df2b5ebb3 100644 --- a/test/pleroma/web/plugs/http_security_plug_test.exs +++ b/test/pleroma/web/plugs/http_security_plug_test.exs @@ -5,7 +5,6 @@ defmodule Pleroma.Web.Plugs.HTTPSecurityPlugTest do use Pleroma.Web.ConnCase - alias Pleroma.Config alias Plug.Conn describe "http security enabled" do diff --git a/test/pleroma/web/static_fe/static_fe_controller_test.exs b/test/pleroma/web/static_fe/static_fe_controller_test.exs index f819a1e52..19506f1d8 100644 --- a/test/pleroma/web/static_fe/static_fe_controller_test.exs +++ b/test/pleroma/web/static_fe/static_fe_controller_test.exs @@ -6,14 +6,12 @@ defmodule Pleroma.Web.StaticFE.StaticFEControllerTest do use Pleroma.Web.ConnCase alias Pleroma.Activity - alias Pleroma.Config alias Pleroma.Web.ActivityPub.Transmogrifier alias Pleroma.Web.CommonAPI import Pleroma.Factory setup_all do: clear_config([:static_fe, :enabled], true) - setup do: clear_config([:instance, :federating], true) setup %{conn: conn} do conn = put_req_header(conn, "accept", "text/html") @@ -74,8 +72,27 @@ defmodule Pleroma.Web.StaticFE.StaticFEControllerTest do refute html =~ ">test29<" end - test "it requires authentication if instance is NOT federating", %{conn: conn, user: user} do - ensure_federating_or_authenticated(conn, "/users/#{user.nickname}", user) + test "does not require authentication on non-federating instances", %{ + conn: conn, + user: user + } do + clear_config([:instance, :federating], false) + + conn = get(conn, "/users/#{user.nickname}") + + assert html_response(conn, 200) =~ user.nickname + end + + test "returns 404 for local user with `restrict_unauthenticated/profiles/local` setting", %{ + conn: conn + } do + clear_config([:restrict_unauthenticated, :profiles, :local], true) + + local_user = insert(:user, local: true) + + conn + |> get("/users/#{local_user.nickname}") + |> html_response(404) end end @@ -187,10 +204,28 @@ defmodule Pleroma.Web.StaticFE.StaticFEControllerTest do assert html_response(conn, 302) =~ "redirected" end - test "it requires authentication if instance is NOT federating", %{conn: conn, user: user} do + test "does not require authentication on non-federating instances", %{ + conn: conn, + user: user + } do + clear_config([:instance, :federating], false) + + {:ok, activity} = CommonAPI.post(user, %{status: "testing a thing!"}) + + conn = get(conn, "/notice/#{activity.id}") + + assert html_response(conn, 200) =~ "testing a thing!" + end + + test "returns 404 for local public activity with `restrict_unauthenticated/activities/local` setting", + %{conn: conn, user: user} do + clear_config([:restrict_unauthenticated, :activities, :local], true) + {:ok, activity} = CommonAPI.post(user, %{status: "testing a thing!"}) - ensure_federating_or_authenticated(conn, "/notice/#{activity.id}", user) + conn + |> get("/notice/#{activity.id}") + |> html_response(404) end end end diff --git a/test/pleroma/web/streamer_test.exs b/test/pleroma/web/streamer_test.exs index 185724a9f..395016da2 100644 --- a/test/pleroma/web/streamer_test.exs +++ b/test/pleroma/web/streamer_test.exs @@ -255,7 +255,9 @@ defmodule Pleroma.Web.StreamerTest do } do other_user = insert(:user) - {:ok, create_activity} = CommonAPI.post_chat_message(other_user, user, "hey cirno") + {:ok, create_activity} = + CommonAPI.post_chat_message(other_user, user, "hey cirno", idempotency_key: "123") + object = Object.normalize(create_activity, false) chat = Chat.get(user.id, other_user.ap_id) cm_ref = MessageReference.for_chat_and_object(chat, object) diff --git a/test/pleroma/web/twitter_api/remote_follow_controller_test.exs b/test/pleroma/web/twitter_api/remote_follow_controller_test.exs index 3852c7ce9..a3e784d13 100644 --- a/test/pleroma/web/twitter_api/remote_follow_controller_test.exs +++ b/test/pleroma/web/twitter_api/remote_follow_controller_test.exs @@ -5,7 +5,6 @@ defmodule Pleroma.Web.TwitterAPI.RemoteFollowControllerTest do use Pleroma.Web.ConnCase - alias Pleroma.Config alias Pleroma.MFA alias Pleroma.MFA.TOTP alias Pleroma.User diff --git a/test/support/conn_case.ex b/test/support/conn_case.ex index 9316a82e4..47cb65a80 100644 --- a/test/support/conn_case.ex +++ b/test/support/conn_case.ex @@ -112,28 +112,6 @@ defmodule Pleroma.Web.ConnCase do defp json_response_and_validate_schema(conn, _status) do flunk("Response schema not found for #{conn.method} #{conn.request_path} #{conn.status}") end - - defp ensure_federating_or_authenticated(conn, url, user) do - initial_setting = Config.get([:instance, :federating]) - on_exit(fn -> Config.put([:instance, :federating], initial_setting) end) - - Config.put([:instance, :federating], false) - - conn - |> get(url) - |> response(403) - - conn - |> assign(:user, user) - |> get(url) - |> response(200) - - Config.put([:instance, :federating], true) - - conn - |> get(url) - |> response(200) - end end end diff --git a/test/support/oban_helpers.ex b/test/support/oban_helpers.ex index 9f90a821c..2468f66dc 100644 --- a/test/support/oban_helpers.ex +++ b/test/support/oban_helpers.ex @@ -7,6 +7,8 @@ defmodule Pleroma.Tests.ObanHelpers do Oban test helpers. """ + require Ecto.Query + alias Pleroma.Repo def wipe_all do @@ -15,6 +17,7 @@ defmodule Pleroma.Tests.ObanHelpers do def perform_all do Oban.Job + |> Ecto.Query.where(state: "available") |> Repo.all() |> perform() end |