defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do
use Pleroma.Web.ConnCase
import Pleroma.Factory
- alias Pleroma.Web.ActivityPub.UserView
- alias Pleroma.Web.ActivityPub.ObjectView
- alias Pleroma.Object
- alias Pleroma.Repo
alias Pleroma.Activity
- alias Pleroma.User
alias Pleroma.Instances
+ alias Pleroma.Object
+ alias Pleroma.User
+ alias Pleroma.Web.ActivityPub.ObjectView
+ alias Pleroma.Web.ActivityPub.UserView
+ alias Pleroma.Web.ActivityPub.Utils
setup_all do
Tesla.Mock.mock_global(fn env -> apply(HttpRequestMock, :request, [env]) end)
end
describe "/users/:nickname" do
- test "it returns a json representation of the user", %{conn: conn} do
+ test "it returns a json representation of the user with accept application/json", %{
+ conn: conn
+ } do
+ user = insert(:user)
+
+ conn =
+ conn
+ |> put_req_header("accept", "application/json")
+ |> get("/users/#{user.nickname}")
+
+ user = User.get_cached_by_id(user.id)
+
+ assert json_response(conn, 200) == UserView.render("user.json", %{user: user})
+ end
+
+ test "it returns a json representation of the user with accept application/activity+json", %{
+ conn: conn
+ } do
user = insert(:user)
conn =
|> put_req_header("accept", "application/activity+json")
|> get("/users/#{user.nickname}")
- user = Repo.get(User, user.id)
+ user = User.get_cached_by_id(user.id)
+
+ assert json_response(conn, 200) == UserView.render("user.json", %{user: user})
+ end
+
+ test "it returns a json representation of the user with accept application/ld+json", %{
+ conn: conn
+ } do
+ user = insert(:user)
+
+ conn =
+ conn
+ |> put_req_header(
+ "accept",
+ "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\""
+ )
+ |> get("/users/#{user.nickname}")
+
+ user = User.get_cached_by_id(user.id)
assert json_response(conn, 200) == UserView.render("user.json", %{user: user})
end
end
describe "/object/:uuid" do
- test "it returns a json representation of the object", %{conn: conn} do
+ test "it returns a json representation of the object with accept application/json", %{
+ conn: conn
+ } do
+ note = insert(:note)
+ uuid = String.split(note.data["id"], "/") |> List.last()
+
+ conn =
+ conn
+ |> put_req_header("accept", "application/json")
+ |> get("/objects/#{uuid}")
+
+ assert json_response(conn, 200) == ObjectView.render("object.json", %{object: note})
+ end
+
+ test "it returns a json representation of the object with accept application/activity+json",
+ %{conn: conn} do
note = insert(:note)
uuid = String.split(note.data["id"], "/") |> List.last()
assert json_response(conn, 200) == ObjectView.render("object.json", %{object: note})
end
+ test "it returns a json representation of the object with accept application/ld+json", %{
+ conn: conn
+ } do
+ note = insert(:note)
+ uuid = String.split(note.data["id"], "/") |> List.last()
+
+ conn =
+ conn
+ |> put_req_header(
+ "accept",
+ "application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\""
+ )
+ |> get("/objects/#{uuid}")
+
+ assert json_response(conn, 200) == ObjectView.render("object.json", %{object: note})
+ end
+
test "it returns 404 for non-public messages", %{conn: conn} do
note = insert(:direct_note)
uuid = String.split(note.data["id"], "/") |> List.last()
end
describe "/users/:nickname/inbox" do
- test "it inserts an incoming activity into the database", %{conn: conn} do
- user = insert(:user)
-
+ setup do
data =
File.read!("test/fixtures/mastodon-post-activity.json")
|> Poison.decode!()
- |> Map.put("bcc", [user.ap_id])
+
+ [data: data]
+ end
+
+ test "it inserts an incoming activity into the database", %{conn: conn, data: data} do
+ user = insert(:user)
+ data = Map.put(data, "bcc", [user.ap_id])
conn =
conn
assert Activity.get_by_ap_id(data["id"])
end
+ test "it accepts messages from actors that are followed by the user", %{
+ conn: conn,
+ data: data
+ } do
+ recipient = insert(:user)
+ actor = insert(:user, %{ap_id: "http://mastodon.example.org/users/actor"})
+
+ {:ok, recipient} = User.follow(recipient, actor)
+
+ object =
+ data["object"]
+ |> Map.put("attributedTo", actor.ap_id)
+
+ data =
+ data
+ |> Map.put("actor", actor.ap_id)
+ |> Map.put("object", object)
+
+ conn =
+ conn
+ |> assign(:valid_signature, true)
+ |> put_req_header("content-type", "application/activity+json")
+ |> post("/users/#{recipient.nickname}/inbox", data)
+
+ assert "ok" == json_response(conn, 200)
+ :timer.sleep(500)
+ assert Activity.get_by_ap_id(data["id"])
+ end
+
test "it rejects reads from other users", %{conn: conn} do
user = insert(:user)
otheruser = insert(:user)
assert response(conn, 200) =~ note_activity.data["object"]["content"]
end
- test "it clears `unreachable` federation status of the sender", %{conn: conn} do
+ test "it clears `unreachable` federation status of the sender", %{conn: conn, data: data} do
user = insert(:user)
-
- data =
- File.read!("test/fixtures/mastodon-post-activity.json")
- |> Poison.decode!()
- |> Map.put("bcc", [user.ap_id])
+ data = Map.put(data, "bcc", [user.ap_id])
sender_host = URI.parse(data["actor"]).host
Instances.set_consistently_unreachable(sender_host)
assert "ok" == json_response(conn, 200)
assert Instances.reachable?(sender_host)
end
+
+ test "it removes all follower collections but actor's", %{conn: conn} do
+ [actor, recipient] = insert_pair(:user)
+
+ data =
+ File.read!("test/fixtures/activitypub-client-post-activity.json")
+ |> Poison.decode!()
+
+ object = Map.put(data["object"], "attributedTo", actor.ap_id)
+
+ data =
+ data
+ |> Map.put("id", Utils.generate_object_id())
+ |> Map.put("actor", actor.ap_id)
+ |> Map.put("object", object)
+ |> Map.put("cc", [
+ recipient.follower_address,
+ actor.follower_address
+ ])
+ |> Map.put("to", [
+ recipient.ap_id,
+ recipient.follower_address,
+ "https://www.w3.org/ns/activitystreams#Public"
+ ])
+
+ conn
+ |> assign(:valid_signature, true)
+ |> put_req_header("content-type", "application/activity+json")
+ |> post("/users/#{recipient.nickname}/inbox", data)
+ |> json_response(200)
+
+ activity = Activity.get_by_ap_id(data["id"])
+
+ assert activity.id
+ assert actor.follower_address in activity.recipients
+ assert actor.follower_address in activity.data["cc"]
+
+ refute recipient.follower_address in activity.recipients
+ refute recipient.follower_address in activity.data["cc"]
+ refute recipient.follower_address in activity.data["to"]
+ end
end
describe "/users/:nickname/outbox" do
+ test "it will not bomb when there is no activity", %{conn: conn} do
+ user = insert(:user)
+
+ conn =
+ conn
+ |> put_req_header("accept", "application/activity+json")
+ |> get("/users/#{user.nickname}/outbox")
+
+ result = json_response(conn, 200)
+ assert user.ap_id <> "/outbox" == result["id"]
+ end
+
test "it returns a note activity in a collection", %{conn: conn} do
note_activity = insert(:note_activity)
user = User.get_cached_by_ap_id(note_activity.data["actor"])
user = insert(:user)
Enum.each(1..15, fn _ ->
- user = Repo.get(User, user.id)
+ user = User.get_cached_by_id(user.id)
other_user = insert(:user)
User.follow(user, other_user)
end)