You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
akkoma-cachapa/test/web/activity_pub/transmogrifier_test.exs

560 lines
19 KiB

defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do
use Pleroma.DataCase
alias Pleroma.Web.ActivityPub.Transmogrifier
alias Pleroma.Web.ActivityPub.Utils
alias Pleroma.Web.OStatus
alias Pleroma.Activity
alias Pleroma.User
alias Pleroma.Repo
alias Pleroma.Web.Websub.WebsubClientSubscription
alias Pleroma.Web.Websub.WebsubServerSubscription
import Ecto.Query
import Pleroma.Factory
alias Pleroma.Web.CommonAPI
describe "handle_incoming" do
test "it ignores an incoming notice if we already have it" do
activity = insert(:note_activity)
7 years ago
data =
File.read!("test/fixtures/mastodon-post-activity.json")
|> Poison.decode!()
|> Map.put("object", activity.data["object"])
{:ok, returned_activity} = Transmogrifier.handle_incoming(data)
assert activity == returned_activity
end
test "it fetches replied-to activities if we don't have them" do
7 years ago
data =
File.read!("test/fixtures/mastodon-post-activity.json")
|> Poison.decode!()
7 years ago
object =
data["object"]
|> Map.put("inReplyTo", "https://shitposter.club/notice/2827873")
7 years ago
data =
data
|> Map.put("object", object)
{:ok, returned_activity} = Transmogrifier.handle_incoming(data)
7 years ago
assert activity =
Activity.get_create_activity_by_object_ap_id(
"tag:shitposter.club,2017-05-05:noticeId=2827873:objectType=comment"
)
assert returned_activity.data["object"]["inReplyToAtomUri"] ==
"https://shitposter.club/notice/2827873"
assert returned_activity.data["object"]["inReplyToStatusId"] == activity.id
end
test "it works for incoming notices" do
7 years ago
data = File.read!("test/fixtures/mastodon-post-activity.json") |> Poison.decode!()
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
7 years ago
assert data["id"] ==
"http://mastodon.example.org/users/admin/statuses/99512778738411822/activity"
assert data["context"] ==
"tag:mastodon.example.org,2018-02-12:objectId=20:objectType=Conversation"
assert data["to"] == ["https://www.w3.org/ns/activitystreams#Public"]
7 years ago
assert data["cc"] == [
7 years ago
"http://mastodon.example.org/users/admin/followers",
"http://localtesting.pleroma.lol/users/lain"
]
assert data["actor"] == "http://mastodon.example.org/users/admin"
object = data["object"]
assert object["id"] == "http://mastodon.example.org/users/admin/statuses/99512778738411822"
assert object["to"] == ["https://www.w3.org/ns/activitystreams#Public"]
7 years ago
assert object["cc"] == [
7 years ago
"http://mastodon.example.org/users/admin/followers",
"http://localtesting.pleroma.lol/users/lain"
]
assert object["actor"] == "http://mastodon.example.org/users/admin"
assert object["attributedTo"] == "http://mastodon.example.org/users/admin"
7 years ago
assert object["context"] ==
"tag:mastodon.example.org,2018-02-12:objectId=20:objectType=Conversation"
assert object["sensitive"] == true
7 years ago
user = User.get_by_ap_id(object["actor"])
assert user.info["note_count"] == 1
end
test "it works for incoming notices with hashtags" do
7 years ago
data = File.read!("test/fixtures/mastodon-post-activity-hashtag.json") |> Poison.decode!()
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
assert Enum.at(data["object"]["tag"], 2) == "moo"
end
test "it works for incoming follow requests" do
user = insert(:user)
7 years ago
data =
File.read!("test/fixtures/mastodon-follow-activity.json")
|> Poison.decode!()
7 years ago
|> 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)
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)
end
test "it works for incoming likes" do
user = insert(:user)
{:ok, activity} = CommonAPI.post(user, %{"status" => "hello"})
7 years ago
data =
File.read!("test/fixtures/mastodon-like.json")
|> Poison.decode!()
7 years ago
|> Map.put("object", activity.data["object"]["id"])
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
assert data["actor"] == "http://mastodon.example.org/users/admin"
assert data["type"] == "Like"
assert data["id"] == "http://mastodon.example.org/users/admin#likes/2"
assert data["object"] == activity.data["object"]["id"]
end
test "it returns an error for incoming unlikes wihout a like activity" do
user = insert(:user)
{:ok, activity} = CommonAPI.post(user, %{"status" => "leave a like pls"})
data =
File.read!("test/fixtures/mastodon-undo-like.json")
|> Poison.decode!()
|> Map.put("object", activity.data["object"]["id"])
assert Transmogrifier.handle_incoming(data) == :error
end
test "it works for incoming unlikes with an existing like activity" do
user = insert(:user)
{:ok, activity} = CommonAPI.post(user, %{"status" => "leave a like pls"})
like_data =
File.read!("test/fixtures/mastodon-like.json")
|> Poison.decode!()
|> Map.put("object", activity.data["object"]["id"])
{:ok, %Activity{data: like_data, local: false}} = Transmogrifier.handle_incoming(like_data)
data =
File.read!("test/fixtures/mastodon-undo-like.json")
|> Poison.decode!()
|> Map.put("object", like_data)
|> Map.put("actor", like_data["actor"])
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
assert data["actor"] == "http://mastodon.example.org/users/admin"
assert data["type"] == "Undo"
assert data["id"] == "http://mastodon.example.org/users/admin#likes/2/undo"
assert data["object"]["id"] == "http://mastodon.example.org/users/admin#likes/2"
end
test "it works for incoming announces" do
7 years ago
data = File.read!("test/fixtures/mastodon-announce.json") |> Poison.decode!()
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
assert data["actor"] == "http://mastodon.example.org/users/admin"
assert data["type"] == "Announce"
7 years ago
assert data["id"] ==
"http://mastodon.example.org/users/admin/statuses/99542391527669785/activity"
assert data["object"] ==
"http://mastodon.example.org/users/admin/statuses/99541947525187367"
assert Activity.get_create_activity_by_object_ap_id(data["object"])
end
test "it works for incoming announces with an existing activity" do
user = insert(:user)
{:ok, activity} = CommonAPI.post(user, %{"status" => "hey"})
7 years ago
data =
File.read!("test/fixtures/mastodon-announce.json")
|> Poison.decode!()
|> Map.put("object", activity.data["object"]["id"])
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
assert data["actor"] == "http://mastodon.example.org/users/admin"
assert data["type"] == "Announce"
7 years ago
assert data["id"] ==
"http://mastodon.example.org/users/admin/statuses/99542391527669785/activity"
assert data["object"] == activity.data["object"]["id"]
assert Activity.get_create_activity_by_object_ap_id(data["object"]).id == activity.id
end
test "it works for incoming update activities" do
7 years ago
data = File.read!("test/fixtures/mastodon-post-activity.json") |> Poison.decode!()
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
7 years ago
update_data = File.read!("test/fixtures/mastodon-update.json") |> Poison.decode!()
object =
update_data["object"]
|> Map.put("actor", data["actor"])
|> Map.put("id", data["actor"])
7 years ago
update_data =
update_data
|> Map.put("actor", data["actor"])
|> Map.put("object", object)
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(update_data)
user = User.get_cached_by_ap_id(data["actor"])
assert user.name == "gargle"
7 years ago
assert user.avatar["url"] == [
%{
"href" =>
"https://cd.niu.moe/accounts/avatars/000/033/323/original/fd7f8ae0b3ffedc9.jpeg"
}
]
assert user.info["banner"]["url"] == [
%{
"href" =>
"https://cd.niu.moe/accounts/headers/000/033/323/original/850b3448fa5fd477.png"
}
]
assert user.bio == "<p>Some bio</p>"
end
test "it works for incoming deletes" do
activity = insert(:note_activity)
7 years ago
data =
File.read!("test/fixtures/mastodon-delete.json")
|> Poison.decode!()
object =
data["object"]
|> Map.put("id", activity.data["object"]["id"])
7 years ago
data =
data
|> Map.put("object", object)
|> Map.put("actor", activity.data["actor"])
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
refute Repo.get(Activity, activity.id)
end
test "it works for incoming unannounces with an existing notice" do
user = insert(:user)
{:ok, activity} = CommonAPI.post(user, %{"status" => "hey"})
announce_data =
File.read!("test/fixtures/mastodon-announce.json")
|> Poison.decode!()
|> Map.put("object", activity.data["object"]["id"])
{:ok, %Activity{data: announce_data, local: false}} =
Transmogrifier.handle_incoming(announce_data)
data =
File.read!("test/fixtures/mastodon-undo-announce.json")
|> Poison.decode!()
|> Map.put("object", announce_data)
|> Map.put("actor", announce_data["actor"])
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
assert data["type"] == "Undo"
assert data["object"]["type"] == "Announce"
assert data["object"]["object"] == activity.data["object"]["id"]
assert data["object"]["id"] ==
"http://mastodon.example.org/users/admin/statuses/99542391527669785/activity"
end
test "it works for incomming unfollows with an existing follow" do
user = insert(:user)
follow_data =
File.read!("test/fixtures/mastodon-follow-activity.json")
|> Poison.decode!()
|> Map.put("object", user.ap_id)
{:ok, %Activity{data: _, local: false}} = Transmogrifier.handle_incoming(follow_data)
data =
File.read!("test/fixtures/mastodon-unfollow-activity.json")
|> Poison.decode!()
|> Map.put("object", follow_data)
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
assert data["type"] == "Undo"
assert data["object"]["type"] == "Follow"
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)
end
test "it works for incoming blocks" do
user = insert(:user)
data =
File.read!("test/fixtures/mastodon-block-activity.json")
|> Poison.decode!()
|> Map.put("object", user.ap_id)
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
assert data["type"] == "Block"
assert data["object"] == user.ap_id
assert data["actor"] == "http://mastodon.example.org/users/admin"
blocker = User.get_by_ap_id(data["actor"])
assert User.blocks?(blocker, user)
end
test "it works for incoming unblocks with an existing block" do
user = insert(:user)
block_data =
File.read!("test/fixtures/mastodon-block-activity.json")
|> Poison.decode!()
|> Map.put("object", user.ap_id)
{:ok, %Activity{data: _, local: false}} = Transmogrifier.handle_incoming(block_data)
data =
File.read!("test/fixtures/mastodon-unblock-activity.json")
|> Poison.decode!()
|> Map.put("object", block_data)
{:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(data)
assert data["type"] == "Undo"
assert data["object"]["type"] == "Block"
assert data["object"]["object"] == user.ap_id
assert data["actor"] == "http://mastodon.example.org/users/admin"
blocker = User.get_by_ap_id(data["actor"])
refute User.blocks?(blocker, user)
end
end
describe "prepare outgoing" do
test "it turns mentions into tags" do
user = insert(:user)
other_user = insert(:user)
7 years ago
{:ok, activity} =
CommonAPI.post(user, %{"status" => "hey, @#{other_user.nickname}, how are ya? #2hu"})
{:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
object = modified["object"]
expected_mention = %{
"href" => other_user.ap_id,
"name" => "@#{other_user.nickname}",
"type" => "Mention"
}
expected_tag = %{
7 years ago
"href" => Pleroma.Web.Endpoint.url() <> "/tags/2hu",
"type" => "Hashtag",
"name" => "#2hu"
}
assert Enum.member?(object["tag"], expected_tag)
assert Enum.member?(object["tag"], expected_mention)
end
test "it adds the sensitive property" do
user = insert(:user)
{:ok, activity} = CommonAPI.post(user, %{"status" => "#nsfw hey"})
{:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
assert modified["object"]["sensitive"]
end
test "it adds the json-ld context and the conversation property" do
user = insert(:user)
{:ok, activity} = CommonAPI.post(user, %{"status" => "hey"})
{:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
assert modified["@context"] == "https://www.w3.org/ns/activitystreams"
assert modified["object"]["conversation"] == modified["context"]
end
test "it sets the 'attributedTo' property to the actor of the object if it doesn't have one" do
user = insert(:user)
{:ok, activity} = CommonAPI.post(user, %{"status" => "hey"})
{:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
assert modified["object"]["actor"] == modified["object"]["attributedTo"]
end
test "it translates ostatus IDs to external URLs" do
incoming = File.read!("test/fixtures/incoming_note_activity.xml")
{:ok, [referent_activity]} = OStatus.handle_incoming(incoming)
user = insert(:user)
{:ok, activity, _} = CommonAPI.favorite(referent_activity.id, user)
{:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
assert modified["object"] == "http://gs.example.org:4040/index.php/notice/29"
end
test "it translates ostatus reply_to IDs to external URLs" do
incoming = File.read!("test/fixtures/incoming_note_activity.xml")
{:ok, [referred_activity]} = OStatus.handle_incoming(incoming)
user = insert(:user)
7 years ago
{:ok, activity} =
CommonAPI.post(user, %{"status" => "HI!", "in_reply_to_status_id" => referred_activity.id})
{:ok, modified} = Transmogrifier.prepare_outgoing(activity.data)
assert modified["object"]["inReplyTo"] == "http://gs.example.org:4040/index.php/notice/29"
end
end
describe "user upgrade" do
test "it upgrades a user to activitypub" do
7 years ago
user =
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"})
})
user_two = insert(:user, %{following: [user.follower_address]})
{:ok, activity} = CommonAPI.post(user, %{"status" => "test"})
{:ok, unrelated_activity} = CommonAPI.post(user_two, %{"status" => "test"})
assert "http://localhost:4001/users/rye@niu.moe/followers" in activity.recipients
user = Repo.get(User, user.id)
assert user.info["note_count"] == 1
{:ok, user} = Transmogrifier.upgrade_user_from_ap_id("https://niu.moe/users/rye")
assert user.info["ap_enabled"]
assert user.info["note_count"] == 1
assert user.follower_address == "https://niu.moe/users/rye/followers"
# Wait for the background task
:timer.sleep(1000)
user = Repo.get(User, user.id)
assert user.info["note_count"] == 1
activity = Repo.get(Activity, activity.id)
assert user.follower_address in activity.recipients
7 years ago
assert %{
"url" => [
%{
"href" =>
"https://cdn.niu.moe/accounts/avatars/000/033/323/original/fd7f8ae0b3ffedc9.jpeg"
}
]
} = user.avatar
assert %{
"url" => [
%{
"href" =>
"https://cdn.niu.moe/accounts/headers/000/033/323/original/850b3448fa5fd477.png"
}
]
} = user.info["banner"]
refute "..." in activity.recipients
unrelated_activity = Repo.get(Activity, unrelated_activity.id)
refute user.follower_address in unrelated_activity.recipients
user_two = Repo.get(User, user_two.id)
assert user.follower_address in user_two.following
refute "..." in user_two.following
end
end
describe "maybe_retire_websub" do
test "it deletes all websub client subscripitions with the user as topic" do
subscription = %WebsubClientSubscription{topic: "https://niu.moe/users/rye.atom"}
{:ok, ws} = Repo.insert(subscription)
subscription = %WebsubClientSubscription{topic: "https://niu.moe/users/pasty.atom"}
{:ok, ws2} = Repo.insert(subscription)
Transmogrifier.maybe_retire_websub("https://niu.moe/users/rye")
refute Repo.get(WebsubClientSubscription, ws.id)
assert Repo.get(WebsubClientSubscription, ws2.id)
end
end
describe "actor rewriting" do
test "it fixes the actor URL property to be a proper URI" do
data = %{
"url" => %{"href" => "http://example.com"}
}
rewritten = Transmogrifier.maybe_fix_user_object(data)
assert rewritten["url"] == "http://example.com"
end
end
end