X-Git-Url: http://git.squeep.com/?a=blobdiff_plain;f=test%2Fweb%2Fmastodon_api%2Fmastodon_api_controller_test.exs;h=d1812457dd27b9dcc899e8dc7d404c8401d0b0cb;hb=bee6acd51dc4e84e44caecf9d123dfff2f640a38;hp=93b29dfaef8631567e4364f85f5b80a35e11b054;hpb=baf66caefd0e8d483ed6feca768b6ad98ab55260;p=akkoma diff --git a/test/web/mastodon_api/mastodon_api_controller_test.exs b/test/web/mastodon_api/mastodon_api_controller_test.exs index 93b29dfae..0136acf8c 100644 --- a/test/web/mastodon_api/mastodon_api_controller_test.exs +++ b/test/web/mastodon_api/mastodon_api_controller_test.exs @@ -1,11 +1,23 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2018 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do use Pleroma.Web.ConnCase alias Pleroma.Web.TwitterAPI.TwitterAPI - alias Pleroma.{Repo, User, Activity, Notification} + alias Pleroma.{Repo, User, Object, Activity, Notification} alias Pleroma.Web.{OStatus, CommonAPI} - + alias Pleroma.Web.ActivityPub.ActivityPub + alias Pleroma.Web.MastodonAPI.FilterView 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) @@ -13,17 +25,19 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do {:ok, _activity} = TwitterAPI.create_status(following, %{"status" => "test"}) - conn = conn - |> assign(:user, user) - |> get("/api/v1/timelines/home") + conn = + conn + |> assign(:user, user) + |> get("/api/v1/timelines/home") assert length(json_response(conn, 200)) == 0 {:ok, user} = User.follow(user, following) - conn = build_conn() - |> assign(:user, user) - |> get("/api/v1/timelines/home") + conn = + build_conn() + |> assign(:user, user) + |> get("/api/v1/timelines/home") assert [%{"content" => "test"}] = json_response(conn, 200) end @@ -31,55 +45,186 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do test "the public timeline", %{conn: conn} do following = insert(:user) - {:ok, _activity} = TwitterAPI.create_status(following, %{"status" => "test"}) - {:ok, [_activity]} = OStatus.fetch_activity_from_url("https://shitposter.club/notice/2827873") + capture_log(fn -> + {:ok, _activity} = TwitterAPI.create_status(following, %{"status" => "test"}) - conn = conn - |> get("/api/v1/timelines/public", %{"local" => "False"}) + {:ok, [_activity]} = + OStatus.fetch_activity_from_url("https://shitposter.club/notice/2827873") - assert length(json_response(conn, 200)) == 2 + conn = + conn + |> get("/api/v1/timelines/public", %{"local" => "False"}) - conn = build_conn() - |> get("/api/v1/timelines/public", %{"local" => "True"}) + assert length(json_response(conn, 200)) == 2 - assert [%{"content" => "test"}] = json_response(conn, 200) + conn = + build_conn() + |> get("/api/v1/timelines/public", %{"local" => "True"}) - conn = build_conn() - |> get("/api/v1/timelines/public", %{"local" => "1"}) + assert [%{"content" => "test"}] = json_response(conn, 200) - assert [%{"content" => "test"}] = json_response(conn, 200) + conn = + build_conn() + |> get("/api/v1/timelines/public", %{"local" => "1"}) + + assert [%{"content" => "test"}] = json_response(conn, 200) + end) end test "posting a status", %{conn: conn} do user = insert(:user) - conn = conn - |> assign(:user, user) - |> post("/api/v1/statuses", %{"status" => "cofe", "spoiler_text" => "2hu", "sensitive" => "false"}) + idempotency_key = "Pikachu rocks!" + + conn_one = + conn + |> assign(:user, user) + |> put_req_header("idempotency-key", idempotency_key) + |> post("/api/v1/statuses", %{ + "status" => "cofe", + "spoiler_text" => "2hu", + "sensitive" => "false" + }) + + {:ok, ttl} = Cachex.ttl(:idempotency_cache, idempotency_key) + # Six hours + assert ttl > :timer.seconds(6 * 60 * 60 - 1) + + assert %{"content" => "cofe", "id" => id, "spoiler_text" => "2hu", "sensitive" => false} = + json_response(conn_one, 200) - assert %{"content" => "cofe", "id" => id, "spoiler_text" => "2hu", "sensitive" => false} = json_response(conn, 200) assert Repo.get(Activity, id) + + conn_two = + conn + |> assign(:user, user) + |> put_req_header("idempotency-key", idempotency_key) + |> post("/api/v1/statuses", %{ + "status" => "cofe", + "spoiler_text" => "2hu", + "sensitive" => "false" + }) + + assert %{"id" => second_id} = json_response(conn_two, 200) + + assert id == second_id + + conn_three = + conn + |> assign(:user, user) + |> post("/api/v1/statuses", %{ + "status" => "cofe", + "spoiler_text" => "2hu", + "sensitive" => "false" + }) + + assert %{"id" => third_id} = json_response(conn_three, 200) + + refute id == third_id end test "posting a sensitive status", %{conn: conn} do user = insert(:user) - conn = conn - |> assign(:user, user) - |> post("/api/v1/statuses", %{"status" => "cofe", "sensitive" => true}) + conn = + conn + |> assign(:user, user) + |> post("/api/v1/statuses", %{"status" => "cofe", "sensitive" => true}) assert %{"content" => "cofe", "id" => id, "sensitive" => true} = json_response(conn, 200) assert Repo.get(Activity, id) end + test "posting a direct status", %{conn: conn} do + user1 = insert(:user) + user2 = insert(:user) + content = "direct cofe @#{user2.nickname}" + + conn = + conn + |> assign(:user, user1) + |> post("api/v1/statuses", %{"status" => content, "visibility" => "direct"}) + + assert %{"id" => id, "visibility" => "direct"} = json_response(conn, 200) + assert activity = Repo.get(Activity, id) + assert activity.recipients == [user2.ap_id] + assert activity.data["to"] == [user2.ap_id] + assert activity.data["cc"] == [] + end + + test "direct timeline", %{conn: conn} do + user_one = insert(:user) + user_two = insert(:user) + + {:ok, user_two} = User.follow(user_two, user_one) + + {:ok, direct} = + CommonAPI.post(user_one, %{ + "status" => "Hi @#{user_two.nickname}!", + "visibility" => "direct" + }) + + {:ok, _follower_only} = + CommonAPI.post(user_one, %{ + "status" => "Hi @#{user_two.nickname}!", + "visibility" => "private" + }) + + # Only direct should be visible here + res_conn = + conn + |> assign(:user, user_two) + |> get("api/v1/timelines/direct") + + [status] = json_response(res_conn, 200) + + assert %{"visibility" => "direct"} = status + assert status["url"] != direct.data["id"] + + # Both should be visible here + res_conn = + conn + |> assign(:user, user_two) + |> 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 user = insert(:user) {:ok, replied_to} = TwitterAPI.create_status(user, %{"status" => "cofe"}) - conn = conn - |> assign(:user, user) - |> post("/api/v1/statuses", %{"status" => "xD", "in_reply_to_id" => replied_to.id}) + conn = + conn + |> assign(:user, user) + |> post("/api/v1/statuses", %{"status" => "xD", "in_reply_to_id" => replied_to.id}) assert %{"content" => "xD", "id" => id} = json_response(conn, 200) @@ -89,22 +234,51 @@ 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) - conn = conn - |> assign(:user, user) - |> get("/api/v1/accounts/verify_credentials") + conn = + conn + |> 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 test "get a status", %{conn: conn} do activity = insert(:note_activity) - conn = conn - |> get("/api/v1/statuses/#{activity.id}") + conn = + conn + |> get("/api/v1/statuses/#{activity.id}") assert %{"id" => id} = json_response(conn, 200) assert id == to_string(activity.id) @@ -115,22 +289,24 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do activity = insert(:note_activity) author = User.get_by_ap_id(activity.data["actor"]) - conn = conn - |> assign(:user, author) - |> delete("/api/v1/statuses/#{activity.id}") + conn = + conn + |> assign(:user, author) + |> delete("/api/v1/statuses/#{activity.id}") assert %{} = json_response(conn, 200) - assert Repo.get(Activity, activity.id) == nil + refute Repo.get(Activity, activity.id) end test "when you didn't create it", %{conn: conn} do activity = insert(:note_activity) user = insert(:user) - conn = conn - |> assign(:user, user) - |> delete("/api/v1/statuses/#{activity.id}") + conn = + conn + |> assign(:user, user) + |> delete("/api/v1/statuses/#{activity.id}") assert %{"error" => _} = json_response(conn, 403) @@ -138,19 +314,294 @@ 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) + + response = + conn + |> assign(:user, user) + |> get("/api/v1/filters") + |> json_response(200) + + assert response == + render_json( + FilterView, + "filters.json", + filters: [filter_two, filter_one] + ) + 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) + + conn = + conn + |> assign(:user, user) + |> post("/api/v1/lists", %{"title" => "cuties"}) + + assert %{"title" => title} = json_response(conn, 200) + assert title == "cuties" + end + + test "adding users to a list", %{conn: conn} do + user = insert(:user) + other_user = insert(:user) + {:ok, list} = Pleroma.List.create("name", user) + + conn = + conn + |> assign(:user, user) + |> post("/api/v1/lists/#{list.id}/accounts", %{"account_ids" => [other_user.id]}) + + assert %{} == json_response(conn, 200) + %Pleroma.List{following: following} = Pleroma.List.get(list.id, user) + assert following == [other_user.follower_address] + end + + test "removing users from a list", %{conn: conn} do + user = insert(:user) + other_user = insert(:user) + third_user = insert(:user) + {:ok, list} = Pleroma.List.create("name", user) + {:ok, list} = Pleroma.List.follow(list, other_user) + {:ok, list} = Pleroma.List.follow(list, third_user) + + conn = + conn + |> assign(:user, user) + |> delete("/api/v1/lists/#{list.id}/accounts", %{"account_ids" => [other_user.id]}) + + assert %{} == json_response(conn, 200) + %Pleroma.List{following: following} = Pleroma.List.get(list.id, user) + assert following == [third_user.follower_address] + end + + test "listing users in a list", %{conn: conn} do + user = insert(:user) + other_user = insert(:user) + {:ok, list} = Pleroma.List.create("name", user) + {:ok, list} = Pleroma.List.follow(list, other_user) + + conn = + conn + |> assign(:user, user) + |> get("/api/v1/lists/#{list.id}/accounts", %{"account_ids" => [other_user.id]}) + + assert [%{"id" => id}] = json_response(conn, 200) + assert id == to_string(other_user.id) + end + + test "retrieving a list", %{conn: conn} do + user = insert(:user) + {:ok, list} = Pleroma.List.create("name", user) + + conn = + conn + |> assign(:user, user) + |> get("/api/v1/lists/#{list.id}") + + assert %{"id" => id} = json_response(conn, 200) + assert id == to_string(list.id) + end + + test "renaming a list", %{conn: conn} do + user = insert(:user) + {:ok, list} = Pleroma.List.create("name", user) + + conn = + conn + |> assign(:user, user) + |> put("/api/v1/lists/#{list.id}", %{"title" => "newname"}) + + assert %{"title" => name} = json_response(conn, 200) + assert name == "newname" + end + + test "deleting a list", %{conn: conn} do + user = insert(:user) + {:ok, list} = Pleroma.List.create("name", user) + + conn = + conn + |> assign(:user, user) + |> delete("/api/v1/lists/#{list.id}") + + assert %{} = json_response(conn, 200) + assert is_nil(Repo.get(Pleroma.List, list.id)) + end + + test "list timeline", %{conn: conn} do + user = insert(:user) + other_user = insert(:user) + {:ok, _activity_one} = TwitterAPI.create_status(user, %{"status" => "Marisa is cute."}) + {:ok, activity_two} = TwitterAPI.create_status(other_user, %{"status" => "Marisa is cute."}) + {: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_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 test "list of notifications", %{conn: conn} do user = insert(:user) other_user = insert(:user) - {:ok, activity} = TwitterAPI.create_status(other_user, %{"status" => "hi @#{user.nickname}"}) - {:ok, [notification]} = Notification.create_notifications(activity) + {:ok, activity} = + TwitterAPI.create_status(other_user, %{"status" => "hi @#{user.nickname}"}) - conn = conn - |> assign(:user, user) - |> get("/api/v1/notifications") + {:ok, [_notification]} = Notification.create_notifications(activity) + + conn = + conn + |> assign(:user, user) + |> get("/api/v1/notifications") + + expected_response = + "hi @#{user.nickname}" - expected_response = "hi @#{user.nickname}" assert [%{"status" => %{"content" => response}} | _rest] = json_response(conn, 200) assert response == expected_response end @@ -159,14 +610,19 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do user = insert(:user) other_user = insert(:user) - {:ok, activity} = TwitterAPI.create_status(other_user, %{"status" => "hi @#{user.nickname}"}) + {:ok, activity} = + TwitterAPI.create_status(other_user, %{"status" => "hi @#{user.nickname}"}) + {:ok, [notification]} = Notification.create_notifications(activity) - conn = conn - |> assign(:user, user) - |> get("/api/v1/notifications/#{notification.id}") + conn = + conn + |> assign(:user, user) + |> get("/api/v1/notifications/#{notification.id}") + + expected_response = + "hi @#{user.nickname}" - expected_response = "hi @#{user.nickname}" assert %{"status" => %{"content" => response}} = json_response(conn, 200) assert response == expected_response end @@ -175,12 +631,15 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do user = insert(:user) other_user = insert(:user) - {:ok, activity} = TwitterAPI.create_status(other_user, %{"status" => "hi @#{user.nickname}"}) + {:ok, activity} = + TwitterAPI.create_status(other_user, %{"status" => "hi @#{user.nickname}"}) + {:ok, [notification]} = Notification.create_notifications(activity) - conn = conn - |> assign(:user, user) - |> post("/api/v1/notifications/dismiss", %{"id" => notification.id}) + conn = + conn + |> assign(:user, user) + |> post("/api/v1/notifications/dismiss", %{"id" => notification.id}) assert %{} = json_response(conn, 200) end @@ -189,18 +648,22 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do user = insert(:user) other_user = insert(:user) - {:ok, activity} = TwitterAPI.create_status(other_user, %{"status" => "hi @#{user.nickname}"}) - {:ok, [notification]} = Notification.create_notifications(activity) + {:ok, activity} = + TwitterAPI.create_status(other_user, %{"status" => "hi @#{user.nickname}"}) - conn = conn - |> assign(:user, user) - |> post("/api/v1/notifications/clear") + {:ok, [_notification]} = Notification.create_notifications(activity) + + conn = + conn + |> assign(:user, user) + |> post("/api/v1/notifications/clear") assert %{} = json_response(conn, 200) - conn = build_conn() - |> assign(:user, user) - |> get("/api/v1/notifications") + conn = + build_conn() + |> assign(:user, user) + |> get("/api/v1/notifications") assert all = json_response(conn, 200) assert all == [] @@ -212,11 +675,32 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do activity = insert(:note_activity) user = insert(:user) - conn = conn - |> assign(:user, user) - |> post("/api/v1/statuses/#{activity.id}/reblog") + conn = + conn + |> assign(:user, user) + |> post("/api/v1/statuses/#{activity.id}/reblog") + + assert %{"reblog" => %{"id" => id, "reblogged" => true, "reblogs_count" => 1}} = + json_response(conn, 200) + + assert to_string(activity.id) == id + end + end + + describe "unreblogging" do + test "unreblogs and returns the unreblogged status", %{conn: conn} do + activity = insert(:note_activity) + user = insert(:user) + + {:ok, _, _} = CommonAPI.repeat(activity.id, user) + + conn = + conn + |> assign(:user, user) + |> post("/api/v1/statuses/#{activity.id}/unreblog") + + assert %{"id" => id, "reblogged" => false, "reblogs_count" => 0} = json_response(conn, 200) - assert %{"reblog" => %{"id" => id, "reblogged" => true, "reblogs_count" => 1}} = json_response(conn, 200) assert to_string(activity.id) == id end end @@ -226,13 +710,28 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do activity = insert(:note_activity) user = insert(:user) - conn = conn - |> assign(:user, user) - |> post("/api/v1/statuses/#{activity.id}/favourite") + conn = + conn + |> assign(:user, user) + |> post("/api/v1/statuses/#{activity.id}/favourite") + + assert %{"id" => id, "favourites_count" => 1, "favourited" => true} = + json_response(conn, 200) - assert %{"id" => id, "favourites_count" => 1, "favourited" => true} = json_response(conn, 200) assert to_string(activity.id) == id end + + test "returns 500 for a wrong id", %{conn: conn} do + user = insert(:user) + + resp = + conn + |> assign(:user, user) + |> post("/api/v1/statuses/1/favourite") + |> json_response(500) + + assert resp == "Something went wrong" + end end describe "unfavoriting" do @@ -242,52 +741,125 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do {:ok, _, _} = CommonAPI.favorite(activity.id, user) - conn = conn - |> assign(:user, user) - |> post("/api/v1/statuses/#{activity.id}/unfavourite") + conn = + conn + |> assign(:user, user) + |> post("/api/v1/statuses/#{activity.id}/unfavourite") + + assert %{"id" => id, "favourites_count" => 0, "favourited" => false} = + json_response(conn, 200) - assert %{"id" => id, "favourites_count" => 0, "favourited" => false} = json_response(conn, 200) assert to_string(activity.id) == id end end describe "user timelines" do test "gets a users statuses", %{conn: conn} do - _note = insert(:note_activity) - note_two = insert(:note_activity) + user_one = insert(:user) + user_two = insert(:user) + user_three = insert(:user) - user = User.get_by_ap_id(note_two.data["actor"]) + {:ok, user_three} = User.follow(user_three, user_one) - conn = conn - |> get("/api/v1/accounts/#{user.id}/statuses") + {:ok, activity} = CommonAPI.post(user_one, %{"status" => "HI!!!"}) - assert [%{"id" => id}] = json_response(conn, 200) + {:ok, direct_activity} = + CommonAPI.post(user_one, %{ + "status" => "Hi, @#{user_two.nickname}.", + "visibility" => "direct" + }) + + {:ok, private_activity} = + CommonAPI.post(user_one, %{"status" => "private", "visibility" => "private"}) + + resp = + conn + |> get("/api/v1/accounts/#{user_one.id}/statuses") + + assert [%{"id" => id}] = json_response(resp, 200) + assert id == to_string(activity.id) + + resp = + conn + |> assign(:user, user_two) + |> get("/api/v1/accounts/#{user_one.id}/statuses") + + assert [%{"id" => id_one}, %{"id" => id_two}] = json_response(resp, 200) + assert id_one == to_string(direct_activity.id) + assert id_two == to_string(activity.id) + + resp = + conn + |> assign(:user, user_three) + |> get("/api/v1/accounts/#{user_one.id}/statuses") + + assert [%{"id" => id_one}, %{"id" => id_two}] = json_response(resp, 200) + assert id_one == to_string(private_activity.id) + assert id_two == to_string(activity.id) + end + + test "unimplemented pinned statuses feature", %{conn: conn} do + note = insert(:note_activity) + user = User.get_by_ap_id(note.data["actor"]) - assert id == to_string(note_two.id) + conn = + conn + |> get("/api/v1/accounts/#{user.id}/statuses?pinned=true") + + assert json_response(conn, 200) == [] end test "gets an users media", %{conn: conn} do note = insert(:note_activity) user = User.get_by_ap_id(note.data["actor"]) - file = %Plug.Upload{content_type: "image/jpg", path: Path.absname("test/fixtures/image.jpg"), filename: "an_image.jpg"} - media = TwitterAPI.upload(file, "json") - |> Poison.decode! + file = %Plug.Upload{ + content_type: "image/jpg", + path: Path.absname("test/fixtures/image.jpg"), + filename: "an_image.jpg" + } + + media = + TwitterAPI.upload(file, user, "json") + |> Poison.decode!() - {:ok, image_post} = TwitterAPI.create_status(user, %{"status" => "cofe", "media_ids" => [media["media_id"]]}) + {:ok, image_post} = + TwitterAPI.create_status(user, %{"status" => "cofe", "media_ids" => [media["media_id"]]}) - conn = conn - |> get("/api/v1/accounts/#{user.id}/statuses", %{"only_media" => "true"}) + conn = + conn + |> get("/api/v1/accounts/#{user.id}/statuses", %{"only_media" => "true"}) assert [%{"id" => id}] = json_response(conn, 200) assert id == to_string(image_post.id) - conn = build_conn() - |> get("/api/v1/accounts/#{user.id}/statuses", %{"only_media" => "1"}) + conn = + build_conn() + |> get("/api/v1/accounts/#{user.id}/statuses", %{"only_media" => "1"}) assert [%{"id" => id}] = json_response(conn, 200) assert id == to_string(image_post.id) end + + test "gets a user's statuses without reblogs", %{conn: conn} do + user = insert(:user) + {:ok, post} = CommonAPI.post(user, %{"status" => "HI!!!"}) + {:ok, _, _} = CommonAPI.repeat(post.id, user) + + conn = + conn + |> get("/api/v1/accounts/#{user.id}/statuses", %{"exclude_reblogs" => "true"}) + + assert [%{"id" => id}] = json_response(conn, 200) + assert id == to_string(post.id) + + conn = + conn + |> get("/api/v1/accounts/#{user.id}/statuses", %{"exclude_reblogs" => "1"}) + + assert [%{"id" => id}] = json_response(conn, 200) + assert id == to_string(post.id) + end end describe "user relationships" do @@ -296,9 +868,10 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do other_user = insert(:user) {:ok, user} = User.follow(user, other_user) - conn = conn - |> assign(:user, user) - |> get("/api/v1/accounts/relationships", %{"id" => [other_user.id]}) + conn = + conn + |> assign(:user, user) + |> get("/api/v1/accounts/relationships", %{"id" => [other_user.id]}) assert [relationship] = json_response(conn, 200) @@ -306,47 +879,154 @@ 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) - conn = conn - |> get("/api/v1/accounts/#{user.id}") + conn = + conn + |> get("/api/v1/accounts/#{user.id}") assert %{"id" => id} = json_response(conn, 200) assert id == to_string(user.id) - conn = build_conn() - |> get("/api/v1/accounts/-1") + conn = + build_conn() + |> get("/api/v1/accounts/-1") assert %{"error" => "Can't find user"} = json_response(conn, 404) end test "media upload", %{conn: conn} do - file = %Plug.Upload{content_type: "image/jpg", path: Path.absname("test/fixtures/image.jpg"), filename: "an_image.jpg"} + file = %Plug.Upload{ + content_type: "image/jpg", + path: Path.absname("test/fixtures/image.jpg"), + filename: "an_image.jpg" + } + + desc = "Description of the image" user = insert(:user) - conn = conn - |> assign(:user, user) - |> post("/api/v1/media", %{"file" => file}) + conn = + conn + |> assign(:user, user) + |> post("/api/v1/media", %{"file" => file, "description" => desc}) assert media = json_response(conn, 200) assert media["type"] == "image" + assert media["description"] == desc + assert media["id"] + + object = Repo.get(Object, media["id"]) + assert object.data["actor"] == User.ap_id(user) end test "hashtag timeline", %{conn: conn} do following = insert(:user) - {:ok, activity} = TwitterAPI.create_status(following, %{"status" => "test #2hu"}) - {:ok, [_activity]} = OStatus.fetch_activity_from_url("https://shitposter.club/notice/2827873") + capture_log(fn -> + {:ok, activity} = TwitterAPI.create_status(following, %{"status" => "test #2hu"}) - conn = conn - |> get("/api/v1/timelines/tag/2hu") + {:ok, [_activity]} = + OStatus.fetch_activity_from_url("https://shitposter.club/notice/2827873") - assert [%{"id" => id}] = json_response(conn, 200) + nconn = + conn + |> get("/api/v1/timelines/tag/2hu") - assert id == to_string(activity.id) + 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) end test "getting followers", %{conn: conn} do @@ -354,46 +1034,103 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do other_user = insert(:user) {:ok, user} = User.follow(user, other_user) - conn = conn - |> get("/api/v1/accounts/#{other_user.id}/followers") + conn = + conn + |> get("/api/v1/accounts/#{other_user.id}/followers") assert [%{"id" => id}] = json_response(conn, 200) 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) {:ok, user} = User.follow(user, other_user) - conn = conn - |> get("/api/v1/accounts/#{user.id}/following") + conn = + conn + |> get("/api/v1/accounts/#{user.id}/following") assert [%{"id" => id}] = json_response(conn, 200) 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) - conn = conn - |> assign(:user, user) - |> post("/api/v1/accounts/#{other_user.id}/follow") + conn = + conn + |> assign(:user, user) + |> post("/api/v1/accounts/#{other_user.id}/follow") - assert %{"id" => id, "following" => true} = json_response(conn, 200) + assert %{"id" => _id, "following" => true} = json_response(conn, 200) user = Repo.get(User, user.id) - conn = build_conn() - |> assign(:user, user) - |> post("/api/v1/accounts/#{other_user.id}/unfollow") - assert %{"id" => id, "following" => false} = json_response(conn, 200) + conn = + build_conn() + |> assign(:user, user) + |> post("/api/v1/accounts/#{other_user.id}/unfollow") + + assert %{"id" => _id, "following" => false} = json_response(conn, 200) user = Repo.get(User, user.id) - conn = build_conn() - |> assign(:user, user) - |> post("/api/v1/follows", %{"uri" => other_user.nickname}) + + conn = + build_conn() + |> assign(:user, user) + |> post("/api/v1/follows", %{"uri" => other_user.nickname}) assert %{"id" => id} = json_response(conn, 200) assert id == to_string(other_user.id) @@ -403,18 +1140,21 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do user = insert(:user) other_user = insert(:user) - conn = conn - |> assign(:user, user) - |> post("/api/v1/accounts/#{other_user.id}/block") + conn = + conn + |> assign(:user, user) + |> post("/api/v1/accounts/#{other_user.id}/block") - assert %{"id" => id, "blocking" => true} = json_response(conn, 200) + assert %{"id" => _id, "blocking" => true} = json_response(conn, 200) user = Repo.get(User, user.id) - conn = build_conn() - |> assign(:user, user) - |> post("/api/v1/accounts/#{other_user.id}/unblock") - assert %{"id" => id, "blocking" => false} = json_response(conn, 200) + conn = + build_conn() + |> assign(:user, user) + |> post("/api/v1/accounts/#{other_user.id}/unblock") + + assert %{"id" => _id, "blocking" => false} = json_response(conn, 200) end test "getting a list of blocks", %{conn: conn} do @@ -423,23 +1163,65 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do {:ok, user} = User.block(user, other_user) - conn = conn - |> assign(:user, user) - |> get("/api/v1/blocks") + conn = + conn + |> assign(:user, user) + |> get("/api/v1/blocks") other_user_id = to_string(other_user.id) 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) ["mute", "unmute"] - |> Enum.each(fn(endpoint) -> - conn = build_conn() - |> assign(:user, user) - |> post("/api/v1/accounts/#{other_user.id}/#{endpoint}") + |> Enum.each(fn endpoint -> + conn = + build_conn() + |> assign(:user, user) + |> post("/api/v1/accounts/#{other_user.id}/#{endpoint}") assert %{"id" => id} = json_response(conn, 200) assert id == to_string(other_user.id) @@ -450,10 +1232,11 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do user = insert(:user) ["blocks", "domain_blocks", "mutes", "follow_requests"] - |> Enum.each(fn(endpoint) -> - conn = build_conn() - |> assign(:user, user) - |> get("/api/v1/#{endpoint}") + |> Enum.each(fn endpoint -> + conn = + build_conn() + |> assign(:user, user) + |> get("/api/v1/#{endpoint}") assert [] = json_response(conn, 200) end) @@ -464,12 +1247,26 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do user_two = insert(:user, %{nickname: "shp@shitposter.club"}) user_three = insert(:user, %{nickname: "shp@heldscal.la", name: "I love 2hu"}) - conn = conn - |> assign(:user, user) - |> get("/api/v1/accounts/search", %{"q" => "2hu"}) + results = + conn + |> assign(:user, user) + |> get("/api/v1/accounts/search", %{"q" => "shp"}) + |> json_response(200) - assert [account] = json_response(conn, 200) - assert account["id"] == to_string(user_three.id) + result_ids = for result <- results, do: result["acct"] + + assert user_two.nickname in result_ids + assert user_three.nickname in result_ids + + results = + conn + |> assign(:user, user) + |> get("/api/v1/accounts/search", %{"q" => "2hu"}) + |> json_response(200) + + result_ids = for result <- results, do: result["acct"] + + assert user_three.nickname in result_ids end test "search", %{conn: conn} do @@ -478,14 +1275,22 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do user_three = insert(:user, %{nickname: "shp@heldscal.la", name: "I love 2hu"}) {:ok, activity} = CommonAPI.post(user, %{"status" => "This is about 2hu"}) + + {:ok, _activity} = + CommonAPI.post(user, %{ + "status" => "This is about 2hu, but private", + "visibility" => "private" + }) + {:ok, _} = CommonAPI.post(user_two, %{"status" => "This isn't"}) - conn = conn - |> get("/api/v1/search", %{"q" => "2hu"}) + conn = + conn + |> get("/api/v1/search", %{"q" => "2hu"}) assert results = json_response(conn, 200) - [account] = results["accounts"] + [account | _] = results["accounts"] assert account["id"] == to_string(user_three.id) assert results["hashtags"] == [] @@ -495,17 +1300,22 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do end test "search fetches remote statuses", %{conn: conn} do - conn = conn - |> get("/api/v1/search", %{"q" => "https://shitposter.club/notice/2827873"}) - assert results = json_response(conn, 200) + capture_log(fn -> + conn = + conn + |> get("/api/v1/search", %{"q" => "https://shitposter.club/notice/2827873"}) - [status] = results["statuses"] - assert status["uri"] == "tag:shitposter.club,2017-05-05:noticeId=2827873:objectType=comment" + assert results = json_response(conn, 200) + + [status] = results["statuses"] + assert status["uri"] == "tag:shitposter.club,2017-05-05:noticeId=2827873:objectType=comment" + end) end test "search fetches remote accounts", %{conn: conn} do - conn = conn - |> get("/api/v1/search", %{"q" => "shp@social.heldscal.la", "resolve" => "true"}) + conn = + conn + |> get("/api/v1/search", %{"q" => "shp@social.heldscal.la", "resolve" => "true"}) assert results = json_response(conn, 200) [account] = results["accounts"] @@ -521,65 +1331,97 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do {:ok, _, _} = CommonAPI.favorite(activity.id, user) - conn = conn - |> assign(:user, user) - |> get("/api/v1/favourites") + conn = + conn + |> assign(:user, user) + |> get("/api/v1/favourites") assert [status] = json_response(conn, 200) assert status["id"] == to_string(activity.id) end describe "updating credentials" do - test "updates the user's bio" 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"}) + conn = + conn + |> assign(:user, user) + |> 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 #cofe with @#{user2.nickname}" end - test "updates the user's name" do + test "updates the user's locking status", %{conn: conn} do user = insert(:user) - conn = conn - |> assign(:user, user) - |> patch("/api/v1/accounts/update_credentials", %{"display_name" => "markorepairs"}) + 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 + user = insert(:user) + + conn = + conn + |> assign(:user, user) + |> patch("/api/v1/accounts/update_credentials", %{"display_name" => "markorepairs"}) assert user = json_response(conn, 200) assert user["display_name"] == "markorepairs" end - test "updates the user's avatar" do + test "updates the user's avatar", %{conn: conn} do user = insert(:user) - new_avatar = %Plug.Upload{content_type: "image/jpg", path: Path.absname("test/fixtures/image.jpg"), filename: "an_image.jpg"} + new_avatar = %Plug.Upload{ + content_type: "image/jpg", + path: Path.absname("test/fixtures/image.jpg"), + filename: "an_image.jpg" + } - conn = conn - |> assign(:user, user) - |> patch("/api/v1/accounts/update_credentials", %{"avatar" => new_avatar}) + conn = + conn + |> 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" do + test "updates the user's banner", %{conn: conn} do user = insert(:user) - new_header = %Plug.Upload{content_type: "image/jpg", path: Path.absname("test/fixtures/image.jpg"), filename: "an_image.jpg"} + new_header = %Plug.Upload{ + content_type: "image/jpg", + path: Path.absname("test/fixtures/image.jpg"), + filename: "an_image.jpg" + } - conn = conn - |> assign(:user, user) - |> patch("/api/v1/accounts/update_credentials", %{"header" => new_header}) + conn = + conn + |> 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 - test "get instance information" do + test "get instance information", %{conn: conn} do insert(:user, %{local: true}) user = insert(:user, %{local: true}) insert(:user, %{local: false}) @@ -588,12 +1430,27 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIControllerTest do Pleroma.Stats.update_stats() - conn = conn - |> get("/api/v1/instance") + conn = + conn + |> get("/api/v1/instance") assert result = json_response(conn, 200) assert result["stats"]["user_count"] == 2 assert result["stats"]["status_count"] == 1 end + + test "put settings", %{conn: conn} do + user = insert(:user) + + conn = + conn + |> assign(:user, user) + |> put("/api/web/settings", %{"data" => %{"programming" => "socks"}}) + + assert result = json_response(conn, 200) + + user = User.get_cached_by_ap_id(user.ap_id) + assert user.info.settings == %{"programming" => "socks"} + end end