X-Git-Url: http://git.squeep.com/?a=blobdiff_plain;f=test%2Fweb%2Fmastodon_api%2Fcontrollers%2Ftimeline_controller_test.exs;h=8a70cfd64bdd02c67ae751b89e33bb492c82d9c1;hb=3f9263fb16ad519d2dd45106549a8ba42b68fc1f;hp=f8b9289f37cb04c7d893e667ea3d8d7b152a9efd;hpb=d15aa9d9503e59b3cd0731394855781f435ec63c;p=akkoma diff --git a/test/web/mastodon_api/controllers/timeline_controller_test.exs b/test/web/mastodon_api/controllers/timeline_controller_test.exs index f8b9289f3..8a70cfd64 100644 --- a/test/web/mastodon_api/controllers/timeline_controller_test.exs +++ b/test/web/mastodon_api/controllers/timeline_controller_test.exs @@ -20,12 +20,10 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do describe "home" do setup do: oauth_access(["read:statuses"]) - test "does NOT render account/pleroma/relationship if this is disabled by default", %{ + test "does NOT embed account/pleroma/relationship in statuses", %{ user: user, conn: conn } do - clear_config([:extensions, :output_relationships_in_statuses_by_default], false) - other_user = insert(:user) {:ok, _} = CommonAPI.post(other_user, %{status: "hi @#{user.nickname}"}) @@ -41,72 +39,6 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do end) end - test "the home timeline", %{user: user, conn: conn} do - uri = "/api/v1/timelines/home?with_relationships=1" - - following = insert(:user, nickname: "followed") - third_user = insert(:user, nickname: "repeated") - - {:ok, _activity} = CommonAPI.post(following, %{status: "post"}) - {:ok, activity} = CommonAPI.post(third_user, %{status: "repeated post"}) - {:ok, _, _} = CommonAPI.repeat(activity.id, following) - - ret_conn = get(conn, uri) - - assert Enum.empty?(json_response_and_validate_schema(ret_conn, :ok)) - - {:ok, _user} = User.follow(user, following) - - ret_conn = get(conn, uri) - - assert [ - %{ - "reblog" => %{ - "content" => "repeated post", - "account" => %{ - "pleroma" => %{ - "relationship" => %{"following" => false, "followed_by" => false} - } - } - }, - "account" => %{"pleroma" => %{"relationship" => %{"following" => true}}} - }, - %{ - "content" => "post", - "account" => %{ - "acct" => "followed", - "pleroma" => %{"relationship" => %{"following" => true}} - } - } - ] = json_response_and_validate_schema(ret_conn, :ok) - - {:ok, _user} = User.follow(third_user, user) - - ret_conn = get(conn, uri) - - assert [ - %{ - "reblog" => %{ - "content" => "repeated post", - "account" => %{ - "acct" => "repeated", - "pleroma" => %{ - "relationship" => %{"following" => false, "followed_by" => true} - } - } - }, - "account" => %{"pleroma" => %{"relationship" => %{"following" => true}}} - }, - %{ - "content" => "post", - "account" => %{ - "acct" => "followed", - "pleroma" => %{"relationship" => %{"following" => true}} - } - } - ] = json_response_and_validate_schema(ret_conn, :ok) - end - test "the home timeline when the direct messages are excluded", %{user: user, conn: conn} do {:ok, public_activity} = CommonAPI.post(user, %{status: ".", visibility: "public"}) {:ok, direct_activity} = CommonAPI.post(user, %{status: ".", visibility: "direct"}) @@ -128,9 +60,9 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do describe "public" do @tag capture_log: true test "the public timeline", %{conn: conn} do - following = insert(:user) + user = insert(:user) - {:ok, _activity} = CommonAPI.post(following, %{status: "test"}) + {:ok, activity} = CommonAPI.post(user, %{status: "test"}) _activity = insert(:note_activity, local: false) @@ -145,6 +77,13 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do conn = get(build_conn(), "/api/v1/timelines/public?local=1") assert [%{"content" => "test"}] = json_response_and_validate_schema(conn, :ok) + + # does not contain repeats + {:ok, _} = CommonAPI.repeat(activity.id, user) + + conn = get(build_conn(), "/api/v1/timelines/public?local=true") + + assert [_] = json_response_and_validate_schema(conn, :ok) end test "the public timeline includes only public statuses for an authenticated user" do @@ -158,6 +97,69 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do res_conn = get(conn, "/api/v1/timelines/public") assert length(json_response_and_validate_schema(res_conn, 200)) == 1 end + + test "doesn't return replies if follower is posting with blocked user" do + %{conn: conn, user: blocker} = oauth_access(["read:statuses"]) + [blockee, friend] = insert_list(2, :user) + {:ok, blocker} = User.follow(blocker, friend) + {:ok, _} = User.block(blocker, blockee) + + conn = assign(conn, :user, blocker) + + {:ok, %{id: activity_id} = activity} = CommonAPI.post(friend, %{status: "hey!"}) + + {:ok, reply_from_blockee} = + CommonAPI.post(blockee, %{status: "heya", in_reply_to_status_id: activity}) + + {:ok, _reply_from_friend} = + CommonAPI.post(friend, %{status: "status", in_reply_to_status_id: reply_from_blockee}) + + # Still shows replies from yourself + {:ok, %{id: reply_from_me}} = + CommonAPI.post(blocker, %{status: "status", in_reply_to_status_id: reply_from_blockee}) + + response = + get(conn, "/api/v1/timelines/public") + |> json_response_and_validate_schema(200) + + assert length(response) == 2 + [%{"id" => ^reply_from_me}, %{"id" => ^activity_id}] = response + end + + test "doesn't return replies if follow is posting with users from blocked domain" do + %{conn: conn, user: blocker} = oauth_access(["read:statuses"]) + friend = insert(:user) + blockee = insert(:user, ap_id: "https://example.com/users/blocked") + {:ok, blocker} = User.follow(blocker, friend) + {:ok, blocker} = User.block_domain(blocker, "example.com") + + conn = assign(conn, :user, blocker) + + {:ok, %{id: activity_id} = activity} = CommonAPI.post(friend, %{status: "hey!"}) + + {:ok, reply_from_blockee} = + CommonAPI.post(blockee, %{status: "heya", in_reply_to_status_id: activity}) + + {:ok, _reply_from_friend} = + CommonAPI.post(friend, %{status: "status", in_reply_to_status_id: reply_from_blockee}) + + res_conn = get(conn, "/api/v1/timelines/public") + + activities = json_response_and_validate_schema(res_conn, 200) + [%{"id" => ^activity_id}] = activities + end + + test "can be filtered by instance", %{conn: conn} do + user = insert(:user, ap_id: "https://lain.com/users/lain") + insert(:note_activity, local: false) + insert(:note_activity, local: false) + + {:ok, _} = CommonAPI.post(user, %{status: "test"}) + + conn = get(conn, "/api/v1/timelines/public?instance=lain.com") + + assert length(json_response_and_validate_schema(conn, :ok)) == 1 + end end defp local_and_remote_activities do @@ -351,6 +353,46 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do describe "list" do setup do: oauth_access(["read:lists"]) + test "does not contain retoots", %{user: user, conn: conn} do + other_user = insert(:user) + {:ok, activity_one} = CommonAPI.post(user, %{status: "Marisa is cute."}) + {:ok, activity_two} = CommonAPI.post(other_user, %{status: "Marisa is stupid."}) + {:ok, _} = CommonAPI.repeat(activity_one.id, other_user) + + {:ok, list} = Pleroma.List.create("name", user) + {:ok, list} = Pleroma.List.follow(list, other_user) + + conn = get(conn, "/api/v1/timelines/list/#{list.id}") + + assert [%{"id" => id}] = json_response_and_validate_schema(conn, :ok) + + assert id == to_string(activity_two.id) + end + + test "works with pagination", %{user: user, conn: conn} do + other_user = insert(:user) + {:ok, list} = Pleroma.List.create("name", user) + {:ok, list} = Pleroma.List.follow(list, other_user) + + Enum.each(1..30, fn i -> + CommonAPI.post(other_user, %{status: "post number #{i}"}) + end) + + res = + get(conn, "/api/v1/timelines/list/#{list.id}?limit=1") + |> json_response_and_validate_schema(:ok) + + assert length(res) == 1 + + [first] = res + + res = + get(conn, "/api/v1/timelines/list/#{list.id}?max_id=#{first["id"]}&limit=30") + |> json_response_and_validate_schema(:ok) + + assert length(res) == 29 + end + test "list timeline", %{user: user, conn: conn} do other_user = insert(:user) {:ok, _activity_one} = CommonAPI.post(user, %{status: "Marisa is cute."}) @@ -436,4 +478,95 @@ defmodule Pleroma.Web.MastodonAPI.TimelineControllerTest do assert [status_none] == json_response_and_validate_schema(all_test, :ok) end end + + describe "hashtag timeline handling of :restrict_unauthenticated setting" do + setup do + user = insert(:user) + {:ok, activity1} = CommonAPI.post(user, %{status: "test #tag1"}) + {:ok, _activity2} = CommonAPI.post(user, %{status: "test #tag1"}) + + activity1 + |> Ecto.Changeset.change(%{local: false}) + |> Pleroma.Repo.update() + + base_uri = "/api/v1/timelines/tag/tag1" + error_response = %{"error" => "authorization required for timeline view"} + + %{base_uri: base_uri, error_response: error_response} + end + + defp ensure_authenticated_access(base_uri) 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 + + res_conn = get(auth_conn, "#{base_uri}?local=false") + assert length(json_response(res_conn, 200)) == 2 + end + + test "with default settings on private instances, returns 403 for unauthenticated users", %{ + conn: conn, + base_uri: base_uri, + error_response: error_response + } do + clear_config([:instance, :public], false) + clear_config([:restrict_unauthenticated, :timelines]) + + for local <- [true, false] do + res_conn = get(conn, "#{base_uri}?local=#{local}") + + assert json_response(res_conn, :unauthorized) == error_response + end + + ensure_authenticated_access(base_uri) + end + + test "with `%{local: true, federated: true}`, returns 403 for unauthenticated users", %{ + conn: conn, + base_uri: base_uri, + error_response: error_response + } do + clear_config([:restrict_unauthenticated, :timelines, :local], true) + clear_config([:restrict_unauthenticated, :timelines, :federated], true) + + for local <- [true, false] do + res_conn = get(conn, "#{base_uri}?local=#{local}") + + assert json_response(res_conn, :unauthorized) == error_response + end + + ensure_authenticated_access(base_uri) + end + + test "with `%{local: false, federated: true}`, forbids unauthenticated access to federated timeline", + %{conn: conn, base_uri: base_uri, error_response: error_response} do + clear_config([:restrict_unauthenticated, :timelines, :local], false) + clear_config([:restrict_unauthenticated, :timelines, :federated], true) + + res_conn = get(conn, "#{base_uri}?local=true") + assert length(json_response(res_conn, 200)) == 1 + + res_conn = get(conn, "#{base_uri}?local=false") + assert json_response(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)", + %{conn: conn, base_uri: base_uri, error_response: error_response} do + 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 + + # 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 + + ensure_authenticated_access(base_uri) + end + end end