use Pleroma.DataCase
alias Pleroma.Activity
alias Pleroma.Object
+ alias Pleroma.Object.Fetcher
alias Pleroma.Repo
alias Pleroma.User
alias Pleroma.Web.ActivityPub.ActivityPub
alias Pleroma.Web.ActivityPub.Transmogrifier
- alias Pleroma.Web.ActivityPub.Utils
alias Pleroma.Web.OStatus
alias Pleroma.Web.Websub.WebsubClientSubscription
assert returned_object.data["inReplyToAtomUri"] == "https://shitposter.club/notice/2827873"
end
+ test "it does not crash if the object in inReplyTo can't be fetched" do
+ data =
+ File.read!("test/fixtures/mastodon-post-activity.json")
+ |> Poison.decode!()
+
+ object =
+ data["object"]
+ |> Map.put("inReplyTo", "https://404.site/whatever")
+
+ data =
+ data
+ |> Map.put("object", object)
+
+ {:ok, _returned_activity} = Transmogrifier.handle_incoming(data)
+ end
+
test "it works for incoming notices" do
data = File.read!("test/fixtures/mastodon-post-activity.json") |> Poison.decode!()
assert object["sensitive"] == true
- user = User.get_by_ap_id(object["actor"])
+ user = User.get_cached_by_ap_id(object["actor"])
assert user.info.note_count == 1
end
assert Enum.at(object.data["tag"], 2) == "moo"
end
+ test "it works for incoming questions" do
+ data = File.read!("test/fixtures/mastodon-question-activity.json") |> Poison.decode!()
+
+ {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data)
+
+ object = Object.normalize(activity)
+
+ assert Enum.all?(object.data["oneOf"], fn choice ->
+ choice["name"] in [
+ "Dunno",
+ "Everyone knows that!",
+ "25 char limit is dumb",
+ "I can't even fit a funny"
+ ]
+ end)
+ end
+
+ test "it rewrites Note votes to Answers and increments vote counters on question activities" do
+ user = insert(:user)
+
+ {:ok, activity} =
+ CommonAPI.post(user, %{
+ "status" => "suya...",
+ "poll" => %{"options" => ["suya", "suya.", "suya.."], "expires_in" => 10}
+ })
+
+ object = Object.normalize(activity)
+
+ data =
+ File.read!("test/fixtures/mastodon-vote.json")
+ |> Poison.decode!()
+ |> Kernel.put_in(["to"], user.ap_id)
+ |> Kernel.put_in(["object", "inReplyTo"], object.data["id"])
+ |> Kernel.put_in(["object", "to"], user.ap_id)
+
+ {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data)
+ answer_object = Object.normalize(activity)
+ assert answer_object.data["type"] == "Answer"
+ object = Object.get_by_ap_id(object.data["id"])
+
+ assert Enum.any?(
+ object.data["oneOf"],
+ fn
+ %{"name" => "suya..", "replies" => %{"totalItems" => 1}} -> true
+ _ -> false
+ end
+ )
+ end
+
test "it works for incoming notices with contentMap" do
data =
File.read!("test/fixtures/mastodon-post-activity-contentmap.json") |> Poison.decode!()
data = Map.put(data, "object", object)
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
+ {:ok, %Activity{data: data, local: false} = activity} = Transmogrifier.handle_incoming(data)
assert data["to"] == []
assert data["cc"] == to
- object = data["object"]
-
- assert object["to"] == []
- assert object["cc"] == to
- end
-
- test "it works for incoming follow requests" do
- user = insert(:user)
-
- data =
- File.read!("test/fixtures/mastodon-follow-activity.json")
- |> Poison.decode!()
- |> Map.put("object", user.ap_id)
-
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
-
- assert data["actor"] == "http://mastodon.example.org/users/admin"
- assert data["type"] == "Follow"
- assert data["id"] == "http://mastodon.example.org/users/admin#follows/2"
- assert User.following?(User.get_by_ap_id(data["actor"]), user)
- end
-
- test "it works for incoming follow requests from hubzilla" do
- user = insert(:user)
-
- data =
- File.read!("test/fixtures/hubzilla-follow-activity.json")
- |> Poison.decode!()
- |> Map.put("object", user.ap_id)
- |> Utils.normalize_params()
-
- {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
+ object_data = Object.normalize(activity).data
- assert data["actor"] == "https://hubzilla.example.org/channel/kaniini"
- assert data["type"] == "Follow"
- assert data["id"] == "https://hubzilla.example.org/channel/kaniini#follows/2"
- assert User.following?(User.get_by_ap_id(data["actor"]), user)
+ assert object_data["to"] == []
+ assert object_data["cc"] == to
end
test "it works for incoming likes" do
data =
File.read!("test/fixtures/mastodon-announce.json")
|> Poison.decode!()
- |> Map.put("object", activity.data["object"]["id"])
+ |> Map.put("object", Object.normalize(activity).data["id"])
|> Map.put("to", ["http://mastodon.example.org/users/admin/followers"])
|> Map.put("cc", [])
assert data["object"]["object"] == user.ap_id
assert data["actor"] == "http://mastodon.example.org/users/admin"
- refute User.following?(User.get_by_ap_id(data["actor"]), user)
+ refute User.following?(User.get_cached_by_ap_id(data["actor"]), user)
end
test "it works for incoming blocks" do
assert data["object"] == user.ap_id
assert data["actor"] == "http://mastodon.example.org/users/admin"
- blocker = User.get_by_ap_id(data["actor"])
+ blocker = User.get_cached_by_ap_id(data["actor"])
assert User.blocks?(blocker, user)
end
assert data["object"] == blocked.ap_id
assert data["actor"] == blocker.ap_id
- blocker = User.get_by_ap_id(data["actor"])
- blocked = User.get_by_ap_id(data["object"])
+ blocker = User.get_cached_by_ap_id(data["actor"])
+ blocked = User.get_cached_by_ap_id(data["object"])
assert User.blocks?(blocker, blocked)
assert data["object"]["object"] == user.ap_id
assert data["actor"] == "http://mastodon.example.org/users/admin"
- blocker = User.get_by_ap_id(data["actor"])
+ blocker = User.get_cached_by_ap_id(data["actor"])
refute User.blocks?(blocker, user)
end
assert activity.data["object"] == follow_activity.data["id"]
- follower = User.get_by_id(follower.id)
+ follower = User.get_cached_by_id(follower.id)
assert User.following?(follower, followed) == true
end
{:ok, activity} = Transmogrifier.handle_incoming(accept_data)
assert activity.data["object"] == follow_activity.data["id"]
- follower = User.get_by_id(follower.id)
+ follower = User.get_cached_by_id(follower.id)
assert User.following?(follower, followed) == true
end
{:ok, activity} = Transmogrifier.handle_incoming(accept_data)
assert activity.data["object"] == follow_activity.data["id"]
- follower = User.get_by_id(follower.id)
+ follower = User.get_cached_by_id(follower.id)
assert User.following?(follower, followed) == true
end
:error = Transmogrifier.handle_incoming(accept_data)
- follower = User.get_by_id(follower.id)
+ follower = User.get_cached_by_id(follower.id)
refute User.following?(follower, followed) == true
end
:error = Transmogrifier.handle_incoming(accept_data)
- follower = User.get_by_id(follower.id)
+ follower = User.get_cached_by_id(follower.id)
refute User.following?(follower, followed) == true
end
{:ok, activity} = Transmogrifier.handle_incoming(reject_data)
refute activity.local
- follower = User.get_by_id(follower.id)
+ follower = User.get_cached_by_id(follower.id)
assert User.following?(follower, followed) == false
end
{:ok, %Activity{data: _}} = Transmogrifier.handle_incoming(reject_data)
- follower = User.get_by_id(follower.id)
+ follower = User.get_cached_by_id(follower.id)
assert User.following?(follower, followed) == false
end
test "it remaps video URLs as attachments if necessary" do
{:ok, object} =
- ActivityPub.fetch_object_from_id(
+ Fetcher.fetch_object_from_id(
"https://peertube.moe/videos/watch/df5f464b-be8d-46fb-ad81-2d4c2d1630e3"
)
test "it strips internal fields" do
user = insert(:user)
- {:ok, activity} = CommonAPI.post(user, %{"status" => "#2hu :moominmamma:"})
+ {:ok, activity} = CommonAPI.post(user, %{"status" => "#2hu :firefox:"})
{:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
{:ok, unrelated_activity} = CommonAPI.post(user_two, %{"status" => "test"})
assert "http://localhost:4001/users/rye@niu.moe/followers" in activity.recipients
- user = User.get_by_id(user.id)
+ user = User.get_cached_by_id(user.id)
assert user.info.note_count == 1
{:ok, user} = Transmogrifier.upgrade_user_from_ap_id("https://niu.moe/users/rye")
assert user.info.note_count == 1
assert user.follower_address == "https://niu.moe/users/rye/followers"
- user = User.get_by_id(user.id)
+ user = User.get_cached_by_id(user.id)
assert user.info.note_count == 1
activity = Activity.get_by_id(activity.id)
unrelated_activity = Activity.get_by_id(unrelated_activity.id)
refute user.follower_address in unrelated_activity.recipients
- user_two = User.get_by_id(user_two.id)
+ user_two = User.get_cached_by_id(user_two.id)
assert user.follower_address in user_two.following
refute "..." in user_two.following
end
end
end
- describe "general origin containment" do
- test "contain_origin_from_id() catches obvious spoofing attempts" do
- data = %{
- "id" => "http://example.com/~alyssa/activities/1234.json"
- }
-
- :error =
- Transmogrifier.contain_origin_from_id(
- "http://example.org/~alyssa/activities/1234.json",
- data
- )
- end
-
- test "contain_origin_from_id() allows alternate IDs within the same origin domain" do
- data = %{
- "id" => "http://example.com/~alyssa/activities/1234.json"
- }
-
- :ok =
- Transmogrifier.contain_origin_from_id(
- "http://example.com/~alyssa/activities/1234",
- data
- )
- end
-
- test "contain_origin_from_id() allows matching IDs" do
- data = %{
- "id" => "http://example.com/~alyssa/activities/1234.json"
- }
-
- :ok =
- Transmogrifier.contain_origin_from_id(
- "http://example.com/~alyssa/activities/1234.json",
- data
- )
- end
-
- test "users cannot be collided through fake direction spoofing attempts" do
- insert(:user, %{
- nickname: "rye@niu.moe",
- local: false,
- ap_id: "https://niu.moe/users/rye",
- follower_address: User.ap_followers(%User{nickname: "rye@niu.moe"})
- })
-
- {:error, _} = User.get_or_fetch_by_ap_id("https://n1u.moe/users/rye")
- end
-
- test "all objects with fake directions are rejected by the object fetcher" do
- {:error, _} =
- ActivityPub.fetch_and_contain_remote_object_from_id(
- "https://info.pleroma.site/activity4.json"
- )
- end
- end
-
describe "reserialization" do
test "successfully reserializes a message with inReplyTo == nil" do
user = insert(:user)
{:ok, _} = Transmogrifier.prepare_outgoing(activity.data)
end
end
+
+ test "Rewrites Answers to Notes" do
+ user = insert(:user)
+
+ {:ok, poll_activity} =
+ CommonAPI.post(user, %{
+ "status" => "suya...",
+ "poll" => %{"options" => ["suya", "suya.", "suya.."], "expires_in" => 10}
+ })
+
+ poll_object = Object.normalize(poll_activity)
+ # TODO: Replace with CommonAPI vote creation when implemented
+ data =
+ File.read!("test/fixtures/mastodon-vote.json")
+ |> Poison.decode!()
+ |> Kernel.put_in(["to"], user.ap_id)
+ |> Kernel.put_in(["object", "inReplyTo"], poll_object.data["id"])
+ |> Kernel.put_in(["object", "to"], user.ap_id)
+
+ {:ok, %Activity{local: false} = activity} = Transmogrifier.handle_incoming(data)
+ {:ok, data} = Transmogrifier.prepare_outgoing(activity.data)
+
+ assert data["object"]["type"] == "Note"
+ end
+
+ describe "fix_explicit_addressing" do
+ setup do
+ user = insert(:user)
+ [user: user]
+ end
+
+ test "moves non-explicitly mentioned actors to cc", %{user: user} do
+ explicitly_mentioned_actors = [
+ "https://pleroma.gold/users/user1",
+ "https://pleroma.gold/user2"
+ ]
+
+ object = %{
+ "actor" => user.ap_id,
+ "to" => explicitly_mentioned_actors ++ ["https://social.beepboop.ga/users/dirb"],
+ "cc" => [],
+ "tag" =>
+ Enum.map(explicitly_mentioned_actors, fn href ->
+ %{"type" => "Mention", "href" => href}
+ end)
+ }
+
+ fixed_object = Transmogrifier.fix_explicit_addressing(object)
+ assert Enum.all?(explicitly_mentioned_actors, &(&1 in fixed_object["to"]))
+ refute "https://social.beepboop.ga/users/dirb" in fixed_object["to"]
+ assert "https://social.beepboop.ga/users/dirb" in fixed_object["cc"]
+ end
+
+ test "does not move actor's follower collection to cc", %{user: user} do
+ object = %{
+ "actor" => user.ap_id,
+ "to" => [user.follower_address],
+ "cc" => []
+ }
+
+ fixed_object = Transmogrifier.fix_explicit_addressing(object)
+ assert user.follower_address in fixed_object["to"]
+ refute user.follower_address in fixed_object["cc"]
+ end
+
+ test "removes recipient's follower collection from cc", %{user: user} do
+ recipient = insert(:user)
+
+ object = %{
+ "actor" => user.ap_id,
+ "to" => [recipient.ap_id, "https://www.w3.org/ns/activitystreams#Public"],
+ "cc" => [user.follower_address, recipient.follower_address]
+ }
+
+ fixed_object = Transmogrifier.fix_explicit_addressing(object)
+
+ assert user.follower_address in fixed_object["cc"]
+ refute recipient.follower_address in fixed_object["cc"]
+ refute recipient.follower_address in fixed_object["to"]
+ end
+ end
end