Restricted embedding of relationships where applicable (statuses / notifications...
[akkoma] / test / web / mastodon_api / controllers / status_controller_test.exs
index 4f467ac11bd9c641a220098d588ce322ee8b5f2f..00e026087641d9b8b40276d06136d1e60fd1b6f2 100644 (file)
@@ -1,5 +1,5 @@
 # Pleroma: A lightweight social networking server
-# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
+# Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
 # SPDX-License-Identifier: AGPL-3.0-only
 
 defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
@@ -19,9 +19,9 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
 
   import Pleroma.Factory
 
-  clear_config([:instance, :federating])
-  clear_config([:instance, :allow_relay])
-  clear_config([:rich_media, :enabled])
+  setup do: clear_config([:instance, :federating])
+  setup do: clear_config([:instance, :allow_relay])
+  setup do: clear_config([:rich_media, :enabled])
 
   describe "posting statuses" do
     setup do: oauth_access(["write:statuses"])
@@ -302,6 +302,17 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
       assert [] == Repo.all(Activity)
     end
 
+    test "ignores nil values", %{conn: conn} do
+      conn =
+        post(conn, "/api/v1/statuses", %{
+          "status" => "not scheduled",
+          "scheduled_at" => nil
+        })
+
+      assert result = json_response(conn, 200)
+      assert Activity.get_by_id(result["id"])
+    end
+
     test "creates a scheduled activity with a media attachment", %{user: user, conn: conn} do
       scheduled_at = NaiveDateTime.add(NaiveDateTime.utc_now(), :timer.minutes(120), :millisecond)
 
@@ -476,6 +487,104 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
     assert id == to_string(activity.id)
   end
 
+  defp local_and_remote_activities do
+    local = insert(:note_activity)
+    remote = insert(:note_activity, local: false)
+    {:ok, local: local, remote: remote}
+  end
+
+  describe "status with restrict unauthenticated activities for local and remote" do
+    setup do: local_and_remote_activities()
+
+    setup do: clear_config([:restrict_unauthenticated, :activities, :local], true)
+
+    setup do: clear_config([:restrict_unauthenticated, :activities, :remote], true)
+
+    test "if user is unauthenticated", %{conn: conn, local: local, remote: remote} do
+      res_conn = get(conn, "/api/v1/statuses/#{local.id}")
+
+      assert json_response(res_conn, :not_found) == %{
+               "error" => "Record not found"
+             }
+
+      res_conn = get(conn, "/api/v1/statuses/#{remote.id}")
+
+      assert json_response(res_conn, :not_found) == %{
+               "error" => "Record not found"
+             }
+    end
+
+    test "if user is authenticated", %{local: local, remote: remote} do
+      %{conn: conn} = oauth_access(["read"])
+      res_conn = get(conn, "/api/v1/statuses/#{local.id}")
+      assert %{"id" => _} = json_response(res_conn, 200)
+
+      res_conn = get(conn, "/api/v1/statuses/#{remote.id}")
+      assert %{"id" => _} = json_response(res_conn, 200)
+    end
+  end
+
+  describe "status with restrict unauthenticated activities for local" do
+    setup do: local_and_remote_activities()
+
+    setup do: clear_config([:restrict_unauthenticated, :activities, :local], true)
+
+    test "if user is unauthenticated", %{conn: conn, local: local, remote: remote} do
+      res_conn = get(conn, "/api/v1/statuses/#{local.id}")
+
+      assert json_response(res_conn, :not_found) == %{
+               "error" => "Record not found"
+             }
+
+      res_conn = get(conn, "/api/v1/statuses/#{remote.id}")
+      assert %{"id" => _} = json_response(res_conn, 200)
+    end
+
+    test "if user is authenticated", %{local: local, remote: remote} do
+      %{conn: conn} = oauth_access(["read"])
+      res_conn = get(conn, "/api/v1/statuses/#{local.id}")
+      assert %{"id" => _} = json_response(res_conn, 200)
+
+      res_conn = get(conn, "/api/v1/statuses/#{remote.id}")
+      assert %{"id" => _} = json_response(res_conn, 200)
+    end
+  end
+
+  describe "status with restrict unauthenticated activities for remote" do
+    setup do: local_and_remote_activities()
+
+    setup do: clear_config([:restrict_unauthenticated, :activities, :remote], true)
+
+    test "if user is unauthenticated", %{conn: conn, local: local, remote: remote} do
+      res_conn = get(conn, "/api/v1/statuses/#{local.id}")
+      assert %{"id" => _} = json_response(res_conn, 200)
+
+      res_conn = get(conn, "/api/v1/statuses/#{remote.id}")
+
+      assert json_response(res_conn, :not_found) == %{
+               "error" => "Record not found"
+             }
+    end
+
+    test "if user is authenticated", %{local: local, remote: remote} do
+      %{conn: conn} = oauth_access(["read"])
+      res_conn = get(conn, "/api/v1/statuses/#{local.id}")
+      assert %{"id" => _} = json_response(res_conn, 200)
+
+      res_conn = get(conn, "/api/v1/statuses/#{remote.id}")
+      assert %{"id" => _} = json_response(res_conn, 200)
+    end
+  end
+
+  test "getting a status that doesn't exist returns 404" do
+    %{conn: conn} = oauth_access(["read:statuses"])
+    activity = insert(:note_activity)
+
+    conn = get(conn, "/api/v1/statuses/#{String.downcase(activity.id)}")
+
+    assert json_response(conn, 404) == %{"error" => "Record not found"}
+  end
+
   test "get a direct status" do
     %{user: user, conn: conn} = oauth_access(["read:statuses"])
     other_user = insert(:user)
@@ -505,6 +614,70 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
     assert [%{"id" => ^id1}, %{"id" => ^id2}] = Enum.sort_by(json_response(conn, :ok), & &1["id"])
   end
 
+  describe "getting statuses by ids with restricted unauthenticated for local and remote" do
+    setup do: local_and_remote_activities()
+
+    setup do: clear_config([:restrict_unauthenticated, :activities, :local], true)
+
+    setup do: clear_config([:restrict_unauthenticated, :activities, :remote], true)
+
+    test "if user is unauthenticated", %{conn: conn, local: local, remote: remote} do
+      res_conn = get(conn, "/api/v1/statuses", %{ids: [local.id, remote.id]})
+
+      assert json_response(res_conn, 200) == []
+    end
+
+    test "if user is authenticated", %{local: local, remote: remote} do
+      %{conn: conn} = oauth_access(["read"])
+
+      res_conn = get(conn, "/api/v1/statuses", %{ids: [local.id, remote.id]})
+
+      assert length(json_response(res_conn, 200)) == 2
+    end
+  end
+
+  describe "getting statuses by ids with restricted unauthenticated for local" do
+    setup do: local_and_remote_activities()
+
+    setup do: clear_config([:restrict_unauthenticated, :activities, :local], true)
+
+    test "if user is unauthenticated", %{conn: conn, local: local, remote: remote} do
+      res_conn = get(conn, "/api/v1/statuses", %{ids: [local.id, remote.id]})
+
+      remote_id = remote.id
+      assert [%{"id" => ^remote_id}] = json_response(res_conn, 200)
+    end
+
+    test "if user is authenticated", %{local: local, remote: remote} do
+      %{conn: conn} = oauth_access(["read"])
+
+      res_conn = get(conn, "/api/v1/statuses", %{ids: [local.id, remote.id]})
+
+      assert length(json_response(res_conn, 200)) == 2
+    end
+  end
+
+  describe "getting statuses by ids with restricted unauthenticated for remote" do
+    setup do: local_and_remote_activities()
+
+    setup do: clear_config([:restrict_unauthenticated, :activities, :remote], true)
+
+    test "if user is unauthenticated", %{conn: conn, local: local, remote: remote} do
+      res_conn = get(conn, "/api/v1/statuses", %{ids: [local.id, remote.id]})
+
+      local_id = local.id
+      assert [%{"id" => ^local_id}] = json_response(res_conn, 200)
+    end
+
+    test "if user is authenticated", %{local: local, remote: remote} do
+      %{conn: conn} = oauth_access(["read"])
+
+      res_conn = get(conn, "/api/v1/statuses", %{ids: [local.id, remote.id]})
+
+      assert length(json_response(res_conn, 200)) == 2
+    end
+  end
+
   describe "deleting a status" do
     test "when you created it" do
       %{user: author, conn: conn} = oauth_access(["write:statuses"])
@@ -520,6 +693,18 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
       refute Activity.get_by_id(activity.id)
     end
 
+    test "when it doesn't exist" do
+      %{user: author, conn: conn} = oauth_access(["write:statuses"])
+      activity = insert(:note_activity, user: author)
+
+      conn =
+        conn
+        |> assign(:user, author)
+        |> delete("/api/v1/statuses/#{String.downcase(activity.id)}")
+
+      assert %{"error" => "Record not found"} == json_response(conn, 404)
+    end
+
     test "when you didn't create it" do
       %{conn: conn} = oauth_access(["write:statuses"])
       activity = insert(:note_activity)
@@ -574,6 +759,14 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
       assert to_string(activity.id) == id
     end
 
+    test "returns 404 if the reblogged status doesn't exist", %{conn: conn} do
+      activity = insert(:note_activity)
+
+      conn = post(conn, "/api/v1/statuses/#{String.downcase(activity.id)}/reblog")
+
+      assert %{"error" => "Record not found"} = json_response(conn, 404)
+    end
+
     test "reblogs privately and returns the reblogged status", %{conn: conn} do
       activity = insert(:note_activity)
 
@@ -593,7 +786,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
       user1 = insert(:user)
       user2 = insert(:user)
       user3 = insert(:user)
-      CommonAPI.favorite(activity.id, user2)
+      {:ok, _} = CommonAPI.favorite(user2, activity.id)
       {:ok, _bookmark} = Pleroma.Bookmark.create(user2.id, activity.id)
       {:ok, reblog_activity1, _object} = CommonAPI.repeat(activity.id, user1)
       {:ok, _, _object} = CommonAPI.repeat(activity.id, user2)
@@ -626,12 +819,6 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
 
       assert to_string(activity.id) == id
     end
-
-    test "returns 400 error when activity is not exist", %{conn: conn} do
-      conn = post(conn, "/api/v1/statuses/foo/reblog")
-
-      assert json_response(conn, 400) == %{"error" => "Could not repeat"}
-    end
   end
 
   describe "unreblogging" do
@@ -649,10 +836,10 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
       assert to_string(activity.id) == id
     end
 
-    test "returns 400 error when activity is not exist", %{conn: conn} do
+    test "returns 404 error when activity does not exist", %{conn: conn} do
       conn = post(conn, "/api/v1/statuses/foo/unreblog")
 
-      assert json_response(conn, 400) == %{"error" => "Could not unrepeat"}
+      assert json_response(conn, 404) == %{"error" => "Record not found"}
     end
   end
 
@@ -674,13 +861,17 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
       activity = insert(:note_activity)
 
       post(conn, "/api/v1/statuses/#{activity.id}/favourite")
-      assert post(conn, "/api/v1/statuses/#{activity.id}/favourite") |> json_response(200)
+
+      assert post(conn, "/api/v1/statuses/#{activity.id}/favourite")
+             |> json_response(200)
     end
 
-    test "returns 400 error for a wrong id", %{conn: conn} do
-      conn = post(conn, "/api/v1/statuses/1/favourite")
+    test "returns 404 error for a wrong id", %{conn: conn} do
+      conn =
+        conn
+        |> post("/api/v1/statuses/1/favourite")
 
-      assert json_response(conn, 400) == %{"error" => "Could not favorite"}
+      assert json_response(conn, 404) == %{"error" => "Record not found"}
     end
   end
 
@@ -690,7 +881,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
     test "unfavorites a status and returns it", %{user: user, conn: conn} do
       activity = insert(:note_activity)
 
-      {:ok, _, _} = CommonAPI.favorite(activity.id, user)
+      {:ok, _} = CommonAPI.favorite(user, activity.id)
 
       conn = post(conn, "/api/v1/statuses/#{activity.id}/unfavourite")
 
@@ -700,10 +891,10 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
       assert to_string(activity.id) == id
     end
 
-    test "returns 400 error for a wrong id", %{conn: conn} do
+    test "returns 404 error for a wrong id", %{conn: conn} do
       conn = post(conn, "/api/v1/statuses/1/unfavourite")
 
-      assert json_response(conn, 400) == %{"error" => "Could not unfavorite"}
+      assert json_response(conn, 404) == %{"error" => "Record not found"}
     end
   end
 
@@ -716,9 +907,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
       %{activity: activity}
     end
 
-    clear_config([:instance, :max_pinned_statuses]) do
-      Config.put([:instance, :max_pinned_statuses], 1)
-    end
+    setup do: clear_config([:instance, :max_pinned_statuses], 1)
 
     test "pin status", %{conn: conn, user: user, activity: activity} do
       id_str = to_string(activity.id)
@@ -869,6 +1058,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
   end
 
   test "bookmarks" do
+    bookmarks_uri = "/api/v1/bookmarks"
+
     %{conn: conn} = oauth_access(["write:bookmarks", "read:bookmarks"])
     author = insert(:user)
 
@@ -890,7 +1081,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
 
     assert json_response(response2, 200)["bookmarked"] == true
 
-    bookmarks = get(conn, "/api/v1/bookmarks")
+    bookmarks = get(conn, bookmarks_uri)
 
     assert [json_response(response2, 200), json_response(response1, 200)] ==
              json_response(bookmarks, 200)
@@ -899,7 +1090,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
 
     assert json_response(response1, 200)["bookmarked"] == false
 
-    bookmarks = get(conn, "/api/v1/bookmarks")
+    bookmarks = get(conn, bookmarks_uri)
 
     assert [json_response(response2, 200)] == json_response(bookmarks, 200)
   end
@@ -1002,7 +1193,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
 
     test "returns users who have favorited the status", %{conn: conn, activity: activity} do
       other_user = insert(:user)
-      {:ok, _, _} = CommonAPI.favorite(activity.id, other_user)
+      {:ok, _} = CommonAPI.favorite(other_user, activity.id)
 
       response =
         conn
@@ -1033,7 +1224,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
       other_user = insert(:user)
       {:ok, _user_relationship} = User.block(user, other_user)
 
-      {:ok, _, _} = CommonAPI.favorite(activity.id, other_user)
+      {:ok, _} = CommonAPI.favorite(other_user, activity.id)
 
       response =
         conn
@@ -1045,7 +1236,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
 
     test "does not fail on an unauthenticated request", %{activity: activity} do
       other_user = insert(:user)
-      {:ok, _, _} = CommonAPI.favorite(activity.id, other_user)
+      {:ok, _} = CommonAPI.favorite(other_user, activity.id)
 
       response =
         build_conn()
@@ -1065,7 +1256,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
           "visibility" => "direct"
         })
 
-      {:ok, _, _} = CommonAPI.favorite(activity.id, other_user)
+      {:ok, _} = CommonAPI.favorite(other_user, activity.id)
 
       favourited_by_url = "/api/v1/statuses/#{activity.id}/favourited_by"
 
@@ -1225,7 +1416,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
     {:ok, _} = CommonAPI.post(other_user, %{"status" => "bla"})
     {:ok, activity} = CommonAPI.post(other_user, %{"status" => "traps are happy"})
 
-    {:ok, _, _} = CommonAPI.favorite(activity.id, user)
+    {:ok, _} = CommonAPI.favorite(user, activity.id)
 
     first_conn = get(conn, "/api/v1/favourites")
 
@@ -1242,7 +1433,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
           "Trees Are Never Sad Look At Them Every Once In Awhile They're Quite Beautiful."
       })
 
-    {:ok, _, _} = CommonAPI.favorite(second_activity.id, user)
+    {:ok, _} = CommonAPI.favorite(user, second_activity.id)
 
     last_like = status["id"]
 
@@ -1255,4 +1446,23 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
 
     assert [] = json_response(third_conn, 200)
   end
+
+  test "expires_at is nil for another user" do
+    %{conn: conn, user: user} = oauth_access(["read:statuses"])
+    {:ok, activity} = CommonAPI.post(user, %{"status" => "foobar", "expires_in" => 1_000_000})
+
+    expires_at =
+      activity.id
+      |> ActivityExpiration.get_by_activity_id()
+      |> Map.get(:scheduled_at)
+      |> NaiveDateTime.to_iso8601()
+
+    assert %{"pleroma" => %{"expires_at" => ^expires_at}} =
+             conn |> get("/api/v1/statuses/#{activity.id}") |> json_response(:ok)
+
+    %{conn: conn} = oauth_access(["read:statuses"])
+
+    assert %{"pleroma" => %{"expires_at" => nil}} =
+             conn |> get("/api/v1/statuses/#{activity.id}") |> json_response(:ok)
+  end
 end