Add timeline visibility options
[akkoma] / test / pleroma / web / mastodon_api / controllers / timeline_controller_test.exs
index 89225b95d921154cf8ea48c1c83a94d6c6d3dd12..fcc7a204eb58b429d7afd4246ded0a7d30cc59dc 100644 (file)
@@ -288,7 +288,7 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do
         get(conn, "/api/v1/timelines/public")
         |> json_response_and_validate_schema(200)
 
-      assert length(response) == 0
+      assert response == []
     end
 
     test "doesn't return replies if follow is posting with users from blocked domain" do
@@ -367,6 +367,67 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do
                }
              ] = result
     end
+
+    test "should return local-only posts for authenticated users" do
+      user = insert(:user)
+      %{user: _reader, conn: conn} = oauth_access(["read:statuses"])
+
+      {:ok, %{id: id}} = CommonAPI.post(user, %{status: "#2hu #2HU", visibility: "local"})
+
+      result =
+        conn
+        |> get("/api/v1/timelines/public")
+        |> json_response_and_validate_schema(200)
+
+      assert [%{"id" => ^id}] = result
+    end
+
+    test "should not return local-only posts for users without read:statuses" do
+      user = insert(:user)
+      %{user: _reader, conn: conn} = oauth_access([])
+
+      {:ok, _activity} = CommonAPI.post(user, %{status: "#2hu #2HU", visibility: "local"})
+
+      result =
+        conn
+        |> get("/api/v1/timelines/public")
+        |> json_response_and_validate_schema(200)
+
+      assert [] = result
+    end
+
+    test "should not return local-only posts for anonymous users" do
+      user = insert(:user)
+
+      {:ok, _activity} = CommonAPI.post(user, %{status: "#2hu #2HU", visibility: "local"})
+
+      result =
+        build_conn()
+        |> get("/api/v1/timelines/public")
+        |> json_response_and_validate_schema(200)
+
+      assert [] = result
+    end
+
+    test "should return 404 if disabled" do
+      clear_config([:instance, :federated_timeline_available], false)
+
+      result =
+        build_conn()
+        |> get("/api/v1/timelines/public")
+        |> json_response_and_validate_schema(404)
+
+      assert %{"error" => "Federated timeline is disabled"} = result
+    end
+
+    test "should not return 404 if local is specified" do
+      clear_config([:instance, :federated_timeline_available], false)
+
+      result =
+        build_conn()
+        |> get("/api/v1/timelines/public?local=true")
+        |> json_response_and_validate_schema(200)
+    end
   end
 
   defp local_and_remote_activities do
@@ -486,7 +547,7 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do
         |> assign(:token, insert(:oauth_token, user: user_two, scopes: ["read:statuses"]))
 
       # Only direct should be visible here
-      res_conn = get(conn_user_two, "api/v1/timelines/direct")
+      res_conn = get(conn_user_two, "/api/v1/timelines/direct")
 
       assert [status] = json_response_and_validate_schema(res_conn, :ok)
 
@@ -498,14 +559,14 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do
         build_conn()
         |> assign(:user, user_one)
         |> assign(:token, insert(:oauth_token, user: user_one, scopes: ["read:statuses"]))
-        |> get("api/v1/timelines/direct")
+        |> get("/api/v1/timelines/direct")
 
       [status] = json_response_and_validate_schema(res_conn, :ok)
 
       assert %{"visibility" => "direct"} = status
 
       # Both should be visible here
-      res_conn = get(conn_user_two, "api/v1/timelines/home")
+      res_conn = get(conn_user_two, "/api/v1/timelines/home")
 
       [_s1, _s2] = json_response_and_validate_schema(res_conn, :ok)
 
@@ -518,14 +579,14 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do
           })
       end)
 
-      res_conn = get(conn_user_two, "api/v1/timelines/direct")
+      res_conn = get(conn_user_two, "/api/v1/timelines/direct")
 
       statuses = json_response_and_validate_schema(res_conn, :ok)
       assert length(statuses) == 20
 
       max_id = List.last(statuses)["id"]
 
-      res_conn = get(conn_user_two, "api/v1/timelines/direct?max_id=#{max_id}")
+      res_conn = get(conn_user_two, "/api/v1/timelines/direct?max_id=#{max_id}")
 
       assert [status] = json_response_and_validate_schema(res_conn, :ok)
 
@@ -550,7 +611,7 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do
           visibility: "direct"
         })
 
-      res_conn = get(conn, "api/v1/timelines/direct")
+      res_conn = get(conn, "/api/v1/timelines/direct")
 
       [status] = json_response_and_validate_schema(res_conn, :ok)
       assert status["id"] == direct.id
@@ -923,10 +984,10 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do
       %{conn: auth_conn} = oauth_access(["read:statuses"])
 
       res_conn = get(auth_conn, "#{base_uri}?local=true")
-      assert length(json_response(res_conn, 200)) == 1
+      assert length(json_response_and_validate_schema(res_conn, 200)) == 1
 
       res_conn = get(auth_conn, "#{base_uri}?local=false")
-      assert length(json_response(res_conn, 200)) == 2
+      assert length(json_response_and_validate_schema(res_conn, 200)) == 2
     end
 
     test "with default settings on private instances, returns 403 for unauthenticated users", %{
@@ -940,7 +1001,7 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do
       for local <- [true, false] do
         res_conn = get(conn, "#{base_uri}?local=#{local}")
 
-        assert json_response(res_conn, :unauthorized) == error_response
+        assert json_response_and_validate_schema(res_conn, :unauthorized) == error_response
       end
 
       ensure_authenticated_access(base_uri)
@@ -957,7 +1018,7 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do
       for local <- [true, false] do
         res_conn = get(conn, "#{base_uri}?local=#{local}")
 
-        assert json_response(res_conn, :unauthorized) == error_response
+        assert json_response_and_validate_schema(res_conn, :unauthorized) == error_response
       end
 
       ensure_authenticated_access(base_uri)
@@ -969,31 +1030,83 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do
       clear_config([:restrict_unauthenticated, :timelines, :federated], true)
 
       res_conn = get(conn, "#{base_uri}?local=true")
-      assert length(json_response(res_conn, 200)) == 1
+      assert length(json_response_and_validate_schema(res_conn, 200)) == 1
 
       res_conn = get(conn, "#{base_uri}?local=false")
-      assert json_response(res_conn, :unauthorized) == error_response
+      assert json_response_and_validate_schema(res_conn, :unauthorized) == error_response
 
       ensure_authenticated_access(base_uri)
     end
 
-    test "with `%{local: true, federated: false}`, forbids unauthenticated access to public timeline" <>
-           "(but not to local public activities which are delivered as part of federated timeline)",
+    test "with `%{local: true, federated: false}`, forbids unauthenticated access to public timeline",
          %{conn: conn, base_uri: base_uri, error_response: error_response} do
+      # (but not to local public activities which are delivered as part of federated timeline)
       clear_config([:restrict_unauthenticated, :timelines, :local], true)
       clear_config([:restrict_unauthenticated, :timelines, :federated], false)
 
       res_conn = get(conn, "#{base_uri}?local=true")
-      assert json_response(res_conn, :unauthorized) == error_response
+      assert json_response_and_validate_schema(res_conn, :unauthorized) == error_response
 
       # Note: local activities get delivered as part of federated timeline
       res_conn = get(conn, "#{base_uri}?local=false")
-      assert length(json_response(res_conn, 200)) == 2
+      assert length(json_response_and_validate_schema(res_conn, 200)) == 2
 
       ensure_authenticated_access(base_uri)
     end
   end
 
+  describe "bubble" do
+    test "filtering" do
+      %{conn: conn, user: user} = oauth_access(["read:statuses"])
+      clear_config([:instance, :local_bubble], [])
+      # our endpoint host has a port in it so let's set the AP ID
+      local_user = insert(:user, %{ap_id: "https://localhost/users/user"})
+      remote_user = insert(:user, %{ap_id: "https://example.com/users/remote_user"})
+      {:ok, user, local_user} = User.follow(user, local_user)
+      {:ok, _user, remote_user} = User.follow(user, remote_user)
+
+      {:ok, local_activity} = CommonAPI.post(local_user, %{status: "Status"})
+      remote_activity = create_remote_activity(remote_user)
+
+      # If nothing, only include ours
+      clear_config([:instance, :local_bubble], [])
+
+      one_instance =
+        conn
+        |> get("/api/v1/timelines/bubble")
+        |> json_response_and_validate_schema(200)
+        |> Enum.map(& &1["id"])
+
+      assert local_activity.id in one_instance
+
+      # If we have others, also include theirs
+      clear_config([:instance, :local_bubble], ["example.com"])
+
+      two_instances =
+        conn
+        |> get("/api/v1/timelines/bubble")
+        |> json_response_and_validate_schema(200)
+        |> Enum.map(& &1["id"])
+
+      assert local_activity.id in two_instances
+      assert remote_activity.id in two_instances
+    end
+
+    test "restrict_unauthenticated with bubble timeline", %{conn: conn} do
+      clear_config([:restrict_unauthenticated, :timelines, :bubble], true)
+
+      conn
+      |> get("/api/v1/timelines/bubble")
+      |> json_response_and_validate_schema(:unauthorized)
+
+      clear_config([:restrict_unauthenticated, :timelines, :bubble], false)
+
+      conn
+      |> get("/api/v1/timelines/bubble")
+      |> json_response_and_validate_schema(200)
+    end
+  end
+
   defp create_remote_activity(user) do
     obj =
       insert(:note, %{