Merge remote-tracking branch 'origin' into follower-hiding
[akkoma] / test / web / mastodon_api / mastodon_api_controller_test.exs
index 1291c3693dd04135c7363dbb0d3d9403aba0e7dc..6b1215be667e99866d57e69eeaa8b13db4fac36f 100644 (file)
@@ -4,9 +4,16 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
   alias Pleroma.Web.TwitterAPI.TwitterAPI
   alias Pleroma.{Repo, User, Activity, Notification}
   alias Pleroma.Web.{OStatus, CommonAPI}
+  alias Pleroma.Web.ActivityPub.ActivityPub
 
   import Pleroma.Factory
   import ExUnit.CaptureLog
+  import Tesla.Mock
+
+  setup do
+    mock(fn env -> apply(HttpRequestMock, :request, [env]) end)
+    :ok
+  end
 
   test "the home timeline", %{conn: conn} do
     user = insert(:user)
@@ -177,6 +184,32 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
       |> get("api/v1/timelines/home")
 
     [_s1, _s2] = json_response(res_conn, 200)
+
+    # Test pagination
+    Enum.each(1..20, fn _ ->
+      {:ok, _} =
+        CommonAPI.post(user_one, %{
+          "status" => "Hi @#{user_two.nickname}!",
+          "visibility" => "direct"
+        })
+    end)
+
+    res_conn =
+      conn
+      |> assign(:user, user_two)
+      |> get("api/v1/timelines/direct")
+
+    statuses = json_response(res_conn, 200)
+    assert length(statuses) == 20
+
+    res_conn =
+      conn
+      |> assign(:user, user_two)
+      |> get("api/v1/timelines/direct", %{max_id: List.last(statuses)["id"]})
+
+    [status] = json_response(res_conn, 200)
+
+    assert status["url"] != direct.data["id"]
   end
 
   test "replying to a status", %{conn: conn} do
@@ -197,6 +230,21 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
     assert activity.data["object"]["inReplyToStatusId"] == replied_to.id
   end
 
+  test "posting a status with an invalid in_reply_to_id", %{conn: conn} do
+    user = insert(:user)
+
+    conn =
+      conn
+      |> assign(:user, user)
+      |> post("/api/v1/statuses", %{"status" => "xD", "in_reply_to_id" => ""})
+
+    assert %{"content" => "xD", "id" => id} = json_response(conn, 200)
+
+    activity = Repo.get(Activity, id)
+
+    assert activity
+  end
+
   test "verify_credentials", %{conn: conn} do
     user = insert(:user)
 
@@ -205,7 +253,19 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
       |> assign(:user, user)
       |> get("/api/v1/accounts/verify_credentials")
 
-    assert %{"id" => id} = json_response(conn, 200)
+    assert %{"id" => id, "source" => %{"privacy" => "public"}} = json_response(conn, 200)
+    assert id == to_string(user.id)
+  end
+
+  test "verify_credentials default scope unlisted", %{conn: conn} do
+    user = insert(:user, %{info: %Pleroma.User.Info{default_scope: "unlisted"}})
+
+    conn =
+      conn
+      |> assign(:user, user)
+      |> get("/api/v1/accounts/verify_credentials")
+
+    assert %{"id" => id, "source" => %{"privacy" => "unlisted"}} = json_response(conn, 200)
     assert id == to_string(user.id)
   end
 
@@ -250,6 +310,127 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
     end
   end
 
+  describe "filters" do
+    test "creating a filter", %{conn: conn} do
+      user = insert(:user)
+
+      filter = %Pleroma.Filter{
+        phrase: "knights",
+        context: ["home"]
+      }
+
+      conn =
+        conn
+        |> assign(:user, user)
+        |> post("/api/v1/filters", %{"phrase" => filter.phrase, context: filter.context})
+
+      assert response = json_response(conn, 200)
+      assert response["phrase"] == filter.phrase
+      assert response["context"] == filter.context
+      assert response["id"] != nil
+      assert response["id"] != ""
+    end
+
+    test "fetching a list of filters", %{conn: conn} do
+      user = insert(:user)
+
+      query_one = %Pleroma.Filter{
+        user_id: user.id,
+        filter_id: 1,
+        phrase: "knights",
+        context: ["home"]
+      }
+
+      query_two = %Pleroma.Filter{
+        user_id: user.id,
+        filter_id: 2,
+        phrase: "who",
+        context: ["home"]
+      }
+
+      {:ok, filter_one} = Pleroma.Filter.create(query_one)
+      {:ok, filter_two} = Pleroma.Filter.create(query_two)
+
+      conn =
+        conn
+        |> assign(:user, user)
+        |> get("/api/v1/filters")
+
+      assert response = json_response(conn, 200)
+    end
+
+    test "get a filter", %{conn: conn} do
+      user = insert(:user)
+
+      query = %Pleroma.Filter{
+        user_id: user.id,
+        filter_id: 2,
+        phrase: "knight",
+        context: ["home"]
+      }
+
+      {:ok, filter} = Pleroma.Filter.create(query)
+
+      conn =
+        conn
+        |> assign(:user, user)
+        |> get("/api/v1/filters/#{filter.filter_id}")
+
+      assert response = json_response(conn, 200)
+    end
+
+    test "update a filter", %{conn: conn} do
+      user = insert(:user)
+
+      query = %Pleroma.Filter{
+        user_id: user.id,
+        filter_id: 2,
+        phrase: "knight",
+        context: ["home"]
+      }
+
+      {:ok, filter} = Pleroma.Filter.create(query)
+
+      new = %Pleroma.Filter{
+        phrase: "nii",
+        context: ["home"]
+      }
+
+      conn =
+        conn
+        |> assign(:user, user)
+        |> put("/api/v1/filters/#{query.filter_id}", %{
+          phrase: new.phrase,
+          context: new.context
+        })
+
+      assert response = json_response(conn, 200)
+      assert response["phrase"] == new.phrase
+      assert response["context"] == new.context
+    end
+
+    test "delete a filter", %{conn: conn} do
+      user = insert(:user)
+
+      query = %Pleroma.Filter{
+        user_id: user.id,
+        filter_id: 2,
+        phrase: "knight",
+        context: ["home"]
+      }
+
+      {:ok, filter} = Pleroma.Filter.create(query)
+
+      conn =
+        conn
+        |> assign(:user, user)
+        |> delete("/api/v1/filters/#{filter.filter_id}")
+
+      assert response = json_response(conn, 200)
+      assert response == %{}
+    end
+  end
+
   describe "lists" do
     test "creating a list", %{conn: conn} do
       user = insert(:user)
@@ -367,6 +548,30 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
 
       assert id == to_string(activity_two.id)
     end
+
+    test "list timeline does not leak non-public statuses for unfollowed users", %{conn: conn} do
+      user = insert(:user)
+      other_user = insert(:user)
+      {:ok, activity_one} = TwitterAPI.create_status(other_user, %{"status" => "Marisa is cute."})
+
+      {:ok, activity_two} =
+        TwitterAPI.create_status(other_user, %{
+          "status" => "Marisa is cute.",
+          "visibility" => "private"
+        })
+
+      {:ok, list} = Pleroma.List.create("name", user)
+      {:ok, list} = Pleroma.List.follow(list, other_user)
+
+      conn =
+        conn
+        |> assign(:user, user)
+        |> get("/api/v1/timelines/list/#{list.id}")
+
+      assert [%{"id" => id}] = json_response(conn, 200)
+
+      assert id == to_string(activity_one.id)
+    end
   end
 
   describe "notifications" do
@@ -644,6 +849,85 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
     end
   end
 
+  describe "locked accounts" do
+    test "/api/v1/follow_requests works" do
+      user = insert(:user, %{info: %Pleroma.User.Info{locked: true}})
+      other_user = insert(:user)
+
+      {:ok, activity} = ActivityPub.follow(other_user, user)
+
+      user = Repo.get(User, user.id)
+      other_user = Repo.get(User, other_user.id)
+
+      assert User.following?(other_user, user) == false
+
+      conn =
+        build_conn()
+        |> assign(:user, user)
+        |> get("/api/v1/follow_requests")
+
+      assert [relationship] = json_response(conn, 200)
+      assert to_string(other_user.id) == relationship["id"]
+    end
+
+    test "/api/v1/follow_requests/:id/authorize works" do
+      user = insert(:user, %{info: %Pleroma.User.Info{locked: true}})
+      other_user = insert(:user)
+
+      {:ok, activity} = ActivityPub.follow(other_user, user)
+
+      user = Repo.get(User, user.id)
+      other_user = Repo.get(User, other_user.id)
+
+      assert User.following?(other_user, user) == false
+
+      conn =
+        build_conn()
+        |> assign(:user, user)
+        |> post("/api/v1/follow_requests/#{other_user.id}/authorize")
+
+      assert relationship = json_response(conn, 200)
+      assert to_string(other_user.id) == relationship["id"]
+
+      user = Repo.get(User, user.id)
+      other_user = Repo.get(User, other_user.id)
+
+      assert User.following?(other_user, user) == true
+    end
+
+    test "verify_credentials", %{conn: conn} do
+      user = insert(:user, %{info: %Pleroma.User.Info{default_scope: "private"}})
+
+      conn =
+        conn
+        |> assign(:user, user)
+        |> get("/api/v1/accounts/verify_credentials")
+
+      assert %{"id" => id, "source" => %{"privacy" => "private"}} = json_response(conn, 200)
+      assert id == to_string(user.id)
+    end
+
+    test "/api/v1/follow_requests/:id/reject works" do
+      user = insert(:user, %{info: %Pleroma.User.Info{locked: true}})
+      other_user = insert(:user)
+
+      {:ok, activity} = ActivityPub.follow(other_user, user)
+
+      conn =
+        build_conn()
+        |> assign(:user, user)
+        |> post("/api/v1/follow_requests/#{other_user.id}/reject")
+
+      assert relationship = json_response(conn, 200)
+      assert to_string(other_user.id) == relationship["id"]
+
+      user = Repo.get(User, user.id)
+      other_user = Repo.get(User, other_user.id)
+
+      assert User.following?(other_user, user) == false
+    end
+  end
+
   test "account fetching", %{conn: conn} do
     user = insert(:user)
 
@@ -668,16 +952,19 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
       filename: "an_image.jpg"
     }
 
+    desc = "Description of the image"
+
     user = insert(:user)
 
     conn =
       conn
       |> assign(:user, user)
-      |> post("/api/v1/media", %{"file" => file})
+      |> post("/api/v1/media", %{"file" => file, "description" => desc})
 
     assert media = json_response(conn, 200)
 
     assert media["type"] == "image"
+    assert media["description"] == desc
   end
 
   test "hashtag timeline", %{conn: conn} do
@@ -689,11 +976,20 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
       {:ok, [_activity]} =
         OStatus.fetch_activity_from_url("https://shitposter.club/notice/2827873")
 
-      conn =
+      nconn =
         conn
         |> get("/api/v1/timelines/tag/2hu")
 
-      assert [%{"id" => id}] = json_response(conn, 200)
+      assert [%{"id" => id}] = json_response(nconn, 200)
+
+      assert id == to_string(activity.id)
+
+      # works for different capitalization too
+      nconn =
+        conn
+        |> get("/api/v1/timelines/tag/2HU")
+
+      assert [%{"id" => id}] = json_response(nconn, 200)
 
       assert id == to_string(activity.id)
     end)
@@ -712,6 +1008,31 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
     assert id == to_string(user.id)
   end
 
+  test "getting followers, hide_network", %{conn: conn} do
+    user = insert(:user)
+    other_user = insert(:user, %{info: %{hide_network: true}})
+    {:ok, user} = User.follow(user, other_user)
+
+    conn =
+      conn
+      |> get("/api/v1/accounts/#{other_user.id}/followers")
+
+    assert [] == json_response(conn, 200)
+  end
+
+  test "getting followers, hide_network, same user requesting", %{conn: conn} do
+    user = insert(:user)
+    other_user = insert(:user, %{info: %{hide_network: true}})
+    {:ok, user} = User.follow(user, other_user)
+
+    conn =
+      conn
+      |> assign(:user, other_user)
+      |> get("/api/v1/accounts/#{other_user.id}/followers")
+
+    refute [] == json_response(conn, 200)
+  end
+
   test "getting following", %{conn: conn} do
     user = insert(:user)
     other_user = insert(:user)
@@ -725,6 +1046,31 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
     assert id == to_string(other_user.id)
   end
 
+  test "getting following, hide_network", %{conn: conn} do
+    user = insert(:user, %{info: %{hide_network: true}})
+    other_user = insert(:user)
+    {:ok, user} = User.follow(user, other_user)
+
+    conn =
+      conn
+      |> get("/api/v1/accounts/#{user.id}/following")
+
+    assert [] == json_response(conn, 200)
+  end
+
+  test "getting following, hide_network, same user requesting", %{conn: conn} do
+    user = insert(:user, %{info: %{hide_network: true}})
+    other_user = insert(:user)
+    {:ok, user} = User.follow(user, other_user)
+
+    conn =
+      conn
+      |> assign(:user, user)
+      |> get("/api/v1/accounts/#{user.id}/following")
+
+    refute [] == json_response(conn, 200)
+  end
+
   test "following / unfollowing a user", %{conn: conn} do
     user = insert(:user)
     other_user = insert(:user)
@@ -792,6 +1138,46 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
     assert [%{"id" => ^other_user_id}] = json_response(conn, 200)
   end
 
+  test "blocking / unblocking a domain", %{conn: conn} do
+    user = insert(:user)
+    other_user = insert(:user, %{ap_id: "https://dogwhistle.zone/@pundit"})
+
+    conn =
+      conn
+      |> assign(:user, user)
+      |> post("/api/v1/domain_blocks", %{"domain" => "dogwhistle.zone"})
+
+    assert %{} = json_response(conn, 200)
+    user = User.get_cached_by_ap_id(user.ap_id)
+    assert User.blocks?(user, other_user)
+
+    conn =
+      build_conn()
+      |> assign(:user, user)
+      |> delete("/api/v1/domain_blocks", %{"domain" => "dogwhistle.zone"})
+
+    assert %{} = json_response(conn, 200)
+    user = User.get_cached_by_ap_id(user.ap_id)
+    refute User.blocks?(user, other_user)
+  end
+
+  test "getting a list of domain blocks", %{conn: conn} do
+    user = insert(:user)
+
+    {:ok, user} = User.block_domain(user, "bad.site")
+    {:ok, user} = User.block_domain(user, "even.worse.site")
+
+    conn =
+      conn
+      |> assign(:user, user)
+      |> get("/api/v1/domain_blocks")
+
+    domain_blocks = json_response(conn, 200)
+
+    assert "bad.site" in domain_blocks
+    assert "even.worse.site" in domain_blocks
+  end
+
   test "unimplemented mute endpoints" do
     user = insert(:user)
     other_user = insert(:user)
@@ -923,14 +1309,33 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
   describe "updating credentials" do
     test "updates the user's bio", %{conn: conn} do
       user = insert(:user)
+      user2 = insert(:user)
 
       conn =
         conn
         |> assign(:user, user)
-        |> patch("/api/v1/accounts/update_credentials", %{"note" => "I drink #cofe"})
+        |> patch("/api/v1/accounts/update_credentials", %{
+          "note" => "I drink #cofe with @#{user2.nickname}"
+        })
 
       assert user = json_response(conn, 200)
-      assert user["note"] == "I drink #cofe"
+
+      assert user["note"] ==
+               "I drink <a href=\"http://localhost:4001/tag/cofe\">#cofe</a> with <span><a href=\"#{
+                 user2.ap_id
+               }\">@<span>#{user2.nickname}</span></a></span>"
+    end
+
+    test "updates the user's locking status", %{conn: conn} do
+      user = insert(:user)
+
+      conn =
+        conn
+        |> assign(:user, user)
+        |> patch("/api/v1/accounts/update_credentials", %{locked: "true"})
+
+      assert user = json_response(conn, 200)
+      assert user["locked"] == true
     end
 
     test "updates the user's name", %{conn: conn} do
@@ -959,8 +1364,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
         |> assign(:user, user)
         |> patch("/api/v1/accounts/update_credentials", %{"avatar" => new_avatar})
 
-      assert user = json_response(conn, 200)
-      assert user["avatar"] != "https://placehold.it/48x48"
+      assert user_response = json_response(conn, 200)
+      assert user_response["avatar"] != User.avatar_url(user)
     end
 
     test "updates the user's banner", %{conn: conn} do
@@ -977,8 +1382,8 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do
         |> assign(:user, user)
         |> patch("/api/v1/accounts/update_credentials", %{"header" => new_header})
 
-      assert user = json_response(conn, 200)
-      assert user["header"] != "https://placehold.it/700x335"
+      assert user_response = json_response(conn, 200)
+      assert user_response["header"] != User.banner_url(user)
     end
   end