2020-10-19 09:32:37 +02:00
|
|
|
defmodule Mobilizon.Federation.ActivityPub.Transmogrifier.DeleteTest do
|
|
|
|
use Mobilizon.DataCase
|
|
|
|
use ExVCR.Mock, adapter: ExVCR.Adapter.Hackney
|
|
|
|
use Oban.Testing, repo: Mobilizon.Storage.Repo
|
|
|
|
import Mobilizon.Factory
|
|
|
|
import Mox
|
|
|
|
|
2020-10-19 19:21:39 +02:00
|
|
|
alias Mobilizon.{Actors, Discussions, Events, Posts, Resources}
|
2020-10-19 09:32:37 +02:00
|
|
|
alias Mobilizon.Actors.Actor
|
|
|
|
alias Mobilizon.Discussions.Comment
|
|
|
|
alias Mobilizon.Events.Event
|
|
|
|
alias Mobilizon.Posts.Post
|
2020-10-19 19:21:39 +02:00
|
|
|
alias Mobilizon.Resources.Resource
|
2020-10-19 09:32:37 +02:00
|
|
|
alias Mobilizon.Federation.ActivityPub.{Activity, Transmogrifier}
|
|
|
|
alias Mobilizon.Federation.ActivityStream.Convertible
|
|
|
|
alias Mobilizon.Service.HTTP.ActivityPub.Mock
|
|
|
|
|
|
|
|
describe "handle incoming delete activities" do
|
|
|
|
test "it works for incoming deletes" do
|
|
|
|
%Actor{url: actor_url} =
|
|
|
|
actor = insert(:actor, url: "http://mobilizon.tld/@remote", domain: "mobilizon.tld")
|
|
|
|
|
|
|
|
%Comment{url: comment_url} =
|
|
|
|
insert(:comment,
|
|
|
|
actor: nil,
|
|
|
|
actor_id: actor.id,
|
|
|
|
url: "http://mobilizon.tld/comments/9f3794b8-11a0-4a98-8cb7-475ab332c701"
|
|
|
|
)
|
|
|
|
|
|
|
|
Mock
|
|
|
|
|> expect(:call, fn
|
|
|
|
%{method: :get, url: "http://mobilizon.tld/comments/9f3794b8-11a0-4a98-8cb7-475ab332c701"},
|
|
|
|
_opts ->
|
|
|
|
{:ok, %Tesla.Env{status: 410, body: "Gone"}}
|
|
|
|
end)
|
|
|
|
|
|
|
|
data =
|
|
|
|
File.read!("test/fixtures/mastodon-delete.json")
|
|
|
|
|> Jason.decode!()
|
|
|
|
|
|
|
|
object =
|
|
|
|
data["object"]
|
|
|
|
|> Map.put("id", comment_url)
|
|
|
|
|
|
|
|
data =
|
|
|
|
data
|
|
|
|
|> Map.put("object", object)
|
|
|
|
|> Map.put("actor", actor_url)
|
|
|
|
|
|
|
|
assert Discussions.get_comment_from_url(comment_url)
|
|
|
|
assert is_nil(Discussions.get_comment_from_url(comment_url).deleted_at)
|
|
|
|
|
|
|
|
{:ok, %Activity{local: false}, _} = Transmogrifier.handle_incoming(data)
|
|
|
|
|
|
|
|
refute is_nil(Discussions.get_comment_from_url(comment_url).deleted_at)
|
|
|
|
end
|
|
|
|
|
|
|
|
test "it fails for incoming deletes with spoofed origin" do
|
2021-11-13 18:45:01 +01:00
|
|
|
actor_data =
|
|
|
|
File.read!("test/fixtures/mastodon-actor.json")
|
|
|
|
|> Jason.decode!()
|
|
|
|
|
|
|
|
Mock
|
|
|
|
|> expect(:call, 2, fn
|
|
|
|
%{method: :get, url: "https://framapiaf.org/users/peertube"}, _opts ->
|
|
|
|
{:ok, %Tesla.Env{status: 200, body: actor_data}}
|
|
|
|
|
|
|
|
%{method: :get, url: "http://mastodon.example.org/users/gargron"}, _opts ->
|
|
|
|
{:ok, %Tesla.Env{status: 200, body: actor_data}}
|
|
|
|
end)
|
|
|
|
|
2020-10-19 09:32:37 +02:00
|
|
|
comment = insert(:comment)
|
|
|
|
|
|
|
|
announce_data =
|
|
|
|
File.read!("test/fixtures/mastodon-announce.json")
|
|
|
|
|> Jason.decode!()
|
|
|
|
|> Map.put("object", comment.url)
|
|
|
|
|
|
|
|
{:ok, _, _} = Transmogrifier.handle_incoming(announce_data)
|
|
|
|
|
|
|
|
data =
|
|
|
|
File.read!("test/fixtures/mastodon-delete.json")
|
|
|
|
|> Jason.decode!()
|
|
|
|
|
|
|
|
object =
|
|
|
|
data["object"]
|
|
|
|
|> Map.put("id", comment.url)
|
|
|
|
|
|
|
|
data =
|
|
|
|
data
|
|
|
|
|> Map.put("object", object)
|
|
|
|
|
2021-11-13 18:45:01 +01:00
|
|
|
:error = Transmogrifier.handle_incoming(data)
|
2020-10-19 09:32:37 +02:00
|
|
|
|
|
|
|
assert Discussions.get_comment_from_url(comment.url)
|
|
|
|
end
|
|
|
|
|
|
|
|
setup :set_mox_from_context
|
|
|
|
|
|
|
|
test "it works for incoming actor deletes" do
|
|
|
|
%Actor{url: url} =
|
|
|
|
actor = insert(:actor, url: "https://framapiaf.org/users/admin", domain: "framapiaf.org")
|
|
|
|
|
2021-09-24 16:46:42 +02:00
|
|
|
%Event{} = event1 = insert(:event, organizer_actor: actor)
|
2020-10-19 09:32:37 +02:00
|
|
|
insert(:event, organizer_actor: actor)
|
|
|
|
|
2021-09-24 16:46:42 +02:00
|
|
|
%Comment{} = comment1 = insert(:comment, actor: actor)
|
2020-10-19 09:32:37 +02:00
|
|
|
insert(:comment, actor: actor)
|
|
|
|
|
|
|
|
data =
|
|
|
|
File.read!("test/fixtures/mastodon-delete-user.json")
|
|
|
|
|> Jason.decode!()
|
|
|
|
|
|
|
|
Mock
|
|
|
|
|> expect(:call, fn
|
|
|
|
%{method: :get, url: "https://framapiaf.org/users/admin"}, _opts ->
|
|
|
|
{:ok, %Tesla.Env{status: 410, body: "Gone"}}
|
|
|
|
end)
|
|
|
|
|
|
|
|
{:ok, _activity, _actor} = Transmogrifier.handle_incoming(data)
|
2021-09-29 20:28:03 +02:00
|
|
|
assert %{success: 1, snoozed: 0, failure: 0} == Oban.drain_queue(queue: :background)
|
2020-10-19 09:32:37 +02:00
|
|
|
|
|
|
|
assert {:error, :actor_not_found} = Actors.get_actor_by_url(url)
|
|
|
|
assert {:error, :event_not_found} = Events.get_event(event1.id)
|
|
|
|
# Tombstone are cascade deleted, seems correct for now
|
|
|
|
# assert %Tombstone{} = Tombstone.find_tombstone(event1_url)
|
|
|
|
assert %Comment{deleted_at: deleted_at} = Discussions.get_comment(comment1.id)
|
|
|
|
refute is_nil(deleted_at)
|
|
|
|
# assert %Tombstone{} = Tombstone.find_tombstone(comment1_url)
|
|
|
|
end
|
|
|
|
|
|
|
|
test "it fails for incoming actor deletes with spoofed origin" do
|
|
|
|
%{url: url} = insert(:actor)
|
|
|
|
|
|
|
|
data =
|
|
|
|
File.read!("test/fixtures/mastodon-delete-user.json")
|
|
|
|
|> Jason.decode!()
|
|
|
|
|> Map.put("actor", url)
|
|
|
|
|
2021-04-22 12:17:56 +02:00
|
|
|
deleted_actor_url = "https://framapiaf.org/users/admin"
|
|
|
|
|
2020-10-19 09:32:37 +02:00
|
|
|
deleted_actor_data =
|
|
|
|
File.read!("test/fixtures/mastodon-actor.json")
|
|
|
|
|> Jason.decode!()
|
|
|
|
|> Map.put("id", deleted_actor_url)
|
|
|
|
|
|
|
|
Mock
|
2021-11-13 18:45:01 +01:00
|
|
|
|> expect(:call, 2, fn
|
2020-10-19 09:32:37 +02:00
|
|
|
%{url: ^deleted_actor_url}, _opts ->
|
|
|
|
{:ok, %Tesla.Env{status: 200, body: deleted_actor_data}}
|
|
|
|
end)
|
|
|
|
|
2021-11-13 18:45:01 +01:00
|
|
|
assert {:error, "Group object URL remote"} == Transmogrifier.handle_incoming(data)
|
2020-10-19 09:32:37 +02:00
|
|
|
|
|
|
|
assert Actors.get_actor_by_url(url)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe "handle incoming delete activities for group posts" do
|
2020-10-19 19:21:39 +02:00
|
|
|
test "works for remote deletions by moderators" do
|
|
|
|
%Actor{url: remote_actor_url} =
|
|
|
|
remote_actor =
|
|
|
|
insert(:actor,
|
|
|
|
domain: "remote.domain",
|
|
|
|
url: "https://remote.domain/@remote",
|
|
|
|
preferred_username: "remote"
|
|
|
|
)
|
|
|
|
|
|
|
|
group = insert(:group)
|
|
|
|
insert(:member, actor: remote_actor, parent: group, role: :moderator)
|
|
|
|
%Post{} = post = insert(:post, attributed_to: group)
|
|
|
|
|
|
|
|
data = Convertible.model_to_as(post)
|
|
|
|
refute is_nil(Posts.get_post_by_url(data["id"]))
|
|
|
|
|
|
|
|
delete_data =
|
|
|
|
File.read!("test/fixtures/mastodon-delete.json")
|
|
|
|
|> Jason.decode!()
|
|
|
|
|
|
|
|
object =
|
|
|
|
data
|
|
|
|
|> Map.put("type", "Article")
|
|
|
|
|
|
|
|
delete_data =
|
|
|
|
delete_data
|
|
|
|
|> Map.put("actor", remote_actor_url)
|
|
|
|
|> Map.put("object", object)
|
|
|
|
|
|
|
|
{:ok, _activity, _actor} = Transmogrifier.handle_incoming(delete_data)
|
|
|
|
|
|
|
|
assert is_nil(Posts.get_post_by_url(data["id"]))
|
|
|
|
end
|
|
|
|
|
|
|
|
test "doesn't work for remote deletions if the actor is just a group member" do
|
2020-10-19 09:32:37 +02:00
|
|
|
%Actor{url: remote_actor_url} =
|
2020-10-19 19:21:39 +02:00
|
|
|
remote_actor =
|
2020-10-19 09:32:37 +02:00
|
|
|
insert(:actor,
|
|
|
|
domain: "remote.domain",
|
|
|
|
url: "https://remote.domain/@remote",
|
|
|
|
preferred_username: "remote"
|
|
|
|
)
|
|
|
|
|
|
|
|
group = insert(:group)
|
2020-10-19 19:21:39 +02:00
|
|
|
insert(:member, actor: remote_actor, parent: group, role: :member)
|
2020-10-19 09:32:37 +02:00
|
|
|
%Post{} = post = insert(:post, attributed_to: group)
|
|
|
|
|
|
|
|
data = Convertible.model_to_as(post)
|
|
|
|
refute is_nil(Posts.get_post_by_url(data["id"]))
|
|
|
|
|
|
|
|
delete_data =
|
|
|
|
File.read!("test/fixtures/mastodon-delete.json")
|
|
|
|
|> Jason.decode!()
|
|
|
|
|
|
|
|
object =
|
|
|
|
data
|
|
|
|
|> Map.put("type", "Article")
|
|
|
|
|
|
|
|
delete_data =
|
|
|
|
delete_data
|
|
|
|
|> Map.put("actor", remote_actor_url)
|
|
|
|
|> Map.put("object", object)
|
|
|
|
|
|
|
|
:error = Transmogrifier.handle_incoming(delete_data)
|
|
|
|
|
|
|
|
refute is_nil(Posts.get_post_by_url(data["id"]))
|
|
|
|
end
|
|
|
|
|
|
|
|
test "doesn't work for remote deletions if the actor is not a group member" do
|
|
|
|
%Actor{url: remote_actor_url} =
|
|
|
|
insert(:actor,
|
|
|
|
domain: "remote.domain",
|
|
|
|
url: "https://remote.domain/@remote",
|
|
|
|
preferred_username: "remote"
|
|
|
|
)
|
|
|
|
|
|
|
|
group = insert(:group)
|
|
|
|
%Post{} = post = insert(:post, attributed_to: group)
|
|
|
|
|
|
|
|
data = Convertible.model_to_as(post)
|
|
|
|
refute is_nil(Posts.get_post_by_url(data["id"]))
|
|
|
|
|
|
|
|
delete_data =
|
|
|
|
File.read!("test/fixtures/mastodon-delete.json")
|
|
|
|
|> Jason.decode!()
|
|
|
|
|
|
|
|
object =
|
|
|
|
data
|
|
|
|
|> Map.put("type", "Article")
|
|
|
|
|
|
|
|
delete_data =
|
|
|
|
delete_data
|
|
|
|
|> Map.put("actor", remote_actor_url)
|
|
|
|
|> Map.put("object", object)
|
|
|
|
|
|
|
|
:error = Transmogrifier.handle_incoming(delete_data)
|
|
|
|
|
|
|
|
refute is_nil(Posts.get_post_by_url(data["id"]))
|
|
|
|
end
|
|
|
|
end
|
2020-10-19 19:21:39 +02:00
|
|
|
|
|
|
|
describe "handle incoming delete activities for resources" do
|
|
|
|
test "works for remote deletions" do
|
|
|
|
%Actor{url: remote_actor_url} =
|
|
|
|
remote_actor =
|
|
|
|
insert(:actor,
|
|
|
|
domain: "remote.domain",
|
|
|
|
url: "http://remote.domain/@remote",
|
|
|
|
preferred_username: "remote"
|
|
|
|
)
|
|
|
|
|
|
|
|
group = insert(:group)
|
|
|
|
insert(:member, actor: remote_actor, parent: group, role: :member)
|
|
|
|
%Resource{} = resource = insert(:resource, actor: group)
|
|
|
|
|
|
|
|
data = Convertible.model_to_as(resource)
|
|
|
|
refute is_nil(Resources.get_resource_by_url(data["id"]))
|
|
|
|
|
|
|
|
delete_data =
|
|
|
|
File.read!("test/fixtures/mastodon-delete.json")
|
|
|
|
|> Jason.decode!()
|
|
|
|
|
|
|
|
object =
|
|
|
|
data
|
|
|
|
|> Map.put("type", "Document")
|
|
|
|
|
|
|
|
delete_data =
|
|
|
|
delete_data
|
|
|
|
|> Map.put("actor", remote_actor_url)
|
|
|
|
|> Map.put("object", object)
|
|
|
|
|
|
|
|
{:ok, _activity, _actor} = Transmogrifier.handle_incoming(delete_data)
|
|
|
|
|
|
|
|
assert is_nil(Resources.get_resource_by_url(data["id"]))
|
|
|
|
end
|
|
|
|
|
|
|
|
test "doesn't work for remote deletions if the actor is not a group member" do
|
|
|
|
%Actor{url: remote_actor_url} =
|
|
|
|
insert(:actor,
|
|
|
|
domain: "remote.domain",
|
|
|
|
url: "http://remote.domain/@remote",
|
|
|
|
preferred_username: "remote"
|
|
|
|
)
|
|
|
|
|
|
|
|
group = insert(:group)
|
|
|
|
%Post{} = post = insert(:post, attributed_to: group)
|
|
|
|
|
|
|
|
data = Convertible.model_to_as(post)
|
|
|
|
refute is_nil(Posts.get_post_by_url(data["id"]))
|
|
|
|
|
|
|
|
delete_data =
|
|
|
|
File.read!("test/fixtures/mastodon-delete.json")
|
|
|
|
|> Jason.decode!()
|
|
|
|
|
|
|
|
object =
|
|
|
|
data
|
|
|
|
|> Map.put("type", "Article")
|
|
|
|
|
|
|
|
delete_data =
|
|
|
|
delete_data
|
|
|
|
|> Map.put("actor", remote_actor_url)
|
|
|
|
|> Map.put("object", object)
|
|
|
|
|
|
|
|
:error = Transmogrifier.handle_incoming(delete_data)
|
|
|
|
|
|
|
|
refute is_nil(Posts.get_post_by_url(data["id"]))
|
|
|
|
end
|
|
|
|
end
|
2020-10-19 09:32:37 +02:00
|
|
|
end
|